diff --git a/.config/1espt/PipelineAutobaseliningConfig.yml b/.config/1espt/PipelineAutobaseliningConfig.yml new file mode 100644 index 000000000000..71a1098b1aa3 --- /dev/null +++ b/.config/1espt/PipelineAutobaseliningConfig.yml @@ -0,0 +1,21 @@ +## DO NOT MODIFY THIS FILE MANUALLY. This is part of auto-baselining from 1ES Pipeline Templates. Go to [https://aka.ms/1espt-autobaselining] for more details. + +pipelines: + 679: + retail: + binary: + credscan: + lastModifiedDate: 2024-04-11 + binskim: + lastModifiedDate: 2024-04-11 + spotbugs: + lastModifiedDate: 2024-04-11 + source: + credscan: + lastModifiedDate: 2024-04-11 + eslint: + lastModifiedDate: 2024-04-11 + psscriptanalyzer: + lastModifiedDate: 2024-04-11 + armory: + lastModifiedDate: 2024-04-11 diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 9abee6864b8e..d66c4e34a7d3 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -9,13 +9,13 @@ ] }, "dotnet-reportgenerator-globaltool": { - "version": "5.0.2", + "version": "5.3.0", "commands": [ "reportgenerator" ] }, "microsoft.dotnet.xharness.cli": { - "version": "9.0.0-prerelease.24203.1", + "version": "9.0.0-prerelease.24266.1", "commands": [ "xharness" ] diff --git a/.config/guardian/.gdnbaselines b/.config/guardian/.gdnbaselines new file mode 100644 index 000000000000..e2ec41852d17 --- /dev/null +++ b/.config/guardian/.gdnbaselines @@ -0,0 +1,61 @@ +{ + "properties": { + "helpUri": "https://eng.ms/docs/microsoft-security/security/azure-security/cloudai-security-fundamentals-engineering/security-integration/guardian-wiki/microsoft-guardian/general/baselines" + }, + "version": "1.0.0", + "baselines": { + "default": { + "name": "default", + "createdDate": "2024-04-10 20:32:31Z", + "lastUpdatedDate": "2024-04-10 20:32:31Z" + } + }, + "results": { + "3b1bb0185d74dd310884a85ad1252953dab0747790f5aecd5bf5bb3c1e2b515c": { + "signature": "3b1bb0185d74dd310884a85ad1252953dab0747790f5aecd5bf5bb3c1e2b515c", + "alternativeSignatures": [], + "target": "src/libraries/System.Security.Cryptography/tests/X509Certificates/TestData.cs", + "line": 3441, + "memberOf": [ + "default" + ], + "tool": "credscan", + "ruleId": "CSCAN-GENERAL0060", + "createdDate": "2024-04-10 20:32:31Z", + "expirationDate": "2024-09-28 00:14:56Z", + "justification": "This error is baselined with an expiration date of 180 days from 2024-04-11 00:14:56Z" + }, + "2e4598005fdee72a4700697760c5f1b199c25d15a7c54de438ce939f125f3710": { + "signature": "2e4598005fdee72a4700697760c5f1b199c25d15a7c54de438ce939f125f3710", + "alternativeSignatures": [ + "6b533da7f95704f4476b24f493f88b2b1fd7d3bba69105bf63530140e0b3c8f1" + ], + "target": "src/libraries/Common/tests/System/Net/Prerequisites/Deployment/setup_activedirectory_domaincontroller.ps1", + "line": 36, + "memberOf": [ + "default" + ], + "tool": "psscriptanalyzer", + "ruleId": "PSAvoidUsingConvertToSecureStringWithPlainText", + "createdDate": "2024-04-10 20:32:31Z", + "expirationDate": "2024-09-28 00:14:56Z", + "justification": "This error is baselined with an expiration date of 180 days from 2024-04-11 00:14:56Z" + }, + "df6d1096725378c354a363dbb40fca84b9eed42a724ffbde7de57a88fc4042df": { + "signature": "df6d1096725378c354a363dbb40fca84b9eed42a724ffbde7de57a88fc4042df", + "alternativeSignatures": [ + "b090ab235a86ec5bc15243c19bc432f09e5aef816854bcbe120ab04c7c0332e1" + ], + "target": "src/libraries/Common/tests/System/Net/Prerequisites/Deployment/setup_iisserver.ps1", + "line": 82, + "memberOf": [ + "default" + ], + "tool": "psscriptanalyzer", + "ruleId": "PSAvoidUsingConvertToSecureStringWithPlainText", + "createdDate": "2024-04-10 20:32:31Z", + "expirationDate": "2024-09-28 00:14:56Z", + "justification": "This error is baselined with an expiration date of 180 days from 2024-04-11 00:14:56Z" + } + } +} \ No newline at end of file diff --git a/.devcontainer/scripts/onCreateCommand.sh b/.devcontainer/scripts/onCreateCommand.sh index 6c2527c7d1ef..02e5878bab2d 100755 --- a/.devcontainer/scripts/onCreateCommand.sh +++ b/.devcontainer/scripts/onCreateCommand.sh @@ -3,9 +3,6 @@ set -e function wasm_common() { - # prebuild for WASM, so it is ready for wasm development - make -C src/mono/browser provision-wasm - export EMSDK_PATH=$PWD/src/mono/browser/emsdk case "$1" in wasm) # Put your common commands for wasm here diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000000..806f7fad67b0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 5 + labels: + - area-codeflow + ignore: + - dependency-name: "actions/checkout" + update-types: ["version-update:semver-patch","version-update:semver-minor"] diff --git a/.github/policies/resourceManagement.yml b/.github/policies/resourceManagement.yml deleted file mode 100644 index bbfc4c3acb82..000000000000 --- a/.github/policies/resourceManagement.yml +++ /dev/null @@ -1,1881 +0,0 @@ -id: -name: GitOps.PullRequestIssueManagement -description: GitOps.PullRequestIssueManagement primitive -owner: -resource: repository -disabled: false -where: -configuration: - resourceManagementConfiguration: - scheduledSearches: - - description: Automated Issue cleanup - frequencies: - - hourly: - hour: 6 - filters: - - noActivitySince: - days: 1644 - - isIssue - - isOpen - - isNotLabeledWith: - label: backlog-cleanup-candidate - actions: - - addReply: - reply: >- - Due to lack of recent activity, this issue has been marked as a candidate for backlog cleanup. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will undo this process. - - - This process is part of our [issue cleanup automation](https://github.com/dotnet/runtime/blob/main/docs/issue-cleanup.md). - - addLabel: - label: backlog-cleanup-candidate - - addLabel: - label: no-recent-activity - - description: Add no-recent-activity label to issues - frequencies: - - hourly: - hour: 6 - filters: - - isIssue - - isOpen - - hasLabel: - label: needs-author-action - - noActivitySince: - days: 14 - - isNotLabeledWith: - label: no-recent-activity - actions: - - addLabel: - label: no-recent-activity - - addReply: - reply: This issue has been automatically marked `no-recent-activity` because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove `no-recent-activity`. - - description: Add no-recent-activity label to PRs - frequencies: - - hourly: - hour: 6 - filters: - - isPullRequest - - isOpen - - hasLabel: - label: needs-author-action - - noActivitySince: - days: 14 - - isNotLabeledWith: - label: no-recent-activity - actions: - - addLabel: - label: no-recent-activity - - addReply: - reply: This pull request has been automatically marked `no-recent-activity` because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove `no-recent-activity`. - - description: Close issues with no recent activity - frequencies: - - hourly: - hour: 6 - filters: - - isIssue - - isOpen - - hasLabel: - label: no-recent-activity - - noActivitySince: - days: 14 - actions: - - addReply: - reply: This issue will now be closed since it had been marked `no-recent-activity` but received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days. - - closeIssue - - description: Close PRs with no-recent-activity - frequencies: - - hourly: - hour: 6 - filters: - - isPullRequest - - isOpen - - hasLabel: - label: no-recent-activity - - noActivitySince: - days: 14 - actions: - - addReply: - reply: This pull request will now be closed since it had been marked `no-recent-activity` but received no further activity in the past 14 days. It is still possible to reopen or comment on the pull request, but please note that it will be locked if it remains inactive for another 30 days. - - closeIssue - - description: Close inactive Draft PRs - frequencies: - - hourly: - hour: 6 - filters: - - isDraftPullRequest - - isOpen - - noActivitySince: - days: 30 - actions: - - closeIssue - - addReply: - reply: Draft Pull Request was automatically closed for 30 days of inactivity. Please [let us know](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you'd like to reopen it. - eventResponderTasks: - - if: - - or: - - payloadType: Issues - - payloadType: Pull_Request - - isAction: - action: Opened - then: - - if: - - hasLabel: - label: area-AssemblyLoader-coreclr - then: - - mentionUsers: - mentionees: - - vitek-karas - - agocke - - vsadov - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-AssemblyLoader-mono - then: - - mentionUsers: - mentionees: [] - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-CodeGen-coreclr - then: - - mentionUsers: - mentionees: - - JulieLeeMSFT - - jakobbotsch - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Codegen-Interpreter-mono - then: - - mentionUsers: - mentionees: - - brzvlad - - kotlarmilos - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Codegen-JIT-Mono - then: - - mentionUsers: - mentionees: - - lambdageek - - steveisok - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-CodeGen-LLVM-Mono - then: - - mentionUsers: - mentionees: - - lambdageek - - steveisok - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Codegen-Intrinsics-mono - then: - - mentionUsers: - mentionees: - - fanyang-mono - - steveisok - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-CodeGen-meta-Mono - then: - - mentionUsers: - mentionees: - - steveisok - - lambdageek - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.DateTime - then: - - mentionUsers: - mentionees: - - dotnet/area-system-datetime - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Debugger-mono - then: - - mentionUsers: - mentionees: - - thaystg - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-DependencyModel - then: - - mentionUsers: - mentionees: - - dotnet/area-dependencymodel - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Diagnostics-coreclr - then: - - mentionUsers: - mentionees: - - tommcdon - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Extensions-Caching - then: - - mentionUsers: - mentionees: - - dotnet/area-extensions-caching - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Extensions-Configuration - then: - - mentionUsers: - mentionees: - - dotnet/area-extensions-configuration - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Extensions-DependencyInjection - then: - - mentionUsers: - mentionees: - - dotnet/area-extensions-dependencyinjection - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Extensions-FileSystem - then: - - mentionUsers: - mentionees: - - dotnet/area-extensions-filesystem - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Extensions-Hosting - then: - - mentionUsers: - mentionees: - - dotnet/area-extensions-hosting - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Extensions-HttpClientFactory - then: - - mentionUsers: - mentionees: - - dotnet/ncl - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Extensions-Logging - then: - - mentionUsers: - mentionees: - - dotnet/area-extensions-logging - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Extensions-Options - then: - - mentionUsers: - mentionees: - - dotnet/area-extensions-options - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Extensions-Primitives - then: - - mentionUsers: - mentionees: - - dotnet/area-extensions-primitives - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-GC-coreclr - then: - - mentionUsers: - mentionees: - - dotnet/gc - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-GC-mono - then: - - mentionUsers: - mentionees: - - brzvlad - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Host - then: - - mentionUsers: - mentionees: - - vitek-karas - - agocke - - vsadov - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-HostModel - then: - - mentionUsers: - mentionees: - - vitek-karas - - agocke - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-ILTools-coreclr - then: - - mentionUsers: - mentionees: - - JulieLeeMSFT - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Tools-ILVerification - then: - - mentionUsers: - mentionees: - - JulieLeeMSFT - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Infrastructure - then: - - mentionUsers: - mentionees: - - dotnet/runtime-infrastructure - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Infrastructure-coreclr - then: - - mentionUsers: - mentionees: - - hoyosjs - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Infrastructure-libraries - then: - - mentionUsers: - mentionees: - - dotnet/area-infrastructure-libraries - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Infrastructure-mono - then: - - mentionUsers: - mentionees: - - directhex - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Meta - then: - - mentionUsers: - mentionees: - - dotnet/area-meta - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Microsoft.CSharp - then: - - mentionUsers: - mentionees: - - cston - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Microsoft.Extensions - then: - - mentionUsers: - mentionees: - - dotnet/area-microsoft-extensions - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Microsoft.VisualBasic - then: - - mentionUsers: - mentionees: - - cston - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Microsoft.Win32 - then: - - mentionUsers: - mentionees: - - dotnet/area-microsoft-win32 - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-NativeAOT-coreclr - then: - - mentionUsers: - mentionees: - - agocke - - MichalStrehovsky - - jkotas - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Single-File - then: - - mentionUsers: - mentionees: - - agocke - - vitek-karas - - vsadov - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Buffers - then: - - mentionUsers: - mentionees: - - dotnet/area-system-buffers - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.CodeDom - then: - - mentionUsers: - mentionees: - - dotnet/area-system-codedom - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Collections - then: - - mentionUsers: - mentionees: - - dotnet/area-system-collections - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.ComponentModel - then: - - mentionUsers: - mentionees: - - dotnet/area-system-componentmodel - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.ComponentModel.Composition - then: - - mentionUsers: - mentionees: - - dotnet/area-system-componentmodel-composition - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.ComponentModel.DataAnnotations - then: - - mentionUsers: - mentionees: - - dotnet/area-system-componentmodel-dataannotations - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Composition - then: - - mentionUsers: - mentionees: - - dotnet/area-system-composition - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Configuration - then: - - mentionUsers: - mentionees: - - dotnet/area-system-configuration - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Console - then: - - mentionUsers: - mentionees: - - dotnet/area-system-console - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Data - then: - - mentionUsers: - mentionees: - - roji - - ajcvickers - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Data.Odbc - then: - - mentionUsers: - mentionees: - - roji - - ajcvickers - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Data.OleDB - then: - - mentionUsers: - mentionees: - - roji - - ajcvickers - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Data.SqlClient - then: - - mentionUsers: - mentionees: - - davoudeshtehari - - david-engel - - jrahnama - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Diagnostics - then: - - mentionUsers: - mentionees: - - tommcdon - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Diagnostics.Activity - then: - - mentionUsers: - mentionees: - - dotnet/area-system-diagnostics-activity - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Diagnostics.EventLog - then: - - mentionUsers: - mentionees: - - dotnet/area-system-diagnostics-eventlog - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Diagnostics.PerformanceCounter - then: - - mentionUsers: - mentionees: - - dotnet/area-system-diagnostics-performancecounter - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Diagnostics.Process - then: - - mentionUsers: - mentionees: - - dotnet/area-system-diagnostics-process - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Diagnostics.TraceSource - then: - - mentionUsers: - mentionees: - - dotnet/area-system-diagnostics-tracesource - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Diagnostics.Tracing - then: - - mentionUsers: - mentionees: - - tarekgh - - tommcdon - - pjanotti - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.DirectoryServices - then: - - mentionUsers: - mentionees: - - dotnet/area-system-directoryservices - - jay98014 - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Drawing - then: - - mentionUsers: - mentionees: - - dotnet/area-system-drawing - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Dynamic.Runtime - then: - - mentionUsers: - mentionees: - - cston - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Formats.Asn1 - then: - - mentionUsers: - mentionees: - - dotnet/area-system-formats-asn1 - - bartonjs - - vcsjones - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Formats.Cbor - then: - - mentionUsers: - mentionees: - - dotnet/area-system-formats-cbor - - bartonjs - - vcsjones - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Formats.Tar - then: - - mentionUsers: - mentionees: - - dotnet/area-system-formats-tar - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Globalization - then: - - mentionUsers: - mentionees: - - dotnet/area-system-globalization - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.IO - then: - - mentionUsers: - mentionees: - - dotnet/area-system-io - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.IO.Compression - then: - - mentionUsers: - mentionees: - - dotnet/area-system-io-compression - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.IO.Hashing - then: - - mentionUsers: - mentionees: - - dotnet/area-system-io-hashing - - bartonjs - - vcsjones - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.IO.Ports - then: - - mentionUsers: - mentionees: - - dotnet/area-system-io-ports - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Linq - then: - - mentionUsers: - mentionees: - - dotnet/area-system-linq - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Linq.Expressions - then: - - mentionUsers: - mentionees: - - cston - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Linq.Parallel - then: - - mentionUsers: - mentionees: - - dotnet/area-system-linq-parallel - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Management - then: - - mentionUsers: - mentionees: - - dotnet/area-system-management - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Memory - then: - - mentionUsers: - mentionees: - - dotnet/area-system-memory - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Net - then: - - mentionUsers: - mentionees: - - dotnet/ncl - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Net.Http - then: - - mentionUsers: - mentionees: - - dotnet/ncl - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Net.Quic - then: - - mentionUsers: - mentionees: - - dotnet/ncl - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Net.Security - then: - - mentionUsers: - mentionees: - - dotnet/ncl - - bartonjs - - vcsjones - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Net.Sockets - then: - - mentionUsers: - mentionees: - - dotnet/ncl - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Numerics - then: - - mentionUsers: - mentionees: - - dotnet/area-system-numerics - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Numerics.Tensors - then: - - mentionUsers: - mentionees: - - dotnet/area-system-numerics-tensors - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Reflection - then: - - mentionUsers: - mentionees: - - dotnet/area-system-reflection - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Reflection.Emit - then: - - mentionUsers: - mentionees: - - dotnet/area-system-reflection-emit - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Reflection.Metadata - then: - - mentionUsers: - mentionees: - - dotnet/area-system-reflection-metadata - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Resources - then: - - mentionUsers: - mentionees: - - dotnet/area-system-resources - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Runtime - then: - - mentionUsers: - mentionees: - - dotnet/area-system-runtime - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Runtime.CompilerServices - then: - - mentionUsers: - mentionees: - - dotnet/area-system-runtime-compilerservices - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Runtime.InteropServices - then: - - mentionUsers: - mentionees: - - dotnet/interop-contrib - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Runtime.Intrinsics - then: - - mentionUsers: - mentionees: - - dotnet/area-system-runtime-intrinsics - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Security - then: - - mentionUsers: - mentionees: - - dotnet/area-system-security - - bartonjs - - vcsjones - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.ServiceProcess - then: - - mentionUsers: - mentionees: - - dotnet/area-system-serviceprocess - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Speech - then: - - mentionUsers: - mentionees: - - dotnet/area-system-speech - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Text.Encoding - then: - - mentionUsers: - mentionees: - - dotnet/area-system-text-encoding - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Text.Encodings.Web - then: - - mentionUsers: - mentionees: - - dotnet/area-system-text-encodings-web - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Text.Json - then: - - mentionUsers: - mentionees: - - dotnet/area-system-text-json - - gregsdennis - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Text.RegularExpressions - then: - - mentionUsers: - mentionees: - - dotnet/area-system-text-regularexpressions - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Threading - then: - - mentionUsers: - mentionees: - - mangod9 - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Threading.Channels - then: - - mentionUsers: - mentionees: - - dotnet/area-system-threading-channels - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Threading.Tasks - then: - - mentionUsers: - mentionees: - - dotnet/area-system-threading-tasks - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Transactions - then: - - mentionUsers: - mentionees: - - roji - - ajcvickers - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-System.Xml - then: - - mentionUsers: - mentionees: - - dotnet/area-system-xml - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-Tools-ILLink - then: - - mentionUsers: - mentionees: - - agocke - - sbomer - - vitek-karas - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - - if: - - hasLabel: - label: area-vm-coreclr - then: - - mentionUsers: - mentionees: - - mangod9 - replyTemplate: >- - Tagging subscribers to this area: ${mentionees} - - See info in [area-owners.md](https://github.com/dotnet/runtime/blob/main/docs/area-owners.md) if you want to be subscribed. - assignMentionees: False - description: Area-owners - - if: - - payloadType: Issues - - labelAdded: - label: breaking-change - then: - - addLabel: - label: needs-breaking-change-doc-created - - addReply: - reply: >- - Added `needs-breaking-change-doc-created` label because this issue has the `breaking-change` label. - - - 1. [ ] Create and link to this issue a matching issue in the dotnet/docs repo using the [breaking change documentation template](https://aka.ms/dotnet/docs/new-breaking-change-issue), then remove this `needs-breaking-change-doc-created` label. - - - Tagging @dotnet/compat for awareness of the breaking change. - description: Add breaking change doc label to issue - - if: - - payloadType: Pull_Request - - labelAdded: - label: breaking-change - - isPullRequest - then: - - addLabel: - label: needs-breaking-change-doc-created - - addReply: - reply: >- - Added `needs-breaking-change-doc-created` label because this PR has the `breaking-change` label. - - - When you commit this breaking change: - - - 1. [ ] Create and link to this PR and the issue a matching issue in the dotnet/docs repo using the [breaking change documentation template](https://aka.ms/dotnet/docs/new-breaking-change-issue), then remove this `needs-breaking-change-doc-created` label. - - 2. [ ] Ask a committer to mail the `.NET Breaking Change Notification` DL. - - - Tagging @dotnet/compat for awareness of the breaking change. - description: Add breaking change doc label to PR - - if: - - or: - - payloadType: Issues - - payloadType: Pull_Request - - isAction: - action: Opened - then: - - if: - - hasLabel: - label: linkable-framework - then: - - mentionUsers: - mentionees: - - eerhardt - - vitek-karas - - LakshanF - - sbomer - - joperezr - - marek-safar - replyTemplate: >- - Tagging subscribers to 'linkable-framework': ${mentionees} - - See info in area-owners.md if you want to be subscribed. - assignMentionees: False - description: '@Mention for linkable-framework' - - if: - - or: - - payloadType: Issues - - payloadType: Pull_Request - - isAction: - action: Opened - then: - - if: - - hasLabel: - label: size-reduction - then: - - mentionUsers: - mentionees: - - eerhardt - - SamMonoRT - - marek-safar - replyTemplate: >- - Tagging subscribers to 'size-reduction': ${mentionees} - - See info in area-owners.md if you want to be subscribed. - assignMentionees: False - description: '@Mention for size-reduction' - - if: - - or: - - payloadType: Issues - - payloadType: Pull_Request - - isAction: - action: Opened - then: - - if: - - hasLabel: - label: arch-wasm - then: - - mentionUsers: - mentionees: - - lewing - replyTemplate: >- - Tagging subscribers to 'arch-wasm': ${mentionees} - - See info in area-owners.md if you want to be subscribed. - assignMentionees: False - description: '@Mention for wasm' - - if: - - or: - - payloadType: Issues - - payloadType: Pull_Request - - isAction: - action: Opened - then: - - if: - - hasLabel: - label: os-ios - then: - - mentionUsers: - mentionees: - - steveisok - - akoeplinger - - kotlarmilos - replyTemplate: >- - Tagging subscribers to 'os-ios': ${mentionees} - - See info in area-owners.md if you want to be subscribed. - assignMentionees: False - description: '@Mention for ios' - - if: - - or: - - payloadType: Issues - - payloadType: Pull_Request - - isAction: - action: Opened - then: - - if: - - hasLabel: - label: os-android - then: - - mentionUsers: - mentionees: - - steveisok - - akoeplinger - replyTemplate: >- - Tagging subscribers to 'arch-android': ${mentionees} - - See info in area-owners.md if you want to be subscribed. - assignMentionees: False - description: '@Mention for android' - - if: - - payloadType: Pull_Request - - or: - - filesMatchPattern: - pattern: .*ILLink.* - - filesMatchPattern: - pattern: .*illink.* - - not: - hasLabel: - label: linkable-framework - - isPullRequest - - isOpen - then: - - addLabel: - label: linkable-framework - description: '[Linkable-framework workgroup] Add linkable-framework label to new Prs that touch files with *ILLink* that not have it already' - - if: - - payloadType: Pull_Request - - or: - - filesMatchPattern: - pattern: .*ILLink.* - - filesMatchPattern: - pattern: .*illink.* - - not: - hasLabel: - label: linkable-framework - - isPullRequest - - isOpen - - isAction: - action: Synchronize - then: - - addLabel: - label: linkable-framework - description: '[Linkable-framework workgroup] Add linkable-framework label to Prs that get changes pushed where they touch *ILLInk* files' - - if: - - payloadType: Issues - - labelAdded: - label: backlog-cleanup-candidate - then: - - addReply: - reply: >- - Due to lack of recent activity, this issue has been marked as a candidate for backlog cleanup. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will undo this process. - - - This process is part of our [issue cleanup automation](https://github.com/dotnet/runtime/blob/main/docs/issue-cleanup.md). - - addLabel: - label: no-recent-activity - description: Manual Issue Cleanup - - if: - - or: - - payloadType: Issues - - payloadType: Pull_Request - - isAction: - action: Opened - then: - - if: - - hasLabel: - label: os-tvos - then: - - mentionUsers: - mentionees: - - steveisok - - akoeplinger - replyTemplate: >- - Tagging subscribers to 'os-tvos': ${mentionees} - - See info in area-owners.md if you want to be subscribed. - assignMentionees: False - description: '@Mention for tvos' - - if: - - or: - - payloadType: Issues - - payloadType: Pull_Request - - isAction: - action: Opened - then: - - if: - - hasLabel: - label: os-maccatalyst - then: - - mentionUsers: - mentionees: - - steveisok - - akoeplinger - replyTemplate: >- - Tagging subscribers to 'os-maccatalyst': ${mentionees} - - See info in area-owners.md if you want to be subscribed. - assignMentionees: False - description: '@Mention for maccatalyst' - - if: - - payloadType: Issues - - or: - - isAction: - action: Opened - - isAction: - action: Reopened - - isOpen - - not: isPartOfAnyMilestone - - not: - hasLabel: - label: untriaged - then: - - addLabel: - label: untriaged - description: Add untriaged label to new/reopened issues without a milestone - - if: - - payloadType: Issues - - or: - - isAction: - action: Closed - - isPartOfAnyMilestone - - hasLabel: - label: untriaged - then: - - removeLabel: - label: untriaged - description: Remove untriaged label from issues when closed or added to a milestone - - if: - - payloadType: Pull_Request - then: - - inPrLabel: - label: in-pr - description: Add `in-pr` label on issue when an open pull request is targeting it - - if: - - payloadType: Pull_Request - - isAction: - action: Opened - - not: - activitySenderHasPermission: - permission: Read - then: - - assignTo: - author: True - description: Assign Team PRs to author - - if: - - payloadType: Pull_Request - - isAction: - action: Opened - - isPullRequest - - and: - - not: - activitySenderHasPermission: - permission: Admin - - not: - activitySenderHasPermission: - permission: Write - - not: - isActivitySender: - user: github-actions[bot] - issueAuthor: False - - not: - isActivitySender: - user: dotnet-maestro[bot] - issueAuthor: False - - not: - isActivitySender: - user: dotnet-maestro-bot[bot] - issueAuthor: False - - not: - isActivitySender: - user: dotnet-maestro-bot - issueAuthor: False - - not: - isActivitySender: - user: dotnet-maestro - issueAuthor: False - - not: - isActivitySender: - user: github-actions - issueAuthor: False - then: - - addLabel: - label: community-contribution - description: Label community PRs - - if: - - payloadType: Issues - - labelAdded: - label: needs-author-action - then: - - addReply: - reply: This issue has been marked `needs-author-action` and may be missing some important information. - description: Needs-author-action notification - - if: - - payloadType: Pull_Request_Review - - not: - activitySenderHasPermission: - permission: Read - - isPullRequest - - isAction: - action: Submitted - - isReviewState: - reviewState: Changes_requested - then: - - addLabel: - label: needs-author-action - description: PR reviews with "changes requested" applies the needs-author-action label - - if: - - payloadType: Issue_Comment - - isAction: - action: Created - - isActivitySender: - issueAuthor: True - - hasLabel: - label: needs-author-action - - not: - hasLabel: - label: untriaged - - isIssue - - isOpen - then: - - addLabel: - label: needs-further-triage - - removeLabel: - label: needs-author-action - description: Replace `needs-author-action` label with `needs-further-triage` label when the author comments on an issue that is not still untriaged - - if: - - payloadType: Issue_Comment - - isAction: - action: Created - - isActivitySender: - issueAuthor: True - - hasLabel: - label: needs-author-action - - hasLabel: - label: untriaged - - isIssue - - isOpen - then: - - removeLabel: - label: needs-author-action - description: Remove `needs-author-action` label when the author comments on an `untriaged` issue - - if: - - payloadType: Pull_Request - - isPullRequest - - isAction: - action: Synchronize - - hasLabel: - label: needs-author-action - then: - - removeLabel: - label: needs-author-action - description: Pushing changes to PR branch removes the needs-author-action label - - if: - - payloadType: Issue_Comment - - isActivitySender: - issueAuthor: True - - isAction: - action: Created - - hasLabel: - label: needs-author-action - - isPullRequest - - isOpen - then: - - removeLabel: - label: needs-author-action - description: Author commenting in PR removes the needs-author-action label - - if: - - payloadType: Pull_Request_Review - - isActivitySender: - issueAuthor: True - - hasLabel: - label: needs-author-action - - isAction: - action: Submitted - - isPullRequest - - isOpen - then: - - removeLabel: - label: needs-author-action - description: Author responding to a pull request review comment removes the needs-author-action label - - if: - - payloadType: Issues - - not: - isAction: - action: Closed - - hasLabel: - label: no-recent-activity - - not: - labelAdded: - label: no-recent-activity - then: - - removeLabel: - label: no-recent-activity - - removeLabel: - label: backlog-cleanup-candidate - description: Remove `no-recent-activity` label from issues when issue is modified - - if: - - payloadType: Issue_Comment - - hasLabel: - label: no-recent-activity - - isIssue - then: - - removeLabel: - label: no-recent-activity - - removeLabel: - label: backlog-cleanup-candidate - description: Remove `no-recent-activity` label when an issue is commented on - - if: - - payloadType: Pull_Request - - isPullRequest - - isOpen - - hasLabel: - label: no-recent-activity - - not: - labelAdded: - label: no-recent-activity - then: - - removeLabel: - label: no-recent-activity - - removeLabel: - label: backlog-cleanup-candidate - description: Remove `no-recent-activity` label from PRs when modified - - if: - - payloadType: Issue_Comment - - hasLabel: - label: no-recent-activity - - isPullRequest - - isOpen - then: - - removeLabel: - label: no-recent-activity - - removeLabel: - label: backlog-cleanup-candidate - description: Remove `no-recent-activity` label from PRs when commented on - - if: - - payloadType: Pull_Request_Review - - hasLabel: - label: no-recent-activity - - isPullRequest - - isOpen - then: - - removeLabel: - label: no-recent-activity - - removeLabel: - label: backlog-cleanup-candidate - description: Remove `no-recent-activity` label from PRs when new review is added -onFailure: -onSuccess: diff --git a/.github/workflows/aspnetcore-sync.yml b/.github/workflows/aspnetcore-sync.yml index 01aa3dfdabca..582f371cf9ab 100644 --- a/.github/workflows/aspnetcore-sync.yml +++ b/.github/workflows/aspnetcore-sync.yml @@ -16,14 +16,14 @@ jobs: runs-on: windows-latest steps: - name: Checkout aspnetcore - uses: actions/checkout@v2.0.0 + uses: actions/checkout@v4 with: # Test this script using changes in a fork repository: 'dotnet/aspnetcore' path: aspnetcore ref: main - name: Checkout runtime - uses: actions/checkout@v2.0.0 + uses: actions/checkout@v4 with: # Test this script using changes in a fork repository: 'dotnet/runtime' @@ -42,7 +42,7 @@ jobs: mkdir ..\artifacts git status > ..\artifacts\status.txt git diff > ..\artifacts\diff.txt - - uses: actions/upload-artifact@v1 + - uses: actions/upload-artifact@v4 with: name: results path: artifacts @@ -57,7 +57,7 @@ jobs: - name: Send PR if: steps.check.outputs.changed == 'true' # https://github.com/marketplace/actions/create-pull-request - uses: dotnet/actions-create-pull-request@v3 + uses: dotnet/actions-create-pull-request@v4 with: token: ${{ secrets.GITHUB_TOKEN }} path: .\runtime diff --git a/.github/workflows/bump-chrome-version.yml b/.github/workflows/bump-chrome-version.yml index 65427d63f657..e1d1e89658ca 100644 --- a/.github/workflows/bump-chrome-version.yml +++ b/.github/workflows/bump-chrome-version.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Branch run: | git config user.name github-actions[bot] @@ -27,7 +27,7 @@ jobs: run: >- make -C src/mono/wasm build-tasks && PATH=$PWD/.dotnet:$PATH dotnet build eng/testing/bump-chrome-version.proj -p:Configuration=Release && - git add eng/testing/ChromeVersions.props && + git add eng/testing/BrowserVersions.props && cat eng/testing/bump-chrome-pr.env >> "$GITHUB_ENV" - name: Check for changes @@ -47,7 +47,7 @@ jobs: - name: Create PR if: steps.check_changes.outputs.has_changes == 'true' - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const { CHROME_LINUX_VER, CHROME_WIN_VER } = process.env; diff --git a/.github/workflows/locker.yml b/.github/workflows/locker.yml index 2b7ab0032758..bea3f2fa09f9 100644 --- a/.github/workflows/locker.yml +++ b/.github/workflows/locker.yml @@ -20,13 +20,14 @@ permissions: jobs: main: runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'dotnet' }} steps: - name: Checkout Actions uses: actions/checkout@v4 with: repository: "microsoft/vscode-github-triage-actions" path: ./actions - ref: cd16cd2aad6ba2da74bb6c6f7293adddd579a90e + ref: 066bee9cefa6f0b4bf306040ff36fc7d96a6d56d # locker action commit sha - name: Install Actions run: npm install --production --prefix ./actions - name: Run Locker diff --git a/.gitignore b/.gitignore index 9931e9ae0ad3..4bbfe24b82e1 100644 --- a/.gitignore +++ b/.gitignore @@ -187,6 +187,7 @@ node_modules/ *.metaproj *.metaproj.tmp bin.localpkg/ +.mono/ # RIA/Silverlight projects Generated_Code/ diff --git a/Directory.Build.props b/Directory.Build.props index 46c00ca53a38..9e94baffe87f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -62,18 +62,22 @@ - eng/native/configurecompiler.cmake - eng/native/build-commons.sh - src/native/libs/build-native.sh - - src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs + - src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/MachObjectWriter.cs - src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets + - src/mono/mono/tools/offsets-tool/offsets-tool.py + - src/mono/msbuild/apple/build/AppleBuild.targets - src/installer/pkg/sfx/bundle/shared-framework-distribution-template-x64.xml - src/installer/pkg/sfx/bundle/shared-framework-distribution-template-arm64.xml + - src/tasks/AotCompilerTask/MonoAOTCompiler.props + - src/tasks/AppleAppBuilder/Xcode.cs - src/tasks/MobileBuildTasks/Apple/AppleProject.cs - dotnet/installer repo > src/redist/targets/GeneratePKG.targets --> 21 - 11.0 - 11.0 - 10.15 - 11.0 + 12.2 + 12.2 + 12.0 + 15.0 @@ -186,7 +190,9 @@ $([MSBuild]::NormalizePath('$(TestExclusionListTasksDir)', 'TestExclusionListTasks.dll')) $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'coreclr', '$(TargetOS).$(TargetArchitecture).$(RuntimeConfiguration)')) $(CoreCLRToolPath) + $([MSBuild]::NormalizeDirectory($(ArtifactsObjDir), 'wasmtime')) true $([MSBuild]::NormalizeDirectory($(WasmProjectRoot), 'build')) @@ -329,7 +335,7 @@ true - ClrFullNativeBuild;ClrRuntimeSubset;ClrJitSubset;ClrPalTestsSubset;ClrAllJitsSubset;ClrILToolsSubset;ClrNativeAotSubset;ClrSpmiSubset;ClrCrossComponentsSubset;ClrDebugSubset;HostArchitecture;PgoInstrument;NativeOptimizationDataSupported;CMakeArgs + ClrFullNativeBuild;ClrRuntimeSubset;ClrJitSubset;ClrPalTestsSubset;ClrAllJitsSubset;ClrILToolsSubset;ClrNativeAotSubset;ClrSpmiSubset;ClrCrossComponentsSubset;ClrDebugSubset;HostArchitecture;PgoInstrument;NativeOptimizationDataSupported;CMakeArgs;CxxStandardLibrary;CxxStandardLibraryStatic;CxxAbiLibrary @@ -396,7 +402,6 @@ $(NoWarn),CS8969 portable - true true false @@ -409,12 +414,10 @@ true true - true - true - true + true - false + false @@ -425,7 +428,7 @@ '$(IsReferenceAssemblyProject)' != 'true' and '$(IsGeneratorProject)' != 'true' and '$(IsTestProject)' != 'true' and - '$(IsPublishedAppTestProject)' != 'true' and + '$(IsTrimmingTestProject)' != 'true' and '$(IsTestSupportProject)' != 'true' and '$(UsingMicrosoftDotNetSharedFrameworkSdk)' != 'true' and '$(MSBuildProjectExtension)' != '.pkgproj' and @@ -476,7 +479,7 @@ - + true diff --git a/Directory.Build.targets b/Directory.Build.targets index f731eedc390c..1161d409dec1 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -86,9 +86,10 @@ - + $(SystemReflectionMetadataLoadContextVersion) + $(SystemTextJsonVersion)
  • Microsoft.Extensions.DependencyModel
  • | | area-Diagnostics-coreclr | @tommcdon | @tommcdon | | -| area-Diagnostics-mono | @tommcdon | @tommcdon @mdh1418 | | -| area-EnC-mono | @tommcdon | @mikelle-rogers | Hot Reload on WebAssembly, Android, iOS, etc . @lambdageek to consult | +| area-Diagnostics-mono | @tommcdon | @tommcdon @mdh1418 @thaystg | | +| area-EnC-mono | @tommcdon | @mikelle-rogers @thaystg | Hot Reload on WebAssembly, Android, iOS, etc . @lambdageek to consult | | area-ExceptionHandling-coreclr | @mangod9 | @janvorli | | | area-Extensions-Caching | @ericstj | @dotnet/area-extensions-caching | Consultants: @mgravell, @sebastienros | | area-Extensions-Configuration | @ericstj | @dotnet/area-extensions-configuration | Consultants: @eerhardt | @@ -141,7 +141,7 @@ Note: Editing this file doesn't update the mapping used by `@msftbot` for area-s | area-Tools-ILLink | @agocke | @dotnet/illink | | | area-Tools-ILVerification | @JulieLeeMSFT | @BruceForstall @dotnet/jit-contrib | | | area-Tracing-coreclr | @tommcdon | @dotnet/area-tracing-coreclr | .NET runtime issues for EventPipe and ICorProfiler | -| area-Tracing-mono | @tommcdon | @tommcdon | | +| area-Tracing-mono | @tommcdon | @tommcdon @thaystg | | | area-TypeSystem-coreclr | @steveisok | @davidwrighton @MichalStrehovsky @janvorli @mangod9 | | | area-UWP | @tommcdon | @dotnet/area-uwp | UWP-specific issues including Microsoft.NETCore.UniversalWindowsPlatform and Microsoft.Net.UWPCoreRuntimeSdk | | area-VM-coreclr | @mangod9 | @mangod9 | | diff --git a/docs/coding-guidelines/coding-style.md b/docs/coding-guidelines/coding-style.md index d584de831302..32dd1ec8bb65 100644 --- a/docs/coding-guidelines/coding-style.md +++ b/docs/coding-guidelines/coding-style.md @@ -36,7 +36,7 @@ The general rule we follow is "use Visual Studio defaults". An [EditorConfig](https://editorconfig.org "EditorConfig homepage") file (`.editorconfig`) has been provided at the root of the runtime repository, enabling C# auto-formatting conforming to the above guidelines. -We also use the [.NET Codeformatter Tool](https://github.com/dotnet/codeformatter) to ensure the code base maintains a consistent style over time, the tool automatically fixes the code base to conform to the guidelines outlined above. +We also use the [dotnet-format tool](https://learn.microsoft.com/dotnet/core/tools/dotnet-format) to ensure the code base maintains a consistent style over time, the tool automatically fixes the code base to conform to the guidelines outlined above. ### Example File: diff --git a/docs/design/coreclr/botr/vectors-and-intrinsics.md b/docs/design/coreclr/botr/vectors-and-intrinsics.md index 6b15c16981c9..2fc93df7e8ee 100644 --- a/docs/design/coreclr/botr/vectors-and-intrinsics.md +++ b/docs/design/coreclr/botr/vectors-and-intrinsics.md @@ -156,6 +156,14 @@ private void SomeVectorizationHelper() } ``` +#### Non-Deterministic Intrinsics in System.Private.Corelib + +Some APIs exposed in System.Private.Corelib are intentionally non-deterministic across hardware and instead only ensure determinism within the scope of a single process. To facilitate the support of such APIs, the JIT defines `Compiler::BlockNonDeterministicIntrinsics(bool mustExpand)` which should be used to help block such APIs from expanding in scenarios such as ReadyToRun. Additionally, such APIs should recursively call themselves so that indirect invocation (such as via a delegate, function pointer, reflection, etc) will compute the same result. + +An example of such a non-deterministic API is the `ConvertToIntegerNative` APIs exposed on `System.Single` and `System.Double`. These APIs convert from the source value to the target integer type using the fastest mechanism available for the underlying hardware. They exist due to the IEEE 754 specification leaving conversions undefined when the input cannot fit into the output (for example converting `float.MaxValue` to `int`) and thus different hardware having historically provided differing behaviors on these edge cases. They allow developers who do not need to be concerned with edge case handling but where the performance overhead of normalizing results for the default cast operator is too great. + +Another example is the various `*Estimate` APIs, such as `float.ReciprocalSqrtEstimate`. These APIs allow a user to likewise opt into a faster result at the cost of some inaccuracy, where the exact inaccuracy encountered depends on the input and the underlying hardware the instruction is executed against. + # Mechanisms in the JIT to generate correct code to handle varied instruction set support The JIT receives flags which instruct it on what instruction sets are valid to use, and has access to a new jit interface api `notifyInstructionSetUsage(isa, bool supportBehaviorRequired)`. diff --git a/docs/design/datacontracts/Thread.md b/docs/design/datacontracts/Thread.md index 7bee0fe79fdc..2910dc8dbb82 100644 --- a/docs/design/datacontracts/Thread.md +++ b/docs/design/datacontracts/Thread.md @@ -22,9 +22,7 @@ enum ThreadState TS_AbortRequested = 0x00000001, // Abort the thread - TS_GCSuspendPending = 0x00000002, // ThreadSuspend::SuspendRuntime watches this thread to leave coop mode. TS_GCSuspendRedirected = 0x00000004, // ThreadSuspend::SuspendRuntime has redirected the thread to suspention routine. - TS_GCSuspendFlags = TS_GCSuspendPending | TS_GCSuspendRedirected, // used to track suspension progress. Only SuspendRuntime writes/resets these. TS_DebugSuspendPending = 0x00000008, // Is the debugger suspending threads? TS_GCOnTransitions = 0x00000010, // Force a GC on stub transitions (GCStress only) diff --git a/docs/design/datacontracts/contract-descriptor.md b/docs/design/datacontracts/contract-descriptor.md index 1e3ddabd6dd7..fbd58eb33eb9 100644 --- a/docs/design/datacontracts/contract-descriptor.md +++ b/docs/design/datacontracts/contract-descriptor.md @@ -24,9 +24,9 @@ struct DotNetRuntimeContractDescriptor uint32_t flags; uint32_t descriptor_size; const char *descriptor; - uint32_t aux_data_count; + uint32_t pointer_data_count; uint32_t pad0; - uintptr_t *aux_data; + uintptr_t *pointer_data; }; ``` @@ -45,7 +45,7 @@ reserved bits should be written as zero. Diagnostic tooling may ignore non-zero The `descriptor` is a pointer to a UTF-8 JSON string described in [data descriptor physical layout](./data_descriptor.md#Physical_JSON_descriptor). The total number of bytes is given by `descriptor_size`. -The auxiliary data for the JSON descriptor is stored at the location `aux_data` in `aux_data_count` pointer-sized slots. +The auxiliary data for the JSON descriptor is stored at the location `pointer_data` in `pointer_data_count` pointer-sized slots. ### Architecture properties @@ -83,7 +83,7 @@ a JSON integer constant. "globals": { "FEATURE_COMINTEROP": 0, - "s_pThreadStore": [ 0 ] // indirect from aux data offset 0 + "s_pThreadStore": [ 0 ] // indirect from pointer data offset 0 }, "contracts": {"Thread": 1, "GCHandle": 1, "ThreadStore": 1} } diff --git a/docs/design/datacontracts/data/empty.jsonc b/docs/design/datacontracts/data/empty.jsonc new file mode 100644 index 000000000000..29d15882a36b --- /dev/null +++ b/docs/design/datacontracts/data/empty.jsonc @@ -0,0 +1,4 @@ +// the empty baseline data descriptor +{ + "version": 0 +} diff --git a/docs/design/mono/mono-manpage-1.md b/docs/design/mono/mono-manpage-1.md new file mode 100644 index 000000000000..8f5bd56abb3d --- /dev/null +++ b/docs/design/mono/mono-manpage-1.md @@ -0,0 +1,2012 @@ +# Mono Manual Page + +Copyright 2003 Ximian, Inc. \ +Copyright 2004-2011 Novell, Inc. \ +Copyright 2011-2012 Xamarin Inc \ +Copyright 2013 7digital Media Ltd. \ +Copyright (c) .NET Foundation and Contributors + +Author: \ +Miguel de Icaza (miguel@gnu.org) + +## NAME + +mono - Mono's ECMA-CLI native code generator (Just-in-Time and +Ahead-of-Time) + +## SYNOPSIS + +**mono \[options\] file \[arguments...\]** + +**mono-sgen \[options\] file \[arguments...\]** + +## DESCRIPTION + +*mono* is a runtime implementation of the ECMA Common Language +Infrastructure. This can be used to run ECMA and .NET applications. + +The runtime loads the specified *file* and optionally passes the +*arguments* to it. The *file* is an ECMA assembly. They typically have a +.exe or .dll extension. + +These executables can reference additional functionality in the form of +assembly references. By default those assembly references are resolved +as follows: the **mscorlib.dll** is resolved from the system profile +that is configured by Mono, and other assemblies are loaded from the +Global Assembly Cache (GAC). + +The runtime contains a native code generator that transforms the Common +Intermediate Language into native code. + +The code generator can operate in two modes: Just-in-time compilation +(JIT) or Ahead-of-time compilation (AOT). Since code can be dynamically +loaded, the runtime environment and the JIT are always present, even if +code is compiled ahead of time. + +The runtime provides a number of configuration options for running +applications, for developing and debugging, and for testing and +debugging the runtime itself. + +The *mono* command uses the moving and generational SGen garbage +collector while the *mono-boehm* command uses the conservative Boehm +garbage collector. + +## PORTABILITY + +On Unix-based systems, Mono provides a mechanism to emulate the +Windows-style file access, this includes providing a case insensitive +view of the file system, directory separator mapping (from \\ to /) and +stripping the drive letters. + +This functionality is enabled by setting the **MONO_IOMAP** environment +variable to one of **all, drive** and **case.** + +See the description for **MONO_IOMAP** in the environment variables +section for more details. + +## METHOD DESCRIPTIONS + +A number of diagnostic command line options take as argument a method +description. A method description is a textual representation that can +be used to uniquely identify a method. The syntax is as follows: + + [W:][namespace]classname:methodname[(arguments)] + +The values in brackets are optional, like the namespace and the +arguments. The arguments themselves are either empty, or a +comma-separated list of arguments. Both the **classname** and +**methodname** can be set to the special value '\*' to match any values +(Unix shell users should escape the argument to avoid the shell +interpreting this). + +The arguments, if present should be a comma separated list of types +either a full typename, or for built-in types it should use the +low-level ILAsm type names for the built-in types, like 'void', 'char', +'bool', 'byte', 'sbyte', 'uint16', 'int16', 'uint', + +Pointer types should be the name of the type, followed by a '\*', arrays +should be the typename followed by '\[' one or more commas (to indicate +the rank of the array), and '\]'. + +Generic values should use '\<', one or more type names, separated by +both a comma and a space and '\>'. + +By-reference arguments should include a "&" after the typename. + +If the method description is prefixed by 'W:' (or 'w:'), then it will +match a *wrapper* method that may be created by the runtime for the +specified method. (For example imported P/Invoke methods may have a +wrapper generated by the runtime.) + + +Examples: + + *:ctor(int) // All constructors that take an int as an argument + *:Main // Methods named Main in any class + *:Main(string[]) // Methods named Main that take a string array in any class + W:UnixSignal:install // Wrappers for the UnixSignal.install DllImport + +## RUNTIME OPTIONS + +The following options are available: + +**--aot**, **--aot\[=options\]** +This option is used to precompile the CIL code in the specified assembly +to native code. The generated code is stored in a file with the +extension .so. This file will be automatically picked up by the runtime +when the assembly is executed. + +Ahead-of-Time compilation is most useful if you use it in combination +with the -O=all,-shared flag which enables all of the optimizations in +the code generator to be performed. Some of those optimizations are not +practical for Just-in-Time compilation since they might be very time +consuming. + +Unlike the .NET Framework, Ahead-of-Time compilation will not generate +domain independent code: it generates the same code that the +Just-in-Time compiler would produce. Since most applications use a +single domain, this is fine. If you want to optimize the generated code +for use in multi-domain applications, consider using the -O=shared flag. + +This pre-compiles the methods, but the original assembly is still +required to execute as this one contains the metadata and exception +information which is not available on the generated file. When +precompiling code, you might want to compile with all optimizations +(-O=all). Pre-compiled code is position independent code. + +Precompilation is just a mechanism to reduce startup time, increase code +sharing across multiple mono processes and avoid just-in-time +compilation program startup costs. The original assembly must still be +present, as the metadata is contained there. + +AOT code typically can not be moved from one computer to another +(CPU-specific optimizations that are detected at runtime) so you should +not try to move the pre-generated assemblies or package the +pre-generated assemblies for deployment. + +A few options are available as a parameter to the **--aot** command line +option. The options are separated by commas, and more than one can be +specified: + +> *asmonly* +> Instructs the AOT compiler to output assembly code instead of an +> object file. +> +> *bind-to-runtime-version* +> +> If specified, forces the generated AOT files to be bound to the +> runtime version of the compiling Mono. This will prevent the AOT files +> from being consumed by a different Mono runtime. +> +> *data-outfile=FILE.dll.aotdata* +> +> This instructs the AOT code generator to output certain data +> constructs into a separate file. This can reduce the executable images +> some five to twenty percent. Developers need to then ship the +> resulting aotdata as a resource and register a hook to load the data +> on demand by using the *mono_install_load_aot_data_hook* method. +> +> *direct-icalls* +> +> When this option is specified, icalls (internal calls made from the +> standard library into the mono runtime code) are invoked directly +> instead of going through the operating system symbol lookup operation. +> This requires use of the *static* option. +> +> *direct-pinvoke* +> +> When this option is specified, P/Invoke methods are invoked directly +> instead of going through the operating system symbol lookup operation. +> This requires use of the *static* option. +> +> *dwarfdebug* +> Instructs the AOT compiler to emit DWARF debugging information. When +> used together with the nodebug option, only DWARF debugging +> information is emitted, but not the information that can be used at +> runtime. +> +> *full* +> +> This creates binaries which can be used with the --full-aot option. +> +> *hybrid* +> +> This creates binaries which can be used with the --hybrid-aot option. +> +> *llvm* +> AOT will be performed with the LLVM backend instead of the Mono +> backend where possible. This will be slower to compile but most likely +> result in a performance improvement. +> +> *llvmonly* +> AOT will be performed with the LLVM backend exclusively and the Mono +> backend will not be used. The only output in this mode will be the +> bitcode file normally specified with the *llvm-outfile* option. Use of +> *llvmonly* automatically enables the *full* and *llvm* options. This +> feature is experimental. +> +> *llvmopts=\[options\]* +> Use this option to add more flags to the built-in set of flags passed +> to the LLVM optimizer. When you invoke the *mono* command with the +> *--aot=llvm* it displays the current list of flags that are being +> passed to the *opt* command. *The list of possible flags that can be +> passed can be* obtained by calling the bundled *opt* program that +> comes with Mono, and calling it like this: +> +> +> +> +> opt --help +> +> *llvmllc=\[options\]* +> Use this option to add more flags to the built-in set of flags passed +> to the LLVM static compiler (llc). The list of possible flags that can +> be passed can be obtained by calling the bundled *llc* program that +> comes with Mono, and calling it like this: +> +> +> +> +> llc --help +> +> *mcpu=\[native o generic\]* +> cpu=native allows AOT mode to use all instructions current CPU +> supports, e.g. AVX2, SSE42, etc. Default value is 'generic'. +> *mattr=\[cpu feature\]* Allows AOT code generator to use specified CPU +> features where possible including \`System.Runtime.Intrinsics.\*'. +> E.g. \`mattr=+avx2,mattr=-lzcnt' unlocks sse1-4.2, avx1-2 and disables +> lzcnt. It's useful for cross-compilation or when it's not possible to +> use \`-mcpu=native' (which enables all cpu feature current cpu has). +> *llvm-outfile=\[filename\]* Gives the path for the temporary LLVM +> bitcode file created during AOT. *dedup* Each AOT module will +> typically contain the code for inflated methods and wrappers that are +> called by code in that module. In dedup mode, we identify and skip +> compiling all of those methods. When using this mode with fullaot, +> dedup-include is required or these methods will remain missing. +> +> *dedup-include=\[filename\]* +> In dedup-include mode, we are in the pass of compilation where we +> compile the methods that we had previously skipped. All of them are +> emitted into the assembly that is passed as this option. We +> consolidate the many duplicate skipped copies of the same method into +> one. +> +> +> +> *info* +> Print the architecture the AOT in this copy of Mono targets and quit. +> +> *interp* +> Generates all required wrappers, so that it is possible to run +> --interpreter without any code generation at runtime. This option only +> makes sense with **mscorlib.dll**. Embedders can set +> +> *depfile=\[filename\]* +> Outputs a gcc -M style dependency file. +> +> mono_jit_set_aot_mode (MONO_AOT_MODE_INTERP); +> +> +> +> *ld-flags* +> Additional flags to pass to the C linker (if the current AOT mode +> calls for invoking it). +> +> *llvm-path=\* +> Same for the llvm tools 'opt' and 'llc'. +> +> *msym-dir=\* +> Instructs the AOT compiler to generate offline sequence points .msym +> files. The generated .msym files will be stored into a subfolder of +> \ named as the compilation AOTID. +> +> *mtriple=\* +> Use the GNU style target triple \ to determine some code +> generation options, i.e. --mtriple=armv7-linux-gnueabi will generate +> code that targets ARMv7. This is currently only supported by the ARM +> backend. In LLVM mode, this triple is passed on to the LLVM llc +> compiler. +> +> *nimt-trampolines=\[number\]* +> When compiling in full aot mode, the IMT trampolines must be +> precreated in the AOT image. You can add additional method trampolines +> with this argument. Defaults to 512. +> +> *ngsharedvt-trampolines=\[number\]* +> When compiling in full aot mode, the value type generic sharing +> trampolines must be precreated in the AOT image. You can add +> additional method trampolines with this argument. Defaults to 512. +> +> *nodebug* +> Instructs the AOT compiler to not output any debugging information. +> +> *no-direct-calls* +> This prevents the AOT compiler from generating a direct calls to a +> method. The AOT compiler usually generates direct calls for certain +> methods that do not require going through the PLT (for example, +> methods that are known to not require a hook like a static +> constructor) or call into simple internal calls. +> +> *nrgctx-trampolines=\[number\]* +> When compiling in full aot mode, the generic sharing trampolines must +> be precreated in the AOT image. You can add additional method +> trampolines with this argument. Defaults to 4096. +> +> *nrgctx-fetch-trampolines=\[number\]* +> When compiling in full aot mode, the generic sharing fetch trampolines +> must be precreated in the AOT image. You can add additional method +> trampolines with this argument. Defaults to 128. +> +> *ntrampolines=\[number\]* +> When compiling in full aot mode, the method trampolines must be +> precreated in the AOT image. You can add additional method trampolines +> with this argument. Defaults to 4096. +> +> *outfile=\[filename\]* +> Instructs the AOT compiler to save the output to the specified file. +> +> *print-skipped-methods* +> If the AOT compiler cannot compile a method for any reason, enabling +> this flag will output the skipped methods to the console. +> +> *profile=\[file\]* +> Specify a file to use for profile-guided optimization. See the **AOT +> profiler** sub-section. To specify multiple files, include the +> *profile* option multiple times. +> +> *profile-only* +> AOT \*only\* the methods described in the files specified with the +> *profile* option. See the **AOT profiler** sub-section. +> +> *readonly-value=namespace.typename.fieldname=type/value* +> Override the value of a static readonly field. Usually, during JIT +> compilation, the static constructor is ran eagerly, so the value of a +> static readonly field is known at compilation time and the compiler +> can do a number of optimizations based on it. During AOT, instead, the +> static constructor can't be ran, so this option can be used to set the +> value of such a field and enable the same set of optimizations. Type +> can be any of i1, i2, i4 for integers of the respective sizes (in +> bytes). Note that signed/unsigned numbers do not matter here, just the +> storage size. This option can be specified multiple times and it +> doesn't prevent the static constructor for the type defining the field +> to execute with the usual rules at runtime (hence possibly computing a +> different value for the field). +> +> *save-temps,keep-temps* +> Instructs the AOT compiler to keep temporary files. +> +> *soft-debug* +> This instructs the compiler to generate sequence point checks that +> allow Mono's soft debugger to debug applications even on systems where +> it is not possible to set breakpoints or to single step (certain +> hardware configurations like the cell phones and video gaming +> consoles). +> +> *static* +> Create an ELF object file (.o) or .s file which can be statically +> linked into an executable when embedding the mono runtime. When this +> option is used, the object file needs to be registered with the +> embedded runtime using the mono_aot_register_module function which +> takes as its argument the mono_aot_module\_\\_info +> global symbol from the object file: +> +> extern void *mono_aot_module_hello_info; +> +> mono_aot_register_module (mono_aot_module_hello_info); +> +> +> +> *stats* +> Print various stats collected during AOT compilation. +> +> *temp-path=\[path\]* +> Explicitly specify path to store temporary files created during AOT +> compilation. +> +> *threads=\[number\]* +> This is an experimental option for the AOT compiler to use multiple +> threads when compiling the methods. +> +> *tool-prefix=\* +> Prepends \ to the name of tools ran by the AOT compiler, i.e. +> 'as'/'ld'. For example, --tool=prefix=arm-linux-gnueabi- will make the +> AOT compiler run +> +> +> +> *ld-name=NAME* +> One of the tools used for AOT builds is the linker. Its name differs +> between various systems and it may happen that the assumed default +> name of the binary is not present. If the toolchain used does not have +> a linker with the default name (e.g. Android NDK r22 does not have the +> default 'ld' linker prefixed with 'tool-prefix' above, instead it has +> prefixed 'ld.gold' and 'ld.bfd' linkers) this option can be used to +> set the linker binary name. It will be prefixed with 'tool-prefix' to +> form the full linker executable name. +> +> *verbose* +> Prints additional information about type loading failures. +> +> *write-symbols,no-write-symbols* +> Instructs the AOT compiler to emit (or not emit) debug symbol +> information. +> +> *no-opt* +> Instructs the AOT compiler tot no call opt when compiling with LLVM. +> +> For more information about AOT, see: +> http://www.mono-project.com/docs/advanced/aot/ + +**--aot-path=PATH** +List of additional directories to search for AOT images. + +**--apply-bindings=FILE** +Apply the assembly bindings from the specified configuration file when +running the AOT compiler. This is useful when compiling an auxiliary +assembly that is referenced by a main assembly that provides a +configuration file. For example, if app.exe uses lib.dll then in order +to make the assembly bindings from app.exe.config available when +compiling lib.dll ahead of time, use: + + + + mono --apply-bindings=app.exe.config --aot lib.dll + +**--assembly-loader=MODE** +If mode is **strict**, Mono will check that the public key token, +culture and version of a candidate assembly matches the requested strong +name. If mode is **legacy**, as long as the name matches, the candidate +will be allowed. **strict** is the behavior consistent with .NET +Framework but may break some existing mono-based applications. The +default is **legacy**. + +**--attach=\[options\]** +Currently the only option supported by this command line argument is +**disable** which disables the attach functionality. + +**--config filename** +Load the specified configuration file instead of the default one(s). The +default files are /etc/mono/config and ~/.mono/config or the file +specified in the MONO_CONFIG environment variable, if set. See the +mono-config(5) man page for details on the format of this file. + +**--debugger-agent=\[options\]** +This instructs the Mono runtime to start a debugging agent inside the +Mono runtime and connect it to a client user interface will control the +Mono process. This option is typically used by IDEs, like the +MonoDevelop or Visual Studio IDEs. + +The configuration is specified using one of more of the following +options: + +> *address=host:port* +> +> Use this option to specify the IP address where your debugger client +> is listening to. +> +> *loglevel=LEVEL* +> +> Specifies the diagnostics log level for +> +> *logfile=filename* +> +> Used to specify the file where the log will be stored, it defaults to +> standard output. +> +> *server=\[y/n\]* +> Defaults to no, with the default option Mono will actively connect to +> the host/port configured with the **address** option. If you set it to +> 'y', it instructs the Mono runtime to start debugging in server mode, +> where Mono actively waits for the debugger front end to connect to the +> Mono process. Mono will print out to stdout the IP address and port +> where it is listening. +> +> *setpgid=\[y/n\]* +> If set to yes, Mono will call **setpgid(0, 0)** on startup, if that +> function is available on the system. This is useful for ensuring that +> signals delivered to a process that is executing the debuggee are not +> propagated to the debuggee, e.g. when Ctrl-C sends **SIGINT** to the +> **sdb** tool. +> +> *suspend=\[y/n\]* +> Defaults to yes, with the default option Mono will suspend the vm on +> startup until it connects successfully to a debugger front end. If you +> set it to 'n', in conjunction with **server=y**, it instructs the Mono +> runtime to run as normal, while caching metadata to send to the +> debugger front end on connection.. +> +> *transport=transport_name* +> +> This is used to specify the transport that the debugger will use to +> communicate. It must be specified and currently requires this to be +> 'dt_socket'. + +**--desktop** +Configures the virtual machine to be better suited for desktop +applications. Currently this sets the GC system to avoid expanding the +heap as much as possible at the expense of slowing down garbage +collection a bit. + +**--full-aot** +This flag instructs the Mono runtime to not generate any code at runtime +and depend exclusively on the code generated from using mono --aot=full +previously. This is useful for platforms that do not permit dynamic code +generation, or if you need to run assemblies that have been stripped of +IL (for example using mono-cil-strip). + +Notice that this feature will abort execution at runtime if a codepath +in your program, or Mono's class libraries attempts to generate code +dynamically. You should test your software upfront and make sure that +you do not use any dynamic features. + +**--full-aot-interp** +Same as --full-aot with fallback to the interpreter. + +**--gc=boehm**, **--gc=sgen** +Selects the Garbage Collector engine for Mono to use, Boehm or SGen. +Currently this merely ensures that you are running either the *mono* or +*mono-sgen* commands. This flag can be set in the **MONO_ENV_OPTIONS** +environment variable to force all of your child processes to use one +particular kind of GC with the Mono runtime. + +**--gc-debug=\[options\]** +Command line equivalent of the **MONO_GC_DEBUG** environment variable. + +**--gc-params=\[options\]** +Command line equivalent of the **MONO_GC_PARAMS** environment variable. + +**--arch=32**, **--arch=64** +(Mac OS X only): Selects the bitness of the Mono binary used, if +available. If the binary used is already for the selected bitness, +nothing changes. If not, the execution switches to a binary with the +selected bitness suffix installed side by side (for example, '/bin/mono +--arch=64' will switch to '/bin/mono64' iff '/bin/mono' is a 32-bit +build). + +**--help**, **-h** +Displays usage instructions. + +**--interpreter** +The Mono runtime will use its interpreter to execute a given assembly. +The interpreter is usually slower than the JIT, but it can be useful on +platforms where code generation at runtime is not allowed. + +**--hybrid-aot** +This flag allows the Mono runtime to run assemblies that have been +stripped of IL, for example using mono-cil-strip. For this to work, the +assembly must have been AOT compiled with --aot=hybrid. + +This flag is similar to --full-aot, but it does not disable the JIT. +This means you can use dynamic features such as System.Reflection.Emit. + +**--llvm** +If the Mono runtime has been compiled with LLVM support (not available +in all configurations), Mono will use the LLVM optimization and code +generation engine to JIT or AOT compile. + +For more information, consult: +http://www.mono-project.com/docs/advanced/mono-llvm/ + +**--ffast-math** +This flag allows Mono and LLVM to apply aggressive floating point +optimizations. Can break IEEE754 compliance. + +**--nollvm** +When using a Mono that has been compiled with LLVM support, it forces +Mono to fallback to its JIT engine and not use the LLVM backend. + +**--optimize=MODE**, **-O=MODE** +MODE is a comma separated list of optimizations. They also allow +optimizations to be turned off by prefixing the optimization name with a +minus sign. + +In general, Mono has been tuned to use the default set of flags, before +using these flags for a deployment setting, you might want to actually +measure the benefits of using them. + +The following optimization flags are implemented in the core engine: + + abcrem Array bound checks removal + all Turn on all optimizations + aot Usage of Ahead Of Time compiled code + branch Branch optimizations + cfold Constant folding + cmov Conditional moves [arch-dependency] + deadce Dead code elimination + consprop Constant propagation + copyprop Copy propagation + fcmov Fast x86 FP compares [arch-dependency] + float32 Perform 32-bit float arithmetic using 32-bit operations + gshared Enable generic code sharing. + inline Inline method calls + intrins Intrinsic method implementations + linears Linear scan global reg allocation + leaf Leaf procedures optimizations + loop Loop related optimizations + peephole Peephole postpass + precomp Precompile all methods before executing Main + sched Instruction scheduling + shared Emit per-domain code + sse2 SSE2 instructions on x86 [arch-dependency] + tailc Tail recursion and tail calls + +For example, to enable all the optimization but dead code elimination +and inlining, you can use: + + -O=all,-deadce,-inline + +The flags that are flagged with \[arch-dependency\] indicate that the +given option if used in combination with Ahead of Time compilation +(--aot flag) would produce pre-compiled code that will depend on the +current CPU and might not be safely moved to another computer. + +> The following optimizations are supported +> +> *float32* +> Requests that the runtime performn 32-bit floating point operations +> using only 32-bits. By default the Mono runtime tries to use the +> highest precision available for floating point operations, but while +> this might render better results, the code might run slower. This +> options also affects the code generated by the LLVM backend. +> +> *inline* +> Controls whether the runtime should attempt to inline (the default), +> or not inline methods invocations + +**--response=FILE** Provides a response file, this instructs the Mono +command to read other command line options from the specified file, as +if the options had been specified on the command line. Useful when you +have very long command lines. + +**--runtime=VERSION** +Mono supports different runtime versions. The version used depends on +the program that is being run or on its configuration file (named +program.exe.config). This option can be used to override such +autodetection, by forcing a different runtime version to be used. Note +that this should only be used to select a later compatible runtime +version than the one the program was compiled against. A typical usage +is for running a 1.1 program on a 2.0 version: + + mono --runtime=v2.0.50727 program.exe + +**--server** +Configures the virtual machine to be better suited for server operations +(currently, allows a heavier threadpool initialization). + +**--use-map-jit** +Instructs Mono to generate code using MAP_JIT on MacOS. Necessary for +bundled applications. + +**--verify-all** +Verifies mscorlib and assemblies in the global assembly cache for valid +IL, and all user code for IL verifiability. + +This is different from **--security**'s verifiable or validil in that +these options only check user code and skip mscorlib and assemblies +located on the global assembly cache. + +**-V**, **--version** +Prints JIT version information (system configuration, release number and +branch names if available). + +**--version=number** +Print version number only. + +## DEVELOPMENT OPTIONS + +The following options are used to help when developing a JITed +application. + +**--debug**, **--debug=OPTIONS** +Turns on the debugging mode in the runtime. If an assembly was compiled +with debugging information, it will produce line number information for +stack traces. + +The optional OPTIONS argument is a comma separated list of debugging +options. These options are turned off by default since they generate +much larger and slower code at runtime. + +The following options are supported: +*casts* +Produces a detailed error when throwing a InvalidCastException. This +option needs to be enabled as this generates more verbose code at +execution time. + +*mdb-optimizations* +Disable some JIT optimizations which are usually only disabled when +running inside the debugger. This can be helpful if you want to attach +to the running process with mdb. + +*gdb* +Generate and register debugging information with gdb. This is only +supported on some platforms, and only when using gdb 7.0 or later. + +**--profile**\[=*profiler*\[:*profiler_args*\]\] +Loads a profiler module with the given arguments. For more information, +see the **PROFILING** section. + +This option can be used multiple times; each time will load an +additional profiler module. + +**--trace\[=expression\]** +Shows method names as they are invoked. By default all methods are +traced. + +The trace can be customized to include or exclude methods, classes or +assemblies. A trace expression is a comma separated list of targets, +each target can be prefixed with a minus sign to turn off a particular +target. The words \`program', \`all' and \`disabled' have special +meaning. \`program' refers to the main program being executed, and +\`all' means all the method calls. + +The \`disabled' option is used to start up with tracing disabled. It can +be enabled at a later point in time in the program by sending the +SIGUSR2 signal to the runtime. + +Assemblies are specified by their name, for example, to trace all calls +in the System assembly, use: + + + mono --trace=System app.exe + +Classes are specified with the T: prefix. For example, to trace all +calls to the System.String class, use: + + + mono --trace=T:System.String app.exe + +And individual methods are referenced with the M: prefix, and the +standard method notation: + + + mono --trace=M:System.Console:WriteLine app.exe + +Exceptions can also be traced, it will cause a stack trace to be printed +every time an exception of the specified type is thrown. The exception +type can be specified with or without the namespace, and to trace all +exceptions, specify 'all' as the type name. + + + mono --trace=E:System.Exception app.exe + +As previously noted, various rules can be specified at once: + + + mono --trace=T:System.String,T:System.Random app.exe + +You can exclude pieces, the next example traces calls to System.String +except for the System.String:Concat method. + + + mono --trace=T:System.String,-M:System.String:Concat + +You can trace managed to unmanaged transitions using the wrapper +qualifier: + + + mono --trace=wrapper app.exe + +Finally, namespaces can be specified using the N: prefix: + + + mono --trace=N:System.Xml + +**--no-x86-stack-align** +Don't align stack frames on the x86 architecture. By default, Mono +aligns stack frames to 16 bytes on x86, so that local floating point and +SIMD variables can be properly aligned. This option turns off the +alignment, which usually saves one instruction per call, but might +result in significantly lower floating point and SIMD performance. + +**--jitmap** +Generate a JIT method map in a /tmp/perf-PID.map file. This file is then +used, for example, by the perf tool included in recent Linux kernels. +Each line in the file has: + + + + + HEXADDR HEXSIZE methodname + +Currently this option is only supported on Linux. + +## JIT MAINTAINER OPTIONS + +The maintainer options are only used by those developing the runtime +itself, and not typically of interest to runtime users or developers. + +**--bisect=optimization:filename** +This flag is used by the automatic optimization bug bisector. It takes +an optimization flag and a filename of a file containing a list of full +method names, one per line. When it compiles one of the methods in the +file it will use the optimization given, in addition to the +optimizations that are otherwise enabled. Note that if the optimization +is enabled by default, you should disable it with \`-O\`, otherwise it +will just apply to every method, whether it's in the file or not. + +**--break method** +Inserts a breakpoint before the method whose name is \`method' +(namespace.class:methodname). Use \`Main' as method name to insert a +breakpoint on the application's main method. You can use it also with +generics, for example "System.Collections.Generic.Queue\`1:Peek" + +**--breakonex** +Inserts a breakpoint on exceptions. This allows you to debug your +application with a native debugger when an exception is thrown. + +**--compile name** +This compiles a method (namespace.name:methodname), this is used for +testing the compiler performance or to examine the output of the code +generator. + +**--compile-all** +Compiles all the methods in an assembly. This is used to test the +compiler performance or to examine the output of the code generator + +**--graph=TYPE METHOD** +This generates a postscript file with a graph with the details about the +specified method (namespace.name:methodname). This requires \`dot' and +ghostview to be installed (it expects Ghostview to be called "gv"). + +The following graphs are available: + + cfg Control Flow Graph (CFG) + dtree Dominator Tree + code CFG showing code + ssa CFG showing code after SSA translation + optcode CFG showing code after IR optimizations + +Some graphs will only be available if certain optimizations are turned +on. + +**--ncompile** +Instruct the runtime on the number of times that the method specified by +--compile (or all the methods if --compile-all is used) to be compiled. +This is used for testing the code generator performance. + +**--stats=\[method\]** +Displays information about the work done by the runtime during the +execution of an application. If a method (namespace.name:methodname) is +specified, it will display that information when the method is first run +in addition to the end of program execution. + +**--wapi=hps\|semdel** +Perform maintenance of the process shared data. + +semdel will delete the global semaphore. + +hps will list the currently used handles. + +**-v**, **--verbose** +Increases the verbosity level, each time it is listed, increases the +verbosity level to include more information (including, for example, a +disassembly of the native code produced, code selector info etc.). + +## ATTACH SUPPORT + +The Mono runtime allows external processes to attach to a running +process and load assemblies into the running program. To attach to the +process, a special protocol is implemented in the Mono.Management +assembly. + +With this support it is possible to load assemblies that have an entry +point (they are created with -target:exe or -target:winexe) to be loaded +and executed in the Mono process. + +The code is loaded into the root domain, and it starts execution on the +special runtime attach thread. The attached program should create its +own threads and return after invocation. + +This support allows for example debugging applications by having the +csharp shell attach to running processes. + +## PROFILING + +The Mono runtime includes a profiler API that dynamically loaded +profiler modules and embedders can use to collect performance-related +data about an application. Profiler modules are loaded by passing the +**--profile** command line argument to the Mono runtime. + +Mono ships with a few profiler modules, of which the **log** profiler is +the most feature-rich. It is also the default profiler if the *profiler* +argument is not given, or if **default** is given. It is possible to +write your own profiler modules; see the **Custom profilers** +sub-section. + +### Log profiler + +The log profiler can be used to collect a lot of information about a +program running in the Mono runtime. This data can be used (both while +the process is running and later) to do analyses of the program +behavior, determine resource usage, performance issues or even look for +particular execution patterns. + +This is accomplished by logging the events provided by the Mono runtime +through the profiler API and periodically writing them to a file which +can later be inspected with the **mprof-report**(1) tool. + +More information about how to use the log profiler is available on the +**mono-profilers**(1) page, under the **LOG PROFILER** section, as well +as the **mprof-report**(1) page. + +### Coverage profiler + +The code coverage profiler can instrument a program to help determine +which classes, methods, code paths, etc are actually executed. This is +most useful when running a test suite to determine whether the tests +actually cover the code they're expected to. + +More information about how to use the coverage profiler is available on +the **mono-profilers**(1) page, under the **COVERAGE** PROFILER section. + +### AOT profiler + +The AOT profiler can help improve startup performance by logging which +generic instantiations are used by a program, which the AOT compiler can +then use to compile those instantiations ahead of time so that they +won't have to be JIT compiled at startup. + +More information about how to use the AOT profiler is available on the +**mono-profilers**(1) page, under the **AOT PROFILER** section. + +### Custom profilers + +Custom profiler modules can be loaded in exactly the same way as the +standard modules that ship with Mono. They can also access the same +profiler API to gather all kinds of information about the code being +executed. + +For example, to use a third-party profiler called **custom**, you would +load it like this: + + mono --profile=custom program.exe + +You could also pass arguments to it: + + mono --profile=custom:arg1,arg2=arg3 program.exe + +In the above example, Mono will load the profiler from the shared +library called *libmono-profiler-custom.so* (name varies based on +platform, e.g., *libmono-profiler-custom.dylib* on OS X). This profiler +module must be on your dynamic linker library path (**LD_LIBRARY_PATH** +on most systems, **DYLD_LIBRARY_PATH** on OS X). + +For a sample of how to write your own custom profiler, look at the +*samples/profiler/sample.c* file in the Mono source tree. + +## DEBUGGING AIDS + +To debug managed applications, you can use the **mdb** command, a +command line debugger. + +It is possible to obtain a stack trace of all the active threads in Mono +by sending the QUIT signal to Mono, you can do this from the command +line, like this: + + + kill -QUIT pid + +Where pid is the Process ID of the Mono process you want to examine. The +process will continue running afterwards, but its state is not +guaranteed. + +**Important:** this is a last-resort mechanism for debugging +applications and should not be used to monitor or probe a production +application. The integrity of the runtime after sending this signal is +not guaranteed and the application might crash or terminate at any given +point afterwards. + +The **--debug=casts** option can be used to get more detailed +information for Invalid Cast operations, it will provide information +about the types involved. + +You can use the MONO_LOG_LEVEL and MONO_LOG_MASK environment variables +to get verbose debugging output about the execution of your application +within Mono. + +The *MONO_LOG_LEVEL* environment variable if set, the logging level is +changed to the set value. Possible values are "error", "critical", +"warning", "message", "info", "debug". The default value is "error". +Messages with a logging level greater then or equal to the log level +will be printed to stdout/stderr. + +Use "info" to track the dynamic loading of assemblies. + +Use the *MONO_LOG_MASK* environment variable to limit the extent of the +messages you get: If set, the log mask is changed to the set value. +Possible values are "asm" (assembly loader), "type", "dll" (native +library loader), "gc" (garbage collector), "cfg" (config file loader), +"aot" (precompiler), "security" (e.g. Moonlight CoreCLR support), +"threadpool" (thread pool generic), "io-selector" (async socket +operations), "io-layer" (I/O layer - processes, files, sockets, events, +semaphores, mutexes and handles), "io-layer-process", "io-layer-file", +"io-layer-socket", "io-layer-event", "io-layer-semaphore", +"io-layer-mutex", "io-layer-handle" and "all". The default value is +"all". Changing the mask value allows you to display only messages for a +certain component. You can use multiple masks by comma separating them. +For example to see config file messages and assembly loader messages set +you mask to "asm,cfg". + +The following is a common use to track down problems with P/Invoke: + + + $ MONO_LOG_LEVEL="debug" MONO_LOG_MASK="dll" mono glue.exe + +## DEBUGGING WITH LLDB + +If you are using LLDB, you can use the **mono.py** script to print some +internal data structures with it. To use this, add this to your +**\$HOME/.lldbinit** file: + + command script import $PREFIX/lib/mono/lldb/mono.py + +Where \$PREFIX is the prefix value that you used when you configured +Mono (typically /usr). + +Once this is done, then you can inspect some Mono Runtime data +structures, for example: + + (lldb) p method + + (MonoMethod *) $0 = 0x05026ac0 [mscorlib]System.OutOfMemoryException:.ctor() + +## SERIALIZATION + +Mono's XML serialization engine by default will use a reflection-based +approach to serialize which might be slow for continuous processing (web +service applications). The serialization engine will determine when a +class must use a hand-tuned serializer based on a few parameters and if +needed it will produce a customized C# serializer for your types at +runtime. This customized serializer then gets dynamically loaded into +your application. + +You can control this with the MONO_XMLSERIALIZER_THS environment +variable. + +The possible values are **\`no'** to disable the use of a C# customized +serializer, or an integer that is the minimum number of uses before the +runtime will produce a custom serializer (0 will produce a custom +serializer on the first access, 50 will produce a serializer on the 50th +use). Mono will fallback to an interpreted serializer if the serializer +generation somehow fails. This behavior can be disabled by setting the +option **\`nofallback'** (for example: +MONO_XMLSERIALIZER_THS=0,nofallback). + +## ENVIRONMENT VARIABLES + +**GC_DONT_GC** +Turns off the garbage collection in Mono. This should be only used for +debugging purposes + +**HTTP_PROXY** +(Also **http_proxy**) If set, web requests using the Mono Class Library +will be automatically proxied through the given URL. Not supported on +Windows, Mac OS, iOS or Android. See also **NO_PROXY**. + +**LLVM_COUNT** +When Mono is compiled with LLVM support, this instructs the runtime to +stop using LLVM after the specified number of methods are JITed. This is +a tool used in diagnostics to help isolate problems in the code +generation backend. For example **LLVM_COUNT=10** would only compile 10 +methods with LLVM and then switch to the Mono JIT engine. +**LLVM_COUNT=0** would disable the LLVM engine altogether. + +**MONO_ASPNET_INHIBIT_SETTINGSMAP** +Mono contains a feature which allows modifying settings in the .config +files shipped with Mono by using config section mappers. The mappers and +the mapping rules are defined in the \$prefix/etc/mono/2.0/settings.map +file and, optionally, in the settings.map file found in the top-level +directory of your ASP.NET application. Both files are read by System.Web +on application startup, if they are found at the above locations. If you +don't want the mapping to be performed you can set this variable in your +environment before starting the application and no action will be taken. + +**MONO_ASPNET_WEBCONFIG_CACHESIZE** +Mono has a cache of ConfigSection objects for speeding up +WebConfigurationManager queries. Its default size is 100 items, and when +more items are needed, cache evictions start happening. If evictions are +too frequent this could impose unnecessary overhead, which could be +avoided by using this environment variable to set up a higher cache size +(or to lower memory requirements by decreasing it). + +**MONO_CAIRO_DEBUG_DISPOSE** +If set, causes Mono.Cairo to collect stack traces when objects are +allocated, so that the finalization/Dispose warnings include information +about the instance's origin. + +**MONO_CFG_DIR** +If set, this variable overrides the default system configuration +directory (\$PREFIX/etc). It's used to locate machine.config file. + +**MONO_COM** +Sets the style of COM interop. If the value of this variable is "MS" +Mono will use string marhsalling routines from the liboleaut32 for the +BSTR type library, any other values will use the mono-builtin BSTR +string marshalling. + +**MONO_CONFIG** +If set, this variable overrides the default runtime configuration file +(\$PREFIX/etc/mono/config). The --config command line options overrides +the environment variable. + +**MONO_CPU_ARCH** +Override the automatic cpu detection mechanism. Currently used only on +arm. The format of the value is as follows: + + + + + "armvV [thumb[2]]" + +where V is the architecture number 4, 5, 6, 7 and the options can be +currently be "thumb" or "thumb2". Example: + + + MONO_CPU_ARCH="armv4 thumb" mono ... + +**MONO_ARM_FORCE_SOFT_FLOAT** +When Mono is built with a soft float fallback on ARM and this variable +is set to "1", Mono will always emit soft float code, even if a VFP unit +is detected. + +**MONO_DARWIN_USE_KQUEUE_FSW** +Fall back on the kqueue FileSystemWatcher implementation in Darwin. The +default is the FSEvent implementation. + +**MONO_DARWIN_WATCHER_MAXFDS** +This is a debugging aid used to force limits on the kqueue +FileSystemWatcher implementation in Darwin. There is no limit by +default. + +**MONO_DISABLE_MANAGED_COLLATION** +If this environment variable is \`yes', the runtime uses unmanaged +collation (which actually means no culture-sensitive collation). It +internally disables managed collation functionality invoked via the +members of System.Globalization.CompareInfo class. Collation is enabled +by default. + +**MONO_DISABLE_SHARED_AREA** +Unix only: If set, disable usage of shared memory for exposing +performance counters. This means it will not be possible to both +externally read performance counters from this processes or read those +of external processes. + +**MONO_DNS** +When set, enables the use of a fully managed DNS resolver instead of the +regular libc functions. This resolver performs much better when multiple +queries are run in parallel. + +Note that /etc/nsswitch.conf will be ignored. + +**MONO_EGD_SOCKET** +For platforms that do not otherwise have a way of obtaining random bytes +this can be set to the name of a file system socket on which an egd or +prngd daemon is listening. + +**MONO_ENABLE_AIO** +If set, tells mono to attempt using native asynchronous I/O services. If +not set, a default select/poll implementation is used. Currently epoll +and kqueue are supported. + +**MONO_THREADS_SUSPEND** Selects a mechanism that Mono will use to suspend +threads. May be set to "preemptive", "coop", or "hybrid". Threads may +need to be suspended by the debugger, or using some .NET threading APIs, +and most commonly when the SGen garbage collector needs to stop all +threads during a critical phase of garbage collection. Preemptive mode +is the mode that Mono has used historically, going back to the Boehm +days, where the garbage collector would run at any point and suspend +execution of all threads as required to perform a garbage collection. +The cooperative mode on the other hand requires the cooperation of all +threads to stop at a safe point. This makes for an easier to debug +garbage collector and it improves the stability of the runtime because +threads are not suspended when accessing critical resources. In +scenarios where Mono is embedded in another application, cooperative +suspend requires the embedder code to follow coding guidelines in order +to cooperate with the garbage collector. Cooperative suspend in embedded +Mono is currently experimental. Hybrid mode is a combination of the two +that retains better compatability with scenarios where Mono is embedded +in another application: threads that are running managed code or code +that comprises the Mono runtime will be cooperatively suspended, while +threads running embedder code will be preemptively suspended. Hybrid +suspend is the default on some desktop platforms. + +Alternatively, coop and hybrid mode can be enabled at compile time by +using the --enable-cooperative-suspend or --enable-hybrid-suspend flags, +respectively, when calling configure. The **MONO_THREADS_SUSPEND** +environment variable takes priority over the compiled default. + +**MONO_ENABLE_COOP_SUSPEND** +This environment variable is obsolete, but retained for backward +compatibility. Use **MONO_THREADS_SUSPEND** set to "coop" instead. Note +that if configure flags were provided to enable cooperative or hybrid +suspend, this variable is ignored. + +**MONO_ENV_OPTIONS** +This environment variable allows you to pass command line arguments to a +Mono process through the environment. This is useful for example to +force all of your Mono processes to use LLVM or SGEN without having to +modify any launch scripts. + +**MONO_SDB_ENV_OPTIONS** +Used to pass extra options to the debugger agent in the runtime, as they +were passed using --debugger-agent=. + +**MONO_EVENTLOG_TYPE** +Sets the type of event log provider to use (for +System.Diagnostics.EventLog). + +Possible values are: + +> *local\[:path\]* +> +> Persists event logs and entries to the local file system. +> +> The directory in which to persist the event logs, event sources and +> entries can be specified as part of the value. +> +> If the path is not explicitly set, it defaults to +> "/var/lib/mono/eventlog" on unix and "%APPDATA%no\ventlog" on Windows. +> +> *win32* +> +> **Uses the native win32 API to write events and registers event logs +> and** event sources in the registry. This is only available on +> Windows. +> +> On Unix, the directory permission for individual event log and event +> source directories is set to 777 (with +t bit) allowing everyone to +> read and write event log entries while only allowing entries to be +> deleted by the user(s) that created them. +> +> *null* +> +> Silently discards any events. +> +> The default is "null" on Unix (and versions of Windows before NT), and +> "win32" on Windows NT (and higher). + +**MONO_EXTERNAL_ENCODINGS** +If set, contains a colon-separated list of text encodings to try when +turning externally-generated text (e.g. command-line arguments or +filenames) into Unicode. The encoding names come from the list provided +by iconv, and the special case "default_locale" which refers to the +current locale's default encoding. + +When reading externally-generated text strings UTF-8 is tried first, and +then this list is tried in order with the first successful conversion +ending the search. When writing external text (e.g. new filenames or +arguments to new processes) the first item in this list is used, or +UTF-8 if the environment variable is not set. + +The problem with using MONO_EXTERNAL_ENCODINGS to process your files is +that it results in a problem: although its possible to get the right +file name it is not necessarily possible to open the file. In general if +you have problems with encodings in your filenames you should use the +"convmv" program. + +**MONO_GC_PARAMS** +When using Mono with the SGen garbage collector this variable controls +several parameters of the collector. The variable's value is a comma +separated list of words. + +**max-heap-size=***size* +Sets the maximum size of the heap. The size is specified in bytes and +must be a power of two. The suffixes \`k', \`m' and \`g' can be used to +specify kilo-, mega- and gigabytes, respectively. The limit is the sum +of the nursery, major heap and large object heap. Once the limit is +reached the application will receive OutOfMemoryExceptions when trying +to allocate. Not the full extent of memory set in max-heap-size could be +available to satisfy a single allocation due to internal fragmentation. +By default heap limits is disabled and the GC will try to use all +available memory. + +**nursery-size=***size* +Sets the size of the nursery. The size is specified in bytes and must be +a power of two. The suffixes \`k', \`m' and \`g' can be used to specify +kilo-, mega- and gigabytes, respectively. The nursery is the first +generation (of two). A larger nursery will usually speed up the program +but will obviously use more memory. The default nursery size 4 MB. + +**major=***collector* +Specifies which major collector to use. Options are \`marksweep' for the +Mark&Sweep collector, \`marksweep-conc' for concurrent Mark&Sweep and +\`marksweep-conc-par' for parallel and concurrent Mark&Sweep. The +concurrent Mark&Sweep collector is the default. + +**mode=balanced\|throughput\|pause**\[:*max-pause*\] +Specifies what should be the garbage collector's target. The +\`throughput' mode aims to reduce time spent in the garbage collector +and improve application speed, the \`pause' mode aims to keep pause +times to a minimum and it receives the argument *max-pause* which +specifies the maximum pause time in milliseconds that is acceptable and +the \`balanced' mode which is a general purpose optimal mode. + +**soft-heap-limit=***size* +Once the heap size gets larger than this size, ignore what the default +major collection trigger metric says and only allow four nursery size's +of major heap growth between major collections. + +**evacuation-threshold=***threshold* +Sets the evacuation threshold in percent. This option is only available +on the Mark&Sweep major collectors. The value must be an integer in the +range 0 to 100. The default is 66. If the sweep phase of the collection +finds that the occupancy of a specific heap block type is less than this +percentage, it will do a copying collection for that block type in the +next major collection, thereby restoring occupancy to close to 100 +percent. A value of 0 turns evacuation off. + +**(no-)lazy-sweep** +Enables or disables lazy sweep for the Mark&Sweep collector. If enabled, +the sweeping of individual major heap blocks is done piecemeal whenever +the need arises, typically during nursery collections. Lazy sweeping is +enabled by default. + +**(no-)concurrent-sweep** +Enables or disables concurrent sweep for the Mark&Sweep collector. If +enabled, the iteration of all major blocks to determine which ones can +be freed and which ones have to be kept and swept, is done concurrently +with the running program. Concurrent sweeping is enabled by default. + +**stack-mark=***mark-mode* +Specifies how application threads should be scanned. Options are +\`precise\` and \`conservative\`. Precise marking allow the collector to +know what values on stack are references and what are not. Conservative +marking threats all values as potentially references and leave them +untouched. Precise marking reduces floating garbage and can speed up +nursery collection and allocation rate, it has the downside of requiring +a significant extra memory per compiled method. The right option, +unfortunately, requires experimentation. + +**save-target-ratio=***ratio* +Specifies the target save ratio for the major collector. The collector +lets a given amount of memory to be promoted from the nursery due to +minor collections before it triggers a major collection. This amount is +based on how much memory it expects to free. It is represented as a +ratio of the size of the heap after a major collection. Valid values are +between 0.1 and 2.0. The default is 0.5. Smaller values will keep the +major heap size smaller but will trigger more major collections. +Likewise, bigger values will use more memory and result in less frequent +major collections. This option is EXPERIMENTAL, so it might disappear in +later versions of mono. + +**default-allowance-ratio=***ratio* +Specifies the default allocation allowance when the calculated size is +too small. The allocation allowance is how much memory the collector let +be promoted before triggered a major collection. It is a ratio of the +nursery size. Valid values are between 1.0 and 10.0. The default is 4.0. +Smaller values lead to smaller heaps and more frequent major +collections. Likewise, bigger values will allow the heap to grow faster +but use more memory when it reaches a stable size. This option is +EXPERIMENTAL, so it might disappear in later versions of mono. + +**minor=***minor-collector* +Specifies which minor collector to use. Options are \`simple' which +promotes all objects from the nursery directly to the old generation, +\`simple-par' which has same promotion behavior as \`simple' but using +multiple workers and \`split' which lets objects stay longer on the +nursery before promoting. + +**alloc-ratio=***ratio* +Specifies the ratio of memory from the nursery to be use by the alloc +space. This only can only be used with the split minor collector. Valid +values are integers between 1 and 100. Default is 60. + +**promotion-age=***age* +Specifies the required age of an object must reach inside the nursery +before been promoted to the old generation. This only can only be used +with the split minor collector. Valid values are integers between 1 +and 14. Default is 2. + +**(no-)cementing** +Enables or disables cementing. This can dramatically shorten nursery +collection times on some benchmarks where pinned objects are referred to +from the major heap. + +**allow-synchronous-major** +This forbids the major collector from performing synchronous major +collections. The major collector might want to do a synchronous +collection due to excessive fragmentation. Disabling this might trigger +OutOfMemory error in situations that would otherwise not happen. + +**MONO_GC_DEBUG** +When using Mono with the SGen garbage collector this environment +variable can be used to turn on various debugging features of the +collector. The value of this variable is a comma separated list of +words. Do not use these options in production. + +*number* +Sets the debug level to the specified number. + +**print-allowance** +After each major collection prints memory consumption for before and +after the collection and the allowance for the minor collector, i.e. how +much the heap is allowed to grow from minor collections before the next +major collection is triggered. + +**print-pinning** +Gathers statistics on the classes whose objects are pinned in the +nursery and for which global remset entries are added. Prints those +statistics when shutting down. + +**collect-before-allocs** +**check-remset-consistency** +This performs a remset consistency check at various opportunities, and +also clears the nursery at collection time, instead of the default, when +buffers are allocated (clear-at-gc). The consistency check ensures that +there are no major to minor references that are not on the remembered +sets. + +**mod-union-consistency-check** +Checks that the mod-union cardtable is consistent before each finishing +major collection pause. This check is only applicable to concurrent +major collectors. + +**check-mark-bits** +Checks that mark bits in the major heap are consistent at the end of +each major collection. Consistent mark bits mean that if an object is +marked, all objects that it had references to must also be marked. + +**check-nursery-untag** +After garbage collections, check whether all vtable pointers are no +longer tagged. + +**xdomain-checks** +Performs a check to make sure that no references are left to an unloaded +AppDomain. + +**clear-at-tlab-creation** +Clears the nursery incrementally when the thread local allocation +buffers (TLAB) are created. The default setting clears the whole nursery +at GC time. + +**debug-clear-at-tlab-creation** +Clears the nursery incrementally when the thread local allocation +buffers (TLAB) are created, but at GC time fills it with the byte +\`0xff\`, which should result in a crash more quickly if +\`clear-at-tlab-creation\` doesn't work properly. + +**clear-at-gc** +This clears the nursery at GC time instead of doing it when the thread +local allocation buffer (TLAB) is created. The default is to clear the +nursery at TLAB creation time. + +**disable-minor** +Don't do minor collections. If the nursery is full, a major collection +is triggered instead, unless it, too, is disabled. + +**disable-major** +Don't do major collections. + +**conservative-stack-mark** +Forces the GC to scan the stack conservatively, even if precise scanning +is available. + +**no-managed-allocator** +Disables the managed allocator. + +**managed-allocator** +Enables the managed allocator. + +**check-scan-starts** +If set, does a plausibility check on the scan_starts before and after +each collection + +**verify-nursery-at-minor-gc** +If set, does a complete object walk of the nursery at the start of each +minor collection. + +**dump-nursery-at-minor-gc** +If set, dumps the contents of the nursery at the start of each minor +collection. Requires verify-nursery-at-minor-gc to be set. + +**heap-dump=***file* +Dumps the heap contents to the specified file. To visualize the +information, use the mono-heapviz tool. + +**binary-protocol=***file* +Outputs the debugging output to the specified file. For this to work, +Mono needs to be compiled with the BINARY_PROTOCOL define on sgen-gc.c. +You can then use this command to explore the output + + sgen-grep-binprot 0x1234 0x5678 < file + +**nursery-canaries** +If set, objects allocated in the nursery are suffixed with a canary +(guard) word, which is checked on each minor collection. Can be used to +detect/debug heap corruption issues. This disables the usage of the +managed allocator, because allocation from full aot code is inconsistent +with this option. If the application is guaranteed not to use aot code, +the managed allocator can be enabled back with managed-allocator option. + +**do-not-finalize(=***classes***)** +If enabled, finalizers will not be run. Everything else will be +unaffected: finalizable objects will still be put into the finalization +queue where they survive until they're scheduled to finalize. Once +they're not in the queue anymore they will be collected regularly. If a +list of comma-separated class names is given, only objects from those +classes will not be finalized. + +**log-finalizers** +Log verbosely around the finalization process to aid debugging. + +**MONO_GAC_PREFIX** +Provides a prefix the runtime uses to look for Global Assembly Caches. +Directories are separated by the platform path separator (colons on +unix). MONO_GAC_PREFIX should point to the top directory of a prefixed +install. Or to the directory provided in the gacutil /gacdir command. +Example: **/home/username/.mono:/usr/local/mono/** + +**MONO_IOMAP** +(deprecated) Enabled some filename rewriting support to assist +badly-written applications that hard-code Windows paths. It no longer +works as of Mono 6.0. + +**MONO_LLVM** +When Mono is using the LLVM code generation backend you can use this +environment variable to pass code generation options to the LLVM +compiler. + +**MONO_MANAGED_WATCHER** +If set to "disabled", System.IO.FileSystemWatcher will use a file +watcher implementation which silently ignores all the watching requests. +If set to any other value, System.IO.FileSystemWatcher will use the +default managed implementation (slow). If unset, mono will try to use +inotify, FAM, Gamin, kevent under Unix systems and native API calls on +Windows, falling back to the managed implementation on error. + +**MONO_MESSAGING_PROVIDER** +Mono supports a plugin model for its implementation of System.Messaging +making it possible to support a variety of messaging implementations +(e.g. AMQP, ActiveMQ). To specify which messaging implementation is to +be used the evironement variable needs to be set to the full class name +for the provider. E.g. to use the RabbitMQ based AMQP implementation the +variable should be set to: + + Mono.Messaging.RabbitMQ.RabbitMQMessagingProvider,Mono.Messaging.RabbitMQ + MONO_NO_SMP + If set causes the mono process to be bound to a single processor. This may be + useful when debugging or working around race conditions. + MONO_NO_TLS + Disable inlining of thread local accesses. Try setting this if you get a segfault + early on in the execution of mono. + MONO_PATH + Provides a search path to the runtime where to look for library + files. This is a tool convenient for debugging applications, but + should not be used by deployed applications as it breaks the assembly + loader in subtle ways. + Directories are separated by the platform path separator (colons on unix). Example: + /home/username/lib:/usr/local/mono/lib + Relative paths are resolved based on the launch-time current directory. + Alternative solutions to MONO_PATH include: installing libraries into + the Global Assembly Cache (see gacutil(1)) or having the dependent + libraries side-by-side with the main executable. + For a complete description of recommended practices for application + deployment, see + http://www.mono-project.com/docs/getting-started/application-deployment/ + MONO_SHARED_DIR + If set its the directory where the ".wapi" handle state is stored. + This is the directory where the Windows I/O Emulation layer stores its + shared state data (files, events, mutexes, pipes). By default Mono + will store the ".wapi" directory in the users's home directory. + MONO_SHARED_HOSTNAME + Uses the string value of this variable as a replacement for the host name when + creating file names in the ".wapi" directory. This helps if the host name of + your machine is likely to be changed when a mono application is running or if + you have a .wapi directory shared among several different computers. + Mono typically uses the hostname to create the files that are used to + share state across multiple Mono processes. This is done to support + home directories that might be shared over the network. + MONO_STRICT_IO_EMULATION + If set, extra checks are made during IO operations. Currently, this + includes only advisory locks around file writes. + MONO_TLS_PROVIDER + This environment variable controls which TLS/SSL provider Mono will + use. The options are usually determined by the operating system where + Mono was compiled and the configuration options that were used for + it. + default + Uses the default TLS stack that the Mono runtime was configured with. + Usually this is configured to use Apple's SSL stack on Apple + platforms, and Boring SSL on other platforms. + apple + Forces the use of the Apple SSL stack, only works on Apple platforms. + btls + Forces the use of the BoringSSL stack. See + https://opensource.google.com/projects/boringssl for more information + about this stack. + legacy + This is the old Mono stack, which only supports SSL and TLS up to + version 1.0. It is deprecated and will be removed in the future. + MONO_TLS_SESSION_CACHE_TIMEOUT + The time, in seconds, that the SSL/TLS session cache will keep it's entry to + avoid a new negotiation between the client and a server. Negotiation are very + CPU intensive so an application-specific custom value may prove useful for + small embedded systems. + The default is 180 seconds. + MONO_THREADS_PER_CPU + The minimum number of threads in the general threadpool will be + MONO_THREADS_PER_CPU * number of CPUs. The default value for this + variable is 1. + MONO_XMLSERIALIZER_THS + Controls the threshold for the XmlSerializer to produce a custom + serializer for a given class instead of using the Reflection-based + interpreter. The possible values are `no' to disable the use of a + custom serializer or a number to indicate when the XmlSerializer + should start serializing. The default value is 50, which means that + the a custom serializer will be produced on the 50th use. + MONO_X509_REVOCATION_MODE + Sets the revocation mode used when validating a X509 certificate chain (https, + ftps, smtps...). The default is 'nocheck', which performs no revocation check + at all. The other possible values are 'offline', which performs CRL check (not + implemented yet) and 'online' which uses OCSP and CRL to verify the revocation + status (not implemented yet). + NO_PROXY + (Also no_proxy) If both HTTP_PROXY and NO_PROXY are + set, NO_PROXY will be treated as a comma-separated list of "bypass" domains + which will not be sent through the proxy. Domains in NO_PROXY may contain + wildcards, as in "*.mono-project.com" or "build????.local". Not supported on + Windows, Mac OS, iOS or Android. + +## ENVIRONMENT VARIABLES FOR DEBUGGING + +**MONO_ASPNET_NODELETE** +If set to any value, temporary source files generated by ASP.NET support +classes will not be removed. They will be kept in the user's temporary +directory. + +**MONO_DEBUG** +If set, enables some features of the runtime useful for debugging. This +variable should contain a comma separated list of debugging options. +Currently, the following options are supported: + +**align-small-structs** +Enables small structs alignment to 4/8 bytes. + +**arm-use-fallback-tls** +When this option is set on ARM, a fallback thread local store will be +used instead of the default fast thread local storage primitives. + +**break-on-unverified** +If this variable is set, when the Mono VM runs into a verification +problem, instead of throwing an exception it will break into the +debugger. This is useful when debugging verifier problems + +**casts** +This option can be used to get more detailed information from +InvalidCast exceptions, it will provide information about the types +involved. + +**check-pinvoke-callconv** +This option causes the runtime to check for calling convention +mismatches when using pinvoke, i.e. mixing cdecl/stdcall. It only works +on windows. If a mismatch is detected, an ExecutionEngineException is +thrown. + +**collect-pagefault-stats** +Collects information about pagefaults. This is used internally to track +the number of page faults produced to load metadata. To display this +information you must use this option with "--stats" command line option. + +**debug-domain-unload** +When this option is set, the runtime will invalidate the domain memory +pool instead of destroying it. + +**disable_omit_fp** +Disables a compiler optimization where the frame pointer is omitted from +the stack. This optimization can interact badly with debuggers. + +**dont-free-domains** +This is an Optimization for multi-AppDomain applications (most commonly +ASP.NET applications). Due to internal limitations Mono, Mono by default +does not use typed allocations on multi-appDomain applications as they +could leak memory when a domain is unloaded. + +Although this is a fine default, for applications that use more than on +AppDomain heavily (for example, ASP.NET applications) it is worth +trading off the small leaks for the increased performance (additionally, +since ASP.NET applications are not likely going to unload the +application domains on production systems, it is worth using this +feature). + +**dyn-runtime-invoke** +Instructs the runtime to try to use a generic runtime-invoke wrapper +instead of creating one invoke wrapper. + +**explicit-null-checks** +Makes the JIT generate an explicit NULL check on variable dereferences +instead of depending on the operating system to raise a SIGSEGV or +another form of trap event when an invalid memory location is accessed. + +**gdb** +Equivalent to setting the **MONO_XDEBUG** variable, this emits symbols +into a shared library as the code is JITed that can be loaded into GDB +to inspect symbols. + +**gen-seq-points** +Automatically generates sequence points where the IL stack is empty. +These are places where the debugger can set a breakpoint. + +**llvm-disable-implicit-null-checks** +Makes the LLVM backend use explicit NULL checks on variable dereferences +instead of depending on operating system support for signals or traps +when an invalid memory location is accessed. Unconditionally enabled by +explicit-null-checks. + +**no-compact-seq-points** +Unless the option is used, the runtime generates sequence points data +that maps native offsets to IL offsets. Sequence point data is used to +display IL offset in stacktraces. Stacktraces with IL offsets can be +symbolicated using mono-symbolicate tool. + +**handle-sigint** +Captures the interrupt signal (Control-C) and displays a stack trace +when pressed. Useful to find out where the program is executing at a +given point. This only displays the stack trace of a single thread. + +**init-stacks** +Instructs the runtime to initialize the stack with some known values +(0x2a on x86-64) at the start of a method to assist in debuggin the JIT +engine. + +**keep-delegates** +This option will leak delegate trampolines that are no longer referenced +as to present the user with more information about a delegate misuse. +Basically a delegate instance might be created, passed to unmanaged +code, and no references kept in managed code, which will garbage collect +the code. With this option it is possible to track down the source of +the problems. + +**no-gdb-backtrace** +This option will disable the GDB backtrace emitted by the runtime after +a SIGSEGV or SIGABRT in unmanaged code. + +**partial-sharing** +When this option is set, the runtime can share generated code between +generic types effectively reducing the amount of code generated. + +**reverse-pinvoke-exceptions** +This option will cause mono to abort with a descriptive message when +during stack unwinding after an exception it reaches a native stack +frame. This happens when a managed delegate is passed to native code, +and the managed delegate throws an exception. Mono will normally try to +unwind the stack to the first (managed) exception handler, and it will +skip any native stack frames in the process. This leads to undefined +behaviour (since mono doesn't know how to process native frames), leaks, +and possibly crashes too. + +**single-imm-size** +This guarantees that each time managed code is compiled the same +instructions and registers are used, regardless of the size of used +values. + +**soft-breakpoints** +This option allows using single-steps and breakpoints in hardware where +we cannot do it with signals. + +**suspend-on-native-crash** +This option will suspend the program when a native crash occurs +(SIGSEGV, SIGILL, ...). This is useful for debugging crashes which do +not happen under gdb, since a live process contains more information +than a core file. + +**suspend-on-sigsegv** +Same as **suspend-on-native-crash**. + +**suspend-on-exception** +This option will suspend the program when an exception occurs. + +**suspend-on-unhandled** +This option will suspend the program when an unhandled exception occurs. + +**thread-dump-dir=DIR** +Use DIR for storage thread dumps created by SIGQUIT. + +**weak-memory-model** +Don't enforce the CLR memory model on platforms with weak memory models. +This can introduce random crashes in some rare cases, for multithreaded +environments. This can be used for a performance boost on applications +that are single threaded. + +**verbose-gdb** +Make gdb output on native crashes more verbose. + +**MONO_LOG_LEVEL** +The logging level, possible values are \`error', \`critical', +\`warning', \`message', \`info' and \`debug'. See the DEBUGGING section +for more details. + +**MONO_LOG_MASK** +Controls the domain of the Mono runtime that logging will apply to. If +set, the log mask is changed to the set value. Possible values are "asm" +(assembly loader), "type", "dll" (native library loader), "gc" (garbage +collector), "cfg" (config file loader), "aot" (precompiler), "security" +(e.g. Moonlight CoreCLR support) and "all". The default value is "all". +Changing the mask value allows you to display only messages for a +certain component. You can use multiple masks by comma separating them. +For example to see config file messages and assembly loader messages set +you mask to "asm,cfg". + +**MONO_LOG_DEST** +Controls where trace log messages are written. If not set then the +messages go to stdout. If set, the string either specifies a path to a +file that will have messages appended to it, or the string "syslog" in +which case the messages will be written to the system log. Under +Windows, this is simulated by writing to a file called "mono.log". +**MONO_LOG_HEADER** Controls whether trace log messages not directed to +syslog have the id, timestamp, and pid as the prefix to the log message. +To enable a header this environment variable need just be non-null. + +**MONO_TRACE** +Used for runtime tracing of method calls. The format of the comma +separated trace options is: + + + + + [-]M:method name + [-]N:namespace + [-]T:class name + [-]all + [-]program + disabled Trace output off upon start. + +You can toggle trace output on/off sending a SIGUSR2 signal to the +program. + +**MONO_TRACE_LISTENER** +If set, enables the System.Diagnostics.DefaultTraceListener, which will +print the output of the System.Diagnostics Trace and Debug classes. It +can be set to a filename, and to Console.Out or Console.Error to display +output to standard output or standard error, respectively. If it's set +to Console.Out or Console.Error you can append an optional prefix that +will be used when writing messages like this: +Console.Error:MyProgramName. See the +System.Diagnostics.DefaultTraceListener documentation for more +information. + +**MONO_WCF_TRACE** +This eases WCF diagnostics functionality by simply outputs all log +messages from WCF engine to "stdout", "stderr" or any file passed to +this environment variable. The log format is the same as usual +diagnostic output. + +**MONO_XEXCEPTIONS** +This throws an exception when a X11 error is encountered; by default a +message is displayed but execution continues + +**MONO_XMLSERIALIZER_DEBUG** +Set this value to 1 to prevent the serializer from removing the +temporary files that are created for fast serialization; This might be +useful when debugging. + +**MONO_XSYNC** +This is used in the System.Windows.Forms implementation when running +with the X11 backend. This is used to debug problems in Windows.Forms as +it forces all of the commands send to X11 server to be done +synchronously. The default mode of operation is asynchronous which makes +it hard to isolate the root of certain problems. + +**MONO_XDEBUG** +When the the MONO_XDEBUG env var is set, debugging info for JITted code +is emitted into a shared library, loadable into gdb. This enables, for +example, to see managed frame names on gdb backtraces. + +**MONO_VERBOSE_METHOD** +Enables the maximum JIT verbosity for the specified method. This is very +helpfull to diagnose a miscompilation problems of a specific method. +This can be a semicolon-separated list of method names to match. If the +name is simple, this applies to any method with that name, otherwise you +can use a mono method description (see the section METHOD DESCRIPTIONS). + +**MONO_JIT_DUMP_METHOD** +Enables sending of the JITs intermediate representation for a specified +method to the IdealGraphVisualizer tool. + +**MONO_VERBOSE_HWCAP** +If set, makes the JIT output information about detected CPU features +(such as SSE, CMOV, FCMOV, etc) to stdout. + +**MONO_CONSERVATIVE_HWCAP** +If set, the JIT will not perform any hardware capability detection. This +may be useful to pinpoint the cause of JIT issues. This is the default +when Mono is built as an AOT cross compiler, so that the generated code +will run on most hardware. + +**MONO_PROFILE** +Equivalent to **--profile** argument. + +## VALGRIND + +If you want to use Valgrind, you will find the file \`mono.supp' useful, +it contains the suppressions for the GC which trigger incorrect +warnings. Use it like this: + + valgrind --suppressions=mono.supp mono ... + +## DTRACE + +On some platforms, Mono can expose a set of DTrace probes (also known as +user-land statically defined, USDT Probes). + +They are defined in the file \`mono.d'. +**ves-init-begin, ves-init-end** + +Begin and end of runtime initialization. + +**method-compile-begin, method-compile-end** + +Begin and end of method compilation. The probe arguments are class name, +method name and signature, and in case of method-compile-end success or +failure of compilation. + +**gc-begin, gc-end** + +Begin and end of Garbage Collection. + +To verify the availability of the probes, run: + dtrace -P mono'$target' -l -c mono + +## PERMISSIONS + +Mono's Ping implementation for detecting network reachability can create +the ICMP packets itself without requiring the system ping command to do +the work. If you want to enable this on Linux for non-root users, you +need to give the Mono binary special permissions. + +As root, run this command: + + # setcap cap_net_raw=+ep /usr/bin/mono + +## FILES + +On Unix assemblies are loaded from the installation lib directory. If +you set \`prefix' to /usr, the assemblies will be located in /usr/lib. +On Windows, the assemblies are loaded from the directory where mono and +mint live. + +**~/.mono/aot-cache** + +The directory for the ahead-of-time compiler demand creation assemblies +are located. + +**/etc/mono/config, ~/.mono/config** + +Mono runtime configuration file. See the mono-config(5) manual page for +more information. + +**~/.config/.mono/certs, /usr/share/.mono/certs** + +Contains Mono certificate stores for users / machine. See the certmgr(1) +manual page for more information on managing certificate stores and the +mozroots(1) page for information on how to import the Mozilla root +certificates into the Mono certificate store. + +**~/.mono/assemblies/ASSEMBLY/ASSEMBLY.config** + +Files in this directory allow a user to customize the configuration for +a given system assembly, the format is the one described in the +mono-config(5) page. + +**~/.config/.mono/keypairs, /usr/share/.mono/keypairs** + +Contains Mono cryptographic keypairs for users / machine. They can be +accessed by using a CspParameters object with DSACryptoServiceProvider +and RSACryptoServiceProvider classes. + +**~/.config/.isolatedstorage, ~/.local/share/.isolatedstorage, /usr/share/.isolatedstorage** + +Contains Mono isolated storage for non-roaming users, roaming users and +local machine. Isolated storage can be accessed using the classes from +the System.IO.IsolatedStorage namespace. + +**\.config** + +Configuration information for individual assemblies is loaded by the +runtime from side-by-side files with the .config files, see the +http://www.mono-project.com/Config for more information. + +**Web.config, web.config** + +ASP.NET applications are configured through these files, the +configuration is done on a per-directory basis. For more information on +this subject see the http://www.mono-project.com/Config_system.web page. + +## MAILING LISTS + +Mailing lists are listed at the +http://www.mono-project.com/community/help/mailing-lists/ + +## WEB SITE + +http://www.mono-project.com + +## SEE ALSO + +**certmgr**(1), **cert-sync**(1), **csharp**(1), **gacutil**(1), +**mcs**(1), **monodis**(1), **mono-config**(5), **mono-profilers**(1), +**mprof-report**(1), **pdb2mdb**(1), **xsp**(1), **mod_mono**(8) + +For more information on AOT: +http://www.mono-project.com/docs/advanced/aot/ + +For ASP.NET-related documentation, see the xsp(1) manual page diff --git a/docs/project/list-of-diagnostics.md b/docs/project/list-of-diagnostics.md index 9ad0f02f5f88..41d5a78f3f17 100644 --- a/docs/project/list-of-diagnostics.md +++ b/docs/project/list-of-diagnostics.md @@ -109,6 +109,7 @@ The PR that reveals the implementation of the `true` and set one of the attributes in the following section. + +### Disabling runtime tests (src/tests) with issues.targets + +Out-of-process tests are disabled by adding the test to the appropriate place, under the appropriate configuration condition, +in the [issues.targets](../../../src/tests/issues.targets) file. Additionally, tests that are the only `[Fact]`-attributed method in their assembly may be disabled through issues.targets. All temporarily disabled tests must have a link to a GitHub issue in the `` element. Disabling a test here can be conditioned on processor architecture, runtime, and operating system. @@ -64,15 +82,8 @@ Note that these properties can be conditional, e.g.: More information about writing/adding tests to src/tests can be found [here](../testing/coreclr/test-configuration.md). -## Disabling runtime tests (src/tests) with xunit attributes - -When this document was written, the src/tests tree was in the process of being converted to a new -execution model (see [dotnet/runtime#54512](https://github.com/dotnet/runtime/issues/54512)). This model annotates tests with xunit-style -`[Fact]` attributes. For tests which have been converted to this form, all the xunit attributes related to test disabling -described in the "src/libraries" section below are also applicable. - ## Disabling libraries tests (src/libraries) Information on disabling libraries tests is found [here](../testing/libraries/filtering-tests.md). -In particular, look at `ActiveIssueAttribute`, `SkipOnCoreClrAttribute`, and `SkipOnMonoAttribute`. \ No newline at end of file +In particular, look at `ActiveIssueAttribute`, `SkipOnCoreClrAttribute`, and `SkipOnMonoAttribute`. diff --git a/docs/workflow/testing/coreclr/testing.md b/docs/workflow/testing/coreclr/testing.md index a09ef364ae53..46de9e022311 100644 --- a/docs/workflow/testing/coreclr/testing.md +++ b/docs/workflow/testing/coreclr/testing.md @@ -7,11 +7,13 @@ * [Building an Individual Test](#building-an-individual-test) * [Building a Test Directory](#building-a-test-directory) * [Building a Test Subtree](#building-a-test-subtree) + * [Test Executors](#test-executors) + * [The Standalone Test Runner and Build Time Test Filtering](#the-standalone-test-runner-and-build-time-test-filtering) + * [Building all tests with the Standalone Runner](#building-all-tests-with-the-standalone-runner) * [Building C++/CLI Native Test Components Against the Live Ref Assemblies](#building-ccli-native-test-components-against-the-live-ref-assemblies) * [Test Priorities](#test-priorities) * [Running the Tests](#running-the-tests) * [Running Individual Tests](#running-individual-tests) - * [Tests Without a Main Method](#tests-without-a-main-method) * [PAL Tests (macOS and Linux only)](#pal-tests-macos-and-linux-only) * [Building PAL Tests](#building-pal-tests) * [Running PAL Tests](#running-pal-tests) @@ -62,7 +64,7 @@ This example assumes you built CoreCLR on _Debug_ mode and the Libraries on _Rel The following subsections will explain how to segment the test suite according to your needs. There are three main scopes of building tests: -* Individual Test +* Individual Test Runner * Full Directory * Entire Subtree @@ -83,19 +85,19 @@ To build an individual test, you have to pass the `-test` flag along with the pa On Windows: ```cmd -.\src\tests\build.cmd test JIT\Intrinsics\MathRoundDouble_ro.csproj test JIT\Intrinsics\MathFloorDouble_ro.csproj +.\src\tests\build.cmd test JIT\Methodical\Methodical_d1.csproj test JIT\JIT_ro.csproj ``` On macOS and Linux: ```bash -./src/tests/build.sh -test:JIT/Intrinsics/MathRoundDouble_ro.csproj -test:JIT/Intrinsics/MathFloorDouble_ro.csproj +./src/tests/build.sh -test:JIT/Methodical/Methodical_d1.csproj -test:JIT/JIT_ro.csproj ``` Alternatively, you can call _build_ directly using the `dotnet.cmd/dotnet.sh` script at the root of the repo and pass all arguments directly yourself: ```bash -./dotnet.sh build -c src/tests/path/to/test/csproj +./dotnet.sh build -c src/tests/path/to/test.csproj ``` ### Building a Test Directory @@ -105,13 +107,13 @@ To build all the tests contained in an individual directory, you have to pass th On Windows: ```cmd -.\src\tests\build.cmd dir JIT\Methodical\Arrays\lcs dir JIT\Methodical\cctor\misc\Desktop +.\src\tests\build.cmd dir JIT dir Loader ``` On macOS and Linux: ```bash -./src/tests/build.sh -dir:JIT/Methodical/Arrays/lcs -dir:JIT/Methodical/cctor/misc/Desktop +./src/tests/build.sh -dir:JIT -dir:Loader ``` ### Building a Test Subtree @@ -130,6 +132,24 @@ On macOS and Linux: ./src/tests/build.sh -tree:baseservices/exceptions -tree:JIT/Methodical ``` +### Test Executors + +We have multiple different mechanisms of executing tests. + +Our test entrypoints are generally what we call "merged test runners", as they provide an executable runner project for multiple different test assemblies. These projects can be identified by the `` line in their .csproj file. These projects provide a simple experience for running tests. When executing a merged runner project, it will run each test sequentially and record if it passes or fails in an xunit results file. The merged test runner support runtime test filtering. If specified, the first argument to the test runner is treated as a `dotnet test --filter` argument following the xUnit rules in their documentation. Today, the runner only supports the simple form, a substring of a test's fully-qualified name, in the format `Namespace.ContainingTypeName.TypeName.Method`. If support for further filtering options is desired, please open an issue requesting it. + +Some tests need to be run in their own process as they interact with global process state, they have a custom test entrypoint, or they interact poorly with other tests in the same process. These tests are generally marked with `true` in their project files. These tests can be run directly, but they can also be invoked through their corresponding merged test runner. The merged test runner will invoke them as a subprocess in the same manner as if they were run individually. + +#### The Standalone Test Runner and Build Time Test Filtering + +Sometimes you may want to run a test with the least amount of code before actually executing the test. In addition to the merged test runner, we have another runner mode known as the "Standalone" runner. This runner is used by default in tests that require process isolation. This runner consists of a simple `try-catch` around executing each test sequentially, with no test results file or runtime test filtering. + +To filter tests on a merged test runner built as standalone, you can set the `TestFilter` property, like so: `./dotnet.sh build -c Checked src/tests/path/to/test.csproj -p:TestFilter=SubstringOfFullyQualifiedTestName`. This mechanism supports the same filtering as the runtime test filtering. Using this mechanism will allow you to skip individual test cases at build time instead of at runtime. + +#### Building all tests with the Standalone Runner + +If you wish to use the Standalone runner described in the [previous section](#the-standalone-test-runner-and-build-time-test-filtering), you can set the `BuildAllTestsAsStandalone` environment variable to `true` when invoking the `./src/tests/build.sh` or `./src/tests/build.cmd` scripts (for example, `export BuildAllTestsAsStandalone=true` or `set BuildAllTestsAsStandalone=true`). This will build all tests that are not directly in a merged test runner's project as separate executable tests and build only the tests that are compiled into the runner directly. If a runner has no tests that are built directly into the runner, then it will be excluded. + ### Building C++/CLI Native Test Components Against the Live Ref Assemblies By default, the _C++/CLI_ native test components build against the _ref pack_ from the SDK specified in the `global.json` file in the root of the repository. To build these components against the _ref assemblies_ produced in the build, pass the `-cmakeargs -DCPP_CLI_LIVE_REF_ASSEMBLIES=1` parameters to the test build. For example: @@ -233,9 +253,7 @@ cd path/to/JIT/Intrinsics/MathRoundDouble_ro ./MathRoundDouble_ro.sh -coreroot=/artifacts/tests/coreclr/../Tests/Core_Root ``` -#### Tests Without a Main Method - -Guide on how to run tests without a `Main()` Method coming soon! +If you want to run an individual test from a test runner, use the filtering capabilities described in the [Test Executors section](#test-executors). ### PAL Tests (macOS and Linux only) diff --git a/docs/workflow/testing/testing-managed-tools.md b/docs/workflow/testing/testing-managed-tools.md new file mode 100644 index 000000000000..6e2fddbdbd77 --- /dev/null +++ b/docs/workflow/testing/testing-managed-tools.md @@ -0,0 +1,45 @@ +# Testing managed tools + +There are managed unit and functional tests for a number of tools including the +compiler for NativeAOT (`ILCompiler`), and the trimmer (`illink`). + +## Adding new testsuites + +To add a new test suite, create a new `.csproj` with a name that ends in `Tests`, such as: +`MyTool.Tests.csproj`. The property `IsTestProject` will be set by the `Directories.Build.props` in +the repository root. The property will, in turn, add references to the xunit package and the +apropriate test runner. + +Now add a `ProjectToBuild` item in `eng/Substes.props` to one of the existing subsets, such as +`clr.toolstests`, or a new subset. + +## Adding new testsuites to CI + +To run the tests in CI, add a new pipeline or add to an exsiting pipeline such as `CLR_Tools_Tests` +in `eng/pipelines/runtime.yml`. Update the trigger condition, perhaps by adding a new set of paths +to `eng/pipelines/common/evaluate-default-paths.yml` in order to run the tests when the tool source +or the test sources change. + +## Running tests locally + +Build and run the tests locally either with + +```console +./build.[sh|cmd] -s clr.toolstests -c [Release|Debug] -build -test +``` + +or + +```console +./dotnet.[sh|cmd] test .../MyTool.Tests.csproj -c [Release|Debug] +``` + +The `dotnet-test` xunit filter mechanisms work to run a single test or a subset of the tests + +```console +./dotnet.[sh|cmd] test .../MyTool.Tests.csproj -c [Release|Debug] --filter "FullyQualifiedName~MyTest" +``` + +The above command runs all tests whose fully-qualified name contains the substring `MyTest`. See +[dotnet test - Run selective unit tests](https://learn.microsoft.com/en-us/dotnet/core/testing/selective-unit-tests?pivots=mstest#syntax) +for the full syntax. diff --git a/docs/workflow/trimming/feature-switches.md b/docs/workflow/trimming/feature-switches.md index 2c25a36230d4..46e7452fad2c 100644 --- a/docs/workflow/trimming/feature-switches.md +++ b/docs/workflow/trimming/feature-switches.md @@ -35,6 +35,9 @@ configurations but their defaults might vary as any SDK can set the defaults dif | JsonSerializerIsReflectionEnabledByDefault | System.Text.Json.JsonSerializer.IsReflectionEnabledByDefault | When set to false, disables using reflection as the default contract resolver in System.Text.Json | | EnableGeneratedComInterfaceComImportInterop | System.Runtime.InteropServices.Marshalling.EnableGeneratedComInterfaceComImportInterop | When set to true, enables casting source-generated COM object wrappers to built-in COM-based COM interfaces. | | _UseManagedNtlm | System.Net.Security.UseManagedNtlm | When set to true, uses built-in managed implementation of NTLM and SPNEGO algorithm for HTTP, SMTP authentication, and NegotiateAuthentication API instead of system provided GSSAPI implementation. | +| _ComObjectDescriptorSupport | System.ComponentModel.TypeDescriptor.IsComObjectDescriptorSupported | When set to true, supports creating a TypeDescriptor based view of COM objects. | +| _DesignerHostSupport | System.ComponentModel.Design.IDesignerHost.IsSupported | When set to true, supports creating design components at runtime. | +| _DefaultValueAttributeSupport | System.ComponentModel.DefaultValueAttribute.IsSupported | When set to true, supports creating a DefaultValueAttribute at runtime. | Any feature-switch which defines property can be set in csproj file or on the command line as any other MSBuild property. Those without predefined property name diff --git a/eng/DotNetBuild.props b/eng/DotNetBuild.props index 06ea2ee04665..9d68b8265b0c 100644 --- a/eng/DotNetBuild.props +++ b/eng/DotNetBuild.props @@ -65,6 +65,9 @@ $(InnerBuildArgs) /p:WasmEnableThreads=true $(InnerBuildArgs) $(FlagParameterPrefix)s clr.nativeaotlibs+clr.nativeaotruntime+libs+packs /p:BuildNativeAOTRuntimePack=true /p:SkipLibrariesNativeRuntimePackages=true + $(InnerBuildArgs) /p:MonoEnableLLVM=$(DotNetBuildMonoEnableLLVM) + $(InnerBuildArgs) /p:MonoAOTEnableLLVM=$(DotNetBuildMonoAOTEnableLLVM) + $(InnerBuildArgs) /p:MonoBundleLLVMOptimizer=$(DotNetBuildMonoBundleLLVMOptimizer) $(InnerBuildArgs) $(FlagParameterPrefix)pgoinstrument @@ -81,6 +84,7 @@ $(InnerBuildArgs) /p:SourceBuiltNonShippingPackagesDir=$(SourceBuiltNonShippingPackagesDir) $(InnerBuildArgs) /p:SourceBuiltAssetManifestsDir=$(SourceBuiltAssetManifestsDir) $(InnerBuildArgs) /p:SourceBuiltSymbolsDir=$(SourceBuiltSymbolsDir) + $(InnerBuildArgs) /p:GitHubRepositoryName=$(GitHubRepositoryName)
    diff --git a/eng/Subsets.props b/eng/Subsets.props index 8026bf97e046..b55ead61e3be 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -129,6 +129,13 @@ true + + + CxxStandardLibrary=$(TargetCxxStandardLibrary) + $(TargetCxxLibraryProperties);CxxStandardLibraryStatic=$(TargetCxxStandardLibraryStatic) + $(TargetCxxLibraryProperties);CxxAbiLibrary=$(TargetCxxAbiLibrary) + + @@ -180,6 +187,8 @@ + + @@ -274,7 +283,7 @@ @@ -369,6 +378,8 @@ + + @@ -380,6 +391,10 @@ Test="true" Category="clr" Condition="'$(DotNetBuildSourceOnly)' != 'true' and '$(NativeAotSupported)' == 'true'"/> + + + + @@ -463,7 +478,7 @@ - + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index b5717f05a5f5..00c0be13ebbe 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - 1441a3fcbfa87c94b98a27605b06db7dd862f3e4 + 55fed7b2b261aee7f921b13a18dad562c6080014 https://github.com/dotnet/msquic @@ -12,41 +12,41 @@ https://github.com/dotnet/wcf 7f504aabb1988e9a093c1e74d8040bd52feb2f01 - + https://github.com/dotnet/emsdk - 9ad7c262f14dc5e40a64030ade7788b36e74adf0 + 53c4a109e2abc0112996e2bc4a7f830f572f4efd - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 https://github.com/dotnet/command-line-api @@ -58,351 +58,351 @@ a045dd54a4c44723c215d992288160eb1401bb7f - + https://github.com/dotnet/cecil - 9c8ea966df62f764523b51772763e74e71040a92 + 7a4a59f9f66baf6711a6ce2de01d3b2c62ed72d8 - + https://github.com/dotnet/cecil - 9c8ea966df62f764523b51772763e74e71040a92 + 7a4a59f9f66baf6711a6ce2de01d3b2c62ed72d8 - + https://github.com/dotnet/emsdk - 9ad7c262f14dc5e40a64030ade7788b36e74adf0 + 53c4a109e2abc0112996e2bc4a7f830f572f4efd - + https://github.com/dotnet/emsdk - 9ad7c262f14dc5e40a64030ade7788b36e74adf0 + 53c4a109e2abc0112996e2bc4a7f830f572f4efd - + https://github.com/dotnet/source-build-reference-packages - c0b5d69a1a1513528c77fffff708c7502d57c35c + a4c02499bef24d0e16255657ccdb160d26c82c32 - + https://github.com/dotnet/source-build-externals - 1e2e91d2544726b2cf68109f946178ef6bef3ad9 + 59204e5b14e6e197b3c942f992f6e3ec9196e50b - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://github.com/dotnet/runtime-assets - ad97a45c2567fa7c3a067079f166c3f3c9fecd60 + 587c756690070927e81cba864f0db27f0a74e44a - + https://github.com/dotnet/runtime-assets - ad97a45c2567fa7c3a067079f166c3f3c9fecd60 + 587c756690070927e81cba864f0db27f0a74e44a - + https://github.com/dotnet/runtime-assets - ad97a45c2567fa7c3a067079f166c3f3c9fecd60 + 587c756690070927e81cba864f0db27f0a74e44a - + https://github.com/dotnet/runtime-assets - ad97a45c2567fa7c3a067079f166c3f3c9fecd60 + 587c756690070927e81cba864f0db27f0a74e44a - + https://github.com/dotnet/runtime-assets - ad97a45c2567fa7c3a067079f166c3f3c9fecd60 + 587c756690070927e81cba864f0db27f0a74e44a - + https://github.com/dotnet/runtime-assets - ad97a45c2567fa7c3a067079f166c3f3c9fecd60 + 587c756690070927e81cba864f0db27f0a74e44a - + https://github.com/dotnet/runtime-assets - ad97a45c2567fa7c3a067079f166c3f3c9fecd60 + 587c756690070927e81cba864f0db27f0a74e44a - + https://github.com/dotnet/runtime-assets - ad97a45c2567fa7c3a067079f166c3f3c9fecd60 + 587c756690070927e81cba864f0db27f0a74e44a - + https://github.com/dotnet/runtime-assets - ad97a45c2567fa7c3a067079f166c3f3c9fecd60 + 587c756690070927e81cba864f0db27f0a74e44a - + https://github.com/dotnet/runtime-assets - ad97a45c2567fa7c3a067079f166c3f3c9fecd60 + 587c756690070927e81cba864f0db27f0a74e44a - + https://github.com/dotnet/runtime-assets - ad97a45c2567fa7c3a067079f166c3f3c9fecd60 + 587c756690070927e81cba864f0db27f0a74e44a - + https://github.com/dotnet/runtime-assets - ad97a45c2567fa7c3a067079f166c3f3c9fecd60 + 587c756690070927e81cba864f0db27f0a74e44a - + https://github.com/dotnet/runtime-assets - ad97a45c2567fa7c3a067079f166c3f3c9fecd60 + 587c756690070927e81cba864f0db27f0a74e44a - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/llvm-project - 8b4f10702e13ea221a33e91c2ef46c4b7910b56c + 26f8c30340764cfa7fa9090dc01a36c222bf09c1 - + https://github.com/dotnet/runtime - ec4437be46d8b90bc9fa6740c556bd860d9fe5ab + 073e35e7e32624e0f841d94364d2f28c73662ff7 - + https://github.com/dotnet/runtime - ec4437be46d8b90bc9fa6740c556bd860d9fe5ab + 073e35e7e32624e0f841d94364d2f28c73662ff7 - + https://github.com/dotnet/runtime - ec4437be46d8b90bc9fa6740c556bd860d9fe5ab + 073e35e7e32624e0f841d94364d2f28c73662ff7 - + https://github.com/dotnet/runtime - ec4437be46d8b90bc9fa6740c556bd860d9fe5ab + 073e35e7e32624e0f841d94364d2f28c73662ff7 - + https://github.com/dotnet/runtime - ec4437be46d8b90bc9fa6740c556bd860d9fe5ab + 073e35e7e32624e0f841d94364d2f28c73662ff7 - + https://github.com/dotnet/runtime - ec4437be46d8b90bc9fa6740c556bd860d9fe5ab + 073e35e7e32624e0f841d94364d2f28c73662ff7 - + https://github.com/dotnet/runtime - ec4437be46d8b90bc9fa6740c556bd860d9fe5ab + 073e35e7e32624e0f841d94364d2f28c73662ff7 - + https://github.com/dotnet/runtime - ec4437be46d8b90bc9fa6740c556bd860d9fe5ab + 073e35e7e32624e0f841d94364d2f28c73662ff7 - + https://github.com/dotnet/runtime - ec4437be46d8b90bc9fa6740c556bd860d9fe5ab + 073e35e7e32624e0f841d94364d2f28c73662ff7 - + https://github.com/dotnet/xharness - 28af9496b0e260f7e66ec549b39f1410ee9743d1 + 8cbf240a033d37ab8ebae11726bb3f867cfeb9e3 - + https://github.com/dotnet/xharness - 28af9496b0e260f7e66ec549b39f1410ee9743d1 + 8cbf240a033d37ab8ebae11726bb3f867cfeb9e3 - + https://github.com/dotnet/xharness - 28af9496b0e260f7e66ec549b39f1410ee9743d1 + 8cbf240a033d37ab8ebae11726bb3f867cfeb9e3 - + https://github.com/dotnet/arcade - 541820fbd313f9bb82b756b66d258fe316d5e48b + ed14da5934ffb536cff8f41f8b5719334524cbed - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 78a5b978e1965c1335edb4b9a22bc4d6ff5a77a6 + c3acfd159662959ff09f3a0d7663023db48bb78a - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 78a5b978e1965c1335edb4b9a22bc4d6ff5a77a6 + c3acfd159662959ff09f3a0d7663023db48bb78a - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 78a5b978e1965c1335edb4b9a22bc4d6ff5a77a6 + c3acfd159662959ff09f3a0d7663023db48bb78a - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 78a5b978e1965c1335edb4b9a22bc4d6ff5a77a6 + c3acfd159662959ff09f3a0d7663023db48bb78a - + https://github.com/dotnet/hotreload-utils - 668ee30182fea845064853c46be5f54ac6efd110 + 7d4a7804532307d4eef18ce48ae655ac8a6c6fcd - + https://github.com/dotnet/runtime-assets - ad97a45c2567fa7c3a067079f166c3f3c9fecd60 + 587c756690070927e81cba864f0db27f0a74e44a - + https://github.com/dotnet/roslyn - cbca41cad4e21c29548e9e57d7135740b6f78df9 + dd1d6535773f71c1f921589cf59d1d62f6e8c27f - + https://github.com/dotnet/roslyn - cbca41cad4e21c29548e9e57d7135740b6f78df9 + dd1d6535773f71c1f921589cf59d1d62f6e8c27f - + https://github.com/dotnet/roslyn - cbca41cad4e21c29548e9e57d7135740b6f78df9 + dd1d6535773f71c1f921589cf59d1d62f6e8c27f - + https://github.com/dotnet/roslyn-analyzers - ad732e236e7ffcb66de4b45a1b736aad4ccdcd83 + 8dccccec1ce3bd2fb532ec77d7e092ab9d684db7 - + https://github.com/dotnet/roslyn-analyzers - ad732e236e7ffcb66de4b45a1b736aad4ccdcd83 + 8dccccec1ce3bd2fb532ec77d7e092ab9d684db7 - + https://github.com/dotnet/roslyn - cbca41cad4e21c29548e9e57d7135740b6f78df9 + dd1d6535773f71c1f921589cf59d1d62f6e8c27f - + https://github.com/dotnet/sdk - 219a6fc9954d632d7c119b31d59ff1516ff04d98 + 190723c80d85721cdc58fd906e645c4029b947bb - + https://github.com/dotnet/sdk - 219a6fc9954d632d7c119b31d59ff1516ff04d98 + 190723c80d85721cdc58fd906e645c4029b947bb - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 78a5b978e1965c1335edb4b9a22bc4d6ff5a77a6 + c3acfd159662959ff09f3a0d7663023db48bb78a - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 78a5b978e1965c1335edb4b9a22bc4d6ff5a77a6 + c3acfd159662959ff09f3a0d7663023db48bb78a @@ -410,9 +410,41 @@ https://github.com/NuGet/NuGet.Client 8fef55f5a55a3b4f2c96cd1a9b5ddc51d4b927f8 - + https://github.com/dotnet/installer - dc43d363d284c26cb1b463683d6ebb2c88ab0b58 + fa261b952d702c6bd604728fcbdb58ac071a22b1 + + + https://github.com/dotnet/node + 308c7d0f1fa19bd1e7b768ad13646f5206133cdb + + + https://github.com/dotnet/node + 308c7d0f1fa19bd1e7b768ad13646f5206133cdb + + + https://github.com/dotnet/node + 308c7d0f1fa19bd1e7b768ad13646f5206133cdb + + + https://github.com/dotnet/node + 308c7d0f1fa19bd1e7b768ad13646f5206133cdb + + + https://github.com/dotnet/node + 308c7d0f1fa19bd1e7b768ad13646f5206133cdb + + + https://github.com/dotnet/node + 308c7d0f1fa19bd1e7b768ad13646f5206133cdb + + + https://github.com/dotnet/node + 308c7d0f1fa19bd1e7b768ad13646f5206133cdb + + + https://github.com/dotnet/node + 308c7d0f1fa19bd1e7b768ad13646f5206133cdb diff --git a/eng/Versions.props b/eng/Versions.props index cd1960205b4f..631dd7d8c2a4 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -7,11 +7,11 @@ 0 0 9.0.100 - 8.0.2 - 7.0.$([MSBuild]::Add($([System.Version]::Parse('$(PackageVersionNet8)').Build),14)) - 6.0.$([MSBuild]::Add($([System.Version]::Parse('$(PackageVersionNet7)').Build),11)) + 8.0.5 + 7.0.19 + 6.0.$([MSBuild]::Add($([System.Version]::Parse('$(PackageVersionNet8)').Build),25)) preview - 4 + 5 false release @@ -34,17 +34,17 @@ - 3.11.0-beta1.24177.1 - 9.0.0-preview.24177.1 + 3.11.0-beta1.24225.1 + 9.0.0-preview.24225.1 - 4.10.0-3.24202.15 - 4.10.0-3.24202.15 - 4.10.0-3.24202.15 + 4.11.0-2.24269.3 + 4.11.0-2.24269.3 + 4.11.0-2.24269.3 - 9.0.100-preview.4.24175.4 + 9.0.100-preview.5.24263.1 - 9.0.0-beta.24205.4 - 9.0.0-beta.24205.4 - 9.0.0-beta.24205.4 - 9.0.0-beta.24205.4 - 2.6.7-beta.24205.4 - 9.0.0-beta.24205.4 - 2.6.7-beta.24205.4 - 9.0.0-beta.24205.4 - 9.0.0-beta.24205.4 - 9.0.0-beta.24205.4 - 9.0.0-beta.24205.4 - 9.0.0-beta.24205.4 - 9.0.0-beta.24205.4 - 9.0.0-beta.24205.4 - 9.0.0-beta.24205.4 - 9.0.0-beta.24205.4 + 9.0.0-beta.24266.1 + 9.0.0-beta.24266.1 + 9.0.0-beta.24266.1 + 9.0.0-beta.24266.1 + 2.6.7-beta.24266.1 + 9.0.0-beta.24266.1 + 2.6.7-beta.24266.1 + 9.0.0-beta.24266.1 + 9.0.0-beta.24266.1 + 9.0.0-beta.24266.1 + 9.0.0-beta.24266.1 + 9.0.0-beta.24266.1 + 9.0.0-beta.24266.1 + 9.0.0-beta.24266.1 + 9.0.0-beta.24266.1 + 9.0.0-beta.24266.1 1.4.0 6.0.0-preview.1.102 - 9.0.0-preview.4.24201.1 + 9.0.0-preview.5.24262.2 6.0.0 - 9.0.0-preview.4.24201.1 + 9.0.0-preview.5.24262.2 6.0.0 1.1.1 @@ -119,45 +119,46 @@ 8.0.0 5.0.0 4.5.5 - 9.0.0-preview.4.24201.1 - 9.0.0-preview.4.24201.1 + 9.0.0-preview.5.24262.2 + 9.0.0-preview.5.24262.2 6.0.0 5.0.0 5.0.0 5.0.0 7.0.0 - 9.0.0-preview.4.24201.1 + 9.0.0-preview.5.24262.2 6.0.0 7.0.0 4.5.4 4.5.0 - 9.0.0-preview.4.24201.1 + 9.0.0-preview.5.24262.2 8.0.0 + 8.0.0 8.0.0 8.0.0 - 9.0.0-beta.24203.1 - 9.0.0-beta.24203.1 - 9.0.0-beta.24203.1 - 9.0.0-beta.24203.1 - 9.0.0-beta.24203.1 - 9.0.0-beta.24203.1 - 9.0.0-beta.24203.1 - 9.0.0-beta.24203.1 - 9.0.0-beta.24203.1 - 9.0.0-beta.24203.1 - 9.0.0-beta.24203.1 - 9.0.0-beta.24203.1 - 9.0.0-beta.24203.1 - 9.0.0-beta.24203.1 + 9.0.0-beta.24263.1 + 9.0.0-beta.24263.1 + 9.0.0-beta.24263.1 + 9.0.0-beta.24263.1 + 9.0.0-beta.24263.1 + 9.0.0-beta.24263.1 + 9.0.0-beta.24263.1 + 9.0.0-beta.24263.1 + 9.0.0-beta.24263.1 + 9.0.0-beta.24263.1 + 9.0.0-beta.24263.1 + 9.0.0-beta.24263.1 + 9.0.0-beta.24263.1 + 9.0.0-beta.24263.1 - 1.0.0-prerelease.24106.4 - 1.0.0-prerelease.24106.4 - 1.0.0-prerelease.24106.4 - 1.0.0-prerelease.24106.4 - 1.0.0-prerelease.24106.4 - 1.0.0-prerelease.24106.4 + 1.0.0-prerelease.24223.3 + 1.0.0-prerelease.24223.3 + 1.0.0-prerelease.24223.3 + 1.0.0-prerelease.24223.3 + 1.0.0-prerelease.24223.3 + 1.0.0-prerelease.24223.3 2.0.0 17.8.0-beta1.23475.2 @@ -178,10 +179,10 @@ 1.4.0 17.4.0-preview-20220707-01 - 9.0.0-prerelease.24203.1 - 9.0.0-prerelease.24203.1 - 9.0.0-prerelease.24203.1 - 9.0.0-alpha.0.24201.1 + 9.0.0-prerelease.24266.1 + 9.0.0-prerelease.24266.1 + 9.0.0-prerelease.24266.1 + 9.0.0-alpha.0.24263.1 3.12.0 4.5.0 6.0.0 @@ -207,53 +208,57 @@ 8.0.0-preview-20230918.1 - 0.11.4-alpha.24168.1 + 0.11.4-alpha.24230.1 - 9.0.0-preview.4.24201.1 + 9.0.0-preview.5.24262.2 - 9.0.0-preview.4.24201.1 + 9.0.0-preview.5.24263.1 2.3.5 9.0.0-alpha.1.24167.3 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 - 9.0.0-preview.4.24204.9 + 9.0.0-preview.5.24264.2 $(MicrosoftNETWorkloadEmscriptenCurrentManifest90100TransportVersion) - 9.0.0-preview.4.24204.9 + 9.0.0-preview.5.24264.2 1.1.87-gba258badda 1.0.0-v3.14.0.5722 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 - 16.0.5-alpha.1.24203.4 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 + 16.0.5-alpha.1.24204.1 3.1.7 1.0.406601 - 9.0.100-preview.4.24175.5 + 9.0.100-preview.5.24253.16 $(MicrosoftDotnetSdkInternalVersion) + 9.0.0-alpha.1.24175.1 + $(MicrosoftNETRuntimeEmscriptenVersion) + $(runtimewinx64MicrosoftNETCoreRuntimeWasmNodeTransportPackageVersion) + 3.1.34 diff --git a/eng/common/build.ps1 b/eng/common/build.ps1 index 2a115068a927..a7363df316dc 100644 --- a/eng/common/build.ps1 +++ b/eng/common/build.ps1 @@ -19,7 +19,6 @@ Param( [switch] $pack, [switch] $publish, [switch] $clean, - [switch] $verticalBuild, [switch][Alias('pb')]$productBuild, [switch][Alias('bl')]$binaryLog, [switch][Alias('nobl')]$excludeCIBinarylog, @@ -60,7 +59,6 @@ function Print-Usage() { Write-Host " -sign Sign build outputs" Write-Host " -publish Publish artifacts (e.g. symbols)" Write-Host " -clean Clean the solution" - Write-Host " -verticalBuild Run in 'vertical build' infra mode." Write-Host " -productBuild Build the solution in the way it will be built in the full .NET product (VMR) build (short: -pb)" Write-Host "" @@ -124,7 +122,7 @@ function Build { /p:Deploy=$deploy ` /p:Test=$test ` /p:Pack=$pack ` - /p:DotNetBuildRepo=$($productBuild -or $verticalBuild) ` + /p:DotNetBuildRepo=$productBuild ` /p:IntegrationTest=$integrationTest ` /p:PerformanceTest=$performanceTest ` /p:Sign=$sign ` diff --git a/eng/common/build.sh b/eng/common/build.sh index d82ebf742808..ac1ee8620cd2 100755 --- a/eng/common/build.sh +++ b/eng/common/build.sh @@ -62,7 +62,6 @@ scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" restore=false build=false source_build=false -vertical_build=false product_build=false rebuild=false test=false @@ -141,13 +140,6 @@ while [[ $# > 0 ]]; do restore=true pack=true ;; - -verticalbuild|-vb) - build=true - vertical_build=true - product_build=true - restore=true - pack=true - ;; -test|-t) test=true ;; diff --git a/eng/common/core-templates/job/job.yml b/eng/common/core-templates/job/job.yml new file mode 100644 index 000000000000..dc3bd560a50e --- /dev/null +++ b/eng/common/core-templates/job/job.yml @@ -0,0 +1,266 @@ +parameters: +# Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job + cancelTimeoutInMinutes: '' + condition: '' + container: '' + continueOnError: false + dependsOn: '' + displayName: '' + pool: '' + steps: [] + strategy: '' + timeoutInMinutes: '' + variables: [] + workspace: '' + templateContext: {} + +# Job base template specific parameters + # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md + # publishing defaults + artifacts: '' + enableMicrobuild: false + enablePublishBuildArtifacts: false + enablePublishBuildAssets: false + enablePublishTestResults: false + enablePublishUsingPipelines: false + enableBuildRetry: false + disableComponentGovernance: '' + componentGovernanceIgnoreDirectories: '' + mergeTestResults: false + testRunTitle: '' + testResultsFormat: '' + name: '' + preSteps: [] + artifactPublishSteps: [] + runAsPublic: false + +# Sbom related params + enableSbom: true + PackageVersion: 9.0.0 + BuildDropPath: '$(Build.SourcesDirectory)/artifacts' + +# 1es specific parameters + is1ESPipeline: '' + +jobs: +- job: ${{ parameters.name }} + + ${{ if ne(parameters.cancelTimeoutInMinutes, '') }}: + cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }} + + ${{ if ne(parameters.condition, '') }}: + condition: ${{ parameters.condition }} + + ${{ if ne(parameters.container, '') }}: + container: ${{ parameters.container }} + + ${{ if ne(parameters.continueOnError, '') }}: + continueOnError: ${{ parameters.continueOnError }} + + ${{ if ne(parameters.dependsOn, '') }}: + dependsOn: ${{ parameters.dependsOn }} + + ${{ if ne(parameters.displayName, '') }}: + displayName: ${{ parameters.displayName }} + + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + + ${{ if ne(parameters.strategy, '') }}: + strategy: ${{ parameters.strategy }} + + ${{ if ne(parameters.timeoutInMinutes, '') }}: + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} + + ${{ if ne(parameters.templateContext, '') }}: + templateContext: ${{ parameters.templateContext }} + + variables: + - ${{ if ne(parameters.enableTelemetry, 'false') }}: + - name: DOTNET_CLI_TELEMETRY_PROFILE + value: '$(Build.Repository.Uri)' + - ${{ if eq(parameters.enableRichCodeNavigation, 'true') }}: + - name: EnableRichCodeNavigation + value: 'true' + # Retry signature validation up to three times, waiting 2 seconds between attempts. + # See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3028#retry-untrusted-root-failures + - name: NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY + value: 3,2000 + - ${{ each variable in parameters.variables }}: + # handle name-value variable syntax + # example: + # - name: [key] + # value: [value] + - ${{ if ne(variable.name, '') }}: + - name: ${{ variable.name }} + value: ${{ variable.value }} + + # handle variable groups + - ${{ if ne(variable.group, '') }}: + - group: ${{ variable.group }} + + # handle template variable syntax + # example: + # - template: path/to/template.yml + # parameters: + # [key]: [value] + - ${{ if ne(variable.template, '') }}: + - template: ${{ variable.template }} + ${{ if ne(variable.parameters, '') }}: + parameters: ${{ variable.parameters }} + + # handle key-value variable syntax. + # example: + # - [key]: [value] + - ${{ if and(eq(variable.name, ''), eq(variable.group, ''), eq(variable.template, '')) }}: + - ${{ each pair in variable }}: + - name: ${{ pair.key }} + value: ${{ pair.value }} + + # DotNet-HelixApi-Access provides 'HelixApiAccessToken' for internal builds + - ${{ if and(eq(parameters.enableTelemetry, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - group: DotNet-HelixApi-Access + + ${{ if ne(parameters.workspace, '') }}: + workspace: ${{ parameters.workspace }} + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if ne(parameters.preSteps, '') }}: + - ${{ each preStep in parameters.preSteps }}: + - ${{ preStep }} + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if eq(parameters.enableMicrobuild, 'true') }}: + - task: MicroBuildSigningPlugin@4 + displayName: Install MicroBuild plugin + inputs: + signType: $(_SignType) + zipSources: false + feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json + env: + TeamName: $(_TeamName) + MicroBuildOutputFolderOverride: '$(Agent.TempDirectory)' + continueOnError: ${{ parameters.continueOnError }} + condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) + + - ${{ if and(eq(parameters.runAsPublic, 'false'), eq(variables['System.TeamProject'], 'internal')) }}: + - task: NuGetAuthenticate@1 + + - ${{ if and(ne(parameters.artifacts.download, 'false'), ne(parameters.artifacts.download, '')) }}: + - task: DownloadPipelineArtifact@2 + inputs: + buildType: current + artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} + targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} + itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} + + - ${{ each step in parameters.steps }}: + - ${{ step }} + + - ${{ if eq(parameters.enableRichCodeNavigation, true) }}: + - task: RichCodeNavIndexer@0 + displayName: RichCodeNav Upload + inputs: + languages: ${{ coalesce(parameters.richCodeNavigationLanguage, 'csharp') }} + environment: ${{ coalesce(parameters.richCodeNavigationEnvironment, 'internal') }} + richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin + uploadRichNavArtifacts: ${{ coalesce(parameters.richCodeNavigationUploadArtifacts, false) }} + continueOnError: true + + - template: /eng/common/core-templates/steps/component-governance.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + ${{ if eq(parameters.disableComponentGovernance, '') }}: + ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: + disableComponentGovernance: false + ${{ else }}: + disableComponentGovernance: true + ${{ else }}: + disableComponentGovernance: ${{ parameters.disableComponentGovernance }} + componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} + + - ${{ if eq(parameters.enableMicrobuild, 'true') }}: + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - task: MicroBuildCleanup@1 + displayName: Execute Microbuild cleanup tasks + condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} + env: + TeamName: $(_TeamName) + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: + - template: /eng/common/core-templates/steps/generate-sbom.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + PackageVersion: ${{ parameters.packageVersion}} + BuildDropPath: ${{ parameters.buildDropPath }} + IgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} + publishArtifacts: false + + # Publish test results + - ${{ if and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')) }}: + - ${{ if eq(parameters.testResultsFormat, 'xunit') }}: + - task: PublishTestResults@2 + displayName: Publish XUnit Test Results + inputs: + testResultsFormat: 'xUnit' + testResultsFiles: '*.xml' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' + testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit + mergeTestResults: ${{ parameters.mergeTestResults }} + continueOnError: true + condition: always() + - ${{ if eq(parameters.testResultsFormat, 'vstest') }}: + - task: PublishTestResults@2 + displayName: Publish TRX Test Results + inputs: + testResultsFormat: 'VSTest' + testResultsFiles: '*.trx' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' + testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx + mergeTestResults: ${{ parameters.mergeTestResults }} + continueOnError: true + condition: always() + + # gather artifacts + - ${{ if ne(parameters.artifacts.publish, '') }}: + - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: + - task: CopyFiles@2 + displayName: Gather binaries for publish to artifacts + inputs: + SourceFolder: 'artifacts/bin' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' + - task: CopyFiles@2 + displayName: Gather packages for publish to artifacts + inputs: + SourceFolder: 'artifacts/packages' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' + - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: + - task: CopyFiles@2 + displayName: Gather logs for publish to artifacts + inputs: + SourceFolder: 'artifacts/log' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/log' + + - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: + - task: CopyFiles@2 + displayName: Gather logs for publish to artifacts + inputs: + SourceFolder: 'artifacts/log/$(_BuildConfig)' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' + - ${{ if eq(parameters.enableBuildRetry, 'true') }}: + - task: CopyFiles@2 + displayName: Gather buildconfiguration for build retry + inputs: + SourceFolder: '$(Build.SourcesDirectory)/eng/common/BuildConfiguration' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/eng/common/BuildConfiguration' + + - ${{ each step in parameters.artifactPublishSteps }}: + - ${{ step }} diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml new file mode 100644 index 000000000000..00feec8ebbc3 --- /dev/null +++ b/eng/common/core-templates/job/onelocbuild.yml @@ -0,0 +1,121 @@ +parameters: + # Optional: dependencies of the job + dependsOn: '' + + # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool + pool: '' + + CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex + GithubPat: $(BotAccount-dotnet-bot-repo-PAT) + + SourcesDirectory: $(Build.SourcesDirectory) + CreatePr: true + AutoCompletePr: false + ReusePr: true + UseLfLineEndings: true + UseCheckedInLocProjectJson: false + SkipLocProjectJsonGeneration: false + LanguageSet: VS_Main_Languages + LclSource: lclFilesInRepo + LclPackageId: '' + RepoType: gitHub + GitHubOrg: dotnet + MirrorRepo: '' + MirrorBranch: main + condition: '' + JobNameSuffix: '' + is1ESPipeline: '' +jobs: +- job: OneLocBuild${{ parameters.JobNameSuffix }} + + dependsOn: ${{ parameters.dependsOn }} + + displayName: OneLocBuild${{ parameters.JobNameSuffix }} + + variables: + - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat + - name: _GenerateLocProjectArguments + value: -SourcesDirectory ${{ parameters.SourcesDirectory }} + -LanguageSet "${{ parameters.LanguageSet }}" + -CreateNeutralXlfs + - ${{ if eq(parameters.UseCheckedInLocProjectJson, 'true') }}: + - name: _GenerateLocProjectArguments + value: ${{ variables._GenerateLocProjectArguments }} -UseCheckedInLocProjectJson + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + ${{ if eq(parameters.pool, '') }}: + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: $(DncEngInternalBuildPool) + image: 1es-windows-2022 + os: windows + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}: + - task: Powershell@2 + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1 + arguments: $(_GenerateLocProjectArguments) + displayName: Generate LocProject.json + condition: ${{ parameters.condition }} + + - task: OneLocBuild@2 + displayName: OneLocBuild + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + inputs: + locProj: eng/Localize/LocProject.json + outDir: $(Build.ArtifactStagingDirectory) + lclSource: ${{ parameters.LclSource }} + lclPackageId: ${{ parameters.LclPackageId }} + isCreatePrSelected: ${{ parameters.CreatePr }} + isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }} + ${{ if eq(parameters.CreatePr, true) }}: + isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} + ${{ if eq(parameters.RepoType, 'gitHub') }}: + isShouldReusePrSelected: ${{ parameters.ReusePr }} + packageSourceAuth: patAuth + patVariable: ${{ parameters.CeapexPat }} + ${{ if eq(parameters.RepoType, 'gitHub') }}: + repoType: ${{ parameters.RepoType }} + gitHubPatVariable: "${{ parameters.GithubPat }}" + ${{ if ne(parameters.MirrorRepo, '') }}: + isMirrorRepoSelected: true + gitHubOrganization: ${{ parameters.GitHubOrg }} + mirrorRepo: ${{ parameters.MirrorRepo }} + mirrorBranch: ${{ parameters.MirrorBranch }} + condition: ${{ parameters.condition }} + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish Localization Files + pathToPublish: '$(Build.ArtifactStagingDirectory)/loc' + publishLocation: Container + artifactName: Loc + condition: ${{ parameters.condition }} + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish LocProject.json + pathToPublish: '$(Build.SourcesDirectory)/eng/Localize/' + publishLocation: Container + artifactName: Loc + condition: ${{ parameters.condition }} \ No newline at end of file diff --git a/eng/common/core-templates/job/publish-build-assets.yml b/eng/common/core-templates/job/publish-build-assets.yml new file mode 100644 index 000000000000..8fe9299542c5 --- /dev/null +++ b/eng/common/core-templates/job/publish-build-assets.yml @@ -0,0 +1,172 @@ +parameters: + configuration: 'Debug' + + # Optional: condition for the job to run + condition: '' + + # Optional: 'true' if future jobs should run even if this job fails + continueOnError: false + + # Optional: dependencies of the job + dependsOn: '' + + # Optional: Include PublishBuildArtifacts task + enablePublishBuildArtifacts: false + + # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool + pool: {} + + # Optional: should run as a public build even in the internal project + # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. + runAsPublic: false + + # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing + publishUsingPipelines: false + + # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing + publishAssetsImmediately: false + + artifactsPublishingAdditionalParameters: '' + + signingValidationAdditionalParameters: '' + + is1ESPipeline: '' + +jobs: +- job: Asset_Registry_Publish + + dependsOn: ${{ parameters.dependsOn }} + timeoutInMinutes: 150 + + ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: + displayName: Publish Assets + ${{ else }}: + displayName: Publish to Build Asset Registry + + variables: + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - group: Publish-Build-Assets + - group: AzureDevOps-Artifact-Feeds-Pats + - name: runCodesignValidationInjection + value: false + # unconditional - needed for logs publishing (redactor tool version) + - template: /eng/common/core-templates/post-build/common-variables.yml + + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Publishing-Internal + image: windows.vs2019.amd64 + os: windows + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - checkout: self + fetchDepth: 3 + clean: true + + - task: DownloadBuildArtifacts@0 + displayName: Download artifact + inputs: + artifactName: AssetManifests + downloadPath: '$(Build.StagingDirectory)/Download' + checkDownloadedFiles: true + condition: ${{ parameters.condition }} + continueOnError: ${{ parameters.continueOnError }} + + - task: NuGetAuthenticate@1 + + - task: PowerShell@2 + displayName: Publish Build Assets + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task PublishBuildAssets -restore -msbuildEngine dotnet + /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' + /p:BuildAssetRegistryToken=$(MaestroAccessToken) + /p:MaestroApiEndpoint=https://maestro.dot.net + /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} + /p:OfficialBuildId=$(Build.BuildNumber) + condition: ${{ parameters.condition }} + continueOnError: ${{ parameters.continueOnError }} + + - task: powershell@2 + displayName: Create ReleaseConfigs Artifact + inputs: + targetType: inline + script: | + New-Item -Path "$(Build.StagingDirectory)/ReleaseConfigs" -ItemType Directory -Force + $filePath = "$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt" + Add-Content -Path $filePath -Value $(BARBuildId) + Add-Content -Path $filePath -Value "$(DefaultChannels)" + Add-Content -Path $filePath -Value $(IsStableBuild) + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish ReleaseConfigs Artifact + pathToPublish: '$(Build.StagingDirectory)/ReleaseConfigs' + publishLocation: Container + artifactName: ReleaseConfigs + + - task: powershell@2 + displayName: Check if SymbolPublishingExclusionsFile.txt exists + inputs: + targetType: inline + script: | + $symbolExclusionfile = "$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt" + if(Test-Path -Path $symbolExclusionfile) + { + Write-Host "SymbolExclusionFile exists" + Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]true" + } + else{ + Write-Host "Symbols Exclusion file does not exist" + Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]false" + } + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish SymbolPublishingExclusionsFile Artifact + condition: eq(variables['SymbolExclusionFile'], 'true') + pathToPublish: '$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' + publishLocation: Container + artifactName: ReleaseConfigs + + - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: PowerShell@2 + displayName: Publish Using Darc + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 + arguments: -BuildId $(BARBuildId) + -PublishingInfraVersion 3 + -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' + -MaestroToken '$(MaestroApiAccessToken)' + -WaitPublishingFinish true + -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' + -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' + + - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: + - template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + JobLabel: 'Publish_Artifacts_Logs' diff --git a/eng/common/core-templates/job/source-build.yml b/eng/common/core-templates/job/source-build.yml new file mode 100644 index 000000000000..c0ce4b3c8618 --- /dev/null +++ b/eng/common/core-templates/job/source-build.yml @@ -0,0 +1,80 @@ +parameters: + # This template adds arcade-powered source-build to CI. The template produces a server job with a + # default ID 'Source_Build_Complete' to put in a dependency list if necessary. + + # Specifies the prefix for source-build jobs added to pipeline. Use this if disambiguation needed. + jobNamePrefix: 'Source_Build' + + # Defines the platform on which to run the job. By default, a linux-x64 machine, suitable for + # managed-only repositories. This is an object with these properties: + # + # name: '' + # The name of the job. This is included in the job ID. + # targetRID: '' + # The name of the target RID to use, instead of the one auto-detected by Arcade. + # nonPortable: false + # Enables non-portable mode. This means a more specific RID (e.g. fedora.32-x64 rather than + # linux-x64), and compiling against distro-provided packages rather than portable ones. + # skipPublishValidation: false + # Disables publishing validation. By default, a check is performed to ensure no packages are + # published by source-build. + # container: '' + # A container to use. Runs in docker. + # pool: {} + # A pool to use. Runs directly on an agent. + # buildScript: '' + # Specifies the build script to invoke to perform the build in the repo. The default + # './build.sh' should work for typical Arcade repositories, but this is customizable for + # difficult situations. + # jobProperties: {} + # A list of job properties to inject at the top level, for potential extensibility beyond + # container and pool. + platform: {} + + is1ESPipeline: '' + +jobs: +- job: ${{ parameters.jobNamePrefix }}_${{ parameters.platform.name }} + displayName: Source-Build (${{ parameters.platform.name }}) + + ${{ each property in parameters.platform.jobProperties }}: + ${{ property.key }}: ${{ property.value }} + + ${{ if ne(parameters.platform.container, '') }}: + container: ${{ parameters.platform.container }} + + ${{ if eq(parameters.platform.pool, '') }}: + # The default VM host AzDO pool. This should be capable of running Docker containers: almost all + # source-build builds run in Docker, including the default managed platform. + # /eng/common/core-templates/variables/pool-providers.yml can't be used here (some customers declare variables already), so duplicate its logic + ${{ if eq(parameters.is1ESPipeline, 'true') }}: + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] + demands: ImageOverride -equals build.ubuntu.2004.amd64 + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] + image: 1es-mariner-2 + os: linux + ${{ else }}: + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] + demands: ImageOverride -equals Build.Ubuntu.2204.Amd64.Open + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] + demands: ImageOverride -equals Build.Ubuntu.2204.Amd64 + ${{ if ne(parameters.platform.pool, '') }}: + pool: ${{ parameters.platform.pool }} + + workspace: + clean: all + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - template: /eng/common/core-templates/steps/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + platform: ${{ parameters.platform }} diff --git a/eng/common/core-templates/job/source-index-stage1.yml b/eng/common/core-templates/job/source-index-stage1.yml new file mode 100644 index 000000000000..f1938eec1020 --- /dev/null +++ b/eng/common/core-templates/job/source-index-stage1.yml @@ -0,0 +1,91 @@ +parameters: + runAsPublic: false + sourceIndexUploadPackageVersion: 2.0.0-20240502.12 + sourceIndexProcessBinlogPackageVersion: 1.0.1-20240129.2 + sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json + sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" + preSteps: [] + binlogPath: artifacts/log/Debug/Build.binlog + condition: '' + dependsOn: '' + pool: '' + is1ESPipeline: '' + +jobs: +- job: SourceIndexStage1 + dependsOn: ${{ parameters.dependsOn }} + condition: ${{ parameters.condition }} + variables: + - name: SourceIndexUploadPackageVersion + value: ${{ parameters.sourceIndexUploadPackageVersion }} + - name: SourceIndexProcessBinlogPackageVersion + value: ${{ parameters.sourceIndexProcessBinlogPackageVersion }} + - name: SourceIndexPackageSource + value: ${{ parameters.sourceIndexPackageSource }} + - name: BinlogPath + value: ${{ parameters.binlogPath }} + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + ${{ if eq(parameters.pool, '') }}: + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: $(DncEngPublicBuildPool) + image: windows.vs2022.amd64.open + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: $(DncEngInternalBuildPool) + image: windows.vs2022.amd64 + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ each preStep in parameters.preSteps }}: + - ${{ preStep }} + + - task: UseDotNet@2 + displayName: Use .NET 8 SDK + inputs: + packageType: sdk + version: 8.0.x + installationPath: $(Agent.TempDirectory)/dotnet + workingDirectory: $(Agent.TempDirectory) + + - script: | + $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(sourceIndexProcessBinlogPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools + $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(sourceIndexUploadPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools + displayName: Download Tools + # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. + workingDirectory: $(Agent.TempDirectory) + + - script: ${{ parameters.sourceIndexBuildCommand }} + displayName: Build Repository + + - script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i $(BinlogPath) -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output + displayName: Process Binlog into indexable sln + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - task: AzureCLI@2 + displayName: Get stage 1 auth token + inputs: + azureSubscription: 'SourceDotNet Stage1 Publish' + addSpnToEnvironment: true + scriptType: 'ps' + scriptLocation: 'inlineScript' + inlineScript: | + echo "##vso[task.setvariable variable=ARM_CLIENT_ID]$env:servicePrincipalId" + echo "##vso[task.setvariable variable=ARM_ID_TOKEN]$env:idToken" + echo "##vso[task.setvariable variable=ARM_TENANT_ID]$env:tenantId" + + - script: | + echo "Client ID: $(ARM_CLIENT_ID)" + echo "ID Token: $(ARM_ID_TOKEN)" + echo "Tenant ID: $(ARM_TENANT_ID)" + az login --service-principal -u $(ARM_CLIENT_ID) --tenant $(ARM_TENANT_ID) --allow-no-subscriptions --federated-token $(ARM_ID_TOKEN) + displayName: "Login to Azure" + + - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) -s netsourceindexstage1 -b stage1 + displayName: Upload stage1 artifacts to source index \ No newline at end of file diff --git a/eng/common/core-templates/jobs/codeql-build.yml b/eng/common/core-templates/jobs/codeql-build.yml new file mode 100644 index 000000000000..f2144252cc65 --- /dev/null +++ b/eng/common/core-templates/jobs/codeql-build.yml @@ -0,0 +1,33 @@ +parameters: + # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md + continueOnError: false + # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job + jobs: [] + # Optional: if specified, restore and use this version of Guardian instead of the default. + overrideGuardianVersion: '' + is1ESPipeline: '' + +jobs: +- template: /eng/common/core-templates/jobs/jobs.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + enableMicrobuild: false + enablePublishBuildArtifacts: false + enablePublishTestResults: false + enablePublishBuildAssets: false + enablePublishUsingPipelines: false + enableTelemetry: true + + variables: + - group: Publish-Build-Assets + # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in + # sync with the packages.config file. + - name: DefaultGuardianVersion + value: 0.109.0 + - name: GuardianPackagesConfigFile + value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config + - name: GuardianVersion + value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} + + jobs: ${{ parameters.jobs }} + diff --git a/eng/common/core-templates/jobs/jobs.yml b/eng/common/core-templates/jobs/jobs.yml new file mode 100644 index 000000000000..ea69be4341c6 --- /dev/null +++ b/eng/common/core-templates/jobs/jobs.yml @@ -0,0 +1,119 @@ +parameters: + # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md + continueOnError: false + + # Optional: Include PublishBuildArtifacts task + enablePublishBuildArtifacts: false + + # Optional: Enable publishing using release pipelines + enablePublishUsingPipelines: false + + # Optional: Enable running the source-build jobs to build repo from source + enableSourceBuild: false + + # Optional: Parameters for source-build template. + # See /eng/common/core-templates/jobs/source-build.yml for options + sourceBuildParameters: [] + + graphFileGeneration: + # Optional: Enable generating the graph files at the end of the build + enabled: false + # Optional: Include toolset dependencies in the generated graph files + includeToolset: false + + # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job + jobs: [] + + # Optional: Override automatically derived dependsOn value for "publish build assets" job + publishBuildAssetsDependsOn: '' + + # Optional: Publish the assets as soon as the publish to BAR stage is complete, rather doing so in a separate stage. + publishAssetsImmediately: false + + # Optional: If using publishAssetsImmediately and additional parameters are needed, can be used to send along additional parameters (normally sent to post-build.yml) + artifactsPublishingAdditionalParameters: '' + signingValidationAdditionalParameters: '' + + # Optional: should run as a public build even in the internal project + # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. + runAsPublic: false + + enableSourceIndex: false + sourceIndexParams: {} + + artifacts: {} + is1ESPipeline: '' + +# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, +# and some (Microbuild) should only be applied to non-PR cases for internal builds. + +jobs: +- ${{ each job in parameters.jobs }}: + - ${{ if eq(parameters.is1ESPipeline, 'true') }}: + - template: /eng/common/templates-official/job/job.yml + parameters: + # pass along parameters + ${{ each parameter in parameters }}: + ${{ if ne(parameter.key, 'jobs') }}: + ${{ parameter.key }}: ${{ parameter.value }} + + # pass along job properties + ${{ each property in job }}: + ${{ if ne(property.key, 'job') }}: + ${{ property.key }}: ${{ property.value }} + + name: ${{ job.job }} + + - ${{ else }}: + - template: /eng/common/templates/job/job.yml + parameters: + # pass along parameters + ${{ each parameter in parameters }}: + ${{ if ne(parameter.key, 'jobs') }}: + ${{ parameter.key }}: ${{ parameter.value }} + + # pass along job properties + ${{ each property in job }}: + ${{ if ne(property.key, 'job') }}: + ${{ property.key }}: ${{ property.value }} + + name: ${{ job.job }} + +- ${{ if eq(parameters.enableSourceBuild, true) }}: + - template: /eng/common/core-templates/jobs/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + allCompletedJobId: Source_Build_Complete + ${{ each parameter in parameters.sourceBuildParameters }}: + ${{ parameter.key }}: ${{ parameter.value }} + +- ${{ if eq(parameters.enableSourceIndex, 'true') }}: + - template: ../job/source-index-stage1.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + runAsPublic: ${{ parameters.runAsPublic }} + ${{ each parameter in parameters.sourceIndexParams }}: + ${{ parameter.key }}: ${{ parameter.value }} + +- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: + - template: ../job/publish-build-assets.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + continueOnError: ${{ parameters.continueOnError }} + dependsOn: + - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: + - ${{ each job in parameters.publishBuildAssetsDependsOn }}: + - ${{ job.job }} + - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: + - ${{ each job in parameters.jobs }}: + - ${{ job.job }} + - ${{ if eq(parameters.enableSourceBuild, true) }}: + - Source_Build_Complete + + runAsPublic: ${{ parameters.runAsPublic }} + publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} + publishAssetsImmediately: ${{ parameters.publishAssetsImmediately }} + enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }} diff --git a/eng/common/core-templates/jobs/source-build.yml b/eng/common/core-templates/jobs/source-build.yml new file mode 100644 index 000000000000..d8e5d0085226 --- /dev/null +++ b/eng/common/core-templates/jobs/source-build.yml @@ -0,0 +1,50 @@ +parameters: + # This template adds arcade-powered source-build to CI. A job is created for each platform, as + # well as an optional server job that completes when all platform jobs complete. + + # The name of the "join" job for all source-build platforms. If set to empty string, the job is + # not included. Existing repo pipelines can use this job depend on all source-build jobs + # completing without maintaining a separate list of every single job ID: just depend on this one + # server job. By default, not included. Recommended name if used: 'Source_Build_Complete'. + allCompletedJobId: '' + + # See /eng/common/core-templates/job/source-build.yml + jobNamePrefix: 'Source_Build' + + # This is the default platform provided by Arcade, intended for use by a managed-only repo. + defaultManagedPlatform: + name: 'Managed' + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream9' + + # Defines the platforms on which to run build jobs. One job is created for each platform, and the + # object in this array is sent to the job template as 'platform'. If no platforms are specified, + # one job runs on 'defaultManagedPlatform'. + platforms: [] + + is1ESPipeline: '' + +jobs: + +- ${{ if ne(parameters.allCompletedJobId, '') }}: + - job: ${{ parameters.allCompletedJobId }} + displayName: Source-Build Complete + pool: server + dependsOn: + - ${{ each platform in parameters.platforms }}: + - ${{ parameters.jobNamePrefix }}_${{ platform.name }} + - ${{ if eq(length(parameters.platforms), 0) }}: + - ${{ parameters.jobNamePrefix }}_${{ parameters.defaultManagedPlatform.name }} + +- ${{ each platform in parameters.platforms }}: + - template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobNamePrefix: ${{ parameters.jobNamePrefix }} + platform: ${{ platform }} + +- ${{ if eq(length(parameters.platforms), 0) }}: + - template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobNamePrefix: ${{ parameters.jobNamePrefix }} + platform: ${{ parameters.defaultManagedPlatform }} diff --git a/eng/common/core-templates/post-build/common-variables.yml b/eng/common/core-templates/post-build/common-variables.yml new file mode 100644 index 000000000000..b9ede10bf099 --- /dev/null +++ b/eng/common/core-templates/post-build/common-variables.yml @@ -0,0 +1,24 @@ +variables: + - group: Publish-Build-Assets + + # Whether the build is internal or not + - name: IsInternalBuild + value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} + + # Default Maestro++ API Endpoint and API Version + - name: MaestroApiEndPoint + value: "https://maestro.dot.net" + - name: MaestroApiAccessToken + value: $(MaestroAccessToken) + - name: MaestroApiVersion + value: "2020-02-20" + + - name: SourceLinkCLIVersion + value: 3.0.0 + - name: SymbolToolVersion + value: 1.0.1 + - name: BinlogToolVersion + value: 1.0.11 + + - name: runCodesignValidationInjection + value: false diff --git a/eng/common/core-templates/post-build/post-build.yml b/eng/common/core-templates/post-build/post-build.yml new file mode 100644 index 000000000000..865bc1ecb4f0 --- /dev/null +++ b/eng/common/core-templates/post-build/post-build.yml @@ -0,0 +1,314 @@ +parameters: + # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. + # Publishing V1 is no longer supported + # Publishing V2 is no longer supported + # Publishing V3 is the default + - name: publishingInfraVersion + displayName: Which version of publishing should be used to promote the build definition? + type: number + default: 3 + values: + - 3 + + - name: BARBuildId + displayName: BAR Build Id + type: number + default: 0 + + - name: PromoteToChannelIds + displayName: Channel to promote BARBuildId to + type: string + default: '' + + - name: enableSourceLinkValidation + displayName: Enable SourceLink validation + type: boolean + default: false + + - name: enableSigningValidation + displayName: Enable signing validation + type: boolean + default: true + + - name: enableSymbolValidation + displayName: Enable symbol validation + type: boolean + default: false + + - name: enableNugetValidation + displayName: Enable NuGet validation + type: boolean + default: true + + - name: publishInstallersAndChecksums + displayName: Publish installers and checksums + type: boolean + default: true + + - name: SDLValidationParameters + type: object + default: + enable: false + publishGdn: false + continueOnError: false + params: '' + artifactNames: '' + downloadArtifacts: true + + # These parameters let the user customize the call to sdk-task.ps1 for publishing + # symbols & general artifacts as well as for signing validation + - name: symbolPublishingAdditionalParameters + displayName: Symbol publishing additional parameters + type: string + default: '' + + - name: artifactsPublishingAdditionalParameters + displayName: Artifact publishing additional parameters + type: string + default: '' + + - name: signingValidationAdditionalParameters + displayName: Signing validation additional parameters + type: string + default: '' + + # Which stages should finish execution before post-build stages start + - name: validateDependsOn + type: object + default: + - build + + - name: publishDependsOn + type: object + default: + - Validate + + # Optional: Call asset publishing rather than running in a separate stage + - name: publishAssetsImmediately + type: boolean + default: false + + - name: is1ESPipeline + type: boolean + default: false + +stages: +- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: + - stage: Validate + dependsOn: ${{ parameters.validateDependsOn }} + displayName: Validate Build Assets + variables: + - template: /eng/common/core-templates/post-build/common-variables.yml + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobs: + - job: + displayName: NuGet Validation + condition: and(succeededOrFailed(), eq( ${{ parameters.enableNugetValidation }}, 'true')) + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + ${{ if eq(parameters.is1ESPipeline, true) }}: + name: $(DncEngInternalBuildPool) + image: windows.vs2022.amd64 + os: windows + ${{ else }}: + name: $(DncEngInternalBuildPool) + demands: ImageOverride -equals windows.vs2022.amd64 + + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: PackageArtifacts + checkDownloadedFiles: true + + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1 + arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ + -ToolDestinationPath $(Agent.BuildDirectory)/Extract/ + + - job: + displayName: Signing Validation + condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + ${{ if eq(parameters.is1ESPipeline, true) }}: + name: $(DncEngInternalBuildPool) + image: 1es-windows-2022 + os: windows + ${{ else }}: + name: $(DncEngInternalBuildPool) + demands: ImageOverride -equals windows.vs2022.amd64 + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: PackageArtifacts + checkDownloadedFiles: true + itemPattern: | + ** + !**/Microsoft.SourceBuild.Intermediate.*.nupkg + + # This is necessary whenever we want to publish/restore to an AzDO private feed + # Since sdk-task.ps1 tries to restore packages we need to do this authentication here + # otherwise it'll complain about accessing a private feed. + - task: NuGetAuthenticate@1 + displayName: 'Authenticate to AzDO Feeds' + + # Signing validation will optionally work with the buildmanifest file which is downloaded from + # Azure DevOps above. + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task SigningValidation -restore -msbuildEngine vs + /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' + /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' + ${{ parameters.signingValidationAdditionalParameters }} + + - template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + StageLabel: 'Validation' + JobLabel: 'Signing' + BinlogToolVersion: $(BinlogToolVersion) + + - job: + displayName: SourceLink Validation + condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + ${{ if eq(parameters.is1ESPipeline, true) }}: + name: $(DncEngInternalBuildPool) + image: 1es-windows-2022 + os: windows + ${{ else }}: + name: $(DncEngInternalBuildPool) + demands: ImageOverride -equals windows.vs2022.amd64 + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: DownloadBuildArtifacts@0 + displayName: Download Blob Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: BlobArtifacts + checkDownloadedFiles: true + + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1 + arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/ + -ExtractPath $(Agent.BuildDirectory)/Extract/ + -GHRepoName $(Build.Repository.Name) + -GHCommit $(Build.SourceVersion) + -SourcelinkCliVersion $(SourceLinkCLIVersion) + continueOnError: true + +- ${{ if ne(parameters.publishAssetsImmediately, 'true') }}: + - stage: publish_using_darc + ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: + dependsOn: ${{ parameters.publishDependsOn }} + ${{ else }}: + dependsOn: ${{ parameters.validateDependsOn }} + displayName: Publish using Darc + variables: + - template: /eng/common/core-templates/post-build/common-variables.yml + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobs: + - job: + displayName: Publish Using Darc + timeoutInMinutes: 120 + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + ${{ if eq(parameters.is1ESPipeline, true) }}: + name: NetCore1ESPool-Publishing-Internal + image: windows.vs2019.amd64 + os: windows + ${{ else }}: + name: NetCore1ESPool-Publishing-Internal + demands: ImageOverride -equals windows.vs2019.amd64 + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: NuGetAuthenticate@1 + + - task: PowerShell@2 + displayName: Publish Using Darc + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 + arguments: -BuildId $(BARBuildId) + -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} + -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' + -MaestroToken '$(MaestroApiAccessToken)' + -WaitPublishingFinish true + -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' + -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' diff --git a/eng/common/core-templates/post-build/setup-maestro-vars.yml b/eng/common/core-templates/post-build/setup-maestro-vars.yml new file mode 100644 index 000000000000..8d56b5726793 --- /dev/null +++ b/eng/common/core-templates/post-build/setup-maestro-vars.yml @@ -0,0 +1,74 @@ +parameters: + BARBuildId: '' + PromoteToChannelIds: '' + is1ESPipeline: '' + +steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: + - task: DownloadBuildArtifacts@0 + displayName: Download Release Configs + inputs: + buildType: current + artifactName: ReleaseConfigs + checkDownloadedFiles: true + + - task: PowerShell@2 + name: setReleaseVars + displayName: Set Release Configs Vars + inputs: + targetType: inline + pwsh: true + script: | + try { + if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { + $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt + + $BarId = $Content | Select -Index 0 + $Channels = $Content | Select -Index 1 + $IsStableBuild = $Content | Select -Index 2 + + $AzureDevOpsProject = $Env:System_TeamProject + $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId + $AzureDevOpsBuildId = $Env:Build_BuildId + } + else { + $buildApiEndpoint = "${Env:MaestroApiEndPoint}/api/builds/${Env:BARBuildId}?api-version=${Env:MaestroApiVersion}" + + $apiHeaders = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' + $apiHeaders.Add('Accept', 'application/json') + $apiHeaders.Add('Authorization',"Bearer ${Env:MAESTRO_API_TOKEN}") + + $buildInfo = try { Invoke-WebRequest -Method Get -Uri $buildApiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } + + $BarId = $Env:BARBuildId + $Channels = $Env:PromoteToMaestroChannels -split "," + $Channels = $Channels -join "][" + $Channels = "[$Channels]" + + $IsStableBuild = $buildInfo.stable + $AzureDevOpsProject = $buildInfo.azureDevOpsProject + $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId + $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId + } + + Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" + Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" + Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" + + Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" + Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" + Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" + } + catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + exit 1 + } + env: + MAESTRO_API_TOKEN: $(MaestroApiAccessToken) + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} diff --git a/eng/common/core-templates/post-build/trigger-subscription.yml b/eng/common/core-templates/post-build/trigger-subscription.yml new file mode 100644 index 000000000000..da669030daf6 --- /dev/null +++ b/eng/common/core-templates/post-build/trigger-subscription.yml @@ -0,0 +1,13 @@ +parameters: + ChannelId: 0 + +steps: +- task: PowerShell@2 + displayName: Triggering subscriptions + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/trigger-subscriptions.ps1 + arguments: -SourceRepo $(Build.Repository.Uri) + -ChannelId ${{ parameters.ChannelId }} + -MaestroApiAccessToken $(MaestroAccessToken) + -MaestroApiEndPoint $(MaestroApiEndPoint) + -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/core-templates/steps/add-build-to-channel.yml b/eng/common/core-templates/steps/add-build-to-channel.yml new file mode 100644 index 000000000000..f67a210d62f3 --- /dev/null +++ b/eng/common/core-templates/steps/add-build-to-channel.yml @@ -0,0 +1,13 @@ +parameters: + ChannelId: 0 + +steps: +- task: PowerShell@2 + displayName: Add Build to Channel + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/add-build-to-channel.ps1 + arguments: -BuildId $(BARBuildId) + -ChannelId ${{ parameters.ChannelId }} + -MaestroApiAccessToken $(MaestroApiAccessToken) + -MaestroApiEndPoint $(MaestroApiEndPoint) + -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/core-templates/steps/component-governance.yml b/eng/common/core-templates/steps/component-governance.yml new file mode 100644 index 000000000000..df449a34c112 --- /dev/null +++ b/eng/common/core-templates/steps/component-governance.yml @@ -0,0 +1,14 @@ +parameters: + disableComponentGovernance: false + componentGovernanceIgnoreDirectories: '' + is1ESPipeline: false + +steps: +- ${{ if eq(parameters.disableComponentGovernance, 'true') }}: + - script: echo "##vso[task.setvariable variable=skipComponentGovernanceDetection]true" + displayName: Set skipComponentGovernanceDetection variable +- ${{ if ne(parameters.disableComponentGovernance, 'true') }}: + - task: ComponentGovernanceComponentDetection@0 + continueOnError: true + inputs: + ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} \ No newline at end of file diff --git a/eng/common/core-templates/steps/generate-sbom.yml b/eng/common/core-templates/steps/generate-sbom.yml new file mode 100644 index 000000000000..d938b60e1bb5 --- /dev/null +++ b/eng/common/core-templates/steps/generate-sbom.yml @@ -0,0 +1,54 @@ +# BuildDropPath - The root folder of the drop directory for which the manifest file will be generated. +# PackageName - The name of the package this SBOM represents. +# PackageVersion - The version of the package this SBOM represents. +# ManifestDirPath - The path of the directory where the generated manifest files will be placed +# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. + +parameters: + PackageVersion: 9.0.0 + BuildDropPath: '$(Build.SourcesDirectory)/artifacts' + PackageName: '.NET' + ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom + IgnoreDirectories: '' + sbomContinueOnError: true + is1ESPipeline: false + # disable publishArtifacts if some other step is publishing the artifacts (like job.yml). + publishArtifacts: true + +steps: +- task: PowerShell@2 + displayName: Prep for SBOM generation in (Non-linux) + condition: or(eq(variables['Agent.Os'], 'Windows_NT'), eq(variables['Agent.Os'], 'Darwin')) + inputs: + filePath: ./eng/common/generate-sbom-prep.ps1 + arguments: ${{parameters.manifestDirPath}} + +# Chmodding is a workaround for https://github.com/dotnet/arcade/issues/8461 +- script: | + chmod +x ./eng/common/generate-sbom-prep.sh + ./eng/common/generate-sbom-prep.sh ${{parameters.manifestDirPath}} + displayName: Prep for SBOM generation in (Linux) + condition: eq(variables['Agent.Os'], 'Linux') + continueOnError: ${{ parameters.sbomContinueOnError }} + +- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 + displayName: 'Generate SBOM manifest' + continueOnError: ${{ parameters.sbomContinueOnError }} + inputs: + PackageName: ${{ parameters.packageName }} + BuildDropPath: ${{ parameters.buildDropPath }} + PackageVersion: ${{ parameters.packageVersion }} + ManifestDirPath: ${{ parameters.manifestDirPath }} + ${{ if ne(parameters.IgnoreDirectories, '') }}: + AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' + +- ${{ if eq(parameters.publishArtifacts, 'true')}}: + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish SBOM manifest + continueOnError: ${{parameters.sbomContinueOnError}} + targetPath: '${{ parameters.manifestDirPath }}' + artifactName: $(ARTIFACT_NAME) + diff --git a/eng/common/core-templates/steps/publish-build-artifacts.yml b/eng/common/core-templates/steps/publish-build-artifacts.yml new file mode 100644 index 000000000000..f24ce346684e --- /dev/null +++ b/eng/common/core-templates/steps/publish-build-artifacts.yml @@ -0,0 +1,20 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false +- name: args + type: object + default: {} +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - template: /eng/common/templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + ${{ each parameter in parameters.args }}: + ${{ parameter.key }}: ${{ parameter.value }} +- ${{ else }}: + - template: /eng/common/templates-official/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + ${{ each parameter in parameters.args }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/core-templates/steps/publish-logs.yml b/eng/common/core-templates/steps/publish-logs.yml new file mode 100644 index 000000000000..8c5ea77b586d --- /dev/null +++ b/eng/common/core-templates/steps/publish-logs.yml @@ -0,0 +1,59 @@ +parameters: + StageLabel: '' + JobLabel: '' + CustomSensitiveDataList: '' + # A default - in case value from eng/common/core-templates/post-build/common-variables.yml is not passed + BinlogToolVersion: '1.0.11' + is1ESPipeline: false + +steps: +- task: Powershell@2 + displayName: Prepare Binlogs to Upload + inputs: + targetType: inline + script: | + New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ + Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ + continueOnError: true + condition: always() + +- task: PowerShell@2 + displayName: Redact Logs + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/redact-logs.ps1 + # For now this needs to have explicit list of all sensitive data. Taken from eng/publishing/v3/publish.yml + # Sensitive data can as well be added to $(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' + # If the file exists - sensitive data for redaction will be sourced from it + # (single entry per line, lines starting with '# ' are considered comments and skipped) + arguments: -InputPath '$(Build.SourcesDirectory)/PostBuildLogs' + -BinlogToolVersion ${{parameters.BinlogToolVersion}} + -TokensFilePath '$(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' + '$(publishing-dnceng-devdiv-code-r-build-re)' + '$(MaestroAccessToken)' + '$(dn-bot-all-orgs-artifact-feeds-rw)' + '$(akams-client-id)' + '$(akams-client-secret)' + '$(microsoft-symbol-server-pat)' + '$(symweb-symbol-server-pat)' + '$(dn-bot-all-orgs-build-rw-code-rw)' + ${{parameters.CustomSensitiveDataList}} + continueOnError: true + condition: always() + +- task: CopyFiles@2 + displayName: Gather post build logs + inputs: + SourceFolder: '$(Build.SourcesDirectory)/PostBuildLogs' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/PostBuildLogs' + +- template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish Logs + pathToPublish: '$(Build.ArtifactStagingDirectory)/PostBuildLogs' + publishLocation: Container + artifactName: PostBuildLogs + continueOnError: true + condition: always() diff --git a/eng/common/core-templates/steps/publish-pipeline-artifacts.yml b/eng/common/core-templates/steps/publish-pipeline-artifacts.yml new file mode 100644 index 000000000000..2efec04dc2c1 --- /dev/null +++ b/eng/common/core-templates/steps/publish-pipeline-artifacts.yml @@ -0,0 +1,20 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false + +- name: args + type: object + default: {} + +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - template: /eng/common/templates/steps/publish-pipeline-artifacts.yml + parameters: + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} +- ${{ else }}: + - template: /eng/common/templates-official/steps/publish-pipeline-artifacts.yml + parameters: + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/core-templates/steps/retain-build.yml b/eng/common/core-templates/steps/retain-build.yml new file mode 100644 index 000000000000..83d97a26a01f --- /dev/null +++ b/eng/common/core-templates/steps/retain-build.yml @@ -0,0 +1,28 @@ +parameters: + # Optional azure devops PAT with build execute permissions for the build's organization, + # only needed if the build that should be retained ran on a different organization than + # the pipeline where this template is executing from + Token: '' + # Optional BuildId to retain, defaults to the current running build + BuildId: '' + # Azure devops Organization URI for the build in the https://dev.azure.com/ format. + # Defaults to the organization the current pipeline is running on + AzdoOrgUri: '$(System.CollectionUri)' + # Azure devops project for the build. Defaults to the project the current pipeline is running on + AzdoProject: '$(System.TeamProject)' + +steps: + - task: powershell@2 + inputs: + targetType: 'filePath' + filePath: eng/common/retain-build.ps1 + pwsh: true + arguments: > + -AzdoOrgUri: ${{parameters.AzdoOrgUri}} + -AzdoProject ${{parameters.AzdoProject}} + -Token ${{coalesce(parameters.Token, '$env:SYSTEM_ACCESSTOKEN') }} + -BuildId ${{coalesce(parameters.BuildId, '$env:BUILD_ID')}} + displayName: Enable permanent build retention + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + BUILD_ID: $(Build.BuildId) \ No newline at end of file diff --git a/eng/common/core-templates/steps/send-to-helix.yml b/eng/common/core-templates/steps/send-to-helix.yml new file mode 100644 index 000000000000..68fa739c4ab2 --- /dev/null +++ b/eng/common/core-templates/steps/send-to-helix.yml @@ -0,0 +1,93 @@ +# Please remember to update the documentation if you make changes to these parameters! +parameters: + HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/ + HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' + HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number + HelixTargetQueues: '' # required -- semicolon-delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues + HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group + HelixProjectPath: 'eng/common/helixpublish.proj' # optional -- path to the project file to build relative to BUILD_SOURCESDIRECTORY + HelixProjectArguments: '' # optional -- arguments passed to the build command + HelixConfiguration: '' # optional -- additional property attached to a job + HelixPreCommands: '' # optional -- commands to run before Helix work item execution + HelixPostCommands: '' # optional -- commands to run after Helix work item execution + WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects + WorkItemCommand: '' # optional -- a command to execute on the payload; requires WorkItemDirectory; incompatible with XUnitProjects + WorkItemTimeout: '' # optional -- a timeout in TimeSpan.Parse-ready value (e.g. 00:02:00) for the work item command; requires WorkItemDirectory; incompatible with XUnitProjects + CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload + XUnitProjects: '' # optional -- semicolon-delimited list of XUnitProjects to parse and send to Helix; requires XUnitRuntimeTargetFramework, XUnitPublishTargetFramework, XUnitRunnerVersion, and IncludeDotNetCli=true + XUnitWorkItemTimeout: '' # optional -- the workitem timeout in seconds for all workitems created from the xUnit projects specified by XUnitProjects + XUnitPublishTargetFramework: '' # optional -- framework to use to publish your xUnit projects + XUnitRuntimeTargetFramework: '' # optional -- framework to use for the xUnit console runner + XUnitRunnerVersion: '' # optional -- version of the xUnit nuget package you wish to use on Helix; required for XUnitProjects + IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion + DotNetCliPackageType: '' # optional -- either 'sdk', 'runtime' or 'aspnetcore-runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json + DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json + WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." + IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set + HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting https://helix.int-dot.net ) + Creator: '' # optional -- if the build is external, use this to specify who is sending the job + DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO + condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() + continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false + +steps: + - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' + displayName: ${{ parameters.DisplayNamePrefix }} (Windows) + env: + BuildConfig: $(_BuildConfig) + HelixSource: ${{ parameters.HelixSource }} + HelixType: ${{ parameters.HelixType }} + HelixBuild: ${{ parameters.HelixBuild }} + HelixConfiguration: ${{ parameters.HelixConfiguration }} + HelixTargetQueues: ${{ parameters.HelixTargetQueues }} + HelixAccessToken: ${{ parameters.HelixAccessToken }} + HelixPreCommands: ${{ parameters.HelixPreCommands }} + HelixPostCommands: ${{ parameters.HelixPostCommands }} + WorkItemDirectory: ${{ parameters.WorkItemDirectory }} + WorkItemCommand: ${{ parameters.WorkItemCommand }} + WorkItemTimeout: ${{ parameters.WorkItemTimeout }} + CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} + XUnitProjects: ${{ parameters.XUnitProjects }} + XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} + XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} + XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} + XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} + IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} + DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} + DotNetCliVersion: ${{ parameters.DotNetCliVersion }} + WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} + HelixBaseUri: ${{ parameters.HelixBaseUri }} + Creator: ${{ parameters.Creator }} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} + - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog + displayName: ${{ parameters.DisplayNamePrefix }} (Unix) + env: + BuildConfig: $(_BuildConfig) + HelixSource: ${{ parameters.HelixSource }} + HelixType: ${{ parameters.HelixType }} + HelixBuild: ${{ parameters.HelixBuild }} + HelixConfiguration: ${{ parameters.HelixConfiguration }} + HelixTargetQueues: ${{ parameters.HelixTargetQueues }} + HelixAccessToken: ${{ parameters.HelixAccessToken }} + HelixPreCommands: ${{ parameters.HelixPreCommands }} + HelixPostCommands: ${{ parameters.HelixPostCommands }} + WorkItemDirectory: ${{ parameters.WorkItemDirectory }} + WorkItemCommand: ${{ parameters.WorkItemCommand }} + WorkItemTimeout: ${{ parameters.WorkItemTimeout }} + CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} + XUnitProjects: ${{ parameters.XUnitProjects }} + XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} + XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} + XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} + XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} + IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} + DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} + DotNetCliVersion: ${{ parameters.DotNetCliVersion }} + WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} + HelixBaseUri: ${{ parameters.HelixBaseUri }} + Creator: ${{ parameters.Creator }} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} diff --git a/eng/common/core-templates/steps/source-build.yml b/eng/common/core-templates/steps/source-build.yml new file mode 100644 index 000000000000..bdd725b496f9 --- /dev/null +++ b/eng/common/core-templates/steps/source-build.yml @@ -0,0 +1,134 @@ +parameters: + # This template adds arcade-powered source-build to CI. + + # This is a 'steps' template, and is intended for advanced scenarios where the existing build + # infra has a careful build methodology that must be followed. For example, a repo + # (dotnet/runtime) might choose to clone the GitHub repo only once and store it as a pipeline + # artifact for all subsequent jobs to use, to reduce dependence on a strong network connection to + # GitHub. Using this steps template leaves room for that infra to be included. + + # Defines the platform on which to run the steps. See 'eng/common/core-templates/job/source-build.yml' + # for details. The entire object is described in the 'job' template for simplicity, even though + # the usage of the properties on this object is split between the 'job' and 'steps' templates. + platform: {} + is1ESPipeline: false + +steps: +# Build. Keep it self-contained for simple reusability. (No source-build-specific job variables.) +- script: | + set -x + df -h + + # If building on the internal project, the artifact feeds variable may be available (usually only if needed) + # In that case, call the feed setup script to add internal feeds corresponding to public ones. + # In addition, add an msbuild argument to copy the WIP from the repo to the target build location. + # This is because SetupNuGetSources.sh will alter the current NuGet.config file, and we need to preserve those + # changes. + internalRestoreArgs= + if [ '$(dn-bot-dnceng-artifact-feeds-rw)' != '$''(dn-bot-dnceng-artifact-feeds-rw)' ]; then + # Temporarily work around https://github.com/dotnet/arcade/issues/7709 + chmod +x $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh + $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh $(Build.SourcesDirectory)/NuGet.config $(dn-bot-dnceng-artifact-feeds-rw) + internalRestoreArgs='/p:CopyWipIntoInnerSourceBuildRepo=true' + + # The 'Copy WIP' feature of source build uses git stash to apply changes from the original repo. + # This only works if there is a username/email configured, which won't be the case in most CI runs. + git config --get user.email + if [ $? -ne 0 ]; then + git config user.email dn-bot@microsoft.com + git config user.name dn-bot + fi + fi + + # If building on the internal project, the internal storage variable may be available (usually only if needed) + # In that case, add variables to allow the download of internal runtimes if the specified versions are not found + # in the default public locations. + internalRuntimeDownloadArgs= + if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then + internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://dotnetbuilds.blob.core.windows.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://dotnetbuilds.blob.core.windows.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' + fi + + buildConfig=Release + # Check if AzDO substitutes in a build config from a variable, and use it if so. + if [ '$(_BuildConfig)' != '$''(_BuildConfig)' ]; then + buildConfig='$(_BuildConfig)' + fi + + officialBuildArgs= + if [ '${{ and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}' = 'True' ]; then + officialBuildArgs='/p:DotNetPublishUsingPipelines=true /p:OfficialBuildId=$(BUILD.BUILDNUMBER)' + fi + + targetRidArgs= + if [ '${{ parameters.platform.targetRID }}' != '' ]; then + targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' + fi + + runtimeOsArgs= + if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then + runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' + fi + + baseOsArgs= + if [ '${{ parameters.platform.baseOS }}' != '' ]; then + baseOsArgs='/p:BaseOS=${{ parameters.platform.baseOS }}' + fi + + publishArgs= + if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then + publishArgs='--publish' + fi + + assetManifestFileName=SourceBuild_RidSpecific.xml + if [ '${{ parameters.platform.name }}' != '' ]; then + assetManifestFileName=SourceBuild_${{ parameters.platform.name }}.xml + fi + + ${{ coalesce(parameters.platform.buildScript, './build.sh') }} --ci \ + --configuration $buildConfig \ + --restore --build --pack $publishArgs -bl \ + $officialBuildArgs \ + $internalRuntimeDownloadArgs \ + $internalRestoreArgs \ + $targetRidArgs \ + $runtimeOsArgs \ + $baseOsArgs \ + /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ + /p:ArcadeBuildFromSource=true \ + /p:DotNetBuildSourceOnly=true \ + /p:DotNetBuildRepo=true \ + /p:AssetManifestFileName=$assetManifestFileName + displayName: Build + +# Upload build logs for diagnosis. +- task: CopyFiles@2 + displayName: Prepare BuildLogs staging directory + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: | + **/*.log + **/*.binlog + artifacts/sb/prebuilt-report/** + TargetFolder: '$(Build.StagingDirectory)/BuildLogs' + CleanTargetFolder: true + continueOnError: true + condition: succeededOrFailed() + +- template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish BuildLogs + targetPath: '$(Build.StagingDirectory)/BuildLogs' + artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) + continueOnError: true + condition: succeededOrFailed() + +# Manually inject component detection so that we can ignore the source build upstream cache, which contains +# a nupkg cache of input packages (a local feed). +# This path must match the upstream cache path in property 'CurrentRepoSourceBuiltNupkgCacheDir' +# in src\Microsoft.DotNet.Arcade.Sdk\tools\SourceBuild\SourceBuildArcade.targets +- task: ComponentGovernanceComponentDetection@0 + displayName: Component Detection (Exclude upstream cache) + inputs: + ignoreDirectories: '$(Build.SourcesDirectory)/artifacts/sb/src/artifacts/obj/source-built-upstream-cache' diff --git a/eng/common/core-templates/variables/pool-providers.yml b/eng/common/core-templates/variables/pool-providers.yml new file mode 100644 index 000000000000..41053d382a2e --- /dev/null +++ b/eng/common/core-templates/variables/pool-providers.yml @@ -0,0 +1,8 @@ +parameters: + is1ESPipeline: false + +variables: + - ${{ if eq(parameters.is1ESPipeline, 'true') }}: + - template: /eng/common/templates-official/variables/pool-providers.yml + - ${{ else }}: + - template: /eng/common/templates/variables/pool-providers.yml \ No newline at end of file diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh index 99a9dd6bb609..a8e35df7cee1 100755 --- a/eng/common/cross/build-rootfs.sh +++ b/eng/common/cross/build-rootfs.sh @@ -142,7 +142,6 @@ while :; do case $lowerI in -\?|-h|--help) usage - exit 1 ;; arm) __BuildArch=arm @@ -229,12 +228,19 @@ while :; do __UbuntuRepo="http://archive.ubuntu.com/ubuntu/" ;; lldb*) - version="${lowerI/lldb/}" - parts=(${version//./ }) + version="$(echo "$lowerI" | tr -d '[:alpha:]-=')" + majorVersion="${version%%.*}" + + [ -z "${version##*.*}" ] && minorVersion="${version#*.}" + if [ -z "$minorVersion" ]; then + minorVersion=0 + fi # for versions > 6.0, lldb has dropped the minor version - if [[ "${parts[0]}" -gt 6 ]]; then - version="${parts[0]}" + if [ "$majorVersion" -le 6 ]; then + version="$majorVersion.$minorVersion" + else + version="$majorVersion" fi __LLDB_Package="liblldb-${version}-dev" @@ -243,15 +249,19 @@ while :; do unset __LLDB_Package ;; llvm*) - version="${lowerI/llvm/}" - parts=(${version//./ }) - __LLVM_MajorVersion="${parts[0]}" - __LLVM_MinorVersion="${parts[1]}" - - # for versions > 6.0, llvm has dropped the minor version - if [[ -z "$__LLVM_MinorVersion" && "$__LLVM_MajorVersion" -le 6 ]]; then - __LLVM_MinorVersion=0; + version="$(echo "$lowerI" | tr -d '[:alpha:]-=')" + __LLVM_MajorVersion="${version%%.*}" + + [ -z "${version##*.*}" ] && __LLVM_MinorVersion="${version#*.}" + if [ -z "$__LLVM_MinorVersion" ]; then + __LLVM_MinorVersion=0 + fi + + # for versions > 6.0, lldb has dropped the minor version + if [ "$__LLVM_MajorVersion" -gt 6 ]; then + __LLVM_MinorVersion= fi + ;; xenial) # Ubuntu 16.04 if [[ "$__CodeName" != "jessie" ]]; then @@ -323,15 +333,14 @@ while :; do alpine*) __CodeName=alpine __UbuntuRepo= - version="${lowerI/alpine/}" - if [[ "$version" == "edge" ]]; then + if [[ "$lowerI" == "alpineedge" ]]; then __AlpineVersion=edge else - parts=(${version//./ }) - __AlpineMajorVersion="${parts[0]}" - __AlpineMinoVersion="${parts[1]}" - __AlpineVersion="$__AlpineMajorVersion.$__AlpineMinoVersion" + version="$(echo "$lowerI" | tr -d '[:alpha:]-=')" + __AlpineMajorVersion="${version%%.*}" + __AlpineMinorVersion="${version#*.}" + __AlpineVersion="$__AlpineMajorVersion.$__AlpineMinorVersion" fi ;; freebsd13) @@ -442,13 +451,39 @@ fi mkdir -p "$__RootfsDir" __RootfsDir="$( cd "$__RootfsDir" && pwd )" +__hasWget= +ensureDownloadTool() +{ + if command -v wget &> /dev/null; then + __hasWget=1 + elif command -v curl &> /dev/null; then + __hasWget=0 + else + >&2 echo "ERROR: either wget or curl is required by this script." + exit 1 + fi +} + if [[ "$__CodeName" == "alpine" ]]; then __ApkToolsVersion=2.12.11 - __ApkToolsSHA512SUM=53e57b49230da07ef44ee0765b9592580308c407a8d4da7125550957bb72cb59638e04f8892a18b584451c8d841d1c7cb0f0ab680cc323a3015776affaa3be33 __ApkToolsDir="$(mktemp -d)" __ApkKeysDir="$(mktemp -d)" + arch="$(uname -m)" - wget "https://gitlab.alpinelinux.org/api/v4/projects/5/packages/generic//v$__ApkToolsVersion/x86_64/apk.static" -P "$__ApkToolsDir" + ensureDownloadTool + + if [[ "$__hasWget" == 1 ]]; then + wget -P "$__ApkToolsDir" "https://gitlab.alpinelinux.org/api/v4/projects/5/packages/generic/v$__ApkToolsVersion/$arch/apk.static" + else + curl -SLO --create-dirs --output-dir "$__ApkToolsDir" "https://gitlab.alpinelinux.org/api/v4/projects/5/packages/generic/v$__ApkToolsVersion/$arch/apk.static" + fi + if [[ "$arch" == "x86_64" ]]; then + __ApkToolsSHA512SUM="53e57b49230da07ef44ee0765b9592580308c407a8d4da7125550957bb72cb59638e04f8892a18b584451c8d841d1c7cb0f0ab680cc323a3015776affaa3be33" + elif [[ "$arch" == "aarch64" ]]; then + __ApkToolsSHA512SUM="9e2b37ecb2b56c05dad23d379be84fd494c14bd730b620d0d576bda760588e1f2f59a7fcb2f2080577e0085f23a0ca8eadd993b4e61c2ab29549fdb71969afd0" + else + echo "WARNING: add missing hash for your host architecture. To find the value, use: 'find /tmp -name apk.static -exec sha512sum {} \;'" + fi echo "$__ApkToolsSHA512SUM $__ApkToolsDir/apk.static" | sha512sum -c chmod +x "$__ApkToolsDir/apk.static" @@ -477,12 +512,14 @@ if [[ "$__CodeName" == "alpine" ]]; then fi # initialize DB + # shellcheck disable=SC2086 "$__ApkToolsDir/apk.static" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/main" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/community" \ -U $__ApkSignatureArg --root "$__RootfsDir" --arch "$__AlpineArch" --initdb add if [[ "$__AlpineLlvmLibsLookup" == 1 ]]; then + # shellcheck disable=SC2086 __AlpinePackages+=" $("$__ApkToolsDir/apk.static" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/main" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/community" \ @@ -491,6 +528,7 @@ if [[ "$__CodeName" == "alpine" ]]; then fi # install all packages in one go + # shellcheck disable=SC2086 "$__ApkToolsDir/apk.static" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/main" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/community" \ @@ -501,12 +539,23 @@ if [[ "$__CodeName" == "alpine" ]]; then elif [[ "$__CodeName" == "freebsd" ]]; then mkdir -p "$__RootfsDir"/usr/local/etc JOBS=${MAXJOBS:="$(getconf _NPROCESSORS_ONLN)"} - wget -O - "https://download.freebsd.org/ftp/releases/${__FreeBSDArch}/${__FreeBSDMachineArch}/${__FreeBSDBase}/base.txz" | tar -C "$__RootfsDir" -Jxf - ./lib ./usr/lib ./usr/libdata ./usr/include ./usr/share/keys ./etc ./bin/freebsd-version + + ensureDownloadTool + + if [[ "$__hasWget" == 1 ]]; then + wget -O- "https://download.freebsd.org/ftp/releases/${__FreeBSDArch}/${__FreeBSDMachineArch}/${__FreeBSDBase}/base.txz" | tar -C "$__RootfsDir" -Jxf - ./lib ./usr/lib ./usr/libdata ./usr/include ./usr/share/keys ./etc ./bin/freebsd-version + else + curl -SL "https://download.freebsd.org/ftp/releases/${__FreeBSDArch}/${__FreeBSDMachineArch}/${__FreeBSDBase}/base.txz" | tar -C "$__RootfsDir" -Jxf - ./lib ./usr/lib ./usr/libdata ./usr/include ./usr/share/keys ./etc ./bin/freebsd-version + fi echo "ABI = \"FreeBSD:${__FreeBSDABI}:${__FreeBSDMachineArch}\"; FINGERPRINTS = \"${__RootfsDir}/usr/share/keys\"; REPOS_DIR = [\"${__RootfsDir}/etc/pkg\"]; REPO_AUTOUPDATE = NO; RUN_SCRIPTS = NO;" > "${__RootfsDir}"/usr/local/etc/pkg.conf echo "FreeBSD: { url: \"pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly\", mirror_type: \"srv\", signature_type: \"fingerprints\", fingerprints: \"${__RootfsDir}/usr/share/keys/pkg\", enabled: yes }" > "${__RootfsDir}"/etc/pkg/FreeBSD.conf mkdir -p "$__RootfsDir"/tmp # get and build package manager - wget -O - "https://github.com/freebsd/pkg/archive/${__FreeBSDPkg}.tar.gz" | tar -C "$__RootfsDir"/tmp -zxf - + if [[ "$__hasWget" == 1 ]]; then + wget -O- "https://github.com/freebsd/pkg/archive/${__FreeBSDPkg}.tar.gz" | tar -C "$__RootfsDir"/tmp -zxf - + else + curl -SL "https://github.com/freebsd/pkg/archive/${__FreeBSDPkg}.tar.gz" | tar -C "$__RootfsDir"/tmp -zxf - + fi cd "$__RootfsDir/tmp/pkg-${__FreeBSDPkg}" # needed for install to succeed mkdir -p "$__RootfsDir"/host/etc @@ -514,20 +563,36 @@ elif [[ "$__CodeName" == "freebsd" ]]; then rm -rf "$__RootfsDir/tmp/pkg-${__FreeBSDPkg}" # install packages we need. INSTALL_AS_USER=$(whoami) "$__RootfsDir"/host/sbin/pkg -r "$__RootfsDir" -C "$__RootfsDir"/usr/local/etc/pkg.conf update + # shellcheck disable=SC2086 INSTALL_AS_USER=$(whoami) "$__RootfsDir"/host/sbin/pkg -r "$__RootfsDir" -C "$__RootfsDir"/usr/local/etc/pkg.conf install --yes $__FreeBSDPackages elif [[ "$__CodeName" == "illumos" ]]; then mkdir "$__RootfsDir/tmp" pushd "$__RootfsDir/tmp" JOBS=${MAXJOBS:="$(getconf _NPROCESSORS_ONLN)"} + + ensureDownloadTool + echo "Downloading sysroot." - wget -O - https://github.com/illumos/sysroot/releases/download/20181213-de6af22ae73b-v1/illumos-sysroot-i386-20181213-de6af22ae73b-v1.tar.gz | tar -C "$__RootfsDir" -xzf - + if [[ "$__hasWget" == 1 ]]; then + wget -O- https://github.com/illumos/sysroot/releases/download/20181213-de6af22ae73b-v1/illumos-sysroot-i386-20181213-de6af22ae73b-v1.tar.gz | tar -C "$__RootfsDir" -xzf - + else + curl -SL https://github.com/illumos/sysroot/releases/download/20181213-de6af22ae73b-v1/illumos-sysroot-i386-20181213-de6af22ae73b-v1.tar.gz | tar -C "$__RootfsDir" -xzf - + fi echo "Building binutils. Please wait.." - wget -O - https://ftp.gnu.org/gnu/binutils/binutils-2.33.1.tar.bz2 | tar -xjf - + if [[ "$__hasWget" == 1 ]]; then + wget -O- https://ftp.gnu.org/gnu/binutils/binutils-2.33.1.tar.bz2 | tar -xjf - + else + curl -SL https://ftp.gnu.org/gnu/binutils/binutils-2.33.1.tar.bz2 | tar -xjf - + fi mkdir build-binutils && cd build-binutils ../binutils-2.33.1/configure --prefix="$__RootfsDir" --target="${__illumosArch}-sun-solaris2.10" --program-prefix="${__illumosArch}-illumos-" --with-sysroot="$__RootfsDir" make -j "$JOBS" && make install && cd .. echo "Building gcc. Please wait.." - wget -O - https://ftp.gnu.org/gnu/gcc/gcc-8.4.0/gcc-8.4.0.tar.xz | tar -xJf - + if [[ "$__hasWget" == 1 ]]; then + wget -O- https://ftp.gnu.org/gnu/gcc/gcc-8.4.0/gcc-8.4.0.tar.xz | tar -xJf - + else + curl -SL https://ftp.gnu.org/gnu/gcc/gcc-8.4.0/gcc-8.4.0.tar.xz | tar -xJf - + fi CFLAGS="-fPIC" CXXFLAGS="-fPIC" CXXFLAGS_FOR_TARGET="-fPIC" @@ -544,7 +609,11 @@ elif [[ "$__CodeName" == "illumos" ]]; then fi BaseUrl="$BaseUrl/packages/SmartOS/trunk/${__illumosArch}/All" echo "Downloading manifest" - wget "$BaseUrl" + if [[ "$__hasWget" == 1 ]]; then + wget "$BaseUrl" + else + curl -SLO "$BaseUrl" + fi echo "Downloading dependencies." read -ra array <<<"$__IllumosPackages" for package in "${array[@]}"; do @@ -552,7 +621,11 @@ elif [[ "$__CodeName" == "illumos" ]]; then # find last occurrence of package in listing and extract its name package="$(sed -En '/.*href="('"$package"'-[0-9].*).tgz".*/h;$!d;g;s//\1/p' All)" echo "Resolved name '$package'" - wget "$BaseUrl"/"$package".tgz + if [[ "$__hasWget" == 1 ]]; then + wget "$BaseUrl"/"$package".tgz + else + curl -SLO "$BaseUrl"/"$package".tgz + fi ar -x "$package".tgz tar --skip-old-files -xzf "$package".tmp.tg* -C "$__RootfsDir" 2>/dev/null done @@ -561,10 +634,17 @@ elif [[ "$__CodeName" == "illumos" ]]; then rm -rf "$__RootfsDir"/{tmp,+*} mkdir -p "$__RootfsDir"/usr/include/net mkdir -p "$__RootfsDir"/usr/include/netpacket - wget -P "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/bpf.h - wget -P "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/dlt.h - wget -P "$__RootfsDir"/usr/include/netpacket https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/inet/sockmods/netpacket/packet.h - wget -P "$__RootfsDir"/usr/include/sys https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/sys/sdt.h + if [[ "$__hasWget" == 1 ]]; then + wget -P "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/bpf.h + wget -P "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/dlt.h + wget -P "$__RootfsDir"/usr/include/netpacket https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/inet/sockmods/netpacket/packet.h + wget -P "$__RootfsDir"/usr/include/sys https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/sys/sdt.h + else + curl -SLO --create-dirs --output-dir "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/bpf.h + curl -SLO --create-dirs --output-dir "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/dlt.h + curl -SLO --create-dirs --output-dir "$__RootfsDir"/usr/include/netpacket https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/inet/sockmods/netpacket/packet.h + curl -SLO --create-dirs --output-dir "$__RootfsDir"/usr/include/sys https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/sys/sdt.h + fi elif [[ "$__CodeName" == "haiku" ]]; then JOBS=${MAXJOBS:="$(getconf _NPROCESSORS_ONLN)"} @@ -574,9 +654,16 @@ elif [[ "$__CodeName" == "haiku" ]]; then mkdir "$__RootfsDir/tmp/download" + ensureDownloadTool + echo "Downloading Haiku package tool" - git clone https://github.com/haiku/haiku-toolchains-ubuntu --depth 1 $__RootfsDir/tmp/script - wget -O "$__RootfsDir/tmp/download/hosttools.zip" $($__RootfsDir/tmp/script/fetch.sh --hosttools) + git clone https://github.com/haiku/haiku-toolchains-ubuntu --depth 1 "$__RootfsDir/tmp/script" + if [[ "$__hasWget" == 1 ]]; then + wget -O "$__RootfsDir/tmp/download/hosttools.zip" "$("$__RootfsDir/tmp/script/fetch.sh" --hosttools)" + else + curl -SLo "$__RootfsDir/tmp/download/hosttools.zip" "$("$__RootfsDir/tmp/script/fetch.sh" --hosttools)" + fi + unzip -o "$__RootfsDir/tmp/download/hosttools.zip" -d "$__RootfsDir/tmp/bin" DepotBaseUrl="https://depot.haiku-os.org/__api/v2/pkg/get-pkg" @@ -589,14 +676,25 @@ elif [[ "$__CodeName" == "haiku" ]]; then echo "Downloading $package..." # API documented here: https://github.com/haiku/haikudepotserver/blob/master/haikudepotserver-api2/src/main/resources/api2/pkg.yaml#L60 # The schema here: https://github.com/haiku/haikudepotserver/blob/master/haikudepotserver-api2/src/main/resources/api2/pkg.yaml#L598 - hpkgDownloadUrl="$(wget -qO- --post-data='{"name":"'"$package"'","repositorySourceCode":"haikuports_'$__HaikuArch'","versionType":"LATEST","naturalLanguageCode":"en"}' \ - --header='Content-Type:application/json' "$DepotBaseUrl" | jq -r '.result.versions[].hpkgDownloadURL')" - wget -P "$__RootfsDir/tmp/download" "$hpkgDownloadUrl" + if [[ "$__hasWget" == 1 ]]; then + hpkgDownloadUrl="$(wget -qO- --post-data '{"name":"'"$package"'","repositorySourceCode":"haikuports_'$__HaikuArch'","versionType":"LATEST","naturalLanguageCode":"en"}' \ + --header 'Content-Type:application/json' "$DepotBaseUrl" | jq -r '.result.versions[].hpkgDownloadURL')" + wget -P "$__RootfsDir/tmp/download" "$hpkgDownloadUrl" + else + hpkgDownloadUrl="$(curl -sSL -XPOST --data '{"name":"'"$package"'","repositorySourceCode":"haikuports_'$__HaikuArch'","versionType":"LATEST","naturalLanguageCode":"en"}' \ + --header 'Content-Type:application/json' "$DepotBaseUrl" | jq -r '.result.versions[].hpkgDownloadURL')" + curl -SLO --create-dirs --output-dir "$__RootfsDir/tmp/download" "$hpkgDownloadUrl" + fi done for package in haiku haiku_devel; do echo "Downloading $package..." - hpkgVersion="$(wget -qO- $HpkgBaseUrl | sed -n 's/^.*version: "\([^"]*\)".*$/\1/p')" - wget -P "$__RootfsDir/tmp/download" "$HpkgBaseUrl/packages/$package-$hpkgVersion-1-$__HaikuArch.hpkg" + if [[ "$__hasWget" == 1 ]]; then + hpkgVersion="$(wget -qO- "$HpkgBaseUrl" | sed -n 's/^.*version: "\([^"]*\)".*$/\1/p')" + wget -P "$__RootfsDir/tmp/download" "$HpkgBaseUrl/packages/$package-$hpkgVersion-1-$__HaikuArch.hpkg" + else + hpkgVersion="$(curl -sSL "$HpkgBaseUrl" | sed -n 's/^.*version: "\([^"]*\)".*$/\1/p')" + curl -SLO --create-dirs --output-dir "$__RootfsDir/tmp/download" "$HpkgBaseUrl/packages/$package-$hpkgVersion-1-$__HaikuArch.hpkg" + fi done # Set up the sysroot @@ -609,7 +707,11 @@ elif [[ "$__CodeName" == "haiku" ]]; then # Download buildtools echo "Downloading Haiku buildtools" - wget -O "$__RootfsDir/tmp/download/buildtools.zip" $($__RootfsDir/tmp/script/fetch.sh --buildtools --arch=$__HaikuArch) + if [[ "$__hasWget" == 1 ]]; then + wget -O "$__RootfsDir/tmp/download/buildtools.zip" "$("$__RootfsDir/tmp/script/fetch.sh" --buildtools --arch=$__HaikuArch)" + else + curl -SLo "$__RootfsDir/tmp/download/buildtools.zip" "$("$__RootfsDir/tmp/script/fetch.sh" --buildtools --arch=$__HaikuArch)" + fi unzip -o "$__RootfsDir/tmp/download/buildtools.zip" -d "$__RootfsDir" # Cleaning up temporary files @@ -622,10 +724,12 @@ elif [[ -n "$__CodeName" ]]; then __Keyring="$__Keyring --force-check-gpg" fi + # shellcheck disable=SC2086 debootstrap "--variant=minbase" $__Keyring --arch "$__UbuntuArch" "$__CodeName" "$__RootfsDir" "$__UbuntuRepo" cp "$__CrossDir/$__BuildArch/sources.list.$__CodeName" "$__RootfsDir/etc/apt/sources.list" chroot "$__RootfsDir" apt-get update chroot "$__RootfsDir" apt-get -f -y install + # shellcheck disable=SC2086 chroot "$__RootfsDir" apt-get -y install $__UbuntuPackages chroot "$__RootfsDir" symlinks -cr /usr chroot "$__RootfsDir" apt-get clean @@ -643,6 +747,5 @@ elif [[ "$__Tizen" == "tizen" ]]; then ROOTFS_DIR="$__RootfsDir" "$__CrossDir/tizen-build-rootfs.sh" "$__BuildArch" else echo "Unsupported target platform." - usage; - exit 1 + usage fi diff --git a/eng/common/cross/toolchain.cmake b/eng/common/cross/toolchain.cmake index 3762640fdcf7..9a4e285a5ae3 100644 --- a/eng/common/cross/toolchain.cmake +++ b/eng/common/cross/toolchain.cmake @@ -382,6 +382,26 @@ if(TARGET_ARCH_NAME MATCHES "^(arm|armel|x86)$") endif() endif() +# Set C++ standard library options if specified +set(CLR_CMAKE_CXX_STANDARD_LIBRARY "" CACHE STRING "Standard library flavor to link against. Only supported with the Clang compiler.") +if (CLR_CMAKE_CXX_STANDARD_LIBRARY) + add_compile_options($<$:--stdlib=${CLR_CMAKE_CXX_STANDARD_LIBRARY}>) + add_link_options($<$:--stdlib=${CLR_CMAKE_CXX_STANDARD_LIBRARY}>) +endif() + +option(CLR_CMAKE_CXX_STANDARD_LIBRARY_STATIC "Statically link against the C++ standard library" OFF) +if(CLR_CMAKE_CXX_STANDARD_LIBRARY_STATIC) + add_link_options($<$:-static-libstdc++>) +endif() + +set(CLR_CMAKE_CXX_ABI_LIBRARY "" CACHE STRING "C++ ABI implementation library to link against. Only supported with the Clang compiler.") +if (CLR_CMAKE_CXX_ABI_LIBRARY) + # The user may specify the ABI library with the 'lib' prefix, like 'libstdc++'. Strip the prefix here so the linker finds the right library. + string(REGEX REPLACE "^lib(.+)" "\\1" CLR_CMAKE_CXX_ABI_LIBRARY ${CLR_CMAKE_CXX_ABI_LIBRARY}) + # We need to specify this as a linker-backend option as Clang will filter this option out when linking to libc++. + add_link_options("LINKER:-l${CLR_CMAKE_CXX_ABI_LIBRARY}") +endif() + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/eng/common/native/init-compiler.sh b/eng/common/native/init-compiler.sh index afdeb7a4d54a..ccd3a17268e2 100644 --- a/eng/common/native/init-compiler.sh +++ b/eng/common/native/init-compiler.sh @@ -64,7 +64,7 @@ if [ -z "$CLR_CC" ]; then 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="18 17 16 15 14 13 12 11 10 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5" - elif [ "$compiler" = "gcc" ]; then versions="13 12 11 10 9 8 7 6 5 4.9"; fi + elif [ "$compiler" = "gcc" ]; then versions="14 13 12 11 10 9 8 7 6 5 4.9"; fi for version in $versions; do _major="${version%%.*}" diff --git a/eng/common/native/init-distro-rid.sh b/eng/common/native/init-distro-rid.sh index 228be0b15986..83ea7aab0e08 100644 --- a/eng/common/native/init-distro-rid.sh +++ b/eng/common/native/init-distro-rid.sh @@ -20,10 +20,6 @@ getNonPortableDistroRid() # shellcheck disable=SC1091 if [ -e "${rootfsDir}/etc/os-release" ]; then . "${rootfsDir}/etc/os-release" - if [ "${ID}" = "rhel" ] || [ "${ID}" = "rocky" ] || [ "${ID}" = "alpine" ] || [ "${ID}" = "ol" ]; then - VERSION_ID="${VERSION_ID%.*}" # Remove the last version digit for these distros - fi - if echo "${VERSION_ID:-}" | grep -qE '^([[:digit:]]|\.)+$'; then nonPortableRid="${ID}.${VERSION_ID}-${targetArch}" else @@ -48,19 +44,7 @@ getNonPortableDistroRid() nonPortableRid="android.$__android_sdk_version-${targetArch}" elif [ "$targetOs" = "illumos" ]; then __uname_version=$(uname -v) - case "$__uname_version" in - omnios-*) - __omnios_major_version=$(echo "$__uname_version" | cut -c9-10) - nonPortableRid="omnios.$__omnios_major_version-${targetArch}" - ;; - joyent_*) - __smartos_major_version=$(echo "$__uname_version" | cut -c9-10) - nonPortableRid="smartos.$__smartos_major_version-${targetArch}" - ;; - *) - nonPortableRid="illumos-${targetArch}" - ;; - esac + nonPortableRid="illumos-${targetArch}" elif [ "$targetOs" = "solaris" ]; then __uname_version=$(uname -v) __solaris_major_version=$(echo "$__uname_version" | cut -d'.' -f1) diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1 index 091023970f1c..aab40de3fd9a 100644 --- a/eng/common/sdk-task.ps1 +++ b/eng/common/sdk-task.ps1 @@ -64,7 +64,7 @@ try { $GlobalJson.tools | Add-Member -Name "vs" -Value (ConvertFrom-Json "{ `"version`": `"16.5`" }") -MemberType NoteProperty } if( -not ($GlobalJson.tools.PSObject.Properties.Name -match "xcopy-msbuild" )) { - $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.8.5" -MemberType NoteProperty + $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.10.0-pre.4.0" -MemberType NoteProperty } if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true diff --git a/eng/common/template-guidance.md b/eng/common/template-guidance.md new file mode 100644 index 000000000000..c114bc28dcb9 --- /dev/null +++ b/eng/common/template-guidance.md @@ -0,0 +1,137 @@ +# Overview + +Arcade provides templates for public (`/templates`) and 1ES pipeline templates (`/templates-official`) scenarios. Pipelines which are required to be managed by 1ES pipeline templates should reference `/templates-offical`, all other pipelines may reference `/templates`. + +## How to use + +Basic guidance is: + +- 1ES Pipeline Template or 1ES Microbuild template runs should reference `eng/common/templates-official`. Any internal production-graded pipeline should use these templates. + +- All other runs should reference `eng/common/templates`. + +See [azure-pipelines.yml](../../azure-pipelines.yml) (templates-official example) or [azure-pipelines-pr.yml](../../azure-pipelines-pr.yml) (templates example) for examples. + +#### The `templateIs1ESManaged` parameter + +The `templateIs1ESManaged` is available on most templates and affects which of the variants is used for nested templates. See [Development Notes](#development-notes) below for more information on the `templateIs1ESManaged1 parameter. + +- For templates under `job/`, `jobs/`, `steps`, or `post-build/`, this parameter must be explicitly set. + +## Multiple outputs + +1ES pipeline templates impose a policy where every publish artifact execution results in additional security scans being injected into your pipeline. When using `templates-official/jobs/jobs.yml`, Arcade reduces the number of additional security injections by gathering all publishing outputs into the [Build.ArtifactStagingDirectory](https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#build-variables-devops-services), and utilizing the [outputParentDirectory](https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/1es-pipeline-templates/features/outputs#multiple-outputs) feature of 1ES pipeline templates. When implementing your pipeline, if you ensure publish artifacts are located in the `$(Build.ArtifactStagingDirectory)`, and utilize the 1ES provided template context, then you can reduce the number of security scans for your pipeline. + +Example: +``` yaml +# azure-pipelines.yml +extends: + template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate + parameters: + stages: + - stage: build + jobs: + - template: /eng/common/templates-official/jobs/jobs.yml@self + parameters: + # 1ES makes use of outputs to reduce security task injection overhead + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Publish logs from source' + continueOnError: true + condition: always() + targetPath: $(Build.ArtifactStagingDirectory)/artifacts/log + artifactName: Logs + jobs: + - job: Windows + steps: + - script: echo "friendly neighborhood" > artifacts/marvel/spiderman.txt + # copy build outputs to artifact staging directory for publishing + - task: CopyFiles@2 + displayName: Gather build output + inputs: + SourceFolder: '$(Build.SourcesDirectory)/artifacts/marvel' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/marvel' +``` + +Note: Multiple outputs are ONLY applicable to 1ES PT publishing (only usable when referencing `templates-official`). + +# Development notes + +**Folder / file structure** + +``` text +eng\common\ + [templates || templates-official]\ + job\ + job.yml (shim + artifact publishing logic) + onelocbuild.yml (shim) + publish-build-assets.yml (shim) + source-build.yml (shim) + source-index-stage1.yml (shim) + jobs\ + codeql-build.yml (shim) + jobs.yml (shim) + source-build.yml (shim) + post-build\ + post-build.yml (shim) + trigger-subscription.yml (shim) + common-variabls.yml (shim) + setup-maestro-vars.yml (shim) + steps\ + publish-build-artifacts.yml (logic) + publish-pipeline-artifacts.yml (logic) + add-build-channel.yml (shim) + component-governance.yml (shim) + generate-sbom.yml (shim) + publish-logs.yml (shim) + retain-build.yml (shim) + send-to-helix.yml (shim) + source-build.yml (shim) + variables\ + pool-providers.yml (logic + redirect) # templates/variables/pool-providers.yml will redirect to templates-official/variables/pool-providers.yml if you are running in the internal project + sdl-variables.yml (logic) + core-templates\ + job\ + job.yml (logic) + onelocbuild.yml (logic) + publish-build-assets.yml (logic) + source-build.yml (logic) + source-index-stage1.yml (logic) + jobs\ + codeql-build.yml (logic) + jobs.yml (logic) + source-build.yml (logic) + post-build\ + common-variabls.yml (logic) + post-build.yml (logic) + setup-maestro-vars.yml (logic) + trigger-subscription.yml (logic) + steps\ + add-build-to-channel.yml (logic) + component-governance.yml (logic) + generate-sbom.yml (logic) + publish-build-artifacts.yml (redirect) + publish-logs.yml (logic) + publish-pipeline-artifacts.yml (redirect) + retain-build.yml (logic) + send-to-helix.yml (logic) + source-build.yml (logic) + variables\ + pool-providers.yml (redirect) +``` + +In the table above, a file is designated as "shim", "logic", or "redirect". + +- shim - represents a yaml file which is an intermediate step between pipeline logic and .Net Core Engineering's templates (`core-templates`) and defines the `is1ESPipeline` parameter value. + +- logic - represents actual base template logic. + +- redirect- represents a file in `core-templates` which redirects to the "logic" file in either `templates` or `templates-official`. + +Logic for Arcade's templates live **primarily** in the `core-templates` folder. The exceptions to the location of the logic files are around artifact publishing, which is handled differently between 1es pipeline templates and standard templates. `templates` and `templates-official` provide shim entry points which redirect to `core-templates` while also defining the `is1ESPipeline` parameter. If a shim is referenced in `templates`, then `is1ESPipeline` is set to `false`. If a shim is referenced in `templates-official`, then `is1ESPipeline` is set to `true`. + +Within `templates` and `templates-official`, the templates at the "stages", and "jobs" / "job" level have been replaced with shims. Templates at the "steps" and "variables" level are typically too granular to be replaced with shims and instead persist logic which is directly applicable to either scenario. + +Within `core-templates`, there are a handful of places where logic is dependent on which shim entry point was used. In those places, we redirect back to the respective logic file in `templates` or `templates-official`. diff --git a/eng/common/templates-official/job/job.yml b/eng/common/templates-official/job/job.yml index c63e17e863ed..4724e9aaa809 100644 --- a/eng/common/templates-official/job/job.yml +++ b/eng/common/templates-official/job/job.yml @@ -1,264 +1,62 @@ -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - -parameters: -# Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - cancelTimeoutInMinutes: '' - condition: '' - container: '' - continueOnError: false - dependsOn: '' - displayName: '' - pool: '' - steps: [] - strategy: '' - timeoutInMinutes: '' - variables: [] - workspace: '' - templateContext: '' - -# Job base template specific parameters - # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md - artifacts: '' - enableMicrobuild: false - enablePublishBuildArtifacts: false - enablePublishBuildAssets: false - enablePublishTestResults: false - enablePublishUsingPipelines: false - enableBuildRetry: false - disableComponentGovernance: '' - componentGovernanceIgnoreDirectories: '' - mergeTestResults: false - testRunTitle: '' - testResultsFormat: '' - name: '' - preSteps: [] - runAsPublic: false -# Sbom related params - enableSbom: true - PackageVersion: 7.0.0 - BuildDropPath: '$(Build.SourcesDirectory)/artifacts' - jobs: -- job: ${{ parameters.name }} - - ${{ if ne(parameters.cancelTimeoutInMinutes, '') }}: - cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }} - - ${{ if ne(parameters.condition, '') }}: - condition: ${{ parameters.condition }} - - ${{ if ne(parameters.container, '') }}: - container: ${{ parameters.container }} - - ${{ if ne(parameters.continueOnError, '') }}: - continueOnError: ${{ parameters.continueOnError }} - - ${{ if ne(parameters.dependsOn, '') }}: - dependsOn: ${{ parameters.dependsOn }} - - ${{ if ne(parameters.displayName, '') }}: - displayName: ${{ parameters.displayName }} - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - - ${{ if ne(parameters.strategy, '') }}: - strategy: ${{ parameters.strategy }} - - ${{ if ne(parameters.timeoutInMinutes, '') }}: - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - - ${{ if ne(parameters.templateContext, '') }}: - templateContext: ${{ parameters.templateContext }} - - variables: - - ${{ if ne(parameters.enableTelemetry, 'false') }}: - - name: DOTNET_CLI_TELEMETRY_PROFILE - value: '$(Build.Repository.Uri)' - - ${{ if eq(parameters.enableRichCodeNavigation, 'true') }}: - - name: EnableRichCodeNavigation - value: 'true' - # Retry signature validation up to three times, waiting 2 seconds between attempts. - # See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3028#retry-untrusted-root-failures - - name: NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY - value: 3,2000 - - ${{ each variable in parameters.variables }}: - # handle name-value variable syntax - # example: - # - name: [key] - # value: [value] - - ${{ if ne(variable.name, '') }}: - - name: ${{ variable.name }} - value: ${{ variable.value }} - - # handle variable groups - - ${{ if ne(variable.group, '') }}: - - group: ${{ variable.group }} - - # handle template variable syntax - # example: - # - template: path/to/template.yml - # parameters: - # [key]: [value] - - ${{ if ne(variable.template, '') }}: - - template: ${{ variable.template }} - ${{ if ne(variable.parameters, '') }}: - parameters: ${{ variable.parameters }} - - # handle key-value variable syntax. - # example: - # - [key]: [value] - - ${{ if and(eq(variable.name, ''), eq(variable.group, ''), eq(variable.template, '')) }}: - - ${{ each pair in variable }}: - - name: ${{ pair.key }} - value: ${{ pair.value }} - - # DotNet-HelixApi-Access provides 'HelixApiAccessToken' for internal builds - - ${{ if and(eq(parameters.enableTelemetry, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: DotNet-HelixApi-Access - - ${{ if ne(parameters.workspace, '') }}: - workspace: ${{ parameters.workspace }} - - steps: - - ${{ if ne(parameters.preSteps, '') }}: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - task: MicroBuildSigningPlugin@4 - displayName: Install MicroBuild plugin - inputs: - signType: $(_SignType) - zipSources: false - feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json - env: - TeamName: $(_TeamName) - MicroBuildOutputFolderOverride: '$(Agent.TempDirectory)' - continueOnError: ${{ parameters.continueOnError }} - condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - - - ${{ if and(eq(parameters.runAsPublic, 'false'), eq(variables['System.TeamProject'], 'internal')) }}: - - task: NuGetAuthenticate@1 - - - ${{ if and(ne(parameters.artifacts.download, 'false'), ne(parameters.artifacts.download, '')) }}: - - task: DownloadPipelineArtifact@2 - inputs: - buildType: current - artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} - targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} - itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} - - - ${{ each step in parameters.steps }}: - - ${{ step }} - - - ${{ if eq(parameters.enableRichCodeNavigation, true) }}: - - task: RichCodeNavIndexer@0 - displayName: RichCodeNav Upload - inputs: - languages: ${{ coalesce(parameters.richCodeNavigationLanguage, 'csharp') }} - environment: ${{ coalesce(parameters.richCodeNavigationEnvironment, 'internal') }} - richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin - uploadRichNavArtifacts: ${{ coalesce(parameters.richCodeNavigationUploadArtifacts, false) }} - continueOnError: true - - - template: /eng/common/templates-official/steps/component-governance.yml - parameters: - ${{ if eq(parameters.disableComponentGovernance, '') }}: - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: - disableComponentGovernance: false - ${{ else }}: - disableComponentGovernance: true - ${{ else }}: - disableComponentGovernance: ${{ parameters.disableComponentGovernance }} - componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: MicroBuildCleanup@1 - displayName: Execute Microbuild cleanup tasks - condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - env: - TeamName: $(_TeamName) - - - ${{ if ne(parameters.artifacts.publish, '') }}: - - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: - - task: CopyFiles@2 - displayName: Gather binaries for publish to artifacts - inputs: - SourceFolder: 'artifacts/bin' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' - - task: CopyFiles@2 - displayName: Gather packages for publish to artifacts - inputs: - SourceFolder: 'artifacts/packages' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish pipeline artifacts - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} - continueOnError: true - condition: always() - - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: - - task: 1ES.PublishPipelineArtifact@1 - inputs: - targetPath: 'artifacts/log' - artifactName: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)') }} - displayName: 'Publish logs' - continueOnError: true - condition: always() - - - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} - continueOnError: true - condition: always() - - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'xunit')) }}: - - task: PublishTestResults@2 - displayName: Publish XUnit Test Results - inputs: - testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'vstest')) }}: - - task: PublishTestResults@2 - displayName: Publish TRX Test Results - inputs: - testResultsFormat: 'VSTest' - testResultsFiles: '*.trx' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: - - template: /eng/common/templates-official/steps/generate-sbom.yml - parameters: - PackageVersion: ${{ parameters.packageVersion}} - BuildDropPath: ${{ parameters.buildDropPath }} - IgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableBuildRetry, 'true') }}: - - task: 1ES.PublishPipelineArtifact@1 - inputs: - targetPath: '$(Build.SourcesDirectory)\eng\common\BuildConfiguration' - artifactName: 'BuildConfiguration' - displayName: 'Publish build retry configuration' - continueOnError: true \ No newline at end of file +- template: /eng/common/core-templates/job/job.yml + parameters: + is1ESPipeline: true + + # publish artifacts + # for 1ES managed templates, use the templateContext.output to handle multiple outputs. + templateContext: + outputParentDirectory: $(Build.ArtifactStagingDirectory) + outputs: + - ${{ if ne(parameters.artifacts.publish, '') }}: + - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: + - output: buildArtifacts + displayName: Publish pipeline artifacts + PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' + ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} + condition: always() + continueOnError: true + - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: + - output: pipelineArtifact + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/log' + artifactName: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)_Attempt$(System.JobAttempt)') }} + displayName: 'Publish logs' + continueOnError: true + condition: always() + + - ${{ if eq(parameters.enablePublishBuildArtifacts, true) }}: + - output: buildArtifacts + displayName: Publish Logs + PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' + publishLocation: Container + ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} + continueOnError: true + condition: always() + + - ${{ if eq(parameters.enableBuildRetry, 'true') }}: + - output: pipelineArtifact + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/eng/common/BuildConfiguration' + artifactName: 'BuildConfiguration' + displayName: 'Publish build retry configuration' + continueOnError: true + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: + - output: pipelineArtifact + displayName: Publish SBOM manifest + continueOnError: true + targetPath: $(Build.ArtifactStagingDirectory)/sbom + artifactName: $(ARTIFACT_NAME) + + # add any outputs provided via root yaml + - ${{ if ne(parameters.templateContext.outputs, '') }}: + - ${{ each output in parameters.templateContext.outputs }}: + - ${{ output }} + + # add any remaining templateContext properties + ${{ each context in parameters.templateContext }}: + ${{ if and(ne(context.key, 'outputParentDirectory'), ne(context.key, 'outputs')) }}: + ${{ context.key }}: ${{ context.value }} + + ${{ each parameter in parameters }}: + ${{ if and(ne(parameter.key, 'templateContext'), ne(parameter.key, 'is1ESPipeline')) }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/onelocbuild.yml b/eng/common/templates-official/job/onelocbuild.yml index ba9ba4930329..0f0c514b912d 100644 --- a/eng/common/templates-official/job/onelocbuild.yml +++ b/eng/common/templates-official/job/onelocbuild.yml @@ -1,112 +1,7 @@ -parameters: - # Optional: dependencies of the job - dependsOn: '' - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: '' - - CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex - GithubPat: $(BotAccount-dotnet-bot-repo-PAT) - - SourcesDirectory: $(Build.SourcesDirectory) - CreatePr: true - AutoCompletePr: false - ReusePr: true - UseLfLineEndings: true - UseCheckedInLocProjectJson: false - SkipLocProjectJsonGeneration: false - LanguageSet: VS_Main_Languages - LclSource: lclFilesInRepo - LclPackageId: '' - RepoType: gitHub - GitHubOrg: dotnet - MirrorRepo: '' - MirrorBranch: main - condition: '' - JobNameSuffix: '' - jobs: -- job: OneLocBuild${{ parameters.JobNameSuffix }} - - dependsOn: ${{ parameters.dependsOn }} - - displayName: OneLocBuild${{ parameters.JobNameSuffix }} - - variables: - - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat - - name: _GenerateLocProjectArguments - value: -SourcesDirectory ${{ parameters.SourcesDirectory }} - -LanguageSet "${{ parameters.LanguageSet }}" - -CreateNeutralXlfs - - ${{ if eq(parameters.UseCheckedInLocProjectJson, 'true') }}: - - name: _GenerateLocProjectArguments - value: ${{ variables._GenerateLocProjectArguments }} -UseCheckedInLocProjectJson - - template: /eng/common/templates-official/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022-pt - os: windows - - steps: - - ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}: - - task: Powershell@2 - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1 - arguments: $(_GenerateLocProjectArguments) - displayName: Generate LocProject.json - condition: ${{ parameters.condition }} - - - task: OneLocBuild@2 - displayName: OneLocBuild - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - locProj: eng/Localize/LocProject.json - outDir: $(Build.ArtifactStagingDirectory) - lclSource: ${{ parameters.LclSource }} - lclPackageId: ${{ parameters.LclPackageId }} - isCreatePrSelected: ${{ parameters.CreatePr }} - isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }} - ${{ if eq(parameters.CreatePr, true) }}: - isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - isShouldReusePrSelected: ${{ parameters.ReusePr }} - packageSourceAuth: patAuth - patVariable: ${{ parameters.CeapexPat }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - repoType: ${{ parameters.RepoType }} - gitHubPatVariable: "${{ parameters.GithubPat }}" - ${{ if ne(parameters.MirrorRepo, '') }}: - isMirrorRepoSelected: true - gitHubOrganization: ${{ parameters.GitHubOrg }} - mirrorRepo: ${{ parameters.MirrorRepo }} - mirrorBranch: ${{ parameters.MirrorBranch }} - condition: ${{ parameters.condition }} - - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish Localization Files - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/loc' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} +- template: /eng/common/core-templates/job/onelocbuild.yml + parameters: + is1ESPipeline: true - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish LocProject.json - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/Localize/' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} \ No newline at end of file + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/publish-build-assets.yml b/eng/common/templates-official/job/publish-build-assets.yml index 38340d3e3861..d667a70e8de7 100644 --- a/eng/common/templates-official/job/publish-build-assets.yml +++ b/eng/common/templates-official/job/publish-build-assets.yml @@ -1,159 +1,7 @@ -parameters: - configuration: 'Debug' - - # Optional: condition for the job to run - condition: '' - - # Optional: 'true' if future jobs should run even if this job fails - continueOnError: false - - # Optional: dependencies of the job - dependsOn: '' - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: {} - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishUsingPipelines: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishAssetsImmediately: false - - artifactsPublishingAdditionalParameters: '' - - signingValidationAdditionalParameters: '' - jobs: -- job: Asset_Registry_Publish - - dependsOn: ${{ parameters.dependsOn }} - timeoutInMinutes: 150 - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - displayName: Publish Assets - ${{ else }}: - displayName: Publish to Build Asset Registry - - variables: - - template: /eng/common/templates-official/variables/pool-providers.yml - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: Publish-Build-Assets - - group: AzureDevOps-Artifact-Feeds-Pats - - name: runCodesignValidationInjection - value: false - # unconditional - needed for logs publishing (redactor tool version) - - template: /eng/common/templates-official/post-build/common-variables.yml - - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: NetCore1ESPool-Publishing-Internal - image: windows.vs2019.amd64 - os: windows - steps: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - checkout: self - fetchDepth: 3 - clean: true - - - task: DownloadBuildArtifacts@0 - displayName: Download artifact - inputs: - artifactName: AssetManifests - downloadPath: '$(Build.StagingDirectory)/Download' - checkDownloadedFiles: true - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: NuGetAuthenticate@1 - - - task: PowerShell@2 - displayName: Publish Build Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishBuildAssets -restore -msbuildEngine dotnet - /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' - /p:BuildAssetRegistryToken=$(MaestroAccessToken) - /p:MaestroApiEndpoint=https://maestro.dot.net - /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} - /p:OfficialBuildId=$(Build.BuildNumber) - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: powershell@2 - displayName: Create ReleaseConfigs Artifact - inputs: - targetType: inline - script: | - New-Item -Path "$(Build.StagingDirectory)/ReleaseConfigs" -ItemType Directory -Force - $filePath = "$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt" - Add-Content -Path $filePath -Value $(BARBuildId) - Add-Content -Path $filePath -Value "$(DefaultChannels)" - Add-Content -Path $filePath -Value $(IsStableBuild) - - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish ReleaseConfigs Artifact - inputs: - PathtoPublish: '$(Build.StagingDirectory)/ReleaseConfigs' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - task: powershell@2 - displayName: Check if SymbolPublishingExclusionsFile.txt exists - inputs: - targetType: inline - script: | - $symbolExclusionfile = "$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt" - if(Test-Path -Path $symbolExclusionfile) - { - Write-Host "SymbolExclusionFile exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]true" - } - else{ - Write-Host "Symbols Exclusion file does not exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]false" - } - - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish SymbolPublishingExclusionsFile Artifact - condition: eq(variables['SymbolExclusionFile'], 'true') - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - - template: /eng/common/templates-official/post-build/setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: PowerShell@2 - displayName: Publish Using Darc - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion 3 - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' - -MaestroToken '$(MaestroApiAccessToken)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' +- template: /eng/common/core-templates/job/publish-build-assets.yml + parameters: + is1ESPipeline: true - - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: - - template: /eng/common/templates-official/steps/publish-logs.yml - parameters: - JobLabel: 'Publish_Artifacts_Logs' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/source-build.yml b/eng/common/templates-official/job/source-build.yml index 50f04e642a35..1a480034b678 100644 --- a/eng/common/templates-official/job/source-build.yml +++ b/eng/common/templates-official/job/source-build.yml @@ -1,67 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. The template produces a server job with a - # default ID 'Source_Build_Complete' to put in a dependency list if necessary. - - # Specifies the prefix for source-build jobs added to pipeline. Use this if disambiguation needed. - jobNamePrefix: 'Source_Build' - - # Defines the platform on which to run the job. By default, a linux-x64 machine, suitable for - # managed-only repositories. This is an object with these properties: - # - # name: '' - # The name of the job. This is included in the job ID. - # targetRID: '' - # The name of the target RID to use, instead of the one auto-detected by Arcade. - # nonPortable: false - # Enables non-portable mode. This means a more specific RID (e.g. fedora.32-x64 rather than - # linux-x64), and compiling against distro-provided packages rather than portable ones. - # skipPublishValidation: false - # Disables publishing validation. By default, a check is performed to ensure no packages are - # published by source-build. - # container: '' - # A container to use. Runs in docker. - # pool: {} - # A pool to use. Runs directly on an agent. - # buildScript: '' - # Specifies the build script to invoke to perform the build in the repo. The default - # './build.sh' should work for typical Arcade repositories, but this is customizable for - # difficult situations. - # jobProperties: {} - # A list of job properties to inject at the top level, for potential extensibility beyond - # container and pool. - platform: {} - jobs: -- job: ${{ parameters.jobNamePrefix }}_${{ parameters.platform.name }} - displayName: Source-Build (${{ parameters.platform.name }}) - - ${{ each property in parameters.platform.jobProperties }}: - ${{ property.key }}: ${{ property.value }} - - ${{ if ne(parameters.platform.container, '') }}: - container: ${{ parameters.platform.container }} - - ${{ if eq(parameters.platform.pool, '') }}: - # The default VM host AzDO pool. This should be capable of running Docker containers: almost all - # source-build builds run in Docker, including the default managed platform. - # /eng/common/templates-official/variables/pool-providers.yml can't be used here (some customers declare variables already), so duplicate its logic - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] - demands: ImageOverride -equals build.ubuntu.1804.amd64 - - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] - image: 1es-mariner-2-pt - os: linux - - ${{ if ne(parameters.platform.pool, '') }}: - pool: ${{ parameters.platform.pool }} - - workspace: - clean: all +- template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: true - steps: - - template: /eng/common/templates-official/steps/source-build.yml - parameters: - platform: ${{ parameters.platform }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/source-index-stage1.yml b/eng/common/templates-official/job/source-index-stage1.yml index 53a9ef51fd82..6d5ead316f92 100644 --- a/eng/common/templates-official/job/source-index-stage1.yml +++ b/eng/common/templates-official/job/source-index-stage1.yml @@ -1,67 +1,7 @@ -parameters: - runAsPublic: false - sourceIndexPackageVersion: 1.0.1-20240129.2 - sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json - sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" - preSteps: [] - binlogPath: artifacts/log/Debug/Build.binlog - condition: '' - dependsOn: '' - pool: '' - jobs: -- job: SourceIndexStage1 - dependsOn: ${{ parameters.dependsOn }} - condition: ${{ parameters.condition }} - variables: - - name: SourceIndexPackageVersion - value: ${{ parameters.sourceIndexPackageVersion }} - - name: SourceIndexPackageSource - value: ${{ parameters.sourceIndexPackageSource }} - - name: BinlogPath - value: ${{ parameters.binlogPath }} - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: source-dot-net stage1 variables - - template: /eng/common/templates-official/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $(DncEngPublicBuildPool) - image: windows.vs2022.amd64.open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $(DncEngInternalBuildPool) - image: windows.vs2022.amd64 - - steps: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - task: UseDotNet@2 - displayName: Use .NET 8 SDK - inputs: - packageType: sdk - version: 8.0.x - installationPath: $(Agent.TempDirectory)/dotnet - workingDirectory: $(Agent.TempDirectory) - - - script: | - $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - displayName: Download Tools - # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. - workingDirectory: $(Agent.TempDirectory) - - - script: ${{ parameters.sourceIndexBuildCommand }} - displayName: Build Repository - - - script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i $(BinlogPath) -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output - displayName: Process Binlog into indexable sln +- template: /eng/common/core-templates/job/source-index-stage1.yml + parameters: + is1ESPipeline: true - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) - displayName: Upload stage1 artifacts to source index - env: - BLOB_CONTAINER_URL: $(source-dot-net-stage1-blob-container-url) + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/jobs/codeql-build.yml b/eng/common/templates-official/jobs/codeql-build.yml index b68d3c2f3199..a726322ecfe0 100644 --- a/eng/common/templates-official/jobs/codeql-build.yml +++ b/eng/common/templates-official/jobs/codeql-build.yml @@ -1,31 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - jobs: -- template: /eng/common/templates-official/jobs/jobs.yml +- template: /eng/common/core-templates/jobs/codeql-build.yml parameters: - enableMicrobuild: false - enablePublishBuildArtifacts: false - enablePublishTestResults: false - enablePublishBuildAssets: false - enablePublishUsingPipelines: false - enableTelemetry: true + is1ESPipeline: true - variables: - - group: Publish-Build-Assets - # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in - # sync with the packages.config file. - - name: DefaultGuardianVersion - value: 0.109.0 - - name: GuardianPackagesConfigFile - value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config - - name: GuardianVersion - value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - - jobs: ${{ parameters.jobs }} - + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/jobs/jobs.yml b/eng/common/templates-official/jobs/jobs.yml index 857a0f8ba43e..007deddaea0f 100644 --- a/eng/common/templates-official/jobs/jobs.yml +++ b/eng/common/templates-official/jobs/jobs.yml @@ -1,97 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: Enable publishing using release pipelines - enablePublishUsingPipelines: false - - # Optional: Enable running the source-build jobs to build repo from source - enableSourceBuild: false - - # Optional: Parameters for source-build template. - # See /eng/common/templates-official/jobs/source-build.yml for options - sourceBuildParameters: [] - - graphFileGeneration: - # Optional: Enable generating the graph files at the end of the build - enabled: false - # Optional: Include toolset dependencies in the generated graph files - includeToolset: false - - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - - # Optional: Override automatically derived dependsOn value for "publish build assets" job - publishBuildAssetsDependsOn: '' - - # Optional: Publish the assets as soon as the publish to BAR stage is complete, rather doing so in a separate stage. - publishAssetsImmediately: false - - # Optional: If using publishAssetsImmediately and additional parameters are needed, can be used to send along additional parameters (normally sent to post-build.yml) - artifactsPublishingAdditionalParameters: '' - signingValidationAdditionalParameters: '' - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - enableSourceIndex: false - sourceIndexParams: {} - -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - jobs: -- ${{ each job in parameters.jobs }}: - - template: ../job/job.yml - parameters: - # pass along parameters - ${{ each parameter in parameters }}: - ${{ if ne(parameter.key, 'jobs') }}: - ${{ parameter.key }}: ${{ parameter.value }} - - # pass along job properties - ${{ each property in job }}: - ${{ if ne(property.key, 'job') }}: - ${{ property.key }}: ${{ property.value }} - - name: ${{ job.job }} - -- ${{ if eq(parameters.enableSourceBuild, true) }}: - - template: /eng/common/templates-official/jobs/source-build.yml - parameters: - allCompletedJobId: Source_Build_Complete - ${{ each parameter in parameters.sourceBuildParameters }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if eq(parameters.enableSourceIndex, 'true') }}: - - template: ../job/source-index-stage1.yml - parameters: - runAsPublic: ${{ parameters.runAsPublic }} - ${{ each parameter in parameters.sourceIndexParams }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: - - template: ../job/publish-build-assets.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - dependsOn: - - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.publishBuildAssetsDependsOn }}: - - ${{ job.job }} - - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.jobs }}: - - ${{ job.job }} - - ${{ if eq(parameters.enableSourceBuild, true) }}: - - Source_Build_Complete +- template: /eng/common/core-templates/jobs/jobs.yml + parameters: + is1ESPipeline: true - runAsPublic: ${{ parameters.runAsPublic }} - publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} - publishAssetsImmediately: ${{ parameters.publishAssetsImmediately }} - enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/jobs/source-build.yml b/eng/common/templates-official/jobs/source-build.yml index 08e5db9bb116..483e7b611f34 100644 --- a/eng/common/templates-official/jobs/source-build.yml +++ b/eng/common/templates-official/jobs/source-build.yml @@ -1,46 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. A job is created for each platform, as - # well as an optional server job that completes when all platform jobs complete. - - # The name of the "join" job for all source-build platforms. If set to empty string, the job is - # not included. Existing repo pipelines can use this job depend on all source-build jobs - # completing without maintaining a separate list of every single job ID: just depend on this one - # server job. By default, not included. Recommended name if used: 'Source_Build_Complete'. - allCompletedJobId: '' - - # See /eng/common/templates-official/job/source-build.yml - jobNamePrefix: 'Source_Build' - - # This is the default platform provided by Arcade, intended for use by a managed-only repo. - defaultManagedPlatform: - name: 'Managed' - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8' - - # Defines the platforms on which to run build jobs. One job is created for each platform, and the - # object in this array is sent to the job template as 'platform'. If no platforms are specified, - # one job runs on 'defaultManagedPlatform'. - platforms: [] - jobs: +- template: /eng/common/core-templates/jobs/source-build.yml + parameters: + is1ESPipeline: true -- ${{ if ne(parameters.allCompletedJobId, '') }}: - - job: ${{ parameters.allCompletedJobId }} - displayName: Source-Build Complete - pool: server - dependsOn: - - ${{ each platform in parameters.platforms }}: - - ${{ parameters.jobNamePrefix }}_${{ platform.name }} - - ${{ if eq(length(parameters.platforms), 0) }}: - - ${{ parameters.jobNamePrefix }}_${{ parameters.defaultManagedPlatform.name }} - -- ${{ each platform in parameters.platforms }}: - - template: /eng/common/templates-official/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ platform }} - -- ${{ if eq(length(parameters.platforms), 0) }}: - - template: /eng/common/templates-official/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ parameters.defaultManagedPlatform }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/post-build/common-variables.yml b/eng/common/templates-official/post-build/common-variables.yml index b9ede10bf099..c32fc49233f8 100644 --- a/eng/common/templates-official/post-build/common-variables.yml +++ b/eng/common/templates-official/post-build/common-variables.yml @@ -1,24 +1,8 @@ variables: - - group: Publish-Build-Assets +- template: /eng/common/core-templates/post-build/common-variables.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: true - # Whether the build is internal or not - - name: IsInternalBuild - value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} - - # Default Maestro++ API Endpoint and API Version - - name: MaestroApiEndPoint - value: "https://maestro.dot.net" - - name: MaestroApiAccessToken - value: $(MaestroAccessToken) - - name: MaestroApiVersion - value: "2020-02-20" - - - name: SourceLinkCLIVersion - value: 3.0.0 - - name: SymbolToolVersion - value: 1.0.1 - - name: BinlogToolVersion - value: 1.0.11 - - - name: runCodesignValidationInjection - value: false + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/post-build/post-build.yml b/eng/common/templates-official/post-build/post-build.yml index d286e956bdfa..2364c0fd4a52 100644 --- a/eng/common/templates-official/post-build/post-build.yml +++ b/eng/common/templates-official/post-build/post-build.yml @@ -1,285 +1,8 @@ -parameters: - # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. - # Publishing V1 is no longer supported - # Publishing V2 is no longer supported - # Publishing V3 is the default - - name: publishingInfraVersion - displayName: Which version of publishing should be used to promote the build definition? - type: number - default: 3 - values: - - 3 - - - name: BARBuildId - displayName: BAR Build Id - type: number - default: 0 - - - name: PromoteToChannelIds - displayName: Channel to promote BARBuildId to - type: string - default: '' - - - name: enableSourceLinkValidation - displayName: Enable SourceLink validation - type: boolean - default: false - - - name: enableSigningValidation - displayName: Enable signing validation - type: boolean - default: true - - - name: enableSymbolValidation - displayName: Enable symbol validation - type: boolean - default: false - - - name: enableNugetValidation - displayName: Enable NuGet validation - type: boolean - default: true - - - name: publishInstallersAndChecksums - displayName: Publish installers and checksums - type: boolean - default: true - - - name: SDLValidationParameters - type: object - default: - enable: false - publishGdn: false - continueOnError: false - params: '' - artifactNames: '' - downloadArtifacts: true - - # These parameters let the user customize the call to sdk-task.ps1 for publishing - # symbols & general artifacts as well as for signing validation - - name: symbolPublishingAdditionalParameters - displayName: Symbol publishing additional parameters - type: string - default: '' - - - name: artifactsPublishingAdditionalParameters - displayName: Artifact publishing additional parameters - type: string - default: '' - - - name: signingValidationAdditionalParameters - displayName: Signing validation additional parameters - type: string - default: '' - - # Which stages should finish execution before post-build stages start - - name: validateDependsOn - type: object - default: - - build - - - name: publishDependsOn - type: object - default: - - Validate - - # Optional: Call asset publishing rather than running in a separate stage - - name: publishAssetsImmediately - type: boolean - default: false - stages: -- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - - stage: Validate - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Validate Build Assets - variables: - - template: common-variables.yml - - template: /eng/common/templates-official/variables/pool-providers.yml - jobs: - - job: - displayName: NuGet Validation - condition: and(succeededOrFailed(), eq( ${{ parameters.enableNugetValidation }}, 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022-pt - os: windows - - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1 - arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ - -ToolDestinationPath $(Agent.BuildDirectory)/Extract/ - - - job: - displayName: Signing Validation - condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022-pt - os: windows - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - itemPattern: | - ** - !**/Microsoft.SourceBuild.Intermediate.*.nupkg - - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@1 - displayName: 'Authenticate to AzDO Feeds' - - # Signing validation will optionally work with the buildmanifest file which is downloaded from - # Azure DevOps above. - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task SigningValidation -restore -msbuildEngine vs - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' - /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' - ${{ parameters.signingValidationAdditionalParameters }} - - - template: ../steps/publish-logs.yml - parameters: - StageLabel: 'Validation' - JobLabel: 'Signing' - BinlogToolVersion: $(BinlogToolVersion) - - - job: - displayName: SourceLink Validation - condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022-pt - os: windows - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: BlobArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1 - arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/ - -ExtractPath $(Agent.BuildDirectory)/Extract/ - -GHRepoName $(Build.Repository.Name) - -GHCommit $(Build.SourceVersion) - -SourcelinkCliVersion $(SourceLinkCLIVersion) - continueOnError: true - -- ${{ if ne(parameters.publishAssetsImmediately, 'true') }}: - - stage: publish_using_darc - ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - dependsOn: ${{ parameters.publishDependsOn }} - ${{ else }}: - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Publish using Darc - variables: - - template: common-variables.yml - - template: /eng/common/templates-official/variables/pool-providers.yml - jobs: - - job: - displayName: Publish Using Darc - timeoutInMinutes: 120 - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: NetCore1ESPool-Publishing-Internal - image: windows.vs2019.amd64 - os: windows - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: NuGetAuthenticate@1 +- template: /eng/common/core-templates/post-build/post-build.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: true - - task: PowerShell@2 - displayName: Publish Using Darc - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' - -MaestroToken '$(MaestroApiAccessToken)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/post-build/setup-maestro-vars.yml b/eng/common/templates-official/post-build/setup-maestro-vars.yml index 0c87f149a4ad..024397d87864 100644 --- a/eng/common/templates-official/post-build/setup-maestro-vars.yml +++ b/eng/common/templates-official/post-build/setup-maestro-vars.yml @@ -1,70 +1,8 @@ -parameters: - BARBuildId: '' - PromoteToChannelIds: '' - steps: - - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Release Configs - inputs: - buildType: current - artifactName: ReleaseConfigs - checkDownloadedFiles: true - - - task: PowerShell@2 - name: setReleaseVars - displayName: Set Release Configs Vars - inputs: - targetType: inline - pwsh: true - script: | - try { - if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { - $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt - - $BarId = $Content | Select -Index 0 - $Channels = $Content | Select -Index 1 - $IsStableBuild = $Content | Select -Index 2 - - $AzureDevOpsProject = $Env:System_TeamProject - $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId - $AzureDevOpsBuildId = $Env:Build_BuildId - } - else { - $buildApiEndpoint = "${Env:MaestroApiEndPoint}/api/builds/${Env:BARBuildId}?api-version=${Env:MaestroApiVersion}" - - $apiHeaders = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $apiHeaders.Add('Accept', 'application/json') - $apiHeaders.Add('Authorization',"Bearer ${Env:MAESTRO_API_TOKEN}") - - $buildInfo = try { Invoke-WebRequest -Method Get -Uri $buildApiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - - $BarId = $Env:BARBuildId - $Channels = $Env:PromoteToMaestroChannels -split "," - $Channels = $Channels -join "][" - $Channels = "[$Channels]" - - $IsStableBuild = $buildInfo.stable - $AzureDevOpsProject = $buildInfo.azureDevOpsProject - $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId - $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId - } - - Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" - Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" - Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" +- template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: true - Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" - Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" - Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" - } - catch { - Write-Host $_ - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - exit 1 - } - env: - MAESTRO_API_TOKEN: $(MaestroApiAccessToken) - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/steps/add-build-to-channel.yml b/eng/common/templates-official/steps/add-build-to-channel.yml index f67a210d62f3..543dea8c6969 100644 --- a/eng/common/templates-official/steps/add-build-to-channel.yml +++ b/eng/common/templates-official/steps/add-build-to-channel.yml @@ -1,13 +1,7 @@ -parameters: - ChannelId: 0 - steps: -- task: PowerShell@2 - displayName: Add Build to Channel - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/add-build-to-channel.ps1 - arguments: -BuildId $(BARBuildId) - -ChannelId ${{ parameters.ChannelId }} - -MaestroApiAccessToken $(MaestroApiAccessToken) - -MaestroApiEndPoint $(MaestroApiEndPoint) - -MaestroApiVersion $(MaestroApiVersion) +- template: /eng/common/core-templates/steps/add-build-to-channel.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/component-governance.yml b/eng/common/templates-official/steps/component-governance.yml index 0ecec47b0c91..30bb3985ca2b 100644 --- a/eng/common/templates-official/steps/component-governance.yml +++ b/eng/common/templates-official/steps/component-governance.yml @@ -1,13 +1,7 @@ -parameters: - disableComponentGovernance: false - componentGovernanceIgnoreDirectories: '' - steps: -- ${{ if eq(parameters.disableComponentGovernance, 'true') }}: - - script: "echo ##vso[task.setvariable variable=skipComponentGovernanceDetection]true" - displayName: Set skipComponentGovernanceDetection variable -- ${{ if ne(parameters.disableComponentGovernance, 'true') }}: - - task: ComponentGovernanceComponentDetection@0 - continueOnError: true - inputs: - ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} \ No newline at end of file +- template: /eng/common/core-templates/steps/component-governance.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/generate-sbom.yml b/eng/common/templates-official/steps/generate-sbom.yml index 488b560e8ba4..9a89a4706d94 100644 --- a/eng/common/templates-official/steps/generate-sbom.yml +++ b/eng/common/templates-official/steps/generate-sbom.yml @@ -1,48 +1,7 @@ -# BuildDropPath - The root folder of the drop directory for which the manifest file will be generated. -# PackageName - The name of the package this SBOM represents. -# PackageVersion - The version of the package this SBOM represents. -# ManifestDirPath - The path of the directory where the generated manifest files will be placed -# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. - -parameters: - PackageVersion: 7.0.0 - BuildDropPath: '$(Build.SourcesDirectory)/artifacts' - PackageName: '.NET' - ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom - IgnoreDirectories: '' - sbomContinueOnError: true - steps: -- task: PowerShell@2 - displayName: Prep for SBOM generation in (Non-linux) - condition: or(eq(variables['Agent.Os'], 'Windows_NT'), eq(variables['Agent.Os'], 'Darwin')) - inputs: - filePath: ./eng/common/generate-sbom-prep.ps1 - arguments: ${{parameters.manifestDirPath}} - -# Chmodding is a workaround for https://github.com/dotnet/arcade/issues/8461 -- script: | - chmod +x ./eng/common/generate-sbom-prep.sh - ./eng/common/generate-sbom-prep.sh ${{parameters.manifestDirPath}} - displayName: Prep for SBOM generation in (Linux) - condition: eq(variables['Agent.Os'], 'Linux') - continueOnError: ${{ parameters.sbomContinueOnError }} - -- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 - displayName: 'Generate SBOM manifest' - continueOnError: ${{ parameters.sbomContinueOnError }} - inputs: - PackageName: ${{ parameters.packageName }} - BuildDropPath: ${{ parameters.buildDropPath }} - PackageVersion: ${{ parameters.packageVersion }} - ManifestDirPath: ${{ parameters.manifestDirPath }} - ${{ if ne(parameters.IgnoreDirectories, '') }}: - AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' - -- task: 1ES.PublishPipelineArtifact@1 - displayName: Publish SBOM manifest - continueOnError: ${{parameters.sbomContinueOnError}} - inputs: - targetPath: '${{parameters.manifestDirPath}}' - artifactName: $(ARTIFACT_NAME) +- template: /eng/common/core-templates/steps/generate-sbom.yml + parameters: + is1ESPipeline: true + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/publish-build-artifacts.yml b/eng/common/templates-official/steps/publish-build-artifacts.yml new file mode 100644 index 000000000000..100a3fc98493 --- /dev/null +++ b/eng/common/templates-official/steps/publish-build-artifacts.yml @@ -0,0 +1,41 @@ +parameters: +- name: displayName + type: string + default: 'Publish to Build Artifact' + +- name: condition + type: string + default: succeeded() + +- name: artifactName + type: string + +- name: pathToPublish + type: string + +- name: continueOnError + type: boolean + default: false + +- name: publishLocation + type: string + default: 'Container' + +- name: is1ESPipeline + type: boolean + default: true + +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates-official cannot be referenced from a non-1ES managed template': error +- task: 1ES.PublishBuildArtifacts@1 + displayName: ${{ parameters.displayName }} + condition: ${{ parameters.condition }} + ${{ if parameters.continueOnError }}: + continueOnError: ${{ parameters.continueOnError }} + inputs: + PublishLocation: ${{ parameters.publishLocation }} + PathtoPublish: ${{ parameters.pathToPublish }} + ${{ if parameters.artifactName }}: + ArtifactName: ${{ parameters.artifactName }} + diff --git a/eng/common/templates-official/steps/publish-logs.yml b/eng/common/templates-official/steps/publish-logs.yml index 84b2f559c56e..579fd531e94c 100644 --- a/eng/common/templates-official/steps/publish-logs.yml +++ b/eng/common/templates-official/steps/publish-logs.yml @@ -1,49 +1,7 @@ -parameters: - StageLabel: '' - JobLabel: '' - CustomSensitiveDataList: '' - # A default - in case value from eng/common/templates-official/post-build/common-variables.yml is not passed - BinlogToolVersion: '1.0.11' - steps: -- task: Powershell@2 - displayName: Prepare Binlogs to Upload - inputs: - targetType: inline - script: | - New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - continueOnError: true - condition: always() - -- task: PowerShell@2 - displayName: Redact Logs - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/redact-logs.ps1 - # For now this needs to have explicit list of all sensitive data. Taken from eng/publishing/v3/publish.yml - # Sensitive data can as well be added to $(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' - # If the file exists - sensitive data for redaction will be sourced from it - # (single entry per line, lines starting with '# ' are considered comments and skipped) - arguments: -InputPath '$(Build.SourcesDirectory)/PostBuildLogs' - -BinlogToolVersion ${{parameters.BinlogToolVersion}} - -TokensFilePath '$(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' - '$(publishing-dnceng-devdiv-code-r-build-re)' - '$(MaestroAccessToken)' - '$(dn-bot-all-orgs-artifact-feeds-rw)' - '$(akams-client-id)' - '$(akams-client-secret)' - '$(microsoft-symbol-server-pat)' - '$(symweb-symbol-server-pat)' - '$(dn-bot-all-orgs-build-rw-code-rw)' - ${{parameters.CustomSensitiveDataList}} - continueOnError: true - condition: always() - -- task: 1ES.PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/PostBuildLogs' - PublishLocation: Container - ArtifactName: PostBuildLogs - continueOnError: true - condition: always() +- template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/publish-pipeline-artifacts.yml b/eng/common/templates-official/steps/publish-pipeline-artifacts.yml new file mode 100644 index 000000000000..d71eb0c74398 --- /dev/null +++ b/eng/common/templates-official/steps/publish-pipeline-artifacts.yml @@ -0,0 +1,26 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: true + +- name: args + type: object + default: {} + +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates-official cannot be referenced from a non-1ES managed template': error +- task: 1ES.PublishPipelineArtifact@1 + displayName: ${{ coalesce(parameters.args.displayName, 'Publish to Build Artifact') }} + ${{ if parameters.args.condition }}: + condition: ${{ parameters.args.condition }} + ${{ else }}: + condition: succeeded() + ${{ if parameters.args.continueOnError }}: + continueOnError: ${{ parameters.args.continueOnError }} + inputs: + targetPath: ${{ parameters.args.targetPath }} + ${{ if parameters.args.artifactName }}: + artifactName: ${{ parameters.args.artifactName }} + ${{ if parameters.args.properties }}: + properties: ${{ parameters.args.properties }} \ No newline at end of file diff --git a/eng/common/templates-official/steps/retain-build.yml b/eng/common/templates-official/steps/retain-build.yml index 83d97a26a01f..5594551508a3 100644 --- a/eng/common/templates-official/steps/retain-build.yml +++ b/eng/common/templates-official/steps/retain-build.yml @@ -1,28 +1,7 @@ -parameters: - # Optional azure devops PAT with build execute permissions for the build's organization, - # only needed if the build that should be retained ran on a different organization than - # the pipeline where this template is executing from - Token: '' - # Optional BuildId to retain, defaults to the current running build - BuildId: '' - # Azure devops Organization URI for the build in the https://dev.azure.com/ format. - # Defaults to the organization the current pipeline is running on - AzdoOrgUri: '$(System.CollectionUri)' - # Azure devops project for the build. Defaults to the project the current pipeline is running on - AzdoProject: '$(System.TeamProject)' - steps: - - task: powershell@2 - inputs: - targetType: 'filePath' - filePath: eng/common/retain-build.ps1 - pwsh: true - arguments: > - -AzdoOrgUri: ${{parameters.AzdoOrgUri}} - -AzdoProject ${{parameters.AzdoProject}} - -Token ${{coalesce(parameters.Token, '$env:SYSTEM_ACCESSTOKEN') }} - -BuildId ${{coalesce(parameters.BuildId, '$env:BUILD_ID')}} - displayName: Enable permanent build retention - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - BUILD_ID: $(Build.BuildId) \ No newline at end of file +- template: /eng/common/core-templates/steps/retain-build.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/send-to-helix.yml b/eng/common/templates-official/steps/send-to-helix.yml index 68fa739c4ab2..6500f21bf845 100644 --- a/eng/common/templates-official/steps/send-to-helix.yml +++ b/eng/common/templates-official/steps/send-to-helix.yml @@ -1,93 +1,7 @@ -# Please remember to update the documentation if you make changes to these parameters! -parameters: - HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/ - HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' - HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number - HelixTargetQueues: '' # required -- semicolon-delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues - HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group - HelixProjectPath: 'eng/common/helixpublish.proj' # optional -- path to the project file to build relative to BUILD_SOURCESDIRECTORY - HelixProjectArguments: '' # optional -- arguments passed to the build command - HelixConfiguration: '' # optional -- additional property attached to a job - HelixPreCommands: '' # optional -- commands to run before Helix work item execution - HelixPostCommands: '' # optional -- commands to run after Helix work item execution - WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects - WorkItemCommand: '' # optional -- a command to execute on the payload; requires WorkItemDirectory; incompatible with XUnitProjects - WorkItemTimeout: '' # optional -- a timeout in TimeSpan.Parse-ready value (e.g. 00:02:00) for the work item command; requires WorkItemDirectory; incompatible with XUnitProjects - CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload - XUnitProjects: '' # optional -- semicolon-delimited list of XUnitProjects to parse and send to Helix; requires XUnitRuntimeTargetFramework, XUnitPublishTargetFramework, XUnitRunnerVersion, and IncludeDotNetCli=true - XUnitWorkItemTimeout: '' # optional -- the workitem timeout in seconds for all workitems created from the xUnit projects specified by XUnitProjects - XUnitPublishTargetFramework: '' # optional -- framework to use to publish your xUnit projects - XUnitRuntimeTargetFramework: '' # optional -- framework to use for the xUnit console runner - XUnitRunnerVersion: '' # optional -- version of the xUnit nuget package you wish to use on Helix; required for XUnitProjects - IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion - DotNetCliPackageType: '' # optional -- either 'sdk', 'runtime' or 'aspnetcore-runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." - IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set - HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting https://helix.int-dot.net ) - Creator: '' # optional -- if the build is external, use this to specify who is sending the job - DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO - condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() - continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false - steps: - - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' - displayName: ${{ parameters.DisplayNamePrefix }} (Windows) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog - displayName: ${{ parameters.DisplayNamePrefix }} (Unix) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} +- template: /eng/common/core-templates/steps/send-to-helix.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/source-build.yml b/eng/common/templates-official/steps/source-build.yml index 53ed57b6d48a..8f92c49e7b06 100644 --- a/eng/common/templates-official/steps/source-build.yml +++ b/eng/common/templates-official/steps/source-build.yml @@ -1,131 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. - - # This is a 'steps' template, and is intended for advanced scenarios where the existing build - # infra has a careful build methodology that must be followed. For example, a repo - # (dotnet/runtime) might choose to clone the GitHub repo only once and store it as a pipeline - # artifact for all subsequent jobs to use, to reduce dependence on a strong network connection to - # GitHub. Using this steps template leaves room for that infra to be included. - - # Defines the platform on which to run the steps. See 'eng/common/templates-official/job/source-build.yml' - # for details. The entire object is described in the 'job' template for simplicity, even though - # the usage of the properties on this object is split between the 'job' and 'steps' templates. - platform: {} - steps: -# Build. Keep it self-contained for simple reusability. (No source-build-specific job variables.) -- script: | - set -x - df -h - - # If building on the internal project, the artifact feeds variable may be available (usually only if needed) - # In that case, call the feed setup script to add internal feeds corresponding to public ones. - # In addition, add an msbuild argument to copy the WIP from the repo to the target build location. - # This is because SetupNuGetSources.sh will alter the current NuGet.config file, and we need to preserve those - # changes. - internalRestoreArgs= - if [ '$(dn-bot-dnceng-artifact-feeds-rw)' != '$''(dn-bot-dnceng-artifact-feeds-rw)' ]; then - # Temporarily work around https://github.com/dotnet/arcade/issues/7709 - chmod +x $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh - $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh $(Build.SourcesDirectory)/NuGet.config $(dn-bot-dnceng-artifact-feeds-rw) - internalRestoreArgs='/p:CopyWipIntoInnerSourceBuildRepo=true' - - # The 'Copy WIP' feature of source build uses git stash to apply changes from the original repo. - # This only works if there is a username/email configured, which won't be the case in most CI runs. - git config --get user.email - if [ $? -ne 0 ]; then - git config user.email dn-bot@microsoft.com - git config user.name dn-bot - fi - fi - - # If building on the internal project, the internal storage variable may be available (usually only if needed) - # In that case, add variables to allow the download of internal runtimes if the specified versions are not found - # in the default public locations. - internalRuntimeDownloadArgs= - if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then - internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://dotnetbuilds.blob.core.windows.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://dotnetbuilds.blob.core.windows.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' - fi - - buildConfig=Release - # Check if AzDO substitutes in a build config from a variable, and use it if so. - if [ '$(_BuildConfig)' != '$''(_BuildConfig)' ]; then - buildConfig='$(_BuildConfig)' - fi - - officialBuildArgs= - if [ '${{ and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}' = 'True' ]; then - officialBuildArgs='/p:DotNetPublishUsingPipelines=true /p:OfficialBuildId=$(BUILD.BUILDNUMBER)' - fi - - targetRidArgs= - if [ '${{ parameters.platform.targetRID }}' != '' ]; then - targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' - fi - - runtimeOsArgs= - if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then - runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' - fi - - baseOsArgs= - if [ '${{ parameters.platform.baseOS }}' != '' ]; then - baseOsArgs='/p:BaseOS=${{ parameters.platform.baseOS }}' - fi - - publishArgs= - if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then - publishArgs='--publish' - fi - - assetManifestFileName=SourceBuild_RidSpecific.xml - if [ '${{ parameters.platform.name }}' != '' ]; then - assetManifestFileName=SourceBuild_${{ parameters.platform.name }}.xml - fi - - ${{ coalesce(parameters.platform.buildScript, './build.sh') }} --ci \ - --configuration $buildConfig \ - --restore --build --pack $publishArgs -bl \ - $officialBuildArgs \ - $internalRuntimeDownloadArgs \ - $internalRestoreArgs \ - $targetRidArgs \ - $runtimeOsArgs \ - $baseOsArgs \ - /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ - /p:ArcadeBuildFromSource=true \ - /p:DotNetBuildSourceOnly=true \ - /p:DotNetBuildRepo=true \ - /p:AssetManifestFileName=$assetManifestFileName - displayName: Build - -# Upload build logs for diagnosis. -- task: CopyFiles@2 - displayName: Prepare BuildLogs staging directory - inputs: - SourceFolder: '$(Build.SourcesDirectory)' - Contents: | - **/*.log - **/*.binlog - artifacts/sb/prebuilt-report/** - TargetFolder: '$(Build.StagingDirectory)/BuildLogs' - CleanTargetFolder: true - continueOnError: true - condition: succeededOrFailed() - -- task: 1ES.PublishPipelineArtifact@1 - displayName: Publish BuildLogs - inputs: - targetPath: '$(Build.StagingDirectory)/BuildLogs' - artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) - continueOnError: true - condition: succeededOrFailed() +- template: /eng/common/core-templates/steps/source-build.yml + parameters: + is1ESPipeline: true -# Manually inject component detection so that we can ignore the source build upstream cache, which contains -# a nupkg cache of input packages (a local feed). -# This path must match the upstream cache path in property 'CurrentRepoSourceBuiltNupkgCacheDir' -# in src\Microsoft.DotNet.Arcade.Sdk\tools\SourceBuild\SourceBuildArcade.targets -- task: ComponentGovernanceComponentDetection@0 - displayName: Component Detection (Exclude upstream cache) - inputs: - ignoreDirectories: '$(Build.SourcesDirectory)/artifacts/sb/src/artifacts/obj/source-built-upstream-cache' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/variables/pool-providers.yml b/eng/common/templates-official/variables/pool-providers.yml index beab7d1bfba0..1f308b24efc4 100644 --- a/eng/common/templates-official/variables/pool-providers.yml +++ b/eng/common/templates-official/variables/pool-providers.yml @@ -23,7 +23,7 @@ # # pool: # name: $(DncEngInternalBuildPool) -# image: 1es-windows-2022-pt +# image: 1es-windows-2022 variables: # Coalesce the target and source branches so we know when a PR targets a release branch diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml deleted file mode 100644 index 7870f93bc176..000000000000 --- a/eng/common/templates/job/execute-sdl.yml +++ /dev/null @@ -1,139 +0,0 @@ -parameters: - enable: 'false' # Whether the SDL validation job should execute or not - overrideParameters: '' # Optional: to override values for parameters. - additionalParameters: '' # Optional: parameters that need user specific values eg: '-SourceToolsList @("abc","def") -ArtifactToolsList @("ghi","jkl")' - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - # Optional: if true, publish the '.gdn' folder as a pipeline artifact. This can help with in-depth - # diagnosis of problems with specific tool configurations. - publishGuardianDirectoryToPipeline: false - # The script to run to execute all SDL tools. Use this if you want to use a script to define SDL - # parameters rather than relying on YAML. It may be better to use a local script, because you can - # reproduce results locally without piecing together a command based on the YAML. - executeAllSdlToolsScript: 'eng/common/sdl/execute-all-sdl-tools.ps1' - # There is some sort of bug (has been reported) in Azure DevOps where if this parameter is named - # 'continueOnError', the parameter value is not correctly picked up. - # This can also be remedied by the caller (post-build.yml) if it does not use a nested parameter - sdlContinueOnError: false # optional: determines whether to continue the build if the step errors; - # optional: determines if build artifacts should be downloaded. - downloadArtifacts: true - # optional: determines if this job should search the directory of downloaded artifacts for - # 'tar.gz' and 'zip' archive files and extract them before running SDL validation tasks. - extractArchiveArtifacts: false - dependsOn: '' # Optional: dependencies of the job - artifactNames: '' # Optional: patterns supplied to DownloadBuildArtifacts - # Usage: - # artifactNames: - # - 'BlobArtifacts' - # - 'Artifacts_Windows_NT_Release' - # Optional: download a list of pipeline artifacts. 'downloadArtifacts' controls build artifacts, - # not pipeline artifacts, so doesn't affect the use of this parameter. - pipelineArtifactNames: [] - -jobs: -- job: Run_SDL - dependsOn: ${{ parameters.dependsOn }} - displayName: Run SDL tool - condition: and(succeededOrFailed(), eq( ${{ parameters.enable }}, 'true')) - variables: - - group: DotNet-VSTS-Bot - - name: AzDOProjectName - value: ${{ parameters.AzDOProjectName }} - - name: AzDOPipelineId - value: ${{ parameters.AzDOPipelineId }} - - name: AzDOBuildId - value: ${{ parameters.AzDOBuildId }} - - template: /eng/common/templates/variables/sdl-variables.yml - - name: GuardianVersion - value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - - template: /eng/common/templates/variables/pool-providers.yml - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - checkout: self - clean: true - - # If the template caller didn't provide an AzDO parameter, set them all up as Maestro vars. - - ${{ if not(and(parameters.AzDOProjectName, parameters.AzDOPipelineId, parameters.AzDOBuildId)) }}: - - template: /eng/common/templates/post-build/setup-maestro-vars.yml - - - ${{ if ne(parameters.downloadArtifacts, 'false')}}: - - ${{ if ne(parameters.artifactNames, '') }}: - - ${{ each artifactName in parameters.artifactNames }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Build Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: ${{ artifactName }} - downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - checkDownloadedFiles: true - - ${{ if eq(parameters.artifactNames, '') }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Build Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - downloadType: specific files - itemPattern: "**" - downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - checkDownloadedFiles: true - - - ${{ each artifactName in parameters.pipelineArtifactNames }}: - - task: DownloadPipelineArtifact@2 - displayName: Download Pipeline Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: ${{ artifactName }} - downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - checkDownloadedFiles: true - - - powershell: eng/common/sdl/trim-assets-version.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts - displayName: Trim the version from the NuGet packages - continueOnError: ${{ parameters.sdlContinueOnError }} - - - powershell: eng/common/sdl/extract-artifact-packages.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts\BlobArtifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts\BlobArtifacts - displayName: Extract Blob Artifacts - continueOnError: ${{ parameters.sdlContinueOnError }} - - - powershell: eng/common/sdl/extract-artifact-packages.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts\PackageArtifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts\PackageArtifacts - displayName: Extract Package Artifacts - continueOnError: ${{ parameters.sdlContinueOnError }} - - - ${{ if ne(parameters.extractArchiveArtifacts, 'false') }}: - - powershell: eng/common/sdl/extract-artifact-archives.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts - displayName: Extract Archive Artifacts - continueOnError: ${{ parameters.sdlContinueOnError }} - - - template: /eng/common/templates/steps/execute-sdl.yml - parameters: - overrideGuardianVersion: ${{ parameters.overrideGuardianVersion }} - executeAllSdlToolsScript: ${{ parameters.executeAllSdlToolsScript }} - overrideParameters: ${{ parameters.overrideParameters }} - additionalParameters: ${{ parameters.additionalParameters }} - publishGuardianDirectoryToPipeline: ${{ parameters.publishGuardianDirectoryToPipeline }} - sdlContinueOnError: ${{ parameters.sdlContinueOnError }} diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index a3277bf15c51..1cf9a6d48127 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -1,259 +1,61 @@ -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - -parameters: -# Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - cancelTimeoutInMinutes: '' - condition: '' - container: '' - continueOnError: false - dependsOn: '' - displayName: '' - pool: '' - steps: [] - strategy: '' - timeoutInMinutes: '' - variables: [] - workspace: '' - templateContext: '' - -# Job base template specific parameters - # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md - artifacts: '' - enableMicrobuild: false +parameters: enablePublishBuildArtifacts: false - enablePublishBuildAssets: false - enablePublishTestResults: false - enablePublishUsingPipelines: false - enableBuildRetry: false - disableComponentGovernance: '' - componentGovernanceIgnoreDirectories: '' - mergeTestResults: false - testRunTitle: '' - testResultsFormat: '' - name: '' - preSteps: [] - runAsPublic: false -# Sbom related params - enableSbom: true - PackageVersion: 7.0.0 - BuildDropPath: '$(Build.SourcesDirectory)/artifacts' jobs: -- job: ${{ parameters.name }} - - ${{ if ne(parameters.cancelTimeoutInMinutes, '') }}: - cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }} - - ${{ if ne(parameters.condition, '') }}: - condition: ${{ parameters.condition }} - - ${{ if ne(parameters.container, '') }}: - container: ${{ parameters.container }} - - ${{ if ne(parameters.continueOnError, '') }}: - continueOnError: ${{ parameters.continueOnError }} - - ${{ if ne(parameters.dependsOn, '') }}: - dependsOn: ${{ parameters.dependsOn }} - - ${{ if ne(parameters.displayName, '') }}: - displayName: ${{ parameters.displayName }} - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - - ${{ if ne(parameters.strategy, '') }}: - strategy: ${{ parameters.strategy }} - - ${{ if ne(parameters.timeoutInMinutes, '') }}: - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - - ${{ if ne(parameters.templateContext, '') }}: - templateContext: ${{ parameters.templateContext }} - - variables: - - ${{ if ne(parameters.enableTelemetry, 'false') }}: - - name: DOTNET_CLI_TELEMETRY_PROFILE - value: '$(Build.Repository.Uri)' - - ${{ if eq(parameters.enableRichCodeNavigation, 'true') }}: - - name: EnableRichCodeNavigation - value: 'true' - # Retry signature validation up to three times, waiting 2 seconds between attempts. - # See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3028#retry-untrusted-root-failures - - name: NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY - value: 3,2000 - - ${{ each variable in parameters.variables }}: - # handle name-value variable syntax - # example: - # - name: [key] - # value: [value] - - ${{ if ne(variable.name, '') }}: - - name: ${{ variable.name }} - value: ${{ variable.value }} - - # handle variable groups - - ${{ if ne(variable.group, '') }}: - - group: ${{ variable.group }} - - # handle template variable syntax - # example: - # - template: path/to/template.yml - # parameters: - # [key]: [value] - - ${{ if ne(variable.template, '') }}: - - template: ${{ variable.template }} - ${{ if ne(variable.parameters, '') }}: - parameters: ${{ variable.parameters }} - - # handle key-value variable syntax. - # example: - # - [key]: [value] - - ${{ if and(eq(variable.name, ''), eq(variable.group, ''), eq(variable.template, '')) }}: - - ${{ each pair in variable }}: - - name: ${{ pair.key }} - value: ${{ pair.value }} - - # DotNet-HelixApi-Access provides 'HelixApiAccessToken' for internal builds - - ${{ if and(eq(parameters.enableTelemetry, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: DotNet-HelixApi-Access - - ${{ if ne(parameters.workspace, '') }}: - workspace: ${{ parameters.workspace }} - - steps: - - ${{ if ne(parameters.preSteps, '') }}: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - task: MicroBuildSigningPlugin@3 - displayName: Install MicroBuild plugin - inputs: - signType: $(_SignType) - zipSources: false - feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json - env: - TeamName: $(_TeamName) - continueOnError: ${{ parameters.continueOnError }} - condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - - - ${{ if and(eq(parameters.runAsPublic, 'false'), eq(variables['System.TeamProject'], 'internal')) }}: - - task: NuGetAuthenticate@1 - - - ${{ if and(ne(parameters.artifacts.download, 'false'), ne(parameters.artifacts.download, '')) }}: - - task: DownloadPipelineArtifact@2 - inputs: - buildType: current - artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} - targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} - itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} - - - ${{ each step in parameters.steps }}: - - ${{ step }} - - - ${{ if eq(parameters.enableRichCodeNavigation, true) }}: - - task: RichCodeNavIndexer@0 - displayName: RichCodeNav Upload - inputs: - languages: ${{ coalesce(parameters.richCodeNavigationLanguage, 'csharp') }} - environment: ${{ coalesce(parameters.richCodeNavigationEnvironment, 'internal') }} - richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin - uploadRichNavArtifacts: ${{ coalesce(parameters.richCodeNavigationUploadArtifacts, false) }} - continueOnError: true - - - template: /eng/common/templates/steps/component-governance.yml - parameters: - ${{ if eq(parameters.disableComponentGovernance, '') }}: - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: - disableComponentGovernance: false - ${{ else }}: - disableComponentGovernance: true - ${{ else }}: - disableComponentGovernance: ${{ parameters.disableComponentGovernance }} - componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: MicroBuildCleanup@1 - displayName: Execute Microbuild cleanup tasks - condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - env: - TeamName: $(_TeamName) - - - ${{ if ne(parameters.artifacts.publish, '') }}: - - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: - - task: CopyFiles@2 - displayName: Gather binaries for publish to artifacts - inputs: - SourceFolder: 'artifacts/bin' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' - - task: CopyFiles@2 - displayName: Gather packages for publish to artifacts - inputs: - SourceFolder: 'artifacts/packages' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' - - task: PublishBuildArtifacts@1 - displayName: Publish pipeline artifacts - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} - continueOnError: true - condition: always() - - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: - - publish: artifacts/log - artifact: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)') }} - displayName: Publish logs - continueOnError: true - condition: always() - - - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: - - task: PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} - continueOnError: true - condition: always() - - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'xunit')) }}: - - task: PublishTestResults@2 - displayName: Publish XUnit Test Results - inputs: - testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'vstest')) }}: - - task: PublishTestResults@2 - displayName: Publish TRX Test Results - inputs: - testResultsFormat: 'VSTest' - testResultsFiles: '*.trx' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: - - template: /eng/common/templates/steps/generate-sbom.yml - parameters: - PackageVersion: ${{ parameters.packageVersion}} - BuildDropPath: ${{ parameters.buildDropPath }} - IgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableBuildRetry, 'true') }}: - - publish: $(Build.SourcesDirectory)\eng\common\BuildConfiguration - artifact: BuildConfiguration - displayName: Publish build retry configuration - continueOnError: true +- template: /eng/common/core-templates/job/job.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ if and(ne(parameter.key, 'steps'), ne(parameter.key, 'is1ESPipeline')) }}: + ${{ parameter.key }}: ${{ parameter.value }} + + steps: + - ${{ each step in parameters.steps }}: + - ${{ step }} + + artifactPublishSteps: + - ${{ if ne(parameters.artifacts.publish, '') }}: + - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: false + args: + displayName: Publish pipeline artifacts + pathToPublish: '$(Build.ArtifactStagingDirectory)/artifacts' + publishLocation: Container + artifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} + continueOnError: true + condition: always() + - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: false + args: + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/log' + artifactName: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)') }} + displayName: 'Publish logs' + continueOnError: true + condition: always() + + - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: false + args: + displayName: Publish Logs + pathToPublish: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' + publishLocation: Container + artifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} + continueOnError: true + condition: always() + + - ${{ if eq(parameters.enableBuildRetry, 'true') }}: + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: false + args: + targetPath: '$(Build.SourcesDirectory)\eng\common\BuildConfiguration' + artifactName: 'BuildConfiguration' + displayName: 'Publish build retry configuration' + continueOnError: true diff --git a/eng/common/templates/job/onelocbuild.yml b/eng/common/templates/job/onelocbuild.yml index 60ab00c4de3a..ff829dc4c700 100644 --- a/eng/common/templates/job/onelocbuild.yml +++ b/eng/common/templates/job/onelocbuild.yml @@ -1,109 +1,7 @@ -parameters: - # Optional: dependencies of the job - dependsOn: '' - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: '' - - CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex - GithubPat: $(BotAccount-dotnet-bot-repo-PAT) - - SourcesDirectory: $(Build.SourcesDirectory) - CreatePr: true - AutoCompletePr: false - ReusePr: true - UseLfLineEndings: true - UseCheckedInLocProjectJson: false - SkipLocProjectJsonGeneration: false - LanguageSet: VS_Main_Languages - LclSource: lclFilesInRepo - LclPackageId: '' - RepoType: gitHub - GitHubOrg: dotnet - MirrorRepo: '' - MirrorBranch: main - condition: '' - JobNameSuffix: '' - jobs: -- job: OneLocBuild${{ parameters.JobNameSuffix }} - - dependsOn: ${{ parameters.dependsOn }} - - displayName: OneLocBuild${{ parameters.JobNameSuffix }} - - variables: - - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat - - name: _GenerateLocProjectArguments - value: -SourcesDirectory ${{ parameters.SourcesDirectory }} - -LanguageSet "${{ parameters.LanguageSet }}" - -CreateNeutralXlfs - - ${{ if eq(parameters.UseCheckedInLocProjectJson, 'true') }}: - - name: _GenerateLocProjectArguments - value: ${{ variables._GenerateLocProjectArguments }} -UseCheckedInLocProjectJson - - template: /eng/common/templates/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - - steps: - - ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}: - - task: Powershell@2 - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1 - arguments: $(_GenerateLocProjectArguments) - displayName: Generate LocProject.json - condition: ${{ parameters.condition }} - - - task: OneLocBuild@2 - displayName: OneLocBuild - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - locProj: eng/Localize/LocProject.json - outDir: $(Build.ArtifactStagingDirectory) - lclSource: ${{ parameters.LclSource }} - lclPackageId: ${{ parameters.LclPackageId }} - isCreatePrSelected: ${{ parameters.CreatePr }} - isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }} - ${{ if eq(parameters.CreatePr, true) }}: - isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - isShouldReusePrSelected: ${{ parameters.ReusePr }} - packageSourceAuth: patAuth - patVariable: ${{ parameters.CeapexPat }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - repoType: ${{ parameters.RepoType }} - gitHubPatVariable: "${{ parameters.GithubPat }}" - ${{ if ne(parameters.MirrorRepo, '') }}: - isMirrorRepoSelected: true - gitHubOrganization: ${{ parameters.GitHubOrg }} - mirrorRepo: ${{ parameters.MirrorRepo }} - mirrorBranch: ${{ parameters.MirrorBranch }} - condition: ${{ parameters.condition }} - - - task: PublishBuildArtifacts@1 - displayName: Publish Localization Files - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/loc' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} +- template: /eng/common/core-templates/job/onelocbuild.yml + parameters: + is1ESPipeline: false - - task: PublishBuildArtifacts@1 - displayName: Publish LocProject.json - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/Localize/' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} \ No newline at end of file + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/publish-build-assets.yml b/eng/common/templates/job/publish-build-assets.yml index bb42240f865b..ab2edec2adb5 100644 --- a/eng/common/templates/job/publish-build-assets.yml +++ b/eng/common/templates/job/publish-build-assets.yml @@ -1,155 +1,7 @@ -parameters: - configuration: 'Debug' - - # Optional: condition for the job to run - condition: '' - - # Optional: 'true' if future jobs should run even if this job fails - continueOnError: false - - # Optional: dependencies of the job - dependsOn: '' - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: {} - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishUsingPipelines: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishAssetsImmediately: false - - artifactsPublishingAdditionalParameters: '' - - signingValidationAdditionalParameters: '' - jobs: -- job: Asset_Registry_Publish - - dependsOn: ${{ parameters.dependsOn }} - timeoutInMinutes: 150 - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - displayName: Publish Assets - ${{ else }}: - displayName: Publish to Build Asset Registry - - variables: - - template: /eng/common/templates/variables/pool-providers.yml - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: Publish-Build-Assets - - group: AzureDevOps-Artifact-Feeds-Pats - - name: runCodesignValidationInjection - value: false - # unconditional - needed for logs publishing (redactor tool version) - - template: /eng/common/templates/post-build/common-variables.yml - - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: NetCore1ESPool-Publishing-Internal - demands: ImageOverride -equals windows.vs2019.amd64 - - steps: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - checkout: self - fetchDepth: 3 - clean: true - - - task: DownloadBuildArtifacts@0 - displayName: Download artifact - inputs: - artifactName: AssetManifests - downloadPath: '$(Build.StagingDirectory)/Download' - checkDownloadedFiles: true - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: NuGetAuthenticate@1 - - - task: PowerShell@2 - displayName: Publish Build Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishBuildAssets -restore -msbuildEngine dotnet - /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' - /p:BuildAssetRegistryToken=$(MaestroAccessToken) - /p:MaestroApiEndpoint=https://maestro.dot.net - /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} - /p:OfficialBuildId=$(Build.BuildNumber) - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: powershell@2 - displayName: Create ReleaseConfigs Artifact - inputs: - targetType: inline - script: | - Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value $(BARBuildId) - Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value "$(DefaultChannels)" - Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value $(IsStableBuild) - - - task: PublishBuildArtifacts@1 - displayName: Publish ReleaseConfigs Artifact - inputs: - PathtoPublish: '$(Build.StagingDirectory)/ReleaseConfigs.txt' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - task: powershell@2 - displayName: Check if SymbolPublishingExclusionsFile.txt exists - inputs: - targetType: inline - script: | - $symbolExclusionfile = "$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt" - if(Test-Path -Path $symbolExclusionfile) - { - Write-Host "SymbolExclusionFile exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]true" - } - else{ - Write-Host "Symbols Exclusion file does not exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]false" - } - - - task: PublishBuildArtifacts@1 - displayName: Publish SymbolPublishingExclusionsFile Artifact - condition: eq(variables['SymbolExclusionFile'], 'true') - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - - template: /eng/common/templates/post-build/setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: PowerShell@2 - displayName: Publish Using Darc - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion 3 - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' - -MaestroToken '$(MaestroApiAccessToken)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' +- template: /eng/common/core-templates/job/publish-build-assets.yml + parameters: + is1ESPipeline: false - - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: - - template: /eng/common/templates/steps/publish-logs.yml - parameters: - JobLabel: 'Publish_Artifacts_Logs' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/source-build.yml b/eng/common/templates/job/source-build.yml index 8a3deef2b727..e44d47b1d760 100644 --- a/eng/common/templates/job/source-build.yml +++ b/eng/common/templates/job/source-build.yml @@ -1,66 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. The template produces a server job with a - # default ID 'Source_Build_Complete' to put in a dependency list if necessary. - - # Specifies the prefix for source-build jobs added to pipeline. Use this if disambiguation needed. - jobNamePrefix: 'Source_Build' - - # Defines the platform on which to run the job. By default, a linux-x64 machine, suitable for - # managed-only repositories. This is an object with these properties: - # - # name: '' - # The name of the job. This is included in the job ID. - # targetRID: '' - # The name of the target RID to use, instead of the one auto-detected by Arcade. - # nonPortable: false - # Enables non-portable mode. This means a more specific RID (e.g. fedora.32-x64 rather than - # linux-x64), and compiling against distro-provided packages rather than portable ones. - # skipPublishValidation: false - # Disables publishing validation. By default, a check is performed to ensure no packages are - # published by source-build. - # container: '' - # A container to use. Runs in docker. - # pool: {} - # A pool to use. Runs directly on an agent. - # buildScript: '' - # Specifies the build script to invoke to perform the build in the repo. The default - # './build.sh' should work for typical Arcade repositories, but this is customizable for - # difficult situations. - # jobProperties: {} - # A list of job properties to inject at the top level, for potential extensibility beyond - # container and pool. - platform: {} - jobs: -- job: ${{ parameters.jobNamePrefix }}_${{ parameters.platform.name }} - displayName: Source-Build (${{ parameters.platform.name }}) - - ${{ each property in parameters.platform.jobProperties }}: - ${{ property.key }}: ${{ property.value }} - - ${{ if ne(parameters.platform.container, '') }}: - container: ${{ parameters.platform.container }} - - ${{ if eq(parameters.platform.pool, '') }}: - # The default VM host AzDO pool. This should be capable of running Docker containers: almost all - # source-build builds run in Docker, including the default managed platform. - # /eng/common/templates/variables/pool-providers.yml can't be used here (some customers declare variables already), so duplicate its logic - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] - demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open - - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] - demands: ImageOverride -equals Build.Ubuntu.1804.Amd64 - - ${{ if ne(parameters.platform.pool, '') }}: - pool: ${{ parameters.platform.pool }} - - workspace: - clean: all +- template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: false - steps: - - template: /eng/common/templates/steps/source-build.yml - parameters: - platform: ${{ parameters.platform }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/source-index-stage1.yml b/eng/common/templates/job/source-index-stage1.yml index b5a3e5c4a6c8..89f3291593cb 100644 --- a/eng/common/templates/job/source-index-stage1.yml +++ b/eng/common/templates/job/source-index-stage1.yml @@ -1,67 +1,7 @@ -parameters: - runAsPublic: false - sourceIndexPackageVersion: 1.0.1-20240129.2 - sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json - sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" - preSteps: [] - binlogPath: artifacts/log/Debug/Build.binlog - condition: '' - dependsOn: '' - pool: '' - jobs: -- job: SourceIndexStage1 - dependsOn: ${{ parameters.dependsOn }} - condition: ${{ parameters.condition }} - variables: - - name: SourceIndexPackageVersion - value: ${{ parameters.sourceIndexPackageVersion }} - - name: SourceIndexPackageSource - value: ${{ parameters.sourceIndexPackageSource }} - - name: BinlogPath - value: ${{ parameters.binlogPath }} - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: source-dot-net stage1 variables - - template: /eng/common/templates/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $(DncEngPublicBuildPool) - demands: ImageOverride -equals windows.vs2022.amd64.open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2022.amd64 - - steps: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - task: UseDotNet@2 - displayName: Use .NET 8 SDK - inputs: - packageType: sdk - version: 8.0.x - installationPath: $(Agent.TempDirectory)/dotnet - workingDirectory: $(Agent.TempDirectory) - - - script: | - $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - displayName: Download Tools - # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. - workingDirectory: $(Agent.TempDirectory) - - - script: ${{ parameters.sourceIndexBuildCommand }} - displayName: Build Repository - - - script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i $(BinlogPath) -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output - displayName: Process Binlog into indexable sln +- template: /eng/common/core-templates/job/source-index-stage1.yml + parameters: + is1ESPipeline: false - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) - displayName: Upload stage1 artifacts to source index - env: - BLOB_CONTAINER_URL: $(source-dot-net-stage1-blob-container-url) + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/jobs/codeql-build.yml b/eng/common/templates/jobs/codeql-build.yml index f7dc5ea4aaa6..517f24d6a52c 100644 --- a/eng/common/templates/jobs/codeql-build.yml +++ b/eng/common/templates/jobs/codeql-build.yml @@ -1,31 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - jobs: -- template: /eng/common/templates/jobs/jobs.yml +- template: /eng/common/core-templates/jobs/codeql-build.yml parameters: - enableMicrobuild: false - enablePublishBuildArtifacts: false - enablePublishTestResults: false - enablePublishBuildAssets: false - enablePublishUsingPipelines: false - enableTelemetry: true + is1ESPipeline: false - variables: - - group: Publish-Build-Assets - # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in - # sync with the packages.config file. - - name: DefaultGuardianVersion - value: 0.109.0 - - name: GuardianPackagesConfigFile - value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config - - name: GuardianVersion - value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - - jobs: ${{ parameters.jobs }} - + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/jobs/jobs.yml b/eng/common/templates/jobs/jobs.yml index 289bb2396ce8..388e9037b3e6 100644 --- a/eng/common/templates/jobs/jobs.yml +++ b/eng/common/templates/jobs/jobs.yml @@ -1,97 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: Enable publishing using release pipelines - enablePublishUsingPipelines: false - - # Optional: Enable running the source-build jobs to build repo from source - enableSourceBuild: false - - # Optional: Parameters for source-build template. - # See /eng/common/templates/jobs/source-build.yml for options - sourceBuildParameters: [] - - graphFileGeneration: - # Optional: Enable generating the graph files at the end of the build - enabled: false - # Optional: Include toolset dependencies in the generated graph files - includeToolset: false - - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - - # Optional: Override automatically derived dependsOn value for "publish build assets" job - publishBuildAssetsDependsOn: '' - - # Optional: Publish the assets as soon as the publish to BAR stage is complete, rather doing so in a separate stage. - publishAssetsImmediately: false - - # Optional: If using publishAssetsImmediately and additional parameters are needed, can be used to send along additional parameters (normally sent to post-build.yml) - artifactsPublishingAdditionalParameters: '' - signingValidationAdditionalParameters: '' - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - enableSourceIndex: false - sourceIndexParams: {} - -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - jobs: -- ${{ each job in parameters.jobs }}: - - template: ../job/job.yml - parameters: - # pass along parameters - ${{ each parameter in parameters }}: - ${{ if ne(parameter.key, 'jobs') }}: - ${{ parameter.key }}: ${{ parameter.value }} - - # pass along job properties - ${{ each property in job }}: - ${{ if ne(property.key, 'job') }}: - ${{ property.key }}: ${{ property.value }} - - name: ${{ job.job }} - -- ${{ if eq(parameters.enableSourceBuild, true) }}: - - template: /eng/common/templates/jobs/source-build.yml - parameters: - allCompletedJobId: Source_Build_Complete - ${{ each parameter in parameters.sourceBuildParameters }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if eq(parameters.enableSourceIndex, 'true') }}: - - template: ../job/source-index-stage1.yml - parameters: - runAsPublic: ${{ parameters.runAsPublic }} - ${{ each parameter in parameters.sourceIndexParams }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: - - template: ../job/publish-build-assets.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - dependsOn: - - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.publishBuildAssetsDependsOn }}: - - ${{ job.job }} - - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.jobs }}: - - ${{ job.job }} - - ${{ if eq(parameters.enableSourceBuild, true) }}: - - Source_Build_Complete +- template: /eng/common/core-templates/jobs/jobs.yml + parameters: + is1ESPipeline: false - runAsPublic: ${{ parameters.runAsPublic }} - publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} - publishAssetsImmediately: ${{ parameters.publishAssetsImmediately }} - enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/jobs/source-build.yml b/eng/common/templates/jobs/source-build.yml index a15b07eb51d9..818d4c326dbb 100644 --- a/eng/common/templates/jobs/source-build.yml +++ b/eng/common/templates/jobs/source-build.yml @@ -1,46 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. A job is created for each platform, as - # well as an optional server job that completes when all platform jobs complete. - - # The name of the "join" job for all source-build platforms. If set to empty string, the job is - # not included. Existing repo pipelines can use this job depend on all source-build jobs - # completing without maintaining a separate list of every single job ID: just depend on this one - # server job. By default, not included. Recommended name if used: 'Source_Build_Complete'. - allCompletedJobId: '' - - # See /eng/common/templates/job/source-build.yml - jobNamePrefix: 'Source_Build' - - # This is the default platform provided by Arcade, intended for use by a managed-only repo. - defaultManagedPlatform: - name: 'Managed' - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8' - - # Defines the platforms on which to run build jobs. One job is created for each platform, and the - # object in this array is sent to the job template as 'platform'. If no platforms are specified, - # one job runs on 'defaultManagedPlatform'. - platforms: [] - jobs: +- template: /eng/common/core-templates/jobs/source-build.yml + parameters: + is1ESPipeline: false -- ${{ if ne(parameters.allCompletedJobId, '') }}: - - job: ${{ parameters.allCompletedJobId }} - displayName: Source-Build Complete - pool: server - dependsOn: - - ${{ each platform in parameters.platforms }}: - - ${{ parameters.jobNamePrefix }}_${{ platform.name }} - - ${{ if eq(length(parameters.platforms), 0) }}: - - ${{ parameters.jobNamePrefix }}_${{ parameters.defaultManagedPlatform.name }} - -- ${{ each platform in parameters.platforms }}: - - template: /eng/common/templates/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ platform }} - -- ${{ if eq(length(parameters.platforms), 0) }}: - - template: /eng/common/templates/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ parameters.defaultManagedPlatform }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index b9ede10bf099..7fa105875592 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -1,24 +1,8 @@ variables: - - group: Publish-Build-Assets +- template: /eng/common/core-templates/post-build/common-variables.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: false - # Whether the build is internal or not - - name: IsInternalBuild - value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} - - # Default Maestro++ API Endpoint and API Version - - name: MaestroApiEndPoint - value: "https://maestro.dot.net" - - name: MaestroApiAccessToken - value: $(MaestroAccessToken) - - name: MaestroApiVersion - value: "2020-02-20" - - - name: SourceLinkCLIVersion - value: 3.0.0 - - name: SymbolToolVersion - value: 1.0.1 - - name: BinlogToolVersion - value: 1.0.11 - - - name: runCodesignValidationInjection - value: false + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index ee70e2b399c5..53ede714bdd2 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -1,282 +1,8 @@ -parameters: - # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. - # Publishing V1 is no longer supported - # Publishing V2 is no longer supported - # Publishing V3 is the default - - name: publishingInfraVersion - displayName: Which version of publishing should be used to promote the build definition? - type: number - default: 3 - values: - - 3 - - - name: BARBuildId - displayName: BAR Build Id - type: number - default: 0 - - - name: PromoteToChannelIds - displayName: Channel to promote BARBuildId to - type: string - default: '' - - - name: enableSourceLinkValidation - displayName: Enable SourceLink validation - type: boolean - default: false - - - name: enableSigningValidation - displayName: Enable signing validation - type: boolean - default: true - - - name: enableSymbolValidation - displayName: Enable symbol validation - type: boolean - default: false - - - name: enableNugetValidation - displayName: Enable NuGet validation - type: boolean - default: true - - - name: publishInstallersAndChecksums - displayName: Publish installers and checksums - type: boolean - default: true - - - name: SDLValidationParameters - type: object - default: - enable: false - publishGdn: false - continueOnError: false - params: '' - artifactNames: '' - downloadArtifacts: true - - # These parameters let the user customize the call to sdk-task.ps1 for publishing - # symbols & general artifacts as well as for signing validation - - name: symbolPublishingAdditionalParameters - displayName: Symbol publishing additional parameters - type: string - default: '' - - - name: artifactsPublishingAdditionalParameters - displayName: Artifact publishing additional parameters - type: string - default: '' - - - name: signingValidationAdditionalParameters - displayName: Signing validation additional parameters - type: string - default: '' - - # Which stages should finish execution before post-build stages start - - name: validateDependsOn - type: object - default: - - build - - - name: publishDependsOn - type: object - default: - - Validate - - # Optional: Call asset publishing rather than running in a separate stage - - name: publishAssetsImmediately - type: boolean - default: false - stages: -- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - - stage: Validate - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Validate Build Assets - variables: - - template: common-variables.yml - - template: /eng/common/templates/variables/pool-providers.yml - jobs: - - job: - displayName: NuGet Validation - condition: and(succeededOrFailed(), eq( ${{ parameters.enableNugetValidation }}, 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1 - arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ - -ToolDestinationPath $(Agent.BuildDirectory)/Extract/ - - - job: - displayName: Signing Validation - condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - itemPattern: | - ** - !**/Microsoft.SourceBuild.Intermediate.*.nupkg - - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@1 - displayName: 'Authenticate to AzDO Feeds' - - # Signing validation will optionally work with the buildmanifest file which is downloaded from - # Azure DevOps above. - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task SigningValidation -restore -msbuildEngine vs - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' - /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' - ${{ parameters.signingValidationAdditionalParameters }} - - - template: ../steps/publish-logs.yml - parameters: - StageLabel: 'Validation' - JobLabel: 'Signing' - BinlogToolVersion: $(BinlogToolVersion) - - - job: - displayName: SourceLink Validation - condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: BlobArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1 - arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/ - -ExtractPath $(Agent.BuildDirectory)/Extract/ - -GHRepoName $(Build.Repository.Name) - -GHCommit $(Build.SourceVersion) - -SourcelinkCliVersion $(SourceLinkCLIVersion) - continueOnError: true - - - template: /eng/common/templates/job/execute-sdl.yml - parameters: - enable: ${{ parameters.SDLValidationParameters.enable }} - publishGuardianDirectoryToPipeline: ${{ parameters.SDLValidationParameters.publishGdn }} - additionalParameters: ${{ parameters.SDLValidationParameters.params }} - continueOnError: ${{ parameters.SDLValidationParameters.continueOnError }} - artifactNames: ${{ parameters.SDLValidationParameters.artifactNames }} - downloadArtifacts: ${{ parameters.SDLValidationParameters.downloadArtifacts }} - -- ${{ if ne(parameters.publishAssetsImmediately, 'true') }}: - - stage: publish_using_darc - ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - dependsOn: ${{ parameters.publishDependsOn }} - ${{ else }}: - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Publish using Darc - variables: - - template: common-variables.yml - - template: /eng/common/templates/variables/pool-providers.yml - jobs: - - job: - displayName: Publish Using Darc - timeoutInMinutes: 120 - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: NetCore1ESPool-Publishing-Internal - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: NuGetAuthenticate@1 +- template: /eng/common/core-templates/post-build/post-build.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: false - - task: PowerShell@2 - displayName: Publish Using Darc - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' - -MaestroToken '$(MaestroApiAccessToken)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/post-build/setup-maestro-vars.yml b/eng/common/templates/post-build/setup-maestro-vars.yml index 0c87f149a4ad..a79fab5b441e 100644 --- a/eng/common/templates/post-build/setup-maestro-vars.yml +++ b/eng/common/templates/post-build/setup-maestro-vars.yml @@ -1,70 +1,8 @@ -parameters: - BARBuildId: '' - PromoteToChannelIds: '' - steps: - - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Release Configs - inputs: - buildType: current - artifactName: ReleaseConfigs - checkDownloadedFiles: true - - - task: PowerShell@2 - name: setReleaseVars - displayName: Set Release Configs Vars - inputs: - targetType: inline - pwsh: true - script: | - try { - if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { - $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt - - $BarId = $Content | Select -Index 0 - $Channels = $Content | Select -Index 1 - $IsStableBuild = $Content | Select -Index 2 - - $AzureDevOpsProject = $Env:System_TeamProject - $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId - $AzureDevOpsBuildId = $Env:Build_BuildId - } - else { - $buildApiEndpoint = "${Env:MaestroApiEndPoint}/api/builds/${Env:BARBuildId}?api-version=${Env:MaestroApiVersion}" - - $apiHeaders = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $apiHeaders.Add('Accept', 'application/json') - $apiHeaders.Add('Authorization',"Bearer ${Env:MAESTRO_API_TOKEN}") - - $buildInfo = try { Invoke-WebRequest -Method Get -Uri $buildApiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - - $BarId = $Env:BARBuildId - $Channels = $Env:PromoteToMaestroChannels -split "," - $Channels = $Channels -join "][" - $Channels = "[$Channels]" - - $IsStableBuild = $buildInfo.stable - $AzureDevOpsProject = $buildInfo.azureDevOpsProject - $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId - $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId - } - - Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" - Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" - Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" +- template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: false - Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" - Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" - Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" - } - catch { - Write-Host $_ - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - exit 1 - } - env: - MAESTRO_API_TOKEN: $(MaestroApiAccessToken) - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/steps/add-build-to-channel.yml b/eng/common/templates/steps/add-build-to-channel.yml index f67a210d62f3..42bbba161b9b 100644 --- a/eng/common/templates/steps/add-build-to-channel.yml +++ b/eng/common/templates/steps/add-build-to-channel.yml @@ -1,13 +1,7 @@ -parameters: - ChannelId: 0 - steps: -- task: PowerShell@2 - displayName: Add Build to Channel - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/add-build-to-channel.ps1 - arguments: -BuildId $(BARBuildId) - -ChannelId ${{ parameters.ChannelId }} - -MaestroApiAccessToken $(MaestroApiAccessToken) - -MaestroApiEndPoint $(MaestroApiEndPoint) - -MaestroApiVersion $(MaestroApiVersion) +- template: /eng/common/core-templates/steps/add-build-to-channel.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/build-reason.yml b/eng/common/templates/steps/build-reason.yml deleted file mode 100644 index eba58109b52c..000000000000 --- a/eng/common/templates/steps/build-reason.yml +++ /dev/null @@ -1,12 +0,0 @@ -# build-reason.yml -# Description: runs steps if build.reason condition is valid. conditions is a string of valid build reasons -# to include steps (',' separated). -parameters: - conditions: '' - steps: [] - -steps: - - ${{ if and( not(startsWith(parameters.conditions, 'not')), contains(parameters.conditions, variables['build.reason'])) }}: - - ${{ parameters.steps }} - - ${{ if and( startsWith(parameters.conditions, 'not'), not(contains(parameters.conditions, variables['build.reason']))) }}: - - ${{ parameters.steps }} diff --git a/eng/common/templates/steps/component-governance.yml b/eng/common/templates/steps/component-governance.yml index 0ecec47b0c91..c12a5f8d21d7 100644 --- a/eng/common/templates/steps/component-governance.yml +++ b/eng/common/templates/steps/component-governance.yml @@ -1,13 +1,7 @@ -parameters: - disableComponentGovernance: false - componentGovernanceIgnoreDirectories: '' - steps: -- ${{ if eq(parameters.disableComponentGovernance, 'true') }}: - - script: "echo ##vso[task.setvariable variable=skipComponentGovernanceDetection]true" - displayName: Set skipComponentGovernanceDetection variable -- ${{ if ne(parameters.disableComponentGovernance, 'true') }}: - - task: ComponentGovernanceComponentDetection@0 - continueOnError: true - inputs: - ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} \ No newline at end of file +- template: /eng/common/core-templates/steps/component-governance.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/execute-codeql.yml b/eng/common/templates/steps/execute-codeql.yml deleted file mode 100644 index 3930b1630214..000000000000 --- a/eng/common/templates/steps/execute-codeql.yml +++ /dev/null @@ -1,32 +0,0 @@ -parameters: - # Language that should be analyzed. Defaults to csharp - language: csharp - # Build Commands - buildCommands: '' - overrideParameters: '' # Optional: to override values for parameters. - additionalParameters: '' # Optional: parameters that need user specific values eg: '-SourceToolsList @("abc","def") -ArtifactToolsList @("ghi","jkl")' - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - # Optional: if true, publish the '.gdn' folder as a pipeline artifact. This can help with in-depth - # diagnosis of problems with specific tool configurations. - publishGuardianDirectoryToPipeline: false - # The script to run to execute all SDL tools. Use this if you want to use a script to define SDL - # parameters rather than relying on YAML. It may be better to use a local script, because you can - # reproduce results locally without piecing together a command based on the YAML. - executeAllSdlToolsScript: 'eng/common/sdl/execute-all-sdl-tools.ps1' - # There is some sort of bug (has been reported) in Azure DevOps where if this parameter is named - # 'continueOnError', the parameter value is not correctly picked up. - # This can also be remedied by the caller (post-build.yml) if it does not use a nested parameter - # optional: determines whether to continue the build if the step errors; - sdlContinueOnError: false - -steps: -- template: /eng/common/templates/steps/execute-sdl.yml - parameters: - overrideGuardianVersion: ${{ parameters.overrideGuardianVersion }} - executeAllSdlToolsScript: ${{ parameters.executeAllSdlToolsScript }} - overrideParameters: ${{ parameters.overrideParameters }} - additionalParameters: '${{ parameters.additionalParameters }} - -CodeQLAdditionalRunConfigParams @("BuildCommands < ${{ parameters.buildCommands }}", "Language < ${{ parameters.language }}")' - publishGuardianDirectoryToPipeline: ${{ parameters.publishGuardianDirectoryToPipeline }} - sdlContinueOnError: ${{ parameters.sdlContinueOnError }} \ No newline at end of file diff --git a/eng/common/templates/steps/execute-sdl.yml b/eng/common/templates/steps/execute-sdl.yml deleted file mode 100644 index 07426fde05d8..000000000000 --- a/eng/common/templates/steps/execute-sdl.yml +++ /dev/null @@ -1,88 +0,0 @@ -parameters: - overrideGuardianVersion: '' - executeAllSdlToolsScript: '' - overrideParameters: '' - additionalParameters: '' - publishGuardianDirectoryToPipeline: false - sdlContinueOnError: false - condition: '' - -steps: -- task: NuGetAuthenticate@1 - inputs: - nuGetServiceConnections: GuardianConnect - -- task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - -- ${{ if ne(parameters.overrideGuardianVersion, '') }}: - - pwsh: | - Set-Location -Path $(Build.SourcesDirectory)\eng\common\sdl - . .\sdl.ps1 - $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts -Version ${{ parameters.overrideGuardianVersion }} - Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" - displayName: Install Guardian (Overridden) - -- ${{ if eq(parameters.overrideGuardianVersion, '') }}: - - pwsh: | - Set-Location -Path $(Build.SourcesDirectory)\eng\common\sdl - . .\sdl.ps1 - $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts - Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" - displayName: Install Guardian - -- ${{ if ne(parameters.overrideParameters, '') }}: - - powershell: ${{ parameters.executeAllSdlToolsScript }} ${{ parameters.overrideParameters }} - displayName: Execute SDL (Overridden) - continueOnError: ${{ parameters.sdlContinueOnError }} - condition: ${{ parameters.condition }} - -- ${{ if eq(parameters.overrideParameters, '') }}: - - powershell: ${{ parameters.executeAllSdlToolsScript }} - -GuardianCliLocation $(GuardianCliLocation) - -NugetPackageDirectory $(Build.SourcesDirectory)\.packages - -AzureDevOpsAccessToken $(dn-bot-dotnet-build-rw-code-rw) - ${{ parameters.additionalParameters }} - displayName: Execute SDL - continueOnError: ${{ parameters.sdlContinueOnError }} - condition: ${{ parameters.condition }} - -- ${{ if ne(parameters.publishGuardianDirectoryToPipeline, 'false') }}: - # We want to publish the Guardian results and configuration for easy diagnosis. However, the - # '.gdn' dir is a mix of configuration, results, extracted dependencies, and Guardian default - # tooling files. Some of these files are large and aren't useful during an investigation, so - # exclude them by simply deleting them before publishing. (As of writing, there is no documented - # way to selectively exclude a dir from the pipeline artifact publish task.) - - task: DeleteFiles@1 - displayName: Delete Guardian dependencies to avoid uploading - inputs: - SourceFolder: $(Agent.BuildDirectory)/.gdn - Contents: | - c - i - condition: succeededOrFailed() - - - publish: $(Agent.BuildDirectory)/.gdn - artifact: GuardianConfiguration - displayName: Publish GuardianConfiguration - condition: succeededOrFailed() - - # Publish the SARIF files in a container named CodeAnalysisLogs to enable integration - # with the "SARIF SAST Scans Tab" Azure DevOps extension - - task: CopyFiles@2 - displayName: Copy SARIF files - inputs: - flattenFolders: true - sourceFolder: $(Agent.BuildDirectory)/.gdn/rc/ - contents: '**/*.sarif' - targetFolder: $(Build.SourcesDirectory)/CodeAnalysisLogs - condition: succeededOrFailed() - - # Use PublishBuildArtifacts because the SARIF extension only checks this case - # see microsoft/sarif-azuredevops-extension#4 - - task: PublishBuildArtifacts@1 - displayName: Publish SARIF files to CodeAnalysisLogs container - inputs: - pathToPublish: $(Build.SourcesDirectory)/CodeAnalysisLogs - artifactName: CodeAnalysisLogs - condition: succeededOrFailed() \ No newline at end of file diff --git a/eng/common/templates/steps/generate-sbom.yml b/eng/common/templates/steps/generate-sbom.yml index a06373f38fa5..26dc00a2e0f3 100644 --- a/eng/common/templates/steps/generate-sbom.yml +++ b/eng/common/templates/steps/generate-sbom.yml @@ -1,48 +1,7 @@ -# BuildDropPath - The root folder of the drop directory for which the manifest file will be generated. -# PackageName - The name of the package this SBOM represents. -# PackageVersion - The version of the package this SBOM represents. -# ManifestDirPath - The path of the directory where the generated manifest files will be placed -# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. - -parameters: - PackageVersion: 7.0.0 - BuildDropPath: '$(Build.SourcesDirectory)/artifacts' - PackageName: '.NET' - ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom - IgnoreDirectories: '' - sbomContinueOnError: true - steps: -- task: PowerShell@2 - displayName: Prep for SBOM generation in (Non-linux) - condition: or(eq(variables['Agent.Os'], 'Windows_NT'), eq(variables['Agent.Os'], 'Darwin')) - inputs: - filePath: ./eng/common/generate-sbom-prep.ps1 - arguments: ${{parameters.manifestDirPath}} - -# Chmodding is a workaround for https://github.com/dotnet/arcade/issues/8461 -- script: | - chmod +x ./eng/common/generate-sbom-prep.sh - ./eng/common/generate-sbom-prep.sh ${{parameters.manifestDirPath}} - displayName: Prep for SBOM generation in (Linux) - condition: eq(variables['Agent.Os'], 'Linux') - continueOnError: ${{ parameters.sbomContinueOnError }} - -- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 - displayName: 'Generate SBOM manifest' - continueOnError: ${{ parameters.sbomContinueOnError }} - inputs: - PackageName: ${{ parameters.packageName }} - BuildDropPath: ${{ parameters.buildDropPath }} - PackageVersion: ${{ parameters.packageVersion }} - ManifestDirPath: ${{ parameters.manifestDirPath }} - ${{ if ne(parameters.IgnoreDirectories, '') }}: - AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' - -- task: PublishPipelineArtifact@1 - displayName: Publish SBOM manifest - continueOnError: ${{parameters.sbomContinueOnError}} - inputs: - targetPath: '${{parameters.manifestDirPath}}' - artifactName: $(ARTIFACT_NAME) +- template: /eng/common/core-templates/steps/generate-sbom.yml + parameters: + is1ESPipeline: false + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/publish-build-artifacts.yml b/eng/common/templates/steps/publish-build-artifacts.yml new file mode 100644 index 000000000000..6428a98dfef6 --- /dev/null +++ b/eng/common/templates/steps/publish-build-artifacts.yml @@ -0,0 +1,40 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false + +- name: displayName + type: string + default: 'Publish to Build Artifact' + +- name: condition + type: string + default: succeeded() + +- name: artifactName + type: string + +- name: pathToPublish + type: string + +- name: continueOnError + type: boolean + default: false + +- name: publishLocation + type: string + default: 'Container' + +steps: +- ${{ if eq(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates cannot be referenced from a 1ES managed template': error +- task: PublishBuildArtifacts@1 + displayName: ${{ parameters.displayName }} + condition: ${{ parameters.condition }} + ${{ if parameters.continueOnError }}: + continueOnError: ${{ parameters.continueOnError }} + inputs: + PublishLocation: ${{ parameters.publishLocation }} + PathtoPublish: ${{ parameters.pathToPublish }} + ${{ if parameters.artifactName }}: + ArtifactName: ${{ parameters.artifactName }} \ No newline at end of file diff --git a/eng/common/templates/steps/publish-logs.yml b/eng/common/templates/steps/publish-logs.yml index 80861297ddc0..4ea86bd88235 100644 --- a/eng/common/templates/steps/publish-logs.yml +++ b/eng/common/templates/steps/publish-logs.yml @@ -1,49 +1,7 @@ -parameters: - StageLabel: '' - JobLabel: '' - CustomSensitiveDataList: '' - # A default - in case value from eng/common/templates/post-build/common-variables.yml is not passed - BinlogToolVersion: '1.0.11' - steps: -- task: Powershell@2 - displayName: Prepare Binlogs to Upload - inputs: - targetType: inline - script: | - New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - continueOnError: true - condition: always() - -- task: PowerShell@2 - displayName: Redact Logs - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/redact-logs.ps1 - # For now this needs to have explicit list of all sensitive data. Taken from eng/publishing/v3/publish.yml - # Sensitive data can as well be added to $(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' - # If the file exists - sensitive data for redaction will be sourced from it - # (single entry per line, lines starting with '# ' are considered comments and skipped) - arguments: -InputPath '$(Build.SourcesDirectory)/PostBuildLogs' - -BinlogToolVersion ${{parameters.BinlogToolVersion}} - -TokensFilePath '$(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' - '$(publishing-dnceng-devdiv-code-r-build-re)' - '$(MaestroAccessToken)' - '$(dn-bot-all-orgs-artifact-feeds-rw)' - '$(akams-client-id)' - '$(akams-client-secret)' - '$(microsoft-symbol-server-pat)' - '$(symweb-symbol-server-pat)' - '$(dn-bot-all-orgs-build-rw-code-rw)' - ${{parameters.CustomSensitiveDataList}} - continueOnError: true - condition: always() - -- task: PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/PostBuildLogs' - PublishLocation: Container - ArtifactName: PostBuildLogs - continueOnError: true - condition: always() +- template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/publish-pipeline-artifacts.yml b/eng/common/templates/steps/publish-pipeline-artifacts.yml new file mode 100644 index 000000000000..5dd698b212fc --- /dev/null +++ b/eng/common/templates/steps/publish-pipeline-artifacts.yml @@ -0,0 +1,34 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false + +- name: args + type: object + default: {} + +steps: +- ${{ if eq(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates cannot be referenced from a 1ES managed template': error +- task: PublishPipelineArtifact@1 + displayName: ${{ coalesce(parameters.args.displayName, 'Publish to Build Artifact') }} + ${{ if parameters.args.condition }}: + condition: ${{ parameters.args.condition }} + ${{ else }}: + condition: succeeded() + ${{ if parameters.args.continueOnError }}: + continueOnError: ${{ parameters.args.continueOnError }} + inputs: + targetPath: ${{ parameters.args.targetPath }} + ${{ if parameters.args.artifactName }}: + artifactName: ${{ parameters.args.artifactName }} + ${{ if parameters.args.publishLocation }}: + publishLocation: ${{ parameters.args.publishLocation }} + ${{ if parameters.args.fileSharePath }}: + fileSharePath: ${{ parameters.args.fileSharePath }} + ${{ if parameters.args.Parallel }}: + parallel: ${{ parameters.args.Parallel }} + ${{ if parameters.args.parallelCount }}: + parallelCount: ${{ parameters.args.parallelCount }} + ${{ if parameters.args.properties }}: + properties: ${{ parameters.args.properties }} \ No newline at end of file diff --git a/eng/common/templates/steps/retain-build.yml b/eng/common/templates/steps/retain-build.yml index 83d97a26a01f..8e841ace3d29 100644 --- a/eng/common/templates/steps/retain-build.yml +++ b/eng/common/templates/steps/retain-build.yml @@ -1,28 +1,7 @@ -parameters: - # Optional azure devops PAT with build execute permissions for the build's organization, - # only needed if the build that should be retained ran on a different organization than - # the pipeline where this template is executing from - Token: '' - # Optional BuildId to retain, defaults to the current running build - BuildId: '' - # Azure devops Organization URI for the build in the https://dev.azure.com/ format. - # Defaults to the organization the current pipeline is running on - AzdoOrgUri: '$(System.CollectionUri)' - # Azure devops project for the build. Defaults to the project the current pipeline is running on - AzdoProject: '$(System.TeamProject)' - steps: - - task: powershell@2 - inputs: - targetType: 'filePath' - filePath: eng/common/retain-build.ps1 - pwsh: true - arguments: > - -AzdoOrgUri: ${{parameters.AzdoOrgUri}} - -AzdoProject ${{parameters.AzdoProject}} - -Token ${{coalesce(parameters.Token, '$env:SYSTEM_ACCESSTOKEN') }} - -BuildId ${{coalesce(parameters.BuildId, '$env:BUILD_ID')}} - displayName: Enable permanent build retention - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - BUILD_ID: $(Build.BuildId) \ No newline at end of file +- template: /eng/common/core-templates/steps/retain-build.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/run-on-unix.yml b/eng/common/templates/steps/run-on-unix.yml deleted file mode 100644 index e1733814f65d..000000000000 --- a/eng/common/templates/steps/run-on-unix.yml +++ /dev/null @@ -1,7 +0,0 @@ -parameters: - agentOs: '' - steps: [] - -steps: -- ${{ if ne(parameters.agentOs, 'Windows_NT') }}: - - ${{ parameters.steps }} diff --git a/eng/common/templates/steps/run-on-windows.yml b/eng/common/templates/steps/run-on-windows.yml deleted file mode 100644 index 73e7e9c275a1..000000000000 --- a/eng/common/templates/steps/run-on-windows.yml +++ /dev/null @@ -1,7 +0,0 @@ -parameters: - agentOs: '' - steps: [] - -steps: -- ${{ if eq(parameters.agentOs, 'Windows_NT') }}: - - ${{ parameters.steps }} diff --git a/eng/common/templates/steps/run-script-ifequalelse.yml b/eng/common/templates/steps/run-script-ifequalelse.yml deleted file mode 100644 index 3d1242f5587c..000000000000 --- a/eng/common/templates/steps/run-script-ifequalelse.yml +++ /dev/null @@ -1,33 +0,0 @@ -parameters: - # if parameter1 equals parameter 2, run 'ifScript' command, else run 'elsescript' command - parameter1: '' - parameter2: '' - ifScript: '' - elseScript: '' - - # name of script step - name: Script - - # display name of script step - displayName: If-Equal-Else Script - - # environment - env: {} - - # conditional expression for step execution - condition: '' - -steps: -- ${{ if and(ne(parameters.ifScript, ''), eq(parameters.parameter1, parameters.parameter2)) }}: - - script: ${{ parameters.ifScript }} - name: ${{ parameters.name }} - displayName: ${{ parameters.displayName }} - env: ${{ parameters.env }} - condition: ${{ parameters.condition }} - -- ${{ if and(ne(parameters.elseScript, ''), ne(parameters.parameter1, parameters.parameter2)) }}: - - script: ${{ parameters.elseScript }} - name: ${{ parameters.name }} - displayName: ${{ parameters.displayName }} - env: ${{ parameters.env }} - condition: ${{ parameters.condition }} \ No newline at end of file diff --git a/eng/common/templates/steps/send-to-helix.yml b/eng/common/templates/steps/send-to-helix.yml index 68fa739c4ab2..39f99fc2762d 100644 --- a/eng/common/templates/steps/send-to-helix.yml +++ b/eng/common/templates/steps/send-to-helix.yml @@ -1,93 +1,7 @@ -# Please remember to update the documentation if you make changes to these parameters! -parameters: - HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/ - HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' - HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number - HelixTargetQueues: '' # required -- semicolon-delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues - HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group - HelixProjectPath: 'eng/common/helixpublish.proj' # optional -- path to the project file to build relative to BUILD_SOURCESDIRECTORY - HelixProjectArguments: '' # optional -- arguments passed to the build command - HelixConfiguration: '' # optional -- additional property attached to a job - HelixPreCommands: '' # optional -- commands to run before Helix work item execution - HelixPostCommands: '' # optional -- commands to run after Helix work item execution - WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects - WorkItemCommand: '' # optional -- a command to execute on the payload; requires WorkItemDirectory; incompatible with XUnitProjects - WorkItemTimeout: '' # optional -- a timeout in TimeSpan.Parse-ready value (e.g. 00:02:00) for the work item command; requires WorkItemDirectory; incompatible with XUnitProjects - CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload - XUnitProjects: '' # optional -- semicolon-delimited list of XUnitProjects to parse and send to Helix; requires XUnitRuntimeTargetFramework, XUnitPublishTargetFramework, XUnitRunnerVersion, and IncludeDotNetCli=true - XUnitWorkItemTimeout: '' # optional -- the workitem timeout in seconds for all workitems created from the xUnit projects specified by XUnitProjects - XUnitPublishTargetFramework: '' # optional -- framework to use to publish your xUnit projects - XUnitRuntimeTargetFramework: '' # optional -- framework to use for the xUnit console runner - XUnitRunnerVersion: '' # optional -- version of the xUnit nuget package you wish to use on Helix; required for XUnitProjects - IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion - DotNetCliPackageType: '' # optional -- either 'sdk', 'runtime' or 'aspnetcore-runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." - IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set - HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting https://helix.int-dot.net ) - Creator: '' # optional -- if the build is external, use this to specify who is sending the job - DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO - condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() - continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false - steps: - - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' - displayName: ${{ parameters.DisplayNamePrefix }} (Windows) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog - displayName: ${{ parameters.DisplayNamePrefix }} (Unix) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} +- template: /eng/common/core-templates/steps/send-to-helix.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/source-build.yml b/eng/common/templates/steps/source-build.yml index 32738aa93801..23c1d6f4e9f8 100644 --- a/eng/common/templates/steps/source-build.yml +++ b/eng/common/templates/steps/source-build.yml @@ -1,131 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. - - # This is a 'steps' template, and is intended for advanced scenarios where the existing build - # infra has a careful build methodology that must be followed. For example, a repo - # (dotnet/runtime) might choose to clone the GitHub repo only once and store it as a pipeline - # artifact for all subsequent jobs to use, to reduce dependence on a strong network connection to - # GitHub. Using this steps template leaves room for that infra to be included. - - # Defines the platform on which to run the steps. See 'eng/common/templates/job/source-build.yml' - # for details. The entire object is described in the 'job' template for simplicity, even though - # the usage of the properties on this object is split between the 'job' and 'steps' templates. - platform: {} - steps: -# Build. Keep it self-contained for simple reusability. (No source-build-specific job variables.) -- script: | - set -x - df -h - - # If building on the internal project, the artifact feeds variable may be available (usually only if needed) - # In that case, call the feed setup script to add internal feeds corresponding to public ones. - # In addition, add an msbuild argument to copy the WIP from the repo to the target build location. - # This is because SetupNuGetSources.sh will alter the current NuGet.config file, and we need to preserve those - # changes. - internalRestoreArgs= - if [ '$(dn-bot-dnceng-artifact-feeds-rw)' != '$''(dn-bot-dnceng-artifact-feeds-rw)' ]; then - # Temporarily work around https://github.com/dotnet/arcade/issues/7709 - chmod +x $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh - $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh $(Build.SourcesDirectory)/NuGet.config $(dn-bot-dnceng-artifact-feeds-rw) - internalRestoreArgs='/p:CopyWipIntoInnerSourceBuildRepo=true' - - # The 'Copy WIP' feature of source build uses git stash to apply changes from the original repo. - # This only works if there is a username/email configured, which won't be the case in most CI runs. - git config --get user.email - if [ $? -ne 0 ]; then - git config user.email dn-bot@microsoft.com - git config user.name dn-bot - fi - fi - - # If building on the internal project, the internal storage variable may be available (usually only if needed) - # In that case, add variables to allow the download of internal runtimes if the specified versions are not found - # in the default public locations. - internalRuntimeDownloadArgs= - if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then - internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://dotnetbuilds.blob.core.windows.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://dotnetbuilds.blob.core.windows.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' - fi - - buildConfig=Release - # Check if AzDO substitutes in a build config from a variable, and use it if so. - if [ '$(_BuildConfig)' != '$''(_BuildConfig)' ]; then - buildConfig='$(_BuildConfig)' - fi - - officialBuildArgs= - if [ '${{ and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}' = 'True' ]; then - officialBuildArgs='/p:DotNetPublishUsingPipelines=true /p:OfficialBuildId=$(BUILD.BUILDNUMBER)' - fi - - targetRidArgs= - if [ '${{ parameters.platform.targetRID }}' != '' ]; then - targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' - fi - - runtimeOsArgs= - if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then - runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' - fi - - baseOsArgs= - if [ '${{ parameters.platform.baseOS }}' != '' ]; then - baseOsArgs='/p:BaseOS=${{ parameters.platform.baseOS }}' - fi - - publishArgs= - if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then - publishArgs='--publish' - fi - - assetManifestFileName=SourceBuild_RidSpecific.xml - if [ '${{ parameters.platform.name }}' != '' ]; then - assetManifestFileName=SourceBuild_${{ parameters.platform.name }}.xml - fi - - ${{ coalesce(parameters.platform.buildScript, './build.sh') }} --ci \ - --configuration $buildConfig \ - --restore --build --pack $publishArgs -bl \ - $officialBuildArgs \ - $internalRuntimeDownloadArgs \ - $internalRestoreArgs \ - $targetRidArgs \ - $runtimeOsArgs \ - $baseOsArgs \ - /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ - /p:ArcadeBuildFromSource=true \ - /p:DotNetBuildSourceOnly=true \ - /p:DotNetBuildRepo=true \ - /p:AssetManifestFileName=$assetManifestFileName - displayName: Build - -# Upload build logs for diagnosis. -- task: CopyFiles@2 - displayName: Prepare BuildLogs staging directory - inputs: - SourceFolder: '$(Build.SourcesDirectory)' - Contents: | - **/*.log - **/*.binlog - artifacts/sb/prebuilt-report/** - TargetFolder: '$(Build.StagingDirectory)/BuildLogs' - CleanTargetFolder: true - continueOnError: true - condition: succeededOrFailed() - -- task: PublishPipelineArtifact@1 - displayName: Publish BuildLogs - inputs: - targetPath: '$(Build.StagingDirectory)/BuildLogs' - artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) - continueOnError: true - condition: succeededOrFailed() +- template: /eng/common/core-templates/steps/source-build.yml + parameters: + is1ESPipeline: false -# Manually inject component detection so that we can ignore the source build upstream cache, which contains -# a nupkg cache of input packages (a local feed). -# This path must match the upstream cache path in property 'CurrentRepoSourceBuiltNupkgCacheDir' -# in src\Microsoft.DotNet.Arcade.Sdk\tools\SourceBuild\SourceBuildArcade.targets -- task: ComponentGovernanceComponentDetection@0 - displayName: Component Detection (Exclude upstream cache) - inputs: - ignoreDirectories: '$(Build.SourcesDirectory)/artifacts/sb/src/artifacts/obj/source-built-upstream-cache' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/telemetry-end.yml b/eng/common/templates/steps/telemetry-end.yml deleted file mode 100644 index fadc04ca1b9a..000000000000 --- a/eng/common/templates/steps/telemetry-end.yml +++ /dev/null @@ -1,102 +0,0 @@ -parameters: - maxRetries: 5 - retryDelay: 10 # in seconds - -steps: -- bash: | - if [ "$AGENT_JOBSTATUS" = "Succeeded" ] || [ "$AGENT_JOBSTATUS" = "PartiallySucceeded" ]; then - errorCount=0 - else - errorCount=1 - fi - warningCount=0 - - curlStatus=1 - retryCount=0 - # retry loop to harden against spotty telemetry connections - # we don't retry successes and 4xx client errors - until [[ $curlStatus -eq 0 || ( $curlStatus -ge 400 && $curlStatus -le 499 ) || $retryCount -ge $MaxRetries ]] - do - if [ $retryCount -gt 0 ]; then - echo "Failed to send telemetry to Helix; waiting $RetryDelay seconds before retrying..." - sleep $RetryDelay - fi - - # create a temporary file for curl output - res=`mktemp` - - curlResult=` - curl --verbose --output $res --write-out "%{http_code}"\ - -H 'Content-Type: application/json' \ - -H "X-Helix-Job-Token: $Helix_JobToken" \ - -H 'Content-Length: 0' \ - -X POST -G "https://helix.dot.net/api/2018-03-14/telemetry/job/build/$Helix_WorkItemId/finish" \ - --data-urlencode "errorCount=$errorCount" \ - --data-urlencode "warningCount=$warningCount"` - curlStatus=$? - - if [ $curlStatus -eq 0 ]; then - if [ $curlResult -gt 299 ] || [ $curlResult -lt 200 ]; then - curlStatus=$curlResult - fi - fi - - let retryCount++ - done - - if [ $curlStatus -ne 0 ]; then - echo "Failed to Send Build Finish information after $retryCount retries" - vstsLogOutput="vso[task.logissue type=error;sourcepath=templates/steps/telemetry-end.yml;code=1;]Failed to Send Build Finish information: $curlStatus" - echo "##$vstsLogOutput" - exit 1 - fi - displayName: Send Unix Build End Telemetry - env: - # defined via VSTS variables in start-job.sh - Helix_JobToken: $(Helix_JobToken) - Helix_WorkItemId: $(Helix_WorkItemId) - MaxRetries: ${{ parameters.maxRetries }} - RetryDelay: ${{ parameters.retryDelay }} - condition: and(always(), ne(variables['Agent.Os'], 'Windows_NT')) -- powershell: | - if (($env:Agent_JobStatus -eq 'Succeeded') -or ($env:Agent_JobStatus -eq 'PartiallySucceeded')) { - $ErrorCount = 0 - } else { - $ErrorCount = 1 - } - $WarningCount = 0 - - # Basic retry loop to harden against server flakiness - $retryCount = 0 - while ($retryCount -lt $env:MaxRetries) { - try { - Invoke-RestMethod -Uri "https://helix.dot.net/api/2018-03-14/telemetry/job/build/$env:Helix_WorkItemId/finish?errorCount=$ErrorCount&warningCount=$WarningCount" -Method Post -ContentType "application/json" -Body "" ` - -Headers @{ 'X-Helix-Job-Token'=$env:Helix_JobToken } - break - } - catch { - $statusCode = $_.Exception.Response.StatusCode.value__ - if ($statusCode -ge 400 -and $statusCode -le 499) { - Write-Host "##vso[task.logissue]error Failed to send telemetry to Helix (status code $statusCode); not retrying (4xx client error)" - Write-Host "##vso[task.logissue]error ", $_.Exception.GetType().FullName, $_.Exception.Message - exit 1 - } - Write-Host "Failed to send telemetry to Helix (status code $statusCode); waiting $env:RetryDelay seconds before retrying..." - $retryCount++ - sleep $env:RetryDelay - continue - } - } - - if ($retryCount -ge $env:MaxRetries) { - Write-Host "##vso[task.logissue]error Failed to send telemetry to Helix after $retryCount retries." - exit 1 - } - displayName: Send Windows Build End Telemetry - env: - # defined via VSTS variables in start-job.ps1 - Helix_JobToken: $(Helix_JobToken) - Helix_WorkItemId: $(Helix_WorkItemId) - MaxRetries: ${{ parameters.maxRetries }} - RetryDelay: ${{ parameters.retryDelay }} - condition: and(always(),eq(variables['Agent.Os'], 'Windows_NT')) diff --git a/eng/common/templates/steps/telemetry-start.yml b/eng/common/templates/steps/telemetry-start.yml deleted file mode 100644 index 32c01ef0b553..000000000000 --- a/eng/common/templates/steps/telemetry-start.yml +++ /dev/null @@ -1,241 +0,0 @@ -parameters: - helixSource: 'undefined_defaulted_in_telemetry.yml' - helixType: 'undefined_defaulted_in_telemetry.yml' - buildConfig: '' - runAsPublic: false - maxRetries: 5 - retryDelay: 10 # in seconds - -steps: -- ${{ if and(eq(parameters.runAsPublic, 'false'), not(eq(variables['System.TeamProject'], 'public'))) }}: - - task: AzureKeyVault@1 - inputs: - azureSubscription: 'HelixProd_KeyVault' - KeyVaultName: HelixProdKV - SecretsFilter: 'HelixApiAccessToken' - condition: always() -- bash: | - # create a temporary file - jobInfo=`mktemp` - - # write job info content to temporary file - cat > $jobInfo < false - - true + + true $(IntermediateOutputPath)ILLink.Resources.Substitutions.xml true diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets index c4c03648e2e3..d739736338e4 100644 --- a/eng/liveBuilds.targets +++ b/eng/liveBuilds.targets @@ -216,6 +216,7 @@ $(LibrariesNativeArtifactsPath)dotnet.js; $(LibrariesNativeArtifactsPath)dotnet.js.map; $(LibrariesNativeArtifactsPath)dotnet.native.js; + $(LibrariesNativeArtifactsPath)dotnet.globalization.js; $(LibrariesNativeArtifactsPath)dotnet.runtime.js; $(LibrariesNativeArtifactsPath)dotnet.runtime.js.map; $(LibrariesNativeArtifactsPath)dotnet.d.ts; diff --git a/eng/liveILLink.targets b/eng/liveILLink.targets index f18b89622982..6b45e00a49d5 100644 --- a/eng/liveILLink.targets +++ b/eng/liveILLink.targets @@ -30,11 +30,13 @@ + + SetConfiguration="Configuration=$(ToolsConfiguration)" + GlobalPropertiesToRemove="TargetArchitecture;TargetOS" > TargetFramework=$(NetCoreAppToolCurrent) TargetFramework=$(NetFrameworkToolCurrent) diff --git a/eng/native/build-commons.sh b/eng/native/build-commons.sh index 0916abb396fa..2cf33442a932 100755 --- a/eng/native/build-commons.sh +++ b/eng/native/build-commons.sh @@ -109,7 +109,7 @@ build_native() # set default iOS simulator deployment target # keep in sync with SetOSTargetMinVersions in the root Directory.Build.props - cmakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $cmakeArgs" + cmakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $cmakeArgs" if [[ "$__TargetArch" == x64 ]]; then cmakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"x86_64\" $cmakeArgs" elif [[ "$__TargetArch" == arm64 ]]; then @@ -123,7 +123,7 @@ build_native() # set default iOS device deployment target # keep in sync with SetOSTargetMinVersions in the root Directory.Build.props - cmakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $cmakeArgs" + cmakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $cmakeArgs" if [[ "$__TargetArch" == arm64 ]]; then cmakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"arm64\" $cmakeArgs" else @@ -135,7 +135,7 @@ build_native() # set default tvOS simulator deployment target # keep in sync with SetOSTargetMinVersions in the root Directory.Build.props - cmakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $cmakeArgs" + cmakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $cmakeArgs" if [[ "$__TargetArch" == x64 ]]; then cmakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"x86_64\" $cmakeArgs" elif [[ "$__TargetArch" == arm64 ]]; then @@ -149,7 +149,7 @@ build_native() # set default tvOS device deployment target # keep in sync with SetOSTargetMinVersions in the root Directory.Build.props - cmakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $cmakeArgs" + cmakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $cmakeArgs" if [[ "$__TargetArch" == arm64 ]]; then cmakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"arm64\" $cmakeArgs" else diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index 18dc063e51e0..04436c0dd4b6 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -14,6 +14,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) +include(CheckLinkerFlag) # "configureoptimization.cmake" must be included after CLR_CMAKE_HOST_UNIX has been set. include(${CMAKE_CURRENT_LIST_DIR}/configureoptimization.cmake) @@ -210,8 +211,8 @@ if (CLR_CMAKE_ENABLE_SANITIZERS) # Disable the use-after-return check for ASAN on Clang. This is because we have a lot of code that # depends on the fact that our locals are not saved in a parallel stack, so we can't enable this today. # If we ever have a way to detect a parallel stack and track its bounds, we can re-enable this check. - add_compile_options($<$:-fsanitize-address-use-after-return=never>) - add_compile_options($<$:-fsanitize-address-use-after-return=never>) + add_compile_options($<$:-fsanitize-address-use-after-return=never>) + add_compile_options($<$:-fsanitize-address-use-after-return=never>) endif() endif() @@ -300,7 +301,13 @@ elseif(CLR_CMAKE_HOST_SUNOS) add_definitions(-D__EXTENSIONS__ -D_XPG4_2 -D_POSIX_PTHREAD_SEMANTICS) elseif(CLR_CMAKE_HOST_OSX AND NOT CLR_CMAKE_HOST_MACCATALYST AND NOT CLR_CMAKE_HOST_IOS AND NOT CLR_CMAKE_HOST_TVOS) add_definitions(-D_XOPEN_SOURCE) - add_linker_flag("-Wl,-bind_at_load") + + # the new linker in Xcode 15 (ld_new/ld_prime) deprecated the -bind_at_load flag for macOS which causes a warning + # that fails the build since we build with -Werror. Only pass the flag if we need it, i.e. older linkers. + check_linker_flag(C "-Wl,-bind_at_load,-fatal_warnings" LINKER_SUPPORTS_BIND_AT_LOAD_FLAG) + if(LINKER_SUPPORTS_BIND_AT_LOAD_FLAG) + add_linker_flag("-Wl,-bind_at_load") + endif() elseif(CLR_CMAKE_HOST_HAIKU) add_compile_options($<$:-Wa,--noexecstack>) add_linker_flag("-Wl,--no-undefined") @@ -667,11 +674,11 @@ if (CLR_CMAKE_HOST_UNIX) set(DISABLE_OVERRIDING_MIN_VERSION_ERROR -Wno-overriding-t-option) add_link_options(-Wno-overriding-t-option) if(CLR_CMAKE_HOST_ARCH_ARM64) - set(MACOS_VERSION_MIN_FLAGS "-target arm64-apple-ios14.2-macabi") - add_link_options(-target arm64-apple-ios14.2-macabi) + set(MACOS_VERSION_MIN_FLAGS "-target arm64-apple-ios15.0-macabi") + add_link_options(-target arm64-apple-ios15.0-macabi) elseif(CLR_CMAKE_HOST_ARCH_AMD64) - set(MACOS_VERSION_MIN_FLAGS "-target x86_64-apple-ios13.5-macabi") - add_link_options(-target x86_64-apple-ios13.5-macabi) + set(MACOS_VERSION_MIN_FLAGS "-target x86_64-apple-ios15.0-macabi") + add_link_options(-target x86_64-apple-ios15.0-macabi) else() clr_unknown_arch() endif() @@ -684,11 +691,10 @@ if (CLR_CMAKE_HOST_UNIX) set(CMAKE_OBJC_FLAGS "${CMAKE_OBJC_FLAGS} ${MACOS_VERSION_MIN_FLAGS} ${DISABLE_OVERRIDING_MIN_VERSION_ERROR}") set(CMAKE_OBJCXX_FLAGS "${CMAKE_OBJCXX_FLAGS} ${MACOS_VERSION_MIN_FLAGS} ${DISABLE_OVERRIDING_MIN_VERSION_ERROR}") elseif(CLR_CMAKE_HOST_OSX) + set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0") if(CLR_CMAKE_HOST_ARCH_ARM64) - set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0") add_compile_options(-arch arm64) elseif(CLR_CMAKE_HOST_ARCH_AMD64) - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15") add_compile_options(-arch x86_64) else() clr_unknown_arch() diff --git a/eng/native/gen-buildsys.cmd b/eng/native/gen-buildsys.cmd index 7de701b7be36..4e69470c73e8 100644 --- a/eng/native/gen-buildsys.cmd +++ b/eng/native/gen-buildsys.cmd @@ -53,7 +53,7 @@ if /i "%__Arch%" == "wasm" ( if /i "%__Os%" == "wasi" ( if "%WASI_SDK_PATH%" == "" ( if not exist "%__repoRoot%\src\mono\wasi\wasi-sdk" ( - echo Error: Should set WASI_SDK_PATH environment variable pointing to wasi-sdk root. + echo Error: Should set WASI_SDK_PATH environment variable pointing to WASI SDK root. exit /B 1 ) diff --git a/eng/native/sanitizer-ignorelist.txt b/eng/native/sanitizer-ignorelist.txt index ecc8bef9bf68..8e89d3ca960d 100644 --- a/eng/native/sanitizer-ignorelist.txt +++ b/eng/native/sanitizer-ignorelist.txt @@ -10,5 +10,5 @@ fun:_ZN11CMiniMdBase19UsesAllocatedMemoryEP11CMiniColDef # 2 0x4e8051 in __ubsan_handle_dynamic_type_cache_miss # 3 0x7f02ce676cd8 in JIT_InitPInvokeFrame(InlinedCallFrame*, void*) /home/steveharter/git/dotnet_coreclr/vm/jithelpers.cpp:6491:9 # 4 0x7f0252bbceb2 () -fun:_Z20JIT_InitPInvokeFrameP16InlinedCallFramePv +fun:_Z20JIT_InitPInvokeFrameP16InlinedCallFrame diff --git a/eng/nativeSanitizers.targets b/eng/nativeSanitizers.targets index 69ec76b93487..bcaec8691450 100644 --- a/eng/nativeSanitizers.targets +++ b/eng/nativeSanitizers.targets @@ -12,7 +12,7 @@ arm64 - + diff --git a/eng/pipelines/common/evaluate-default-paths.yml b/eng/pipelines/common/evaluate-default-paths.yml index edbc1c618f60..5d9373ea3cb0 100644 --- a/eng/pipelines/common/evaluate-default-paths.yml +++ b/eng/pipelines/common/evaluate-default-paths.yml @@ -7,7 +7,7 @@ parameters: _const_paths: _wasm_specific_only: [ eng/testing/bump-chrome-version.proj - eng/testing/ChromeVersions.props + eng/testing/BrowserVersions.props eng/testing/WasmRunner* eng/testing/WasiRunner* eng/testing/scenarios/BuildWasiAppsJobsList.txt @@ -22,6 +22,7 @@ parameters: src/libraries/sendtohelix-browser.targets src/libraries/sendtohelix-wasi.targets src/libraries/sendtohelix-wasm.targets + src/libraries/System.Runtime.InteropServices.JavaScript/* src/mono/mono/**/*wasm* src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/* src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk/* @@ -57,7 +58,7 @@ parameters: ] _wasm_chrome: [ eng/testing/bump-chrome-version.proj - eng/testing/ChromeVersions.props + eng/testing/BrowserVersions.props ] _perf_pipeline_specific_only: [ eng/pipelines/runtime-wasm-perf.yml @@ -161,8 +162,14 @@ jobs: - subset: tools_illink include: - src/tools/illink/* + - src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/* + - src/coreclr/tools/ILVerification/* - global.json + - subset: tools_cdacreader + include: + - src/native/managed/cdacreader/* + - subset: installer include: exclude: diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml index 1f0f14ac0b32..e19a92e62077 100644 --- a/eng/pipelines/common/global-build-job.yml +++ b/eng/pipelines/common/global-build-job.yml @@ -25,8 +25,6 @@ parameters: useContinueOnErrorDuringBuild: false shouldContinueOnError: false isOfficialBuild: false - isSourceBuild: false - isNonPortableSourceBuild: false runtimeFlavor: 'coreclr' runtimeVariant: '' helixQueues: '' @@ -34,12 +32,9 @@ parameters: testResultsFormat: '' postBuildSteps: [] extraVariablesTemplates: [] - isManualCodeQLBuild: false preBuildSteps: [] - enableRichCodeNavigation: false - richCodeNavigationLanguage: 'csharp' - disableComponentGovernance: '' templatePath: 'templates' + templateContext: '' jobs: - template: /eng/common/${{ parameters.templatePath }}/job/job.yml @@ -57,8 +52,8 @@ jobs: enablePublishTestResults: ${{ parameters.enablePublishTestResults }} testResultsFormat: ${{ parameters.testResultsFormat }} - enableRichCodeNavigation: ${{ parameters.enableRichCodeNavigation }} - richCodeNavigationLanguage: ${{ parameters.richCodeNavigationLanguage }} + ${{ if ne(parameters.templateContext, '') }}: + templateContext: ${{ parameters.templateContext }} artifacts: publish: @@ -104,10 +99,26 @@ jobs: - name: crossArg value: '-cross' - - ${{ if ne(parameters.jobParameters.crossrootfsDir, '') }}: - # This is only required for cross builds. - - name: ROOTFS_DIR - value: ${{ parameters.jobParameters.crossrootfsDir }} + - name: CxxStandardLibraryArg + value: '' + - ${{ if ne(parameters.cxxStandardLibrary, '') }}: + - name: CxxStandardLibraryArg + value: /p:TargetCxxStandardLibrary=${{ parameters.cxxStandardLibrary }} + + - name: CxxStandardLibraryStaticArg + value: '' + - ${{ if ne(parameters.cxxStandardLibraryStatic, '') }}: + - name: CxxStandardLibraryStaticArg + value: /p:TargetCxxStandardLibraryStatic=${{ parameters.cxxStandardLibraryStatic }} + + - name: CxxAbiLibraryArg + value: '' + - ${{ if ne(parameters.cxxAbiLibrary, '') }}: + - name: CxxAbiLibraryArg + value: /p:TargetCxxAbiLibrary=${{ parameters.cxxAbiLibrary }} + + - name: TargetCxxLibraryConfigurationArgs + value: $(CxxStandardLibraryArg) $(CxxStandardLibraryStaticArg) $(CxxAbiLibraryArg) - name: _officialBuildParameter ${{ if eq(parameters.isOfficialBuild, true) }}: @@ -154,10 +165,7 @@ jobs: - checkout: self clean: true - # If running in source build mode, a git stash will be used for the inner clone. Avoid setting a fetch depth, - # as a stash of a shallow cloned repo is not currently supported. - ${{ if ne(parameters.isSourceBuild, true) }}: - fetchDepth: $(checkoutFetchDepth) + fetchDepth: $(checkoutFetchDepth) - ${{ if and(eq(parameters.isOfficialBuild, true), notin(parameters.osGroup, 'osx', 'maccatalyst', 'ios', 'iossimulator', 'tvos', 'tvossimulator')) }}: - template: /eng/pipelines/common/restore-internal-tools.yml @@ -187,16 +195,6 @@ jobs: artifact: Mono_Offsets_${{monoCrossAOTTargetOS}} path: '$(Build.SourcesDirectory)/artifacts/obj/mono/offsetfiles' - - ${{ if eq(parameters.isSourceBuild, true) }}: - - template: /eng/common/${{ parameters.templatePath }}/steps/source-build.yml - parameters: - platform: - baseOS: ${{ parameters.baseOS }} - buildScript: $(Build.SourcesDirectory)$(dir)build$(scriptExt) - nonPortable: ${{ parameters.isNonPortableSourceBuild }} - targetRID: ${{ parameters.targetRid }} - name: ${{ parameters.platform }} - - ${{ if in(parameters.osGroup, 'osx', 'maccatalyst', 'ios', 'iossimulator', 'tvos', 'tvossimulator') }}: - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh ${{ parameters.osGroup }} displayName: Install Build Dependencies @@ -250,7 +248,6 @@ jobs: targetRid: ${{ parameters.targetRid }} nameSuffix: ${{ parameters.nameSuffix }} platform: ${{ parameters.platform }} - pgoType: ${{ parameters.pgoType }} shouldContinueOnError: ${{ parameters.shouldContinueOnError }} ${{ if ne(preBuildStep.forwardedParameters, '') }}: ${{ each parameter in preBuildStep.forwardedParameters }}: @@ -261,21 +258,11 @@ jobs: - ${{ preBuildStep }} # Build - - ${{ if eq(parameters.isSourceBuild, false) }}: - - ${{ if eq(parameters.isManualCodeQLBuild, true) }}: - - task: CodeQL3000Init@0 - displayName: Initialize CodeQL (manually-injected) - - - template: /eng/pipelines/common/templates/global-build-step.yml - parameters: - buildArgs: ${{ parameters.buildArgs }} - useContinueOnErrorDuringBuild: ${{ parameters.useContinueOnErrorDuringBuild }} - shouldContinueOnError: ${{ parameters.shouldContinueOnError }} - - - ${{ if eq(parameters.isManualCodeQLBuild, true) }}: - - task: CodeQL3000Finalize@0 - displayName: Finalize CodeQL (manually-injected) - #endif isSourceBuild + - template: /eng/pipelines/common/templates/global-build-step.yml + parameters: + buildArgs: ${{ parameters.buildArgs }} + useContinueOnErrorDuringBuild: ${{ parameters.useContinueOnErrorDuringBuild }} + shouldContinueOnError: ${{ parameters.shouldContinueOnError }} - ${{ if in(parameters.osGroup, 'osx', 'ios', 'tvos', 'android') }}: - script: | diff --git a/eng/pipelines/common/platform-matrix.yml b/eng/pipelines/common/platform-matrix.yml index 7245e5216804..49f9ba6e3f24 100644 --- a/eng/pipelines/common/platform-matrix.yml +++ b/eng/pipelines/common/platform-matrix.yml @@ -253,30 +253,7 @@ jobs: crossBuild: true ${{ insert }}: ${{ parameters.jobParameters }} -# Linux x86 - -- ${{ if containsValue(parameters.platforms, 'linux_x86') }}: - - template: xplat-setup.yml - parameters: - jobTemplate: ${{ parameters.jobTemplate }} - helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }} - variables: ${{ parameters.variables }} - osGroup: linux - archType: x86 - targetRid: linux-x86 - platform: linux_x86 - shouldContinueOnError: ${{ parameters.shouldContinueOnError }} - container: linux_x86 - jobParameters: - runtimeFlavor: ${{ parameters.runtimeFlavor }} - buildConfig: ${{ parameters.buildConfig }} - helixQueueGroup: ${{ parameters.helixQueueGroup }} - crossBuild: true - ${{ insert }}: ${{ parameters.jobParameters }} - -# Runtime-dev-innerloop build - -- ${{ if containsValue(parameters.platforms, 'linux_x64_dev_innerloop') }}: +- ${{ if containsValue(parameters.platforms, 'linux_x64_sanitizer') }}: - template: xplat-setup.yml parameters: jobTemplate: ${{ parameters.jobTemplate }} @@ -287,38 +264,41 @@ jobs: targetRid: linux-x64 platform: linux_x64 shouldContinueOnError: ${{ parameters.shouldContinueOnError }} - container: linux_x64_dev_innerloop + container: linux_x64_sanitizer jobParameters: runtimeFlavor: ${{ parameters.runtimeFlavor }} buildConfig: ${{ parameters.buildConfig }} helixQueueGroup: ${{ parameters.helixQueueGroup }} + crossBuild: true + cxxStandardLibrary: libc++ + cxxStandardLibraryStatic: true + cxxAbiLibrary: libstdc++ ${{ insert }}: ${{ parameters.jobParameters }} -# Centos 8 Stream x64 Source Build +# Linux x86 -- ${{ if containsValue(parameters.platforms, 'SourceBuild_centos8_x64') }}: +- ${{ if containsValue(parameters.platforms, 'linux_x86') }}: - template: xplat-setup.yml parameters: jobTemplate: ${{ parameters.jobTemplate }} helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }} variables: ${{ parameters.variables }} osGroup: linux - archType: x64 - targetRid: centos.8-x64 - platform: centos8_linux_x64 + archType: x86 + targetRid: linux-x86 + platform: linux_x86 shouldContinueOnError: ${{ parameters.shouldContinueOnError }} - container: SourceBuild_centos_x64 + container: linux_x86 jobParameters: runtimeFlavor: ${{ parameters.runtimeFlavor }} buildConfig: ${{ parameters.buildConfig }} helixQueueGroup: ${{ parameters.helixQueueGroup }} - isSourceBuild: true - isNonPortableSourceBuild: true + crossBuild: true ${{ insert }}: ${{ parameters.jobParameters }} -# Non-existent RID Source Build +# Runtime-dev-innerloop build -- ${{ if containsValue(parameters.platforms, 'SourceBuild_banana24_x64') }}: +- ${{ if containsValue(parameters.platforms, 'linux_x64_dev_innerloop') }}: - template: xplat-setup.yml parameters: jobTemplate: ${{ parameters.jobTemplate }} @@ -326,39 +306,33 @@ jobs: variables: ${{ parameters.variables }} osGroup: linux archType: x64 - targetRid: banana.24-x64 - platform: banana24_linux_x64 + targetRid: linux-x64 + platform: linux_x64 shouldContinueOnError: ${{ parameters.shouldContinueOnError }} - container: SourceBuild_centos_x64 # Run the unknown-rid build on a platform with a known RID so our RID graph tooling can automatically add it to the RID graph. + container: linux_x64_dev_innerloop jobParameters: runtimeFlavor: ${{ parameters.runtimeFlavor }} - baseOS: linux buildConfig: ${{ parameters.buildConfig }} helixQueueGroup: ${{ parameters.helixQueueGroup }} - isSourceBuild: true - isNonPortableSourceBuild: true ${{ insert }}: ${{ parameters.jobParameters }} -# Portable Linux x64 Source Build - -- ${{ if containsValue(parameters.platforms, 'SourceBuild_linux_x64') }}: +- ${{ if containsValue(parameters.platforms, 'linux_musl_x64_dev_innerloop') }}: - template: xplat-setup.yml parameters: jobTemplate: ${{ parameters.jobTemplate }} helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }} variables: ${{ parameters.variables }} osGroup: linux + osSubgroup: _musl archType: x64 - targetRid: linux-x64 - platform: linux_x64 + targetRid: linux-musl-x64 + platform: linux_musl_x64 shouldContinueOnError: ${{ parameters.shouldContinueOnError }} - container: SourceBuild_linux_x64 + container: linux_musl_x64_dev_innerloop jobParameters: runtimeFlavor: ${{ parameters.runtimeFlavor }} buildConfig: ${{ parameters.buildConfig }} helixQueueGroup: ${{ parameters.helixQueueGroup }} - isSourceBuild: true - isNonPortableSourceBuild: false ${{ insert }}: ${{ parameters.jobParameters }} # GCC Linux x64 Build @@ -374,7 +348,7 @@ jobs: targetRid: linux-x64 platform: linux_x64 shouldContinueOnError: ${{ parameters.shouldContinueOnError }} - container: debian-12-gcc13-amd64 + container: debian-12-gcc14-amd64 jobParameters: runtimeFlavor: ${{ parameters.runtimeFlavor }} buildConfig: ${{ parameters.buildConfig }} diff --git a/eng/pipelines/common/templates/global-build-step.yml b/eng/pipelines/common/templates/global-build-step.yml index b88207c516c1..2a2262d9a4ea 100644 --- a/eng/pipelines/common/templates/global-build-step.yml +++ b/eng/pipelines/common/templates/global-build-step.yml @@ -4,12 +4,13 @@ parameters: shouldContinueOnError: false archParameter: $(_archParameter) crossArg: $(crossArg) + targetCxxLibraryConfigurationArgs: $(TargetCxxLibraryConfigurationArgs) displayName: Build product container: '' condition: succeeded() steps: - - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci ${{ parameters.archParameter }} $(_osParameter) ${{ parameters.crossArg }} ${{ parameters.buildArgs }} $(_officialBuildParameter) $(_buildDarwinFrameworksParameter) $(_overrideTestScriptWindowsCmdParameter) + - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci ${{ parameters.archParameter }} $(_osParameter) ${{ parameters.crossArg }} ${{ parameters.buildArgs }} ${{ parameters.targetCxxLibraryConfigurationArgs }} $(_officialBuildParameter) $(_buildDarwinFrameworksParameter) $(_overrideTestScriptWindowsCmdParameter) displayName: ${{ parameters.displayName }} ${{ if eq(parameters.useContinueOnErrorDuringBuild, true) }}: continueOnError: ${{ parameters.shouldContinueOnError }} diff --git a/eng/pipelines/common/templates/pipeline-with-resources.yml b/eng/pipelines/common/templates/pipeline-with-resources.yml index 5ae3a3f7a38f..dd10e2a4bbe0 100644 --- a/eng/pipelines/common/templates/pipeline-with-resources.yml +++ b/eng/pipelines/common/templates/pipeline-with-resources.yml @@ -17,7 +17,7 @@ extends: containers: linux_arm: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-arm + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0-20240507035943-1390eea env: ROOTFS_DIR: /crossrootfs/arm @@ -27,23 +27,22 @@ extends: ROOTFS_DIR: /crossrootfs/armv6 linux_arm64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-biarch-amd64-arm64 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm64-net9.0 env: - ROOTFS_HOST_DIR: /crossrootfs/x64 ROOTFS_DIR: /crossrootfs/arm64 linux_musl_x64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-amd64-alpine + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-amd64-alpine-net9.0 env: ROOTFS_DIR: /crossrootfs/x64 linux_musl_arm: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-arm-alpine + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-alpine-net9.0 env: ROOTFS_DIR: /crossrootfs/arm linux_musl_arm64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-arm64-alpine + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm64-alpine-net9.0 env: ROOTFS_DIR: /crossrootfs/arm64 @@ -56,18 +55,26 @@ extends: image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-android-docker linux_x64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-amd64 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-amd64-net9.0 env: ROOTFS_DIR: /crossrootfs/x64 linux_x86: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-x86 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-x86-net9.0 env: ROOTFS_DIR: /crossrootfs/x86 linux_x64_dev_innerloop: image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04 + linux_musl_x64_dev_innerloop: + image: mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.19-WithNode + + linux_x64_sanitizer: + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-amd64-net9.0-sanitizer + env: + ROOTFS_DIR: /crossrootfs/x64 + # We use a CentOS Stream 8 image here to test building from source on CentOS Stream 8. SourceBuild_centos_x64: image: mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8 @@ -77,12 +84,12 @@ extends: image: mcr.microsoft.com/dotnet-buildtools/prereqs:almalinux-8-source-build linux_s390x: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-cross-s390x + image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-s390x env: ROOTFS_DIR: /crossrootfs/s390x linux_ppc64le: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-cross-ppc64le + image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-ppc64le env: ROOTFS_DIR: /crossrootfs/ppc64le @@ -91,14 +98,14 @@ extends: env: ROOTFS_DIR: /crossrootfs/riscv64 - debian-12-gcc13-amd64: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-gcc13-amd64 + debian-12-gcc14-amd64: + image: mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-gcc14-amd64 linux_x64_llvmaot: image: mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8 browser_wasm: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-webassembly-20230913040940-1edc1c6 + image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-webassembly env: ROOTFS_DIR: /crossrootfs/x64 @@ -121,4 +128,4 @@ extends: image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-debpkg rpmpkg: - image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-fpm \ No newline at end of file + image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-fpm diff --git a/eng/pipelines/common/templates/publish-pipeline-artifacts.yml b/eng/pipelines/common/templates/publish-pipeline-artifacts.yml deleted file mode 100644 index 81f292ec5528..000000000000 --- a/eng/pipelines/common/templates/publish-pipeline-artifacts.yml +++ /dev/null @@ -1,17 +0,0 @@ -parameters: -- name: displayName - type: string -- name: inputs - type: object -- name: isOfficialBuild - type: boolean - -steps: - - ${{ if parameters.isOfficialBuild }}: - - task: 1ES.PublishPipelineArtifact@1 - displayName: ${{ parameters.displayName }} - inputs: ${{ parameters.inputs }} - - ${{ else }}: - - task: PublishPipelineArtifact@1 - displayName: ${{ parameters.displayName }} - inputs: ${{ parameters.inputs }} \ No newline at end of file diff --git a/eng/pipelines/common/templates/runtimes/run-test-job.yml b/eng/pipelines/common/templates/runtimes/run-test-job.yml index d6404617a3e1..0899b32fe524 100644 --- a/eng/pipelines/common/templates/runtimes/run-test-job.yml +++ b/eng/pipelines/common/templates/runtimes/run-test-job.yml @@ -537,6 +537,7 @@ jobs: - jitosr_stress - jitpartialcompilation_pgo - jitoptrepeat + - jitrpolayout ${{ else }}: scenarios: - jitosr_stress @@ -549,6 +550,7 @@ jobs: - jitphysicalpromotion_full - jitrlcse - jitoptrepeat + - jitrpolayout ${{ if in(parameters.testGroup, 'jit-cfg') }}: scenarios: - jitcfg diff --git a/eng/pipelines/common/templates/simple-wasm-build-tests.yml b/eng/pipelines/common/templates/simple-wasm-build-tests.yml index 7a593f4f9be2..273a80fc65ee 100644 --- a/eng/pipelines/common/templates/simple-wasm-build-tests.yml +++ b/eng/pipelines/common/templates/simple-wasm-build-tests.yml @@ -34,7 +34,7 @@ jobs: isExtraPlatforms: ${{ parameters.isExtraPlatformsBuild }} testGroup: innerloop nameSuffix: WasmBuildTests - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmBuildTests=true /p:TestAssemblies=false /p:BrowserHost=$(_hostedOs) /p:WorkloadsTestPreviousVersions=$(workloadsTestPreviousVersionsVar) ${{ parameters.extraBuildArgs }} + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:MonoEnableAssertMessages=true /p:ArchiveTests=true /p:TestWasmBuildTests=true /p:TestAssemblies=false /p:BrowserHost=$(_hostedOs) /p:WorkloadsTestPreviousVersions=$(workloadsTestPreviousVersionsVar) ${{ parameters.extraBuildArgs }} timeoutInMinutes: 180 condition: >- or( diff --git a/eng/pipelines/common/templates/template1es.yml b/eng/pipelines/common/templates/template1es.yml index 0770e37d6bd0..0964295750d2 100644 --- a/eng/pipelines/common/templates/template1es.yml +++ b/eng/pipelines/common/templates/template1es.yml @@ -15,11 +15,14 @@ resources: - repository: 1ESPipelineTemplates type: git name: 1ESPipelineTemplates/1ESPipelineTemplates - ref: refs/tags/release + ref: refs/tags/release-2024-05-13-1 extends: template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates parameters: + sdl: + credscan: + suppressionsFile: $(Build.SourcesDirectory)/.config/CredScanSuppressions.json pool: name: $(DncEngInternalBuildPool) image: 1es-windows-2022 @@ -28,4 +31,4 @@ extends: containers: ${{ parameters.containers }} - stages: ${{ parameters.stages }} \ No newline at end of file + stages: ${{ parameters.stages }} diff --git a/eng/pipelines/common/templates/wasm-library-aot-tests.yml b/eng/pipelines/common/templates/wasm-library-aot-tests.yml index 9937d44ef21f..2336f9840151 100644 --- a/eng/pipelines/common/templates/wasm-library-aot-tests.yml +++ b/eng/pipelines/common/templates/wasm-library-aot-tests.yml @@ -1,7 +1,7 @@ parameters: alwaysRun: false extraBuildArgs: '' - extraHelixArgs: '' + extraHelixArguments: '' isExtraPlatformsBuild: false isWasmOnlyBuild: false buildAOTOnHelix: true @@ -26,12 +26,14 @@ jobs: isExtraPlatformsBuild: ${{ parameters.isExtraPlatformsBuild }} isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} extraBuildArgs: /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=${{ parameters.buildAOTOnHelix }} /p:RunAOTCompilation=${{ parameters.runAOT }} ${{ parameters.extraBuildArgs }} - extraHelixArgs: /p:NeedsToBuildWasmAppsOnHelix=true ${{ parameters.extraHelixArgs }} + extraHelixArguments: /p:NeedsToBuildWasmAppsOnHelix=true ${{ parameters.extraHelixArguments }} alwaysRun: ${{ parameters.alwaysRun }} shouldRunSmokeOnly: ${{ parameters.shouldRunSmokeOnly }} shouldContinueOnError: ${{ parameters.shouldContinueOnError }} scenarios: + - ${{ if eq(platform, 'browser_wasm') }}: + - WasmTestOnV8 - ${{ if eq(platform, 'browser_wasm_win') }}: - - WasmTestOnBrowser - - ${{ if ne(platform, 'browser_wasm_win') }}: - - normal + - WasmTestOnChrome + - ${{ if or(eq(platform, 'wasi_wasm_win'), eq(platform, 'wasi_wasm')) }}: + - WasmTestOnWasmtime diff --git a/eng/pipelines/common/templates/wasm-library-tests.yml b/eng/pipelines/common/templates/wasm-library-tests.yml index b1b041604439..f015563fef00 100644 --- a/eng/pipelines/common/templates/wasm-library-tests.yml +++ b/eng/pipelines/common/templates/wasm-library-tests.yml @@ -1,12 +1,12 @@ parameters: alwaysRun: false extraBuildArgs: '' - extraHelixArgs: '' + extraHelixArguments: '' isExtraPlatformsBuild: false isWasmOnlyBuild: false nameSuffix: '' platforms: [] - scenarios: ['normal'] + scenarios: ['WasmTestOnV8'] shouldContinueOnError: false shouldRunSmokeOnly: false @@ -61,12 +61,17 @@ jobs: - name: _wasmRunSmokeTestsOnlyArg value: /p:RunSmokeTestsOnly=$(shouldRunSmokeOnlyVar) - name: chromeInstallArg - ${{ if containsValue(parameters.scenarios, 'wasmtestonbrowser') }}: + ${{ if containsValue(parameters.scenarios, 'WasmTestOnChrome') }}: value: /p:InstallChromeForTests=true ${{ else }}: value: '' + - name: firefoxInstallArg + ${{ if containsValue(parameters.scenarios, 'WasmTestOnFirefox') }}: + value: /p:InstallFirefoxForTests=true + ${{ else }}: + value: '' - name: v8InstallArg - ${{ if containsValue(parameters.scenarios, 'normal') }}: + ${{ if containsValue(parameters.scenarios, 'WasmTestOnV8') }}: value: /p:InstallV8ForTests=true ${{ else }}: value: '' @@ -75,7 +80,7 @@ jobs: isExtraPlatforms: ${{ parameters.isExtraPlatformsBuild }} testGroup: innerloop nameSuffix: LibraryTests${{ parameters.nameSuffix }} - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=$(_hostedOs) $(_wasmRunSmokeTestsOnlyArg) $(chromeInstallArg) $(v8InstallArg) ${{ parameters.extraBuildArgs }} + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:MonoEnableAssertMessages=true /p:BrowserHost=$(_hostedOs) $(_wasmRunSmokeTestsOnlyArg) $(chromeInstallArg) $(firefoxInstallArg) $(v8InstallArg) ${{ parameters.extraBuildArgs }} timeoutInMinutes: 240 # if !alwaysRun, then: # if this is runtime-wasm (isWasmOnlyBuild): @@ -92,5 +97,5 @@ jobs: parameters: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) - extraHelixArguments: /p:BrowserHost=$(_hostedOs) $(_wasmRunSmokeTestsOnlyArg) ${{ parameters.extraHelixArgs }} + extraHelixArguments: /p:BrowserHost=$(_hostedOs) $(_wasmRunSmokeTestsOnlyArg) ${{ parameters.extraHelixArguments }} scenarios: ${{ parameters.scenarios }} diff --git a/eng/pipelines/common/templates/wasm-runtime-tests.yml b/eng/pipelines/common/templates/wasm-runtime-tests.yml index 3a8affe48a21..510607830f08 100644 --- a/eng/pipelines/common/templates/wasm-runtime-tests.yml +++ b/eng/pipelines/common/templates/wasm-runtime-tests.yml @@ -36,7 +36,7 @@ jobs: isExtraPlatforms: ${{ parameters.isExtraPlatformsBuild }} nameSuffix: AllSubsets_Mono_RuntimeTests runtimeVariant: monointerpreter - buildArgs: -s mono+libs -c $(_BuildConfig) /p:InstallV8ForTests=false ${{ parameters.extraBuildArgs }} + buildArgs: -s mono+libs -c $(_BuildConfig) /p:MonoEnableAssertMessages=true /p:InstallV8ForTests=false ${{ parameters.extraBuildArgs }} timeoutInMinutes: 180 condition: >- or( diff --git a/eng/pipelines/coreclr/libraries-pgo.yml b/eng/pipelines/coreclr/libraries-pgo.yml index a8f0e16b01f3..e6dd78aba4a7 100644 --- a/eng/pipelines/coreclr/libraries-pgo.yml +++ b/eng/pipelines/coreclr/libraries-pgo.yml @@ -71,3 +71,4 @@ extends: - syntheticpgo - syntheticpgo_blend - jitrlcse + - jitrpolayout diff --git a/eng/pipelines/coreclr/nativeaot-post-build-steps.yml b/eng/pipelines/coreclr/nativeaot-post-build-steps.yml index 94761028f48a..bc29a657c456 100644 --- a/eng/pipelines/coreclr/nativeaot-post-build-steps.yml +++ b/eng/pipelines/coreclr/nativeaot-post-build-steps.yml @@ -21,11 +21,3 @@ steps: nativeAotTest: true helixQueues: ${{ parameters.helixQueues }} liveLibrariesBuildConfig: ${{ parameters.liveLibrariesBuildConfig }} - - # Can't run arm/arm64 tests on x64 build machines - - ${{ if and(ne(parameters.archType, 'arm'), ne(parameters.archType, 'arm64')) }}: - - # Publishing tooling doesn't support different configs between runtime and libs, so only run tests in Release config - - ${{ if eq(parameters.buildConfig, 'release') }}: - - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(_osParameter) -s libs.tests -c $(_BuildConfig) $(crossArg) $(_nativeSanitizersArg) /p:TestAssemblies=false /p:RunNativeAotTestApps=true $(_officialBuildParameter) /bl:$(Build.SourcesDirectory)/artifacts/log/$(buildConfigUpper)/NativeAotTests.binlog ${{ parameters.extraTestArgs }} - displayName: Run NativeAot Library Tests diff --git a/eng/pipelines/coreclr/perf-non-wasm-jobs.yml b/eng/pipelines/coreclr/perf-non-wasm-jobs.yml index c48103af929c..574728cfed7e 100644 --- a/eng/pipelines/coreclr/perf-non-wasm-jobs.yml +++ b/eng/pipelines/coreclr/perf-non-wasm-jobs.yml @@ -306,7 +306,7 @@ jobs: runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml logicalmachine: 'perfviper' - # run coreclr perfowl microbenchmarks perf gdv3 jobs + # run coreclr perfowl microbenchmarks perf rlcse jobs - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml @@ -322,9 +322,9 @@ jobs: runKind: micro runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml logicalmachine: 'perfowl' - experimentName: 'gdv3' + experimentName: 'rlcse' - # run coreclr perfowl microbenchmarks perf rlcse jobs + # run coreclr perfowl microbenchmarks perf jitoptrepeat jobs - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml @@ -340,9 +340,9 @@ jobs: runKind: micro runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml logicalmachine: 'perfowl' - experimentName: 'rlcse' + experimentName: 'jitoptrepeat' - # run coreclr perfowl microbenchmarks perf jitoptrepeat jobs + # run coreclr perfowl microbenchmarks perf rpolayout jobs - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml @@ -358,7 +358,7 @@ jobs: runKind: micro runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml logicalmachine: 'perfowl' - experimentName: 'jitoptrepeat' + experimentName: 'rpolayout' # run coreclr crossgen perf job - template: /eng/pipelines/common/platform-matrix.yml diff --git a/eng/pipelines/coreclr/perf_slow.yml b/eng/pipelines/coreclr/perf_slow.yml index 4a6fa32a81f1..f5d10f2a01fa 100644 --- a/eng/pipelines/coreclr/perf_slow.yml +++ b/eng/pipelines/coreclr/perf_slow.yml @@ -121,7 +121,7 @@ extends: platforms: - linux_arm64 jobParameters: - buildArgs: -s mono+libs+host+packs -c $(_BuildConfig) /p:MonoAOTEnableLLVM=true /p:MonoEnableLLVM=true /p:BuildMonoAOTCrossCompiler=true /p:MonoLibClang="/usr/local/lib/libclang.so.16" /p:AotHostArchitecture=arm64 /p:AotHostOS=linux + buildArgs: -s mono+libs+host+packs -c $(_BuildConfig) /p:MonoAOTEnableLLVM=true /p:MonoEnableLLVM=true /p:BuildMonoAOTCrossCompiler=true /p:MonoLibClang="/usr/local/lib/libclang.so" /p:AotHostArchitecture=arm64 /p:AotHostOS=linux nameSuffix: AOT isOfficialBuild: false postBuildSteps: diff --git a/eng/pipelines/coreclr/runtime-nativeaot-outerloop.yml b/eng/pipelines/coreclr/runtime-nativeaot-outerloop.yml index e8bfd86cd81d..494601a890df 100644 --- a/eng/pipelines/coreclr/runtime-nativeaot-outerloop.yml +++ b/eng/pipelines/coreclr/runtime-nativeaot-outerloop.yml @@ -69,7 +69,7 @@ extends: testGroup: innerloop isSingleFile: true nameSuffix: NativeAOT_Libs - buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) /p:TestNativeAot=true /p:ArchiveTests=true /p:IlcUseServerGc=false /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs+libs.tests -c $(_BuildConfig) /p:TestNativeAot=true /p:ArchiveTests=true /p:IlcUseServerGc=false /p:RunAnalyzers=false timeoutInMinutes: 300 # doesn't normally take this long, but I've seen Helix queues backed up for 160 minutes includeAllPlatforms: true # extra steps, run tests @@ -95,7 +95,7 @@ extends: testGroup: innerloop isSingleFile: true nameSuffix: NativeAOT_Checked_Libs - buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:IlcUseServerGc=false /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:IlcUseServerGc=false /p:RunAnalyzers=false timeoutInMinutes: 360 # extra steps, run tests postBuildSteps: @@ -120,7 +120,7 @@ extends: testGroup: innerloop isSingleFile: true nameSuffix: NativeAOT_Checked_Libs_SizeOpt - buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:OptimizationPreference=Size /p:IlcUseServerGc=false /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:OptimizationPreference=Size /p:IlcUseServerGc=false /p:RunAnalyzers=false timeoutInMinutes: 240 # extra steps, run tests postBuildSteps: @@ -145,7 +145,7 @@ extends: testGroup: innerloop isSingleFile: true nameSuffix: NativeAOT_Checked_Libs_SpeedOpt - buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:OptimizationPreference=Speed /p:IlcUseServerGc=false /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:OptimizationPreference=Speed /p:IlcUseServerGc=false /p:RunAnalyzers=false timeoutInMinutes: 240 # extra steps, run tests postBuildSteps: @@ -176,7 +176,7 @@ extends: jobParameters: timeoutInMinutes: 300 # doesn't normally take this long, but we have had Helix queues backed up for over an hour nameSuffix: NativeAOT_Pri0 - buildArgs: -s clr.aot+host.native+libs -rc $(_BuildConfig) -lc Release -hc Release /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs -rc $(_BuildConfig) -lc Release /p:RunAnalyzers=false postBuildSteps: - template: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml parameters: diff --git a/eng/pipelines/coreclr/templates/run-performance-job.yml b/eng/pipelines/coreclr/templates/run-performance-job.yml index 12d630a5b3f3..2b61558e2fc9 100644 --- a/eng/pipelines/coreclr/templates/run-performance-job.yml +++ b/eng/pipelines/coreclr/templates/run-performance-job.yml @@ -91,6 +91,9 @@ jobs: export ORIGPYPATH=$PYTHONPATH export CRYPTOGRAPHY_ALLOW_OPENSSL_102=true; echo "** Installing prerequistes **"; + echo "** Waiting for dpkg to unlock (up to 2 minutes) **" && + timeout 2m bash -c 'while sudo fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; do if [ -z "$printed" ]; then echo "Waiting for dpkg lock to be released... Lock is held by: $(ps -o cmd= -p $(sudo fuser /var/lib/dpkg/lock-frontend))"; printed=1; fi; echo "Waiting 5 seconds to check again"; sleep 5; done;' && + sudo apt-get remove -y lttng-modules-dkms && sudo apt-get -y install python3-pip && python3 -m pip install --user -U pip && sudo apt-get -y install python3-venv && @@ -192,4 +195,4 @@ jobs: WorkItemDirectory: '$(WorkItemDirectory)' # WorkItemDirectory can not be empty, so we send it some docs to keep it happy CorrelationPayloadDirectory: '$(PayloadDirectory)' # it gets checked out to a folder with shorter path than WorkItemDirectory so we can avoid file name too long exceptions ProjectFile: ${{ parameters.projectFile }} - osGroup: ${{ parameters.osGroup }} \ No newline at end of file + osGroup: ${{ parameters.osGroup }} diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslike.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslike.yml index 051cb8b286bd..be6ef9c63c00 100644 --- a/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslike.yml +++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslike.yml @@ -35,7 +35,11 @@ jobs: testGroup: innerloop nameSuffix: AllSubsets_Mono isExtraPlatforms: ${{ parameters.isExtraPlatformsBuild }} - buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg) /p:BuildTestsOnHelix=true /p:EnableAdditionalTimezoneChecks=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true /p:IsManualOrRollingBuild=true + # Don't trim tests on rolling builds + ${{ if eq(variables['isRollingBuild'], true) }}: + buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg) /p:BuildTestsOnHelix=true /p:EnableAdditionalTimezoneChecks=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true /p:IsManualOrRollingBuild=true /p:EnableAggressiveTrimming=false + ${{ else }}: + buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg) /p:BuildTestsOnHelix=true /p:EnableAdditionalTimezoneChecks=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true /p:IsManualOrRollingBuild=true /p:EnableAggressiveTrimming=true timeoutInMinutes: 480 # extra steps, run tests postBuildSteps: diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-linuxbionic.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-linuxbionic.yml index 7eb5fa47f808..862f7e54848e 100644 --- a/eng/pipelines/extra-platforms/runtime-extra-platforms-linuxbionic.yml +++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-linuxbionic.yml @@ -12,6 +12,7 @@ jobs: # # Build the whole product using Mono for Android Linux with Bionic libc +# FIXME: disabled test runs https://github.com/dotnet/runtime/issues/100281 # - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -41,9 +42,9 @@ jobs: nameSuffix: AllSubsets_Mono buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true timeoutInMinutes: 480 - # extra steps, run tests - postBuildSteps: - - template: /eng/pipelines/libraries/helix.yml - parameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig)_LinuxBionic + # extra steps, run tests # FIXME: see https://github.com/dotnet/runtime/issues/100281 + # postBuildSteps: + # - template: /eng/pipelines/libraries/helix.yml + # parameters: + # creator: dotnet-bot + # testRunNamePrefixSuffix: Mono_$(_BuildConfig)_LinuxBionic diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml index fc8d757233cd..a5c6cb414227 100644 --- a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml +++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml @@ -89,8 +89,8 @@ jobs: isExtraPlatformsBuild: ${{ parameters.isExtraPlatformsBuild }} isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} scenarios: - - normal - - WasmTestOnBrowser + - WasmTestOnV8 + - WasmTestOnChrome # this only runs on the extra pipeline - template: /eng/pipelines/common/templates/wasm-library-tests.yml @@ -114,7 +114,7 @@ jobs: isExtraPlatformsBuild: ${{ parameters.isExtraPlatformsBuild }} isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} scenarios: - - WasmTestOnBrowser + - WasmTestOnChrome - WasmTestOnNodeJS # EAT Library tests - only run on linux @@ -183,7 +183,7 @@ jobs: shouldContinueOnError: ${{ not(parameters.isWasmOnlyBuild) }} alwaysRun: ${{ variables.isRollingBuild }} scenarios: - - normal + - WasmTestOnV8 # Hybrid Globalization tests - template: /eng/pipelines/common/templates/wasm-library-tests.yml @@ -197,8 +197,8 @@ jobs: isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} alwaysRun: true scenarios: - - normal - - WasmTestOnBrowser + - WasmTestOnChrome + - WasmTestOnFirefox - WasmTestOnNodeJS # Hybrid Globalization AOT tests @@ -214,8 +214,7 @@ jobs: isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} alwaysRun: true scenarios: - - normal - - WasmTestOnBrowser + - WasmTestOnChrome - WasmTestOnNodeJS - ${{ if and(ne(parameters.isRollingBuild, true), ne(parameters.excludeNonLibTests, true), ne(parameters.debuggerTestsOnly, true)) }}: @@ -321,4 +320,4 @@ jobs: isExtraPlatformsBuild: ${{ parameters.isExtraPlatformsBuild }} isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} scenarios: - - normal + - WasmTestOnWasmtime diff --git a/eng/pipelines/global-build.yml b/eng/pipelines/global-build.yml index 32e4ec79c831..d7302fe253b6 100644 --- a/eng/pipelines/global-build.yml +++ b/eng/pipelines/global-build.yml @@ -1,6 +1,6 @@ -# The purpose of this pipeline is to exercise local developer workflow in the consolidated -# runtime repo. In particular, it is supposed to run the root "build" script just like any -# normal developer normally would and monitor regressions w.r.t. this fundamental scenario. +# The purpose of this pipeline is to exercise various developer workflows in the repo. +# Primarily, it is meant to cover local (non-cross) build scenarios and +# source-build scenarios that commonly cause build breaks. trigger: none @@ -41,28 +41,6 @@ extends: - stage: Build jobs: - # - # Build with Release config and Debug runtimeConfiguration - # - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: release - platforms: - - windows_x86 - - osx_x64 - - osx_arm64 - jobParameters: - testGroup: innerloop - nameSuffix: Runtime_Debug - buildArgs: -c release -runtimeConfiguration debug - timeoutInMinutes: 120 - condition: - or( - eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), - eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_non_mono_and_wasm.containsChange'], true), - eq(variables['isRollingBuild'], true)) - # # Build with Release config and runtimeConfiguration with MSBuild generator # @@ -83,26 +61,6 @@ extends: eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_non_mono_and_wasm.containsChange'], true), eq(variables['isRollingBuild'], true)) - # - # Build with Debug config and Release runtimeConfiguration - # - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: debug - platforms: - - linux_x64_dev_innerloop - jobParameters: - testGroup: innerloop - nameSuffix: Runtime_Release - buildArgs: -c debug -runtimeConfiguration release - timeoutInMinutes: 120 - condition: - or( - eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), - eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_non_mono_and_wasm.containsChange'], true), - eq(variables['isRollingBuild'], true)) - # # Build with RuntimeFlavor only. This exercise code paths where only RuntimeFlavor is # specified. Catches cases where we depend on Configuration also being specified @@ -124,38 +82,37 @@ extends: eq(variables['isRollingBuild'], true)) # - # Build Mono + Libraries. This exercises the code path where we build libraries without - # first building CoreCLR + # Build Libraries AllConfigurations. This exercises the code path where we build libraries for all + # configurations on a non Windows operating system. # - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml buildConfig: debug platforms: - - windows_x64 + - linux_x64_dev_innerloop jobParameters: - testGroup: innerloop - nameSuffix: Mono_Libraries - buildArgs: -subset mono+libs /p:RuntimeFlavor=Mono + nameSuffix: Libraries_AllConfigurations + buildArgs: -subset libs -allconfigurations timeoutInMinutes: 120 condition: or( - eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_non_wasm.containsChange'], true), + eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_non_mono_and_wasm.containsChange'], true), eq(variables['isRollingBuild'], true)) # - # Build Libraries AllConfigurations. This exercises the code path where we build libraries for all - # configurations on a non Windows operating system. + # Build native assets on Alpine. This exercises more modern musl libc changes that have a tendendy to break source-build. + # We don't add this as a source-build job as the repo source-build infrastructure isn't set up to run on alpine effectively. # - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: debug + buildConfig: release platforms: - - linux_x64_dev_innerloop + - linux_musl_x64_dev_innerloop jobParameters: - nameSuffix: Libraries_AllConfigurations - buildArgs: -subset libs -allconfigurations + nameSuffix: Musl_Validation + buildArgs: -subset clr.native+libs.native+host.native -c $(_BuildConfig) timeoutInMinutes: 120 condition: or( @@ -163,16 +120,11 @@ extends: eq(variables['isRollingBuild'], true)) # - # SourceBuild Build + # Build Portable SourceBuild # - - template: /eng/pipelines/common/platform-matrix.yml + - template: /eng/common/templates/jobs/source-build.yml parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: Release platforms: - - SourceBuild_linux_x64 - jobParameters: - nameSuffix: PortableSourceBuild - timeoutInMinutes: 95 - condition: - eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_non_mono_and_wasm.containsChange'], true) + - name: Linux_x64 + targetRid: linux-x64 + container: SourceBuild_linux_x64 diff --git a/eng/pipelines/libraries/execute-trimming-tests-steps.yml b/eng/pipelines/libraries/execute-trimming-tests-steps.yml index 567abab0bb98..13778ee0ab63 100644 --- a/eng/pipelines/libraries/execute-trimming-tests-steps.yml +++ b/eng/pipelines/libraries/execute-trimming-tests-steps.yml @@ -1,8 +1,14 @@ parameters: archType: '' extraTestArgs: '' + runAotTests: true steps: # Execute tests - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(_osParameter) -s libs.tests -c $(_BuildConfig) $(crossArg) /p:TestAssemblies=false /p:TestTrimming=true $(_officialBuildParameter) /bl:$(Build.SourcesDirectory)/artifacts/log/$(buildConfigUpper)/TrimmingTests.binlog ${{ parameters.extraTestArgs }} displayName: Run Trimming Tests + + # Execute AOT test app tests + - ${{ if eq(parameters.runAotTests, true) }}: + - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(_osParameter) -s libs.tests -c $(_BuildConfig) $(crossArg) /p:TestAssemblies=false /p:RunNativeAotTestApps=true $(_officialBuildParameter) /bl:$(Build.SourcesDirectory)/artifacts/log/$(buildConfigUpper)/NativeAotTestAppTests.binlog ${{ parameters.extraTestArgs }} + displayName: Run Native AOT Test App Tests diff --git a/eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml b/eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml new file mode 100644 index 000000000000..a26558ee148f --- /dev/null +++ b/eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml @@ -0,0 +1,107 @@ +trigger: none + +schedules: +- cron: "0 10 * * *" # 10 AM UTC + displayName: OneFuzz deployment nightly run + branches: + include: + - main + +variables: + - template: ../variables.yml + - name: fuzzerProject + value: $(Build.SourcesDirectory)/src/libraries/Fuzzing/DotnetFuzzing + - name: dotnetPath + value: $(Build.SourcesDirectory)/.dotnet/dotnet + +extends: + template: /eng/pipelines/common/templates/pipeline-with-resources.yml + parameters: + stages: + - stage: Build + jobs: + - job: windows + displayName: Build & Deploy to OneFuzz + timeoutInMinutes: 120 + pool: + name: $(DncEngInternalBuildPool) + demands: ImageOverride -equals windows.vs2022.amd64 + + steps: + - checkout: self + clean: true + fetchDepth: 1 + lfs: false + + - powershell: | + cd $(Build.SourcesDirectory) + ./build.cmd clr+libs+packs+host -rc Checked -c Debug + displayName: Build runtime (checked + debug) + + - powershell: | + cd $(fuzzerProject) + $(dotnetPath) publish -o publish + displayName: Build Fuzzing targets + + - powershell: | + cd $(fuzzerProject) + $(dotnetPath) tool install --tool-path . SharpFuzz.CommandLine + displayName: Install SharpFuzz.CommandLine + + - powershell: | + cd $(fuzzerProject) + publish/DotnetFuzzing.exe prepare-onefuzz deployment + displayName: Prepare OneFuzz deployment + +# OneFuzz can't currently handle a single deployment where multiple jobs share similar assemblies/pdbs. +# As a workaround, we emit a task for every fuzzing target individually. +# https://fuzzfest.visualstudio.com/Onefuzz/_workitems/edit/191504/ is tracking this issue. +# - task: onefuzz-task@0 +# inputs: +# onefuzzOSes: 'Windows' +# env: +# onefuzzDropDirectory: $(fuzzerProject)/deployment +# SYSTEM_ACCESSTOKEN: $(System.AccessToken) +# displayName: Send to OneFuzz + +# ONEFUZZ_TASK_WORKAROUND_START + - task: onefuzz-task@0 + inputs: + onefuzzOSes: 'Windows' + env: + onefuzzDropDirectory: $(fuzzerProject)/deployment/HttpHeadersFuzzer + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + displayName: Send HttpHeadersFuzzer to OneFuzz + + - task: onefuzz-task@0 + inputs: + onefuzzOSes: 'Windows' + env: + onefuzzDropDirectory: $(fuzzerProject)/deployment/JsonDocumentFuzzer + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + displayName: Send JsonDocumentFuzzer to OneFuzz + + - task: onefuzz-task@0 + inputs: + onefuzzOSes: 'Windows' + env: + onefuzzDropDirectory: $(fuzzerProject)/deployment/SearchValuesByteCharFuzzer + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + displayName: Send SearchValuesByteCharFuzzer to OneFuzz + + - task: onefuzz-task@0 + inputs: + onefuzzOSes: 'Windows' + env: + onefuzzDropDirectory: $(fuzzerProject)/deployment/SearchValuesStringFuzzer + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + displayName: Send SearchValuesStringFuzzer to OneFuzz + + - task: onefuzz-task@0 + inputs: + onefuzzOSes: 'Windows' + env: + onefuzzDropDirectory: $(fuzzerProject)/deployment/UTF8Fuzzer + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + displayName: Send UTF8Fuzzer to OneFuzz +# ONEFUZZ_TASK_WORKAROUND_END diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index cb52e5acf042..91fe25701b07 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -146,7 +146,6 @@ jobs: - ${{ if notIn(parameters.jobParameters.framework, 'net48') }}: # mono outerloop - ${{ if and(eq(parameters.jobParameters.testScope, 'outerloop'), eq(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - - Windows.7.Amd64.Open - Windows.11.Amd64.Client.Open # libraries on coreclr (outerloop and innerloop), or libraries on mono innerloop - ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}: @@ -155,7 +154,6 @@ jobs: - Windows.Amd64.Server2022.Open - ${{ if or(ne(parameters.jobParameters.isExtraPlatformsBuild, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - Windows.Amd64.Server2022.Open - - Windows.7.Amd64.Open # .NETFramework - ${{ if eq(parameters.jobParameters.framework, 'net48') }}: diff --git a/eng/pipelines/libraries/outerloop-mono.yml b/eng/pipelines/libraries/outerloop-mono.yml index 34b1af3c71b5..b9d4bcfecd7b 100644 --- a/eng/pipelines/libraries/outerloop-mono.yml +++ b/eng/pipelines/libraries/outerloop-mono.yml @@ -65,7 +65,7 @@ extends: - template: /eng/pipelines/libraries/helix.yml parameters: scenarios: - - normal + - WasmTestOnV8 testScope: outerloop creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) diff --git a/eng/pipelines/mono/templates/generate-offsets.yml b/eng/pipelines/mono/templates/generate-offsets.yml deleted file mode 100644 index 8d8d781dd326..000000000000 --- a/eng/pipelines/mono/templates/generate-offsets.yml +++ /dev/null @@ -1,88 +0,0 @@ -parameters: - buildConfig: 'Debug' - osGroup: '' - osSubGroup: '' - platform: '' - container: '' - timeoutInMinutes: '' - variables: {} - pool: '' - condition: true - isOfficialBuild: false - templatePath: 'templates' - -### Product build -jobs: -- template: /eng/pipelines/common/templates/runtimes/xplat-job.yml - parameters: - templatePath: ${{ parameters.templatePath }} - buildConfig: ${{ parameters.buildConfig }} - osGroup: ${{ parameters.osGroup }} - osSubGroup: ${{ parameters.osSubGroup }} - helixType: 'build/product/' - enableMicrobuild: true - pool: ${{ parameters.pool }} - condition: ${{ parameters.condition }} - dependOnEvaluatePaths: ${{ parameters.dependOnEvaluatePaths }} - logsName: 'BuildLogs_Attempt$(System.JobAttempt)_Mono_Offsets_$(osGroup)$(osSubGroup)' - - # Compute job name from template parameters - name: ${{ format('mono_{0}{1}_offsets', parameters.osGroup, parameters.osSubGroup) }} - displayName: ${{ format('Mono {0}{1} AOT offsets', parameters.osGroup, parameters.osSubGroup) }} - - # Run all steps in the container. - # Note that the containers are defined in platform-matrix.yml - container: ${{ parameters.container }} - - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - - gatherAssetManifests: true - variables: - - name: osGroup - value: ${{ parameters.osGroup }} - - name: osSubGroup - value: ${{ parameters.osSubGroup }} - - name: officialBuildIdArg - value: '' - - ${{ if eq(parameters.isOfficialBuild, true) }}: - - name: officialBuildIdArg - value: '/p:OfficialBuildId=$(Build.BuildNumber)' - - name: osOverride - value: -os linux - - name: archType - value: x64 - - ${{ parameters.variables }} - - steps: - - # Install native dependencies - # Linux builds use docker images with dependencies preinstalled, - # and FreeBSD builds use a build agent with dependencies - # preinstalled, so we only need this step for OSX and Windows. - - ${{ if in(parameters.osGroup, 'osx', 'maccatalyst', 'ios', 'iossimulator', 'tvos', 'tvossimulator') }}: - - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh $(osGroup) - displayName: Install native dependencies - - # Build - - ${{ if ne(parameters.osGroup, 'windows') }}: - - script: ./build$(scriptExt) -subset mono.aotcross -c $(buildConfig) -arch $(archType) $(osOverride) -ci $(officialBuildIdArg) /p:MonoGenerateOffsetsOSGroups=$(osGroup) - displayName: Generate AOT offsets - - ${{ if eq(parameters.osGroup, 'windows') }}: - - script: build$(scriptExt) -subset mono.aotcross -c $(buildConfig) -arch $(archType) $(osOverride) -ci $(officialBuildIdArg) /p:MonoGenerateOffsetsOSGroups=$(osGroup) - displayName: Generate AOT offsets - - # Upload offset files - - task: CopyFiles@2 - displayName: Collect offset files - inputs: - sourceFolder: '$(Build.SourcesDirectory)/artifacts/obj/mono/' - contents: '**/offsets-*.h' - targetFolder: '$(Build.SourcesDirectory)/artifacts/obj/mono/offsetfiles/' - - - template: /eng/pipelines/common/templates/publish-pipeline-artifacts.yml - parameters: - displayName: Upload offset files - isOfficialBuild: ${{ parameters.isOfficialBuild }} - inputs: - targetPath: '$(Build.SourcesDirectory)/artifacts/obj/mono/offsetfiles' - artifactName: 'Mono_Offsets_$(osGroup)$(osSubGroup)' diff --git a/eng/pipelines/mono/templates/workloads-build.yml b/eng/pipelines/mono/templates/workloads-build.yml deleted file mode 100644 index 72e4c3adc8fb..000000000000 --- a/eng/pipelines/mono/templates/workloads-build.yml +++ /dev/null @@ -1,116 +0,0 @@ -parameters: - archType: '' - buildConfig: '' - container: '' - dependsOn: [] - isOfficialBuild: false - osGroup: '' - osSubgroup: '' - platform: '' - pool: '' - runtimeVariant: '' - testGroup: '' - timeoutInMinutes: '' - templatePath: 'templates' - variables: {} - -jobs: -- template: /eng/pipelines/common/templates/runtimes/xplat-job.yml - parameters: - templatePath: ${{ parameters.templatePath }} - archType: ${{ parameters.archType }} - buildConfig: ${{ parameters.buildConfig }} - container: ${{ parameters.container }} - condition: and(succeeded(), ${{ parameters.isOfficialBuild }}) - helixType: 'build/product/' - osGroup: ${{ parameters.osGroup }} - osSubgroup: ${{ parameters.osSubgroup }} - pool: ${{ parameters.pool }} - runtimeVariant: ${{ parameters.runtimeVariant }} - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - logsName: WorkloadLogs_Attempt$(System.JobAttempt) - - dependsOn: ${{ parameters.dependsOn }} - - name: workloadsbuild - displayName: Build Workloads - - variables: - - name: officialBuildIdArg - value: '' - - ${{ if eq(parameters.isOfficialBuild, true) }}: - - name: officialBuildIdArg - value: '/p:OfficialBuildId=$(Build.BuildNumber)' - - name: SignType - value: $[ coalesce(variables.OfficialSignType, 'real') ] - - name: workloadPackagesPath - value: $(Build.SourcesDirectory)/artifacts/workloadPackages - - name: workloadArtifactsPath - value: $(Build.SourcesDirectory)/artifacts/workloads - - ${{ parameters.variables }} - - steps: - - task: DownloadPipelineArtifact@2 - inputs: - artifact: 'IntermediateArtifacts' - path: $(workloadPackagesPath) - patterns: | - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.android-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-arm64.Cross.android-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.browser-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-arm64.Cross.browser-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.wasi-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-arm64.Cross.wasi-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.android-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.browser-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.ios-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.iossimulator-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.maccatalyst-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.tvos-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.tvossimulator-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.wasi-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.Current.Manifest*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net6.Manifest*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net7.Manifest*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net8.Manifest*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.MonoTargets.Sdk*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.MonoAOTCompiler.Task*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Sdk*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Wasi*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Templates*.nupkg - IntermediateArtifacts/windows_arm64/Shipping/Microsoft.NETCore.App.Runtime.win-arm64*.nupkg - IntermediateArtifacts/windows_x64/Shipping/Microsoft.NETCore.App.Runtime.win-x64*.nupkg - IntermediateArtifacts/windows_x86/Shipping/Microsoft.NETCore.App.Runtime.win-x86*.nupkg - - - task: CopyFiles@2 - displayName: Flatten packages - inputs: - sourceFolder: $(workloadPackagesPath) - contents: '*/Shipping/*.nupkg' - cleanTargetFolder: false - targetFolder: $(workloadPackagesPath) - flattenFolders: true - - - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -subset mono.workloads -arch $(archType) -c $(buildConfig) $(officialBuildIdArg) -ci - displayName: Build workload artifacts - - # Upload packages wrapping msis - - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml - parameters: - name: workloads - - # Delete wixpdb files before they are uploaded to artifacts - - task: DeleteFiles@1 - displayName: Delete wixpdb's - inputs: - SourceFolder: $(workloadArtifactsPath) - Contents: '*.wixpdb' - - # Upload artifacts to be used for generating VS components - - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml - parameters: - name: workloads-vs - publishPackagesCondition: false - publishVSSetupCondition: true diff --git a/eng/pipelines/official/jobs/prepare-signed-artifacts.yml b/eng/pipelines/official/jobs/prepare-signed-artifacts.yml index 24fd2df48d74..eb25d311890a 100644 --- a/eng/pipelines/official/jobs/prepare-signed-artifacts.yml +++ b/eng/pipelines/official/jobs/prepare-signed-artifacts.yml @@ -1,76 +1,65 @@ parameters: - dependsOn: [] PublishRidAgnosticPackagesFromPlatform: '' isOfficialBuild: false logArtifactName: 'Logs-PrepareSignedArtifacts_Attempt$(System.JobAttempt)' jobs: -- job: PrepareSignedArtifacts - displayName: Prepare Signed Artifacts - dependsOn: ${{ parameters.dependsOn }} - pool: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals 1es-windows-2022 - # Double the default timeout. - timeoutInMinutes: 240 - workspace: - clean: all +- template: /eng/common/templates-official/job/job.yml + parameters: + name: 'PrepareSignedArtifacts' + displayName: 'Prepare Signed Artifacts' - variables: - - name: SignType - value: $[ coalesce(variables.OfficialSignType, 'real') ] + pool: + name: $(DncEngInternalBuildPool) + demands: ImageOverride -equals 1es-windows-2022 - templateContext: - outputs: - - output: pipelineArtifact - displayName: 'Publish BuildLogs' - condition: succeededOrFailed() - targetPath: '$(Build.StagingDirectory)\BuildLogs' - artifactName: ${{ parameters.logArtifactName }} + # Double the default timeout. + timeoutInMinutes: 240 - steps: - - checkout: self - clean: true - fetchDepth: 20 + workspace: + clean: all - - ${{ if eq(parameters.isOfficialBuild, true) }}: - - task: NuGetAuthenticate@1 + enableMicrobuild: true - - task: MicroBuildSigningPlugin@2 - displayName: Install MicroBuild plugin for Signing - inputs: - signType: $(SignType) - zipSources: false - feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json - continueOnError: false - condition: and(succeeded(), - in(variables['SignType'], 'real', 'test')) - - - task: DownloadBuildArtifacts@0 - displayName: Download IntermediateArtifacts - inputs: - artifactName: IntermediateArtifacts - downloadPath: $(Build.SourcesDirectory)\artifacts\PackageDownload - checkDownloadedFiles: true - - - script: >- - build.cmd -ci - -subset publish - -configuration Release - /p:PublishRidAgnosticPackagesFromPlatform=${{ parameters.PublishRidAgnosticPackagesFromPlatform }} - /p:OfficialBuildId=$(Build.BuildNumber) - /p:SignType=$(SignType) - /p:DotNetSignType=$(SignType) - /bl:$(Build.SourcesDirectory)\prepare-artifacts.binlog - displayName: Prepare artifacts and upload to build - - - task: CopyFiles@2 - displayName: Copy Files to $(Build.StagingDirectory)\BuildLogs - inputs: - SourceFolder: '$(Build.SourcesDirectory)' - Contents: | - **/*.log - **/*.binlog - TargetFolder: '$(Build.StagingDirectory)\BuildLogs' - continueOnError: true - condition: succeededOrFailed() \ No newline at end of file + variables: + - name: '_SignType' + value: $[ coalesce(variables.OfficialSignType, 'real') ] + + templateContext: + inputs: + - input: checkout + repository: self + clean: true + fetchDepth: 20 + - input: pipelineArtifact + artifactName: IntermediateArtifacts + targetPath: $(Build.SourcesDirectory)\artifacts\PackageDownload\IntermediateArtifacts + outputs: + - output: pipelineArtifact + displayName: 'Publish BuildLogs' + condition: succeededOrFailed() + targetPath: '$(Build.StagingDirectory)\BuildLogs' + artifactName: ${{ parameters.logArtifactName }} + + steps: + - script: >- + build.cmd -ci + -subset publish + -configuration Release + /p:PublishRidAgnosticPackagesFromPlatform=${{ parameters.PublishRidAgnosticPackagesFromPlatform }} + /p:OfficialBuildId=$(Build.BuildNumber) + /p:SignType=$(_SignType) + /p:DotNetSignType=$(_SignType) + /bl:$(Build.SourcesDirectory)\prepare-artifacts.binlog + displayName: Prepare artifacts and upload to build + + - task: CopyFiles@2 + displayName: Copy Files to $(Build.StagingDirectory)\BuildLogs + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: | + **/*.log + **/*.binlog + TargetFolder: '$(Build.StagingDirectory)\BuildLogs' + continueOnError: true + condition: succeededOrFailed() \ No newline at end of file diff --git a/eng/pipelines/runtime-codeql.yml b/eng/pipelines/runtime-codeql.yml index 9eff98fef5ab..599622f88f62 100644 --- a/eng/pipelines/runtime-codeql.yml +++ b/eng/pipelines/runtime-codeql.yml @@ -47,7 +47,12 @@ extends: nameSuffix: AllSubsets_CoreCLR isOfficialBuild: ${{ variables.isOfficialBuild }} timeoutInMinutes: 360 - isManualCodeQLBuild: true + preBuildSteps: + - task: CodeQL3000Init@0 + displayName: Initialize CodeQL (manually-injected) + postBuildSteps: + - task: CodeQL3000Finalize@0 + displayName: Finalize CodeQL (manually-injected) # # Build Mono runtime packs @@ -65,4 +70,9 @@ extends: nameSuffix: AllSubsets_Mono isOfficialBuild: ${{ variables.isOfficialBuild }} timeoutInMinutes: 360 - isManualCodeQLBuild: true + preBuildSteps: + - task: CodeQL3000Init@0 + displayName: Initialize CodeQL (manually-injected) + postBuildSteps: + - task: CodeQL3000Finalize@0 + displayName: Finalize CodeQL (manually-injected) diff --git a/eng/pipelines/runtime-linker-tests.yml b/eng/pipelines/runtime-linker-tests.yml index aec5e1057ac5..2b001b769f50 100644 --- a/eng/pipelines/runtime-linker-tests.yml +++ b/eng/pipelines/runtime-linker-tests.yml @@ -135,3 +135,4 @@ extends: - template: /eng/pipelines/libraries/execute-trimming-tests-steps.yml parameters: extraTestArgs: '/p:WasmBuildNative=false' + runAotTests: false diff --git a/eng/pipelines/runtime-official.yml b/eng/pipelines/runtime-official.yml index ba09a957605e..cf856d94df61 100644 --- a/eng/pipelines/runtime-official.yml +++ b/eng/pipelines/runtime-official.yml @@ -23,6 +23,8 @@ pr: none variables: - template: /eng/pipelines/common/variables.yml + parameters: + templatePath: 'templates-official' - template: /eng/pipelines/common/internal-variables.yml parameters: teamName: dotnet-core-acquisition @@ -379,11 +381,12 @@ extends: parameters: name: MonoRuntimePacks + # Build Mono AOT offset headers once, for consumption elsewhere # - template: /eng/pipelines/common/platform-matrix.yml parameters: - jobTemplate: /eng/pipelines/mono/templates/generate-offsets.yml + jobTemplate: /eng/pipelines/common/global-build-job.yml buildConfig: release platforms: - android_x64 @@ -392,9 +395,31 @@ extends: - tvos_arm64 - ios_arm64 - maccatalyst_x64 + variables: + - name: _osParameter + value: -os linux + - name: _archParameter + value: -arch x64 jobParameters: templatePath: 'templates-official' - isOfficialBuild: ${{ variables.isOfficialBuild }} + nameSuffix: MonoAOTOffsets + buildArgs: -s mono.aotcross -c $(_BuildConfig) /p:MonoGenerateOffsetsOSGroups=$(osGroup) + postBuildSteps: + # Upload offset files + - task: CopyFiles@2 + displayName: Collect offset files + inputs: + sourceFolder: '$(Build.SourcesDirectory)/artifacts/obj/mono/' + contents: '**/offsets-*.h' + targetFolder: '$(Build.SourcesDirectory)/artifacts/obj/mono/offsetfiles/' + + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Publish Mono AOT offsets' + condition: succeeded() + targetPath: '$(Build.SourcesDirectory)/artifacts/obj/mono/offsetfiles' + artifactName: 'Mono_Offsets_$(osGroup)$(osSubGroup)' # # Build Mono release AOT cross-compilers @@ -416,9 +441,9 @@ extends: nameSuffix: CrossAOT_Mono runtimeVariant: crossaot dependsOn: - - mono_android_offsets - - mono_browser_offsets - - mono_wasi_offsets + - build_android_x64_release_MonoAOTOffsets + - build_browser_wasm_linux_release_MonoAOTOffsets + - build_wasi_wasm_linux_release_MonoAOTOffsets monoCrossAOTTargetOS: - android - browser @@ -444,9 +469,9 @@ extends: nameSuffix: CrossAOT_Mono runtimeVariant: crossaot dependsOn: - - mono_android_offsets - - mono_browser_offsets - - mono_wasi_offsets + - build_android_x64_release_MonoAOTOffsets + - build_browser_wasm_linux_release_MonoAOTOffsets + - build_wasi_wasm_linux_release_MonoAOTOffsets monoCrossAOTTargetOS: - android - browser @@ -472,12 +497,12 @@ extends: nameSuffix: CrossAOT_Mono runtimeVariant: crossaot dependsOn: - - mono_android_offsets - - mono_browser_offsets - - mono_wasi_offsets - - mono_tvos_offsets - - mono_ios_offsets - - mono_maccatalyst_offsets + - build_android_x64_release_MonoAOTOffsets + - build_browser_wasm_linux_release_MonoAOTOffsets + - build_wasi_wasm_linux_release_MonoAOTOffsets + - build_tvos_arm64_release_MonoAOTOffsets + - build_ios_arm64_release_MonoAOTOffsets + - build_maccatalyst_x64_release_MonoAOTOffsets monoCrossAOTTargetOS: - android - browser @@ -560,22 +585,12 @@ extends: # # Build SourceBuild packages # - - template: /eng/pipelines/common/platform-matrix.yml + - template: /eng/common/templates-official/jobs/source-build.yml parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: Release - helixQueueGroup: ci platforms: - - SourceBuild_linux_x64 - jobParameters: - templatePath: 'templates-official' - nameSuffix: PortableSourceBuild - isOfficialBuild: ${{ variables.isOfficialBuild }} - postBuildSteps: - - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml - parameters: - name: SourceBuildPackages - timeoutInMinutes: 95 + - name: Linux_x64 + targetRid: linux-x64 + container: SourceBuild_linux_x64 # # Build PGO Instrumented CoreCLR Release @@ -607,12 +622,80 @@ extends: # - template: /eng/pipelines/common/platform-matrix.yml parameters: - jobTemplate: /eng/pipelines/mono/templates/workloads-build.yml + jobTemplate: /eng/pipelines/common/global-build-job.yml buildConfig: release platforms: - windows_x64 jobParameters: templatePath: 'templates-official' + nameSuffix: Workloads + preBuildSteps: + - task: DownloadPipelineArtifact@2 + inputs: + artifact: 'IntermediateArtifacts' + path: $(Build.SourcesDirectory)/artifacts/workloadPackages + patterns: | + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.android-*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-arm64.Cross.android-*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.browser-wasm*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-arm64.Cross.browser-wasm*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.wasi-wasm*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-arm64.Cross.wasi-wasm*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.android-*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.browser-wasm*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.ios-*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.iossimulator-*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.maccatalyst-*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.tvos-*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.tvossimulator-*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.wasi-wasm*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.Current.Manifest*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net6.Manifest*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net7.Manifest*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net8.Manifest*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.MonoTargets.Sdk*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.MonoAOTCompiler.Task*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Sdk*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Wasi*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Templates*.nupkg + IntermediateArtifacts/windows_arm64/Shipping/Microsoft.NETCore.App.Runtime.win-arm64*.nupkg + IntermediateArtifacts/windows_x64/Shipping/Microsoft.NETCore.App.Runtime.win-x64*.nupkg + IntermediateArtifacts/windows_x86/Shipping/Microsoft.NETCore.App.Runtime.win-x86*.nupkg + IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Sdk.WebAssembly.Pack*.nupkg + + - task: CopyFiles@2 + displayName: Flatten packages + inputs: + sourceFolder: $(Build.SourcesDirectory)/artifacts/workloadPackages + contents: '*/Shipping/*.nupkg' + cleanTargetFolder: false + targetFolder: $(Build.SourcesDirectory)/artifacts/workloadPackages + flattenFolders: true + + buildArgs: -s mono.workloads -c $(_BuildConfig) /p:PackageSource=$(Build.SourcesDirectory)/artifacts/workloadPackages /p:WorkloadOutputPath=$(Build.SourcesDirectory)/artifacts/workloads + + postBuildSteps: + # Upload packages wrapping msis + - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml + parameters: + name: workloads + + # Delete wixpdb files before they are uploaded to artifacts + - task: DeleteFiles@1 + displayName: Delete wixpdb's + inputs: + SourceFolder: $(Build.SourcesDirectory)/artifacts/workloads + Contents: '*.wixpdb' + + # Upload artifacts to be used for generating VS components + - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml + parameters: + name: workloads-vs + publishPackagesCondition: false + publishVSSetupCondition: always() + isOfficialBuild: ${{ variables.isOfficialBuild }} timeoutInMinutes: 120 dependsOn: diff --git a/eng/pipelines/runtime-sanitized.yml b/eng/pipelines/runtime-sanitized.yml index ed0334b61b3e..329f9b9af9cd 100644 --- a/eng/pipelines/runtime-sanitized.yml +++ b/eng/pipelines/runtime-sanitized.yml @@ -28,7 +28,7 @@ extends: buildConfig: Checked runtimeFlavor: coreclr platforms: - - linux_x64 + - linux_x64_sanitizer - osx_x64 - windows_x64 variables: @@ -63,7 +63,7 @@ extends: buildConfig: Debug runtimeFlavor: coreclr platforms: - - linux_x64 + - linux_x64_sanitizer - osx_x64 variables: - name: _nativeSanitizersArg @@ -123,7 +123,7 @@ extends: helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml buildConfig: release platforms: - - linux_x64 + - linux_x64_sanitizer - osx_x64 - windows_x64 variables: @@ -133,7 +133,7 @@ extends: testGroup: innerloop timeoutInMinutes: 120 nameSuffix: NativeAOT - buildArgs: -s clr.aot+host.native+libs -rc $(_BuildConfig) -lc Release -hc Release $(_nativeSanitizersArg) + buildArgs: -s clr.aot+libs -rc $(_BuildConfig) -lc Release $(_nativeSanitizersArg) postBuildSteps: - template: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml parameters: diff --git a/eng/pipelines/runtime-wasm-perf.yml b/eng/pipelines/runtime-wasm-perf.yml index 91e508e2c966..39645a501ecf 100644 --- a/eng/pipelines/runtime-wasm-perf.yml +++ b/eng/pipelines/runtime-wasm-perf.yml @@ -16,7 +16,7 @@ pr: - eng/pipelines/coreclr/templates/run-perf* - eng/pipelines/coreclr/templates/run-scenarios-job.yml - eng/testing/performance/* - - eng/testing/ChromeVersions.props + - eng/testing/BrowserVersions.props variables: - template: /eng/pipelines/common/variables.yml diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 98dc5285250f..cb7aadde9fab 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -498,7 +498,7 @@ extends: jobParameters: testScope: innerloop nameSuffix: CoreCLR_NonPortable - buildArgs: -s clr.native+clr.tools+clr.corelib+clr.nativecorelib+clr.aot+clr.packages -c $(_BuildConfig) /p:PortableBuild=false + buildArgs: -s clr.native+clr.tools+clr.corelib+clr.nativecorelib+clr.aot+clr.packages --outputrid tizen.9.0.0-armel -c $(_BuildConfig) /p:PortableBuild=false timeoutInMinutes: 120 condition: >- or( @@ -567,7 +567,7 @@ extends: jobParameters: timeoutInMinutes: 120 nameSuffix: NativeAOT - buildArgs: -s clr.aot+host.native+libs -rc $(_BuildConfig) -lc Release -hc Release /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs -rc $(_BuildConfig) -lc Release /p:RunAnalyzers=false postBuildSteps: - template: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml parameters: @@ -606,7 +606,7 @@ extends: jobParameters: timeoutInMinutes: 180 nameSuffix: NativeAOT - buildArgs: -s clr.aot+host.native+libs.native+libs.sfx -rc $(_BuildConfig) -lc Release -hc Release /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs.native+libs.sfx -rc $(_BuildConfig) -lc Release /p:RunAnalyzers=false postBuildSteps: - template: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml parameters: @@ -651,7 +651,7 @@ extends: testGroup: innerloop timeoutInMinutes: 120 nameSuffix: NativeAOT - buildArgs: -s clr.aot+host.native+libs+tools.illink -c $(_BuildConfig) -rc $(_BuildConfig) -lc Release -hc Release /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs+tools.illink -c $(_BuildConfig) -rc $(_BuildConfig) -lc Release /p:RunAnalyzers=false postBuildSteps: - template: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml parameters: @@ -688,7 +688,7 @@ extends: testGroup: innerloop isSingleFile: true nameSuffix: NativeAOT_Libraries - buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) /p:TestNativeAot=true /p:RunSmokeTestsOnly=true /p:ArchiveTests=true /p:RunAnalyzers=false + buildArgs: -s clr.aot+libs+libs.tests -c $(_BuildConfig) /p:TestNativeAot=true /p:RunSmokeTestsOnly=true /p:ArchiveTests=true /p:RunAnalyzers=false timeoutInMinutes: 240 # Doesn't actually take long, but we've seen the ARM64 Helix queue often get backlogged for 2+ hours # extra steps, run tests postBuildSteps: @@ -713,7 +713,7 @@ extends: jobParameters: timeoutInMinutes: 120 nameSuffix: CLR_Tools_Tests - buildArgs: -s clr.aot+clr.iltools+libs.sfx+clr.toolstests -c $(_BuildConfig) -test + buildArgs: -s clr.aot+clr.iltools+libs.sfx+clr.toolstests+tools.cdacreadertests -c $(_BuildConfig) -test enablePublishTestResults: true testResultsFormat: 'xunit' # We want to run AOT tests when illink changes because there's share code and tests from illink which are used by AOT @@ -721,6 +721,7 @@ extends: or( eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_tools_illink.containsChange'], true), + eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_tools_cdacreader.containsChange'], true), eq(variables['isRollingBuild'], true)) # # Build CrossDacs @@ -753,8 +754,7 @@ extends: # - template: /eng/pipelines/common/platform-matrix.yml parameters: - jobTemplate: /eng/pipelines/mono/templates/generate-offsets.yml - templatePath: 'templates' + jobTemplate: /eng/pipelines/common/global-build-job.yml buildConfig: release platforms: - android_x64 @@ -763,8 +763,26 @@ extends: - tvos_arm64 - ios_arm64 - maccatalyst_x64 + variables: + - name: _osParameter + value: -os linux + - name: _archParameter + value: -arch x64 jobParameters: - isOfficialBuild: false + nameSuffix: MonoAOTOffsets + buildArgs: -s mono.aotcross -c $(_BuildConfig) /p:MonoGenerateOffsetsOSGroups=$(osGroup) + postBuildSteps: + # Upload offset files + - task: CopyFiles@2 + displayName: Collect offset files + inputs: + sourceFolder: '$(Build.SourcesDirectory)/artifacts/obj/mono/' + contents: '**/offsets-*.h' + targetFolder: '$(Build.SourcesDirectory)/artifacts/obj/mono/offsetfiles/' + + - publish: '$(Build.SourcesDirectory)/artifacts/obj/mono/offsetfiles' + artifact: Mono_Offsets_$(osGroup)$(osSubGroup) + displayName: Upload offset files # needed by crossaot condition: >- or( @@ -823,8 +841,9 @@ extends: alwaysRun: ${{ variables.isRollingBuild }} extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) scenarios: - - normal - - WasmTestOnBrowser + - WasmTestOnV8 + - WasmTestOnChrome + - WasmTestOnFirefox - template: /eng/pipelines/common/templates/wasm-library-tests.yml parameters: @@ -833,7 +852,7 @@ extends: alwaysRun: ${{ variables.isRollingBuild }} extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) scenarios: - - WasmTestOnBrowser + - WasmTestOnChrome # Library tests with full threading - template: /eng/pipelines/common/templates/wasm-library-tests.yml @@ -843,10 +862,12 @@ extends: #- browser_wasm_win nameSuffix: _Threading extraBuildArgs: /p:WasmEnableThreads=true /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) + extraHelixArguments: /p:WasmEnableThreads=true alwaysRun: ${{ variables.isRollingBuild }} shouldRunSmokeOnly: onLibrariesAndIllinkChanges scenarios: - - WasmTestOnBrowser + - WasmTestOnChrome + - WasmTestOnFirefox #- WasmTestOnNodeJS - this is not supported yet, https://github.com/dotnet/runtime/issues/85592 # EAT Library tests - only run on linux @@ -867,7 +888,6 @@ extends: - browser_wasm - browser_wasm_win - wasi_wasm - - wasi_wasm_win nameSuffix: _Smoke_AOT runAOT: true shouldRunSmokeOnly: true @@ -935,7 +955,7 @@ extends: shouldRunSmokeOnly: true alwaysRun: ${{ variables.isRollingBuild }} scenarios: - - normal + - WasmTestOnWasmtime - template: /eng/pipelines/common/templates/simple-wasm-build-tests.yml parameters: @@ -1009,7 +1029,7 @@ extends: jobParameters: testGroup: innerloop nameSuffix: AllSubsets_Mono - buildArgs: -s mono+libs+libs.tests+host+packs -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true /p:RunSmokeTestsOnly=true /p:BuildTestsOnHelix=true /p:EnableAdditionalTimezoneChecks=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true + buildArgs: -s mono+libs+libs.tests+host+packs -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true /p:RunSmokeTestsOnly=true /p:BuildTestsOnHelix=true /p:EnableAdditionalTimezoneChecks=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true /p:EnableAggressiveTrimming=true timeoutInMinutes: 480 condition: >- or( @@ -1245,9 +1265,9 @@ extends: nameSuffix: CrossAOT_Mono runtimeVariant: crossaot dependsOn: - - mono_android_offsets - - mono_browser_offsets - - mono_wasi_offsets + - build_android_x64_release_MonoAOTOffsets + - build_browser_wasm_linux_release_MonoAOTOffsets + - build_wasi_wasm_linux_release_MonoAOTOffsets monoCrossAOTTargetOS: - android - browser @@ -1272,9 +1292,9 @@ extends: nameSuffix: CrossAOT_Mono runtimeVariant: crossaot dependsOn: - - mono_android_offsets - - mono_browser_offsets - - mono_wasi_offsets + - build_android_x64_release_MonoAOTOffsets + - build_browser_wasm_linux_release_MonoAOTOffsets + - build_wasi_wasm_linux_release_MonoAOTOffsets monoCrossAOTTargetOS: - android - browser @@ -1303,12 +1323,12 @@ extends: nameSuffix: CrossAOT_Mono runtimeVariant: crossaot dependsOn: - - mono_android_offsets - - mono_browser_offsets - - mono_wasi_offsets - - mono_tvos_offsets - - mono_ios_offsets - - mono_maccatalyst_offsets + - build_android_x64_release_MonoAOTOffsets + - build_browser_wasm_linux_release_MonoAOTOffsets + - build_wasi_wasm_linux_release_MonoAOTOffsets + - build_tvos_arm64_release_MonoAOTOffsets + - build_ios_arm64_release_MonoAOTOffsets + - build_maccatalyst_x64_release_MonoAOTOffsets monoCrossAOTTargetOS: - android - browser @@ -1878,36 +1898,29 @@ extends: eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_mono_excluding_wasm.containsChange'], true), eq(variables['isRollingBuild'], true)) - # - # Sourcebuild legs - # We have 3 important legs for source-build: - # - Centos.8 (ensures that known non-portable RID is working) - # - Linux-x64 portable (used for dependency flow and downstream PR verification) - # - Banana.24 - Non-existent RID to ensure we don't break RIDs we don't know about. - # - # Running all of these everywhere is wasteful. Run Banana.24 and CentOS.8 in rolling CI, - # Run Linux-x64 in PR. - - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: Release - helixQueueGroup: pr - platforms: - - SourceBuild_centos8_x64 - jobParameters: - nameSuffix: centos8SourceBuild - timeoutInMinutes: 95 - condition: eq(variables['isRollingBuild'], true) - - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: Release - helixQueueGroup: pr - platforms: - - SourceBuild_banana24_x64 - jobParameters: - nameSuffix: banana24SourceBuild - timeoutInMinutes: 95 - condition: eq(variables['isRollingBuild'], true) + - stage: SourceBuild + displayName: Source Build Validation + dependsOn: [] + condition: eq(variables['isRollingBuild'], true) + jobs: + # + # Sourcebuild legs + # We have 3 important legs for source-build: + # - Centos.8 (ensures that known non-portable RID is working) + # - Linux-x64 portable (used for dependency flow and downstream PR verification) + # - Banana.24 - Non-existent RID to ensure we don't break RIDs we don't know about. + # + # Running all of these everywhere is wasteful. Run Banana.24 and CentOS.8 in rolling CI, + # Run Linux-x64 in PR. + - template: /eng/common/templates/jobs/source-build.yml + parameters: + platforms: + - name: CentOS8 + targetRid: centos.8-x64 + nonPortable: true + container: SourceBuild_centos_x64 + - name: NonexistentRID + baseOS: linux + targetRid: banana.24-x64 + nonPortable: true + container: SourceBuild_centos_x64 diff --git a/eng/pipelines/runtimelab.yml b/eng/pipelines/runtimelab.yml index 3b71ae9475cd..e8bea9140f53 100644 --- a/eng/pipelines/runtimelab.yml +++ b/eng/pipelines/runtimelab.yml @@ -59,7 +59,7 @@ extends: helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml buildConfig: debug platforms: - - osx_x64 + # - osx_x64 # Upstream break. - windows_x64 - Browser_wasm_win - wasi_wasm_win diff --git a/eng/testing/BrowserVersions.props b/eng/testing/BrowserVersions.props new file mode 100644 index 000000000000..08d0faffe037 --- /dev/null +++ b/eng/testing/BrowserVersions.props @@ -0,0 +1,16 @@ + + + 125.0.6422.60 + 1287751 + https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/1287757 + 12.5.227 + 125.0.6422.60 + 1287751 + https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/1287751 + 12.5.227 + 125.0.1 + 0.34.0 + 125.0.1 + 0.34.0 + + \ No newline at end of file diff --git a/eng/testing/ChromeVersions.props b/eng/testing/ChromeVersions.props deleted file mode 100644 index c919397b3a06..000000000000 --- a/eng/testing/ChromeVersions.props +++ /dev/null @@ -1,12 +0,0 @@ - - - 123.0.6312.58 - 1262506 - https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/1262506 - 12.3.219 - 123.0.6312.58 - 1262506 - https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/1262514 - 12.3.219 - - diff --git a/eng/testing/WasiRunnerAOTTemplate.sh b/eng/testing/WasiRunnerAOTTemplate.sh deleted file mode 100644 index b45c553b67c5..000000000000 --- a/eng/testing/WasiRunnerAOTTemplate.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env bash - -# SetCommands defined in eng\testing\tests.wasm.targets -[[SetCommands]] -[[SetCommandsEcho]] - -EXECUTION_DIR=$(dirname $0) -if [[ -n "$3" ]]; then - SCENARIO=$3 -fi - -export PATH=$PREPEND_PATH:$PATH - -if [[ -z "$HELIX_WORKITEM_UPLOAD_ROOT" ]]; then - XHARNESS_OUT="$EXECUTION_DIR/xharness-output" -else - XHARNESS_OUT="$HELIX_WORKITEM_UPLOAD_ROOT/xharness-output" -fi - -if [[ -n "$XHARNESS_CLI_PATH" ]]; then - # When running in CI, we only have the .NET runtime available - # We need to call the XHarness CLI DLL directly via dotnet exec - HARNESS_RUNNER="dotnet exec $XHARNESS_CLI_PATH" -else - HARNESS_RUNNER="dotnet xharness" -fi - -if [[ -z "$XHARNESS_COMMAND" ]]; then - XHARNESS_COMMAND="test" -fi - -echo PATH=$PATH -echo EXECUTION_DIR=$EXECUTION_DIR -echo SCENARIO=$SCENARIO -echo XHARNESS_OUT=$XHARNESS_OUT -echo XHARNESS_CLI_PATH=$XHARNESS_CLI_PATH -echo HARNESS_RUNNER=$HARNESS_RUNNER -echo XHARNESS_COMMAND=$XHARNESS_COMMAND -echo XHARNESS_ARGS=$XHARNESS_ARGS - -function _buildAOTFunc() -{ - local projectFile=$1 - local binLog=$2 - shift 2 - - time dotnet msbuild $projectFile /bl:$binLog $* - local buildExitCode=$? - - echo "\n** Performance summary for the build **\n" - dotnet msbuild $binLog -clp:PerformanceSummary -v:q -nologo - if [[ "$(uname -s)" == "Linux" && $buildExitCode -ne 0 ]]; then - echo "\nLast few messages from dmesg:\n" - local lastLines=`dmesg | tail -n 20` - echo $lastLines - - if [[ "$lastLines" =~ "oom-kill" ]]; then - return 9200 # OOM - fi - fi - - echo - echo - - if [[ $buildExitCode -ne 0 ]]; then - return 9100 # aot build failure - fi - - return 0 -} - -pushd $EXECUTION_DIR - -# ========================= BEGIN Test Execution ============================= -echo ----- start $(date) =============== To repro directly: ===================================================== -echo pushd $EXECUTION_DIR -# RunCommands defined in eng\testing\tests.wasm.targets -[[RunCommandsEcho]] -echo popd -echo =========================================================================================================== -pushd $EXECUTION_DIR -# RunCommands defined in eng\testing\tests.wasm.targets -[[RunCommands]] -_exitCode=$? -popd -echo ----- end $(date) ----- exit code $_exitCode ---------------------------------------------------------- - -echo "XHarness artifacts: $XHARNESS_OUT" - -exit $_exitCode diff --git a/eng/testing/WasiRunnerTemplate.sh b/eng/testing/WasiRunnerTemplate.sh index 7a3752d32117..66e6731e03f2 100644 --- a/eng/testing/WasiRunnerTemplate.sh +++ b/eng/testing/WasiRunnerTemplate.sh @@ -47,6 +47,37 @@ echo HARNESS_RUNNER=$HARNESS_RUNNER echo XHARNESS_COMMAND=$XHARNESS_COMMAND echo XHARNESS_ARGS=$XHARNESS_ARGS +function _buildAOTFunc() +{ + local projectFile=$1 + local binLog=$2 + shift 2 + + time dotnet msbuild $projectFile /bl:$binLog $* + local buildExitCode=$? + + echo "\n** Performance summary for the build **\n" + dotnet msbuild $binLog -clp:PerformanceSummary -v:q -nologo + if [[ "$(uname -s)" == "Linux" && $buildExitCode -ne 0 ]]; then + echo "\nLast few messages from dmesg:\n" + local lastLines=`dmesg | tail -n 20` + echo $lastLines + + if [[ "$lastLines" =~ "oom-kill" ]]; then + return 9200 # OOM + fi + fi + + echo + echo + + if [[ $buildExitCode -ne 0 ]]; then + return 9100 # aot build failure + fi + + return 0 +} + pushd $EXECUTION_DIR # ========================= BEGIN Test Execution ============================= diff --git a/eng/testing/WasmRunnerAOTTemplate.sh b/eng/testing/WasmRunnerAOTTemplate.sh deleted file mode 100644 index 1e17a2a4770e..000000000000 --- a/eng/testing/WasmRunnerAOTTemplate.sh +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env bash - -# SetCommands defined in eng\testing\tests.wasm.targets -[[SetCommands]] -[[SetCommandsEcho]] - -export PATH="$HOME/.jsvu/bin:$PATH" -export PATH=$PREPEND_PATH:$PATH - -EXECUTION_DIR=$(dirname $0) -if [[ -n "$3" ]]; then - SCENARIO=$3 -fi - -if [[ -z "$HELIX_WORKITEM_UPLOAD_ROOT" ]]; then - XHARNESS_OUT="$EXECUTION_DIR/xharness-output" -else - XHARNESS_OUT="$HELIX_WORKITEM_UPLOAD_ROOT/xharness-output" -fi - -if [[ -n "$XHARNESS_CLI_PATH" ]]; then - # When running in CI, we only have the .NET runtime available - # We need to call the XHarness CLI DLL directly via dotnet exec - HARNESS_RUNNER="dotnet exec $XHARNESS_CLI_PATH" -else - HARNESS_RUNNER="dotnet xharness" -fi - -if [[ -z "$XHARNESS_COMMAND" ]]; then - if [[ "$SCENARIO" == "WasmTestOnBrowser" || "$SCENARIO" == "wasmtestonbrowser" ]]; then - XHARNESS_COMMAND="test-browser" - else - XHARNESS_COMMAND="test" - fi -fi - -if [[ "$XHARNESS_COMMAND" == "test" ]]; then - if [[ -z "$JS_ENGINE_ARGS" ]]; then - JS_ENGINE_ARGS="--engine-arg=--stack-trace-limit=1000" - if [[ "$SCENARIO" != "WasmTestOnNodeJS" && "$SCENARIO" != "wasmtestonnodejs" ]]; then - JS_ENGINE_ARGS="$JS_ENGINE_ARGS --engine-arg=--module" - fi - if [[ "$SCENARIO" == "WasmTestOnNodeJS" || "$SCENARIO" == "wasmtestonnodejs" ]]; then - JS_ENGINE_ARGS="$JS_ENGINE_ARGS --engine-arg=--experimental-wasm-eh" - fi - fi - - if [[ -z "$MAIN_JS" ]]; then - MAIN_JS="--js-file=test-main.js" - fi - - if [[ -z "$JS_ENGINE" ]]; then - if [[ "$SCENARIO" == "WasmTestOnNodeJS" || "$SCENARIO" == "wasmtestonnodejs" ]]; then - JS_ENGINE="--engine=NodeJS" - else - JS_ENGINE="--engine=V8" - if [[ -n "$V8_PATH_FOR_TESTS" ]]; then - JS_ENGINE_ARGS="$JS_ENGINE_ARGS --js-engine-path=$V8_PATH_FOR_TESTS" - fi - fi - fi -fi - -if [[ -z "$XHARNESS_ARGS" ]]; then - XHARNESS_ARGS="$JS_ENGINE $JS_ENGINE_ARGS $MAIN_JS" -fi - -echo PATH=$PATH -echo EXECUTION_DIR=$EXECUTION_DIR -echo SCENARIO=$SCENARIO -echo XHARNESS_OUT=$XHARNESS_OUT -echo XHARNESS_CLI_PATH=$XHARNESS_CLI_PATH -echo HARNESS_RUNNER=$HARNESS_RUNNER -echo XHARNESS_COMMAND=$XHARNESS_COMMAND -echo MAIN_JS=$MAIN_JS -echo JS_ENGINE=$JS_ENGINE -echo JS_ENGINE_ARGS=$JS_ENGINE_ARGS -echo XHARNESS_ARGS=$XHARNESS_ARGS - -function _buildAOTFunc() -{ - local projectFile=$1 - local binLog=$2 - shift 2 - - time dotnet msbuild $projectFile /bl:$binLog $* - local buildExitCode=$? - - echo "\n** Performance summary for the build **\n" - dotnet msbuild $binLog -clp:PerformanceSummary -v:q -nologo - if [[ "$(uname -s)" == "Linux" && $buildExitCode -ne 0 ]]; then - echo "\nLast few messages from dmesg:\n" - local lastLines=`dmesg | tail -n 20` - echo $lastLines - - if [[ "$lastLines" =~ "oom-kill" ]]; then - return 9200 # OOM - fi - fi - - echo - echo - - if [[ $buildExitCode -ne 0 ]]; then - return 9100 # aot build failure - fi - - return 0 -} - - -pushd $EXECUTION_DIR - -# ========================= BEGIN Test Execution ============================= -echo ----- start $(date) =============== To repro directly: ===================================================== -echo pushd $EXECUTION_DIR -# RunCommands defined in eng\testing\tests.wasm.targets -[[RunCommandsEcho]] -echo popd -echo =========================================================================================================== -pushd $EXECUTION_DIR -# RunCommands defined in eng\testing\tests.wasm.targets -[[RunCommands]] -_exitCode=$? -popd -echo ----- end $(date) ----- exit code $_exitCode ---------------------------------------------------------- - -echo "XHarness artifacts: $XHARNESS_OUT" - -exit $_exitCode diff --git a/eng/testing/WasmRunnerTemplate.cmd b/eng/testing/WasmRunnerTemplate.cmd index f92cee17cc9d..e043ce7a34e9 100644 --- a/eng/testing/WasmRunnerTemplate.cmd +++ b/eng/testing/WasmRunnerTemplate.cmd @@ -27,10 +27,14 @@ if [%XHARNESS_CLI_PATH%] NEQ [] ( ) if [%XHARNESS_COMMAND%] == [] ( - if /I [%SCENARIO%]==[WasmTestOnBrowser] ( + if /I [%SCENARIO%]==[WasmTestOnChrome] ( set XHARNESS_COMMAND=test-browser ) else ( - set XHARNESS_COMMAND=test + if /I [%SCENARIO%]==[WasmTestOnFirefox] ( + set XHARNESS_COMMAND=test-browser + ) else ( + set XHARNESS_COMMAND=test + ) ) ) @@ -56,11 +60,25 @@ if /I [%XHARNESS_COMMAND%] == [test] ( ) ) ) else ( - if [%BROWSER_PATH%] == [] if not [%HELIX_CORRELATION_PAYLOAD%] == [] ( - set "BROWSER_PATH=--browser-path^=%HELIX_CORRELATION_PAYLOAD%\chrome-win\chrome.exe" - ) - if [%JS_ENGINE_ARGS%] == [] ( - set "JS_ENGINE_ARGS=--browser-arg^=--js-flags^=--stack-trace-limit^=1000" + if /I [%SCENARIO%] == [WasmTestOnChrome] ( + if [%BROWSER_PATH%] == [] if not [%HELIX_CORRELATION_PAYLOAD%] == [] ( + set "BROWSER_PATH=--browser-path^=%HELIX_CORRELATION_PAYLOAD%\chrome-win\chrome.exe" + ) + if [%JS_ENGINE_ARGS%] == [] ( + set "JS_ENGINE_ARGS=--browser-arg^=--js-flags^=--stack-trace-limit^=1000" + ) + ) else ( + if /I [%SCENARIO%] == [WasmTestOnFirefox] ( + if [%BROWSER_PATH%] == [] if not [%HELIX_CORRELATION_PAYLOAD%] == [] ( + set "BROWSER_PATH=--browser-path^=%HELIX_CORRELATION_PAYLOAD%\firefox\firefox.exe" + ) + if [%JS_ENGINE%] == [] ( + set "JS_ENGINE=--browser^=Firefox" + ) + if [%JS_ENGINE_ARGS%] == [] ( + set "JS_ENGINE_ARGS=--browser-arg^=-private-window" + ) + ) ) ) diff --git a/eng/testing/WasmRunnerTemplate.sh b/eng/testing/WasmRunnerTemplate.sh index 4f5856546fc5..6cf4dc11d4be 100644 --- a/eng/testing/WasmRunnerTemplate.sh +++ b/eng/testing/WasmRunnerTemplate.sh @@ -26,7 +26,9 @@ else fi if [[ -z "$XHARNESS_COMMAND" ]]; then - if [[ "$SCENARIO" == "WasmTestOnBrowser" || "$SCENARIO" == "wasmtestonbrowser" ]]; then + if [[ "$SCENARIO" == "WasmTestOnFirefox" || "$SCENARIO" == "wasmtestonfirefox" ]]; then + XHARNESS_COMMAND="test-browser" + elif [[ "$SCENARIO" == "WasmTestOnChrome" || "$SCENARIO" == "wasmtestonchrome" ]]; then XHARNESS_COMMAND="test-browser" else XHARNESS_COMMAND="test" @@ -59,8 +61,17 @@ if [[ "$XHARNESS_COMMAND" == "test" ]]; then fi fi else - if [[ -z "$JS_ENGINE_ARGS" ]]; then - JS_ENGINE_ARGS="--browser-arg=--js-flags=--stack-trace-limit=1000" + if [[ "$SCENARIO" == "WasmTestOnChrome" || "$SCENARIO" == "wasmtestonchrome" ]]; then + if [[ -z "$JS_ENGINE_ARGS" ]]; then + JS_ENGINE_ARGS="--browser-arg=--js-flags=--stack-trace-limit=1000" + fi + elif [[ "$SCENARIO" == "WasmTestOnFirefox" || "$SCENARIO" == "wasmtestonfirefox" ]]; then + if [[ -z "$JS_ENGINE" ]]; then + JS_ENGINE="--browser=Firefox" + fi + if [[ -z "$JS_ENGINE_ARGS" ]]; then + JS_ENGINE_ARGS="--browser-arg=-private-window" + fi fi fi @@ -88,6 +99,38 @@ echo JS_ENGINE=$JS_ENGINE echo JS_ENGINE_ARGS=$JS_ENGINE_ARGS echo XHARNESS_ARGS=$XHARNESS_ARGS +function _buildAOTFunc() +{ + local projectFile=$1 + local binLog=$2 + shift 2 + + time dotnet msbuild $projectFile /bl:$binLog $* + local buildExitCode=$? + + echo "\n** Performance summary for the build **\n" + dotnet msbuild $binLog -clp:PerformanceSummary -v:q -nologo + if [[ "$(uname -s)" == "Linux" && $buildExitCode -ne 0 ]]; then + echo "\nLast few messages from dmesg:\n" + local lastLines=`dmesg | tail -n 20` + echo $lastLines + + if [[ "$lastLines" =~ "oom-kill" ]]; then + return 9200 # OOM + fi + fi + + echo + echo + + if [[ $buildExitCode -ne 0 ]]; then + return 9100 # aot build failure + fi + + return 0 +} + + pushd $EXECUTION_DIR # ========================= BEGIN Test Execution ============================= diff --git a/eng/testing/bump-chrome-version.proj b/eng/testing/bump-chrome-version.proj index 334e37bfd32b..77fc525f8c80 100644 --- a/eng/testing/bump-chrome-version.proj +++ b/eng/testing/bump-chrome-version.proj @@ -3,7 +3,7 @@ - $(RepositoryEngineeringDir)testing\ChromeVersions.props + $(RepositoryEngineeringDir)testing\BrowserVersions.props $(RepositoryEngineeringDir)testing\bump-chrome-pr.env diff --git a/eng/testing/helix-extension-example.targets b/eng/testing/helix-extension-example.targets index e14095c07567..77b3490d5001 100644 --- a/eng/testing/helix-extension-example.targets +++ b/eng/testing/helix-extension-example.targets @@ -1,5 +1,5 @@ - + $(HelixExtensionTargets);_AddHelixCrypoItems <_CryptoProjectName>System.Security.Cryptography.Tests diff --git a/eng/testing/linker/SupportFiles/Directory.Build.props b/eng/testing/linker/SupportFiles/Directory.Build.props index 5a54c83e5692..4e33801ab128 100644 --- a/eng/testing/linker/SupportFiles/Directory.Build.props +++ b/eng/testing/linker/SupportFiles/Directory.Build.props @@ -11,6 +11,7 @@ false true + true $(NoWarn);IL2121 diff --git a/eng/testing/linker/trimmingTests.props b/eng/testing/linker/trimmingTests.props index b917cd5fe382..b822294a93d0 100644 --- a/eng/testing/linker/trimmingTests.props +++ b/eng/testing/linker/trimmingTests.props @@ -1,6 +1,8 @@ - $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'trimmingTests')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'trimmingTests')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'aotTests')) + $([MSBuild]::NormalizeDirectory('$(TrimmingTestDir)', 'projects')) $(MSBuildThisFileDirectory)project.csproj.template true diff --git a/eng/testing/linker/trimmingTests.targets b/eng/testing/linker/trimmingTests.targets index 926bafa52cfe..7ff8fccc2c01 100644 --- a/eng/testing/linker/trimmingTests.targets +++ b/eng/testing/linker/trimmingTests.targets @@ -38,7 +38,13 @@ - + <_SkippedAppSourceFiles Include="@(TestConsoleAppSourceFiles)" Condition="$([System.String]::Copy('%(TestConsoleAppSourceFiles.SkipOnTestRuntimes)').Contains('$(PackageRID)'))" /> + + <_SkippedAppSourceFiles Include="@(TestConsoleAppSourceFiles)" Condition="'$(RunNativeAotTestApps)' == 'true' and '%(TestConsoleAppSourceFiles.NativeAotIncompatible)' == 'true'" /> + + <_AppSourceFiles Include="@(TestConsoleAppSourceFiles)" Exclude="@(_SkippedAppSourceFiles)" /> + + %(FullPath) @@ -81,6 +87,9 @@ <_additionalPropertiesString>@(_propertiesAsItems->'<%(Identity)>%(Value)</%(Identity)>', '%0a ') + + + + Properties="Configuration=$(Configuration);BuildProjectReferences=false;TargetOS=$(TargetOS);TargetArchitecture=$(TargetArchitecture);_IsPublishing=true" /> - + diff --git a/eng/testing/performance/performance-setup.sh b/eng/testing/performance/performance-setup.sh index ff04015375a3..489b3a22cccd 100755 --- a/eng/testing/performance/performance-setup.sh +++ b/eng/testing/performance/performance-setup.sh @@ -451,7 +451,7 @@ if [[ -n "$wasm_bundle_directory" ]]; then # get required version if [[ -z "$v8_version" ]]; then - v8_version=`grep linux_V8Version $source_directory/eng/testing/ChromeVersions.props | sed -e 's,.*>\([^\<]*\)<.*,\1,g' | cut -d. -f 1-3` + v8_version=`grep linux_V8Version $source_directory/eng/testing/BrowserVersions.props | sed -e 's,.*>\([^\<]*\)<.*,\1,g' | cut -d. -f 1-3` echo "V8 version: $v8_version" fi if [[ -z "$javascript_engine_path" ]]; then diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt index 5ccb34b25e18..11bfdab2c741 100644 --- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt +++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt @@ -3,7 +3,7 @@ Wasm.Build.NativeRebuild.Tests.NoopNativeRebuildTest Wasm.Build.NativeRebuild.Tests.OptimizationFlagChangeTests Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest Wasm.Build.NativeRebuild.Tests.SimpleSourceChangeRebuildTest -Wasm.Build.Templates.Tests.InterpPgoTests +Wasm.Build.Tests.TestAppScenarios.InterpPgoTests Wasm.Build.Templates.Tests.NativeBuildTests Wasm.Build.Tests.Blazor.AppsettingsTests Wasm.Build.Tests.Blazor.BuildPublishTests @@ -17,6 +17,7 @@ Wasm.Build.Tests.Blazor.NoopNativeRebuildTest Wasm.Build.Tests.Blazor.WorkloadRequiredTests Wasm.Build.Tests.Blazor.IcuTests Wasm.Build.Tests.Blazor.IcuShardingTests +Wasm.Build.Tests.Blazor.SignalRClientTests Wasm.Build.Tests.BuildPublishTests Wasm.Build.Tests.ConfigSrcTests Wasm.Build.Tests.HybridGlobalizationTests @@ -36,8 +37,8 @@ Wasm.Build.Tests.TestAppScenarios.AppSettingsTests Wasm.Build.Tests.TestAppScenarios.LazyLoadingTests Wasm.Build.Tests.TestAppScenarios.LibraryInitializerTests Wasm.Build.Tests.TestAppScenarios.SatelliteLoadingTests -Wasm.Build.Tests.TestAppScenarios.DownloadResourceProgressTests -Wasm.Build.Tests.TestAppScenarios.SignalRClientTests +Wasm.Build.Tests.TestAppScenarios.ModuleConfigTests +Wasm.Build.Tests.AspNetCore.SignalRClientTests Wasm.Build.Tests.WasmBuildAppTest Wasm.Build.Tests.WasmNativeDefaultsTests Wasm.Build.Tests.WasmRunOutOfAppBundleTests diff --git a/eng/testing/tests.browser.targets b/eng/testing/tests.browser.targets index 982b8589e76c..3ff4c3b50776 100644 --- a/eng/testing/tests.browser.targets +++ b/eng/testing/tests.browser.targets @@ -26,7 +26,10 @@ true + '$(Scenario)' == 'WasmTestOnChrome'">true + true - <_WasmBrowserPathForTests Condition="'$(BROWSER_PATH_FOR_TESTS)' != ''">$(BROWSER_PATH_FOR_TESTS) - <_WasmBrowserPathForTests Condition="'$(_WasmBrowserPathForTests)' == '' and '$(InstallChromeForTests)' == 'true'">$(ChromeBinaryPath) + <_WasmChromePathForTests Condition="'$(CHROME_PATH_FOR_TESTS)' != ''">$(CHROME_PATH_FOR_TESTS) + <_WasmChromePathForTests Condition="'$(_WasmChromePathForTests)' == '' and '$(InstallChromeForTests)' == 'true'">$(ChromeBinaryPath) + + <_WasmFirefoxPathForTests Condition="'$(FIREFOX_PATH_FOR_TESTS)' != ''">$(FIREFOX_PATH_FOR_TESTS) + <_WasmFirefoxPathForTests Condition="'$(_WasmFirefoxPathForTests)' == '' and '$(InstallFirefoxForTests)' == 'true'">$(FirefoxBinaryPath) <_WasmJSEnginePathForTests Condition="'$(V8_PATH_FOR_TESTS)' != ''">$(V8_PATH_FOR_TESTS) <_WasmJSEnginePathForTests Condition="'$(_WasmJSEnginePathForTests)' == '' and '$(InstallV8ForTests)' == 'true'">$(V8BinaryPath) @@ -87,8 +93,6 @@ <_AppArgs Condition="'$(IsFunctionalTest)' != 'true' and '$(WasmMainAssemblyFileName)' != ''">--run $(WasmMainAssemblyFileName) <_AppArgs Condition="'$(IsFunctionalTest)' == 'true'">--run $(AssemblyName).dll - $(WasmTestAppArgs) -backgroundExec - $(WasmXHarnessMonoArgs) --setenv=IsWasmBackgroundExec=true <_AppArgs Condition="'$(WasmTestAppArgs)' != ''">$(_AppArgs) $(WasmTestAppArgs) $(WasmXHarnessMonoArgs) --setenv=XHARNESS_LOG_TEST_START=true @@ -107,7 +111,8 @@ <_XHarnessArgs >$(_XHarnessArgs) -s dotnet.native.js.symbols <_XHarnessArgs Condition="'$(_UseWasmSymbolicator)' == 'true'" >$(_XHarnessArgs) --symbol-patterns wasm-symbol-patterns.txt <_XHarnessArgs Condition="'$(_UseWasmSymbolicator)' == 'true'" >$(_XHarnessArgs) --symbolicator WasmSymbolicator.dll,Microsoft.WebAssembly.Internal.SymbolicatorWrapperForXHarness - <_XHarnessArgs Condition="'$(_WasmBrowserPathForTests)' != ''" >$(_XHarnessArgs) "--browser-path=$(_WasmBrowserPathForTests)" + <_XHarnessArgs Condition="'$(_WasmChromePathForTests)' != ''" >$(_XHarnessArgs) "--browser-path=$(_WasmChromePathForTests)" + <_XHarnessArgs Condition="'$(_WasmFirefoxPathForTests)' != ''" >$(_XHarnessArgs) "--browser-path=$(_WasmFirefoxPathForTests)" <_XHarnessArgs Condition="'$(WasmXHarnessTestsTimeout)' != ''" >$(_XHarnessArgs) "--timeout=$(WasmXHarnessTestsTimeout)" <_XHarnessArgs Condition="'$(WasmXHarnessVerbosity)' != ''" >$(_XHarnessArgs) --verbosity=$(WasmXHarnessVerbosity) <_XHarnessArgs Condition="'$(WasmXHarnessArgsCli)' != ''" >$(_XHarnessArgs) $(WasmXHarnessArgsCli) @@ -243,15 +248,25 @@ <_NodeNpmModuleStringTrimmed Include="@(_NodeNpmModuleString->Trim(':'))" /> + WasmTestOnV8 @(_NodeNpmModuleStringTrimmed, ',') + + + @@ -259,6 +274,7 @@ + diff --git a/eng/testing/tests.ioslike.targets b/eng/testing/tests.ioslike.targets index 50f89bfef82a..dde49575d7ae 100644 --- a/eng/testing/tests.ioslike.targets +++ b/eng/testing/tests.ioslike.targets @@ -16,7 +16,7 @@ <_AOTBuildCommand Condition="'$(ContinuousIntegrationBuild)' != 'true'">$(_AOTBuildCommand) /p:RuntimeSrcDir=$(RepoRoot) /p:RuntimeConfig=$(Configuration) - <_AOTBuildCommand>$(_AOTBuildCommand) /p:XHARNESS_EXECUTION_DIR="$XHARNESS_EXECUTION_DIR" /p:RunAOTCompilation=$(RunAOTCompilation) /p:UseNativeAOTRuntime=$(UseNativeAOTRuntime) /p:TargetOS=$(TargetOS) /p:TargetArchitecture=$(TargetArchitecture) /p:MonoForceInterpreter=$(MonoForceInterpreter) /p:MonoEnableLLVM=true /p:DevTeamProvisioning=$(DevTeamProvisioning) /p:UsePortableRuntimePack=true /p:Configuration=$(Configuration) + <_AOTBuildCommand>$(_AOTBuildCommand) /p:XHARNESS_EXECUTION_DIR="$XHARNESS_EXECUTION_DIR" /p:RunAOTCompilation=$(RunAOTCompilation) /p:UseNativeAOTRuntime=$(UseNativeAOTRuntime) /p:TargetOS=$(TargetOS) /p:TargetArchitecture=$(TargetArchitecture) /p:MonoForceInterpreter=$(MonoForceInterpreter) /p:MonoEnableLLVM=true /p:DevTeamProvisioning=$(DevTeamProvisioning) /p:UsePortableRuntimePack=true /p:Configuration=$(Configuration) /p:EnableAggressiveTrimming=$(EnableAggressiveTrimming) <_AOTBuildCommand Condition="'$(NativeLib)' != ''">$(_AOTBuildCommand) /p:NativeLib=$(NativeLib) /p:BundlesResources=$(BundlesResources) /p:ForceLibraryModeGenerateAppBundle=$(ForceLibraryModeGenerateAppBundle) <_AOTBuildCommand>$(_AOTBuildCommand) @@ -46,11 +46,11 @@ PrepareForAppleBuildApp;$(AppleBuildDependsOn);_CopyTestArchive - + AppleBuild $(BundleTestAppleAppDependsOn);_BundleAOTTestAppleAppForHelix;_CopyTestArchive - + $(BundleDir)publish - + <_MainAssemblyPath Condition="'%(AppleAssembliesToBundle.FileName)' == $(AssemblyName) and '%(AppleAssembliesToBundle.Extension)' == '.dll'">%(AppleAssembliesToBundle.Identity) $([System.IO.Path]::ChangeExtension($(_MainAssemblyPath), '.runtimeconfig.json')) @@ -76,6 +76,8 @@ + @@ -104,41 +106,62 @@ <_RuntimePackFiles Include="$(MicrosoftNetCoreAppRuntimePackRidLibTfmDir)**\*.*" /> <_RuntimePackFiles Include="$(MicrosoftNetCoreAppRuntimePackNativeDir)*.*" /> - + <_UnusedRuntimePackFiles Include="@(_PublishBundleFiles)" Exclude="@(_RuntimePackFiles->'$(AppBundlePath)/%(FileName)%(Extension)')" /> <_UsedRuntimePackFiles Include="@(_PublishBundleFiles)" Exclude="@(_UnusedRuntimePackFiles)" /> - + <_RuntimePackFilesToDelete Include="@(_RuntimePackFiles->'$(AppBundlePath)/%(FileName)%(Extension)')" /> + + + + + - <_ApplePropertyNames Include="InvariantGlobalization" /> - <_ApplePropertyNames Include="HybridGlobalization" /> + <_ApplePropertyNames Include="AssemblyName" /> - <_ApplePropertyNames Include="MonoEnableLLVM" /> + <_ApplePropertyNames Include="IncludesTestRunner" /> <_ApplePropertyNames Include="MainLibraryFileName" /> + <_ApplePropertyNames Include="MonoEnableLLVM" /> + <_ApplePropertyNames Include="ShouldILStrip" /> <_ApplePropertyNames Include="UseConsoleUITemplate" /> <_ApplePropertyNames Include="UseRuntimeComponents" /> - <_ApplePropertyNames Include="IncludesTestRunner" /> - <_ApplePropertyNames Include="ShouldILStrip" /> + <_ApplePropertyNames Include="_NetCoreAppToolCurrent" /> + + + <_ApplePropertyNames Include="HybridGlobalization" /> + <_ApplePropertyNames Include="InvariantGlobalization" /> + + <_AppleUsedRuntimePackFiles + Include="@(_UsedRuntimePackFiles->'%(FileName)%(Extension)')" + RemoveMetadata="_IsNative;TargetDir" /> <_ApplePropertiesToPass - Include="$(%(_ApplePropertyNames.Identity))" - Name="%(_ApplePropertyNames.Identity)" - ConditionToUse__="%(_ApplePropertyNames.ConditionToUse__)" /> - - <_AppleUsedRuntimePackFiles - Include="@(_UsedRuntimePackFiles->'%(FileName)%(Extension)')" - RemoveMetadata="_IsNative;TargetDir" /> - + Include="$(%(_ApplePropertyNames.Identity))" + Name="%(_ApplePropertyNames.Identity)" + ConditionToUse__="%(_ApplePropertyNames.ConditionToUse__)" /> + <_AppleItemsToPass Include="@(_AppleUsedRuntimePackFiles)" OriginalItemName__="_AppleUsedRuntimePackFiles" /> + <_AppleItemsToPass Include="@(AppleReferenceSharedPathFiles->'%(FileName)%(Extension)')" + OriginalItemName__="AppleReferenceSharedPathFiles" /> + + <_AppleItemsToPass Include="@(ReferenceExtraPathFiles->'%(FileName)%(Extension)')" + OriginalItemName__="AppleReferenceExtraPathFiles" /> + + <_AppleItemsToPass Include="@(RuntimeHostConfigurationOption)" + OriginalItemName__="_AppleUsedRuntimeHostConfigurationOption" /> + + <_AppleItemsToPass Include="@(TrimmerRootAssembly)" + OriginalItemName__="TrimmerRootAssembly" /> + + true true $(NoWarn);IL2103;IL2105;IL2025;IL2111 - - $(NoWarn);IL2035 - - false false @@ -93,10 +90,9 @@ - + - link - copyused + link @@ -107,24 +103,11 @@ TrimMode="" is needed so the root assemblies are correctly identified --> - - - - - - - - - - - - - + Include="%(ResolvedFileToPublish.FileName)" /> diff --git a/eng/testing/tests.targets b/eng/testing/tests.targets index e63040ff750f..d2980871283f 100644 --- a/eng/testing/tests.targets +++ b/eng/testing/tests.targets @@ -9,11 +9,9 @@ AppleHelixRunnerTemplate.sh AppleRunnerTemplate.sh AndroidRunnerTemplate.sh - WasiRunnerAOTTemplate.sh - WasiRunnerTemplate.sh + WasiRunnerTemplate.sh WasiRunnerTemplate.cmd - WasmRunnerAOTTemplate.sh - WasmRunnerTemplate.sh + WasmRunnerTemplate.sh WasmRunnerTemplate.cmd BionicRunnerTemplate.sh BionicRunnerTemplate.cmd diff --git a/eng/testing/tests.wasi.targets b/eng/testing/tests.wasi.targets index d147fea218fe..e8f75ee3821b 100644 --- a/eng/testing/tests.wasi.targets +++ b/eng/testing/tests.wasi.targets @@ -46,7 +46,7 @@ <_XHarnessArgs Condition="'$(IsFunctionalTest)' == 'true'" >$(_XHarnessArgs) --expected-exit-code=$(ExpectedExitCode) <_XHarnessArgs Condition="'$(WasmXHarnessArgs)' != ''" >$(_XHarnessArgs) $(WasmXHarnessArgs) <_XHarnessArgs Condition="'$(WasmXHarnessTestsTimeout)' != ''" >$(_XHarnessArgs) "--timeout=$(WasmXHarnessTestsTimeout)" - <_XHarnessArgs >$(_XHarnessArgs) --engine-arg=--max-wasm-stack=134217728 + <_XHarnessArgs >$(_XHarnessArgs) --engine-arg=-W --engine-arg=max-wasm-stack=134217728 <_XHarnessArgs Condition="'$(WasmXHarnessArgsCli)' != ''" >$(_XHarnessArgs) $(WasmXHarnessArgsCli) <_InvariantGlobalization Condition="'$(InvariantGlobalization)' == 'true'">--env=DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true @@ -147,6 +147,13 @@ + + WasmTestOnWasmtime + + + diff --git a/eng/testing/wasm-provisioning.targets b/eng/testing/wasm-provisioning.targets index 4852fd5ecc2e..540fcfb035fa 100644 --- a/eng/testing/wasm-provisioning.targets +++ b/eng/testing/wasm-provisioning.targets @@ -11,21 +11,42 @@ false + false false - $(ArtifactsBinDir)firefox\ - $([MSBuild]::NormalizePath($(FirefoxDir), '.install-firefox-$(FirefoxRevision).stamp')) <_BrowserStampDir>$(ArtifactsBinDir)\ Build - + - - 108.0.1 - https://ftp.mozilla.org/pub/firefox/releases/$(FirefoxRevision)/linux-x86_64/en-US/firefox-$(FirefoxRevision).tar.bz2 + + $(ArtifactsBinDir)firefox\ + firefox + geckodriver + $(ArtifactsBinDir)geckodriver\ + + + https://ftp.mozilla.org/pub/firefox/releases/$(linux_FirefoxRevision)/linux-x86_64/en-US/firefox-$(linux_FirefoxRevision).tar.bz2 + https://github.com/mozilla/geckodriver/releases/download/v$(linux_GeckoDriverRevision)/geckodriver-v$(linux_GeckoDriverRevision)-linux64.tar.gz firefox + geckodriver + $([MSBuild]::NormalizePath($(FirefoxDir), '.install-firefox-$(linux_FirefoxRevision).stamp')) + $([MSBuild]::NormalizePath($(GeckoDriverDir), '.install-geckodriver-$(linux_GeckoDriverRevision).stamp')) + $([MSBuild]::NormalizePath($(FirefoxDir), $(FirefoxDirName), $(FirefoxBinaryName))) + $([MSBuild]::NormalizePath($(GeckoDriverDir), $(GeckoDriverDirName), $(GeckoDriverBinaryName))) + + + + https://ftp.mozilla.org/pub/firefox/releases/$(win_FirefoxRevision)/win64/en-US/Firefox%20Setup%20$(win_FirefoxRevision).exe + https://github.com/mozilla/geckodriver/releases/download/v$(win_GeckoDriverRevision)/geckodriver-v$(win_GeckoDriverRevision)-win64.zip + firefox.exe + geckodriver.exe + $([MSBuild]::NormalizePath($(FirefoxDir), '.install-firefox-$(win_FirefoxRevision).stamp')) + $([MSBuild]::NormalizePath($(GeckoDriverDir), '.install-geckodriver-$(win_GeckoDriverRevision).stamp')) + $([MSBuild]::NormalizePath($(FirefoxDir), $(FirefoxDirName), $(FirefoxBinaryName))) + $([MSBuild]::NormalizePath($(GeckoDriverDir), $(GeckoDriverDirName), $(GeckoDriverBinaryName))) @@ -84,12 +105,6 @@ $([MSBuild]::NormalizePath($(V8Dir), $(V8BinaryName))) - - 108.0.1 - https://ftp.mozilla.org/pub/firefox/releases/$(FirefoxRevision)/linux-x86_64/en-US/firefox-$(FirefoxRevision).tar.bz2 - firefox - - @@ -97,7 +112,7 @@ + Text="No %24(ChromeVersion) set. This can be set in eng/testing/BrowserVersions.props" /> @@ -125,7 +140,7 @@ + Text="No %24(ChromeVersion) set. This can be set in eng/testing/BrowserVersions.props" /> @@ -180,7 +195,7 @@ export __SCRIPT_DIR=%24( cd -- "%24( dirname -- "%24{BASH_SOURCE[0]}" )" &> + Condition="!Exists($(FirefoxStampFile)) and '$(InstallFirefoxForTests)' == 'true'"> <_StampFile Include="$(_BrowserStampDir).install-firefox*.stamp" /> @@ -188,21 +203,51 @@ export __SCRIPT_DIR=%24( cd -- "%24( dirname -- "%24{BASH_SOURCE[0]}" )" &> + + - - - - - <_FirefoxBinaryPath>$([MSBuild]::NormalizePath($(FirefoxDir), $(FirefoxBinaryName))) - + + + + - + - + + + + + <_StampFile Include="$(_BrowserStampDir).install-geckodriver*.stamp" /> + + + + + + + + + + + + + + + + + + + + + diff --git a/global.json b/global.json index b3d764e6c152..5522bd311383 100644 --- a/global.json +++ b/global.json @@ -1,18 +1,18 @@ { "sdk": { - "version": "9.0.100-preview.1.24101.2", + "version": "9.0.100-preview.3.24204.13", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "9.0.100-preview.1.24101.2" + "dotnet": "9.0.100-preview.3.24204.13" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24205.4", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.24205.4", - "Microsoft.DotNet.SharedFramework.Sdk": "9.0.0-beta.24205.4", + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24266.1", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.24266.1", + "Microsoft.DotNet.SharedFramework.Sdk": "9.0.0-beta.24266.1", "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.Build.Traversal": "3.4.0", - "Microsoft.NET.Sdk.IL": "9.0.0-preview.4.24201.1" + "Microsoft.NET.Sdk.IL": "9.0.0-preview.5.24262.2" } } diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt index 68af87ce57e8..d8a255ae2d2b 100644 --- a/src/coreclr/CMakeLists.txt +++ b/src/coreclr/CMakeLists.txt @@ -214,6 +214,7 @@ if(CLR_CMAKE_HOST_UNIX) # warnings and errors to be suppressed. # Suppress these warnings here to avoid breaking the build. add_compile_options($<$:-Wno-null-arithmetic>) + add_compile_options($<$:-Wno-sync-alignment>) add_compile_options($<$:-Wno-conversion-null>) add_compile_options($<$:-Wno-pointer-arith>) diff --git a/src/coreclr/Directory.Build.props b/src/coreclr/Directory.Build.props index 233bfbeacebf..2f86002cccf4 100644 --- a/src/coreclr/Directory.Build.props +++ b/src/coreclr/Directory.Build.props @@ -1,6 +1,6 @@ - true + true $(__BuildType) diff --git a/src/coreclr/System.Private.CoreLib/CompatibilitySuppressions.xml b/src/coreclr/System.Private.CoreLib/CompatibilitySuppressions.xml deleted file mode 100644 index 97b65a274840..000000000000 --- a/src/coreclr/System.Private.CoreLib/CompatibilitySuppressions.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.Write``1(System.String,``0):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.Write``1(System.String,System.Diagnostics.Tracing.EventSourceOptions@,``0@):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.Write``1(System.String,System.Diagnostics.Tracing.EventSourceOptions@,System.Guid@,System.Guid@,``0@):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.WriteEvent(System.Int32,System.Object[]):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.WriteEventCore(System.Int32,System.Int32,System.Diagnostics.Tracing.EventSource.EventData*):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.WriteEventWithRelatedActivityId(System.Int32,System.Guid,System.Object[]):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.WriteEventWithRelatedActivityIdCore(System.Int32,System.Guid*,System.Int32,System.Diagnostics.Tracing.EventSource.EventData*):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - \ No newline at end of file diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 9ef1024c449d..a37abf7a0c11 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -39,6 +39,7 @@ $(TargetArchitecture) arm + AnyCPU true false @@ -59,28 +60,21 @@ - x64 - false $(DefineConstants);TARGET_AMD64 - x86 $(DefineConstants);TARGET_X86 - arm $(DefineConstants);TARGET_ARM - AnyCPU $(DefineConstants);TARGET_ARM64 - AnyCPU $(DefineConstants);TARGET_LOONGARCH64 - AnyCPU $(DefineConstants);TARGET_RISCV64 @@ -198,7 +192,7 @@ - + diff --git a/src/coreclr/System.Private.CoreLib/src/Microsoft/Win32/OAVariantLib.cs b/src/coreclr/System.Private.CoreLib/src/Microsoft/Win32/OAVariantLib.cs index a5fbad6504f3..a51ec6f0132e 100644 --- a/src/coreclr/System.Private.CoreLib/src/Microsoft/Win32/OAVariantLib.cs +++ b/src/coreclr/System.Private.CoreLib/src/Microsoft/Win32/OAVariantLib.cs @@ -13,11 +13,13 @@ ===========================================================*/ using System; +using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace Microsoft.Win32 { @@ -26,48 +28,32 @@ internal static unsafe partial class OAVariantLib #region Constants // Constants for VariantChangeType from OleAuto.h - public const int NoValueProp = 0x01; - public const int AlphaBool = 0x02; - public const int NoUserOverride = 0x04; - public const int CalendarHijri = 0x08; public const int LocalBool = 0x10; - internal static readonly Type?[] ClassTypes = { - typeof(Empty), - typeof(void), - typeof(bool), - typeof(char), - typeof(sbyte), - typeof(byte), - typeof(short), - typeof(ushort), - typeof(int), - typeof(uint), - typeof(long), - typeof(ulong), - typeof(float), - typeof(double), - typeof(string), - typeof(void), - typeof(DateTime), - typeof(TimeSpan), - typeof(object), - typeof(decimal), - null, // Enums - what do we do here? - typeof(Missing), - typeof(DBNull), + private static readonly Dictionary ClassTypes = new Dictionary + { + { typeof(bool), VarEnum.VT_BOOL }, + { typeof(char), VarEnum.VT_I2 }, + { typeof(sbyte), VarEnum.VT_I1 }, + { typeof(byte), VarEnum.VT_UI1 }, + { typeof(short), VarEnum.VT_I2 }, + { typeof(ushort), VarEnum.VT_UI2 }, + { typeof(int), VarEnum.VT_I4 }, + { typeof(uint), VarEnum.VT_UI4 }, + { typeof(long), VarEnum.VT_I8 }, + { typeof(ulong), VarEnum.VT_UI8 }, + { typeof(float), VarEnum.VT_R4 }, + { typeof(double), VarEnum.VT_R8 }, + { typeof(string), VarEnum.VT_BSTR }, + { typeof(DateTime), VarEnum.VT_DATE }, + { typeof(decimal), VarEnum.VT_DECIMAL }, }; - // Keep these numbers in sync w/ the above array. - private const int CV_OBJECT = 0x12; - #endregion #region Internal Methods -#pragma warning disable CS8500 - /** * Changes a Variant from one type to another, calling the OLE * Automation VariantChangeTypeEx routine. Note the legal types here are @@ -75,53 +61,129 @@ internal static unsafe partial class OAVariantLib * Variant and the types that CLR supports explicitly in the * CLR Variant class. */ - internal static Variant ChangeType(Variant source, Type targetClass, short options, CultureInfo culture) + internal static object? ChangeType(object source, Type targetClass, short options, CultureInfo culture) { ArgumentNullException.ThrowIfNull(targetClass); ArgumentNullException.ThrowIfNull(culture); - Variant result = default; - ChangeType( - &result, - &source, - culture.LCID, - targetClass.TypeHandle.Value, - GetCVTypeFromClass(targetClass), - options); - return result; - } + object? result = null; - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "OAVariant_ChangeType")] - private static partial void ChangeType(Variant* result, Variant* source, int lcid, IntPtr typeHandle, int cvType, short flags); + if (Variant.IsSystemDrawingColor(targetClass)) + { + if (source is int || source is uint) + { + uint sourceData = source is int ? (uint)(int)source : (uint)source; + // Int32/UInt32 can be converted to System.Drawing.Color + Variant.ConvertOleColorToSystemColor(ObjectHandleOnStack.Create(ref result), sourceData, targetClass.TypeHandle.Value); + Debug.Assert(result != null); + return result; + } + } -#pragma warning restore CS8500 + if (!ClassTypes.TryGetValue(targetClass, out VarEnum vt)) + { + throw new NotSupportedException(SR.NotSupported_ChangeType); + } - #endregion + ComVariant vOp = ToOAVariant(source); + ComVariant ret = default; + int hr = Interop.OleAut32.VariantChangeTypeEx(&ret, &vOp, culture.LCID, options, (ushort)vt); - #region Private Helpers + using (vOp) + using (ret) + { + if (hr < 0) + { + OAFailed(hr); + } - private static int GetCVTypeFromClass(Type ctype) - { - Debug.Assert(ctype != null); - Debug.Assert(ClassTypes[CV_OBJECT] == typeof(object), "OAVariantLib::ClassTypes[CV_OBJECT] == Object.class"); + result = FromOAVariant(ret); + if (targetClass == typeof(char)) + { + result = (char)(uint)result!; + } + } - // OleAut Binder works better if unrecognized - // types were changed to Object. - int cvtype = CV_OBJECT; + return result; + } - for (int i = 0; i < ClassTypes.Length; i++) + private static void OAFailed(int hr) + { + switch (hr) { - if (ctype.Equals(ClassTypes[i])) - { - cvtype = i; - break; - } + case HResults.COR_E_OUTOFMEMORY: + throw new OutOfMemoryException(); + case HResults.DISP_E_BADVARTYPE: + throw new NotSupportedException(SR.NotSupported_OleAutBadVarType); + case HResults.DISP_E_DIVBYZERO: + throw new DivideByZeroException(); + case HResults.DISP_E_OVERFLOW: + throw new OverflowException(); + case HResults.DISP_E_TYPEMISMATCH: + throw new InvalidCastException(SR.InvalidCast_OATypeMismatch); + case HResults.E_INVALIDARG: + throw new ArgumentException(); + default: + Debug.Fail("Unrecognized HResult - OAVariantLib routine failed in an unexpected way!"); + throw Marshal.GetExceptionForHR(hr); } + } - return cvtype; + private static ComVariant ToOAVariant(object input) + { + return input switch + { + string str => ComVariant.Create(str), + DateTime dateTime => ComVariant.Create(dateTime), + bool b => ComVariant.Create(b), + decimal d => ComVariant.Create(d), + sbyte i1 => ComVariant.Create(i1), + byte u1 => ComVariant.Create(u1), + short i2 => ComVariant.Create(i2), + ushort u2 => ComVariant.Create(u2), + int i4 => ComVariant.Create(i4), + uint u4 => ComVariant.Create(u4), + long i8 => ComVariant.Create(i8), + ulong u8 => ComVariant.Create(u8), + float r4 => ComVariant.Create(r4), + double r8 => ComVariant.Create(r8), + null => default, + Missing => throw new NotSupportedException(SR.NotSupported_ChangeType), + DBNull => ComVariant.Null, + _ => GetComIPFromObjectRef(input) // Convert the object to an IDispatch/IUnknown pointer. + }; + } + + private static ComVariant GetComIPFromObjectRef(object? obj) + { + IntPtr pUnk = GetIUnknownOrIDispatchForObject(ObjectHandleOnStack.Create(ref obj), out bool isIDispatch); + return ComVariant.CreateRaw(isIDispatch ? VarEnum.VT_DISPATCH : VarEnum.VT_UNKNOWN, pUnk); } + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MarshalNative_GetIUnknownOrIDispatchForObject")] + private static partial IntPtr GetIUnknownOrIDispatchForObject(ObjectHandleOnStack o, [MarshalAs(UnmanagedType.Bool)] out bool isIDispatch); + + private static object? FromOAVariant(ComVariant input) => + input.VarType switch + { + VarEnum.VT_BSTR => input.As(), + VarEnum.VT_DATE => input.As(), + VarEnum.VT_BOOL => input.As(), + VarEnum.VT_DECIMAL => input.As(), + VarEnum.VT_I1 => input.As(), + VarEnum.VT_UI1 => input.As(), + VarEnum.VT_I2 => input.As(), + VarEnum.VT_UI2 => input.As(), + VarEnum.VT_I4 or VarEnum.VT_INT => input.As(), + VarEnum.VT_UI4 or VarEnum.VT_UINT => input.As(), + VarEnum.VT_I8 => input.As(), + VarEnum.VT_UI8 => input.As(), + VarEnum.VT_R4 => input.As(), + VarEnum.VT_R8 => input.As(), + _ => throw new NotSupportedException(SR.NotSupported_ChangeType), + }; + #endregion } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs index de7b3021c458..74e073984816 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs @@ -694,7 +694,7 @@ public ArrayInitializeCache(RuntimeType arrayType) // it for type and executes it. // // The "T" will reflect the interface used to invoke the method. The actual runtime "this" will be - // array that is castable to "T[]" (i.e. for primitivs and valuetypes, it will be exactly + // array that is castable to "T[]" (i.e. for primitives and valuetypes, it will be exactly // "T[]" - for orefs, it may be a "U[]" where U derives from T.) //---------------------------------------------------------------------------------------- internal sealed class SZArrayHelper diff --git a/src/coreclr/System.Private.CoreLib/src/System/Enum.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Enum.CoreCLR.cs index 6f578ccad411..cc46e2a75d8b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Enum.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Enum.CoreCLR.cs @@ -14,9 +14,6 @@ public abstract partial class Enum [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Enum_GetValuesAndNames")] private static partial void GetEnumValuesAndNames(QCallTypeHandle enumType, ObjectHandleOnStack values, ObjectHandleOnStack names, Interop.BOOL getNames); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern object InternalBoxEnum(RuntimeType enumType, long value); - [MethodImpl(MethodImplOptions.InternalCall)] private static extern unsafe CorElementType InternalGetCorElementType(MethodTable* pMT); diff --git a/src/coreclr/System.Private.CoreLib/src/System/OleAutBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/OleAutBinder.cs index d1072ff86ec8..32a69bb155f1 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/OleAutBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/OleAutBinder.cs @@ -18,7 +18,6 @@ internal sealed class OleAutBinder : DefaultBinder // This binder uses OLEAUT to change the type of the variant. public override object ChangeType(object value, Type type, CultureInfo? cultureInfo) { - Variant myValue = new Variant(value); cultureInfo ??= CultureInfo.CurrentCulture; #if DISPLAY_DEBUG_INFO @@ -62,7 +61,7 @@ public override object ChangeType(object value, Type type, CultureInfo? cultureI #endif // Specify the LocalBool flag to have BOOL values converted to local language rather // than 0 or -1. - object RetObj = OAVariantLib.ChangeType(myValue, type, OAVariantLib.LocalBool, cultureInfo).ToObject()!; + object RetObj = OAVariantLib.ChangeType(value, type, OAVariantLib.LocalBool, cultureInfo)!; #if DISPLAY_DEBUG_INFO Console.WriteLine("Object returned from ChangeType is of type: " + RetObj.GetType().Name); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdConstant.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdConstant.cs index 498b6adf52e4..1ef9ed2e3317 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdConstant.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdConstant.cs @@ -72,7 +72,7 @@ internal static class MdConstant #endregion } - return RuntimeType.CreateEnum(fieldType, defaultValue); + return Enum.ToObject(fieldType, defaultValue); } else if (fieldType == typeof(DateTime)) { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs index d1944cbbf77c..c95e1630a04a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs @@ -171,39 +171,42 @@ public static bool IsTokenOfType(int token, params MetadataTokenType[] types) public override string ToString() => string.Create(CultureInfo.InvariantCulture, stackalloc char[64], $"0x{Value:x8}"); } - internal unsafe struct MetadataEnumResult + internal ref struct MetadataEnumResult { - // Keep the definition in sync with vm\ManagedMdImport.hpp - private int[] largeResult; - private int length; - private fixed int smallResult[16]; + internal int _length; + + internal const int SmallIntArrayLength = 16; + + [InlineArray(SmallIntArrayLength)] + internal struct SmallIntArray + { + public int e; + } + internal SmallIntArray _smallResult; + internal int[]? _largeResult; - public int Length => length; + public int Length => _length; public int this[int index] { get { Debug.Assert(0 <= index && index < Length); - if (largeResult != null) - return largeResult[index]; + if (_largeResult != null) + return _largeResult[index]; - fixed (int* p = smallResult) - return p[index]; + return _smallResult[index]; } } } #pragma warning disable CA1066 // IEquatable interface implementation isn't used - internal readonly struct MetadataImport + internal readonly partial struct MetadataImport #pragma warning restore CA1067 { private readonly IntPtr m_metadataImport2; - private readonly object? m_keepalive; #region Override methods from Object - internal static readonly MetadataImport EmptyImport = new MetadataImport((IntPtr)0, null); - public override int GetHashCode() { return HashCode.Combine(m_metadataImport2); @@ -225,47 +228,104 @@ private bool Equals(MetadataImport import) #region Static Members [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetMarshalAs(IntPtr pNativeType, int cNativeType, out int unmanagedType, out int safeArraySubType, out string? safeArrayUserDefinedSubType, - out int arraySubType, out int sizeParamIndex, out int sizeConst, out string? marshalType, out string? marshalCookie, + private static extern unsafe bool GetMarshalAs( + IntPtr pNativeType, + int cNativeType, + out int unmanagedType, + out int safeArraySubType, + out byte* safeArrayUserDefinedSubType, + out int arraySubType, + out int sizeParamIndex, + out int sizeConst, + out byte* marshalType, + out byte* marshalCookie, out int iidParamIndex); - internal static void GetMarshalAs(ConstArray nativeType, - out UnmanagedType unmanagedType, out VarEnum safeArraySubType, out string? safeArrayUserDefinedSubType, - out UnmanagedType arraySubType, out int sizeParamIndex, out int sizeConst, out string? marshalType, out string? marshalCookie, - out int iidParamIndex) - { - _GetMarshalAs(nativeType.Signature, (int)nativeType.Length, - out int _unmanagedType, out int _safeArraySubType, out safeArrayUserDefinedSubType, - out int _arraySubType, out sizeParamIndex, out sizeConst, out marshalType, out marshalCookie, - out iidParamIndex); - unmanagedType = (UnmanagedType)_unmanagedType; - safeArraySubType = (VarEnum)_safeArraySubType; - arraySubType = (UnmanagedType)_arraySubType; - } - #endregion + internal static unsafe MarshalAsAttribute GetMarshalAs(ConstArray nativeType, RuntimeModule scope) + { + if (!GetMarshalAs( + nativeType.Signature, + nativeType.Length, + out int unmanagedTypeRaw, + out int safeArraySubTypeRaw, + out byte* safeArrayUserDefinedSubTypeRaw, + out int arraySubTypeRaw, + out int sizeParamIndex, + out int sizeConst, + out byte* marshalTypeRaw, + out byte* marshalCookieRaw, + out int iidParamIndex)) + { + throw new BadImageFormatException(); + } - #region Internal Static Members - internal static void ThrowError(int hResult) - { - throw new MetadataException(hResult); + string? safeArrayUserDefinedTypeName = safeArrayUserDefinedSubTypeRaw == null + ? null + : Text.Encoding.UTF8.GetString(MemoryMarshal.CreateReadOnlySpanFromNullTerminated(safeArrayUserDefinedSubTypeRaw)); + string? marshalTypeName = marshalTypeRaw == null + ? null + : Text.Encoding.UTF8.GetString(MemoryMarshal.CreateReadOnlySpanFromNullTerminated(marshalTypeRaw)); + string? marshalCookie = marshalCookieRaw == null + ? null + : Text.Encoding.UTF8.GetString(MemoryMarshal.CreateReadOnlySpanFromNullTerminated(marshalCookieRaw)); + + RuntimeType? safeArrayUserDefinedType = string.IsNullOrEmpty(safeArrayUserDefinedTypeName) ? null : + TypeNameResolver.GetTypeReferencedByCustomAttribute(safeArrayUserDefinedTypeName, scope); + RuntimeType? marshalTypeRef = null; + + try + { + marshalTypeRef = marshalTypeName is null ? null : TypeNameResolver.GetTypeReferencedByCustomAttribute(marshalTypeName, scope); + } + catch (TypeLoadException) + { + // The user may have supplied a bad type name string causing this TypeLoadException + // Regardless, we return the bad type name + Debug.Assert(marshalTypeName is not null); + } + + MarshalAsAttribute attribute = new MarshalAsAttribute((UnmanagedType)unmanagedTypeRaw); + + attribute.SafeArraySubType = (VarEnum)safeArraySubTypeRaw; + attribute.SafeArrayUserDefinedSubType = safeArrayUserDefinedType; + attribute.IidParameterIndex = iidParamIndex; + attribute.ArraySubType = (UnmanagedType)arraySubTypeRaw; + attribute.SizeParamIndex = (short)sizeParamIndex; + attribute.SizeConst = sizeConst; + attribute.MarshalType = marshalTypeName; + attribute.MarshalTypeRef = marshalTypeRef; + attribute.MarshalCookie = marshalCookie; + + return attribute; } #endregion #region Constructor - internal MetadataImport(IntPtr metadataImport2, object? keepalive) + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern unsafe IntPtr GetMetadataImport(RuntimeModule module); + + internal MetadataImport(RuntimeModule module) { - m_metadataImport2 = metadataImport2; - m_keepalive = keepalive; + ArgumentNullException.ThrowIfNull(module); + + // The MetadataImport instance needs to be acquired in this manner + // since the instance can be replaced during HotReload and EnC scenarios. + m_metadataImport2 = GetMetadataImport(module); } #endregion - #region FCalls - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _Enum(IntPtr scope, int type, int parent, out MetadataEnumResult result); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MetadataImport_Enum")] + private static unsafe partial void Enum(IntPtr scope, int type, int parent, ref int length, int* shortResult, ObjectHandleOnStack longResult); - public void Enum(MetadataTokenType type, int parent, out MetadataEnumResult result) + public unsafe void Enum(MetadataTokenType type, int parent, out MetadataEnumResult result) { - _Enum(m_metadataImport2, (int)type, parent, out result); + result = default; + int length = MetadataEnumResult.SmallIntArrayLength; + fixed (int* p = &result._smallResult.e) + { + Enum(m_metadataImport2, (int)type, parent, ref length, p, ObjectHandleOnStack.Create(ref result._largeResult)); + } + result._length = length; } public void EnumNestedTypes(int mdTypeDef, out MetadataEnumResult result) @@ -298,117 +358,131 @@ public void EnumEvents(int mdTypeDef, out MetadataEnumResult result) Enum(MetadataTokenType.Event, mdTypeDef, out result); } + private static unsafe string? ConvertMetadataStringPermitInvalidContent(char* stringMetadataEncoding, int length) + { + Debug.Assert(stringMetadataEncoding != null); + // Metadata encoding is always UTF-16LE, but user strings can be leveraged to encode invalid surrogates. + // This means we rely on the string's constructor rather than the stricter Encoding.Unicode API. + return new string(stringMetadataEncoding, 0, length); + } + + #region FCalls [MethodImpl(MethodImplOptions.InternalCall)] - private static extern string? _GetDefaultValue(IntPtr scope, int mdToken, out long value, out int length, out int corElementType); - public string? GetDefaultValue(int mdToken, out long value, out int length, out CorElementType corElementType) + private static extern unsafe int GetDefaultValue( + IntPtr scope, + int mdToken, + out long value, + out char* stringMetadataEncoding, + out int length, + out int corElementType); + + public unsafe string? GetDefaultValue(int mdToken, out long value, out int length, out CorElementType corElementType) { - string? stringVal = _GetDefaultValue(m_metadataImport2, mdToken, out value, out length, out int _corElementType); - corElementType = (CorElementType)_corElementType; - return stringVal; + ThrowBadImageExceptionForHR(GetDefaultValue(m_metadataImport2, mdToken, out value, out char* stringMetadataEncoding, out length, out int corElementTypeRaw)); + + corElementType = (CorElementType)corElementTypeRaw; + + if (corElementType is CorElementType.ELEMENT_TYPE_STRING + && stringMetadataEncoding != null) + { + return ConvertMetadataStringPermitInvalidContent(stringMetadataEncoding, length); + } + + return null; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern unsafe void _GetUserString(IntPtr scope, int mdToken, void** name, out int length); + private static extern unsafe int GetUserString(IntPtr scope, int mdToken, out char* stringMetadataEncoding, out int length); + public unsafe string? GetUserString(int mdToken) { - void* name; - _GetUserString(m_metadataImport2, mdToken, &name, out int length); + ThrowBadImageExceptionForHR(GetUserString(m_metadataImport2, mdToken, out char* stringMetadataEncoding, out int length)); - return name != null ? - new string((char*)name, 0, length) : + return stringMetadataEncoding != null ? + ConvertMetadataStringPermitInvalidContent(stringMetadataEncoding, length) : null; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern unsafe void _GetName(IntPtr scope, int mdToken, void** name); + private static extern unsafe int GetName(IntPtr scope, int mdToken, out byte* name); + public unsafe MdUtf8String GetName(int mdToken) { - void* name; - _GetName(m_metadataImport2, mdToken, &name); - + ThrowBadImageExceptionForHR(GetName(m_metadataImport2, mdToken, out byte* name)); return new MdUtf8String(name); } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern unsafe void _GetNamespace(IntPtr scope, int mdToken, void** namesp); + private static extern unsafe int GetNamespace(IntPtr scope, int mdToken, out byte* namesp); + public unsafe MdUtf8String GetNamespace(int mdToken) { - void* namesp; - _GetNamespace(m_metadataImport2, mdToken, &namesp); - + ThrowBadImageExceptionForHR(GetNamespace(m_metadataImport2, mdToken, out byte* namesp)); return new MdUtf8String(namesp); } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern unsafe void _GetEventProps(IntPtr scope, int mdToken, void** name, out int eventAttributes); + private static extern unsafe int GetEventProps(IntPtr scope, int mdToken, out void* name, out int eventAttributes); + public unsafe void GetEventProps(int mdToken, out void* name, out EventAttributes eventAttributes) { - void* _name; - _GetEventProps(m_metadataImport2, mdToken, &_name, out int _eventAttributes); - name = _name; - eventAttributes = (EventAttributes)_eventAttributes; + ThrowBadImageExceptionForHR(GetEventProps(m_metadataImport2, mdToken, out name, out int eventAttributesRaw)); + eventAttributes = (EventAttributes)eventAttributesRaw; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetFieldDefProps(IntPtr scope, int mdToken, out int fieldAttributes); + private static extern int GetFieldDefProps(IntPtr scope, int mdToken, out int fieldAttributes); + public void GetFieldDefProps(int mdToken, out FieldAttributes fieldAttributes) { - _GetFieldDefProps(m_metadataImport2, mdToken, out int _fieldAttributes); - fieldAttributes = (FieldAttributes)_fieldAttributes; + ThrowBadImageExceptionForHR(GetFieldDefProps(m_metadataImport2, mdToken, out int fieldAttributesRaw)); + fieldAttributes = (FieldAttributes)fieldAttributesRaw; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern unsafe void _GetPropertyProps(IntPtr scope, - int mdToken, void** name, out int propertyAttributes, out ConstArray signature); + private static extern unsafe int GetPropertyProps(IntPtr scope, int mdToken, out void* name, out int propertyAttributes, out ConstArray signature); + public unsafe void GetPropertyProps(int mdToken, out void* name, out PropertyAttributes propertyAttributes, out ConstArray signature) { - void* _name; - _GetPropertyProps(m_metadataImport2, mdToken, &_name, out int _propertyAttributes, out signature); - name = _name; - propertyAttributes = (PropertyAttributes)_propertyAttributes; + ThrowBadImageExceptionForHR(GetPropertyProps(m_metadataImport2, mdToken, out name, out int propertyAttributesRaw, out signature)); + propertyAttributes = (PropertyAttributes)propertyAttributesRaw; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetParentToken(IntPtr scope, - int mdToken, out int tkParent); + private static extern int GetParentToken(IntPtr scope, int mdToken, out int tkParent); + public int GetParentToken(int tkToken) { - _GetParentToken(m_metadataImport2, tkToken, out int tkParent); + ThrowBadImageExceptionForHR(GetParentToken(m_metadataImport2, tkToken, out int tkParent)); return tkParent; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetParamDefProps(IntPtr scope, - int parameterToken, out int sequence, out int attributes); + private static extern int GetParamDefProps(IntPtr scope, int parameterToken, out int sequence, out int attributes); + public void GetParamDefProps(int parameterToken, out int sequence, out ParameterAttributes attributes) { - - _GetParamDefProps(m_metadataImport2, parameterToken, out sequence, out int _attributes); - - attributes = (ParameterAttributes)_attributes; + ThrowBadImageExceptionForHR(GetParamDefProps(m_metadataImport2, parameterToken, out sequence, out int attributesRaw)); + attributes = (ParameterAttributes)attributesRaw; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetGenericParamProps(IntPtr scope, - int genericParameter, - out int flags); + private static extern int GetGenericParamProps(IntPtr scope, int genericParameter, out int flags); public void GetGenericParamProps( int genericParameter, out GenericParameterAttributes attributes) { - _GetGenericParamProps(m_metadataImport2, genericParameter, out int _attributes); - attributes = (GenericParameterAttributes)_attributes; + ThrowBadImageExceptionForHR(GetGenericParamProps(m_metadataImport2, genericParameter, out int attributesRaw)); + attributes = (GenericParameterAttributes)attributesRaw; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetScopeProps(IntPtr scope, - out Guid mvid); + private static extern int GetScopeProps(IntPtr scope, out Guid mvid); - public void GetScopeProps( - out Guid mvid) + public void GetScopeProps(out Guid mvid) { - _GetScopeProps(m_metadataImport2, out mvid); + ThrowBadImageExceptionForHR(GetScopeProps(m_metadataImport2, out mvid)); } public ConstArray GetMethodSignature(MetadataToken token) @@ -420,47 +494,36 @@ public ConstArray GetMethodSignature(MetadataToken token) } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetSigOfMethodDef(IntPtr scope, - int methodToken, - ref ConstArray signature); + private static extern int GetSigOfMethodDef(IntPtr scope, int methodToken, ref ConstArray signature); public ConstArray GetSigOfMethodDef(int methodToken) { ConstArray signature = default; - - _GetSigOfMethodDef(m_metadataImport2, methodToken, ref signature); - + ThrowBadImageExceptionForHR(GetSigOfMethodDef(m_metadataImport2, methodToken, ref signature)); return signature; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetSignatureFromToken(IntPtr scope, - int methodToken, - ref ConstArray signature); + private static extern int GetSignatureFromToken(IntPtr scope, int methodToken, ref ConstArray signature); public ConstArray GetSignatureFromToken(int token) { ConstArray signature = default; - - _GetSignatureFromToken(m_metadataImport2, token, ref signature); - + ThrowBadImageExceptionForHR(GetSignatureFromToken(m_metadataImport2, token, ref signature)); return signature; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetMemberRefProps(IntPtr scope, - int memberTokenRef, - out ConstArray signature); + private static extern int GetMemberRefProps(IntPtr scope, int memberTokenRef, out ConstArray signature); public ConstArray GetMemberRefProps(int memberTokenRef) { - _GetMemberRefProps(m_metadataImport2, memberTokenRef, out ConstArray signature); - + ThrowBadImageExceptionForHR(GetMemberRefProps(m_metadataImport2, memberTokenRef, out ConstArray signature)); return signature; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetCustomAttributeProps(IntPtr scope, + private static extern int GetCustomAttributeProps(IntPtr scope, int customAttributeToken, out int constructorToken, out ConstArray signature); @@ -470,66 +533,62 @@ public void GetCustomAttributeProps( out int constructorToken, out ConstArray signature) { - _GetCustomAttributeProps(m_metadataImport2, customAttributeToken, - out constructorToken, out signature); + ThrowBadImageExceptionForHR(GetCustomAttributeProps(m_metadataImport2, customAttributeToken, out constructorToken, out signature)); } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetClassLayout(IntPtr scope, - int typeTokenDef, out int packSize, out int classSize); + private static extern int GetClassLayout(IntPtr scope, int typeTokenDef, out int packSize, out int classSize); + public void GetClassLayout( int typeTokenDef, out int packSize, out int classSize) { - _GetClassLayout(m_metadataImport2, typeTokenDef, out packSize, out classSize); + ThrowBadImageExceptionForHR(GetClassLayout(m_metadataImport2, typeTokenDef, out packSize, out classSize)); } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool _GetFieldOffset(IntPtr scope, - int typeTokenDef, int fieldTokenDef, out int offset); + private static extern int GetFieldOffset(IntPtr scope, int typeTokenDef, int fieldTokenDef, out int offset, out bool found); + public bool GetFieldOffset( int typeTokenDef, int fieldTokenDef, out int offset) { - return _GetFieldOffset(m_metadataImport2, typeTokenDef, fieldTokenDef, out offset); + int hr = GetFieldOffset(m_metadataImport2, typeTokenDef, fieldTokenDef, out offset, out bool found); + if (!found && hr < 0) + { + throw new BadImageFormatException(); + } + return found; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetSigOfFieldDef(IntPtr scope, - int fieldToken, - ref ConstArray fieldMarshal); + private static extern int GetSigOfFieldDef(IntPtr scope, int fieldToken, ref ConstArray fieldMarshal); public ConstArray GetSigOfFieldDef(int fieldToken) { - ConstArray fieldMarshal = default; - - _GetSigOfFieldDef(m_metadataImport2, fieldToken, ref fieldMarshal); - - return fieldMarshal; + ConstArray sig = default; + ThrowBadImageExceptionForHR(GetSigOfFieldDef(m_metadataImport2, fieldToken, ref sig)); + return sig; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetFieldMarshal(IntPtr scope, - int fieldToken, - ref ConstArray fieldMarshal); + private static extern int GetFieldMarshal(IntPtr scope, int fieldToken, ref ConstArray fieldMarshal); public ConstArray GetFieldMarshal(int fieldToken) { ConstArray fieldMarshal = default; - - _GetFieldMarshal(m_metadataImport2, fieldToken, ref fieldMarshal); - + ThrowBadImageExceptionForHR(GetFieldMarshal(m_metadataImport2, fieldToken, ref fieldMarshal)); return fieldMarshal; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern unsafe void _GetPInvokeMap(IntPtr scope, + private static extern unsafe int GetPInvokeMap(IntPtr scope, int token, out int attributes, - void** importName, - void** importDll); + out byte* importName, + out byte* importDll); public unsafe void GetPInvokeMap( int token, @@ -537,28 +596,28 @@ public unsafe void GetPInvokeMap( out string importName, out string importDll) { - void* _importName, _importDll; - _GetPInvokeMap(m_metadataImport2, token, out int _attributes, &_importName, &_importDll); - importName = new MdUtf8String(_importName).ToString(); - importDll = new MdUtf8String(_importDll).ToString(); + ThrowBadImageExceptionForHR(GetPInvokeMap(m_metadataImport2, token, out int attributesRaw, out byte* importNameRaw, out byte* importDllRaw)); - attributes = (PInvokeAttributes)_attributes; + importName = Text.Encoding.UTF8.GetString(MemoryMarshal.CreateReadOnlySpanFromNullTerminated(importNameRaw)); + importDll = Text.Encoding.UTF8.GetString(MemoryMarshal.CreateReadOnlySpanFromNullTerminated(importDllRaw)); + attributes = (PInvokeAttributes)attributesRaw; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool _IsValidToken(IntPtr scope, int token); + private static extern bool IsValidToken(IntPtr scope, int token); + public bool IsValidToken(int token) { - return _IsValidToken(m_metadataImport2, token); + return IsValidToken(m_metadataImport2, token); } #endregion - } - - internal sealed class MetadataException : Exception - { - private readonly int m_hr; - internal MetadataException(int hr) { m_hr = hr; } - public override string ToString() => $"{nameof(MetadataException)} HResult = {m_hr:x}."; + private static void ThrowBadImageExceptionForHR(int hr) + { + if (hr < 0) + { + throw new BadImageFormatException(); + } + } } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index 53f2690948df..3af48057a870 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -249,7 +249,7 @@ private static partial void GetTypeCoreIgnoreCase(QCallAssembly assembly, { ArgumentException.ThrowIfNullOrEmpty(name); - return TypeNameParser.GetType(name, topLevelAssembly: this, + return TypeNameResolver.GetType(name, topLevelAssembly: this, throwOnError: throwOnError, ignoreCase: ignoreCase); } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs index dd0b5cf897f4..e00b0b1854a3 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs @@ -215,6 +215,7 @@ internal static CustomAttributeRecord[] GetCustomAttributeRecords(RuntimeModule scope.GetCustomAttributeProps(tkCustomAttributeTokens[i], out records[i].tkCtor.Value, out records[i].blob); } + GC.KeepAlive(module); return records; } @@ -250,13 +251,13 @@ internal static CustomAttributeTypedArgument Filter(IList a private RuntimeCustomAttributeData(RuntimeModule scope, MetadataToken caCtorToken, in ConstArray blob) { m_scope = scope; - m_ctor = (RuntimeConstructorInfo)RuntimeType.GetMethodBase(scope, caCtorToken)!; + m_ctor = (RuntimeConstructorInfo)RuntimeType.GetMethodBase(m_scope, caCtorToken)!; if (m_ctor!.DeclaringType!.IsGenericType) { - MetadataImport metadataScope = scope.MetadataImport; - Type attributeType = scope.ResolveType(metadataScope.GetParentToken(caCtorToken), null, null)!; - m_ctor = (RuntimeConstructorInfo)scope.ResolveMethod(caCtorToken, attributeType.GenericTypeArguments, null)!.MethodHandle.GetMethodInfo(); + MetadataImport metadataScope = m_scope.MetadataImport; + Type attributeType = m_scope.ResolveType(metadataScope.GetParentToken(caCtorToken), null, null)!; + m_ctor = (RuntimeConstructorInfo)m_scope.ResolveMethod(caCtorToken, attributeType.GenericTypeArguments, null)!.MethodHandle.GetMethodInfo(); } ReadOnlySpan parameters = m_ctor.GetParametersAsSpan(); @@ -542,7 +543,7 @@ private static object EncodedValueToRawValue(PrimitiveValue val, CustomAttribute } private static RuntimeType ResolveType(RuntimeModule scope, string typeName) { - RuntimeType type = TypeNameParser.GetTypeReferencedByCustomAttribute(typeName, scope); + RuntimeType type = TypeNameResolver.GetTypeReferencedByCustomAttribute(typeName, scope); Debug.Assert(type is not null); return type; } @@ -898,7 +899,7 @@ private static CustomAttributeType ParseCustomAttributeType(ref CustomAttributeD throw new BadImageFormatException(); } - enumType = TypeNameParser.GetTypeReferencedByCustomAttribute(enumTypeMaybe, module); + enumType = TypeNameResolver.GetTypeReferencedByCustomAttribute(enumTypeMaybe, module); if (!enumType.IsEnum) { throw new BadImageFormatException(); @@ -1466,6 +1467,7 @@ private static bool IsCustomAttributeDefined( } } } + GC.KeepAlive(decoratedModule); return false; } @@ -1615,6 +1617,7 @@ private static void AddCustomAttributes( attributes.Add(attribute); } + GC.KeepAlive(decoratedModule); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", @@ -2194,10 +2197,11 @@ internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType? caType) if ((method.Attributes & MethodAttributes.PinvokeImpl) == 0) return null; - MetadataImport scope = ModuleHandle.GetMetadataImport(method.Module.ModuleHandle.GetRuntimeModule()); + RuntimeModule module = method.Module.ModuleHandle.GetRuntimeModule(); + MetadataImport scope = module.MetadataImport; int token = method.MetadataToken; - scope.GetPInvokeMap(token, out PInvokeAttributes flags, out string entryPoint, out string dllName); + GC.KeepAlive(module); CharSet charSet = CharSet.None; @@ -2252,51 +2256,25 @@ internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType? caType) private static MarshalAsAttribute? GetMarshalAsCustomAttribute(int token, RuntimeModule scope) { - ConstArray nativeType = ModuleHandle.GetMetadataImport(scope).GetFieldMarshal(token); + ConstArray nativeType = scope.MetadataImport.GetFieldMarshal(token); if (nativeType.Length == 0) return null; - MetadataImport.GetMarshalAs(nativeType, - out UnmanagedType unmanagedType, out VarEnum safeArraySubType, out string? safeArrayUserDefinedTypeName, out UnmanagedType arraySubType, out int sizeParamIndex, - out int sizeConst, out string? marshalTypeName, out string? marshalCookie, out int iidParamIndex); - - RuntimeType? safeArrayUserDefinedType = string.IsNullOrEmpty(safeArrayUserDefinedTypeName) ? null : - TypeNameParser.GetTypeReferencedByCustomAttribute(safeArrayUserDefinedTypeName, scope); - RuntimeType? marshalTypeRef = null; - - try - { - marshalTypeRef = marshalTypeName is null ? null : TypeNameParser.GetTypeReferencedByCustomAttribute(marshalTypeName, scope); - } - catch (TypeLoadException) - { - // The user may have supplied a bad type name string causing this TypeLoadException - // Regardless, we return the bad type name - Debug.Assert(marshalTypeName is not null); - } - - MarshalAsAttribute attribute = new MarshalAsAttribute(unmanagedType); - - attribute.SafeArraySubType = safeArraySubType; - attribute.SafeArrayUserDefinedSubType = safeArrayUserDefinedType; - attribute.IidParameterIndex = iidParamIndex; - attribute.ArraySubType = arraySubType; - attribute.SizeParamIndex = (short)sizeParamIndex; - attribute.SizeConst = sizeConst; - attribute.MarshalType = marshalTypeName; - attribute.MarshalTypeRef = marshalTypeRef; - attribute.MarshalCookie = marshalCookie; - - return attribute; + return MetadataImport.GetMarshalAs(nativeType, scope); } private static FieldOffsetAttribute? GetFieldOffsetCustomAttribute(RuntimeFieldInfo field) { - if (field.DeclaringType is not null && - field.GetRuntimeModule().MetadataImport.GetFieldOffset(field.DeclaringType.MetadataToken, field.MetadataToken, out int fieldOffset)) - return new FieldOffsetAttribute(fieldOffset); - + if (field.DeclaringType is not null) + { + RuntimeModule module = field.GetRuntimeModule(); + if (module.MetadataImport.GetFieldOffset(field.DeclaringType.MetadataToken, field.MetadataToken, out int fieldOffset)) + { + return new FieldOffsetAttribute(fieldOffset); + } + GC.KeepAlive(module); + } return null; } @@ -2322,7 +2300,9 @@ internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType? caType) case TypeAttributes.UnicodeClass: charSet = CharSet.Unicode; break; default: Debug.Fail("Unreachable code"); break; } - type.GetRuntimeModule().MetadataImport.GetClassLayout(type.MetadataToken, out int pack, out int size); + RuntimeModule module = type.GetRuntimeModule(); + module.MetadataImport.GetClassLayout(type.MetadataToken, out int pack, out int size); + GC.KeepAlive(module); StructLayoutAttribute attribute = new StructLayoutAttribute(layoutKind); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs index 8e7e4a05c73d..43760e17b4d9 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs @@ -202,7 +202,7 @@ public override byte[] ResolveSignature(int metadataToken) if (declaringType.IsGenericType || declaringType.IsArray) { - int tkDeclaringType = ModuleHandle.GetMetadataImport(this).GetParentToken(metadataToken); + int tkDeclaringType = MetadataImport.GetParentToken(metadataToken); declaringType = (RuntimeType)ResolveType(tkDeclaringType, genericTypeArguments, genericMethodArguments); } @@ -353,7 +353,7 @@ public override void GetPEKind(out PortableExecutableKinds peKind, out ImageFile #region Internal Members internal RuntimeType RuntimeType => m_runtimeType ??= ModuleHandle.GetModuleType(this); - internal MetadataImport MetadataImport => ModuleHandle.GetMetadataImport(this); + internal MetadataImport MetadataImport => new MetadataImport(this); #endregion #region ICustomAttributeProvider Members @@ -403,7 +403,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont { ArgumentException.ThrowIfNullOrEmpty(className); - return TypeNameParser.GetType(className, topLevelAssembly: Assembly, + return TypeNameResolver.GetType(className, topLevelAssembly: Assembly, throwOnError: throwOnError, ignoreCase: ignoreCase); } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs index 5af77b790f49..24dd89c21131 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs @@ -29,6 +29,11 @@ internal static ParameterInfo GetReturnParameter(IRuntimeMethodInfo method, Memb private static ParameterInfo[] GetParameters( IRuntimeMethodInfo methodHandle, MemberInfo member, Signature sig, out ParameterInfo? returnParameter, bool fetchReturnParameter) { + // The lifetime rules for MetadataImport expect these two objects to be the same instance. + // See the lifetime of MetadataImport, acquired through IRuntimeMethodInfo, but extended + // through the MemberInfo instance. + Debug.Assert(ReferenceEquals(methodHandle, member)); + returnParameter = null; int sigArgCount = sig.Arguments.Length; ParameterInfo[] args = @@ -43,7 +48,7 @@ private static ParameterInfo[] GetParameters( // are generated on the fly by the runtime. if (!MdToken.IsNullToken(tkMethodDef)) { - MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(RuntimeMethodHandle.GetDeclaringType(methodHandle)); + MetadataImport scope = RuntimeMethodHandle.GetDeclaringType(methodHandle).GetRuntimeModule().MetadataImport; scope.EnumParams(tkMethodDef, out MetadataEnumResult tkParamDefs); @@ -73,7 +78,7 @@ private static ParameterInfo[] GetParameters( } else if (!fetchReturnParameter && position >= 0) { - // position beyong sigArgCount? + // position beyond sigArgCount? if (position >= sigArgCount) throw new BadImageFormatException(SR.BadImageFormat_ParameterSignatureMismatch); @@ -86,7 +91,7 @@ private static ParameterInfo[] GetParameters( // Fill in empty ParameterInfos for those without tokens if (fetchReturnParameter) { - returnParameter ??= new RuntimeParameterInfo(sig, MetadataImport.EmptyImport, 0, -1, (ParameterAttributes)0, member); + returnParameter ??= new RuntimeParameterInfo(sig, default, 0, -1, (ParameterAttributes)0, member); } else { @@ -97,7 +102,7 @@ private static ParameterInfo[] GetParameters( if (args[i] != null) continue; - args[i] = new RuntimeParameterInfo(sig, MetadataImport.EmptyImport, 0, i, (ParameterAttributes)0, member); + args[i] = new RuntimeParameterInfo(sig, default, 0, i, (ParameterAttributes)0, member); } } } @@ -165,7 +170,7 @@ private RuntimeParameterInfo(RuntimeParameterInfo accessor, MemberInfo member) PositionImpl = accessor.Position; AttrsImpl = accessor.Attributes; - // Strictly speeking, property's don't contain parameter tokens + // Strictly speaking, properties don't contain parameter tokens // However we need this to make ca's work... oh well... m_tkParamDef = MdToken.IsNullToken(accessor.MetadataToken) ? (int)MetadataTokenType.ParamDef : accessor.MetadataToken; m_scope = accessor.m_scope; @@ -176,7 +181,7 @@ private RuntimeParameterInfo( int position, ParameterAttributes attributes, MemberInfo member) { Debug.Assert(member != null); - Debug.Assert(MdToken.IsNullToken(tkParamDef) == scope.Equals(MetadataImport.EmptyImport)); + Debug.Assert(MdToken.IsNullToken(tkParamDef) == scope.Equals((MetadataImport)default)); Debug.Assert(MdToken.IsNullToken(tkParamDef) || MdToken.IsTokenOfType(tkParamDef, MetadataTokenType.ParamDef)); PositionImpl = position; @@ -201,7 +206,7 @@ internal RuntimeParameterInfo(MethodInfo owner, string? name, Type parameterType PositionImpl = position; AttrsImpl = ParameterAttributes.None; m_tkParamDef = (int)MetadataTokenType.ParamDef; - m_scope = MetadataImport.EmptyImport; + m_scope = default; } #endregion @@ -239,6 +244,7 @@ public override string? Name if (!MdToken.IsNullToken(m_tkParamDef)) { string name = m_scope.GetName(m_tkParamDef).ToString(); + GC.KeepAlive(this); NameImpl = name; } @@ -339,6 +345,7 @@ private bool TryGetDefaultValueInternal(bool raw, out object? defaultValue) #region Look for a default value in metadata // This will return DBNull.Value if no constant value is defined on m_tkParamDef in the metadata. defaultValue = MdConstant.GetValue(m_scope, m_tkParamDef, ParameterType.TypeHandle, raw); + GC.KeepAlive(this); // If default value is not specified in metadata, look for it in custom attributes if (defaultValue == DBNull.Value) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs index 933e05d0bf78..d49ac821e684 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs @@ -35,7 +35,8 @@ internal RuntimePropertyInfo( Debug.Assert(reflectedTypeCache != null); Debug.Assert(!reflectedTypeCache.IsGlobal); - MetadataImport scope = declaredType.GetRuntimeModule().MetadataImport; + RuntimeModule module = declaredType.GetRuntimeModule(); + MetadataImport scope = module.MetadataImport; m_token = tkProperty; m_reflectedTypeCache = reflectedTypeCache; @@ -47,6 +48,7 @@ internal RuntimePropertyInfo( out _, out _, out _, out m_getterMethod, out m_setterMethod, out m_otherMethod, out isPrivate, out m_bindingFlags); + GC.KeepAlive(module); } #endregion @@ -65,9 +67,9 @@ internal Signature Signature { if (m_signature == null) { - GetRuntimeModule().MetadataImport.GetPropertyProps( m_token, out _, out _, out ConstArray sig); + GC.KeepAlive(this); m_signature = new Signature(sig.Signature.ToPointer(), sig.Length, m_declaringType); } @@ -210,6 +212,7 @@ public override Type[] GetOptionalCustomModifiers() internal object GetConstantValue(bool raw) { object? defaultValue = MdConstant.GetValue(GetRuntimeModule().MetadataImport, m_token, PropertyType.TypeHandle, raw); + GC.KeepAlive(this); if (defaultValue == DBNull.Value) // Arg_EnumLitValueNotFound -> "Literal value was not found." diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameParser.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameParser.CoreCLR.cs deleted file mode 100644 index 2af4bb792d45..000000000000 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameParser.CoreCLR.cs +++ /dev/null @@ -1,301 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Runtime.Loader; -using System.Text; -using System.Threading; - -namespace System.Reflection -{ - internal partial struct TypeNameParser - { - private Func? _assemblyResolver; - private Func? _typeResolver; - private bool _throwOnError; - private bool _ignoreCase; - private bool _extensibleParser; - private bool _requireAssemblyQualifiedName; - private bool _suppressContextualReflectionContext; - private Assembly? _requestingAssembly; - private Assembly? _topLevelAssembly; - - [RequiresUnreferencedCode("The type might be removed")] - internal static Type? GetType( - string typeName, - Assembly requestingAssembly, - bool throwOnError = false, - bool ignoreCase = false) - { - return GetType(typeName, assemblyResolver: null, typeResolver: null, requestingAssembly: requestingAssembly, - throwOnError: throwOnError, ignoreCase: ignoreCase, extensibleParser: false); - } - - [RequiresUnreferencedCode("The type might be removed")] - internal static Type? GetType( - string typeName, - Func? assemblyResolver, - Func? typeResolver, - Assembly? requestingAssembly, - bool throwOnError = false, - bool ignoreCase = false, - bool extensibleParser = true) - { - ArgumentNullException.ThrowIfNull(typeName); - - // Compat: Empty name throws TypeLoadException instead of - // the natural ArgumentException - if (typeName.Length == 0) - { - if (throwOnError) - throw new TypeLoadException(SR.Arg_TypeLoadNullStr); - return null; - } - - return new TypeNameParser(typeName) - { - _assemblyResolver = assemblyResolver, - _typeResolver = typeResolver, - _throwOnError = throwOnError, - _ignoreCase = ignoreCase, - _extensibleParser = extensibleParser, - _requestingAssembly = requestingAssembly - }.Parse(); - } - - [RequiresUnreferencedCode("The type might be removed")] - internal static Type? GetType( - string typeName, - bool throwOnError, - bool ignoreCase, - Assembly topLevelAssembly) - { - return new TypeNameParser(typeName) - { - _throwOnError = throwOnError, - _ignoreCase = ignoreCase, - _topLevelAssembly = topLevelAssembly, - _requestingAssembly = topLevelAssembly - }.Parse(); - } - - // Resolve type name referenced by a custom attribute metadata. - // It uses the standard Type.GetType(typeName, throwOnError: true) algorithm with the following modifications: - // - ContextualReflectionContext is not taken into account - // - The dependency between the returned type and the requesting assembly is recorded for the purpose of - // lifetime tracking of collectible types. - internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName, RuntimeModule scope) - { - ArgumentException.ThrowIfNullOrEmpty(typeName); - - RuntimeAssembly requestingAssembly = scope.GetRuntimeAssembly(); - - RuntimeType? type = (RuntimeType?)new TypeNameParser(typeName) - { - _throwOnError = true, - _suppressContextualReflectionContext = true, - _requestingAssembly = requestingAssembly - }.Parse(); - - Debug.Assert(type != null); - - RuntimeTypeHandle.RegisterCollectibleTypeDependency(type, requestingAssembly); - - return type; - } - - // Used by VM - internal static unsafe RuntimeType? GetTypeHelper(char* pTypeName, RuntimeAssembly? requestingAssembly, - bool throwOnError, bool requireAssemblyQualifiedName) - { - ReadOnlySpan typeName = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(pTypeName); - - // Compat: Empty name throws TypeLoadException instead of - // the natural ArgumentException - if (typeName.Length == 0) - { - if (throwOnError) - throw new TypeLoadException(SR.Arg_TypeLoadNullStr); - return null; - } - - RuntimeType? type = (RuntimeType?)new TypeNameParser(typeName) - { - _requestingAssembly = requestingAssembly, - _throwOnError = throwOnError, - _suppressContextualReflectionContext = true, - _requireAssemblyQualifiedName = requireAssemblyQualifiedName, - }.Parse(); - - if (type != null) - RuntimeTypeHandle.RegisterCollectibleTypeDependency(type, requestingAssembly); - - return type; - } - - private bool CheckTopLevelAssemblyQualifiedName() - { - if (_topLevelAssembly is not null) - { - if (_throwOnError) - throw new ArgumentException(SR.Argument_AssemblyGetTypeCannotSpecifyAssembly); - return false; - } - return true; - } - - private Assembly? ResolveAssembly(string assemblyName) - { - Assembly? assembly; - if (_assemblyResolver is not null) - { - assembly = _assemblyResolver(new AssemblyName(assemblyName)); - if (assembly is null && _throwOnError) - { - throw new FileNotFoundException(SR.Format(SR.FileNotFound_ResolveAssembly, assemblyName)); - } - } - else - { - assembly = RuntimeAssembly.InternalLoad(new AssemblyName(assemblyName), ref Unsafe.NullRef(), - _suppressContextualReflectionContext ? null : AssemblyLoadContext.CurrentContextualReflectionContext, - requestingAssembly: (RuntimeAssembly?)_requestingAssembly, throwOnFileNotFound: _throwOnError); - } - return assembly; - } - - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "TypeNameParser.GetType is marked as RequiresUnreferencedCode.")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", - Justification = "TypeNameParser.GetType is marked as RequiresUnreferencedCode.")] - private Type? GetType(string typeName, ReadOnlySpan nestedTypeNames, string? assemblyNameIfAny) - { - Assembly? assembly; - - if (assemblyNameIfAny is not null) - { - assembly = ResolveAssembly(assemblyNameIfAny); - if (assembly is null) - return null; - } - else - { - assembly = _topLevelAssembly; - } - - Type? type; - - // Resolve the top level type. - if (_typeResolver is not null) - { - string escapedTypeName = EscapeTypeName(typeName); - - type = _typeResolver(assembly, escapedTypeName, _ignoreCase); - - if (type is null) - { - if (_throwOnError) - { - throw new TypeLoadException(assembly is null ? - SR.Format(SR.TypeLoad_ResolveType, escapedTypeName) : - SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, escapedTypeName, assembly.FullName)); - } - return null; - } - } - else - { - if (assembly is null) - { - if (_requireAssemblyQualifiedName) - { - if (_throwOnError) - { - throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveType, EscapeTypeName(typeName))); - } - return null; - } - return GetTypeFromDefaultAssemblies(typeName, nestedTypeNames); - } - - if (assembly is RuntimeAssembly runtimeAssembly) - { - // Compat: Non-extensible parser allows ambiguous matches with ignore case lookup - if (!_extensibleParser || !_ignoreCase) - { - return runtimeAssembly.GetTypeCore(typeName, nestedTypeNames, throwOnError: _throwOnError, ignoreCase: _ignoreCase); - } - type = runtimeAssembly.GetTypeCore(typeName, default, throwOnError: _throwOnError, ignoreCase: _ignoreCase); - } - else - { - // This is a third-party Assembly object. Emulate GetTypeCore() by calling the public GetType() - // method. This is wasteful because it'll probably reparse a type string that we've already parsed - // but it can't be helped. - type = assembly.GetType(EscapeTypeName(typeName), throwOnError: _throwOnError, ignoreCase: _ignoreCase); - } - - if (type is null) - return null; - } - - for (int i = 0; i < nestedTypeNames.Length; i++) - { - BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public; - if (_ignoreCase) - bindingFlags |= BindingFlags.IgnoreCase; - - type = type.GetNestedType(nestedTypeNames[i], bindingFlags); - - if (type is null) - { - if (_throwOnError) - { - throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveNestedType, - nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : typeName)); - } - return null; - } - } - - return type; - } - - private Type? GetTypeFromDefaultAssemblies(string typeName, ReadOnlySpan nestedTypeNames) - { - RuntimeAssembly? requestingAssembly = (RuntimeAssembly?)_requestingAssembly; - if (requestingAssembly is not null) - { - Type? type = ((RuntimeAssembly)requestingAssembly).GetTypeCore(typeName, nestedTypeNames, throwOnError: false, ignoreCase: _ignoreCase); - if (type is not null) - return type; - } - - RuntimeAssembly coreLib = (RuntimeAssembly)typeof(object).Assembly; - if (requestingAssembly != coreLib) - { - Type? type = ((RuntimeAssembly)coreLib).GetTypeCore(typeName, nestedTypeNames, throwOnError: false, ignoreCase: _ignoreCase); - if (type is not null) - return type; - } - - RuntimeAssembly? resolvedAssembly = AssemblyLoadContext.OnTypeResolve(requestingAssembly, EscapeTypeName(typeName, nestedTypeNames)); - if (resolvedAssembly is not null) - { - Type? type = resolvedAssembly.GetTypeCore(typeName, nestedTypeNames, throwOnError: false, ignoreCase: _ignoreCase); - if (type is not null) - return type; - } - - if (_throwOnError) - throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, EscapeTypeName(typeName), (requestingAssembly ?? coreLib).FullName)); - - return null; - } - } -} diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.CoreCLR.cs new file mode 100644 index 000000000000..78e2422b3410 --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.CoreCLR.cs @@ -0,0 +1,312 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Reflection.Metadata; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Loader; +using System.Threading; + +namespace System.Reflection +{ + internal partial struct TypeNameResolver + { + private Func? _assemblyResolver; + private Func? _typeResolver; + private bool _throwOnError; + private bool _ignoreCase; + private bool _extensibleParser; + private bool _requireAssemblyQualifiedName; + private bool _suppressContextualReflectionContext; + private Assembly? _requestingAssembly; + private Assembly? _topLevelAssembly; + + [RequiresUnreferencedCode("The type might be removed")] + internal static Type? GetType( + string typeName, + Assembly requestingAssembly, + bool throwOnError = false, + bool ignoreCase = false) + { + return GetType(typeName, assemblyResolver: null, typeResolver: null, requestingAssembly: requestingAssembly, + throwOnError: throwOnError, ignoreCase: ignoreCase, extensibleParser: false); + } + + [RequiresUnreferencedCode("The type might be removed")] + internal static Type? GetType( + string typeName, + Func? assemblyResolver, + Func? typeResolver, + Assembly? requestingAssembly, + bool throwOnError = false, + bool ignoreCase = false, + bool extensibleParser = true) + { + ArgumentNullException.ThrowIfNull(typeName); + + // Compat: Empty name throws TypeLoadException instead of + // the natural ArgumentException + if (typeName.Length == 0) + { + if (throwOnError) + throw new TypeLoadException(SR.Arg_TypeLoadNullStr); + return null; + } + + TypeName? parsed = TypeNameParser.Parse(typeName, throwOnError); + if (parsed is null) + { + return null; + } + + return new TypeNameResolver() + { + _assemblyResolver = assemblyResolver, + _typeResolver = typeResolver, + _throwOnError = throwOnError, + _ignoreCase = ignoreCase, + _extensibleParser = extensibleParser, + _requestingAssembly = requestingAssembly + }.Resolve(parsed); + } + + [RequiresUnreferencedCode("The type might be removed")] + internal static Type? GetType( + string typeName, + bool throwOnError, + bool ignoreCase, + Assembly topLevelAssembly) + { + TypeName? parsed = TypeNameParser.Parse(typeName, throwOnError); + + if (parsed is null) + { + return null; + } + else if (topLevelAssembly is not null && parsed.AssemblyName is not null) + { + return throwOnError ? throw new ArgumentException(SR.Argument_AssemblyGetTypeCannotSpecifyAssembly) : null; + } + + return new TypeNameResolver() + { + _throwOnError = throwOnError, + _ignoreCase = ignoreCase, + _topLevelAssembly = topLevelAssembly, + _requestingAssembly = topLevelAssembly + }.Resolve(parsed); + } + + // Resolve type name referenced by a custom attribute metadata. + // It uses the standard Type.GetType(typeName, throwOnError: true) algorithm with the following modifications: + // - ContextualReflectionContext is not taken into account + // - The dependency between the returned type and the requesting assembly is recorded for the purpose of + // lifetime tracking of collectible types. + internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName, RuntimeModule scope) + { + ArgumentException.ThrowIfNullOrEmpty(typeName); + + RuntimeAssembly requestingAssembly = scope.GetRuntimeAssembly(); + + TypeName parsed = TypeName.Parse(typeName); + RuntimeType? type = (RuntimeType?)new TypeNameResolver() + { + _throwOnError = true, + _suppressContextualReflectionContext = true, + _requestingAssembly = requestingAssembly + }.Resolve(parsed); + + Debug.Assert(type != null); + + RuntimeTypeHandle.RegisterCollectibleTypeDependency(type, requestingAssembly); + + return type; + } + + // Used by VM + internal static unsafe RuntimeType? GetTypeHelper(char* pTypeName, RuntimeAssembly? requestingAssembly, + bool throwOnError, bool requireAssemblyQualifiedName) + { + ReadOnlySpan typeName = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(pTypeName); + + // Compat: Empty name throws TypeLoadException instead of + // the natural ArgumentException + if (typeName.Length == 0) + { + if (throwOnError) + throw new TypeLoadException(SR.Arg_TypeLoadNullStr); + return null; + } + + TypeName? parsed = TypeNameParser.Parse(typeName, throwOnError); + if (parsed is null) + { + return null; + } + + RuntimeType? type = (RuntimeType?)new TypeNameResolver() + { + _requestingAssembly = requestingAssembly, + _throwOnError = throwOnError, + _suppressContextualReflectionContext = true, + _requireAssemblyQualifiedName = requireAssemblyQualifiedName, + }.Resolve(parsed); + + if (type != null) + RuntimeTypeHandle.RegisterCollectibleTypeDependency(type, requestingAssembly); + + return type; + } + + private Assembly? ResolveAssembly(AssemblyName assemblyName) + { + Assembly? assembly; + if (_assemblyResolver is not null) + { + assembly = _assemblyResolver(assemblyName); + if (assembly is null && _throwOnError) + { + throw new FileNotFoundException(SR.Format(SR.FileNotFound_ResolveAssembly, assemblyName)); + } + } + else + { + assembly = RuntimeAssembly.InternalLoad(assemblyName, ref Unsafe.NullRef(), + _suppressContextualReflectionContext ? null : AssemblyLoadContext.CurrentContextualReflectionContext, + requestingAssembly: (RuntimeAssembly?)_requestingAssembly, throwOnFileNotFound: _throwOnError); + } + return assembly; + } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "TypeNameResolver.GetType is marked as RequiresUnreferencedCode.")] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", + Justification = "TypeNameResolver.GetType is marked as RequiresUnreferencedCode.")] + private Type? GetType(string escapedTypeName, ReadOnlySpan nestedTypeNames, TypeName parsedName) + { + Assembly? assembly; + + if (parsedName.AssemblyName is not null) + { + assembly = ResolveAssembly(parsedName.AssemblyName.ToAssemblyName()); + if (assembly is null) + return null; + } + else + { + assembly = _topLevelAssembly; + } + + Type? type; + + // Resolve the top level type. + if (_typeResolver is not null) + { + type = _typeResolver(assembly, escapedTypeName, _ignoreCase); + + if (type is null) + { + if (_throwOnError) + { + throw new TypeLoadException(assembly is null ? + SR.Format(SR.TypeLoad_ResolveType, escapedTypeName) : + SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, escapedTypeName, assembly.FullName)); + } + return null; + } + } + else + { + if (assembly is null) + { + if (_requireAssemblyQualifiedName) + { + if (_throwOnError) + { + throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveType, escapedTypeName)); + } + return null; + } + return GetTypeFromDefaultAssemblies(TypeNameHelpers.Unescape(escapedTypeName), nestedTypeNames, parsedName); + } + + if (assembly is RuntimeAssembly runtimeAssembly) + { + string unescapedTypeName = TypeNameHelpers.Unescape(escapedTypeName); + // Compat: Non-extensible parser allows ambiguous matches with ignore case lookup + if (!_extensibleParser || !_ignoreCase) + { + return runtimeAssembly.GetTypeCore(unescapedTypeName, nestedTypeNames, throwOnError: _throwOnError, ignoreCase: _ignoreCase); + } + type = runtimeAssembly.GetTypeCore(unescapedTypeName, default, throwOnError: _throwOnError, ignoreCase: _ignoreCase); + } + else + { + // This is a third-party Assembly object. Emulate GetTypeCore() by calling the public GetType() + // method. This is wasteful because it'll probably reparse a type string that we've already parsed + // but it can't be helped. + type = assembly.GetType(escapedTypeName, throwOnError: _throwOnError, ignoreCase: _ignoreCase); + } + + if (type is null) + return null; + } + + for (int i = 0; i < nestedTypeNames.Length; i++) + { + BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public; + if (_ignoreCase) + bindingFlags |= BindingFlags.IgnoreCase; + + type = type.GetNestedType(nestedTypeNames[i], bindingFlags); + + if (type is null) + { + if (_throwOnError) + { + throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveNestedType, + nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : TypeNameHelpers.Unescape(escapedTypeName))); + } + return null; + } + } + + return type; + } + + private Type? GetTypeFromDefaultAssemblies(string typeName, ReadOnlySpan nestedTypeNames, TypeName parsedName) + { + RuntimeAssembly? requestingAssembly = (RuntimeAssembly?)_requestingAssembly; + if (requestingAssembly is not null) + { + Type? type = requestingAssembly.GetTypeCore(typeName, nestedTypeNames, throwOnError: false, ignoreCase: _ignoreCase); + if (type is not null) + return type; + } + + RuntimeAssembly coreLib = (RuntimeAssembly)typeof(object).Assembly; + if (requestingAssembly != coreLib) + { + Type? type = coreLib.GetTypeCore(typeName, nestedTypeNames, throwOnError: false, ignoreCase: _ignoreCase); + if (type is not null) + return type; + } + + RuntimeAssembly? resolvedAssembly = AssemblyLoadContext.OnTypeResolve(requestingAssembly, parsedName.FullName); + if (resolvedAssembly is not null) + { + Type? type = resolvedAssembly.GetTypeCore(typeName, nestedTypeNames, throwOnError: false, ignoreCase: _ignoreCase); + if (type is not null) + return type; + } + + if (_throwOnError) + throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, parsedName.FullName, (requestingAssembly ?? coreLib).FullName)); + + return null; + } + } +} diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs index 69506c2feda1..43ddbfecf006 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs @@ -458,6 +458,32 @@ private static unsafe void DispatchTailCalls( return Unsafe.As(ref target); } } + + [LibraryImport(QCall, EntryPoint = "ReflectionInvocation_SizeOf")] + [SuppressGCTransition] + private static partial int SizeOf(QCallTypeHandle handle); + + /// + /// Get the size of an object of the given type. + /// + /// The type to get the size of. + /// The size of instances of the type. + /// The passed-in type is not a valid type to get the size of. + /// + /// This API returns the same value as for the type that represents. + /// + public static unsafe int SizeOf(RuntimeTypeHandle type) + { + if (type.IsNullHandle()) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.type); + + int result = SizeOf(new QCallTypeHandle(ref type)); + + if (result <= 0) + throw new ArgumentException(SR.Arg_TypeNotSupported); + + return result; + } } // Helper class to assist with unsafe pinning of arbitrary objects. // It's used by VM code. diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs index bbdccc6cd2ee..64669dd5458f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs @@ -21,7 +21,7 @@ public static partial class Marshal /// /// IUnknown is {00000000-0000-0000-C000-000000000046} /// - internal static Guid IID_IUnknown = new Guid(0, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46); + internal static readonly Guid IID_IUnknown = new Guid(0, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46); #endif //FEATURE_COMINTEROP internal static int SizeOfHelper(RuntimeType t, [MarshalAs(UnmanagedType.Bool)] bool throwIfNotMarshalable) @@ -929,7 +929,7 @@ public static object BindToMoniker(string monikerName) ThrowExceptionForHR(MkParseDisplayName(bindctx, monikerName, out _, out IntPtr pmoniker)); try { - ThrowExceptionForHR(BindMoniker(pmoniker, 0, ref IID_IUnknown, out IntPtr ptr)); + ThrowExceptionForHR(BindMoniker(pmoniker, 0, in IID_IUnknown, out IntPtr ptr)); try { return GetObjectForIUnknown(ptr); @@ -956,7 +956,7 @@ public static object BindToMoniker(string monikerName) private static partial int MkParseDisplayName(IntPtr pbc, [MarshalAs(UnmanagedType.LPWStr)] string szUserName, out uint pchEaten, out IntPtr ppmk); [LibraryImport(Interop.Libraries.Ole32)] - private static partial int BindMoniker(IntPtr pmk, uint grfOpt, ref Guid iidResult, out IntPtr ppvResult); + private static partial int BindMoniker(IntPtr pmk, uint grfOpt, in Guid iidResult, out IntPtr ppvResult); [SupportedOSPlatform("windows")] public static void ChangeWrapperHandleStrength(object otp, bool fIsWeak) diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 001a9fcdfee6..380981993451 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -650,14 +650,6 @@ internal static bool SatisfiesConstraints(RuntimeType paramType, RuntimeType[]? } } - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern IntPtr _GetMetadataImport(RuntimeType type); - - internal static MetadataImport GetMetadataImport(RuntimeType type) - { - return new MetadataImport(_GetMetadataImport(type), type); - } - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_RegisterCollectibleTypeDependency")] private static partial void RegisterCollectibleTypeDependency(QCallTypeHandle type, QCallAssembly assembly); @@ -1247,8 +1239,6 @@ internal ModuleHandle(RuntimeModule module) } #endregion - #region Internal FCalls - internal RuntimeModule GetRuntimeModule() { return m_ptr; @@ -1278,6 +1268,7 @@ public bool Equals(ModuleHandle handle) public static bool operator !=(ModuleHandle left, ModuleHandle right) => !left.Equals(right); + #region Internal FCalls [MethodImpl(MethodImplOptions.InternalCall)] internal static extern IRuntimeMethodInfo GetDynamicMethod(Reflection.Emit.DynamicMethod method, RuntimeModule module, string name, byte[] sig, Resolver resolver); @@ -1336,7 +1327,7 @@ public RuntimeTypeHandle ResolveTypeHandle(int typeToken, RuntimeTypeHandle[]? t } catch (Exception) { - if (!GetMetadataImport(module).IsValidToken(typeToken)) + if (!module.MetadataImport.IsValidToken(typeToken)) throw new ArgumentOutOfRangeException(nameof(typeToken), SR.Format(SR.Argument_InvalidToken, typeToken, new ModuleHandle(module))); throw; @@ -1389,7 +1380,7 @@ internal static RuntimeMethodHandleInternal ResolveMethodHandleInternal(RuntimeM } catch (Exception) { - if (!GetMetadataImport(module).IsValidToken(methodToken)) + if (!module.MetadataImport.IsValidToken(methodToken)) throw new ArgumentOutOfRangeException(nameof(methodToken), SR.Format(SR.Argument_InvalidToken, methodToken, new ModuleHandle(module))); throw; @@ -1442,7 +1433,7 @@ public RuntimeFieldHandle ResolveFieldHandle(int fieldToken, RuntimeTypeHandle[] } catch (Exception) { - if (!GetMetadataImport(module).IsValidToken(fieldToken)) + if (!module.MetadataImport.IsValidToken(fieldToken)) throw new ArgumentOutOfRangeException(nameof(fieldToken), SR.Format(SR.Argument_InvalidToken, fieldToken, new ModuleHandle(module))); throw; @@ -1485,14 +1476,6 @@ internal static void GetPEKind(RuntimeModule module, out PortableExecutableKinds internal static extern int GetMDStreamVersion(RuntimeModule module); public int MDStreamVersion => GetMDStreamVersion(GetRuntimeModule()); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern IntPtr _GetMetadataImport(RuntimeModule module); - - internal static MetadataImport GetMetadataImport(RuntimeModule module) - { - return new MetadataImport(_GetMetadataImport(module), module); - } #endregion } diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index 6a1fae9e05c7..c6ea76fde9b8 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -932,7 +932,8 @@ private void PopulateLiteralFields(Filter filter, RuntimeType declaringType, ref if (MdToken.IsNullToken(tkDeclaringType)) return; - MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(declaringType); + RuntimeModule module = declaringType.GetRuntimeModule(); + MetadataImport scope = module.MetadataImport; scope.EnumFields(tkDeclaringType, out MetadataEnumResult tkFields); @@ -976,6 +977,7 @@ private void PopulateLiteralFields(Filter filter, RuntimeType declaringType, ref list.Add(runtimeFieldInfo); } } + GC.KeepAlive(module); } private void AddSpecialInterface( @@ -1102,7 +1104,7 @@ private RuntimeType[] PopulateNestedClasses(Filter filter) ListBuilder list = default; ModuleHandle moduleHandle = new ModuleHandle(RuntimeTypeHandle.GetModule(declaringType)); - MetadataImport scope = ModuleHandle.GetMetadataImport(moduleHandle.GetRuntimeModule()); + MetadataImport scope = moduleHandle.GetRuntimeModule().MetadataImport; scope.EnumNestedTypes(tkEnclosingType, out MetadataEnumResult tkNestedClasses); @@ -1174,7 +1176,8 @@ private void PopulateEvents( if (MdToken.IsNullToken(tkDeclaringType)) return; - MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(declaringType); + RuntimeModule module = declaringType.GetRuntimeModule(); + MetadataImport scope = module.MetadataImport; scope.EnumEvents(tkDeclaringType, out MetadataEnumResult tkEvents); @@ -1220,6 +1223,7 @@ private void PopulateEvents( list.Add(eventInfo); } + GC.KeepAlive(module); } private RuntimePropertyInfo[] PopulateProperties(Filter filter) @@ -1286,7 +1290,8 @@ private void PopulateProperties( if (MdToken.IsNullToken(tkDeclaringType)) return; - MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(declaringType); + RuntimeModule module = declaringType.GetRuntimeModule(); + MetadataImport scope = module.MetadataImport; scope.EnumProperties(tkDeclaringType, out MetadataEnumResult tkProperties); @@ -1304,7 +1309,7 @@ private void PopulateProperties( if (filter.RequiresStringComparison()) { - MdUtf8String name = declaringType.GetRuntimeModule().MetadataImport.GetName(tkProperty); + MdUtf8String name = scope.GetName(tkProperty); if (!filter.Match(name)) continue; @@ -1399,6 +1404,7 @@ private void PopulateProperties( list.Add(propertyInfo); } + GC.KeepAlive(module); } #endregion @@ -1571,7 +1577,9 @@ internal Type[] FunctionPointerReturnAndParameterTypes while (type.IsNested) type = type.DeclaringType!; - m_namespace = RuntimeTypeHandle.GetMetadataImport((RuntimeType)type).GetNamespace(type.MetadataToken).ToString(); + RuntimeModule module = ((RuntimeType)type).GetRuntimeModule(); + m_namespace = module.MetadataImport.GetNamespace(type.MetadataToken).ToString(); + GC.KeepAlive(module); } return m_namespace; @@ -3499,8 +3507,9 @@ public override GenericParameterAttributes GenericParameterAttributes if (!IsGenericParameter) throw new InvalidOperationException(SR.Arg_NotGenericParameter); - - RuntimeTypeHandle.GetMetadataImport(this).GetGenericParamProps(MetadataToken, out GenericParameterAttributes attributes); + RuntimeModule module = GetRuntimeModule(); + module.MetadataImport.GetGenericParamProps(MetadataToken, out GenericParameterAttributes attributes); + GC.KeepAlive(module); return attributes; } @@ -3664,9 +3673,6 @@ public override Type MakeArrayType(int rank) [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool CanValueSpecialCast(RuntimeType valueType, RuntimeType targetType); - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern object AllocateValueType(RuntimeType type, object? value); - private CheckValueStatus TryChangeTypeSpecial(ref object value) { Pointer? pointer = value as Pointer; @@ -3973,14 +3979,6 @@ internal object GetUninitializedObject() #region Legacy internal static - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern object _CreateEnum(RuntimeType enumType, long value); - - internal static object CreateEnum(RuntimeType enumType, long value) - { - return _CreateEnum(enumType, value); - } - #if FEATURE_COMINTEROP [MethodImpl(MethodImplOptions.InternalCall)] private extern object InvokeDispMethod( diff --git a/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs index 03a92b709eb1..8707db0cf7f6 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; -using System.Runtime.Versioning; using System.Security; using StackCrawlMark = System.Threading.StackCrawlMark; @@ -17,7 +16,7 @@ public abstract partial class Type : MemberInfo, IReflect public static Type? GetType(string typeName, bool throwOnError, bool ignoreCase) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return TypeNameParser.GetType(typeName, Assembly.GetExecutingAssembly(ref stackMark), + return TypeNameResolver.GetType(typeName, Assembly.GetExecutingAssembly(ref stackMark), throwOnError: throwOnError, ignoreCase: ignoreCase); } @@ -26,7 +25,7 @@ public abstract partial class Type : MemberInfo, IReflect public static Type? GetType(string typeName, bool throwOnError) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return TypeNameParser.GetType(typeName, Assembly.GetExecutingAssembly(ref stackMark), + return TypeNameResolver.GetType(typeName, Assembly.GetExecutingAssembly(ref stackMark), throwOnError: throwOnError); } @@ -35,7 +34,7 @@ public abstract partial class Type : MemberInfo, IReflect public static Type? GetType(string typeName) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return TypeNameParser.GetType(typeName, Assembly.GetExecutingAssembly(ref stackMark)); + return TypeNameResolver.GetType(typeName, Assembly.GetExecutingAssembly(ref stackMark)); } [RequiresUnreferencedCode("The type might be removed")] @@ -46,7 +45,7 @@ public abstract partial class Type : MemberInfo, IReflect Func? typeResolver) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver, + return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver, ((assemblyResolver != null) && (typeResolver != null)) ? null : Assembly.GetExecutingAssembly(ref stackMark)); } @@ -59,7 +58,7 @@ public abstract partial class Type : MemberInfo, IReflect bool throwOnError) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver, + return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver, ((assemblyResolver != null) && (typeResolver != null)) ? null : Assembly.GetExecutingAssembly(ref stackMark), throwOnError: throwOnError); } @@ -74,7 +73,7 @@ public abstract partial class Type : MemberInfo, IReflect bool ignoreCase) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver, + return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver, ((assemblyResolver != null) && (typeResolver != null)) ? null : Assembly.GetExecutingAssembly(ref stackMark), throwOnError: throwOnError, ignoreCase: ignoreCase); } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Variant.cs b/src/coreclr/System.Private.CoreLib/src/System/Variant.cs index b945b28e08a7..f32f2b99e788 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Variant.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Variant.cs @@ -17,7 +17,7 @@ namespace System { - internal struct Variant + internal partial struct Variant { // Do Not change the order of these fields. // They are mapped to the native VariantData * data structure. @@ -70,6 +70,14 @@ internal struct Variant internal static Variant Missing => new Variant(CV_MISSING, Type.Missing, 0); internal static Variant DBNull => new Variant(CV_NULL, System.DBNull.Value, 0); + internal static bool IsSystemDrawingColor(Type type) => type.FullName == "System.Drawing.Color"; // Matches the behavior of IsTypeRefOrDef + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Variant_ConvertSystemColorToOleColor")] + internal static partial uint ConvertSystemColorToOleColor(ObjectHandleOnStack obj); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Variant_ConvertOleColorToSystemColor")] + internal static partial void ConvertOleColorToSystemColor(ObjectHandleOnStack objret, uint value, IntPtr pMT); + // // Native Methods // diff --git a/src/coreclr/binder/assemblybindercommon.cpp b/src/coreclr/binder/assemblybindercommon.cpp index 55f9a0ae5336..e1de7af70677 100644 --- a/src/coreclr/binder/assemblybindercommon.cpp +++ b/src/coreclr/binder/assemblybindercommon.cpp @@ -1297,7 +1297,7 @@ HRESULT AssemblyBinderCommon::CreateDefaultBinder(DefaultAssemblyBinder** ppDefa hr = pApplicationContext->Init(); if (SUCCEEDED(hr)) { - pBinder->SetManagedAssemblyLoadContext(NULL); + pBinder->SetManagedAssemblyLoadContext((INT_PTR)NULL); *ppDefaultBinder = pBinder.Extract(); } } diff --git a/src/coreclr/binder/customassemblybinder.cpp b/src/coreclr/binder/customassemblybinder.cpp index ac1cf61bcf6a..99297c2bd9ce 100644 --- a/src/coreclr/binder/customassemblybinder.cpp +++ b/src/coreclr/binder/customassemblybinder.cpp @@ -242,13 +242,13 @@ void CustomAssemblyBinder::PrepareForLoadContextRelease(INT_PTR ptrManagedStrong CustomAssemblyBinder::CustomAssemblyBinder() { m_pDefaultBinder = NULL; - m_ptrManagedStrongAssemblyLoadContext = NULL; + m_ptrManagedStrongAssemblyLoadContext = (INT_PTR)NULL; } void CustomAssemblyBinder::ReleaseLoadContext() { - VERIFY(GetManagedAssemblyLoadContext() != NULL); - VERIFY(m_ptrManagedStrongAssemblyLoadContext != NULL); + VERIFY(GetManagedAssemblyLoadContext() != (INT_PTR)NULL); + VERIFY(m_ptrManagedStrongAssemblyLoadContext != (INT_PTR)NULL); // This method is called to release the weak and strong handles on the managed AssemblyLoadContext // once the Unloading event has been fired @@ -256,7 +256,7 @@ void CustomAssemblyBinder::ReleaseLoadContext() DestroyLongWeakHandle(handle); handle = reinterpret_cast(m_ptrManagedStrongAssemblyLoadContext); DestroyHandle(handle); - SetManagedAssemblyLoadContext(NULL); + SetManagedAssemblyLoadContext((INT_PTR)NULL); // The AssemblyLoaderAllocator is in a process of shutdown and should not be used // after this point. diff --git a/src/coreclr/binder/defaultassemblybinder.cpp b/src/coreclr/binder/defaultassemblybinder.cpp index d4ad4f3265ce..54a70e51f05e 100644 --- a/src/coreclr/binder/defaultassemblybinder.cpp +++ b/src/coreclr/binder/defaultassemblybinder.cpp @@ -63,7 +63,7 @@ HRESULT DefaultAssemblyBinder::BindUsingAssemblyName(BINDER_SPACE::AssemblyName // Attempt to resolve the assembly via managed ALC instance. This can either fail the bind or return reference to an existing // assembly that has been loaded INT_PTR pManagedAssemblyLoadContext = GetManagedAssemblyLoadContext(); - if (pManagedAssemblyLoadContext == NULL) + if (pManagedAssemblyLoadContext == (INT_PTR)NULL) { // For satellite assemblies, the managed ALC has additional resolution logic (defined by the runtime) which // should be run even if the managed default ALC has not yet been used. (For non-satellite assemblies, any @@ -78,11 +78,11 @@ HRESULT DefaultAssemblyBinder::BindUsingAssemblyName(BINDER_SPACE::AssemblyName CALL_MANAGED_METHOD_NORET(args) pManagedAssemblyLoadContext = GetManagedAssemblyLoadContext(); - _ASSERTE(pManagedAssemblyLoadContext != NULL); + _ASSERTE(pManagedAssemblyLoadContext != (INT_PTR)NULL); } } - if (pManagedAssemblyLoadContext != NULL) + if (pManagedAssemblyLoadContext != (INT_PTR)NULL) { hr = AssemblyBinderCommon::BindUsingHostAssemblyResolver(pManagedAssemblyLoadContext, pAssemblyName, NULL, this, &pCoreCLRFoundAssembly); diff --git a/src/coreclr/classlibnative/bcltype/CMakeLists.txt b/src/coreclr/classlibnative/bcltype/CMakeLists.txt index 8e4baf95751e..e8cce56d1735 100644 --- a/src/coreclr/classlibnative/bcltype/CMakeLists.txt +++ b/src/coreclr/classlibnative/bcltype/CMakeLists.txt @@ -2,7 +2,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(BCLTYPE_SOURCES arraynative.cpp - oavariant.cpp objectnative.cpp system.cpp varargsnative.cpp diff --git a/src/coreclr/classlibnative/bcltype/arraynative.cpp b/src/coreclr/classlibnative/bcltype/arraynative.cpp index 32bc52b96f1a..02ff0360ac4b 100644 --- a/src/coreclr/classlibnative/bcltype/arraynative.cpp +++ b/src/coreclr/classlibnative/bcltype/arraynative.cpp @@ -32,7 +32,7 @@ extern "C" PCODE QCALLTYPE Array_GetElementConstructorEntrypoint(QCall::TypeHand { QCALL_CONTRACT; - PCODE ctorEntrypoint = NULL; + PCODE ctorEntrypoint = (PCODE)NULL; BEGIN_QCALL; diff --git a/src/coreclr/classlibnative/bcltype/arraynative.inl b/src/coreclr/classlibnative/bcltype/arraynative.inl index 913b8c64939b..632b83905849 100644 --- a/src/coreclr/classlibnative/bcltype/arraynative.inl +++ b/src/coreclr/classlibnative/bcltype/arraynative.inl @@ -307,7 +307,12 @@ FORCEINLINE void InlinedMemmoveGCRefsHelper(void *dest, const void *src, size_t _ASSERTE(CheckPointer(dest)); _ASSERTE(CheckPointer(src)); - GCHeapMemoryBarrier(); + const bool notInHeap = ((BYTE*)dest < g_lowest_address || (BYTE*)dest >= g_highest_address); + + if (!notInHeap) + { + GCHeapMemoryBarrier(); + } // To be able to copy forwards, the destination buffer cannot start inside the source buffer if ((size_t)dest - (size_t)src >= len) @@ -319,7 +324,10 @@ FORCEINLINE void InlinedMemmoveGCRefsHelper(void *dest, const void *src, size_t InlinedBackwardGCSafeCopyHelper(dest, src, len); } - InlinedSetCardsAfterBulkCopyHelper((Object**)dest, len); + if (!notInHeap) + { + InlinedSetCardsAfterBulkCopyHelper((Object**)dest, len); + } } #endif // !_ARRAYNATIVE_INL_ diff --git a/src/coreclr/classlibnative/bcltype/oavariant.cpp b/src/coreclr/classlibnative/bcltype/oavariant.cpp deleted file mode 100644 index ac8c55f359d8..000000000000 --- a/src/coreclr/classlibnative/bcltype/oavariant.cpp +++ /dev/null @@ -1,420 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// File: OAVariant.cpp -// - -#include - -#ifdef FEATURE_COMINTEROP - -#include -#include "excep.h" -#include "oavariant.h" -#include "comdatetime.h" // DateTime <-> OleAut date conversions -#include "interoputil.h" -#include "interopconverter.h" -#include "excep.h" -#include "string.h" -#include "comutilnative.h" // for COMDate - -#define INVALID_MAPPING (BYTE)(-1) - -static const BYTE CVtoVTTable [] = -{ - VT_EMPTY, // CV_EMPTY - VT_VOID, // CV_VOID - VT_BOOL, // CV_BOOLEAN - VT_UI2, // CV_CHAR - VT_I1, // CV_I1 - VT_UI1, // CV_U1 - VT_I2, // CV_I2 - VT_UI2, // CV_U2 - VT_I4, // CV_I4 - VT_UI4, // CV_U4 - VT_I8, // CV_I8 - VT_UI8, // CV_U8 - VT_R4, // CV_R4 - VT_R8, // CV_R8 - VT_BSTR, // CV_STRING - INVALID_MAPPING, // CV_PTR - VT_DATE, // CV_DATETIME - INVALID_MAPPING, // CV_TIMESPAN - VT_UNKNOWN, // CV_OBJECT - VT_DECIMAL, // CV_DECIMAL - VT_CY, // CV_CURRENCY - INVALID_MAPPING, // CV_ENUM - INVALID_MAPPING, // CV_MISSING - VT_NULL, // CV_NULL - INVALID_MAPPING // CV_LAST -}; - -static const BYTE VTtoCVTable[] = -{ - CV_EMPTY, // VT_EMPTY - CV_NULL, // VT_NULL - CV_I2, // VT_I2 - CV_I4, // VT_I4 - CV_R4, // VT_R4 - CV_R8, // VT_R8 - CV_CURRENCY,// VT_CY - CV_DATETIME,// VT_DATE - CV_STRING, // VT_BSTR - INVALID_MAPPING, // VT_DISPATCH - INVALID_MAPPING, // VT_ERROR - CV_BOOLEAN, // VT_BOOL - CV_OBJECT, // VT_VARIANT - CV_OBJECT, // VT_UNKNOWN - CV_DECIMAL, // VT_DECIMAL - INVALID_MAPPING, // An unused enum table entry - CV_I1, // VT_I1 - CV_U1, // VT_UI1 - CV_U2, // VT_UI2 - CV_U4, // VT_UI4 - CV_I8, // VT_I8 - CV_U8, // VT_UI8 - CV_I4, // VT_INT - CV_U4, // VT_UINT - CV_VOID // VT_VOID -}; - -// Need translations from CVType to VARENUM and vice versa. CVTypes -// is defined in olevariant.h. VARENUM is defined in OleAut's variant.h -// Assumption here is we will only deal with VARIANTs and not other OLE -// constructs such as property sets or safe arrays. -static VARENUM CVtoVT(const CVTypes cv) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(cv >= 0 && cv < CV_LAST); - } - CONTRACTL_END; - - if (CVtoVTTable[cv] == INVALID_MAPPING) - COMPlusThrow(kNotSupportedException, W("NotSupported_ChangeType")); - - return (VARENUM) CVtoVTTable[cv]; -} - -// Need translations from CVType to VARENUM and vice versa. CVTypes -// is defined in olevariant.h. VARENUM is defined in OleAut's variant.h -static CVTypes VTtoCV(const VARENUM vt) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(vt < VT_VOID); - } - CONTRACTL_END; - - if (vt <0 || vt > VT_VOID || VTtoCVTable[vt]==INVALID_MAPPING) - COMPlusThrow(kNotSupportedException, W("NotSupported_ChangeType")); - - return (CVTypes) VTtoCVTable[vt]; -} - - -// Converts a COM+ Variant to an OleAut Variant. Returns true if -// there was a native object allocated by this method that must be freed, -// else false. -static bool ToOAVariant(VariantData const* src, VARIANT* oa) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - INJECT_FAULT(COMPlusThrowOM()); - PRECONDITION(CheckPointer(src)); - PRECONDITION(CheckPointer(oa)); - } - CONTRACTL_END; - - SafeVariantInit(oa); - UINT64 * dest = (UINT64*) &V_UI1(oa); - *dest = 0; - - WCHAR * chars; - int strLen; - - // Set the data field of the OA Variant to be either the object reference - // or the data (ie int) that it needs. - - switch (src->GetType()) - { - case CV_STRING: - if (src->GetObjRef() == NULL) - { - V_BSTR(oa) = NULL; - V_VT(oa) = static_cast(CVtoVT(src->GetType())); - - // OA perf feature: VarClear calls SysFreeString(null), which access violates. - return false; - } - - ((STRINGREF) (src->GetObjRef()))->RefInterpretGetStringValuesDangerousForGC(&chars, &strLen); - V_BSTR(oa) = SysAllocStringLen(chars, strLen); - if (V_BSTR(oa) == NULL) - COMPlusThrowOM(); - - V_VT(oa) = static_cast(CVtoVT(src->GetType())); - - return true; - - case CV_CHAR: - chars = (WCHAR*)src->GetData(); - V_BSTR(oa) = SysAllocStringLen(chars, 1); - if (V_BSTR(oa) == NULL) - COMPlusThrowOM(); - - // We should override the VTtoVT default of VT_UI2 for this case. - V_VT(oa) = VT_BSTR; - - return true; - - case CV_DATETIME: - V_DATE(oa) = COMDateTime::TicksToDoubleDate(src->GetDataAsInt64()); - V_VT(oa) = static_cast(CVtoVT(src->GetType())); - return false; - - case CV_BOOLEAN: - V_BOOL(oa) = (src->GetDataAsInt64()==0 ? VARIANT_FALSE : VARIANT_TRUE); - V_VT(oa) = static_cast(CVtoVT(src->GetType())); - return false; - - case CV_DECIMAL: - { - OBJECTREF obj = src->GetObjRef(); - DECIMAL * d = (DECIMAL*) obj->GetData(); - // DECIMALs and Variants are the same size. Variants are a union between - // all the normal Variant fields (vt, bval, etc) and a Decimal. Decimals - // also have the first 2 bytes reserved, for a VT field. - - V_DECIMAL(oa) = *d; - V_VT(oa) = VT_DECIMAL; - return false; - } - - case CV_OBJECT: - { - OBJECTREF obj = src->GetObjRef(); - GCPROTECT_BEGIN(obj) - { - IUnknown *pUnk = NULL; - - // Convert the object to an IDispatch/IUnknown pointer. - ComIpType FetchedIpType = ComIpType_None; - pUnk = GetComIPFromObjectRef(&obj, ComIpType_Both, &FetchedIpType); - V_UNKNOWN(oa) = pUnk; - V_VT(oa) = static_cast(FetchedIpType == ComIpType_Dispatch ? VT_DISPATCH : VT_UNKNOWN); - } - GCPROTECT_END(); - return true; - } - - default: - *dest = src->GetDataAsInt64(); - V_VT(oa) = static_cast(CVtoVT(src->GetType())); - return false; - } -} - -// Converts an OleAut Variant into a COM+ Variant. -// Note that we pass the VariantData Byref so that if GC happens, 'var' gets updated -static void FromOAVariant(VARIANT const* src, VariantData*& var) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - INJECT_FAULT(COMPlusThrowOM()); - PRECONDITION(CheckPointer(src)); - } - CONTRACTL_END; - - // Clear the return variant value. It's allocated on - // the stack and we only want valid state data in there. - memset(var, 0, sizeof(VariantData)); - - CVTypes type = VTtoCV((VARENUM) V_VT(src)); - var->SetType(type); - - switch (type) - { - case CV_STRING: - { - // BSTRs have an int with the string buffer length (not the string length) - // followed by the data. The pointer to the BSTR points to the start of the - // characters, NOT the start of the BSTR. - WCHAR* chars = V_BSTR(src); - int strLen = SysStringLen(V_BSTR(src)); - STRINGREF str = StringObject::NewString(chars, strLen); - var->SetObjRef((OBJECTREF)str); - break; - } - case CV_DATETIME: - var->SetDataAsInt64(COMDateTime::DoubleDateToTicks(V_DATE(src))); - break; - - case CV_BOOLEAN: - var->SetDataAsInt64(V_BOOL(src) == VARIANT_FALSE ? FALSE : TRUE); - break; - - case CV_DECIMAL: - { - MethodTable * pDecimalMT = GetTypeHandleForCVType(CV_DECIMAL).GetMethodTable(); - _ASSERTE(pDecimalMT); - OBJECTREF pDecimalRef = AllocateObject(pDecimalMT); - - *(DECIMAL *) pDecimalRef->GetData() = V_DECIMAL(src); - var->SetObjRef(pDecimalRef); - break; - } - - // All types less than 4 bytes need an explicit cast from their original - // type to be sign extended to 8 bytes. This makes Variant's ToInt32 - // function simpler for these types. - case CV_I1: - var->SetDataAsInt64(V_I1(src)); - break; - - case CV_U1: - var->SetDataAsInt64(V_UI1(src)); - break; - - case CV_I2: - var->SetDataAsInt64(V_I2(src)); - break; - - case CV_U2: - var->SetDataAsInt64(V_UI2(src)); - break; - - case CV_EMPTY: - case CV_NULL: - // Must set up the Variant's m_or to the appropriate classes. - // Note that OleAut doesn't have any VT_MISSING. - VariantData::NewVariant(var, type, NULL DEBUG_ARG(TRUE)); - break; - - case CV_OBJECT: - { - // Convert the IUnknown pointer to an OBJECTREF. - OBJECTREF oref = NULL; - GCPROTECT_BEGIN(oref); - GetObjectRefFromComIP(&oref, V_UNKNOWN(src)); - var->SetObjRef(oref); - GCPROTECT_END(); - break; - } - default: - // Copy all the bits there, and make sure we don't do any float to int conversions. - void* data = (void*)&(V_UI1(src)); - var->SetData(data); - break; - } -} - -static void OAFailed(HRESULT hr) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(FAILED(hr)); - } - CONTRACTL_END; - - switch (hr) - { - case E_OUTOFMEMORY: - COMPlusThrowOM(); - - case DISP_E_BADVARTYPE: - COMPlusThrow(kNotSupportedException, W("NotSupported_OleAutBadVarType")); - - case DISP_E_DIVBYZERO: - COMPlusThrow(kDivideByZeroException); - - case DISP_E_OVERFLOW: - COMPlusThrow(kOverflowException); - - case DISP_E_TYPEMISMATCH: - COMPlusThrow(kInvalidCastException, W("InvalidCast_OATypeMismatch")); - - case E_INVALIDARG: - COMPlusThrow(kArgumentException); - - default: - _ASSERTE(!"Unrecognized HResult - OAVariantLib routine failed in an unexpected way!"); - COMPlusThrowHR(hr); - } -} - -extern "C" void QCALLTYPE OAVariant_ChangeType(VariantData* result, VariantData* source, LCID lcid, void* targetType, int cvType, INT16 flags) -{ - CONTRACTL - { - QCALL_CHECK; - PRECONDITION(CheckPointer(result)); - } - CONTRACTL_END; - - BEGIN_QCALL; - - GCX_COOP(); - - bool converted = false; - - TypeHandle thTarget = TypeHandle::FromPtr(targetType); - if (cvType == CV_OBJECT && IsTypeRefOrDef(g_ColorClassName, thTarget.GetModule(), thTarget.GetCl())) - { - CVTypes sourceType = source->GetType(); - if (sourceType == CV_I4 || sourceType == CV_U4) - { - // Int32/UInt32 can be converted to System.Drawing.Color - SYSTEMCOLOR SystemColor; - ConvertOleColorToSystemColor(source->GetDataAsUInt32(), &SystemColor); - - result->SetObjRef(thTarget.AsMethodTable()->Box(&SystemColor)); - result->SetType(CV_OBJECT); - - converted = true; - } - } - - if (!converted) - { - VariantHolder ret; - VariantHolder vOp; - - VARENUM vt = CVtoVT((CVTypes) cvType); - ToOAVariant(source, &vOp); - - HRESULT hr = SafeVariantChangeTypeEx(&ret, &vOp, lcid, flags, static_cast(vt)); - - if (FAILED(hr)) - OAFailed(hr); - - if ((CVTypes) cvType == CV_CHAR) - { - result->SetType(CV_CHAR); - result->SetDataAsUInt16(V_UI2(&ret)); - } - else - { - FromOAVariant(&ret, result); - } - } - - END_QCALL; -} - -#endif // FEATURE_COMINTEROP diff --git a/src/coreclr/classlibnative/bcltype/oavariant.h b/src/coreclr/classlibnative/bcltype/oavariant.h deleted file mode 100644 index 2ee4de551b69..000000000000 --- a/src/coreclr/classlibnative/bcltype/oavariant.h +++ /dev/null @@ -1,18 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// File: OAVariant.h -// - -#ifndef _OAVARIANT_H_ -#define _OAVARIANT_H_ - -#ifndef FEATURE_COMINTEROP -#error FEATURE_COMINTEROP is required for this file -#endif // FEATURE_COMINTEROP - -#include "olevariant.h" - -extern "C" void QCALLTYPE OAVariant_ChangeType(VariantData* result, VariantData* source, LCID lcid, void* targetType, int cvType, INT16 flags); - -#endif // _OAVARIANT_H_ diff --git a/src/coreclr/classlibnative/bcltype/variant.cpp b/src/coreclr/classlibnative/bcltype/variant.cpp index a269644d7970..1a3cf7e75bb4 100644 --- a/src/coreclr/classlibnative/bcltype/variant.cpp +++ b/src/coreclr/classlibnative/bcltype/variant.cpp @@ -20,6 +20,7 @@ #include "vars.hpp" #include "variant.h" #include "string.h" + #include "field.h" // The following values are used to represent underlying @@ -286,4 +287,35 @@ int COMVariant::GetEnumFlags(TypeHandle th) } } +extern "C" uint32_t QCALLTYPE Variant_ConvertSystemColorToOleColor(QCall::ObjectHandleOnStack obj) +{ + QCALL_CONTRACT; + + uint32_t ret = 0; + + BEGIN_QCALL; + + GCX_COOP(); + OBJECTREF srcObj = obj.Get(); + ret = ConvertSystemColorToOleColor(&srcObj); + + END_QCALL; + + return ret; +} + +extern "C" void QCALLTYPE Variant_ConvertOleColorToSystemColor(QCall::ObjectHandleOnStack objRet, uint32_t oleColor, MethodTable* pMT) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + GCX_COOP(); + SYSTEMCOLOR systemColor{}; + ConvertOleColorToSystemColor(oleColor, &systemColor); + objRet.Set(pMT->Box(&systemColor)); + + END_QCALL; +} + #endif // FEATURE_COMINTEROP diff --git a/src/coreclr/classlibnative/bcltype/variant.h b/src/coreclr/classlibnative/bcltype/variant.h index aae0a5f9741a..12c5a3d36d53 100644 --- a/src/coreclr/classlibnative/bcltype/variant.h +++ b/src/coreclr/classlibnative/bcltype/variant.h @@ -40,5 +40,8 @@ class COMVariant static int GetEnumFlags(TypeHandle th); }; +extern "C" uint32_t QCALLTYPE Variant_ConvertSystemColorToOleColor(QCall::ObjectHandleOnStack obj); +extern "C" void QCALLTYPE Variant_ConvertOleColorToSystemColor(QCall::ObjectHandleOnStack objRet, uint32_t oleColor, MethodTable* pMT); + #endif // _VARIANT_H_ diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index a739bc6660f6..831f133cd2bc 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -16,6 +16,7 @@ elseif (CLR_CMAKE_TARGET_ARCH_ARM) add_definitions(-DFEATURE_EMULATE_SINGLESTEP) elseif (CLR_CMAKE_TARGET_ARCH_RISCV64) add_definitions(-DFEATURE_EMULATE_SINGLESTEP) + add_compile_definitions($<$>>:FEATURE_MULTIREG_RETURN>) endif (CLR_CMAKE_TARGET_ARCH_ARM64) if (CLR_CMAKE_TARGET_UNIX) @@ -41,7 +42,6 @@ if(CLR_CMAKE_TARGET_LINUX_MUSL) add_definitions(-DNO_FIXED_STACK_LIMIT) endif(CLR_CMAKE_TARGET_LINUX_MUSL) -add_definitions(-D_BLD_CLR) add_definitions(-DDEBUGGING_SUPPORTED) add_compile_definitions($<$>>:PROFILING_SUPPORTED>) add_compile_definitions($<$>:PROFILING_SUPPORTED_DATA>) @@ -222,7 +222,7 @@ if (NOT CLR_CMAKE_TARGET_ARCH_I386 OR NOT CLR_CMAKE_TARGET_WIN32) add_compile_definitions($<$>>:FEATURE_EH_FUNCLETS>) endif (NOT CLR_CMAKE_TARGET_ARCH_I386 OR NOT CLR_CMAKE_TARGET_WIN32) -if (CLR_CMAKE_TARGET_WIN32 AND CLR_CMAKE_TARGET_ARCH_AMD64) +if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64)) add_definitions(-DFEATURE_SPECIAL_USER_MODE_APC) endif() diff --git a/src/coreclr/debug/createdump/crashinfo.cpp b/src/coreclr/debug/createdump/crashinfo.cpp index 93e0111376f1..72c27bd38ee4 100644 --- a/src/coreclr/debug/createdump/crashinfo.cpp +++ b/src/coreclr/debug/createdump/crashinfo.cpp @@ -927,6 +927,17 @@ CrashInfo::SearchMemoryRegions(const std::set& regions, const Memo return nullptr; } +// Declare the prototype for the Itanium C++ ABI demangler API. +// We may not have the Itanium C++ ABI header available even when we're building against this ABI +// so we'll declare the prototype ourselves. +// See Itanium C++ ABI, March 14, 2017 Revision, Chapter 3, Section 3.4 +namespace abi { + extern "C" char* __cxa_demangle (const char* mangled_name, + char* buf, + size_t* n, + int* status); +} + // // Lookup a symbol in a module. The caller needs to call "free()" on symbol returned. // diff --git a/src/coreclr/debug/createdump/createdump.h b/src/coreclr/debug/createdump/createdump.h index 4095a5693794..bb385f6acdde 100644 --- a/src/coreclr/debug/createdump/createdump.h +++ b/src/coreclr/debug/createdump/createdump.h @@ -72,7 +72,6 @@ typedef int T_CONTEXT; #include #include #include -#include #ifdef __APPLE__ #include #else diff --git a/src/coreclr/debug/daccess/CMakeLists.txt b/src/coreclr/debug/daccess/CMakeLists.txt index 5332e957c9ec..9ed71521d428 100644 --- a/src/coreclr/debug/daccess/CMakeLists.txt +++ b/src/coreclr/debug/daccess/CMakeLists.txt @@ -1,5 +1,7 @@ add_definitions(-DFEATURE_NO_HOST) +add_subdirectory(${CLR_SRC_NATIVE_DIR}/managed/cdacreader/cmake ${CLR_ARTIFACTS_OBJ_DIR}/cdacreader) + include_directories(BEFORE ${VM_DIR}) include_directories(BEFORE ${VM_DIR}/${ARCH_SOURCES_DIR}) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}) @@ -12,6 +14,7 @@ if(CLR_CMAKE_HOST_UNIX) endif(CLR_CMAKE_HOST_UNIX) set(DACCESS_SOURCES + cdac.cpp dacdbiimpl.cpp dacdbiimpllocks.cpp dacdbiimplstackwalk.cpp @@ -40,6 +43,7 @@ convert_to_absolute_path(DACCESS_SOURCES ${DACCESS_SOURCES}) add_library_clr(daccess ${DACCESS_SOURCES}) set_target_properties(daccess PROPERTIES DAC_COMPONENT TRUE) target_precompile_headers(daccess PRIVATE [["stdafx.h"]]) +target_link_libraries(daccess PRIVATE cdacreader_api) add_dependencies(daccess eventing_headers) diff --git a/src/coreclr/debug/daccess/cdac.cpp b/src/coreclr/debug/daccess/cdac.cpp new file mode 100644 index 000000000000..b7bb7585e6bc --- /dev/null +++ b/src/coreclr/debug/daccess/cdac.cpp @@ -0,0 +1,88 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "cdac.h" +#include +#include +#include "dbgutil.h" +#include + +#define CDAC_LIB_NAME MAKEDLLNAME_W(W("cdacreader")) + +namespace +{ + bool TryLoadCDACLibrary(HMODULE *phCDAC) + { + // Load cdacreader from next to DAC binary + PathString path; + if (FAILED(GetClrModuleDirectory(path))) + return false; + + path.Append(CDAC_LIB_NAME); + *phCDAC = CLRLoadLibrary(path.GetUnicode()); + if (*phCDAC == NULL) + return false; + + return true; + } + + int ReadFromTargetCallback(uint64_t addr, uint8_t* dest, uint32_t count, void* context) + { + ICorDebugDataTarget* target = reinterpret_cast(context); + HRESULT hr = ReadFromDataTarget(target, addr, dest, count); + if (FAILED(hr)) + return hr; + + return S_OK; + } +} + +CDAC CDAC::Create(uint64_t descriptorAddr, ICorDebugDataTarget* target) +{ + HMODULE cdacLib; + if (!TryLoadCDACLibrary(&cdacLib)) + return {}; + + decltype(&cdac_reader_init) init = reinterpret_cast(::GetProcAddress(cdacLib, "cdac_reader_init")); + _ASSERTE(init != nullptr); + + intptr_t handle; + if (init(descriptorAddr, &ReadFromTargetCallback, target, &handle) != 0) + { + ::FreeLibrary(cdacLib); + return {}; + } + + return CDAC{cdacLib, handle, target}; +} + +CDAC::CDAC(HMODULE module, intptr_t handle, ICorDebugDataTarget* target) + : m_module{module} + , m_cdac_handle{handle} + , m_target{target} +{ + _ASSERTE(m_module != NULL && m_cdac_handle != 0 && m_target != NULL); + + m_target->AddRef(); + decltype(&cdac_reader_get_sos_interface) getSosInterface = reinterpret_cast(::GetProcAddress(m_module, "cdac_reader_get_sos_interface")); + _ASSERTE(getSosInterface != nullptr); + getSosInterface(m_cdac_handle, &m_sos); +} + +CDAC::~CDAC() +{ + if (m_cdac_handle) + { + decltype(&cdac_reader_free) free = reinterpret_cast(::GetProcAddress(m_module, "cdac_reader_free")); + _ASSERTE(free != nullptr); + free(m_cdac_handle); + } + + if (m_module != NULL) + ::FreeLibrary(m_module); +} + +IUnknown* CDAC::SosInterface() +{ + return m_sos; +} diff --git a/src/coreclr/debug/daccess/cdac.h b/src/coreclr/debug/daccess/cdac.h new file mode 100644 index 000000000000..51078ffcf2e4 --- /dev/null +++ b/src/coreclr/debug/daccess/cdac.h @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef CDAC_H +#define CDAC_H + +class CDAC final +{ +public: // static + static CDAC Create(uint64_t descriptorAddr, ICorDebugDataTarget *pDataTarget); + +public: + CDAC() = default; + + CDAC(const CDAC&) = delete; + CDAC& operator=(const CDAC&) = delete; + + CDAC(CDAC&& other) + : m_module{ other.m_module } + , m_cdac_handle{ other.m_cdac_handle } + , m_target{ other.m_target.Extract() } + , m_sos{ other.m_sos.Extract() } + { + other.m_module = NULL; + other.m_cdac_handle = 0; + other.m_target = NULL; + other.m_sos = NULL; + } + + CDAC& operator=(CDAC&& other) + { + m_module = other.m_module; + m_cdac_handle = other.m_cdac_handle; + m_target = other.m_target.Extract(); + m_sos = other.m_sos.Extract(); + + other.m_module = NULL; + other.m_cdac_handle = 0; + other.m_target = NULL; + other.m_sos = NULL; + + return *this; + } + + ~CDAC(); + + bool IsValid() const + { + return m_module != NULL && m_cdac_handle != 0; + } + + // This does not AddRef the returned interface + IUnknown* SosInterface(); + +private: + CDAC(HMODULE module, intptr_t handle, ICorDebugDataTarget* target); + +private: + HMODULE m_module; + intptr_t m_cdac_handle; + NonVMComHolder m_target; + NonVMComHolder m_sos; +}; + +#endif // CDAC_H diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index d6b8d99d7c37..09c41e2c84bf 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -23,11 +23,15 @@ #include "dwreport.h" #include "primitives.h" #include "dbgutil.h" +#include "cdac.h" +#include #ifdef USE_DAC_TABLE_RVA #include #else extern "C" bool TryGetSymbol(ICorDebugDataTarget* dataTarget, uint64_t baseAddress, const char* symbolName, uint64_t* symbolAddress); +// cDAC depends on symbol lookup to find the contract descriptor +#define CAN_USE_CDAC #endif #include "dwbucketmanager.hpp" @@ -1748,7 +1752,7 @@ DacInstanceManager::Find(TADDR addr) { #if defined(DAC_MEASURE_PERF) - unsigned _int64 nStart, nEnd; + uint64_t nStart, nEnd; g_nFindCalls++; nStart = GetCycleCount(); #endif // #if defined(DAC_MEASURE_PERF) @@ -3034,6 +3038,7 @@ class DacStreamManager //---------------------------------------------------------------------------- ClrDataAccess::ClrDataAccess(ICorDebugDataTarget * pTarget, ICLRDataTarget * pLegacyTarget/*=0*/) + : m_cdac{} { SUPPORTS_DAC_HOST_ONLY; // ctor does no marshalling - don't check with DacCop @@ -3123,7 +3128,6 @@ ClrDataAccess::ClrDataAccess(ICorDebugDataTarget * pTarget, ICLRDataTarget * pLe // see ClrDataAccess::VerifyDlls for details. m_fEnableDllVerificationAsserts = false; #endif - } ClrDataAccess::~ClrDataAccess(void) @@ -4324,7 +4328,7 @@ ClrDataAccess::TranslateExceptionRecordToNotification( GcEvtArgs pubGcEvtArgs = {}; ULONG32 notifyType = 0; DWORD catcherNativeOffset = 0; - TADDR nativeCodeLocation = NULL; + TADDR nativeCodeLocation = (TADDR)NULL; DAC_ENTER(); @@ -4706,7 +4710,7 @@ ClrDataAccess::SetAllCodeNotifications( BOOL changedTable; TADDR modulePtr = mod ? PTR_HOST_TO_TADDR(((ClrDataModule*)mod)->GetModule()) : - NULL; + (TADDR)NULL; if (jn.SetAllNotifications(modulePtr, (USHORT)flags, &changedTable)) { @@ -4822,7 +4826,7 @@ ClrDataAccess::GetCodeNotifications( } else { - TADDR modulePtr = NULL; + TADDR modulePtr = (TADDR)NULL; if (singleMod) { modulePtr = PTR_HOST_TO_TADDR(((ClrDataModule*)singleMod)-> @@ -4908,7 +4912,7 @@ ClrDataAccess::SetCodeNotifications( goto Exit; } - TADDR modulePtr = NULL; + TADDR modulePtr = (TADDR)NULL; if (singleMod) { modulePtr = @@ -5491,6 +5495,30 @@ ClrDataAccess::Initialize(void) IfFailRet(GetDacGlobalValues()); IfFailRet(DacGetHostVtPtrs()); +// TODO: [cdac] TryGetSymbol is only implemented for Linux, OSX, and Windows. +#ifdef CAN_USE_CDAC + CLRConfigNoCache enable = CLRConfigNoCache::Get("ENABLE_CDAC"); + if (enable.IsSet()) + { + DWORD val; + if (enable.TryAsInteger(10, val) && val == 1) + { + uint64_t contractDescriptorAddr = 0; + if (TryGetSymbol(m_pTarget, m_globalBase, "DotNetRuntimeContractDescriptor", &contractDescriptorAddr)) + { + m_cdac = CDAC::Create(contractDescriptorAddr, m_pTarget); + if (m_cdac.IsValid()) + { + // Get SOS interfaces from the cDAC if available. + IUnknown* unk = m_cdac.SosInterface(); + (void)unk->QueryInterface(__uuidof(ISOSDacInterface), (void**)&m_cdacSos); + (void)unk->QueryInterface(__uuidof(ISOSDacInterface9), (void**)&m_cdacSos9); + } + } + } + } +#endif + // // DAC is now setup and ready to use // @@ -5952,10 +5980,10 @@ ClrDataAccess::GetMethodVarInfo(MethodDesc* methodDesc, COUNT_T countNativeVarInfo; NewHolder nativeVars(NULL); TADDR nativeCodeStartAddr; - if (address != NULL) + if (address != (TADDR)NULL) { NativeCodeVersion requestedNativeCodeVersion = ExecutionManager::GetNativeCodeVersion(address); - if (requestedNativeCodeVersion.IsNull() || requestedNativeCodeVersion.GetNativeCode() == NULL) + if (requestedNativeCodeVersion.IsNull() || requestedNativeCodeVersion.GetNativeCode() == (PCODE)NULL) { return E_INVALIDARG; } @@ -6010,10 +6038,10 @@ ClrDataAccess::GetMethodNativeMap(MethodDesc* methodDesc, // Use the DebugInfoStore to get IL->Native maps. // It doesn't matter whether we're jitted, ngenned etc. TADDR nativeCodeStartAddr; - if (address != NULL) + if (address != (TADDR)NULL) { NativeCodeVersion requestedNativeCodeVersion = ExecutionManager::GetNativeCodeVersion(address); - if (requestedNativeCodeVersion.IsNull() || requestedNativeCodeVersion.GetNativeCode() == NULL) + if (requestedNativeCodeVersion.IsNull() || requestedNativeCodeVersion.GetNativeCode() == (PCODE)NULL) { return E_INVALIDARG; } @@ -6922,7 +6950,7 @@ GetDacTableAddress(ICorDebugDataTarget* dataTarget, ULONG64 baseAddress, PULONG6 return E_INVALIDARG; } #endif - // On MacOS, FreeBSD or NetBSD use the RVA include file + // On FreeBSD, NetBSD, or SunOS use the RVA include file *dacTableAddress = baseAddress + DAC_TABLE_RVA; #else // Otherwise, try to get the dac table address via the export symbol @@ -6947,7 +6975,7 @@ ClrDataAccess::GetDacGlobalValues() { return CORDBG_E_MISSING_DEBUGGER_EXPORTS; } - if (m_dacGlobals.ThreadStore__s_pThreadStore == NULL) + if (m_dacGlobals.ThreadStore__s_pThreadStore == (TADDR)NULL) { return CORDBG_E_UNSUPPORTED; } @@ -7746,6 +7774,8 @@ void CALLBACK DacHandleWalker::EnumCallback(PTR_UNCHECKED_OBJECTREF handle, uint data.Type = param->Type; if (param->Type == HNDTYPE_DEPENDENT) data.Secondary = GetDependentHandleSecondary(handle.GetAddr()).GetAddr(); + else if (param->Type == HNDTYPE_WEAK_INTERIOR_POINTER) + data.Secondary = TO_CDADDR(HndGetHandleExtraInfo(handle.GetAddr())); else data.Secondary = 0; data.AppDomain = param->AppDomain; diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index d1a0a1ada64d..715c87dedafe 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -1240,7 +1240,7 @@ mdSignature DacDbiInterfaceImpl::GetILCodeAndSigHelper(Module * pModule, pIL->cbSize = header.GetCodeSize(); // Now we get the signature token - if (header.LocalVarSigTok != NULL) + if (header.LocalVarSigTok != mdTokenNil) { mdSig = header.GetLocalVarSigTok(); } @@ -1314,14 +1314,14 @@ void DacDbiInterfaceImpl::GetMethodRegionInfo(MethodDesc * pMethodDe } CONTRACTL_END; - IJitManager::MethodRegionInfo methodRegionInfo = {NULL, 0, NULL, 0}; + IJitManager::MethodRegionInfo methodRegionInfo = {(TADDR)NULL, 0, (TADDR)NULL, 0}; PCODE functionAddress = pMethodDesc->GetNativeCode(); // get the start address of the hot region and initialize the jit manager pCodeInfo->m_rgCodeRegions[kHot].pAddress = CORDB_ADDRESS(PCODEToPINSTR(functionAddress)); // if the start address is NULL, the code isn't available yet, so just return - if (functionAddress != NULL) + if (functionAddress != (PCODE)NULL) { EECodeInfo codeInfo(functionAddress); _ASSERTE(codeInfo.IsValid()); @@ -1372,7 +1372,7 @@ void DacDbiInterfaceImpl::GetNativeCodeInfo(VMPTR_DomainAssembly vmDomai if(pMethodDesc != NULL) { GetMethodRegionInfo(pMethodDesc, pCodeInfo); - if (pCodeInfo->m_rgCodeRegions[kHot].pAddress != NULL) + if (pCodeInfo->m_rgCodeRegions[kHot].pAddress != (CORDB_ADDRESS)NULL) { pCodeInfo->isInstantiatedGeneric = pMethodDesc->HasClassOrMethodInstantiation(); LookupEnCVersions(pModule, @@ -1397,14 +1397,14 @@ void DacDbiInterfaceImpl::GetNativeCodeInfoForAddr(VMPTR_MethodDesc vmMe _ASSERTE(pCodeInfo != NULL); - if (hotCodeStartAddr == NULL) + if (hotCodeStartAddr == (CORDB_ADDRESS)NULL) { // if the start address is NULL, the code isn't available yet, so just return _ASSERTE(!pCodeInfo->IsValid()); return; } - IJitManager::MethodRegionInfo methodRegionInfo = {NULL, 0, NULL, 0}; + IJitManager::MethodRegionInfo methodRegionInfo = {(TADDR)NULL, 0, (TADDR)NULL, 0}; TADDR codeAddr = CORDB_ADDRESS_TO_TADDR(hotCodeStartAddr); #ifdef TARGET_ARM @@ -1655,7 +1655,7 @@ void DacDbiInterfaceImpl::ComputeFieldData(PTR_FieldDesc pFD, if (pCurrentFieldData->OkToGetOrSetStaticAddress()) { - pCurrentFieldData->SetStaticAddress(NULL); + pCurrentFieldData->SetStaticAddress((TADDR)NULL); } } else @@ -3192,7 +3192,7 @@ CORDB_ADDRESS DacDbiInterfaceImpl::GetThreadStaticAddress(VMPTR_FieldDesc vmFiel Thread * pRuntimeThread = vmRuntimeThread.GetDacPtr(); PTR_FieldDesc pFieldDesc = vmField.GetDacPtr(); - TADDR fieldAddress = NULL; + TADDR fieldAddress = (TADDR)NULL; _ASSERTE(pRuntimeThread != NULL); @@ -3441,7 +3441,7 @@ HRESULT DacDbiInterfaceImpl::GetDelegateType(VMPTR_Object delegateObject, Delega PTR_Object pInvocationList = OBJECTREFToObject(pDelObj->GetInvocationList()); - if (invocationCount == NULL) + if (invocationCount == 0) { if (pInvocationList == NULL) { @@ -3449,7 +3449,7 @@ HRESULT DacDbiInterfaceImpl::GetDelegateType(VMPTR_Object delegateObject, Delega // Special case: This might fail in a VSD delegate (instance open virtual)... // TODO: There is the special signatures cases missing. TADDR targetMethodPtr = PCODEToPINSTR(pDelObj->GetMethodPtrAux()); - if (targetMethodPtr == NULL) + if (targetMethodPtr == (TADDR)NULL) { // Static extension methods, other closed static delegates, and instance delegates fall into this category. *delegateType = kClosedDelegate; @@ -3501,7 +3501,7 @@ HRESULT DacDbiInterfaceImpl::GetDelegateFunctionData( HRESULT hr = S_OK; PTR_DelegateObject pDelObj = dac_cast(delegateObject.GetDacPtr()); - TADDR targetMethodPtr = NULL; + TADDR targetMethodPtr = (TADDR)NULL; VMPTR_MethodDesc pMD; switch (delegateType) @@ -3552,7 +3552,7 @@ HRESULT DacDbiInterfaceImpl::GetDelegateTargetObject( } default: - ppTargetObj->SetDacTargetPtr(NULL); + ppTargetObj->SetDacTargetPtr((TADDR)NULL); break; } @@ -4388,7 +4388,7 @@ void DacDbiInterfaceImpl::GetModuleData(VMPTR_Module vmModule, ModuleInfo * pDat // Get PE BaseAddress and Size // For dynamic modules, these are 0. Else, - pData->pPEBaseAddress = NULL; + pData->pPEBaseAddress = (CORDB_ADDRESS)NULL; pData->nPESize = 0; if (!fIsDynamic) @@ -4765,7 +4765,7 @@ BOOL DacDbiInterfaceImpl::HasUnhandledException(VMPTR_Thread vmThread) // most managed exceptions are just a throwable bound to a // native exception. In that case this handle will be non-null OBJECTHANDLE ohException = pThread->GetThrowableAsHandle(); - if (ohException != NULL) + if (ohException != (OBJECTHANDLE)NULL) { // during the UEF we set the unhandled bit, if it is set the exception // was unhandled @@ -4854,7 +4854,7 @@ VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetCurrentException(VMPTR_Thread vmThrea // OBJECTHANDLEs are really just TADDRs. OBJECTHANDLE ohException = pThread->GetThrowableAsHandle(); // ohException can be NULL - if (ohException == NULL) + if (ohException == (OBJECTHANDLE)NULL) { if (pThread->IsLastThrownObjectUnhandled()) { @@ -4872,7 +4872,7 @@ VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetObjectForCCW(CORDB_ADDRESS ccwPtr) { DD_ENTER_MAY_THROW; - OBJECTHANDLE ohCCW = NULL; + OBJECTHANDLE ohCCW = (OBJECTHANDLE)NULL; #ifdef FEATURE_COMWRAPPERS if (DACTryGetComWrappersHandleFromCCW(ccwPtr, &ohCCW) != S_OK) @@ -4922,12 +4922,7 @@ VMPTR_AppDomain DacDbiInterfaceImpl::GetCurrentAppDomain(VMPTR_Thread vmThread) DD_ENTER_MAY_THROW; Thread * pThread = vmThread.GetDacPtr(); - AppDomain * pAppDomain = pThread->GetDomain(); - - if (pAppDomain == NULL) - { - ThrowHR(E_FAIL); - } + AppDomain * pAppDomain = AppDomain::GetCurrentDomain(); VMPTR_AppDomain vmAppDomain = VMPTR_AppDomain::NullPtr(); vmAppDomain.SetDacTargetPtr(PTR_HOST_TO_TADDR(pAppDomain)); @@ -4963,13 +4958,13 @@ CLR_DEBUGGING_PROCESS_FLAGS DacDbiInterfaceImpl::GetAttachStateFlags() // Non-null Target Address of hijack function. TADDR DacDbiInterfaceImpl::GetHijackAddress() { - TADDR addr = NULL; + TADDR addr = (TADDR)NULL; if (g_pDebugger != NULL) { // Get the start address of the redirect function for unhandled exceptions. addr = dac_cast(g_pDebugger->m_rgHijackFunction[Debugger::kUnhandledException].StartAddress()); } - if (addr == NULL) + if (addr == (TADDR)NULL) { ThrowHR(CORDBG_E_NOTREADY); } @@ -5209,8 +5204,8 @@ void DacDbiInterfaceImpl::Hijack( // space used by the OS exception dispatcher. We are using the latter approach here. // - CORDB_ADDRESS espOSContext = NULL; - CORDB_ADDRESS espOSRecord = NULL; + CORDB_ADDRESS espOSContext = (CORDB_ADDRESS)NULL; + CORDB_ADDRESS espOSRecord = (CORDB_ADDRESS)NULL; if (pThread != NULL && pThread->IsExceptionInProgress()) { espOSContext = (CORDB_ADDRESS)PTR_TO_TADDR(pThread->GetExceptionState()->GetContextRecord()); @@ -5360,10 +5355,10 @@ TargetBuffer DacDbiInterfaceImpl::GetVarArgSig(CORDB_ADDRESS VASigCookieAddr, DD_ENTER_MAY_THROW; _ASSERTE(pArgBase != NULL); - *pArgBase = NULL; + *pArgBase = (CORDB_ADDRESS)NULL; // First, read the VASigCookie pointer. - TADDR taVASigCookie = NULL; + TADDR taVASigCookie = (TADDR)NULL; SafeReadStructOrThrow(VASigCookieAddr, &taVASigCookie); // Now create a DAC copy of VASigCookie. @@ -5665,7 +5660,7 @@ CORDB_ADDRESS DacDbiInterfaceImpl::GetDebuggerControlBlockAddress() return CORDB_ADDRESS(dac_cast(g_pDebugger->m_pRCThread->GetDCB())); } - return NULL; + return (CORDB_ADDRESS)NULL; } // DacDbi API: Get the context for a particular thread of the target process @@ -6541,7 +6536,7 @@ HRESULT DacHeapWalker::Init(CORDB_ADDRESS start, CORDB_ADDRESS end) if (ctx == NULL) continue; - if ((CORDB_ADDRESS)ctx->alloc_ptr != NULL) + if ((CORDB_ADDRESS)ctx->alloc_ptr != (CORDB_ADDRESS)NULL) { mAllocInfo[j].Ptr = (CORDB_ADDRESS)ctx->alloc_ptr; mAllocInfo[j].Limit = (CORDB_ADDRESS)ctx->alloc_limit; @@ -6856,7 +6851,7 @@ HRESULT DacDbiInterfaceImpl::WalkHeap(HeapWalkHandle handle, { objects[i].address = addr; objects[i].type.token1 = mt; - objects[i].type.token2 = NULL; + objects[i].type.token2 = 0; objects[i].size = size; i++; } @@ -7477,7 +7472,7 @@ HRESULT DacDbiInterfaceImpl::GetDefinesBitField(ULONG32 *pDefines) if (g_pDebugger == NULL) return CORDBG_E_NOTREADY; - + *pDefines = g_pDebugger->m_defines; return S_OK; } diff --git a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp index 0707a7253699..4ccaa7a5fa76 100644 --- a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp +++ b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp @@ -505,7 +505,7 @@ void DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread Thread * pThread = vmThread.GetDacPtr(); Frame * pFrame = pThread->GetFrame(); - AppDomain * pAppDomain = pThread->GetDomain(INDEBUG(TRUE)); + AppDomain * pAppDomain = AppDomain::GetCurrentDomain(); // This used to be only true for Enter-Managed chains. // Since we don't have chains anymore, this can always be false. @@ -589,7 +589,7 @@ void DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread } else { - frameData.stubFrame.funcMetadataToken = (pMD == NULL ? NULL : pMD->GetMemberDef()); + frameData.stubFrame.funcMetadataToken = (pMD == NULL ? mdTokenNil : pMD->GetMemberDef()); frameData.stubFrame.vmDomainAssembly.SetHostPtr(pDomainAssembly); frameData.stubFrame.vmMethodDesc.SetHostPtr(pMD); } @@ -832,7 +832,7 @@ void DacDbiInterfaceImpl::InitFrameData(StackFrameIterator * pIter, } else { - pFrameData->v.exactGenericArgsToken = NULL; + pFrameData->v.exactGenericArgsToken = (GENERICS_TYPE_TOKEN)NULL; pFrameData->v.dwExactGenericArgsTokenIndex = (DWORD)ICorDebugInfo::MAX_ILNUM; } @@ -1249,7 +1249,7 @@ void DacDbiInterfaceImpl::UpdateContextFromRegDisp(REGDISPLAY * pRegDisp, PTR_CONTEXT DacDbiInterfaceImpl::RetrieveHijackedContext(REGDISPLAY * pRD) { - CORDB_ADDRESS ContextPointerAddr = NULL; + CORDB_ADDRESS ContextPointerAddr = (CORDB_ADDRESS)NULL; TADDR controlPC = PCODEToPINSTR(GetControlPC(pRD)); diff --git a/src/coreclr/debug/daccess/dacfn.cpp b/src/coreclr/debug/daccess/dacfn.cpp index c3131e2d571e..2c9f28481d21 100644 --- a/src/coreclr/debug/daccess/dacfn.cpp +++ b/src/coreclr/debug/daccess/dacfn.cpp @@ -154,7 +154,7 @@ DacReadAll(TADDR addr, PVOID buffer, ULONG32 size, bool throwEx) ULONG32 returned; #if defined(DAC_MEASURE_PERF) - unsigned __int64 nStart, nEnd; + uint64_t nStart, nEnd; nStart = GetCycleCount(); #endif // #if defined(DAC_MEASURE_PERF) @@ -1525,7 +1525,7 @@ HRESULT DacReplacePatchesInHostMemory(MemoryRange range, PVOID pBuffer) { CORDB_ADDRESS patchAddress = (CORDB_ADDRESS)dac_cast(pPatch->address); - if (patchAddress != NULL) + if (patchAddress != (CORDB_ADDRESS)NULL) { PRD_TYPE opcode = pPatch->opcode; diff --git a/src/coreclr/debug/daccess/dacimpl.h b/src/coreclr/debug/daccess/dacimpl.h index e698eed4c180..8b1771d7132e 100644 --- a/src/coreclr/debug/daccess/dacimpl.h +++ b/src/coreclr/debug/daccess/dacimpl.h @@ -794,6 +794,7 @@ class DacStreamManager; #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS +#include "cdac.h" //---------------------------------------------------------------------------- // @@ -1208,7 +1209,7 @@ class ClrDataAccess CLRDATA_ADDRESS *allocLimit); // ISOSDacInterface13 - virtual HRESULT STDMETHODCALLTYPE TraverseLoaderHeap(CLRDATA_ADDRESS loaderHeapAddr, LoaderHeapKind kind, VISITHEAP pCallback); + virtual HRESULT STDMETHODCALLTYPE TraverseLoaderHeap(CLRDATA_ADDRESS loaderHeapAddr, LoaderHeapKind kind, VISITHEAP pCallback); virtual HRESULT STDMETHODCALLTYPE GetDomainLoaderAllocator(CLRDATA_ADDRESS domainAddress, CLRDATA_ADDRESS *pLoaderAllocator); virtual HRESULT STDMETHODCALLTYPE GetLoaderAllocatorHeapNames(int count, const char **ppNames, int *pNeeded); virtual HRESULT STDMETHODCALLTYPE GetLoaderAllocatorHeaps(CLRDATA_ADDRESS loaderAllocator, int count, CLRDATA_ADDRESS *pLoaderHeaps, LoaderHeapKind *pKinds, int *pNeeded); @@ -1221,13 +1222,15 @@ class ClrDataAccess virtual HRESULT STDMETHODCALLTYPE GetStaticBaseAddress(CLRDATA_ADDRESS methodTable, CLRDATA_ADDRESS *nonGCStaticsAddress, CLRDATA_ADDRESS *GCStaticsAddress); virtual HRESULT STDMETHODCALLTYPE GetThreadStaticBaseAddress(CLRDATA_ADDRESS methodTable, CLRDATA_ADDRESS thread, CLRDATA_ADDRESS *nonGCStaticsAddress, CLRDATA_ADDRESS *GCStaticsAddress); virtual HRESULT STDMETHODCALLTYPE GetMethodTableInitializationFlags(CLRDATA_ADDRESS methodTable, MethodTableInitializationFlags *initializationStatus); - + // // ClrDataAccess. // HRESULT Initialize(void); + HRESULT GetThreadStoreDataImpl(struct DacpThreadStoreData *data); + BOOL IsExceptionFromManagedCode(EXCEPTION_RECORD * pExceptionRecord); #ifndef TARGET_UNIX HRESULT GetWatsonBuckets(DWORD dwThreadId, GenericModeBlock * pGM); @@ -1414,6 +1417,10 @@ class ClrDataAccess ULONG32 m_instanceAge; bool m_debugMode; + CDAC m_cdac; + NonVMComHolder m_cdacSos; + NonVMComHolder m_cdacSos9; + #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS protected: @@ -1964,7 +1971,7 @@ class DacMemoryEnumerator : public DefaultCOMImplGetNativeCode(); - if (addr != NULL) + if (addr != (PCODE)NULL) { EECodeInfo codeInfo(addr); if (codeInfo.IsValid()) { - IJitManager::MethodRegionInfo methodRegionInfo = { NULL, 0, NULL, 0 }; + IJitManager::MethodRegionInfo methodRegionInfo = { (TADDR)NULL, 0, (TADDR)NULL, 0 }; codeInfo.GetMethodRegionInfo(&methodRegionInfo); } } @@ -764,7 +764,7 @@ HRESULT ClrDataAccess::EnumMemWalkStackHelper(CLRDataEnumMemoryFlags flags, #if defined(DAC_MEASURE_PERF) g_nStackWalk = 1; - unsigned __int64 nStart= GetCycleCount(); + uint64_t nStart= GetCycleCount(); #endif HRESULT status = S_OK; @@ -785,7 +785,7 @@ HRESULT ClrDataAccess::EnumMemWalkStackHelper(CLRDataEnumMemoryFlags flags, { bool frameHadContext = false; status = pStackWalk->GetFrame(&pFrame); - PCODE addr = NULL; + PCODE addr = (PCODE)NULL; if (status == S_OK && pFrame != NULL) { // write out the code that ip pointed to @@ -917,7 +917,7 @@ HRESULT ClrDataAccess::EnumMemWalkStackHelper(CLRDataEnumMemoryFlags flags, // This method has a generic type token which is required to figure out the exact instantiation // of the method. // We need to use the variable index of the generic type token in order to do the look up. - CLRDATA_ADDRESS address = NULL; + CLRDATA_ADDRESS address = (CLRDATA_ADDRESS)NULL; DWORD dwExactGenericArgsTokenIndex = 0; ReleaseHolder pDV(NULL); ReleaseHolder pAssociatedValue(NULL); @@ -955,7 +955,7 @@ HRESULT ClrDataAccess::EnumMemWalkStackHelper(CLRDataEnumMemoryFlags flags, #if defined(FEATURE_EH_FUNCLETS) && defined(USE_GC_INFO_DECODER) - if (addr != NULL) + if (addr != (PCODE)NULL) { EECodeInfo codeInfo(addr); @@ -997,7 +997,7 @@ HRESULT ClrDataAccess::EnumMemWalkStackHelper(CLRDataEnumMemoryFlags flags, EX_END_CATCH(RethrowCancelExceptions) #if defined(DAC_MEASURE_PERF) - unsigned __int64 nEnd = GetCycleCount(); + uint64_t nEnd = GetCycleCount(); g_nStackTotalTime += nEnd - nStart; g_nStackWalk = 0; #endif // #if defined(DAC_MEASURE_PERF) @@ -1961,8 +1961,8 @@ ClrDataAccess::EnumMemoryRegions(IN ICLRDataEnumMemoryRegionsCallback* callback, g_nFindStackTotalTime = 0; LARGE_INTEGER nClockFrequency; - unsigned __int64 nStart = 0; - unsigned __int64 nEnd = 0; + uint64_t nStart = 0; + uint64_t nEnd = 0; QueryPerformanceFrequency(&nClockFrequency); diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index dea3b8544ab9..4657aadf2296 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -38,6 +38,8 @@ typedef DPTR(InteropLib::ABI::ManagedObjectWrapperLayout) PTR_ManagedObjectWrapp #include "rejit.h" #include "request_common.h" +#include "cdac.h" + // GC headers define these to EE-specific stuff that we don't want. #undef EnterCriticalSection #undef LeaveCriticalSection @@ -67,13 +69,13 @@ typedef DPTR(InteropLib::ABI::ManagedObjectWrapperLayout) PTR_ManagedObjectWrapp TADDR DACGetMethodTableFromObjectPointer(TADDR objAddr, ICorDebugDataTarget * target) { ULONG32 returned = 0; - TADDR Value = NULL; + TADDR Value = (TADDR)NULL; HRESULT hr = target->ReadVirtual(objAddr, (PBYTE)&Value, sizeof(TADDR), &returned); if ((hr != S_OK) || (returned != sizeof(TADDR))) { - return NULL; + return (TADDR)NULL; } #if TARGET_64BIT @@ -88,7 +90,7 @@ TADDR DACGetMethodTableFromObjectPointer(TADDR objAddr, ICorDebugDataTarget * ta PTR_SyncBlock DACGetSyncBlockFromObjectPointer(TADDR objAddr, ICorDebugDataTarget * target) { ULONG32 returned = 0; - DWORD Value = NULL; + DWORD Value = 0; HRESULT hr = target->ReadVirtual(objAddr - sizeof(DWORD), (PBYTE)&Value, sizeof(DWORD), &returned); @@ -299,31 +301,64 @@ HRESULT ClrDataAccess::GetThreadStoreData(struct DacpThreadStoreData *threadStor { SOSDacEnter(); - ThreadStore* threadStore = ThreadStore::s_pThreadStore; - if (!threadStore) + if (m_cdacSos != NULL) { - hr = E_UNEXPECTED; + // Try the cDAC first - it will return E_NOTIMPL if it doesn't support this method yet. Fall back to the DAC. + hr = m_cdacSos->GetThreadStoreData(threadStoreData); + if (FAILED(hr)) + { + hr = GetThreadStoreDataImpl(threadStoreData); + } +#ifdef _DEBUG + else + { + // Assert that the data is the same as what we get from the DAC. + DacpThreadStoreData threadStoreDataLocal; + HRESULT hrLocal = GetThreadStoreDataImpl(&threadStoreDataLocal); + _ASSERTE(hr == hrLocal); + _ASSERTE(threadStoreData->threadCount == threadStoreDataLocal.threadCount); + _ASSERTE(threadStoreData->unstartedThreadCount == threadStoreDataLocal.unstartedThreadCount); + _ASSERTE(threadStoreData->backgroundThreadCount == threadStoreDataLocal.backgroundThreadCount); + _ASSERTE(threadStoreData->pendingThreadCount == threadStoreDataLocal.pendingThreadCount); + _ASSERTE(threadStoreData->deadThreadCount == threadStoreDataLocal.deadThreadCount); + _ASSERTE(threadStoreData->fHostConfig == threadStoreDataLocal.fHostConfig); + _ASSERTE(threadStoreData->firstThread == threadStoreDataLocal.firstThread); + _ASSERTE(threadStoreData->finalizerThread == threadStoreDataLocal.finalizerThread); + _ASSERTE(threadStoreData->gcThread == threadStoreDataLocal.gcThread); + } +#endif } else { - // initialize the fields of our local structure - threadStoreData->threadCount = threadStore->m_ThreadCount; - threadStoreData->unstartedThreadCount = threadStore->m_UnstartedThreadCount; - threadStoreData->backgroundThreadCount = threadStore->m_BackgroundThreadCount; - threadStoreData->pendingThreadCount = threadStore->m_PendingThreadCount; - threadStoreData->deadThreadCount = threadStore->m_DeadThreadCount; - threadStoreData->fHostConfig = FALSE; - - // identify the "important" threads - threadStoreData->firstThread = HOST_CDADDR(threadStore->m_ThreadList.GetHead()); - threadStoreData->finalizerThread = HOST_CDADDR(g_pFinalizerThread); - threadStoreData->gcThread = HOST_CDADDR(g_pSuspensionThread); + hr = GetThreadStoreDataImpl(threadStoreData); } SOSDacLeave(); return hr; } +HRESULT ClrDataAccess::GetThreadStoreDataImpl(struct DacpThreadStoreData *threadStoreData) +{ + ThreadStore* threadStore = ThreadStore::s_pThreadStore; + if (!threadStore) + return E_UNEXPECTED; + + // initialize the fields of our local structure + threadStoreData->threadCount = threadStore->m_ThreadCount; + threadStoreData->unstartedThreadCount = threadStore->m_UnstartedThreadCount; + threadStoreData->backgroundThreadCount = threadStore->m_BackgroundThreadCount; + threadStoreData->pendingThreadCount = threadStore->m_PendingThreadCount; + threadStoreData->deadThreadCount = threadStore->m_DeadThreadCount; + threadStoreData->fHostConfig = FALSE; + + // identify the "important" threads + threadStoreData->firstThread = HOST_CDADDR(threadStore->m_ThreadList.GetHead()); + threadStoreData->finalizerThread = HOST_CDADDR(g_pFinalizerThread); + threadStoreData->gcThread = HOST_CDADDR(g_pSuspensionThread); + + return S_OK; +} + HRESULT ClrDataAccess::GetStressLogAddress(CLRDATA_ADDRESS *stressLog) { @@ -414,7 +449,7 @@ ClrDataAccess::GetMethodTableSlot(CLRDATA_ADDRESS mt, unsigned int slot, CLRDATA HRESULT ClrDataAccess::GetCodeHeapList(CLRDATA_ADDRESS jitManager, unsigned int count, struct DacpJitCodeHeapInfo codeHeaps[], unsigned int *pNeeded) { - if (jitManager == NULL) + if (jitManager == (CLRDATA_ADDRESS)NULL) return E_INVALIDARG; SOSDacEnter(); @@ -743,16 +778,16 @@ ClrDataAccess::GetThreadData(CLRDATA_ADDRESS threadAddr, struct DacpThreadData * threadData->allocContextPtr = TO_CDADDR(thread->m_alloc_context.alloc_ptr); threadData->allocContextLimit = TO_CDADDR(thread->m_alloc_context.alloc_limit); - threadData->fiberData = NULL; + threadData->fiberData = (CLRDATA_ADDRESS)NULL; threadData->pFrame = PTR_CDADDR(thread->m_pFrame); - threadData->context = PTR_CDADDR(thread->m_pDomain); - threadData->domain = PTR_CDADDR(thread->m_pDomain); + threadData->context = PTR_CDADDR(AppDomain::GetCurrentDomain()); + threadData->domain = PTR_CDADDR(AppDomain::GetCurrentDomain()); threadData->lockCount = (DWORD)-1; #ifndef TARGET_UNIX threadData->teb = TO_CDADDR(thread->m_pTEB); #else - threadData->teb = NULL; + threadData->teb = (CLRDATA_ADDRESS)NULL; #endif threadData->lastThrownObjectHandle = TO_CDADDR(thread->m_LastThrownObjectHandle); @@ -868,7 +903,7 @@ HRESULT ClrDataAccess::GetMethodDescData( *pcNeededRevertedRejitData = 0; NativeCodeVersion requestedNativeCodeVersion, activeNativeCodeVersion; - if (ip != NULL) + if (ip != (CLRDATA_ADDRESS)NULL) { requestedNativeCodeVersion = ExecutionManager::GetNativeCodeVersion(CLRDATA_ADDRESS_TO_TADDR(ip)); } @@ -885,7 +920,7 @@ HRESULT ClrDataAccess::GetMethodDescData( methodDescData->requestedIP = ip; methodDescData->bIsDynamic = (pMD->IsLCGMethod()) ? TRUE : FALSE; methodDescData->wSlotNumber = pMD->GetSlot(); - if (!requestedNativeCodeVersion.IsNull() && requestedNativeCodeVersion.GetNativeCode() != NULL) + if (!requestedNativeCodeVersion.IsNull() && requestedNativeCodeVersion.GetNativeCode() != (PCODE)NULL) { methodDescData->bHasNativeCode = TRUE; methodDescData->NativeCodeAddr = TO_CDADDR(PCODEToPINSTR(requestedNativeCodeVersion.GetNativeCode())); @@ -895,7 +930,7 @@ HRESULT ClrDataAccess::GetMethodDescData( methodDescData->bHasNativeCode = FALSE; methodDescData->NativeCodeAddr = (CLRDATA_ADDRESS)-1; } - methodDescData->AddressOfNativeCodeSlot = pMD->HasNativeCodeSlot() ? TO_CDADDR(dac_cast(pMD->GetAddrOfNativeCodeSlot())) : NULL; + methodDescData->AddressOfNativeCodeSlot = pMD->HasNativeCodeSlot() ? TO_CDADDR(dac_cast(pMD->GetAddrOfNativeCodeSlot())) : (CLRDATA_ADDRESS)NULL; methodDescData->MDToken = pMD->GetMemberDef(); methodDescData->MethodDescPtr = methodDesc; methodDescData->MethodTablePtr = HOST_CDADDR(pMD->GetMethodTable()); @@ -929,7 +964,7 @@ HRESULT ClrDataAccess::GetMethodDescData( // Requested ReJitInfo _ASSERTE(methodDescData->rejitDataRequested.rejitID == 0); - if (ip != NULL && !requestedNativeCodeVersion.IsNull()) + if (ip != (CLRDATA_ADDRESS)NULL && !requestedNativeCodeVersion.IsNull()) { CopyNativeCodeVersionToReJitData( requestedNativeCodeVersion, @@ -1091,8 +1126,8 @@ HRESULT ClrDataAccess::GetTieredVersions( goto cleanup; } - TADDR r2rImageBase = NULL; - TADDR r2rImageEnd = NULL; + TADDR r2rImageBase = (TADDR)NULL; + TADDR r2rImageEnd = (TADDR)NULL; { PTR_Module pModule = (PTR_Module)pMD->GetModule(); if (pModule->IsReadyToRun()) @@ -1221,10 +1256,10 @@ ClrDataAccess::GetCodeHeaderData(CLRDATA_ADDRESS ip, struct DacpCodeHeaderData * { codeHeaderData->MethodDescPtr = HOST_CDADDR(methodDescI); codeHeaderData->JITType = TYPE_UNKNOWN; - codeHeaderData->GCInfo = NULL; - codeHeaderData->MethodStart = NULL; + codeHeaderData->GCInfo = (CLRDATA_ADDRESS)NULL; + codeHeaderData->MethodStart = (CLRDATA_ADDRESS)NULL; codeHeaderData->MethodSize = 0; - codeHeaderData->ColdRegionStart = NULL; + codeHeaderData->ColdRegionStart = (CLRDATA_ADDRESS)NULL; } } else @@ -1239,7 +1274,7 @@ ClrDataAccess::GetCodeHeaderData(CLRDATA_ADDRESS ip, struct DacpCodeHeaderData * _ASSERTE(FitsIn(methodSize)); codeHeaderData->MethodSize = static_cast(methodSize); - IJitManager::MethodRegionInfo methodRegionInfo = {NULL, 0, NULL, 0}; + IJitManager::MethodRegionInfo methodRegionInfo = {(TADDR)NULL, 0, (TADDR)NULL, 0}; codeInfo.GetMethodRegionInfo(&methodRegionInfo); codeHeaderData->HotRegionSize = (DWORD) methodRegionInfo.hotSize; @@ -1261,7 +1296,7 @@ ClrDataAccess::GetMethodDescPtrFromFrame(CLRDATA_ADDRESS frameAddr, CLRDATA_ADDR Frame *pFrame = PTR_Frame(TO_TADDR(frameAddr)); CLRDATA_ADDRESS methodDescAddr = HOST_CDADDR(pFrame->GetFunction()); - if ((methodDescAddr == NULL) || !DacValidateMD(PTR_MethodDesc(TO_TADDR(methodDescAddr)))) + if ((methodDescAddr == (CLRDATA_ADDRESS)NULL) || !DacValidateMD(PTR_MethodDesc(TO_TADDR(methodDescAddr)))) { hr = E_INVALIDARG; } @@ -1292,7 +1327,7 @@ ClrDataAccess::GetMethodDescPtrFromIP(CLRDATA_ADDRESS ip, CLRDATA_ADDRESS * ppMD else { CLRDATA_ADDRESS pMD = HOST_CDADDR(codeInfo.GetMethodDesc()); - if ((pMD == NULL) || !DacValidateMD(PTR_MethodDesc(TO_TADDR(pMD)))) + if ((pMD == (CLRDATA_ADDRESS)NULL) || !DacValidateMD(PTR_MethodDesc(TO_TADDR(pMD)))) { hr = E_INVALIDARG; } @@ -1475,7 +1510,7 @@ ClrDataAccess::GetObjectClassName(CLRDATA_ADDRESS obj, unsigned int count, _Inou // scans of the gc heap. PTR_MethodTable mt = NULL; TADDR mtTADDR = DACGetMethodTableFromObjectPointer(CLRDATA_ADDRESS_TO_TADDR(obj), m_pTarget); - if (mtTADDR != NULL) + if (mtTADDR != (TADDR)NULL) mt = PTR_MethodTable(mtTADDR); else hr = E_INVALIDARG; @@ -1834,12 +1869,12 @@ ClrDataAccess::GetFieldDescData(CLRDATA_ADDRESS addr, struct DacpFieldDescData * } else { - FieldDescData->MTOfType = NULL; + FieldDescData->MTOfType = (CLRDATA_ADDRESS)NULL; } } EX_CATCH { - FieldDescData->MTOfType = NULL; + FieldDescData->MTOfType = (CLRDATA_ADDRESS)NULL; } EX_END_CATCH(SwallowAllExceptions) @@ -1864,7 +1899,7 @@ ClrDataAccess::GetFieldDescData(CLRDATA_ADDRESS addr, struct DacpFieldDescData * { // There is no encoded token of field type FieldDescData->TokenOfType = mdTypeDefNil; - if (FieldDescData->MTOfType == NULL) + if (FieldDescData->MTOfType == (CLRDATA_ADDRESS)NULL) { // If there is no encoded token (that is, it is primitive type) and no MethodTable for it, remember the // element_type from signature @@ -2100,7 +2135,7 @@ ClrDataAccess::GetPEFileBase(CLRDATA_ADDRESS addr, CLRDATA_ADDRESS *base) if (!pPEAssembly->IsDynamic()) *base = TO_CDADDR(pPEAssembly->GetIJWBase()); else - *base = NULL; + *base = (CLRDATA_ADDRESS)NULL; SOSDacLeave(); return hr; @@ -2112,7 +2147,7 @@ DWORD DACGetNumComponents(TADDR addr, ICorDebugDataTarget* target) // array components. addr+=sizeof(size_t); ULONG32 returned = 0; - DWORD Value = NULL; + DWORD Value = 0; HRESULT hr = target->ReadVirtual(addr, (PBYTE)&Value, sizeof(DWORD), &returned); if ((hr != S_OK) || (returned != sizeof(DWORD))) @@ -2132,7 +2167,7 @@ ClrDataAccess::GetObjectData(CLRDATA_ADDRESS addr, struct DacpObjectData *object ZeroMemory (objectData, sizeof(DacpObjectData)); TADDR mtTADDR = DACGetMethodTableFromObjectPointer(CLRDATA_ADDRESS_TO_TADDR(addr),m_pTarget); - if (mtTADDR==NULL) + if (mtTADDR==(TADDR)NULL) hr = E_INVALIDARG; BOOL bFree = FALSE; @@ -2261,7 +2296,7 @@ ClrDataAccess::GetAppDomainStoreData(struct DacpAppDomainStoreData *adsData) SOSDacEnter(); adsData->systemDomain = HOST_CDADDR(SystemDomain::System()); - adsData->sharedDomain = NULL; + adsData->sharedDomain = (CLRDATA_ADDRESS)NULL; // Get an accurate count of appdomains. adsData->DomainCount = 0; @@ -2332,7 +2367,7 @@ ClrDataAccess::GetAppDomainData(CLRDATA_ADDRESS addr, struct DacpAppDomainData * HRESULT ClrDataAccess::GetFailedAssemblyData(CLRDATA_ADDRESS assembly, unsigned int *pContext, HRESULT *pResult) { - if (assembly == NULL || (pContext == NULL && pResult == NULL)) + if (assembly == (CLRDATA_ADDRESS)NULL || (pContext == NULL && pResult == NULL)) { return E_INVALIDARG; } @@ -2358,7 +2393,7 @@ HRESULT ClrDataAccess::GetFailedAssemblyLocation(CLRDATA_ADDRESS assembly, unsigned int count, _Inout_updates_z_(count) WCHAR *location, unsigned int *pNeeded) { - if (assembly == NULL || (location == NULL && pNeeded == NULL) || (location != NULL && count == 0)) + if (assembly == (CLRDATA_ADDRESS)NULL || (location == NULL && pNeeded == NULL) || (location != NULL && count == 0)) return E_INVALIDARG; SOSDacEnter(); @@ -2377,7 +2412,7 @@ ClrDataAccess::GetFailedAssemblyLocation(CLRDATA_ADDRESS assembly, unsigned int HRESULT ClrDataAccess::GetFailedAssemblyDisplayName(CLRDATA_ADDRESS assembly, unsigned int count, _Inout_updates_z_(count) WCHAR *name, unsigned int *pNeeded) { - if (assembly == NULL || (name == NULL && pNeeded == NULL) || (name != NULL && count == 0)) + if (assembly == (CLRDATA_ADDRESS)NULL || (name == NULL && pNeeded == NULL) || (name != NULL && count == 0)) return E_INVALIDARG; SOSDacEnter(); @@ -2407,7 +2442,7 @@ ClrDataAccess::GetFailedAssemblyDisplayName(CLRDATA_ADDRESS assembly, unsigned i HRESULT ClrDataAccess::GetAssemblyList(CLRDATA_ADDRESS addr, int count, CLRDATA_ADDRESS values[], int *pNeeded) { - if (addr == NULL) + if (addr == (CLRDATA_ADDRESS)NULL) return E_INVALIDARG; SOSDacEnter(); @@ -2459,7 +2494,7 @@ HRESULT ClrDataAccess::GetFailedAssemblyList(CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[], unsigned int *pNeeded) { - if ((appDomain == NULL) || (values == NULL && pNeeded == NULL)) + if ((appDomain == (CLRDATA_ADDRESS)NULL) || (values == NULL && pNeeded == NULL)) { return E_INVALIDARG; } @@ -2554,7 +2589,7 @@ ClrDataAccess::GetAppDomainConfigFile(CLRDATA_ADDRESS appDomain, int count, HRESULT ClrDataAccess::GetAssemblyData(CLRDATA_ADDRESS cdBaseDomainPtr, CLRDATA_ADDRESS assembly, struct DacpAssemblyData *assemblyData) { - if (assembly == NULL && cdBaseDomainPtr == NULL) + if (assembly == (CLRDATA_ADDRESS)NULL && cdBaseDomainPtr == (CLRDATA_ADDRESS)NULL) { return E_INVALIDARG; } @@ -2568,7 +2603,7 @@ ClrDataAccess::GetAssemblyData(CLRDATA_ADDRESS cdBaseDomainPtr, CLRDATA_ADDRESS // If the specified BaseDomain is an AppDomain, get a pointer to it AppDomain * pDomain = NULL; - if (cdBaseDomainPtr != NULL) + if (cdBaseDomainPtr != (CLRDATA_ADDRESS)NULL) { assemblyData->BaseDomainPtr = cdBaseDomainPtr; PTR_BaseDomain baseDomain = PTR_BaseDomain(TO_TADDR(cdBaseDomainPtr)); @@ -2636,7 +2671,7 @@ ClrDataAccess::GetAssemblyName(CLRDATA_ADDRESS assembly, unsigned int count, _In HRESULT ClrDataAccess::GetAssemblyLocation(CLRDATA_ADDRESS assembly, int count, _Inout_updates_z_(count) WCHAR *location, unsigned int *pNeeded) { - if ((assembly == NULL) || (location == NULL && pNeeded == NULL) || (location != NULL && count == 0)) + if ((assembly == (CLRDATA_ADDRESS)NULL) || (location == NULL && pNeeded == NULL) || (location != NULL && count == 0)) { return E_INVALIDARG; } @@ -2721,7 +2756,7 @@ ClrDataAccess::GetGCHeapStaticData(struct DacpGcHeapDetails *detailsData) SOSDacEnter(); - detailsData->heapAddr = NULL; + detailsData->heapAddr = (CLRDATA_ADDRESS)NULL; detailsData->lowest_address = PTR_CDADDR(g_lowest_address); detailsData->highest_address = PTR_CDADDR(g_highest_address); @@ -2825,7 +2860,7 @@ ClrDataAccess::GetHeapSegmentData(CLRDATA_ADDRESS seg, struct DacpHeapSegmentDat heapSegment->mem = (CLRDATA_ADDRESS)(ULONG_PTR) pSegment->mem; heapSegment->next = (CLRDATA_ADDRESS)dac_cast(pSegment->next); heapSegment->flags = pSegment->flags; - heapSegment->gc_heap = NULL; + heapSegment->gc_heap = (CLRDATA_ADDRESS)NULL; heapSegment->background_allocated = (CLRDATA_ADDRESS)(ULONG_PTR)pSegment->background_allocated; if (seg == (CLRDATA_ADDRESS)*g_gcDacGlobals->ephemeral_heap_segment) @@ -3255,7 +3290,7 @@ ClrDataAccess::GetThreadLocalModuleData(CLRDATA_ADDRESS thread, unsigned int ind HRESULT ClrDataAccess::GetHandleEnum(ISOSHandleEnum **ppHandleEnum) { unsigned int types[] = {HNDTYPE_WEAK_SHORT, HNDTYPE_WEAK_LONG, HNDTYPE_STRONG, HNDTYPE_PINNED, HNDTYPE_DEPENDENT, - HNDTYPE_SIZEDREF, + HNDTYPE_SIZEDREF, HNDTYPE_WEAK_INTERIOR_POINTER, #if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS) || defined(FEATURE_OBJCMARSHAL) HNDTYPE_REFCOUNTED, #endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS || FEATURE_OBJCMARSHAL @@ -3736,7 +3771,7 @@ ClrDataAccess::GetSyncBlockCleanupData(CLRDATA_ADDRESS syncBlock, struct DacpSyn ZeroMemory (syncBlockCData, sizeof(DacpSyncBlockCleanupData)); SyncBlock *pBlock = NULL; - if (syncBlock == NULL && SyncBlockCache::s_pSyncBlockCache->m_pCleanupBlockList) + if (syncBlock == (CLRDATA_ADDRESS)NULL && SyncBlockCache::s_pSyncBlockCache->m_pCleanupBlockList) { pBlock = (SyncBlock *) PTR_SyncBlock( PTR_HOST_TO_TADDR(SyncBlockCache::s_pSyncBlockCache->m_pCleanupBlockList) - offsetof(SyncBlock, m_Link)); @@ -4235,7 +4270,7 @@ BOOL ClrDataAccess::DACGetComWrappersCCWVTableQIAddress(CLRDATA_ADDRESS ccwPtr, HRESULT hr = S_OK; ULONG32 bytesRead = 0; TADDR ccw = CLRDATA_ADDRESS_TO_TADDR(ccwPtr); - *vTableAddress = NULL; + *vTableAddress = (TADDR)NULL; if (FAILED(m_pTarget->ReadVirtual(ccw, (PBYTE)vTableAddress, sizeof(TADDR), &bytesRead)) || bytesRead != sizeof(TADDR) || vTableAddress == NULL) @@ -4243,7 +4278,7 @@ BOOL ClrDataAccess::DACGetComWrappersCCWVTableQIAddress(CLRDATA_ADDRESS ccwPtr, return FALSE; } - *qiAddress = NULL; + *qiAddress = (TADDR)NULL; if (FAILED(m_pTarget->ReadVirtual(*vTableAddress, (PBYTE)qiAddress, sizeof(TADDR), &bytesRead)) || bytesRead != sizeof(TADDR) || qiAddress == NULL) @@ -4262,8 +4297,8 @@ BOOL ClrDataAccess::DACGetComWrappersCCWVTableQIAddress(CLRDATA_ADDRESS ccwPtr, BOOL ClrDataAccess::DACIsComWrappersCCW(CLRDATA_ADDRESS ccwPtr) { - TADDR vTableAddress = NULL; - TADDR qiAddress = NULL; + TADDR vTableAddress = (TADDR)NULL; + TADDR qiAddress = (TADDR)NULL; if (!DACGetComWrappersCCWVTableQIAddress(ccwPtr, &vTableAddress, &qiAddress)) { return FALSE; @@ -4277,7 +4312,7 @@ TADDR ClrDataAccess::DACGetManagedObjectWrapperFromCCW(CLRDATA_ADDRESS ccwPtr) { if (!DACIsComWrappersCCW(ccwPtr)) { - return NULL; + return (TADDR)NULL; } ULONG32 bytesRead = 0; @@ -4286,7 +4321,7 @@ TADDR ClrDataAccess::DACGetManagedObjectWrapperFromCCW(CLRDATA_ADDRESS ccwPtr) if (FAILED(m_pTarget->ReadVirtual(managedObjectWrapperPtrPtr, (PBYTE)&managedObjectWrapperPtr, sizeof(TADDR), &bytesRead)) || bytesRead != sizeof(TADDR)) { - return NULL; + return (TADDR)NULL; } return managedObjectWrapperPtr; @@ -4299,7 +4334,7 @@ HRESULT ClrDataAccess::DACTryGetComWrappersHandleFromCCW(CLRDATA_ADDRESS ccwPtr, ULONG32 bytesRead = 0; OBJECTHANDLE handle; - if (ccwPtr == 0 || objHandle == NULL) + if (ccwPtr == 0 || objHandle == 0) { hr = E_INVALIDARG; goto ErrExit; @@ -4315,7 +4350,7 @@ HRESULT ClrDataAccess::DACTryGetComWrappersHandleFromCCW(CLRDATA_ADDRESS ccwPtr, // Return ManagedObjectWrapper as an OBJECTHANDLE. (The OBJECTHANDLE is guaranteed to live at offset 0). managedObjectWrapperPtr = DACGetManagedObjectWrapperFromCCW(ccwPtr); - if (managedObjectWrapperPtr == NULL) + if (managedObjectWrapperPtr == (TADDR)NULL) { hr = E_FAIL; goto ErrExit; @@ -4382,7 +4417,7 @@ HRESULT ClrDataAccess::GetCCWData(CLRDATA_ADDRESS ccw, struct DacpCCWData *ccwDa ccwData->isExtendsCOMObject = pCCW->GetSimpleWrapper()->IsExtendsCOMObject(); ccwData->isAggregated = pCCW->GetSimpleWrapper()->IsAggregated(); - if (pCCW->GetObjectHandle() != NULL) + if (pCCW->GetObjectHandle() != (OBJECTHANDLE)NULL) ccwData->managedObject = PTR_CDADDR(ObjectFromHandle(pCCW->GetObjectHandle())); // count the number of COM vtables @@ -4535,7 +4570,7 @@ HRESULT ClrDataAccess::GetClrNotification(CLRDATA_ADDRESS arguments[], int count *pNeeded = MAX_CLR_NOTIFICATION_ARGS; - if (g_clrNotificationArguments[0] == NULL) + if (g_clrNotificationArguments[0] == (CLRDATA_ADDRESS)NULL) { hr = E_FAIL; } @@ -4645,7 +4680,7 @@ HRESULT ClrDataAccess::GetProfilerModifiedILInformation(CLRDATA_ADDRESS methodDe pILData->type = DacpProfilerILData::Unmodified; pILData->rejitID = 0; - pILData->il = NULL; + pILData->il = (CLRDATA_ADDRESS)NULL; PTR_MethodDesc pMD = PTR_MethodDesc(TO_TADDR(methodDesc)); CodeVersionManager* pCodeVersionManager = pMD->GetCodeVersionManager(); @@ -4658,7 +4693,7 @@ HRESULT ClrDataAccess::GetProfilerModifiedILInformation(CLRDATA_ADDRESS methodDe } TADDR pDynamicIL = pMD->GetModule()->GetDynamicIL(pMD->GetMemberDef()); - if (pDynamicIL != NULL) + if (pDynamicIL != (TADDR)NULL) { pILData->type = DacpProfilerILData::ILModified; pILData->il = (CLRDATA_ADDRESS)pDynamicIL; @@ -4701,7 +4736,7 @@ HRESULT ClrDataAccess::GetMethodsWithProfilerModifiedIL(CLRDATA_ADDRESS mod, CLR TADDR pDynamicIL = pModule->GetDynamicIL(pMD->GetMemberDef()); ILCodeVersion ilVersion = pCodeVersionManager->GetActiveILCodeVersion(pMD); - if (ilVersion.GetRejitState() != ILCodeVersion::kStateActive || !ilVersion.HasDefaultIL() || pDynamicIL != NULL) + if (ilVersion.GetRejitState() != ILCodeVersion::kStateActive || !ilVersion.HasDefaultIL() || pDynamicIL != (TADDR)NULL) { methodDescs[*pcMethodDescs] = PTR_CDADDR(pMD); ++(*pcMethodDescs); @@ -4824,7 +4859,7 @@ HRESULT ClrDataAccess::GetFinalizationFillPointers(unsigned int cFillPointers, C HRESULT ClrDataAccess::GetGenerationTableSvr(CLRDATA_ADDRESS heapAddr, unsigned int cGenerations, struct DacpGenerationData *pGenerationData, unsigned int *pNeeded) { - if (heapAddr == NULL || (cGenerations > 0 && pGenerationData == NULL)) + if (heapAddr == (CLRDATA_ADDRESS)NULL || (cGenerations > 0 && pGenerationData == NULL)) { return E_INVALIDARG; } @@ -4874,7 +4909,7 @@ HRESULT ClrDataAccess::GetGenerationTableSvr(CLRDATA_ADDRESS heapAddr, unsigned HRESULT ClrDataAccess::GetFinalizationFillPointersSvr(CLRDATA_ADDRESS heapAddr, unsigned int cFillPointers, CLRDATA_ADDRESS *pFinalizationFillPointers, unsigned int *pNeeded) { - if (heapAddr == NULL || (cFillPointers > 0 && pFinalizationFillPointers == NULL)) + if (heapAddr == (CLRDATA_ADDRESS)NULL || (cFillPointers > 0 && pFinalizationFillPointers == NULL)) { return E_INVALIDARG; } @@ -4951,7 +4986,15 @@ HRESULT ClrDataAccess::GetBreakingChangeVersion(int* pVersion) if (pVersion == nullptr) return E_INVALIDARG; - *pVersion = SOS_BREAKING_CHANGE_VERSION; + if (m_cdacSos9 != nullptr && SUCCEEDED(m_cdacSos9->GetBreakingChangeVersion(pVersion))) + { + _ASSERTE(*pVersion == SOS_BREAKING_CHANGE_VERSION); + } + else + { + *pVersion = SOS_BREAKING_CHANGE_VERSION; + } + return S_OK; } @@ -5052,7 +5095,7 @@ HRESULT ClrDataAccess::IsComWrappersCCW(CLRDATA_ADDRESS ccw, BOOL *isComWrappers if (isComWrappersCCW != NULL) { TADDR managedObjectWrapperPtr = DACGetManagedObjectWrapperFromCCW(ccw); - *isComWrappersCCW = managedObjectWrapperPtr != NULL; + *isComWrappersCCW = managedObjectWrapperPtr != (TADDR)NULL; hr = *isComWrappersCCW ? S_OK : S_FALSE; } @@ -5074,7 +5117,7 @@ HRESULT ClrDataAccess::GetComWrappersCCWData(CLRDATA_ADDRESS ccw, CLRDATA_ADDRES SOSDacEnter(); TADDR managedObjectWrapperPtr = DACGetManagedObjectWrapperFromCCW(ccw); - if (managedObjectWrapperPtr != NULL) + if (managedObjectWrapperPtr != (TADDR)NULL) { PTR_ManagedObjectWrapper pMOW(managedObjectWrapperPtr); @@ -5245,7 +5288,7 @@ HRESULT ClrDataAccess::IsTrackedType( SOSDacEnter(); TADDR mtTADDR = DACGetMethodTableFromObjectPointer(CLRDATA_ADDRESS_TO_TADDR(objAddr), m_pTarget); - if (mtTADDR==NULL) + if (mtTADDR==(TADDR)NULL) hr = E_INVALIDARG; BOOL bFree = FALSE; @@ -5280,7 +5323,7 @@ HRESULT ClrDataAccess::GetTaggedMemory( return E_INVALIDARG; } - *taggedMemory = NULL; + *taggedMemory = (TADDR)NULL; *taggedMemorySizeInBytes = 0; SOSDacEnter(); @@ -5406,10 +5449,10 @@ HRESULT STDMETHODCALLTYPE ClrDataAccess::GetStaticBaseAddress(CLRDATA_ADDRESS me { if (!nonGCStaticsAddress && !GCStaticsAddress) return E_POINTER; - + if (!methodTable) return E_INVALIDARG; - + SOSDacEnter(); PTR_MethodTable mTable = PTR_MethodTable(TO_TADDR(methodTable)); @@ -5440,13 +5483,13 @@ HRESULT STDMETHODCALLTYPE ClrDataAccess::GetThreadStaticBaseAddress(CLRDATA_ADDR { if (!nonGCStaticsAddress && !GCStaticsAddress) return E_POINTER; - + if (!methodTable) return E_INVALIDARG; if (!threadPtr) return E_INVALIDARG; - + SOSDacEnter(); PTR_MethodTable mTable = PTR_MethodTable(TO_TADDR(methodTable)); diff --git a/src/coreclr/debug/daccess/task.cpp b/src/coreclr/debug/daccess/task.cpp index b0215cdf780e..d878fae66897 100644 --- a/src/coreclr/debug/daccess/task.cpp +++ b/src/coreclr/debug/daccess/task.cpp @@ -121,16 +121,8 @@ ClrDataTask::GetCurrentAppDomain( EX_TRY { - if (m_thread->GetDomain()) - { - *appDomain = new (nothrow) - ClrDataAppDomain(m_dac, m_thread->GetDomain()); - status = *appDomain ? S_OK : E_OUTOFMEMORY; - } - else - { - status = E_INVALIDARG; - } + *appDomain = new (nothrow) ClrDataAppDomain(m_dac, AppDomain::GetCurrentDomain()); + status = *appDomain ? S_OK : E_OUTOFMEMORY; } EX_CATCH { @@ -549,7 +541,7 @@ ClrDataTask::GetLastExceptionState( { *exception = new (nothrow) ClrDataExceptionState(m_dac, - m_thread->GetDomain(), + AppDomain::GetCurrentDomain(), m_thread, CLRDATA_EXCEPTION_PARTIAL, NULL, @@ -4962,7 +4954,7 @@ ClrDataExceptionState::NewFromThread(ClrDataAccess* dac, exIf = new (nothrow) ClrDataExceptionState(dac, - thread->GetDomain(), + AppDomain::GetCurrentDomain(), thread, CLRDATA_EXCEPTION_DEFAULT, exState, @@ -5122,7 +5114,7 @@ EnumMethodDefinitions::CdStart(Module* mod, { HRESULT status; - *handle = NULL; + *handle = 0; if (!mod) { diff --git a/src/coreclr/debug/di/divalue.cpp b/src/coreclr/debug/di/divalue.cpp index 9645ee76526b..853bac550e45 100644 --- a/src/coreclr/debug/di/divalue.cpp +++ b/src/coreclr/debug/di/divalue.cpp @@ -458,7 +458,7 @@ HRESULT CordbValue::InternalCreateHandle(CorDebugHandleType handleType, true, m_appdomain->GetADToken()); - CORDB_ADDRESS addr = GetValueHome() != NULL ? GetValueHome()->GetAddress() : NULL; + CORDB_ADDRESS addr = GetValueHome() != NULL ? GetValueHome()->GetAddress() : (CORDB_ADDRESS)NULL; event.CreateHandle.objectToken = CORDB_ADDRESS_TO_PTR(addr); event.CreateHandle.handleType = handleType; @@ -546,7 +546,7 @@ CordbGenericValue::CordbGenericValue(CordbAppDomain * pAppdomain, // Arguments: // input: pType - the type of the value CordbGenericValue::CordbGenericValue(CordbType * pType) - : CordbValue(NULL, pType, NULL, true), + : CordbValue(NULL, pType, (CORDB_ADDRESS)NULL, true), m_pValueHome(NULL) { // The only purpose of a literal value is to hold a RS literal value. @@ -776,7 +776,7 @@ CordbReferenceValue::CordbReferenceValue(CordbAppDomain * pAppdomai // Arguments: // input: pType - the type of the value CordbReferenceValue::CordbReferenceValue(CordbType * pType) - : CordbValue(NULL, pType, NULL, true, pType->GetAppDomain()->GetSweepableExitNeuterList()) + : CordbValue(NULL, pType, (CORDB_ADDRESS)NULL, true, pType->GetAppDomain()->GetSweepableExitNeuterList()) { memset(&m_info, 0, sizeof(m_info)); @@ -905,7 +905,7 @@ HRESULT CordbReferenceValue::GetAddress(CORDB_ADDRESS *pAddress) PUBLIC_REENTRANT_API_ENTRY(this); VALIDATE_POINTER_TO_OBJECT(pAddress, CORDB_ADDRESS *); - *pAddress = m_valueHome.m_pHome ? m_valueHome.m_pHome->GetAddress() : NULL; + *pAddress = m_valueHome.m_pHome ? m_valueHome.m_pHome->GetAddress() : (CORDB_ADDRESS)NULL; return (S_OK); } @@ -940,7 +940,7 @@ HRESULT CordbReferenceValue::GetValue(CORDB_ADDRESS *pAddress) // Copy out the value, which is simply the value the object reference. if (m_isLiteral) - *pAddress = NULL; + *pAddress = (CORDB_ADDRESS)NULL; else *pAddress = PTR_TO_CORDB_ADDRESS(m_info.objRef); @@ -1840,6 +1840,10 @@ HRESULT CordbObjectValue::QueryInterface(REFIID id, void **pInterface) { *pInterface = static_cast(static_cast(this)); } + else if (id == IID_ICorDebugExceptionObjectValue2 && m_fIsExceptionObject) + { + *pInterface = static_cast(static_cast(this)); + } else if (id == IID_ICorDebugComObjectValue && m_fIsRcw) { *pInterface = static_cast(this); @@ -2489,6 +2493,41 @@ HRESULT CordbObjectValue::EnumerateExceptionCallStack(ICorDebugExceptionObjectCa return hr; } +HRESULT CordbObjectValue::ForceCatchHandlerFoundEvents(BOOL enableEvents) +{ + PUBLIC_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); + + HRESULT hr = S_OK; + + EX_TRY + { + CordbProcess * pProcess = GetProcess(); + + CORDB_ADDRESS objAddr = m_valueHome.GetAddress(); + + IDacDbiInterface* pDAC = GetProcess()->GetDAC(); + VMPTR_Object vmObj = pDAC->GetObject(objAddr); + + DebuggerIPCEvent event; + CordbAppDomain * pAppDomain = GetAppDomain(); + _ASSERTE (pAppDomain != NULL); + + pProcess->InitIPCEvent(&event, DB_IPCE_FORCE_CATCH_HANDLER_FOUND, true, pAppDomain->GetADToken()); + event.ForceCatchHandlerFoundData.enableEvents = enableEvents; + event.ForceCatchHandlerFoundData.vmObj = vmObj; + + hr = pProcess->m_cordb->SendIPCEvent(pProcess, &event, sizeof(DebuggerIPCEvent)); + + _ASSERTE(event.type == DB_IPCE_CATCH_HANDLER_FOUND_RESULT); + + hr = event.hr; + } + EX_CATCH_HRESULT(hr); + return hr; +} + HRESULT CordbObjectValue::IsExceptionObject() { HRESULT hr = S_OK; @@ -2501,7 +2540,7 @@ HRESULT CordbObjectValue::IsExceptionObject() { CORDB_ADDRESS objAddr = m_valueHome.GetAddress(); - if (objAddr == NULL) + if (objAddr == (CORDB_ADDRESS)NULL) { // object is a literal hr = S_FALSE; @@ -2533,7 +2572,7 @@ HRESULT CordbObjectValue::IsRcw() { CORDB_ADDRESS objAddr = m_valueHome.GetAddress(); - if (objAddr == NULL) + if (objAddr == (CORDB_ADDRESS)NULL) { // object is a literal hr = S_FALSE; @@ -2565,7 +2604,7 @@ HRESULT CordbObjectValue::IsDelegate() { CORDB_ADDRESS objAddr = m_valueHome.GetAddress(); - if (objAddr == NULL) + if (objAddr == (CORDB_ADDRESS)NULL) { // object is a literal hr = S_FALSE; @@ -4104,7 +4143,7 @@ CordbHandleValue::CordbHandleValue( CordbAppDomain * pAppdomain, CordbType * pType, // The type of object that we create handle on CorDebugHandleType handleType) // strong or weak handle - : CordbValue(pAppdomain, pType, NULL, false, + : CordbValue(pAppdomain, pType, (CORDB_ADDRESS)NULL, false, pAppdomain->GetSweepableExitNeuterList() ) { diff --git a/src/coreclr/debug/di/module.cpp b/src/coreclr/debug/di/module.cpp index 1f4216908637..d184206c08e3 100644 --- a/src/coreclr/debug/di/module.cpp +++ b/src/coreclr/debug/di/module.cpp @@ -526,9 +526,9 @@ void CordbModule::RefreshMetaData() // So far we've only got a reader for in-memory-writable metadata (MDInternalRW implementation) // We could make a reader for MDInternalRO, but no need yet. This also ensures we don't encroach into common // scenario where we can map a file on disk. - TADDR remoteMDInternalRWAddr = NULL; + TADDR remoteMDInternalRWAddr = (TADDR)NULL; GetProcess()->GetDAC()->GetPEFileMDInternalRW(m_vmPEFile, &remoteMDInternalRWAddr); - if (remoteMDInternalRWAddr != NULL) + if (remoteMDInternalRWAddr != (TADDR)NULL) { // we should only be doing this once to initialize, we don't support reopen with this technique _ASSERTE(m_pIMImport == NULL); @@ -4125,7 +4125,7 @@ HRESULT CordbNativeCode::GetAddress(CORDB_ADDRESS * pStart) // Since we don't do code-pitching, the address points directly to the code. *pStart = (m_rgCodeRegions[kHot].pAddress); - if (*pStart == NULL) + if (*pStart == (CORDB_ADDRESS)NULL) { return CORDBG_E_CODE_NOT_AVAILABLE; } @@ -4661,7 +4661,7 @@ int CordbNativeCode::GetCallInstructionLength(BYTE *ip, ULONG32 count) return -1; #elif defined(TARGET_AMD64) - BYTE rex = NULL; + BYTE rex = 0; BYTE prefix = *ip; BOOL fContainsPrefix = FALSE; @@ -4743,7 +4743,7 @@ int CordbNativeCode::GetCallInstructionLength(BYTE *ip, ULONG32 count) BYTE rex_x = 0; BYTE rex_r = 0; - if (rex != NULL) + if (rex != 0) { rex_b = (rex & 0x1); // high bit to modrm r/m field or SIB base field or OPCODE reg field -- Hmm, when which? rex_x = (rex & 0x2) >> 1; // high bit to sib index field @@ -4757,7 +4757,7 @@ int CordbNativeCode::GetCallInstructionLength(BYTE *ip, ULONG32 count) { BYTE modrm = *ip++; - _ASSERT(modrm != NULL); + _ASSERT(modrm != 0); BYTE mod = (modrm & 0xC0) >> 6; BYTE reg = (modrm & 0x38) >> 3; @@ -4788,7 +4788,7 @@ int CordbNativeCode::GetCallInstructionLength(BYTE *ip, ULONG32 count) // Get values from the SIB byte // BYTE sib = *ip; - _ASSERT(sib != NULL); + _ASSERT(sib != 0); BYTE base = (sib & 0x07); base |= (rex_b << 3); diff --git a/src/coreclr/debug/di/process.cpp b/src/coreclr/debug/di/process.cpp index 13aa3ec623e4..38c11c89127b 100644 --- a/src/coreclr/debug/di/process.cpp +++ b/src/coreclr/debug/di/process.cpp @@ -5318,7 +5318,7 @@ void CordbProcess::RawDispatchEvent( // if the class is NULL, that means the debugger never enabled notifications for it. Otherwise, // the CordbClass instance would already have been created when the notifications were // enabled. - if ((pNotificationClass != NULL) && pNotificationClass->CustomNotificationsEnabled()) + if (pNotificationClass != NULL) { PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent); @@ -6608,7 +6608,7 @@ HRESULT CordbProcess::ReadMemory(CORDB_ADDRESS address, VALIDATE_POINTER_TO_OBJECT_ARRAY(buffer, BYTE, size, true, true); VALIDATE_POINTER_TO_OBJECT(buffer, SIZE_T *); - if (address == NULL) + if (address == (CORDB_ADDRESS)NULL) return E_INVALIDARG; // If no read parameter is supplied, we ignore it. This matches the semantics of kernel32!ReadProcessMemory. @@ -6706,8 +6706,8 @@ HRESULT CordbProcess::AdjustBuffer( CORDB_ADDRESS address, _ASSERTE(m_initialized); _ASSERTE(this->ThreadHoldsProcessLock()); - if ( address == NULL - || size == NULL + if ( address == (CORDB_ADDRESS)NULL + || size == 0 || buffer == NULL || (mode != AB_READ && mode != AB_WRITE) ) return E_INVALIDARG; @@ -7167,7 +7167,7 @@ HRESULT CordbProcess::WriteMemory(CORDB_ADDRESS address, DWORD size, _ASSERTE(m_runtimeOffsetsInitialized); - if (size == 0 || address == NULL) + if (size == 0 || address == (CORDB_ADDRESS)NULL) return E_INVALIDARG; VALIDATE_POINTER_TO_OBJECT_ARRAY(buffer, BYTE, size, true, true); @@ -7500,9 +7500,9 @@ void CordbProcess::GetEventBlock(BOOL * pfBlockExists) // This is not technically necessary for Mac debugging. The event channel doesn't rely on // knowing the target address of the DCB on the LS. - CORDB_ADDRESS pLeftSideDCB = NULL; + CORDB_ADDRESS pLeftSideDCB = (CORDB_ADDRESS)NULL; pLeftSideDCB = (GetDAC()->GetDebuggerControlBlockAddress()); - if (pLeftSideDCB == NULL) + if (pLeftSideDCB == (CORDB_ADDRESS)NULL) { *pfBlockExists = false; ThrowHR(CORDBG_E_DEBUGGING_NOT_POSSIBLE); @@ -9746,7 +9746,7 @@ bool CordbProcess::CopyManagedEventFromTarget( // Determine if the event is really a debug event, and for our instance. CORDB_ADDRESS ptrRemoteManagedEvent = IsEventDebuggerNotification(pRecord, m_clrInstanceId); - if (ptrRemoteManagedEvent == NULL) + if (ptrRemoteManagedEvent == (CORDB_ADDRESS)NULL) { return false; } @@ -10734,6 +10734,7 @@ HRESULT CordbRCEventThread::WaitForIPCEventFromProcess(CordbProcess * pProcess, CordbAppDomain * pAppDomain, DebuggerIPCEvent * pEvent) { + CORDBRequireProcessStateOKAndSync(pProcess, pAppDomain); DWORD dwStatus; @@ -11413,14 +11414,37 @@ const EXCEPTION_RECORD * CordbProcess::ValidateExceptionRecord( HRESULT CordbProcess::SetEnableCustomNotification(ICorDebugClass * pClass, BOOL fEnable) { HRESULT hr = S_OK; - PUBLIC_API_BEGIN(this); // takes the lock + PUBLIC_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); ValidateOrThrow(pClass); - ((CordbClass *)pClass)->SetCustomNotifications(fEnable); + CordbProcess * pProcess = GetProcess(); + RSLockHolder lockHolder(pProcess->GetProcessLock()); - PUBLIC_API_END(hr); - return hr; + DebuggerIPCEvent event; + CordbClass *pCordbClass = static_cast(pClass); + _ASSERTE(pCordbClass != NULL); + CordbAppDomain * pAppDomain = pCordbClass->GetAppDomain(); + _ASSERTE (pAppDomain != NULL); + CordbModule *pModule = pCordbClass->GetModule(); + + pProcess->InitIPCEvent(&event, + DB_IPCE_SET_ENABLE_CUSTOM_NOTIFICATION, + true, + pAppDomain->GetADToken()); + event.CustomNotificationData.vmModule = pModule->GetRuntimeModule(); + event.CustomNotificationData.classMetadataToken = pCordbClass->MDToken(); + event.CustomNotificationData.Enabled = fEnable; + + lockHolder.Release(); + hr = pProcess->m_cordb->SendIPCEvent(pProcess, &event, sizeof(DebuggerIPCEvent)); + lockHolder.Acquire(); + + _ASSERTE(event.type == DB_IPCE_SET_ENABLE_CUSTOM_NOTIFICATION_RESULT); + + return event.hr; } // CordbProcess::SetEnableCustomNotification //--------------------------------------------------------------------------------------- @@ -14913,7 +14937,7 @@ HRESULT CordbProcess::GetReferenceValueFromGCHandle( EX_TRY { - if (gcHandle == NULL) + if (gcHandle == (UINT_PTR)0) { ThrowHR(CORDBG_E_BAD_REFERENCE_VALUE); } diff --git a/src/coreclr/debug/di/rsclass.cpp b/src/coreclr/debug/di/rsclass.cpp index 55f83b48a6d2..d60d1777de0b 100644 --- a/src/coreclr/debug/di/rsclass.cpp +++ b/src/coreclr/debug/di/rsclass.cpp @@ -34,8 +34,7 @@ CordbClass::CordbClass(CordbModule *m, mdTypeDef classMetadataToken) m_fIsValueClassKnown(false), m_fIsValueClass(false), m_fHasTypeParams(false), - m_continueCounterLastSync(0), - m_fCustomNotificationsEnabled(false) + m_continueCounterLastSync(0) { m_classInfo.Clear(); } @@ -237,7 +236,7 @@ HRESULT CordbClass::GetStaticFieldValue2(CordbModule * pModule, return CORDBG_E_FIELD_NOT_STATIC; } - CORDB_ADDRESS pRmtStaticValue = NULL; + CORDB_ADDRESS pRmtStaticValue = (CORDB_ADDRESS)NULL; CordbProcess * pProcess = pModule->GetProcess(); if (!pFieldData->m_fFldIsTLS) @@ -300,7 +299,7 @@ HRESULT CordbClass::GetStaticFieldValue2(CordbModule * pModule, } } - if (pRmtStaticValue == NULL) + if (pRmtStaticValue == (CORDB_ADDRESS)NULL) { // type probably wasn't loaded yet. // The debugger may chose to func-eval the creation of an instance of this type and try again. @@ -812,7 +811,7 @@ BOOL CordbClass::GotUnallocatedStatic(DacDbiArrayList * pFieldList) while ((count < pFieldList->Count()) && !fGotUnallocatedStatic ) { if ((*pFieldList)[count].OkToGetOrSetStaticAddress() && - (*pFieldList)[count].GetStaticAddress() == NULL ) + (*pFieldList)[count].GetStaticAddress() == (CORDB_ADDRESS)NULL ) { // The address for a regular static field isn't available yet // How can this happen? Statics appear to get allocated during domain load. @@ -938,7 +937,7 @@ void CordbClass::InitEnCFieldInfo(EnCHangingFieldInfo * pEncField, { // the field is static, we don't need any additional data pEncField->Init(VMPTR_Object::NullPtr(), /* vmObject */ - NULL, /* offsetToVars */ + 0, /* offsetToVars */ fieldToken, ELEMENT_TYPE_MAX, classToken, diff --git a/src/coreclr/debug/di/rspriv.h b/src/coreclr/debug/di/rspriv.h index 63886b56bfa5..ee9f4e9849a4 100644 --- a/src/coreclr/debug/di/rspriv.h +++ b/src/coreclr/debug/di/rspriv.h @@ -3475,7 +3475,7 @@ class CordbProcess : * are passed in, while going through the table we'll undo patches * in buffer at the same time */ - HRESULT RefreshPatchTable(CORDB_ADDRESS address = NULL, SIZE_T size = NULL, BYTE buffer[] = NULL); + HRESULT RefreshPatchTable(CORDB_ADDRESS address = 0, SIZE_T size = 0, BYTE buffer[] = NULL); // Find if a patch exists at a given address. HRESULT FindPatchByAddress(CORDB_ADDRESS address, bool *patchFound, bool *patchIsUnmanaged); @@ -5100,10 +5100,6 @@ class CordbClass : public CordbBase, public ICorDebugClass, public ICorDebugClas public: - // set or clear the custom notifications flag to control whether we ignore custom debugger notifications - void SetCustomNotifications(BOOL fEnable) { m_fCustomNotificationsEnabled = fEnable; } - BOOL CustomNotificationsEnabled () { return m_fCustomNotificationsEnabled; } - HRESULT GetFieldInfo(mdFieldDef fldToken, FieldData ** ppFieldData); // If you want to force the init to happen even if we think the class @@ -5178,9 +5174,6 @@ class CordbClass : public CordbBase, public ICorDebugClass, public ICorDebugClas // their value will be hung off the FieldDesc. Hold information about such fields here. CordbHangingFieldTable m_hangingFieldsStatic; - // this indicates whether we should send custom debugger notifications - BOOL m_fCustomNotificationsEnabled; - }; @@ -5934,7 +5927,7 @@ class CordbNativeCode : public CordbCode, ULONG32 GetColdSize(); // Return true if the Code is split into hot + cold regions. - bool HasColdRegion() { return m_rgCodeRegions[kCold].pAddress != NULL; } + bool HasColdRegion() { return m_rgCodeRegions[kCold].pAddress != (CORDB_ADDRESS)NULL; } // Get the number of fixed arguments for this function (the "this" // but not varargs) @@ -8406,7 +8399,7 @@ class RegisterValueHome: public ValueHome // gets the remote address for the value or returns NULL if none exists virtual - CORDB_ADDRESS GetAddress() { return NULL; }; + CORDB_ADDRESS GetAddress() { return (CORDB_ADDRESS)NULL; }; // Gets a value and returns it in dest virtual @@ -8925,7 +8918,7 @@ class CordbGenericValue : public CordbValue, public ICorDebugGenericValue, publi FAIL_IF_NEUTERED(this); VALIDATE_POINTER_TO_OBJECT_OR_NULL(pAddress, CORDB_ADDRESS *); - *pAddress = m_pValueHome ? m_pValueHome->GetAddress() : NULL; + *pAddress = m_pValueHome ? m_pValueHome->GetAddress() : (CORDB_ADDRESS)NULL; return (S_OK); } @@ -9170,6 +9163,7 @@ class CordbObjectValue : public CordbValue, public ICorDebugHeapValue3, public ICorDebugHeapValue4, public ICorDebugExceptionObjectValue, + public ICorDebugExceptionObjectValue2, public ICorDebugComObjectValue, public ICorDebugDelegateObjectValue { @@ -9292,6 +9286,11 @@ class CordbObjectValue : public CordbValue, //----------------------------------------------------------- COM_METHOD EnumerateExceptionCallStack(ICorDebugExceptionObjectCallStackEnum** ppCallStackEnum); + //----------------------------------------------------------- + // ICorDebugExceptionObjectValue2 + //----------------------------------------------------------- + COM_METHOD ForceCatchHandlerFoundEvents(BOOL enableEvents); + //----------------------------------------------------------- // ICorDebugComObjectValue //----------------------------------------------------------- diff --git a/src/coreclr/debug/di/rsthread.cpp b/src/coreclr/debug/di/rsthread.cpp index 1f455dad376d..f8c81ed692cb 100644 --- a/src/coreclr/debug/di/rsthread.cpp +++ b/src/coreclr/debug/di/rsthread.cpp @@ -656,7 +656,7 @@ void CordbThread::RefreshHandle(HANDLE * phThread) hThread, GetCurrentProcess(), &m_hCachedThread, - NULL, + 0, FALSE, DUPLICATE_SAME_ACCESS); *phThread = m_hCachedThread; @@ -5335,11 +5335,11 @@ HRESULT CordbInternalFrame::GetStackRange(CORDB_ADDRESS *pStart, { if (pStart != NULL) { - *pStart = NULL; + *pStart = (CORDB_ADDRESS)NULL; } if (pEnd != NULL) { - *pEnd = NULL; + *pEnd = (CORDB_ADDRESS)NULL; } return E_NOTIMPL; } @@ -5956,11 +5956,11 @@ HRESULT CordbNativeFrame::GetStackRange(CORDB_ADDRESS *pStart, { if (pStart != NULL) { - *pStart = NULL; + *pStart = (CORDB_ADDRESS)NULL; } if (pEnd != NULL) { - *pEnd = NULL; + *pEnd = (CORDB_ADDRESS)NULL; } return E_NOTIMPL; } @@ -7304,7 +7304,7 @@ SIZE_T CordbNativeFrame::GetInspectionIP() bool CordbNativeFrame::IsFunclet() { #ifdef FEATURE_EH_FUNCLETS - return (m_misc.parentIP != NULL); + return (m_misc.parentIP != (SIZE_T)NULL); #else return false; #endif // FEATURE_EH_FUNCLETS @@ -7406,7 +7406,7 @@ CordbJITILFrame::CordbJITILFrame(CordbNativeFrame * pNativeFrame, m_fVarArgFnx(fVarArgFnx), m_allArgsCount(0), m_rgbSigParserBuf(NULL), - m_FirstArgAddr(NULL), + m_FirstArgAddr((CORDB_ADDRESS)NULL), m_rgNVI(NULL), m_genericArgs(), m_genericArgsLoaded(false), @@ -7533,7 +7533,7 @@ HRESULT CordbJITILFrame::Init() // The stackwalking code can't always successfully retrieve the generics type token. // For example, on 64-bit, the JIT only encodes the generics type token location if // a method has catch clause for a generic exception (e.g. "catch(MyException e)"). - if ((m_dwFrameParamsTokenIndex != (DWORD)ICorDebugInfo::MAX_ILNUM) && (m_frameParamsToken == NULL)) + if ((m_dwFrameParamsTokenIndex != (DWORD)ICorDebugInfo::MAX_ILNUM) && (m_frameParamsToken == (GENERICS_TYPE_TOKEN)NULL)) { // All variables are unavailable in the prolog and the epilog. // This includes the generics type token. Failing to get the token just means that @@ -9314,7 +9314,7 @@ HRESULT CordbEval::GatherArgInfo(ICorDebugValue *pValue, argData->fullArgType = buffer; argData->fullArgTypeNodeCount = fullArgTypeNodeCount; // Is it enregistered? - if ((addr == NULL) && (pVCObjVal->GetValueHome() != NULL)) + if ((addr == (CORDB_ADDRESS)NULL) && (pVCObjVal->GetValueHome() != NULL)) { pVCObjVal->GetValueHome()->CopyToIPCEType(&(argData->argHome)); } @@ -9332,7 +9332,7 @@ HRESULT CordbEval::GatherArgInfo(ICorDebugValue *pValue, CordbGenericValue *gv = (CordbGenericValue*)pValue; argData->argIsLiteral = gv->CopyLiteralData(argData->argLiteralData); // Is it enregistered? - if ((addr == NULL) && (gv->GetValueHome() != NULL)) + if ((addr == (CORDB_ADDRESS)NULL) && (gv->GetValueHome() != NULL)) { gv->GetValueHome()->CopyToIPCEType(&(argData->argHome)); } diff --git a/src/coreclr/debug/ee/amd64/walker.cpp b/src/coreclr/debug/ee/amd64/walker.cpp index 815366def5b0..ce9ea611754b 100644 --- a/src/coreclr/debug/ee/amd64/walker.cpp +++ b/src/coreclr/debug/ee/amd64/walker.cpp @@ -29,7 +29,7 @@ void NativeWalker::Decode() m_skipIP = NULL; m_nextIP = NULL; - BYTE rex = NULL; + BYTE rex = 0; LOG((LF_CORDB, LL_INFO100000, "NW:Decode: m_ip 0x%p\n", m_ip)); @@ -117,7 +117,7 @@ void NativeWalker::Decode() BYTE rex_x = 0; BYTE rex_r = 0; - if (rex != NULL) + if (rex != 0) { rex_b = (rex & 0x1); // high bit to modrm r/m field or SIB base field or OPCODE reg field -- Hmm, when which? rex_x = (rex & 0x2) >> 1; // high bit to sib index field @@ -275,7 +275,7 @@ void NativeWalker::Decode() // the instruction uses r8-r15, add in the extra byte to the displacement // for the REX prefix which was used to specify the extended register - if (rex != NULL) + if (rex != 0) { displace++; } diff --git a/src/coreclr/debug/ee/controller.cpp b/src/coreclr/debug/ee/controller.cpp index 1c689b8eee54..98f532f2e771 100644 --- a/src/coreclr/debug/ee/controller.cpp +++ b/src/coreclr/debug/ee/controller.cpp @@ -770,7 +770,7 @@ DebuggerControllerPatch *DebuggerPatchTable::GetNextPatch(DebuggerControllerPatc #ifdef _DEBUG void DebuggerPatchTable::CheckPatchTable() { - if (NULL != m_pcEntries) + if ((TADDR)NULL != m_pcEntries) { LOG((LF_CORDB,LL_INFO1000, "DPT:CPT: %u\n", m_iEntries)); DebuggerControllerPatch *dcp; @@ -793,7 +793,7 @@ int DebuggerPatchTable::GetNumberOfPatches() { int total = 0; - if (NULL != m_pcEntries) + if ((TADDR)NULL != m_pcEntries) { DebuggerControllerPatch *dcp; ULONG i = 0; @@ -2069,7 +2069,7 @@ BOOL DebuggerController::AddBindAndActivatePatchForMethodDesc(MethodDesc *fd, kind, fp, pAppDomain, - NULL, + 0, dji); if (DebuggerController::BindPatch(patch, fd, NULL)) @@ -2430,7 +2430,7 @@ bool DebuggerController::MatchPatch(Thread *thread, // the appdomain switches halfway through a step. if (patch->pAppDomain != NULL) { - AppDomain *pAppDomainCur = thread->GetDomain(); + AppDomain *pAppDomainCur = AppDomain::GetCurrentDomain(); if (pAppDomainCur != patch->pAppDomain) { @@ -2517,7 +2517,7 @@ DebuggerPatchSkip *DebuggerController::ActivatePatchSkip(Thread *thread, // // !!! check result LOG((LF_CORDB,LL_INFO10000, "DC::APS: About to skip from PC=0x%p\n", PC)); - skip = new (interopsafe) DebuggerPatchSkip(thread, patch, thread->GetDomain()); + skip = new (interopsafe) DebuggerPatchSkip(thread, patch); TRACE_ALLOC(skip); } @@ -2962,7 +2962,7 @@ DPOSS_ACTION DebuggerController::DispatchPatchOrSingleStep(Thread *thread, CONTE if (!event->m_deleted) { #ifdef DEBUGGING_SUPPORTED - if (thread->GetDomain()->IsDebuggerAttached()) + if (AppDomain::GetCurrentDomain()->IsDebuggerAttached()) { if (event->SendEvent(thread, fIpChanged)) { @@ -4295,9 +4295,8 @@ bool DebuggerController::DispatchNativeException(EXCEPTION_RECORD *pException, // * ------------------------------------------------------------------------- DebuggerPatchSkip::DebuggerPatchSkip(Thread *thread, - DebuggerControllerPatch *patch, - AppDomain *pAppDomain) - : DebuggerController(thread, pAppDomain), + DebuggerControllerPatch *patch) + : DebuggerController(thread, AppDomain::GetCurrentDomain()), m_address(patch->address) { LOG((LF_CORDB, LL_INFO10000, @@ -4656,17 +4655,6 @@ TP_RESULT DebuggerPatchSkip::TriggerExceptionHook(Thread *thread, CONTEXT * cont } CONTRACTL_END; - if (m_pAppDomain != NULL) - { - AppDomain *pAppDomainCur = thread->GetDomain(); - - if (pAppDomainCur != m_pAppDomain) - { - LOG((LF_CORDB,LL_INFO10000, "DPS::TEH: Appdomain mismatch - not skiiping!\n")); - return TPR_IGNORE; - } - } - LOG((LF_CORDB,LL_INFO10000, "DPS::TEH: doing the patch-skip thing\n")); #if defined(TARGET_ARM64) && !defined(FEATURE_EMULATE_SINGLESTEP) @@ -4797,18 +4785,6 @@ bool DebuggerPatchSkip::TriggerSingleStep(Thread *thread, const BYTE *ip) { LOG((LF_CORDB,LL_INFO10000, "DPS::TSS: basically a no-op\n")); - if (m_pAppDomain != NULL) - { - AppDomain *pAppDomainCur = thread->GetDomain(); - - if (pAppDomainCur != m_pAppDomain) - { - LOG((LF_CORDB,LL_INFO10000, "DPS::TSS: Appdomain mismatch - " - "not SingSteping!!\n")); - return false; - } - } - #if defined(TARGET_AMD64) // Dev11 91932: for RIP-relative writes we need to copy the value that was written in our buffer to the actual address _ASSERTE(m_pSharedPatchBypassBuffer); @@ -6082,6 +6058,8 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in) } } LOG((LF_CORDB,LL_INFO1000,"Ending TrapStep\n")); + + return false; } bool DebuggerStepper::IsAddrWithinFrame(DebuggerJitInfo *dji, @@ -7110,7 +7088,7 @@ TP_RESULT DebuggerStepper::TriggerPatch(DebuggerControllerPatch *patch, dji = g_pDebugger->GetJitInfoFromAddr((TADDR) traceManagerRetAddr); MethodDesc* mdNative = NULL; - PCODE pcodeNative = NULL; + PCODE pcodeNative = (PCODE)NULL; if (dji != NULL) { mdNative = dji->m_nativeCodeVersion.GetMethodDesc(); @@ -8259,7 +8237,7 @@ void DebuggerThreadStarter::TriggerTraceCall(Thread *thread, const BYTE *ip) { LOG((LF_CORDB, LL_EVERYTHING, "DTS::TTC called\n")); #ifdef DEBUGGING_SUPPORTED - if (thread->GetDomain()->IsDebuggerAttached()) + if (AppDomain::GetCurrentDomain()->IsDebuggerAttached()) { TraceDestination trace; diff --git a/src/coreclr/debug/ee/controller.h b/src/coreclr/debug/ee/controller.h index b838e11c0f85..23f6c5125e16 100644 --- a/src/coreclr/debug/ee/controller.h +++ b/src/coreclr/debug/ee/controller.h @@ -1453,8 +1453,7 @@ class DebuggerPatchSkip : public DebuggerController friend class DebuggerController; DebuggerPatchSkip(Thread *thread, - DebuggerControllerPatch *patch, - AppDomain *pAppDomain); + DebuggerControllerPatch *patch); ~DebuggerPatchSkip(); diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp index 79aa2d5f13fc..1d15dd957607 100644 --- a/src/coreclr/debug/ee/debugger.cpp +++ b/src/coreclr/debug/ee/debugger.cpp @@ -915,6 +915,8 @@ Debugger::Debugger() m_unrecoverableError(FALSE), m_ignoreThreadDetach(FALSE), m_pMethodInfos(NULL), + m_pForceCatchHandlerFoundEventsTable(NULL), + m_pCustomNotificationTable(NULL), m_mutex(CrstDebuggerMutex, (CrstFlags)(CRST_UNSAFE_ANYMODE | CRST_REENTRANCY | CRST_DEBUGGER_THREAD)), #ifdef _DEBUG m_mutexOwner(0), @@ -956,10 +958,8 @@ Debugger::Debugger() m_processId = GetCurrentProcessId(); - // Initialize these in ctor because we free them in dtor. - // And we can't set them to some safe uninited value (like NULL). - - + m_pForceCatchHandlerFoundEventsTable = new ForceCatchHandlerFoundTable(); + m_pCustomNotificationTable = new CustomNotificationTable(); //------------------------------------------------------------------------------ // Metadata data structure version numbers @@ -971,7 +971,7 @@ Debugger::Debugger() m_mdDataStructureVersion = 1; m_fOutOfProcessSetContextEnabled = #if defined(OUT_OF_PROCESS_SETTHREADCONTEXT) && !defined(DACCESS_COMPILE) - Thread::AreCetShadowStacksEnabled() || CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_OutOfProcessSetContext) != 0; + Thread::AreShadowStacksEnabled() || CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_OutOfProcessSetContext) != 0; #else FALSE; #endif @@ -1353,7 +1353,7 @@ DebuggerEval::DebuggerEval(CONTEXT * pContext, DebuggerIPCE_FuncEvalInfo * pEval m_debuggerModule = g_pDebugger->LookupOrCreateModule(pEvalInfo->vmDomainAssembly); m_funcEvalKey = pEvalInfo->funcEvalKey; m_argCount = pEvalInfo->argCount; - m_targetCodeAddr = NULL; + m_targetCodeAddr = (TADDR)NULL; m_stringSize = pEvalInfo->stringSize; m_arrayRank = pEvalInfo->arrayRank; m_genericArgsCount = pEvalInfo->genericArgsCount; @@ -2238,7 +2238,7 @@ DebuggerLazyInit::DebuggerLazyInit() : m_exAttachEvent(NULL), m_exUnmanagedAttachEvent(NULL), m_garbageCollectionBlockerEvent(NULL), - m_DebuggerHandlingCtrlC(NULL) + m_DebuggerHandlingCtrlC(FALSE) { } @@ -2724,7 +2724,7 @@ DebuggerJitInfo *Debugger::GetJitInfoWorker(MethodDesc *fd, const BYTE *pbAddr, else { PCODE startAddr = g_pEEInterface->GetNativeCodeStartAddress((PCODE)pbAddr); - if (startAddr == NULL) + if (startAddr == (PCODE)NULL) { LOG((LF_CORDB,LL_INFO1000,"D::GJIW: Couldn't find a DJI by address 0x%p, " "so it might be a stub or thunk\n", pbAddr)); @@ -2748,7 +2748,7 @@ DebuggerJitInfo *Debugger::GetJitInfoWorker(MethodDesc *fd, const BYTE *pbAddr, #endif // LOGGING } - if (startAddr != NULL) + if (startAddr != (PCODE)NULL) { dji = dmi->FindOrCreateInitAndAddJitInfo(fd, startAddr); } @@ -3488,7 +3488,7 @@ HRESULT Debugger::SetIP( bool fCanSetIPOnly, Thread *thread,Module *module, BOOL exact; SIZE_T offsetNatTo; - PCODE pbDest = NULL; + PCODE pbDest = (PCODE)NULL; BYTE *pbBase = NULL; CONTEXT *pCtx = NULL; DWORD dwSize = 0; @@ -5828,7 +5828,7 @@ void Debugger::SuspendForGarbageCollectionCompleted() InitIPCEvent(ipce1, DB_IPCE_BEFORE_GARBAGE_COLLECTION, pThread, - pThread->GetDomain()); + AppDomain::GetCurrentDomain()); m_pRCThread->SendIPCEvent(); this->SuspendComplete(true); @@ -5866,7 +5866,7 @@ void Debugger::ResumeForGarbageCollectionStarted() InitIPCEvent(ipce1, DB_IPCE_AFTER_GARBAGE_COLLECTION, pThread, - pThread->GetDomain()); + AppDomain::GetCurrentDomain()); m_pRCThread->SendIPCEvent(); this->SuspendComplete(true); @@ -5916,7 +5916,7 @@ void Debugger::SendDataBreakpoint(Thread *thread, CONTEXT *context, InitIPCEvent(ipce, DB_IPCE_DATA_BREAKPOINT, thread, - thread->GetDomain()); + AppDomain::GetCurrentDomain()); //_ASSERTE(breakpoint->m_pAppDomain == ipce->vmAppDomain.GetRawPtr()); m_pRCThread->SendIPCEvent(); @@ -5963,7 +5963,7 @@ void Debugger::SendBreakpoint(Thread *thread, CONTEXT *context, InitIPCEvent(ipce, DB_IPCE_BREAKPOINT, thread, - thread->GetDomain()); + AppDomain::GetCurrentDomain()); ipce->BreakpointData.breakpointToken.Set(breakpoint); _ASSERTE( breakpoint->m_pAppDomain == ipce->vmAppDomain.GetRawPtr()); @@ -6036,7 +6036,7 @@ void Debugger::SendRawUserBreakpoint(Thread * pThread) InitIPCEvent(pEvent, DB_IPCE_USER_BREAKPOINT, pThread, - pThread->GetDomain()); + AppDomain::GetCurrentDomain()); m_pRCThread->SendIPCEvent(); } @@ -6068,7 +6068,7 @@ void Debugger::SendInterceptExceptionComplete(Thread *thread) InitIPCEvent(ipce, DB_IPCE_INTERCEPT_EXCEPTION_COMPLETE, thread, - thread->GetDomain()); + AppDomain::GetCurrentDomain()); m_pRCThread->SendIPCEvent(); } @@ -6107,7 +6107,7 @@ void Debugger::SendStep(Thread *thread, CONTEXT *context, InitIPCEvent(ipce, DB_IPCE_STEP_COMPLETE, thread, - thread->GetDomain()); + AppDomain::GetCurrentDomain()); ipce->StepData.stepperToken.Set(stepper); ipce->StepData.reason = reason; m_pRCThread->SendIPCEvent(); @@ -6148,7 +6148,7 @@ void Debugger::LockAndSendEnCRemapEvent(DebuggerJitInfo * dji, SIZE_T currentIP, InitIPCEvent(ipce, DB_IPCE_ENC_REMAP, thread, - thread->GetDomain()); + AppDomain::GetCurrentDomain()); ipce->EnCRemap.currentVersionNumber = dji->m_encVersion; ipce->EnCRemap.resumeVersionNumber = dji->m_methodInfo->GetCurrentEnCVersion();; @@ -6161,7 +6161,7 @@ void Debugger::LockAndSendEnCRemapEvent(DebuggerJitInfo * dji, SIZE_T currentIP, Module *pRuntimeModule = pMD->GetModule(); - DebuggerModule * pDModule = LookupOrCreateModule(pRuntimeModule, thread->GetDomain()); + DebuggerModule * pDModule = LookupOrCreateModule(pRuntimeModule, AppDomain::GetCurrentDomain()); ipce->EnCRemap.vmDomainAssembly.SetRawPtr((pDModule ? pDModule->GetDomainAssembly() : NULL)); LOG((LF_CORDB, LL_INFO10000, "D::LASEnCRE: %s::%s dmod:%p\n", @@ -6200,13 +6200,13 @@ void Debugger::LockAndSendEnCRemapCompleteEvent(MethodDesc *pMD) InitIPCEvent(ipce, DB_IPCE_ENC_REMAP_COMPLETE, thread, - thread->GetDomain()); + AppDomain::GetCurrentDomain()); ipce->EnCRemapComplete.funcMetadataToken = pMD->GetMemberDef(); Module *pRuntimeModule = pMD->GetModule(); - DebuggerModule * pDModule = LookupOrCreateModule(pRuntimeModule, thread->GetDomain()); + DebuggerModule * pDModule = LookupOrCreateModule(pRuntimeModule, AppDomain::GetCurrentDomain()); ipce->EnCRemapComplete.vmDomainAssembly.SetRawPtr((pDModule ? pDModule->GetDomainAssembly() : NULL)); LOG((LF_CORDB, LL_INFO10000, "D::LASEnCRE: %s::%s dmod:%p, methodDef:0x%08x \n", @@ -6321,7 +6321,7 @@ void Debugger::LockAndSendBreakpointSetError(PATCH_UNORDERED_ARRAY * listUnbinda i+1, count, controller, controller->GetDCType())); // Send a breakpoint set error event to the Right Side. - InitIPCEvent(ipce, DB_IPCE_BREAKPOINT_SET_ERROR, thread, thread->GetDomain()); + InitIPCEvent(ipce, DB_IPCE_BREAKPOINT_SET_ERROR, thread, AppDomain::GetCurrentDomain()); ipce->BreakpointSetErrorData.breakpointToken.Set(static_cast (controller)); @@ -7294,7 +7294,7 @@ HRESULT Debugger::SendExceptionHelperAndBlock( // // Send pre-Whidbey EXCEPTION IPC event. // - InitIPCEvent(ipce, DB_IPCE_EXCEPTION, pThread, pThread->GetDomain()); + InitIPCEvent(ipce, DB_IPCE_EXCEPTION, pThread, AppDomain::GetCurrentDomain()); ipce->Exception.vmExceptionHandle.SetRawPtr(exceptionHandle); ipce->Exception.firstChance = (eventType == DEBUG_EXCEPTION_FIRST_CHANCE); @@ -7306,7 +7306,7 @@ HRESULT Debugger::SendExceptionHelperAndBlock( // // Send Whidbey EXCEPTION IPC event. // - InitIPCEvent(ipce, DB_IPCE_EXCEPTION_CALLBACK2, pThread, pThread->GetDomain()); + InitIPCEvent(ipce, DB_IPCE_EXCEPTION_CALLBACK2, pThread, AppDomain::GetCurrentDomain()); ipce->ExceptionCallback2.framePointer = framePointer; ipce->ExceptionCallback2.eventType = eventType; @@ -7448,8 +7448,8 @@ void Debugger::SendExceptionEventsWorker( g_pDebugger->IncThreadsAtUnsafePlaces(); } } // end of GCX_CCOP_EEINTERFACE(); - } //end if (m_sendExceptionsOutsideOfJMC && !SentDebugFirstChance()) + } //end if (m_sendExceptionsOutsideOfJMC && !SentDebugFirstChance()) // // If this is a JMC function, then we send a USER's first chance as well. // @@ -7459,7 +7459,7 @@ void Debugger::SendExceptionEventsWorker( { SENDIPCEVENT_BEGIN(this, pThread); - InitIPCEvent(ipce, DB_IPCE_EXCEPTION_CALLBACK2, pThread, pThread->GetDomain()); + InitIPCEvent(ipce, DB_IPCE_EXCEPTION_CALLBACK2, pThread, AppDomain::GetCurrentDomain()); ipce->ExceptionCallback2.framePointer = framePointer; ipce->ExceptionCallback2.eventType = DEBUG_EXCEPTION_USER_FIRST_CHANCE; @@ -7846,11 +7846,14 @@ void Debugger::FirstChanceManagedExceptionCatcherFound(Thread *pThread, } } + BOOL forceSendCatchHandlerFound = FALSE; + { + GCX_COOP_EEINTERFACE(); + forceSendCatchHandlerFound = ShouldSendCatchHandlerFound(pThread); + } // Here we check if debugger opted-out of receiving exception related events from outside of JMC methods // or this exception ever crossed JMC frame (in this case we have already sent user first chance event) - if (m_sendExceptionsOutsideOfJMC || - isInJMCFunction || - pThread->GetExceptionState()->GetFlags()->SentDebugUserFirstChance()) + if (isInJMCFunction || forceSendCatchHandlerFound) { if (pDebugJitInfo != NULL) { @@ -7979,9 +7982,15 @@ LONG Debugger::NotifyOfCHFFilter(EXCEPTION_POINTERS* pExceptionPointers, PVOID p pExceptionPointers); } + BOOL forceSendCatchHandlerFound = FALSE; + { + GCX_COOP_EEINTERFACE(); + forceSendCatchHandlerFound = ShouldSendCatchHandlerFound(pThread); + } + // Here we check if debugger opted-out of receiving exception related events from outside of JMC methods // or this exception ever crossed JMC frame (in this case we have already sent user first chance event) - if (m_sendExceptionsOutsideOfJMC || pExState->GetFlags()->SentDebugUserFirstChance()) + if (forceSendCatchHandlerFound) { SendCatchHandlerFound(pThread, fp, offset, dwFlags); } @@ -8008,6 +8017,48 @@ LONG Debugger::NotifyOfCHFFilter(EXCEPTION_POINTERS* pExceptionPointers, PVOID p return EXCEPTION_CONTINUE_SEARCH; } +BOOL Debugger::ShouldSendCatchHandlerFound(Thread* pThread) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_COOPERATIVE; + } + CONTRACTL_END; + + ThreadExceptionState* pExState = pThread->GetExceptionState(); + if (m_sendExceptionsOutsideOfJMC || pExState->GetFlags()->SentDebugUserFirstChance()) + { + return TRUE; + } + else + { + BOOL forceSendCatchHandlerFound = FALSE; + OBJECTHANDLE objHandle = pThread->GetThrowableAsHandle(); + OBJECTHANDLE retrievedHandle = m_pForceCatchHandlerFoundEventsTable->Lookup(objHandle); //destroy handle + if (retrievedHandle != NULL) + { + forceSendCatchHandlerFound = TRUE; + } + return forceSendCatchHandlerFound; + } +} + +BOOL Debugger::ShouldSendCustomNotification(DomainAssembly *pAssembly, mdTypeDef typeDef) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + Module *pModule = pAssembly->GetModule(); + TypeInModule tim(pModule, typeDef); + return !(m_pCustomNotificationTable->Lookup(tim).IsNull()); +} // Actually send the catch handler found event. // This can be used to send CHF for both regular managed catchers as well @@ -8068,7 +8119,7 @@ void Debugger::SendCatchHandlerFound( // // Send Whidbey EXCEPTION IPC event. // - InitIPCEvent(ipce, DB_IPCE_EXCEPTION_CALLBACK2, pThread, pThread->GetDomain()); + InitIPCEvent(ipce, DB_IPCE_EXCEPTION_CALLBACK2, pThread, AppDomain::GetCurrentDomain()); ipce->ExceptionCallback2.framePointer = fp; ipce->ExceptionCallback2.eventType = DEBUG_EXCEPTION_CATCH_HANDLER_FOUND; @@ -8171,7 +8222,7 @@ void Debugger::ManagedExceptionUnwindBegin(Thread *pThread) // // Send Whidbey EXCEPTION IPC event. // - InitIPCEvent(ipce, DB_IPCE_EXCEPTION_UNWIND, pThread, pThread->GetDomain()); + InitIPCEvent(ipce, DB_IPCE_EXCEPTION_UNWIND, pThread, AppDomain::GetCurrentDomain()); ipce->ExceptionUnwind.eventType = DEBUG_EXCEPTION_UNWIND_BEGIN; ipce->ExceptionUnwind.dwFlags = 0; @@ -8546,8 +8597,8 @@ LONG Debugger::LastChanceManagedException(EXCEPTION_POINTERS * pExceptionInfo, // attach stuff out here and not bother with the flag. hr = SendException(thread, FALSE, - ((pContext != NULL) ? (SIZE_T)GetIP(pContext) : NULL), - ((pContext != NULL) ? (SIZE_T)GetSP(pContext) : NULL), + ((pContext != NULL) ? (SIZE_T)GetIP(pContext) : 0), + ((pContext != NULL) ? (SIZE_T)GetSP(pContext) : 0), continuable, !!jitAttachRequested, // If we are JIT attaching on an unhandled exceptioin, we force !!jitAttachRequested, // the exception to be uninterceptable. @@ -8952,7 +9003,7 @@ void Debugger::ThreadStarted(Thread* pRuntimeThread) return; LOG((LF_CORDB, LL_INFO100, "D::TS: thread attach : ID=%#x AD:%#x\n", - GetThreadIdHelper(pRuntimeThread), pRuntimeThread->GetDomain())); + GetThreadIdHelper(pRuntimeThread), AppDomain::GetCurrentDomain())); // We just need to send a VMPTR_Thread. The RS will get everything else it needs from DAC. // @@ -8966,7 +9017,7 @@ void Debugger::ThreadStarted(Thread* pRuntimeThread) InitIPCEvent(ipce, DB_IPCE_THREAD_ATTACH, pRuntimeThread, - pRuntimeThread->GetDomain()); + AppDomain::GetCurrentDomain()); m_pRCThread->SendIPCEvent(); @@ -9019,7 +9070,7 @@ void Debugger::DetachThread(Thread *pRuntimeThread) LOG((LF_CORDB, LL_INFO100, "D::DT: thread detach : ID=%#x AD:%#x.\n", - GetThreadIdHelper(pRuntimeThread), pRuntimeThread->GetDomain())); + GetThreadIdHelper(pRuntimeThread), AppDomain::GetCurrentDomain())); // We may be killing a thread before the Thread-starter fired. @@ -9040,7 +9091,7 @@ void Debugger::DetachThread(Thread *pRuntimeThread) InitIPCEvent(pEvent, DB_IPCE_THREAD_DETACH, pRuntimeThread, - pRuntimeThread->GetDomain()); + AppDomain::GetCurrentDomain()); m_pRCThread->SendIPCEvent(); @@ -10015,7 +10066,7 @@ void Debugger::FuncEvalComplete(Thread* pThread, DebuggerEval *pDE) // We can't easily convert our ADID to an AppDomain* (SystemDomain::GetAppDomainFromId) // because we can't prove that the AppDomain* would be valid (not unloaded). // - AppDomain *pDomain = pThread->GetDomain(); + AppDomain *pDomain = AppDomain::GetCurrentDomain(); AppDomain *pResultDomain = ((pDE->m_debuggerModule == NULL) ? pDomain : pDE->m_debuggerModule->GetAppDomain()); // Send a func eval complete event to the Right Side. @@ -10427,6 +10478,47 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) } break; + case DB_IPCE_FORCE_CATCH_HANDLER_FOUND: + { + BOOL enableEvents = pEvent->ForceCatchHandlerFoundData.enableEvents; + AppDomain *pAppDomain = pEvent->vmAppDomain.GetRawPtr(); + OBJECTREF exObj = ObjectToOBJECTREF(pEvent->ForceCatchHandlerFoundData.vmObj.GetRawPtr()); + HRESULT hr = E_INVALIDARG; + + hr = UpdateForceCatchHandlerFoundTable(enableEvents, exObj, pAppDomain); + + DebuggerIPCEvent * pIPCResult = m_pRCThread->GetIPCEventReceiveBuffer(); + InitIPCEvent(pIPCResult, + DB_IPCE_CATCH_HANDLER_FOUND_RESULT, + g_pEEInterface->GetThread(), + pEvent->vmAppDomain); + + pIPCResult->hr = hr; + + m_pRCThread->SendIPCReply(); + } + break; + + case DB_IPCE_SET_ENABLE_CUSTOM_NOTIFICATION: + { + Module * pModule = pEvent->CustomNotificationData.vmModule.GetRawPtr(); + mdTypeDef classToken = pEvent->CustomNotificationData.classMetadataToken; + BOOL enabled = pEvent->CustomNotificationData.Enabled; + + HRESULT hr = UpdateCustomNotificationTable(pModule, classToken, enabled); + + DebuggerIPCEvent * pIPCResult = m_pRCThread->GetIPCEventReceiveBuffer(); + InitIPCEvent(pIPCResult, + DB_IPCE_SET_ENABLE_CUSTOM_NOTIFICATION_RESULT, + g_pEEInterface->GetThread(), + pEvent->vmAppDomain); + + pIPCResult->hr = hr; + + m_pRCThread->SendIPCReply(); + } + break; + case DB_IPCE_BREAKPOINT_ADD: { @@ -10953,7 +11045,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) Thread * pThread = pEvent->FuncEval.vmThreadToken.GetRawPtr(); - InitIPCEvent(pEvent, DB_IPCE_FUNC_EVAL_SETUP_RESULT, pThread, pThread->GetDomain()); + InitIPCEvent(pEvent, DB_IPCE_FUNC_EVAL_SETUP_RESULT, pThread, AppDomain::GetCurrentDomain()); BYTE * pbArgDataArea = NULL; DebuggerEval * pDebuggerEvalKey = NULL; @@ -12221,13 +12313,14 @@ HRESULT Debugger::DeoptimizeMethodHelper(Module* pModule, mdMethodDef methodDef) ILCodeVersion ilCodeVersion; CodeVersionManager *pCodeVersionManager = pModule->GetCodeVersionManager(); + LOG((LF_TIEREDCOMPILATION, LL_INFO100, "Debugger::DeoptimizeMethodHelper Module=%p Method=0x%08x\n", + pModule, methodDef)); + { CodeVersionManager::LockHolder codeVersioningLockHolder; if (FAILED(hr = pCodeVersionManager->AddILCodeVersion(pModule, methodDef, &ilCodeVersion, TRUE))) { - LOG((LF_TIEREDCOMPILATION, LL_INFO100, "TieredCompilationManager::DeOptimizeMethodHelper Module=0x%x Method=0x%x, AddILCodeVersion returned hr 0x%x\n", - pModule, methodDef, - hr)); + LOG((LF_TIEREDCOMPILATION, LL_INFO100, "Debugger::DeoptimizeMethodHelper AddILCodeVersion returned hr 0x%x\n", hr)); return hr; } @@ -12243,8 +12336,7 @@ HRESULT Debugger::DeoptimizeMethodHelper(Module* pModule, mdMethodDef methodDef) { if (FAILED(hr = pCodeVersionManager->SetActiveILCodeVersions(&ilCodeVersion, 1, NULL))) { - LOG((LF_TIEREDCOMPILATION, LL_INFO100, "TieredCompilationManager::DeOptimizeMethodHelper Module=0x%x Method=0x%x, SetActiveILCodeVersions returned hr 0x%x\n", - pModule, methodDef, + LOG((LF_TIEREDCOMPILATION, LL_INFO100, "Debugger::DeoptimizeMethodHelper SetActiveILCodeVersions returned hr 0x%x\n", hr)); return hr; } @@ -12266,7 +12358,7 @@ HRESULT Debugger::DeoptimizeMethod(Module* pModule, mdMethodDef methodDef) HRESULT hr = DeoptimizeMethodHelper(pModule, methodDef); if (FAILED(hr)) { - LOG((LF_TIEREDCOMPILATION, LL_INFO100, "TieredCompilationManager::DeOptimizeMethod Module=0x%x Method=0x%x,, initial ReJIT returned hr 0x%x, aborting\n", + LOG((LF_TIEREDCOMPILATION, LL_INFO100, "Debugger::DeoptimizeMethod Module=%p Method=0x%08x, initial ReJIT returned hr 0x%x, aborting\n", pModule, methodDef, hr)); return hr; } @@ -12350,6 +12442,73 @@ HRESULT Debugger::IsMethodDeoptimized(Module *pModule, mdMethodDef methodDef, BO return S_OK; } +HRESULT Debugger::UpdateCustomNotificationTable(Module *pModule, mdTypeDef classToken, BOOL enabled) +{ + CONTRACTL + { + THROWS; + CAN_TAKE_LOCK; + GC_NOTRIGGER; + } + CONTRACTL_END; + + TypeInModule tim(pModule, classToken); + if (enabled) + { + if (m_pCustomNotificationTable->Lookup(tim).IsNull()) + { + m_pCustomNotificationTable->Add(tim); + } + } + else + { + if (!(m_pCustomNotificationTable->Lookup(tim).IsNull())) + { + m_pCustomNotificationTable->Remove(tim); + } + } + + return S_OK; +} + +HRESULT Debugger::UpdateForceCatchHandlerFoundTable(BOOL enableEvents, OBJECTREF exObj, AppDomain *pAppDomain) +{ + CONTRACTL + { + THROWS; + CAN_TAKE_LOCK; + GC_NOTRIGGER; + } + CONTRACTL_END; + + OBJECTHANDLE objHandle = pAppDomain->CreateLongWeakHandle(exObj); + if (objHandle == NULL) + { + return E_INVALIDARG; + } + if (enableEvents) + { + OBJECTHANDLE objHandleFound = m_pForceCatchHandlerFoundEventsTable->Lookup(objHandle); + if (objHandleFound == NULL) + { + m_pForceCatchHandlerFoundEventsTable->Add(objHandle); + } + else + { + DestroyLongWeakHandle(objHandle); + } + } + else + { + if (m_pForceCatchHandlerFoundEventsTable->Lookup(objHandle) != NULL) + { + m_pForceCatchHandlerFoundEventsTable->Remove(objHandle); + } + DestroyLongWeakHandle(objHandle); + } + return S_OK; +} + // // UnrecoverableError causes the Left Side to enter a state where no more // debugging can occur and we leave around enough information for the @@ -13984,7 +14143,7 @@ bool Debugger::GetILOffsetFromNative (MethodDesc *pFunc, const BYTE *pbAddr, } PCODE methodStartAddress = g_pEEInterface->GetNativeCodeStartAddress((PCODE)pbAddr); - if (methodStartAddress == NULL) + if (methodStartAddress == (PCODE)NULL) { return false; } @@ -14143,7 +14302,7 @@ void Debugger::SendRawMDANotification( DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer(); Thread * pThread = params->m_pThread; - AppDomain *pAppDomain = (pThread != NULL) ? pThread->GetDomain() : NULL; + AppDomain *pAppDomain = (pThread != NULL) ? AppDomain::GetCurrentDomain() : NULL; InitIPCEvent(ipce, DB_IPCE_MDA_NOTIFICATION, @@ -14324,7 +14483,7 @@ void Debugger::SendLogMessage(int iLevel, // Send the message only if the debugger is attached to this appdomain. // Note the debugger may detach at any time, so we'll have to check // this again after we get the lock. - AppDomain *pAppDomain = g_pEEInterface->GetThread()->GetDomain(); + AppDomain *pAppDomain = AppDomain::GetCurrentDomain(); if (!CORDebuggerAttached()) { @@ -14430,7 +14589,7 @@ void Debugger::SendLogSwitchSetting(int iLevel, InitIPCEvent(ipce, DB_IPCE_LOGSWITCH_SET_MESSAGE, pThread, - pThread->GetDomain()); + AppDomain::GetCurrentDomain()); ipce->LogSwitchSettingMessage.iLevel = iLevel; ipce->LogSwitchSettingMessage.iReason = iReason; @@ -14487,13 +14646,13 @@ void Debugger::SendCustomDebuggerNotification(Thread * pThread, Thread *curThread = g_pEEInterface->GetThread(); SENDIPCEVENT_BEGIN(this, curThread); - if (CORDebuggerAttached()) + if (CORDebuggerAttached() && ShouldSendCustomNotification(pDomain, classToken)) { DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer(); InitIPCEvent(ipce, DB_IPCE_CUSTOM_NOTIFICATION, curThread, - curThread->GetDomain()); + AppDomain::GetCurrentDomain()); VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::MakePtr(pDomain); @@ -15615,8 +15774,7 @@ HRESULT Debugger::NameChangeEvent(AppDomain *pAppDomain, Thread *pThread) InitIPCEvent(ipce, DB_IPCE_NAME_CHANGE, curThread, - curThread->GetDomain()); - + AppDomain::GetCurrentDomain()); if (pAppDomain) { diff --git a/src/coreclr/debug/ee/debugger.h b/src/coreclr/debug/ee/debugger.h index 2b8573e31b36..24caa135f0e7 100644 --- a/src/coreclr/debug/ee/debugger.h +++ b/src/coreclr/debug/ee/debugger.h @@ -535,6 +535,143 @@ struct DebuggerPendingFuncEval typedef DPTR(struct DebuggerPendingFuncEval) PTR_DebuggerPendingFuncEval; +/* ------------------------------------------------------------------------ * + * SHash to hold weak object handles of exceptions with ForceCatchHandlerFound equal to true + * ------------------------------------------------------------------------ */ +#ifndef DACCESS_COMPILE +class EMPTY_BASES_DECL ForceCatchHandlerFoundSHashTraits : public DefaultSHashTraits +{ + public: + typedef OBJECTHANDLE element_t; + typedef OBJECTHANDLE key_t; + static const bool s_supports_autoremove = true; + static const bool s_NoThrow = false; + static const bool s_RemovePerEntryCleanupAction = true; + + static BOOL Equals(const OBJECTHANDLE &e, const OBJECTHANDLE &f) + { + return ObjectFromHandle(e) == ObjectFromHandle(f); + } + static OBJECTHANDLE GetKey(const OBJECTHANDLE &e) + { + return e; + } + static INT32 Hash(const OBJECTHANDLE &e) + { + return ObjectFromHandle(e)->GetHashCodeEx(); + } + static bool ShouldDelete(const OBJECTHANDLE &e) + { + return ObjectHandleIsNull(e); + } + static OBJECTHANDLE Null() + { + OBJECTHANDLE e = (OBJECTHANDLE)(TADDR)0; + return e; + } + static bool IsNull(const OBJECTHANDLE &e) + { + return e == (OBJECTHANDLE)(TADDR)0; + } + static OBJECTHANDLE Deleted() + { + OBJECTHANDLE e = (OBJECTHANDLE)(TADDR)-1; + return e; + } + static bool IsDeleted(const OBJECTHANDLE &e) + { + return e == (OBJECTHANDLE)(TADDR)-1; + } + static void OnRemovePerEntryCleanupAction(const OBJECTHANDLE &e) + { + DestroyLongWeakHandle(e); + } +}; +typedef SHash ForceCatchHandlerFoundTable; + +class TypeInModule +{ +private: + Module *m_module; + mdTypeDef m_typeDef; + +public: + + bool operator ==(const TypeInModule& other) const + { + return m_module == other.m_module && m_typeDef == other.m_typeDef; + } + + bool operator !=(const TypeInModule& other) const + { + return !(*this == other); + } + + bool IsNull() const + { + return m_module == NULL && m_typeDef == 0; + } + + INT32 Hash() const + { + return (INT32)((UINT_PTR)m_module ^ m_typeDef); + } + + TypeInModule(Module * module, mdTypeDef typeDef) + :m_module(module), m_typeDef(typeDef) + { + LIMITED_METHOD_DAC_CONTRACT; + } + + TypeInModule() + :m_module(NULL), m_typeDef(0) + { + LIMITED_METHOD_DAC_CONTRACT; + } +}; + +class EMPTY_BASES_DECL CustomNotificationSHashTraits : public DefaultSHashTraits +{ + public: + typedef TypeInModule element_t; + typedef TypeInModule key_t; + static const bool s_NoThrow = false; + + static BOOL Equals(const TypeInModule &e, const TypeInModule &f) + { + return e == f; + } + static TypeInModule GetKey(const TypeInModule &e) + { + return e; + } + static INT32 Hash(const TypeInModule &e) + { + return e.Hash(); + } + static TypeInModule Null() + { + TypeInModule tim; + return tim; + } + static bool IsNull(const TypeInModule &e) + { + return e.IsNull(); + } + static TypeInModule Deleted() + { + TypeInModule tim((Module *)-1, -1); + return tim; + } + static bool IsDeleted(const TypeInModule &e) + { + TypeInModule tim((Module *)-1, -1); + return e == tim; + } +}; +typedef SHash CustomNotificationTable; +#endif + /* ------------------------------------------------------------------------ * * DebuggerRCThread class -- the Runtime Controller thread. * ------------------------------------------------------------------------ */ @@ -1237,8 +1374,8 @@ class CodeRegionInfo { public: CodeRegionInfo() : - m_addrOfHotCode(NULL), - m_addrOfColdCode(NULL), + m_addrOfHotCode((PCODE)NULL), + m_addrOfColdCode((PCODE)NULL), m_sizeOfHotCode(0), m_sizeOfColdCode(0) { @@ -1273,7 +1410,7 @@ class CodeRegionInfo { LIMITED_METHOD_CONTRACT; - if (m_addrOfHotCode != NULL) + if (m_addrOfHotCode != (PCODE)NULL) { if (offset < m_sizeOfHotCode) { @@ -1289,7 +1426,7 @@ class CodeRegionInfo } else { - return NULL; + return (PCODE)NULL; } } @@ -1312,7 +1449,7 @@ class CodeRegionInfo } _ASSERTE(!"addressToOffset called with invalid address"); - return NULL; + return 0; } // Determines whether the address lies within the method @@ -1917,6 +2054,10 @@ class Debugger : public DebugInterface Module *classModule, BOOL fIsLoadEvent); + BOOL ShouldSendCatchHandlerFound(Thread* pThread); + + BOOL ShouldSendCustomNotification(DomainAssembly *pAssembly, mdTypeDef typeDef); + void SendCatchHandlerFound(Thread *pThread, FramePointer fp, SIZE_T nOffset, @@ -2218,6 +2359,8 @@ class Debugger : public DebugInterface HRESULT DeoptimizeMethod(Module* pModule, mdMethodDef methodDef); #endif //DACCESS_COMPILE HRESULT IsMethodDeoptimized(Module *pModule, mdMethodDef methodDef, BOOL *pResult); + HRESULT UpdateForceCatchHandlerFoundTable(BOOL enableEvents, OBJECTREF exObj, AppDomain *pAppDomain); + HRESULT UpdateCustomNotificationTable(Module *pModule, mdTypeDef classToken, BOOL enabled); // // The debugger mutex is used to protect any "global" Left Side @@ -2710,10 +2853,9 @@ class Debugger : public DebugInterface Thread *pThread = g_pEEInterface->GetThread(); AppDomain *pAppDomain = NULL; - if (pThread) { - pAppDomain = pThread->GetDomain(); + pAppDomain = AppDomain::GetCurrentDomain(); } InitIPCEvent(ipce, @@ -2806,6 +2948,13 @@ class Debugger : public DebugInterface BOOL m_unrecoverableError; BOOL m_ignoreThreadDetach; PTR_DebuggerMethodInfoTable m_pMethodInfos; + #ifdef DACCESS_COMPILE + VOID *m_pForceCatchHandlerFoundEventsTable; + VOID *m_pCustomNotificationTable; + #else + ForceCatchHandlerFoundTable *m_pForceCatchHandlerFoundEventsTable; + CustomNotificationTable *m_pCustomNotificationTable; + #endif // This is the main debugger lock. It is a large lock and used to synchronize complex operations @@ -3550,7 +3699,7 @@ inline void * __cdecl operator new[](size_t n, const InteropSafe&) return result; } -inline void * __cdecl operator new(size_t n, const InteropSafe&, const NoThrow&) throw() +inline void * __cdecl operator new(size_t n, const InteropSafe&, const std::nothrow_t&) noexcept { CONTRACTL { @@ -3569,7 +3718,7 @@ inline void * __cdecl operator new(size_t n, const InteropSafe&, const NoThrow&) return result; } -inline void * __cdecl operator new[](size_t n, const InteropSafe&, const NoThrow&) throw() +inline void * __cdecl operator new[](size_t n, const InteropSafe&, const std::nothrow_t&) noexcept { CONTRACTL { @@ -3744,7 +3893,7 @@ HANDLE OpenWin32EventOrThrow( // debugger may not be expecting it. Instead, just leave the lock and retry. // When we leave, we'll enter coop mode first and get suspended if a suspension is in progress. // Afterwards, we'll transition back into preemptive mode, and we'll block because this thread -// has been suspended by the debugger (see code:Thread::RareEnablePreemptiveGC). +// has been suspended by the debugger (see code:Thread::RareDisablePreemptiveGC). #define SENDIPCEVENT_BEGIN_EX(pDebugger, thread, gcxStmt) \ { \ FireEtwDebugIPCEventStart(); \ diff --git a/src/coreclr/debug/ee/debugger.inl b/src/coreclr/debug/ee/debugger.inl index 8b7a973f48ef..4a8ea12740f7 100644 --- a/src/coreclr/debug/ee/debugger.inl +++ b/src/coreclr/debug/ee/debugger.inl @@ -202,7 +202,7 @@ inline TADDR FuncEvalFrame::GetReturnAddressPtr() if (GetDebuggerEval()->m_evalDuringException) { - return NULL; + return (TADDR)NULL; } else { diff --git a/src/coreclr/debug/ee/frameinfo.cpp b/src/coreclr/debug/ee/frameinfo.cpp index 9193f90b6dc3..d7f9604b6ad7 100644 --- a/src/coreclr/debug/ee/frameinfo.cpp +++ b/src/coreclr/debug/ee/frameinfo.cpp @@ -760,7 +760,7 @@ void FrameInfo::InitFromStubHelper( this->internal = false; this->managed = true; this->relOffset = 0; - this->ambientSP = NULL; + this->ambientSP = (TADDR)NULL; // Method associated w/a stub will never have a JitManager. @@ -1019,7 +1019,7 @@ StackWalkAction TrackUMChain(CrawlFrame *pCF, DebuggerFrameData *d) // If we have a valid reg-display (non-null IP) then update it. // We may have an invalid reg-display if we have an exit frame on an inactive thread. REGDISPLAY * pNewRD = pCF->GetRegisterSet(); - if (GetControlPC(pNewRD) != NULL) + if (GetControlPC(pNewRD) != (PCODE)NULL) { LOG((LF_CORDB, LL_EVERYTHING, "DWSP. updating RD while tracking UM chain\n")); CopyREGDISPLAY(d->GetUMChainStartRD(), pNewRD); @@ -1538,7 +1538,7 @@ StackWalkAction DebuggerWalkStackProc(CrawlFrame *pCF, void *data) #endif // FEATURE_EH_FUNCLETS d->info.frame = frame; - d->info.ambientSP = NULL; + d->info.ambientSP = (TADDR)NULL; // Record the appdomain that the thread was in when it // was running code for this frame. diff --git a/src/coreclr/debug/ee/funceval.cpp b/src/coreclr/debug/ee/funceval.cpp index a7e888452c78..c0ed54095cea 100644 --- a/src/coreclr/debug/ee/funceval.cpp +++ b/src/coreclr/debug/ee/funceval.cpp @@ -1018,7 +1018,7 @@ static void GetFuncEvalArgValue(DebuggerEval *pDE, } else { - *pArgument = NULL; + *pArgument = (ARG_SLOT)NULL; } } } @@ -1051,7 +1051,7 @@ static void GetFuncEvalArgValue(DebuggerEval *pDE, } else { - *pArgument = NULL; + *pArgument = (ARG_SLOT)NULL; } } else @@ -1069,7 +1069,7 @@ static void GetFuncEvalArgValue(DebuggerEval *pDE, } else { - *pArgument = NULL; + *pArgument = (ARG_SLOT)NULL; } } else @@ -2955,7 +2955,7 @@ void UnpackFuncEvalResult(DebuggerEval *pDE, IsElementTypeSpecial(retClassET)) { LOG((LF_CORDB, LL_EVERYTHING, "Creating strong handle for boxed DoNormalFuncEval result.\n")); - OBJECTHANDLE oh = pDE->m_thread->GetDomain()->CreateStrongHandle(ArgSlotToObj(pDE->m_result[0])); + OBJECTHANDLE oh = AppDomain::GetCurrentDomain()->CreateStrongHandle(ArgSlotToObj(pDE->m_result[0])); pDE->m_result[0] = (INT64)(LONG_PTR)oh; pDE->m_vmObjectHandle = VMPTR_OBJECTHANDLE::MakePtr(oh); } @@ -3139,7 +3139,7 @@ static void RecordFuncEvalException(DebuggerEval *pDE, pDE->m_result[0] = ObjToArgSlot(ppException); pDE->m_resultType = ppException->GetTypeHandle(); - OBJECTHANDLE oh = pDE->m_thread->GetDomain()->CreateStrongHandle(ArgSlotToObj(pDE->m_result[0])); + OBJECTHANDLE oh = AppDomain::GetCurrentDomain()->CreateStrongHandle(ArgSlotToObj(pDE->m_result[0])); pDE->m_result[0] = (ARG_SLOT)(LONG_PTR)oh; pDE->m_vmObjectHandle = VMPTR_OBJECTHANDLE::MakePtr(oh); @@ -3682,7 +3682,7 @@ void FuncEvalHijackRealWorker(DebuggerEval *pDE, Thread* pThread, FuncEvalFrame* pDE->m_retValueBoxing = Debugger::AllBoxed; // Make a strong handle for the result. - OBJECTHANDLE oh = pDE->m_thread->GetDomain()->CreateStrongHandle(newObj); + OBJECTHANDLE oh = AppDomain::GetCurrentDomain()->CreateStrongHandle(newObj); pDE->m_result[0] = (ARG_SLOT)(LONG_PTR)oh; pDE->m_vmObjectHandle = VMPTR_OBJECTHANDLE::MakePtr(oh); @@ -3712,7 +3712,7 @@ void FuncEvalHijackRealWorker(DebuggerEval *pDE, Thread* pThread, FuncEvalFrame* pDE->m_resultType = newObj->GetTypeHandle(); // Place the result in a strong handle to protect it from a collection. - OBJECTHANDLE oh = pDE->m_thread->GetDomain()->CreateStrongHandle(newObj); + OBJECTHANDLE oh = AppDomain::GetCurrentDomain()->CreateStrongHandle(newObj); pDE->m_result[0] = (ARG_SLOT)(LONG_PTR)oh; pDE->m_vmObjectHandle = VMPTR_OBJECTHANDLE::MakePtr(oh); @@ -3758,7 +3758,7 @@ void FuncEvalHijackRealWorker(DebuggerEval *pDE, Thread* pThread, FuncEvalFrame* pDE->m_resultType = newObj->GetTypeHandle(); // Place the result in a strong handle to protect it from a collection. - OBJECTHANDLE oh = pDE->m_thread->GetDomain()->CreateStrongHandle(newObj); + OBJECTHANDLE oh = AppDomain::GetCurrentDomain()->CreateStrongHandle(newObj); pDE->m_result[0] = (ARG_SLOT)(LONG_PTR)oh; pDE->m_vmObjectHandle = VMPTR_OBJECTHANDLE::MakePtr(oh); @@ -3967,7 +3967,7 @@ void * STDCALL FuncEvalHijackWorker(DebuggerEval *pDE) // SENDIPCEVENT_BEGIN(g_pDebugger, pDE->m_thread); - if ((pDE->m_thread->GetDomain() != NULL) && pDE->m_thread->GetDomain()->IsDebuggerAttached()) + if ((AppDomain::GetCurrentDomain() != NULL) && AppDomain::GetCurrentDomain()->IsDebuggerAttached()) { if (CORDebuggerAttached()) diff --git a/src/coreclr/debug/ee/functioninfo.cpp b/src/coreclr/debug/ee/functioninfo.cpp index fad9ac786ba7..41a16ef76316 100644 --- a/src/coreclr/debug/ee/functioninfo.cpp +++ b/src/coreclr/debug/ee/functioninfo.cpp @@ -253,7 +253,7 @@ DebuggerJitInfo::DebuggerJitInfo(DebuggerMethodInfo *minfo, NativeCodeVersion na m_encBreakpointsApplied(false), #endif //FEATURE_METADATA_UPDATER m_methodInfo(minfo), - m_addrOfCode(NULL), + m_addrOfCode((CORDB_ADDRESS)NULL), m_sizeOfCode(0), m_prevJitInfo(NULL), m_nextJitInfo(NULL), m_lastIL(0), m_sequenceMap(NULL), @@ -1572,10 +1572,10 @@ DebuggerJitInfo *DebuggerMethodInfo::FindOrCreateInitAndAddJitInfo(MethodDesc* f return NULL; } - if (startAddr == NULL) + if (startAddr == (PCODE)NULL) { startAddr = g_pEEInterface->GetFunctionAddress(fd); - if (startAddr == NULL) + if (startAddr == (PCODE)NULL) { //The only case this should happen is if we are trying to get the DJI for a method that has not been jitted yet. return NULL; @@ -2355,7 +2355,7 @@ PTR_DebuggerJitInfo DebuggerMethodInfo::GetLatestJitInfo(MethodDesc *mdesc) // This ensures that there is an entry in the DJI list for this particular MethodDesc. // in the case of generic code it may not be the first entry in the list. - FindOrCreateInitAndAddJitInfo(mdesc, NULL /* startAddr */); + FindOrCreateInitAndAddJitInfo(mdesc, (PCODE)NULL /* startAddr */); #endif // #ifndef DACCESS_COMPILE diff --git a/src/coreclr/debug/inc/common.h b/src/coreclr/debug/inc/common.h index 16cfb852896d..8051138b93a0 100644 --- a/src/coreclr/debug/inc/common.h +++ b/src/coreclr/debug/inc/common.h @@ -17,15 +17,11 @@ inline CORDB_ADDRESS PTR_TO_CORDB_ADDRESS(const void* ptr) { SUPPORTS_DAC; - // Cast a void* to a ULONG is not 64-bit safe and triggers compiler warning C3411. - // But this is x86 only, so we know it's ok. Use PtrToUlong to do the conversion - // without invoking the error. - return (CORDB_ADDRESS)(PtrToUlong(ptr)); + return (CORDB_ADDRESS)(ULONG)(UINT_PTR)ptr; } inline CORDB_ADDRESS PTR_TO_CORDB_ADDRESS(UINT_PTR ptr) { SUPPORTS_DAC; - // PtrToUlong return (CORDB_ADDRESS)(ULONG)(ptr); } #else diff --git a/src/coreclr/debug/inc/dacdbistructures.h b/src/coreclr/debug/inc/dacdbistructures.h index ccb92dfd5209..e91cd9fb9bb4 100644 --- a/src/coreclr/debug/inc/dacdbistructures.h +++ b/src/coreclr/debug/inc/dacdbistructures.h @@ -499,7 +499,7 @@ class MSLAYOUT NativeCodeFunctionData // method hasn't been jitted yet. // In all cases, we can check the hot region start address to determine whether the rest of the // the information is valid. - BOOL IsValid() { return (m_rgCodeRegions[kHot].pAddress != NULL); } + BOOL IsValid() { return (m_rgCodeRegions[kHot].pAddress != (CORDB_ADDRESS)NULL); } void Clear(); // data members diff --git a/src/coreclr/debug/inc/dacdbistructures.inl b/src/coreclr/debug/inc/dacdbistructures.inl index e31583faff58..a408a2c1ffb8 100644 --- a/src/coreclr/debug/inc/dacdbistructures.inl +++ b/src/coreclr/debug/inc/dacdbistructures.inl @@ -166,7 +166,7 @@ unsigned int DacDbiArrayList::Count() const inline TargetBuffer::TargetBuffer() { - this->pAddress = NULL; + this->pAddress = (CORDB_ADDRESS)NULL; this->cbSize = 0; } @@ -219,7 +219,7 @@ TargetBuffer TargetBuffer::SubBuffer(ULONG byteOffset, ULONG byteLength) const inline void TargetBuffer::Clear() { - pAddress = NULL; + pAddress = (CORDB_ADDRESS)NULL; cbSize = 0; } @@ -637,14 +637,14 @@ void FieldData::ClearFields() m_fldSignatureCache = NULL; m_fldSignatureCacheSize = 0; m_fldInstanceOffset = 0; - m_pFldStaticAddress = NULL; + m_pFldStaticAddress = (TADDR)NULL; } inline BOOL FieldData::OkToGetOrSetInstanceOffset() { return (!m_fFldIsStatic && !m_fFldIsRVA && !m_fFldIsTLS && - m_fFldStorageAvailable && (m_pFldStaticAddress == NULL)); + m_fFldStorageAvailable && (m_pFldStaticAddress == (TADDR)NULL)); } // If this is an instance field, store its offset @@ -655,7 +655,7 @@ void FieldData::SetInstanceOffset(SIZE_T offset) _ASSERTE(!m_fFldIsRVA); _ASSERTE(!m_fFldIsTLS); _ASSERTE(m_fFldStorageAvailable); - _ASSERTE(m_pFldStaticAddress == NULL); + _ASSERTE(m_pFldStaticAddress == (TADDR)NULL); m_fldInstanceOffset = offset; } @@ -685,7 +685,7 @@ SIZE_T FieldData::GetInstanceOffset() _ASSERTE(!m_fFldIsRVA); _ASSERTE(!m_fFldIsTLS); _ASSERTE(m_fFldStorageAvailable); - _ASSERTE(m_pFldStaticAddress == NULL); + _ASSERTE(m_pFldStaticAddress == (TADDR)NULL); return m_fldInstanceOffset; } @@ -695,7 +695,7 @@ TADDR FieldData::GetStaticAddress() { _ASSERTE(m_fFldIsStatic); _ASSERTE(!m_fFldIsTLS); - _ASSERTE(m_fFldStorageAvailable || (m_pFldStaticAddress == NULL)); + _ASSERTE(m_fFldStorageAvailable || (m_pFldStaticAddress == (TADDR)NULL)); _ASSERTE(m_fldInstanceOffset == 0); return m_pFldStaticAddress; } diff --git a/src/coreclr/debug/inc/dbgappdomain.h b/src/coreclr/debug/inc/dbgappdomain.h index 6ef343d01e72..de8a06b38c9e 100644 --- a/src/coreclr/debug/inc/dbgappdomain.h +++ b/src/coreclr/debug/inc/dbgappdomain.h @@ -117,7 +117,7 @@ struct RemoteHANDLE { BOOL DuplicateToLocalProcess(HANDLE hProcess, HANDLE* pHandle) { return DuplicateHandle(hProcess, m_hLocal, GetCurrentProcess(), pHandle, - NULL, FALSE, DUPLICATE_SAME_ACCESS); + 0, FALSE, DUPLICATE_SAME_ACCESS); } void CloseInRemoteProcess(HANDLE hProcess) @@ -127,7 +127,7 @@ struct RemoteHANDLE { HANDLE hTmp; if (DuplicateHandle(hProcess, hHandle, GetCurrentProcess(), &hTmp, - NULL, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) + 0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) { CloseHandle(hTmp); } diff --git a/src/coreclr/debug/inc/dbgipcevents.h b/src/coreclr/debug/inc/dbgipcevents.h index 1545aa280837..6c39939f0030 100644 --- a/src/coreclr/debug/inc/dbgipcevents.h +++ b/src/coreclr/debug/inc/dbgipcevents.h @@ -10,7 +10,7 @@ #ifndef _DbgIPCEvents_h_ #define _DbgIPCEvents_h_ -#include +#include #include #include #include // for ICorDebugInfo::VarLocType & VarLoc @@ -25,6 +25,8 @@ #include "./common.h" +using std::nothrow; + //----------------------------------------------------------------------------- // V3 additions to IPC protocol between LS and RS. //----------------------------------------------------------------------------- @@ -780,7 +782,7 @@ class MSLAYOUT VMPTR_Base #endif // _PREFAST_ VMPTR_This dummy; - dummy.m_addr = NULL; + dummy.m_addr = (TADDR)NULL; return dummy; #ifdef _PREFAST_ @@ -2054,6 +2056,19 @@ struct MSLAYOUT DebuggerIPCEvent VMPTR_Module pModule; } DisableOptData; + struct MSLAYOUT + { + BOOL enableEvents; + VMPTR_Object vmObj; + } ForceCatchHandlerFoundData; + + struct MSLAYOUT + { + VMPTR_Module vmModule; + mdTypeDef classMetadataToken; + BOOL Enabled; + } CustomNotificationData; + struct MSLAYOUT { LSPTR_BREAKPOINT breakpointToken; diff --git a/src/coreclr/debug/inc/dbgipceventtypes.h b/src/coreclr/debug/inc/dbgipceventtypes.h index 9c3a09afcf9b..0c028619b69e 100644 --- a/src/coreclr/debug/inc/dbgipceventtypes.h +++ b/src/coreclr/debug/inc/dbgipceventtypes.h @@ -93,7 +93,9 @@ IPC_EVENT_TYPE1(DB_IPCE_DATA_BREAKPOINT ,0x0160) IPC_EVENT_TYPE1(DB_IPCE_BEFORE_GARBAGE_COLLECTION ,0x0161) IPC_EVENT_TYPE1(DB_IPCE_AFTER_GARBAGE_COLLECTION ,0x0162) IPC_EVENT_TYPE1(DB_IPCE_DISABLE_OPTS_RESULT ,0x0163) -IPC_EVENT_TYPE0(DB_IPCE_RUNTIME_LAST ,0x0165) // The last event from runtime +IPC_EVENT_TYPE1(DB_IPCE_CATCH_HANDLER_FOUND_RESULT ,0x0165) +IPC_EVENT_TYPE1(DB_IPCE_SET_ENABLE_CUSTOM_NOTIFICATION_RESULT, 0x0166) +IPC_EVENT_TYPE0(DB_IPCE_RUNTIME_LAST ,0x0167) // The last event from runtime @@ -143,5 +145,7 @@ IPC_EVENT_TYPE2(DB_IPCE_GET_GCHANDLE_INFO ,0x0251) IPC_EVENT_TYPE2(DB_IPCE_RESOLVE_UPDATE_METADATA_1 ,0x0256) IPC_EVENT_TYPE2(DB_IPCE_RESOLVE_UPDATE_METADATA_2 ,0x0257) IPC_EVENT_TYPE2(DB_IPCE_DISABLE_OPTS ,0x0258) -IPC_EVENT_TYPE0(DB_IPCE_DEBUGGER_LAST ,0x025A) // The last event from the debugger +IPC_EVENT_TYPE2(DB_IPCE_FORCE_CATCH_HANDLER_FOUND ,0x025A) +IPC_EVENT_TYPE2(DB_IPCE_SET_ENABLE_CUSTOM_NOTIFICATION, 0x025B) +IPC_EVENT_TYPE0(DB_IPCE_DEBUGGER_LAST ,0x025C) // The last event from the debugger diff --git a/src/coreclr/debug/runtimeinfo/CMakeLists.txt b/src/coreclr/debug/runtimeinfo/CMakeLists.txt index e6d45ada1201..77ecf9a4dd9b 100644 --- a/src/coreclr/debug/runtimeinfo/CMakeLists.txt +++ b/src/coreclr/debug/runtimeinfo/CMakeLists.txt @@ -37,3 +37,58 @@ endif() # publish runtimeinfo lib install_clr(TARGETS runtimeinfo DESTINATIONS lib COMPONENT runtime) + + +# cDAC contract descriptor + +if (NOT CDAC_BUILD_TOOL_BINARY_PATH) + # if CDAC_BUILD_TOOL_BINARY_PATH is unspecified (for example for a build without a .NET SDK or msbuild), + # link a stub contract descriptor into the runtime + add_library_clr(cdac_contract_descriptor OBJECT contractdescriptorstub.c) + message(STATUS "Using a stub cDAC contract descriptor") +else() + # generate a contract descriptor using cdac-build-tool from a data descriptor and contract json file + + add_library(cdac_data_descriptor OBJECT datadescriptor.cpp) + # don't build the data descriptor before the VM (and any of its dependencies' generated headers) + add_dependencies(cdac_data_descriptor cee_wks_core) + if(CLR_CMAKE_TARGET_WIN32) + # turn off whole program optimization: + # 1. it creates object files that cdac-build-tool can't read + # 2. we never link cdac_data_descriptor into the final product - it's only job is to be scraped + target_compile_options(cdac_data_descriptor PRIVATE /GL-) + endif() + target_include_directories(cdac_data_descriptor BEFORE PRIVATE ${VM_DIR}) + target_include_directories(cdac_data_descriptor BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR}) + target_include_directories(cdac_data_descriptor PRIVATE ${CLR_DIR}/interop/inc) + + set(GENERATED_CDAC_DESCRIPTOR_DIR "${CMAKE_CURRENT_BINARY_DIR}/cdac") + set(CONTRACT_DESCRIPTOR_OUTPUT "${GENERATED_CDAC_DESCRIPTOR_DIR}/contract-descriptor.c") + if(NOT EXISTS "${CDAC_BUILD_TOOL_BINARY_PATH}") + message(FATAL_ERROR "${CDAC_BUILD_TOOL_BINARY_PATH} does not exist") + endif() + + set(CONTRACT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/contracts.jsonc") + + # generate the contract descriptor by running cdac-build-tool + # n.b. this just uses `dotnet` from the PATH. InitializeDotNetCli adds the apropropriate directory + add_custom_command( + OUTPUT "${CONTRACT_DESCRIPTOR_OUTPUT}" + VERBATIM + COMMAND ${CLR_DOTNET_HOST_PATH} ${CDAC_BUILD_TOOL_BINARY_PATH} compose -o "${CONTRACT_DESCRIPTOR_OUTPUT}" -c "${CONTRACT_FILE}" $ + DEPENDS cdac_data_descriptor cee_wks_core $ "${CONTRACT_FILE}" + USES_TERMINAL + ) + + # It is important that cdac_contract_descriptor is an object library; + # if it was static, linking it into the final dll would not export + # DotNetRuntimeContractDescriptor since it is not referenced anywhere. + add_library_clr(cdac_contract_descriptor OBJECT + "${CONTRACT_DESCRIPTOR_OUTPUT}" + contractpointerdata.cpp + ) + target_include_directories(cdac_contract_descriptor BEFORE PRIVATE ${VM_DIR}) + target_include_directories(cdac_contract_descriptor BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR}) + target_include_directories(cdac_contract_descriptor PRIVATE ${CLR_DIR}/interop/inc) + add_dependencies(cdac_contract_descriptor cdac_data_descriptor cee_wks_core) +endif() diff --git a/src/coreclr/debug/runtimeinfo/contractdescriptorstub.c b/src/coreclr/debug/runtimeinfo/contractdescriptorstub.c new file mode 100644 index 000000000000..59421a6692d2 --- /dev/null +++ b/src/coreclr/debug/runtimeinfo/contractdescriptorstub.c @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include + +#ifdef _MSC_VER +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT __attribute__((visibility("default"))) +#endif + +struct DotNetRuntimeContractDescriptor +{ + uint64_t magic; + uint32_t flags; + const uint32_t descriptor_size; + const char *descriptor; + const uint32_t pointer_data_count; + uint32_t pad0; + const uintptr_t *pointer_data; +}; + +extern const uintptr_t contractDescriptorPointerData[]; + +// just the placeholder pointer +const uintptr_t contractDescriptorPointerData[] = { (uintptr_t)0 }; + +DLLEXPORT struct DotNetRuntimeContractDescriptor DotNetRuntimeContractDescriptor; + +#define STUB_DESCRIPTOR "{\"version\":0,\"baseline\":\"empty\",\"contracts\":{},\"types\":{},\"globals\":{}}" + +DLLEXPORT struct DotNetRuntimeContractDescriptor DotNetRuntimeContractDescriptor = { + .magic = 0x0043414443434e44ull, // "DNCCDAC\0" + .flags = 0x1u & (sizeof(void*) == 4 ? 0x02u : 0x00u), + .descriptor_size = sizeof(STUB_DESCRIPTOR), + .descriptor = STUB_DESCRIPTOR, + .pointer_data_count = 1, + .pointer_data = &contractDescriptorPointerData[0], +}; diff --git a/src/coreclr/debug/runtimeinfo/contractpointerdata.cpp b/src/coreclr/debug/runtimeinfo/contractpointerdata.cpp new file mode 100644 index 000000000000..ae1440af4219 --- /dev/null +++ b/src/coreclr/debug/runtimeinfo/contractpointerdata.cpp @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "common.h" + +#include +#include + +#include "threads.h" + +extern "C" +{ + +// without an extern declaration, clang does not emit this global into the object file +extern const uintptr_t contractDescriptorPointerData[]; + +const uintptr_t contractDescriptorPointerData[] = { + (uintptr_t)0, // placeholder +#define CDAC_GLOBAL_POINTER(name,value) (uintptr_t)(value), +#include "datadescriptor.h" +}; + +} diff --git a/src/coreclr/debug/runtimeinfo/contracts.jsonc b/src/coreclr/debug/runtimeinfo/contracts.jsonc new file mode 100644 index 000000000000..ab82fbc38c40 --- /dev/null +++ b/src/coreclr/debug/runtimeinfo/contracts.jsonc @@ -0,0 +1,15 @@ +//algorithmic contracts for coreclr +// The format of this file is: JSON with comments +// { +// "CONTRACT NAME": VERSION, +// ... +// } +// CONTRACT NAME is an arbitrary string, VERSION is an integer +// +// cdac-build-tool can take multiple "-c contract_file" arguments +// so to conditionally include contracts, put additional contracts in a separate file +{ + "Thread": 1, + "SOSBreakingChangeVersion": 1 // example contract: "runtime exports an SOS breaking change version global" +} + diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.cpp b/src/coreclr/debug/runtimeinfo/datadescriptor.cpp new file mode 100644 index 000000000000..99fe1cca7eec --- /dev/null +++ b/src/coreclr/debug/runtimeinfo/datadescriptor.cpp @@ -0,0 +1,297 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "common.h" + +#include +#include + +#include "static_assert.h" + +#include +#include "threads.h" + +// begin blob definition + +extern "C" +{ + +struct TypeSpec +{ + uint32_t Name; + uint32_t Fields; + uint16_t Size; // note: C++ fragile no designated initializers - Size must come after Name and Fields +}; + +struct FieldSpec +{ + uint32_t Name; + uint32_t TypeName; + uint16_t FieldOffset; +}; + +struct GlobalLiteralSpec +{ + uint32_t Name; + uint32_t TypeName; + uint64_t Value; +}; + +struct GlobalPointerSpec +{ + uint32_t Name; + uint32_t PointerDataIndex; +}; + +#define CONCAT(token1,token2) token1 ## token2 +#define CONCAT4(token1, token2, token3, token4) token1 ## token2 ## token3 ## token4 + +#define MAKE_TYPELEN_NAME(tyname) CONCAT(cdac_string_pool_typename__, tyname) +#define MAKE_FIELDLEN_NAME(tyname,membername) CONCAT4(cdac_string_pool_membername__, tyname, __, membername) +#define MAKE_FIELDTYPELEN_NAME(tyname,membername) CONCAT4(cdac_string_pool_membertypename__, tyname, __, membername) +#define MAKE_GLOBALLEN_NAME(globalname) CONCAT(cdac_string_pool_globalname__, globalname) +#define MAKE_GLOBALTYPELEN_NAME(globalname) CONCAT(cdac_string_pool_globaltypename__, globalname) + +// define a struct where the size of each field is the length of some string. we will use offsetof to get +// the offset of each struct element, which will be equal to the offset of the beginning of that string in the +// string pool. +struct CDacStringPoolSizes +{ + char cdac_string_pool_nil; // make the first real string start at offset 1 +#define DECL_LEN(membername,len) char membername[(len)]; +#define CDAC_BASELINE(name) DECL_LEN(cdac_string_pool_baseline_, (sizeof(name))) +#define CDAC_TYPE_BEGIN(name) DECL_LEN(MAKE_TYPELEN_NAME(name), sizeof(#name)) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) DECL_LEN(MAKE_FIELDLEN_NAME(tyname,membername), sizeof(#membername)) \ + DECL_LEN(MAKE_FIELDTYPELEN_NAME(tyname,membername), sizeof(#membertyname)) +#define CDAC_GLOBAL_POINTER(name,value) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name)) +#define CDAC_GLOBAL(name,tyname,value) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name)) \ + DECL_LEN(MAKE_GLOBALTYPELEN_NAME(name), sizeof(#tyname)) +#include "datadescriptor.h" + char cdac_string_pool_trailing_nil; +#undef DECL_LEN +}; + +#define GET_TYPE_NAME(name) offsetof(struct CDacStringPoolSizes, MAKE_TYPELEN_NAME(name)) +#define GET_FIELD_NAME(tyname,membername) offsetof(struct CDacStringPoolSizes, MAKE_FIELDLEN_NAME(tyname,membername)) +#define GET_FIELDTYPE_NAME(tyname,membername) offsetof(struct CDacStringPoolSizes, MAKE_FIELDTYPELEN_NAME(tyname,membername)) +#define GET_GLOBAL_NAME(globalname) offsetof(struct CDacStringPoolSizes, MAKE_GLOBALLEN_NAME(globalname)) +#define GET_GLOBALTYPE_NAME(globalname) offsetof(struct CDacStringPoolSizes, MAKE_GLOBALTYPELEN_NAME(globalname)) + +// count the types +enum +{ + CDacBlobTypesCount = +#define CDAC_TYPES_BEGIN() 0 +#define CDAC_TYPE_BEGIN(name) + 1 +#include "datadescriptor.h" +}; + +// count the field pool size. +// there's 1 placeholder element at the start, and 1 endmarker after each type +enum +{ + CDacBlobFieldsPoolCount = +#define CDAC_TYPES_BEGIN() 1 +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) + 1 +#define CDAC_TYPE_END(name) + 1 +#include "datadescriptor.h" +}; + +// count the literal globals +enum +{ + CDacBlobGlobalLiteralsCount = +#define CDAC_GLOBALS_BEGIN() 0 +#define CDAC_GLOBAL(name,tyname,value) + 1 +#include "datadescriptor.h" +}; + +// count the aux vector globals +enum +{ + CDacBlobGlobalPointersCount = +#define CDAC_GLOBALS_BEGIN() 0 +#define CDAC_GLOBAL_POINTER(name,value) + 1 +#include "datadescriptor.h" +}; + + +#define MAKE_TYPEFIELDS_TYNAME(tyname) CONCAT(CDacFieldsPoolTypeStart__, tyname) + +// index of each run of fields. +// we make a struct containing one 1-byte field for each field in the run, and then take the offset of the +// struct to get the index of the run of fields. +// this looks like +// +// struct CDacFieldsPoolSizes { +// char cdac_fields_pool_start_placeholder__; +// struct CDacFieldsPoolTypeStart__MethodTable { +// char cdac_fields_pool_member__MethodTable__GCHandle; +// char cdac_fields_pool_member__MethodTable_endmarker; +// } CDacFieldsPoolTypeStart__MethodTable; +// ... +// }; +// +// so that offsetof(struct CDacFieldsPoolSizes, CDacFieldsPoolTypeStart__MethodTable) will give the offset of the +// method table field descriptors in the run of fields +struct CDacFieldsPoolSizes +{ +#define DECL_LEN(membername) char membername; +#define CDAC_TYPES_BEGIN() DECL_LEN(cdac_fields_pool_start_placeholder__) +#define CDAC_TYPE_BEGIN(name) struct MAKE_TYPEFIELDS_TYNAME(name) { +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) DECL_LEN(CONCAT4(cdac_fields_pool_member__, tyname, __, membername)) +#define CDAC_TYPE_END(name) DECL_LEN(CONCAT4(cdac_fields_pool_member__, tyname, _, endmarker)) \ + } MAKE_TYPEFIELDS_TYNAME(name); +#include "datadescriptor.h" +#undef DECL_LEN +}; + +#define GET_TYPE_FIELDS(tyname) offsetof(struct CDacFieldsPoolSizes, MAKE_TYPEFIELDS_TYNAME(tyname)) + +// index of each global pointer +// +// struct CDacGlobalPointerIndex +// { +// char placeholder; +// char firstGlobalPointerName; +// char secondGlobalPointerName; +// ... +//} +// +// offsetof (CDACGlobalPointerIndex, NAME) returns the index of the global +struct CDacGlobalPointerIndex +{ +#define DECL_LEN(membername) char membername; +#define CDAC_GLOBALS_BEGIN() DECL_LEN(cdac_global_pointer_index_start_placeholder__) +#define CDAC_GLOBAL_POINTER(name,value) DECL_LEN(CONCAT(cdac_global_pointer_index__, name)) +#include "datadescriptor.h" +#undef DECL_LEN +}; + +#define GET_GLOBAL_POINTER_INDEX(name) offsetof(struct CDacGlobalPointerIndex, CONCAT(cdac_global_pointer_index__, name)) + +struct BinaryBlobDataDescriptor +{ + // The blob begins with a directory that gives the relative offsets of the `Baseline`, `Types`, + // `FieldsPool`, `GlobalLiteralValues`, `GlobalPointerValues` and `Names` fields of the blob. + // The number of elements of each of the arrays is next. This is followed by the sizes of the + // spec structs. Since `BinaryBlobDataDescriptor` is created via macros, we want to embed the + // `offsetof` and `sizeof` of the components of the blob into the blob itself without having to + // account for any padding that the C/C++ compiler may introduce to enforce alignment. + // Additionally the `Directory` tries to follow a common C/C++ alignment rule (we don't want + // padding introduced in the directory itself): N-byte members are aligned to start on N-byte + // boundaries. + struct Directory { + uint32_t FlagsAndBaselineStart; + uint32_t TypesStart; + + uint32_t FieldsPoolStart; + uint32_t GlobalLiteralValuesStart; + + uint32_t GlobalPointersStart; + uint32_t NamesPoolStart; + + uint32_t TypeCount; + uint32_t FieldsPoolCount; + + uint32_t GlobalLiteralValuesCount; + uint32_t GlobalPointerValuesCount; + + uint32_t NamesPoolCount; + + uint8_t TypeSpecSize; + uint8_t FieldSpecSize; + uint8_t GlobalLiteralSpecSize; + uint8_t GlobalPointerSpecSize; + } Directory; + uint32_t PlatformFlags; + uint32_t BaselineName; + struct TypeSpec Types[CDacBlobTypesCount]; + struct FieldSpec FieldsPool[CDacBlobFieldsPoolCount]; + struct GlobalLiteralSpec GlobalLiteralValues[CDacBlobGlobalLiteralsCount]; + struct GlobalPointerSpec GlobalPointerValues[CDacBlobGlobalPointersCount]; + uint8_t NamesPool[sizeof(struct CDacStringPoolSizes)]; + uint8_t EndMagic[4]; +}; + +struct MagicAndBlob { + uint64_t magic; + struct BinaryBlobDataDescriptor Blob; +}; + +// we only support 32-bit and 64-bit right now +static_assert_no_msg(sizeof(void*) == 4 || sizeof(void*) == 8); + +// C-style designated initializers are a C++20 feature. Have to use plain old aggregate initialization instead. + +DLLEXPORT +struct MagicAndBlob BlobDataDescriptor = { + /*.magic = */ 0x00424F4C42434144ull,// "DACBLOB", + /*.Blob =*/ { + /*.Directory =*/ { + /* .FlagsAndBaselineStart = */ offsetof(struct BinaryBlobDataDescriptor, PlatformFlags), + /* .TypesStart = */ offsetof(struct BinaryBlobDataDescriptor, Types), + /* .FieldsPoolStart = */ offsetof(struct BinaryBlobDataDescriptor, FieldsPool), + /* .GlobalLiteralValuesStart = */ offsetof(struct BinaryBlobDataDescriptor, GlobalLiteralValues), + /* .GlobalPointersStart = */ offsetof(struct BinaryBlobDataDescriptor, GlobalPointerValues), + /* .NamesPoolStart = */ offsetof(struct BinaryBlobDataDescriptor, NamesPool), + /* .TypeCount = */ CDacBlobTypesCount, + /* .FieldsPoolCount = */ CDacBlobFieldsPoolCount, + /* .GlobalLiteralValuesCount = */ CDacBlobGlobalLiteralsCount, + /* .GlobalPointerValuesCount = */ CDacBlobGlobalPointersCount, + /* .NamesPoolCount = */ sizeof(struct CDacStringPoolSizes), + /* .TypeSpecSize = */ sizeof(struct TypeSpec), + /* .FieldSpecSize = */ sizeof(struct FieldSpec), + /* .GlobalLiteralSpecSize = */ sizeof(struct GlobalLiteralSpec), + /* .GlobalPointerSpecSize = */ sizeof(struct GlobalPointerSpec), + }, + /* .PlatformFlags = */ (sizeof(void*) == 4 ? 0x02 : 0) | 0x01, + /* .BaselineName = */ offsetof(struct CDacStringPoolSizes, cdac_string_pool_baseline_), + + /* .Types = */ { +#define CDAC_TYPE_BEGIN(name) { \ + /* .Name = */ GET_TYPE_NAME(name), \ + /* .Fields = */ GET_TYPE_FIELDS(name), +#define CDAC_TYPE_INDETERMINATE(name) /*.Size = */ 0, +#define CDAC_TYPE_SIZE(size) /* .Size = */ size, +#define CDAC_TYPE_END(name) }, +#include "datadescriptor.h" + }, + + /* .FieldsPool = */ { +#define CDAC_TYPES_BEGIN() {0,}, +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) { \ + /* .Name = */ GET_FIELD_NAME(tyname,membername), \ + /* .TypeName = */ GET_FIELDTYPE_NAME(tyname,membername), \ + /* .FieldOffset = */ offset, \ +}, +#define CDAC_TYPE_END(name) { 0, }, +#include "datadescriptor.h" + }, + + /* .GlobalLiteralValues = */ { +#define CDAC_GLOBAL(name,tyname,value) { /*.Name = */ GET_GLOBAL_NAME(name), /* .TypeName = */ GET_GLOBALTYPE_NAME(name), /* .Value = */ value }, +#include "datadescriptor.h" + }, + + /* .GlobalPointerValues = */ { +#define CDAC_GLOBAL_POINTER(name,value) { /* .Name = */ GET_GLOBAL_NAME(name), /* .PointerDataIndex = */ GET_GLOBAL_POINTER_INDEX(name) }, +#include "datadescriptor.h" + }, + + /* .NamesPool = */ ("\0" // starts with a nul +#define CDAC_BASELINE(name) name "\0" +#define CDAC_TYPE_BEGIN(name) #name "\0" +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) #membername "\0" #membertyname "\0" +#define CDAC_GLOBAL_POINTER(name,value) #name "\0" +#define CDAC_GLOBAL(name,tyname,value) #name "\0" #tyname "\0" +#include "datadescriptor.h" + ), + + /* .EndMagic = */ { 0x01, 0x02, 0x03, 0x04 }, + } +}; + +// end blob definition + +} // extern "C" diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.h b/src/coreclr/debug/runtimeinfo/datadescriptor.h new file mode 100644 index 000000000000..2687ceff5535 --- /dev/null +++ b/src/coreclr/debug/runtimeinfo/datadescriptor.h @@ -0,0 +1,145 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// No include guards. This file is included multiple times. + +// The format is: +// CDAC_BASELINE("string") baseline data contract that the runtime should follow. "empty" is reasonable +// CDAC_TYPES_BEGIN() +// ... ... +// CDAC_TYPES_END() +// CDAC_GLOBALS_BEGIN() +// ... ... +// CDAC_GLOBALS_END() +// +// In the format is: +// CDAC_TYPE_BEGIN(cdacTypeIdentifier) // defined a new data descriptor named cdacIdentifier +// +// CDAC_TYPE_SIZE(k) -or- CDAC_TYPE_INDETERMINATE(cdacTypeIdentifier) specifies that the type has +// size k (bytes - usually sizeof(SomeNativeType)) or specify that the type's size is not provided +// It is important that CDAC_TYPE_SIZE or CDAC_TYPE_INDETERMINATE immediately follows +// CDAC_TYPE_BEGIN +// +// CDAC_TYPE_FIELD(cdacTypeIdentifier, cdacFieldTypeIdentifier, cdacFieldName, k) specifies the +// field of "cdacTypeIdentifier" that has name cdacFieldName and has the type +// "cdacFieldtypeIdentifier" located at offset k in the type layout. k is usually +// offsetof(SomeClass, m_FieldName) if the field is public +// +// if the field is private, the convention is that SomeClass declares a friend struct +// cdac_offsets and provides a specialization of cdac_offsets with a public constexpr +// size_t member that holds the offset: +// +// class MyClass { +// private: +// void* m_myField; +// friend template cdac_offsets; +// }; +// template<> struct cdac_offsets { +// static constexpr size_t MyField = offsetof(MyClass, m_myField); +// }; +// +// then the field layout can be specified as +// CDAC_TYPE_FIELD(MyClassLayout, pointer, MyField, cdac_offsets::MyField) +// There can be zero or more CDAC_TYPE_FIELD entries per type layout +// +// CDAC_TYPE_END(cdacTypeIdentifier) specifies the end of the type layout for cdacTypeIdentifier +// +// In the format is: +// +// CDAC_GLOBAL(cdacGlobalName, cdacTypeIdentifier, value) +// or +// CDAC_GLOBAL_POINTER(cdacGlobalName, cdacTypeIdentifier, address) +// +// Zero or more globals can be defined +// +// if a global is given with CDAC_GLOBAL(), `value` should be a constexpr uint64_t (or convertible +// to uint64_t) for example, it can be a literal constant or a preprocessor definition +// +// if a global is a CDAC_GLOBAL_POINTER(), address should be a constexpr pointer or a constexpr +// uintptr_t +// +// +// +// This file is compiled using the target architecture. Preprocessor defines for the target +// platform will be available. It is ok to use `#ifdef`. + +#ifndef CDAC_BASELINE +#define CDAC_BASELINE(identifier) +#endif +#ifndef CDAC_TYPES_BEGIN +#define CDAC_TYPES_BEGIN() +#endif +#ifndef CDAC_TYPE_BEGIN +#define CDAC_TYPE_BEGIN(tyname) +#endif +#ifndef CDAC_TYPE_SIZE +#define CDAC_TYPE_SIZE(k) +#endif +#ifndef CDAC_TYPE_INDETERMINATE +#define CDAC_TYPE_INDETERMINATE(tyname) +#endif +#ifndef CDAC_TYPE_FIELD +#define CDAC_TYPE_FIELD(tyname,fieldtyname,fieldname,off) +#endif +#ifndef CDAC_TYPE_END +#define CDAC_TYPE_END(tyname) +#endif +#ifndef CDAC_TYPES_END +#define CDAC_TYPES_END() +#endif +#ifndef CDAC_GLOBALS_BEGIN +#define CDAC_GLOBALS_BEGIN() +#endif +#ifndef CDAC_GLOBAL +#define CDAC_GLOBAL(globalname,tyname,val) +#endif +#ifndef CDAC_GLOBAL_POINTER +#define CDAC_GLOBAL_POINTER(globalname,addr) +#endif +#ifndef CDAC_GLOBALS_END +#define CDAC_GLOBALS_END() +#endif + +CDAC_BASELINE("empty") +CDAC_TYPES_BEGIN() + +CDAC_TYPE_BEGIN(Thread) +CDAC_TYPE_INDETERMINATE(Thread) +CDAC_TYPE_FIELD(Thread, GCHandle, GCHandle, cdac_offsets::ExposedObject) +CDAC_TYPE_FIELD(Thread, pointer, LinkNext, cdac_offsets::Link) +CDAC_TYPE_END(Thread) + +CDAC_TYPE_BEGIN(ThreadStore) +CDAC_TYPE_INDETERMINATE(ThreadStore) +CDAC_TYPE_FIELD(ThreadStore, /*omit type*/, ThreadCount, cdac_offsets::ThreadCount) +CDAC_TYPE_FIELD(ThreadStore, /*omit type*/, ThreadList, cdac_offsets::ThreadList) +CDAC_TYPE_END(ThreadStore) + +CDAC_TYPE_BEGIN(GCHandle) +CDAC_TYPE_SIZE(sizeof(OBJECTHANDLE)) +CDAC_TYPE_END(GCHandle) + +CDAC_TYPES_END() + +CDAC_GLOBALS_BEGIN() +CDAC_GLOBAL_POINTER(ThreadStore, &ThreadStore::s_pThreadStore) +#if FEATURE_EH_FUNCLETS +CDAC_GLOBAL(FeatureEHFunclets, uint8, 1) +#else +CDAC_GLOBAL(FeatureEHFunclets, uint8, 0) +#endif +CDAC_GLOBAL(SOSBreakingChangeVersion, uint8, SOS_BREAKING_CHANGE_VERSION) +CDAC_GLOBALS_END() + +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef CDAC_TYPES_END +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBALS_END diff --git a/src/coreclr/debug/shared/dbgtransportsession.cpp b/src/coreclr/debug/shared/dbgtransportsession.cpp index 3bebb8282aed..f05cb0007c8e 100644 --- a/src/coreclr/debug/shared/dbgtransportsession.cpp +++ b/src/coreclr/debug/shared/dbgtransportsession.cpp @@ -2203,6 +2203,7 @@ DWORD DbgTransportSession::GetEventSize(DebuggerIPCEvent *pEvent) case DB_IPCE_BEFORE_GARBAGE_COLLECTION: case DB_IPCE_AFTER_GARBAGE_COLLECTION: case DB_IPCE_DISABLE_OPTS_RESULT: + case DB_IPCE_CATCH_HANDLER_FOUND_RESULT: cbAdditionalSize = 0; break; @@ -2502,6 +2503,14 @@ DWORD DbgTransportSession::GetEventSize(DebuggerIPCEvent *pEvent) cbAdditionalSize = sizeof(pEvent->DisableOptData); break; + case DB_IPCE_FORCE_CATCH_HANDLER_FOUND: + cbAdditionalSize = sizeof(pEvent->ForceCatchHandlerFoundData); + break; + + case DB_IPCE_SET_ENABLE_CUSTOM_NOTIFICATION: + cbAdditionalSize = sizeof(pEvent->CustomNotificationData); + break; + default: STRESS_LOG1(LF_CORDB, LL_INFO1000, "Unknown debugger event type: 0x%x\n", (pEvent->type & DB_IPCE_TYPE_MASK)); _ASSERTE(!"Unknown debugger event type"); diff --git a/src/coreclr/debug/shared/utils.cpp b/src/coreclr/debug/shared/utils.cpp index 73badc2e0575..b3fdc5bc3494 100644 --- a/src/coreclr/debug/shared/utils.cpp +++ b/src/coreclr/debug/shared/utils.cpp @@ -46,7 +46,7 @@ CORDB_ADDRESS IsEventDebuggerNotification( // If it's not even our exception code, then it's not ours. if (pRecord->ExceptionCode != CLRDBG_NOTIFICATION_EXCEPTION_CODE) { - return NULL; + return (CORDB_ADDRESS)NULL; } // @@ -57,7 +57,7 @@ CORDB_ADDRESS IsEventDebuggerNotification( // if (pRecord->NumberParameters != 3) { - return NULL; + return (CORDB_ADDRESS)NULL; } // 1st argument should always be the cookie. @@ -66,7 +66,7 @@ CORDB_ADDRESS IsEventDebuggerNotification( DWORD cookie = (DWORD) pRecord->ExceptionInformation[0]; if (cookie != CLRDBG_EXCEPTION_DATA_CHECKSUM) { - return NULL; + return (CORDB_ADDRESS)NULL; } // TODO: We don't do this check in case of non-windows debugging now, because we don't support @@ -79,7 +79,7 @@ CORDB_ADDRESS IsEventDebuggerNotification( CORDB_ADDRESS pTargetBase = GetExceptionInfoAsAddress(pRecord, 1); if (pTargetBase != pClrBaseAddress) { - return NULL; + return (CORDB_ADDRESS)NULL; } #endif diff --git a/src/coreclr/dlls/mscordac/mscordac_unixexports.src b/src/coreclr/dlls/mscordac/mscordac_unixexports.src index ad056eb1104e..3257e6f37960 100644 --- a/src/coreclr/dlls/mscordac/mscordac_unixexports.src +++ b/src/coreclr/dlls/mscordac/mscordac_unixexports.src @@ -60,8 +60,6 @@ nativeStringResourceTable_mscorrc #vsprintf_s #_snprintf_s #_vsnprintf_s -#_itow_s -#_i64tow_s #memcpy_s #sscanf_s diff --git a/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt b/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt index c600af1fb6aa..7ba58d0297f9 100644 --- a/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt +++ b/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt @@ -109,6 +109,7 @@ set(CORECLR_LIBRARIES interop coreclrminipal gc_pal + cdac_contract_descriptor ) if(CLR_CMAKE_TARGET_ARCH_AMD64) diff --git a/src/coreclr/dlls/mscoree/exports.cpp b/src/coreclr/dlls/mscoree/exports.cpp index f1cfb2faf5c8..8c28aa0545a8 100644 --- a/src/coreclr/dlls/mscoree/exports.cpp +++ b/src/coreclr/dlls/mscoree/exports.cpp @@ -26,7 +26,7 @@ #define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS((expr)) #ifdef TARGET_UNIX -#define NO_HOSTING_API_RETURN_ADDRESS ((void*)ULONG_PTR_MAX) +#define NO_HOSTING_API_RETURN_ADDRESS ((void*)UINTPTR_MAX) void* g_hostingApiReturnAddress = NO_HOSTING_API_RETURN_ADDRESS; class HostingApiFrameHolder diff --git a/src/coreclr/dlls/mscoree/mscorwks_ntdef.src b/src/coreclr/dlls/mscoree/mscorwks_ntdef.src index 0ac421b63e07..a2076bd62433 100644 --- a/src/coreclr/dlls/mscoree/mscorwks_ntdef.src +++ b/src/coreclr/dlls/mscoree/mscorwks_ntdef.src @@ -28,3 +28,6 @@ EXPORTS ; Used by profilers MetaDataGetDispenser + + ; cDAC contract descriptor + DotNetRuntimeContractDescriptor diff --git a/src/coreclr/dlls/mscoree/mscorwks_unixexports.src b/src/coreclr/dlls/mscoree/mscorwks_unixexports.src index a35a59c09560..3eacb7fa4848 100644 --- a/src/coreclr/dlls/mscoree/mscorwks_unixexports.src +++ b/src/coreclr/dlls/mscoree/mscorwks_unixexports.src @@ -14,3 +14,6 @@ g_dacTable ; Used by profilers MetaDataGetDispenser + +; cDAC contract descriptor +DotNetRuntimeContractDescriptor diff --git a/src/coreclr/dlls/mscorpe/ceefilegenwriter.cpp b/src/coreclr/dlls/mscorpe/ceefilegenwriter.cpp index b6cc342c741d..37611c4fb446 100644 --- a/src/coreclr/dlls/mscorpe/ceefilegenwriter.cpp +++ b/src/coreclr/dlls/mscorpe/ceefilegenwriter.cpp @@ -256,13 +256,13 @@ CeeFileGenWriter::CeeFileGenWriter() // ctor is protected m_dllCount = 0; m_dwManifestSize = 0; - m_dwManifestRVA = NULL; + m_dwManifestRVA = 0; m_dwStrongNameSize = 0; - m_dwStrongNameRVA = NULL; + m_dwStrongNameRVA = 0; m_dwVTableSize = 0; - m_dwVTableRVA = NULL; + m_dwVTableRVA = 0; m_iDataDlls = NULL; diff --git a/src/coreclr/dlls/mscorrc/mscorrc.rc b/src/coreclr/dlls/mscorrc/mscorrc.rc index b95946881f10..5b4faf05edb4 100644 --- a/src/coreclr/dlls/mscorrc/mscorrc.rc +++ b/src/coreclr/dlls/mscorrc/mscorrc.rc @@ -113,7 +113,6 @@ BEGIN COR_E_FILELOAD "Unable to load file '%1'." COR_E_ASSEMBLYEXPECTED "The module '%1' was expected to contain an assembly manifest." FUSION_E_REF_DEF_MISMATCH "The located assembly's manifest definition with name '%1' does not match the assembly reference." - FUSION_E_PRIVATE_ASM_DISALLOWED "Assembly '%1' is required to be strongly named." FUSION_E_INVALID_NAME "The given assembly name, '%1', was invalid." FUSION_E_APP_DOMAIN_LOCKED "The requested assembly version conflicts with what is already bound in the app domain or specified in the manifest." IDS_EE_HASH_VAL_FAILED "Hash validation failed for file or assembly '%1'." diff --git a/src/coreclr/gc/env/volatile.h b/src/coreclr/gc/env/volatile.h index c40e5c2d6096..e1c014543139 100644 --- a/src/coreclr/gc/env/volatile.h +++ b/src/coreclr/gc/env/volatile.h @@ -161,16 +161,16 @@ T VolatileLoad(T const * pt) switch (sizeof(T)) { case 1: - *(unsigned __int8* )pv = __ldar8 ((unsigned __int8 volatile*)pt); + *(uint8_t* )pv = __ldar8 ((uint8_t volatile*)pt); break; case 2: - *(unsigned __int16*)pv = __ldar16((unsigned __int16 volatile*)pt); + *(uint16_t*)pv = __ldar16((uint16_t volatile*)pt); break; case 4: - *(unsigned __int32*)pv = __ldar32((unsigned __int32 volatile*)pt); + *(uint32_t*)pv = __ldar32((uint32_t volatile*)pt); break; case 8: - *(unsigned __int64*)pv = __ldar64((unsigned __int64 volatile*)pt); + *(uint64_t*)pv = __ldar64((uint64_t volatile*)pt); break; default: val = *(T volatile const*)pt; @@ -240,16 +240,16 @@ void VolatileStore(T* pt, T val) switch (sizeof(T)) { case 1: - __stlr8 ((unsigned __int8 volatile*)pt, *(unsigned __int8* )pv); + __stlr8 ((uint8_t volatile*)pt, *(uint8_t* )pv); break; case 2: - __stlr16((unsigned __int16 volatile*)pt, *(unsigned __int16*)pv); + __stlr16((uint16_t volatile*)pt, *(uint16_t*)pv); break; case 4: - __stlr32((unsigned __int32 volatile*)pt, *(unsigned __int32*)pv); + __stlr32((uint32_t volatile*)pt, *(uint32_t*)pv); break; case 8: - __stlr64((unsigned __int64 volatile*)pt, *(unsigned __int64*)pv); + __stlr64((uint64_t volatile*)pt, *(uint64_t*)pv); break; default: __dmb(_ARM64_BARRIER_ISH); diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index e43047cf6e11..79b4b9ee2383 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -386,9 +386,15 @@ int relative_index_power2_free_space (size_t power2) return ((index < MIN_INDEX_POWER2) ? -1 : (index - MIN_INDEX_POWER2)); } +inline +float mb (size_t num) +{ + return (float)((float)num / 1000.0 / 1000.0); +} + #ifdef BACKGROUND_GC uint32_t bgc_alloc_spin_count = 140; -uint32_t bgc_alloc_spin_count_loh = 16; +uint32_t bgc_alloc_spin_count_uoh = 16; uint32_t bgc_alloc_spin = 2; inline @@ -2657,13 +2663,10 @@ 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; +size_t gc_heap::uoh_a_no_bgc[uoh_generation_count] = {}; +size_t gc_heap::uoh_a_bgc_marking[uoh_generation_count] = {}; +size_t gc_heap::uoh_a_bgc_planning[uoh_generation_count] = {}; #ifdef BGC_SERVO_TUNING -uint64_t gc_heap::loh_a_no_bgc = 0; - -uint64_t gc_heap::loh_a_bgc_marking = 0; - -uint64_t gc_heap::loh_a_bgc_planning = 0; - size_t gc_heap::bgc_maxgen_end_fl_size = 0; #endif //BGC_SERVO_TUNING @@ -2794,9 +2797,9 @@ FinalizerWorkItem* gc_heap::finalizer_work; BOOL gc_heap::proceed_with_gc_p = FALSE; GCSpinLock gc_heap::gc_lock; -#ifdef BGC_SERVO_TUNING -uint64_t gc_heap::total_loh_a_last_bgc = 0; -#endif //BGC_SERVO_TUNING +#ifdef BACKGROUND_GC +uint64_t gc_heap::total_uoh_a_last_bgc = 0; +#endif //BACKGROUND_GC #ifdef USE_REGIONS region_free_list gc_heap::global_regions_to_decommit[count_free_region_kinds]; @@ -6970,6 +6973,7 @@ void gc_heap::gc_thread_function () { assert (dynamic_adaptation_mode == dynamic_adaptation_to_application_sizes); + wait_on_time_out_p = true; dynamic_heap_count_data_t::sample& sample = dynamic_heap_count_data.samples[dynamic_heap_count_data.sample_index]; wait_time = min (wait_time, (uint32_t)(sample.elapsed_between_gcs / 1000 / 3)); wait_time = max (wait_time, 1u); @@ -15039,10 +15043,13 @@ gc_heap::init_gc_heap (int h_number) make_mark_stack(arr); #ifdef BACKGROUND_GC + for (int i = uoh_start_generation; i < total_generation_count; i++) + { + uoh_a_no_bgc[i - uoh_start_generation] = 0; + uoh_a_bgc_marking[i - uoh_start_generation] = 0; + uoh_a_bgc_planning[i - uoh_start_generation] = 0; + } #ifdef BGC_SERVO_TUNING - loh_a_no_bgc = 0; - loh_a_bgc_marking = 0; - loh_a_bgc_planning = 0; bgc_maxgen_end_fl_size = 0; #endif //BGC_SERVO_TUNING freeable_soh_segment = 0; @@ -18424,6 +18431,31 @@ bool gc_heap::should_retry_other_heap (int gen_number, size_t size) } } +#ifdef BACKGROUND_GC +void gc_heap::bgc_record_uoh_allocation(int gen_number, size_t size) +{ + assert((gen_number >= uoh_start_generation) && (gen_number < total_generation_count)); + + if (gc_heap::background_running_p()) + { + background_uoh_alloc_count++; + + if (current_c_gc_state == c_gc_state_planning) + { + uoh_a_bgc_planning[gen_number - uoh_start_generation] += size; + } + else + { + uoh_a_bgc_marking[gen_number - uoh_start_generation] += size; + } + } + else + { + uoh_a_no_bgc[gen_number - uoh_start_generation] += size; + } +} +#endif //BACKGROUND_GC + allocation_state gc_heap::allocate_uoh (int gen_number, size_t size, alloc_context* acontext, @@ -18446,26 +18478,12 @@ allocation_state gc_heap::allocate_uoh (int gen_number, #endif //RECORD_LOH_STATE #ifdef BACKGROUND_GC + bgc_record_uoh_allocation(gen_number, size); + if (gc_heap::background_running_p()) { -#ifdef BGC_SERVO_TUNING - bool planning_p = (current_c_gc_state == c_gc_state_planning); -#endif //BGC_SERVO_TUNING - - background_uoh_alloc_count++; - //if ((background_loh_alloc_count % bgc_alloc_spin_count_loh) == 0) + //if ((background_uoh_alloc_count % bgc_alloc_spin_count_uoh) == 0) { -#ifdef BGC_SERVO_TUNING - if (planning_p) - { - loh_a_bgc_planning += size; - } - else - { - loh_a_bgc_marking += size; - } -#endif //BGC_SERVO_TUNING - int spin_for_allocation = (gen_number == loh_generation) ? bgc_loh_allocate_spin() : bgc_poh_allocate_spin(); @@ -18491,12 +18509,6 @@ allocation_state gc_heap::allocate_uoh (int gen_number, } } } -#ifdef BGC_SERVO_TUNING - else - { - loh_a_no_bgc += size; - } -#endif //BGC_SERVO_TUNING #endif //BACKGROUND_GC gc_reason gr = reason_oos_loh; @@ -20954,14 +20966,14 @@ size_t gc_heap::get_total_allocated_since_last_gc() { gc_heap* hp = gc_heap::g_heaps[i]; #else //MULTIPLE_HEAPS - { - gc_heap* hp = pGenGCHeap; + { + gc_heap* hp = pGenGCHeap; #endif //MULTIPLE_HEAPS - total_allocated_size += hp->allocated_since_last_gc[0] + hp->allocated_since_last_gc[1]; - hp->allocated_since_last_gc[0] = 0; - hp->allocated_since_last_gc[1] = 0; - } - return total_allocated_size; + total_allocated_size += hp->allocated_since_last_gc[0] + hp->allocated_since_last_gc[1]; + hp->allocated_since_last_gc[0] = 0; + hp->allocated_since_last_gc[1] = 0; + } + return total_allocated_size; } // Gets what's allocated on both SOH, LOH, etc that hasn't been collected. @@ -22023,20 +22035,44 @@ void gc_heap::update_end_gc_time_per_heap() #ifdef DYNAMIC_HEAP_COUNT if ((heap_number == 0) && (dynamic_adaptation_mode == dynamic_adaptation_to_application_sizes)) { + size_t desired_per_heap = dd_desired_allocation (dynamic_data_of (0)); if (settings.gc_index > 1) { + size_t gc_index = VolatileLoadWithoutBarrier (&settings.gc_index); dynamic_heap_count_data_t::sample& sample = dynamic_heap_count_data.samples[dynamic_heap_count_data.sample_index]; sample.elapsed_between_gcs = end_gc_time - last_suspended_end_time; sample.gc_pause_time = dd_gc_elapsed_time (dynamic_data_of (0)); sample.msl_wait_time = get_msl_wait_time (); + sample.gc_index = gc_index; // could cache this - we will get it again soon in do_post_gc sample.gc_survived_size = get_total_promoted (); - dprintf (6666, ("sample#%d: this GC end %I64d - last sus end %I64d = %I64d, this GC pause %I64d, msl wait %I64d", - dynamic_heap_count_data.sample_index, end_gc_time, last_suspended_end_time, sample.elapsed_between_gcs, sample.gc_pause_time, sample.msl_wait_time)); + // We check to see if we want to adjust the budget here for DATAS. + size_t desired_per_heap_datas = desired_per_heap; + float tcp = (sample.elapsed_between_gcs ? + (((float)sample.msl_wait_time / n_heaps + sample.gc_pause_time) * 100.0f / (float)sample.elapsed_between_gcs) : 0.0f); + size_t total_soh_stable_size = get_total_soh_stable_size(); + desired_per_heap_datas = dynamic_heap_count_data.compute_gen0_budget_per_heap (total_soh_stable_size, tcp, desired_per_heap); + dprintf (6666, ("gen0 new_alloc %Id (%.3fmb), from datas: %Id (%.3fmb)", + desired_per_heap, mb (desired_per_heap), desired_per_heap_datas, mb (desired_per_heap_datas))); + dprintf (6666, ("budget DATAS %Id, previous %Id", desired_per_heap_datas, desired_per_heap)); + + sample.gen0_budget_per_heap = (int)desired_per_heap_datas; + if (desired_per_heap_datas != desired_per_heap) + { + dprintf (6666, ("adjusted budget for DATAS, assigning to all heaps")); + assign_new_budget (0, desired_per_heap_datas); + } + + dprintf (6666, ("sample#%d: %d heaps, this GC end %I64d - last sus end %I64d = %I64d, this GC pause %.3fms, msl wait %I64dus, tcp %.3f, surv %zd, gc speed %.3fmb/ms (%.3fkb/ms/heap)", + dynamic_heap_count_data.sample_index, n_heaps, end_gc_time, last_suspended_end_time, sample.elapsed_between_gcs, + (sample.gc_pause_time / 1000.0), sample.msl_wait_time, ((float)((sample.msl_wait_time / n_heaps) + sample.gc_pause_time) * 100.0 / (float)sample.elapsed_between_gcs), + sample.gc_survived_size, + (sample.gc_pause_time ? (sample.gc_survived_size / 1000.0 / sample.gc_pause_time) : 0), + (sample.gc_pause_time ? ((float)sample.gc_survived_size / sample.gc_pause_time / n_heaps) : 0))); GCEventFireHeapCountSample_V1 ( - (uint64_t)VolatileLoadWithoutBarrier (&settings.gc_index), + (uint64_t)gc_index, sample.elapsed_between_gcs, sample.gc_pause_time, sample.msl_wait_time); @@ -22061,6 +22097,17 @@ void gc_heap::update_end_gc_time_per_heap() calculate_new_heap_count (); } + else + { + // For DATAS we can't just take the BCS because it's likely very large and that could totally make the max heap size larger. We just take the + // min budget. + size_t min_desired = dd_min_size (dynamic_data_of (0)); + if (min_desired != desired_per_heap) + { + dprintf (6666, ("use the min budget for DATAS, assigning to all heaps")); + assign_new_budget (0, min_desired); + } + } last_suspended_end_time = end_gc_time; } @@ -22527,14 +22574,6 @@ void gc_heap::gc1() limit = total_generation_count-1; } - size_t total_max_gen_size = 0; - for (int i = 0; i < gc_heap::n_heaps; i++) - { - gc_heap* hp = gc_heap::g_heaps[i]; - dynamic_data* dd = hp->dynamic_data_of (max_generation); - total_max_gen_size += dd_current_size (dd) + dd_desired_allocation (dd); - } - for (int gen = 0; gen <= limit; gen++) { size_t total_desired = 0; @@ -22569,18 +22608,6 @@ void gc_heap::gc1() if (gen == 0) { -#ifdef DYNAMIC_HEAP_COUNT - if (dynamic_adaptation_mode == dynamic_adaptation_to_application_sizes) - { - size_t new_allocation_datas = dynamic_heap_count_data.compute_gen0_new_allocation (total_max_gen_size); - new_allocation_datas = Align (new_allocation_datas, get_alignment_constant (gen <= max_generation)); - dprintf (6666, ("gen0 new_alloc %Id (%.3fmb), from datas: %Id (%.3fmb)", - desired_per_heap, ((double)desired_per_heap / 1000.0 / 1000.0), - new_allocation_datas, ((double)new_allocation_datas / 1000.0 / 1000.0))); - desired_per_heap = min (desired_per_heap, new_allocation_datas); - } -#endif //DYNAMIC_HEAP_COUNT - // to avoid spikes in mem usage due to short terms fluctuations in survivorship, // apply some smoothing. size_t desired_per_heap_before_smoothing = desired_per_heap; @@ -22607,9 +22634,10 @@ void gc_heap::gc1() } } #ifdef HOST_64BIT + size_t desired_per_heap_before_trim = desired_per_heap; desired_per_heap = joined_youngest_desired (desired_per_heap); - dprintf (6666, ("final gen0 new_alloc: total desired: %Id (%.3fmb/heap), before smooth %zd -> after smooth %zd -> after joined %zd", + dprintf (6666, ("final gen0 bcs: total desired: %Id (%.3fmb/heap), before smooth %zd -> after smooth %zd -> after joined %zd", total_desired, ((double)(total_desired / n_heaps)/ 1000.0 / 1000.0), desired_per_heap_before_smoothing, desired_per_heap_after_smoothing, desired_per_heap)); #endif // HOST_64BIT @@ -22772,6 +22800,47 @@ void gc_heap::gc1() } #ifdef DYNAMIC_HEAP_COUNT +size_t gc_heap::get_total_soh_stable_size() +{ + size_t total_stable_size = 0; + bool use_max_gen_p = (dynamic_heap_count_data.current_gen2_samples_count > 0); + int gen_number = max_generation; + for (int i = 0; i < gc_heap::n_heaps; i++) + { + gc_heap* hp = g_heaps[i]; + + if (use_max_gen_p) + { + dynamic_data* dd = hp->dynamic_data_of (gen_number); + total_stable_size += dd_current_size (dd) + dd_desired_allocation (dd); + } + else + { + total_stable_size += hp->generation_size (max_generation - 1) / 2; + } + } + + return total_stable_size; +} + +void gc_heap::assign_new_budget (int gen_number, size_t desired_per_heap) +{ + for (int i = 0; i < gc_heap::n_heaps; i++) + { + gc_heap* hp = gc_heap::g_heaps[i]; + dynamic_data* dd = hp->dynamic_data_of (gen_number); + dd_desired_allocation (dd) = desired_per_heap; + dd_gc_new_allocation (dd) = desired_per_heap; + dd_new_allocation (dd) = desired_per_heap; + if (gen_number == 0) + { + hp->fgn_last_alloc = desired_per_heap; + } + } + + gc_data_global.final_youngest_desired = desired_per_heap; +} + bool gc_heap::prepare_rethread_fl_items() { if (!min_fl_list) @@ -24244,9 +24313,6 @@ size_t gc_heap::get_promoted_bytes() dprintf (3, ("h%d getting surv", heap_number)); size_t promoted = 0; -#ifdef _MSC_VER -#pragma loop(no_vector) -#endif for (size_t i = 0; i < region_count; i++) { if (survived_per_region[i] > 0) @@ -25209,7 +25275,7 @@ float mean (float* arr, int size) int max_times_to_print_tcp = 0; // Return the slope, and the average values in the avg arg. -float slope (float* y, int n, float* avg) +float gc_heap::dynamic_heap_count_data_t::slope (float* y, int n, float* avg) { assert (n > 0); @@ -25250,7 +25316,7 @@ float slope (float* y, int n, float* avg) return (numerator / denominator); } -int gc_heap::calculate_new_heap_count () +void gc_heap::calculate_new_heap_count () { assert (dynamic_adaptation_mode == dynamic_adaptation_to_application_sizes); @@ -25262,7 +25328,7 @@ int gc_heap::calculate_new_heap_count () (dynamic_heap_count_data.current_gen2_samples_count < (dynamic_heap_count_data.processed_gen2_samples_count + dynamic_heap_count_data_t::sample_size))) { dprintf (6666, ("not enough GCs, skipping")); - return n_heaps; + return; } bool process_eph_samples_p = (dynamic_heap_count_data.current_samples_count >= (dynamic_heap_count_data.processed_samples_count + dynamic_heap_count_data_t::sample_size)); @@ -25281,12 +25347,14 @@ int gc_heap::calculate_new_heap_count () for (int i = 0; i < dynamic_heap_count_data_t::sample_size; i++) { dynamic_heap_count_data_t::sample& sample = dynamic_heap_count_data.samples[i]; + assert (sample.elapsed_between_gcs > 0); throughput_cost_percents[i] = (sample.elapsed_between_gcs ? (((float)sample.msl_wait_time / n_heaps + sample.gc_pause_time) * 100.0f / (float)sample.elapsed_between_gcs) : 0.0f); assert (throughput_cost_percents[i] >= 0.0); if (throughput_cost_percents[i] > 100.0) throughput_cost_percents[i] = 100.0; - dprintf (6666, ("sample %d: msl %I64d / %d + pause %I64d / elapsed %I64d = throughput_cost_percent: %.3f", i, - sample.msl_wait_time, n_heaps, sample.gc_pause_time, sample.elapsed_between_gcs, throughput_cost_percents[i])); + dprintf (6666, ("sample %d in GC#%Id msl %I64d / %d + pause %I64d / elapsed %I64d = tcp: %.3f, surv %zd, gc speed %zd/ms", i, + sample.gc_index, sample.msl_wait_time, n_heaps, sample.gc_pause_time, sample.elapsed_between_gcs, throughput_cost_percents[i], + sample.gc_survived_size, (sample.gc_pause_time ? (sample.gc_survived_size * 1000 / sample.gc_pause_time) : 0))); } float median_throughput_cost_percent = median_of_3 (throughput_cost_percents[0], throughput_cost_percents[1], throughput_cost_percents[2]); @@ -25328,80 +25396,12 @@ int gc_heap::calculate_new_heap_count () median_throughput_cost_percent = min_tcp; } - // apply exponential smoothing and use 1/3 for the smoothing factor - const float smoothing = 3; - float smoothed_median_throughput_cost_percent = dynamic_heap_count_data.smoothed_median_throughput_cost_percent; - if (smoothed_median_throughput_cost_percent != 0.0f) - { - // average it with the previous value - smoothed_median_throughput_cost_percent = median_throughput_cost_percent / smoothing + (smoothed_median_throughput_cost_percent / smoothing) * (smoothing - 1); - } - else - { - smoothed_median_throughput_cost_percent = median_throughput_cost_percent; - } - - dprintf (6666, ("median tcp: %.3f, smoothed tcp: %.3f, avg tcp: %.3f, gen2 tcp %.3f(%.3f, %.3f, %.3f)", - median_throughput_cost_percent, smoothed_median_throughput_cost_percent, avg_throughput_cost_percent, median_gen2_tcp_percent, + dprintf (6666, ("median tcp: %.3f, avg tcp: %.3f, gen2 tcp %.3f(%.3f, %.3f, %.3f)", + median_throughput_cost_percent, avg_throughput_cost_percent, median_gen2_tcp_percent, dynamic_heap_count_data.gen2_samples[0].gc_percent, dynamic_heap_count_data.gen2_samples[1].gc_percent, dynamic_heap_count_data.gen2_samples[2].gc_percent)); - // - // I'm keeping the old logic for now just to handle gen2. - // - size_t heap_size = 0; - for (int i = 0; i < n_heaps; i++) - { - gc_heap* hp = g_heaps[i]; - - for (int gen_idx = 0; gen_idx < total_generation_count; gen_idx++) - { - dynamic_data* dd = hp->dynamic_data_of (gen_idx); - - // estimate the size of each generation as the live data size plus the budget - heap_size += dd_current_size (dd) + dd_desired_allocation (dd); - dprintf (3, ("h%d g%d current: %zd desired allocation: %zd", i, gen_idx, dd_promoted_size (dd), dd_desired_allocation (dd))); - } - } - - // estimate the space cost of adding a heap as the min gen0 budget - size_t heap_space_cost_per_heap = dd_min_size (g_heaps[0]->dynamic_data_of (0)); - - // compute the % space cost of adding a heap - float percent_heap_space_cost_per_heap = heap_space_cost_per_heap * 100.0f / heap_size; - - // compute reasonable step sizes for the heap count - // - // on the way up, we essentially multiply the heap count by 1.5, so we go 1, 2, 3, 5, 8 ... - // we don't go all the way to the number of CPUs, but stay 1 or 2 short - int step_up = (n_heaps + 1) / 2; int extra_heaps = (n_max_heaps >= 16) + (n_max_heaps >= 64); int actual_n_max_heaps = n_max_heaps - extra_heaps; - int max_growth = max ((n_max_heaps / 4), (1 + (actual_n_max_heaps > 3))); - - step_up = min (step_up, (actual_n_max_heaps - n_heaps)); - - // on the way down, we essentially divide the heap count by 1.5 - int step_down = (n_heaps + 1) / 3; - - // estimate the potential time benefit of going up a step - float tcp_reduction_per_step_up = smoothed_median_throughput_cost_percent * step_up / (n_heaps + step_up); - - // estimate the potential time cost of going down a step - float tcp_increase_per_step_down = smoothed_median_throughput_cost_percent * step_down / (n_heaps - step_down); - - // estimate the potential space cost of going up a step - float scp_increase_per_step_up = percent_heap_space_cost_per_heap * step_up; - - // estimate the potential space saving of going down a step - float scp_decrease_per_step_down = percent_heap_space_cost_per_heap * step_down; - - dprintf (6666, ("[CHP] u %d, d %d | space cost %Id / heap %Id(%.2fmb) = scp %.3f (u: %.3f, d: %.3f) | stcp %.3f, u * %.1f = %.3f, d * %.1f = %.3f", - step_up, step_down, - heap_space_cost_per_heap, heap_size, ((float)heap_size / (float)1000 / (float)1000), percent_heap_space_cost_per_heap, - scp_increase_per_step_up, scp_decrease_per_step_down, - smoothed_median_throughput_cost_percent, - ((float)step_up / (float)(n_heaps + step_up)), tcp_reduction_per_step_up, - ((float)step_down / (float)(n_heaps - step_down)), tcp_increase_per_step_down)); #ifdef STRESS_DYNAMIC_HEAP_COUNT // quick hack for initial testing @@ -25417,357 +25417,133 @@ int gc_heap::calculate_new_heap_count () #else //STRESS_DYNAMIC_HEAP_COUNT int new_n_heaps = n_heaps; - // target_tcp should be configurable. - float target_tcp = 5.0; - float target_gen2_tcp = 10.0; - float log_base = (float)1.11; - - dynamic_heap_count_data.add_to_recorded_tcp (median_throughput_cost_percent); - - // This is the average of whatever is in the recorded tcp buffer. - float avg_recorded_tcp = 0.0; - - size_t num_gcs_since_last_change = current_gc_index - dynamic_heap_count_data.last_changed_gc_index; + float target_tcp = dynamic_heap_count_data.target_tcp; + float target_gen2_tcp = dynamic_heap_count_data.target_gen2_tcp; if (process_eph_samples_p) { - dynamic_heap_count_data.last_processed_stcp = smoothed_median_throughput_cost_percent; - - if ((median_throughput_cost_percent > 10.0f) || (smoothed_median_throughput_cost_percent > target_tcp)) - { - // If median is high but stcp is lower than target, and if this situation continues, stcp will quickly be above target anyway; otherwise - // we treat it as an outlier. - if (smoothed_median_throughput_cost_percent >= (target_tcp + 1.0)) - { - float step_up_float = (float)(1 + actual_n_max_heaps * log_with_base ((smoothed_median_throughput_cost_percent - target_tcp), log_base) / 100.0); - int step_up_int = (int)step_up_float; - - dprintf (6666, ("[CHP0] inc %d(%.3f), last inc %d, %Id GCs elapsed, last stcp %.3f", - step_up_int, step_up_float, (int)dynamic_heap_count_data.last_changed_count, - num_gcs_since_last_change, dynamic_heap_count_data.last_changed_stcp)); - - // Don't adjust if we just adjusted last time we checked, unless we are in an extreme situation. - if ((smoothed_median_throughput_cost_percent < 20.0f) && - (avg_throughput_cost_percent < 20.0f) && - (num_gcs_since_last_change < (2 * dynamic_heap_count_data_t::sample_size))) - { - dprintf (6666, ("[CHP0] we just adjusted %Id GCs ago, skipping", num_gcs_since_last_change)); - } - else - { - if (step_up_int) - { - if (dynamic_heap_count_data.dec_failure_count) - { - dprintf (6666, ("[CHP0] intending to grow, reset dec failure count (was %d)", dynamic_heap_count_data.dec_failure_count)); - dynamic_heap_count_data.dec_failure_count = 0; - } - - if (((int)dynamic_heap_count_data.last_changed_count > 0) && (dynamic_heap_count_data.last_changed_gc_index > 0.0) && - (num_gcs_since_last_change <= (3 * dynamic_heap_count_data_t::sample_size))) - { - dprintf (6666, ("[CHP0-0] just grew %d GCs ago, no change", num_gcs_since_last_change)); - step_up_int = 0; - } - else - { - // If the calculation tells us to grow, we should check to see if the slope has been coming down rapidly, if so there's no reason to grow. - int above_target_tcp_count = dynamic_heap_count_data.rearrange_recorded_tcp (); - float above_target_tcp_slope = slope (dynamic_heap_count_data.recorded_tcp_rearranged, above_target_tcp_count, &avg_recorded_tcp); - float diff_pct = (target_tcp - avg_recorded_tcp) / target_tcp; - float adjusted_target_tcp = dynamic_heap_count_data.get_range_upper (target_tcp); - - dprintf (6666, ("[CHP0] slope of last %d samples is %.3f. avg %.3f (%.3f%%), current tcp %.3f, adjusted target is %.3f, failure count is %d", - above_target_tcp_count, above_target_tcp_slope, avg_recorded_tcp, (diff_pct * 100.0), - median_throughput_cost_percent, adjusted_target_tcp, dynamic_heap_count_data.inc_failure_count)); - - if (dynamic_heap_count_data.is_tcp_in_range (diff_pct, above_target_tcp_slope)) - { - step_up_int = 0; - dprintf (6666, ("[CHP0-1] slope %.3f and already close to target %.3f (%.3f%%), no change", above_target_tcp_slope, avg_recorded_tcp, (diff_pct * 100.0))); - } - else - { - if (above_target_tcp_slope < 0.0) - { - // If we are already trending down and the tcp is small enough, just wait. - if ((median_throughput_cost_percent < adjusted_target_tcp) || (avg_recorded_tcp < adjusted_target_tcp)) - { - step_up_int = 0; - dprintf (6666, ("[CHP0-2] trending down, slope is %.3f, tcp is %.3f, avg is %.3f, already below adjusted target %.3f, no change", - above_target_tcp_slope, median_throughput_cost_percent, avg_recorded_tcp, adjusted_target_tcp)); - } - } - else - { - // We are trending up, but we have too few samples and the avg is already small enough. - if ((above_target_tcp_count <= dynamic_heap_count_data.inc_recheck_threshold) && (avg_recorded_tcp < adjusted_target_tcp)) - { - step_up_int = 0; - dprintf (6666, ("[CHP0-3] trending up, only %d samples, slope is %.3f, avg is %.3f already below adjusted target %.3f, no change", - above_target_tcp_count, above_target_tcp_slope, avg_recorded_tcp, adjusted_target_tcp)); - } - } - } - } - - // If we still decided to grow, check if we need to grow aggressively. - if (step_up_int) - { - if (((int)dynamic_heap_count_data.last_changed_count > 0) && (dynamic_heap_count_data.last_changed_gc_index > 0.0)) - { - if (num_gcs_since_last_change > (16 * dynamic_heap_count_data_t::sample_size)) - { - dynamic_heap_count_data.inc_failure_count = 0; - dprintf (6666, ("[CHP0-4] grew %d GCs ago, too far in the past, set aggressive factor to 0, grow from %d -> %d more heaps", - num_gcs_since_last_change, dynamic_heap_count_data.inc_failure_count, step_up_int, (step_up_int * (dynamic_heap_count_data.inc_failure_count + 1)))); - } - else - { - (dynamic_heap_count_data.inc_failure_count)++; - dprintf (6666, ("[CHP0-4] grew %d GCs ago, aggressive factor is %d, grow more aggressively from %d -> %d more heaps", - num_gcs_since_last_change, dynamic_heap_count_data.inc_failure_count, step_up_int, (step_up_int * (dynamic_heap_count_data.inc_failure_count + 1)))); - } - step_up_int *= dynamic_heap_count_data.inc_failure_count + 1; - } - } - } + dynamic_heap_count_data.add_to_recorded_tcp (median_throughput_cost_percent); - step_up_int = min (step_up_int, max_growth); - - new_n_heaps = n_heaps + step_up_int; - new_n_heaps = min (new_n_heaps, actual_n_max_heaps); - - // If we are going to grow to be very close to max heap, it's better to just grow to it. - if ((new_n_heaps < actual_n_max_heaps) && dynamic_heap_count_data.is_close_to_max (new_n_heaps, actual_n_max_heaps)) - { - dprintf (6666, ("[CHP0-5] %d is close to max heaps %d, grow to max", new_n_heaps, actual_n_max_heaps)); - new_n_heaps = actual_n_max_heaps; - } - - if (new_n_heaps > n_heaps) - { - dynamic_heap_count_data.last_changed_gc_index = current_gc_index; - dynamic_heap_count_data.last_changed_count = step_up_float; - dynamic_heap_count_data.last_changed_stcp = smoothed_median_throughput_cost_percent; - } - - dprintf (6666, ("[CHP0] tcp %.3f, stcp %.3f -> (%d -> %.3f) -> %d + %d = %d -> %d", - median_throughput_cost_percent, smoothed_median_throughput_cost_percent, - actual_n_max_heaps, step_up_float, step_up_int, n_heaps, (n_heaps + step_up_int), new_n_heaps)); - } - } - } - else + float tcp_to_consider = 0.0; + if (dynamic_heap_count_data.should_change (median_throughput_cost_percent, &tcp_to_consider, current_gc_index)) { - // When we are below target, we accumulate the distance to target and only adjust when we've accumulated enough in this state. Note that - // this can include tcp's that are slightly above target, as long as it's not high enough for us to adjust the heap count. If we are just - // oscillating around target, this makes those tcp's cancel each other out. - if (dynamic_heap_count_data.below_target_accumulation == 0) + size_t total_soh_stable_size = get_total_soh_stable_size(); + size_t total_bcd = dynamic_heap_count_data.compute_total_gen0_budget (total_soh_stable_size); + int max_heap_count_datas = (int)(total_bcd / dynamic_heap_count_data.min_gen0_new_allocation); + int min_heap_count_datas = (int)(total_bcd / dynamic_heap_count_data.max_gen0_new_allocation); + int max_heap_count_growth_step = dynamic_heap_count_data.get_max_growth (n_heaps); + int max_heap_count_growth_datas = max_heap_count_datas - n_heaps; + if (max_heap_count_growth_datas < 0) { - dynamic_heap_count_data.first_below_target_gc_index = current_gc_index; - dynamic_heap_count_data.init_recorded_tcp (); - dynamic_heap_count_data.add_to_recorded_tcp (median_throughput_cost_percent); + max_heap_count_growth_datas = 0; } - dprintf (6666, ("[CHP1] last time adjusted %s by %d at GC#%Id (%Id GCs since), stcp was %.3f, now stcp is %.3f", - ((dynamic_heap_count_data.last_changed_count > 0.0) ? "up" : "down"), (int)dynamic_heap_count_data.last_changed_count, - dynamic_heap_count_data.last_changed_gc_index, num_gcs_since_last_change, - dynamic_heap_count_data.last_changed_stcp, smoothed_median_throughput_cost_percent)); + int max_heap_count_growth_core = actual_n_max_heaps - n_heaps; + int max_heap_count_growth = min (max_heap_count_growth_step, min (max_heap_count_growth_datas, max_heap_count_growth_core)); - float below_target_diff = target_tcp - median_throughput_cost_percent; - dynamic_heap_count_data.below_target_accumulation += below_target_diff; + float distance = tcp_to_consider - target_tcp; - dprintf (6666, ("[CHP1] below target for the past %Id GCs, accumulated %.3f, min (10%% of max is %.2f, 20%% of hc is %.2f)", - (current_gc_index - dynamic_heap_count_data.first_below_target_gc_index), dynamic_heap_count_data.below_target_accumulation, - (actual_n_max_heaps * 0.1), (n_heaps * 0.2))); + dprintf (6666, ("median tcp %.3f, recent tcp %.3f - target %.1f = %.3f", median_throughput_cost_percent, tcp_to_consider, target_tcp, distance)); - if (dynamic_heap_count_data.below_target_accumulation >= dynamic_heap_count_data.below_target_threshold) + float diff_pct = distance / target_tcp; + // Different for above and below target to avoid oscillation. + float hc_change_factor = (float)((diff_pct > 0.0) ? 1.5 : 3.0); + float change_float = diff_pct / hc_change_factor * (float)n_heaps; + float change_float_rounded = (float)round(change_float); + int change_int = (int)change_float_rounded; + dprintf (6666, ("diff pct %.3f / %.1f * %d = %d (%.3f), max hc allowed by datas %d | by core %d, max growth per step %d, max growth by datas %d | by core %d", + diff_pct, hc_change_factor, n_heaps, change_int, ((float)change_int / n_heaps), max_heap_count_datas, actual_n_max_heaps, + max_heap_count_growth_step, max_heap_count_growth_datas, max_heap_count_growth_core)); + + if (change_int > 0) { - int below_target_tcp_count = dynamic_heap_count_data.rearrange_recorded_tcp (); - float below_target_tcp_slope = slope (dynamic_heap_count_data.recorded_tcp_rearranged, below_target_tcp_count, &avg_recorded_tcp); - float diff_pct = (target_tcp - smoothed_median_throughput_cost_percent) / target_tcp; - int step_down_int = (int)(diff_pct / 2.0 * n_heaps); - if ((step_down_int == 0) && dynamic_heap_count_data.is_tcp_far_below (diff_pct)) + int agg_factor = dynamic_heap_count_data.get_aggressiveness (change_int); + if (agg_factor > 1) { - dprintf (6666, ("[CHP1] we are far below target, reduce by 1 heap")); - step_down_int = 1; + change_int *= agg_factor; + dprintf (6666, ("agg factor is %d, change by %d heaps", agg_factor, change_int)); } + } - dprintf (6666, ("[CHP1] observed %d tcp's <= or ~ target, avg %.3f, slope %.3f, stcp %.3f%% below target, shrink by %.3f%% * %d = %d heaps", - below_target_tcp_count, avg_recorded_tcp, below_target_tcp_slope, (diff_pct * 100.0), (diff_pct * 50.0), n_heaps, step_down_int)); + if (change_int) + { + dynamic_heap_count_data_t::adjust_metric adj_metric = dynamic_heap_count_data.should_change_hc (max_heap_count_datas, min_heap_count_datas, + max_heap_count_growth, change_int, current_gc_index); - bool shrink_p = false; - if (dynamic_heap_count_data.is_tcp_in_range (diff_pct, below_target_tcp_slope)) + // If we decide to change budget, we let the next GC calculate the right budget, ie, we delay changing by one GC which is acceptable. + if (adj_metric != dynamic_heap_count_data_t::adjust_metric::adjust_hc) { - step_down_int = 0; - dprintf (6666, ("[CHP1-0] slope %.3f is flat and stcp is already close to target %.3f (%.3f%%), no change", - below_target_tcp_slope, smoothed_median_throughput_cost_percent, (diff_pct * 100.0))); - } - else - { - // If we adjusted last time and it was unsuccessful, we need to inc our failure count. - // If we have a non zero failure count, we don't want to adjust for a while if we continue to be in that same situation. - bool last_dec_p = (dynamic_heap_count_data.last_changed_gc_index > 0) && (dynamic_heap_count_data.last_changed_count < 0.0); - float last_dec_tcp_diff_pct = (last_dec_p ? - ((smoothed_median_throughput_cost_percent - dynamic_heap_count_data.last_changed_stcp) / dynamic_heap_count_data.last_changed_stcp) : 0.0f); - bool stable_p = last_dec_p && ((last_dec_tcp_diff_pct <= 0.2) && (last_dec_tcp_diff_pct >= -0.2)); - dprintf (6666, ("[CHP1] since last adjustment stcp changed %.3f->%.3f = %.3f%%, %s, dec_failure_count is %d", - dynamic_heap_count_data.last_changed_stcp, smoothed_median_throughput_cost_percent, (last_dec_tcp_diff_pct * 100.0), - (stable_p ? "stable" : "not stable"), dynamic_heap_count_data.dec_failure_count)); - - bool check_dec_p = true; - - if (stable_p) - { - if (dynamic_heap_count_data.dec_failure_count) - { - (dynamic_heap_count_data.dec_failure_count)++; - } - else - { - dynamic_heap_count_data.dec_failure_count = 1; - } - - if (dynamic_heap_count_data.dec_failure_count <= dynamic_heap_count_data.dec_failure_recheck_threshold) - { - check_dec_p = false; - dprintf (6666, ("[CHP1-1] dec was still unsuccessful, <= %d, no change", dynamic_heap_count_data.dec_failure_recheck_threshold)); - } - } - - if (check_dec_p) - { - dynamic_heap_count_data.dec_failure_count = 0; - - if (below_target_tcp_slope <= 0.0) - { - shrink_p = true; - } - else - { - // It's trending upwards, but if takes too many samples to get to target, we do want to shrink. - int num_samples_to_goal = (int)((target_tcp + below_target_tcp_slope - median_throughput_cost_percent) / below_target_tcp_slope); - bool far_below_goal_p = (num_samples_to_goal > (3 * dynamic_heap_count_data_t::sample_size)); - dprintf (6666, ("[CHP1] it'll take ((%.3f + %.3f - %.3f) / %.3f = %d) samples to get to target, %s", - target_tcp, below_target_tcp_slope, median_throughput_cost_percent, below_target_tcp_slope, - num_samples_to_goal, (far_below_goal_p ? "shrink" : "no change"))); - - if (far_below_goal_p) - { - // We could be in a situation where the slope changes directions but since we only compute one number, we take another look at - // the samples to make a better assessment by looking at the highest tcps and if their average is close to target, we don't shrink. - // - // TODO - we only check this when the slope is going up but since this includes the situation where the slope changes directions - // we should really be checking this regardless of the slope to handle that. - float highest_avg_tcp = 0.0; - int highest_count = dynamic_heap_count_data.highest_avg_recorded_tcp (below_target_tcp_count, avg_recorded_tcp, &highest_avg_tcp); - float highest_count_pct = (float)highest_count / (float)below_target_tcp_count; - - shrink_p = (highest_count_pct < 0.3) || (highest_avg_tcp < (target_tcp * 0.8)); - dprintf (6666, ("[CHP1-2] %d samples were above avg (%.3f%%), their avg is %.3f (%s)", - highest_count, (highest_count_pct * 100.0), highest_avg_tcp, (shrink_p ? "shrink" : "no change"))); - } - } - } + change_int = 0; } - if (shrink_p && step_down_int && (new_n_heaps > step_down_int)) + if (adj_metric != dynamic_heap_count_data_t::adjust_metric::not_adjusted) { - if (step_down_int == 1) - { - if (dynamic_heap_count_data.should_dec_by_one()) - { - dprintf (6666, ("[CHP1-3] shrink by one heap")); - } - else - { - step_down_int = 0; - dprintf (6666, ("[CHP1-3] don't shrink just yet if it's just one heap")); - } - } - else + if (adj_metric == dynamic_heap_count_data_t::adjust_metric::adjust_hc) { - dynamic_heap_count_data.reset_dec_by_one(); - dprintf (6666, ("[CHP1-3] shrink by %d heap(s), reset dec by one", step_down_int)); + new_n_heaps = n_heaps + change_int; } - new_n_heaps -= step_down_int; - dprintf (6666, ("[CHP1] shrink by %d heaps -> %d", step_down_int, new_n_heaps)); + dynamic_heap_count_data.record_adjustment (adj_metric, distance, change_int, current_gc_index); } - - // Always reinit the buffer as we want to look at the more recent history. - dynamic_heap_count_data.init_recorded_tcp (); - dynamic_heap_count_data.below_target_accumulation = 0; } - if (new_n_heaps < n_heaps) - { - dynamic_heap_count_data.last_changed_gc_index = current_gc_index; - dynamic_heap_count_data.last_changed_count = (float)(new_n_heaps - n_heaps); - dynamic_heap_count_data.last_changed_stcp = smoothed_median_throughput_cost_percent; - dprintf (6666, ("[CHP1] setting last changed gc index to %Id, count to %.3f, stcp to %.3f", - dynamic_heap_count_data.last_changed_gc_index, dynamic_heap_count_data.last_changed_count, dynamic_heap_count_data.last_changed_stcp)); + // We always need to reset these since we already made decisions based on them. + dynamic_heap_count_data.reset_accumulation(); + dprintf (6666, ("changing HC or budget %d -> %d at GC#%Id", n_heaps, new_n_heaps, current_gc_index)); - if (dynamic_heap_count_data.inc_failure_count) - { - dprintf (6666, ("[CHP1] shrink, reset inc failure count (was %d)", dynamic_heap_count_data.inc_failure_count)); - dynamic_heap_count_data.inc_failure_count = 0; - } - } + dprintf (6666, ("total max gen %.3fmb, total bcd %.3fmb, diff %% %.3f-> +%d hc (%%%.3f)", + mb (total_soh_stable_size), mb (total_bcd), diff_pct, change_int, (change_int * 100.0 / n_heaps))); } } if ((new_n_heaps == n_heaps) && !process_eph_samples_p && process_gen2_samples_p) { - // The gen2 samples only serve as a backstop so this is quite crude. - if (median_gen2_tcp_percent > target_gen2_tcp) + // If we have already been processing eph samples, we don't need to process gen2. + if ((dynamic_heap_count_data.current_samples_count / dynamic_heap_count_data.current_gen2_samples_count) < 10) { - float step_up_percent = log_with_base ((median_gen2_tcp_percent - target_gen2_tcp + log_base), log_base); - float step_up_float = (float)(step_up_percent / 100.0 * actual_n_max_heaps); - new_n_heaps += (int)step_up_float; - new_n_heaps = min (new_n_heaps, actual_n_max_heaps); - dprintf (6666, ("[CHP2-0] gen2 tcp: %.3f, inc by %.3f%% = %d, %d -> %d", median_gen2_tcp_percent, step_up_percent, (int)step_up_float, n_heaps, new_n_heaps)); + int step_up = (n_heaps + 1) / 2; + int max_growth = max ((n_max_heaps / 4), (1 + (actual_n_max_heaps > 3))); + step_up = min (step_up, (actual_n_max_heaps - n_heaps)); + + int step_down = (n_heaps + 1) / 3; - if ((new_n_heaps < actual_n_max_heaps) && dynamic_heap_count_data.is_close_to_max (new_n_heaps, actual_n_max_heaps)) + // The gen2 samples only serve as a backstop so this is quite crude. + if (median_gen2_tcp_percent > target_gen2_tcp) { - dprintf (6666, ("[CHP2-1] %d is close to max heaps %d, grow to max", new_n_heaps, actual_n_max_heaps)); - new_n_heaps = actual_n_max_heaps; + new_n_heaps += step_up; + new_n_heaps = min (new_n_heaps, actual_n_max_heaps); + dprintf (6666, ("[CHP2-0] gen2 tcp: %.3f, inc by %d + %d = %d", median_gen2_tcp_percent, step_up, n_heaps, new_n_heaps)); + + if ((new_n_heaps < actual_n_max_heaps) && dynamic_heap_count_data.is_close_to_max (new_n_heaps, actual_n_max_heaps)) + { + dprintf (6666, ("[CHP2-1] %d is close to max heaps %d, grow to max", new_n_heaps, actual_n_max_heaps)); + new_n_heaps = actual_n_max_heaps; + } + } + else if ((median_gen2_tcp_percent < (target_gen2_tcp / 2)) && + ((dynamic_heap_count_data.current_gen2_samples_count - dynamic_heap_count_data.gen2_last_changed_sample_count) > 30)) + { + new_n_heaps -= step_down; + dprintf (6666, ("[CHP3-0] last gen2 sample count when changed: %Id, gen2 tcp: %.3f, dec by %d, %d -> %d", + dynamic_heap_count_data.gen2_last_changed_sample_count, median_gen2_tcp_percent, step_down, n_heaps, new_n_heaps)); + } + + if (new_n_heaps != n_heaps) + { + dynamic_heap_count_data.gen2_last_changed_sample_count = dynamic_heap_count_data.current_gen2_samples_count; } - } - else if ((dynamic_heap_count_data.last_processed_stcp < 1.0) && - (median_gen2_tcp_percent < (target_gen2_tcp / 2)) && - (scp_decrease_per_step_down - tcp_increase_per_step_down >= 1.0f)) - { - new_n_heaps -= step_down; - dprintf (6666, ("[CHP3-0] last eph stcp: %.3f, gen2 tcp: %.3f, dec by %d, %d -> %d", - dynamic_heap_count_data.last_processed_stcp, median_gen2_tcp_percent, step_down, n_heaps, new_n_heaps)); } } assert (new_n_heaps >= 1); assert (new_n_heaps <= actual_n_max_heaps); - #endif //STRESS_DYNAMIC_HEAP_COUNT - // store data used for decision to emit in ETW event - dynamic_heap_count_data.median_throughput_cost_percent = median_throughput_cost_percent; - dynamic_heap_count_data.smoothed_median_throughput_cost_percent = smoothed_median_throughput_cost_percent; - dynamic_heap_count_data.percent_heap_space_cost_per_heap = percent_heap_space_cost_per_heap; - dynamic_heap_count_data.tcp_reduction_per_step_up = tcp_reduction_per_step_up; - dynamic_heap_count_data.tcp_increase_per_step_down = tcp_increase_per_step_down; - dynamic_heap_count_data.scp_increase_per_step_up = scp_increase_per_step_up; - dynamic_heap_count_data.scp_decrease_per_step_down = scp_decrease_per_step_down; - + float reserved_field = (float)0.0; GCEventFireHeapCountTuning_V1 ( (uint16_t)dynamic_heap_count_data.new_n_heaps, (uint64_t)VolatileLoadWithoutBarrier (&settings.gc_index), - dynamic_heap_count_data.median_throughput_cost_percent, - dynamic_heap_count_data.smoothed_median_throughput_cost_percent, - dynamic_heap_count_data.tcp_reduction_per_step_up, - dynamic_heap_count_data.tcp_increase_per_step_down, - dynamic_heap_count_data.scp_increase_per_step_up, - dynamic_heap_count_data.scp_decrease_per_step_down - ); + median_throughput_cost_percent, + reserved_field, reserved_field, reserved_field, reserved_field, reserved_field); if (process_eph_samples_p) { @@ -25787,13 +25563,7 @@ int gc_heap::calculate_new_heap_count () VolatileLoadWithoutBarrier (&settings.gc_index), n_heaps, new_n_heaps, ((n_heaps < new_n_heaps) ? "INC" : "DEC"))); dynamic_heap_count_data.heap_count_to_change_to = new_n_heaps; dynamic_heap_count_data.should_change_heap_count = true; - dynamic_heap_count_data.init_recorded_tcp (); - dynamic_heap_count_data.below_target_accumulation = 0; - dynamic_heap_count_data.first_below_target_gc_index = current_gc_index; - dprintf (6666, ("CHANGING HC, resetting tcp index, below target")); } - - return new_n_heaps; } void gc_heap::check_heap_count () @@ -25833,9 +25603,6 @@ void gc_heap::check_heap_count () if (dynamic_heap_count_data.new_n_heaps == n_heaps) { - dynamic_heap_count_data.last_changed_gc_index = 0; - dynamic_heap_count_data.last_changed_count = 0.0; - dynamic_heap_count_data.processed_samples_count = dynamic_heap_count_data.current_samples_count; dynamic_heap_count_data.processed_gen2_samples_count = dynamic_heap_count_data.current_gen2_samples_count; dynamic_heap_count_data.should_change_heap_count = false; @@ -25886,8 +25653,6 @@ void gc_heap::check_heap_count () GCToEEInterface::RestartEE(TRUE); dprintf (9999, ("h0 restarted EE")); - dynamic_heap_count_data.smoothed_median_throughput_cost_percent = 0.0; - dprintf (6666, ("h0 finished changing, set should change to false!\n")); dynamic_heap_count_data.should_change_heap_count = false; } @@ -26364,6 +26129,7 @@ bool gc_heap::change_heap_count (int new_n_heaps) if (heap_number == 0) { change_heap_count_time = GetHighPrecisionTimeStamp() - start_time; + dprintf (6666, ("changing HC took %I64dus", change_heap_count_time)); } return true; @@ -29966,7 +29732,7 @@ void gc_heap::mark_phase (int condemned_gen_number) #endif //MULTIPLE_HEAPS { #ifdef FEATURE_EVENT_TRACE - record_mark_time (gc_time_info[time_plan - 1], current_mark_time, last_mark_time); + record_mark_time (gc_time_info[time_mark_long_weak], current_mark_time, last_mark_time); gc_time_info[time_plan] = last_mark_time; #endif //FEATURE_EVENT_TRACE @@ -33964,26 +33730,12 @@ void gc_heap::plan_phase (int condemned_gen_number) if (gc_t_join.joined()) #endif //MULTIPLE_HEAPS { -#ifdef FEATURE_EVENT_TRACE - if (informational_event_enabled_p) - { - uint64_t current_time = GetHighPrecisionTimeStamp(); - gc_time_info[time_compact] = current_time - gc_time_info[time_compact]; - } -#endif //FEATURE_EVENT_TRACE - #ifdef MULTIPLE_HEAPS for (int i = 0; i < n_heaps; i++) { -#ifdef USE_REGIONS - g_heaps [i]->rearrange_uoh_segments(); -#endif //USE_REGIONS g_heaps [i]->rearrange_heap_segments (TRUE); } #else //MULTIPLE_HEAPS -#ifdef USE_REGIONS - rearrange_uoh_segments(); -#endif //USE_REGIONS rearrange_heap_segments (TRUE); #endif //MULTIPLE_HEAPS @@ -34018,7 +33770,7 @@ void gc_heap::plan_phase (int condemned_gen_number) #endif //MULTIPLE_HEAPS #ifdef FEATURE_EVENT_TRACE - if (informational_event_enabled_p && (condemned_gen_number < (max_generation -1))) + if (informational_event_enabled_p) { uint64_t current_time = GetHighPrecisionTimeStamp(); gc_time_info[time_compact] = current_time - gc_time_info[time_compact]; @@ -40638,7 +40390,7 @@ void gc_heap::bgc_tuning::record_and_adjust_bgc_end() calculate_tuning (max_generation, true); - if (total_loh_a_last_bgc > 0) + if (total_uoh_a_last_bgc > 0) { calculate_tuning (loh_generation, true); } @@ -43639,30 +43391,35 @@ size_t gc_heap::desired_new_allocation (dynamic_data* dd, new_allocation = linear_allocation_model (allocation_fraction, new_allocation, dd_desired_allocation (dd), time_since_previous_collection_secs); - if (gen_number == 0) +#ifdef DYNAMIC_HEAP_COUNT + if (dynamic_adaptation_mode != dynamic_adaptation_to_application_sizes) +#endif //DYNAMIC_HEAP_COUNT { - if (pass == 0) + if (gen_number == 0) { - size_t free_space = generation_free_list_space (generation_of (gen_number)); - // DTREVIEW - is min_gc_size really a good choice? - // on 64-bit this will almost always be true. - dprintf (GTC_LOG, ("frag: %zd, min: %zd", free_space, min_gc_size)); - if (free_space > min_gc_size) + if (pass == 0) { - settings.gen0_reduction_count = 2; + size_t free_space = generation_free_list_space (generation_of (gen_number)); + // DTREVIEW - is min_gc_size really a good choice? + // on 64-bit this will almost always be true. + dprintf (GTC_LOG, ("frag: %zd, min: %zd", free_space, min_gc_size)); + if (free_space > min_gc_size) + { + settings.gen0_reduction_count = 2; + } + else + { + if (settings.gen0_reduction_count > 0) + settings.gen0_reduction_count--; + } } - else + if (settings.gen0_reduction_count > 0) { - if (settings.gen0_reduction_count > 0) - settings.gen0_reduction_count--; + dprintf (2, ("Reducing new allocation based on fragmentation")); + new_allocation = min (new_allocation, + max (min_gc_size, (max_size/3))); } } - if (settings.gen0_reduction_count > 0) - { - dprintf (2, ("Reducing new allocation based on fragmentation")); - new_allocation = min (new_allocation, - max (min_gc_size, (max_size/3))); - } } } @@ -45835,9 +45592,6 @@ void gc_heap::background_sweep() concurrent_print_time_delta ("Sw"); dprintf (2, ("---- (GC%zu)Background Sweep Phase ----", VolatileLoad(&settings.gc_index))); - //block concurrent allocation for large objects - dprintf (3, ("lh state: planning")); - for (int i = 0; i <= max_generation; i++) { generation* gen_to_reset = generation_of (i); @@ -45886,6 +45640,9 @@ void gc_heap::background_sweep() sweep_ro_segments(); #endif //FEATURE_BASICFREEZE + dprintf (3, ("lh state: planning")); + + // Multiple threads may reach here. This conditional partially avoids multiple volatile writes. if (current_c_gc_state != c_gc_state_planning) { current_c_gc_state = c_gc_state_planning; @@ -45916,9 +45673,7 @@ void gc_heap::background_sweep() if (heap_number == 0) { -#ifdef BGC_SERVO_TUNING - get_and_reset_loh_alloc_info(); -#endif //BGC_SERVO_TUNING + get_and_reset_uoh_alloc_info(); uint64_t suspended_end_ts = GetHighPrecisionTimeStamp(); last_bgc_info[last_bgc_info_index].pause_durations[1] = (size_t)(suspended_end_ts - suspended_start_time); total_suspended_time += last_bgc_info[last_bgc_info_index].pause_durations[1]; @@ -46247,6 +46002,7 @@ void gc_heap::background_sweep() concurrent_print_time_delta ("Swe SOH"); FIRE_EVENT(BGC1stSweepEnd, 0); + //block concurrent allocation for UOH objects enter_spin_lock (&more_space_lock_uoh); add_saved_spinlock_info (true, me_acquire, mt_bgc_uoh_sweep, msl_entered); @@ -46302,6 +46058,15 @@ void gc_heap::background_sweep() // be accurate. compute_new_dynamic_data (max_generation); + // We also need to adjust size_before for UOH allocations that occurred during sweeping. + gc_history_per_heap* current_gc_data_per_heap = get_gc_data_per_heap(); + for (int i = uoh_start_generation; i < total_generation_count; i++) + { + assert(uoh_a_bgc_marking[i - uoh_start_generation] == 0); + assert(uoh_a_no_bgc[i - uoh_start_generation] == 0); + current_gc_data_per_heap->gen_data[i].size_before += uoh_a_bgc_planning[i - uoh_start_generation]; + } + #ifdef DOUBLY_LINKED_FL current_bgc_state = bgc_not_in_process; @@ -48833,13 +48598,17 @@ HRESULT GCHeap::Initialize() // This needs to be different from our initial heap count so we can make sure we wait for // the idle threads correctly in gc_thread_function. gc_heap::dynamic_heap_count_data.last_n_heaps = 0; + + int target_tcp = (int)GCConfig::GetGCDTargetTCP(); + if (target_tcp > 0) + { + gc_heap::dynamic_heap_count_data.target_tcp = (float)target_tcp; + } // This should be adjusted based on the target tcp. See comments in gcpriv.h - gc_heap::dynamic_heap_count_data.below_target_threshold = 10.0; - gc_heap::dynamic_heap_count_data.inc_recheck_threshold = 5; - gc_heap::dynamic_heap_count_data.dec_failure_recheck_threshold = 5; + gc_heap::dynamic_heap_count_data.around_target_threshold = 10.0; // This should really be set as part of computing static data and should take conserve_mem_setting into consideration. - gc_heap::dynamic_heap_count_data.max_gen0_new_allocation = min (dd_max_size (gc_heap::g_heaps[0]->dynamic_data_of (0)), (size_t)(64 * 1024 * 1024)); - gc_heap::dynamic_heap_count_data.min_gen0_new_allocation = dd_min_size (gc_heap::g_heaps[0]->dynamic_data_of (0)); + gc_heap::dynamic_heap_count_data.max_gen0_new_allocation = Align (min (dd_max_size (gc_heap::g_heaps[0]->dynamic_data_of (0)), (size_t)(64 * 1024 * 1024)), get_alignment_constant (TRUE)); + gc_heap::dynamic_heap_count_data.min_gen0_new_allocation = Align (dd_min_size (gc_heap::g_heaps[0]->dynamic_data_of (0)), get_alignment_constant (TRUE)); dprintf (6666, ("datas max gen0 budget %Id, min %Id", gc_heap::dynamic_heap_count_data.max_gen0_new_allocation, gc_heap::dynamic_heap_count_data.min_gen0_new_allocation)); @@ -50271,17 +50040,16 @@ void gc_heap::check_and_adjust_bgc_tuning (int gen_number, size_t physical_size, } } } +#endif //BGC_SERVO_TUNING -void gc_heap::get_and_reset_loh_alloc_info() +#ifdef BACKGROUND_GC +void gc_heap::get_and_reset_uoh_alloc_info() { - if (!bgc_tuning::enable_fl_tuning) - return; + total_uoh_a_last_bgc = 0; - total_loh_a_last_bgc = 0; - - uint64_t total_loh_a_no_bgc = 0; - uint64_t total_loh_a_bgc_marking = 0; - uint64_t total_loh_a_bgc_planning = 0; + uint64_t total_uoh_a_no_bgc = 0; + uint64_t total_uoh_a_bgc_marking = 0; + uint64_t total_uoh_a_bgc_planning = 0; #ifdef MULTIPLE_HEAPS for (int i = 0; i < gc_heap::n_heaps; i++) { @@ -50290,21 +50058,33 @@ void gc_heap::get_and_reset_loh_alloc_info() { gc_heap* hp = pGenGCHeap; #endif //MULTIPLE_HEAPS - total_loh_a_no_bgc += hp->loh_a_no_bgc; - hp->loh_a_no_bgc = 0; - total_loh_a_bgc_marking += hp->loh_a_bgc_marking; - hp->loh_a_bgc_marking = 0; - total_loh_a_bgc_planning += hp->loh_a_bgc_planning; - hp->loh_a_bgc_planning = 0; + + // We need to adjust size_before for UOH allocations that occurred during marking + // before we lose the values here. + gc_history_per_heap* current_gc_data_per_heap = hp->get_gc_data_per_heap(); + // loh/poh_a_bgc_planning should be the same as they were when init_records set size_before. + for (int i = uoh_start_generation; i < total_generation_count; i++) + { + current_gc_data_per_heap->gen_data[i].size_before += hp->uoh_a_bgc_marking[i - uoh_start_generation]; + + total_uoh_a_no_bgc += hp->uoh_a_no_bgc[i - uoh_start_generation]; + hp->uoh_a_no_bgc[i - uoh_start_generation] = 0; + + total_uoh_a_bgc_marking += hp->uoh_a_bgc_marking[i - uoh_start_generation]; + hp->uoh_a_bgc_marking[i - uoh_start_generation] = 0; + + total_uoh_a_bgc_planning += hp->uoh_a_bgc_planning[i - uoh_start_generation]; + hp->uoh_a_bgc_planning[i - uoh_start_generation] = 0; + } } dprintf (2, ("LOH alloc: outside bgc: %zd; bm: %zd; bp: %zd", - total_loh_a_no_bgc, - total_loh_a_bgc_marking, - total_loh_a_bgc_planning)); + total_uoh_a_no_bgc, + total_uoh_a_bgc_marking, + total_uoh_a_bgc_planning)); - total_loh_a_last_bgc = total_loh_a_no_bgc + total_loh_a_bgc_marking + total_loh_a_bgc_planning; + total_uoh_a_last_bgc = total_uoh_a_no_bgc + total_uoh_a_bgc_marking + total_uoh_a_bgc_planning; } -#endif //BGC_SERVO_TUNING +#endif //BACKGROUND_GC bool gc_heap::is_pm_ratio_exceeded() { diff --git a/src/coreclr/gc/gc.h b/src/coreclr/gc/gc.h index a1093b5e76ce..e80853489a24 100644 --- a/src/coreclr/gc/gc.h +++ b/src/coreclr/gc/gc.h @@ -124,7 +124,10 @@ enum gc_generation_num ephemeral_generation_count = max_generation, // number of all generations - total_generation_count = poh_generation + 1 + total_generation_count = poh_generation + 1, + + // number of uoh generations + uoh_generation_count = total_generation_count - uoh_start_generation }; #ifdef GC_CONFIG_DRIVEN diff --git a/src/coreclr/gc/gcconfig.h b/src/coreclr/gc/gcconfig.h index f4b88d26db1e..3f38166e9014 100644 --- a/src/coreclr/gc/gcconfig.h +++ b/src/coreclr/gc/gcconfig.h @@ -137,9 +137,11 @@ class GCConfigStringHolder INT_CONFIG (GCEnabledInstructionSets, "GCEnabledInstructionSets", NULL, -1, "Specifies whether GC can use AVX2 or AVX512F - 0 for neither, 1 for AVX2, 3 for AVX512F")\ INT_CONFIG (GCConserveMem, "GCConserveMemory", "System.GC.ConserveMemory", 0, "Specifies how hard GC should try to conserve memory - values 0-9") \ INT_CONFIG (GCWriteBarrier, "GCWriteBarrier", NULL, 0, "Specifies whether GC should use more precise but slower write barrier") \ - STRING_CONFIG(GCName, "GCName", "System.GC.Name", "Specifies the path of the standalone GC implementation.") \ + STRING_CONFIG(GCName, "GCName", "System.GC.Name", "Specifies the name of the standalone GC implementation.") \ + STRING_CONFIG(GCPath, "GCPath", "System.GC.Path", "Specifies the path of the standalone GC implementation.") \ INT_CONFIG (GCSpinCountUnit, "GCSpinCountUnit", NULL, 0, "Specifies the spin count unit used by the GC.") \ - INT_CONFIG (GCDynamicAdaptationMode, "GCDynamicAdaptationMode", "System.GC.DynamicAdaptationMode", 0, "Enable the GC to dynamically adapt to application sizes.") + INT_CONFIG (GCDynamicAdaptationMode, "GCDynamicAdaptationMode", "System.GC.DynamicAdaptationMode", 0, "Enable the GC to dynamically adapt to application sizes.") \ + INT_CONFIG (GCDTargetTCP, "GCDTargetTCP", "System.GC.DTargetTCP", 0, "Specifies the target tcp for DATAS") // This class is responsible for retreiving configuration information // for how the GC should operate. class GCConfig diff --git a/src/coreclr/gc/gchandletable.cpp b/src/coreclr/gc/gchandletable.cpp index a4b3ab8629a0..ef0bbf8c93ae 100644 --- a/src/coreclr/gc/gchandletable.cpp +++ b/src/coreclr/gc/gchandletable.cpp @@ -213,7 +213,7 @@ Object* GCHandleManager::InterlockedCompareExchangeObjectInHandle(OBJECTHANDLE h HandleType GCHandleManager::HandleFetchType(OBJECTHANDLE handle) { uint32_t type = ::HandleFetchType(handle); - assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_NATIVE_COM); + assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_INTERIOR_POINTER); return static_cast(type); } diff --git a/src/coreclr/gc/gcinterface.h b/src/coreclr/gc/gcinterface.h index 75b84684bb9e..f15ee691ebef 100644 --- a/src/coreclr/gc/gcinterface.h +++ b/src/coreclr/gc/gcinterface.h @@ -502,7 +502,17 @@ typedef enum * but we are keeping it here for backward compatibility purposes" * */ - HNDTYPE_WEAK_NATIVE_COM = 9 + HNDTYPE_WEAK_NATIVE_COM = 9, + + /* + * INTERIOR POINTER HANDLES + * + * Interior pointer handles allow the vm to request that the GC keep an interior pointer to + * a given object updated to keep pointing at the same location within an object. These handles + * have an extra pointer which points at an interior pointer into the first object. + * + */ + HNDTYPE_WEAK_INTERIOR_POINTER = 10 } HandleType; typedef enum diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 6bd88798a493..85eb22d6080c 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -140,10 +140,10 @@ inline void FATAL_GC_ERROR() // // This means any empty regions can be freely used for any generation. For // Server GC we will balance regions between heaps. -// For now disable regions for StandAlone GC, NativeAOT and MacOS builds +// For now disable regions for standalone GC and macOS builds #if defined (HOST_64BIT) && !defined (BUILD_AS_STANDALONE) && !defined(__APPLE__) #define USE_REGIONS -#endif //HOST_64BIT && BUILD_AS_STANDALONE +#endif //HOST_64BIT && BUILD_AS_STANDALONE && !__APPLE__ //#define SPINLOCK_HISTORY //#define RECORD_LOH_STATE @@ -1754,6 +1754,8 @@ class gc_heap PER_HEAP_ISOLATED_METHOD void add_to_history(); + PER_HEAP_ISOLATED_METHOD void get_and_reset_uoh_alloc_info(); + #ifdef BGC_SERVO_TUNING // Currently BGC servo tuning is an experimental feature. class bgc_tuning @@ -1999,7 +2001,6 @@ class gc_heap }; PER_HEAP_ISOLATED_METHOD void check_and_adjust_bgc_tuning (int gen_number, size_t physical_size, ptrdiff_t virtual_fl_size); - PER_HEAP_ISOLATED_METHOD void get_and_reset_loh_alloc_info(); #endif //BGC_SERVO_TUNING #ifndef USE_REGIONS @@ -2118,6 +2119,8 @@ class gc_heap PER_HEAP_METHOD void gc1(); #ifdef DYNAMIC_HEAP_COUNT + PER_HEAP_ISOLATED_METHOD size_t get_total_soh_stable_size(); + PER_HEAP_ISOLATED_METHOD void assign_new_budget (int gen_number, size_t desired_per_heap); PER_HEAP_METHOD bool prepare_rethread_fl_items(); PER_HEAP_METHOD void rethread_fl_items(int gen_idx); PER_HEAP_ISOLATED_METHOD void merge_fl_from_other_heaps (int gen_idx, int to_n_heaps, int from_n_heaps); @@ -2232,6 +2235,8 @@ class gc_heap PER_HEAP_METHOD BOOL bgc_loh_allocate_spin(); PER_HEAP_METHOD BOOL bgc_poh_allocate_spin(); + + PER_HEAP_METHOD void bgc_record_uoh_allocation(int gen_number, size_t size); #endif //BACKGROUND_GC PER_HEAP_METHOD void add_saved_spinlock_info ( @@ -2558,7 +2563,7 @@ class gc_heap // re-initialize a heap in preparation to putting it back into service PER_HEAP_METHOD void recommission_heap(); - PER_HEAP_ISOLATED_METHOD int calculate_new_heap_count(); + PER_HEAP_ISOLATED_METHOD void calculate_new_heap_count(); // check if we should change the heap count PER_HEAP_METHOD void check_heap_count(); @@ -3438,6 +3443,11 @@ class gc_heap PER_HEAP_FIELD_SINGLE_GC uint8_t* next_sweep_obj; PER_HEAP_FIELD_SINGLE_GC uint8_t* current_sweep_pos; + + PER_HEAP_FIELD_SINGLE_GC size_t uoh_a_no_bgc[uoh_generation_count]; + PER_HEAP_FIELD_SINGLE_GC size_t uoh_a_bgc_marking[uoh_generation_count]; + PER_HEAP_FIELD_SINGLE_GC size_t uoh_a_bgc_planning[uoh_generation_count]; + #ifdef DOUBLY_LINKED_FL PER_HEAP_FIELD_SINGLE_GC heap_segment* current_sweep_seg; #endif //DOUBLY_LINKED_FL @@ -3463,9 +3473,6 @@ class gc_heap #endif //SNOOP_STATS #ifdef BGC_SERVO_TUNING - PER_HEAP_FIELD_SINGLE_GC uint64_t loh_a_no_bgc; - PER_HEAP_FIELD_SINGLE_GC uint64_t loh_a_bgc_marking; - PER_HEAP_FIELD_SINGLE_GC uint64_t loh_a_bgc_planning; PER_HEAP_FIELD_SINGLE_GC size_t bgc_maxgen_end_fl_size; #endif //BGC_SERVO_TUNING #endif //BACKGROUND_GC @@ -4099,11 +4106,9 @@ class gc_heap PER_HEAP_ISOLATED_FIELD_SINGLE_GC GCEvent bgc_start_event; -#ifdef BGC_SERVO_TUNING // Total allocated last BGC's plan + between last and this bgc + // this bgc's mark - PER_HEAP_ISOLATED_FIELD_SINGLE_GC uint64_t total_loh_a_last_bgc; -#endif //BGC_SERVO_TUNING + PER_HEAP_ISOLATED_FIELD_SINGLE_GC uint64_t total_uoh_a_last_bgc; #endif //BACKGROUND_GC #ifdef USE_REGIONS @@ -4237,6 +4242,10 @@ class gc_heap // to smooth out the situation when we rarely pick the gen2 GCs in the first array. struct dynamic_heap_count_data_t { + float target_tcp = 5.0; + float target_gen2_tcp = 10.0; + + static const int recorded_adjustment_size = 4; static const int sample_size = 3; static const int recorded_tcp_array_size = 64; @@ -4245,15 +4254,127 @@ class gc_heap uint64_t elapsed_between_gcs; // time between gcs in microseconds (this should really be between_pauses) uint64_t gc_pause_time; // pause time for this GC uint64_t msl_wait_time; + size_t gc_index; size_t gc_survived_size; + int gen0_budget_per_heap; }; uint32_t sample_index; sample samples[sample_size]; + sample& get_last_sample() + { + int last_sample_index = (sample_index + sample_size - 1) % sample_size; + sample& s = samples[last_sample_index]; + return s; + } + + enum adjust_metric + { + not_adjusted = 0, + adjust_budget = 1, + adjust_hc = 2 + }; + + const char* const str_adjust_metrics[4] = + { + "no adjustment", + "budget", + "HC" + }; + + // For adjust_budget I'm keeping a counter that records how many times we've done this instead of recording + // a separate entry each time since we could have many in a row. + struct adjustment + { + adjust_metric metric; + int count; + int avg_msl_per_heap; + // Distance to target + float distance; + int hc_change; + size_t gc_index; + + // This is determined by looking at the median of the next samples after change + // Success means it did achieve the effect we wanted to achieve, ie, + // if we inc-ed HC, we observed msl and pause time go down. + // It doesn't mean we necessarily achieved target. + bool successful; + }; + + adjustment adjustment_history[recorded_adjustment_size]; + int current_adjustment_index; + size_t current_samples_count; size_t processed_samples_count; + adjustment* get_last_nth_adjustment (int distance_to_current) + { + int adjustment_idx = (current_adjustment_index + recorded_adjustment_size + distance_to_current) % recorded_adjustment_size; + return &adjustment_history[adjustment_idx]; + } + + adjustment* get_last_adjustment() + { + return get_last_nth_adjustment (-1); + } + + void record_adjustment (adjust_metric metric, float distance, int change_int, size_t current_gc_index) + { + if (metric == adjust_budget) + { + adjustment* adj = get_last_adjustment(); + if (adj->metric == adjust_budget) + { + (adj->count)++; + dprintf (6666, ("last adjustment was also budget at GC#%Id, inc count to %d", adj->gc_index, adj->count)); + return; + } + } + + adjustment* adj = &adjustment_history[current_adjustment_index]; + adj->metric = metric; + adj->count = 1; + adj->distance = distance; + adj->hc_change = change_int; + adj->gc_index = current_gc_index; + + dprintf (6666, ("recording adjustment %s at #%d GC#%Id - distance to target %.3f, changed %d HC", + str_adjust_metrics[metric], current_adjustment_index, adj->gc_index, adj->distance, adj->hc_change)); + + current_adjustment_index = (current_adjustment_index + 1) % recorded_adjustment_size; + } + + bool same_action_succeeded (adjust_metric metric, int distance_to_current, int change_int) + { + int adjustment_idx = (current_adjustment_index + recorded_adjustment_size + distance_to_current) % recorded_adjustment_size; + adjustment* adj = &adjustment_history[adjustment_idx]; + dprintf (6666, ("adj->metric %d, metric %d, adj#%d: hc_change > 0 = %d, change_int > 0 = %d", + adjustment_idx, (adj->hc_change > 0), (change_int > 0))); + if ((adj->metric == metric) && ((change_int > 0) == (adj->hc_change > 0))) + { + return adj->successful; + } + + return false; + } + + void reset_budget_adjustment() + { + // adjust_budget is a transient state, as in, we only maintain it to detect if we should actually change HC instead. So + // if we were in a situation where we chose to change budget instead of HC, then we got out of that situation, we should + // reset this adjustment. + adjustment* adj = get_last_adjustment(); + if (adj->metric == adjust_budget) + { + memset (adj, 0, sizeof (adjustment)); + int saved_current_adjustment_index = current_adjustment_index; + current_adjustment_index = (current_adjustment_index + recorded_adjustment_size - 1) % recorded_adjustment_size; + + dprintf (6666, ("reset last budget adj at %d, set current adj to %d", saved_current_adjustment_index, current_adjustment_index)); + } + } + // // We need to observe the history of tcp's so record them in a small buffer. // @@ -4261,6 +4382,78 @@ class gc_heap float recorded_tcp[recorded_tcp_array_size]; int recorded_tcp_index; int total_recorded_tcp; + int tcp_count_in_rearrange; + float tcp_slope_in_rearrange; + + float get_avg_tcp_in_rearrange (int start_idx, int end_idx) + { + float total_tcp = 0.0; + int count = start_idx - end_idx + 1; + for (int idx = start_idx; idx >= end_idx ; idx--) + { + assert ((idx > 0) && (idx < tcp_count_in_rearrange)); + total_tcp += recorded_tcp_rearranged[idx]; + } + + float avg_tcp = total_tcp / count; + dprintf (6666, ("getting avg for entry#%d-%d, total %.3f / %d = %.3f", end_idx, start_idx, total_tcp, count, avg_tcp)); + + return avg_tcp; + } + + // If our buffer has a lot of entries, it means we've been stable for a while. We can have a situation where + // suddenly the tcp's change dramatically, we should treat those as temporary and not act on them. + // + // If we consider this not temporary, tcp_to_consider will be set to either the avg of the most recent entries + // or the most recent entry. + bool is_temp_change (float* tcp_to_consider) + { + assert (tcp_count_in_rearrange >= 1); + + int avg_count = 3; + int start_idx = tcp_count_in_rearrange - 1; + + // If we don't even have <= 3 entries, or have a really steep slope, it means we are far from target, + // We should consider to adjust. + if ((tcp_count_in_rearrange <= avg_count) || (fabs (tcp_slope_in_rearrange) > 3.0)) + { + dprintf (6666, ("%d tcps, slope is %.3f, returning last one %.3f", + tcp_count_in_rearrange, tcp_slope_in_rearrange, recorded_tcp_rearranged[start_idx])); + *tcp_to_consider = recorded_tcp_rearranged[start_idx]; + return false; + } + + int end_idx = start_idx - avg_count + 1; + float avg = get_avg_tcp_in_rearrange (start_idx, end_idx); + *tcp_to_consider = avg; + + if (tcp_count_in_rearrange > (avg_count * 3)) + { + // We look back to see if the previous entries are within 30% of this average. + start_idx = end_idx - 1; + end_idx = start_idx - avg_count + 1; + float last_avg = get_avg_tcp_in_rearrange (start_idx, end_idx); + float diff_pct_in_avg = 0.0; + if (avg > last_avg) + { + diff_pct_in_avg = (avg - last_avg) / last_avg; + } + else + { + diff_pct_in_avg = (last_avg - avg) / avg; + } + + dprintf (6666, ("avg of last %d tcps is %.3f, avg of the %d tcps before those is %.3f, diff (to min) is %.3f", + avg_count, *tcp_to_consider, avg_count, last_avg, diff_pct_in_avg)); + + return (diff_pct_in_avg > 0.3); + } + else + { + dprintf (6666, ("we have only %d entries, consider %.3f not temporary", tcp_count_in_rearrange, *tcp_to_consider)); + return false; + } + } int add_to_recorded_tcp (float tcp) { @@ -4298,142 +4491,472 @@ class gc_heap return copied_count; } - int highest_avg_recorded_tcp (int count, float avg, float* highest_avg) + void init_recorded_tcp () { - float highest_sum = 0.0; - int highest_count = 0; + total_recorded_tcp = 0; + recorded_tcp_index = 0; + dprintf (6666, ("INIT tcp buffer")); + } + + int get_recorded_tcp_count () { return total_recorded_tcp; } - for (int i = 0; i < count; i++) + float around_target_accumulation; + float around_target_threshold; + + bool is_tcp_in_range (float diff_pct, float slope) + { + return ((diff_pct <= 0.2) && (diff_pct >= -0.2) && (slope <= 0.1) && (slope >= -0.1)); + } + + bool is_close_to_max (int new_n, int max) + { + return ((max - new_n) <= (max / 10)); + } + + float slope (float* y, int n, float* avg); + + // if the last attempt was successful, and we still aren't to target, we should be more aggressive. + int get_aggressiveness (int change_int) + { + int factor = 1; + + adjust_metric metric = adjust_hc; + + // Looking at the last 2 adjustments was too aggressive - so currently only look at the last one. + for (int i = -1; i >= -1; i--) { - if (recorded_tcp_rearranged[i] > avg) + bool last_action_succeeded = same_action_succeeded (metric, i, change_int); + dprintf (6666, ("current %d adjustment of %s %s, agg factor %d", + i, str_adjust_metrics[metric], (last_action_succeeded ? "succeeded" : "failed"), + (factor + last_action_succeeded))); + if (!last_action_succeeded) { - highest_count++; - highest_sum += recorded_tcp_rearranged[i]; + break; } - } - if (highest_count) - { - *highest_avg = highest_sum / highest_count; + factor += 1; } - return highest_count; + return factor; } - void init_recorded_tcp () + void check_success_after_adjust (size_t current_gc_index, adjustment* adj, float tcp) { - total_recorded_tcp = 0; - recorded_tcp_index = 0; - dprintf (6666, ("INIT tcp buffer")); - } + // If this is right after we adjusted, we should see if we were successful with the adjustment. + size_t last_changed_gc_index = adj->gc_index; + if (!last_changed_gc_index) return; - int get_recorded_tcp_count () { return total_recorded_tcp; } + bool check_p = (current_gc_index < (last_changed_gc_index + (2 * sample_size))); - // - // Maintain some info about last time we did change heap count. - // - size_t last_changed_gc_index; - // This is intentionally kept as a float for precision. - float last_changed_count; - float last_changed_stcp; + dprintf (6666, ("last adjusted at GC#%Id, %Id GCs ago, %s", + last_changed_gc_index, (current_gc_index - last_changed_gc_index), (check_p ? "check success" : "already checked success"))); + if (!check_p) + { + return; + } - // - // For tuning above/below target tcp. - // - // If we just increased the heap count and immediately need to grow again, that counts as a failure. - // The higher the failure count, the more aggressive we should grow. - int inc_failure_count; - - // If we are trending up and the tcp is already close enough to target, we need this many samples - // before we adjust. - int inc_recheck_threshold; - - // If we shrink and the stcp doesn't change much, that counts as a failure. For the below target case - // it's fine to stay here for a while. Either it'll naturally change and break out of this situation - // or we wait for a while before we re-evaluate. How long we wait is defined by dec_recheck_threshold - // each time our calculation tells us to shrink. - int dec_failure_count; - int dec_failure_recheck_threshold; - - // If we continue to be below target for an extended period of time, ie, we've accumulated more than - // below_target_threshold, we want to reduce the heap count. - float below_target_accumulation; - float below_target_threshold; - - // TODO: we should refactor this and the inc checks into a utility class. - bool dec_by_one_scheduled; - int dec_by_one_count; - - // Currently only used for dprintf. - size_t first_below_target_gc_index; - - float get_range_upper (float t) - { - return (t * 1.2f); + adjust_metric adj_metric = adj->metric; + + // We are guaranteed to have at least sample_size amount of new samples. + if (adj_metric == adjust_hc) + { + // For hc case, we just check if tcp has changed in the right direction. + bool adjusted_up = (adj->hc_change > 0); + // Do we want to do a percentage here instead of absolute comparison? + bool tcp_reduced_p = (tcp < (adj->distance + target_tcp)); + adj->successful = (adjusted_up == tcp_reduced_p); + dprintf (6666, ("last adjust hc - %d -> %d heaps, tcp %.3f -> %.3f, %s", + (n_heaps - adj->hc_change), n_heaps, (adj->distance + target_tcp), tcp, + (adj->successful ? "success" : "fail"))); + } } - bool is_tcp_in_range (float diff_pct, float slope) + void reset_accumulation() { - return ((diff_pct <= 0.2) && (diff_pct >= -0.2) && (slope <= 0.1) && (slope >= -0.1)); + around_target_accumulation = 0.0; + init_recorded_tcp(); } - bool is_tcp_far_below (float diff_pct) + bool should_change (float tcp, float* tcp_to_consider, size_t current_gc_index) { - return (diff_pct >= 0.4); + adjustment* adj = get_last_adjustment(); + size_t last_changed_gc_index = adj->gc_index; + + check_success_after_adjust (current_gc_index, adj, tcp); + + float diff_to_target = tcp - target_tcp; + dprintf (6666, ("accumulating %.3f + %.3f -> %.3f", + around_target_accumulation, diff_to_target, (around_target_accumulation + diff_to_target))); + around_target_accumulation += diff_to_target; + + size_t num_gcs_since_last_change = current_gc_index - last_changed_gc_index; + dprintf (6666, ("we adjusted at GC#%Id, %Id GCs ago", last_changed_gc_index, num_gcs_since_last_change)); + if (last_changed_gc_index && (num_gcs_since_last_change < (2 * sample_size))) + { + dprintf (6666, ("we just adjusted %Id GCs ago, skipping", num_gcs_since_last_change)); + return false; + } + + // If we haven't accumulated enough changes. + if ((around_target_accumulation < around_target_threshold) && (around_target_accumulation > -around_target_threshold)) + { + dprintf (6666, ("accumulated %.3f < %.3f and > %.3f, skipping", + around_target_accumulation, around_target_threshold, -around_target_threshold)); + return false; + } + + // If the slope clearly indicates it's already going the direction we want to. + float avg_recorded_tcp = 0.0; + int tcp_count = rearrange_recorded_tcp (); + float tcp_slope = slope (recorded_tcp_rearranged, tcp_count, &avg_recorded_tcp); + dprintf (6666, ("acc thres exceeded! %s slope of %d tcps is %.3f", + ((around_target_accumulation > 0.0) ? "above" : "below"), tcp_count, tcp_slope)); + + // if threshold is 2 * target, this means the avg tcp in the buffer is 40% higher/lower + if ((tcp_count >= 5) && + (((around_target_accumulation > 0.0) && (tcp_slope < -0.2)) || + ((around_target_accumulation < 0.0) && (tcp_slope > 0.2)))) + { + dprintf (6666, ("already trending the right direction, skipping")); + reset_accumulation(); + return false; + } + + // If the tcp has been hovering around the target. + float diff_pct = diff_to_target / target_tcp; + if (is_tcp_in_range (diff_pct, tcp_slope)) + { + dprintf (6666, ("diff %.3f, slope %.3f already in range", diff_pct, tcp_slope)); + reset_accumulation(); + return false; + } + + tcp_count_in_rearrange = tcp_count; + tcp_slope_in_rearrange = tcp_slope; + + if (is_temp_change (tcp_to_consider)) + { + dprintf (6666, ("this is a temporary change, ignore")); + reset_accumulation(); + return false; + } + + return true; } - bool is_close_to_max (int new_n, int max) + /* + | | | max | + | hc | f | growth | + | ---- | ---- | ------ | + | 1 | 4.00 | 4 | + | 2 | 2.46 | 5 | + | 4 | 1.52 | 6 | + | 6 | 1.14 | 7 | + | 8 | 0.93 | 7 | + | 10 | 0.80 | 8 | + | 14 | 0.63 | 9 | + | 16 | 0.57 | 9 | + | 32 | 0.35 | 11 | + | 64 | 0.22 | 14 | + | 80 | 0.19 | 15 | + */ + int get_max_growth(int current_hc) { - return ((max - new_n) <= (max / 10)); + return (int)round(current_hc * (4.0 * pow (current_hc, -0.7))); } - bool should_dec_by_one() + int get_hc_change_factors (int change_int, size_t last_change_gc_index) { - if (!dec_by_one_scheduled) + int factor = 3; + int inc_factor = factor; + + if (last_change_gc_index) { - dec_by_one_scheduled = true; + if (change_heap_count_time == 0) + { + dprintf (6666, ("WHAT!!! last HC change took 0us?!")); + return 0; + } + + assert (change_heap_count_time != 0); + + // If changing HC is expensive, we need to space it out. + uint64_t total_gc_pause_time = 0; + for (int i = 0; i < sample_size; i++) + { + total_gc_pause_time += samples[i].gc_pause_time; + } + + uint64_t avg_gc_pause_time = total_gc_pause_time / sample_size; + + if (change_heap_count_time > avg_gc_pause_time) + { + factor *= 2 * (int)(change_heap_count_time/ avg_gc_pause_time); + } + + dprintf (6666, ("last HC change took %.3fms / avg gc pause %.3fms = %d , factor %d", + (change_heap_count_time / 1000.0), (avg_gc_pause_time / 1000.0), + (change_heap_count_time / avg_gc_pause_time), factor)); } - if (dec_by_one_scheduled) + if (change_int < 0) { - dec_by_one_count++; - dprintf (6666, ("scheduled to dec by 1 heap %d times", dec_by_one_count)); + // Dec in general should be done less frequently than inc. + factor *= 2; + + adjustment* adj = get_last_adjustment(); + int last_hc_change = adj->hc_change; + + dprintf (6666, ("dec: last HC change %d heaps at GC#%Id, factor %d", last_hc_change, last_change_gc_index, factor)); + + if (last_hc_change < 0) + { + // If it's the 2nd time in a row we want to dec, we also delay it. + dprintf (6666, ("last was dec, factor %d->%d", factor, (factor * 2))); + factor *= 2; + } + else + { + // If the last adj was inc, and there was another dec adjustment before that, we delay dec. + adj = get_last_nth_adjustment (-2); + size_t last_2nd_change_gc_index = adj->gc_index; + + if (last_2nd_change_gc_index > 0) + { + int last_2nd_hc_change = adj->hc_change; + dprintf (6666, ("before last was %d heaps at GC#%Id (%Id GCs), factor is now %d", + last_2nd_hc_change, last_2nd_change_gc_index, (last_change_gc_index - last_2nd_change_gc_index), factor)); + + if (last_2nd_hc_change < 0) + { + bool inc_too_quick_p = ((last_change_gc_index - last_2nd_change_gc_index) < (size_t)(inc_factor * 2 * sample_size)); + + if (inc_too_quick_p) + { + dprintf (6666, ("We dec-ed and quickly followed with an inc, factor %d -> %d", factor, (factor * 4))); + factor *= 4; + } + } + } + } } - return (dec_by_one_count >= 5); + return factor; } - void reset_dec_by_one() + adjust_metric should_change_hc (int max_hc_datas, int min_hc_datas, int max_hc_growth, int& change_int, size_t current_gc_index) { - dec_by_one_scheduled = false; - dec_by_one_count = 0; + adjust_metric adj_metric = not_adjusted; + + int saved_change_int = change_int; + + if (change_int > 0) + { + change_int = min (max_hc_growth, change_int); + } + else if (change_int < 0) + { + if ((change_int + n_heaps) < 1) + { + change_int = 1 - n_heaps; + } + } + + if (change_int == 0) + { + dprintf (6666, ("cannot change due to upper/lower limit!")); + return adj_metric; + } + + if (saved_change_int != change_int) + { + dprintf (6666, ("change %d heaps instead of %d so we don't go over upper/lower limit", change_int, saved_change_int)); + } + + // Now we need to decide whether we should change the HC or the budget. + // + // There are scenarios where we must change the HC because we cannot change budget to make tcp go the + // direction we want. + // + // When we are in a situation where we have the flexibility to change HC or budget, we should only change HC + // in the following cases - + // + // 1) if the change is large enough or we kept meaning to change it but kept getting into this same situation, or + // + // 2) if it's large enough and there have been enough GCs since we last changed + // + // Note that we only return adj_budget if we had the choice to adjust budget or HC and chose to adjust budget, + // because we use this to indicate if at some point we should change HC instead. + if ((change_int > 0) && (n_heaps == min_hc_datas)) + { + dprintf (6666, ("we are already at min datas heaps %d, cannot inc budget so must inc HC", n_heaps)); + adj_metric = adjust_hc; + } + else if ((change_int < 0) && (n_heaps == max_hc_datas)) + { + dprintf (6666, ("we are already at max datas heaps %d, cannot dec budget so must dec HC", n_heaps)); + adj_metric = adjust_hc; + } + + float hc_change_pct = fabsf ((float)change_int / n_heaps); + + adjustment* adj = get_last_adjustment(); + size_t last_change_gc_index = adj->gc_index; + + // Now we are at the point we do want to change HC but there may be some things that make us want to opt out it. + adj_metric = adjust_hc; + + if (last_change_gc_index) + { + size_t num_gcs_since_change = current_gc_index - last_change_gc_index; + int hc_change_factor = get_hc_change_factors (change_int, last_change_gc_index); + + dprintf (6666, ("hc would change %.3f, factor is %d", hc_change_pct, hc_change_factor)); + if (hc_change_pct < 0.2) + { + // Should we also consider absolute time here? + int delayed_hc_change_factor = hc_change_factor * 3; + int count = 0; + if (adj->metric == adjust_budget) + { + count = adj->count; + } + + dprintf (6666, ("we've changed budget instead of HC %d times from %Id GCs ago, thres %d times", + count, num_gcs_since_change, delayed_hc_change_factor)); + + if (count < delayed_hc_change_factor) + { + adj_metric = adjust_budget; + } + } + else + { + bool change_p = (num_gcs_since_change > (size_t)(hc_change_factor * sample_size)); + dprintf (6666, ("It's been %Id GCs since we wanted to change HC last time, thres %d GCs, %s", + num_gcs_since_change, (hc_change_factor * sample_size), (change_p ? "change" : "don't change yet"))); + if (!change_p) + { + adj_metric = not_adjusted; + } + } + } + + dprintf (6666, ("conclusion: %s", str_adjust_metrics[adj_metric])); + if (adj_metric == adjust_hc) + { + reset_budget_adjustment(); + } + return adj_metric; } + // + // Budget computation. Now we have 2 budgets - + // BCS (Budget Computed via Survrate) and + // BCD (Budget Computed via DATAS) + // + // When DATAS is on, BCD is our upper bound because we want to control how much allocation to allow before + // the next GC happens which directly contributes to the heap size. + // If BCS is smaller, it means we have room to adjust budget. Currently we don't adjust it dramatically because + // then we risk affecting tcp too much (tcp is still calculated using both the collection time and the wait + // time in msl). + // + size_t max_gen0_new_allocation; size_t min_gen0_new_allocation; - size_t compute_gen0_new_allocation (size_t total_old_gen_size) + size_t compute_total_gen0_budget (size_t total_soh_stable_size) { - assert (total_old_gen_size > 0); + assert (total_soh_stable_size > 0); - // TODO: adjust these based on conserve_mem_setting. - double old_gen_growth_factor = 16.0 / sqrt ((double)total_old_gen_size / 1000.0 / 1000.0); + float factor = (float)(20 - conserve_mem_setting); + double old_gen_growth_factor = factor / sqrt ((double)total_soh_stable_size / 1000.0 / 1000.0); double saved_old_gen_growth_factor = old_gen_growth_factor; old_gen_growth_factor = min (10.0, old_gen_growth_factor); old_gen_growth_factor = max (0.1, old_gen_growth_factor); - size_t total_new_allocation_old_gen = (size_t)(old_gen_growth_factor * (double)total_old_gen_size); - size_t new_allocation_old_gen = total_new_allocation_old_gen / n_heaps; - - dprintf (6666, ("total gen2 %Id (%.3fmb), factor %.3f=>%.3f -> total gen0 new_alloc %Id (%Id/heap, %.3fmb)", - total_old_gen_size, ((double)total_old_gen_size / 1000.0 / 1000.0), + size_t total_new_allocation_old_gen = (size_t)(old_gen_growth_factor * (double)total_soh_stable_size); + dprintf (6666, ("stable soh %Id (%.3fmb), factor %.3f=>%.3f -> total gen0 new_alloc %Id (%.3fmb)", + total_soh_stable_size, ((double)total_soh_stable_size / 1000.0 / 1000.0), saved_old_gen_growth_factor, old_gen_growth_factor, total_new_allocation_old_gen, - new_allocation_old_gen, ((double)new_allocation_old_gen / 1000.0 / 1000.0))); + ((double)total_new_allocation_old_gen / 1000.0 / 1000.0))); + return total_new_allocation_old_gen; + } - new_allocation_old_gen = min (max_gen0_new_allocation, new_allocation_old_gen); - new_allocation_old_gen = max (min_gen0_new_allocation, new_allocation_old_gen); + // Called at the end of a blocking GC before that GC's sample is recorded. + // + // Usually we want to take BCS because it's good for surv rate but if BCS is < BCD, we have room + // to adjust to affect tcp. + size_t compute_gen0_budget_per_heap (size_t total_soh_stable_size, float tcp, size_t bcs_per_heap) + { + size_t total_budget_old_gen = compute_total_gen0_budget (total_soh_stable_size); + size_t budget_old_gen_per_heap = total_budget_old_gen / n_heaps; + budget_old_gen_per_heap = Align (budget_old_gen_per_heap, get_alignment_constant (TRUE)); + + dprintf (6666, ("-> %Id / heap (% .3fmb)", + budget_old_gen_per_heap, ((double)budget_old_gen_per_heap / 1000.0 / 1000.0))); + + budget_old_gen_per_heap = min (max_gen0_new_allocation, budget_old_gen_per_heap); + budget_old_gen_per_heap = max (min_gen0_new_allocation, budget_old_gen_per_heap); + + // We want to return a number between bcs and bcd + if (bcs_per_heap < budget_old_gen_per_heap) + { + // If tcp was above target, we can increase budget up to what DATAS allows. But we only + // do this when tcp is close enough. + sample& sample = get_last_sample(); + size_t last_budget_per_heap = sample.gen0_budget_per_heap; + + // We don't do anything if we just changed HC between this GC start and previous suspend end. + adjustment* adj = get_last_adjustment(); + size_t last_changed_gc_index = adj->gc_index; + size_t saved_last_changed_gc_index = last_changed_gc_index; + size_t current_gc_index = VolatileLoadWithoutBarrier (&settings.gc_index); + size_t last_bgc_index = VolatileLoadWithoutBarrier (&saved_bgc_settings.gc_index); + + if (last_bgc_index == (current_gc_index - 1)) + { + last_changed_gc_index++; + } - return new_allocation_old_gen; + dprintf (6666, ("last gc gen0 budget %Id, last adjustment %s was at GC#%Id, last BGC was #%Id, this GC #%Id, %s", + last_budget_per_heap, str_adjust_metrics[adj->metric], saved_last_changed_gc_index, last_bgc_index, current_gc_index, + ((last_changed_gc_index < (current_gc_index - 1)) ? "didn't just change" : "did just change"))); + + if ((adj->metric == adjust_budget) || (last_changed_gc_index < (current_gc_index - 1))) + { + float diff = tcp - target_tcp; + + adjustment* adj = get_last_adjustment(); + bool adjust_budget_p = (adj->metric == adjust_budget); + //bool adjust_budget_p = false; + + dprintf (6666, ("tcp of last sample was %.3f, diff to target %.3f, pct %.3f, last adj %s budget", + tcp, diff, (diff / target_tcp), (adjust_budget_p ? "was" : "was not"))); + + if (adjust_budget_p || + ((diff > 0.0) && ((diff < 2.0) || ((diff / target_tcp) < 0.4)))) + { + float last_alloc_time = (float)100.0 - tcp; + float target_alloc_time = (float)100.0 - target_tcp; + + size_t new_budget_per_heap = (size_t)(last_budget_per_heap / last_alloc_time * target_alloc_time); + new_budget_per_heap = Align (new_budget_per_heap, get_alignment_constant (TRUE)); + + dprintf (6666, ("adjust last budget %Id to %Id (%.3fmb)", + last_budget_per_heap, new_budget_per_heap, (new_budget_per_heap / 1000.0 / 1000.0))); + + if ((new_budget_per_heap >= bcs_per_heap) && (new_budget_per_heap <= budget_old_gen_per_heap)) + { + dprintf (6666, ("setting this as the new budget!")); + return new_budget_per_heap; + } + } + } + } + + dprintf (6666, ("taking min of the two: %Id, %Id", bcs_per_heap, budget_old_gen_per_heap)); + return min (bcs_per_heap, budget_old_gen_per_heap); } // @@ -4453,17 +4976,7 @@ class gc_heap size_t current_gen2_samples_count; size_t processed_gen2_samples_count; - - // This records the stcp last time we processed ephemeral samples. We use it - float last_processed_stcp; - - float median_throughput_cost_percent; // estimated overhead of allocator + gc - float smoothed_median_throughput_cost_percent; // exponentially smoothed version - float percent_heap_space_cost_per_heap; // percent space cost of adding a heap - float tcp_reduction_per_step_up; // throughput cost percent effect of increasing heap count - float tcp_increase_per_step_down; // throughput cost percent effect of decreasing heap count - float scp_increase_per_step_up; // space cost percent effect of increasing heap count - float scp_decrease_per_step_down; // space cost percent effect of decreasing heap count + size_t gen2_last_changed_sample_count; int new_n_heaps; // the heap count we changed from diff --git a/src/coreclr/gc/gcscan.cpp b/src/coreclr/gc/gcscan.cpp index 92ed7f3a8687..6f200810fed5 100644 --- a/src/coreclr/gc/gcscan.cpp +++ b/src/coreclr/gc/gcscan.cpp @@ -171,6 +171,7 @@ void GCScan::GcScanHandles (promote_func* fn, int condemned, int max_gen, Ref_UpdatePointers(condemned, max_gen, sc, fn); Ref_UpdatePinnedPointers(condemned, max_gen, sc, fn); Ref_ScanDependentHandlesForRelocation(condemned, max_gen, sc, fn); + Ref_ScanWeakInteriorPointersForRelocation(condemned, max_gen, sc, fn); } } diff --git a/src/coreclr/gc/handletablescan.cpp b/src/coreclr/gc/handletablescan.cpp index 7c0692ad5b8f..e5b27da8e621 100644 --- a/src/coreclr/gc/handletablescan.cpp +++ b/src/coreclr/gc/handletablescan.cpp @@ -931,6 +931,15 @@ static void VerifyObjectAndAge(_UNCHECKED_OBJECTREF from, _UNCHECKED_OBJECTREF o } } +size_t my_get_size (_UNCHECKED_OBJECTREF ob) +{ + MethodTable* mT = ob->GetGCSafeMethodTable(); + + return (mT->GetBaseSize() + + (mT->HasComponentSize() ? + ((size_t)reinterpret_cast(ob)->GetNumComponents() * mT->RawGetComponentSize()) : 0)); +} + /* * BlockVerifyAgeMapForBlocksWorker * @@ -992,6 +1001,23 @@ void BlockVerifyAgeMapForBlocksWorker(uint32_t *pdwGen, uint32_t dwClumpMask, Sc } } } + if (uType == HNDTYPE_WEAK_INTERIOR_POINTER) + { + PTR_uintptr_t pUserData = HandleQuickFetchUserDataPointer((OBJECTHANDLE)pValue); + + // if we did then copy the value + if (pUserData) + { + uintptr_t pObjectInteriorPointer = **reinterpret_cast(pUserData); + _UNCHECKED_OBJECTREF pObjectPointerRef = *pValue; + uintptr_t pObjectPointer = reinterpret_cast(pObjectPointerRef); + if (pObjectInteriorPointer < pObjectPointer || pObjectInteriorPointer >= (pObjectPointer + my_get_size(pObjectPointerRef))) + { + _ASSERTE(!"Weak interior pointer has interior pointer which does not point at the object of the handle."); + GCToEEInterface::HandleFatalError(COR_E_EXECUTIONENGINE); + } + } + } } } } diff --git a/src/coreclr/gc/objecthandle.cpp b/src/coreclr/gc/objecthandle.cpp index 1c404c6c23b1..5374229b5b06 100644 --- a/src/coreclr/gc/objecthandle.cpp +++ b/src/coreclr/gc/objecthandle.cpp @@ -145,6 +145,47 @@ void CALLBACK TraceDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pEx } } +void CALLBACK UpdateWeakInteriorHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pExtraInfo, uintptr_t lp1, uintptr_t lp2) +{ + LIMITED_METHOD_CONTRACT; + _ASSERTE(pExtraInfo); + + Object **pPrimaryRef = (Object **)pObjRef; + uintptr_t **ppInteriorPtrRef = (uintptr_t **)pExtraInfo; + + LOG((LF_GC, LL_INFO10000, LOG_HANDLE_OBJECT("Querying for new location of ", + pPrimaryRef, "to ", *pPrimaryRef))); + + Object *pOldPrimary = *pPrimaryRef; + + _ASSERTE(lp2); + promote_func* callback = (promote_func*) lp2; + callback(pPrimaryRef, (ScanContext *)lp1, 0); + + Object *pNewPrimary = *pPrimaryRef; + if (pNewPrimary != NULL) + { + uintptr_t pOldInterior = **ppInteriorPtrRef; + uintptr_t delta = ((uintptr_t)pNewPrimary) - ((uintptr_t)pOldPrimary); + uintptr_t pNewInterior = pOldInterior + delta; + **ppInteriorPtrRef = pNewInterior; +#ifdef _DEBUG + if (pOldPrimary != *pPrimaryRef) + LOG((LF_GC, LL_INFO10000, "Updating " FMT_HANDLE "from" FMT_ADDR "to " FMT_OBJECT "\n", + DBG_ADDR(pPrimaryRef), DBG_ADDR(pOldPrimary), DBG_ADDR(*pPrimaryRef))); + else + LOG((LF_GC, LL_INFO10000, "Updating " FMT_HANDLE "- " FMT_OBJECT "did not move\n", + DBG_ADDR(pPrimaryRef), DBG_ADDR(*pPrimaryRef))); + if (pOldInterior != pNewInterior) + LOG((LF_GC, LL_INFO10000, "Updating " FMT_HANDLE "from" FMT_ADDR "to " FMT_OBJECT "\n", + DBG_ADDR(*ppInteriorPtrRef), DBG_ADDR(pOldInterior), DBG_ADDR(pNewInterior))); + else + LOG((LF_GC, LL_INFO10000, "Updating " FMT_HANDLE "- " FMT_OBJECT "did not move\n", + DBG_ADDR(*ppInteriorPtrRef), DBG_ADDR(pOldInterior))); +#endif + } +} + void CALLBACK UpdateDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pExtraInfo, uintptr_t lp1, uintptr_t lp2) { LIMITED_METHOD_CONTRACT; @@ -427,6 +468,7 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, uintpt break; case HNDTYPE_WEAK_SHORT: case HNDTYPE_WEAK_LONG: + case HNDTYPE_WEAK_INTERIOR_POINTER: #ifdef FEATURE_WEAK_NATIVE_COM_HANDLES case HNDTYPE_WEAK_NATIVE_COM: #endif // FEATURE_WEAK_NATIVE_COM_HANDLES @@ -527,6 +569,7 @@ static const uint32_t s_rgTypeFlags[] = HNDF_NORMAL, // HNDTYPE_ASYNCPINNED HNDF_EXTRAINFO, // HNDTYPE_SIZEDREF HNDF_EXTRAINFO, // HNDTYPE_WEAK_NATIVE_COM + HNDF_EXTRAINFO, // HNDTYPE_WEAK_INTERIOR_POINTER }; int getNumberOfSlots() @@ -1170,6 +1213,7 @@ void Ref_CheckReachable(uint32_t condemned, uint32_t maxgen, ScanContext *sc) #ifdef FEATURE_REFCOUNTED_HANDLES HNDTYPE_REFCOUNTED, #endif + HNDTYPE_WEAK_INTERIOR_POINTER }; // check objects pointed to by short weak handles @@ -1339,6 +1383,40 @@ void Ref_ScanDependentHandlesForClearing(uint32_t condemned, uint32_t maxgen, Sc } } +// Perform a scan of weak interior pointers for the purpose of updating handles to track relocated objects. +void Ref_ScanWeakInteriorPointersForRelocation(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Ref_promote_func* fn) +{ + LOG((LF_GC, LL_INFO10000, "Relocating moved dependent handles in generation %u\n", condemned)); + uint32_t type = HNDTYPE_WEAK_INTERIOR_POINTER; + uint32_t flags = (sc->concurrent) ? HNDGCF_ASYNC : HNDGCF_NORMAL; + flags |= HNDGCF_EXTRAINFO; + + HandleTableMap *walk = &g_HandleTableMap; + while (walk) + { + for (uint32_t i = 0; i < INITIAL_HANDLE_TABLE_ARRAY_SIZE; i ++) + { + if (walk->pBuckets[i] != NULL) + { + int uCPUindex = getSlotNumber(sc); + int uCPUlimit = getNumberOfSlots(); + assert(uCPUlimit > 0); + int uCPUstep = getThreadCount(sc); + HHANDLETABLE* pTable = walk->pBuckets[i]->pTable; + for ( ; uCPUindex < uCPUlimit; uCPUindex += uCPUstep) + { + HHANDLETABLE hTable = pTable[uCPUindex]; + if (hTable) + { + HndScanHandlesForGC(hTable, UpdateWeakInteriorHandle, uintptr_t(sc), uintptr_t(fn), &type, 1, condemned, maxgen, flags ); + } + } + } + } + walk = walk->pNext; + } +} + // Perform a scan of dependent handles for the purpose of updating handles to track relocated objects. void Ref_ScanDependentHandlesForRelocation(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Ref_promote_func* fn) { @@ -1590,6 +1668,7 @@ void Ref_ScanHandlesForProfilerAndETW(uint32_t maxgen, uintptr_t lp1, handle_sca HNDTYPE_ASYNCPINNED, #endif HNDTYPE_SIZEDREF, + HNDTYPE_WEAK_INTERIOR_POINTER }; uint32_t flags = HNDGCF_NORMAL; @@ -1712,6 +1791,7 @@ void Ref_AgeHandles(uint32_t condemned, uint32_t maxgen, ScanContext* sc) HNDTYPE_ASYNCPINNED, #endif HNDTYPE_SIZEDREF, + HNDTYPE_WEAK_INTERIOR_POINTER }; // perform a multi-type scan that ages the handles @@ -1766,6 +1846,7 @@ void Ref_RejuvenateHandles(uint32_t condemned, uint32_t maxgen, ScanContext* sc) HNDTYPE_ASYNCPINNED, #endif HNDTYPE_SIZEDREF, + HNDTYPE_WEAK_INTERIOR_POINTER }; // reset the ages of these handles @@ -1819,6 +1900,7 @@ void Ref_VerifyHandleTable(uint32_t condemned, uint32_t maxgen, ScanContext* sc) #endif HNDTYPE_SIZEDREF, HNDTYPE_DEPENDENT, + HNDTYPE_WEAK_INTERIOR_POINTER }; // verify these handles diff --git a/src/coreclr/gc/objecthandle.h b/src/coreclr/gc/objecthandle.h index d579e8631d6c..634510758c32 100644 --- a/src/coreclr/gc/objecthandle.h +++ b/src/coreclr/gc/objecthandle.h @@ -102,6 +102,7 @@ DhContext *Ref_GetDependentHandleContext(ScanContext* sc); bool Ref_ScanDependentHandlesForPromotion(DhContext *pDhContext); void Ref_ScanDependentHandlesForClearing(uint32_t condemned, uint32_t maxgen, ScanContext* sc); void Ref_ScanDependentHandlesForRelocation(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Ref_promote_func* fn); +void Ref_ScanWeakInteriorPointersForRelocation(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Ref_promote_func* fn); void Ref_ScanSizedRefHandles(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Ref_promote_func* fn); void Ref_CheckReachable (uint32_t uCondemnedGeneration, uint32_t uMaxGeneration, ScanContext* sc); diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 192a4c1216df..6635083a20ba 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -935,34 +935,6 @@ static size_t GetLogicalProcessorCacheSizeFromOS() } #endif -#if (defined(HOST_ARM64) || defined(HOST_LOONGARCH64)) && !defined(TARGET_APPLE) - if (cacheSize == 0) - { - // We expect to get the L3 cache size for Arm64 but currently expected to be missing that info - // from most of the machines. - // - // _SC_LEVEL*_*CACHE_SIZE is not yet present. Work is in progress to enable this for arm64 - // - // /sys/devices/system/cpu/cpu*/cache/index*/ is also not yet present in most systems. - // Arm64 patch is in Linux kernel tip. - // - // midr_el1 is available in "/sys/devices/system/cpu/cpu0/regs/identification/midr_el1", - // but without an exhaustive list of ARM64 processors any decode of midr_el1 - // Would likely be incomplete - - // Published information on ARM64 architectures is limited. - // If we use recent high core count chips as a guide for state of the art, we find - // total L3 cache to be 1-2MB/core. As always, there are exceptions. - - // Estimate cache size based on CPU count - // Assume lower core count are lighter weight parts which are likely to have smaller caches - // Assume L3$/CPU grows linearly from 256K to 1.5M/CPU as logicalCPUs grows from 2 to 12 CPUs - DWORD logicalCPUs = g_processAffinitySet.Count(); - - cacheSize = logicalCPUs * std::min(1536, std::max(256, (int)logicalCPUs * 128)) * 1024; - } -#endif - #if HAVE_SYSCTLBYNAME if (cacheSize == 0) { diff --git a/src/coreclr/gcdump/i386/gcdumpx86.cpp b/src/coreclr/gcdump/i386/gcdumpx86.cpp index c5d359aac517..ba267bd3470c 100644 --- a/src/coreclr/gcdump/i386/gcdumpx86.cpp +++ b/src/coreclr/gcdump/i386/gcdumpx86.cpp @@ -456,10 +456,10 @@ size_t GCDump::DumpGCTable(PTR_CBYTE table, /* non-ptr arg push */ curOffs += (val & 0x07); -#ifndef UNIX_X86_ABI - // For x86/Linux, non-ptr arg pushes can be reported even for EBP frames +#ifndef FEATURE_EH_FUNCLETS + // For funclets, non-ptr arg pushes can be reported even for EBP frames _ASSERTE(!header.ebpFrame); -#endif // UNIX_X86_ABI +#endif // FEATURE_EH_FUNCLETS argCnt++; DumpEncoding(bp, table-bp); bp = table; diff --git a/src/coreclr/gcinfo/gcinfoencoder.cpp b/src/coreclr/gcinfo/gcinfoencoder.cpp index 115f7cdcf253..0abf65047b8d 100644 --- a/src/coreclr/gcinfo/gcinfoencoder.cpp +++ b/src/coreclr/gcinfo/gcinfoencoder.cpp @@ -922,7 +922,11 @@ void GcInfoEncoder::FinalizeSlotIds() #endif } -bool GcInfoEncoder::IsAlwaysScratch(GcSlotDesc &slotDesc) +#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED + +// tells whether a slot cannot contain an object reference +// at call instruction or right after returning +bool GcInfoEncoder::DoNotTrackInPartiallyInterruptible(GcSlotDesc &slotDesc) { #if defined(TARGET_ARM) @@ -933,7 +937,31 @@ bool GcInfoEncoder::IsAlwaysScratch(GcSlotDesc &slotDesc) _ASSERTE(regNum >= 0 && regNum <= 14); _ASSERTE(regNum != 13); // sp - return ((regNum <= 3) || (regNum >= 12)); // R12 and R14/LR are both scratch registers + return ((regNum <= 3) || (regNum >= 12)) // R12 is volatile and SP/LR can't contain objects around calls + && regNum != 0 // R0 can contain return value + ; + } + else if (!slotDesc.IsUntracked() && (slotDesc.Slot.Stack.Base == GC_SP_REL) && + ((UINT32)slotDesc.Slot.Stack.SpOffset < m_SizeOfStackOutgoingAndScratchArea)) + { + return TRUE; + } + else + return FALSE; + +#elif defined(TARGET_ARM64) + + _ASSERTE(m_SizeOfStackOutgoingAndScratchArea != (UINT32)-1); + if (slotDesc.IsRegister()) + { + int regNum = (int)slotDesc.Slot.RegisterNumber; + _ASSERTE(regNum >= 0 && regNum <= 30); + _ASSERTE(regNum != 18); + + return (regNum <= 17 || regNum >= 29) // X0 through X17 are scratch, FP/LR can't be used for objects around calls + && regNum != 0 // X0 can contain return value + && regNum != 1 // X1 can contain return value + ; } else if (!slotDesc.IsUntracked() && (slotDesc.Slot.Stack.Base == GC_SP_REL) && ((UINT32)slotDesc.Slot.Stack.SpOffset < m_SizeOfStackOutgoingAndScratchArea)) @@ -953,7 +981,7 @@ bool GcInfoEncoder::IsAlwaysScratch(GcSlotDesc &slotDesc) _ASSERTE(regNum != 4); // rsp UINT16 PreservedRegMask = - (1 << 3) // rbx + (1 << 3) // rbx | (1 << 5) // rbp #ifndef UNIX_AMD64_ABI | (1 << 6) // rsi @@ -962,7 +990,12 @@ bool GcInfoEncoder::IsAlwaysScratch(GcSlotDesc &slotDesc) | (1 << 12) // r12 | (1 << 13) // r13 | (1 << 14) // r14 - | (1 << 15); // r15 + | (1 << 15) // r15 + | (1 << 0) // rax - may contain return value +#ifdef UNIX_AMD64_ABI + | (1 << 2) // rdx - may contain return value +#endif + ; return !(PreservedRegMask & (1 << regNum)); } @@ -978,6 +1011,7 @@ bool GcInfoEncoder::IsAlwaysScratch(GcSlotDesc &slotDesc) return FALSE; #endif } +#endif // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED void GcInfoEncoder::Build() { @@ -1396,7 +1430,7 @@ void GcInfoEncoder::Build() else { UINT32 slotIndex = pCurrent->SlotId; - if(!IsAlwaysScratch(m_SlotTable[slotIndex])) + if(!DoNotTrackInPartiallyInterruptible(m_SlotTable[slotIndex])) { BYTE becomesLive = pCurrent->BecomesLive; _ASSERTE((liveState.ReadBit(slotIndex) && !becomesLive) diff --git a/src/coreclr/ilasm/README.md b/src/coreclr/ilasm/README.md new file mode 100644 index 000000000000..35f621b6df9a --- /dev/null +++ b/src/coreclr/ilasm/README.md @@ -0,0 +1,18 @@ +# Generating the Parser using Bison + +- Bison for Windows: https://github.com/lexxmark/winflexbison +- Other platforms: https://www.gnu.org/software/bison + +To generate `asmparse.cpp`, run either of following: +- Unix: `yacc asmparse.y -o prebuilt/asmparse.cpp` +- Windows: `win_bison asmparse.y -o prebuilt\asmparse.cpp` + +## Docker +```bash +$ cd runtime + +# run a throw-away-after-exit container with --rm +$ docker run --rm -v$(pwd):/runtime -w /runtime/src/coreclr/ilasm alpine \ + sh -c 'apk add bison && yacc asmparse.y -o prebuilt/asmparse.cpp' +``` + diff --git a/src/coreclr/ilasm/asmparse.h b/src/coreclr/ilasm/asmparse.h index 5300a092b4e2..7376bab5badf 100644 --- a/src/coreclr/ilasm/asmparse.h +++ b/src/coreclr/ilasm/asmparse.h @@ -313,7 +313,7 @@ class AsmParse : public ErrorReporter friend char* skipBlanks(_In_ __nullterminated char*,unsigned*); friend char* nextBlank(_In_ __nullterminated char*); friend int ProcessEOF(); - friend unsigned __int8* skipType(unsigned __int8* ptr, BOOL fFixupType); + friend uint8_t* skipType(uint8_t* ptr, BOOL fFixupType); friend void FixupConstraints(); Assembler* assem; // This does most of the semantic processing diff --git a/src/coreclr/ilasm/asmparse.y b/src/coreclr/ilasm/asmparse.y index c9861d58d797..2257ecb31af7 100644 --- a/src/coreclr/ilasm/asmparse.y +++ b/src/coreclr/ilasm/asmparse.y @@ -27,8 +27,8 @@ CorTypeAttr exptAttr; CorManifestResourceFlags manresAttr; double* float64; - __int64* int64; - __int32 int32; + int64_t* int64; + int32_t int32; char* string; BinStr* binstr; Labels* labels; @@ -42,13 +42,13 @@ }; /* These are returned by the LEXER and have values */ -%token ERROR_ BAD_COMMENT_ BAD_LITERAL_ /* bad strings, */ +%token BAD_COMMENT_ BAD_LITERAL_ /* bad strings, */ %token ID /* testing343 */ %token DOTTEDNAME /* System.Object */ %token QSTRING /* "Hello World\n" */ %token SQSTRING /* 'Hello World\n' */ -%token INT32 /* 3425 0x34FA 0352 */ -%token INT64 /* 342534523534534 0x34FA434644554 */ +%token INT32_V /* 3425 0x34FA 0352 */ +%token INT64_V /* 342534523534534 0x34FA434644554 */ %token FLOAT64 /* -334234 24E-34 */ %token HEXBYTE /* 05 1A FA */ %token TYPEDEF_T @@ -96,7 +96,7 @@ %token _CLASS _NAMESPACE _METHOD _FIELD _DATA _THIS _BASE _NESTER %token _EMITBYTE _TRY _MAXSTACK _LOCALS _ENTRYPOINT _ZEROINIT %token _EVENT _ADDON _REMOVEON _FIRE _OTHER -%token _PROPERTY _SET _GET DEFAULT_ +%token _PROPERTY _SET _GET %token _PERMISSION _PERMISSIONSET /* security actions */ @@ -259,15 +259,15 @@ dottedName : id { $$ = $1; } | dottedName '.' dottedName { $$ = newStringWDel($1, '.', $3); } ; -int32 : INT32 { $$ = $1; } +int32 : INT32_V { $$ = $1; } ; -int64 : INT64 { $$ = $1; } - | INT32 { $$ = neg ? new __int64($1) : new __int64((unsigned)$1); } +int64 : INT64_V { $$ = $1; } + | INT32_V { $$ = neg ? new int64_t($1) : new int64_t((unsigned)$1); } ; float64 : FLOAT64 { $$ = $1; } - | FLOAT32_ '(' int32 ')' { float f; *((__int32*) (&f)) = $3; $$ = new double(f); } + | FLOAT32_ '(' int32 ')' { float f; *((int32_t*) (&f)) = $3; $$ = new double(f); } | FLOAT64_ '(' int64 ')' { $$ = (double*) $3; } ; @@ -693,7 +693,7 @@ memberRef : methodSpec methodRef { $$ = $2; PASM->SetMemberRefFixup($$,iOpcodeLen); } | FIELD_ type dottedName { $2->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); - $$ = PASM->MakeMemberRef(NULL, $3, $2); + $$ = PASM->MakeMemberRef(mdTokenNil, $3, $2); PASM->SetMemberRefFixup($$,iOpcodeLen); } | FIELD_ TYPEDEF_F { $$ = $2->m_tkTypeSpec; PASM->SetMemberRefFixup($$,iOpcodeLen); } @@ -916,13 +916,13 @@ methodDecl : _EMITBYTE int32 { PASM->EmitByte($2) | _VTENTRY int32 ':' int32 { PASM->m_pCurMethod->m_wVTEntry = (WORD)$2; PASM->m_pCurMethod->m_wVTSlot = (WORD)$4; } | _OVERRIDE typeSpec DCOLON methodName - { PASM->AddMethodImpl($2,$4,NULL,NULL,NULL,NULL); } + { PASM->AddMethodImpl($2,$4,NULL,mdTokenNil,NULL,NULL); } | _OVERRIDE METHOD_ callConv type typeSpec DCOLON methodName genArity '(' sigArgs0 ')' { PASM->AddMethodImpl($5,$7, ($8==0 ? parser->MakeSig($3,$4,$10) : parser->MakeSig($3| IMAGE_CEE_CS_CALLCONV_GENERIC,$4,$10,$8)) - ,NULL,NULL,NULL); + ,mdTokenNil,NULL,NULL); PASM->ResetArgNameList(); } | scopeBlock @@ -1068,55 +1068,55 @@ ddItem : CHAR_ '*' '(' compQstring ')' { PASM->EmitDataStr } else PASM->report->error("Out of memory emitting data block %d bytes\n", sizeof(double)*$5); } | INT64_ '(' int64 ')' ddItemCount - { __int64* p = new (nothrow) __int64[$5]; + { int64_t* p = new (nothrow) int64_t[$5]; if(p != NULL) { for(int i=0; i<$5; i++) p[i] = *($3); - PASM->EmitData(p, sizeof(__int64)*$5); delete $3; delete [] p; + PASM->EmitData(p, sizeof(int64_t)*$5); delete $3; delete [] p; } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(__int64)*$5); } + sizeof(int64_t)*$5); } | INT32_ '(' int32 ')' ddItemCount - { __int32* p = new (nothrow) __int32[$5]; + { int32_t* p = new (nothrow) int32_t[$5]; if(p != NULL) { for(int i=0; i<$5; i++) p[i] = $3; - PASM->EmitData(p, sizeof(__int32)*$5); delete [] p; + PASM->EmitData(p, sizeof(int32_t)*$5); delete [] p; } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(__int32)*$5); } + sizeof(int32_t)*$5); } | INT16_ '(' int32 ')' ddItemCount - { __int16 i = (__int16) $3; FAIL_UNLESS(i == $3, ("Value %d too big\n", $3)); - __int16* p = new (nothrow) __int16[$5]; + { int16_t i = (int16_t) $3; FAIL_UNLESS(i == $3, ("Value %d too big\n", $3)); + int16_t* p = new (nothrow) int16_t[$5]; if(p != NULL) { for(int j=0; j<$5; j++) p[j] = i; - PASM->EmitData(p, sizeof(__int16)*$5); delete [] p; + PASM->EmitData(p, sizeof(int16_t)*$5); delete [] p; } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(__int16)*$5); } + sizeof(int16_t)*$5); } | INT8_ '(' int32 ')' ddItemCount - { __int8 i = (__int8) $3; FAIL_UNLESS(i == $3, ("Value %d too big\n", $3)); - __int8* p = new (nothrow) __int8[$5]; + { int8_t i = (int8_t) $3; FAIL_UNLESS(i == $3, ("Value %d too big\n", $3)); + int8_t* p = new (nothrow) int8_t[$5]; if(p != NULL) { for(int j=0; j<$5; j++) p[j] = i; - PASM->EmitData(p, sizeof(__int8)*$5); delete [] p; + PASM->EmitData(p, sizeof(int8_t)*$5); delete [] p; } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(__int8)*$5); } + sizeof(int8_t)*$5); } | FLOAT32_ ddItemCount { PASM->EmitData(NULL, sizeof(float)*$2); } | FLOAT64_ ddItemCount { PASM->EmitData(NULL, sizeof(double)*$2); } - | INT64_ ddItemCount { PASM->EmitData(NULL, sizeof(__int64)*$2); } - | INT32_ ddItemCount { PASM->EmitData(NULL, sizeof(__int32)*$2); } - | INT16_ ddItemCount { PASM->EmitData(NULL, sizeof(__int16)*$2); } - | INT8_ ddItemCount { PASM->EmitData(NULL, sizeof(__int8)*$2); } + | INT64_ ddItemCount { PASM->EmitData(NULL, sizeof(int64_t)*$2); } + | INT32_ ddItemCount { PASM->EmitData(NULL, sizeof(int32_t)*$2); } + | INT16_ ddItemCount { PASM->EmitData(NULL, sizeof(int16_t)*$2); } + | INT8_ ddItemCount { PASM->EmitData(NULL, sizeof(int8_t)*$2); } ; /* Default values declaration for fields, parameters and verbal form of CA blob description */ fieldSerInit : FLOAT32_ '(' float64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R4); float f = (float)(*$3); - $$->appendInt32(*((__int32*)&f)); delete $3; } + $$->appendInt32(*((int32_t*)&f)); delete $3; } | FLOAT64_ '(' float64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R8); - $$->appendInt64((__int64 *)$3); delete $3; } + $$->appendInt64((int64_t *)$3); delete $3; } | FLOAT32_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R4); $$->appendInt32($3); } | FLOAT64_ '(' int64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_R8); - $$->appendInt64((__int64 *)$3); delete $3; } + $$->appendInt64((int64_t *)$3); delete $3; } | INT64_ '(' int64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I8); - $$->appendInt64((__int64 *)$3); delete $3; } + $$->appendInt64((int64_t *)$3); delete $3; } | INT32_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I4); $$->appendInt32($3); } | INT16_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I2); @@ -1124,7 +1124,7 @@ fieldSerInit : FLOAT32_ '(' float64 ')' { $$ = new BinStr() | INT8_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_I1); $$->appendInt8($3); } | UNSIGNED_ INT64_ '(' int64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U8); - $$->appendInt64((__int64 *)$4); delete $4; } + $$->appendInt64((int64_t *)$4); delete $4; } | UNSIGNED_ INT32_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U4); $$->appendInt32($4); } | UNSIGNED_ INT16_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U2); @@ -1132,7 +1132,7 @@ fieldSerInit : FLOAT32_ '(' float64 ')' { $$ = new BinStr() | UNSIGNED_ INT8_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U1); $$->appendInt8($4); } | UINT64_ '(' int64 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U8); - $$->appendInt64((__int64 *)$3); delete $3; } + $$->appendInt64((int64_t *)$3); delete $3; } | UINT32_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U4); $$->appendInt32($3); } | UINT16_ '(' int32 ')' { $$ = new BinStr(); $$->appendInt8(ELEMENT_TYPE_U2); @@ -1154,8 +1154,8 @@ bytes : /* EMPTY */ { $$ = new BinStr() | hexbytes { $$ = $1; } ; -hexbytes : HEXBYTE { __int8 i = (__int8) $1; $$ = new BinStr(); $$->appendInt8(i); } - | hexbytes HEXBYTE { __int8 i = (__int8) $2; $$ = $1; $$->appendInt8(i); } +hexbytes : HEXBYTE { int8_t i = (int8_t) $1; $$ = new BinStr(); $$->appendInt8(i); } + | hexbytes HEXBYTE { int8_t i = (int8_t) $2; $$ = $1; $$->appendInt8(i); } ; /* Field/parameter initialization */ @@ -1257,21 +1257,21 @@ serInit : fieldSerInit { $$ = $1; } f32seq : /* EMPTY */ { $$ = new BinStr(); } | f32seq float64 { $$ = $1; - float f = (float) (*$2); $$->appendInt32(*((__int32*)&f)); delete $2; } + float f = (float) (*$2); $$->appendInt32(*((int32_t*)&f)); delete $2; } | f32seq int32 { $$ = $1; $$->appendInt32($2); } ; f64seq : /* EMPTY */ { $$ = new BinStr(); } | f64seq float64 { $$ = $1; - $$->appendInt64((__int64 *)$2); delete $2; } + $$->appendInt64((int64_t *)$2); delete $2; } | f64seq int64 { $$ = $1; - $$->appendInt64((__int64 *)$2); delete $2; } + $$->appendInt64((int64_t *)$2); delete $2; } ; i64seq : /* EMPTY */ { $$ = new BinStr(); } | i64seq int64 { $$ = $1; - $$->appendInt64((__int64 *)$2); delete $2; } + $$->appendInt64((int64_t *)$2); delete $2; } ; i32seq : /* EMPTY */ { $$ = new BinStr(); } diff --git a/src/coreclr/ilasm/assembler.cpp b/src/coreclr/ilasm/assembler.cpp index 1a8cef9abcaf..e105c00162c5 100644 --- a/src/coreclr/ilasm/assembler.cpp +++ b/src/coreclr/ilasm/assembler.cpp @@ -146,7 +146,7 @@ class TypeSpecContainer { private: // Contain a BinStr - unsigned __int8 *ptr_; + uint8_t *ptr_; unsigned len_; // Hash the BinStr, just for speed of lookup unsigned hash_; @@ -166,7 +166,7 @@ class TypeSpecContainer // Constructor for a 'permanent' object // Don't bother re-hashing, since we will always have already constructed the lookup object TypeSpecContainer(const TypeSpecContainer &t, mdToken tk) : - ptr_(new unsigned __int8[t.len_]), + ptr_(new uint8_t[t.len_]), len_(t.len_), hash_(t.hash_), token_(tk) @@ -523,7 +523,7 @@ void Assembler::AddClass() m_pCurClass->m_Attr = attr; m_pCurClass->m_crExtends = (m_pCurClass->m_cl == m_tkSysObject)? mdTypeRefNil : crExtends; - if ((m_pCurClass->m_dwNumInterfaces = m_nImplList) != NULL) + if ((m_pCurClass->m_dwNumInterfaces = m_nImplList) != 0) { if(bIsEnum) report->error("Enum implementing interface(s)\n"); if((m_pCurClass->m_crImplements = new mdTypeRef[m_nImplList+1]) != NULL) @@ -1284,7 +1284,7 @@ void Assembler::EmitDD(_In_ __nullterminated char *str) _ASSERTE(SUCCEEDED(hr)); DWORD* ptr; - DWORD sizeofptr = (DWORD)((m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32) ? sizeof(DWORD) : sizeof(__int64)); + DWORD sizeofptr = (DWORD)((m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32) ? sizeof(DWORD) : sizeof(int64_t)); hr = m_pCeeFileGen->GetSectionBlock(m_pCurSection, sizeofptr, 1, (void**) &ptr); if (FAILED(hr)) { @@ -1318,7 +1318,7 @@ void Assembler::EmitDD(_In_ __nullterminated char *str) else { m_dwComImageFlags &= ~COMIMAGE_FLAGS_ILONLY; - *((__int64*)ptr) = (__int64)dwAddr; + *((int64_t*)ptr) = (int64_t)dwAddr; } } @@ -1654,10 +1654,10 @@ void Assembler::EmitInstrI(Instr* instr, int val) } /**************************************************************************/ -void Assembler::EmitInstrI8(Instr* instr, __int64* val) +void Assembler::EmitInstrI8(Instr* instr, int64_t* val) { EmitOpcode(instr); - EmitBytes((BYTE *)val, sizeof(__int64)); + EmitBytes((BYTE *)val, sizeof(int64_t)); delete val; } @@ -2005,7 +2005,7 @@ void Assembler::SetPropMethod(int MethodCode, mdToken tk) void Assembler::EmitInstrStringLiteral(Instr* instr, BinStr* literal, BOOL ConvertToUnicode, BOOL Swap /*=FALSE*/) { DWORD DataLen = literal->length(),L; - unsigned __int8 *pb = literal->ptr(); + uint8_t *pb = literal->ptr(); HRESULT hr = S_OK; mdToken tk; WCHAR *UnicodeString; @@ -2431,7 +2431,7 @@ HRESULT Assembler::SavePdbFile() if (FAILED(hr = (m_pPortablePdbWriter->GetEmitter() == NULL ? E_FAIL : S_OK))) goto exit; if (FAILED(hr = m_pCeeFileGen->GetEntryPoint(m_pCeeFile, &entryPoint))) goto exit; if (FAILED(hr = m_pPortablePdbWriter->BuildPdbStream(m_pEmitter, entryPoint))) goto exit; - if (FAILED(hr = m_pPortablePdbWriter->GetEmitter()->Save(m_wzPdbFileName, NULL))) goto exit; + if (FAILED(hr = m_pPortablePdbWriter->GetEmitter()->Save(m_wzPdbFileName, 0))) goto exit; exit: return hr; diff --git a/src/coreclr/ilasm/assembler.h b/src/coreclr/ilasm/assembler.h index b80ef9a16d3c..facdfc8c02fc 100644 --- a/src/coreclr/ilasm/assembler.h +++ b/src/coreclr/ilasm/assembler.h @@ -538,7 +538,7 @@ class PermissionDecl *pBlob++ = pVal[1]; break; case SERIALIZATION_TYPE_I4: - *(__int32*)pBlob = *(__int32*)&pVal[1]; + *(int32_t*)pBlob = *(int32_t*)&pVal[1]; pBlob += 4; break; case SERIALIZATION_TYPE_STRING: @@ -552,15 +552,15 @@ class PermissionDecl // We can have enums with base type of I1, I2 and I4. switch (pVal[1 + length + 1]) { case 1: - *(__int8*)pBlob = *(__int8*)&pVal[1 + length + 2]; + *(int8_t*)pBlob = *(int8_t*)&pVal[1 + length + 2]; pBlob += 1; break; case 2: - *(__int16*)pBlob = *(__int16*)&pVal[1 + length + 2]; + *(int16_t*)pBlob = *(int16_t*)&pVal[1 + length + 2]; pBlob += 2; break; case 4: - *(__int32*)pBlob = *(__int32*)&pVal[1 + length + 2]; + *(int32_t*)pBlob = *(int32_t*)&pVal[1 + length + 2]; pBlob += 4; break; default: @@ -901,7 +901,7 @@ class Assembler { void EmitInstrVar(Instr* instr, int var); void EmitInstrVarByName(Instr* instr, _In_ __nullterminated char* label); void EmitInstrI(Instr* instr, int val); - void EmitInstrI8(Instr* instr, __int64* val); + void EmitInstrI8(Instr* instr, int64_t* val); void EmitInstrR(Instr* instr, double* val); void EmitInstrBrOffset(Instr* instr, int offset); void EmitInstrBrTarget(Instr* instr, _In_ __nullterminated char* label); diff --git a/src/coreclr/ilasm/binstr.h b/src/coreclr/ilasm/binstr.h index f22a5e218877..013e35cb2889 100644 --- a/src/coreclr/ilasm/binstr.h +++ b/src/coreclr/ilasm/binstr.h @@ -24,11 +24,11 @@ class BinStr { void appendInt8(int val) { if (len >= max) Realloc(); ptr_[len++] = (uint8_t)val; } void appendInt16(int val) { if (len + 2 > max) Realloc(); SET_UNALIGNED_16(&ptr_[len], val); len += 2; } void appendInt32(int val) { if (len + 4 > max) Realloc(); SET_UNALIGNED_32(&ptr_[len], val); len += 4; } - void appendInt64(__int64 *pval) { if (len + 8 > max) Realloc(8); SET_UNALIGNED_64(&ptr_[len],(*pval)); len += 8; } - unsigned __int8* getBuff(unsigned size) { + void appendInt64(int64_t *pval) { if (len + 8 > max) Realloc(8); SET_UNALIGNED_64(&ptr_[len],(*pval)); len += 8; } + uint8_t* getBuff(unsigned size) { if (len + size > max) Realloc(size); _ASSERTE(len + size <= max); - unsigned __int8* ret = &ptr_[len]; + uint8_t* ret = &ptr_[len]; len += size; return(ret); } @@ -46,7 +46,7 @@ class BinStr { void remove(unsigned size) { _ASSERTE(len >= size); len -= size; } - unsigned __int8* ptr() { return(ptr_); } + uint8_t* ptr() { return(ptr_); } unsigned length() { return(len); } private: @@ -55,7 +55,7 @@ class BinStr { if (max < atLeast + len) max = atLeast + len; _ASSERTE(max >= len + atLeast); - unsigned __int8* newPtr = new unsigned __int8[max]; + uint8_t* newPtr = new uint8_t[max]; memcpy(newPtr, ptr_, len); if (ptr_ != buff) delete [] ptr_; ptr_ = newPtr; @@ -64,8 +64,8 @@ class BinStr { private: unsigned len; unsigned max; - unsigned __int8 *ptr_; - unsigned __int8 buff[8]; + uint8_t *ptr_; + uint8_t buff[8]; }; BinStr* BinStrToUnicode(BinStr* pSource, bool Swap = false); #ifdef _PREFAST_ diff --git a/src/coreclr/ilasm/grammar_after.cpp b/src/coreclr/ilasm/grammar_after.cpp index 45591afc9c57..9f7f37a59ea2 100644 --- a/src/coreclr/ilasm/grammar_after.cpp +++ b/src/coreclr/ilasm/grammar_after.cpp @@ -339,9 +339,9 @@ void Init_str2uint64() for(i='A'; i <= 'Z'; i++) digits[i] = i + 10 - 'A'; for(i='a'; i <= 'z'; i++) digits[i] = i + 10 - 'a'; } -static unsigned __int64 str2uint64(const char* str, const char** endStr, unsigned radix) +static uint64_t str2uint64(const char* str, const char** endStr, unsigned radix) { - unsigned __int64 ret = 0; + uint64_t ret = 0; unsigned digit,ix; _ASSERTE(radix <= 36); for(;;str = nextchar((char*)str)) @@ -1203,19 +1203,19 @@ int yylex() } begNum = curPos; { - unsigned __int64 i64 = str2uint64(begNum, const_cast(&curPos), radix); - unsigned __int64 mask64 = neg ? UI64(0xFFFFFFFF80000000) : UI64(0xFFFFFFFF00000000); - unsigned __int64 largestNegVal32 = UI64(0x0000000080000000); + uint64_t i64 = str2uint64(begNum, const_cast(&curPos), radix); + uint64_t mask64 = neg ? UI64(0xFFFFFFFF80000000) : UI64(0xFFFFFFFF00000000); + uint64_t largestNegVal32 = UI64(0x0000000080000000); if ((i64 & mask64) && (i64 != largestNegVal32)) { - yylval.int64 = new __int64(i64); - tok = INT64; + yylval.int64 = new int64_t(i64); + tok = INT64_V; if (neg) *yylval.int64 = -*yylval.int64; } else { - yylval.int32 = (__int32)i64; - tok = INT32; + yylval.int32 = (int32_t)i64; + tok = INT32_V; if(neg) yylval.int32 = -yylval.int32; } } @@ -1280,7 +1280,7 @@ int yylex() } dbprintf((" Line %d token %d (%c) val = %s\n", PENV->curLine, tok, (tok < 128 && isprint(tok)) ? tok : ' ', - (tok > 255 && tok != INT32 && tok != INT64 && tok!= FLOAT64) ? yylval.string : "")); + (tok > 255 && tok != INT32_V && tok != INT64_V && tok!= FLOAT64) ? yylval.string : "")); PENV->curPos = curPos; PENV->curTok = curTok; @@ -1333,7 +1333,7 @@ static void corEmitInt(BinStr* buff, unsigned data) /**************************************************************************/ /* move 'ptr past the exactly one type description */ -unsigned __int8* skipType(unsigned __int8* ptr, BOOL fFixupType) +uint8_t* skipType(uint8_t* ptr, BOOL fFixupType) { mdToken tk; AGAIN: @@ -1412,7 +1412,7 @@ unsigned __int8* skipType(unsigned __int8* ptr, BOOL fFixupType) if(fFixupType) { BYTE* pb = ptr-1; // ptr incremented in switch - unsigned __int8* ptr_save = ptr; + uint8_t* ptr_save = ptr; int n = CorSigUncompressData((PCCOR_SIGNATURE&) ptr); // fixup # int compressed_size_n = (int)(ptr - ptr_save); // ptr was updated by CorSigUncompressData() int m = -1; @@ -1472,7 +1472,7 @@ unsigned __int8* skipType(unsigned __int8* ptr, BOOL fFixupType) if ((compressed_size_m == 1) && (compressed_size_n == 2)) { - unsigned __int8 m1 = *(pb + 1); + uint8_t m1 = *(pb + 1); _ASSERTE(m1 < 0x80); *(pb + 1) = 0x80; *(pb + 2) = m1; @@ -1481,7 +1481,7 @@ unsigned __int8* skipType(unsigned __int8* ptr, BOOL fFixupType) if ((compressed_size_m == 1) && (compressed_size_n == 4)) { - unsigned __int8 m1 = *(pb + 1); + uint8_t m1 = *(pb + 1); _ASSERTE(m1 < 0x80); *(pb + 1) = 0xC0; *(pb + 2) = 0x00; @@ -1492,8 +1492,8 @@ unsigned __int8* skipType(unsigned __int8* ptr, BOOL fFixupType) if ((compressed_size_m == 2) && (compressed_size_n == 4)) { - unsigned __int8 m1 = *(pb + 1); - unsigned __int8 m2 = *(pb + 2); + uint8_t m1 = *(pb + 1); + uint8_t m2 = *(pb + 2); _ASSERTE(m1 >= 0x80); m1 &= 0x7f; // strip the bit indicating it's a 2-byte thing *(pb + 1) = 0xC0; @@ -1559,8 +1559,8 @@ void FixupTyPars(BinStr* pbstype) /**************************************************************************/ static unsigned corCountArgs(BinStr* args) { - unsigned __int8* ptr = args->ptr(); - unsigned __int8* end = &args->ptr()[args->length()]; + uint8_t* ptr = args->ptr(); + uint8_t* end = &args->ptr()[args->length()]; unsigned ret = 0; while(ptr < end) { diff --git a/src/coreclr/ilasm/grammar_before.cpp b/src/coreclr/ilasm/grammar_before.cpp index b49a382f7d89..04286fa137fb 100644 --- a/src/coreclr/ilasm/grammar_before.cpp +++ b/src/coreclr/ilasm/grammar_before.cpp @@ -51,6 +51,10 @@ static char* newString(_In_ __nullterminated const char* str1); static void corEmitInt(BinStr* buff, unsigned data); static void AppendStringWithLength(BinStr* pbs, _In_ __nullterminated char* sz); static void AppendFieldToCustomBlob(BinStr* pBlob, _In_ BinStr* pField); +static unsigned corCountArgs(BinStr* args); +Instr* SetupInstr(unsigned short); +void yyerror(_In_ __nullterminated const char*); +int yylex(); bool bParsingByteArray = FALSE; int iOpcodeLen = 0; int iCallConv = 0; diff --git a/src/coreclr/ilasm/main.cpp b/src/coreclr/ilasm/main.cpp index 0fe683838d89..ebb63e3434fe 100644 --- a/src/coreclr/ilasm/main.cpp +++ b/src/coreclr/ilasm/main.cpp @@ -151,11 +151,6 @@ extern "C" int _cdecl wmain(int argc, _In_ WCHAR **argv) memset(wzOutputFilename,0,sizeof(wzOutputFilename)); memset(wzPdbFilename, 0, sizeof(wzPdbFilename)); -#ifdef _DEBUG - DisableThrowCheck(); - //CONTRACT_VIOLATION(ThrowsViolation); -#endif - if(argc < 2) goto ErrorExit; #ifdef _PREFAST_ #pragma warning(push) diff --git a/src/coreclr/ilasm/prebuilt/asmparse.cpp b/src/coreclr/ilasm/prebuilt/asmparse.cpp index 08f686f29018..4a5d9b3486b8 100644 --- a/src/coreclr/ilasm/prebuilt/asmparse.cpp +++ b/src/coreclr/ilasm/prebuilt/asmparse.cpp @@ -1,8 +1,74 @@ -/* - * Created by Microsoft VCBU Internal YACC from "asmparse.y" - */ +/* A Bison parser, made by GNU Bison 3.8.2. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output, and Bison version. */ +#define YYBISON 30802 + +/* Bison version string. */ +#define YYBISON_VERSION "3.8.2" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + + + +/* First part of user prologue. */ +#line 1 "asmparse.y" -#line 2 "asmparse.y" // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. @@ -15,10 +81,343 @@ #include "grammar_before.cpp" +#line 85 "asmparse.cpp" + +# ifndef YY_CAST +# ifdef __cplusplus +# define YY_CAST(Type, Val) static_cast (Val) +# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) +# else +# define YY_CAST(Type, Val) ((Type) (Val)) +# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) +# endif +# endif +# ifndef YY_NULLPTR +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# else +# define YY_NULLPTR ((void*)0) +# endif +# endif + + +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token kinds. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + YYEMPTY = -2, + YYEOF = 0, /* "end of file" */ + YYerror = 256, /* error */ + YYUNDEF = 257, /* "invalid token" */ + BAD_COMMENT_ = 258, /* BAD_COMMENT_ */ + BAD_LITERAL_ = 259, /* BAD_LITERAL_ */ + ID = 260, /* ID */ + DOTTEDNAME = 261, /* DOTTEDNAME */ + QSTRING = 262, /* QSTRING */ + SQSTRING = 263, /* SQSTRING */ + INT32_V = 264, /* INT32_V */ + INT64_V = 265, /* INT64_V */ + FLOAT64 = 266, /* FLOAT64 */ + HEXBYTE = 267, /* HEXBYTE */ + TYPEDEF_T = 268, /* TYPEDEF_T */ + TYPEDEF_M = 269, /* TYPEDEF_M */ + TYPEDEF_F = 270, /* TYPEDEF_F */ + TYPEDEF_TS = 271, /* TYPEDEF_TS */ + TYPEDEF_MR = 272, /* TYPEDEF_MR */ + TYPEDEF_CA = 273, /* TYPEDEF_CA */ + DCOLON = 274, /* DCOLON */ + ELLIPSIS = 275, /* ELLIPSIS */ + VOID_ = 276, /* VOID_ */ + BOOL_ = 277, /* BOOL_ */ + CHAR_ = 278, /* CHAR_ */ + UNSIGNED_ = 279, /* UNSIGNED_ */ + INT_ = 280, /* INT_ */ + INT8_ = 281, /* INT8_ */ + INT16_ = 282, /* INT16_ */ + INT32_ = 283, /* INT32_ */ + INT64_ = 284, /* INT64_ */ + FLOAT_ = 285, /* FLOAT_ */ + FLOAT32_ = 286, /* FLOAT32_ */ + FLOAT64_ = 287, /* FLOAT64_ */ + BYTEARRAY_ = 288, /* BYTEARRAY_ */ + UINT_ = 289, /* UINT_ */ + UINT8_ = 290, /* UINT8_ */ + UINT16_ = 291, /* UINT16_ */ + UINT32_ = 292, /* UINT32_ */ + UINT64_ = 293, /* UINT64_ */ + FLAGS_ = 294, /* FLAGS_ */ + CALLCONV_ = 295, /* CALLCONV_ */ + MDTOKEN_ = 296, /* MDTOKEN_ */ + OBJECT_ = 297, /* OBJECT_ */ + STRING_ = 298, /* STRING_ */ + NULLREF_ = 299, /* NULLREF_ */ + DEFAULT_ = 300, /* DEFAULT_ */ + CDECL_ = 301, /* CDECL_ */ + VARARG_ = 302, /* VARARG_ */ + STDCALL_ = 303, /* STDCALL_ */ + THISCALL_ = 304, /* THISCALL_ */ + FASTCALL_ = 305, /* FASTCALL_ */ + CLASS_ = 306, /* CLASS_ */ + BYREFLIKE_ = 307, /* BYREFLIKE_ */ + TYPEDREF_ = 308, /* TYPEDREF_ */ + UNMANAGED_ = 309, /* UNMANAGED_ */ + FINALLY_ = 310, /* FINALLY_ */ + HANDLER_ = 311, /* HANDLER_ */ + CATCH_ = 312, /* CATCH_ */ + FILTER_ = 313, /* FILTER_ */ + FAULT_ = 314, /* FAULT_ */ + EXTENDS_ = 315, /* EXTENDS_ */ + IMPLEMENTS_ = 316, /* IMPLEMENTS_ */ + TO_ = 317, /* TO_ */ + AT_ = 318, /* AT_ */ + TLS_ = 319, /* TLS_ */ + TRUE_ = 320, /* TRUE_ */ + FALSE_ = 321, /* FALSE_ */ + _INTERFACEIMPL = 322, /* _INTERFACEIMPL */ + VALUE_ = 323, /* VALUE_ */ + VALUETYPE_ = 324, /* VALUETYPE_ */ + NATIVE_ = 325, /* NATIVE_ */ + INSTANCE_ = 326, /* INSTANCE_ */ + SPECIALNAME_ = 327, /* SPECIALNAME_ */ + FORWARDER_ = 328, /* FORWARDER_ */ + STATIC_ = 329, /* STATIC_ */ + PUBLIC_ = 330, /* PUBLIC_ */ + PRIVATE_ = 331, /* PRIVATE_ */ + FAMILY_ = 332, /* FAMILY_ */ + FINAL_ = 333, /* FINAL_ */ + SYNCHRONIZED_ = 334, /* SYNCHRONIZED_ */ + INTERFACE_ = 335, /* INTERFACE_ */ + SEALED_ = 336, /* SEALED_ */ + NESTED_ = 337, /* NESTED_ */ + ABSTRACT_ = 338, /* ABSTRACT_ */ + AUTO_ = 339, /* AUTO_ */ + SEQUENTIAL_ = 340, /* SEQUENTIAL_ */ + EXPLICIT_ = 341, /* EXPLICIT_ */ + ANSI_ = 342, /* ANSI_ */ + UNICODE_ = 343, /* UNICODE_ */ + AUTOCHAR_ = 344, /* AUTOCHAR_ */ + IMPORT_ = 345, /* IMPORT_ */ + ENUM_ = 346, /* ENUM_ */ + VIRTUAL_ = 347, /* VIRTUAL_ */ + NOINLINING_ = 348, /* NOINLINING_ */ + AGGRESSIVEINLINING_ = 349, /* AGGRESSIVEINLINING_ */ + NOOPTIMIZATION_ = 350, /* NOOPTIMIZATION_ */ + AGGRESSIVEOPTIMIZATION_ = 351, /* AGGRESSIVEOPTIMIZATION_ */ + UNMANAGEDEXP_ = 352, /* UNMANAGEDEXP_ */ + BEFOREFIELDINIT_ = 353, /* BEFOREFIELDINIT_ */ + STRICT_ = 354, /* STRICT_ */ + RETARGETABLE_ = 355, /* RETARGETABLE_ */ + WINDOWSRUNTIME_ = 356, /* WINDOWSRUNTIME_ */ + NOPLATFORM_ = 357, /* NOPLATFORM_ */ + METHOD_ = 358, /* METHOD_ */ + FIELD_ = 359, /* FIELD_ */ + PINNED_ = 360, /* PINNED_ */ + MODREQ_ = 361, /* MODREQ_ */ + MODOPT_ = 362, /* MODOPT_ */ + SERIALIZABLE_ = 363, /* SERIALIZABLE_ */ + PROPERTY_ = 364, /* PROPERTY_ */ + TYPE_ = 365, /* TYPE_ */ + ASSEMBLY_ = 366, /* ASSEMBLY_ */ + FAMANDASSEM_ = 367, /* FAMANDASSEM_ */ + FAMORASSEM_ = 368, /* FAMORASSEM_ */ + PRIVATESCOPE_ = 369, /* PRIVATESCOPE_ */ + HIDEBYSIG_ = 370, /* HIDEBYSIG_ */ + NEWSLOT_ = 371, /* NEWSLOT_ */ + RTSPECIALNAME_ = 372, /* RTSPECIALNAME_ */ + PINVOKEIMPL_ = 373, /* PINVOKEIMPL_ */ + _CTOR = 374, /* _CTOR */ + _CCTOR = 375, /* _CCTOR */ + LITERAL_ = 376, /* LITERAL_ */ + NOTSERIALIZED_ = 377, /* NOTSERIALIZED_ */ + INITONLY_ = 378, /* INITONLY_ */ + REQSECOBJ_ = 379, /* REQSECOBJ_ */ + CIL_ = 380, /* CIL_ */ + OPTIL_ = 381, /* OPTIL_ */ + MANAGED_ = 382, /* MANAGED_ */ + FORWARDREF_ = 383, /* FORWARDREF_ */ + PRESERVESIG_ = 384, /* PRESERVESIG_ */ + RUNTIME_ = 385, /* RUNTIME_ */ + INTERNALCALL_ = 386, /* INTERNALCALL_ */ + _IMPORT = 387, /* _IMPORT */ + NOMANGLE_ = 388, /* NOMANGLE_ */ + LASTERR_ = 389, /* LASTERR_ */ + WINAPI_ = 390, /* WINAPI_ */ + AS_ = 391, /* AS_ */ + BESTFIT_ = 392, /* BESTFIT_ */ + ON_ = 393, /* ON_ */ + OFF_ = 394, /* OFF_ */ + CHARMAPERROR_ = 395, /* CHARMAPERROR_ */ + INSTR_NONE = 396, /* INSTR_NONE */ + INSTR_VAR = 397, /* INSTR_VAR */ + INSTR_I = 398, /* INSTR_I */ + INSTR_I8 = 399, /* INSTR_I8 */ + INSTR_R = 400, /* INSTR_R */ + INSTR_BRTARGET = 401, /* INSTR_BRTARGET */ + INSTR_METHOD = 402, /* INSTR_METHOD */ + INSTR_FIELD = 403, /* INSTR_FIELD */ + INSTR_TYPE = 404, /* INSTR_TYPE */ + INSTR_STRING = 405, /* INSTR_STRING */ + INSTR_SIG = 406, /* INSTR_SIG */ + INSTR_TOK = 407, /* INSTR_TOK */ + INSTR_SWITCH = 408, /* INSTR_SWITCH */ + _CLASS = 409, /* _CLASS */ + _NAMESPACE = 410, /* _NAMESPACE */ + _METHOD = 411, /* _METHOD */ + _FIELD = 412, /* _FIELD */ + _DATA = 413, /* _DATA */ + _THIS = 414, /* _THIS */ + _BASE = 415, /* _BASE */ + _NESTER = 416, /* _NESTER */ + _EMITBYTE = 417, /* _EMITBYTE */ + _TRY = 418, /* _TRY */ + _MAXSTACK = 419, /* _MAXSTACK */ + _LOCALS = 420, /* _LOCALS */ + _ENTRYPOINT = 421, /* _ENTRYPOINT */ + _ZEROINIT = 422, /* _ZEROINIT */ + _EVENT = 423, /* _EVENT */ + _ADDON = 424, /* _ADDON */ + _REMOVEON = 425, /* _REMOVEON */ + _FIRE = 426, /* _FIRE */ + _OTHER = 427, /* _OTHER */ + _PROPERTY = 428, /* _PROPERTY */ + _SET = 429, /* _SET */ + _GET = 430, /* _GET */ + _PERMISSION = 431, /* _PERMISSION */ + _PERMISSIONSET = 432, /* _PERMISSIONSET */ + REQUEST_ = 433, /* REQUEST_ */ + DEMAND_ = 434, /* DEMAND_ */ + ASSERT_ = 435, /* ASSERT_ */ + DENY_ = 436, /* DENY_ */ + PERMITONLY_ = 437, /* PERMITONLY_ */ + LINKCHECK_ = 438, /* LINKCHECK_ */ + INHERITCHECK_ = 439, /* INHERITCHECK_ */ + REQMIN_ = 440, /* REQMIN_ */ + REQOPT_ = 441, /* REQOPT_ */ + REQREFUSE_ = 442, /* REQREFUSE_ */ + PREJITGRANT_ = 443, /* PREJITGRANT_ */ + PREJITDENY_ = 444, /* PREJITDENY_ */ + NONCASDEMAND_ = 445, /* NONCASDEMAND_ */ + NONCASLINKDEMAND_ = 446, /* NONCASLINKDEMAND_ */ + NONCASINHERITANCE_ = 447, /* NONCASINHERITANCE_ */ + _LINE = 448, /* _LINE */ + P_LINE = 449, /* P_LINE */ + _LANGUAGE = 450, /* _LANGUAGE */ + _CUSTOM = 451, /* _CUSTOM */ + INIT_ = 452, /* INIT_ */ + _SIZE = 453, /* _SIZE */ + _PACK = 454, /* _PACK */ + _VTABLE = 455, /* _VTABLE */ + _VTFIXUP = 456, /* _VTFIXUP */ + FROMUNMANAGED_ = 457, /* FROMUNMANAGED_ */ + CALLMOSTDERIVED_ = 458, /* CALLMOSTDERIVED_ */ + _VTENTRY = 459, /* _VTENTRY */ + RETAINAPPDOMAIN_ = 460, /* RETAINAPPDOMAIN_ */ + _FILE = 461, /* _FILE */ + NOMETADATA_ = 462, /* NOMETADATA_ */ + _HASH = 463, /* _HASH */ + _ASSEMBLY = 464, /* _ASSEMBLY */ + _PUBLICKEY = 465, /* _PUBLICKEY */ + _PUBLICKEYTOKEN = 466, /* _PUBLICKEYTOKEN */ + ALGORITHM_ = 467, /* ALGORITHM_ */ + _VER = 468, /* _VER */ + _LOCALE = 469, /* _LOCALE */ + EXTERN_ = 470, /* EXTERN_ */ + _MRESOURCE = 471, /* _MRESOURCE */ + _MODULE = 472, /* _MODULE */ + _EXPORT = 473, /* _EXPORT */ + LEGACY_ = 474, /* LEGACY_ */ + LIBRARY_ = 475, /* LIBRARY_ */ + X86_ = 476, /* X86_ */ + AMD64_ = 477, /* AMD64_ */ + ARM_ = 478, /* ARM_ */ + ARM64_ = 479, /* ARM64_ */ + MARSHAL_ = 480, /* MARSHAL_ */ + CUSTOM_ = 481, /* CUSTOM_ */ + SYSSTRING_ = 482, /* SYSSTRING_ */ + FIXED_ = 483, /* FIXED_ */ + VARIANT_ = 484, /* VARIANT_ */ + CURRENCY_ = 485, /* CURRENCY_ */ + SYSCHAR_ = 486, /* SYSCHAR_ */ + DECIMAL_ = 487, /* DECIMAL_ */ + DATE_ = 488, /* DATE_ */ + BSTR_ = 489, /* BSTR_ */ + TBSTR_ = 490, /* TBSTR_ */ + LPSTR_ = 491, /* LPSTR_ */ + LPWSTR_ = 492, /* LPWSTR_ */ + LPTSTR_ = 493, /* LPTSTR_ */ + OBJECTREF_ = 494, /* OBJECTREF_ */ + IUNKNOWN_ = 495, /* IUNKNOWN_ */ + IDISPATCH_ = 496, /* IDISPATCH_ */ + STRUCT_ = 497, /* STRUCT_ */ + SAFEARRAY_ = 498, /* SAFEARRAY_ */ + BYVALSTR_ = 499, /* BYVALSTR_ */ + LPVOID_ = 500, /* LPVOID_ */ + ANY_ = 501, /* ANY_ */ + ARRAY_ = 502, /* ARRAY_ */ + LPSTRUCT_ = 503, /* LPSTRUCT_ */ + IIDPARAM_ = 504, /* IIDPARAM_ */ + IN_ = 505, /* IN_ */ + OUT_ = 506, /* OUT_ */ + OPT_ = 507, /* OPT_ */ + _PARAM = 508, /* _PARAM */ + _OVERRIDE = 509, /* _OVERRIDE */ + WITH_ = 510, /* WITH_ */ + NULL_ = 511, /* NULL_ */ + ERROR_ = 512, /* ERROR_ */ + HRESULT_ = 513, /* HRESULT_ */ + CARRAY_ = 514, /* CARRAY_ */ + USERDEFINED_ = 515, /* USERDEFINED_ */ + RECORD_ = 516, /* RECORD_ */ + FILETIME_ = 517, /* FILETIME_ */ + BLOB_ = 518, /* BLOB_ */ + STREAM_ = 519, /* STREAM_ */ + STORAGE_ = 520, /* STORAGE_ */ + STREAMED_OBJECT_ = 521, /* STREAMED_OBJECT_ */ + STORED_OBJECT_ = 522, /* STORED_OBJECT_ */ + BLOB_OBJECT_ = 523, /* BLOB_OBJECT_ */ + CF_ = 524, /* CF_ */ + CLSID_ = 525, /* CLSID_ */ + VECTOR_ = 526, /* VECTOR_ */ + _SUBSYSTEM = 527, /* _SUBSYSTEM */ + _CORFLAGS = 528, /* _CORFLAGS */ + ALIGNMENT_ = 529, /* ALIGNMENT_ */ + _IMAGEBASE = 530, /* _IMAGEBASE */ + _STACKRESERVE = 531, /* _STACKRESERVE */ + _TYPEDEF = 532, /* _TYPEDEF */ + _TEMPLATE = 533, /* _TEMPLATE */ + _TYPELIST = 534, /* _TYPELIST */ + _MSCORLIB = 535, /* _MSCORLIB */ + P_DEFINE = 536, /* P_DEFINE */ + P_UNDEF = 537, /* P_UNDEF */ + P_IFDEF = 538, /* P_IFDEF */ + P_IFNDEF = 539, /* P_IFNDEF */ + P_ELSE = 540, /* P_ELSE */ + P_ENDIF = 541, /* P_ENDIF */ + P_INCLUDE = 542, /* P_INCLUDE */ + CONSTRAINT_ = 543 /* CONSTRAINT_ */ + }; + typedef enum yytokentype yytoken_kind_t; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +union YYSTYPE +{ #line 15 "asmparse.y" -#define UNION 1 -typedef union { CorRegTypeAttr classAttr; CorMethodAttr methAttr; CorFieldAttr fieldAttr; @@ -33,8 +432,8 @@ typedef union { CorTypeAttr exptAttr; CorManifestResourceFlags manresAttr; double* float64; - __int64* int64; - __int32 int32; + int64_t* int64; + int32_t int32; char* string; BinStr* binstr; Labels* labels; @@ -45,4907 +444,8435 @@ typedef union { TypeDefDescr* tdd; CustomDescr* cad; unsigned short opcode; -} YYSTYPE; -# define ERROR_ 257 -# define BAD_COMMENT_ 258 -# define BAD_LITERAL_ 259 -# define ID 260 -# define DOTTEDNAME 261 -# define QSTRING 262 -# define SQSTRING 263 -# define INT32 264 -# define INT64 265 -# define FLOAT64 266 -# define HEXBYTE 267 -# define TYPEDEF_T 268 -# define TYPEDEF_M 269 -# define TYPEDEF_F 270 -# define TYPEDEF_TS 271 -# define TYPEDEF_MR 272 -# define TYPEDEF_CA 273 -# define DCOLON 274 -# define ELLIPSIS 275 -# define VOID_ 276 -# define BOOL_ 277 -# define CHAR_ 278 -# define UNSIGNED_ 279 -# define INT_ 280 -# define INT8_ 281 -# define INT16_ 282 -# define INT32_ 283 -# define INT64_ 284 -# define FLOAT_ 285 -# define FLOAT32_ 286 -# define FLOAT64_ 287 -# define BYTEARRAY_ 288 -# define UINT_ 289 -# define UINT8_ 290 -# define UINT16_ 291 -# define UINT32_ 292 -# define UINT64_ 293 -# define FLAGS_ 294 -# define CALLCONV_ 295 -# define MDTOKEN_ 296 -# define OBJECT_ 297 -# define STRING_ 298 -# define NULLREF_ 299 -# define DEFAULT_ 300 -# define CDECL_ 301 -# define VARARG_ 302 -# define STDCALL_ 303 -# define THISCALL_ 304 -# define FASTCALL_ 305 -# define CLASS_ 306 -# define BYREFLIKE_ 307 -# define GENCONSTRAINT_ 308 -# define TYPEDREF_ 309 -# define UNMANAGED_ 310 -# define FINALLY_ 311 -# define HANDLER_ 312 -# define CATCH_ 313 -# define FILTER_ 314 -# define FAULT_ 315 -# define EXTENDS_ 316 -# define IMPLEMENTS_ 317 -# define TO_ 318 -# define AT_ 319 -# define TLS_ 320 -# define TRUE_ 321 -# define FALSE_ 322 -# define _INTERFACEIMPL 323 -# define VALUE_ 324 -# define VALUETYPE_ 325 -# define NATIVE_ 326 -# define INSTANCE_ 327 -# define SPECIALNAME_ 328 -# define FORWARDER_ 329 -# define STATIC_ 330 -# define PUBLIC_ 331 -# define PRIVATE_ 332 -# define FAMILY_ 333 -# define FINAL_ 334 -# define SYNCHRONIZED_ 335 -# define INTERFACE_ 336 -# define SEALED_ 337 -# define NESTED_ 338 -# define ABSTRACT_ 339 -# define AUTO_ 340 -# define SEQUENTIAL_ 341 -# define EXPLICIT_ 342 -# define ANSI_ 343 -# define UNICODE_ 344 -# define AUTOCHAR_ 345 -# define IMPORT_ 346 -# define ENUM_ 347 -# define VIRTUAL_ 348 -# define NOINLINING_ 349 -# define AGGRESSIVEINLINING_ 350 -# define NOOPTIMIZATION_ 351 -# define AGGRESSIVEOPTIMIZATION_ 352 -# define UNMANAGEDEXP_ 353 -# define BEFOREFIELDINIT_ 354 -# define STRICT_ 355 -# define RETARGETABLE_ 356 -# define WINDOWSRUNTIME_ 357 -# define NOPLATFORM_ 358 -# define METHOD_ 359 -# define FIELD_ 360 -# define PINNED_ 361 -# define MODREQ_ 362 -# define MODOPT_ 363 -# define SERIALIZABLE_ 364 -# define PROPERTY_ 365 -# define TYPE_ 366 -# define ASSEMBLY_ 367 -# define FAMANDASSEM_ 368 -# define FAMORASSEM_ 369 -# define PRIVATESCOPE_ 370 -# define HIDEBYSIG_ 371 -# define NEWSLOT_ 372 -# define RTSPECIALNAME_ 373 -# define PINVOKEIMPL_ 374 -# define _CTOR 375 -# define _CCTOR 376 -# define LITERAL_ 377 -# define NOTSERIALIZED_ 378 -# define INITONLY_ 379 -# define REQSECOBJ_ 380 -# define CIL_ 381 -# define OPTIL_ 382 -# define MANAGED_ 383 -# define FORWARDREF_ 384 -# define PRESERVESIG_ 385 -# define RUNTIME_ 386 -# define INTERNALCALL_ 387 -# define _IMPORT 388 -# define NOMANGLE_ 389 -# define LASTERR_ 390 -# define WINAPI_ 391 -# define AS_ 392 -# define BESTFIT_ 393 -# define ON_ 394 -# define OFF_ 395 -# define CHARMAPERROR_ 396 -# define INSTR_NONE 397 -# define INSTR_VAR 398 -# define INSTR_I 399 -# define INSTR_I8 400 -# define INSTR_R 401 -# define INSTR_BRTARGET 402 -# define INSTR_METHOD 403 -# define INSTR_FIELD 404 -# define INSTR_TYPE 405 -# define INSTR_STRING 406 -# define INSTR_SIG 407 -# define INSTR_TOK 408 -# define INSTR_SWITCH 409 -# define _CLASS 410 -# define _NAMESPACE 411 -# define _METHOD 412 -# define _FIELD 413 -# define _DATA 414 -# define _THIS 415 -# define _BASE 416 -# define _NESTER 417 -# define _EMITBYTE 418 -# define _TRY 419 -# define _MAXSTACK 420 -# define _LOCALS 421 -# define _ENTRYPOINT 422 -# define _ZEROINIT 423 -# define _EVENT 424 -# define _ADDON 425 -# define _REMOVEON 426 -# define _FIRE 427 -# define _OTHER 428 -# define _PROPERTY 429 -# define _SET 430 -# define _GET 431 -# define _PERMISSION 432 -# define _PERMISSIONSET 433 -# define REQUEST_ 434 -# define DEMAND_ 435 -# define ASSERT_ 436 -# define DENY_ 437 -# define PERMITONLY_ 438 -# define LINKCHECK_ 439 -# define INHERITCHECK_ 440 -# define REQMIN_ 441 -# define REQOPT_ 442 -# define REQREFUSE_ 443 -# define PREJITGRANT_ 444 -# define PREJITDENY_ 445 -# define NONCASDEMAND_ 446 -# define NONCASLINKDEMAND_ 447 -# define NONCASINHERITANCE_ 448 -# define _LINE 449 -# define P_LINE 450 -# define _LANGUAGE 451 -# define _CUSTOM 452 -# define INIT_ 453 -# define _SIZE 454 -# define _PACK 455 -# define _VTABLE 456 -# define _VTFIXUP 457 -# define FROMUNMANAGED_ 458 -# define CALLMOSTDERIVED_ 459 -# define _VTENTRY 460 -# define RETAINAPPDOMAIN_ 461 -# define _FILE 462 -# define NOMETADATA_ 463 -# define _HASH 464 -# define _ASSEMBLY 465 -# define _PUBLICKEY 466 -# define _PUBLICKEYTOKEN 467 -# define ALGORITHM_ 468 -# define _VER 469 -# define _LOCALE 470 -# define EXTERN_ 471 -# define _MRESOURCE 472 -# define _MODULE 473 -# define _EXPORT 474 -# define LEGACY_ 475 -# define LIBRARY_ 476 -# define X86_ 477 -# define AMD64_ 478 -# define ARM_ 479 -# define ARM64_ 480 -# define MARSHAL_ 481 -# define CUSTOM_ 482 -# define SYSSTRING_ 483 -# define FIXED_ 484 -# define VARIANT_ 485 -# define CURRENCY_ 486 -# define SYSCHAR_ 487 -# define DECIMAL_ 488 -# define DATE_ 489 -# define BSTR_ 490 -# define TBSTR_ 491 -# define LPSTR_ 492 -# define LPWSTR_ 493 -# define LPTSTR_ 494 -# define OBJECTREF_ 495 -# define IUNKNOWN_ 496 -# define IDISPATCH_ 497 -# define STRUCT_ 498 -# define SAFEARRAY_ 499 -# define BYVALSTR_ 500 -# define LPVOID_ 501 -# define ANY_ 502 -# define ARRAY_ 503 -# define LPSTRUCT_ 504 -# define IIDPARAM_ 505 -# define IN_ 506 -# define OUT_ 507 -# define OPT_ 508 -# define _PARAM 509 -# define _OVERRIDE 510 -# define WITH_ 511 -# define NULL_ 512 -# define HRESULT_ 513 -# define CARRAY_ 514 -# define USERDEFINED_ 515 -# define RECORD_ 516 -# define FILETIME_ 517 -# define BLOB_ 518 -# define STREAM_ 519 -# define STORAGE_ 520 -# define STREAMED_OBJECT_ 521 -# define STORED_OBJECT_ 522 -# define BLOB_OBJECT_ 523 -# define CF_ 524 -# define CLSID_ 525 -# define VECTOR_ 526 -# define _SUBSYSTEM 527 -# define _CORFLAGS 528 -# define ALIGNMENT_ 529 -# define _IMAGEBASE 530 -# define _STACKRESERVE 531 -# define _TYPEDEF 532 -# define _TEMPLATE 533 -# define _TYPELIST 534 -# define _MSCORLIB 535 -# define P_DEFINE 536 -# define P_UNDEF 537 -# define P_IFDEF 538 -# define P_IFNDEF 539 -# define P_ELSE 540 -# define P_ENDIF 541 -# define P_INCLUDE 542 -# define CONSTRAINT_ 543 -#define yyclearin yychar = -1 -#define yyerrok yyerrflag = 0 -#ifndef YYMAXDEPTH -#define YYMAXDEPTH 150 -#endif -YYSTYPE yylval, yyval; -#ifndef YYFARDATA -#define YYFARDATA /*nothing*/ -#endif -#if ! defined YYSTATIC -#define YYSTATIC /*nothing*/ -#endif -#if ! defined YYCONST -#define YYCONST /*nothing*/ -#endif -#ifndef YYACT -#define YYACT yyact -#endif -#ifndef YYPACT -#define YYPACT yypact -#endif -#ifndef YYPGO -#define YYPGO yypgo -#endif -#ifndef YYR1 -#define YYR1 yyr1 + +#line 449 "asmparse.cpp" + +}; +typedef union YYSTYPE YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 #endif -#ifndef YYR2 -#define YYR2 yyr2 + + +extern YYSTYPE yylval; + + +int yyparse (void); + + + +/* Symbol kind. */ +enum yysymbol_kind_t +{ + YYSYMBOL_YYEMPTY = -2, + YYSYMBOL_YYEOF = 0, /* "end of file" */ + YYSYMBOL_YYerror = 1, /* error */ + YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ + YYSYMBOL_BAD_COMMENT_ = 3, /* BAD_COMMENT_ */ + YYSYMBOL_BAD_LITERAL_ = 4, /* BAD_LITERAL_ */ + YYSYMBOL_ID = 5, /* ID */ + YYSYMBOL_DOTTEDNAME = 6, /* DOTTEDNAME */ + YYSYMBOL_QSTRING = 7, /* QSTRING */ + YYSYMBOL_SQSTRING = 8, /* SQSTRING */ + YYSYMBOL_INT32_V = 9, /* INT32_V */ + YYSYMBOL_INT64_V = 10, /* INT64_V */ + YYSYMBOL_FLOAT64 = 11, /* FLOAT64 */ + YYSYMBOL_HEXBYTE = 12, /* HEXBYTE */ + YYSYMBOL_TYPEDEF_T = 13, /* TYPEDEF_T */ + YYSYMBOL_TYPEDEF_M = 14, /* TYPEDEF_M */ + YYSYMBOL_TYPEDEF_F = 15, /* TYPEDEF_F */ + YYSYMBOL_TYPEDEF_TS = 16, /* TYPEDEF_TS */ + YYSYMBOL_TYPEDEF_MR = 17, /* TYPEDEF_MR */ + YYSYMBOL_TYPEDEF_CA = 18, /* TYPEDEF_CA */ + YYSYMBOL_DCOLON = 19, /* DCOLON */ + YYSYMBOL_ELLIPSIS = 20, /* ELLIPSIS */ + YYSYMBOL_VOID_ = 21, /* VOID_ */ + YYSYMBOL_BOOL_ = 22, /* BOOL_ */ + YYSYMBOL_CHAR_ = 23, /* CHAR_ */ + YYSYMBOL_UNSIGNED_ = 24, /* UNSIGNED_ */ + YYSYMBOL_INT_ = 25, /* INT_ */ + YYSYMBOL_INT8_ = 26, /* INT8_ */ + YYSYMBOL_INT16_ = 27, /* INT16_ */ + YYSYMBOL_INT32_ = 28, /* INT32_ */ + YYSYMBOL_INT64_ = 29, /* INT64_ */ + YYSYMBOL_FLOAT_ = 30, /* FLOAT_ */ + YYSYMBOL_FLOAT32_ = 31, /* FLOAT32_ */ + YYSYMBOL_FLOAT64_ = 32, /* FLOAT64_ */ + YYSYMBOL_BYTEARRAY_ = 33, /* BYTEARRAY_ */ + YYSYMBOL_UINT_ = 34, /* UINT_ */ + YYSYMBOL_UINT8_ = 35, /* UINT8_ */ + YYSYMBOL_UINT16_ = 36, /* UINT16_ */ + YYSYMBOL_UINT32_ = 37, /* UINT32_ */ + YYSYMBOL_UINT64_ = 38, /* UINT64_ */ + YYSYMBOL_FLAGS_ = 39, /* FLAGS_ */ + YYSYMBOL_CALLCONV_ = 40, /* CALLCONV_ */ + YYSYMBOL_MDTOKEN_ = 41, /* MDTOKEN_ */ + YYSYMBOL_OBJECT_ = 42, /* OBJECT_ */ + YYSYMBOL_STRING_ = 43, /* STRING_ */ + YYSYMBOL_NULLREF_ = 44, /* NULLREF_ */ + YYSYMBOL_DEFAULT_ = 45, /* DEFAULT_ */ + YYSYMBOL_CDECL_ = 46, /* CDECL_ */ + YYSYMBOL_VARARG_ = 47, /* VARARG_ */ + YYSYMBOL_STDCALL_ = 48, /* STDCALL_ */ + YYSYMBOL_THISCALL_ = 49, /* THISCALL_ */ + YYSYMBOL_FASTCALL_ = 50, /* FASTCALL_ */ + YYSYMBOL_CLASS_ = 51, /* CLASS_ */ + YYSYMBOL_BYREFLIKE_ = 52, /* BYREFLIKE_ */ + YYSYMBOL_TYPEDREF_ = 53, /* TYPEDREF_ */ + YYSYMBOL_UNMANAGED_ = 54, /* UNMANAGED_ */ + YYSYMBOL_FINALLY_ = 55, /* FINALLY_ */ + YYSYMBOL_HANDLER_ = 56, /* HANDLER_ */ + YYSYMBOL_CATCH_ = 57, /* CATCH_ */ + YYSYMBOL_FILTER_ = 58, /* FILTER_ */ + YYSYMBOL_FAULT_ = 59, /* FAULT_ */ + YYSYMBOL_EXTENDS_ = 60, /* EXTENDS_ */ + YYSYMBOL_IMPLEMENTS_ = 61, /* IMPLEMENTS_ */ + YYSYMBOL_TO_ = 62, /* TO_ */ + YYSYMBOL_AT_ = 63, /* AT_ */ + YYSYMBOL_TLS_ = 64, /* TLS_ */ + YYSYMBOL_TRUE_ = 65, /* TRUE_ */ + YYSYMBOL_FALSE_ = 66, /* FALSE_ */ + YYSYMBOL__INTERFACEIMPL = 67, /* _INTERFACEIMPL */ + YYSYMBOL_VALUE_ = 68, /* VALUE_ */ + YYSYMBOL_VALUETYPE_ = 69, /* VALUETYPE_ */ + YYSYMBOL_NATIVE_ = 70, /* NATIVE_ */ + YYSYMBOL_INSTANCE_ = 71, /* INSTANCE_ */ + YYSYMBOL_SPECIALNAME_ = 72, /* SPECIALNAME_ */ + YYSYMBOL_FORWARDER_ = 73, /* FORWARDER_ */ + YYSYMBOL_STATIC_ = 74, /* STATIC_ */ + YYSYMBOL_PUBLIC_ = 75, /* PUBLIC_ */ + YYSYMBOL_PRIVATE_ = 76, /* PRIVATE_ */ + YYSYMBOL_FAMILY_ = 77, /* FAMILY_ */ + YYSYMBOL_FINAL_ = 78, /* FINAL_ */ + YYSYMBOL_SYNCHRONIZED_ = 79, /* SYNCHRONIZED_ */ + YYSYMBOL_INTERFACE_ = 80, /* INTERFACE_ */ + YYSYMBOL_SEALED_ = 81, /* SEALED_ */ + YYSYMBOL_NESTED_ = 82, /* NESTED_ */ + YYSYMBOL_ABSTRACT_ = 83, /* ABSTRACT_ */ + YYSYMBOL_AUTO_ = 84, /* AUTO_ */ + YYSYMBOL_SEQUENTIAL_ = 85, /* SEQUENTIAL_ */ + YYSYMBOL_EXPLICIT_ = 86, /* EXPLICIT_ */ + YYSYMBOL_ANSI_ = 87, /* ANSI_ */ + YYSYMBOL_UNICODE_ = 88, /* UNICODE_ */ + YYSYMBOL_AUTOCHAR_ = 89, /* AUTOCHAR_ */ + YYSYMBOL_IMPORT_ = 90, /* IMPORT_ */ + YYSYMBOL_ENUM_ = 91, /* ENUM_ */ + YYSYMBOL_VIRTUAL_ = 92, /* VIRTUAL_ */ + YYSYMBOL_NOINLINING_ = 93, /* NOINLINING_ */ + YYSYMBOL_AGGRESSIVEINLINING_ = 94, /* AGGRESSIVEINLINING_ */ + YYSYMBOL_NOOPTIMIZATION_ = 95, /* NOOPTIMIZATION_ */ + YYSYMBOL_AGGRESSIVEOPTIMIZATION_ = 96, /* AGGRESSIVEOPTIMIZATION_ */ + YYSYMBOL_UNMANAGEDEXP_ = 97, /* UNMANAGEDEXP_ */ + YYSYMBOL_BEFOREFIELDINIT_ = 98, /* BEFOREFIELDINIT_ */ + YYSYMBOL_STRICT_ = 99, /* STRICT_ */ + YYSYMBOL_RETARGETABLE_ = 100, /* RETARGETABLE_ */ + YYSYMBOL_WINDOWSRUNTIME_ = 101, /* WINDOWSRUNTIME_ */ + YYSYMBOL_NOPLATFORM_ = 102, /* NOPLATFORM_ */ + YYSYMBOL_METHOD_ = 103, /* METHOD_ */ + YYSYMBOL_FIELD_ = 104, /* FIELD_ */ + YYSYMBOL_PINNED_ = 105, /* PINNED_ */ + YYSYMBOL_MODREQ_ = 106, /* MODREQ_ */ + YYSYMBOL_MODOPT_ = 107, /* MODOPT_ */ + YYSYMBOL_SERIALIZABLE_ = 108, /* SERIALIZABLE_ */ + YYSYMBOL_PROPERTY_ = 109, /* PROPERTY_ */ + YYSYMBOL_TYPE_ = 110, /* TYPE_ */ + YYSYMBOL_ASSEMBLY_ = 111, /* ASSEMBLY_ */ + YYSYMBOL_FAMANDASSEM_ = 112, /* FAMANDASSEM_ */ + YYSYMBOL_FAMORASSEM_ = 113, /* FAMORASSEM_ */ + YYSYMBOL_PRIVATESCOPE_ = 114, /* PRIVATESCOPE_ */ + YYSYMBOL_HIDEBYSIG_ = 115, /* HIDEBYSIG_ */ + YYSYMBOL_NEWSLOT_ = 116, /* NEWSLOT_ */ + YYSYMBOL_RTSPECIALNAME_ = 117, /* RTSPECIALNAME_ */ + YYSYMBOL_PINVOKEIMPL_ = 118, /* PINVOKEIMPL_ */ + YYSYMBOL__CTOR = 119, /* _CTOR */ + YYSYMBOL__CCTOR = 120, /* _CCTOR */ + YYSYMBOL_LITERAL_ = 121, /* LITERAL_ */ + YYSYMBOL_NOTSERIALIZED_ = 122, /* NOTSERIALIZED_ */ + YYSYMBOL_INITONLY_ = 123, /* INITONLY_ */ + YYSYMBOL_REQSECOBJ_ = 124, /* REQSECOBJ_ */ + YYSYMBOL_CIL_ = 125, /* CIL_ */ + YYSYMBOL_OPTIL_ = 126, /* OPTIL_ */ + YYSYMBOL_MANAGED_ = 127, /* MANAGED_ */ + YYSYMBOL_FORWARDREF_ = 128, /* FORWARDREF_ */ + YYSYMBOL_PRESERVESIG_ = 129, /* PRESERVESIG_ */ + YYSYMBOL_RUNTIME_ = 130, /* RUNTIME_ */ + YYSYMBOL_INTERNALCALL_ = 131, /* INTERNALCALL_ */ + YYSYMBOL__IMPORT = 132, /* _IMPORT */ + YYSYMBOL_NOMANGLE_ = 133, /* NOMANGLE_ */ + YYSYMBOL_LASTERR_ = 134, /* LASTERR_ */ + YYSYMBOL_WINAPI_ = 135, /* WINAPI_ */ + YYSYMBOL_AS_ = 136, /* AS_ */ + YYSYMBOL_BESTFIT_ = 137, /* BESTFIT_ */ + YYSYMBOL_ON_ = 138, /* ON_ */ + YYSYMBOL_OFF_ = 139, /* OFF_ */ + YYSYMBOL_CHARMAPERROR_ = 140, /* CHARMAPERROR_ */ + YYSYMBOL_INSTR_NONE = 141, /* INSTR_NONE */ + YYSYMBOL_INSTR_VAR = 142, /* INSTR_VAR */ + YYSYMBOL_INSTR_I = 143, /* INSTR_I */ + YYSYMBOL_INSTR_I8 = 144, /* INSTR_I8 */ + YYSYMBOL_INSTR_R = 145, /* INSTR_R */ + YYSYMBOL_INSTR_BRTARGET = 146, /* INSTR_BRTARGET */ + YYSYMBOL_INSTR_METHOD = 147, /* INSTR_METHOD */ + YYSYMBOL_INSTR_FIELD = 148, /* INSTR_FIELD */ + YYSYMBOL_INSTR_TYPE = 149, /* INSTR_TYPE */ + YYSYMBOL_INSTR_STRING = 150, /* INSTR_STRING */ + YYSYMBOL_INSTR_SIG = 151, /* INSTR_SIG */ + YYSYMBOL_INSTR_TOK = 152, /* INSTR_TOK */ + YYSYMBOL_INSTR_SWITCH = 153, /* INSTR_SWITCH */ + YYSYMBOL__CLASS = 154, /* _CLASS */ + YYSYMBOL__NAMESPACE = 155, /* _NAMESPACE */ + YYSYMBOL__METHOD = 156, /* _METHOD */ + YYSYMBOL__FIELD = 157, /* _FIELD */ + YYSYMBOL__DATA = 158, /* _DATA */ + YYSYMBOL__THIS = 159, /* _THIS */ + YYSYMBOL__BASE = 160, /* _BASE */ + YYSYMBOL__NESTER = 161, /* _NESTER */ + YYSYMBOL__EMITBYTE = 162, /* _EMITBYTE */ + YYSYMBOL__TRY = 163, /* _TRY */ + YYSYMBOL__MAXSTACK = 164, /* _MAXSTACK */ + YYSYMBOL__LOCALS = 165, /* _LOCALS */ + YYSYMBOL__ENTRYPOINT = 166, /* _ENTRYPOINT */ + YYSYMBOL__ZEROINIT = 167, /* _ZEROINIT */ + YYSYMBOL__EVENT = 168, /* _EVENT */ + YYSYMBOL__ADDON = 169, /* _ADDON */ + YYSYMBOL__REMOVEON = 170, /* _REMOVEON */ + YYSYMBOL__FIRE = 171, /* _FIRE */ + YYSYMBOL__OTHER = 172, /* _OTHER */ + YYSYMBOL__PROPERTY = 173, /* _PROPERTY */ + YYSYMBOL__SET = 174, /* _SET */ + YYSYMBOL__GET = 175, /* _GET */ + YYSYMBOL__PERMISSION = 176, /* _PERMISSION */ + YYSYMBOL__PERMISSIONSET = 177, /* _PERMISSIONSET */ + YYSYMBOL_REQUEST_ = 178, /* REQUEST_ */ + YYSYMBOL_DEMAND_ = 179, /* DEMAND_ */ + YYSYMBOL_ASSERT_ = 180, /* ASSERT_ */ + YYSYMBOL_DENY_ = 181, /* DENY_ */ + YYSYMBOL_PERMITONLY_ = 182, /* PERMITONLY_ */ + YYSYMBOL_LINKCHECK_ = 183, /* LINKCHECK_ */ + YYSYMBOL_INHERITCHECK_ = 184, /* INHERITCHECK_ */ + YYSYMBOL_REQMIN_ = 185, /* REQMIN_ */ + YYSYMBOL_REQOPT_ = 186, /* REQOPT_ */ + YYSYMBOL_REQREFUSE_ = 187, /* REQREFUSE_ */ + YYSYMBOL_PREJITGRANT_ = 188, /* PREJITGRANT_ */ + YYSYMBOL_PREJITDENY_ = 189, /* PREJITDENY_ */ + YYSYMBOL_NONCASDEMAND_ = 190, /* NONCASDEMAND_ */ + YYSYMBOL_NONCASLINKDEMAND_ = 191, /* NONCASLINKDEMAND_ */ + YYSYMBOL_NONCASINHERITANCE_ = 192, /* NONCASINHERITANCE_ */ + YYSYMBOL__LINE = 193, /* _LINE */ + YYSYMBOL_P_LINE = 194, /* P_LINE */ + YYSYMBOL__LANGUAGE = 195, /* _LANGUAGE */ + YYSYMBOL__CUSTOM = 196, /* _CUSTOM */ + YYSYMBOL_INIT_ = 197, /* INIT_ */ + YYSYMBOL__SIZE = 198, /* _SIZE */ + YYSYMBOL__PACK = 199, /* _PACK */ + YYSYMBOL__VTABLE = 200, /* _VTABLE */ + YYSYMBOL__VTFIXUP = 201, /* _VTFIXUP */ + YYSYMBOL_FROMUNMANAGED_ = 202, /* FROMUNMANAGED_ */ + YYSYMBOL_CALLMOSTDERIVED_ = 203, /* CALLMOSTDERIVED_ */ + YYSYMBOL__VTENTRY = 204, /* _VTENTRY */ + YYSYMBOL_RETAINAPPDOMAIN_ = 205, /* RETAINAPPDOMAIN_ */ + YYSYMBOL__FILE = 206, /* _FILE */ + YYSYMBOL_NOMETADATA_ = 207, /* NOMETADATA_ */ + YYSYMBOL__HASH = 208, /* _HASH */ + YYSYMBOL__ASSEMBLY = 209, /* _ASSEMBLY */ + YYSYMBOL__PUBLICKEY = 210, /* _PUBLICKEY */ + YYSYMBOL__PUBLICKEYTOKEN = 211, /* _PUBLICKEYTOKEN */ + YYSYMBOL_ALGORITHM_ = 212, /* ALGORITHM_ */ + YYSYMBOL__VER = 213, /* _VER */ + YYSYMBOL__LOCALE = 214, /* _LOCALE */ + YYSYMBOL_EXTERN_ = 215, /* EXTERN_ */ + YYSYMBOL__MRESOURCE = 216, /* _MRESOURCE */ + YYSYMBOL__MODULE = 217, /* _MODULE */ + YYSYMBOL__EXPORT = 218, /* _EXPORT */ + YYSYMBOL_LEGACY_ = 219, /* LEGACY_ */ + YYSYMBOL_LIBRARY_ = 220, /* LIBRARY_ */ + YYSYMBOL_X86_ = 221, /* X86_ */ + YYSYMBOL_AMD64_ = 222, /* AMD64_ */ + YYSYMBOL_ARM_ = 223, /* ARM_ */ + YYSYMBOL_ARM64_ = 224, /* ARM64_ */ + YYSYMBOL_MARSHAL_ = 225, /* MARSHAL_ */ + YYSYMBOL_CUSTOM_ = 226, /* CUSTOM_ */ + YYSYMBOL_SYSSTRING_ = 227, /* SYSSTRING_ */ + YYSYMBOL_FIXED_ = 228, /* FIXED_ */ + YYSYMBOL_VARIANT_ = 229, /* VARIANT_ */ + YYSYMBOL_CURRENCY_ = 230, /* CURRENCY_ */ + YYSYMBOL_SYSCHAR_ = 231, /* SYSCHAR_ */ + YYSYMBOL_DECIMAL_ = 232, /* DECIMAL_ */ + YYSYMBOL_DATE_ = 233, /* DATE_ */ + YYSYMBOL_BSTR_ = 234, /* BSTR_ */ + YYSYMBOL_TBSTR_ = 235, /* TBSTR_ */ + YYSYMBOL_LPSTR_ = 236, /* LPSTR_ */ + YYSYMBOL_LPWSTR_ = 237, /* LPWSTR_ */ + YYSYMBOL_LPTSTR_ = 238, /* LPTSTR_ */ + YYSYMBOL_OBJECTREF_ = 239, /* OBJECTREF_ */ + YYSYMBOL_IUNKNOWN_ = 240, /* IUNKNOWN_ */ + YYSYMBOL_IDISPATCH_ = 241, /* IDISPATCH_ */ + YYSYMBOL_STRUCT_ = 242, /* STRUCT_ */ + YYSYMBOL_SAFEARRAY_ = 243, /* SAFEARRAY_ */ + YYSYMBOL_BYVALSTR_ = 244, /* BYVALSTR_ */ + YYSYMBOL_LPVOID_ = 245, /* LPVOID_ */ + YYSYMBOL_ANY_ = 246, /* ANY_ */ + YYSYMBOL_ARRAY_ = 247, /* ARRAY_ */ + YYSYMBOL_LPSTRUCT_ = 248, /* LPSTRUCT_ */ + YYSYMBOL_IIDPARAM_ = 249, /* IIDPARAM_ */ + YYSYMBOL_IN_ = 250, /* IN_ */ + YYSYMBOL_OUT_ = 251, /* OUT_ */ + YYSYMBOL_OPT_ = 252, /* OPT_ */ + YYSYMBOL__PARAM = 253, /* _PARAM */ + YYSYMBOL__OVERRIDE = 254, /* _OVERRIDE */ + YYSYMBOL_WITH_ = 255, /* WITH_ */ + YYSYMBOL_NULL_ = 256, /* NULL_ */ + YYSYMBOL_ERROR_ = 257, /* ERROR_ */ + YYSYMBOL_HRESULT_ = 258, /* HRESULT_ */ + YYSYMBOL_CARRAY_ = 259, /* CARRAY_ */ + YYSYMBOL_USERDEFINED_ = 260, /* USERDEFINED_ */ + YYSYMBOL_RECORD_ = 261, /* RECORD_ */ + YYSYMBOL_FILETIME_ = 262, /* FILETIME_ */ + YYSYMBOL_BLOB_ = 263, /* BLOB_ */ + YYSYMBOL_STREAM_ = 264, /* STREAM_ */ + YYSYMBOL_STORAGE_ = 265, /* STORAGE_ */ + YYSYMBOL_STREAMED_OBJECT_ = 266, /* STREAMED_OBJECT_ */ + YYSYMBOL_STORED_OBJECT_ = 267, /* STORED_OBJECT_ */ + YYSYMBOL_BLOB_OBJECT_ = 268, /* BLOB_OBJECT_ */ + YYSYMBOL_CF_ = 269, /* CF_ */ + YYSYMBOL_CLSID_ = 270, /* CLSID_ */ + YYSYMBOL_VECTOR_ = 271, /* VECTOR_ */ + YYSYMBOL__SUBSYSTEM = 272, /* _SUBSYSTEM */ + YYSYMBOL__CORFLAGS = 273, /* _CORFLAGS */ + YYSYMBOL_ALIGNMENT_ = 274, /* ALIGNMENT_ */ + YYSYMBOL__IMAGEBASE = 275, /* _IMAGEBASE */ + YYSYMBOL__STACKRESERVE = 276, /* _STACKRESERVE */ + YYSYMBOL__TYPEDEF = 277, /* _TYPEDEF */ + YYSYMBOL__TEMPLATE = 278, /* _TEMPLATE */ + YYSYMBOL__TYPELIST = 279, /* _TYPELIST */ + YYSYMBOL__MSCORLIB = 280, /* _MSCORLIB */ + YYSYMBOL_P_DEFINE = 281, /* P_DEFINE */ + YYSYMBOL_P_UNDEF = 282, /* P_UNDEF */ + YYSYMBOL_P_IFDEF = 283, /* P_IFDEF */ + YYSYMBOL_P_IFNDEF = 284, /* P_IFNDEF */ + YYSYMBOL_P_ELSE = 285, /* P_ELSE */ + YYSYMBOL_P_ENDIF = 286, /* P_ENDIF */ + YYSYMBOL_P_INCLUDE = 287, /* P_INCLUDE */ + YYSYMBOL_CONSTRAINT_ = 288, /* CONSTRAINT_ */ + YYSYMBOL_289_ = 289, /* '{' */ + YYSYMBOL_290_ = 290, /* '}' */ + YYSYMBOL_291_ = 291, /* '+' */ + YYSYMBOL_292_ = 292, /* ',' */ + YYSYMBOL_293_ = 293, /* '.' */ + YYSYMBOL_294_ = 294, /* '(' */ + YYSYMBOL_295_ = 295, /* ')' */ + YYSYMBOL_296_ = 296, /* ';' */ + YYSYMBOL_297_ = 297, /* '=' */ + YYSYMBOL_298_ = 298, /* '[' */ + YYSYMBOL_299_ = 299, /* ']' */ + YYSYMBOL_300_ = 300, /* '<' */ + YYSYMBOL_301_ = 301, /* '>' */ + YYSYMBOL_302_ = 302, /* '-' */ + YYSYMBOL_303_ = 303, /* ':' */ + YYSYMBOL_304_ = 304, /* '*' */ + YYSYMBOL_305_ = 305, /* '&' */ + YYSYMBOL_306_ = 306, /* '/' */ + YYSYMBOL_307_ = 307, /* '!' */ + YYSYMBOL_YYACCEPT = 308, /* $accept */ + YYSYMBOL_decls = 309, /* decls */ + YYSYMBOL_decl = 310, /* decl */ + YYSYMBOL_classNameSeq = 311, /* classNameSeq */ + YYSYMBOL_compQstring = 312, /* compQstring */ + YYSYMBOL_languageDecl = 313, /* languageDecl */ + YYSYMBOL_id = 314, /* id */ + YYSYMBOL_dottedName = 315, /* dottedName */ + YYSYMBOL_int32 = 316, /* int32 */ + YYSYMBOL_int64 = 317, /* int64 */ + YYSYMBOL_float64 = 318, /* float64 */ + YYSYMBOL_typedefDecl = 319, /* typedefDecl */ + YYSYMBOL_compControl = 320, /* compControl */ + YYSYMBOL_customDescr = 321, /* customDescr */ + YYSYMBOL_customDescrWithOwner = 322, /* customDescrWithOwner */ + YYSYMBOL_customHead = 323, /* customHead */ + YYSYMBOL_customHeadWithOwner = 324, /* customHeadWithOwner */ + YYSYMBOL_customType = 325, /* customType */ + YYSYMBOL_ownerType = 326, /* ownerType */ + YYSYMBOL_customBlobDescr = 327, /* customBlobDescr */ + YYSYMBOL_customBlobArgs = 328, /* customBlobArgs */ + YYSYMBOL_customBlobNVPairs = 329, /* customBlobNVPairs */ + YYSYMBOL_fieldOrProp = 330, /* fieldOrProp */ + YYSYMBOL_customAttrDecl = 331, /* customAttrDecl */ + YYSYMBOL_serializType = 332, /* serializType */ + YYSYMBOL_moduleHead = 333, /* moduleHead */ + YYSYMBOL_vtfixupDecl = 334, /* vtfixupDecl */ + YYSYMBOL_vtfixupAttr = 335, /* vtfixupAttr */ + YYSYMBOL_vtableDecl = 336, /* vtableDecl */ + YYSYMBOL_vtableHead = 337, /* vtableHead */ + YYSYMBOL_nameSpaceHead = 338, /* nameSpaceHead */ + YYSYMBOL__class = 339, /* _class */ + YYSYMBOL_classHeadBegin = 340, /* classHeadBegin */ + YYSYMBOL_classHead = 341, /* classHead */ + YYSYMBOL_classAttr = 342, /* classAttr */ + YYSYMBOL_extendsClause = 343, /* extendsClause */ + YYSYMBOL_implClause = 344, /* implClause */ + YYSYMBOL_classDecls = 345, /* classDecls */ + YYSYMBOL_implList = 346, /* implList */ + YYSYMBOL_typeList = 347, /* typeList */ + YYSYMBOL_typeListNotEmpty = 348, /* typeListNotEmpty */ + YYSYMBOL_typarsClause = 349, /* typarsClause */ + YYSYMBOL_typarAttrib = 350, /* typarAttrib */ + YYSYMBOL_typarAttribs = 351, /* typarAttribs */ + YYSYMBOL_typars = 352, /* typars */ + YYSYMBOL_typarsRest = 353, /* typarsRest */ + YYSYMBOL_tyBound = 354, /* tyBound */ + YYSYMBOL_genArity = 355, /* genArity */ + YYSYMBOL_genArityNotEmpty = 356, /* genArityNotEmpty */ + YYSYMBOL_classDecl = 357, /* classDecl */ + YYSYMBOL_fieldDecl = 358, /* fieldDecl */ + YYSYMBOL_fieldAttr = 359, /* fieldAttr */ + YYSYMBOL_atOpt = 360, /* atOpt */ + YYSYMBOL_initOpt = 361, /* initOpt */ + YYSYMBOL_repeatOpt = 362, /* repeatOpt */ + YYSYMBOL_methodRef = 363, /* methodRef */ + YYSYMBOL_callConv = 364, /* callConv */ + YYSYMBOL_callKind = 365, /* callKind */ + YYSYMBOL_mdtoken = 366, /* mdtoken */ + YYSYMBOL_memberRef = 367, /* memberRef */ + YYSYMBOL_eventHead = 368, /* eventHead */ + YYSYMBOL_eventAttr = 369, /* eventAttr */ + YYSYMBOL_eventDecls = 370, /* eventDecls */ + YYSYMBOL_eventDecl = 371, /* eventDecl */ + YYSYMBOL_propHead = 372, /* propHead */ + YYSYMBOL_propAttr = 373, /* propAttr */ + YYSYMBOL_propDecls = 374, /* propDecls */ + YYSYMBOL_propDecl = 375, /* propDecl */ + YYSYMBOL_methodHeadPart1 = 376, /* methodHeadPart1 */ + YYSYMBOL_marshalClause = 377, /* marshalClause */ + YYSYMBOL_marshalBlob = 378, /* marshalBlob */ + YYSYMBOL_marshalBlobHead = 379, /* marshalBlobHead */ + YYSYMBOL_methodHead = 380, /* methodHead */ + YYSYMBOL_methAttr = 381, /* methAttr */ + YYSYMBOL_pinvAttr = 382, /* pinvAttr */ + YYSYMBOL_methodName = 383, /* methodName */ + YYSYMBOL_paramAttr = 384, /* paramAttr */ + YYSYMBOL_implAttr = 385, /* implAttr */ + YYSYMBOL_localsHead = 386, /* localsHead */ + YYSYMBOL_methodDecls = 387, /* methodDecls */ + YYSYMBOL_methodDecl = 388, /* methodDecl */ + YYSYMBOL_scopeBlock = 389, /* scopeBlock */ + YYSYMBOL_scopeOpen = 390, /* scopeOpen */ + YYSYMBOL_sehBlock = 391, /* sehBlock */ + YYSYMBOL_sehClauses = 392, /* sehClauses */ + YYSYMBOL_tryBlock = 393, /* tryBlock */ + YYSYMBOL_tryHead = 394, /* tryHead */ + YYSYMBOL_sehClause = 395, /* sehClause */ + YYSYMBOL_filterClause = 396, /* filterClause */ + YYSYMBOL_filterHead = 397, /* filterHead */ + YYSYMBOL_catchClause = 398, /* catchClause */ + YYSYMBOL_finallyClause = 399, /* finallyClause */ + YYSYMBOL_faultClause = 400, /* faultClause */ + YYSYMBOL_handlerBlock = 401, /* handlerBlock */ + YYSYMBOL_dataDecl = 402, /* dataDecl */ + YYSYMBOL_ddHead = 403, /* ddHead */ + YYSYMBOL_tls = 404, /* tls */ + YYSYMBOL_ddBody = 405, /* ddBody */ + YYSYMBOL_ddItemList = 406, /* ddItemList */ + YYSYMBOL_ddItemCount = 407, /* ddItemCount */ + YYSYMBOL_ddItem = 408, /* ddItem */ + YYSYMBOL_fieldSerInit = 409, /* fieldSerInit */ + YYSYMBOL_bytearrayhead = 410, /* bytearrayhead */ + YYSYMBOL_bytes = 411, /* bytes */ + YYSYMBOL_hexbytes = 412, /* hexbytes */ + YYSYMBOL_fieldInit = 413, /* fieldInit */ + YYSYMBOL_serInit = 414, /* serInit */ + YYSYMBOL_f32seq = 415, /* f32seq */ + YYSYMBOL_f64seq = 416, /* f64seq */ + YYSYMBOL_i64seq = 417, /* i64seq */ + YYSYMBOL_i32seq = 418, /* i32seq */ + YYSYMBOL_i16seq = 419, /* i16seq */ + YYSYMBOL_i8seq = 420, /* i8seq */ + YYSYMBOL_boolSeq = 421, /* boolSeq */ + YYSYMBOL_sqstringSeq = 422, /* sqstringSeq */ + YYSYMBOL_classSeq = 423, /* classSeq */ + YYSYMBOL_objSeq = 424, /* objSeq */ + YYSYMBOL_methodSpec = 425, /* methodSpec */ + YYSYMBOL_instr_none = 426, /* instr_none */ + YYSYMBOL_instr_var = 427, /* instr_var */ + YYSYMBOL_instr_i = 428, /* instr_i */ + YYSYMBOL_instr_i8 = 429, /* instr_i8 */ + YYSYMBOL_instr_r = 430, /* instr_r */ + YYSYMBOL_instr_brtarget = 431, /* instr_brtarget */ + YYSYMBOL_instr_method = 432, /* instr_method */ + YYSYMBOL_instr_field = 433, /* instr_field */ + YYSYMBOL_instr_type = 434, /* instr_type */ + YYSYMBOL_instr_string = 435, /* instr_string */ + YYSYMBOL_instr_sig = 436, /* instr_sig */ + YYSYMBOL_instr_tok = 437, /* instr_tok */ + YYSYMBOL_instr_switch = 438, /* instr_switch */ + YYSYMBOL_instr_r_head = 439, /* instr_r_head */ + YYSYMBOL_instr = 440, /* instr */ + YYSYMBOL_labels = 441, /* labels */ + YYSYMBOL_tyArgs0 = 442, /* tyArgs0 */ + YYSYMBOL_tyArgs1 = 443, /* tyArgs1 */ + YYSYMBOL_tyArgs2 = 444, /* tyArgs2 */ + YYSYMBOL_sigArgs0 = 445, /* sigArgs0 */ + YYSYMBOL_sigArgs1 = 446, /* sigArgs1 */ + YYSYMBOL_sigArg = 447, /* sigArg */ + YYSYMBOL_className = 448, /* className */ + YYSYMBOL_slashedName = 449, /* slashedName */ + YYSYMBOL_typeSpec = 450, /* typeSpec */ + YYSYMBOL_nativeType = 451, /* nativeType */ + YYSYMBOL_iidParamIndex = 452, /* iidParamIndex */ + YYSYMBOL_variantType = 453, /* variantType */ + YYSYMBOL_type = 454, /* type */ + YYSYMBOL_simpleType = 455, /* simpleType */ + YYSYMBOL_bounds1 = 456, /* bounds1 */ + YYSYMBOL_bound = 457, /* bound */ + YYSYMBOL_secDecl = 458, /* secDecl */ + YYSYMBOL_secAttrSetBlob = 459, /* secAttrSetBlob */ + YYSYMBOL_secAttrBlob = 460, /* secAttrBlob */ + YYSYMBOL_psetHead = 461, /* psetHead */ + YYSYMBOL_nameValPairs = 462, /* nameValPairs */ + YYSYMBOL_nameValPair = 463, /* nameValPair */ + YYSYMBOL_truefalse = 464, /* truefalse */ + YYSYMBOL_caValue = 465, /* caValue */ + YYSYMBOL_secAction = 466, /* secAction */ + YYSYMBOL_esHead = 467, /* esHead */ + YYSYMBOL_extSourceSpec = 468, /* extSourceSpec */ + YYSYMBOL_fileDecl = 469, /* fileDecl */ + YYSYMBOL_fileAttr = 470, /* fileAttr */ + YYSYMBOL_fileEntry = 471, /* fileEntry */ + YYSYMBOL_hashHead = 472, /* hashHead */ + YYSYMBOL_assemblyHead = 473, /* assemblyHead */ + YYSYMBOL_asmAttr = 474, /* asmAttr */ + YYSYMBOL_assemblyDecls = 475, /* assemblyDecls */ + YYSYMBOL_assemblyDecl = 476, /* assemblyDecl */ + YYSYMBOL_intOrWildcard = 477, /* intOrWildcard */ + YYSYMBOL_asmOrRefDecl = 478, /* asmOrRefDecl */ + YYSYMBOL_publicKeyHead = 479, /* publicKeyHead */ + YYSYMBOL_publicKeyTokenHead = 480, /* publicKeyTokenHead */ + YYSYMBOL_localeHead = 481, /* localeHead */ + YYSYMBOL_assemblyRefHead = 482, /* assemblyRefHead */ + YYSYMBOL_assemblyRefDecls = 483, /* assemblyRefDecls */ + YYSYMBOL_assemblyRefDecl = 484, /* assemblyRefDecl */ + YYSYMBOL_exptypeHead = 485, /* exptypeHead */ + YYSYMBOL_exportHead = 486, /* exportHead */ + YYSYMBOL_exptAttr = 487, /* exptAttr */ + YYSYMBOL_exptypeDecls = 488, /* exptypeDecls */ + YYSYMBOL_exptypeDecl = 489, /* exptypeDecl */ + YYSYMBOL_manifestResHead = 490, /* manifestResHead */ + YYSYMBOL_manresAttr = 491, /* manresAttr */ + YYSYMBOL_manifestResDecls = 492, /* manifestResDecls */ + YYSYMBOL_manifestResDecl = 493 /* manifestResDecl */ +}; +typedef enum yysymbol_kind_t yysymbol_kind_t; + + + + +#ifdef short +# undef short #endif -#ifndef YYCHK -#define YYCHK yychk + +/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure + and (if available) are included + so that the code can choose integer types of a good width. */ + +#ifndef __PTRDIFF_MAX__ +# include /* INFRINGES ON USER NAME SPACE */ +# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_STDINT_H +# endif #endif -#ifndef YYDEF -#define YYDEF yydef + +/* Narrow types that promote to a signed type and that can represent a + signed or unsigned integer of at least N bits. In tables they can + save space and decrease cache pressure. Promoting to a signed type + helps avoid bugs in integer arithmetic. */ + +#ifdef __INT_LEAST8_MAX__ +typedef __INT_LEAST8_TYPE__ yytype_int8; +#elif defined YY_STDINT_H +typedef int_least8_t yytype_int8; +#else +typedef signed char yytype_int8; #endif -#ifndef YYV -#define YYV yyv + +#ifdef __INT_LEAST16_MAX__ +typedef __INT_LEAST16_TYPE__ yytype_int16; +#elif defined YY_STDINT_H +typedef int_least16_t yytype_int16; +#else +typedef short yytype_int16; #endif -#ifndef YYS -#define YYS yys + +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + . */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 #endif -#ifndef YYLOCAL -#define YYLOCAL + +#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST8_TYPE__ yytype_uint8; +#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST8_MAX <= INT_MAX) +typedef uint_least8_t yytype_uint8; +#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX +typedef unsigned char yytype_uint8; +#else +typedef short yytype_uint8; #endif -#ifndef YYR_T -#define YYR_T int + +#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST16_TYPE__ yytype_uint16; +#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST16_MAX <= INT_MAX) +typedef uint_least16_t yytype_uint16; +#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX +typedef unsigned short yytype_uint16; +#else +typedef int yytype_uint16; #endif -typedef YYR_T yyr_t; -#ifndef YYEXIND_T -#define YYEXIND_T unsigned int + +#ifndef YYPTRDIFF_T +# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ +# define YYPTRDIFF_T __PTRDIFF_TYPE__ +# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ +# elif defined PTRDIFF_MAX +# ifndef ptrdiff_t +# include /* INFRINGES ON USER NAME SPACE */ +# endif +# define YYPTRDIFF_T ptrdiff_t +# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX +# else +# define YYPTRDIFF_T long +# define YYPTRDIFF_MAXIMUM LONG_MAX +# endif #endif -typedef YYEXIND_T yyexind_t; -#ifndef YYOPTTIME -#define YYOPTTIME 0 + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned +# endif #endif -# define YYERRCODE 256 -#line 2063 "asmparse.y" +#define YYSIZE_MAXIMUM \ + YY_CAST (YYPTRDIFF_T, \ + (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ + ? YYPTRDIFF_MAXIMUM \ + : YY_CAST (YYSIZE_T, -1))) +#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) -#include "grammar_after.cpp" -YYSTATIC YYCONST short yyexca[] = { -#if !(YYOPTTIME) --1, 1, -#endif - 0, -1, - -2, 0, -#if !(YYOPTTIME) --1, 452, -#endif - 41, 540, - -2, 313, -#if !(YYOPTTIME) --1, 622, -#endif - 274, 557, - 47, 557, - -2, 232, -#if !(YYOPTTIME) --1, 643, -#endif - 40, 312, - 60, 312, - -2, 557, -#if !(YYOPTTIME) --1, 665, -#endif - 41, 540, - -2, 313, -#if !(YYOPTTIME) --1, 690, -#endif - 274, 557, - 47, 557, - -2, 518, -#if !(YYOPTTIME) --1, 811, -#endif - 123, 237, - -2, 557, -#if !(YYOPTTIME) --1, 838, + +/* Stored state numbers (used for stacks). */ +typedef yytype_int16 yy_state_t; + +/* State numbers in computations. */ +typedef int yy_state_fast_t; + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif #endif - 41, 540, - -2, 313, -#if !(YYOPTTIME) --1, 963, + + +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define YY_ATTRIBUTE_PURE +# endif #endif - 41, 540, - -2, 313, -#if !(YYOPTTIME) --1, 997, + +#ifndef YY_ATTRIBUTE_UNUSED +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +# else +# define YY_ATTRIBUTE_UNUSED +# endif #endif - 41, 540, - -2, 313, -#if !(YYOPTTIME) --1, 998, + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YY_USE(E) ((void) (E)) +#else +# define YY_USE(E) /* empty */ #endif - 41, 540, - -2, 313, -#if !(YYOPTTIME) --1, 1328, + +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") +# else +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# endif +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value #endif - 41, 540, - -2, 313, -#if !(YYOPTTIME) --1, 1329, +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END #endif - 41, 540, - -2, 313, -#if !(YYOPTTIME) --1, 1336, +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif - 41, 540, - -2, 313, -#if !(YYOPTTIME) --1, 1344, + +#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END \ + _Pragma ("GCC diagnostic pop") #endif - 41, 540, - -2, 313, -#if !(YYOPTTIME) --1, 1470, +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END #endif - 41, 540, - -2, 313, -#if !(YYOPTTIME) --1, 1502, + + +#define YY_ASSERT(E) ((void) (0 && (E))) + +#if !defined yyoverflow + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* !defined yyoverflow */ + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yy_state_t yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYPTRDIFF_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / YYSIZEOF (*yyptr); \ + } \ + while (0) + #endif - 41, 540, - -2, 313, -#if !(YYOPTTIME) --1, 1569, + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYPTRDIFF_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 2 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 3777 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 308 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 186 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 846 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 1590 + +/* YYMAXUTOK -- Last valid token kind. */ +#define YYMAXUTOK 543 + + +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ +#define YYTRANSLATE(YYX) \ + (0 <= (YYX) && (YYX) <= YYMAXUTOK \ + ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ + : YYSYMBOL_YYUNDEF) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex. */ +static const yytype_int16 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 307, 2, 2, 2, 2, 305, 2, + 294, 295, 304, 291, 292, 302, 293, 306, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 303, 296, + 300, 297, 301, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 298, 2, 299, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 289, 2, 290, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, + 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, + 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288 +}; + +#if YYDEBUG +/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_int16 yyrline[] = +{ + 0, 189, 189, 190, 193, 194, 195, 199, 200, 201, + 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, + 212, 222, 223, 226, 229, 230, 231, 232, 233, 234, + 237, 238, 241, 242, 245, 246, 248, 253, 254, 257, + 258, 259, 262, 265, 266, 269, 270, 271, 275, 276, + 277, 278, 279, 284, 285, 286, 287, 290, 293, 294, + 298, 299, 303, 304, 305, 306, 309, 310, 311, 313, + 316, 319, 325, 328, 329, 333, 339, 340, 342, 345, + 346, 352, 355, 356, 359, 363, 364, 372, 373, 374, + 375, 377, 379, 384, 385, 386, 393, 397, 398, 399, + 400, 401, 402, 405, 408, 412, 415, 418, 424, 427, + 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, + 448, 449, 450, 451, 452, 453, 456, 457, 460, 461, + 464, 465, 468, 469, 473, 474, 477, 478, 481, 482, + 485, 486, 487, 488, 489, 490, 491, 494, 495, 498, + 499, 502, 503, 506, 509, 510, 513, 517, 521, 522, + 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, + 538, 547, 548, 549, 554, 560, 561, 562, 569, 574, + 575, 576, 577, 578, 579, 580, 581, 593, 595, 596, + 597, 598, 599, 600, 601, 604, 605, 608, 609, 612, + 613, 617, 634, 640, 656, 661, 662, 663, 666, 667, + 668, 669, 672, 673, 674, 675, 676, 677, 678, 679, + 682, 685, 690, 694, 698, 700, 702, 707, 708, 712, + 713, 714, 717, 718, 721, 722, 723, 724, 725, 726, + 727, 728, 732, 738, 739, 740, 743, 744, 748, 749, + 750, 751, 752, 753, 754, 758, 764, 765, 768, 769, + 772, 775, 791, 792, 793, 794, 795, 796, 797, 798, + 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, + 809, 810, 811, 814, 817, 822, 823, 824, 825, 826, + 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, + 837, 840, 841, 842, 845, 846, 847, 848, 849, 852, + 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, + 863, 864, 865, 866, 867, 870, 874, 875, 878, 879, + 880, 881, 883, 886, 887, 888, 889, 890, 891, 892, + 893, 894, 895, 896, 906, 916, 918, 921, 928, 929, + 934, 940, 941, 943, 964, 967, 971, 974, 975, 978, + 979, 980, 984, 989, 990, 991, 992, 996, 997, 999, + 1003, 1007, 1012, 1016, 1020, 1021, 1022, 1027, 1030, 1031, + 1034, 1035, 1036, 1039, 1040, 1043, 1044, 1047, 1048, 1053, + 1054, 1055, 1056, 1063, 1070, 1077, 1084, 1092, 1100, 1101, + 1102, 1103, 1104, 1105, 1109, 1112, 1114, 1116, 1118, 1120, + 1122, 1124, 1126, 1128, 1130, 1132, 1134, 1136, 1138, 1140, + 1142, 1144, 1146, 1150, 1153, 1154, 1157, 1158, 1162, 1163, + 1164, 1169, 1170, 1171, 1173, 1175, 1177, 1178, 1179, 1183, + 1187, 1191, 1195, 1199, 1203, 1207, 1211, 1215, 1219, 1223, + 1227, 1231, 1235, 1239, 1243, 1247, 1251, 1258, 1259, 1261, + 1265, 1266, 1268, 1272, 1273, 1277, 1278, 1281, 1282, 1285, + 1286, 1289, 1290, 1294, 1295, 1296, 1300, 1301, 1302, 1304, + 1308, 1309, 1313, 1319, 1322, 1325, 1328, 1331, 1334, 1337, + 1345, 1348, 1351, 1354, 1357, 1360, 1363, 1367, 1368, 1369, + 1370, 1371, 1372, 1373, 1374, 1383, 1384, 1385, 1392, 1400, + 1408, 1414, 1420, 1426, 1430, 1431, 1433, 1435, 1439, 1445, + 1448, 1449, 1450, 1451, 1452, 1456, 1457, 1460, 1461, 1464, + 1465, 1469, 1470, 1473, 1474, 1477, 1478, 1479, 1483, 1484, + 1485, 1486, 1487, 1488, 1489, 1490, 1493, 1499, 1506, 1507, + 1510, 1511, 1512, 1513, 1517, 1518, 1525, 1531, 1533, 1536, + 1538, 1539, 1541, 1543, 1544, 1545, 1546, 1547, 1548, 1549, + 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, + 1561, 1563, 1568, 1573, 1576, 1578, 1580, 1581, 1582, 1583, + 1584, 1586, 1588, 1590, 1591, 1593, 1596, 1600, 1601, 1602, + 1603, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1615, + 1616, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, + 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, + 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, + 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, + 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, + 1671, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, + 1687, 1689, 1696, 1703, 1709, 1715, 1730, 1745, 1746, 1747, + 1748, 1749, 1750, 1751, 1754, 1755, 1756, 1757, 1758, 1759, + 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, + 1770, 1771, 1774, 1775, 1778, 1779, 1780, 1781, 1784, 1788, + 1790, 1792, 1793, 1794, 1796, 1805, 1806, 1807, 1810, 1813, + 1818, 1819, 1823, 1824, 1827, 1830, 1831, 1834, 1837, 1840, + 1843, 1847, 1853, 1859, 1865, 1873, 1874, 1875, 1876, 1877, + 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, + 1891, 1892, 1895, 1898, 1900, 1903, 1905, 1909, 1912, 1916, + 1919, 1923, 1926, 1932, 1934, 1937, 1938, 1941, 1942, 1945, + 1948, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, + 1960, 1963, 1964, 1967, 1968, 1969, 1972, 1973, 1976, 1977, + 1979, 1980, 1981, 1982, 1985, 1988, 1991, 1994, 1996, 2000, + 2001, 2004, 2005, 2006, 2007, 2010, 2013, 2016, 2017, 2018, + 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2028, 2029, 2032, + 2033, 2034, 2035, 2037, 2039, 2040, 2043, 2044, 2048, 2049, + 2050, 2053, 2054, 2057, 2058, 2059, 2060 +}; #endif - 41, 540, - -2, 313, -#if !(YYOPTTIME) --1, 1586, + +/** Accessing symbol of state STATE. */ +#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) + +#if YYDEBUG || 0 +/* The user-facing name of the symbol whose (internal) number is + YYSYMBOL. No bounds checking. */ +static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; + +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "\"end of file\"", "error", "\"invalid token\"", "BAD_COMMENT_", + "BAD_LITERAL_", "ID", "DOTTEDNAME", "QSTRING", "SQSTRING", "INT32_V", + "INT64_V", "FLOAT64", "HEXBYTE", "TYPEDEF_T", "TYPEDEF_M", "TYPEDEF_F", + "TYPEDEF_TS", "TYPEDEF_MR", "TYPEDEF_CA", "DCOLON", "ELLIPSIS", "VOID_", + "BOOL_", "CHAR_", "UNSIGNED_", "INT_", "INT8_", "INT16_", "INT32_", + "INT64_", "FLOAT_", "FLOAT32_", "FLOAT64_", "BYTEARRAY_", "UINT_", + "UINT8_", "UINT16_", "UINT32_", "UINT64_", "FLAGS_", "CALLCONV_", + "MDTOKEN_", "OBJECT_", "STRING_", "NULLREF_", "DEFAULT_", "CDECL_", + "VARARG_", "STDCALL_", "THISCALL_", "FASTCALL_", "CLASS_", "BYREFLIKE_", + "TYPEDREF_", "UNMANAGED_", "FINALLY_", "HANDLER_", "CATCH_", "FILTER_", + "FAULT_", "EXTENDS_", "IMPLEMENTS_", "TO_", "AT_", "TLS_", "TRUE_", + "FALSE_", "_INTERFACEIMPL", "VALUE_", "VALUETYPE_", "NATIVE_", + "INSTANCE_", "SPECIALNAME_", "FORWARDER_", "STATIC_", "PUBLIC_", + "PRIVATE_", "FAMILY_", "FINAL_", "SYNCHRONIZED_", "INTERFACE_", + "SEALED_", "NESTED_", "ABSTRACT_", "AUTO_", "SEQUENTIAL_", "EXPLICIT_", + "ANSI_", "UNICODE_", "AUTOCHAR_", "IMPORT_", "ENUM_", "VIRTUAL_", + "NOINLINING_", "AGGRESSIVEINLINING_", "NOOPTIMIZATION_", + "AGGRESSIVEOPTIMIZATION_", "UNMANAGEDEXP_", "BEFOREFIELDINIT_", + "STRICT_", "RETARGETABLE_", "WINDOWSRUNTIME_", "NOPLATFORM_", "METHOD_", + "FIELD_", "PINNED_", "MODREQ_", "MODOPT_", "SERIALIZABLE_", "PROPERTY_", + "TYPE_", "ASSEMBLY_", "FAMANDASSEM_", "FAMORASSEM_", "PRIVATESCOPE_", + "HIDEBYSIG_", "NEWSLOT_", "RTSPECIALNAME_", "PINVOKEIMPL_", "_CTOR", + "_CCTOR", "LITERAL_", "NOTSERIALIZED_", "INITONLY_", "REQSECOBJ_", + "CIL_", "OPTIL_", "MANAGED_", "FORWARDREF_", "PRESERVESIG_", "RUNTIME_", + "INTERNALCALL_", "_IMPORT", "NOMANGLE_", "LASTERR_", "WINAPI_", "AS_", + "BESTFIT_", "ON_", "OFF_", "CHARMAPERROR_", "INSTR_NONE", "INSTR_VAR", + "INSTR_I", "INSTR_I8", "INSTR_R", "INSTR_BRTARGET", "INSTR_METHOD", + "INSTR_FIELD", "INSTR_TYPE", "INSTR_STRING", "INSTR_SIG", "INSTR_TOK", + "INSTR_SWITCH", "_CLASS", "_NAMESPACE", "_METHOD", "_FIELD", "_DATA", + "_THIS", "_BASE", "_NESTER", "_EMITBYTE", "_TRY", "_MAXSTACK", "_LOCALS", + "_ENTRYPOINT", "_ZEROINIT", "_EVENT", "_ADDON", "_REMOVEON", "_FIRE", + "_OTHER", "_PROPERTY", "_SET", "_GET", "_PERMISSION", "_PERMISSIONSET", + "REQUEST_", "DEMAND_", "ASSERT_", "DENY_", "PERMITONLY_", "LINKCHECK_", + "INHERITCHECK_", "REQMIN_", "REQOPT_", "REQREFUSE_", "PREJITGRANT_", + "PREJITDENY_", "NONCASDEMAND_", "NONCASLINKDEMAND_", + "NONCASINHERITANCE_", "_LINE", "P_LINE", "_LANGUAGE", "_CUSTOM", "INIT_", + "_SIZE", "_PACK", "_VTABLE", "_VTFIXUP", "FROMUNMANAGED_", + "CALLMOSTDERIVED_", "_VTENTRY", "RETAINAPPDOMAIN_", "_FILE", + "NOMETADATA_", "_HASH", "_ASSEMBLY", "_PUBLICKEY", "_PUBLICKEYTOKEN", + "ALGORITHM_", "_VER", "_LOCALE", "EXTERN_", "_MRESOURCE", "_MODULE", + "_EXPORT", "LEGACY_", "LIBRARY_", "X86_", "AMD64_", "ARM_", "ARM64_", + "MARSHAL_", "CUSTOM_", "SYSSTRING_", "FIXED_", "VARIANT_", "CURRENCY_", + "SYSCHAR_", "DECIMAL_", "DATE_", "BSTR_", "TBSTR_", "LPSTR_", "LPWSTR_", + "LPTSTR_", "OBJECTREF_", "IUNKNOWN_", "IDISPATCH_", "STRUCT_", + "SAFEARRAY_", "BYVALSTR_", "LPVOID_", "ANY_", "ARRAY_", "LPSTRUCT_", + "IIDPARAM_", "IN_", "OUT_", "OPT_", "_PARAM", "_OVERRIDE", "WITH_", + "NULL_", "ERROR_", "HRESULT_", "CARRAY_", "USERDEFINED_", "RECORD_", + "FILETIME_", "BLOB_", "STREAM_", "STORAGE_", "STREAMED_OBJECT_", + "STORED_OBJECT_", "BLOB_OBJECT_", "CF_", "CLSID_", "VECTOR_", + "_SUBSYSTEM", "_CORFLAGS", "ALIGNMENT_", "_IMAGEBASE", "_STACKRESERVE", + "_TYPEDEF", "_TEMPLATE", "_TYPELIST", "_MSCORLIB", "P_DEFINE", "P_UNDEF", + "P_IFDEF", "P_IFNDEF", "P_ELSE", "P_ENDIF", "P_INCLUDE", "CONSTRAINT_", + "'{'", "'}'", "'+'", "','", "'.'", "'('", "')'", "';'", "'='", "'['", + "']'", "'<'", "'>'", "'-'", "':'", "'*'", "'&'", "'/'", "'!'", "$accept", + "decls", "decl", "classNameSeq", "compQstring", "languageDecl", "id", + "dottedName", "int32", "int64", "float64", "typedefDecl", "compControl", + "customDescr", "customDescrWithOwner", "customHead", + "customHeadWithOwner", "customType", "ownerType", "customBlobDescr", + "customBlobArgs", "customBlobNVPairs", "fieldOrProp", "customAttrDecl", + "serializType", "moduleHead", "vtfixupDecl", "vtfixupAttr", "vtableDecl", + "vtableHead", "nameSpaceHead", "_class", "classHeadBegin", "classHead", + "classAttr", "extendsClause", "implClause", "classDecls", "implList", + "typeList", "typeListNotEmpty", "typarsClause", "typarAttrib", + "typarAttribs", "typars", "typarsRest", "tyBound", "genArity", + "genArityNotEmpty", "classDecl", "fieldDecl", "fieldAttr", "atOpt", + "initOpt", "repeatOpt", "methodRef", "callConv", "callKind", "mdtoken", + "memberRef", "eventHead", "eventAttr", "eventDecls", "eventDecl", + "propHead", "propAttr", "propDecls", "propDecl", "methodHeadPart1", + "marshalClause", "marshalBlob", "marshalBlobHead", "methodHead", + "methAttr", "pinvAttr", "methodName", "paramAttr", "implAttr", + "localsHead", "methodDecls", "methodDecl", "scopeBlock", "scopeOpen", + "sehBlock", "sehClauses", "tryBlock", "tryHead", "sehClause", + "filterClause", "filterHead", "catchClause", "finallyClause", + "faultClause", "handlerBlock", "dataDecl", "ddHead", "tls", "ddBody", + "ddItemList", "ddItemCount", "ddItem", "fieldSerInit", "bytearrayhead", + "bytes", "hexbytes", "fieldInit", "serInit", "f32seq", "f64seq", + "i64seq", "i32seq", "i16seq", "i8seq", "boolSeq", "sqstringSeq", + "classSeq", "objSeq", "methodSpec", "instr_none", "instr_var", "instr_i", + "instr_i8", "instr_r", "instr_brtarget", "instr_method", "instr_field", + "instr_type", "instr_string", "instr_sig", "instr_tok", "instr_switch", + "instr_r_head", "instr", "labels", "tyArgs0", "tyArgs1", "tyArgs2", + "sigArgs0", "sigArgs1", "sigArg", "className", "slashedName", "typeSpec", + "nativeType", "iidParamIndex", "variantType", "type", "simpleType", + "bounds1", "bound", "secDecl", "secAttrSetBlob", "secAttrBlob", + "psetHead", "nameValPairs", "nameValPair", "truefalse", "caValue", + "secAction", "esHead", "extSourceSpec", "fileDecl", "fileAttr", + "fileEntry", "hashHead", "assemblyHead", "asmAttr", "assemblyDecls", + "assemblyDecl", "intOrWildcard", "asmOrRefDecl", "publicKeyHead", + "publicKeyTokenHead", "localeHead", "assemblyRefHead", + "assemblyRefDecls", "assemblyRefDecl", "exptypeHead", "exportHead", + "exptAttr", "exptypeDecls", "exptypeDecl", "manifestResHead", + "manresAttr", "manifestResDecls", "manifestResDecl", YY_NULLPTR +}; + +static const char * +yysymbol_name (yysymbol_kind_t yysymbol) +{ + return yytname[yysymbol]; +} #endif - 41, 540, - -2, 313, +#define YYPACT_NINF (-1367) + +#define yypact_value_is_default(Yyn) \ + ((Yyn) == YYPACT_NINF) + +#define YYTABLE_NINF (-559) + +#define yytable_value_is_error(Yyn) \ + 0 + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int16 yypact[] = +{ + -1367, 2062, -1367, -1367, -51, 987, -1367, -86, 123, 2317, + 2317, -1367, -1367, 246, 182, -31, -19, 16, 105, -1367, + 133, 272, 272, 215, 215, 1641, 9, -1367, 987, 987, + 987, 987, -1367, -1367, 315, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, 320, 320, -1367, -1367, -1367, -1367, 320, 74, + -1367, 285, 103, -1367, -1367, -1367, -1367, 729, -1367, 320, + 272, -1367, -1367, 116, 144, 167, 169, -1367, -1367, -1367, + -1367, -1367, 191, 272, -1367, -1367, -1367, 368, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, 1929, 43, 58, -1367, -1367, 181, 195, + -1367, -1367, 824, 502, 502, 1825, 166, -1367, 2925, -1367, + -1367, 202, 272, 272, 238, -1367, 620, 849, 987, 191, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, 2925, + -1367, -1367, -1367, 894, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, 589, -1367, 418, 589, + 378, -1367, 2339, -1367, -1367, -1367, 67, 50, 191, 373, + 387, -1367, 404, 1377, 414, 254, 745, -1367, 589, 45, + 191, 191, 191, -1367, -1367, 282, 579, 301, 314, -1367, + 3481, 1929, 557, -1367, 3653, 2269, 335, 17, 93, 276, + 281, 291, 317, 347, 782, 358, -1367, -1367, 320, 359, + 61, -1367, -1367, -1367, -1367, 1130, 987, 385, 2715, 380, + 95, -1367, 502, -1367, 330, 926, -1367, 402, -11, 413, + 664, 272, 272, -1367, -1367, -1367, -1367, -1367, -1367, 432, + -1367, -1367, 91, 1273, -1367, 447, -1367, -1367, 69, 620, + -1367, -1367, -1367, -1367, 533, -1367, -1367, -1367, -1367, 191, + -1367, -1367, -34, 191, 926, -1367, -1367, -1367, -1367, -1367, + 589, -1367, 741, -1367, -1367, -1367, -1367, 1582, 987, 483, + 4, 523, 472, 191, -1367, 987, 987, 987, -1367, 2925, + 987, 987, -1367, 507, 536, 987, 68, 2925, -1367, -1367, + 490, 589, 413, -1367, -1367, -1367, -1367, 2862, 539, -1367, + -1367, -1367, -1367, -1367, -1367, 803, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -135, + -1367, 1929, -1367, 3003, 543, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, 562, -1367, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, 272, -1367, + 272, -1367, -1367, -1367, 272, 529, 11, 1999, -1367, -1367, + -1367, 537, -1367, -1367, -44, -1367, -1367, -1367, -1367, 546, + 208, -1367, -1367, 503, 272, 215, 296, 503, 1377, 985, + 1929, 171, 502, 1825, 582, 320, -1367, -1367, -1367, 588, + 272, 272, -1367, 272, -1367, 272, -1367, 215, -1367, 303, + -1367, 303, -1367, -1367, 559, 594, 368, 596, -1367, -1367, + -1367, 272, 272, 954, 3164, 1071, 581, -1367, -1367, -1367, + 868, 191, 191, -1367, 599, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, 607, 56, + -1367, 987, 44, 2925, 905, 629, -1367, 2093, -1367, 923, + 641, 651, 655, 1377, -1367, -1367, 413, -1367, -1367, 85, + 38, 654, 937, -1367, -1367, 763, -4, -1367, 987, -1367, + -1367, 38, 955, 107, 987, 987, 987, 191, -1367, 191, + 191, 191, 1433, 191, 191, 1929, 1929, 191, -1367, -1367, + 940, -62, -1367, 674, 690, 926, -1367, -1367, -1367, 272, + -1367, -1367, -1367, -1367, -1367, -1367, 222, -1367, 691, -1367, + 874, -1367, -1367, -1367, 272, 272, -1367, 25, 2162, -1367, + -1367, -1367, -1367, 702, -1367, -1367, 707, 714, -1367, -1367, + -1367, -1367, 715, 272, 905, 2819, -1367, -1367, 712, 272, + 111, 137, 272, 502, 1000, -1367, 735, 100, 2432, -1367, + 1929, -1367, -1367, -1367, 546, 28, 208, 28, 28, 28, + 968, 973, -1367, -1367, -1367, -1367, -1367, -1367, 743, 750, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, 1582, + -1367, 753, 413, 320, 2925, -1367, 503, 751, 905, 756, + 749, 757, 761, 762, 765, 766, -1367, 782, 767, -1367, + 755, 55, 862, 785, 21, 82, -1367, -1367, -1367, -1367, + -1367, -1367, 320, 320, -1367, 786, 788, -1367, 320, -1367, + 320, -1367, 792, 73, 987, 876, -1367, -1367, -1367, -1367, + 987, 877, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, 272, 3377, 8, 121, 987, 1085, 27, 798, + 806, -1367, 675, 802, 810, 809, -1367, 1100, -1367, -1367, + 825, 836, 3058, 2874, 839, 840, 575, 996, 320, 987, + 191, 987, 987, 254, 254, 254, 846, 848, 850, 272, + 146, -1367, -1367, 2925, 854, 847, -1367, -1367, -1367, -1367, + -1367, -1367, 222, 125, 843, 1929, 1929, 1741, 752, -1367, + -1367, 1130, 142, 164, 502, 1139, -1367, -1367, -1367, 2516, + -1367, 864, 1, 2005, 209, 426, 272, 873, 272, 191, + 272, 237, 878, 2925, 575, 100, -1367, 2819, 866, 881, + -1367, -1367, -1367, -1367, 503, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, 368, 272, 272, 215, 38, 1144, 905, + 883, 871, 887, 888, 893, -1367, 225, 884, -1367, 884, + 884, 884, 884, 884, -1367, -1367, 272, -1367, 272, 272, + 889, -1367, -1367, 886, 899, 413, 902, 907, 910, 913, + 915, 918, 272, 987, -1367, 191, 987, 15, 987, 919, + -1367, -1367, -1367, 791, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, 914, 976, 981, -1367, + 974, 925, -7, 1199, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, 914, 914, -1367, 2977, -1367, -1367, + -1367, -1367, 927, 320, 149, 368, 932, 987, 486, -1367, + 905, 933, 935, 944, -1367, 2093, -1367, 92, -1367, 355, + 365, 941, 375, 381, 388, 395, 403, 411, 417, 419, + 425, 434, 439, 441, 449, -1367, 1230, -1367, 320, -1367, + 272, 942, 100, 100, 191, 654, -1367, -1367, 368, -1367, + -1367, -1367, 939, 191, 191, 254, 100, -1367, -1367, -1367, + -1367, 926, -1367, 272, -1367, 1929, 374, 987, -1367, -1367, + 1046, -1367, -1367, 470, 987, -1367, -1367, 2925, 191, 272, + 191, 272, 481, 2925, 575, 3138, 870, 1533, -1367, 1129, + -1367, 905, 2196, 951, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, 943, 948, -1367, 956, 957, 967, + 969, 953, 575, -1367, 1117, 970, 971, 1929, 932, 1582, + -1367, 977, 426, -1367, 1251, 1211, 1212, -1367, -1367, 990, + 992, 987, 476, -1367, 100, 503, 503, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, 66, 1268, -1367, -1367, 21, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, 993, 254, 191, + 272, 191, -1367, -1367, -1367, -1367, -1367, -1367, 1033, -1367, + -1367, -1367, -1367, 905, 1005, 1008, -1367, -1367, -1367, -1367, + -1367, 879, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, + 363, -1367, 31, 78, -1367, -1367, 2281, -1367, 997, -1367, + -1367, 413, -1367, 1004, -1367, -1367, -1367, -1367, 1001, -1367, + -1367, -1367, -1367, 413, 780, 272, 272, 272, 485, 500, + 509, 527, 272, 272, 272, 272, 272, 272, 215, 272, + 633, 272, 555, 272, 272, 272, 272, 272, 272, 272, + 215, 272, 3468, 272, 189, 272, 497, 272, -1367, -1367, + -1367, 3236, 1012, 1013, -1367, 1018, 1022, 1024, 1025, -1367, + 1154, 1026, 1028, 1032, 1036, -1367, 222, -1367, 374, 1377, + -1367, 191, 56, 1030, 1031, 1929, 1582, 1076, -1367, 1377, + 1377, 1377, 1377, -1367, -1367, -1367, -1367, -1367, -1367, 1377, + 1377, 1377, -1367, -1367, -1367, -1367, -1367, -1367, -1367, 413, + -1367, 272, 430, 722, -1367, -1367, -1367, -1367, 3377, 1037, + 368, -1367, 1040, -1367, -1367, 1317, -1367, 368, -1367, 368, + 272, -1367, -1367, 191, -1367, 1045, -1367, -1367, -1367, 272, + -1367, 1042, -1367, -1367, 1049, 619, 272, 272, -1367, -1367, + -1367, -1367, -1367, -1367, 905, 1048, -1367, -1367, 272, -1367, + -39, 1054, 1055, 1041, 1056, 1065, 1066, 1068, 1069, 1072, + 1074, 1077, 1078, 1079, -1367, 413, -1367, -1367, 272, 742, + -1367, 794, 1080, 1082, 1075, 1086, 1083, 272, 272, 272, + 272, 272, 272, 215, 272, 1089, 1088, 1101, 1096, 1103, + 1102, 1104, 1105, 1107, 1110, 1108, 1111, 1113, 1121, 1114, + 1122, 1128, 1127, 1132, 1131, 1133, 1141, 1134, 1143, 1148, + 1149, 1146, 1152, 1367, 1155, 1153, -1367, 531, -1367, 168, + -1367, -1367, 1099, -1367, -1367, 100, 100, -1367, -1367, -1367, + -1367, 1929, -1367, -1367, 643, -1367, 1159, -1367, 1439, 502, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, 2405, 1171, -1367, + -1367, -1367, -1367, 1172, 1183, -1367, 1929, 575, -1367, -1367, + -1367, -1367, 1470, 21, 272, 905, 1180, 1182, 413, -1367, + 1184, 272, -1367, 1188, 1191, 1194, 1195, 1196, 1187, 1192, + 1201, 1202, 1260, -1367, -1367, -1367, 1213, -1367, 1216, 1210, + 1207, 1223, 1220, 1228, 1225, 1232, 1226, -1367, 1234, -1367, + 1235, -1367, 1236, -1367, 1237, -1367, -1367, 1238, -1367, -1367, + 1239, -1367, 1240, -1367, 1241, -1367, 1254, -1367, 1255, -1367, + 1261, -1367, -1367, 1263, -1367, 1259, -1367, 1265, 1552, -1367, + 1262, 535, -1367, 1267, 1269, -1367, 100, 1929, 575, 2925, + -1367, -1367, -1367, 100, -1367, 1266, -1367, 1264, 1270, 266, + -1367, 3447, -1367, 1271, -1367, 272, 272, 272, -1367, -1367, + -1367, -1367, -1367, 1274, -1367, 1275, -1367, 1278, -1367, 1280, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, 3468, -1367, -1367, 1281, + -1367, 1266, 1582, 1286, 1277, 1288, -1367, 21, -1367, 905, + -1367, 149, -1367, 1289, 1290, 1291, 176, 57, -1367, -1367, + -1367, -1367, 83, 87, 101, 170, 175, 179, 106, 109, + 162, 173, 1881, 148, 477, -1367, 932, 1295, 1544, -1367, + 100, -1367, 635, -1367, -1367, -1367, -1367, -1367, -1367, -1367, + 205, 206, 212, 193, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, 1583, -1367, -1367, + -1367, 100, 575, 2387, 1301, 905, -1367, -1367, -1367, -1367, + -1367, 1302, 1305, 1306, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, + 505, 1346, 100, 272, -1367, 1504, 1320, 1321, 502, -1367, + -1367, 2925, 1582, 1593, 575, 1266, 1327, 100, 1331, -1367 }; -# define YYNPROD 846 -#if YYOPTTIME -YYSTATIC YYCONST yyexind_t yyexcaind[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 42, 46, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 50, 54, - 0, 0, 0, 0, 0, 0, 58, 0, 0, 0, - 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 70, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 78 +/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_int16 yydefact[] = +{ + 2, 0, 1, 86, 106, 0, 265, 209, 390, 0, + 0, 760, 761, 0, 222, 0, 0, 775, 781, 838, + 93, 0, 0, 0, 0, 0, 0, 29, 0, 0, + 0, 0, 58, 59, 0, 61, 3, 25, 26, 27, + 84, 85, 434, 434, 19, 17, 10, 9, 434, 0, + 109, 136, 0, 7, 272, 336, 8, 0, 18, 434, + 0, 11, 12, 0, 0, 0, 0, 817, 37, 40, + 38, 39, 105, 0, 189, 391, 392, 389, 745, 746, + 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, + 757, 758, 759, 0, 0, 34, 216, 217, 0, 0, + 223, 224, 229, 222, 222, 0, 62, 72, 0, 220, + 215, 0, 0, 0, 0, 781, 0, 0, 0, 94, + 42, 20, 21, 44, 43, 23, 24, 554, 711, 0, + 688, 696, 694, 0, 697, 698, 699, 700, 701, 702, + 707, 708, 709, 710, 671, 695, 0, 687, 0, 0, + 0, 492, 0, 555, 556, 557, 0, 0, 558, 0, + 0, 236, 0, 222, 0, 552, 0, 692, 30, 53, + 55, 56, 57, 60, 436, 0, 435, 0, 0, 2, + 0, 0, 138, 140, 222, 0, 0, 397, 397, 397, + 397, 397, 397, 0, 0, 0, 387, 394, 434, 0, + 763, 791, 809, 827, 841, 0, 0, 0, 0, 0, + 0, 553, 222, 560, 721, 563, 32, 0, 0, 723, + 0, 0, 0, 225, 226, 227, 228, 218, 219, 0, + 74, 73, 0, 0, 104, 0, 22, 776, 777, 0, + 782, 783, 784, 786, 0, 787, 788, 789, 790, 780, + 839, 840, 836, 95, 693, 703, 704, 705, 706, 670, + 0, 673, 0, 689, 691, 234, 235, 0, 0, 0, + 0, 0, 0, 686, 684, 0, 0, 0, 231, 0, + 0, 0, 678, 0, 0, 0, 714, 537, 677, 676, + 0, 30, 54, 65, 437, 69, 103, 0, 0, 112, + 133, 110, 111, 114, 115, 0, 116, 117, 118, 119, + 120, 121, 122, 123, 113, 132, 125, 124, 134, 148, + 137, 0, 108, 0, 0, 278, 273, 274, 275, 276, + 277, 281, 279, 289, 280, 282, 283, 284, 285, 286, + 287, 288, 0, 290, 314, 493, 494, 495, 496, 497, + 498, 499, 500, 501, 502, 503, 504, 505, 0, 372, + 0, 335, 343, 344, 0, 0, 0, 0, 365, 6, + 350, 0, 352, 351, 0, 337, 358, 336, 339, 0, + 0, 345, 507, 0, 0, 0, 0, 0, 222, 0, + 0, 0, 222, 0, 0, 434, 346, 348, 349, 0, + 0, 0, 413, 0, 412, 0, 411, 0, 410, 0, + 408, 0, 409, 433, 0, 396, 0, 0, 722, 772, + 762, 0, 0, 0, 0, 0, 0, 820, 819, 818, + 0, 815, 41, 210, 0, 196, 190, 191, 192, 193, + 198, 199, 200, 201, 195, 202, 203, 194, 0, 0, + 388, 0, 0, 0, 0, 0, 731, 725, 730, 0, + 35, 0, 0, 222, 76, 70, 63, 311, 312, 714, + 313, 535, 0, 97, 778, 774, 807, 785, 0, 672, + 690, 233, 0, 0, 0, 0, 0, 685, 683, 51, + 52, 50, 0, 49, 559, 0, 0, 48, 715, 674, + 716, 0, 712, 0, 538, 539, 28, 31, 5, 0, + 126, 127, 128, 129, 130, 131, 157, 107, 139, 143, + 0, 106, 239, 253, 0, 0, 817, 0, 0, 4, + 181, 182, 175, 0, 141, 171, 0, 0, 336, 172, + 173, 174, 0, 0, 295, 0, 338, 340, 0, 0, + 0, 0, 0, 222, 0, 347, 0, 314, 0, 382, + 0, 380, 383, 366, 368, 0, 0, 0, 0, 0, + 0, 0, 369, 509, 508, 510, 511, 45, 0, 0, + 506, 513, 512, 516, 515, 517, 521, 522, 520, 0, + 523, 0, 524, 434, 0, 528, 530, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 393, 0, 0, 401, + 0, 765, 0, 0, 0, 0, 13, 803, 802, 794, + 792, 795, 434, 434, 814, 0, 0, 14, 434, 812, + 434, 810, 0, 0, 0, 0, 15, 835, 834, 828, + 0, 0, 16, 846, 845, 842, 821, 822, 823, 824, + 825, 826, 0, 564, 205, 0, 561, 0, 0, 0, + 732, 76, 0, 0, 0, 726, 33, 0, 221, 230, + 66, 0, 79, 537, 0, 0, 0, 0, 434, 0, + 837, 0, 0, 550, 548, 549, 677, 0, 0, 718, + 714, 675, 682, 0, 0, 0, 152, 154, 153, 155, + 150, 151, 157, 0, 0, 0, 0, 0, 222, 176, + 177, 0, 0, 0, 222, 0, 140, 242, 256, 0, + 827, 0, 295, 0, 0, 266, 0, 0, 0, 360, + 0, 0, 0, 0, 0, 314, 545, 0, 0, 542, + 543, 364, 381, 367, 0, 384, 374, 378, 379, 377, + 373, 375, 376, 0, 0, 0, 0, 519, 0, 0, + 0, 0, 533, 534, 0, 514, 0, 397, 398, 397, + 397, 397, 397, 397, 395, 400, 0, 764, 0, 0, + 0, 797, 796, 0, 0, 800, 0, 0, 0, 0, + 0, 0, 0, 0, 833, 829, 0, 0, 0, 0, + 618, 572, 573, 0, 607, 574, 575, 576, 577, 578, + 579, 609, 585, 586, 587, 588, 619, 0, 0, 615, + 0, 0, 0, 569, 570, 571, 594, 595, 596, 613, + 597, 598, 599, 600, 619, 619, 603, 621, 611, 617, + 580, 270, 0, 0, 268, 0, 207, 562, 0, 719, + 0, 0, 38, 0, 724, 725, 36, 0, 64, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 78, 75, 441, 434, 77, + 0, 0, 314, 314, 313, 535, 98, 99, 0, 100, + 101, 102, 0, 808, 232, 551, 314, 679, 680, 717, + 713, 540, 135, 0, 158, 144, 161, 0, 149, 142, + 0, 241, 240, 558, 0, 255, 254, 0, 816, 0, + 184, 0, 0, 0, 0, 0, 0, 0, 167, 0, + 291, 0, 0, 0, 302, 303, 304, 305, 297, 298, + 299, 296, 300, 301, 0, 0, 294, 0, 0, 0, + 0, 0, 0, 355, 353, 0, 0, 0, 207, 0, + 356, 0, 266, 341, 314, 0, 0, 370, 371, 0, + 0, 0, 0, 526, 314, 530, 530, 529, 399, 407, + 406, 405, 404, 402, 403, 769, 767, 793, 804, 0, + 806, 798, 801, 779, 805, 811, 813, 0, 830, 831, + 0, 844, 204, 608, 581, 582, 583, 584, 0, 604, + 610, 612, 616, 0, 0, 0, 614, 601, 602, 625, + 626, 0, 653, 627, 628, 629, 630, 631, 632, 655, + 637, 638, 639, 640, 623, 624, 645, 646, 647, 648, + 649, 650, 651, 652, 622, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 641, + 605, 197, 0, 0, 589, 206, 0, 188, 0, 735, + 736, 740, 738, 0, 737, 734, 733, 720, 0, 79, + 727, 76, 71, 67, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 82, 83, + 81, 0, 0, 0, 536, 0, 0, 0, 0, 96, + 777, 0, 0, 0, 145, 146, 157, 160, 161, 222, + 187, 237, 0, 0, 0, 0, 0, 0, 168, 222, + 222, 222, 222, 169, 250, 251, 249, 243, 248, 222, + 222, 222, 170, 263, 264, 261, 257, 262, 178, 295, + 293, 0, 0, 0, 315, 316, 317, 318, 564, 148, + 0, 359, 0, 362, 363, 0, 342, 546, 544, 0, + 0, 46, 47, 518, 525, 0, 531, 532, 768, 0, + 766, 0, 832, 843, 0, 0, 0, 0, 654, 633, + 634, 635, 636, 643, 0, 0, 644, 269, 0, 590, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 440, 439, 438, 208, 0, 0, + 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 89, 0, 88, 0, + 87, 432, 0, 214, 213, 314, 314, 773, 681, 156, + 163, 0, 162, 159, 0, 183, 0, 186, 0, 222, + 244, 245, 246, 247, 260, 258, 259, 0, 0, 306, + 307, 308, 309, 0, 0, 354, 0, 0, 547, 385, + 386, 527, 771, 0, 0, 0, 0, 0, 606, 642, + 0, 0, 591, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 728, 68, 431, 0, 430, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 421, 0, 420, + 0, 419, 0, 418, 0, 416, 414, 0, 417, 415, + 0, 429, 0, 428, 0, 427, 0, 426, 0, 447, + 0, 443, 442, 0, 446, 0, 445, 0, 0, 91, + 0, 0, 166, 0, 0, 147, 314, 0, 0, 0, + 292, 310, 267, 314, 361, 164, 770, 0, 0, 0, + 567, 564, 593, 0, 739, 0, 0, 0, 744, 729, + 481, 477, 425, 0, 424, 0, 423, 0, 422, 0, + 479, 477, 475, 473, 467, 470, 479, 477, 475, 473, + 490, 483, 444, 486, 90, 92, 0, 212, 211, 0, + 185, 164, 0, 0, 0, 0, 165, 0, 620, 0, + 566, 568, 592, 0, 0, 0, 0, 0, 479, 477, + 475, 473, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 80, 207, 0, 0, 319, + 314, 799, 0, 741, 742, 743, 463, 482, 462, 478, + 0, 0, 0, 0, 453, 480, 452, 451, 476, 450, + 474, 448, 469, 468, 449, 472, 471, 457, 456, 455, + 454, 466, 491, 485, 484, 464, 487, 0, 465, 489, + 252, 314, 0, 0, 0, 0, 461, 460, 459, 458, + 488, 0, 0, 0, 324, 320, 329, 330, 331, 332, + 333, 321, 322, 323, 325, 326, 327, 328, 271, 357, + 0, 0, 314, 0, 565, 0, 0, 0, 222, 179, + 334, 0, 0, 0, 0, 164, 0, 314, 0, 180 }; -#endif -# define YYLAST 3872 - -YYSTATIC YYCONST short YYFARDATA YYACT[] = { - 703, 1421, 1136, 640, 660, 1490, 191, 1039, 888, 974, - 1489, 790, 1488, 702, 1487, 1149, 625, 779, 887, 729, - 73, 75, 150, 414, 536, 977, 1422, 1526, 975, 190, - 478, 757, 794, 176, 760, 755, 1080, 110, 106, 107, - 694, 275, 862, 604, 662, 44, 273, 219, 780, 24, - 78, 81, 217, 86, 17, 599, 262, 153, 204, 214, - 301, 7, 6, 654, 85, 5, 76, 3, 188, 1574, - 218, 1210, 10, 1257, 115, 1128, 1072, 264, 461, 74, - 516, 133, 1261, 178, 179, 180, 181, 221, 1258, 26, - 136, 677, 1126, 300, 139, 137, 1073, 278, 1127, 581, - 74, 719, 716, 202, 203, 113, 112, 700, 272, 376, - 322, 265, 520, 1028, 220, 452, 18, 994, 88, 87, - 462, 89, 216, 338, 56, 941, 942, 277, 676, 268, - 68, 56, 537, 1247, 1248, 1259, 352, 305, 1245, 1246, - 353, 343, 591, 88, 87, 327, 89, 368, 339, 277, - 342, 98, 366, 277, 1034, 361, 360, 359, 357, 358, - 225, 940, 656, 352, 1346, 185, 345, 353, 1578, 1042, - 348, 56, 198, 1542, 277, 365, 271, 199, 1041, 200, - 369, 88, 87, 699, 89, 357, 374, 201, 362, 351, - 514, 364, 698, 373, 1141, 1142, 105, 1437, 277, 258, - 84, 379, 417, 418, 195, 816, 748, 749, 750, 450, - 387, 451, 98, 363, 480, 615, 351, 388, 782, 196, - 783, 1510, 664, 1284, 456, 470, 186, 468, 472, 471, - 376, 473, 475, 416, 481, 482, 484, 502, 410, 1074, - 655, 663, 751, 752, 753, 501, 767, 495, 457, 1583, - 815, 493, 441, 24, 1501, 376, 346, 434, 17, 1283, - 476, 479, 491, 597, 433, 7, 486, 432, 269, 74, - 428, 492, 429, 483, 1334, 435, 10, 1218, 307, 487, - 600, 597, 835, 544, 474, 1342, 1341, 1340, 1339, 485, - 803, 793, 442, 26, 777, 541, 641, 642, 500, 668, - 943, 944, 420, 945, 421, 422, 423, 714, 542, 572, - 108, 545, 321, 505, 575, 268, 576, 154, 577, 436, - 18, 864, 865, 866, 1568, 579, 580, 88, 87, 116, - 89, 1567, 192, 80, 79, 480, 499, 571, 46, 574, - 573, 549, 74, 1253, 88, 87, 266, 89, 512, 512, - 529, 535, 601, 459, 1564, 481, 482, 494, 569, 1440, - 627, 628, 629, 177, 88, 87, 267, 89, 613, 80, - 79, 582, 583, 477, 498, 511, 511, 528, 534, 310, - 312, 314, 316, 318, 596, 46, 88, 624, 678, 89, - 371, 370, 607, 608, 609, 610, 630, 631, 632, 606, - 372, 614, 1373, 621, 1357, 519, 1566, 74, 612, 480, - 611, 619, 620, 622, 192, 340, 341, 884, 1131, 352, - 644, 375, 957, 353, 878, 704, 879, 880, 881, 481, - 482, 706, 1157, 586, 74, 585, 584, 1158, 649, 650, - 639, 357, 587, 1512, 635, 600, 1541, 886, 88, 87, - 643, 89, 74, 1141, 1142, 1536, 666, 348, 154, 354, - 355, 356, 674, 600, 652, 669, 873, 874, 875, 788, - 685, 857, 351, 88, 87, 1535, 89, 595, 277, 1511, - 1565, 784, 786, 347, 177, 321, 354, 355, 356, 1522, - 135, 869, 682, 671, 673, 747, 1534, 348, 696, 588, - 785, 546, 1533, 537, 759, 192, 488, 1525, 182, 177, - 154, 689, 872, 876, 877, 1252, 882, 63, 1413, 883, - 506, 690, 1143, 684, 973, 953, 715, 56, 453, 520, - 460, 513, 521, 692, 508, 509, 1133, 693, 1196, 1271, - 543, 705, 566, 375, 41, 43, 701, 74, 727, 707, - 787, 695, 216, 538, 74, 709, 413, 710, 713, 645, - 1531, 683, 999, 1529, 63, 1250, 718, 1527, 745, 88, - 1260, 659, 89, 74, 56, 97, 504, 723, 513, 863, - 728, 508, 509, 730, 675, 1145, 724, 758, 725, 1473, - 225, 1256, 651, 1021, 679, 680, 681, 80, 79, 480, - 734, 49, 50, 51, 52, 53, 54, 55, 49, 50, - 51, 52, 53, 54, 55, 1416, 762, 720, 648, 481, - 482, 1195, 754, 152, 601, 258, 768, 769, 733, 74, - 56, 647, 348, 646, 789, 539, 639, 352, 593, 838, - 1012, 353, 1188, 1187, 1186, 1185, 643, 74, 49, 50, - 51, 52, 53, 54, 55, 88, 87, 542, 89, 357, - 804, 543, 82, 72, 71, 814, 70, 795, 823, 74, - 821, 827, 824, 828, 773, 774, 775, 198, 74, 832, - 809, 810, 199, 69, 200, 98, 377, 833, 806, 808, - 351, 811, 201, 817, 348, 367, 1363, 67, 74, 216, - 843, 844, 825, 80, 79, 799, 820, 792, 802, 195, - 66, 826, 80, 79, 480, 834, 352, 1462, 856, 74, - 353, 592, 1460, 836, 196, 80, 79, 867, 1519, 1349, - 80, 79, 831, 932, 481, 482, 74, 225, 357, 1367, - 325, 46, 354, 355, 356, 860, 946, 947, 870, 277, - 855, 1458, 842, 858, 324, 1132, 969, 56, 193, 859, - 348, 194, 88, 1456, 527, 89, 74, 601, 959, 351, - 952, 111, 854, 350, 1266, 1262, 1263, 1264, 1265, 1348, - 773, 948, 517, 74, 198, 177, 74, 744, 46, 199, - 74, 200, 88, 87, 637, 956, 861, 996, 496, 201, - 155, 1079, 1075, 1076, 1077, 1078, 1024, 1022, 1025, 1255, - 362, 965, 807, 962, 968, 96, 195, 1439, 104, 103, - 102, 101, 958, 99, 100, 105, 1430, 825, 177, 1429, - 970, 196, 88, 87, 964, 89, 74, 825, 606, 1427, - 1000, 696, 696, 1047, 1029, 1412, 1023, 441, 1010, 1019, - 1035, 277, 434, 1038, 1410, 1027, 1030, 1400, 1052, 433, - 1050, 766, 432, 1032, 1031, 428, 1054, 429, 1398, 1045, - 435, 1008, 1018, 382, 383, 384, 385, 636, 525, 976, - 1396, 1048, 1049, 1394, 337, 1392, 74, 442, 1011, 1020, - 529, 1390, 375, 1065, 695, 695, 825, 277, 776, 56, - 1388, 1060, 352, 1359, 1360, 1361, 772, 192, 88, 87, - 765, 89, 805, 1386, 436, 1009, 1017, 528, 1384, 964, - 63, 56, 88, 87, 357, 89, 74, 672, 277, 1070, - 524, 1157, 670, 526, 308, 1381, 1158, 1378, 88, 87, - 1066, 89, 1376, 1016, 722, 1014, 1015, 156, 157, 158, - 1372, 74, 1137, 480, 1082, 351, 1083, 455, 326, 323, - 354, 355, 356, 1356, 61, 62, 47, 63, 1147, 1332, - 1213, 1212, 1154, 481, 482, 616, 88, 87, 762, 89, - 1059, 88, 87, 1139, 89, 1058, 1134, 522, 1057, 1144, - 1056, 1037, 1036, 1153, 1130, 830, 822, 737, 1140, 618, - 1201, 1148, 1199, 1200, 49, 50, 51, 52, 53, 54, - 55, 617, 578, 565, 109, 934, 348, 935, 936, 937, - 938, 939, 92, 1198, 276, 1320, 1068, 1194, 1318, 1197, - 1202, 966, 1316, 1193, 1203, 1204, 1205, 1206, 1314, 354, - 355, 356, 591, 1238, 1207, 1208, 1209, 1211, 1, 1191, - 1214, 49, 50, 51, 52, 53, 54, 55, 1157, 770, - 951, 1040, 1156, 1158, 1215, 1249, 1221, 1354, 1146, 1189, - 1251, 1242, 1222, 145, 1243, 1069, 1321, 995, 1241, 1319, - 1244, 88, 87, 1317, 89, 1183, 1216, 955, 1217, 1315, - 88, 87, 1181, 89, 589, 1237, 88, 87, 1179, 89, - 1192, 88, 87, 1254, 89, 1177, 1175, 49, 50, 51, - 52, 53, 54, 55, 277, 590, 205, 993, 992, 991, - 1190, 986, 985, 984, 983, 712, 981, 982, 105, 1438, - 990, 989, 988, 987, 1267, 46, 1184, 980, 978, 711, - 708, 634, 412, 1182, 187, 97, 277, 1423, 1173, 1180, - 626, 1171, 56, 1169, 796, 1270, 1178, 1176, 527, 1167, - 626, 1285, 1165, 1289, 1273, 1291, 1293, 1294, 1274, 1297, - 1163, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1279, 1307, - 1308, 1309, 1310, 1311, 1312, 1313, 328, 329, 330, 1435, - 1322, 1323, 1290, 1325, 1324, 1296, 1292, 1298, 1295, 1174, - 1161, 56, 1172, 1434, 1170, 1306, 979, 1327, 1287, 1159, - 1168, 332, 317, 1166, 145, 1433, 1424, 1333, 1002, 1240, - 315, 1164, 1337, 1063, 1062, 354, 355, 356, 313, 311, - 94, 309, 846, 746, 49, 50, 51, 52, 53, 54, - 55, 152, 306, 1338, 667, 454, 45, 415, 1150, 1336, - 277, 1162, 825, 1350, 1343, 277, 1352, 1353, 378, 1026, - 1160, 277, 829, 308, 277, 277, 145, 530, 1335, 1358, - 1362, 308, 525, 192, 192, 192, 192, 591, 1563, 308, - 308, 1364, 308, 192, 192, 192, 1475, 1276, 591, 1474, - 1355, 591, 1351, 308, 1219, 140, 138, 192, 56, 1576, - 1365, 591, 1046, 954, 591, 331, 950, 333, 334, 335, - 336, 933, 1366, 591, 63, 841, 1402, 1403, 1404, 1405, - 1406, 1407, 1408, 840, 524, 819, 771, 526, 764, 1369, - 721, 567, 349, 1414, 1415, 591, 303, 1588, 1418, 1579, - 1577, 1420, 1401, 117, 1570, 1546, 1509, 1508, 1507, 1425, - 1426, 1477, 1472, 1469, 1466, 1431, 1465, 1461, 1156, 1419, - 1459, 1457, 258, 1455, 798, 1442, 46, 1436, 825, 1432, - 1411, 1409, 1399, 1397, 1586, 1417, 49, 50, 51, 52, - 53, 54, 55, 1428, 152, 96, 1395, 134, 104, 103, - 102, 101, 56, 99, 100, 105, 1393, 1391, 49, 50, - 51, 52, 53, 54, 55, 1389, 1387, 1385, 1383, 1382, - 88, 87, 348, 89, 74, 46, 1380, 1379, 155, 1377, - 1468, 1375, 1374, 1371, 1370, 1347, 1345, 1331, 1330, 1326, - 1277, 1275, 1272, 1138, 1478, 1479, 1480, 1239, 1471, 1476, - 1129, 1467, 1067, 1053, 1051, 1571, 177, 1513, 1044, 1043, - 1033, 972, 1156, 961, 960, 949, 258, 868, 697, 851, - 1494, 850, 848, 56, 1493, 1492, 1491, 1481, 845, 839, - 837, 1141, 1142, 1569, 1499, 1504, 818, 1503, 797, 778, - 742, 741, 740, 739, 738, 736, 1521, 735, 688, 1528, - 1530, 1532, 638, 1528, 1530, 1532, 570, 152, 425, 88, - 1530, 424, 89, 1543, 1540, 1544, 1506, 1545, 1539, 1538, - 1537, 344, 46, 1518, 1524, 320, 1520, 1523, 1004, 1005, - 1006, 1007, 1502, 152, 1498, 1497, 1496, 1495, 1470, 1001, - 1516, 1464, 1463, 1454, 1453, 825, 1452, 1451, 531, 1528, - 1530, 1532, 61, 62, 47, 63, 1450, 1449, 1448, 1447, - 1446, 1445, 1444, 88, 87, 1443, 89, 56, 1441, 1320, - 1318, 155, 1316, 1314, 523, 156, 157, 158, 1344, 1191, - 1189, 1183, 1575, 1181, 1573, 1179, 1177, 1175, 1173, 1171, - 1169, 1167, 1165, 56, 1329, 1580, 1585, 1584, 1328, 177, - 1269, 1587, 1288, 88, 63, 1572, 89, 1268, 1081, 1286, - 1071, 1064, 1055, 998, 532, 1582, 46, 533, 997, 971, - 963, 853, 852, 849, 847, 732, 731, 825, 717, 691, - 687, 258, 1581, 206, 686, 665, 633, 603, 602, 49, - 50, 51, 52, 53, 54, 55, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 449, - 594, 568, 548, 59, 547, 497, 419, 208, 259, 210, - 228, 212, 213, 411, 386, 319, 88, 87, 304, 89, - 302, 41, 43, 515, 155, 518, 510, 46, 49, 50, - 51, 52, 53, 54, 55, 507, 503, 36, 61, 62, - 47, 63, 88, 87, 56, 89, 184, 93, 33, 223, - 155, 469, 177, 467, 95, 1514, 466, 465, 156, 157, - 158, 464, 1515, 222, 244, 463, 227, 243, 215, 209, - 207, 211, 889, 31, 1013, 1003, 439, 444, 177, 801, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 431, 800, 430, 427, 59, 226, 224, - 540, 208, 259, 210, 228, 212, 213, 270, 88, 83, - 29, 89, 57, 56, 34, 41, 43, 25, 16, 263, - 15, 46, 14, 261, 13, 49, 50, 51, 52, 53, - 54, 55, 61, 62, 47, 63, 260, 12, 11, 9, - 8, 4, 2, 223, 234, 242, 241, 46, 240, 239, - 238, 237, 236, 235, 233, 232, 231, 222, 230, 229, - 114, 77, 42, 756, 448, 152, 58, 32, 59, 658, - 657, 156, 157, 158, 1505, 299, 90, 183, 445, 426, - 1155, 761, 791, 446, 1278, 967, 41, 43, 1152, 1151, - 605, 1484, 226, 224, 1483, 1482, 1500, 156, 157, 158, - 1486, 1485, 1220, 61, 62, 47, 63, 1135, 437, 438, - 598, 661, 781, 91, 1084, 743, 65, 64, 197, 49, - 50, 51, 52, 53, 54, 55, 885, 0, 447, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 0, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 46, 0, - 0, 0, 59, 443, 440, 0, 208, 259, 210, 228, - 212, 213, 1547, 0, 0, 0, 0, 0, 0, 0, - 41, 43, 0, 0, 38, 30, 58, 32, 59, 0, - 49, 50, 51, 52, 53, 54, 55, 61, 62, 47, - 63, 0, 0, 1101, 0, 0, 41, 43, 223, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 222, 61, 62, 47, 63, 46, 0, 0, - 60, 35, 0, 0, 88, 87, 21, 89, 0, 37, - 0, 0, 155, 0, 0, 0, 39, 40, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 226, 224, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 177, 0, 0, 0, 0, 0, 0, 444, 0, 0, - 1368, 0, 0, 0, 49, 50, 51, 52, 53, 54, - 55, 0, 0, 0, 0, 38, 30, 58, 32, 59, - 0, 19, 20, 0, 22, 23, 48, 0, 27, 28, - 49, 50, 51, 52, 53, 54, 55, 41, 43, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 61, 62, 47, 63, 0, 0, - 1061, 60, 35, 1562, 0, 0, 0, 21, 0, 931, - 37, 0, 0, 0, 0, 0, 0, 39, 40, 1552, - 0, 0, 0, 0, 448, 0, 58, 32, 59, 0, - 0, 0, 0, 0, 1517, 1548, 0, 0, 445, 0, - 0, 0, 0, 446, 1557, 0, 41, 43, 0, 156, - 157, 158, 0, 0, 0, 0, 0, 0, 1558, 1559, - 1560, 1561, 0, 61, 62, 47, 63, 0, 437, 438, - 0, 0, 19, 20, 0, 22, 23, 48, 1112, 27, - 28, 49, 50, 51, 52, 53, 54, 55, 447, 0, - 1549, 1550, 1551, 1553, 1554, 1555, 1556, 1088, 1089, 0, - 1096, 1110, 1090, 1091, 1092, 1093, 0, 1094, 1095, 0, - 1111, 1097, 1098, 1099, 1100, 0, 0, 0, 0, 0, - 0, 0, 0, 443, 440, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 903, 0, 0, 0, 0, 0, 0, - 49, 50, 51, 52, 53, 54, 55, 930, 0, 0, - 0, 0, 895, 896, 0, 904, 921, 897, 898, 899, - 900, 0, 901, 902, 0, 922, 905, 906, 907, 908, - 903, 0, 0, 0, 0, 0, 146, 0, 0, 0, - 0, 0, 0, 0, 930, 0, 0, 0, 0, 895, - 896, 0, 904, 921, 897, 898, 899, 900, 0, 901, - 902, 348, 922, 905, 906, 907, 908, 0, 0, 0, - 0, 0, 919, 0, 923, 0, 1236, 1235, 1230, 925, - 1229, 1228, 1227, 1226, 0, 1224, 1225, 105, 189, 1234, - 1233, 1232, 1231, 0, 0, 927, 0, 0, 1223, 0, - 0, 871, 0, 884, 0, 0, 0, 0, 0, 919, - 878, 923, 879, 880, 881, 0, 925, 0, 0, 0, - 993, 992, 991, 0, 986, 985, 984, 983, 928, 981, - 982, 105, 927, 990, 989, 988, 987, 0, 0, 0, - 980, 978, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 873, 874, 875, 0, 1086, 1087, 0, 1102, - 1103, 1104, 0, 1105, 1106, 928, 0, 1107, 1108, 0, - 1109, 0, 0, 0, 0, 0, 0, 0, 0, 146, - 0, 0, 0, 1085, 1113, 1114, 1115, 1116, 1117, 1118, - 1119, 1120, 1121, 1122, 1123, 1124, 1125, 0, 872, 876, - 877, 0, 882, 0, 0, 883, 0, 0, 0, 979, - 0, 0, 0, 0, 0, 0, 0, 0, 890, 0, - 891, 892, 893, 894, 909, 910, 911, 926, 912, 913, - 914, 915, 916, 917, 918, 920, 924, 152, 0, 0, - 929, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 890, 0, 891, 892, 893, - 894, 909, 910, 911, 926, 912, 913, 914, 915, 916, - 917, 918, 920, 924, 175, 0, 0, 929, 151, 148, - 163, 161, 170, 146, 164, 165, 166, 167, 352, 168, - 169, 0, 772, 171, 172, 173, 174, 564, 0, 0, - 142, 162, 0, 0, 0, 0, 0, 0, 0, 141, - 357, 0, 147, 0, 0, 0, 0, 193, 0, 0, - 194, 0, 0, 0, 0, 0, 0, 143, 144, 149, - 0, 556, 0, 550, 551, 552, 553, 0, 0, 0, - 0, 623, 146, 198, 177, 0, 0, 352, 199, 0, - 200, 353, 0, 0, 884, 0, 0, 0, 201, 0, - 0, 878, 160, 879, 880, 881, 0, 0, 0, 357, - 558, 559, 560, 561, 0, 195, 555, 0, 0, 0, - 562, 563, 554, 0, 0, 0, 0, 0, 0, 0, - 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 623, 0, 0, 873, 874, 875, 88, 87, 0, 89, - 0, 0, 0, 0, 155, 0, 0, 175, 0, 0, - 0, 151, 148, 163, 161, 170, 0, 164, 165, 166, - 167, 0, 168, 169, 0, 0, 171, 172, 173, 174, - 0, 0, 177, 142, 162, 0, 0, 0, 0, 872, - 876, 877, 141, 882, 0, 147, 883, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 143, 144, 149, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 557, 0, 0, 0, 0, 0, - 0, 0, 146, 0, 0, 0, 0, 352, 0, 0, - 0, 353, 0, 0, 0, 160, 159, 0, 0, 0, - 88, 87, 0, 89, 0, 0, 0, 0, 155, 357, - 0, 175, 0, 0, 0, 151, 148, 163, 161, 170, - 0, 164, 165, 166, 167, 0, 168, 169, 0, 0, - 171, 172, 173, 174, 0, 0, 177, 142, 162, 0, - 623, 0, 146, 0, 0, 0, 141, 0, 0, 147, - 0, 156, 157, 158, 0, 0, 0, 0, 0, 88, - 87, 0, 89, 0, 143, 144, 149, 155, 0, 0, - 175, 0, 0, 0, 151, 148, 163, 161, 170, 0, - 164, 165, 166, 167, 0, 168, 169, 0, 63, 171, - 172, 173, 174, 0, 0, 177, 142, 162, 0, 160, - 274, 354, 355, 356, 0, 141, 0, 0, 147, 88, - 87, 0, 89, 0, 0, 641, 642, 0, 0, 0, - 0, 0, 0, 143, 144, 149, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 146, 409, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 156, 157, 158, 160, 0, - 354, 355, 356, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 391, 641, 642, 0, 407, 0, 0, - 389, 390, 0, 0, 0, 393, 394, 405, 395, 396, - 397, 398, 399, 400, 401, 402, 392, 0, 0, 0, - 274, 146, 0, 406, 0, 0, 404, 0, 0, 88, - 87, 0, 89, 403, 156, 157, 158, 155, 0, 0, - 175, 0, 408, 0, 151, 148, 163, 161, 170, 0, - 164, 165, 166, 167, 0, 168, 169, 0, 0, 171, - 172, 173, 174, 0, 0, 177, 142, 162, 0, 0, - 0, 0, 0, 0, 0, 141, 0, 0, 147, 274, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, - 87, 0, 89, 143, 144, 149, 0, 155, 0, 0, - 175, 0, 0, 0, 151, 148, 163, 161, 170, 0, - 164, 165, 166, 167, 0, 168, 169, 0, 0, 171, - 172, 173, 174, 146, 0, 177, 142, 162, 160, 0, - 354, 355, 356, 0, 0, 141, 0, 0, 147, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 175, 143, 144, 149, 0, 813, 163, 161, - 170, 0, 164, 165, 166, 167, 0, 168, 169, 0, - 0, 171, 172, 173, 174, 0, 0, 0, 1281, 162, - 0, 274, 146, 0, 156, 157, 158, 0, 160, 88, - 87, 0, 89, 0, 0, 0, 0, 155, 0, 0, - 175, 0, 812, 0, 151, 148, 163, 161, 170, 0, - 164, 165, 166, 167, 0, 168, 169, 0, 0, 171, - 172, 173, 174, 0, 0, 177, 142, 162, 1282, 0, - 0, 0, 0, 0, 0, 141, 0, 0, 147, 0, - 274, 0, 0, 0, 156, 157, 158, 1280, 88, 87, - 0, 89, 0, 143, 144, 149, 155, 0, 0, 175, - 0, 0, 0, 151, 148, 163, 161, 170, 0, 164, - 165, 166, 167, 0, 168, 169, 0, 0, 171, 172, - 173, 174, 146, 0, 177, 142, 162, 0, 160, 159, - 0, 0, 0, 0, 141, 0, 0, 147, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 143, 144, 149, 0, 0, 993, 992, 991, - 0, 986, 985, 984, 983, 0, 981, 982, 105, 0, - 990, 989, 988, 987, 0, 0, 0, 980, 978, 0, - 274, 0, 0, 0, 156, 157, 158, 160, 0, 0, - 88, 87, 0, 89, 0, 0, 0, 0, 155, 0, - 0, 175, 0, 0, 0, 151, 148, 163, 161, 170, - 0, 164, 165, 166, 167, 0, 168, 169, 0, 0, - 171, 172, 173, 174, 0, 0, 177, 142, 162, 0, - 0, 0, 0, 0, 0, 0, 763, 146, 0, 147, - 0, 0, 0, 156, 157, 158, 979, 0, 0, 88, - 87, 0, 89, 0, 143, 144, 149, 155, 0, 0, - 175, 0, 0, 0, 151, 148, 163, 161, 170, 0, - 164, 165, 166, 167, 0, 168, 169, 0, 0, 171, - 172, 173, 174, 0, 0, 177, 142, 162, 0, 160, - 0, 0, 0, 0, 146, 141, 0, 0, 147, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 143, 144, 149, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 156, 157, 158, 653, 88, - 87, 146, 89, 0, 0, 0, 0, 155, 0, 0, - 175, 0, 0, 0, 151, 148, 163, 161, 170, 0, - 164, 165, 166, 167, 0, 168, 169, 0, 0, 171, - 172, 173, 174, 0, 0, 177, 142, 162, 0, 0, - 0, 297, 198, 0, 0, 141, 0, 199, 147, 200, - 0, 0, 0, 146, 156, 157, 158, 201, 0, 999, - 0, 0, 0, 143, 144, 149, 0, 0, 0, 0, - 0, 0, 0, 0, 195, 284, 0, 279, 280, 281, - 282, 283, 0, 0, 0, 0, 287, 0, 0, 196, - 0, 0, 0, 0, 0, 285, 0, 0, 458, 0, - 295, 0, 286, 0, 0, 146, 0, 0, 0, 0, - 0, 726, 0, 0, 288, 289, 290, 291, 292, 293, - 294, 298, 0, 0, 489, 175, 490, 296, 0, 151, - 148, 163, 161, 170, 0, 164, 165, 166, 167, 0, - 168, 169, 0, 0, 171, 172, 173, 174, 0, 0, - 177, 142, 162, 0, 156, 157, 158, 0, 0, 0, - 141, 0, 0, 147, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 143, 144, - 149, 380, 175, 381, 0, 0, 151, 148, 163, 161, - 170, 0, 164, 165, 166, 167, 0, 168, 169, 0, - 0, 171, 172, 173, 174, 0, 0, 0, 142, 162, - 0, 0, 0, 160, 0, 0, 0, 141, 0, 0, - 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 143, 144, 149, 0, 175, - 0, 0, 0, 151, 148, 163, 161, 170, 0, 164, - 165, 166, 167, 0, 168, 169, 0, 0, 171, 172, - 173, 174, 0, 0, 0, 142, 162, 0, 0, 0, - 160, 0, 0, 0, 141, 0, 0, 147, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 175, 143, 144, 149, 151, 148, 163, 161, 170, - 0, 164, 165, 166, 167, 0, 168, 169, 0, 0, - 171, 172, 173, 174, 0, 0, 0, 142, 162, 0, - 0, 0, 0, 0, 0, 0, 141, 160, 0, 147, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 175, 143, 144, 149, 151, 148, 163, - 161, 170, 0, 164, 165, 166, 167, 0, 168, 169, - 0, 0, 171, 172, 173, 174, 0, 0, 0, 142, - 162, 0, 0, 0, 0, 0, 0, 0, 141, 160, - 0, 147, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 143, 144, 149, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 160 + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -1367, 1443, -1367, 1336, -72, 32, -41, -5, 10, 22, + -358, -1367, 13, -18, 1603, -1367, -1367, 1166, 1243, -640, + -1367, -975, -1367, 26, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -313, -1367, -1367, -1367, 916, -1367, -1367, + -1367, 451, -1367, 929, 498, 499, -1367, -1366, -437, -1367, + -312, -1367, -1367, -942, -1367, -162, -98, -1367, 35, 1613, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, 677, + 462, -1367, -311, -1367, -702, -667, 1297, -1367, -1367, -243, + -1367, -141, -1367, -1367, 1081, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, 328, 7, -1367, -1367, -1367, 1035, -150, + 1586, 578, -40, -30, 805, -1367, -1058, -1367, -1367, -1324, + -1299, -1192, -1269, -1367, -1367, -1367, -1367, 23, -1367, -1367, + -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, + -1367, -1367, -1367, -27, 768, 982, -1367, -688, -1367, 692, + -22, -405, -74, 239, 130, -1367, -23, 538, -1367, 984, + 3, 811, -1367, -1367, 808, -1367, -1049, -1367, 1661, -1367, + 36, -1367, -1367, 545, 1205, -1367, 1566, -1367, -1367, -961, + 1272, -1367, -1367, -1367, -1367, -1367, -1367, -1367, -1367, 1160, + 975, -1367, -1367, -1367, -1367, -1367 }; -YYSTATIC YYCONST short YYFARDATA YYPACT[] = { --1000, 1635,-1000, 587, 574,-1000,-1000,-1000,-1000,-1000, --1000,-1000, 560, 543, 541, 540,-1000,-1000,-1000, 78, - 78, -463, 105, 105,-1000,-1000,-1000, 539,-1000, -116, - 395,-1000, 931, 1107, 43, 923, 78, -365, -366,-1000, - -142, 1445, 43, 1445,-1000,-1000,-1000, 227, 2386, 395, - 395, 395, 395,-1000,-1000, 246,-1000,-1000,-1000, -155, - 1083,-1000,-1000, 2288, 43, 43,-1000,-1000, 1498,-1000, --1000,-1000,-1000,-1000,-1000,-1000, 78, -117,-1000,-1000, --1000,-1000, 1432, -141, 2918, 1219,-1000,-1000,-1000,-1000, - 3187,-1000, 78,-1000, 537,-1000, 1294, 1628, 43, 1202, - 1191, 1189, 1188, 1180, 1172, 1625, 1474, 45,-1000, 78, - 696, 830,-1000,-1000, 84, 1219, 395, 2918,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000, 1470, 195, 1288, 381, -233, -235, -236, - -237, 1432,-1000, -93, 1432, 489, 662,-1000,-1000, 111, --1000, 3512, 213, 1211,-1000,-1000,-1000,-1000,-1000, 3351, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, - 592,-1000,-1000,-1000,-1000,-1000, 1219, 1624, 432, 1219, - 1219, 1219,-1000, 2599, 126,-1000,-1000, 1623, 1081, 2859, --1000, 3512,-1000,-1000,-1000, 382, 382,-1000, 1616,-1000, --1000, 1, 1460, 1457, 1704, 1524,-1000,-1000, 78,-1000, - 78, 75,-1000,-1000,-1000,-1000, 1187,-1000,-1000,-1000, --1000,-1000, 866, 78, 3179,-1000, -13, -86,-1000,-1000, - 309, 78, 105, 333, 43, 309, 489, 3294, 2918, -92, - 382, 2859, 1615,-1000, 502,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, - 112, 65, 862, 1142,-1000, 81,-1000, 428, 1432,-1000, --1000, 2918,-1000,-1000, 67, 125, 382, 395,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000, 1614, 1612, 2243, - 920, 417, 1287, 1611, 126, 1455, -52,-1000, 78, -52, --1000, 105,-1000, 78,-1000, 78,-1000, 78,-1000,-1000, --1000,-1000, 919,-1000, 78, 78,-1000, 1219,-1000,-1000, --1000, -377,-1000,-1000,-1000,-1000,-1000, 830, 104, 107, --1000,-1000, 1219, 1054,-1000, 1292, 598, 1610,-1000, 214, - 395, 170,-1000,-1000,-1000, 1588, 1587, 3512, 395, 395, - 395, 395,-1000, 1432,-1000,-1000, 3512, 572,-1000, 1219, --1000, -65,-1000, 125, 882, 918, 906, 395, 395, 2699, --1000,-1000,-1000,-1000,-1000,-1000, 78, 1292, 1100,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000, 29,-1000,-1000,-1000, 1586, - 1080,-1000, 754, 1451,-1000,-1000, 2549,-1000,-1000, 78, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, 510, - 508, 495,-1000,-1000,-1000,-1000,-1000, 78, 78, 469, - 3079,-1000,-1000, -303, -204,-1000,-1000,-1000,-1000,-1000, --1000,-1000, -34, 1585,-1000, 78, 1186, 25, 382, 841, - 836, 78,-1000, -86, 76, 76, 76, 76, 2918, 502, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000, 1584, 1580, 1447,-1000,-1000,-1000, 2699,-1000,-1000, --1000,-1000, 1292, 1579, 43, 3512,-1000, 309, 1333,-1000, - -126, -135,-1000,-1000, -361,-1000,-1000, 43, 383, 370, - 43,-1000,-1000, 1079,-1000,-1000, 43,-1000, 43,-1000, - 1078, 1064,-1000,-1000, 395, -164, -369, 1578,-1000,-1000, --1000,-1000, 395, -370,-1000,-1000, -352,-1000,-1000,-1000, - 1286,-1000, 851, 395, 3512, 1219, 3460, 78, 235, 678, --1000,-1000,-1000,-1000,-1000,-1000,-1000, 1576,-1000,-1000, --1000,-1000,-1000,-1000, 1575,-1000,-1000, 537, 235, 1446, --1000, 1444, 904, 1443, 1442, 1441, 1440, 1439,-1000, 524, - 1175,-1000, 103, 1219,-1000,-1000,-1000, -125, 395, 235, - 464, 242, 3020,-1000,-1000, 1284, 1219,-1000, 817,-1000, --1000, -29, 2918, 2918, 997, 1282, 125, 1219, 1219, 1219, - 1219,-1000, 2490,-1000, 1219,-1000, 395, 395, 395, 805, - 1219, 20, 1219, 188, 1438,-1000, 175,-1000,-1000,-1000, --1000,-1000,-1000, 78,-1000, 1292,-1000,-1000, 489, 17, - 1094,-1000,-1000, 1219, 1437, 1239,-1000,-1000,-1000,-1000, --1000,-1000, 16, 382, 821, 721, 2918, 2759, -123, 104, - 1435, 1281,-1000,-1000, 3460, -34, 903, 78, -79, 3512, - 78, 1219, 78, 1218, 902,-1000,-1000,-1000, 309,-1000, --1000,-1000,-1000,-1000,-1000,-1000, 78, 105,-1000, 8, - 1219, 235, 1429, 599, 1428, 1279, 1271,-1000, 126, 78, - 78, 1427, 1174,-1000,-1000, 1292, 1574, 1421, 1573, 1420, - 1418, 1572, 1571, 1219, 395,-1000, 395, 78, 152, 395, - 43, 2918, 395, 703, 864, 98, -185, 1416, 99, 2300, - 128, 1976, 78,-1000, 1270,-1000, 843,-1000, 843, 843, - 843, 843, 843, -158,-1000, 78, 78, 395,-1000,-1000, --1000,-1000,-1000,-1000, 1219, 1414, 1262, 999,-1000,-1000, - 400, 1259, 1026, 532, 159,-1000, 5, 78, 1413, 1412, --1000, 3512, 1570, 1211, 1211, 1211, 395, 395,-1000, 969, - 716, 175,-1000,-1000,-1000,-1000,-1000,-1000, 1569, 1410, - 399, 840, 1016, -79, 1568, 1563, 3408,-1000,-1000, 1404, - 1093, 515, 468, -79, 3512, 78, 1219, 78, 1215, -339, - 395, 1219,-1000,-1000, 3512,-1000,-1000, 1219,-1000, -34, - 98, 1409, -238,-1000,-1000, 1219, 2699, 899, 898, 2918, - 1000, -140, -149, 1408, 1407, 395, 1261,-1000, -34,-1000, - 309, 309,-1000,-1000,-1000,-1000, 383,-1000,-1000,-1000, --1000,-1000,-1000,-1000, 1211, 1219, 1403, 78, 1219, 1402, --1000, 395, -79, 1562, 897, 895, 892, 887,-1000, 235, - 2049,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000, 1166, 1165, 1561, 1000, 126, 1401, 984, 43, - 1560, -407, -38,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000, 521,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000, 1558, 1558,-1000, 1558, - 1911,-1000,-1000, -406,-1000, -392,-1000,-1000, -427,-1000, --1000,-1000, 1399,-1000,-1000,-1000,-1000,-1000,-1000,-1000, - 126,-1000,-1000,-1000,-1000,-1000, 155, 492, 1219,-1000, - 235, 1150, 397,-1000, 3020, 462, 1007,-1000,-1000,-1000, --1000,-1000, 125, -34, 1211, 1219,-1000, 395, 1204, 2918, --1000, 78,-1000,-1000, 698,-1000,-1000,-1000, 1169, 1160, - 1130, 1122, 1119, 1113, 1111, 1108, 1066, 1065, 1058, 1052, - 1045, 361, 1029, 1009, 43, 498, 1094, -34, -34, 78, - 968,-1000,-1000,-1000, 489, 489, 489, 489,-1000,-1000, --1000,-1000,-1000,-1000, 489, 489, 489,-1000,-1000,-1000, --1000,-1000, -440, 2699, 878, 877, 2918,-1000, 489, 1219, - 678,-1000, 126,-1000, 126, 3,-1000, 1250,-1000,-1000, - 2039, 126, 78,-1000,-1000, 1219,-1000, 1396,-1000,-1000, - 1161,-1000,-1000, -290, 1090, 1976,-1000,-1000,-1000,-1000, - 1292,-1000, -256, -261, 78,-1000,-1000,-1000,-1000, 472, - 218, 235, 718, 500,-1000,-1000,-1000,-1000,-1000,-1000, --1000, -432,-1000,-1000, 44,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000, 494,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000, 78,-1000,-1000,-1000,-1000, 1557, 1292, - 1550,-1000,-1000,-1000,-1000,-1000, 416, 1391, 1204,-1000, - 175, 1390, 1243,-1000, 1389, 2811,-1000,-1000,-1000, -40, - 78, 1293, 78, 2970, 78, 143, 78, 69, 78, 105, - 78, 78, 78, 78, 78, 78, 78, 105, 78, 78, - 78, 78, 78, 78, 78, 998, 992, 988, 985, 78, - 78, -127, 78, 1388, 1292,-1000,-1000, 1548, 1544, 1387, - 1386, 876,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, - 382, 0,-1000, 1224,-1000, 1209,-1000,-1000, -79, 2918, --1000,-1000, 1292,-1000, 1542, 1541, 1540, 1539, 1538, 1537, - 4, 1536, 1535, 1533, 1531, 1530, 1529,-1000,-1000,-1000, - 383,-1000, 1528, 1385, 123,-1000,-1000,-1000,-1000, 1384, --1000, 686, 78,-1000, 1248, 78, 78, 1006, 235, 870, --1000,-1000,-1000,-1000,-1000,-1000,-1000, 141, 78, 622, - 571,-1000,-1000,-1000,-1000,-1000, 2918,-1000, 648,-1000, --1000,-1000, 1724, 1383, 1382, 857, 139, 1381, 1380, 849, - 1378, 844, 1376, 1375, 842, 1368, 1367, 825, 1366, 820, - 1365, 807, 1364, 798, 1356, 792, 1355, 790, 1345, 787, - 1332, 775, 1331, 764, 105, 78, 78, 78, 78, 78, - 78, 78, 1330, 761, 1329, 752,-1000, 393, -34, -34, --1000,-1000, 553, 3512, -79, 2918, -34, 1087,-1000, 1523, - 1522, 1520, 1519, 1158, -34,-1000,-1000,-1000,-1000, 78, - 746, 235, 736, 733, 78, 1292,-1000,-1000, 1328, 1157, - 1145, 1131, 1326,-1000, 72,-1000, 1068, 724, 96,-1000, --1000,-1000, 1518, 1324,-1000,-1000, 1515,-1000, 1512,-1000, --1000, 1511,-1000,-1000, 1510,-1000, 1509,-1000, 1508,-1000, - 1507,-1000, 1506,-1000, 1497,-1000, 1496,-1000, 1494,-1000, - 1493, 1322, 670, 1320, 658, 1319, 629, 1316, 624,-1000, - 1492,-1000, 1491,-1000, 1315, 1313,-1000, 2699, 1087,-1000, - 1312, 1488,-1000, 471, 383, 1311, 496,-1000, 1245,-1000, - 2013, 1310,-1000, 78, 78, 78,-1000,-1000, 2970,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000, 1487,-1000, 1486,-1000, - 1485,-1000, 1484,-1000,-1000,-1000,-1000, -20, 1482, 1000, - -34,-1000,-1000,-1000, 235,-1000, 984,-1000, 1307, 1306, - 1305,-1000, 180, 1406, 2083, 687, 448, 466, 526, 522, - 519, 461, 455, 434, 414,-1000,-1000,-1000,-1000, 405, - 132, -79, -34,-1000, 1304, 1799, 1234,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000, 91,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000, 439, 365, 290, - 283,-1000,-1000,-1000, 1433, 1303,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000, 1405, 235,-1000,-1000,-1000,-1000,-1000, -34, - -442, 78, 1258, 1299, -191, 1298,-1000,-1000, 382,-1000, - 3512, 2699, -25, -79, 1087, 1334, -34, 1296,-1000 +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + 0, 1, 36, 290, 658, 370, 71, 158, 782, 1520, + 582, 38, 372, 40, 41, 42, 43, 106, 229, 671, + 672, 876, 1121, 373, 1289, 45, 46, 677, 47, 48, + 49, 50, 51, 52, 180, 182, 322, 323, 518, 1133, + 1134, 517, 702, 703, 704, 1137, 907, 1465, 1466, 534, + 53, 208, 846, 1067, 74, 107, 108, 109, 211, 230, + 536, 707, 926, 1157, 537, 708, 927, 1166, 54, 952, + 842, 843, 55, 184, 723, 471, 737, 1543, 374, 185, + 375, 745, 377, 378, 563, 379, 380, 564, 565, 566, + 567, 568, 569, 746, 381, 57, 77, 196, 414, 402, + 415, 877, 878, 175, 176, 1237, 879, 1486, 1487, 1485, + 1484, 1477, 1482, 1476, 1493, 1494, 1492, 212, 382, 383, + 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 764, 675, 503, 504, 738, 739, 740, + 213, 165, 231, 844, 1009, 1060, 215, 167, 501, 502, + 397, 664, 665, 59, 659, 660, 1074, 1075, 93, 60, + 398, 62, 114, 475, 628, 63, 116, 423, 620, 783, + 621, 622, 630, 623, 64, 424, 631, 65, 542, 205, + 425, 639, 66, 117, 426, 645 }; -YYSTATIC YYCONST short YYFARDATA YYPGO[] = { - 0, 33, 53, 3, 1876, 57, 40, 6, 1868, 0, - 1867, 1866, 1865, 222, 278, 1864, 1863, 2, 1862, 48, - 36, 1, 26, 30, 27, 4, 1861, 44, 41, 55, - 1860, 38, 39, 8, 18, 7, 31, 1857, 42, 1852, - 28, 25, 1851, 1850, 5, 10, 12, 14, 1846, 1845, - 1844, 1841, 22, 32, 43, 1840, 1839, 1838, 1835, 11, - 1834, 1832, 9, 1831, 34, 1830, 13, 15, 17, 16, - 46, 23, 556, 68, 1247, 29, 268, 1827, 1826, 1825, - 1824, 1820, 1819, 19, 35, 1813, 1343, 1812, 1811, 24, - 771, 123, 1810, 45, 1246, 1809, 1808, 1806, 1805, 1804, - 1803, 1802, 1801, 1800, 1799, 1798, 1796, 1795, 1794, 1048, - 1792, 67, 58, 1791, 65, 130, 62, 59, 1790, 1789, - 70, 1788, 1787, 1786, 1774, 1773, 1772, 56, 1770, 1769, - 1768, 52, 114, 47, 1767, 87, 366, 1764, 1762, 1760, - 1759, 1757, 1750, 1746, 1745, 1744, 1743, 1729, 1726, 1024, - 1725, 1724, 1723, 1722, 1721, 1720, 1719, 1718, 91, 1717, - 1716, 120, 1715, 1714, 1711, 128, 1707, 1706, 1703, 1701, - 1698, 1697, 1696, 60, 1670, 117, 1687, 80, 1686, 520, - 1685, 1676, 1675, 1673, 1564, 1538 +/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int16 yytable[] = +{ + 72, 278, 166, 164, 58, 227, 228, 159, 56, 885, + 533, 535, 538, 177, 39, 119, 1184, 198, 178, 214, + 932, 851, 219, 169, 170, 171, 172, 44, 1201, 199, + 120, 121, 122, 37, 674, 1243, 209, 61, 404, 406, + 408, 410, 412, 294, 376, 125, 126, 961, 163, 110, + 216, 604, 216, 605, 1277, 68, 69, -558, 70, 120, + 161, 68, 69, 777, 70, 279, 120, 960, 419, 420, + 200, 845, 68, 69, 1198, 70, 217, 120, 1000, 683, + 684, 685, 120, 207, 744, 233, 344, 120, 498, 216, + 68, 69, 120, 70, 120, 1497, 120, 292, 216, 216, + 68, 69, 478, 70, 1241, 498, 254, 320, 99, 238, + 120, 249, 252, 253, 453, 120, 68, 69, 120, 70, + 736, 550, 235, 236, 259, 1491, 99, 261, 163, 267, + 68, 69, 679, 70, 558, 712, 99, 931, 68, 69, + 161, 70, 68, 69, 371, 70, 291, 68, 69, 1490, + 70, 270, 273, 556, 198, 120, 1533, 1513, 206, 472, + 466, 282, 283, 284, 67, 516, 498, 274, 417, 68, + 69, 120, 70, 68, 69, 319, 70, 1488, 216, 123, + 124, 1512, 123, 124, 120, 449, 577, 75, 123, 124, + 577, 271, 1534, 482, 1125, 1126, 96, 1279, 110, 97, + 431, 432, 123, 124, 193, 452, 578, 579, 1131, 1510, + 578, 579, 73, 68, 120, 120, 70, 120, 120, 1586, + 1014, 120, 98, 99, 123, 124, 585, 100, 470, 101, + 690, 461, 462, 1280, 476, 474, 102, 691, 479, 572, + 1015, 1069, 1070, 68, 69, 271, 70, 519, 76, 1483, + 557, 684, 1341, 103, 95, 1489, 492, 1147, 591, 206, + 1342, 695, 481, 483, 505, 1352, 111, 487, 104, 291, + 489, 490, 491, 696, 697, 493, 494, 895, 457, 112, + 497, 120, 488, 458, 268, 1179, 1195, 1511, 793, 206, + 113, 698, 459, 554, 594, 719, 500, 206, 168, 551, + 58, 206, 451, 485, 56, 123, 124, 577, 206, 552, + 39, 400, 451, 713, 577, 401, 590, 368, 459, 592, + 115, 1217, 173, 44, 848, 781, 540, 578, 579, 37, + 539, 206, 174, 61, 578, 579, 531, 206, 206, 570, + 218, 699, 573, 656, -558, 181, 583, 778, 118, 532, + 220, 593, 1508, 421, 286, 530, 287, 272, 1199, 541, + 288, 289, 206, 179, 422, 597, 589, 499, 546, 1218, + 547, 269, 1417, 68, 548, 608, 70, 1219, 1514, 784, + 464, 1081, 1516, 663, 499, 465, 1082, 403, 998, 269, + 571, 401, 183, 574, 575, -541, 1517, 584, 1495, 269, + 206, 1527, 262, 263, 1528, 201, 682, 576, 581, 728, + 599, 600, 264, 601, 206, 602, 163, 376, 472, 905, + 847, 687, 688, 110, 588, 749, 619, 1507, 161, 603, + 657, 610, 611, 202, 1532, 730, 617, 617, 637, 643, + 919, 1242, 895, 1535, 654, 237, 655, 1063, 1127, 618, + 618, 638, 644, 1064, 715, 733, 203, 1529, 204, 947, + 948, 949, 921, 232, 452, 1519, 1400, 1317, 1530, 260, + 1521, 1506, 722, 680, 1524, 221, 105, 68, 69, 500, + 70, 120, 68, 69, 206, 70, 742, 470, 1549, 222, + 127, 68, 69, 216, 70, 120, 234, 368, 110, 127, + 1546, 1547, 68, 69, 271, 70, 1501, 1548, 68, 275, + 127, 70, 120, 700, 1068, 758, 459, 371, 99, 694, + 978, 1536, 725, 276, 701, 747, 766, 99, 1537, 957, + 206, 282, 283, 284, 709, 710, 68, 69, 99, 70, + 277, 1282, 98, 785, 127, 729, 731, 100, 1283, 101, + 280, 1069, 1070, 721, 1540, 762, 102, 459, 1469, 727, + 281, 1470, 732, 760, 123, 124, 577, 198, 1319, 1320, + 405, 761, 99, 103, 401, 407, 748, 293, 376, 401, + 68, 69, 1398, 70, 757, 409, 578, 579, 104, 401, + 580, 294, 786, 787, 68, 69, 295, 70, 790, 3, + 791, 559, 127, 560, 561, 562, 763, 1403, 1404, 296, + 917, 411, 533, 535, 538, 401, 923, 979, 321, 980, + 981, 982, 983, 984, 454, 68, 69, 455, 70, 795, + 99, 909, 910, 914, 1213, 797, 153, 154, 155, 399, + 259, 413, 120, 794, 577, 153, 154, 155, 892, 1084, + 505, 951, 416, 1085, 418, 1214, 153, 154, 155, 1086, + 1415, 1215, 799, 1087, 578, 579, 1136, 206, 1216, 1092, + 901, 884, 460, 1093, 893, 1094, 894, 450, 371, 1095, + 68, 69, 1096, 852, 433, 875, 1097, 972, 127, 1098, + 153, 154, 155, 1099, 467, 468, 456, 1100, 906, 899, + 500, 1101, 913, 965, 459, 1102, 918, 920, 922, 1103, + 959, 1104, 967, 1106, 962, 1105, 99, 1107, 1459, 1108, + 240, 241, 242, 1109, 286, 1463, 287, 463, 1110, 884, + 288, 289, 1111, 1112, 950, 1114, 953, 1113, 955, 1115, + 956, 1461, 1264, 1116, 1267, 243, 473, 1117, 153, 154, + 155, 120, 186, 477, 966, 187, 188, 189, 190, -238, + 191, 192, 193, 206, 968, 969, 480, 459, 1348, 1349, + 1350, 1194, 1538, 1145, 206, 156, 1071, 14, 970, 1247, + 506, 663, 484, 1248, 156, 1083, 985, 640, 986, 987, + 641, 999, 98, 1001, 1249, 156, 459, 100, 1250, 101, + 1574, 495, 997, 1251, 1065, 186, 102, 1252, 187, 188, + 189, 190, 1544, 191, 192, 193, 1003, 1004, 1005, 1006, + 1007, 1253, 486, 103, 915, 1254, 1073, 549, 206, 156, + 496, 1135, 1456, 509, 153, 154, 155, 543, 104, 244, + 555, 245, 246, 247, 248, 1069, 1070, 1129, 1122, 606, + 282, 283, 284, 1551, 68, 69, 544, 70, 1072, 1169, + 1321, 1322, 28, 29, 30, 31, 32, 33, 34, 916, + 223, 642, 224, 225, 226, 1552, 596, 35, 510, 511, + 512, 285, 598, 1183, 1576, 1185, 607, 156, 3, 1120, + 1123, 609, 1140, 652, 1142, 750, 751, 752, 1118, 1588, + 1146, 653, 1138, 1119, 1208, 1209, 1210, 1211, 1212, 1141, + 459, 1335, 216, 1132, 513, 514, 515, 1585, 661, 884, + 255, 256, 257, 258, 250, 251, 459, 1545, 540, 1143, + 666, 1144, 539, 667, 762, 762, 206, 1406, 531, 1155, + 1164, 1205, 637, 646, 647, 648, 668, 884, 1196, 1197, + 669, 532, 1156, 1165, 673, 638, 676, 530, 1154, 1163, + 689, 541, 1158, 1167, 1017, 1018, 1193, 1088, 1089, 1090, + 1091, 625, 3, 156, 681, 692, 282, 283, 284, 649, + 650, 651, 693, 705, 706, 763, 763, 1310, 1311, 1312, + 1313, 716, 68, 69, 1235, 70, 717, 1314, 1315, 1316, + 586, 128, 587, 718, 720, 129, 130, 131, 132, 133, + 1203, 134, 135, 136, 137, 726, 138, 139, 194, 734, + 140, 141, 142, 143, 886, 887, 99, 144, 145, 735, + 753, 282, 283, 284, 195, 754, 146, 755, 147, 1149, + 1150, 1151, 1152, 286, 756, 287, 765, 759, 768, 288, + 289, 767, 769, 148, 149, 150, 770, 771, 776, 888, + 772, 773, 775, 11, 12, 13, 14, 1343, 1344, 1345, + 1346, 1307, 1308, 1220, 779, 28, 29, 30, 31, 32, + 33, 34, 780, 788, 1353, 789, 792, 195, 151, 3, + 35, 796, 798, 849, 1284, 1244, 1245, 1246, 850, 853, + 854, 855, 1255, 1256, 1257, 1258, 1259, 1260, 856, 1262, + 1263, 1265, 632, 1268, 1269, 1270, 1271, 1272, 1273, 1274, + 1261, 1276, 857, 1278, 1266, 1281, 858, 1285, 1523, 1526, + 9, 10, 1275, 882, 883, 68, 69, 1304, 70, 1325, + 896, 903, 1338, 897, 908, 898, 1328, 3, 1329, 902, + 14, 28, 29, 30, 31, 32, 33, 34, 924, 930, + 1153, 963, 612, 971, 613, 974, 35, 614, 615, 286, + 632, 287, 954, 964, 110, 288, 289, 958, 973, 975, + 976, 1318, 401, 988, 110, 110, 110, 110, 977, 989, + 282, 283, 284, 990, 110, 110, 110, 991, 889, 890, + 1330, 891, 992, 427, 993, 428, 429, 994, 1008, 1332, + 995, 1409, 430, 996, 1002, 1011, 1336, 1337, 1010, 1013, + 1012, 1016, 1061, 1077, 286, 633, 287, 1405, 1340, 1066, + 288, 289, 1078, 1079, 1130, 28, 29, 30, 31, 32, + 33, 34, 1139, 1124, 616, 1171, 1172, 1178, 1347, 1351, + 35, 1173, 1414, 1180, 1120, 1174, 1175, 1359, 1360, 1361, + 1362, 1363, 1364, 1419, 1366, 1399, 1176, 14, 1177, 1181, + 1182, 736, 1186, 1189, 1190, 1365, 1200, 634, 68, 69, + 635, 70, 1204, 633, 1401, 1191, 127, 1192, 1202, 128, + 1240, 1238, 157, 129, 130, 131, 132, 133, 1239, 134, + 135, 136, 137, 1206, 138, 139, 1207, 1291, 140, 141, + 142, 143, 1292, 1293, 99, 144, 145, 1294, 1295, 1296, + 474, 1298, 884, 1299, 146, 14, 147, 1300, 1301, 1305, + 1306, 1309, 1326, 1460, 1118, 634, 1327, 516, 635, 1119, + 1331, 148, 149, 150, 1418, 1333, 1334, 1339, 1084, 1086, + 1092, 1423, 28, 29, 30, 31, 32, 33, 34, 1094, + 1096, 636, 1098, 1100, 1118, 1120, 1102, 35, 1104, 1119, + 1354, 1106, 1108, 1110, 1356, 1395, 151, 1355, 282, 283, + 284, 1357, 1358, 286, 1367, 287, 1462, 1368, 1498, 686, + 289, 96, 467, 468, 97, 1370, 1369, 1502, 1371, 1373, + 1402, 1372, 1375, 884, 1374, 1376, 1378, 1377, 1379, 1381, + 28, 29, 30, 31, 32, 33, 34, 98, 99, 1168, + 1380, 1382, 100, 1383, 101, 35, 1384, 1385, 1387, 1389, + 1386, 102, 153, 154, 155, 1473, 1474, 1475, 68, 69, + 1388, 70, 1390, 1391, 1392, 1393, 127, 1394, 103, 128, + 1396, 1407, 1397, 129, 130, 131, 132, 133, 1408, 134, + 135, 136, 137, 104, 138, 139, 1411, 1412, 140, 141, + 142, 143, 1539, 1570, 99, 144, 145, 1413, 1416, 1420, + 1581, 1421, 1247, 1422, 146, 1249, 147, 1509, 1251, 1253, + 1425, 1424, 1515, 1509, 1518, 1426, 1522, 1428, 1515, 1509, + 1518, 148, 149, 150, 1427, 1432, 1433, 1430, 1583, 1525, + 1431, 28, 29, 30, 31, 32, 33, 34, 1434, 1435, + 1515, 1509, 1518, 1436, 1437, 1439, 35, 1438, 1440, 1441, + 1442, 1443, 1444, 1445, 1446, 1447, 151, 884, 282, 283, + 284, 28, 29, 30, 31, 32, 33, 34, 1448, 1449, + 1429, 3, 467, 468, 1452, 1450, 35, 1451, 1582, 1453, + 1454, 1455, 1457, 1542, 1458, 1468, 1464, 1467, 1478, 1479, + 1472, 469, 1480, 287, 1481, 880, 1496, 288, 289, 884, + 157, 1499, 1500, 1577, 1503, 1504, 1505, 68, 69, 1541, + 70, 1550, 153, 154, 155, 127, 1569, 1571, 128, 1572, + 1573, 1575, 129, 130, 131, 132, 133, 1578, 134, 135, + 136, 137, 1584, 138, 139, 1579, 1580, 140, 141, 142, + 143, 1587, 297, 99, 144, 145, 1589, 507, 160, 670, + 1324, 904, 925, 146, 1302, 147, 595, 1303, 162, 1187, + 1323, 545, 774, 197, 1236, 743, 68, 69, 1062, 70, + 148, 149, 150, 1128, 127, 881, 1188, 128, 1076, 1290, + 1471, 129, 130, 131, 132, 133, 1080, 134, 135, 136, + 137, 94, 138, 139, 900, 1297, 140, 141, 142, 143, + 678, 239, 99, 144, 145, 151, 711, 282, 283, 284, + 0, 0, 146, 0, 147, 929, 629, 0, 0, 0, + 0, 0, 0, 0, 0, 1159, 0, 1160, 1161, 148, + 149, 150, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 11, 12, 13, 14, + 0, 469, 0, 287, 0, 0, 0, 686, 289, 0, + 157, 153, 154, 155, 151, 152, 68, 69, 0, 70, + 0, 0, 0, 0, 127, 0, 0, 128, 0, 0, + 0, 129, 130, 131, 132, 133, 0, 134, 135, 136, + 137, 0, 138, 139, 0, 0, 140, 141, 142, 143, + 0, 0, 99, 144, 145, 0, 0, 0, 0, 0, + 0, 0, 146, 0, 147, 0, 0, 0, 0, 0, + 153, 154, 155, 0, 0, 0, 0, 0, 0, 148, + 149, 150, 0, 911, 28, 29, 30, 31, 32, 33, + 34, 0, 0, 1162, 0, 0, 0, 0, 0, 35, + 68, 69, 0, 70, 0, 0, 0, 14, 127, 0, + 0, 128, 0, 0, 151, 129, 130, 131, 132, 133, + 0, 134, 135, 136, 137, 0, 138, 139, 912, 0, + 140, 141, 142, 143, 0, 0, 99, 144, 145, 0, + 0, 0, 0, 0, 0, 0, 146, 0, 147, 0, + 469, 0, 287, 0, 0, 0, 288, 289, 0, 157, + 0, 0, 0, 148, 149, 150, 0, 0, 0, 0, + 153, 154, 155, 859, 860, 861, 0, 862, 863, 864, + 865, 0, 866, 867, 193, 0, 868, 869, 870, 871, + 0, 0, 0, 872, 873, 0, 0, 0, 151, 152, + 0, 0, 0, 0, 68, 69, 0, 70, 0, 156, + 0, 0, 127, 0, 0, 128, 0, 0, 157, 129, + 130, 131, 132, 133, 0, 134, 135, 136, 137, 0, + 138, 139, 0, 0, 140, 141, 142, 143, 0, 0, + 99, 144, 145, 0, 0, 0, 0, 0, 0, 0, + 146, 0, 147, 0, 153, 154, 155, 0, 0, 0, + 0, 874, 0, 0, 0, 0, 0, 148, 149, 150, + 0, 0, 0, 0, 68, 69, 0, 70, 0, 0, + 0, 0, 127, 0, 0, 128, 0, 0, 0, 129, + 130, 131, 132, 133, 0, 134, 135, 136, 137, 0, + 138, 139, 151, 0, 140, 141, 142, 143, 0, 210, + 99, 144, 145, 0, 933, 0, 0, 0, 157, 0, + 146, 934, 147, 935, 936, 937, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, 0, 148, 149, 150, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 153, 154, + 155, 0, 938, 939, 940, 0, 0, 0, 68, 69, + 0, 70, 553, 0, 0, 0, 127, 0, 0, 128, + 0, 0, 0, 129, 130, 131, 132, 133, 0, 134, + 135, 136, 137, 210, 138, 139, 0, 0, 140, 141, + 142, 143, 157, 0, 99, 144, 145, 0, 941, 942, + 943, 0, 944, 0, 662, 945, 147, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 153, 154, + 155, 148, 149, 150, 0, 0, 0, 68, 69, 0, + 70, 0, 0, 0, 0, 127, 1531, 0, 128, 0, + 0, 0, 129, 130, 131, 132, 133, 0, 134, 135, + 136, 137, 0, 138, 139, 0, 151, 140, 141, 142, + 143, 0, 0, 99, 144, 145, 0, 0, 0, 0, + 0, 0, 0, 146, 0, 147, 4, 5, 6, 7, + 8, 0, 0, 0, 0, 0, 0, 210, 0, 0, + 148, 149, 150, 0, 0, 933, 157, 0, 9, 10, + 0, 0, 934, 0, 935, 936, 937, 0, 0, 0, + 0, 0, 153, 154, 155, 11, 12, 13, 14, 0, + 0, 0, 15, 16, 0, 714, 0, 0, 17, 0, + 0, 18, 0, 0, 68, 0, 0, 70, 19, 20, + 0, 0, 0, 938, 939, 940, 0, 3, 216, 0, + 0, 0, 0, 0, 0, 0, 0, 210, 0, 0, + 946, 0, 0, 1221, 1222, 1223, 157, 1224, 1225, 1226, + 1227, 0, 1228, 1229, 193, 0, 1230, 1231, 1232, 1233, + 0, 153, 154, 155, 0, 1234, 0, 0, 0, 941, + 942, 943, 0, 944, 21, 22, 945, 23, 24, 25, + 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 0, 0, 0, 0, 265, 128, 266, 0, 35, 129, + 130, 131, 132, 133, 0, 134, 135, 136, 137, 0, + 138, 139, 0, 0, 140, 141, 142, 143, 0, 0, + 0, 144, 145, 0, 0, 0, 0, 0, 0, 0, + 146, 210, 147, 0, 0, 0, 0, 0, 0, 0, + 157, 0, 0, 0, 0, 0, 0, 148, 149, 150, + 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 0, 0, 0, 1553, 8, 0, 0, + 0, 358, 359, 360, 361, 362, 363, 68, 0, 0, + 70, 1554, 151, 0, 933, 9, 10, 0, 0, 0, + 3, 934, 0, 935, 936, 937, 0, 1555, 0, 0, + 210, 0, 11, 12, 13, 14, 1556, 0, 0, 157, + 0, 0, 0, 364, 0, 0, 0, 0, 0, 0, + 1557, 1558, 1559, 1560, 0, 0, 0, 365, 0, 0, + 0, 1170, 938, 939, 940, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 0, 0, 1561, 1562, 1563, 1564, 1565, 1566, 1567, 0, + 0, 68, 366, 367, 70, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 941, 942, + 943, 0, 944, 0, 0, 945, 0, 0, 0, 0, + 28, 29, 30, 31, 32, 33, 34, 0, 368, 369, + 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, + 0, 0, 0, 345, 346, 347, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 0, 0, 0, 0, + 8, 0, 0, 0, 358, 359, 360, 361, 362, 363, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 11, 12, 13, 14, 0, + 0, 0, 0, 0, 0, 0, 364, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 157, 0, 0, 0, + 365, 0, 0, 0, 0, 0, 0, 345, 346, 347, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 0, 0, 0, 0, 8, 0, 1568, 0, 358, 359, + 360, 361, 362, 363, 0, 366, 367, 0, 0, 0, + 0, 0, 9, 10, 0, 0, 0, 0, 0, 0, + 1410, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 12, 13, 14, 28, 29, 30, 31, 32, 33, 34, + 364, 368, 741, 0, 0, 0, 0, 0, 35, 0, + 0, 128, 0, 0, 365, 129, 130, 131, 132, 133, + 0, 134, 135, 136, 137, 0, 138, 139, 0, 0, + 140, 141, 142, 143, 434, 0, 0, 144, 145, 0, + 0, 0, 0, 0, 0, 0, 146, 0, 147, 366, + 367, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 148, 149, 150, 0, 435, 0, 436, + 437, 438, 439, 0, 0, 0, 0, 28, 29, 30, + 31, 32, 33, 34, 0, 368, 928, 0, 0, 0, + 0, 0, 35, 0, 0, 0, 0, 0, 151, 0, + 0, 0, 0, 0, 0, 0, 440, 441, 442, 443, + 0, 0, 444, 0, 0, 128, 445, 446, 447, 129, + 130, 131, 132, 133, 0, 134, 135, 136, 137, 0, + 138, 139, 0, 0, 140, 141, 142, 143, 0, 0, + 0, 144, 145, 0, 0, 0, 0, 0, 0, 0, + 146, 0, 147, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 148, 149, 150, + 128, 0, 0, 0, 129, 130, 131, 132, 133, 0, + 134, 135, 136, 137, 0, 138, 139, 0, 0, 140, + 141, 142, 143, 0, 0, 0, 144, 145, 0, 0, + 0, 0, 151, 0, 0, 146, 0, 147, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 448, 128, 148, 149, 150, 129, 130, 131, 132, 133, + 0, 134, 135, 136, 137, 0, 138, 139, 0, 0, + 140, 141, 142, 143, 0, 0, 0, 144, 145, 0, + 0, 0, 0, 0, 0, 0, 146, 151, 147, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 148, 149, 150, 0, 0, 1019, 1020, + 0, 1021, 1022, 1023, 1024, 1025, 1026, 0, 1027, 1028, + 0, 1029, 1030, 1031, 1032, 1033, 4, 5, 6, 7, + 8, 3, 157, 0, 0, 0, 0, 0, 151, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 11, 12, 13, 14, 0, + 0, 0, 15, 16, 0, 0, 0, 0, 17, 0, + 520, 18, 0, 0, 0, 0, 0, 0, 19, 20, + 859, 860, 861, 0, 862, 863, 864, 865, 0, 866, + 867, 193, 0, 868, 869, 870, 871, 0, 0, 0, + 872, 873, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 724, 0, 0, + 0, 0, 0, 0, 0, 0, 157, 0, 0, 0, + 0, 0, 0, 0, 21, 22, 0, 23, 24, 25, + 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 0, 0, 508, 0, 0, 0, 3, 521, 35, 6, + 7, 8, 0, 0, 0, 0, 0, 0, 874, 0, + 0, 522, 880, 0, 0, 0, 523, 0, 0, 9, + 10, 157, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 11, 12, 13, 14, + 0, 524, 525, 0, 0, 520, 1034, 1035, 0, 1036, + 1037, 1038, 0, 1039, 1040, 0, 0, 1041, 1042, 0, + 1043, 526, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 157, 1044, 1045, 1046, 1047, 1048, 1049, 1050, + 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 624, 0, + 0, 0, 128, 0, 0, 0, 527, 528, 131, 132, + 133, 0, 134, 135, 136, 137, 0, 138, 139, 0, + 0, 140, 141, 142, 143, 0, 0, 0, 1286, 145, + 0, 1059, 0, 0, 28, 29, 30, 31, 32, 33, + 34, 0, 521, 529, 6, 7, 8, 0, 0, 35, + 0, 0, 0, 0, 0, 0, 522, 0, 0, 0, + 0, 523, 0, 0, 9, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1287, 0, 0, + 0, 11, 12, 13, 14, 0, 524, 525, 0, 28, + 29, 30, 31, 32, 33, 34, 1288, 0, 0, 0, + 0, 0, 0, 0, 35, 0, 526, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 625, 0, 613, 626, 0, 614, 615, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 527, 528, 800, 0, 0, 0, 0, 801, 802, + 0, 803, 804, 805, 806, 807, 808, 0, 809, 810, + 0, 811, 812, 813, 814, 815, 0, 0, 0, 28, + 29, 30, 31, 32, 33, 34, 0, 0, 1148, 0, + 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 28, 29, 30, 31, 32, + 33, 34, 0, 0, 627, 0, 0, 816, 0, 817, + 35, 0, 0, 800, 818, 0, 0, 0, 801, 802, + 0, 803, 804, 805, 806, 807, 808, 0, 809, 810, + 819, 811, 812, 813, 814, 815, 68, 69, 0, 70, + 859, 860, 861, 0, 862, 863, 864, 865, 0, 866, + 867, 193, 0, 868, 869, 870, 871, 0, 0, 0, + 872, 873, 0, 820, 0, 0, 0, 0, 0, 0, + 298, 0, 0, 0, 0, 0, 0, 816, 0, 817, + 0, 0, 0, 0, 818, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 299, + 819, 0, 0, 300, 0, 0, 301, 302, 0, 0, + 0, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 0, 0, 0, 0, 0, 874, 315, + 0, 0, 316, 820, 0, 0, 0, 0, 0, 317, + 0, 0, 0, 0, 0, 0, 0, 0, 318, 0, + 0, 0, 0, 821, 0, 822, 823, 824, 825, 826, + 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, + 837, 838, 0, 0, 0, 839, 0, 0, 0, 0, + 0, 0, 0, 0, 840, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 841, 0, 0, 0, + 0, 0, 0, 821, 0, 822, 823, 824, 825, 826, + 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, + 837, 838, 324, 98, 0, 839, 0, 0, 100, 0, + 101, 0, 0, 0, 840, 0, 0, 102, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 103, 325, 0, 326, 327, 328, + 329, 330, 0, 0, 0, 0, 331, 0, 0, 104, + 0, 0, 0, 0, 0, 332, 0, 0, 0, 0, + 333, 0, 334, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 335, 336, 337, 338, 339, 340, + 341, 342, 0, 0, 0, 0, 0, 343 }; -YYSTATIC YYCONST yyr_t YYFARDATA YYR1[]={ - - 0, 109, 109, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 136, - 136, 36, 36, 133, 133, 133, 2, 2, 1, 1, - 1, 9, 24, 24, 23, 23, 23, 134, 134, 134, - 134, 134, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 93, 93, 93, 93, 94, 94, 94, 94, 10, - 11, 73, 72, 72, 59, 61, 61, 61, 62, 62, - 62, 65, 65, 132, 132, 132, 60, 60, 60, 60, - 60, 60, 130, 130, 130, 119, 12, 12, 12, 12, - 12, 12, 118, 137, 113, 138, 139, 111, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 140, 140, 141, 141, 112, - 112, 142, 142, 56, 56, 57, 57, 69, 69, 18, - 18, 18, 18, 18, 18, 18, 19, 19, 68, 68, - 67, 67, 58, 21, 21, 22, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 116, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 4, 4, 35, 35, 16, 16, - 75, 75, 75, 75, 75, 75, 75, 7, 7, 7, - 7, 8, 8, 8, 8, 8, 8, 8, 8, 76, - 74, 74, 74, 74, 74, 74, 144, 144, 81, 81, - 81, 145, 145, 150, 150, 150, 150, 150, 150, 150, - 150, 146, 82, 82, 82, 147, 147, 151, 151, 151, - 151, 151, 151, 151, 152, 38, 38, 34, 34, 153, - 114, 78, 78, 78, 78, 78, 78, 78, 78, 78, - 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, - 78, 78, 78, 78, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 3, 3, 3, 13, 13, 13, 13, 13, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 154, 115, 115, 155, 155, 155, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 158, 159, 156, 161, 161, 160, 160, - 160, 163, 162, 162, 162, 162, 166, 166, 166, 169, - 164, 167, 168, 165, 165, 165, 117, 170, 170, 172, - 172, 172, 171, 171, 173, 173, 14, 14, 174, 174, - 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 174, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 175, 31, 31, 32, 32, 39, 39, 39, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 42, 42, 42, 43, - 43, 43, 47, 47, 46, 46, 45, 45, 44, 44, - 48, 48, 49, 49, 49, 50, 50, 50, 50, 51, - 51, 149, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, 108, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 6, - 6, 6, 6, 6, 53, 53, 54, 54, 55, 55, - 25, 25, 26, 26, 27, 27, 27, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 5, 5, 71, - 71, 71, 71, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 20, 20, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 30, 30, 29, 29, 29, 29, 29, 131, 131, - 131, 131, 131, 131, 64, 64, 64, 63, 63, 87, - 87, 84, 84, 85, 17, 17, 37, 37, 37, 37, - 37, 37, 37, 37, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86, 86, 176, - 176, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 121, 121, 88, 88, 89, 89, 177, 122, - 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, - 123, 123, 178, 178, 178, 66, 66, 179, 179, 179, - 179, 179, 179, 180, 182, 181, 124, 124, 125, 125, - 183, 183, 183, 183, 126, 148, 91, 91, 91, 91, - 91, 91, 91, 91, 91, 91, 127, 127, 184, 184, - 184, 184, 184, 184, 184, 128, 128, 92, 92, 92, - 129, 129, 185, 185, 185, 185 }; -YYSTATIC YYCONST yyr_t YYFARDATA YYR2[]={ - - 0, 0, 2, 4, 4, 3, 1, 1, 1, 1, - 1, 1, 4, 4, 4, 4, 1, 1, 1, 2, - 2, 3, 2, 2, 1, 1, 1, 4, 1, 0, - 2, 1, 3, 2, 4, 6, 1, 1, 1, 1, - 3, 1, 1, 1, 1, 4, 4, 4, 4, 4, - 4, 4, 2, 3, 2, 2, 2, 1, 1, 2, - 1, 2, 4, 6, 3, 5, 7, 9, 3, 4, - 7, 1, 1, 1, 2, 0, 2, 2, 0, 6, - 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, - 2, 3, 1, 2, 3, 7, 0, 2, 2, 2, - 2, 2, 3, 3, 2, 1, 4, 3, 0, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, - 3, 2, 2, 2, 5, 0, 2, 0, 2, 0, - 2, 3, 1, 0, 1, 1, 3, 0, 3, 1, - 1, 1, 1, 1, 1, 4, 0, 2, 4, 3, - 0, 2, 3, 0, 1, 5, 3, 4, 4, 4, - 1, 1, 1, 1, 1, 2, 2, 4, 13, 22, - 1, 1, 5, 3, 7, 5, 4, 7, 0, 2, - 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, - 2, 2, 2, 5, 0, 2, 0, 2, 0, 3, - 9, 9, 7, 7, 1, 1, 1, 2, 2, 1, - 4, 0, 1, 1, 2, 2, 2, 2, 1, 4, - 2, 5, 3, 2, 2, 1, 4, 3, 0, 2, - 2, 0, 2, 2, 2, 2, 2, 1, 1, 1, - 1, 9, 0, 2, 2, 0, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 0, 4, 1, 3, 1, - 13, 0, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 5, 8, 6, 5, 0, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 4, 4, 4, 4, 5, - 1, 1, 1, 0, 4, 4, 4, 4, 0, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 5, 1, 0, 2, 2, 1, 2, - 4, 5, 1, 1, 1, 1, 2, 1, 1, 1, - 1, 1, 4, 6, 4, 4, 11, 1, 5, 3, - 7, 5, 5, 3, 1, 2, 2, 1, 2, 4, - 4, 1, 2, 2, 2, 2, 2, 2, 2, 1, - 2, 1, 1, 1, 4, 4, 2, 4, 2, 0, - 1, 1, 3, 1, 3, 1, 0, 3, 5, 4, - 3, 5, 5, 5, 5, 5, 5, 2, 2, 2, - 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, - 4, 5, 5, 5, 5, 4, 4, 4, 4, 4, - 4, 3, 2, 0, 1, 1, 2, 1, 1, 1, - 1, 4, 4, 5, 4, 4, 4, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, - 8, 7, 7, 7, 7, 7, 0, 2, 2, 0, - 2, 2, 0, 2, 0, 2, 0, 2, 0, 2, - 0, 2, 0, 2, 2, 0, 2, 3, 2, 0, - 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 1, 2, 2, 2, - 2, 2, 2, 3, 2, 2, 2, 5, 3, 2, - 2, 2, 2, 2, 5, 4, 6, 2, 4, 0, - 3, 3, 1, 1, 0, 3, 0, 1, 1, 3, - 0, 1, 1, 3, 1, 3, 4, 4, 4, 4, - 5, 1, 1, 1, 1, 1, 1, 1, 3, 1, - 3, 4, 1, 0, 10, 6, 5, 6, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 1, 1, 1, 1, 2, 3, - 4, 6, 5, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 1, 2, 2, 4, 1, 2, 1, 2, - 1, 2, 1, 2, 1, 2, 1, 1, 0, 5, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, - 1, 3, 2, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 1, 3, 2, 3, 4, 2, 2, 2, 5, 5, - 7, 4, 3, 2, 3, 2, 1, 1, 2, 3, - 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, - 1, 1, 3, 0, 1, 1, 3, 2, 6, 7, - 3, 3, 3, 6, 0, 1, 3, 5, 6, 4, - 4, 1, 3, 3, 1, 1, 1, 1, 4, 1, - 6, 6, 6, 4, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 2, 5, 4, 7, 6, 7, 6, 9, - 8, 3, 8, 4, 0, 2, 0, 1, 3, 3, - 0, 2, 2, 2, 3, 2, 2, 2, 2, 2, - 0, 2, 3, 1, 1, 1, 1, 3, 8, 2, - 3, 1, 1, 3, 3, 3, 4, 6, 0, 2, - 3, 1, 3, 1, 4, 3, 0, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 0, 2, 2, 3, - 3, 4, 2, 1, 1, 3, 5, 0, 2, 2, - 0, 2, 4, 3, 1, 1 }; -YYSTATIC YYCONST short YYFARDATA YYCHK[]={ - --1000,-109,-110,-111,-113,-114,-116,-117,-118,-119, --120,-121,-122,-124,-126,-128,-130,-131,-132, 527, - 528, 462, 530, 531,-133,-134,-135, 534, 535,-139, - 411,-152, 413,-170,-137, 457,-176, 465, 410, 472, - 473, 432, -87, 433, -93, -94, 273, 451, 532, 536, - 537, 538, 539, 540, 541, 542, 59,-138, 412, 414, - 456, 449, 450, 452, -10, -11, 123, 123,-115, 123, - 123, 123, 123, -9, 264, -9, 529, -88, -24, 265, - 264, -24, 123,-140, 316, -1, -2, 261, 260, 263, - -78, -16, 91,-171, 123,-174, 278, 38,-175, 286, - 287, 284, 283, 282, 281, 288, -31, -32, 267, 91, - -9, -90, 471, 471, -92, -1, 471, -86, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, - 446, 447, 448, -31, -86, 263, -28, -70, -74, -93, - -94, 306, 297, 324, 325,-149, 33, 309, 276, 326, - -52, 275, 91, -5, -76, 268, 415, 416, 417, 360, - 359, 278, 298, 277, 281, 282, 283, 284, 286, 287, - 279, 290, 291, 292, 293, 271, -1, 296, -1, -1, - -1, -1, 262, -77,-172, 320, 381, 61, -73, 40, - -75, -7, -76, 269, 272, 327, 342, -8, 295, 300, - 302, 310, -31, -31,-112,-109, 125,-155, 418,-156, - 420,-154, 422, 423,-117,-157, -2,-131,-120,-133, --132,-135, 474, 460, 510,-158, 509,-160, 421, -95, - -96, -97, -98, -99,-108,-100,-101,-102,-103,-104, --105,-106,-107,-159,-163, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 123, 419, --123,-125,-127,-129, -9, -1, 463,-136, -70, -76, --141, 317, -71, -70, 91, -28,-149, 46, -7, 330, - 331, 332, 333, 334, 328, 348, 355, 339, 367, 368, - 369, 370, 371, 372, 373, 353, 380, 294, 374, -79, - -9,-173,-174, 42, 40, -31, 40, -14, 91, 40, - -14, 40, -14, 40, -14, 40, -14, 40, -14, 40, - 41, 267, -9, 263, 58, 44, 262, -1, 356, 357, - 358, 475, 381, 477, 478, 479, 480, -90, -91, -1, - 331, 332, -1, -71, 41, -36, 61, 288, 262, 44, - 392, 91, 38, 42, 361, 362, 363, 60, 392, 392, - 392, 392, -70, 306, -70, -75, -7, 33, -9, -1, - 280, 279, 289, -28, -1, -76, 42, 473, 47, -28, - 270, 272, 281, 282, 283, 284, 40, -36, -1, 331, - 332, 324, 347, 336, 337, 339, 340, 341, 342, 343, - 344, 345, 346, 364, 357, 338, 354, 328, 373, 294, - -2, 40, 61, -72, -71, -74, -28, -7, -7, 40, - 301, 303, 304, 305, 41, 41, 125,-143,-114,-111, --144,-146,-116,-117,-131,-120,-132, 454, 455,-148, - 510,-133,-135, 509, 323, 424, 429, 474, 410, 125, - -9, -9, 40, 453, 58, 91, -9, -71, 359, 366, - 543, 91,-161,-162,-164,-166,-167,-168, 313,-169, - 311, 315, 314, -9, -2, -9, -24, 40, -23, -24, - 266, 286, 287, -31, -9, -2, -75, -28, -76, 270, - 272, -71, -36, 343,-175, -7, -72, 40,-115,-158, - -2, -9, 125,-178, 464,-131,-179,-180, 469, 470, --181,-132,-135, 466, 125,-183,-177,-179,-182, 340, - 464, 467, 125,-184, 462, 410, 465, 296,-132,-135, - 125,-185, 462, 465,-132,-135, -89, 422, 125,-136, --142, -71, -1, 473, -7, -1, -13, 40, 40, -28, - 330, 331, 332, 333, 379, 373, 328, 481, 367, 368, - 369, 370, 377, 378, 294, 93, 125, 44, 40, -2, - 41, -23, -9, -23, -24, -9, -9, -9, 93, -9, - -9, 476, -1, -1, 332, 331, 329, 338, 392, 40, - 61, 43, 123, 40, 40, 263, -1, 93, -30, -29, - 275, -9, 40, 40, -54, -55, -28, -1, -1, -1, - -1, -70, -28, -9, -1, 280, 93, 93, 93, -1, - -1, -71, -1, 91, -9, -69, 60, 331, 332, 333, - 367, 368, 369, 40, 61, -36, 123, 40, 41, -71, - -3, 375, 376, -1, -9,-115, 123, 123, 123, -9, - -9, 123, -71, 359, 366, 543, 366, -81, -82, -91, - -25, -26, -27, 275, -13, 40, -9, 58, 274, -7, - 91, -1, 91, -1, -9,-161,-165,-158, 312,-165, --165,-165, -71,-158, -2, -9, 40, 40, 41, -71, - -1, 40, -31, -28, -6, -2, -9, 125, 318, 318, - 468, -31, -66, -9, 42, -36, 61, -31, 61, -31, - -31, 61, 61, -1, 471, -9, 471, 40, -1, 471, --177, 44, 93, -1, -28, -28, 91, -9, -36, -83, - -1, 40, 40,-173, -36, 41, 41, 93, 41, 41, - 41, 41, 41, -12, 263, 44, 58, 392, 331, 332, - 333, 367, 368, 369, -1, -84, -85, -36, 123, 262, - -64, -63, -71, 306, 44, 93, 44, 275, -71, -71, - 62, 44, 42, -5, -5, -5, 93, 274, 41, -68, - -19, -18, 43, 45, 306, 325, 307, 375, 294, -9, - -59, -61, -73, 274, -53, -22, 60, 41, 125,-112, --145,-147,-127, 274, -7, 91, -1, 91, -1, -71, - -71, -1, 373, 328, -7, 373, 328, -1, 41, 44, - -28, -25, 93, -9, -3, -1, -28, -9, -9, 44, - 93, -2, -9, -9, -24, 274, -36, 41, 40, 41, - 44, 44, -2, -9, -9, 41, 58, 40, 41, 40, - 41, 41, 40, 40, -5, -1, -9, 319, -1, -31, - -71, 93, -38, 481, 506, 507, 508, -9, 41, 392, - -83, 41, 389, 343, 344, 345, 390, 391, 301, 303, - 304, 305, 393, 396, 294, -4, 319, -34, -33,-153, - 482, 484, 485, 486, 487, 276, 277, 281, 282, 283, - 284, 286, 287, 257, 279, 290, 291, 292, 293, 488, - 489, 490, 492, 493, 494, 495, 496, 497, 498, 336, - 499, 280, 289, 338, 500, 343, 491, 359, 392, 504, - 271, 123, -9, 41, -14, -14, -14, -14, -14, -14, - 319, 283, 284, 458, 459, 461, -9, -9, -1, 41, - 44, 61, -59, 125, 44, 61, 263, 263, -29, -9, - 41, 41, -28, 40, -5, -1, 62, -58, -1, 40, - -19, 40, 41, 125, -62, -40,-135, -41, 298, 366, - 297, 286, 287, 284, 283, 282, 281, 293, 292, 291, - 290, 279, 278, 277,-175, 61, -3, 40, 40, 91, - -54, 125, 125,-150, 425, 426, 427, 428,-120,-132, --133,-135, 125,-151, 430, 431, 428,-132,-120,-133, --135, 125, -3, -28, -9, -9, 44, -93, 452, -1, - -28, -27, -38, 41, 392, -71, 93, 93, -71, -35, - 61, 318, 318, 41, 41, -1, 41, -25, -6, -6, - -66, 41, -9, 41, -3, 40, 93, 93, 93, 93, - -36, 41, 58, 58, 40, -35, -2, 41, 42, 91, - -32, 40, 483, 503, 277, 281, 282, 283, 284, 280, - -20, 40, -20, -20, -15, 512, 485, 486, 276, 277, - 281, 282, 283, 284, 286, 287, 279, 290, 291, 292, - 293, 42, 488, 489, 490, 492, 493, 496, 497, 499, - 280, 289, 257, 513, 514, 515, 516, 517, 518, 519, - 520, 521, 522, 523, 524, 525, 498, 490, 502, 41, - -2, 263, 263, 44, -84, -37, -17, -9, 283, -36, - -70, 321, 322, 125, -64, 123, 61, -25, -1, -67, - 44, -56, -57, -71, -9, -65,-135, 360, 365, 40, - 91, 40, 91, 40, 91, 40, 91, 40, 91, 40, - 91, 40, 91, 40, 91, 40, 91, 40, 91, 40, - 91, 40, 91, 40, 91, 284, 283, 282, 281, 40, - 91, 40, 91, -31, -36, 123, 40, -53, -22, -25, - -25, -9, 62, -75, -75, -75, -75, -75, -75, -75, - 511, -71, 93, 93, -71, -1, -2, -2, 274, 44, - -39, -41, -36, 299, 286, 287, 284, 283, 282, 281, - 279, 293, 292, 291, 290, 278, 277, -2, -9, 41, - 58, -89, -69, -34, -83, 394, 395, 394, 395, -9, - 93, -9, 43, 125, -36, 91, 91, 505, 44, 91, - 526, 38, 281, 282, 283, 284, 280, -9, 40, 40, - -62, 123, 41, -67, -68, 41, 44, 41, -60, -52, - 366, 297, 347, 299, 263, -9, 306, -70, 299, -9, - -40, -9, -23, -9, -9, -23, -24, -9, -24, -9, - -9, -9, -9, -9, -9, -9, -24, -9, -9, -9, - -9, -9, -9, -9, 40, 91, 40, 91, 40, 91, - 40, 91, -9, -9, -17, -9, 41, -59, 40, 40, - 41, 41, 93, -7, 274, 44, 40, -3, -71, 284, - 283, 282, 281, -66, 40, 41, 41, 41, 93, 43, - -9, 44, -9, -9, 61, -36, 93, 263, -9, 281, - 282, 283, -9, 125, -62, -71, -1, 91, 306, -70, - 41, 41, 93, 263, 41, 41, 93, 41, 93, 41, - 41, 93, 41, 41, 93, 41, 93, 41, 93, 41, - 93, 41, 93, 41, 93, 41, 93, 41, 93, 41, - 93, -24, -9, -9, -9, -9, -9, -9, -9, 41, - 93, 41, 93, 125, -25, -25, 62, -28, -3, -71, - -25, -21, -22, 60, 58, -25, -9, 93, -36, 93, - 93, -9, 41, 58, 58, 58, 41, 125, 61, 93, - 263, 40, 41, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 41, 93, 41, 93, 41, - 93, 41, 93, 40, 40, 41, 41, -71, -21, 41, - 40, -66, 41, 93, 44, 41, -33, 41, -9, -9, - -9, -40, -49, -50, -51, -42, -43, -47, -46, -45, - -44, -47, -46, -45, -44, 40, 40, 40, 40, -45, - -48, 274, 40, -35, -25, -80, -36, 41, 41, 41, - 41, 299, 263, 41, 299, 306, -70, 41, -40, 41, - -23, -9, 41, -23, -24, 41, -24, 41, -9, 41, - -9, 41, -9, 41, 41, 41, 41, -47, -46, -45, - -44, 41, 41, -17, -3, -25, 41, 123, 326, 381, - 382, 383, 310, 384, 385, 386, 387, 335, 349, 350, - 351, 352, 294, 44, 263, 41, 41, 41, 41, 40, - 41, 40, -36, -25, 511, -9, 41, 41, 359, 41, - -7, -28, -71, 274, -3, -21, 40, -25, 41 }; -YYSTATIC YYCONST short YYFARDATA YYDEF[]={ - - 1, -2, 2, 0, 0, 335, 6, 7, 8, 9, - 10, 11, 0, 0, 0, 0, 16, 17, 18, 0, - 0, 774, 0, 0, 24, 25, 26, 0, 28, 135, - 0, 271, 208, 0, 433, 0, 0, 780, 105, 837, - 92, 0, 433, 0, 83, 84, 85, 0, 0, 0, - 0, 0, 0, 57, 58, 0, 60, 108, 264, 389, - 0, 759, 760, 221, 433, 433, 139, 1, 0, 790, - 808, 826, 840, 19, 41, 20, 0, 0, 22, 42, - 43, 23, 29, 137, 0, 104, 38, 39, 36, 37, - 221, 188, 0, 386, 0, 393, 0, 0, 433, 396, - 396, 396, 396, 396, 396, 0, 0, 434, 435, 0, - 762, 0, 780, 816, 0, 93, 0, 0, 744, 745, - 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, - 756, 757, 758, 0, 0, 33, 0, 0, 0, 0, - 0, 0, 670, 0, 0, 221, 0, 686, 687, 0, - 691, 0, 0, 551, 235, 553, 554, 555, 556, 0, - 491, 693, 694, 695, 696, 697, 698, 699, 700, 701, - 0, 706, 707, 708, 709, 710, 557, 0, 52, 54, - 55, 56, 59, 0, 388, 390, 391, 0, 61, 0, - 71, 0, 214, 215, 216, 221, 221, 219, 0, 222, - 223, 228, 0, 0, 0, 0, 5, 336, 0, 338, - 0, 0, 342, 343, 344, 345, 0, 347, 348, 349, - 350, 351, 0, 0, 0, 357, 0, 0, 334, 506, - 0, 0, 0, 0, 433, 0, 221, 0, 0, 0, - 221, 0, 0, 335, 0, 492, 493, 494, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 364, 371, - 0, 0, 0, 0, 21, 776, 775, 0, 29, 552, - 107, 0, 136, 559, 0, 562, 221, 0, 313, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 287, 288, 289, 0, 0, 0, - 0, 0, 395, 0, 0, 0, 0, 407, 0, 0, - 408, 0, 409, 0, 410, 0, 411, 0, 412, 432, - 102, 436, 0, 761, 0, 0, 771, 779, 781, 782, - 783, 0, 785, 786, 787, 788, 789, 0, 0, 835, - 838, 839, 94, 720, 721, 722, 0, 0, 31, 0, - 0, 713, 675, 676, 677, 0, 0, 536, 0, 0, - 0, 0, 669, 0, 672, 230, 0, 0, 683, 685, - 688, 0, 690, 692, 0, 0, 0, 0, 0, 0, - 233, 234, 702, 703, 704, 705, 0, 53, 147, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 0, 131, 132, 133, 0, - 0, 103, 0, 0, 72, 73, 0, 217, 218, 0, - 224, 225, 226, 227, 64, 68, 3, 140, 335, 0, - 0, 0, 170, 171, 172, 173, 174, 0, 0, 0, - 0, 180, 181, 0, 0, 238, 252, 816, 105, 4, - 337, 339, -2, 0, 346, 0, 0, 0, 221, 0, - 0, 0, 365, 367, 0, 0, 0, 0, 0, 0, - 381, 382, 379, 507, 508, 509, 510, 505, 511, 512, - 44, 0, 0, 0, 514, 515, 516, 0, 519, 520, - 521, 522, 523, 0, 433, 0, 527, 529, 0, 368, - 0, 0, 12, 791, 0, 793, 794, 433, 0, 0, - 433, 801, 802, 0, 13, 809, 433, 811, 433, 813, - 0, 0, 14, 827, 0, 0, 0, 0, 833, 834, - 15, 841, 0, 0, 844, 845, 773, 777, 27, 30, - 138, 142, 0, 0, 0, 40, 0, 0, 294, 0, - 189, 190, 191, 192, 193, 194, 195, 0, 197, 198, - 199, 200, 201, 202, 0, 209, 392, 0, 0, 0, - 400, 0, 0, 0, 0, 0, 0, 0, 96, 764, - 0, 784, 806, 814, 817, 818, 819, 0, 0, 0, - 0, 0, 724, 729, 730, 34, 47, 673, 0, 711, - 714, 715, 0, 0, 0, 537, 538, 48, 49, 50, - 51, 671, 0, 682, 684, 689, 0, 0, 0, 0, - 558, 0, -2, 713, 0, 106, 156, 125, 126, 127, - 128, 129, 130, 0, 387, 62, 75, 69, 221, 0, - 534, 310, 311, -2, 0, 0, 139, 241, 255, 175, - 176, 826, 0, 221, 0, 0, 0, 0, 221, 0, - 0, 541, 542, 544, 0, -2, 0, 0, 0, 0, - 0, 359, 0, 0, 0, 366, 372, 383, 0, 373, - 374, 375, 380, 376, 377, 378, 0, 0, 513, 0, - -2, 0, 0, 0, 0, 532, 533, 363, 0, 0, - 0, 0, 0, 795, 796, 799, 0, 0, 0, 0, - 0, 0, 0, 828, 0, 832, 0, 0, 0, 0, - 433, 0, 560, 0, 0, 265, 0, 0, 294, 0, - 204, 563, 0, 394, 0, 399, 396, 397, 396, 396, - 396, 396, 396, 0, 763, 0, 0, 0, 820, 821, - 822, 823, 824, 825, 836, 0, 731, 0, 75, 32, - 0, 725, 0, 0, 0, 674, 713, 717, 0, 0, - 681, 0, 676, 547, 548, 549, 0, 0, 229, 0, - 0, 156, 149, 150, 151, 152, 153, 154, 0, 0, - 0, 78, 65, 0, 0, 0, 536, 220, 166, 0, - 0, 0, 0, 0, 0, 0, 183, 0, 0, 0, - 0, -2, 239, 240, 0, 253, 254, 815, 340, 313, - 265, 0, 352, 354, 355, 312, 0, 0, 0, 0, - 206, 0, 0, 0, 0, 0, 0, 525, -2, 528, - 529, 529, 369, 370, 792, 797, 0, 805, 800, 803, - 810, 812, 778, 804, 829, 830, 0, 0, 843, 0, - 141, 561, 0, 0, 0, 0, 0, 0, 290, 0, - 0, 293, 295, 296, 297, 298, 299, 300, 301, 302, - 303, 304, 0, 0, 0, 206, 0, 0, 267, 0, - 0, 0, 568, 569, 570, 571, 572, 573, 574, 575, - 576, 577, 578, 579, 0, 584, 585, 586, 587, 593, - 594, 595, 596, 597, 598, 599, 618, 618, 602, 618, - 620, 606, 608, 0, 610, 0, 612, 614, 0, 616, - 617, 269, 0, 398, 401, 402, 403, 404, 405, 406, - 0, 97, 98, 99, 100, 101, 766, 768, 807, 718, - 0, 0, 0, 723, 724, 0, 37, 35, 712, 716, - 678, 679, 539, -2, 550, 231, 148, 0, 160, 143, - 157, 0, 134, 63, 74, 76, 77, 440, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 433, 0, 534, -2, -2, 0, - 0, 167, 168, 242, 221, 221, 221, 221, 247, 248, - 249, 250, 169, 256, 221, 221, 221, 260, 261, 262, - 263, 177, 0, 0, 0, 0, 0, 186, 221, 236, - 0, 543, 545, 341, 0, 0, 358, 0, 361, 362, - 0, 0, 0, 45, 46, 517, 524, 0, 530, 531, - 0, 831, 842, 776, 147, 563, 314, 315, 316, 317, - 294, 292, 0, 0, 0, 187, 205, 196, 588, 0, - 0, 0, 0, 0, 613, 580, 581, 582, 583, 607, - 600, 0, 601, 603, 604, 621, 622, 623, 624, 625, - 626, 627, 628, 629, 630, 631, 0, 636, 637, 638, - 639, 640, 644, 645, 646, 647, 648, 649, 650, 651, - 652, 654, 655, 656, 657, 658, 659, 660, 661, 662, - 663, 664, 665, 666, 667, 668, 609, 611, 615, 203, - 95, 765, 767, 0, 732, 733, 736, 737, 0, 739, - 0, 734, 735, 719, 726, 78, 0, 0, 160, 159, - 156, 0, 144, 145, 0, 0, 80, 81, 82, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 66, 75, 70, 0, 0, 0, - 0, 0, 535, 243, 244, 245, 246, 257, 258, 259, - 221, 0, 182, 0, 185, 0, 546, 353, 0, 0, - 207, 437, 438, 439, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 384, 385, 526, - 0, 772, 0, 0, 0, 305, 306, 307, 308, 0, - 589, 0, 0, 268, 0, 0, 0, 0, 0, 0, - 642, 643, 632, 633, 634, 635, 653, 770, 0, 0, - 0, 78, 680, 158, 161, 162, 0, 155, 0, 86, - 87, 88, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 431, 0, -2, -2, - 212, 213, 0, 0, 0, 0, -2, 163, 360, 0, - 0, 0, 0, 0, -2, 266, 291, 309, 590, 0, - 0, 0, 0, 0, 0, 605, 641, 769, 0, 0, - 0, 0, 0, 727, 0, 146, 0, 0, 0, 90, - 441, 442, 0, 0, 444, 445, 0, 446, 0, 413, - 415, 0, 414, 416, 0, 417, 0, 418, 0, 419, - 0, 420, 0, 425, 0, 426, 0, 427, 0, 428, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 429, - 0, 430, 0, 67, 0, 0, 165, 0, 163, 184, - 0, 0, 164, 0, 0, 0, 0, 592, 0, 566, - 563, 0, 738, 0, 0, 0, 743, 728, 0, 91, - 89, 482, 443, 485, 489, 466, 469, 472, 474, 476, - 478, 472, 474, 476, 478, 421, 0, 422, 0, 423, - 0, 424, 0, 476, 480, 210, 211, 0, 0, 206, - -2, 798, 318, 591, 0, 565, 567, 619, 0, 0, - 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 472, 474, 476, 478, 0, - 0, 0, -2, 251, 0, 0, 0, 740, 741, 742, - 463, 483, 484, 464, 486, 0, 488, 465, 490, 447, - 467, 468, 448, 470, 471, 449, 473, 450, 475, 451, - 477, 452, 479, 453, 454, 455, 456, 0, 0, 0, - 0, 461, 462, 481, 0, 0, 356, 270, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, - 331, 332, 0, 0, 487, 457, 458, 459, 460, -2, - 0, 0, 0, 0, 0, 0, 564, 178, 221, 333, - 0, 0, 0, 0, 163, 0, -2, 0, 179 }; -#ifdef YYRECOVER -YYSTATIC YYCONST short yyrecover[] = { --1000 + +static const yytype_int16 yycheck[] = +{ + 5, 163, 25, 25, 1, 103, 104, 25, 1, 676, + 323, 323, 323, 43, 1, 20, 958, 57, 48, 93, + 722, 661, 94, 28, 29, 30, 31, 1, 989, 59, + 9, 21, 22, 1, 471, 1084, 77, 1, 188, 189, + 190, 191, 192, 12, 185, 23, 24, 735, 25, 14, + 7, 409, 7, 411, 1112, 5, 6, 19, 8, 9, + 25, 5, 6, 8, 8, 163, 9, 734, 7, 8, + 60, 63, 5, 6, 8, 8, 33, 9, 63, 484, + 485, 486, 9, 73, 56, 108, 184, 9, 20, 7, + 5, 6, 9, 8, 9, 1461, 9, 169, 7, 7, + 5, 6, 136, 8, 1079, 20, 129, 181, 41, 114, + 9, 116, 117, 118, 212, 9, 5, 6, 9, 8, + 20, 110, 112, 113, 146, 1449, 41, 149, 105, 152, + 5, 6, 136, 8, 377, 110, 41, 136, 5, 6, + 105, 8, 5, 6, 185, 8, 168, 5, 6, 1448, + 8, 156, 157, 197, 194, 9, 8, 1481, 293, 233, + 232, 105, 106, 107, 215, 300, 20, 157, 198, 5, + 6, 9, 8, 5, 6, 180, 8, 1446, 7, 9, + 10, 1480, 9, 10, 9, 208, 11, 64, 9, 10, + 11, 156, 44, 267, 882, 883, 14, 8, 163, 17, + 205, 206, 9, 10, 33, 210, 31, 32, 896, 1478, + 31, 32, 298, 5, 9, 9, 8, 9, 9, 1585, + 227, 9, 40, 41, 9, 10, 388, 45, 233, 47, + 292, 221, 222, 44, 239, 166, 54, 299, 260, 380, + 247, 65, 66, 5, 6, 210, 8, 321, 125, 1441, + 294, 656, 291, 71, 8, 1447, 279, 924, 87, 293, + 299, 39, 267, 268, 287, 1240, 297, 272, 86, 291, + 275, 276, 277, 51, 52, 280, 281, 682, 289, 298, + 285, 9, 272, 294, 217, 952, 974, 1479, 215, 293, + 274, 69, 291, 367, 392, 538, 286, 293, 289, 288, + 297, 293, 217, 299, 297, 9, 10, 11, 293, 298, + 297, 294, 217, 288, 11, 298, 390, 289, 291, 391, + 215, 290, 7, 297, 297, 304, 323, 31, 32, 297, + 323, 293, 12, 297, 31, 32, 323, 293, 293, 380, + 297, 119, 383, 299, 306, 60, 387, 292, 215, 323, + 292, 391, 295, 292, 298, 323, 300, 307, 292, 323, + 304, 305, 293, 289, 303, 395, 389, 299, 358, 291, + 360, 304, 1333, 5, 364, 416, 8, 299, 295, 297, + 289, 289, 295, 457, 299, 294, 294, 294, 793, 304, + 380, 298, 289, 383, 384, 295, 295, 387, 1456, 304, + 293, 295, 24, 25, 295, 289, 299, 385, 386, 298, + 400, 401, 34, 403, 293, 405, 393, 558, 492, 294, + 299, 495, 496, 388, 389, 566, 423, 1476, 393, 407, + 453, 421, 422, 289, 1492, 298, 423, 424, 425, 426, + 298, 1081, 847, 295, 449, 207, 451, 298, 885, 423, + 424, 425, 426, 304, 528, 553, 289, 295, 289, 250, + 251, 252, 298, 297, 469, 295, 298, 1169, 295, 51, + 295, 295, 544, 478, 295, 294, 294, 5, 6, 469, + 8, 9, 5, 6, 293, 8, 560, 492, 295, 294, + 13, 5, 6, 7, 8, 9, 294, 289, 463, 13, + 295, 295, 5, 6, 469, 8, 1467, 295, 5, 136, + 13, 8, 9, 291, 28, 589, 291, 558, 41, 509, + 295, 44, 545, 136, 302, 566, 598, 41, 51, 292, + 293, 105, 106, 107, 524, 525, 5, 6, 41, 8, + 136, 44, 40, 615, 13, 550, 551, 45, 51, 47, + 136, 65, 66, 543, 1496, 596, 54, 291, 292, 549, + 306, 295, 552, 593, 9, 10, 11, 607, 138, 139, + 294, 594, 41, 71, 298, 294, 566, 295, 719, 298, + 5, 6, 51, 8, 589, 294, 31, 32, 86, 298, + 294, 12, 622, 623, 5, 6, 295, 8, 628, 18, + 630, 55, 13, 57, 58, 59, 596, 1295, 1296, 295, + 708, 294, 925, 925, 925, 298, 714, 767, 61, 769, + 770, 771, 772, 773, 294, 5, 6, 297, 8, 634, + 41, 705, 706, 707, 271, 640, 159, 160, 161, 304, + 662, 294, 9, 633, 11, 159, 160, 161, 678, 294, + 673, 225, 294, 298, 295, 292, 159, 160, 161, 294, + 1327, 298, 652, 298, 31, 32, 292, 293, 305, 294, + 693, 676, 8, 298, 679, 294, 681, 297, 719, 298, + 5, 6, 294, 8, 299, 672, 298, 759, 13, 294, + 159, 160, 161, 298, 119, 120, 294, 294, 703, 689, + 690, 298, 707, 744, 291, 294, 711, 712, 713, 298, + 733, 294, 753, 294, 737, 298, 41, 298, 1406, 294, + 100, 101, 102, 298, 298, 1413, 300, 295, 294, 734, + 304, 305, 298, 294, 724, 294, 726, 298, 728, 298, + 730, 1408, 1100, 294, 1102, 125, 299, 298, 159, 160, + 161, 9, 23, 220, 744, 26, 27, 28, 29, 289, + 31, 32, 33, 293, 754, 755, 25, 291, 26, 27, + 28, 295, 295, 292, 293, 298, 848, 196, 756, 294, + 290, 855, 299, 298, 298, 857, 776, 206, 778, 779, + 209, 796, 40, 798, 294, 298, 291, 45, 298, 47, + 295, 294, 792, 294, 845, 23, 54, 298, 26, 27, + 28, 29, 1500, 31, 32, 33, 25, 26, 27, 28, + 29, 294, 299, 71, 72, 298, 848, 298, 293, 298, + 294, 905, 297, 294, 159, 160, 161, 294, 86, 219, + 303, 221, 222, 223, 224, 65, 66, 888, 878, 290, + 105, 106, 107, 1541, 5, 6, 294, 8, 848, 931, + 138, 139, 281, 282, 283, 284, 285, 286, 287, 117, + 46, 290, 48, 49, 50, 1542, 294, 296, 75, 76, + 77, 136, 294, 957, 1572, 959, 292, 298, 18, 876, + 880, 295, 910, 294, 917, 567, 568, 569, 104, 1587, + 923, 294, 907, 109, 25, 26, 27, 28, 29, 914, + 291, 292, 7, 903, 111, 112, 113, 1584, 289, 924, + 26, 27, 28, 29, 75, 76, 291, 292, 925, 919, + 7, 921, 925, 292, 975, 976, 293, 294, 925, 926, + 927, 1013, 929, 75, 76, 77, 295, 952, 975, 976, + 295, 925, 926, 927, 300, 929, 19, 925, 926, 927, + 20, 925, 926, 927, 834, 835, 971, 26, 27, 28, + 29, 208, 18, 298, 19, 301, 105, 106, 107, 111, + 112, 113, 292, 292, 110, 975, 976, 1149, 1150, 1151, + 1152, 289, 5, 6, 1066, 8, 289, 1159, 1160, 1161, + 15, 16, 17, 289, 289, 20, 21, 22, 23, 24, + 1000, 26, 27, 28, 29, 303, 31, 32, 289, 19, + 35, 36, 37, 38, 28, 29, 41, 42, 43, 294, + 62, 105, 106, 107, 305, 62, 51, 294, 53, 169, + 170, 171, 172, 298, 294, 300, 295, 294, 299, 304, + 305, 295, 295, 68, 69, 70, 295, 295, 303, 63, + 295, 295, 295, 193, 194, 195, 196, 26, 27, 28, + 29, 1145, 1146, 1063, 212, 281, 282, 283, 284, 285, + 286, 287, 297, 297, 290, 297, 294, 305, 103, 18, + 296, 215, 215, 295, 1116, 1085, 1086, 1087, 292, 297, + 290, 292, 1092, 1093, 1094, 1095, 1096, 1097, 8, 1099, + 1100, 1101, 41, 1103, 1104, 1105, 1106, 1107, 1108, 1109, + 1098, 1111, 297, 1113, 1102, 1115, 290, 1117, 1486, 1487, + 176, 177, 1110, 294, 294, 5, 6, 1142, 8, 1180, + 294, 294, 1214, 295, 301, 295, 1187, 18, 1189, 295, + 196, 281, 282, 283, 284, 285, 286, 287, 19, 295, + 290, 295, 208, 19, 210, 294, 296, 213, 214, 298, + 41, 300, 299, 292, 1139, 304, 305, 299, 295, 292, + 292, 1171, 298, 294, 1149, 1150, 1151, 1152, 295, 303, + 105, 106, 107, 294, 1159, 1160, 1161, 295, 202, 203, + 1190, 205, 295, 73, 294, 75, 76, 294, 294, 1199, + 295, 1309, 82, 295, 295, 234, 1206, 1207, 242, 294, + 246, 22, 295, 290, 298, 154, 300, 1301, 1218, 297, + 304, 305, 297, 289, 295, 281, 282, 283, 284, 285, + 286, 287, 196, 301, 290, 294, 303, 294, 1238, 1239, + 296, 303, 1326, 136, 1241, 299, 299, 1247, 1248, 1249, + 1250, 1251, 1252, 1335, 1254, 1287, 299, 196, 299, 299, + 299, 20, 295, 62, 62, 1253, 8, 206, 5, 6, + 209, 8, 249, 154, 1289, 295, 13, 295, 295, 16, + 289, 294, 307, 20, 21, 22, 23, 24, 294, 26, + 27, 28, 29, 298, 31, 32, 298, 295, 35, 36, + 37, 38, 299, 295, 41, 42, 43, 295, 294, 294, + 166, 295, 1327, 295, 51, 196, 53, 295, 292, 299, + 299, 255, 292, 1407, 104, 206, 19, 300, 209, 109, + 295, 68, 69, 70, 1334, 303, 297, 299, 294, 294, + 294, 1341, 281, 282, 283, 284, 285, 286, 287, 294, + 294, 290, 294, 294, 104, 1352, 294, 296, 294, 109, + 290, 294, 294, 294, 299, 8, 103, 295, 105, 106, + 107, 295, 299, 298, 295, 300, 1409, 299, 1462, 304, + 305, 14, 119, 120, 17, 299, 295, 1469, 295, 295, + 301, 299, 295, 1408, 299, 295, 295, 299, 295, 295, + 281, 282, 283, 284, 285, 286, 287, 40, 41, 290, + 299, 299, 45, 295, 47, 296, 299, 295, 295, 295, + 299, 54, 159, 160, 161, 1425, 1426, 1427, 5, 6, + 299, 8, 299, 295, 295, 299, 13, 295, 71, 16, + 295, 292, 299, 20, 21, 22, 23, 24, 19, 26, + 27, 28, 29, 86, 31, 32, 295, 295, 35, 36, + 37, 38, 1494, 1545, 41, 42, 43, 294, 8, 299, + 1578, 299, 294, 299, 51, 294, 53, 1477, 294, 294, + 303, 295, 1482, 1483, 1484, 303, 1486, 295, 1488, 1489, + 1490, 68, 69, 70, 303, 295, 299, 294, 1582, 1487, + 294, 281, 282, 283, 284, 285, 286, 287, 295, 299, + 1510, 1511, 1512, 295, 299, 299, 296, 295, 294, 294, + 294, 294, 294, 294, 294, 294, 103, 1542, 105, 106, + 107, 281, 282, 283, 284, 285, 286, 287, 294, 294, + 290, 18, 119, 120, 295, 294, 296, 294, 1581, 294, + 8, 299, 295, 19, 295, 295, 300, 303, 294, 294, + 299, 298, 294, 300, 294, 298, 295, 304, 305, 1584, + 307, 295, 294, 1573, 295, 295, 295, 5, 6, 294, + 8, 8, 159, 160, 161, 13, 295, 295, 16, 294, + 294, 255, 20, 21, 22, 23, 24, 103, 26, 27, + 28, 29, 19, 31, 32, 295, 295, 35, 36, 37, + 38, 294, 179, 41, 42, 43, 295, 291, 25, 463, + 1179, 702, 716, 51, 1136, 53, 393, 1138, 25, 962, + 1178, 344, 607, 57, 1066, 564, 5, 6, 843, 8, + 68, 69, 70, 885, 13, 673, 964, 16, 850, 1121, + 1421, 20, 21, 22, 23, 24, 855, 26, 27, 28, + 29, 10, 31, 32, 690, 1130, 35, 36, 37, 38, + 475, 115, 41, 42, 43, 103, 526, 105, 106, 107, + -1, -1, 51, -1, 53, 720, 424, -1, -1, -1, + -1, -1, -1, -1, -1, 172, -1, 174, 175, 68, + 69, 70, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 193, 194, 195, 196, + -1, 298, -1, 300, -1, -1, -1, 304, 305, -1, + 307, 159, 160, 161, 103, 104, 5, 6, -1, 8, + -1, -1, -1, -1, 13, -1, -1, 16, -1, -1, + -1, 20, 21, 22, 23, 24, -1, 26, 27, 28, + 29, -1, 31, 32, -1, -1, 35, 36, 37, 38, + -1, -1, 41, 42, 43, -1, -1, -1, -1, -1, + -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, + 159, 160, 161, -1, -1, -1, -1, -1, -1, 68, + 69, 70, -1, 72, 281, 282, 283, 284, 285, 286, + 287, -1, -1, 290, -1, -1, -1, -1, -1, 296, + 5, 6, -1, 8, -1, -1, -1, 196, 13, -1, + -1, 16, -1, -1, 103, 20, 21, 22, 23, 24, + -1, 26, 27, 28, 29, -1, 31, 32, 117, -1, + 35, 36, 37, 38, -1, -1, 41, 42, 43, -1, + -1, -1, -1, -1, -1, -1, 51, -1, 53, -1, + 298, -1, 300, -1, -1, -1, 304, 305, -1, 307, + -1, -1, -1, 68, 69, 70, -1, -1, -1, -1, + 159, 160, 161, 22, 23, 24, -1, 26, 27, 28, + 29, -1, 31, 32, 33, -1, 35, 36, 37, 38, + -1, -1, -1, 42, 43, -1, -1, -1, 103, 104, + -1, -1, -1, -1, 5, 6, -1, 8, -1, 298, + -1, -1, 13, -1, -1, 16, -1, -1, 307, 20, + 21, 22, 23, 24, -1, 26, 27, 28, 29, -1, + 31, 32, -1, -1, 35, 36, 37, 38, -1, -1, + 41, 42, 43, -1, -1, -1, -1, -1, -1, -1, + 51, -1, 53, -1, 159, 160, 161, -1, -1, -1, + -1, 110, -1, -1, -1, -1, -1, 68, 69, 70, + -1, -1, -1, -1, 5, 6, -1, 8, -1, -1, + -1, -1, 13, -1, -1, 16, -1, -1, -1, 20, + 21, 22, 23, 24, -1, 26, 27, 28, 29, -1, + 31, 32, 103, -1, 35, 36, 37, 38, -1, 298, + 41, 42, 43, -1, 39, -1, -1, -1, 307, -1, + 51, 46, 53, 48, 49, 50, -1, -1, -1, -1, + -1, -1, 0, -1, -1, -1, -1, 68, 69, 70, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 18, -1, -1, -1, -1, -1, -1, -1, 159, 160, + 161, -1, 87, 88, 89, -1, -1, -1, 5, 6, + -1, 8, 103, -1, -1, -1, 13, -1, -1, 16, + -1, -1, -1, 20, 21, 22, 23, 24, -1, 26, + 27, 28, 29, 298, 31, 32, -1, -1, 35, 36, + 37, 38, 307, -1, 41, 42, 43, -1, 133, 134, + 135, -1, 137, -1, 51, 140, 53, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 159, 160, + 161, 68, 69, 70, -1, -1, -1, 5, 6, -1, + 8, -1, -1, -1, -1, 13, 295, -1, 16, -1, + -1, -1, 20, 21, 22, 23, 24, -1, 26, 27, + 28, 29, -1, 31, 32, -1, 103, 35, 36, 37, + 38, -1, -1, 41, 42, 43, -1, -1, -1, -1, + -1, -1, -1, 51, -1, 53, 154, 155, 156, 157, + 158, -1, -1, -1, -1, -1, -1, 298, -1, -1, + 68, 69, 70, -1, -1, 39, 307, -1, 176, 177, + -1, -1, 46, -1, 48, 49, 50, -1, -1, -1, + -1, -1, 159, 160, 161, 193, 194, 195, 196, -1, + -1, -1, 200, 201, -1, 103, -1, -1, 206, -1, + -1, 209, -1, -1, 5, -1, -1, 8, 216, 217, + -1, -1, -1, 87, 88, 89, -1, 18, 7, -1, + -1, -1, -1, -1, -1, -1, -1, 298, -1, -1, + 295, -1, -1, 22, 23, 24, 307, 26, 27, 28, + 29, -1, 31, 32, 33, -1, 35, 36, 37, 38, + -1, 159, 160, 161, -1, 44, -1, -1, -1, 133, + 134, 135, -1, 137, 272, 273, 140, 275, 276, 277, + -1, 279, 280, 281, 282, 283, 284, 285, 286, 287, + -1, -1, -1, -1, 15, 16, 17, -1, 296, 20, + 21, 22, 23, 24, -1, 26, 27, 28, 29, -1, + 31, 32, -1, -1, 35, 36, 37, 38, -1, -1, + -1, 42, 43, -1, -1, -1, -1, -1, -1, -1, + 51, 298, 53, -1, -1, -1, -1, -1, -1, -1, + 307, -1, -1, -1, -1, -1, -1, 68, 69, 70, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, -1, -1, -1, 39, 158, -1, -1, + -1, 162, 163, 164, 165, 166, 167, 5, -1, -1, + 8, 54, 103, -1, 39, 176, 177, -1, -1, -1, + 18, 46, -1, 48, 49, 50, -1, 70, -1, -1, + 298, -1, 193, 194, 195, 196, 79, -1, -1, 307, + -1, -1, -1, 204, -1, -1, -1, -1, -1, -1, + 93, 94, 95, 96, -1, -1, -1, 218, -1, -1, + -1, 295, 87, 88, 89, 178, 179, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + -1, -1, 125, 126, 127, 128, 129, 130, 131, -1, + -1, 5, 253, 254, 8, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 18, -1, -1, -1, 133, 134, + 135, -1, 137, -1, -1, 140, -1, -1, -1, -1, + 281, 282, 283, 284, 285, 286, 287, -1, 289, 290, + -1, -1, -1, -1, -1, 296, -1, -1, -1, -1, + -1, -1, -1, 141, 142, 143, 144, 145, 146, 147, + 148, 149, 150, 151, 152, 153, -1, -1, -1, -1, + 158, -1, -1, -1, 162, 163, 164, 165, 166, 167, + -1, -1, -1, -1, -1, -1, -1, -1, 176, 177, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 193, 194, 195, 196, -1, + -1, -1, -1, -1, -1, -1, 204, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 307, -1, -1, -1, + 218, -1, -1, -1, -1, -1, -1, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, + -1, -1, -1, -1, 158, -1, 289, -1, 162, 163, + 164, 165, 166, 167, -1, 253, 254, -1, -1, -1, + -1, -1, 176, 177, -1, -1, -1, -1, -1, -1, + 295, -1, -1, -1, -1, -1, -1, -1, -1, 193, + 194, 195, 196, 281, 282, 283, 284, 285, 286, 287, + 204, 289, 290, -1, -1, -1, -1, -1, 296, -1, + -1, 16, -1, -1, 218, 20, 21, 22, 23, 24, + -1, 26, 27, 28, 29, -1, 31, 32, -1, -1, + 35, 36, 37, 38, 39, -1, -1, 42, 43, -1, + -1, -1, -1, -1, -1, -1, 51, -1, 53, 253, + 254, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 68, 69, 70, -1, 72, -1, 74, + 75, 76, 77, -1, -1, -1, -1, 281, 282, 283, + 284, 285, 286, 287, -1, 289, 290, -1, -1, -1, + -1, -1, 296, -1, -1, -1, -1, -1, 103, -1, + -1, -1, -1, -1, -1, -1, 111, 112, 113, 114, + -1, -1, 117, -1, -1, 16, 121, 122, 123, 20, + 21, 22, 23, 24, -1, 26, 27, 28, 29, -1, + 31, 32, -1, -1, 35, 36, 37, 38, -1, -1, + -1, 42, 43, -1, -1, -1, -1, -1, -1, -1, + 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, + 18, -1, -1, -1, -1, -1, -1, 68, 69, 70, + 16, -1, -1, -1, 20, 21, 22, 23, 24, -1, + 26, 27, 28, 29, -1, 31, 32, -1, -1, 35, + 36, 37, 38, -1, -1, -1, 42, 43, -1, -1, + -1, -1, 103, -1, -1, 51, -1, 53, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 225, 16, 68, 69, 70, 20, 21, 22, 23, 24, + -1, 26, 27, 28, 29, -1, 31, 32, -1, -1, + 35, 36, 37, 38, -1, -1, -1, 42, 43, -1, + -1, -1, -1, -1, -1, -1, 51, 103, 53, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 68, 69, 70, -1, -1, 21, 22, + -1, 24, 25, 26, 27, 28, 29, -1, 31, 32, + -1, 34, 35, 36, 37, 38, 154, 155, 156, 157, + 158, 18, 307, -1, -1, -1, -1, -1, 103, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 176, 177, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 193, 194, 195, 196, -1, + -1, -1, 200, 201, -1, -1, -1, -1, 206, -1, + 67, 209, -1, -1, -1, -1, -1, -1, 216, 217, + 22, 23, 24, -1, 26, 27, 28, 29, -1, 31, + 32, 33, -1, 35, 36, 37, 38, -1, -1, -1, + 42, 43, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 298, -1, -1, + -1, -1, -1, -1, -1, -1, 307, -1, -1, -1, + -1, -1, -1, -1, 272, 273, -1, 275, 276, 277, + -1, 279, 280, 281, 282, 283, 284, 285, 286, 287, + -1, -1, 290, -1, -1, -1, 18, 154, 296, 156, + 157, 158, -1, -1, -1, -1, -1, -1, 110, -1, + -1, 168, 298, -1, -1, -1, 173, -1, -1, 176, + 177, 307, 18, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 193, 194, 195, 196, + -1, 198, 199, -1, -1, 67, 229, 230, -1, 232, + 233, 234, -1, 236, 237, -1, -1, 240, 241, -1, + 243, 218, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 307, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, 266, 267, 268, 269, 270, 84, -1, + -1, -1, 16, -1, -1, -1, 253, 254, 22, 23, + 24, -1, 26, 27, 28, 29, -1, 31, 32, -1, + -1, 35, 36, 37, 38, -1, -1, -1, 42, 43, + -1, 304, -1, -1, 281, 282, 283, 284, 285, 286, + 287, -1, 154, 290, 156, 157, 158, -1, -1, 296, + -1, -1, -1, -1, -1, -1, 168, -1, -1, -1, + -1, 173, -1, -1, 176, 177, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 91, -1, -1, + -1, 193, 194, 195, 196, -1, 198, 199, -1, 281, + 282, 283, 284, 285, 286, 287, 110, -1, -1, -1, + -1, -1, -1, -1, 296, -1, 218, -1, -1, -1, + 196, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 208, -1, 210, 211, -1, 213, 214, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 253, 254, 16, -1, -1, -1, -1, 21, 22, + -1, 24, 25, 26, 27, 28, 29, -1, 31, 32, + -1, 34, 35, 36, 37, 38, -1, -1, -1, 281, + 282, 283, 284, 285, 286, 287, -1, -1, 290, -1, + -1, -1, -1, -1, 296, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 281, 282, 283, 284, 285, + 286, 287, -1, -1, 290, -1, -1, 80, -1, 82, + 296, -1, -1, 16, 87, -1, -1, -1, 21, 22, + -1, 24, 25, 26, 27, 28, 29, -1, 31, 32, + 103, 34, 35, 36, 37, 38, 5, 6, -1, 8, + 22, 23, 24, -1, 26, 27, 28, 29, -1, 31, + 32, 33, -1, 35, 36, 37, 38, -1, -1, -1, + 42, 43, -1, 136, -1, -1, -1, -1, -1, -1, + 39, -1, -1, -1, -1, -1, -1, 80, -1, 82, + -1, -1, -1, -1, 87, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 68, + 103, -1, -1, 72, -1, -1, 75, 76, -1, -1, + -1, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, -1, -1, -1, -1, -1, 110, 98, + -1, -1, 101, 136, -1, -1, -1, -1, -1, 108, + -1, -1, -1, -1, -1, -1, -1, -1, 117, -1, + -1, -1, -1, 226, -1, 228, 229, 230, 231, 232, + 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, -1, -1, -1, 248, -1, -1, -1, -1, + -1, -1, -1, -1, 257, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 289, -1, -1, -1, + -1, -1, -1, 226, -1, 228, 229, 230, 231, 232, + 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, 39, 40, -1, 248, -1, -1, 45, -1, + 47, -1, -1, -1, 257, -1, -1, 54, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 71, 72, -1, 74, 75, 76, + 77, 78, -1, -1, -1, -1, 83, -1, -1, 86, + -1, -1, -1, -1, -1, 92, -1, -1, -1, -1, + 97, -1, 99, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 111, 112, 113, 114, 115, 116, + 117, 118, -1, -1, -1, -1, -1, 124 +}; + +/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of + state STATE-NUM. */ +static const yytype_int16 yystos[] = +{ + 0, 309, 0, 18, 154, 155, 156, 157, 158, 176, + 177, 193, 194, 195, 196, 200, 201, 206, 209, 216, + 217, 272, 273, 275, 276, 277, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 296, 310, 313, 319, 320, + 321, 322, 323, 324, 331, 333, 334, 336, 337, 338, + 339, 340, 341, 358, 376, 380, 402, 403, 458, 461, + 467, 468, 469, 473, 482, 485, 490, 215, 5, 6, + 8, 314, 315, 298, 362, 64, 125, 404, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 466, 466, 8, 14, 17, 40, 41, + 45, 47, 54, 71, 86, 294, 325, 363, 364, 365, + 366, 297, 298, 274, 470, 215, 474, 491, 215, 315, + 9, 316, 316, 9, 10, 317, 317, 13, 16, 20, + 21, 22, 23, 24, 26, 27, 28, 29, 31, 32, + 35, 36, 37, 38, 42, 43, 51, 53, 68, 69, + 70, 103, 104, 159, 160, 161, 298, 307, 315, 321, + 322, 366, 367, 425, 448, 449, 454, 455, 289, 315, + 315, 315, 315, 7, 12, 411, 412, 411, 411, 289, + 342, 60, 343, 289, 381, 387, 23, 26, 27, 28, + 29, 31, 32, 33, 289, 305, 405, 408, 410, 411, + 316, 289, 289, 289, 289, 487, 293, 316, 359, 314, + 298, 366, 425, 448, 450, 454, 7, 33, 297, 312, + 292, 294, 294, 46, 48, 49, 50, 364, 364, 326, + 367, 450, 297, 454, 294, 316, 316, 207, 315, 474, + 100, 101, 102, 125, 219, 221, 222, 223, 224, 315, + 75, 76, 315, 315, 454, 26, 27, 28, 29, 448, + 51, 448, 24, 25, 34, 15, 17, 454, 217, 304, + 315, 366, 307, 315, 316, 136, 136, 136, 363, 364, + 136, 306, 105, 106, 107, 136, 298, 300, 304, 305, + 311, 448, 312, 295, 12, 295, 295, 309, 39, 68, + 72, 75, 76, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 98, 101, 108, 117, 315, + 450, 61, 344, 345, 39, 72, 74, 75, 76, 77, + 78, 83, 92, 97, 99, 111, 112, 113, 114, 115, + 116, 117, 118, 124, 364, 141, 142, 143, 144, 145, + 146, 147, 148, 149, 150, 151, 152, 153, 162, 163, + 164, 165, 166, 167, 204, 218, 253, 254, 289, 290, + 313, 314, 320, 331, 386, 388, 389, 390, 391, 393, + 394, 402, 426, 427, 428, 429, 430, 431, 432, 433, + 434, 435, 436, 437, 438, 439, 440, 458, 468, 304, + 294, 298, 407, 294, 407, 294, 407, 294, 407, 294, + 407, 294, 407, 294, 406, 408, 294, 411, 295, 7, + 8, 292, 303, 475, 483, 488, 492, 73, 75, 76, + 82, 315, 315, 299, 39, 72, 74, 75, 76, 77, + 111, 112, 113, 114, 117, 121, 122, 123, 225, 454, + 297, 217, 315, 364, 294, 297, 294, 289, 294, 291, + 8, 316, 316, 295, 289, 294, 312, 119, 120, 298, + 315, 383, 450, 299, 166, 471, 315, 220, 136, 448, + 25, 315, 450, 315, 299, 299, 299, 315, 316, 315, + 315, 315, 454, 315, 315, 294, 294, 315, 20, 299, + 316, 456, 457, 443, 444, 454, 290, 311, 290, 294, + 75, 76, 77, 111, 112, 113, 300, 349, 346, 450, + 67, 154, 168, 173, 198, 199, 218, 253, 254, 290, + 313, 320, 331, 341, 357, 358, 368, 372, 380, 402, + 458, 468, 486, 294, 294, 384, 316, 316, 316, 298, + 110, 288, 298, 103, 450, 303, 197, 294, 387, 55, + 57, 58, 59, 392, 395, 396, 397, 398, 399, 400, + 314, 316, 389, 314, 316, 316, 317, 11, 31, 32, + 294, 317, 318, 314, 316, 363, 15, 17, 366, 454, + 450, 87, 312, 410, 364, 326, 294, 411, 294, 316, + 316, 316, 316, 317, 318, 318, 290, 292, 314, 295, + 316, 316, 208, 210, 213, 214, 290, 320, 331, 458, + 476, 478, 479, 481, 84, 208, 211, 290, 472, 478, + 480, 484, 41, 154, 206, 209, 290, 320, 331, 489, + 206, 209, 290, 320, 331, 493, 75, 76, 77, 111, + 112, 113, 294, 294, 315, 315, 299, 454, 312, 462, + 463, 289, 51, 450, 459, 460, 7, 292, 295, 295, + 325, 327, 328, 300, 356, 442, 19, 335, 472, 136, + 315, 19, 299, 449, 449, 449, 304, 450, 450, 20, + 292, 299, 301, 292, 316, 39, 51, 52, 69, 119, + 291, 302, 350, 351, 352, 292, 110, 369, 373, 316, + 316, 487, 110, 288, 103, 450, 289, 289, 289, 387, + 289, 316, 312, 382, 298, 454, 303, 316, 298, 315, + 298, 315, 316, 364, 19, 294, 20, 384, 445, 446, + 447, 290, 450, 392, 56, 389, 401, 314, 316, 389, + 401, 401, 401, 62, 62, 294, 294, 315, 450, 294, + 411, 454, 314, 316, 441, 295, 312, 295, 299, 295, + 295, 295, 295, 295, 406, 295, 303, 8, 292, 212, + 297, 304, 316, 477, 297, 312, 411, 411, 297, 297, + 411, 411, 294, 215, 316, 315, 215, 315, 215, 316, + 16, 21, 22, 24, 25, 26, 27, 28, 29, 31, + 32, 34, 35, 36, 37, 38, 80, 82, 87, 103, + 136, 226, 228, 229, 230, 231, 232, 233, 234, 235, + 236, 237, 238, 239, 240, 241, 242, 243, 244, 248, + 257, 289, 378, 379, 451, 63, 360, 299, 297, 295, + 292, 327, 8, 297, 290, 292, 8, 297, 290, 22, + 23, 24, 26, 27, 28, 29, 31, 32, 35, 36, + 37, 38, 42, 43, 110, 320, 329, 409, 410, 414, + 298, 443, 294, 294, 315, 383, 28, 29, 63, 202, + 203, 205, 411, 315, 315, 449, 294, 295, 295, 316, + 457, 454, 295, 294, 351, 294, 315, 354, 301, 450, + 450, 72, 117, 315, 450, 72, 117, 364, 315, 298, + 315, 298, 315, 364, 19, 345, 370, 374, 290, 488, + 295, 136, 382, 39, 46, 48, 49, 50, 87, 88, + 89, 133, 134, 135, 137, 140, 295, 250, 251, 252, + 316, 225, 377, 316, 299, 316, 316, 292, 299, 454, + 383, 445, 454, 295, 292, 314, 316, 314, 316, 316, + 317, 19, 312, 295, 294, 292, 292, 295, 295, 407, + 407, 407, 407, 407, 407, 316, 316, 316, 294, 303, + 294, 295, 295, 294, 294, 295, 295, 316, 449, 315, + 63, 315, 295, 25, 26, 27, 28, 29, 294, 452, + 242, 234, 246, 294, 227, 247, 22, 452, 452, 21, + 22, 24, 25, 26, 27, 28, 29, 31, 32, 34, + 35, 36, 37, 38, 229, 230, 232, 233, 234, 236, + 237, 240, 241, 243, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 304, + 453, 295, 412, 298, 304, 314, 297, 361, 28, 65, + 66, 312, 316, 448, 464, 465, 462, 290, 297, 289, + 459, 289, 294, 312, 294, 298, 294, 298, 26, 27, + 28, 29, 294, 298, 294, 298, 294, 298, 294, 298, + 294, 298, 294, 298, 294, 298, 294, 298, 294, 298, + 294, 298, 294, 298, 294, 298, 294, 298, 104, 109, + 320, 330, 411, 316, 301, 445, 445, 356, 442, 314, + 295, 445, 316, 347, 348, 450, 292, 353, 315, 196, + 321, 315, 454, 316, 316, 292, 454, 383, 290, 169, + 170, 171, 172, 290, 313, 320, 331, 371, 468, 172, + 174, 175, 290, 313, 320, 331, 375, 468, 290, 312, + 295, 294, 303, 303, 299, 299, 299, 299, 294, 383, + 136, 299, 299, 450, 361, 450, 295, 377, 447, 62, + 62, 295, 295, 315, 295, 445, 441, 441, 8, 292, + 8, 477, 295, 316, 249, 312, 298, 298, 25, 26, + 27, 28, 29, 271, 292, 298, 305, 290, 291, 299, + 316, 22, 23, 24, 26, 27, 28, 29, 31, 32, + 35, 36, 37, 38, 44, 312, 409, 413, 294, 294, + 289, 329, 327, 464, 316, 316, 316, 294, 298, 294, + 298, 294, 298, 294, 298, 316, 316, 316, 316, 316, + 316, 317, 316, 316, 318, 316, 317, 318, 316, 316, + 316, 316, 316, 316, 316, 317, 316, 414, 316, 8, + 44, 316, 44, 51, 448, 316, 42, 91, 110, 332, + 455, 295, 299, 295, 295, 294, 294, 471, 295, 295, + 295, 292, 352, 353, 315, 299, 299, 450, 450, 255, + 363, 363, 363, 363, 363, 363, 363, 382, 316, 138, + 139, 138, 139, 378, 349, 314, 292, 19, 314, 314, + 316, 295, 316, 303, 297, 292, 316, 316, 312, 299, + 316, 291, 299, 26, 27, 28, 29, 316, 26, 27, + 28, 316, 329, 290, 290, 295, 299, 295, 299, 316, + 316, 316, 316, 316, 316, 317, 316, 295, 299, 295, + 299, 295, 299, 295, 299, 295, 295, 299, 295, 295, + 299, 295, 299, 295, 299, 295, 299, 295, 299, 295, + 299, 295, 295, 299, 295, 8, 295, 299, 51, 448, + 298, 315, 301, 445, 445, 450, 294, 292, 19, 364, + 295, 295, 295, 294, 450, 383, 8, 477, 316, 312, + 299, 299, 299, 316, 295, 303, 303, 303, 295, 290, + 294, 294, 295, 299, 295, 299, 295, 299, 295, 299, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 295, 294, 8, 299, 297, 295, 295, 445, + 450, 383, 454, 445, 300, 355, 356, 303, 295, 292, + 295, 451, 299, 316, 316, 316, 421, 419, 294, 294, + 294, 294, 420, 419, 418, 417, 415, 416, 420, 419, + 418, 417, 424, 422, 423, 414, 295, 355, 450, 295, + 294, 477, 312, 295, 295, 295, 295, 464, 295, 316, + 420, 419, 418, 417, 295, 316, 295, 295, 316, 295, + 317, 295, 316, 318, 295, 317, 318, 295, 295, 295, + 295, 295, 414, 8, 44, 295, 44, 51, 295, 448, + 361, 294, 19, 385, 445, 292, 295, 295, 295, 295, + 8, 445, 383, 39, 54, 70, 79, 93, 94, 95, + 96, 125, 126, 127, 128, 129, 130, 131, 289, 295, + 312, 295, 294, 294, 295, 255, 445, 316, 103, 295, + 295, 364, 454, 450, 19, 383, 355, 294, 445, 295 +}; + +/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ +static const yytype_int16 yyr1[] = +{ + 0, 308, 309, 309, 310, 310, 310, 310, 310, 310, + 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, + 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, + 311, 311, 312, 312, 313, 313, 313, 314, 314, 315, + 315, 315, 316, 317, 317, 318, 318, 318, 319, 319, + 319, 319, 319, 320, 320, 320, 320, 320, 320, 320, + 320, 320, 321, 321, 321, 321, 322, 322, 322, 322, + 323, 324, 325, 326, 326, 327, 328, 328, 328, 329, + 329, 329, 330, 330, 331, 331, 331, 332, 332, 332, + 332, 332, 332, 333, 333, 333, 334, 335, 335, 335, + 335, 335, 335, 336, 337, 338, 339, 340, 341, 342, + 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, + 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, + 342, 342, 342, 342, 342, 342, 343, 343, 344, 344, + 345, 345, 346, 346, 347, 347, 348, 348, 349, 349, + 350, 350, 350, 350, 350, 350, 350, 351, 351, 352, + 352, 353, 353, 354, 355, 355, 356, 357, 357, 357, + 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, + 357, 357, 357, 357, 357, 357, 357, 357, 358, 359, + 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, + 359, 359, 359, 359, 359, 360, 360, 361, 361, 362, + 362, 363, 363, 363, 363, 363, 363, 363, 364, 364, + 364, 364, 365, 365, 365, 365, 365, 365, 365, 365, + 366, 367, 367, 367, 367, 367, 367, 368, 368, 369, + 369, 369, 370, 370, 371, 371, 371, 371, 371, 371, + 371, 371, 372, 373, 373, 373, 374, 374, 375, 375, + 375, 375, 375, 375, 375, 376, 377, 377, 378, 378, + 379, 380, 381, 381, 381, 381, 381, 381, 381, 381, + 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, + 381, 381, 381, 381, 381, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, + 382, 383, 383, 383, 384, 384, 384, 384, 384, 385, + 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, + 385, 385, 385, 385, 385, 386, 387, 387, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 388, 388, 388, 388, 389, 390, 391, 392, 392, 393, + 393, 393, 394, 395, 395, 395, 395, 396, 396, 396, + 397, 398, 399, 400, 401, 401, 401, 402, 403, 403, + 404, 404, 404, 405, 405, 406, 406, 407, 407, 408, + 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, + 408, 408, 408, 408, 409, 409, 409, 409, 409, 409, + 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, + 409, 409, 409, 410, 411, 411, 412, 412, 413, 413, + 413, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 415, 415, 415, + 416, 416, 416, 417, 417, 418, 418, 419, 419, 420, + 420, 421, 421, 422, 422, 422, 423, 423, 423, 423, + 424, 424, 425, 426, 427, 428, 429, 430, 431, 432, + 433, 434, 435, 436, 437, 438, 439, 440, 440, 440, + 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, + 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, + 441, 441, 441, 441, 441, 442, 442, 443, 443, 444, + 444, 445, 445, 446, 446, 447, 447, 447, 448, 448, + 448, 448, 448, 448, 448, 448, 448, 448, 449, 449, + 450, 450, 450, 450, 451, 451, 451, 451, 451, 451, + 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, + 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, + 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, + 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, + 451, 451, 451, 451, 451, 451, 451, 451, 451, 452, + 452, 453, 453, 453, 453, 453, 453, 453, 453, 453, + 453, 453, 453, 453, 453, 453, 453, 453, 453, 453, + 453, 453, 453, 453, 453, 453, 453, 453, 453, 453, + 453, 453, 453, 453, 453, 453, 453, 453, 453, 453, + 453, 453, 453, 453, 453, 453, 453, 453, 453, 453, + 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, + 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, + 454, 454, 454, 454, 455, 455, 455, 455, 455, 455, + 455, 455, 455, 455, 455, 455, 455, 455, 455, 455, + 455, 455, 456, 456, 457, 457, 457, 457, 457, 458, + 458, 458, 458, 458, 458, 459, 459, 459, 460, 460, + 461, 461, 462, 462, 463, 464, 464, 465, 465, 465, + 465, 465, 465, 465, 465, 466, 466, 466, 466, 466, + 466, 466, 466, 466, 466, 466, 466, 466, 466, 466, + 467, 467, 468, 468, 468, 468, 468, 468, 468, 468, + 468, 468, 468, 469, 469, 470, 470, 471, 471, 472, + 473, 474, 474, 474, 474, 474, 474, 474, 474, 474, + 474, 475, 475, 476, 476, 476, 477, 477, 478, 478, + 478, 478, 478, 478, 479, 480, 481, 482, 482, 483, + 483, 484, 484, 484, 484, 485, 486, 487, 487, 487, + 487, 487, 487, 487, 487, 487, 487, 488, 488, 489, + 489, 489, 489, 489, 489, 489, 490, 490, 491, 491, + 491, 492, 492, 493, 493, 493, 493 +}; + +/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ +static const yytype_int8 yyr2[] = +{ + 0, 2, 0, 2, 4, 4, 3, 1, 1, 1, + 1, 1, 1, 4, 4, 4, 4, 1, 1, 1, + 2, 2, 3, 2, 2, 1, 1, 1, 4, 1, + 0, 2, 1, 3, 2, 4, 6, 1, 1, 1, + 1, 3, 1, 1, 1, 1, 4, 4, 4, 4, + 4, 4, 4, 2, 3, 2, 2, 2, 1, 1, + 2, 1, 2, 4, 6, 3, 5, 7, 9, 3, + 4, 7, 1, 1, 1, 2, 0, 2, 2, 0, + 6, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 2, 3, 1, 2, 3, 7, 0, 2, 2, + 2, 2, 2, 3, 3, 2, 1, 4, 3, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 2, 2, 2, 5, 0, 2, 0, 2, + 0, 2, 3, 1, 0, 1, 1, 3, 0, 3, + 1, 1, 1, 1, 1, 1, 4, 0, 2, 4, + 3, 0, 2, 3, 0, 1, 5, 3, 4, 4, + 4, 1, 1, 1, 1, 1, 2, 2, 4, 13, + 22, 1, 1, 5, 3, 7, 5, 4, 7, 0, + 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, + 2, 2, 2, 2, 5, 0, 2, 0, 2, 0, + 3, 9, 9, 7, 7, 1, 1, 1, 2, 2, + 1, 4, 0, 1, 1, 2, 2, 2, 2, 1, + 4, 2, 5, 3, 2, 2, 1, 4, 3, 0, + 2, 2, 0, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 9, 0, 2, 2, 0, 2, 2, 2, + 2, 1, 1, 1, 1, 1, 0, 4, 1, 3, + 1, 13, 0, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 5, 8, 6, 5, 0, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, + 5, 1, 1, 1, 0, 4, 4, 4, 4, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 5, 1, 0, 2, 2, 1, + 2, 4, 5, 1, 1, 1, 1, 2, 1, 1, + 1, 1, 1, 4, 6, 4, 4, 11, 1, 5, + 3, 7, 5, 5, 3, 1, 2, 2, 1, 2, + 4, 4, 1, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 1, 1, 1, 4, 4, 2, 4, 2, + 0, 1, 1, 3, 1, 3, 1, 0, 3, 5, + 4, 3, 5, 5, 5, 5, 5, 5, 2, 2, + 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, + 4, 4, 5, 5, 5, 5, 4, 4, 4, 4, + 4, 4, 3, 2, 0, 1, 1, 2, 1, 1, + 1, 1, 4, 4, 5, 4, 4, 4, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 7, 7, 7, 7, 7, 0, 2, 2, + 0, 2, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 2, 0, 2, 3, 2, + 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, + 2, 2, 2, 2, 3, 2, 2, 2, 5, 3, + 2, 2, 2, 2, 2, 5, 4, 6, 2, 4, + 0, 3, 3, 1, 1, 0, 3, 0, 1, 1, + 3, 0, 1, 1, 3, 1, 3, 4, 4, 4, + 4, 5, 1, 1, 1, 1, 1, 1, 1, 3, + 1, 3, 4, 1, 0, 10, 6, 5, 6, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, + 3, 4, 6, 5, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 1, 2, 2, 4, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, 1, 0, + 5, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, + 1, 1, 3, 2, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 1, 3, 2, 3, 4, 2, 2, 2, 5, + 5, 7, 4, 3, 2, 3, 2, 1, 1, 2, + 3, 2, 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, + 1, 1, 1, 3, 0, 1, 1, 3, 2, 6, + 7, 3, 3, 3, 6, 0, 1, 3, 5, 6, + 4, 4, 1, 3, 3, 1, 1, 1, 1, 4, + 1, 6, 6, 6, 4, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 2, 5, 4, 7, 6, 7, 6, + 9, 8, 3, 8, 4, 0, 2, 0, 1, 3, + 3, 0, 2, 2, 2, 3, 2, 2, 2, 2, + 2, 0, 2, 3, 1, 1, 1, 1, 3, 8, + 2, 3, 1, 1, 3, 3, 3, 4, 6, 0, + 2, 3, 1, 3, 1, 4, 3, 0, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 0, 2, 2, + 3, 3, 4, 2, 1, 1, 3, 5, 0, 2, + 2, 0, 2, 4, 3, 1, 1 }; -#endif -/* SCCSWHAT( "@(#)yypars.c 3.1 88/11/16 22:00:49 " ) */ -#line 3 "F:\\NetFXDev1\\src\\tools\\devdiv\\amd64\\yypars.c" -#if ! defined(YYAPI_PACKAGE) -/* -** YYAPI_TOKENNAME : name used for return value of yylex -** YYAPI_TOKENTYPE : type of the token -** YYAPI_TOKENEME(t) : the value of the token that the parser should see -** YYAPI_TOKENNONE : the representation when there is no token -** YYAPI_VALUENAME : the name of the value of the token -** YYAPI_VALUETYPE : the type of the value of the token (if null, then the value is derivable from the token itself) -** YYAPI_VALUEOF(v) : how to get the value of the token. -*/ -#define YYAPI_TOKENNAME yychar -#define YYAPI_TOKENTYPE int -#define YYAPI_TOKENEME(t) (t) -#define YYAPI_TOKENNONE -1 -#define YYAPI_TOKENSTR(t) (sprintf_s(yytokbuf, ARRAY_SIZE(yytokbuf), "%d", t), yytokbuf) -#define YYAPI_VALUENAME yylval -#define YYAPI_VALUETYPE YYSTYPE -#define YYAPI_VALUEOF(v) (v) -#endif -#if ! defined(YYAPI_CALLAFTERYYLEX) -#define YYAPI_CALLAFTERYYLEX -#endif -# define YYFLAG -1000 -# define YYERROR goto yyerrlab -# define YYACCEPT return(0) -# define YYABORT return(1) +enum { YYENOMEM = -2 }; -#ifdef YYDEBUG /* RRR - 10/9/85 */ -char yytokbuf[20]; -# ifndef YYDBFLG -# define YYDBFLG (yydebug) +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab +#define YYNOMEM goto yyexhaustedlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) + +/* Backward compatibility with an undocumented macro. + Use YYerror or YYUNDEF. */ +#define YYERRCODE YYUNDEF + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf # endif -# define yyprintf(a, b, c, d) if (YYDBFLG) YYPRINT(a, b, c, d) -#else -# define yyprintf(a, b, c, d) -#endif -#ifndef YYPRINT -#define YYPRINT printf -#endif +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) -/* parser for yacc output */ -#ifdef YYDUMP -int yydump = 1; /* 1 for dumping */ -void yydumpinfo(void); -#endif -#ifdef YYDEBUG -YYSTATIC int yydebug = 0; /* 1 for debugging */ -#endif -YYSTATIC YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ -YYSTATIC short yys[YYMAXDEPTH]; /* the parse stack */ -#if ! defined(YYRECURSIVE) -YYSTATIC YYAPI_TOKENTYPE YYAPI_TOKENNAME = YYAPI_TOKENNONE; -#if defined(YYAPI_VALUETYPE) -// YYSTATIC YYAPI_VALUETYPE YYAPI_VALUENAME; FIX -#endif -YYSTATIC int yynerrs = 0; /* number of errors */ -YYSTATIC short yyerrflag = 0; /* error recovery flag */ -#endif -#ifdef YYRECOVER -/* -** yyscpy : copy f onto t and return a ptr to the null terminator at the -** end of t. -*/ -YYSTATIC char *yyscpy(register char*t, register char*f) - { - while(*t = *f++) - t++; - return(t); /* ptr to the null char */ - } -#endif +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Kind, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) -#ifndef YYNEAR -#define YYNEAR -#endif -#ifndef YYPASCAL -#define YYPASCAL -#endif -#ifndef YYLOCAL -#define YYLOCAL -#endif -#if ! defined YYPARSER -#define YYPARSER yyparse -#endif -#if ! defined YYLEX -#define YYLEX yylex -#endif -#if defined(YYRECURSIVE) +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ - YYSTATIC YYAPI_TOKENTYPE YYAPI_TOKENNAME = YYAPI_TOKENNONE; - #if defined(YYAPI_VALUETYPE) - YYSTATIC YYAPI_VALUETYPE YYAPI_VALUENAME; - #endif - YYSTATIC int yynerrs = 0; /* number of errors */ - YYSTATIC short yyerrflag = 0; /* error recovery flag */ +static void +yy_symbol_value_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep) +{ + FILE *yyoutput = yyo; + YY_USE (yyoutput); + if (!yyvaluep) + return; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YY_USE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} - YYSTATIC short yyn; - YYSTATIC short yystate = 0; - YYSTATIC short *yyps= &yys[-1]; - YYSTATIC YYSTYPE *yypv= &yyv[-1]; - YYSTATIC short yyj; - YYSTATIC short yym; -#endif +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ -#pragma warning(disable:102) -YYLOCAL YYNEAR YYPASCAL YYPARSER() +static void +yy_symbol_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep) { -#if ! defined(YYRECURSIVE) + YYFPRINTF (yyo, "%s %s (", + yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); - register short yyn; - short yystate, *yyps; - YYSTYPE *yypv; - short yyj, yym; + yy_symbol_value_print (yyo, yykind, yyvaluep); + YYFPRINTF (yyo, ")"); +} - YYAPI_TOKENNAME = YYAPI_TOKENNONE; - yystate = 0; +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable:6200) // Index '-1' is out of valid index range...for non-stack buffer... -#endif - yyps= &yys[-1]; - yypv= &yyv[-1]; -#ifdef _PREFAST_ -#pragma warning(pop) -#endif +static void +yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} -#endif +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, + int yyrule) +{ + int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), + &yyvsp[(yyi + 1) - (yynrhs)]); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) ((void) 0) +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ -#ifdef YYDUMP - yydumpinfo(); + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 #endif - yystack: /* put a state and value onto the stack */ - -#ifdef YYDEBUG - if(YYAPI_TOKENNAME == YYAPI_TOKENNONE) { - yyprintf( "state %d, token # '%d'\n", yystate, -1, 0 ); - } - else { - yyprintf( "state %d, token # '%s'\n", yystate, YYAPI_TOKENSTR(YYAPI_TOKENNAME), 0 ); - } + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 #endif - if( ++yyps > &yys[YYMAXDEPTH] ) { - yyerror( "yacc stack overflow" ); - return(1); - } - *yyps = yystate; - ++yypv; - *yypv = yyval; + + + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, + yysymbol_kind_t yykind, YYSTYPE *yyvaluep) +{ + YY_USE (yyvaluep); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YY_USE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + +/* Lookahead token kind. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; +/* Number of syntax errors so far. */ +int yynerrs; + + + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (void) +{ + yy_state_fast_t yystate = 0; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus = 0; + + /* Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* Their size. */ + YYPTRDIFF_T yystacksize = YYINITDEPTH; + + /* The state stack: array, bottom, top. */ + yy_state_t yyssa[YYINITDEPTH]; + yy_state_t *yyss = yyssa; + yy_state_t *yyssp = yyss; + + /* The semantic value stack: array, bottom, top. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp = yyvs; + + int yyn; + /* The return value of yyparse. */ + int yyresult; + /* Lookahead symbol kind. */ + yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yychar = YYEMPTY; /* Cause a token to be read. */ + + goto yysetstate; + + +/*------------------------------------------------------------. +| yynewstate -- push a new state, which is found in yystate. | +`------------------------------------------------------------*/ yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + +/*--------------------------------------------------------------------. +| yysetstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); + YY_IGNORE_USELESS_CAST_BEGIN + *yyssp = YY_CAST (yy_state_t, yystate); + YY_IGNORE_USELESS_CAST_END + YY_STACK_PRINT (yyss, yyssp); - yyn = YYPACT[yystate]; - - if( yyn <= YYFLAG ) { /* simple state, no lookahead */ - goto yydefault; - } - if( YYAPI_TOKENNAME == YYAPI_TOKENNONE ) { /* need a lookahead */ - YYAPI_TOKENNAME = YYLEX(); - YYAPI_CALLAFTERYYLEX(YYAPI_TOKENNAME); - } - if( ((yyn += (short)YYAPI_TOKENEME(YYAPI_TOKENNAME)) < 0) || (yyn >= YYLAST) ) { - goto yydefault; - } - if( YYCHK[ yyn = YYACT[ yyn ] ] == YYAPI_TOKENEME(YYAPI_TOKENNAME) ) { /* valid shift */ - yyval = YYAPI_VALUEOF(YYAPI_VALUENAME); - yystate = yyn; - yyprintf( "SHIFT: saw token '%s', now in state %4d\n", YYAPI_TOKENSTR(YYAPI_TOKENNAME), yystate, 0 ); - YYAPI_TOKENNAME = YYAPI_TOKENNONE; - if( yyerrflag > 0 ) { - --yyerrflag; - } - goto yystack; - } - - yydefault: - /* default state action */ - - if( (yyn = YYDEF[yystate]) == -2 ) { - register YYCONST short *yyxi; - - if( YYAPI_TOKENNAME == YYAPI_TOKENNONE ) { - YYAPI_TOKENNAME = YYLEX(); - YYAPI_CALLAFTERYYLEX(YYAPI_TOKENNAME); - yyprintf("LOOKAHEAD: token '%s'\n", YYAPI_TOKENSTR(YYAPI_TOKENNAME), 0, 0); - } -/* -** search exception table, we find a -1 followed by the current state. -** if we find one, we'll look through terminal,state pairs. if we find -** a terminal which matches the current one, we have a match. -** the exception table is when we have a reduce on a terminal. -*/ - -#if YYOPTTIME - yyxi = yyexca + yyexcaind[yystate]; - while(( *yyxi != YYAPI_TOKENEME(YYAPI_TOKENNAME) ) && ( *yyxi >= 0 )){ - yyxi += 2; - } + if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + YYNOMEM; #else - for(yyxi = yyexca; - (*yyxi != (-1)) || (yyxi[1] != yystate); - yyxi += 2 - ) { - ; /* VOID */ - } - - while( *(yyxi += 2) >= 0 ){ - if( *yyxi == YYAPI_TOKENEME(YYAPI_TOKENNAME) ) { - break; - } - } -#endif - if( (yyn = yyxi[1]) < 0 ) { - return(0); /* accept */ - } - } - - if( yyn == 0 ){ /* error */ - /* error ... attempt to resume parsing */ - - switch( yyerrflag ){ - - case 0: /* brand new error */ -#ifdef YYRECOVER - { - register int i,j; - - for(i = 0; - (yyrecover[i] != -1000) && (yystate > yyrecover[i]); - i += 3 - ) { - ; - } - if(yystate == yyrecover[i]) { - yyprintf("recovered, from state %d to state %d on token # %d\n", - yystate,yyrecover[i+2],yyrecover[i+1] - ); - j = yyrecover[i + 1]; - if(j < 0) { - /* - ** here we have one of the injection set, so we're not quite - ** sure that the next valid thing will be a shift. so we'll - ** count it as an error and continue. - ** actually we're not absolutely sure that the next token - ** we were supposed to get is the one when j > 0. for example, - ** for(+) {;} error recovery with yyerrflag always set, stops - ** after inserting one ; before the +. at the point of the +, - ** we're pretty sure the guy wants a 'for' loop. without - ** setting the flag, when we're almost absolutely sure, we'll - ** give him one, since the only thing we can shift on this - ** error is after finding an expression followed by a + - */ - yyerrflag++; - j = -j; - } - if(yyerrflag <= 1) { /* only on first insertion */ - yyrecerr(YYAPI_TOKENNAME, j); /* what was, what should be first */ - } - yyval = yyeval(j); - yystate = yyrecover[i + 2]; - goto yystack; - } - } -#endif - yyerror("syntax error"); + { + /* Get the current used size of the three stacks, in elements. */ + YYPTRDIFF_T yysize = yyssp - yyss + 1; + +# if defined yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + yy_state_t *yyss1 = yyss; + YYSTYPE *yyvs1 = yyvs; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * YYSIZEOF (*yyssp), + &yyvs1, yysize * YYSIZEOF (*yyvsp), + &yystacksize); + yyss = yyss1; + yyvs = yyvs1; + } +# else /* defined YYSTACK_RELOCATE */ + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + YYNOMEM; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yy_state_t *yyss1 = yyss; + union yyalloc *yyptr = + YY_CAST (union yyalloc *, + YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); + if (! yyptr) + YYNOMEM; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YY_IGNORE_USELESS_CAST_BEGIN + YYDPRINTF ((stderr, "Stack size increased to %ld\n", + YY_CAST (long, yystacksize))); + YY_IGNORE_USELESS_CAST_END + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - yyerrlab: - ++yynerrs; - FALLTHROUGH; - case 1: - case 2: /* incompletely recovered error ... try again */ - yyerrflag = 3; + if (yystate == YYFINAL) + YYACCEPT; - /* find a state where "error" is a legal shift action */ + goto yybackup; - while ( yyps >= yys ) { - yyn = YYPACT[*yyps] + YYERRCODE; - if( yyn>= 0 && yyn < YYLAST && YYCHK[YYACT[yyn]] == YYERRCODE ){ - yystate = YYACT[yyn]; /* simulate a shift of "error" */ - yyprintf( "SHIFT 'error': now in state %4d\n", yystate, 0, 0 ); - goto yystack; - } - yyn = YYPACT[*yyps]; - /* the current yyps has no shift onn "error", pop stack */ +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ - yyprintf( "error recovery pops state %4d, uncovers %4d\n", *yyps, yyps[-1], 0 ); - --yyps; - --yypv; - } + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; - /* there is no state on the stack with an error shift ... abort */ + /* Not known => get a lookahead token if don't already have one. */ - yyabort: - return(1); + /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token\n")); + yychar = yylex (); + } + if (yychar <= YYEOF) + { + yychar = YYEOF; + yytoken = YYSYMBOL_YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else if (yychar == YYerror) + { + /* The scanner already issued an error message, process directly + to error recovery. But do not keep the error token as + lookahead, it is too special and may lead us to an endless + loop in error recovery. */ + yychar = YYUNDEF; + yytoken = YYSYMBOL_YYerror; + goto yyerrlab1; + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } - case 3: /* no shift yet; clobber input char */ + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } - yyprintf( "error recovery discards token '%s'\n", YYAPI_TOKENSTR(YYAPI_TOKENNAME), 0, 0 ); + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; - if( YYAPI_TOKENEME(YYAPI_TOKENNAME) == 0 ) goto yyabort; /* don't discard EOF, quit */ - YYAPI_TOKENNAME = YYAPI_TOKENNONE; - goto yynewstate; /* try again in the same state */ - } - } + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END - /* reduction by production yyn */ + /* Discard the shifted token. */ + yychar = YYEMPTY; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- do a reduction. | +`-----------------------------*/ yyreduce: - { - register YYSTYPE *yypvt; - yypvt = yypv; - yyps -= YYR2[yyn]; - yypv -= YYR2[yyn]; - yyval = yypv[1]; - yyprintf("REDUCE: rule %4d, popped %2d tokens, uncovered state %4d, ",yyn, YYR2[yyn], *yyps); - yym = yyn; - yyn = (short)YYR1[yyn]; /* consult goto table to find next state */ - yyj = YYPGO[yyn] + *yyps + 1; - if( (yyj >= YYLAST) || (YYCHK[ yystate = YYACT[yyj] ] != -yyn) ) { - yystate = YYACT[YYPGO[yyn]]; - } - yyprintf("goto state %4d\n", yystate, 0, 0); -#ifdef YYDUMP - yydumpinfo(); -#endif - switch(yym){ + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; -case 3: + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 4: /* decl: classHead '{' classDecls '}' */ #line 193 "asmparse.y" -{ PASM->EndClass(); } break; -case 4: + { PASM->EndClass(); } +#line 3542 "asmparse.cpp" + break; + + case 5: /* decl: nameSpaceHead '{' decls '}' */ #line 194 "asmparse.y" -{ PASM->EndNameSpace(); } break; -case 5: + { PASM->EndNameSpace(); } +#line 3548 "asmparse.cpp" + break; + + case 6: /* decl: methodHead methodDecls '}' */ #line 195 "asmparse.y" -{ if(PASM->m_pCurMethod->m_ulLines[1] ==0) + { if(PASM->m_pCurMethod->m_ulLines[1] ==0) { PASM->m_pCurMethod->m_ulLines[1] = PASM->m_ulCurLine; PASM->m_pCurMethod->m_ulColumns[1]=PASM->m_ulCurColumn;} - PASM->EndMethod(); } break; -case 12: + PASM->EndMethod(); } +#line 3557 "asmparse.cpp" + break; + + case 13: /* decl: assemblyHead '{' assemblyDecls '}' */ #line 205 "asmparse.y" -{ PASMM->EndAssembly(); } break; -case 13: + { PASMM->EndAssembly(); } +#line 3563 "asmparse.cpp" + break; + + case 14: /* decl: assemblyRefHead '{' assemblyRefDecls '}' */ #line 206 "asmparse.y" -{ PASMM->EndAssembly(); } break; -case 14: + { PASMM->EndAssembly(); } +#line 3569 "asmparse.cpp" + break; + + case 15: /* decl: exptypeHead '{' exptypeDecls '}' */ #line 207 "asmparse.y" -{ PASMM->EndComType(); } break; -case 15: + { PASMM->EndComType(); } +#line 3575 "asmparse.cpp" + break; + + case 16: /* decl: manifestResHead '{' manifestResDecls '}' */ #line 208 "asmparse.y" -{ PASMM->EndManifestRes(); } break; -case 19: + { PASMM->EndManifestRes(); } +#line 3581 "asmparse.cpp" + break; + + case 20: /* decl: _SUBSYSTEM int32 */ #line 212 "asmparse.y" -{ + { #ifdef _PREFAST_ #pragma warning(push) #pragma warning(disable:22011) // Suppress PREFast warning about integer overflow/underflow #endif - PASM->m_dwSubsystem = yypvt[-0].int32; + PASM->m_dwSubsystem = (yyvsp[0].int32); #ifdef _PREFAST_ #pragma warning(pop) #endif - } break; -case 20: + } +#line 3596 "asmparse.cpp" + break; + + case 21: /* decl: _CORFLAGS int32 */ #line 222 "asmparse.y" -{ PASM->m_dwComImageFlags = yypvt[-0].int32; } break; -case 21: + { PASM->m_dwComImageFlags = (yyvsp[0].int32); } +#line 3602 "asmparse.cpp" + break; + + case 22: /* decl: _FILE ALIGNMENT_ int32 */ #line 223 "asmparse.y" -{ PASM->m_dwFileAlignment = yypvt[-0].int32; - if((yypvt[-0].int32 & (yypvt[-0].int32 - 1))||(yypvt[-0].int32 < 0x200)||(yypvt[-0].int32 > 0x10000)) - PASM->report->error("Invalid file alignment, must be power of 2 from 0x200 to 0x10000\n");} break; -case 22: + { PASM->m_dwFileAlignment = (yyvsp[0].int32); + if(((yyvsp[0].int32) & ((yyvsp[0].int32) - 1))||((yyvsp[0].int32) < 0x200)||((yyvsp[0].int32) > 0x10000)) + PASM->report->error("Invalid file alignment, must be power of 2 from 0x200 to 0x10000\n");} +#line 3610 "asmparse.cpp" + break; + + case 23: /* decl: _IMAGEBASE int64 */ #line 226 "asmparse.y" -{ PASM->m_stBaseAddress = (ULONGLONG)(*(yypvt[-0].int64)); delete yypvt[-0].int64; + { PASM->m_stBaseAddress = (ULONGLONG)(*((yyvsp[0].int64))); delete (yyvsp[0].int64); if(PASM->m_stBaseAddress & 0xFFFF) - PASM->report->error("Invalid image base, must be 0x10000-aligned\n");} break; -case 23: + PASM->report->error("Invalid image base, must be 0x10000-aligned\n");} +#line 3618 "asmparse.cpp" + break; + + case 24: /* decl: _STACKRESERVE int64 */ #line 229 "asmparse.y" -{ PASM->m_stSizeOfStackReserve = (size_t)(*(yypvt[-0].int64)); delete yypvt[-0].int64; } break; -case 28: + { PASM->m_stSizeOfStackReserve = (size_t)(*((yyvsp[0].int64))); delete (yyvsp[0].int64); } +#line 3624 "asmparse.cpp" + break; + + case 29: /* decl: _MSCORLIB */ #line 234 "asmparse.y" -{ PASM->m_fIsMscorlib = TRUE; } break; -case 31: + { PASM->m_fIsMscorlib = TRUE; } +#line 3630 "asmparse.cpp" + break; + + case 32: /* compQstring: QSTRING */ #line 241 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 32: + { (yyval.binstr) = (yyvsp[0].binstr); } +#line 3636 "asmparse.cpp" + break; + + case 33: /* compQstring: compQstring '+' QSTRING */ #line 242 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; -case 33: + { (yyval.binstr) = (yyvsp[-2].binstr); (yyval.binstr)->append((yyvsp[0].binstr)); delete (yyvsp[0].binstr); } +#line 3642 "asmparse.cpp" + break; + + case 34: /* languageDecl: _LANGUAGE SQSTRING */ #line 245 "asmparse.y" -{ LPCSTRToGuid(yypvt[-0].string,&(PASM->m_guidLang)); } break; -case 34: + { LPCSTRToGuid((yyvsp[0].string),&(PASM->m_guidLang)); } +#line 3648 "asmparse.cpp" + break; + + case 35: /* languageDecl: _LANGUAGE SQSTRING ',' SQSTRING */ #line 246 "asmparse.y" -{ LPCSTRToGuid(yypvt[-2].string,&(PASM->m_guidLang)); - LPCSTRToGuid(yypvt[-0].string,&(PASM->m_guidLangVendor));} break; -case 35: + { LPCSTRToGuid((yyvsp[-2].string),&(PASM->m_guidLang)); + LPCSTRToGuid((yyvsp[0].string),&(PASM->m_guidLangVendor));} +#line 3655 "asmparse.cpp" + break; + + case 36: /* languageDecl: _LANGUAGE SQSTRING ',' SQSTRING ',' SQSTRING */ #line 248 "asmparse.y" -{ LPCSTRToGuid(yypvt[-4].string,&(PASM->m_guidLang)); - LPCSTRToGuid(yypvt[-2].string,&(PASM->m_guidLangVendor)); - LPCSTRToGuid(yypvt[-2].string,&(PASM->m_guidDoc));} break; -case 36: + { LPCSTRToGuid((yyvsp[-4].string),&(PASM->m_guidLang)); + LPCSTRToGuid((yyvsp[-2].string),&(PASM->m_guidLangVendor)); + LPCSTRToGuid((yyvsp[-2].string),&(PASM->m_guidDoc));} +#line 3663 "asmparse.cpp" + break; + + case 37: /* id: ID */ #line 253 "asmparse.y" -{ yyval.string = yypvt[-0].string; } break; -case 37: + { (yyval.string) = (yyvsp[0].string); } +#line 3669 "asmparse.cpp" + break; + + case 38: /* id: SQSTRING */ #line 254 "asmparse.y" -{ yyval.string = yypvt[-0].string; } break; -case 38: + { (yyval.string) = (yyvsp[0].string); } +#line 3675 "asmparse.cpp" + break; + + case 39: /* dottedName: id */ #line 257 "asmparse.y" -{ yyval.string = yypvt[-0].string; } break; -case 39: + { (yyval.string) = (yyvsp[0].string); } +#line 3681 "asmparse.cpp" + break; + + case 40: /* dottedName: DOTTEDNAME */ #line 258 "asmparse.y" -{ yyval.string = yypvt[-0].string; } break; -case 40: + { (yyval.string) = (yyvsp[0].string); } +#line 3687 "asmparse.cpp" + break; + + case 41: /* dottedName: dottedName '.' dottedName */ #line 259 "asmparse.y" -{ yyval.string = newStringWDel(yypvt[-2].string, '.', yypvt[-0].string); } break; -case 41: + { (yyval.string) = newStringWDel((yyvsp[-2].string), '.', (yyvsp[0].string)); } +#line 3693 "asmparse.cpp" + break; + + case 42: /* int32: INT32_V */ #line 262 "asmparse.y" -{ yyval.int32 = yypvt[-0].int32; } break; -case 42: + { (yyval.int32) = (yyvsp[0].int32); } +#line 3699 "asmparse.cpp" + break; + + case 43: /* int64: INT64_V */ #line 265 "asmparse.y" -{ yyval.int64 = yypvt[-0].int64; } break; -case 43: + { (yyval.int64) = (yyvsp[0].int64); } +#line 3705 "asmparse.cpp" + break; + + case 44: /* int64: INT32_V */ #line 266 "asmparse.y" -{ yyval.int64 = neg ? new __int64(yypvt[-0].int32) : new __int64((unsigned)yypvt[-0].int32); } break; -case 44: + { (yyval.int64) = neg ? new int64_t((yyvsp[0].int32)) : new int64_t((unsigned)(yyvsp[0].int32)); } +#line 3711 "asmparse.cpp" + break; + + case 45: /* float64: FLOAT64 */ #line 269 "asmparse.y" -{ yyval.float64 = yypvt[-0].float64; } break; -case 45: + { (yyval.float64) = (yyvsp[0].float64); } +#line 3717 "asmparse.cpp" + break; + + case 46: /* float64: FLOAT32_ '(' int32 ')' */ #line 270 "asmparse.y" -{ float f; *((__int32*) (&f)) = yypvt[-1].int32; yyval.float64 = new double(f); } break; -case 46: + { float f; *((int32_t*) (&f)) = (yyvsp[-1].int32); (yyval.float64) = new double(f); } +#line 3723 "asmparse.cpp" + break; + + case 47: /* float64: FLOAT64_ '(' int64 ')' */ #line 271 "asmparse.y" -{ yyval.float64 = (double*) yypvt[-1].int64; } break; -case 47: + { (yyval.float64) = (double*) (yyvsp[-1].int64); } +#line 3729 "asmparse.cpp" + break; + + case 48: /* typedefDecl: _TYPEDEF type AS_ dottedName */ #line 275 "asmparse.y" -{ PASM->AddTypeDef(yypvt[-2].binstr,yypvt[-0].string); } break; -case 48: + { PASM->AddTypeDef((yyvsp[-2].binstr),(yyvsp[0].string)); } +#line 3735 "asmparse.cpp" + break; + + case 49: /* typedefDecl: _TYPEDEF className AS_ dottedName */ #line 276 "asmparse.y" -{ PASM->AddTypeDef(yypvt[-2].token,yypvt[-0].string); } break; -case 49: + { PASM->AddTypeDef((yyvsp[-2].token),(yyvsp[0].string)); } +#line 3741 "asmparse.cpp" + break; + + case 50: /* typedefDecl: _TYPEDEF memberRef AS_ dottedName */ #line 277 "asmparse.y" -{ PASM->AddTypeDef(yypvt[-2].token,yypvt[-0].string); } break; -case 50: + { PASM->AddTypeDef((yyvsp[-2].token),(yyvsp[0].string)); } +#line 3747 "asmparse.cpp" + break; + + case 51: /* typedefDecl: _TYPEDEF customDescr AS_ dottedName */ #line 278 "asmparse.y" -{ yypvt[-2].cad->tkOwner = 0; PASM->AddTypeDef(yypvt[-2].cad,yypvt[-0].string); } break; -case 51: + { (yyvsp[-2].cad)->tkOwner = 0; PASM->AddTypeDef((yyvsp[-2].cad),(yyvsp[0].string)); } +#line 3753 "asmparse.cpp" + break; + + case 52: /* typedefDecl: _TYPEDEF customDescrWithOwner AS_ dottedName */ #line 279 "asmparse.y" -{ PASM->AddTypeDef(yypvt[-2].cad,yypvt[-0].string); } break; -case 52: + { PASM->AddTypeDef((yyvsp[-2].cad),(yyvsp[0].string)); } +#line 3759 "asmparse.cpp" + break; + + case 53: /* compControl: P_DEFINE dottedName */ #line 284 "asmparse.y" -{ DefineVar(yypvt[-0].string, NULL); } break; -case 53: + { DefineVar((yyvsp[0].string), NULL); } +#line 3765 "asmparse.cpp" + break; + + case 54: /* compControl: P_DEFINE dottedName compQstring */ #line 285 "asmparse.y" -{ DefineVar(yypvt[-1].string, yypvt[-0].binstr); } break; -case 54: + { DefineVar((yyvsp[-1].string), (yyvsp[0].binstr)); } +#line 3771 "asmparse.cpp" + break; + + case 55: /* compControl: P_UNDEF dottedName */ #line 286 "asmparse.y" -{ UndefVar(yypvt[-0].string); } break; -case 55: + { UndefVar((yyvsp[0].string)); } +#line 3777 "asmparse.cpp" + break; + + case 56: /* compControl: P_IFDEF dottedName */ #line 287 "asmparse.y" -{ SkipToken = !IsVarDefined(yypvt[-0].string); + { SkipToken = !IsVarDefined((yyvsp[0].string)); IfEndif++; - } break; -case 56: + } +#line 3785 "asmparse.cpp" + break; + + case 57: /* compControl: P_IFNDEF dottedName */ #line 290 "asmparse.y" -{ SkipToken = IsVarDefined(yypvt[-0].string); + { SkipToken = IsVarDefined((yyvsp[0].string)); IfEndif++; - } break; -case 57: + } +#line 3793 "asmparse.cpp" + break; + + case 58: /* compControl: P_ELSE */ #line 293 "asmparse.y" -{ if(IfEndif == 1) SkipToken = !SkipToken;} break; -case 58: + { if(IfEndif == 1) SkipToken = !SkipToken;} +#line 3799 "asmparse.cpp" + break; + + case 59: /* compControl: P_ENDIF */ #line 294 "asmparse.y" -{ if(IfEndif == 0) + { if(IfEndif == 0) PASM->report->error("Unmatched #endif\n"); else IfEndif--; - } break; -case 59: + } +#line 3808 "asmparse.cpp" + break; + + case 60: /* compControl: P_INCLUDE QSTRING */ #line 298 "asmparse.y" -{ _ASSERTE(!"yylex should have dealt with this"); } break; -case 60: + { _ASSERTE(!"yylex should have dealt with this"); } +#line 3814 "asmparse.cpp" + break; + + case 61: /* compControl: ';' */ #line 299 "asmparse.y" -{ } break; -case 61: + { } +#line 3820 "asmparse.cpp" + break; + + case 62: /* customDescr: _CUSTOM customType */ #line 303 "asmparse.y" -{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-0].token, NULL); } break; -case 62: + { (yyval.cad) = new CustomDescr(PASM->m_tkCurrentCVOwner, (yyvsp[0].token), NULL); } +#line 3826 "asmparse.cpp" + break; + + case 63: /* customDescr: _CUSTOM customType '=' compQstring */ #line 304 "asmparse.y" -{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-2].token, yypvt[-0].binstr); } break; -case 63: + { (yyval.cad) = new CustomDescr(PASM->m_tkCurrentCVOwner, (yyvsp[-2].token), (yyvsp[0].binstr)); } +#line 3832 "asmparse.cpp" + break; + + case 64: /* customDescr: _CUSTOM customType '=' '{' customBlobDescr '}' */ #line 305 "asmparse.y" -{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-4].token, yypvt[-1].binstr); } break; -case 64: + { (yyval.cad) = new CustomDescr(PASM->m_tkCurrentCVOwner, (yyvsp[-4].token), (yyvsp[-1].binstr)); } +#line 3838 "asmparse.cpp" + break; + + case 65: /* customDescr: customHead bytes ')' */ #line 306 "asmparse.y" -{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-2].int32, yypvt[-1].binstr); } break; -case 65: + { (yyval.cad) = new CustomDescr(PASM->m_tkCurrentCVOwner, (yyvsp[-2].int32), (yyvsp[-1].binstr)); } +#line 3844 "asmparse.cpp" + break; + + case 66: /* customDescrWithOwner: _CUSTOM '(' ownerType ')' customType */ #line 309 "asmparse.y" -{ yyval.cad = new CustomDescr(yypvt[-2].token, yypvt[-0].token, NULL); } break; -case 66: + { (yyval.cad) = new CustomDescr((yyvsp[-2].token), (yyvsp[0].token), NULL); } +#line 3850 "asmparse.cpp" + break; + + case 67: /* customDescrWithOwner: _CUSTOM '(' ownerType ')' customType '=' compQstring */ #line 310 "asmparse.y" -{ yyval.cad = new CustomDescr(yypvt[-4].token, yypvt[-2].token, yypvt[-0].binstr); } break; -case 67: + { (yyval.cad) = new CustomDescr((yyvsp[-4].token), (yyvsp[-2].token), (yyvsp[0].binstr)); } +#line 3856 "asmparse.cpp" + break; + + case 68: /* customDescrWithOwner: _CUSTOM '(' ownerType ')' customType '=' '{' customBlobDescr '}' */ #line 312 "asmparse.y" -{ yyval.cad = new CustomDescr(yypvt[-6].token, yypvt[-4].token, yypvt[-1].binstr); } break; -case 68: + { (yyval.cad) = new CustomDescr((yyvsp[-6].token), (yyvsp[-4].token), (yyvsp[-1].binstr)); } +#line 3862 "asmparse.cpp" + break; + + case 69: /* customDescrWithOwner: customHeadWithOwner bytes ')' */ #line 313 "asmparse.y" -{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-2].int32, yypvt[-1].binstr); } break; -case 69: + { (yyval.cad) = new CustomDescr(PASM->m_tkCurrentCVOwner, (yyvsp[-2].int32), (yyvsp[-1].binstr)); } +#line 3868 "asmparse.cpp" + break; + + case 70: /* customHead: _CUSTOM customType '=' '(' */ #line 316 "asmparse.y" -{ yyval.int32 = yypvt[-2].token; bParsingByteArray = TRUE; } break; -case 70: + { (yyval.int32) = (yyvsp[-2].token); bParsingByteArray = TRUE; } +#line 3874 "asmparse.cpp" + break; + + case 71: /* customHeadWithOwner: _CUSTOM '(' ownerType ')' customType '=' '(' */ #line 320 "asmparse.y" -{ PASM->m_pCustomDescrList = NULL; - PASM->m_tkCurrentCVOwner = yypvt[-4].token; - yyval.int32 = yypvt[-2].token; bParsingByteArray = TRUE; } break; -case 71: + { PASM->m_pCustomDescrList = NULL; + PASM->m_tkCurrentCVOwner = (yyvsp[-4].token); + (yyval.int32) = (yyvsp[-2].token); bParsingByteArray = TRUE; } +#line 3882 "asmparse.cpp" + break; + + case 72: /* customType: methodRef */ #line 325 "asmparse.y" -{ yyval.token = yypvt[-0].token; } break; -case 72: + { (yyval.token) = (yyvsp[0].token); } +#line 3888 "asmparse.cpp" + break; + + case 73: /* ownerType: typeSpec */ #line 328 "asmparse.y" -{ yyval.token = yypvt[-0].token; } break; -case 73: + { (yyval.token) = (yyvsp[0].token); } +#line 3894 "asmparse.cpp" + break; + + case 74: /* ownerType: memberRef */ #line 329 "asmparse.y" -{ yyval.token = yypvt[-0].token; } break; -case 74: + { (yyval.token) = (yyvsp[0].token); } +#line 3900 "asmparse.cpp" + break; + + case 75: /* customBlobDescr: customBlobArgs customBlobNVPairs */ #line 333 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - yyval.binstr->appendInt16(VAL16(nCustomBlobNVPairs)); - yyval.binstr->append(yypvt[-0].binstr); - nCustomBlobNVPairs = 0; } break; -case 75: + { (yyval.binstr) = (yyvsp[-1].binstr); + (yyval.binstr)->appendInt16(VAL16(nCustomBlobNVPairs)); + (yyval.binstr)->append((yyvsp[0].binstr)); + nCustomBlobNVPairs = 0; } +#line 3909 "asmparse.cpp" + break; + + case 76: /* customBlobArgs: %empty */ #line 339 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt16(VAL16(0x0001)); } break; -case 76: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt16(VAL16(0x0001)); } +#line 3915 "asmparse.cpp" + break; + + case 77: /* customBlobArgs: customBlobArgs serInit */ #line 340 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - AppendFieldToCustomBlob(yyval.binstr,yypvt[-0].binstr); } break; -case 77: + { (yyval.binstr) = (yyvsp[-1].binstr); + AppendFieldToCustomBlob((yyval.binstr),(yyvsp[0].binstr)); } +#line 3922 "asmparse.cpp" + break; + + case 78: /* customBlobArgs: customBlobArgs compControl */ #line 342 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; } break; -case 78: + { (yyval.binstr) = (yyvsp[-1].binstr); } +#line 3928 "asmparse.cpp" + break; + + case 79: /* customBlobNVPairs: %empty */ #line 345 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 79: + { (yyval.binstr) = new BinStr(); } +#line 3934 "asmparse.cpp" + break; + + case 80: /* customBlobNVPairs: customBlobNVPairs fieldOrProp serializType dottedName '=' serInit */ #line 347 "asmparse.y" -{ yyval.binstr = yypvt[-5].binstr; yyval.binstr->appendInt8(yypvt[-4].int32); - yyval.binstr->append(yypvt[-3].binstr); - AppendStringWithLength(yyval.binstr,yypvt[-2].string); - AppendFieldToCustomBlob(yyval.binstr,yypvt[-0].binstr); - nCustomBlobNVPairs++; } break; -case 80: + { (yyval.binstr) = (yyvsp[-5].binstr); (yyval.binstr)->appendInt8((yyvsp[-4].int32)); + (yyval.binstr)->append((yyvsp[-3].binstr)); + AppendStringWithLength((yyval.binstr),(yyvsp[-2].string)); + AppendFieldToCustomBlob((yyval.binstr),(yyvsp[0].binstr)); + nCustomBlobNVPairs++; } +#line 3944 "asmparse.cpp" + break; + + case 81: /* customBlobNVPairs: customBlobNVPairs compControl */ #line 352 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; } break; -case 81: + { (yyval.binstr) = (yyvsp[-1].binstr); } +#line 3950 "asmparse.cpp" + break; + + case 82: /* fieldOrProp: FIELD_ */ #line 355 "asmparse.y" -{ yyval.int32 = SERIALIZATION_TYPE_FIELD; } break; -case 82: + { (yyval.int32) = SERIALIZATION_TYPE_FIELD; } +#line 3956 "asmparse.cpp" + break; + + case 83: /* fieldOrProp: PROPERTY_ */ #line 356 "asmparse.y" -{ yyval.int32 = SERIALIZATION_TYPE_PROPERTY; } break; -case 83: + { (yyval.int32) = SERIALIZATION_TYPE_PROPERTY; } +#line 3962 "asmparse.cpp" + break; + + case 84: /* customAttrDecl: customDescr */ #line 359 "asmparse.y" -{ if(yypvt[-0].cad->tkOwner && !yypvt[-0].cad->tkInterfacePair) - PASM->DefineCV(yypvt[-0].cad); + { if((yyvsp[0].cad)->tkOwner && !(yyvsp[0].cad)->tkInterfacePair) + PASM->DefineCV((yyvsp[0].cad)); else if(PASM->m_pCustomDescrList) - PASM->m_pCustomDescrList->PUSH(yypvt[-0].cad); } break; -case 84: + PASM->m_pCustomDescrList->PUSH((yyvsp[0].cad)); } +#line 3971 "asmparse.cpp" + break; + + case 85: /* customAttrDecl: customDescrWithOwner */ #line 363 "asmparse.y" -{ PASM->DefineCV(yypvt[-0].cad); } break; -case 85: + { PASM->DefineCV((yyvsp[0].cad)); } +#line 3977 "asmparse.cpp" + break; + + case 86: /* customAttrDecl: TYPEDEF_CA */ #line 364 "asmparse.y" -{ CustomDescr* pNew = new CustomDescr(yypvt[-0].tdd->m_pCA); + { CustomDescr* pNew = new CustomDescr((yyvsp[0].tdd)->m_pCA); if(pNew->tkOwner == 0) pNew->tkOwner = PASM->m_tkCurrentCVOwner; if(pNew->tkOwner) PASM->DefineCV(pNew); else if(PASM->m_pCustomDescrList) - PASM->m_pCustomDescrList->PUSH(pNew); } break; -case 86: + PASM->m_pCustomDescrList->PUSH(pNew); } +#line 3988 "asmparse.cpp" + break; + + case 87: /* serializType: simpleType */ #line 372 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 87: + { (yyval.binstr) = (yyvsp[0].binstr); } +#line 3994 "asmparse.cpp" + break; + + case 88: /* serializType: TYPE_ */ #line 373 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); } break; -case 88: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_TYPE); } +#line 4000 "asmparse.cpp" + break; + + case 89: /* serializType: OBJECT_ */ #line 374 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TAGGED_OBJECT); } break; -case 89: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_TAGGED_OBJECT); } +#line 4006 "asmparse.cpp" + break; + + case 90: /* serializType: ENUM_ CLASS_ SQSTRING */ #line 375 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); - AppendStringWithLength(yyval.binstr,yypvt[-0].string); } break; -case 90: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_ENUM); + AppendStringWithLength((yyval.binstr),(yyvsp[0].string)); } +#line 4013 "asmparse.cpp" + break; + + case 91: /* serializType: ENUM_ className */ #line 377 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); - AppendStringWithLength(yyval.binstr,PASM->ReflectionNotation(yypvt[-0].token)); } break; -case 91: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_ENUM); + AppendStringWithLength((yyval.binstr),PASM->ReflectionNotation((yyvsp[0].token))); } +#line 4020 "asmparse.cpp" + break; + + case 92: /* serializType: serializType '[' ']' */ #line 379 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 92: + { (yyval.binstr) = (yyvsp[-2].binstr); (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 4026 "asmparse.cpp" + break; + + case 93: /* moduleHead: _MODULE */ #line 384 "asmparse.y" -{ PASMM->SetModuleName(NULL); PASM->m_tkCurrentCVOwner=1; } break; -case 93: + { PASMM->SetModuleName(NULL); PASM->m_tkCurrentCVOwner=1; } +#line 4032 "asmparse.cpp" + break; + + case 94: /* moduleHead: _MODULE dottedName */ #line 385 "asmparse.y" -{ PASMM->SetModuleName(yypvt[-0].string); PASM->m_tkCurrentCVOwner=1; } break; -case 94: + { PASMM->SetModuleName((yyvsp[0].string)); PASM->m_tkCurrentCVOwner=1; } +#line 4038 "asmparse.cpp" + break; + + case 95: /* moduleHead: _MODULE EXTERN_ dottedName */ #line 386 "asmparse.y" -{ BinStr* pbs = new BinStr(); - unsigned L = (unsigned)strlen(yypvt[-0].string); - memcpy((char*)(pbs->getBuff(L)),yypvt[-0].string,L); - PASM->EmitImport(pbs); delete pbs;} break; -case 95: + { BinStr* pbs = new BinStr(); + unsigned L = (unsigned)strlen((yyvsp[0].string)); + memcpy((char*)(pbs->getBuff(L)),(yyvsp[0].string),L); + PASM->EmitImport(pbs); delete pbs;} +#line 4047 "asmparse.cpp" + break; + + case 96: /* vtfixupDecl: _VTFIXUP '[' int32 ']' vtfixupAttr AT_ id */ #line 393 "asmparse.y" -{ /*PASM->SetDataSection(); PASM->EmitDataLabel($7);*/ - PASM->m_VTFList.PUSH(new VTFEntry((USHORT)yypvt[-4].int32, (USHORT)yypvt[-2].int32, yypvt[-0].string)); } break; -case 96: + { /*PASM->SetDataSection(); PASM->EmitDataLabel($7);*/ + PASM->m_VTFList.PUSH(new VTFEntry((USHORT)(yyvsp[-4].int32), (USHORT)(yyvsp[-2].int32), (yyvsp[0].string))); } +#line 4054 "asmparse.cpp" + break; + + case 97: /* vtfixupAttr: %empty */ #line 397 "asmparse.y" -{ yyval.int32 = 0; } break; -case 97: + { (yyval.int32) = 0; } +#line 4060 "asmparse.cpp" + break; + + case 98: /* vtfixupAttr: vtfixupAttr INT32_ */ #line 398 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_32BIT; } break; -case 98: + { (yyval.int32) = (yyvsp[-1].int32) | COR_VTABLE_32BIT; } +#line 4066 "asmparse.cpp" + break; + + case 99: /* vtfixupAttr: vtfixupAttr INT64_ */ #line 399 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_64BIT; } break; -case 99: + { (yyval.int32) = (yyvsp[-1].int32) | COR_VTABLE_64BIT; } +#line 4072 "asmparse.cpp" + break; + + case 100: /* vtfixupAttr: vtfixupAttr FROMUNMANAGED_ */ #line 400 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_FROM_UNMANAGED; } break; -case 100: + { (yyval.int32) = (yyvsp[-1].int32) | COR_VTABLE_FROM_UNMANAGED; } +#line 4078 "asmparse.cpp" + break; + + case 101: /* vtfixupAttr: vtfixupAttr CALLMOSTDERIVED_ */ #line 401 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_CALL_MOST_DERIVED; } break; -case 101: + { (yyval.int32) = (yyvsp[-1].int32) | COR_VTABLE_CALL_MOST_DERIVED; } +#line 4084 "asmparse.cpp" + break; + + case 102: /* vtfixupAttr: vtfixupAttr RETAINAPPDOMAIN_ */ #line 402 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN; } break; -case 102: + { (yyval.int32) = (yyvsp[-1].int32) | COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN; } +#line 4090 "asmparse.cpp" + break; + + case 103: /* vtableDecl: vtableHead bytes ')' */ #line 405 "asmparse.y" -{ PASM->m_pVTable = yypvt[-1].binstr; } break; -case 103: + { PASM->m_pVTable = (yyvsp[-1].binstr); } +#line 4096 "asmparse.cpp" + break; + + case 104: /* vtableHead: _VTABLE '=' '(' */ #line 408 "asmparse.y" -{ bParsingByteArray = TRUE; } break; -case 104: + { bParsingByteArray = TRUE; } +#line 4102 "asmparse.cpp" + break; + + case 105: /* nameSpaceHead: _NAMESPACE dottedName */ #line 412 "asmparse.y" -{ PASM->StartNameSpace(yypvt[-0].string); } break; -case 105: + { PASM->StartNameSpace((yyvsp[0].string)); } +#line 4108 "asmparse.cpp" + break; + + case 106: /* _class: _CLASS */ #line 415 "asmparse.y" -{ newclass = TRUE; } break; -case 106: + { newclass = TRUE; } +#line 4114 "asmparse.cpp" + break; + + case 107: /* classHeadBegin: _class classAttr dottedName typarsClause */ #line 418 "asmparse.y" -{ if(yypvt[-0].typarlist) FixupConstraints(); - PASM->StartClass(yypvt[-1].string, yypvt[-2].classAttr, yypvt[-0].typarlist); + { if((yyvsp[0].typarlist)) FixupConstraints(); + PASM->StartClass((yyvsp[-1].string), (yyvsp[-2].classAttr), (yyvsp[0].typarlist)); TyParFixupList.RESET(false); newclass = FALSE; - } break; -case 107: + } +#line 4124 "asmparse.cpp" + break; + + case 108: /* classHead: classHeadBegin extendsClause implClause */ #line 424 "asmparse.y" -{ PASM->AddClass(); } break; -case 108: + { PASM->AddClass(); } +#line 4130 "asmparse.cpp" + break; + + case 109: /* classAttr: %empty */ #line 427 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) 0; } break; -case 109: + { (yyval.classAttr) = (CorRegTypeAttr) 0; } +#line 4136 "asmparse.cpp" + break; + + case 110: /* classAttr: classAttr PUBLIC_ */ #line 428 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdVisibilityMask) | tdPublic); } break; -case 110: + { (yyval.classAttr) = (CorRegTypeAttr) (((yyvsp[-1].classAttr) & ~tdVisibilityMask) | tdPublic); } +#line 4142 "asmparse.cpp" + break; + + case 111: /* classAttr: classAttr PRIVATE_ */ #line 429 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdVisibilityMask) | tdNotPublic); } break; -case 111: + { (yyval.classAttr) = (CorRegTypeAttr) (((yyvsp[-1].classAttr) & ~tdVisibilityMask) | tdNotPublic); } +#line 4148 "asmparse.cpp" + break; + + case 112: /* classAttr: classAttr VALUE_ */ #line 430 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | 0x80000000 | tdSealed); } break; -case 112: + { (yyval.classAttr) = (CorRegTypeAttr) ((yyvsp[-1].classAttr) | 0x80000000 | tdSealed); } +#line 4154 "asmparse.cpp" + break; + + case 113: /* classAttr: classAttr ENUM_ */ #line 431 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | 0x40000000); } break; -case 113: + { (yyval.classAttr) = (CorRegTypeAttr) ((yyvsp[-1].classAttr) | 0x40000000); } +#line 4160 "asmparse.cpp" + break; + + case 114: /* classAttr: classAttr INTERFACE_ */ #line 432 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdInterface | tdAbstract); } break; -case 114: + { (yyval.classAttr) = (CorRegTypeAttr) ((yyvsp[-1].classAttr) | tdInterface | tdAbstract); } +#line 4166 "asmparse.cpp" + break; + + case 115: /* classAttr: classAttr SEALED_ */ #line 433 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdSealed); } break; -case 115: + { (yyval.classAttr) = (CorRegTypeAttr) ((yyvsp[-1].classAttr) | tdSealed); } +#line 4172 "asmparse.cpp" + break; + + case 116: /* classAttr: classAttr ABSTRACT_ */ #line 434 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdAbstract); } break; -case 116: + { (yyval.classAttr) = (CorRegTypeAttr) ((yyvsp[-1].classAttr) | tdAbstract); } +#line 4178 "asmparse.cpp" + break; + + case 117: /* classAttr: classAttr AUTO_ */ #line 435 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdLayoutMask) | tdAutoLayout); } break; -case 117: + { (yyval.classAttr) = (CorRegTypeAttr) (((yyvsp[-1].classAttr) & ~tdLayoutMask) | tdAutoLayout); } +#line 4184 "asmparse.cpp" + break; + + case 118: /* classAttr: classAttr SEQUENTIAL_ */ #line 436 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdLayoutMask) | tdSequentialLayout); } break; -case 118: + { (yyval.classAttr) = (CorRegTypeAttr) (((yyvsp[-1].classAttr) & ~tdLayoutMask) | tdSequentialLayout); } +#line 4190 "asmparse.cpp" + break; + + case 119: /* classAttr: classAttr EXPLICIT_ */ #line 437 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdLayoutMask) | tdExplicitLayout); } break; -case 119: + { (yyval.classAttr) = (CorRegTypeAttr) (((yyvsp[-1].classAttr) & ~tdLayoutMask) | tdExplicitLayout); } +#line 4196 "asmparse.cpp" + break; + + case 120: /* classAttr: classAttr ANSI_ */ #line 438 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdStringFormatMask) | tdAnsiClass); } break; -case 120: + { (yyval.classAttr) = (CorRegTypeAttr) (((yyvsp[-1].classAttr) & ~tdStringFormatMask) | tdAnsiClass); } +#line 4202 "asmparse.cpp" + break; + + case 121: /* classAttr: classAttr UNICODE_ */ #line 439 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdStringFormatMask) | tdUnicodeClass); } break; -case 121: + { (yyval.classAttr) = (CorRegTypeAttr) (((yyvsp[-1].classAttr) & ~tdStringFormatMask) | tdUnicodeClass); } +#line 4208 "asmparse.cpp" + break; + + case 122: /* classAttr: classAttr AUTOCHAR_ */ #line 440 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdStringFormatMask) | tdAutoClass); } break; -case 122: + { (yyval.classAttr) = (CorRegTypeAttr) (((yyvsp[-1].classAttr) & ~tdStringFormatMask) | tdAutoClass); } +#line 4214 "asmparse.cpp" + break; + + case 123: /* classAttr: classAttr IMPORT_ */ #line 441 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdImport); } break; -case 123: + { (yyval.classAttr) = (CorRegTypeAttr) ((yyvsp[-1].classAttr) | tdImport); } +#line 4220 "asmparse.cpp" + break; + + case 124: /* classAttr: classAttr SERIALIZABLE_ */ #line 442 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdSerializable); } break; -case 124: + { (yyval.classAttr) = (CorRegTypeAttr) ((yyvsp[-1].classAttr) | tdSerializable); } +#line 4226 "asmparse.cpp" + break; + + case 125: /* classAttr: classAttr WINDOWSRUNTIME_ */ #line 443 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdWindowsRuntime); } break; -case 125: + { (yyval.classAttr) = (CorRegTypeAttr) ((yyvsp[-1].classAttr) | tdWindowsRuntime); } +#line 4232 "asmparse.cpp" + break; + + case 126: /* classAttr: classAttr NESTED_ PUBLIC_ */ #line 444 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedPublic); } break; -case 126: + { (yyval.classAttr) = (CorRegTypeAttr) (((yyvsp[-2].classAttr) & ~tdVisibilityMask) | tdNestedPublic); } +#line 4238 "asmparse.cpp" + break; + + case 127: /* classAttr: classAttr NESTED_ PRIVATE_ */ #line 445 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedPrivate); } break; -case 127: + { (yyval.classAttr) = (CorRegTypeAttr) (((yyvsp[-2].classAttr) & ~tdVisibilityMask) | tdNestedPrivate); } +#line 4244 "asmparse.cpp" + break; + + case 128: /* classAttr: classAttr NESTED_ FAMILY_ */ #line 446 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedFamily); } break; -case 128: + { (yyval.classAttr) = (CorRegTypeAttr) (((yyvsp[-2].classAttr) & ~tdVisibilityMask) | tdNestedFamily); } +#line 4250 "asmparse.cpp" + break; + + case 129: /* classAttr: classAttr NESTED_ ASSEMBLY_ */ #line 447 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedAssembly); } break; -case 129: + { (yyval.classAttr) = (CorRegTypeAttr) (((yyvsp[-2].classAttr) & ~tdVisibilityMask) | tdNestedAssembly); } +#line 4256 "asmparse.cpp" + break; + + case 130: /* classAttr: classAttr NESTED_ FAMANDASSEM_ */ #line 448 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedFamANDAssem); } break; -case 130: + { (yyval.classAttr) = (CorRegTypeAttr) (((yyvsp[-2].classAttr) & ~tdVisibilityMask) | tdNestedFamANDAssem); } +#line 4262 "asmparse.cpp" + break; + + case 131: /* classAttr: classAttr NESTED_ FAMORASSEM_ */ #line 449 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedFamORAssem); } break; -case 131: + { (yyval.classAttr) = (CorRegTypeAttr) (((yyvsp[-2].classAttr) & ~tdVisibilityMask) | tdNestedFamORAssem); } +#line 4268 "asmparse.cpp" + break; + + case 132: /* classAttr: classAttr BEFOREFIELDINIT_ */ #line 450 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdBeforeFieldInit); } break; -case 132: + { (yyval.classAttr) = (CorRegTypeAttr) ((yyvsp[-1].classAttr) | tdBeforeFieldInit); } +#line 4274 "asmparse.cpp" + break; + + case 133: /* classAttr: classAttr SPECIALNAME_ */ #line 451 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdSpecialName); } break; -case 133: + { (yyval.classAttr) = (CorRegTypeAttr) ((yyvsp[-1].classAttr) | tdSpecialName); } +#line 4280 "asmparse.cpp" + break; + + case 134: /* classAttr: classAttr RTSPECIALNAME_ */ #line 452 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr); } break; -case 134: + { (yyval.classAttr) = (CorRegTypeAttr) ((yyvsp[-1].classAttr)); } +#line 4286 "asmparse.cpp" + break; + + case 135: /* classAttr: classAttr FLAGS_ '(' int32 ')' */ #line 453 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].int32); } break; -case 136: + { (yyval.classAttr) = (CorRegTypeAttr) ((yyvsp[-1].int32)); } +#line 4292 "asmparse.cpp" + break; + + case 137: /* extendsClause: EXTENDS_ typeSpec */ #line 457 "asmparse.y" -{ PASM->m_crExtends = yypvt[-0].token; } break; -case 141: + { PASM->m_crExtends = (yyvsp[0].token); } +#line 4298 "asmparse.cpp" + break; + + case 142: /* implList: implList ',' typeSpec */ #line 468 "asmparse.y" -{ PASM->AddToImplList(yypvt[-0].token); } break; -case 142: + { PASM->AddToImplList((yyvsp[0].token)); } +#line 4304 "asmparse.cpp" + break; + + case 143: /* implList: typeSpec */ #line 469 "asmparse.y" -{ PASM->AddToImplList(yypvt[-0].token); } break; -case 143: + { PASM->AddToImplList((yyvsp[0].token)); } +#line 4310 "asmparse.cpp" + break; + + case 144: /* typeList: %empty */ #line 473 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 144: + { (yyval.binstr) = new BinStr(); } +#line 4316 "asmparse.cpp" + break; + + case 145: /* typeList: typeListNotEmpty */ #line 474 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 145: + { (yyval.binstr) = (yyvsp[0].binstr); } +#line 4322 "asmparse.cpp" + break; + + case 146: /* typeListNotEmpty: typeSpec */ #line 477 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(yypvt[-0].token); } break; -case 146: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt32((yyvsp[0].token)); } +#line 4328 "asmparse.cpp" + break; + + case 147: /* typeListNotEmpty: typeListNotEmpty ',' typeSpec */ #line 478 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->appendInt32(yypvt[-0].token); } break; -case 147: + { (yyval.binstr) = (yyvsp[-2].binstr); (yyval.binstr)->appendInt32((yyvsp[0].token)); } +#line 4334 "asmparse.cpp" + break; + + case 148: /* typarsClause: %empty */ #line 481 "asmparse.y" -{ yyval.typarlist = NULL; PASM->m_TyParList = NULL;} break; -case 148: + { (yyval.typarlist) = NULL; PASM->m_TyParList = NULL;} +#line 4340 "asmparse.cpp" + break; + + case 149: /* typarsClause: '<' typars '>' */ #line 482 "asmparse.y" -{ yyval.typarlist = yypvt[-1].typarlist; PASM->m_TyParList = yypvt[-1].typarlist;} break; -case 149: + { (yyval.typarlist) = (yyvsp[-1].typarlist); PASM->m_TyParList = (yyvsp[-1].typarlist);} +#line 4346 "asmparse.cpp" + break; + + case 150: /* typarAttrib: '+' */ #line 485 "asmparse.y" -{ yyval.int32 = gpCovariant; } break; -case 150: + { (yyval.int32) = gpCovariant; } +#line 4352 "asmparse.cpp" + break; + + case 151: /* typarAttrib: '-' */ #line 486 "asmparse.y" -{ yyval.int32 = gpContravariant; } break; -case 151: + { (yyval.int32) = gpContravariant; } +#line 4358 "asmparse.cpp" + break; + + case 152: /* typarAttrib: CLASS_ */ #line 487 "asmparse.y" -{ yyval.int32 = gpReferenceTypeConstraint; } break; -case 152: + { (yyval.int32) = gpReferenceTypeConstraint; } +#line 4364 "asmparse.cpp" + break; + + case 153: /* typarAttrib: VALUETYPE_ */ #line 488 "asmparse.y" -{ yyval.int32 = gpNotNullableValueTypeConstraint; } break; -case 153: + { (yyval.int32) = gpNotNullableValueTypeConstraint; } +#line 4370 "asmparse.cpp" + break; + + case 154: /* typarAttrib: BYREFLIKE_ */ #line 489 "asmparse.y" -{ yyval.int32 = gpAllowByRefLike; } break; -case 154: + { (yyval.int32) = gpAllowByRefLike; } +#line 4376 "asmparse.cpp" + break; + + case 155: /* typarAttrib: _CTOR */ #line 490 "asmparse.y" -{ yyval.int32 = gpDefaultConstructorConstraint; } break; -case 155: + { (yyval.int32) = gpDefaultConstructorConstraint; } +#line 4382 "asmparse.cpp" + break; + + case 156: /* typarAttrib: FLAGS_ '(' int32 ')' */ #line 491 "asmparse.y" -{ yyval.int32 = (CorGenericParamAttr)yypvt[-1].int32; } break; -case 156: + { (yyval.int32) = (CorGenericParamAttr)(yyvsp[-1].int32); } +#line 4388 "asmparse.cpp" + break; + + case 157: /* typarAttribs: %empty */ #line 494 "asmparse.y" -{ yyval.int32 = 0; } break; -case 157: + { (yyval.int32) = 0; } +#line 4394 "asmparse.cpp" + break; + + case 158: /* typarAttribs: typarAttrib typarAttribs */ #line 495 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | yypvt[-0].int32; } break; -case 158: + { (yyval.int32) = (yyvsp[-1].int32) | (yyvsp[0].int32); } +#line 4400 "asmparse.cpp" + break; + + case 159: /* typars: typarAttribs tyBound dottedName typarsRest */ #line 498 "asmparse.y" -{yyval.typarlist = new TyParList(yypvt[-3].int32, yypvt[-2].binstr, yypvt[-1].string, yypvt[-0].typarlist);} break; -case 159: + {(yyval.typarlist) = new TyParList((yyvsp[-3].int32), (yyvsp[-2].binstr), (yyvsp[-1].string), (yyvsp[0].typarlist));} +#line 4406 "asmparse.cpp" + break; + + case 160: /* typars: typarAttribs dottedName typarsRest */ #line 499 "asmparse.y" -{yyval.typarlist = new TyParList(yypvt[-2].int32, NULL, yypvt[-1].string, yypvt[-0].typarlist);} break; -case 160: + {(yyval.typarlist) = new TyParList((yyvsp[-2].int32), NULL, (yyvsp[-1].string), (yyvsp[0].typarlist));} +#line 4412 "asmparse.cpp" + break; + + case 161: /* typarsRest: %empty */ #line 502 "asmparse.y" -{ yyval.typarlist = NULL; } break; -case 161: + { (yyval.typarlist) = NULL; } +#line 4418 "asmparse.cpp" + break; + + case 162: /* typarsRest: ',' typars */ #line 503 "asmparse.y" -{ yyval.typarlist = yypvt[-0].typarlist; } break; -case 162: + { (yyval.typarlist) = (yyvsp[0].typarlist); } +#line 4424 "asmparse.cpp" + break; + + case 163: /* tyBound: '(' typeList ')' */ #line 506 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; } break; -case 163: + { (yyval.binstr) = (yyvsp[-1].binstr); } +#line 4430 "asmparse.cpp" + break; + + case 164: /* genArity: %empty */ #line 509 "asmparse.y" -{ yyval.int32= 0; } break; -case 164: + { (yyval.int32)= 0; } +#line 4436 "asmparse.cpp" + break; + + case 165: /* genArity: genArityNotEmpty */ #line 510 "asmparse.y" -{ yyval.int32 = yypvt[-0].int32; } break; -case 165: + { (yyval.int32) = (yyvsp[0].int32); } +#line 4442 "asmparse.cpp" + break; + + case 166: /* genArityNotEmpty: '<' '[' int32 ']' '>' */ #line 513 "asmparse.y" -{ yyval.int32 = yypvt[-2].int32; } break; -case 166: + { (yyval.int32) = (yyvsp[-2].int32); } +#line 4448 "asmparse.cpp" + break; + + case 167: /* classDecl: methodHead methodDecls '}' */ #line 517 "asmparse.y" -{ if(PASM->m_pCurMethod->m_ulLines[1] ==0) + { if(PASM->m_pCurMethod->m_ulLines[1] ==0) { PASM->m_pCurMethod->m_ulLines[1] = PASM->m_ulCurLine; PASM->m_pCurMethod->m_ulColumns[1]=PASM->m_ulCurColumn;} - PASM->EndMethod(); } break; -case 167: + PASM->EndMethod(); } +#line 4457 "asmparse.cpp" + break; + + case 168: /* classDecl: classHead '{' classDecls '}' */ #line 521 "asmparse.y" -{ PASM->EndClass(); } break; -case 168: + { PASM->EndClass(); } +#line 4463 "asmparse.cpp" + break; + + case 169: /* classDecl: eventHead '{' eventDecls '}' */ #line 522 "asmparse.y" -{ PASM->EndEvent(); } break; -case 169: + { PASM->EndEvent(); } +#line 4469 "asmparse.cpp" + break; + + case 170: /* classDecl: propHead '{' propDecls '}' */ #line 523 "asmparse.y" -{ PASM->EndProp(); } break; -case 175: + { PASM->EndProp(); } +#line 4475 "asmparse.cpp" + break; + + case 176: /* classDecl: _SIZE int32 */ #line 529 "asmparse.y" -{ PASM->m_pCurClass->m_ulSize = yypvt[-0].int32; } break; -case 176: + { PASM->m_pCurClass->m_ulSize = (yyvsp[0].int32); } +#line 4481 "asmparse.cpp" + break; + + case 177: /* classDecl: _PACK int32 */ #line 530 "asmparse.y" -{ PASM->m_pCurClass->m_ulPack = yypvt[-0].int32; } break; -case 177: + { PASM->m_pCurClass->m_ulPack = (yyvsp[0].int32); } +#line 4487 "asmparse.cpp" + break; + + case 178: /* classDecl: exportHead '{' exptypeDecls '}' */ #line 531 "asmparse.y" -{ PASMM->EndComType(); } break; -case 178: + { PASMM->EndComType(); } +#line 4493 "asmparse.cpp" + break; + + case 179: /* classDecl: _OVERRIDE typeSpec DCOLON methodName WITH_ callConv type typeSpec DCOLON methodName '(' sigArgs0 ')' */ #line 533 "asmparse.y" -{ BinStr *sig1 = parser->MakeSig(yypvt[-7].int32, yypvt[-6].binstr, yypvt[-1].binstr); + { BinStr *sig1 = parser->MakeSig((yyvsp[-7].int32), (yyvsp[-6].binstr), (yyvsp[-1].binstr)); BinStr *sig2 = new BinStr(); sig2->append(sig1); - PASM->AddMethodImpl(yypvt[-11].token,yypvt[-9].string,sig1,yypvt[-5].token,yypvt[-3].string,sig2); + PASM->AddMethodImpl((yyvsp[-11].token),(yyvsp[-9].string),sig1,(yyvsp[-5].token),(yyvsp[-3].string),sig2); PASM->ResetArgNameList(); - } break; -case 179: + } +#line 4503 "asmparse.cpp" + break; + + case 180: /* classDecl: _OVERRIDE METHOD_ callConv type typeSpec DCOLON methodName genArity '(' sigArgs0 ')' WITH_ METHOD_ callConv type typeSpec DCOLON methodName genArity '(' sigArgs0 ')' */ #line 539 "asmparse.y" -{ PASM->AddMethodImpl(yypvt[-17].token,yypvt[-15].string, - (yypvt[-14].int32==0 ? parser->MakeSig(yypvt[-19].int32,yypvt[-18].binstr,yypvt[-12].binstr) : - parser->MakeSig(yypvt[-19].int32| IMAGE_CEE_CS_CALLCONV_GENERIC,yypvt[-18].binstr,yypvt[-12].binstr,yypvt[-14].int32)), - yypvt[-6].token,yypvt[-4].string, - (yypvt[-3].int32==0 ? parser->MakeSig(yypvt[-8].int32,yypvt[-7].binstr,yypvt[-1].binstr) : - parser->MakeSig(yypvt[-8].int32| IMAGE_CEE_CS_CALLCONV_GENERIC,yypvt[-7].binstr,yypvt[-1].binstr,yypvt[-3].int32))); + { PASM->AddMethodImpl((yyvsp[-17].token),(yyvsp[-15].string), + ((yyvsp[-14].int32)==0 ? parser->MakeSig((yyvsp[-19].int32),(yyvsp[-18].binstr),(yyvsp[-12].binstr)) : + parser->MakeSig((yyvsp[-19].int32)| IMAGE_CEE_CS_CALLCONV_GENERIC,(yyvsp[-18].binstr),(yyvsp[-12].binstr),(yyvsp[-14].int32))), + (yyvsp[-6].token),(yyvsp[-4].string), + ((yyvsp[-3].int32)==0 ? parser->MakeSig((yyvsp[-8].int32),(yyvsp[-7].binstr),(yyvsp[-1].binstr)) : + parser->MakeSig((yyvsp[-8].int32)| IMAGE_CEE_CS_CALLCONV_GENERIC,(yyvsp[-7].binstr),(yyvsp[-1].binstr),(yyvsp[-3].int32)))); PASM->ResetArgNameList(); - } break; -case 182: + } +#line 4516 "asmparse.cpp" + break; + + case 183: /* classDecl: _PARAM TYPE_ '[' int32 ']' */ #line 549 "asmparse.y" -{ if((yypvt[-1].int32 > 0) && (yypvt[-1].int32 <= (int)PASM->m_pCurClass->m_NumTyPars)) - PASM->m_pCustomDescrList = PASM->m_pCurClass->m_TyPars[yypvt[-1].int32-1].CAList(); + { if(((yyvsp[-1].int32) > 0) && ((yyvsp[-1].int32) <= (int)PASM->m_pCurClass->m_NumTyPars)) + PASM->m_pCustomDescrList = PASM->m_pCurClass->m_TyPars[(yyvsp[-1].int32)-1].CAList(); else PASM->report->error("Type parameter index out of range\n"); - } break; -case 183: + } +#line 4526 "asmparse.cpp" + break; + + case 184: /* classDecl: _PARAM TYPE_ dottedName */ #line 554 "asmparse.y" -{ int n = PASM->m_pCurClass->FindTyPar(yypvt[-0].string); + { int n = PASM->m_pCurClass->FindTyPar((yyvsp[0].string)); if(n >= 0) PASM->m_pCustomDescrList = PASM->m_pCurClass->m_TyPars[n].CAList(); else - PASM->report->error("Type parameter '%s' undefined\n",yypvt[-0].string); - } break; -case 184: + PASM->report->error("Type parameter '%s' undefined\n",(yyvsp[0].string)); + } +#line 4537 "asmparse.cpp" + break; + + case 185: /* classDecl: _PARAM CONSTRAINT_ '[' int32 ']' ',' typeSpec */ #line 560 "asmparse.y" -{ PASM->AddGenericParamConstraint(yypvt[-3].int32, 0, yypvt[-0].token); } break; -case 185: + { PASM->AddGenericParamConstraint((yyvsp[-3].int32), 0, (yyvsp[0].token)); } +#line 4543 "asmparse.cpp" + break; + + case 186: /* classDecl: _PARAM CONSTRAINT_ dottedName ',' typeSpec */ #line 561 "asmparse.y" -{ PASM->AddGenericParamConstraint(0, yypvt[-2].string, yypvt[-0].token); } break; -case 186: + { PASM->AddGenericParamConstraint(0, (yyvsp[-2].string), (yyvsp[0].token)); } +#line 4549 "asmparse.cpp" + break; + + case 187: /* classDecl: _INTERFACEIMPL TYPE_ typeSpec customDescr */ #line 562 "asmparse.y" -{ yypvt[-0].cad->tkInterfacePair = yypvt[-1].token; + { (yyvsp[0].cad)->tkInterfacePair = (yyvsp[-1].token); if(PASM->m_pCustomDescrList) - PASM->m_pCustomDescrList->PUSH(yypvt[-0].cad); - } break; -case 187: + PASM->m_pCustomDescrList->PUSH((yyvsp[0].cad)); + } +#line 4558 "asmparse.cpp" + break; + + case 188: /* fieldDecl: _FIELD repeatOpt fieldAttr type dottedName atOpt initOpt */ #line 570 "asmparse.y" -{ yypvt[-3].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); - PASM->AddField(yypvt[-2].string, yypvt[-3].binstr, yypvt[-4].fieldAttr, yypvt[-1].string, yypvt[-0].binstr, yypvt[-5].int32); } break; -case 188: + { (yyvsp[-3].binstr)->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + PASM->AddField((yyvsp[-2].string), (yyvsp[-3].binstr), (yyvsp[-4].fieldAttr), (yyvsp[-1].string), (yyvsp[0].binstr), (yyvsp[-5].int32)); } +#line 4565 "asmparse.cpp" + break; + + case 189: /* fieldAttr: %empty */ #line 574 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) 0; } break; -case 189: + { (yyval.fieldAttr) = (CorFieldAttr) 0; } +#line 4571 "asmparse.cpp" + break; + + case 190: /* fieldAttr: fieldAttr STATIC_ */ #line 575 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdStatic); } break; -case 190: + { (yyval.fieldAttr) = (CorFieldAttr) ((yyvsp[-1].fieldAttr) | fdStatic); } +#line 4577 "asmparse.cpp" + break; + + case 191: /* fieldAttr: fieldAttr PUBLIC_ */ #line 576 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdPublic); } break; -case 191: + { (yyval.fieldAttr) = (CorFieldAttr) (((yyvsp[-1].fieldAttr) & ~mdMemberAccessMask) | fdPublic); } +#line 4583 "asmparse.cpp" + break; + + case 192: /* fieldAttr: fieldAttr PRIVATE_ */ #line 577 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdPrivate); } break; -case 192: + { (yyval.fieldAttr) = (CorFieldAttr) (((yyvsp[-1].fieldAttr) & ~mdMemberAccessMask) | fdPrivate); } +#line 4589 "asmparse.cpp" + break; + + case 193: /* fieldAttr: fieldAttr FAMILY_ */ #line 578 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdFamily); } break; -case 193: + { (yyval.fieldAttr) = (CorFieldAttr) (((yyvsp[-1].fieldAttr) & ~mdMemberAccessMask) | fdFamily); } +#line 4595 "asmparse.cpp" + break; + + case 194: /* fieldAttr: fieldAttr INITONLY_ */ #line 579 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdInitOnly); } break; -case 194: + { (yyval.fieldAttr) = (CorFieldAttr) ((yyvsp[-1].fieldAttr) | fdInitOnly); } +#line 4601 "asmparse.cpp" + break; + + case 195: /* fieldAttr: fieldAttr RTSPECIALNAME_ */ #line 580 "asmparse.y" -{ yyval.fieldAttr = yypvt[-1].fieldAttr; } break; -case 195: + { (yyval.fieldAttr) = (yyvsp[-1].fieldAttr); } +#line 4607 "asmparse.cpp" + break; + + case 196: /* fieldAttr: fieldAttr SPECIALNAME_ */ #line 581 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdSpecialName); } break; -case 196: + { (yyval.fieldAttr) = (CorFieldAttr) ((yyvsp[-1].fieldAttr) | fdSpecialName); } +#line 4613 "asmparse.cpp" + break; + + case 197: /* fieldAttr: fieldAttr MARSHAL_ '(' marshalBlob ')' */ #line 594 "asmparse.y" -{ PASM->m_pMarshal = yypvt[-1].binstr; } break; -case 197: + { PASM->m_pMarshal = (yyvsp[-1].binstr); } +#line 4619 "asmparse.cpp" + break; + + case 198: /* fieldAttr: fieldAttr ASSEMBLY_ */ #line 595 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdAssembly); } break; -case 198: + { (yyval.fieldAttr) = (CorFieldAttr) (((yyvsp[-1].fieldAttr) & ~mdMemberAccessMask) | fdAssembly); } +#line 4625 "asmparse.cpp" + break; + + case 199: /* fieldAttr: fieldAttr FAMANDASSEM_ */ #line 596 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdFamANDAssem); } break; -case 199: + { (yyval.fieldAttr) = (CorFieldAttr) (((yyvsp[-1].fieldAttr) & ~mdMemberAccessMask) | fdFamANDAssem); } +#line 4631 "asmparse.cpp" + break; + + case 200: /* fieldAttr: fieldAttr FAMORASSEM_ */ #line 597 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdFamORAssem); } break; -case 200: + { (yyval.fieldAttr) = (CorFieldAttr) (((yyvsp[-1].fieldAttr) & ~mdMemberAccessMask) | fdFamORAssem); } +#line 4637 "asmparse.cpp" + break; + + case 201: /* fieldAttr: fieldAttr PRIVATESCOPE_ */ #line 598 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdPrivateScope); } break; -case 201: + { (yyval.fieldAttr) = (CorFieldAttr) (((yyvsp[-1].fieldAttr) & ~mdMemberAccessMask) | fdPrivateScope); } +#line 4643 "asmparse.cpp" + break; + + case 202: /* fieldAttr: fieldAttr LITERAL_ */ #line 599 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdLiteral); } break; -case 202: + { (yyval.fieldAttr) = (CorFieldAttr) ((yyvsp[-1].fieldAttr) | fdLiteral); } +#line 4649 "asmparse.cpp" + break; + + case 203: /* fieldAttr: fieldAttr NOTSERIALIZED_ */ #line 600 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdNotSerialized); } break; -case 203: + { (yyval.fieldAttr) = (CorFieldAttr) ((yyvsp[-1].fieldAttr) | fdNotSerialized); } +#line 4655 "asmparse.cpp" + break; + + case 204: /* fieldAttr: fieldAttr FLAGS_ '(' int32 ')' */ #line 601 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].int32); } break; -case 204: + { (yyval.fieldAttr) = (CorFieldAttr) ((yyvsp[-1].int32)); } +#line 4661 "asmparse.cpp" + break; + + case 205: /* atOpt: %empty */ #line 604 "asmparse.y" -{ yyval.string = 0; } break; -case 205: + { (yyval.string) = 0; } +#line 4667 "asmparse.cpp" + break; + + case 206: /* atOpt: AT_ id */ #line 605 "asmparse.y" -{ yyval.string = yypvt[-0].string; } break; -case 206: + { (yyval.string) = (yyvsp[0].string); } +#line 4673 "asmparse.cpp" + break; + + case 207: /* initOpt: %empty */ #line 608 "asmparse.y" -{ yyval.binstr = NULL; } break; -case 207: + { (yyval.binstr) = NULL; } +#line 4679 "asmparse.cpp" + break; + + case 208: /* initOpt: '=' fieldInit */ #line 609 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 208: + { (yyval.binstr) = (yyvsp[0].binstr); } +#line 4685 "asmparse.cpp" + break; + + case 209: /* repeatOpt: %empty */ #line 612 "asmparse.y" -{ yyval.int32 = 0xFFFFFFFF; } break; -case 209: + { (yyval.int32) = 0xFFFFFFFF; } +#line 4691 "asmparse.cpp" + break; + + case 210: /* repeatOpt: '[' int32 ']' */ #line 613 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32; } break; -case 210: + { (yyval.int32) = (yyvsp[-1].int32); } +#line 4697 "asmparse.cpp" + break; + + case 211: /* methodRef: callConv type typeSpec DCOLON methodName tyArgs0 '(' sigArgs0 ')' */ #line 618 "asmparse.y" -{ PASM->ResetArgNameList(); - if (yypvt[-3].binstr == NULL) + { PASM->ResetArgNameList(); + if ((yyvsp[-3].binstr) == NULL) { - if((iCallConv)&&((yypvt[-8].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); - yyval.token = PASM->MakeMemberRef(yypvt[-6].token, yypvt[-4].string, parser->MakeSig(yypvt[-8].int32|iCallConv, yypvt[-7].binstr, yypvt[-1].binstr)); + if((iCallConv)&&(((yyvsp[-8].int32) & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + (yyval.token) = PASM->MakeMemberRef((yyvsp[-6].token), (yyvsp[-4].string), parser->MakeSig((yyvsp[-8].int32)|iCallConv, (yyvsp[-7].binstr), (yyvsp[-1].binstr))); } else { mdToken mr; - if((iCallConv)&&((yypvt[-8].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); - mr = PASM->MakeMemberRef(yypvt[-6].token, yypvt[-4].string, - parser->MakeSig(yypvt[-8].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-7].binstr, yypvt[-1].binstr, corCountArgs(yypvt[-3].binstr))); - yyval.token = PASM->MakeMethodSpec(mr, - parser->MakeSig(IMAGE_CEE_CS_CALLCONV_INSTANTIATION, 0, yypvt[-3].binstr)); + if((iCallConv)&&(((yyvsp[-8].int32) & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + mr = PASM->MakeMemberRef((yyvsp[-6].token), (yyvsp[-4].string), + parser->MakeSig((yyvsp[-8].int32) | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, (yyvsp[-7].binstr), (yyvsp[-1].binstr), corCountArgs((yyvsp[-3].binstr)))); + (yyval.token) = PASM->MakeMethodSpec(mr, + parser->MakeSig(IMAGE_CEE_CS_CALLCONV_INSTANTIATION, 0, (yyvsp[-3].binstr))); } - } break; -case 211: + } +#line 4718 "asmparse.cpp" + break; + + case 212: /* methodRef: callConv type typeSpec DCOLON methodName genArityNotEmpty '(' sigArgs0 ')' */ #line 635 "asmparse.y" -{ PASM->ResetArgNameList(); - if((iCallConv)&&((yypvt[-8].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); - yyval.token = PASM->MakeMemberRef(yypvt[-6].token, yypvt[-4].string, - parser->MakeSig(yypvt[-8].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-7].binstr, yypvt[-1].binstr, yypvt[-3].int32)); - } break; -case 212: + { PASM->ResetArgNameList(); + if((iCallConv)&&(((yyvsp[-8].int32) & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + (yyval.token) = PASM->MakeMemberRef((yyvsp[-6].token), (yyvsp[-4].string), + parser->MakeSig((yyvsp[-8].int32) | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, (yyvsp[-7].binstr), (yyvsp[-1].binstr), (yyvsp[-3].int32))); + } +#line 4728 "asmparse.cpp" + break; + + case 213: /* methodRef: callConv type methodName tyArgs0 '(' sigArgs0 ')' */ #line 641 "asmparse.y" -{ PASM->ResetArgNameList(); - if (yypvt[-3].binstr == NULL) + { PASM->ResetArgNameList(); + if ((yyvsp[-3].binstr) == NULL) { - if((iCallConv)&&((yypvt[-6].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); - yyval.token = PASM->MakeMemberRef(mdTokenNil, yypvt[-4].string, parser->MakeSig(yypvt[-6].int32|iCallConv, yypvt[-5].binstr, yypvt[-1].binstr)); + if((iCallConv)&&(((yyvsp[-6].int32) & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + (yyval.token) = PASM->MakeMemberRef(mdTokenNil, (yyvsp[-4].string), parser->MakeSig((yyvsp[-6].int32)|iCallConv, (yyvsp[-5].binstr), (yyvsp[-1].binstr))); } else { mdToken mr; - if((iCallConv)&&((yypvt[-6].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); - mr = PASM->MakeMemberRef(mdTokenNil, yypvt[-4].string, parser->MakeSig(yypvt[-6].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-5].binstr, yypvt[-1].binstr, corCountArgs(yypvt[-3].binstr))); - yyval.token = PASM->MakeMethodSpec(mr, - parser->MakeSig(IMAGE_CEE_CS_CALLCONV_INSTANTIATION, 0, yypvt[-3].binstr)); + if((iCallConv)&&(((yyvsp[-6].int32) & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + mr = PASM->MakeMemberRef(mdTokenNil, (yyvsp[-4].string), parser->MakeSig((yyvsp[-6].int32) | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, (yyvsp[-5].binstr), (yyvsp[-1].binstr), corCountArgs((yyvsp[-3].binstr)))); + (yyval.token) = PASM->MakeMethodSpec(mr, + parser->MakeSig(IMAGE_CEE_CS_CALLCONV_INSTANTIATION, 0, (yyvsp[-3].binstr))); } - } break; -case 213: + } +#line 4748 "asmparse.cpp" + break; + + case 214: /* methodRef: callConv type methodName genArityNotEmpty '(' sigArgs0 ')' */ #line 657 "asmparse.y" -{ PASM->ResetArgNameList(); - if((iCallConv)&&((yypvt[-6].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); - yyval.token = PASM->MakeMemberRef(mdTokenNil, yypvt[-4].string, parser->MakeSig(yypvt[-6].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-5].binstr, yypvt[-1].binstr, yypvt[-3].int32)); - } break; -case 214: + { PASM->ResetArgNameList(); + if((iCallConv)&&(((yyvsp[-6].int32) & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + (yyval.token) = PASM->MakeMemberRef(mdTokenNil, (yyvsp[-4].string), parser->MakeSig((yyvsp[-6].int32) | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, (yyvsp[-5].binstr), (yyvsp[-1].binstr), (yyvsp[-3].int32))); + } +#line 4757 "asmparse.cpp" + break; + + case 215: /* methodRef: mdtoken */ #line 661 "asmparse.y" -{ yyval.token = yypvt[-0].token; } break; -case 215: + { (yyval.token) = (yyvsp[0].token); } +#line 4763 "asmparse.cpp" + break; + + case 216: /* methodRef: TYPEDEF_M */ #line 662 "asmparse.y" -{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; } break; -case 216: + { (yyval.token) = (yyvsp[0].tdd)->m_tkTypeSpec; } +#line 4769 "asmparse.cpp" + break; + + case 217: /* methodRef: TYPEDEF_MR */ #line 663 "asmparse.y" -{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; } break; -case 217: + { (yyval.token) = (yyvsp[0].tdd)->m_tkTypeSpec; } +#line 4775 "asmparse.cpp" + break; + + case 218: /* callConv: INSTANCE_ callConv */ #line 666 "asmparse.y" -{ yyval.int32 = (yypvt[-0].int32 | IMAGE_CEE_CS_CALLCONV_HASTHIS); } break; -case 218: + { (yyval.int32) = ((yyvsp[0].int32) | IMAGE_CEE_CS_CALLCONV_HASTHIS); } +#line 4781 "asmparse.cpp" + break; + + case 219: /* callConv: EXPLICIT_ callConv */ #line 667 "asmparse.y" -{ yyval.int32 = (yypvt[-0].int32 | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS); } break; -case 219: + { (yyval.int32) = ((yyvsp[0].int32) | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS); } +#line 4787 "asmparse.cpp" + break; + + case 220: /* callConv: callKind */ #line 668 "asmparse.y" -{ yyval.int32 = yypvt[-0].int32; } break; -case 220: + { (yyval.int32) = (yyvsp[0].int32); } +#line 4793 "asmparse.cpp" + break; + + case 221: /* callConv: CALLCONV_ '(' int32 ')' */ #line 669 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32; } break; -case 221: + { (yyval.int32) = (yyvsp[-1].int32); } +#line 4799 "asmparse.cpp" + break; + + case 222: /* callKind: %empty */ #line 672 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_DEFAULT; } break; -case 222: + { (yyval.int32) = IMAGE_CEE_CS_CALLCONV_DEFAULT; } +#line 4805 "asmparse.cpp" + break; + + case 223: /* callKind: DEFAULT_ */ #line 673 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_DEFAULT; } break; -case 223: + { (yyval.int32) = IMAGE_CEE_CS_CALLCONV_DEFAULT; } +#line 4811 "asmparse.cpp" + break; + + case 224: /* callKind: VARARG_ */ #line 674 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_VARARG; } break; -case 224: + { (yyval.int32) = IMAGE_CEE_CS_CALLCONV_VARARG; } +#line 4817 "asmparse.cpp" + break; + + case 225: /* callKind: UNMANAGED_ CDECL_ */ #line 675 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_C; } break; -case 225: + { (yyval.int32) = IMAGE_CEE_CS_CALLCONV_C; } +#line 4823 "asmparse.cpp" + break; + + case 226: /* callKind: UNMANAGED_ STDCALL_ */ #line 676 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_STDCALL; } break; -case 226: + { (yyval.int32) = IMAGE_CEE_CS_CALLCONV_STDCALL; } +#line 4829 "asmparse.cpp" + break; + + case 227: /* callKind: UNMANAGED_ THISCALL_ */ #line 677 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_THISCALL; } break; -case 227: + { (yyval.int32) = IMAGE_CEE_CS_CALLCONV_THISCALL; } +#line 4835 "asmparse.cpp" + break; + + case 228: /* callKind: UNMANAGED_ FASTCALL_ */ #line 678 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_FASTCALL; } break; -case 228: + { (yyval.int32) = IMAGE_CEE_CS_CALLCONV_FASTCALL; } +#line 4841 "asmparse.cpp" + break; + + case 229: /* callKind: UNMANAGED_ */ #line 679 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_UNMANAGED; } break; -case 229: + { (yyval.int32) = IMAGE_CEE_CS_CALLCONV_UNMANAGED; } +#line 4847 "asmparse.cpp" + break; + + case 230: /* mdtoken: MDTOKEN_ '(' int32 ')' */ #line 682 "asmparse.y" -{ yyval.token = yypvt[-1].int32; } break; -case 230: + { (yyval.token) = (yyvsp[-1].int32); } +#line 4853 "asmparse.cpp" + break; + + case 231: /* memberRef: methodSpec methodRef */ #line 685 "asmparse.y" -{ yyval.token = yypvt[-0].token; + { (yyval.token) = (yyvsp[0].token); PASM->delArgNameList(PASM->m_firstArgName); PASM->m_firstArgName = parser->m_ANSFirst.POP(); PASM->m_lastArgName = parser->m_ANSLast.POP(); - PASM->SetMemberRefFixup(yypvt[-0].token,iOpcodeLen); } break; -case 231: + PASM->SetMemberRefFixup((yyvsp[0].token),iOpcodeLen); } +#line 4863 "asmparse.cpp" + break; + + case 232: /* memberRef: FIELD_ type typeSpec DCOLON dottedName */ #line 691 "asmparse.y" -{ yypvt[-3].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); - yyval.token = PASM->MakeMemberRef(yypvt[-2].token, yypvt[-0].string, yypvt[-3].binstr); - PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; -case 232: + { (yyvsp[-3].binstr)->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + (yyval.token) = PASM->MakeMemberRef((yyvsp[-2].token), (yyvsp[0].string), (yyvsp[-3].binstr)); + PASM->SetMemberRefFixup((yyval.token),iOpcodeLen); } +#line 4871 "asmparse.cpp" + break; + + case 233: /* memberRef: FIELD_ type dottedName */ #line 695 "asmparse.y" -{ yypvt[-1].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); - yyval.token = PASM->MakeMemberRef(NULL, yypvt[-0].string, yypvt[-1].binstr); - PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; -case 233: + { (yyvsp[-1].binstr)->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + (yyval.token) = PASM->MakeMemberRef(mdTokenNil, (yyvsp[0].string), (yyvsp[-1].binstr)); + PASM->SetMemberRefFixup((yyval.token),iOpcodeLen); } +#line 4879 "asmparse.cpp" + break; + + case 234: /* memberRef: FIELD_ TYPEDEF_F */ #line 698 "asmparse.y" -{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; - PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; -case 234: + { (yyval.token) = (yyvsp[0].tdd)->m_tkTypeSpec; + PASM->SetMemberRefFixup((yyval.token),iOpcodeLen); } +#line 4886 "asmparse.cpp" + break; + + case 235: /* memberRef: FIELD_ TYPEDEF_MR */ #line 700 "asmparse.y" -{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; - PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; -case 235: + { (yyval.token) = (yyvsp[0].tdd)->m_tkTypeSpec; + PASM->SetMemberRefFixup((yyval.token),iOpcodeLen); } +#line 4893 "asmparse.cpp" + break; + + case 236: /* memberRef: mdtoken */ #line 702 "asmparse.y" -{ yyval.token = yypvt[-0].token; - PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; -case 236: + { (yyval.token) = (yyvsp[0].token); + PASM->SetMemberRefFixup((yyval.token),iOpcodeLen); } +#line 4900 "asmparse.cpp" + break; + + case 237: /* eventHead: _EVENT eventAttr typeSpec dottedName */ #line 707 "asmparse.y" -{ PASM->ResetEvent(yypvt[-0].string, yypvt[-1].token, yypvt[-2].eventAttr); } break; -case 237: + { PASM->ResetEvent((yyvsp[0].string), (yyvsp[-1].token), (yyvsp[-2].eventAttr)); } +#line 4906 "asmparse.cpp" + break; + + case 238: /* eventHead: _EVENT eventAttr dottedName */ #line 708 "asmparse.y" -{ PASM->ResetEvent(yypvt[-0].string, mdTypeRefNil, yypvt[-1].eventAttr); } break; -case 238: + { PASM->ResetEvent((yyvsp[0].string), mdTypeRefNil, (yyvsp[-1].eventAttr)); } +#line 4912 "asmparse.cpp" + break; + + case 239: /* eventAttr: %empty */ #line 712 "asmparse.y" -{ yyval.eventAttr = (CorEventAttr) 0; } break; -case 239: + { (yyval.eventAttr) = (CorEventAttr) 0; } +#line 4918 "asmparse.cpp" + break; + + case 240: /* eventAttr: eventAttr RTSPECIALNAME_ */ #line 713 "asmparse.y" -{ yyval.eventAttr = yypvt[-1].eventAttr; } break; -case 240: + { (yyval.eventAttr) = (yyvsp[-1].eventAttr); } +#line 4924 "asmparse.cpp" + break; + + case 241: /* eventAttr: eventAttr SPECIALNAME_ */ #line 714 "asmparse.y" -{ yyval.eventAttr = (CorEventAttr) (yypvt[-1].eventAttr | evSpecialName); } break; -case 243: + { (yyval.eventAttr) = (CorEventAttr) ((yyvsp[-1].eventAttr) | evSpecialName); } +#line 4930 "asmparse.cpp" + break; + + case 244: /* eventDecl: _ADDON methodRef */ #line 721 "asmparse.y" -{ PASM->SetEventMethod(0, yypvt[-0].token); } break; -case 244: + { PASM->SetEventMethod(0, (yyvsp[0].token)); } +#line 4936 "asmparse.cpp" + break; + + case 245: /* eventDecl: _REMOVEON methodRef */ #line 722 "asmparse.y" -{ PASM->SetEventMethod(1, yypvt[-0].token); } break; -case 245: + { PASM->SetEventMethod(1, (yyvsp[0].token)); } +#line 4942 "asmparse.cpp" + break; + + case 246: /* eventDecl: _FIRE methodRef */ #line 723 "asmparse.y" -{ PASM->SetEventMethod(2, yypvt[-0].token); } break; -case 246: + { PASM->SetEventMethod(2, (yyvsp[0].token)); } +#line 4948 "asmparse.cpp" + break; + + case 247: /* eventDecl: _OTHER methodRef */ #line 724 "asmparse.y" -{ PASM->SetEventMethod(3, yypvt[-0].token); } break; -case 251: + { PASM->SetEventMethod(3, (yyvsp[0].token)); } +#line 4954 "asmparse.cpp" + break; + + case 252: /* propHead: _PROPERTY propAttr callConv type dottedName '(' sigArgs0 ')' initOpt */ #line 733 "asmparse.y" -{ PASM->ResetProp(yypvt[-4].string, + { PASM->ResetProp((yyvsp[-4].string), parser->MakeSig((IMAGE_CEE_CS_CALLCONV_PROPERTY | - (yypvt[-6].int32 & IMAGE_CEE_CS_CALLCONV_HASTHIS)),yypvt[-5].binstr,yypvt[-2].binstr), yypvt[-7].propAttr, yypvt[-0].binstr);} break; -case 252: + ((yyvsp[-6].int32) & IMAGE_CEE_CS_CALLCONV_HASTHIS)),(yyvsp[-5].binstr),(yyvsp[-2].binstr)), (yyvsp[-7].propAttr), (yyvsp[0].binstr));} +#line 4962 "asmparse.cpp" + break; + + case 253: /* propAttr: %empty */ #line 738 "asmparse.y" -{ yyval.propAttr = (CorPropertyAttr) 0; } break; -case 253: + { (yyval.propAttr) = (CorPropertyAttr) 0; } +#line 4968 "asmparse.cpp" + break; + + case 254: /* propAttr: propAttr RTSPECIALNAME_ */ #line 739 "asmparse.y" -{ yyval.propAttr = yypvt[-1].propAttr; } break; -case 254: + { (yyval.propAttr) = (yyvsp[-1].propAttr); } +#line 4974 "asmparse.cpp" + break; + + case 255: /* propAttr: propAttr SPECIALNAME_ */ #line 740 "asmparse.y" -{ yyval.propAttr = (CorPropertyAttr) (yypvt[-1].propAttr | prSpecialName); } break; -case 257: + { (yyval.propAttr) = (CorPropertyAttr) ((yyvsp[-1].propAttr) | prSpecialName); } +#line 4980 "asmparse.cpp" + break; + + case 258: /* propDecl: _SET methodRef */ #line 748 "asmparse.y" -{ PASM->SetPropMethod(0, yypvt[-0].token); } break; -case 258: + { PASM->SetPropMethod(0, (yyvsp[0].token)); } +#line 4986 "asmparse.cpp" + break; + + case 259: /* propDecl: _GET methodRef */ #line 749 "asmparse.y" -{ PASM->SetPropMethod(1, yypvt[-0].token); } break; -case 259: + { PASM->SetPropMethod(1, (yyvsp[0].token)); } +#line 4992 "asmparse.cpp" + break; + + case 260: /* propDecl: _OTHER methodRef */ #line 750 "asmparse.y" -{ PASM->SetPropMethod(2, yypvt[-0].token); } break; -case 264: + { PASM->SetPropMethod(2, (yyvsp[0].token)); } +#line 4998 "asmparse.cpp" + break; + + case 265: /* methodHeadPart1: _METHOD */ #line 758 "asmparse.y" -{ PASM->ResetForNextMethod(); + { PASM->ResetForNextMethod(); uMethodBeginLine = PASM->m_ulCurLine; uMethodBeginColumn=PASM->m_ulCurColumn; - } break; -case 265: + } +#line 5007 "asmparse.cpp" + break; + + case 266: /* marshalClause: %empty */ #line 764 "asmparse.y" -{ yyval.binstr = NULL; } break; -case 266: + { (yyval.binstr) = NULL; } +#line 5013 "asmparse.cpp" + break; + + case 267: /* marshalClause: MARSHAL_ '(' marshalBlob ')' */ #line 765 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; } break; -case 267: + { (yyval.binstr) = (yyvsp[-1].binstr); } +#line 5019 "asmparse.cpp" + break; + + case 268: /* marshalBlob: nativeType */ #line 768 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 268: + { (yyval.binstr) = (yyvsp[0].binstr); } +#line 5025 "asmparse.cpp" + break; + + case 269: /* marshalBlob: marshalBlobHead hexbytes '}' */ #line 769 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; } break; -case 269: + { (yyval.binstr) = (yyvsp[-1].binstr); } +#line 5031 "asmparse.cpp" + break; + + case 270: /* marshalBlobHead: '{' */ #line 772 "asmparse.y" -{ bParsingByteArray = TRUE; } break; -case 270: + { bParsingByteArray = TRUE; } +#line 5037 "asmparse.cpp" + break; + + case 271: /* methodHead: methodHeadPart1 methAttr callConv paramAttr type marshalClause methodName typarsClause '(' sigArgs0 ')' implAttr '{' */ #line 776 "asmparse.y" -{ BinStr* sig; - if (yypvt[-5].typarlist == NULL) sig = parser->MakeSig(yypvt[-10].int32, yypvt[-8].binstr, yypvt[-3].binstr); + { BinStr* sig; + if ((yyvsp[-5].typarlist) == NULL) sig = parser->MakeSig((yyvsp[-10].int32), (yyvsp[-8].binstr), (yyvsp[-3].binstr)); else { - FixupTyPars(yypvt[-8].binstr); - sig = parser->MakeSig(yypvt[-10].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC, yypvt[-8].binstr, yypvt[-3].binstr, yypvt[-5].typarlist->Count()); + FixupTyPars((yyvsp[-8].binstr)); + sig = parser->MakeSig((yyvsp[-10].int32) | IMAGE_CEE_CS_CALLCONV_GENERIC, (yyvsp[-8].binstr), (yyvsp[-3].binstr), (yyvsp[-5].typarlist)->Count()); FixupConstraints(); } - PASM->StartMethod(yypvt[-6].string, sig, yypvt[-11].methAttr, yypvt[-7].binstr, yypvt[-9].int32, yypvt[-5].typarlist); + PASM->StartMethod((yyvsp[-6].string), sig, (yyvsp[-11].methAttr), (yyvsp[-7].binstr), (yyvsp[-9].int32), (yyvsp[-5].typarlist)); TyParFixupList.RESET(false); - PASM->SetImplAttr((USHORT)yypvt[-1].implAttr); + PASM->SetImplAttr((USHORT)(yyvsp[-1].implAttr)); PASM->m_pCurMethod->m_ulLines[0] = uMethodBeginLine; PASM->m_pCurMethod->m_ulColumns[0]=uMethodBeginColumn; - } break; -case 271: + } +#line 5055 "asmparse.cpp" + break; + + case 272: /* methAttr: %empty */ #line 791 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) 0; } break; -case 272: + { (yyval.methAttr) = (CorMethodAttr) 0; } +#line 5061 "asmparse.cpp" + break; + + case 273: /* methAttr: methAttr STATIC_ */ #line 792 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdStatic); } break; -case 273: + { (yyval.methAttr) = (CorMethodAttr) ((yyvsp[-1].methAttr) | mdStatic); } +#line 5067 "asmparse.cpp" + break; + + case 274: /* methAttr: methAttr PUBLIC_ */ #line 793 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdPublic); } break; -case 274: + { (yyval.methAttr) = (CorMethodAttr) (((yyvsp[-1].methAttr) & ~mdMemberAccessMask) | mdPublic); } +#line 5073 "asmparse.cpp" + break; + + case 275: /* methAttr: methAttr PRIVATE_ */ #line 794 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdPrivate); } break; -case 275: + { (yyval.methAttr) = (CorMethodAttr) (((yyvsp[-1].methAttr) & ~mdMemberAccessMask) | mdPrivate); } +#line 5079 "asmparse.cpp" + break; + + case 276: /* methAttr: methAttr FAMILY_ */ #line 795 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdFamily); } break; -case 276: + { (yyval.methAttr) = (CorMethodAttr) (((yyvsp[-1].methAttr) & ~mdMemberAccessMask) | mdFamily); } +#line 5085 "asmparse.cpp" + break; + + case 277: /* methAttr: methAttr FINAL_ */ #line 796 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdFinal); } break; -case 277: + { (yyval.methAttr) = (CorMethodAttr) ((yyvsp[-1].methAttr) | mdFinal); } +#line 5091 "asmparse.cpp" + break; + + case 278: /* methAttr: methAttr SPECIALNAME_ */ #line 797 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdSpecialName); } break; -case 278: + { (yyval.methAttr) = (CorMethodAttr) ((yyvsp[-1].methAttr) | mdSpecialName); } +#line 5097 "asmparse.cpp" + break; + + case 279: /* methAttr: methAttr VIRTUAL_ */ #line 798 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdVirtual); } break; -case 279: + { (yyval.methAttr) = (CorMethodAttr) ((yyvsp[-1].methAttr) | mdVirtual); } +#line 5103 "asmparse.cpp" + break; + + case 280: /* methAttr: methAttr STRICT_ */ #line 799 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdCheckAccessOnOverride); } break; -case 280: + { (yyval.methAttr) = (CorMethodAttr) ((yyvsp[-1].methAttr) | mdCheckAccessOnOverride); } +#line 5109 "asmparse.cpp" + break; + + case 281: /* methAttr: methAttr ABSTRACT_ */ #line 800 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdAbstract); } break; -case 281: + { (yyval.methAttr) = (CorMethodAttr) ((yyvsp[-1].methAttr) | mdAbstract); } +#line 5115 "asmparse.cpp" + break; + + case 282: /* methAttr: methAttr ASSEMBLY_ */ #line 801 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdAssem); } break; -case 282: + { (yyval.methAttr) = (CorMethodAttr) (((yyvsp[-1].methAttr) & ~mdMemberAccessMask) | mdAssem); } +#line 5121 "asmparse.cpp" + break; + + case 283: /* methAttr: methAttr FAMANDASSEM_ */ #line 802 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdFamANDAssem); } break; -case 283: + { (yyval.methAttr) = (CorMethodAttr) (((yyvsp[-1].methAttr) & ~mdMemberAccessMask) | mdFamANDAssem); } +#line 5127 "asmparse.cpp" + break; + + case 284: /* methAttr: methAttr FAMORASSEM_ */ #line 803 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdFamORAssem); } break; -case 284: + { (yyval.methAttr) = (CorMethodAttr) (((yyvsp[-1].methAttr) & ~mdMemberAccessMask) | mdFamORAssem); } +#line 5133 "asmparse.cpp" + break; + + case 285: /* methAttr: methAttr PRIVATESCOPE_ */ #line 804 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdPrivateScope); } break; -case 285: + { (yyval.methAttr) = (CorMethodAttr) (((yyvsp[-1].methAttr) & ~mdMemberAccessMask) | mdPrivateScope); } +#line 5139 "asmparse.cpp" + break; + + case 286: /* methAttr: methAttr HIDEBYSIG_ */ #line 805 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdHideBySig); } break; -case 286: + { (yyval.methAttr) = (CorMethodAttr) ((yyvsp[-1].methAttr) | mdHideBySig); } +#line 5145 "asmparse.cpp" + break; + + case 287: /* methAttr: methAttr NEWSLOT_ */ #line 806 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdNewSlot); } break; -case 287: + { (yyval.methAttr) = (CorMethodAttr) ((yyvsp[-1].methAttr) | mdNewSlot); } +#line 5151 "asmparse.cpp" + break; + + case 288: /* methAttr: methAttr RTSPECIALNAME_ */ #line 807 "asmparse.y" -{ yyval.methAttr = yypvt[-1].methAttr; } break; -case 288: + { (yyval.methAttr) = (yyvsp[-1].methAttr); } +#line 5157 "asmparse.cpp" + break; + + case 289: /* methAttr: methAttr UNMANAGEDEXP_ */ #line 808 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdUnmanagedExport); } break; -case 289: + { (yyval.methAttr) = (CorMethodAttr) ((yyvsp[-1].methAttr) | mdUnmanagedExport); } +#line 5163 "asmparse.cpp" + break; + + case 290: /* methAttr: methAttr REQSECOBJ_ */ #line 809 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdRequireSecObject); } break; -case 290: + { (yyval.methAttr) = (CorMethodAttr) ((yyvsp[-1].methAttr) | mdRequireSecObject); } +#line 5169 "asmparse.cpp" + break; + + case 291: /* methAttr: methAttr FLAGS_ '(' int32 ')' */ #line 810 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].int32); } break; -case 291: + { (yyval.methAttr) = (CorMethodAttr) ((yyvsp[-1].int32)); } +#line 5175 "asmparse.cpp" + break; + + case 292: /* methAttr: methAttr PINVOKEIMPL_ '(' compQstring AS_ compQstring pinvAttr ')' */ #line 812 "asmparse.y" -{ PASM->SetPinvoke(yypvt[-4].binstr,0,yypvt[-2].binstr,yypvt[-1].pinvAttr); - yyval.methAttr = (CorMethodAttr) (yypvt[-7].methAttr | mdPinvokeImpl); } break; -case 292: + { PASM->SetPinvoke((yyvsp[-4].binstr),0,(yyvsp[-2].binstr),(yyvsp[-1].pinvAttr)); + (yyval.methAttr) = (CorMethodAttr) ((yyvsp[-7].methAttr) | mdPinvokeImpl); } +#line 5182 "asmparse.cpp" + break; + + case 293: /* methAttr: methAttr PINVOKEIMPL_ '(' compQstring pinvAttr ')' */ #line 815 "asmparse.y" -{ PASM->SetPinvoke(yypvt[-2].binstr,0,NULL,yypvt[-1].pinvAttr); - yyval.methAttr = (CorMethodAttr) (yypvt[-5].methAttr | mdPinvokeImpl); } break; -case 293: + { PASM->SetPinvoke((yyvsp[-2].binstr),0,NULL,(yyvsp[-1].pinvAttr)); + (yyval.methAttr) = (CorMethodAttr) ((yyvsp[-5].methAttr) | mdPinvokeImpl); } +#line 5189 "asmparse.cpp" + break; + + case 294: /* methAttr: methAttr PINVOKEIMPL_ '(' pinvAttr ')' */ #line 818 "asmparse.y" -{ PASM->SetPinvoke(new BinStr(),0,NULL,yypvt[-1].pinvAttr); - yyval.methAttr = (CorMethodAttr) (yypvt[-4].methAttr | mdPinvokeImpl); } break; -case 294: + { PASM->SetPinvoke(new BinStr(),0,NULL,(yyvsp[-1].pinvAttr)); + (yyval.methAttr) = (CorMethodAttr) ((yyvsp[-4].methAttr) | mdPinvokeImpl); } +#line 5196 "asmparse.cpp" + break; + + case 295: /* pinvAttr: %empty */ #line 822 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) 0; } break; -case 295: + { (yyval.pinvAttr) = (CorPinvokeMap) 0; } +#line 5202 "asmparse.cpp" + break; + + case 296: /* pinvAttr: pinvAttr NOMANGLE_ */ #line 823 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmNoMangle); } break; -case 296: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-1].pinvAttr) | pmNoMangle); } +#line 5208 "asmparse.cpp" + break; + + case 297: /* pinvAttr: pinvAttr ANSI_ */ #line 824 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCharSetAnsi); } break; -case 297: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-1].pinvAttr) | pmCharSetAnsi); } +#line 5214 "asmparse.cpp" + break; + + case 298: /* pinvAttr: pinvAttr UNICODE_ */ #line 825 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCharSetUnicode); } break; -case 298: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-1].pinvAttr) | pmCharSetUnicode); } +#line 5220 "asmparse.cpp" + break; + + case 299: /* pinvAttr: pinvAttr AUTOCHAR_ */ #line 826 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCharSetAuto); } break; -case 299: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-1].pinvAttr) | pmCharSetAuto); } +#line 5226 "asmparse.cpp" + break; + + case 300: /* pinvAttr: pinvAttr LASTERR_ */ #line 827 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmSupportsLastError); } break; -case 300: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-1].pinvAttr) | pmSupportsLastError); } +#line 5232 "asmparse.cpp" + break; + + case 301: /* pinvAttr: pinvAttr WINAPI_ */ #line 828 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvWinapi); } break; -case 301: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-1].pinvAttr) | pmCallConvWinapi); } +#line 5238 "asmparse.cpp" + break; + + case 302: /* pinvAttr: pinvAttr CDECL_ */ #line 829 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvCdecl); } break; -case 302: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-1].pinvAttr) | pmCallConvCdecl); } +#line 5244 "asmparse.cpp" + break; + + case 303: /* pinvAttr: pinvAttr STDCALL_ */ #line 830 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvStdcall); } break; -case 303: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-1].pinvAttr) | pmCallConvStdcall); } +#line 5250 "asmparse.cpp" + break; + + case 304: /* pinvAttr: pinvAttr THISCALL_ */ #line 831 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvThiscall); } break; -case 304: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-1].pinvAttr) | pmCallConvThiscall); } +#line 5256 "asmparse.cpp" + break; + + case 305: /* pinvAttr: pinvAttr FASTCALL_ */ #line 832 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvFastcall); } break; -case 305: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-1].pinvAttr) | pmCallConvFastcall); } +#line 5262 "asmparse.cpp" + break; + + case 306: /* pinvAttr: pinvAttr BESTFIT_ ':' ON_ */ #line 833 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmBestFitEnabled); } break; -case 306: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-3].pinvAttr) | pmBestFitEnabled); } +#line 5268 "asmparse.cpp" + break; + + case 307: /* pinvAttr: pinvAttr BESTFIT_ ':' OFF_ */ #line 834 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmBestFitDisabled); } break; -case 307: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-3].pinvAttr) | pmBestFitDisabled); } +#line 5274 "asmparse.cpp" + break; + + case 308: /* pinvAttr: pinvAttr CHARMAPERROR_ ':' ON_ */ #line 835 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmThrowOnUnmappableCharEnabled); } break; -case 308: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-3].pinvAttr) | pmThrowOnUnmappableCharEnabled); } +#line 5280 "asmparse.cpp" + break; + + case 309: /* pinvAttr: pinvAttr CHARMAPERROR_ ':' OFF_ */ #line 836 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmThrowOnUnmappableCharDisabled); } break; -case 309: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-3].pinvAttr) | pmThrowOnUnmappableCharDisabled); } +#line 5286 "asmparse.cpp" + break; + + case 310: /* pinvAttr: pinvAttr FLAGS_ '(' int32 ')' */ #line 837 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].int32); } break; -case 310: + { (yyval.pinvAttr) = (CorPinvokeMap) ((yyvsp[-1].int32)); } +#line 5292 "asmparse.cpp" + break; + + case 311: /* methodName: _CTOR */ #line 840 "asmparse.y" -{ yyval.string = newString(COR_CTOR_METHOD_NAME); } break; -case 311: + { (yyval.string) = newString(COR_CTOR_METHOD_NAME); } +#line 5298 "asmparse.cpp" + break; + + case 312: /* methodName: _CCTOR */ #line 841 "asmparse.y" -{ yyval.string = newString(COR_CCTOR_METHOD_NAME); } break; -case 312: + { (yyval.string) = newString(COR_CCTOR_METHOD_NAME); } +#line 5304 "asmparse.cpp" + break; + + case 313: /* methodName: dottedName */ #line 842 "asmparse.y" -{ yyval.string = yypvt[-0].string; } break; -case 313: + { (yyval.string) = (yyvsp[0].string); } +#line 5310 "asmparse.cpp" + break; + + case 314: /* paramAttr: %empty */ #line 845 "asmparse.y" -{ yyval.int32 = 0; } break; -case 314: + { (yyval.int32) = 0; } +#line 5316 "asmparse.cpp" + break; + + case 315: /* paramAttr: paramAttr '[' IN_ ']' */ #line 846 "asmparse.y" -{ yyval.int32 = yypvt[-3].int32 | pdIn; } break; -case 315: + { (yyval.int32) = (yyvsp[-3].int32) | pdIn; } +#line 5322 "asmparse.cpp" + break; + + case 316: /* paramAttr: paramAttr '[' OUT_ ']' */ #line 847 "asmparse.y" -{ yyval.int32 = yypvt[-3].int32 | pdOut; } break; -case 316: + { (yyval.int32) = (yyvsp[-3].int32) | pdOut; } +#line 5328 "asmparse.cpp" + break; + + case 317: /* paramAttr: paramAttr '[' OPT_ ']' */ #line 848 "asmparse.y" -{ yyval.int32 = yypvt[-3].int32 | pdOptional; } break; -case 317: + { (yyval.int32) = (yyvsp[-3].int32) | pdOptional; } +#line 5334 "asmparse.cpp" + break; + + case 318: /* paramAttr: paramAttr '[' int32 ']' */ #line 849 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 + 1; } break; -case 318: + { (yyval.int32) = (yyvsp[-1].int32) + 1; } +#line 5340 "asmparse.cpp" + break; + + case 319: /* implAttr: %empty */ #line 852 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (miIL | miManaged); } break; -case 319: + { (yyval.implAttr) = (CorMethodImpl) (miIL | miManaged); } +#line 5346 "asmparse.cpp" + break; + + case 320: /* implAttr: implAttr NATIVE_ */ #line 853 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFF4) | miNative); } break; -case 320: + { (yyval.implAttr) = (CorMethodImpl) (((yyvsp[-1].implAttr) & 0xFFF4) | miNative); } +#line 5352 "asmparse.cpp" + break; + + case 321: /* implAttr: implAttr CIL_ */ #line 854 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFF4) | miIL); } break; -case 321: + { (yyval.implAttr) = (CorMethodImpl) (((yyvsp[-1].implAttr) & 0xFFF4) | miIL); } +#line 5358 "asmparse.cpp" + break; + + case 322: /* implAttr: implAttr OPTIL_ */ #line 855 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFF4) | miOPTIL); } break; -case 322: + { (yyval.implAttr) = (CorMethodImpl) (((yyvsp[-1].implAttr) & 0xFFF4) | miOPTIL); } +#line 5364 "asmparse.cpp" + break; + + case 323: /* implAttr: implAttr MANAGED_ */ #line 856 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFFB) | miManaged); } break; -case 323: + { (yyval.implAttr) = (CorMethodImpl) (((yyvsp[-1].implAttr) & 0xFFFB) | miManaged); } +#line 5370 "asmparse.cpp" + break; + + case 324: /* implAttr: implAttr UNMANAGED_ */ #line 857 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFFB) | miUnmanaged); } break; -case 324: + { (yyval.implAttr) = (CorMethodImpl) (((yyvsp[-1].implAttr) & 0xFFFB) | miUnmanaged); } +#line 5376 "asmparse.cpp" + break; + + case 325: /* implAttr: implAttr FORWARDREF_ */ #line 858 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miForwardRef); } break; -case 325: + { (yyval.implAttr) = (CorMethodImpl) ((yyvsp[-1].implAttr) | miForwardRef); } +#line 5382 "asmparse.cpp" + break; + + case 326: /* implAttr: implAttr PRESERVESIG_ */ #line 859 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miPreserveSig); } break; -case 326: + { (yyval.implAttr) = (CorMethodImpl) ((yyvsp[-1].implAttr) | miPreserveSig); } +#line 5388 "asmparse.cpp" + break; + + case 327: /* implAttr: implAttr RUNTIME_ */ #line 860 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miRuntime); } break; -case 327: + { (yyval.implAttr) = (CorMethodImpl) ((yyvsp[-1].implAttr) | miRuntime); } +#line 5394 "asmparse.cpp" + break; + + case 328: /* implAttr: implAttr INTERNALCALL_ */ #line 861 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miInternalCall); } break; -case 328: + { (yyval.implAttr) = (CorMethodImpl) ((yyvsp[-1].implAttr) | miInternalCall); } +#line 5400 "asmparse.cpp" + break; + + case 329: /* implAttr: implAttr SYNCHRONIZED_ */ #line 862 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miSynchronized); } break; -case 329: + { (yyval.implAttr) = (CorMethodImpl) ((yyvsp[-1].implAttr) | miSynchronized); } +#line 5406 "asmparse.cpp" + break; + + case 330: /* implAttr: implAttr NOINLINING_ */ #line 863 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miNoInlining); } break; -case 330: + { (yyval.implAttr) = (CorMethodImpl) ((yyvsp[-1].implAttr) | miNoInlining); } +#line 5412 "asmparse.cpp" + break; + + case 331: /* implAttr: implAttr AGGRESSIVEINLINING_ */ #line 864 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miAggressiveInlining); } break; -case 331: + { (yyval.implAttr) = (CorMethodImpl) ((yyvsp[-1].implAttr) | miAggressiveInlining); } +#line 5418 "asmparse.cpp" + break; + + case 332: /* implAttr: implAttr NOOPTIMIZATION_ */ #line 865 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miNoOptimization); } break; -case 332: + { (yyval.implAttr) = (CorMethodImpl) ((yyvsp[-1].implAttr) | miNoOptimization); } +#line 5424 "asmparse.cpp" + break; + + case 333: /* implAttr: implAttr AGGRESSIVEOPTIMIZATION_ */ #line 866 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miAggressiveOptimization); } break; -case 333: + { (yyval.implAttr) = (CorMethodImpl) ((yyvsp[-1].implAttr) | miAggressiveOptimization); } +#line 5430 "asmparse.cpp" + break; + + case 334: /* implAttr: implAttr FLAGS_ '(' int32 ')' */ #line 867 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].int32); } break; -case 334: + { (yyval.implAttr) = (CorMethodImpl) ((yyvsp[-1].int32)); } +#line 5436 "asmparse.cpp" + break; + + case 335: /* localsHead: _LOCALS */ #line 870 "asmparse.y" -{ PASM->delArgNameList(PASM->m_firstArgName); PASM->m_firstArgName = NULL;PASM->m_lastArgName = NULL; - } break; -case 337: + { PASM->delArgNameList(PASM->m_firstArgName); PASM->m_firstArgName = NULL;PASM->m_lastArgName = NULL; + } +#line 5443 "asmparse.cpp" + break; + + case 338: /* methodDecl: _EMITBYTE int32 */ #line 878 "asmparse.y" -{ PASM->EmitByte(yypvt[-0].int32); } break; -case 338: + { PASM->EmitByte((yyvsp[0].int32)); } +#line 5449 "asmparse.cpp" + break; + + case 339: /* methodDecl: sehBlock */ #line 879 "asmparse.y" -{ delete PASM->m_SEHD; PASM->m_SEHD = PASM->m_SEHDstack.POP(); } break; -case 339: + { delete PASM->m_SEHD; PASM->m_SEHD = PASM->m_SEHDstack.POP(); } +#line 5455 "asmparse.cpp" + break; + + case 340: /* methodDecl: _MAXSTACK int32 */ #line 880 "asmparse.y" -{ PASM->EmitMaxStack(yypvt[-0].int32); } break; -case 340: + { PASM->EmitMaxStack((yyvsp[0].int32)); } +#line 5461 "asmparse.cpp" + break; + + case 341: /* methodDecl: localsHead '(' sigArgs0 ')' */ #line 881 "asmparse.y" -{ PASM->EmitLocals(parser->MakeSig(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, 0, yypvt[-1].binstr)); - } break; -case 341: + { PASM->EmitLocals(parser->MakeSig(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, 0, (yyvsp[-1].binstr))); + } +#line 5468 "asmparse.cpp" + break; + + case 342: /* methodDecl: localsHead INIT_ '(' sigArgs0 ')' */ #line 883 "asmparse.y" -{ PASM->EmitZeroInit(); - PASM->EmitLocals(parser->MakeSig(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, 0, yypvt[-1].binstr)); - } break; -case 342: + { PASM->EmitZeroInit(); + PASM->EmitLocals(parser->MakeSig(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, 0, (yyvsp[-1].binstr))); + } +#line 5476 "asmparse.cpp" + break; + + case 343: /* methodDecl: _ENTRYPOINT */ #line 886 "asmparse.y" -{ PASM->EmitEntryPoint(); } break; -case 343: + { PASM->EmitEntryPoint(); } +#line 5482 "asmparse.cpp" + break; + + case 344: /* methodDecl: _ZEROINIT */ #line 887 "asmparse.y" -{ PASM->EmitZeroInit(); } break; -case 346: + { PASM->EmitZeroInit(); } +#line 5488 "asmparse.cpp" + break; + + case 347: /* methodDecl: id ':' */ #line 890 "asmparse.y" -{ PASM->AddLabel(PASM->m_CurPC,yypvt[-1].string); /*PASM->EmitLabel($1);*/ } break; -case 352: + { PASM->AddLabel(PASM->m_CurPC,(yyvsp[-1].string)); /*PASM->EmitLabel($1);*/ } +#line 5494 "asmparse.cpp" + break; + + case 353: /* methodDecl: _EXPORT '[' int32 ']' */ #line 896 "asmparse.y" -{ if(PASM->m_pCurMethod->m_dwExportOrdinal == 0xFFFFFFFF) + { if(PASM->m_pCurMethod->m_dwExportOrdinal == 0xFFFFFFFF) { - PASM->m_pCurMethod->m_dwExportOrdinal = yypvt[-1].int32; + PASM->m_pCurMethod->m_dwExportOrdinal = (yyvsp[-1].int32); PASM->m_pCurMethod->m_szExportAlias = NULL; if(PASM->m_pCurMethod->m_wVTEntry == 0) PASM->m_pCurMethod->m_wVTEntry = 1; - if(PASM->m_pCurMethod->m_wVTSlot == 0) PASM->m_pCurMethod->m_wVTSlot = (WORD)(yypvt[-1].int32 + 0x8000); + if(PASM->m_pCurMethod->m_wVTSlot == 0) PASM->m_pCurMethod->m_wVTSlot = (WORD)((yyvsp[-1].int32) + 0x8000); } else PASM->report->warn("Duplicate .export directive, ignored\n"); - } break; -case 353: + } +#line 5509 "asmparse.cpp" + break; + + case 354: /* methodDecl: _EXPORT '[' int32 ']' AS_ id */ #line 906 "asmparse.y" -{ if(PASM->m_pCurMethod->m_dwExportOrdinal == 0xFFFFFFFF) + { if(PASM->m_pCurMethod->m_dwExportOrdinal == 0xFFFFFFFF) { - PASM->m_pCurMethod->m_dwExportOrdinal = yypvt[-3].int32; - PASM->m_pCurMethod->m_szExportAlias = yypvt[-0].string; + PASM->m_pCurMethod->m_dwExportOrdinal = (yyvsp[-3].int32); + PASM->m_pCurMethod->m_szExportAlias = (yyvsp[0].string); if(PASM->m_pCurMethod->m_wVTEntry == 0) PASM->m_pCurMethod->m_wVTEntry = 1; - if(PASM->m_pCurMethod->m_wVTSlot == 0) PASM->m_pCurMethod->m_wVTSlot = (WORD)(yypvt[-3].int32 + 0x8000); + if(PASM->m_pCurMethod->m_wVTSlot == 0) PASM->m_pCurMethod->m_wVTSlot = (WORD)((yyvsp[-3].int32) + 0x8000); } else PASM->report->warn("Duplicate .export directive, ignored\n"); - } break; -case 354: + } +#line 5524 "asmparse.cpp" + break; + + case 355: /* methodDecl: _VTENTRY int32 ':' int32 */ #line 916 "asmparse.y" -{ PASM->m_pCurMethod->m_wVTEntry = (WORD)yypvt[-2].int32; - PASM->m_pCurMethod->m_wVTSlot = (WORD)yypvt[-0].int32; } break; -case 355: + { PASM->m_pCurMethod->m_wVTEntry = (WORD)(yyvsp[-2].int32); + PASM->m_pCurMethod->m_wVTSlot = (WORD)(yyvsp[0].int32); } +#line 5531 "asmparse.cpp" + break; + + case 356: /* methodDecl: _OVERRIDE typeSpec DCOLON methodName */ #line 919 "asmparse.y" -{ PASM->AddMethodImpl(yypvt[-2].token,yypvt[-0].string,NULL,NULL,NULL,NULL); } break; -case 356: + { PASM->AddMethodImpl((yyvsp[-2].token),(yyvsp[0].string),NULL,mdTokenNil,NULL,NULL); } +#line 5537 "asmparse.cpp" + break; + + case 357: /* methodDecl: _OVERRIDE METHOD_ callConv type typeSpec DCOLON methodName genArity '(' sigArgs0 ')' */ #line 922 "asmparse.y" -{ PASM->AddMethodImpl(yypvt[-6].token,yypvt[-4].string, - (yypvt[-3].int32==0 ? parser->MakeSig(yypvt[-8].int32,yypvt[-7].binstr,yypvt[-1].binstr) : - parser->MakeSig(yypvt[-8].int32| IMAGE_CEE_CS_CALLCONV_GENERIC,yypvt[-7].binstr,yypvt[-1].binstr,yypvt[-3].int32)) - ,NULL,NULL,NULL); + { PASM->AddMethodImpl((yyvsp[-6].token),(yyvsp[-4].string), + ((yyvsp[-3].int32)==0 ? parser->MakeSig((yyvsp[-8].int32),(yyvsp[-7].binstr),(yyvsp[-1].binstr)) : + parser->MakeSig((yyvsp[-8].int32)| IMAGE_CEE_CS_CALLCONV_GENERIC,(yyvsp[-7].binstr),(yyvsp[-1].binstr),(yyvsp[-3].int32))) + ,mdTokenNil,NULL,NULL); PASM->ResetArgNameList(); - } break; -case 358: + } +#line 5548 "asmparse.cpp" + break; + + case 359: /* methodDecl: _PARAM TYPE_ '[' int32 ']' */ #line 929 "asmparse.y" -{ if((yypvt[-1].int32 > 0) && (yypvt[-1].int32 <= (int)PASM->m_pCurMethod->m_NumTyPars)) - PASM->m_pCustomDescrList = PASM->m_pCurMethod->m_TyPars[yypvt[-1].int32-1].CAList(); + { if(((yyvsp[-1].int32) > 0) && ((yyvsp[-1].int32) <= (int)PASM->m_pCurMethod->m_NumTyPars)) + PASM->m_pCustomDescrList = PASM->m_pCurMethod->m_TyPars[(yyvsp[-1].int32)-1].CAList(); else PASM->report->error("Type parameter index out of range\n"); - } break; -case 359: + } +#line 5558 "asmparse.cpp" + break; + + case 360: /* methodDecl: _PARAM TYPE_ dottedName */ #line 934 "asmparse.y" -{ int n = PASM->m_pCurMethod->FindTyPar(yypvt[-0].string); + { int n = PASM->m_pCurMethod->FindTyPar((yyvsp[0].string)); if(n >= 0) PASM->m_pCustomDescrList = PASM->m_pCurMethod->m_TyPars[n].CAList(); else - PASM->report->error("Type parameter '%s' undefined\n",yypvt[-0].string); - } break; -case 360: + PASM->report->error("Type parameter '%s' undefined\n",(yyvsp[0].string)); + } +#line 5569 "asmparse.cpp" + break; + + case 361: /* methodDecl: _PARAM CONSTRAINT_ '[' int32 ']' ',' typeSpec */ #line 940 "asmparse.y" -{ PASM->m_pCurMethod->AddGenericParamConstraint(yypvt[-3].int32, 0, yypvt[-0].token); } break; -case 361: + { PASM->m_pCurMethod->AddGenericParamConstraint((yyvsp[-3].int32), 0, (yyvsp[0].token)); } +#line 5575 "asmparse.cpp" + break; + + case 362: /* methodDecl: _PARAM CONSTRAINT_ dottedName ',' typeSpec */ #line 941 "asmparse.y" -{ PASM->m_pCurMethod->AddGenericParamConstraint(0, yypvt[-2].string, yypvt[-0].token); } break; -case 362: + { PASM->m_pCurMethod->AddGenericParamConstraint(0, (yyvsp[-2].string), (yyvsp[0].token)); } +#line 5581 "asmparse.cpp" + break; + + case 363: /* methodDecl: _PARAM '[' int32 ']' initOpt */ #line 944 "asmparse.y" -{ if( yypvt[-2].int32 ) { - ARG_NAME_LIST* pAN=PASM->findArg(PASM->m_pCurMethod->m_firstArgName, yypvt[-2].int32 - 1); + { if( (yyvsp[-2].int32) ) { + ARG_NAME_LIST* pAN=PASM->findArg(PASM->m_pCurMethod->m_firstArgName, (yyvsp[-2].int32) - 1); if(pAN) { PASM->m_pCustomDescrList = &(pAN->CustDList); - pAN->pValue = yypvt[-0].binstr; + pAN->pValue = (yyvsp[0].binstr); } else { PASM->m_pCustomDescrList = NULL; - if(yypvt[-0].binstr) delete yypvt[-0].binstr; + if((yyvsp[0].binstr)) delete (yyvsp[0].binstr); } } else { PASM->m_pCustomDescrList = &(PASM->m_pCurMethod->m_RetCustDList); - PASM->m_pCurMethod->m_pRetValue = yypvt[-0].binstr; + PASM->m_pCurMethod->m_pRetValue = (yyvsp[0].binstr); } PASM->m_tkCurrentCVOwner = 0; - } break; -case 363: + } +#line 5604 "asmparse.cpp" + break; + + case 364: /* scopeBlock: scopeOpen methodDecls '}' */ #line 964 "asmparse.y" -{ PASM->m_pCurMethod->CloseScope(); } break; -case 364: + { PASM->m_pCurMethod->CloseScope(); } +#line 5610 "asmparse.cpp" + break; + + case 365: /* scopeOpen: '{' */ #line 967 "asmparse.y" -{ PASM->m_pCurMethod->OpenScope(); } break; -case 368: + { PASM->m_pCurMethod->OpenScope(); } +#line 5616 "asmparse.cpp" + break; + + case 369: /* tryBlock: tryHead scopeBlock */ #line 978 "asmparse.y" -{ PASM->m_SEHD->tryTo = PASM->m_CurPC; } break; -case 369: + { PASM->m_SEHD->tryTo = PASM->m_CurPC; } +#line 5622 "asmparse.cpp" + break; + + case 370: /* tryBlock: tryHead id TO_ id */ #line 979 "asmparse.y" -{ PASM->SetTryLabels(yypvt[-2].string, yypvt[-0].string); } break; -case 370: + { PASM->SetTryLabels((yyvsp[-2].string), (yyvsp[0].string)); } +#line 5628 "asmparse.cpp" + break; + + case 371: /* tryBlock: tryHead int32 TO_ int32 */ #line 980 "asmparse.y" -{ if(PASM->m_SEHD) {PASM->m_SEHD->tryFrom = yypvt[-2].int32; - PASM->m_SEHD->tryTo = yypvt[-0].int32;} } break; -case 371: + { if(PASM->m_SEHD) {PASM->m_SEHD->tryFrom = (yyvsp[-2].int32); + PASM->m_SEHD->tryTo = (yyvsp[0].int32);} } +#line 5635 "asmparse.cpp" + break; + + case 372: /* tryHead: _TRY */ #line 984 "asmparse.y" -{ PASM->NewSEHDescriptor(); - PASM->m_SEHD->tryFrom = PASM->m_CurPC; } break; -case 372: + { PASM->NewSEHDescriptor(); + PASM->m_SEHD->tryFrom = PASM->m_CurPC; } +#line 5642 "asmparse.cpp" + break; + + case 373: /* sehClause: catchClause handlerBlock */ #line 989 "asmparse.y" -{ PASM->EmitTry(); } break; -case 373: + { PASM->EmitTry(); } +#line 5648 "asmparse.cpp" + break; + + case 374: /* sehClause: filterClause handlerBlock */ #line 990 "asmparse.y" -{ PASM->EmitTry(); } break; -case 374: + { PASM->EmitTry(); } +#line 5654 "asmparse.cpp" + break; + + case 375: /* sehClause: finallyClause handlerBlock */ #line 991 "asmparse.y" -{ PASM->EmitTry(); } break; -case 375: + { PASM->EmitTry(); } +#line 5660 "asmparse.cpp" + break; + + case 376: /* sehClause: faultClause handlerBlock */ #line 992 "asmparse.y" -{ PASM->EmitTry(); } break; -case 376: + { PASM->EmitTry(); } +#line 5666 "asmparse.cpp" + break; + + case 377: /* filterClause: filterHead scopeBlock */ #line 996 "asmparse.y" -{ PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; -case 377: + { PASM->m_SEHD->sehHandler = PASM->m_CurPC; } +#line 5672 "asmparse.cpp" + break; + + case 378: /* filterClause: filterHead id */ #line 997 "asmparse.y" -{ PASM->SetFilterLabel(yypvt[-0].string); - PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; -case 378: + { PASM->SetFilterLabel((yyvsp[0].string)); + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } +#line 5679 "asmparse.cpp" + break; + + case 379: /* filterClause: filterHead int32 */ #line 999 "asmparse.y" -{ PASM->m_SEHD->sehFilter = yypvt[-0].int32; - PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; -case 379: + { PASM->m_SEHD->sehFilter = (yyvsp[0].int32); + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } +#line 5686 "asmparse.cpp" + break; + + case 380: /* filterHead: FILTER_ */ #line 1003 "asmparse.y" -{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FILTER; - PASM->m_SEHD->sehFilter = PASM->m_CurPC; } break; -case 380: + { PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FILTER; + PASM->m_SEHD->sehFilter = PASM->m_CurPC; } +#line 5693 "asmparse.cpp" + break; + + case 381: /* catchClause: CATCH_ typeSpec */ #line 1007 "asmparse.y" -{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_NONE; - PASM->SetCatchClass(yypvt[-0].token); - PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; -case 381: + { PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_NONE; + PASM->SetCatchClass((yyvsp[0].token)); + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } +#line 5701 "asmparse.cpp" + break; + + case 382: /* finallyClause: FINALLY_ */ #line 1012 "asmparse.y" -{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FINALLY; - PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; -case 382: + { PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FINALLY; + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } +#line 5708 "asmparse.cpp" + break; + + case 383: /* faultClause: FAULT_ */ #line 1016 "asmparse.y" -{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FAULT; - PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; -case 383: + { PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FAULT; + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } +#line 5715 "asmparse.cpp" + break; + + case 384: /* handlerBlock: scopeBlock */ #line 1020 "asmparse.y" -{ PASM->m_SEHD->sehHandlerTo = PASM->m_CurPC; } break; -case 384: + { PASM->m_SEHD->sehHandlerTo = PASM->m_CurPC; } +#line 5721 "asmparse.cpp" + break; + + case 385: /* handlerBlock: HANDLER_ id TO_ id */ #line 1021 "asmparse.y" -{ PASM->SetHandlerLabels(yypvt[-2].string, yypvt[-0].string); } break; -case 385: + { PASM->SetHandlerLabels((yyvsp[-2].string), (yyvsp[0].string)); } +#line 5727 "asmparse.cpp" + break; + + case 386: /* handlerBlock: HANDLER_ int32 TO_ int32 */ #line 1022 "asmparse.y" -{ PASM->m_SEHD->sehHandler = yypvt[-2].int32; - PASM->m_SEHD->sehHandlerTo = yypvt[-0].int32; } break; -case 387: + { PASM->m_SEHD->sehHandler = (yyvsp[-2].int32); + PASM->m_SEHD->sehHandlerTo = (yyvsp[0].int32); } +#line 5734 "asmparse.cpp" + break; + + case 388: /* ddHead: _DATA tls id '=' */ #line 1030 "asmparse.y" -{ PASM->EmitDataLabel(yypvt[-1].string); } break; -case 389: + { PASM->EmitDataLabel((yyvsp[-1].string)); } +#line 5740 "asmparse.cpp" + break; + + case 390: /* tls: %empty */ #line 1034 "asmparse.y" -{ PASM->SetDataSection(); } break; -case 390: + { PASM->SetDataSection(); } +#line 5746 "asmparse.cpp" + break; + + case 391: /* tls: TLS_ */ #line 1035 "asmparse.y" -{ PASM->SetTLSSection(); } break; -case 391: + { PASM->SetTLSSection(); } +#line 5752 "asmparse.cpp" + break; + + case 392: /* tls: CIL_ */ #line 1036 "asmparse.y" -{ PASM->SetILSection(); } break; -case 396: + { PASM->SetILSection(); } +#line 5758 "asmparse.cpp" + break; + + case 397: /* ddItemCount: %empty */ #line 1047 "asmparse.y" -{ yyval.int32 = 1; } break; -case 397: + { (yyval.int32) = 1; } +#line 5764 "asmparse.cpp" + break; + + case 398: /* ddItemCount: '[' int32 ']' */ #line 1048 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32; - if(yypvt[-1].int32 <= 0) { PASM->report->error("Illegal item count: %d\n",yypvt[-1].int32); - if(!PASM->OnErrGo) yyval.int32 = 1; }} break; -case 398: + { (yyval.int32) = (yyvsp[-1].int32); + if((yyvsp[-1].int32) <= 0) { PASM->report->error("Illegal item count: %d\n",(yyvsp[-1].int32)); + if(!PASM->OnErrGo) (yyval.int32) = 1; }} +#line 5772 "asmparse.cpp" + break; + + case 399: /* ddItem: CHAR_ '*' '(' compQstring ')' */ #line 1053 "asmparse.y" -{ PASM->EmitDataString(yypvt[-1].binstr); } break; -case 399: + { PASM->EmitDataString((yyvsp[-1].binstr)); } +#line 5778 "asmparse.cpp" + break; + + case 400: /* ddItem: '&' '(' id ')' */ #line 1054 "asmparse.y" -{ PASM->EmitDD(yypvt[-1].string); } break; -case 400: + { PASM->EmitDD((yyvsp[-1].string)); } +#line 5784 "asmparse.cpp" + break; + + case 401: /* ddItem: bytearrayhead bytes ')' */ #line 1055 "asmparse.y" -{ PASM->EmitData(yypvt[-1].binstr->ptr(),yypvt[-1].binstr->length()); } break; -case 401: + { PASM->EmitData((yyvsp[-1].binstr)->ptr(),(yyvsp[-1].binstr)->length()); } +#line 5790 "asmparse.cpp" + break; + + case 402: /* ddItem: FLOAT32_ '(' float64 ')' ddItemCount */ #line 1057 "asmparse.y" -{ float f = (float) (*yypvt[-2].float64); float* p = new (nothrow) float[yypvt[-0].int32]; + { float f = (float) (*(yyvsp[-2].float64)); float* p = new (nothrow) float[(yyvsp[0].int32)]; if(p != NULL) { - for(int i=0; i < yypvt[-0].int32; i++) p[i] = f; - PASM->EmitData(p, sizeof(float)*yypvt[-0].int32); delete yypvt[-2].float64; delete [] p; + for(int i=0; i < (yyvsp[0].int32); i++) p[i] = f; + PASM->EmitData(p, sizeof(float)*(yyvsp[0].int32)); delete (yyvsp[-2].float64); delete [] p; } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(float)*yypvt[-0].int32); } break; -case 402: + sizeof(float)*(yyvsp[0].int32)); } +#line 5801 "asmparse.cpp" + break; + + case 403: /* ddItem: FLOAT64_ '(' float64 ')' ddItemCount */ #line 1064 "asmparse.y" -{ double* p = new (nothrow) double[yypvt[-0].int32]; + { double* p = new (nothrow) double[(yyvsp[0].int32)]; if(p != NULL) { - for(int i=0; iEmitData(p, sizeof(double)*yypvt[-0].int32); delete yypvt[-2].float64; delete [] p; + for(int i=0; i<(yyvsp[0].int32); i++) p[i] = *((yyvsp[-2].float64)); + PASM->EmitData(p, sizeof(double)*(yyvsp[0].int32)); delete (yyvsp[-2].float64); delete [] p; } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(double)*yypvt[-0].int32); } break; -case 403: + sizeof(double)*(yyvsp[0].int32)); } +#line 5812 "asmparse.cpp" + break; + + case 404: /* ddItem: INT64_ '(' int64 ')' ddItemCount */ #line 1071 "asmparse.y" -{ __int64* p = new (nothrow) __int64[yypvt[-0].int32]; + { int64_t* p = new (nothrow) int64_t[(yyvsp[0].int32)]; if(p != NULL) { - for(int i=0; iEmitData(p, sizeof(__int64)*yypvt[-0].int32); delete yypvt[-2].int64; delete [] p; + for(int i=0; i<(yyvsp[0].int32); i++) p[i] = *((yyvsp[-2].int64)); + PASM->EmitData(p, sizeof(int64_t)*(yyvsp[0].int32)); delete (yyvsp[-2].int64); delete [] p; } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(__int64)*yypvt[-0].int32); } break; -case 404: + sizeof(int64_t)*(yyvsp[0].int32)); } +#line 5823 "asmparse.cpp" + break; + + case 405: /* ddItem: INT32_ '(' int32 ')' ddItemCount */ #line 1078 "asmparse.y" -{ __int32* p = new (nothrow) __int32[yypvt[-0].int32]; + { int32_t* p = new (nothrow) int32_t[(yyvsp[0].int32)]; if(p != NULL) { - for(int i=0; iEmitData(p, sizeof(__int32)*yypvt[-0].int32); delete [] p; + for(int i=0; i<(yyvsp[0].int32); i++) p[i] = (yyvsp[-2].int32); + PASM->EmitData(p, sizeof(int32_t)*(yyvsp[0].int32)); delete [] p; } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(__int32)*yypvt[-0].int32); } break; -case 405: + sizeof(int32_t)*(yyvsp[0].int32)); } +#line 5834 "asmparse.cpp" + break; + + case 406: /* ddItem: INT16_ '(' int32 ')' ddItemCount */ #line 1085 "asmparse.y" -{ __int16 i = (__int16) yypvt[-2].int32; FAIL_UNLESS(i == yypvt[-2].int32, ("Value %d too big\n", yypvt[-2].int32)); - __int16* p = new (nothrow) __int16[yypvt[-0].int32]; + { int16_t i = (int16_t) (yyvsp[-2].int32); FAIL_UNLESS(i == (yyvsp[-2].int32), ("Value %d too big\n", (yyvsp[-2].int32))); + int16_t* p = new (nothrow) int16_t[(yyvsp[0].int32)]; if(p != NULL) { - for(int j=0; jEmitData(p, sizeof(__int16)*yypvt[-0].int32); delete [] p; + for(int j=0; j<(yyvsp[0].int32); j++) p[j] = i; + PASM->EmitData(p, sizeof(int16_t)*(yyvsp[0].int32)); delete [] p; } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(__int16)*yypvt[-0].int32); } break; -case 406: + sizeof(int16_t)*(yyvsp[0].int32)); } +#line 5846 "asmparse.cpp" + break; + + case 407: /* ddItem: INT8_ '(' int32 ')' ddItemCount */ #line 1093 "asmparse.y" -{ __int8 i = (__int8) yypvt[-2].int32; FAIL_UNLESS(i == yypvt[-2].int32, ("Value %d too big\n", yypvt[-2].int32)); - __int8* p = new (nothrow) __int8[yypvt[-0].int32]; + { int8_t i = (int8_t) (yyvsp[-2].int32); FAIL_UNLESS(i == (yyvsp[-2].int32), ("Value %d too big\n", (yyvsp[-2].int32))); + int8_t* p = new (nothrow) int8_t[(yyvsp[0].int32)]; if(p != NULL) { - for(int j=0; jEmitData(p, sizeof(__int8)*yypvt[-0].int32); delete [] p; + for(int j=0; j<(yyvsp[0].int32); j++) p[j] = i; + PASM->EmitData(p, sizeof(int8_t)*(yyvsp[0].int32)); delete [] p; } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(__int8)*yypvt[-0].int32); } break; -case 407: + sizeof(int8_t)*(yyvsp[0].int32)); } +#line 5858 "asmparse.cpp" + break; + + case 408: /* ddItem: FLOAT32_ ddItemCount */ #line 1100 "asmparse.y" -{ PASM->EmitData(NULL, sizeof(float)*yypvt[-0].int32); } break; -case 408: + { PASM->EmitData(NULL, sizeof(float)*(yyvsp[0].int32)); } +#line 5864 "asmparse.cpp" + break; + + case 409: /* ddItem: FLOAT64_ ddItemCount */ #line 1101 "asmparse.y" -{ PASM->EmitData(NULL, sizeof(double)*yypvt[-0].int32); } break; -case 409: + { PASM->EmitData(NULL, sizeof(double)*(yyvsp[0].int32)); } +#line 5870 "asmparse.cpp" + break; + + case 410: /* ddItem: INT64_ ddItemCount */ #line 1102 "asmparse.y" -{ PASM->EmitData(NULL, sizeof(__int64)*yypvt[-0].int32); } break; -case 410: + { PASM->EmitData(NULL, sizeof(int64_t)*(yyvsp[0].int32)); } +#line 5876 "asmparse.cpp" + break; + + case 411: /* ddItem: INT32_ ddItemCount */ #line 1103 "asmparse.y" -{ PASM->EmitData(NULL, sizeof(__int32)*yypvt[-0].int32); } break; -case 411: + { PASM->EmitData(NULL, sizeof(int32_t)*(yyvsp[0].int32)); } +#line 5882 "asmparse.cpp" + break; + + case 412: /* ddItem: INT16_ ddItemCount */ #line 1104 "asmparse.y" -{ PASM->EmitData(NULL, sizeof(__int16)*yypvt[-0].int32); } break; -case 412: + { PASM->EmitData(NULL, sizeof(int16_t)*(yyvsp[0].int32)); } +#line 5888 "asmparse.cpp" + break; + + case 413: /* ddItem: INT8_ ddItemCount */ #line 1105 "asmparse.y" -{ PASM->EmitData(NULL, sizeof(__int8)*yypvt[-0].int32); } break; -case 413: + { PASM->EmitData(NULL, sizeof(int8_t)*(yyvsp[0].int32)); } +#line 5894 "asmparse.cpp" + break; + + case 414: /* fieldSerInit: FLOAT32_ '(' float64 ')' */ #line 1109 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R4); - float f = (float)(*yypvt[-1].float64); - yyval.binstr->appendInt32(*((__int32*)&f)); delete yypvt[-1].float64; } break; -case 414: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_R4); + float f = (float)(*(yyvsp[-1].float64)); + (yyval.binstr)->appendInt32(*((int32_t*)&f)); delete (yyvsp[-1].float64); } +#line 5902 "asmparse.cpp" + break; + + case 415: /* fieldSerInit: FLOAT64_ '(' float64 ')' */ #line 1112 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R8); - yyval.binstr->appendInt64((__int64 *)yypvt[-1].float64); delete yypvt[-1].float64; } break; -case 415: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_R8); + (yyval.binstr)->appendInt64((int64_t *)(yyvsp[-1].float64)); delete (yyvsp[-1].float64); } +#line 5909 "asmparse.cpp" + break; + + case 416: /* fieldSerInit: FLOAT32_ '(' int32 ')' */ #line 1114 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R4); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 416: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_R4); + (yyval.binstr)->appendInt32((yyvsp[-1].int32)); } +#line 5916 "asmparse.cpp" + break; + + case 417: /* fieldSerInit: FLOAT64_ '(' int64 ')' */ #line 1116 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R8); - yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; -case 417: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_R8); + (yyval.binstr)->appendInt64((int64_t *)(yyvsp[-1].int64)); delete (yyvsp[-1].int64); } +#line 5923 "asmparse.cpp" + break; + + case 418: /* fieldSerInit: INT64_ '(' int64 ')' */ #line 1118 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I8); - yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; -case 418: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_I8); + (yyval.binstr)->appendInt64((int64_t *)(yyvsp[-1].int64)); delete (yyvsp[-1].int64); } +#line 5930 "asmparse.cpp" + break; + + case 419: /* fieldSerInit: INT32_ '(' int32 ')' */ #line 1120 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I4); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 419: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_I4); + (yyval.binstr)->appendInt32((yyvsp[-1].int32)); } +#line 5937 "asmparse.cpp" + break; + + case 420: /* fieldSerInit: INT16_ '(' int32 ')' */ #line 1122 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I2); - yyval.binstr->appendInt16(yypvt[-1].int32); } break; -case 420: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_I2); + (yyval.binstr)->appendInt16((yyvsp[-1].int32)); } +#line 5944 "asmparse.cpp" + break; + + case 421: /* fieldSerInit: INT8_ '(' int32 ')' */ #line 1124 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I1); - yyval.binstr->appendInt8(yypvt[-1].int32); } break; -case 421: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_I1); + (yyval.binstr)->appendInt8((yyvsp[-1].int32)); } +#line 5951 "asmparse.cpp" + break; + + case 422: /* fieldSerInit: UNSIGNED_ INT64_ '(' int64 ')' */ #line 1126 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); - yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; -case 422: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U8); + (yyval.binstr)->appendInt64((int64_t *)(yyvsp[-1].int64)); delete (yyvsp[-1].int64); } +#line 5958 "asmparse.cpp" + break; + + case 423: /* fieldSerInit: UNSIGNED_ INT32_ '(' int32 ')' */ #line 1128 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 423: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U4); + (yyval.binstr)->appendInt32((yyvsp[-1].int32)); } +#line 5965 "asmparse.cpp" + break; + + case 424: /* fieldSerInit: UNSIGNED_ INT16_ '(' int32 ')' */ #line 1130 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); - yyval.binstr->appendInt16(yypvt[-1].int32); } break; -case 424: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U2); + (yyval.binstr)->appendInt16((yyvsp[-1].int32)); } +#line 5972 "asmparse.cpp" + break; + + case 425: /* fieldSerInit: UNSIGNED_ INT8_ '(' int32 ')' */ #line 1132 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); - yyval.binstr->appendInt8(yypvt[-1].int32); } break; -case 425: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U1); + (yyval.binstr)->appendInt8((yyvsp[-1].int32)); } +#line 5979 "asmparse.cpp" + break; + + case 426: /* fieldSerInit: UINT64_ '(' int64 ')' */ #line 1134 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); - yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; -case 426: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U8); + (yyval.binstr)->appendInt64((int64_t *)(yyvsp[-1].int64)); delete (yyvsp[-1].int64); } +#line 5986 "asmparse.cpp" + break; + + case 427: /* fieldSerInit: UINT32_ '(' int32 ')' */ #line 1136 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 427: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U4); + (yyval.binstr)->appendInt32((yyvsp[-1].int32)); } +#line 5993 "asmparse.cpp" + break; + + case 428: /* fieldSerInit: UINT16_ '(' int32 ')' */ #line 1138 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); - yyval.binstr->appendInt16(yypvt[-1].int32); } break; -case 428: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U2); + (yyval.binstr)->appendInt16((yyvsp[-1].int32)); } +#line 6000 "asmparse.cpp" + break; + + case 429: /* fieldSerInit: UINT8_ '(' int32 ')' */ #line 1140 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); - yyval.binstr->appendInt8(yypvt[-1].int32); } break; -case 429: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U1); + (yyval.binstr)->appendInt8((yyvsp[-1].int32)); } +#line 6007 "asmparse.cpp" + break; + + case 430: /* fieldSerInit: CHAR_ '(' int32 ')' */ #line 1142 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_CHAR); - yyval.binstr->appendInt16(yypvt[-1].int32); } break; -case 430: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_CHAR); + (yyval.binstr)->appendInt16((yyvsp[-1].int32)); } +#line 6014 "asmparse.cpp" + break; + + case 431: /* fieldSerInit: BOOL_ '(' truefalse ')' */ #line 1144 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_BOOLEAN); - yyval.binstr->appendInt8(yypvt[-1].int32);} break; -case 431: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_BOOLEAN); + (yyval.binstr)->appendInt8((yyvsp[-1].int32));} +#line 6021 "asmparse.cpp" + break; + + case 432: /* fieldSerInit: bytearrayhead bytes ')' */ #line 1146 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); - yyval.binstr->append(yypvt[-1].binstr); delete yypvt[-1].binstr;} break; -case 432: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_STRING); + (yyval.binstr)->append((yyvsp[-1].binstr)); delete (yyvsp[-1].binstr);} +#line 6028 "asmparse.cpp" + break; + + case 433: /* bytearrayhead: BYTEARRAY_ '(' */ #line 1150 "asmparse.y" -{ bParsingByteArray = TRUE; } break; -case 433: + { bParsingByteArray = TRUE; } +#line 6034 "asmparse.cpp" + break; + + case 434: /* bytes: %empty */ #line 1153 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 434: + { (yyval.binstr) = new BinStr(); } +#line 6040 "asmparse.cpp" + break; + + case 435: /* bytes: hexbytes */ #line 1154 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 435: + { (yyval.binstr) = (yyvsp[0].binstr); } +#line 6046 "asmparse.cpp" + break; + + case 436: /* hexbytes: HEXBYTE */ #line 1157 "asmparse.y" -{ __int8 i = (__int8) yypvt[-0].int32; yyval.binstr = new BinStr(); yyval.binstr->appendInt8(i); } break; -case 436: + { int8_t i = (int8_t) (yyvsp[0].int32); (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(i); } +#line 6052 "asmparse.cpp" + break; + + case 437: /* hexbytes: hexbytes HEXBYTE */ #line 1158 "asmparse.y" -{ __int8 i = (__int8) yypvt[-0].int32; yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(i); } break; -case 437: + { int8_t i = (int8_t) (yyvsp[0].int32); (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->appendInt8(i); } +#line 6058 "asmparse.cpp" + break; + + case 438: /* fieldInit: fieldSerInit */ #line 1162 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 438: + { (yyval.binstr) = (yyvsp[0].binstr); } +#line 6064 "asmparse.cpp" + break; + + case 439: /* fieldInit: compQstring */ #line 1163 "asmparse.y" -{ yyval.binstr = BinStrToUnicode(yypvt[-0].binstr,true); yyval.binstr->insertInt8(ELEMENT_TYPE_STRING);} break; -case 439: + { (yyval.binstr) = BinStrToUnicode((yyvsp[0].binstr),true); (yyval.binstr)->insertInt8(ELEMENT_TYPE_STRING);} +#line 6070 "asmparse.cpp" + break; + + case 440: /* fieldInit: NULLREF_ */ #line 1164 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_CLASS); - yyval.binstr->appendInt32(0); } break; -case 440: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_CLASS); + (yyval.binstr)->appendInt32(0); } +#line 6077 "asmparse.cpp" + break; + + case 441: /* serInit: fieldSerInit */ #line 1169 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 441: + { (yyval.binstr) = (yyvsp[0].binstr); } +#line 6083 "asmparse.cpp" + break; + + case 442: /* serInit: STRING_ '(' NULLREF_ ')' */ #line 1170 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); yyval.binstr->appendInt8(0xFF); } break; -case 442: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_STRING); (yyval.binstr)->appendInt8(0xFF); } +#line 6089 "asmparse.cpp" + break; + + case 443: /* serInit: STRING_ '(' SQSTRING ')' */ #line 1171 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); - AppendStringWithLength(yyval.binstr,yypvt[-1].string); delete [] yypvt[-1].string;} break; -case 443: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_STRING); + AppendStringWithLength((yyval.binstr),(yyvsp[-1].string)); delete [] (yyvsp[-1].string);} +#line 6096 "asmparse.cpp" + break; + + case 444: /* serInit: TYPE_ '(' CLASS_ SQSTRING ')' */ #line 1173 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); - AppendStringWithLength(yyval.binstr,yypvt[-1].string); delete [] yypvt[-1].string;} break; -case 444: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_TYPE); + AppendStringWithLength((yyval.binstr),(yyvsp[-1].string)); delete [] (yyvsp[-1].string);} +#line 6103 "asmparse.cpp" + break; + + case 445: /* serInit: TYPE_ '(' className ')' */ #line 1175 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); - AppendStringWithLength(yyval.binstr,PASM->ReflectionNotation(yypvt[-1].token));} break; -case 445: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_TYPE); + AppendStringWithLength((yyval.binstr),PASM->ReflectionNotation((yyvsp[-1].token)));} +#line 6110 "asmparse.cpp" + break; + + case 446: /* serInit: TYPE_ '(' NULLREF_ ')' */ #line 1177 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); yyval.binstr->appendInt8(0xFF); } break; -case 446: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_TYPE); (yyval.binstr)->appendInt8(0xFF); } +#line 6116 "asmparse.cpp" + break; + + case 447: /* serInit: OBJECT_ '(' serInit ')' */ #line 1178 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(SERIALIZATION_TYPE_TAGGED_OBJECT);} break; -case 447: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt8(SERIALIZATION_TYPE_TAGGED_OBJECT);} +#line 6122 "asmparse.cpp" + break; + + case 448: /* serInit: FLOAT32_ '[' int32 ']' '(' f32seq ')' */ #line 1180 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_R4); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 448: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_R4); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6130 "asmparse.cpp" + break; + + case 449: /* serInit: FLOAT64_ '[' int32 ']' '(' f64seq ')' */ #line 1184 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_R8); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 449: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_R8); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6138 "asmparse.cpp" + break; + + case 450: /* serInit: INT64_ '[' int32 ']' '(' i64seq ')' */ #line 1188 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_I8); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 450: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_I8); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6146 "asmparse.cpp" + break; + + case 451: /* serInit: INT32_ '[' int32 ']' '(' i32seq ')' */ #line 1192 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_I4); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 451: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_I4); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6154 "asmparse.cpp" + break; + + case 452: /* serInit: INT16_ '[' int32 ']' '(' i16seq ')' */ #line 1196 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_I2); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 452: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_I2); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6162 "asmparse.cpp" + break; + + case 453: /* serInit: INT8_ '[' int32 ']' '(' i8seq ')' */ #line 1200 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_I1); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 453: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_I1); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6170 "asmparse.cpp" + break; + + case 454: /* serInit: UINT64_ '[' int32 ']' '(' i64seq ')' */ #line 1204 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U8); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 454: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_U8); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6178 "asmparse.cpp" + break; + + case 455: /* serInit: UINT32_ '[' int32 ']' '(' i32seq ')' */ #line 1208 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U4); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 455: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_U4); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6186 "asmparse.cpp" + break; + + case 456: /* serInit: UINT16_ '[' int32 ']' '(' i16seq ')' */ #line 1212 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U2); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 456: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_U2); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6194 "asmparse.cpp" + break; + + case 457: /* serInit: UINT8_ '[' int32 ']' '(' i8seq ')' */ #line 1216 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U1); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 457: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_U1); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6202 "asmparse.cpp" + break; + + case 458: /* serInit: UNSIGNED_ INT64_ '[' int32 ']' '(' i64seq ')' */ #line 1220 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U8); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 458: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_U8); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6210 "asmparse.cpp" + break; + + case 459: /* serInit: UNSIGNED_ INT32_ '[' int32 ']' '(' i32seq ')' */ #line 1224 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U4); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 459: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_U4); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6218 "asmparse.cpp" + break; + + case 460: /* serInit: UNSIGNED_ INT16_ '[' int32 ']' '(' i16seq ')' */ #line 1228 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U2); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 460: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_U2); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6226 "asmparse.cpp" + break; + + case 461: /* serInit: UNSIGNED_ INT8_ '[' int32 ']' '(' i8seq ')' */ #line 1232 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U1); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 461: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_U1); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6234 "asmparse.cpp" + break; + + case 462: /* serInit: CHAR_ '[' int32 ']' '(' i16seq ')' */ #line 1236 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_CHAR); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 462: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_CHAR); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6242 "asmparse.cpp" + break; + + case 463: /* serInit: BOOL_ '[' int32 ']' '(' boolSeq ')' */ #line 1240 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_BOOLEAN); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 463: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_BOOLEAN); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6250 "asmparse.cpp" + break; + + case 464: /* serInit: STRING_ '[' int32 ']' '(' sqstringSeq ')' */ #line 1244 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_STRING); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 464: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_STRING); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6258 "asmparse.cpp" + break; + + case 465: /* serInit: TYPE_ '[' int32 ']' '(' classSeq ')' */ #line 1248 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(SERIALIZATION_TYPE_TYPE); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 465: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(SERIALIZATION_TYPE_TYPE); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6266 "asmparse.cpp" + break; + + case 466: /* serInit: OBJECT_ '[' int32 ']' '(' objSeq ')' */ #line 1252 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(SERIALIZATION_TYPE_TAGGED_OBJECT); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 466: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt32((yyvsp[-4].int32)); + (yyval.binstr)->insertInt8(SERIALIZATION_TYPE_TAGGED_OBJECT); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 6274 "asmparse.cpp" + break; + + case 467: /* f32seq: %empty */ #line 1258 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 467: + { (yyval.binstr) = new BinStr(); } +#line 6280 "asmparse.cpp" + break; + + case 468: /* f32seq: f32seq float64 */ #line 1259 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - float f = (float) (*yypvt[-0].float64); yyval.binstr->appendInt32(*((__int32*)&f)); delete yypvt[-0].float64; } break; -case 468: + { (yyval.binstr) = (yyvsp[-1].binstr); + float f = (float) (*(yyvsp[0].float64)); (yyval.binstr)->appendInt32(*((int32_t*)&f)); delete (yyvsp[0].float64); } +#line 6287 "asmparse.cpp" + break; + + case 469: /* f32seq: f32seq int32 */ #line 1261 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - yyval.binstr->appendInt32(yypvt[-0].int32); } break; -case 469: + { (yyval.binstr) = (yyvsp[-1].binstr); + (yyval.binstr)->appendInt32((yyvsp[0].int32)); } +#line 6294 "asmparse.cpp" + break; + + case 470: /* f64seq: %empty */ #line 1265 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 470: + { (yyval.binstr) = new BinStr(); } +#line 6300 "asmparse.cpp" + break; + + case 471: /* f64seq: f64seq float64 */ #line 1266 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - yyval.binstr->appendInt64((__int64 *)yypvt[-0].float64); delete yypvt[-0].float64; } break; -case 471: + { (yyval.binstr) = (yyvsp[-1].binstr); + (yyval.binstr)->appendInt64((int64_t *)(yyvsp[0].float64)); delete (yyvsp[0].float64); } +#line 6307 "asmparse.cpp" + break; + + case 472: /* f64seq: f64seq int64 */ #line 1268 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - yyval.binstr->appendInt64((__int64 *)yypvt[-0].int64); delete yypvt[-0].int64; } break; -case 472: + { (yyval.binstr) = (yyvsp[-1].binstr); + (yyval.binstr)->appendInt64((int64_t *)(yyvsp[0].int64)); delete (yyvsp[0].int64); } +#line 6314 "asmparse.cpp" + break; + + case 473: /* i64seq: %empty */ #line 1272 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 473: + { (yyval.binstr) = new BinStr(); } +#line 6320 "asmparse.cpp" + break; + + case 474: /* i64seq: i64seq int64 */ #line 1273 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - yyval.binstr->appendInt64((__int64 *)yypvt[-0].int64); delete yypvt[-0].int64; } break; -case 474: + { (yyval.binstr) = (yyvsp[-1].binstr); + (yyval.binstr)->appendInt64((int64_t *)(yyvsp[0].int64)); delete (yyvsp[0].int64); } +#line 6327 "asmparse.cpp" + break; + + case 475: /* i32seq: %empty */ #line 1277 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 475: + { (yyval.binstr) = new BinStr(); } +#line 6333 "asmparse.cpp" + break; + + case 476: /* i32seq: i32seq int32 */ #line 1278 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt32(yypvt[-0].int32);} break; -case 476: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->appendInt32((yyvsp[0].int32));} +#line 6339 "asmparse.cpp" + break; + + case 477: /* i16seq: %empty */ #line 1281 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 477: + { (yyval.binstr) = new BinStr(); } +#line 6345 "asmparse.cpp" + break; + + case 478: /* i16seq: i16seq int32 */ #line 1282 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt16(yypvt[-0].int32);} break; -case 478: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->appendInt16((yyvsp[0].int32));} +#line 6351 "asmparse.cpp" + break; + + case 479: /* i8seq: %empty */ #line 1285 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 479: + { (yyval.binstr) = new BinStr(); } +#line 6357 "asmparse.cpp" + break; + + case 480: /* i8seq: i8seq int32 */ #line 1286 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(yypvt[-0].int32); } break; -case 480: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->appendInt8((yyvsp[0].int32)); } +#line 6363 "asmparse.cpp" + break; + + case 481: /* boolSeq: %empty */ #line 1289 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 481: + { (yyval.binstr) = new BinStr(); } +#line 6369 "asmparse.cpp" + break; + + case 482: /* boolSeq: boolSeq truefalse */ #line 1290 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - yyval.binstr->appendInt8(yypvt[-0].int32);} break; -case 482: + { (yyval.binstr) = (yyvsp[-1].binstr); + (yyval.binstr)->appendInt8((yyvsp[0].int32));} +#line 6376 "asmparse.cpp" + break; + + case 483: /* sqstringSeq: %empty */ #line 1294 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 483: + { (yyval.binstr) = new BinStr(); } +#line 6382 "asmparse.cpp" + break; + + case 484: /* sqstringSeq: sqstringSeq NULLREF_ */ #line 1295 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(0xFF); } break; -case 484: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->appendInt8(0xFF); } +#line 6388 "asmparse.cpp" + break; + + case 485: /* sqstringSeq: sqstringSeq SQSTRING */ #line 1296 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - AppendStringWithLength(yyval.binstr,yypvt[-0].string); delete [] yypvt[-0].string;} break; -case 485: + { (yyval.binstr) = (yyvsp[-1].binstr); + AppendStringWithLength((yyval.binstr),(yyvsp[0].string)); delete [] (yyvsp[0].string);} +#line 6395 "asmparse.cpp" + break; + + case 486: /* classSeq: %empty */ #line 1300 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 486: + { (yyval.binstr) = new BinStr(); } +#line 6401 "asmparse.cpp" + break; + + case 487: /* classSeq: classSeq NULLREF_ */ #line 1301 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(0xFF); } break; -case 487: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->appendInt8(0xFF); } +#line 6407 "asmparse.cpp" + break; + + case 488: /* classSeq: classSeq CLASS_ SQSTRING */ #line 1302 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; - AppendStringWithLength(yyval.binstr,yypvt[-0].string); delete [] yypvt[-0].string;} break; -case 488: + { (yyval.binstr) = (yyvsp[-2].binstr); + AppendStringWithLength((yyval.binstr),(yyvsp[0].string)); delete [] (yyvsp[0].string);} +#line 6414 "asmparse.cpp" + break; + + case 489: /* classSeq: classSeq className */ #line 1304 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - AppendStringWithLength(yyval.binstr,PASM->ReflectionNotation(yypvt[-0].token));} break; -case 489: + { (yyval.binstr) = (yyvsp[-1].binstr); + AppendStringWithLength((yyval.binstr),PASM->ReflectionNotation((yyvsp[0].token)));} +#line 6421 "asmparse.cpp" + break; + + case 490: /* objSeq: %empty */ #line 1308 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 490: + { (yyval.binstr) = new BinStr(); } +#line 6427 "asmparse.cpp" + break; + + case 491: /* objSeq: objSeq serInit */ #line 1309 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; -case 491: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->append((yyvsp[0].binstr)); delete (yyvsp[0].binstr); } +#line 6433 "asmparse.cpp" + break; + + case 492: /* methodSpec: METHOD_ */ #line 1313 "asmparse.y" -{ parser->m_ANSFirst.PUSH(PASM->m_firstArgName); + { parser->m_ANSFirst.PUSH(PASM->m_firstArgName); parser->m_ANSLast.PUSH(PASM->m_lastArgName); PASM->m_firstArgName = NULL; - PASM->m_lastArgName = NULL; } break; -case 492: + PASM->m_lastArgName = NULL; } +#line 6442 "asmparse.cpp" + break; + + case 493: /* instr_none: INSTR_NONE */ #line 1319 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 493: + { (yyval.instr) = SetupInstr((yyvsp[0].opcode)); } +#line 6448 "asmparse.cpp" + break; + + case 494: /* instr_var: INSTR_VAR */ #line 1322 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 494: + { (yyval.instr) = SetupInstr((yyvsp[0].opcode)); } +#line 6454 "asmparse.cpp" + break; + + case 495: /* instr_i: INSTR_I */ #line 1325 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 495: + { (yyval.instr) = SetupInstr((yyvsp[0].opcode)); } +#line 6460 "asmparse.cpp" + break; + + case 496: /* instr_i8: INSTR_I8 */ #line 1328 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 496: + { (yyval.instr) = SetupInstr((yyvsp[0].opcode)); } +#line 6466 "asmparse.cpp" + break; + + case 497: /* instr_r: INSTR_R */ #line 1331 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 497: + { (yyval.instr) = SetupInstr((yyvsp[0].opcode)); } +#line 6472 "asmparse.cpp" + break; + + case 498: /* instr_brtarget: INSTR_BRTARGET */ #line 1334 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 498: + { (yyval.instr) = SetupInstr((yyvsp[0].opcode)); } +#line 6478 "asmparse.cpp" + break; + + case 499: /* instr_method: INSTR_METHOD */ #line 1337 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); + { (yyval.instr) = SetupInstr((yyvsp[0].opcode)); if((!PASM->OnErrGo)&& - ((yypvt[-0].opcode == CEE_NEWOBJ)|| - (yypvt[-0].opcode == CEE_CALLVIRT))) + (((yyvsp[0].opcode) == CEE_NEWOBJ)|| + ((yyvsp[0].opcode) == CEE_CALLVIRT))) iCallConv = IMAGE_CEE_CS_CALLCONV_HASTHIS; - } break; -case 499: + } +#line 6489 "asmparse.cpp" + break; + + case 500: /* instr_field: INSTR_FIELD */ #line 1345 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 500: + { (yyval.instr) = SetupInstr((yyvsp[0].opcode)); } +#line 6495 "asmparse.cpp" + break; + + case 501: /* instr_type: INSTR_TYPE */ #line 1348 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 501: + { (yyval.instr) = SetupInstr((yyvsp[0].opcode)); } +#line 6501 "asmparse.cpp" + break; + + case 502: /* instr_string: INSTR_STRING */ #line 1351 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 502: + { (yyval.instr) = SetupInstr((yyvsp[0].opcode)); } +#line 6507 "asmparse.cpp" + break; + + case 503: /* instr_sig: INSTR_SIG */ #line 1354 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 503: + { (yyval.instr) = SetupInstr((yyvsp[0].opcode)); } +#line 6513 "asmparse.cpp" + break; + + case 504: /* instr_tok: INSTR_TOK */ #line 1357 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); iOpcodeLen = PASM->OpcodeLen(yyval.instr); } break; -case 504: + { (yyval.instr) = SetupInstr((yyvsp[0].opcode)); iOpcodeLen = PASM->OpcodeLen((yyval.instr)); } +#line 6519 "asmparse.cpp" + break; + + case 505: /* instr_switch: INSTR_SWITCH */ #line 1360 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 505: + { (yyval.instr) = SetupInstr((yyvsp[0].opcode)); } +#line 6525 "asmparse.cpp" + break; + + case 506: /* instr_r_head: instr_r '(' */ #line 1363 "asmparse.y" -{ yyval.instr = yypvt[-1].instr; bParsingByteArray = TRUE; } break; -case 506: + { (yyval.instr) = (yyvsp[-1].instr); bParsingByteArray = TRUE; } +#line 6531 "asmparse.cpp" + break; + + case 507: /* instr: instr_none */ #line 1367 "asmparse.y" -{ PASM->EmitOpcode(yypvt[-0].instr); } break; -case 507: + { PASM->EmitOpcode((yyvsp[0].instr)); } +#line 6537 "asmparse.cpp" + break; + + case 508: /* instr: instr_var int32 */ #line 1368 "asmparse.y" -{ PASM->EmitInstrVar(yypvt[-1].instr, yypvt[-0].int32); } break; -case 508: + { PASM->EmitInstrVar((yyvsp[-1].instr), (yyvsp[0].int32)); } +#line 6543 "asmparse.cpp" + break; + + case 509: /* instr: instr_var id */ #line 1369 "asmparse.y" -{ PASM->EmitInstrVarByName(yypvt[-1].instr, yypvt[-0].string); } break; -case 509: + { PASM->EmitInstrVarByName((yyvsp[-1].instr), (yyvsp[0].string)); } +#line 6549 "asmparse.cpp" + break; + + case 510: /* instr: instr_i int32 */ #line 1370 "asmparse.y" -{ PASM->EmitInstrI(yypvt[-1].instr, yypvt[-0].int32); } break; -case 510: + { PASM->EmitInstrI((yyvsp[-1].instr), (yyvsp[0].int32)); } +#line 6555 "asmparse.cpp" + break; + + case 511: /* instr: instr_i8 int64 */ #line 1371 "asmparse.y" -{ PASM->EmitInstrI8(yypvt[-1].instr, yypvt[-0].int64); } break; -case 511: + { PASM->EmitInstrI8((yyvsp[-1].instr), (yyvsp[0].int64)); } +#line 6561 "asmparse.cpp" + break; + + case 512: /* instr: instr_r float64 */ #line 1372 "asmparse.y" -{ PASM->EmitInstrR(yypvt[-1].instr, yypvt[-0].float64); delete (yypvt[-0].float64);} break; -case 512: + { PASM->EmitInstrR((yyvsp[-1].instr), (yyvsp[0].float64)); delete ((yyvsp[0].float64));} +#line 6567 "asmparse.cpp" + break; + + case 513: /* instr: instr_r int64 */ #line 1373 "asmparse.y" -{ double f = (double) (*yypvt[-0].int64); PASM->EmitInstrR(yypvt[-1].instr, &f); } break; -case 513: + { double f = (double) (*(yyvsp[0].int64)); PASM->EmitInstrR((yyvsp[-1].instr), &f); } +#line 6573 "asmparse.cpp" + break; + + case 514: /* instr: instr_r_head bytes ')' */ #line 1374 "asmparse.y" -{ unsigned L = yypvt[-1].binstr->length(); + { unsigned L = (yyvsp[-1].binstr)->length(); FAIL_UNLESS(L >= sizeof(float), ("%d hexbytes, must be at least %d\n", L,sizeof(float))); if(L < sizeof(float)) {YYERROR; } else { - double f = (L >= sizeof(double)) ? *((double *)(yypvt[-1].binstr->ptr())) - : (double)(*(float *)(yypvt[-1].binstr->ptr())); - PASM->EmitInstrR(yypvt[-2].instr,&f); } - delete yypvt[-1].binstr; } break; -case 514: + double f = (L >= sizeof(double)) ? *((double *)((yyvsp[-1].binstr)->ptr())) + : (double)(*(float *)((yyvsp[-1].binstr)->ptr())); + PASM->EmitInstrR((yyvsp[-2].instr),&f); } + delete (yyvsp[-1].binstr); } +#line 6587 "asmparse.cpp" + break; + + case 515: /* instr: instr_brtarget int32 */ #line 1383 "asmparse.y" -{ PASM->EmitInstrBrOffset(yypvt[-1].instr, yypvt[-0].int32); } break; -case 515: + { PASM->EmitInstrBrOffset((yyvsp[-1].instr), (yyvsp[0].int32)); } +#line 6593 "asmparse.cpp" + break; + + case 516: /* instr: instr_brtarget id */ #line 1384 "asmparse.y" -{ PASM->EmitInstrBrTarget(yypvt[-1].instr, yypvt[-0].string); } break; -case 516: + { PASM->EmitInstrBrTarget((yyvsp[-1].instr), (yyvsp[0].string)); } +#line 6599 "asmparse.cpp" + break; + + case 517: /* instr: instr_method methodRef */ #line 1386 "asmparse.y" -{ PASM->SetMemberRefFixup(yypvt[-0].token,PASM->OpcodeLen(yypvt[-1].instr)); - PASM->EmitInstrI(yypvt[-1].instr,yypvt[-0].token); - PASM->m_tkCurrentCVOwner = yypvt[-0].token; + { PASM->SetMemberRefFixup((yyvsp[0].token),PASM->OpcodeLen((yyvsp[-1].instr))); + PASM->EmitInstrI((yyvsp[-1].instr),(yyvsp[0].token)); + PASM->m_tkCurrentCVOwner = (yyvsp[0].token); PASM->m_pCustomDescrList = NULL; iCallConv = 0; - } break; -case 517: + } +#line 6610 "asmparse.cpp" + break; + + case 518: /* instr: instr_field type typeSpec DCOLON dottedName */ #line 1393 "asmparse.y" -{ yypvt[-3].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); - mdToken mr = PASM->MakeMemberRef(yypvt[-2].token, yypvt[-0].string, yypvt[-3].binstr); - PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-4].instr)); - PASM->EmitInstrI(yypvt[-4].instr,mr); + { (yyvsp[-3].binstr)->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + mdToken mr = PASM->MakeMemberRef((yyvsp[-2].token), (yyvsp[0].string), (yyvsp[-3].binstr)); + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen((yyvsp[-4].instr))); + PASM->EmitInstrI((yyvsp[-4].instr),mr); PASM->m_tkCurrentCVOwner = mr; PASM->m_pCustomDescrList = NULL; - } break; -case 518: + } +#line 6622 "asmparse.cpp" + break; + + case 519: /* instr: instr_field type dottedName */ #line 1401 "asmparse.y" -{ yypvt[-1].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); - mdToken mr = PASM->MakeMemberRef(mdTokenNil, yypvt[-0].string, yypvt[-1].binstr); - PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-2].instr)); - PASM->EmitInstrI(yypvt[-2].instr,mr); + { (yyvsp[-1].binstr)->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + mdToken mr = PASM->MakeMemberRef(mdTokenNil, (yyvsp[0].string), (yyvsp[-1].binstr)); + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen((yyvsp[-2].instr))); + PASM->EmitInstrI((yyvsp[-2].instr),mr); PASM->m_tkCurrentCVOwner = mr; PASM->m_pCustomDescrList = NULL; - } break; -case 519: + } +#line 6634 "asmparse.cpp" + break; + + case 520: /* instr: instr_field mdtoken */ #line 1408 "asmparse.y" -{ mdToken mr = yypvt[-0].token; - PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-1].instr)); - PASM->EmitInstrI(yypvt[-1].instr,mr); + { mdToken mr = (yyvsp[0].token); + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen((yyvsp[-1].instr))); + PASM->EmitInstrI((yyvsp[-1].instr),mr); PASM->m_tkCurrentCVOwner = mr; PASM->m_pCustomDescrList = NULL; - } break; -case 520: + } +#line 6645 "asmparse.cpp" + break; + + case 521: /* instr: instr_field TYPEDEF_F */ #line 1414 "asmparse.y" -{ mdToken mr = yypvt[-0].tdd->m_tkTypeSpec; - PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-1].instr)); - PASM->EmitInstrI(yypvt[-1].instr,mr); + { mdToken mr = (yyvsp[0].tdd)->m_tkTypeSpec; + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen((yyvsp[-1].instr))); + PASM->EmitInstrI((yyvsp[-1].instr),mr); PASM->m_tkCurrentCVOwner = mr; PASM->m_pCustomDescrList = NULL; - } break; -case 521: + } +#line 6656 "asmparse.cpp" + break; + + case 522: /* instr: instr_field TYPEDEF_MR */ #line 1420 "asmparse.y" -{ mdToken mr = yypvt[-0].tdd->m_tkTypeSpec; - PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-1].instr)); - PASM->EmitInstrI(yypvt[-1].instr,mr); + { mdToken mr = (yyvsp[0].tdd)->m_tkTypeSpec; + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen((yyvsp[-1].instr))); + PASM->EmitInstrI((yyvsp[-1].instr),mr); PASM->m_tkCurrentCVOwner = mr; PASM->m_pCustomDescrList = NULL; - } break; -case 522: + } +#line 6667 "asmparse.cpp" + break; + + case 523: /* instr: instr_type typeSpec */ #line 1426 "asmparse.y" -{ PASM->EmitInstrI(yypvt[-1].instr, yypvt[-0].token); - PASM->m_tkCurrentCVOwner = yypvt[-0].token; + { PASM->EmitInstrI((yyvsp[-1].instr), (yyvsp[0].token)); + PASM->m_tkCurrentCVOwner = (yyvsp[0].token); PASM->m_pCustomDescrList = NULL; - } break; -case 523: + } +#line 6676 "asmparse.cpp" + break; + + case 524: /* instr: instr_string compQstring */ #line 1430 "asmparse.y" -{ PASM->EmitInstrStringLiteral(yypvt[-1].instr, yypvt[-0].binstr,TRUE); } break; -case 524: + { PASM->EmitInstrStringLiteral((yyvsp[-1].instr), (yyvsp[0].binstr),TRUE); } +#line 6682 "asmparse.cpp" + break; + + case 525: /* instr: instr_string ANSI_ '(' compQstring ')' */ #line 1432 "asmparse.y" -{ PASM->EmitInstrStringLiteral(yypvt[-4].instr, yypvt[-1].binstr,FALSE); } break; -case 525: + { PASM->EmitInstrStringLiteral((yyvsp[-4].instr), (yyvsp[-1].binstr),FALSE); } +#line 6688 "asmparse.cpp" + break; + + case 526: /* instr: instr_string bytearrayhead bytes ')' */ #line 1434 "asmparse.y" -{ PASM->EmitInstrStringLiteral(yypvt[-3].instr, yypvt[-1].binstr,FALSE,TRUE); } break; -case 526: + { PASM->EmitInstrStringLiteral((yyvsp[-3].instr), (yyvsp[-1].binstr),FALSE,TRUE); } +#line 6694 "asmparse.cpp" + break; + + case 527: /* instr: instr_sig callConv type '(' sigArgs0 ')' */ #line 1436 "asmparse.y" -{ PASM->EmitInstrSig(yypvt[-5].instr, parser->MakeSig(yypvt[-4].int32, yypvt[-3].binstr, yypvt[-1].binstr)); + { PASM->EmitInstrSig((yyvsp[-5].instr), parser->MakeSig((yyvsp[-4].int32), (yyvsp[-3].binstr), (yyvsp[-1].binstr))); PASM->ResetArgNameList(); - } break; -case 527: + } +#line 6702 "asmparse.cpp" + break; + + case 528: /* instr: instr_tok ownerType */ #line 1440 "asmparse.y" -{ PASM->EmitInstrI(yypvt[-1].instr,yypvt[-0].token); - PASM->m_tkCurrentCVOwner = yypvt[-0].token; + { PASM->EmitInstrI((yyvsp[-1].instr),(yyvsp[0].token)); + PASM->m_tkCurrentCVOwner = (yyvsp[0].token); PASM->m_pCustomDescrList = NULL; iOpcodeLen = 0; - } break; -case 528: + } +#line 6712 "asmparse.cpp" + break; + + case 529: /* instr: instr_switch '(' labels ')' */ #line 1445 "asmparse.y" -{ PASM->EmitInstrSwitch(yypvt[-3].instr, yypvt[-1].labels); } break; -case 529: + { PASM->EmitInstrSwitch((yyvsp[-3].instr), (yyvsp[-1].labels)); } +#line 6718 "asmparse.cpp" + break; + + case 530: /* labels: %empty */ #line 1448 "asmparse.y" -{ yyval.labels = 0; } break; -case 530: + { (yyval.labels) = 0; } +#line 6724 "asmparse.cpp" + break; + + case 531: /* labels: id ',' labels */ #line 1449 "asmparse.y" -{ yyval.labels = new Labels(yypvt[-2].string, yypvt[-0].labels, TRUE); } break; -case 531: + { (yyval.labels) = new Labels((yyvsp[-2].string), (yyvsp[0].labels), TRUE); } +#line 6730 "asmparse.cpp" + break; + + case 532: /* labels: int32 ',' labels */ #line 1450 "asmparse.y" -{ yyval.labels = new Labels((char *)(UINT_PTR)yypvt[-2].int32, yypvt[-0].labels, FALSE); } break; -case 532: + { (yyval.labels) = new Labels((char *)(UINT_PTR)(yyvsp[-2].int32), (yyvsp[0].labels), FALSE); } +#line 6736 "asmparse.cpp" + break; + + case 533: /* labels: id */ #line 1451 "asmparse.y" -{ yyval.labels = new Labels(yypvt[-0].string, NULL, TRUE); } break; -case 533: + { (yyval.labels) = new Labels((yyvsp[0].string), NULL, TRUE); } +#line 6742 "asmparse.cpp" + break; + + case 534: /* labels: int32 */ #line 1452 "asmparse.y" -{ yyval.labels = new Labels((char *)(UINT_PTR)yypvt[-0].int32, NULL, FALSE); } break; -case 534: + { (yyval.labels) = new Labels((char *)(UINT_PTR)(yyvsp[0].int32), NULL, FALSE); } +#line 6748 "asmparse.cpp" + break; + + case 535: /* tyArgs0: %empty */ #line 1456 "asmparse.y" -{ yyval.binstr = NULL; } break; -case 535: + { (yyval.binstr) = NULL; } +#line 6754 "asmparse.cpp" + break; + + case 536: /* tyArgs0: '<' tyArgs1 '>' */ #line 1457 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; } break; -case 536: + { (yyval.binstr) = (yyvsp[-1].binstr); } +#line 6760 "asmparse.cpp" + break; + + case 537: /* tyArgs1: %empty */ #line 1460 "asmparse.y" -{ yyval.binstr = NULL; } break; -case 537: + { (yyval.binstr) = NULL; } +#line 6766 "asmparse.cpp" + break; + + case 538: /* tyArgs1: tyArgs2 */ #line 1461 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 538: + { (yyval.binstr) = (yyvsp[0].binstr); } +#line 6772 "asmparse.cpp" + break; + + case 539: /* tyArgs2: type */ #line 1464 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 539: + { (yyval.binstr) = (yyvsp[0].binstr); } +#line 6778 "asmparse.cpp" + break; + + case 540: /* tyArgs2: tyArgs2 ',' type */ #line 1465 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; -case 540: + { (yyval.binstr) = (yyvsp[-2].binstr); (yyval.binstr)->append((yyvsp[0].binstr)); delete (yyvsp[0].binstr); } +#line 6784 "asmparse.cpp" + break; + + case 541: /* sigArgs0: %empty */ #line 1469 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 541: + { (yyval.binstr) = new BinStr(); } +#line 6790 "asmparse.cpp" + break; + + case 542: /* sigArgs0: sigArgs1 */ #line 1470 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr;} break; -case 542: + { (yyval.binstr) = (yyvsp[0].binstr);} +#line 6796 "asmparse.cpp" + break; + + case 543: /* sigArgs1: sigArg */ #line 1473 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 543: + { (yyval.binstr) = (yyvsp[0].binstr); } +#line 6802 "asmparse.cpp" + break; + + case 544: /* sigArgs1: sigArgs1 ',' sigArg */ #line 1474 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; -case 544: + { (yyval.binstr) = (yyvsp[-2].binstr); (yyval.binstr)->append((yyvsp[0].binstr)); delete (yyvsp[0].binstr); } +#line 6808 "asmparse.cpp" + break; + + case 545: /* sigArg: ELLIPSIS */ #line 1477 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_SENTINEL); } break; -case 545: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_SENTINEL); } +#line 6814 "asmparse.cpp" + break; + + case 546: /* sigArg: paramAttr type marshalClause */ #line 1478 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-1].binstr); PASM->addArgName(NULL, yypvt[-1].binstr, yypvt[-0].binstr, yypvt[-2].int32); } break; -case 546: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->append((yyvsp[-1].binstr)); PASM->addArgName(NULL, (yyvsp[-1].binstr), (yyvsp[0].binstr), (yyvsp[-2].int32)); } +#line 6820 "asmparse.cpp" + break; + + case 547: /* sigArg: paramAttr type marshalClause id */ #line 1479 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-2].binstr); PASM->addArgName(yypvt[-0].string, yypvt[-2].binstr, yypvt[-1].binstr, yypvt[-3].int32);} break; -case 547: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->append((yyvsp[-2].binstr)); PASM->addArgName((yyvsp[0].string), (yyvsp[-2].binstr), (yyvsp[-1].binstr), (yyvsp[-3].int32));} +#line 6826 "asmparse.cpp" + break; + + case 548: /* className: '[' dottedName ']' slashedName */ #line 1483 "asmparse.y" -{ yyval.token = PASM->ResolveClassRef(PASM->GetAsmRef(yypvt[-2].string), yypvt[-0].string, NULL); delete[] yypvt[-2].string;} break; -case 548: + { (yyval.token) = PASM->ResolveClassRef(PASM->GetAsmRef((yyvsp[-2].string)), (yyvsp[0].string), NULL); delete[] (yyvsp[-2].string);} +#line 6832 "asmparse.cpp" + break; + + case 549: /* className: '[' mdtoken ']' slashedName */ #line 1484 "asmparse.y" -{ yyval.token = PASM->ResolveClassRef(yypvt[-2].token, yypvt[-0].string, NULL); } break; -case 549: + { (yyval.token) = PASM->ResolveClassRef((yyvsp[-2].token), (yyvsp[0].string), NULL); } +#line 6838 "asmparse.cpp" + break; + + case 550: /* className: '[' '*' ']' slashedName */ #line 1485 "asmparse.y" -{ yyval.token = PASM->ResolveClassRef(mdTokenNil, yypvt[-0].string, NULL); } break; -case 550: + { (yyval.token) = PASM->ResolveClassRef(mdTokenNil, (yyvsp[0].string), NULL); } +#line 6844 "asmparse.cpp" + break; + + case 551: /* className: '[' _MODULE dottedName ']' slashedName */ #line 1486 "asmparse.y" -{ yyval.token = PASM->ResolveClassRef(PASM->GetModRef(yypvt[-2].string),yypvt[-0].string, NULL); delete[] yypvt[-2].string;} break; -case 551: + { (yyval.token) = PASM->ResolveClassRef(PASM->GetModRef((yyvsp[-2].string)),(yyvsp[0].string), NULL); delete[] (yyvsp[-2].string);} +#line 6850 "asmparse.cpp" + break; + + case 552: /* className: slashedName */ #line 1487 "asmparse.y" -{ yyval.token = PASM->ResolveClassRef(1,yypvt[-0].string,NULL); } break; -case 552: + { (yyval.token) = PASM->ResolveClassRef(1,(yyvsp[0].string),NULL); } +#line 6856 "asmparse.cpp" + break; + + case 553: /* className: mdtoken */ #line 1488 "asmparse.y" -{ yyval.token = yypvt[-0].token; } break; -case 553: + { (yyval.token) = (yyvsp[0].token); } +#line 6862 "asmparse.cpp" + break; + + case 554: /* className: TYPEDEF_T */ #line 1489 "asmparse.y" -{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; } break; -case 554: + { (yyval.token) = (yyvsp[0].tdd)->m_tkTypeSpec; } +#line 6868 "asmparse.cpp" + break; + + case 555: /* className: _THIS */ #line 1490 "asmparse.y" -{ if(PASM->m_pCurClass != NULL) yyval.token = PASM->m_pCurClass->m_cl; - else { yyval.token = 0; PASM->report->error(".this outside class scope\n"); } - } break; -case 555: + { if(PASM->m_pCurClass != NULL) (yyval.token) = PASM->m_pCurClass->m_cl; + else { (yyval.token) = 0; PASM->report->error(".this outside class scope\n"); } + } +#line 6876 "asmparse.cpp" + break; + + case 556: /* className: _BASE */ #line 1493 "asmparse.y" -{ if(PASM->m_pCurClass != NULL) { - yyval.token = PASM->m_pCurClass->m_crExtends; - if(RidFromToken(yyval.token) == 0) + { if(PASM->m_pCurClass != NULL) { + (yyval.token) = PASM->m_pCurClass->m_crExtends; + if(RidFromToken((yyval.token)) == 0) PASM->report->error(".base undefined\n"); - } else { yyval.token = 0; PASM->report->error(".base outside class scope\n"); } - } break; -case 556: + } else { (yyval.token) = 0; PASM->report->error(".base outside class scope\n"); } + } +#line 6887 "asmparse.cpp" + break; + + case 557: /* className: _NESTER */ #line 1499 "asmparse.y" -{ if(PASM->m_pCurClass != NULL) { - if(PASM->m_pCurClass->m_pEncloser != NULL) yyval.token = PASM->m_pCurClass->m_pEncloser->m_cl; - else { yyval.token = 0; PASM->report->error(".nester undefined\n"); } - } else { yyval.token = 0; PASM->report->error(".nester outside class scope\n"); } - } break; -case 557: + { if(PASM->m_pCurClass != NULL) { + if(PASM->m_pCurClass->m_pEncloser != NULL) (yyval.token) = PASM->m_pCurClass->m_pEncloser->m_cl; + else { (yyval.token) = 0; PASM->report->error(".nester undefined\n"); } + } else { (yyval.token) = 0; PASM->report->error(".nester outside class scope\n"); } + } +#line 6897 "asmparse.cpp" + break; + + case 558: /* slashedName: dottedName */ #line 1506 "asmparse.y" -{ yyval.string = yypvt[-0].string; } break; -case 558: + { (yyval.string) = (yyvsp[0].string); } +#line 6903 "asmparse.cpp" + break; + + case 559: /* slashedName: slashedName '/' dottedName */ #line 1507 "asmparse.y" -{ yyval.string = newStringWDel(yypvt[-2].string, NESTING_SEP, yypvt[-0].string); } break; -case 559: + { (yyval.string) = newStringWDel((yyvsp[-2].string), NESTING_SEP, (yyvsp[0].string)); } +#line 6909 "asmparse.cpp" + break; + + case 560: /* typeSpec: className */ #line 1510 "asmparse.y" -{ yyval.token = yypvt[-0].token;} break; -case 560: + { (yyval.token) = (yyvsp[0].token);} +#line 6915 "asmparse.cpp" + break; + + case 561: /* typeSpec: '[' dottedName ']' */ #line 1511 "asmparse.y" -{ yyval.token = PASM->GetAsmRef(yypvt[-1].string); delete[] yypvt[-1].string;} break; -case 561: + { (yyval.token) = PASM->GetAsmRef((yyvsp[-1].string)); delete[] (yyvsp[-1].string);} +#line 6921 "asmparse.cpp" + break; + + case 562: /* typeSpec: '[' _MODULE dottedName ']' */ #line 1512 "asmparse.y" -{ yyval.token = PASM->GetModRef(yypvt[-1].string); delete[] yypvt[-1].string;} break; -case 562: + { (yyval.token) = PASM->GetModRef((yyvsp[-1].string)); delete[] (yyvsp[-1].string);} +#line 6927 "asmparse.cpp" + break; + + case 563: /* typeSpec: type */ #line 1513 "asmparse.y" -{ yyval.token = PASM->ResolveTypeSpec(yypvt[-0].binstr); } break; -case 563: + { (yyval.token) = PASM->ResolveTypeSpec((yyvsp[0].binstr)); } +#line 6933 "asmparse.cpp" + break; + + case 564: /* nativeType: %empty */ #line 1517 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 564: + { (yyval.binstr) = new BinStr(); } +#line 6939 "asmparse.cpp" + break; + + case 565: /* nativeType: CUSTOM_ '(' compQstring ',' compQstring ',' compQstring ',' compQstring ')' */ #line 1519 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_CUSTOMMARSHALER); - corEmitInt(yyval.binstr,yypvt[-7].binstr->length()); yyval.binstr->append(yypvt[-7].binstr); - corEmitInt(yyval.binstr,yypvt[-5].binstr->length()); yyval.binstr->append(yypvt[-5].binstr); - corEmitInt(yyval.binstr,yypvt[-3].binstr->length()); yyval.binstr->append(yypvt[-3].binstr); - corEmitInt(yyval.binstr,yypvt[-1].binstr->length()); yyval.binstr->append(yypvt[-1].binstr); - PASM->report->warn("Deprecated 4-string form of custom marshaler, first two strings ignored\n");} break; -case 565: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_CUSTOMMARSHALER); + corEmitInt((yyval.binstr),(yyvsp[-7].binstr)->length()); (yyval.binstr)->append((yyvsp[-7].binstr)); + corEmitInt((yyval.binstr),(yyvsp[-5].binstr)->length()); (yyval.binstr)->append((yyvsp[-5].binstr)); + corEmitInt((yyval.binstr),(yyvsp[-3].binstr)->length()); (yyval.binstr)->append((yyvsp[-3].binstr)); + corEmitInt((yyval.binstr),(yyvsp[-1].binstr)->length()); (yyval.binstr)->append((yyvsp[-1].binstr)); + PASM->report->warn("Deprecated 4-string form of custom marshaler, first two strings ignored\n");} +#line 6950 "asmparse.cpp" + break; + + case 566: /* nativeType: CUSTOM_ '(' compQstring ',' compQstring ')' */ #line 1526 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_CUSTOMMARSHALER); - corEmitInt(yyval.binstr,0); - corEmitInt(yyval.binstr,0); - corEmitInt(yyval.binstr,yypvt[-3].binstr->length()); yyval.binstr->append(yypvt[-3].binstr); - corEmitInt(yyval.binstr,yypvt[-1].binstr->length()); yyval.binstr->append(yypvt[-1].binstr); } break; -case 566: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_CUSTOMMARSHALER); + corEmitInt((yyval.binstr),0); + corEmitInt((yyval.binstr),0); + corEmitInt((yyval.binstr),(yyvsp[-3].binstr)->length()); (yyval.binstr)->append((yyvsp[-3].binstr)); + corEmitInt((yyval.binstr),(yyvsp[-1].binstr)->length()); (yyval.binstr)->append((yyvsp[-1].binstr)); } +#line 6960 "asmparse.cpp" + break; + + case 567: /* nativeType: FIXED_ SYSSTRING_ '[' int32 ']' */ #line 1531 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_FIXEDSYSSTRING); - corEmitInt(yyval.binstr,yypvt[-1].int32); } break; -case 567: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_FIXEDSYSSTRING); + corEmitInt((yyval.binstr),(yyvsp[-1].int32)); } +#line 6967 "asmparse.cpp" + break; + + case 568: /* nativeType: FIXED_ ARRAY_ '[' int32 ']' nativeType */ #line 1534 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_FIXEDARRAY); - corEmitInt(yyval.binstr,yypvt[-2].int32); yyval.binstr->append(yypvt[-0].binstr); } break; -case 568: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_FIXEDARRAY); + corEmitInt((yyval.binstr),(yyvsp[-2].int32)); (yyval.binstr)->append((yyvsp[0].binstr)); } +#line 6974 "asmparse.cpp" + break; + + case 569: /* nativeType: VARIANT_ */ #line 1536 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_VARIANT); - PASM->report->warn("Deprecated native type 'variant'\n"); } break; -case 569: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_VARIANT); + PASM->report->warn("Deprecated native type 'variant'\n"); } +#line 6981 "asmparse.cpp" + break; + + case 570: /* nativeType: CURRENCY_ */ #line 1538 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_CURRENCY); } break; -case 570: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_CURRENCY); } +#line 6987 "asmparse.cpp" + break; + + case 571: /* nativeType: SYSCHAR_ */ #line 1539 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_SYSCHAR); - PASM->report->warn("Deprecated native type 'syschar'\n"); } break; -case 571: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_SYSCHAR); + PASM->report->warn("Deprecated native type 'syschar'\n"); } +#line 6994 "asmparse.cpp" + break; + + case 572: /* nativeType: VOID_ */ #line 1541 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_VOID); - PASM->report->warn("Deprecated native type 'void'\n"); } break; -case 572: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_VOID); + PASM->report->warn("Deprecated native type 'void'\n"); } +#line 7001 "asmparse.cpp" + break; + + case 573: /* nativeType: BOOL_ */ #line 1543 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_BOOLEAN); } break; -case 573: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_BOOLEAN); } +#line 7007 "asmparse.cpp" + break; + + case 574: /* nativeType: INT8_ */ #line 1544 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I1); } break; -case 574: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_I1); } +#line 7013 "asmparse.cpp" + break; + + case 575: /* nativeType: INT16_ */ #line 1545 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I2); } break; -case 575: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_I2); } +#line 7019 "asmparse.cpp" + break; + + case 576: /* nativeType: INT32_ */ #line 1546 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I4); } break; -case 576: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_I4); } +#line 7025 "asmparse.cpp" + break; + + case 577: /* nativeType: INT64_ */ #line 1547 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I8); } break; -case 577: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_I8); } +#line 7031 "asmparse.cpp" + break; + + case 578: /* nativeType: FLOAT32_ */ #line 1548 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_R4); } break; -case 578: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_R4); } +#line 7037 "asmparse.cpp" + break; + + case 579: /* nativeType: FLOAT64_ */ #line 1549 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_R8); } break; -case 579: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_R8); } +#line 7043 "asmparse.cpp" + break; + + case 580: /* nativeType: ERROR_ */ #line 1550 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_ERROR); } break; -case 580: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_ERROR); } +#line 7049 "asmparse.cpp" + break; + + case 581: /* nativeType: UNSIGNED_ INT8_ */ #line 1551 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U1); } break; -case 581: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_U1); } +#line 7055 "asmparse.cpp" + break; + + case 582: /* nativeType: UNSIGNED_ INT16_ */ #line 1552 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U2); } break; -case 582: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_U2); } +#line 7061 "asmparse.cpp" + break; + + case 583: /* nativeType: UNSIGNED_ INT32_ */ #line 1553 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U4); } break; -case 583: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_U4); } +#line 7067 "asmparse.cpp" + break; + + case 584: /* nativeType: UNSIGNED_ INT64_ */ #line 1554 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U8); } break; -case 584: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_U8); } +#line 7073 "asmparse.cpp" + break; + + case 585: /* nativeType: UINT8_ */ #line 1555 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U1); } break; -case 585: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_U1); } +#line 7079 "asmparse.cpp" + break; + + case 586: /* nativeType: UINT16_ */ #line 1556 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U2); } break; -case 586: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_U2); } +#line 7085 "asmparse.cpp" + break; + + case 587: /* nativeType: UINT32_ */ #line 1557 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U4); } break; -case 587: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_U4); } +#line 7091 "asmparse.cpp" + break; + + case 588: /* nativeType: UINT64_ */ #line 1558 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U8); } break; -case 588: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_U8); } +#line 7097 "asmparse.cpp" + break; + + case 589: /* nativeType: nativeType '*' */ #line 1559 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(NATIVE_TYPE_PTR); - PASM->report->warn("Deprecated native type '*'\n"); } break; -case 589: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt8(NATIVE_TYPE_PTR); + PASM->report->warn("Deprecated native type '*'\n"); } +#line 7104 "asmparse.cpp" + break; + + case 590: /* nativeType: nativeType '[' ']' */ #line 1561 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); - yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); } break; -case 590: + { (yyval.binstr) = (yyvsp[-2].binstr); if((yyval.binstr)->length()==0) (yyval.binstr)->appendInt8(NATIVE_TYPE_MAX); + (yyval.binstr)->insertInt8(NATIVE_TYPE_ARRAY); } +#line 7111 "asmparse.cpp" + break; + + case 591: /* nativeType: nativeType '[' int32 ']' */ #line 1563 "asmparse.y" -{ yyval.binstr = yypvt[-3].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); - yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); - corEmitInt(yyval.binstr,0); - corEmitInt(yyval.binstr,yypvt[-1].int32); - corEmitInt(yyval.binstr,0); } break; -case 591: + { (yyval.binstr) = (yyvsp[-3].binstr); if((yyval.binstr)->length()==0) (yyval.binstr)->appendInt8(NATIVE_TYPE_MAX); + (yyval.binstr)->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt((yyval.binstr),0); + corEmitInt((yyval.binstr),(yyvsp[-1].int32)); + corEmitInt((yyval.binstr),0); } +#line 7121 "asmparse.cpp" + break; + + case 592: /* nativeType: nativeType '[' int32 '+' int32 ']' */ #line 1568 "asmparse.y" -{ yyval.binstr = yypvt[-5].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); - yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); - corEmitInt(yyval.binstr,yypvt[-1].int32); - corEmitInt(yyval.binstr,yypvt[-3].int32); - corEmitInt(yyval.binstr,ntaSizeParamIndexSpecified); } break; -case 592: + { (yyval.binstr) = (yyvsp[-5].binstr); if((yyval.binstr)->length()==0) (yyval.binstr)->appendInt8(NATIVE_TYPE_MAX); + (yyval.binstr)->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt((yyval.binstr),(yyvsp[-1].int32)); + corEmitInt((yyval.binstr),(yyvsp[-3].int32)); + corEmitInt((yyval.binstr),ntaSizeParamIndexSpecified); } +#line 7131 "asmparse.cpp" + break; + + case 593: /* nativeType: nativeType '[' '+' int32 ']' */ #line 1573 "asmparse.y" -{ yyval.binstr = yypvt[-4].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); - yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); - corEmitInt(yyval.binstr,yypvt[-1].int32); } break; -case 593: + { (yyval.binstr) = (yyvsp[-4].binstr); if((yyval.binstr)->length()==0) (yyval.binstr)->appendInt8(NATIVE_TYPE_MAX); + (yyval.binstr)->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt((yyval.binstr),(yyvsp[-1].int32)); } +#line 7139 "asmparse.cpp" + break; + + case 594: /* nativeType: DECIMAL_ */ #line 1576 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_DECIMAL); - PASM->report->warn("Deprecated native type 'decimal'\n"); } break; -case 594: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_DECIMAL); + PASM->report->warn("Deprecated native type 'decimal'\n"); } +#line 7146 "asmparse.cpp" + break; + + case 595: /* nativeType: DATE_ */ #line 1578 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_DATE); - PASM->report->warn("Deprecated native type 'date'\n"); } break; -case 595: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_DATE); + PASM->report->warn("Deprecated native type 'date'\n"); } +#line 7153 "asmparse.cpp" + break; + + case 596: /* nativeType: BSTR_ */ #line 1580 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_BSTR); } break; -case 596: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_BSTR); } +#line 7159 "asmparse.cpp" + break; + + case 597: /* nativeType: LPSTR_ */ #line 1581 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPSTR); } break; -case 597: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_LPSTR); } +#line 7165 "asmparse.cpp" + break; + + case 598: /* nativeType: LPWSTR_ */ #line 1582 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPWSTR); } break; -case 598: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_LPWSTR); } +#line 7171 "asmparse.cpp" + break; + + case 599: /* nativeType: LPTSTR_ */ #line 1583 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPTSTR); } break; -case 599: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_LPTSTR); } +#line 7177 "asmparse.cpp" + break; + + case 600: /* nativeType: OBJECTREF_ */ #line 1584 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_OBJECTREF); - PASM->report->warn("Deprecated native type 'objectref'\n"); } break; -case 600: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_OBJECTREF); + PASM->report->warn("Deprecated native type 'objectref'\n"); } +#line 7184 "asmparse.cpp" + break; + + case 601: /* nativeType: IUNKNOWN_ iidParamIndex */ #line 1586 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_IUNKNOWN); - if(yypvt[-0].int32 != -1) corEmitInt(yyval.binstr,yypvt[-0].int32); } break; -case 601: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_IUNKNOWN); + if((yyvsp[0].int32) != -1) corEmitInt((yyval.binstr),(yyvsp[0].int32)); } +#line 7191 "asmparse.cpp" + break; + + case 602: /* nativeType: IDISPATCH_ iidParamIndex */ #line 1588 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_IDISPATCH); - if(yypvt[-0].int32 != -1) corEmitInt(yyval.binstr,yypvt[-0].int32); } break; -case 602: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_IDISPATCH); + if((yyvsp[0].int32) != -1) corEmitInt((yyval.binstr),(yyvsp[0].int32)); } +#line 7198 "asmparse.cpp" + break; + + case 603: /* nativeType: STRUCT_ */ #line 1590 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_STRUCT); } break; -case 603: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_STRUCT); } +#line 7204 "asmparse.cpp" + break; + + case 604: /* nativeType: INTERFACE_ iidParamIndex */ #line 1591 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_INTF); - if(yypvt[-0].int32 != -1) corEmitInt(yyval.binstr,yypvt[-0].int32); } break; -case 604: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_INTF); + if((yyvsp[0].int32) != -1) corEmitInt((yyval.binstr),(yyvsp[0].int32)); } +#line 7211 "asmparse.cpp" + break; + + case 605: /* nativeType: SAFEARRAY_ variantType */ #line 1593 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_SAFEARRAY); - corEmitInt(yyval.binstr,yypvt[-0].int32); - corEmitInt(yyval.binstr,0);} break; -case 605: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_SAFEARRAY); + corEmitInt((yyval.binstr),(yyvsp[0].int32)); + corEmitInt((yyval.binstr),0);} +#line 7219 "asmparse.cpp" + break; + + case 606: /* nativeType: SAFEARRAY_ variantType ',' compQstring */ #line 1596 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_SAFEARRAY); - corEmitInt(yyval.binstr,yypvt[-2].int32); - corEmitInt(yyval.binstr,yypvt[-0].binstr->length()); yyval.binstr->append(yypvt[-0].binstr); } break; -case 606: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_SAFEARRAY); + corEmitInt((yyval.binstr),(yyvsp[-2].int32)); + corEmitInt((yyval.binstr),(yyvsp[0].binstr)->length()); (yyval.binstr)->append((yyvsp[0].binstr)); } +#line 7227 "asmparse.cpp" + break; + + case 607: /* nativeType: INT_ */ #line 1600 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_INT); } break; -case 607: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_INT); } +#line 7233 "asmparse.cpp" + break; + + case 608: /* nativeType: UNSIGNED_ INT_ */ #line 1601 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_UINT); } break; -case 608: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_UINT); } +#line 7239 "asmparse.cpp" + break; + + case 609: /* nativeType: UINT_ */ #line 1602 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_UINT); } break; -case 609: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_UINT); } +#line 7245 "asmparse.cpp" + break; + + case 610: /* nativeType: NESTED_ STRUCT_ */ #line 1603 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_NESTEDSTRUCT); - PASM->report->warn("Deprecated native type 'nested struct'\n"); } break; -case 610: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_NESTEDSTRUCT); + PASM->report->warn("Deprecated native type 'nested struct'\n"); } +#line 7252 "asmparse.cpp" + break; + + case 611: /* nativeType: BYVALSTR_ */ #line 1605 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_BYVALSTR); } break; -case 611: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_BYVALSTR); } +#line 7258 "asmparse.cpp" + break; + + case 612: /* nativeType: ANSI_ BSTR_ */ #line 1606 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_ANSIBSTR); } break; -case 612: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_ANSIBSTR); } +#line 7264 "asmparse.cpp" + break; + + case 613: /* nativeType: TBSTR_ */ #line 1607 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_TBSTR); } break; -case 613: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_TBSTR); } +#line 7270 "asmparse.cpp" + break; + + case 614: /* nativeType: VARIANT_ BOOL_ */ #line 1608 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_VARIANTBOOL); } break; -case 614: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_VARIANTBOOL); } +#line 7276 "asmparse.cpp" + break; + + case 615: /* nativeType: METHOD_ */ #line 1609 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_FUNC); } break; -case 615: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_FUNC); } +#line 7282 "asmparse.cpp" + break; + + case 616: /* nativeType: AS_ ANY_ */ #line 1610 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_ASANY); } break; -case 616: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_ASANY); } +#line 7288 "asmparse.cpp" + break; + + case 617: /* nativeType: LPSTRUCT_ */ #line 1611 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPSTRUCT); } break; -case 617: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(NATIVE_TYPE_LPSTRUCT); } +#line 7294 "asmparse.cpp" + break; + + case 618: /* nativeType: TYPEDEF_TS */ #line 1612 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-0].tdd->m_pbsTypeSpec); } break; -case 618: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->append((yyvsp[0].tdd)->m_pbsTypeSpec); } +#line 7300 "asmparse.cpp" + break; + + case 619: /* iidParamIndex: %empty */ #line 1615 "asmparse.y" -{ yyval.int32 = -1; } break; -case 619: + { (yyval.int32) = -1; } +#line 7306 "asmparse.cpp" + break; + + case 620: /* iidParamIndex: '(' IIDPARAM_ '=' int32 ')' */ #line 1616 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32; } break; -case 620: + { (yyval.int32) = (yyvsp[-1].int32); } +#line 7312 "asmparse.cpp" + break; + + case 621: /* variantType: %empty */ #line 1619 "asmparse.y" -{ yyval.int32 = VT_EMPTY; } break; -case 621: + { (yyval.int32) = VT_EMPTY; } +#line 7318 "asmparse.cpp" + break; + + case 622: /* variantType: NULL_ */ #line 1620 "asmparse.y" -{ yyval.int32 = VT_NULL; } break; -case 622: + { (yyval.int32) = VT_NULL; } +#line 7324 "asmparse.cpp" + break; + + case 623: /* variantType: VARIANT_ */ #line 1621 "asmparse.y" -{ yyval.int32 = VT_VARIANT; } break; -case 623: + { (yyval.int32) = VT_VARIANT; } +#line 7330 "asmparse.cpp" + break; + + case 624: /* variantType: CURRENCY_ */ #line 1622 "asmparse.y" -{ yyval.int32 = VT_CY; } break; -case 624: + { (yyval.int32) = VT_CY; } +#line 7336 "asmparse.cpp" + break; + + case 625: /* variantType: VOID_ */ #line 1623 "asmparse.y" -{ yyval.int32 = VT_VOID; } break; -case 625: + { (yyval.int32) = VT_VOID; } +#line 7342 "asmparse.cpp" + break; + + case 626: /* variantType: BOOL_ */ #line 1624 "asmparse.y" -{ yyval.int32 = VT_BOOL; } break; -case 626: + { (yyval.int32) = VT_BOOL; } +#line 7348 "asmparse.cpp" + break; + + case 627: /* variantType: INT8_ */ #line 1625 "asmparse.y" -{ yyval.int32 = VT_I1; } break; -case 627: + { (yyval.int32) = VT_I1; } +#line 7354 "asmparse.cpp" + break; + + case 628: /* variantType: INT16_ */ #line 1626 "asmparse.y" -{ yyval.int32 = VT_I2; } break; -case 628: + { (yyval.int32) = VT_I2; } +#line 7360 "asmparse.cpp" + break; + + case 629: /* variantType: INT32_ */ #line 1627 "asmparse.y" -{ yyval.int32 = VT_I4; } break; -case 629: + { (yyval.int32) = VT_I4; } +#line 7366 "asmparse.cpp" + break; + + case 630: /* variantType: INT64_ */ #line 1628 "asmparse.y" -{ yyval.int32 = VT_I8; } break; -case 630: + { (yyval.int32) = VT_I8; } +#line 7372 "asmparse.cpp" + break; + + case 631: /* variantType: FLOAT32_ */ #line 1629 "asmparse.y" -{ yyval.int32 = VT_R4; } break; -case 631: + { (yyval.int32) = VT_R4; } +#line 7378 "asmparse.cpp" + break; + + case 632: /* variantType: FLOAT64_ */ #line 1630 "asmparse.y" -{ yyval.int32 = VT_R8; } break; -case 632: + { (yyval.int32) = VT_R8; } +#line 7384 "asmparse.cpp" + break; + + case 633: /* variantType: UNSIGNED_ INT8_ */ #line 1631 "asmparse.y" -{ yyval.int32 = VT_UI1; } break; -case 633: + { (yyval.int32) = VT_UI1; } +#line 7390 "asmparse.cpp" + break; + + case 634: /* variantType: UNSIGNED_ INT16_ */ #line 1632 "asmparse.y" -{ yyval.int32 = VT_UI2; } break; -case 634: + { (yyval.int32) = VT_UI2; } +#line 7396 "asmparse.cpp" + break; + + case 635: /* variantType: UNSIGNED_ INT32_ */ #line 1633 "asmparse.y" -{ yyval.int32 = VT_UI4; } break; -case 635: + { (yyval.int32) = VT_UI4; } +#line 7402 "asmparse.cpp" + break; + + case 636: /* variantType: UNSIGNED_ INT64_ */ #line 1634 "asmparse.y" -{ yyval.int32 = VT_UI8; } break; -case 636: + { (yyval.int32) = VT_UI8; } +#line 7408 "asmparse.cpp" + break; + + case 637: /* variantType: UINT8_ */ #line 1635 "asmparse.y" -{ yyval.int32 = VT_UI1; } break; -case 637: + { (yyval.int32) = VT_UI1; } +#line 7414 "asmparse.cpp" + break; + + case 638: /* variantType: UINT16_ */ #line 1636 "asmparse.y" -{ yyval.int32 = VT_UI2; } break; -case 638: + { (yyval.int32) = VT_UI2; } +#line 7420 "asmparse.cpp" + break; + + case 639: /* variantType: UINT32_ */ #line 1637 "asmparse.y" -{ yyval.int32 = VT_UI4; } break; -case 639: + { (yyval.int32) = VT_UI4; } +#line 7426 "asmparse.cpp" + break; + + case 640: /* variantType: UINT64_ */ #line 1638 "asmparse.y" -{ yyval.int32 = VT_UI8; } break; -case 640: + { (yyval.int32) = VT_UI8; } +#line 7432 "asmparse.cpp" + break; + + case 641: /* variantType: '*' */ #line 1639 "asmparse.y" -{ yyval.int32 = VT_PTR; } break; -case 641: + { (yyval.int32) = VT_PTR; } +#line 7438 "asmparse.cpp" + break; + + case 642: /* variantType: variantType '[' ']' */ #line 1640 "asmparse.y" -{ yyval.int32 = yypvt[-2].int32 | VT_ARRAY; } break; -case 642: + { (yyval.int32) = (yyvsp[-2].int32) | VT_ARRAY; } +#line 7444 "asmparse.cpp" + break; + + case 643: /* variantType: variantType VECTOR_ */ #line 1641 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | VT_VECTOR; } break; -case 643: + { (yyval.int32) = (yyvsp[-1].int32) | VT_VECTOR; } +#line 7450 "asmparse.cpp" + break; + + case 644: /* variantType: variantType '&' */ #line 1642 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | VT_BYREF; } break; -case 644: + { (yyval.int32) = (yyvsp[-1].int32) | VT_BYREF; } +#line 7456 "asmparse.cpp" + break; + + case 645: /* variantType: DECIMAL_ */ #line 1643 "asmparse.y" -{ yyval.int32 = VT_DECIMAL; } break; -case 645: + { (yyval.int32) = VT_DECIMAL; } +#line 7462 "asmparse.cpp" + break; + + case 646: /* variantType: DATE_ */ #line 1644 "asmparse.y" -{ yyval.int32 = VT_DATE; } break; -case 646: + { (yyval.int32) = VT_DATE; } +#line 7468 "asmparse.cpp" + break; + + case 647: /* variantType: BSTR_ */ #line 1645 "asmparse.y" -{ yyval.int32 = VT_BSTR; } break; -case 647: + { (yyval.int32) = VT_BSTR; } +#line 7474 "asmparse.cpp" + break; + + case 648: /* variantType: LPSTR_ */ #line 1646 "asmparse.y" -{ yyval.int32 = VT_LPSTR; } break; -case 648: + { (yyval.int32) = VT_LPSTR; } +#line 7480 "asmparse.cpp" + break; + + case 649: /* variantType: LPWSTR_ */ #line 1647 "asmparse.y" -{ yyval.int32 = VT_LPWSTR; } break; -case 649: + { (yyval.int32) = VT_LPWSTR; } +#line 7486 "asmparse.cpp" + break; + + case 650: /* variantType: IUNKNOWN_ */ #line 1648 "asmparse.y" -{ yyval.int32 = VT_UNKNOWN; } break; -case 650: + { (yyval.int32) = VT_UNKNOWN; } +#line 7492 "asmparse.cpp" + break; + + case 651: /* variantType: IDISPATCH_ */ #line 1649 "asmparse.y" -{ yyval.int32 = VT_DISPATCH; } break; -case 651: + { (yyval.int32) = VT_DISPATCH; } +#line 7498 "asmparse.cpp" + break; + + case 652: /* variantType: SAFEARRAY_ */ #line 1650 "asmparse.y" -{ yyval.int32 = VT_SAFEARRAY; } break; -case 652: + { (yyval.int32) = VT_SAFEARRAY; } +#line 7504 "asmparse.cpp" + break; + + case 653: /* variantType: INT_ */ #line 1651 "asmparse.y" -{ yyval.int32 = VT_INT; } break; -case 653: + { (yyval.int32) = VT_INT; } +#line 7510 "asmparse.cpp" + break; + + case 654: /* variantType: UNSIGNED_ INT_ */ #line 1652 "asmparse.y" -{ yyval.int32 = VT_UINT; } break; -case 654: + { (yyval.int32) = VT_UINT; } +#line 7516 "asmparse.cpp" + break; + + case 655: /* variantType: UINT_ */ #line 1653 "asmparse.y" -{ yyval.int32 = VT_UINT; } break; -case 655: + { (yyval.int32) = VT_UINT; } +#line 7522 "asmparse.cpp" + break; + + case 656: /* variantType: ERROR_ */ #line 1654 "asmparse.y" -{ yyval.int32 = VT_ERROR; } break; -case 656: + { (yyval.int32) = VT_ERROR; } +#line 7528 "asmparse.cpp" + break; + + case 657: /* variantType: HRESULT_ */ #line 1655 "asmparse.y" -{ yyval.int32 = VT_HRESULT; } break; -case 657: + { (yyval.int32) = VT_HRESULT; } +#line 7534 "asmparse.cpp" + break; + + case 658: /* variantType: CARRAY_ */ #line 1656 "asmparse.y" -{ yyval.int32 = VT_CARRAY; } break; -case 658: + { (yyval.int32) = VT_CARRAY; } +#line 7540 "asmparse.cpp" + break; + + case 659: /* variantType: USERDEFINED_ */ #line 1657 "asmparse.y" -{ yyval.int32 = VT_USERDEFINED; } break; -case 659: + { (yyval.int32) = VT_USERDEFINED; } +#line 7546 "asmparse.cpp" + break; + + case 660: /* variantType: RECORD_ */ #line 1658 "asmparse.y" -{ yyval.int32 = VT_RECORD; } break; -case 660: + { (yyval.int32) = VT_RECORD; } +#line 7552 "asmparse.cpp" + break; + + case 661: /* variantType: FILETIME_ */ #line 1659 "asmparse.y" -{ yyval.int32 = VT_FILETIME; } break; -case 661: + { (yyval.int32) = VT_FILETIME; } +#line 7558 "asmparse.cpp" + break; + + case 662: /* variantType: BLOB_ */ #line 1660 "asmparse.y" -{ yyval.int32 = VT_BLOB; } break; -case 662: + { (yyval.int32) = VT_BLOB; } +#line 7564 "asmparse.cpp" + break; + + case 663: /* variantType: STREAM_ */ #line 1661 "asmparse.y" -{ yyval.int32 = VT_STREAM; } break; -case 663: + { (yyval.int32) = VT_STREAM; } +#line 7570 "asmparse.cpp" + break; + + case 664: /* variantType: STORAGE_ */ #line 1662 "asmparse.y" -{ yyval.int32 = VT_STORAGE; } break; -case 664: + { (yyval.int32) = VT_STORAGE; } +#line 7576 "asmparse.cpp" + break; + + case 665: /* variantType: STREAMED_OBJECT_ */ #line 1663 "asmparse.y" -{ yyval.int32 = VT_STREAMED_OBJECT; } break; -case 665: + { (yyval.int32) = VT_STREAMED_OBJECT; } +#line 7582 "asmparse.cpp" + break; + + case 666: /* variantType: STORED_OBJECT_ */ #line 1664 "asmparse.y" -{ yyval.int32 = VT_STORED_OBJECT; } break; -case 666: + { (yyval.int32) = VT_STORED_OBJECT; } +#line 7588 "asmparse.cpp" + break; + + case 667: /* variantType: BLOB_OBJECT_ */ #line 1665 "asmparse.y" -{ yyval.int32 = VT_BLOB_OBJECT; } break; -case 667: + { (yyval.int32) = VT_BLOB_OBJECT; } +#line 7594 "asmparse.cpp" + break; + + case 668: /* variantType: CF_ */ #line 1666 "asmparse.y" -{ yyval.int32 = VT_CF; } break; -case 668: + { (yyval.int32) = VT_CF; } +#line 7600 "asmparse.cpp" + break; + + case 669: /* variantType: CLSID_ */ #line 1667 "asmparse.y" -{ yyval.int32 = VT_CLSID; } break; -case 669: + { (yyval.int32) = VT_CLSID; } +#line 7606 "asmparse.cpp" + break; + + case 670: /* type: CLASS_ className */ #line 1671 "asmparse.y" -{ if(yypvt[-0].token == PASM->m_tkSysString) - { yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); } - else if(yypvt[-0].token == PASM->m_tkSysObject) - { yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_OBJECT); } + { if((yyvsp[0].token) == PASM->m_tkSysString) + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_STRING); } + else if((yyvsp[0].token) == PASM->m_tkSysObject) + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_OBJECT); } else - yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_CLASS, yypvt[-0].token); } break; -case 670: + (yyval.binstr) = parser->MakeTypeClass(ELEMENT_TYPE_CLASS, (yyvsp[0].token)); } +#line 7617 "asmparse.cpp" + break; + + case 671: /* type: OBJECT_ */ #line 1677 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_OBJECT); } break; -case 671: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_OBJECT); } +#line 7623 "asmparse.cpp" + break; + + case 672: /* type: VALUE_ CLASS_ className */ #line 1678 "asmparse.y" -{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_VALUETYPE, yypvt[-0].token); } break; -case 672: + { (yyval.binstr) = parser->MakeTypeClass(ELEMENT_TYPE_VALUETYPE, (yyvsp[0].token)); } +#line 7629 "asmparse.cpp" + break; + + case 673: /* type: VALUETYPE_ className */ #line 1679 "asmparse.y" -{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_VALUETYPE, yypvt[-0].token); } break; -case 673: + { (yyval.binstr) = parser->MakeTypeClass(ELEMENT_TYPE_VALUETYPE, (yyvsp[0].token)); } +#line 7635 "asmparse.cpp" + break; + + case 674: /* type: type '[' ']' */ #line 1680 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 674: + { (yyval.binstr) = (yyvsp[-2].binstr); (yyval.binstr)->insertInt8(ELEMENT_TYPE_SZARRAY); } +#line 7641 "asmparse.cpp" + break; + + case 675: /* type: type '[' bounds1 ']' */ #line 1681 "asmparse.y" -{ yyval.binstr = parser->MakeTypeArray(ELEMENT_TYPE_ARRAY, yypvt[-3].binstr, yypvt[-1].binstr); } break; -case 675: + { (yyval.binstr) = parser->MakeTypeArray(ELEMENT_TYPE_ARRAY, (yyvsp[-3].binstr), (yyvsp[-1].binstr)); } +#line 7647 "asmparse.cpp" + break; + + case 676: /* type: type '&' */ #line 1682 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_BYREF); } break; -case 676: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt8(ELEMENT_TYPE_BYREF); } +#line 7653 "asmparse.cpp" + break; + + case 677: /* type: type '*' */ #line 1683 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_PTR); } break; -case 677: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt8(ELEMENT_TYPE_PTR); } +#line 7659 "asmparse.cpp" + break; + + case 678: /* type: type PINNED_ */ #line 1684 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_PINNED); } break; -case 678: + { (yyval.binstr) = (yyvsp[-1].binstr); (yyval.binstr)->insertInt8(ELEMENT_TYPE_PINNED); } +#line 7665 "asmparse.cpp" + break; + + case 679: /* type: type MODREQ_ '(' typeSpec ')' */ #line 1685 "asmparse.y" -{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_CMOD_REQD, yypvt[-1].token); - yyval.binstr->append(yypvt[-4].binstr); } break; -case 679: + { (yyval.binstr) = parser->MakeTypeClass(ELEMENT_TYPE_CMOD_REQD, (yyvsp[-1].token)); + (yyval.binstr)->append((yyvsp[-4].binstr)); } +#line 7672 "asmparse.cpp" + break; + + case 680: /* type: type MODOPT_ '(' typeSpec ')' */ #line 1687 "asmparse.y" -{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_CMOD_OPT, yypvt[-1].token); - yyval.binstr->append(yypvt[-4].binstr); } break; -case 680: + { (yyval.binstr) = parser->MakeTypeClass(ELEMENT_TYPE_CMOD_OPT, (yyvsp[-1].token)); + (yyval.binstr)->append((yyvsp[-4].binstr)); } +#line 7679 "asmparse.cpp" + break; + + case 681: /* type: methodSpec callConv type '*' '(' sigArgs0 ')' */ #line 1690 "asmparse.y" -{ yyval.binstr = parser->MakeSig(yypvt[-5].int32, yypvt[-4].binstr, yypvt[-1].binstr); - yyval.binstr->insertInt8(ELEMENT_TYPE_FNPTR); + { (yyval.binstr) = parser->MakeSig((yyvsp[-5].int32), (yyvsp[-4].binstr), (yyvsp[-1].binstr)); + (yyval.binstr)->insertInt8(ELEMENT_TYPE_FNPTR); PASM->delArgNameList(PASM->m_firstArgName); PASM->m_firstArgName = parser->m_ANSFirst.POP(); PASM->m_lastArgName = parser->m_ANSLast.POP(); - } break; -case 681: + } +#line 7690 "asmparse.cpp" + break; + + case 682: /* type: type '<' tyArgs1 '>' */ #line 1696 "asmparse.y" -{ if(yypvt[-1].binstr == NULL) yyval.binstr = yypvt[-3].binstr; + { if((yyvsp[-1].binstr) == NULL) (yyval.binstr) = (yyvsp[-3].binstr); else { - yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(ELEMENT_TYPE_GENERICINST); - yyval.binstr->append(yypvt[-3].binstr); - corEmitInt(yyval.binstr, corCountArgs(yypvt[-1].binstr)); - yyval.binstr->append(yypvt[-1].binstr); delete yypvt[-3].binstr; delete yypvt[-1].binstr; }} break; -case 682: + (yyval.binstr) = new BinStr(); + (yyval.binstr)->appendInt8(ELEMENT_TYPE_GENERICINST); + (yyval.binstr)->append((yyvsp[-3].binstr)); + corEmitInt((yyval.binstr), corCountArgs((yyvsp[-1].binstr))); + (yyval.binstr)->append((yyvsp[-1].binstr)); delete (yyvsp[-3].binstr); delete (yyvsp[-1].binstr); }} +#line 7702 "asmparse.cpp" + break; + + case 683: /* type: '!' '!' int32 */ #line 1703 "asmparse.y" -{ //if(PASM->m_pCurMethod) { + { //if(PASM->m_pCurMethod) { // if(($3 < 0)||((DWORD)$3 >= PASM->m_pCurMethod->m_NumTyPars)) // PASM->report->error("Invalid method type parameter '%d'\n",$3); - yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_MVAR); corEmitInt(yyval.binstr, yypvt[-0].int32); + (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_MVAR); corEmitInt((yyval.binstr), (yyvsp[0].int32)); //} else PASM->report->error("Method type parameter '%d' outside method scope\n",$3); - } break; -case 683: + } +#line 7713 "asmparse.cpp" + break; + + case 684: /* type: '!' int32 */ #line 1709 "asmparse.y" -{ //if(PASM->m_pCurClass) { + { //if(PASM->m_pCurClass) { // if(($2 < 0)||((DWORD)$2 >= PASM->m_pCurClass->m_NumTyPars)) // PASM->report->error("Invalid type parameter '%d'\n",$2); - yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_VAR); corEmitInt(yyval.binstr, yypvt[-0].int32); + (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_VAR); corEmitInt((yyval.binstr), (yyvsp[0].int32)); //} else PASM->report->error("Type parameter '%d' outside class scope\n",$2); - } break; -case 684: + } +#line 7724 "asmparse.cpp" + break; + + case 685: /* type: '!' '!' dottedName */ #line 1715 "asmparse.y" -{ int eltype = ELEMENT_TYPE_MVAR; + { int eltype = ELEMENT_TYPE_MVAR; int n=-1; - if(PASM->m_pCurMethod) n = PASM->m_pCurMethod->FindTyPar(yypvt[-0].string); + if(PASM->m_pCurMethod) n = PASM->m_pCurMethod->FindTyPar((yyvsp[0].string)); else { - if(PASM->m_TyParList) n = PASM->m_TyParList->IndexOf(yypvt[-0].string); + if(PASM->m_TyParList) n = PASM->m_TyParList->IndexOf((yyvsp[0].string)); if(n == -1) { n = TyParFixupList.COUNT(); - TyParFixupList.PUSH(yypvt[-0].string); + TyParFixupList.PUSH((yyvsp[0].string)); eltype = ELEMENT_TYPE_MVARFIXUP; } } - if(n == -1) { PASM->report->error("Invalid method type parameter '%s'\n",yypvt[-0].string); + if(n == -1) { PASM->report->error("Invalid method type parameter '%s'\n",(yyvsp[0].string)); n = 0x1FFFFFFF; } - yyval.binstr = new BinStr(); yyval.binstr->appendInt8(eltype); corEmitInt(yyval.binstr,n); - } break; -case 685: + (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(eltype); corEmitInt((yyval.binstr),n); + } +#line 7744 "asmparse.cpp" + break; + + case 686: /* type: '!' dottedName */ #line 1730 "asmparse.y" -{ int eltype = ELEMENT_TYPE_VAR; + { int eltype = ELEMENT_TYPE_VAR; int n=-1; - if(PASM->m_pCurClass && !newclass) n = PASM->m_pCurClass->FindTyPar(yypvt[-0].string); + if(PASM->m_pCurClass && !newclass) n = PASM->m_pCurClass->FindTyPar((yyvsp[0].string)); else { - if(PASM->m_TyParList) n = PASM->m_TyParList->IndexOf(yypvt[-0].string); + if(PASM->m_TyParList) n = PASM->m_TyParList->IndexOf((yyvsp[0].string)); if(n == -1) { n = TyParFixupList.COUNT(); - TyParFixupList.PUSH(yypvt[-0].string); + TyParFixupList.PUSH((yyvsp[0].string)); eltype = ELEMENT_TYPE_VARFIXUP; } } - if(n == -1) { PASM->report->error("Invalid type parameter '%s'\n",yypvt[-0].string); + if(n == -1) { PASM->report->error("Invalid type parameter '%s'\n",(yyvsp[0].string)); n = 0x1FFFFFFF; } - yyval.binstr = new BinStr(); yyval.binstr->appendInt8(eltype); corEmitInt(yyval.binstr,n); - } break; -case 686: + (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(eltype); corEmitInt((yyval.binstr),n); + } +#line 7764 "asmparse.cpp" + break; + + case 687: /* type: TYPEDREF_ */ #line 1745 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_TYPEDBYREF); } break; -case 687: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_TYPEDBYREF); } +#line 7770 "asmparse.cpp" + break; + + case 688: /* type: VOID_ */ #line 1746 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_VOID); } break; -case 688: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_VOID); } +#line 7776 "asmparse.cpp" + break; + + case 689: /* type: NATIVE_ INT_ */ #line 1747 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I); } break; -case 689: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_I); } +#line 7782 "asmparse.cpp" + break; + + case 690: /* type: NATIVE_ UNSIGNED_ INT_ */ #line 1748 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U); } break; -case 690: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U); } +#line 7788 "asmparse.cpp" + break; + + case 691: /* type: NATIVE_ UINT_ */ #line 1749 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U); } break; -case 691: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U); } +#line 7794 "asmparse.cpp" + break; + + case 692: /* type: simpleType */ #line 1750 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 692: + { (yyval.binstr) = (yyvsp[0].binstr); } +#line 7800 "asmparse.cpp" + break; + + case 693: /* type: ELLIPSIS type */ #line 1751 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_SENTINEL); } break; -case 693: + { (yyval.binstr) = (yyvsp[0].binstr); (yyval.binstr)->insertInt8(ELEMENT_TYPE_SENTINEL); } +#line 7806 "asmparse.cpp" + break; + + case 694: /* simpleType: CHAR_ */ #line 1754 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_CHAR); } break; -case 694: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_CHAR); } +#line 7812 "asmparse.cpp" + break; + + case 695: /* simpleType: STRING_ */ #line 1755 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); } break; -case 695: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_STRING); } +#line 7818 "asmparse.cpp" + break; + + case 696: /* simpleType: BOOL_ */ #line 1756 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_BOOLEAN); } break; -case 696: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_BOOLEAN); } +#line 7824 "asmparse.cpp" + break; + + case 697: /* simpleType: INT8_ */ #line 1757 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I1); } break; -case 697: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_I1); } +#line 7830 "asmparse.cpp" + break; + + case 698: /* simpleType: INT16_ */ #line 1758 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I2); } break; -case 698: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_I2); } +#line 7836 "asmparse.cpp" + break; + + case 699: /* simpleType: INT32_ */ #line 1759 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I4); } break; -case 699: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_I4); } +#line 7842 "asmparse.cpp" + break; + + case 700: /* simpleType: INT64_ */ #line 1760 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I8); } break; -case 700: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_I8); } +#line 7848 "asmparse.cpp" + break; + + case 701: /* simpleType: FLOAT32_ */ #line 1761 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R4); } break; -case 701: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_R4); } +#line 7854 "asmparse.cpp" + break; + + case 702: /* simpleType: FLOAT64_ */ #line 1762 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R8); } break; -case 702: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_R8); } +#line 7860 "asmparse.cpp" + break; + + case 703: /* simpleType: UNSIGNED_ INT8_ */ #line 1763 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); } break; -case 703: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U1); } +#line 7866 "asmparse.cpp" + break; + + case 704: /* simpleType: UNSIGNED_ INT16_ */ #line 1764 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); } break; -case 704: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U2); } +#line 7872 "asmparse.cpp" + break; + + case 705: /* simpleType: UNSIGNED_ INT32_ */ #line 1765 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); } break; -case 705: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U4); } +#line 7878 "asmparse.cpp" + break; + + case 706: /* simpleType: UNSIGNED_ INT64_ */ #line 1766 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); } break; -case 706: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U8); } +#line 7884 "asmparse.cpp" + break; + + case 707: /* simpleType: UINT8_ */ #line 1767 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); } break; -case 707: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U1); } +#line 7890 "asmparse.cpp" + break; + + case 708: /* simpleType: UINT16_ */ #line 1768 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); } break; -case 708: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U2); } +#line 7896 "asmparse.cpp" + break; + + case 709: /* simpleType: UINT32_ */ #line 1769 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); } break; -case 709: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U4); } +#line 7902 "asmparse.cpp" + break; + + case 710: /* simpleType: UINT64_ */ #line 1770 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); } break; -case 710: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt8(ELEMENT_TYPE_U8); } +#line 7908 "asmparse.cpp" + break; + + case 711: /* simpleType: TYPEDEF_TS */ #line 1771 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-0].tdd->m_pbsTypeSpec); } break; -case 711: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->append((yyvsp[0].tdd)->m_pbsTypeSpec); } +#line 7914 "asmparse.cpp" + break; + + case 712: /* bounds1: bound */ #line 1774 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 712: + { (yyval.binstr) = (yyvsp[0].binstr); } +#line 7920 "asmparse.cpp" + break; + + case 713: /* bounds1: bounds1 ',' bound */ #line 1775 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yypvt[-2].binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; -case 713: + { (yyval.binstr) = (yyvsp[-2].binstr); (yyvsp[-2].binstr)->append((yyvsp[0].binstr)); delete (yyvsp[0].binstr); } +#line 7926 "asmparse.cpp" + break; + + case 714: /* bound: %empty */ #line 1778 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(0x7FFFFFFF); yyval.binstr->appendInt32(0x7FFFFFFF); } break; -case 714: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt32(0x7FFFFFFF); (yyval.binstr)->appendInt32(0x7FFFFFFF); } +#line 7932 "asmparse.cpp" + break; + + case 715: /* bound: ELLIPSIS */ #line 1779 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(0x7FFFFFFF); yyval.binstr->appendInt32(0x7FFFFFFF); } break; -case 715: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt32(0x7FFFFFFF); (yyval.binstr)->appendInt32(0x7FFFFFFF); } +#line 7938 "asmparse.cpp" + break; + + case 716: /* bound: int32 */ #line 1780 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(0); yyval.binstr->appendInt32(yypvt[-0].int32); } break; -case 716: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt32(0); (yyval.binstr)->appendInt32((yyvsp[0].int32)); } +#line 7944 "asmparse.cpp" + break; + + case 717: /* bound: int32 ELLIPSIS int32 */ #line 1781 "asmparse.y" -{ FAIL_UNLESS(yypvt[-2].int32 <= yypvt[-0].int32, ("lower bound %d must be <= upper bound %d\n", yypvt[-2].int32, yypvt[-0].int32)); - if (yypvt[-2].int32 > yypvt[-0].int32) { YYERROR; }; - yyval.binstr = new BinStr(); yyval.binstr->appendInt32(yypvt[-2].int32); yyval.binstr->appendInt32(yypvt[-0].int32-yypvt[-2].int32+1); } break; -case 717: + { FAIL_UNLESS((yyvsp[-2].int32) <= (yyvsp[0].int32), ("lower bound %d must be <= upper bound %d\n", (yyvsp[-2].int32), (yyvsp[0].int32))); + if ((yyvsp[-2].int32) > (yyvsp[0].int32)) { YYERROR; }; + (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt32((yyvsp[-2].int32)); (yyval.binstr)->appendInt32((yyvsp[0].int32)-(yyvsp[-2].int32)+1); } +#line 7952 "asmparse.cpp" + break; + + case 718: /* bound: int32 ELLIPSIS */ #line 1784 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(yypvt[-1].int32); yyval.binstr->appendInt32(0x7FFFFFFF); } break; -case 718: + { (yyval.binstr) = new BinStr(); (yyval.binstr)->appendInt32((yyvsp[-1].int32)); (yyval.binstr)->appendInt32(0x7FFFFFFF); } +#line 7958 "asmparse.cpp" + break; + + case 719: /* secDecl: _PERMISSION secAction typeSpec '(' nameValPairs ')' */ #line 1789 "asmparse.y" -{ PASM->AddPermissionDecl(yypvt[-4].secAct, yypvt[-3].token, yypvt[-1].pair); } break; -case 719: + { PASM->AddPermissionDecl((yyvsp[-4].secAct), (yyvsp[-3].token), (yyvsp[-1].pair)); } +#line 7964 "asmparse.cpp" + break; + + case 720: /* secDecl: _PERMISSION secAction typeSpec '=' '{' customBlobDescr '}' */ #line 1791 "asmparse.y" -{ PASM->AddPermissionDecl(yypvt[-5].secAct, yypvt[-4].token, yypvt[-1].binstr); } break; -case 720: + { PASM->AddPermissionDecl((yyvsp[-5].secAct), (yyvsp[-4].token), (yyvsp[-1].binstr)); } +#line 7970 "asmparse.cpp" + break; + + case 721: /* secDecl: _PERMISSION secAction typeSpec */ #line 1792 "asmparse.y" -{ PASM->AddPermissionDecl(yypvt[-1].secAct, yypvt[-0].token, (NVPair *)NULL); } break; -case 721: + { PASM->AddPermissionDecl((yyvsp[-1].secAct), (yyvsp[0].token), (NVPair *)NULL); } +#line 7976 "asmparse.cpp" + break; + + case 722: /* secDecl: psetHead bytes ')' */ #line 1793 "asmparse.y" -{ PASM->AddPermissionSetDecl(yypvt[-2].secAct, yypvt[-1].binstr); } break; -case 722: + { PASM->AddPermissionSetDecl((yyvsp[-2].secAct), (yyvsp[-1].binstr)); } +#line 7982 "asmparse.cpp" + break; + + case 723: /* secDecl: _PERMISSIONSET secAction compQstring */ #line 1795 "asmparse.y" -{ PASM->AddPermissionSetDecl(yypvt[-1].secAct,BinStrToUnicode(yypvt[-0].binstr,true));} break; -case 723: + { PASM->AddPermissionSetDecl((yyvsp[-1].secAct),BinStrToUnicode((yyvsp[0].binstr),true));} +#line 7988 "asmparse.cpp" + break; + + case 724: /* secDecl: _PERMISSIONSET secAction '=' '{' secAttrSetBlob '}' */ #line 1797 "asmparse.y" -{ BinStr* ret = new BinStr(); + { BinStr* ret = new BinStr(); ret->insertInt8('.'); corEmitInt(ret, nSecAttrBlobs); - ret->append(yypvt[-1].binstr); - PASM->AddPermissionSetDecl(yypvt[-4].secAct,ret); - nSecAttrBlobs = 0; } break; -case 724: + ret->append((yyvsp[-1].binstr)); + PASM->AddPermissionSetDecl((yyvsp[-4].secAct),ret); + nSecAttrBlobs = 0; } +#line 7999 "asmparse.cpp" + break; + + case 725: /* secAttrSetBlob: %empty */ #line 1805 "asmparse.y" -{ yyval.binstr = new BinStr(); nSecAttrBlobs = 0;} break; -case 725: + { (yyval.binstr) = new BinStr(); nSecAttrBlobs = 0;} +#line 8005 "asmparse.cpp" + break; + + case 726: /* secAttrSetBlob: secAttrBlob */ #line 1806 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; nSecAttrBlobs = 1; } break; -case 726: + { (yyval.binstr) = (yyvsp[0].binstr); nSecAttrBlobs = 1; } +#line 8011 "asmparse.cpp" + break; + + case 727: /* secAttrSetBlob: secAttrBlob ',' secAttrSetBlob */ #line 1807 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); nSecAttrBlobs++; } break; -case 727: + { (yyval.binstr) = (yyvsp[-2].binstr); (yyval.binstr)->append((yyvsp[0].binstr)); nSecAttrBlobs++; } +#line 8017 "asmparse.cpp" + break; + + case 728: /* secAttrBlob: typeSpec '=' '{' customBlobNVPairs '}' */ #line 1811 "asmparse.y" -{ yyval.binstr = PASM->EncodeSecAttr(PASM->ReflectionNotation(yypvt[-4].token),yypvt[-1].binstr,nCustomBlobNVPairs); - nCustomBlobNVPairs = 0; } break; -case 728: + { (yyval.binstr) = PASM->EncodeSecAttr(PASM->ReflectionNotation((yyvsp[-4].token)),(yyvsp[-1].binstr),nCustomBlobNVPairs); + nCustomBlobNVPairs = 0; } +#line 8024 "asmparse.cpp" + break; + + case 729: /* secAttrBlob: CLASS_ SQSTRING '=' '{' customBlobNVPairs '}' */ #line 1814 "asmparse.y" -{ yyval.binstr = PASM->EncodeSecAttr(yypvt[-4].string,yypvt[-1].binstr,nCustomBlobNVPairs); - nCustomBlobNVPairs = 0; } break; -case 729: + { (yyval.binstr) = PASM->EncodeSecAttr((yyvsp[-4].string),(yyvsp[-1].binstr),nCustomBlobNVPairs); + nCustomBlobNVPairs = 0; } +#line 8031 "asmparse.cpp" + break; + + case 730: /* psetHead: _PERMISSIONSET secAction '=' '(' */ #line 1818 "asmparse.y" -{ yyval.secAct = yypvt[-2].secAct; bParsingByteArray = TRUE; } break; -case 730: + { (yyval.secAct) = (yyvsp[-2].secAct); bParsingByteArray = TRUE; } +#line 8037 "asmparse.cpp" + break; + + case 731: /* psetHead: _PERMISSIONSET secAction BYTEARRAY_ '(' */ #line 1820 "asmparse.y" -{ yyval.secAct = yypvt[-2].secAct; bParsingByteArray = TRUE; } break; -case 731: + { (yyval.secAct) = (yyvsp[-2].secAct); bParsingByteArray = TRUE; } +#line 8043 "asmparse.cpp" + break; + + case 732: /* nameValPairs: nameValPair */ #line 1823 "asmparse.y" -{ yyval.pair = yypvt[-0].pair; } break; -case 732: + { (yyval.pair) = (yyvsp[0].pair); } +#line 8049 "asmparse.cpp" + break; + + case 733: /* nameValPairs: nameValPair ',' nameValPairs */ #line 1824 "asmparse.y" -{ yyval.pair = yypvt[-2].pair->Concat(yypvt[-0].pair); } break; -case 733: + { (yyval.pair) = (yyvsp[-2].pair)->Concat((yyvsp[0].pair)); } +#line 8055 "asmparse.cpp" + break; + + case 734: /* nameValPair: compQstring '=' caValue */ #line 1827 "asmparse.y" -{ yypvt[-2].binstr->appendInt8(0); yyval.pair = new NVPair(yypvt[-2].binstr, yypvt[-0].binstr); } break; -case 734: + { (yyvsp[-2].binstr)->appendInt8(0); (yyval.pair) = new NVPair((yyvsp[-2].binstr), (yyvsp[0].binstr)); } +#line 8061 "asmparse.cpp" + break; + + case 735: /* truefalse: TRUE_ */ #line 1830 "asmparse.y" -{ yyval.int32 = 1; } break; -case 735: + { (yyval.int32) = 1; } +#line 8067 "asmparse.cpp" + break; + + case 736: /* truefalse: FALSE_ */ #line 1831 "asmparse.y" -{ yyval.int32 = 0; } break; -case 736: + { (yyval.int32) = 0; } +#line 8073 "asmparse.cpp" + break; + + case 737: /* caValue: truefalse */ #line 1834 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_BOOLEAN); - yyval.binstr->appendInt8(yypvt[-0].int32); } break; -case 737: + { (yyval.binstr) = new BinStr(); + (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_BOOLEAN); + (yyval.binstr)->appendInt8((yyvsp[0].int32)); } +#line 8081 "asmparse.cpp" + break; + + case 738: /* caValue: int32 */ #line 1837 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_I4); - yyval.binstr->appendInt32(yypvt[-0].int32); } break; -case 738: + { (yyval.binstr) = new BinStr(); + (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_I4); + (yyval.binstr)->appendInt32((yyvsp[0].int32)); } +#line 8089 "asmparse.cpp" + break; + + case 739: /* caValue: INT32_ '(' int32 ')' */ #line 1840 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_I4); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 739: + { (yyval.binstr) = new BinStr(); + (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_I4); + (yyval.binstr)->appendInt32((yyvsp[-1].int32)); } +#line 8097 "asmparse.cpp" + break; + + case 740: /* caValue: compQstring */ #line 1843 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_STRING); - yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; - yyval.binstr->appendInt8(0); } break; -case 740: + { (yyval.binstr) = new BinStr(); + (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_STRING); + (yyval.binstr)->append((yyvsp[0].binstr)); delete (yyvsp[0].binstr); + (yyval.binstr)->appendInt8(0); } +#line 8106 "asmparse.cpp" + break; + + case 741: /* caValue: className '(' INT8_ ':' int32 ')' */ #line 1847 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); - char* sz = PASM->ReflectionNotation(yypvt[-5].token); - strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); - yyval.binstr->appendInt8(1); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 741: + { (yyval.binstr) = new BinStr(); + (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation((yyvsp[-5].token)); + strcpy_s((char *)(yyval.binstr)->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + (yyval.binstr)->appendInt8(1); + (yyval.binstr)->appendInt32((yyvsp[-1].int32)); } +#line 8117 "asmparse.cpp" + break; + + case 742: /* caValue: className '(' INT16_ ':' int32 ')' */ #line 1853 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); - char* sz = PASM->ReflectionNotation(yypvt[-5].token); - strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); - yyval.binstr->appendInt8(2); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 742: + { (yyval.binstr) = new BinStr(); + (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation((yyvsp[-5].token)); + strcpy_s((char *)(yyval.binstr)->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + (yyval.binstr)->appendInt8(2); + (yyval.binstr)->appendInt32((yyvsp[-1].int32)); } +#line 8128 "asmparse.cpp" + break; + + case 743: /* caValue: className '(' INT32_ ':' int32 ')' */ #line 1859 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); - char* sz = PASM->ReflectionNotation(yypvt[-5].token); - strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); - yyval.binstr->appendInt8(4); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 743: + { (yyval.binstr) = new BinStr(); + (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation((yyvsp[-5].token)); + strcpy_s((char *)(yyval.binstr)->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + (yyval.binstr)->appendInt8(4); + (yyval.binstr)->appendInt32((yyvsp[-1].int32)); } +#line 8139 "asmparse.cpp" + break; + + case 744: /* caValue: className '(' int32 ')' */ #line 1865 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); - char* sz = PASM->ReflectionNotation(yypvt[-3].token); - strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); - yyval.binstr->appendInt8(4); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 744: + { (yyval.binstr) = new BinStr(); + (yyval.binstr)->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation((yyvsp[-3].token)); + strcpy_s((char *)(yyval.binstr)->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + (yyval.binstr)->appendInt8(4); + (yyval.binstr)->appendInt32((yyvsp[-1].int32)); } +#line 8150 "asmparse.cpp" + break; + + case 745: /* secAction: REQUEST_ */ #line 1873 "asmparse.y" -{ yyval.secAct = dclRequest; } break; -case 745: + { (yyval.secAct) = dclRequest; } +#line 8156 "asmparse.cpp" + break; + + case 746: /* secAction: DEMAND_ */ #line 1874 "asmparse.y" -{ yyval.secAct = dclDemand; } break; -case 746: + { (yyval.secAct) = dclDemand; } +#line 8162 "asmparse.cpp" + break; + + case 747: /* secAction: ASSERT_ */ #line 1875 "asmparse.y" -{ yyval.secAct = dclAssert; } break; -case 747: + { (yyval.secAct) = dclAssert; } +#line 8168 "asmparse.cpp" + break; + + case 748: /* secAction: DENY_ */ #line 1876 "asmparse.y" -{ yyval.secAct = dclDeny; } break; -case 748: + { (yyval.secAct) = dclDeny; } +#line 8174 "asmparse.cpp" + break; + + case 749: /* secAction: PERMITONLY_ */ #line 1877 "asmparse.y" -{ yyval.secAct = dclPermitOnly; } break; -case 749: + { (yyval.secAct) = dclPermitOnly; } +#line 8180 "asmparse.cpp" + break; + + case 750: /* secAction: LINKCHECK_ */ #line 1878 "asmparse.y" -{ yyval.secAct = dclLinktimeCheck; } break; -case 750: + { (yyval.secAct) = dclLinktimeCheck; } +#line 8186 "asmparse.cpp" + break; + + case 751: /* secAction: INHERITCHECK_ */ #line 1879 "asmparse.y" -{ yyval.secAct = dclInheritanceCheck; } break; -case 751: + { (yyval.secAct) = dclInheritanceCheck; } +#line 8192 "asmparse.cpp" + break; + + case 752: /* secAction: REQMIN_ */ #line 1880 "asmparse.y" -{ yyval.secAct = dclRequestMinimum; } break; -case 752: + { (yyval.secAct) = dclRequestMinimum; } +#line 8198 "asmparse.cpp" + break; + + case 753: /* secAction: REQOPT_ */ #line 1881 "asmparse.y" -{ yyval.secAct = dclRequestOptional; } break; -case 753: + { (yyval.secAct) = dclRequestOptional; } +#line 8204 "asmparse.cpp" + break; + + case 754: /* secAction: REQREFUSE_ */ #line 1882 "asmparse.y" -{ yyval.secAct = dclRequestRefuse; } break; -case 754: + { (yyval.secAct) = dclRequestRefuse; } +#line 8210 "asmparse.cpp" + break; + + case 755: /* secAction: PREJITGRANT_ */ #line 1883 "asmparse.y" -{ yyval.secAct = dclPrejitGrant; } break; -case 755: + { (yyval.secAct) = dclPrejitGrant; } +#line 8216 "asmparse.cpp" + break; + + case 756: /* secAction: PREJITDENY_ */ #line 1884 "asmparse.y" -{ yyval.secAct = dclPrejitDenied; } break; -case 756: + { (yyval.secAct) = dclPrejitDenied; } +#line 8222 "asmparse.cpp" + break; + + case 757: /* secAction: NONCASDEMAND_ */ #line 1885 "asmparse.y" -{ yyval.secAct = dclNonCasDemand; } break; -case 757: + { (yyval.secAct) = dclNonCasDemand; } +#line 8228 "asmparse.cpp" + break; + + case 758: /* secAction: NONCASLINKDEMAND_ */ #line 1886 "asmparse.y" -{ yyval.secAct = dclNonCasLinkDemand; } break; -case 758: + { (yyval.secAct) = dclNonCasLinkDemand; } +#line 8234 "asmparse.cpp" + break; + + case 759: /* secAction: NONCASINHERITANCE_ */ #line 1887 "asmparse.y" -{ yyval.secAct = dclNonCasInheritance; } break; -case 759: + { (yyval.secAct) = dclNonCasInheritance; } +#line 8240 "asmparse.cpp" + break; + + case 760: /* esHead: _LINE */ #line 1891 "asmparse.y" -{ PASM->ResetLineNumbers(); nCurrPC = PASM->m_CurPC; PENV->bExternSource = TRUE; PENV->bExternSourceAutoincrement = FALSE; } break; -case 760: + { PASM->ResetLineNumbers(); nCurrPC = PASM->m_CurPC; PENV->bExternSource = TRUE; PENV->bExternSourceAutoincrement = FALSE; } +#line 8246 "asmparse.cpp" + break; + + case 761: /* esHead: P_LINE */ #line 1892 "asmparse.y" -{ PASM->ResetLineNumbers(); nCurrPC = PASM->m_CurPC; PENV->bExternSource = TRUE; PENV->bExternSourceAutoincrement = TRUE; } break; -case 761: + { PASM->ResetLineNumbers(); nCurrPC = PASM->m_CurPC; PENV->bExternSource = TRUE; PENV->bExternSourceAutoincrement = TRUE; } +#line 8252 "asmparse.cpp" + break; + + case 762: /* extSourceSpec: esHead int32 SQSTRING */ #line 1895 "asmparse.y" -{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-1].int32; + { PENV->nExtLine = PENV->nExtLineEnd = (yyvsp[-1].int32); PENV->nExtCol = 0; PENV->nExtColEnd = static_cast(-1); - PASM->SetSourceFileName(yypvt[-0].string);} break; -case 762: + PASM->SetSourceFileName((yyvsp[0].string));} +#line 8260 "asmparse.cpp" + break; + + case 763: /* extSourceSpec: esHead int32 */ #line 1898 "asmparse.y" -{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-0].int32; - PENV->nExtCol = 0; PENV->nExtColEnd = static_cast(-1); } break; -case 763: + { PENV->nExtLine = PENV->nExtLineEnd = (yyvsp[0].int32); + PENV->nExtCol = 0; PENV->nExtColEnd = static_cast(-1); } +#line 8267 "asmparse.cpp" + break; + + case 764: /* extSourceSpec: esHead int32 ':' int32 SQSTRING */ #line 1900 "asmparse.y" -{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-3].int32; - PENV->nExtCol=yypvt[-1].int32; PENV->nExtColEnd = static_cast(-1); - PASM->SetSourceFileName(yypvt[-0].string);} break; -case 764: + { PENV->nExtLine = PENV->nExtLineEnd = (yyvsp[-3].int32); + PENV->nExtCol=(yyvsp[-1].int32); PENV->nExtColEnd = static_cast(-1); + PASM->SetSourceFileName((yyvsp[0].string));} +#line 8275 "asmparse.cpp" + break; + + case 765: /* extSourceSpec: esHead int32 ':' int32 */ #line 1903 "asmparse.y" -{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-2].int32; - PENV->nExtCol=yypvt[-0].int32; PENV->nExtColEnd = static_cast(-1);} break; -case 765: + { PENV->nExtLine = PENV->nExtLineEnd = (yyvsp[-2].int32); + PENV->nExtCol=(yyvsp[0].int32); PENV->nExtColEnd = static_cast(-1);} +#line 8282 "asmparse.cpp" + break; + + case 766: /* extSourceSpec: esHead int32 ':' int32 ',' int32 SQSTRING */ #line 1906 "asmparse.y" -{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-5].int32; - PENV->nExtCol=yypvt[-3].int32; PENV->nExtColEnd = yypvt[-1].int32; - PASM->SetSourceFileName(yypvt[-0].string);} break; -case 766: + { PENV->nExtLine = PENV->nExtLineEnd = (yyvsp[-5].int32); + PENV->nExtCol=(yyvsp[-3].int32); PENV->nExtColEnd = (yyvsp[-1].int32); + PASM->SetSourceFileName((yyvsp[0].string));} +#line 8290 "asmparse.cpp" + break; + + case 767: /* extSourceSpec: esHead int32 ':' int32 ',' int32 */ #line 1910 "asmparse.y" -{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-4].int32; - PENV->nExtCol=yypvt[-2].int32; PENV->nExtColEnd = yypvt[-0].int32; } break; -case 767: + { PENV->nExtLine = PENV->nExtLineEnd = (yyvsp[-4].int32); + PENV->nExtCol=(yyvsp[-2].int32); PENV->nExtColEnd = (yyvsp[0].int32); } +#line 8297 "asmparse.cpp" + break; + + case 768: /* extSourceSpec: esHead int32 ',' int32 ':' int32 SQSTRING */ #line 1913 "asmparse.y" -{ PENV->nExtLine = yypvt[-5].int32; PENV->nExtLineEnd = yypvt[-3].int32; - PENV->nExtCol=yypvt[-1].int32; PENV->nExtColEnd = static_cast(-1); - PASM->SetSourceFileName(yypvt[-0].string);} break; -case 768: + { PENV->nExtLine = (yyvsp[-5].int32); PENV->nExtLineEnd = (yyvsp[-3].int32); + PENV->nExtCol=(yyvsp[-1].int32); PENV->nExtColEnd = static_cast(-1); + PASM->SetSourceFileName((yyvsp[0].string));} +#line 8305 "asmparse.cpp" + break; + + case 769: /* extSourceSpec: esHead int32 ',' int32 ':' int32 */ #line 1917 "asmparse.y" -{ PENV->nExtLine = yypvt[-4].int32; PENV->nExtLineEnd = yypvt[-2].int32; - PENV->nExtCol=yypvt[-0].int32; PENV->nExtColEnd = static_cast(-1); } break; -case 769: + { PENV->nExtLine = (yyvsp[-4].int32); PENV->nExtLineEnd = (yyvsp[-2].int32); + PENV->nExtCol=(yyvsp[0].int32); PENV->nExtColEnd = static_cast(-1); } +#line 8312 "asmparse.cpp" + break; + + case 770: /* extSourceSpec: esHead int32 ',' int32 ':' int32 ',' int32 SQSTRING */ #line 1920 "asmparse.y" -{ PENV->nExtLine = yypvt[-7].int32; PENV->nExtLineEnd = yypvt[-5].int32; - PENV->nExtCol=yypvt[-3].int32; PENV->nExtColEnd = yypvt[-1].int32; - PASM->SetSourceFileName(yypvt[-0].string);} break; -case 770: + { PENV->nExtLine = (yyvsp[-7].int32); PENV->nExtLineEnd = (yyvsp[-5].int32); + PENV->nExtCol=(yyvsp[-3].int32); PENV->nExtColEnd = (yyvsp[-1].int32); + PASM->SetSourceFileName((yyvsp[0].string));} +#line 8320 "asmparse.cpp" + break; + + case 771: /* extSourceSpec: esHead int32 ',' int32 ':' int32 ',' int32 */ #line 1924 "asmparse.y" -{ PENV->nExtLine = yypvt[-6].int32; PENV->nExtLineEnd = yypvt[-4].int32; - PENV->nExtCol=yypvt[-2].int32; PENV->nExtColEnd = yypvt[-0].int32; } break; -case 771: + { PENV->nExtLine = (yyvsp[-6].int32); PENV->nExtLineEnd = (yyvsp[-4].int32); + PENV->nExtCol=(yyvsp[-2].int32); PENV->nExtColEnd = (yyvsp[0].int32); } +#line 8327 "asmparse.cpp" + break; + + case 772: /* extSourceSpec: esHead int32 QSTRING */ #line 1926 "asmparse.y" -{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-1].int32 - 1; + { PENV->nExtLine = PENV->nExtLineEnd = (yyvsp[-1].int32) - 1; PENV->nExtCol = 0; PENV->nExtColEnd = static_cast(-1); - PASM->SetSourceFileName(yypvt[-0].binstr);} break; -case 772: + PASM->SetSourceFileName((yyvsp[0].binstr));} +#line 8335 "asmparse.cpp" + break; + + case 773: /* fileDecl: _FILE fileAttr dottedName fileEntry hashHead bytes ')' fileEntry */ #line 1933 "asmparse.y" -{ PASMM->AddFile(yypvt[-5].string, yypvt[-6].fileAttr|yypvt[-4].fileAttr|yypvt[-0].fileAttr, yypvt[-2].binstr); } break; -case 773: + { PASMM->AddFile((yyvsp[-5].string), (yyvsp[-6].fileAttr)|(yyvsp[-4].fileAttr)|(yyvsp[0].fileAttr), (yyvsp[-2].binstr)); } +#line 8341 "asmparse.cpp" + break; + + case 774: /* fileDecl: _FILE fileAttr dottedName fileEntry */ #line 1934 "asmparse.y" -{ PASMM->AddFile(yypvt[-1].string, yypvt[-2].fileAttr|yypvt[-0].fileAttr, NULL); } break; -case 774: + { PASMM->AddFile((yyvsp[-1].string), (yyvsp[-2].fileAttr)|(yyvsp[0].fileAttr), NULL); } +#line 8347 "asmparse.cpp" + break; + + case 775: /* fileAttr: %empty */ #line 1937 "asmparse.y" -{ yyval.fileAttr = (CorFileFlags) 0; } break; -case 775: + { (yyval.fileAttr) = (CorFileFlags) 0; } +#line 8353 "asmparse.cpp" + break; + + case 776: /* fileAttr: fileAttr NOMETADATA_ */ #line 1938 "asmparse.y" -{ yyval.fileAttr = (CorFileFlags) (yypvt[-1].fileAttr | ffContainsNoMetaData); } break; -case 776: + { (yyval.fileAttr) = (CorFileFlags) ((yyvsp[-1].fileAttr) | ffContainsNoMetaData); } +#line 8359 "asmparse.cpp" + break; + + case 777: /* fileEntry: %empty */ #line 1941 "asmparse.y" -{ yyval.fileAttr = (CorFileFlags) 0; } break; -case 777: + { (yyval.fileAttr) = (CorFileFlags) 0; } +#line 8365 "asmparse.cpp" + break; + + case 778: /* fileEntry: _ENTRYPOINT */ #line 1942 "asmparse.y" -{ yyval.fileAttr = (CorFileFlags) 0x80000000; } break; -case 778: + { (yyval.fileAttr) = (CorFileFlags) 0x80000000; } +#line 8371 "asmparse.cpp" + break; + + case 779: /* hashHead: _HASH '=' '(' */ #line 1945 "asmparse.y" -{ bParsingByteArray = TRUE; } break; -case 779: + { bParsingByteArray = TRUE; } +#line 8377 "asmparse.cpp" + break; + + case 780: /* assemblyHead: _ASSEMBLY asmAttr dottedName */ #line 1948 "asmparse.y" -{ PASMM->StartAssembly(yypvt[-0].string, NULL, (DWORD)yypvt[-1].asmAttr, FALSE); } break; -case 780: + { PASMM->StartAssembly((yyvsp[0].string), NULL, (DWORD)(yyvsp[-1].asmAttr), FALSE); } +#line 8383 "asmparse.cpp" + break; + + case 781: /* asmAttr: %empty */ #line 1951 "asmparse.y" -{ yyval.asmAttr = (CorAssemblyFlags) 0; } break; -case 781: + { (yyval.asmAttr) = (CorAssemblyFlags) 0; } +#line 8389 "asmparse.cpp" + break; + + case 782: /* asmAttr: asmAttr RETARGETABLE_ */ #line 1952 "asmparse.y" -{ yyval.asmAttr = (CorAssemblyFlags) (yypvt[-1].asmAttr | afRetargetable); } break; -case 782: + { (yyval.asmAttr) = (CorAssemblyFlags) ((yyvsp[-1].asmAttr) | afRetargetable); } +#line 8395 "asmparse.cpp" + break; + + case 783: /* asmAttr: asmAttr WINDOWSRUNTIME_ */ #line 1953 "asmparse.y" -{ yyval.asmAttr = (CorAssemblyFlags) (yypvt[-1].asmAttr | afContentType_WindowsRuntime); } break; -case 783: + { (yyval.asmAttr) = (CorAssemblyFlags) ((yyvsp[-1].asmAttr) | afContentType_WindowsRuntime); } +#line 8401 "asmparse.cpp" + break; + + case 784: /* asmAttr: asmAttr NOPLATFORM_ */ #line 1954 "asmparse.y" -{ yyval.asmAttr = (CorAssemblyFlags) (yypvt[-1].asmAttr | afPA_NoPlatform); } break; -case 784: + { (yyval.asmAttr) = (CorAssemblyFlags) ((yyvsp[-1].asmAttr) | afPA_NoPlatform); } +#line 8407 "asmparse.cpp" + break; + + case 785: /* asmAttr: asmAttr LEGACY_ LIBRARY_ */ #line 1955 "asmparse.y" -{ yyval.asmAttr = yypvt[-2].asmAttr; } break; -case 785: + { (yyval.asmAttr) = (yyvsp[-2].asmAttr); } +#line 8413 "asmparse.cpp" + break; + + case 786: /* asmAttr: asmAttr CIL_ */ #line 1956 "asmparse.y" -{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_MSIL); } break; -case 786: + { SET_PA((yyval.asmAttr),(yyvsp[-1].asmAttr),afPA_MSIL); } +#line 8419 "asmparse.cpp" + break; + + case 787: /* asmAttr: asmAttr X86_ */ #line 1957 "asmparse.y" -{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_x86); } break; -case 787: + { SET_PA((yyval.asmAttr),(yyvsp[-1].asmAttr),afPA_x86); } +#line 8425 "asmparse.cpp" + break; + + case 788: /* asmAttr: asmAttr AMD64_ */ #line 1958 "asmparse.y" -{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_AMD64); } break; -case 788: + { SET_PA((yyval.asmAttr),(yyvsp[-1].asmAttr),afPA_AMD64); } +#line 8431 "asmparse.cpp" + break; + + case 789: /* asmAttr: asmAttr ARM_ */ #line 1959 "asmparse.y" -{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_ARM); } break; -case 789: + { SET_PA((yyval.asmAttr),(yyvsp[-1].asmAttr),afPA_ARM); } +#line 8437 "asmparse.cpp" + break; + + case 790: /* asmAttr: asmAttr ARM64_ */ #line 1960 "asmparse.y" -{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_ARM64); } break; -case 792: + { SET_PA((yyval.asmAttr),(yyvsp[-1].asmAttr),afPA_ARM64); } +#line 8443 "asmparse.cpp" + break; + + case 793: /* assemblyDecl: _HASH ALGORITHM_ int32 */ #line 1967 "asmparse.y" -{ PASMM->SetAssemblyHashAlg(yypvt[-0].int32); } break; -case 795: + { PASMM->SetAssemblyHashAlg((yyvsp[0].int32)); } +#line 8449 "asmparse.cpp" + break; + + case 796: /* intOrWildcard: int32 */ #line 1972 "asmparse.y" -{ yyval.int32 = yypvt[-0].int32; } break; -case 796: + { (yyval.int32) = (yyvsp[0].int32); } +#line 8455 "asmparse.cpp" + break; + + case 797: /* intOrWildcard: '*' */ #line 1973 "asmparse.y" -{ yyval.int32 = 0xFFFF; } break; -case 797: + { (yyval.int32) = 0xFFFF; } +#line 8461 "asmparse.cpp" + break; + + case 798: /* asmOrRefDecl: publicKeyHead bytes ')' */ #line 1976 "asmparse.y" -{ PASMM->SetAssemblyPublicKey(yypvt[-1].binstr); } break; -case 798: + { PASMM->SetAssemblyPublicKey((yyvsp[-1].binstr)); } +#line 8467 "asmparse.cpp" + break; + + case 799: /* asmOrRefDecl: _VER intOrWildcard ':' intOrWildcard ':' intOrWildcard ':' intOrWildcard */ #line 1978 "asmparse.y" -{ PASMM->SetAssemblyVer((USHORT)yypvt[-6].int32, (USHORT)yypvt[-4].int32, (USHORT)yypvt[-2].int32, (USHORT)yypvt[-0].int32); } break; -case 799: + { PASMM->SetAssemblyVer((USHORT)(yyvsp[-6].int32), (USHORT)(yyvsp[-4].int32), (USHORT)(yyvsp[-2].int32), (USHORT)(yyvsp[0].int32)); } +#line 8473 "asmparse.cpp" + break; + + case 800: /* asmOrRefDecl: _LOCALE compQstring */ #line 1979 "asmparse.y" -{ yypvt[-0].binstr->appendInt8(0); PASMM->SetAssemblyLocale(yypvt[-0].binstr,TRUE); } break; -case 800: + { (yyvsp[0].binstr)->appendInt8(0); PASMM->SetAssemblyLocale((yyvsp[0].binstr),TRUE); } +#line 8479 "asmparse.cpp" + break; + + case 801: /* asmOrRefDecl: localeHead bytes ')' */ #line 1980 "asmparse.y" -{ PASMM->SetAssemblyLocale(yypvt[-1].binstr,FALSE); } break; -case 803: + { PASMM->SetAssemblyLocale((yyvsp[-1].binstr),FALSE); } +#line 8485 "asmparse.cpp" + break; + + case 804: /* publicKeyHead: _PUBLICKEY '=' '(' */ #line 1985 "asmparse.y" -{ bParsingByteArray = TRUE; } break; -case 804: + { bParsingByteArray = TRUE; } +#line 8491 "asmparse.cpp" + break; + + case 805: /* publicKeyTokenHead: _PUBLICKEYTOKEN '=' '(' */ #line 1988 "asmparse.y" -{ bParsingByteArray = TRUE; } break; -case 805: + { bParsingByteArray = TRUE; } +#line 8497 "asmparse.cpp" + break; + + case 806: /* localeHead: _LOCALE '=' '(' */ #line 1991 "asmparse.y" -{ bParsingByteArray = TRUE; } break; -case 806: + { bParsingByteArray = TRUE; } +#line 8503 "asmparse.cpp" + break; + + case 807: /* assemblyRefHead: _ASSEMBLY EXTERN_ asmAttr dottedName */ #line 1995 "asmparse.y" -{ PASMM->StartAssembly(yypvt[-0].string, NULL, yypvt[-1].asmAttr, TRUE); } break; -case 807: + { PASMM->StartAssembly((yyvsp[0].string), NULL, (yyvsp[-1].asmAttr), TRUE); } +#line 8509 "asmparse.cpp" + break; + + case 808: /* assemblyRefHead: _ASSEMBLY EXTERN_ asmAttr dottedName AS_ dottedName */ #line 1997 "asmparse.y" -{ PASMM->StartAssembly(yypvt[-2].string, yypvt[-0].string, yypvt[-3].asmAttr, TRUE); } break; -case 810: + { PASMM->StartAssembly((yyvsp[-2].string), (yyvsp[0].string), (yyvsp[-3].asmAttr), TRUE); } +#line 8515 "asmparse.cpp" + break; + + case 811: /* assemblyRefDecl: hashHead bytes ')' */ #line 2004 "asmparse.y" -{ PASMM->SetAssemblyHashBlob(yypvt[-1].binstr); } break; -case 812: + { PASMM->SetAssemblyHashBlob((yyvsp[-1].binstr)); } +#line 8521 "asmparse.cpp" + break; + + case 813: /* assemblyRefDecl: publicKeyTokenHead bytes ')' */ #line 2006 "asmparse.y" -{ PASMM->SetAssemblyPublicKeyToken(yypvt[-1].binstr); } break; -case 813: + { PASMM->SetAssemblyPublicKeyToken((yyvsp[-1].binstr)); } +#line 8527 "asmparse.cpp" + break; + + case 814: /* assemblyRefDecl: AUTO_ */ #line 2007 "asmparse.y" -{ PASMM->SetAssemblyAutodetect(); } break; -case 814: + { PASMM->SetAssemblyAutodetect(); } +#line 8533 "asmparse.cpp" + break; + + case 815: /* exptypeHead: _CLASS EXTERN_ exptAttr dottedName */ #line 2010 "asmparse.y" -{ PASMM->StartComType(yypvt[-0].string, yypvt[-1].exptAttr);} break; -case 815: + { PASMM->StartComType((yyvsp[0].string), (yyvsp[-1].exptAttr));} +#line 8539 "asmparse.cpp" + break; + + case 816: /* exportHead: _EXPORT exptAttr dottedName */ #line 2013 "asmparse.y" -{ PASMM->StartComType(yypvt[-0].string, yypvt[-1].exptAttr); } break; -case 816: + { PASMM->StartComType((yyvsp[0].string), (yyvsp[-1].exptAttr)); } +#line 8545 "asmparse.cpp" + break; + + case 817: /* exptAttr: %empty */ #line 2016 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) 0; } break; -case 817: + { (yyval.exptAttr) = (CorTypeAttr) 0; } +#line 8551 "asmparse.cpp" + break; + + case 818: /* exptAttr: exptAttr PRIVATE_ */ #line 2017 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-1].exptAttr | tdNotPublic); } break; -case 818: + { (yyval.exptAttr) = (CorTypeAttr) ((yyvsp[-1].exptAttr) | tdNotPublic); } +#line 8557 "asmparse.cpp" + break; + + case 819: /* exptAttr: exptAttr PUBLIC_ */ #line 2018 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-1].exptAttr | tdPublic); } break; -case 819: + { (yyval.exptAttr) = (CorTypeAttr) ((yyvsp[-1].exptAttr) | tdPublic); } +#line 8563 "asmparse.cpp" + break; + + case 820: /* exptAttr: exptAttr FORWARDER_ */ #line 2019 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-1].exptAttr | tdForwarder); } break; -case 820: + { (yyval.exptAttr) = (CorTypeAttr) ((yyvsp[-1].exptAttr) | tdForwarder); } +#line 8569 "asmparse.cpp" + break; + + case 821: /* exptAttr: exptAttr NESTED_ PUBLIC_ */ #line 2020 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedPublic); } break; -case 821: + { (yyval.exptAttr) = (CorTypeAttr) ((yyvsp[-2].exptAttr) | tdNestedPublic); } +#line 8575 "asmparse.cpp" + break; + + case 822: /* exptAttr: exptAttr NESTED_ PRIVATE_ */ #line 2021 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedPrivate); } break; -case 822: + { (yyval.exptAttr) = (CorTypeAttr) ((yyvsp[-2].exptAttr) | tdNestedPrivate); } +#line 8581 "asmparse.cpp" + break; + + case 823: /* exptAttr: exptAttr NESTED_ FAMILY_ */ #line 2022 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedFamily); } break; -case 823: + { (yyval.exptAttr) = (CorTypeAttr) ((yyvsp[-2].exptAttr) | tdNestedFamily); } +#line 8587 "asmparse.cpp" + break; + + case 824: /* exptAttr: exptAttr NESTED_ ASSEMBLY_ */ #line 2023 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedAssembly); } break; -case 824: + { (yyval.exptAttr) = (CorTypeAttr) ((yyvsp[-2].exptAttr) | tdNestedAssembly); } +#line 8593 "asmparse.cpp" + break; + + case 825: /* exptAttr: exptAttr NESTED_ FAMANDASSEM_ */ #line 2024 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedFamANDAssem); } break; -case 825: + { (yyval.exptAttr) = (CorTypeAttr) ((yyvsp[-2].exptAttr) | tdNestedFamANDAssem); } +#line 8599 "asmparse.cpp" + break; + + case 826: /* exptAttr: exptAttr NESTED_ FAMORASSEM_ */ #line 2025 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedFamORAssem); } break; -case 828: + { (yyval.exptAttr) = (CorTypeAttr) ((yyvsp[-2].exptAttr) | tdNestedFamORAssem); } +#line 8605 "asmparse.cpp" + break; + + case 829: /* exptypeDecl: _FILE dottedName */ #line 2032 "asmparse.y" -{ PASMM->SetComTypeFile(yypvt[-0].string); } break; -case 829: + { PASMM->SetComTypeFile((yyvsp[0].string)); } +#line 8611 "asmparse.cpp" + break; + + case 830: /* exptypeDecl: _CLASS EXTERN_ slashedName */ #line 2033 "asmparse.y" -{ PASMM->SetComTypeComType(yypvt[-0].string); } break; -case 830: + { PASMM->SetComTypeComType((yyvsp[0].string)); } +#line 8617 "asmparse.cpp" + break; + + case 831: /* exptypeDecl: _ASSEMBLY EXTERN_ dottedName */ #line 2034 "asmparse.y" -{ PASMM->SetComTypeAsmRef(yypvt[-0].string); } break; -case 831: + { PASMM->SetComTypeAsmRef((yyvsp[0].string)); } +#line 8623 "asmparse.cpp" + break; + + case 832: /* exptypeDecl: MDTOKEN_ '(' int32 ')' */ #line 2035 "asmparse.y" -{ if(!PASMM->SetComTypeImplementationTok(yypvt[-1].int32)) - PASM->report->error("Invalid implementation of exported type\n"); } break; -case 832: + { if(!PASMM->SetComTypeImplementationTok((yyvsp[-1].int32))) + PASM->report->error("Invalid implementation of exported type\n"); } +#line 8630 "asmparse.cpp" + break; + + case 833: /* exptypeDecl: _CLASS int32 */ #line 2037 "asmparse.y" -{ if(!PASMM->SetComTypeClassTok(yypvt[-0].int32)) - PASM->report->error("Invalid TypeDefID of exported type\n"); } break; -case 835: + { if(!PASMM->SetComTypeClassTok((yyvsp[0].int32))) + PASM->report->error("Invalid TypeDefID of exported type\n"); } +#line 8637 "asmparse.cpp" + break; + + case 836: /* manifestResHead: _MRESOURCE manresAttr dottedName */ #line 2043 "asmparse.y" -{ PASMM->StartManifestRes(yypvt[-0].string, yypvt[-0].string, yypvt[-1].manresAttr); } break; -case 836: + { PASMM->StartManifestRes((yyvsp[0].string), (yyvsp[0].string), (yyvsp[-1].manresAttr)); } +#line 8643 "asmparse.cpp" + break; + + case 837: /* manifestResHead: _MRESOURCE manresAttr dottedName AS_ dottedName */ #line 2045 "asmparse.y" -{ PASMM->StartManifestRes(yypvt[-2].string, yypvt[-0].string, yypvt[-3].manresAttr); } break; -case 837: + { PASMM->StartManifestRes((yyvsp[-2].string), (yyvsp[0].string), (yyvsp[-3].manresAttr)); } +#line 8649 "asmparse.cpp" + break; + + case 838: /* manresAttr: %empty */ #line 2048 "asmparse.y" -{ yyval.manresAttr = (CorManifestResourceFlags) 0; } break; -case 838: + { (yyval.manresAttr) = (CorManifestResourceFlags) 0; } +#line 8655 "asmparse.cpp" + break; + + case 839: /* manresAttr: manresAttr PUBLIC_ */ #line 2049 "asmparse.y" -{ yyval.manresAttr = (CorManifestResourceFlags) (yypvt[-1].manresAttr | mrPublic); } break; -case 839: + { (yyval.manresAttr) = (CorManifestResourceFlags) ((yyvsp[-1].manresAttr) | mrPublic); } +#line 8661 "asmparse.cpp" + break; + + case 840: /* manresAttr: manresAttr PRIVATE_ */ #line 2050 "asmparse.y" -{ yyval.manresAttr = (CorManifestResourceFlags) (yypvt[-1].manresAttr | mrPrivate); } break; -case 842: + { (yyval.manresAttr) = (CorManifestResourceFlags) ((yyvsp[-1].manresAttr) | mrPrivate); } +#line 8667 "asmparse.cpp" + break; + + case 843: /* manifestResDecl: _FILE dottedName AT_ int32 */ #line 2057 "asmparse.y" -{ PASMM->SetManifestResFile(yypvt[-2].string, (ULONG)yypvt[-0].int32); } break; -case 843: + { PASMM->SetManifestResFile((yyvsp[-2].string), (ULONG)(yyvsp[0].int32)); } +#line 8673 "asmparse.cpp" + break; + + case 844: /* manifestResDecl: _ASSEMBLY EXTERN_ dottedName */ #line 2058 "asmparse.y" -{ PASMM->SetManifestResAsmRef(yypvt[-0].string); } break;/* End of actions */ -#line 329 "F:\\NetFXDev1\\src\\tools\\devdiv\\amd64\\yypars.c" - } - } - goto yystack; /* stack new state and value */ - } -#pragma warning(default:102) + { PASMM->SetManifestResAsmRef((yyvsp[0].string)); } +#line 8679 "asmparse.cpp" + break; -#ifdef YYDUMP -YYLOCAL void YYNEAR YYPASCAL yydumpinfo(void) -{ - short stackindex; - short valindex; - - //dump yys - printf("short yys[%d] {\n", YYMAXDEPTH); - for (stackindex = 0; stackindex < YYMAXDEPTH; stackindex++){ - if (stackindex) - printf(", %s", stackindex % 10 ? "\0" : "\n"); - printf("%6d", yys[stackindex]); - } - printf("\n};\n"); - - //dump yyv - printf("YYSTYPE yyv[%d] {\n", YYMAXDEPTH); - for (valindex = 0; valindex < YYMAXDEPTH; valindex++){ - if (valindex) - printf(", %s", valindex % 5 ? "\0" : "\n"); - printf("%#*x", 3+sizeof(YYSTYPE), yyv[valindex]); - } - printf("\n};\n"); - } +#line 8683 "asmparse.cpp" + + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; + yyerror (YY_("syntax error")); + } + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; + ++yynerrs; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + /* Pop stack until we find a state that shifts the error token. */ + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYSYMBOL_YYerror; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + YY_ACCESSING_SYMBOL (yystate), yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturnlab; + + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturnlab; + + +/*-----------------------------------------------------------. +| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | +`-----------------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + goto yyreturnlab; + + +/*----------------------------------------------------------. +| yyreturnlab -- parsing is finished, clean up and return. | +`----------------------------------------------------------*/ +yyreturnlab: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + YY_ACCESSING_SYMBOL (+*yyssp), yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); #endif + + return yyresult; +} + +#line 2063 "asmparse.y" + + +#include "grammar_after.cpp" diff --git a/src/coreclr/ilasm/writer.cpp b/src/coreclr/ilasm/writer.cpp index 6f96b0bd632f..ca86a0d16ab2 100644 --- a/src/coreclr/ilasm/writer.cpp +++ b/src/coreclr/ilasm/writer.cpp @@ -34,6 +34,14 @@ HRESULT Assembler::InitMetaData() if (FAILED(hr)) goto exit; + if(m_wzMetadataVersion) + { + VARIANT optionValue; + V_VT(&optionValue) = VT_BSTR; + V_BSTR(&optionValue) = m_wzMetadataVersion; // IMetaDataDispenserEx does not require proper BSTR + hr = m_pDisp->SetOption(MetaDataRuntimeVersion, &optionValue); + } + hr = m_pDisp->DefineScope(CLSID_CorMetaDataRuntime, 0, IID_IMetaDataEmit3, (IUnknown **)&m_pEmitter); if (FAILED(hr)) @@ -131,7 +139,7 @@ HRESULT Assembler::CreateTLSDirectory() { } else { - DWORD sizeofptr = (DWORD)sizeof(__int64); + DWORD sizeofptr = (DWORD)sizeof(int64_t); DWORD sizeofdir = (DWORD)sizeof(IMAGE_TLS_DIRECTORY64); DWORD offsetofStartAddressOfRawData = (DWORD)offsetof(IMAGE_TLS_DIRECTORY64, StartAddressOfRawData); DWORD offsetofEndAddressOfRawData = (DWORD)offsetof(IMAGE_TLS_DIRECTORY64, EndAddressOfRawData); @@ -141,7 +149,7 @@ HRESULT Assembler::CreateTLSDirectory() { // Get memory for the TLS directory block,as well as a spot for callback chain IMAGE_TLS_DIRECTORY64* tlsDir; if(FAILED(hr=m_pCeeFileGen->GetSectionBlock(tlsDirSec, sizeofdir + sizeofptr, sizeofptr, (void**) &tlsDir))) return(hr); - __int64* callBackChain = (__int64*) &tlsDir[1]; + int64_t* callBackChain = (int64_t*) &tlsDir[1]; *callBackChain = 0; // Find out where the tls directory will end up @@ -530,7 +538,7 @@ DWORD Assembler::EmitExportStub(DWORD dwVTFSlotRVA) else { report->error("Unmanaged exports are not implemented for unknown platform"); - return NULL; + return 0; } // Addr must be aligned, not the stub! if (FAILED(m_pCeeFileGen->GetSectionDataLen (m_pILSection, &PEFileOffset))) return 0; @@ -1212,7 +1220,7 @@ HRESULT Assembler::CreatePEFile(_In_ __nullterminated WCHAR *pwzOutputFilename) { #define ELEMENT_TYPE_TYPEDEF (ELEMENT_TYPE_MAX+1) TypeDefDescr* pTDD; - unsigned __int8* pb; + uint8_t* pb; unsigned namesize; while((pTDD = m_TypeDefDList.POP())) { diff --git a/src/coreclr/ildasm/dasm.cpp b/src/coreclr/ildasm/dasm.cpp index da3aa514c0dc..4332ef7f756e 100644 --- a/src/coreclr/ildasm/dasm.cpp +++ b/src/coreclr/ildasm/dasm.cpp @@ -56,7 +56,7 @@ PELoader * g_pPELoader; void * g_pMetaData; unsigned g_cbMetaData; IMAGE_COR20_HEADER * g_CORHeader; -DynamicArray<__int32> *g_pPtrTags = NULL; //to keep track of all "ldptr" +DynamicArray *g_pPtrTags = NULL; //to keep track of all "ldptr" DynamicArray *g_pPtrSize= NULL; //to keep track of all "ldptr" int g_iPtrCount = 0; mdToken * g_cl_list = NULL; @@ -899,7 +899,7 @@ void DumpMscorlib(void* GUICookie) // Retrieve the type def properties as well, so that we can check a few more things about // the System.Object type // - if (SUCCEEDED(g_pPubImport->GetTypeDefProps(tkObjectTypeDef, NULL, NULL, 0, &dwClassAttrs, &tkExtends))) + if (SUCCEEDED(g_pPubImport->GetTypeDefProps(tkObjectTypeDef, NULL, 0, NULL, &dwClassAttrs, &tkExtends))) { bool bExtends = g_pPubImport->IsValidToken(tkExtends); bool isClass = ((dwClassAttrs & tdClassSemanticsMask) == tdClass); @@ -3538,7 +3538,7 @@ BOOL DumpMethod(mdToken FuncToken, const char *pszClassName, DWORD dwEntryPointT pComSig = NULL; } - if (cComSig == NULL) + if (cComSig == 0) { sprintf_s(szString, SZSTRING_SIZE, "%sERROR: method '%s' has no signature", g_szAsmCodeIndent, pszMemberName); printError(GUICookie, ERRORMSG(szString)); @@ -4010,7 +4010,7 @@ BOOL DumpField(mdToken FuncToken, const char *pszClassName,void *GUICookie, BOOL { pComSig = NULL; } - if (cComSig == NULL) + if (cComSig == 0) { char sz[2048]; sprintf_s(sz,2048,"%sERROR: field '%s' has no signature",g_szAsmCodeIndent,pszMemberName); @@ -5053,8 +5053,8 @@ void DumpVTables(IMAGE_COR20_HEADER *CORHeader, void* GUICookie) } else { - sprintf_s(szString,SZSTRING_SIZE,"// [0x%04x] (0x%16llx)", iSlot, VAL64(*(unsigned __int64 *) pSlot)); - pSlot += sizeof(unsigned __int64); + sprintf_s(szString,SZSTRING_SIZE,"// [0x%04x] (0x%16llx)", iSlot, VAL64(*(uint64_t *) pSlot)); + pSlot += sizeof(uint64_t); } printLine(GUICookie,szStr); @@ -5880,7 +5880,7 @@ IMetaDataTables *pITables = NULL; //ULONG sizeRec, count; //int size, size2; int metaSize = 0; -__int64 fTableSeen; +int64_t fTableSeen; inline void TableSeen(unsigned long n) { fTableSeen |= (I64(1) << n); } inline int IsTableSeen(unsigned long n) { return (fTableSeen & (I64(1) << n)) ? 1 : 0;} inline void TableSeenReset() { fTableSeen = 0;} @@ -6904,8 +6904,8 @@ void DumpVtable(void* GUICookie) } else { - szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %016I64X", VAL64(*(unsigned __int64 *)pSlot)); - pSlot += sizeof(unsigned __int64); + szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %016I64X", VAL64(*(uint64_t *)pSlot)); + pSlot += sizeof(uint64_t); } if (g_prVTableRef == NULL) { diff --git a/src/coreclr/ildasm/dis.cpp b/src/coreclr/ildasm/dis.cpp index 2ad1ecd2d200..91b878e3e19c 100644 --- a/src/coreclr/ildasm/dis.cpp +++ b/src/coreclr/ildasm/dis.cpp @@ -29,7 +29,7 @@ extern BOOL g_fInsertSourceLines; extern BOOL g_fTryInCode; extern BOOL g_fQuoteAllNames; extern BOOL g_fDumpTokens; -extern DynamicArray<__int32> *g_pPtrTags; //to keep track of all "ldptr" +extern DynamicArray *g_pPtrTags; //to keep track of all "ldptr" extern DynamicArray *g_pPtrSize; //to keep track of all "ldptr" extern int g_iPtrCount; static BOOL ConvToLiteral(__inout __nullterminated char* retBuff, const WCHAR* str, int cbStr); @@ -527,7 +527,7 @@ char* DumpDataPtr(__inout __nullterminated char* buffer, DWORD ptr, DWORD size) if(i < dwNumberOfSections) { // yes, the pointer points to real data int j; - for(j=0; (j < g_iPtrCount)&&((*g_pPtrTags)[j] != (__int32)ptr); j++); + for(j=0; (j < g_iPtrCount)&&((*g_pPtrTags)[j] != (int32_t)ptr); j++); if(j == g_iPtrCount) { if (g_pPtrSize == NULL) @@ -536,7 +536,7 @@ char* DumpDataPtr(__inout __nullterminated char* buffer, DWORD ptr, DWORD size) } if (g_pPtrTags == NULL) { - g_pPtrTags = new DynamicArray<__int32>; + g_pPtrTags = new DynamicArray; } (*g_pPtrSize)[g_iPtrCount] = size; @@ -727,8 +727,7 @@ void OpenScope(ISymUnmanagedScope *pIScope, char* DumpUnicodeString(void* GUICookie, __inout __nullterminated char* szString, _In_reads_(cbString) WCHAR* pszString, - ULONG cbString, - bool SwapString ) + ULONG cbString) { unsigned i,L; char* szStr=NULL, *szRet = NULL; @@ -750,8 +749,7 @@ char* DumpUnicodeString(void* GUICookie, #endif #if BIGENDIAN - if (SwapString) - SwapStringLength(pszString, cbString); + SwapStringLength(pszString, cbString); #endif // first, check for embedded zeros: @@ -782,7 +780,7 @@ char* DumpUnicodeString(void* GUICookie, strcat_s(szString,SZSTRING_SIZE," ("); #if BIGENDIAN - SwapStringLength(pszString, cbString); + SwapStringLength(pszString, cbString); #endif DumpByteArray(szString,(BYTE*)pszString,cbString*sizeof(WCHAR),GUICookie); szRet = &szString[strlen(szString)]; @@ -1528,14 +1526,14 @@ BOOL Disassemble(IMDInternalImport *pImport, BYTE *ILHeader, void *GUICookie, md case InlineI8: { - __int64 v = (__int64) pCode[PC] + - (((__int64) pCode[PC+1]) << 8) + - (((__int64) pCode[PC+2]) << 16) + - (((__int64) pCode[PC+3]) << 24) + - (((__int64) pCode[PC+4]) << 32) + - (((__int64) pCode[PC+5]) << 40) + - (((__int64) pCode[PC+6]) << 48) + - (((__int64) pCode[PC+7]) << 56); + int64_t v = (int64_t) pCode[PC] + + (((int64_t) pCode[PC+1]) << 8) + + (((int64_t) pCode[PC+2]) << 16) + + (((int64_t) pCode[PC+3]) << 24) + + (((int64_t) pCode[PC+4]) << 32) + + (((int64_t) pCode[PC+5]) << 40) + + (((int64_t) pCode[PC+6]) << 48) + + (((int64_t) pCode[PC+7]) << 56); if(g_fShowBytes) { @@ -1554,10 +1552,10 @@ BOOL Disassemble(IMDInternalImport *pImport, BYTE *ILHeader, void *GUICookie, md case ShortInlineR: { - __int32 v = (__int32) pCode[PC] + - (((__int32) pCode[PC+1]) << 8) + - (((__int32) pCode[PC+2]) << 16) + - (((__int32) pCode[PC+3]) << 24); + int32_t v = (int32_t) pCode[PC] + + (((int32_t) pCode[PC+1]) << 8) + + (((int32_t) pCode[PC+2]) << 16) + + (((int32_t) pCode[PC+3]) << 24); float f = (float&)v; @@ -1577,7 +1575,7 @@ BOOL Disassemble(IMDInternalImport *pImport, BYTE *ILHeader, void *GUICookie, md float fd = (float)atof(szf); // Must compare as underlying bytes, not floating point otherwise optimizer will // try to enregister and compare 80-bit precision number with 32-bit precision number!!!! - if(((__int32&)fd == v)&&!IsSpecialNumber(szf)) + if(((int32_t&)fd == v)&&!IsSpecialNumber(szf)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName, szf); else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s (%2.2X %2.2X %2.2X %2.2X)", @@ -1588,14 +1586,14 @@ BOOL Disassemble(IMDInternalImport *pImport, BYTE *ILHeader, void *GUICookie, md case InlineR: { - __int64 v = (__int64) pCode[PC] + - (((__int64) pCode[PC+1]) << 8) + - (((__int64) pCode[PC+2]) << 16) + - (((__int64) pCode[PC+3]) << 24) + - (((__int64) pCode[PC+4]) << 32) + - (((__int64) pCode[PC+5]) << 40) + - (((__int64) pCode[PC+6]) << 48) + - (((__int64) pCode[PC+7]) << 56); + int64_t v = (int64_t) pCode[PC] + + (((int64_t) pCode[PC+1]) << 8) + + (((int64_t) pCode[PC+2]) << 16) + + (((int64_t) pCode[PC+3]) << 24) + + (((int64_t) pCode[PC+4]) << 32) + + (((int64_t) pCode[PC+5]) << 40) + + (((int64_t) pCode[PC+6]) << 48) + + (((int64_t) pCode[PC+7]) << 56); double d = (double&)v; @@ -1616,7 +1614,7 @@ BOOL Disassemble(IMDInternalImport *pImport, BYTE *ILHeader, void *GUICookie, md double df = strtod(szf, &pch); //atof(szf); // Must compare as underlying bytes, not floating point otherwise optimizer will // try to enregister and compare 80-bit precision number with 64-bit precision number!!!! - if (((__int64&)df == v)&&!IsSpecialNumber(szf)) + if (((int64_t&)df == v)&&!IsSpecialNumber(szf)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName, szf); else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), @@ -2546,7 +2544,7 @@ void PrettyPrintToken(__inout __nullterminated char* szString, mdToken tk, IMDIn } if (pszString != NULL) { - DumpUnicodeString(GUICookie,szString,(WCHAR *)pszString,cbString, true); + DumpUnicodeString(GUICookie,szString,(WCHAR *)pszString,cbString); } else { diff --git a/src/coreclr/ildasm/dis.h b/src/coreclr/ildasm/dis.h index 6aef96aefcfa..1b60192a60b8 100644 --- a/src/coreclr/ildasm/dis.h +++ b/src/coreclr/ildasm/dis.h @@ -78,8 +78,7 @@ void DumpVtable(void* GUICookie); char* DumpUnicodeString(void* GUICookie, __inout __nullterminated char* szString, _In_reads_(cbString) WCHAR* pszString, - ULONG cbString, - bool SwapString = false); + ULONG cbString); void TokenSigInit(IMDInternalImport *pImport); void TokenSigDelete(); diff --git a/src/coreclr/ildasm/windasm.cpp b/src/coreclr/ildasm/windasm.cpp index 8a4c5d06a7aa..970b0e400d01 100644 --- a/src/coreclr/ildasm/windasm.cpp +++ b/src/coreclr/ildasm/windasm.cpp @@ -17,7 +17,9 @@ #include #include "resource.h" -#include "new.hpp" +#include + +using std::nothrow; #define MODE_DUMP_ALL 0 #define MODE_DUMP_CLASS 1 @@ -465,10 +467,6 @@ int main(int argc, char* argv[]) } #endif -#ifdef _DEBUG - DisableThrowCheck(); -#endif - int iCommandLineParsed = 0; WCHAR* wzCommandLine = NULL; char* szCommandLine = NULL; diff --git a/src/coreclr/inc/CrstTypes.def b/src/coreclr/inc/CrstTypes.def index 7f94e9e0996a..c71a65cfa125 100644 --- a/src/coreclr/inc/CrstTypes.def +++ b/src/coreclr/inc/CrstTypes.def @@ -193,7 +193,7 @@ Crst DynamicIL End Crst DynamicMT - AcquiredBefore IbcProfile + AcquiredBefore IbcProfile CodeVersioning End Crst EventStore diff --git a/src/coreclr/inc/bitposition.h b/src/coreclr/inc/bitposition.h index aacc50ce15e0..91a89c116126 100644 --- a/src/coreclr/inc/bitposition.h +++ b/src/coreclr/inc/bitposition.h @@ -36,7 +36,7 @@ unsigned BitPosition(unsigned value) // It performs the "TrailingZeroCount" operation using intrinsics. // inline -unsigned BitPosition(unsigned __int64 value) +unsigned BitPosition(uint64_t value) { _ASSERTE((value != 0) && ((value & (value-1)) == 0)); DWORD index; diff --git a/src/coreclr/inc/bitvector.h b/src/coreclr/inc/bitvector.h index 0f17697dddce..b957bdadc5a5 100644 --- a/src/coreclr/inc/bitvector.h +++ b/src/coreclr/inc/bitvector.h @@ -401,7 +401,7 @@ typedef BitVector ptrArgTP; #else // !USE_BITVECTOR -typedef unsigned __int64 ptrArgTP; +typedef uint64_t ptrArgTP; // Maximum number of bits in our bitvector #define MAX_PTRARG_OFS (sizeof(ptrArgTP) * 8) diff --git a/src/coreclr/inc/cahlpr.h b/src/coreclr/inc/cahlpr.h index c5b4446b83cd..eef6c79204ff 100644 --- a/src/coreclr/inc/cahlpr.h +++ b/src/coreclr/inc/cahlpr.h @@ -18,23 +18,23 @@ struct CaValue { union { - signed __int8 i1; - unsigned __int8 u1; - signed __int16 i2; - unsigned __int16 u2; - signed __int32 i4; - unsigned __int32 u4; - signed __int64 i8; - unsigned __int64 u8; - float r4; - double r8; + int8_t i1; + uint8_t u1; + int16_t i2; + uint16_t u2; + int32_t i4; + uint32_t u4; + int64_t i8; + uint64_t u8; + float r4; + double r8; struct { LPCUTF8 pStr; ULONG cbStr; } str; }; - unsigned __int8 tag; + uint8_t tag; }; #endif // __CAHLPR_H__ diff --git a/src/coreclr/inc/caparser.h b/src/coreclr/inc/caparser.h index 177e5aa59268..4526495bfb48 100644 --- a/src/coreclr/inc/caparser.h +++ b/src/coreclr/inc/caparser.h @@ -28,63 +28,63 @@ class CustomAttributeParser { } private: - signed __int8 GetI1() + int8_t GetI1() { LIMITED_METHOD_CONTRACT; - signed __int8 tmp = *reinterpret_cast(m_pbCur); - m_pbCur += sizeof(signed __int8); + int8_t tmp = *reinterpret_cast(m_pbCur); + m_pbCur += sizeof(int8_t); return tmp; } - unsigned __int8 GetU1() + uint8_t GetU1() { LIMITED_METHOD_CONTRACT; - unsigned __int8 tmp = *reinterpret_cast(m_pbCur); - m_pbCur += sizeof(unsigned __int8); + uint8_t tmp = *reinterpret_cast(m_pbCur); + m_pbCur += sizeof(uint8_t); return tmp; } - signed __int16 GetI2() + int16_t GetI2() { LIMITED_METHOD_CONTRACT; - signed __int16 tmp = GET_UNALIGNED_VAL16(m_pbCur); - m_pbCur += sizeof(signed __int16); + int16_t tmp = GET_UNALIGNED_VAL16(m_pbCur); + m_pbCur += sizeof(int16_t); return tmp; } - unsigned __int16 GetU2() + uint16_t GetU2() { LIMITED_METHOD_CONTRACT; - unsigned __int16 tmp = GET_UNALIGNED_VAL16(m_pbCur); - m_pbCur += sizeof(unsigned __int16 ); + uint16_t tmp = GET_UNALIGNED_VAL16(m_pbCur); + m_pbCur += sizeof(uint16_t ); return tmp; } - signed __int32 GetI4() + int32_t GetI4() { LIMITED_METHOD_CONTRACT; - signed __int32 tmp = GET_UNALIGNED_VAL32(m_pbCur); - m_pbCur += sizeof(signed __int32 ); + int32_t tmp = GET_UNALIGNED_VAL32(m_pbCur); + m_pbCur += sizeof(int32_t ); return tmp; } - unsigned __int32 GetU4() + uint32_t GetU4() { LIMITED_METHOD_CONTRACT; - unsigned __int32 tmp = GET_UNALIGNED_VAL32(m_pbCur); - m_pbCur += sizeof(unsigned __int32 ); + uint32_t tmp = GET_UNALIGNED_VAL32(m_pbCur); + m_pbCur += sizeof(uint32_t ); return tmp; } - signed __int64 GetI8() + int64_t GetI8() { LIMITED_METHOD_CONTRACT; - signed __int64 tmp = GET_UNALIGNED_VAL64(m_pbCur); - m_pbCur += sizeof(signed __int64 ); + int64_t tmp = GET_UNALIGNED_VAL64(m_pbCur); + m_pbCur += sizeof(int64_t ); return tmp; } - unsigned __int64 GetU8() + uint64_t GetU8() { LIMITED_METHOD_CONTRACT; - unsigned __int64 tmp = GET_UNALIGNED_VAL64(m_pbCur); - m_pbCur += sizeof(unsigned __int64 ); + uint64_t tmp = GET_UNALIGNED_VAL64(m_pbCur); + m_pbCur += sizeof(uint64_t ); return tmp; } @@ -92,8 +92,8 @@ class CustomAttributeParser { float GetR4() { LIMITED_METHOD_CONTRACT; - __int32 tmp = GET_UNALIGNED_VAL32(m_pbCur); - _ASSERTE(sizeof(__int32) == sizeof(float)); + int32_t tmp = GET_UNALIGNED_VAL32(m_pbCur); + _ASSERTE(sizeof(int32_t) == sizeof(float)); m_pbCur += sizeof(float); return (float &)tmp; } @@ -101,17 +101,17 @@ class CustomAttributeParser { double GetR8() { LIMITED_METHOD_CONTRACT; - __int64 tmp = GET_UNALIGNED_VAL64(m_pbCur); - _ASSERTE(sizeof(__int64) == sizeof(double)); + int64_t tmp = GET_UNALIGNED_VAL64(m_pbCur); + _ASSERTE(sizeof(int64_t) == sizeof(double)); m_pbCur += sizeof(double); return (double &)tmp; } private: - unsigned __int16 GetProlog() + uint16_t GetProlog() { WRAPPER_NO_CONTRACT; - unsigned __int16 val; + uint16_t val; VERIFY(SUCCEEDED(GetProlog(&val))); return val; } @@ -125,11 +125,11 @@ class CustomAttributeParser { } public: - HRESULT GetI1(signed __int8 *pVal) + HRESULT GetI1(int8_t *pVal) { WRAPPER_NO_CONTRACT; - if (BytesLeft() < (int) sizeof(signed __int8)) + if (BytesLeft() < (int) sizeof(int8_t)) return META_E_CA_INVALID_BLOB; *pVal = GetI1(); return S_OK; @@ -139,74 +139,74 @@ class CustomAttributeParser { { WRAPPER_NO_CONTRACT; HRESULT hr; - signed __int8 tmp; + int8_t tmp; IfFailRet(GetI1(&tmp)); - *pVal = (CorSerializationType)((unsigned __int8)tmp); + *pVal = (CorSerializationType)((uint8_t)tmp); return hr; } - HRESULT GetU1(unsigned __int8 *pVal) + HRESULT GetU1(uint8_t *pVal) { WRAPPER_NO_CONTRACT; - if (BytesLeft() < (int) sizeof(unsigned __int8)) + if (BytesLeft() < (int) sizeof(uint8_t)) return META_E_CA_INVALID_BLOB; *pVal = GetU1(); return S_OK; } - HRESULT GetI2(signed __int16 *pVal) + HRESULT GetI2(int16_t *pVal) { WRAPPER_NO_CONTRACT; - if (BytesLeft() < (int) sizeof(signed __int16)) + if (BytesLeft() < (int) sizeof(int16_t)) return META_E_CA_INVALID_BLOB; *pVal = GetI2(); return S_OK; } - HRESULT GetU2(unsigned __int16 *pVal) + HRESULT GetU2(uint16_t *pVal) { WRAPPER_NO_CONTRACT; - if (BytesLeft() < (int) sizeof(unsigned __int16)) + if (BytesLeft() < (int) sizeof(uint16_t)) return META_E_CA_INVALID_BLOB; *pVal = GetU2(); return S_OK; } - HRESULT GetI4(signed __int32 *pVal) + HRESULT GetI4(int32_t *pVal) { WRAPPER_NO_CONTRACT; - if (BytesLeft() < (int) sizeof(signed __int32)) + if (BytesLeft() < (int) sizeof(int32_t)) return META_E_CA_INVALID_BLOB; *pVal = GetI4(); return S_OK; } - HRESULT GetU4(unsigned __int32 *pVal) + HRESULT GetU4(uint32_t *pVal) { WRAPPER_NO_CONTRACT; - if (BytesLeft() < (int) sizeof(unsigned __int32)) + if (BytesLeft() < (int) sizeof(uint32_t)) return META_E_CA_INVALID_BLOB; *pVal = GetU4(); return S_OK; } - HRESULT GetI8(signed __int64 *pVal) + HRESULT GetI8(int64_t *pVal) { WRAPPER_NO_CONTRACT; - if (BytesLeft() < (int) sizeof(signed __int64)) + if (BytesLeft() < (int) sizeof(int64_t)) return META_E_CA_INVALID_BLOB; *pVal = GetI8(); return S_OK; } - HRESULT GetU8(unsigned __int64 *pVal) + HRESULT GetU8(uint64_t *pVal) { WRAPPER_NO_CONTRACT; - if (BytesLeft() < (int) sizeof(unsigned __int64)) + if (BytesLeft() < (int) sizeof(uint64_t)) return META_E_CA_INVALID_BLOB; *pVal = GetU8(); return S_OK; @@ -231,7 +231,7 @@ class CustomAttributeParser { return S_OK; } - HRESULT GetProlog(unsigned __int16 *pVal) + HRESULT GetProlog(uint16_t *pVal) { WRAPPER_NO_CONTRACT; @@ -247,14 +247,14 @@ class CustomAttributeParser { // blobs where the prolog is the only incorrect data. HRESULT SkipProlog() { - unsigned __int16 val; + uint16_t val; return GetProlog(&val); } HRESULT ValidateProlog() { HRESULT hr; - unsigned __int16 val; + uint16_t val; IfFailRet(GetProlog(&val)); if (val != 0x0001) diff --git a/src/coreclr/inc/clrconfig.h b/src/coreclr/inc/clrconfig.h index f3e22d7ded16..549f372f4e7a 100644 --- a/src/coreclr/inc/clrconfig.h +++ b/src/coreclr/inc/clrconfig.h @@ -147,6 +147,6 @@ inline CLRConfig::LookupOptions operator&(CLRConfig::LookupOptions lhs, CLRConfi return static_cast(static_cast(lhs) & static_cast(rhs)); } -typedef Wrapper CLRConfigStringHolder; +typedef Wrapper CLRConfigStringHolder; #endif //__CLRConfig_h__ diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index ddc7c79506ad..07fa685484f0 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -261,7 +261,6 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_UseEntryPointFilter, W("UseEntryPointFilter"), RETAIL_CONFIG_DWORD_INFO(INTERNAL_Corhost_Swallow_Uncaught_Exceptions, W("Corhost_Swallow_Uncaught_Exceptions"), 0, "") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_LegacyExceptionHandling, W("LegacyExceptionHandling"), 0, "Enable legacy exception handling."); - /// /// Garbage collector /// @@ -284,6 +283,7 @@ CONFIG_DWORD_INFO(INTERNAL_GcStressOnDirectCalls, W("GcStressOnDirectCalls"), 0, RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_HeapVerify, W("HeapVerify"), 0, "When set verifies the integrity of the managed heap on entry and exit of each GC") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCCpuGroup, W("GCCpuGroup"), 0, "Specifies if to enable GC to support CPU groups") RETAIL_CONFIG_STRING_INFO(EXTERNAL_GCName, W("GCName"), "") +RETAIL_CONFIG_STRING_INFO(EXTERNAL_GCPath, W("GCPath"), "") /** * This flag allows us to force the runtime to use global allocation context on Windows x86/amd64 instead of thread allocation context just for testing purpose. * The flag is unsafe for a subtle reason. Although the access to the g_global_alloc_context is protected under a lock. The implementation of @@ -505,6 +505,7 @@ CONFIG_DWORD_INFO(INTERNAL_DiagnosticSuspend, W("DiagnosticSuspend"), 0, "") CONFIG_DWORD_INFO(INTERNAL_SuspendDeadlockTimeout, W("SuspendDeadlockTimeout"), 40000, "") CONFIG_DWORD_INFO(INTERNAL_SuspendThreadDeadlockTimeoutMs, W("SuspendThreadDeadlockTimeoutMs"), 2000, "") RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadSuspendInjection, W("INTERNAL_ThreadSuspendInjection"), 1, "Specifies whether to inject activations for thread suspension on Unix") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterruptibleCallSites, W("InterruptibleCallSites"), 1, "Specifies whether to allow asynchronous thread interruptions at call sites (requires GCInfo v3)") /// /// Thread (miscellaneous) @@ -686,7 +687,7 @@ RETAIL_CONFIG_STRING_INFO(INTERNAL_EventPipeConfig, W("EventPipeConfig"), "Confi RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeRundown, W("EventPipeRundown"), 1, "Enable/disable eventpipe rundown.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeCircularMB, W("EventPipeCircularMB"), 1024, "The EventPipe circular buffer size in megabytes.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeProcNumbers, W("EventPipeProcNumbers"), 0, "Enable/disable capturing processor numbers in EventPipe event headers") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeOutputStreaming, W("EventPipeOutputStreaming"), 0, "Enable/disable streaming for trace file set in DOTNET_EventPipeOutputPath. Non-zero values enable streaming.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeOutputStreaming, W("EventPipeOutputStreaming"), 1, "Enable/disable streaming for trace file set in DOTNET_EventPipeOutputPath. Non-zero values enable streaming.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeEnableStackwalk, W("EventPipeEnableStackwalk"), 1, "Set to 0 to disable collecting stacks for EventPipe events.") #ifdef FEATURE_AUTO_TRACE @@ -817,7 +818,6 @@ CONFIG_STRING_INFO(INTERNAL_DumpOnClassLoad, W("DumpOnClassLoad"), "Dumps inform CONFIG_DWORD_INFO(INTERNAL_ExpandAllOnLoad, W("ExpandAllOnLoad"), 0, "") CONFIG_DWORD_INFO(INTERNAL_ForceRelocs, W("ForceRelocs"), 0, "") CONFIG_DWORD_INFO(INTERNAL_GenerateLongJumpDispatchStubRatio, W("GenerateLongJumpDispatchStubRatio"), 0, "Useful for testing VSD on AMD64") -CONFIG_DWORD_INFO(INTERNAL_HashStack, W("HashStack"), 0, "") CONFIG_DWORD_INFO(INTERNAL_HostManagerConfig, W("HostManagerConfig"), (DWORD)-1, "") CONFIG_DWORD_INFO(INTERNAL_HostTestThreadAbort, W("HostTestThreadAbort"), 0, "") CONFIG_STRING_INFO(INTERNAL_InvokeHalt, W("InvokeHalt"), "Throws an assert when the given method is invoked through reflection.") diff --git a/src/coreclr/inc/clrhost.h b/src/coreclr/inc/clrhost.h index 393e6996fe7d..73d17c74e082 100644 --- a/src/coreclr/inc/clrhost.h +++ b/src/coreclr/inc/clrhost.h @@ -8,6 +8,8 @@ #ifndef __CLRHOST_H__ #define __CLRHOST_H__ +#include + #include "windows.h" // worth to include before mscoree.h so we are guaranteed to pick few definitions #ifdef CreateSemaphore #undef CreateSemaphore @@ -16,7 +18,9 @@ #include "clrinternal.h" #include "switches.h" #include "holder.h" -#include "new.hpp" + +using std::nothrow; + #include "staticcontract.h" #include "predeftlsslot.h" #include "safemath.h" @@ -65,10 +69,6 @@ BOOL ClrVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWO HANDLE ClrGetProcessExecutableHeap(); #endif -#ifdef FAILPOINTS_ENABLED -extern int RFS_HashStack(); -#endif - // Critical section support for CLR DLLs other than the EE. // Include the header defining each Crst type and its corresponding level (relative rank). This is // auto-generated from a tool that takes a high-level description of each Crst type and its dependencies. @@ -86,11 +86,11 @@ DWORD ClrSleepEx(DWORD dwMilliseconds, BOOL bAlertable); // be used. This guarantees that the locks will be vacated when the scope is popped, // either on exception or on return. -typedef Holder CRITSEC_Holder; +typedef Holder CRITSEC_Holder; // Use this holder to manage CRITSEC_COOKIE allocation to ensure it will be released if anything goes wrong FORCEINLINE void VoidClrDeleteCriticalSection(CRITSEC_COOKIE cs) { if (cs != NULL) ClrDeleteCriticalSection(cs); } -typedef Wrapper, VoidClrDeleteCriticalSection, NULL> CRITSEC_AllocationHolder; +typedef Wrapper, VoidClrDeleteCriticalSection, 0> CRITSEC_AllocationHolder; #ifndef DACCESS_COMPILE // Suspend/resume APIs that fail-fast on errors diff --git a/src/coreclr/inc/cordebug.idl b/src/coreclr/inc/cordebug.idl index 2e06651c9249..077d811cd45b 100644 --- a/src/coreclr/inc/cordebug.idl +++ b/src/coreclr/inc/cordebug.idl @@ -7781,6 +7781,17 @@ interface ICorDebugExceptionObjectValue : IUnknown HRESULT EnumerateExceptionCallStack([out] ICorDebugExceptionObjectCallStackEnum** ppCallStackEnum); }; +[ + object, + local, + uuid(e3b2f332-cc46-4f1e-ab4e-5400e332195e), + pointer_default(unique) +] +interface ICorDebugExceptionObjectValue2 : IUnknown +{ + HRESULT ForceCatchHandlerFoundEvents([in] BOOL enableEvents); +}; + /* ------------------------------------------------------------------------- * * Library definition * ------------------------------------------------------------------------- */ diff --git a/src/coreclr/inc/corerror.xml b/src/coreclr/inc/corerror.xml index 1d4129305fa6..68c9a1aa5dfb 100644 --- a/src/coreclr/inc/corerror.xml +++ b/src/coreclr/inc/corerror.xml @@ -172,12 +172,6 @@ The located assembly's manifest definition does not match the assembly reference. - - FUSION_E_PRIVATE_ASM_DISALLOWED - "A strongly-named assembly is required." - A strongly-named assembly is required. - - FUSION_E_INVALID_NAME "The given assembly name was invalid." diff --git a/src/coreclr/inc/corhlpr.cpp b/src/coreclr/inc/corhlpr.cpp index f4dc78d4f37c..61dc050ce52e 100644 --- a/src/coreclr/inc/corhlpr.cpp +++ b/src/coreclr/inc/corhlpr.cpp @@ -8,9 +8,7 @@ ****************************************************************************/ #ifndef SOS_INCLUDE -#ifdef _BLD_CLR #include "utilcode.h" -#endif #include "corhlpr.h" #include diff --git a/src/coreclr/inc/corhlpr.h b/src/coreclr/inc/corhlpr.h index 3cc0a36701e7..0bd3b1e1dfe8 100644 --- a/src/coreclr/inc/corhlpr.h +++ b/src/coreclr/inc/corhlpr.h @@ -22,14 +22,9 @@ #include "corhdr.h" #include "corerror.h" #include "unreachable.h" +#include -// This header is consumed both within the runtime and externally. In the former -// case we need to wrap memory allocations, in the latter there is no -// infrastructure to support this. Detect which way we're building and provide a -// very simple abstraction layer (handles allocating bytes only). -#ifdef _BLD_CLR -#include "new.hpp" - +using std::nothrow; #define NEW_NOTHROW(_bytes) new (nothrow) BYTE[_bytes] #define NEW_THROWS(_bytes) new BYTE[_bytes] @@ -38,27 +33,6 @@ inline void DECLSPEC_NORETURN THROW_OUT_OF_MEMORY() { ThrowOutOfMemory(); } -#else -#define NEW_NOTHROW(_bytes) new BYTE[_bytes] -#define NEW_THROWS(_bytes) __CorHlprNewThrows(_bytes) -static inline void DECLSPEC_NORETURN __CorHlprThrowOOM() -{ - RaiseException(STATUS_NO_MEMORY, 0, 0, NULL); - __UNREACHABLE(); -} -static inline BYTE *__CorHlprNewThrows(size_t bytes) -{ - BYTE *pbMemory = new BYTE[bytes]; - if (pbMemory == NULL) - __CorHlprThrowOOM(); - return pbMemory; -} -inline void DECLSPEC_NORETURN THROW_OUT_OF_MEMORY() -{ - __CorHlprThrowOOM(); -} -#endif - //***************************************************************************** // There are a set of macros commonly used in the helpers which you will want diff --git a/src/coreclr/inc/corhlprpriv.cpp b/src/coreclr/inc/corhlprpriv.cpp index c5d26cc6ce86..97c25d3cfb58 100644 --- a/src/coreclr/inc/corhlprpriv.cpp +++ b/src/coreclr/inc/corhlprpriv.cpp @@ -8,9 +8,7 @@ ****************************************************************************/ #ifndef SOS_INCLUDE -#ifdef _BLD_CLR #include "utilcode.h" -#endif #include "corhlprpriv.h" #include @@ -23,7 +21,6 @@ template HRESULT CQuickMemoryBase::ReSizeNoThrow(SIZE_T iItems) { -#ifdef _BLD_CLR #ifdef _DEBUG #ifndef DACCESS_COMPILE // Exercise heap for OOM-fault injection purposes @@ -38,7 +35,6 @@ HRESULT CQuickMemoryBase::ReSizeNoThrow(SIZE_T iItems) delete [] pTmp; } #endif -#endif #endif BYTE *pbBuffNew; if (iItems <= cbTotal) @@ -47,12 +43,10 @@ HRESULT CQuickMemoryBase::ReSizeNoThrow(SIZE_T iItems) return NOERROR; } -#ifdef _BLD_CLR #ifndef DACCESS_COMPILE // not allowed to do allocation if current thread suspends EE if (IsSuspendEEThread ()) return E_OUTOFMEMORY; -#endif #endif pbBuffNew = NEW_NOTHROW(iItems + INCREMENT); if (!pbBuffNew) diff --git a/src/coreclr/inc/corhlprpriv.h b/src/coreclr/inc/corhlprpriv.h index 62298798d701..9cbdaa4a3ea8 100644 --- a/src/coreclr/inc/corhlprpriv.h +++ b/src/coreclr/inc/corhlprpriv.h @@ -81,7 +81,7 @@ class CQuickMemoryBase template void *_Alloc(SIZE_T iItems) { -#if defined(_BLD_CLR) && defined(_DEBUG) +#if defined(_DEBUG) { // Exercise heap for OOM-fault injection purposes BYTE * pb = NSQuickBytesHelper::_AllocBytes::Invoke(iItems); _ASSERTE(!bThrow || pb != NULL); // _AllocBytes would have thrown if bThrow == TRUE @@ -474,12 +474,12 @@ template class CQuickArrayBase : public CQuickBytesBase template class CQuickArray : public CQuickArrayBase { public: - CQuickArray() + CQuickArray() { this->Init(); } - ~CQuickArray() + ~CQuickArray() { this->Destroy(); } diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index be3085aacf9f..645b46ede0f3 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -497,7 +497,7 @@ enum CorInfoHelpFunc CORINFO_HELP_ASSIGN_REF_ENSURE_NONHEAP, // Do the store, and ensure that the target was not in the heap. CORINFO_HELP_ASSIGN_BYREF, - CORINFO_HELP_ASSIGN_STRUCT, + CORINFO_HELP_BULK_WRITEBARRIER, /* Accessing fields */ @@ -1764,6 +1764,9 @@ struct CORINFO_EE_INFO // Size of the Frame structure unsigned size; + // Size of the Frame structure when it also contains the secret stub arg + unsigned sizeWithSecretStubArg; + unsigned offsetOfGSCookie; unsigned offsetOfFrameVptr; unsigned offsetOfFrameLink; @@ -1771,6 +1774,7 @@ struct CORINFO_EE_INFO unsigned offsetOfCalleeSavedFP; unsigned offsetOfCallTarget; unsigned offsetOfReturnAddress; + unsigned offsetOfSecretStubArg; // This offset is used only for ARM unsigned offsetOfSPAfterProlog; } @@ -2719,6 +2723,11 @@ class ICorStaticInfo CORINFO_CLASS_HANDLE cls ) = 0; + // Returns whether a class handle represents a Nullable type, if that can be statically determined. + virtual TypeCompareState isNullableType( + CORINFO_CLASS_HANDLE cls + ) = 0; + // Returns TypeCompareState::Must if cls is known to be an enum. // For enums with known exact type returns the underlying // type in underlyingType when the provided pointer is diff --git a/src/coreclr/inc/corjit.h b/src/coreclr/inc/corjit.h index 16116517b68d..a168fff609c5 100644 --- a/src/coreclr/inc/corjit.h +++ b/src/coreclr/inc/corjit.h @@ -455,7 +455,8 @@ class ICorJitInfo : public ICorDynamicInfo uint32_t * pCountSchemaItems, // OUT: pointer to the count of schema items in `pSchema` array. uint8_t ** pInstrumentationData, // OUT: `*pInstrumentationData` is set to the address of the instrumentation data // (pointer will not remain valid after jit completes). - PgoSource * pPgoSource // OUT: value describing source of pgo data + PgoSource * pPgoSource, // OUT: value describing source of pgo data + bool * pDynamicPgo // OUT: dynamic PGO is enabled (valid even when return value is failure) ) = 0; // Allocate a profile buffer for use in the current process diff --git a/src/coreclr/inc/crsttypes_generated.h b/src/coreclr/inc/crsttypes_generated.h index 79864b97db01..ed317f6d8656 100644 --- a/src/coreclr/inc/crsttypes_generated.h +++ b/src/coreclr/inc/crsttypes_generated.h @@ -172,7 +172,7 @@ int g_rgCrstLevelMap[] = 0, // CrstDelegateToFPtrHash 18, // CrstDomainLocalBlock 0, // CrstDynamicIL - 3, // CrstDynamicMT + 10, // CrstDynamicMT 0, // CrstEtwTypeLogHash 20, // CrstEventPipe 0, // CrstEventStore diff --git a/src/coreclr/inc/cycletimer.h b/src/coreclr/inc/cycletimer.h index bd81bba043b5..c261d851ff31 100644 --- a/src/coreclr/inc/cycletimer.h +++ b/src/coreclr/inc/cycletimer.h @@ -14,7 +14,7 @@ class CycleTimer { // This returns the value of the *non-thread-virtualized* cycle counter. - static unsigned __int64 GetCycleCount64(); + static uint64_t GetCycleCount64(); // This wraps GetCycleCount64 in the signature of QueryThreadCycleTime -- but note @@ -39,16 +39,16 @@ class CycleTimer // Does a large number of queries, and returns the average of their overhead, so other measurements // can adjust for this. - static unsigned __int64 QueryOverhead(); + static uint64_t QueryOverhead(); // There's no "native" atomic add for 64 bit, so we have this convenience function. - static void InterlockedAddU64(unsigned __int64* loc, unsigned __int64 amount); + static void InterlockedAddU64(uint64_t* loc, uint64_t amount); // Attempts to query the cycle counter of the current thread. If successful, returns "true" and sets // *cycles to the cycle counter value. Otherwise, returns false. Note that the value returned is (currently) // virtualized to the current thread only on Windows; on non-windows x86/x64 platforms, directly reads // the cycle counter and returns that value. - static bool GetThreadCyclesS(unsigned __int64* cycles); + static bool GetThreadCyclesS(uint64_t* cycles); }; #endif // _CYCLETIMER_H_ diff --git a/src/coreclr/inc/daccess.h b/src/coreclr/inc/daccess.h index 2d7cd5f34625..936a31950247 100644 --- a/src/coreclr/inc/daccess.h +++ b/src/coreclr/inc/daccess.h @@ -856,7 +856,7 @@ inline TADDR DacTAddrOffset( TADDR taBase, TSIZE_T dwIndex, TSIZE_T dwElementSiz class __TPtrBase { public: - __TPtrBase(void) + __TPtrBase() { // Make uninitialized pointers obvious. m_addr = (TADDR)-1; @@ -866,15 +866,44 @@ class __TPtrBase m_addr = addr; } + // We use this delayed check to avoid ambiguous overload issues with TADDR + // on platforms where NULL is defined as anything other than a uintptr_t constant + // or nullptr_t exactly. + // Without this, any valid "null pointer constant" that is not directly either type + // will be implicitly convertible to both TADDR and std::nullptr_t, causing ambiguity. + // With this, this constructor (and all similarly declared operators) drop out of + // consideration when used with NULL (and not nullptr_t). + // With this workaround, we get identical behavior between the DAC and non-DAC builds for assigning NULL + // to DACized pointer types. + template::value>::type> + __TPtrBase(T) + { + m_addr = 0; + } + + __TPtrBase& operator=(TADDR addr) + { + m_addr = addr; + return *this; + } + + template::value>::type> + __TPtrBase& operator=(T) + { + m_addr = 0; + return *this; + } + bool operator!() const { return m_addr == 0; } - // We'd like to have an implicit conversion to bool here since the C++ + + // We'd like to have an explicit conversion to bool here since the C++ // standard says all pointer types are implicitly converted to bool. // Unfortunately, that would cause ambiguous overload errors for uses - // of operator== and operator!=. Instead callers will have to compare - // directly against NULL. + // of operator== and operator!= with NULL on MSVC (where NULL is a 32-bit int on all platforms). + // Instead callers will have to compare directly against NULL. bool operator==(TADDR addr) const { @@ -884,6 +913,18 @@ class __TPtrBase { return m_addr != addr; } + + template::value>::type> + bool operator==(T) const + { + return m_addr == 0; + } + + template::value>::type> + bool operator!=(T) const + { + return m_addr != 0; + } bool operator<(TADDR addr) const { return m_addr < addr; @@ -919,61 +960,55 @@ class __TPtrBase // This has the common functionality between __DPtr and __ArrayDPtr. // The DPtrType type parameter is the actual derived type in use. This is necessary so that // inhereted functions preserve exact return types. -template +template class DPtrTemplate> class __DPtrBase : public __TPtrBase { public: typedef type _Type; typedef type* _Ptr; + using DPtrType = DPtrTemplate; -protected: - // Constructors - // All protected - this type should not be used directly - use one of the derived types instead. - __DPtrBase< type, DPtrType >(void) : __TPtrBase() {} - __DPtrBase< type, DPtrType >(TADDR addr) : __TPtrBase(addr) {} + using __TPtrBase::__TPtrBase; - explicit __DPtrBase< type, DPtrType >(__TPtrBase addr) - { - m_addr = addr.GetAddr(); - } - explicit __DPtrBase< type, DPtrType >(type const * host) + __DPtrBase() = default; + + explicit __DPtrBase(__TPtrBase ptr) : __TPtrBase(ptr.GetAddr()) {} + + // construct const from non-const + __DPtrBase(__DPtrBase::type, DPtrTemplate> const & rhs) : __DPtrBase(rhs.GetAddr()) {} + + explicit __DPtrBase(type const * host) { m_addr = DacGetTargetAddrForHostAddr(host, true); } public: + using __TPtrBase::operator=; + DPtrType& operator=(const __TPtrBase& ptr) { m_addr = ptr.GetAddr(); return DPtrType(m_addr); } - DPtrType& operator=(TADDR addr) - { - m_addr = addr; - return DPtrType(m_addr); - } type& operator*(void) const { return *(type*)DacInstantiateTypeByAddress(m_addr, sizeof(type), true); } + using __TPtrBase::operator==; + using __TPtrBase::operator!=; + bool operator==(const DPtrType& ptr) const { return m_addr == ptr.GetAddr(); } - bool operator==(TADDR addr) const - { - return m_addr == addr; - } + bool operator!=(const DPtrType& ptr) const { return !operator==(ptr); } - bool operator!=(TADDR addr) const - { - return m_addr != addr; - } + bool operator<(const DPtrType& ptr) const { return m_addr < ptr.GetAddr(); @@ -1176,31 +1211,25 @@ class __GlobalPtr; // Pointer wrapper for objects which are just plain data // and need no special handling. template -class __DPtr : public __DPtrBase > +class __DPtr : public __DPtrBase { public: - // constructors - all chain to __DPtrBase constructors - __DPtr< type >(void) : __DPtrBase >() {} - __DPtr< type >(TADDR addr) : __DPtrBase >(addr) {} + using __DPtrBase::__DPtrBase; - // construct const from non-const - typedef typename std::remove_const::type mutable_type; - __DPtr< type >(__DPtr const & rhs) : __DPtrBase >(rhs.GetAddr()) {} + __DPtr() = default; // construct from GlobalPtr - explicit __DPtr< type >(__GlobalPtr< type*, __DPtr< type > > globalPtr) : - __DPtrBase >(globalPtr.GetAddr()) {} - - explicit __DPtr< type >(__TPtrBase addr) : __DPtrBase >(addr) {} - explicit __DPtr< type >(type const * host) : __DPtrBase >(host) {} + explicit __DPtr(__GlobalPtr< type*, __DPtr< type > > globalPtr) : + __DPtrBase(globalPtr.GetAddr()) {} operator type*() const { return (type*)DacInstantiateTypeByAddress(this->m_addr, sizeof(type), true); } + type* operator->() const { - return (type*)DacInstantiateTypeByAddress(this->m_addr, sizeof(type), true); + return (type*)(*this); } }; @@ -1214,21 +1243,16 @@ class __DPtr : public __DPtrBase > // If you really must marshal a single instance (eg. converting T* to PTR_T is too painful for now), // then use code:DacUnsafeMarshalSingleElement so we can identify such unsafe code. template -class __ArrayDPtr : public __DPtrBase > +class __ArrayDPtr : public __DPtrBase { public: - // constructors - all chain to __DPtrBase constructors - __ArrayDPtr< type >(void) : __DPtrBase >() {} - __ArrayDPtr< type >(TADDR addr) : __DPtrBase >(addr) {} - - // construct const from non-const - typedef typename std::remove_const::type mutable_type; - __ArrayDPtr< type >(__ArrayDPtr const & rhs) : __DPtrBase >(rhs.GetAddr()) {} + using __DPtrBase::__DPtrBase; - explicit __ArrayDPtr< type >(__TPtrBase addr) : __DPtrBase >(addr) {} + __ArrayDPtr() = default; - // Note that there is also no explicit constructor from host instances (type*). + // We delete the base type's constructor from host pointer. // Going this direction is less problematic, but often still represents risky coding. + explicit __ArrayDPtr(type const * host) = delete; }; #define ArrayDPTR(type) __ArrayDPtr< type > @@ -1245,27 +1269,24 @@ class __SPtr : public __TPtrBase typedef type _Type; typedef type* _Ptr; - __SPtr< type >(void) : __TPtrBase() {} - __SPtr< type >(TADDR addr) : __TPtrBase(addr) {} - explicit __SPtr< type >(__TPtrBase addr) - { - m_addr = addr.GetAddr(); - } - explicit __SPtr< type >(type* host) + using __TPtrBase::__TPtrBase; + + __SPtr() = default; + + explicit __SPtr(__TPtrBase ptr) : __TPtrBase(ptr.GetAddr()) {} + + explicit __SPtr(type* host) { m_addr = DacGetTargetAddrForHostAddr(host, true); } - __SPtr< type >& operator=(const __TPtrBase& ptr) + using __TPtrBase::operator=; + + __SPtr& operator=(const __TPtrBase& ptr) { m_addr = ptr.GetAddr(); return *this; } - __SPtr< type >& operator=(TADDR addr) - { - m_addr = addr; - return *this; - } operator type*() const { @@ -1337,27 +1358,24 @@ class __VPtr : public __TPtrBase typedef type* _Type; typedef type* _Ptr; - __VPtr< type >(void) : __TPtrBase() {} - __VPtr< type >(TADDR addr) : __TPtrBase(addr) {} - explicit __VPtr< type >(__TPtrBase addr) - { - m_addr = addr.GetAddr(); - } - explicit __VPtr< type >(type* host) + using __TPtrBase::__TPtrBase; + + __VPtr() = default; + + explicit __VPtr(__TPtrBase ptr) : __TPtrBase(ptr.GetAddr()) {} + + explicit __VPtr(type* host) { m_addr = DacGetTargetAddrForHostAddr(host, true); } - __VPtr< type >& operator=(const __TPtrBase& ptr) + using __TPtrBase::operator=; + + __VPtr& operator=(const __TPtrBase& ptr) { m_addr = ptr.GetAddr(); return *this; } - __VPtr< type >& operator=(TADDR addr) - { - m_addr = addr; - return *this; - } operator type*() const { @@ -1368,22 +1386,18 @@ class __VPtr : public __TPtrBase return (type*)DacInstantiateClassByVTable(m_addr, sizeof(type), true); } - bool operator==(const __VPtr< type >& ptr) const + using __TPtrBase::operator==; + using __TPtrBase::operator!=; + + bool operator==(const __VPtr& ptr) const { return m_addr == ptr.m_addr; } - bool operator==(TADDR addr) const - { - return m_addr == addr; - } - bool operator!=(const __VPtr< type >& ptr) const + + bool operator!=(const __VPtr& ptr) const { return !operator==(ptr); } - bool operator!=(TADDR addr) const - { - return m_addr != addr; - } bool IsValid(void) const { @@ -1409,27 +1423,22 @@ class __Str8Ptr : public __DPtr typedef type _Type; typedef type* _Ptr; - __Str8Ptr< type, maxChars >(void) : __DPtr() {} - __Str8Ptr< type, maxChars >(TADDR addr) : __DPtr(addr) {} - explicit __Str8Ptr< type, maxChars >(__TPtrBase addr) - { - m_addr = addr.GetAddr(); - } - explicit __Str8Ptr< type, maxChars >(type* host) + using __DPtr::__DPtr; + + __Str8Ptr() = default; + + explicit __Str8Ptr(type* host) { m_addr = DacGetTargetAddrForHostAddr(host, true); } - __Str8Ptr< type, maxChars >& operator=(const __TPtrBase& ptr) + using __TPtrBase::operator=; + + __Str8Ptr& operator=(const __TPtrBase& ptr) { m_addr = ptr.GetAddr(); return *this; } - __Str8Ptr< type, maxChars >& operator=(TADDR addr) - { - m_addr = addr; - return *this; - } operator type*() const { @@ -1462,27 +1471,22 @@ class __Str16Ptr : public __DPtr typedef type _Type; typedef type* _Ptr; - __Str16Ptr< type, maxChars >(void) : __DPtr() {} - __Str16Ptr< type, maxChars >(TADDR addr) : __DPtr(addr) {} - explicit __Str16Ptr< type, maxChars >(__TPtrBase addr) - { - m_addr = addr.GetAddr(); - } - explicit __Str16Ptr< type, maxChars >(type* host) + using __DPtr::__DPtr; + + __Str16Ptr() = default; + + explicit __Str16Ptr(type* host) { m_addr = DacGetTargetAddrForHostAddr(host, true); } - __Str16Ptr< type, maxChars >& operator=(const __TPtrBase& ptr) + using __TPtrBase::operator=; + + __Str16Ptr& operator=(const __TPtrBase& ptr) { m_addr = ptr.GetAddr(); return *this; } - __Str16Ptr< type, maxChars >& operator=(TADDR addr) - { - m_addr = addr; - return *this; - } operator type*() const { @@ -1511,7 +1515,7 @@ template class __GlobalVal { public: - __GlobalVal< type >(TADDR DacGlobals::* ptr) + __GlobalVal(TADDR DacGlobals::* ptr) { m_ptr = ptr; } @@ -1557,7 +1561,7 @@ template class __GlobalArray { public: - __GlobalArray< type, size >(TADDR DacGlobals::* ptr) + __GlobalArray(TADDR DacGlobals::* ptr) { m_ptr = ptr; } @@ -1589,20 +1593,21 @@ class __GlobalArray template class __GlobalPtr { + using DPtr = __DPtr; public: - __GlobalPtr< acc_type, store_type >(TADDR DacGlobals::* ptr) + __GlobalPtr(TADDR DacGlobals::* ptr) { m_ptr = ptr; } - __DPtr< store_type > operator&() const + DPtr operator&() const { - return __DPtr< store_type >(DacGlobalValues()->*m_ptr); + return DPtr(DacGlobalValues()->*m_ptr); } - store_type & operator=(store_type & val) + store_type& operator=(store_type & val) { - store_type* ptr = __DPtr< store_type >(DacGlobalValues()->*m_ptr); + store_type* ptr = DPtr(DacGlobalValues()->*m_ptr); // Update the host copy; *ptr = val; // Write back to the target. @@ -1612,34 +1617,34 @@ class __GlobalPtr acc_type operator->() const { - return (acc_type)*__DPtr< store_type >(DacGlobalValues()->*m_ptr); + return (acc_type)*DPtr(DacGlobalValues()->*m_ptr); } operator acc_type() const { - return (acc_type)*__DPtr< store_type >(DacGlobalValues()->*m_ptr); + return (acc_type)*DPtr(DacGlobalValues()->*m_ptr); } operator store_type() const { - return *__DPtr< store_type >(DacGlobalValues()->*m_ptr); + return *DPtr(DacGlobalValues()->*m_ptr); } bool operator!() const { - return !*__DPtr< store_type >(DacGlobalValues()->*m_ptr); + return !*DPtr(DacGlobalValues()->*m_ptr); } typename store_type::_Type& operator[](int index) { - return (*__DPtr< store_type >(DacGlobalValues()->*m_ptr))[index]; + return (*DPtr(DacGlobalValues()->*m_ptr))[index]; } typename store_type::_Type& operator[](unsigned int index) { - return (*__DPtr< store_type >(DacGlobalValues()->*m_ptr))[index]; + return (*DPtr(DacGlobalValues()->*m_ptr))[index]; } TADDR GetAddr() const { - return (*__DPtr< store_type >(DacGlobalValues()->*m_ptr)).GetAddr(); + return (*DPtr(DacGlobalValues()->*m_ptr)).GetAddr(); } TADDR GetAddrRaw () const @@ -1652,17 +1657,17 @@ class __GlobalPtr // bool IsValidPtr(void) const { - return __DPtr< store_type >(DacGlobalValues()->*m_ptr).IsValid(); + return DPtr(DacGlobalValues()->*m_ptr).IsValid(); } bool IsValid(void) const { - return __DPtr< store_type >(DacGlobalValues()->*m_ptr).IsValid() && - (*__DPtr< store_type >(DacGlobalValues()->*m_ptr)).IsValid(); + return DPtr(DacGlobalValues()->*m_ptr).IsValid() && + (*DPtr(DacGlobalValues()->*m_ptr)).IsValid(); } void EnumMem(void) const { - __DPtr< store_type > ptr(DacGlobalValues()->*m_ptr); + DPtr ptr(DacGlobalValues()->*m_ptr); ptr.EnumMem(); if (ptr.IsValid()) { @@ -1734,8 +1739,9 @@ inline bool operator!=(acc_type host, class __VoidPtr : public __TPtrBase { public: - __VoidPtr(void) : __TPtrBase() {} - __VoidPtr(TADDR addr) : __TPtrBase(addr) {} + using __TPtrBase::__TPtrBase; + + __VoidPtr() = default; // Note, unlike __DPtr, this ctor form is not explicit. We allow implicit // conversions from any pointer type (just like for void*). @@ -1761,38 +1767,31 @@ class __VoidPtr : public __TPtrBase // Note, unlike __DPtr, any pointer type can be assigned to a __VoidPtr // This is to mirror the assignability of any pointer type to a void* + using __TPtrBase::operator=; + __VoidPtr& operator=(const __TPtrBase& ptr) { m_addr = ptr.GetAddr(); return *this; } - __VoidPtr& operator=(TADDR addr) - { - m_addr = addr; - return *this; - } // note, no marshalling operators (type* conversion, operator ->, operator*) // A void* can't be marshalled because we don't know how much to copy // PTR_Void can be compared to any other pointer type (because conceptually, // any other pointer type should be implicitly convertible to void*) + + using __TPtrBase::operator==; + using __TPtrBase::operator!=; + bool operator==(const __TPtrBase& ptr) const { return m_addr == ptr.GetAddr(); } - bool operator==(TADDR addr) const - { - return m_addr == addr; - } bool operator!=(const __TPtrBase& ptr) const { return !operator==(ptr); } - bool operator!=(TADDR addr) const - { - return m_addr != addr; - } bool operator<(const __TPtrBase& ptr) const { return m_addr < ptr.GetAddr(); diff --git a/src/coreclr/inc/dacvars.h b/src/coreclr/inc/dacvars.h index 8f710c8fde12..b387c770de16 100644 --- a/src/coreclr/inc/dacvars.h +++ b/src/coreclr/inc/dacvars.h @@ -123,6 +123,7 @@ DEFINE_DACVAR(BOOL, dac__g_isNewExceptionHandlingEnabled, ::g_isNewExceptionHand DEFINE_DACVAR(PTR_SString, SString__s_Empty, SString::s_Empty) DEFINE_DACVAR(INT32, ArrayBase__s_arrayBoundsZero, ArrayBase::s_arrayBoundsZero) +DEFINE_DACVAR(BOOL, CodeVersionManager__s_HasNonDefaultILVersions, CodeVersionManager::s_HasNonDefaultILVersions) DEFINE_DACVAR(PTR_JITNotification, dac__g_pNotificationTable, ::g_pNotificationTable) DEFINE_DACVAR(ULONG32, dac__g_dacNotificationFlags, ::g_dacNotificationFlags) diff --git a/src/coreclr/inc/eetwain.h b/src/coreclr/inc/eetwain.h index bee2f658ee7c..c7b1be02e5c6 100644 --- a/src/coreclr/inc/eetwain.h +++ b/src/coreclr/inc/eetwain.h @@ -457,6 +457,9 @@ virtual bool IsGcSafe( EECodeInfo *pCodeInfo, DWORD dwRelOffset); +static +bool InterruptibleSafePointsEnabled(); + #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) virtual bool HasTailCalls(EECodeInfo *pCodeInfo); diff --git a/src/coreclr/inc/ex.h b/src/coreclr/inc/ex.h index 5496c999e039..50949d62f013 100644 --- a/src/coreclr/inc/ex.h +++ b/src/coreclr/inc/ex.h @@ -827,6 +827,15 @@ Exception *ExThrowWithInnerHelper(Exception *inner); } \ SCAN_EHMARKER_END_TRY(); \ } \ + PAL_CPP_CATCH_NON_DERIVED_NOARG (const std::bad_alloc&) \ + { \ + SCAN_EHMARKER_CATCH(); \ + __state.SetCaughtCxx(); \ + __state.m_pExceptionPtr = Exception::GetOOMException(); \ + SCAN_EHMARKER_END_CATCH(); \ + SCAN_IGNORE_THROW_MARKER; \ + ThrowOutOfMemory(); \ + } \ PAL_CPP_CATCH_DERIVED (DerivedExceptionClass, __pExceptionRaw) \ { \ SCAN_EHMARKER_CATCH(); \ @@ -862,18 +871,34 @@ Exception *ExThrowWithInnerHelper(Exception *inner); PAL_CPP_TRY \ { \ SCAN_EHMARKER_TRY(); \ - CAutoTryCleanup __autoCleanupTry(__state); \ - /* prevent annotations from being dropped by optimizations in debug */ \ - INDEBUG(static bool __alwayszero;) \ - INDEBUG(VolatileLoad(&__alwayszero);) \ + SCAN_EHMARKER(); \ + PAL_CPP_TRY \ { \ - /* Disallow returns to make exception handling work. */ \ - /* Some work is done after the catch, see EX_ENDTRY. */ \ - DEBUG_ASSURE_NO_RETURN_BEGIN(EX_TRY) \ + SCAN_EHMARKER_TRY(); \ + CAutoTryCleanup __autoCleanupTry(__state); \ + /* prevent annotations from being dropped by optimizations in debug */ \ + INDEBUG(static bool __alwayszero;) \ + INDEBUG(VolatileLoad(&__alwayszero);) \ + { \ + /* Disallow returns to make exception handling work. */ \ + /* Some work is done after the catch, see EX_ENDTRY. */ \ + DEBUG_ASSURE_NO_RETURN_BEGIN(EX_TRY) \ #define EX_CATCH_IMPL_CPP_ONLY \ - DEBUG_ASSURE_NO_RETURN_END(EX_TRY) \ + DEBUG_ASSURE_NO_RETURN_END(EX_TRY) \ + } \ + SCAN_EHMARKER_END_TRY(); \ + } \ + PAL_CPP_CATCH_NON_DERIVED_NOARG (const std::bad_alloc&) \ + { \ + SCAN_EHMARKER_CATCH(); \ + __state.SetCaughtCxx(); \ + __state.m_pExceptionPtr = Exception::GetOOMException(); \ + SCAN_EHMARKER_END_CATCH(); \ + SCAN_IGNORE_THROW_MARKER; \ + ThrowOutOfMemory(); \ } \ + PAL_CPP_ENDTRY \ SCAN_EHMARKER_END_TRY(); \ } \ PAL_CPP_CATCH_DERIVED (Exception, __pExceptionRaw) \ diff --git a/src/coreclr/inc/gcinfo.h b/src/coreclr/inc/gcinfo.h index 16bff25525a9..d526405c9f2c 100644 --- a/src/coreclr/inc/gcinfo.h +++ b/src/coreclr/inc/gcinfo.h @@ -36,7 +36,7 @@ const unsigned this_OFFSET_FLAG = 0x2; // the offset is "this" // The current GCInfo Version //----------------------------------------------------------------------------- -#define GCINFO_VERSION 2 +#define GCINFO_VERSION 3 //----------------------------------------------------------------------------- // GCInfoToken: A wrapper that contains the GcInfo data and version number. @@ -65,9 +65,16 @@ struct GCInfoToken } #endif - static uint32_t ReadyToRunVersionToGcInfoVersion(uint32_t readyToRunMajorVersion) + static uint32_t ReadyToRunVersionToGcInfoVersion(uint32_t readyToRunMajorVersion, uint32_t readyToRunMinorVersion) { - // GcInfo version is current from ReadyToRun version 2.0 + // Once MINIMUM_READYTORUN_MAJOR_VERSION is bumped to 10+ + // delete the following and just return GCINFO_VERSION + // + // R2R 9.0 and 9.1 use GCInfo v2 + // R2R 9.2 uses GCInfo v3 + if (readyToRunMajorVersion == 9 && readyToRunMinorVersion < 2) + return 2; + return GCINFO_VERSION; } }; diff --git a/src/coreclr/inc/gcinfodecoder.h b/src/coreclr/inc/gcinfodecoder.h index b42f5aae8f60..8534bc2508c5 100644 --- a/src/coreclr/inc/gcinfodecoder.h +++ b/src/coreclr/inc/gcinfodecoder.h @@ -502,12 +502,17 @@ class GcInfoDecoder //------------------------------------------------------------------------ bool IsInterruptible(); + bool HasInterruptibleRanges(); #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED + bool IsSafePoint(); + bool AreSafePointsInterruptible(); + bool IsInterruptibleSafePoint(); + // This is used for gccoverage bool IsSafePoint(UINT32 codeOffset); - typedef void EnumerateSafePointsCallback (UINT32 offset, void * hCallback); + typedef void EnumerateSafePointsCallback (GcInfoDecoder* decoder, UINT32 offset, void * hCallback); void EnumerateSafePoints(EnumerateSafePointsCallback * pCallback, void * hCallback); #endif diff --git a/src/coreclr/inc/gcinfoencoder.h b/src/coreclr/inc/gcinfoencoder.h index 5085e5971a8e..b3199a1a9561 100644 --- a/src/coreclr/inc/gcinfoencoder.h +++ b/src/coreclr/inc/gcinfoencoder.h @@ -542,7 +542,9 @@ class GcInfoEncoder void SizeofSlotStateVarLengthVector(const BitArray& vector, UINT32 baseSkip, UINT32 baseRun, UINT32 * pSizeofSimple, UINT32 * pSizeofRLE, UINT32 * pSizeofRLENeg); UINT32 WriteSlotStateVarLengthVector(BitStreamWriter &writer, const BitArray& vector, UINT32 baseSkip, UINT32 baseRun); - bool IsAlwaysScratch(GcSlotDesc &slot); +#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED + bool DoNotTrackInPartiallyInterruptible(GcSlotDesc &slot); +#endif // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED // Assumes that "*ppTransitions" is has size "numTransitions", is sorted by CodeOffset then by SlotId, // and that "*ppEndTransitions" points one beyond the end of the array. If "*ppTransitions" contains diff --git a/src/coreclr/inc/holder.h b/src/coreclr/inc/holder.h index 984260308d04..eb537804daa9 100644 --- a/src/coreclr/inc/holder.h +++ b/src/coreclr/inc/holder.h @@ -817,9 +817,9 @@ class Wrapper : public BaseWrapper, #endif template -class SpecializedWrapper : public Wrapper<_TYPE*, DoNothing<_TYPE*>, _RELEASEF, NULL> +class SpecializedWrapper : public Wrapper<_TYPE*, DoNothing<_TYPE*>, _RELEASEF, 0> { - using BaseT = Wrapper<_TYPE*, DoNothing<_TYPE*>, _RELEASEF, NULL>; + using BaseT = Wrapper<_TYPE*, DoNothing<_TYPE*>, _RELEASEF, 0>; public: FORCEINLINE SpecializedWrapper() : BaseT(NULL, FALSE) { @@ -997,19 +997,6 @@ FORCEINLINE void Delete(TYPE *value) template using NewHolder = SpecializedWrapper<_TYPE, Delete<_TYPE>>; - //----------------------------------------------------------------------------- -// NewExecutableHolder : New'ed memory holder for executable memory. -// -// { -// NewExecutableHolder foo = (Foo*) new (executable) Byte[num]; -// } // delete foo on out of scope -//----------------------------------------------------------------------------- -// IJW -template void DeleteExecutable(T *p); - -template -using NewExecutableHolder = SpecializedWrapper<_TYPE, DeleteExecutable<_TYPE>>; - //----------------------------------------------------------------------------- // NewArrayHolder : New []'ed pointer holder // { @@ -1146,7 +1133,7 @@ typedef Wrapper MapViewHolder; // A holder for HMODULE. FORCEINLINE void HolderFreeLibrary(HMODULE h) { FreeLibrary(h); } -typedef Wrapper, HolderFreeLibrary, NULL> HModuleHolder; +typedef Wrapper, HolderFreeLibrary, 0> HModuleHolder; template FORCEINLINE void DoLocalFree(T* pMem) diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 2348162d9485..5572a044b9b0 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -344,6 +344,9 @@ bool isMoreSpecificType( bool isExactType( CORINFO_CLASS_HANDLE cls) override; +TypeCompareState isNullableType( + CORINFO_CLASS_HANDLE cls) override; + TypeCompareState isEnum( CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType) override; @@ -708,7 +711,8 @@ JITINTERFACE_HRESULT getPgoInstrumentationResults( ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, - ICorJitInfo::PgoSource* pgoSource) override; + ICorJitInfo::PgoSource* pPgoSource, + bool* pDynamicPgo) override; JITINTERFACE_HRESULT allocPgoInstrumentationBySchema( CORINFO_METHOD_HANDLE ftnHnd, diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 0e9f6e2940bc..46b50f5410ce 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 3c216494-65f8-49e2-b69a-7f272193bcc6 */ - 0x3c216494, - 0x65f8, - 0x49e2, - {0xb6, 0x9a, 0x7f, 0x27, 0x21, 0x93, 0xbc, 0xc6} +constexpr GUID JITEEVersionIdentifier = { /* 227e46fa-1be3-4770-b613-4a239e7c28aa */ + 0x227e46fa, + 0x1be3, + 0x4770, + {0xb6, 0x13, 0x4a, 0x23, 0x9e, 0x7c, 0x28, 0xaa} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/inc/jithelpers.h b/src/coreclr/inc/jithelpers.h index 5dedc2f18324..bc76a586d772 100644 --- a/src/coreclr/inc/jithelpers.h +++ b/src/coreclr/inc/jithelpers.h @@ -47,8 +47,8 @@ JITHELPER(CORINFO_HELP_LRSZ, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) #endif // TARGET_64BIT JITHELPER(CORINFO_HELP_LMUL, JIT_LMul, CORINFO_HELP_SIG_16_STACK) - JITHELPER(CORINFO_HELP_LMUL_OVF, JIT_LMulOvf, CORINFO_HELP_SIG_16_STACK) - JITHELPER(CORINFO_HELP_ULMUL_OVF, JIT_ULMulOvf, CORINFO_HELP_SIG_16_STACK) + DYNAMICJITHELPER(CORINFO_HELP_LMUL_OVF, NULL, CORINFO_HELP_SIG_16_STACK) + DYNAMICJITHELPER(CORINFO_HELP_ULMUL_OVF, NULL, CORINFO_HELP_SIG_16_STACK) JITHELPER(CORINFO_HELP_LDIV, JIT_LDiv, CORINFO_HELP_SIG_16_STACK) JITHELPER(CORINFO_HELP_LMOD, JIT_LMod, CORINFO_HELP_SIG_16_STACK) JITHELPER(CORINFO_HELP_ULDIV, JIT_ULDiv, CORINFO_HELP_SIG_16_STACK) @@ -56,13 +56,13 @@ JITHELPER(CORINFO_HELP_LNG2DBL, JIT_Lng2Dbl, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_ULNG2DBL, JIT_ULng2Dbl, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_DBL2INT, JIT_Dbl2Int, CORINFO_HELP_SIG_8_STACK) - JITHELPER(CORINFO_HELP_DBL2INT_OVF, JIT_Dbl2IntOvf, CORINFO_HELP_SIG_8_STACK) + DYNAMICJITHELPER(CORINFO_HELP_DBL2INT_OVF, NULL, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_DBL2LNG, JIT_Dbl2Lng, CORINFO_HELP_SIG_8_STACK) - JITHELPER(CORINFO_HELP_DBL2LNG_OVF, JIT_Dbl2LngOvf, CORINFO_HELP_SIG_8_STACK) + DYNAMICJITHELPER(CORINFO_HELP_DBL2LNG_OVF, NULL, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_DBL2UINT, JIT_Dbl2UInt, CORINFO_HELP_SIG_8_STACK) - JITHELPER(CORINFO_HELP_DBL2UINT_OVF, JIT_Dbl2UIntOvf, CORINFO_HELP_SIG_8_STACK) + DYNAMICJITHELPER(CORINFO_HELP_DBL2UINT_OVF, NULL, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_DBL2ULNG, JIT_Dbl2ULng, CORINFO_HELP_SIG_8_STACK) - JITHELPER(CORINFO_HELP_DBL2ULNG_OVF, JIT_Dbl2ULngOvf, CORINFO_HELP_SIG_8_STACK) + DYNAMICJITHELPER(CORINFO_HELP_DBL2ULNG_OVF, NULL, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_FLTREM, JIT_FltRem, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_DBLREM, JIT_DblRem, CORINFO_HELP_SIG_16_STACK) DYNAMICJITHELPER(CORINFO_HELP_FLTROUND, NULL, CORINFO_HELP_SIG_8_STACK) @@ -154,8 +154,7 @@ JITHELPER(CORINFO_HELP_ASSIGN_REF_ENSURE_NONHEAP, JIT_WriteBarrierEnsureNonHeapTarget,CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_ASSIGN_BYREF, JIT_ByRefWriteBarrier,CORINFO_HELP_SIG_NO_ALIGN_STUB) - - JITHELPER(CORINFO_HELP_ASSIGN_STRUCT, JIT_StructWriteBarrier,CORINFO_HELP_SIG_4_STACK) + DYNAMICJITHELPER(CORINFO_HELP_BULK_WRITEBARRIER, NULL, CORINFO_HELP_SIG_REG_ONLY) // Accessing fields JITHELPER(CORINFO_HELP_GETFIELD8, JIT_GetField8,CORINFO_HELP_SIG_REG_ONLY) diff --git a/src/coreclr/inc/metadata.h b/src/coreclr/inc/metadata.h index 766893bea17b..65ac907421c2 100644 --- a/src/coreclr/inc/metadata.h +++ b/src/coreclr/inc/metadata.h @@ -220,19 +220,6 @@ struct HENUMInternal //***************************************** typedef struct _MDDefaultValue { -#if BIGENDIAN - _MDDefaultValue(void) - { - m_bType = ELEMENT_TYPE_END; - } - ~_MDDefaultValue(void) - { - if (m_bType == ELEMENT_TYPE_STRING) - { - delete[] m_wzValue; - } - } -#endif // type of default value BYTE m_bType; // CorElementType for the default value @@ -251,7 +238,7 @@ typedef struct _MDDefaultValue ULONGLONG m_ullValue; // ELEMENT_TYPE_UI8 FLOAT m_fltValue; // ELEMENT_TYPE_R4 DOUBLE m_dblValue; // ELEMENT_TYPE_R8 - LPCWSTR m_wzValue; // ELEMENT_TYPE_STRING + LPCWSTR m_wzValue; // ELEMENT_TYPE_STRING - Little endian IUnknown *m_unkValue; // ELEMENT_TYPE_CLASS }; ULONG m_cbSize; // default value size (for blob) diff --git a/src/coreclr/inc/new.hpp b/src/coreclr/inc/new.hpp deleted file mode 100644 index 09eec5d1ffcf..000000000000 --- a/src/coreclr/inc/new.hpp +++ /dev/null @@ -1,26 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// - -// - -#ifndef __new__hpp -#define __new__hpp - -#if defined(_MSC_VER) && _MSC_VER < 1900 -#define NOEXCEPT -#else -#define NOEXCEPT noexcept -#endif - -struct NoThrow { int x; }; -extern const NoThrow nothrow; - -void * __cdecl operator new(size_t n, const NoThrow&) NOEXCEPT; -void * __cdecl operator new[](size_t n, const NoThrow&) NOEXCEPT; - -#ifdef _DEBUG -void DisableThrowCheck(); -#endif - -#endif diff --git a/src/coreclr/inc/opinfo.h b/src/coreclr/inc/opinfo.h index 85ce3a744104..94dd9121e13f 100644 --- a/src/coreclr/inc/opinfo.h +++ b/src/coreclr/inc/opinfo.h @@ -32,8 +32,8 @@ enum OpFlow { // These are all the possible arguments for the instruction /****************************************************************************/ union OpArgsVal { - __int32 i; - __int64 i8; + int32_t i; + int64_t i8; double r; struct { unsigned count; diff --git a/src/coreclr/inc/outstring.h b/src/coreclr/inc/outstring.h index abd69cb5891f..c719c465457b 100644 --- a/src/coreclr/inc/outstring.h +++ b/src/coreclr/inc/outstring.h @@ -51,14 +51,14 @@ class OutString { // prints out the hexidecimal representation OutString& hex(unsigned i, int minWidth = 0, unsigned flags = none); - OutString& hex(unsigned __int64 i, int minWidth = 0, unsigned flags = none); + OutString& hex(uint64_t i, int minWidth = 0, unsigned flags = none); OutString& hex(int i, int minWidth = 0, unsigned flags = none) { return hex(unsigned(i), minWidth, flags); } - OutString& hex(__int64 i, int minWidth = 0, unsigned flags = none) { - return hex((unsigned __int64) i, minWidth, flags); + OutString& hex(int64_t i, int minWidth = 0, unsigned flags = none) { + return hex((uint64_t) i, minWidth, flags); } // print out 'count' instances of the character 'c' diff --git a/src/coreclr/inc/palclr.h b/src/coreclr/inc/palclr.h index 40fe2d1d3a2d..98321ba87f83 100644 --- a/src/coreclr/inc/palclr.h +++ b/src/coreclr/inc/palclr.h @@ -481,6 +481,8 @@ #define PAL_CPP_THROW(type, obj) do { SCAN_THROW_MARKER; throw obj; } while (false) #define PAL_CPP_RETHROW do { SCAN_THROW_MARKER; throw; } while (false) #define PAL_CPP_CATCH_DERIVED(type, obj) catch (type * obj) +#define PAL_CPP_CATCH_NON_DERIVED(type, obj) catch (type obj) +#define PAL_CPP_CATCH_NON_DERIVED_NOARG(type) catch (type) #define PAL_CPP_CATCH_ALL catch (...) #define PAL_CPP_CATCH_EXCEPTION_NOARG catch (Exception *) diff --git a/src/coreclr/inc/pedecoder.h b/src/coreclr/inc/pedecoder.h index efd0555a4f7b..057dfa9a25de 100644 --- a/src/coreclr/inc/pedecoder.h +++ b/src/coreclr/inc/pedecoder.h @@ -309,10 +309,6 @@ class PEDecoder BOOL HasReadyToRunHeader() const; READYTORUN_HEADER *GetReadyToRunHeader() const; - void GetEXEStackSizes(SIZE_T *PE_SizeOfStackReserve, SIZE_T *PE_SizeOfStackCommit) const; - - CHECK CheckWillCreateGuardPage() const; - // Native DLLMain Entrypoint BOOL HasNativeEntryPoint() const; void *GetNativeEntryPoint() const; diff --git a/src/coreclr/inc/pedecoder.inl b/src/coreclr/inc/pedecoder.inl index 9b3c9c47238d..7257bd9a78a5 100644 --- a/src/coreclr/inc/pedecoder.inl +++ b/src/coreclr/inc/pedecoder.inl @@ -200,9 +200,9 @@ inline void PEDecoder::Reset() GC_NOTRIGGER; } CONTRACTL_END; - m_base=NULL; - m_flags=NULL; - m_size=NULL; + m_base=(TADDR)0; + m_flags=0; + m_size=0; m_pNTHeaders=NULL; m_pCorHeader=NULL; m_pReadyToRunHeader=NULL; @@ -411,42 +411,6 @@ inline WORD PEDecoder::GetCharacteristics() const return VAL16(FindNTHeaders()->FileHeader.Characteristics); } -inline SIZE_T PEDecoder::GetSizeOfStackReserve() const -{ - CONTRACTL - { - INSTANCE_CHECK; - PRECONDITION(CheckNTHeaders()); - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - if (Has32BitNTHeaders()) - return (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.SizeOfStackReserve); - else - return (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.SizeOfStackReserve); -} - - -inline SIZE_T PEDecoder::GetSizeOfStackCommit() const -{ - CONTRACTL - { - INSTANCE_CHECK; - PRECONDITION(CheckNTHeaders()); - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - if (Has32BitNTHeaders()) - return (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.SizeOfStackCommit); - else - return (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.SizeOfStackCommit); -} - - inline SIZE_T PEDecoder::GetSizeOfHeapReserve() const { CONTRACTL diff --git a/src/coreclr/inc/profilepriv.inl b/src/coreclr/inc/profilepriv.inl index df5d91a20a8a..5b50e4e8e13b 100644 --- a/src/coreclr/inc/profilepriv.inl +++ b/src/coreclr/inc/profilepriv.inl @@ -290,7 +290,7 @@ inline void EEFunctionIDMapperHelper(ProfilerInfo *pProfilerInfo, FunctionID fun inline UINT_PTR ProfControlBlock::EEFunctionIDMapper(FunctionID funcId, BOOL *pbHookFunction) { LIMITED_METHOD_CONTRACT; - UINT_PTR ptr = NULL; + UINT_PTR ptr = 0; DoOneProfilerIteration(&mainProfilerInfo, ProfilerCallbackType::Active, &EEFunctionIDMapperHelper, diff --git a/src/coreclr/inc/readytorun.h b/src/coreclr/inc/readytorun.h index 88219146a123..a9050dae85f7 100644 --- a/src/coreclr/inc/readytorun.h +++ b/src/coreclr/inc/readytorun.h @@ -20,7 +20,7 @@ // If you update this, ensure you run `git grep MINIMUM_READYTORUN_MAJOR_VERSION` // and handle pending work. #define READYTORUN_MAJOR_VERSION 0x0009 -#define READYTORUN_MINOR_VERSION 0x0002 +#define READYTORUN_MINOR_VERSION 0x0003 #define MINIMUM_READYTORUN_MAJOR_VERSION 0x009 @@ -34,7 +34,8 @@ // R2R Version 9.0 adds support for the Vector512 type // R2R Version 9.1 adds new helpers to allocate objects on frozen segments // R2R Version 9.2 adds MemZero and NativeMemSet helpers - +// R2R Version 9.3 adds BulkWriteBarrier helper +// uses GCInfo v3, which makes safe points in partially interruptible code interruptible. struct READYTORUN_CORE_HEADER { @@ -321,6 +322,7 @@ enum ReadyToRunHelper READYTORUN_HELPER_WriteBarrier = 0x30, READYTORUN_HELPER_CheckedWriteBarrier = 0x31, READYTORUN_HELPER_ByRefWriteBarrier = 0x32, + READYTORUN_HELPER_BulkWriteBarrier = 0x33, // Array helpers READYTORUN_HELPER_Stelem_Ref = 0x38, diff --git a/src/coreclr/inc/readytorunhelpers.h b/src/coreclr/inc/readytorunhelpers.h index bbb586e8eb4a..a1fcef8fbaf8 100644 --- a/src/coreclr/inc/readytorunhelpers.h +++ b/src/coreclr/inc/readytorunhelpers.h @@ -24,6 +24,7 @@ HELPER(READYTORUN_HELPER_ThrowDivZero, CORINFO_HELP_THROWDIVZERO, HELPER(READYTORUN_HELPER_WriteBarrier, CORINFO_HELP_ASSIGN_REF, ) HELPER(READYTORUN_HELPER_CheckedWriteBarrier, CORINFO_HELP_CHECKED_ASSIGN_REF, ) HELPER(READYTORUN_HELPER_ByRefWriteBarrier, CORINFO_HELP_ASSIGN_BYREF, ) +HELPER(READYTORUN_HELPER_BulkWriteBarrier, CORINFO_HELP_BULK_WRITEBARRIER, ) HELPER(READYTORUN_HELPER_Stelem_Ref, CORINFO_HELP_ARRADDR_ST, ) HELPER(READYTORUN_HELPER_Ldelema_Ref, CORINFO_HELP_LDELEMA_REF, ) diff --git a/src/coreclr/inc/regdisp.h b/src/coreclr/inc/regdisp.h index ec47b9019dbc..47a67237fb8f 100644 --- a/src/coreclr/inc/regdisp.h +++ b/src/coreclr/inc/regdisp.h @@ -261,12 +261,12 @@ struct REGDISPLAY : public REGDISPLAY_BASE { inline TADDR GetRegdisplayFP(REGDISPLAY *display) { LIMITED_METHOD_CONTRACT; - return NULL; + return 0; } inline TADDR GetRegdisplayFPAddress(REGDISPLAY *display) { LIMITED_METHOD_CONTRACT; - return NULL; + return 0; } // This function tells us if the given stack pointer is in one of the frames of the functions called by the given frame diff --git a/src/coreclr/inc/safemath.h b/src/coreclr/inc/safemath.h index ff1fcbee7811..e40e267984b1 100644 --- a/src/coreclr/inc/safemath.h +++ b/src/coreclr/inc/safemath.h @@ -688,10 +688,6 @@ template class ClrSafeInt INDEBUG( mutable bool m_checkedOverflow; ) }; -#if defined(_MSC_VER) && defined(HOST_ARM64) // Workaround for https://github.com/dotnet/runtime/issues/93442 -#pragma optimize("", off) -#endif - template <> inline bool ClrSafeInt::multiply(int64_t lhs, int64_t rhs, int64_t &result) { @@ -878,10 +874,6 @@ inline bool ClrSafeInt::multiply(uint8_t lhs, uint8_t rhs, uint8_t &res return true; } -#if defined(_MSC_VER) && defined(HOST_ARM64) // Workaround for https://github.com/dotnet/runtime/issues/93442 -#pragma optimize("", on) -#endif - // Allows creation of a ClrSafeInt corresponding to the type of the argument. template ClrSafeInt AsClrSafeInt(T t) diff --git a/src/coreclr/inc/sbuffer.inl b/src/coreclr/inc/sbuffer.inl index a613f847f49f..402cda72f473 100644 --- a/src/coreclr/inc/sbuffer.inl +++ b/src/coreclr/inc/sbuffer.inl @@ -19,7 +19,7 @@ inline SBuffer::SBuffer(PreallocFlag flag, void *buffer, COUNT_T size) : m_size(0), - m_allocation(NULL), + m_allocation(0), m_flags(0), m_buffer(NULL) { diff --git a/src/coreclr/inc/simplerhash.inl b/src/coreclr/inc/simplerhash.inl index 6694ab61212b..e47880e50856 100644 --- a/src/coreclr/inc/simplerhash.inl +++ b/src/coreclr/inc/simplerhash.inl @@ -11,9 +11,9 @@ inline unsigned magicNumberDivide(unsigned numerator, const PrimeInfo &p) { - unsigned __int64 num = numerator; - unsigned __int64 mag = p.magic; - unsigned __int64 product = (num * mag) >> (32 + p.shift); + uint64_t num = numerator; + uint64_t mag = p.magic; + uint64_t product = (num * mag) >> (32 + p.shift); return (unsigned) product; } diff --git a/src/coreclr/inc/stackframe.h b/src/coreclr/inc/stackframe.h index 12b047a6b4d7..3c33d0e1e9fb 100644 --- a/src/coreclr/inc/stackframe.h +++ b/src/coreclr/inc/stackframe.h @@ -10,7 +10,7 @@ struct StackFrame { const static UINT_PTR maxVal = (UINT_PTR)(INT_PTR)-1; - StackFrame() : SP(NULL) + StackFrame() : SP(0) { } @@ -21,7 +21,7 @@ struct StackFrame void Clear() { - SP = NULL; + SP = 0; } void SetMaxVal() @@ -31,7 +31,7 @@ struct StackFrame bool IsNull() { - return (SP == NULL); + return (SP == 0); } bool IsMaxVal() diff --git a/src/coreclr/inc/stresslog.h b/src/coreclr/inc/stresslog.h index 04d31177c0ab..ef8ecb146298 100644 --- a/src/coreclr/inc/stresslog.h +++ b/src/coreclr/inc/stresslog.h @@ -314,8 +314,8 @@ class StressLog { unsigned padding; // Preserve the layout for SOS Volatile deadCount; // count of dead threads in the log CRITSEC_COOKIE lock; // lock - unsigned __int64 tickFrequency; // number of ticks per second - unsigned __int64 startTimeStamp; // start time from when tick counter started + uint64_t tickFrequency; // number of ticks per second + uint64_t startTimeStamp; // start time from when tick counter started FILETIME startTime; // time the application started SIZE_T moduleOffset; // Used to compute format strings. struct ModuleDesc @@ -539,7 +539,7 @@ typedef USHORT }; #ifndef STRESS_LOG_ANALYZER -typedef Holder> StressLogLockHolder; +typedef Holder> StressLogLockHolder; #endif //!STRESS_LOG_ANALYZER #if defined(DACCESS_COMPILE) @@ -807,7 +807,7 @@ class ThreadStressLog { #endif //!STRESS_LOG_READONLY && !STRESS_LOG_ANALYZER #if defined(MEMORY_MAPPED_STRESSLOG) && !defined(STRESS_LOG_ANALYZER) - void* __cdecl operator new(size_t n, const NoThrow&) NOEXCEPT; + void* __cdecl operator new(size_t n, const std::nothrow_t&) noexcept; void __cdecl operator delete (void * chunk); #endif diff --git a/src/coreclr/inc/switches.h b/src/coreclr/inc/switches.h index ab71d22dc21d..4c4792c6f465 100644 --- a/src/coreclr/inc/switches.h +++ b/src/coreclr/inc/switches.h @@ -33,13 +33,6 @@ #define LOGGING #endif -#if !defined(FEATURE_UTILCODE_NO_DEPENDENCIES) -// Failpoint support -#if defined(_DEBUG) && !defined(DACCESS_COMPILE) && !defined(TARGET_UNIX) -#define FAILPOINTS_ENABLED -#endif -#endif //!defined(FEATURE_UTILCODE_NO_DEPENDENCIES) - #if 0 // Enable to track details of EESuspension #define TIME_SUSPEND diff --git a/src/coreclr/inc/utilcode.h b/src/coreclr/inc/utilcode.h index 55713550aedc..53e4b2bb0fe9 100644 --- a/src/coreclr/inc/utilcode.h +++ b/src/coreclr/inc/utilcode.h @@ -14,6 +14,9 @@ #include #include #include +#include + +using std::nothrow; #include "crtwrap.h" #include "winwrap.h" @@ -29,7 +32,6 @@ #include "corhlprpriv.h" #include "check.h" #include "safemath.h" -#include "new.hpp" #include "contract.h" @@ -55,6 +57,8 @@ #define CoreLibSatelliteName_A "System.Private.CoreLib.resources" #define CoreLibSatelliteNameLen 32 +bool ValidateModuleName(LPCWSTR pwzModuleName); + class StringArrayList; #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) @@ -316,10 +320,10 @@ _Ret_bytecap_(n) void * __cdecl operator new[](size_t n); void __cdecl -operator delete(void *p) NOEXCEPT; +operator delete(void *p) noexcept; void __cdecl -operator delete[](void *p) NOEXCEPT; +operator delete[](void *p) noexcept; #ifdef _DEBUG_IMPL HRESULT _OutOfMemory(LPCSTR szFile, int iLine); @@ -843,7 +847,7 @@ template class SimpleListNode { public: - SimpleListNode(const T& _t) + SimpleListNode(const T& _t) { data = _t; next = 0; @@ -859,7 +863,7 @@ class SimpleList public: typedef SimpleListNode NodeType; - SimpleList() + SimpleList() { head = NULL; } @@ -1742,7 +1746,7 @@ class CHashTable HASHFIND *psSrch) // Search object. { WRAPPER_NO_CONTRACT; - if (m_piBuckets == 0) + if (m_piBuckets == nullptr) return (0); psSrch->iBucket = 1; psSrch->iNext = m_piBuckets[0]; @@ -3716,41 +3720,8 @@ namespace util } } - -/* ------------------------------------------------------------------------ * - * Overloaded operators for the executable heap - * ------------------------------------------------------------------------ */ - -#ifdef HOST_WINDOWS - -struct CExecutable { int x; }; -extern const CExecutable executable; - -void * __cdecl operator new(size_t n, const CExecutable&); -void * __cdecl operator new[](size_t n, const CExecutable&); -void * __cdecl operator new(size_t n, const CExecutable&, const NoThrow&); -void * __cdecl operator new[](size_t n, const CExecutable&, const NoThrow&); - - -// -// Executable heap delete to match the executable heap new above. -// -template void DeleteExecutable(T *p) -{ - if (p != NULL) - { - p->T::~T(); - - HeapFree(ClrGetProcessExecutableHeap(), 0, p); - } -} - -#endif // HOST_WINDOWS - INDEBUG(BOOL DbgIsExecutable(LPVOID lpMem, SIZE_T length);) -BOOL ThreadWillCreateGuardPage(SIZE_T sizeReservedStack, SIZE_T sizeCommittedStack); - #ifdef FEATURE_COMINTEROP FORCEINLINE void HolderSysFreeString(BSTR str) { CONTRACT_VIOLATION(ThrowsViolation); SysFreeString(str); } diff --git a/src/coreclr/inc/volatile.h b/src/coreclr/inc/volatile.h index 177c4932166c..efcb25f8acd8 100644 --- a/src/coreclr/inc/volatile.h +++ b/src/coreclr/inc/volatile.h @@ -168,16 +168,16 @@ T VolatileLoad(T const * pt) switch (sizeof(T)) { case 1: - *(unsigned __int8* )pv = __ldar8 ((unsigned __int8 volatile*)pt); + *(uint8_t* )pv = __ldar8 ((uint8_t volatile*)pt); break; case 2: - *(unsigned __int16*)pv = __ldar16((unsigned __int16 volatile*)pt); + *(uint16_t*)pv = __ldar16((uint16_t volatile*)pt); break; case 4: - *(unsigned __int32*)pv = __ldar32((unsigned __int32 volatile*)pt); + *(uint32_t*)pv = __ldar32((uint32_t volatile*)pt); break; case 8: - *(unsigned __int64*)pv = __ldar64((unsigned __int64 volatile*)pt); + *(uint64_t*)pv = __ldar64((uint64_t volatile*)pt); break; default: val = *(T volatile const*)pt; @@ -252,16 +252,16 @@ void VolatileStore(T* pt, T val) switch (sizeof(T)) { case 1: - __stlr8 ((unsigned __int8 volatile*)pt, *(unsigned __int8* )pv); + __stlr8 ((uint8_t volatile*)pt, *(uint8_t* )pv); break; case 2: - __stlr16((unsigned __int16 volatile*)pt, *(unsigned __int16*)pv); + __stlr16((uint16_t volatile*)pt, *(uint16_t*)pv); break; case 4: - __stlr32((unsigned __int32 volatile*)pt, *(unsigned __int32*)pv); + __stlr32((uint32_t volatile*)pt, *(uint32_t*)pv); break; case 8: - __stlr64((unsigned __int64 volatile*)pt, *(unsigned __int64*)pv); + __stlr64((uint64_t volatile*)pt, *(uint64_t*)pv); break; default: __dmb(_ARM64_BARRIER_ISH); diff --git a/src/coreclr/interop/comwrappers.cpp b/src/coreclr/interop/comwrappers.cpp index 095f098e2860..58b83368f7bf 100644 --- a/src/coreclr/interop/comwrappers.cpp +++ b/src/coreclr/interop/comwrappers.cpp @@ -736,7 +736,9 @@ HRESULT ManagedObjectWrapper::QueryInterface( return E_NOINTERFACE; default: +#if !defined(__clang__) || (__clang_major__ > 13) // Workaround bug in old clang _ASSERTE(false && "Unknown result value"); +#endif FALLTHROUGH; case TryInvokeICustomQueryInterfaceResult::FailedToInvoke: // Set the 'lacks' flag since our attempt to use ICustomQueryInterface diff --git a/src/coreclr/jit/ICorJitInfo_names_generated.h b/src/coreclr/jit/ICorJitInfo_names_generated.h index 30c499518e00..2e2573a91199 100644 --- a/src/coreclr/jit/ICorJitInfo_names_generated.h +++ b/src/coreclr/jit/ICorJitInfo_names_generated.h @@ -85,6 +85,7 @@ DEF_CLR_API(compareTypesForCast) DEF_CLR_API(compareTypesForEquality) DEF_CLR_API(isMoreSpecificType) DEF_CLR_API(isExactType) +DEF_CLR_API(isNullableType) DEF_CLR_API(isEnum) DEF_CLR_API(getParentType) DEF_CLR_API(getChildType) diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index 77af720739ec..e001c56c26dc 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -804,6 +804,15 @@ bool WrapICorJitInfo::isExactType( return temp; } +TypeCompareState WrapICorJitInfo::isNullableType( + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(isNullableType); + TypeCompareState temp = wrapHnd->isNullableType(cls); + API_LEAVE(isNullableType); + return temp; +} + TypeCompareState WrapICorJitInfo::isEnum( CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType) @@ -1657,10 +1666,11 @@ JITINTERFACE_HRESULT WrapICorJitInfo::getPgoInstrumentationResults( ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, - ICorJitInfo::PgoSource* pgoSource) + ICorJitInfo::PgoSource* pPgoSource, + bool* pDynamicPgo) { API_ENTER(getPgoInstrumentationResults); - JITINTERFACE_HRESULT temp = wrapHnd->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pgoSource); + JITINTERFACE_HRESULT temp = wrapHnd->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, pDynamicPgo); API_LEAVE(getPgoInstrumentationResults); return temp; } diff --git a/src/coreclr/jit/abi.cpp b/src/coreclr/jit/abi.cpp index 91f74fca03c8..a4b5e19921f8 100644 --- a/src/coreclr/jit/abi.cpp +++ b/src/coreclr/jit/abi.cpp @@ -70,6 +70,17 @@ regMaskTP ABIPassingSegment::GetRegisterMask() const // Return Value: // Offset relative to the first stack argument. // +// Remarks: +// On x86, for the managed ABI where arguments are pushed in order and thus +// come in reverse order in the callee, this is the offset to subtract from +// the top of the stack to get the argument's address. By top of the stack is +// meant esp on entry + 4 for the return address + total size of stack +// arguments. In varargs methods the varargs cookie contains the information +// required to allow the computation of the total size of stack arguments. +// +// Outside the managed x86 ABI this is the offset to add to the first +// argument's address. +// unsigned ABIPassingSegment::GetStackOffset() const { assert(IsPassedOnStack()); @@ -77,14 +88,14 @@ unsigned ABIPassingSegment::GetStackOffset() const } //----------------------------------------------------------------------------- -// GetRegisterStoreType: -// Return a type that can be used to store from the register this segment is -// in, taking the segment's size into account. +// GetRegisterType: +// Return the smallest type larger or equal to Size that most naturally +// represents the register this segment is passed in. // // Return Value: -// A type that matches ABIPassingSegment::Size and the register type. +// A type that matches ABIPassingSegment::Size and the register. // -var_types ABIPassingSegment::GetRegisterStoreType() const +var_types ABIPassingSegment::GetRegisterType() const { assert(IsPassedInRegister()); if (genIsValidFloatReg(m_register)) @@ -100,6 +111,7 @@ var_types ABIPassingSegment::GetRegisterStoreType() const return TYP_SIMD16; #endif default: + assert(!"Unexpected size for floating point register"); return TYP_UNDEF; } } @@ -111,13 +123,18 @@ var_types ABIPassingSegment::GetRegisterStoreType() const return TYP_UBYTE; case 2: return TYP_USHORT; + case 3: case 4: return TYP_INT; #ifdef TARGET_64BIT + case 5: + case 6: + case 7: case 8: return TYP_LONG; #endif default: + assert(!"Unexpected size for integer register"); return TYP_UNDEF; } } @@ -138,7 +155,9 @@ var_types ABIPassingSegment::GetRegisterStoreType() const // ABIPassingSegment ABIPassingSegment::InRegister(regNumber reg, unsigned offset, unsigned size) { +#if !defined(TARGET_WASM) assert(reg != REG_NA); +#endif //!TARGET_WASM - TODO-LLVM: Delete when old classifer has gone. ABIPassingSegment segment; segment.m_register = reg; segment.m_stackOffset = 0; @@ -208,6 +227,18 @@ bool ABIPassingInformation::HasAnyStackSegment() const return false; } +//----------------------------------------------------------------------------- +// HasExactlyOneRegisterSegment: +// Check if this value is passed as a single register segment. +// +// Return Value: +// True if so. +// +bool ABIPassingInformation::HasExactlyOneRegisterSegment() const +{ + return (NumSegments == 1) && Segments[0].IsPassedInRegister(); +} + //----------------------------------------------------------------------------- // HasExactlyOneStackSegment: // Check if this value is passed as a single stack segment. @@ -230,14 +261,20 @@ bool ABIPassingInformation::HasExactlyOneStackSegment() const // bool ABIPassingInformation::IsSplitAcrossRegistersAndStack() const { - bool anyReg = false; - bool anyStack = false; - for (unsigned i = 0; i < NumSegments; i++) + if (NumSegments < 2) { - anyReg |= Segments[i].IsPassedInRegister(); - anyStack |= Segments[i].IsPassedOnStack(); + return false; } - return anyReg && anyStack; + + bool isFirstInReg = Segments[0].IsPassedInRegister(); + for (unsigned i = 1; i < NumSegments; i++) + { + if (isFirstInReg != Segments[i].IsPassedInRegister()) + { + return true; + } + } + return false; } //----------------------------------------------------------------------------- @@ -253,10 +290,7 @@ bool ABIPassingInformation::IsSplitAcrossRegistersAndStack() const // ABIPassingInformation ABIPassingInformation::FromSegment(Compiler* comp, const ABIPassingSegment& segment) { - ABIPassingInformation info; - info.NumSegments = 1; - info.Segments = new (comp, CMK_ABI) ABIPassingSegment(segment); - return info; + return {1, new (comp, CMK_ABI) ABIPassingSegment(segment)}; } #ifdef DEBUG @@ -390,6 +424,9 @@ ABIPassingInformation SwiftABIClassifier::Classify(Compiler* comp, { ABIPassingSegment newSegment = elemInfo.Segments[j]; newSegment.Offset += lowering->offsets[i]; + // Adjust the tail size if necessary; the lowered sequence can + // pass the tail as a larger type than the tail size. + newSegment.Size = min(newSegment.Size, structLayout->GetSize() - newSegment.Offset); segments.Push(newSegment); } } diff --git a/src/coreclr/jit/abi.h b/src/coreclr/jit/abi.h index 7236627d375d..ae59b9b0b155 100644 --- a/src/coreclr/jit/abi.h +++ b/src/coreclr/jit/abi.h @@ -28,10 +28,10 @@ class ABIPassingSegment regMaskTP GetRegisterMask() const; // If this segment is passed on the stack then return the particular stack - // offset, relative to the first stack argument's offset. + // offset, relative to the base of stack arguments. unsigned GetStackOffset() const; - var_types GetRegisterStoreType() const; + var_types GetRegisterType() const; static ABIPassingSegment InRegister(regNumber reg, unsigned offset, unsigned size); static ABIPassingSegment OnStack(unsigned stackOffset, unsigned offset, unsigned size); @@ -48,16 +48,30 @@ struct ABIPassingInformation // multiple register segments and a struct segment. // - On Windows x64, all parameters always fit into one stack slot or // register, and thus always have NumSegments == 1 - unsigned NumSegments = 0; - ABIPassingSegment* Segments = nullptr; + // - On loongarch64/riscv64, structs can be passed in two registers or + // can be split out over register and stack, giving + // multiple register segments and a struct segment. + unsigned NumSegments; + ABIPassingSegment* Segments; + + ABIPassingInformation(unsigned numSegments = 0, ABIPassingSegment* segments = nullptr) + : NumSegments(numSegments) + , Segments(segments) + { + } bool HasAnyRegisterSegment() const; bool HasAnyStackSegment() const; + bool HasExactlyOneRegisterSegment() const; bool HasExactlyOneStackSegment() const; bool IsSplitAcrossRegistersAndStack() const; static ABIPassingInformation FromSegment(Compiler* comp, const ABIPassingSegment& segment); +#ifdef WINDOWS_AMD64_ABI + static bool GetShadowSpaceCallerOffsetForReg(regNumber reg, int* offset); +#endif + #ifdef DEBUG void Dump() const; #endif @@ -76,7 +90,7 @@ class RegisterQueue { } - unsigned Count() + unsigned Count() const { return m_numRegs - m_index; } @@ -96,12 +110,18 @@ struct ClassifierInfo class X86Classifier { - RegisterQueue m_regs; - unsigned m_stackArgSize = 0; + const ClassifierInfo& m_info; + RegisterQueue m_regs; + unsigned m_stackArgSize = 0; public: X86Classifier(const ClassifierInfo& info); + unsigned StackSize() + { + return m_stackArgSize; + } + ABIPassingInformation Classify(Compiler* comp, var_types type, ClassLayout* structLayout, @@ -112,11 +132,16 @@ class WinX64Classifier { RegisterQueue m_intRegs; RegisterQueue m_floatRegs; - unsigned m_stackArgSize = 0; + unsigned m_stackArgSize = 32; public: WinX64Classifier(const ClassifierInfo& info); + unsigned StackSize() + { + return m_stackArgSize; + } + ABIPassingInformation Classify(Compiler* comp, var_types type, ClassLayout* structLayout, @@ -132,6 +157,11 @@ class SysVX64Classifier public: SysVX64Classifier(const ClassifierInfo& info); + unsigned StackSize() + { + return m_stackArgSize; + } + ABIPassingInformation Classify(Compiler* comp, var_types type, ClassLayout* structLayout, @@ -148,6 +178,11 @@ class Arm64Classifier public: Arm64Classifier(const ClassifierInfo& info); + unsigned StackSize() + { + return roundUp(m_stackArgSize, TARGET_POINTER_SIZE); + } + ABIPassingInformation Classify(Compiler* comp, var_types type, ClassLayout* structLayout, @@ -172,6 +207,72 @@ class Arm32Classifier public: Arm32Classifier(const ClassifierInfo& info); + unsigned StackSize() + { + return m_stackArgSize; + } + + ABIPassingInformation Classify(Compiler* comp, + var_types type, + ClassLayout* structLayout, + WellKnownArg wellKnownParam); +}; + +class RiscV64Classifier +{ + const ClassifierInfo& m_info; + RegisterQueue m_intRegs; + RegisterQueue m_floatRegs; + unsigned m_stackArgSize = 0; + +public: + RiscV64Classifier(const ClassifierInfo& info); + + unsigned StackSize() + { + return m_stackArgSize; + } + + ABIPassingInformation Classify(Compiler* comp, + var_types type, + ClassLayout* structLayout, + WellKnownArg wellKnownParam); +}; + +class LoongArch64Classifier +{ + const ClassifierInfo& m_info; + RegisterQueue m_intRegs; + RegisterQueue m_floatRegs; + unsigned m_stackArgSize = 0; + +public: + LoongArch64Classifier(const ClassifierInfo& info); + + unsigned StackSize() + { + return m_stackArgSize; + } + + ABIPassingInformation Classify(Compiler* comp, + var_types type, + ClassLayout* structLayout, + WellKnownArg wellKnownParam); +}; + +class WasmClassifier +{ + const ClassifierInfo& m_info; + unsigned m_stackArgSize = 0; + +public: + WasmClassifier(const ClassifierInfo& info); + + unsigned StackSize() + { + return m_stackArgSize; + } + ABIPassingInformation Classify(Compiler* comp, var_types type, ClassLayout* structLayout, @@ -188,6 +289,12 @@ typedef SysVX64Classifier PlatformClassifier; typedef Arm64Classifier PlatformClassifier; #elif defined(TARGET_ARM) typedef Arm32Classifier PlatformClassifier; +#elif defined(TARGET_RISCV64) +typedef RiscV64Classifier PlatformClassifier; +#elif defined(TARGET_LOONGARCH64) +typedef LoongArch64Classifier PlatformClassifier; +#elif defined(TARGET_WASM) +typedef WasmClassifier PlatformClassifier; #endif #ifdef SWIFT_SUPPORT @@ -201,6 +308,11 @@ class SwiftABIClassifier { } + unsigned StackSize() + { + return m_classifier.StackSize(); + } + ABIPassingInformation Classify(Compiler* comp, var_types type, ClassLayout* structLayout, diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index ebcb101663a3..6d72657fd97f 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -769,9 +769,9 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse } else if (curAssertion->op1.kind == O1K_ARR_BND) { - printf("[idx:"); + printf("[idx: " FMT_VN, curAssertion->op1.bnd.vnIdx); vnStore->vnDump(this, curAssertion->op1.bnd.vnIdx); - printf(";len:"); + printf("; len: " FMT_VN, curAssertion->op1.bnd.vnLen); vnStore->vnDump(this, curAssertion->op1.bnd.vnLen); printf("]"); } @@ -795,11 +795,6 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse printf("Const_Loop_Bnd_Un"); vnStore->vnDump(this, curAssertion->op1.vn); } - else if (curAssertion->op1.kind == O1K_VALUE_NUMBER) - { - printf("Value_Number"); - vnStore->vnDump(this, curAssertion->op1.vn); - } else { printf("?op1.kind?"); @@ -897,18 +892,7 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse } else { - var_types op1Type; - - if (curAssertion->op1.kind == O1K_VALUE_NUMBER) - { - op1Type = vnStore->TypeOfVN(curAssertion->op1.vn); - } - else - { - unsigned lclNum = curAssertion->op1.lcl.lclNum; - op1Type = lvaGetDesc(lclNum)->lvType; - } - + var_types op1Type = lvaGetDesc(curAssertion->op1.lcl.lclNum)->lvType; if (op1Type == TYP_REF) { if (curAssertion->op2.u1.iconVal == 0) @@ -939,7 +923,7 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse break; case O2K_CONST_DOUBLE: - if (*((__int64*)&curAssertion->op2.dconVal) == (__int64)I64(0x8000000000000000)) + if (FloatingPointUtils::isNegativeZero(curAssertion->op2.dconVal)) { printf("-0.00000"); } @@ -1175,64 +1159,23 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, ValueNum vn; - // - // We only perform null-checks on GC refs - // so only make non-null assertions about GC refs or byrefs if we can't determine - // the corresponding ref. - // - if (lclVar->TypeGet() != TYP_REF) + // We only perform null-checks on byrefs and GC refs + if (!varTypeIsGC(lclVar->TypeGet())) { - if (optLocalAssertionProp || (lclVar->TypeGet() != TYP_BYREF)) - { - goto DONE_ASSERTION; // Don't make an assertion - } - - vn = optConservativeNormalVN(op1); - VNFuncApp funcAttr; - - // Try to get value number corresponding to the GC ref of the indirection - while (vnStore->GetVNFunc(vn, &funcAttr) && (funcAttr.m_func == (VNFunc)GT_ADD) && - (vnStore->TypeOfVN(vn) == TYP_BYREF)) - { - if (vnStore->IsVNConstant(funcAttr.m_args[1]) && - varTypeIsIntegral(vnStore->TypeOfVN(funcAttr.m_args[1]))) - { - offset += vnStore->CoercedConstantValue(funcAttr.m_args[1]); - vn = funcAttr.m_args[0]; - } - else if (vnStore->IsVNConstant(funcAttr.m_args[0]) && - varTypeIsIntegral(vnStore->TypeOfVN(funcAttr.m_args[0]))) - { - offset += vnStore->CoercedConstantValue(funcAttr.m_args[0]); - vn = funcAttr.m_args[1]; - } - else - { - break; - } - } - - if (fgIsBigOffset(offset)) - { - goto DONE_ASSERTION; // Don't make an assertion - } - - assertion.op1.kind = O1K_VALUE_NUMBER; + goto DONE_ASSERTION; // Don't make an assertion } - else - { - // If the local variable has its address exposed then bail - if (lclVar->IsAddressExposed()) - { - goto DONE_ASSERTION; // Don't make an assertion - } - assertion.op1.kind = O1K_LCLVAR; - assertion.op1.lcl.lclNum = lclNum; - assertion.op1.lcl.ssaNum = op1->AsLclVarCommon()->GetSsaNum(); - vn = optConservativeNormalVN(op1); + // If the local variable has its address exposed then bail + if (lclVar->IsAddressExposed()) + { + goto DONE_ASSERTION; // Don't make an assertion } + assertion.op1.kind = O1K_LCLVAR; + assertion.op1.lcl.lclNum = lclNum; + assertion.op1.lcl.ssaNum = op1->AsLclVarCommon()->GetSsaNum(); + vn = optConservativeNormalVN(op1); + assertion.op1.vn = vn; assertion.assertionKind = assertionKind; assertion.op2.kind = O2K_CONST_INT; @@ -1597,7 +1540,7 @@ AssertionIndex Compiler::optFinalizeCreatingAssertion(AssertionDsc* assertion) } // TODO: only copy assertions rely on valid SSA number so we could generate more assertions here - if ((assertion->op1.kind != O1K_VALUE_NUMBER) && (assertion->op1.lcl.ssaNum == SsaConfig::RESERVED_SSA_NUM)) + if (assertion->op1.lcl.ssaNum == SsaConfig::RESERVED_SSA_NUM) { return NO_ASSERTION_INDEX; } @@ -1866,7 +1809,6 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion) case O1K_BOUND_LOOP_BND: case O1K_CONSTANT_LOOP_BND: case O1K_CONSTANT_LOOP_BND_UN: - case O1K_VALUE_NUMBER: assert(!optLocalAssertionProp); break; default: @@ -1887,9 +1829,6 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion) assert((lvaGetDesc(assertion->op1.lcl.lclNum)->lvType != TYP_REF) || (assertion->op2.u1.iconVal == 0) || doesMethodHaveFrozenObjects()); break; - case O1K_VALUE_NUMBER: - assert((vnStore->TypeOfVN(assertion->op1.vn) != TYP_REF) || (assertion->op2.u1.iconVal == 0)); - break; default: break; } @@ -2327,8 +2266,8 @@ AssertionInfo Compiler::optAssertionGenJtrue(GenTree* tree) std::swap(op1, op2); } // Validate op1 and op2 - if ((op1->gtOper != GT_CALL) || (op1->AsCall()->gtCallType != CT_HELPER) || (op1->TypeGet() != TYP_REF) || // op1 - (op2->gtOper != GT_CNS_INT) || (op2->AsIntCon()->gtIconVal != 0)) // op2 + if (!op1->OperIs(GT_CALL) || !op1->AsCall()->IsHelperCall() || !op1->TypeIs(TYP_REF) || // op1 + !op2->OperIs(GT_CNS_INT) || (op2->AsIntCon()->gtIconVal != 0)) // op2 { return NO_ASSERTION_INDEX; } @@ -2827,6 +2766,16 @@ GenTree* Compiler::optVNBasedFoldConstExpr(BasicBlock* block, GenTree* parent, G // Check if node evaluates to a constant if (!vnStore->IsVNConstant(vnCns)) { + // Last chance - propagate VNF_PtrToLoc(lcl, offset) as GT_LCL_ADDR node + VNFuncApp funcApp; + if (((tree->gtFlags & GTF_SIDE_EFFECT) == 0) && vnStore->GetVNFunc(vnCns, &funcApp) && + (funcApp.m_func == VNF_PtrToLoc)) + { + unsigned lcl = (unsigned)vnStore->CoercedConstantValue(funcApp.m_args[0]); + unsigned offs = (unsigned)vnStore->CoercedConstantValue(funcApp.m_args[1]); + return gtNewLclAddrNode(lcl, offs, tree->TypeGet()); + } + return nullptr; } @@ -3991,6 +3940,18 @@ void Compiler::optAssertionProp_RangeProperties(ASSERT_VALARG_TP assertions, { AssertionDsc* curAssertion = optGetAssertion(GetAssertionIndex(index)); + // if treeVN has a bound-check assertion where it's an index, then + // it means it's not negative, example: + // + // array[idx] = 42; // creates 'BoundsCheckNoThrow' assertion + // return idx % 8; // idx is known to be never negative here, hence, MOD->UMOD + // + if (curAssertion->IsBoundsCheckNoThrow() && (curAssertion->op1.bnd.vnIdx == treeVN)) + { + *isKnownNonNegative = true; + continue; + } + // First, analyze possible X ==/!= CNS assertions. if (curAssertion->IsConstantInt32Assertion() && (curAssertion->op1.vn == treeVN)) { @@ -4109,7 +4070,7 @@ GenTree* Compiler::optAssertionProp_ModDiv(ASSERT_VALARG_TP assertions, GenTreeO } //------------------------------------------------------------------------ -// optAssertionProp_Return: Try and optimize a GT_RETURN via assertions. +// optAssertionProp_Return: Try and optimize a GT_RETURN/GT_SWIFT_ERROR_RET via assertions. // // Propagates ZEROOBJ for the return value. // @@ -4124,9 +4085,9 @@ GenTree* Compiler::optAssertionProp_ModDiv(ASSERT_VALARG_TP assertions, GenTreeO // Notes: // stmt may be nullptr during local assertion prop // -GenTree* Compiler::optAssertionProp_Return(ASSERT_VALARG_TP assertions, GenTreeUnOp* ret, Statement* stmt) +GenTree* Compiler::optAssertionProp_Return(ASSERT_VALARG_TP assertions, GenTreeOp* ret, Statement* stmt) { - GenTree* retValue = ret->gtGetOp1(); + GenTree* retValue = ret->GetReturnValue(); // Only propagate zeroes that lowering can deal with. if (!ret->TypeIs(TYP_VOID) && varTypeIsStruct(retValue) && !varTypeIsStruct(info.compRetNativeType)) @@ -5512,7 +5473,8 @@ GenTree* Compiler::optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree, return optAssertionProp_BlockStore(assertions, tree->AsBlk(), stmt); case GT_RETURN: - return optAssertionProp_Return(assertions, tree->AsUnOp(), stmt); + case GT_SWIFT_ERROR_RET: + return optAssertionProp_Return(assertions, tree->AsOp(), stmt); case GT_MOD: case GT_DIV: @@ -5679,8 +5641,7 @@ void Compiler::optImpliedByTypeOfAssertions(ASSERT_TP& activeAssertions) } // impAssertion must be a Non Null assertion on lclNum - if ((impAssertion->assertionKind != OAK_NOT_EQUAL) || - ((impAssertion->op1.kind != O1K_LCLVAR) && (impAssertion->op1.kind != O1K_VALUE_NUMBER)) || + if ((impAssertion->assertionKind != OAK_NOT_EQUAL) || (impAssertion->op1.kind != O1K_LCLVAR) || (impAssertion->op2.kind != O2K_CONST_INT) || (impAssertion->op1.vn != chkAssertion->op1.vn)) { continue; diff --git a/src/coreclr/jit/block.cpp b/src/coreclr/jit/block.cpp index 60dbce6aaf00..ecee292264ec 100644 --- a/src/coreclr/jit/block.cpp +++ b/src/coreclr/jit/block.cpp @@ -137,14 +137,17 @@ void FlowEdge::addLikelihood(weight_t addedLikelihood) // AllSuccessorEnumerator: Construct an instance of the enumerator. // // Arguments: -// comp - Compiler instance -// block - The block whose successors are to be iterated +// comp - Compiler instance +// block - The block whose successors are to be iterated +// useProfile - If true, determines the order of successors visited using profile data // -AllSuccessorEnumerator::AllSuccessorEnumerator(Compiler* comp, BasicBlock* block) +AllSuccessorEnumerator::AllSuccessorEnumerator(Compiler* comp, BasicBlock* block, const bool useProfile /* = false */) : m_block(block) { m_numSuccs = 0; - block->VisitAllSuccs(comp, [this](BasicBlock* succ) { + block->VisitAllSuccs( + comp, + [this](BasicBlock* succ) { if (m_numSuccs < ArrLen(m_successors)) { m_successors[m_numSuccs] = succ; @@ -152,18 +155,22 @@ AllSuccessorEnumerator::AllSuccessorEnumerator(Compiler* comp, BasicBlock* block m_numSuccs++; return BasicBlockVisit::Continue; - }); + }, + useProfile); if (m_numSuccs > ArrLen(m_successors)) { m_pSuccessors = new (comp, CMK_BasicBlock) BasicBlock*[m_numSuccs]; unsigned numSuccs = 0; - block->VisitAllSuccs(comp, [this, &numSuccs](BasicBlock* succ) { + block->VisitAllSuccs( + comp, + [this, &numSuccs](BasicBlock* succ) { assert(numSuccs < m_numSuccs); m_pSuccessors[numSuccs++] = succ; return BasicBlockVisit::Continue; - }); + }, + useProfile); assert(numSuccs == m_numSuccs); } diff --git a/src/coreclr/jit/block.h b/src/coreclr/jit/block.h index 500b5274b6f4..b0baaf941832 100644 --- a/src/coreclr/jit/block.h +++ b/src/coreclr/jit/block.h @@ -413,7 +413,7 @@ class BBEhfSuccList // BasicBlockFlags: a bitmask of flags for BasicBlock // // clang-format off -enum BasicBlockFlags : unsigned __int64 +enum BasicBlockFlags : uint64_t { #define MAKE_BBFLAG(bit) (1ULL << (bit)) BBF_EMPTY = 0, @@ -500,31 +500,31 @@ enum BasicBlockFlags : unsigned __int64 FORCEINLINE constexpr BasicBlockFlags operator ~(BasicBlockFlags a) { - return (BasicBlockFlags)(~(unsigned __int64)a); + return (BasicBlockFlags)(~(uint64_t)a); } FORCEINLINE constexpr BasicBlockFlags operator |(BasicBlockFlags a, BasicBlockFlags b) { - return (BasicBlockFlags)((unsigned __int64)a | (unsigned __int64)b); + return (BasicBlockFlags)((uint64_t)a | (uint64_t)b); } FORCEINLINE constexpr BasicBlockFlags operator &(BasicBlockFlags a, BasicBlockFlags b) { - return (BasicBlockFlags)((unsigned __int64)a & (unsigned __int64)b); + return (BasicBlockFlags)((uint64_t)a & (uint64_t)b); } FORCEINLINE BasicBlockFlags& operator |=(BasicBlockFlags& a, BasicBlockFlags b) { - return a = (BasicBlockFlags)((unsigned __int64)a | (unsigned __int64)b); + return a = (BasicBlockFlags)((uint64_t)a | (uint64_t)b); } FORCEINLINE BasicBlockFlags& operator &=(BasicBlockFlags& a, BasicBlockFlags b) { - return a = (BasicBlockFlags)((unsigned __int64)a & (unsigned __int64)b); + return a = (BasicBlockFlags)((uint64_t)a & (uint64_t)b); } enum class BasicBlockVisit @@ -587,10 +587,6 @@ struct FlowEdge // The destination of the control flow BasicBlock* m_destBlock; - // Edge weights - weight_t m_edgeWeightMin; - weight_t m_edgeWeightMax; - // Likelihood that m_sourceBlock transfers control along this edge. // Values in range [0..1] weight_t m_likelihood; @@ -606,8 +602,6 @@ struct FlowEdge : m_nextPredEdge(rest) , m_sourceBlock(sourceBlock) , m_destBlock(destBlock) - , m_edgeWeightMin(0) - , m_edgeWeightMax(0) , m_likelihood(0) , m_dupCount(0) #ifdef DEBUG @@ -655,24 +649,6 @@ struct FlowEdge m_destBlock = newBlock; } - weight_t edgeWeightMin() const - { - return m_edgeWeightMin; - } - - weight_t edgeWeightMax() const - { - return m_edgeWeightMax; - } - - // These two methods are used to set new values for edge weights. - // They return false if the newWeight is not between the current [min..max] - // when slop is non-zero we allow for the case where our weights might be off by 'slop' - // - bool setEdgeWeightMinChecked(weight_t newWeight, BasicBlock* bDst, weight_t slop, bool* wbUsedSlop); - bool setEdgeWeightMaxChecked(weight_t newWeight, BasicBlock* bDst, weight_t slop, bool* wbUsedSlop); - void setEdgeWeights(weight_t newMinWeight, weight_t newMaxWeight, BasicBlock* bDst); - weight_t getLikelihood() const { assert(m_likelihoodSet); @@ -1280,27 +1256,6 @@ struct BasicBlock : private LIR::Range this->scaleBBWeight(BB_ZERO_WEIGHT); } - // makeBlockHot() - // This is used to override any profiling data - // and force a block to be in the hot region. - // We only call this method for handler entry point - // and only when HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION is 1. - // Doing this helps fgReorderBlocks() by telling - // it to try to move these blocks into the hot region. - // Note that we do this strictly as an optimization, - // not for correctness. fgDetermineFirstColdBlock() - // will find all handler entry points and ensure that - // for now we don't place them in the cold section. - // - void makeBlockHot() - { - if (this->bbWeight == BB_ZERO_WEIGHT) - { - this->RemoveFlags(BBF_RUN_RARELY | BBF_PROF_WEIGHT); - this->bbWeight = 1; - } - } - bool isMaxBBWeight() const { return (bbWeight >= BB_MAX_WEIGHT); @@ -1844,7 +1799,7 @@ struct BasicBlock : private LIR::Range BasicBlockVisit VisitEHEnclosedHandlerSecondPassSuccs(Compiler* comp, TFunc func); template - BasicBlockVisit VisitAllSuccs(Compiler* comp, TFunc func); + BasicBlockVisit VisitAllSuccs(Compiler* comp, TFunc func, const bool useProfile = false); template BasicBlockVisit VisitEHSuccs(Compiler* comp, TFunc func); @@ -2542,7 +2497,7 @@ class AllSuccessorEnumerator public: // Constructs an enumerator of all `block`'s successors. - AllSuccessorEnumerator(Compiler* comp, BasicBlock* block); + AllSuccessorEnumerator(Compiler* comp, BasicBlock* block, const bool useProfile = false); // Gets the block whose successors are enumerated. BasicBlock* Block() diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index 161180a5fcf7..2dc1837dce2c 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -47,22 +47,6 @@ class CodeGen final : public CodeGenInterface private: #if defined(TARGET_XARCH) - // Bit masks used in negating a float or double number. - // This is to avoid creating more than one data constant for these bitmasks when a - // method has more than one GT_NEG operation on floating point values. - CORINFO_FIELD_HANDLE negBitmaskFlt; - CORINFO_FIELD_HANDLE negBitmaskDbl; - - // Bit masks used in computing Math.Abs() of a float or double number. - CORINFO_FIELD_HANDLE absBitmaskFlt; - CORINFO_FIELD_HANDLE absBitmaskDbl; - - // Bit mask used in zeroing the 3rd element of a SIMD12 - CORINFO_FIELD_HANDLE zroSimd12Elm3; - - // Bit mask used in U8 -> double conversion to adjust the result. - CORINFO_FIELD_HANDLE u8ToDblBitmask; - // Generates SSE2 code for the given tree as "Operand BitWiseOp BitMask" void genSSE2BitwiseOp(GenTree* treeNode); @@ -101,6 +85,16 @@ class CodeGen final : public CodeGenInterface } } +#if defined(TARGET_ARM64) + regNumber getNextSIMDRegWithWraparound(regNumber reg) + { + regNumber nextReg = REG_NEXT(reg); + + // Wraparound if necessary, REG_V0 comes next after REG_V31. + return (nextReg > REG_V31) ? REG_V0 : nextReg; + } +#endif // defined(TARGET_ARM64) + static GenTreeIndir indirForm(var_types type, GenTree* base); static GenTreeStoreInd storeIndirForm(var_types type, GenTree* base, GenTree* data); @@ -261,20 +255,23 @@ class CodeGen final : public CodeGenInterface // Prolog functions and data (there are a few exceptions for more generally used things) // - void genEstablishFramePointer(int delta, bool reportUnwindData); -#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - void genFnPrologCalleeRegArgs(); -#else - void genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbered, RegState* regState); -#endif - void genEnregisterIncomingStackArgs(); + void genEstablishFramePointer(int delta, bool reportUnwindData); + void genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed); + regMaskTP genGetParameterHomingTempRegisterCandidates(); + + var_types genParamStackType(LclVarDsc* dsc, const ABIPassingSegment& seg); + void genSpillOrAddRegisterParam(unsigned lclNum, class RegGraph* graph); + void genSpillOrAddNonStandardRegisterParam(unsigned lclNum, regNumber sourceReg, class RegGraph* graph); + void genEnregisterIncomingStackArgs(); #if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) void genEnregisterOSRArgsAndLocals(regNumber initReg, bool* pInitRegZeroed); #else void genEnregisterOSRArgsAndLocals(); #endif + void genHomeStackSegment(unsigned lclNum, const ABIPassingSegment& seg, regNumber initReg, bool* pInitRegZeroed); void genHomeSwiftStructParameters(bool handleStack); + void genHomeStackPartOfSplitParameter(regNumber initReg, bool* initRegStillZeroed); void genCheckUseBlockInit(); #if defined(UNIX_AMD64_ABI) && defined(FEATURE_SIMD) @@ -437,26 +434,7 @@ class CodeGen final : public CodeGenInterface FuncletFrameInfoDsc genFuncletInfo; -#elif defined(TARGET_LOONGARCH64) - - // A set of information that is used by funclet prolog and epilog generation. - // It is collected once, before funclet prologs and epilogs are generated, - // and used by all funclet prologs and epilogs, which must all be the same. - struct FuncletFrameInfoDsc - { - regMaskTP fiSaveRegs; // Set of callee-saved registers saved in the funclet prolog (includes RA) - int fiFunction_CallerSP_to_FP_delta; // Delta between caller SP and the frame pointer in the parent function - // (negative) - int fiSP_to_CalleeSaved_delta; // CalleeSaved register save offset from SP (positive) - int fiCalleeSavedPadding; // CalleeSaved offset padding (positive) - int fiSP_to_PSP_slot_delta; // PSP slot offset from SP (positive) - int fiCallerSP_to_PSP_slot_delta; // PSP slot offset from Caller SP (negative) - int fiSpDelta; // Stack pointer delta (negative) - }; - - FuncletFrameInfoDsc genFuncletInfo; - -#elif defined(TARGET_RISCV64) +#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) // A set of information that is used by funclet prolog and epilog generation. // It is collected once, before funclet prologs and epilogs are generated, @@ -467,7 +445,6 @@ class CodeGen final : public CodeGenInterface int fiFunction_CallerSP_to_FP_delta; // Delta between caller SP and the frame pointer in the parent function // (negative) int fiSP_to_CalleeSaved_delta; // CalleeSaved register save offset from SP (positive) - int fiCalleeSavedPadding; // CalleeSaved offset padding (positive) int fiSP_to_PSP_slot_delta; // PSP slot offset from SP (positive) int fiCallerSP_to_PSP_slot_delta; // PSP slot offset from Caller SP (negative) int fiSpDelta; // Stack pointer delta (negative) @@ -513,7 +490,8 @@ class CodeGen final : public CodeGenInterface MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize), const DebugInfo& di, regNumber base, - bool isJump); + bool isJump, + bool noSafePoint = false); // clang-format on // clang-format off @@ -967,38 +945,35 @@ class CodeGen final : public CodeGenInterface #ifdef FEATURE_HW_INTRINSICS void genHWIntrinsic(GenTreeHWIntrinsic* node); #if defined(TARGET_XARCH) - void genHWIntrinsic_R_RM(GenTreeHWIntrinsic* node, - instruction ins, - emitAttr attr, - regNumber reg, - GenTree* rmOp, - insOpts instOptions = INS_OPTS_NONE); - void genHWIntrinsic_R_RM_I(GenTreeHWIntrinsic* node, instruction ins, emitAttr attr, int8_t ival); + void genHWIntrinsic_R_RM( + GenTreeHWIntrinsic* node, instruction ins, emitAttr attr, regNumber reg, GenTree* rmOp, insOpts instOptions); + void genHWIntrinsic_R_RM_I( + GenTreeHWIntrinsic* node, instruction ins, emitAttr attr, int8_t ival, insOpts instOptions); void genHWIntrinsic_R_R_RM(GenTreeHWIntrinsic* node, instruction ins, emitAttr attr, insOpts instOptions); - void genHWIntrinsic_R_R_RM_I(GenTreeHWIntrinsic* node, instruction ins, emitAttr attr, int8_t ival); - void genHWIntrinsic_R_R_RM_R(GenTreeHWIntrinsic* node, instruction ins, emitAttr attr); + void genHWIntrinsic_R_R_RM_I( + GenTreeHWIntrinsic* node, instruction ins, emitAttr attr, int8_t ival, insOpts instOptions); + void genHWIntrinsic_R_R_RM_R(GenTreeHWIntrinsic* node, instruction ins, emitAttr attr, insOpts instOptions); void genHWIntrinsic_R_R_R_RM(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, GenTree* op3, - insOpts instOptions = INS_OPTS_NONE); - void genHWIntrinsic_R_R_R_RM_I(GenTreeHWIntrinsic* node, instruction ins, emitAttr attr, int8_t ival); + insOpts instOptions); + void genHWIntrinsic_R_R_R_RM_I( + GenTreeHWIntrinsic* node, instruction ins, emitAttr attr, int8_t ival, insOpts instOptions); - void genBaseIntrinsic(GenTreeHWIntrinsic* node); - void genX86BaseIntrinsic(GenTreeHWIntrinsic* node); + void genBaseIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions); + void genX86BaseIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions); void genSSEIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions); void genSSE2Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptions); - void genSSE41Intrinsic(GenTreeHWIntrinsic* node); - void genSSE42Intrinsic(GenTreeHWIntrinsic* node); + void genSSE41Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptions); + void genSSE42Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptions); void genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions); - void genAESIntrinsic(GenTreeHWIntrinsic* node); void genBMI1OrBMI2Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptions); void genFMAIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions); - void genPermuteVar2x(GenTreeHWIntrinsic* node); + void genPermuteVar2x(GenTreeHWIntrinsic* node, insOpts instOptions); void genLZCNTIntrinsic(GenTreeHWIntrinsic* node); - void genPCLMULQDQIntrinsic(GenTreeHWIntrinsic* node); void genPOPCNTIntrinsic(GenTreeHWIntrinsic* node); void genXCNTIntrinsic(GenTreeHWIntrinsic* node, instruction ins); void genX86SerializeIntrinsic(GenTreeHWIntrinsic* node); @@ -1011,13 +986,15 @@ class CodeGen final : public CodeGenInterface HWIntrinsicSwitchCaseBody emitSwCase); void genNonTableDrivenHWIntrinsicsJumpTableFallback(GenTreeHWIntrinsic* node, GenTree* lastOp); + + static insOpts AddEmbBroadcastMode(insOpts instOptions); #endif // defined(TARGET_XARCH) #ifdef TARGET_ARM64 class HWIntrinsicImmOpHelper final { public: - HWIntrinsicImmOpHelper(CodeGen* codeGen, GenTree* immOp, GenTreeHWIntrinsic* intrin); + HWIntrinsicImmOpHelper(CodeGen* codeGen, GenTree* immOp, GenTreeHWIntrinsic* intrin, int immNum = 1); void EmitBegin(); void EmitCaseEnd(); @@ -1269,10 +1246,10 @@ class CodeGen final : public CodeGenInterface void genCall(GenTreeCall* call); void genCallInstruction(GenTreeCall* call X86_ARG(target_ssize_t stackArgBytes)); void genDefinePendingCallLabel(GenTreeCall* call); - void genJmpMethod(GenTree* jmp); + void genJmpPlaceArgs(GenTree* jmp); + void genJmpPlaceVarArgs(); BasicBlock* genCallFinally(BasicBlock* block); #if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - // TODO: refactor for LA. void genCodeForJumpCompare(GenTreeOpCC* tree); #endif #if defined(TARGET_ARM64) @@ -1309,6 +1286,10 @@ class CodeGen final : public CodeGenInterface void genReturn(GenTree* treeNode); +#ifdef SWIFT_SUPPORT + void genSwiftErrorReturn(GenTree* treeNode); +#endif // SWIFT_SUPPORT + #ifdef TARGET_XARCH void genStackPointerConstantAdjustment(ssize_t spDelta, bool trackSpAdjustments); void genStackPointerConstantAdjustmentWithProbe(ssize_t spDelta, bool trackSpAdjustments); @@ -1581,7 +1562,7 @@ class CodeGen final : public CodeGenInterface void inst_TT(instruction ins, emitAttr size, GenTree* op1); void inst_RV_TT(instruction ins, emitAttr size, regNumber op1Reg, GenTree* op2); void inst_RV_RV_IV(instruction ins, emitAttr size, regNumber reg1, regNumber reg2, unsigned ival); - void inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenTree* rmOp, int ival); + void inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenTree* rmOp, int ival, insOpts instOptions); void inst_RV_RV_TT(instruction ins, emitAttr size, regNumber targetReg, @@ -1589,8 +1570,14 @@ class CodeGen final : public CodeGenInterface GenTree* op2, bool isRMW, insOpts instOptions); - void inst_RV_RV_TT_IV( - instruction ins, emitAttr size, regNumber targetReg, regNumber op1Reg, GenTree* op2, int8_t ival, bool isRMW); + void inst_RV_RV_TT_IV(instruction ins, + emitAttr size, + regNumber targetReg, + regNumber op1Reg, + GenTree* op2, + int8_t ival, + bool isRMW, + insOpts instOptions); #endif void inst_set_SV_var(GenTree* tree); diff --git a/src/coreclr/jit/codegenarm.cpp b/src/coreclr/jit/codegenarm.cpp index 2c010f116a26..82deccb99ede 100644 --- a/src/coreclr/jit/codegenarm.cpp +++ b/src/coreclr/jit/codegenarm.cpp @@ -280,7 +280,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre if (targetType == TYP_FLOAT) { // Get a temp integer register - regNumber tmpReg = tree->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(tree); float f = forceCastToFloat(constValue); instGen_Set_Reg_To_Imm(EA_4BYTE, tmpReg, *((int*)(&f))); @@ -293,8 +293,8 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre unsigned* cv = (unsigned*)&constValue; // Get two temp integer registers - regNumber tmpReg1 = tree->ExtractTempReg(); - regNumber tmpReg2 = tree->GetSingleTempReg(); + regNumber tmpReg1 = internalRegisters.Extract(tree); + regNumber tmpReg2 = internalRegisters.GetSingle(tree); instGen_Set_Reg_To_Imm(EA_4BYTE, tmpReg1, cv[0]); instGen_Set_Reg_To_Imm(EA_4BYTE, tmpReg2, cv[1]); @@ -431,9 +431,9 @@ void CodeGen::genLclHeap(GenTree* tree) } // Setup the regTmp, if there is one. - if (tree->AvailableTempRegCount() > 0) + if (internalRegisters.Count(tree) > 0) { - regTmp = tree->ExtractTempReg(); + regTmp = internalRegisters.Extract(tree); } // If we have an outgoing arg area then we must adjust the SP by popping off the @@ -816,7 +816,8 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) sourceIsLocal = true; } - bool dstOnStack = dstAddr->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR); + bool dstOnStack = + dstAddr->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR) || cpObjNode->GetLayout()->IsStackOnly(compiler); #ifdef DEBUG assert(!dstAddr->isContained()); @@ -833,7 +834,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) gcInfo.gcMarkRegPtrVal(REG_WRITE_BARRIER_DST_BYREF, dstAddr->TypeGet()); // Temp register used to perform the sequence of loads and stores. - regNumber tmpReg = cpObjNode->ExtractTempReg(); + regNumber tmpReg = internalRegisters.Extract(cpObjNode); assert(genIsValidIntReg(tmpReg)); if (cpObjNode->IsVolatile()) @@ -1026,18 +1027,18 @@ void CodeGen::genCodeForStoreLclFld(GenTreeLclFld* tree) { // Arm supports unaligned access only for integer types, // convert the storing floating data into 1 or 2 integer registers and write them as int. - regNumber addr = tree->ExtractTempReg(); + regNumber addr = internalRegisters.Extract(tree); emit->emitIns_R_S(INS_lea, EA_PTRSIZE, addr, varNum, offset); if (targetType == TYP_FLOAT) { - regNumber floatAsInt = tree->GetSingleTempReg(); + regNumber floatAsInt = internalRegisters.GetSingle(tree); emit->emitIns_Mov(INS_vmov_f2i, EA_4BYTE, floatAsInt, dataReg, /* canSkip */ false); emit->emitIns_R_R(INS_str, EA_4BYTE, floatAsInt, addr); } else { - regNumber halfdoubleAsInt1 = tree->ExtractTempReg(); - regNumber halfdoubleAsInt2 = tree->GetSingleTempReg(); + regNumber halfdoubleAsInt1 = internalRegisters.Extract(tree); + regNumber halfdoubleAsInt2 = internalRegisters.GetSingle(tree); emit->emitIns_R_R_R(INS_vmov_d2i, EA_8BYTE, halfdoubleAsInt1, halfdoubleAsInt2, dataReg); emit->emitIns_R_R_I(INS_str, EA_4BYTE, halfdoubleAsInt1, addr, 0); emit->emitIns_R_R_I(INS_str, EA_4BYTE, halfdoubleAsInt1, addr, 4); @@ -1209,7 +1210,7 @@ void CodeGen::genCkfinite(GenTree* treeNode) emitter* emit = GetEmitter(); var_types targetType = treeNode->TypeGet(); - regNumber intReg = treeNode->GetSingleTempReg(); + regNumber intReg = internalRegisters.GetSingle(treeNode); regNumber fpReg = genConsumeReg(treeNode->AsOp()->gtOp1); regNumber targetReg = treeNode->GetRegNum(); @@ -1592,7 +1593,7 @@ void CodeGen::genFloatToIntCast(GenTree* treeNode) genConsumeOperands(treeNode->AsOp()); - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); assert(insVcvt != INS_invalid); GetEmitter()->emitIns_R_R(insVcvt, dstSize, tmpReg, op1->GetRegNum()); @@ -1761,7 +1762,7 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper) // For the tail call case, the helper call is introduced during lower, // so the allocator will arrange things so R0 is not in use here. // - // For the tail jump case, all reg args have been spilled via genJmpMethod, + // For the tail jump case, all reg args have been spilled via genJmpPlaceArgs, // so R0 is likewise not in use. r0InUse = false; } @@ -1926,14 +1927,15 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni void CodeGen::genPushFltRegs(regMaskTP regMask) { - assert(regMask != 0); // Don't call uness we have some registers to push - assert((regMask & RBM_ALLFLOAT) == regMask); // Only floasting point registers should be in regMask + assert(regMask != 0); // Don't call unless we have some registers to push + assert((regMask & RBM_ALLFLOAT) == regMask); // Only floating point registers should be in regMask regNumber lowReg = genRegNumFromMask(genFindLowestBit(regMask)); int slots = genCountBits(regMask); + // regMask should be contiguously set - regMaskTP tmpMask = ((regMask >> lowReg) + 1); // tmpMask should have a single bit set - assert((tmpMask & (tmpMask - 1)) == 0); + regMaskSmall tmpMask = ((regMask.getLow() >> lowReg) + 1); // tmpMask should have a single bit set + assert(genMaxOneBit(tmpMask)); assert(lowReg == REG_F16); // Currently we expect to start at F16 in the unwind codes // Our calling convention requires that we only use vpush for TYP_DOUBLE registers @@ -1951,8 +1953,8 @@ void CodeGen::genPopFltRegs(regMaskTP regMask) regNumber lowReg = genRegNumFromMask(genFindLowestBit(regMask)); int slots = genCountBits(regMask); // regMask should be contiguously set - regMaskTP tmpMask = ((regMask >> lowReg) + 1); // tmpMask should have a single bit set - assert((tmpMask & (tmpMask - 1)) == 0); + regMaskSmall tmpMask = ((regMask.getLow() >> lowReg) + 1); // tmpMask should have a single bit set + assert(genMaxOneBit(tmpMask)); // Our calling convention requires that we only use vpop for TYP_DOUBLE registers noway_assert(floatRegCanHoldType(lowReg, TYP_DOUBLE)); @@ -2191,7 +2193,7 @@ void CodeGen::genPopCalleeSavedRegisters(bool jmpEpilog) genUsedPopToReturn = false; } - assert(FitsIn(maskPopRegsInt)); + assert(FitsIn(maskPopRegsInt.getLow())); inst_IV(INS_pop, (int)maskPopRegsInt); compiler->unwindPopMaskInt(maskPopRegsInt); } @@ -2319,7 +2321,7 @@ void CodeGen::genFuncletProlog(BasicBlock* block) regMaskTP maskStackAlloc = genStackAllocRegisterMask(genFuncletInfo.fiSpDelta, maskPushRegsFloat); maskPushRegsInt |= maskStackAlloc; - assert(FitsIn(maskPushRegsInt)); + assert(FitsIn(maskPushRegsInt.getLow())); inst_IV(INS_push, (int)maskPushRegsInt); compiler->unwindPushMaskInt(maskPushRegsInt); @@ -2436,7 +2438,7 @@ void CodeGen::genFuncletEpilog() compiler->unwindPopMaskFloat(maskPopRegsFloat); } - assert(FitsIn(maskPopRegsInt)); + assert(FitsIn(maskPopRegsInt.getLow())); inst_IV(INS_pop, (int)maskPopRegsInt); compiler->unwindPopMaskInt(maskPopRegsInt); diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index cd1b1558d93e..4ecbcc80a1ce 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -922,7 +922,7 @@ void CodeGen::genSaveCalleeSavedRegistersHelp(regMaskTP regsToSaveMask, int lowe assert((spDelta % 16) == 0); // We also can save FP and LR, even though they are not in RBM_CALLEE_SAVED. - assert(regsToSaveCount <= genCountBits(RBM_CALLEE_SAVED | RBM_FP | RBM_LR)); + assert(regsToSaveCount <= genCountBits(regMaskTP(RBM_CALLEE_SAVED | RBM_FP | RBM_LR))); // Save integer registers at higher addresses than floating-point registers. @@ -1035,7 +1035,7 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in assert((spDelta % 16) == 0); // We also can restore FP and LR, even though they are not in RBM_CALLEE_SAVED. - assert(regsToRestoreCount <= genCountBits(RBM_CALLEE_SAVED | RBM_FP | RBM_LR)); + assert(regsToRestoreCount <= genCountBits(regMaskTP(RBM_CALLEE_SAVED | RBM_FP | RBM_LR))); // Point past the end, to start. We predecrement to find the offset to load from. static_assert_no_msg(REGSIZE_BYTES == FPSAVE_REGSIZE_BYTES); @@ -2358,7 +2358,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre double constValue = tree->AsDblCon()->DconValue(); // Make sure we use "movi reg, 0x00" only for positive zero (0.0) and not for negative zero (-0.0) - if (*(__int64*)&constValue == 0) + if (*(int64_t*)&constValue == 0) { // A faster/smaller way to generate 0.0 // We will just zero out the entire vector register for both float and double @@ -2372,7 +2372,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre else { // Get a temp integer register to compute long address. - regNumber addrReg = tree->GetSingleTempReg(); + regNumber addrReg = internalRegisters.GetSingle(tree); // We must load the FP constant from the constant pool // Emit a data section constant for the float or double constant. @@ -2395,73 +2395,57 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre { #if defined(FEATURE_SIMD) case TYP_SIMD8: - { - if (vecCon->IsAllBitsSet()) - { - emit->emitIns_R_I(INS_mvni, attr, targetReg, 0, INS_OPTS_2S); - } - else if (vecCon->IsZero()) - { - emit->emitIns_R_I(INS_movi, attr, targetReg, 0, INS_OPTS_2S); - } - else - { - // Get a temp integer register to compute long address. - regNumber addrReg = tree->GetSingleTempReg(); - - simd8_t constValue; - memcpy(&constValue, &vecCon->gtSimdVal, sizeof(simd8_t)); - - CORINFO_FIELD_HANDLE hnd = emit->emitSimd8Const(constValue); - emit->emitIns_R_C(INS_ldr, attr, targetReg, addrReg, hnd, 0); - } - break; - } - case TYP_SIMD12: - { - if (vecCon->IsAllBitsSet()) - { - emit->emitIns_R_I(INS_mvni, attr, targetReg, 0, INS_OPTS_4S); - } - else if (vecCon->IsZero()) - { - emit->emitIns_R_I(INS_movi, attr, targetReg, 0, INS_OPTS_4S); - } - else - { - // Get a temp integer register to compute long address. - regNumber addrReg = tree->GetSingleTempReg(); - - simd16_t constValue = {}; - memcpy(&constValue, &vecCon->gtSimdVal, sizeof(simd12_t)); - - CORINFO_FIELD_HANDLE hnd = emit->emitSimd16Const(constValue); - emit->emitIns_R_C(INS_ldr, attr, targetReg, addrReg, hnd, 0); - } - break; - } - case TYP_SIMD16: { + // We ignore any differences between SIMD12 and SIMD16 here if we can broadcast the value + // via mvni/movi. + const bool is8 = tree->TypeIs(TYP_SIMD8); if (vecCon->IsAllBitsSet()) { - emit->emitIns_R_I(INS_mvni, attr, targetReg, 0, INS_OPTS_4S); + emit->emitIns_R_I(INS_mvni, attr, targetReg, 0, is8 ? INS_OPTS_2S : INS_OPTS_4S); } else if (vecCon->IsZero()) { - emit->emitIns_R_I(INS_movi, attr, targetReg, 0, INS_OPTS_4S); + emit->emitIns_R_I(INS_movi, attr, targetReg, 0, is8 ? INS_OPTS_2S : INS_OPTS_4S); } else { - // Get a temp integer register to compute long address. - regNumber addrReg = tree->GetSingleTempReg(); - - simd16_t constValue; - memcpy(&constValue, &vecCon->gtSimdVal, sizeof(simd16_t)); - - CORINFO_FIELD_HANDLE hnd = emit->emitSimd16Const(constValue); - emit->emitIns_R_C(INS_ldr, attr, targetReg, addrReg, hnd, 0); + simd16_t val = vecCon->gtSimd16Val; + if (ElementsAreSame(val.i32, is8 ? 2 : 4) && + emitter::emitIns_valid_imm_for_movi(val.i32[0], EA_4BYTE)) + { + emit->emitIns_R_I(INS_movi, attr, targetReg, val.i32[0], is8 ? INS_OPTS_2S : INS_OPTS_4S); + } + else if (ElementsAreSame(val.i16, is8 ? 4 : 8) && + emitter::emitIns_valid_imm_for_movi(val.i16[0], EA_2BYTE)) + { + emit->emitIns_R_I(INS_movi, attr, targetReg, val.i16[0], is8 ? INS_OPTS_4H : INS_OPTS_8H); + } + else if (ElementsAreSame(val.i8, is8 ? 8 : 16) && + emitter::emitIns_valid_imm_for_movi(val.i8[0], EA_1BYTE)) + { + emit->emitIns_R_I(INS_movi, attr, targetReg, val.i8[0], is8 ? INS_OPTS_8B : INS_OPTS_16B); + } + else + { + // Get a temp integer register to compute long address. + regNumber addrReg = internalRegisters.GetSingle(tree); + CORINFO_FIELD_HANDLE hnd; + if (is8) + { + simd8_t constValue; + memcpy(&constValue, &vecCon->gtSimdVal, sizeof(simd8_t)); + hnd = emit->emitSimd8Const(constValue); + } + else + { + simd16_t constValue; + memcpy(&constValue, &vecCon->gtSimdVal, sizeof(simd16_t)); + hnd = emit->emitSimd16Const(constValue); + } + emit->emitIns_R_C(INS_ldr, attr, targetReg, addrReg, hnd, 0); + } } break; } @@ -2655,6 +2639,48 @@ void CodeGen::genCodeForBinary(GenTreeOp* tree) genProduceReg(tree); return; } + else if (op2->OperIs(GT_ROR) && op2->isContained()) + { + assert(varTypeIsIntegral(tree)); + + GenTree* a = op1; + GenTree* b = op2->gtGetOp1(); + GenTree* c = op2->gtGetOp2(); + + // The rotate amount needs to be contained as well + assert(c->isContained() && c->IsCnsIntOrI()); + + instruction ins = genGetInsForOper(tree->OperGet(), targetType); + insOpts opt = INS_OPTS_NONE; + + if ((tree->gtFlags & GTF_SET_FLAGS) != 0) + { + // A subset of operations can still set flags + + switch (oper) + { + case GT_AND: + { + ins = INS_ands; + break; + } + + default: + { + noway_assert(!"Unexpected BinaryOp with GTF_SET_FLAGS set"); + } + } + } + + assert(op2->OperIs(GT_ROR)); + opt = INS_OPTS_ROR; + + emit->emitIns_R_R_R_I(ins, emitActualTypeSize(tree), targetReg, a->GetRegNum(), b->GetRegNum(), + c->AsIntConCommon()->IconValue(), opt); + + genProduceReg(tree); + return; + } else if (op2->OperIs(GT_CAST) && op2->isContained()) { assert(varTypeIsIntegral(tree)); @@ -2990,15 +3016,15 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* lclNode) // Note: treeNode's and op1's registers are already consumed. // // Arguments: -// treeNode - The GT_RETURN or GT_RETFILT tree node with non-struct and non-void type +// treeNode - The GT_RETURN/GT_RETFILT/GT_SWIFT_ERROR_RET tree node with non-struct and non-void type // // Return Value: // None // void CodeGen::genSimpleReturn(GenTree* treeNode) { - assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT); - GenTree* op1 = treeNode->gtGetOp1(); + assert(treeNode->OperIs(GT_RETURN, GT_RETFILT, GT_SWIFT_ERROR_RET)); + GenTree* op1 = treeNode->AsOp()->GetReturnValue(); var_types targetType = treeNode->TypeGet(); assert(targetType != TYP_STRUCT); @@ -3090,12 +3116,12 @@ void CodeGen::genLclHeap(GenTree* tree) // since we don't need any internal registers. if (compiler->info.compInitMem) { - assert(tree->AvailableTempRegCount() == 0); + assert(internalRegisters.Count(tree) == 0); regCnt = targetReg; } else { - regCnt = tree->ExtractTempReg(); + regCnt = internalRegisters.Extract(tree); inst_Mov(size->TypeGet(), regCnt, targetReg, /* canSkip */ true); } @@ -3212,12 +3238,12 @@ void CodeGen::genLclHeap(GenTree* tree) assert(regCnt == REG_NA); if (compiler->info.compInitMem) { - assert(tree->AvailableTempRegCount() == 0); + assert(internalRegisters.Count(tree) == 0); regCnt = targetReg; } else { - regCnt = tree->ExtractTempReg(); + regCnt = internalRegisters.Extract(tree); } instGen_Set_Reg_To_Imm(((unsigned int)amount == amount) ? EA_4BYTE : EA_8BYTE, regCnt, amount); } @@ -3281,7 +3307,7 @@ void CodeGen::genLclHeap(GenTree* tree) // // Setup the regTmp - regNumber regTmp = tree->GetSingleTempReg(); + regNumber regTmp = internalRegisters.GetSingle(tree); BasicBlock* loop = genCreateTempLabel(); BasicBlock* done = genCreateTempLabel(); @@ -3606,7 +3632,8 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) sourceIsLocal = true; } - bool dstOnStack = dstAddr->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR); + bool dstOnStack = + dstAddr->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR) || cpObjNode->GetLayout()->IsStackOnly(compiler); #ifdef DEBUG assert(!dstAddr->isContained()); @@ -3626,7 +3653,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) unsigned slots = layout->GetSlotCount(); // Temp register(s) used to perform the sequence of loads and stores. - regNumber tmpReg = cpObjNode->ExtractTempReg(RBM_ALLINT); + regNumber tmpReg = internalRegisters.Extract(cpObjNode, RBM_ALLINT); regNumber tmpReg2 = REG_NA; assert(genIsValidIntReg(tmpReg)); @@ -3635,7 +3662,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) if (slots > 1) { - tmpReg2 = cpObjNode->ExtractTempReg(RBM_ALLINT); + tmpReg2 = internalRegisters.Extract(cpObjNode, RBM_ALLINT); assert(tmpReg2 != tmpReg); assert(genIsValidIntReg(tmpReg2)); assert(tmpReg2 != REG_WRITE_BARRIER_DST_BYREF); @@ -3688,8 +3715,8 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) regNumber tmpSimdReg2 = REG_NA; if ((slots >= 4) && compiler->IsBaselineSimdIsaSupported()) { - tmpSimdReg1 = cpObjNode->ExtractTempReg(RBM_ALLFLOAT); - tmpSimdReg2 = cpObjNode->ExtractTempReg(RBM_ALLFLOAT); + tmpSimdReg1 = internalRegisters.Extract(cpObjNode, RBM_ALLFLOAT); + tmpSimdReg2 = internalRegisters.Extract(cpObjNode, RBM_ALLFLOAT); } unsigned i = 0; @@ -3768,7 +3795,7 @@ void CodeGen::genTableBasedSwitch(GenTree* treeNode) regNumber idxReg = treeNode->AsOp()->gtOp1->GetRegNum(); regNumber baseReg = treeNode->AsOp()->gtOp2->GetRegNum(); - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); // load the ip-relative offset (which is relative to start of fgFirstBB) GetEmitter()->emitIns_R_R_R(INS_ldr, EA_4BYTE, baseReg, baseReg, idxReg, INS_OPTS_LSL); @@ -3827,7 +3854,7 @@ void CodeGen::genLockedInstructions(GenTreeOp* treeNode) case GT_XAND: { // Grab a temp reg to perform `MVN` for dataReg first. - regNumber tempReg = treeNode->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(treeNode); GetEmitter()->emitIns_R_R(INS_mvn, dataSize, tempReg, dataReg); GetEmitter()->emitIns_R_R_R(INS_ldclral, dataSize, tempReg, (targetReg == REG_NA) ? REG_ZR : targetReg, addrReg); @@ -3860,9 +3887,10 @@ void CodeGen::genLockedInstructions(GenTreeOp* treeNode) // These are imported normally if Atomics aren't supported. assert(!treeNode->OperIs(GT_XORR, GT_XAND)); - regNumber exResultReg = treeNode->ExtractTempReg(RBM_ALLINT); - regNumber storeDataReg = (treeNode->OperGet() == GT_XCHG) ? dataReg : treeNode->ExtractTempReg(RBM_ALLINT); - regNumber loadReg = (targetReg != REG_NA) ? targetReg : storeDataReg; + regNumber exResultReg = internalRegisters.Extract(treeNode, RBM_ALLINT); + regNumber storeDataReg = + (treeNode->OperGet() == GT_XCHG) ? dataReg : internalRegisters.Extract(treeNode, RBM_ALLINT); + regNumber loadReg = (targetReg != REG_NA) ? targetReg : storeDataReg; // Check allocator assumptions // @@ -4013,7 +4041,7 @@ void CodeGen::genCodeForCmpXchg(GenTreeCmpXchg* treeNode) } else { - regNumber exResultReg = treeNode->ExtractTempReg(RBM_ALLINT); + regNumber exResultReg = internalRegisters.Extract(treeNode, RBM_ALLINT); // Check allocator assumptions // @@ -4558,7 +4586,7 @@ void CodeGen::genCkfinite(GenTree* treeNode) emitter* emit = GetEmitter(); // Extract exponent into a register. - regNumber intReg = treeNode->GetSingleTempReg(); + regNumber intReg = internalRegisters.GetSingle(treeNode); regNumber fpReg = genConsumeReg(op1); inst_Mov(targetType, intReg, fpReg, /* canSkip */ false, emitActualTypeSize(treeNode)); @@ -5309,7 +5337,7 @@ void CodeGen::genStoreIndTypeSimd12(GenTreeStoreInd* treeNode) regNumber dataReg = genConsumeReg(data); // Need an additional integer register to extract upper 4 bytes from data. - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); // 8-byte write GetEmitter()->emitIns_R_R(INS_str, EA_8BYTE, dataReg, addrReg); @@ -5344,7 +5372,7 @@ void CodeGen::genLoadIndTypeSimd12(GenTreeIndir* treeNode) regNumber addrReg = genConsumeReg(addr); // Need an additional int register to read upper 4 bytes, which is different from targetReg - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); // 8-byte read GetEmitter()->emitIns_R_R(INS_ldr, EA_8BYTE, tgtReg, addrReg); diff --git a/src/coreclr/jit/codegenarm64test.cpp b/src/coreclr/jit/codegenarm64test.cpp index 52633ed6733e..8cf6a5181ef8 100644 --- a/src/coreclr/jit/codegenarm64test.cpp +++ b/src/coreclr/jit/codegenarm64test.cpp @@ -4572,34 +4572,12 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_S); // EOR ., /M, ., . theEmitter->emitIns_R_R_R(INS_sve_orr, EA_SCALABLE, REG_V29, REG_P7, REG_V31, INS_OPTS_SCALABLE_D); // ORR ., /M, ., . - - // IF_SVE_AB_3A theEmitter->emitIns_R_R_R(INS_sve_add, EA_SCALABLE, REG_V5, REG_P6, REG_V7, INS_OPTS_SCALABLE_B); // ADD ., /M, ., . theEmitter->emitIns_R_R_R(INS_sve_sub, EA_SCALABLE, REG_V15, REG_P7, REG_V29, INS_OPTS_SCALABLE_H); // SUB ., /M, ., . theEmitter->emitIns_R_R_R(INS_sve_subr, EA_SCALABLE, REG_V2, REG_P0, REG_V13, INS_OPTS_SCALABLE_S); // SUBR ., /M, ., . - -#ifdef ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED - // IF_SVE_AB_3B - theEmitter->emitIns_R_R_R(INS_sve_addpt, EA_SCALABLE, REG_V0, REG_P1, REG_V2, - INS_OPTS_SCALABLE_D); // ADDPT .D, /M, .D, .D - theEmitter->emitIns_R_R_R(INS_sve_subpt, EA_SCALABLE, REG_V0, REG_P1, REG_V2, - INS_OPTS_SCALABLE_D); // SUBPT .D, /M, .D, .D -#endif // ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED - - // IF_SVE_AC_3A - theEmitter->emitIns_R_R_R(INS_sve_sdiv, EA_SCALABLE, REG_V3, REG_P2, REG_V9, - INS_OPTS_SCALABLE_S); // SDIV ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_sdivr, EA_SCALABLE, REG_V31, REG_P3, REG_V29, - INS_OPTS_SCALABLE_D); // SDIVR ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_udiv, EA_SCALABLE, REG_V1, REG_P0, REG_V0, - INS_OPTS_SCALABLE_S); // UDIV ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_udivr, EA_SCALABLE, REG_V13, REG_P7, REG_V15, - INS_OPTS_SCALABLE_D); // UDIVR ., /M, ., . - - // IF_SVE_AD_3A theEmitter->emitIns_R_R_R(INS_sve_smax, EA_SCALABLE, REG_V24, REG_P0, REG_V2, INS_OPTS_SCALABLE_B); // SMAX ., /M, ., . theEmitter->emitIns_R_R_R(INS_sve_smin, EA_SCALABLE, REG_V9, REG_P1, REG_V27, @@ -4612,14 +4590,108 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_S); // UMAX ., /M, ., . theEmitter->emitIns_R_R_R(INS_sve_umin, EA_SCALABLE, REG_V12, REG_P7, REG_V0, INS_OPTS_SCALABLE_D); // UMIN ., /M, ., . - - // IF_SVE_AE_3A theEmitter->emitIns_R_R_R(INS_sve_mul, EA_SCALABLE, REG_V5, REG_P1, REG_V3, INS_OPTS_SCALABLE_D); // MUL ., /M, ., . theEmitter->emitIns_R_R_R(INS_sve_smulh, EA_SCALABLE, REG_V17, REG_P5, REG_V5, INS_OPTS_SCALABLE_S); // SMULH ., /M, ., . theEmitter->emitIns_R_R_R(INS_sve_umulh, EA_SCALABLE, REG_V12, REG_P2, REG_V24, INS_OPTS_SCALABLE_B); // UMULH ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_asr, EA_SCALABLE, REG_V5, REG_P0, REG_V21, + INS_OPTS_SCALABLE_S); // ASR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_asrr, EA_SCALABLE, REG_V1, REG_P7, REG_V20, + INS_OPTS_SCALABLE_B); // ASRR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_lsl, EA_SCALABLE, REG_V0, REG_P2, REG_V0, + INS_OPTS_SCALABLE_H); // LSL ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_lslr, EA_SCALABLE, REG_V27, REG_P6, REG_V31, + INS_OPTS_SCALABLE_D); // LSLR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_lsr, EA_SCALABLE, REG_V5, REG_P5, REG_V6, + INS_OPTS_SCALABLE_B); // LSR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_lsrr, EA_SCALABLE, REG_V15, REG_P4, REG_V17, + INS_OPTS_SCALABLE_S); // LSRR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_shadd, EA_SCALABLE, REG_V15, REG_P0, REG_V10, + INS_OPTS_SCALABLE_B); // SHADD ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_shsub, EA_SCALABLE, REG_V16, REG_P1, REG_V11, + INS_OPTS_SCALABLE_H); // SHSUB ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_shsubr, EA_SCALABLE, REG_V17, REG_P2, REG_V12, + INS_OPTS_SCALABLE_S); // SHSUBR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_srhadd, EA_SCALABLE, REG_V18, REG_P3, REG_V13, + INS_OPTS_SCALABLE_D); // SRHADD ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_uhadd, EA_SCALABLE, REG_V19, REG_P4, REG_V14, + INS_OPTS_SCALABLE_B); // UHADD ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_uhsub, EA_SCALABLE, REG_V20, REG_P5, REG_V15, + INS_OPTS_SCALABLE_H); // UHSUB ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_uhsubr, EA_SCALABLE, REG_V21, REG_P6, REG_V16, + INS_OPTS_SCALABLE_S); // UHSUBR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_urhadd, EA_SCALABLE, REG_V22, REG_P7, REG_V17, + INS_OPTS_SCALABLE_D); // URHADD ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_addp, EA_SCALABLE, REG_V23, REG_P6, REG_V18, + INS_OPTS_SCALABLE_B); // ADDP ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_smaxp, EA_SCALABLE, REG_V24, REG_P5, REG_V19, + INS_OPTS_SCALABLE_H); // SMAXP ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_sminp, EA_SCALABLE, REG_V25, REG_P4, REG_V20, + INS_OPTS_SCALABLE_S); // SMINP ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_umaxp, EA_SCALABLE, REG_V26, REG_P3, REG_V21, + INS_OPTS_SCALABLE_D); // UMAXP ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_uminp, EA_SCALABLE, REG_V27, REG_P2, REG_V22, + INS_OPTS_SCALABLE_B); // UMINP ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_sqadd, EA_SCALABLE, REG_V28, REG_P1, REG_V23, + INS_OPTS_SCALABLE_B); // SQADD ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_sqsub, EA_SCALABLE, REG_V29, REG_P0, REG_V24, + INS_OPTS_SCALABLE_H); // SQSUB ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_sqsubr, EA_SCALABLE, REG_V30, REG_P1, REG_V25, + INS_OPTS_SCALABLE_H); // SQSUBR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_suqadd, EA_SCALABLE, REG_V31, REG_P2, REG_V26, + INS_OPTS_SCALABLE_B); // SUQADD ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_uqadd, EA_SCALABLE, REG_V0, REG_P3, REG_V27, + INS_OPTS_SCALABLE_S); // UQADD ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_uqsub, EA_SCALABLE, REG_V1, REG_P4, REG_V28, + INS_OPTS_SCALABLE_D); // UQSUB ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_uqsubr, EA_SCALABLE, REG_V2, REG_P5, REG_V29, + INS_OPTS_SCALABLE_B); // UQSUBR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_usqadd, EA_SCALABLE, REG_V3, REG_P6, REG_V30, + INS_OPTS_SCALABLE_B); // USQADD ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_sqrshl, EA_SCALABLE, REG_V4, REG_P7, REG_V31, + INS_OPTS_SCALABLE_B); // SQRSHL ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_sqrshlr, EA_SCALABLE, REG_V5, REG_P0, REG_V30, + INS_OPTS_SCALABLE_H); // SQRSHLR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_sqshl, EA_SCALABLE, REG_V6, REG_P1, REG_V29, + INS_OPTS_SCALABLE_S); // SQSHL ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_sqshlr, EA_SCALABLE, REG_V7, REG_P2, REG_V28, + INS_OPTS_SCALABLE_D); // SQSHLR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_srshl, EA_SCALABLE, REG_V8, REG_P3, REG_V27, + INS_OPTS_SCALABLE_B); // SRSHL ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_srshlr, EA_SCALABLE, REG_V9, REG_P4, REG_V26, + INS_OPTS_SCALABLE_H); // SRSHLR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_uqrshl, EA_SCALABLE, REG_V10, REG_P5, REG_V25, + INS_OPTS_SCALABLE_S); // UQRSHL ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_uqrshlr, EA_SCALABLE, REG_V11, REG_P6, REG_V24, + INS_OPTS_SCALABLE_D); // UQRSHLR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_uqshl, EA_SCALABLE, REG_V12, REG_P7, REG_V23, + INS_OPTS_SCALABLE_B); // UQSHL ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_uqshlr, EA_SCALABLE, REG_V13, REG_P0, REG_V22, + INS_OPTS_SCALABLE_H); // UQSHLR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_urshl, EA_SCALABLE, REG_V14, REG_P1, REG_V21, + INS_OPTS_SCALABLE_S); // URSHL ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_urshlr, EA_SCALABLE, REG_V15, REG_P2, REG_V20, + INS_OPTS_SCALABLE_D); // URSHLR ., /M, ., . + +#ifdef ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED + // IF_SVE_AB_3B + theEmitter->emitIns_R_R_R(INS_sve_addpt, EA_SCALABLE, REG_V0, REG_P1, REG_V2, + INS_OPTS_SCALABLE_D); // ADDPT .D, /M, .D, .D + theEmitter->emitIns_R_R_R(INS_sve_subpt, EA_SCALABLE, REG_V0, REG_P1, REG_V2, + INS_OPTS_SCALABLE_D); // SUBPT .D, /M, .D, .D +#endif // ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED + + // IF_SVE_AC_3A + theEmitter->emitIns_R_R_R(INS_sve_sdiv, EA_SCALABLE, REG_V3, REG_P2, REG_V9, + INS_OPTS_SCALABLE_S); // SDIV ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_sdivr, EA_SCALABLE, REG_V31, REG_P3, REG_V29, + INS_OPTS_SCALABLE_D); // SDIVR ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_udiv, EA_SCALABLE, REG_V1, REG_P0, REG_V0, + INS_OPTS_SCALABLE_S); // UDIV ., /M, ., . + theEmitter->emitIns_R_R_R(INS_sve_udivr, EA_SCALABLE, REG_V13, REG_P7, REG_V15, + INS_OPTS_SCALABLE_D); // UDIVR ., /M, ., . // IF_SVE_AH_3A theEmitter->emitIns_R_R_R(INS_sve_movprfx, EA_SCALABLE, REG_V13, REG_P0, REG_V31, @@ -4711,20 +4783,6 @@ void CodeGen::genArm64EmitterUnitTestsSve() theEmitter->emitIns_R_R_I(INS_sve_uqshl, EA_SCALABLE, REG_V0, REG_P2, 63, INS_OPTS_SCALABLE_D); // UQSHL ., /M, ., # - // IF_SVE_AN_3A - theEmitter->emitIns_R_R_R(INS_sve_asr, EA_SCALABLE, REG_V5, REG_P0, REG_V21, - INS_OPTS_SCALABLE_S); // ASR ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_asrr, EA_SCALABLE, REG_V1, REG_P7, REG_V20, - INS_OPTS_SCALABLE_B); // ASRR ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_lsl, EA_SCALABLE, REG_V0, REG_P2, REG_V0, - INS_OPTS_SCALABLE_H); // LSL ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_lslr, EA_SCALABLE, REG_V27, REG_P6, REG_V31, - INS_OPTS_SCALABLE_D); // LSLR ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_lsr, EA_SCALABLE, REG_V5, REG_P5, REG_V6, - INS_OPTS_SCALABLE_B); // LSR ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_lsrr, EA_SCALABLE, REG_V15, REG_P4, REG_V17, - INS_OPTS_SCALABLE_S); // LSRR ., /M, ., . - // IF_SVE_AO_3A theEmitter->emitIns_R_R_R(INS_sve_asr, EA_SCALABLE, REG_V4, REG_P3, REG_V24, INS_OPTS_SCALABLE_B, INS_SCALABLE_OPTS_WIDE); // ASR ., /M, ., .D @@ -4802,11 +4860,11 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_D); // CLASTB ., , ., . // IF_SVE_CN_3A - theEmitter->emitIns_R_R_R(INS_sve_clasta, EA_2BYTE, REG_V12, REG_P1, REG_V15, INS_OPTS_SCALABLE_H, + theEmitter->emitIns_R_R_R(INS_sve_clasta, EA_SCALABLE, REG_V12, REG_P1, REG_V15, INS_OPTS_SCALABLE_H, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CLASTA , , , . - theEmitter->emitIns_R_R_R(INS_sve_clastb, EA_4BYTE, REG_V13, REG_P2, REG_V16, INS_OPTS_SCALABLE_S, + theEmitter->emitIns_R_R_R(INS_sve_clastb, EA_SCALABLE, REG_V13, REG_P2, REG_V16, INS_OPTS_SCALABLE_S, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CLASTB , , , . - theEmitter->emitIns_R_R_R(INS_sve_clastb, EA_8BYTE, REG_V14, REG_P0, REG_V17, INS_OPTS_SCALABLE_D, + theEmitter->emitIns_R_R_R(INS_sve_clastb, EA_SCALABLE, REG_V14, REG_P0, REG_V17, INS_OPTS_SCALABLE_D, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CLASTB , , , . // IF_SVE_CO_3A @@ -4940,8 +4998,9 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_SCALABLE_OPTS_PREDICATE_MERGE); /* MOV .B, /M, .B */ // IF_SVE_CZ_4A_L - theEmitter->emitIns_R_R(INS_sve_mov, EA_SCALABLE, REG_P0, REG_P15, INS_OPTS_SCALABLE_B); /* MOV .B, .B - */ + theEmitter->emitIns_Mov(INS_sve_mov, EA_SCALABLE, REG_P0, REG_P15, /* canSkip */ false, + INS_OPTS_SCALABLE_B); /* MOV .B, .B + */ // IF_SVE_DA_4A theEmitter->emitIns_R_R_R_R(INS_sve_brkpa, EA_SCALABLE, REG_P0, REG_P1, REG_P10, REG_P15, @@ -5011,80 +5070,6 @@ void CodeGen::genArm64EmitterUnitTestsSve() theEmitter->emitIns_R_R_R(INS_sve_cntp, EA_8BYTE, REG_R29, REG_P0, REG_P15, INS_OPTS_SCALABLE_D); // CNTP , , . - // IF_SVE_EP_3A - theEmitter->emitIns_R_R_R(INS_sve_shadd, EA_SCALABLE, REG_V15, REG_P0, REG_V10, - INS_OPTS_SCALABLE_B); // SHADD ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_shsub, EA_SCALABLE, REG_V16, REG_P1, REG_V11, - INS_OPTS_SCALABLE_H); // SHSUB ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_shsubr, EA_SCALABLE, REG_V17, REG_P2, REG_V12, - INS_OPTS_SCALABLE_S); // SHSUBR ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_srhadd, EA_SCALABLE, REG_V18, REG_P3, REG_V13, - INS_OPTS_SCALABLE_D); // SRHADD ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_uhadd, EA_SCALABLE, REG_V19, REG_P4, REG_V14, - INS_OPTS_SCALABLE_B); // UHADD ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_uhsub, EA_SCALABLE, REG_V20, REG_P5, REG_V15, - INS_OPTS_SCALABLE_H); // UHSUB ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_uhsubr, EA_SCALABLE, REG_V21, REG_P6, REG_V16, - INS_OPTS_SCALABLE_S); // UHSUBR ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_urhadd, EA_SCALABLE, REG_V22, REG_P7, REG_V17, - INS_OPTS_SCALABLE_D); // URHADD ., /M, ., . - - // IF_SVE_ER_3A - theEmitter->emitIns_R_R_R(INS_sve_addp, EA_SCALABLE, REG_V23, REG_P6, REG_V18, - INS_OPTS_SCALABLE_B); // ADDP ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_smaxp, EA_SCALABLE, REG_V24, REG_P5, REG_V19, - INS_OPTS_SCALABLE_H); // SMAXP ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_sminp, EA_SCALABLE, REG_V25, REG_P4, REG_V20, - INS_OPTS_SCALABLE_S); // SMINP ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_umaxp, EA_SCALABLE, REG_V26, REG_P3, REG_V21, - INS_OPTS_SCALABLE_D); // UMAXP ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_uminp, EA_SCALABLE, REG_V27, REG_P2, REG_V22, - INS_OPTS_SCALABLE_B); // UMINP ., /M, ., . - - // IF_SVE_ET_3A - theEmitter->emitIns_R_R_R(INS_sve_sqadd, EA_SCALABLE, REG_V28, REG_P1, REG_V23, - INS_OPTS_SCALABLE_B); // SQADD ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_sqsub, EA_SCALABLE, REG_V29, REG_P0, REG_V24, - INS_OPTS_SCALABLE_H); // SQSUB ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_sqsubr, EA_SCALABLE, REG_V30, REG_P1, REG_V25, - INS_OPTS_SCALABLE_H); // SQSUBR ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_suqadd, EA_SCALABLE, REG_V31, REG_P2, REG_V26, - INS_OPTS_SCALABLE_B); // SUQADD ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_uqadd, EA_SCALABLE, REG_V0, REG_P3, REG_V27, - INS_OPTS_SCALABLE_S); // UQADD ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_uqsub, EA_SCALABLE, REG_V1, REG_P4, REG_V28, - INS_OPTS_SCALABLE_D); // UQSUB ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_uqsubr, EA_SCALABLE, REG_V2, REG_P5, REG_V29, - INS_OPTS_SCALABLE_B); // UQSUBR ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_usqadd, EA_SCALABLE, REG_V3, REG_P6, REG_V30, - INS_OPTS_SCALABLE_B); // USQADD ., /M, ., . - - // IF_SVE_EU_3A - theEmitter->emitIns_R_R_R(INS_sve_sqrshl, EA_SCALABLE, REG_V4, REG_P7, REG_V31, - INS_OPTS_SCALABLE_B); // SQRSHL ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_sqrshlr, EA_SCALABLE, REG_V5, REG_P0, REG_V30, - INS_OPTS_SCALABLE_H); // SQRSHLR ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_sqshl, EA_SCALABLE, REG_V6, REG_P1, REG_V29, - INS_OPTS_SCALABLE_S); // SQSHL ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_sqshlr, EA_SCALABLE, REG_V7, REG_P2, REG_V28, - INS_OPTS_SCALABLE_D); // SQSHLR ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_srshl, EA_SCALABLE, REG_V8, REG_P3, REG_V27, - INS_OPTS_SCALABLE_B); // SRSHL ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_srshlr, EA_SCALABLE, REG_V9, REG_P4, REG_V26, - INS_OPTS_SCALABLE_H); // SRSHLR ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_uqrshl, EA_SCALABLE, REG_V10, REG_P5, REG_V25, - INS_OPTS_SCALABLE_S); // UQRSHL ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_uqrshlr, EA_SCALABLE, REG_V11, REG_P6, REG_V24, - INS_OPTS_SCALABLE_D); // UQRSHLR ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_uqshl, EA_SCALABLE, REG_V12, REG_P7, REG_V23, - INS_OPTS_SCALABLE_B); // UQSHL ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_uqshlr, EA_SCALABLE, REG_V13, REG_P0, REG_V22, - INS_OPTS_SCALABLE_H); // UQSHLR ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_urshl, EA_SCALABLE, REG_V14, REG_P1, REG_V21, - INS_OPTS_SCALABLE_S); // URSHL ., /M, ., . - theEmitter->emitIns_R_R_R(INS_sve_urshlr, EA_SCALABLE, REG_V15, REG_P2, REG_V20, - INS_OPTS_SCALABLE_D); // URSHLR ., /M, ., . - // IF_SVE_GE_4A theEmitter->emitIns_R_R_R_R(INS_sve_match, EA_SCALABLE, REG_P15, REG_P0, REG_V21, REG_V0, INS_OPTS_SCALABLE_B); // MATCH ., /Z, ., . @@ -5116,11 +5101,11 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_H); // FMINP ., /M, ., . // IF_SVE_HJ_3A - theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_2BYTE, REG_V21, REG_P6, REG_V14, + theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_SCALABLE, REG_V21, REG_P6, REG_V14, INS_OPTS_SCALABLE_H); // FADDA , , , . - theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_4BYTE, REG_V22, REG_P5, REG_V13, + theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_SCALABLE, REG_V22, REG_P5, REG_V13, INS_OPTS_SCALABLE_S); // FADDA , , , . - theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_8BYTE, REG_V23, REG_P4, REG_V12, + theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_SCALABLE, REG_V23, REG_P4, REG_V12, INS_OPTS_SCALABLE_D); // FADDA , , , . // IF_SVE_HL_3A @@ -5292,13 +5277,13 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_H); // FNMLS ., /M, ., . // IF_SVE_AF_3A - theEmitter->emitIns_R_R_R(INS_sve_andv, EA_1BYTE, REG_V0, REG_P0, REG_V0, + theEmitter->emitIns_R_R_R(INS_sve_andv, EA_SCALABLE, REG_V0, REG_P0, REG_V0, INS_OPTS_SCALABLE_B); // ANDV , , . - theEmitter->emitIns_R_R_R(INS_sve_eorv, EA_2BYTE, REG_V1, REG_P1, REG_V1, + theEmitter->emitIns_R_R_R(INS_sve_eorv, EA_SCALABLE, REG_V1, REG_P1, REG_V1, INS_OPTS_SCALABLE_H); // EORV , , . - theEmitter->emitIns_R_R_R(INS_sve_orv, EA_4BYTE, REG_V2, REG_P2, REG_V2, + theEmitter->emitIns_R_R_R(INS_sve_orv, EA_SCALABLE, REG_V2, REG_P2, REG_V2, INS_OPTS_SCALABLE_S); // ORV , , . - theEmitter->emitIns_R_R_R(INS_sve_orv, EA_8BYTE, REG_V3, REG_P3, REG_V3, + theEmitter->emitIns_R_R_R(INS_sve_orv, EA_SCALABLE, REG_V3, REG_P3, REG_V3, INS_OPTS_SCALABLE_D); // ORV , , . // IF_SVE_AG_3A @@ -5314,11 +5299,11 @@ void CodeGen::genArm64EmitterUnitTestsSve() #endif // ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED // IF_SVE_AI_3A - theEmitter->emitIns_R_R_R(INS_sve_saddv, EA_1BYTE, REG_V1, REG_P4, REG_V2, + theEmitter->emitIns_R_R_R(INS_sve_saddv, EA_SCALABLE, REG_V1, REG_P4, REG_V2, INS_OPTS_SCALABLE_B); // SADDV
    , , . - theEmitter->emitIns_R_R_R(INS_sve_saddv, EA_2BYTE, REG_V2, REG_P5, REG_V3, + theEmitter->emitIns_R_R_R(INS_sve_saddv, EA_SCALABLE, REG_V2, REG_P5, REG_V3, INS_OPTS_SCALABLE_H); // SADDV
    , , . - theEmitter->emitIns_R_R_R(INS_sve_uaddv, EA_4BYTE, REG_V3, REG_P6, REG_V4, + theEmitter->emitIns_R_R_R(INS_sve_uaddv, EA_SCALABLE, REG_V3, REG_P6, REG_V4, INS_OPTS_SCALABLE_S); // UADDV
    , , . // IF_SVE_AJ_3A @@ -5328,13 +5313,13 @@ void CodeGen::genArm64EmitterUnitTestsSve() #endif // ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED // IF_SVE_AK_3A - theEmitter->emitIns_R_R_R(INS_sve_smaxv, EA_8BYTE, REG_V15, REG_P7, REG_V4, + theEmitter->emitIns_R_R_R(INS_sve_smaxv, EA_SCALABLE, REG_V15, REG_P7, REG_V4, INS_OPTS_SCALABLE_D); // SMAXV , , . - theEmitter->emitIns_R_R_R(INS_sve_sminv, EA_4BYTE, REG_V16, REG_P6, REG_V14, + theEmitter->emitIns_R_R_R(INS_sve_sminv, EA_SCALABLE, REG_V16, REG_P6, REG_V14, INS_OPTS_SCALABLE_S); // SMINV , , . - theEmitter->emitIns_R_R_R(INS_sve_umaxv, EA_2BYTE, REG_V17, REG_P5, REG_V24, + theEmitter->emitIns_R_R_R(INS_sve_umaxv, EA_SCALABLE, REG_V17, REG_P5, REG_V24, INS_OPTS_SCALABLE_H); // UMAXV , , . - theEmitter->emitIns_R_R_R(INS_sve_uminv, EA_1BYTE, REG_V18, REG_P4, REG_V31, + theEmitter->emitIns_R_R_R(INS_sve_uminv, EA_SCALABLE, REG_V18, REG_P4, REG_V31, INS_OPTS_SCALABLE_B); // UMINV , , . // IF_SVE_AL_3A @@ -5420,62 +5405,18 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_SCALABLE_OPTS_UNPREDICATED); // UQADD ., ., . theEmitter->emitIns_R_R_R(INS_sve_uqsub, EA_SCALABLE, REG_V31, REG_V31, REG_V31, INS_OPTS_SCALABLE_H, INS_SCALABLE_OPTS_UNPREDICATED); // UQSUB ., ., . - - // IF_SVE_BA_3A - theEmitter->emitIns_R_R_R(INS_sve_index, EA_4BYTE, REG_V24, REG_ZR, REG_R9, - INS_OPTS_SCALABLE_B); // INDEX ., , - theEmitter->emitIns_R_R_R(INS_sve_index, EA_8BYTE, REG_V12, REG_R15, REG_R0, - INS_OPTS_SCALABLE_D); // INDEX ., , - - // IF_SVE_BD_3A theEmitter->emitIns_R_R_R(INS_sve_mul, EA_SCALABLE, REG_V5, REG_V0, REG_V31, INS_OPTS_SCALABLE_B, INS_SCALABLE_OPTS_UNPREDICATED); // MUL ., ., . theEmitter->emitIns_R_R_R(INS_sve_smulh, EA_SCALABLE, REG_V0, REG_V31, REG_V5, INS_OPTS_SCALABLE_H, INS_SCALABLE_OPTS_UNPREDICATED); // SMULH ., ., . theEmitter->emitIns_R_R_R(INS_sve_umulh, EA_SCALABLE, REG_V31, REG_V5, REG_V0, INS_OPTS_SCALABLE_D, INS_SCALABLE_OPTS_UNPREDICATED); // UMULH ., ., . - - // IF_SVE_BD_3B - theEmitter->emitIns_R_R_R(INS_sve_pmul, EA_SCALABLE, REG_V0, REG_V1, REG_V2, - INS_OPTS_SCALABLE_B); // PMUL .B, .B, .B - - // IF_SVE_BE_3A theEmitter->emitIns_R_R_R(INS_sve_sqdmulh, EA_SCALABLE, REG_V7, REG_V28, REG_V0, INS_OPTS_SCALABLE_B); // SQDMULH ., ., . theEmitter->emitIns_R_R_R(INS_sve_sqrdmulh, EA_SCALABLE, REG_V23, REG_V3, REG_V31, INS_OPTS_SCALABLE_H); // SQRDMULH ., ., . - - // IF_SVE_BG_3A - theEmitter->emitIns_R_R_R(INS_sve_asr, EA_SCALABLE, REG_V9, REG_V31, REG_V2, INS_OPTS_SCALABLE_B, - INS_SCALABLE_OPTS_UNPREDICATED_WIDE); // ASR ., ., .D - theEmitter->emitIns_R_R_R(INS_sve_lsl, EA_SCALABLE, REG_V19, REG_V0, REG_V12, INS_OPTS_SCALABLE_H, - INS_SCALABLE_OPTS_UNPREDICATED_WIDE); // LSL ., ., .D - theEmitter->emitIns_R_R_R(INS_sve_lsr, EA_SCALABLE, REG_V29, REG_V10, REG_V22, INS_OPTS_SCALABLE_S, - INS_SCALABLE_OPTS_UNPREDICATED_WIDE); // LSR ., ., .D - - // IF_SVE_BH_3A - theEmitter->emitInsSve_R_R_R_I(INS_sve_adr, EA_SCALABLE, REG_V4, REG_V2, REG_V0, 0, INS_OPTS_SCALABLE_D, - INS_SCALABLE_OPTS_LSL_N); // ADR ., [., .{, }] - theEmitter->emitInsSve_R_R_R_I(INS_sve_adr, EA_SCALABLE, REG_V29, REG_V1, REG_V10, 1, INS_OPTS_SCALABLE_S, - INS_SCALABLE_OPTS_LSL_N); // ADR ., [., .{, }] - - // IF_SVE_BH_3B - theEmitter->emitInsSve_R_R_R_I(INS_sve_adr, EA_SCALABLE, REG_V9, REG_V7, REG_V9, 0, - INS_OPTS_SCALABLE_D_SXTW); // ADR .D, [.D, .D, SXTW{}] - theEmitter->emitInsSve_R_R_R_I(INS_sve_adr, EA_SCALABLE, REG_V12, REG_V3, REG_V5, 2, - INS_OPTS_SCALABLE_D_SXTW); // ADR .D, [.D, .D, SXTW{}] - - // IF_SVE_BH_3B_A - theEmitter->emitInsSve_R_R_R_I(INS_sve_adr, EA_SCALABLE, REG_V9, REG_V10, REG_V14, 0, - INS_OPTS_SCALABLE_D_UXTW); // ADR .D, [.D, .D, UXTW{}] - theEmitter->emitInsSve_R_R_R_I(INS_sve_adr, EA_SCALABLE, REG_V3, REG_V15, REG_V11, 3, - INS_OPTS_SCALABLE_D_UXTW); // ADR .D, [.D, .D, UXTW{}] - - // IF_SVE_BK_3A theEmitter->emitIns_R_R_R(INS_sve_ftssel, EA_SCALABLE, REG_V17, REG_V16, REG_V15, INS_OPTS_SCALABLE_D); // FTSSEL ., ., . - - // IF_SVE_BR_3A theEmitter->emitIns_R_R_R(INS_sve_trn1, EA_SCALABLE, REG_V0, REG_V1, REG_V2, INS_OPTS_SCALABLE_B, INS_SCALABLE_OPTS_UNPREDICATED); // TRN1 ., ., . theEmitter->emitIns_R_R_R(INS_sve_trn1, EA_SCALABLE, REG_V3, REG_V4, REG_V5, INS_OPTS_SCALABLE_H, @@ -5500,6 +5441,92 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_SCALABLE_OPTS_UNPREDICATED); // ZIP2 ., ., . theEmitter->emitIns_R_R_R(INS_sve_zip2, EA_SCALABLE, REG_V1, REG_V2, REG_V3, INS_OPTS_SCALABLE_D, INS_SCALABLE_OPTS_UNPREDICATED); // ZIP2 ., ., . + theEmitter->emitIns_R_R_R(INS_sve_tbxq, EA_SCALABLE, REG_V0, REG_V1, REG_V2, + INS_OPTS_SCALABLE_B); // TBXQ ., ., . + theEmitter->emitIns_R_R_R(INS_sve_tbxq, EA_SCALABLE, REG_V3, REG_V4, REG_V5, + INS_OPTS_SCALABLE_H); // TBXQ ., ., . + theEmitter->emitIns_R_R_R(INS_sve_tbxq, EA_SCALABLE, REG_V6, REG_V7, REG_V8, + INS_OPTS_SCALABLE_S); // TBXQ ., ., . + theEmitter->emitIns_R_R_R(INS_sve_tbxq, EA_SCALABLE, REG_V9, REG_V10, REG_V11, + INS_OPTS_SCALABLE_D); // TBXQ ., ., . + theEmitter->emitIns_R_R_R(INS_sve_sclamp, EA_SCALABLE, REG_V0, REG_V1, REG_V2, + INS_OPTS_SCALABLE_B); // SCLAMP ., ., . + theEmitter->emitIns_R_R_R(INS_sve_sclamp, EA_SCALABLE, REG_V3, REG_V4, REG_V5, + INS_OPTS_SCALABLE_H); // SCLAMP ., ., . + theEmitter->emitIns_R_R_R(INS_sve_uclamp, EA_SCALABLE, REG_V6, REG_V7, REG_V8, + INS_OPTS_SCALABLE_S); // UCLAMP ., ., . + theEmitter->emitIns_R_R_R(INS_sve_uclamp, EA_SCALABLE, REG_V9, REG_V10, REG_V11, + INS_OPTS_SCALABLE_D); // UCLAMP ., ., . + theEmitter->emitIns_R_R_R(INS_sve_fclamp, EA_SCALABLE, REG_V0, REG_V1, REG_V2, + INS_OPTS_SCALABLE_H); // FCLAMP ., ., . + theEmitter->emitIns_R_R_R(INS_sve_fclamp, EA_SCALABLE, REG_V3, REG_V4, REG_V5, + INS_OPTS_SCALABLE_S); // FCLAMP ., ., . + theEmitter->emitIns_R_R_R(INS_sve_fclamp, EA_SCALABLE, REG_V6, REG_V7, REG_V8, + INS_OPTS_SCALABLE_D); // FCLAMP ., ., . + theEmitter->emitIns_R_R_R(INS_sve_eorbt, EA_SCALABLE, REG_V0, REG_V1, REG_V2, + INS_OPTS_SCALABLE_B); // EORBT ., ., . + theEmitter->emitIns_R_R_R(INS_sve_eorbt, EA_SCALABLE, REG_V3, REG_V4, REG_V5, + INS_OPTS_SCALABLE_H); // EORBT ., ., . + theEmitter->emitIns_R_R_R(INS_sve_eortb, EA_SCALABLE, REG_V6, REG_V7, REG_V8, + INS_OPTS_SCALABLE_S); // EORTB ., ., . + theEmitter->emitIns_R_R_R(INS_sve_eortb, EA_SCALABLE, REG_V9, REG_V10, REG_V11, + INS_OPTS_SCALABLE_D); // EORTB ., ., . + theEmitter->emitIns_R_R_R(INS_sve_bdep, EA_SCALABLE, REG_V0, REG_V1, REG_V2, + INS_OPTS_SCALABLE_B); // BDEP ., ., . + theEmitter->emitIns_R_R_R(INS_sve_bext, EA_SCALABLE, REG_V3, REG_V4, REG_V5, + INS_OPTS_SCALABLE_H); // BEXT ., ., . + theEmitter->emitIns_R_R_R(INS_sve_bgrp, EA_SCALABLE, REG_V6, REG_V7, REG_V8, + INS_OPTS_SCALABLE_S); // BGRP ., ., . + theEmitter->emitIns_R_R_R(INS_sve_bgrp, EA_SCALABLE, REG_V9, REG_V10, REG_V11, + INS_OPTS_SCALABLE_D); // BGRP ., ., . + theEmitter->emitIns_R_R_R(INS_sve_fadd, EA_SCALABLE, REG_V0, REG_V1, REG_V2, INS_OPTS_SCALABLE_H, + INS_SCALABLE_OPTS_UNPREDICATED); // FADD ., ., . + theEmitter->emitIns_R_R_R(INS_sve_fmul, EA_SCALABLE, REG_V3, REG_V4, REG_V5, INS_OPTS_SCALABLE_S, + INS_SCALABLE_OPTS_UNPREDICATED); // FMUL ., ., . + theEmitter->emitIns_R_R_R(INS_sve_frecps, EA_SCALABLE, REG_V6, REG_V7, REG_V8, INS_OPTS_SCALABLE_D, + INS_SCALABLE_OPTS_UNPREDICATED); // FRECPS ., ., . + theEmitter->emitIns_R_R_R(INS_sve_frsqrts, EA_SCALABLE, REG_V9, REG_V10, REG_V11, INS_OPTS_SCALABLE_H, + INS_SCALABLE_OPTS_UNPREDICATED); // FRSQRTS ., ., . + theEmitter->emitIns_R_R_R(INS_sve_fsub, EA_SCALABLE, REG_V12, REG_V13, REG_V14, INS_OPTS_SCALABLE_S, + INS_SCALABLE_OPTS_UNPREDICATED); // FSUB ., ., . + theEmitter->emitIns_R_R_R(INS_sve_ftsmul, EA_SCALABLE, REG_V15, REG_V16, REG_V17, INS_OPTS_SCALABLE_D, + INS_SCALABLE_OPTS_UNPREDICATED); // FTSMUL ., ., . + + // IF_SVE_BA_3A + theEmitter->emitIns_R_R_R(INS_sve_index, EA_4BYTE, REG_V24, REG_ZR, REG_R9, + INS_OPTS_SCALABLE_B); // INDEX ., , + theEmitter->emitIns_R_R_R(INS_sve_index, EA_8BYTE, REG_V12, REG_R15, REG_R0, + INS_OPTS_SCALABLE_D); // INDEX ., , + + // IF_SVE_BD_3B + theEmitter->emitIns_R_R_R(INS_sve_pmul, EA_SCALABLE, REG_V0, REG_V1, REG_V2, + INS_OPTS_SCALABLE_B); // PMUL .B, .B, .B + + // IF_SVE_BG_3A + theEmitter->emitIns_R_R_R(INS_sve_asr, EA_SCALABLE, REG_V9, REG_V31, REG_V2, INS_OPTS_SCALABLE_B, + INS_SCALABLE_OPTS_UNPREDICATED_WIDE); // ASR ., ., .D + theEmitter->emitIns_R_R_R(INS_sve_lsl, EA_SCALABLE, REG_V19, REG_V0, REG_V12, INS_OPTS_SCALABLE_H, + INS_SCALABLE_OPTS_UNPREDICATED_WIDE); // LSL ., ., .D + theEmitter->emitIns_R_R_R(INS_sve_lsr, EA_SCALABLE, REG_V29, REG_V10, REG_V22, INS_OPTS_SCALABLE_S, + INS_SCALABLE_OPTS_UNPREDICATED_WIDE); // LSR ., ., .D + + // IF_SVE_BH_3A + theEmitter->emitInsSve_R_R_R_I(INS_sve_adr, EA_SCALABLE, REG_V4, REG_V2, REG_V0, 0, INS_OPTS_SCALABLE_D, + INS_SCALABLE_OPTS_LSL_N); // ADR ., [., .{, }] + theEmitter->emitInsSve_R_R_R_I(INS_sve_adr, EA_SCALABLE, REG_V29, REG_V1, REG_V10, 1, INS_OPTS_SCALABLE_S, + INS_SCALABLE_OPTS_LSL_N); // ADR ., [., .{, }] + + // IF_SVE_BH_3B + theEmitter->emitInsSve_R_R_R_I(INS_sve_adr, EA_SCALABLE, REG_V9, REG_V7, REG_V9, 0, + INS_OPTS_SCALABLE_D_SXTW); // ADR .D, [.D, .D, SXTW{}] + theEmitter->emitInsSve_R_R_R_I(INS_sve_adr, EA_SCALABLE, REG_V12, REG_V3, REG_V5, 2, + INS_OPTS_SCALABLE_D_SXTW); // ADR .D, [.D, .D, SXTW{}] + + // IF_SVE_BH_3B_A + theEmitter->emitInsSve_R_R_R_I(INS_sve_adr, EA_SCALABLE, REG_V9, REG_V10, REG_V14, 0, + INS_OPTS_SCALABLE_D_UXTW); // ADR .D, [.D, .D, UXTW{}] + theEmitter->emitInsSve_R_R_R_I(INS_sve_adr, EA_SCALABLE, REG_V3, REG_V15, REG_V11, 3, + INS_OPTS_SCALABLE_D_UXTW); // ADR .D, [.D, .D, UXTW{}] // IF_SVE_BR_3B theEmitter->emitIns_R_R_R(INS_sve_trn1, EA_SCALABLE, REG_V0, REG_V1, REG_V2, INS_OPTS_SCALABLE_Q, @@ -5664,16 +5691,6 @@ void CodeGen::genArm64EmitterUnitTestsSve() theEmitter->emitIns_R_R_R(INS_sve_tbl, EA_SCALABLE, REG_V9, REG_V10, REG_V11, INS_OPTS_SCALABLE_D, INS_SCALABLE_OPTS_WITH_VECTOR_PAIR); // TBL ., {., .}, . - // IF_SVE_CA_3A - theEmitter->emitIns_R_R_R(INS_sve_tbxq, EA_SCALABLE, REG_V0, REG_V1, REG_V2, - INS_OPTS_SCALABLE_B); // TBXQ ., ., . - theEmitter->emitIns_R_R_R(INS_sve_tbxq, EA_SCALABLE, REG_V3, REG_V4, REG_V5, - INS_OPTS_SCALABLE_H); // TBXQ ., ., . - theEmitter->emitIns_R_R_R(INS_sve_tbxq, EA_SCALABLE, REG_V6, REG_V7, REG_V8, - INS_OPTS_SCALABLE_S); // TBXQ ., ., . - theEmitter->emitIns_R_R_R(INS_sve_tbxq, EA_SCALABLE, REG_V9, REG_V10, REG_V11, - INS_OPTS_SCALABLE_D); // TBXQ ., ., . - // IF_SVE_EH_3A theEmitter->emitIns_R_R_R(INS_sve_sdot, EA_SCALABLE, REG_V0, REG_V1, REG_V2, INS_OPTS_SCALABLE_S); // SDOT ., ., . @@ -5701,26 +5718,12 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_H); // UMLSLB ., ., . theEmitter->emitIns_R_R_R(INS_sve_umlslt, EA_SCALABLE, REG_V21, REG_V22, REG_V23, INS_OPTS_SCALABLE_S); // UMLSLT ., ., . - - // IF_SVE_EM_3A - theEmitter->emitIns_R_R_R(INS_sve_sqrdmlah, EA_SCALABLE, REG_V0, REG_V1, REG_V2, - INS_OPTS_SCALABLE_B); // SQRDMLAH ., ., . - theEmitter->emitIns_R_R_R(INS_sve_sqrdmlah, EA_SCALABLE, REG_V3, REG_V4, REG_V5, - INS_OPTS_SCALABLE_H); // SQRDMLAH ., ., . - theEmitter->emitIns_R_R_R(INS_sve_sqrdmlsh, EA_SCALABLE, REG_V6, REG_V7, REG_V8, - INS_OPTS_SCALABLE_S); // SQRDMLSH ., ., . - theEmitter->emitIns_R_R_R(INS_sve_sqrdmlsh, EA_SCALABLE, REG_V9, REG_V10, REG_V11, - INS_OPTS_SCALABLE_D); // SQRDMLSH ., ., . - - // IF_SVE_EN_3A theEmitter->emitIns_R_R_R(INS_sve_sqdmlalbt, EA_SCALABLE, REG_V0, REG_V1, REG_V2, INS_OPTS_SCALABLE_H); // SQDMLALBT ., ., . theEmitter->emitIns_R_R_R(INS_sve_sqdmlslbt, EA_SCALABLE, REG_V3, REG_V4, REG_V5, INS_OPTS_SCALABLE_S); // SQDMLSLBT ., ., . theEmitter->emitIns_R_R_R(INS_sve_sqdmlslbt, EA_SCALABLE, REG_V6, REG_V7, REG_V8, INS_OPTS_SCALABLE_D); // SQDMLSLBT ., ., . - - // IF_SVE_EO_3A theEmitter->emitIns_R_R_R(INS_sve_sqdmlalb, EA_SCALABLE, REG_V0, REG_V1, REG_V2, INS_OPTS_SCALABLE_H); // SQDMLALB ., ., . theEmitter->emitIns_R_R_R(INS_sve_sqdmlalt, EA_SCALABLE, REG_V3, REG_V4, REG_V5, @@ -5729,16 +5732,24 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_D); // SQDMLSLB ., ., . theEmitter->emitIns_R_R_R(INS_sve_sqdmlslt, EA_SCALABLE, REG_V9, REG_V10, REG_V11, INS_OPTS_SCALABLE_H); // SQDMLSLT ., ., . + theEmitter->emitIns_R_R_R(INS_sve_sabalb, EA_SCALABLE, REG_V0, REG_V1, REG_V2, + INS_OPTS_SCALABLE_H); // SABALB ., ., . + theEmitter->emitIns_R_R_R(INS_sve_sabalt, EA_SCALABLE, REG_V3, REG_V4, REG_V5, + INS_OPTS_SCALABLE_S); // SABALT ., ., . + theEmitter->emitIns_R_R_R(INS_sve_uabalb, EA_SCALABLE, REG_V6, REG_V7, REG_V8, + INS_OPTS_SCALABLE_D); // UABALB ., ., . + theEmitter->emitIns_R_R_R(INS_sve_uabalt, EA_SCALABLE, REG_V9, REG_V10, REG_V11, + INS_OPTS_SCALABLE_H); // UABALT ., ., . - // IF_SVE_EV_3A - theEmitter->emitIns_R_R_R(INS_sve_sclamp, EA_SCALABLE, REG_V0, REG_V1, REG_V2, - INS_OPTS_SCALABLE_B); // SCLAMP ., ., . - theEmitter->emitIns_R_R_R(INS_sve_sclamp, EA_SCALABLE, REG_V3, REG_V4, REG_V5, - INS_OPTS_SCALABLE_H); // SCLAMP ., ., . - theEmitter->emitIns_R_R_R(INS_sve_uclamp, EA_SCALABLE, REG_V6, REG_V7, REG_V8, - INS_OPTS_SCALABLE_S); // UCLAMP ., ., . - theEmitter->emitIns_R_R_R(INS_sve_uclamp, EA_SCALABLE, REG_V9, REG_V10, REG_V11, - INS_OPTS_SCALABLE_D); // UCLAMP ., ., . + // IF_SVE_EM_3A + theEmitter->emitIns_R_R_R(INS_sve_sqrdmlah, EA_SCALABLE, REG_V0, REG_V1, REG_V2, + INS_OPTS_SCALABLE_B); // SQRDMLAH ., ., . + theEmitter->emitIns_R_R_R(INS_sve_sqrdmlah, EA_SCALABLE, REG_V3, REG_V4, REG_V5, + INS_OPTS_SCALABLE_H); // SQRDMLAH ., ., . + theEmitter->emitIns_R_R_R(INS_sve_sqrdmlsh, EA_SCALABLE, REG_V6, REG_V7, REG_V8, + INS_OPTS_SCALABLE_S); // SQRDMLSH ., ., . + theEmitter->emitIns_R_R_R(INS_sve_sqrdmlsh, EA_SCALABLE, REG_V9, REG_V10, REG_V11, + INS_OPTS_SCALABLE_D); // SQRDMLSH ., ., . // IF_SVE_EX_3A theEmitter->emitIns_R_R_R(INS_sve_tblq, EA_SCALABLE, REG_V0, REG_V1, REG_V2, @@ -5777,6 +5788,28 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_S); // USUBLB ., ., . theEmitter->emitIns_R_R_R(INS_sve_usublt, EA_SCALABLE, REG_V1, REG_V2, REG_V3, INS_OPTS_SCALABLE_D); // USUBLT ., ., . + theEmitter->emitIns_R_R_R(INS_sve_pmullb, EA_SCALABLE, REG_V0, REG_V1, REG_V2, + INS_OPTS_SCALABLE_H); // PMULLB ., ., . + theEmitter->emitIns_R_R_R(INS_sve_pmullt, EA_SCALABLE, REG_V3, REG_V4, REG_V5, + INS_OPTS_SCALABLE_D); // PMULLT ., ., . + theEmitter->emitIns_R_R_R(INS_sve_smullb, EA_SCALABLE, REG_V6, REG_V7, REG_V8, + INS_OPTS_SCALABLE_H); // SMULLB ., ., . + theEmitter->emitIns_R_R_R(INS_sve_smullt, EA_SCALABLE, REG_V9, REG_V10, REG_V11, + INS_OPTS_SCALABLE_D); // SMULLT ., ., . + theEmitter->emitIns_R_R_R(INS_sve_sqdmullb, EA_SCALABLE, REG_V12, REG_V13, REG_V14, + INS_OPTS_SCALABLE_H); // SQDMULLB ., ., . + theEmitter->emitIns_R_R_R(INS_sve_sqdmullt, EA_SCALABLE, REG_V15, REG_V16, REG_V17, + INS_OPTS_SCALABLE_D); // SQDMULLT ., ., . + theEmitter->emitIns_R_R_R(INS_sve_umullb, EA_SCALABLE, REG_V18, REG_V19, REG_V20, + INS_OPTS_SCALABLE_H); // UMULLB ., ., . + theEmitter->emitIns_R_R_R(INS_sve_umullt, EA_SCALABLE, REG_V21, REG_V22, REG_V23, + INS_OPTS_SCALABLE_D); // UMULLT ., ., . + theEmitter->emitIns_R_R_R(INS_sve_saddlbt, EA_SCALABLE, REG_V0, REG_V1, REG_V2, + INS_OPTS_SCALABLE_H); // SADDLBT ., ., . + theEmitter->emitIns_R_R_R(INS_sve_ssublbt, EA_SCALABLE, REG_V3, REG_V4, REG_V5, + INS_OPTS_SCALABLE_S); // SSUBLBT ., ., . + theEmitter->emitIns_R_R_R(INS_sve_ssubltb, EA_SCALABLE, REG_V6, REG_V7, REG_V8, + INS_OPTS_SCALABLE_D); // SSUBLTB ., ., . // IF_SVE_FM_3A theEmitter->emitIns_R_R_R(INS_sve_saddwb, EA_SCALABLE, REG_V0, REG_V1, REG_V2, @@ -5796,24 +5829,6 @@ void CodeGen::genArm64EmitterUnitTestsSve() theEmitter->emitIns_R_R_R(INS_sve_usubwt, EA_SCALABLE, REG_V21, REG_V22, REG_V23, INS_OPTS_SCALABLE_S); // USUBWT ., ., . - // IF_SVE_FN_3A - theEmitter->emitIns_R_R_R(INS_sve_pmullb, EA_SCALABLE, REG_V0, REG_V1, REG_V2, - INS_OPTS_SCALABLE_H); // PMULLB ., ., . - theEmitter->emitIns_R_R_R(INS_sve_pmullt, EA_SCALABLE, REG_V3, REG_V4, REG_V5, - INS_OPTS_SCALABLE_D); // PMULLT ., ., . - theEmitter->emitIns_R_R_R(INS_sve_smullb, EA_SCALABLE, REG_V6, REG_V7, REG_V8, - INS_OPTS_SCALABLE_H); // SMULLB ., ., . - theEmitter->emitIns_R_R_R(INS_sve_smullt, EA_SCALABLE, REG_V9, REG_V10, REG_V11, - INS_OPTS_SCALABLE_D); // SMULLT ., ., . - theEmitter->emitIns_R_R_R(INS_sve_sqdmullb, EA_SCALABLE, REG_V12, REG_V13, REG_V14, - INS_OPTS_SCALABLE_H); // SQDMULLB ., ., . - theEmitter->emitIns_R_R_R(INS_sve_sqdmullt, EA_SCALABLE, REG_V15, REG_V16, REG_V17, - INS_OPTS_SCALABLE_D); // SQDMULLT ., ., . - theEmitter->emitIns_R_R_R(INS_sve_umullb, EA_SCALABLE, REG_V18, REG_V19, REG_V20, - INS_OPTS_SCALABLE_H); // UMULLB ., ., . - theEmitter->emitIns_R_R_R(INS_sve_umullt, EA_SCALABLE, REG_V21, REG_V22, REG_V23, - INS_OPTS_SCALABLE_D); // UMULLT ., ., . - // IF_SVE_FN_3B theEmitter->emitIns_R_R_R(INS_sve_pmullb, EA_SCALABLE, REG_V0, REG_V1, REG_V2, INS_OPTS_SCALABLE_Q); // PMULLB .Q, .D, .D @@ -5828,34 +5843,6 @@ void CodeGen::genArm64EmitterUnitTestsSve() theEmitter->emitIns_R_R_R(INS_sve_usmmla, EA_SCALABLE, REG_V6, REG_V7, REG_V8, INS_OPTS_SCALABLE_S); // USMMLA .S, .B, .B - // IF_SVE_FP_3A - theEmitter->emitIns_R_R_R(INS_sve_eorbt, EA_SCALABLE, REG_V0, REG_V1, REG_V2, - INS_OPTS_SCALABLE_B); // EORBT ., ., . - theEmitter->emitIns_R_R_R(INS_sve_eorbt, EA_SCALABLE, REG_V3, REG_V4, REG_V5, - INS_OPTS_SCALABLE_H); // EORBT ., ., . - theEmitter->emitIns_R_R_R(INS_sve_eortb, EA_SCALABLE, REG_V6, REG_V7, REG_V8, - INS_OPTS_SCALABLE_S); // EORTB ., ., . - theEmitter->emitIns_R_R_R(INS_sve_eortb, EA_SCALABLE, REG_V9, REG_V10, REG_V11, - INS_OPTS_SCALABLE_D); // EORTB ., ., . - - // IF_SVE_FQ_3A - theEmitter->emitIns_R_R_R(INS_sve_bdep, EA_SCALABLE, REG_V0, REG_V1, REG_V2, - INS_OPTS_SCALABLE_B); // BDEP ., ., . - theEmitter->emitIns_R_R_R(INS_sve_bext, EA_SCALABLE, REG_V3, REG_V4, REG_V5, - INS_OPTS_SCALABLE_H); // BEXT ., ., . - theEmitter->emitIns_R_R_R(INS_sve_bgrp, EA_SCALABLE, REG_V6, REG_V7, REG_V8, - INS_OPTS_SCALABLE_S); // BGRP ., ., . - theEmitter->emitIns_R_R_R(INS_sve_bgrp, EA_SCALABLE, REG_V9, REG_V10, REG_V11, - INS_OPTS_SCALABLE_D); // BGRP ., ., . - - // IF_SVE_FS_3A - theEmitter->emitIns_R_R_R(INS_sve_saddlbt, EA_SCALABLE, REG_V0, REG_V1, REG_V2, - INS_OPTS_SCALABLE_H); // SADDLBT ., ., . - theEmitter->emitIns_R_R_R(INS_sve_ssublbt, EA_SCALABLE, REG_V3, REG_V4, REG_V5, - INS_OPTS_SCALABLE_S); // SSUBLBT ., ., . - theEmitter->emitIns_R_R_R(INS_sve_ssubltb, EA_SCALABLE, REG_V6, REG_V7, REG_V8, - INS_OPTS_SCALABLE_D); // SSUBLTB ., ., . - // IF_SVE_FW_3A theEmitter->emitIns_R_R_R(INS_sve_saba, EA_SCALABLE, REG_V0, REG_V1, REG_V2, INS_OPTS_SCALABLE_B); // SABA ., ., . @@ -5866,16 +5853,6 @@ void CodeGen::genArm64EmitterUnitTestsSve() theEmitter->emitIns_R_R_R(INS_sve_uaba, EA_SCALABLE, REG_V9, REG_V10, REG_V11, INS_OPTS_SCALABLE_D); // UABA ., ., . - // IF_SVE_FX_3A - theEmitter->emitIns_R_R_R(INS_sve_sabalb, EA_SCALABLE, REG_V0, REG_V1, REG_V2, - INS_OPTS_SCALABLE_H); // SABALB ., ., . - theEmitter->emitIns_R_R_R(INS_sve_sabalt, EA_SCALABLE, REG_V3, REG_V4, REG_V5, - INS_OPTS_SCALABLE_S); // SABALT ., ., . - theEmitter->emitIns_R_R_R(INS_sve_uabalb, EA_SCALABLE, REG_V6, REG_V7, REG_V8, - INS_OPTS_SCALABLE_D); // UABALB ., ., . - theEmitter->emitIns_R_R_R(INS_sve_uabalt, EA_SCALABLE, REG_V9, REG_V10, REG_V11, - INS_OPTS_SCALABLE_H); // UABALT ., ., . - #ifdef ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED // IF_SVE_GC_3A theEmitter->emitIns_R_R_R(INS_sve_addhnb, EA_SCALABLE, REG_V0, REG_V1, REG_V2, @@ -5900,32 +5877,10 @@ void CodeGen::genArm64EmitterUnitTestsSve() theEmitter->emitIns_R_R_R(INS_sve_histseg, EA_SCALABLE, REG_V0, REG_V1, REG_V2, INS_OPTS_SCALABLE_B); // HISTSEG .B, .B, .B - // IF_SVE_GW_3A - theEmitter->emitIns_R_R_R(INS_sve_fclamp, EA_SCALABLE, REG_V0, REG_V1, REG_V2, - INS_OPTS_SCALABLE_H); // FCLAMP ., ., . - theEmitter->emitIns_R_R_R(INS_sve_fclamp, EA_SCALABLE, REG_V3, REG_V4, REG_V5, - INS_OPTS_SCALABLE_S); // FCLAMP ., ., . - theEmitter->emitIns_R_R_R(INS_sve_fclamp, EA_SCALABLE, REG_V6, REG_V7, REG_V8, - INS_OPTS_SCALABLE_D); // FCLAMP ., ., . - // IF_SVE_GW_3B theEmitter->emitIns_R_R_R(INS_sve_bfclamp, EA_SCALABLE, REG_V0, REG_V1, REG_V2, INS_OPTS_SCALABLE_H); // BFCLAMP .H, .H, .H - // IF_SVE_HK_3A - theEmitter->emitIns_R_R_R(INS_sve_fadd, EA_SCALABLE, REG_V0, REG_V1, REG_V2, INS_OPTS_SCALABLE_H, - INS_SCALABLE_OPTS_UNPREDICATED); // FADD ., ., . - theEmitter->emitIns_R_R_R(INS_sve_fmul, EA_SCALABLE, REG_V3, REG_V4, REG_V5, INS_OPTS_SCALABLE_S, - INS_SCALABLE_OPTS_UNPREDICATED); // FMUL ., ., . - theEmitter->emitIns_R_R_R(INS_sve_frecps, EA_SCALABLE, REG_V6, REG_V7, REG_V8, INS_OPTS_SCALABLE_D, - INS_SCALABLE_OPTS_UNPREDICATED); // FRECPS ., ., . - theEmitter->emitIns_R_R_R(INS_sve_frsqrts, EA_SCALABLE, REG_V9, REG_V10, REG_V11, INS_OPTS_SCALABLE_H, - INS_SCALABLE_OPTS_UNPREDICATED); // FRSQRTS ., ., . - theEmitter->emitIns_R_R_R(INS_sve_fsub, EA_SCALABLE, REG_V12, REG_V13, REG_V14, INS_OPTS_SCALABLE_S, - INS_SCALABLE_OPTS_UNPREDICATED); // FSUB ., ., . - theEmitter->emitIns_R_R_R(INS_sve_ftsmul, EA_SCALABLE, REG_V15, REG_V16, REG_V17, INS_OPTS_SCALABLE_D, - INS_SCALABLE_OPTS_UNPREDICATED); // FTSMUL ., ., . - // IF_SVE_HK_3B theEmitter->emitIns_R_R_R(INS_sve_bfadd, EA_SCALABLE, REG_V0, REG_V1, REG_V2, INS_OPTS_SCALABLE_H, INS_SCALABLE_OPTS_UNPREDICATED); // BFADD .H, .H, .H @@ -6222,13 +6177,13 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_D); // COMPACT ., , . // IF_SVE_CP_3A - theEmitter->emitIns_R_R_R(INS_sve_cpy, EA_1BYTE, REG_V14, REG_P1, REG_V11, INS_OPTS_SCALABLE_B, + theEmitter->emitIns_R_R_R(INS_sve_cpy, EA_SCALABLE, REG_V14, REG_P1, REG_V11, INS_OPTS_SCALABLE_B, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CPY ., /M, - theEmitter->emitIns_R_R_R(INS_sve_cpy, EA_4BYTE, REG_V13, REG_P2, REG_V10, INS_OPTS_SCALABLE_S, + theEmitter->emitIns_R_R_R(INS_sve_cpy, EA_SCALABLE, REG_V13, REG_P2, REG_V10, INS_OPTS_SCALABLE_S, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CPY ., /M, - theEmitter->emitIns_R_R_R(INS_sve_mov, EA_2BYTE, REG_V12, REG_P3, REG_V9, INS_OPTS_SCALABLE_H, + theEmitter->emitIns_R_R_R(INS_sve_mov, EA_SCALABLE, REG_V12, REG_P3, REG_V9, INS_OPTS_SCALABLE_H, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // MOV ., /M, - theEmitter->emitIns_R_R_R(INS_sve_mov, EA_8BYTE, REG_V11, REG_P4, REG_V8, INS_OPTS_SCALABLE_D, + theEmitter->emitIns_R_R_R(INS_sve_mov, EA_SCALABLE, REG_V11, REG_P4, REG_V8, INS_OPTS_SCALABLE_D, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // MOV ., /M, // IF_SVE_CQ_3A @@ -6243,13 +6198,13 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_B); // MOV ., /M, // IF_SVE_CR_3A - theEmitter->emitIns_R_R_R(INS_sve_lasta, EA_1BYTE, REG_V6, REG_P1, REG_V27, INS_OPTS_SCALABLE_B, + theEmitter->emitIns_R_R_R(INS_sve_lasta, EA_SCALABLE, REG_V6, REG_P1, REG_V27, INS_OPTS_SCALABLE_B, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // LASTA , , . - theEmitter->emitIns_R_R_R(INS_sve_lasta, EA_2BYTE, REG_V5, REG_P2, REG_V26, INS_OPTS_SCALABLE_H, + theEmitter->emitIns_R_R_R(INS_sve_lasta, EA_SCALABLE, REG_V5, REG_P2, REG_V26, INS_OPTS_SCALABLE_H, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // LASTA , , . - theEmitter->emitIns_R_R_R(INS_sve_lastb, EA_4BYTE, REG_V4, REG_P3, REG_V25, INS_OPTS_SCALABLE_S, + theEmitter->emitIns_R_R_R(INS_sve_lastb, EA_SCALABLE, REG_V4, REG_P3, REG_V25, INS_OPTS_SCALABLE_S, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // LASTB , , . - theEmitter->emitIns_R_R_R(INS_sve_lastb, EA_8BYTE, REG_V3, REG_P4, REG_V24, INS_OPTS_SCALABLE_D, + theEmitter->emitIns_R_R_R(INS_sve_lastb, EA_SCALABLE, REG_V3, REG_P4, REG_V24, INS_OPTS_SCALABLE_D, INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // LASTB , , . // IF_SVE_CS_3A @@ -6768,15 +6723,15 @@ void CodeGen::genArm64EmitterUnitTestsSve() #endif // ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED // IF_SVE_HE_3A - theEmitter->emitIns_R_R_R(INS_sve_faddv, EA_2BYTE, REG_V21, REG_P7, REG_V7, + theEmitter->emitIns_R_R_R(INS_sve_faddv, EA_SCALABLE, REG_V21, REG_P7, REG_V7, INS_OPTS_SCALABLE_H); // FADDV , , . - theEmitter->emitIns_R_R_R(INS_sve_fmaxnmv, EA_2BYTE, REG_V22, REG_P6, REG_V6, + theEmitter->emitIns_R_R_R(INS_sve_fmaxnmv, EA_SCALABLE, REG_V22, REG_P6, REG_V6, INS_OPTS_SCALABLE_H); // FMAXNMV , , . - theEmitter->emitIns_R_R_R(INS_sve_fmaxv, EA_4BYTE, REG_V23, REG_P5, REG_V5, + theEmitter->emitIns_R_R_R(INS_sve_fmaxv, EA_SCALABLE, REG_V23, REG_P5, REG_V5, INS_OPTS_SCALABLE_S); // FMAXV , , . - theEmitter->emitIns_R_R_R(INS_sve_fminnmv, EA_8BYTE, REG_V24, REG_P4, REG_V4, + theEmitter->emitIns_R_R_R(INS_sve_fminnmv, EA_SCALABLE, REG_V24, REG_P4, REG_V4, INS_OPTS_SCALABLE_D); // FMINNMV , , . - theEmitter->emitIns_R_R_R(INS_sve_fminv, EA_4BYTE, REG_V25, REG_P3, REG_V3, + theEmitter->emitIns_R_R_R(INS_sve_fminv, EA_SCALABLE, REG_V25, REG_P3, REG_V3, INS_OPTS_SCALABLE_S); // FMINV , , . // IF_SVE_HQ_3A @@ -7040,23 +6995,23 @@ void CodeGen::genArm64EmitterUnitTestsSve() // IF_SVE_EY_3A theEmitter->emitIns_R_R_R_I(INS_sve_sdot, EA_SCALABLE, REG_V9, REG_V10, REG_V4, 0, - INS_OPTS_SCALABLE_B); // SDOT .S, .B, .B[] + INS_OPTS_SCALABLE_S); // SDOT .S, .B, .B[] theEmitter->emitIns_R_R_R_I(INS_sve_sdot, EA_SCALABLE, REG_V11, REG_V12, REG_V5, 1, - INS_OPTS_SCALABLE_B); // SDOT .S, .B, .B[] + INS_OPTS_SCALABLE_S); // SDOT .S, .B, .B[] theEmitter->emitIns_R_R_R_I(INS_sve_udot, EA_SCALABLE, REG_V13, REG_V14, REG_V6, 2, - INS_OPTS_SCALABLE_B); // UDOT .S, .B, .B[] + INS_OPTS_SCALABLE_S); // UDOT .S, .B, .B[] theEmitter->emitIns_R_R_R_I(INS_sve_udot, EA_SCALABLE, REG_V15, REG_V16, REG_V7, 3, - INS_OPTS_SCALABLE_B); // UDOT .S, .B, .B[] + INS_OPTS_SCALABLE_S); // UDOT .S, .B, .B[] // IF_SVE_EY_3B - theEmitter->emitIns_R_R_R_I(INS_sve_sdot, EA_SCALABLE, REG_V0, REG_V1, REG_V0, - 0); // SDOT .D, .H, .H[] - theEmitter->emitIns_R_R_R_I(INS_sve_sdot, EA_SCALABLE, REG_V2, REG_V3, REG_V5, - 1); // SDOT .D, .H, .H[] - theEmitter->emitIns_R_R_R_I(INS_sve_udot, EA_SCALABLE, REG_V4, REG_V5, REG_V10, - 0); // UDOT .D, .H, .H[] - theEmitter->emitIns_R_R_R_I(INS_sve_udot, EA_SCALABLE, REG_V6, REG_V7, REG_V15, - 1); // UDOT .D, .H, .H[] + theEmitter->emitIns_R_R_R_I(INS_sve_sdot, EA_SCALABLE, REG_V0, REG_V1, REG_V0, 0, + INS_OPTS_SCALABLE_D); // SDOT .D, .H, .H[] + theEmitter->emitIns_R_R_R_I(INS_sve_sdot, EA_SCALABLE, REG_V2, REG_V3, REG_V5, 1, + INS_OPTS_SCALABLE_D); // SDOT .D, .H, .H[] + theEmitter->emitIns_R_R_R_I(INS_sve_udot, EA_SCALABLE, REG_V4, REG_V5, REG_V10, 0, + INS_OPTS_SCALABLE_D); // UDOT .D, .H, .H[] + theEmitter->emitIns_R_R_R_I(INS_sve_udot, EA_SCALABLE, REG_V6, REG_V7, REG_V15, 1, + INS_OPTS_SCALABLE_D); // UDOT .D, .H, .H[] // IF_SVE_EZ_3A theEmitter->emitIns_R_R_R_I(INS_sve_sudot, EA_SCALABLE, REG_V17, REG_V18, REG_V0, 0, @@ -8909,7 +8864,7 @@ void CodeGen::genArm64EmitterUnitTestsSve() // SUNPKLO ., . theEmitter->emitIns_R_R(INS_sve_sunpklo, EA_SCALABLE, REG_V1, REG_V5, INS_OPTS_SCALABLE_S); // UUNPKHI ., . - theEmitter->emitIns_R_R(INS_sve_uunpkhi, EA_SCALABLE, REG_V5, REG_V1, INS_OPTS_SCALABLE_D); + theEmitter->emitIns_R_R(INS_sve_uunpkhi, EA_SCALABLE, REG_V5, REG_V1, INS_OPTS_SCALABLE_B); // UUNPKLO ., . theEmitter->emitIns_R_R(INS_sve_uunpklo, EA_SCALABLE, REG_V8, REG_V6, INS_OPTS_SCALABLE_S); @@ -8938,15 +8893,15 @@ void CodeGen::genArm64EmitterUnitTestsSve() // DUP ., theEmitter->emitIns_R_R(INS_sve_dup, EA_8BYTE, REG_V4, REG_SP, INS_OPTS_SCALABLE_D); // MOV ., - theEmitter->emitIns_R_R(INS_sve_mov, EA_4BYTE, REG_V4, REG_R2, INS_OPTS_SCALABLE_B); + theEmitter->emitIns_Mov(INS_sve_mov, EA_4BYTE, REG_V4, REG_R2, /* canSkip */ false, INS_OPTS_SCALABLE_B); // MOV ., - theEmitter->emitIns_R_R(INS_sve_mov, EA_4BYTE, REG_V4, REG_R2, INS_OPTS_SCALABLE_H); + theEmitter->emitIns_Mov(INS_sve_mov, EA_4BYTE, REG_V4, REG_R2, /* canSkip */ false, INS_OPTS_SCALABLE_H); // MOV ., - theEmitter->emitIns_R_R(INS_sve_mov, EA_4BYTE, REG_V1, REG_R3, INS_OPTS_SCALABLE_S); + theEmitter->emitIns_Mov(INS_sve_mov, EA_4BYTE, REG_V1, REG_R3, /* canSkip */ false, INS_OPTS_SCALABLE_S); // MOV ., - theEmitter->emitIns_R_R(INS_sve_mov, EA_8BYTE, REG_V5, REG_SP, INS_OPTS_SCALABLE_D); + theEmitter->emitIns_Mov(INS_sve_mov, EA_8BYTE, REG_V5, REG_SP, /* canSkip */ false, INS_OPTS_SCALABLE_D); // MOV ., - theEmitter->emitIns_R_R(INS_sve_mov, EA_8BYTE, REG_V2, REG_R9, INS_OPTS_SCALABLE_D); + theEmitter->emitIns_Mov(INS_sve_mov, EA_8BYTE, REG_V2, REG_R9, /* canSkip */ false, INS_OPTS_SCALABLE_D); // IF_SVE_BJ_2A // FEXPA ., . diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index a9e2a41f73f9..668493901764 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -282,6 +282,12 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) genReturn(treeNode); break; +#ifdef SWIFT_SUPPORT + case GT_SWIFT_ERROR_RET: + genSwiftErrorReturn(treeNode); + break; +#endif // SWIFT_SUPPORT + case GT_LEA: // If we are here, it is the case where there is an LEA that cannot be folded into a parent instruction. genLeaInstruction(treeNode->AsAddrMode()); @@ -318,7 +324,7 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) #endif // TARGET_ARM64 case GT_JMP: - genJmpMethod(treeNode); + genJmpPlaceArgs(treeNode); break; case GT_CKFINITE: @@ -904,9 +910,9 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) // in ARM64/ARM // Setup loReg (and hiReg) from the internal registers that we reserved in lower. // - regNumber loReg = treeNode->ExtractTempReg(); + regNumber loReg = internalRegisters.Extract(treeNode); #ifdef TARGET_ARM64 - regNumber hiReg = treeNode->GetSingleTempReg(); + regNumber hiReg = internalRegisters.GetSingle(treeNode); #endif // TARGET_ARM64 GenTreeLclVarCommon* srcLclNode = nullptr; @@ -1262,7 +1268,7 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) regNumber allocatedValueReg = REG_NA; if (treeNode->gtNumRegs == 1) { - allocatedValueReg = treeNode->ExtractTempReg(); + allocatedValueReg = internalRegisters.Extract(treeNode); } // Pick a register to store intermediate values in for the to-stack @@ -1634,19 +1640,19 @@ void CodeGen::genCodeForLclFld(GenTreeLclFld* tree) { // Arm supports unaligned access only for integer types, // load the floating data as 1 or 2 integer registers and convert them to float. - regNumber addr = tree->ExtractTempReg(); + regNumber addr = internalRegisters.Extract(tree); emit->emitIns_R_S(INS_lea, EA_PTRSIZE, addr, varNum, offs); if (targetType == TYP_FLOAT) { - regNumber floatAsInt = tree->GetSingleTempReg(); + regNumber floatAsInt = internalRegisters.GetSingle(tree); emit->emitIns_R_R(INS_ldr, EA_4BYTE, floatAsInt, addr); emit->emitIns_Mov(INS_vmov_i2f, EA_4BYTE, targetReg, floatAsInt, /* canSkip */ false); } else { - regNumber halfdoubleAsInt1 = tree->ExtractTempReg(); - regNumber halfdoubleAsInt2 = tree->GetSingleTempReg(); + regNumber halfdoubleAsInt1 = internalRegisters.Extract(tree); + regNumber halfdoubleAsInt2 = internalRegisters.GetSingle(tree); emit->emitIns_R_R_I(INS_ldr, EA_4BYTE, halfdoubleAsInt1, addr, 0); emit->emitIns_R_R_I(INS_ldr, EA_4BYTE, halfdoubleAsInt2, addr, 4); emit->emitIns_R_R_R(INS_vmov_i2d, EA_8BYTE, targetReg, halfdoubleAsInt1, halfdoubleAsInt2); @@ -1688,7 +1694,7 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) // The index is never contained, even if it is a constant. assert(index->isUsedFromReg()); - const regNumber tmpReg = node->ExtractTempReg(); + const regNumber tmpReg = internalRegisters.Extract(node); regNumber indexReg = index->GetRegNum(); @@ -1736,7 +1742,7 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) #ifdef TARGET_ARM64 if (!index->TypeIs(TYP_I_IMPL)) { - const regNumber tmpReg2 = node->ExtractTempReg(); + const regNumber tmpReg2 = internalRegisters.Extract(node); GetEmitter()->emitIns_Mov(INS_mov, EA_4BYTE, tmpReg2, indexReg, /* canSkip */ false); indexReg = tmpReg2; } @@ -2656,7 +2662,7 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) const int dstOffsetAdjustment = helper.GetDstOffset() - dstRegAddrAlignment; dstRegAddrAlignment = 0; - const regNumber tempReg = node->ExtractTempReg(RBM_ALLINT); + const regNumber tempReg = internalRegisters.Extract(node, RBM_ALLINT); genInstrWithConstant(INS_add, EA_PTRSIZE, tempReg, dstReg, dstOffsetAdjustment, tempReg); dstReg = tempReg; @@ -2678,7 +2684,7 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) if (shouldUse16ByteWideInstrs) { - const regNumber simdReg = node->GetSingleTempReg(RBM_ALLFLOAT); + const regNumber simdReg = internalRegisters.GetSingle(node, RBM_ALLFLOAT); const int initValue = (src->AsIntCon()->IconValue() & 0xFF); emit->emitIns_R_I(INS_movi, EA_16BYTE, simdReg, initValue, INS_OPTS_16B); @@ -2961,23 +2967,23 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) if ((srcOffsetAdjustment != 0) && (dstOffsetAdjustment != 0)) { - const regNumber tempReg1 = node->ExtractTempReg(RBM_ALLINT); + const regNumber tempReg1 = internalRegisters.Extract(node, RBM_ALLINT); genInstrWithConstant(INS_add, EA_PTRSIZE, tempReg1, srcReg, srcOffsetAdjustment, tempReg1); srcReg = tempReg1; - const regNumber tempReg2 = node->ExtractTempReg(RBM_ALLINT); + const regNumber tempReg2 = internalRegisters.Extract(node, RBM_ALLINT); genInstrWithConstant(INS_add, EA_PTRSIZE, tempReg2, dstReg, dstOffsetAdjustment, tempReg2); dstReg = tempReg2; } else if (srcOffsetAdjustment != 0) { - const regNumber tempReg = node->ExtractTempReg(RBM_ALLINT); + const regNumber tempReg = internalRegisters.Extract(node, RBM_ALLINT); genInstrWithConstant(INS_add, EA_PTRSIZE, tempReg, srcReg, srcOffsetAdjustment, tempReg); srcReg = tempReg; } else if (dstOffsetAdjustment != 0) { - const regNumber tempReg = node->ExtractTempReg(RBM_ALLINT); + const regNumber tempReg = internalRegisters.Extract(node, RBM_ALLINT); genInstrWithConstant(INS_add, EA_PTRSIZE, tempReg, dstReg, dstOffsetAdjustment, tempReg); dstReg = tempReg; } @@ -2985,16 +2991,16 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) regNumber intReg1 = REG_NA; regNumber intReg2 = REG_NA; - const unsigned intRegCount = node->AvailableTempRegCount(RBM_ALLINT); + const unsigned intRegCount = internalRegisters.Count(node, RBM_ALLINT); if (intRegCount >= 2) { - intReg1 = node->ExtractTempReg(RBM_ALLINT); - intReg2 = node->ExtractTempReg(RBM_ALLINT); + intReg1 = internalRegisters.Extract(node, RBM_ALLINT); + intReg2 = internalRegisters.Extract(node, RBM_ALLINT); } else if (intRegCount == 1) { - intReg1 = node->GetSingleTempReg(RBM_ALLINT); + intReg1 = internalRegisters.GetSingle(node, RBM_ALLINT); intReg2 = rsGetRsvdReg(); } else @@ -3004,8 +3010,8 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) if (shouldUse16ByteWideInstrs) { - const regNumber simdReg1 = node->ExtractTempReg(RBM_ALLFLOAT); - const regNumber simdReg2 = node->GetSingleTempReg(RBM_ALLFLOAT); + const regNumber simdReg1 = internalRegisters.Extract(node, RBM_ALLFLOAT); + const regNumber simdReg2 = internalRegisters.GetSingle(node, RBM_ALLFLOAT); helper.Unroll(FP_REGSIZE_BYTES, intReg1, simdReg1, simdReg2, srcReg, dstReg, GetEmitter()); } @@ -3016,7 +3022,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) #endif // TARGET_ARM64 #ifdef TARGET_ARM - const regNumber tempReg = node->ExtractTempReg(RBM_ALLINT); + const regNumber tempReg = internalRegisters.Extract(node, RBM_ALLINT); for (unsigned regSize = REGSIZE_BYTES; size > 0; size -= regSize, srcOffset += regSize, dstOffset += regSize) { @@ -3141,13 +3147,13 @@ void CodeGen::genCodeForMemmove(GenTreeBlk* tree) if (size >= simdSize) { // Number of SIMD regs needed to save the whole src to regs. - const unsigned numberOfSimdRegs = tree->AvailableTempRegCount(RBM_ALLFLOAT); + const unsigned numberOfSimdRegs = internalRegisters.Count(tree, RBM_ALLFLOAT); // Pop all temp regs to a local array, currently, this impl is limited with LSRA's MaxInternalCount regNumber tempRegs[LinearScan::MaxInternalCount] = {}; for (unsigned i = 0; i < numberOfSimdRegs; i++) { - tempRegs[i] = tree->ExtractTempReg(RBM_ALLFLOAT); + tempRegs[i] = internalRegisters.Extract(tree, RBM_ALLFLOAT); } auto emitSimdLoadStore = [&](bool load) { @@ -3184,15 +3190,15 @@ void CodeGen::genCodeForMemmove(GenTreeBlk* tree) const unsigned loadStoreSize = 1 << BitOperations::Log2(size); if (loadStoreSize == size) { - const regNumber tmpReg = tree->GetSingleTempReg(RBM_ALLINT); + const regNumber tmpReg = internalRegisters.GetSingle(tree, RBM_ALLINT); emitLoadStore(/* load */ true, loadStoreSize, tmpReg, 0); emitLoadStore(/* load */ false, loadStoreSize, tmpReg, 0); } else { - assert(tree->AvailableTempRegCount() == 2); - const regNumber tmpReg1 = tree->ExtractTempReg(RBM_ALLINT); - const regNumber tmpReg2 = tree->ExtractTempReg(RBM_ALLINT); + assert(internalRegisters.Count(tree) == 2); + const regNumber tmpReg1 = internalRegisters.Extract(tree, RBM_ALLINT); + const regNumber tmpReg2 = internalRegisters.Extract(tree, RBM_ALLINT); emitLoadStore(/* load */ true, loadStoreSize, tmpReg1, 0); emitLoadStore(/* load */ true, loadStoreSize, tmpReg2, size - loadStoreSize); emitLoadStore(/* load */ false, loadStoreSize, tmpReg1, 0); @@ -3252,7 +3258,7 @@ void CodeGen::genCodeForInitBlkLoop(GenTreeBlk* initBlkNode) // Extend liveness of dstReg in case if it gets killed by the store. gcInfo.gcMarkRegPtrVal(dstReg, dstNode->TypeGet()); - const regNumber offsetReg = initBlkNode->GetSingleTempReg(); + const regNumber offsetReg = internalRegisters.GetSingle(initBlkNode); instGen_Set_Reg_To_Imm(EA_PTRSIZE, offsetReg, size - TARGET_POINTER_SIZE); BasicBlock* loop = genCreateTempLabel(); @@ -3336,7 +3342,7 @@ void CodeGen::genCall(GenTreeCall* call) const regNumber regThis = genGetThisArgReg(call); #if defined(TARGET_ARM) - const regNumber tmpReg = call->ExtractTempReg(); + const regNumber tmpReg = internalRegisters.Extract(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); @@ -3362,7 +3368,7 @@ void CodeGen::genCall(GenTreeCall* call) (call->IsVirtualStubRelativeIndir() && (call->gtEntryPoint.accessType == IAT_VALUE))); assert(call->gtControlExpr == nullptr); - regNumber tmpReg = call->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(call); // Register where we save call address in should not be overridden by epilog. assert((genRegMask(tmpReg) & (RBM_INT_CALLEE_TRASH & ~RBM_LR)) == genRegMask(tmpReg)); @@ -3370,7 +3376,7 @@ void CodeGen::genCall(GenTreeCall* call) call->IsVirtualStubRelativeIndir() ? compiler->virtualStubParamInfo->GetReg() : REG_R2R_INDIRECT_PARAM; GetEmitter()->emitIns_R_R(ins_Load(TYP_I_IMPL), emitActualTypeSize(TYP_I_IMPL), tmpReg, callAddrReg); // We will use this again when emitting the jump in genCallInstruction in the epilog - call->gtRsvdRegs |= genRegMask(tmpReg); + internalRegisters.Add(call, genRegMask(tmpReg)); } #endif @@ -3497,25 +3503,35 @@ void CodeGen::genCallInstruction(GenTreeCall* call) emitAttr retSize = EA_PTRSIZE; emitAttr secondRetSize = EA_UNKNOWN; - if (call->HasMultiRegRetVal()) - { - retSize = emitTypeSize(pRetTypeDesc->GetReturnRegType(0)); - secondRetSize = emitTypeSize(pRetTypeDesc->GetReturnRegType(1)); - } - else + // unused values are of no interest to GC. + if (!call->IsUnusedValue()) { - assert(call->gtType != TYP_STRUCT); - - if (call->gtType == TYP_REF) + if (call->HasMultiRegRetVal()) { - retSize = EA_GCREF; + retSize = emitTypeSize(pRetTypeDesc->GetReturnRegType(0)); + secondRetSize = emitTypeSize(pRetTypeDesc->GetReturnRegType(1)); } - else if (call->gtType == TYP_BYREF) + else { - retSize = EA_BYREF; + assert(call->gtType != TYP_STRUCT); + + if (call->gtType == TYP_REF) + { + retSize = EA_GCREF; + } + else if (call->gtType == TYP_BYREF) + { + retSize = EA_BYREF; + } } } +#ifdef TARGET_ARM + // ARM32 support multireg returns, but only to return 64bit primitives. + assert(secondRetSize != EA_GCREF); + assert(secondRetSize != EA_BYREF); +#endif + DebugInfo di; // We need to propagate the debug information to the call instruction, so we can emit // an IL to native mapping record for the call, to support managed return value debugging. @@ -3530,7 +3546,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) #ifdef DEBUG // Pass the call signature information down into the emitter so the emitter can associate // native call sites with the signatures they were generated from. - if (call->gtCallType != CT_HELPER) + if (!call->IsHelperCall()) { sigInfo = call->callSig; } @@ -3583,6 +3599,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) // We just need to emit "call reg" in this case. // assert(genIsValidIntReg(target->GetRegNum())); + bool noSafePoint = false; #ifdef TARGET_ARM64 bool isTlsHandleTarget = @@ -3596,6 +3613,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) GenTreeIntCon* iconNode = target->AsIntCon(); methHnd = (CORINFO_METHOD_HANDLE)iconNode->gtIconVal; retSize = EA_SET_FLG(retSize, EA_CNS_TLSGD_RELOC); + noSafePoint = true; // For NativeAOT, linux/arm64, linker wants the following pattern, so we will generate // it as part of the call. Generating individual instructions is tricky to get it @@ -3631,7 +3649,8 @@ void CodeGen::genCallInstruction(GenTreeCall* call) MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), di, target->GetRegNum(), - call->IsFastTailCall()); + call->IsFastTailCall(), + noSafePoint); #ifdef TARGET_ARM64 if (isTlsHandleTarget) @@ -3660,15 +3679,25 @@ void CodeGen::genCallInstruction(GenTreeCall* call) if (callThroughIndirReg != REG_NA) { assert(call->IsR2ROrVirtualStubRelativeIndir()); - regNumber targetAddrReg = call->GetSingleTempReg(); + regNumber targetAddrReg; // For fast tailcalls we have already loaded the call target when processing the call node. if (!call->IsFastTailCall()) { +#ifdef TARGET_ARM + // For arm32 we've allocated an internal register to load the target into. + // Loading into IP takes 4 bytes (instead of potentially 2 with another register). + targetAddrReg = internalRegisters.GetSingle(call); +#else + // For arm64 we just use IP0 and skip the internal register. + targetAddrReg = REG_INDIRECT_CALL_TARGET_REG; +#endif + GetEmitter()->emitIns_R_R(ins_Load(TYP_I_IMPL), emitActualTypeSize(TYP_I_IMPL), targetAddrReg, callThroughIndirReg); } else { + targetAddrReg = internalRegisters.GetSingle(call); // Register where we save call address in should not be overridden by epilog. assert((genRegMask(targetAddrReg) & (RBM_INT_CALLEE_TRASH & ~RBM_LR)) == genRegMask(targetAddrReg)); } @@ -3693,7 +3722,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) else { // Generate a direct call to a non-virtual user defined or helper method - assert(call->gtCallType == CT_HELPER || call->gtCallType == CT_USER_FUNC); + assert(call->IsHelperCall() || (call->gtCallType == CT_USER_FUNC)); void* addr = nullptr; #ifdef FEATURE_READYTORUN @@ -3704,7 +3733,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) } else #endif // FEATURE_READYTORUN - if (call->gtCallType == CT_HELPER) + if (call->IsHelperCall()) { CorInfoHelpFunc helperNum = compiler->eeGetHelperNum(methHnd); noway_assert(helperNum != CORINFO_HELP_UNDEF); @@ -3725,7 +3754,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) #ifdef TARGET_ARM if (!validImmForBL((ssize_t)addr)) { - regNumber tmpReg = call->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(call); instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, tmpReg, (ssize_t)addr); // clang-format off genEmitCall(emitter::EC_INDIR_R, @@ -3757,358 +3786,70 @@ void CodeGen::genCallInstruction(GenTreeCall* call) } } -// Produce code for a GT_JMP node. -// The arguments of the caller needs to be transferred to the callee before exiting caller. -// The actual jump to callee is generated as part of caller epilog sequence. -// Therefore the codegen of GT_JMP is to ensure that the callee arguments are correctly setup. -void CodeGen::genJmpMethod(GenTree* jmp) +//------------------------------------------------------------------------ +// genJmpPlaceVarArgs: +// Generate code to place all varargs correctly for a JMP. +// +void CodeGen::genJmpPlaceVarArgs() { - assert(jmp->OperGet() == GT_JMP); - assert(compiler->compJmpOpUsed); - - // If no arguments, nothing to do - if (compiler->info.compArgsCount == 0) - { - return; - } + assert(compiler->info.compIsVarArgs); - // Make sure register arguments are in their initial registers - // and stack arguments are put back as well. - unsigned varNum; - LclVarDsc* varDsc; +#ifdef TARGET_ARM64 + regMaskTP potentialArgs = RBM_ARG_REGS; - // First move any en-registered stack arguments back to the stack. - // At the same time any reg arg not in correct reg is moved back to its stack location. - // - // We are not strictly required to spill reg args that are not in the desired reg for a jmp call - // But that would require us to deal with circularity while moving values around. Spilling - // to stack makes the implementation simple, which is not a bad trade off given Jmp calls - // are not frequent. - for (varNum = 0; varNum < compiler->info.compArgsCount; varNum++) + for (unsigned varNum = 0; varNum < compiler->info.compArgsCount; varNum++) { - varDsc = compiler->lvaGetDesc(varNum); - - if (varDsc->lvPromoted) - { - noway_assert(varDsc->lvFieldCnt == 1); // We only handle one field here - - unsigned fieldVarNum = varDsc->lvFieldLclStart; - varDsc = compiler->lvaGetDesc(fieldVarNum); - } - noway_assert(varDsc->lvIsParam); - - if (varDsc->lvIsRegArg && (varDsc->GetRegNum() != REG_STK)) - { - // Skip reg args which are already in its right register for jmp call. - // If not, we will spill such args to their stack locations. - // - // If we need to generate a tail call profiler hook, then spill all - // arg regs to free them up for the callback. - if (!compiler->compIsProfilerHookNeeded() && (varDsc->GetRegNum() == varDsc->GetArgReg())) - continue; - } - else if (varDsc->GetRegNum() == REG_STK) - { - // Skip args which are currently living in stack. - continue; - } - - // If we came here it means either a reg argument not in the right register or - // a stack argument currently living in a register. In either case the following - // assert should hold. - assert(varDsc->GetRegNum() != REG_STK); - assert(varDsc->IsEnregisterableLcl()); - var_types storeType = varDsc->GetStackSlotHomeType(); - emitAttr storeSize = emitActualTypeSize(storeType); - -#ifdef TARGET_ARM - if (varDsc->TypeGet() == TYP_LONG) + const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(varNum); + for (unsigned i = 0; i < abiInfo.NumSegments; i++) { - // long - at least the low half must be enregistered - GetEmitter()->emitIns_S_R(INS_str, EA_4BYTE, varDsc->GetRegNum(), varNum, 0); - - // Is the upper half also enregistered? - if (varDsc->GetOtherReg() != REG_STK) + const ABIPassingSegment& segment = abiInfo.Segments[i]; + if (segment.IsPassedInRegister()) { - GetEmitter()->emitIns_S_R(INS_str, EA_4BYTE, varDsc->GetOtherReg(), varNum, sizeof(int)); + potentialArgs &= ~segment.GetRegisterMask(); } } - else -#endif // TARGET_ARM - { - GetEmitter()->emitIns_S_R(ins_Store(storeType), storeSize, varDsc->GetRegNum(), varNum, 0); - } - // Update lvRegNum life and GC info to indicate lvRegNum is dead and varDsc stack slot is going live. - // Note that we cannot modify varDsc->GetRegNum() here because another basic block may not be expecting it. - // Therefore manually update life of varDsc->GetRegNum(). - regMaskTP tempMask = genRegMask(varDsc->GetRegNum()); - regSet.RemoveMaskVars(tempMask); - gcInfo.gcMarkRegSetNpt(tempMask); - if (compiler->lvaIsGCTracked(varDsc)) - { - VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varNum); - } } -#ifdef PROFILING_SUPPORTED - // At this point all arg regs are free. - // Emit tail call profiler callback. - genProfilingLeaveCallback(CORINFO_HELP_PROF_FCN_TAILCALL); -#endif - - // Next move any un-enregistered register arguments back to their register. - regMaskTP fixedIntArgMask = RBM_NONE; // tracks the int arg regs occupying fixed args in case of a vararg method. - unsigned firstArgVarNum = BAD_VAR_NUM; // varNum of the first argument in case of a vararg method. - for (varNum = 0; varNum < compiler->info.compArgsCount; varNum++) + if (potentialArgs == RBM_NONE) { - varDsc = compiler->lvaGetDesc(varNum); - if (varDsc->lvPromoted) - { - noway_assert(varDsc->lvFieldCnt == 1); // We only handle one field here - - unsigned fieldVarNum = varDsc->lvFieldLclStart; - varDsc = compiler->lvaGetDesc(fieldVarNum); - } - noway_assert(varDsc->lvIsParam); - - // Skip if arg not passed in a register. - if (!varDsc->lvIsRegArg) - continue; - - // Register argument - noway_assert(isRegParamType(genActualType(varDsc->TypeGet()))); - - // Is register argument already in the right register? - // If not load it from its stack location. - regNumber argReg = varDsc->GetArgReg(); // incoming arg register - regNumber argRegNext = REG_NA; - -#ifdef TARGET_ARM64 - if (varDsc->GetRegNum() != argReg) - { - var_types loadType = TYP_UNDEF; - - if (varDsc->lvIsHfaRegArg()) - { - // Note that for HFA, the argument is currently marked address exposed so lvRegNum will always be - // REG_STK. We home the incoming HFA argument registers in the prolog. Then we'll load them back - // here, whether they are already in the correct registers or not. This is such a corner case that - // it is not worth optimizing it. - - assert(!compiler->info.compIsVarArgs); - - loadType = varDsc->GetHfaType(); - regNumber fieldReg = argReg; - emitAttr loadSize = emitActualTypeSize(loadType); - unsigned cSlots = varDsc->lvHfaSlots(); - - for (unsigned ofs = 0, cSlot = 0; cSlot < cSlots; cSlot++, ofs += (unsigned)loadSize) - { - GetEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, fieldReg, varNum, ofs); - assert(genIsValidFloatReg(fieldReg)); // No GC register tracking for floating point registers. - fieldReg = regNextOfType(fieldReg, loadType); - } - } - else - { - if (varTypeIsStruct(varDsc)) - { - // Must be <= 16 bytes or else it wouldn't be passed in registers, except for HFA, - // which can be bigger (and is handled above). - noway_assert(EA_SIZE_IN_BYTES(varDsc->lvSize()) <= 16); - loadType = varDsc->GetLayout()->GetGCPtrType(0); - } - else - { - loadType = compiler->mangleVarArgsType(genActualType(varDsc->TypeGet())); - } - emitAttr loadSize = emitActualTypeSize(loadType); - GetEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, argReg, varNum, 0); - - // Update argReg life and GC Info to indicate varDsc stack slot is dead and argReg is going live. - // Note that we cannot modify varDsc->GetRegNum() here because another basic block may not be - // expecting it. Therefore manually update life of argReg. Note that GT_JMP marks the end of - // the basic block and after which reg life and gc info will be recomputed for the new block - // in genCodeForBBList(). - regSet.AddMaskVars(genRegMask(argReg)); - gcInfo.gcMarkRegPtrVal(argReg, loadType); - - if (compiler->lvaIsMultiregStruct(varDsc, compiler->info.compIsVarArgs)) - { - // Restore the second register. - argRegNext = genRegArgNext(argReg); - - loadType = varDsc->GetLayout()->GetGCPtrType(1); - loadSize = emitActualTypeSize(loadType); - GetEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, argRegNext, varNum, TARGET_POINTER_SIZE); - - regSet.AddMaskVars(genRegMask(argRegNext)); - gcInfo.gcMarkRegPtrVal(argRegNext, loadType); - } - - if (compiler->lvaIsGCTracked(varDsc)) - { - VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); - } - } - } - - if (compiler->info.compIsVarArgs) - { - // In case of a jmp call to a vararg method ensure only integer registers are passed. - assert((genRegMask(argReg) & (RBM_ARG_REGS | RBM_ARG_RET_BUFF)) != RBM_NONE); - assert(!varDsc->lvIsHfaRegArg()); - - fixedIntArgMask |= genRegMask(argReg); - - if (compiler->lvaIsMultiregStruct(varDsc, compiler->info.compIsVarArgs)) - { - assert(argRegNext != REG_NA); - fixedIntArgMask |= genRegMask(argRegNext); - } - - if (argReg == REG_ARG_0) - { - assert(firstArgVarNum == BAD_VAR_NUM); - firstArgVarNum = varNum; - } - } - -#else // !TARGET_ARM64 + return; + } - bool twoParts = false; - var_types loadType = TYP_UNDEF; - if (varDsc->TypeGet() == TYP_LONG) - { - twoParts = true; - } - else if (varDsc->TypeGet() == TYP_DOUBLE) - { - if (compiler->info.compIsVarArgs || compiler->opts.compUseSoftFP) - { - twoParts = true; - } - } + // If we have more argument registers that weren't fixed args, then move + // them from their home (where we spilled them in the prolog) back to both + // the integer and float registers here. They may contain GC refs, so we + // cannot keep GC enabled while we do this. + GetEmitter()->emitDisableGC(); - if (twoParts) - { - argRegNext = genRegArgNext(argReg); + do + { + regNumber reg = genFirstRegNumFromMaskAndToggle(potentialArgs); - if (varDsc->GetRegNum() != argReg) - { - GetEmitter()->emitIns_R_S(INS_ldr, EA_PTRSIZE, argReg, varNum, 0); - GetEmitter()->emitIns_R_S(INS_ldr, EA_PTRSIZE, argRegNext, varNum, REGSIZE_BYTES); - } + int regIndex = reg - REG_ARG_0; + assert((regIndex >= 0) && (regIndex < MAX_REG_ARG)); - if (compiler->info.compIsVarArgs) - { - fixedIntArgMask |= genRegMask(argReg); - fixedIntArgMask |= genRegMask(argRegNext); - } - } - else if (varDsc->lvIsHfaRegArg()) - { - loadType = varDsc->GetHfaType(); - regNumber fieldReg = argReg; - emitAttr loadSize = emitActualTypeSize(loadType); - unsigned maxSize = min(varDsc->lvSize(), (LAST_FP_ARGREG + 1 - argReg) * REGSIZE_BYTES); + // In varargs methods we always save x0 to x7 as the first step in the + // prolog. They occupy the 8*8 bytes below the initial SP, with x7 at + // the top. + int loadOffset = (MAX_REG_ARG - regIndex) * -8; - for (unsigned ofs = 0; ofs < maxSize; ofs += (unsigned)loadSize) - { - if (varDsc->GetRegNum() != argReg) - { - GetEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, fieldReg, varNum, ofs); - } - assert(genIsValidFloatReg(fieldReg)); // we don't use register tracking for FP - fieldReg = regNextOfType(fieldReg, loadType); - } - } - else if (varTypeIsStruct(varDsc)) + if (isFramePointerUsed()) { - regNumber slotReg = argReg; - unsigned maxSize = min(varDsc->lvSize(), (REG_ARG_LAST + 1 - argReg) * REGSIZE_BYTES); - - for (unsigned ofs = 0; ofs < maxSize; ofs += REGSIZE_BYTES) - { - unsigned idx = ofs / REGSIZE_BYTES; - loadType = varDsc->GetLayout()->GetGCPtrType(idx); - - if (varDsc->GetRegNum() != argReg) - { - emitAttr loadSize = emitActualTypeSize(loadType); - - GetEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, slotReg, varNum, ofs); - } - - regSet.AddMaskVars(genRegMask(slotReg)); - gcInfo.gcMarkRegPtrVal(slotReg, loadType); - if (genIsValidIntReg(slotReg) && compiler->info.compIsVarArgs) - { - fixedIntArgMask |= genRegMask(slotReg); - } - - slotReg = genRegArgNext(slotReg); - } + loadOffset -= genCallerSPtoFPdelta(); } else { - loadType = compiler->mangleVarArgsType(genActualType(varDsc->TypeGet())); - - if (varDsc->GetRegNum() != argReg) - { - GetEmitter()->emitIns_R_S(ins_Load(loadType), emitTypeSize(loadType), argReg, varNum, 0); - } - - regSet.AddMaskVars(genRegMask(argReg)); - gcInfo.gcMarkRegPtrVal(argReg, loadType); - - if (genIsValidIntReg(argReg) && compiler->info.compIsVarArgs) - { - fixedIntArgMask |= genRegMask(argReg); - } - } - - if (compiler->lvaIsGCTracked(varDsc)) - { - VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); + loadOffset -= genCallerSPtoInitialSPdelta(); } -#endif // !TARGET_ARM64 - } - // Jmp call to a vararg method - if the method has fewer than fixed arguments that can be max size of reg, - // load the remaining integer arg registers from the corresponding - // shadow stack slots. This is for the reason that we don't know the number and type - // of non-fixed params passed by the caller, therefore we have to assume the worst case - // of caller passing all integer arg regs that can be max size of reg. - // - // The caller could have passed gc-ref/byref type var args. Since these are var args - // the callee no way of knowing their gc-ness. Therefore, mark the region that loads - // remaining arg registers from shadow stack slots as non-gc interruptible. - if (fixedIntArgMask != RBM_NONE) - { - assert(compiler->info.compIsVarArgs); - assert(firstArgVarNum != BAD_VAR_NUM); - - regMaskTP remainingIntArgMask = RBM_ARG_REGS & ~fixedIntArgMask; - if (remainingIntArgMask != RBM_NONE) - { - GetEmitter()->emitDisableGC(); - for (int argNum = 0, argOffset = 0; argNum < MAX_REG_ARG; ++argNum) - { - regNumber argReg = intArgRegs[argNum]; - regMaskTP argRegMask = genRegMask(argReg); + GetEmitter()->emitIns_R_R_I(INS_ldr, EA_PTRSIZE, reg, genFramePointerReg(), loadOffset); - if ((remainingIntArgMask & argRegMask) != 0) - { - remainingIntArgMask &= ~argRegMask; - GetEmitter()->emitIns_R_S(INS_ldr, EA_PTRSIZE, argReg, firstArgVarNum, argOffset); - } + } while (potentialArgs != RBM_NONE); - argOffset += REGSIZE_BYTES; - } - GetEmitter()->emitEnableGC(); - } - } + GetEmitter()->emitEnableGC(); +#else + unreached(); +#endif } //------------------------------------------------------------------------ @@ -4715,7 +4456,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) if (offset != 0) { - regNumber tmpReg = lea->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(lea); // When generating fully interruptible code we have to use the "large offset" sequence // when calculating a EA_BYREF as we can't report a byref that points outside of the object @@ -4797,7 +4538,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) else { // We require a tmpReg to hold the offset - regNumber tmpReg = lea->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(lea); // First load tmpReg with the large offset constant instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset); @@ -4946,7 +4687,7 @@ void CodeGen::genPushCalleeSavedRegisters() maskPushRegsInt |= genStackAllocRegisterMask(compiler->compLclFrameSize, maskPushRegsFloat); - assert(FitsIn(maskPushRegsInt)); + assert(FitsIn(maskPushRegsInt.getLow())); inst_IV(INS_push, (int)maskPushRegsInt); compiler->unwindPushMaskInt(maskPushRegsInt); diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 021a5d9dc579..a4c4bb9b45e9 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -62,10 +62,117 @@ CodeGenInterface* getCodeGenerator(Compiler* comp) return new (comp, CMK_Codegen) CodeGen(comp); } +NodeInternalRegisters::NodeInternalRegisters(Compiler* comp) + : m_table(comp->getAllocator(CMK_LSRA)) +{ +} + +//------------------------------------------------------------------------ +// Add: Add internal allocated registers for the specified node. +// +// Parameters: +// tree - IR node to add internal allocated registers to +// regs - Registers to add +// +void NodeInternalRegisters::Add(GenTree* tree, regMaskTP regs) +{ + assert(regs != RBM_NONE); + + regMaskTP* result = m_table.LookupPointerOrAdd(tree, RBM_NONE); + *result |= regs; +} + +//------------------------------------------------------------------------ +// Extract: Find the lowest number temporary register from the gtRsvdRegs set +// that is also in the optional given mask (typically, RBM_ALLINT or +// RBM_ALLFLOAT), and return it. Remove this register from the temporary +// register set, so it won't be returned again. +// +// Parameters: +// tree - IR node whose internal registers to extract +// mask - Mask of allowed registers that can be returned +// +// Returns: +// Register number. +// +regNumber NodeInternalRegisters::Extract(GenTree* tree, regMaskTP mask) +{ + regMaskTP* regs = m_table.LookupPointer(tree); + assert(regs != nullptr); + + regMaskTP availableSet = *regs & mask; + assert(availableSet != RBM_NONE); + + regNumber result = genFirstRegNumFromMask(availableSet); + *regs ^= genRegMask(result); + + return result; +} + +//------------------------------------------------------------------------ +// GetSingleTempReg: There is expected to be exactly one available temporary register +// in the given mask in the internal register set. Get that register. No future calls to get +// a temporary register are expected. Removes the register from the set, but only in +// DEBUG to avoid doing unnecessary work in non-DEBUG builds. +// +// Parameters: +// tree - IR node whose internal registers to extract +// mask - Mask of allowed registers that can be returned +// +// Returns: +// Register number. +// +regNumber NodeInternalRegisters::GetSingle(GenTree* tree, regMaskTP mask) +{ + regMaskTP* regs = m_table.LookupPointer(tree); + assert(regs != nullptr); + + regMaskTP availableSet = *regs & mask; + assert(genExactlyOneBit(availableSet)); + + regNumber result = genFirstRegNumFromMask(availableSet); + INDEBUG(*regs &= ~genRegMask(result)); + + return result; +} + +//------------------------------------------------------------------------ +// GetAll: Get all internal registers for the specified IR node. +// +// Parameters: +// tree - IR node whose internal registers to query +// +// Returns: +// Mask of registers. +// +regMaskTP NodeInternalRegisters::GetAll(GenTree* tree) +{ + regMaskTP regs; + return m_table.Lookup(tree, ®s) ? regs : RBM_NONE; +} + +//------------------------------------------------------------------------ +// Count: return the number of available temporary registers in the (optional) +// given set (typically, RBM_ALLINT or RBM_ALLFLOAT). +// +// Parameters: +// tree - IR node whose internal registers to query +// mask - Mask of registers to count +// +// Returns: +// Count of nodes +// +unsigned NodeInternalRegisters::Count(GenTree* tree, regMaskTP mask) +{ + regMaskTP regs; + return m_table.Lookup(tree, ®s) ? genCountBits(regs & mask) : 0; +} + // CodeGen constructor CodeGenInterface::CodeGenInterface(Compiler* theCompiler) : gcInfo(theCompiler) , regSet(theCompiler, gcInfo) + , internalRegisters(theCompiler) , compiler(theCompiler) , treeLifeUpdater(nullptr) { @@ -89,15 +196,6 @@ void CodeGenInterface::CopyRegisterInfo() CodeGen::CodeGen(Compiler* theCompiler) : CodeGenInterface(theCompiler) { -#if defined(TARGET_XARCH) - negBitmaskFlt = nullptr; - negBitmaskDbl = nullptr; - absBitmaskFlt = nullptr; - absBitmaskDbl = nullptr; - zroSimd12Elm3 = nullptr; - u8ToDblBitmask = nullptr; -#endif // defined(TARGET_XARCH) - #if defined(FEATURE_PUT_STRUCT_ARG_STK) && !defined(TARGET_X86) m_stkArgVarNum = BAD_VAR_NUM; #endif @@ -890,8 +988,8 @@ void CodeGen::genLogLabel(BasicBlock* bb) void CodeGen::genDefineTempLabel(BasicBlock* label) { genLogLabel(label); - label->bbEmitCookie = GetEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, - gcInfo.gcRegByrefSetCur DEBUG_ARG(label)); + label->bbEmitCookie = + GetEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur); } // genDefineInlineTempLabel: Define an inline label that does not affect the GC @@ -1665,7 +1763,7 @@ void CodeGen::genGenerateCode(void** codePtr, uint32_t* nativeSizeOfCode) if (genWriteBarrierUsed && JitConfig.EnableExtraSuperPmiQueries() && !compiler->opts.IsReadyToRun()) { void* ignored; - for (int i = CORINFO_HELP_ASSIGN_REF; i <= CORINFO_HELP_ASSIGN_STRUCT; i++) + for (int i = CORINFO_HELP_ASSIGN_REF; i <= CORINFO_HELP_BULK_WRITEBARRIER; i++) { compiler->compGetHelperFtn((CorInfoHelpFunc)i, &ignored); } @@ -1831,8 +1929,7 @@ void CodeGen::genGenerateMachineCode() if (compiler->fgHaveProfileWeights()) { - printf("; with %s: edge weights are %s, and fgCalledCount is " FMT_WT "\n", - compiler->compGetPgoSourceName(), compiler->fgHaveValidEdgeWeights ? "valid" : "invalid", + printf("; with %s: fgCalledCount is " FMT_WT "\n", compiler->compGetPgoSourceName(), compiler->fgCalledCount); } @@ -2803,1406 +2900,600 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ -/***************************************************************************** - * - * Generates code for moving incoming register arguments to their - * assigned location, in the function prolog. - */ +struct RegNode; -// std::max isn't constexpr until C++14 and we're still on C++11 -constexpr size_t const_max(size_t a, size_t b) +struct RegNodeEdge { - return a > b ? a : b; -} - -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable : 21000) // Suppress PREFast warning about overly large function -#endif - -#if !defined(TARGET_LOONGARCH64) && !defined(TARGET_RISCV64) -void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbered, RegState* regState) + RegNodeEdge* nextIncoming; + RegNode* from; + RegNode* to; + unsigned destOffset; + var_types type; +}; + +struct RegNode { -#ifdef DEBUG - if (verbose) + regNumber reg; + regNumber copiedReg; + RegNodeEdge* incoming; + RegNodeEdge* outgoing; + RegNode* next; +}; + +class RegGraph +{ + Compiler* m_comp; + ArrayStack m_nodes; + +public: + RegGraph(Compiler* compiler) + : m_comp(compiler) + , m_nodes(compiler->getAllocator(CMK_Codegen)) { - printf("*************** In genFnPrologCalleeRegArgs() for %s regs\n", regState->rsIsFloat ? "float" : "int"); } -#endif - - unsigned argMax; // maximum argNum value plus 1, (including the RetBuffArg) - unsigned argNum; // current argNum, always in [0..argMax-1] - unsigned fixedRetBufIndex; // argNum value used by the fixed return buffer argument (ARM64) - unsigned regArgNum; // index into the regArgTab[] table - regMaskTP regArgMaskLive = regState->rsCalleeRegArgMaskLiveIn; - bool doingFloat = regState->rsIsFloat; - - // We should be generating the prolog block when we are called - assert(compiler->compGeneratingProlog); - - // We expect to have some registers of the type we are doing, that are LiveIn, otherwise we don't need to be called. - noway_assert(regArgMaskLive != 0); - // If a method has 3 args (and no fixed return buffer) then argMax is 3 and valid indexes are 0,1,2 - // If a method has a fixed return buffer (on ARM64) then argMax gets set to 9 and valid index are 0-8 + // ----------------------------------------------------------------------------- + // Get: Find the node representing a register. // - // The regArgTab can always have unused entries, - // for example if an architecture always increments the arg register number but uses either - // an integer register or a floating point register to hold the next argument - // then with a mix of float and integer args you could have: + // Parameters: + // reg - Register // - // sampleMethod(int i, float x, int j, float y, int k, float z); - // r0, r2 and r4 as valid integer arguments with argMax as 5 - // and f1, f3 and f5 and valid floating point arguments with argMax as 6 - // The first one is doingFloat==false and the second one is doingFloat==true + // Returns: + // Node in the graph that represents "reg". Returns nullptr if no such + // node exists. // - // If a fixed return buffer (in r8) was also present then the first one would become: - // r0, r2, r4 and r8 as valid integer arguments with argMax as 9 - // - - argMax = regState->rsCalleeRegArgCount; - fixedRetBufIndex = (unsigned)-1; // Invalid value - - // If necessary we will select a correct xtraReg for circular floating point args later. - if (doingFloat) + RegNode* Get(regNumber reg) { - xtraReg = REG_NA; - noway_assert(argMax <= MAX_FLOAT_REG_ARG); + for (int i = 0; i < m_nodes.Height(); i++) + { + RegNode* node = m_nodes.Bottom(i); + if (node->reg == reg) + { + return node; + } + } + + return nullptr; } - else // we are doing the integer registers + + // ----------------------------------------------------------------------------- + // GetOrAdd: Find (or create) the node representing a register. + // + // Parameters: + // reg - Register + // + // Returns: + // Node in the graph that represents "reg". If no node exists it is + // created. + // + RegNode* GetOrAdd(regNumber reg) { - noway_assert(argMax <= MAX_REG_ARG); - if (hasFixedRetBuffReg(compiler->info.compCallConv)) + RegNode* node = Get(reg); + + if (node == nullptr) { - fixedRetBufIndex = theFixedRetBuffArgNum(compiler->info.compCallConv); - // We have an additional integer register argument when hasFixedRetBuffReg() is true - argMax = fixedRetBufIndex + 1; - assert(argMax == (MAX_REG_ARG + 1)); + node = new (m_comp, CMK_Codegen) RegNode; + node->reg = reg; + node->copiedReg = REG_NA; + node->incoming = nullptr; + node->outgoing = nullptr; + m_nodes.Push(node); } + + return node; } + // ----------------------------------------------------------------------------- + // AddEdge: Add an edge to the graph, indicating that data needs to be + // moved from one register to another. // - // Construct a table with the register arguments, for detecting circular and - // non-circular dependencies between the register arguments. A dependency is when - // an argument register Rn needs to be moved to register Rm that is also an argument - // register. The table is constructed in the order the arguments are passed in - // registers: the first register argument is in regArgTab[0], the second in - // regArgTab[1], etc. Note that on ARM, a TYP_DOUBLE takes two entries, starting - // at an even index. The regArgTab is indexed from 0 to argMax - 1. - // Note that due to an extra argument register for ARM64 (i.e theFixedRetBuffReg()) - // we have increased the allocated size of the regArgTab[] by one. + // Parameters: + // from - The source register node + // to - The destination register node + // type - The type of the data that is being moved from the source into the destination + // destOffset - The offset in the destination register where the data should be put // - struct regArgElem - { - unsigned varNum; // index into compiler->lvaTable[] for this register argument - var_types type; // the Jit type of this regArgTab entry - unsigned trashBy; // index into this regArgTab[] table of the register that will be copied to this register. - // That is, for regArgTab[x].trashBy = y, argument register number 'y' will be copied to - // argument register number 'x'. Only used when circular = true. - char slot; // 0 means the register is not used for a register argument - // 1 means the first part of a register argument - // 2, 3 or 4 means the second,third or fourth part of a multireg argument - bool stackArg; // true if the argument gets homed to the stack - bool writeThru; // true if the argument gets homed to both stack and register - bool processed; // true after we've processed the argument (and it is in its final location) - bool circular; // true if this register participates in a circular dependency loop. - bool hfaConflict; // arg is part of an HFA that will end up in the same register - // but in a different slot (eg arg in s3 = v3.s[0], needs to end up in v3.s[3]) - } regArgTab[const_max(MAX_REG_ARG + 1, MAX_FLOAT_REG_ARG)] = {}; + void AddEdge(RegNode* from, RegNode* to, var_types type, unsigned destOffset) + { + assert(type != TYP_STRUCT); + RegNodeEdge* edge = new (m_comp, CMK_Codegen) RegNodeEdge; + edge->from = from; + edge->to = to; + edge->type = type; + edge->destOffset = destOffset; - unsigned varNum; - LclVarDsc* varDsc; + // We currently never have multiple outgoing edges. + assert(from->outgoing == nullptr); + from->outgoing = edge; + + edge->nextIncoming = to->incoming; + to->incoming = edge; + } - for (varNum = 0; varNum < compiler->lvaCount; ++varNum) + // ----------------------------------------------------------------------------- + // FindNodeToProcess: Find the next register node to process incoming moves to. + // + // Returns: + // A register node to process, based on heuristics that try to reduce the + // amount of shuffling that needs to happen. + // + RegNode* FindNodeToProcess() { - varDsc = compiler->lvaGetDesc(varNum); + RegNode* lastNode = nullptr; - // Is this variable a register arg? - if (!varDsc->lvIsParam) + // Prefer a node with no outgoing edges meaning that its value does not + // need to be saved. + for (int i = 0; i < m_nodes.Height(); i++) { - continue; + RegNode* reg = m_nodes.Bottom(i); + if (reg->incoming == nullptr) + { + continue; + } + + if (reg->outgoing == nullptr) + { + return reg; + } + + lastNode = reg; } - if (!varDsc->lvIsRegArg) + // Otherwise we'll need to save some value regardless, so any node will + // do. + return lastNode; + } + + // ----------------------------------------------------------------------------- + // RemoveIncomingEdges: Mark that the incoming edges of a register nodes + // have been handled by deleting all its incoming edges from the graph. + // + // Parameters: + // node - The register node that has been handled and now contains its correct value + // busyRegs - [in, out] Pointer to register mask of registers that have live values we may need. + // This function may remove registers from this set since the source registers of the + // incoming edges no longer have outgoing edges and thus do not need to have their values + // preserved. + // + void RemoveIncomingEdges(RegNode* node, regMaskTP* busyRegs) + { + for (RegNodeEdge* edge = node->incoming; edge != nullptr; edge = edge->nextIncoming) { - continue; + // Unlink from source. + assert(edge->from->outgoing == edge); + edge->from->outgoing = nullptr; + + // Source no longer has outgoing edges, so its value is no longer + // needed for anything. Make the registers it was occupying + // available. + regNumber sourceReg = edge->from->copiedReg != REG_NA ? edge->from->copiedReg : edge->from->reg; + *busyRegs &= ~genRegMask(sourceReg); } - // When we have a promoted struct we have two possible LclVars that can represent the incoming argument - // in the regArgTab[], either the original TYP_STRUCT argument or the introduced lvStructField. - // We will use the lvStructField if we have a TYPE_INDEPENDENT promoted struct field otherwise - // use the original TYP_STRUCT argument. - // - if (varDsc->lvPromoted || varDsc->lvIsStructField) + node->incoming = nullptr; + } + +#ifdef DEBUG + // ----------------------------------------------------------------------------- + // Dump: Dump a textual representation of the graph to jitstdout. + // + void Dump() + { + printf("%d registers in register parameter interference graph\n", m_nodes.Height()); + for (int i = 0; i < m_nodes.Height(); i++) { - LclVarDsc* parentVarDsc = varDsc; - if (varDsc->lvIsStructField) + RegNode* regNode = m_nodes.Bottom(i); + printf(" %s", getRegName(regNode->reg)); + for (RegNodeEdge* incoming = regNode->incoming; incoming != nullptr; incoming = incoming->nextIncoming) { - assert(!varDsc->lvPromoted); - parentVarDsc = compiler->lvaGetDesc(varDsc->lvParentLcl); + printf("\n <- %s", getRegName(incoming->from->reg), varTypeName(incoming->type)); + + if (incoming->destOffset != 0) + { + printf(" (offset: %d)", incoming->destOffset); + } } - Compiler::lvaPromotionType promotionType = compiler->lvaGetPromotionType(parentVarDsc); + printf("\n"); + } + } +#endif +}; + +// ----------------------------------------------------------------------------- +// genParamStackType: Get the type that a part of a parameter passed in a +// register occupies on the stack. +// +// Parameters: +// dsc - The parameter +// seg - The segment passed in a register +// +// Return Value: +// Suitable type for the store. +// +var_types CodeGen::genParamStackType(LclVarDsc* dsc, const ABIPassingSegment& seg) +{ + assert(seg.IsPassedInRegister()); - if (promotionType == Compiler::PROMOTION_TYPE_INDEPENDENT) + switch (dsc->TypeGet()) + { + case TYP_BYREF: + case TYP_REF: + assert((seg.Offset == 0) && (seg.Size == TARGET_POINTER_SIZE)); + return dsc->TypeGet(); + case TYP_STRUCT: + { + if (genIsValidFloatReg(seg.GetRegister())) { - // For register arguments that are independent promoted structs we put the promoted field varNum in the - // regArgTab[] - if (varDsc->lvPromoted) - { - continue; - } + return seg.GetRegisterType(); } - else + + ClassLayout* layout = dsc->GetLayout(); + assert(seg.Offset < layout->GetSize()); + if (((seg.Offset % TARGET_POINTER_SIZE) == 0) && (seg.Size == TARGET_POINTER_SIZE)) { - // For register arguments that are not independent promoted structs we put the parent struct varNum in - // the regArgTab[] - if (varDsc->lvIsStructField) - { - continue; - } + return layout->GetGCPtrType(seg.Offset / TARGET_POINTER_SIZE); } + +#ifdef TARGET_ARM64 + // We round struct sizes up to TYP_I_IMPL on the stack frame so we + // can always use the full register size here. This allows us to + // use stp more often. + return TYP_I_IMPL; +#else + return genActualType(seg.GetRegisterType()); +#endif + } + default: + { + return genActualType(seg.GetRegisterType()); } + } +} -#ifdef SWIFT_SUPPORT - // The Swift self parameter is passed in a callee save register and is - // not part of the arg register order that this function relies on to - // handle conflicts. For this reason we always mark it as DNER and - // handle it outside the normal register arguments. - // TODO-CQ: Fix this. - if (varNum == compiler->lvaSwiftSelfArg) +// ----------------------------------------------------------------------------- +// genSpillOrAddRegisterParam: Handle a register parameter either by homing it +// to stack immediately, or by adding it to the register graph. +// +// Parameters: +// lclNum - Parameter local (or field of it) +// graph - The register graph to add to +// +void CodeGen::genSpillOrAddRegisterParam(unsigned lclNum, RegGraph* graph) +{ + regMaskTP paramRegs = intRegState.rsCalleeRegArgMaskLiveIn | floatRegState.rsCalleeRegArgMaskLiveIn; + LclVarDsc* varDsc = compiler->lvaGetDesc(lclNum); + + unsigned baseOffset = varDsc->lvIsStructField ? varDsc->lvFldOffset : 0; + unsigned size = varDsc->lvExactSize(); + + unsigned paramLclNum = varDsc->lvIsStructField ? varDsc->lvParentLcl : lclNum; + LclVarDsc* paramVarDsc = compiler->lvaGetDesc(paramLclNum); + const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(paramLclNum); + for (unsigned i = 0; i < abiInfo.NumSegments; i++) + { + const ABIPassingSegment& seg = abiInfo.Segments[i]; + if (!seg.IsPassedInRegister() || ((paramRegs & genRegMask(seg.GetRegister())) == 0)) { continue; } - // On a similar note, the SwiftError* parameter is not a real argument, - // and should not be allocated any registers/stack space. - // We mark it as being passed in REG_SWIFT_ERROR so it won't interfere with other args. - // In genFnProlog, we should have removed this callee-save register from intRegState.rsCalleeRegArgMaskLiveIn. - // TODO-CQ: Fix this. - if (varNum == compiler->lvaSwiftErrorArg) + if (seg.Offset + seg.Size <= baseOffset) + { + continue; + } + + if (baseOffset + size <= seg.Offset) { - assert((intRegState.rsCalleeRegArgMaskLiveIn & RBM_SWIFT_ERROR) == 0); continue; } -#endif - var_types regType = compiler->mangleVarArgsType(varDsc->TypeGet()); - // Change regType to the HFA type when we have a HFA argument - if (varDsc->lvIsHfaRegArg()) + if (varDsc->lvOnFrame && (!varDsc->lvIsInReg() || varDsc->lvLiveInOutOfHndlr)) { - if (TargetOS::IsWindows && TargetArchitecture::IsArm64 && compiler->info.compIsVarArgs) + var_types storeType = genParamStackType(paramVarDsc, seg); + if ((varDsc->TypeGet() != TYP_STRUCT) && (genTypeSize(genActualType(varDsc)) < genTypeSize(storeType))) { - assert(!"Illegal incoming HFA arg encountered in Vararg method."); + // Can happen for struct fields due to padding. + storeType = genActualType(varDsc); } - regType = varDsc->GetHfaType(); + + GetEmitter()->emitIns_S_R(ins_Store(storeType), emitActualTypeSize(storeType), seg.GetRegister(), lclNum, + seg.Offset - baseOffset); } -#if defined(UNIX_AMD64_ABI) - if (!varTypeIsStruct(regType)) -#endif // defined(UNIX_AMD64_ABI) + if (!varDsc->lvIsInReg()) { - bool isFloatReg = emitter::isFloatReg(varDsc->GetArgReg()); + continue; + } - if (isFloatReg != doingFloat) - { - // A struct might be passed partially in XMM register for System V calls. - // So a single arg might use both register files. - continue; - } - else if (isFloatReg != varTypeUsesFloatArgReg(regType)) - { - if (regType == TYP_FLOAT) - { - regType = TYP_INT; - } - else - { - assert(regType == TYP_DOUBLE); - regType = TYP_LONG; - } - } + var_types edgeType = genActualType(varDsc->GetRegisterType()); + // Some parameters can be passed in multiple registers but enregistered + // in a single one (e.g. SIMD types on arm64). In this case the edges + // we add here represent insertions of each element. + if (seg.Size < genTypeSize(edgeType)) + { + edgeType = seg.GetRegisterType(); } - int slots = 0; + RegNode* sourceReg = graph->GetOrAdd(seg.GetRegister()); + RegNode* destReg = graph->GetOrAdd(varDsc->GetRegNum()); -#if defined(UNIX_AMD64_ABI) - if (varTypeIsStruct(varDsc)) + if ((sourceReg != destReg) || (baseOffset != seg.Offset)) { - CORINFO_CLASS_HANDLE typeHnd; - if (varDsc->lvIsStructField) - { - // The only case we currently permit is a wrapped SIMD field, - // where we won't have the class handle available, so get it - // from the parent struct -- they will agree on ABI details. - LclVarDsc* parentDsc = compiler->lvaGetDesc(varDsc->lvParentLcl); - assert(varTypeIsSIMD(varDsc) && (parentDsc->lvFieldCnt == 1)); - typeHnd = parentDsc->GetLayout()->GetClassHandle(); - } - else - { - typeHnd = varDsc->GetLayout()->GetClassHandle(); - } - assert(typeHnd != nullptr); - SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc; - compiler->eeGetSystemVAmd64PassStructInRegisterDescriptor(typeHnd, &structDesc); - if (!structDesc.passedInRegisters) +#ifdef TARGET_ARM + if (edgeType == TYP_DOUBLE) { - // The var is not passed in registers. + assert(seg.Offset == baseOffset); + graph->AddEdge(sourceReg, destReg, TYP_FLOAT, 0); + + sourceReg = graph->GetOrAdd(REG_NEXT(sourceReg->reg)); + destReg = graph->GetOrAdd(REG_NEXT(destReg->reg)); + graph->AddEdge(sourceReg, destReg, TYP_FLOAT, 0); continue; } - - unsigned firstRegSlot = 0; - for (unsigned slotCounter = 0; slotCounter < structDesc.eightByteCount; slotCounter++) - { - regNumber regNum = varDsc->lvRegNumForSlot(slotCounter); - var_types slotRegType; - -#ifdef FEATURE_SIMD - // Assumption 1: - // RyuJit backend depends on the assumption that on 64-Bit targets Vector3 size is rounded off - // to TARGET_POINTER_SIZE and hence Vector3 locals on stack can be treated as TYP_SIMD16 for - // reading and writing purposes. Hence while homing a Vector3 type arg on stack we should - // home entire 16-bytes so that the upper-most 4-bytes will be zeroed when written to stack. - // - // Assumption 2: - // RyuJit backend is making another implicit assumption that Vector3 type args when passed in - // registers or on stack, the upper most 4-bytes will be zero. - // - // For P/Invoke return and Reverse P/Invoke argument passing, native compiler doesn't guarantee - // that upper 4-bytes of a Vector3 type struct is zero initialized and hence assumption 2 is - // invalid. - // - // RyuJIT x64 Windows: arguments are treated as passed by ref and hence read/written just 12 - // bytes. In case of Vector3 returns, Caller allocates a zero initialized Vector3 local and - // passes it retBuf arg and Callee method writes only 12 bytes to retBuf. For this reason, - // there is no need to clear upper 4-bytes of Vector3 type args. - // - // RyuJIT x64 Unix: arguments are treated as passed by value and read/writen as if TYP_SIMD16. - // Vector3 return values are returned two return registers and Caller assembles them into a - // single xmm reg. Hence RyuJIT explicitly generates code to clears upper 4-bytes of Vector3 - // type args in prolog and Vector3 type return value of a call - - if (varDsc->lvType == TYP_SIMD12) - { - slotRegType = TYP_DOUBLE; - } - else #endif - { - slotRegType = compiler->GetEightByteType(structDesc, slotCounter); - } - - regArgNum = genMapRegNumToRegArgNum(regNum, slotRegType, compiler->info.compCallConv); + graph->AddEdge(sourceReg, destReg, edgeType, seg.Offset - baseOffset); + } + } +} - if ((!doingFloat && (structDesc.IsIntegralSlot(slotCounter))) || - (doingFloat && (structDesc.IsSseSlot(slotCounter)))) - { - // Store the reg for the first slot. - if (slots == 0) - { - firstRegSlot = regArgNum; - } +// ----------------------------------------------------------------------------- +// genSpillOrAddNonStandardRegisterParam: Handle a non-standard register parameter either +// by homing it to stack immediately, or by adding it to the register graph. +// +// Parameters: +// lclNum - Local that represents the non-standard parameter +// sourceReg - Register that the non-standard parameter is in on entry to the function +// graph - The register graph to add to +// +void CodeGen::genSpillOrAddNonStandardRegisterParam(unsigned lclNum, regNumber sourceReg, RegGraph* graph) +{ + LclVarDsc* varDsc = compiler->lvaGetDesc(lclNum); + if (varDsc->lvOnFrame && (!varDsc->lvIsInReg() || varDsc->lvLiveInOutOfHndlr)) + { + GetEmitter()->emitIns_S_R(ins_Store(varDsc->TypeGet()), emitActualTypeSize(varDsc), sourceReg, lclNum, 0); + } - // Bingo - add it to our table - noway_assert(regArgNum < argMax); - noway_assert(regArgTab[regArgNum].slot == 0); // we better not have added it already (there better - // not be multiple vars representing this argument - // register) - regArgTab[regArgNum].varNum = varNum; - regArgTab[regArgNum].slot = (char)(slotCounter + 1); - regArgTab[regArgNum].type = slotRegType; - slots++; - } - } + if (varDsc->lvIsInReg()) + { + RegNode* sourceRegNode = graph->GetOrAdd(sourceReg); + RegNode* destRegNode = graph->GetOrAdd(varDsc->GetRegNum()); + graph->AddEdge(sourceRegNode, destRegNode, TYP_I_IMPL, 0); + } +} - if (slots == 0) - { - continue; // Nothing to do for this regState set. - } +// ----------------------------------------------------------------------------- +// genHomeRegisterParams: Move all register parameters to their initial +// assigned location. +// +// Parameters: +// initReg - A register that this method should communicate if it becomes non-zero +// initRegStillZeroed - [out] whether or not initReg is still zeroed +// +void CodeGen::genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed) +{ +#ifdef DEBUG + if (verbose) + { + printf("*************** In genHomeRegisterParams()\n"); + } +#endif - regArgNum = firstRegSlot; - } - else -#endif // defined(UNIX_AMD64_ABI) + regMaskTP paramRegs = intRegState.rsCalleeRegArgMaskLiveIn | floatRegState.rsCalleeRegArgMaskLiveIn; + if (compiler->opts.OptimizationDisabled()) + { + // All registers are going to frame + for (unsigned lclNum = 0; lclNum < compiler->info.compArgsCount; lclNum++) { - // Bingo - add it to our table - regArgNum = genMapRegNumToRegArgNum(varDsc->GetArgReg(), regType, compiler->info.compCallConv); - slots = 1; + LclVarDsc* lclDsc = compiler->lvaGetDesc(lclNum); - if (TargetArchitecture::IsArm32 || - (TargetOS::IsWindows && TargetArchitecture::IsArm64 && compiler->info.compIsVarArgs)) + if (!lclDsc->lvOnFrame) { - int lclSize = compiler->lvaLclSize(varNum); - if (lclSize > REGSIZE_BYTES) - { - slots = lclSize / REGSIZE_BYTES; - } - } -#if FEATURE_MULTIREG_ARGS - else if (varDsc->lvIsMultiRegArg) - { - if (varDsc->lvIsHfaRegArg()) - { - // We have an HFA argument, set slots to the number of registers used - slots = varDsc->lvHfaSlots(); - } - else - { - // Currently all non-HFA multireg structs are two registers in size (i.e. two slots) - assert(varDsc->lvSize() == (2 * TARGET_POINTER_SIZE)); - // We have a non-HFA multireg argument, set slots to two - slots = 2; - } + continue; } -#endif // FEATURE_MULTIREG_ARGS - // Handle args split between registers and stack. The arm64 fixed ret buf arg is never split. - if (compFeatureArgSplit() && (fixedRetBufIndex != regArgNum)) + const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(lclNum); + for (unsigned i = 0; i < abiInfo.NumSegments; i++) { - unsigned maxRegArgNum = doingFloat ? MAX_FLOAT_REG_ARG : MAX_REG_ARG; - if (regArgNum + slots > maxRegArgNum) + const ABIPassingSegment& seg = abiInfo.Segments[i]; + if (seg.IsPassedInRegister() && ((paramRegs & genRegMask(seg.GetRegister())) != 0)) { - JITDUMP("Splitting V%02u: %u registers, %u stack slots\n", varNum, maxRegArgNum - regArgNum, - regArgNum + slots - maxRegArgNum); - slots = maxRegArgNum - regArgNum; + var_types storeType = genParamStackType(lclDsc, seg); + GetEmitter()->emitIns_S_R(ins_Store(storeType), emitActualTypeSize(storeType), seg.GetRegister(), + lclNum, seg.Offset); } } + } - // Note that regArgNum + 1 represents an argument index not an actual argument register; - // see genMapRegArgNumToRegNum(). + if (compiler->info.compPublishStubParam && ((paramRegs & RBM_SECRET_STUB_PARAM) != RBM_NONE)) + { + GetEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SECRET_STUB_PARAM, + compiler->lvaStubArgumentVar, 0); + } - for (int i = 0; i < slots; i++) - { - noway_assert((regArgNum + i) < argMax); + return; + } - // We better not have added it already (there better not be multiple vars representing this argument - // register) - noway_assert(regArgTab[regArgNum + i].slot == 0); + // We build an interference graph where each node represents a register, + // and an edge regX -> regY represents moving (part of) register X to (part + // of) register Y. Note that in the general case each register can have + // multiple incoming edges. For example, on arm64/SysV x64 SIMD types can + // be passed in multiple registers but enregistered in a single vector + // register. + // Currently we never have multiple outgoing edges but one could imagine + // this situation if we allowed promotion when fields didn't fit exactly on + // top of the underlying registers. + RegGraph graph(compiler); - regArgTab[regArgNum + i].varNum = varNum; - regArgTab[regArgNum + i].slot = static_cast(i + 1); + for (unsigned lclNum = 0; lclNum < compiler->info.compArgsCount; lclNum++) + { + LclVarDsc* lclDsc = compiler->lvaGetDesc(lclNum); - regArgTab[regArgNum + i].type = regType; // Set the register type. + if (compiler->lvaGetPromotionType(lclNum) == Compiler::PROMOTION_TYPE_INDEPENDENT) + { + for (unsigned fld = 0; fld < lclDsc->lvFieldCnt; fld++) + { + unsigned fieldLclNum = lclDsc->lvFieldLclStart + fld; + genSpillOrAddRegisterParam(fieldLclNum, &graph); } } - - for (int i = 0; i < slots; i++) + else { - regType = regArgTab[regArgNum + i].type; - regNumber regNum = genMapRegArgNumToRegNum(regArgNum + i, regType, compiler->info.compCallConv); + genSpillOrAddRegisterParam(lclNum, &graph); + } + } -#if !defined(UNIX_AMD64_ABI) - assert((i > 0) || (regNum == varDsc->GetArgReg())); -#endif // defined(UNIX_AMD64_ABI) - - // Is the arg dead on entry to the method ? - - if ((regArgMaskLive & genRegMask(regNum)) == 0) - { - if (varDsc->lvTrackedNonStruct()) - { - // We may now see some tracked locals with zero refs. - // See Lowering::DoPhase. Tolerate these. - if (varDsc->lvRefCnt() > 0) - { - noway_assert(!VarSetOps::IsMember(compiler, compiler->fgFirstBB->bbLiveIn, varDsc->lvVarIndex)); - } - } - else - { -#ifdef TARGET_X86 - noway_assert(varDsc->lvType == TYP_STRUCT); -#else // !TARGET_X86 - // For LSRA, it may not be in regArgMaskLive if it has a zero - // refcnt. This is in contrast with the non-LSRA case in which all - // non-tracked args are assumed live on entry. - noway_assert((varDsc->lvRefCnt() == 0) || (varDsc->lvType == TYP_STRUCT) || - (varDsc->IsAddressExposed() && compiler->info.compIsVarArgs) || - (varDsc->IsAddressExposed() && compiler->opts.compUseSoftFP)); -#endif // !TARGET_X86 - } - // Mark it as processed and be done with it - regArgTab[regArgNum + i].processed = true; - goto NON_DEP; - } - -#ifdef TARGET_ARM - // On the ARM when the varDsc is a struct arg (or pre-spilled due to varargs) the initReg/xtraReg - // could be equal to GetArgReg(). The pre-spilled registers are also not considered live either since - // they've already been spilled. - // - if ((regSet.rsMaskPreSpillRegs(false) & genRegMask(regNum)) == 0) -#endif // TARGET_ARM - { -#if !defined(UNIX_AMD64_ABI) - noway_assert(xtraReg != (varDsc->GetArgReg() + i)); -#endif - noway_assert(regArgMaskLive & genRegMask(regNum)); - } - - regArgTab[regArgNum + i].processed = false; - regArgTab[regArgNum + i].writeThru = (varDsc->lvIsInReg() && varDsc->lvLiveInOutOfHndlr); - - /* mark stack arguments since we will take care of those first */ - regArgTab[regArgNum + i].stackArg = varDsc->lvIsInReg() ? false : true; - - /* If it goes on the stack or in a register that doesn't hold - * an argument anymore -> CANNOT form a circular dependency */ - - if (varDsc->lvIsInReg() && (genRegMask(regNum) & regArgMaskLive)) - { - /* will trash another argument -> possible dependency - * We may need several passes after the table is constructed - * to decide on that */ - - /* Maybe the argument stays in the register (IDEAL) */ - - if ((i == 0) && (varDsc->GetRegNum() == regNum)) - { - goto NON_DEP; - } - -#if !defined(TARGET_64BIT) - if ((i == 1) && varTypeIsStruct(varDsc) && (varDsc->GetOtherReg() == regNum)) - { - goto NON_DEP; - } - if ((i == 1) && (genActualType(varDsc->TypeGet()) == TYP_LONG) && (varDsc->GetOtherReg() == regNum)) - { - goto NON_DEP; - } - - if ((i == 1) && (genActualType(varDsc->TypeGet()) == TYP_DOUBLE) && - (REG_NEXT(varDsc->GetRegNum()) == regNum)) - { - goto NON_DEP; - } -#endif // !defined(TARGET_64BIT) - regArgTab[regArgNum + i].circular = true; - } - else - { - NON_DEP: - regArgTab[regArgNum + i].circular = false; - - /* mark the argument register as free */ - regArgMaskLive &= ~genRegMask(regNum); - } - } - } - - /* Find the circular dependencies for the argument registers, if any. - * A circular dependency is a set of registers R1, R2, ..., Rn - * such that R1->R2 (that is, R1 needs to be moved to R2), R2->R3, ..., Rn->R1 */ - - bool change = true; - bool hasHfaConflict = false; - if (regArgMaskLive) - { - /* Possible circular dependencies still exist; the previous pass was not enough - * to filter them out. Use a "sieve" strategy to find all circular dependencies. */ - - while (change) - { - change = false; - - for (argNum = 0; argNum < argMax; argNum++) - { - // If we already marked the argument as non-circular then continue - - if (!regArgTab[argNum].circular) - { - continue; - } - - if (regArgTab[argNum].slot == 0) // Not a register argument - { - continue; - } - - varNum = regArgTab[argNum].varNum; - varDsc = compiler->lvaGetDesc(varNum); - const var_types varRegType = varDsc->GetRegisterType(); - noway_assert(varDsc->lvIsParam && varDsc->lvIsRegArg); - - /* cannot possibly have stack arguments */ - noway_assert(varDsc->lvIsInReg()); - noway_assert(!regArgTab[argNum].stackArg); - - var_types regType = regArgTab[argNum].type; - regNumber regNum = genMapRegArgNumToRegNum(argNum, regType, compiler->info.compCallConv); - - regNumber destRegNum = REG_NA; - if (varTypeIsPromotable(varDsc) && - (compiler->lvaGetPromotionType(varDsc) == Compiler::PROMOTION_TYPE_INDEPENDENT)) - { - assert(regArgTab[argNum].slot <= varDsc->lvFieldCnt); - LclVarDsc* fieldVarDsc = compiler->lvaGetDesc(varDsc->lvFieldLclStart + regArgTab[argNum].slot - 1); - destRegNum = fieldVarDsc->GetRegNum(); - } - else if (regArgTab[argNum].slot == 1) - { - destRegNum = varDsc->GetRegNum(); - } -#if defined(TARGET_ARM64) && defined(FEATURE_SIMD) - else if (varDsc->lvIsHfa()) - { - // This must be a SIMD type that's fully enregistered, but is passed as an HFA. - // Each field will be inserted into the same destination register. - // - assert(varTypeIsSIMD(varDsc)); - assert(regArgTab[argNum].slot <= (int)varDsc->lvHfaSlots()); - assert(argNum > 0); - assert(regArgTab[argNum - 1].varNum == varNum); - - // If the field is passed in the same register as the destination, - // but is in the wrong part of the register, mark it specially so later - // we make sure to move it to the right spot before "freeing" the destination. - // - destRegNum = varDsc->GetRegNum(); - if (regNum == destRegNum) - { - // We only get here if the HFA part is not already in the right slot in - // the destination. That is, it is not slot-1. - // - const int slot = regArgTab[argNum].slot; - assert(slot != 1); - JITDUMP("HFA conflict; arg num %u needs to move from %s[%u] to %s[%u]\n", argNum, - getRegName(regNum), 0, getRegName(destRegNum), slot - 1); - regArgTab[argNum].hfaConflict = true; - - // We'll need to do a special pass later to resolve these - // - hasHfaConflict = true; - } - regArgMaskLive &= ~genRegMask(regNum); - regArgTab[argNum].circular = false; - change = true; - continue; - } -#elif defined(UNIX_AMD64_ABI) && defined(FEATURE_SIMD) - else - { - assert(regArgTab[argNum].slot == 2); - assert(argNum > 0); - assert(regArgTab[argNum - 1].slot == 1); - assert(regArgTab[argNum - 1].varNum == varNum); - assert((varRegType == TYP_SIMD12) || (varRegType == TYP_SIMD16)); - regArgMaskLive &= ~genRegMask(regNum); - regArgTab[argNum].circular = false; - change = true; - continue; - } -#endif // defined(UNIX_AMD64_ABI) && defined(FEATURE_SIMD) -#if !defined(TARGET_64BIT) - else if (regArgTab[argNum].slot == 2 && genActualType(varDsc->TypeGet()) == TYP_LONG) - { - destRegNum = varDsc->GetOtherReg(); - } - else - { - assert(regArgTab[argNum].slot == 2); - assert(varDsc->TypeGet() == TYP_DOUBLE); - destRegNum = REG_NEXT(varDsc->GetRegNum()); - } -#endif // !defined(TARGET_64BIT) - noway_assert(destRegNum != REG_NA); - if (genRegMask(destRegNum) & regArgMaskLive) - { - /* we are trashing a live argument register - record it */ - unsigned destRegArgNum = genMapRegNumToRegArgNum(destRegNum, regType, compiler->info.compCallConv); - noway_assert(destRegArgNum < argMax); - regArgTab[destRegArgNum].trashBy = argNum; - } - else - { - /* argument goes to a free register */ - regArgTab[argNum].circular = false; - change = true; - - /* mark the argument register as free */ - regArgMaskLive &= ~genRegMask(regNum); - } - } - } - } - - /* At this point, everything that has the "circular" flag - * set to "true" forms a circular dependency */ - -#ifdef DEBUG - if (regArgMaskLive) + if (compiler->info.compPublishStubParam && ((paramRegs & RBM_SECRET_STUB_PARAM) != RBM_NONE)) { - if (verbose) - { - printf("Circular dependencies found while home-ing the incoming arguments.\n"); - } + genSpillOrAddNonStandardRegisterParam(compiler->lvaStubArgumentVar, REG_SECRET_STUB_PARAM, &graph); } -#endif - - // LSRA allocates registers to incoming parameters in order and will not overwrite - // a register still holding a live parameter. - - noway_assert(((regArgMaskLive & RBM_FLTARG_REGS) == 0) && - "Homing of float argument registers with circular dependencies not implemented."); - - // Now move the arguments to their locations. - // First consider ones that go on the stack since they may free some registers. - // Also home writeThru args, since they're also homed to the stack. - - regArgMaskLive = regState->rsCalleeRegArgMaskLiveIn; // reset the live in to what it was at the start - for (argNum = 0; argNum < argMax; argNum++) - { - emitAttr size; - -#if defined(UNIX_AMD64_ABI) - // If this is the wrong register file, just continue. - if (regArgTab[argNum].type == TYP_UNDEF) - { - // This could happen if the reg in regArgTab[argNum] is of the other register file - - // for System V register passed structs where the first reg is GPR and the second an XMM reg. - // The next register file processing will process it. - continue; - } -#endif // defined(UNIX_AMD64_ABI) - - // If the arg is dead on entry to the method, skip it - - if (regArgTab[argNum].processed) - { - continue; - } - - if (regArgTab[argNum].slot == 0) // Not a register argument - { - continue; - } - - varNum = regArgTab[argNum].varNum; - varDsc = compiler->lvaGetDesc(varNum); - -#ifndef TARGET_64BIT - // If this arg is never on the stack, go to the next one. - if (varDsc->lvType == TYP_LONG) - { - if (regArgTab[argNum].slot == 1 && !regArgTab[argNum].stackArg && !regArgTab[argNum].writeThru) - { - continue; - } - else if (varDsc->GetOtherReg() != REG_STK) - { - continue; - } - } - else -#endif // !TARGET_64BIT - { - // If this arg is never on the stack, go to the next one. - if (!regArgTab[argNum].stackArg && !regArgTab[argNum].writeThru) - { - continue; - } - } - -#if defined(TARGET_ARM) - if (varDsc->lvType == TYP_DOUBLE) - { - if (regArgTab[argNum].slot == 2) - { - // We handled the entire double when processing the first half (slot == 1) - continue; - } - } -#endif - - noway_assert(regArgTab[argNum].circular == false); - - noway_assert(varDsc->lvIsParam); - noway_assert(varDsc->lvIsRegArg); - noway_assert(varDsc->lvIsInReg() == false || varDsc->lvLiveInOutOfHndlr || - (varDsc->lvType == TYP_LONG && varDsc->GetOtherReg() == REG_STK && regArgTab[argNum].slot == 2)); - var_types storeType = TYP_UNDEF; - unsigned slotSize = TARGET_POINTER_SIZE; + DBEXEC(VERBOSE, graph.Dump()); - if (varTypeIsStruct(varDsc)) - { - storeType = TYP_I_IMPL; // Default store type for a struct type is a pointer sized integer -#if FEATURE_MULTIREG_ARGS - // Must be <= MAX_PASS_MULTIREG_BYTES or else it wouldn't be passed in registers - noway_assert(varDsc->lvSize() <= MAX_PASS_MULTIREG_BYTES); -#endif // FEATURE_MULTIREG_ARGS -#ifdef UNIX_AMD64_ABI - storeType = regArgTab[argNum].type; -#endif // !UNIX_AMD64_ABI - if (varDsc->lvIsHfaRegArg()) - { -#ifdef TARGET_ARM - // On ARM32 the storeType for HFA args is always TYP_FLOAT - storeType = TYP_FLOAT; - slotSize = (unsigned)emitActualTypeSize(storeType); -#else // TARGET_ARM64 - storeType = genActualType(varDsc->GetHfaType()); - slotSize = (unsigned)emitActualTypeSize(storeType); -#endif // TARGET_ARM64 - } - } - else // Not a struct type - { - storeType = genActualType(regArgTab[argNum].type); - } - size = emitActualTypeSize(storeType); -#ifdef TARGET_X86 - noway_assert(genTypeSize(storeType) == TARGET_POINTER_SIZE); -#endif // TARGET_X86 - - regNumber srcRegNum = genMapRegArgNumToRegNum(argNum, storeType, compiler->info.compCallConv); - - // Stack argument - if the ref count is 0 don't care about it - - if (!varDsc->lvOnFrame) - { - noway_assert(varDsc->lvRefCnt() == 0); - } - else - { - // Since slot is typically 1, baseOffset is typically 0 - int baseOffset = (regArgTab[argNum].slot - 1) * slotSize; - - GetEmitter()->emitIns_S_R(ins_Store(storeType), size, srcRegNum, varNum, baseOffset); - -#ifndef UNIX_AMD64_ABI - // Check if we are writing past the end of the struct - if (varTypeIsStruct(varDsc)) - { - assert(varDsc->lvSize() >= baseOffset + (unsigned)size); - } -#endif // !UNIX_AMD64_ABI - } - - // Mark the argument as processed, and set it as no longer live in srcRegNum, - // unless it is a writeThru var, in which case we home it to the stack, but - // don't mark it as processed until below. - if (!regArgTab[argNum].writeThru) - { - regArgTab[argNum].processed = true; - regArgMaskLive &= ~genRegMask(srcRegNum); - } - -#if defined(TARGET_ARM) - if ((storeType == TYP_DOUBLE) && !regArgTab[argNum].writeThru) - { - regArgTab[argNum + 1].processed = true; - regArgMaskLive &= ~genRegMask(REG_NEXT(srcRegNum)); - } -#endif - } - - /* Process any circular dependencies */ - if (regArgMaskLive) + regMaskTP busyRegs = intRegState.rsCalleeRegArgMaskLiveIn | floatRegState.rsCalleeRegArgMaskLiveIn; + while (true) { - unsigned begReg, destReg, srcReg; - unsigned varNumDest, varNumSrc; - LclVarDsc* varDscDest; - LclVarDsc* varDscSrc; - instruction insCopy = INS_mov; - - if (doingFloat) + RegNode* node = graph.FindNodeToProcess(); + if (node == nullptr) { -#ifndef UNIX_AMD64_ABI - if (GlobalJitOptions::compFeatureHfa) -#endif // !UNIX_AMD64_ABI - { - insCopy = ins_Copy(TYP_DOUBLE); - // Compute xtraReg here when we have a float argument - assert(xtraReg == REG_NA); - - regMaskTP fpAvailMask; - - fpAvailMask = RBM_FLT_CALLEE_TRASH & ~regArgMaskLive; - if (GlobalJitOptions::compFeatureHfa) - { - fpAvailMask &= RBM_ALLDOUBLE; - } - - if (fpAvailMask == RBM_NONE) - { - fpAvailMask = RBM_ALLFLOAT & ~regArgMaskLive; - if (GlobalJitOptions::compFeatureHfa) - { - fpAvailMask &= RBM_ALLDOUBLE; - } - } - - assert(fpAvailMask != RBM_NONE); - - // We pick the lowest avail register number - regMaskTP tempMask = genFindLowestBit(fpAvailMask); - xtraReg = genRegNumFromMask(tempMask); - } -#if defined(TARGET_X86) - // This case shouldn't occur on x86 since NYI gets converted to an assert - NYI("Homing circular FP registers via xtraReg"); -#endif + break; } - for (argNum = 0; argNum < argMax; argNum++) - { - // If not a circular dependency then continue - if (!regArgTab[argNum].circular) - { - continue; - } - - // If already processed the dependency then continue - - if (regArgTab[argNum].processed) - { - continue; - } - - if (regArgTab[argNum].slot == 0) // Not a register argument - { - continue; - } - - destReg = begReg = argNum; - srcReg = regArgTab[argNum].trashBy; - - varNumDest = regArgTab[destReg].varNum; - varDscDest = compiler->lvaGetDesc(varNumDest); - noway_assert(varDscDest->lvIsParam && varDscDest->lvIsRegArg); - - noway_assert(srcReg < argMax); - varNumSrc = regArgTab[srcReg].varNum; - varDscSrc = compiler->lvaGetDesc(varNumSrc); - noway_assert(varDscSrc->lvIsParam && varDscSrc->lvIsRegArg); - - emitAttr size = EA_PTRSIZE; - -#ifdef TARGET_XARCH - // - // The following code relies upon the target architecture having an - // 'xchg' instruction which directly swaps the values held in two registers. - // On the ARM architecture we do not have such an instruction. - // - if (destReg == regArgTab[srcReg].trashBy) - { - /* only 2 registers form the circular dependency - use "xchg" */ - - varNum = regArgTab[argNum].varNum; - varDsc = compiler->lvaGetDesc(varNum); - noway_assert(varDsc->lvIsParam && varDsc->lvIsRegArg); - - noway_assert(genTypeSize(genActualType(varDscSrc->TypeGet())) <= REGSIZE_BYTES); - - /* Set "size" to indicate GC if one and only one of - * the operands is a pointer - * RATIONALE: If both are pointers, nothing changes in - * the GC pointer tracking. If only one is a pointer we - * have to "swap" the registers in the GC reg pointer mask - */ - - if (varTypeIsGC(varDscSrc) != varTypeIsGC(varDscDest)) - { - size = EA_GCREF; - } - - noway_assert(varDscDest->GetArgReg() == varDscSrc->GetRegNum()); - - GetEmitter()->emitIns_R_R(INS_xchg, size, varDscSrc->GetRegNum(), varDscSrc->GetArgReg()); - regSet.verifyRegUsed(varDscSrc->GetRegNum()); - regSet.verifyRegUsed(varDscSrc->GetArgReg()); - - /* mark both arguments as processed */ - regArgTab[destReg].processed = true; - regArgTab[srcReg].processed = true; - - regArgMaskLive &= ~genRegMask(varDscSrc->GetArgReg()); - regArgMaskLive &= ~genRegMask(varDscDest->GetArgReg()); - } - else -#endif // TARGET_XARCH - { - var_types destMemType = varDscDest->TypeGet(); - -#ifdef TARGET_ARM - bool cycleAllDouble = true; // assume the best - - unsigned iter = begReg; - do - { - if (compiler->lvaGetDesc(regArgTab[iter].varNum)->TypeGet() != TYP_DOUBLE) - { - cycleAllDouble = false; - break; - } - iter = regArgTab[iter].trashBy; - } while (iter != begReg); - - // We may treat doubles as floats for ARM because we could have partial circular - // dependencies of a float with a lo/hi part of the double. We mark the - // trashBy values for each slot of the double, so let the circular dependency - // logic work its way out for floats rather than doubles. If a cycle has all - // doubles, then optimize so that instead of two vmov.f32's to move a double, - // we can use one vmov.f64. - // - if (!cycleAllDouble && destMemType == TYP_DOUBLE) - { - destMemType = TYP_FLOAT; - } -#endif // TARGET_ARM - - if (destMemType == TYP_REF) - { - size = EA_GCREF; - } - else if (destMemType == TYP_BYREF) - { - size = EA_BYREF; - } - else if (destMemType == TYP_DOUBLE) - { - size = EA_8BYTE; - } - else if (destMemType == TYP_FLOAT) - { - size = EA_4BYTE; - } - // HVA types...? - - /* move the dest reg (begReg) in the extra reg */ - - assert(xtraReg != REG_NA); - - regNumber begRegNum = genMapRegArgNumToRegNum(begReg, destMemType, compiler->info.compCallConv); - GetEmitter()->emitIns_Mov(insCopy, size, xtraReg, begRegNum, /* canSkip */ false); - assert(!genIsValidIntReg(xtraReg) || !genIsValidFloatReg(begRegNum)); - - regSet.verifyRegUsed(xtraReg); - - *pXtraRegClobbered = true; - /* start moving everything to its right place */ - - while (srcReg != begReg) - { - /* mov dest, src */ - - regNumber destRegNum = genMapRegArgNumToRegNum(destReg, destMemType, compiler->info.compCallConv); - regNumber srcRegNum = genMapRegArgNumToRegNum(srcReg, destMemType, compiler->info.compCallConv); - - GetEmitter()->emitIns_Mov(insCopy, size, destRegNum, srcRegNum, /* canSkip */ false); - assert(!genIsValidIntReg(destRegNum) || !genIsValidFloatReg(srcRegNum)); - - regSet.verifyRegUsed(destRegNum); - - /* mark 'src' as processed */ - noway_assert(srcReg < argMax); - regArgTab[srcReg].processed = true; -#ifdef TARGET_ARM - if (size == EA_8BYTE) - regArgTab[srcReg + 1].processed = true; -#endif - regArgMaskLive &= ~genMapArgNumToRegMask(srcReg, destMemType); - - /* move to the next pair */ - destReg = srcReg; - srcReg = regArgTab[srcReg].trashBy; - - varDscDest = varDscSrc; - destMemType = varDscDest->TypeGet(); -#ifdef TARGET_ARM - if (!cycleAllDouble && destMemType == TYP_DOUBLE) - { - destMemType = TYP_FLOAT; - } -#endif - varNumSrc = regArgTab[srcReg].varNum; - varDscSrc = compiler->lvaGetDesc(varNumSrc); - noway_assert(varDscSrc->lvIsParam && varDscSrc->lvIsRegArg); - - if (destMemType == TYP_REF) - { - size = EA_GCREF; - } - else if (destMemType == TYP_DOUBLE) - { - size = EA_8BYTE; - } - else - { - size = EA_4BYTE; - } - } - - /* take care of the beginning register */ - - noway_assert(srcReg == begReg); - - /* move the dest reg (begReg) in the extra reg */ - - regNumber destRegNum = genMapRegArgNumToRegNum(destReg, destMemType, compiler->info.compCallConv); + assert(node->incoming != nullptr); - GetEmitter()->emitIns_Mov(insCopy, size, destRegNum, xtraReg, /* canSkip */ false); - assert(!genIsValidIntReg(destRegNum) || !genIsValidFloatReg(xtraReg)); - - regSet.verifyRegUsed(destRegNum); - /* mark the beginning register as processed */ - - regArgTab[srcReg].processed = true; #ifdef TARGET_ARM - if (size == EA_8BYTE) - regArgTab[srcReg + 1].processed = true; -#endif - regArgMaskLive &= ~genMapArgNumToRegMask(srcReg, destMemType); - } - } - } - -#if defined(TARGET_ARM64) && defined(FEATURE_SIMD) - // If we saw any hfa conflicts, handle those now. - // - if (hasHfaConflict) - { - // Up above we noticed that there was at least one non-slot-1 HFA arg whose - // destination register was the same as the arg register. - // - // For example, say an HFA was passed as s0-s3 and the destination was v3. - // s3 is in the right register, but not in the right slot in the register. - // - // We handle this by first moving the conflicting part to the right slot - // in the destination (via pass 0 below), and then moving the remaining parts - // to their respective slots (via pass 1). - // - // Note the slot index in the register is one less than value of - // regArgTab[argNum].slot, so a slot-1 hfa arg goes into slot 0 of the destination). - // - // So for the above example, we'd first move the "slot-4" s3 (== v3.s[0]) to v3.s[3]. - // Then we can insert s0 to v3.s[0]) and so on. - // - // We can exempt slot-1 cases as the conflicting part is already in the - // right slot, and code lower down correctly handles populating the remaining slots. - // - for (argNum = 0; argNum < argMax; argNum++) + // As an optimization on arm32 we handle the easy double move cases in + // a single move. + if (genIsValidFloatReg(node->reg) && (node->incoming->nextIncoming == nullptr) && (node->outgoing == nullptr) && + (node->incoming->from->copiedReg == REG_NA)) { - if (!regArgTab[argNum].hfaConflict) - { - continue; - } - - varNum = regArgTab[argNum].varNum; - varDsc = compiler->lvaGetDesc(varNum); - const regNumber destRegNum = varDsc->GetRegNum(); - const var_types regType = regArgTab[argNum].type; - const unsigned firstArgNum = argNum - (regArgTab[argNum].slot - 1); - const unsigned lastArgNum = firstArgNum + varDsc->lvHfaSlots() - 1; - - assert(varDsc->lvIsHfa()); - assert((argNum >= firstArgNum) && (argNum <= lastArgNum)); - assert(destRegNum == genMapRegArgNumToRegNum(argNum, regType, compiler->info.compCallConv)); - - // Pass 0: move the conflicting part; Pass1: insert everything else - // - for (int pass = 0; pass <= 1; pass++) - { - for (unsigned currentArgNum = firstArgNum; currentArgNum <= lastArgNum; currentArgNum++) - { - const regNumber regNum = - genMapRegArgNumToRegNum(currentArgNum, regType, compiler->info.compCallConv); - bool insertArg = - ((pass == 0) && (currentArgNum == argNum)) || ((pass == 1) && (currentArgNum != argNum)); - - if (insertArg) - { - assert(!regArgTab[currentArgNum].processed); - - // EA_4BYTE is probably wrong here (and below) - // todo -- suppress self move - GetEmitter()->emitIns_R_R_I_I(INS_mov, EA_4BYTE, destRegNum, regNum, - regArgTab[currentArgNum].slot - 1, 0); - assert(!genIsValidIntReg(destRegNum) || !genIsValidFloatReg(regNum)); - regArgTab[currentArgNum].processed = true; - regArgMaskLive &= ~genRegMask(regNum); - } - } - } - } - } -#endif // defined(TARGET_ARM64) && defined(FEATURE_SIMD) - - /* Finally take care of the remaining arguments that must be enregistered */ - while (regArgMaskLive) - { - regMaskTP regArgMaskLiveSave = regArgMaskLive; - - for (argNum = 0; argNum < argMax; argNum++) - { - /* If already processed go to the next one */ - if (regArgTab[argNum].processed) - { - continue; - } - - if (regArgTab[argNum].slot == 0) - { // Not a register argument - continue; - } - - varNum = regArgTab[argNum].varNum; - varDsc = compiler->lvaGetDesc(varNum); - const var_types regType = regArgTab[argNum].type; - const regNumber regNum = genMapRegArgNumToRegNum(argNum, regType, compiler->info.compCallConv); - const var_types varRegType = varDsc->GetRegisterType(); - -#if defined(UNIX_AMD64_ABI) - if (regType == TYP_UNDEF) - { - // This could happen if the reg in regArgTab[argNum] is of the other register file - - // for System V register passed structs where the first reg is GPR and the second an XMM reg. - // The next register file processing will process it. - regArgMaskLive &= ~genRegMask(regNum); - continue; - } -#endif // defined(UNIX_AMD64_ABI) - - noway_assert(varDsc->lvIsParam && varDsc->lvIsRegArg); -#ifdef TARGET_X86 - // On x86 we don't enregister args that are not pointer sized. - noway_assert(genTypeSize(varDsc->GetStackSlotHomeType()) == TARGET_POINTER_SIZE); -#endif // TARGET_X86 - - noway_assert(varDsc->lvIsInReg() && !regArgTab[argNum].circular); - - /* Register argument - hopefully it stays in the same register */ - regNumber destRegNum = REG_NA; - var_types destMemType = varDsc->GetRegisterType(); - - if (regArgTab[argNum].slot == 1) - { - destRegNum = varDsc->GetRegNum(); + RegNode* otherReg; + RegNode* lowReg; + RegNode* highReg; -#ifdef TARGET_ARM - if (genActualType(destMemType) == TYP_DOUBLE && regArgTab[argNum + 1].processed) - { - // The second half of the double has already been processed! Treat this as a single. - destMemType = TYP_FLOAT; - } -#endif // TARGET_ARM - } -#ifndef TARGET_64BIT - else if (regArgTab[argNum].slot == 2 && genActualType(destMemType) == TYP_LONG) + if (genIsValidDoubleReg(node->reg)) { - assert(genActualType(varDsc->TypeGet()) == TYP_LONG || genActualType(varDsc->TypeGet()) == TYP_DOUBLE); - if (genActualType(varDsc->TypeGet()) == TYP_DOUBLE) - { - destRegNum = regNum; - } - else - { - destRegNum = varDsc->GetOtherReg(); - } - - assert(destRegNum != REG_STK); + otherReg = graph.Get(REG_NEXT(node->reg)); + lowReg = node; + highReg = otherReg; } - else - { - assert(regArgTab[argNum].slot == 2); - assert(destMemType == TYP_DOUBLE); - - // For doubles, we move the entire double using the argNum representing - // the first half of the double. There are two things we won't do: - // (1) move the double when the 1st half of the destination is free but the - // 2nd half is occupied, and (2) move the double when the 2nd half of the - // destination is free but the 1st half is occupied. Here we consider the - // case where the first half can't be moved initially because its target is - // still busy, but the second half can be moved. We wait until the entire - // double can be moved, if possible. For example, we have F0/F1 double moving to F2/F3, - // and F2 single moving to F16. When we process F0, its target F2 is busy, - // so we skip it on the first pass. When we process F1, its target F3 is - // available. However, we want to move F0/F1 all at once, so we skip it here. - // We process F2, which frees up F2. The next pass through, we process F0 and - // F2/F3 are empty, so we move it. Note that if half of a double is involved - // in a circularity with a single, then we will have already moved that half - // above, so we go ahead and move the remaining half as a single. - // Because there are no circularities left, we are guaranteed to terminate. - - assert(argNum > 0); - assert(regArgTab[argNum - 1].slot == 1); - - if (!regArgTab[argNum - 1].processed) - { - // The first half of the double hasn't been processed; try to be processed at the same time - continue; - } - - // The first half of the double has been processed but the second half hasn't! - // This could happen for double F2/F3 moving to F0/F1, and single F0 moving to F2. - // In that case, there is a F0/F2 loop that is not a double-only loop. The circular - // dependency logic above will move them as singles, leaving just F3 to move. Treat - // it as a single to finish the shuffling. - - destMemType = TYP_FLOAT; - destRegNum = REG_NEXT(varDsc->GetRegNum()); - } -#endif // !TARGET_64BIT -#if (defined(UNIX_AMD64_ABI) || defined(TARGET_ARM64)) && defined(FEATURE_SIMD) - else - { - assert(regArgTab[argNum].slot == 2); - assert(argNum > 0); - assert(regArgTab[argNum - 1].slot == 1); - assert((varRegType == TYP_SIMD12) || (varRegType == TYP_SIMD16)); - destRegNum = varDsc->GetRegNum(); - noway_assert(regNum != destRegNum); - continue; - } -#endif // (defined(UNIX_AMD64_ABI) || defined(TARGET_ARM64)) && defined(FEATURE_SIMD) - noway_assert(destRegNum != REG_NA); - if (destRegNum != regNum) - { - /* Cannot trash a currently live register argument. - * Skip this one until its target will be free - * which is guaranteed to happen since we have no circular dependencies. */ - - regMaskTP destMask = genRegMask(destRegNum); -#ifdef TARGET_ARM - // Don't process the double until both halves of the destination are clear. - if (genActualType(destMemType) == TYP_DOUBLE) - { - assert((destMask & RBM_ALLDOUBLE) != 0); - destMask |= genRegMask(REG_NEXT(destRegNum)); - } -#endif - - if (destMask & regArgMaskLive) - { - continue; - } - - /* Move it to the new register */ - - emitAttr size = emitActualTypeSize(destMemType); - -#if defined(TARGET_ARM64) - if (varTypeIsSIMD(varDsc) && argNum < (argMax - 1) && regArgTab[argNum + 1].slot == 2) - { - // For a SIMD type that is passed in two integer registers, - // Limit the copy below to the first 8 bytes from the first integer register. - // Handle the remaining 8 bytes from the second slot in the code further below - assert(EA_SIZE(size) >= 8); - size = EA_8BYTE; - } -#endif - inst_Mov(destMemType, destRegNum, regNum, /* canSkip */ false, size); - assert(!genIsValidIntReg(destRegNum) || !genIsValidFloatReg(regNum)); + else + { + otherReg = graph.Get(REG_PREV(node->reg)); + lowReg = otherReg; + highReg = node; } - /* mark the argument as processed */ - - assert(!regArgTab[argNum].processed); - regArgTab[argNum].processed = true; - regArgMaskLive &= ~genRegMask(regNum); -#if FEATURE_MULTIREG_ARGS - int argRegCount = 1; -#ifdef TARGET_ARM - if (genActualType(destMemType) == TYP_DOUBLE) + if ((otherReg != nullptr) && (otherReg->incoming != nullptr) && + (otherReg->incoming->nextIncoming == nullptr) && (otherReg->incoming->from->copiedReg == REG_NA) && + (otherReg->outgoing == nullptr) && genIsValidDoubleReg(lowReg->incoming->from->reg) && + (highReg->incoming->from->reg == REG_NEXT(lowReg->incoming->from->reg))) { - argRegCount = 2; + instruction ins = ins_Copy(lowReg->incoming->from->reg, TYP_DOUBLE); + GetEmitter()->emitIns_Mov(ins, EA_8BYTE, lowReg->reg, lowReg->incoming->from->reg, false); + graph.RemoveIncomingEdges(lowReg, &busyRegs); + graph.RemoveIncomingEdges(highReg, &busyRegs); + busyRegs |= genRegMask(lowReg->reg) | genRegMask(highReg->reg); + assert((lowReg->reg != initReg) && (highReg->reg != initReg)); + continue; } + } #endif -#if defined(UNIX_AMD64_ABI) && defined(FEATURE_SIMD) - if (varTypeIsStruct(varDsc) && argNum < (argMax - 1) && regArgTab[argNum + 1].slot == 2) + + if ((node->outgoing != nullptr) && (node->copiedReg == REG_NA)) + { + var_types copyType = node->outgoing->type; + regMaskTP tempRegCandidates = genGetParameterHomingTempRegisterCandidates(); + tempRegCandidates &= ~busyRegs; + + regMaskTP regTypeMask = varTypeUsesFloatReg(copyType) ? RBM_ALLFLOAT : RBM_ALLINT; + regMaskTP availRegs = tempRegCandidates & regTypeMask; + + // We should have ensured temporary registers are available in + // genFinalizeFrame. + noway_assert(availRegs != RBM_NONE); + node->copiedReg = genFirstRegNumFromMask(availRegs); + busyRegs |= genRegMask(node->copiedReg); + + instruction ins = ins_Copy(node->reg, copyType); + GetEmitter()->emitIns_Mov(ins, emitActualTypeSize(copyType), node->copiedReg, node->reg, + /* canSkip */ false); + if (node->copiedReg == initReg) { - argRegCount = 2; - int nextArgNum = argNum + 1; - regNumber nextRegNum = - genMapRegArgNumToRegNum(nextArgNum, regArgTab[nextArgNum].type, compiler->info.compCallConv); - noway_assert(regArgTab[nextArgNum].varNum == varNum); - // Emit a shufpd with a 0 immediate, which preserves the 0th element of the dest reg - // and moves the 0th element of the src reg into the 1st element of the dest reg. - GetEmitter()->emitIns_R_R_I(INS_shufpd, emitActualTypeSize(varRegType), destRegNum, nextRegNum, 0); - assert(!genIsValidIntReg(destRegNum) || !genIsValidFloatReg(nextRegNum)); - // Set destRegNum to regNum so that we skip the setting of the register below, - // but mark argNum as processed and clear regNum from the live mask. - destRegNum = regNum; + *initRegStillZeroed = false; } -#endif // defined(UNIX_AMD64_ABI) && defined(FEATURE_SIMD) -#ifdef TARGET_ARMARCH - if (varDsc->lvIsHfa()) + } + + // First handle edges that aren't insertions. We clobber the full register for these edges. + for (RegNodeEdge* edge = node->incoming; edge != nullptr; edge = edge->nextIncoming) + { + if (edge->destOffset != 0) { - // This includes both fixed-size SIMD types that are independently promoted, as well - // as other HFA structs. - argRegCount = varDsc->lvHfaSlots(); - if (argNum < (argMax - argRegCount + 1)) - { - if (compiler->lvaGetPromotionType(varDsc) == Compiler::PROMOTION_TYPE_INDEPENDENT) - { - // For an HFA type that is passed in multiple registers and promoted, we copy each field to its - // destination register. - for (int i = 0; i < argRegCount; i++) - { - int nextArgNum = argNum + i; - LclVarDsc* fieldVarDsc = compiler->lvaGetDesc(varDsc->lvFieldLclStart + i); - regNumber nextRegNum = genMapRegArgNumToRegNum(nextArgNum, regArgTab[nextArgNum].type, - compiler->info.compCallConv); - destRegNum = fieldVarDsc->GetRegNum(); - noway_assert(regArgTab[nextArgNum].varNum == varNum); - noway_assert(genIsValidFloatReg(nextRegNum)); - noway_assert(genIsValidFloatReg(destRegNum)); - GetEmitter()->emitIns_Mov(INS_mov, EA_8BYTE, destRegNum, nextRegNum, /* canSkip */ false); - assert(!genIsValidIntReg(destRegNum) || !genIsValidFloatReg(nextRegNum)); - } - } -#if defined(TARGET_ARM64) && defined(FEATURE_SIMD) - else - { - // For a SIMD type that is passed in multiple registers but enregistered as a vector, - // the code above copies the first argument register into the lower 4 or 8 bytes - // of the target register. Here we must handle the subsequent fields by - // inserting them into the upper bytes of the target SIMD floating point register. - argRegCount = varDsc->lvHfaSlots(); - for (int i = 1; i < argRegCount; i++) - { - int nextArgNum = argNum + i; - regArgElem* nextArgElem = ®ArgTab[nextArgNum]; - var_types nextArgType = nextArgElem->type; - regNumber nextRegNum = - genMapRegArgNumToRegNum(nextArgNum, nextArgType, compiler->info.compCallConv); - noway_assert(nextArgElem->varNum == varNum); - noway_assert(genIsValidFloatReg(nextRegNum)); - noway_assert(genIsValidFloatReg(destRegNum)); - GetEmitter()->emitIns_R_R_I_I(INS_mov, EA_4BYTE, destRegNum, nextRegNum, i, 0); - assert(!genIsValidIntReg(destRegNum) || !genIsValidFloatReg(nextRegNum)); - } - } -#endif // defined(TARGET_ARM64) && defined(FEATURE_SIMD) - } + continue; } -#endif // TARGET_ARMARCH - // Mark the rest of the argument registers corresponding to this multi-reg type as - // being processed and no longer live. - for (int regSlot = 1; regSlot < argRegCount; regSlot++) + regNumber sourceReg = edge->from->copiedReg != REG_NA ? edge->from->copiedReg : edge->from->reg; + instruction ins = ins_Copy(sourceReg, genActualType(edge->type)); + GetEmitter()->emitIns_Mov(ins, emitActualTypeSize(edge->type), node->reg, sourceReg, + /* canSkip */ true); + break; + } + + // Next handle all insertions. + for (RegNodeEdge* edge = node->incoming; edge != nullptr; edge = edge->nextIncoming) + { + if (edge->destOffset == 0) { - int nextArgNum = argNum + regSlot; - assert(!regArgTab[nextArgNum].processed); - regArgTab[nextArgNum].processed = true; - regNumber nextRegNum = - genMapRegArgNumToRegNum(nextArgNum, regArgTab[nextArgNum].type, compiler->info.compCallConv); - regArgMaskLive &= ~genRegMask(nextRegNum); + continue; } -#endif // FEATURE_MULTIREG_ARGS + + regNumber sourceReg = edge->from->copiedReg != REG_NA ? edge->from->copiedReg : edge->from->reg; + +#if defined(TARGET_ARM64) + // On arm64 SIMD parameters are HFAs and passed in multiple float + // registers while we can enregister them as single registers. + GetEmitter()->emitIns_R_R_I_I(INS_mov, emitTypeSize(edge->type), node->reg, sourceReg, + edge->destOffset / genTypeSize(edge->type), 0); +#elif defined(UNIX_AMD64_ABI) + // For SysV x64 the only insertions we should have is to offset 8, + // which happens for example for Vector3 which can be passed in + // xmm0[0..8), xmm1[8..12) but enregistered in a single register. + noway_assert(edge->destOffset == 8); + assert(genIsValidFloatReg(node->reg)); + // The shufpd here picks the first 8 bytes from the dest register + // to go in the lower half, and the second 8 bytes from the source + // register to go in the upper half. + GetEmitter()->emitIns_R_R_I(INS_shufpd, EA_16BYTE, node->reg, sourceReg, 0); +#else + noway_assert(!"Insertion into register is not supported"); +#endif } - noway_assert(regArgMaskLiveSave != regArgMaskLive); // if it doesn't change, we have an infinite loop + graph.RemoveIncomingEdges(node, &busyRegs); + busyRegs |= genRegMask(node->reg); + + if (node->reg == initReg) + { + *initRegStillZeroed = false; + } } } -#endif // !TARGET_LOONGARCH64 && !TARGET_RISCV64 -#ifdef _PREFAST_ -#pragma warning(pop) -#endif +// ----------------------------------------------------------------------------- +// genGetParameterHomingTempRegisterCandidates: Get the registers that are +// usable during register homing. +// +// Remarks: +// Register homing is expected to take into account that values in some of +// these registers may still be needed. For example because it is the final +// destination register of a parameter, or because a value passed in one of +// these registers is still needed. +// +regMaskTP CodeGen::genGetParameterHomingTempRegisterCandidates() +{ + return RBM_CALLEE_TRASH | intRegState.rsCalleeRegArgMaskLiveIn | floatRegState.rsCalleeRegArgMaskLiveIn | + regSet.rsGetModifiedRegsMask(); +} /***************************************************************************** * If any incoming stack arguments live in registers, load them. @@ -4520,13 +3811,6 @@ void CodeGen::genCheckUseBlockInit() { regMaskTP maskCalleeRegArgMask = intRegState.rsCalleeRegArgMaskLiveIn; - // If there is a secret stub param, don't count it, as it will no longer - // be live when we do block init. - if (compiler->info.compPublishStubParam) - { - maskCalleeRegArgMask &= ~RBM_SECRET_STUB_PARAM; - } - #ifdef TARGET_ARM // // On the Arm if we are using a block init to initialize, then we @@ -4565,9 +3849,9 @@ void CodeGen::genZeroInitFltRegs(const regMaskTP& initFltRegs, const regMaskTP& // Iterate through float/double registers and initialize them to 0 or // copy from already initialized register of the same type. - regMaskTP regMask = genRegMask(REG_FP_FIRST); - for (regNumber reg = REG_FP_FIRST; reg <= REG_FP_LAST; reg = REG_NEXT(reg), regMask <<= 1) + for (regNumber reg = REG_FP_FIRST; reg <= REG_FP_LAST; reg = REG_NEXT(reg)) { + regMaskTP regMask = genRegMask(reg); if (regMask & initFltRegs) { // Do we have a float register already set to 0? @@ -4592,7 +3876,7 @@ void CodeGen::genZeroInitFltRegs(const regMaskTP& initFltRegs, const regMaskTP& } #elif defined(TARGET_XARCH) // XORPS is the fastest and smallest way to initialize a XMM register to zero. - GetEmitter()->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, reg, reg, reg); + GetEmitter()->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, reg, reg, reg, INS_OPTS_NONE); dblInitReg = reg; #elif defined(TARGET_ARM64) // We will just zero out the entire vector register. This sets it to a double/float zero value @@ -4632,7 +3916,7 @@ void CodeGen::genZeroInitFltRegs(const regMaskTP& initFltRegs, const regMaskTP& } #elif defined(TARGET_XARCH) // XORPS is the fastest and smallest way to initialize a XMM register to zero. - GetEmitter()->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, reg, reg, reg); + GetEmitter()->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, reg, reg, reg, INS_OPTS_NONE); fltInitReg = reg; #elif defined(TARGET_ARM64) // We will just zero out the entire vector register. This sets it to a double/float zero value @@ -4962,15 +4246,77 @@ void CodeGen::genEnregisterOSRArgsAndLocals() } } +#if defined(SWIFT_SUPPORT) || defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) +//----------------------------------------------------------------------------- +// genHomeSwiftStructParameters: Move the incoming segment to the local stack frame. +// +// Arguments: +// lclNum - Number of local variable to home +// seg - Stack segment of the local variable to home +// initReg - Scratch register to use if needed +// initRegStillZeroed - Set to false if the scratch register was needed +// +void CodeGen::genHomeStackSegment(unsigned lclNum, + const ABIPassingSegment& seg, + regNumber initReg, + bool* initRegStillZeroed) +{ + var_types loadType = TYP_UNDEF; + switch (seg.Size) + { + case 1: + loadType = TYP_UBYTE; + break; + case 2: + loadType = TYP_USHORT; + break; + case 3: + case 4: + loadType = TYP_INT; + break; + case 5: + case 6: + case 7: + case 8: + loadType = TYP_LONG; + break; + default: + assert(!"Unexpected segment size for struct parameter not passed implicitly by ref"); + return; + } + emitAttr size = emitTypeSize(loadType); + + int loadOffset = (int)seg.GetStackOffset(); + if (isFramePointerUsed()) + { + loadOffset -= genCallerSPtoFPdelta(); + } + else + { + loadOffset -= genCallerSPtoInitialSPdelta(); + } + +#ifdef TARGET_XARCH + GetEmitter()->emitIns_R_AR(ins_Load(loadType), size, initReg, genFramePointerReg(), loadOffset); +#else + genInstrWithConstant(ins_Load(loadType), size, initReg, genFramePointerReg(), loadOffset, initReg); +#endif + GetEmitter()->emitIns_S_R(ins_Store(loadType), size, initReg, lclNum, seg.Offset); + + if (initRegStillZeroed) + *initRegStillZeroed = false; +} +#endif // defined(SWIFT_SUPPORT) || defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) + #ifdef SWIFT_SUPPORT //----------------------------------------------------------------------------- // genHomeSwiftStructParameters: -// Reassemble Swift struct parameters if necessary. +// Reassemble Swift struct parameters if necessary. // -// Parameters: -// handleStack - If true, reassemble the segments that were passed on the stack. -// If false, reassemble the segments that were passed in registers. +// Arguments: +// handleStack - If true, reassemble the segments that were passed on the stack. +// If false, reassemble the segments that were passed in registers. // void CodeGen::genHomeSwiftStructParameters(bool handleStack) { @@ -4988,7 +4334,7 @@ void CodeGen::genHomeSwiftStructParameters(bool handleStack) } JITDUMP("Homing Swift parameter V%02u: ", lclNum); - const ABIPassingInformation& abiInfo = compiler->lvaParameterPassingInfo[lclNum]; + const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(lclNum); DBEXEC(VERBOSE, abiInfo.Dump()); for (unsigned i = 0; i < abiInfo.NumSegments; i++) @@ -5006,7 +4352,7 @@ void CodeGen::genHomeSwiftStructParameters(bool handleStack) if ((regState->rsCalleeRegArgMaskLiveIn & regs) != RBM_NONE) { - var_types storeType = seg.GetRegisterStoreType(); + var_types storeType = seg.GetRegisterType(); assert(storeType != TYP_UNDEF); GetEmitter()->emitIns_S_R(ins_Store(storeType), emitTypeSize(storeType), seg.GetRegister(), lclNum, seg.Offset); @@ -5016,55 +4362,63 @@ void CodeGen::genHomeSwiftStructParameters(bool handleStack) } else { - var_types loadType = TYP_UNDEF; - switch (seg.Size) - { - case 1: - loadType = TYP_UBYTE; - break; - case 2: - loadType = TYP_USHORT; - break; - case 4: - loadType = TYP_INT; - break; - case 8: - loadType = TYP_LONG; - break; - default: - assert(!"Unexpected segment size for struct parameter not passed implicitly by ref"); - continue; - } + // We can use REG_SCRATCH as a temporary register here as we ensured that during LSRA build. + genHomeStackSegment(lclNum, seg, REG_SCRATCH, nullptr); + } + } + } +} +#endif - int offset; - if (isFramePointerUsed()) - { - offset = -genCallerSPtoFPdelta(); - } - else - { - offset = -genCallerSPtoInitialSPdelta(); - } +//----------------------------------------------------------------------------- +// genHomeStackPartOfSplitParameter: Home the tail (stack) portion of a split parameter next to where the head +// (register) portion is homed. +// +// Arguments: +// initReg - scratch register to use if needed +// initRegStillZeroed - set to false if scratch register was needed +// +// Notes: +// No-op on platforms where argument registers are already homed to form a contiguous space with incoming stack. +// +void CodeGen::genHomeStackPartOfSplitParameter(regNumber initReg, bool* initRegStillZeroed) +{ +#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) + unsigned lclNum = 0; + for (; lclNum < compiler->info.compArgsCount; lclNum++) + { + LclVarDsc* var = compiler->lvaGetDesc(lclNum); + if (!var->lvOnFrame || !varTypeIsStruct(var)) + { + continue; + } - offset += (int)seg.GetStackOffset(); + const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(lclNum); + if (abiInfo.IsSplitAcrossRegistersAndStack()) + { + assert(var->lvIsSplit); + JITDUMP("Homing stack part of split parameter V%02u\n", lclNum); - // Move the incoming segment to the local stack frame. We can - // use REG_SCRATCH as a temporary register here as we ensured - // that during LSRA build. -#ifdef TARGET_XARCH - GetEmitter()->emitIns_R_AR(ins_Load(loadType), emitTypeSize(loadType), REG_SCRATCH, - genFramePointerReg(), offset); -#else - genInstrWithConstant(ins_Load(loadType), emitTypeSize(loadType), REG_SCRATCH, genFramePointerReg(), - offset, REG_SCRATCH); -#endif + assert(abiInfo.NumSegments == 2); + assert(abiInfo.Segments[0].GetRegister() == REG_ARG_LAST); + assert(abiInfo.Segments[1].GetStackOffset() == 0); + const ABIPassingSegment& seg = abiInfo.Segments[1]; + + genHomeStackSegment(lclNum, seg, initReg, initRegStillZeroed); - GetEmitter()->emitIns_S_R(ins_Store(loadType), emitTypeSize(loadType), REG_SCRATCH, lclNum, seg.Offset); +#ifdef DEBUG + for (lclNum += 1; lclNum < compiler->info.compArgsCount; lclNum++) + { + const ABIPassingInformation& abiInfo2 = compiler->lvaGetParameterABIInfo(lclNum); + // There should be only one split parameter + assert(!abiInfo2.IsSplitAcrossRegistersAndStack()); } +#endif + break; } } +#endif // TARGET_RISCV64 || TARGET_LOONGARCH64 } -#endif /*----------------------------------------------------------------------------- * @@ -5469,6 +4823,27 @@ void CodeGen::genFinalizeFrame() regSet.rsSetRegsModified(RBM_INT_CALLEE_SAVED & ~RBM_FPBASE); } + // Parameter homing may need an additional register to handle conflicts if + // all callee trash registers are used by parameters. + regMaskTP homingCandidates = genGetParameterHomingTempRegisterCandidates(); + if (((homingCandidates & ~intRegState.rsCalleeRegArgMaskLiveIn) & RBM_ALLINT) == RBM_NONE) + { + regMaskTP extraRegMask = RBM_ALLINT & ~homingCandidates; + assert(extraRegMask != RBM_NONE); + regNumber extraReg = genFirstRegNumFromMask(extraRegMask); + JITDUMP("No temporary registers are available for integer parameter homing. Adding %s\n", getRegName(extraReg)); + regSet.rsSetRegsModified(genRegMask(extraReg)); + } + + if (((homingCandidates & ~floatRegState.rsCalleeRegArgMaskLiveIn) & RBM_ALLFLOAT) == RBM_NONE) + { + regMaskTP extraRegMask = RBM_ALLFLOAT & ~homingCandidates; + assert(extraRegMask != RBM_NONE); + regNumber extraReg = genFirstRegNumFromMask(extraRegMask); + JITDUMP("No temporary registers are available for float parameter homing. Adding %s\n", getRegName(extraReg)); + regSet.rsSetRegsModified(genRegMask(extraReg)); + } + #ifdef UNIX_AMD64_ABI // On Unix x64 we also save R14 and R15 for ELT profiler hook generation. if (compiler->compIsProfilerHookNeeded()) @@ -5563,20 +4938,13 @@ void CodeGen::genFinalizeFrame() #endif // defined(TARGET_XARCH) #if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - if (isFramePointerUsed()) - { - // For a FP based frame we have to push/pop the FP register - // - maskCalleeRegsPushed |= RBM_FPBASE; + // This assert check that we are not using REG_FP + assert(!regSet.rsRegsModified(RBM_FPBASE)); - // This assert check that we are not using REG_FP - // as both the frame pointer and as a codegen register - // - assert(!regSet.rsRegsModified(RBM_FPBASE)); - } + assert(isFramePointerUsed()); + // we always push FP/RA. See genPushCalleeSavedRegisters + maskCalleeRegsPushed |= (RBM_FPBASE | RBM_RA); - // we always push RA. See genPushCalleeSavedRegisters - maskCalleeRegsPushed |= RBM_RA; #endif // TARGET_LOONGARCH64 || TARGET_RISCV64 compiler->compCalleeRegsPushed = genCountBits(maskCalleeRegsPushed); @@ -5925,28 +5293,6 @@ void CodeGen::genFnProlog() // will be skipped. bool initRegZeroed = false; regMaskTP excludeMask = intRegState.rsCalleeRegArgMaskLiveIn; - regMaskTP tempMask; - - // We should not use the special PINVOKE registers as the initReg - // since they are trashed by the jithelper call to setup the PINVOKE frame - if (compiler->compMethodRequiresPInvokeFrame()) - { - excludeMask |= RBM_PINVOKE_FRAME; - - assert(!compiler->opts.ShouldUsePInvokeHelpers() || (compiler->info.compLvFrameListRoot == BAD_VAR_NUM)); - if (!compiler->opts.ShouldUsePInvokeHelpers()) - { - excludeMask |= (RBM_PINVOKE_TCB | RBM_PINVOKE_SCRATCH); - - // We also must exclude the register used by compLvFrameListRoot when it is enregistered - // - const LclVarDsc* varDsc = compiler->lvaGetDesc(compiler->info.compLvFrameListRoot); - if (varDsc->lvRegister) - { - excludeMask |= genRegMask(varDsc->GetRegNum()); - } - } - } #ifdef TARGET_ARM // If we have a variable sized frame (compLocallocUsed is true) @@ -5965,7 +5311,7 @@ void CodeGen::genFnProlog() const bool isOSRx64Root = false; #endif // TARGET_AMD64 - tempMask = initRegs & ~excludeMask & ~regSet.rsMaskResvd; + regMaskTP tempMask = initRegs & ~excludeMask & ~regSet.rsMaskResvd; if (tempMask != RBM_NONE) { @@ -6019,17 +5365,6 @@ void CodeGen::genFnProlog() } #endif -#if !defined(TARGET_LOONGARCH64) && !defined(TARGET_RISCV64) - // For LoongArch64's OSR root frames, we may need a scratch register for large - // offset addresses. But this does not conflict with the REG_PINVOKE_FRAME. - // - // RISC-V64's OSR root frames are similar to LoongArch64's. In this case - // REG_SCRATCH also shouldn't conflict with REG_PINVOKE_FRAME, even if - // technically they are the same register - REG_T0. - // - noway_assert(!compiler->compMethodRequiresPInvokeFrame() || (initReg != REG_PINVOKE_FRAME)); -#endif // !TARGET_LOONGARCH64 && !TARGET_RISCV64 - #if defined(TARGET_AMD64) // If we are a varargs call, in order to set up the arguments correctly this // must be done in a 2 step process. As per the x64 ABI: @@ -6224,16 +5559,6 @@ void CodeGen::genFnProlog() } #endif // TARGET_ARM - if (compiler->info.compPublishStubParam) - { - GetEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SECRET_STUB_PARAM, - compiler->lvaStubArgumentVar, 0); - assert(intRegState.rsCalleeRegArgMaskLiveIn & RBM_SECRET_STUB_PARAM); - - // It's no longer live; clear it out so it can be used after this in the prolog - intRegState.rsCalleeRegArgMaskLiveIn &= ~RBM_SECRET_STUB_PARAM; - } - // // Zero out the frame as needed // @@ -6369,56 +5694,12 @@ void CodeGen::genFnProlog() { compiler->lvaUpdateArgsWithInitialReg(); -#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - if (intRegState.rsCalleeRegArgMaskLiveIn || floatRegState.rsCalleeRegArgMaskLiveIn) + genHomeStackPartOfSplitParameter(initReg, &initRegZeroed); + + if ((intRegState.rsCalleeRegArgMaskLiveIn | floatRegState.rsCalleeRegArgMaskLiveIn) != RBM_NONE) { - initRegZeroed = false; - genFnPrologCalleeRegArgs(); + genHomeRegisterParams(initReg, &initRegZeroed); } -#else - auto assignIncomingRegisterArgs = [this, initReg, &initRegZeroed](RegState* regState) { - if (regState->rsCalleeRegArgMaskLiveIn) - { - // If we need an extra register to shuffle around the incoming registers - // we will use xtraReg (initReg) and set the xtraRegClobbered flag, - // if we don't need to use the xtraReg then this flag will stay false - // - regNumber xtraReg; - bool xtraRegClobbered = false; - - if (genRegMask(initReg) & RBM_ARG_REGS) - { - xtraReg = initReg; - } - else - { - xtraReg = REG_SCRATCH; - initRegZeroed = false; - } - - genFnPrologCalleeRegArgs(xtraReg, &xtraRegClobbered, regState); - - if (xtraRegClobbered) - { - initRegZeroed = false; - } - } - }; - -#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_ARM) - // Handle float parameters first; in the presence of struct promotion - // we can have parameters that are homed into float registers but - // passed in integer registers. So make sure we get those out of the - // integer registers before we potentially override those as part of - // handling integer parameters. - - assignIncomingRegisterArgs(&floatRegState); - assignIncomingRegisterArgs(&intRegState); -#else - assignIncomingRegisterArgs(&intRegState); -#endif // TARGET_ARM64 || TARGET_LOONGARCH64 || TARGET_RISCV64 - -#endif // TARGET_LOONGARCH64 || TARGET_RISCV64 // Home the incoming arguments. genEnregisterIncomingStackArgs(); @@ -6428,10 +5709,9 @@ void CodeGen::genFnProlog() if (initRegs) { - regMaskTP regMask = 0x1; - - for (regNumber reg = REG_INT_FIRST; reg <= REG_INT_LAST; reg = REG_NEXT(reg), regMask <<= 1) + for (regNumber reg = REG_INT_FIRST; reg <= REG_INT_LAST; reg = REG_NEXT(reg)) { + regMaskTP regMask = genRegMask(reg); if (regMask & initRegs) { // Check if we have already zeroed this register @@ -6520,7 +5800,8 @@ void CodeGen::genFnProlog() noway_assert(compiler->info.compArgsCount > 0); // MOV EAX, - GetEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_EAX, compiler->info.compArgsCount - 1, 0); + assert(compiler->lvaVarargsHandleArg == compiler->info.compArgsCount - 1); + GetEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_EAX, compiler->lvaVarargsHandleArg, 0); regSet.verifyRegUsed(REG_EAX); // MOV EAX, [EAX] @@ -6529,7 +5810,7 @@ void CodeGen::genFnProlog() // EDX might actually be holding something here. So make sure to only use EAX for this code // sequence. - const LclVarDsc* lastArg = compiler->lvaGetDesc(compiler->info.compArgsCount - 1); + const LclVarDsc* lastArg = compiler->lvaGetDesc(compiler->lvaVarargsHandleArg); noway_assert(!lastArg->lvRegister); signed offset = lastArg->GetStackOffset(); assert(offset != BAD_STK_OFFS); @@ -7732,8 +7013,8 @@ GenTreeIntCon CodeGen::intForm(var_types type, ssize_t value) // void CodeGen::genLongReturn(GenTree* treeNode) { - assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT); - assert(treeNode->TypeGet() == TYP_LONG); + assert(treeNode->OperIs(GT_RETURN, GT_RETFILT)); + assert(treeNode->TypeIs(TYP_LONG)); GenTree* op1 = treeNode->gtGetOp1(); var_types targetType = treeNode->TypeGet(); @@ -7757,16 +7038,16 @@ void CodeGen::genLongReturn(GenTree* treeNode) // In case of LONG return on 32-bit, delegates to the genLongReturn method. // // Arguments: -// treeNode - The GT_RETURN or GT_RETFILT tree node. +// treeNode - The GT_RETURN/GT_RETFILT/GT_SWIFT_ERROR_RET tree node. // // Return Value: // None // void CodeGen::genReturn(GenTree* treeNode) { - assert(treeNode->OperIs(GT_RETURN, GT_RETFILT)); + assert(treeNode->OperIs(GT_RETURN, GT_RETFILT, GT_SWIFT_ERROR_RET)); - GenTree* op1 = treeNode->gtGetOp1(); + GenTree* op1 = treeNode->AsOp()->GetReturnValue(); var_types targetType = treeNode->TypeGet(); // A void GT_RETFILT is the end of a finally. For non-void filter returns we need to load the result in the return @@ -7868,7 +7149,7 @@ void CodeGen::genReturn(GenTree* treeNode) // // There should be a single GT_RETURN while generating profiler ELT callbacks. // - if (treeNode->OperIs(GT_RETURN) && compiler->compIsProfilerHookNeeded()) + if (treeNode->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET) && compiler->compIsProfilerHookNeeded()) { // !! NOTE !! // Since we are invalidating the assumption that we would slip into the epilog @@ -7938,18 +7219,28 @@ void CodeGen::genReturn(GenTree* treeNode) genStackPointerCheck(doStackPointerCheck, compiler->lvaReturnSpCheck); #endif // defined(DEBUG) && defined(TARGET_XARCH) +} #ifdef SWIFT_SUPPORT - // If this method has a SwiftError* out parameter, load the SwiftError pseudolocal value into the error register. - // TODO-CQ: Introduce GenTree node that models returning a normal and Swift error value. - if (compiler->lvaSwiftErrorArg != BAD_VAR_NUM) - { - assert(compiler->info.compCallConv == CorInfoCallConvExtension::Swift); - assert(compiler->lvaSwiftErrorLocal != BAD_VAR_NUM); - GetEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_SWIFT_ERROR, compiler->lvaSwiftErrorLocal, 0); - } -#endif // SWIFT_SUPPORT +//------------------------------------------------------------------------ +// genSwiftErrorReturn: Generates code for returning the normal return value, +// and loading the SwiftError pseudolocal value in the error register. +// +// Arguments: +// treeNode - The GT_SWIFT_ERROR_RET tree node. +// +// Return Value: +// None +// +void CodeGen::genSwiftErrorReturn(GenTree* treeNode) +{ + assert(treeNode->OperIs(GT_SWIFT_ERROR_RET)); + GenTree* swiftErrorNode = treeNode->gtGetOp1(); + const regNumber errorSrcReg = genConsumeReg(swiftErrorNode); + inst_Mov(swiftErrorNode->TypeGet(), REG_SWIFT_ERROR, errorSrcReg, true, EA_PTRSIZE); + genReturn(treeNode); } +#endif // SWIFT_SUPPORT //------------------------------------------------------------------------ // isStructReturn: Returns whether the 'treeNode' is returning a struct. @@ -7958,15 +7249,15 @@ void CodeGen::genReturn(GenTree* treeNode) // treeNode - The tree node to evaluate whether is a struct return. // // Return Value: -// Returns true if the 'treeNode" is a GT_RETURN node of type struct. +// Returns true if the 'treeNode' is a GT_RETURN/GT_SWIFT_ERROR_RET node of type struct. // Otherwise returns false. // bool CodeGen::isStructReturn(GenTree* treeNode) { - // This method could be called for 'treeNode' of GT_RET_FILT or GT_RETURN. + // This method could be called for 'treeNode' of GT_RET_FILT/GT_RETURN/GT_SWIFT_ERROR_RET. // For the GT_RET_FILT, the return is always a bool or a void, for the end of a finally block. - noway_assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT); - if (treeNode->OperGet() != GT_RETURN) + noway_assert(treeNode->OperIs(GT_RETURN, GT_RETFILT, GT_SWIFT_ERROR_RET)); + if (!treeNode->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)) { return false; } @@ -7993,13 +7284,13 @@ bool CodeGen::isStructReturn(GenTree* treeNode) // void CodeGen::genStructReturn(GenTree* treeNode) { - assert(treeNode->OperGet() == GT_RETURN); - - genConsumeRegs(treeNode->gtGetOp1()); + assert(treeNode->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)); - GenTree* op1 = treeNode->gtGetOp1(); + GenTree* op1 = treeNode->AsOp()->GetReturnValue(); GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); + genConsumeRegs(op1); + ReturnTypeDesc retTypeDesc = compiler->compRetTypeDesc; const unsigned regCount = retTypeDesc.GetReturnRegCount(); assert(regCount <= MAX_RET_REG_COUNT); @@ -8112,6 +7403,118 @@ void CodeGen::genStructReturn(GenTree* treeNode) #endif } +//------------------------------------------------------------------------ +// genJmpPlaceArgs: Place all parameters into their initial (ABI-decided) +// registers in preparation for a GT_JMP node. +// +// Arguments: +// jmp - The GT_JMP node +// +void CodeGen::genJmpPlaceArgs(GenTree* jmp) +{ + assert(jmp->OperIs(GT_JMP)); + assert(compiler->compJmpOpUsed); + + // First move any en-registered stack arguments back to the stack. + // At the same time any reg arg not in correct reg is moved back to its stack location. + // + // We are not strictly required to spill reg args that are not in the desired reg for a jmp call + // But that would require us to deal with circularity while moving values around. Spilling + // to stack makes the implementation simple, which is not a bad trade off given Jmp calls + // are not frequent. + for (unsigned varNum = 0; varNum < compiler->info.compArgsCount; varNum++) + { + LclVarDsc* varDsc = compiler->lvaGetDesc(varNum); + // Promotion is currently disabled entirely for methods using CEE_JMP. + assert(!varDsc->lvPromoted); + + if (varDsc->GetRegNum() == REG_STK) + { + continue; + } + + var_types storeType = varDsc->GetStackSlotHomeType(); + GetEmitter()->emitIns_S_R(ins_Store(storeType), emitTypeSize(storeType), varDsc->GetRegNum(), varNum, 0); + + // Update lvRegNum life and GC info to indicate lvRegNum is dead and varDsc stack slot is going live. + // Note that we cannot modify varDsc->GetRegNum() here because another basic block may not be expecting it. + // Therefore manually update life of varDsc->GetRegNum(). + regMaskTP tempMask = varDsc->lvRegMask(); + regSet.RemoveMaskVars(tempMask); + gcInfo.gcMarkRegSetNpt(tempMask); + if (compiler->lvaIsGCTracked(varDsc)) + { +#ifdef DEBUG + if (!VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex)) + { + JITDUMP("\t\t\t\t\t\t\tVar V%02u becoming live\n", varNum); + } + else + { + JITDUMP("\t\t\t\t\t\t\tVar V%02u continuing live\n", varNum); + } +#endif // DEBUG + + VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); + } + } + +#ifdef PROFILING_SUPPORTED + // At this point all arg regs are free. + // Emit tail call profiler callback. + genProfilingLeaveCallback(CORINFO_HELP_PROF_FCN_TAILCALL); +#endif + + // Next move any un-enregistered register arguments back to their register. + for (unsigned varNum = 0; varNum < compiler->info.compArgsCount; varNum++) + { + LclVarDsc* varDsc = compiler->lvaGetDesc(varNum); + + const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(varNum); + for (unsigned i = 0; i < abiInfo.NumSegments; i++) + { + const ABIPassingSegment& segment = abiInfo.Segments[i]; + if (segment.IsPassedOnStack()) + { + continue; + } + + var_types stackType = genParamStackType(varDsc, segment); + GetEmitter()->emitIns_R_S(ins_Load(stackType), emitTypeSize(stackType), segment.GetRegister(), varNum, + segment.Offset); + + // Update argReg life and GC Info to indicate varDsc stack slot is dead and argReg is going live. + // Note that we cannot modify varDsc->GetRegNum() here because another basic block may not be + // expecting it. Therefore manually update life of argReg. Note that GT_JMP marks the end of the + // basic block and after which reg life and gc info will be recomputed for the new block in + // genCodeForBBList(). + regSet.AddMaskVars(segment.GetRegisterMask()); + gcInfo.gcMarkRegPtrVal(segment.GetRegister(), stackType); + } + + if (compiler->lvaIsGCTracked(varDsc)) + { +#ifdef DEBUG + if (VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex)) + { + JITDUMP("\t\t\t\t\t\t\tVar V%02u becoming dead\n", varNum); + } + else + { + JITDUMP("\t\t\t\t\t\t\tVar V%02u continuing dead\n", varNum); + } +#endif // DEBUG + + VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); + } + } + + if (compFeatureVarArg() && compiler->info.compIsVarArgs) + { + genJmpPlaceVarArgs(); + } +} + //---------------------------------------------------------------------------------- // genMultiRegStoreToLocal: store multi-reg value to a local // diff --git a/src/coreclr/jit/codegeninterface.h b/src/coreclr/jit/codegeninterface.h index c47f505afc8f..42a22f3110bd 100644 --- a/src/coreclr/jit/codegeninterface.h +++ b/src/coreclr/jit/codegeninterface.h @@ -47,6 +47,21 @@ struct RegState CodeGenInterface* getCodeGenerator(Compiler* comp); +class NodeInternalRegisters +{ + typedef JitHashTable, regMaskTP> NodeInternalRegistersTable; + NodeInternalRegistersTable m_table; + +public: + NodeInternalRegisters(Compiler* comp); + + void Add(GenTree* tree, regMaskTP reg); + regNumber Extract(GenTree* tree, regMaskTP mask = static_cast(-1)); + regNumber GetSingle(GenTree* tree, regMaskTP mask = static_cast(-1)); + regMaskTP GetAll(GenTree* tree); + unsigned Count(GenTree* tree, regMaskTP mask = static_cast(-1)); +}; + class CodeGenInterface { friend class emitter; @@ -123,9 +138,10 @@ class CodeGenInterface GCInfo gcInfo; - RegSet regSet; - RegState intRegState; - RegState floatRegState; + RegSet regSet; + RegState intRegState; + RegState floatRegState; + NodeInternalRegisters internalRegisters; protected: Compiler* compiler; diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index 351ca1494283..75583e90dda9 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -348,7 +348,7 @@ void CodeGen::genCodeForBBlist() // Mark a label and update the current set of live GC refs block->bbEmitCookie = GetEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, - gcInfo.gcRegByrefSetCur DEBUG_ARG(block)); + gcInfo.gcRegByrefSetCur, block->Prev()); } if (block->IsFirstColdBlock(compiler)) @@ -498,9 +498,10 @@ void CodeGen::genCodeForBBlist() // as the determiner because something we are tracking as a byref // might be used as a return value of a int function (which is legal) GenTree* blockLastNode = block->lastNode(); - if ((blockLastNode != nullptr) && (blockLastNode->gtOper == GT_RETURN) && + if ((blockLastNode != nullptr) && (blockLastNode->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)) && (varTypeIsGC(compiler->info.compRetType) || - (blockLastNode->AsOp()->gtOp1 != nullptr && varTypeIsGC(blockLastNode->AsOp()->gtOp1->TypeGet())))) + (blockLastNode->AsOp()->GetReturnValue() != nullptr && + varTypeIsGC(blockLastNode->AsOp()->GetReturnValue()->TypeGet())))) { nonVarPtrRegs &= ~RBM_INTRET; } @@ -713,17 +714,14 @@ void CodeGen::genCodeForBBlist() } // Do likewise for blocks that end in DOES_NOT_RETURN calls // that were not caught by the above rules. This ensures that - // gc register liveness doesn't change across call instructions - // in fully-interruptible mode. + // gc register liveness doesn't change to some random state after call instructions else { GenTree* call = block->lastNode(); if ((call != nullptr) && (call->gtOper == GT_CALL)) { - if ((call->AsCall()->gtCallMoreFlags & GTF_CALL_M_DOES_NOT_RETURN) != 0 || - ((call->AsCall()->gtCallType == CT_HELPER) && - Compiler::s_helperCallProperties.AlwaysThrow(call->AsCall()->GetHelperNum()))) + if (call->AsCall()->IsNoReturn()) { instGen(INS_BREAKPOINT); // This should never get executed } @@ -761,19 +759,14 @@ void CodeGen::genCodeForBBlist() case BBJ_ALWAYS: { +#ifdef DEBUG GenTree* call = block->lastNode(); if ((call != nullptr) && (call->gtOper == GT_CALL)) { - if ((call->AsCall()->gtCallMoreFlags & GTF_CALL_M_DOES_NOT_RETURN) != 0 || - ((call->AsCall()->gtCallType == CT_HELPER) && - Compiler::s_helperCallProperties.AlwaysThrow(call->AsCall()->GetHelperNum()))) - { - // NOTE: We should probably never see a BBJ_ALWAYS block ending with a throw in a first place. - // If that is fixed, this condition can be just an assert. - // For the reasons why we insert a BP, see the similar code in "case BBJ_THROW:" above. - instGen(INS_BREAKPOINT); // This should never get executed - } + // At this point, BBJ_ALWAYS should never end with a call that doesn't return. + assert(!call->AsCall()->IsNoReturn()); } +#endif // DEBUG // If this block jumps to the next one, we might be able to skip emitting the jump if (block->CanRemoveJumpToNext(compiler)) @@ -1654,7 +1647,6 @@ void CodeGen::genConsumeRegs(GenTree* tree) // Update the life of the lcl var. genUpdateLife(tree); } -#ifdef TARGET_XARCH #ifdef FEATURE_HW_INTRINSICS else if (tree->OperIs(GT_HWINTRINSIC)) { @@ -1662,8 +1654,7 @@ void CodeGen::genConsumeRegs(GenTree* tree) genConsumeMultiOpOperands(hwintrinsic); } #endif // FEATURE_HW_INTRINSICS -#endif // TARGET_XARCH - else if (tree->OperIs(GT_BITCAST, GT_NEG, GT_CAST, GT_LSH, GT_RSH, GT_RSZ, GT_BSWAP, GT_BSWAP16)) + else if (tree->OperIs(GT_BITCAST, GT_NEG, GT_CAST, GT_LSH, GT_RSH, GT_RSZ, GT_ROR, GT_BSWAP, GT_BSWAP16)) { genConsumeRegs(tree->gtGetOp1()); } @@ -1913,7 +1904,7 @@ void CodeGen::genSetBlockSize(GenTreeBlk* blkNode, regNumber sizeReg) { if (sizeReg != REG_NA) { - assert((blkNode->gtRsvdRegs & genRegMask(sizeReg)) != 0); + assert((internalRegisters.GetAll(blkNode) & genRegMask(sizeReg)) != 0); // This can go via helper which takes the size as a native uint. instGen_Set_Reg_To_Imm(EA_PTRSIZE, sizeReg, blkNode->Size()); } @@ -2255,6 +2246,7 @@ void CodeGen::genTransferRegGCState(regNumber dst, regNumber src) // pass in 'addr' for a relative call or 'base' for a indirect register call // methHnd - optional, only used for pretty printing // retSize - emitter type of return for GC purposes, should be EA_BYREF, EA_GCREF, or EA_PTRSIZE(not GC) +// noSafePoint - force not making this call a safe point in partially interruptible code // // clang-format off void CodeGen::genEmitCall(int callType, @@ -2266,7 +2258,8 @@ void CodeGen::genEmitCall(int callType, MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize), const DebugInfo& di, regNumber base, - bool isJump) + bool isJump, + bool noSafePoint) { #if !defined(TARGET_X86) int argSize = 0; @@ -2286,7 +2279,7 @@ void CodeGen::genEmitCall(int callType, gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur, - di, base, REG_NA, 0, 0, isJump); + di, base, REG_NA, 0, 0, isJump, noSafePoint); } // clang-format on diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index 94329e348610..f86f3b515863 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -190,8 +190,7 @@ void CodeGen::genStackPointerAdjustment(ssize_t spDelta, regNumber tmpReg, bool* // reg1 - First register of pair to save. // reg2 - Second register of pair to save. // spOffset - The offset from SP to store reg1 (must be positive or zero). -// spDelta - If non-zero, the amount to add to SP before the register saves (must be negative or -// zero). +// spDelta - Always zero for LoongArch64 now. // useSaveNextPair - True if the last prolog instruction was to save the previous register pair. This // allows us to emit the "save_next" unwind code. // tmpReg - An available temporary register. Needed for the case of large frames. @@ -210,8 +209,7 @@ void CodeGen::genPrologSaveRegPair(regNumber reg1, bool* pTmpRegIsZero) { assert(spOffset >= 0); - assert(spDelta <= 0); - assert((spDelta % 16) == 0); // SP changes must be 16-byte aligned + assert(spDelta == 0); assert(genIsValidFloatReg(reg1) == genIsValidFloatReg(reg2)); // registers must be both general-purpose, or both // FP/SIMD @@ -221,16 +219,6 @@ void CodeGen::genPrologSaveRegPair(regNumber reg1, ins = INS_fst_d; } - if (spDelta != 0) - { - // generate addi.d SP,SP,-imm - genStackPointerAdjustment(spDelta, tmpReg, pTmpRegIsZero, /* reportUnwindData */ true); - - assert((spDelta + spOffset + 16) <= 0); - - assert(spOffset <= 2031); // 2047-16 - } - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); compiler->unwindSaveReg(reg1, spOffset); @@ -249,8 +237,7 @@ void CodeGen::genPrologSaveRegPair(regNumber reg1, // Arguments: // reg1 - Register to save. // spOffset - The offset from SP to store reg1 (must be positive or zero). -// spDelta - If non-zero, the amount to add to SP before the register saves (must be negative or -// zero). +// spDelta - Always zero for LoongArch64 now. // tmpReg - An available temporary register. Needed for the case of large frames. // pTmpRegIsZero - If we use tmpReg, and pTmpRegIsZero is non-null, we set *pTmpRegIsZero to 'false'. // Otherwise, we don't touch it. @@ -261,8 +248,7 @@ void CodeGen::genPrologSaveRegPair(regNumber reg1, void CodeGen::genPrologSaveReg(regNumber reg1, int spOffset, int spDelta, regNumber tmpReg, bool* pTmpRegIsZero) { assert(spOffset >= 0); - assert(spDelta <= 0); - assert((spDelta % 16) == 0); // SP changes must be 16-byte aligned + assert(spDelta == 0); instruction ins = INS_st_d; if (genIsValidFloatReg(reg1)) @@ -270,12 +256,6 @@ void CodeGen::genPrologSaveReg(regNumber reg1, int spOffset, int spDelta, regNum ins = INS_fst_d; } - if (spDelta != 0) - { - // generate addi.d SP,SP,-imm - genStackPointerAdjustment(spDelta, tmpReg, pTmpRegIsZero, /* reportUnwindData */ true); - } - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); compiler->unwindSaveReg(reg1, spOffset); } @@ -290,8 +270,7 @@ void CodeGen::genPrologSaveReg(regNumber reg1, int spOffset, int spDelta, regNum // reg1 - First register of pair to restore. // reg2 - Second register of pair to restore. // spOffset - The offset from SP to load reg1 (must be positive or zero). -// spDelta - If non-zero, the amount to add to SP after the register restores (must be positive or -// zero). +// spDelta - Always zero for LoongArch64 now. // useSaveNextPair - True if the last prolog instruction was to save the previous register pair. This // allows us to emit the "save_next" unwind code. // tmpReg - An available temporary register. Needed for the case of large frames. @@ -310,8 +289,7 @@ void CodeGen::genEpilogRestoreRegPair(regNumber reg1, bool* pTmpRegIsZero) { assert(spOffset >= 0); - assert(spDelta >= 0); - assert((spDelta % 16) == 0); // SP changes must be 16-byte aligned + assert(spDelta == 0); assert(genIsValidFloatReg(reg1) == genIsValidFloatReg(reg2)); // registers must be both general-purpose, or both // FP/SIMD @@ -321,27 +299,11 @@ void CodeGen::genEpilogRestoreRegPair(regNumber reg1, ins = INS_fld_d; } - if (spDelta != 0) - { - assert(!useSaveNextPair); - - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg2, REG_SPBASE, spOffset + 8); - compiler->unwindSaveReg(reg2, spOffset + 8); - - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); - compiler->unwindSaveReg(reg1, spOffset); - - // generate addi.d SP,SP,imm - genStackPointerAdjustment(spDelta, tmpReg, pTmpRegIsZero, /* reportUnwindData */ true); - } - else - { - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg2, REG_SPBASE, spOffset + 8); - compiler->unwindSaveReg(reg2, spOffset + 8); + GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg2, REG_SPBASE, spOffset + 8); + compiler->unwindSaveReg(reg2, spOffset + 8); - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); - compiler->unwindSaveReg(reg1, spOffset); - } + GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); + compiler->unwindSaveReg(reg1, spOffset); } //------------------------------------------------------------------------ @@ -350,8 +312,7 @@ void CodeGen::genEpilogRestoreRegPair(regNumber reg1, // Arguments: // reg1 - Register to restore. // spOffset - The offset from SP to restore reg1 (must be positive or zero). -// spDelta - If non-zero, the amount to add to SP after the register restores (must be positive or -// zero). +// spDelta - Always zero for LoongArch64 now. // tmpReg - An available temporary register. Needed for the case of large frames. // pTmpRegIsZero - If we use tmpReg, and pTmpRegIsZero is non-null, we set *pTmpRegIsZero to 'false'. // Otherwise, we don't touch it. @@ -362,8 +323,7 @@ void CodeGen::genEpilogRestoreRegPair(regNumber reg1, void CodeGen::genEpilogRestoreReg(regNumber reg1, int spOffset, int spDelta, regNumber tmpReg, bool* pTmpRegIsZero) { assert(spOffset >= 0); - assert(spDelta >= 0); - assert((spDelta % 16) == 0); // SP changes must be 16-byte aligned + assert(spDelta == 0); instruction ins = INS_ld_d; if (genIsValidFloatReg(reg1)) @@ -371,20 +331,8 @@ void CodeGen::genEpilogRestoreReg(regNumber reg1, int spOffset, int spDelta, reg ins = INS_fld_d; } - if (spDelta != 0) - { - // ld.d reg1,SP,offset - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); - compiler->unwindSaveReg(reg1, spOffset); - - // generate addi.d SP,SP,imm - genStackPointerAdjustment(spDelta, tmpReg, pTmpRegIsZero, /* reportUnwindData */ true); - } - else - { - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); - compiler->unwindSaveReg(reg1, spOffset); - } + GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); + compiler->unwindSaveReg(reg1, spOffset); } //------------------------------------------------------------------------ @@ -519,12 +467,13 @@ int CodeGen::genGetSlotSizeForRegsInMask(regMaskTP regsMask) // genSaveCalleeSavedRegisterGroup: Saves the group of registers described by the mask. // // Arguments: -// regsMask - a mask of registers for prolog generation; -// spDelta - if non-zero, the amount to add to SP before the first register save (or together with it); -// spOffset - the offset from SP that is the beginning of the callee-saved register area; +// regsMask - a mask of registers for prolog generation; +// spDelta - Always zero for LoongArch64 now. +// spOffset - the offset from SP that is the beginning of the callee-saved register area; // void CodeGen::genSaveCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta, int spOffset) { + assert(spDelta == 0); const int slotSize = genGetSlotSizeForRegsInMask(regsMask); ArrayStack regStack(compiler->getAllocator(CMK_Codegen)); @@ -536,19 +485,16 @@ void CodeGen::genSaveCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta, i if (regPair.reg2 != REG_NA) { // We can use two SD instructions. - genPrologSaveRegPair(regPair.reg1, regPair.reg2, spOffset, spDelta, regPair.useSaveNextPair, REG_R21, - nullptr); + genPrologSaveRegPair(regPair.reg1, regPair.reg2, spOffset, 0, regPair.useSaveNextPair, REG_R21, nullptr); spOffset += 2 * slotSize; } else { // No register pair; we use a SD instruction. - genPrologSaveReg(regPair.reg1, spOffset, spDelta, REG_R21, nullptr); + genPrologSaveReg(regPair.reg1, spOffset, 0, REG_R21, nullptr); spOffset += slotSize; } - - spDelta = 0; // We've now changed SP already, if necessary; don't do it again. } } @@ -574,34 +520,22 @@ void CodeGen::genSaveCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta, i // // Arguments: // regsToSaveMask - The mask of callee-saved registers to save. If empty, this function does nothing. -// lowestCalleeSavedOffset - The offset from SP that is the beginning of the callee-saved register area. Note that -// if non-zero spDelta, then this is the offset of the first save *after* that -// SP adjustment. -// spDelta - If non-zero, the amount to add to SP before the register saves (must be negative or -// zero). +// lowestCalleeSavedOffset - The offset from SP that is the beginning of the callee-saved register area. +// spDelta - Always zero for LoongArch64 now. // // Notes: // The save set can not contain FP/RA in which case FP/RA is saved along with the other callee-saved registers. // void CodeGen::genSaveCalleeSavedRegistersHelp(regMaskTP regsToSaveMask, int lowestCalleeSavedOffset, int spDelta) { - assert(spDelta <= 0); + assert(spDelta == 0); - unsigned regsToSaveCount = genCountBits(regsToSaveMask); - if (regsToSaveCount == 0) + if (regsToSaveMask == 0) { - if (spDelta != 0) - { - // Currently this is the case for varargs only - // whose size is MAX_REG_ARG * REGSIZE_BYTES = 64 bytes. - genStackPointerAdjustment(spDelta, REG_R21, nullptr, /* reportUnwindData */ true); - } return; } - assert((spDelta % 16) == 0); - - assert(regsToSaveCount <= genCountBits(RBM_CALLEE_SAVED)); + assert(genCountBits(regsToSaveMask) <= genCountBits(regMaskTP(RBM_CALLEE_SAVED))); // Save integer registers at higher addresses than floating-point registers. @@ -610,15 +544,14 @@ void CodeGen::genSaveCalleeSavedRegistersHelp(regMaskTP regsToSaveMask, int lowe if (maskSaveRegsFloat != RBM_NONE) { - genSaveCalleeSavedRegisterGroup(maskSaveRegsFloat, spDelta, lowestCalleeSavedOffset); - spDelta = 0; + genSaveCalleeSavedRegisterGroup(maskSaveRegsFloat, 0, lowestCalleeSavedOffset); lowestCalleeSavedOffset += genCountBits(maskSaveRegsFloat) * FPSAVE_REGSIZE_BYTES; } if (maskSaveRegsInt != RBM_NONE) { - genSaveCalleeSavedRegisterGroup(maskSaveRegsInt, spDelta, lowestCalleeSavedOffset); - // No need to update spDelta, lowestCalleeSavedOffset since they're not used after this. + // No need to update spDelta. + genSaveCalleeSavedRegisterGroup(maskSaveRegsInt, 0, lowestCalleeSavedOffset); } } @@ -627,11 +560,12 @@ void CodeGen::genSaveCalleeSavedRegistersHelp(regMaskTP regsToSaveMask, int lowe // // Arguments: // regsMask - a mask of registers for epilog generation; -// spDelta - if non-zero, the amount to add to SP after the last register restore (or together with it); +// spDelta - Always zero for LoongArch64 now. // spOffset - the offset from SP that is the beginning of the callee-saved register area; // void CodeGen::genRestoreCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta, int spOffset) { + assert(spDelta == 0); const int slotSize = genGetSlotSizeForRegsInMask(regsMask); ArrayStack regStack(compiler->getAllocator(CMK_Codegen)); @@ -640,15 +574,6 @@ void CodeGen::genRestoreCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta int stackDelta = 0; for (int i = 0; i < regStack.Height(); ++i) { - bool lastRestoreInTheGroup = (i == regStack.Height() - 1); - bool updateStackDelta = lastRestoreInTheGroup && (spDelta != 0); - if (updateStackDelta) - { - // Update stack delta only if it is the last restore (the first save). - assert(stackDelta == 0); - stackDelta = spDelta; - } - RegPair regPair = regStack.Top(i); if (regPair.reg2 != REG_NA) { @@ -670,10 +595,9 @@ void CodeGen::genRestoreCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta // in the function or funclet epilog. This exactly reverses the actions of genSaveCalleeSavedRegistersHelp(). // // Arguments: -// regsToRestoreMask - The mask of callee-saved registers to restore. If empty, this function does nothing. -// lowestCalleeSavedOffset - The offset from SP that is the beginning of the callee-saved register area. -// spDelta - If non-zero, the amount to add to SP after the register restores (must be positive or -// zero). +// regsToRestoreMask - The mask of callee-saved registers to restore. If empty, this function does nothing. +// lowestCalleeSavedOffset - The offset from SP that is the beginning of the callee-saved register area. +// spDelta - Always zero for LoongArch64 now. // // Here's an example restore sequence: // ld.d s8,sp,#xxx @@ -694,23 +618,15 @@ void CodeGen::genRestoreCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, int lowestCalleeSavedOffset, int spDelta) { - assert(spDelta >= 0); - unsigned regsToRestoreCount = genCountBits(regsToRestoreMask); - if (regsToRestoreCount == 0) + assert(spDelta == 0); + if (regsToRestoreMask == 0) { - if (spDelta != 0) - { - // Currently this is the case for varargs only - // whose size is MAX_REG_ARG * REGSIZE_BYTES = 64 bytes. - genStackPointerAdjustment(spDelta, REG_R21, nullptr, /* reportUnwindData */ true); - } return; } - assert((spDelta % 16) == 0); - - // We also can restore FP and RA, even though they are not in RBM_CALLEE_SAVED. - assert(regsToRestoreCount <= genCountBits(RBM_CALLEE_SAVED | RBM_FP | RBM_RA)); + unsigned regsToRestoreCount = genCountBits(regsToRestoreMask); + // The FP and RA are not in RBM_CALLEE_SAVED. + assert(regsToRestoreCount <= genCountBits(regMaskTP(RBM_CALLEE_SAVED))); // Point past the end, to start. We predecrement to find the offset to load from. static_assert_no_msg(REGSIZE_BYTES == FPSAVE_REGSIZE_BYTES); @@ -725,15 +641,13 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in if (maskRestoreRegsInt != RBM_NONE) { - int spIntDelta = (maskRestoreRegsFloat != RBM_NONE) ? 0 : spDelta; // should we delay the SP adjustment? - genRestoreCalleeSavedRegisterGroup(maskRestoreRegsInt, spIntDelta, spOffset); + genRestoreCalleeSavedRegisterGroup(maskRestoreRegsInt, 0, spOffset); spOffset -= genCountBits(maskRestoreRegsInt) * REGSIZE_BYTES; } if (maskRestoreRegsFloat != RBM_NONE) { - // If there is any spDelta, it must be used here. - genRestoreCalleeSavedRegisterGroup(maskRestoreRegsFloat, spDelta, spOffset); + genRestoreCalleeSavedRegisterGroup(maskRestoreRegsFloat, 0, spOffset); // No need to update spOffset since it's not used after this. } } @@ -755,7 +669,7 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * filter: a0 = non-zero if the handler should handle the exception, zero otherwise (see GT_RETFILT) * finally/fault: none * - * The LOONGARCH64 funclet prolog is the following (Note: #framesz is total funclet frame size, + * The LoongArch64 funclet prolog is the following (Note: #framesz is total funclet frame size, * including everything; #outsz is outgoing argument space. #framesz must be a multiple of 16): * * Frame type liking: @@ -771,19 +685,17 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * |-----------------------| * | incoming arguments | * +=======================+ <---- Caller's SP - * | OSR padding | // If required - * |-----------------------| - * | Varargs regs space | // Only for varargs main functions; 64 bytes + * | Varargs regs space | // Only for varargs main functions; not used for LA64. * |-----------------------| * | MonitorAcquired | // 8 bytes; for synchronized methods * |-----------------------| * | PSP slot | // 8 bytes (omitted in NativeAOT ABI) * |-----------------------| - * ~ alignment padding ~ // To make the whole frame 16 byte aligned + * |Callee saved registers | // multiple of 8 bytes, not including FP/RA * |-----------------------| * | Saved FP, RA | // 16 bytes * |-----------------------| - * |Callee saved registers | // multiple of 8 bytes, not includting FP/RA + * ~ alignment padding ~ // To make the whole frame 16 byte aligned * |-----------------------| * | Outgoing arg space | // multiple of 8 bytes; if required (i.e., #outsz != 0) * |-----------------------| <---- Ambient SP @@ -793,38 +705,22 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * V * * - * Both #1 and #2 only change SP once. That means that there will be a maximum of one alignment slot needed. For the general case, #3, - * it is possible that we will need to add alignment to both changes to SP, leading to 16 bytes of alignment. Remember that the stack - * pointer needs to be 16 byte aligned at all times. The size of the PSP slot plus callee-saved registers space is a maximum of 232 bytes: - * - * FP,RA registers - * 9 int callee-saved register s0-s8 - * 8 float callee-saved registers f24-f31 - * 8 saved integer argument registers a0-a7, if varargs function support. - * 1 PSP slot - * == 20 slots * 8 bytes = 160 bytes. - * * The outgoing argument size, however, can be very large, if we call a function that takes a large number of * arguments (note that we currently use the same outgoing argument space size in the funclet as for the main * function, even if the funclet doesn't have any calls, or has a much smaller, or larger, maximum number of - * outgoing arguments for any call). In that case, we need to 16-byte align the initial change to SP, before - * saving off the callee-saved registers and establishing the PSPsym, so we can use the limited immediate offset - * encodings we have available, before doing another 16-byte aligned SP adjustment to create the outgoing argument - * space. Both changes to SP might need to add alignment padding. + * outgoing arguments for any call). * - * In addition to the above "standard" frames, we also need to support a frame where the saved FP/RA are at the - * highest addresses. This is to match the frame layout (specifically, callee-saved registers including FP/RA - * and the PSPSym) that is used in the main function when a GS cookie is required due to the use of localloc. - * (Note that localloc cannot be used in a funclet.) In these variants, not only has the position of FP/RA - * changed, but where the alignment padding is placed has also changed. - * - * - * Note that in all cases, the PSPSym is in exactly the same position with respect to Caller-SP, and that location is the same relative to Caller-SP - * as in the main function. + * Note that in all cases, the PSPSym is in exactly the same position with respect to Caller-SP, + * and that location is the same relative to Caller-SP as in the main function where higher than + * the callee-saved registers. + * That is to say, the PSPSym's relative offset to Caller-SP is not depended on the callee-saved registers. + * TODO-LoongArch64: the funclet's callee-saved registers should not shared with main function. * * Funclets do not have varargs arguments. However, because the PSPSym must exist at the same offset from Caller-SP as in the main function, we * must add buffer space for the saved varargs/argument registers here, if the main function did the same. * + * Note that localloc cannot be used in a funclet. + * * ; After this header, fill the PSP slot, for use by the VM (it gets reported with the GC info), or by code generation of nested filters. * ; This is not part of the "OS prolog"; it has no associated unwind data, and is not reversed in the funclet epilog. * @@ -880,7 +776,9 @@ void CodeGen::genFuncletProlog(BasicBlock* block) { #ifdef DEBUG if (verbose) + { printf("*************** In genFuncletProlog()\n"); + } #endif assert(block != NULL); @@ -910,42 +808,39 @@ void CodeGen::genFuncletProlog(BasicBlock* block) maskArgRegsLiveIn = RBM_A0; } - regMaskTP maskSaveRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; - int regsSavedSize = (compiler->compCalleeRegsPushed - 2) << 3; + regMaskTP maskSaveRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; + int FP_offset = genFuncletInfo.fiSP_to_CalleeSaved_delta; - int SP_to_CalleeSaved_delta = genFuncletInfo.fiSP_to_CalleeSaved_delta; - if ((SP_to_CalleeSaved_delta + regsSavedSize + genFuncletInfo.fiCalleeSavedPadding) <= 2040) + if ((FP_offset + (genCountBits(maskSaveRegs) << 3)) <= (2040 - 16)) // no FP/RA. { - SP_to_CalleeSaved_delta += genFuncletInfo.fiCalleeSavedPadding; - genStackPointerAdjustment(frameSize, REG_R21, nullptr, /* reportUnwindData */ true); - genSaveCalleeSavedRegistersHelp(maskSaveRegs, SP_to_CalleeSaved_delta, 0); - SP_to_CalleeSaved_delta += regsSavedSize; + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, SP_to_CalleeSaved_delta); - compiler->unwindSaveReg(REG_RA, SP_to_CalleeSaved_delta); + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, SP_to_CalleeSaved_delta + 8); - compiler->unwindSaveReg(REG_FP, SP_to_CalleeSaved_delta + 8); + genSaveCalleeSavedRegistersHelp(maskSaveRegs, FP_offset + 16, 0); } else { assert(frameSize < -2040); - int SP_delta = frameSize + SP_to_CalleeSaved_delta; - genStackPointerAdjustment(SP_delta, REG_R21, nullptr, /* reportUnwindData */ true); + genStackPointerAdjustment(frameSize + (FP_offset & -16), REG_R21, nullptr, true); - genSaveCalleeSavedRegistersHelp(maskSaveRegs, genFuncletInfo.fiCalleeSavedPadding, 0); - regsSavedSize += genFuncletInfo.fiCalleeSavedPadding; + frameSize = -(FP_offset & -16); + FP_offset &= 0xf; - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, regsSavedSize); - compiler->unwindSaveReg(REG_RA, regsSavedSize); + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, regsSavedSize + 8); - compiler->unwindSaveReg(REG_FP, regsSavedSize + 8); + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - genStackPointerAdjustment(-SP_to_CalleeSaved_delta, REG_R21, nullptr, /* reportUnwindData */ true); + genSaveCalleeSavedRegistersHelp(maskSaveRegs, FP_offset + 16, 0); + + genStackPointerAdjustment(frameSize, REG_R21, nullptr, true); } // This is the end of the OS-reported prolog for purposes of unwinding @@ -1012,41 +907,28 @@ void CodeGen::genFuncletEpilog() int frameSize = genFuncletInfo.fiSpDelta; assert(frameSize < 0); - regMaskTP regsToRestoreMask = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; - int regsRestoreSize = (compiler->compCalleeRegsPushed - 2) << 3; + regMaskTP maskSaveRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; + int FP_offset = genFuncletInfo.fiSP_to_CalleeSaved_delta; - int SP_to_CalleeSaved_delta = genFuncletInfo.fiSP_to_CalleeSaved_delta; - if ((SP_to_CalleeSaved_delta + regsRestoreSize + genFuncletInfo.fiCalleeSavedPadding) <= 2040) + if ((FP_offset + (genCountBits(maskSaveRegs) << 3)) > (2040 - 16)) // no FP/RA. { - SP_to_CalleeSaved_delta += genFuncletInfo.fiCalleeSavedPadding; - genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, SP_to_CalleeSaved_delta, 0); - SP_to_CalleeSaved_delta += regsRestoreSize; - - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, SP_to_CalleeSaved_delta); - compiler->unwindSaveReg(REG_RA, SP_to_CalleeSaved_delta); + assert(frameSize < -2040); - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, SP_to_CalleeSaved_delta + 8); - compiler->unwindSaveReg(REG_FP, SP_to_CalleeSaved_delta + 8); + genStackPointerAdjustment(FP_offset & -16, REG_R21, nullptr, /* reportUnwindData */ true); - genStackPointerAdjustment(-frameSize, REG_R21, nullptr, /* reportUnwindData */ true); + frameSize += FP_offset & -16; + FP_offset = FP_offset & 0xf; } - else - { - assert(frameSize < -2040); - - genStackPointerAdjustment(SP_to_CalleeSaved_delta, REG_R21, nullptr, /* reportUnwindData */ true); - genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, genFuncletInfo.fiCalleeSavedPadding, 0); - regsRestoreSize += genFuncletInfo.fiCalleeSavedPadding; + genRestoreCalleeSavedRegistersHelp(maskSaveRegs, FP_offset + 16, 0); - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, regsRestoreSize); - compiler->unwindSaveReg(REG_RA, regsRestoreSize); + GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, regsRestoreSize + 8); - compiler->unwindSaveReg(REG_FP, regsRestoreSize + 8); + GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - genStackPointerAdjustment(-frameSize - SP_to_CalleeSaved_delta, REG_R21, nullptr, /* reportUnwindData */ true); - } + genStackPointerAdjustment(-frameSize, REG_R21, nullptr, /* reportUnwindData */ true); GetEmitter()->emitIns_R_R_I(INS_jirl, emitActualTypeSize(TYP_I_IMPL), REG_R0, REG_RA, 0); compiler->unwindReturn(REG_RA); @@ -1072,7 +954,6 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() } assert(isFramePointerUsed()); - // The frame size and offsets must be finalized assert(compiler->lvaDoneFrameLayout == Compiler::FINAL_FRAME_LAYOUT); @@ -1080,58 +961,40 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() assert((rsMaskSaveRegs & RBM_RA) != 0); assert((rsMaskSaveRegs & RBM_FP) != 0); - unsigned PSPSize = (compiler->lvaPSPSym != BAD_VAR_NUM) ? 8 : 0; - // Because a method and funclets must have the same caller-relative PSPSym offset, // if there is a PSPSym, we have to pad the funclet frame size for OSR. // - unsigned osrPad = 0; - if (compiler->opts.IsOSR() && (PSPSize > 0)) + int osrPad = 0; + if (compiler->opts.IsOSR()) { - osrPad = compiler->info.compPatchpointInfo->TotalFrameSize(); + osrPad -= compiler->info.compPatchpointInfo->TotalFrameSize(); // OSR pad must be already aligned to stack size. assert((osrPad % STACK_ALIGN) == 0); } - genFuncletInfo.fiCalleeSavedPadding = 0; - genFuncletInfo.fiFunction_CallerSP_to_FP_delta = genCallerSPtoFPdelta() - osrPad; - - unsigned regsSavedSize = genCountBits(rsMaskSaveRegs) << 3; - assert(genCountBits(rsMaskSaveRegs) == compiler->compCalleeRegsPushed); - - unsigned saveRegsPlusPSPSize = regsSavedSize + PSPSize; - - assert(compiler->lvaOutgoingArgSpaceSize % REGSIZE_BYTES == 0); - unsigned outgoingArgSpaceAligned = roundUp(compiler->lvaOutgoingArgSpaceSize, STACK_ALIGN); + /* Now save it for future use */ + genFuncletInfo.fiFunction_CallerSP_to_FP_delta = genCallerSPtoFPdelta() + osrPad; - unsigned funcletFrameSize = osrPad + saveRegsPlusPSPSize + compiler->lvaOutgoingArgSpaceSize; - unsigned funcletFrameSizeAligned = roundUp(funcletFrameSize, STACK_ALIGN); + int funcletFrameSize = compiler->lvaOutgoingArgSpaceSize; - int SP_to_CalleeSaved_delta = compiler->lvaOutgoingArgSpaceSize; - if ((SP_to_CalleeSaved_delta + regsSavedSize) >= 2040) - { - int offset = funcletFrameSizeAligned - SP_to_CalleeSaved_delta; - SP_to_CalleeSaved_delta = AlignUp((UINT)offset, STACK_ALIGN); + genFuncletInfo.fiSP_to_CalleeSaved_delta = funcletFrameSize; - genFuncletInfo.fiCalleeSavedPadding = SP_to_CalleeSaved_delta - offset; - } + funcletFrameSize += genCountBits(rsMaskSaveRegs) * REGSIZE_BYTES; - if (compiler->lvaMonAcquired != BAD_VAR_NUM && !compiler->opts.IsOSR()) + int delta_PSP = -TARGET_POINTER_SIZE; + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) { - // We furthermore allocate the "monitor acquired" bool between PSP and - // the saved registers because this is part of the EnC header. - // Note that OSR methods reuse the monitor bool created by tier 0. - osrPad += compiler->lvaLclSize(compiler->lvaMonAcquired); + delta_PSP -= TARGET_POINTER_SIZE; } - /* Now save it for future use */ - genFuncletInfo.fiSpDelta = -(int)funcletFrameSizeAligned; - genFuncletInfo.fiSaveRegs = rsMaskSaveRegs; - genFuncletInfo.fiSP_to_CalleeSaved_delta = SP_to_CalleeSaved_delta; + funcletFrameSize = funcletFrameSize - delta_PSP - osrPad; + funcletFrameSize = roundUp((unsigned)funcletFrameSize, STACK_ALIGN); - genFuncletInfo.fiSP_to_PSP_slot_delta = funcletFrameSizeAligned - osrPad - 8; - genFuncletInfo.fiCallerSP_to_PSP_slot_delta = -(int)osrPad - 8; + genFuncletInfo.fiSpDelta = -funcletFrameSize; + genFuncletInfo.fiSaveRegs = rsMaskSaveRegs; + genFuncletInfo.fiSP_to_PSP_slot_delta = funcletFrameSize + delta_PSP + osrPad; + genFuncletInfo.fiCallerSP_to_PSP_slot_delta = osrPad + delta_PSP; #ifdef DEBUG if (verbose) @@ -1641,7 +1504,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre // Make sure we use "addi.d reg, zero, 0x00" only for positive zero (0.0) // and not for negative zero (-0.0) - if (*(__int64*)&constValue == 0) + if (*(int64_t*)&constValue == 0) { // A faster/smaller way to generate 0.0 // We will just zero out the entire vector register for both float and double @@ -1650,7 +1513,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre else { // Get a temp integer register to compute long address. - // regNumber addrReg = tree->GetSingleTempReg(); + // regNumber addrReg = internalRegisters.GetSingle(tree); // We must load the FP constant from the constant pool // Emit a data section constant for the float or double constant. @@ -2099,12 +1962,12 @@ void CodeGen::genLclHeap(GenTree* tree) // since we don't need any internal registers. if (compiler->info.compInitMem) { - assert(tree->AvailableTempRegCount() == 0); + assert(internalRegisters.Count(tree) == 0); regCnt = targetReg; } else { - regCnt = tree->ExtractTempReg(); + regCnt = internalRegisters.Extract(tree); if (regCnt != targetReg) { emit->emitIns_R_R_I(INS_ori, easz, regCnt, targetReg, 0); @@ -2201,12 +2064,12 @@ void CodeGen::genLclHeap(GenTree* tree) assert(regCnt == REG_NA); if (compiler->info.compInitMem) { - assert(tree->AvailableTempRegCount() == 0); + assert(internalRegisters.Count(tree) == 0); regCnt = targetReg; } else { - regCnt = tree->ExtractTempReg(); + regCnt = internalRegisters.Extract(tree); } instGen_Set_Reg_To_Imm(((unsigned int)amount == amount) ? EA_4BYTE : EA_8BYTE, regCnt, amount); } @@ -2271,7 +2134,7 @@ void CodeGen::genLclHeap(GenTree* tree) // // Setup the regTmp - regNumber regTmp = tree->GetSingleTempReg(); + regNumber regTmp = internalRegisters.GetSingle(tree); assert(regCnt != REG_R21); emit->emitIns_R_R_R(INS_sltu, EA_PTRSIZE, REG_R21, REG_SPBASE, regCnt); @@ -2702,7 +2565,8 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) sourceIsLocal = true; } - bool dstOnStack = dstAddr->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR); + bool dstOnStack = + dstAddr->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR) || cpObjNode->GetLayout()->IsStackOnly(compiler); #ifdef DEBUG assert(!dstAddr->isContained()); @@ -2722,7 +2586,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) unsigned slots = layout->GetSlotCount(); // Temp register(s) used to perform the sequence of loads and stores. - regNumber tmpReg = cpObjNode->ExtractTempReg(); + regNumber tmpReg = internalRegisters.Extract(cpObjNode); regNumber tmpReg2 = REG_NA; assert(genIsValidIntReg(tmpReg)); @@ -2731,7 +2595,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) if (slots > 1) { - tmpReg2 = cpObjNode->GetSingleTempReg(); + tmpReg2 = internalRegisters.GetSingle(cpObjNode); assert(tmpReg2 != tmpReg); assert(genIsValidIntReg(tmpReg2)); assert(tmpReg2 != REG_WRITE_BARRIER_DST_BYREF); @@ -2866,7 +2730,7 @@ void CodeGen::genTableBasedSwitch(GenTree* treeNode) regNumber idxReg = treeNode->AsOp()->gtOp1->GetRegNum(); regNumber baseReg = treeNode->AsOp()->gtOp2->GetRegNum(); - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); // load the ip-relative offset (which is relative to start of fgFirstBB) GetEmitter()->emitIns_R_R_I(INS_slli_d, EA_8BYTE, REG_R21, idxReg, 2); @@ -3728,7 +3592,7 @@ void CodeGen::genCkfinite(GenTree* treeNode) emitAttr attr = emitActualTypeSize(treeNode); // Extract exponent into a register. - regNumber intReg = treeNode->GetSingleTempReg(); + regNumber intReg = internalRegisters.GetSingle(treeNode); regNumber fpReg = genConsumeReg(op1); emit->emitIns_R_R(attr == EA_8BYTE ? INS_movfr2gr_d : INS_movfr2gr_s, attr, intReg, fpReg); @@ -4278,9 +4142,17 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree) int CodeGenInterface::genSPtoFPdelta() const { assert(isFramePointerUsed()); - assert(compiler->compCalleeRegsPushed >= 2); + assert(compiler->compCalleeRegsPushed >= 2); // always FP/RA. - int delta = compiler->lvaOutgoingArgSpaceSize + (compiler->compCalleeRegsPushed << 3) - 8; + int delta = compiler->compLclFrameSize; + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + delta -= TARGET_POINTER_SIZE; + } + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) + { + delta -= TARGET_POINTER_SIZE; + } assert(delta >= 0); return delta; @@ -4784,7 +4656,7 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) break; case GT_JMP: - genJmpMethod(treeNode); + genJmpPlaceArgs(treeNode); break; case GT_CKFINITE: @@ -5230,7 +5102,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) // Setup loReg from the internal registers that we reserved in lower. // - regNumber loReg = treeNode->ExtractTempReg(); + regNumber loReg = internalRegisters.Extract(treeNode); regNumber addrReg = REG_NA; GenTreeLclVarCommon* varNode = nullptr; @@ -5511,7 +5383,7 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) assert(source->OperGet() == GT_BLK); assert(varTypeIsStruct(targetType)); - regNumber baseReg = treeNode->ExtractTempReg(); + regNumber baseReg = internalRegisters.Extract(treeNode); regNumber addrReg = REG_NA; GenTreeLclVarCommon* varNode = nullptr; @@ -6148,7 +6020,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode) assert(srcOffset < INT32_MAX - static_cast(size)); assert(dstOffset < INT32_MAX - static_cast(size)); - regNumber tempReg = cpBlkNode->ExtractTempReg(RBM_ALLINT); + regNumber tempReg = internalRegisters.Extract(cpBlkNode, RBM_ALLINT); if (size >= 2 * REGSIZE_BYTES) { @@ -6277,7 +6149,7 @@ void CodeGen::genCodeForInitBlkLoop(GenTreeBlk* initBlkNode) // Extend liveness of dstReg in case if it gets killed by the store. gcInfo.gcMarkRegPtrVal(dstReg, dstNode->TypeGet()); - const regNumber offsetReg = initBlkNode->GetSingleTempReg(); + const regNumber offsetReg = internalRegisters.GetSingle(initBlkNode); instGen_Set_Reg_To_Imm(EA_PTRSIZE, offsetReg, size - TARGET_POINTER_SIZE); // loop begin: @@ -6376,7 +6248,7 @@ void CodeGen::genCall(GenTreeCall* call) (call->IsVirtualStubRelativeIndir() && (call->gtEntryPoint.accessType == IAT_VALUE))); assert(call->gtControlExpr == nullptr); - regNumber tmpReg = call->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(call); // Register where we save call address in should not be overridden by epilog. assert((genRegMask(tmpReg) & (RBM_INT_CALLEE_TRASH & ~RBM_RA)) == genRegMask(tmpReg)); @@ -6384,7 +6256,7 @@ void CodeGen::genCall(GenTreeCall* call) call->IsVirtualStubRelativeIndir() ? compiler->virtualStubParamInfo->GetReg() : REG_R2R_INDIRECT_PARAM; GetEmitter()->emitIns_R_R_I(ins_Load(TYP_I_IMPL), emitActualTypeSize(TYP_I_IMPL), tmpReg, callAddrReg, 0); // We will use this again when emitting the jump in genCallInstruction in the epilog - call->gtRsvdRegs |= genRegMask(tmpReg); + internalRegisters.Add(call, genRegMask(tmpReg)); } #endif @@ -6485,22 +6357,26 @@ void CodeGen::genCallInstruction(GenTreeCall* call) emitAttr retSize = EA_PTRSIZE; emitAttr secondRetSize = EA_UNKNOWN; - if (call->HasMultiRegRetVal()) - { - retSize = emitTypeSize(pRetTypeDesc->GetReturnRegType(0)); - secondRetSize = emitTypeSize(pRetTypeDesc->GetReturnRegType(1)); - } - else + // unused values are of no interest to GC. + if (!call->IsUnusedValue()) { - assert(call->gtType != TYP_STRUCT); - - if (call->gtType == TYP_REF) + if (call->HasMultiRegRetVal()) { - retSize = EA_GCREF; + retSize = emitTypeSize(pRetTypeDesc->GetReturnRegType(0)); + secondRetSize = emitTypeSize(pRetTypeDesc->GetReturnRegType(1)); } - else if (call->gtType == TYP_BYREF) + else { - retSize = EA_BYREF; + assert(call->gtType != TYP_STRUCT); + + if (call->gtType == TYP_REF) + { + retSize = EA_GCREF; + } + else if (call->gtType == TYP_BYREF) + { + retSize = EA_BYREF; + } } } @@ -6518,7 +6394,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) #ifdef DEBUG // Pass the call signature information down into the emitter so the emitter can associate // native call sites with the signatures they were generated from. - if (call->gtCallType != CT_HELPER) + if (!call->IsHelperCall()) { sigInfo = call->callSig; } @@ -6602,7 +6478,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) if (callThroughIndirReg != REG_NA) { assert(call->IsR2ROrVirtualStubRelativeIndir()); - regNumber targetAddrReg = call->GetSingleTempReg(); + regNumber targetAddrReg = internalRegisters.GetSingle(call); // For fast tailcalls we have already loaded the call target when processing the call node. if (!call->IsFastTailCall()) { @@ -6635,7 +6511,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) else { // Generate a direct call to a non-virtual user defined or helper method - assert(call->gtCallType == CT_HELPER || call->gtCallType == CT_USER_FUNC); + assert(call->IsHelperCall() || (call->gtCallType == CT_USER_FUNC)); void* addr = nullptr; #ifdef FEATURE_READYTORUN @@ -6646,7 +6522,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) } else #endif // FEATURE_READYTORUN - if (call->gtCallType == CT_HELPER) + if (call->IsHelperCall()) { CorInfoHelpFunc helperNum = compiler->eeGetHelperNum(methHnd); noway_assert(helperNum != CORINFO_HELP_UNDEF); @@ -6678,186 +6554,13 @@ void CodeGen::genCallInstruction(GenTreeCall* call) } } -// Produce code for a GT_JMP node. -// The arguments of the caller needs to be transferred to the callee before exiting caller. -// The actual jump to callee is generated as part of caller epilog sequence. -// Therefore the codegen of GT_JMP is to ensure that the callee arguments are correctly setup. -void CodeGen::genJmpMethod(GenTree* jmp) +//------------------------------------------------------------------------ +// genJmpPlaceVarArgs: +// Generate code to place all varargs correctly for a JMP. +// +void CodeGen::genJmpPlaceVarArgs() { - assert(jmp->OperGet() == GT_JMP); - assert(compiler->compJmpOpUsed); - - // If no arguments, nothing to do - if (compiler->info.compArgsCount == 0) - { - return; - } - - // Make sure register arguments are in their initial registers - // and stack arguments are put back as well. - unsigned varNum; - LclVarDsc* varDsc; - - // First move any en-registered stack arguments back to the stack. - // At the same time any reg arg not in correct reg is moved back to its stack location. - // - // We are not strictly required to spill reg args that are not in the desired reg for a jmp call - // But that would require us to deal with circularity while moving values around. Spilling - // to stack makes the implementation simple, which is not a bad trade off given Jmp calls - // are not frequent. - for (varNum = 0; (varNum < compiler->info.compArgsCount); varNum++) - { - varDsc = compiler->lvaTable + varNum; - - if (varDsc->lvPromoted) - { - noway_assert(varDsc->lvFieldCnt == 1); // We only handle one field here - - unsigned fieldVarNum = varDsc->lvFieldLclStart; - varDsc = compiler->lvaTable + fieldVarNum; - } - noway_assert(varDsc->lvIsParam); - - if (varDsc->lvIsRegArg && (varDsc->GetRegNum() != REG_STK)) - { - // Skip reg args which are already in its right register for jmp call. - // If not, we will spill such args to their stack locations. - // - // If we need to generate a tail call profiler hook, then spill all - // arg regs to free them up for the callback. - if (!compiler->compIsProfilerHookNeeded() && (varDsc->GetRegNum() == varDsc->GetArgReg())) - { - continue; - } - } - else if (varDsc->GetRegNum() == REG_STK) - { - // Skip args which are currently living in stack. - continue; - } - - // If we came here it means either a reg argument not in the right register or - // a stack argument currently living in a register. In either case the following - // assert should hold. - assert(varDsc->GetRegNum() != REG_STK); - assert(varDsc->TypeGet() != TYP_STRUCT); - var_types storeType = varDsc->GetStackSlotHomeType(); - emitAttr storeSize = emitActualTypeSize(storeType); - - GetEmitter()->emitIns_S_R(ins_Store(storeType), storeSize, varDsc->GetRegNum(), varNum, 0); - // Update GetRegNum() life and GC info to indicate GetRegNum() is dead and varDsc stack slot is going live. - // Note that we cannot modify varDsc->GetRegNum() here because another basic block may not be expecting it. - // Therefore manually update life of varDsc->GetRegNum(). - regMaskTP tempMask = genRegMask(varDsc->GetRegNum()); - regSet.RemoveMaskVars(tempMask); - gcInfo.gcMarkRegSetNpt(tempMask); - if (compiler->lvaIsGCTracked(varDsc)) - { - VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varNum); - } - } - -#ifdef PROFILING_SUPPORTED - // At this point all arg regs are free. - // Emit tail call profiler callback. - genProfilingLeaveCallback(CORINFO_HELP_PROF_FCN_TAILCALL); -#endif - - // Next move any un-enregistered register arguments back to their register. - unsigned firstArgVarNum = BAD_VAR_NUM; // varNum of the first argument in case of a vararg method. - for (varNum = 0; (varNum < compiler->info.compArgsCount); varNum++) - { - varDsc = compiler->lvaTable + varNum; - if (varDsc->lvPromoted) - { - noway_assert(varDsc->lvFieldCnt == 1); // We only handle one field here - - unsigned fieldVarNum = varDsc->lvFieldLclStart; - varDsc = compiler->lvaTable + fieldVarNum; - } - noway_assert(varDsc->lvIsParam); - - // Skip if arg not passed in a register. - if (!varDsc->lvIsRegArg) - { - continue; - } - - // Register argument - noway_assert(isRegParamType(genActualType(varDsc->TypeGet()))); - - // Is register argument already in the right register? - // If not load it from its stack location. - regNumber argReg = varDsc->GetArgReg(); // incoming arg register - regNumber argRegNext = REG_NA; - - if (varDsc->GetRegNum() != argReg) - { - var_types loadType = TYP_UNDEF; - - // NOTE for LOONGARCH: not supports the HFA. - assert(!varDsc->lvIsHfaRegArg()); - { - if (varTypeIsStruct(varDsc)) - { - // Must be <= 16 bytes or else it wouldn't be passed in registers, - // which can be bigger (and is handled above). - noway_assert(EA_SIZE_IN_BYTES(varDsc->lvSize()) <= 16); - if (emitter::isFloatReg(argReg)) - { - loadType = varDsc->lvIs4Field1 ? TYP_FLOAT : TYP_DOUBLE; - } - else - loadType = varDsc->GetLayout()->GetGCPtrType(0); - } - else - { - loadType = compiler->mangleVarArgsType(genActualType(varDsc->TypeGet())); - } - - emitAttr loadSize = emitActualTypeSize(loadType); - GetEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, argReg, varNum, 0); - - // Update argReg life and GC Info to indicate varDsc stack slot is dead and argReg is going live. - // Note that we cannot modify varDsc->GetRegNum() here because another basic block may not be expecting - // it. - // Therefore manually update life of argReg. Note that GT_JMP marks the end of the basic block - // and after which reg life and gc info will be recomputed for the new block in genCodeForBBList(). - regSet.AddMaskVars(genRegMask(argReg)); - gcInfo.gcMarkRegPtrVal(argReg, loadType); - - if (varDsc->GetOtherArgReg() < REG_STK) - { - // Restore the second register. - argRegNext = varDsc->GetOtherArgReg(); - - if (emitter::isFloatReg(argRegNext)) - { - loadType = varDsc->lvIs4Field2 ? TYP_FLOAT : TYP_DOUBLE; - } - else - loadType = varDsc->GetLayout()->GetGCPtrType(1); - - loadSize = emitActualTypeSize(loadType); - int offs = loadSize == EA_4BYTE ? 4 : 8; - GetEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, argRegNext, varNum, offs); - - regSet.AddMaskVars(genRegMask(argRegNext)); - gcInfo.gcMarkRegPtrVal(argRegNext, loadType); - } - - if (compiler->lvaIsGCTracked(varDsc)) - { - VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); - } - } - } - - if (compiler->info.compIsVarArgs) - { - NYI_LOONGARCH64("genJmpMethod unsupports compIsVarArgs"); - } - } + NYI_LOONGARCH64("Varargs not supported"); } //------------------------------------------------------------------------ @@ -7260,7 +6963,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) } else { - regNumber tmpReg = lea->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(lea); noway_assert(tmpReg != index->GetRegNum()); noway_assert(tmpReg != memBase->GetRegNum()); @@ -7297,7 +7000,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) else { // We require a tmpReg to hold the offset - regNumber tmpReg = lea->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(lea); // First load tmpReg with the large offset constant emit->emitIns_I_la(EA_PTRSIZE, tmpReg, offset); @@ -7660,8 +7363,8 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) * ... * st.d s8,sp,off2+8*8 * - * st.d ra,sp,off3 - * st.d fp,sp,off3+8 + * st.d ra,sp,off3+8 + * st.d fp,sp,off3 * * Notes: * 1. FP is always saved, and the first store is FP, RA. @@ -7669,37 +7372,41 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) * 3. For frames with varargs, not implemented completely and not tested ! * 4. We allocate the frame here; no further changes to SP are allowed (except in the body, for localloc). * - * For functions with GS and localloc, we change the frame so the frame pointer and RA are saved at the top - * of the frame, just under the varargs registers (if any). Note that the funclet frames must follow the same - * rule, and both main frame and funclet frames (if any) must put PSPSym in the same offset from Caller-SP. + * For functions with GS and localloc, we had saved the frame pointer and RA at the top + * of the frame. Note that the funclet frames must follow the same rule, + * and both main frame and funclet frames (if any) must put PSPSym in the same offset from Caller-SP. * Since this frame type is relatively rare, we force using it via stress modes, for additional coverage. * * The frames look like the following (simplified to only include components that matter for establishing the * frames). See also Compiler::lvaAssignFrameOffsets(). * - * * The LoongArch64's frame layout is liking: * + * If we need to generate a GS cookie, we need to make sure the saved frame pointer and return address + * (FP and RA) are protected from buffer overrun by the GS cookie. + * So we always save the FP/RA along with the rest of the callee-saved registers above. + * * | | * |-----------------------| * | incoming arguments | * +=======================+ <---- Caller's SP - * | Arguments Or | // if needed. * | Varargs regs space | // Only for varargs functions; (varargs not implemented for LoongArch64) * |-----------------------| * | MonitorAcquired | // 8 bytes; for synchronized methods * |-----------------------| - * | PSP slot | // 8 bytes (omitted in NativeAOT ABI) + * | PSPSym | // 8 bytes, Only for frames with EH, (omitted in NativeAOT ABI) * |-----------------------| - * | locals, temps, etc. | + * |Callee saved registers | // not including FP/RA; multiple of 8 bytes * |-----------------------| - * | possible GS cookie | + * | Saved RA | // 8 bytes * |-----------------------| * | Saved FP | // 8 bytes * |-----------------------| - * | Saved RA | // 8 bytes + * | possible GS cookie | * |-----------------------| - * |Callee saved registers | // not including FP/RA; multiple of 8 bytes + * | locals, temps, etc. | + * |-----------------------| + * | possible GS cookie | * |-----------------------| * | Outgoing arg space | // multiple of 8 bytes; if required (i.e., #outsz != 0) * |-----------------------| <---- Ambient SP @@ -7748,6 +7455,9 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe regSet.rsMaskCalleeSaved = rsPushRegs | RBM_FPBASE | RBM_RA; #ifdef DEBUG + JITDUMP("Frame info. #outsz=%d; #framesz=%d; LclFrameSize=%d;\n", unsigned(compiler->lvaOutgoingArgSpaceSize), + genTotalFrameSize(), compiler->compLclFrameSize); + if (compiler->compCalleeRegsPushed != genCountBits(regSet.rsMaskCalleeSaved)) { printf("Error: unexpected number of callee-saved registers to push. Expected: %d. Got: %d ", @@ -7770,84 +7480,52 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe } #endif // DEBUG - // The frameType number is arbitrary, is defined below, and corresponds to one of the frame styles we - // generate based on various sizes. - int frameType = 0; - - // The amount to add from SP before starting to store the callee-saved registers. - int calleeSaveSPDelta = 0; - - // If we need to generate a GS cookie, we need to make sure the saved frame pointer and return address - // (FP and RA) are protected from buffer overrun by the GS cookie. If FP/RA are at the lowest addresses, - // then they are safe, since they are lower than any unsafe buffers. And the GS cookie we add will - // protect our caller's frame. If we have a localloc, however, that is dynamically placed lower than our - // saved FP/RA. In that case, we save FP/RA along with the rest of the callee-saved registers, above - // the GS cookie. - // - // After the frame is allocated, the frame pointer is established, pointing at the saved frame pointer to - // create a frame pointer chain. - // + int totalFrameSize = genTotalFrameSize(); + int leftFrameSize = 0; + int localFrameSize = compiler->compLclFrameSize; + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + localFrameSize -= TARGET_POINTER_SIZE; + } + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) + { + localFrameSize -= TARGET_POINTER_SIZE; + } - // This will be the starting place for saving the callee-saved registers, in increasing order. - int offset = compiler->lvaOutgoingArgSpaceSize; +#ifdef DEBUG + if (compiler->opts.disAsm) + { + printf("Frame info. #outsz=%d; #framesz=%d; lcl=%d\n", unsigned(compiler->lvaOutgoingArgSpaceSize), + genTotalFrameSize(), localFrameSize); + } +#endif - int totalFrameSize = genTotalFrameSize(); - // The (totalFrameSize <= 2040) condition ensures the offsets of st.d/ld.d. + int FP_offset = localFrameSize; if (totalFrameSize <= 2040) { GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, -totalFrameSize); compiler->unwindAllocStack(totalFrameSize); - - // Case #1. - // - // Generate: - // addi.d sp, sp, -framesz - // st.d callee_saved_registers ### not including the fp and ra. - // st.d ra,sp,outsz - // st.d fp,sp,outsz+8 - // - // After saving callee-saved registers, ra and fp, we establish the frame pointer with: - // addi.d fp, sp, (the offset of saving fp) - // We do this *after* saving callee-saved registers, so the prolog/epilog unwind codes mostly match. - - JITDUMP("Frame type 1. #outsz=%d; #framesz=%d; LclFrameSize=%d\n", unsigned(compiler->lvaOutgoingArgSpaceSize), - totalFrameSize, compiler->compLclFrameSize); - - frameType = 1; } else { - JITDUMP("Frame type 2. #outsz=%d; #framesz=%d; LclFrameSize=%d\n", unsigned(compiler->lvaOutgoingArgSpaceSize), - totalFrameSize, compiler->compLclFrameSize); - - frameType = 2; - - if ((offset + (compiler->compCalleeRegsPushed << 3)) >= 2040) - { - offset = totalFrameSize - compiler->lvaOutgoingArgSpaceSize; - calleeSaveSPDelta = AlignUp((UINT)offset, STACK_ALIGN); - offset = calleeSaveSPDelta - offset; - - genStackPointerAdjustment(-calleeSaveSPDelta, initReg, pInitRegZeroed, /* reportUnwindData */ true); - } - else + if ((localFrameSize + (compiler->compCalleeRegsPushed << 3)) > 2040) { - genStackPointerAdjustment(-totalFrameSize, initReg, pInitRegZeroed, /* reportUnwindData */ true); + leftFrameSize = localFrameSize & -16; + totalFrameSize = totalFrameSize - (localFrameSize & -16); + FP_offset = localFrameSize & 0xf; } + genStackPointerAdjustment(-totalFrameSize, initReg, pInitRegZeroed, /* reportUnwindData */ true); } + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - JITDUMP(" offset=%d, calleeSaveSPDelta=%d\n", offset, calleeSaveSPDelta); - genSaveCalleeSavedRegistersHelp(rsPushRegs, offset, 0); - offset += (int)(genCountBits(rsPushRegs) << 3); + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, offset); - compiler->unwindSaveReg(REG_RA, offset); + genSaveCalleeSavedRegistersHelp(rsPushRegs, FP_offset + 16, 0); - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, offset + 8); - compiler->unwindSaveReg(REG_FP, offset + 8); - - JITDUMP(" offsetSpToSavedFp=%d\n", offset + 8); - genEstablishFramePointer(offset + 8, /* reportUnwindData */ true); + JITDUMP(" offsetSpToSavedFp=%d\n", FP_offset); + genEstablishFramePointer(FP_offset, /* reportUnwindData */ true); // For varargs, home the incoming arg registers last. Note that there is nothing to unwind here, // so we just report "NOP" unwind codes. If there's no more frame setup after this, we don't @@ -7858,19 +7536,9 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe NYI_LOONGARCH64("genPushCalleeSavedRegisters unsupports compIsVarArgs"); } -#ifdef DEBUG - if (compiler->opts.disAsm) + if (leftFrameSize != 0) { - assert(frameType != 0); - printf("DEBUG: LOONGARCH64, frameType:%d\n\n", frameType); - } -#endif - - if (calleeSaveSPDelta != 0) - { - assert(frameType == 2); - calleeSaveSPDelta = totalFrameSize - calleeSaveSPDelta; - genStackPointerAdjustment(-calleeSaveSPDelta, initReg, pInitRegZeroed, /* reportUnwindData */ true); + genStackPointerAdjustment(-leftFrameSize, initReg, pInitRegZeroed, /* reportUnwindData */ true); } } @@ -7882,85 +7550,78 @@ void CodeGen::genPopCalleeSavedRegisters(bool jmpEpilog) assert(isFramePointerUsed()); - // This will be the starting place for restoring the callee-saved registers, in decreasing order. - int calleeSaveSPOffset = 0; - int remainingSPSize = 0; - int totalFrameSize = genTotalFrameSize(); - if (totalFrameSize <= 2040) + int localFrameSize = compiler->compLclFrameSize; + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + localFrameSize -= TARGET_POINTER_SIZE; + } + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) { - JITDUMP("Frame type 1. #outsz=%d; #framesz=%d; localloc? %s\n", unsigned(compiler->lvaOutgoingArgSpaceSize), - totalFrameSize, dspBool(compiler->compLocallocUsed)); + localFrameSize -= TARGET_POINTER_SIZE; + } + JITDUMP("Frame type. #outsz=%d; #framesz=%d; #calleeSaveRegsPushed:%d; " + "localloc? %s\n", + unsigned(compiler->lvaOutgoingArgSpaceSize), totalFrameSize, compiler->compCalleeRegsPushed, + dspBool(compiler->compLocallocUsed)); + + emitter* emit = GetEmitter(); + int FP_offset = localFrameSize; + int remainingSPSize = totalFrameSize; + if (totalFrameSize <= 2040) + { if (compiler->compLocallocUsed) { - int SPtoFPdelta = (compiler->compCalleeRegsPushed << 3) - 8 + compiler->lvaOutgoingArgSpaceSize; - + int SPtoFPdelta = genSPtoFPdelta(); // Restore sp from fp - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); + emit->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); compiler->unwindSetFrameReg(REG_FPBASE, SPtoFPdelta); } - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize; - remainingSPSize = totalFrameSize; } else { - JITDUMP("Frame type 2. #outsz=%d; #framesz=%d; #calleeSaveRegsPushed:%d; " - "localloc? %s\n", - unsigned(compiler->lvaOutgoingArgSpaceSize), totalFrameSize, compiler->compCalleeRegsPushed, - dspBool(compiler->compLocallocUsed)); - - if ((compiler->lvaOutgoingArgSpaceSize + (compiler->compCalleeRegsPushed << 3)) > 2047) + if (compiler->compLocallocUsed) { - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize & -16; - if (compiler->compLocallocUsed) + int SPtoFPdelta = genSPtoFPdelta(); + // Restore sp from fp + if (emitter::isValidSimm12(SPtoFPdelta)) { - int SPtoFPdelta = (compiler->compCalleeRegsPushed << 3) - 8; - - // Restore sp from fp - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); - compiler->unwindSetFrameReg(REG_FPBASE, SPtoFPdelta); + emit->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); } else { - genStackPointerAdjustment(calleeSaveSPOffset, REG_RA, nullptr, /* reportUnwindData */ true); + emit->emitIns_I_la(EA_PTRSIZE, REG_RA, SPtoFPdelta); + emit->emitIns_R_R_R(INS_sub_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, REG_RA); } - remainingSPSize = totalFrameSize - calleeSaveSPOffset; - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize - calleeSaveSPOffset; } - else + if ((localFrameSize + (compiler->compCalleeRegsPushed << 3)) > 2040) { - if (compiler->compLocallocUsed) - { - int SPtoFPdelta = (compiler->compCalleeRegsPushed << 3) - 8 + compiler->lvaOutgoingArgSpaceSize; + remainingSPSize = localFrameSize & -16; + genStackPointerAdjustment(remainingSPSize, REG_RA, nullptr, /* reportUnwindData */ true); - // Restore sp from fp - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); - compiler->unwindSetFrameReg(REG_FPBASE, SPtoFPdelta); - } - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize; - remainingSPSize = totalFrameSize; + remainingSPSize = totalFrameSize - remainingSPSize; + FP_offset = localFrameSize & 0xf; } } - JITDUMP(" calleeSaveSPOffset=%d\n", calleeSaveSPOffset); - genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, calleeSaveSPOffset, 0); - calleeSaveSPOffset += (compiler->compCalleeRegsPushed - 2) << 3; + JITDUMP(" calleeSaveSPOffset=%d\n", FP_offset + 16); + genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, FP_offset + 16, 0); - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, calleeSaveSPOffset); - compiler->unwindSaveReg(REG_RA, calleeSaveSPOffset); + emit->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, calleeSaveSPOffset + 8); - compiler->unwindSaveReg(REG_FP, calleeSaveSPOffset + 8); + emit->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); if (emitter::isValidUimm11(remainingSPSize)) { - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, remainingSPSize); + emit->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, remainingSPSize); } else { - GetEmitter()->emitIns_I_la(EA_PTRSIZE, REG_R21, remainingSPSize); - GetEmitter()->emitIns_R_R_R(INS_add_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, REG_R21); + emit->emitIns_I_la(EA_PTRSIZE, REG_R21, remainingSPSize); + emit->emitIns_R_R_R(INS_add_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, REG_R21); } compiler->unwindAllocStack(remainingSPSize); @@ -7972,555 +7633,17 @@ void CodeGen::genPopCalleeSavedRegisters(bool jmpEpilog) if (emitter::isValidUimm11(tier0FrameSize)) { - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, tier0FrameSize); + emit->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, tier0FrameSize); } else { - GetEmitter()->emitIns_I_la(EA_PTRSIZE, REG_R21, tier0FrameSize); - GetEmitter()->emitIns_R_R_R(INS_add_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, REG_R21); + emit->emitIns_I_la(EA_PTRSIZE, REG_R21, tier0FrameSize); + emit->emitIns_R_R_R(INS_add_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, REG_R21); } compiler->unwindAllocStack(tier0FrameSize); } } -void CodeGen::genFnPrologCalleeRegArgs() -{ - assert(!(intRegState.rsCalleeRegArgMaskLiveIn & floatRegState.rsCalleeRegArgMaskLiveIn)); - - regMaskTP regArgMaskLive = intRegState.rsCalleeRegArgMaskLiveIn | floatRegState.rsCalleeRegArgMaskLiveIn; - -#ifdef DEBUG - if (verbose) - { - printf("*************** In genFnPrologCalleeRegArgs() LOONGARCH64:0x%llx.\n", regArgMaskLive); - } -#endif - - // We should be generating the prolog block when we are called - assert(compiler->compGeneratingProlog); - - // We expect to have some registers of the type we are doing, that are LiveIn, otherwise we don't need to be called. - noway_assert(regArgMaskLive != 0); - - unsigned varNum; - unsigned regArgMaskIsInt = 0; - int regArgNum = 0; - // Process any circular dependencies - unsigned regArg[MAX_REG_ARG * 2] = {0}; - unsigned regArgInit[MAX_REG_ARG * 2] = {0}; - for (varNum = 0; varNum < compiler->lvaCount; ++varNum) - { - LclVarDsc* varDsc = compiler->lvaTable + varNum; - - // Is this variable a register arg? - if (!varDsc->lvIsParam) - { - continue; - } - - if (!varDsc->lvIsRegArg) - { - continue; - } - - if (varDsc->lvIsInReg()) - { - assert(genIsValidIntReg(varDsc->GetArgReg()) || genIsValidFloatReg(varDsc->GetArgReg())); - assert(!(genIsValidIntReg(varDsc->GetOtherArgReg()) || genIsValidFloatReg(varDsc->GetOtherArgReg()))); - if (varDsc->GetArgInitReg() != varDsc->GetArgReg()) - { - if (genIsValidIntReg(varDsc->GetArgInitReg())) - { - if (varDsc->GetArgInitReg() > REG_ARG_LAST) - { - bool isSkip; - instruction ins; - emitAttr size; - if (genIsValidIntReg(varDsc->GetArgReg())) - { - ins = INS_mov; - if (varDsc->TypeGet() == TYP_INT) - { - size = EA_4BYTE; - isSkip = false; - } - else - { - size = EA_PTRSIZE; - isSkip = true; - } - } - else - { - ins = INS_movfr2gr_d; - size = EA_PTRSIZE; - isSkip = true; - } - GetEmitter()->emitIns_Mov(ins, size, varDsc->GetArgInitReg(), varDsc->GetArgReg(), isSkip); - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - } - else - { - if (genIsValidIntReg(varDsc->GetArgReg())) - { - assert(varDsc->GetArgReg() >= REG_ARG_FIRST); - regArg[varDsc->GetArgReg() - REG_ARG_FIRST] = varDsc->GetArgReg(); - regArgInit[varDsc->GetArgReg() - REG_ARG_FIRST] = varDsc->GetArgInitReg(); - if (varDsc->TypeGet() == TYP_INT) - { - regArgMaskIsInt = 1 << (unsigned)varDsc->GetArgReg(); - } - } - else - { - assert(genIsValidFloatReg(varDsc->GetArgReg())); - regArg[(varDsc->GetArgReg() & 7) | 0x8] = varDsc->GetArgReg(); - regArgInit[(varDsc->GetArgReg() & 7) | 0x8] = varDsc->GetArgInitReg(); - } - regArgNum++; - } - } - else - { - assert(genIsValidFloatReg(varDsc->GetArgInitReg())); - if (genIsValidIntReg(varDsc->GetArgReg())) - { - GetEmitter()->emitIns_Mov(INS_movgr2fr_d, EA_PTRSIZE, varDsc->GetArgInitReg(), - varDsc->GetArgReg(), false); - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - } - else if (varDsc->GetArgInitReg() > REG_ARG_FP_LAST) - { - GetEmitter()->emitIns_Mov(INS_fmov_d, EA_PTRSIZE, varDsc->GetArgInitReg(), varDsc->GetArgReg(), - true); - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - } - else - { - assert(genIsValidFloatReg(varDsc->GetArgReg())); - regArg[(varDsc->GetArgReg() & 7) | 0x8] = varDsc->GetArgReg(); - regArgInit[(varDsc->GetArgReg() & 7) | 0x8] = varDsc->GetArgInitReg(); - regArgNum++; - } - } - } - else - { - // TODO for LoongArch64: should delete this by optimization "struct {long a; int32_t b;};" - // liking AMD64_ABI within morph. - if (genIsValidIntReg(varDsc->GetArgReg()) && (varDsc->TypeGet() == TYP_INT)) - { - GetEmitter()->emitIns_Mov(INS_mov, EA_4BYTE, varDsc->GetArgInitReg(), varDsc->GetArgReg(), false); - } - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - } -#ifdef USING_SCOPE_INFO - psiMoveToReg(varNum); -#endif // USING_SCOPE_INFO - if (!varDsc->lvLiveInOutOfHndlr) - { - continue; - } - } - - // When we have a promoted struct we have two possible LclVars that can represent the incoming argument - // in the regArgTab[], either the original TYP_STRUCT argument or the introduced lvStructField. - // We will use the lvStructField if we have a TYPE_INDEPENDENT promoted struct field otherwise - // use the original TYP_STRUCT argument. - // - if (varDsc->lvPromoted || varDsc->lvIsStructField) - { - LclVarDsc* parentVarDsc = varDsc; - if (varDsc->lvIsStructField) - { - assert(!varDsc->lvPromoted); - parentVarDsc = &compiler->lvaTable[varDsc->lvParentLcl]; - } - - Compiler::lvaPromotionType promotionType = compiler->lvaGetPromotionType(parentVarDsc); - - if (promotionType == Compiler::PROMOTION_TYPE_INDEPENDENT) - { - // For register arguments that are independent promoted structs we put the promoted field varNum - // in the regArgTab[] - if (varDsc->lvPromoted) - { - continue; - } - } - else - { - // For register arguments that are not independent promoted structs we put the parent struct varNum - // in the regArgTab[] - if (varDsc->lvIsStructField) - { - continue; - } - } - } - - var_types storeType = TYP_UNDEF; - int slotSize = TARGET_POINTER_SIZE; - - if (varTypeIsStruct(varDsc)) - { - if (emitter::isFloatReg(varDsc->GetArgReg())) - { - storeType = varDsc->lvIs4Field1 ? TYP_FLOAT : TYP_DOUBLE; - } - else - { - assert(emitter::isGeneralRegister(varDsc->GetArgReg())); - if (varDsc->lvIs4Field1) - { - storeType = TYP_INT; - } - else - { - storeType = varDsc->GetLayout()->GetGCPtrType(0); - } - } - slotSize = (int)EA_SIZE(emitActualTypeSize(storeType)); - -#if FEATURE_MULTIREG_ARGS - // Must be <= MAX_PASS_MULTIREG_BYTES or else it wouldn't be passed in registers - noway_assert(varDsc->lvSize() <= MAX_PASS_MULTIREG_BYTES); -#endif - } - else // Not a struct type - { - storeType = compiler->mangleVarArgsType(genActualType(varDsc->TypeGet())); - if (emitter::isFloatReg(varDsc->GetArgReg()) != varTypeIsFloating(storeType)) - { - assert(varTypeIsFloating(storeType)); - storeType = storeType == TYP_DOUBLE ? TYP_I_IMPL : TYP_INT; - } - } - emitAttr size = emitActualTypeSize(storeType); - - regNumber srcRegNum = varDsc->GetArgReg(); - - // Stack argument - if the ref count is 0 don't care about it - if (!varDsc->lvOnFrame) - { - noway_assert(varDsc->lvRefCnt() == 0); - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - if (varDsc->GetOtherArgReg() < REG_STK) - { - regArgMaskLive &= ~genRegMask(varDsc->GetOtherArgReg()); - } - } - else - { - assert(srcRegNum != varDsc->GetOtherArgReg()); - - regNumber tmp_reg = REG_NA; - - bool FPbased; - int baseOffset = compiler->lvaFrameAddress(varNum, &FPbased); - - // First store the `varDsc->GetArgReg()` on stack. - if (emitter::isValidSimm12(baseOffset)) - { - GetEmitter()->emitIns_S_R(ins_Store(storeType), size, srcRegNum, varNum, 0); - } - else - { - assert(tmp_reg == REG_NA); - - tmp_reg = REG_R21; - GetEmitter()->emitIns_I_la(EA_PTRSIZE, REG_R21, baseOffset); - // The last parameter `int offs` of the `emitIns_S_R` is negtive, - // it means the offset imm had been stored within the `REG_R21`. - GetEmitter()->emitIns_S_R(ins_Store(storeType, true), size, srcRegNum, varNum, -8); - } - - regArgMaskLive &= ~genRegMask(srcRegNum); - - // Then check if varDsc is a struct arg - if (varTypeIsStruct(varDsc)) - { - if (emitter::isFloatReg(varDsc->GetOtherArgReg())) - { - srcRegNum = varDsc->GetOtherArgReg(); - storeType = varDsc->lvIs4Field2 ? TYP_FLOAT : TYP_DOUBLE; - size = EA_SIZE(emitActualTypeSize(storeType)); - - slotSize = slotSize < (int)size ? (int)size : slotSize; - } - else if (emitter::isGeneralRegister(varDsc->GetOtherArgReg())) - { - if (varDsc->lvIs4Field2) - { - storeType = TYP_INT; - } - else - { - storeType = varDsc->GetLayout()->GetGCPtrType(1); - } - - srcRegNum = varDsc->GetOtherArgReg(); - size = emitActualTypeSize(storeType); - - slotSize = slotSize < (int)EA_SIZE(size) ? (int)EA_SIZE(size) : slotSize; - } - baseOffset += slotSize; - - // if the struct passed by two register, then store the second register `varDsc->GetOtherArgReg()`. - if (srcRegNum == varDsc->GetOtherArgReg()) - { - if (emitter::isValidSimm12(baseOffset)) - { - GetEmitter()->emitIns_S_R(ins_Store(storeType), size, srcRegNum, varNum, slotSize); - } - else - { - if (tmp_reg == REG_NA) - { - GetEmitter()->emitIns_I_la(EA_PTRSIZE, REG_R21, baseOffset); - // The last parameter `int offs` of the `emitIns_S_R` is negtive, - // it means the offset imm had been stored within the `REG_R21`. - GetEmitter()->emitIns_S_R(ins_Store(storeType, true), size, srcRegNum, varNum, - -slotSize - 8); - } - else - { - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_R21, REG_R21, slotSize); - GetEmitter()->emitIns_S_R(ins_Store(storeType, true), size, srcRegNum, varNum, - -slotSize - 8); - } - } - regArgMaskLive &= ~genRegMask(srcRegNum); // maybe do this later is better! - } - else if (varDsc->lvIsSplit) - { - // the struct is a split struct. - assert(varDsc->GetArgReg() == REG_ARG_LAST && varDsc->GetOtherArgReg() == REG_STK); - - // For the LA's ABI, the split struct arg will be passed via `A7` and a stack slot on caller. - // But if the `A7` is stored on stack on the callee side, the whole split struct should be - // stored continuous on the stack on the callee side. - // So, after we save `A7` on the stack in prolog, it has to copy the stack slot of the split struct - // which was passed by the caller. Here we load the stack slot to `REG_SCRATCH`, and save it - // on the stack following the `A7` in prolog. - if (emitter::isValidSimm12(genTotalFrameSize())) - { - GetEmitter()->emitIns_R_R_I(INS_ld_d, size, REG_SCRATCH, REG_SPBASE, genTotalFrameSize()); - } - else - { - assert(!EA_IS_RELOC(size)); - GetEmitter()->emitIns_I_la(size, REG_SCRATCH, genTotalFrameSize()); - GetEmitter()->emitIns_R_R_R(INS_ldx_d, size, REG_SCRATCH, REG_SPBASE, REG_SCRATCH); - } - - if (emitter::isValidSimm12(baseOffset)) - { - GetEmitter()->emitIns_S_R(INS_st_d, size, REG_SCRATCH, varNum, TARGET_POINTER_SIZE); - } - else - { - if (tmp_reg == REG_NA) - { - GetEmitter()->emitIns_I_la(EA_PTRSIZE, REG_R21, baseOffset); - // The last parameter `int offs` of the `emitIns_S_R` is negtive, - // it means the offset imm had been stored within the `REG_R21`. - GetEmitter()->emitIns_S_R(INS_stx_d, size, REG_SCRATCH, varNum, -8); - } - else - { - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_R21, REG_R21, TARGET_POINTER_SIZE); - GetEmitter()->emitIns_S_R(INS_stx_d, size, REG_SCRATCH, varNum, -slotSize - 8); - } - } - } - } - -#ifdef USING_SCOPE_INFO - { - psiMoveToStack(varNum); - } -#endif // USING_SCOPE_INFO - } - } - - if (regArgNum > 0) - { - instruction ins; - for (int i = MAX_REG_ARG - 1; i >= 0; i--) - { - if (regArg[i] > 0) - { - assert(genIsValidIntReg((regNumber)regArg[i])); - assert(genIsValidIntReg((regNumber)regArgInit[i])); - - unsigned tmpRegs[MAX_REG_ARG] = {0}; - - unsigned tmpArg = regArg[i]; - unsigned nextReg = regArgInit[i] - REG_ARG_FIRST; - - assert(tmpArg <= REG_ARG_LAST); - assert(nextReg < MAX_REG_ARG); - assert(nextReg != (unsigned)i); - - regArg[i] = 0; - int count = 0; - - while (regArg[nextReg] != 0) - { - tmpRegs[count] = nextReg; - nextReg = regArgInit[nextReg] - REG_ARG_FIRST; - assert(nextReg < MAX_REG_ARG); - - for (int count2 = 0; count2 < count; count2++) - { - if (nextReg == tmpRegs[count2]) - { - NYI_LOONGARCH64("-----------CodeGen::genFnPrologCalleeRegArgs() error: intRegs!"); - } - } - - count++; - } - - if (nextReg == (unsigned)i) - { - GetEmitter()->emitIns_R_R_I(INS_ori, EA_PTRSIZE, REG_R21, (regNumber)tmpArg, 0); - regArgMaskLive &= ~genRegMask((regNumber)tmpArg); - assert(count > 0); - } - else if (count == 0) - { - tmpRegs[0] = (unsigned)i; - regArg[i] = tmpArg; - } - else - { - count--; - } - - do - { - tmpArg = tmpRegs[count]; - - instruction ins = (regArgMaskIsInt & (1 << regArg[tmpArg])) != 0 ? INS_slli_w : INS_ori; - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, (regNumber)regArgInit[tmpArg], - (regNumber)regArg[tmpArg], 0); - - regArgMaskLive &= ~genRegMask((regNumber)regArg[tmpArg]); - regArg[tmpArg] = 0; - count--; - regArgNum--; - assert(regArgNum >= 0); - } while (count >= 0); - - if (nextReg == (unsigned)i) - { - instruction ins = (regArgMaskIsInt & (1 << regArg[i])) != 0 ? INS_slli_w : INS_ori; - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, (regNumber)regArgInit[i], REG_R21, 0); - regArgNum--; - assert(regArgNum >= 0); - } - else if (tmpRegs[0] != (unsigned)i) - { - instruction ins = (regArgMaskIsInt & (1 << (i + REG_ARG_FIRST))) != 0 ? INS_slli_w : INS_ori; - GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, (regNumber)regArgInit[i], - (regNumber)(i + REG_ARG_FIRST), 0); - - regArgMaskLive &= ~genRegMask((regNumber)(i + REG_ARG_FIRST)); - regArgNum--; - } - assert(regArgNum >= 0); - } - } - - if (regArgNum > 0) - { - for (int i = MAX_REG_ARG + MAX_FLOAT_REG_ARG - 1; i >= MAX_REG_ARG; i--) - { - if (regArg[i] > 0) - { - assert(genIsValidFloatReg((regNumber)regArg[i])); - - instruction ins = genIsValidIntReg((regNumber)regArgInit[i]) ? INS_movfr2gr_d : INS_fmov_d; - - regArgNum--; - regArgMaskLive &= ~genRegMask((regNumber)regArg[i]); - if (regArgNum == 0) - { - GetEmitter()->emitIns_Mov(ins, EA_PTRSIZE, (regNumber)regArgInit[i], (regNumber)regArg[i], - true); - break; - } - else if (regArgInit[i] > regArg[i]) - { - GetEmitter()->emitIns_R_R(INS_fmov_d, EA_PTRSIZE, (regNumber)regArgInit[i], - (regNumber)regArg[i]); - } - else - { - assert(i > MAX_REG_ARG); - assert(regArgNum > 0); - - int j = genIsValidIntReg((regNumber)regArgInit[i]) ? (regArgInit[i] - REG_ARG_FIRST) - : ((regArgInit[i] & 0x7) | 0x8); - if (regArg[j] == 0) - { - GetEmitter()->emitIns_Mov(ins, EA_PTRSIZE, (regNumber)regArgInit[i], (regNumber)regArg[i], - true); - } - else - { - // NOTE: Not support the int-register case. - assert(genIsValidFloatReg((regNumber)regArg[j])); - assert(genIsValidFloatReg((regNumber)regArgInit[j])); - - int k = (regArgInit[j] & 0x7) | 0x8; - if ((regArg[k] == 0) || (k > i)) - { - GetEmitter()->emitIns_R_R(INS_fmov_d, EA_PTRSIZE, (regNumber)regArgInit[j], - (regNumber)regArg[j]); - GetEmitter()->emitIns_R_R(INS_fmov_d, EA_PTRSIZE, (regNumber)regArgInit[i], - (regNumber)regArg[i]); - regArgNum--; - regArgMaskLive &= ~genRegMask((regNumber)regArg[j]); - regArg[j] = 0; - if (regArgNum == 0) - { - break; - } - } - else if (k == i) - { - GetEmitter()->emitIns_R_R(INS_fmov_d, EA_PTRSIZE, REG_SCRATCH_FLT, - (regNumber)regArg[i]); - GetEmitter()->emitIns_R_R(INS_fmov_d, EA_PTRSIZE, (regNumber)regArgInit[j], - (regNumber)regArg[j]); - GetEmitter()->emitIns_R_R(INS_fmov_d, EA_PTRSIZE, (regNumber)regArgInit[i], - REG_SCRATCH_FLT); - regArgNum--; - regArgMaskLive &= ~genRegMask((regNumber)regArg[j]); - regArg[j] = 0; - if (regArgNum == 0) - { - break; - } - } - else - { - NYI_LOONGARCH64("-----------CodeGen::genFnPrologCalleeRegArgs() error!--"); - } - } - } - } - } - } - assert(regArgNum == 0); - } - - assert(!regArgMaskLive); -} - #ifdef PROFILING_SUPPORTED //----------------------------------------------------------------------------------- // genProfilingEnterCallback: Generate the profiling function enter callback. diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index 0df6f56c5b76..e4e2ede54b37 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -607,7 +607,7 @@ void CodeGen::genSaveCalleeSavedRegistersHelp(regMaskTP regsToSaveMask, int lowe assert((spDelta % STACK_ALIGN) == 0); - assert(regsToSaveCount <= genCountBits(RBM_CALLEE_SAVED)); + assert(regsToSaveCount <= genCountBits(regMaskTP(RBM_CALLEE_SAVED))); // Save integer registers at higher addresses than floating-point registers. regMaskTP maskSaveRegsFloat = regsToSaveMask & RBM_ALLFLOAT; @@ -718,7 +718,7 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in assert((spDelta % STACK_ALIGN) == 0); // We also can restore FP and RA, even though they are not in RBM_CALLEE_SAVED. - assert(regsToRestoreCount <= genCountBits(RBM_CALLEE_SAVED | RBM_FP | RBM_RA)); + assert(regsToRestoreCount <= genCountBits(regMaskTP(RBM_CALLEE_SAVED | RBM_FP | RBM_RA))); // Point past the end, to start. We predecrement to find the offset to load from. static_assert_no_msg(REGSIZE_BYTES == FPSAVE_REGSIZE_BYTES); @@ -770,8 +770,8 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * addi sp, sp, -#framesz ; establish the frame * sd s1, #outsz(sp) ; save callee-saved registers, as necessary * sd s2, #(outsz+8)(sp) - * sd ra, #(outsz+?)(sp) ; save RA (8 bytes) - * sd fp, #(outsz+?+8)(sp) ; save FP (8 bytes) + * sd ra, #(outsz+?+8)(sp) ; save RA (8 bytes) + * sd fp, #(outsz+?)(sp) ; save FP (8 bytes) * * The funclet frame layout: * @@ -779,8 +779,7 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * |-----------------------| * | incoming arguments | * +=======================+ <---- Caller's SP - * | Arguments Or | // if needed - * | Varargs regs space | // Only for varargs functions; NYI on RV64 + * | Varargs regs space | // Only for varargs main functions; not used for RV64. * |-----------------------| * | MonitorAcquired | // 8 bytes; for synchronized methods * |-----------------------| @@ -788,11 +787,9 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * |-----------------------| * ~ alignment padding ~ // To make the whole frame 16 byte aligned * |-----------------------| - * | Saved FP | // 8 bytes - * |-----------------------| - * | Saved RA | // 8 bytes + * |Callee saved registers | // multiple of 8 bytes, not including FP/RA * |-----------------------| - * |Callee saved registers | // multiple of 8 bytes, not includting RA/FP + * | Saved FP, RA | // 16 bytes * |-----------------------| * | Outgoing arg space | // multiple of 8 bytes; if required (i.e., #outsz != 0) * |-----------------------| <---- Ambient SP @@ -801,31 +798,27 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * | | downward | * V * - * Note, that SP only change once. That means, there will be a maximum of one alignment slot needed. - * Also remember, the stack oiubter needs to be 16 byte aligned at all times. - * The size of the PSP slot plus callee-saved registers space is a maximum of 280 bytes: - * - * RA,FP registers - * 11 int callee-saved register s1-s11 - * 12 float callee-saved registers f8-f9, f18-f27 - * 8 saved integer argument registers a0-a7, if varargs function support. - * 1 PSP slot - * 1 alignment slot or monitor acquired slot - * == 35 slots * 8 bytes = 280 bytes. * * The outgoing argument size, however, can be very large, if we call a function that takes a large number of * arguments (note that we currently use the same outgoing argument space size in the funclet as for the main * function, even if the funclet doesn't have any calls, or has a much smaller, or larger, maximum number of - * outgoing arguments for any call). In that case, we need to 16-byte align the initial change to SP, before - * saving off the callee-saved registers and establishing the PSPsym, so we can use the limited immediate offset - * encodings we have available, before doing another 16-byte aligned SP adjustment to create the outgoing argument - * space. Both changes to SP might need to add alignment padding. + * outgoing arguments for any call). + * + * Note that in all cases, the PSPSym is in exactly the same position with respect to Caller-SP, + * and that location is the same relative to Caller-SP as in the main function where higher than + * the callee-saved registers. + * That is to say, the PSPSym's relative offset to Caller-SP is not depended on the callee-saved registers. + * + * Funclets do not have varargs arguments. However, because the PSPSym must exist at the same offset from Caller-SP as in the main function, we + * must add buffer space for the saved varargs/argument registers here, if the main function did the same. + * + * Note that localloc cannot be used in a funclet. * * An example epilog sequence: * addi sp, sp, #outsz ; if any outgoing argument space * ld s1, #(xxx-8)(sp) ; restore callee-saved registers * ld s2, #xxx(sp) - * ld ra, #(xxx+?-8)(sp) ; restore RA + * ld ra, #(xxx+?+8)(sp) ; restore RA * ld fp, #(xxx+?)(sp) ; restore FP * addi sp, sp, #framesz * jarl zero, ra @@ -840,8 +833,8 @@ void CodeGen::genFuncletProlog(BasicBlock* block) printf("*************** In genFuncletProlog()\n"); } #endif + // TODO-RISCV64: Implement varargs (NYI_RISCV64) - // TODO-RISCV64-CQ: We can use C extension for optimization assert(block != NULL); assert(block->HasFlag(BBF_FUNCLET_BEG)); @@ -852,9 +845,8 @@ void CodeGen::genFuncletProlog(BasicBlock* block) compiler->unwindBegProlog(); - const bool isFilter = (block->bbCatchTyp == BBCT_FILTER); - const int frameSize = genFuncletInfo.fiSpDelta; - + bool isFilter = (block->bbCatchTyp == BBCT_FILTER); + int frameSize = genFuncletInfo.fiSpDelta; assert(frameSize < 0); regMaskTP maskArgRegsLiveIn; @@ -871,53 +863,39 @@ void CodeGen::genFuncletProlog(BasicBlock* block) maskArgRegsLiveIn = RBM_A0; } - regMaskTP maskSaveRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; - int regsSavedSize = (compiler->compCalleeRegsPushed - 2) << 3; - - int calleeSavedDelta = genFuncletInfo.fiSP_to_CalleeSaved_delta; + regMaskTP maskSaveRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; + int FP_offset = genFuncletInfo.fiSP_to_CalleeSaved_delta; - emitter* emit = GetEmitter(); - - if (calleeSavedDelta + regsSavedSize + genFuncletInfo.fiCalleeSavedPadding <= 2040) + if ((FP_offset + (genCountBits(maskSaveRegs) << 3)) <= (2040 - 16)) // no FP/RA. { - calleeSavedDelta += genFuncletInfo.fiCalleeSavedPadding; - - // addi sp, sp, #frameSize genStackPointerAdjustment(frameSize, REG_SCRATCH, nullptr, /* reportUnwindData */ true); - genSaveCalleeSavedRegistersHelp(maskSaveRegs, calleeSavedDelta, 0); - calleeSavedDelta += regsSavedSize; + GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - // sd ra, #calleeSavedDelta(sp) - emit->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_RA, REG_SPBASE, calleeSavedDelta); - compiler->unwindSaveReg(REG_RA, calleeSavedDelta); + GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - // sd fp, #(calleeSavedDelta+8)(sp) - emit->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_FP, REG_SPBASE, calleeSavedDelta + 8); - compiler->unwindSaveReg(REG_FP, calleeSavedDelta + 8); + genSaveCalleeSavedRegistersHelp(maskSaveRegs, FP_offset + 16, 0); } else { assert(frameSize < -2040); - int spDelta = frameSize + calleeSavedDelta; + genStackPointerAdjustment(frameSize + (FP_offset & -16), REG_SCRATCH, nullptr, true); - // addi sp, sp, #spDelta - genStackPointerAdjustment(spDelta, REG_SCRATCH, nullptr, /* reportUnwindData */ true); + frameSize = -(FP_offset & -16); + FP_offset &= 0xf; - genSaveCalleeSavedRegistersHelp(maskSaveRegs, genFuncletInfo.fiCalleeSavedPadding, 0); - regsSavedSize += genFuncletInfo.fiCalleeSavedPadding; + GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - // sd ra, #regsSavedSize(sp) - emit->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_RA, REG_SPBASE, regsSavedSize); - compiler->unwindSaveReg(REG_RA, regsSavedSize); + GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - // sd fp, #(regsSavedSize+8)(sp) - emit->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_FP, REG_SPBASE, regsSavedSize + 8); - compiler->unwindSaveReg(REG_FP, regsSavedSize + 8); + genSaveCalleeSavedRegistersHelp(maskSaveRegs, FP_offset + 16, 0); - // addi sp, sp -#calleeSavedDelta - genStackPointerAdjustment(-calleeSavedDelta, REG_SCRATCH, nullptr, /* reportUnwindData */ true); + genStackPointerAdjustment(frameSize, REG_SCRATCH, nullptr, true); } // This is the end of the OS-reported prolog for purposes of unwinding @@ -977,66 +955,38 @@ void CodeGen::genFuncletEpilog() printf("*************** In genFuncletEpilog()\n"); } #endif - // TODO-RISCV64: Implement varargs (NYI_RISCV64) - // TODO-RISCV64-CQ: We can use C extension for optimization ScopedSetVariable _setGeneratingEpilog(&compiler->compGeneratingEpilog, true); compiler->unwindBegEpilog(); - const int frameSize = genFuncletInfo.fiSpDelta; - + int frameSize = genFuncletInfo.fiSpDelta; assert(frameSize < 0); - regMaskTP maskRestoreRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; - int regsRestoreSize = (compiler->compCalleeRegsPushed - 2) << 3; - - int calleeSavedDelta = genFuncletInfo.fiSP_to_CalleeSaved_delta; + regMaskTP maskSaveRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; + int FP_offset = genFuncletInfo.fiSP_to_CalleeSaved_delta; - emitter* emit = GetEmitter(); - regNumber tempReg = rsGetRsvdReg(); - - if (calleeSavedDelta + regsRestoreSize + genFuncletInfo.fiCalleeSavedPadding <= 2040) + if ((FP_offset + (genCountBits(maskSaveRegs) << 3)) > (2040 - 16)) // no FP/RA. { - calleeSavedDelta += genFuncletInfo.fiCalleeSavedPadding; - genRestoreCalleeSavedRegistersHelp(maskRestoreRegs, calleeSavedDelta, 0); - calleeSavedDelta += regsRestoreSize; - - // ld ra, #calleeSavedDelta(sp) - emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_RA, REG_SPBASE, calleeSavedDelta); - compiler->unwindSaveReg(REG_RA, calleeSavedDelta); + assert(frameSize < -2040); - // ld fp, #(calleeSavedDelta+8)(sp) - emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_FP, REG_SPBASE, calleeSavedDelta + 8); - compiler->unwindSaveReg(REG_FP, calleeSavedDelta + 8); + genStackPointerAdjustment(FP_offset & -16, REG_SCRATCH, nullptr, /* reportUnwindData */ true); - // addi sp, sp, -#frameSize - genStackPointerAdjustment(-frameSize, tempReg, nullptr, /* reportUnwindData */ true); + frameSize += FP_offset & -16; + FP_offset = FP_offset & 0xf; } - else - { - assert(frameSize < -2040); - - // addi sp, sp, #calleeSavedDelta - genStackPointerAdjustment(calleeSavedDelta, tempReg, nullptr, /* reportUnwindData */ true); - genRestoreCalleeSavedRegistersHelp(maskRestoreRegs, genFuncletInfo.fiCalleeSavedPadding, 0); - regsRestoreSize += genFuncletInfo.fiCalleeSavedPadding; + genRestoreCalleeSavedRegistersHelp(maskSaveRegs, FP_offset + 16, 0); - // ld ra, #regsRestoreSize(sp) - emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_RA, REG_SPBASE, regsRestoreSize); - compiler->unwindSaveReg(REG_RA, regsRestoreSize); + GetEmitter()->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - // ld fp, #(regsRestoreSize+8)(sp) - emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_FP, REG_SPBASE, regsRestoreSize + 8); - compiler->unwindSaveReg(REG_FP, regsRestoreSize + 8); + GetEmitter()->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - // addi sp, sp, -#(frameSize + calleeSavedDelta) - genStackPointerAdjustment(-(frameSize + calleeSavedDelta), tempReg, nullptr, /* reportUnwindData */ true); - } + genStackPointerAdjustment(-frameSize, REG_SCRATCH, nullptr, /* reportUnwindData */ true); - // jarl zero, ra - emit->emitIns_R_R_I(INS_jalr, emitActualTypeSize(TYP_I_IMPL), REG_R0, REG_RA, 0); + GetEmitter()->emitIns_R_R_I(INS_jalr, emitActualTypeSize(TYP_I_IMPL), REG_R0, REG_RA, 0); compiler->unwindReturn(REG_RA); compiler->unwindEndEpilog(); @@ -1059,7 +1009,6 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() } assert(isFramePointerUsed()); - // The frame size and offsets must be finalized assert(compiler->lvaDoneFrameLayout == Compiler::FINAL_FRAME_LAYOUT); @@ -1067,74 +1016,56 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() assert((rsMaskSaveRegs & RBM_RA) != 0); assert((rsMaskSaveRegs & RBM_FP) != 0); - unsigned pspSize = (compiler->lvaPSPSym != BAD_VAR_NUM) ? 8 : 0; - - // If there is a PSP slot, we have to pad the funclet frame size for OSR. - // For more details see CodeGen::genFuncletProlog + // Because a method and funclets must have the same caller-relative PSPSym offset, + // if there is a PSPSym, we have to pad the funclet frame size for OSR. // - unsigned osrPad = 0; - if (compiler->opts.IsOSR() && (pspSize != 0)) + int osrPad = 0; + if (compiler->opts.IsOSR()) { - osrPad = compiler->info.compPatchpointInfo->TotalFrameSize(); + osrPad -= compiler->info.compPatchpointInfo->TotalFrameSize(); - // osrPad must be aligned to stackSize - assert(osrPad % STACK_ALIGN == 0); + // OSR pad must be already aligned to stack size. + assert((osrPad % STACK_ALIGN) == 0); } - genFuncletInfo.fiCalleeSavedPadding = 0; - genFuncletInfo.fiFunction_CallerSP_to_FP_delta = genCallerSPtoFPdelta() - osrPad; - - unsigned savedRegsSize = genCountBits(rsMaskSaveRegs); - assert(savedRegsSize == compiler->compCalleeRegsPushed); - savedRegsSize <<= 3; + /* Now save it for future use */ + genFuncletInfo.fiFunction_CallerSP_to_FP_delta = genCallerSPtoFPdelta() + osrPad; - unsigned saveRegsPlusPSPSize = savedRegsSize + pspSize; + int funcletFrameSize = compiler->lvaOutgoingArgSpaceSize; - assert(compiler->lvaOutgoingArgSpaceSize % REGSIZE_BYTES == 0); - unsigned outgoingArgSpaceAligned = roundUp(compiler->lvaOutgoingArgSpaceSize, STACK_ALIGN); + genFuncletInfo.fiSP_to_CalleeSaved_delta = funcletFrameSize; - unsigned funcletFrameSize = osrPad + saveRegsPlusPSPSize + compiler->lvaOutgoingArgSpaceSize; - unsigned funcletFrameSizeAligned = roundUp(funcletFrameSize, STACK_ALIGN); + funcletFrameSize += genCountBits(rsMaskSaveRegs) * REGSIZE_BYTES; - int SP_to_CalleeSaved_delta = compiler->lvaOutgoingArgSpaceSize; - if ((SP_to_CalleeSaved_delta + savedRegsSize) >= 2040) + int delta_PSP = -TARGET_POINTER_SIZE; + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) { - int offset = funcletFrameSizeAligned - SP_to_CalleeSaved_delta; - SP_to_CalleeSaved_delta = AlignUp((UINT)offset, STACK_ALIGN); - - genFuncletInfo.fiCalleeSavedPadding = SP_to_CalleeSaved_delta - offset; + delta_PSP -= TARGET_POINTER_SIZE; } - if (compiler->lvaMonAcquired != BAD_VAR_NUM && !compiler->opts.IsOSR()) - { - // We furthermore allocate the "monitor acquired" bool between PSP and - // the saved registers because this is part of the EnC header. - // Note that OSR methods reuse the monitor bool created by tier 0. - osrPad += compiler->lvaLclSize(compiler->lvaMonAcquired); - } + funcletFrameSize = funcletFrameSize - delta_PSP - osrPad; + funcletFrameSize = roundUp((unsigned)funcletFrameSize, STACK_ALIGN); - /* Now save it for future use */ - genFuncletInfo.fiSpDelta = -(int)funcletFrameSizeAligned; + genFuncletInfo.fiSpDelta = -funcletFrameSize; genFuncletInfo.fiSaveRegs = rsMaskSaveRegs; - genFuncletInfo.fiSP_to_CalleeSaved_delta = SP_to_CalleeSaved_delta; - genFuncletInfo.fiSP_to_PSP_slot_delta = funcletFrameSizeAligned - osrPad - 8; - genFuncletInfo.fiCallerSP_to_PSP_slot_delta = -(int)osrPad - 8; + genFuncletInfo.fiSP_to_PSP_slot_delta = funcletFrameSize + delta_PSP + osrPad; + genFuncletInfo.fiCallerSP_to_PSP_slot_delta = osrPad + delta_PSP; #ifdef DEBUG if (verbose) { printf("\n"); printf("Funclet prolog / epilog info\n"); - printf(" Save regs: "); + printf(" Save regs: "); dspRegMask(genFuncletInfo.fiSaveRegs); printf("\n"); if (compiler->opts.IsOSR()) { - printf(" OSR Pad: %d\n", osrPad); + printf(" OSR Pad: %d\n", osrPad); } - printf(" Function CallerSP-to-FP delta: %d\n", genFuncletInfo.fiFunction_CallerSP_to_FP_delta); + printf(" Function CallerSP-to-FP delta: %d\n", genFuncletInfo.fiFunction_CallerSP_to_FP_delta); printf(" SP to CalleeSaved location delta: %d\n", genFuncletInfo.fiSP_to_CalleeSaved_delta); - printf(" SP delta: %d\n", genFuncletInfo.fiSpDelta); + printf(" SP delta: %d\n", genFuncletInfo.fiSpDelta); } assert(genFuncletInfo.fiSP_to_CalleeSaved_delta >= 0); @@ -1605,7 +1536,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre else { // Get a temp integer register to compute long address. - // regNumber addrReg = tree->GetSingleTempReg(); + // regNumber addrReg = internalRegisters.GetSingle(tree); // We must load the FP constant from the constant pool // Emit a data section constant for the float or double constant. @@ -1685,7 +1616,7 @@ void CodeGen::genCodeForMulHi(GenTreeOp* treeNode) assert(EA_SIZE(attr) == EA_4BYTE); if (isUnsigned) { - regNumber tempReg = treeNode->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(treeNode); emit->emitIns_R_R_I(INS_slli, EA_8BYTE, tempReg, op1->GetRegNum(), 32); emit->emitIns_R_R_I(INS_slli, EA_8BYTE, targetReg, op2->GetRegNum(), 32); emit->emitIns_R_R_R(INS_mulhu, EA_8BYTE, targetReg, tempReg, targetReg); @@ -2012,7 +1943,7 @@ void CodeGen::genLclHeap(GenTree* tree) noway_assert(isFramePointerUsed()); // localloc requires Frame Pointer to be established since SP changes noway_assert(genStackLevel == 0); // Can't have anything on the stack - const target_ssize_t pageSize = compiler->eeGetPageSize(); + const target_size_t pageSize = compiler->eeGetPageSize(); // According to RISC-V Privileged ISA page size is 4KiB noway_assert(pageSize == 0x1000); @@ -2051,7 +1982,7 @@ void CodeGen::genLclHeap(GenTree* tree) } else { - regCnt = tree->ExtractTempReg(); + regCnt = internalRegisters.Extract(tree); if (regCnt != targetReg) { emit->emitIns_R_R_I(INS_ori, easz, regCnt, targetReg, 0); @@ -2081,7 +2012,7 @@ void CodeGen::genLclHeap(GenTree* tree) unsigned outgoingArgSpaceAligned = roundUp(compiler->lvaOutgoingArgSpaceSize, STACK_ALIGN); // assert((compiler->lvaOutgoingArgSpaceSize % STACK_ALIGN) == 0); // This must be true for the stack to remain // // aligned - tempReg = tree->ExtractTempReg(); + tempReg = internalRegisters.Extract(tree); genInstrWithConstant(INS_addi, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, outgoingArgSpaceAligned, tempReg); stackAdjustment += outgoingArgSpaceAligned; } @@ -2136,7 +2067,7 @@ void CodeGen::genLclHeap(GenTree* tree) else { if (tempReg == REG_NA) - tempReg = tree->ExtractTempReg(); + tempReg = internalRegisters.Extract(tree); emit->emitLoadImmediate(EA_PTRSIZE, tempReg, amount); emit->emitIns_R_R_R(INS_sub, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, tempReg); } @@ -2154,7 +2085,7 @@ void CodeGen::genLclHeap(GenTree* tree) } else { - regCnt = tree->ExtractTempReg(); + regCnt = internalRegisters.Extract(tree); } instGen_Set_Reg_To_Imm(((unsigned int)amount == amount) ? EA_4BYTE : EA_8BYTE, regCnt, amount); } @@ -2221,9 +2152,9 @@ void CodeGen::genLclHeap(GenTree* tree) // if (tempReg == REG_NA) - tempReg = tree->ExtractTempReg(); + tempReg = internalRegisters.Extract(tree); - regNumber rPageSize = tree->GetSingleTempReg(); + regNumber rPageSize = internalRegisters.GetSingle(tree); assert(regCnt != tempReg); emit->emitIns_R_R_R(INS_sltu, EA_PTRSIZE, tempReg, REG_SPBASE, regCnt); @@ -2428,7 +2359,7 @@ void CodeGen::genCodeForDivMod(GenTreeOp* tree) ssize_t intConst = (int)(divisorOp->AsIntCon()->gtIconVal); if (!emitter::isGeneralRegister(divisorReg)) { - tempReg = tree->GetSingleTempReg(); + tempReg = internalRegisters.GetSingle(tree); divisorReg = tempReg; } emit->emitLoadImmediate(EA_PTRSIZE, divisorReg, intConst); @@ -2451,7 +2382,7 @@ void CodeGen::genCodeForDivMod(GenTreeOp* tree) if ((exceptions & ExceptionSetFlags::ArithmeticException) != ExceptionSetFlags::None) { if (tempReg == REG_NA) - tempReg = tree->GetSingleTempReg(); + tempReg = internalRegisters.GetSingle(tree); // Check if the divisor is not -1 branch to 'sdivLabel' emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, tempReg, REG_ZERO, -1); @@ -2657,7 +2588,8 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) sourceIsLocal = true; } - bool dstOnStack = dstAddr->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR); + bool dstOnStack = + dstAddr->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR) || cpObjNode->GetLayout()->IsStackOnly(compiler); #ifdef DEBUG assert(!dstAddr->isContained()); @@ -2677,7 +2609,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) unsigned slots = layout->GetSlotCount(); // Temp register(s) used to perform the sequence of loads and stores. - regNumber tmpReg = cpObjNode->ExtractTempReg(); + regNumber tmpReg = internalRegisters.Extract(cpObjNode); regNumber tmpReg2 = REG_NA; assert(genIsValidIntReg(tmpReg)); @@ -2686,7 +2618,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) if (slots > 1) { - tmpReg2 = cpObjNode->GetSingleTempReg(); + tmpReg2 = internalRegisters.GetSingle(cpObjNode); assert(tmpReg2 != tmpReg); assert(genIsValidIntReg(tmpReg2)); assert(tmpReg2 != REG_WRITE_BARRIER_DST_BYREF); @@ -2821,7 +2753,7 @@ void CodeGen::genTableBasedSwitch(GenTree* treeNode) regNumber idxReg = treeNode->AsOp()->gtOp1->GetRegNum(); regNumber baseReg = treeNode->AsOp()->gtOp2->GetRegNum(); - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); // load the ip-relative offset (which is relative to start of fgFirstBB) GetEmitter()->emitIns_R_R_I(INS_slli, EA_8BYTE, tmpReg, idxReg, 2); @@ -2921,7 +2853,7 @@ void CodeGen::genCodeForCmpXchg(GenTreeCmpXchg* treeNode) regNumber loc = locOp->GetRegNum(); regNumber val = valOp->GetRegNum(); regNumber comparand = comparandOp->GetRegNum(); - regNumber storeErr = treeNode->ExtractTempReg(RBM_ALLINT); + regNumber storeErr = internalRegisters.Extract(treeNode, RBM_ALLINT); // Register allocator should have extended the lifetimes of all input and internal registers // They should all be different @@ -3628,7 +3560,7 @@ void CodeGen::genFloatToIntCast(GenTree* treeNode) genConsumeOperands(treeNode->AsOp()); - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); assert(tmpReg != treeNode->GetRegNum()); assert(tmpReg != op1->GetRegNum()); @@ -3675,7 +3607,7 @@ void CodeGen::genCkfinite(GenTree* treeNode) emitAttr attr = emitActualTypeSize(treeNode); // Extract exponent into a register. - regNumber intReg = treeNode->GetSingleTempReg(); + regNumber intReg = internalRegisters.GetSingle(treeNode); regNumber fpReg = genConsumeReg(op1); emit->emitIns_R_R(attr == EA_4BYTE ? INS_fclass_s : INS_fclass_d, attr, intReg, fpReg); @@ -3740,7 +3672,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) } else if (tree->OperIs(GT_EQ)) { - regNumber tempReg = tree->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(tree); skipLabel = genCreateTempLabel(); emit->emitIns_R_R(cmpSize == EA_4BYTE ? INS_fclass_s : INS_fclass_d, cmpSize, targetReg, regOp1); emit->emitIns_R_R(cmpSize == EA_4BYTE ? INS_fclass_s : INS_fclass_d, cmpSize, tempReg, regOp2); @@ -3785,7 +3717,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) } else if (tree->OperIs(GT_NE)) { - regNumber tempReg = tree->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(tree); emit->emitIns_R_R(cmpSize == EA_4BYTE ? INS_fclass_s : INS_fclass_d, cmpSize, targetReg, regOp1); emit->emitIns_R_R(cmpSize == EA_4BYTE ? INS_fclass_s : INS_fclass_d, cmpSize, tempReg, regOp2); emit->emitIns_R_R_R(INS_or, EA_8BYTE, tempReg, targetReg, tempReg); @@ -3824,7 +3756,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) { imm = static_cast(imm); - regNumber tmpRegOp1 = tree->GetSingleTempReg(); + regNumber tmpRegOp1 = internalRegisters.GetSingle(tree); assert(regOp1 != tmpRegOp1); emit->emitIns_R_R_I(INS_slli, EA_8BYTE, tmpRegOp1, regOp1, 32); @@ -3953,7 +3885,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) if (cmpSize == EA_4BYTE) { regNumber tmpRegOp1 = REG_RA; - regNumber tmpRegOp2 = tree->GetSingleTempReg(); + regNumber tmpRegOp2 = internalRegisters.GetSingle(tree); assert(regOp1 != tmpRegOp2); assert(regOp2 != tmpRegOp2); @@ -4224,9 +4156,17 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree) int CodeGenInterface::genSPtoFPdelta() const { assert(isFramePointerUsed()); - assert(compiler->compCalleeRegsPushed >= 2); + assert(compiler->compCalleeRegsPushed >= 2); // always FP/RA. - int delta = compiler->lvaOutgoingArgSpaceSize + (compiler->compCalleeRegsPushed << 3) - 8; + int delta = compiler->compLclFrameSize; + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + delta -= TARGET_POINTER_SIZE; + } + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) + { + delta -= TARGET_POINTER_SIZE; + } assert(delta >= 0); return delta; @@ -4290,8 +4230,8 @@ int CodeGenInterface::genCallerSPtoInitialSPdelta() const // at the end static void emitLoadConstAtAddr(emitter* emit, regNumber dstRegister, ssize_t imm) { - ssize_t high = (imm >> 32) & 0xffffffff; - emit->emitIns_R_I(INS_lui, EA_PTRSIZE, dstRegister, (((high + 0x800) >> 12) & 0xfffff)); + ssize_t high = imm >> 32; + emit->emitIns_R_I(INS_lui, EA_PTRSIZE, dstRegister, (high + 0x800) >> 12); emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, dstRegister, dstRegister, (high & 0xfff)); ssize_t low = imm & 0xffffffff; @@ -4914,7 +4854,7 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) break; case GT_JMP: - genJmpMethod(treeNode); + genJmpPlaceArgs(treeNode); break; case GT_CKFINITE: @@ -5197,7 +5137,7 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) UINT32 high = ((ssize_t)compiler->gsGlobalSecurityCookieAddr) >> 32; if (((high + 0x800) >> 12) != 0) { - GetEmitter()->emitIns_R_I(INS_lui, EA_PTRSIZE, regGSConst, (((high + 0x800) >> 12) & 0xfffff)); + GetEmitter()->emitIns_R_I(INS_lui, EA_PTRSIZE, regGSConst, ((int32_t)(high + 0x800)) >> 12); } if ((high & 0xFFF) != 0) { @@ -5341,7 +5281,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) // Setup loReg from the internal registers that we reserved in lower. // - regNumber loReg = treeNode->ExtractTempReg(); + regNumber loReg = internalRegisters.Extract(treeNode); GenTreeLclVarCommon* srcLclNode = nullptr; regNumber addrReg = REG_NA; @@ -5584,7 +5524,7 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) regNumber allocatedValueReg = REG_NA; if (treeNode->gtNumRegs == 1) { - allocatedValueReg = treeNode->ExtractTempReg(); + allocatedValueReg = internalRegisters.Extract(treeNode); } // Pick a register to store intermediate values in for the to-stack @@ -5731,13 +5671,13 @@ void CodeGen::genRangeCheck(GenTree* oper) if (genActualType(length) == TYP_INT) { - regNumber tempReg = oper->ExtractTempReg(); + regNumber tempReg = internalRegisters.Extract(oper); GetEmitter()->emitIns_R_R_I(INS_addiw, EA_4BYTE, tempReg, lengthReg, 0); // sign-extend lengthReg = tempReg; } if (genActualType(index) == TYP_INT) { - regNumber tempReg = oper->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(oper); GetEmitter()->emitIns_R_R_I(INS_addiw, EA_4BYTE, tempReg, indexReg, 0); // sign-extend indexReg = tempReg; } @@ -5820,7 +5760,7 @@ void CodeGen::genCodeForShift(GenTree* tree) if (tree->OperIs(GT_ROR, GT_ROL)) { - regNumber tempReg = tree->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(tree); unsigned immWidth = emitter::getBitWidth(size); // For RISCV64, immWidth will be set to 32 or 64 if (!shiftBy->IsCnsIntOrI()) { @@ -6010,7 +5950,7 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) // The index is never contained, even if it is a constant. assert(index->isUsedFromReg()); - regNumber tempReg = node->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(node); // Generate the bounds check if necessary. if (node->IsBoundsChecked()) @@ -6217,7 +6157,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode) assert(srcOffset < INT32_MAX - static_cast(size)); assert(dstOffset < INT32_MAX - static_cast(size)); - regNumber tempReg = cpBlkNode->ExtractTempReg(RBM_ALLINT); + regNumber tempReg = internalRegisters.Extract(cpBlkNode, RBM_ALLINT); if (size >= 2 * REGSIZE_BYTES) { @@ -6346,7 +6286,7 @@ void CodeGen::genCodeForInitBlkLoop(GenTreeBlk* initBlkNode) // Extend liveness of dstReg in case if it gets killed by the store. gcInfo.gcMarkRegPtrVal(dstReg, dstNode->TypeGet()); - const regNumber tempReg = initBlkNode->GetSingleTempReg(); + const regNumber tempReg = internalRegisters.GetSingle(initBlkNode); instGen_Set_Reg_To_Imm(EA_PTRSIZE, tempReg, size - TARGET_POINTER_SIZE); // tempReg = dstReg + tempReg (a new interior pointer, but in a nongc region) @@ -6452,7 +6392,7 @@ void CodeGen::genCall(GenTreeCall* call) (call->IsVirtualStubRelativeIndir() && (call->gtEntryPoint.accessType == IAT_VALUE))); assert(call->gtControlExpr == nullptr); - regNumber tmpReg = call->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(call); // Register where we save call address in should not be overridden by epilog. assert((genRegMask(tmpReg) & (RBM_INT_CALLEE_TRASH & ~RBM_RA)) == genRegMask(tmpReg)); @@ -6460,7 +6400,7 @@ void CodeGen::genCall(GenTreeCall* call) call->IsVirtualStubRelativeIndir() ? compiler->virtualStubParamInfo->GetReg() : REG_R2R_INDIRECT_PARAM; GetEmitter()->emitIns_R_R_I(ins_Load(TYP_I_IMPL), emitActualTypeSize(TYP_I_IMPL), tmpReg, callAddrReg, 0); // We will use this again when emitting the jump in genCallInstruction in the epilog - call->gtRsvdRegs |= genRegMask(tmpReg); + internalRegisters.Add(call, genRegMask(tmpReg)); } #endif @@ -6561,22 +6501,26 @@ void CodeGen::genCallInstruction(GenTreeCall* call) emitAttr retSize = EA_PTRSIZE; emitAttr secondRetSize = EA_UNKNOWN; - if (call->HasMultiRegRetVal()) + // unused values are of no interest to GC. + if (!call->IsUnusedValue()) { - retSize = emitTypeSize(pRetTypeDesc->GetReturnRegType(0)); - secondRetSize = emitTypeSize(pRetTypeDesc->GetReturnRegType(1)); - } - else - { - assert(call->gtType != TYP_STRUCT); - - if (call->gtType == TYP_REF) + if (call->HasMultiRegRetVal()) { - retSize = EA_GCREF; + retSize = emitTypeSize(pRetTypeDesc->GetReturnRegType(0)); + secondRetSize = emitTypeSize(pRetTypeDesc->GetReturnRegType(1)); } - else if (call->gtType == TYP_BYREF) + else { - retSize = EA_BYREF; + assert(call->gtType != TYP_STRUCT); + + if (call->gtType == TYP_REF) + { + retSize = EA_GCREF; + } + else if (call->gtType == TYP_BYREF) + { + retSize = EA_BYREF; + } } } @@ -6594,7 +6538,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) #ifdef DEBUG // Pass the call signature information down into the emitter so the emitter can associate // native call sites with the signatures they were generated from. - if (call->gtCallType != CT_HELPER) + if (!call->IsHelperCall()) { sigInfo = call->callSig; } @@ -6678,7 +6622,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) if (callThroughIndirReg != REG_NA) { assert(call->IsR2ROrVirtualStubRelativeIndir()); - regNumber targetAddrReg = call->GetSingleTempReg(); + regNumber targetAddrReg = internalRegisters.GetSingle(call); // For fast tailcalls we have already loaded the call target when processing the call node. if (!call->IsFastTailCall()) { @@ -6711,7 +6655,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) else { // Generate a direct call to a non-virtual user defined or helper method - assert(call->gtCallType == CT_HELPER || call->gtCallType == CT_USER_FUNC); + assert(call->IsHelperCall() || (call->gtCallType == CT_USER_FUNC)); void* addr = nullptr; #ifdef FEATURE_READYTORUN @@ -6722,7 +6666,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) } else #endif // FEATURE_READYTORUN - if (call->gtCallType == CT_HELPER) + if (call->IsHelperCall()) { CorInfoHelpFunc helperNum = compiler->eeGetHelperNum(methHnd); noway_assert(helperNum != CORINFO_HELP_UNDEF); @@ -6754,176 +6698,13 @@ void CodeGen::genCallInstruction(GenTreeCall* call) } } -// Produce code for a GT_JMP node. -// The arguments of the caller needs to be transferred to the callee before exiting caller. -// The actual jump to callee is generated as part of caller epilog sequence. -// Therefore the codegen of GT_JMP is to ensure that the callee arguments are correctly setup. -void CodeGen::genJmpMethod(GenTree* jmp) +//------------------------------------------------------------------------ +// genJmpPlaceVarArgs: +// Generate code to place all varargs correctly for a JMP. +// +void CodeGen::genJmpPlaceVarArgs() { - assert(jmp->OperGet() == GT_JMP); - assert(compiler->compJmpOpUsed); - - // If no arguments, nothing to do - if (compiler->info.compArgsCount == 0) - { - return; - } - - // Make sure register arguments are in their initial registers - // and stack arguments are put back as well. - unsigned varNum; - LclVarDsc* varDsc; - - // First move any en-registered stack arguments back to the stack. - // At the same time any reg arg not in correct reg is moved back to its stack location. - // - // We are not strictly required to spill reg args that are not in the desired reg for a jmp call - // But that would require us to deal with circularity while moving values around. Spilling - // to stack makes the implementation simple, which is not a bad trade off given Jmp calls - // are not frequent. - for (varNum = 0; varNum < compiler->info.compArgsCount; varNum++) - { - varDsc = compiler->lvaGetDesc(varNum); - - if (varDsc->lvPromoted) - { - noway_assert(varDsc->lvFieldCnt == 1); // We only handle one field here - - unsigned fieldVarNum = varDsc->lvFieldLclStart; - varDsc = compiler->lvaGetDesc(fieldVarNum); - } - noway_assert(varDsc->lvIsParam); - - if (varDsc->lvIsRegArg && (varDsc->GetRegNum() != REG_STK)) - { - // Skip reg args which are already in its right register for jmp call. - // If not, we will spill such args to their stack locations. - // - // If we need to generate a tail call profiler hook, then spill all - // arg regs to free them up for the callback. - if (!compiler->compIsProfilerHookNeeded() && (varDsc->GetRegNum() == varDsc->GetArgReg())) - continue; - } - else if (varDsc->GetRegNum() == REG_STK) - { - // Skip args which are currently living in stack. - continue; - } - - // If we came here it means either a reg argument not in the right register or - // a stack argument currently living in a register. In either case the following - // assert should hold. - assert(varDsc->GetRegNum() != REG_STK); - assert(varDsc->IsEnregisterableLcl()); - var_types storeType = varDsc->GetStackSlotHomeType(); - emitAttr storeSize = emitActualTypeSize(storeType); - - GetEmitter()->emitIns_S_R(ins_Store(storeType), storeSize, varDsc->GetRegNum(), varNum, 0); - - // Update lvRegNum life and GC info to indicate lvRegNum is dead and varDsc stack slot is going live. - // Note that we cannot modify varDsc->GetRegNum() here because another basic block may not be expecting it. - // Therefore manually update life of varDsc->GetRegNum(). - regMaskTP tempMask = genRegMask(varDsc->GetRegNum()); - regSet.RemoveMaskVars(tempMask); - gcInfo.gcMarkRegSetNpt(tempMask); - if (compiler->lvaIsGCTracked(varDsc)) - { - VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varNum); - } - } - -#ifdef PROFILING_SUPPORTED - // At this point all arg regs are free. - // Emit tail call profiler callback. - genProfilingLeaveCallback(CORINFO_HELP_PROF_FCN_TAILCALL); -#endif - - // Next move any un-enregistered register arguments back to their register. - for (varNum = 0; varNum < compiler->info.compArgsCount; varNum++) - { - varDsc = compiler->lvaGetDesc(varNum); - if (varDsc->lvPromoted) - { - noway_assert(varDsc->lvFieldCnt == 1); // We only handle one field here - - unsigned fieldVarNum = varDsc->lvFieldLclStart; - varDsc = compiler->lvaGetDesc(fieldVarNum); - } - noway_assert(varDsc->lvIsParam); - - // Skip if arg not passed in a register. - if (!varDsc->lvIsRegArg) - continue; - - // Register argument - noway_assert(isRegParamType(genActualType(varDsc->TypeGet()))); - - // Is register argument already in the right register? - // If not load it from its stack location. - regNumber argReg = varDsc->GetArgReg(); // incoming arg register - regNumber argRegNext = REG_NA; - - if (varDsc->GetRegNum() != argReg) - { - var_types loadType = TYP_UNDEF; - - if (varTypeIsStruct(varDsc)) - { - // Must be <= 16 bytes or else it wouldn't be passed in registers, except for HFA, - // which can be bigger (and is handled above). - noway_assert(EA_SIZE_IN_BYTES(varDsc->lvSize()) <= 16); - if (emitter::isFloatReg(argReg)) - { - loadType = varDsc->lvIs4Field1 ? TYP_FLOAT : TYP_DOUBLE; - } - else - { - loadType = varDsc->GetLayout()->GetGCPtrType(0); - } - } - else - { - loadType = compiler->mangleVarArgsType(genActualType(varDsc->TypeGet())); - } - emitAttr loadSize = emitActualTypeSize(loadType); - GetEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, argReg, varNum, 0); - - // Update argReg life and GC Info to indicate varDsc stack slot is dead and argReg is going live. - // Note that we cannot modify varDsc->GetRegNum() here because another basic block may not be - // expecting it. Therefore manually update life of argReg. Note that GT_JMP marks the end of - // the basic block and after which reg life and gc info will be recomputed for the new block - // in genCodeForBBList(). - regSet.AddMaskVars(genRegMask(argReg)); - gcInfo.gcMarkRegPtrVal(argReg, loadType); - - if (varDsc->GetOtherArgReg() < REG_STK) - { - // Restore the second register. - argRegNext = varDsc->GetOtherArgReg(); - - if (emitter::isFloatReg(argRegNext)) - { - loadType = varDsc->lvIs4Field2 ? TYP_FLOAT : TYP_DOUBLE; - } - else - { - loadType = varDsc->GetLayout()->GetGCPtrType(1); - } - - loadSize = emitActualTypeSize(loadType); - int offs = loadSize == EA_4BYTE ? 4 : 8; - GetEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, argRegNext, varNum, offs); - - regSet.AddMaskVars(genRegMask(argRegNext)); - gcInfo.gcMarkRegPtrVal(argRegNext, loadType); - } - - if (compiler->lvaIsGCTracked(varDsc)) - { - VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); - } - } - } + NYI_RISCV64("Varargs not supported"); } //------------------------------------------------------------------------ @@ -6946,7 +6727,7 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d case GenIntCastDesc::CHECK_UINT_RANGE: { - regNumber tempReg = cast->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(cast); // We need to check if the value is not greater than 0xFFFFFFFF // if the upper 32 bits are zero. ssize_t imm = -1; @@ -6960,7 +6741,7 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d case GenIntCastDesc::CHECK_POSITIVE_INT_RANGE: { - regNumber tempReg = cast->GetSingleTempReg(); + regNumber tempReg = internalRegisters.GetSingle(cast); // We need to check if the value is not greater than 0x7FFFFFFF // if the upper 33 bits are zero. // instGen_Set_Reg_To_Imm(EA_8BYTE, tempReg, 0xFFFFFFFF80000000LL); @@ -6976,7 +6757,7 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d case GenIntCastDesc::CHECK_INT_RANGE: { - const regNumber tempReg = cast->GetSingleTempReg(); + const regNumber tempReg = internalRegisters.GetSingle(cast); assert(tempReg != reg); GetEmitter()->emitLoadImmediate(EA_8BYTE, tempReg, INT32_MAX); genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_blt, tempReg, nullptr, reg); @@ -6991,7 +6772,7 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d assert(desc.CheckKind() == GenIntCastDesc::CHECK_SMALL_INT_RANGE); const int castMaxValue = desc.CheckSmallIntMax(); const int castMinValue = desc.CheckSmallIntMin(); - const regNumber tempReg = cast->GetSingleTempReg(); + const regNumber tempReg = internalRegisters.GetSingle(cast); instruction ins; if (castMaxValue > 2047) @@ -7290,7 +7071,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) assert(isPow2(lea->gtScale)); BitScanForward(&scale, lea->gtScale); assert(scale <= 4); - regNumber scaleTempReg = scale ? lea->ExtractTempReg() : REG_NA; + regNumber scaleTempReg = scale ? internalRegisters.Extract(lea) : REG_NA; if (offset == 0) { @@ -7311,7 +7092,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) } else { - regNumber tmpReg = lea->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(lea); noway_assert(tmpReg != index->GetRegNum()); noway_assert(tmpReg != memBase->GetRegNum()); @@ -7348,7 +7129,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) else { // We require a tmpReg to hold the offset - regNumber tmpReg = lea->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(lea); // First load tmpReg with the large offset constant emit->emitLoadImmediate(EA_PTRSIZE, tmpReg, offset); @@ -7733,8 +7514,8 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) * sd s11, #(offset+8*10)(sp) * * ; save ra, fp - * sd ra, #offset3(sp) ; save RA (8 bytes) - * sd fp, #(offset3+8)(sp) ; save FP (8 bytes) + * sd ra, #offset3+8(sp) ; save RA (8 bytes) + * sd fp, #(offset3)(sp) ; save FP (8 bytes) * * Notes: * 1. FP is always saved, and the first store is FP, RA. @@ -7742,9 +7523,9 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) * 3. For frames with varargs, not implemented completely and not tested ! * 4. We allocate the frame here; no further changes to SP are allowed (except in the body, for localloc). * - * For functions with GS and localloc, we change the frame so the frame pointer and RA are saved at the top - * of the frame, just under the varargs registers (if any). Note that the funclet frames must follow the same - * rule, and both main frame and funclet frames (if any) must put PSPSym in the same offset from Caller-SP. + * For functions with GS and localloc, we had saved the frame pointer and RA at the top + * of the frame. Note that the funclet frames must follow the same rule, + * and both main frame and funclet frames (if any) must put PSPSym in the same offset from Caller-SP. * Since this frame type is relatively rare, we force using it via stress modes, for additional coverage. * * The frames look like the following (simplified to only include components that matter for establishing the @@ -7752,6 +7533,10 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) * * The RISC-V's frame layout is liking: * + * If we need to generate a GS cookie, we need to make sure the saved frame pointer and return address + * (FP and RA) are protected from buffer overrun by the GS cookie. + * So we always save the FP/RA along with the rest of the callee-saved registers above. + * * | | * |-----------------------| * | incoming arguments | @@ -7763,15 +7548,17 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) * |-----------------------| * | PSP slot | // 8 bytes (omitted in NativeAOT ABI) * |-----------------------| - * | locals, temps, etc. | - * |-----------------------| - * | possible GS cookie | + * |Callee saved registers | // not including FP/RA; multiple of 8 bytes * |-----------------------| * | Saved FP | // 8 bytes * |-----------------------| * | Saved RA | // 8 bytes * |-----------------------| - * |Callee saved registers | // not including FP/RA; multiple of 8 bytes + * | possible GS cookie | + * |-----------------------| + * | locals, temps, etc. | + * |-----------------------| + * | possible GS cookie | * |-----------------------| * | Outgoing arg space | // multiple of 8 bytes; if required (i.e., #outsz != 0) * |-----------------------| <---- Ambient SP @@ -7785,12 +7572,6 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe { assert(compiler->compGeneratingProlog); - // The 'initReg' could have been calculated as one of the callee-saved registers (let's say T0, T1 and T2 are in - // use, so the next possible register is S1, which should be callee-save register). This is fine, as long as we - // save callee-saved registers before using 'initReg' for the first time. Instead, we can use REG_SCRATCH - // beforehand. We don't care if REG_SCRATCH will be overwritten, so we'll skip 'RegZeroed check'. - // - // Unlike on x86/x64, we can also push float registers to stack regMaskTP rsPushRegs = regSet.rsGetModifiedCalleeSavedRegsMask(); #if ETW_EBP_FRAMED @@ -7800,7 +7581,7 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe } #endif - // On RV64 we always use the FP (frame-pointer) + // We always use the FP (frame-pointer). assert(isFramePointerUsed()); // @@ -7823,25 +7604,25 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe // is not worth it. // - // we will push callee-saved registers along with fp and ra registers to stack - regMaskTP rsPushRegsMask = rsPushRegs | RBM_FP | RBM_RA; - regSet.rsMaskCalleeSaved = rsPushRegsMask; + regSet.rsMaskCalleeSaved = rsPushRegs | RBM_FPBASE | RBM_RA; #ifdef DEBUG - if (compiler->compCalleeRegsPushed != genCountBits(rsPushRegsMask)) + JITDUMP("Frame info. #outsz=%d; #framesz=%d; LclFrameSize=%d;\n", unsigned(compiler->lvaOutgoingArgSpaceSize), + genTotalFrameSize(), compiler->compLclFrameSize); + + if (compiler->compCalleeRegsPushed != genCountBits(regSet.rsMaskCalleeSaved)) { printf("Error: unexpected number of callee-saved registers to push. Expected: %d. Got: %d ", - compiler->compCalleeRegsPushed, genCountBits(rsPushRegsMask)); - dspRegMask(rsPushRegsMask); + compiler->compCalleeRegsPushed, genCountBits(rsPushRegs | RBM_FPBASE | RBM_RA)); + dspRegMask(rsPushRegs | RBM_FPBASE | RBM_RA); printf("\n"); - assert(compiler->compCalleeRegsPushed == genCountBits(rsPushRegsMask)); + assert(compiler->compCalleeRegsPushed == genCountBits(rsPushRegs | RBM_FPBASE | RBM_RA)); } if (verbose) { - regMaskTP maskSaveRegsFloat = rsPushRegs & RBM_FLT_CALLEE_SAVED; - regMaskTP maskSaveRegsInt = rsPushRegs & RBM_INT_CALLEE_SAVED; - + regMaskTP maskSaveRegsFloat = rsPushRegs & RBM_ALLFLOAT; + regMaskTP maskSaveRegsInt = rsPushRegs & ~maskSaveRegsFloat; printf("Save float regs: "); dspRegMask(maskSaveRegsFloat); printf("\n"); @@ -7851,80 +7632,57 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe } #endif // DEBUG - // The frameType number is arbitrary, is defined below, and corresponds to one of the frame styles we - // generate based on various sizes. - int frameType = 0; - - // The amount to subtract from SP before starting to store the callee-saved registers. It might be folded into the - // first save instruction as a "predecrement" amount, if possible. - int calleeSaveSPDelta = 0; - - // If we need to generate a GS cookie, we need to make sure the saved frame pointer and return address - // (FP and RA) are protected from buffer overrun by the GS cookie. If FP/RA are at the lowest addresses, - // then they are safe, since they are lower than any unsafe buffers. And the GS cookie we add will - // protect our caller's frame. If we have a localloc, however, that is dynamically placed lower than our - // saved FP/RA. In that case, we save FP/RA along with the rest of the callee-saved registers, above - // the GS cookie. - // - // After the frame is allocated, the frame pointer is established, pointing at the saved frame pointer to - // create a frame pointer chain. - // - - // This will be the starting place for saving the callee-saved registers, in increasing order. - int offset = compiler->lvaOutgoingArgSpaceSize; - int totalFrameSize = genTotalFrameSize(); + int leftFrameSize = 0; + int localFrameSize = compiler->compLclFrameSize; + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + localFrameSize -= TARGET_POINTER_SIZE; + } + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) + { + localFrameSize -= TARGET_POINTER_SIZE; + } - emitter* emit = GetEmitter(); +#ifdef DEBUG + if (compiler->opts.disAsm) + { + printf("Frame info. #outsz=%d; #framesz=%d; lcl=%d\n", unsigned(compiler->lvaOutgoingArgSpaceSize), + genTotalFrameSize(), localFrameSize); + } +#endif - // ensure offset of sd/ld + int FP_offset = localFrameSize; if (totalFrameSize <= 2040) { - frameType = 1; - - emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, -totalFrameSize); + GetEmitter()->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, -totalFrameSize); compiler->unwindAllocStack(totalFrameSize); - - JITDUMP("Frame type 1. #outsz=%d; #framesz=%d; LclFrameSize=%d\n", unsigned(compiler->lvaOutgoingArgSpaceSize), - totalFrameSize, compiler->compLclFrameSize); } else { - frameType = 2; - // we have to adjust stack pointer; probably using add instead of addi - - JITDUMP("Frame type 2. #outsz=%d; #framesz=%d; LclFrameSize=%d\n", unsigned(compiler->lvaOutgoingArgSpaceSize), - totalFrameSize, compiler->compLclFrameSize); - - if ((offset + (compiler->compCalleeRegsPushed << 3)) >= 2040) - { - offset = totalFrameSize - compiler->lvaOutgoingArgSpaceSize; - calleeSaveSPDelta = AlignUp((UINT)offset, STACK_ALIGN); - offset = calleeSaveSPDelta - offset; - - genStackPointerAdjustment(-calleeSaveSPDelta, REG_SCRATCH, nullptr, /* reportUnwindData */ true); - } - else + if ((localFrameSize + (compiler->compCalleeRegsPushed << 3)) > 2040) { - genStackPointerAdjustment(-totalFrameSize, REG_SCRATCH, nullptr, /* reportUnwindData */ true); + leftFrameSize = localFrameSize & -16; + totalFrameSize = totalFrameSize - (localFrameSize & -16); + FP_offset = localFrameSize & 0xf; } + // The 'initReg' could have been calculated as one of the callee-saved registers (let's say T0, T1 and T2 are in + // use, so the next possible register is S1, which should be callee-save register). This is fine, as long as we + // save callee-saved registers before using 'initReg' for the first time. Instead, we can use REG_SCRATCH + // beforehand. We don't care if REG_SCRATCH will be overwritten, so we'll skip 'RegZeroed check'. + // TODO-RV64: this should be resolved before calling `genPushCalleeSavedRegisters`. + genStackPointerAdjustment(-totalFrameSize, REG_SCRATCH, nullptr, /* reportUnwindData */ true); } + GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); - JITDUMP(" offset=%d, calleeSaveSPDelta=%d\n", offset, calleeSaveSPDelta); - - genSaveCalleeSavedRegistersHelp(rsPushRegs, offset, 0); - offset += (int)(genCountBits(rsPushRegs) << 3); // each reg has 8 bytes + GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - // From now on, we can safely use initReg. + genSaveCalleeSavedRegistersHelp(rsPushRegs, FP_offset + 16, 0); - emit->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_RA, REG_SPBASE, offset); - compiler->unwindSaveReg(REG_RA, offset); - - emit->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_FP, REG_SPBASE, offset + 8); - compiler->unwindSaveReg(REG_FP, offset + 8); - - JITDUMP(" offsetSpToSavedFp=%d\n", offset + 8); - genEstablishFramePointer(offset + 8, /* reportUnwindData */ true); + JITDUMP(" offsetSpToSavedFp=%d\n", FP_offset); + genEstablishFramePointer(FP_offset, /* reportUnwindData */ true); // For varargs, home the incoming arg registers last. Note that there is nothing to unwind here, // so we just report "NOP" unwind codes. If there's no more frame setup after this, we don't @@ -7935,18 +7693,9 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe NYI_RISCV64("genPushCalleeSavedRegisters unsupports compIsVarArgs"); } -#ifdef DEBUG - if (compiler->opts.disAsm) + if (leftFrameSize != 0) { - printf("DEBUG: RISCV64, frameType:%d\n\n", frameType); - } -#endif - - if (calleeSaveSPDelta != 0) - { - assert(frameType == 2); - calleeSaveSPDelta = totalFrameSize - calleeSaveSPDelta; - genStackPointerAdjustment(-calleeSaveSPDelta, initReg, pInitRegZeroed, /* reportUnwindData */ true); + genStackPointerAdjustment(-leftFrameSize, REG_SCRATCH, nullptr, /* reportUnwindData */ true); } } @@ -7956,80 +7705,72 @@ void CodeGen::genPopCalleeSavedRegisters(bool jmpEpilog) regMaskTP regsToRestoreMask = regSet.rsGetModifiedCalleeSavedRegsMask(); - // On RV64 we always use the FP (frame-pointer) assert(isFramePointerUsed()); - int totalFrameSize = genTotalFrameSize(); - int remainingSPSize = totalFrameSize; - int callerSPtoFPdelta = 0; - int calleeSaveSPOffset = 0; // This will be the starting place for restoring - // the callee-saved registers, in decreasing order. + int totalFrameSize = genTotalFrameSize(); + int localFrameSize = compiler->compLclFrameSize; + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + localFrameSize -= TARGET_POINTER_SIZE; + } + if ((compiler->lvaMonAcquired != BAD_VAR_NUM) && !compiler->opts.IsOSR()) + { + localFrameSize -= TARGET_POINTER_SIZE; + } - emitter* emit = GetEmitter(); + JITDUMP("Frame type. #outsz=%d; #framesz=%d; #calleeSaveRegsPushed:%d; " + "localloc? %s\n", + unsigned(compiler->lvaOutgoingArgSpaceSize), totalFrameSize, compiler->compCalleeRegsPushed, + dspBool(compiler->compLocallocUsed)); - // ensure offset of sd/ld + emitter* emit = GetEmitter(); + int FP_offset = localFrameSize; + int remainingSPSize = totalFrameSize; if (totalFrameSize <= 2040) { - JITDUMP("Frame type 1. #outsz=%d; #framesz=%d; localloc? %s\n", unsigned(compiler->lvaOutgoingArgSpaceSize), - totalFrameSize, dspBool(compiler->compLocallocUsed)); - if (compiler->compLocallocUsed) { - callerSPtoFPdelta = (compiler->compCalleeRegsPushed << 3) - 8 + compiler->lvaOutgoingArgSpaceSize; + int SPtoFPdelta = genSPtoFPdelta(); + // Restore sp from fp + emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); + compiler->unwindSetFrameReg(REG_FPBASE, SPtoFPdelta); } - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize; - // remainingSPSize = totalFrameSize; } else { - JITDUMP("Frame type 2. #outsz=%d; #framesz=%d; calleeSaveRegsPushed: %d; localloc? %s\n", - unsigned(compiler->lvaOutgoingArgSpaceSize), totalFrameSize, compiler->compCalleeRegsPushed, - dspBool(compiler->compLocallocUsed)); - - if ((compiler->lvaOutgoingArgSpaceSize + (compiler->compCalleeRegsPushed << 3)) > 2047) + if (compiler->compLocallocUsed) { - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize & 0xfffffff0; - - if (compiler->compLocallocUsed) + int SPtoFPdelta = genSPtoFPdelta(); + // Restore sp from fp + if (emitter::isValidSimm12(SPtoFPdelta)) { - callerSPtoFPdelta = (compiler->compCalleeRegsPushed << 3) - 8; + emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); } else { - genStackPointerAdjustment(calleeSaveSPOffset, REG_RA, nullptr, /* reportUnwindData */ true); + regNumber tempReg = rsGetRsvdReg(); + emit->emitLoadImmediate(EA_PTRSIZE, tempReg, SPtoFPdelta); + emit->emitIns_R_R_R(INS_sub, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, tempReg); } - remainingSPSize = totalFrameSize - calleeSaveSPOffset; - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize - calleeSaveSPOffset; } - else + if ((localFrameSize + (compiler->compCalleeRegsPushed << 3)) > 2040) { - if (compiler->compLocallocUsed) - { - callerSPtoFPdelta = (compiler->compCalleeRegsPushed << 3) - 8 + compiler->lvaOutgoingArgSpaceSize; - } - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize; - // remainingSPSize = totalFrameSize; - } - } + remainingSPSize = localFrameSize & -16; + genStackPointerAdjustment(remainingSPSize, REG_RA, nullptr, /* reportUnwindData */ true); - if (compiler->compLocallocUsed) - { - // restore sp form fp: addi sp, -#callerSPtoFPdelta(fp) - emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -callerSPtoFPdelta); - compiler->unwindSetFrameReg(REG_FPBASE, callerSPtoFPdelta); + remainingSPSize = totalFrameSize - remainingSPSize; + FP_offset = localFrameSize & 0xf; + } } - JITDUMP(" calleeSaveSPOffset=%d, callerSPtoFPdelta=%d\n", calleeSaveSPOffset, callerSPtoFPdelta); - genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, calleeSaveSPOffset, 0); - - // restore ra/fp regs - calleeSaveSPOffset += (compiler->compCalleeRegsPushed - 2) << 3; + JITDUMP(" calleeSaveSPOffset=%d\n", FP_offset + 16); + genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, FP_offset + 16, 0); - emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_RA, REG_SPBASE, calleeSaveSPOffset); - compiler->unwindSaveReg(REG_RA, calleeSaveSPOffset); + emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_RA, REG_SPBASE, FP_offset + 8); + compiler->unwindSaveReg(REG_RA, FP_offset + 8); - emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_FP, REG_SPBASE, calleeSaveSPOffset + 8); - compiler->unwindSaveReg(REG_FP, calleeSaveSPOffset + 8); + emit->emitIns_R_R_I(INS_ld, EA_PTRSIZE, REG_FP, REG_SPBASE, FP_offset); + compiler->unwindSaveReg(REG_FP, FP_offset); if (emitter::isValidUimm11(remainingSPSize)) { @@ -8043,7 +7784,7 @@ void CodeGen::genPopCalleeSavedRegisters(bool jmpEpilog) } compiler->unwindAllocStack(remainingSPSize); - // for OSR we have to adjust SP to remove tier0 frame + // For OSR, we must also adjust the SP to remove the Tier0 frame. if (compiler->opts.IsOSR()) { const int tier0FrameSize = compiler->info.compPatchpointInfo->TotalFrameSize(); @@ -8063,448 +7804,6 @@ void CodeGen::genPopCalleeSavedRegisters(bool jmpEpilog) } } -void CodeGen::genFnPrologCalleeRegArgs() -{ - assert(!(intRegState.rsCalleeRegArgMaskLiveIn & floatRegState.rsCalleeRegArgMaskLiveIn)); - - regMaskTP regArgMaskLive = intRegState.rsCalleeRegArgMaskLiveIn | floatRegState.rsCalleeRegArgMaskLiveIn; - -#ifdef DEBUG - if (verbose) - { - printf("*************** In genFnPrologCalleeRegArgs() RISCV64:0x%llx.\n", regArgMaskLive); - } -#endif - - // We should be generating the prolog block when we are called - assert(compiler->compGeneratingProlog); - - // We expect to have some registers of the type we are doing, that are LiveIn, otherwise we don't need to be called. - noway_assert(regArgMaskLive != 0); - - unsigned varNum; - unsigned regArgNum = 0; - // Process any rearrangements including circular dependencies. - regNumber regArg[MAX_REG_ARG + MAX_FLOAT_REG_ARG]; - regNumber regArgInit[MAX_REG_ARG + MAX_FLOAT_REG_ARG]; - emitAttr regArgAttr[MAX_REG_ARG + MAX_FLOAT_REG_ARG]; - - for (int i = 0; i < MAX_REG_ARG + MAX_FLOAT_REG_ARG; i++) - { - regArg[i] = REG_NA; - -#ifdef DEBUG - regArgInit[i] = REG_NA; - regArgAttr[i] = EA_UNKNOWN; -#endif - } - - for (varNum = 0; varNum < compiler->lvaCount; ++varNum) - { - LclVarDsc* varDsc = compiler->lvaTable + varNum; - - // Is this variable a register arg? - if (!varDsc->lvIsParam) - { - continue; - } - - if (!varDsc->lvIsRegArg) - { - continue; - } - - if (varDsc->lvIsInReg()) - { - assert(genIsValidIntReg(varDsc->GetArgReg()) || genIsValidFloatReg(varDsc->GetArgReg())); - assert(!(genIsValidIntReg(varDsc->GetOtherArgReg()) || genIsValidFloatReg(varDsc->GetOtherArgReg()))); - if (varDsc->GetArgInitReg() != varDsc->GetArgReg()) - { - if (genIsValidIntReg(varDsc->GetArgInitReg())) - { - if (varDsc->GetArgInitReg() > REG_ARG_LAST) - { - bool isSkip; - instruction ins; - emitAttr size; - if (genIsValidIntReg(varDsc->GetArgReg())) - { - ins = INS_mov; - if (varDsc->TypeGet() == TYP_INT) - { - size = EA_4BYTE; - isSkip = false; - } - else - { - size = EA_PTRSIZE; - isSkip = true; - } - } - else - { - ins = INS_fmv_x_d; - size = EA_PTRSIZE; - isSkip = true; - } - GetEmitter()->emitIns_Mov(ins, size, varDsc->GetArgInitReg(), varDsc->GetArgReg(), isSkip); - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - } - else - { - if (genIsValidIntReg(varDsc->GetArgReg())) - { - assert(isValidIntArgReg(varDsc->GetArgReg(), compiler->info.compCallConv)); - regArg[varDsc->GetArgReg() - REG_ARG_FIRST] = varDsc->GetArgReg(); - regArgInit[varDsc->GetArgReg() - REG_ARG_FIRST] = varDsc->GetArgInitReg(); - regArgAttr[varDsc->GetArgReg() - REG_ARG_FIRST] = - varDsc->TypeGet() == TYP_INT ? EA_4BYTE : EA_PTRSIZE; - } - else - { - assert(isValidFloatArgReg(varDsc->GetArgReg())); - regArg[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = varDsc->GetArgReg(); - regArgInit[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = varDsc->GetArgInitReg(); - regArgAttr[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = - varDsc->TypeGet() == TYP_FLOAT ? EA_4BYTE : EA_PTRSIZE; - } - regArgNum++; - } - } - else - { - assert(genIsValidFloatReg(varDsc->GetArgInitReg())); - if (genIsValidIntReg(varDsc->GetArgReg())) - { - emitAttr size = (varDsc->TypeGet() == TYP_FLOAT) ? EA_4BYTE : EA_PTRSIZE; - GetEmitter()->emitIns_Mov(size, varDsc->GetArgInitReg(), varDsc->GetArgReg(), false); - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - } - else if (varDsc->GetArgInitReg() > REG_ARG_FP_LAST) - { - GetEmitter()->emitIns_Mov(INS_fsgnj_d, EA_PTRSIZE, varDsc->GetArgInitReg(), varDsc->GetArgReg(), - true); - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - } - else - { - assert(isValidFloatArgReg(varDsc->GetArgReg())); - regArg[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = varDsc->GetArgReg(); - regArgInit[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = varDsc->GetArgInitReg(); - regArgAttr[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = - varDsc->TypeGet() == TYP_FLOAT ? EA_4BYTE : EA_PTRSIZE; - regArgNum++; - } - } - } - else - { - // TODO-RISCV64: should delete this by optimization "struct {long a; int32_t b;};" - // liking AMD64_ABI within morph. - if (genIsValidIntReg(varDsc->GetArgReg()) && (varDsc->TypeGet() == TYP_INT)) - { - GetEmitter()->emitIns_Mov(INS_mov, EA_4BYTE, varDsc->GetArgInitReg(), varDsc->GetArgReg(), false); - } - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - } -#ifdef USING_SCOPE_INFO - psiMoveToReg(varNum); -#endif // USING_SCOPE_INFO - if (!varDsc->lvLiveInOutOfHndlr) - { - continue; - } - } - - // When we have a promoted struct we have two possible LclVars that can represent the incoming argument - // in the regArgTab[], either the original TYP_STRUCT argument or the introduced lvStructField. - // We will use the lvStructField if we have a TYPE_INDEPENDENT promoted struct field otherwise - // use the original TYP_STRUCT argument. - // - if (varDsc->lvPromoted || varDsc->lvIsStructField) - { - LclVarDsc* parentVarDsc = varDsc; - if (varDsc->lvIsStructField) - { - assert(!varDsc->lvPromoted); - parentVarDsc = &compiler->lvaTable[varDsc->lvParentLcl]; - } - - Compiler::lvaPromotionType promotionType = compiler->lvaGetPromotionType(parentVarDsc); - - if (promotionType == Compiler::PROMOTION_TYPE_INDEPENDENT) - { - // For register arguments that are independent promoted structs we put the promoted field varNum - // in the regArgTab[] - if (varDsc->lvPromoted) - { - continue; - } - } - else - { - // For register arguments that are not independent promoted structs we put the parent struct varNum - // in the regArgTab[] - if (varDsc->lvIsStructField) - { - continue; - } - } - } - - var_types storeType = TYP_UNDEF; - int slotSize = TARGET_POINTER_SIZE; - - if (varTypeIsStruct(varDsc)) - { - if (emitter::isFloatReg(varDsc->GetArgReg())) - { - storeType = varDsc->lvIs4Field1 ? TYP_FLOAT : TYP_DOUBLE; - } - else - { - assert(emitter::isGeneralRegister(varDsc->GetArgReg())); - if (varDsc->lvIs4Field1) - { - storeType = TYP_INT; - } - else - { - storeType = varDsc->GetLayout()->GetGCPtrType(0); - } - } - slotSize = (int)EA_SIZE(emitActualTypeSize(storeType)); - -#if FEATURE_MULTIREG_ARGS - // Must be <= MAX_PASS_MULTIREG_BYTES or else it wouldn't be passed in registers - noway_assert(varDsc->lvSize() <= MAX_PASS_MULTIREG_BYTES); -#endif - } - else // Not a struct type - { - storeType = compiler->mangleVarArgsType(genActualType(varDsc->TypeGet())); - if (emitter::isFloatReg(varDsc->GetArgReg()) != varTypeIsFloating(storeType)) - { - assert(varTypeIsFloating(storeType)); - storeType = storeType == TYP_DOUBLE ? TYP_I_IMPL : TYP_INT; - } - } - emitAttr size = emitActualTypeSize(storeType); - - regNumber srcRegNum = varDsc->GetArgReg(); - - // Stack argument - if the ref count is 0 don't care about it - if (!varDsc->lvOnFrame) - { - noway_assert(varDsc->lvRefCnt() == 0); - regArgMaskLive &= ~genRegMask(varDsc->GetArgReg()); - if (varDsc->GetOtherArgReg() < REG_STK) - { - regArgMaskLive &= ~genRegMask(varDsc->GetOtherArgReg()); - } - } - else - { - assert(srcRegNum != varDsc->GetOtherArgReg()); - - regNumber tmpReg = REG_NA; - - bool FPbased; - int baseOffset = compiler->lvaFrameAddress(varNum, &FPbased); - - // First store the `varDsc->GetArgReg()` on stack. - if (emitter::isValidSimm12(baseOffset)) - { - GetEmitter()->emitIns_S_R(ins_Store(storeType), size, srcRegNum, varNum, 0); - } - else - { - assert(tmpReg == REG_NA); - - tmpReg = REG_RA; - // Prepare tmpReg to possible future use - GetEmitter()->emitLoadImmediate(EA_PTRSIZE, tmpReg, baseOffset); - GetEmitter()->emitIns_R_R_R(INS_add, EA_PTRSIZE, tmpReg, tmpReg, FPbased ? REG_FPBASE : REG_SPBASE); - GetEmitter()->emitIns_S_R_R(ins_Store(storeType), size, srcRegNum, tmpReg, varNum, 0); - } - - regArgMaskLive &= ~genRegMask(srcRegNum); - - // Then check if varDsc is a struct arg - if (varTypeIsStruct(varDsc)) - { - if (emitter::isFloatReg(varDsc->GetOtherArgReg())) - { - srcRegNum = varDsc->GetOtherArgReg(); - storeType = varDsc->lvIs4Field2 ? TYP_FLOAT : TYP_DOUBLE; - size = EA_SIZE(emitActualTypeSize(storeType)); - - slotSize = slotSize < (int)size ? (int)size : slotSize; - } - else if (emitter::isGeneralRegister(varDsc->GetOtherArgReg())) - { - if (varDsc->lvIs4Field2) - { - storeType = TYP_INT; - } - else - { - storeType = varDsc->GetLayout()->GetGCPtrType(1); - } - - srcRegNum = varDsc->GetOtherArgReg(); - size = emitActualTypeSize(storeType); - - slotSize = slotSize < (int)EA_SIZE(size) ? (int)EA_SIZE(size) : slotSize; - } - baseOffset += slotSize; - - // if the struct passed by two register, then store the second register `varDsc->GetOtherArgReg()`. - if (srcRegNum == varDsc->GetOtherArgReg()) - { - GetEmitter()->emitIns_S_R_R(ins_Store(storeType), size, srcRegNum, tmpReg, varNum, slotSize); - regArgMaskLive &= ~genRegMask(srcRegNum); // maybe do this later is better! - } - else if (varDsc->lvIsSplit) - { - // the struct is a split struct. - assert(varDsc->GetArgReg() == REG_ARG_LAST && varDsc->GetOtherArgReg() == REG_STK); - - // For the RISCV64's ABI, the split struct arg will be passed via `A7` and a stack slot on caller. - // But if the `A7` is stored on stack on the callee side, the whole split struct should be - // stored continuous on the stack on the callee side. - // So, after we save `A7` on the stack in prolog, it has to copy the stack slot of the split struct - // which was passed by the caller. Here we load the stack slot to `REG_SCRATCH`, and save it - // on the stack following the `A7` in prolog. - if (emitter::isValidSimm12(genTotalFrameSize())) - { - GetEmitter()->emitIns_R_R_I(INS_ld, size, REG_SCRATCH, REG_SPBASE, genTotalFrameSize()); - } - else - { - assert(!EA_IS_RELOC(size)); - GetEmitter()->emitLoadImmediate(size, REG_SCRATCH, genTotalFrameSize()); - GetEmitter()->emitIns_R_R_R(INS_add, size, REG_SCRATCH, REG_SCRATCH, REG_SPBASE); - GetEmitter()->emitIns_R_R_I(INS_ld, size, REG_SCRATCH, REG_SCRATCH, 0); - } - - GetEmitter()->emitIns_S_R_R(ins_Store(storeType), size, REG_SCRATCH, tmpReg, varNum, slotSize); - } - } - -#ifdef USING_SCOPE_INFO - { - psiMoveToStack(varNum); - } -#endif // USING_SCOPE_INFO - } - } - - if (regArgNum > 0) - { - for (int i = MAX_REG_ARG + MAX_FLOAT_REG_ARG - 1; i >= 0; i--) - { - if (regArg[i] != REG_NA && !isValidIntArgReg(regArgInit[i], compiler->info.compCallConv) && - !isValidFloatArgReg(regArgInit[i])) - { - assert(regArg[i] != regArgInit[i]); - assert(isValidIntArgReg(regArg[i], compiler->info.compCallConv) || isValidFloatArgReg(regArg[i])); - - GetEmitter()->emitIns_Mov(regArgAttr[i], regArgInit[i], regArg[i], false); - - regArgMaskLive &= ~genRegMask(regArg[i]); - regArg[i] = REG_NA; - regArgNum -= 1; - } - } - } - - if (regArgNum > 0) - { - for (int i = MAX_REG_ARG + MAX_FLOAT_REG_ARG - 1; i >= 0; i--) - { - if (regArg[i] != REG_NA) - { - assert(regArg[i] != regArgInit[i]); - - // regArg indexes list - unsigned indexList[MAX_REG_ARG + MAX_FLOAT_REG_ARG]; - int count = 0; // Number of nodes in list - bool loop = false; // List has a loop - - for (unsigned cur = i; regArg[cur] != REG_NA; count++) - { - if (cur == i && count > 0) - { - loop = true; - break; - } - - indexList[count] = cur; - - for (int count2 = 0; count2 < count; count2++) - { - // The list could not have backlinks except last to first case which handled above. - assert(cur != indexList[count2] && "Attempt to move several values on same register."); - } - assert(cur < MAX_REG_ARG + MAX_FLOAT_REG_ARG); - assert(isValidIntArgReg(regArg[cur], compiler->info.compCallConv) || - isValidFloatArgReg(regArg[cur])); - - if (isValidIntArgReg(regArgInit[cur], compiler->info.compCallConv)) - { - cur = regArgInit[cur] - REG_ARG_FIRST; - } - else if (isValidFloatArgReg(regArgInit[cur])) - { - cur = regArgInit[cur] - REG_ARG_FP_FIRST + MAX_REG_ARG; - } - else - { - assert(!"Argument register is neither valid float nor valid int argument register"); - } - } - - if (loop) - { - unsigned tmpArg = indexList[count - 1]; - - GetEmitter()->emitIns_Mov(regArgAttr[tmpArg], rsGetRsvdReg(), regArg[tmpArg], false); - count--; // Decrease count to not access last node which regArgInit points to start node i - assert(count > 0); - } - - for (int cur = count - 1; cur >= 0; cur--) - { - unsigned tmpArg = indexList[cur]; - - GetEmitter()->emitIns_Mov(regArgAttr[tmpArg], regArgInit[tmpArg], regArg[tmpArg], false); - - regArgMaskLive &= ~genRegMask(regArg[tmpArg]); - regArg[tmpArg] = REG_NA; - regArgNum--; - assert(regArgNum >= 0); - }; - - if (loop) - { - unsigned tmpArg = indexList[count]; // count was decreased for loop case - - GetEmitter()->emitIns_Mov(regArgAttr[i], regArg[tmpArg], rsGetRsvdReg(), false); - - regArgMaskLive &= ~genRegMask(regArg[tmpArg]); - regArg[tmpArg] = REG_NA; - regArgNum--; - } - assert(regArgNum >= 0); - } - } - } - - assert(regArgNum == 0); - assert(!regArgMaskLive); -} - #ifdef PROFILING_SUPPORTED //----------------------------------------------------------------------------------- // genProfilingEnterCallback: Generate the profiling function enter callback. diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 3e5f1a4b38a6..64c2b84e87b4 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -467,16 +467,16 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, simd_t { assert(compiler->compIsaSupportedDebugOnly(InstructionSet_AVX512F)); emit->emitIns_SIMD_R_R_R_I(INS_vpternlogd, attr, targetReg, targetReg, targetReg, - static_cast(0xFF)); + static_cast(0xFF), INS_OPTS_NONE); } else { - emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, EA_16BYTE, targetReg, targetReg, targetReg); + emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, EA_16BYTE, targetReg, targetReg, targetReg, INS_OPTS_NONE); } } else if (val8.IsZero()) { - emit->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, targetReg, targetReg, targetReg); + emit->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, targetReg, targetReg, targetReg, INS_OPTS_NONE); } else { @@ -494,16 +494,16 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, simd_t { assert(compiler->compIsaSupportedDebugOnly(InstructionSet_AVX512F)); emit->emitIns_SIMD_R_R_R_I(INS_vpternlogd, attr, targetReg, targetReg, targetReg, - static_cast(0xFF)); + static_cast(0xFF), INS_OPTS_NONE); } else { - emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, EA_16BYTE, targetReg, targetReg, targetReg); + emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, EA_16BYTE, targetReg, targetReg, targetReg, INS_OPTS_NONE); } } else if (val12.IsZero()) { - emit->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, targetReg, targetReg, targetReg); + emit->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, targetReg, targetReg, targetReg, INS_OPTS_NONE); } else { @@ -523,16 +523,16 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, simd_t { assert(compiler->compIsaSupportedDebugOnly(InstructionSet_AVX512F)); emit->emitIns_SIMD_R_R_R_I(INS_vpternlogd, attr, targetReg, targetReg, targetReg, - static_cast(0xFF)); + static_cast(0xFF), INS_OPTS_NONE); } else { - emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, attr, targetReg, targetReg, targetReg); + emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, attr, targetReg, targetReg, targetReg, INS_OPTS_NONE); } } else if (val16.IsZero()) { - emit->emitIns_SIMD_R_R_R(INS_xorps, attr, targetReg, targetReg, targetReg); + emit->emitIns_SIMD_R_R_R(INS_xorps, attr, targetReg, targetReg, targetReg, INS_OPTS_NONE); } else { @@ -550,16 +550,16 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, simd_t { assert(compiler->compIsaSupportedDebugOnly(InstructionSet_AVX512F)); emit->emitIns_SIMD_R_R_R_I(INS_vpternlogd, attr, targetReg, targetReg, targetReg, - static_cast(0xFF)); + static_cast(0xFF), INS_OPTS_NONE); } else { - emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, attr, targetReg, targetReg, targetReg); + emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, attr, targetReg, targetReg, targetReg, INS_OPTS_NONE); } } else if (val32.IsZero()) { - emit->emitIns_SIMD_R_R_R(INS_xorps, attr, targetReg, targetReg, targetReg); + emit->emitIns_SIMD_R_R_R(INS_xorps, attr, targetReg, targetReg, targetReg, INS_OPTS_NONE); } else { @@ -574,7 +574,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, simd_t if (val64.IsAllBitsSet() && compiler->compOpportunisticallyDependsOn(InstructionSet_AVX512F)) { emit->emitIns_SIMD_R_R_R_I(INS_vpternlogd, attr, targetReg, targetReg, targetReg, - static_cast(0xFF)); + static_cast(0xFF), INS_OPTS_NONE); } else if (val64.IsZero()) { @@ -584,7 +584,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, simd_t // xorps zmm0, zmm0, zmm0 (6 bytes) // xorps ymm0, ymm0, ymm0 (4 bytes) // - emit->emitIns_SIMD_R_R_R(INS_xorps, EA_32BYTE, targetReg, targetReg, targetReg); + emit->emitIns_SIMD_R_R_R(INS_xorps, EA_32BYTE, targetReg, targetReg, targetReg, INS_OPTS_NONE); } else { @@ -661,7 +661,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre if (tree->IsFloatPositiveZero()) { // A faster/smaller way to generate Zero - emit->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, targetReg, targetReg, targetReg); + emit->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, targetReg, targetReg, targetReg, INS_OPTS_NONE); } else if (tree->IsFloatAllBitsSet()) { @@ -669,12 +669,12 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre { assert(compiler->compIsaSupportedDebugOnly(InstructionSet_AVX512F)); emit->emitIns_SIMD_R_R_R_I(INS_vpternlogd, EA_16BYTE, targetReg, targetReg, targetReg, - static_cast(0xFF)); + static_cast(0xFF), INS_OPTS_NONE); } else { // A faster/smaller way to generate AllBitsSet - emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, EA_16BYTE, targetReg, targetReg, targetReg); + emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, EA_16BYTE, targetReg, targetReg, targetReg, INS_OPTS_NONE); } } else @@ -914,7 +914,7 @@ void CodeGen::genCodeForLongUMod(GenTreeOp* node) // xor edx, edx // div divisor->GetRegNum() // mov eax, temp - const regNumber tempReg = node->GetSingleTempReg(); + const regNumber tempReg = internalRegisters.GetSingle(node); inst_Mov(TYP_INT, tempReg, REG_EAX, /* canSkip */ false); inst_Mov(TYP_INT, REG_EAX, REG_EDX, /* canSkip */ false); instGen_Set_Reg_To_Zero(EA_PTRSIZE, REG_EDX); @@ -1366,7 +1366,7 @@ void CodeGen::genSIMDSplitReturn(GenTree* src, ReturnTypeDesc* retTypeDesc) inst_Mov(TYP_SIMD16, reg0, opReg, /* canSkip */ true); // Move upper 64-bits of opReg into reg1 - GetEmitter()->emitIns_SIMD_R_R_R(INS_movhlps, EA_16BYTE, reg1, reg1, opReg); + GetEmitter()->emitIns_SIMD_R_R_R(INS_movhlps, EA_16BYTE, reg1, reg1, opReg, INS_OPTS_NONE); #else // TARGET_X86 assert(src->TypeIs(TYP_SIMD8)); assert(srcIsFloatReg != dstIsFloatReg); @@ -1378,14 +1378,14 @@ void CodeGen::genSIMDSplitReturn(GenTree* src, ReturnTypeDesc* retTypeDesc) // reg1 = opRef[61:32] if (compiler->compOpportunisticallyDependsOn(InstructionSet_SSE41)) { - inst_RV_TT_IV(INS_pextrd, EA_4BYTE, reg1, src, 1); + inst_RV_TT_IV(INS_pextrd, EA_4BYTE, reg1, src, 1, INS_OPTS_NONE); } else { bool isRMW = !compiler->canUseVexEncoding(); int8_t shuffleMask = 1; // we only need [61:32]->[31:0], the rest is not read. - inst_RV_RV_TT_IV(INS_pshufd, EA_8BYTE, opReg, opReg, src, shuffleMask, isRMW); + inst_RV_RV_TT_IV(INS_pshufd, EA_8BYTE, opReg, opReg, src, shuffleMask, isRMW, INS_OPTS_NONE); inst_Mov(TYP_INT, reg1, opReg, /* canSkip */ false); } #endif // TARGET_X86 @@ -1402,13 +1402,15 @@ void CodeGen::genSIMDSplitReturn(GenTree* src, ReturnTypeDesc* retTypeDesc) // // Arguments: // treeNode - The GT_RETURN or GT_RETFILT tree node with float type. +// (We don't expect treeNode to be a GT_SWIFT_ERROR_RET node, +// as Swift interop isn't supported on x86.) // // Return Value: // None // void CodeGen::genFloatReturn(GenTree* treeNode) { - assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT); + assert(treeNode->OperIs(GT_RETURN, GT_RETFILT)); assert(varTypeIsFloating(treeNode)); GenTree* op1 = treeNode->gtGetOp1(); @@ -1759,7 +1761,7 @@ void CodeGen::genCodeForReturnTrap(GenTreeOp* tree) inst_JMP(EJ_je, skipLabel); // emit the call to the EE-helper that stops for GC (or other reasons) - regNumber tmpReg = tree->GetSingleTempReg(RBM_ALLINT); + regNumber tmpReg = internalRegisters.GetSingle(tree, RBM_ALLINT); assert(genIsValidIntReg(tmpReg)); genEmitHelperCall(CORINFO_HELP_STOP_FOR_GC, 0, EA_UNKNOWN, tmpReg); @@ -1966,6 +1968,12 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) genReturn(treeNode); break; +#ifdef SWIFT_SUPPORT + case GT_SWIFT_ERROR_RET: + genSwiftErrorReturn(treeNode); + break; +#endif // SWIFT_SUPPORT + case GT_LEA: // If we are here, it is the case where there is an LEA that cannot be folded into a parent instruction. genLeaInstruction(treeNode->AsAddrMode()); @@ -2075,7 +2083,7 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) break; case GT_JMP: - genJmpMethod(treeNode); + genJmpPlaceArgs(treeNode); break; case GT_LOCKADD: @@ -2286,7 +2294,7 @@ void CodeGen::genMultiRegStoreToSIMDLocal(GenTreeLclVar* lclNode) if (targetReg != reg1) { - GetEmitter()->emitIns_SIMD_R_R_R(INS_movlhps, EA_16BYTE, targetReg, reg0, reg1); + GetEmitter()->emitIns_SIMD_R_R_R(INS_movlhps, EA_16BYTE, targetReg, reg0, reg1, INS_OPTS_NONE); } else { @@ -2303,8 +2311,8 @@ void CodeGen::genMultiRegStoreToSIMDLocal(GenTreeLclVar* lclNode) // and next swap low and high 8-bytes of targetReg to have them // rearranged in the right order. - GetEmitter()->emitIns_SIMD_R_R_R(INS_movlhps, EA_16BYTE, targetReg, reg1, reg0); - GetEmitter()->emitIns_SIMD_R_R_R_I(INS_shufpd, EA_16BYTE, targetReg, targetReg, reg1, 0x01); + GetEmitter()->emitIns_SIMD_R_R_R(INS_movlhps, EA_16BYTE, targetReg, reg1, reg0, INS_OPTS_NONE); + GetEmitter()->emitIns_SIMD_R_R_R_I(INS_shufpd, EA_16BYTE, targetReg, targetReg, reg1, 0x01, INS_OPTS_NONE); } genProduceReg(lclNode); #elif defined(TARGET_X86) @@ -2322,14 +2330,14 @@ void CodeGen::genMultiRegStoreToSIMDLocal(GenTreeLclVar* lclNode) const emitAttr size = emitTypeSize(TYP_SIMD8); if (compiler->compOpportunisticallyDependsOn(InstructionSet_SSE41)) { - GetEmitter()->emitIns_SIMD_R_R_R_I(INS_pinsrd, size, targetReg, targetReg, reg1, 1); + GetEmitter()->emitIns_SIMD_R_R_R_I(INS_pinsrd, size, targetReg, targetReg, reg1, 1, INS_OPTS_NONE); } else { - regNumber tempXmm = lclNode->GetSingleTempReg(); + regNumber tempXmm = internalRegisters.GetSingle(lclNode); assert(tempXmm != targetReg); inst_Mov(TYP_FLOAT, tempXmm, reg1, /* canSkip */ false); - GetEmitter()->emitIns_SIMD_R_R_R(INS_punpckldq, size, targetReg, targetReg, tempXmm); + GetEmitter()->emitIns_SIMD_R_R_R(INS_punpckldq, size, targetReg, targetReg, tempXmm, INS_OPTS_NONE); } genProduceReg(lclNode); } @@ -2667,7 +2675,7 @@ void CodeGen::genCodeForMemmove(GenTreeBlk* tree) if ((size >= simdSize) && (simdSize > 0)) { // Number of SIMD regs needed to save the whole src to regs. - unsigned numberOfSimdRegs = tree->AvailableTempRegCount(RBM_ALLFLOAT); + unsigned numberOfSimdRegs = internalRegisters.Count(tree, RBM_ALLFLOAT); // Lowering takes care to only introduce this node such that we will always have enough // temporary SIMD registers to fully load the source and avoid any potential issues with overlap. @@ -2677,7 +2685,7 @@ void CodeGen::genCodeForMemmove(GenTreeBlk* tree) regNumber tempRegs[LinearScan::MaxInternalCount] = {}; for (unsigned i = 0; i < numberOfSimdRegs; i++) { - tempRegs[i] = tree->ExtractTempReg(RBM_ALLFLOAT); + tempRegs[i] = internalRegisters.Extract(tree, RBM_ALLFLOAT); } auto emitSimdLoadStore = [&](bool load) { @@ -2762,15 +2770,15 @@ void CodeGen::genCodeForMemmove(GenTreeBlk* tree) unsigned loadStoreSize = 1 << BitOperations::Log2(size); if (loadStoreSize == size) { - regNumber tmpReg = tree->GetSingleTempReg(RBM_ALLINT); + regNumber tmpReg = internalRegisters.GetSingle(tree, RBM_ALLINT); emitScalarLoadStore(/* load */ true, loadStoreSize, tmpReg, 0); emitScalarLoadStore(/* load */ false, loadStoreSize, tmpReg, 0); } else { - assert(tree->AvailableTempRegCount() == 2); - regNumber tmpReg1 = tree->ExtractTempReg(RBM_ALLINT); - regNumber tmpReg2 = tree->ExtractTempReg(RBM_ALLINT); + assert(internalRegisters.Count(tree) == 2); + regNumber tmpReg1 = internalRegisters.Extract(tree, RBM_ALLINT); + regNumber tmpReg2 = internalRegisters.Extract(tree, RBM_ALLINT); emitScalarLoadStore(/* load */ true, loadStoreSize, tmpReg1, 0); emitScalarLoadStore(/* load */ true, loadStoreSize, tmpReg2, size - loadStoreSize); emitScalarLoadStore(/* load */ false, loadStoreSize, tmpReg1, 0); @@ -2847,12 +2855,12 @@ void CodeGen::genLclHeap(GenTree* tree) // since we don't need any internal registers. if (compiler->info.compInitMem) { - assert(tree->AvailableTempRegCount() == 0); + assert(internalRegisters.Count(tree) == 0); regCnt = targetReg; } else { - regCnt = tree->GetSingleTempReg(); + regCnt = internalRegisters.GetSingle(tree); // Above, we put the size in targetReg. Now, copy it to our new temp register if necessary. inst_Mov(size->TypeGet(), regCnt, targetReg, /* canSkip */ true); @@ -2946,7 +2954,7 @@ void CodeGen::genLclHeap(GenTree* tree) // via BLK explicitly, so just bump the stack pointer. if ((amount >= compiler->eeGetPageSize()) || (TARGET_POINTER_SIZE == 4)) { - regCnt = tree->GetSingleTempReg(); + regCnt = internalRegisters.GetSingle(tree); instGen_Set_Reg_To_Imm(EA_PTRSIZE, regCnt, -(ssize_t)amount); genStackPointerDynamicAdjustmentWithProbe(regCnt); // lastTouchDelta is dynamic, and can be up to a page. So if we have outgoing arg space, @@ -2963,7 +2971,7 @@ void CodeGen::genLclHeap(GenTree* tree) } // We should not have any temp registers at this point. - assert(tree->AvailableTempRegCount() == 0); + assert(internalRegisters.Count(tree) == 0); if (compiler->info.compInitMem) { @@ -3223,10 +3231,22 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) assert(size <= INT32_MAX); assert(dstOffset < (INT32_MAX - static_cast(size))); + auto emitStore = [&](instruction ins, unsigned width, regNumber target) { + if (dstLclNum != BAD_VAR_NUM) + { + emit->emitIns_S_R(ins, EA_ATTR(width), target, dstLclNum, dstOffset); + } + else + { + emit->emitIns_ARX_R(ins, EA_ATTR(width), target, dstAddrBaseReg, dstAddrIndexReg, dstAddrIndexScale, + dstOffset); + } + }; + #ifdef FEATURE_SIMD if (willUseSimdMov) { - regNumber srcXmmReg = node->GetSingleTempReg(RBM_ALLFLOAT); + regNumber srcXmmReg = internalRegisters.GetSingle(node, RBM_ALLFLOAT); unsigned regSize = compiler->roundDownSIMDSize(size); var_types loadType = compiler->getSIMDTypeForSize(regSize); simd_t vecCon; @@ -3236,18 +3256,6 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) instruction simdMov = simdUnalignedMovIns(); unsigned bytesWritten = 0; - auto emitSimdMovs = [&]() { - if (dstLclNum != BAD_VAR_NUM) - { - emit->emitIns_S_R(simdMov, EA_ATTR(regSize), srcXmmReg, dstLclNum, dstOffset); - } - else - { - emit->emitIns_ARX_R(simdMov, EA_ATTR(regSize), srcXmmReg, dstAddrBaseReg, dstAddrIndexReg, - dstAddrIndexScale, dstOffset); - } - }; - while (bytesWritten < size) { if (bytesWritten + regSize > size) @@ -3256,7 +3264,7 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) break; } - emitSimdMovs(); + emitStore(simdMov, regSize, srcXmmReg); dstOffset += regSize; bytesWritten += regSize; } @@ -3271,10 +3279,71 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) // Rewind dstOffset so we can fit a vector for the while remainder dstOffset -= (regSize - size); - emitSimdMovs(); + emitStore(simdMov, regSize, srcXmmReg); size = 0; } } + else if (node->IsOnHeapAndContainsReferences() && ((internalRegisters.GetAll(node) & RBM_ALLFLOAT) != 0)) + { + // For block with GC refs we still can use SIMD, but only for continuous + // non-GC parts where atomicity guarantees are not that strict. + assert(!willUseSimdMov); + ClassLayout* layout = node->GetLayout(); + + regNumber simdZeroReg = REG_NA; + unsigned slots = layout->GetSlotCount(); + unsigned slot = 0; + while (slot < slots) + { + if (!layout->IsGCPtr(slot)) + { + // How many continuous non-GC slots do we have? + unsigned nonGcSlotCount = 0; + do + { + nonGcSlotCount++; + slot++; + } while ((slot < slots) && !layout->IsGCPtr(slot)); + + for (unsigned nonGcSlot = 0; nonGcSlot < nonGcSlotCount; nonGcSlot++) + { + // Are continuous nongc slots enough to use SIMD? + unsigned simdSize = compiler->roundDownSIMDSize((nonGcSlotCount - nonGcSlot) * REGSIZE_BYTES); + if (simdSize > 0) + { + // Initialize simdZeroReg with zero on demand + if (simdZeroReg == REG_NA) + { + simdZeroReg = internalRegisters.GetSingle(node, RBM_ALLFLOAT); + // SIMD16 is sufficient for any SIMD size + simd_t vecCon = {}; + genSetRegToConst(simdZeroReg, TYP_SIMD16, &vecCon); + } + + emitStore(simdUnalignedMovIns(), simdSize, simdZeroReg); + dstOffset += (int)simdSize; + nonGcSlot += (simdSize / REGSIZE_BYTES) - 1; + } + else + { + emitStore(INS_mov, REGSIZE_BYTES, srcIntReg); + dstOffset += REGSIZE_BYTES; + } + } + } + else + { + // GC slot - update atomically + emitStore(INS_mov, REGSIZE_BYTES, srcIntReg); + dstOffset += REGSIZE_BYTES; + slot++; + } + } + + // There are no trailing elements + assert((layout->GetSize() % TARGET_POINTER_SIZE) == 0); + size = 0; + } #endif // FEATURE_SIMD assert((srcIntReg != REG_NA) || (size == 0)); @@ -3290,15 +3359,7 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) for (; size > regSize; size -= regSize, dstOffset += regSize) { - if (dstLclNum != BAD_VAR_NUM) - { - emit->emitIns_S_R(INS_mov, EA_ATTR(regSize), srcIntReg, dstLclNum, dstOffset); - } - else - { - emit->emitIns_ARX_R(INS_mov, EA_ATTR(regSize), srcIntReg, dstAddrBaseReg, dstAddrIndexReg, - dstAddrIndexScale, dstOffset); - } + emitStore(INS_mov, regSize, srcIntReg); } // Handle the non-SIMD remainder by overlapping with previously processed data if needed @@ -3314,15 +3375,7 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) assert(shiftBack <= regSize); dstOffset -= shiftBack; - if (dstLclNum != BAD_VAR_NUM) - { - emit->emitIns_S_R(INS_mov, EA_ATTR(regSize), srcIntReg, dstLclNum, dstOffset); - } - else - { - emit->emitIns_ARX_R(INS_mov, EA_ATTR(regSize), srcIntReg, dstAddrBaseReg, dstAddrIndexReg, - dstAddrIndexScale, dstOffset); - } + emitStore(INS_mov, regSize, srcIntReg); } #else // TARGET_X86 for (unsigned regSize = REGSIZE_BYTES; size > 0; size -= regSize, dstOffset += regSize) @@ -3331,15 +3384,8 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) { regSize /= 2; } - if (dstLclNum != BAD_VAR_NUM) - { - emit->emitIns_S_R(INS_mov, EA_ATTR(regSize), srcIntReg, dstLclNum, dstOffset); - } - else - { - emit->emitIns_ARX_R(INS_mov, EA_ATTR(regSize), srcIntReg, dstAddrBaseReg, dstAddrIndexReg, - dstAddrIndexScale, dstOffset); - } + + emitStore(INS_mov, regSize, srcIntReg); } #endif } @@ -3384,7 +3430,7 @@ void CodeGen::genCodeForInitBlkLoop(GenTreeBlk* initBlkNode) // Extend liveness of dstReg in case if it gets killed by the store. gcInfo.gcMarkRegPtrVal(dstReg, dstNode->TypeGet()); - const regNumber offsetReg = initBlkNode->GetSingleTempReg(); + const regNumber offsetReg = internalRegisters.GetSingle(initBlkNode); instGen_Set_Reg_To_Imm(EA_PTRSIZE, offsetReg, size - TARGET_POINTER_SIZE); BasicBlock* loop = genCreateTempLabel(); @@ -3523,7 +3569,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) if ((size >= regSize) && (regSize > 0)) { - regNumber tempReg = node->GetSingleTempReg(RBM_ALLFLOAT); + regNumber tempReg = internalRegisters.GetSingle(node, RBM_ALLFLOAT); instruction simdMov = simdUnalignedMovIns(); @@ -3585,7 +3631,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) // Fill the remainder with normal loads/stores if (size > 0) { - regNumber tempReg = node->GetSingleTempReg(RBM_ALLINT); + regNumber tempReg = internalRegisters.GetSingle(node, RBM_ALLINT); #ifdef TARGET_AMD64 unsigned regSize = REGSIZE_BYTES; @@ -3870,11 +3916,11 @@ void CodeGen::genStructPutArgUnroll(GenTreePutArgStk* putArgNode) if (loadSize >= XMM_REGSIZE_BYTES) #endif { - xmmTmpReg = putArgNode->GetSingleTempReg(RBM_ALLFLOAT); + xmmTmpReg = internalRegisters.GetSingle(putArgNode, RBM_ALLFLOAT); } if ((loadSize % XMM_REGSIZE_BYTES) != 0) { - intTmpReg = putArgNode->GetSingleTempReg(RBM_ALLINT); + intTmpReg = internalRegisters.GetSingle(putArgNode, RBM_ALLINT); } #ifdef TARGET_X86 @@ -3926,7 +3972,7 @@ void CodeGen::genStructPutArgRepMovs(GenTreePutArgStk* putArgNode) // Make sure we got the arguments of the cpblk operation in the right registers, and that // 'src' is contained as expected. - assert(putArgNode->gtRsvdRegs == (RBM_RDI | RBM_RCX | RBM_RSI)); + assert(internalRegisters.GetAll(putArgNode) == (RBM_RDI | RBM_RCX | RBM_RSI)); assert(src->isContained()); genConsumePutStructArgStk(putArgNode, REG_RDI, REG_RSI, REG_RCX); @@ -4156,7 +4202,8 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) GenTree* dstAddr = cpObjNode->Addr(); GenTree* source = cpObjNode->Data(); var_types srcAddrType = TYP_BYREF; - bool dstOnStack = dstAddr->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR); + bool dstOnStack = + dstAddr->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR) || cpObjNode->GetLayout()->IsStackOnly(compiler); // If the GenTree node has data about GC pointers, this means we're dealing // with CpObj, so this requires special logic. @@ -4211,7 +4258,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) { // If the destination of the CpObj is on the stack, make sure we allocated // RCX to emit the movsp (alias for movsd or movsq for 32 and 64 bits respectively). - assert((cpObjNode->gtRsvdRegs & RBM_RCX) != 0); + assert((internalRegisters.GetAll(cpObjNode) & RBM_RCX) != 0); GetEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, slots); instGen(INS_r_movsp); @@ -4261,7 +4308,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) { // Otherwise, we can save code-size and improve CQ by emitting // rep movsp (alias for movsd/movsq for x86/x64) - assert((cpObjNode->gtRsvdRegs & RBM_RCX) != 0); + assert((internalRegisters.GetAll(cpObjNode) & RBM_RCX) != 0); GetEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, nonGcSlotCount); instGen(INS_r_movsp); @@ -4292,7 +4339,7 @@ void CodeGen::genTableBasedSwitch(GenTree* treeNode) regNumber idxReg = treeNode->AsOp()->gtOp1->GetRegNum(); regNumber baseReg = treeNode->AsOp()->gtOp2->GetRegNum(); - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); // load the ip-relative offset (which is relative to start of fgFirstBB) GetEmitter()->emitIns_R_ARX(INS_mov, EA_4BYTE, baseReg, baseReg, idxReg, 4, 0); @@ -4419,7 +4466,7 @@ void CodeGen::genLockedInstructions(GenTreeOp* node) // Extend liveness of addr gcInfo.gcMarkRegPtrVal(addr->GetRegNum(), addr->TypeGet()); - const regNumber tmpReg = node->GetSingleTempReg(); + const regNumber tmpReg = internalRegisters.GetSingle(node); GetEmitter()->emitIns_R_AR(INS_mov, size, REG_RAX, addr->GetRegNum(), 0); BasicBlock* loop = genCreateTempLabel(); genDefineTempLabel(loop); @@ -5298,7 +5345,7 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) regNumber tmpReg = REG_NA; #ifdef TARGET_64BIT - tmpReg = node->GetSingleTempReg(); + tmpReg = internalRegisters.GetSingle(node); #endif // Generate the bounds check if necessary. @@ -5348,7 +5395,7 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) // The VM doesn't allow such large array elements but let's be sure. noway_assert(scale <= INT32_MAX); #else // !TARGET_64BIT - tmpReg = node->GetSingleTempReg(); + tmpReg = internalRegisters.GetSingle(node); #endif // !TARGET_64BIT GetEmitter()->emitIns_R_I(emitter::inst3opImulForReg(tmpReg), EA_PTRSIZE, indexReg, @@ -6132,7 +6179,7 @@ void CodeGen::genCall(GenTreeCall* call) // This needs to be here, rather than above where fPossibleSyncHelperCall is set, // so the GC state vars have been updated before creating the label. - if ((call->gtCallType == CT_HELPER) && (compiler->info.compFlags & CORINFO_FLG_SYNCH)) + if (call->IsHelperCall() && (compiler->info.compFlags & CORINFO_FLG_SYNCH)) { CorInfoHelpFunc helperNum = compiler->eeGetHelperNum(call->gtCallMethHnd); noway_assert(helperNum != CORINFO_HELP_UNDEF); @@ -6204,22 +6251,26 @@ void CodeGen::genCallInstruction(GenTreeCall* call X86_ARG(target_ssize_t stackA emitAttr retSize = EA_PTRSIZE; emitAttr secondRetSize = EA_UNKNOWN; - if (call->HasMultiRegRetVal()) - { - retSize = emitTypeSize(retTypeDesc->GetReturnRegType(0)); - secondRetSize = emitTypeSize(retTypeDesc->GetReturnRegType(1)); - } - else + // unused values are of no interest to GC. + if (!call->IsUnusedValue()) { - assert(!varTypeIsStruct(call)); - - if (call->gtType == TYP_REF) + if (call->HasMultiRegRetVal()) { - retSize = EA_GCREF; + retSize = emitTypeSize(retTypeDesc->GetReturnRegType(0)); + secondRetSize = emitTypeSize(retTypeDesc->GetReturnRegType(1)); } - else if (call->gtType == TYP_BYREF) + else { - retSize = EA_BYREF; + assert(!varTypeIsStruct(call)); + + if (call->gtType == TYP_REF) + { + retSize = EA_GCREF; + } + else if (call->gtType == TYP_BYREF) + { + retSize = EA_BYREF; + } } } @@ -6239,7 +6290,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call X86_ARG(target_ssize_t stackA #ifdef DEBUG // Pass the call signature information down into the emitter so the emitter can associate // native call sites with the signatures they were generated from. - if (call->gtCallType != CT_HELPER) + if (!call->IsHelperCall()) { sigInfo = call->callSig; } @@ -6384,7 +6435,8 @@ void CodeGen::genCallInstruction(GenTreeCall* call X86_ARG(target_ssize_t stackA MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), di, target->GetRegNum(), - call->IsFastTailCall()); + call->IsFastTailCall(), + true); // noSafePoint // clang-format on } } @@ -6439,10 +6491,10 @@ void CodeGen::genCallInstruction(GenTreeCall* call X86_ARG(target_ssize_t stackA else { // Generate a direct call to a non-virtual user defined or helper method - assert(call->gtCallType == CT_HELPER || call->gtCallType == CT_USER_FUNC); + assert(call->IsHelperCall() || (call->gtCallType == CT_USER_FUNC)); void* addr = nullptr; - if (call->gtCallType == CT_HELPER) + if (call->IsHelperCall()) { // Direct call to a helper method. CorInfoHelpFunc helperNum = compiler->eeGetHelperNum(methHnd); @@ -6478,302 +6530,88 @@ void CodeGen::genCallInstruction(GenTreeCall* call X86_ARG(target_ssize_t stackA } } -// Produce code for a GT_JMP node. -// The arguments of the caller needs to be transferred to the callee before exiting caller. -// The actual jump to callee is generated as part of caller epilog sequence. -// Therefore the codegen of GT_JMP is to ensure that the callee arguments are correctly setup. -void CodeGen::genJmpMethod(GenTree* jmp) +//------------------------------------------------------------------------ +// genJmpPlaceVarArgs: +// Generate code to place all varargs correctly for a JMP. +// +void CodeGen::genJmpPlaceVarArgs() { - assert(jmp->OperGet() == GT_JMP); - assert(compiler->compJmpOpUsed); + assert(compiler->info.compIsVarArgs); - // If no arguments, nothing to do - if (compiler->info.compArgsCount == 0) - { - return; - } - - // Make sure register arguments are in their initial registers - // and stack arguments are put back as well. - unsigned varNum; - LclVarDsc* varDsc; - - // First move any en-registered stack arguments back to the stack. - // At the same time any reg arg not in correct reg is moved back to its stack location. - // - // We are not strictly required to spill reg args that are not in the desired reg for a jmp call - // But that would require us to deal with circularity while moving values around. Spilling - // to stack makes the implementation simple, which is not a bad trade off given Jmp calls - // are not frequent. - for (varNum = 0; varNum < compiler->info.compArgsCount; varNum++) +#if defined(TARGET_X86) + // Nothing to do, everything is already on the stack +#elif defined(WINDOWS_AMD64_ABI) + // For win-x64 varargs all fixed floating point registers must also be + // loaded into the corresponding integer register. Furthermore, the + // remaining potential register arguments (that we spilled in the prolog) + // must be loaded into their corresponding integer and float registers. + regMaskTP potentialArgs = RBM_ARG_REGS; + for (unsigned varNum = 0; varNum < compiler->info.compArgsCount; varNum++) { - varDsc = compiler->lvaGetDesc(varNum); - - if (varDsc->lvPromoted) - { - noway_assert(varDsc->lvFieldCnt == 1); // We only handle one field here - - unsigned fieldVarNum = varDsc->lvFieldLclStart; - varDsc = compiler->lvaGetDesc(fieldVarNum); - } - noway_assert(varDsc->lvIsParam); - - if (varDsc->lvIsRegArg && (varDsc->GetRegNum() != REG_STK)) + const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(varNum); + for (unsigned i = 0; i < abiInfo.NumSegments; i++) { - // Skip reg args which are already in its right register for jmp call. - // If not, we will spill such args to their stack locations. - // - // If we need to generate a tail call profiler hook, then spill all - // arg regs to free them up for the callback. - if (!compiler->compIsProfilerHookNeeded() && (varDsc->GetRegNum() == varDsc->GetArgReg())) + const ABIPassingSegment& segment = abiInfo.Segments[i]; + if (segment.IsPassedOnStack()) { continue; } - } - else if (varDsc->GetRegNum() == REG_STK) - { - // Skip args which are currently living in stack. - continue; - } - - // If we came here it means either a reg argument not in the right register or - // a stack argument currently living in a register. In either case the following - // assert should hold. - assert(varDsc->GetRegNum() != REG_STK); - assert(!varDsc->lvIsStructField || (compiler->lvaGetDesc(varDsc->lvParentLcl)->lvFieldCnt == 1)); - var_types storeType = varDsc->GetStackSlotHomeType(); // We own the memory and can use the full move. - GetEmitter()->emitIns_S_R(ins_Store(storeType), emitTypeSize(storeType), varDsc->GetRegNum(), varNum, 0); - - // Update lvRegNum life and GC info to indicate lvRegNum is dead and varDsc stack slot is going live. - // Note that we cannot modify varDsc->GetRegNum() here because another basic block may not be expecting it. - // Therefore manually update life of varDsc->GetRegNum(). - regMaskTP tempMask = varDsc->lvRegMask(); - regSet.RemoveMaskVars(tempMask); - gcInfo.gcMarkRegSetNpt(tempMask); - if (compiler->lvaIsGCTracked(varDsc)) - { -#ifdef DEBUG - if (!VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex)) + var_types segmentType = segment.GetRegisterType(); + if (varTypeIsFloating(segmentType)) { - JITDUMP("\t\t\t\t\t\t\tVar V%02u becoming live\n", varNum); + regNumber intArgReg = compiler->getCallArgIntRegister(segment.GetRegister()); + inst_Mov(TYP_LONG, intArgReg, segment.GetRegister(), /* canSkip */ false, + emitActualTypeSize(segmentType)); + potentialArgs &= ~genRegMask(intArgReg); } else { - JITDUMP("\t\t\t\t\t\t\tVar V%02u continuing live\n", varNum); + potentialArgs &= ~segment.GetRegisterMask(); } -#endif // DEBUG - - VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); } } -#ifdef PROFILING_SUPPORTED - // At this point all arg regs are free. - // Emit tail call profiler callback. - genProfilingLeaveCallback(CORINFO_HELP_PROF_FCN_TAILCALL); -#endif - - // Next move any un-enregistered register arguments back to their register. - regMaskTP fixedIntArgMask = RBM_NONE; // tracks the int arg regs occupying fixed args in case of a vararg method. - unsigned firstArgVarNum = BAD_VAR_NUM; // varNum of the first argument in case of a vararg method. - for (varNum = 0; varNum < compiler->info.compArgsCount; varNum++) + if (potentialArgs == RBM_NONE) { - varDsc = compiler->lvaGetDesc(varNum); - if (varDsc->lvPromoted) - { - noway_assert(varDsc->lvFieldCnt == 1); // We only handle one field here - - unsigned fieldVarNum = varDsc->lvFieldLclStart; - varDsc = compiler->lvaGetDesc(fieldVarNum); - } - noway_assert(varDsc->lvIsParam); - - // Skip if arg not passed in a register. - if (!varDsc->lvIsRegArg) - { - continue; - } - -#if defined(UNIX_AMD64_ABI) - if (varTypeIsStruct(varDsc)) - { - CORINFO_CLASS_HANDLE typeHnd = varDsc->GetLayout()->GetClassHandle(); - assert(typeHnd != nullptr); - - SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc; - compiler->eeGetSystemVAmd64PassStructInRegisterDescriptor(typeHnd, &structDesc); - assert(structDesc.passedInRegisters); - - unsigned __int8 offset0 = 0; - unsigned __int8 offset1 = 0; - var_types type0 = TYP_UNKNOWN; - var_types type1 = TYP_UNKNOWN; + return; + } - // Get the eightbyte data - compiler->GetStructTypeOffset(structDesc, &type0, &type1, &offset0, &offset1); + // If we have more argument registers that weren't fixed args, then + // move them from the shadow space allocated by the caller (where we + // spilled them in the prolog) back to both the integer and float + // registers here. They may contain GC refs, so we cannot keep GC + // enabled while we do this. + GetEmitter()->emitDisableGC(); - // Move the values into the right registers. - // - - // Update varDsc->GetArgReg() and lvOtherArgReg life and GC Info to indicate varDsc stack slot is dead and - // argReg is going live. Note that we cannot modify varDsc->GetRegNum() and lvOtherArgReg here - // because another basic block may not be expecting it. - // Therefore manually update life of argReg. Note that GT_JMP marks - // the end of the basic block and after which reg life and gc info will be recomputed for the new block in - // genCodeForBBList(). - if (type0 != TYP_UNKNOWN) - { - GetEmitter()->emitIns_R_S(ins_Load(type0), emitTypeSize(type0), varDsc->GetArgReg(), varNum, offset0); - regSet.SetMaskVars(regSet.GetMaskVars() | genRegMask(varDsc->GetArgReg())); - gcInfo.gcMarkRegPtrVal(varDsc->GetArgReg(), type0); - } + do + { + regNumber potentialArg = genFirstRegNumFromMaskAndToggle(potentialArgs); + regNumber potentialArgFloat = compiler->getCallArgFloatRegister(potentialArg); - if (type1 != TYP_UNKNOWN) - { - GetEmitter()->emitIns_R_S(ins_Load(type1), emitTypeSize(type1), varDsc->GetOtherArgReg(), varNum, - offset1); - regSet.SetMaskVars(regSet.GetMaskVars() | genRegMask(varDsc->GetOtherArgReg())); - gcInfo.gcMarkRegPtrVal(varDsc->GetOtherArgReg(), type1); - } + int offset = 0; + bool result = ABIPassingInformation::GetShadowSpaceCallerOffsetForReg(potentialArg, &offset); + assert(result); - if (varDsc->lvTracked) - { - VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); - } - } - else -#endif // !defined(UNIX_AMD64_ABI) + if (isFramePointerUsed()) { - // Register argument -#ifdef TARGET_X86 - noway_assert(isRegParamType(genActualType(varDsc->TypeGet())) || - ((varDsc->TypeGet() == TYP_STRUCT) && - compiler->isTrivialPointerSizedStruct(varDsc->GetLayout()->GetClassHandle()))); -#else - noway_assert(isRegParamType(genActualType(varDsc->TypeGet()))); -#endif // TARGET_X86 - - // Is register argument already in the right register? - // If not load it from its stack location. - var_types loadType = varDsc->GetRegisterType(); - -#ifdef TARGET_X86 - if (varTypeIsStruct(varDsc->TypeGet())) - { - // Treat trivial pointer-sized structs as a pointer sized primitive - // for the purposes of registers. - loadType = TYP_I_IMPL; - } -#endif - - regNumber argReg = varDsc->GetArgReg(); // incoming arg register - - if (varDsc->GetRegNum() != argReg) - { - assert(genIsValidReg(argReg)); - GetEmitter()->emitIns_R_S(ins_Load(loadType), emitTypeSize(loadType), argReg, varNum, 0); - - // Update argReg life and GC Info to indicate varDsc stack slot is dead and argReg is going live. - // Note that we cannot modify varDsc->GetRegNum() here because another basic block may not be - // expecting it. Therefore manually update life of argReg. Note that GT_JMP marks the end of the - // basic block and after which reg life and gc info will be recomputed for the new block in - // genCodeForBBList(). - regSet.AddMaskVars(genRegMask(argReg)); - gcInfo.gcMarkRegPtrVal(argReg, loadType); - if (compiler->lvaIsGCTracked(varDsc)) - { -#ifdef DEBUG - if (VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex)) - { - JITDUMP("\t\t\t\t\t\t\tVar V%02u becoming dead\n", varNum); - } - else - { - JITDUMP("\t\t\t\t\t\t\tVar V%02u continuing dead\n", varNum); - } -#endif // DEBUG - - VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); - } - } + offset -= genCallerSPtoFPdelta(); } - -#if defined(TARGET_AMD64) - // In case of a jmp call to a vararg method also pass the float/double arg in the corresponding int arg - // register. This is due to the AMD64 ABI which requires floating point values passed to varargs functions to - // be passed in both integer and floating point registers. It doesn't apply to x86, which passes floating point - // values on the stack. - if (compFeatureVarArg() && compiler->info.compIsVarArgs) + else { - regNumber intArgReg; - var_types loadType = varDsc->GetRegisterType(); - regNumber argReg = varDsc->GetArgReg(); // incoming arg register - - if (varTypeIsFloating(loadType)) - { - intArgReg = compiler->getCallArgIntRegister(argReg); - inst_Mov(TYP_LONG, intArgReg, argReg, /* canSkip */ false, emitActualTypeSize(loadType)); - } - else - { - intArgReg = argReg; - } - - fixedIntArgMask |= genRegMask(intArgReg); - - if (intArgReg == REG_ARG_0) - { - assert(firstArgVarNum == BAD_VAR_NUM); - firstArgVarNum = varNum; - } + offset -= genCallerSPtoInitialSPdelta(); } -#endif // TARGET_AMD64 - } -#if defined(TARGET_AMD64) - // Jmp call to a vararg method - if the method has fewer than 4 fixed arguments, - // load the remaining arg registers (both int and float) from the corresponding - // shadow stack slots. This is for the reason that we don't know the number and type - // of non-fixed params passed by the caller, therefore we have to assume the worst case - // of caller passing float/double args both in int and float arg regs. - // - // This doesn't apply to x86, which doesn't pass floating point values in floating - // point registers. - // - // The caller could have passed gc-ref/byref type var args. Since these are var args - // the callee no way of knowing their gc-ness. Therefore, mark the region that loads - // remaining arg registers from shadow stack slots as non-gc interruptible. - if (compFeatureVarArg() && fixedIntArgMask != RBM_NONE) - { - assert(compiler->info.compIsVarArgs); - assert(firstArgVarNum != BAD_VAR_NUM); - - regMaskTP remainingIntArgMask = RBM_ARG_REGS & ~fixedIntArgMask; - if (remainingIntArgMask != RBM_NONE) - { - GetEmitter()->emitDisableGC(); - for (int argNum = 0, argOffset = 0; argNum < MAX_REG_ARG; ++argNum) - { - regNumber argReg = intArgRegs[argNum]; - regMaskTP argRegMask = genRegMask(argReg); + GetEmitter()->emitIns_R_AR(INS_mov, EA_8BYTE, potentialArg, genFramePointerReg(), offset); + inst_Mov(TYP_DOUBLE, potentialArgFloat, potentialArg, /* canSkip */ false, emitActualTypeSize(TYP_I_IMPL)); - if ((remainingIntArgMask & argRegMask) != 0) - { - remainingIntArgMask &= ~argRegMask; - GetEmitter()->emitIns_R_S(INS_mov, EA_8BYTE, argReg, firstArgVarNum, argOffset); + } while (potentialArgs != RBM_NONE); - // also load it in corresponding float arg reg - regNumber floatReg = compiler->getCallArgFloatRegister(argReg); - inst_Mov(TYP_DOUBLE, floatReg, argReg, /* canSkip */ false, emitActualTypeSize(TYP_I_IMPL)); - } - - argOffset += REGSIZE_BYTES; - } - GetEmitter()->emitEnableGC(); - } - } -#endif // TARGET_AMD64 + GetEmitter()->emitEnableGC(); +#else + // For SysV we don't support varargs. + unreached(); +#endif } // produce code for a GT_LEA subnode @@ -7231,7 +7069,7 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d // We need to check if the value is not greater than 0xFFFFFFFF but this value // cannot be encoded in an immediate operand. Use a right shift to test if the // upper 32 bits are zero. This requires a temporary register. - const regNumber tempReg = cast->GetSingleTempReg(); + const regNumber tempReg = internalRegisters.GetSingle(cast); assert(tempReg != reg); GetEmitter()->emitIns_Mov(INS_mov, EA_8BYTE, tempReg, reg, /* canSkip */ false); GetEmitter()->emitIns_R_I(INS_shr_N, EA_8BYTE, tempReg, 32); @@ -7247,7 +7085,7 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d case GenIntCastDesc::CHECK_INT_RANGE: { // Emit "if ((long)(int)x != x) goto OVERFLOW" - const regNumber regTmp = cast->GetSingleTempReg(); + const regNumber regTmp = internalRegisters.GetSingle(cast); GetEmitter()->emitIns_Mov(INS_movsxd, EA_8BYTE, regTmp, reg, true); GetEmitter()->emitIns_R_R(INS_cmp, EA_8BYTE, reg, regTmp); genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW); @@ -7511,7 +7349,7 @@ void CodeGen::genIntToFloatCast(GenTree* treeNode) genConsumeOperands(treeNode->AsOp()); GetEmitter()->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, treeNode->GetRegNum(), treeNode->GetRegNum(), - treeNode->GetRegNum()); + treeNode->GetRegNum(), INS_OPTS_NONE); // Note that here we need to specify srcType that will determine // the size of source reg/mem operand and rex.w prefix. @@ -7520,47 +7358,53 @@ void CodeGen::genIntToFloatCast(GenTree* treeNode) // integral to floating-point conversions all have RMW semantics if VEX support // is not available - bool isRMW = !compiler->canUseVexEncoding(); - inst_RV_RV_TT(ins, emitTypeSize(srcType), targetReg, targetReg, op1, isRMW, INS_OPTS_NONE); + const bool isRMW = !compiler->canUseVexEncoding(); // Handle the case of srcType = TYP_ULONG. SSE2 conversion instruction // will interpret ULONG value as LONG. Hence we need to adjust the // result if sign-bit of srcType is set. if (srcType == TYP_ULONG) { - // The instruction sequence below is less accurate than what clang - // and gcc generate. However, we keep the current sequence for backward compatibility. - // If we change the instructions below, FloatingPointUtils::convertUInt64ToDobule - // should be also updated for consistent conversion result. assert(dstType == TYP_DOUBLE); assert(op1->isUsedFromReg()); - // Set the flags without modifying op1. - // test op1Reg, op1Reg - inst_RV_RV(INS_test, op1->GetRegNum(), op1->GetRegNum(), srcType); + // The following LONG->DOUBLE cast machinery is based on clang's implementation + // with "-ffp-model=strict" flag: + // + // mov tmp1, arg (8 byte) + // shr tmp1 + // mov tmp2, arg (4 byte) + // and tmp2, 1 + // or tmp2, tmp1 + // test arg, arg + // cmovns tmp2, arg + // cvtsi2sd xmm0, tmp2 + // jns .LABEL + // addsd xmm0, xmm0 + //.LABEL + // + regNumber argReg = treeNode->gtGetOp1()->GetRegNum(); + regNumber tmpReg1 = internalRegisters.Extract(treeNode); + regNumber tmpReg2 = internalRegisters.Extract(treeNode); + + inst_Mov(TYP_LONG, tmpReg1, argReg, /* canSkip */ false, EA_8BYTE); + inst_RV_SH(INS_shr, EA_8BYTE, tmpReg1, 1); + inst_Mov(TYP_INT, tmpReg2, argReg, /* canSkip */ false, EA_4BYTE); + GetEmitter()->emitIns_R_I(INS_and, EA_4BYTE, tmpReg2, 1); + GetEmitter()->emitIns_R_R(INS_or, EA_8BYTE, tmpReg2, tmpReg1); + GetEmitter()->emitIns_R_R(INS_test, EA_8BYTE, argReg, argReg); + GetEmitter()->emitIns_R_R(INS_cmovns, EA_8BYTE, tmpReg2, argReg); + GetEmitter()->emitIns_R_R(ins, EA_8BYTE, targetReg, tmpReg2); - // No need to adjust result if op1 >= 0 i.e. positive - // Jge label BasicBlock* label = genCreateTempLabel(); - inst_JMP(EJ_jge, label); - - // Adjust the result - // result = result + 0x43f00000 00000000 - // addsd resultReg, 0x43f00000 00000000 - CORINFO_FIELD_HANDLE* cns = &u8ToDblBitmask; - if (*cns == nullptr) - { - double d; - static_assert_no_msg(sizeof(double) == sizeof(__int64)); - *((__int64*)&d) = 0x43f0000000000000LL; - - *cns = GetEmitter()->emitFltOrDblConst(d, EA_8BYTE); - } - GetEmitter()->emitIns_SIMD_R_R_C(INS_addsd, EA_8BYTE, targetReg, targetReg, *cns, 0); - + inst_JMP(EJ_jns, label); + GetEmitter()->emitIns_R_R(INS_addsd, EA_8BYTE, targetReg, targetReg); genDefineTempLabel(label); } - + else + { + inst_RV_RV_TT(ins, emitTypeSize(srcType), targetReg, targetReg, op1, isRMW, INS_OPTS_NONE); + } genProduceReg(treeNode); } @@ -7658,7 +7502,7 @@ void CodeGen::genCkfinite(GenTree* treeNode) regNumber targetReg = treeNode->GetRegNum(); // Extract exponent into a register. - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); genConsumeReg(op1); @@ -7722,7 +7566,8 @@ void CodeGen::genCkfinite(GenTree* treeNode) if (targetType == TYP_DOUBLE) { inst_Mov(targetType, targetReg, op1->GetRegNum(), /* canSkip */ true); - GetEmitter()->emitIns_SIMD_R_R_R_I(INS_shufps, EA_16BYTE, targetReg, targetReg, targetReg, (int8_t)0xB1); + GetEmitter()->emitIns_SIMD_R_R_R_I(INS_shufps, EA_16BYTE, targetReg, targetReg, targetReg, (int8_t)0xB1, + INS_OPTS_NONE); copyToTmpSrcReg = targetReg; } else @@ -7744,7 +7589,8 @@ void CodeGen::genCkfinite(GenTree* treeNode) if ((targetType == TYP_DOUBLE) && (targetReg == op1->GetRegNum())) { // We need to re-shuffle the targetReg to get the correct result. - GetEmitter()->emitIns_SIMD_R_R_R_I(INS_shufps, EA_16BYTE, targetReg, targetReg, targetReg, (int8_t)0xB1); + GetEmitter()->emitIns_SIMD_R_R_R_I(INS_shufps, EA_16BYTE, targetReg, targetReg, targetReg, (int8_t)0xB1, + INS_OPTS_NONE); } else { @@ -7885,23 +7731,21 @@ void CodeGen::genSSE2BitwiseOp(GenTree* treeNode) { regNumber targetReg = treeNode->GetRegNum(); regNumber operandReg = genConsumeReg(treeNode->gtGetOp1()); - emitAttr size = emitTypeSize(treeNode); assert(varTypeIsFloating(treeNode->TypeGet())); assert(treeNode->gtGetOp1()->isUsedFromReg()); - CORINFO_FIELD_HANDLE* maskFld = nullptr; - UINT64 mask = 0; - instruction ins = INS_invalid; + CORINFO_FIELD_HANDLE maskFld = NO_FIELD_HANDLE; + UINT64 mask = 0; + instruction ins = INS_invalid; if (treeNode->OperIs(GT_NEG)) { // Neg(x) = flip the sign bit. // Neg(f) = f ^ 0x80000000 x4 (packed) // Neg(d) = d ^ 0x8000000000000000 x2 (packed) - ins = INS_xorps; - mask = treeNode->TypeIs(TYP_FLOAT) ? 0x8000000080000000UL : 0x8000000000000000UL; - maskFld = treeNode->TypeIs(TYP_FLOAT) ? &negBitmaskFlt : &negBitmaskDbl; + ins = INS_xorps; + mask = treeNode->TypeIs(TYP_FLOAT) ? 0x8000000080000000UL : 0x8000000000000000UL; } else if (treeNode->OperIs(GT_INTRINSIC)) { @@ -7909,30 +7753,24 @@ void CodeGen::genSSE2BitwiseOp(GenTree* treeNode) // Abs(x) = set sign-bit to zero // Abs(f) = f & 0x7fffffff x4 (packed) // Abs(d) = d & 0x7fffffffffffffff x2 (packed) - ins = INS_andps; - mask = treeNode->TypeIs(TYP_FLOAT) ? 0x7FFFFFFF7FFFFFFFUL : 0x7FFFFFFFFFFFFFFFUL; - maskFld = treeNode->TypeIs(TYP_FLOAT) ? &absBitmaskFlt : &absBitmaskDbl; + ins = INS_andps; + mask = treeNode->TypeIs(TYP_FLOAT) ? 0x7FFFFFFF7FFFFFFFUL : 0x7FFFFFFFFFFFFFFFUL; } else { assert(!"genSSE2BitwiseOp: unsupported oper"); } - if (*maskFld == nullptr) - { - simd16_t constValue; - - constValue.u64[0] = mask; - constValue.u64[1] = mask; - + simd16_t constValue; + constValue.u64[0] = mask; + constValue.u64[1] = mask; #if defined(FEATURE_SIMD) - *maskFld = GetEmitter()->emitSimd16Const(constValue); + maskFld = GetEmitter()->emitSimd16Const(constValue); #else - *maskFld = GetEmitter()->emitBlkConst(&constValue, 16, 16, treeNode->TypeGet()); + maskFld = GetEmitter()->emitBlkConst(&constValue, 16, 16, treeNode->TypeGet()); #endif - } - GetEmitter()->emitIns_SIMD_R_R_C(ins, EA_16BYTE, targetReg, operandReg, *maskFld, 0); + GetEmitter()->emitIns_SIMD_R_R_C(ins, EA_16BYTE, targetReg, operandReg, maskFld, 0, INS_OPTS_NONE); } //----------------------------------------------------------------------------------------- @@ -8003,7 +7841,7 @@ void CodeGen::genSSE41RoundOp(GenTreeOp* treeNode) } bool isRMW = !compiler->canUseVexEncoding(); - inst_RV_RV_TT_IV(ins, size, dstReg, dstReg, srcNode, ival, isRMW); + inst_RV_RV_TT_IV(ins, size, dstReg, dstReg, srcNode, ival, isRMW, INS_OPTS_NONE); } //--------------------------------------------------------------------- @@ -8349,17 +8187,17 @@ void CodeGen::genPutArgStkFieldList(GenTreePutArgStk* putArgStk) unsigned prevFieldOffset = currentOffset; regNumber intTmpReg = REG_NA; regNumber simdTmpReg = REG_NA; - if (putArgStk->AvailableTempRegCount() != 0) + if (internalRegisters.Count(putArgStk) != 0) { - regMaskTP rsvdRegs = putArgStk->gtRsvdRegs; + regMaskTP rsvdRegs = internalRegisters.GetAll(putArgStk); if ((rsvdRegs & RBM_ALLINT) != 0) { - intTmpReg = putArgStk->GetSingleTempReg(RBM_ALLINT); + intTmpReg = internalRegisters.GetSingle(putArgStk, RBM_ALLINT); assert(genIsValidIntReg(intTmpReg)); } if ((rsvdRegs & RBM_ALLFLOAT) != 0) { - simdTmpReg = putArgStk->GetSingleTempReg(RBM_ALLFLOAT); + simdTmpReg = internalRegisters.GetSingle(putArgStk, RBM_ALLFLOAT); assert(genIsValidFloatReg(simdTmpReg)); } assert(genCountBits(rsvdRegs) == (unsigned)((intTmpReg == REG_NA) ? 0 : 1) + ((simdTmpReg == REG_NA) ? 0 : 1)); @@ -10981,7 +10819,7 @@ void CodeGen::genZeroInitFrameUsingBlockInit(int untrLclHi, int untrLclLo, regNu // mov qword ptr [ebp/esp-OFFS], rax // // NOTE: it implicitly zeroes YMM4 and ZMM4 as well. - emit->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, zeroSIMDReg, zeroSIMDReg, zeroSIMDReg); + emit->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, zeroSIMDReg, zeroSIMDReg, zeroSIMDReg, INS_OPTS_NONE); int i = 0; if (maxSimdSize > XMM_REGSIZE_BYTES) @@ -11016,7 +10854,7 @@ void CodeGen::genZeroInitFrameUsingBlockInit(int untrLclHi, int untrLclLo, regNu // add rax, 48 ; | // jne SHORT -5 instr ; ---+ - emit->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, zeroSIMDReg, zeroSIMDReg, zeroSIMDReg); + emit->emitIns_SIMD_R_R_R(INS_xorps, EA_16BYTE, zeroSIMDReg, zeroSIMDReg, zeroSIMDReg, INS_OPTS_NONE); // How many extra don't fit into the 3x unroll int extraSimd = (blkSize % (XMM_REGSIZE_BYTES * 3)) / XMM_REGSIZE_BYTES; diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index c47b7152907e..8ea57617b698 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -70,7 +70,7 @@ LONG GlobalJitOptions::compUseSoftFPConfigured = 0; #if defined(_MSC_VER) #include -inline bool _our_GetThreadCycles(unsigned __int64* cycleOut) +inline bool _our_GetThreadCycles(uint64_t* cycleOut) { *cycleOut = __rdtsc(); return true; @@ -78,11 +78,11 @@ inline bool _our_GetThreadCycles(unsigned __int64* cycleOut) #elif defined(__GNUC__) -inline bool _our_GetThreadCycles(unsigned __int64* cycleOut) +inline bool _our_GetThreadCycles(uint64_t* cycleOut) { uint32_t hi, lo; __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi)); - *cycleOut = (static_cast(hi) << 32) | static_cast(lo); + *cycleOut = (static_cast(hi) << 32) | static_cast(lo); return true; } @@ -2076,7 +2076,7 @@ void* Compiler::compGetHelperFtn(CorInfoHelpFunc ftnNum, /* IN */ else { // If we don't have a matched VM, we won't get valid results when asking for a helper function. - addr = UlongToPtr(0xCA11CA11); // "callcall" + addr = (void*)(uintptr_t)(0xCA11CA11); // "callcall" } return addr; @@ -2223,7 +2223,7 @@ const char* Compiler::compRegVarName(regNumber reg, bool displayVar, bool isFloa // consecutive calls before printing static int index = 0; // for circular index into the name array - index = (index + 1) % 2; // circular reuse of index + index ^= 1; // circular reuse of index sprintf_s(nameVarReg[index], NAME_VAR_REG_BUFFER_LEN, "%s'%s'", getRegName(reg), VarNameToStr(varName)); return nameVarReg[index]; @@ -2822,15 +2822,14 @@ void Compiler::compInitOptions(JitFlags* jitFlags) fgPgoSource = ICorJitInfo::PgoSource::Unknown; fgPgoHaveWeights = false; fgPgoSynthesized = false; - -#ifdef DEBUG - fgPgoConsistent = false; -#endif + fgPgoConsistent = false; + fgPgoDynamic = false; if (jitFlags->IsSet(JitFlags::JIT_FLAG_BBOPT)) { - fgPgoQueryResult = info.compCompHnd->getPgoInstrumentationResults(info.compMethodHnd, &fgPgoSchema, - &fgPgoSchemaCount, &fgPgoData, &fgPgoSource); + fgPgoQueryResult = + info.compCompHnd->getPgoInstrumentationResults(info.compMethodHnd, &fgPgoSchema, &fgPgoSchemaCount, + &fgPgoData, &fgPgoSource, &fgPgoDynamic); // a failed result that also has a non-NULL fgPgoSchema // indicates that the ILSize for the method no longer matches @@ -2853,6 +2852,7 @@ void Compiler::compInitOptions(JitFlags* jitFlags) fgPgoData = nullptr; fgPgoSchema = nullptr; fgPgoDisabled = true; + fgPgoDynamic = false; } #ifdef DEBUG // Optionally, enable use of profile data for only some methods. @@ -3065,7 +3065,7 @@ void Compiler::compInitOptions(JitFlags* jitFlags) #endif // !TARGET_WASM } - treesBeforeAfterMorph = (JitConfig.TreesBeforeAfterMorph() == 1); + treesBeforeAfterMorph = (JitConfig.JitDumpBeforeAfterMorph() == 1); morphNum = 0; // Initialize the morphed-trees counting. expensiveDebugCheckLevel = JitConfig.JitExpensiveDebugCheckLevel(); @@ -3796,7 +3796,7 @@ void Compiler::dumpRegMask(regMaskTP regs) const { printf("[allDouble]"); } -#ifdef TARGET_XARCH +#ifdef FEATURE_MASKED_HW_INTRINSICS else if (regs == RBM_ALLMASK) { printf("[allMask]"); @@ -4124,7 +4124,18 @@ void Compiler::compSetOptimizationLevel() { info.compCompHnd->setMethodAttribs(info.compMethodHnd, CORINFO_FLG_SWITCHED_TO_MIN_OPT); opts.jitFlags->Clear(JitFlags::JIT_FLAG_TIER1); + opts.jitFlags->Clear(JitFlags::JIT_FLAG_BBOPT); compSwitchedToMinOpts = true; + + // We may have read PGO data. Clear it out because we won't be using it. + // + fgPgoFailReason = "method switched to min-opts"; + fgPgoQueryResult = E_FAIL; + fgPgoHaveWeights = false; + fgPgoData = nullptr; + fgPgoSchema = nullptr; + fgPgoDisabled = true; + fgPgoDynamic = false; } #ifdef DEBUG @@ -4629,11 +4640,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl assert(lvaStubArgumentVar == BAD_VAR_NUM); lvaStubArgumentVar = lvaGrabTempWithImplicitUse(false DEBUGARG("stub argument")); lvaGetDesc(lvaStubArgumentVar)->lvType = TYP_I_IMPL; - // TODO-CQ: there is no need to mark it as doNotEnreg. There are no stores for this local - // before codegen so liveness and LSRA mark it as "liveIn" and always allocate a stack slot for it. - // However, it would be better to process it like other argument locals and keep it in - // a reg for the whole method without spilling to the stack when possible. - lvaSetVarDoNotEnregister(lvaStubArgumentVar DEBUGARG(DoNotEnregisterReason::VMNeedsStackAddr)); } }; DoPhase(this, PHASE_PRE_IMPORT, preImportPhase); @@ -4740,6 +4746,11 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // Record "start" values for post-inlining cycles and elapsed time. RecordStateAtEndOfInlining(); + // Drop back to just checking profile likelihoods. + // + activePhaseChecks &= ~PhaseChecks::CHECK_PROFILE; + activePhaseChecks |= PhaseChecks::CHECK_LIKELIHOODS; + // Transform each GT_ALLOCOBJ node into either an allocation helper call or // local variable allocation on the stack. ObjectAllocator objectAllocator(this); // PHASE_ALLOCATE_OBJECTS @@ -4755,6 +4766,12 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // DoPhase(this, PHASE_MORPH_ADD_INTERNAL, &Compiler::fgAddInternal); +#ifdef SWIFT_SUPPORT + // Transform GT_RETURN nodes into GT_SWIFT_ERROR_RET nodes if this method has Swift error handling + // + DoPhase(this, PHASE_SWIFT_ERROR_RET, &Compiler::fgAddSwiftErrorReturns); +#endif // SWIFT_SUPPORT + // Remove empty try regions // DoPhase(this, PHASE_EMPTY_TRY, &Compiler::fgRemoveEmptyTry); @@ -4860,6 +4877,14 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl if (opts.OptimizationEnabled()) { + // Canonicalize entry to have unique entry BB to put IR in for the upcoming phases + // + DoPhase(this, PHASE_CANONICALIZE_ENTRY, &Compiler::fgCanonicalizeFirstBB); + + // Build post-order and remove dead blocks + // + DoPhase(this, PHASE_DFS_BLOCKS, &Compiler::fgDfsBlocksAndRemove); + fgNodeThreading = NodeThreading::AllLocals; } @@ -4897,13 +4922,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl fgStress64RsltMul(); #endif // DEBUG - if (opts.OptimizationEnabled()) - { - // Build post-order that morph will use, and remove dead blocks - // - DoPhase(this, PHASE_DFS_BLOCKS, &Compiler::fgDfsBlocksAndRemove); - } - // Morph the trees in all the blocks of the method // unsigned const preMorphBBCount = fgBBcount; @@ -4942,9 +4960,9 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // DoPhase(this, PHASE_GS_COOKIE, &Compiler::gsPhase); - // Compute the block and edge weights + // Compute the block weights // - DoPhase(this, PHASE_COMPUTE_EDGE_WEIGHTS, &Compiler::fgComputeBlockAndEdgeWeights); + DoPhase(this, PHASE_COMPUTE_BLOCK_WEIGHTS, &Compiler::fgComputeBlockWeights); if (UsesFunclets()) { @@ -5180,10 +5198,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // update the flowgraph if we modified it during the optimization phase // DoPhase(this, PHASE_OPT_UPDATE_FLOW_GRAPH, &Compiler::fgUpdateFlowGraphPhase); - - // Recompute the edge weight if we have modified the flow graph - // - DoPhase(this, PHASE_COMPUTE_EDGE_WEIGHTS2, &Compiler::fgComputeEdgeWeights); } // Iterate if requested, resetting annotations first. @@ -8138,6 +8152,7 @@ if (!inlineInfo && compileFlags->Set(JitFlags::JIT_FLAG_MIN_OPT); compileFlags->Clear(JitFlags::JIT_FLAG_SIZE_OPT); compileFlags->Clear(JitFlags::JIT_FLAG_SPEED_OPT); + compileFlags->Clear(JitFlags::JIT_FLAG_BBOPT); goto START; } @@ -8290,8 +8305,8 @@ var_types Compiler::GetEightByteType(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASS void Compiler::GetStructTypeOffset(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR& structDesc, var_types* type0, var_types* type1, - unsigned __int8* offset0, - unsigned __int8* offset1) + uint8_t* offset0, + uint8_t* offset1) { *offset0 = structDesc.eightByteOffsets[0]; *offset1 = structDesc.eightByteOffsets[1]; @@ -8322,11 +8337,8 @@ void Compiler::GetStructTypeOffset(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSIN // 'offset0' - out param; returns the offset of the first eightbyte. // 'offset1' - out param; returns the offset of the second eightbyte. // -void Compiler::GetStructTypeOffset(CORINFO_CLASS_HANDLE typeHnd, - var_types* type0, - var_types* type1, - unsigned __int8* offset0, - unsigned __int8* offset1) +void Compiler::GetStructTypeOffset( + CORINFO_CLASS_HANDLE typeHnd, var_types* type0, var_types* type1, uint8_t* offset0, uint8_t* offset1) { SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc; eeGetSystemVAmd64PassStructInRegisterDescriptor(typeHnd, &structDesc); @@ -8491,7 +8503,7 @@ void Compiler::compCallArgStats() if (call->AsCall()->gtCallThisArg == nullptr) { - if (call->AsCall()->gtCallType == CT_HELPER) + if (call->AsCall()->IsHelperCall()) { argHelperCalls++; } @@ -8974,8 +8986,8 @@ void CompTimeSummaryInfo::Print(FILE* f) if (calls == 0) continue; - unsigned __int64 cycles = m_total.m_perClrAPIcycles[i]; - double millis = 1000.0 * cycles / countsPerSec; + uint64_t cycles = m_total.m_perClrAPIcycles[i]; + double millis = 1000.0 * cycles / countsPerSec; // Don't show the small fry to keep the results manageable if (millis < 0.5) @@ -8999,8 +9011,8 @@ void CompTimeSummaryInfo::Print(FILE* f) continue; } - unsigned __int32 maxcyc = m_maximum.m_maxClrAPIcycles[i]; - double max_ms = 1000.0 * maxcyc / countsPerSec; + uint32_t maxcyc = m_maximum.m_maxClrAPIcycles[i]; + double max_ms = 1000.0 * maxcyc / countsPerSec; fprintf(f, " %-40s", APInames[i]); // API name fprintf(f, " %8u %9.1f ms", calls, millis); // #calls, total time @@ -9050,7 +9062,7 @@ JitTimer::JitTimer(unsigned byteCodeSize) #endif #endif - unsigned __int64 threadCurCycles; + uint64_t threadCurCycles; if (_our_GetThreadCycles(&threadCurCycles)) { m_start = threadCurCycles; @@ -9064,10 +9076,10 @@ void JitTimer::EndPhase(Compiler* compiler, Phases phase) // We re-run some phases currently, so this following assert doesn't work. // assert((int)phase > (int)m_lastPhase); // We should end phases in increasing order. - unsigned __int64 threadCurCycles; + uint64_t threadCurCycles; if (_our_GetThreadCycles(&threadCurCycles)) { - unsigned __int64 phaseCycles = (threadCurCycles - m_curPhaseStart); + uint64_t phaseCycles = (threadCurCycles - m_curPhaseStart); // If this is not a leaf phase, the assumption is that the last subphase must have just recently ended. // Credit the duration to "slop", the total of which should be very small. @@ -9169,7 +9181,7 @@ void JitTimer::CLRApiCallLeave(unsigned apix) { if (JitConfig.JitEECallTimingInfo() != 0) { - unsigned __int64 threadCurCycles; + uint64_t threadCurCycles; if (_our_GetThreadCycles(&threadCurCycles)) { // Compute the cycles spent in the call. @@ -9185,7 +9197,7 @@ void JitTimer::CLRApiCallLeave(unsigned apix) m_info.m_perClrAPIcalls[apix] += 1; m_info.m_perClrAPIcycles[apix] += threadCurCycles; - m_info.m_maxClrAPIcycles[apix] = max(m_info.m_maxClrAPIcycles[apix], (unsigned __int32)threadCurCycles); + m_info.m_maxClrAPIcycles[apix] = max(m_info.m_maxClrAPIcycles[apix], (uint32_t)threadCurCycles); // Subtract the cycles from the enclosing phase by bumping its start time m_curPhaseStart += threadCurCycles; @@ -9329,7 +9341,7 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp) fprintf(s_csvFile, "%d,", comp->Metrics.LoopsAligned); #endif // DEBUG #endif // FEATURE_LOOP_ALIGN - unsigned __int64 totCycles = 0; + uint64_t totCycles = 0; for (int i = 0; i < PHASE_NUMBER_OF; i++) { if (!PhaseHasChildren[i]) @@ -9474,8 +9486,8 @@ void Compiler::RecordStateAtEndOfCompilation() // Common portion m_compCycles = 0; - unsigned __int64 compCyclesAtEnd; - bool b = CycleTimer::GetThreadCyclesS(&compCyclesAtEnd); + uint64_t compCyclesAtEnd; + bool b = CycleTimer::GetThreadCyclesS(&compCyclesAtEnd); if (!b) { return; // We don't have a thread cycle counter. @@ -11002,10 +11014,6 @@ void Compiler::EnregisterStats::RecordLocal(const LclVarDsc* varDsc) m_simdUserForcesDep++; break; - case DoNotEnregisterReason::NonStandardParameter: - m_nonStandardParameter++; - break; - default: unreached(); break; @@ -11133,7 +11141,6 @@ void Compiler::EnregisterStats::Dump(FILE* fout) const PRINT_STATS(m_returnSpCheck, notEnreg); PRINT_STATS(m_callSpCheck, notEnreg); PRINT_STATS(m_simdUserForcesDep, notEnreg); - PRINT_STATS(m_nonStandardParameter, notEnreg); fprintf(fout, "\nAddr exposed details:\n"); if (m_addrExposed == 0) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 436ced83ae05..343afd8cb86f 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -87,6 +87,7 @@ class OptBoolsDsc; // defined in optimizer.cpp struct RelopImplicationInfo; // defined in redundantbranchopts.cpp struct JumpThreadInfo; // defined in redundantbranchopts.cpp class ProfileSynthesis; // defined in profilesynthesis.h +class LoopLocalOccurrences; // defined in inductionvariableopts.cpp #ifdef DEBUG struct IndentStack; #endif @@ -127,7 +128,7 @@ void* operator new[](size_t n, Compiler* context, CompMemKind cmk); /*****************************************************************************/ unsigned genLog2(unsigned value); -unsigned genLog2(unsigned __int64 value); +unsigned genLog2(uint64_t value); unsigned ReinterpretHexAsDecimal(unsigned in); @@ -472,7 +473,6 @@ enum class DoNotEnregisterReason CallSpCheck, // the local is used to do SP check on every call SimdUserForcesDep, // a promoted struct was used by a SIMD/HWI node; it must be dependently promoted HiddenBufferStructArg, // the argument is a hidden return buffer passed to a method. - NonStandardParameter, // local is a parameter that is passed in a register unhandled by genFnPrologCalleeRegArgs }; enum class AddressExposedReason @@ -1040,7 +1040,7 @@ class LclVarDsc } else { -#ifdef TARGET_XARCH +#ifdef FEATURE_MASKED_HW_INTRINSICS assert(varTypeUsesIntReg(this) || varTypeUsesMaskReg(this)); #else assert(varTypeUsesIntReg(this)); @@ -1546,8 +1546,9 @@ enum class PhaseChecks : unsigned int CHECK_FG = 1 << 2, // flow graph integrity CHECK_EH = 1 << 3, // eh table integrity CHECK_LOOPS = 1 << 4, // loop integrity/canonicalization - CHECK_PROFILE = 1 << 5, // profile data integrity - CHECK_LINKED_LOCALS = 1 << 6, // check linked list of locals + CHECK_LIKELIHOODS = 1 << 5, // profile data likelihood integrity + CHECK_PROFILE = 1 << 6, // profile data full integrity + CHECK_LINKED_LOCALS = 1 << 7, // check linked list of locals }; inline constexpr PhaseChecks operator ~(PhaseChecks a) @@ -1579,6 +1580,12 @@ inline PhaseChecks& operator ^=(PhaseChecks& a, PhaseChecks b) { return a = (PhaseChecks)((unsigned int)a ^ (unsigned int)b); } + +inline bool hasFlag(const PhaseChecks& flagSet, const PhaseChecks& flag) +{ + return ((flagSet & flag) == flag); +} + // clang-format on // Specify which dumps should be run after each phase @@ -1603,12 +1610,11 @@ enum API_ICorJitInfo_Names enum class ProfileChecks : unsigned int { CHECK_NONE = 0, - CHECK_CLASSIC = 1 << 0, // check "classic" jit weights - CHECK_HASLIKELIHOOD = 1 << 1, // check all FlowEdges for hasLikelihood - CHECK_LIKELIHOODSUM = 1 << 2, // check block successor likelihoods sum to 1 - CHECK_LIKELY = 1 << 3, // fully check likelihood based weights - RAISE_ASSERT = 1 << 4, // assert on check failure - CHECK_ALL_BLOCKS = 1 << 5, // check blocks even if bbHasProfileWeight is false + CHECK_HASLIKELIHOOD = 1 << 0, // check all FlowEdges for hasLikelihood + CHECK_LIKELIHOODSUM = 1 << 1, // check block succesor likelihoods sum to 1 + CHECK_LIKELY = 1 << 2, // fully check likelihood based weights + RAISE_ASSERT = 1 << 3, // assert on check failure + CHECK_ALL_BLOCKS = 1 << 4, // check blocks even if bbHasProfileWeight is false }; inline constexpr ProfileChecks operator ~(ProfileChecks a) @@ -1667,12 +1673,12 @@ struct CompTimeInfo static bool PhaseReportsIRSize[]; unsigned m_byteCodeBytes; - unsigned __int64 m_totalCycles; - unsigned __int64 m_invokesByPhase[PHASE_NUMBER_OF]; - unsigned __int64 m_cyclesByPhase[PHASE_NUMBER_OF]; + uint64_t m_totalCycles; + uint64_t m_invokesByPhase[PHASE_NUMBER_OF]; + uint64_t m_cyclesByPhase[PHASE_NUMBER_OF]; #if MEASURE_CLRAPI_CALLS - unsigned __int64 m_CLRinvokesByPhase[PHASE_NUMBER_OF]; - unsigned __int64 m_CLRcyclesByPhase[PHASE_NUMBER_OF]; + uint64_t m_CLRinvokesByPhase[PHASE_NUMBER_OF]; + uint64_t m_CLRcyclesByPhase[PHASE_NUMBER_OF]; #endif unsigned m_nodeCountAfterPhase[PHASE_NUMBER_OF]; @@ -1685,16 +1691,16 @@ struct CompTimeInfo // it out in a report, so we can verify that it is, indeed, very small. If it ever // isn't, this means that we're doing something significant between the end of the last // declared subphase and the end of its parent. - unsigned __int64 m_parentPhaseEndSlop; + uint64_t m_parentPhaseEndSlop; bool m_timerFailure; #if MEASURE_CLRAPI_CALLS // The following measures the time spent inside each individual CLR API call. unsigned m_allClrAPIcalls; unsigned m_perClrAPIcalls[API_ICorJitInfo_Names::API_COUNT]; - unsigned __int64 m_allClrAPIcycles; - unsigned __int64 m_perClrAPIcycles[API_ICorJitInfo_Names::API_COUNT]; - unsigned __int32 m_maxClrAPIcycles[API_ICorJitInfo_Names::API_COUNT]; + uint64_t m_allClrAPIcycles; + uint64_t m_perClrAPIcycles[API_ICorJitInfo_Names::API_COUNT]; + uint32_t m_maxClrAPIcycles[API_ICorJitInfo_Names::API_COUNT]; #endif // MEASURE_CLRAPI_CALLS CompTimeInfo(unsigned byteCodeBytes); @@ -1752,12 +1758,12 @@ class CompTimeSummaryInfo // class JitTimer { - unsigned __int64 m_start; // Start of the compilation. - unsigned __int64 m_curPhaseStart; // Start of the current phase. + uint64_t m_start; // Start of the compilation. + uint64_t m_curPhaseStart; // Start of the current phase. #if MEASURE_CLRAPI_CALLS - unsigned __int64 m_CLRcallStart; // Start of the current CLR API call (if any). - unsigned __int64 m_CLRcallInvokes; // CLR API invokes under current outer so far - unsigned __int64 m_CLRcallCycles; // CLR API cycles under current outer so far. + uint64_t m_CLRcallStart; // Start of the current CLR API call (if any). + uint64_t m_CLRcallInvokes; // CLR API invokes under current outer so far + uint64_t m_CLRcallCycles; // CLR API cycles under current outer so far. int m_CLRcallAPInum; // The enum/index of the current CLR API call (or -1). static double s_cyclesPerSec; // Cached for speedier measurements #endif @@ -1803,7 +1809,7 @@ class JitTimer // Attempts to query the cycle counter of the current thread. If successful, returns "true" and sets // *cycles to the cycle counter value. Otherwise, returns false and sets the "m_timerFailure" flag of // "m_info" to true. - bool GetThreadCycles(unsigned __int64* cycles) + bool GetThreadCycles(uint64_t* cycles) { bool res = CycleTimer::GetThreadCyclesS(cycles); if (!res) @@ -2553,6 +2559,7 @@ class Compiler friend class CSE_HeuristicReplay; friend class CSE_HeuristicRL; friend class CSE_HeuristicParameterized; + friend class CSE_HeuristicRLHook; friend class CSE_Heuristic; friend class CodeGenInterface; friend class CodeGen; @@ -2807,6 +2814,9 @@ class Compiler EHblkDsc* ehIsBlockHndLast(BasicBlock* block); bool ehIsBlockEHLast(BasicBlock* block); + template + void ehUpdateTryLasts(GetTryLast getTryLast, SetTryLast setTryLast); + bool ehBlockHasExnFlowDsc(BasicBlock* block); // Return the region index of the most nested EH region this block is in. @@ -3018,7 +3028,7 @@ class Compiler GenTree* gtNewStringLiteralNode(InfoAccessType iat, void* pValue); GenTreeIntCon* gtNewStringLiteralLength(GenTreeStrCon* node); - GenTree* gtNewLconNode(__int64 value); + GenTree* gtNewLconNode(int64_t value); GenTree* gtNewDconNodeF(float value); GenTree* gtNewDconNodeD(double value); @@ -3204,13 +3214,17 @@ class Compiler CorInfoType simdBaseJitType, unsigned simdSize); -#if defined(TARGET_XARCH) - GenTree* gtNewSimdCvtNode(var_types type, - GenTree* op1, - CorInfoType simdTargetBaseJitType, - CorInfoType simdSourceBaseJitType, - unsigned simdSize); -#endif //TARGET_XARCH + GenTree* gtNewSimdCvtNode(var_types type, + GenTree* op1, + CorInfoType simdTargetBaseJitType, + CorInfoType simdSourceBaseJitType, + unsigned simdSize); + + GenTree* gtNewSimdCvtNativeNode(var_types type, + GenTree* op1, + CorInfoType simdTargetBaseJitType, + CorInfoType simdSourceBaseJitType, + unsigned simdSize); GenTree* gtNewSimdCreateBroadcastNode( var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize); @@ -3233,6 +3247,13 @@ class Compiler GenTree* gtNewSimdFloorNode( var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize); + GenTree* gtNewSimdFmaNode(var_types type, + GenTree* op1, + GenTree* op2, + GenTree* op3, + CorInfoType simdBaseJitType, + unsigned simdSize); + GenTree* gtNewSimdGetElementNode(var_types type, GenTree* op1, GenTree* op2, @@ -3489,6 +3510,7 @@ class Compiler #if defined(TARGET_ARM64) GenTree* gtNewSimdConvertVectorToMaskNode(var_types type, GenTree* node, CorInfoType simdBaseJitType, unsigned simdSize); GenTree* gtNewSimdConvertMaskToVectorNode(GenTreeHWIntrinsic* node, var_types type); + GenTree* gtNewSimdAllTrueMaskNode(CorInfoType simdBaseJitType, unsigned simdSize); #endif //------------------------------------------------------------------------ @@ -3800,6 +3822,7 @@ class Compiler unsigned lvaTableCnt; // lvaTable size (>= lvaCount) ABIPassingInformation* lvaParameterPassingInfo; + unsigned lvaParameterStackSize; unsigned lvaTrackedCount; // actual # of locals being tracked unsigned lvaTrackedCountInSizeTUnits; // min # of size_t's sufficient to hold a bit for all the locals being tracked @@ -3811,9 +3834,9 @@ class Compiler VARSET_TP lvaLongVars; // set of long (64-bit) variables #endif VARSET_TP lvaFloatVars; // set of floating-point (32-bit and 64-bit) or SIMD variables -#ifdef TARGET_XARCH +#ifdef FEATURE_MASKED_HW_INTRINSICS VARSET_TP lvaMaskVars; // set of mask variables -#endif // TARGET_XARCH +#endif // FEATURE_MASKED_HW_INTRINSICS unsigned lvaCurEpoch; // VarSets are relative to a specific set of tracked var indices. // It that changes, this changes. VarSets from different epochs @@ -3947,11 +3970,7 @@ class Compiler void lvaUpdateArgWithInitialReg(LclVarDsc* varDsc); void lvaUpdateArgsWithInitialReg(); void lvaAssignVirtualFrameOffsetsToArgs(); -#ifdef UNIX_AMD64_ABI - int lvaAssignVirtualFrameOffsetToArg(unsigned lclNum, unsigned argSize, int argOffs, int* callerArgOffset); -#else // !UNIX_AMD64_ABI - int lvaAssignVirtualFrameOffsetToArg(unsigned lclNum, unsigned argSize, int argOffs); -#endif // !UNIX_AMD64_ABI + bool lvaGetRelativeOffsetToCallerAllocatedSpaceForParameter(unsigned lclNum, int* offset); void lvaAssignVirtualFrameOffsetsToLocals(); bool lvaParamHasLocalStackSpace(unsigned lclNum); int lvaAllocLocalAndSetVirtualOffset(unsigned lclNum, unsigned size, int stkOffs); @@ -4044,6 +4063,12 @@ class Compiler return lvaGetDesc(lclVar->GetLclNum()); } + const ABIPassingInformation& lvaGetParameterABIInfo(unsigned lclNum) + { + assert(lclNum < info.compArgsCount); + return lvaParameterPassingInfo[lclNum]; + } + unsigned lvaTrackedIndexToLclNum(unsigned trackedIndex) { assert(trackedIndex < lvaTrackedCount); @@ -4112,18 +4137,7 @@ class Compiler bool lvaIsOriginalThisReadOnly(); // return true if there is no place in the code // that writes to arg0 -#ifdef TARGET_X86 - bool lvaIsArgAccessedViaVarArgsCookie(unsigned lclNum) - { - if (!info.compIsVarArgs) - { - return false; - } - - LclVarDsc* varDsc = lvaGetDesc(lclNum); - return varDsc->lvIsParam && !varDsc->lvIsRegArg && (lclNum != lvaVarargsHandleArg); - } -#endif // TARGET_X86 + bool lvaIsArgAccessedViaVarArgsCookie(unsigned lclNum); bool lvaIsImplicitByRefLocal(unsigned lclNum) const; bool lvaIsLocalImplicitlyAccessedByRef(unsigned lclNum) const; @@ -4258,7 +4272,7 @@ class Compiler return lvaGetDesc(lclNum)->lvInSsa; } - unsigned lvaStubArgumentVar; // variable representing the secret stub argument coming in EAX + unsigned lvaStubArgumentVar; // variable representing the secret stub argument unsigned lvaPSPSym; // variable representing the PSPSym @@ -4271,7 +4285,7 @@ class Compiler Compiler* impInlineRoot(); #if defined(DEBUG) - unsigned __int64 getInlineCycleCount() + uint64_t getInlineCycleCount() { return m_compCycles; } @@ -4540,6 +4554,11 @@ class Compiler CORINFO_THIS_TRANSFORM constraintCallThisTransform, NamedIntrinsic* pIntrinsicName, bool* isSpecialIntrinsic = nullptr); + GenTree* impEstimateIntrinsic(CORINFO_METHOD_HANDLE method, + CORINFO_SIG_INFO* sig, + CorInfoType callJitType, + NamedIntrinsic intrinsicName, + bool mustExpand); GenTree* impMathIntrinsic(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, var_types callType, @@ -4570,7 +4589,8 @@ class Compiler GenTree* impPrimitiveNamedIntrinsic(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig); + CORINFO_SIG_INFO* sig, + bool mustExpand); #ifdef FEATURE_HW_INTRINSICS GenTree* impHWIntrinsic(NamedIntrinsic intrinsic, @@ -4582,7 +4602,8 @@ class Compiler CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, - GenTree* newobjThis); + GenTree* newobjThis, + bool mustExpand); protected: bool compSupportsHWIntrinsic(CORINFO_InstructionSet isa); @@ -4593,7 +4614,8 @@ class Compiler var_types retType, CorInfoType simdBaseJitType, unsigned simdSize, - GenTree* newobjThis); + GenTree* newobjThis, + bool mustExpand); GenTree* impSpecialIntrinsic(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, @@ -4601,7 +4623,8 @@ class Compiler CORINFO_SIG_INFO* sig, CorInfoType simdBaseJitType, var_types retType, - unsigned simdSize); + unsigned simdSize, + bool mustExpand); GenTree* getArgForHWIntrinsic(var_types argType, CORINFO_CLASS_HANDLE argClass, @@ -4612,6 +4635,34 @@ class Compiler NamedIntrinsic intrinsic, GenTree* immOp, bool mustExpand, int immLowerBound, int immUpperBound); GenTree* addRangeCheckForHWIntrinsic(GenTree* immOp, int immLowerBound, int immUpperBound); + void getHWIntrinsicImmOps(NamedIntrinsic intrinsic, + CORINFO_SIG_INFO* sig, + GenTree** immOp1Ptr, + GenTree** immOp2Ptr); + + bool CheckHWIntrinsicImmRange(NamedIntrinsic intrinsic, + CorInfoType simdBaseJitType, + GenTree* immOp, + bool mustExpand, + int immLowerBound, + int immUpperBound, + bool hasFullRangeImm, + bool *useFallback); + +#if defined(TARGET_ARM64) + + void getHWIntrinsicImmTypes(NamedIntrinsic intrinsic, + CORINFO_SIG_INFO* sig, + unsigned immNumber, + var_types simdBaseType, + CorInfoType simdBaseJitType, + CORINFO_CLASS_HANDLE op2ClsHnd, + CORINFO_CLASS_HANDLE op3ClsHnd, + unsigned* immSimdSize, + var_types* immSimdBaseType); + +#endif // TARGET_ARM64 + #endif // FEATURE_HW_INTRINSICS GenTree* impArrayAccessIntrinsic(CORINFO_CLASS_HANDLE clsHnd, CORINFO_SIG_INFO* sig, @@ -5186,7 +5237,6 @@ class Compiler bool fgModified; // True if the flow graph has been modified recently bool fgPredsComputed; // Have we computed the bbPreds list bool fgOptimizedFinally; // Did we optimize any try-finallys? - bool fgCanonicalizedFirstBB; // TODO-Quirk: did we end up canonicalizing first BB? bool fgHasSwitch; // any BBJ_SWITCH jumps? @@ -5226,14 +5276,10 @@ class Compiler // - Rationalization links all nodes into linear form which is kept until // the end of compilation. The first and last nodes are stored in the block. NodeThreading fgNodeThreading; - bool fgCanRelocateEHRegions; // true if we are allowed to relocate the EH regions - bool fgEdgeWeightsComputed; // true after we have called fgComputeEdgeWeights - bool fgHaveValidEdgeWeights; // true if we were successful in computing all of the edge weights - bool fgSlopUsedInEdgeWeights; // true if their was some slop used when computing the edge weights - bool fgRangeUsedInEdgeWeights; // true if some of the edgeWeight are expressed in Min..Max form - weight_t fgCalledCount; // count of the number of times this method was called - // This is derived from the profile data - // or is BB_UNITY_WEIGHT when we don't have profile data + bool fgCanRelocateEHRegions; // true if we are allowed to relocate the EH regions + weight_t fgCalledCount; // count of the number of times this method was called + // This is derived from the profile data + // or is BB_UNITY_WEIGHT when we don't have profile data bool fgFuncletsCreated; // true if the funclet creation phase has been run @@ -5301,9 +5347,14 @@ class Compiler // The number of separate return points in the method. unsigned fgReturnCount; + unsigned fgThrowCount; PhaseStatus fgAddInternal(); +#ifdef SWIFT_SUPPORT + PhaseStatus fgAddSwiftErrorReturns(); +#endif // SWIFT_SUPPORT + enum class FoldResult { FOLD_DID_NOTHING, @@ -5708,6 +5759,9 @@ class Compiler // Adds the exception sets for the current tree node which is performing a division or modulus operation void fgValueNumberAddExceptionSetForDivision(GenTree* tree); + // Compute exceptions for a division operation + ValueNumPair fgValueNumberDivisionExceptions(genTreeOps oper, GenTree* dividend, GenTree* divisor); + // Adds the exception set for the current tree node which is performing a overflow checking operation void fgValueNumberAddExceptionSetForOverflow(GenTree* tree); @@ -5946,7 +6000,7 @@ class Compiler void fgReplaceEhfSuccessor(BasicBlock* block, BasicBlock* oldSucc, BasicBlock* newSucc); void fgRemoveEhfSuccessor(BasicBlock* block, const unsigned succIndex); - + void fgRemoveEhfSuccessor(FlowEdge* succEdge); void fgReplaceJumpTarget(BasicBlock* block, BasicBlock* oldTarget, BasicBlock* newTarget); @@ -6010,7 +6064,7 @@ class Compiler bool fgCanCompactBlocks(BasicBlock* block, BasicBlock* bNext); - void fgCompactBlocks(BasicBlock* block, BasicBlock* bNext); + void fgCompactBlocks(BasicBlock* block, BasicBlock* bNext DEBUGARG(bool doDebugCheck = true)); BasicBlock* fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst); @@ -6062,12 +6116,16 @@ class Compiler #ifdef DEBUG void fgPrintEdgeWeights(); #endif - PhaseStatus fgComputeBlockAndEdgeWeights(); + PhaseStatus fgComputeBlockWeights(); bool fgComputeMissingBlockWeights(weight_t* returnWeight); bool fgComputeCalledCount(weight_t returnWeight); - PhaseStatus fgComputeEdgeWeights(); bool fgReorderBlocks(bool useProfile); + void fgDoReversePostOrderLayout(); + void fgMoveColdBlocks(); + + template + void fgMoveBackwardJumpsToSuccessors(); bool fgFuncletsAreCold(); @@ -6088,9 +6146,10 @@ class Compiler PhaseStatus fgSetBlockOrder(); bool fgHasCycleWithoutGCSafePoint(); - template + template unsigned fgRunDfs(VisitPreorder assignPreorder, VisitPostorder assignPostorder, VisitEdge visitEdge); + template FlowGraphDfsTree* fgComputeDfs(); void fgInvalidateDfsTree(); @@ -6156,7 +6215,7 @@ class Compiler void fgDebugCheckDispFlags(GenTree* tree, GenTreeFlags dispFlags, GenTreeDebugFlags debugFlags); void fgDebugCheckFlagsHelper(GenTree* tree, GenTreeFlags actualFlags, GenTreeFlags expectedFlags); void fgDebugCheckTryFinallyExits(); - void fgDebugCheckProfileWeights(); + void fgDebugCheckProfile(PhaseChecks checks = PhaseChecks::CHECK_NONE); bool fgDebugCheckProfileWeights(ProfileChecks checks); bool fgDebugCheckIncomingProfileData(BasicBlock* block, ProfileChecks checks); bool fgDebugCheckOutgoingProfileData(BasicBlock* block, ProfileChecks checks); @@ -6167,6 +6226,7 @@ class Compiler static bool fgProfileWeightsEqual(weight_t weight1, weight_t weight2, weight_t epsilon = 0.01); static bool fgProfileWeightsConsistent(weight_t weight1, weight_t weight2); + static bool fgProfileWeightsConsistentOrSmall(weight_t weight1, weight_t weight2, weight_t epsilon = 1e-4); static GenTree* fgGetFirstNode(GenTree* tree); @@ -6235,7 +6295,7 @@ class Compiler void fgLinkBasicBlocks(); - unsigned fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, FixedBitVect* jumpTarget); + void fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, FixedBitVect* jumpTarget); void fgCheckBasicBlockControlFlow(); @@ -6298,10 +6358,11 @@ class Compiler unsigned fgPgoInlineeNoPgoSingleBlock; bool fgPgoHaveWeights; bool fgPgoSynthesized; + bool fgPgoDynamic; bool fgPgoConsistent; #ifdef DEBUG - bool fgPgoConsistentCheck; + bool fgPgoDeferredInconsistency; #endif @@ -6547,7 +6608,7 @@ class Compiler GenTree* fgOptimizeBitwiseAnd(GenTreeOp* andOp); GenTree* fgOptimizeBitwiseXor(GenTreeOp* xorOp); GenTree* fgPropagateCommaThrow(GenTree* parent, GenTreeOp* commaThrow, GenTreeFlags precedingSideEffects); - GenTree* fgMorphRetInd(GenTreeUnOp* tree); + GenTree* fgMorphRetInd(GenTreeOp* tree); GenTree* fgMorphModToZero(GenTreeOp* tree); GenTree* fgMorphModToSubMulDiv(GenTreeOp* tree); GenTree* fgMorphUModToAndSub(GenTreeOp* tree); @@ -6792,11 +6853,11 @@ class Compiler int m_loopVarFPCount; int m_hoistedFPExprCount; -#ifdef TARGET_XARCH +#ifdef FEATURE_MASKED_HW_INTRINSICS int m_loopVarInOutMskCount; int m_loopVarMskCount; int m_hoistedMskExprCount; -#endif // TARGET_XARCH +#endif // FEATURE_MASKED_HW_INTRINSICS // Get the VN cache for current loop VNSet* GetHoistedInCurLoop(Compiler* comp) @@ -6881,7 +6942,6 @@ class Compiler BasicBlock* optTryAdvanceLoopCompactionInsertionPoint(FlowGraphNaturalLoop* loop, BasicBlock* insertionPoint, BasicBlock* top, BasicBlock* bottom); bool optCreatePreheader(FlowGraphNaturalLoop* loop); void optSetWeightForPreheaderOrExit(FlowGraphNaturalLoop* loop, BasicBlock* block); - weight_t optEstimateEdgeLikelihood(BasicBlock* from, BasicBlock* to, bool* fromProfile); bool optCanonicalizeExits(FlowGraphNaturalLoop* loop); bool optCanonicalizeExit(FlowGraphNaturalLoop* loop, BasicBlock* exit); @@ -7430,6 +7490,14 @@ class Compiler optNoReturnCallCount++; } + void setCallDoesNotReturn(GenTreeCall* const call) + { + assert(call != nullptr); + assert(!call->IsNoReturn()); + call->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN; + setMethodHasNoReturnCalls(); + } + unsigned optNoReturnCallCount; // Recursion bound controls how far we can go backwards tracking for a SSA value. @@ -7472,14 +7540,19 @@ class Compiler #endif PhaseStatus optInductionVariables(); - bool optCanSinkWidenedIV(unsigned lclNum, FlowGraphNaturalLoop* loop); - bool optIsIVWideningProfitable(unsigned lclNum, - BasicBlock* initBlock, - bool initedToConstant, - FlowGraphNaturalLoop* loop, - ArrayStack& ivUses); - void optBestEffortReplaceNarrowIVUses( - unsigned lclNum, unsigned ssaNum, unsigned newLclNum, BasicBlock* block, Statement* firstStmt); + bool optWidenPrimaryIV(FlowGraphNaturalLoop* loop, + unsigned lclNum, + ScevAddRec* addRec, + LoopLocalOccurrences* loopLocals); + + bool optCanSinkWidenedIV(unsigned lclNum, FlowGraphNaturalLoop* loop); + bool optIsIVWideningProfitable(unsigned lclNum, + BasicBlock* initBlock, + bool initedToConstant, + FlowGraphNaturalLoop* loop, + LoopLocalOccurrences* loopLocals); + void optBestEffortReplaceNarrowIVUses( + unsigned lclNum, unsigned ssaNum, unsigned newLclNum, BasicBlock* block, Statement* firstStmt); void optReplaceWidenedIV(unsigned lclNum, unsigned ssaNum, unsigned newLclNum, Statement* stmt); void optSinkWidenedIV(unsigned lclNum, unsigned newLclNum, FlowGraphNaturalLoop* loop); @@ -7496,6 +7569,9 @@ class Compiler BitVecTraits* optReachableBitVecTraits; BitVec optReachableBitVec; void optRelopImpliesRelop(RelopImplicationInfo* rii); + bool optRelopTryInferWithOneEqualOperand(const VNFuncApp& domApp, + const VNFuncApp& treeApp, + RelopImplicationInfo* rii); /************************************************************************** * Value/Assertion propagation @@ -7528,7 +7604,6 @@ class Compiler O1K_CONSTANT_LOOP_BND_UN, O1K_EXACT_TYPE, O1K_SUBTYPE, - O1K_VALUE_NUMBER, O1K_COUNT }; @@ -7587,7 +7662,7 @@ class Compiler { SsaVar lcl; IntVal u1; - __int64 lconVal; + int64_t lconVal; double dconVal; IntegralRange u2; }; @@ -7902,7 +7977,7 @@ class Compiler GenTree* optAssertionProp_LocalStore(ASSERT_VALARG_TP assertions, GenTreeLclVarCommon* store, Statement* stmt); GenTree* optAssertionProp_BlockStore(ASSERT_VALARG_TP assertions, GenTreeBlk* store, Statement* stmt); GenTree* optAssertionProp_ModDiv(ASSERT_VALARG_TP assertions, GenTreeOp* tree, Statement* stmt); - GenTree* optAssertionProp_Return(ASSERT_VALARG_TP assertions, GenTreeUnOp* ret, Statement* stmt); + GenTree* optAssertionProp_Return(ASSERT_VALARG_TP assertions, GenTreeOp* ret, Statement* stmt); GenTree* optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt); GenTree* optAssertionProp_Cast(ASSERT_VALARG_TP assertions, GenTreeCast* cast, Statement* stmt); GenTree* optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call, Statement* stmt); @@ -8042,32 +8117,6 @@ class Compiler Lowering* m_pLowering; // Lowering; needed to Lower IR that's added or modified after Lowering. LinearScanInterface* m_pLinearScan; // Linear Scan allocator - /* raIsVarargsStackArg is called by raMaskStkVars and by - lvaComputeRefCounts. It identifies the special case - where a varargs function has a parameter passed on the - stack, other than the special varargs handle. Such parameters - require special treatment, because they cannot be tracked - by the GC (their offsets in the stack are not known - at compile time). - */ - - bool raIsVarargsStackArg(unsigned lclNum) - { -#ifdef TARGET_X86 - - LclVarDsc* varDsc = lvaGetDesc(lclNum); - - assert(varDsc->lvIsParam); - - return (info.compIsVarArgs && !varDsc->lvIsRegArg && (lclNum != lvaVarargsHandleArg)); - -#else // TARGET_X86 - - return false; - -#endif // TARGET_X86 - } - /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX @@ -8266,6 +8315,22 @@ class Compiler return eeGetEEInfo()->targetAbi == abi; } + bool BlockNonDeterministicIntrinsics(bool mustExpand) + { + // We explicitly block these APIs from being expanded in R2R + // since we know they are non-deterministic across hardware + + if (opts.IsReadyToRun() && !IsTargetAbi(CORINFO_NATIVEAOT_ABI)) + { + if (mustExpand) + { + implLimitation(); + } + return true; + } + return false; + } + #if defined(FEATURE_EH_WINDOWS_X86) bool eeIsNativeAotAbi; bool UsesFunclets() const @@ -8468,6 +8533,10 @@ class Compiler unsigned genReturnLocal; // Local number for the return value when applicable. BasicBlock* genReturnBB; // jumped to when not optimizing for speed. +#ifdef SWIFT_SUPPORT + unsigned genReturnErrorLocal; // Local number for the Swift error value when applicable. +#endif // SWIFT_SUPPORT + // The following properties are part of CodeGenContext. Getters are provided here for // convenience and backward compatibility, but the properties can only be set by invoking // the setter on CodeGenContext directly. @@ -9521,6 +9590,16 @@ class Compiler #endif } + bool canUseEmbeddedBroadcast() const + { + return JitConfig.EnableEmbeddedBroadcast(); + } + + bool canUseEmbeddedMasking() const + { + return JitConfig.EnableEmbeddedMasking(); + } + #ifdef TARGET_XARCH public: bool canUseVexEncoding() const @@ -10171,6 +10250,7 @@ class Compiler STRESS_MODE(PHYSICAL_PROMOTION_COST) \ STRESS_MODE(UNWIND) /* stress unwind info; e.g., create function fragments */ \ STRESS_MODE(OPT_REPEAT) /* stress JitOptRepeat */ \ + STRESS_MODE(INITIAL_PARAM_REG) /* Stress initial register assigned to parameters */ \ \ /* After COUNT_VARN, stress level 2 does all of these all the time */ \ \ @@ -10707,7 +10787,6 @@ class Compiler unsigned m_returnSpCheck; unsigned m_callSpCheck; unsigned m_simdUserForcesDep; - unsigned m_nonStandardParameter; unsigned m_liveInOutHndlr; unsigned m_depField; unsigned m_noRegVars; @@ -11054,9 +11133,9 @@ class Compiler #if defined(DEBUG) // These variables are associated with maintaining SQM data about compile time. - unsigned __int64 m_compCyclesAtEndOfInlining; // The thread-virtualized cycle count at the end of the inlining phase - // in the current compilation. - unsigned __int64 m_compCycles; // Net cycle count for current compilation + uint64_t m_compCyclesAtEndOfInlining; // The thread-virtualized cycle count at the end of the inlining phase + // in the current compilation. + uint64_t m_compCycles; // Net cycle count for current compilation DWORD m_compTickCountAtEndOfInlining; // The result of GetTickCount() (# ms since some epoch marker) at the end of // the inlining phase in the current compilation. #endif // defined(DEBUG) @@ -11194,14 +11273,11 @@ class Compiler static void GetStructTypeOffset(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR& structDesc, var_types* type0, var_types* type1, - unsigned __int8* offset0, - unsigned __int8* offset1); + uint8_t* offset0, + uint8_t* offset1); - void GetStructTypeOffset(CORINFO_CLASS_HANDLE typeHnd, - var_types* type0, - var_types* type1, - unsigned __int8* offset0, - unsigned __int8* offset1); + void GetStructTypeOffset( + CORINFO_CLASS_HANDLE typeHnd, var_types* type0, var_types* type1, uint8_t* offset0, uint8_t* offset1); #endif // defined(UNIX_AMD64_ABI) @@ -12044,16 +12120,16 @@ struct NodeSizeStats } // Count of tree nodes allocated. - unsigned __int64 genTreeNodeCnt; + uint64_t genTreeNodeCnt; // The size we allocate. - unsigned __int64 genTreeNodeSize; + uint64_t genTreeNodeSize; // The actual size of the node. Note that the actual size will likely be smaller // than the allocated size, but we sometimes use SetOper()/ChangeOper() to change // a smaller node to a larger one. TODO-Cleanup: add stats on // SetOper()/ChangeOper() usage to quantify this. - unsigned __int64 genTreeNodeActualSize; + uint64_t genTreeNodeActualSize; }; extern NodeSizeStats genNodeSizeStats; // Total node size stats extern NodeSizeStats genNodeSizeStatsPerFunc; // Per-function node size stats diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 0c61cfe83299..0a91cd81c21c 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -99,6 +99,31 @@ inline bool genExactlyOneBit(T value) return ((value != 0) && genMaxOneBit(value)); } +inline regMaskTP genFindLowestBit(regMaskTP value) +{ + return regMaskTP(genFindLowestBit(value.getLow())); +} + +/***************************************************************************** + * + * Return true if the given value has exactly zero or one bits set. + */ + +inline bool genMaxOneBit(regMaskTP value) +{ + return genMaxOneBit(value.getLow()); +} + +/***************************************************************************** + * + * Return true if the given value has exactly one bit set. + */ + +inline bool genExactlyOneBit(regMaskTP value) +{ + return genExactlyOneBit(value.getLow()); +} + /***************************************************************************** * * Given a value that has exactly one bit set, return the position of that @@ -110,7 +135,7 @@ inline unsigned genLog2(unsigned value) return BitOperations::BitScanForward(value); } -inline unsigned genLog2(unsigned __int64 value) +inline unsigned genLog2(uint64_t value) { assert(genExactlyOneBit(value)); return BitOperations::BitScanForward(value); @@ -119,20 +144,20 @@ inline unsigned genLog2(unsigned __int64 value) #ifdef __APPLE__ inline unsigned genLog2(size_t value) { - return genLog2((unsigned __int64)value); + return genLog2((uint64_t)value); } #endif // __APPLE__ // Given an unsigned 64-bit value, returns the lower 32-bits in unsigned format // -inline unsigned ulo32(unsigned __int64 value) +inline unsigned ulo32(uint64_t value) { return static_cast(value); } // Given an unsigned 64-bit value, returns the upper 32-bits in unsigned format // -inline unsigned uhi32(unsigned __int64 value) +inline unsigned uhi32(uint64_t value) { return static_cast(value >> 32); } @@ -142,9 +167,9 @@ inline unsigned uhi32(unsigned __int64 value) * A rather simple routine that counts the number of bits in a given number. */ -inline unsigned genCountBits(uint64_t bits) +inline unsigned genCountBits(regMaskTP mask) { - return BitOperations::PopCount(bits); + return BitOperations::PopCount(mask.getLow()); } /***************************************************************************** @@ -165,7 +190,7 @@ inline unsigned genCountBits(uint32_t bits) * value[bitNum(end) - 1, bitNum(start) + 1] */ -inline unsigned __int64 BitsBetween(unsigned __int64 value, unsigned __int64 end, unsigned __int64 start) +inline uint64_t BitsBetween(uint64_t value, uint64_t end, uint64_t start) { assert(start != 0); assert(start < end); @@ -623,12 +648,13 @@ BasicBlockVisit BasicBlock::VisitEHSuccs(Compiler* comp, TFunc func) // Arguments: // comp - Compiler instance // func - Callback +// useProfile - If true, determines the order of successors visited using profile data // // Returns: // Whether or not the visiting was aborted. // template -BasicBlockVisit BasicBlock::VisitAllSuccs(Compiler* comp, TFunc func) +BasicBlockVisit BasicBlock::VisitAllSuccs(Compiler* comp, TFunc func, const bool useProfile /* = false */) { switch (bbKind) { @@ -662,10 +688,22 @@ BasicBlockVisit BasicBlock::VisitAllSuccs(Compiler* comp, TFunc func) return VisitEHSuccs(comp, func); case BBJ_COND: - RETURN_ON_ABORT(func(GetFalseTarget())); - - if (!TrueEdgeIs(GetFalseEdge())) + if (TrueEdgeIs(GetFalseEdge())) + { + RETURN_ON_ABORT(func(GetFalseTarget())); + } + else if (useProfile && (GetTrueEdge()->getLikelihood() < GetFalseEdge()->getLikelihood())) { + // When building an RPO-based block layout, we want to visit the unlikely successor first + // so that in the DFS computation, the likely successor will be processed right before this block, + // meaning the RPO-based layout will enable fall-through into the likely successor. + // + RETURN_ON_ABORT(func(GetTrueTarget())); + RETURN_ON_ABORT(func(GetFalseTarget())); + } + else + { + RETURN_ON_ABORT(func(GetFalseTarget())); RETURN_ON_ABORT(func(GetTrueTarget())); } @@ -696,8 +734,8 @@ BasicBlockVisit BasicBlock::VisitAllSuccs(Compiler* comp, TFunc func) // VisitRegularSuccs: Visit regular successors of this block. // // Arguments: -// comp - Compiler instance -// func - Callback +// comp - Compiler instance +// func - Callback // // Returns: // Whether or not the visiting was aborted. @@ -901,11 +939,10 @@ inline regNumber genRegNumFromMask(regMaskTP mask) /* Convert the mask to a register number */ - regNumber regNum = (regNumber)genLog2(mask); + regNumber regNum = (regNumber)genLog2(mask.getLow()); /* Make sure we got it right */ - - assert(genRegMask(regNum) == mask); + assert(genRegMask(regNum) == mask.getLow()); return regNum; } @@ -927,7 +964,8 @@ inline regNumber genFirstRegNumFromMaskAndToggle(regMaskTP& mask) /* Convert the mask to a register number */ - regNumber regNum = (regNumber)BitOperations::BitScanForward(mask); + regNumber regNum = (regNumber)BitScanForward(mask); + mask ^= genRegMask(regNum); return regNum; @@ -949,7 +987,7 @@ inline regNumber genFirstRegNumFromMask(regMaskTP mask) /* Convert the mask to a register number */ - regNumber regNum = (regNumber)BitOperations::BitScanForward(mask); + regNumber regNum = (regNumber)BitScanForward(mask); return regNum; } @@ -1111,50 +1149,50 @@ const char* varTypeName(var_types); /*****************************************************************************/ // Helpers to pull little-endian values out of a byte stream. -inline unsigned __int8 getU1LittleEndian(const BYTE* ptr) +inline uint8_t getU1LittleEndian(const BYTE* ptr) { - return *(UNALIGNED unsigned __int8*)ptr; + return *(UNALIGNED uint8_t*)ptr; } -inline unsigned __int16 getU2LittleEndian(const BYTE* ptr) +inline uint16_t getU2LittleEndian(const BYTE* ptr) { return GET_UNALIGNED_VAL16(ptr); } -inline unsigned __int32 getU4LittleEndian(const BYTE* ptr) +inline uint32_t getU4LittleEndian(const BYTE* ptr) { return GET_UNALIGNED_VAL32(ptr); } -inline signed __int8 getI1LittleEndian(const BYTE* ptr) +inline int8_t getI1LittleEndian(const BYTE* ptr) { - return *(UNALIGNED signed __int8*)ptr; + return *(UNALIGNED int8_t*)ptr; } -inline signed __int16 getI2LittleEndian(const BYTE* ptr) +inline int16_t getI2LittleEndian(const BYTE* ptr) { return GET_UNALIGNED_VAL16(ptr); } -inline signed __int32 getI4LittleEndian(const BYTE* ptr) +inline int32_t getI4LittleEndian(const BYTE* ptr) { return GET_UNALIGNED_VAL32(ptr); } -inline signed __int64 getI8LittleEndian(const BYTE* ptr) +inline int64_t getI8LittleEndian(const BYTE* ptr) { return GET_UNALIGNED_VAL64(ptr); } inline float getR4LittleEndian(const BYTE* ptr) { - __int32 val = getI4LittleEndian(ptr); + int32_t val = getI4LittleEndian(ptr); return *(float*)&val; } inline double getR8LittleEndian(const BYTE* ptr) { - __int64 val = getI8LittleEndian(ptr); + int64_t val = getI8LittleEndian(ptr); return *(double*)&val; } @@ -1386,10 +1424,17 @@ inline GenTree* Compiler::gtNewIconEmbFldHndNode(CORINFO_FIELD_HANDLE fldHnd) inline GenTreeCall* Compiler::gtNewHelperCallNode( unsigned helper, var_types type, GenTree* arg1, GenTree* arg2, GenTree* arg3) { - GenTreeFlags flags = s_helperCallProperties.NoThrow((CorInfoHelpFunc)helper) ? GTF_EMPTY : GTF_EXCEPT; - GenTreeCall* result = gtNewCallNode(CT_HELPER, eeFindHelper(helper), type); - result->gtFlags |= flags; + GenTreeCall* const result = gtNewCallNode(CT_HELPER, eeFindHelper(helper), type); + if (!s_helperCallProperties.NoThrow((CorInfoHelpFunc)helper)) + { + result->gtFlags |= GTF_EXCEPT; + + if (s_helperCallProperties.AlwaysThrow((CorInfoHelpFunc)helper)) + { + setCallDoesNotReturn(result); + } + } #if DEBUG // Helper calls are never candidates. @@ -3751,7 +3796,7 @@ inline bool Compiler::IsStaticHelperEligibleForExpansion(GenTree* tree, bool* is inline bool Compiler::IsSharedStaticHelper(GenTree* tree) { - if (tree->gtOper != GT_CALL || tree->AsCall()->gtCallType != CT_HELPER) + if (!tree->OperIs(GT_CALL) || !tree->AsCall()->IsHelperCall()) { return false; } @@ -4447,7 +4492,7 @@ inline void* operator new[](size_t sz, Compiler* compiler, CompMemKind cmk) inline void printRegMask(regMaskTP mask) { - printf(REG_MASK_ALL_FMT, mask); + printf(REG_MASK_ALL_FMT, mask.getLow()); } inline char* regMaskToString(regMaskTP mask, Compiler* context) @@ -4455,14 +4500,14 @@ inline char* regMaskToString(regMaskTP mask, Compiler* context) const size_t cchRegMask = 24; char* regmask = new (context, CMK_Unknown) char[cchRegMask]; - sprintf_s(regmask, cchRegMask, REG_MASK_ALL_FMT, mask); + sprintf_s(regmask, cchRegMask, REG_MASK_ALL_FMT, mask.getLow()); return regmask; } inline void printRegMaskInt(regMaskTP mask) { - printf(REG_MASK_INT_FMT, (mask & RBM_ALLINT)); + printf(REG_MASK_INT_FMT, (mask & RBM_ALLINT).getLow()); } inline char* regMaskIntToString(regMaskTP mask, Compiler* context) @@ -4470,7 +4515,7 @@ inline char* regMaskIntToString(regMaskTP mask, Compiler* context) const size_t cchRegMask = 24; char* regmask = new (context, CMK_Unknown) char[cchRegMask]; - sprintf_s(regmask, cchRegMask, REG_MASK_INT_FMT, (mask & RBM_ALLINT)); + sprintf_s(regmask, cchRegMask, REG_MASK_INT_FMT, (mask & RBM_ALLINT).getLow()); return regmask; } @@ -4742,6 +4787,7 @@ inline bool Compiler::compCanHavePatchpoints(const char** reason) // VisitPreorder - Functor type that takes a BasicBlock* and its preorder number // VisitPostorder - Functor type that takes a BasicBlock* and its postorder number // VisitEdge - Functor type that takes two BasicBlock*. +// useProfile - If true, determines order of successors visited using profile data // // Parameters: // visitPreorder - Functor to visit block in its preorder @@ -4752,7 +4798,7 @@ inline bool Compiler::compCanHavePatchpoints(const char** reason) // Returns: // Number of blocks visited. // -template +template unsigned Compiler::fgRunDfs(VisitPreorder visitPreorder, VisitPostorder visitPostorder, VisitEdge visitEdge) { BitVecTraits traits(fgBBNumMax + 1, this); @@ -4765,7 +4811,7 @@ unsigned Compiler::fgRunDfs(VisitPreorder visitPreorder, VisitPostorder visitPos auto dfsFrom = [&](BasicBlock* firstBB) { BitVecOps::AddElemD(&traits, visited, firstBB->bbNum); - blocks.Emplace(this, firstBB); + blocks.Emplace(this, firstBB, useProfile); visitPreorder(firstBB, preOrderIndex++); while (!blocks.Empty()) @@ -4777,7 +4823,7 @@ unsigned Compiler::fgRunDfs(VisitPreorder visitPreorder, VisitPostorder visitPos { if (BitVecOps::TryAddElemD(&traits, visited, succ->bbNum)) { - blocks.Emplace(this, succ); + blocks.Emplace(this, succ, useProfile); visitPreorder(succ, preOrderIndex++); } diff --git a/src/coreclr/jit/compphases.h b/src/coreclr/jit/compphases.h index 0fb92c9f33c0..55ba7579c952 100644 --- a/src/coreclr/jit/compphases.h +++ b/src/coreclr/jit/compphases.h @@ -34,6 +34,7 @@ CompPhaseNameMacro(PHASE_INCPROFILE, "Profile incorporation", CompPhaseNameMacro(PHASE_MORPH_INIT, "Morph - Init", false, -1, false) CompPhaseNameMacro(PHASE_MORPH_INLINE, "Morph - Inlining", false, -1, true) CompPhaseNameMacro(PHASE_MORPH_ADD_INTERNAL, "Morph - Add internal blocks", false, -1, true) +CompPhaseNameMacro(PHASE_SWIFT_ERROR_RET, "Add Swift error returns", false, -1, true) CompPhaseNameMacro(PHASE_ALLOCATE_OBJECTS, "Allocate Objects", false, -1, false) CompPhaseNameMacro(PHASE_EMPTY_TRY, "Remove empty try", false, -1, false) CompPhaseNameMacro(PHASE_EMPTY_FINALLY, "Remove empty finally", false, -1, false) @@ -54,7 +55,7 @@ CompPhaseNameMacro(PHASE_MORPH_GLOBAL, "Morph - Global", CompPhaseNameMacro(PHASE_POST_MORPH, "Post-Morph", false, -1, false) CompPhaseNameMacro(PHASE_MORPH_END, "Morph - Finish", false, -1, true) CompPhaseNameMacro(PHASE_GS_COOKIE, "GS Cookie", false, -1, false) -CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS, "Compute edge weights (1, false)",false, -1, false) +CompPhaseNameMacro(PHASE_COMPUTE_BLOCK_WEIGHTS, "Compute block weights", false, -1, false) CompPhaseNameMacro(PHASE_CREATE_FUNCLETS, "Create EH funclets", false, -1, false) CompPhaseNameMacro(PHASE_HEAD_TAIL_MERGE, "Head and tail merge", false, -1, false) CompPhaseNameMacro(PHASE_MERGE_THROWS, "Merge throw blocks", false, -1, false) @@ -94,7 +95,6 @@ CompPhaseNameMacro(PHASE_ASSERTION_PROP_MAIN, "Assertion prop", CompPhaseNameMacro(PHASE_IF_CONVERSION, "If conversion", false, -1, false) CompPhaseNameMacro(PHASE_VN_BASED_DEAD_STORE_REMOVAL,"VN-based dead store removal", false, -1, false) CompPhaseNameMacro(PHASE_OPT_UPDATE_FLOW_GRAPH, "Update flow graph opt pass", false, -1, false) -CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS2, "Compute edge weights (2, false)",false, -1, false) CompPhaseNameMacro(PHASE_STRESS_SPLIT_TREE, "Stress gtSplitTree", false, -1, false) CompPhaseNameMacro(PHASE_EXPAND_RTLOOKUPS, "Expand runtime lookups", false, -1, true) CompPhaseNameMacro(PHASE_EXPAND_STATIC_INIT, "Expand static init", false, -1, true) diff --git a/src/coreclr/jit/copyprop.cpp b/src/coreclr/jit/copyprop.cpp index bb645b26bb49..11bce9e358e3 100644 --- a/src/coreclr/jit/copyprop.cpp +++ b/src/coreclr/jit/copyprop.cpp @@ -230,18 +230,16 @@ bool Compiler::optCopyProp( continue; } - if (tree->OperIs(GT_LCL_VAR)) + var_types newLclType = newLclVarDsc->TypeGet(); + if (!newLclVarDsc->lvNormalizeOnLoad()) { - var_types newLclType = newLclVarDsc->TypeGet(); - if (!newLclVarDsc->lvNormalizeOnLoad()) - { - newLclType = genActualType(newLclType); - } + newLclType = genActualType(newLclType); + } - if (newLclType != tree->TypeGet()) - { - continue; - } + var_types oldLclType = tree->OperIs(GT_LCL_VAR) ? tree->TypeGet() : varDsc->TypeGet(); + if (newLclType != oldLclType) + { + continue; } #ifdef DEBUG diff --git a/src/coreclr/jit/decomposelongs.cpp b/src/coreclr/jit/decomposelongs.cpp index ea87a996dbb1..84802400feeb 100644 --- a/src/coreclr/jit/decomposelongs.cpp +++ b/src/coreclr/jit/decomposelongs.cpp @@ -188,7 +188,8 @@ GenTree* DecomposeLongs::DecomposeNode(GenTree* tree) break; case GT_RETURN: - assert(tree->AsOp()->gtOp1->OperGet() == GT_LONG); + case GT_SWIFT_ERROR_RET: + assert(tree->AsOp()->GetReturnValue()->OperIs(GT_LONG)); break; case GT_STOREIND: diff --git a/src/coreclr/jit/earlyprop.cpp b/src/coreclr/jit/earlyprop.cpp index ef03524a1810..ca57a44e7288 100644 --- a/src/coreclr/jit/earlyprop.cpp +++ b/src/coreclr/jit/earlyprop.cpp @@ -511,7 +511,7 @@ GenTree* Compiler::optFindNullCheckToFold(GenTree* tree, LocalNumberToNullCheckT { assert(tree->OperIsIndirOrArrMetaData()); - GenTree* addr = tree->GetIndirOrArrMetaDataAddr(); + GenTree* addr = tree->GetIndirOrArrMetaDataAddr()->gtEffectiveVal(); ssize_t offsetValue = 0; diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index 5259b936646f..9e68a57805e4 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -2217,6 +2217,10 @@ void emitter::emitCreatePlaceholderIG(insGroupPlaceholderType igType, emitCurIG->igFlags &= ~IGF_PROPAGATE_MASK; } + // since we have emitted a placeholder, the last ins is not longer the last. + emitLastIns = nullptr; + emitLastInsIG = nullptr; + #ifdef DEBUG if (emitComp->verbose) { @@ -2834,6 +2838,16 @@ bool emitter::emitNoGChelper(CorInfoHelpFunc helpFunc) case CORINFO_HELP_INIT_PINVOKE_FRAME: + case CORINFO_HELP_FAIL_FAST: + case CORINFO_HELP_STACK_PROBE: + + case CORINFO_HELP_CHECK_OBJ: + + // never present on stack at the time of GC + case CORINFO_HELP_TAILCALL: + case CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER: + case CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER_TRACK_TRANSITIONS: + case CORINFO_HELP_VALIDATE_INDIRECT_CALL: return true; @@ -2868,10 +2882,36 @@ bool emitter::emitNoGChelper(CORINFO_METHOD_HANDLE methHnd) * Mark the current spot as having a label. */ -void* emitter::emitAddLabel(VARSET_VALARG_TP GCvars, - regMaskTP gcrefRegs, - regMaskTP byrefRegs DEBUG_ARG(BasicBlock* block)) +void* emitter::emitAddLabel(VARSET_VALARG_TP GCvars, regMaskTP gcrefRegs, regMaskTP byrefRegs, BasicBlock* prevBlock) { + // if starting a new block that can be a target of a branch and the last instruction was GC-capable call. + if ((prevBlock != nullptr) && emitComp->compCurBB->HasFlag(BBF_HAS_LABEL) && emitLastInsIsCallWithGC()) + { + // no GC-capable calls expected in prolog + assert(!emitIGisInEpilog(emitLastInsIG)); + + // We have just emitted a call that can do GC and conservatively recorded what is alive after the call. + // Now we see that the next instruction may be reachable by a branch with a different liveness. + // We want to maintain the invariant that the GC info at IP after a GC-capable call is the same + // regardless how it is reached. + // One way to ensure that is by adding an instruction (NOP or BRK) after the call. + if ((emitThisGCrefRegs != gcrefRegs) || (emitThisByrefRegs != byrefRegs) || + !VarSetOps::Equal(emitComp, emitThisGCrefVars, GCvars)) + { + if (prevBlock->KindIs(BBJ_THROW)) + { + emitIns(INS_BREAKPOINT); + } + else + { + // other block kinds should emit something at the end that is not a call. + assert(prevBlock->KindIs(BBJ_ALWAYS)); + // CONSIDER: In many cases we could instead patch up the GC info for previous call instruction. + emitIns(INS_nop); + } + } + } + /* Create a new IG if the current one is non-empty */ if (emitCurIGnonEmpty()) @@ -3470,7 +3510,7 @@ void emitter::emitDispRegSet(regMaskTP regs) continue; } - regs -= curReg; + regs ^= curReg; if (sp) { @@ -3632,6 +3672,7 @@ emitter::instrDesc* emitter::emitNewInstrCallInd(int argCnt, /* Make sure we didn't waste space unexpectedly */ assert(!id->idIsLargeCns()); + id->idSetIsCall(); #ifdef TARGET_XARCH /* Store the displacement and make sure the value fit */ @@ -3711,6 +3752,7 @@ emitter::instrDesc* emitter::emitNewInstrCallDir(int argCnt, /* Make sure we didn't waste space unexpectedly */ assert(!id->idIsLargeCns()); + id->idSetIsCall(); /* Save the live GC registers in the unused register fields */ assert((gcrefRegs & RBM_CALLEE_TRASH) == 0); @@ -3828,8 +3870,8 @@ void emitter::emitDispGCRegDelta(const char* title, regMaskTP prevRegs, regMaskT { emitDispGCDeltaTitle(title); regMaskTP sameRegs = prevRegs & curRegs; - regMaskTP removedRegs = prevRegs - sameRegs; - regMaskTP addedRegs = curRegs - sameRegs; + regMaskTP removedRegs = prevRegs ^ sameRegs; + regMaskTP addedRegs = curRegs ^ sameRegs; if (removedRegs != RBM_NONE) { printf(" -"); @@ -6680,11 +6722,11 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, emitFullyInt = fullyInt; emitFullGCinfo = fullPtrMap; - -#ifndef UNIX_X86_ABI - emitFullArgInfo = !emitHasFramePtr; +#if TARGET_X86 + // On x86 with funclets we emit full ptr map even for EBP frames + emitFullArgInfo = comp->UsesFunclets() ? fullPtrMap : !emitHasFramePtr; #else - emitFullArgInfo = fullPtrMap; + emitFullArgInfo = !emitHasFramePtr; #endif #if EMITTER_STATS @@ -8720,6 +8762,16 @@ void emitter::emitUpdateLiveGCvars(VARSET_VALARG_TP vars, BYTE* addr) emitThisGCrefVset = true; } +/***************************************************************************** + * + * Last emitted instruction is a call and it is not a NoGC call. + */ + +bool emitter::emitLastInsIsCallWithGC() +{ + return emitLastIns != nullptr && emitLastIns->idIsCall() && !emitLastIns->idIsNoGC(); +} + /***************************************************************************** * * Record a call location for GC purposes (we know that this is a method that @@ -8735,7 +8787,7 @@ void emitter::emitRecordGCcall(BYTE* codePos, unsigned char callInstrSize) callDsc* call; #ifdef JIT32_GCENCODER - unsigned regs = (emitThisGCrefRegs | emitThisByrefRegs) & ~RBM_INTRET; + unsigned regs = (unsigned)(emitThisGCrefRegs | emitThisByrefRegs) & ~RBM_INTRET; // The JIT32 GCInfo encoder allows us to (as the comment previously here said): // "Bail if this is a totally boring call", but the GCInfoEncoder/Decoder interface @@ -8920,7 +8972,7 @@ void emitter::emitUpdateLiveGCregs(GCtype gcType, regMaskTP regs, BYTE* addr) emitGCregDeadUpd(reg, addr); } - chg -= bit; + chg ^= bit; } while (chg); assert(emitThisXXrefRegs == regs); @@ -9076,7 +9128,7 @@ unsigned char emitter::emitOutputSizeT(BYTE* dst, ssize_t val) //------------------------------------------------------------------------ // Wrappers to emitOutputByte, emitOutputWord, emitOutputLong, emitOutputSizeT -// that take unsigned __int64 or size_t type instead of ssize_t. Used on RyuJIT/x86. +// that take uint64_t or size_t type instead of ssize_t. Used on RyuJIT/x86. // // Arguments: // dst - passed through @@ -9108,22 +9160,22 @@ unsigned char emitter::emitOutputSizeT(BYTE* dst, size_t val) return emitOutputSizeT(dst, (ssize_t)val); } -unsigned char emitter::emitOutputByte(BYTE* dst, unsigned __int64 val) +unsigned char emitter::emitOutputByte(BYTE* dst, uint64_t val) { return emitOutputByte(dst, (ssize_t)val); } -unsigned char emitter::emitOutputWord(BYTE* dst, unsigned __int64 val) +unsigned char emitter::emitOutputWord(BYTE* dst, uint64_t val) { return emitOutputWord(dst, (ssize_t)val); } -unsigned char emitter::emitOutputLong(BYTE* dst, unsigned __int64 val) +unsigned char emitter::emitOutputLong(BYTE* dst, uint64_t val) { return emitOutputLong(dst, (ssize_t)val); } -unsigned char emitter::emitOutputSizeT(BYTE* dst, unsigned __int64 val) +unsigned char emitter::emitOutputSizeT(BYTE* dst, uint64_t val) { return emitOutputSizeT(dst, (ssize_t)val); } @@ -10008,7 +10060,7 @@ void emitter::emitStackPopLargeStk(BYTE* addr, bool isCall, unsigned char callIn // We make a bitmask whose bits correspond to callee-saved register indices (in the sequence // of callee-saved registers only). - for (unsigned calleeSavedRegIdx = 0; calleeSavedRegIdx < CNT_CALLEE_SAVED; calleeSavedRegIdx++) + for (unsigned calleeSavedRegIdx = 0; calleeSavedRegIdx < CNT_CALL_GC_REGS; calleeSavedRegIdx++) { regMaskTP calleeSavedRbm = raRbmCalleeSaveOrder[calleeSavedRegIdx]; if (emitThisGCrefRegs & calleeSavedRbm) diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index b41ef5fa5c1c..8df694ac4915 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -762,10 +762,10 @@ class emitter // loongarch64: 28 bits // risc-v: 28 bits - unsigned _idSmallDsc : 1; // is this a "small" descriptor? - unsigned _idLargeCns : 1; // does a large constant follow? - unsigned _idLargeDsp : 1; // does a large displacement follow? - unsigned _idLargeCall : 1; // large call descriptor used + unsigned _idSmallDsc : 1; // is this a "small" descriptor? + unsigned _idLargeCns : 1; // does a large constant follow? (or if large call descriptor used) + unsigned _idLargeDsp : 1; // does a large displacement follow? + unsigned _idCall : 1; // this is a call // We have several pieces of information we need to encode but which are only applicable // to a subset of instrDescs. To accommodate that, we define a several _idCustom# bitfields @@ -1565,7 +1565,7 @@ class emitter bool idIsLargeCns() const { - return _idLargeCns != 0; + return _idLargeCns != 0 && !idIsCall(); } void idSetIsLargeCns() { @@ -1585,13 +1585,23 @@ class emitter _idLargeDsp = 0; } + bool idIsCall() const + { + return _idCall != 0; + } + void idSetIsCall() + { + _idCall = 1; + } + bool idIsLargeCall() const { - return _idLargeCall != 0; + return idIsCall() && _idLargeCns == 1; } void idSetIsLargeCall() { - _idLargeCall = 1; + idSetIsCall(); + _idLargeCns = 1; } bool idIsBound() const @@ -1653,21 +1663,30 @@ class emitter { assert(!idIsEvexbContextSet()); - if (instOptions == INS_OPTS_EVEX_eb_er_rd) - { - _idEvexbContext = 1; - } - else if (instOptions == INS_OPTS_EVEX_er_ru) + switch (instOptions & INS_OPTS_EVEX_b_MASK) { - _idEvexbContext = 2; - } - else if (instOptions == INS_OPTS_EVEX_er_rz) - { - _idEvexbContext = 3; - } - else - { - unreached(); + case INS_OPTS_EVEX_eb_er_rd: + { + _idEvexbContext = 1; + break; + } + + case INS_OPTS_EVEX_er_ru: + { + _idEvexbContext = 2; + break; + } + + case INS_OPTS_EVEX_er_rz: + { + _idEvexbContext = 3; + break; + } + + default: + { + unreached(); + } } } @@ -1676,6 +1695,11 @@ class emitter return _idEvexbContext; } + bool idIsEvexAaaContextSet() const + { + return idGetEvexAaaContext() != 0; + } + unsigned idGetEvexAaaContext() const { assert(IsAvx512OrPriorInstruction(_idIns)); @@ -2279,9 +2303,9 @@ class emitter void emitDispInsAddr(const BYTE* code); void emitDispInsOffs(unsigned offs, bool doffs); void emitDispInsHex(instrDesc* id, BYTE* code, size_t sz); - void emitDispEmbBroadcastCount(instrDesc* id); - void emitDispEmbRounding(instrDesc* id); - void emitDispEmbMasking(instrDesc* id); + void emitDispEmbBroadcastCount(instrDesc* id) const; + void emitDispEmbRounding(instrDesc* id) const; + void emitDispEmbMasking(instrDesc* id) const; void emitDispIns(instrDesc* id, bool isNew, bool doffs, @@ -2440,10 +2464,10 @@ class emitter unsigned char emitOutputLong(BYTE* dst, size_t val); unsigned char emitOutputSizeT(BYTE* dst, size_t val); - unsigned char emitOutputByte(BYTE* dst, unsigned __int64 val); - unsigned char emitOutputWord(BYTE* dst, unsigned __int64 val); - unsigned char emitOutputLong(BYTE* dst, unsigned __int64 val); - unsigned char emitOutputSizeT(BYTE* dst, unsigned __int64 val); + unsigned char emitOutputByte(BYTE* dst, uint64_t val); + unsigned char emitOutputWord(BYTE* dst, uint64_t val); + unsigned char emitOutputLong(BYTE* dst, uint64_t val); + unsigned char emitOutputSizeT(BYTE* dst, uint64_t val); #endif // defined(TARGET_X86) #endif // !defined(HOST_64BIT) @@ -2857,9 +2881,11 @@ class emitter // Mark this instruction group as having a label; return the new instruction group. // Sets the emitter's record of the currently live GC variables // and registers. - void* emitAddLabel(VARSET_VALARG_TP GCvars, - regMaskTP gcrefRegs, - regMaskTP byrefRegs DEBUG_ARG(BasicBlock* block = nullptr)); + // prevBlock is passed when starting a new block. + void* emitAddLabel(VARSET_VALARG_TP GCvars, + regMaskTP gcrefRegs, + regMaskTP byrefRegs, + BasicBlock* prevBlock = nullptr); // Same as above, except the label is added and is conceptually "inline" in // the current block. Thus it extends the previous block and the emitter @@ -3190,6 +3216,8 @@ class emitter void emitRecordGCcall(BYTE* codePos, unsigned char callInstrSize); + bool emitLastInsIsCallWithGC(); + // Helpers for the above void emitStackPushLargeStk(BYTE* addr, GCtype gcType, unsigned count = 1); @@ -4020,6 +4048,8 @@ emitAttr emitter::emitGetBaseMemOpSize(instrDesc* id) const case INS_subss: case INS_ucomiss: case INS_vbroadcastss: + case INS_vcvttss2usi32: + case INS_vcvttss2usi64: case INS_vfmadd132ss: case INS_vfmadd213ss: case INS_vfmadd231ss: @@ -4067,6 +4097,8 @@ emitAttr emitter::emitGetBaseMemOpSize(instrDesc* id) const case INS_subsd: case INS_ucomisd: case INS_vbroadcastsd: + case INS_vcvttsd2usi32: + case INS_vcvttsd2usi64: case INS_vfmadd132sd: case INS_vfmadd213sd: case INS_vfmadd231sd: diff --git a/src/coreclr/jit/emitarm.cpp b/src/coreclr/jit/emitarm.cpp index 5a20f8a1f940..f714e49bf4e3 100644 --- a/src/coreclr/jit/emitarm.cpp +++ b/src/coreclr/jit/emitarm.cpp @@ -3995,7 +3995,7 @@ void emitter::emitIns_R_C(instruction ins, emitAttr attr, regNumber reg, CORINFO } int doff = Compiler::eeGetJitDataOffs(fldHnd); - ssize_t addr = NULL; + ssize_t addr = 0; if (doff >= 0) { @@ -4660,6 +4660,8 @@ void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNu * * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA. * + * noSafePoint - force not making this call a safe point in partially interruptible code + * * Please consult the "debugger team notification" comment in genFnProlog(). */ @@ -4677,7 +4679,8 @@ void emitter::emitIns_Call(EmitCallType callType, regNumber xreg /* = REG_NA */, unsigned xmul /* = 0 */, ssize_t disp /* = 0 */, - bool isJump /* = false */) + bool isJump /* = false */, + bool noSafePoint /* = false */) { /* Sanity check the arguments depending on callType */ @@ -4754,11 +4757,22 @@ void emitter::emitIns_Call(EmitCallType callType, /* Update the emitter's live GC ref sets */ + // If the method returns a GC ref, mark R0 appropriately + if (retSize == EA_GCREF) + { + gcrefRegs |= RBM_R0; + } + else if (retSize == EA_BYREF) + { + byrefRegs |= RBM_R0; + } + VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars); emitThisGCrefRegs = gcrefRegs; emitThisByrefRegs = byrefRegs; - id->idSetIsNoGC(emitNoGChelper(methHnd)); + // for the purpose of GC safepointing tail-calls are not real calls + id->idSetIsNoGC(isJump || noSafePoint || emitNoGChelper(methHnd)); /* Set the instruction - special case jumping a function */ instruction ins; @@ -5757,15 +5771,15 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) assert(REG_NA == (int)REG_NA); VARSET_TP GCvars(VarSetOps::UninitVal()); + regMaskTP gcrefRegs; + regMaskTP byrefRegs; /* What instruction format have we got? */ switch (fmt) { - int imm; - BYTE* addr; - regMaskTP gcrefRegs; - regMaskTP byrefRegs; + int imm; + BYTE* addr; case IF_T1_A: // T1_A ................ sz = SMALL_IDSC_SIZE; @@ -7869,15 +7883,15 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR var_types type = indir->AsStoreInd()->Data()->TypeGet(); if (type == TYP_FLOAT) { - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); emitIns_Mov(INS_vmov_f2i, EA_4BYTE, tmpReg, dataReg, /* canSkip */ false); emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg, indir, 0); return; } else if (type == TYP_DOUBLE) { - regNumber tmpReg1 = indir->ExtractTempReg(); - regNumber tmpReg2 = indir->GetSingleTempReg(); + regNumber tmpReg1 = codeGen->internalRegisters.Extract(indir); + regNumber tmpReg2 = codeGen->internalRegisters.GetSingle(indir); emitIns_R_R_R(INS_vmov_d2i, EA_8BYTE, tmpReg1, tmpReg2, dataReg); emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg1, indir, 0); emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg2, indir, 4); @@ -7889,15 +7903,15 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR var_types type = indir->TypeGet(); if (type == TYP_FLOAT) { - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg, indir, 0); emitIns_Mov(INS_vmov_i2f, EA_4BYTE, dataReg, tmpReg, /* canSkip */ false); return; } else if (type == TYP_DOUBLE) { - regNumber tmpReg1 = indir->ExtractTempReg(); - regNumber tmpReg2 = indir->GetSingleTempReg(); + regNumber tmpReg1 = codeGen->internalRegisters.Extract(indir); + regNumber tmpReg2 = codeGen->internalRegisters.GetSingle(indir); emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg1, indir, 0); emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg2, indir, 4); emitIns_R_R_R(INS_vmov_i2d, EA_8BYTE, dataReg, tmpReg1, tmpReg2); @@ -7940,7 +7954,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR if (offset != 0) { - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); // If the LEA produces a GCREF or BYREF, we need to be careful to mark any temp register // computed with the base register as a BYREF. @@ -8023,7 +8037,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR else { // We require a tmpReg to hold the offset - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); // First load/store tmpReg with the large offset constant codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset); @@ -8175,7 +8189,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, { if (isMulOverflow) { - regNumber extraReg = dst->GetSingleTempReg(); + regNumber extraReg = codeGen->internalRegisters.GetSingle(dst); assert(extraReg != dst->GetRegNum()); if ((dst->gtFlags & GTF_UNSIGNED) != 0) diff --git a/src/coreclr/jit/emitarm.h b/src/coreclr/jit/emitarm.h index 6ae0c57dea6d..20c7b851499c 100644 --- a/src/coreclr/jit/emitarm.h +++ b/src/coreclr/jit/emitarm.h @@ -330,12 +330,13 @@ void emitIns_Call(EmitCallType callType, VARSET_VALARG_TP ptrVars, regMaskTP gcrefRegs, regMaskTP byrefRegs, - const DebugInfo& di = DebugInfo(), - regNumber ireg = REG_NA, - regNumber xreg = REG_NA, - unsigned xmul = 0, - ssize_t disp = 0, - bool isJump = false); + const DebugInfo& di = DebugInfo(), + regNumber ireg = REG_NA, + regNumber xreg = REG_NA, + unsigned xmul = 0, + ssize_t disp = 0, + bool isJump = false, + bool noSafePoint = false); /***************************************************************************** * diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 181b9706e416..ff88d9fe29c9 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -4248,6 +4248,50 @@ void emitter::emitIns_Mov( break; } + case INS_sve_mov: + { + // TODO-SVE: Remove check for insOptsNone() when predicate registers + // are present. + if (insOptsNone(opt) && isPredicateRegister(dstReg) && isPredicateRegister(srcReg)) + { + // assert(insOptsNone(opt)); + + opt = INS_OPTS_SCALABLE_B; + attr = EA_SCALABLE; + + if (IsRedundantMov(ins, size, dstReg, srcReg, canSkip)) + { + return; + } + fmt = IF_SVE_CZ_4A_L; + } + else if (isVectorRegister(dstReg) && isVectorRegister(srcReg)) + { + assert(insOptsScalable(opt)); + + if (IsRedundantMov(ins, size, dstReg, srcReg, canSkip)) + { + return; + } + fmt = IF_SVE_AU_3A; + } + else if (isVectorRegister(dstReg) && isGeneralRegisterOrSP(srcReg)) + { + assert(insOptsScalable(opt)); + if (IsRedundantMov(ins, size, dstReg, srcReg, canSkip)) + { + return; + } + srcReg = encodingSPtoZR(srcReg); + fmt = IF_SVE_CB_2A; + } + else + { + unreached(); + } + + break; + } default: { unreached(); @@ -8933,6 +8977,8 @@ void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount) * * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA. * + * noSafePoint - force not making this call a safe point in partially interruptible code + * * Please consult the "debugger team notification" comment in genFnProlog(). */ @@ -8951,7 +8997,8 @@ void emitter::emitIns_Call(EmitCallType callType, regNumber xreg /* = REG_NA */, unsigned xmul /* = 0 */, ssize_t disp /* = 0 */, - bool isJump /* = false */) + bool isJump /* = false */, + bool noSafePoint /* = false */) { /* Sanity check the arguments depending on callType */ @@ -9020,11 +9067,32 @@ void emitter::emitIns_Call(EmitCallType callType, /* Update the emitter's live GC ref sets */ + // If the method returns a GC ref, mark RBM_INTRET appropriately + if (retSize == EA_GCREF) + { + gcrefRegs |= RBM_INTRET; + } + else if (retSize == EA_BYREF) + { + byrefRegs |= RBM_INTRET; + } + + // If is a multi-register return method is called, mark RBM_INTRET_1 appropriately + if (secondRetSize == EA_GCREF) + { + gcrefRegs |= RBM_INTRET_1; + } + else if (secondRetSize == EA_BYREF) + { + byrefRegs |= RBM_INTRET_1; + } + VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars); emitThisGCrefRegs = gcrefRegs; emitThisByrefRegs = byrefRegs; - id->idSetIsNoGC(emitNoGChelper(methHnd)); + // for the purpose of GC safepointing tail-calls are not real calls + id->idSetIsNoGC(isJump || noSafePoint || emitNoGChelper(methHnd)); /* Set the instruction - special case jumping a function */ instruction ins; @@ -14243,7 +14311,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR if (offset != 0) { - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE; @@ -14350,7 +14418,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR else { // We require a tmpReg to hold the offset - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); // First load/store tmpReg with the large offset constant codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset); @@ -14490,7 +14558,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, { if (isMulOverflow) { - regNumber extraReg = dst->GetSingleTempReg(); + regNumber extraReg = codeGen->internalRegisters.GetSingle(dst); assert(extraReg != dst->GetRegNum()); if ((dst->gtFlags & GTF_UNSIGNED) != 0) @@ -16352,6 +16420,7 @@ bool emitter::IsMovInstruction(instruction ins) case INS_sxtw: case INS_uxtb: case INS_uxth: + case INS_sve_mov: { return true; } @@ -16400,7 +16469,7 @@ bool emitter::IsMovInstruction(instruction ins) bool emitter::IsRedundantMov(instruction ins, emitAttr size, regNumber dst, regNumber src, bool canSkip) { - assert(ins == INS_mov); + assert((ins == INS_mov) || (ins == INS_sve_mov)); if (canSkip && (dst == src)) { @@ -16996,7 +17065,7 @@ void emitter::emitStoreSimd12ToLclOffset(unsigned varNum, unsigned offset, regNu emitIns_S_R(INS_str, EA_8BYTE, dataReg, varNum, offset); // Extract upper 4-bytes from data - regNumber tmpReg = tmpRegProvider->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(tmpRegProvider); emitIns_R_R_I(INS_mov, EA_4BYTE, tmpReg, dataReg, 2); // 4-byte write diff --git a/src/coreclr/jit/emitarm64.h b/src/coreclr/jit/emitarm64.h index cc3254c06810..25cfcb84452d 100644 --- a/src/coreclr/jit/emitarm64.h +++ b/src/coreclr/jit/emitarm64.h @@ -1745,7 +1745,8 @@ void emitIns_Call(EmitCallType callType, regNumber xreg, unsigned xmul, ssize_t disp, - bool isJump); + bool isJump, + bool noSafePoint = false); BYTE* emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i); unsigned emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* i, code_t code); diff --git a/src/coreclr/jit/emitarm64sve.cpp b/src/coreclr/jit/emitarm64sve.cpp index 1b90b26ba799..4f6275fa71f3 100644 --- a/src/coreclr/jit/emitarm64sve.cpp +++ b/src/coreclr/jit/emitarm64sve.cpp @@ -316,7 +316,7 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) IF_SVE_HW_4B, IF_SVE_HW_4B_D, IF_SVE_HX_3A_E, IF_SVE_IG_4A_G}; const static insFormat formatEncode7A[7] = {IF_SVE_IJ_3A, IF_SVE_IK_4A, IF_SVE_IU_4A, IF_SVE_IU_4A_A, IF_SVE_IU_4B, IF_SVE_IU_4B_B, IF_SVE_IV_3A}; - const static insFormat formatEncode6A[6] = {IF_SVE_AE_3A, IF_SVE_BD_3A, IF_SVE_EE_1A, + const static insFormat formatEncode6A[6] = {IF_SVE_AA_3A, IF_SVE_AT_3A, IF_SVE_EE_1A, IF_SVE_FD_3A, IF_SVE_FD_3B, IF_SVE_FD_3C}; const static insFormat formatEncode6B[6] = {IF_SVE_GY_3A, IF_SVE_GY_3B, IF_SVE_GY_3B_D, IF_SVE_HA_3A, IF_SVE_HA_3A_E, IF_SVE_HA_3A_F}; @@ -330,8 +330,8 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) IF_SVE_IU_4B, IF_SVE_IU_4B_B, IF_SVE_IV_3A}; const static insFormat formatEncode6G[6] = {IF_SVE_JD_4A, IF_SVE_JI_3A_A, IF_SVE_JK_4A, IF_SVE_JK_4A_B, IF_SVE_JK_4B, IF_SVE_JN_3A}; - const static insFormat formatEncode5A[5] = {IF_SVE_AM_2A, IF_SVE_AN_3A, IF_SVE_AO_3A, IF_SVE_BF_2A, IF_SVE_BG_3A}; - const static insFormat formatEncode5B[5] = {IF_SVE_GX_3A, IF_SVE_GX_3B, IF_SVE_HK_3A, IF_SVE_HL_3A, IF_SVE_HM_2A}; + const static insFormat formatEncode5A[5] = {IF_SVE_AM_2A, IF_SVE_AA_3A, IF_SVE_AO_3A, IF_SVE_BF_2A, IF_SVE_BG_3A}; + const static insFormat formatEncode5B[5] = {IF_SVE_GX_3A, IF_SVE_GX_3B, IF_SVE_AT_3A, IF_SVE_HL_3A, IF_SVE_HM_2A}; const static insFormat formatEncode5C[5] = {IF_SVE_EF_3A, IF_SVE_EG_3A, IF_SVE_EH_3A, IF_SVE_EY_3A, IF_SVE_EY_3B}; const static insFormat formatEncode5D[5] = {IF_SVE_HW_4A, IF_SVE_HW_4A_A, IF_SVE_HW_4B, IF_SVE_HX_3A_B, IF_SVE_IG_4A_D}; @@ -339,7 +339,7 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) IF_SVE_IG_4A_E}; const static insFormat formatEncode4A[4] = {IF_SVE_AA_3A, IF_SVE_AU_3A, IF_SVE_BS_1A, IF_SVE_CZ_4A}; const static insFormat formatEncode4B[4] = {IF_SVE_BU_2A, IF_SVE_BV_2B, IF_SVE_EA_1A, IF_SVE_EB_1B}; - const static insFormat formatEncode4E[4] = {IF_SVE_BE_3A, IF_SVE_FI_3A, IF_SVE_FI_3B, IF_SVE_FI_3C}; + const static insFormat formatEncode4E[4] = {IF_SVE_AT_3A, IF_SVE_FI_3A, IF_SVE_FI_3B, IF_SVE_FI_3C}; const static insFormat formatEncode4F[4] = {IF_SVE_EM_3A, IF_SVE_FK_3A, IF_SVE_FK_3B, IF_SVE_FK_3C}; const static insFormat formatEncode4G[4] = {IF_SVE_AR_4A, IF_SVE_FF_3A, IF_SVE_FF_3B, IF_SVE_FF_3C}; const static insFormat formatEncode4H[4] = {IF_SVE_GM_3A, IF_SVE_GN_3A, IF_SVE_GZ_3A, IF_SVE_HB_3A}; @@ -347,14 +347,14 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static insFormat formatEncode4J[4] = {IF_SVE_BV_2A, IF_SVE_BV_2A_A, IF_SVE_CP_3A, IF_SVE_CQ_3A}; const static insFormat formatEncode4K[4] = {IF_SVE_IF_4A, IF_SVE_IF_4A_A, IF_SVE_IM_3A, IF_SVE_IN_4A}; const static insFormat formatEncode4L[4] = {IF_SVE_IZ_4A, IF_SVE_IZ_4A_A, IF_SVE_JB_4A, IF_SVE_JM_3A}; - const static insFormat formatEncode3A[3] = {IF_SVE_AB_3A, IF_SVE_AT_3A, IF_SVE_EC_1A}; + const static insFormat formatEncode3A[3] = {IF_SVE_AA_3A, IF_SVE_AT_3A, IF_SVE_EC_1A}; const static insFormat formatEncode3B[3] = {IF_SVE_BH_3A, IF_SVE_BH_3B, IF_SVE_BH_3B_A}; const static insFormat formatEncode3C[3] = {IF_SVE_BW_2A, IF_SVE_CB_2A, IF_SVE_EB_1A}; - const static insFormat formatEncode3D[3] = {IF_SVE_BR_3A, IF_SVE_BR_3B, IF_SVE_CI_3A}; - const static insFormat formatEncode3E[3] = {IF_SVE_AT_3A, IF_SVE_EC_1A, IF_SVE_ET_3A}; + const static insFormat formatEncode3D[3] = {IF_SVE_AT_3A, IF_SVE_BR_3B, IF_SVE_CI_3A}; + const static insFormat formatEncode3E[3] = {IF_SVE_AT_3A, IF_SVE_EC_1A, IF_SVE_AA_3A}; const static insFormat formatEncode3F[3] = {IF_SVE_GU_3A, IF_SVE_GU_3B, IF_SVE_HU_4A}; const static insFormat formatEncode3G[3] = {IF_SVE_GH_3A, IF_SVE_GH_3B, IF_SVE_GH_3B_B}; - const static insFormat formatEncode3H[3] = {IF_SVE_HK_3A, IF_SVE_HL_3A, IF_SVE_HM_2A}; + const static insFormat formatEncode3H[3] = {IF_SVE_AT_3A, IF_SVE_HL_3A, IF_SVE_HM_2A}; const static insFormat formatEncode3I[3] = {IF_SVE_CM_3A, IF_SVE_CN_3A, IF_SVE_CO_3A}; const static insFormat formatEncode3J[3] = {IF_SVE_CX_4A, IF_SVE_CX_4A_A, IF_SVE_CY_3A}; const static insFormat formatEncode3K[3] = {IF_SVE_CX_4A, IF_SVE_CX_4A_A, IF_SVE_CY_3B}; @@ -363,21 +363,21 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static insFormat formatEncode3N[3] = {IF_SVE_EK_3A, IF_SVE_FB_3A, IF_SVE_FB_3B}; const static insFormat formatEncode3O[3] = {IF_SVE_EK_3A, IF_SVE_FC_3A, IF_SVE_FC_3B}; const static insFormat formatEncode3P[3] = {IF_SVE_EL_3A, IF_SVE_FG_3A, IF_SVE_FG_3B}; - const static insFormat formatEncode3Q[3] = {IF_SVE_EO_3A, IF_SVE_FJ_3A, IF_SVE_FJ_3B}; - const static insFormat formatEncode3R[3] = {IF_SVE_FE_3A, IF_SVE_FE_3B, IF_SVE_FN_3A}; - const static insFormat formatEncode3S[3] = {IF_SVE_FH_3A, IF_SVE_FH_3B, IF_SVE_FN_3A}; + const static insFormat formatEncode3Q[3] = {IF_SVE_EL_3A, IF_SVE_FJ_3A, IF_SVE_FJ_3B}; + const static insFormat formatEncode3R[3] = {IF_SVE_FE_3A, IF_SVE_FE_3B, IF_SVE_FL_3A}; + const static insFormat formatEncode3S[3] = {IF_SVE_FH_3A, IF_SVE_FH_3B, IF_SVE_FL_3A}; const static insFormat formatEncode3T[3] = {IF_SVE_GX_3C, IF_SVE_HK_3B, IF_SVE_HL_3B}; const static insFormat formatEncode3U[3] = {IF_SVE_IM_3A, IF_SVE_IN_4A, IF_SVE_IX_4A}; const static insFormat formatEncode3V[3] = {IF_SVE_JA_4A, IF_SVE_JB_4A, IF_SVE_JM_3A}; const static insFormat formatEncode2AA[2] = {IF_SVE_ID_2A, IF_SVE_IE_2A}; const static insFormat formatEncode2AB[2] = {IF_SVE_JG_2A, IF_SVE_JH_2A}; - const static insFormat formatEncode2AC[2] = {IF_SVE_AD_3A, IF_SVE_ED_1A}; + const static insFormat formatEncode2AC[2] = {IF_SVE_AA_3A, IF_SVE_ED_1A}; const static insFormat formatEncode2AD[2] = {IF_SVE_AB_3B, IF_SVE_AT_3B}; const static insFormat formatEncode2AE[2] = {IF_SVE_CG_2A, IF_SVE_CJ_2A}; - const static insFormat formatEncode2AF[2] = {IF_SVE_AE_3A, IF_SVE_BD_3A}; + const static insFormat formatEncode2AF[2] = {IF_SVE_AA_3A, IF_SVE_AT_3A}; const static insFormat formatEncode2AG[2] = {IF_SVE_BS_1A, IF_SVE_CZ_4A}; const static insFormat formatEncode2AH[2] = {IF_SVE_BQ_2A, IF_SVE_BQ_2B}; - const static insFormat formatEncode2AI[2] = {IF_SVE_AM_2A, IF_SVE_EU_3A}; + const static insFormat formatEncode2AI[2] = {IF_SVE_AM_2A, IF_SVE_AA_3A}; const static insFormat formatEncode2AJ[2] = {IF_SVE_HI_3A, IF_SVE_HT_4A}; const static insFormat formatEncode2AK[2] = {IF_SVE_BZ_3A, IF_SVE_BZ_3A_A}; const static insFormat formatEncode2AL[2] = {IF_SVE_GG_3A, IF_SVE_GG_3B}; @@ -387,7 +387,7 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static insFormat formatEncode2AP[2] = {IF_SVE_GY_3B, IF_SVE_HA_3A}; const static insFormat formatEncode2AQ[2] = {IF_SVE_GO_3A, IF_SVE_HC_3A}; const static insFormat formatEncode2AR[2] = {IF_SVE_AP_3A, IF_SVE_CZ_4A}; - const static insFormat formatEncode2AT[2] = {IF_SVE_AB_3A, IF_SVE_EC_1A}; + const static insFormat formatEncode2AT[2] = {IF_SVE_AA_3A, IF_SVE_EC_1A}; const static insFormat formatEncode2AU[2] = {IF_SVE_AH_3A, IF_SVE_BI_2A}; const static insFormat formatEncode2AV[2] = {IF_SVE_BM_1A, IF_SVE_BN_1A}; const static insFormat formatEncode2AW[2] = {IF_SVE_BO_1A, IF_SVE_BP_1A}; @@ -402,7 +402,7 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) const static insFormat formatEncode2BF[2] = {IF_SVE_DM_2A, IF_SVE_DN_2A}; const static insFormat formatEncode2BG[2] = {IF_SVE_DO_2A, IF_SVE_DP_2A}; const static insFormat formatEncode2BH[2] = {IF_SVE_DW_2A, IF_SVE_DW_2B}; - const static insFormat formatEncode2BI[2] = {IF_SVE_FN_3A, IF_SVE_FN_3B}; + const static insFormat formatEncode2BI[2] = {IF_SVE_FL_3A, IF_SVE_FN_3B}; const static insFormat formatEncode2BJ[2] = {IF_SVE_GQ_3A, IF_SVE_HG_2A}; const static insFormat formatEncode2BK[2] = {IF_SVE_GU_3C, IF_SVE_HU_4B}; const static insFormat formatEncode2BL[2] = {IF_SVE_GZ_3A, IF_SVE_HB_3A}; @@ -2185,7 +2185,7 @@ void emitter::emitInsSve_R_R(instruction ins, case INS_sve_uunpkhi: case INS_sve_uunpklo: assert(insScalableOptsNone(sopt)); - assert(insOptsScalableAtLeastHalf(opt)); + assert(insOptsScalableWide(opt)); assert(isVectorRegister(reg1)); assert(isVectorRegister(reg2)); assert(isScalableVectorSize(size)); @@ -2919,7 +2919,10 @@ void emitter::emitInsSve_R_R_R(instruction ins, if (sopt == INS_SCALABLE_OPTS_UNPREDICATED) { - assert(opt == INS_OPTS_SCALABLE_D); + // The instruction only has a .D variant. However, this doesn't matter as + // it operates on bits not lanes. Effectively this means all standard opt + // sizes are supported. + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg2)); // nnnnn fmt = IF_SVE_AU_3A; } @@ -2947,7 +2950,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, { assert(isLowPredicateRegister(reg2)); assert(insScalableOptsNone(sopt)); - fmt = IF_SVE_AB_3A; + fmt = IF_SVE_AA_3A; } break; @@ -2994,7 +2997,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg3)); assert(insOptsScalableStandard(opt)); assert(insScalableOptsNone(sopt)); - fmt = IF_SVE_AD_3A; + fmt = IF_SVE_AA_3A; break; case INS_sve_mul: @@ -3006,13 +3009,13 @@ void emitter::emitInsSve_R_R_R(instruction ins, if (sopt == INS_SCALABLE_OPTS_UNPREDICATED) { assert(isVectorRegister(reg2)); - fmt = IF_SVE_BD_3A; + fmt = IF_SVE_AT_3A; } else { assert(insScalableOptsNone(sopt)); assert(isLowPredicateRegister(reg2)); - fmt = IF_SVE_AE_3A; + fmt = IF_SVE_AA_3A; } break; @@ -3060,7 +3063,6 @@ void emitter::emitInsSve_R_R_R(instruction ins, break; case INS_sve_saddv: - case INS_sve_uaddv: assert(isFloatReg(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); @@ -3069,6 +3071,15 @@ void emitter::emitInsSve_R_R_R(instruction ins, fmt = IF_SVE_AI_3A; break; + case INS_sve_uaddv: + assert(isFloatReg(reg1)); + assert(isLowPredicateRegister(reg2)); + assert(isVectorRegister(reg3)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); + fmt = IF_SVE_AI_3A; + break; + case INS_sve_addqv: unreached(); // TODO-SVE: Not yet supported. assert(isVectorRegister(reg1)); @@ -3112,7 +3123,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg3)); assert(insOptsScalableStandard(opt)); assert(insScalableOptsNone(sopt)); - fmt = IF_SVE_AN_3A; + fmt = IF_SVE_AA_3A; break; case INS_sve_asr: @@ -3137,7 +3148,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isLowPredicateRegister(reg2)); assert(insScalableOptsNone(sopt)); assert(insOptsScalableStandard(opt)); - fmt = IF_SVE_AN_3A; + fmt = IF_SVE_AA_3A; } break; @@ -3162,7 +3173,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, else { assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx - fmt = IF_SVE_BR_3A; + fmt = IF_SVE_AT_3A; } } else @@ -3208,7 +3219,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg2)); // nnnnn assert(isVectorRegister(reg3)); // mmmmm assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx - fmt = IF_SVE_CA_3A; + fmt = IF_SVE_AT_3A; break; case INS_sve_sdot: @@ -3270,7 +3281,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg2)); // nnnnn assert(isVectorRegister(reg3)); // mmmmm assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx - fmt = IF_SVE_EN_3A; + fmt = IF_SVE_EL_3A; break; case INS_sve_sqdmlalb: @@ -3282,7 +3293,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg2)); // nnnnn assert(isVectorRegister(reg3)); // mmmmm assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx - fmt = IF_SVE_EO_3A; + fmt = IF_SVE_EL_3A; break; case INS_sve_sclamp: @@ -3292,7 +3303,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg2)); // nnnnn assert(isVectorRegister(reg3)); // mmmmm assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx - fmt = IF_SVE_EV_3A; + fmt = IF_SVE_AT_3A; break; case INS_sve_zipq1: @@ -3355,7 +3366,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg2)); // nnnnn assert(isVectorRegister(reg3)); // mmmmm assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx - fmt = IF_SVE_FN_3A; + fmt = IF_SVE_FL_3A; break; case INS_sve_pmullb: @@ -3372,7 +3383,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, { assert((opt == INS_OPTS_SCALABLE_H) || (opt == INS_OPTS_SCALABLE_D)); assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx - fmt = IF_SVE_FN_3A; + fmt = IF_SVE_FL_3A; } break; @@ -3509,7 +3520,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg2)); // nnnnn assert(isVectorRegister(reg3)); // mmmmm assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx - fmt = IF_SVE_FP_3A; + fmt = IF_SVE_AT_3A; break; case INS_sve_bext: @@ -3520,7 +3531,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg2)); // nnnnn assert(isVectorRegister(reg3)); // mmmmm assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx - fmt = IF_SVE_FQ_3A; + fmt = IF_SVE_AT_3A; break; case INS_sve_saddlbt: @@ -3531,7 +3542,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg2)); // nnnnn assert(isVectorRegister(reg3)); // mmmmm assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx - fmt = IF_SVE_FS_3A; + fmt = IF_SVE_FL_3A; break; case INS_sve_saba: @@ -3553,7 +3564,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg2)); // nnnnn assert(isVectorRegister(reg3)); // mmmmm assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx - fmt = IF_SVE_FX_3A; + fmt = IF_SVE_EL_3A; break; case INS_sve_addhnb: @@ -3588,15 +3599,10 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg2)); // nnnnn assert(isVectorRegister(reg3)); // mmmmm assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx - fmt = IF_SVE_GW_3A; + fmt = IF_SVE_AT_3A; break; - case INS_sve_clz: - case INS_sve_cls: - case INS_sve_cnt: - case INS_sve_cnot: case INS_sve_not: - case INS_sve_nots: if (isPredicateRegister(reg1) && sopt != INS_SCALABLE_OPTS_UNPREDICATED) { assert(opt == INS_OPTS_SCALABLE_B); @@ -3616,6 +3622,26 @@ void emitter::emitInsSve_R_R_R(instruction ins, } break; + case INS_sve_nots: + assert(opt == INS_OPTS_SCALABLE_B); + assert(isPredicateRegister(reg1)); // DDDD + assert(isPredicateRegister(reg2)); // gggg + assert(isPredicateRegister(reg3)); // NNNN + fmt = IF_SVE_CZ_4A; + break; + + case INS_sve_clz: + case INS_sve_cls: + case INS_sve_cnt: + case INS_sve_cnot: + assert(isVectorRegister(reg1)); + assert(isLowPredicateRegister(reg2)); + assert(isVectorRegister(reg3)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); + fmt = IF_SVE_AP_3A; + break; + case INS_sve_fabs: case INS_sve_fneg: assert(isVectorRegister(reg1)); @@ -3684,7 +3710,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg3)); assert(insOptsScalableStandard(opt)); assert(insScalableOptsNone(sopt)); - fmt = IF_SVE_BE_3A; + fmt = IF_SVE_AT_3A; break; case INS_sve_ftssel: @@ -3694,7 +3720,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg3)); assert(insOptsScalableFloat(opt)); assert(insScalableOptsNone(sopt)); - fmt = IF_SVE_BK_3A; + fmt = IF_SVE_AT_3A; break; case INS_sve_compact: @@ -3720,7 +3746,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, else if (sopt == INS_SCALABLE_OPTS_WITH_SIMD_SCALAR) { assert(isFloatReg(reg1)); - assert(isValidVectorElemsize(size)); + assert(isScalableVectorSize(size)); fmt = IF_SVE_CN_3A; } else @@ -3740,7 +3766,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, if (sopt == INS_SCALABLE_OPTS_UNPREDICATED) { assert(ins == INS_sve_mov); - assert(opt == INS_OPTS_SCALABLE_D); + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); // ddddd assert(isVectorRegister(reg2)); // nnnnn assert(isVectorRegister(reg3)); // mmmmm @@ -3911,7 +3937,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg3)); assert(insOptsScalableStandard(opt)); assert(insScalableOptsNone(sopt)); - fmt = IF_SVE_EP_3A; + fmt = IF_SVE_AA_3A; break; case INS_sve_sadalp: @@ -3934,7 +3960,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg3)); assert(insOptsScalableStandard(opt)); assert(insScalableOptsNone(sopt)); - fmt = IF_SVE_ER_3A; + fmt = IF_SVE_AA_3A; break; case INS_sve_sqabs: @@ -3974,7 +4000,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, { assert(insScalableOptsNone(sopt)); assert(isLowPredicateRegister(reg2)); - fmt = IF_SVE_ET_3A; + fmt = IF_SVE_AA_3A; } break; @@ -3988,7 +4014,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(insOptsScalableStandard(opt)); assert(insScalableOptsNone(sopt)); assert(isScalableVectorSize(size)); - fmt = IF_SVE_ET_3A; + fmt = IF_SVE_AA_3A; break; case INS_sve_sqrshl: @@ -4008,7 +4034,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg3)); assert(insOptsScalableStandard(opt)); assert(insScalableOptsNone(sopt)); - fmt = IF_SVE_EU_3A; + fmt = IF_SVE_AA_3A; break; case INS_sve_fcvtnt: @@ -4059,7 +4085,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableFloat(opt)); - assert(isValidVectorElemsizeSveFloat(size)); + assert(isScalableVectorSize(size)); assert(insScalableOptsNone(sopt)); fmt = IF_SVE_HE_3A; break; @@ -4069,7 +4095,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableFloat(opt)); - assert(isValidVectorElemsizeSveFloat(size)); + assert(isScalableVectorSize(size)); assert(insScalableOptsNone(sopt)); fmt = IF_SVE_HJ_3A; break; @@ -4082,7 +4108,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, assert(isVectorRegister(reg2)); // nnnnn assert(isVectorRegister(reg3)); // mmmmm assert(isValidVectorElemsize(optGetSveElemsize(opt))); // xx - fmt = IF_SVE_HK_3A; + fmt = IF_SVE_AT_3A; break; case INS_sve_fadd: @@ -4096,7 +4122,7 @@ void emitter::emitInsSve_R_R_R(instruction ins, if (sopt == INS_SCALABLE_OPTS_UNPREDICATED) { assert(isVectorRegister(reg2)); // nnnnn - fmt = IF_SVE_HK_3A; + fmt = IF_SVE_AT_3A; } else { @@ -4349,8 +4375,11 @@ void emitter::emitInsSve_R_R_R(instruction ins, break; case INS_sve_ld1b: + case INS_sve_ld1sb: case INS_sve_ld1h: + case INS_sve_ld1sh: case INS_sve_ld1w: + case INS_sve_ld1sw: case INS_sve_ld1d: return emitIns_R_R_R_I(ins, size, reg1, reg2, reg3, 0, opt); @@ -4465,21 +4494,20 @@ void emitter::emitInsSve_R_R_R_I(instruction ins, assert(isVectorRegister(reg2)); // nnnnn assert(isLowVectorRegister(reg3)); // mmmm - if (opt == INS_OPTS_SCALABLE_B) + if (opt == INS_OPTS_SCALABLE_H) { - assert((REG_V0 <= reg3) && (reg3 <= REG_V7)); // mmm - assert(isValidUimm<2>(imm)); // ii - fmt = IF_SVE_EY_3A; + assert(isValidUimm<2>(imm)); // ii + fmt = IF_SVE_EG_3A; } - else if (opt == INS_OPTS_SCALABLE_H) + else if (opt == INS_OPTS_SCALABLE_S) { assert((REG_V0 <= reg3) && (reg3 <= REG_V7)); // mmm assert(isValidUimm<2>(imm)); // ii - fmt = IF_SVE_EG_3A; + fmt = IF_SVE_EY_3A; } else { - assert(insOptsNone(opt)); + assert(opt == INS_OPTS_SCALABLE_D); assert(isValidUimm<1>(imm)); // i opt = INS_OPTS_SCALABLE_H; fmt = IF_SVE_EY_3B; @@ -7994,7 +8022,6 @@ void emitter::emitIns_PRFOP_R_R_I(instruction ins, case IF_SVE_CP_3A: case IF_SVE_CQ_3A: case IF_SVE_AM_2A: - case IF_SVE_AN_3A: case IF_SVE_AO_3A: case IF_SVE_HL_3A: case IF_SVE_HM_2A: @@ -8006,14 +8033,9 @@ void emitter::emitIns_PRFOP_R_R_I(instruction ins, case IF_SVE_HP_3B: case IF_SVE_AR_4A: case IF_SVE_BV_2A_A: - case IF_SVE_AB_3A: - case IF_SVE_ET_3A: case IF_SVE_HU_4A: case IF_SVE_HL_3B: - case IF_SVE_AD_3A: case IF_SVE_AB_3B: - case IF_SVE_AE_3A: - case IF_SVE_EU_3A: case IF_SVE_GT_4A: case IF_SVE_AP_3A: case IF_SVE_HO_3A: @@ -8024,11 +8046,9 @@ void emitter::emitIns_PRFOP_R_R_I(instruction ins, case IF_SVE_AQ_3A: case IF_SVE_CU_3A: case IF_SVE_AC_3A: - case IF_SVE_ER_3A: case IF_SVE_GR_3A: case IF_SVE_ES_3A: case IF_SVE_HR_3A: - case IF_SVE_EP_3A: case IF_SVE_GP_3A: case IF_SVE_EQ_3A: case IF_SVE_HQ_3A: @@ -9894,18 +9914,14 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id) switch (fmt) { // Scalable. - case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations (predicated) - case IF_SVE_AB_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer add/subtract vectors (predicated) + case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd case IF_SVE_AC_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer divide vectors (predicated) - case IF_SVE_AD_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer min/max/difference (predicated) - case IF_SVE_AE_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer multiply vectors (predicated) case IF_SVE_AF_3A: // ........xx...... ...gggnnnnnddddd -- SVE bitwise logical reduction (predicated) case IF_SVE_AG_3A: // ........xx...... ...gggnnnnnddddd -- SVE bitwise logical reduction (quadwords) case IF_SVE_AI_3A: // ........xx...... ...gggnnnnnddddd -- SVE integer add reduction (predicated) case IF_SVE_AJ_3A: // ........xx...... ...gggnnnnnddddd -- SVE integer add reduction (quadwords) case IF_SVE_AK_3A: // ........xx...... ...gggnnnnnddddd -- SVE integer min/max reduction (predicated) case IF_SVE_AL_3A: // ........xx...... ...gggnnnnnddddd -- SVE integer min/max reduction (quadwords) - case IF_SVE_AN_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise shift by vector (predicated) case IF_SVE_AO_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise shift by wide elements (predicated) case IF_SVE_AP_3A: // ........xx...... ...gggnnnnnddddd -- SVE bitwise unary operations (predicated) case IF_SVE_AQ_3A: // ........xx...... ...gggnnnnnddddd -- SVE integer unary operations (predicated) @@ -9916,13 +9932,8 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id) // (predicated) case IF_SVE_CR_3A: // ........xx...... ...gggnnnnnddddd -- SVE extract element to SIMD&FP scalar register case IF_SVE_CU_3A: // ........xx...... ...gggnnnnnddddd -- SVE reverse within elements - case IF_SVE_EP_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 integer halving add/subtract (predicated) case IF_SVE_EQ_3A: // ........xx...... ...gggnnnnnddddd -- SVE2 integer pairwise add and accumulate long - case IF_SVE_ER_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 integer pairwise arithmetic case IF_SVE_ES_3A: // ........xx...... ...gggnnnnnddddd -- SVE2 integer unary operations (predicated) - case IF_SVE_ET_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 saturating add/subtract - case IF_SVE_EU_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 saturating/rounding bitwise shift left - // (predicated) case IF_SVE_GR_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 floating-point pairwise operations case IF_SVE_GS_3A: // ........xx...... ...gggnnnnnddddd -- SVE floating-point recursive reduction (quadwords) case IF_SVE_HE_3A: // ........xx...... ...gggnnnnnddddd -- SVE floating-point recursive reduction @@ -9999,35 +10010,19 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id) break; // Scalable, 3 regs, no predicates - case IF_SVE_AT_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE integer add/subtract vectors (unpredicated) - case IF_SVE_BD_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply vectors (unpredicated) - case IF_SVE_BE_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 signed saturating doubling multiply high - // (unpredicated) + case IF_SVE_AT_3A: // ........xx.mmmmm ......nnnnnddddd case IF_SVE_BG_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE bitwise shift by wide elements (unpredicated) - case IF_SVE_BK_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE floating-point trig select coefficient - case IF_SVE_BR_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE permute vector segments case IF_SVE_BZ_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE table lookup (three sources) case IF_SVE_BZ_3A_A: // ........xx.mmmmm ......nnnnnddddd -- SVE table lookup (three sources) - case IF_SVE_CA_3A: // ........xx.mmmmm ......nnnnnddddd -- sve_int_perm_tbxquads case IF_SVE_EH_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE integer dot product (unpredicated) - case IF_SVE_EL_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply-add long + case IF_SVE_EL_3A: // ........xx.mmmmm ......nnnnnddddd case IF_SVE_EM_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 saturating multiply-add high - case IF_SVE_EN_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 saturating multiply-add interleaved long - case IF_SVE_EO_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 saturating multiply-add long - case IF_SVE_EV_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE integer clamp case IF_SVE_EX_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE permute vector elements (quadwords) - case IF_SVE_FL_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract long + case IF_SVE_FL_3A: // ........xx.mmmmm ......nnnnnddddd case IF_SVE_FM_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract wide - case IF_SVE_FN_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply long - case IF_SVE_FP_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 bitwise exclusive-or interleaved - case IF_SVE_FQ_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 bitwise permute - case IF_SVE_FS_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract interleaved long case IF_SVE_FW_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer absolute difference and accumulate - case IF_SVE_FX_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer absolute difference and accumulate long - case IF_SVE_GC_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract narrow high part - case IF_SVE_GF_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 histogram generation (segment) - case IF_SVE_GW_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE FP clamp - case IF_SVE_HK_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE floating-point arithmetic (unpredicated) + case IF_SVE_GC_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract narrow high part + case IF_SVE_GF_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 histogram generation (segment) code = emitInsCodeSve(ins, fmt); code |= insEncodeReg_V<4, 0>(id->idReg1()); // ddddd code |= insEncodeReg_V<9, 5>(id->idReg2()); // nnnnn @@ -10373,7 +10368,6 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id) case IF_SVE_FN_3B: // ...........mmmmm ......nnnnnddddd -- SVE2 integer multiply long case IF_SVE_FO_3A: // ...........mmmmm ......nnnnnddddd -- SVE integer matrix multiply accumulate case IF_SVE_AT_3B: // ...........mmmmm ......nnnnnddddd -- SVE integer add/subtract vectors (unpredicated) - case IF_SVE_AU_3A: // ...........mmmmm ......nnnnnddddd -- SVE bitwise logical operations (unpredicated) case IF_SVE_BD_3B: // ...........mmmmm ......nnnnnddddd -- SVE2 integer multiply vectors (unpredicated) case IF_SVE_EF_3A: // ...........mmmmm ......nnnnnddddd -- SVE two-way dot product case IF_SVE_EI_3A: // ...........mmmmm ......nnnnnddddd -- SVE mixed sign dot product @@ -10395,6 +10389,17 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id) dst += emitOutput_Instr(dst, code); break; + case IF_SVE_AU_3A: // ...........mmmmm ......nnnnnddddd -- SVE bitwise logical operations (unpredicated) + code = emitInsCodeSve(ins, fmt); + code |= insEncodeReg_V<4, 0>(id->idReg1()); // ddddd + code |= insEncodeReg_V<9, 5>(id->idReg2()); // nnnnn + if (id->idIns() != INS_sve_mov) + { + code |= insEncodeReg_V<20, 16>(id->idReg3()); // mmmmm + } + dst += emitOutput_Instr(dst, code); + break; + case IF_SVE_AV_3A: // ...........mmmmm ......kkkkkddddd -- SVE2 bitwise ternary operations code = emitInsCodeSve(ins, fmt); code |= insEncodeReg_V<4, 0>(id->idReg1()); // ddddd @@ -11794,7 +11799,6 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id) case IF_SVE_BJ_2A: // ........xx...... ......nnnnnddddd -- SVE floating-point exponential accelerator case IF_SVE_CG_2A: // ........xx...... ......nnnnnddddd -- SVE reverse vector elements - case IF_SVE_CH_2A: // ........xx...... ......nnnnnddddd -- SVE unpack vector elements case IF_SVE_HF_2A: // ........xx...... ......nnnnnddddd -- SVE floating-point reciprocal estimate (unpredicated) code = emitInsCodeSve(ins, fmt); code |= insEncodeReg_V<4, 0>(id->idReg1()); // ddddd @@ -11803,6 +11807,14 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id) dst += emitOutput_Instr(dst, code); break; + case IF_SVE_CH_2A: // ........xx...... ......nnnnnddddd -- SVE unpack vector elements + code = emitInsCodeSve(ins, fmt); + code |= insEncodeReg_V<4, 0>(id->idReg1()); // ddddd + code |= insEncodeReg_V<9, 5>(id->idReg2()); // nnnnn + code |= insEncodeSveElemsize(optGetSveElemsize((insOpts)(id->idInsOpt() + 1))); // xx + dst += emitOutput_Instr(dst, code); + break; + case IF_SVE_BF_2A: // ........xx.xxiii ......nnnnnddddd -- SVE bitwise shift by immediate (unpredicated) case IF_SVE_FT_2A: // ........xx.xxiii ......nnnnnddddd -- SVE2 bitwise shift and insert case IF_SVE_FU_2A: // ........xx.xxiii ......nnnnnddddd -- SVE2 bitwise shift right and accumulate @@ -12539,17 +12551,8 @@ void emitter::emitInsSveSanityCheck(instrDesc* id) break; // Scalable. - case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations (predicated) - case IF_SVE_AB_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer add/subtract vectors (predicated) - case IF_SVE_AD_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer min/max/difference (predicated) - case IF_SVE_AE_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer multiply vectors (predicated) - case IF_SVE_AN_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise shift by vector (predicated) + case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd case IF_SVE_CM_3A: // ........xx...... ...gggmmmmmddddd -- SVE conditionally broadcast element to vector - case IF_SVE_EP_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 integer halving add/subtract (predicated) - case IF_SVE_ER_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 integer pairwise arithmetic - case IF_SVE_ET_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 saturating add/subtract - case IF_SVE_EU_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 saturating/rounding bitwise shift left - // (predicated) assert(insOptsScalableStandard(id->idInsOpt())); // xx assert(isVectorRegister(id->idReg1())); // ddddd assert(isLowPredicateRegister(id->idReg2())); // ggg @@ -12605,7 +12608,7 @@ void emitter::emitInsSveSanityCheck(instrDesc* id) assert(isVectorRegister(id->idReg1())); // ddddd assert(isLowPredicateRegister(id->idReg2())); // ggg assert(isVectorRegister(id->idReg3())); // mmmmm - assert(isValidVectorElemsize(id->idOpSize())); + assert(isScalableVectorSize(id->idOpSize())); break; // Scalable to FP SIMD scalar. @@ -12615,7 +12618,7 @@ void emitter::emitInsSveSanityCheck(instrDesc* id) assert(isVectorRegister(id->idReg1())); // ddddd assert(isLowPredicateRegister(id->idReg2())); // ggg assert(isVectorRegister(id->idReg3())); // mmmmm - assert(isValidVectorElemsizeSveFloat(id->idOpSize())); + assert(isScalableVectorSize(id->idOpSize())); break; // Scalable to general register. @@ -12644,35 +12647,19 @@ void emitter::emitInsSveSanityCheck(instrDesc* id) break; // Scalable, unpredicated - case IF_SVE_AT_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE integer add/subtract vectors (unpredicated) - case IF_SVE_BD_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply vectors (unpredicated) - case IF_SVE_BE_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 signed saturating doubling multiply high - // (unpredicated) + case IF_SVE_AT_3A: // ........xx.mmmmm ......nnnnnddddd case IF_SVE_BG_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE bitwise shift by wide elements (unpredicated) - case IF_SVE_BK_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE floating-point trig select coefficient - case IF_SVE_BR_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE permute vector segments case IF_SVE_BZ_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE table lookup (three sources) case IF_SVE_BZ_3A_A: // ........xx.mmmmm ......nnnnnddddd -- SVE table lookup (three sources) - case IF_SVE_CA_3A: // ........xx.mmmmm ......nnnnnddddd -- sve_int_perm_tbxquads case IF_SVE_EH_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE integer dot product (unpredicated) - case IF_SVE_EL_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply-add long + case IF_SVE_EL_3A: // ........xx.mmmmm ......nnnnnddddd case IF_SVE_EM_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 saturating multiply-add high - case IF_SVE_EN_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 saturating multiply-add interleaved long - case IF_SVE_EO_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 saturating multiply-add long - case IF_SVE_EV_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE integer clamp case IF_SVE_EX_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE permute vector elements (quadwords) - case IF_SVE_FL_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract long + case IF_SVE_FL_3A: // ........xx.mmmmm ......nnnnnddddd case IF_SVE_FM_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract wide - case IF_SVE_FN_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply long - case IF_SVE_FP_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 bitwise exclusive-or interleaved - case IF_SVE_FQ_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 bitwise permute - case IF_SVE_FS_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract interleaved long case IF_SVE_FW_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer absolute difference and accumulate - case IF_SVE_FX_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer absolute difference and accumulate long - case IF_SVE_GC_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract narrow high part - case IF_SVE_GF_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 histogram generation (segment) - case IF_SVE_GW_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE FP clamp - case IF_SVE_HK_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE floating-point arithmetic (unpredicated) + case IF_SVE_GC_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract narrow high part + case IF_SVE_GF_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 histogram generation (segment) assert(insOptsScalableStandard(id->idInsOpt())); // xx assert(isVectorRegister(id->idReg1())); // ddddd assert(isVectorRegister(id->idReg2())); // nnnnn @@ -12894,7 +12881,6 @@ void emitter::emitInsSveSanityCheck(instrDesc* id) case IF_SVE_FN_3B: // ...........mmmmm ......nnnnnddddd -- SVE2 integer multiply long case IF_SVE_FO_3A: // ...........mmmmm ......nnnnnddddd -- SVE integer matrix multiply accumulate case IF_SVE_AT_3B: // ...........mmmmm ......nnnnnddddd -- SVE integer add/subtract vectors (unpredicated) - case IF_SVE_AU_3A: // ...........mmmmm ......nnnnnddddd -- SVE bitwise logical operations (unpredicated) case IF_SVE_BD_3B: // ...........mmmmm ......nnnnnddddd -- SVE2 integer multiply vectors (unpredicated) case IF_SVE_EF_3A: // ...........mmmmm ......nnnnnddddd -- SVE two-way dot product case IF_SVE_EI_3A: // ...........mmmmm ......nnnnnddddd -- SVE mixed sign dot product @@ -12914,6 +12900,12 @@ void emitter::emitInsSveSanityCheck(instrDesc* id) assert(isVectorRegister(id->idReg2())); // nnnnn/mmmmm assert(isVectorRegister(id->idReg3())); // mmmmm/aaaaa break; + case IF_SVE_AU_3A: // ...........mmmmm ......nnnnnddddd -- SVE bitwise logical operations (unpredicated) + assert(insOptsScalable(id->idInsOpt())); + assert(isVectorRegister(id->idReg1())); // ddddd + assert(isVectorRegister(id->idReg2())); // nnnnn/mmmmm + assert((id->idIns() == INS_sve_mov) || isVectorRegister(id->idReg3())); // mmmmm/aaaaa + break; case IF_SVE_HA_3A_F: // ...........mmmmm ......nnnnnddddd -- SVE BFloat16 floating-point dot product case IF_SVE_EW_3A: // ...........mmmmm ......nnnnnddddd -- SVE2 multiply-add (checked pointer) @@ -13208,11 +13200,20 @@ void emitter::emitInsSveSanityCheck(instrDesc* id) // Scalable, widening to scalar SIMD. case IF_SVE_AI_3A: // ........xx...... ...gggnnnnnddddd -- SVE integer add reduction (predicated) - assert(insOptsScalableWide(id->idInsOpt())); // xx + switch (id->idIns()) + { + case INS_sve_saddv: + assert(insOptsScalableWide(id->idInsOpt())); // xx + break; + + default: + assert(insOptsScalableStandard(id->idInsOpt())); // xx + break; + } assert(isVectorRegister(id->idReg1())); // ddddd assert(isLowPredicateRegister(id->idReg2())); // ggg assert(isVectorRegister(id->idReg3())); // mmmmm - assert(isValidVectorElemsizeWidening(id->idOpSize())); + assert(isScalableVectorSize(id->idOpSize())); break; // Scalable, possibly FP. @@ -14367,13 +14368,18 @@ void emitter::emitInsSveSanityCheck(instrDesc* id) break; case IF_SVE_BJ_2A: // ........xx...... ......nnnnnddddd -- SVE floating-point exponential accelerator - case IF_SVE_CH_2A: // ........xx...... ......nnnnnddddd -- SVE unpack vector elements case IF_SVE_HF_2A: // ........xx...... ......nnnnnddddd -- SVE floating-point reciprocal estimate (unpredicated) assert(insOptsScalableAtLeastHalf(id->idInsOpt())); assert(isVectorRegister(id->idReg1())); assert(isVectorRegister(id->idReg2())); break; + case IF_SVE_CH_2A: // ........xx...... ......nnnnnddddd -- SVE unpack vector elements + assert(insOptsScalableWide(id->idInsOpt())); + assert(isVectorRegister(id->idReg1())); + assert(isVectorRegister(id->idReg2())); + break; + case IF_SVE_BF_2A: // ........xx.xxiii ......nnnnnddddd -- SVE bitwise shift by immediate (unpredicated) case IF_SVE_FT_2A: // ........xx.xxiii ......nnnnnddddd -- SVE2 bitwise shift and insert case IF_SVE_FU_2A: // ........xx.xxiii ......nnnnnddddd -- SVE2 bitwise shift right and accumulate @@ -14458,17 +14464,8 @@ void emitter::emitDispInsSveHelp(instrDesc* id) bitMaskImm bmi; // ., /M, ., . - case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations (predicated) - case IF_SVE_AB_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer add/subtract vectors (predicated) + case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd case IF_SVE_AC_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer divide vectors (predicated) - case IF_SVE_AD_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer min/max/difference (predicated) - case IF_SVE_AE_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer multiply vectors (predicated) - case IF_SVE_AN_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise shift by vector (predicated) - case IF_SVE_EP_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 integer halving add/subtract (predicated) - case IF_SVE_ER_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 integer pairwise arithmetic - case IF_SVE_ET_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 saturating add/subtract - case IF_SVE_EU_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 saturating/rounding bitwise shift left - // (predicated) case IF_SVE_GR_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 floating-point pairwise operations case IF_SVE_HL_3A: // ........xx...... ...gggmmmmmddddd -- SVE floating-point arithmetic (predicated) // .D, /M, .D, .D @@ -14523,18 +14520,7 @@ void emitter::emitDispInsSveHelp(instrDesc* id) break; // ., ., . - case IF_SVE_AT_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE integer add/subtract vectors (unpredicated) - case IF_SVE_BD_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply vectors (unpredicated) - case IF_SVE_BE_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 signed saturating doubling multiply high - // (unpredicated) - case IF_SVE_FP_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 bitwise exclusive-or interleaved - case IF_SVE_FQ_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 bitwise permute - case IF_SVE_BK_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE floating-point trig select coefficient - case IF_SVE_BR_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE permute vector segments - case IF_SVE_CA_3A: // ........xx.mmmmm ......nnnnnddddd -- sve_int_perm_tbxquads - case IF_SVE_EV_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE integer clamp - case IF_SVE_GW_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE FP clamp - case IF_SVE_HK_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE floating-point arithmetic (unpredicated) + case IF_SVE_AT_3A: // ........xx.mmmmm ......nnnnnddddd // ., ., . case IF_SVE_EM_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 saturating multiply-add high case IF_SVE_FW_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer absolute difference and accumulate @@ -14544,7 +14530,6 @@ void emitter::emitDispInsSveHelp(instrDesc* id) case IF_SVE_HD_3A_A: // ...........mmmmm ......nnnnnddddd -- SVE floating point matrix multiply accumulate // .D, .D, .D case IF_SVE_AT_3B: // ...........mmmmm ......nnnnnddddd -- SVE integer add/subtract vectors (unpredicated) - case IF_SVE_AU_3A: // ...........mmmmm ......nnnnnddddd -- SVE bitwise logical operations (unpredicated) // .B, .B, .B case IF_SVE_GF_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 histogram generation (segment) case IF_SVE_BD_3B: // ...........mmmmm ......nnnnnddddd -- SVE2 integer multiply vectors (unpredicated) @@ -14559,6 +14544,20 @@ void emitter::emitDispInsSveHelp(instrDesc* id) emitDispSveReg(id->idReg3(), id->idInsOpt(), false); // mmmmm/aaaaa break; + // .D, .D, .D + case IF_SVE_AU_3A: // ...........mmmmm ......nnnnnddddd -- SVE bitwise logical operations (unpredicated) + emitDispSveReg(id->idReg1(), id->idInsOpt(), true); // ddddd + if (id->idIns() == INS_sve_mov) + { + emitDispSveReg(id->idReg2(), id->idInsOpt(), false); // nnnnn/mmmmm + } + else + { + emitDispSveReg(id->idReg2(), id->idInsOpt(), true); // nnnnn/mmmmm + emitDispSveReg(id->idReg3(), id->idInsOpt(), false); // mmmmm/aaaaa + } + break; + // .D, .D, .D case IF_SVE_EW_3A: // ...........mmmmm ......nnnnnddddd -- SVE2 multiply-add (checked pointer) // .D, .D, .D @@ -15507,14 +15506,9 @@ void emitter::emitDispInsSveHelp(instrDesc* id) } // ., ., . - case IF_SVE_EL_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply-add long - case IF_SVE_EN_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 saturating multiply-add interleaved long - case IF_SVE_EO_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 saturating multiply-add long - case IF_SVE_FX_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer absolute difference and accumulate long + case IF_SVE_EL_3A: // ........xx.mmmmm ......nnnnnddddd // ., ., . - case IF_SVE_FL_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract long - case IF_SVE_FN_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply long - case IF_SVE_FS_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract interleaved long + case IF_SVE_FL_3A: // ........xx.mmmmm ......nnnnnddddd // .Q, .D, .D case IF_SVE_FN_3B: // ...........mmmmm ......nnnnnddddd -- SVE2 integer multiply long { @@ -16211,8 +16205,8 @@ void emitter::emitDispInsSveHelp(instrDesc* id) case IF_SVE_HH_2A: // ................ ......nnnnnddddd -- SVE2 FP8 upconverts // ., . case IF_SVE_CH_2A: // ........xx...... ......nnnnnddddd -- SVE unpack vector elements - emitDispSveReg(id->idReg1(), id->idInsOpt(), true); - emitDispSveReg(id->idReg2(), (insOpts)((unsigned)id->idInsOpt() - 1), false); + emitDispSveReg(id->idReg1(), (insOpts)(id->idInsOpt() + 1), true); + emitDispSveReg(id->idReg2(), id->idInsOpt(), false); break; // ., . @@ -16315,19 +16309,77 @@ void emitter::getInsSveExecutionCharacteristics(instrDesc* id, insExecutionChara instruction ins = id->idIns(); switch (id->idInsFmt()) { - // Predicate logical - case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations (predicated) - result.insLatency = PERFSCORE_LATENCY_1C; - result.insThroughput = PERFSCORE_THROUGHPUT_1C; - break; + case IF_SVE_AA_3A: // ........xx...... ...gggmmmmmddddd + switch (ins) + { + case INS_sve_add: + case INS_sve_sub: + case INS_sve_subr: + case INS_sve_sabd: + case INS_sve_smax: + case INS_sve_smin: + case INS_sve_uabd: + case INS_sve_umax: + case INS_sve_umin: + case INS_sve_shadd: + case INS_sve_shsub: + case INS_sve_shsubr: + case INS_sve_srhadd: + case INS_sve_uhadd: + case INS_sve_uhsub: + case INS_sve_uhsubr: + case INS_sve_urhadd: + case INS_sve_addp: + case INS_sve_smaxp: + case INS_sve_sminp: + case INS_sve_umaxp: + case INS_sve_uminp: + case INS_sve_sqadd: + case INS_sve_sqsub: + case INS_sve_uqadd: + case INS_sve_uqsub: + case INS_sve_sqsubr: + case INS_sve_suqadd: + case INS_sve_uqsubr: + case INS_sve_usqadd: + result.insLatency = PERFSCORE_LATENCY_2C; + result.insThroughput = PERFSCORE_THROUGHPUT_2X; + break; - // Arithmetic, basic - case IF_SVE_AB_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer add/subtract vectors (predicated) - case IF_SVE_EP_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 integer halving add/subtract (predicated) - // Max/min, basic and pairwise - case IF_SVE_AD_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer min/max/difference (predicated) - result.insLatency = PERFSCORE_LATENCY_2C; - result.insThroughput = PERFSCORE_THROUGHPUT_2X; + case INS_sve_mul: + case INS_sve_smulh: + case INS_sve_umulh: + case INS_sve_sqrshl: + case INS_sve_sqrshlr: + case INS_sve_sqshl: + case INS_sve_sqshlr: + case INS_sve_srshl: + case INS_sve_srshlr: + case INS_sve_uqrshl: + case INS_sve_uqrshlr: + case INS_sve_uqshl: + case INS_sve_uqshlr: + case INS_sve_urshl: + case INS_sve_urshlr: + result.insLatency = PERFSCORE_LATENCY_4C; + result.insThroughput = PERFSCORE_THROUGHPUT_1C; + break; + + case INS_sve_asrr: + case INS_sve_lslr: + case INS_sve_lsrr: + case INS_sve_asr: + case INS_sve_lsl: + case INS_sve_lsr: + result.insLatency = PERFSCORE_LATENCY_2C; + result.insThroughput = PERFSCORE_THROUGHPUT_1C; + break; + + default: + result.insLatency = PERFSCORE_LATENCY_1C; + result.insThroughput = PERFSCORE_THROUGHPUT_1C; + break; + } break; // Divides, 32 bit (Note: worse for 64 bit) @@ -16336,12 +16388,6 @@ void emitter::getInsSveExecutionCharacteristics(instrDesc* id, insExecutionChara result.insThroughput = PERFSCORE_THROUGHPUT_11C; // 1/11 to 1/7 break; - // Multiply, B, H, S element size (Note: D element size is slightly slower) - case IF_SVE_AE_3A: // ........xx...... ...gggmmmmmddddd -- SVE integer multiply vectors (predicated) - result.insLatency = PERFSCORE_LATENCY_4C; - result.insThroughput = PERFSCORE_THROUGHPUT_1C; - break; - // Reduction, logical case IF_SVE_AF_3A: // ........xx...... ...gggnnnnnddddd -- SVE bitwise logical reduction (predicated) result.insLatency = PERFSCORE_LATENCY_6C; @@ -16387,7 +16433,6 @@ void emitter::getInsSveExecutionCharacteristics(instrDesc* id, insExecutionChara break; // Arithmetic, shift - case IF_SVE_AN_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise shift by vector (predicated) case IF_SVE_AO_3A: // ........xx...... ...gggmmmmmddddd -- SVE bitwise shift by wide elements (predicated) result.insLatency = PERFSCORE_LATENCY_2C; result.insThroughput = PERFSCORE_THROUGHPUT_1C; @@ -16435,9 +16480,6 @@ void emitter::getInsSveExecutionCharacteristics(instrDesc* id, insExecutionChara // (predicated) case IF_SVE_AS_4A: // ........xx.mmmmm ...gggaaaaaddddd -- SVE integer multiply-add writing multiplicand // (predicated) - case IF_SVE_BD_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply vectors (unpredicated) - case IF_SVE_BE_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 signed saturating doubling multiply high - // (unpredicated) case IF_SVE_FD_3A: // .........i.iimmm ......nnnnnddddd -- SVE2 integer multiply (indexed) case IF_SVE_FD_3B: // ...........iimmm ......nnnnnddddd -- SVE2 integer multiply (indexed) case IF_SVE_FD_3C: // ...........immmm ......nnnnnddddd -- SVE2 integer multiply (indexed) @@ -16554,10 +16596,7 @@ void emitter::getInsSveExecutionCharacteristics(instrDesc* id, insExecutionChara case IF_SVE_GX_3C: // .........i.iimmm ......nnnnnddddd -- SVE floating-point multiply (indexed) case IF_SVE_EW_3A: // ...........mmmmm ......nnnnnddddd -- SVE2 multiply-add (checked pointer) case IF_SVE_EW_3B: // ...........mmmmm ......aaaaaddddd -- SVE2 multiply-add (checked pointer) - case IF_SVE_CA_3A: // ........xx.mmmmm ......nnnnnddddd -- sve_int_perm_tbxquads - case IF_SVE_EV_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE integer clamp case IF_SVE_EX_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE permute vector elements (quadwords) - case IF_SVE_GW_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE FP clamp case IF_SVE_AT_3B: // ...........mmmmm ......nnnnnddddd -- SVE integer add/subtract vectors (unpredicated) case IF_SVE_AB_3B: // ................ ...gggmmmmmddddd -- SVE integer add/subtract vectors (predicated) case IF_SVE_HL_3B: // ................ ...gggmmmmmddddd -- SVE floating-point arithmetic (predicated) @@ -16571,31 +16610,54 @@ void emitter::getInsSveExecutionCharacteristics(instrDesc* id, insExecutionChara result.insLatency = PERFSCORE_LATENCY_1C; // need to fix break; - case IF_SVE_AT_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE integer add/subtract vectors (unpredicated) - case IF_SVE_BR_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE permute vector segments - case IF_SVE_BR_3B: // ...........mmmmm ......nnnnnddddd -- SVE permute vector segments - case IF_SVE_BZ_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE table lookup (three sources) - case IF_SVE_BZ_3A_A: // ........xx.mmmmm ......nnnnnddddd -- SVE table lookup (three sources) - case IF_SVE_FL_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract long - case IF_SVE_FM_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract wide - case IF_SVE_FP_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 bitwise exclusive-or interleaved - case IF_SVE_FS_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract interleaved long - case IF_SVE_GC_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract narrow high part - case IF_SVE_GF_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 histogram generation (segment) - case IF_SVE_AU_3A: // ...........mmmmm ......nnnnnddddd -- SVE bitwise logical operations (unpredicated) - case IF_SVE_GI_4A: // ........xx.mmmmm ...gggnnnnnddddd -- SVE2 histogram generation (vector) - case IF_SVE_BB_2A: // ...........nnnnn .....iiiiiiddddd -- SVE stack frame adjustment - case IF_SVE_BC_1A: // ................ .....iiiiiiddddd -- SVE stack frame size - result.insThroughput = PERFSCORE_THROUGHPUT_2C; - result.insLatency = PERFSCORE_LATENCY_2C; - break; + case IF_SVE_AT_3A: // ........xx.mmmmm ......nnnnnddddd + switch (ins) + { + case INS_sve_tbxq: + case INS_sve_sclamp: + case INS_sve_uclamp: + case INS_sve_fclamp: + result.insThroughput = PERFSCORE_THROUGHPUT_1C; // need to fix + result.insLatency = PERFSCORE_LATENCY_1C; // need to fix + break; - case IF_SVE_FQ_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 bitwise permute - result.insThroughput = PERFSCORE_THROUGHPUT_2X; - result.insLatency = PERFSCORE_LATENCY_6C; + case INS_sve_bext: + case INS_sve_bdep: + case INS_sve_bgrp: + result.insThroughput = PERFSCORE_THROUGHPUT_2X; + result.insLatency = PERFSCORE_LATENCY_6C; + break; + + case INS_sve_ftssel: + case INS_sve_fmul: + case INS_sve_ftsmul: + result.insThroughput = PERFSCORE_THROUGHPUT_2C; + result.insLatency = PERFSCORE_LATENCY_3C; + break; + + case INS_sve_frecps: + case INS_sve_frsqrts: + result.insThroughput = PERFSCORE_THROUGHPUT_2C; + result.insLatency = PERFSCORE_LATENCY_4C; + break; + + case INS_sve_mul: + case INS_sve_smulh: + case INS_sve_umulh: + case INS_sve_sqdmulh: + case INS_sve_sqrdmulh: + result.insThroughput = PERFSCORE_THROUGHPUT_2X; + result.insLatency = PERFSCORE_LATENCY_5C; + break; + + default: + result.insThroughput = PERFSCORE_THROUGHPUT_2C; + result.insLatency = PERFSCORE_LATENCY_2C; + break; + } break; - case IF_SVE_FN_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply long + case IF_SVE_FL_3A: // ........xx.mmmmm ......nnnnnddddd switch (ins) { case INS_sve_smullb: @@ -16607,18 +16669,34 @@ void emitter::getInsSveExecutionCharacteristics(instrDesc* id, insExecutionChara result.insThroughput = PERFSCORE_THROUGHPUT_1C; result.insLatency = PERFSCORE_LATENCY_4C; break; + case INS_sve_pmullb: case INS_sve_pmullt: result.insThroughput = PERFSCORE_THROUGHPUT_1C; result.insLatency = PERFSCORE_LATENCY_2C; break; + default: - // all other instructions - perfScoreUnhandledInstruction(id, &result); + result.insThroughput = PERFSCORE_THROUGHPUT_2C; + result.insLatency = PERFSCORE_LATENCY_2C; break; } break; + case IF_SVE_BR_3B: // ...........mmmmm ......nnnnnddddd -- SVE permute vector segments + case IF_SVE_BZ_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE table lookup (three sources) + case IF_SVE_BZ_3A_A: // ........xx.mmmmm ......nnnnnddddd -- SVE table lookup (three sources) + case IF_SVE_FM_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract wide + case IF_SVE_GC_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract narrow high part + case IF_SVE_GF_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 histogram generation (segment) + case IF_SVE_AU_3A: // ...........mmmmm ......nnnnnddddd -- SVE bitwise logical operations (unpredicated) + case IF_SVE_GI_4A: // ........xx.mmmmm ...gggnnnnnddddd -- SVE2 histogram generation (vector) + case IF_SVE_BB_2A: // ...........nnnnn .....iiiiiiddddd -- SVE stack frame adjustment + case IF_SVE_BC_1A: // ................ .....iiiiiiddddd -- SVE stack frame size + result.insThroughput = PERFSCORE_THROUGHPUT_2C; + result.insLatency = PERFSCORE_LATENCY_2C; + break; + case IF_SVE_BA_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE index generation (register start, register // increment) case IF_SVE_AX_1A: // ........xx.iiiii ......iiiiiddddd -- SVE index generation (immediate start, immediate @@ -16652,7 +16730,6 @@ void emitter::getInsSveExecutionCharacteristics(instrDesc* id, insExecutionChara result.insLatency = PERFSCORE_LATENCY_2C; break; - case IF_SVE_BK_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE floating-point trig select coefficient case IF_SVE_FO_3A: // ...........mmmmm ......nnnnnddddd -- SVE integer matrix multiply accumulate result.insThroughput = PERFSCORE_THROUGHPUT_2C; result.insLatency = PERFSCORE_LATENCY_3C; @@ -16762,11 +16839,8 @@ void emitter::getInsSveExecutionCharacteristics(instrDesc* id, insExecutionChara case IF_SVE_FJ_3A: // ...........iimmm ....i.nnnnnddddd -- SVE2 saturating multiply-add (indexed) case IF_SVE_FJ_3B: // ...........immmm ....i.nnnnnddddd -- SVE2 saturating multiply-add (indexed) case IF_SVE_EH_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE integer dot product (unpredicated) - case IF_SVE_EL_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply-add long - case IF_SVE_EN_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 saturating multiply-add interleaved long - case IF_SVE_EO_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 saturating multiply-add long + case IF_SVE_EL_3A: // ........xx.mmmmm ......nnnnnddddd case IF_SVE_FW_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer absolute difference and accumulate - case IF_SVE_FX_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE2 integer absolute difference and accumulate long result.insLatency = PERFSCORE_LATENCY_4C; result.insThroughput = PERFSCORE_THROUGHPUT_1C; break; @@ -16996,13 +17070,6 @@ void emitter::getInsSveExecutionCharacteristics(instrDesc* id, insExecutionChara result.insThroughput = PERFSCORE_THROUGHPUT_2X; break; - // Arithmetic, pairwise add - // Max/min, basic and pairwise - case IF_SVE_ER_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 integer pairwise arithmetic - result.insLatency = PERFSCORE_LATENCY_2C; - result.insThroughput = PERFSCORE_THROUGHPUT_2X; - break; - case IF_SVE_ES_3A: // ........xx...... ...gggnnnnnddddd -- SVE2 integer unary operations (predicated) switch (ins) { @@ -17028,15 +17095,6 @@ void emitter::getInsSveExecutionCharacteristics(instrDesc* id, insExecutionChara } break; - // Arithmetic, complex - case IF_SVE_ET_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 saturating add/subtract - result.insLatency = PERFSCORE_LATENCY_2C; - result.insThroughput = PERFSCORE_THROUGHPUT_2X; - break; - - // Arithmetic, shift complex - case IF_SVE_EU_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 saturating/rounding bitwise shift left - // (predicated) // Arithmetic, pairwise add and accum long case IF_SVE_EQ_3A: // ........xx...... ...gggnnnnnddddd -- SVE2 integer pairwise add and accumulate long case IF_SVE_EF_3A: // ...........mmmmm ......nnnnnddddd -- SVE two-way dot product @@ -17068,34 +17126,6 @@ void emitter::getInsSveExecutionCharacteristics(instrDesc* id, insExecutionChara result.insThroughput = PERFSCORE_THROUGHPUT_2X; break; - case IF_SVE_HK_3A: // ........xx.mmmmm ......nnnnnddddd -- SVE floating-point arithmetic (unpredicated) - switch (ins) - { - case INS_sve_frecps: - case INS_sve_frsqrts: - result.insThroughput = PERFSCORE_THROUGHPUT_2C; - result.insLatency = PERFSCORE_LATENCY_4C; - break; - - case INS_sve_fmul: - case INS_sve_ftsmul: - result.insThroughput = PERFSCORE_THROUGHPUT_2C; - result.insLatency = PERFSCORE_LATENCY_3C; - break; - - case INS_sve_fadd: - case INS_sve_fsub: - result.insThroughput = PERFSCORE_THROUGHPUT_2C; - result.insLatency = PERFSCORE_LATENCY_2C; - break; - - default: - // all other instructions - perfScoreUnhandledInstruction(id, &result); - break; - } - break; - case IF_SVE_HL_3A: // ........xx...... ...gggmmmmmddddd -- SVE floating-point arithmetic (predicated) switch (ins) { diff --git a/src/coreclr/jit/emitfmtsarm64sve.h b/src/coreclr/jit/emitfmtsarm64sve.h index cd27f567478c..91b409bc7f4f 100644 --- a/src/coreclr/jit/emitfmtsarm64sve.h +++ b/src/coreclr/jit/emitfmtsarm64sve.h @@ -137,12 +137,10 @@ IF_DEF(SVE_2BS, IS_NONE, NONE) // Instruction has 2 possible encoding types, ty * x -- element size *****************************************************************************/ -IF_DEF(SVE_AA_3A, IS_NONE, NONE) // SVE_AA_3A ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations (predicated) -IF_DEF(SVE_AB_3A, IS_NONE, NONE) // SVE_AB_3A ........xx...... ...gggmmmmmddddd -- SVE integer add/subtract vectors (predicated) +// SVE_AA_3A ........xx...... ...gggmmmmmddddd -- SVE bitwise logical operations + SVE integer add/subtract/multiply vectors + SVE integer min/max/difference + SVE bitwise shift by vector + SVE2 integer halving add/subtract + SVE2 integer pairwise arithmetic + SVE2 saturating add/subtract + SVE2 saturating/rounding bitwise shift left (predicated) +IF_DEF(SVE_AA_3A, IS_NONE, NONE) IF_DEF(SVE_AB_3B, IS_NONE, NONE) // SVE_AB_3B ................ ...gggmmmmmddddd -- SVE integer add/subtract vectors (predicated) IF_DEF(SVE_AC_3A, IS_NONE, NONE) // SVE_AC_3A ........xx...... ...gggmmmmmddddd -- SVE integer divide vectors (predicated) -IF_DEF(SVE_AD_3A, IS_NONE, NONE) // SVE_AD_3A ........xx...... ...gggmmmmmddddd -- SVE integer min/max/difference (predicated) -IF_DEF(SVE_AE_3A, IS_NONE, NONE) // SVE_AE_3A ........xx...... ...gggmmmmmddddd -- SVE integer multiply vectors (predicated) IF_DEF(SVE_AF_3A, IS_NONE, NONE) // SVE_AF_3A ........xx...... ...gggnnnnnddddd -- SVE bitwise logical reduction (predicated) IF_DEF(SVE_AG_3A, IS_NONE, NONE) // SVE_AG_3A ........xx...... ...gggnnnnnddddd -- SVE bitwise logical reduction (quadwords) IF_DEF(SVE_AH_3A, IS_NONE, NONE) // SVE_AH_3A ........xx.....M ...gggnnnnnddddd -- SVE constructive prefix (predicated) @@ -151,13 +149,13 @@ IF_DEF(SVE_AJ_3A, IS_NONE, NONE) // SVE_AJ_3A ........xx...... ...gggnnnnnddd IF_DEF(SVE_AK_3A, IS_NONE, NONE) // SVE_AK_3A ........xx...... ...gggnnnnnddddd -- SVE integer min/max reduction (predicated) IF_DEF(SVE_AL_3A, IS_NONE, NONE) // SVE_AL_3A ........xx...... ...gggnnnnnddddd -- SVE integer min/max reduction (quadwords) IF_DEF(SVE_AM_2A, IS_NONE, NONE) // SVE_AM_2A ........xx...... ...gggxxiiiddddd -- SVE bitwise shift by immediate (predicated) -IF_DEF(SVE_AN_3A, IS_NONE, NONE) // SVE_AN_3A ........xx...... ...gggmmmmmddddd -- SVE bitwise shift by vector (predicated) IF_DEF(SVE_AO_3A, IS_NONE, NONE) // SVE_AO_3A ........xx...... ...gggmmmmmddddd -- SVE bitwise shift by wide elements (predicated) IF_DEF(SVE_AP_3A, IS_NONE, NONE) // SVE_AP_3A ........xx...... ...gggnnnnnddddd -- SVE bitwise unary operations (predicated) IF_DEF(SVE_AQ_3A, IS_NONE, NONE) // SVE_AQ_3A ........xx...... ...gggnnnnnddddd -- SVE integer unary operations (predicated) IF_DEF(SVE_AR_4A, IS_NONE, NONE) // SVE_AR_4A ........xx.mmmmm ...gggnnnnnddddd -- SVE integer multiply-accumulate writing addend (predicated) IF_DEF(SVE_AS_4A, IS_NONE, NONE) // SVE_AS_4A ........xx.mmmmm ...gggaaaaaddddd -- SVE integer multiply-add writing multiplicand (predicated) -IF_DEF(SVE_AT_3A, IS_NONE, NONE) // SVE_AT_3A ........xx.mmmmm ......nnnnnddddd -- SVE integer add/subtract vectors (unpredicated) +// SVE_AT_3A ........xx.mmmmm ......nnnnnddddd -- SVE integer add/subtract vectors (unpredicated) + SVE2 integer multiply vectors (unpredicated) + SVE2 signed saturating doubling multiply high (unpredicated) + SVE floating-point trig select coefficient + SVE permute vector segments + sve_int_perm_tbxquads + SVE integer clamp + SVE2 bitwise exclusive-or interleaved + SVE2 bitwise permute + SVE FP clamp + SVE floating-point arithmetic (unpredicated) +IF_DEF(SVE_AT_3A, IS_NONE, NONE) IF_DEF(SVE_AT_3B, IS_NONE, NONE) // SVE_AT_3B ...........mmmmm ......nnnnnddddd -- SVE integer add/subtract vectors (unpredicated) IF_DEF(SVE_AU_3A, IS_NONE, NONE) // SVE_AU_3A ...........mmmmm ......nnnnnddddd -- SVE bitwise logical operations (unpredicated) IF_DEF(SVE_AV_3A, IS_NONE, NONE) // SVE_AV_3A ...........mmmmm ......kkkkkddddd -- SVE2 bitwise ternary operations @@ -168,9 +166,7 @@ IF_DEF(SVE_AZ_2A, IS_NONE, NONE) // SVE_AZ_2A ........xx.iiiii ......nnnnnddd IF_DEF(SVE_BA_3A, IS_NONE, NONE) // SVE_BA_3A ........xx.mmmmm ......nnnnnddddd -- SVE index generation (register start, register increment) IF_DEF(SVE_BB_2A, IS_NONE, NONE) // SVE_BB_2A ...........nnnnn .....iiiiiiddddd -- SVE stack frame adjustment IF_DEF(SVE_BC_1A, IS_NONE, NONE) // SVE_BC_1A ................ .....iiiiiiddddd -- SVE stack frame size -IF_DEF(SVE_BD_3A, IS_NONE, NONE) // SVE_BD_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply vectors (unpredicated) IF_DEF(SVE_BD_3B, IS_NONE, NONE) // SVE_BD_3B ...........mmmmm ......nnnnnddddd -- SVE2 integer multiply vectors (unpredicated) -IF_DEF(SVE_BE_3A, IS_NONE, NONE) // SVE_BE_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 signed saturating doubling multiply high (unpredicated) IF_DEF(SVE_BF_2A, IS_NONE, NONE) // SVE_BF_2A ........xx.xxiii ......nnnnnddddd -- SVE bitwise shift by immediate (unpredicated) IF_DEF(SVE_BG_3A, IS_NONE, NONE) // SVE_BG_3A ........xx.mmmmm ......nnnnnddddd -- SVE bitwise shift by wide elements (unpredicated) IF_DEF(SVE_BH_3A, IS_NONE, NONE) // SVE_BH_3A .........x.mmmmm ....hhnnnnnddddd -- SVE address generation @@ -178,7 +174,6 @@ IF_DEF(SVE_BH_3B, IS_NONE, NONE) // SVE_BH_3B ...........mmmmm ....hhnnnnnddd IF_DEF(SVE_BH_3B_A, IS_NONE, NONE) // SVE_BH_3B_A ...........mmmmm ....hhnnnnnddddd -- IF_DEF(SVE_BI_2A, IS_NONE, NONE) // SVE_BI_2A ................ ......nnnnnddddd -- SVE constructive prefix (unpredicated) IF_DEF(SVE_BJ_2A, IS_NONE, NONE) // SVE_BJ_2A ........xx...... ......nnnnnddddd -- SVE floating-point exponential accelerator -IF_DEF(SVE_BK_3A, IS_NONE, NONE) // SVE_BK_3A ........xx.mmmmm ......nnnnnddddd -- SVE floating-point trig select coefficient IF_DEF(SVE_BL_1A, IS_NONE, NONE) // SVE_BL_1A ............iiii ......pppppddddd -- SVE element count IF_DEF(SVE_BM_1A, IS_NONE, NONE) // SVE_BM_1A ............iiii ......pppppddddd -- SVE inc/dec register by element count IF_DEF(SVE_BN_1A, IS_NONE, NONE) // SVE_BN_1A ............iiii ......pppppddddd -- SVE inc/dec vector by element count @@ -187,7 +182,6 @@ IF_DEF(SVE_BO_1A_A, IS_NONE, NONE) // SVE_BO_1A_A ...........Xiiii ......pppppd IF_DEF(SVE_BP_1A, IS_NONE, NONE) // SVE_BP_1A ............iiii ......pppppddddd -- SVE saturating inc/dec vector by element count IF_DEF(SVE_BQ_2A, IS_NONE, NONE) // SVE_BQ_2A ...........iiiii ...iiinnnnnddddd -- SVE extract vector (immediate offset, destructive) IF_DEF(SVE_BQ_2B, IS_NONE, NONE) // SVE_BQ_2B ...........iiiii ...iiimmmmmddddd -- SVE extract vector (immediate offset, destructive) -IF_DEF(SVE_BR_3A, IS_NONE, NONE) // SVE_BR_3A ........xx.mmmmm ......nnnnnddddd -- SVE permute vector segments IF_DEF(SVE_BR_3B, IS_NONE, NONE) // SVE_BR_3B ...........mmmmm ......nnnnnddddd -- SVE permute vector segments IF_DEF(SVE_BS_1A, IS_NONE, NONE) // SVE_BS_1A ..............ii iiiiiiiiiiiddddd -- SVE bitwise logical with immediate (unpredicated) IF_DEF(SVE_BT_1A, IS_NONE, NONE) // SVE_BT_1A ..............ii iiiiiiiiiiiddddd -- SVE broadcast bitmask immediate @@ -201,7 +195,6 @@ IF_DEF(SVE_BX_2A, IS_NONE, NONE) // SVE_BX_2A ...........ixxxx ......nnnnnddd IF_DEF(SVE_BY_2A, IS_NONE, NONE) // SVE_BY_2A ............iiii ......mmmmmddddd -- sve_int_perm_extq IF_DEF(SVE_BZ_3A, IS_NONE, NONE) // SVE_BZ_3A ........xx.mmmmm ......nnnnnddddd -- SVE table lookup (three sources) IF_DEF(SVE_BZ_3A_A, IS_NONE, NONE) // SVE_BZ_3A_A ........xx.mmmmm ......nnnnnddddd -- -IF_DEF(SVE_CA_3A, IS_NONE, NONE) // SVE_CA_3A ........xx.mmmmm ......nnnnnddddd -- sve_int_perm_tbxquads IF_DEF(SVE_CB_2A, IS_NONE, NONE) // SVE_CB_2A ........xx...... ......nnnnnddddd -- SVE broadcast general register IF_DEF(SVE_CC_2A, IS_NONE, NONE) // SVE_CC_2A ........xx...... ......mmmmmddddd -- SVE insert SIMD&FP scalar register IF_DEF(SVE_CD_2A, IS_NONE, NONE) // SVE_CD_2A ........xx...... ......mmmmmddddd -- SVE insert general register @@ -280,17 +273,11 @@ IF_DEF(SVE_EH_3A, IS_NONE, NONE) // SVE_EH_3A ........xx.mmmmm ......nnnnnddd IF_DEF(SVE_EI_3A, IS_NONE, NONE) // SVE_EI_3A ...........mmmmm ......nnnnnddddd -- SVE mixed sign dot product IF_DEF(SVE_EJ_3A, IS_NONE, NONE) // SVE_EJ_3A ........xx.mmmmm ....rrnnnnnddddd -- SVE2 complex integer dot product IF_DEF(SVE_EK_3A, IS_NONE, NONE) // SVE_EK_3A ........xx.mmmmm ....rrnnnnnddddd -- SVE2 complex integer multiply-add -IF_DEF(SVE_EL_3A, IS_NONE, NONE) // SVE_EL_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply-add long +// SVE_EL_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply-add long + SVE2 saturating multiply-add interleaved long + SVE2 saturating multiply-add long + SVE2 integer absolute difference and accumulate long +IF_DEF(SVE_EL_3A, IS_NONE, NONE) IF_DEF(SVE_EM_3A, IS_NONE, NONE) // SVE_EM_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 saturating multiply-add high -IF_DEF(SVE_EN_3A, IS_NONE, NONE) // SVE_EN_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 saturating multiply-add interleaved long -IF_DEF(SVE_EO_3A, IS_NONE, NONE) // SVE_EO_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 saturating multiply-add long -IF_DEF(SVE_EP_3A, IS_NONE, NONE) // SVE_EP_3A ........xx...... ...gggmmmmmddddd -- SVE2 integer halving add/subtract (predicated) IF_DEF(SVE_EQ_3A, IS_NONE, NONE) // SVE_EQ_3A ........xx...... ...gggnnnnnddddd -- SVE2 integer pairwise add and accumulate long -IF_DEF(SVE_ER_3A, IS_NONE, NONE) // SVE_ER_3A ........xx...... ...gggmmmmmddddd -- SVE2 integer pairwise arithmetic IF_DEF(SVE_ES_3A, IS_NONE, NONE) // SVE_ES_3A ........xx...... ...gggnnnnnddddd -- SVE2 integer unary operations (predicated) -IF_DEF(SVE_ET_3A, IS_NONE, NONE) // SVE_ET_3A ........xx...... ...gggmmmmmddddd -- SVE2 saturating add/subtract -IF_DEF(SVE_EU_3A, IS_NONE, NONE) // SVE_EU_3A ........xx...... ...gggmmmmmddddd -- SVE2 saturating/rounding bitwise shift left (predicated) -IF_DEF(SVE_EV_3A, IS_NONE, NONE) // SVE_EV_3A ........xx.mmmmm ......nnnnnddddd -- SVE integer clamp IF_DEF(SVE_EW_3A, IS_NONE, NONE) // SVE_EW_3A ...........mmmmm ......nnnnnddddd -- SVE2 multiply-add (checked pointer) IF_DEF(SVE_EW_3B, IS_NONE, NONE) // SVE_EW_3B ...........mmmmm ......aaaaaddddd -- SVE2 multiply-add (checked pointer) IF_DEF(SVE_EX_3A, IS_NONE, NONE) // SVE_EX_3A ........xx.mmmmm ......nnnnnddddd -- SVE permute vector elements (quadwords) @@ -323,20 +310,16 @@ IF_DEF(SVE_FJ_3B, IS_NONE, NONE) // SVE_FJ_3B ...........immmm ....i.nnnnnddd IF_DEF(SVE_FK_3A, IS_NONE, NONE) // SVE_FK_3A .........i.iimmm ......nnnnnddddd -- SVE2 saturating multiply-add high (indexed) IF_DEF(SVE_FK_3B, IS_NONE, NONE) // SVE_FK_3B ...........iimmm ......nnnnnddddd -- SVE2 saturating multiply-add high (indexed) IF_DEF(SVE_FK_3C, IS_NONE, NONE) // SVE_FK_3C ...........immmm ......nnnnnddddd -- SVE2 saturating multiply-add high (indexed) -IF_DEF(SVE_FL_3A, IS_NONE, NONE) // SVE_FL_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract long +// SVE_FL_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract long + SVE2 integer multiply long + SVE2 integer add/subtract interleaved long +IF_DEF(SVE_FL_3A, IS_NONE, NONE) IF_DEF(SVE_FM_3A, IS_NONE, NONE) // SVE_FM_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract wide -IF_DEF(SVE_FN_3A, IS_NONE, NONE) // SVE_FN_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 integer multiply long IF_DEF(SVE_FN_3B, IS_NONE, NONE) // SVE_FN_3B ...........mmmmm ......nnnnnddddd -- SVE2 integer multiply long IF_DEF(SVE_FO_3A, IS_NONE, NONE) // SVE_FO_3A ...........mmmmm ......nnnnnddddd -- SVE integer matrix multiply accumulate -IF_DEF(SVE_FP_3A, IS_NONE, NONE) // SVE_FP_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 bitwise exclusive-or interleaved -IF_DEF(SVE_FQ_3A, IS_NONE, NONE) // SVE_FQ_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 bitwise permute IF_DEF(SVE_FR_2A, IS_NONE, NONE) // SVE_FR_2A .........x.xxiii ......nnnnnddddd -- SVE2 bitwise shift left long -IF_DEF(SVE_FS_3A, IS_NONE, NONE) // SVE_FS_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract interleaved long IF_DEF(SVE_FT_2A, IS_NONE, NONE) // SVE_FT_2A ........xx.xxiii ......nnnnnddddd -- SVE2 bitwise shift and insert IF_DEF(SVE_FU_2A, IS_NONE, NONE) // SVE_FU_2A ........xx.xxiii ......nnnnnddddd -- SVE2 bitwise shift right and accumulate IF_DEF(SVE_FV_2A, IS_NONE, NONE) // SVE_FV_2A ........xx...... .....rmmmmmddddd -- SVE2 complex integer add IF_DEF(SVE_FW_3A, IS_NONE, NONE) // SVE_FW_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 integer absolute difference and accumulate -IF_DEF(SVE_FX_3A, IS_NONE, NONE) // SVE_FX_3A ........xx.mmmmm ......nnnnnddddd -- SVE2 integer absolute difference and accumulate long IF_DEF(SVE_FY_3A, IS_NONE, NONE) // SVE_FY_3A .........x.mmmmm ......nnnnnddddd -- SVE2 integer add/subtract long with carry IF_DEF(SVE_FZ_2A, IS_NONE, NONE) // SVE_FZ_2A ................ ......nnnn.ddddd -- SME2 multi-vec extract narrow IF_DEF(SVE_GA_2A, IS_NONE, NONE) // SVE_GA_2A ............iiii ......nnnn.ddddd -- SME2 multi-vec shift narrow @@ -366,7 +349,6 @@ IF_DEF(SVE_GU_3A, IS_NONE, NONE) // SVE_GU_3A ...........iimmm ......nnnnnddd IF_DEF(SVE_GU_3B, IS_NONE, NONE) // SVE_GU_3B ...........immmm ......nnnnnddddd -- SVE floating-point multiply-add (indexed) IF_DEF(SVE_GU_3C, IS_NONE, NONE) // SVE_GU_3C .........i.iimmm ......nnnnnddddd -- SVE floating-point multiply-add (indexed) IF_DEF(SVE_GV_3A, IS_NONE, NONE) // SVE_GV_3A ...........immmm ....rrnnnnnddddd -- SVE floating-point complex multiply-add (indexed) -IF_DEF(SVE_GW_3A, IS_NONE, NONE) // SVE_GW_3A ........xx.mmmmm ......nnnnnddddd -- SVE FP clamp IF_DEF(SVE_GW_3B, IS_NONE, NONE) // SVE_GW_3B ...........mmmmm ......nnnnnddddd -- SVE FP clamp IF_DEF(SVE_GX_3A, IS_NONE, NONE) // SVE_GX_3A ...........iimmm ......nnnnnddddd -- SVE floating-point multiply (indexed) IF_DEF(SVE_GX_3B, IS_NONE, NONE) // SVE_GX_3B ...........immmm ......nnnnnddddd -- SVE floating-point multiply (indexed) @@ -388,7 +370,6 @@ IF_DEF(SVE_HG_2A, IS_NONE, NONE) // SVE_HG_2A ................ ......nnnn.ddd IF_DEF(SVE_HH_2A, IS_NONE, NONE) // SVE_HH_2A ................ ......nnnnnddddd -- SVE2 FP8 upconverts IF_DEF(SVE_HI_3A, IS_NONE, NONE) // SVE_HI_3A ........xx...... ...gggnnnnn.DDDD -- SVE floating-point compare with zero IF_DEF(SVE_HJ_3A, IS_NONE, NONE) // SVE_HJ_3A ........xx...... ...gggmmmmmddddd -- SVE floating-point serial reduction (predicated) -IF_DEF(SVE_HK_3A, IS_NONE, NONE) // SVE_HK_3A ........xx.mmmmm ......nnnnnddddd -- SVE floating-point arithmetic (unpredicated) IF_DEF(SVE_HK_3B, IS_NONE, NONE) // SVE_HK_3B ...........mmmmm ......nnnnnddddd -- SVE floating-point arithmetic (unpredicated) IF_DEF(SVE_HL_3A, IS_NONE, NONE) // SVE_HL_3A ........xx...... ...gggmmmmmddddd -- SVE floating-point arithmetic (predicated) IF_DEF(SVE_HL_3B, IS_NONE, NONE) // SVE_HL_3B ................ ...gggmmmmmddddd -- SVE floating-point arithmetic (predicated) diff --git a/src/coreclr/jit/emitloongarch64.cpp b/src/coreclr/jit/emitloongarch64.cpp index c69ea7c5a36e..9a10ef23e989 100644 --- a/src/coreclr/jit/emitloongarch64.cpp +++ b/src/coreclr/jit/emitloongarch64.cpp @@ -2375,6 +2375,8 @@ void emitter::emitIns_I_la(emitAttr size, regNumber reg, ssize_t imm) * * For LOONGARCH xreg, xmul and disp are never used and should always be 0/REG_NA. * + * noSafePoint - force not making this call a safe point in partially interruptible code + * * Please consult the "debugger team notification" comment in genFnProlog(). */ @@ -2392,7 +2394,8 @@ void emitter::emitIns_Call(EmitCallType callType, regNumber xreg /* = REG_NA */, unsigned xmul /* = 0 */, ssize_t disp /* = 0 */, - bool isJump /* = false */) + bool isJump /* = false */, + bool noSafePoint /* = false */) { /* Sanity check the arguments depending on callType */ @@ -2464,11 +2467,32 @@ void emitter::emitIns_Call(EmitCallType callType, /* Update the emitter's live GC ref sets */ + // If the method returns a GC ref, mark RBM_INTRET appropriately + if (retSize == EA_GCREF) + { + gcrefRegs |= RBM_INTRET; + } + else if (retSize == EA_BYREF) + { + byrefRegs |= RBM_INTRET; + } + + // If is a multi-register return method is called, mark RBM_INTRET_1 appropriately + if (secondRetSize == EA_GCREF) + { + gcrefRegs |= RBM_INTRET_1; + } + else if (secondRetSize == EA_BYREF) + { + byrefRegs |= RBM_INTRET_1; + } + VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars); emitThisGCrefRegs = gcrefRegs; emitThisByrefRegs = byrefRegs; - id->idSetIsNoGC(emitNoGChelper(methHnd)); + // for the purpose of GC safepointing tail-calls are not real calls + id->idSetIsNoGC(isJump || noSafePoint || emitNoGChelper(methHnd)); /* Set the instruction - special case jumping a function */ instruction ins; @@ -3848,8 +3872,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) } } -#ifdef DEBUG - if (emitComp->opts.disAsm || emitComp->verbose) + if (emitComp->opts.disAsm INDEBUG(|| emitComp->verbose)) { code_t* cp = (code_t*)(*dp + writeableOffset); while ((BYTE*)cp != dstRW) @@ -3859,6 +3882,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) } } +#ifdef DEBUG if (emitComp->compDebugBreak) { // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for @@ -3882,8 +3906,6 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) /*****************************************************************************/ /*****************************************************************************/ -#ifdef DEBUG - // clang-format off static const char* const RegNames[] = { @@ -3964,19 +3986,21 @@ void emitter::emitDisInsName(code_t code, const BYTE* addr, instrDesc* id) { const BYTE* insAdr = addr - writeableOffset; - bool disOpcode = !emitComp->opts.disDiffable; - bool disAddr = emitComp->opts.disAddr; - if (disAddr) +#ifdef DEBUG + if (emitComp->opts.disAddr) { printf(" 0x%llx", insAdr); } printf(" "); - if (disOpcode) + if (!emitComp->opts.disDiffable) { printf("%08X ", code); } +#else + printf(" "); +#endif const int regd = code & 0x1f; const int regj = (code >> 5) & 0x1f; @@ -4190,8 +4214,9 @@ void emitter::emitDisInsName(code_t code, const BYTE* addr, instrDesc* id) return; case DF_F_RG12I: { - tmp = ((code >> 10) & 0xfff); - printf("%s, %s, 0x%x\n", RegNames[regd + 32], RegNames[regj], tmp); + tmp = code << 10; + tmp >>= 20; + printf("%s, %s, %d\n", RegNames[regd + 32], RegNames[regj], tmp); return; } case DF_F_FG: @@ -4539,51 +4564,16 @@ void emitter::emitDispIns( } } +#ifdef DEBUG /***************************************************************************** * * Display a stack frame reference. */ - void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm) { - printf("["); - - if (varx < 0) - printf("TEMP_%02u", -varx); - else - emitComp->gtDispLclVar(+varx, false); - - if (disp < 0) - printf("-0x%02x", -disp); - else if (disp > 0) - printf("+0x%02x", +disp); - - printf("]"); - - if (varx >= 0 && emitComp->opts.varNames) - { - LclVarDsc* varDsc; - const char* varName; - - assert((unsigned)varx < emitComp->lvaCount); - varDsc = emitComp->lvaTable + varx; - varName = emitComp->compLocalVarName(varx, offs); - - if (varName) - { - printf("'%s", varName); - - if (disp < 0) - printf("-%d", -disp); - else if (disp > 0) - printf("+%d", +disp); - - printf("'"); - } - } + NYI_LOONGARCH64("emitDispFrameRef-----unused on LoongArch64."); } - -#endif // DEBUG +#endif // Generate code for a load or store operation with a potentially complex addressing mode // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset] @@ -4620,7 +4610,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR if (offset != 0) { - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); if (isValidSimm12(offset)) { @@ -4761,7 +4751,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR else { // We require a tmpReg to hold the offset - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); // First load/store tmpReg with the large offset constant emitIns_I_la(EA_PTRSIZE, tmpReg, offset); @@ -5092,7 +5082,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, if ((dst->gtFlags & GTF_UNSIGNED) == 0) { - saveOperReg2 = dst->GetSingleTempReg(); + saveOperReg2 = codeGen->internalRegisters.GetSingle(dst); assert((saveOperReg2 != REG_RA) && (saveOperReg2 != REG_R21)); assert(REG_RA != regOp1); assert(saveOperReg2 != regOp2); diff --git a/src/coreclr/jit/emitloongarch64.h b/src/coreclr/jit/emitloongarch64.h index 135f9cf40067..e07e9d47e12e 100644 --- a/src/coreclr/jit/emitloongarch64.h +++ b/src/coreclr/jit/emitloongarch64.h @@ -19,10 +19,6 @@ struct CnsVal bool cnsReloc; }; -#ifdef DEBUG -/************************************************************************/ -/* Debug-only routines to display instructions */ -/************************************************************************/ enum insDisasmFmt { DF_G_INVALID = 0, @@ -108,7 +104,6 @@ code_t emitGetInsMask(int ins); insDisasmFmt emitGetInsFmt(instruction ins); void emitDispInst(instruction ins); void emitDisInsName(code_t code, const BYTE* addr, instrDesc* id); -#endif // DEBUG void emitIns_J_cond_la(instruction ins, BasicBlock* dst, regNumber reg1 = REG_R0, regNumber reg2 = REG_R0); void emitIns_I_la(emitAttr attr, regNumber reg, ssize_t imm); @@ -333,7 +328,7 @@ enum EmitCallType EC_FUNC_TOKEN, // Direct call to a helper/static/nonvirtual/global method // EC_FUNC_TOKEN_INDIR, // Indirect call to a helper/static/nonvirtual/global method - // EC_FUNC_ADDR, // Direct call to an absolute address + // EC_FUNC_ADDR, // Direct call to an absolute address EC_INDIR_R, // Indirect call via register @@ -350,11 +345,12 @@ void emitIns_Call(EmitCallType callType, regMaskTP gcrefRegs, regMaskTP byrefRegs, const DebugInfo& di, - regNumber ireg = REG_NA, - regNumber xreg = REG_NA, - unsigned xmul = 0, - ssize_t disp = 0, - bool isJump = false); + regNumber ireg = REG_NA, + regNumber xreg = REG_NA, + unsigned xmul = 0, + ssize_t disp = 0, + bool isJump = false, + bool noSafePoint = false); unsigned emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code); diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 533d26ef2307..e292e260ad99 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -479,7 +479,7 @@ void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t case INS_auipc: assert(reg != REG_R0); assert(isGeneralRegister(reg)); - assert((((size_t)imm) >> 20) == 0); + assert(isValidSimm20(imm)); code |= reg << 7; code |= (imm & 0xfffff) << 12; @@ -956,7 +956,9 @@ void emitter::emitIns_R_C( id->idCodeSize(8); } else - id->idCodeSize(16); + { + id->idCodeSize(24); + } if (EA_IS_GCREF(attr)) { @@ -1056,11 +1058,11 @@ void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNu // auipc reg, offset-hi20 // addi reg, reg, offset-lo12 // - // else: 3-ins: - // lui tmp, dst-hi-20bits + // else: 5-ins: + // lui tmp, dst-lo-20bits // addi tmp, tmp, dst-lo-12bits - // lui reg, 0xff << 12 - // slli reg, reg, 32 + // lui reg, dst-hi-15bits + // slli reg, reg, 20 // add reg, tmp, reg instrDesc* id = emitNewInstr(attr); @@ -1253,7 +1255,7 @@ void emitter::emitLoadImmediate(emitAttr size, regNumber reg, ssize_t imm) // Since ADDIW use sign extension fo immediate // we have to adjust higher 19 bit loaded by LUI // for case when low part is bigger than 0x800. - UINT32 high19 = (high31 + 0x800) >> 12; + INT32 high19 = ((int32_t)(high31 + 0x800)) >> 12; emitIns_R_I(INS_lui, size, reg, high19); emitIns_R_R_I(INS_addiw, size, reg, reg, high31 & 0xFFF); @@ -1285,6 +1287,8 @@ void emitter::emitLoadImmediate(emitAttr size, regNumber reg, ssize_t imm) * If callType is one of these emitCallTypes, addr has to be NULL. * EC_INDIR_R : "call ireg". * + * noSafePoint - force not making this call a safe point in partially interruptible code + * */ void emitter::emitIns_Call(EmitCallType callType, @@ -1301,7 +1305,8 @@ void emitter::emitIns_Call(EmitCallType callType, regNumber xreg /* = REG_NA */, unsigned xmul /* = 0 */, ssize_t disp /* = 0 */, - bool isJump /* = false */) + bool isJump /* = false */, + bool noSafePoint /* = false */) { /* Sanity check the arguments depending on callType */ @@ -1373,11 +1378,32 @@ void emitter::emitIns_Call(EmitCallType callType, /* Update the emitter's live GC ref sets */ + // If the method returns a GC ref, mark RBM_INTRET appropriately + if (retSize == EA_GCREF) + { + gcrefRegs |= RBM_INTRET; + } + else if (retSize == EA_BYREF) + { + byrefRegs |= RBM_INTRET; + } + + // If is a multi-register return method is called, mark RBM_INTRET_1 appropriately + if (secondRetSize == EA_GCREF) + { + gcrefRegs |= RBM_INTRET_1; + } + else if (secondRetSize == EA_BYREF) + { + byrefRegs |= RBM_INTRET_1; + } + VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars); emitThisGCrefRegs = gcrefRegs; emitThisByrefRegs = byrefRegs; - id->idSetIsNoGC(emitNoGChelper(methHnd)); + // for the purpose of GC safepointing tail-calls are not real calls + id->idSetIsNoGC(isJump || noSafePoint || emitNoGChelper(methHnd)); /* Set the instruction - special case jumping a function */ instruction ins; @@ -1448,11 +1474,14 @@ void emitter::emitIns_Call(EmitCallType callType, VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars)); } } - - id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token - id->idDebugOnlyInfo()->idCallSig = sigInfo; #endif // DEBUG + if (m_debugInfoSize > 0) + { + INDEBUG(id->idDebugOnlyInfo()->idCallSig = sigInfo); + id->idDebugOnlyInfo()->idMemCookie = reinterpret_cast(methHnd); // method token + } + #ifdef LATE_DISASM if (addr != nullptr) { @@ -1562,7 +1591,7 @@ unsigned emitter::emitOutputCall(const insGroup* ig, BYTE* dst, instrDesc* id, c // jalr t2 ssize_t imm = (ssize_t)(id->idAddr()->iiaAddr); - assert((imm >> 32) <= 0xff); + assert((uint64_t)(imm >> 32) <= 0x7fff); // RISC-V Linux Kernel SV48 int reg2 = (int)(imm & 1); imm -= reg2; @@ -2960,14 +2989,16 @@ BYTE* emitter::emitOutputInstr_OptsRcReloc(BYTE* dst, instruction* ins, unsigned BYTE* emitter::emitOutputInstr_OptsRcNoReloc(BYTE* dst, instruction* ins, unsigned offset, regNumber reg1) { const ssize_t immediate = reinterpret_cast(emitConsBlock) + offset; - assertCodeLength(static_cast(immediate), 40); + assertCodeLength(static_cast(immediate), 48); // RISC-V Linux Kernel SV48 const regNumber rsvdReg = codeGen->rsGetRsvdReg(); const instruction lastIns = (*ins == INS_jal) ? (*ins = INS_addi) : *ins; - const ssize_t high = immediate >> 11; + const ssize_t high = immediate >> 16; dst += emitOutput_UTypeInstr(dst, INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(high)); dst += emitOutput_ITypeInstr(dst, INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(high)); + dst += emitOutput_ITypeInstr(dst, INS_slli, rsvdReg, rsvdReg, 5); + dst += emitOutput_ITypeInstr(dst, INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<5>(immediate >> 11)); dst += emitOutput_ITypeInstr(dst, INS_slli, rsvdReg, rsvdReg, 11); dst += emitOutput_ITypeInstr(dst, lastIns, reg1, rsvdReg, LowerNBitsOfWord<11>(immediate)); return dst; @@ -3003,15 +3034,15 @@ BYTE* emitter::emitOutputInstr_OptsRlReloc(BYTE* dst, ssize_t igOffs, regNumber BYTE* emitter::emitOutputInstr_OptsRlNoReloc(BYTE* dst, ssize_t igOffs, regNumber reg1) { const ssize_t immediate = reinterpret_cast(emitCodeBlock) + igOffs; - assertCodeLength(static_cast(immediate), 32 + 20); + assertCodeLength(static_cast(immediate), 48); // RISC-V Linux Kernel SV48 const regNumber rsvdReg = codeGen->rsGetRsvdReg(); const ssize_t upperSignExt = UpperWordOfDoubleWordDoubleSignExtend<32, 52>(immediate); dst += emitOutput_UTypeInstr(dst, INS_lui, rsvdReg, UpperNBitsOfWordSignExtend<20>(immediate)); dst += emitOutput_ITypeInstr(dst, INS_addi, rsvdReg, rsvdReg, LowerNBitsOfWord<12>(immediate)); - dst += emitOutput_ITypeInstr(dst, INS_addi, reg1, REG_ZERO, LowerNBitsOfWord<12>(upperSignExt)); - dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 32); + dst += emitOutput_UTypeInstr(dst, INS_lui, reg1, LowerNBitsOfWord<16>(upperSignExt)); + dst += emitOutput_ITypeInstr(dst, INS_slli, reg1, reg1, 20); dst += emitOutput_RTypeInstr(dst, INS_add, reg1, reg1, rsvdReg); return dst; } @@ -4460,7 +4491,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR if (offset != 0) { - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); if (isValidSimm12(offset)) { @@ -4493,7 +4524,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg)); noway_assert(tmpReg != index->GetRegNum()); - regNumber scaleReg = indir->GetSingleTempReg(); + regNumber scaleReg = codeGen->internalRegisters.GetSingle(indir); // Then load/store dataReg from/to [tmpReg + index*scale] emitIns_R_R_I(INS_slli, addType, scaleReg, index->GetRegNum(), lsl); emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, scaleReg); @@ -4602,7 +4633,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR else { // We require a tmpReg to hold the offset - regNumber tmpReg = indir->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(indir); // First load/store tmpReg with the large offset constant emitLoadImmediate(EA_PTRSIZE, tmpReg, offset); @@ -4768,7 +4799,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, assert(ins == INS_addi || ins == INS_addiw || ins == INS_andi || ins == INS_ori || ins == INS_xori); - regNumber tempReg = needCheckOv ? dst->ExtractTempReg() : REG_NA; + regNumber tempReg = needCheckOv ? codeGen->internalRegisters.Extract(dst) : REG_NA; if (needCheckOv) { @@ -4820,7 +4851,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, } else { - regNumber tempReg = needCheckOv ? dst->ExtractTempReg() : REG_NA; + regNumber tempReg = needCheckOv ? codeGen->internalRegisters.Extract(dst) : REG_NA; switch (dst->OperGet()) { @@ -4894,7 +4925,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, } else { - regNumber tempReg2 = dst->ExtractTempReg(); + regNumber tempReg2 = codeGen->internalRegisters.Extract(dst); assert(tempReg2 != dstReg); assert(tempReg2 != src1Reg); assert(tempReg2 != src2Reg); @@ -5000,7 +5031,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, else { tempReg1 = REG_RA; - tempReg2 = dst->ExtractTempReg(); + tempReg2 = codeGen->internalRegisters.Extract(dst); assert(tempReg1 != tempReg2); assert(tempReg1 != saveOperReg1); assert(tempReg2 != saveOperReg2); diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 07e603a70afb..5409c76233de 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -310,7 +310,7 @@ enum EmitCallType EC_FUNC_TOKEN, // Direct call to a helper/static/nonvirtual/global method // EC_FUNC_TOKEN_INDIR, // Indirect call to a helper/static/nonvirtual/global method - // EC_FUNC_ADDR, // Direct call to an absolute address + // EC_FUNC_ADDR, // Direct call to an absolute address // EC_FUNC_VIRTUAL, // Call to a virtual method (using the vtable) EC_INDIR_R, // Indirect call via register @@ -331,11 +331,12 @@ void emitIns_Call(EmitCallType callType, regMaskTP gcrefRegs, regMaskTP byrefRegs, const DebugInfo& di, - regNumber ireg = REG_NA, - regNumber xreg = REG_NA, - unsigned xmul = 0, - ssize_t disp = 0, - bool isJump = false); + regNumber ireg = REG_NA, + regNumber xreg = REG_NA, + unsigned xmul = 0, + ssize_t disp = 0, + bool isJump = false, + bool noSafePoint = false); unsigned emitOutputCall(const insGroup* ig, BYTE* dst, instrDesc* id, code_t code); diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 6bf148cf2d88..e8ff553f80cc 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -1226,13 +1226,9 @@ bool emitter::TakesEvexPrefix(const instrDesc* id) const return true; } - if (HasEmbeddedBroadcast(id)) + if (HasEmbeddedBroadcast(id) || HasEmbeddedMask(id)) { // Requires the EVEX encoding due to embedded functionality - // - // TODO-XArch-AVX512: This needs to return true when the id includes: - // * embedded rounding control - // * other EVEX specific functionality return true; } @@ -1369,7 +1365,7 @@ emitter::code_t emitter::AddEvexPrefix(const instrDesc* id, code_t code, emitAtt { case IF_RWR_RRD_ARD_RRD: { - assert(id->idGetEvexAaaContext() == 0); + assert(!id->idIsEvexAaaContextSet()); CnsVal cnsVal; emitGetInsAmdCns(id, &cnsVal); @@ -1380,7 +1376,7 @@ emitter::code_t emitter::AddEvexPrefix(const instrDesc* id, code_t code, emitAtt case IF_RWR_RRD_MRD_RRD: { - assert(id->idGetEvexAaaContext() == 0); + assert(!id->idIsEvexAaaContextSet()); CnsVal cnsVal; emitGetInsDcmCns(id, &cnsVal); @@ -1391,7 +1387,7 @@ emitter::code_t emitter::AddEvexPrefix(const instrDesc* id, code_t code, emitAtt case IF_RWR_RRD_SRD_RRD: { - assert(id->idGetEvexAaaContext() == 0); + assert(!id->idIsEvexAaaContextSet()); CnsVal cnsVal; emitGetInsCns(id, &cnsVal); @@ -1402,7 +1398,7 @@ emitter::code_t emitter::AddEvexPrefix(const instrDesc* id, code_t code, emitAtt case IF_RWR_RRD_RRD_RRD: { - assert(id->idGetEvexAaaContext() == 0); + assert(!id->idIsEvexAaaContextSet()); maskReg = id->idReg4(); break; } @@ -5641,7 +5637,7 @@ void emitter::emitStoreSimd12ToLclOffset(unsigned varNum, unsigned offset, regNu } else { - regNumber tmpReg = tmpRegProvider->GetSingleTempReg(); + regNumber tmpReg = codeGen->internalRegisters.GetSingle(tmpRegProvider); assert(isFloatReg(tmpReg)); // Extract upper 4 bytes from data @@ -6606,7 +6602,8 @@ void emitter::emitIns_R_R(instruction ins, emitAttr attr, regNumber reg1, regNum * Add an instruction with two register operands and an integer constant. */ -void emitter::emitIns_R_R_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int ival) +void emitter::emitIns_R_R_I( + instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int ival, insOpts instOptions) { #ifdef TARGET_AMD64 // mov reg, imm64 is the only opcode which takes a full 8 byte immediate @@ -6636,6 +6633,9 @@ void emitter::emitIns_R_R_I(instruction ins, emitAttr attr, regNumber reg1, regN code = insCodeRM(ins); } + assert((instOptions & INS_OPTS_EVEX_b_MASK) == 0); + SetEvexEmbMaskIfNeeded(id, instOptions); + UNATIVE_OFFSET sz = emitInsSizeRR(id, code, ival); id->idCodeSize(sz); @@ -6668,16 +6668,17 @@ void emitter::emitIns_AR(instruction ins, emitAttr attr, regNumber base, int off // and that does not return a value // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op2Reg -- The register of the second operand -// op3Reg -- The register of the third operand -// base -- The base register used for the memory address (first operand) -// offs -- The offset from base +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op2Reg -- The register of the second operand +// op3Reg -- The register of the third operand +// base -- The base register used for the memory address (first operand) +// offs -- The offset from base +// instOptions -- The options that modify how the instruction is generated // void emitter::emitIns_AR_R_R( - instruction ins, emitAttr attr, regNumber op2Reg, regNumber op3Reg, regNumber base, int offs) + instruction ins, emitAttr attr, regNumber op2Reg, regNumber op3Reg, regNumber base, int offs, insOpts instOptions) { assert(IsAvx512OrPriorInstruction(ins)); assert(IsThreeOperandAVXInstruction(ins)); @@ -6692,6 +6693,9 @@ void emitter::emitIns_AR_R_R( id->idAddr()->iiaAddrMode.amBaseReg = base; id->idAddr()->iiaAddrMode.amIndxReg = REG_NA; + assert((instOptions & INS_OPTS_EVEX_b_MASK) == 0); + SetEvexEmbMaskIfNeeded(id, instOptions); + UNATIVE_OFFSET sz = emitInsSizeAM(id, insCodeMR(ins)); id->idCodeSize(sz); @@ -6699,7 +6703,7 @@ void emitter::emitIns_AR_R_R( emitCurIGsize += sz; } -void emitter::emitIns_R_A(instruction ins, emitAttr attr, regNumber reg1, GenTreeIndir* indir) +void emitter::emitIns_R_A(instruction ins, emitAttr attr, regNumber reg1, GenTreeIndir* indir, insOpts instOptions) { ssize_t offs = indir->Offset(); instrDesc* id = emitNewInstrAmd(attr, offs); @@ -6709,6 +6713,9 @@ void emitter::emitIns_R_A(instruction ins, emitAttr attr, regNumber reg1, GenTre emitHandleMemOp(indir, id, emitInsModeFormat(ins, IF_RRD_ARD), ins); + SetEvexBroadcastIfNeeded(id, instOptions); + SetEvexEmbMaskIfNeeded(id, instOptions); + UNATIVE_OFFSET sz = emitInsSizeAM(id, insCodeRM(ins)); id->idCodeSize(sz); @@ -6716,7 +6723,8 @@ void emitter::emitIns_R_A(instruction ins, emitAttr attr, regNumber reg1, GenTre emitCurIGsize += sz; } -void emitter::emitIns_R_A_I(instruction ins, emitAttr attr, regNumber reg1, GenTreeIndir* indir, int ival) +void emitter::emitIns_R_A_I( + instruction ins, emitAttr attr, regNumber reg1, GenTreeIndir* indir, int ival, insOpts instOptions) { noway_assert(emitVerifyEncodable(ins, EA_SIZE(attr), reg1)); assert(IsAvx512OrPriorInstruction(ins)); @@ -6740,6 +6748,9 @@ void emitter::emitIns_R_A_I(instruction ins, emitAttr attr, regNumber reg1, GenT code = insCodeRM(ins); } + SetEvexBroadcastIfNeeded(id, instOptions); + SetEvexEmbMaskIfNeeded(id, instOptions); + UNATIVE_OFFSET sz = emitInsSizeAM(id, code, ival); id->idCodeSize(sz); @@ -6747,8 +6758,13 @@ void emitter::emitIns_R_A_I(instruction ins, emitAttr attr, regNumber reg1, GenT emitCurIGsize += sz; } -void emitter::emitIns_R_C_I( - instruction ins, emitAttr attr, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs, int ival) +void emitter::emitIns_R_C_I(instruction ins, + emitAttr attr, + regNumber reg1, + CORINFO_FIELD_HANDLE fldHnd, + int offs, + int ival, + insOpts instOptions) { // Static always need relocs if (!jitStaticFldIsGlobAddr(fldHnd)) @@ -6777,6 +6793,9 @@ void emitter::emitIns_R_C_I( code = insCodeRM(ins); } + SetEvexBroadcastIfNeeded(id, instOptions); + SetEvexEmbMaskIfNeeded(id, instOptions); + UNATIVE_OFFSET sz = emitInsSizeCV(id, code, ival); id->idCodeSize(sz); @@ -6784,7 +6803,8 @@ void emitter::emitIns_R_C_I( emitCurIGsize += sz; } -void emitter::emitIns_R_S_I(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs, int ival) +void emitter::emitIns_R_S_I( + instruction ins, emitAttr attr, regNumber reg1, int varx, int offs, int ival, insOpts instOptions) { noway_assert(emitVerifyEncodable(ins, EA_SIZE(attr), reg1)); assert(IsAvx512OrPriorInstruction(ins)); @@ -6811,6 +6831,9 @@ void emitter::emitIns_R_S_I(instruction ins, emitAttr attr, regNumber reg1, int code = insCodeRM(ins); } + SetEvexBroadcastIfNeeded(id, instOptions); + SetEvexEmbMaskIfNeeded(id, instOptions); + UNATIVE_OFFSET sz = emitInsSizeSV(id, code, varx, offs, ival); id->idCodeSize(sz); @@ -7029,8 +7052,14 @@ void emitter::emitIns_R_R_S( emitCurIGsize += sz; } -void emitter::emitIns_R_R_A_I( - instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, GenTreeIndir* indir, int ival, insFormat fmt) +void emitter::emitIns_R_R_A_I(instruction ins, + emitAttr attr, + regNumber reg1, + regNumber reg2, + GenTreeIndir* indir, + int ival, + insFormat fmt, + insOpts instOptions) { assert(IsAvx512OrPriorInstruction(ins)); assert(IsThreeOperandAVXInstruction(ins)); @@ -7044,6 +7073,9 @@ void emitter::emitIns_R_R_A_I( emitHandleMemOp(indir, id, fmt, ins); + SetEvexBroadcastIfNeeded(id, instOptions); + SetEvexEmbMaskIfNeeded(id, instOptions); + UNATIVE_OFFSET sz = emitInsSizeAM(id, insCodeRM(ins), ival); id->idCodeSize(sz); @@ -7074,8 +7106,14 @@ void emitter::emitIns_R_R_AR_I( emitCurIGsize += sz; } -void emitter::emitIns_R_R_C_I( - instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, CORINFO_FIELD_HANDLE fldHnd, int offs, int ival) +void emitter::emitIns_R_R_C_I(instruction ins, + emitAttr attr, + regNumber reg1, + regNumber reg2, + CORINFO_FIELD_HANDLE fldHnd, + int offs, + int ival, + insOpts instOptions) { assert(IsAvx512OrPriorInstruction(ins)); assert(IsThreeOperandAVXInstruction(ins)); @@ -7094,6 +7132,9 @@ void emitter::emitIns_R_R_C_I( id->idReg2(reg2); id->idAddr()->iiaFieldHnd = fldHnd; + SetEvexBroadcastIfNeeded(id, instOptions); + SetEvexEmbMaskIfNeeded(id, instOptions); + UNATIVE_OFFSET sz = emitInsSizeCV(id, insCodeRM(ins), ival); id->idCodeSize(sz); @@ -7105,16 +7146,17 @@ void emitter::emitIns_R_R_C_I( * emitIns_R_R_R_I: Add an instruction with three register operands and an immediate. * * Arguments: - * ins - the instruction to add - * attr - the emitter attribute for instruction - * targetReg - the target (destination) register - * reg1 - the first source register - * reg2 - the second source register - * ival - the immediate value + * ins - the instruction to add + * attr - the emitter attribute for instruction + * targetReg - the target (destination) register + * reg1 - the first source register + * reg2 - the second source register + * ival - the immediate value + * instOptions - the options that modify how the instruction is generated */ void emitter::emitIns_R_R_R_I( - instruction ins, emitAttr attr, regNumber targetReg, regNumber reg1, regNumber reg2, int ival) + instruction ins, emitAttr attr, regNumber targetReg, regNumber reg1, regNumber reg2, int ival, insOpts instOptions) { assert(IsAvx512OrPriorInstruction(ins)); assert(IsThreeOperandAVXInstruction(ins)); @@ -7126,6 +7168,9 @@ void emitter::emitIns_R_R_R_I( id->idReg2(reg1); id->idReg3(reg2); + assert((instOptions & INS_OPTS_EVEX_b_MASK) == 0); + SetEvexEmbMaskIfNeeded(id, instOptions); + UNATIVE_OFFSET sz = emitInsSizeRR(id, insCodeRM(ins), ival); id->idCodeSize(sz); @@ -7134,7 +7179,7 @@ void emitter::emitIns_R_R_R_I( } void emitter::emitIns_R_R_S_I( - instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int varx, int offs, int ival) + instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int varx, int offs, int ival, insOpts instOptions) { assert(IsAvx512OrPriorInstruction(ins)); assert(IsThreeOperandAVXInstruction(ins)); @@ -7147,6 +7192,9 @@ void emitter::emitIns_R_R_S_I( id->idReg2(reg2); id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs); + SetEvexBroadcastIfNeeded(id, instOptions); + SetEvexEmbMaskIfNeeded(id, instOptions); + #ifdef DEBUG id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs; #endif @@ -7163,18 +7211,24 @@ void emitter::emitIns_R_R_S_I( // another register operand, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op3Reg -- The register of the third operand -// indir -- The GenTreeIndir used for the memory address +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op3Reg -- The register of the third operand +// indir -- The GenTreeIndir used for the memory address +// instOptions -- The options that modify how the instruction is generated // // Remarks: // op2 is built from indir // -void emitter::emitIns_R_R_A_R( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op3Reg, GenTreeIndir* indir) +void emitter::emitIns_R_R_A_R(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op3Reg, + GenTreeIndir* indir, + insOpts instOptions) { assert(isAvxBlendv(ins) || isAvx512Blendv(ins)); assert(UseSimdEncoding()); @@ -7189,6 +7243,9 @@ void emitter::emitIns_R_R_A_R( emitHandleMemOp(indir, id, IF_RWR_RRD_ARD_RRD, ins); + SetEvexBroadcastIfNeeded(id, instOptions); + SetEvexEmbMaskIfNeeded(id, instOptions); + UNATIVE_OFFSET sz = emitInsSizeAM(id, insCodeRM(ins), ival); id->idCodeSize(sz); @@ -7201,13 +7258,14 @@ void emitter::emitIns_R_R_A_R( // offset, another register operand, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op3Reg -- The register of the third operand -// fldHnd -- The CORINFO_FIELD_HANDLE used for the memory address -// offs -- The offset added to the memory address from fldHnd +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op3Reg -- The register of the third operand +// fldHnd -- The CORINFO_FIELD_HANDLE used for the memory address +// offs -- The offset added to the memory address from fldHnd +// instOptions -- The options that modify how the instruction is generated // // Remarks: // op2 is built from fldHnd + offs @@ -7218,7 +7276,8 @@ void emitter::emitIns_R_R_C_R(instruction ins, regNumber op1Reg, regNumber op3Reg, CORINFO_FIELD_HANDLE fldHnd, - int offs) + int offs, + insOpts instOptions) { assert(isAvxBlendv(ins) || isAvx512Blendv(ins)); assert(UseSimdEncoding()); @@ -7239,6 +7298,9 @@ void emitter::emitIns_R_R_C_R(instruction ins, id->idInsFmt(IF_RWR_RRD_MRD_RRD); id->idAddr()->iiaFieldHnd = fldHnd; + SetEvexBroadcastIfNeeded(id, instOptions); + SetEvexEmbMaskIfNeeded(id, instOptions); + UNATIVE_OFFSET sz = emitInsSizeCV(id, insCodeRM(ins), ival); id->idCodeSize(sz); @@ -7251,19 +7313,26 @@ void emitter::emitIns_R_R_C_R(instruction ins, // offset, another register operand, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op3Reg -- The register of the third operand -// varx -- The variable index used for the memory address -// offs -- The offset added to the memory address from varx +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op3Reg -- The register of the third operand +// varx -- The variable index used for the memory address +// offs -- The offset added to the memory address from varx +// instOptions -- The options that modify how the instruction is generated // // Remarks: // op2 is built from varx + offs // -void emitter::emitIns_R_R_S_R( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op3Reg, int varx, int offs) +void emitter::emitIns_R_R_S_R(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op3Reg, + int varx, + int offs, + insOpts instOptions) { assert(isAvxBlendv(ins) || isAvx512Blendv(ins)); assert(UseSimdEncoding()); @@ -7278,6 +7347,9 @@ void emitter::emitIns_R_R_S_R( id->idInsFmt(IF_RWR_RRD_SRD_RRD); id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs); + SetEvexBroadcastIfNeeded(id, instOptions); + SetEvexEmbMaskIfNeeded(id, instOptions); + UNATIVE_OFFSET sz = emitInsSizeSV(id, insCodeRM(ins), varx, offs, ival); id->idCodeSize(sz); @@ -7285,8 +7357,13 @@ void emitter::emitIns_R_R_S_R( emitCurIGsize += sz; } -void emitter::emitIns_R_R_R_R( - instruction ins, emitAttr attr, regNumber targetReg, regNumber reg1, regNumber reg2, regNumber reg3) +void emitter::emitIns_R_R_R_R(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber reg1, + regNumber reg2, + regNumber reg3, + insOpts instOptions) { assert(isAvxBlendv(ins) || isAvx512Blendv(ins)); assert(UseSimdEncoding()); @@ -7300,6 +7377,9 @@ void emitter::emitIns_R_R_R_R( id->idReg3(reg2); id->idReg4(reg3); + assert((instOptions & INS_OPTS_EVEX_b_MASK) == 0); + SetEvexEmbMaskIfNeeded(id, instOptions); + UNATIVE_OFFSET sz = emitInsSizeRR(id, insCodeRM(ins)); if (!isMaskReg(reg3)) @@ -7318,7 +7398,8 @@ void emitter::emitIns_R_R_R_R( * * Add an instruction with a register + static member operands. */ -void emitter::emitIns_R_C(instruction ins, emitAttr attr, regNumber reg, CORINFO_FIELD_HANDLE fldHnd, int offs) +void emitter::emitIns_R_C( + instruction ins, emitAttr attr, regNumber reg, CORINFO_FIELD_HANDLE fldHnd, int offs, insOpts instOptions) { // Static always need relocs if (!jitStaticFldIsGlobAddr(fldHnd)) @@ -7384,6 +7465,9 @@ void emitter::emitIns_R_C(instruction ins, emitAttr attr, regNumber reg, CORINFO } } + SetEvexBroadcastIfNeeded(id, instOptions); + SetEvexEmbMaskIfNeeded(id, instOptions); + id->idCodeSize(sz); id->idAddr()->iiaFieldHnd = fldHnd; @@ -8223,11 +8307,12 @@ void emitter::emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNu // and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// ival -- The immediate value +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// ival -- The immediate value +// instOptions -- The options that modify how the instruction is generated // // Notes: // This will handle the required register copy if 'op1Reg' and 'targetReg' are not the same, and @@ -8236,14 +8321,16 @@ void emitter::emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNu // where we frequently need to handle the case of generating 3-operand or 2-operand forms // depending on what target ISA is supported. // -void emitter::emitIns_SIMD_R_R_I(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int ival) +void emitter::emitIns_SIMD_R_R_I( + instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int ival, insOpts instOptions) { if (UseSimdEncoding() || IsDstSrcImmAvxInstruction(ins)) { - emitIns_R_R_I(ins, attr, targetReg, op1Reg, ival); + emitIns_R_R_I(ins, attr, targetReg, op1Reg, ival, instOptions); } else { + assert(instOptions == INS_OPTS_NONE); emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); emitIns_R_I(ins, attr, targetReg, ival); } @@ -8254,11 +8341,12 @@ void emitter::emitIns_SIMD_R_R_I(instruction ins, emitAttr attr, regNumber targe // and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// indir -- The GenTreeIndir used for the memory address +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// indir -- The GenTreeIndir used for the memory address +// instOptions -- The options that modify how the instruction is generated // void emitter::emitIns_SIMD_R_R_A( instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, GenTreeIndir* indir, insOpts instOptions) @@ -8280,12 +8368,13 @@ void emitter::emitIns_SIMD_R_R_A( // and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// fldHnd -- The CORINFO_FIELD_HANDLE used for the memory address -// offs -- The offset added to the memory address from fldHnd +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// fldHnd -- The CORINFO_FIELD_HANDLE used for the memory address +// offs -- The offset added to the memory address from fldHnd +// instOptions -- The options that modify how the instruction is generated // void emitter::emitIns_SIMD_R_R_C(instruction ins, emitAttr attr, @@ -8312,11 +8401,12 @@ void emitter::emitIns_SIMD_R_R_C(instruction ins, // value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op2Reg -- The register of the second operand +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op2Reg -- The register of the second operand +// instOptions -- The options that modify how the instruction is generated // void emitter::emitIns_SIMD_R_R_R( instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, insOpts instOptions) @@ -8327,6 +8417,8 @@ void emitter::emitIns_SIMD_R_R_R( } else { + assert(instOptions == INS_OPTS_NONE); + // Ensure we aren't overwriting op2 assert((op2Reg != targetReg) || (op1Reg == targetReg)); @@ -8348,12 +8440,13 @@ void emitter::emitIns_SIMD_R_R_R( // and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// varx -- The variable index used for the memory address -// offs -- The offset added to the memory address from varx +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// varx -- The variable index used for the memory address +// offs -- The offset added to the memory address from varx +// instOptions -- The options that modify how the instruction is generated // void emitter::emitIns_SIMD_R_R_S( instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int varx, int offs, insOpts instOptions) @@ -8375,22 +8468,29 @@ void emitter::emitIns_SIMD_R_R_S( // an immediate operand, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// indir -- The GenTreeIndir used for the memory address -// ival -- The immediate value -// -void emitter::emitIns_SIMD_R_R_A_I( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, GenTreeIndir* indir, int ival) +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// indir -- The GenTreeIndir used for the memory address +// ival -- The immediate value +// instOptions -- The options that modify how the instruction is generated +// +void emitter::emitIns_SIMD_R_R_A_I(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + GenTreeIndir* indir, + int ival, + insOpts instOptions) { if (UseSimdEncoding()) { - emitIns_R_R_A_I(ins, attr, targetReg, op1Reg, indir, ival, IF_RWR_RRD_ARD_CNS); + emitIns_R_R_A_I(ins, attr, targetReg, op1Reg, indir, ival, IF_RWR_RRD_ARD_CNS, instOptions); } else { + assert(instOptions == INS_OPTS_NONE); emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); emitIns_R_A_I(ins, attr, targetReg, indir, ival); } @@ -8401,13 +8501,14 @@ void emitter::emitIns_SIMD_R_R_A_I( // an immediate operand, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// fldHnd -- The CORINFO_FIELD_HANDLE used for the memory address -// offs -- The offset added to the memory address from fldHnd -// ival -- The immediate value +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// fldHnd -- The CORINFO_FIELD_HANDLE used for the memory address +// offs -- The offset added to the memory address from fldHnd +// ival -- The immediate value +// instOptions -- The options that modify how the instruction is generated // void emitter::emitIns_SIMD_R_R_C_I(instruction ins, emitAttr attr, @@ -8415,14 +8516,16 @@ void emitter::emitIns_SIMD_R_R_C_I(instruction ins, regNumber op1Reg, CORINFO_FIELD_HANDLE fldHnd, int offs, - int ival) + int ival, + insOpts instOptions) { if (UseSimdEncoding()) { - emitIns_R_R_C_I(ins, attr, targetReg, op1Reg, fldHnd, offs, ival); + emitIns_R_R_C_I(ins, attr, targetReg, op1Reg, fldHnd, offs, ival, instOptions); } else { + assert(instOptions == INS_OPTS_NONE); emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); emitIns_R_C_I(ins, attr, targetReg, fldHnd, offs, ival); } @@ -8433,22 +8536,30 @@ void emitter::emitIns_SIMD_R_R_C_I(instruction ins, // and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op2Reg -- The register of the second operand -// ival -- The immediate value -// -void emitter::emitIns_SIMD_R_R_R_I( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, int ival) +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op2Reg -- The register of the second operand +// ival -- The immediate value +// instOptions -- The options that modify how the instruction is generated +// +void emitter::emitIns_SIMD_R_R_R_I(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op2Reg, + int ival, + insOpts instOptions) { if (UseSimdEncoding()) { - emitIns_R_R_R_I(ins, attr, targetReg, op1Reg, op2Reg, ival); + emitIns_R_R_R_I(ins, attr, targetReg, op1Reg, op2Reg, ival, instOptions); } else { + assert(instOptions == INS_OPTS_NONE); + // Ensure we aren't overwriting op2 assert((op2Reg != targetReg) || (op1Reg == targetReg)); @@ -8462,23 +8573,31 @@ void emitter::emitIns_SIMD_R_R_R_I( // an immediate operand, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// varx -- The variable index used for the memory address -// offs -- The offset added to the memory address from varx -// ival -- The immediate value -// -void emitter::emitIns_SIMD_R_R_S_I( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int varx, int offs, int ival) +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// varx -- The variable index used for the memory address +// offs -- The offset added to the memory address from varx +// ival -- The immediate value +// instOptions -- The options that modify how the instruction is generated +// +void emitter::emitIns_SIMD_R_R_S_I(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + int varx, + int offs, + int ival, + insOpts instOptions) { if (UseSimdEncoding()) { - emitIns_R_R_S_I(ins, attr, targetReg, op1Reg, varx, offs, ival); + emitIns_R_R_S_I(ins, attr, targetReg, op1Reg, varx, offs, ival, instOptions); } else { + assert(instOptions == INS_OPTS_NONE); emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); emitIns_R_S_I(ins, attr, targetReg, varx, offs, ival); } @@ -8490,15 +8609,21 @@ void emitter::emitIns_SIMD_R_R_S_I( // and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op2Reg -- The register of the second operand -// indir -- The GenTreeIndir used for the memory address -// -void emitter::emitIns_SIMD_R_R_R_A( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, GenTreeIndir* indir) +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op2Reg -- The register of the second operand +// indir -- The GenTreeIndir used for the memory address +// instOptions -- The options that modify how the instruction is generated +// +void emitter::emitIns_SIMD_R_R_R_A(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op2Reg, + GenTreeIndir* indir, + insOpts instOptions) { assert(IsFMAInstruction(ins) || IsPermuteVar2xInstruction(ins) || IsAVXVNNIInstruction(ins)); assert(UseSimdEncoding()); @@ -8507,7 +8632,7 @@ void emitter::emitIns_SIMD_R_R_R_A( assert((op2Reg != targetReg) || (op1Reg == targetReg)); emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); - emitIns_R_R_A(ins, attr, targetReg, op2Reg, indir); + emitIns_R_R_A(ins, attr, targetReg, op2Reg, indir, instOptions); } //------------------------------------------------------------------------ @@ -8515,13 +8640,14 @@ void emitter::emitIns_SIMD_R_R_R_A( // offset, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op2Reg -- The register of the second operand -// fldHnd -- The CORINFO_FIELD_HANDLE used for the memory address -// offs -- The offset added to the memory address from fldHnd +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op2Reg -- The register of the second operand +// fldHnd -- The CORINFO_FIELD_HANDLE used for the memory address +// offs -- The offset added to the memory address from fldHnd +// instOptions -- The options that modify how the instruction is generated // void emitter::emitIns_SIMD_R_R_R_C(instruction ins, emitAttr attr, @@ -8529,7 +8655,8 @@ void emitter::emitIns_SIMD_R_R_R_C(instruction ins, regNumber op1Reg, regNumber op2Reg, CORINFO_FIELD_HANDLE fldHnd, - int offs) + int offs, + insOpts instOptions) { assert(IsFMAInstruction(ins) || IsPermuteVar2xInstruction(ins) || IsAVXVNNIInstruction(ins)); assert(UseSimdEncoding()); @@ -8538,7 +8665,7 @@ void emitter::emitIns_SIMD_R_R_R_C(instruction ins, assert((op2Reg != targetReg) || (op1Reg == targetReg)); emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); - emitIns_R_R_C(ins, attr, targetReg, op2Reg, fldHnd, offs); + emitIns_R_R_C(ins, attr, targetReg, op2Reg, fldHnd, offs, instOptions); } //------------------------------------------------------------------------ @@ -8546,13 +8673,13 @@ void emitter::emitIns_SIMD_R_R_R_C(instruction ins, // value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op2Reg -- The register of the second operand -// op3Reg -- The register of the second operand -// instOptions - The options that modify how the instruction is generated +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op2Reg -- The register of the second operand +// op3Reg -- The register of the second operand +// instOptions -- The options that modify how the instruction is generated // void emitter::emitIns_SIMD_R_R_R_R(instruction ins, emitAttr attr, @@ -8598,11 +8725,12 @@ void emitter::emitIns_SIMD_R_R_R_R(instruction ins, default: break; } - emitIns_R_R_R_R(ins, attr, targetReg, op1Reg, op2Reg, op3Reg); + emitIns_R_R_R_R(ins, attr, targetReg, op1Reg, op2Reg, op3Reg, instOptions); } else { assert(isSse41Blendv(ins)); + assert(instOptions == INS_OPTS_NONE); // Ensure we aren't overwriting op1 or op2 assert((op1Reg != REG_XMM0) || (op3Reg == REG_XMM0)); @@ -8630,16 +8758,23 @@ void emitter::emitIns_SIMD_R_R_R_R(instruction ins, // offset, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op2Reg -- The register of the second operand -// varx -- The variable index used for the memory address -// offs -- The offset added to the memory address from varx -// -void emitter::emitIns_SIMD_R_R_R_S( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, int varx, int offs) +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op2Reg -- The register of the second operand +// varx -- The variable index used for the memory address +// offs -- The offset added to the memory address from varx +// instOptions -- The options that modify how the instruction is generated +// +void emitter::emitIns_SIMD_R_R_R_S(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op2Reg, + int varx, + int offs, + insOpts instOptions) { assert(IsFMAInstruction(ins) || IsPermuteVar2xInstruction(ins) || IsAVXVNNIInstruction(ins)); assert(UseSimdEncoding()); @@ -8648,7 +8783,7 @@ void emitter::emitIns_SIMD_R_R_R_S( assert((op2Reg != targetReg) || (op1Reg == targetReg)); emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); - emitIns_R_R_S(ins, attr, targetReg, op2Reg, varx, offs); + emitIns_R_R_S(ins, attr, targetReg, op2Reg, varx, offs, instOptions); } //------------------------------------------------------------------------ @@ -8656,15 +8791,21 @@ void emitter::emitIns_SIMD_R_R_R_S( // another register operand, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op3Reg -- The register of the third operand -// indir -- The GenTreeIndir used for the memory address -// -void emitter::emitIns_SIMD_R_R_A_R( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op3Reg, GenTreeIndir* indir) +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op3Reg -- The register of the third operand +// indir -- The GenTreeIndir used for the memory address +// instOptions -- The options that modify how the instruction is generated +// +void emitter::emitIns_SIMD_R_R_A_R(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op3Reg, + GenTreeIndir* indir, + insOpts instOptions) { if (UseSimdEncoding()) { @@ -8697,11 +8838,12 @@ void emitter::emitIns_SIMD_R_R_A_R( } } - emitIns_R_R_A_R(ins, attr, targetReg, op1Reg, op3Reg, indir); + emitIns_R_R_A_R(ins, attr, targetReg, op1Reg, op3Reg, indir, instOptions); } else { assert(isSse41Blendv(ins)); + assert(instOptions == INS_OPTS_NONE); // Ensure we aren't overwriting op1 assert(op1Reg != REG_XMM0); @@ -8722,13 +8864,14 @@ void emitter::emitIns_SIMD_R_R_A_R( // offset, another register operand, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op3Reg -- The register of the third operand -// fldHnd -- The CORINFO_FIELD_HANDLE used for the memory address -// offs -- The offset added to the memory address from fldHnd +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op3Reg -- The register of the third operand +// fldHnd -- The CORINFO_FIELD_HANDLE used for the memory address +// offs -- The offset added to the memory address from fldHnd +// instOptions -- The options that modify how the instruction is generated // void emitter::emitIns_SIMD_R_R_C_R(instruction ins, emitAttr attr, @@ -8736,7 +8879,8 @@ void emitter::emitIns_SIMD_R_R_C_R(instruction ins, regNumber op1Reg, regNumber op3Reg, CORINFO_FIELD_HANDLE fldHnd, - int offs) + int offs, + insOpts instOptions) { if (UseSimdEncoding()) { @@ -8769,11 +8913,12 @@ void emitter::emitIns_SIMD_R_R_C_R(instruction ins, } } - emitIns_R_R_C_R(ins, attr, targetReg, op1Reg, op3Reg, fldHnd, offs); + emitIns_R_R_C_R(ins, attr, targetReg, op1Reg, op3Reg, fldHnd, offs, instOptions); } else { assert(isSse41Blendv(ins)); + assert(instOptions == INS_OPTS_NONE); // Ensure we aren't overwriting op1 assert(op1Reg != REG_XMM0); @@ -8794,16 +8939,23 @@ void emitter::emitIns_SIMD_R_R_C_R(instruction ins, // offset, another register operand, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op3Reg -- The register of the third operand -// varx -- The variable index used for the memory address -// offs -- The offset added to the memory address from varx -// -void emitter::emitIns_SIMD_R_R_S_R( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op3Reg, int varx, int offs) +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op3Reg -- The register of the third operand +// varx -- The variable index used for the memory address +// offs -- The offset added to the memory address from varx +// instOptions -- The options that modify how the instruction is generated +// +void emitter::emitIns_SIMD_R_R_S_R(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op3Reg, + int varx, + int offs, + insOpts instOptions) { if (UseSimdEncoding()) { @@ -8836,11 +8988,12 @@ void emitter::emitIns_SIMD_R_R_S_R( } } - emitIns_R_R_S_R(ins, attr, targetReg, op1Reg, op3Reg, varx, offs); + emitIns_R_R_S_R(ins, attr, targetReg, op1Reg, op3Reg, varx, offs, instOptions); } else { assert(isSse41Blendv(ins)); + assert(instOptions == INS_OPTS_NONE); // Ensure we aren't overwriting op1 assert(op1Reg != REG_XMM0); @@ -8861,13 +9014,14 @@ void emitter::emitIns_SIMD_R_R_S_R( // address, an immediate operand, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op2Reg -- The register of the second operand -// indir -- The GenTreeIndir used for the memory address -// ival -- The immediate value +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op2Reg -- The register of the second operand +// indir -- The GenTreeIndir used for the memory address +// ival -- The immediate value +// instOptions -- The options that modify how the instruction is generated // void emitter::emitIns_SIMD_R_R_R_A_I(instruction ins, emitAttr attr, @@ -8875,11 +9029,12 @@ void emitter::emitIns_SIMD_R_R_R_A_I(instruction ins, regNumber op1Reg, regNumber op2Reg, GenTreeIndir* indir, - int ival) + int ival, + insOpts instOptions) { assert(UseSimdEncoding()); emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); - emitIns_R_R_A_I(ins, attr, targetReg, op2Reg, indir, ival, IF_RWR_RRD_ARD_CNS); + emitIns_R_R_A_I(ins, attr, targetReg, op2Reg, indir, ival, IF_RWR_RRD_ARD_CNS, instOptions); } //------------------------------------------------------------------------ @@ -8887,14 +9042,15 @@ void emitter::emitIns_SIMD_R_R_R_A_I(instruction ins, // offset, an immediate operand, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op2Reg -- The register of the second operand -// fldHnd -- The CORINFO_FIELD_HANDLE used for the memory address -// offs -- The offset added to the memory address from fldHnd -// ival -- The immediate value +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op2Reg -- The register of the second operand +// fldHnd -- The CORINFO_FIELD_HANDLE used for the memory address +// offs -- The offset added to the memory address from fldHnd +// ival -- The immediate value +// instOptions -- The options that modify how the instruction is generated // void emitter::emitIns_SIMD_R_R_R_C_I(instruction ins, emitAttr attr, @@ -8903,11 +9059,12 @@ void emitter::emitIns_SIMD_R_R_R_C_I(instruction ins, regNumber op2Reg, CORINFO_FIELD_HANDLE fldHnd, int offs, - int ival) + int ival, + insOpts instOptions) { assert(UseSimdEncoding()); emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); - emitIns_R_R_C_I(ins, attr, targetReg, op2Reg, fldHnd, offs, ival); + emitIns_R_R_C_I(ins, attr, targetReg, op2Reg, fldHnd, offs, ival, instOptions); } //------------------------------------------------------------------------ @@ -8915,20 +9072,27 @@ void emitter::emitIns_SIMD_R_R_R_C_I(instruction ins, // operand, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op2Reg -- The register of the second operand -// op3Reg -- The register of the third operand -// ival -- The immediate value -// -void emitter::emitIns_SIMD_R_R_R_R_I( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, regNumber op3Reg, int ival) +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op2Reg -- The register of the second operand +// op3Reg -- The register of the third operand +// ival -- The immediate value +// instOptions -- The options that modify how the instruction is generated +// +void emitter::emitIns_SIMD_R_R_R_R_I(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op2Reg, + regNumber op3Reg, + int ival, + insOpts instOptions) { assert(UseSimdEncoding()); emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); - emitIns_R_R_R_I(ins, attr, targetReg, op2Reg, op3Reg, ival); + emitIns_R_R_R_I(ins, attr, targetReg, op2Reg, op3Reg, ival, instOptions); } //------------------------------------------------------------------------ @@ -8936,14 +9100,15 @@ void emitter::emitIns_SIMD_R_R_R_R_I( // offset, an immediate operand, and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// targetReg -- The target register -// op1Reg -- The register of the first operand -// op2Reg -- The register of the second operand -// varx -- The variable index used for the memory address -// offs -- The offset added to the memory address from varx -// ival -- The immediate value +// ins -- The instruction being emitted +// attr -- The emit attribute +// targetReg -- The target register +// op1Reg -- The register of the first operand +// op2Reg -- The register of the second operand +// varx -- The variable index used for the memory address +// offs -- The offset added to the memory address from varx +// ival -- The immediate value +// instOptions -- The options that modify how the instruction is generated // void emitter::emitIns_SIMD_R_R_R_S_I(instruction ins, emitAttr attr, @@ -8952,11 +9117,12 @@ void emitter::emitIns_SIMD_R_R_R_S_I(instruction ins, regNumber op2Reg, int varx, int offs, - int ival) + int ival, + insOpts instOptions) { assert(UseSimdEncoding()); emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); - emitIns_R_R_S_I(ins, attr, targetReg, op2Reg, varx, offs, ival); + emitIns_R_R_S_I(ins, attr, targetReg, op2Reg, varx, offs, ival, instOptions); } #endif // FEATURE_HW_INTRINSICS @@ -9105,7 +9271,7 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber ireg, int va emitCurIGsize += sz; } -void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs) +void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs, insOpts instOptions) { emitAttr size = EA_SIZE(attr); noway_assert(emitVerifyEncodable(ins, size, ireg)); @@ -9123,6 +9289,9 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber ireg, int va id->idReg1(ireg); id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs); + SetEvexBroadcastIfNeeded(id, instOptions); + SetEvexEmbMaskIfNeeded(id, instOptions); + sz = emitInsSizeSV(id, insCodeRM(ins), varx, offs); id->idCodeSize(sz); #ifdef DEBUG @@ -9477,6 +9646,8 @@ void emitter::emitAdjustStackDepth(instruction ins, ssize_t val) * EC_INDIR_C : "call clsVar" (eg. call [clsVarAddr]) * EC_INDIR_ARD : "call [ireg+xreg*xmul+disp]" * + * noSafePoint - force not making this call a safe point in partially interruptible code + * */ // clang-format off @@ -9495,7 +9666,8 @@ void emitter::emitIns_Call(EmitCallType callType, regNumber xreg, unsigned xmul, ssize_t disp, - bool isJump) + bool isJump, + bool noSafePoint) // clang-format on { /* Sanity check the arguments depending on callType */ @@ -9578,6 +9750,28 @@ void emitter::emitIns_Call(EmitCallType callType, /* Update the emitter's live GC ref sets */ + // If the method returns a GC ref, mark EAX appropriately + if (retSize == EA_GCREF) + { + gcrefRegs |= RBM_EAX; + } + else if (retSize == EA_BYREF) + { + byrefRegs |= RBM_EAX; + } + +#ifdef UNIX_AMD64_ABI + // If is a multi-register return method is called, mark RDX appropriately (for System V AMD64). + if (secondRetSize == EA_GCREF) + { + gcrefRegs |= RBM_RDX; + } + else if (secondRetSize == EA_BYREF) + { + byrefRegs |= RBM_RDX; + } +#endif // UNIX_AMD64_ABI + VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars); emitThisGCrefRegs = gcrefRegs; emitThisByrefRegs = byrefRegs; @@ -9598,7 +9792,8 @@ void emitter::emitIns_Call(EmitCallType callType, } id->idIns(ins); - id->idSetIsNoGC(emitNoGChelper(methHnd)); + // for the purpose of GC safepointing tail-calls are not real calls + id->idSetIsNoGC(isJump || noSafePoint || emitNoGChelper(methHnd)); UNATIVE_OFFSET sz; @@ -10102,7 +10297,7 @@ const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName) con suffix = 'd'; goto APPEND_SUFFIX; } - rbc = (rbc + 1) % 2; + rbc ^= 1; rb[rbc][0] = 'e'; rb[rbc][1] = rn[1]; rb[rbc][2] = rn[2]; @@ -10133,7 +10328,7 @@ const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName) con { suffix = 'b'; APPEND_SUFFIX: - rbc = (rbc + 1) % 2; + rbc ^= 1; rb[rbc][0] = rn[0]; rb[rbc][1] = rn[1]; if (rn[2]) @@ -10151,7 +10346,7 @@ const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName) con } else { - rbc = (rbc + 1) % 2; + rbc ^= 1; rb[rbc][0] = rn[1]; if (reg < 4) { @@ -10168,7 +10363,7 @@ const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName) con #endif // TARGET_AMD64 #if defined(TARGET_X86) - rbc = (rbc + 1) % 2; + rbc ^= 1; rb[rbc][0] = rn[1]; rb[rbc][1] = 'l'; strcpy_s(&rb[rbc][2], sizeof(rb[0]) - 2, rn + 3); @@ -10462,11 +10657,14 @@ void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm) * * Display the mask for the instruction */ -void emitter::emitDispMask(const instrDesc* id, regNumber reg, emitAttr size) const +void emitter::emitDispMask(const instrDesc* id, regNumber reg) const { - printf("{%s}", emitRegName(reg, size)); - // TODO: Handle printing {z} if EVEX.z is set - printf(", "); + printf(" {%s}", emitRegName(reg)); + + if (id->idIsEvexZContextSet()) + { + printf("{z}"); + } } /***************************************************************************** @@ -10770,9 +10968,9 @@ void emitter::emitDispInsHex(instrDesc* id, BYTE* code, size_t sz) // Arguments: // id - The instruction descriptor // -void emitter::emitDispEmbBroadcastCount(instrDesc* id) +void emitter::emitDispEmbBroadcastCount(instrDesc* id) const { - if (!id->idIsEvexbContextSet()) + if (!IsEvexEncodableInstruction(id->idIns()) || !id->idIsEvexbContextSet()) { return; } @@ -10786,7 +10984,7 @@ void emitter::emitDispEmbBroadcastCount(instrDesc* id) // Arguments: // id - The instruction descriptor // -void emitter::emitDispEmbRounding(instrDesc* id) +void emitter::emitDispEmbRounding(instrDesc* id) const { if (!id->idIsEvexbContextSet()) { @@ -10817,21 +11015,21 @@ void emitter::emitDispEmbRounding(instrDesc* id) // Arguments: // id - The instruction descriptor // -void emitter::emitDispEmbMasking(instrDesc* id) +void emitter::emitDispEmbMasking(instrDesc* id) const { - regNumber maskReg = static_cast(id->idGetEvexAaaContext() + KBASE); - - if (maskReg == REG_K0) + if (!IsEvexEncodableInstruction(id->idIns())) { return; } - printf(" {%s}", emitRegName(maskReg)); + regNumber maskReg = static_cast(id->idGetEvexAaaContext() + KBASE); - if (id->idIsEvexZContextSet()) + if (maskReg == REG_K0) { - printf(" {z}"); + return; } + + emitDispMask(id, maskReg); } //-------------------------------------------------------------------- @@ -10933,7 +11131,7 @@ void emitter::emitDispIns( if (id->idOpSize() <= EA_4BYTE) printf("DD %d \n", addr ? *(int *)addr : 0); else - printf("DQ %D \n", addr ? *(__int64 *)addr : 0); + printf("DQ %D \n", addr ? *(int64_t *)addr : 0); } } #endif @@ -11039,6 +11237,8 @@ void emitter::emitDispIns( case IF_CNS: { + assert(!IsEvexEncodableInstruction(id->idIns())); + val = emitGetInsSC(id); #ifdef TARGET_AMD64 // no 8-byte immediates allowed here! @@ -11082,6 +11282,8 @@ void emitter::emitDispIns( case IF_AWR: case IF_ARW: { + assert(!IsEvexEncodableInstruction(id->idIns())); + if (((ins == INS_call) || (ins == INS_tail_i_jmp)) && id->idIsCallRegPtr()) { printf("%s", emitRegName(id->idAddr()->iiaAddrMode.amBaseReg)); @@ -11145,8 +11347,11 @@ void emitter::emitDispIns( // This logic ensures that we print `crc32 eax, bx` instead of `crc32 ax, bx` attr = EA_4BYTE; } - printf("%s, %s", emitRegName(id->idReg1(), attr), sstr); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s", sstr); emitDispAddrMode(id); + emitDispEmbBroadcastCount(id); emitDispCommentForHandle(id->idDebugOnlyInfo()->idMemCookie, 0, id->idDebugOnlyInfo()->idFlags); break; @@ -11156,8 +11361,11 @@ void emitter::emitDispIns( case IF_RRW_ARD_CNS: case IF_RWR_ARD_CNS: { - printf("%s, %s", emitRegName(id->idReg1(), attr), sstr); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s", sstr); emitDispAddrMode(id); + emitDispEmbBroadcastCount(id); emitGetInsAmdCns(id, &cnsVal); val = cnsVal.cnsVal; @@ -11209,6 +11417,7 @@ void emitter::emitDispIns( printf(sstr); emitDispAddrMode(id); + emitDispEmbMasking(id); printf(", %s", emitRegName(id->idReg1(), attr)); emitGetInsAmdCns(id, &cnsVal); @@ -11250,16 +11459,22 @@ void emitter::emitDispIns( attr = EA_16BYTE; } sstr = codeGen->genSizeStr(EA_ATTR(4)); - printf("%s, %s", emitRegName(id->idReg1(), attr), sstr); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s", sstr); emitDispAddrMode(id); + emitDispEmbBroadcastCount(id); printf(", %s", emitRegName(id->idReg2(), attr)); break; } case IF_RWR_RRD_ARD_CNS: { - printf("%s, %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), attr), sstr); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s, %s", emitRegName(id->idReg2(), attr), sstr); emitDispAddrMode(id); + emitDispEmbBroadcastCount(id); emitGetInsAmdCns(id, &cnsVal); val = cnsVal.cnsVal; @@ -11279,7 +11494,8 @@ void emitter::emitDispIns( case IF_RWR_RRD_ARD_RRD: { - printf("%s ", emitRegName(id->idReg1(), attr)); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); emitGetInsAmdCns(id, &cnsVal); regNumber op3Reg = decodeRegFromIval(cnsVal.cnsVal); @@ -11287,11 +11503,12 @@ void emitter::emitDispIns( if (hasMaskReg) { - emitDispMask(id, op3Reg, attr); + emitDispMask(id, op3Reg); } - printf("%s, %s", emitRegName(id->idReg2(), attr), sstr); + printf(", %s, %s", emitRegName(id->idReg2(), attr), sstr); emitDispAddrMode(id); + emitDispEmbBroadcastCount(id); if (!hasMaskReg) { @@ -11307,6 +11524,7 @@ void emitter::emitDispIns( { printf("%s", sstr); emitDispAddrMode(id); + emitDispEmbMasking(id); printf(", %s", emitRegName(id->idReg1(), attr)); break; } @@ -11315,6 +11533,7 @@ void emitter::emitDispIns( { printf("%s", sstr); emitDispAddrMode(id); + emitDispEmbMasking(id); printf(", %s", emitRegName(id->idReg1(), attr)); printf(", %s", emitRegName(id->idReg2(), attr)); break; @@ -11327,6 +11546,7 @@ void emitter::emitDispIns( { printf("%s", sstr); emitDispAddrMode(id); + emitDispEmbMasking(id); emitGetInsAmdCns(id, &cnsVal); val = cnsVal.cnsVal; #ifdef TARGET_AMD64 @@ -11356,6 +11576,7 @@ void emitter::emitDispIns( case IF_SWR: case IF_SRW: { + assert(!IsEvexEncodableInstruction(id->idIns())); printf("%s", sstr); #if !FEATURE_FIXED_OUT_ARGS @@ -11384,6 +11605,7 @@ void emitter::emitDispIns( emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(), id->idDebugOnlyInfo()->idVarRefOffs, asmfm); + emitDispEmbMasking(id); printf(", %s", emitRegName(id->idReg1(), attr)); break; @@ -11398,6 +11620,7 @@ void emitter::emitDispIns( emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(), id->idDebugOnlyInfo()->idVarRefOffs, asmfm); + emitDispEmbMasking(id); emitGetInsCns(id, &cnsVal); val = cnsVal.cnsVal; @@ -11435,6 +11658,7 @@ void emitter::emitDispIns( emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(), id->idDebugOnlyInfo()->idVarRefOffs, asmfm); + emitDispEmbMasking(id); printf(", %s", emitRegName(id->idReg1(), attr)); @@ -11474,9 +11698,12 @@ void emitter::emitDispIns( attr = EA_4BYTE; } - printf("%s, %s", emitRegName(id->idReg1(), attr), sstr); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s", sstr); emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(), id->idDebugOnlyInfo()->idVarRefOffs, asmfm); + emitDispEmbBroadcastCount(id); break; } @@ -11485,9 +11712,12 @@ void emitter::emitDispIns( case IF_RWR_SRD_CNS: case IF_RRW_SRD_CNS: { - printf("%s, %s", emitRegName(id->idReg1(), attr), sstr); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s", sstr); emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(), id->idDebugOnlyInfo()->idVarRefOffs, asmfm); + emitDispEmbBroadcastCount(id); emitGetInsCns(id, &cnsVal); val = cnsVal.cnsVal; @@ -11520,9 +11750,12 @@ void emitter::emitDispIns( case IF_RWR_RRD_SRD_CNS: { - printf("%s, %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), attr), sstr); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s, %s", emitRegName(id->idReg2(), attr), sstr); emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(), id->idDebugOnlyInfo()->idVarRefOffs, asmfm); + emitDispEmbBroadcastCount(id); emitGetInsCns(id, &cnsVal); val = cnsVal.cnsVal; @@ -11541,7 +11774,8 @@ void emitter::emitDispIns( case IF_RWR_RRD_SRD_RRD: { - printf("%s ", emitRegName(id->idReg1(), attr)); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); emitGetInsCns(id, &cnsVal); regNumber op3Reg = decodeRegFromIval(cnsVal.cnsVal); @@ -11549,12 +11783,13 @@ void emitter::emitDispIns( if (hasMaskReg) { - emitDispMask(id, op3Reg, attr); + emitDispMask(id, op3Reg); } - printf("%s, %s", emitRegName(id->idReg2(), attr), sstr); + printf(", %s, %s", emitRegName(id->idReg2(), attr), sstr); emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(), id->idDebugOnlyInfo()->idVarRefOffs, asmfm); + emitDispEmbBroadcastCount(id); if (!hasMaskReg) { @@ -11567,9 +11802,13 @@ void emitter::emitDispIns( case IF_RWR_SRD_RRD: case IF_RRW_SRD_RRD: { - printf("%s, %s", emitRegName(id->idReg1(), attr), sstr); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s", sstr); + emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(), id->idDebugOnlyInfo()->idVarRefOffs, asmfm); + emitDispEmbBroadcastCount(id); printf(", %s", emitRegName(id->idReg2(), attr)); break; } @@ -11579,6 +11818,7 @@ void emitter::emitDispIns( printf("%s", sstr); emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(), id->idDebugOnlyInfo()->idVarRefOffs, asmfm); + emitDispEmbMasking(id); printf(", %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), attr)); break; } @@ -11592,6 +11832,7 @@ void emitter::emitDispIns( { case INS_pmovmskb: { + assert(!id->idIsEvexAaaContextSet()); printf("%s, %s", emitRegName(id->idReg1(), EA_4BYTE), emitRegName(id->idReg2(), attr)); break; } @@ -11601,7 +11842,8 @@ void emitter::emitDispIns( case INS_cvtsi2ss64: case INS_cvtsi2sd64: { - printf(" %s, %s", emitRegName(id->idReg1(), EA_16BYTE), emitRegName(id->idReg2(), attr)); + assert(!id->idIsEvexAaaContextSet()); + printf("%s, %s", emitRegName(id->idReg1(), EA_16BYTE), emitRegName(id->idReg2(), attr)); break; } @@ -11618,7 +11860,8 @@ void emitter::emitDispIns( case INS_vcvttss2usi32: case INS_vcvttss2usi64: { - printf(" %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), EA_16BYTE)); + assert(!id->idIsEvexAaaContextSet()); + printf("%s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), EA_16BYTE)); break; } @@ -11663,19 +11906,25 @@ void emitter::emitDispIns( case INS_vpbroadcastd_gpr: case INS_vpbroadcastw_gpr: { - printf(" %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), EA_4BYTE)); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s", emitRegName(id->idReg2(), EA_4BYTE)); break; } case INS_vpbroadcastq_gpr: { - printf(" %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), EA_8BYTE)); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s", emitRegName(id->idReg2(), EA_8BYTE)); break; } default: { - printf("%s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), attr)); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s", emitRegName(id->idReg2(), attr)); emitDispEmbRounding(id); break; } @@ -11690,8 +11939,10 @@ void emitter::emitDispIns( { assert(IsVexOrEvexEncodableInstruction(ins)); assert(IsThreeOperandAVXInstruction(ins) || IsKInstruction(ins)); + regNumber reg2 = id->idReg2(); regNumber reg3 = id->idReg3(); + if (ins == INS_bextr || ins == INS_bzhi #ifdef TARGET_AMD64 || ins == INS_shrx || ins == INS_shlx || ins == INS_sarx @@ -11716,8 +11967,10 @@ void emitter::emitDispIns( { assert(IsVexOrEvexEncodableInstruction(ins)); assert(IsThreeOperandAVXInstruction(ins)); - printf("%s, ", emitRegName(id->idReg1(), attr)); - printf("%s, ", emitRegName(id->idReg2(), attr)); + + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s", emitRegName(id->idReg2(), attr)); switch (ins) { @@ -11759,7 +12012,7 @@ void emitter::emitDispIns( } } - printf("%s, ", emitRegName(id->idReg3(), attr)); + printf(", %s, ", emitRegName(id->idReg3(), attr)); val = emitGetInsSC(id); goto PRINT_CONSTANT; break; @@ -11770,18 +12023,17 @@ void emitter::emitDispIns( assert(IsVexOrEvexEncodableInstruction(ins)); assert(UseVEXEncoding()); - printf("%s ", emitRegName(id->idReg1(), attr)); + printf("%s", emitRegName(id->idReg1(), attr)); regNumber op4Reg = id->idReg4(); bool hasMaskReg = isMaskReg(op4Reg); if (hasMaskReg) { - emitDispMask(id, op4Reg, attr); + emitDispMask(id, op4Reg); } - printf("%s, ", emitRegName(id->idReg2(), attr)); - printf("%s", emitRegName(id->idReg3(), attr)); + printf(", %s, %s", emitRegName(id->idReg2(), attr), emitRegName(id->idReg3(), attr)); if (!hasMaskReg) { @@ -11852,8 +12104,9 @@ void emitter::emitDispIns( } } - printf("%s,", emitRegName(id->idReg1(), tgtAttr)); - printf(" %s", emitRegName(id->idReg2(), attr)); + printf("%s", emitRegName(id->idReg1(), tgtAttr)); + emitDispEmbMasking(id); + printf(", %s", emitRegName(id->idReg2(), attr)); val = emitGetInsSC(id); #ifdef TARGET_AMD64 // no 8-byte immediates allowed here! @@ -11875,6 +12128,7 @@ void emitter::emitDispIns( case IF_RWR: case IF_RRW: { + assert(!IsEvexEncodableInstruction(id->idIns())); printf("%s", emitRegName(id->idReg1(), attr)); emitDispShift(ins); break; @@ -11886,6 +12140,7 @@ void emitter::emitDispIns( case IF_RRW_SHF: { printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); emitGetInsCns(id, &cnsVal); val = cnsVal.cnsVal; @@ -11930,9 +12185,12 @@ void emitter::emitDispIns( // This logic ensures that we print `crc32 eax, bx` instead of `crc32 ax, bx` attr = EA_4BYTE; } - printf("%s, %s", emitRegName(id->idReg1(), attr), sstr); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s", sstr); offs = emitGetInsDsp(id); emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC); + emitDispEmbBroadcastCount(id); break; } @@ -11940,9 +12198,12 @@ void emitter::emitDispIns( case IF_RWR_MRD_CNS: case IF_RRW_MRD_CNS: { - printf("%s, %s", emitRegName(id->idReg1(), attr), sstr); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s", sstr); offs = emitGetInsDsp(id); emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC); + emitDispEmbBroadcastCount(id); emitGetInsDcmCns(id, &cnsVal); val = cnsVal.cnsVal; @@ -11994,6 +12255,7 @@ void emitter::emitDispIns( printf(sstr); offs = emitGetInsDsp(id); emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC); + emitDispEmbMasking(id); printf(", %s", emitRegName(id->idReg1(), attr)); emitGetInsDcmCns(id, &cnsVal); @@ -12028,9 +12290,12 @@ void emitter::emitDispIns( case IF_RWR_RRD_MRD_CNS: { - printf("%s, %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), attr), sstr); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s, %s", emitRegName(id->idReg2(), attr), sstr); offs = emitGetInsDsp(id); emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC); + emitDispEmbBroadcastCount(id); emitGetInsDcmCns(id, &cnsVal); val = cnsVal.cnsVal; @@ -12049,7 +12314,7 @@ void emitter::emitDispIns( case IF_RWR_RRD_MRD_RRD: { - printf("%s ", emitRegName(id->idReg1(), attr)); + printf("%s", emitRegName(id->idReg1(), attr)); emitGetInsDcmCns(id, &cnsVal); regNumber op3Reg = decodeRegFromIval(cnsVal.cnsVal); @@ -12057,12 +12322,13 @@ void emitter::emitDispIns( if (hasMaskReg) { - emitDispMask(id, op3Reg, attr); + emitDispMask(id, op3Reg); } - printf("%s, %s", emitRegName(id->idReg2(), attr), sstr); + printf(", %s, %s", emitRegName(id->idReg2(), attr), sstr); offs = emitGetInsDsp(id); emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC); + emitDispEmbBroadcastCount(id); if (!hasMaskReg) { @@ -12073,6 +12339,7 @@ void emitter::emitDispIns( case IF_RWR_MRD_OFF: { + assert(!IsEvexEncodableInstruction(id->idIns())); printf("%s, %s", emitRegName(id->idReg1(), attr), "offset"); offs = emitGetInsDsp(id); emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC); @@ -12087,6 +12354,7 @@ void emitter::emitDispIns( printf("%s", sstr); offs = emitGetInsDsp(id); emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC); + emitDispEmbMasking(id); printf(", %s", emitRegName(id->idReg1(), attr)); break; } @@ -12099,6 +12367,7 @@ void emitter::emitDispIns( printf("%s", sstr); offs = emitGetInsDsp(id); emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC); + emitDispEmbMasking(id); emitGetInsDcmCns(id, &cnsVal); val = cnsVal.cnsVal; #ifdef TARGET_AMD64 @@ -12125,6 +12394,7 @@ void emitter::emitDispIns( case IF_MWR: case IF_MRW: { + assert(!IsEvexEncodableInstruction(id->idIns())); printf("%s", sstr); offs = emitGetInsDsp(id); emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC); @@ -12134,6 +12404,7 @@ void emitter::emitDispIns( case IF_MRD_OFF: { + assert(!IsEvexEncodableInstruction(id->idIns())); printf("offset "); offs = emitGetInsDsp(id); emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC); @@ -12144,9 +12415,12 @@ void emitter::emitDispIns( case IF_RWR_MRD_RRD: case IF_RRW_MRD_RRD: { - printf("%s, %s", emitRegName(id->idReg1(), attr), sstr); + printf("%s", emitRegName(id->idReg1(), attr)); + emitDispEmbMasking(id); + printf(", %s, %s", emitRegName(id->idReg2(), attr), sstr); offs = emitGetInsDsp(id); emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC); + emitDispEmbBroadcastCount(id); printf(", %s", emitRegName(id->idReg2(), attr)); break; } @@ -12154,6 +12428,7 @@ void emitter::emitDispIns( case IF_MWR_RRD_RRD: { printf("%s", sstr); + emitDispEmbMasking(id); offs = emitGetInsDsp(id); emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC); printf(", %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), attr)); @@ -12164,6 +12439,8 @@ void emitter::emitDispIns( case IF_RWR_LABEL: case IF_SWR_LABEL: { + assert(!IsEvexEncodableInstruction(id->idIns())); + if (ins == INS_lea) { printf("%s, ", emitRegName(id->idReg1(), attr)); @@ -12205,6 +12482,7 @@ void emitter::emitDispIns( case IF_METHOD: case IF_METHPTR: { + assert(!IsEvexEncodableInstruction(id->idIns())); methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie); if (id->idInsFmt() == IF_METHPTR) @@ -15517,6 +15795,7 @@ BYTE* emitter::emitOutputRI(BYTE* dst, instrDesc* id) break; case IF_RRW_CNS: + { assert(id->idGCref() == GCT_BYREF); #ifdef DEBUG @@ -15538,7 +15817,7 @@ BYTE* emitter::emitOutputRI(BYTE* dst, instrDesc* id) // Mark it as holding a GCT_BYREF emitGCregLiveUpd(GCT_BYREF, id->idReg1(), dst); break; - + } default: #ifdef DEBUG emitDispIns(id, false, false, false); @@ -16331,6 +16610,8 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) assert(instrIs3opImul(id->idIns()) == 0 || size >= EA_4BYTE); // Has no 'w' bit VARSET_TP GCvars(VarSetOps::UninitVal()); + regMaskTP gcrefRegs; + regMaskTP byrefRegs; // What instruction format have we got? switch (insFmt) @@ -16343,9 +16624,6 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) BYTE* addr; bool recCall; - regMaskTP gcrefRegs; - regMaskTP byrefRegs; - /********************************************************************/ /* No operands */ /********************************************************************/ @@ -16496,9 +16774,6 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) case IF_METHOD: case IF_METHPTR: { - // Assume we'll be recording this call - recCall = true; - // Get hold of the argument count and field Handle args = emitGetInsCDinfo(id); @@ -16525,12 +16800,6 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) addr = (BYTE*)id->idAddr()->iiaAddr; assert(addr != nullptr); - // Some helpers don't get recorded in GC tables - if (id->idIsNoGC()) - { - recCall = false; - } - // What kind of a call do we have here? if (id->idInsFmt() == IF_METHPTR) { @@ -16616,6 +16885,15 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) DONE_CALL: + // Assume we'll be recording this call + recCall = true; + + // Some helpers don't get recorded in GC tables + if (id->idIsNoGC()) + { + recCall = false; + } + /* We update the variable (not register) GC info before the call as the variables cannot be used by the call. Killing variables before the call helps with boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029. @@ -16988,8 +17266,6 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) sz = sizeof(instrDesc); } - recCall = true; - goto DONE_CALL; default: diff --git a/src/coreclr/jit/emitxarch.h b/src/coreclr/jit/emitxarch.h index e32cab66254f..d24a697d93c7 100644 --- a/src/coreclr/jit/emitxarch.h +++ b/src/coreclr/jit/emitxarch.h @@ -45,7 +45,7 @@ inline static bool isHighSimdReg(regNumber reg) // code_t is a type used to accumulate bits of opcode + prefixes. On amd64, it must be 64 bits // to support the REX prefixes. On both x86 and amd64, it must be 64 bits to support AVX, with // its 3-byte VEX prefix. -typedef unsigned __int64 code_t; +typedef uint64_t code_t; struct CnsVal { @@ -514,7 +514,7 @@ bool isPrefetch(instruction ins) /* Debug-only routines to display instructions */ /************************************************************************/ -void emitDispMask(const instrDesc* id, regNumber reg, emitAttr size) const; +void emitDispMask(const instrDesc* id, regNumber reg) const; void emitDispReloc(ssize_t value); void emitDispAddrMode(instrDesc* id, bool noDetail = false); void emitDispShift(instruction ins, int cnt = 0); @@ -637,19 +637,35 @@ void emitIns_Mov(instruction ins, emitAttr attr, regNumber dstReg, regNumber srg void emitIns_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts instOptions = INS_OPTS_NONE); -void emitIns_R_R_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int ival); +void emitIns_R_R_I( + instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int ival, insOpts instOptions = INS_OPTS_NONE); void emitIns_AR(instruction ins, emitAttr attr, regNumber base, int offs); -void emitIns_AR_R_R(instruction ins, emitAttr attr, regNumber op2Reg, regNumber op3Reg, regNumber base, int offs); +void emitIns_AR_R_R(instruction ins, + emitAttr attr, + regNumber op2Reg, + regNumber op3Reg, + regNumber base, + int offs, + insOpts instOptions = INS_OPTS_NONE); -void emitIns_R_A(instruction ins, emitAttr attr, regNumber reg1, GenTreeIndir* indir); +void emitIns_R_A( + instruction ins, emitAttr attr, regNumber reg1, GenTreeIndir* indir, insOpts instOptions = INS_OPTS_NONE); -void emitIns_R_A_I(instruction ins, emitAttr attr, regNumber reg1, GenTreeIndir* indir, int ival); +void emitIns_R_A_I( + instruction ins, emitAttr attr, regNumber reg1, GenTreeIndir* indir, int ival, insOpts instOptions = INS_OPTS_NONE); -void emitIns_R_C_I(instruction ins, emitAttr attr, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs, int ival); +void emitIns_R_C_I(instruction ins, + emitAttr attr, + regNumber reg1, + CORINFO_FIELD_HANDLE fldHnd, + int offs, + int ival, + insOpts instOptions = INS_OPTS_NONE); -void emitIns_R_S_I(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs, int ival); +void emitIns_R_S_I( + instruction ins, emitAttr attr, regNumber reg1, int varx, int offs, int ival, insOpts instOptions = INS_OPTS_NONE); void emitIns_R_R_A(instruction ins, emitAttr attr, @@ -692,8 +708,14 @@ void emitIns_R_R_R(instruction ins, regNumber reg3, insOpts instOptions = INS_OPTS_NONE); -void emitIns_R_R_A_I( - instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, GenTreeIndir* indir, int ival, insFormat fmt); +void emitIns_R_R_A_I(instruction ins, + emitAttr attr, + regNumber reg1, + regNumber reg2, + GenTreeIndir* indir, + int ival, + insFormat fmt, + insOpts instOptions = INS_OPTS_NONE); void emitIns_R_R_AR_I( instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber base, int offs, int ival); @@ -701,15 +723,39 @@ void emitIns_C_R_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, void emitIns_S_R_I(instruction ins, emitAttr attr, int varNum, int offs, regNumber reg, int ival); void emitIns_A_R_I(instruction ins, emitAttr attr, GenTreeIndir* indir, regNumber reg, int imm); -void emitIns_R_R_C_I( - instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, CORINFO_FIELD_HANDLE fldHnd, int offs, int ival); - -void emitIns_R_R_R_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, int ival); - -void emitIns_R_R_S_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int varx, int offs, int ival); - -void emitIns_R_R_A_R( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op3Reg, GenTreeIndir* indir); +void emitIns_R_R_C_I(instruction ins, + emitAttr attr, + regNumber reg1, + regNumber reg2, + CORINFO_FIELD_HANDLE fldHnd, + int offs, + int ival, + insOpts instOptions = INS_OPTS_NONE); + +void emitIns_R_R_R_I(instruction ins, + emitAttr attr, + regNumber reg1, + regNumber reg2, + regNumber reg3, + int ival, + insOpts instOptions = INS_OPTS_NONE); + +void emitIns_R_R_S_I(instruction ins, + emitAttr attr, + regNumber reg1, + regNumber reg2, + int varx, + int offs, + int ival, + insOpts instOptions = INS_OPTS_NONE); + +void emitIns_R_R_A_R(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op3Reg, + GenTreeIndir* indir, + insOpts instOptions); void emitIns_R_R_C_R(instruction ins, emitAttr attr, @@ -717,22 +763,41 @@ void emitIns_R_R_C_R(instruction ins, regNumber op1Reg, regNumber op3Reg, CORINFO_FIELD_HANDLE fldHnd, - int offs); - -void emitIns_R_R_S_R( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op3Reg, int varx, int offs); - -void emitIns_R_R_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4); + int offs, + insOpts instOptions = INS_OPTS_NONE); + +void emitIns_R_R_S_R(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op3Reg, + int varx, + int offs, + insOpts instOptions = INS_OPTS_NONE); + +void emitIns_R_R_R_R(instruction ins, + emitAttr attr, + regNumber reg1, + regNumber reg2, + regNumber reg3, + regNumber reg4, + insOpts instOptions = INS_OPTS_NONE); void emitIns_S(instruction ins, emitAttr attr, int varx, int offs); void emitIns_S_R(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs); -void emitIns_R_S(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs); +void emitIns_R_S( + instruction ins, emitAttr attr, regNumber ireg, int varx, int offs, insOpts instOptions = INS_OPTS_NONE); void emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val); -void emitIns_R_C(instruction ins, emitAttr attr, regNumber reg, CORINFO_FIELD_HANDLE fldHnd, int offs); +void emitIns_R_C(instruction ins, + emitAttr attr, + regNumber reg, + CORINFO_FIELD_HANDLE fldHnd, + int offs, + insOpts instOptions = INS_OPTS_NONE); void emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs); @@ -786,80 +851,109 @@ void emitIns_R_AX(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, void emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, unsigned mul, int disp); -void emitIns_SIMD_R_R_I(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int ival); +void emitIns_SIMD_R_R_I( + instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int ival, insOpts instOptions); -void emitIns_SIMD_R_R_A(instruction ins, - emitAttr attr, - regNumber targetReg, - regNumber op1Reg, - GenTreeIndir* indir, - insOpts instOptions = INS_OPTS_NONE); +void emitIns_SIMD_R_R_A( + instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, GenTreeIndir* indir, insOpts instOptions); void emitIns_SIMD_R_R_C(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, CORINFO_FIELD_HANDLE fldHnd, int offs, - insOpts instOptions = INS_OPTS_NONE); -void emitIns_SIMD_R_R_R(instruction ins, - emitAttr attr, - regNumber targetReg, - regNumber op1Reg, - regNumber op2Reg, - insOpts instOptions = INS_OPTS_NONE); -void emitIns_SIMD_R_R_S(instruction ins, - emitAttr attr, - regNumber targetReg, - regNumber op1Reg, - int varx, - int offs, - insOpts instOptions = INS_OPTS_NONE); - -void emitIns_SIMD_R_R_A_I( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, GenTreeIndir* indir, int ival); + insOpts instOptions); +void emitIns_SIMD_R_R_R( + instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, insOpts instOptions); +void emitIns_SIMD_R_R_S( + instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int varx, int offs, insOpts instOptions); + +void emitIns_SIMD_R_R_A_I(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + GenTreeIndir* indir, + int ival, + insOpts instOptions); void emitIns_SIMD_R_R_C_I(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, CORINFO_FIELD_HANDLE fldHnd, int offs, - int ival); -void emitIns_SIMD_R_R_R_I( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, int ival); -void emitIns_SIMD_R_R_S_I( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int varx, int offs, int ival); + int ival, + insOpts instOptions); +void emitIns_SIMD_R_R_R_I(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op2Reg, + int ival, + insOpts instOptions); +void emitIns_SIMD_R_R_S_I(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + int varx, + int offs, + int ival, + insOpts instOptions); #ifdef FEATURE_HW_INTRINSICS -void emitIns_SIMD_R_R_R_A( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, GenTreeIndir* indir); +void emitIns_SIMD_R_R_R_A(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op2Reg, + GenTreeIndir* indir, + insOpts instOptions); void emitIns_SIMD_R_R_R_C(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, CORINFO_FIELD_HANDLE fldHnd, - int offs); + int offs, + insOpts instOptions); void emitIns_SIMD_R_R_R_R(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, regNumber op3Reg, - insOpts instOptions = INS_OPTS_NONE); -void emitIns_SIMD_R_R_R_S( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, int varx, int offs); - -void emitIns_SIMD_R_R_A_R( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, GenTreeIndir* indir); + insOpts instOptions); +void emitIns_SIMD_R_R_R_S(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op2Reg, + int varx, + int offs, + insOpts instOptions); + +void emitIns_SIMD_R_R_A_R(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op2Reg, + GenTreeIndir* indir, + insOpts instOptions); void emitIns_SIMD_R_R_C_R(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, CORINFO_FIELD_HANDLE fldHnd, - int offs); -void emitIns_SIMD_R_R_S_R( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, int varx, int offs); + int offs, + insOpts instOptions); +void emitIns_SIMD_R_R_S_R(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + regNumber op2Reg, + int varx, + int offs, + insOpts instOptions); void emitIns_SIMD_R_R_R_A_I(instruction ins, emitAttr attr, @@ -867,7 +961,8 @@ void emitIns_SIMD_R_R_R_A_I(instruction ins, regNumber op1Reg, regNumber op2Reg, GenTreeIndir* indir, - int ival); + int ival, + insOpts instOptions); void emitIns_SIMD_R_R_R_C_I(instruction ins, emitAttr attr, regNumber targetReg, @@ -875,14 +970,16 @@ void emitIns_SIMD_R_R_R_C_I(instruction ins, regNumber op2Reg, CORINFO_FIELD_HANDLE fldHnd, int offs, - int ival); + int ival, + insOpts instOptions); void emitIns_SIMD_R_R_R_R_I(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, regNumber op3Reg, - int ival); + int ival, + insOpts instOptions); void emitIns_SIMD_R_R_R_S_I(instruction ins, emitAttr attr, regNumber targetReg, @@ -890,7 +987,8 @@ void emitIns_SIMD_R_R_R_S_I(instruction ins, regNumber op2Reg, int varx, int offs, - int ival); + int ival, + insOpts instOptions); #endif // FEATURE_HW_INTRINSICS enum EmitCallType @@ -919,7 +1017,8 @@ void emitIns_Call(EmitCallType callType, regNumber xreg = REG_NA, unsigned xmul = 0, ssize_t disp = 0, - bool isJump = false); + bool isJump = false, + bool noSafePoint = false); // clang-format on #ifdef TARGET_AMD64 @@ -973,6 +1072,20 @@ inline bool HasEmbeddedBroadcast(const instrDesc* id) const return id->idIsEvexbContextSet(); } +//------------------------------------------------------------------------ +// HasEmbeddedBroadcast: Do we consider embedded broadcast while encoding. +// +// Arguments: +// id - Instruction descriptor. +// +// Returns: +// `true` if the instruction does embedded broadcast. +// +inline bool HasEmbeddedMask(const instrDesc* id) const +{ + return id->idIsEvexAaaContextSet(); +} + inline bool HasHighSIMDReg(const instrDesc* id) const; inline bool HasMaskReg(const instrDesc* id) const; diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index 37683b188c30..9895d5c940c0 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -23,12 +23,8 @@ void Compiler::fgInit() /* We haven't yet computed the bbPreds lists */ fgPredsComputed = false; - /* We haven't yet computed the edge weight */ - fgEdgeWeightsComputed = false; - fgHaveValidEdgeWeights = false; - fgSlopUsedInEdgeWeights = false; - fgRangeUsedInEdgeWeights = true; - fgCalledCount = BB_ZERO_WEIGHT; + /* We haven't yet computed block weights */ + fgCalledCount = BB_ZERO_WEIGHT; /* Initialize the basic block list */ @@ -54,6 +50,7 @@ void Compiler::fgInit() fgDomBBcount = 0; fgBBVarSetsInited = false; fgReturnCount = 0; + fgThrowCount = 0; m_dfsTree = nullptr; m_loops = nullptr; @@ -70,6 +67,10 @@ void Compiler::fgInit() genReturnBB = nullptr; genReturnLocal = BAD_VAR_NUM; +#ifdef SWIFT_SUPPORT + genReturnErrorLocal = BAD_VAR_NUM; +#endif // SWIFT_SUPPORT + /* We haven't reached the global morphing phase */ fgGlobalMorph = false; fgGlobalMorphDone = false; @@ -167,7 +168,6 @@ void Compiler::fgInit() fgHistogramInstrumentor = nullptr; fgValueInstrumentor = nullptr; fgPredListSortVector = nullptr; - fgCanonicalizedFirstBB = false; } //------------------------------------------------------------------------ @@ -215,10 +215,41 @@ bool Compiler::fgEnsureFirstBBisScratch() block = BasicBlock::New(this); - // If we have profile data the new block will inherit fgFirstBlock's weight + // If we have profile data determine the weight of the scratch BB + // if (fgFirstBB->hasProfileWeight()) { - block->inheritWeight(fgFirstBB); + // If current entry has preds, sum up those weights + // + weight_t nonEntryWeight = 0; + for (FlowEdge* const edge : fgFirstBB->PredEdges()) + { + nonEntryWeight += edge->getLikelyWeight(); + } + + // entry weight is weight not from any pred + // + weight_t const entryWeight = fgFirstBB->bbWeight - nonEntryWeight; + if (entryWeight <= 0) + { + // If the result is clearly nonsensical, just inherit + // + JITDUMP( + "\fgEnsureFirstBBisScratch: Profile data could not be locally repaired. Data %s inconsistent.\n", + fgPgoConsistent ? "is now" : "was already"); + + if (fgPgoConsistent) + { + Metrics.ProfileInconsistentScratchBB++; + fgPgoConsistent = false; + } + + block->inheritWeight(fgFirstBB); + } + else + { + block->setBBProfileWeight(entryWeight); + } } // The new scratch bb will fall through to the old first bb @@ -1124,7 +1155,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed INDEBUG(ilInstsSet->bitVectSet((UINT)(codeAddr - codeBegp))); - codeAddr += sizeof(__int8); + codeAddr += sizeof(int8_t); if (!handled && preciseScan) { @@ -1163,7 +1194,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed goto TOO_FAR; } opcode = (OPCODE)(256 + getU1LittleEndian(codeAddr)); - codeAddr += sizeof(__int8); + codeAddr += sizeof(int8_t); goto DECODE_OPCODE; } @@ -2224,10 +2255,10 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed case CEE_UNALIGNED: { - noway_assert(sz == sizeof(__int8)); + noway_assert(sz == sizeof(int8_t)); prefixFlags |= PREFIX_UNALIGNED; - codeAddr += sizeof(__int8); + codeAddr += sizeof(int8_t); impValidateMemoryAccessOpcode(codeAddr, codeEndp, false); handled = true; @@ -2645,9 +2676,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed info.compCompHnd->notifyMethodInfoUsage(impInlineInfo->iciCall->gtCallMethHnd)) { // Mark the call node as "no return" as it can impact caller's code quality. - impInlineInfo->iciCall->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN; - // Mark root method as containing a noreturn call. - impInlineRoot()->setMethodHasNoReturnCalls(); + setCallDoesNotReturn(impInlineInfo->iciCall); // NOTE: we also ask VM whether we're allowed to do so - we don't want to mark a call // as "no-return" if its IL may change. @@ -2942,11 +2971,23 @@ void Compiler::fgLinkBasicBlocks() curBBdesc->SetTrueEdge(trueEdge); curBBdesc->SetFalseEdge(falseEdge); + // Avoid making BBJ_THROW successors look likely, if possible. + // if (trueEdge == falseEdge) { assert(trueEdge->getDupCount() == 2); trueEdge->setLikelihood(1.0); } + else if (trueTarget->KindIs(BBJ_THROW) && !falseTarget->KindIs(BBJ_THROW)) + { + trueEdge->setLikelihood(0.0); + falseEdge->setLikelihood(1.0); + } + else if (!trueTarget->KindIs(BBJ_THROW) && falseTarget->KindIs(BBJ_THROW)) + { + trueEdge->setLikelihood(1.0); + falseEdge->setLikelihood(0.0); + } else { trueEdge->setLikelihood(0.5); @@ -3060,19 +3101,18 @@ void Compiler::fgLinkBasicBlocks() // codeSize -- length of the IL stream // jumpTarget -- [in] bit vector of jump targets found by fgFindJumpTargets // -// Returns: -// number of return blocks (BBJ_RETURN) in the method (may be zero) -// // Notes: -// Invoked for prejited and jitted methods, and for all inlinees - -unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, FixedBitVect* jumpTarget) +// Invoked for prejitted and jitted methods, and for all inlinees. +// Sets fgReturnCount and fgThrowCount +// +void Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, FixedBitVect* jumpTarget) { - unsigned retBlocks = 0; - const BYTE* codeBegp = codeAddr; - const BYTE* codeEndp = codeAddr + codeSize; - bool tailCall = false; - unsigned curBBoffs = 0; + unsigned retBlocks = 0; + unsigned throwBlocks = 0; + const BYTE* codeBegp = codeAddr; + const BYTE* codeEndp = codeAddr + codeSize; + bool tailCall = false; + unsigned curBBoffs = 0; BasicBlock* curBBdesc; // Keep track of where we are in the scope lists, as we will also @@ -3097,7 +3137,7 @@ unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, F BBswtDesc* swtDsc = nullptr; unsigned nxtBBoffs; OPCODE opcode = (OPCODE)getU1LittleEndian(codeAddr); - codeAddr += sizeof(__int8); + codeAddr += sizeof(int8_t); BBKinds jmpKind = BBJ_COUNT; DECODE_OPCODE: @@ -3120,7 +3160,7 @@ unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, F } opcode = (OPCODE)(256 + getU1LittleEndian(codeAddr)); - codeAddr += sizeof(__int8); + codeAddr += sizeof(int8_t); goto DECODE_OPCODE; /* Check to see if we have a jump/return opcode */ @@ -3273,7 +3313,8 @@ unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, F // can be dispatched as tail calls from the caller. compInlineResult->NoteFatal(InlineObservation::CALLEE_EXPLICIT_TAIL_PREFIX); retBlocks++; - return retBlocks; + fgReturnCount = retBlocks; + return; } FALLTHROUGH; @@ -3376,6 +3417,7 @@ unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, F case CEE_THROW: case CEE_RETHROW: + throwBlocks++; jmpKind = BBJ_THROW; break; @@ -3558,7 +3600,8 @@ unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, F fgLinkBasicBlocks(); - return retBlocks; + fgReturnCount = retBlocks; + fgThrowCount = throwBlocks; } /***************************************************************************** @@ -3670,7 +3713,7 @@ void Compiler::fgFindBasicBlocks() /* Now create the basic blocks */ - fgReturnCount = fgMakeBasicBlocks(info.compCode, info.compILCodeSize, jumpTarget); + fgMakeBasicBlocks(info.compCode, info.compILCodeSize, jumpTarget); if (compIsForInlining()) { @@ -4224,6 +4267,16 @@ void Compiler::fgFixEntryFlowForOSR() JITDUMP("OSR: redirecting flow at method entry from " FMT_BB " to OSR entry " FMT_BB " for the importer\n", fgFirstBB->bbNum, fgOSREntryBB->bbNum); + + // If the original entry block still has preds, it is a loop header, and is not + // the OSR entry, when we change the flow above we've made profile inconsistent. + // + if ((fgEntryBB->bbPreds != nullptr) && (fgEntryBB != fgOSREntryBB)) + { + JITDUMP("OSR: profile data could not be locally repaired. Data %s inconsistent.\n", + fgPgoConsistent ? "is now" : "was already"); + fgPgoConsistent = false; + } } /***************************************************************************** @@ -5043,17 +5096,28 @@ BasicBlock* Compiler::fgSplitEdge(BasicBlock* curr, BasicBlock* succ) fgReplaceJumpTarget(curr, succ, newBlock); // And 'succ' has 'newBlock' as a new predecessor. - FlowEdge* const newEdge = fgAddRefPred(succ, newBlock); - newBlock->SetTargetEdge(newEdge); + FlowEdge* const newSuccEdge = fgAddRefPred(succ, newBlock); + newBlock->SetTargetEdge(newSuccEdge); - // This isn't accurate, but it is complex to compute a reasonable number so just assume that we take the - // branch 50% of the time. - // - // TODO: leverage edge likelihood. + // Set weight for newBlock // - if (!curr->KindIs(BBJ_ALWAYS)) + if (curr->KindIs(BBJ_ALWAYS)) { - newBlock->inheritWeightPercentage(curr, 50); + newBlock->inheritWeight(curr); + } + else + { + if (curr->hasProfileWeight()) + { + FlowEdge* const currNewEdge = fgGetPredForBlock(newBlock, curr); + newBlock->setBBProfileWeight(currNewEdge->getLikelyWeight()); + } + else + { + // Todo: use likelihood even w/o profile? + // + newBlock->inheritWeightPercentage(curr, 50); + } } // The bbLiveIn and bbLiveOut are both equal to the bbLiveIn of 'succ' @@ -5422,6 +5486,7 @@ BasicBlock* Compiler::fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst) // Add a new block after bSrc which jumps to 'bDst' jmpBlk = fgNewBBafter(BBJ_ALWAYS, bSrc, true); FlowEdge* const oldEdge = bSrc->GetFalseEdge(); + // Access the likelihood of oldEdge before // it gets reset by SetTargetEdge below. // @@ -5433,29 +5498,9 @@ BasicBlock* Compiler::fgConnectFallThrough(BasicBlock* bSrc, BasicBlock* bDst) // When adding a new jmpBlk we will set the bbWeight and bbFlags // - if (fgHaveValidEdgeWeights && fgHaveProfileWeights()) + if (fgHaveProfileWeights()) { - jmpBlk->bbWeight = (newEdge->edgeWeightMin() + newEdge->edgeWeightMax()) / 2; - if (bSrc->bbWeight == BB_ZERO_WEIGHT) - { - jmpBlk->bbWeight = BB_ZERO_WEIGHT; - } - - if (jmpBlk->bbWeight == BB_ZERO_WEIGHT) - { - jmpBlk->SetFlags(BBF_RUN_RARELY); - } - - weight_t weightDiff = (newEdge->edgeWeightMax() - newEdge->edgeWeightMin()); - weight_t slop = BasicBlock::GetSlopFraction(bSrc, bDst); - // - // If the [min/max] values for our edge weight is within the slop factor - // then we will set the BBF_PROF_WEIGHT flag for the block - // - if (weightDiff <= slop) - { - jmpBlk->SetFlags(BBF_PROF_WEIGHT); - } + jmpBlk->setBBProfileWeight(newEdge->getLikelyWeight()); } else { @@ -6109,7 +6154,7 @@ BasicBlock* Compiler::fgNewBBFromTreeAfter( */ void Compiler::fgInsertBBbefore(BasicBlock* insertBeforeBlk, BasicBlock* newBlk) { - if (insertBeforeBlk->IsFirst()) + if (fgFirstBB == insertBeforeBlk) { newBlk->SetNext(fgFirstBB); diff --git a/src/coreclr/jit/fgdiagnostic.cpp b/src/coreclr/jit/fgdiagnostic.cpp index c214a5e5b634..ec3eacdcd8a6 100644 --- a/src/coreclr/jit/fgdiagnostic.cpp +++ b/src/coreclr/jit/fgdiagnostic.cpp @@ -28,26 +28,17 @@ void Compiler::fgPrintEdgeWeights() printf(FMT_BB " ", bSrc->bbNum); - if (edge->edgeWeightMin() < BB_MAX_WEIGHT) + const weight_t weight = edge->getLikelyWeight(); + + if (weight < BB_MAX_WEIGHT) { - printf("(%f", edge->edgeWeightMin()); + printf("(%f)", weight); } else { - printf("(MAX"); - } - if (edge->edgeWeightMin() != edge->edgeWeightMax()) - { - if (edge->edgeWeightMax() < BB_MAX_WEIGHT) - { - printf("..%f", edge->edgeWeightMax()); - } - else - { - printf("..MAX"); - } + printf("(MAX)"); } - printf(")"); + if (edge->getNextPredEdge() != nullptr) { printf(", "); @@ -735,7 +726,6 @@ bool Compiler::fgDumpFlowGraph(Phases phase, PhasePosition pos) JITDUMP("Writing out flow graph %s phase %s\n", (pos == PhasePosition::PrePhase) ? "before" : "after", PhaseNames[phase]); - bool validWeights = fgHaveValidEdgeWeights; double weightDivisor = (double)BasicBlock::getCalledCount(this); const char* escapedString; const char* regionString = "NONE"; @@ -791,14 +781,6 @@ bool Compiler::fgDumpFlowGraph(Phases phase, PhasePosition pos) { fprintf(fgxFile, "\n hasLoops=\"true\""); } - if (validWeights) - { - fprintf(fgxFile, "\n validEdgeWeights=\"true\""); - if (!fgSlopUsedInEdgeWeights && !fgRangeUsedInEdgeWeights) - { - fprintf(fgxFile, "\n exactEdgeWeights=\"true\""); - } - } if (fgFirstColdBlock != nullptr) { fprintf(fgxFile, "\n firstColdBlock=\"%d\"", fgFirstColdBlock->bbNum); @@ -1081,11 +1063,8 @@ bool Compiler::fgDumpFlowGraph(Phases phase, PhasePosition pos) fprintf(fgxFile, " ["); } - if (validWeights) - { - weight_t edgeWeight = (edge->edgeWeightMin() + edge->edgeWeightMax()) / 2; - fprintf(fgxFile, "%slabel=\"%7.2f\"", sep, (double)edgeWeight / weightDivisor); - } + const weight_t edgeWeight = edge->getLikelyWeight(); + fprintf(fgxFile, "%slabel=\"%7.2f\"", sep, (double)edgeWeight / weightDivisor); fprintf(fgxFile, "];\n"); } @@ -1106,32 +1085,22 @@ bool Compiler::fgDumpFlowGraph(Phases phase, PhasePosition pos) fprintf(fgxFile, "\n switchDefault=\"true\""); } } - if (validWeights) - { - weight_t edgeWeight = (edge->edgeWeightMin() + edge->edgeWeightMax()) / 2; - fprintf(fgxFile, "\n weight="); - fprintfDouble(fgxFile, ((double)edgeWeight) / weightDivisor); - if (edge->edgeWeightMin() != edge->edgeWeightMax()) + const weight_t edgeWeight = edge->getLikelyWeight(); + fprintf(fgxFile, "\n weight="); + fprintfDouble(fgxFile, ((double)edgeWeight) / weightDivisor); + + if (edgeWeight > 0) + { + if (edgeWeight < bSource->bbWeight) { - fprintf(fgxFile, "\n minWeight="); - fprintfDouble(fgxFile, ((double)edge->edgeWeightMin()) / weightDivisor); - fprintf(fgxFile, "\n maxWeight="); - fprintfDouble(fgxFile, ((double)edge->edgeWeightMax()) / weightDivisor); + fprintf(fgxFile, "\n out="); + fprintfDouble(fgxFile, ((double)edgeWeight) / sourceWeightDivisor); } - - if (edgeWeight > 0) + if (edgeWeight < bTarget->bbWeight) { - if (edgeWeight < bSource->bbWeight) - { - fprintf(fgxFile, "\n out="); - fprintfDouble(fgxFile, ((double)edgeWeight) / sourceWeightDivisor); - } - if (edgeWeight < bTarget->bbWeight) - { - fprintf(fgxFile, "\n in="); - fprintfDouble(fgxFile, ((double)edgeWeight) / targetWeightDivisor); - } + fprintf(fgxFile, "\n in="); + fprintfDouble(fgxFile, ((double)edgeWeight) / targetWeightDivisor); } } } @@ -1815,13 +1784,13 @@ void Compiler::fgTableDispBasicBlock(const BasicBlock* block, int blockTargetFieldWidth /* = 21 */, int ibcColWidth /* = 0 */) { - const unsigned __int64 flags = block->GetFlagsRaw(); - unsigned bbNumMax = fgBBNumMax; - int maxBlockNumWidth = CountDigits(bbNumMax); - maxBlockNumWidth = max(maxBlockNumWidth, 2); - int blockNumWidth = CountDigits(block->bbNum); - blockNumWidth = max(blockNumWidth, 2); - int blockNumPadding = maxBlockNumWidth - blockNumWidth; + const uint64_t flags = block->GetFlagsRaw(); + unsigned bbNumMax = fgBBNumMax; + int maxBlockNumWidth = CountDigits(bbNumMax); + maxBlockNumWidth = max(maxBlockNumWidth, 2); + int blockNumWidth = CountDigits(block->bbNum); + blockNumWidth = max(blockNumWidth, 2); + int blockNumPadding = maxBlockNumWidth - blockNumWidth; // Instead of displaying a block number, should we instead display "*" when the specified block is // the next block? diff --git a/src/coreclr/jit/fgehopt.cpp b/src/coreclr/jit/fgehopt.cpp index 47127fc0ad20..743559717e47 100644 --- a/src/coreclr/jit/fgehopt.cpp +++ b/src/coreclr/jit/fgehopt.cpp @@ -1229,16 +1229,6 @@ PhaseStatus Compiler::fgCloneFinally() block->setBBProfileWeight(blockWeight * originalScale); JITDUMP("Set weight of " FMT_BB " to " FMT_WT "\n", block->bbNum, block->bbWeight); -#if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION - // Handle a special case -- some handler entries can't have zero profile count. - // - if (bbIsHandlerBeg(block) && block->isRunRarely()) - { - JITDUMP("Suppressing zero count for " FMT_BB " as it is a handler entry\n", block->bbNum); - block->makeBlockHot(); - } -#endif - BasicBlock* const clonedBlock = blockMap[block]; clonedBlock->setBBProfileWeight(blockWeight * clonedScale); JITDUMP("Set weight of " FMT_BB " to " FMT_WT "\n", clonedBlock->bbNum, clonedBlock->bbWeight); @@ -1910,7 +1900,7 @@ PhaseStatus Compiler::fgTailMergeThrows() // The second pass modifies flow so that predecessors of // non-canonical throw blocks now transfer control to the // appropriate canonical block. - int numCandidates = 0; + unsigned numCandidates = 0; // First pass // @@ -1960,9 +1950,6 @@ PhaseStatus Compiler::fgTailMergeThrows() continue; } - // Sanity check -- only user funcs should be marked do not return - assert(call->gtCallType == CT_USER_FUNC); - // Ok, we've found a suitable call. See if this is one we know // about already, or something new. BasicBlock* canonicalBlock = nullptr; @@ -1987,6 +1974,8 @@ PhaseStatus Compiler::fgTailMergeThrows() } } + assert(numCandidates <= optNoReturnCallCount); + // Bail if no candidates were found if (numCandidates == 0) { diff --git a/src/coreclr/jit/fgflow.cpp b/src/coreclr/jit/fgflow.cpp index f4f650f6b5d3..c1060e1373d6 100644 --- a/src/coreclr/jit/fgflow.cpp +++ b/src/coreclr/jit/fgflow.cpp @@ -191,42 +191,6 @@ FlowEdge* Compiler::fgAddRefPred(BasicBlock* block, BasicBlock* blockPred, FlowE // flow->setLikelihood(oldEdge->getLikelihood()); } - - if (fgHaveValidEdgeWeights) - { - // We are creating an edge from blockPred to block - // and we have already computed the edge weights, so - // we will try to setup this new edge with valid edge weights. - // - if (oldEdge != nullptr) - { - // If our caller has given us the old edge weights - // then we will use them. - // - flow->setEdgeWeights(oldEdge->edgeWeightMin(), oldEdge->edgeWeightMax(), block); - } - else - { - // Set the max edge weight to be the minimum of block's or blockPred's weight - // - weight_t newWeightMax = min(block->bbWeight, blockPred->bbWeight); - - // If we are inserting a conditional block the minimum weight is zero, - // otherwise it is the same as the edge's max weight. - if (blockPred->NumSucc() > 1) - { - flow->setEdgeWeights(BB_ZERO_WEIGHT, newWeightMax, block); - } - else - { - flow->setEdgeWeights(flow->edgeWeightMax(), newWeightMax, block); - } - } - } - else - { - flow->setEdgeWeights(BB_ZERO_WEIGHT, BB_MAX_WEIGHT, block); - } } // Pred list should (still) be ordered. diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp index 0f0fb3c7c484..7a6246a988fd 100644 --- a/src/coreclr/jit/fginline.cpp +++ b/src/coreclr/jit/fginline.cpp @@ -624,24 +624,86 @@ class SubstitutePlaceholdersAndDevirtualizeWalker : public GenTreeVisitordspTreeID(tree), block->bbNum); + m_compiler->Metrics.InlinerBranchFold++; // 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. m_compiler->gtUpdateNodeSideEffects(tree); assert((tree->gtFlags & GTF_SIDE_EFFECT) == 0); tree->gtBashToNOP(); - m_madeChanges = true; + m_madeChanges = true; + FlowEdge* removedEdge = nullptr; if (condTree->IsIntegralConst(0)) { - m_compiler->fgRemoveRefPred(block->GetTrueEdge()); + removedEdge = block->GetTrueEdge(); + m_compiler->fgRemoveRefPred(removedEdge); block->SetKindAndTargetEdge(BBJ_ALWAYS, block->GetFalseEdge()); } else { - m_compiler->fgRemoveRefPred(block->GetFalseEdge()); + removedEdge = block->GetFalseEdge(); + m_compiler->fgRemoveRefPred(removedEdge); block->SetKindAndTargetEdge(BBJ_ALWAYS, block->GetTrueEdge()); } + + // Update profile; make it consistent if possible + // + if (block->hasProfileWeight()) + { + bool repairWasComplete = true; + weight_t const weight = removedEdge->getLikelyWeight(); + + if (weight > 0) + { + // Target block weight will increase. + // + BasicBlock* const target = block->GetTarget(); + assert(target->hasProfileWeight()); + target->setBBProfileWeight(target->bbWeight + weight); + + // Alternate weight will decrease + // + BasicBlock* const alternate = removedEdge->getDestinationBlock(); + assert(alternate->hasProfileWeight()); + weight_t const alternateNewWeight = alternate->bbWeight - weight; + + // If profile weights are consistent, expect at worst a slight underflow. + // + if (m_compiler->fgPgoConsistent && (alternateNewWeight < 0)) + { + assert(m_compiler->fgProfileWeightsEqual(alternateNewWeight, 0)); + } + alternate->setBBProfileWeight(max(0.0, alternateNewWeight)); + + // This will affect profile transitively, so in general + // the profile will become inconsistent. + // + repairWasComplete = false; + + // But we can check for the special case where the + // block's postdominator is target's target (simple + // if/then/else/join). + // + if (target->KindIs(BBJ_ALWAYS)) + { + repairWasComplete = + alternate->KindIs(BBJ_ALWAYS) && alternate->TargetIs(target->GetTarget()); + } + } + + if (!repairWasComplete) + { + JITDUMP("Profile data could not be locally repaired. Data %s inconsistent.\n", + m_compiler->fgPgoConsistent ? "is now" : "was already"); + + if (m_compiler->fgPgoConsistent) + { + m_compiler->Metrics.ProfileInconsistentInlinerBranchFold++; + m_compiler->fgPgoConsistent = false; + } + } + } } } else @@ -692,6 +754,11 @@ PhaseStatus Compiler::fgInline() JitConfig.JitPrintInlinedMethods().contains(info.compMethodHnd, info.compClassHnd, &info.compMethodInfo->args); #endif // DEBUG + if (fgPgoConsistent) + { + Metrics.ProfileConsistentBeforeInline++; + } + noway_assert(fgFirstBB != nullptr); BasicBlock* block = fgFirstBB; @@ -822,6 +889,14 @@ PhaseStatus Compiler::fgInline() fgRenumberBlocks(); } + if (fgPgoConsistent) + { + Metrics.ProfileConsistentAfterInline++; + } + + Metrics.InlineCount = m_inlineStrategy->GetInlineCount(); + Metrics.InlineAttempt = m_inlineStrategy->GetImportCount(); + return madeChanges ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING; } @@ -910,6 +985,12 @@ void Compiler::fgMorphCallInline(GenTreeCall* call, InlineResult* inlineResult) noway_assert(fgMorphStmt->GetRootNode() == call); fgMorphStmt->SetRootNode(gtNewNothingNode()); } + + // Inlinee compiler may have determined call does not return; if so, update this compiler's state. + if (call->IsNoReturn()) + { + setMethodHasNoReturnCalls(); + } } } @@ -1520,7 +1601,7 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) } // - // At this point, we have successully inserted inlinee's code. + // At this point, we have successfully inserted inlinee's code. // // @@ -1581,6 +1662,14 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) } } + // Update no-return call count + optNoReturnCallCount += InlineeCompiler->optNoReturnCallCount; + +#ifdef DEBUG + // Update metrics + Metrics.mergeToRoot(InlineeCompiler); +#endif + // Update optMethodFlags #ifdef DEBUG @@ -1597,6 +1686,75 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) } #endif + // Update profile consistency + // + // If inlinee is inconsistent, root method will be inconsistent too. + // + if (!InlineeCompiler->fgPgoConsistent) + { + if (fgPgoConsistent) + { + JITDUMP("INLINER: profile data in root now inconsistent -- inlinee had inconsistency\n"); + Metrics.ProfileInconsistentInlinee++; + fgPgoConsistent = false; + } + } + + // If we inline a no-return call at a site with profile weight, + // we will introduce inconsistency. + // + if (InlineeCompiler->fgReturnCount == 0) + { + JITDUMP("INLINER: no-return inlinee\n"); + + if (iciBlock->bbWeight > 0) + { + if (fgPgoConsistent) + { + JITDUMP("INLINER: profile data in root now inconsistent -- no-return inlinee at call site in " FMT_BB + " with weight " FMT_WT "\n", + iciBlock->bbNum, iciBlock->bbWeight); + Metrics.ProfileInconsistentNoReturnInlinee++; + fgPgoConsistent = false; + } + } + else + { + // Inlinee scaling should assure this is so. + // + assert(InlineeCompiler->fgFirstBB->bbWeight == 0); + } + } + + // If the call site is not in a try and the callee has a throw, + // we may introduce inconsistency. + // + // Technically we should check if the callee has a throw not in a try, but since + // we can't inline methods with EH yet we don't see those. + // + if (InlineeCompiler->fgThrowCount > 0) + { + JITDUMP("INLINER: may-throw inlinee\n"); + + if (iciBlock->bbWeight > 0) + { + if (fgPgoConsistent) + { + JITDUMP("INLINER: profile data in root now inconsistent -- may-throw inlinee at call site in " FMT_BB + " with weight " FMT_WT "\n", + iciBlock->bbNum, iciBlock->bbWeight); + Metrics.ProfileInconsistentMayThrowInlinee++; + fgPgoConsistent = false; + } + } + else + { + // Inlinee scaling should assure this is so. + // + assert(InlineeCompiler->fgFirstBB->bbWeight == 0); + } + } + // If an inlinee needs GS cookie we need to make sure that the cookie will not be allocated at zero stack offset. // Note that if the root method needs GS cookie then this has already been taken care of. if (!getNeedsGSSecurityCookie() && InlineeCompiler->getNeedsGSSecurityCookie()) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index adb3df9327a2..4fd6e4ff39f2 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -731,17 +731,8 @@ PhaseStatus Compiler::fgPostImportationCleanup() // auto addConditionalFlow = [this, entryStateVar, &entryJumpTarget, &addedBlocks](BasicBlock* fromBlock, BasicBlock* toBlock) { - // We may have previously though this try entry was unreachable, but now we're going to - // step through it on the way to the OSR entry. So ensure it has plausible profile weight. - // - if (fgHaveProfileWeights() && !fromBlock->hasProfileWeight()) - { - JITDUMP("Updating block weight for now-reachable try entry " FMT_BB " via " FMT_BB "\n", - fromBlock->bbNum, fgFirstBB->bbNum); - fromBlock->inheritWeight(fgFirstBB); - } - BasicBlock* const newBlock = fgSplitBlockAtBeginning(fromBlock); + newBlock->inheritWeight(fromBlock); fromBlock->SetFlags(BBF_INTERNAL); newBlock->RemoveFlags(BBF_DONT_REMOVE); addedBlocks++; @@ -754,16 +745,40 @@ PhaseStatus Compiler::fgPostImportationCleanup() fgNewStmtAtBeg(fromBlock, jumpIfEntryStateZero); FlowEdge* const osrTryEntryEdge = fgAddRefPred(toBlock, fromBlock); - newBlock->inheritWeight(fromBlock); fromBlock->SetCond(osrTryEntryEdge, normalTryEntryEdge); - // Not sure what the correct edge likelihoods are just yet; - // for now we'll say the OSR path is the likely one. - // - // Todo: can we leverage profile data here to get a better answer? - // - osrTryEntryEdge->setLikelihood(0.9); - normalTryEntryEdge->setLikelihood(0.1); + if (fgHaveProfileWeights()) + { + // We are adding a path from (ultimately) the method entry to "fromBlock" + // Update the profile weight. + // + weight_t const entryWeight = fgFirstBB->bbWeight; + + JITDUMP("Updating block weight for now-reachable try entry " FMT_BB " via " FMT_BB "\n", + fromBlock->bbNum, fgFirstBB->bbNum); + fromBlock->setBBProfileWeight(fromBlock->bbWeight + entryWeight); + + // We updated the weight of fromBlock above. + // + // Set the likelihoods such that the additional weight flows to toBlock + // (and so the "normal path" profile out of fromBlock to newBlock is unaltered) + // + // In some stress cases we may have a zero-weight OSR entry. + // Tolerate this by capping the fromToLikelihood. + // + weight_t const fromWeight = fromBlock->bbWeight; + weight_t const fromToLikelihood = min(1.0, entryWeight / fromWeight); + + osrTryEntryEdge->setLikelihood(fromToLikelihood); + normalTryEntryEdge->setLikelihood(1.0 - fromToLikelihood); + } + else + { + // Just set likelihoods arbitrarily + // + osrTryEntryEdge->setLikelihood(0.9); + normalTryEntryEdge->setLikelihood(0.1); + } entryJumpTarget = fromBlock; }; @@ -950,8 +965,10 @@ bool Compiler::fgCanCompactBlocks(BasicBlock* block, BasicBlock* bNext) // Arguments: // block - move all code into this block. // bNext - bbNext of `block`. This block will be removed. +// doDebugCheck - in Debug builds, check flowgraph for correctness after compaction +// (some callers might compact blocks during destructive flowgraph changes, and thus should skip checks) // -void Compiler::fgCompactBlocks(BasicBlock* block, BasicBlock* bNext) +void Compiler::fgCompactBlocks(BasicBlock* block, BasicBlock* bNext DEBUGARG(bool doDebugCheck /* = true */)) { noway_assert(block != nullptr); noway_assert(bNext != nullptr); @@ -1316,7 +1333,7 @@ void Compiler::fgCompactBlocks(BasicBlock* block, BasicBlock* bNext) #endif #if DEBUG - if (JitConfig.JitSlowDebugChecksEnabled() != 0) + if (doDebugCheck && (JitConfig.JitSlowDebugChecksEnabled() != 0)) { // Make sure that the predecessor lists are accurate fgDebugCheckBBlist(); @@ -1449,33 +1466,14 @@ bool Compiler::fgOptimizeBranchToEmptyUnconditional(BasicBlock* block, BasicBloc // // When we optimize a branch to branch we need to update the profile weight - // of bDest by subtracting out the block/edge weight of the path that is being optimized. + // of bDest by subtracting out the weight of the path that is being optimized. // - if (fgHaveValidEdgeWeights && bDest->hasProfileWeight()) + if (bDest->hasProfileWeight()) { - FlowEdge* edge1 = fgGetPredForBlock(bDest, block); - noway_assert(edge1 != nullptr); + FlowEdge* const edge = fgGetPredForBlock(bDest, block); + noway_assert(edge != nullptr); - weight_t edgeWeight; - - if (edge1->edgeWeightMin() != edge1->edgeWeightMax()) - { - // - // We only have an estimate for the edge weight - // - edgeWeight = (edge1->edgeWeightMin() + edge1->edgeWeightMax()) / 2; - // - // Clear the profile weight flag - // - bDest->RemoveFlags(BBF_PROF_WEIGHT); - } - else - { - // - // We only have the exact edge weight - // - edgeWeight = edge1->edgeWeightMin(); - } + const weight_t edgeWeight = edge->getLikelyWeight(); // // Update the bDest->bbWeight @@ -1489,36 +1487,6 @@ bool Compiler::fgOptimizeBranchToEmptyUnconditional(BasicBlock* block, BasicBloc bDest->bbWeight = BB_ZERO_WEIGHT; bDest->SetFlags(BBF_RUN_RARELY); // Set the RarelyRun flag } - - FlowEdge* edge2 = bDest->GetTargetEdge(); - - if (edge2 != nullptr) - { - // - // Update the edge2 min/max weights - // - weight_t newEdge2Min; - weight_t newEdge2Max; - - if (edge2->edgeWeightMin() > edge1->edgeWeightMin()) - { - newEdge2Min = edge2->edgeWeightMin() - edge1->edgeWeightMin(); - } - else - { - newEdge2Min = BB_ZERO_WEIGHT; - } - - if (edge2->edgeWeightMax() > edge1->edgeWeightMin()) - { - newEdge2Max = edge2->edgeWeightMax() - edge1->edgeWeightMin(); - } - else - { - newEdge2Max = BB_ZERO_WEIGHT; - } - edge2->setEdgeWeights(newEdge2Min, newEdge2Max, bDest); - } } // Optimize the JUMP to empty unconditional JUMP to go to the new target @@ -1711,7 +1679,7 @@ bool Compiler::fgOptimizeEmptyBlock(BasicBlock* block) break; } - // When using profile weights, fgComputeEdgeWeights expects the first non-internal block to have profile + // When using profile weights, fgComputeCalledCount expects the first non-internal block to have profile // weight. // Make sure we don't break that invariant. if (fgIsUsingProfileWeights() && block->hasProfileWeight() && !block->HasFlag(BBF_INTERNAL)) @@ -1807,29 +1775,24 @@ bool Compiler::fgOptimizeSwitchBranches(BasicBlock* block) { // // When we optimize a branch to branch we need to update the profile weight - // of bDest by subtracting out the block/edge weight of the path that is being optimized. + // of bDest by subtracting out the block weight of the path that is being optimized. // + FlowEdge* const oldEdge = *jmpTab; + if (fgIsUsingProfileWeights() && bDest->hasProfileWeight()) { - if (fgHaveValidEdgeWeights) + weight_t const branchThroughWeight = oldEdge->getLikelyWeight(); + if (bDest->bbWeight > branchThroughWeight) { - FlowEdge* edge = *jmpTab; - weight_t branchThroughWeight = edge->edgeWeightMin(); - - if (bDest->bbWeight > branchThroughWeight) - { - bDest->bbWeight -= branchThroughWeight; - } - else - { - bDest->bbWeight = BB_ZERO_WEIGHT; - bDest->SetFlags(BBF_RUN_RARELY); - } + bDest->bbWeight -= branchThroughWeight; + } + else + { + bDest->bbSetRunRarely(); } } // Update the switch jump table - FlowEdge* const oldEdge = *jmpTab; fgRemoveRefPred(oldEdge); FlowEdge* const newEdge = fgAddRefPred(bNewDest, block, oldEdge); *jmpTab = newEdge; @@ -3045,47 +3008,9 @@ bool Compiler::fgOptimizeSwitchJumps() newBlock->setBBProfileWeight(blockToNewBlockWeight); - blockToTargetEdge->setEdgeWeights(blockToTargetWeight, blockToTargetWeight, dominantTarget); blockToTargetEdge->setLikelihood(fraction); - blockToNewBlockEdge->setEdgeWeights(blockToNewBlockWeight, blockToNewBlockWeight, block); blockToNewBlockEdge->setLikelihood(max(0.0, 1.0 - fraction)); - // There may be other switch cases that lead to this same block, but there's just - // one edge in the flowgraph. So we need to subtract off the profile data that now flows - // along the peeled edge. - // - for (FlowEdge* pred = dominantTarget->bbPreds; pred != nullptr; pred = pred->getNextPredEdge()) - { - if (pred->getSourceBlock() == newBlock) - { - if (pred->getDupCount() == 1) - { - // The only switch case leading to the dominant target was the one we peeled. - // So the edge from the switch now has zero weight. - // - pred->setEdgeWeights(BB_ZERO_WEIGHT, BB_ZERO_WEIGHT, dominantTarget); - } - else - { - // Other switch cases also lead to the dominant target. - // Subtract off the weight we transferred to the peel. - // - weight_t newMinWeight = pred->edgeWeightMin() - blockToTargetWeight; - weight_t newMaxWeight = pred->edgeWeightMax() - blockToTargetWeight; - - if (newMinWeight < BB_ZERO_WEIGHT) - { - newMinWeight = BB_ZERO_WEIGHT; - } - if (newMaxWeight < BB_ZERO_WEIGHT) - { - newMaxWeight = BB_ZERO_WEIGHT; - } - pred->setEdgeWeights(newMinWeight, newMaxWeight, dominantTarget); - } - } - } - // For now we leave the switch as is, since there's no way // to indicate that one of the cases is now unreachable. // @@ -3493,9 +3418,22 @@ bool Compiler::fgReorderBlocks(bool useProfile) } } - // If we will be reordering blocks, ensure the false target of a BBJ_COND block is its next block if (useProfile) { + if (JitConfig.JitDoReversePostOrderLayout()) + { + fgDoReversePostOrderLayout(); + fgMoveColdBlocks(); + + // Renumber blocks to facilitate LSRA's order of block visitation + // TODO: Consider removing this, and using traversal order in lSRA + // + fgRenumberBlocks(); + + return true; + } + + // We will be reordering blocks, so ensure the false target of a BBJ_COND block is its next block for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->Next()) { if (block->KindIs(BBJ_COND) && !block->NextIs(block->GetFalseTarget())) @@ -3637,43 +3575,19 @@ bool Compiler::fgReorderBlocks(bool useProfile) // bool moveDestUp = true; - if (fgHaveValidEdgeWeights) - { - // - // The edge bPrev -> bDest must have a higher minimum weight - // than every other edge into bDest - // - FlowEdge* edgeFromPrev = bPrev->GetTargetEdge(); - noway_assert(edgeFromPrev != nullptr); + // + // The edge bPrev -> bDest must have a higher weight + // than every other edge into bDest + // + weight_t const weightToBeat = bPrev->GetTargetEdge()->getLikelyWeight(); - // Examine all of the other edges into bDest - for (FlowEdge* const edge : bDest->PredEdges()) - { - if (edge != edgeFromPrev) - { - if (edge->edgeWeightMax() >= edgeFromPrev->edgeWeightMin()) - { - moveDestUp = false; - break; - } - } - } - } - else + // Examine all of the other edges into bDest + for (FlowEdge* const edge : bDest->PredEdges()) { - // - // The block bPrev must have a higher weight - // than every other block that goes into bDest - // - - // Examine all of the other edges into bDest - for (BasicBlock* const predBlock : bDest->PredBlocks()) + if (edge->getLikelyWeight() > weightToBeat) { - if ((predBlock != bPrev) && (predBlock->bbWeight >= bPrev->bbWeight)) - { - moveDestUp = false; - break; - } + moveDestUp = false; + break; } } @@ -3707,98 +3621,43 @@ bool Compiler::fgReorderBlocks(bool useProfile) { noway_assert(bPrev->KindIs(BBJ_COND)); // - // We will reverse branch if the taken-jump to bDest ratio (i.e. 'takenRatio') - // is more than 51% + // We will reverse branch if the true edge's likelihood is more than 51%. // - // We will setup profHotWeight to be maximum bbWeight that a block - // could have for us not to want to reverse the conditional branch + // We will set up profHotWeight to be maximum bbWeight that a block + // could have for us not to want to reverse the conditional branch. // // We will consider all blocks that have less weight than profHotWeight to be - // uncommonly run blocks as compared with the hot path of bPrev taken-jump to bDest + // uncommonly run blocks compared to the weight of bPrev's true edge. + // + // We will check if bPrev's true edge weight + // is more than twice bPrev's false edge weight. // - if (fgHaveValidEdgeWeights) + // bPrev --> [BB04, weight 100] + // | \. + // falseEdge ---------------> O \. + // [likelihood=0.33] V \. + // block --> [BB05, weight 33] \. + // \. + // trueEdge ------------------------------> O + // [likelihood=0.67] | + // V + // bDest ---------------> [BB08, weight 67] + // + assert(bPrev->FalseTargetIs(block)); + FlowEdge* trueEdge = bPrev->GetTrueEdge(); + FlowEdge* falseEdge = bPrev->GetFalseEdge(); + noway_assert(trueEdge != nullptr); + noway_assert(falseEdge != nullptr); + + // If we take the true branch more than half the time, we will reverse the branch. + if (trueEdge->getLikelihood() < 0.51) { - // We have valid edge weights, however even with valid edge weights - // we may have a minimum and maximum range for each edges value - // - // We will check that the min weight of the bPrev to bDest edge - // is more than twice the max weight of the bPrev to block edge. - // - // bPrev --> [BB04, weight 31] - // | \. - // edgeToBlock -------------> O \. - // [min=8,max=10] V \. - // block --> [BB05, weight 10] \. - // \. - // edgeToDest ----------------------------> O - // [min=21,max=23] | - // V - // bDest ---------------> [BB08, weight 21] - // - assert(bPrev->FalseTargetIs(block)); - FlowEdge* edgeToDest = bPrev->GetTrueEdge(); - FlowEdge* edgeToBlock = bPrev->GetFalseEdge(); - noway_assert(edgeToDest != nullptr); - noway_assert(edgeToBlock != nullptr); - // - // Calculate the taken ratio - // A takenRation of 0.10 means taken 10% of the time, not taken 90% of the time - // A takenRation of 0.50 means taken 50% of the time, not taken 50% of the time - // A takenRation of 0.90 means taken 90% of the time, not taken 10% of the time - // - double takenCount = - ((double)edgeToDest->edgeWeightMin() + (double)edgeToDest->edgeWeightMax()) / 2.0; - double notTakenCount = - ((double)edgeToBlock->edgeWeightMin() + (double)edgeToBlock->edgeWeightMax()) / 2.0; - double totalCount = takenCount + notTakenCount; - - // If the takenRatio (takenCount / totalCount) is greater or equal to 51% then we will reverse - // the branch - if (takenCount < (0.51 * totalCount)) - { - reorderBlock = false; - } - else - { - // set profHotWeight - profHotWeight = (edgeToBlock->edgeWeightMin() + edgeToBlock->edgeWeightMax()) / 2 - 1; - } + reorderBlock = false; } else { - // We don't have valid edge weight so we will be more conservative - // We could have bPrev, block or bDest as part of a loop and thus have extra weight - // - // We will do two checks: - // 1. Check that the weight of bDest is at least two times more than block - // 2. Check that the weight of bPrev is at least three times more than block - // - // bPrev --> [BB04, weight 31] - // | \. - // V \. - // block --> [BB05, weight 10] \. - // \. - // | - // V - // bDest ---------------> [BB08, weight 21] - // - // For this case weightDest is calculated as (21+1)/2 or 11 - // and weightPrev is calculated as (31+2)/3 also 11 - // - // Generally both weightDest and weightPrev should calculate - // the same value unless bPrev or bDest are part of a loop - // - weight_t weightDest = bDest->isMaxBBWeight() ? bDest->bbWeight : (bDest->bbWeight + 1) / 2; - weight_t weightPrev = bPrev->isMaxBBWeight() ? bPrev->bbWeight : (bPrev->bbWeight + 2) / 3; - - // select the lower of weightDest and weightPrev - profHotWeight = (weightDest < weightPrev) ? weightDest : weightPrev; - - // if the weight of block is greater (or equal) to profHotWeight then we don't reverse the cond - if (block->bbWeight >= profHotWeight) - { - reorderBlock = false; - } + // set profHotWeight + profHotWeight = falseEdge->getLikelyWeight() - 1; } } } @@ -4682,6 +4541,626 @@ bool Compiler::fgReorderBlocks(bool useProfile) #pragma warning(pop) #endif +//----------------------------------------------------------------------------- +// fgMoveBackwardJumpsToSuccessors: Try to move backward unconditional jumps to fall into their successors. +// +// Template parameters: +// hasEH - If true, method has EH regions, so check that we don't try to move blocks in different regions +// +template +void Compiler::fgMoveBackwardJumpsToSuccessors() +{ +#ifdef DEBUG + if (verbose) + { + printf("*************** In fgMoveBackwardJumpsToSuccessors()\n"); + + printf("\nInitial BasicBlocks"); + fgDispBasicBlocks(verboseTrees); + printf("\n"); + } +#endif // DEBUG + + // Compact blocks before trying to move any jumps. + // This can unlock more opportunities for fallthrough behavior. + // + for (BasicBlock* block = fgFirstBB; block != fgFirstFuncletBB;) + { + if (fgCanCompactBlocks(block, block->Next())) + { + // We haven't fixed EH information yet, so don't do any correctness checks here + // + fgCompactBlocks(block, block->Next() DEBUGARG(/* doDebugCheck */ false)); + } + else + { + block = block->Next(); + } + } + + EnsureBasicBlockEpoch(); + BlockSet visitedBlocks(BlockSetOps::MakeEmpty(this)); + BlockSetOps::AddElemD(this, visitedBlocks, fgFirstBB->bbNum); + + // Don't try to move the first block. + // Also, if we have a funclet region, don't bother reordering anything in it. + // + BasicBlock* next; + for (BasicBlock* block = fgFirstBB->Next(); block != fgFirstFuncletBB; block = next) + { + next = block->Next(); + BlockSetOps::AddElemD(this, visitedBlocks, block->bbNum); + + // Don't bother trying to move cold blocks + // + if (!block->KindIs(BBJ_ALWAYS) || block->isRunRarely()) + { + continue; + } + + // We will consider moving only backward jumps + // + BasicBlock* const target = block->GetTarget(); + if ((block == target) || !BlockSetOps::IsMember(this, visitedBlocks, target->bbNum)) + { + continue; + } + + if (hasEH) + { + // Don't move blocks in different EH regions + // + if (!BasicBlock::sameEHRegion(block, target)) + { + continue; + } + + // block and target are in the same try/handler regions, and target is behind block, + // so block cannot possibly be the start of the region. + // + assert(!bbIsTryBeg(block) && !bbIsHandlerBeg(block)); + + // Don't change the entry block of an EH region + // + if (bbIsTryBeg(target) || bbIsHandlerBeg(target)) + { + continue; + } + } + + // We don't want to change the first block, so if the jump target is the first block, + // don't try moving this block before it. + // Also, if the target is cold, don't bother moving this block up to it. + // + if (target->IsFirst() || target->isRunRarely()) + { + continue; + } + + // If moving block will break up existing fallthrough behavior into target, make sure it's worth it + // + FlowEdge* const fallthroughEdge = fgGetPredForBlock(target, target->Prev()); + if ((fallthroughEdge != nullptr) && + (fallthroughEdge->getLikelyWeight() >= block->GetTargetEdge()->getLikelyWeight())) + { + continue; + } + + // Move block to before target + // + fgUnlinkBlock(block); + fgInsertBBbefore(target, block); + } +} + +//----------------------------------------------------------------------------- +// fgDoReversePostOrderLayout: Reorder blocks using a greedy RPO traversal. +// +void Compiler::fgDoReversePostOrderLayout() +{ +#ifdef DEBUG + if (verbose) + { + printf("*************** In fgDoReversePostOrderLayout()\n"); + + printf("\nInitial BasicBlocks"); + fgDispBasicBlocks(verboseTrees); + printf("\n"); + } +#endif // DEBUG + + // Compute DFS of all blocks in the method, using profile data to determine the order successors are visited in + // + FlowGraphDfsTree* const dfsTree = fgComputeDfs(); + + // Fast path: We don't have any EH regions, so just reorder the blocks + // + if (compHndBBtabCount == 0) + { + for (unsigned i = dfsTree->GetPostOrderCount() - 1; i != 0; i--) + { + BasicBlock* const block = dfsTree->GetPostOrder(i); + BasicBlock* const blockToMove = dfsTree->GetPostOrder(i - 1); + fgUnlinkBlock(blockToMove); + fgInsertBBafter(block, blockToMove); + } + + // The RPO established a good base layout, but in some cases, it might produce a subpar layout for loops. + // In particular, it may place the loop head after the loop exit, creating unnecessary branches. + // Fix this by moving unconditional backward jumps up to their targets, + // increasing the likelihood that the loop exit block is the last block in the loop. + // + fgMoveBackwardJumpsToSuccessors(); + + return; + } + + // The RPO will scramble the EH regions, requiring us to correct their state. + // To do so, we will need to determine the new end blocks of each region. + // + struct EHLayoutInfo + { + BasicBlock* tryRegionEnd; + BasicBlock* hndRegionEnd; + bool tryRegionInMainBody; + + // Default constructor provided so we can call ArrayStack::Emplace + // + EHLayoutInfo() = default; + }; + + ArrayStack regions(getAllocator(CMK_ArrayStack), compHndBBtabCount); + + // The RPO will break up call-finally pairs, so save them before re-ordering + // + struct CallFinallyPair + { + BasicBlock* callFinally; + BasicBlock* callFinallyRet; + + // Constructor provided so we can call ArrayStack::Emplace + // + CallFinallyPair(BasicBlock* first, BasicBlock* second) + : callFinally(first) + , callFinallyRet(second) + { + } + }; + + ArrayStack callFinallyPairs(getAllocator()); + + for (EHblkDsc* const HBtab : EHClauses(this)) + { + // Default-initialize a EHLayoutInfo for each EH clause + regions.Emplace(); + + if (HBtab->HasFinallyHandler()) + { + for (BasicBlock* const pred : HBtab->ebdHndBeg->PredBlocks()) + { + assert(pred->KindIs(BBJ_CALLFINALLY)); + if (pred->isBBCallFinallyPair()) + { + callFinallyPairs.Emplace(pred, pred->Next()); + } + } + } + } + + // Reorder blocks + // + for (unsigned i = dfsTree->GetPostOrderCount() - 1; i != 0; i--) + { + BasicBlock* const block = dfsTree->GetPostOrder(i); + BasicBlock* const blockToMove = dfsTree->GetPostOrder(i - 1); + + // Only reorder blocks within the same EH region -- we don't want to make them non-contiguous + // + if (BasicBlock::sameEHRegion(block, blockToMove)) + { + // Don't reorder EH regions with filter handlers -- we want the filter to come first + // + if (block->hasHndIndex() && ehGetDsc(block->getHndIndex())->HasFilter()) + { + continue; + } + + fgUnlinkBlock(blockToMove); + fgInsertBBafter(block, blockToMove); + } + } + + // Fix up call-finally pairs + // + for (int i = 0; i < callFinallyPairs.Height(); i++) + { + const CallFinallyPair& pair = callFinallyPairs.BottomRef(i); + fgUnlinkBlock(pair.callFinallyRet); + fgInsertBBafter(pair.callFinally, pair.callFinallyRet); + } + + fgMoveBackwardJumpsToSuccessors(); + + // The RPO won't change the entry blocks of any EH regions, but reordering can change the last block in a region + // (for example, by pushing throw blocks unreachable via normal flow to the end of the region). + // First, determine the new EH region ends. + // + + for (BasicBlock* const block : Blocks(fgFirstBB, fgLastBBInMainFunction())) + { + if (block->hasTryIndex()) + { + EHLayoutInfo& layoutInfo = regions.BottomRef(block->getTryIndex()); + layoutInfo.tryRegionEnd = block; + layoutInfo.tryRegionInMainBody = true; + } + + if (block->hasHndIndex()) + { + regions.BottomRef(block->getHndIndex()).hndRegionEnd = block; + } + } + + for (BasicBlock* const block : Blocks(fgFirstFuncletBB)) + { + if (block->hasHndIndex()) + { + regions.BottomRef(block->getHndIndex()).hndRegionEnd = block; + } + + if (block->hasTryIndex()) + { + EHLayoutInfo& layoutInfo = regions.BottomRef(block->getTryIndex()); + + if (!layoutInfo.tryRegionInMainBody) + { + layoutInfo.tryRegionEnd = block; + } + } + } + + // Now, update the EH descriptors, starting with the try regions + // + auto getTryLast = [®ions](const unsigned index) -> BasicBlock* { + return regions.BottomRef(index).tryRegionEnd; + }; + + auto setTryLast = [®ions](const unsigned index, BasicBlock* const block) { + regions.BottomRef(index).tryRegionEnd = block; + }; + + ehUpdateTryLasts(getTryLast, setTryLast); + + // Now, do the handler regions + // + unsigned XTnum = 0; + for (EHblkDsc* const HBtab : EHClauses(this)) + { + // The end of each handler region should have been visited by iterating the blocklist above + // + BasicBlock* const hndEnd = regions.BottomRef(XTnum++).hndRegionEnd; + assert(hndEnd != nullptr); + + // Update the end pointer of this handler region to the new last block + // + HBtab->ebdHndLast = hndEnd; + const unsigned enclosingHndIndex = HBtab->ebdEnclosingHndIndex; + + // If this handler region is nested in another one, we might need to update its enclosing region's end block + // + if (enclosingHndIndex != EHblkDsc::NO_ENCLOSING_INDEX) + { + BasicBlock* const enclosingHndEnd = regions.BottomRef(enclosingHndIndex).hndRegionEnd; + assert(enclosingHndEnd != nullptr); + + // If the enclosing region ends right before the nested region begins, + // extend the enclosing region's last block to the end of the nested region. + // + BasicBlock* const hndBeg = HBtab->HasFilter() ? HBtab->ebdFilter : HBtab->ebdHndBeg; + if (enclosingHndEnd->NextIs(hndBeg)) + { + regions.BottomRef(enclosingHndIndex).hndRegionEnd = hndEnd; + } + } + } +} + +//----------------------------------------------------------------------------- +// fgMoveColdBlocks: Move rarely-run blocks to the end of their respective regions. +// +// Notes: +// Exception handlers are assumed to be cold, so we won't move blocks within them. +// +void Compiler::fgMoveColdBlocks() +{ +#ifdef DEBUG + if (verbose) + { + printf("*************** In fgMoveColdBlocks()\n"); + + printf("\nInitial BasicBlocks"); + fgDispBasicBlocks(verboseTrees); + printf("\n"); + } +#endif // DEBUG + + auto moveColdMainBlocks = [this]() { + // Find the last block in the main body that isn't part of an EH region + // + BasicBlock* lastMainBB; + for (lastMainBB = this->fgLastBBInMainFunction(); lastMainBB != nullptr; lastMainBB = lastMainBB->Prev()) + { + if (!lastMainBB->hasTryIndex() && !lastMainBB->hasHndIndex()) + { + break; + } + } + + // Nothing to do if there are two or fewer non-EH blocks + // + if ((lastMainBB == nullptr) || lastMainBB->IsFirst() || lastMainBB->PrevIs(fgFirstBB)) + { + return; + } + + // Search the main method body for rarely-run blocks to move + // + BasicBlock* prev; + for (BasicBlock* block = lastMainBB->Prev(); block != fgFirstBB; block = prev) + { + prev = block->Prev(); + + // We only want to move cold blocks. + // Also, don't consider blocks in EH regions for now; only move blocks in the main method body. + // Finally, don't move block if it is the beginning of a call-finally pair, + // as we want to keep these pairs contiguous + // (if we encounter the end of a pair below, we'll move the whole pair). + // + if (!block->isRunRarely() || block->hasTryIndex() || block->hasHndIndex() || block->isBBCallFinallyPair()) + { + continue; + } + + this->fgUnlinkBlock(block); + this->fgInsertBBafter(lastMainBB, block); + + // If block is the end of a call-finally pair, prev is the beginning of the pair. + // Move prev to before block to keep the pair contiguous. + // + if (block->KindIs(BBJ_CALLFINALLYRET)) + { + BasicBlock* const callFinally = prev; + prev = prev->Prev(); + assert(callFinally->KindIs(BBJ_CALLFINALLY)); + assert(!callFinally->HasFlag(BBF_RETLESS_CALL)); + this->fgUnlinkBlock(callFinally); + this->fgInsertBBafter(lastMainBB, callFinally); + } + } + + // We have moved all cold main blocks before lastMainBB to after lastMainBB. + // If lastMainBB itself is cold, move it to the end of the method to restore its relative ordering. + // + if (lastMainBB->isRunRarely()) + { + BasicBlock* const newLastMainBB = this->fgLastBBInMainFunction(); + if (lastMainBB != newLastMainBB) + { + BasicBlock* const prev = lastMainBB->Prev(); + this->fgUnlinkBlock(lastMainBB); + this->fgInsertBBafter(newLastMainBB, lastMainBB); + + // Call-finally check + // + if (lastMainBB->KindIs(BBJ_CALLFINALLYRET)) + { + assert(prev->KindIs(BBJ_CALLFINALLY)); + assert(!prev->HasFlag(BBF_RETLESS_CALL)); + assert(prev != newLastMainBB); + this->fgUnlinkBlock(prev); + this->fgInsertBBafter(newLastMainBB, prev); + } + } + } + }; + + moveColdMainBlocks(); + + // No EH regions + // + if (compHndBBtabCount == 0) + { + return; + } + + // We assume exception handlers are cold, so we won't bother moving blocks within them. + // We will move blocks only within try regions. + // First, determine where each try region ends, without considering nested regions. + // We will use these end blocks as insertion points. + // + BasicBlock** const tryRegionEnds = new (this, CMK_Generic) BasicBlock* [compHndBBtabCount] {}; + + for (BasicBlock* const block : Blocks(fgFirstBB, fgLastBBInMainFunction())) + { + if (block->hasTryIndex()) + { + tryRegionEnds[block->getTryIndex()] = block; + } + } + + // Search all try regions in the main method body for cold blocks to move + // + BasicBlock* prev; + for (BasicBlock* block = fgLastBBInMainFunction(); block != fgFirstBB; block = prev) + { + prev = block->Prev(); + + // Only consider rarely-run blocks in try regions. + // If we have such a block that is also part of an exception handler, don't bother moving it. + // Finally, don't move block if it is the beginning of a call-finally pair, + // as we want to keep these pairs contiguous + // (if we encounter the end of a pair below, we'll move the whole pair). + // + if (!block->hasTryIndex() || !block->isRunRarely() || block->hasHndIndex() || block->isBBCallFinallyPair()) + { + continue; + } + + const unsigned tryIndex = block->getTryIndex(); + EHblkDsc* const HBtab = ehGetDsc(tryIndex); + + // Don't move the beginning of a try region. + // Also, if this try region's entry is cold, don't bother moving its blocks. + // + if ((HBtab->ebdTryBeg == block) || (HBtab->ebdTryBeg->isRunRarely())) + { + continue; + } + + BasicBlock* const insertionPoint = tryRegionEnds[tryIndex]; + assert(insertionPoint != nullptr); + + // Don't move the end of this try region + // + if (block == insertionPoint) + { + continue; + } + + fgUnlinkBlock(block); + fgInsertBBafter(insertionPoint, block); + + // Keep call-finally pairs contiguous + // + if (block->KindIs(BBJ_CALLFINALLYRET)) + { + BasicBlock* const callFinally = prev; + prev = prev->Prev(); + assert(callFinally->KindIs(BBJ_CALLFINALLY)); + assert(!callFinally->HasFlag(BBF_RETLESS_CALL)); + fgUnlinkBlock(callFinally); + fgInsertBBafter(insertionPoint, callFinally); + } + } + + // Before updating EH descriptors, find the new try region ends + // + for (unsigned XTnum = 0; XTnum < compHndBBtabCount; XTnum++) + { + BasicBlock* const tryEnd = tryRegionEnds[XTnum]; + + // This try region isn't in the main method body + // + if (tryEnd == nullptr) + { + continue; + } + + // If we moved cold blocks to the end of this try region, + // search for the new end block + // + BasicBlock* newTryEnd = tryEnd; + for (BasicBlock* const block : Blocks(tryEnd, fgLastBBInMainFunction())) + { + if (!BasicBlock::sameTryRegion(tryEnd, block)) + { + break; + } + + newTryEnd = block; + } + + // We moved cold blocks to the end of this try region, but the old end block is cold, too. + // Move the old end block to the end of the region to preserve its relative ordering. + // + if ((tryEnd != newTryEnd) && tryEnd->isRunRarely() && !tryEnd->hasHndIndex()) + { + BasicBlock* const prev = tryEnd->Prev(); + fgUnlinkBlock(tryEnd); + fgInsertBBafter(newTryEnd, tryEnd); + + // Keep call-finally pairs contiguous + // + if (tryEnd->KindIs(BBJ_CALLFINALLYRET)) + { + assert(prev->KindIs(BBJ_CALLFINALLY)); + assert(!prev->HasFlag(BBF_RETLESS_CALL)); + fgUnlinkBlock(prev); + fgInsertBBafter(newTryEnd, prev); + } + } + else + { + // Otherwise, just update the try region end + // + tryRegionEnds[XTnum] = newTryEnd; + } + } + + // Now, update EH descriptors + // + auto getTryLast = [tryRegionEnds](const unsigned index) -> BasicBlock* { + return tryRegionEnds[index]; + }; + + auto setTryLast = [tryRegionEnds](const unsigned index, BasicBlock* const block) { + tryRegionEnds[index] = block; + }; + + ehUpdateTryLasts(getTryLast, setTryLast); +} + +//------------------------------------------------------------- +// ehUpdateTryLasts: Iterates EH descriptors, updating each try region's +// end block as determined by getTryLast. +// +// Type parameters: +// GetTryLast - Functor type that takes an EH index, +// and returns the corresponding region's new try end block +// SetTryLast - Functor type that takes an EH index and a BasicBlock*, +// and updates some internal state tracking the new try end block of each EH region +// +// Parameters: +// getTryLast - Functor to get new try end block for an EH region +// setTryLast - Functor to update the new try end block for an EH region +// +template +void Compiler::ehUpdateTryLasts(GetTryLast getTryLast, SetTryLast setTryLast) +{ + unsigned XTnum = 0; + for (EHblkDsc* const HBtab : EHClauses(this)) + { + BasicBlock* const tryEnd = getTryLast(XTnum++); + + if (tryEnd == nullptr) + { + continue; + } + + // Update the end pointer of this try region to the new last block + // + HBtab->ebdTryLast = tryEnd; + const unsigned enclosingTryIndex = HBtab->ebdEnclosingTryIndex; + + // If this try region is nested in another one, we might need to update its enclosing region's end block + // + if (enclosingTryIndex != EHblkDsc::NO_ENCLOSING_INDEX) + { + BasicBlock* const enclosingTryEnd = getTryLast(enclosingTryIndex); + + // If multiple EH descriptors map to the same try region, + // then the enclosing region's last block might be null in the table, so set it here. + // Similarly, if the enclosing region ends right before the nested region begins, + // extend the enclosing region's last block to the end of the nested region. + // + if ((enclosingTryEnd == nullptr) || enclosingTryEnd->NextIs(HBtab->ebdTryBeg)) + { + setTryLast(enclosingTryIndex, tryEnd); + } + } + } +} + //------------------------------------------------------------- // fgUpdateFlowGraphPhase: run flow graph optimization as a // phase, with no tail duplication @@ -4910,9 +5389,9 @@ bool Compiler::fgUpdateFlowGraph(bool doTailDuplication /* = false */, bool isPh // if (fgIsUsingProfileWeights()) { - // if block and bdest are in different hot/cold regions we can't do this optimization + // if block and bDest are in different hot/cold regions we can't do this optimization // because we can't allow fall-through into the cold region. - if (!fgEdgeWeightsComputed || fgInDifferentRegions(block, bDest)) + if (fgInDifferentRegions(block, bDest)) { optimizeJump = false; } diff --git a/src/coreclr/jit/fgprofile.cpp b/src/coreclr/jit/fgprofile.cpp index 9fa4e7273862..4fcf748416d7 100644 --- a/src/coreclr/jit/fgprofile.cpp +++ b/src/coreclr/jit/fgprofile.cpp @@ -18,26 +18,15 @@ // true if so // // Note: -// This now returns true for inlinees. We might consider preserving the -// old behavior for crossgen, since crossgen BBINSTRs still do inlining -// and don't instrument the inlinees. +// In most cases it is more appropriate to call fgHaveProfileWeights, +// since that tells you if blocks have profile-based weights. // -// Thus if BBINSTR and BBOPT do the same inlines (which can happen) -// profile data for an inlinee (if available) will not fully reflect -// the behavior of the inlinee when called from this method. +// This method literally checks if the runtime had a profile schema, +// from which we can derive weights. // -// If this inlinee was not inlined by the BBINSTR run then the -// profile data for the inlinee will reflect this method's influence. -// -// * for ALWAYS_INLINE and FORCE_INLINE cases it is unlikely we'll find -// any profile data, as BBINSTR and BBOPT callers will both inline; -// only indirect callers will invoke the instrumented version to run. -// * for DISCRETIONARY_INLINE cases we may or may not find relevant -// data, depending, but chances are the data is relevant. -// -// TieredPGO data comes from Tier0 methods, which currently do not do -// any inlining; thus inlinee profile data should be available and -// representative. +// Schema-based data comes from Tier0 methods, which currently do not do +// any inlining; thus inlinee profile data should be available and +// representative. // bool Compiler::fgHaveProfileData() { @@ -47,6 +36,9 @@ bool Compiler::fgHaveProfileData() //------------------------------------------------------------------------ // fgHaveProfileWeights: Check if we have a profile that has weights. // +// Notes: +// These weights may come from instrumentation or from synthesis. +// bool Compiler::fgHaveProfileWeights() { return fgPgoHaveWeights; @@ -149,22 +141,39 @@ void Compiler::fgApplyProfileScale() JITDUMP(" ... no callee profile data, will use non-pgo weight to scale\n"); } - // Ostensibly this should be fgCalledCount for the callee, but that's not available - // as it requires some analysis. + // Determine the weight of the first block preds, if any. + // (only happens if the first block is a loop head). // - // For most callees it will be the same as the entry block count. - // - // Note when/if we early do normalization this may need to change. + weight_t firstBlockPredWeight = 0; + for (FlowEdge* const firstBlockPred : fgFirstBB->PredEdges()) + { + firstBlockPredWeight += firstBlockPred->getLikelyWeight(); + } + + // Determine the "input" weight for the callee // weight_t calleeWeight = fgFirstBB->bbWeight; - // Callee entry weight is nonzero? + // Callee entry weight is zero or negative (taking backedges into account)? // If so, just choose the smallest plausible weight. // - if (calleeWeight == BB_ZERO_WEIGHT) + if (calleeWeight <= firstBlockPredWeight) { calleeWeight = fgHaveProfileWeights() ? 1.0 : BB_UNITY_WEIGHT; - JITDUMP(" ... callee entry has weight zero, will use weight of " FMT_WT " to scale\n", calleeWeight); + JITDUMP(" ... callee entry has zero or negative weight, will use weight of " FMT_WT " to scale\n", + calleeWeight); + JITDUMP("Profile data could not be scaled consistently. Data %s inconsistent.\n", + fgPgoConsistent ? "is now" : "was already"); + + if (fgPgoConsistent) + { + Metrics.ProfileInconsistentInlineeScale++; + fgPgoConsistent = false; + } + } + else + { + calleeWeight -= firstBlockPredWeight; } // Call site has profile weight? @@ -1689,16 +1698,42 @@ void EfficientEdgeCountInstrumentor::RelocateProbes() { BasicBlock* intermediary = m_comp->fgNewBBbefore(BBJ_ALWAYS, block, /* extendRegion */ true); intermediary->SetFlags(BBF_IMPORTED); - intermediary->inheritWeight(block); FlowEdge* const newEdge = m_comp->fgAddRefPred(block, intermediary); intermediary->SetTargetEdge(newEdge); NewRelocatedProbe(intermediary, probe->source, probe->target, &leader); SetModifiedFlow(); + // Redirect flow and figure out profile impact. + // + // We don't expect to see mixtures of profiled and unprofiled preds, + // but if we do, fall back to our old default behavior. + // + weight_t weight = 0; + bool allPredsHaveProfile = true; + while (criticalPreds.Height() > 0) { BasicBlock* const pred = criticalPreds.Pop(); m_comp->fgReplaceJumpTarget(pred, block, intermediary); + + if (pred->hasProfileWeight()) + { + FlowEdge* const predIntermediaryEdge = m_comp->fgGetPredForBlock(intermediary, pred); + weight += predIntermediaryEdge->getLikelyWeight(); + } + else + { + allPredsHaveProfile = false; + } + } + + if (allPredsHaveProfile) + { + intermediary->setBBProfileWeight(weight); + } + else + { + intermediary->inheritWeight(block); } } } @@ -2817,11 +2852,19 @@ PhaseStatus Compiler::fgIncorporateProfileData() { JITDUMP("JitStress -- incorporating random profile data\n"); fgIncorporateBlockCounts(); - fgApplyProfileScale(); ProfileSynthesis::Run(this, ProfileSynthesisOption::RepairLikelihoods); + fgApplyProfileScale(); return PhaseStatus::MODIFIED_EVERYTHING; } + // For now we only rely on profile data when optimizing. + // + if (!opts.OptimizationEnabled()) + { + JITDUMP("not optimizing, so not incorporating any profile data\n"); + return PhaseStatus::MODIFIED_NOTHING; + } + #ifdef DEBUG // Optionally run synthesis // @@ -2831,6 +2874,7 @@ PhaseStatus Compiler::fgIncorporateProfileData() { JITDUMP("Synthesizing profile data\n"); ProfileSynthesis::Run(this, ProfileSynthesisOption::AssignLikelihoods); + fgApplyProfileScale(); return PhaseStatus::MODIFIED_EVERYTHING; } } @@ -2842,6 +2886,7 @@ PhaseStatus Compiler::fgIncorporateProfileData() { JITDUMP("Synthesizing profile data and writing it out as the actual profile data\n"); ProfileSynthesis::Run(this, ProfileSynthesisOption::AssignLikelihoods); + fgApplyProfileScale(); return PhaseStatus::MODIFIED_EVERYTHING; } #endif @@ -2861,6 +2906,14 @@ PhaseStatus Compiler::fgIncorporateProfileData() JITDUMP("BBOPT not set\n"); } + // Is dynamic PGO active? If so, run synthesis. + // + if (fgPgoDynamic) + { + JITDUMP("Dynamic PGO active, synthesizing profile data\n"); + ProfileSynthesis::Run(this, ProfileSynthesisOption::AssignLikelihoods); + } + // Scale the "synthetic" block weights. // fgApplyProfileScale(); @@ -2951,28 +3004,23 @@ PhaseStatus Compiler::fgIncorporateProfileData() { // If for some reason we have both block and edge counts, prefer the edge counts. // - bool dataIsGood = false; - if (haveEdgeCounts) { - dataIsGood = fgIncorporateEdgeCounts(); + fgIncorporateEdgeCounts(); } else if (haveBlockCounts) { - dataIsGood = fgIncorporateBlockCounts(); + fgIncorporateBlockCounts(); } - // If profile incorporation hit fixable problems, run synthesis in blend mode. + // We now always run repair, to get consistent initial counts // - if (fgPgoHaveWeights && !dataIsGood) - { - JITDUMP("\nIncorporated count data had inconsistencies; repairing profile...\n"); - ProfileSynthesis::Run(this, ProfileSynthesisOption::RepairLikelihoods); - } + JITDUMP("\n%sRepairing profile...\n", opts.IsOSR() ? "blending" : "repairing"); + ProfileSynthesis::Run(this, ProfileSynthesisOption::RepairLikelihoods); } #ifdef DEBUG - // Optionally synthesize & blend + // Optionally blend and recompute counts. // if (JitConfig.JitSynthesizeCounts() == 3) { @@ -2997,21 +3045,10 @@ PhaseStatus Compiler::fgIncorporateProfileData() // // Notes: // Does inlinee scaling. -// Handles handler entry special case. // void Compiler::fgSetProfileWeight(BasicBlock* block, weight_t profileWeight) { block->setBBProfileWeight(profileWeight); - -#if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION - // Handle a special case -- some handler entries can't have zero profile count. - // - if (this->bbIsHandlerBeg(block) && block->isRunRarely()) - { - JITDUMP("Suppressing zero count for " FMT_BB " as it is a handler entry\n", block->bbNum); - block->makeBlockHot(); - } -#endif } //------------------------------------------------------------------------ @@ -4262,265 +4299,17 @@ bool Compiler::fgIncorporateEdgeCounts() return e.IsGood(); } -//------------------------------------------------------------------------ -// setEdgeWeightMinChecked: possibly update minimum edge weight -// -// Arguments: -// newWeight - proposed new weight -// bDst - destination block for edge -// slop - profile slush fund -// wbUsedSlop [out] - true if we tapped into the slush fund -// -// Returns: -// true if the edge weight was adjusted -// false if the edge weight update was inconsistent with the -// edge's current [min,max} -// -bool FlowEdge::setEdgeWeightMinChecked(weight_t newWeight, BasicBlock* bDst, weight_t slop, bool* wbUsedSlop) -{ - // Negative weights are nonsensical. - // - // If we can't cover the deficit with slop, fail. - // If we can, set the new weight to zero. - // - bool usedSlop = false; - - if (newWeight < BB_ZERO_WEIGHT) - { - if ((newWeight + slop) < BB_ZERO_WEIGHT) - { - return false; - } - - newWeight = BB_ZERO_WEIGHT; - usedSlop = true; - } - - bool result = false; - - if ((newWeight <= m_edgeWeightMax) && (newWeight >= m_edgeWeightMin)) - { - m_edgeWeightMin = newWeight; - result = true; - } - else if (slop > 0) - { - // We allow for a small amount of inaccuracy in block weight counts. - if (m_edgeWeightMax < newWeight) - { - // We have already determined that this edge's weight - // is less than newWeight, so we just allow for the slop - if (newWeight <= (m_edgeWeightMax + slop)) - { - result = true; - usedSlop = true; - - if (m_edgeWeightMax != BB_ZERO_WEIGHT) - { - // We will raise m_edgeWeightMin and Max towards newWeight - m_edgeWeightMin = m_edgeWeightMax; - m_edgeWeightMax = newWeight; - } - } - } - else if (m_edgeWeightMin > newWeight) - { - // We have already determined that this edge's weight - // is more than newWeight, so we just allow for the slop - if ((newWeight + slop) >= m_edgeWeightMin) - { - result = true; - usedSlop = true; - - if (m_edgeWeightMax != BB_ZERO_WEIGHT) - { - // We will lower m_edgeWeightMin towards newWeight - // But not below zero. - // - m_edgeWeightMin = max(BB_ZERO_WEIGHT, newWeight); - } - } - } - - // If we are returning true then we should have adjusted the range so that - // the newWeight is in new range [Min..Max] or fgEdgeWeightMax is zero. - // - if (result) - { - assert((m_edgeWeightMax == BB_ZERO_WEIGHT) || - ((newWeight <= m_edgeWeightMax) && (newWeight >= m_edgeWeightMin))); - } - } - - if (result && usedSlop && (wbUsedSlop != nullptr)) - { - *wbUsedSlop = true; - } - -#if DEBUG - if (result) - { - JITDUMP("Updated min weight of " FMT_BB " -> " FMT_BB " to [" FMT_WT ".." FMT_WT "]\n", getSourceBlock()->bbNum, - bDst->bbNum, m_edgeWeightMin, m_edgeWeightMax); - } - else - { - JITDUMP("Not adjusting min weight of " FMT_BB " -> " FMT_BB "; new value " FMT_WT " not in range [" FMT_WT - ".." FMT_WT "] (+/- " FMT_WT ")\n", - getSourceBlock()->bbNum, bDst->bbNum, newWeight, m_edgeWeightMin, m_edgeWeightMax, slop); - result = false; // break here - } -#endif // DEBUG - - return result; -} - -//------------------------------------------------------------------------ -// setEdgeWeightMaxChecked: possibly update maximum edge weight -// -// Arguments: -// newWeight - proposed new weight -// bDst - destination block for edge -// slop - profile slush fund -// wbUsedSlop [out] - true if we tapped into the slush fund -// -// Returns: -// true if the edge weight was adjusted -// false if the edge weight update was inconsistent with the -// edge's current [min,max} -// -bool FlowEdge::setEdgeWeightMaxChecked(weight_t newWeight, BasicBlock* bDst, weight_t slop, bool* wbUsedSlop) -{ - // Negative weights are nonsensical. - // - // If we can't cover the deficit with slop, fail. - // If we can, set the new weight to zero. - // - bool usedSlop = false; - - if (newWeight < BB_ZERO_WEIGHT) - { - if ((newWeight + slop) < BB_ZERO_WEIGHT) - { - return false; - } - - newWeight = BB_ZERO_WEIGHT; - usedSlop = true; - } - - bool result = false; - - if ((newWeight >= m_edgeWeightMin) && (newWeight <= m_edgeWeightMax)) - { - m_edgeWeightMax = newWeight; - result = true; - } - else if (slop > 0) - { - // We allow for a small amount of inaccuracy in block weight counts. - if (m_edgeWeightMax < newWeight) - { - // We have already determined that this edge's weight - // is less than newWeight, so we just allow for the slop - if (newWeight <= (m_edgeWeightMax + slop)) - { - result = true; - usedSlop = true; - - if (m_edgeWeightMax != BB_ZERO_WEIGHT) - { - // We will allow this to raise m_edgeWeightMax towards newWeight - m_edgeWeightMax = newWeight; - } - } - } - else if (m_edgeWeightMin > newWeight) - { - // We have already determined that this edge's weight - // is more than newWeight, so we just allow for the slop - if ((newWeight + slop) >= m_edgeWeightMin) - { - result = true; - usedSlop = true; - - if (m_edgeWeightMax != BB_ZERO_WEIGHT) - { - // We will allow this to lower m_edgeWeightMin and Max towards newWeight - m_edgeWeightMax = m_edgeWeightMin; - m_edgeWeightMin = newWeight; - } - } - } - - // If we are returning true then we should have adjusted the range so that - // the newWeight is in new range [Min..Max] or fgEdgeWeightMax is zero - if (result) - { - assert((m_edgeWeightMax == BB_ZERO_WEIGHT) || - ((newWeight <= m_edgeWeightMax) && (newWeight >= m_edgeWeightMin))); - } - } - - if (result && usedSlop && (wbUsedSlop != nullptr)) - { - *wbUsedSlop = true; - } - -#if DEBUG - if (result) - { - JITDUMP("Updated max weight of " FMT_BB " -> " FMT_BB " to [" FMT_WT ".." FMT_WT "]\n", getSourceBlock()->bbNum, - bDst->bbNum, m_edgeWeightMin, m_edgeWeightMax); - } - else - { - JITDUMP("Not adjusting max weight of " FMT_BB " -> " FMT_BB "; new value " FMT_WT " not in range [" FMT_WT - ".." FMT_WT "] (+/- " FMT_WT ")\n", - getSourceBlock()->bbNum, bDst->bbNum, newWeight, m_edgeWeightMin, m_edgeWeightMax, slop); - result = false; // break here - } -#endif // DEBUG - - return result; -} - -//------------------------------------------------------------------------ -// setEdgeWeights: Sets the minimum lower (m_edgeWeightMin) value -// and the maximum upper (m_edgeWeightMax) value -// Asserts that the max value is greater or equal to the min value -// -// Arguments: -// theMinWeight - the new minimum lower (m_edgeWeightMin) -// theMaxWeight - the new maximum upper (m_edgeWeightMin) -// bDst - the destination block for the edge -// -void FlowEdge::setEdgeWeights(weight_t theMinWeight, weight_t theMaxWeight, BasicBlock* bDst) -{ - assert(theMinWeight <= theMaxWeight); - assert(theMinWeight >= 0.0); - assert(theMaxWeight >= 0.0); - - JITDUMP("Setting edge weights for " FMT_BB " -> " FMT_BB " to [" FMT_WT " .. " FMT_WT "]\n", - getSourceBlock()->bbNum, bDst->bbNum, theMinWeight, theMaxWeight); - - m_edgeWeightMin = theMinWeight; - m_edgeWeightMax = theMaxWeight; -} - //------------------------------------------------------------- -// fgComputeBlockAndEdgeWeights: determine weights for blocks -// and optionally for edges +// fgComputeBlockWeights: determine weights for blocks // // Returns: // Suitable phase status // -PhaseStatus Compiler::fgComputeBlockAndEdgeWeights() +PhaseStatus Compiler::fgComputeBlockWeights() { const bool usingProfileWeights = fgIsUsingProfileWeights(); bool madeChanges = false; fgModified = false; - fgHaveValidEdgeWeights = false; fgCalledCount = BB_UNITY_WEIGHT; #if DEBUG @@ -4544,13 +4333,6 @@ PhaseStatus Compiler::fgComputeBlockAndEdgeWeights() JITDUMP(" -- no profile data, so using default called count\n"); } - PhaseStatus edgeStatus = fgComputeEdgeWeights(); - - if (edgeStatus != PhaseStatus::MODIFIED_NOTHING) - { - return edgeStatus; - } - return madeChanges ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING; } @@ -4790,405 +4572,6 @@ bool Compiler::fgComputeCalledCount(weight_t returnWeight) return madeChanges; } -//------------------------------------------------------------- -// fgComputeEdgeWeights: compute edge weights from block weights -// -// Returns: -// Suitable phase status -// -PhaseStatus Compiler::fgComputeEdgeWeights() -{ - const bool isOptimizing = opts.OptimizationEnabled(); - const bool usingProfileWeights = fgIsUsingProfileWeights(); - - if (!isOptimizing || !usingProfileWeights) - { - JITDUMP(" -- not optimizing or no profile data, so not computing edge weights\n"); - return PhaseStatus::MODIFIED_NOTHING; - } - - BasicBlock* bSrc; - BasicBlock* bDst; - weight_t slop; - unsigned goodEdgeCountCurrent = 0; - unsigned goodEdgeCountPrevious = 0; - bool inconsistentProfileData = false; - bool hasIncompleteEdgeWeights = false; - bool usedSlop = false; - unsigned numEdges = 0; - unsigned iterations = 0; - - JITDUMP("Initial weight assignments\n\n"); - - // Now we will compute the initial m_edgeWeightMin and m_edgeWeightMax values - for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->Next()) - { - weight_t bDstWeight = bDst->bbWeight; - - // We subtract out the called count so that bDstWeight is - // the sum of all edges that go into this block from this method. - // - if (bDst == fgFirstBB) - { - bDstWeight -= fgCalledCount; - } - - for (FlowEdge* const edge : bDst->PredEdges()) - { - bool assignOK = true; - - bSrc = edge->getSourceBlock(); - // We are processing the control flow edge (bSrc -> bDst) - - numEdges++; - - // - // If the bSrc or bDst blocks do not have exact profile weights - // then we must reset any values that they currently have - // - - if (!bSrc->hasProfileWeight() || !bDst->hasProfileWeight()) - { - edge->setEdgeWeights(BB_ZERO_WEIGHT, BB_MAX_WEIGHT, bDst); - } - - slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1; - switch (bSrc->GetKind()) - { - case BBJ_ALWAYS: - case BBJ_EHCATCHRET: - case BBJ_CALLFINALLY: - case BBJ_CALLFINALLYRET: - // We know the exact edge weight - assignOK &= edge->setEdgeWeightMinChecked(bSrc->bbWeight, bDst, slop, &usedSlop); - assignOK &= edge->setEdgeWeightMaxChecked(bSrc->bbWeight, bDst, slop, &usedSlop); - break; - - case BBJ_COND: - case BBJ_SWITCH: - case BBJ_EHFINALLYRET: - case BBJ_EHFAULTRET: - case BBJ_EHFILTERRET: - if (edge->edgeWeightMax() > bSrc->bbWeight) - { - // The maximum edge weight to block can't be greater than the weight of bSrc - assignOK &= edge->setEdgeWeightMaxChecked(bSrc->bbWeight, bDst, slop, &usedSlop); - } - break; - - default: - // We should never have an edge that starts from one of these jump kinds - noway_assert(!"Unexpected bbKind"); - break; - } - - // The maximum edge weight to block can't be greater than the weight of bDst - if (edge->edgeWeightMax() > bDstWeight) - { - assignOK &= edge->setEdgeWeightMaxChecked(bDstWeight, bDst, slop, &usedSlop); - } - - if (!assignOK) - { - // Here we have inconsistent profile data - inconsistentProfileData = true; - // No point in continuing - goto EARLY_EXIT; - } - } - } - - fgEdgeCount = numEdges; - - iterations = 0; - - do - { - JITDUMP("\nSolver pass %u\n", iterations); - - iterations++; - goodEdgeCountPrevious = goodEdgeCountCurrent; - goodEdgeCountCurrent = 0; - hasIncompleteEdgeWeights = false; - - JITDUMP("\n -- step 1 --\n"); - for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->Next()) - { - for (FlowEdge* const edge : bDst->PredEdges()) - { - bool assignOK = true; - - // We are processing the control flow edge (bSrc -> bDst) - bSrc = edge->getSourceBlock(); - - slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1; - if (bSrc->KindIs(BBJ_COND)) - { - weight_t diff; - FlowEdge* otherEdge; - BasicBlock* otherDst; - if (bSrc->FalseTargetIs(bDst)) - { - otherEdge = bSrc->GetTrueEdge(); - } - else - { - otherEdge = bSrc->GetFalseEdge(); - } - otherDst = otherEdge->getDestinationBlock(); - - // If we see min/max violations, just give up on the computations - // - const bool edgeWeightSensible = edge->edgeWeightMin() <= edge->edgeWeightMax(); - const bool otherEdgeWeightSensible = otherEdge->edgeWeightMin() <= otherEdge->edgeWeightMax(); - - assignOK &= edgeWeightSensible && otherEdgeWeightSensible; - - if (assignOK) - { - // Adjust edge->m_edgeWeightMin up or adjust otherEdge->m_edgeWeightMax down - diff = bSrc->bbWeight - (edge->edgeWeightMin() + otherEdge->edgeWeightMax()); - if (diff > 0) - { - assignOK &= - edge->setEdgeWeightMinChecked(edge->edgeWeightMin() + diff, bDst, slop, &usedSlop); - } - else if (diff < 0) - { - assignOK &= otherEdge->setEdgeWeightMaxChecked(otherEdge->edgeWeightMax() + diff, otherDst, - slop, &usedSlop); - } - - // Adjust otherEdge->m_edgeWeightMin up or adjust edge->m_edgeWeightMax down - diff = bSrc->bbWeight - (otherEdge->edgeWeightMin() + edge->edgeWeightMax()); - if (diff > 0) - { - assignOK &= otherEdge->setEdgeWeightMinChecked(otherEdge->edgeWeightMin() + diff, otherDst, - slop, &usedSlop); - } - else if (diff < 0) - { - assignOK &= - edge->setEdgeWeightMaxChecked(edge->edgeWeightMax() + diff, bDst, slop, &usedSlop); - } - } - - if (!assignOK) - { - // Here we have inconsistent profile data - inconsistentProfileData = true; - // No point in continuing - goto EARLY_EXIT; - } -#ifdef DEBUG - // Now edge->m_edgeWeightMin and otherEdge->m_edgeWeightMax) should add up to bSrc->bbWeight - diff = bSrc->bbWeight - (edge->edgeWeightMin() + otherEdge->edgeWeightMax()); - - if (!((-slop) <= diff) && (diff <= slop)) - { - JITDUMP("Edge weight discrepancy: " FMT_BB "[" FMT_WT "] -> {" FMT_BB "[min:" FMT_WT - "], " FMT_BB "[max: " FMT_WT "]} diff " FMT_WT " exceeds slop " FMT_WT "\n", - bSrc->bbNum, bSrc->bbWeight, bDst->bbNum, edge->edgeWeightMin(), otherDst->bbNum, - otherEdge->edgeWeightMax(), diff, slop); - } - - // Now otherEdge->m_edgeWeightMin and edge->m_edgeWeightMax) should add up to bSrc->bbWeight - diff = bSrc->bbWeight - (otherEdge->edgeWeightMin() + edge->edgeWeightMax()); - if (!((-slop) <= diff) && (diff <= slop)) - { - JITDUMP("Edge weight discrepancy: " FMT_BB "[" FMT_WT "] -> {" FMT_BB "[max:" FMT_WT - "], " FMT_BB "[min: " FMT_WT "]} diff " FMT_WT " exceeds slop " FMT_WT "\n", - bSrc->bbNum, bSrc->bbWeight, bDst->bbNum, edge->edgeWeightMax(), otherDst->bbNum, - otherEdge->edgeWeightMin(), diff, slop); - } -#endif // DEBUG - } - } - } - - JITDUMP("\n -- step 2 --\n"); - - for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->Next()) - { - weight_t bDstWeight = bDst->bbWeight; - - if (bDstWeight == BB_MAX_WEIGHT) - { - inconsistentProfileData = true; - // No point in continuing - goto EARLY_EXIT; - } - else - { - // We subtract out the called count so that bDstWeight is - // the sum of all edges that go into this block from this method. - // - if (bDst == fgFirstBB) - { - bDstWeight -= fgCalledCount; - } - - weight_t minEdgeWeightSum = 0; - weight_t maxEdgeWeightSum = 0; - - // Calculate the sums of the minimum and maximum edge weights - for (FlowEdge* const edge : bDst->PredEdges()) - { - maxEdgeWeightSum += edge->edgeWeightMax(); - minEdgeWeightSum += edge->edgeWeightMin(); - } - - // maxEdgeWeightSum is the sum of all m_edgeWeightMax values into bDst - // minEdgeWeightSum is the sum of all m_edgeWeightMin values into bDst - - for (FlowEdge* const edge : bDst->PredEdges()) - { - bool assignOK = true; - - // We are processing the control flow edge (bSrc -> bDst) - bSrc = edge->getSourceBlock(); - slop = BasicBlock::GetSlopFraction(bSrc, bDst) + 1; - - // otherMaxEdgesWeightSum is the sum of all of the other edges m_edgeWeightMax values - // This can be used to compute a lower bound for our minimum edge weight - // - weight_t const otherMaxEdgesWeightSum = maxEdgeWeightSum - edge->edgeWeightMax(); - - if (otherMaxEdgesWeightSum >= BB_ZERO_WEIGHT) - { - if (bDstWeight >= otherMaxEdgesWeightSum) - { - // minWeightCalc is our minWeight when every other path to bDst takes it's m_edgeWeightMax - // value - weight_t minWeightCalc = (weight_t)(bDstWeight - otherMaxEdgesWeightSum); - if (minWeightCalc > edge->edgeWeightMin()) - { - assignOK &= edge->setEdgeWeightMinChecked(minWeightCalc, bDst, slop, &usedSlop); - } - } - } - - // otherMinEdgesWeightSum is the sum of all of the other edges m_edgeWeightMin values - // This can be used to compute an upper bound for our maximum edge weight - // - weight_t const otherMinEdgesWeightSum = minEdgeWeightSum - edge->edgeWeightMin(); - - if (otherMinEdgesWeightSum >= BB_ZERO_WEIGHT) - { - if (bDstWeight >= otherMinEdgesWeightSum) - { - // maxWeightCalc is our maxWeight when every other path to bDst takes it's m_edgeWeightMin - // value - weight_t maxWeightCalc = (weight_t)(bDstWeight - otherMinEdgesWeightSum); - if (maxWeightCalc < edge->edgeWeightMax()) - { - assignOK &= edge->setEdgeWeightMaxChecked(maxWeightCalc, bDst, slop, &usedSlop); - } - } - } - - if (!assignOK) - { - // Here we have inconsistent profile data - JITDUMP("Inconsistent profile data at " FMT_BB " -> " FMT_BB ": dest weight " FMT_WT - ", min/max into dest is " FMT_WT "/" FMT_WT ", edge " FMT_WT "/" FMT_WT "\n", - bSrc->bbNum, bDst->bbNum, bDstWeight, minEdgeWeightSum, maxEdgeWeightSum, - edge->edgeWeightMin(), edge->edgeWeightMax()); - - inconsistentProfileData = true; - // No point in continuing - goto EARLY_EXIT; - } - - // When m_edgeWeightMin equals m_edgeWeightMax we have a "good" edge weight - if (edge->edgeWeightMin() == edge->edgeWeightMax()) - { - // Count how many "good" edge weights we have - // Each time through we should have more "good" weights - // We exit the while loop when no longer find any new "good" edges - goodEdgeCountCurrent++; - } - else - { - // Remember that we have seen at least one "Bad" edge weight - // so that we will repeat the while loop again - hasIncompleteEdgeWeights = true; - } - } - } - } - - assert(!inconsistentProfileData); // Should use EARLY_EXIT when it is false. - - if (numEdges == goodEdgeCountCurrent) - { - noway_assert(hasIncompleteEdgeWeights == false); - break; - } - - } while (hasIncompleteEdgeWeights && (goodEdgeCountCurrent > goodEdgeCountPrevious) && (iterations < 8)); - -EARLY_EXIT:; - -#ifdef DEBUG - if (verbose) - { - if (inconsistentProfileData) - { - printf("fgComputeEdgeWeights() found inconsistent profile data, not using the edge weights\n"); - } - else - { - if (hasIncompleteEdgeWeights) - { - printf("fgComputeEdgeWeights() was able to compute exact edge weights for %3d of the %3d edges, using " - "%d passes.\n", - goodEdgeCountCurrent, numEdges, iterations); - } - else - { - printf("fgComputeEdgeWeights() was able to compute exact edge weights for all of the %3d edges, using " - "%d passes.\n", - numEdges, iterations); - } - - fgPrintEdgeWeights(); - } - } -#endif // DEBUG - - fgSlopUsedInEdgeWeights = usedSlop; - fgRangeUsedInEdgeWeights = false; - - // See if any edge weight are expressed in [min..max] form - - for (BasicBlock* const bDst : Blocks()) - { - if (bDst->bbPreds != nullptr) - { - for (FlowEdge* const edge : bDst->PredEdges()) - { - // This is the control flow edge (edge->getBlock() -> bDst) - - if (edge->edgeWeightMin() != edge->edgeWeightMax()) - { - fgRangeUsedInEdgeWeights = true; - break; - } - } - if (fgRangeUsedInEdgeWeights) - { - break; - } - } - } - - fgHaveValidEdgeWeights = !inconsistentProfileData; - fgEdgeWeightsComputed = true; - - return PhaseStatus::MODIFIED_EVERYTHING; -} - //------------------------------------------------------------------------ // fgProfileWeightsEqual: check if two profile weights are equal // (or nearly so) @@ -5227,29 +4610,68 @@ bool Compiler::fgProfileWeightsConsistent(weight_t weight1, weight_t weight2) return fgProfileWeightsEqual(relativeDiff, BB_ZERO_WEIGHT); } +//------------------------------------------------------------------------ +// fgProfileWeightsConsistentOrSmall: check if two profile weights are within +// some small percentage of one another, or are both less than some epsilon. +// +// Arguments: +// weight1 -- first weight +// weight2 -- second weight +// epsilon -- small weight threshold +// +bool Compiler::fgProfileWeightsConsistentOrSmall(weight_t weight1, weight_t weight2, weight_t epsilon) +{ + if (weight2 == BB_ZERO_WEIGHT) + { + return fgProfileWeightsEqual(weight1, weight2, epsilon); + } + + weight_t const delta = fabs(weight2 - weight1); + + if (delta <= epsilon) + { + return true; + } + + weight_t const relativeDelta = delta / weight2; + + return fgProfileWeightsEqual(relativeDelta, BB_ZERO_WEIGHT); +} + #ifdef DEBUG //------------------------------------------------------------------------ -// fgDebugCheckProfileWeights: verify profile weights are self-consistent +// fgDebugCheckProfile: verify profile data on flow graph is self-consistent // (or nearly so) // +// Arguments: +// checks -- [optional] phase checks in force +// // Notes: -// By default, just checks for each flow edge having likelihood. +// Will check full profile or just likelihoods, depending on the phase check arg. +// // Can be altered via external config. // -void Compiler::fgDebugCheckProfileWeights() +void Compiler::fgDebugCheckProfile(PhaseChecks checks) { const bool configEnabled = (JitConfig.JitProfileChecks() >= 0) && fgHaveProfileWeights() && fgPredsComputed; + assert(checks != PhaseChecks::CHECK_NONE); + if (configEnabled) { fgDebugCheckProfileWeights((ProfileChecks)JitConfig.JitProfileChecks()); } - else + else if (hasFlag(checks, PhaseChecks::CHECK_PROFILE)) { - ProfileChecks checks = + ProfileChecks profileChecks = ProfileChecks::CHECK_LIKELY | ProfileChecks::RAISE_ASSERT; + fgDebugCheckProfileWeights(profileChecks); + } + else if (hasFlag(checks, PhaseChecks::CHECK_LIKELIHOODS)) + { + ProfileChecks profileChecks = ProfileChecks::CHECK_HASLIKELIHOOD | ProfileChecks::CHECK_LIKELIHOODSUM | ProfileChecks::RAISE_ASSERT; - fgDebugCheckProfileWeights(checks); + fgDebugCheckProfileWeights(profileChecks); } } @@ -5280,25 +4702,34 @@ bool Compiler::fgDebugCheckProfileWeights(ProfileChecks checks) // and/or // new likelihood based weights. // - const bool verifyClassicWeights = fgEdgeWeightsComputed && hasFlag(checks, ProfileChecks::CHECK_CLASSIC); - const bool verifyLikelyWeights = hasFlag(checks, ProfileChecks::CHECK_LIKELY); - const bool verifyHasLikelihood = hasFlag(checks, ProfileChecks::CHECK_HASLIKELIHOOD); - const bool verifyLikelihoodSum = hasFlag(checks, ProfileChecks::CHECK_LIKELIHOODSUM); - const bool assertOnFailure = hasFlag(checks, ProfileChecks::RAISE_ASSERT); - const bool checkAllBlocks = hasFlag(checks, ProfileChecks::CHECK_ALL_BLOCKS); + const bool verifyLikelyWeights = hasFlag(checks, ProfileChecks::CHECK_LIKELY); + const bool verifyHasLikelihood = hasFlag(checks, ProfileChecks::CHECK_HASLIKELIHOOD); + const bool verifyLikelihoodSum = hasFlag(checks, ProfileChecks::CHECK_LIKELIHOODSUM); + const bool assertOnFailure = hasFlag(checks, ProfileChecks::RAISE_ASSERT) && fgPgoConsistent; + const bool checkAllBlocks = hasFlag(checks, ProfileChecks::CHECK_ALL_BLOCKS); - if (!(verifyClassicWeights || verifyLikelyWeights || verifyHasLikelihood)) + if (!verifyLikelyWeights && !verifyHasLikelihood) { JITDUMP("[profile weight checks disabled]\n"); return true; } + if (fgPgoDeferredInconsistency) + { + // We have a deferred consistency check failure. Just return w/o checking further + // We will assert later once we see the method has valid IL. + // + JITDUMP("[deferred prior check failed -- skipping this check]\n"); + return false; + } + JITDUMP("Checking Profile Weights (flags:0x%x)\n", checks); unsigned problemBlocks = 0; unsigned unprofiledBlocks = 0; unsigned profiledBlocks = 0; bool entryProfiled = false; bool exitProfiled = false; + bool hasTry = false; weight_t entryWeight = 0; weight_t exitWeight = 0; @@ -5316,6 +4747,15 @@ bool Compiler::fgDebugCheckProfileWeights(ProfileChecks checks) // profiledBlocks++; + // If there is a try region in the method, we won't be able + // to reliably verify entry/exit counts. + // + // Technically this checking will fail only if there's a try that + // must be exited via exception, but that's not worth checking for, + // either here or in the solver. + // + hasTry |= block->hasTryIndex(); + // Currently using raw counts. Consider using normalized counts instead? // weight_t blockWeight = block->bbWeight; @@ -5342,13 +4782,26 @@ bool Compiler::fgDebugCheckProfileWeights(ProfileChecks checks) // Exit blocks // - if (block->KindIs(BBJ_RETURN, BBJ_THROW)) + if (block->KindIs(BBJ_RETURN)) + { + exitWeight += blockWeight; + exitProfiled = true; + verifyOutgoing = false; + } + else if (block->KindIs(BBJ_THROW)) { - if (BasicBlock::sameHndRegion(block, fgFirstBB)) + bool const isCatchableThrow = block->hasTryIndex(); + + if (isCatchableThrow) + { + assert(hasTry); + } + else { exitWeight += blockWeight; - exitProfiled = !opts.IsOSR(); + exitProfiled = true; } + verifyOutgoing = false; } @@ -5362,6 +4815,19 @@ bool Compiler::fgDebugCheckProfileWeights(ProfileChecks checks) verifyIncoming = false; } + // Original entries in OSR methods that also are + // loop headers. + // + // These will frequently have a profile imbalance as + // synthesis will have injected profile weight for + // method entry, but when we transform flow for OSR, + // only the loop back edges remain. + // + if (block == fgEntryBB) + { + verifyIncoming = false; + } + // Handler entries // if (block->hasEHBoundaryIn()) @@ -5401,11 +4867,14 @@ bool Compiler::fgDebugCheckProfileWeights(ProfileChecks checks) } } - // Verify overall input-output balance. + // Verify overall entry-exit balance. // - if (verifyClassicWeights || verifyLikelyWeights) + if (verifyLikelyWeights) { - if (entryProfiled && exitProfiled) + // If there's a try, significant weight might pass along exception edges. + // We don't model that, and it can throw off entry-exit balance. + // + if (entryProfiled && exitProfiled && !hasTry) { // Note these may not agree, if fgEntryBB is a loop header. // @@ -5429,7 +4898,7 @@ bool Compiler::fgDebugCheckProfileWeights(ProfileChecks checks) { JITDUMP("No blocks were profiled, so nothing to check\n"); } - else if (verifyClassicWeights || verifyLikelyWeights) + else if (verifyLikelyWeights) { JITDUMP("Profile is self-consistent (%d profiled blocks, %d unprofiled)\n", profiledBlocks, unprofiledBlocks); @@ -5448,6 +4917,8 @@ bool Compiler::fgDebugCheckProfileWeights(ProfileChecks checks) JITDUMP("Profile is NOT self-consistent, found %d problems (%d profiled blocks, %d unprofiled)\n", problemBlocks, profiledBlocks, unprofiledBlocks); + // Note we only assert when we think the profile data should be consistent. + // if (assertOnFailure) { assert(!"Inconsistent profile data"); @@ -5473,32 +4944,32 @@ bool Compiler::fgDebugCheckProfileWeights(ProfileChecks checks) // bool Compiler::fgDebugCheckIncomingProfileData(BasicBlock* block, ProfileChecks checks) { - const bool verifyClassicWeights = fgEdgeWeightsComputed && hasFlag(checks, ProfileChecks::CHECK_CLASSIC); - const bool verifyLikelyWeights = hasFlag(checks, ProfileChecks::CHECK_LIKELY); - const bool verifyHasLikelihood = hasFlag(checks, ProfileChecks::CHECK_HASLIKELIHOOD); + const bool verifyLikelyWeights = hasFlag(checks, ProfileChecks::CHECK_LIKELY); + const bool verifyHasLikelihood = hasFlag(checks, ProfileChecks::CHECK_HASLIKELIHOOD); - if (!(verifyClassicWeights || verifyLikelyWeights || verifyHasLikelihood)) + if (!verifyLikelyWeights && !verifyHasLikelihood) { return true; } weight_t const blockWeight = block->bbWeight; - weight_t incomingWeightMin = 0; - weight_t incomingWeightMax = 0; weight_t incomingLikelyWeight = 0; unsigned missingLikelyWeight = 0; bool foundPreds = false; + bool foundEHPreds = false; for (FlowEdge* const predEdge : block->PredEdges()) { - incomingWeightMin += predEdge->edgeWeightMin(); - incomingWeightMax += predEdge->edgeWeightMax(); if (predEdge->hasLikelihood()) { if (BasicBlock::sameHndRegion(block, predEdge->getSourceBlock())) { incomingLikelyWeight += predEdge->getLikelyWeight(); } + else + { + foundEHPreds = true; + } } else { @@ -5510,38 +4981,33 @@ bool Compiler::fgDebugCheckIncomingProfileData(BasicBlock* block, ProfileChecks foundPreds = true; } - bool classicWeightsValid = true; - bool likelyWeightsValid = true; - - if (foundPreds) + // We almost certainly won't get the likelihoods on a BBJ_EHFINALLYRET right, + // so special-case BBJ_CALLFINALLYRET incoming flow. + // + if (block->isBBCallFinallyPairTail()) { - if (verifyClassicWeights) - { - if (!fgProfileWeightsConsistent(incomingWeightMin, incomingWeightMax)) - { - JITDUMP(" " FMT_BB " - incoming min " FMT_WT " inconsistent with incoming max " FMT_WT "\n", - block->bbNum, incomingWeightMin, incomingWeightMax); - classicWeightsValid = false; - } + incomingLikelyWeight = block->Prev()->bbWeight; + foundEHPreds = false; + } - if (!fgProfileWeightsConsistent(blockWeight, incomingWeightMin)) - { - JITDUMP(" " FMT_BB " - block weight " FMT_WT " inconsistent with incoming min " FMT_WT "\n", - block->bbNum, blockWeight, incomingWeightMin); - classicWeightsValid = false; - } + // We almost certainly won't get the likelihoods on a BBJ_EHFINALLYRET right, + // so special-case BBJ_CALLFINALLYRET incoming flow. + // + if (block->isBBCallFinallyPairTail()) + { + incomingLikelyWeight = block->Prev()->bbWeight; + foundEHPreds = false; + } - if (!fgProfileWeightsConsistent(blockWeight, incomingWeightMax)) - { - JITDUMP(" " FMT_BB " - block weight " FMT_WT " inconsistent with incoming max " FMT_WT "\n", - block->bbNum, blockWeight, incomingWeightMax); - classicWeightsValid = false; - } - } + bool likelyWeightsValid = true; + // If we have EH preds we may not have consistent incoming flow. + // + if (foundPreds && !foundEHPreds) + { if (verifyLikelyWeights) { - if (!fgProfileWeightsConsistent(blockWeight, incomingLikelyWeight)) + if (!fgProfileWeightsConsistentOrSmall(blockWeight, incomingLikelyWeight)) { JITDUMP(" " FMT_BB " - block weight " FMT_WT " inconsistent with incoming likely weight " FMT_WT "\n", block->bbNum, blockWeight, incomingLikelyWeight); @@ -5560,7 +5026,7 @@ bool Compiler::fgDebugCheckIncomingProfileData(BasicBlock* block, ProfileChecks } } - return classicWeightsValid && likelyWeightsValid; + return likelyWeightsValid; } //------------------------------------------------------------------------ @@ -5579,17 +5045,15 @@ bool Compiler::fgDebugCheckIncomingProfileData(BasicBlock* block, ProfileChecks // bool Compiler::fgDebugCheckOutgoingProfileData(BasicBlock* block, ProfileChecks checks) { - const bool verifyClassicWeights = fgEdgeWeightsComputed && hasFlag(checks, ProfileChecks::CHECK_CLASSIC); - const bool verifyHasLikelihood = hasFlag(checks, ProfileChecks::CHECK_HASLIKELIHOOD); - const bool verifyLikelihoodSum = hasFlag(checks, ProfileChecks::CHECK_LIKELIHOODSUM); + const bool verifyHasLikelihood = hasFlag(checks, ProfileChecks::CHECK_HASLIKELIHOOD); + const bool verifyLikelihoodSum = hasFlag(checks, ProfileChecks::CHECK_LIKELIHOODSUM); - if (!(verifyClassicWeights || verifyHasLikelihood || verifyLikelihoodSum)) + if (!verifyHasLikelihood && !verifyLikelihoodSum) { return true; } - bool classicWeightsValid = true; - bool likelyWeightsValid = true; + bool likelyWeightsValid = true; // We want switch targets unified, but not EH edges. // @@ -5598,8 +5062,6 @@ bool Compiler::fgDebugCheckOutgoingProfileData(BasicBlock* block, ProfileChecks if ((numSuccs > 0) && !block->KindIs(BBJ_EHFINALLYRET, BBJ_EHFAULTRET, BBJ_EHFILTERRET)) { weight_t const blockWeight = block->bbWeight; - weight_t outgoingWeightMin = 0; - weight_t outgoingWeightMax = 0; weight_t outgoingLikelihood = 0; // Walk successor edges and add up flow counts. @@ -5612,9 +5074,6 @@ bool Compiler::fgDebugCheckOutgoingProfileData(BasicBlock* block, ProfileChecks assert(succEdge != nullptr); BasicBlock* succBlock = succEdge->getDestinationBlock(); - outgoingWeightMin += succEdge->edgeWeightMin(); - outgoingWeightMax += succEdge->edgeWeightMax(); - if (succEdge->hasLikelihood()) { outgoingLikelihood += succEdge->getLikelihood(); @@ -5629,32 +5088,7 @@ bool Compiler::fgDebugCheckOutgoingProfileData(BasicBlock* block, ProfileChecks if (missingEdges > 0) { JITDUMP(" " FMT_BB " - missing %d successor edges\n", block->bbNum, missingEdges); - classicWeightsValid = false; - likelyWeightsValid = false; - } - - if (verifyClassicWeights) - { - if (!fgProfileWeightsConsistent(outgoingWeightMin, outgoingWeightMax)) - { - JITDUMP(" " FMT_BB " - outgoing min " FMT_WT " inconsistent with outgoing max " FMT_WT "\n", - block->bbNum, outgoingWeightMin, outgoingWeightMax); - classicWeightsValid = false; - } - - if (!fgProfileWeightsConsistent(blockWeight, outgoingWeightMin)) - { - JITDUMP(" " FMT_BB " - block weight " FMT_WT " inconsistent with outgoing min " FMT_WT "\n", - block->bbNum, blockWeight, outgoingWeightMin); - classicWeightsValid = false; - } - - if (!fgProfileWeightsConsistent(blockWeight, outgoingWeightMax)) - { - JITDUMP(" " FMT_BB " - block weight " FMT_WT " inconsistent with outgoing max " FMT_WT "\n", - block->bbNum, blockWeight, outgoingWeightMax); - classicWeightsValid = false; - } + likelyWeightsValid = false; } if (verifyHasLikelihood) @@ -5707,7 +5141,7 @@ bool Compiler::fgDebugCheckOutgoingProfileData(BasicBlock* block, ProfileChecks } } - return classicWeightsValid && likelyWeightsValid; + return likelyWeightsValid; } #endif // DEBUG diff --git a/src/coreclr/jit/fgprofilesynthesis.cpp b/src/coreclr/jit/fgprofilesynthesis.cpp index 70b7ab6448b3..b9ff493c87d4 100644 --- a/src/coreclr/jit/fgprofilesynthesis.cpp +++ b/src/coreclr/jit/fgprofilesynthesis.cpp @@ -83,6 +83,50 @@ void ProfileSynthesis::Run(ProfileSynthesisOption option) // ComputeBlockWeights(); + // If the initial pass results were approximate, iterate until we get + // something that is self-consistent (or, accept the fact that + // the results can never be self-consistent -- infinite loops, eg). + // + // Each iteration will blend in increasing amounts of synthetic profile, + // and also modulate the synthetic probabilities towards 50/50. The net result + // is that the profile moves towards something "blander" with less dramatic loop + // iteration counts. This blending helps facilitate convergence, which is also + // impacted by extremely high loop iteration counts. + // + // Put another way, we take an initially approximate profile as a sign that the + // profile data itself may be a bit suspect, and so we adjust based on a "prior" + // belief that the profile should be somewhat flatter. + // + unsigned retries = 0; + while (m_approximate && (retries < maxRepairRetries)) + { + JITDUMP("\n\n[%d] Retrying reconstruction with blend factor " FMT_WT ", because %s\n", retries, m_blendFactor, + m_cappedCyclicProbabilities ? "capped cyclic probabilities" : "solver failed to converge"); + + // Reset + // + m_approximate = false; + m_overflow = false; + m_cappedCyclicProbabilities = 0; + + // Regularize the edge likelihoods... + // + BlendLikelihoods(); + ComputeCyclicProbabilities(); + AssignInputWeights(option); + ComputeBlockWeights(); + + // Increase blend factor and decrease synthetic loop likelihoods + // to try and force convergence + // + m_blendFactor = min(1.0, blendFactorGrowthRate * m_blendFactor); + m_loopExitLikelihood *= 0.9; + m_loopBackLikelihood *= 0.9; + m_returnLikelihood *= 1.05; + + retries++; + } + // Update pgo info // const bool hadPgoWeights = m_comp->fgPgoHaveWeights; @@ -102,21 +146,41 @@ void ProfileSynthesis::Run(ProfileSynthesisOption option) m_comp->fgPgoSynthesized = true; m_comp->fgPgoConsistent = !m_approximate; + m_comp->Metrics.ProfileSynthesizedBlendedOrRepaired++; + + if (m_approximate) + { + JITDUMP("Profile is inconsistent. Bypassing post-phase consistency checks.\n"); + m_comp->Metrics.ProfileInconsistentInitially++; + } + #ifdef DEBUG - if (JitConfig.JitCheckSynthesizedCounts() > 0) + // We want to assert that the profile is consistent. + // However, we need to defer asserting since invalid IL can + // match the one-pass convergence criteria (where we assume + // convergence) but not actually converge because of + // nonsensical flow. + // + // This generally only happens under pure synthesis, because + // methods with invalid IL won't have real PGO data. + // + // Assume all is well. + // + m_comp->fgPgoDeferredInconsistency = false; + + if (m_comp->fgPgoConsistent) { - // Verify consistency, provided we didn't see any improper headers - // or cap any Cp values. - // - // Unfortunately invalid IL may also cause inconsistencies, - // so if we are running before the importer, we can't reliably - // assert. So we check now, but defer asserting until the end of fgImport. + const bool isConsistent = + m_comp->fgDebugCheckProfileWeights(ProfileChecks::CHECK_LIKELY | ProfileChecks::CHECK_ALL_BLOCKS); + + // We thought profile data was consistent, but it wasn't. + // Leave a note so we can bypass the post-phase check, and + // instead assert at the end of fgImport, if we make it that far. // - if (m_comp->fgPgoConsistent) + if (!isConsistent) { - // verify likely weights, assert on failure, check all blocks - m_comp->fgPgoConsistentCheck = - m_comp->fgDebugCheckProfileWeights(ProfileChecks::CHECK_LIKELY | ProfileChecks::CHECK_ALL_BLOCKS); + m_comp->fgPgoDeferredInconsistency = true; + JITDUMP("Will defer asserting until after importation\n"); } } #endif @@ -206,8 +270,8 @@ void ProfileSynthesis::AssignLikelihoodCond(BasicBlock* block) return; } - BasicBlock* trueTarget = trueEdge->getDestinationBlock(); - BasicBlock* falseTarget = falseEdge->getDestinationBlock(); + BasicBlock* const trueTarget = trueEdge->getDestinationBlock(); + BasicBlock* const falseTarget = falseEdge->getDestinationBlock(); // THROW heuristic // @@ -218,13 +282,13 @@ void ProfileSynthesis::AssignLikelihoodCond(BasicBlock* block) { if (isTrueThrow) { - trueEdge->setLikelihood(0.0); - falseEdge->setLikelihood(1.0); + trueEdge->setLikelihood(throwLikelihood); + falseEdge->setLikelihood(1.0 - throwLikelihood); } else { - trueEdge->setLikelihood(1.0); - falseEdge->setLikelihood(0.0); + trueEdge->setLikelihood(1.0 - throwLikelihood); + falseEdge->setLikelihood(throwLikelihood); } return; @@ -240,14 +304,14 @@ void ProfileSynthesis::AssignLikelihoodCond(BasicBlock* block) if (isTrueEdgeBackEdge) { JITDUMP(FMT_BB "->" FMT_BB " is loop back edge\n", block->bbNum, trueTarget->bbNum); - trueEdge->setLikelihood(loopBackLikelihood); - falseEdge->setLikelihood(1.0 - loopBackLikelihood); + trueEdge->setLikelihood(m_loopBackLikelihood); + falseEdge->setLikelihood(1.0 - m_loopBackLikelihood); } else { JITDUMP(FMT_BB "->" FMT_BB " is loop back edge\n", block->bbNum, falseTarget->bbNum); - trueEdge->setLikelihood(1.0 - loopBackLikelihood); - falseEdge->setLikelihood(loopBackLikelihood); + trueEdge->setLikelihood(1.0 - m_loopBackLikelihood); + falseEdge->setLikelihood(m_loopBackLikelihood); } return; @@ -266,14 +330,14 @@ void ProfileSynthesis::AssignLikelihoodCond(BasicBlock* block) if (isTrueEdgeExitEdge) { JITDUMP(FMT_BB "->" FMT_BB " is loop exit edge\n", block->bbNum, trueTarget->bbNum); - trueEdge->setLikelihood(1.0 - loopExitLikelihood); - falseEdge->setLikelihood(loopExitLikelihood); + trueEdge->setLikelihood(1.0 - m_loopExitLikelihood); + falseEdge->setLikelihood(m_loopExitLikelihood); } else { JITDUMP(FMT_BB "->" FMT_BB " is loop exit edge\n", block->bbNum, falseTarget->bbNum); - trueEdge->setLikelihood(loopExitLikelihood); - falseEdge->setLikelihood(1.0 - loopExitLikelihood); + trueEdge->setLikelihood(m_loopExitLikelihood); + falseEdge->setLikelihood(1.0 - m_loopExitLikelihood); } return; @@ -288,13 +352,13 @@ void ProfileSynthesis::AssignLikelihoodCond(BasicBlock* block) { if (isJumpReturn) { - trueEdge->setLikelihood(returnLikelihood); - falseEdge->setLikelihood(1.0 - returnLikelihood); + trueEdge->setLikelihood(m_returnLikelihood); + falseEdge->setLikelihood(1.0 - m_returnLikelihood); } else { - trueEdge->setLikelihood(1.0 - returnLikelihood); - falseEdge->setLikelihood(returnLikelihood); + trueEdge->setLikelihood(1.0 - m_returnLikelihood); + falseEdge->setLikelihood(m_returnLikelihood); } return; @@ -531,14 +595,14 @@ void ProfileSynthesis::BlendLikelihoods() // Blend // JITDUMP("Blending likelihoods in " FMT_BB " with blend factor " FMT_WT " \n", block->bbNum, - blendFactor); + m_blendFactor); iter = likelihoods.begin(); for (FlowEdge* const succEdge : block->SuccEdges(m_comp)) { weight_t newLikelihood = succEdge->getLikelihood(); weight_t oldLikelihood = *iter; - succEdge->setLikelihood((blendFactor * oldLikelihood) + ((1.0 - blendFactor) * newLikelihood)); + succEdge->setLikelihood(((1.0 - m_blendFactor) * oldLikelihood) + (m_blendFactor * newLikelihood)); BasicBlock* const succBlock = succEdge->getDestinationBlock(); JITDUMP(FMT_BB " -> " FMT_BB " was " FMT_WT " now " FMT_WT "\n", block->bbNum, succBlock->bbNum, oldLikelihood, succEdge->getLikelihood()); @@ -670,6 +734,35 @@ void ProfileSynthesis::ComputeCyclicProbabilities() // void ProfileSynthesis::ComputeCyclicProbabilities(FlowGraphNaturalLoop* loop) { + // If a loop has no back edge, then bypass the below and + // cap the probability. + // + // If all loop exit edges are zero likelihood, this loop + // is effectively infinite, so do likewise. + // + // We may not be able to produce consistent counts for + // this flow graph, so make a note. + // + bool hasExit = false; + bool hasLikelyExit = false; + + for (FlowEdge* const exitEdge : loop->ExitEdges()) + { + hasExit = true; + if (exitEdge->getLikelihood() > 0) + { + hasLikelyExit = true; + break; + } + } + + if (!hasLikelyExit) + { + JITDUMP("Loop headed by " FMT_BB " has %s exit edges (is infinite)\n", loop->GetHeader()->bbNum, + hasExit ? "no likely" : "no"); + m_hasInfiniteLoop = true; + } + // Initialize // loop->VisitLoopBlocks([](BasicBlock* loopBlock) { @@ -685,7 +778,7 @@ void ProfileSynthesis::ComputeCyclicProbabilities(FlowGraphNaturalLoop* loop) // if (block == loop->GetHeader()) { - JITDUMP("ccp: " FMT_BB " :: 1.0\n", block->bbNum); + JITDUMP("ccp: " FMT_BB " :: 1.0 (header)\n", block->bbNum); block->bbWeight = 1.0; } else @@ -713,7 +806,7 @@ void ProfileSynthesis::ComputeCyclicProbabilities(FlowGraphNaturalLoop* loop) newWeight *= m_cyclicProbabilities[nestedLoop->GetIndex()]; block->bbWeight = newWeight; - JITDUMP("ccp (nested header): " FMT_BB " :: " FMT_WT "\n", block->bbNum, newWeight); + JITDUMP("ccp: " FMT_BB " :: " FMT_WT " (nested header)\n", block->bbNum, newWeight); } else { @@ -721,7 +814,12 @@ void ProfileSynthesis::ComputeCyclicProbabilities(FlowGraphNaturalLoop* loop) for (FlowEdge* const edge : block->PredEdges()) { - if (BasicBlock::sameHndRegion(block, edge->getSourceBlock())) + BasicBlock* const sourceBlock = edge->getSourceBlock(); + + // Ignore flow across EH, or from preds not in the loop. + // Latter can happen if there are unreachable blocks that flow into the loop. + // + if (BasicBlock::sameHndRegion(block, sourceBlock) && loop->ContainsBlock(sourceBlock)) { newWeight += edge->getLikelyWeight(); } @@ -767,8 +865,9 @@ void ProfileSynthesis::ComputeCyclicProbabilities(FlowGraphNaturalLoop* loop) // weight_t const cyclicProbability = 1.0 / (1.0 - cyclicWeight); - JITDUMP("For loop at " FMT_BB " cyclic weight is " FMT_WT " cyclic probability is " FMT_WT "%s\n", - loop->GetHeader()->bbNum, cyclicWeight, cyclicProbability, capped ? " [capped]" : ""); + JITDUMP("For loop at " FMT_BB " cyclic weight is " FMT_WT " cyclic probability is " FMT_WT "%s%s\n", + loop->GetHeader()->bbNum, cyclicWeight, cyclicProbability, capped ? " [capped]" : "", + loop->ContainsImproperHeader() ? " [likely underestimated, (loop contains improper loop)]" : ""); m_cyclicProbabilities[loop->GetIndex()] = cyclicProbability; @@ -948,35 +1047,34 @@ void ProfileSynthesis::AssignInputWeights(ProfileSynthesisOption option) // Determine input weight for EH regions, if any. // - weight_t exceptionScaleFactor = exceptionScale; + weight_t ehWeight = exceptionWeight; #ifdef DEBUG - if (JitConfig.JitSynthesisExceptionScale() != nullptr) + if (JitConfig.JitSynthesisExceptionWeight() != nullptr) { - ConfigDoubleArray JitSynthesisExceptionScaleArray; - JitSynthesisExceptionScaleArray.EnsureInit(JitConfig.JitSynthesisExceptionScale()); - weight_t newFactor = JitSynthesisExceptionScaleArray.GetData()[0]; + ConfigDoubleArray JitSynthesisExceptionWeightArray; + JitSynthesisExceptionWeightArray.EnsureInit(JitConfig.JitSynthesisExceptionWeight()); + weight_t newFactor = JitSynthesisExceptionWeightArray.GetData()[0]; if ((newFactor >= 0) && (newFactor <= 1.0)) { - exceptionScaleFactor = newFactor; + ehWeight = newFactor; } } #endif - JITDUMP("Synthesis: exception scale factor " FMT_WT "\n", exceptionScaleFactor); - const weight_t ehWeight = entryWeight * exceptionScaleFactor; + JITDUMP("Synthesis: exception weight " FMT_WT "\n", ehWeight); if (ehWeight != 0) { - // We can't inline methods with EH, also inlinees share the parent - // EH tab, so we can't rely on this being empty. + // We can't inline methods with EH. Inlinees share the parent + // EH tab, so we can't rely on the EH table being empty. // if (!m_comp->compIsForInlining()) { for (EHblkDsc* const HBtab : EHClauses(m_comp)) { - // Only set weights on the filter/hander entries + // Only set weights on the filter/handler entries // if the associated try is reachable. // BasicBlock* const tryBlock = HBtab->ebdTryBeg; @@ -1098,17 +1196,19 @@ void ProfileSynthesis::GaussSeidelSolver() // The algorithm. // - bool converged = false; - weight_t previousResidual = 0; - weight_t residual = 0; - weight_t relResidual = 0; - weight_t oldRelResidual = 0; - weight_t eigenvalue = 0; - weight_t const stopRelResidual = 0.002; - BasicBlock* residualBlock = nullptr; - BasicBlock* relResidualBlock = nullptr; - const FlowGraphDfsTree* const dfs = m_loops->GetDfsTree(); - unsigned const blockCount = dfs->GetPostOrderCount(); + bool converged = false; + weight_t previousResidual = 0; + weight_t residual = 0; + weight_t relResidual = 0; + weight_t oldRelResidual = 0; + weight_t eigenvalue = 0; + weight_t const stopRelResidual = 0.002; + BasicBlock* residualBlock = nullptr; + BasicBlock* relResidualBlock = nullptr; + const FlowGraphDfsTree* const dfs = m_loops->GetDfsTree(); + unsigned const blockCount = dfs->GetPostOrderCount(); + bool checkEntryExitWeight = true; + bool showDetails = false; // Remember the entry block // @@ -1119,7 +1219,7 @@ void ProfileSynthesis::GaussSeidelSolver() // to converge. We don't have time for that, so we will give up // fairly quickly. // - // This can be mitgated somewhat by using blend mode for repairs, as that tends + // This can be mitigated somewhat by using blend mode for repairs, as that tends // to shift likelihoods off of the extremes (say 0.999) can lead to high // iteration counts. // @@ -1129,7 +1229,7 @@ void ProfileSynthesis::GaussSeidelSolver() // It is possible that a more sophisticated solver (say GMRES or BiCGStab) // might be more effective and run in acceptable time. // - unsigned const iterationLimit = (m_improperLoopHeaders > 0) ? 20 : 1; + unsigned const iterationLimit = (m_improperLoopHeaders > 0) ? maxSolverIterations : 1; // Push weights forward in flow, iterate until convergence. // @@ -1141,6 +1241,9 @@ void ProfileSynthesis::GaussSeidelSolver() residual = 0; relResidual = 0; + weight_t entryWeight = 0; + weight_t exitWeight = 0; + // Compute new counts based on Gauss-Seidel iteration // // Todo: after 1st iteration we can start at the postorder @@ -1158,11 +1261,17 @@ void ProfileSynthesis::GaussSeidelSolver() BasicBlock* const block = dfs->GetPostOrder(j - 1); weight_t newWeight = 0; + // If there's a block in a try, we can't expect to see + // entry and exit weights agree. + // + checkEntryExitWeight &= !block->hasTryIndex(); + // Some blocks have additional profile weights that don't come from flow edges. // if (block == entryBlock) { - newWeight = block->bbWeight; + newWeight = block->bbWeight; + entryWeight = newWeight; } else { @@ -1219,6 +1328,11 @@ void ProfileSynthesis::GaussSeidelSolver() } else { + if ((loop != nullptr) && showDetails) + { + JITDUMP(" .. not using Cp for " FMT_BB "; loop contains improper header\n", block->bbNum); + } + // A self-edge that's part of a bigger SCC may // not be detected as simple loop. // @@ -1230,7 +1344,7 @@ void ProfileSynthesis::GaussSeidelSolver() if (predBlock == block) { - // We might see a degenerate self BBJ_COND. Hoepfully not. + // We might see a degenerate self BBJ_COND. Hopefully not. // assert(selfEdge == nullptr); selfEdge = edge; @@ -1267,19 +1381,41 @@ void ProfileSynthesis::GaussSeidelSolver() // assert(change >= 0); - JITDUMP("iteration %u: " FMT_BB " :: old " FMT_WT " new " FMT_WT " change " FMT_WT "\n", i, block->bbNum, - oldWeight, newWeight, change); + bool isExit = false; + if (checkEntryExitWeight) + { + if (block->KindIs(BBJ_RETURN)) + { + exitWeight += newWeight; + isExit = true; + } + else if (block->KindIs(BBJ_THROW)) + { + if (!block->hasTryIndex()) + { + exitWeight += newWeight; + isExit = true; + } + } + } + + if (showDetails) + { + JITDUMP("iteration %u: " FMT_BB " :: old " FMT_WT " new " FMT_WT " change " FMT_WT "%s\n", i, + block->bbNum, oldWeight, newWeight, change, isExit ? " [exit]" : ""); + } + countVector[block->bbNum] = newWeight; // Remember max absolute and relative change - // (note rel residual will be infinite on the first pass, that's ok) + // (note rel residual will be infinite at times, that's ok) // // Note we are using a "point" bound here ("infinity norm") rather than say - // computing the l2-norm of the entire residual vector. + // computing the L2-norm of the entire residual vector. // weight_t const blockRelResidual = change / oldWeight; - if ((relResidualBlock == nullptr) || ((oldWeight > 0) && (blockRelResidual > relResidual))) + if ((relResidualBlock == nullptr) || (blockRelResidual > relResidual)) { relResidual = blockRelResidual; relResidualBlock = block; @@ -1307,6 +1443,26 @@ void ProfileSynthesis::GaussSeidelSolver() break; } + // Compute the relative entry/exit "residual", if we have reason to believe it + // should balance. + // + if (checkEntryExitWeight) + { + // we can see slight overflow here in the exit residual, so use abs + // + weight_t const entryExitResidual = fabs(entryWeight - exitWeight); + JITDUMP("Entry weight " FMT_WT " exit weight " FMT_WT " residual " FMT_WT "\n", entryWeight, exitWeight, + entryExitResidual); + weight_t const entryExitRelResidual = entryExitResidual / entryWeight; + assert(entryExitRelResidual >= 0); + + if (entryExitRelResidual > relResidual) + { + relResidual = entryExitRelResidual; + relResidualBlock = entryBlock; + } + } + JITDUMP("iteration %u: max residual is at " FMT_BB " : " FMT_WT "\n", i, residualBlock->bbNum, residual); JITDUMP("iteration %u: max rel residual is at " FMT_BB " : " FMT_WT "\n", i, relResidualBlock->bbNum, relResidual); @@ -1340,14 +1496,6 @@ void ProfileSynthesis::GaussSeidelSolver() JITDUMP("%s at iteration %u rel residual " FMT_WT " eigenvalue " FMT_WT "\n", converged ? "converged" : "failed to converge", i, relResidual, eigenvalue); - // TODO: computation above may be on the edge of diverging as there is - // nothing preventing a general cycle from having 1.0 likelihood. That - // is, there is nothing analogous to the capped cyclic check for more - // general cycles. - // - // We should track if the overall residual error (say L1 or L2 norm). - // If it is not decreasing, consider not using the data. - // // Propagate the computed weights to the blocks. // for (unsigned j = m_dfsTree->GetPostOrderCount(); j != 0; j--) diff --git a/src/coreclr/jit/fgprofilesynthesis.h b/src/coreclr/jit/fgprofilesynthesis.h index e2e7c58cbac4..e704f291802e 100644 --- a/src/coreclr/jit/fgprofilesynthesis.h +++ b/src/coreclr/jit/fgprofilesynthesis.h @@ -45,14 +45,18 @@ class ProfileSynthesis { } - static constexpr weight_t exceptionScale = 0.001; - static constexpr weight_t blendFactor = 0.99; - static constexpr weight_t cappedLikelihood = 0.999; - static constexpr weight_t returnLikelihood = 0.2; - static constexpr weight_t ilNextLikelihood = 0.52; - static constexpr weight_t loopBackLikelihood = 0.9; - static constexpr weight_t loopExitLikelihood = 0.9; - static constexpr weight_t maxCount = 1e12; + static constexpr weight_t exceptionWeight = 0.00001; + static constexpr weight_t initialBlendFactor = 0.05; + static constexpr weight_t blendFactorGrowthRate = 3; + static constexpr weight_t cappedLikelihood = 0.999; + static constexpr weight_t returnLikelihood = 0.2; + static constexpr weight_t ilNextLikelihood = 0.52; + static constexpr weight_t loopBackLikelihood = 0.9; + static constexpr weight_t loopExitLikelihood = 0.9; + static constexpr weight_t throwLikelihood = 0; + static constexpr unsigned maxRepairRetries = 4; + static constexpr unsigned maxSolverIterations = 50; + static constexpr weight_t maxCount = 1e12; void Run(ProfileSynthesisOption option); @@ -83,10 +87,15 @@ class ProfileSynthesis FlowGraphDfsTree* m_dfsTree = nullptr; FlowGraphNaturalLoops* m_loops = nullptr; weight_t* m_cyclicProbabilities = nullptr; + weight_t m_blendFactor = initialBlendFactor; + weight_t m_loopExitLikelihood = loopExitLikelihood; + weight_t m_loopBackLikelihood = loopBackLikelihood; + weight_t m_returnLikelihood = returnLikelihood; unsigned m_improperLoopHeaders = 0; unsigned m_cappedCyclicProbabilities = 0; bool m_approximate = false; bool m_overflow = false; + bool m_hasInfiniteLoop = false; }; #endif // !_FGPROFILESYNTHESIS_H_ diff --git a/src/coreclr/jit/fgstmt.cpp b/src/coreclr/jit/fgstmt.cpp index 2189955a6f97..85809339965f 100644 --- a/src/coreclr/jit/fgstmt.cpp +++ b/src/coreclr/jit/fgstmt.cpp @@ -18,9 +18,9 @@ bool Compiler::fgBlockContainsStatementBounded(BasicBlock* block, Statement* stmt, bool answerOnBoundExceeded /*= true*/) { - const __int64 maxLinks = 100000000; + const int64_t maxLinks = 100000000; - __int64* numTraversed = &JitTls::GetCompiler()->compNumStatementLinksTraversed; + int64_t* numTraversed = &JitTls::GetCompiler()->compNumStatementLinksTraversed; if (*numTraversed > maxLinks) { @@ -197,7 +197,7 @@ void Compiler::fgInsertStmtNearEnd(BasicBlock* block, Statement* stmt) } else if (block->KindIs(BBJ_RETURN)) { - assert((lastStmt->GetRootNode()->OperIs(GT_RETURN, GT_JMP)) || + assert((lastStmt->GetRootNode()->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET, GT_JMP)) || // BBJ_RETURN blocks in functions returning void do not get a GT_RETURN node if they // have a .tail prefix (even if canTailCall returns false for these calls) // code:Compiler::impImportBlockCode (search for the RET: label) @@ -538,6 +538,7 @@ inline bool OperIsControlFlow(genTreeOps oper) case GT_RETURN: case GT_RETFILT: + case GT_SWIFT_ERROR_RET: #if defined(FEATURE_EH_WINDOWS_X86) case GT_END_LFIN: #endif // FEATURE_EH_WINDOWS_X86 diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index d172539582ca..4aa172fea9db 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -587,11 +587,15 @@ PhaseStatus Compiler::fgImport() // Now that we've made it through the importer, we know the IL was valid. // If we synthesized profile data and though it should be consistent, - // verify that it was consistent. + // but it wasn't, assert now. // if (fgPgoSynthesized && fgPgoConsistent) { - assert(fgPgoConsistentCheck); + assert(!fgPgoDeferredInconsistency); + + // Reset this as it is a one-shot thing. + // + INDEBUG(fgPgoDeferredInconsistency = false); } return PhaseStatus::MODIFIED_EVERYTHING; @@ -609,8 +613,9 @@ bool Compiler::fgIsThrow(GenTree* tree) return false; } GenTreeCall* call = tree->AsCall(); - if ((call->gtCallType == CT_HELPER) && s_helperCallProperties.AlwaysThrow(eeGetHelperNum(call->gtCallMethHnd))) + if (call->IsHelperCall() && s_helperCallProperties.AlwaysThrow(eeGetHelperNum(call->gtCallMethHnd))) { + assert(call->IsNoReturn()); noway_assert(call->gtFlags & GTF_EXCEPT); return true; } @@ -1060,14 +1065,26 @@ GenTree* Compiler::fgOptimizeDelegateConstructor(GenTreeCall* call, else { assert(oper != GT_FTN_ADDR); - CORINFO_CONST_LOOKUP genericLookup; - info.compCompHnd->getReadyToRunHelper(&ldftnToken->m_token, &pLookup.lookupKind, - CORINFO_HELP_READYTORUN_GENERIC_HANDLE, info.compMethodHnd, - &genericLookup); - GenTree* ctxTree = getRuntimeContextTree(pLookup.lookupKind.runtimeLookupKind); - call = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, TYP_VOID, thisPointer, - targetObjPointers, ctxTree); - call->setEntryPoint(genericLookup); + + if (pLookup.lookupKind.runtimeLookupKind != CORINFO_LOOKUP_NOT_SUPPORTED) + { + CORINFO_CONST_LOOKUP genericLookup; + info.compCompHnd->getReadyToRunHelper(&ldftnToken->m_token, &pLookup.lookupKind, + CORINFO_HELP_READYTORUN_GENERIC_HANDLE, + info.compMethodHnd, &genericLookup); + GenTree* ctxTree = getRuntimeContextTree(pLookup.lookupKind.runtimeLookupKind); + call = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, TYP_VOID, thisPointer, + targetObjPointers, ctxTree); + call->setEntryPoint(genericLookup); + } + else + { + // Runtime does not support inlining of all shapes of runtime lookups + // Inlining has to be aborted in such a case + assert(compIsForInlining()); + compInlineResult->NoteFatal(InlineObservation::CALLSITE_GENERIC_DICTIONARY_LOOKUP); + JITDUMP("not optimized, generic inlining restriction\n"); + } } } else @@ -1590,7 +1607,7 @@ GenTree* Compiler::fgCreateMonitorTree(unsigned lvaMonAcquired, unsigned lvaThis } #endif - if (block->KindIs(BBJ_RETURN) && block->lastStmt()->GetRootNode()->gtOper == GT_RETURN) + if (block->KindIs(BBJ_RETURN) && block->lastStmt()->GetRootNode()->OperIs(GT_RETURN)) { GenTreeUnOp* retNode = block->lastStmt()->GetRootNode()->AsUnOp(); GenTree* retExpr = retNode->gtOp1; @@ -2441,7 +2458,10 @@ PhaseStatus Compiler::fgAddInternal() LclVarDsc* varDsc = lvaGetDesc(lvaInlinedPInvokeFrameVar); // Make room for the inlined frame. - lvaSetStruct(lvaInlinedPInvokeFrameVar, typGetBlkLayout(eeGetEEInfo()->inlinedCallFrameInfo.size), false); + const CORINFO_EE_INFO* eeInfo = eeGetEEInfo(); + unsigned frameSize = info.compPublishStubParam ? eeInfo->inlinedCallFrameInfo.sizeWithSecretStubArg + : eeInfo->inlinedCallFrameInfo.size; + lvaSetStruct(lvaInlinedPInvokeFrameVar, typGetBlkLayout(frameSize), false); } // Do we need to insert a "JustMyCode" callback? @@ -2567,6 +2587,93 @@ PhaseStatus Compiler::fgAddInternal() return madeChanges ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING; } +#ifdef SWIFT_SUPPORT +//------------------------------------------------------------------------ +// fgAddSwiftErrorReturns: If this method uses Swift error handling, +// transform all GT_RETURN nodes into GT_SWIFT_ERROR_RET nodes +// to handle returning the error value alongside the normal return value. +// Also transform any GT_LCL_VAR uses of lvaSwiftErrorArg (the SwiftError* parameter) +// into GT_LCL_ADDR uses of lvaSwiftErrorLocal (the SwiftError pseudolocal). +// +// Returns: +// Suitable phase status. +// +PhaseStatus Compiler::fgAddSwiftErrorReturns() +{ + if (lvaSwiftErrorArg == BAD_VAR_NUM) + { + // No Swift error handling in this method + return PhaseStatus::MODIFIED_NOTHING; + } + + assert(lvaSwiftErrorLocal != BAD_VAR_NUM); + assert(info.compCallConv == CorInfoCallConvExtension::Swift); + + struct ReplaceSwiftErrorVisitor final : public GenTreeVisitor + { + enum + { + DoPreOrder = true, + DoLclVarsOnly = true, + }; + + ReplaceSwiftErrorVisitor(Compiler* comp) + : GenTreeVisitor(comp) + { + } + + fgWalkResult PreOrderVisit(GenTree** use, GenTree* user) + { + if ((*use)->AsLclVarCommon()->GetLclNum() == m_compiler->lvaSwiftErrorArg) + { + if (!(*use)->OperIs(GT_LCL_VAR)) + { + BADCODE("Found invalid use of SwiftError* parameter"); + } + + *use = m_compiler->gtNewLclVarAddrNode(m_compiler->lvaSwiftErrorLocal, genActualType(*use)); + } + + return fgWalkResult::WALK_CONTINUE; + } + }; + + ReplaceSwiftErrorVisitor visitor(this); + + for (BasicBlock* block : Blocks()) + { + for (Statement* const stmt : block->Statements()) + { + visitor.WalkTree(stmt->GetRootNodePointer(), nullptr); + } + + if (block->KindIs(BBJ_RETURN)) + { + GenTree* const ret = block->lastNode(); + assert(ret->OperIs(GT_RETURN)); + ret->SetOperRaw(GT_SWIFT_ERROR_RET); + ret->AsOp()->gtOp2 = ret->AsOp()->gtOp1; + + // If this is the merged return block, use the merged return error local as the error operand. + // Else, load the error value from the SwiftError pseudolocal (this will probably get promoted, anyway). + if (block == genReturnBB) + { + assert(genReturnErrorLocal == BAD_VAR_NUM); + genReturnErrorLocal = lvaGrabTemp(true DEBUGARG("Single return block SwiftError value")); + lvaGetDesc(genReturnErrorLocal)->lvType = TYP_I_IMPL; + ret->AsOp()->gtOp1 = gtNewLclvNode(genReturnErrorLocal, TYP_I_IMPL); + } + else + { + ret->AsOp()->gtOp1 = gtNewLclFldNode(lvaSwiftErrorLocal, TYP_I_IMPL, 0); + } + } + } + + return PhaseStatus::MODIFIED_EVERYTHING; +} +#endif // SWIFT_SUPPORT + /*****************************************************************************/ /*****************************************************************************/ @@ -2999,17 +3106,12 @@ bool Compiler::fgFuncletsAreCold() // // Notes: // Walk the basic blocks list to determine the first block to place in the -// cold section. This would be the first of a series of rarely executed blocks +// cold section. This would be the first of a series of rarely executed blocks // such that no succeeding blocks are in a try region or an exception handler // or are rarely executed. // PhaseStatus Compiler::fgDetermineFirstColdBlock() { - // Since we may need to create a new transition block - // we assert that it is OK to create new blocks. - // - assert(fgPredsComputed); - assert(fgSafeBasicBlockCreation); assert(fgFirstColdBlock == nullptr); if (!opts.compProcedureSplitting) @@ -3050,15 +3152,6 @@ PhaseStatus Compiler::fgDetermineFirstColdBlock() for (lblk = nullptr, block = fgFirstBB; block != nullptr; lblk = block, block = block->Next()) { - bool blockMustBeInHotSection = false; - -#if HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION - if (bbIsHandlerBeg(block)) - { - blockMustBeInHotSection = true; - } -#endif // HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION - // Make note of if we're in the funclet section, // so we can stop the search early. if (block == fgFirstFuncletBB) @@ -3072,7 +3165,7 @@ PhaseStatus Compiler::fgDetermineFirstColdBlock() // We have a candidate for first cold block // Is this a hot block? - if (blockMustBeInHotSection || (block->isRunRarely() == false)) + if (!block->isRunRarely()) { // We have to restart the search for the first cold block firstColdBlock = nullptr; @@ -3111,7 +3204,7 @@ PhaseStatus Compiler::fgDetermineFirstColdBlock() } // Is this a cold block? - if (!blockMustBeInHotSection && block->isRunRarely()) + if (block->isRunRarely()) { // // If the last block that was hot was a BBJ_COND @@ -3959,8 +4052,8 @@ bool FlowGraphDfsTree::Contains(BasicBlock* block) const // block `descendant` // // Arguments: -// ancestor -- block that is possible ancestor -// descendant -- block that is possible descendant +// ancestor - block that is possible ancestor +// descendant - block that is possible descendant // // Returns: // True if `ancestor` is ancestor of `descendant` in the depth first spanning @@ -3979,6 +4072,9 @@ bool FlowGraphDfsTree::IsAncestor(BasicBlock* ancestor, BasicBlock* descendant) //------------------------------------------------------------------------ // fgComputeDfs: Compute a depth-first search tree for the flow graph. // +// Type parameters: +// useProfile - If true, determines order of successors visited using profile data +// // Returns: // The tree. // @@ -3986,6 +4082,7 @@ bool FlowGraphDfsTree::IsAncestor(BasicBlock* ancestor, BasicBlock* descendant) // Preorder and postorder numbers are assigned into the BasicBlock structure. // The tree returned contains a postorder of the basic blocks. // +template FlowGraphDfsTree* Compiler::fgComputeDfs() { BasicBlock** postOrder = new (this, CMK_DepthFirstSearch) BasicBlock*[fgBBcount]; @@ -4011,10 +4108,17 @@ FlowGraphDfsTree* Compiler::fgComputeDfs() } }; - unsigned numBlocks = fgRunDfs(visitPreorder, visitPostorder, visitEdge); + unsigned numBlocks = + fgRunDfs(visitPreorder, + visitPostorder, + visitEdge); return new (this, CMK_DepthFirstSearch) FlowGraphDfsTree(this, postOrder, numBlocks, hasCycle); } +// Add explicit instantiations. +template FlowGraphDfsTree* Compiler::fgComputeDfs(); +template FlowGraphDfsTree* Compiler::fgComputeDfs(); + //------------------------------------------------------------------------ // fgInvalidateDfsTree: Invalidate computed DFS tree and dependent annotations // (like loops, dominators and SSA). @@ -4379,6 +4483,7 @@ FlowGraphNaturalLoops* FlowGraphNaturalLoops::Find(const FlowGraphDfsTree* dfsTr { if (otherLoop->ContainsBlock(header)) { + JITDUMP("Noting that " FMT_LP " contains an improper loop header\n", loop->GetIndex()); otherLoop->m_containsImproperHeader = true; } } @@ -5484,7 +5589,7 @@ bool FlowGraphNaturalLoop::InitBlockEntersLoopOnTrue(BasicBlock* initBlock) // the loop. // // Returns: -// Block with highest bbNum. +// First block in block order contained in the loop. // // Remarks: // Mostly exists as a quirk while transitioning from the old loop @@ -5492,12 +5597,13 @@ bool FlowGraphNaturalLoop::InitBlockEntersLoopOnTrue(BasicBlock* initBlock) // BasicBlock* FlowGraphNaturalLoop::GetLexicallyTopMostBlock() { - BasicBlock* top = m_header; - VisitLoopBlocks([&top](BasicBlock* loopBlock) { - if (loopBlock->bbNum < top->bbNum) - top = loopBlock; - return BasicBlockVisit::Continue; - }); + BasicBlock* top = m_dfsTree->GetCompiler()->fgFirstBB; + + while (!ContainsBlock(top)) + { + top = top->Next(); + assert(top != nullptr); + } return top; } @@ -5507,7 +5613,7 @@ BasicBlock* FlowGraphNaturalLoop::GetLexicallyTopMostBlock() // within the loop. // // Returns: -// Block with highest bbNum. +// Last block in block order contained in the loop. // // Remarks: // Mostly exists as a quirk while transitioning from the old loop @@ -5515,12 +5621,13 @@ BasicBlock* FlowGraphNaturalLoop::GetLexicallyTopMostBlock() // BasicBlock* FlowGraphNaturalLoop::GetLexicallyBottomMostBlock() { - BasicBlock* bottom = m_header; - VisitLoopBlocks([&bottom](BasicBlock* loopBlock) { - if (loopBlock->bbNum > bottom->bbNum) - bottom = loopBlock; - return BasicBlockVisit::Continue; - }); + BasicBlock* bottom = m_dfsTree->GetCompiler()->fgLastBB; + + while (!ContainsBlock(bottom)) + { + bottom = bottom->Prev(); + assert(bottom != nullptr); + } return bottom; } diff --git a/src/coreclr/jit/forwardsub.cpp b/src/coreclr/jit/forwardsub.cpp index de4ac5fe8a47..9d57fa3a4a6d 100644 --- a/src/coreclr/jit/forwardsub.cpp +++ b/src/coreclr/jit/forwardsub.cpp @@ -798,7 +798,7 @@ bool Compiler::fgForwardSubStatement(Statement* stmt) // interaction between decomposition and RA. // if (compMethodReturnsMultiRegRetType() && (fsv.GetParentNode() != nullptr) && - fsv.GetParentNode()->OperIs(GT_RETURN)) + fsv.GetParentNode()->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)) { #if defined(TARGET_X86) if (fwdSubNode->TypeGet() == TYP_LONG) diff --git a/src/coreclr/jit/gcencode.cpp b/src/coreclr/jit/gcencode.cpp index b7972f216d53..d1721f7896bb 100644 --- a/src/coreclr/jit/gcencode.cpp +++ b/src/coreclr/jit/gcencode.cpp @@ -2584,9 +2584,7 @@ size_t GCInfo::gcMakeRegPtrTable(BYTE* dest, int mask, const InfoHdr& header, un assert((codeDelta & 0x7) == codeDelta); *dest++ = 0xB0 | (BYTE)codeDelta; -#ifndef UNIX_X86_ABI - assert(!compiler->isFramePointerUsed()); -#endif + assert(compiler->UsesFunclets() || !compiler->isFramePointerUsed()); /* Remember the new 'last' offset */ @@ -2876,7 +2874,7 @@ size_t GCInfo::gcMakeRegPtrTable(BYTE* dest, int mask, const InfoHdr& header, un if (compiler->lvaKeepAliveAndReportThis() && compiler->lvaTable[compiler->info.compThisArg].lvRegister) { - unsigned thisRegMask = genRegMask(compiler->lvaTable[compiler->info.compThisArg].GetRegNum()); + unsigned thisRegMask = (unsigned)genRegMask(compiler->lvaTable[compiler->info.compThisArg].GetRegNum()); unsigned thisPtrRegEnc = gceEncodeCalleeSavedRegs(thisRegMask) << 4; if (thisPtrRegEnc) @@ -4473,8 +4471,8 @@ void GCInfo::gcMakeRegPtrTable( assert(call->u1.cdArgMask == 0 && call->cdArgCnt == 0); // Other than that, we just have to deal with the regmasks. - regMaskSmall gcrefRegMask = call->cdGCrefRegs & RBM_CALLEE_SAVED; - regMaskSmall byrefRegMask = call->cdByrefRegs & RBM_CALLEE_SAVED; + regMaskSmall gcrefRegMask = call->cdGCrefRegs & RBM_CALL_GC_REGS; + regMaskSmall byrefRegMask = call->cdByrefRegs & RBM_CALL_GC_REGS; assert((gcrefRegMask & byrefRegMask) == 0); @@ -4669,7 +4667,7 @@ void GCInfo::gcInfoRecordGCRegStateChange(GcInfoEncoder* gcInfoEncoder, } // Turn the bit we've just generated off and continue. - regMask -= tmpMask; // EAX,ECX,EDX,EBX,---,EBP,ESI,EDI + regMask ^= tmpMask; // EAX,ECX,EDX,EBX,---,EBP,ESI,EDI } } diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index ead6b4d83c21..7cc38b4961f2 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -420,10 +420,10 @@ inline unsigned hashme(genTreeOps op1, genTreeOps op2) struct BashHashDsc { - unsigned __int32 bhFullHash; // the hash value (unique for all old->new pairs) - unsigned __int32 bhCount; // the same old->new bashings seen so far - unsigned __int8 bhOperOld; // original gtOper - unsigned __int8 bhOperNew; // new gtOper + uint32_t bhFullHash; // the hash value (unique for all old->new pairs) + uint32_t bhCount; // the same old->new bashings seen so far + uint8_t bhOperOld; // original gtOper + uint8_t bhOperNew; // new gtOper }; static BashHashDsc BashHash[BASH_HASH_SIZE]; @@ -2248,7 +2248,7 @@ GenTree* Compiler::getArrayLengthFromAllocation(GenTree* tree DEBUGARG(BasicBloc { GenTreeCall* call = tree->AsCall(); - if (call->gtCallType == CT_HELPER) + if (call->IsHelperCall()) { CorInfoHelpFunc helper = eeGetHelperNum(call->gtCallMethHnd); switch (helper) @@ -2405,7 +2405,7 @@ bool GenTreeCall::HasSideEffects(Compiler* compiler, bool ignoreExceptions, bool { // Generally all GT_CALL nodes are considered to have side-effects, but we may have extra information about helper // calls that can prove them side-effect-free. - if (gtCallType != CT_HELPER) + if (!IsHelperCall()) { // If needed, we can annotate other special intrinsic methods as side effect free as well. if (IsSpecialIntrinsic(compiler, NI_System_Type_GetTypeFromHandle)) @@ -2854,6 +2854,24 @@ bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK) } break; + case GT_CNS_LNG: + { + if (op1->AsLngCon()->gtLconVal == op2->AsLngCon()->gtLconVal) + { + return true; + } + break; + } + + case GT_CNS_DBL: + { + if (op1->AsDblCon()->isBitwiseEqual(op2->AsDblCon())) + { + return true; + } + break; + } + case GT_CNS_STR: if ((op1->AsStrCon()->gtSconCPX == op2->AsStrCon()->gtSconCPX) && (op1->AsStrCon()->gtScpHnd == op2->AsStrCon()->gtScpHnd)) @@ -2871,18 +2889,6 @@ bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK) break; } -#if 0 - // TODO-CQ: Enable this in the future - case GT_CNS_LNG: - if (op1->AsLngCon()->gtLconVal == op2->AsLngCon()->gtLconVal) - return true; - break; - - case GT_CNS_DBL: - if (op1->AsDblCon()->DconValue() == op2->AsDblCon()->DconValue()) - return true; - break; -#endif default: break; } @@ -8325,7 +8331,7 @@ GenTreeIntCon* Compiler::gtNewStringLiteralLength(GenTreeStrCon* node) /*****************************************************************************/ -GenTree* Compiler::gtNewLconNode(__int64 value) +GenTree* Compiler::gtNewLconNode(int64_t value) { #ifdef TARGET_64BIT GenTree* node = new (this, GT_CNS_INT) GenTreeIntCon(TYP_LONG, value); @@ -10129,6 +10135,10 @@ GenTree* Compiler::gtCloneExpr(GenTree* tree) } break; + case GT_SWIFT_ERROR_RET: + copy = new (this, oper) GenTreeOp(oper, tree->TypeGet(), tree->gtGetOp1(), tree->gtGetOp2()); + break; + default: assert(!GenTree::IsExOp(tree->OperKind()) && tree->OperIsSimple()); // We're in the SimpleOp case, so it's always unary or binary. @@ -10257,7 +10267,6 @@ GenTree* Compiler::gtCloneExpr(GenTree* tree) /* Make sure to copy back fields that may have been initialized */ copy->CopyRawCosts(tree); - copy->gtRsvdRegs = tree->gtRsvdRegs; copy->CopyReg(tree); return copy; } @@ -11482,7 +11491,7 @@ void Compiler::gtDispNodeName(GenTree* tree) callType = "CALLV"; } } - else if (tree->AsCall()->gtCallType == CT_HELPER) + else if (tree->AsCall()->IsHelperCall()) { ctType = " help"; } @@ -12122,12 +12131,14 @@ void Compiler::gtDispNode(GenTree* tree, IndentStack* indentStack, _In_ _In_opt_ // for tracking down problems in reguse prediction or liveness tracking +#if !defined(TARGET_WASM) if (verbose && 0) { printf(" RR="); - dspRegMask(tree->gtRsvdRegs); + dspRegMask(JitTls::GetCompiler()->codeGen->internalRegisters.GetAll(tree)); printf("\n"); } +#endif //!TARGET_WASM } } @@ -13618,8 +13629,6 @@ const char* Compiler::gtGetWellKnownArgNameForArgMsg(WellKnownArg arg) return "retbuf"; case WellKnownArg::PInvokeFrame: return "pinv frame"; - case WellKnownArg::SecretStubParam: - return "stub param"; case WellKnownArg::WrapperDelegateCell: return "wrap cell"; case WellKnownArg::ShiftLow: @@ -15894,7 +15903,7 @@ GenTree* Compiler::gtFoldExprConst(GenTree* tree) #if defined(TARGET_64BIT) if (tree->IsUnsigned() && (lval1 < 0)) { - f1 = FloatingPointUtils::convertUInt64ToFloat((unsigned __int64)lval1); + f1 = FloatingPointUtils::convertUInt64ToFloat((uint64_t)lval1); } else { @@ -15907,8 +15916,7 @@ GenTree* Compiler::gtFoldExprConst(GenTree* tree) if (tree->IsUnsigned() && (lval1 < 0)) { - f1 = forceCastToFloat( - FloatingPointUtils::convertUInt64ToDouble((unsigned __int64)lval1)); + f1 = forceCastToFloat(FloatingPointUtils::convertUInt64ToDouble((uint64_t)lval1)); } else { @@ -15924,7 +15932,7 @@ GenTree* Compiler::gtFoldExprConst(GenTree* tree) { if (tree->IsUnsigned() && (lval1 < 0)) { - d1 = FloatingPointUtils::convertUInt64ToDouble((unsigned __int64)lval1); + d1 = FloatingPointUtils::convertUInt64ToDouble((uint64_t)lval1); } else { @@ -17211,7 +17219,7 @@ bool Compiler::gtTreeHasSideEffects(GenTree* tree, GenTreeFlags flags /* = GTF_S { // Generally all trees that contain GT_CALL nodes are considered to have side-effects. // - if (tree->AsCall()->gtCallType == CT_HELPER) + if (tree->AsCall()->IsHelperCall()) { // If this node is a helper call we may not care about the side-effects. // Note that gtNodeHasSideEffects checks the side effects of the helper itself @@ -17673,7 +17681,7 @@ void Compiler::gtExtractSideEffList(GenTree* expr, // Generally all GT_CALL nodes are considered to have side-effects. // So if we get here it must be a helper call that we decided it does // not have side effects that we needed to keep. - assert(!node->OperIs(GT_CALL) || (node->AsCall()->gtCallType == CT_HELPER)); + assert(!node->OperIs(GT_CALL) || node->AsCall()->IsHelperCall()); } if ((m_flags & GTF_IS_IN_CSE) != 0) @@ -17971,7 +17979,7 @@ Compiler::TypeProducerKind Compiler::gtGetTypeProducerKind(GenTree* tree) { if (tree->gtOper == GT_CALL) { - if (tree->AsCall()->gtCallType == CT_HELPER) + if (tree->AsCall()->IsHelperCall()) { if (gtIsTypeHandleToRuntimeTypeHelper(tree->AsCall())) { @@ -18493,7 +18501,7 @@ bool GenTree::canBeContained() const } else if (OperIsHWIntrinsic() && !isContainableHWIntrinsic()) { - return isEvexEmbeddedMaskingCompatibleHWIntrinsic(); + return isEmbeddedMaskingCompatibleHWIntrinsic(); } return true; @@ -19053,7 +19061,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b objClass = sig.retTypeClass; } } - else if (call->gtCallType == CT_HELPER) + else if (call->IsHelperCall()) { objClass = gtGetHelperCallClassHandle(call, pIsExact, pIsNonNull); } @@ -19220,7 +19228,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b // CORINFO_CLASS_HANDLE Compiler::gtGetHelperCallClassHandle(GenTreeCall* call, bool* pIsExact, bool* pIsNonNull) { - assert(call->gtCallType == CT_HELPER); + assert(call->IsHelperCall()); *pIsNonNull = false; *pIsExact = false; @@ -20219,13 +20227,6 @@ bool GenTree::isContainableHWIntrinsic() const return true; } - case NI_Vector128_get_Zero: - case NI_Vector256_get_Zero: - { - // These HWIntrinsic operations are contained as part of Sse41.Insert - return true; - } - case NI_SSE3_MoveAndDuplicate: case NI_AVX_BroadcastScalarToVector128: case NI_AVX2_BroadcastScalarToVector128: @@ -20383,31 +20384,45 @@ bool GenTree::isRMWHWIntrinsic(Compiler* comp) // bool GenTree::isEvexCompatibleHWIntrinsic() const { - // TODO-XARCH-AVX512 remove the ReturnsPerElementMask check once K registers have been properly - // implemented in the register allocator - return OperIsHWIntrinsic() && HWIntrinsicInfo::HasEvexSemantics(AsHWIntrinsic()->GetHWIntrinsicId()) && - !HWIntrinsicInfo::ReturnsPerElementMask(AsHWIntrinsic()->GetHWIntrinsicId()); + return OperIsHWIntrinsic() && HWIntrinsicInfo::HasEvexSemantics(AsHWIntrinsic()->GetHWIntrinsicId()); } //------------------------------------------------------------------------ -// isEvexEmbeddedMaskingCompatibleHWIntrinsic: Checks if the intrinsic is compatible +// isEmbeddedMaskingCompatibleHWIntrinsic : Checks if the intrinsic is compatible // with the EVEX embedded masking form for its intended lowering instruction. // // Return Value: // true if the intrisic node lowering instruction has an EVEX embedded masking // -bool GenTree::isEvexEmbeddedMaskingCompatibleHWIntrinsic() const +bool GenTree::isEmbeddedMaskingCompatibleHWIntrinsic() const { -#if defined(TARGET_XARCH) if (OperIsHWIntrinsic()) { - // TODO-AVX512F-CQ: Expand this to the full set of APIs and make it table driven - // using IsEmbMaskingCompatible. For now, however, limit it to some explicit ids - // for prototyping purposes. - return (AsHWIntrinsic()->GetHWIntrinsicId() == NI_AVX512F_Add); - } -#endif // TARGET_XARCH +#if defined(TARGET_XARCH) + NamedIntrinsic intrinsicId = AsHWIntrinsic()->GetHWIntrinsicId(); + var_types simdBaseType = AsHWIntrinsic()->GetSimdBaseType(); + + switch (intrinsicId) + { + case NI_AVX512F_ConvertToVector256Int32: + case NI_AVX512F_ConvertToVector256UInt32: + case NI_AVX512F_ConvertToVector512Int32: + case NI_AVX512F_ConvertToVector512UInt32: + case NI_AVX512F_VL_ConvertToVector128UInt32: + { + return varTypeIsFloating(simdBaseType); + } + default: + { + return HWIntrinsicInfo::IsEmbMaskingCompatible(intrinsicId); + } + } +#elif defined(TARGET_ARM64) + return HWIntrinsicInfo::IsEmbeddedMaskedOperation(AsHWIntrinsic()->GetHWIntrinsicId()) || + HWIntrinsicInfo::IsOptionalEmbeddedMaskedOperation(AsHWIntrinsic()->GetHWIntrinsicId()); +#endif + } return false; } @@ -21831,7 +21846,6 @@ GenTree* Compiler::gtNewSimdCeilNode(var_types type, GenTree* op1, CorInfoType s return gtNewSimdHWIntrinsicNode(type, op1, intrinsic, simdBaseJitType, simdSize); } -#if defined(TARGET_XARCH) GenTree* Compiler::gtNewSimdCvtNode(var_types type, GenTree* op1, CorInfoType simdTargetBaseJitType, @@ -21849,12 +21863,128 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, assert(varTypeIsIntegral(simdTargetBaseType)); assert(IsBaselineSimdIsaSupportedDebugOnly()); + +#if defined(TARGET_XARCH) assert(IsBaselineVector512IsaSupportedDebugOnly() || ((simdTargetBaseType == TYP_INT) && ((simdSize == 16 && compIsaSupportedDebugOnly(InstructionSet_SSE41)) || (simdSize == 32 && compIsaSupportedDebugOnly(InstructionSet_AVX))))); + GenTree* fixupVal; + + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + /*Generate the control table for VFIXUPIMMSD/SS + - For conversion to unsigned + // QNAN: 0b1000: Saturate to Zero + // SNAN: 0b1000: Saturate to Zero + // ZERO: 0b0000 + // +ONE: 0b0000 + // -INF: 0b1000: Saturate to Zero + // +INF: 0b0000 + // -VAL: 0b1000: Saturate to Zero + // +VAL: 0b0000 + - For conversion to signed + // QNAN: 0b1000: Saturate to Zero + // SNAN: 0b1000: Saturate to Zero + // ZERO: 0b0000 + // +ONE: 0b0000 + // -INF: 0b0000 + // +INF: 0b0000 + // -VAL: 0b0000 + // +VAL: 0b0000 + */ + int32_t iconVal = varTypeIsUnsigned(simdTargetBaseType) ? 0x08080088 : 0x00000088; + GenTree* tblCon = gtNewSimdCreateBroadcastNode(type, gtNewIconNode(iconVal), simdTargetBaseJitType, simdSize); + + // We need op1Clone to run fixup + GenTree* op1Clone = fgMakeMultiUse(&op1); + + // run vfixupimmsd base on table and no flags reporting + fixupVal = gtNewSimdHWIntrinsicNode(type, op1, op1Clone, tblCon, gtNewIconNode(0), NI_AVX512F_Fixup, + simdSourceBaseJitType, simdSize); + } + else + { + // Zero out NaN values from the input. + // mask1 contains the output either 0xFFFFFFFF or 0. + // FixupVal zeros out any NaN values in the input by ANDing input with mask1. + GenTree* op1Clone1 = fgMakeMultiUse(&op1); + GenTree* op1Clone2 = fgMakeMultiUse(&op1); + GenTree* mask1 = gtNewSimdCmpOpNode(GT_EQ, type, op1, op1Clone1, simdSourceBaseJitType, simdSize); + fixupVal = gtNewSimdBinOpNode(GT_AND, type, op1Clone2, mask1, simdSourceBaseJitType, simdSize); + } + + if (varTypeIsSigned(simdTargetBaseType)) + { + GenTree* maxVal; + GenTree* maxValDup; + if (varTypeIsLong(simdTargetBaseType)) + { + int64_t actualMaxVal = INT64_MAX; + maxVal = gtNewDconNode(static_cast(actualMaxVal), simdSourceBaseType); + maxVal = gtNewSimdCreateBroadcastNode(type, maxVal, simdSourceBaseJitType, simdSize); + maxValDup = + gtNewSimdCreateBroadcastNode(type, gtNewLconNode(actualMaxVal), simdTargetBaseJitType, simdSize); + } + else + { + ssize_t actualMaxVal = INT32_MAX; + maxVal = gtNewDconNode(static_cast(actualMaxVal), simdSourceBaseType); + maxVal = gtNewSimdCreateBroadcastNode(type, maxVal, simdSourceBaseJitType, simdSize); + maxValDup = + gtNewSimdCreateBroadcastNode(type, gtNewIconNode(actualMaxVal), simdTargetBaseJitType, simdSize); + } + + // we will be using the input value twice + GenTree* fixupValDup = fgMakeMultiUse(&fixupVal); + + // compare with max value of integer/long + fixupVal = gtNewSimdCmpOpNode(GT_GE, type, fixupVal, maxVal, simdSourceBaseJitType, simdSize); + + // cast it + GenTree* castNode = + gtNewSimdCvtNativeNode(type, fixupValDup, simdTargetBaseJitType, simdSourceBaseJitType, simdSize); + + // use the fixupVal mask with input value and max value to blend + return gtNewSimdCndSelNode(type, fixupVal, maxValDup, castNode, simdTargetBaseJitType, simdSize); + } + else + { + return gtNewSimdCvtNativeNode(type, fixupVal, simdTargetBaseJitType, simdSourceBaseJitType, simdSize); + } +#elif defined(TARGET_ARM64) + return gtNewSimdCvtNativeNode(type, op1, simdTargetBaseJitType, simdSourceBaseJitType, simdSize); +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 +} + +GenTree* Compiler::gtNewSimdCvtNativeNode(var_types type, + GenTree* op1, + CorInfoType simdTargetBaseJitType, + CorInfoType simdSourceBaseJitType, + unsigned simdSize) +{ + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdSourceBaseType = JitType2PreciseVarType(simdSourceBaseJitType); + var_types simdTargetBaseType = JitType2PreciseVarType(simdTargetBaseJitType); + assert(varTypeIsFloating(simdSourceBaseType)); + assert(varTypeIsIntegral(simdTargetBaseType)); + + assert(IsBaselineSimdIsaSupportedDebugOnly()); + // Generate intrinsic needed for conversion NamedIntrinsic hwIntrinsicID = NI_Illegal; + +#if defined(TARGET_XARCH) + assert(IsBaselineVector512IsaSupportedDebugOnly() || + ((simdTargetBaseType == TYP_INT) && + ((simdSize == 16) || (simdSize == 32 && compIsaSupportedDebugOnly(InstructionSet_AVX))))); + switch (simdSourceBaseJitType) { case CORINFO_TYPE_FLOAT: @@ -21870,21 +22000,25 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, hwIntrinsicID = NI_AVX512F_ConvertToVector512Int32WithTruncation; break; } + case 32: { hwIntrinsicID = NI_AVX_ConvertToVector256Int32WithTruncation; break; } + case 16: { hwIntrinsicID = NI_SSE2_ConvertToVector128Int32WithTruncation; break; } + default: unreached(); } break; } + case CORINFO_TYPE_UINT: { switch (simdSize) @@ -21894,26 +22028,31 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, hwIntrinsicID = NI_AVX512F_ConvertToVector512UInt32WithTruncation; break; } + case 32: { hwIntrinsicID = NI_AVX512F_VL_ConvertToVector256UInt32WithTruncation; break; } + case 16: { hwIntrinsicID = NI_AVX512F_VL_ConvertToVector128UInt32WithTruncation; break; } + default: unreached(); } break; } + default: unreached(); } break; } + case CORINFO_TYPE_DOUBLE: { switch (simdTargetBaseJitType) @@ -21927,21 +22066,25 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, hwIntrinsicID = NI_AVX512DQ_ConvertToVector512Int64WithTruncation; break; } + case 32: { hwIntrinsicID = NI_AVX512DQ_VL_ConvertToVector256Int64WithTruncation; break; } + case 16: { hwIntrinsicID = NI_AVX512DQ_VL_ConvertToVector128Int64WithTruncation; break; } + default: unreached(); } break; } + case CORINFO_TYPE_ULONG: { switch (simdSize) @@ -21951,115 +22094,95 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, hwIntrinsicID = NI_AVX512DQ_ConvertToVector512UInt64WithTruncation; break; } + case 32: { hwIntrinsicID = NI_AVX512DQ_VL_ConvertToVector256UInt64WithTruncation; break; } + case 16: { hwIntrinsicID = NI_AVX512DQ_VL_ConvertToVector128UInt64WithTruncation; break; } + default: unreached(); } break; } + default: unreached(); } break; } + default: unreached(); } - assert(hwIntrinsicID != NI_Illegal); - - GenTree* fixupVal; +#elif defined(TARGET_ARM64) + assert((simdSize == 8) || (simdSize == 16)); - if (IsBaselineVector512IsaSupportedOpportunistically()) + switch (simdSourceBaseJitType) { - /*Generate the control table for VFIXUPIMMSD/SS - - For conversion to unsigned - // QNAN: 0b1000: Saturate to Zero - // SNAN: 0b1000: Saturate to Zero - // ZERO: 0b0000 - // +ONE: 0b0000 - // -INF: 0b1000: Saturate to Zero - // +INF: 0b0000 - // -VAL: 0b1000: Saturate to Zero - // +VAL: 0b0000 - - For conversion to signed - // QNAN: 0b1000: Saturate to Zero - // SNAN: 0b1000: Saturate to Zero - // ZERO: 0b0000 - // +ONE: 0b0000 - // -INF: 0b0000 - // +INF: 0b0000 - // -VAL: 0b0000 - // +VAL: 0b0000 - */ - int32_t iconVal = varTypeIsUnsigned(simdTargetBaseType) ? 0x08080088 : 0x00000088; - GenTree* tblCon = gtNewSimdCreateBroadcastNode(type, gtNewIconNode(iconVal), simdTargetBaseJitType, simdSize); - - // We need op1Clone to run fixup - GenTree* op1Clone = fgMakeMultiUse(&op1); + case CORINFO_TYPE_FLOAT: + { + switch (simdTargetBaseJitType) + { + case CORINFO_TYPE_INT: + { + hwIntrinsicID = NI_AdvSimd_ConvertToInt32RoundToZero; + break; + } - // run vfixupimmsd base on table and no flags reporting - fixupVal = gtNewSimdHWIntrinsicNode(type, op1, op1Clone, tblCon, gtNewIconNode(0), NI_AVX512F_Fixup, - simdSourceBaseJitType, simdSize); - } - else - { - // Zero out NaN values from the input. - // mask1 contains the output either 0xFFFFFFFF or 0. - // FixupVal zeros out any NaN values in the input by ANDing input with mask1. - GenTree* op1Clone1 = fgMakeMultiUse(&op1); - GenTree* op1Clone2 = fgMakeMultiUse(&op1); - GenTree* mask1 = gtNewSimdCmpOpNode(GT_EQ, type, op1, op1Clone1, simdSourceBaseJitType, simdSize); - fixupVal = gtNewSimdBinOpNode(GT_AND, type, op1Clone2, mask1, simdSourceBaseJitType, simdSize); - } + case CORINFO_TYPE_UINT: + { + hwIntrinsicID = NI_AdvSimd_ConvertToUInt32RoundToZero; + break; + } - if (varTypeIsSigned(simdTargetBaseType)) - { - GenTree* maxVal; - GenTree* maxValDup; - if (varTypeIsLong(simdTargetBaseType)) - { - int64_t actualMaxVal = INT64_MAX; - maxVal = gtNewDconNode(static_cast(actualMaxVal), simdSourceBaseType); - maxVal = gtNewSimdCreateBroadcastNode(type, maxVal, simdSourceBaseJitType, simdSize); - maxValDup = - gtNewSimdCreateBroadcastNode(type, gtNewLconNode(actualMaxVal), simdTargetBaseJitType, simdSize); - } - else - { - ssize_t actualMaxVal = INT32_MAX; - maxVal = gtNewDconNode(static_cast(actualMaxVal), simdSourceBaseType); - maxVal = gtNewSimdCreateBroadcastNode(type, maxVal, simdSourceBaseJitType, simdSize); - maxValDup = - gtNewSimdCreateBroadcastNode(type, gtNewIconNode(actualMaxVal), simdTargetBaseJitType, simdSize); + default: + unreached(); + } + break; } - // we will be using the input value twice - GenTree* fixupValDup = fgMakeMultiUse(&fixupVal); + case CORINFO_TYPE_DOUBLE: + { + switch (simdTargetBaseJitType) + { + case CORINFO_TYPE_LONG: + { + hwIntrinsicID = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToInt64RoundToZeroScalar + : NI_AdvSimd_Arm64_ConvertToInt64RoundToZero; + break; + } - // compare with max value of integer/long - fixupVal = gtNewSimdCmpOpNode(GT_GE, type, fixupVal, maxVal, simdSourceBaseJitType, simdSize); + case CORINFO_TYPE_ULONG: + { + hwIntrinsicID = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToUInt64RoundToZeroScalar + : NI_AdvSimd_Arm64_ConvertToUInt64RoundToZero; + break; + } - // cast it - GenTree* castNode = gtNewSimdHWIntrinsicNode(type, fixupValDup, hwIntrinsicID, simdSourceBaseJitType, simdSize); + default: + unreached(); + } + break; + } - // use the fixupVal mask with input value and max value to blend - return gtNewSimdCndSelNode(type, fixupVal, maxValDup, castNode, simdTargetBaseJitType, simdSize); - } - else - { - return gtNewSimdHWIntrinsicNode(type, fixupVal, hwIntrinsicID, simdSourceBaseJitType, simdSize); + default: + unreached(); } +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + + assert(hwIntrinsicID != NI_Illegal); + return gtNewSimdHWIntrinsicNode(type, op1, hwIntrinsicID, simdSourceBaseJitType, simdSize); } -#endif // TARGET_XARCH GenTree* Compiler::gtNewSimdCmpOpNode( genTreeOps op, var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) @@ -23754,6 +23877,61 @@ GenTree* Compiler::gtNewSimdFloorNode(var_types type, GenTree* op1, CorInfoType return gtNewSimdHWIntrinsicNode(type, op1, intrinsic, simdBaseJitType, simdSize); } +GenTree* Compiler::gtNewSimdFmaNode( + var_types type, GenTree* op1, GenTree* op2, GenTree* op3, CorInfoType simdBaseJitType, unsigned simdSize) +{ + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + assert(op2 != nullptr); + assert(op2->TypeIs(type)); + + assert(op3 != nullptr); + assert(op3->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsFloating(simdBaseType)); + + NamedIntrinsic intrinsic = NI_Illegal; + +#if defined(TARGET_XARCH) + if (simdSize == 64) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX512F)); + intrinsic = NI_AVX512F_FusedMultiplyAdd; + } + else + { + assert(compIsaSupportedDebugOnly(InstructionSet_FMA)); + intrinsic = NI_FMA_MultiplyAdd; + } +#elif defined(TARGET_ARM64) + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + if (simdBaseType == TYP_DOUBLE) + { + intrinsic = (simdSize == 8) ? NI_AdvSimd_FusedMultiplyAddScalar : NI_AdvSimd_Arm64_FusedMultiplyAdd; + } + else + { + intrinsic = NI_AdvSimd_FusedMultiplyAdd; + } + + // AdvSimd.FusedMultiplyAdd expects (addend, left, right), while the APIs take (left, right, addend) + // We expect op1 and op2 to have already been spilled + + std::swap(op1, op3); +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + + assert(intrinsic != NI_Illegal); + return gtNewSimdHWIntrinsicNode(type, op1, op2, op3, intrinsic, simdBaseJitType, simdSize); +} + GenTree* Compiler::gtNewSimdGetElementNode( var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) { @@ -26879,6 +27057,30 @@ bool GenTreeHWIntrinsic::OperIsMemoryLoad(GenTree** pAddr) const break; case NI_Sve_LoadVector: + case NI_Sve_LoadVectorByteZeroExtendToInt16: + case NI_Sve_LoadVectorByteZeroExtendToInt32: + case NI_Sve_LoadVectorByteZeroExtendToInt64: + case NI_Sve_LoadVectorByteZeroExtendToUInt16: + case NI_Sve_LoadVectorByteZeroExtendToUInt32: + case NI_Sve_LoadVectorByteZeroExtendToUInt64: + case NI_Sve_LoadVectorInt16SignExtendToInt32: + case NI_Sve_LoadVectorInt16SignExtendToInt64: + case NI_Sve_LoadVectorInt16SignExtendToUInt32: + case NI_Sve_LoadVectorInt16SignExtendToUInt64: + case NI_Sve_LoadVectorInt32SignExtendToInt64: + case NI_Sve_LoadVectorInt32SignExtendToUInt64: + case NI_Sve_LoadVectorSByteSignExtendToInt16: + case NI_Sve_LoadVectorSByteSignExtendToInt32: + case NI_Sve_LoadVectorSByteSignExtendToInt64: + case NI_Sve_LoadVectorSByteSignExtendToUInt16: + case NI_Sve_LoadVectorSByteSignExtendToUInt32: + case NI_Sve_LoadVectorSByteSignExtendToUInt64: + case NI_Sve_LoadVectorUInt16ZeroExtendToInt32: + case NI_Sve_LoadVectorUInt16ZeroExtendToInt64: + case NI_Sve_LoadVectorUInt16ZeroExtendToUInt32: + case NI_Sve_LoadVectorUInt16ZeroExtendToUInt64: + case NI_Sve_LoadVectorUInt32ZeroExtendToInt64: + case NI_Sve_LoadVectorUInt32ZeroExtendToUInt64: addr = Op(2); break; #endif // TARGET_ARM64 @@ -27085,7 +27287,23 @@ bool GenTreeHWIntrinsic::OperIsMemoryStoreOrBarrier() const bool GenTreeHWIntrinsic::OperIsEmbBroadcastCompatible() const { #if defined(TARGET_XARCH) - return HWIntrinsicInfo::IsEmbBroadcastCompatible(GetHWIntrinsicId()); + NamedIntrinsic intrinsicId = GetHWIntrinsicId(); + var_types simdBaseType = GetSimdBaseType(); + + switch (intrinsicId) + { + case NI_AVX512F_ConvertToVector256Int32: + case NI_AVX512F_ConvertToVector256UInt32: + case NI_AVX512F_VL_ConvertToVector128UInt32: + { + return varTypeIsFloating(simdBaseType); + } + + default: + { + return !varTypeIsSmall(simdBaseType) && HWIntrinsicInfo::IsEmbBroadcastCompatible(intrinsicId); + } + } #else return false; #endif // TARGET_XARCH @@ -27404,6 +27622,9 @@ void GenTreeHWIntrinsic::SetHWIntrinsicId(NamedIntrinsic intrinsicId) // We'll choose to trust the programmer here. assert((oldOperandCount == static_cast(newOperandCount)) || newCountUnknown); + + // All ids being set must be valid + assert(!HWIntrinsicInfo::IsInvalidNodeId(intrinsicId)); #endif // DEBUG gtHWIntrinsicId = intrinsicId; @@ -27567,7 +27788,7 @@ genTreeOps GenTreeHWIntrinsic::HWOperGet() const GenTree* Compiler::gtNewMustThrowException(unsigned helper, var_types type, CORINFO_CLASS_HANDLE clsHnd) { GenTreeCall* node = gtNewHelperCallNode(helper, TYP_VOID); - node->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN; + assert(node->IsNoReturn()); if (type != TYP_VOID) { unsigned dummyTemp = lvaGrabTemp(true DEBUGARG("dummy temp of must thrown exception")); @@ -28066,75 +28287,14 @@ regMaskTP ReturnTypeDesc::GetABIReturnRegs(CorInfoCallConvExtension callConv) co } //------------------------------------------------------------------------ -// The following functions manage the gtRsvdRegs set of temporary registers -// created by LSRA during code generation. - -//------------------------------------------------------------------------ -// AvailableTempRegCount: return the number of available temporary registers in the (optional) given set -// (typically, RBM_ALLINT or RBM_ALLFLOAT). -// -// Arguments: -// mask - (optional) Check for available temporary registers only in this set. -// -// Return Value: -// Count of available temporary registers in given set. -// -unsigned GenTree::AvailableTempRegCount(regMaskTP mask /* = (regMaskTP)-1 */) const -{ - return genCountBits(gtRsvdRegs & mask); -} - -//------------------------------------------------------------------------ -// GetSingleTempReg: There is expected to be exactly one available temporary register -// in the given mask in the gtRsvdRegs set. Get that register. No future calls to get -// a temporary register are expected. Removes the register from the set, but only in -// DEBUG to avoid doing unnecessary work in non-DEBUG builds. -// -// Arguments: -// mask - (optional) Get an available temporary register only in this set. -// -// Return Value: -// Available temporary register in given mask. -// -regNumber GenTree::GetSingleTempReg(regMaskTP mask /* = (regMaskTP)-1 */) -{ - regMaskTP availableSet = gtRsvdRegs & mask; - assert(genCountBits(availableSet) == 1); - regNumber tempReg = genRegNumFromMask(availableSet); - INDEBUG(gtRsvdRegs &= ~availableSet;) // Remove the register from the set, so it can't be used again. - return tempReg; -} - -//------------------------------------------------------------------------ -// ExtractTempReg: Find the lowest number temporary register from the gtRsvdRegs set -// that is also in the optional given mask (typically, RBM_ALLINT or RBM_ALLFLOAT), -// and return it. Remove this register from the temporary register set, so it won't -// be returned again. -// -// Arguments: -// mask - (optional) Extract an available temporary register only in this set. -// -// Return Value: -// Available temporary register in given mask. -// -regNumber GenTree::ExtractTempReg(regMaskTP mask /* = (regMaskTP)-1 */) -{ - regMaskTP availableSet = gtRsvdRegs & mask; - assert(genCountBits(availableSet) >= 1); - regNumber tempReg = genFirstRegNumFromMask(availableSet); - gtRsvdRegs ^= genRegMask(tempReg); - return tempReg; -} - -//------------------------------------------------------------------------ -// GetNum: Get the SSA number for a given field. +// GetNum: Get the SSA number for a given field. // -// Arguments: -// compiler - The Compiler instance -// index - The field index +// Arguments: +// compiler - The Compiler instance +// index - The field index // -// Return Value: -// The SSA number corresponding to the field at "index". +// Return Value: +// The SSA number corresponding to the field at "index". // unsigned SsaNumInfo::GetNum(Compiler* compiler, unsigned index) const { @@ -28339,7 +28499,7 @@ bool GenTreeLclVar::IsNeverNegative(Compiler* comp) const return comp->lvaGetDesc(GetLclNum())->IsNeverNegative(); } -#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) +#if (defined(TARGET_XARCH) || defined(TARGET_ARM64)) && defined(FEATURE_HW_INTRINSICS) //------------------------------------------------------------------------ // GetResultOpNumForRmwIntrinsic: check if the result is written into one of the operands. // In the case that none of the operand is overwritten, check if any of them is lastUse. @@ -28350,7 +28510,11 @@ bool GenTreeLclVar::IsNeverNegative(Compiler* comp) const // unsigned GenTreeHWIntrinsic::GetResultOpNumForRmwIntrinsic(GenTree* use, GenTree* op1, GenTree* op2, GenTree* op3) { +#if defined(TARGET_XARCH) assert(HWIntrinsicInfo::IsFmaIntrinsic(gtHWIntrinsicId) || HWIntrinsicInfo::IsPermuteVar2x(gtHWIntrinsicId)); +#elif defined(TARGET_ARM64) + assert(HWIntrinsicInfo::IsFmaIntrinsic(gtHWIntrinsicId)); +#endif if (use != nullptr && use->OperIs(GT_STORE_LCL_VAR)) { diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index daaa0051e41a..0239a7193af5 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -173,7 +173,7 @@ enum TargetHandleType : BYTE /*****************************************************************************/ struct BasicBlock; -enum BasicBlockFlags : unsigned __int64; +enum BasicBlockFlags : uint64_t; struct InlineCandidateInfo; struct HandleHistogramProfileCandidateInfo; struct LateDevirtualizationInfo; @@ -559,9 +559,9 @@ enum GenTreeFlags : unsigned int GTF_MDARRLOWERBOUND_NONFAULTING = 0x20000000, // GT_MDARR_LOWER_BOUND -- An MD array lower bound operation that cannot fault. Same as GT_IND_NONFAULTING. -#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) +#ifdef FEATURE_HW_INTRINSICS GTF_HW_EM_OP = 0x10000000, // GT_HWINTRINSIC -- node is used as an operand to an embedded mask -#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS +#endif // FEATURE_HW_INTRINSICS }; inline constexpr GenTreeFlags operator ~(GenTreeFlags a) @@ -958,12 +958,6 @@ struct GenTree ValueNumPair gtVNPair; - regMaskSmall gtRsvdRegs; // set of fixed trashed registers - - unsigned AvailableTempRegCount(regMaskTP mask = (regMaskTP)-1) const; - regNumber GetSingleTempReg(regMaskTP mask = (regMaskTP)-1); - regNumber ExtractTempReg(regMaskTP mask = (regMaskTP)-1); - void SetVNsFromNode(GenTree* tree) { gtVNPair = tree->gtVNPair; @@ -1467,7 +1461,7 @@ struct GenTree bool isContainableHWIntrinsic() const; bool isRMWHWIntrinsic(Compiler* comp); bool isEvexCompatibleHWIntrinsic() const; - bool isEvexEmbeddedMaskingCompatibleHWIntrinsic() const; + bool isEmbeddedMaskingCompatibleHWIntrinsic() const; #else bool isCommutativeHWIntrinsic() const { @@ -1489,7 +1483,7 @@ struct GenTree return false; } - bool isEvexEmbeddedMaskingCompatibleHWIntrinsic() const + bool isEmbeddedMaskingCompatibleHWIntrinsic() const { return false; } @@ -1740,6 +1734,9 @@ struct GenTree #endif // defined(TARGET_ARM64) return true; + + case GT_SWIFT_ERROR_RET: + return (gtType == TYP_VOID); default: return false; } @@ -1769,6 +1766,7 @@ struct GenTree inline bool IsVectorZero() const; inline bool IsVectorCreate() const; inline bool IsVectorAllBitsSet() const; + inline bool IsMaskAllBitsSet() const; inline bool IsVectorConst(); inline uint64_t GetIntegralVectorConstElement(size_t index, var_types simdBaseType); @@ -2225,7 +2223,7 @@ struct GenTree gtFlags &= ~GTF_ICON_HDL_MASK; } -#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) +#ifdef FEATURE_HW_INTRINSICS bool IsEmbMaskOp() { @@ -2239,7 +2237,7 @@ struct GenTree gtFlags |= GTF_HW_EM_OP; } -#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS +#endif // FEATURE_HW_INTRINSICS static bool HandleKindDataIsInvariant(GenTreeFlags flags); @@ -3039,6 +3037,34 @@ struct GenTreeOp : public GenTreeUnOp // then sets the flag GTF_DIV_BY_CNS_OPT and GTF_DONT_CSE on the constant void CheckDivideByConstOptimized(Compiler* comp); + GenTree* GetReturnValue() const + { + assert(OperIs(GT_RETURN, GT_RETFILT, GT_SWIFT_ERROR_RET)); +#ifdef SWIFT_SUPPORT + if (OperIs(GT_SWIFT_ERROR_RET)) + { + return gtOp2; + } +#endif // SWIFT_SUPPORT + + return gtOp1; + } + + void SetReturnValue(GenTree* const retVal) + { + assert(OperIs(GT_RETURN, GT_RETFILT, GT_SWIFT_ERROR_RET)); +#ifdef SWIFT_SUPPORT + if (OperIs(GT_SWIFT_ERROR_RET)) + { + gtOp2 = retVal; + } + else +#endif // SWIFT_SUPPORT + { + gtOp1 = retVal; + } + } + #if !defined(TARGET_64BIT) || defined(TARGET_ARM64) bool IsValidLongMul(); #endif @@ -3358,8 +3384,8 @@ struct GenTreeDblCon : public GenTree bool isBitwiseEqual(GenTreeDblCon* other) { - unsigned __int64 bits = *(unsigned __int64*)(>DconVal); - unsigned __int64 otherBits = *(unsigned __int64*)(&(other->gtDconVal)); + uint64_t bits = *(uint64_t*)(>DconVal); + uint64_t otherBits = *(uint64_t*)(&(other->gtDconVal)); return (bits == otherBits); } @@ -4441,7 +4467,6 @@ enum class WellKnownArg : unsigned InstParam, RetBuffer, PInvokeFrame, - SecretStubParam, WrapperDelegateCell, ShiftLow, ShiftHigh, @@ -9258,6 +9283,32 @@ inline bool GenTree::IsVectorAllBitsSet() const return false; } +inline bool GenTree::IsMaskAllBitsSet() const +{ +#ifdef TARGET_ARM64 + static_assert_no_msg(AreContiguous(NI_Sve_CreateTrueMaskByte, NI_Sve_CreateTrueMaskDouble, + NI_Sve_CreateTrueMaskInt16, NI_Sve_CreateTrueMaskInt32, + NI_Sve_CreateTrueMaskInt64, NI_Sve_CreateTrueMaskSByte, + NI_Sve_CreateTrueMaskSingle, NI_Sve_CreateTrueMaskUInt16, + NI_Sve_CreateTrueMaskUInt32, NI_Sve_CreateTrueMaskUInt64)); + + if (OperIsHWIntrinsic()) + { + NamedIntrinsic id = AsHWIntrinsic()->GetHWIntrinsicId(); + if (id == NI_Sve_ConvertMaskToVector) + { + GenTree* op1 = AsHWIntrinsic()->Op(1); + assert(op1->OperIsHWIntrinsic()); + id = op1->AsHWIntrinsic()->GetHWIntrinsicId(); + } + return ((id == NI_Sve_CreateTrueMaskAll) || + ((id >= NI_Sve_CreateTrueMaskByte) && (id <= NI_Sve_CreateTrueMaskUInt64))); + } + +#endif + return false; +} + //------------------------------------------------------------------- // IsVectorConst: returns true if this node is a HWIntrinsic that represents a constant. // @@ -10025,7 +10076,7 @@ inline bool GenTree::IsCnsNonZeroFltOrDbl() const if (IsCnsFltOrDbl()) { double constValue = AsDblCon()->DconValue(); - return *(__int64*)&constValue != 0; + return *(int64_t*)&constValue != 0; } return false; @@ -10038,7 +10089,7 @@ inline bool GenTree::IsCnsVec() const inline bool GenTree::IsHelperCall() { - return OperGet() == GT_CALL && AsCall()->gtCallType == CT_HELPER; + return OperGet() == GT_CALL && AsCall()->IsHelperCall(); } inline var_types GenTree::CastFromType() diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h index 1d442f276737..2554bb22ef70 100644 --- a/src/coreclr/jit/gtlist.h +++ b/src/coreclr/jit/gtlist.h @@ -290,7 +290,9 @@ GTNODE(END_LFIN , GenTreeVal ,0,0,GTK_LEAF|GTK_NOVALUE) // End l // Swift interop-specific nodes: //----------------------------------------------------------------------------- -GTNODE(SWIFT_ERROR , GenTree ,0,0,GTK_LEAF) // Error register value post-Swift call +GTNODE(SWIFT_ERROR , GenTree ,0,0,GTK_LEAF) // Error register value post-Swift call +GTNODE(SWIFT_ERROR_RET , GenTreeOp ,0,1,GTK_BINOP|GTK_NOVALUE) // Returns normal return value, and SwiftError pseudolocal's value in REG_SWIFT_ERROR. + // op1 is the error value, and op2 is the return value (or null if the method returns void). //----------------------------------------------------------------------------- // Nodes used by Lower to generate a closer CPU representation of other nodes diff --git a/src/coreclr/jit/hashbv.cpp b/src/coreclr/jit/hashbv.cpp index 87acddf099bc..e2c69fcac03d 100644 --- a/src/coreclr/jit/hashbv.cpp +++ b/src/coreclr/jit/hashbv.cpp @@ -127,7 +127,7 @@ int countBitsInWord(unsigned int bits) return (int)bits; } -int countBitsInWord(unsigned __int64 bits) +int countBitsInWord(uint64_t bits) { bits = ((bits >> 1) & 0x5555555555555555) + (bits & 0x5555555555555555); bits = ((bits >> 2) & 0x3333333333333333) + (bits & 0x3333333333333333); diff --git a/src/coreclr/jit/hashbv.h b/src/coreclr/jit/hashbv.h index 561a1c5641e4..232c35d63945 100644 --- a/src/coreclr/jit/hashbv.h +++ b/src/coreclr/jit/hashbv.h @@ -24,8 +24,8 @@ #define BITS_PER_NODE (1 << LOG2_BITS_PER_NODE) #ifdef TARGET_AMD64 -typedef unsigned __int64 elemType; -typedef unsigned __int64 indexType; +typedef uint64_t elemType; +typedef uint64_t indexType; #else typedef unsigned int elemType; typedef unsigned int indexType; diff --git a/src/coreclr/jit/helperexpansion.cpp b/src/coreclr/jit/helperexpansion.cpp index 6c8251eee257..b9dca67a1356 100644 --- a/src/coreclr/jit/helperexpansion.cpp +++ b/src/coreclr/jit/helperexpansion.cpp @@ -307,9 +307,8 @@ bool Compiler::fgExpandRuntimeLookupsForCall(BasicBlock** pBlock, Statement* stm // null-check basic block GenTree* fastPathValue = gtNewIndir(TYP_I_IMPL, gtCloneExpr(slotPtrTree), GTF_IND_NONFAULTING); // Save dictionary slot to a local (to be used by fast path) - GenTree* fastPathValueClone = - opts.OptimizationEnabled() ? fgMakeMultiUse(&fastPathValue) : gtCloneExpr(fastPathValue); - GenTree* nullcheckOp = gtNewOperNode(GT_EQ, TYP_INT, fastPathValue, gtNewIconNode(0, TYP_I_IMPL)); + GenTree* fastPathValueClone = fgMakeMultiUse(&fastPathValue); + GenTree* nullcheckOp = gtNewOperNode(GT_EQ, TYP_INT, fastPathValue, gtNewIconNode(0, TYP_I_IMPL)); nullcheckOp->gtFlags |= GTF_RELOP_JMP_USED; // nullcheckBb conditionally jumps to fallbackBb, but we need to initialize fallbackBb last @@ -2440,7 +2439,7 @@ bool Compiler::fgLateCastExpansionForCall(BasicBlock** pBlock, Statement* stmt, if (typeCheckNotNeeded || (typeCheckFailedAction == TypeCheckFailedAction::CallHelper_AlwaysThrows)) { // fallback call is used only to throw InvalidCastException - call->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN; + setCallDoesNotReturn(call); fallbackBb = fgNewBBFromTreeAfter(BBJ_THROW, lastTypeCheckBb, call, debugInfo, true); } else if (typeCheckFailedAction == TypeCheckFailedAction::ReturnNull) diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index 53970ef4a746..e6b0e5fa72ff 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -1032,6 +1032,97 @@ struct HWIntrinsicSignatureReader final } }; +//------------------------------------------------------------------------ +// CheckHWIntrinsicImmRange: Check if an immediate is within the valid range +// +// Arguments: +// intrinsicId -- HW intrinsic id +// simdBaseJitType -- The base JIT type of SIMD type of the intrinsic +// immOp -- Immediate to check is within range +// mustExpand -- true if the intrinsic must expand to a GenTree*; otherwise, false +// immLowerBound -- the lower valid bound of the immediate +// immLowerBound -- the upper valid bound of the immediate +// hasFullRangeImm -- the range has all valid values. The immediate is always within range. +// useFallback [OUT] -- Only set if false is returned. A fallback can be used instead. +// +// Return Value: +// returns true if immOp is within range. Otherwise false. +// +bool Compiler::CheckHWIntrinsicImmRange(NamedIntrinsic intrinsic, + CorInfoType simdBaseJitType, + GenTree* immOp, + bool mustExpand, + int immLowerBound, + int immUpperBound, + bool hasFullRangeImm, + bool* useFallback) +{ + *useFallback = false; + + if (!hasFullRangeImm && immOp->IsCnsIntOrI()) + { + const int ival = (int)immOp->AsIntCon()->IconValue(); + bool immOutOfRange; +#ifdef TARGET_XARCH + if (HWIntrinsicInfo::isAVX2GatherIntrinsic(intrinsic)) + { + immOutOfRange = (ival != 1) && (ival != 2) && (ival != 4) && (ival != 8); + } + else +#endif + { + immOutOfRange = (ival < immLowerBound) || (ival > immUpperBound); + } + + if (immOutOfRange) + { + assert(!mustExpand); + // The imm-HWintrinsics that do not accept all imm8 values may throw + // ArgumentOutOfRangeException when the imm argument is not in the valid range + return false; + } + } + else if (!immOp->IsCnsIntOrI()) + { + if (HWIntrinsicInfo::NoJmpTableImm(intrinsic)) + { + *useFallback = true; + return false; + } +#if defined(TARGET_XARCH) + else if (HWIntrinsicInfo::MaybeNoJmpTableImm(intrinsic)) + { +#if defined(TARGET_X86) + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + + if (varTypeIsLong(simdBaseType)) + { + if (!mustExpand) + { + return false; + } + } + else +#endif // TARGET_XARCH + { + *useFallback = true; + return false; + } + } +#endif // TARGET_XARCH + else if (!mustExpand) + { + // When the imm-argument is not a constant and we are not being forced to expand, we need to + // return false so a GT_CALL to the intrinsic method is emitted instead. The + // intrinsic method is recursive and will be forced to expand, at which point + // we emit some less efficient fallback code. + return false; + } + } + + return true; +} + //------------------------------------------------------------------------ // impHWIntrinsic: Import a hardware intrinsic as a GT_HWINTRINSIC node if possible // @@ -1162,190 +1253,64 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, } var_types simdBaseType = TYP_UNKNOWN; - GenTree* immOp = nullptr; if (simdBaseJitType != CORINFO_TYPE_UNDEF) { simdBaseType = JitType2PreciseVarType(simdBaseJitType); } + const unsigned simdSize = HWIntrinsicInfo::lookupSimdSize(this, intrinsic, sig); + HWIntrinsicSignatureReader sigReader; sigReader.Read(info.compCompHnd, sig); -#ifdef TARGET_ARM64 - if ((intrinsic == NI_AdvSimd_Insert) || (intrinsic == NI_AdvSimd_InsertScalar) || - ((intrinsic >= NI_AdvSimd_LoadAndInsertScalar) && (intrinsic <= NI_AdvSimd_LoadAndInsertScalarVector64x4)) || - ((intrinsic >= NI_AdvSimd_Arm64_LoadAndInsertScalar) && - (intrinsic <= NI_AdvSimd_Arm64_LoadAndInsertScalarVector128x4))) - { - assert(sig->numArgs == 3); - immOp = impStackTop(1).val; - assert(HWIntrinsicInfo::isImmOp(intrinsic, immOp)); - } - else if (intrinsic == NI_AdvSimd_Arm64_InsertSelectedScalar) - { - // InsertSelectedScalar intrinsic has two immediate operands. - // Since all the remaining intrinsics on both platforms have only one immediate - // operand, in order to not complicate the shared logic even further we ensure here that - // 1) The second immediate operand immOp2 is constant and - // 2) its value belongs to [0, sizeof(op3) / sizeof(op3.BaseType)). - // If either is false, we should fallback to the managed implementation Insert(dst, dstIdx, Extract(src, - // srcIdx)). - // The check for the first immediate operand immOp will use the same logic as other intrinsics that have an - // immediate operand. - - GenTree* immOp2 = nullptr; - - assert(sig->numArgs == 4); - - immOp = impStackTop(2).val; - immOp2 = impStackTop().val; - - assert(HWIntrinsicInfo::isImmOp(intrinsic, immOp)); - assert(HWIntrinsicInfo::isImmOp(intrinsic, immOp2)); - - if (!immOp2->IsCnsIntOrI()) - { - assert(HWIntrinsicInfo::NoJmpTableImm(intrinsic)); - return impNonConstFallback(intrinsic, retType, simdBaseJitType); - } - - unsigned int otherSimdSize = 0; - CorInfoType otherBaseJitType = getBaseJitTypeAndSizeOfSIMDType(sigReader.op3ClsHnd, &otherSimdSize); - var_types otherBaseType = JitType2PreciseVarType(otherBaseJitType); - - assert(otherBaseJitType == simdBaseJitType); - - int immLowerBound2 = 0; - int immUpperBound2 = 0; - - HWIntrinsicInfo::lookupImmBounds(intrinsic, otherSimdSize, otherBaseType, &immLowerBound2, &immUpperBound2); + GenTree* immOp1 = nullptr; + GenTree* immOp2 = nullptr; + int immLowerBound = 0; + int immUpperBound = 0; + bool hasFullRangeImm = false; + bool useFallback = false; - const int immVal2 = (int)immOp2->AsIntCon()->IconValue(); + getHWIntrinsicImmOps(intrinsic, sig, &immOp1, &immOp2); - if ((immVal2 < immLowerBound2) || (immVal2 > immUpperBound2)) + // Validate the second immediate +#ifdef TARGET_ARM64 + if (immOp2 != nullptr) + { + unsigned immSimdSize = simdSize; + var_types immSimdBaseType = simdBaseType; + getHWIntrinsicImmTypes(intrinsic, sig, 2, simdBaseType, simdBaseJitType, sigReader.op2ClsHnd, + sigReader.op3ClsHnd, &immSimdSize, &immSimdBaseType); + HWIntrinsicInfo::lookupImmBounds(intrinsic, immSimdSize, immSimdBaseType, 2, &immLowerBound, &immUpperBound); + + if (!CheckHWIntrinsicImmRange(intrinsic, simdBaseJitType, immOp2, mustExpand, immLowerBound, immUpperBound, + false, &useFallback)) { - assert(!mustExpand); - return nullptr; + return useFallback ? impNonConstFallback(intrinsic, retType, simdBaseJitType) : nullptr; } } - else +#else + assert(immOp2 == nullptr); #endif - if ((sig->numArgs > 0) && HWIntrinsicInfo::isImmOp(intrinsic, impStackTop().val)) - { - // NOTE: The following code assumes that for all intrinsics - // taking an immediate operand, that operand will be last. - immOp = impStackTop().val; - } - - const unsigned simdSize = HWIntrinsicInfo::lookupSimdSize(this, intrinsic, sig); - - int immLowerBound = 0; - int immUpperBound = 0; - bool hasFullRangeImm = false; - if (immOp != nullptr) + // Validate the first immediate + if (immOp1 != nullptr) { -#ifdef TARGET_XARCH +#ifdef TARGET_ARM64 + unsigned immSimdSize = simdSize; + var_types immSimdBaseType = simdBaseType; + getHWIntrinsicImmTypes(intrinsic, sig, 1, simdBaseType, simdBaseJitType, sigReader.op2ClsHnd, + sigReader.op3ClsHnd, &immSimdSize, &immSimdBaseType); + HWIntrinsicInfo::lookupImmBounds(intrinsic, immSimdSize, immSimdBaseType, 1, &immLowerBound, &immUpperBound); +#else immUpperBound = HWIntrinsicInfo::lookupImmUpperBound(intrinsic); hasFullRangeImm = HWIntrinsicInfo::HasFullRangeImm(intrinsic); -#elif defined(TARGET_ARM64) - if (category == HW_Category_SIMDByIndexedElement) - { - CorInfoType indexedElementBaseJitType; - var_types indexedElementBaseType; - unsigned int indexedElementSimdSize = 0; - - if (numArgs == 3) - { - indexedElementBaseJitType = - getBaseJitTypeAndSizeOfSIMDType(sigReader.op2ClsHnd, &indexedElementSimdSize); - indexedElementBaseType = JitType2PreciseVarType(indexedElementBaseJitType); - } - else - { - assert(numArgs == 4); - indexedElementBaseJitType = - getBaseJitTypeAndSizeOfSIMDType(sigReader.op3ClsHnd, &indexedElementSimdSize); - indexedElementBaseType = JitType2PreciseVarType(indexedElementBaseJitType); - - if (intrinsic == NI_Dp_DotProductBySelectedQuadruplet) - { - assert(((simdBaseType == TYP_INT) && (indexedElementBaseType == TYP_BYTE)) || - ((simdBaseType == TYP_UINT) && (indexedElementBaseType == TYP_UBYTE))); - // The second source operand of sdot, udot instructions is an indexed 32-bit element. - indexedElementBaseJitType = simdBaseJitType; - indexedElementBaseType = simdBaseType; - } - } - - assert(indexedElementBaseType == simdBaseType); - HWIntrinsicInfo::lookupImmBounds(intrinsic, indexedElementSimdSize, simdBaseType, &immLowerBound, - &immUpperBound); - } - else - { - HWIntrinsicInfo::lookupImmBounds(intrinsic, simdSize, simdBaseType, &immLowerBound, &immUpperBound); - } #endif - if (!hasFullRangeImm && immOp->IsCnsIntOrI()) + if (!CheckHWIntrinsicImmRange(intrinsic, simdBaseJitType, immOp1, mustExpand, immLowerBound, immUpperBound, + hasFullRangeImm, &useFallback)) { - const int ival = (int)immOp->AsIntCon()->IconValue(); - bool immOutOfRange; -#ifdef TARGET_XARCH - if (HWIntrinsicInfo::isAVX2GatherIntrinsic(intrinsic)) - { - immOutOfRange = (ival != 1) && (ival != 2) && (ival != 4) && (ival != 8); - } - else -#endif - { - immOutOfRange = (ival < immLowerBound) || (ival > immUpperBound); - } - - if (immOutOfRange) - { - assert(!mustExpand); - // The imm-HWintrinsics that do not accept all imm8 values may throw - // ArgumentOutOfRangeException when the imm argument is not in the valid range - return nullptr; - } - } - else if (!immOp->IsCnsIntOrI()) - { - if (HWIntrinsicInfo::NoJmpTableImm(intrinsic)) - { - return impNonConstFallback(intrinsic, retType, simdBaseJitType); - } -#if defined(TARGET_XARCH) - else if (HWIntrinsicInfo::MaybeNoJmpTableImm(intrinsic)) - { -#if defined(TARGET_X86) - var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); - - if (varTypeIsLong(simdBaseType)) - { - if (!mustExpand) - { - return nullptr; - } - } - else -#endif // TARGET_XARCH - { - return impNonConstFallback(intrinsic, retType, simdBaseJitType); - } - } -#endif // TARGET_XARCH - else if (!mustExpand) - { - // When the imm-argument is not a constant and we are not being forced to expand, we need to - // return nullptr so a GT_CALL to the intrinsic method is emitted instead. The - // intrinsic method is recursive and will be forced to expand, at which point - // we emit some less efficient fallback code. - return nullptr; - } + return useFallback ? impNonConstFallback(intrinsic, retType, simdBaseJitType) : nullptr; } } @@ -1396,6 +1361,36 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, GenTree* op3 = nullptr; GenTree* op4 = nullptr; + switch (numArgs) + { + case 4: + op4 = getArgForHWIntrinsic(sigReader.GetOp4Type(), sigReader.op4ClsHnd); + op4 = addRangeCheckIfNeeded(intrinsic, op4, mustExpand, immLowerBound, immUpperBound); + op3 = getArgForHWIntrinsic(sigReader.GetOp3Type(), sigReader.op3ClsHnd); + op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd); + op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); + break; + + case 3: + op3 = getArgForHWIntrinsic(sigReader.GetOp3Type(), sigReader.op3ClsHnd); + op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd); + op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); + break; + + case 2: + op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd); + op2 = addRangeCheckIfNeeded(intrinsic, op2, mustExpand, immLowerBound, immUpperBound); + op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); + break; + + case 1: + op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); + break; + + default: + break; + } + switch (numArgs) { case 0: @@ -1407,8 +1402,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, case 1: { - op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); - if ((category == HW_Category_MemoryLoad) && op1->OperIs(GT_CAST)) { // Although the API specifies a pointer, if what we have is a BYREF, that's what @@ -1467,10 +1460,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, case 2: { - op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd); - op2 = addRangeCheckIfNeeded(intrinsic, op2, mustExpand, immLowerBound, immUpperBound); - op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); - retNode = isScalar ? gtNewScalarHWIntrinsicNode(nodeRetType, op1, op2, intrinsic) : gtNewSimdHWIntrinsicNode(nodeRetType, op1, op2, intrinsic, simdBaseJitType, simdSize); @@ -1515,6 +1504,17 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, } break; + case NI_Sve_CreateWhileLessThanMask8Bit: + case NI_Sve_CreateWhileLessThanOrEqualMask8Bit: + case NI_Sve_CreateWhileLessThanMask16Bit: + case NI_Sve_CreateWhileLessThanOrEqualMask16Bit: + case NI_Sve_CreateWhileLessThanMask32Bit: + case NI_Sve_CreateWhileLessThanOrEqualMask32Bit: + case NI_Sve_CreateWhileLessThanMask64Bit: + case NI_Sve_CreateWhileLessThanOrEqualMask64Bit: + retNode->AsHWIntrinsic()->SetAuxiliaryJitType(sigReader.op1JitType); + break; + default: break; } @@ -1524,10 +1524,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, case 3: { - op3 = getArgForHWIntrinsic(sigReader.GetOp3Type(), sigReader.op3ClsHnd); - op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd); - op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); - #ifdef TARGET_ARM64 if (intrinsic == NI_AdvSimd_LoadAndInsertScalar) { @@ -1569,12 +1565,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, case 4: { - op4 = getArgForHWIntrinsic(sigReader.GetOp4Type(), sigReader.op4ClsHnd); - op4 = addRangeCheckIfNeeded(intrinsic, op4, mustExpand, immLowerBound, immUpperBound); - op3 = getArgForHWIntrinsic(sigReader.GetOp3Type(), sigReader.op3ClsHnd); - op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd); - op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd); - assert(!isScalar); retNode = gtNewSimdHWIntrinsicNode(nodeRetType, op1, op2, op3, op4, intrinsic, simdBaseJitType, simdSize); @@ -1587,14 +1577,27 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, } else { - retNode = impSpecialIntrinsic(intrinsic, clsHnd, method, sig, simdBaseJitType, nodeRetType, simdSize); + retNode = + impSpecialIntrinsic(intrinsic, clsHnd, method, sig, simdBaseJitType, nodeRetType, simdSize, mustExpand); } #if defined(TARGET_ARM64) - if (HWIntrinsicInfo::IsMaskedOperation(intrinsic)) + if (HWIntrinsicInfo::IsExplicitMaskedOperation(intrinsic)) { assert(numArgs > 0); GenTree* op1 = retNode->AsHWIntrinsic()->Op(1); + if (intrinsic == NI_Sve_ConditionalSelect) + { + if (op1->IsVectorAllBitsSet() || op1->IsMaskAllBitsSet()) + { + return retNode->AsHWIntrinsic()->Op(2); + } + else if (op1->IsVectorZero()) + { + return retNode->AsHWIntrinsic()->Op(3); + } + } + if (!varTypeIsMask(op1)) { // Op1 input is a vector. HWInstrinsic requires a mask. diff --git a/src/coreclr/jit/hwintrinsic.h b/src/coreclr/jit/hwintrinsic.h index 5ca302e126f3..16c5b770ada4 100644 --- a/src/coreclr/jit/hwintrinsic.h +++ b/src/coreclr/jit/hwintrinsic.h @@ -58,7 +58,6 @@ enum HWIntrinsicCategory : uint8_t HW_Category_ShiftLeftByImmediate, HW_Category_ShiftRightByImmediate, HW_Category_SIMDByIndexedElement, - HW_Category_EnumPattern, // Helper intrinsics // - do not directly correspond to a instruction, such as Vector64.AllBitsSet @@ -83,9 +82,8 @@ enum HWIntrinsicFlag : unsigned int // - should be transformed in the compiler front-end, cannot reach CodeGen HW_Flag_NoCodeGen = 0x2, - // Multi-instruction - // - that one intrinsic can generate multiple instructions - HW_Flag_MultiIns = 0x4, + // The intrinsic is invalid as the ID of a gtNode + HW_Flag_InvalidNodeId = 0x4, // Select base type using the first argument type HW_Flag_BaseTypeFromFirstArg = 0x8, @@ -186,11 +184,18 @@ enum HWIntrinsicFlag : unsigned int HW_Flag_ReturnsPerElementMask = 0x10000, // The intrinsic uses a mask in arg1 to select elements present in the result - HW_Flag_MaskedOperation = 0x20000, + HW_Flag_ExplicitMaskedOperation = 0x20000, // The intrinsic uses a mask in arg1 to select elements present in the result, and must use a low register. HW_Flag_LowMaskedOperation = 0x40000, + // The intrinsic can optionally use a mask in arg1 to select elements present in the result, which is not present in + // the API call + HW_Flag_OptionalEmbeddedMaskedOperation = 0x80000, + + // The intrinsic uses a mask in arg1 to select elements present in the result, which is not present in the API call + HW_Flag_EmbeddedMaskedOperation = 0x100000, + #else #error Unsupported platform #endif @@ -211,22 +216,32 @@ enum HWIntrinsicFlag : unsigned int // The intrinsic is an RMW intrinsic HW_Flag_RmwIntrinsic = 0x1000000, - // The intrinsic is a FusedMultiplyAdd intrinsic - HW_Flag_FmaIntrinsic = 0x2000000, - // The intrinsic is a PermuteVar2x intrinsic - HW_Flag_PermuteVar2x = 0x4000000, + HW_Flag_PermuteVar2x = 0x2000000, // The intrinsic is an embedded broadcast compatible intrinsic - HW_Flag_EmbBroadcastCompatible = 0x8000000, + HW_Flag_EmbBroadcastCompatible = 0x4000000, // The intrinsic is an embedded rounding compatible intrinsic - HW_Flag_EmbRoundingCompatible = 0x10000000, + HW_Flag_EmbRoundingCompatible = 0x8000000, + + // The intrinsic is an embedded masking compatible intrinsic + HW_Flag_EmbMaskingCompatible = 0x10000000, +#elif defined(TARGET_ARM64) + + // The intrinsic has an enum operand. Using this implies HW_Flag_HasImmediateOperand. + HW_Flag_HasEnumOperand = 0x1000000, - // The intrinsic is an embedded masking incompatible intrinsic - HW_Flag_EmbMaskingIncompatible = 0x20000000, #endif // TARGET_XARCH + // The intrinsic is a FusedMultiplyAdd intrinsic + HW_Flag_FmaIntrinsic = 0x20000000, + +#if defined(TARGET_ARM64) + // The intrinsic uses a mask in arg1 to select elements present in the result, and must use a low vector register. + HW_Flag_LowVectorOperation = 0x4000000, +#endif + HW_Flag_CanBenefitFromConstantProp = 0x80000000, }; @@ -504,7 +519,7 @@ struct HWIntrinsicInfo static int lookupImmUpperBound(NamedIntrinsic intrinsic); #elif defined(TARGET_ARM64) static void lookupImmBounds( - NamedIntrinsic intrinsic, int simdSize, var_types baseType, int* lowerBound, int* upperBound); + NamedIntrinsic intrinsic, int simdSize, var_types baseType, int immNumber, int* lowerBound, int* upperBound); #else #error Unsupported platform #endif @@ -621,7 +636,7 @@ struct HWIntrinsicInfo static bool IsEmbMaskingCompatible(NamedIntrinsic id) { HWIntrinsicFlag flags = lookupFlags(id); - return (flags & HW_Flag_EmbMaskingIncompatible) == 0; + return (flags & HW_Flag_EmbMaskingCompatible) != 0; } #endif // TARGET_XARCH @@ -646,13 +661,7 @@ struct HWIntrinsicInfo static bool RequiresCodegen(NamedIntrinsic id) { HWIntrinsicFlag flags = lookupFlags(id); - return (flags & HW_Flag_NoCodeGen) == 0; - } - - static bool GeneratesMultipleIns(NamedIntrinsic id) - { - HWIntrinsicFlag flags = lookupFlags(id); - return (flags & HW_Flag_MultiIns) != 0; + return (flags & (HW_Flag_NoCodeGen | HW_Flag_InvalidNodeId)) == 0; } static bool SupportsContainment(NamedIntrinsic id) @@ -786,7 +795,13 @@ struct HWIntrinsicInfo static bool HasSpecialImport(NamedIntrinsic id) { HWIntrinsicFlag flags = lookupFlags(id); - return (flags & HW_Flag_SpecialImport) != 0; + return (flags & (HW_Flag_SpecialImport | HW_Flag_InvalidNodeId)) != 0; + } + + static bool IsInvalidNodeId(NamedIntrinsic id) + { + HWIntrinsicFlag flags = lookupFlags(id); + return (flags & HW_Flag_InvalidNodeId) != 0; } static bool IsMultiReg(NamedIntrinsic id) @@ -860,7 +875,7 @@ struct HWIntrinsicInfo static bool HasImmediateOperand(NamedIntrinsic id) { const HWIntrinsicFlag flags = lookupFlags(id); - return (flags & HW_Flag_HasImmediateOperand) != 0; + return ((flags & HW_Flag_HasImmediateOperand) != 0) || HasEnumOperand(id); } static bool IsScalable(NamedIntrinsic id) @@ -872,7 +887,7 @@ struct HWIntrinsicInfo static bool IsMaskedOperation(NamedIntrinsic id) { const HWIntrinsicFlag flags = lookupFlags(id); - return ((flags & HW_Flag_MaskedOperation) != 0) || IsLowMaskedOperation(id); + return IsLowMaskedOperation(id) || IsOptionalEmbeddedMaskedOperation(id) || IsExplicitMaskedOperation(id); } static bool IsLowMaskedOperation(NamedIntrinsic id) @@ -881,6 +896,36 @@ struct HWIntrinsicInfo return (flags & HW_Flag_LowMaskedOperation) != 0; } + static bool IsLowVectorOperation(NamedIntrinsic id) + { + const HWIntrinsicFlag flags = lookupFlags(id); + return (flags & HW_Flag_LowVectorOperation) != 0; + } + + static bool IsOptionalEmbeddedMaskedOperation(NamedIntrinsic id) + { + const HWIntrinsicFlag flags = lookupFlags(id); + return (flags & HW_Flag_OptionalEmbeddedMaskedOperation) != 0; + } + + static bool IsEmbeddedMaskedOperation(NamedIntrinsic id) + { + const HWIntrinsicFlag flags = lookupFlags(id); + return (flags & HW_Flag_EmbeddedMaskedOperation) != 0; + } + + static bool IsExplicitMaskedOperation(NamedIntrinsic id) + { + const HWIntrinsicFlag flags = lookupFlags(id); + return (flags & HW_Flag_ExplicitMaskedOperation) != 0; + } + + static bool HasEnumOperand(NamedIntrinsic id) + { + const HWIntrinsicFlag flags = lookupFlags(id); + return (flags & HW_Flag_HasEnumOperand) != 0; + } + #endif // TARGET_ARM64 static bool HasSpecialSideEffect(NamedIntrinsic id) @@ -901,17 +946,17 @@ struct HWIntrinsicInfo return (flags & HW_Flag_MaybeNoJmpTableIMM) != 0; } -#if defined(TARGET_XARCH) - static bool IsRmwIntrinsic(NamedIntrinsic id) + static bool IsFmaIntrinsic(NamedIntrinsic id) { HWIntrinsicFlag flags = lookupFlags(id); - return (flags & HW_Flag_RmwIntrinsic) != 0; + return (flags & HW_Flag_FmaIntrinsic) != 0; } - static bool IsFmaIntrinsic(NamedIntrinsic id) +#if defined(TARGET_XARCH) + static bool IsRmwIntrinsic(NamedIntrinsic id) { HWIntrinsicFlag flags = lookupFlags(id); - return (flags & HW_Flag_FmaIntrinsic) != 0; + return (flags & HW_Flag_RmwIntrinsic) != 0; } static bool IsPermuteVar2x(NamedIntrinsic id) @@ -949,7 +994,7 @@ struct HWIntrinsic final { // TODO-Arm64-Cleanup - make more categories to the table-driven framework bool isTableDrivenCategory = category != HW_Category_Helper; - bool isTableDrivenFlag = !HWIntrinsicInfo::GeneratesMultipleIns(id) && !HWIntrinsicInfo::HasSpecialCodegen(id); + bool isTableDrivenFlag = !HWIntrinsicInfo::HasSpecialCodegen(id); return isTableDrivenCategory && isTableDrivenFlag; } diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index 8e3288f75d70..5a2154c9d1cf 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -210,6 +210,152 @@ bool HWIntrinsicInfo::isScalarIsa(CORINFO_InstructionSet isa) } } +//------------------------------------------------------------------------ +// getHWIntrinsicImmOps: Gets the immediate Ops for an intrinsic +// +// Arguments: +// intrinsic -- NamedIntrinsic associated with the HWIntrinsic to lookup +// sig -- signature of the intrinsic call. +// immOp1Ptr [OUT] -- The first immediate Op +// immOp2Ptr [OUT] -- The second immediate Op, if any. Otherwise unchanged. +// +void Compiler::getHWIntrinsicImmOps(NamedIntrinsic intrinsic, + CORINFO_SIG_INFO* sig, + GenTree** immOp1Ptr, + GenTree** immOp2Ptr) +{ + if (!HWIntrinsicInfo::HasImmediateOperand(intrinsic)) + { + return; + } + + // Position of the immediates from top of stack + int imm1Pos = -1; + int imm2Pos = -1; + + switch (intrinsic) + { + case NI_AdvSimd_Insert: + case NI_AdvSimd_InsertScalar: + case NI_AdvSimd_LoadAndInsertScalar: + case NI_AdvSimd_LoadAndInsertScalarVector64x2: + case NI_AdvSimd_LoadAndInsertScalarVector64x3: + case NI_AdvSimd_LoadAndInsertScalarVector64x4: + case NI_AdvSimd_Arm64_LoadAndInsertScalar: + case NI_AdvSimd_Arm64_LoadAndInsertScalarVector128x2: + case NI_AdvSimd_Arm64_LoadAndInsertScalarVector128x3: + case NI_AdvSimd_Arm64_LoadAndInsertScalarVector128x4: + assert(sig->numArgs == 3); + imm1Pos = 1; + break; + + case NI_AdvSimd_Arm64_InsertSelectedScalar: + assert(sig->numArgs == 4); + imm1Pos = 2; + imm2Pos = 0; + break; + + default: + assert(sig->numArgs > 0); + imm1Pos = 0; + break; + } + + if (imm1Pos >= 0) + { + *immOp1Ptr = impStackTop(imm1Pos).val; + assert(HWIntrinsicInfo::isImmOp(intrinsic, *immOp1Ptr)); + } + + if (imm2Pos >= 0) + { + *immOp2Ptr = impStackTop(imm2Pos).val; + assert(HWIntrinsicInfo::isImmOp(intrinsic, *immOp2Ptr)); + } +} + +//------------------------------------------------------------------------ +// getHWIntrinsicImmTypes: Gets the type/size for an immediate for an intrinsic +// if it differs from the default type/size of the instrinsic +// +// Arguments: +// intrinsic -- NamedIntrinsic associated with the HWIntrinsic to lookup +// sig -- signature of the intrinsic call. +// immNumber -- Which immediate to use (1 for most intrinsics) +// simdBaseType -- base type of the intrinsic +// simdType -- vector size of the intrinsic +// op2ClsHnd -- cls handler for op2 +// op2ClsHnd -- cls handler for op3 +// immSimdSize [IN/OUT] -- Size of the immediate to override +// immSimdBaseType [IN/OUT] -- Base type of the immediate to override +// +void Compiler::getHWIntrinsicImmTypes(NamedIntrinsic intrinsic, + CORINFO_SIG_INFO* sig, + unsigned immNumber, + var_types simdBaseType, + CorInfoType simdBaseJitType, + CORINFO_CLASS_HANDLE op2ClsHnd, + CORINFO_CLASS_HANDLE op3ClsHnd, + unsigned* immSimdSize, + var_types* immSimdBaseType) +{ + HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsic); + + if (category == HW_Category_SIMDByIndexedElement) + { + assert(immNumber == 1); + + CorInfoType indexedElementBaseJitType; + var_types indexedElementBaseType; + *immSimdSize = 0; + + if (sig->numArgs == 3) + { + indexedElementBaseJitType = getBaseJitTypeAndSizeOfSIMDType(op2ClsHnd, immSimdSize); + indexedElementBaseType = JitType2PreciseVarType(indexedElementBaseJitType); + } + else + { + assert(sig->numArgs == 4); + indexedElementBaseJitType = getBaseJitTypeAndSizeOfSIMDType(op3ClsHnd, immSimdSize); + indexedElementBaseType = JitType2PreciseVarType(indexedElementBaseJitType); + + if (intrinsic == NI_Dp_DotProductBySelectedQuadruplet) + { + assert(((simdBaseType == TYP_INT) && (indexedElementBaseType == TYP_BYTE)) || + ((simdBaseType == TYP_UINT) && (indexedElementBaseType == TYP_UBYTE))); + // The second source operand of sdot, udot instructions is an indexed 32-bit element. + indexedElementBaseType = simdBaseType; + } + + if (intrinsic == NI_Sve_DotProductBySelectedScalar) + { + assert(((simdBaseType == TYP_INT) && (indexedElementBaseType == TYP_BYTE)) || + ((simdBaseType == TYP_UINT) && (indexedElementBaseType == TYP_UBYTE)) || + ((simdBaseType == TYP_LONG) && (indexedElementBaseType == TYP_SHORT)) || + ((simdBaseType == TYP_ULONG) && (indexedElementBaseType == TYP_USHORT))); + + // The second source operand of sdot, udot instructions is an indexed 32-bit element. + indexedElementBaseType = simdBaseType; + } + } + + assert(indexedElementBaseType == simdBaseType); + } + else if (intrinsic == NI_AdvSimd_Arm64_InsertSelectedScalar) + { + if (immNumber == 2) + { + CorInfoType otherBaseJitType = getBaseJitTypeAndSizeOfSIMDType(op3ClsHnd, immSimdSize); + *immSimdBaseType = JitType2PreciseVarType(otherBaseJitType); + assert(otherBaseJitType == simdBaseJitType); + } + // For imm1 use default simd sizes. + } + + // For all other imms, use default simd sizes +} + //------------------------------------------------------------------------ // lookupImmBounds: Gets the lower and upper bounds for the imm-value of a given NamedIntrinsic // @@ -217,11 +363,12 @@ bool HWIntrinsicInfo::isScalarIsa(CORINFO_InstructionSet isa) // intrinsic -- NamedIntrinsic associated with the HWIntrinsic to lookup // simdType -- vector size // baseType -- base type of the Vector64/128 +// immNumber -- which immediate operand to check for (most intrinsics only have one) // pImmLowerBound [OUT] - The lower incl. bound for a value of the intrinsic immediate operand // pImmUpperBound [OUT] - The upper incl. bound for a value of the intrinsic immediate operand // void HWIntrinsicInfo::lookupImmBounds( - NamedIntrinsic intrinsic, int simdSize, var_types baseType, int* pImmLowerBound, int* pImmUpperBound) + NamedIntrinsic intrinsic, int simdSize, var_types baseType, int immNumber, int* pImmLowerBound, int* pImmUpperBound) { HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsic); bool hasImmediateOperand = HasImmediateOperand(intrinsic); @@ -277,6 +424,8 @@ void HWIntrinsicInfo::lookupImmBounds( case NI_AdvSimd_Arm64_StoreSelectedScalarVector128x4: case NI_AdvSimd_Arm64_DuplicateSelectedScalarToVector128: case NI_AdvSimd_Arm64_InsertSelectedScalar: + case NI_Sve_FusedMultiplyAddBySelectedScalar: + case NI_Sve_FusedMultiplySubtractBySelectedScalar: immUpperBound = Compiler::getSIMDVectorLength(simdSize, baseType) - 1; break; @@ -290,6 +439,10 @@ void HWIntrinsicInfo::lookupImmBounds( case NI_Sve_CreateTrueMaskUInt16: case NI_Sve_CreateTrueMaskUInt32: case NI_Sve_CreateTrueMaskUInt64: + case NI_Sve_Count16BitElements: + case NI_Sve_Count32BitElements: + case NI_Sve_Count64BitElements: + case NI_Sve_Count8BitElements: immLowerBound = (int)SVE_PATTERN_POW2; immUpperBound = (int)SVE_PATTERN_ALL; break; @@ -331,6 +484,7 @@ GenTree* Compiler::impNonConstFallback(NamedIntrinsic intrinsic, var_types simdT // sig -- signature of the intrinsic call. // simdBaseJitType -- generic argument of the intrinsic. // retType -- return type of the intrinsic. +// mustExpand -- true if the intrinsic must return a GenTree*; otherwise, false // // Return Value: // The GT_HWINTRINSIC node, or nullptr if not a supported intrinsic @@ -341,7 +495,8 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, CORINFO_SIG_INFO* sig, CorInfoType simdBaseJitType, var_types retType, - unsigned simdSize) + unsigned simdSize, + bool mustExpand) { const HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsic); const int numArgs = sig->numArgs; @@ -620,29 +775,45 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector64_ConvertToInt32Native: + case NI_Vector128_ConvertToInt32Native: + { + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + FALLTHROUGH; + } + case NI_Vector64_ConvertToInt32: case NI_Vector128_ConvertToInt32: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_FLOAT); - op1 = impSIMDPopStack(); - retNode = - gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToInt32RoundToZero, simdBaseJitType, simdSize); + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); break; } + case NI_Vector64_ConvertToInt64Native: + case NI_Vector128_ConvertToInt64Native: + { + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + FALLTHROUGH; + } + case NI_Vector64_ConvertToInt64: case NI_Vector128_ConvertToInt64: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); - intrinsic = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToInt64RoundToZeroScalar - : NI_AdvSimd_Arm64_ConvertToInt64RoundToZero; - op1 = impSIMDPopStack(); - retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); break; } @@ -657,6 +828,16 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector64_ConvertToUInt32Native: + case NI_Vector128_ConvertToUInt32Native: + { + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + FALLTHROUGH; + } + case NI_Vector64_ConvertToUInt32: case NI_Vector128_ConvertToUInt32: { @@ -664,22 +845,28 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, assert(simdBaseType == TYP_FLOAT); op1 = impSIMDPopStack(); - retNode = gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToUInt32RoundToZero, simdBaseJitType, - simdSize); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); break; } + case NI_Vector64_ConvertToUInt64Native: + case NI_Vector128_ConvertToUInt64Native: + { + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + FALLTHROUGH; + } + case NI_Vector64_ConvertToUInt64: case NI_Vector128_ConvertToUInt64: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); - intrinsic = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToUInt64RoundToZeroScalar - : NI_AdvSimd_Arm64_ConvertToUInt64RoundToZero; - op1 = impSIMDPopStack(); - retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); break; } @@ -1171,6 +1358,26 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector64_FusedMultiplyAdd: + case NI_Vector128_FusedMultiplyAdd: + { + assert(sig->numArgs == 3); + assert(varTypeIsFloating(simdBaseType)); + + impSpillSideEffect(true, verCurrentState.esStackDepth - + 3 DEBUGARG("Spilling op1 side effects for FusedMultiplyAdd")); + + impSpillSideEffect(true, verCurrentState.esStackDepth - + 2 DEBUGARG("Spilling op2 side effects for FusedMultiplyAdd")); + + op3 = impSIMDPopStack(); + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); + + retNode = gtNewSimdFmaNode(retType, op1, op2, op3, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_get_AllBitsSet: case NI_Vector128_get_AllBitsSet: { @@ -1515,6 +1722,31 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector64_MultiplyAddEstimate: + case NI_Vector128_MultiplyAddEstimate: + { + assert(sig->numArgs == 3); + assert(varTypeIsFloating(simdBaseType)); + + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + + impSpillSideEffect(true, verCurrentState.esStackDepth - + 3 DEBUGARG("Spilling op1 side effects for MultiplyAddEstimate")); + + impSpillSideEffect(true, verCurrentState.esStackDepth - + 2 DEBUGARG("Spilling op2 side effects for MultiplyAddEstimate")); + + op3 = impSIMDPopStack(); + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); + + retNode = gtNewSimdFmaNode(retType, op1, op2, op3, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_Narrow: case NI_Vector128_Narrow: { @@ -1903,7 +2135,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, } assert(HWIntrinsicInfo::isImmOp(intrinsic, op3)); - HWIntrinsicInfo::lookupImmBounds(intrinsic, simdSize, simdBaseType, &immLowerBound, &immUpperBound); + HWIntrinsicInfo::lookupImmBounds(intrinsic, simdSize, simdBaseType, 1, &immLowerBound, &immUpperBound); op3 = addRangeCheckIfNeeded(intrinsic, op3, (!op3->IsCnsIntOrI()), immLowerBound, immUpperBound); argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg1, &argClass))); op1 = getArgForHWIntrinsic(argType, argClass); @@ -2222,9 +2454,8 @@ GenTree* Compiler::gtNewSimdConvertVectorToMaskNode(var_types type, assert(varTypeIsSIMD(node)); // ConvertVectorToMask uses cmpne which requires an embedded mask. - GenTree* embeddedMask = gtNewSimdHWIntrinsicNode(TYP_MASK, NI_Sve_CreateTrueMaskAll, simdBaseJitType, simdSize); - return gtNewSimdHWIntrinsicNode(TYP_MASK, embeddedMask, node, NI_Sve_ConvertVectorToMask, simdBaseJitType, - simdSize); + GenTree* trueMask = gtNewSimdAllTrueMaskNode(simdBaseJitType, simdSize); + return gtNewSimdHWIntrinsicNode(TYP_MASK, trueMask, node, NI_Sve_ConvertVectorToMask, simdBaseJitType, simdSize); } //------------------------------------------------------------------------ @@ -2246,4 +2477,19 @@ GenTree* Compiler::gtNewSimdConvertMaskToVectorNode(GenTreeHWIntrinsic* node, va node->GetSimdSize()); } +//------------------------------------------------------------------------ +// gtNewSimdEmbeddedMaskNode: Create an embedded mask +// +// Arguments: +// simdBaseJitType -- the base jit type of the nodes being masked +// simdSize -- the simd size of the nodes being masked +// +// Return Value: +// The mask +// +GenTree* Compiler::gtNewSimdAllTrueMaskNode(CorInfoType simdBaseJitType, unsigned simdSize) +{ + return gtNewSimdHWIntrinsicNode(TYP_MASK, NI_Sve_CreateTrueMaskAll, simdBaseJitType, simdSize); +} + #endif // FEATURE_HW_INTRINSICS diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index 9a3a98e087a2..c0dcd95b5b1b 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -20,9 +20,10 @@ // intrinsic node. The register will be later used to store computed branch target address. // // Arguments: -// codeGen -- an instance of CodeGen class. -// immOp -- an immediate operand of the intrinsic. -// intrin -- a hardware intrinsic tree node. +// codeGen -- an instance of CodeGen class. +// immOp -- an immediate operand of the intrinsic. +// intrin -- a hardware intrinsic tree node. +// immNumber -- which immediate operand to use (most intrinsics only have one). // // Note: This class is designed to be used in the following way // HWIntrinsicImmOpHelper helper(this, immOp, intrin); @@ -35,7 +36,10 @@ // This allows to combine logic for cases when immOp->isContainedIntOrIImmed() is either true or false in a form // of a for-loop. // -CodeGen::HWIntrinsicImmOpHelper::HWIntrinsicImmOpHelper(CodeGen* codeGen, GenTree* immOp, GenTreeHWIntrinsic* intrin) +CodeGen::HWIntrinsicImmOpHelper::HWIntrinsicImmOpHelper(CodeGen* codeGen, + GenTree* immOp, + GenTreeHWIntrinsic* intrin, + int immNumber /* = 1 */) : codeGen(codeGen) , endLabel(nullptr) , nonZeroLabel(nullptr) @@ -75,12 +79,12 @@ CodeGen::HWIntrinsicImmOpHelper::HWIntrinsicImmOpHelper(CodeGen* codeGen, GenTre const unsigned int indexedElementSimdSize = genTypeSize(indexedElementOpType); HWIntrinsicInfo::lookupImmBounds(intrin->GetHWIntrinsicId(), indexedElementSimdSize, - intrin->GetSimdBaseType(), &immLowerBound, &immUpperBound); + intrin->GetSimdBaseType(), immNumber, &immLowerBound, &immUpperBound); } else { HWIntrinsicInfo::lookupImmBounds(intrin->GetHWIntrinsicId(), intrin->GetSimdSize(), - intrin->GetSimdBaseType(), &immLowerBound, &immUpperBound); + intrin->GetSimdBaseType(), immNumber, &immLowerBound, &immUpperBound); } nonConstImmReg = immOp->GetRegNum(); @@ -98,8 +102,7 @@ CodeGen::HWIntrinsicImmOpHelper::HWIntrinsicImmOpHelper(CodeGen* codeGen, GenTre // these by // using the same approach as in hwintrinsicxarch.cpp - adding an additional indirection level in form of a // branch table. - assert(!HWIntrinsicInfo::GeneratesMultipleIns(intrin->GetHWIntrinsicId())); - branchTargetReg = intrin->GetSingleTempReg(); + branchTargetReg = codeGen->internalRegisters.GetSingle(intrin); } endLabel = codeGen->genCreateTempLabel(); @@ -380,7 +383,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) emitShift(intrin.op2, op1Reg); } } - else if (intrin.category == HW_Category_EnumPattern) + else if (HWIntrinsicInfo::HasEnumOperand(intrin.id)) { assert(hasImmediateOperand); @@ -401,12 +404,347 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) unreached(); } } + else if (intrin.numOperands >= 2 && intrin.op2->IsEmbMaskOp()) + { + // Handle case where op2 is operation that needs embedded mask + GenTree* op2 = intrin.op2; + assert(intrin.id == NI_Sve_ConditionalSelect); + assert(op2->OperIsHWIntrinsic()); + assert(op2->isContained()); + + // Get the registers and intrinsics that needs embedded mask + const HWIntrinsic intrinEmbMask(op2->AsHWIntrinsic()); + instruction insEmbMask = HWIntrinsicInfo::lookupIns(intrinEmbMask.id, intrinEmbMask.baseType); + const bool instrIsRMW = op2->isRMWHWIntrinsic(compiler); + + regNumber maskReg = op1Reg; + regNumber embMaskOp1Reg = REG_NA; + regNumber embMaskOp2Reg = REG_NA; + regNumber embMaskOp3Reg = REG_NA; + regNumber falseReg = op3Reg; + + switch (intrinEmbMask.numOperands) + { + case 3: + assert(intrinEmbMask.op3 != nullptr); + embMaskOp3Reg = intrinEmbMask.op3->GetRegNum(); + FALLTHROUGH; + + case 2: + assert(intrinEmbMask.op2 != nullptr); + embMaskOp2Reg = intrinEmbMask.op2->GetRegNum(); + FALLTHROUGH; + + case 1: + assert(intrinEmbMask.op1 != nullptr); + embMaskOp1Reg = intrinEmbMask.op1->GetRegNum(); + break; + + default: + unreached(); + } + + switch (intrinEmbMask.numOperands) + { + case 1: + { + assert(!instrIsRMW); + + if (targetReg != falseReg) + { + // If targetReg is not the same as `falseReg` then need to move + // the `falseReg` to `targetReg`. + + if (intrin.op3->isContained()) + { + assert(intrin.op3->IsVectorZero()); + if (intrin.op1->isContained() || intrin.op1->IsMaskAllBitsSet()) + { + // We already skip importing ConditionalSelect if op1 == trueAll, however + // if we still see it here, it is because we wrapped the predicated instruction + // inside ConditionalSelect. + // As such, no need to move the `falseReg` to `targetReg` + // because the predicated instruction will eventually set it. + } + else + { + // If falseValue is zero, just zero out those lanes of targetReg using `movprfx` + // and /Z + GetEmitter()->emitIns_R_R_R(INS_sve_movprfx, emitSize, targetReg, maskReg, targetReg, + opt); + } + } + else if (targetReg == embMaskOp1Reg) + { + // target != falseValue, but we do not want to overwrite target with `embMaskOp1Reg`. + // We will first do the predicate operation and then do conditionalSelect inactive + // elements from falseValue + + // We cannot use use `movprfx` here to move falseReg to targetReg because that will + // overwrite the value of embMaskOp1Reg which is present in targetReg. + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp1Reg, opt); + + GetEmitter()->emitIns_R_R_R_R(INS_sve_sel, emitSize, targetReg, maskReg, targetReg, + falseReg, opt, INS_SCALABLE_OPTS_UNPREDICATED); + break; + } + else + { + // At this point, target != embMaskOp1Reg != falseReg, so just go ahead + // and move the falseReg unpredicated into targetReg. + GetEmitter()->emitIns_R_R(INS_sve_movprfx, EA_SCALABLE, targetReg, falseReg); + } + } + + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp1Reg, opt); + break; + } + + case 2: + { + assert(instrIsRMW); + + if (intrin.op3->IsVectorZero()) + { + // If `falseReg` is zero, then move the first operand of `intrinEmbMask` in the + // destination using /Z. + + assert(targetReg != embMaskOp2Reg); + GetEmitter()->emitIns_R_R_R(INS_sve_movprfx, emitSize, targetReg, maskReg, embMaskOp1Reg, opt); + + // Finally, perform the actual "predicated" operation so that `targetReg` is the first operand + // and `embMaskOp2Reg` is the second operand. + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, opt); + } + else if (targetReg != falseReg) + { + // If `targetReg` and `falseReg` are not same, then we need to move it to `targetReg` first + // so the `insEmbMask` operation can be merged on top of it. + + if (falseReg != embMaskOp1Reg) + { + // At the point, targetReg != embMaskOp1Reg != falseReg + if (HWIntrinsicInfo::IsOptionalEmbeddedMaskedOperation(intrinEmbMask.id)) + { + // If the embedded instruction supports optional mask operation, use the "unpredicated" + // version of the instruction, followed by "sel" to select the active lanes. + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, embMaskOp1Reg, + embMaskOp2Reg, opt, INS_SCALABLE_OPTS_UNPREDICATED); + } + else + { + // If the instruction just has "predicated" version, then move the "embMaskOp1Reg" + // into targetReg. Next, do the predicated operation on the targetReg and last, + // use "sel" to select the active lanes based on mask, and set inactive lanes + // to falseReg. + + assert(targetReg != embMaskOp2Reg); + assert(HWIntrinsicInfo::IsEmbeddedMaskedOperation(intrinEmbMask.id)); + + GetEmitter()->emitIns_R_R(INS_sve_movprfx, EA_SCALABLE, targetReg, embMaskOp1Reg); + + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, + opt); + } + + GetEmitter()->emitIns_R_R_R_R(INS_sve_sel, emitSize, targetReg, maskReg, targetReg, + falseReg, opt, INS_SCALABLE_OPTS_UNPREDICATED); + break; + } + else if (targetReg != embMaskOp1Reg) + { + // embMaskOp1Reg is same as `falseReg`, but not same as `targetReg`. Move the + // `embMaskOp1Reg` i.e. `falseReg` in `targetReg`, using "unpredicated movprfx", so the + // subsequent `insEmbMask` operation can be merged on top of it. + GetEmitter()->emitIns_R_R(INS_sve_movprfx, EA_SCALABLE, targetReg, falseReg); + } + + // Finally, perform the actual "predicated" operation so that `targetReg` is the first operand + // and `embMaskOp2Reg` is the second operand. + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, opt); + } + else + { + // Just perform the actual "predicated" operation so that `targetReg` is the first operand + // and `embMaskOp2Reg` is the second operand. + GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, opt); + } + + break; + } + case 3: + { + assert(instrIsRMW); + assert(HWIntrinsicInfo::IsFmaIntrinsic(intrinEmbMask.id)); + assert(falseReg != embMaskOp1Reg); + assert(falseReg != embMaskOp2Reg); + assert(falseReg != embMaskOp3Reg); + + // For FMA, the operation we are trying to perform is: + // result = op1 + (op2 * op3) + // + // There are two instructions that can be used depending on which operand's register, + // optionally, will store the final result. + // + // 1. If the result is stored in the operand that was used as an "addend" in the operation, + // then we use `FMLA` format: + // reg1 = reg1 + (reg2 * reg3) + // + // 2. If the result is stored in the operand that was used as a "multiplicand" in the operation, + // then we use `FMAD` format: + // reg1 = (reg1 * reg2) + reg3 + // + // Check if the result's register is same as that of one of the operand's register and accordingly + // pick the appropriate format. Suppose `targetReg` holds the result, then we have following cases: + // + // Case# 1: Result is stored in the operand that held the "addend" + // targetReg == reg1 + // + // We generate the FMLA instruction format and no further changes are needed. + // + // Case# 2: Result is stored in the operand `op2` that held the "multiplicand" + // targetReg == reg2 + // + // So we basically have an operation: + // reg2 = reg1 + (reg2 * reg3) + // + // Since, the result will be stored in the "multiplicand", we pick format `FMAD`. + // Then, we rearrange the operands to ensure that the operation is done correctly. + // reg2 = reg1 + (reg2 * reg3) // to start with + // reg2 = reg3 + (reg2 * reg1) // swap reg1 <--> reg3 + // reg1 = reg3 + (reg1 * reg2) // swap reg1 <--> reg2 + // reg1 = (reg1 * reg2) + reg3 // rearrange to get FMAD format + // + // Case# 3: Result is stored in the operand `op3` that held the "multiplier" + // targetReg == reg3 + // + // So we basically have an operation: + // reg3 = reg1 + (reg2 * reg3) + // Since, the result will be stored in the "multiplier", we again pick format `FMAD`. + // Then, we rearrange the operands to ensure that the operation is done correctly. + // reg3 = reg1 + (reg2 * reg3) // to start with + // reg1 = reg3 + (reg2 * reg1) // swap reg1 <--> reg3 + // reg1 = (reg1 * reg2) + reg3 // rearrange to get FMAD format + + bool useAddend = true; + if (targetReg == embMaskOp2Reg) + { + // Case# 2 + useAddend = false; + std::swap(embMaskOp1Reg, embMaskOp3Reg); + std::swap(embMaskOp1Reg, embMaskOp2Reg); + } + else if (targetReg == embMaskOp3Reg) + { + // Case# 3 + useAddend = false; + std::swap(embMaskOp1Reg, embMaskOp3Reg); + } + else + { + // Case# 1 + } + + switch (intrinEmbMask.id) + { + case NI_Sve_FusedMultiplyAdd: + insEmbMask = useAddend ? INS_sve_fmla : INS_sve_fmad; + break; + + case NI_Sve_FusedMultiplyAddNegated: + insEmbMask = useAddend ? INS_sve_fnmla : INS_sve_fnmad; + break; + + case NI_Sve_FusedMultiplySubtract: + insEmbMask = useAddend ? INS_sve_fmls : INS_sve_fmsb; + break; + + case NI_Sve_FusedMultiplySubtractNegated: + insEmbMask = useAddend ? INS_sve_fnmls : INS_sve_fnmsb; + break; + + case NI_Sve_MultiplyAdd: + insEmbMask = useAddend ? INS_sve_mla : INS_sve_mad; + break; + + case NI_Sve_MultiplySubtract: + insEmbMask = useAddend ? INS_sve_mls : INS_sve_msb; + break; + + default: + unreached(); + } + + if (intrin.op3->IsVectorZero()) + { + // If `falseReg` is zero, then move the first operand of `intrinEmbMask` in the + // destination using /Z. + + assert(targetReg != embMaskOp2Reg); + assert(intrin.op3->isContained() || !intrin.op1->IsMaskAllBitsSet()); + GetEmitter()->emitIns_R_R_R(INS_sve_movprfx, emitSize, targetReg, maskReg, embMaskOp1Reg, opt); + } + else + { + // Below are the considerations we need to handle: + // + // targetReg == falseReg && targetReg == embMaskOp1Reg + // fmla Zd, P/m, Zn, Zm + // + // targetReg == falseReg && targetReg != embMaskOp1Reg + // movprfx target, P/m, embMaskOp1Reg + // fmla target, P/m, embMaskOp2Reg, embMaskOp3Reg + // + // targetReg != falseReg && targetReg == embMaskOp1Reg + // sel target, P/m, embMaskOp1Reg, falseReg + // fmla target, P/m, embMaskOp2Reg, embMaskOp3Reg + // + // targetReg != falseReg && targetReg != embMaskOp1Reg + // sel target, P/m, embMaskOp1Reg, falseReg + // fmla target, P/m, embMaskOp2Reg, embMaskOp3Reg + // + // Note that, we just check if the targetReg/falseReg or targetReg/embMaskOp1Reg + // coincides or not. Other combination like falseReg/embMaskOp*Reg cannot happen + // because we marked embMaskOp*Reg as delayFree. + + if (targetReg != falseReg) + { + // If falseReg value is not present in targetReg yet, move the inactive lanes + // into the targetReg using `sel`. Since this is RMW, the active lanes should + // have the value from embMaskOp1Reg + + GetEmitter()->emitIns_R_R_R_R(INS_sve_sel, emitSize, targetReg, maskReg, embMaskOp1Reg, + falseReg, opt, INS_SCALABLE_OPTS_UNPREDICATED); + } + else if (targetReg != embMaskOp1Reg) + { + // If target already contains the values of `falseReg`, just merge the lanes from + // `embMaskOp1Reg`, again because this is RMW semantics. + + GetEmitter()->emitIns_R_R_R(INS_sve_movprfx, emitSize, targetReg, maskReg, embMaskOp1Reg, + opt, INS_SCALABLE_OPTS_PREDICATE_MERGE); + } + } + + // Finally, perform the desired operation. + GetEmitter()->emitIns_R_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, + embMaskOp3Reg, opt); + + break; + } + default: + unreached(); + } + } else { assert(!hasImmediateOperand); switch (intrin.numOperands) { + case 0: + GetEmitter()->emitIns_R(ins, emitSize, targetReg, opt); + break; case 1: GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt); break; @@ -419,6 +757,14 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) { GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt); } + else if (HWIntrinsicInfo::IsScalable(intrin.id)) + { + assert(!node->IsEmbMaskOp()); + // This generates an unpredicated version + // Predicated should be taken care above `intrin.op2->IsEmbMaskOp()` + GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt, + INS_SCALABLE_OPTS_UNPREDICATED); + } else if (isRMW) { if (targetReg != op1Reg) @@ -437,15 +783,23 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) break; case 3: - assert(isRMW); - if (targetReg != op1Reg) + if (isRMW) { - assert(targetReg != op2Reg); - assert(targetReg != op3Reg); + if (targetReg != op1Reg) + { + assert(targetReg != op2Reg); + assert(targetReg != op3Reg); - GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true); + GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, + /* canSkip */ true); + } + GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op2Reg, op3Reg, opt); + } + else + { + GetEmitter()->emitIns_R_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, op3Reg, opt, + INS_SCALABLE_OPTS_UNPREDICATED); } - GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op2Reg, op3Reg, opt); break; default: @@ -833,7 +1187,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GenTree* argNode = use.GetNode(); assert(argReg == argNode->GetRegNum()); - argReg = REG_NEXT(argReg); + argReg = getNextSIMDRegWithWraparound(argReg); } assert((ins == INS_st2 && regCount == 2) || (ins == INS_st3 && regCount == 3) || (ins == INS_st4 && regCount == 4)); @@ -883,7 +1237,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GenTree* argNode = use.GetNode(); assert(argReg == argNode->GetRegNum()); - argReg = REG_NEXT(argReg); + argReg = getNextSIMDRegWithWraparound(argReg); } assert((ins == INS_st1_2regs && regCount == 2) || (ins == INS_st2 && regCount == 2) || (ins == INS_st1_3regs && regCount == 3) || (ins == INS_st3 && regCount == 3) || @@ -1034,7 +1388,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) if (intrin.op1->OperIsLocal()) { unsigned varNum = intrin.op1->AsLclVarCommon()->GetLclNum(); - baseReg = node->ExtractTempReg(); + baseReg = internalRegisters.Extract(node); // Load the address of varNum GetEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, baseReg, varNum, 0); @@ -1054,7 +1408,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) unsigned simdInitTempVarNum = compiler->lvaSIMDInitTempVarNum; noway_assert(simdInitTempVarNum != BAD_VAR_NUM); - baseReg = node->ExtractTempReg(); + baseReg = internalRegisters.Extract(node); // Load the address of simdInitTempVarNum GetEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, baseReg, simdInitTempVarNum, 0); @@ -1186,7 +1540,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GenTree* argNode = use.GetNode(); assert(argReg == argNode->GetRegNum()); - argReg = REG_NEXT(argReg); + argReg = getNextSIMDRegWithWraparound(argReg); #endif } } @@ -1241,7 +1595,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) assert(argReg == argNode->GetRegNum()); // and they should not interfere with targetReg assert(targetReg != argReg); - argReg = REG_NEXT(argReg); + argReg = getNextSIMDRegWithWraparound(argReg); #endif } } @@ -1295,11 +1649,70 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GetEmitter()->emitIns_R_R_R_I(ins, emitSize, targetReg, op1Reg, op2Reg, 0, opt); break; + case NI_Sve_Count16BitElements: + case NI_Sve_Count32BitElements: + case NI_Sve_Count64BitElements: + case NI_Sve_Count8BitElements: + { + // Instruction has an additional immediate to multiply the result by. Use 1. + assert(hasImmediateOperand); + HWIntrinsicImmOpHelper helper(this, intrin.op1, node); + for (helper.EmitBegin(); !helper.Done(); helper.EmitCaseEnd()) + { + const insSvePattern pattern = (insSvePattern)helper.ImmValue(); + GetEmitter()->emitIns_R_PATTERN_I(ins, emitSize, targetReg, pattern, 1, opt); + } + break; + } + case NI_Sve_CreateTrueMaskAll: // Must use the pattern variant, as the non-pattern varient is SVE2.1. GetEmitter()->emitIns_R_PATTERN(ins, emitSize, targetReg, opt, SVE_PATTERN_ALL); break; + case NI_Sve_CreateWhileLessThanMask8Bit: + case NI_Sve_CreateWhileLessThanMask16Bit: + case NI_Sve_CreateWhileLessThanMask32Bit: + case NI_Sve_CreateWhileLessThanMask64Bit: + { + // Emit size and instruction is based on the scalar operands. + var_types auxType = node->GetAuxiliaryType(); + emitSize = emitActualTypeSize(auxType); + if (varTypeIsUnsigned(auxType)) + { + ins = INS_sve_whilelo; + } + + GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt); + break; + } + + case NI_Sve_CreateWhileLessThanOrEqualMask8Bit: + case NI_Sve_CreateWhileLessThanOrEqualMask16Bit: + case NI_Sve_CreateWhileLessThanOrEqualMask32Bit: + case NI_Sve_CreateWhileLessThanOrEqualMask64Bit: + { + // Emit size and instruction is based on the scalar operands. + var_types auxType = node->GetAuxiliaryType(); + emitSize = emitActualTypeSize(auxType); + if (varTypeIsUnsigned(auxType)) + { + ins = INS_sve_whilels; + } + + GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt); + break; + } + + case NI_Sve_UnzipEven: + case NI_Sve_UnzipOdd: + case NI_Sve_ZipHigh: + case NI_Sve_ZipLow: + // Use non-predicated version explicitly + GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt, + INS_SCALABLE_OPTS_UNPREDICATED); + break; + default: unreached(); } diff --git a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp index 79e6b497c368..8ef9517c344d 100644 --- a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp @@ -74,11 +74,10 @@ static void assertIsContainableHWIntrinsicOp(Lowering* lowering, static bool genIsTableDrivenHWIntrinsic(NamedIntrinsic intrinsicId, HWIntrinsicCategory category) { // TODO - make more categories to the table-driven framework - // HW_Category_Helper and HW_Flag_MultiIns/HW_Flag_SpecialCodeGen usually need manual codegen + // HW_Category_Helper and HW_Flag_SpecialCodeGen usually need manual codegen const bool tableDrivenCategory = (category != HW_Category_Special) && (category != HW_Category_Scalar) && (category != HW_Category_Helper); - const bool tableDrivenFlag = - !HWIntrinsicInfo::GeneratesMultipleIns(intrinsicId) && !HWIntrinsicInfo::HasSpecialCodegen(intrinsicId); + const bool tableDrivenFlag = !HWIntrinsicInfo::HasSpecialCodegen(intrinsicId); return tableDrivenCategory && tableDrivenFlag; } @@ -247,8 +246,11 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // We don't need to genProduceReg(node) since that will be handled by processing op2 // likewise, processing op2 will ensure its own registers are consumed - // Make sure we consume the registers that are getting specially handled - genConsumeReg(op1); + if (!mergeWithZero) + { + // Make sure we consume the registers that are getting specially handled + genConsumeReg(op1); + } embMaskOp = op3; } } @@ -323,8 +325,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) insOpts newInstOptions = AddEmbRoundingMode(instOptions, i); genHWIntrinsic_R_RM(node, ins, simdSize, targetReg, rmOp, newInstOptions); }; - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; @@ -335,8 +337,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) insOpts newInstOptions = AddEmbRoundingMode(instOptions, i); genHWIntrinsic_R_R_RM(node, ins, simdSize, newInstOptions); }; - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; @@ -412,17 +414,17 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) { assert(!op1->isContained()); emit->emitIns_SIMD_R_R_R_I(ins, simdSize, targetReg, op1Reg, op1Reg, - static_cast(ival)); + static_cast(ival), instOptions); } else { - genHWIntrinsic_R_RM_I(node, ins, simdSize, static_cast(ival)); + genHWIntrinsic_R_RM_I(node, ins, simdSize, static_cast(ival), instOptions); } } else if (HWIntrinsicInfo::CopiesUpperBits(intrinsicId)) { assert(!op1->isContained()); - emit->emitIns_SIMD_R_R_R(ins, simdSize, targetReg, op1Reg, op1Reg); + emit->emitIns_SIMD_R_R_R(ins, simdSize, targetReg, op1Reg, op1Reg, instOptions); } else { @@ -472,7 +474,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) if (ival != -1) { assert((ival >= 0) && (ival <= 127)); - genHWIntrinsic_R_R_RM_I(node, ins, simdSize, static_cast(ival)); + genHWIntrinsic_R_R_RM_I(node, ins, simdSize, static_cast(ival), instOptions); } else if (category == HW_Category_MemoryLoad) { @@ -502,11 +504,11 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) if (HWIntrinsicInfo::CopiesUpperBits(intrinsicId)) { assert(!op1->isContained()); - emit->emitIns_SIMD_R_R_R_I(ins, simdSize, targetReg, op1Reg, op1Reg, i); + emit->emitIns_SIMD_R_R_R_I(ins, simdSize, targetReg, op1Reg, op1Reg, i, instOptions); } else { - genHWIntrinsic_R_RM_I(node, ins, simdSize, i); + genHWIntrinsic_R_RM_I(node, ins, simdSize, i, instOptions); } }; @@ -524,14 +526,14 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // Reflection. However, it // can also occur if the consumer calls it directly and just doesn't pass a // constant value. - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, op2Reg, baseReg, offsReg, emitSwCase); } } else if (node->TypeGet() == TYP_VOID) { - genHWIntrinsic_R_RM(node, ins, simdSize, op1Reg, op2); + genHWIntrinsic_R_RM(node, ins, simdSize, op1Reg, op2, instOptions); } else { @@ -560,7 +562,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) if (HWIntrinsicInfo::isImmOp(intrinsicId, op3)) { auto emitSwCase = [&](int8_t i) { - genHWIntrinsic_R_R_RM_I(node, ins, simdSize, i); + genHWIntrinsic_R_R_RM_I(node, ins, simdSize, i, instOptions); }; if (op3->IsCnsIntOrI()) @@ -574,18 +576,20 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // We emit a fallback case for the scenario when the imm-op is not a constant. This should // normally happen when the intrinsic is called indirectly, such as via Reflection. However, it // can also occur if the consumer calls it directly and just doesn't pass a constant value. - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, op3Reg, baseReg, offsReg, emitSwCase); } } else if (category == HW_Category_MemoryStore) { + assert(instOptions == INS_OPTS_NONE); + // The Mask instructions do not currently support containment of the address. assert(!op2->isContained()); if (intrinsicId == NI_AVX_MaskStore || intrinsicId == NI_AVX2_MaskStore) { - emit->emitIns_AR_R_R(ins, simdSize, op2Reg, op3Reg, op1Reg, 0); + emit->emitIns_AR_R_R(ins, simdSize, op2Reg, op3Reg, op1Reg, 0, instOptions); } else { @@ -595,7 +599,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // SSE2 MaskMove hardcodes the destination (op3) in DI/EDI/RDI emit->emitIns_Mov(INS_mov, EA_PTRSIZE, REG_EDI, op3Reg, /* canSkip */ true); - emit->emitIns_R_R(ins, simdSize, op1Reg, op2Reg); + emit->emitIns_R_R(ins, simdSize, op1Reg, op2Reg, instOptions); } } else @@ -607,7 +611,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) case NI_AVX2_BlendVariable: case NI_AVX512F_BlendVariableMask: { - genHWIntrinsic_R_R_RM_R(node, ins, simdSize); + genHWIntrinsic_R_R_RM_R(node, ins, simdSize, instOptions); break; } @@ -618,7 +622,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) assert(op1Reg != REG_NA); assert(op2Reg != REG_NA); - genHWIntrinsic_R_R_R_RM(ins, simdSize, targetReg, op1Reg, op2Reg, op3); + genHWIntrinsic_R_R_R_RM(ins, simdSize, targetReg, op1Reg, op2Reg, op3, instOptions); break; } @@ -656,7 +660,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) if (HWIntrinsicInfo::isImmOp(intrinsicId, op4)) { auto emitSwCase = [&](int8_t i) { - genHWIntrinsic_R_R_R_RM_I(node, ins, simdSize, i); + genHWIntrinsic_R_R_R_RM_I(node, ins, simdSize, i, instOptions); }; if (op4->IsCnsIntOrI()) @@ -670,8 +674,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // We emit a fallback case for the scenario when the imm-op is not a constant. This should // normally happen when the intrinsic is called indirectly, such as via Reflection. However, it // can also occur if the consumer calls it directly and just doesn't pass a constant value. - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, op4Reg, baseReg, offsReg, emitSwCase); } } @@ -706,28 +710,45 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) case InstructionSet_Vector128: case InstructionSet_Vector256: case InstructionSet_Vector512: - genBaseIntrinsic(node); + { + genBaseIntrinsic(node, instOptions); break; + } + case InstructionSet_X86Base: case InstructionSet_X86Base_X64: - genX86BaseIntrinsic(node); + { + genX86BaseIntrinsic(node, instOptions); break; + } + case InstructionSet_SSE: case InstructionSet_SSE_X64: + { genSSEIntrinsic(node, instOptions); break; + } case InstructionSet_SSE2: case InstructionSet_SSE2_X64: + { genSSE2Intrinsic(node, instOptions); break; + } + case InstructionSet_SSE41: case InstructionSet_SSE41_X64: - genSSE41Intrinsic(node); + { + genSSE41Intrinsic(node, instOptions); break; + } + case InstructionSet_SSE42: case InstructionSet_SSE42_X64: - genSSE42Intrinsic(node); + { + genSSE42Intrinsic(node, instOptions); break; + } + case InstructionSet_AVX: case InstructionSet_AVX2: case InstructionSet_AVX512F: @@ -737,35 +758,49 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) case InstructionSet_AVX512BW_VL: case InstructionSet_AVX512VBMI: case InstructionSet_AVX512VBMI_VL: + { genAvxFamilyIntrinsic(node, instOptions); break; - case InstructionSet_AES: - genAESIntrinsic(node); - break; + } + case InstructionSet_BMI1: case InstructionSet_BMI1_X64: case InstructionSet_BMI2: case InstructionSet_BMI2_X64: + { genBMI1OrBMI2Intrinsic(node, instOptions); break; + } + case InstructionSet_FMA: + { genFMAIntrinsic(node, instOptions); break; + } + case InstructionSet_LZCNT: case InstructionSet_LZCNT_X64: + { + assert(instOptions == INS_OPTS_NONE); genLZCNTIntrinsic(node); break; - case InstructionSet_PCLMULQDQ: - genPCLMULQDQIntrinsic(node); - break; + } + case InstructionSet_POPCNT: case InstructionSet_POPCNT_X64: + { + assert(instOptions == INS_OPTS_NONE); genPOPCNTIntrinsic(node); break; + } + case InstructionSet_X86Serialize: case InstructionSet_X86Serialize_X64: + { + assert(instOptions == INS_OPTS_NONE); genX86SerializeIntrinsic(node); break; + } default: unreached(); @@ -787,7 +822,13 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) void CodeGen::genHWIntrinsic_R_RM( GenTreeHWIntrinsic* node, instruction ins, emitAttr attr, regNumber reg, GenTree* rmOp, insOpts instOptions) { - emitter* emit = GetEmitter(); + emitter* emit = GetEmitter(); + + if (CodeGenInterface::IsEmbeddedBroadcastEnabled(ins, rmOp)) + { + instOptions = AddEmbBroadcastMode(instOptions); + } + OperandDesc rmOpDesc = genOperandDesc(rmOp); if (((instOptions & INS_OPTS_EVEX_b_MASK) != 0) && (rmOpDesc.GetKind() == OperandKind::Reg)) @@ -809,11 +850,11 @@ void CodeGen::genHWIntrinsic_R_RM( switch (rmOpDesc.GetKind()) { case OperandKind::ClsVar: - emit->emitIns_R_C(ins, attr, reg, rmOpDesc.GetFieldHnd(), 0); + emit->emitIns_R_C(ins, attr, reg, rmOpDesc.GetFieldHnd(), 0, instOptions); break; case OperandKind::Local: - emit->emitIns_R_S(ins, attr, reg, rmOpDesc.GetVarNum(), rmOpDesc.GetLclOffset()); + emit->emitIns_R_S(ins, attr, reg, rmOpDesc.GetVarNum(), rmOpDesc.GetLclOffset(), instOptions); break; case OperandKind::Indir: @@ -822,7 +863,7 @@ void CodeGen::genHWIntrinsic_R_RM( // temporary GT_IND to generate code with. GenTreeIndir indirForm; GenTreeIndir* indir = rmOpDesc.GetIndirForm(&indirForm); - emit->emitIns_R_A(ins, attr, reg, indir); + emit->emitIns_R_A(ins, attr, reg, indir, instOptions); } break; @@ -832,6 +873,7 @@ void CodeGen::genHWIntrinsic_R_RM( if (emit->IsMovInstruction(ins)) { + assert(instOptions == INS_OPTS_NONE); emit->emitIns_Mov(ins, attr, reg, rmOpReg, /* canSkip */ false); } else @@ -936,7 +978,7 @@ void CodeGen::genHWIntrinsic_R_RM( } } - emit->emitIns_R_R(ins, attr, reg, rmOpReg); + emit->emitIns_R_R(ins, attr, reg, rmOpReg, instOptions); } break; } @@ -955,7 +997,8 @@ void CodeGen::genHWIntrinsic_R_RM( // ins - The instruction being generated // ival - The immediate value // -void CodeGen::genHWIntrinsic_R_RM_I(GenTreeHWIntrinsic* node, instruction ins, emitAttr simdSize, int8_t ival) +void CodeGen::genHWIntrinsic_R_RM_I( + GenTreeHWIntrinsic* node, instruction ins, emitAttr simdSize, int8_t ival, insOpts instOptions) { regNumber targetReg = node->GetRegNum(); GenTree* op1 = node->Op(1); @@ -971,7 +1014,7 @@ void CodeGen::genHWIntrinsic_R_RM_I(GenTreeHWIntrinsic* node, instruction ins, e assert(HWIntrinsicInfo::SupportsContainment(node->GetHWIntrinsicId())); assertIsContainableHWIntrinsicOp(compiler->m_pLowering, node, op1); } - inst_RV_TT_IV(ins, simdSize, targetReg, op1, ival); + inst_RV_TT_IV(ins, simdSize, targetReg, op1, ival, instOptions); } //------------------------------------------------------------------------ @@ -1013,7 +1056,8 @@ void CodeGen::genHWIntrinsic_R_R_RM(GenTreeHWIntrinsic* node, instruction ins, e // ins - The instruction being generated // ival - The immediate value // -void CodeGen::genHWIntrinsic_R_R_RM_I(GenTreeHWIntrinsic* node, instruction ins, emitAttr simdSize, int8_t ival) +void CodeGen::genHWIntrinsic_R_R_RM_I( + GenTreeHWIntrinsic* node, instruction ins, emitAttr simdSize, int8_t ival, insOpts instOptions) { regNumber targetReg = node->GetRegNum(); GenTree* op1 = node->Op(1); @@ -1042,7 +1086,7 @@ void CodeGen::genHWIntrinsic_R_R_RM_I(GenTreeHWIntrinsic* node, instruction ins, // insertps can also contain op2 when it is zero in which case // we just reuse op1Reg since ival specifies the entry to zero - GetEmitter()->emitIns_SIMD_R_R_R_I(ins, simdSize, targetReg, op1Reg, op1Reg, ival); + GetEmitter()->emitIns_SIMD_R_R_R_I(ins, simdSize, targetReg, op1Reg, op1Reg, ival, instOptions); return; } } @@ -1050,7 +1094,7 @@ void CodeGen::genHWIntrinsic_R_R_RM_I(GenTreeHWIntrinsic* node, instruction ins, assert(op1Reg != REG_NA); bool isRMW = node->isRMWHWIntrinsic(compiler); - inst_RV_RV_TT_IV(ins, simdSize, targetReg, op1Reg, op2, ival, isRMW); + inst_RV_RV_TT_IV(ins, simdSize, targetReg, op1Reg, op2, ival, isRMW, instOptions); } //------------------------------------------------------------------------ @@ -1061,7 +1105,7 @@ void CodeGen::genHWIntrinsic_R_R_RM_I(GenTreeHWIntrinsic* node, instruction ins, // node - The hardware intrinsic node // ins - The instruction being generated // -void CodeGen::genHWIntrinsic_R_R_RM_R(GenTreeHWIntrinsic* node, instruction ins, emitAttr simdSize) +void CodeGen::genHWIntrinsic_R_R_RM_R(GenTreeHWIntrinsic* node, instruction ins, emitAttr simdSize, insOpts instOptions) { regNumber targetReg = node->GetRegNum(); GenTree* op1 = node->Op(1); @@ -1076,6 +1120,11 @@ void CodeGen::genHWIntrinsic_R_R_RM_R(GenTreeHWIntrinsic* node, instruction ins, assert(op1Reg != REG_NA); assert(op3Reg != REG_NA); + if (CodeGenInterface::IsEmbeddedBroadcastEnabled(ins, op2)) + { + instOptions = AddEmbBroadcastMode(instOptions); + } + OperandDesc op2Desc = genOperandDesc(op2); if (op2Desc.IsContained()) @@ -1087,12 +1136,12 @@ void CodeGen::genHWIntrinsic_R_R_RM_R(GenTreeHWIntrinsic* node, instruction ins, switch (op2Desc.GetKind()) { case OperandKind::ClsVar: - emit->emitIns_SIMD_R_R_C_R(ins, simdSize, targetReg, op1Reg, op3Reg, op2Desc.GetFieldHnd(), 0); + emit->emitIns_SIMD_R_R_C_R(ins, simdSize, targetReg, op1Reg, op3Reg, op2Desc.GetFieldHnd(), 0, instOptions); break; case OperandKind::Local: emit->emitIns_SIMD_R_R_S_R(ins, simdSize, targetReg, op1Reg, op3Reg, op2Desc.GetVarNum(), - op2Desc.GetLclOffset()); + op2Desc.GetLclOffset(), instOptions); break; case OperandKind::Indir: @@ -1101,12 +1150,12 @@ void CodeGen::genHWIntrinsic_R_R_RM_R(GenTreeHWIntrinsic* node, instruction ins, // temporary GT_IND to generate code with. GenTreeIndir indirForm; GenTreeIndir* indir = op2Desc.GetIndirForm(&indirForm); - emit->emitIns_SIMD_R_R_A_R(ins, simdSize, targetReg, op1Reg, op3Reg, indir); + emit->emitIns_SIMD_R_R_A_R(ins, simdSize, targetReg, op1Reg, op3Reg, indir, instOptions); } break; case OperandKind::Reg: - emit->emitIns_SIMD_R_R_R_R(ins, simdSize, targetReg, op1Reg, op2Desc.GetReg(), op3Reg); + emit->emitIns_SIMD_R_R_R_R(ins, simdSize, targetReg, op1Reg, op2Desc.GetReg(), op3Reg, instOptions); break; default: @@ -1139,7 +1188,13 @@ void CodeGen::genHWIntrinsic_R_R_R_RM(instruction ins, assert(op1Reg != REG_NA); assert(op2Reg != REG_NA); - emitter* emit = GetEmitter(); + emitter* emit = GetEmitter(); + + if (CodeGenInterface::IsEmbeddedBroadcastEnabled(ins, op3)) + { + instOptions = AddEmbBroadcastMode(instOptions); + } + OperandDesc op3Desc = genOperandDesc(op3); if (((instOptions & INS_OPTS_EVEX_b_MASK) != 0) && (op3Desc.GetKind() == OperandKind::Reg)) @@ -1155,12 +1210,12 @@ void CodeGen::genHWIntrinsic_R_R_R_RM(instruction ins, switch (op3Desc.GetKind()) { case OperandKind::ClsVar: - emit->emitIns_SIMD_R_R_R_C(ins, attr, targetReg, op1Reg, op2Reg, op3Desc.GetFieldHnd(), 0); + emit->emitIns_SIMD_R_R_R_C(ins, attr, targetReg, op1Reg, op2Reg, op3Desc.GetFieldHnd(), 0, instOptions); break; case OperandKind::Local: emit->emitIns_SIMD_R_R_R_S(ins, attr, targetReg, op1Reg, op2Reg, op3Desc.GetVarNum(), - op3Desc.GetLclOffset()); + op3Desc.GetLclOffset(), instOptions); break; case OperandKind::Indir: @@ -1169,12 +1224,12 @@ void CodeGen::genHWIntrinsic_R_R_R_RM(instruction ins, // temporary GT_IND to generate code with. GenTreeIndir indirForm; GenTreeIndir* indir = op3Desc.GetIndirForm(&indirForm); - emit->emitIns_SIMD_R_R_R_A(ins, attr, targetReg, op1Reg, op2Reg, indir); + emit->emitIns_SIMD_R_R_R_A(ins, attr, targetReg, op1Reg, op2Reg, indir, instOptions); } break; case OperandKind::Reg: - emit->emitIns_SIMD_R_R_R_R(ins, attr, targetReg, op1Reg, op2Reg, op3Desc.GetReg()); + emit->emitIns_SIMD_R_R_R_R(ins, attr, targetReg, op1Reg, op2Reg, op3Desc.GetReg(), instOptions); break; default: @@ -1191,7 +1246,8 @@ void CodeGen::genHWIntrinsic_R_R_R_RM(instruction ins, // ins - The instruction being generated // ival - The immediate value // -void CodeGen::genHWIntrinsic_R_R_R_RM_I(GenTreeHWIntrinsic* node, instruction ins, emitAttr attr, int8_t ival) +void CodeGen::genHWIntrinsic_R_R_R_RM_I( + GenTreeHWIntrinsic* node, instruction ins, emitAttr attr, int8_t ival, insOpts instOptions) { regNumber targetReg = node->GetRegNum(); GenTree* op1 = node->Op(1); @@ -1236,21 +1292,28 @@ void CodeGen::genHWIntrinsic_R_R_R_RM_I(GenTreeHWIntrinsic* node, instruction in assert(op1Reg != REG_NA); assert(op2Reg != REG_NA); - emitter* emit = GetEmitter(); + emitter* emit = GetEmitter(); + + if (CodeGenInterface::IsEmbeddedBroadcastEnabled(ins, op3)) + { + instOptions = AddEmbBroadcastMode(instOptions); + } + OperandDesc op3Desc = genOperandDesc(op3); switch (op3Desc.GetKind()) { case OperandKind::ClsVar: { - emit->emitIns_SIMD_R_R_R_C_I(ins, attr, targetReg, op1Reg, op2Reg, op3Desc.GetFieldHnd(), 0, ival); + emit->emitIns_SIMD_R_R_R_C_I(ins, attr, targetReg, op1Reg, op2Reg, op3Desc.GetFieldHnd(), 0, ival, + instOptions); break; } case OperandKind::Local: { emit->emitIns_SIMD_R_R_R_S_I(ins, attr, targetReg, op1Reg, op2Reg, op3Desc.GetVarNum(), - op3Desc.GetLclOffset(), ival); + op3Desc.GetLclOffset(), ival, instOptions); break; } @@ -1260,13 +1323,13 @@ void CodeGen::genHWIntrinsic_R_R_R_RM_I(GenTreeHWIntrinsic* node, instruction in // temporary GT_IND to generate code with. GenTreeIndir indirForm; GenTreeIndir* indir = op3Desc.GetIndirForm(&indirForm); - emit->emitIns_SIMD_R_R_R_A_I(ins, attr, targetReg, op1Reg, op2Reg, indir, ival); + emit->emitIns_SIMD_R_R_R_A_I(ins, attr, targetReg, op1Reg, op2Reg, indir, ival, instOptions); } break; case OperandKind::Reg: { - emit->emitIns_SIMD_R_R_R_R_I(ins, attr, targetReg, op1Reg, op2Reg, op3Desc.GetReg(), ival); + emit->emitIns_SIMD_R_R_R_R_I(ins, attr, targetReg, op1Reg, op2Reg, op3Desc.GetReg(), ival, instOptions); break; } @@ -1373,8 +1436,8 @@ void CodeGen::genNonTableDrivenHWIntrinsicsJumpTableFallback(GenTreeHWIntrinsic* insOpts newInstOptions = AddEmbRoundingMode(instOptions, i); genHWIntrinsic_R_RM(node, ins, attr, targetReg, rmOp, newInstOptions); }; - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; } @@ -1394,8 +1457,8 @@ void CodeGen::genNonTableDrivenHWIntrinsicsJumpTableFallback(GenTreeHWIntrinsic* insOpts newInstOptions = AddEmbRoundingMode(instOptions, i); genHWIntrinsic_R_RM(node, ins, attr, targetReg, rmOp, newInstOptions); }; - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; } @@ -1408,8 +1471,8 @@ void CodeGen::genNonTableDrivenHWIntrinsicsJumpTableFallback(GenTreeHWIntrinsic* insOpts newInstOptions = AddEmbRoundingMode(instOptions, i); genHWIntrinsic_R_R_RM(node, ins, EA_8BYTE, newInstOptions); }; - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; } @@ -1440,8 +1503,8 @@ void CodeGen::genNonTableDrivenHWIntrinsicsJumpTableFallback(GenTreeHWIntrinsic* insOpts newInstOptions = AddEmbRoundingMode(instOptions, i); genHWIntrinsic_R_R_R_RM(ins, attr, targetReg, op1Reg, op2Reg, op3, newInstOptions); }; - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, lastOp->GetRegNum(), baseReg, offsReg, emitSwCase); break; } @@ -1461,7 +1524,7 @@ void CodeGen::genNonTableDrivenHWIntrinsicsJumpTableFallback(GenTreeHWIntrinsic* // Note: // We currently assume that all base intrinsics have zero or one operand. // -void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node) +void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) { NamedIntrinsic intrinsicId = node->GetHWIntrinsicId(); regNumber targetReg = node->GetRegNum(); @@ -1489,7 +1552,7 @@ void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node) { if (varTypeIsIntegral(baseType)) { - genHWIntrinsic_R_RM(node, ins, emitActualTypeSize(baseType), targetReg, op1); + genHWIntrinsic_R_RM(node, ins, emitActualTypeSize(baseType), targetReg, op1, instOptions); } else { @@ -1499,10 +1562,11 @@ void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node) if (op1->isContained() || op1->isUsedFromSpillTemp()) { - genHWIntrinsic_R_RM(node, ins, attr, targetReg, op1); + genHWIntrinsic_R_RM(node, ins, attr, targetReg, op1, instOptions); } else { + assert(instOptions == INS_OPTS_NONE); // Just use movaps for reg->reg moves as it has zero-latency on modern CPUs emit->emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); } @@ -1514,6 +1578,8 @@ void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node) case NI_Vector256_GetElement: case NI_Vector512_GetElement: { + assert(instOptions == INS_OPTS_NONE); + if (simdType == TYP_SIMD12) { // op1 of TYP_SIMD12 should be considered as TYP_SIMD16 @@ -1603,25 +1669,25 @@ void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node) else { emit->emitIns_SIMD_R_R_R_I(INS_shufps, attr, targetReg, op1Reg, op1Reg, - static_cast(0x55)); + static_cast(0x55), instOptions); } } else if (ival == 2) { - emit->emitIns_SIMD_R_R_R(INS_unpckhps, attr, targetReg, op1Reg, op1Reg); + emit->emitIns_SIMD_R_R_R(INS_unpckhps, attr, targetReg, op1Reg, op1Reg, instOptions); } else { assert(ival == 3); emit->emitIns_SIMD_R_R_R_I(INS_shufps, attr, targetReg, op1Reg, op1Reg, - static_cast(0xFF)); + static_cast(0xFF), instOptions); } } else { assert(baseType == TYP_DOUBLE); assert(ival == 1); - emit->emitIns_SIMD_R_R_R(INS_unpckhpd, attr, targetReg, op1Reg, op1Reg); + emit->emitIns_SIMD_R_R_R(INS_unpckhpd, attr, targetReg, op1Reg, op1Reg, instOptions); } } else @@ -1679,11 +1745,12 @@ void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node) ins = ins_Move_Extend(baseType, false); attr = emitTypeSize(baseType); } - genHWIntrinsic_R_RM(node, ins, attr, targetReg, op1); + genHWIntrinsic_R_RM(node, ins, attr, targetReg, op1, instOptions); } else { assert(varTypeIsFloating(baseType)); + assert(instOptions == INS_OPTS_NONE); // Just use movaps for reg->reg moves as it has zero-latency on modern CPUs emit->emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); @@ -1710,10 +1777,12 @@ void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node) if (op1->isContained() || op1->isUsedFromSpillTemp()) { - genHWIntrinsic_R_RM(node, ins, attr, targetReg, op1); + genHWIntrinsic_R_RM(node, ins, attr, targetReg, op1, instOptions); } else { + assert(instOptions == INS_OPTS_NONE); + // Just use movaps for reg->reg moves as it has zero-latency on modern CPUs emit->emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ false); } @@ -1740,10 +1809,12 @@ void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node) { attr = emitTypeSize(TYP_SIMD16); } - genHWIntrinsic_R_RM(node, ins, attr, targetReg, op1); + genHWIntrinsic_R_RM(node, ins, attr, targetReg, op1, instOptions); } else { + assert(instOptions == INS_OPTS_NONE); + // We want to always emit the EA_32BYTE version here. // // For ToVector256Unsafe the upper bits don't matter and this allows same @@ -1780,7 +1851,7 @@ void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node) // Arguments: // node - The hardware intrinsic node // -void CodeGen::genX86BaseIntrinsic(GenTreeHWIntrinsic* node) +void CodeGen::genX86BaseIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) { NamedIntrinsic intrinsicId = node->GetHWIntrinsicId(); @@ -1798,7 +1869,7 @@ void CodeGen::genX86BaseIntrinsic(GenTreeHWIntrinsic* node) var_types targetType = node->TypeGet(); instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, targetType); - genHWIntrinsic_R_RM(node, ins, emitTypeSize(targetType), targetReg, op1); + genHWIntrinsic_R_RM(node, ins, emitTypeSize(targetType), targetReg, op1, instOptions); break; } @@ -1813,6 +1884,7 @@ void CodeGen::genX86BaseIntrinsic(GenTreeHWIntrinsic* node) case NI_X86Base_X64_DivRem: { assert(node->GetOperandCount() == 3); + assert(instOptions == INS_OPTS_NONE); // SIMD base type is from signature and can distinguish signed and unsigned var_types targetType = node->GetSimdBaseType(); @@ -1878,7 +1950,7 @@ void CodeGen::genSSEIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) { assert(targetType == TYP_LONG); instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType); - genHWIntrinsic_R_RM(node, ins, EA_8BYTE, targetReg, node->Op(1)); + genHWIntrinsic_R_RM(node, ins, EA_8BYTE, targetReg, node->Op(1), instOptions); break; } @@ -1896,6 +1968,7 @@ void CodeGen::genSSEIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) case NI_SSE_PrefetchNonTemporal: { assert(baseType == TYP_UBYTE); + assert(instOptions == INS_OPTS_NONE); // These do not support containment. assert(!node->Op(1)->isContained()); @@ -1951,7 +2024,7 @@ void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) { assert(baseType == TYP_LONG || baseType == TYP_ULONG); instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType); - genHWIntrinsic_R_RM(node, ins, emitTypeSize(baseType), targetReg, node->Op(1)); + genHWIntrinsic_R_RM(node, ins, emitTypeSize(baseType), targetReg, node->Op(1), instOptions); break; } @@ -1975,7 +2048,7 @@ void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) } instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType); - genHWIntrinsic_R_RM(node, ins, attr, targetReg, node->Op(1)); + genHWIntrinsic_R_RM(node, ins, attr, targetReg, node->Op(1), instOptions); break; } @@ -2017,7 +2090,7 @@ void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) // Arguments: // node - The hardware intrinsic node // -void CodeGen::genSSE41Intrinsic(GenTreeHWIntrinsic* node) +void CodeGen::genSSE41Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) { NamedIntrinsic intrinsicId = node->GetHWIntrinsicId(); GenTree* op1 = node->Op(1); @@ -2045,7 +2118,7 @@ void CodeGen::genSSE41Intrinsic(GenTreeHWIntrinsic* node) } else { - genHWIntrinsic_R_RM(node, ins, EA_16BYTE, targetReg, op1); + genHWIntrinsic_R_RM(node, ins, EA_16BYTE, targetReg, op1, instOptions); } break; } @@ -2060,7 +2133,7 @@ void CodeGen::genSSE41Intrinsic(GenTreeHWIntrinsic* node) emitAttr attr = emitActualTypeSize(node->TypeGet()); auto emitSwCase = [&](int8_t i) { - inst_RV_TT_IV(ins, attr, targetReg, op1, i); + inst_RV_TT_IV(ins, attr, targetReg, op1, i, instOptions); }; if (op2->IsCnsIntOrI()) @@ -2074,8 +2147,8 @@ void CodeGen::genSSE41Intrinsic(GenTreeHWIntrinsic* node) // We emit a fallback case for the scenario when the imm-op is not a constant. This should // normally happen when the intrinsic is called indirectly, such as via Reflection. However, it // can also occur if the consumer calls it directly and just doesn't pass a constant value. - regNumber baseReg = node->ExtractTempReg(); - regNumber offsReg = node->GetSingleTempReg(); + regNumber baseReg = internalRegisters.Extract(node); + regNumber offsReg = internalRegisters.GetSingle(node); genHWIntrinsicJumpTableFallback(intrinsicId, op2->GetRegNum(), baseReg, offsReg, emitSwCase); } break; @@ -2095,7 +2168,7 @@ void CodeGen::genSSE41Intrinsic(GenTreeHWIntrinsic* node) // Arguments: // node - The hardware intrinsic node // -void CodeGen::genSSE42Intrinsic(GenTreeHWIntrinsic* node) +void CodeGen::genSSE42Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) { NamedIntrinsic intrinsicId = node->GetHWIntrinsicId(); regNumber targetReg = node->GetRegNum(); @@ -2117,18 +2190,20 @@ void CodeGen::genSSE42Intrinsic(GenTreeHWIntrinsic* node) case NI_SSE42_Crc32: case NI_SSE42_X64_Crc32: { + assert(instOptions == INS_OPTS_NONE); + assert((op2->GetRegNum() != targetReg) || (op1Reg == targetReg)); emit->emitIns_Mov(INS_mov, emitTypeSize(targetType), targetReg, op1Reg, /* canSkip */ true); if ((baseType == TYP_UBYTE) || (baseType == TYP_USHORT)) // baseType is the type of the second argument { assert(targetType == TYP_INT); - genHWIntrinsic_R_RM(node, INS_crc32, emitTypeSize(baseType), targetReg, op2); + genHWIntrinsic_R_RM(node, INS_crc32, emitTypeSize(baseType), targetReg, op2, instOptions); } else { assert((targetType == TYP_INT) || (targetType == TYP_LONG)); - genHWIntrinsic_R_RM(node, INS_crc32, emitTypeSize(targetType), targetReg, op2); + genHWIntrinsic_R_RM(node, INS_crc32, emitTypeSize(targetType), targetReg, op2, instOptions); } break; @@ -2163,7 +2238,7 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption if (HWIntrinsicInfo::IsPermuteVar2x(intrinsicId)) { - genPermuteVar2x(node); + genPermuteVar2x(node, instOptions); return; } @@ -2184,6 +2259,8 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption case NI_AVX2_ConvertToInt32: case NI_AVX2_ConvertToUInt32: { + assert(instOptions == INS_OPTS_NONE); + op1Reg = op1->GetRegNum(); assert((baseType == TYP_INT) || (baseType == TYP_UINT)); instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType); @@ -2206,7 +2283,7 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption } else { - genHWIntrinsic_R_RM(node, ins, EA_32BYTE, targetReg, op1); + genHWIntrinsic_R_RM(node, ins, EA_32BYTE, targetReg, op1, instOptions); } break; } @@ -2216,6 +2293,8 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption case NI_AVX2_GatherMaskVector128: case NI_AVX2_GatherMaskVector256: { + assert(instOptions == INS_OPTS_NONE); + GenTree* op2 = node->Op(2); GenTree* op3 = node->Op(3); GenTree* lastOp = nullptr; @@ -2225,7 +2304,7 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption regNumber op2Reg = op2->GetRegNum(); regNumber addrBaseReg = REG_NA; regNumber addrIndexReg = REG_NA; - regNumber maskReg = node->ExtractTempReg(RBM_ALLFLOAT); + regNumber maskReg = internalRegisters.Extract(node, RBM_ALLFLOAT); if (numArgs == 5) { @@ -2258,7 +2337,7 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption // generate all-one mask vector assert(!emitter::isHighSimdReg(targetReg)); - emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, attr, maskReg, maskReg, maskReg); + emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, attr, maskReg, maskReg, maskReg, instOptions); } bool isVector128GatherWithVector256Index = (targetType == TYP_SIMD16) && (indexOp->TypeGet() == TYP_SIMD32); @@ -2309,6 +2388,8 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption case NI_AVX512F_AddMask: { + assert(instOptions == INS_OPTS_NONE); + uint32_t simdSize = node->GetSimdSize(); uint32_t count = simdSize / genTypeSize(baseType); @@ -2347,6 +2428,8 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption case NI_AVX512F_AndMask: { + assert(instOptions == INS_OPTS_NONE); + uint32_t simdSize = node->GetSimdSize(); uint32_t count = simdSize / genTypeSize(baseType); @@ -2385,6 +2468,8 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption case NI_AVX512F_AndNotMask: { + assert(instOptions == INS_OPTS_NONE); + uint32_t simdSize = node->GetSimdSize(); uint32_t count = simdSize / genTypeSize(baseType); @@ -2423,6 +2508,8 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption case NI_AVX512F_MoveMask: { + assert(instOptions == INS_OPTS_NONE); + uint32_t simdSize = node->GetSimdSize(); uint32_t count = simdSize / genTypeSize(baseType); @@ -2458,6 +2545,8 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption case NI_AVX512F_KORTEST: { + assert(instOptions == INS_OPTS_NONE); + uint32_t simdSize = node->GetSimdSize(); uint32_t count = simdSize / genTypeSize(baseType); @@ -2498,6 +2587,8 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption case NI_AVX512F_KTEST: { + assert(instOptions == INS_OPTS_NONE); + uint32_t simdSize = node->GetSimdSize(); uint32_t count = simdSize / genTypeSize(baseType); @@ -2534,6 +2625,8 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption case NI_AVX512F_NotMask: { + assert(instOptions == INS_OPTS_NONE); + uint32_t simdSize = node->GetSimdSize(); uint32_t count = simdSize / genTypeSize(baseType); @@ -2567,6 +2660,8 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption case NI_AVX512F_OrMask: { + assert(instOptions == INS_OPTS_NONE); + uint32_t simdSize = node->GetSimdSize(); uint32_t count = simdSize / genTypeSize(baseType); @@ -2605,6 +2700,8 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption case NI_AVX512F_ShiftLeftMask: { + assert(instOptions == INS_OPTS_NONE); + uint32_t simdSize = node->GetSimdSize(); uint32_t count = simdSize / genTypeSize(baseType); @@ -2644,6 +2741,8 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption case NI_AVX512F_ShiftRightMask: { + assert(instOptions == INS_OPTS_NONE); + uint32_t simdSize = node->GetSimdSize(); uint32_t count = simdSize / genTypeSize(baseType); @@ -2683,6 +2782,8 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption case NI_AVX512F_XorMask: { + assert(instOptions == INS_OPTS_NONE); + uint32_t simdSize = node->GetSimdSize(); uint32_t count = simdSize / genTypeSize(baseType); @@ -2787,7 +2888,7 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption // is passed in as the RM register and op1 is passed as the R register op1Reg = op1->GetRegNum(); - emit->emitIns_R_R(ins, attr, op1Reg, targetReg); + emit->emitIns_R_R(ins, attr, op1Reg, targetReg, instOptions); break; } @@ -2808,17 +2909,6 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node, insOpts instOption genProduceReg(node); } -//------------------------------------------------------------------------ -// genAESIntrinsic: Generates the code for an AES hardware intrinsic node -// -// Arguments: -// node - The hardware intrinsic node -// -void CodeGen::genAESIntrinsic(GenTreeHWIntrinsic* node) -{ - NYI("Implement AES intrinsic code generation"); -} - //------------------------------------------------------------------------ // genBMI1OrBMI2Intrinsic: Generates the code for a BMI1 and BMI2 hardware intrinsic node // @@ -2864,7 +2954,7 @@ void CodeGen::genBMI1OrBMI2Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptio case NI_BMI1_X64_ResetLowestSetBit: { assert((targetType == TYP_INT) || (targetType == TYP_LONG)); - genHWIntrinsic_R_RM(node, ins, emitTypeSize(node->TypeGet()), targetReg, node->Op(1)); + genHWIntrinsic_R_RM(node, ins, emitTypeSize(node->TypeGet()), targetReg, node->Op(1), instOptions); break; } @@ -2879,6 +2969,9 @@ void CodeGen::genBMI1OrBMI2Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptio case NI_BMI2_MultiplyNoFlags: case NI_BMI2_X64_MultiplyNoFlags: { + + assert(instOptions == INS_OPTS_NONE); + size_t numArgs = node->GetOperandCount(); assert(numArgs == 2 || numArgs == 3); @@ -2902,7 +2995,7 @@ void CodeGen::genBMI1OrBMI2Intrinsic(GenTreeHWIntrinsic* node, insOpts instOptio assert(op3Reg != op1Reg); assert(op3Reg != targetReg); assert(op3Reg != REG_EDX); - lowReg = node->GetSingleTempReg(); + lowReg = internalRegisters.GetSingle(node); assert(op3Reg != lowReg); assert(lowReg != targetReg); } @@ -3061,7 +3154,7 @@ void CodeGen::genFMAIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions) // Arguments: // node - The hardware intrinsic node // -void CodeGen::genPermuteVar2x(GenTreeHWIntrinsic* node) +void CodeGen::genPermuteVar2x(GenTreeHWIntrinsic* node, insOpts instOptions) { NamedIntrinsic intrinsicId = node->GetHWIntrinsicId(); assert(HWIntrinsicInfo::IsPermuteVar2x(intrinsicId)); @@ -3144,7 +3237,7 @@ void CodeGen::genPermuteVar2x(GenTreeHWIntrinsic* node) } assert(ins != INS_invalid); - genHWIntrinsic_R_R_R_RM(ins, attr, targetReg, emitOp1->GetRegNum(), emitOp2->GetRegNum(), emitOp3); + genHWIntrinsic_R_R_R_RM(ins, attr, targetReg, emitOp1->GetRegNum(), emitOp2->GetRegNum(), emitOp3, instOptions); genProduceReg(node); } @@ -3164,17 +3257,6 @@ void CodeGen::genLZCNTIntrinsic(GenTreeHWIntrinsic* node) genProduceReg(node); } -//------------------------------------------------------------------------ -// genPCLMULQDQIntrinsic: Generates the code for a PCLMULQDQ hardware intrinsic node -// -// Arguments: -// node - The hardware intrinsic node -// -void CodeGen::genPCLMULQDQIntrinsic(GenTreeHWIntrinsic* node) -{ - NYI("Implement PCLMULQDQ intrinsic code generation"); -} - //------------------------------------------------------------------------ // genPOPCNTIntrinsic: Generates the code for a POPCNT hardware intrinsic node // @@ -3233,7 +3315,7 @@ void CodeGen::genXCNTIntrinsic(GenTreeHWIntrinsic* node, instruction ins) { GetEmitter()->emitIns_R_R(INS_xor, EA_4BYTE, targetReg, targetReg); } - genHWIntrinsic_R_RM(node, ins, emitTypeSize(node->TypeGet()), targetReg, op1); + genHWIntrinsic_R_RM(node, ins, emitTypeSize(node->TypeGet()), targetReg, op1, INS_OPTS_NONE); } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index f1a48b2d2812..a207ac5bc604 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -15,103 +15,109 @@ // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Vector64 Intrinsics -HARDWARE_INTRINSIC(Vector64, Abs, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Add, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, AndNot, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, As, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsByte, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsDouble, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsInt16, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsInt32, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsInt64, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsNInt, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsNUInt, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsSByte, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsSingle, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsUInt16, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsUInt32, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsUInt64, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, BitwiseAnd, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, BitwiseOr, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Ceiling, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ConditionalSelect, 8, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ConvertToDouble, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, ConvertToInt32, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, ConvertToInt64, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, ConvertToSingle, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, ConvertToUInt32, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, ConvertToUInt64, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, Abs, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Add, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, AndNot, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, As, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsByte, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsDouble, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsInt16, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsInt32, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsInt64, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsNInt, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsNUInt, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsSByte, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsSingle, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsUInt16, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsUInt32, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, AsUInt64, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, BitwiseAnd, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, BitwiseOr, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Ceiling, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, ConditionalSelect, 8, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, ConvertToDouble, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToInt32, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToInt32Native, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToInt64, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToInt64Native, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToSingle, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToUInt32, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToUInt32Native, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToUInt64, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToUInt64Native, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, Create, 8, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, CreateScalar, 8, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, CreateScalarUnsafe, 8, 1, true, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_invalid, INS_invalid, INS_fmov, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(Vector64, CreateSequence, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Divide, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Dot, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Equals, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, EqualsAll, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, EqualsAny, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ExtractMostSignificantBits, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Floor, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, get_AllBitsSet, 8, 0, true, {INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, get_Indices, 8, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, get_One, 8, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, get_Zero, 8, 0, true, {INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) +HARDWARE_INTRINSIC(Vector64, CreateSequence, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Divide, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Dot, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, Equals, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, EqualsAll, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, EqualsAny, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ExtractMostSignificantBits, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, Floor, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, FusedMultiplyAdd, 8, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, get_AllBitsSet, 8, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, get_Indices, 8, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, get_One, 8, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, get_Zero, 8, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, GetElement, 8, 2, true, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, GreaterThan, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, GreaterThanAll, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, GreaterThanAny, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqual, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAll, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAny, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, LessThan, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, LessThanAll, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, LessThanAny, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, LessThanOrEqual, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, LessThanOrEqualAll, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, LessThanOrEqualAny, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Load, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, LoadAligned, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, LoadAlignedNonTemporal, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, LoadUnsafe, 8, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Max, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Min, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Multiply, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Narrow, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Negate, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, OnesComplement, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_Addition, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_BitwiseAnd, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector64, op_BitwiseOr, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector64, op_Division, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, GreaterThan, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, GreaterThanAll, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, GreaterThanAny, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqual, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAll, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAny, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, LessThan, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, LessThanAll, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, LessThanAny, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, LessThanOrEqual, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, LessThanOrEqualAll, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, LessThanOrEqualAny, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, Load, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, LoadAligned, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, LoadAlignedNonTemporal, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, LoadUnsafe, 8, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Max, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Min, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Multiply, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, MultiplyAddEstimate, 8, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Narrow, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Negate, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, OnesComplement, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, op_Addition, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, op_BitwiseAnd, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_Commutative) +HARDWARE_INTRINSIC(Vector64, op_BitwiseOr, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_Commutative) +HARDWARE_INTRINSIC(Vector64, op_Division, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, op_Equality, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative|HW_Flag_CanBenefitFromConstantProp) -HARDWARE_INTRINSIC(Vector64, op_ExclusiveOr, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, op_ExclusiveOr, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, op_Inequality, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative|HW_Flag_CanBenefitFromConstantProp) -HARDWARE_INTRINSIC(Vector64, op_LeftShift, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_Multiply, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_OnesComplement, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_RightShift, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_Subtraction, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_UnaryNegation, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_UnaryPlus, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_UnsignedRightShift, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ShiftLeft, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ShiftRightArithmetic, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ShiftRightLogical, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Shuffle, 8, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Sqrt, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Store, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, StoreAligned, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, StoreAlignedNonTemporal, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, StoreUnsafe, 8, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Subtract, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Sum, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, op_LeftShift, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, op_Multiply, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, op_OnesComplement, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, op_RightShift, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, op_Subtraction, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, op_UnaryNegation, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, op_UnaryPlus, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, op_UnsignedRightShift, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, ShiftLeft, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, ShiftRightArithmetic, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, ShiftRightLogical, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Shuffle, 8, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Sqrt, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Store, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, StoreAligned, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, StoreAlignedNonTemporal, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, StoreUnsafe, 8, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, Subtract, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Sum, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, ToScalar, 8, 1, true, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector64, ToVector128, 8, 1, true, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector64, ToVector128Unsafe, 8, 1, true, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(Vector64, WidenLower, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, WidenUpper, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, WidenLower, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, WidenUpper, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, WithElement, 8, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, Xor, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector64, Xor, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags @@ -119,110 +125,116 @@ HARDWARE_INTRINSIC(Vector64, Xor, // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Vector128 Intrinsics -HARDWARE_INTRINSIC(Vector128, Abs, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Add, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AndNot, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, As, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsByte, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsDouble, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsInt16, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsNInt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsNUInt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsSByte, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsSingle, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsUInt16, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsUInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsUInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsVector, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsVector2, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) +HARDWARE_INTRINSIC(Vector128, Abs, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Add, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, AndNot, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, As, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsByte, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsDouble, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsInt16, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsNInt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsNUInt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsSByte, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsSingle, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsUInt16, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsUInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsUInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsVector, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsVector2, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, AsVector3, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsVector4, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsVector128, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, BitwiseAnd, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, BitwiseOr, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Ceiling, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConditionalSelect, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConvertToDouble, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, ConvertToInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, ConvertToInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, ConvertToSingle, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, ConvertToUInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, ConvertToUInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsVector4, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsVector128, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, BitwiseAnd, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, BitwiseOr, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Ceiling, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, ConditionalSelect, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, ConvertToDouble, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt32Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt64Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToSingle, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt32Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt64Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, Create, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, CreateScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, true, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_fmov, INS_fmov}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(Vector128, CreateSequence, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Divide, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Equals, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, EqualsAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Floor, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, true, {INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, get_Indices, 16, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, get_One, 16, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, get_Zero, 16, 0, true, {INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport) +HARDWARE_INTRINSIC(Vector128, CreateSequence, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Divide, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, Equals, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, EqualsAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, Floor, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, FusedMultiplyAdd, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, get_Indices, 16, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, get_One, 16, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, get_Zero, 16, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, GetElement, 16, 2, true, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, GetLower, 16, 1, true, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector128, GetUpper, 16, 1, true, {INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Load, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LoadAligned, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LoadAlignedNonTemporal, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LoadUnsafe, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Max, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Min, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Multiply, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Narrow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Negate, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, OnesComplement, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_Addition, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_BitwiseAnd, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector128, op_BitwiseOr, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector128, op_Division, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, GreaterThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, GreaterThanAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, GreaterThanAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, LessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, Load, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, LoadAligned, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, LoadAlignedNonTemporal, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, LoadUnsafe, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Max, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Min, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Multiply, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, MultiplyAddEstimate, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Narrow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Negate, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, OnesComplement, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_Addition, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_BitwiseAnd, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_Commutative) +HARDWARE_INTRINSIC(Vector128, op_BitwiseOr, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_Commutative) +HARDWARE_INTRINSIC(Vector128, op_Division, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, op_Equality, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative|HW_Flag_CanBenefitFromConstantProp) -HARDWARE_INTRINSIC(Vector128, op_ExclusiveOr, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, op_ExclusiveOr, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, op_Inequality, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative|HW_Flag_CanBenefitFromConstantProp) -HARDWARE_INTRINSIC(Vector128, op_LeftShift, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_RightShift, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_UnsignedRightShift, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_Multiply, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_OnesComplement, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_Subtraction, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_UnaryNegation, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_UnaryPlus, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ShiftLeft, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ShiftRightArithmetic, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ShiftRightLogical, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Shuffle, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Store, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Subtract, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, op_LeftShift, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_RightShift, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_UnsignedRightShift, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_Multiply, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_OnesComplement, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_Subtraction, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_UnaryNegation, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_UnaryPlus, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, ShiftLeft, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, ShiftRightArithmetic, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, ShiftRightLogical, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Shuffle, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Store, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, Subtract, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, ToScalar, 16, 1, true, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(Vector128, WidenLower, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, WidenUpper, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, WidenLower, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, WidenUpper, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, WithElement, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(Vector128, WithLower, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, WithUpper, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Xor, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, Xor, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags @@ -328,8 +340,8 @@ HARDWARE_INTRINSIC(AdvSimd, LoadAndReplicateToVector128, HARDWARE_INTRINSIC(AdvSimd, LoadAndReplicateToVector64x2, 8, 1, true, {INS_ld2r, INS_ld2r, INS_ld2r, INS_ld2r, INS_ld2r, INS_ld2r, INS_invalid, INS_invalid, INS_ld2r, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport|HW_Flag_MultiReg|HW_Flag_NeedsConsecutiveRegisters) HARDWARE_INTRINSIC(AdvSimd, LoadAndReplicateToVector64x3, 8, 1, true, {INS_ld3r, INS_ld3r, INS_ld3r, INS_ld3r, INS_ld3r, INS_ld3r, INS_invalid, INS_invalid, INS_ld3r, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport|HW_Flag_MultiReg|HW_Flag_NeedsConsecutiveRegisters) HARDWARE_INTRINSIC(AdvSimd, LoadAndReplicateToVector64x4, 8, 1, true, {INS_ld4r, INS_ld4r, INS_ld4r, INS_ld4r, INS_ld4r, INS_ld4r, INS_invalid, INS_invalid, INS_ld4r, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport|HW_Flag_MultiReg|HW_Flag_NeedsConsecutiveRegisters) -HARDWARE_INTRINSIC(AdvSimd, LoadVector64, 8, 1, true, {INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AdvSimd, LoadVector128, 16, 1, true, {INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(AdvSimd, LoadVector64, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AdvSimd, LoadVector128, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(AdvSimd, LoadVector64x2AndUnzip, 8, 1, true, {INS_ld2, INS_ld2, INS_ld2, INS_ld2, INS_ld2, INS_ld2, INS_invalid, INS_invalid, INS_ld2, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport|HW_Flag_MultiReg|HW_Flag_NeedsConsecutiveRegisters) HARDWARE_INTRINSIC(AdvSimd, LoadVector64x3AndUnzip, 8, 1, true, {INS_ld3, INS_ld3, INS_ld3, INS_ld3, INS_ld3, INS_ld3, INS_invalid, INS_invalid, INS_ld3, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport|HW_Flag_MultiReg|HW_Flag_NeedsConsecutiveRegisters) HARDWARE_INTRINSIC(AdvSimd, LoadVector64x4AndUnzip, 8, 1, true, {INS_ld4, INS_ld4, INS_ld4, INS_ld4, INS_ld4, INS_ld4, INS_invalid, INS_invalid, INS_ld4, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport|HW_Flag_MultiReg|HW_Flag_NeedsConsecutiveRegisters) @@ -481,7 +493,7 @@ HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalScalar, HARDWARE_INTRINSIC(AdvSimd, SignExtendWideningLower, 8, 1, true, {INS_sxtl, INS_invalid, INS_sxtl, INS_invalid, INS_sxtl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(AdvSimd, SignExtendWideningUpper, 16, 1, true, {INS_sxtl2, INS_invalid, INS_sxtl2, INS_invalid, INS_sxtl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(AdvSimd, SqrtScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fsqrt, INS_fsqrt}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, Store, -1, 2, true, {INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(AdvSimd, Store, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(AdvSimd, StoreSelectedScalar, 8, 3, true, {INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1, INS_st1}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) HARDWARE_INTRINSIC(AdvSimd, StoreSelectedScalarVector64x2, 8, 3, true, {INS_st2, INS_st2, INS_st2, INS_st2, INS_st2, INS_st2, INS_invalid, INS_invalid, INS_st2, INS_invalid}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_NeedsConsecutiveRegisters) HARDWARE_INTRINSIC(AdvSimd, StoreSelectedScalarVector64x3, 8, 3, true, {INS_st3, INS_st3, INS_st3, INS_st3, INS_st3, INS_st3, INS_invalid, INS_invalid, INS_st3, INS_invalid}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_NeedsConsecutiveRegisters) diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h index ac110c2a0e1b..00b0739604b3 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64sve.h +++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h @@ -17,19 +17,116 @@ // SVE Intrinsics // Sve -HARDWARE_INTRINSIC(Sve, CreateTrueMaskByte, -1, 1, false, {INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskDouble, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskInt16, -1, 1, false, {INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskInt32, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskInt64, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskSByte, -1, 1, false, {INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskSingle, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt16, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt32, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt64, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask) - -HARDWARE_INTRINSIC(Sve, LoadVector, -1, 2, true, {INS_sve_ld1b, INS_sve_ld1b, INS_sve_ld1h, INS_sve_ld1h, INS_sve_ld1w, INS_sve_ld1w, INS_sve_ld1d, INS_sve_ld1d, INS_sve_ld1w, INS_sve_ld1d}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_LowMaskedOperation) - +HARDWARE_INTRINSIC(Sve, Abs, -1, -1, false, {INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_fabs, INS_sve_fabs}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation) +HARDWARE_INTRINSIC(Sve, AbsoluteDifference, -1, -1, false, {INS_sve_sabd, INS_sve_uabd, INS_sve_sabd, INS_sve_uabd, INS_sve_sabd, INS_sve_uabd, INS_sve_sabd, INS_sve_uabd, INS_sve_fabd, INS_sve_fabd}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, Add, -1, -1, false, {INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_fadd, INS_sve_fadd}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, AddAcross, -1, 1, true, {INS_sve_saddv, INS_sve_uaddv, INS_sve_saddv, INS_sve_uaddv, INS_sve_saddv, INS_sve_uaddv, INS_sve_uaddv, INS_sve_uaddv, INS_sve_faddv, INS_sve_faddv}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbeddedMaskedOperation) +HARDWARE_INTRINSIC(Sve, AddSaturate, -1, 2, true, {INS_sve_sqadd, INS_sve_uqadd, INS_sve_sqadd, INS_sve_uqadd, INS_sve_sqadd, INS_sve_uqadd, INS_sve_sqadd, INS_sve_uqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, And, -1, -1, false, {INS_sve_and, INS_sve_and, INS_sve_and, INS_sve_and, INS_sve_and, INS_sve_and, INS_sve_and, INS_sve_and, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, AndAcross, -1, -1, false, {INS_sve_andv, INS_sve_andv, INS_sve_andv, INS_sve_andv, INS_sve_andv, INS_sve_andv, INS_sve_andv, INS_sve_andv, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, BitwiseClear, -1, -1, false, {INS_sve_bic, INS_sve_bic, INS_sve_bic, INS_sve_bic, INS_sve_bic, INS_sve_bic, INS_sve_bic, INS_sve_bic, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, BooleanNot, -1, -1, false, {INS_sve_cnot, INS_sve_cnot, INS_sve_cnot, INS_sve_cnot, INS_sve_cnot, INS_sve_cnot, INS_sve_cnot, INS_sve_cnot, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, ConditionalSelect, -1, 3, true, {INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(Sve, Count16BitElements, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_cnth, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_NoFloatingPointUsed) +HARDWARE_INTRINSIC(Sve, Count32BitElements, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_cntw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_NoFloatingPointUsed) +HARDWARE_INTRINSIC(Sve, Count64BitElements, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_cntd, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_NoFloatingPointUsed) +HARDWARE_INTRINSIC(Sve, Count8BitElements, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_cntb, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_NoFloatingPointUsed) +HARDWARE_INTRINSIC(Sve, CreateFalseMaskByte, -1, 0, false, {INS_invalid, INS_sve_pfalse, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateFalseMaskDouble, -1, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_pfalse}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateFalseMaskInt16, -1, 0, false, {INS_invalid, INS_invalid, INS_sve_pfalse, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateFalseMaskInt32, -1, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_pfalse, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateFalseMaskInt64, -1, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_pfalse, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateFalseMaskSByte, -1, 0, false, {INS_sve_pfalse, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateFalseMaskSingle, -1, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_pfalse, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateFalseMaskUInt16, -1, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_pfalse, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateFalseMaskUInt32, -1, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_pfalse, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateFalseMaskUInt64, -1, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_pfalse, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskByte, -1, 1, false, {INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskDouble, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskInt16, -1, 1, false, {INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskInt32, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskInt64, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskSByte, -1, 1, false, {INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskSingle, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt16, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt32, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt64, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasEnumOperand|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateWhileLessThanMask16Bit, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_whilelt, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateWhileLessThanMask32Bit, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_whilelt, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateWhileLessThanMask64Bit, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_whilelt, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateWhileLessThanMask8Bit, -1, 2, false, {INS_invalid, INS_sve_whilelt, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateWhileLessThanOrEqualMask16Bit, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_whilele, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateWhileLessThanOrEqualMask32Bit, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_whilele, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateWhileLessThanOrEqualMask64Bit, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_whilele, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, CreateWhileLessThanOrEqualMask8Bit, -1, 2, false, {INS_invalid, INS_sve_whilele, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Sve, Divide, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sdiv, INS_sve_udiv, INS_sve_sdiv, INS_sve_udiv, INS_sve_fdiv, INS_sve_fdiv}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, DotProduct, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sdot, INS_sve_udot, INS_sve_sdot, INS_sve_udot, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve, DotProductBySelectedScalar, -1, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sdot, INS_sve_udot, INS_sve_sdot, INS_sve_udot, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_LowVectorOperation) +HARDWARE_INTRINSIC(Sve, FusedMultiplyAdd, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fmla, INS_sve_fmla}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation|HW_Flag_FmaIntrinsic|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, FusedMultiplyAddBySelectedScalar, -1, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fmla, INS_sve_fmla}, HW_Category_SIMDByIndexedElement, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_FmaIntrinsic|HW_Flag_LowVectorOperation) +HARDWARE_INTRINSIC(Sve, FusedMultiplyAddNegated, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fnmla, INS_sve_fnmla}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation|HW_Flag_FmaIntrinsic|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, FusedMultiplySubtract, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fmls, INS_sve_fmls}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation|HW_Flag_FmaIntrinsic|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, FusedMultiplySubtractBySelectedScalar, -1, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fmls, INS_sve_fmls}, HW_Category_SIMDByIndexedElement, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_FmaIntrinsic|HW_Flag_LowVectorOperation) +HARDWARE_INTRINSIC(Sve, FusedMultiplySubtractNegated, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fnmls, INS_sve_fnmls}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation|HW_Flag_FmaIntrinsic|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, LoadVector, -1, 2, true, {INS_sve_ld1b, INS_sve_ld1b, INS_sve_ld1h, INS_sve_ld1h, INS_sve_ld1w, INS_sve_ld1w, INS_sve_ld1d, INS_sve_ld1d, INS_sve_ld1w, INS_sve_ld1d}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToInt16, -1, 2, false, {INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToUInt16, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToUInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorByteZeroExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1b, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorInt16SignExtendToInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorInt16SignExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sh, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorInt16SignExtendToUInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sh, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorInt16SignExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sh, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorInt32SignExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorInt32SignExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sw, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToInt16, -1, 2, false, {INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToUInt16, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToUInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorSByteSignExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1sb, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1h, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1h, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToUInt32, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1h, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt16ZeroExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1h, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, LoadVectorUInt32ZeroExtendToUInt64, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ld1w, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, Max, -1, -1, false, {INS_sve_smax, INS_sve_umax, INS_sve_smax, INS_sve_umax, INS_sve_smax, INS_sve_umax, INS_sve_smax, INS_sve_umax, INS_sve_fmax, INS_sve_fmax}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve, MaxAcross, -1, -1, false, {INS_sve_smaxv, INS_sve_umaxv, INS_sve_smaxv, INS_sve_umaxv, INS_sve_smaxv, INS_sve_umaxv, INS_sve_smaxv, INS_sve_umaxv, INS_sve_fmaxv, INS_sve_fmaxv}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation) +HARDWARE_INTRINSIC(Sve, MaxNumber, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fmaxnm, INS_sve_fmaxnm}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve, MaxNumberAcross, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fmaxnmv, INS_sve_fmaxnmv}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation) +HARDWARE_INTRINSIC(Sve, Min, -1, -1, false, {INS_sve_smin, INS_sve_umin, INS_sve_smin, INS_sve_umin, INS_sve_smin, INS_sve_umin, INS_sve_smin, INS_sve_umin, INS_sve_fmin, INS_sve_fmin}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve, MinAcross, -1, -1, false, {INS_sve_sminv, INS_sve_uminv, INS_sve_sminv, INS_sve_uminv, INS_sve_sminv, INS_sve_uminv, INS_sve_sminv, INS_sve_uminv, INS_sve_fminv, INS_sve_fminv}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation) +HARDWARE_INTRINSIC(Sve, MinNumber, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fminnm, INS_sve_fminnm}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sve, MinNumberAcross, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fminnmv, INS_sve_fminnmv}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation) +HARDWARE_INTRINSIC(Sve, Multiply, -1, 2, true, {INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_mul, INS_sve_fmul, INS_sve_fmul}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, MultiplyAdd, -1, -1, false, {INS_sve_mla, INS_sve_mla, INS_sve_mla, INS_sve_mla, INS_sve_mla, INS_sve_mla, INS_sve_mla, INS_sve_mla, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation|HW_Flag_FmaIntrinsic|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, MultiplyBySelectedScalar, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fmul, INS_sve_fmul}, HW_Category_SIMDByIndexedElement, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_LowVectorOperation) +HARDWARE_INTRINSIC(Sve, MultiplyExtended, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_fmulx, INS_sve_fmulx}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, MultiplySubtract, -1, -1, false, {INS_sve_mls, INS_sve_mls, INS_sve_mls, INS_sve_mls, INS_sve_mls, INS_sve_mls, INS_sve_mls, INS_sve_mls, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation|HW_Flag_FmaIntrinsic|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, Negate, -1, -1, false, {INS_sve_neg, INS_invalid, INS_sve_neg, INS_invalid, INS_sve_neg, INS_invalid, INS_sve_neg, INS_invalid, INS_sve_fneg, INS_sve_fneg}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, Or, -1, -1, false, {INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_sve_orr, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, OrAcross, -1, -1, false, {INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_sve_orv, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, SignExtend16, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sxth, INS_invalid, INS_sve_sxth, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, SignExtend32, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sxtw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, SignExtend8, -1, -1, false, {INS_invalid, INS_invalid, INS_sve_sxtb, INS_invalid, INS_sve_sxtb, INS_invalid, INS_sve_sxtb, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, SignExtendWideningLower, -1, 1, true, {INS_sve_sunpklo, INS_invalid, INS_sve_sunpklo, INS_invalid, INS_sve_sunpklo, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Sve, SignExtendWideningUpper, -1, 1, true, {INS_sve_sunpkhi, INS_invalid, INS_sve_sunpkhi, INS_invalid, INS_sve_sunpkhi, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Sve, Subtract, -1, 2, true, {INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_sub, INS_sve_fsub, INS_sve_fsub}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, SubtractSaturate, -1, 2, true, {INS_sve_sqsub, INS_sve_uqsub, INS_sve_sqsub, INS_sve_uqsub, INS_sve_sqsub, INS_sve_uqsub, INS_sve_sqsub, INS_sve_uqsub, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, UnzipEven, -1, 2, true, {INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1, INS_sve_uzp1}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, UnzipOdd, -1, 2, true, {INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2, INS_sve_uzp2}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, Xor, -1, -1, false, {INS_sve_eor, INS_sve_eor, INS_sve_eor, INS_sve_eor, INS_sve_eor, INS_sve_eor, INS_sve_eor, INS_sve_eor, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, XorAcross, -1, -1, false, {INS_sve_eorv, INS_sve_eorv, INS_sve_eorv, INS_sve_eorv, INS_sve_eorv, INS_sve_eorv, INS_sve_eorv, INS_sve_eorv, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, ZeroExtend16, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_uxth, INS_invalid, INS_sve_uxth, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, ZeroExtend32, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_uxtw, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, ZeroExtend8, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_sve_uxtb, INS_invalid, INS_sve_uxtb, INS_invalid, INS_sve_uxtb, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation) +HARDWARE_INTRINSIC(Sve, ZeroExtendWideningLower, -1, 1, true, {INS_invalid, INS_sve_uunpklo, INS_invalid, INS_sve_uunpklo, INS_invalid, INS_sve_uunpklo, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Sve, ZeroExtendWideningUpper, -1, 1, true, {INS_invalid, INS_sve_uunpkhi, INS_invalid, INS_sve_uunpkhi, INS_invalid, INS_sve_uunpkhi, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Sve, ZipHigh, -1, 2, true, {INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2, INS_sve_zip2}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Sve, ZipLow, -1, 2, true, {INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1, INS_sve_zip1}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_SpecialCodeGen) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** @@ -38,11 +135,11 @@ HARDWARE_INTRINSIC(Sve, LoadVector, // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Special intrinsics that are generated during importing or lowering -HARDWARE_INTRINSIC(Sve, ConvertMaskToVector, -1, 1, true, {INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov}, HW_Category_Helper, HW_Flag_Scalable|HW_Flag_MaskedOperation) +HARDWARE_INTRINSIC(Sve, ConvertMaskToVector, -1, 1, true, {INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov}, HW_Category_Helper, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation) HARDWARE_INTRINSIC(Sve, ConvertVectorToMask, -1, 2, true, {INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne}, HW_Category_Helper, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask|HW_Flag_LowMaskedOperation) - HARDWARE_INTRINSIC(Sve, CreateTrueMaskAll, -1, -1, false, {INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue}, HW_Category_Helper, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask) + #endif // FEATURE_HW_INTRINSIC #undef HARDWARE_INTRINSIC diff --git a/src/coreclr/jit/hwintrinsiclistxarch.h b/src/coreclr/jit/hwintrinsiclistxarch.h index 07bc2e4838c8..aed1d0b1dfb1 100644 --- a/src/coreclr/jit/hwintrinsiclistxarch.h +++ b/src/coreclr/jit/hwintrinsiclistxarch.h @@ -29,325 +29,343 @@ // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Vector128 Intrinsics -HARDWARE_INTRINSIC(Vector128, Abs, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Add, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AndNot, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, As, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsByte, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsDouble, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsInt16, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsNInt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsNUInt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsSByte, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsSingle, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsUInt16, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsUInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsUInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsVector, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, Abs, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Add, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, AndNot, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, As, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsByte, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsDouble, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsInt16, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsNInt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsNUInt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsSByte, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsSingle, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsUInt16, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsUInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsUInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsVector, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, AsVector2, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movsd_simd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector128, AsVector3, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movups, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(Vector128, AsVector4, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsVector128, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, BitwiseAnd, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, BitwiseOr, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Ceiling, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, AsVector4, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, AsVector128, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, BitwiseAnd, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, BitwiseOr, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Ceiling, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, ConditionalSelect, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ConvertToDouble, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, ConvertToInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, ConvertToInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, ConvertToSingle, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, ConvertToUInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, ConvertToUInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToDouble, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt32Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt64Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToSingle, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt32Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt64Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, Create, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, CreateScalar, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, true, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(Vector128, CreateSequence, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Divide, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Equals, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector128, EqualsAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Floor, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, true, {INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_cmpps, INS_cmpps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(Vector128, get_Indices, 16, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, get_One, 16, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, get_Zero, 16, 0, false, {INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Vector128, CreateSequence, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Divide, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, Equals, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, EqualsAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, Floor, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, FusedMultiplyAdd, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, get_Indices, 16, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, get_One, 16, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, get_Zero, 16, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, GetElement, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_extractps, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, GreaterThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector128, GreaterThanAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Load, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LoadAligned, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LoadAlignedNonTemporal, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, LoadUnsafe, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Max, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Min, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Multiply, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Narrow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Negate, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, OnesComplement, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_Addition, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_BitwiseAnd, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector128, op_BitwiseOr, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector128, op_Division, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, GreaterThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, GreaterThanAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, GreaterThanAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, LessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAll, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAny, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, Load, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, LoadAligned, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, LoadAlignedNonTemporal, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, LoadUnsafe, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Max, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Min, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Multiply, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, MultiplyAddEstimate, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Narrow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Negate, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, OnesComplement, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_Addition, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_BitwiseAnd, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_BitwiseOr, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_Division, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, op_Equality, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative|HW_Flag_CanBenefitFromConstantProp) -HARDWARE_INTRINSIC(Vector128, op_ExclusiveOr, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, op_ExclusiveOr, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, op_Inequality, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative|HW_Flag_CanBenefitFromConstantProp) -HARDWARE_INTRINSIC(Vector128, op_LeftShift, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_Multiply, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_OnesComplement, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_RightShift, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_Subtraction, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_UnaryNegation, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_UnaryPlus, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_UnsignedRightShift, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ShiftLeft, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ShiftRightArithmetic, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ShiftRightLogical, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Shuffle, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Store, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Subtract, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, op_LeftShift, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_Multiply, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_OnesComplement, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_RightShift, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_Subtraction, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_UnaryNegation, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_UnaryPlus, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, op_UnsignedRightShift, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, ShiftLeft, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, ShiftRightArithmetic, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, ShiftRightLogical, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Shuffle, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Store, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, Subtract, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, ToScalar, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, ToVector256, 16, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, ToVector256Unsafe, 16, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(Vector128, ToVector512, 16, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(Vector128, WidenLower, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, WidenUpper, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, WidenLower, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, WidenUpper, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, WithElement, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, Xor, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector128, Xor, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Vector256 Intrinsics -HARDWARE_INTRINSIC(Vector256, Abs, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Add, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, AndNot, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, As, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, AsByte, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, AsDouble, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, AsInt16, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, AsInt32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, AsInt64, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, AsNInt, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, AsNUInt, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, AsSByte, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, AsSingle, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, AsUInt16, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, AsUInt32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, AsUInt64, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, AsVector, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, AsVector256, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, BitwiseAnd, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, BitwiseOr, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, Ceiling, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, Abs, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, Add, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, AndNot, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, As, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, AsByte, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, AsDouble, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, AsInt16, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, AsInt32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, AsInt64, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, AsNInt, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, AsNUInt, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, AsSByte, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, AsSingle, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, AsUInt16, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, AsUInt32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, AsUInt64, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, AsVector, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, AsVector256, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, BitwiseAnd, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, BitwiseOr, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, Ceiling, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, ConditionalSelect, 32, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, ConvertToDouble, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector256, ConvertToInt32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, ConvertToInt64, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector256, ConvertToSingle, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, ConvertToUInt32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector256, ConvertToUInt64, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToDouble, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToInt32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, ConvertToInt32Native, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, ConvertToInt64, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToInt64Native, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToSingle, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, ConvertToUInt32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToUInt32Native, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToUInt64, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToUInt64Native, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, Create, 32, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, CreateScalar, 32, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, CreateScalarUnsafe, 32, 1, true, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, CreateSequence, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, Divide, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Dot, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Equals, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector256, EqualsAll, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, EqualsAny, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ExtractMostSignificantBits, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Floor, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, get_AllBitsSet, 32, 0, true, {INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_cmpps, INS_cmpps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask|HW_Flag_AvxOnlyCompatible|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(Vector256, get_Indices, 32, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, get_One, 32, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, get_Zero, 32, 0, false, {INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, CreateSequence, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, Divide, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, Dot, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, Equals, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, EqualsAll, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, EqualsAny, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ExtractMostSignificantBits, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, Floor, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, FusedMultiplyAdd, 32, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, get_AllBitsSet, 32, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, get_Indices, 32, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, get_One, 32, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, get_Zero, 32, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, GetElement, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, GetLower, 32, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, GetUpper, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, GreaterThan, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector256, GreaterThanAll, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, GreaterThanAny, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqual, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAll, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAny, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, LessThan, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector256, LessThanAll, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, LessThanAny, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, LessThanOrEqual, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector256, LessThanOrEqualAll, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, LessThanOrEqualAny, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Load, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, LoadAligned, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, LoadAlignedNonTemporal, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, LoadUnsafe, 32, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, Max, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Min, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Multiply, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Narrow, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Negate, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, OnesComplement, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, op_Addition, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, op_BitwiseAnd, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, op_BitwiseOr, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, op_Division, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, GreaterThan, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, GreaterThanAll, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, GreaterThanAny, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqual, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAny, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAll, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, LessThan, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, LessThanAll, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, LessThanAny, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, LessThanOrEqual, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, LessThanOrEqualAny, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, LessThanOrEqualAll, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, Load, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, LoadAligned, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, LoadAlignedNonTemporal, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, LoadUnsafe, 32, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, Max, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, Min, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, Multiply, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, MultiplyAddEstimate, 32, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, Narrow, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, Negate, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, OnesComplement, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, op_Addition, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, op_BitwiseAnd, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, op_BitwiseOr, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, op_Division, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, op_Equality, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative|HW_Flag_CanBenefitFromConstantProp) -HARDWARE_INTRINSIC(Vector256, op_ExclusiveOr, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, op_ExclusiveOr, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, op_Inequality, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative|HW_Flag_CanBenefitFromConstantProp) -HARDWARE_INTRINSIC(Vector256, op_LeftShift, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, op_Multiply, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, op_OnesComplement, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, op_RightShift, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, op_Subtraction, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, op_UnaryNegation, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, op_UnaryPlus, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, op_UnsignedRightShift, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ShiftLeft, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ShiftRightArithmetic, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ShiftRightLogical, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Shuffle, 32, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Sqrt, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, Store, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, StoreAligned, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, StoreAlignedNonTemporal, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, StoreUnsafe, 32, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, Subtract, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Sum, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector256, op_LeftShift, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, op_Multiply, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, op_OnesComplement, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, op_RightShift, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, op_Subtraction, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, op_UnaryNegation, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, op_UnaryPlus, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, op_UnsignedRightShift, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, ShiftLeft, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, ShiftRightArithmetic, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, ShiftRightLogical, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, Shuffle, 32, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, Sqrt, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, Store, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, StoreAligned, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, StoreAlignedNonTemporal, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, StoreUnsafe, 32, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, Subtract, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, Sum, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, ToScalar, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, ToVector512, 32, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, ToVector512Unsafe, 32, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector256, WidenLower, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector256, WidenUpper, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, WidenLower, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, WidenUpper, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, WithElement, 32, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, WithLower, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, WithUpper, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, Xor, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, Xor, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Vector512 Intrinsics -HARDWARE_INTRINSIC(Vector512, Abs, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Add, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AndNot, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, As, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AsByte, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AsDouble, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AsInt16, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AsInt32, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AsInt64, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AsNInt, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AsNUInt, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AsSByte, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AsSingle, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AsUInt16, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AsUInt32, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AsUInt64, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AsVector, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, AsVector512, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, BitwiseAnd, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector512, Abs, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, Add, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, AndNot, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, As, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, AsByte, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, AsDouble, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, AsInt16, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, AsInt32, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, AsInt64, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, AsNInt, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, AsNUInt, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, AsSByte, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, AsSingle, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, AsUInt16, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, AsUInt32, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, AsUInt64, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, AsVector, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, AsVector512, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, BitwiseAnd, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, ConditionalSelect, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, BitwiseOr, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Ceiling, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector512, BitwiseOr, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, Ceiling, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, Create, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector512, CreateScalar, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector512, CreateScalarUnsafe, 64, 1, true, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(Vector512, CreateSequence, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, ConvertToDouble, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, ConvertToSingle, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, ConvertToInt32, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, ConvertToInt64, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, ConvertToUInt32, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, ConvertToUInt64, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, Divide, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Equals, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, EqualsAll, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, EqualsAny, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, ExtractMostSignificantBits, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Floor, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, get_AllBitsSet, 64, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector512, get_Indices, 64, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, get_One, 64, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, get_Zero, 64, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(Vector512, CreateSequence, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, ConvertToDouble, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToInt32, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToInt32Native, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToInt64, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToInt64Native, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToSingle, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToUInt32, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToUInt32Native, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToUInt64, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToUInt64Native, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, Divide, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, Equals, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, EqualsAll, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, EqualsAny, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ExtractMostSignificantBits, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, Floor, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, FusedMultiplyAdd, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, get_AllBitsSet, 64, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, get_Indices, 64, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, get_One, 64, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, get_Zero, 64, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, GetElement, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, GetLower, 64, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector512, GetLower128, 64, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, GetUpper, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, GreaterThan, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector512, GreaterThanAll, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, GreaterThanAny, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqualAll, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqualAny, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, LessThan, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector512, LessThanAll, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, LessThanAny, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, LessThanOrEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector512, LessThanOrEqualAll, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, LessThanOrEqualAny, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Load, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, LoadAligned, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, LoadAlignedNonTemporal, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, LoadUnsafe, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Max, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Min, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Multiply, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Narrow, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Negate, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, OnesComplement, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_Addition, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_BitwiseAnd, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector512, op_BitwiseOr, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector512, op_Division, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector512, GreaterThan, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, GreaterThanAll, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, GreaterThanAny, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqualAll, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqualAny, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, LessThan, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, LessThanAll, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, LessThanAny, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, LessThanOrEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, LessThanOrEqualAll, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, LessThanOrEqualAny, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, Load, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, LoadAligned, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, LoadAlignedNonTemporal, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, LoadUnsafe, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, Max, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, Min, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, Multiply, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, MultiplyAddEstimate, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, Narrow, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, Negate, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, OnesComplement, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, op_Addition, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, op_BitwiseAnd, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, op_BitwiseOr, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, op_Division, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, op_Equality, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative|HW_Flag_CanBenefitFromConstantProp) -HARDWARE_INTRINSIC(Vector512, op_ExclusiveOr, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector512, op_ExclusiveOr, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, op_Inequality, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative|HW_Flag_CanBenefitFromConstantProp) -HARDWARE_INTRINSIC(Vector512, op_LeftShift, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_Multiply, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_OnesComplement, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_RightShift, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_Subtraction, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_UnaryNegation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_UnaryPlus, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_UnsignedRightShift, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, ShiftLeft, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, ShiftRightArithmetic, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, ShiftRightLogical, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Shuffle, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Sqrt, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Store, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, StoreAligned, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, StoreAlignedNonTemporal, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, StoreUnsafe, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Subtract, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Sum, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector512, op_LeftShift, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, op_Multiply, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, op_OnesComplement, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, op_RightShift, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, op_Subtraction, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, op_UnaryNegation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, op_UnaryPlus, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, op_UnsignedRightShift, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, ShiftLeft, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, ShiftRightArithmetic, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, ShiftRightLogical, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, Shuffle, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, Sqrt, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, Store, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, StoreAligned, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, StoreAlignedNonTemporal, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, StoreUnsafe, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, Subtract, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, Sum, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, ToScalar, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, WidenLower, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, WidenUpper, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, WidenLower, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, WidenUpper, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, WithElement, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, WithLower, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector512, WithUpper, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Xor, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(Vector512, Xor, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags @@ -373,10 +391,10 @@ HARDWARE_INTRINSIC(X86Base_X64, DivRem, // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSE Intrinsics -HARDWARE_INTRINSIC(SSE, Add, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_addps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(SSE, Add, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_addps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE, AddScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_addss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE, And, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(SSE, AndNot, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andnps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(SSE, And, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE, AndNot, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andnps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE, CompareEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE, CompareScalarOrderedEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE, CompareScalarEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) @@ -397,7 +415,7 @@ HARDWARE_INTRINSIC(SSE, CompareLessThanOrEqual, HARDWARE_INTRINSIC(SSE, CompareScalarOrderedLessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE, CompareScalarLessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE, CompareScalarUnorderedLessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE, CompareNotEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(SSE, CompareNotEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE, CompareScalarOrderedNotEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE, CompareScalarNotEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE, CompareScalarUnorderedNotEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) @@ -416,24 +434,24 @@ HARDWARE_INTRINSIC(SSE, CompareScalarUnordered, HARDWARE_INTRINSIC(SSE, ConvertToInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE, ConvertScalarToVector128Single, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2ss32, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE, ConvertToInt32WithTruncation, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttss2si32, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE, Divide, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(SSE, Divide, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE, DivideScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE, LoadAlignedVector128, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movaps, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE, LoadHigh, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movhps, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE, LoadLow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movlps, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE, LoadScalarVector128, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE, LoadVector128, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movups, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(SSE, Max, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(SSE, LoadVector128, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(SSE, Max, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE, MaxScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE, Min, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(SSE, Min, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE, MinScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE, MoveHighToLow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movhlps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment) HARDWARE_INTRINSIC(SSE, MoveLowToHigh, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movlhps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment) HARDWARE_INTRINSIC(SSE, MoveMask, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movmskps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE, MoveScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoContainment) -HARDWARE_INTRINSIC(SSE, Multiply, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mulps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(SSE, Multiply, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mulps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE, MultiplyScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mulss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE, Or, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_orps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(SSE, Or, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_orps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE, Prefetch0, 0, 1, false, {INS_invalid, INS_prefetcht0, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics|HW_Flag_SpecialSideEffect_Other) HARDWARE_INTRINSIC(SSE, Prefetch1, 0, 1, false, {INS_invalid, INS_prefetcht1, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics|HW_Flag_SpecialSideEffect_Other) HARDWARE_INTRINSIC(SSE, Prefetch2, 0, 1, false, {INS_invalid, INS_prefetcht2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics|HW_Flag_SpecialSideEffect_Other) @@ -442,21 +460,21 @@ HARDWARE_INTRINSIC(SSE, Reciprocal, HARDWARE_INTRINSIC(SSE, ReciprocalScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rcpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE, ReciprocalSqrt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rsqrtps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE, ReciprocalSqrtScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rsqrtss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, Shuffle, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_shufps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(SSE, Sqrt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE, Shuffle, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_shufps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE, Sqrt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE, SqrtScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE, Store, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movups, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(SSE, Store, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE, StoreAligned, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movaps, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE, StoreAlignedNonTemporal, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movntps, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE, StoreFence, 0, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics|HW_Flag_SpecialSideEffect_Barrier) HARDWARE_INTRINSIC(SSE, StoreHigh, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movhps, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE, StoreLow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movlps, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE, StoreScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(SSE, Subtract, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_subps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(SSE, Subtract, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_subps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE, SubtractScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_subss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE, UnpackHigh, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_unpckhps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE, UnpackLow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_unpcklps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE, Xor, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_xorps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(SSE, UnpackHigh, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_unpckhps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE, UnpackLow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_unpcklps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE, Xor, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_xorps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags @@ -472,12 +490,12 @@ HARDWARE_INTRINSIC(SSE_X64, ConvertScalarToVector128Single, // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSE2 Intrinsics -HARDWARE_INTRINSIC(SSE2, Add, 16, 2, true, {INS_paddb, INS_paddb, INS_paddw, INS_paddw, INS_paddd, INS_paddd, INS_paddq, INS_paddq, INS_invalid, INS_addpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(SSE2, AddSaturate, 16, 2, true, {INS_paddsb, INS_paddusb, INS_paddsw, INS_paddusw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(SSE2, Add, 16, 2, true, {INS_paddb, INS_paddb, INS_paddw, INS_paddw, INS_paddd, INS_paddd, INS_paddq, INS_paddq, INS_invalid, INS_addpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, AddSaturate, 16, 2, true, {INS_paddsb, INS_paddusb, INS_paddsw, INS_paddusw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE2, AddScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_addsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2, And, 16, 2, true, {INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_invalid, INS_andpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(SSE2, AndNot, 16, 2, true, {INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_invalid, INS_andnpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(SSE2, Average, 16, 2, true, {INS_invalid, INS_pavgb, INS_invalid, INS_pavgw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(SSE2, And, 16, 2, true, {INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_invalid, INS_andpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, AndNot, 16, 2, true, {INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_invalid, INS_andnpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, Average, 16, 2, true, {INS_invalid, INS_pavgb, INS_invalid, INS_pavgw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE2, CompareEqual, 16, 2, true, {INS_pcmpeqb, INS_pcmpeqb, INS_pcmpeqw, INS_pcmpeqw, INS_pcmpeqd, INS_pcmpeqd, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarOrderedEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) @@ -486,7 +504,7 @@ HARDWARE_INTRINSIC(SSE2, CompareGreaterThan, HARDWARE_INTRINSIC(SSE2, CompareScalarOrderedGreaterThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarGreaterThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarUnorderedGreaterThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2, CompareGreaterThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(SSE2, CompareGreaterThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarOrderedGreaterThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarGreaterThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarUnorderedGreaterThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) @@ -494,38 +512,38 @@ HARDWARE_INTRINSIC(SSE2, CompareLessThan, HARDWARE_INTRINSIC(SSE2, CompareScalarOrderedLessThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarLessThan, 16, 2, true, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarUnorderedLessThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2, CompareLessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(SSE2, CompareLessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarOrderedLessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarLessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarUnorderedLessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2, CompareNotEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(SSE2, CompareScalarOrderedNotEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2, CompareNotEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE2, CompareScalarOrderedNotEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarNotEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE2, CompareScalarUnorderedNotEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2, CompareScalarUnorderedNotEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, CompareNotGreaterThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarNotGreaterThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareNotGreaterThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarNotGreaterThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareNotLessThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarNotLessThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE2, CompareNotLessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(SSE2, CompareNotLessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarNotLessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE2, CompareOrdered, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(SSE2, CompareOrdered, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarOrdered, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE2, CompareUnordered, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(SSE2, CompareUnordered, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, CompareScalarUnordered, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, ConvertToInt32, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, ConvertToInt32WithTruncation, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttsd2si32}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, ConvertToUInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2, ConvertToVector128Double, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2pd, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2pd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2, ConvertToVector128Double, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2pd, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2pd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, ConvertScalarToVector128Double, 16, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2sd32, INS_invalid, INS_invalid, INS_invalid, INS_cvtss2sd, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(SSE2, ConvertToVector128Int32, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2dq, INS_cvtpd2dq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2, ConvertToVector128Int32, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2dq, INS_cvtpd2dq}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, ConvertScalarToVector128Int32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2, ConvertToVector128Int32WithTruncation, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttps2dq, INS_cvttpd2dq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2, ConvertToVector128Single, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2ps}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2, ConvertToVector128Int32WithTruncation, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttps2dq, INS_cvttpd2dq}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2, ConvertToVector128Single, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2ps}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, ConvertScalarToVector128Single, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsd2ss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE2, ConvertScalarToVector128UInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2, Divide, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(SSE2, Divide, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE2, DivideScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE2, Extract, 16, 2, false, {INS_invalid, INS_invalid, INS_pextrw, INS_pextrw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, Insert, 16, 3, false, {INS_invalid, INS_invalid, INS_pinsrw, INS_pinsrw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_CanBenefitFromConstantProp) @@ -534,47 +552,47 @@ HARDWARE_INTRINSIC(SSE2, LoadFence, HARDWARE_INTRINSIC(SSE2, LoadHigh, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movhpd}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, LoadLow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movlpd}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, LoadScalarVector128, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_movd, INS_movq, INS_movq, INS_invalid, INS_movsd_simd}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2, LoadVector128, 16, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_invalid, INS_movupd}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(SSE2, LoadVector128, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(SSE2, MaskMove, 16, 3, false, {INS_maskmovdqu, INS_maskmovdqu, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(SSE2, Max, 16, 2, true, {INS_invalid, INS_pmaxub, INS_pmaxsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxpd}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(SSE2, Max, 16, 2, true, {INS_invalid, INS_pmaxub, INS_pmaxsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxpd}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE2, MemoryFence, 0, 0, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics|HW_Flag_SpecialSideEffect_Barrier) HARDWARE_INTRINSIC(SSE2, MaxScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2, Min, 16, 2, true, {INS_invalid, INS_pminub, INS_pminsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minpd}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(SSE2, Min, 16, 2, true, {INS_invalid, INS_pminub, INS_pminsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minpd}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE2, MinScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE2, MoveMask, 16, 1, true, {INS_pmovmskb, INS_pmovmskb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movmskpd}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE2, MoveScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movq, INS_movq, INS_invalid, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_NoContainment) -HARDWARE_INTRINSIC(SSE2, Multiply, 16, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmuludq, INS_invalid, INS_mulpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(SSE2, MultiplyHigh, 16, 2, true, {INS_invalid, INS_invalid, INS_pmulhw, INS_pmulhuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(SSE2, MultiplyAddAdjacent, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmaddwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(SSE2, MultiplyLow, 16, 2, false, {INS_invalid, INS_invalid, INS_pmullw, INS_pmullw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(SSE2, Multiply, 16, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmuludq, INS_invalid, INS_mulpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, MultiplyHigh, 16, 2, true, {INS_invalid, INS_invalid, INS_pmulhw, INS_pmulhuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, MultiplyAddAdjacent, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmaddwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, MultiplyLow, 16, 2, false, {INS_invalid, INS_invalid, INS_pmullw, INS_pmullw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE2, MultiplyScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mulsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2, Or, 16, 2, true, {INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_invalid, INS_orpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(SSE2, PackSignedSaturate, 16, 2, true, {INS_packsswb, INS_invalid, INS_packssdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2, PackUnsignedSaturate, 16, 2, false, {INS_invalid, INS_packuswb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2, SumAbsoluteDifferences, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_psadbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2, ShiftLeftLogical, 16, 2, true, {INS_invalid, INS_invalid, INS_psllw, INS_psllw, INS_pslld, INS_pslld, INS_psllq, INS_psllq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(SSE2, Or, 16, 2, true, {INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_invalid, INS_orpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, PackSignedSaturate, 16, 2, true, {INS_packsswb, INS_invalid, INS_packssdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, PackUnsignedSaturate, 16, 2, false, {INS_invalid, INS_packuswb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, SumAbsoluteDifferences, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_psadbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(SSE2, ShiftLeftLogical, 16, 2, true, {INS_invalid, INS_invalid, INS_psllw, INS_psllw, INS_pslld, INS_pslld, INS_psllq, INS_psllq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE2, ShiftLeftLogical128BitLane, 16, 2, false, {INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(SSE2, ShiftRightArithmetic, 16, 2, true, {INS_invalid, INS_invalid, INS_psraw, INS_invalid, INS_psrad, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(SSE2, ShiftRightLogical, 16, 2, true, {INS_invalid, INS_invalid, INS_psrlw, INS_psrlw, INS_psrld, INS_psrld, INS_psrlq, INS_psrlq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(SSE2, ShiftRightArithmetic, 16, 2, true, {INS_invalid, INS_invalid, INS_psraw, INS_invalid, INS_psrad, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, ShiftRightLogical, 16, 2, true, {INS_invalid, INS_invalid, INS_psrlw, INS_psrlw, INS_psrld, INS_psrld, INS_psrlq, INS_psrlq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE2, ShiftRightLogical128BitLane, 16, 2, false, {INS_psrldq, INS_psrldq, INS_psrldq, INS_psrldq, INS_psrldq, INS_psrldq, INS_psrldq, INS_psrldq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(SSE2, Shuffle, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pshufd, INS_pshufd, INS_invalid, INS_invalid, INS_invalid, INS_shufpd}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(SSE2, ShuffleHigh, 16, 2, false, {INS_invalid, INS_invalid, INS_pshufhw, INS_pshufhw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(SSE2, ShuffleLow, 16, 2, false, {INS_invalid, INS_invalid, INS_pshuflw, INS_pshuflw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(SSE2, Sqrt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2, Shuffle, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pshufd, INS_pshufd, INS_invalid, INS_invalid, INS_invalid, INS_shufpd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, ShuffleHigh, 16, 2, false, {INS_invalid, INS_invalid, INS_pshufhw, INS_pshufhw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, ShuffleLow, 16, 2, false, {INS_invalid, INS_invalid, INS_pshuflw, INS_pshuflw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, Sqrt, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2, SqrtScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2, Store, 16, 2, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_invalid, INS_movupd}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(SSE2, Store, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE2, StoreAligned, 16, 2, true, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_invalid, INS_movapd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE2, StoreAlignedNonTemporal, 16, 2, true, {INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_invalid, INS_movntpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE2, StoreHigh, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movhpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE2, StoreLow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movlpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE2, StoreNonTemporal, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movnti, INS_movnti, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(SSE2, StoreScalar, 16, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_movd, INS_movq, INS_movq, INS_invalid, INS_movsd_simd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(SSE2, Subtract, 16, 2, true, {INS_psubb, INS_psubb, INS_psubw, INS_psubw, INS_psubd, INS_psubd, INS_psubq, INS_psubq, INS_invalid, INS_subpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(SSE2, SubtractSaturate, 16, 2, true, {INS_psubsb, INS_psubusb, INS_psubsw, INS_psubusw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(SSE2, Subtract, 16, 2, true, {INS_psubb, INS_psubb, INS_psubw, INS_psubw, INS_psubd, INS_psubd, INS_psubq, INS_psubq, INS_invalid, INS_subpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, SubtractSaturate, 16, 2, true, {INS_psubsb, INS_psubusb, INS_psubsw, INS_psubusw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE2, SubtractScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_subsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2, UnpackHigh, 16, 2, true, {INS_punpckhbw, INS_punpckhbw, INS_punpckhwd, INS_punpckhwd, INS_punpckhdq, INS_punpckhdq, INS_punpckhqdq, INS_punpckhqdq, INS_invalid, INS_unpckhpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2, UnpackLow, 16, 2, true, {INS_punpcklbw, INS_punpcklbw, INS_punpcklwd, INS_punpcklwd, INS_punpckldq, INS_punpckldq, INS_punpcklqdq, INS_punpcklqdq, INS_invalid, INS_unpcklpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2, Xor, 16, 2, true, {INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_invalid, INS_xorpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(SSE2, UnpackHigh, 16, 2, true, {INS_punpckhbw, INS_punpckhbw, INS_punpckhwd, INS_punpckhwd, INS_punpckhdq, INS_punpckhdq, INS_punpckhqdq, INS_punpckhqdq, INS_invalid, INS_unpckhpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, UnpackLow, 16, 2, true, {INS_punpcklbw, INS_punpcklbw, INS_punpcklwd, INS_punpcklwd, INS_punpckldq, INS_punpckldq, INS_punpcklqdq, INS_punpcklqdq, INS_invalid, INS_unpcklpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE2, Xor, 16, 2, true, {INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_invalid, INS_xorpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags @@ -608,15 +626,15 @@ HARDWARE_INTRINSIC(SSE3, MoveLowAndDuplicate, // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSSE3 Intrinsics -HARDWARE_INTRINSIC(SSSE3, Abs, 16, 1, true, {INS_pabsb, INS_invalid, INS_pabsw, INS_invalid, INS_pabsd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(SSSE3, AlignRight, 16, 3, false, {INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(SSSE3, Abs, 16, 1, true, {INS_pabsb, INS_invalid, INS_pabsw, INS_invalid, INS_pabsd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSSE3, AlignRight, 16, 3, false, {INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSSE3, HorizontalAdd, 16, 2, true, {INS_invalid, INS_invalid, INS_phaddw, INS_phaddw, INS_phaddd, INS_phaddd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSSE3, HorizontalAddSaturate, 16, 2, false, {INS_invalid, INS_invalid, INS_phaddsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSSE3, HorizontalSubtract, 16, 2, true, {INS_invalid, INS_invalid, INS_phsubw, INS_invalid, INS_phsubd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSSE3, HorizontalSubtractSaturate, 16, 2, false, {INS_invalid, INS_invalid, INS_phsubsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSSE3, MultiplyAddAdjacent, 16, 2, false, {INS_invalid, INS_invalid, INS_pmaddubsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSSE3, MultiplyHighRoundScale, 16, 2, false, {INS_invalid, INS_invalid, INS_pmulhrsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSSE3, Shuffle, 16, 2, false, {INS_pshufb, INS_pshufb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(SSSE3, MultiplyAddAdjacent, 16, 2, false, {INS_invalid, INS_invalid, INS_pmaddubsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSSE3, MultiplyHighRoundScale, 16, 2, false, {INS_invalid, INS_invalid, INS_pmulhrsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSSE3, Shuffle, 16, 2, false, {INS_pshufb, INS_pshufb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSSE3, Sign, 16, 2, true, {INS_psignb, INS_invalid, INS_psignw, INS_invalid, INS_psignd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** @@ -626,34 +644,34 @@ HARDWARE_INTRINSIC(SSSE3, Sign, // SSE41 Intrinsics HARDWARE_INTRINSIC(SSE41, Blend, 16, 3, true, {INS_invalid, INS_invalid, INS_pblendw, INS_pblendw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_blendps, INS_blendpd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE41, BlendVariable, 16, 3, true, {INS_pblendvb, INS_pblendvb, INS_pblendvb, INS_pblendvb, INS_pblendvb, INS_pblendvb, INS_pblendvb, INS_pblendvb, INS_blendvps, INS_blendvpd}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE41, Ceiling, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE41, Ceiling, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE41, CeilingScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE41, CompareEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pcmpeqq, INS_pcmpeqq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int16, 16, 1, true, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics|HW_Flag_MaybeMemoryLoad) HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int32, 16, 1, true, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics|HW_Flag_MaybeMemoryLoad) HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int64, 16, 1, true, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics|HW_Flag_MaybeMemoryLoad) HARDWARE_INTRINSIC(SSE41, DotProduct, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_dpps, INS_dppd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE41, Extract, 16, 2, true, {INS_pextrb, INS_pextrb, INS_invalid, INS_invalid, INS_pextrd, INS_pextrd, INS_invalid, INS_invalid, INS_extractps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiIns|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE41, Floor, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE41, Extract, 16, 2, true, {INS_pextrb, INS_pextrb, INS_invalid, INS_invalid, INS_pextrd, INS_pextrd, INS_invalid, INS_invalid, INS_extractps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE41, Floor, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE41, FloorScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE41, Insert, 16, 3, true, {INS_pinsrb, INS_pinsrb, INS_invalid, INS_invalid, INS_pinsrd, INS_pinsrd, INS_invalid, INS_invalid, INS_insertps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_CanBenefitFromConstantProp) HARDWARE_INTRINSIC(SSE41, LoadAlignedVector128NonTemporal, 16, 1, false, {INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE41, Max, 16, 2, true, {INS_pmaxsb, INS_invalid, INS_invalid, INS_pmaxuw, INS_pmaxsd, INS_pmaxud, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(SSE41, Min, 16, 2, true, {INS_pminsb, INS_invalid, INS_invalid, INS_pminuw, INS_pminsd, INS_pminud, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(SSE41, Max, 16, 2, true, {INS_pmaxsb, INS_invalid, INS_invalid, INS_pmaxuw, INS_pmaxsd, INS_pmaxud, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_Commutative) +HARDWARE_INTRINSIC(SSE41, Min, 16, 2, true, {INS_pminsb, INS_invalid, INS_invalid, INS_pminuw, INS_pminsd, INS_pminud, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_Commutative) HARDWARE_INTRINSIC(SSE41, MinHorizontal, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_phminposuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE41, MultipleSumAbsoluteDifferences, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_mpsadbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE41, Multiply, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmuldq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(SSE41, MultiplyLow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmulld, INS_pmulld, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(SSE41, PackUnsignedSaturate, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_packusdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE41, RoundCurrentDirection, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE41, Multiply, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmuldq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE41, MultiplyLow, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmulld, INS_pmulld, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE41, PackUnsignedSaturate, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_packusdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(SSE41, RoundCurrentDirection, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE41, RoundCurrentDirectionScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE41, RoundToNearestInteger, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE41, RoundToNearestInteger, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE41, RoundToNearestIntegerScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE41, RoundToNegativeInfinity, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE41, RoundToNegativeInfinity, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE41, RoundToNegativeInfinityScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE41, RoundToPositiveInfinity, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE41, RoundToPositiveInfinity, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE41, RoundToPositiveInfinityScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE41, RoundToZero, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE41, RoundToZero, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(SSE41, RoundToZeroScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE41, TestC, 16, 2, false, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(SSE41, TestNotZAndNotC, 16, 2, false, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoEvexSemantics) @@ -664,7 +682,7 @@ HARDWARE_INTRINSIC(SSE41, TestZ, // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSE41 64-bit-only Intrinsics -HARDWARE_INTRINSIC(SSE41_X64, Extract, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pextrq, INS_pextrq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiIns|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE41_X64, Extract, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pextrq, INS_pextrq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE41_X64, Insert, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pinsrq, INS_pinsrq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_CanBenefitFromConstantProp) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** @@ -673,8 +691,8 @@ HARDWARE_INTRINSIC(SSE41_X64, Insert, // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSE42 Intrinsics HARDWARE_INTRINSIC(SSE42, Crc32, 0, 2, false, {INS_invalid, INS_crc32, INS_invalid, INS_crc32, INS_invalid, INS_crc32, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(SSE42, CompareGreaterThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pcmpgtq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(SSE42, CompareLessThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pcmpgtq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(SSE42, CompareGreaterThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pcmpgtq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE42, CompareLessThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pcmpgtq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags @@ -688,91 +706,91 @@ HARDWARE_INTRINSIC(SSE42_X64, Crc32, // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AVX Intrinsics -HARDWARE_INTRINSIC(AVX, Add, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_addps, INS_addpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX, Add, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_addps, INS_addpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX, AddSubtract, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_addsubps, INS_addsubpd}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX, And, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andps, INS_andpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX, AndNot, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andnps, INS_andnpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX, And, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andps, INS_andpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, AndNot, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andnps, INS_andnpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX, Blend, 32, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_blendps, INS_blendpd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX, BlendVariable, 32, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vblendvps, INS_vblendvpd}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX, Ceiling, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AVX, Ceiling, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX, BroadcastScalarToVector128, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vbroadcastss, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX, BroadcastScalarToVector256, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vbroadcastss, INS_vbroadcastsd}, HW_Category_MemoryLoad, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX, BroadcastVector128ToVector256, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vbroadcastf128, INS_vbroadcastf128}, HW_Category_MemoryLoad, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, Compare, 32, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_IMM, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX, CompareEqual, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX, CompareGreaterThan, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX, CompareGreaterThanOrEqual, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX, CompareLessThan, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX, CompareLessThanOrEqual, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX, CompareNotEqual, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX, CompareNotGreaterThan, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX, CompareNotGreaterThanOrEqual, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX, CompareNotLessThan, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX, CompareNotLessThanOrEqual, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX, CompareOrdered, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX, CompareUnordered, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(AVX, Compare, 32, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_IMM, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX, CompareEqual, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX, CompareGreaterThan, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX, CompareGreaterThanOrEqual, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX, CompareLessThan, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX, CompareLessThanOrEqual, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX, CompareNotEqual, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX, CompareNotGreaterThan, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX, CompareNotGreaterThanOrEqual, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX, CompareNotLessThan, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX, CompareNotLessThanOrEqual, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX, CompareOrdered, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX, CompareUnordered, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX, CompareScalar, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_cmpsd}, HW_Category_IMM, HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX, ConvertToVector128Int32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2dq, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2dq}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, ConvertToVector128Single, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2ps}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX, ConvertToVector256Int32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2dq, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2dq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, ConvertToVector256Single, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX, ConvertToVector256Double, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2pd, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2pd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX, ConvertToVector128Int32WithTruncation, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttpd2dq, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, ConvertToVector256Int32WithTruncation, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttps2dq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX, Divide, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divps, INS_divpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX, ConvertToVector128Int32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2dq, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2dq}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, ConvertToVector128Single, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2ps}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, ConvertToVector256Int32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2dq, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2dq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, ConvertToVector256Single, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, ConvertToVector256Double, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2pd, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2pd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, ConvertToVector128Int32WithTruncation, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttpd2dq, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, ConvertToVector256Int32WithTruncation, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttps2dq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AVX, Divide, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divps, INS_divpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX, DotProduct, 32, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_dpps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX, DuplicateEvenIndexed, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movsldup, INS_movddup}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX, DuplicateOddIndexed, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movshdup, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, ExtractVector128, 32, 2, false, {INS_vextractf128, INS_vextractf128, INS_vextractf128, INS_vextractf128, INS_vextractf128, INS_vextractf128, INS_vextractf128, INS_vextractf128, INS_vextractf128, INS_vextractf128}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX, Floor, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AVX, ExtractVector128, 32, 2, false, {INS_vextractf128, INS_vextractf128, INS_vextractf128, INS_vextractf128, INS_vextractf128, INS_vextractf128, INS_vextractf128, INS_vextractf128, INS_vextractf128, INS_vextractf128}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, Floor, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX, HorizontalAdd, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_haddps, INS_haddpd}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX, HorizontalSubtract, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_hsubps, INS_hsubpd}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX, InsertVector128, 32, 3, false, {INS_vinsertf128, INS_vinsertf128, INS_vinsertf128, INS_vinsertf128, INS_vinsertf128, INS_vinsertf128, INS_vinsertf128, INS_vinsertf128, INS_vinsertf128, INS_vinsertf128}, HW_Category_IMM, HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX, InsertVector128, 32, 3, false, {INS_vinsertf128, INS_vinsertf128, INS_vinsertf128, INS_vinsertf128, INS_vinsertf128, INS_vinsertf128, INS_vinsertf128, INS_vinsertf128, INS_vinsertf128, INS_vinsertf128}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX, LoadAlignedVector256, 32, 1, true, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movaps, INS_movapd}, HW_Category_MemoryLoad, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX, LoadDquVector256, 32, 1, false, {INS_lddqu, INS_lddqu, INS_lddqu, INS_lddqu, INS_lddqu, INS_lddqu, INS_lddqu, INS_lddqu, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX, LoadVector256, 32, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX, Max, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxps, INS_maxpd}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX, Min, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minps, INS_minpd}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX, LoadVector256, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX, Max, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_maxps, INS_maxpd}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, Min, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minps, INS_minpd}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX, MaskLoad, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vmaskmovps, INS_vmaskmovpd}, HW_Category_MemoryLoad, HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX, MaskStore, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vmaskmovps, INS_vmaskmovpd}, HW_Category_MemoryStore, HW_Flag_NoContainment|HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX, MoveMask, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movmskps, INS_movmskpd}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX, Multiply, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mulps, INS_mulpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX, Or, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_orps, INS_orpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX, Permute, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermilps, INS_vpermilpd}, HW_Category_IMM, HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX, Multiply, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mulps, INS_mulpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, Or, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_orps, INS_orpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, Permute, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermilps, INS_vpermilpd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX, Permute2x128, 32, 3, false, {INS_vperm2f128, INS_vperm2f128, INS_vperm2f128, INS_vperm2f128, INS_vperm2f128, INS_vperm2f128, INS_vperm2f128, INS_vperm2f128, INS_vperm2f128, INS_vperm2f128}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX, PermuteVar, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermilpsvar, INS_vpermilpdvar}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AVX, PermuteVar, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermilpsvar, INS_vpermilpdvar}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX, Reciprocal, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rcpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX, ReciprocalSqrt, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rsqrtps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX, RoundCurrentDirection, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, RoundToNearestInteger, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, RoundToNegativeInfinity, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, RoundToPositiveInfinity, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, RoundToZero, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, Shuffle, 32, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_shufps, INS_shufpd}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX, Sqrt, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtps, INS_sqrtpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, Store, 32, 2, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(AVX, RoundCurrentDirection, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, RoundToNearestInteger, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, RoundToNegativeInfinity, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, RoundToPositiveInfinity, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, RoundToZero, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, Shuffle, 32, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_shufps, INS_shufpd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, Sqrt, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtps, INS_sqrtpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, Store, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(AVX, StoreAligned, 32, 2, true, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movaps, INS_movapd}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(AVX, StoreAlignedNonTemporal, 32, 2, true, {INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntps, INS_movntpd}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(AVX, Subtract, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_subps, INS_subpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX, Subtract, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_subps, INS_subpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX, TestC, -1, 2, true, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX, TestNotZAndNotC, -1, 2, true, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX, TestZ, -1, 2, true, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX, UnpackHigh, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_unpckhps, INS_unpckhpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, UnpackLow, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_unpcklps, INS_unpcklpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, Xor, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_xorps, INS_xorpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX, UnpackHigh, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_unpckhps, INS_unpckhpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, UnpackLow, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_unpcklps, INS_unpcklpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX, Xor, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_xorps, INS_xorpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AVX2 Intrinsics -HARDWARE_INTRINSIC(AVX2, Abs, 32, 1, true, {INS_pabsb, INS_invalid, INS_pabsw, INS_invalid, INS_pabsd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX2, Add, 32, 2, true, {INS_paddb, INS_paddb, INS_paddw, INS_paddw, INS_paddd, INS_paddd, INS_paddq, INS_paddq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX2, AddSaturate, 32, 2, true, {INS_paddsb, INS_paddusb, INS_paddsw, INS_paddusw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AVX2, AlignRight, 32, 3, false, {INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX2, And, 32, 2, false, {INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX2, AndNot, 32, 2, false, {INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX2, Average, 32, 2, true, {INS_invalid, INS_pavgb, INS_invalid, INS_pavgw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AVX2, Abs, 32, 1, true, {INS_pabsb, INS_invalid, INS_pabsw, INS_invalid, INS_pabsd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, Add, 32, 2, true, {INS_paddb, INS_paddb, INS_paddw, INS_paddw, INS_paddd, INS_paddd, INS_paddq, INS_paddq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, AddSaturate, 32, 2, true, {INS_paddsb, INS_paddusb, INS_paddsw, INS_paddusw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, AlignRight, 32, 3, false, {INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_palignr, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, And, 32, 2, false, {INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, AndNot, 32, 2, false, {INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, Average, 32, 2, true, {INS_invalid, INS_pavgb, INS_invalid, INS_pavgw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX2, Blend, -1, 3, true, {INS_invalid, INS_invalid, INS_pblendw, INS_pblendw, INS_vpblendd, INS_vpblendd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX2, BlendVariable, 32, 3, false, {INS_vpblendvb, INS_vpblendvb, INS_vpblendvb, INS_vpblendvb, INS_vpblendvb, INS_vpblendvb, INS_vpblendvb, INS_vpblendvb, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX2, BroadcastScalarToVector128, 16, 1, true, {INS_vpbroadcastb, INS_vpbroadcastb, INS_vpbroadcastw, INS_vpbroadcastw, INS_vpbroadcastd, INS_vpbroadcastd, INS_vpbroadcastq, INS_vpbroadcastq, INS_vbroadcastss, INS_movddup}, HW_Category_SIMDScalar, HW_Flag_MaybeMemoryLoad) @@ -781,7 +799,7 @@ HARDWARE_INTRINSIC(AVX2, BroadcastVector128ToVector256, HARDWARE_INTRINSIC(AVX2, CompareEqual, 32, 2, true, {INS_pcmpeqb, INS_pcmpeqb, INS_pcmpeqw, INS_pcmpeqw, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqq, INS_pcmpeqq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX2, CompareGreaterThan, 32, 2, true, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_pcmpgtq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX2, CompareLessThan, 32, 2, true, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_pcmpgtq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX2, ExtractVector128, 32, 2, false, {INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX2, ExtractVector128, 32, 2, false, {INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX2, ConvertToInt32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX2, ConvertToUInt32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int16, 32, 1, true, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_MaybeMemoryLoad) @@ -795,72 +813,73 @@ HARDWARE_INTRINSIC(AVX2, HorizontalAdd, HARDWARE_INTRINSIC(AVX2, HorizontalAddSaturate, 32, 2, false, {INS_invalid, INS_invalid, INS_phaddsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX2, HorizontalSubtract, 32, 2, true, {INS_invalid, INS_invalid, INS_phsubw, INS_invalid, INS_phsubd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX2, HorizontalSubtractSaturate, 32, 2, false, {INS_invalid, INS_invalid, INS_phsubsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX2, InsertVector128, 32, 3, false, {INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX2, InsertVector128, 32, 3, false, {INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX2, LoadAlignedVector256NonTemporal, 32, 1, false, {INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX2, MaskLoad, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmaskmovd, INS_vpmaskmovd, INS_vpmaskmovq, INS_vpmaskmovq, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX2, MaskStore, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmaskmovd, INS_vpmaskmovd, INS_vpmaskmovq, INS_vpmaskmovq, INS_invalid, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoContainment|HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX2, Max, 32, 2, true, {INS_pmaxsb, INS_pmaxub, INS_pmaxsw, INS_pmaxuw, INS_pmaxsd, INS_pmaxud, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX2, Min, 32, 2, true, {INS_pminsb, INS_pminub, INS_pminsw, INS_pminuw, INS_pminsd, INS_pminud, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX2, Max, 32, 2, true, {INS_pmaxsb, INS_pmaxub, INS_pmaxsw, INS_pmaxuw, INS_pmaxsd, INS_pmaxud, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AVX2, Min, 32, 2, true, {INS_pminsb, INS_pminub, INS_pminsw, INS_pminuw, INS_pminsd, INS_pminud, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_Commutative) HARDWARE_INTRINSIC(AVX2, MoveMask, 32, 1, false, {INS_pmovmskb, INS_pmovmskb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX2, Multiply, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmuldq, INS_pmuludq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX2, Multiply, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmuldq, INS_pmuludq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX2, MultipleSumAbsoluteDifferences, 32, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_mpsadbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX2, MultiplyAddAdjacent, 32, 2, true, {INS_invalid, INS_invalid, INS_pmaddubsw, INS_invalid, INS_pmaddwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX2, MultiplyHigh, 32, 2, true, {INS_invalid, INS_invalid, INS_pmulhw, INS_pmulhuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AVX2, MultiplyHighRoundScale, 32, 2, false, {INS_invalid, INS_invalid, INS_pmulhrsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX2, MultiplyLow, 32, 2, true, {INS_invalid, INS_invalid, INS_pmullw, INS_pmullw, INS_pmulld, INS_pmulld, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX2, Or, 32, 2, false, {INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX2, MultiplyAddAdjacent, 32, 2, true, {INS_invalid, INS_invalid, INS_pmaddubsw, INS_invalid, INS_pmaddwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, MultiplyHigh, 32, 2, true, {INS_invalid, INS_invalid, INS_pmulhw, INS_pmulhuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, MultiplyHighRoundScale, 32, 2, false, {INS_invalid, INS_invalid, INS_pmulhrsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, MultiplyLow, 32, 2, true, {INS_invalid, INS_invalid, INS_pmullw, INS_pmullw, INS_pmulld, INS_pmulld, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, Or, 32, 2, false, {INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX2, Permute2x128, 32, 3, false, {INS_vperm2i128, INS_vperm2i128, INS_vperm2i128, INS_vperm2i128, INS_vperm2i128, INS_vperm2i128, INS_vperm2i128, INS_vperm2i128, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX2, Permute4x64, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermq, INS_vpermq, INS_invalid, INS_vpermpd}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX2, PermuteVar8x32, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermd, INS_vpermd, INS_invalid, INS_invalid, INS_vpermps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AVX2, PackSignedSaturate, 32, 2, true, {INS_packsswb, INS_invalid, INS_packssdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX2, PackUnsignedSaturate, 32, 2, true, {INS_invalid, INS_packuswb, INS_invalid, INS_packusdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX2, ShiftLeftLogical, 32, 2, true, {INS_invalid, INS_invalid, INS_psllw, INS_psllw, INS_pslld, INS_pslld, INS_psllq, INS_psllq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX2, Permute4x64, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermq, INS_vpermq, INS_invalid, INS_vpermpd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, PermuteVar8x32, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermd, INS_vpermd, INS_invalid, INS_invalid, INS_vpermps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, PackSignedSaturate, 32, 2, true, {INS_packsswb, INS_invalid, INS_packssdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, PackUnsignedSaturate, 32, 2, true, {INS_invalid, INS_packuswb, INS_invalid, INS_packusdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, ShiftLeftLogical, 32, 2, true, {INS_invalid, INS_invalid, INS_psllw, INS_psllw, INS_pslld, INS_pslld, INS_psllq, INS_psllq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX2, ShiftLeftLogical128BitLane, 32, 2, false, {INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX2, ShiftLeftLogicalVariable, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsllvd, INS_vpsllvd, INS_vpsllvq, INS_vpsllvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX2, ShiftRightArithmetic, 32, 2, true, {INS_invalid, INS_invalid, INS_psraw, INS_invalid, INS_psrad, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX2, ShiftRightArithmeticVariable, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsravd, INS_vpsravd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX2, ShiftRightLogical, 32, 2, true, {INS_invalid, INS_invalid, INS_psrlw, INS_psrlw, INS_psrld, INS_psrld, INS_psrlq, INS_psrlq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX2, ShiftLeftLogicalVariable, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsllvd, INS_vpsllvd, INS_vpsllvq, INS_vpsllvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, ShiftRightArithmetic, 32, 2, true, {INS_invalid, INS_invalid, INS_psraw, INS_invalid, INS_psrad, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, ShiftRightArithmeticVariable, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsravd, INS_vpsravd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, ShiftRightLogical, 32, 2, true, {INS_invalid, INS_invalid, INS_psrlw, INS_psrlw, INS_psrld, INS_psrld, INS_psrlq, INS_psrlq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX2, ShiftRightLogical128BitLane, 32, 2, false, {INS_psrldq, INS_psrldq, INS_psrldq, INS_psrldq, INS_psrldq, INS_psrldq, INS_psrldq, INS_psrldq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX2, ShiftRightLogicalVariable, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsrlvd, INS_vpsrlvd, INS_vpsrlvq, INS_vpsrlvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX2, Shuffle, 32, 2, true, {INS_pshufb, INS_pshufb, INS_invalid, INS_invalid, INS_pshufd, INS_pshufd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_MaybeIMM) -HARDWARE_INTRINSIC(AVX2, ShuffleHigh, 32, 2, false, {INS_invalid, INS_invalid, INS_pshufhw, INS_pshufhw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX2, ShuffleLow, 32, 2, false, {INS_invalid, INS_invalid, INS_pshuflw, INS_pshuflw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX2, ShiftRightLogicalVariable, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsrlvd, INS_vpsrlvd, INS_vpsrlvq, INS_vpsrlvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, Shuffle, 32, 2, true, {INS_pshufb, INS_pshufb, INS_invalid, INS_invalid, INS_pshufd, INS_pshufd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_MaybeIMM) +HARDWARE_INTRINSIC(AVX2, ShuffleHigh, 32, 2, false, {INS_invalid, INS_invalid, INS_pshufhw, INS_pshufhw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, ShuffleLow, 32, 2, false, {INS_invalid, INS_invalid, INS_pshuflw, INS_pshuflw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX2, Sign, 32, 2, true, {INS_psignb, INS_invalid, INS_psignw, INS_invalid, INS_psignd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX2, SumAbsoluteDifferences, 32, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_psadbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX2, Subtract, 32, 2, true, {INS_psubb, INS_psubb, INS_psubw, INS_psubw, INS_psubd, INS_psubd, INS_psubq, INS_psubq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX2, SubtractSaturate, 32, 2, true, {INS_psubsb, INS_psubusb, INS_psubsw, INS_psubusw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX2, UnpackHigh, 32, 2, true, {INS_punpckhbw, INS_punpckhbw, INS_punpckhwd, INS_punpckhwd, INS_punpckhdq, INS_punpckhdq, INS_punpckhqdq, INS_punpckhqdq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX2, UnpackLow, 32, 2, true, {INS_punpcklbw, INS_punpcklbw, INS_punpcklwd, INS_punpcklwd, INS_punpckldq, INS_punpckldq, INS_punpcklqdq, INS_punpcklqdq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX2, Xor, 32, 2, false, {INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX2, Subtract, 32, 2, true, {INS_psubb, INS_psubb, INS_psubw, INS_psubw, INS_psubd, INS_psubd, INS_psubq, INS_psubq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, SubtractSaturate, 32, 2, true, {INS_psubsb, INS_psubusb, INS_psubsw, INS_psubusw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, UnpackHigh, 32, 2, true, {INS_punpckhbw, INS_punpckhbw, INS_punpckhwd, INS_punpckhwd, INS_punpckhdq, INS_punpckhdq, INS_punpckhqdq, INS_punpckhqdq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, UnpackLow, 32, 2, true, {INS_punpcklbw, INS_punpcklbw, INS_punpcklwd, INS_punpcklwd, INS_punpckldq, INS_punpckldq, INS_punpcklqdq, INS_punpcklqdq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX2, Xor, 32, 2, false, {INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AVX512F Intrinsics -HARDWARE_INTRINSIC(AVX512F, Abs, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pabsd, INS_invalid, INS_vpabsq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512F, Add, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_paddd, INS_paddd, INS_paddq, INS_paddq, INS_addps, INS_addpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbRoundingCompatible) +HARDWARE_INTRINSIC(AVX512F, Abs, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pabsd, INS_invalid, INS_vpabsq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, Add, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_paddd, INS_paddd, INS_paddq, INS_paddq, INS_addps, INS_addpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_EmbRoundingCompatible) HARDWARE_INTRINSIC(AVX512F, AddScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_addss, INS_addsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, AlignRight32, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_valignd, INS_valignd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, AlignRight64, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_valignq, INS_valignq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, And, 64, 2, true, {INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_vpandq, INS_vpandq, INS_andps, INS_andpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX512F, AndNot, 64, 2, true, {INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_vpandnq, INS_vpandnq, INS_andnps, INS_andnpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX512F, BlendVariable, 64, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpblendmd, INS_vpblendmd, INS_vpblendmq, INS_vpblendmq, INS_vblendmps, INS_vblendmpd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(AVX512F, AlignRight32, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_valignd, INS_valignd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, AlignRight64, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_valignq, INS_valignq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, And, 64, 2, true, {INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_pand, INS_vpandq, INS_vpandq, INS_andps, INS_andpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, AndNot, 64, 2, true, {INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_vpandnq, INS_vpandnq, INS_andnps, INS_andnpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, BlendVariable, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(AVX512F, BroadcastScalarToVector512, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpbroadcastd, INS_vpbroadcastd, INS_vpbroadcastq, INS_vpbroadcastq, INS_vbroadcastss, INS_vbroadcastsd}, HW_Category_SIMDScalar, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX512F, BroadcastVector128ToVector512, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vbroadcasti128, INS_vbroadcasti128, INS_invalid, INS_invalid, INS_vbroadcastf128, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MaybeMemoryLoad) HARDWARE_INTRINSIC(AVX512F, BroadcastVector256ToVector512, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vbroadcasti64x4, INS_vbroadcasti64x4, INS_invalid, INS_vbroadcastf64x4}, HW_Category_SimpleSIMD, HW_Flag_MaybeMemoryLoad) -HARDWARE_INTRINSIC(AVX512F, CompareEqual, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpcmpeqd, INS_vpcmpeqd, INS_vpcmpeqq, INS_vpcmpeqq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(AVX512F, CompareGreaterThan, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpcmpgtd, INS_vpcmpud, INS_vpcmpgtq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512F, CompareGreaterThanOrEqual, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512F, CompareLessThan, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512F, CompareLessThanOrEqual, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512F, CompareNotEqual, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(AVX512F, CompareNotGreaterThan, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512F, CompareNotGreaterThanOrEqual, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512F, CompareNotLessThan, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512F, CompareNotLessThanOrEqual, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512F, CompareOrdered, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512F, CompareUnordered, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(AVX512F, Compare, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F, CompareEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F, CompareGreaterThan, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F, CompareGreaterThanOrEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F, CompareLessThan, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F, CompareLessThanOrEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F, CompareNotEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F, CompareNotGreaterThan, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F, CompareNotGreaterThanOrEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F, CompareNotLessThan, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F, CompareNotLessThanOrEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F, CompareOrdered, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F, CompareUnordered, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(AVX512F, ConvertScalarToVector128Double, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2sd32, INS_vcvtusi2sd32, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(AVX512F, ConvertScalarToVector128Single, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2ss32, INS_vcvtusi2ss32, INS_invalid, INS_invalid, INS_invalid, INS_cvtsd2ss}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits|HW_Flag_EmbRoundingCompatible) HARDWARE_INTRINSIC(AVX512F, ConvertToInt32, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtss2si, INS_cvtsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_EmbRoundingCompatible) @@ -878,149 +897,149 @@ HARDWARE_INTRINSIC(AVX512F, ConvertToVector256Int16, HARDWARE_INTRINSIC(AVX512F, ConvertToVector256Int16WithSaturation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovsdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512F, ConvertToVector256Int32, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovqd, INS_vpmovqd, INS_invalid, INS_cvtpd2dq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_EmbRoundingCompatible) HARDWARE_INTRINSIC(AVX512F, ConvertToVector256Int32WithSaturation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovsqd, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector256Int32WithTruncation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttpd2dq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector256Single, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2ps}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbRoundingCompatible) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector256Int32WithTruncation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttpd2dq}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector256Single, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2ps}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_EmbRoundingCompatible) HARDWARE_INTRINSIC(AVX512F, ConvertToVector256UInt16, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovdw, INS_vpmovdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512F, ConvertToVector256UInt16WithSaturation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovusdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512F, ConvertToVector256UInt32, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovqd, INS_vpmovqd, INS_invalid, INS_vcvtpd2udq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_EmbRoundingCompatible) HARDWARE_INTRINSIC(AVX512F, ConvertToVector256UInt32WithSaturation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovusqd, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector256UInt32WithTruncation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttpd2udq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector512Double, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2pd, INS_vcvtudq2pd, INS_invalid, INS_invalid, INS_cvtps2pd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector512Int32, 64, -1, false, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2dq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector512Int32WithTruncation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttps2dq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector256UInt32WithTruncation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttpd2udq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector512Double, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2pd, INS_vcvtudq2pd, INS_invalid, INS_invalid, INS_cvtps2pd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector512Int32, 64, -1, false, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2dq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbRoundingCompatible) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector512Int32WithTruncation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttps2dq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512F, ConvertToVector512Int64, 64, 1, true, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector512Single, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2ps, INS_vcvtudq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector512UInt32, 64, -1, false, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2udq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector512UInt32WithTruncation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2udq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector512Single, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2ps, INS_vcvtudq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_EmbRoundingCompatible) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector512UInt32, 64, -1, false, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2udq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbRoundingCompatible) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector512UInt32WithTruncation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2udq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512F, ConvertToVector512UInt64, 64, 1, true, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512F, Divide, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divps, INS_divpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbRoundingCompatible) +HARDWARE_INTRINSIC(AVX512F, Divide, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divps, INS_divpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_EmbRoundingCompatible) HARDWARE_INTRINSIC(AVX512F, DivideScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divss, INS_divsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_EmbRoundingCompatible) HARDWARE_INTRINSIC(AVX512F, DuplicateEvenIndexed, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movsldup, INS_movddup}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX512F, DuplicateOddIndexed, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movshdup, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F, ExtractVector128, 64, 2, true, {INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextractf128, INS_vextractf128}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, ExtractVector256, 64, 2, true, {INS_vextracti64x4, INS_vextracti64x4, INS_vextracti64x4, INS_vextracti64x4, INS_vextracti64x4, INS_vextracti64x4, INS_vextracti64x4, INS_vextracti64x4, INS_vextractf64x4, INS_vextractf64x4}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, Fixup, 64, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfixupimmps, INS_vfixupimmpd}, HW_Category_IMM, HW_Flag_SpecialImport|HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX512F, ExtractVector128, 64, 2, true, {INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextractf128, INS_vextractf128}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, ExtractVector256, 64, 2, true, {INS_vextracti64x4, INS_vextracti64x4, INS_vextracti64x4, INS_vextracti64x4, INS_vextracti64x4, INS_vextracti64x4, INS_vextracti64x4, INS_vextracti64x4, INS_vextractf64x4, INS_vextractf64x4}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, Fixup, 64, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfixupimmps, INS_vfixupimmpd}, HW_Category_IMM, HW_Flag_SpecialImport|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512F, FixupScalar, 16, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfixupimmss, INS_vfixupimmsd}, HW_Category_IMM, HW_Flag_SpecialImport|HW_Flag_FullRangeIMM|HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(AVX512F, FusedMultiplyAdd, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmadd213ps, INS_vfmadd213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, FusedMultiplyAddScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmadd213ss, INS_vfmadd213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_CopyUpperBits|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, FusedMultiplyAddNegated, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmadd213ps, INS_vfnmadd213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, FusedMultiplyAddNegatedScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmadd213ss, INS_vfnmadd213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_CopyUpperBits|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, FusedMultiplyAddSubtract, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmaddsub213ps, INS_vfmaddsub213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, FusedMultiplySubtract, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmsub213ps, INS_vfmsub213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, FusedMultiplySubtractScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmsub213ss, INS_vfmsub213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_CopyUpperBits|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, FusedMultiplySubtractAdd, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmsubadd213ps, INS_vfmsubadd213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, FusedMultiplySubtractNegated, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmsub213ps, INS_vfnmsub213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, FusedMultiplySubtractNegatedScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmsub213ss, INS_vfnmsub213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_CopyUpperBits|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, GetExponent, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vgetexpps, INS_vgetexppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AVX512F, FusedMultiplyAdd, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmadd213ps, INS_vfmadd213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, FusedMultiplyAddScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmadd213ss, INS_vfmadd213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible|HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(AVX512F, FusedMultiplyAddNegated, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmadd213ps, INS_vfnmadd213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, FusedMultiplyAddNegatedScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmadd213ss, INS_vfnmadd213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible|HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(AVX512F, FusedMultiplyAddSubtract, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmaddsub213ps, INS_vfmaddsub213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, FusedMultiplySubtract, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmsub213ps, INS_vfmsub213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, FusedMultiplySubtractScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmsub213ss, INS_vfmsub213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible|HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(AVX512F, FusedMultiplySubtractAdd, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmsubadd213ps, INS_vfmsubadd213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, FusedMultiplySubtractNegated, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmsub213ps, INS_vfnmsub213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, FusedMultiplySubtractNegatedScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmsub213ss, INS_vfnmsub213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbRoundingCompatible|HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(AVX512F, GetExponent, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vgetexpps, INS_vgetexppd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512F, GetExponentScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vgetexpss, INS_vgetexpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(AVX512F, GetMantissa, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vgetmantps, INS_vgetmantpd}, HW_Category_IMM, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AVX512F, GetMantissa, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vgetmantps, INS_vgetmantpd}, HW_Category_IMM, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512F, GetMantissaScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vgetmantss, INS_vgetmantsd}, HW_Category_IMM, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(AVX512F, InsertVector128, 64, 3, true, {INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinsertf128, INS_vinsertf128}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, InsertVector256, 64, 3, true, {INS_vinserti64x4, INS_vinserti64x4, INS_vinserti64x4, INS_vinserti64x4, INS_vinserti64x4, INS_vinserti64x4, INS_vinserti64x4, INS_vinserti64x4, INS_vinsertf64x4, INS_vinsertf64x4}, HW_Category_IMM, HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX512F, InsertVector128, 64, 3, true, {INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinserti128, INS_vinsertf128, INS_vinsertf128}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, InsertVector256, 64, 3, true, {INS_vinserti64x4, INS_vinserti64x4, INS_vinserti64x4, INS_vinserti64x4, INS_vinserti64x4, INS_vinserti64x4, INS_vinserti64x4, INS_vinserti64x4, INS_vinsertf64x4, INS_vinsertf64x4}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512F, LoadAlignedVector512, 64, 1, true, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_vmovdqa64, INS_vmovdqa64, INS_movaps, INS_movapd}, HW_Category_MemoryLoad, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX512F, LoadAlignedVector512NonTemporal, 64, 1, false, {INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F, LoadVector512, 64, 1, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512F, Max, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmaxsd, INS_pmaxud, INS_vpmaxsq, INS_vpmaxuq, INS_maxps, INS_maxpd}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX512F, Min, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pminsd, INS_pminud, INS_vpminsq, INS_vpminuq, INS_minps, INS_minpd}, HW_Category_SimpleSIMD, HW_Flag_MaybeCommutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX512F, Multiply, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmuldq, INS_pmuludq, INS_mulps, INS_mulpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbRoundingCompatible) +HARDWARE_INTRINSIC(AVX512F, LoadVector512, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F, Max, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmaxsd, INS_pmaxud, INS_vpmaxsq, INS_vpmaxuq, INS_maxps, INS_maxpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_MaybeCommutative) +HARDWARE_INTRINSIC(AVX512F, Min, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pminsd, INS_pminud, INS_vpminsq, INS_vpminuq, INS_minps, INS_minpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_MaybeCommutative) +HARDWARE_INTRINSIC(AVX512F, Multiply, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmuldq, INS_pmuludq, INS_mulps, INS_mulpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_EmbRoundingCompatible) HARDWARE_INTRINSIC(AVX512F, MultiplyScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mulss, INS_mulsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, MultiplyLow, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmulld, INS_pmulld, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX512F, Or, 64, 2, true, {INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_vporq, INS_vporq, INS_orps, INS_orpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX512F, Permute2x64, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermilpd}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, Permute4x32, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermilps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, Permute4x64, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermq, INS_vpermq, INS_invalid, INS_vpermpd}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, PermuteVar2x64, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermilpdvar}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F, PermuteVar4x32, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermilpsvar, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F, PermuteVar8x64, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermq_reg, INS_vpermq_reg, INS_invalid, INS_vpermpd_reg}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AVX512F, PermuteVar8x64x2, 64, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermt2q, INS_vpermt2q, INS_invalid, INS_vpermt2pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(AVX512F, PermuteVar16x32, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermd, INS_vpermd, INS_invalid, INS_invalid, INS_vpermps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AVX512F, PermuteVar16x32x2, 64, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermt2d, INS_vpermt2d, INS_invalid, INS_invalid, INS_vpermt2ps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(AVX512F, Reciprocal14, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrcp14ps, INS_vrcp14pd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AVX512F, MultiplyLow, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmulld, INS_pmulld, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, Or, 64, 2, true, {INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_vporq, INS_vporq, INS_orps, INS_orpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, Permute2x64, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermilpd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, Permute4x32, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermilps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, Permute4x64, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermq, INS_vpermq, INS_invalid, INS_vpermpd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, PermuteVar2x64, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermilpdvar}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, PermuteVar4x32, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermilpsvar, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, PermuteVar8x64, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermq_reg, INS_vpermq_reg, INS_invalid, INS_vpermpd_reg}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, PermuteVar8x64x2, 64, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermt2q, INS_vpermt2q, INS_invalid, INS_vpermt2pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, PermuteVar16x32, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermd, INS_vpermd, INS_invalid, INS_invalid, INS_vpermps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, PermuteVar16x32x2, 64, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermt2d, INS_vpermt2d, INS_invalid, INS_invalid, INS_vpermt2ps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, Reciprocal14, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrcp14ps, INS_vrcp14pd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512F, Reciprocal14Scalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrcp14ss, INS_vrcp14sd}, HW_Category_SimpleSIMD, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(AVX512F, ReciprocalSqrt14, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrsqrt14ps, INS_vrsqrt14pd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AVX512F, ReciprocalSqrt14, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrsqrt14ps, INS_vrsqrt14pd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512F, ReciprocalSqrt14Scalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrsqrt14ss, INS_vrsqrt14sd}, HW_Category_SimpleSIMD, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(AVX512F, RotateLeft, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprold, INS_vprold, INS_vprolq, INS_vprolq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_MaybeNoJmpTableIMM|HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, RotateLeftVariable, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprolvd, INS_vprolvd, INS_vprolvq, INS_vprolvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F, RotateRight, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprord, INS_vprord, INS_vprorq, INS_vprorq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_MaybeNoJmpTableIMM|HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, RotateRightVariable, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprorvd, INS_vprorvd, INS_vprorvq, INS_vprorvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F, RoundScale, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrndscaleps, INS_vrndscalepd}, HW_Category_IMM, HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX512F, RotateLeft, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprold, INS_vprold, INS_vprolq, INS_vprolq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_MaybeNoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, RotateLeftVariable, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprolvd, INS_vprolvd, INS_vprolvq, INS_vprolvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, RotateRight, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprord, INS_vprord, INS_vprorq, INS_vprorq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_MaybeNoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, RotateRightVariable, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprorvd, INS_vprorvd, INS_vprorvq, INS_vprorvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, RoundScale, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrndscaleps, INS_vrndscalepd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512F, RoundScaleScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrndscaless, INS_vrndscalesd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(AVX512F, Scale, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vscalefps, INS_vscalefpd}, HW_Category_SimpleSIMD, HW_Flag_EmbRoundingCompatible) +HARDWARE_INTRINSIC(AVX512F, Scale, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vscalefps, INS_vscalefpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_EmbRoundingCompatible) HARDWARE_INTRINSIC(AVX512F, ScaleScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vscalefss, INS_vscalefsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, ShiftLeftLogical, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pslld, INS_pslld, INS_psllq, INS_psllq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, ShiftLeftLogicalVariable, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsllvd, INS_vpsllvd, INS_vpsllvq, INS_vpsllvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX512F, ShiftRightArithmetic, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_psrad, INS_invalid, INS_vpsraq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, ShiftRightArithmeticVariable, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsravd, INS_invalid, INS_vpsravq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX512F, ShiftRightLogical, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_psrld, INS_psrld, INS_psrlq, INS_psrlq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, ShiftRightLogicalVariable, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsrlvd, INS_vpsrlvd, INS_vpsrlvq, INS_vpsrlvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX512F, Shuffle, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pshufd, INS_pshufd, INS_invalid, INS_invalid, INS_shufps, INS_shufpd}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, Shuffle4x128, 64, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vshufi32x4, INS_vshufi32x4, INS_vshufi64x2, INS_vshufi64x2, INS_vshuff32x4, INS_vshuff64x2}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, Sqrt, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtps, INS_sqrtpd}, HW_Category_SimpleSIMD, HW_Flag_EmbRoundingCompatible) +HARDWARE_INTRINSIC(AVX512F, ShiftLeftLogical, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pslld, INS_pslld, INS_psllq, INS_psllq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, ShiftLeftLogicalVariable, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsllvd, INS_vpsllvd, INS_vpsllvq, INS_vpsllvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, ShiftRightArithmetic, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_psrad, INS_invalid, INS_vpsraq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, ShiftRightArithmeticVariable, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsravd, INS_invalid, INS_vpsravq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, ShiftRightLogical, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_psrld, INS_psrld, INS_psrlq, INS_psrlq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, ShiftRightLogicalVariable, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsrlvd, INS_vpsrlvd, INS_vpsrlvq, INS_vpsrlvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, Shuffle, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pshufd, INS_pshufd, INS_invalid, INS_invalid, INS_shufps, INS_shufpd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, Shuffle4x128, 64, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vshufi32x4, INS_vshufi32x4, INS_vshufi64x2, INS_vshufi64x2, INS_vshuff32x4, INS_vshuff64x2}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, Sqrt, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtps, INS_sqrtpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_EmbRoundingCompatible) HARDWARE_INTRINSIC(AVX512F, SqrtScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrtss, INS_sqrtsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, Store, 64, 2, true, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(AVX512F, Store, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(AVX512F, StoreAligned, 64, 2, true, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_vmovdqa64, INS_vmovdqa64, INS_movaps, INS_movapd}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromSecondArg) HARDWARE_INTRINSIC(AVX512F, StoreAlignedNonTemporal, 64, 2, true, {INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntps, INS_movntpd}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(AVX512F, Subtract, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_psubd, INS_psubd, INS_psubq, INS_psubq, INS_subps, INS_subpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbRoundingCompatible) +HARDWARE_INTRINSIC(AVX512F, Subtract, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_psubd, INS_psubd, INS_psubq, INS_psubq, INS_subps, INS_subpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_EmbRoundingCompatible) HARDWARE_INTRINSIC(AVX512F, SubtractScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_subss, INS_subsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512F, UnpackHigh, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_punpckhdq, INS_punpckhdq, INS_punpckhqdq, INS_punpckhqdq, INS_unpckhps, INS_unpckhpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F, TernaryLogic, 64, 4, true, {INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogq, INS_vpternlogq, INS_vpternlogd, INS_vpternlogq}, HW_Category_IMM, HW_Flag_SpecialImport|HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F, UnpackLow, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_punpckldq, INS_punpckldq, INS_punpcklqdq, INS_punpcklqdq, INS_unpcklps, INS_unpcklpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F, Xor, 64, 2, true, {INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_vpxorq, INS_vpxorq, INS_xorps, INS_xorpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512F, TernaryLogic, 64, 4, true, {INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogq, INS_vpternlogq, INS_vpternlogd, INS_vpternlogq}, HW_Category_IMM, HW_Flag_SpecialImport|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, UnpackHigh, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_punpckhdq, INS_punpckhdq, INS_punpckhqdq, INS_punpckhqdq, INS_unpckhps, INS_unpckhpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, UnpackLow, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_punpckldq, INS_punpckldq, INS_punpcklqdq, INS_punpcklqdq, INS_unpcklps, INS_unpcklpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F, Xor, 64, 2, true, {INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_vpxorq, INS_vpxorq, INS_xorps, INS_xorpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AVX512F.VL Intrinsics -HARDWARE_INTRINSIC(AVX512F_VL, Abs, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpabsq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512F_VL, AlignRight32, -1, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_valignd, INS_valignd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F_VL, AlignRight64, -1, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_valignq, INS_valignq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F_VL, Max, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmaxsq, INS_vpmaxuq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX512F_VL, Min, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpminsq, INS_vpminuq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX512F_VL, CompareGreaterThan, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpcmpud, INS_invalid, INS_vpcmpuq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512F_VL, CompareGreaterThanOrEqual, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512F_VL, CompareLessThan, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512F_VL, CompareLessThanOrEqual, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512F_VL, CompareNotEqual, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AVX512F_VL, Abs, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpabsq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, AlignRight32, -1, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_valignd, INS_valignd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, AlignRight64, -1, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_valignq, INS_valignq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, Max, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmaxsq, INS_vpmaxuq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AVX512F_VL, Min, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpminsq, INS_vpminuq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AVX512F_VL, CompareGreaterThan, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F_VL, CompareGreaterThanOrEqual, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F_VL, CompareLessThan, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F_VL, CompareLessThanOrEqual, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512F_VL, CompareNotEqual, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128Byte, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovdb, INS_vpmovdb, INS_vpmovqb, INS_vpmovqb, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128ByteWithSaturation, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovusdb, INS_invalid, INS_vpmovusqb, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128Double, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtudq2pd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128Double, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtudq2pd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128Int16, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovdw, INS_vpmovdw, INS_vpmovqw, INS_vpmovqw, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128Int16WithSaturation, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovsdw, INS_invalid, INS_vpmovsqw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128Int32, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovqd, INS_vpmovqd, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128Int32WithSaturation, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovsqd, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128SByte, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovdb, INS_vpmovdb, INS_vpmovqb, INS_vpmovqb, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128SByteWithSaturation, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovsdb, INS_invalid, INS_vpmovsqb, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128Single, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtudq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128Single, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtudq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128UInt16, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovdw, INS_vpmovdw, INS_vpmovqw, INS_vpmovqw, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128UInt16WithSaturation, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovusdw, INS_invalid, INS_vpmovusqw, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128UInt32, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovqd, INS_vpmovqd, INS_vcvtps2udq, INS_vcvtpd2udq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128UInt32WithSaturation, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovusqd, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128UInt32WithTruncation, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2udq, INS_vcvttpd2udq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector256Double, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtudq2pd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector256Single, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtudq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector256UInt32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2udq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector256UInt32WithTruncation, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2udq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512F_VL, Fixup, -1, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfixupimmps, INS_vfixupimmpd}, HW_Category_IMM, HW_Flag_SpecialImport|HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F_VL, GetExponent, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vgetexpps, INS_vgetexppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F_VL, GetMantissa, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vgetmantps, INS_vgetmantpd}, HW_Category_IMM, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F_VL, PermuteVar2x64x2, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermt2q, INS_vpermt2q, INS_invalid, INS_vpermt2pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(AVX512F_VL, PermuteVar4x32x2, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermt2d, INS_vpermt2d, INS_invalid, INS_invalid, INS_vpermt2ps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(AVX512F_VL, PermuteVar4x64, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermq_reg, INS_vpermq_reg, INS_invalid, INS_vpermpd_reg}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AVX512F_VL, PermuteVar4x64x2, 32, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermt2q, INS_vpermt2q, INS_invalid, INS_vpermt2pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(AVX512F_VL, PermuteVar8x32x2, 32, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermt2d, INS_vpermt2d, INS_invalid, INS_invalid, INS_vpermt2ps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(AVX512F_VL, Reciprocal14, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrcp14ps, INS_vrcp14pd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F_VL, ReciprocalSqrt14, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrsqrt14ps, INS_vrsqrt14pd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F_VL, RotateLeft, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprold, INS_vprold, INS_vprolq, INS_vprolq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_MaybeNoJmpTableIMM|HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F_VL, RotateLeftVariable, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprolvd, INS_vprolvd, INS_vprolvq, INS_vprolvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F_VL, RotateRight, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprord, INS_vprord, INS_vprorq, INS_vprorq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_MaybeNoJmpTableIMM|HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F_VL, RotateRightVariable, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprorvd, INS_vprorvd, INS_vprorvq, INS_vprorvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F_VL, RoundScale, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrndscaleps, INS_vrndscalepd}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F_VL, Scale, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vscalefps, INS_vscalefpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F_VL, ShiftRightArithmetic, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsraq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F_VL, ShiftRightArithmeticVariable, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsravq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX512F_VL, Shuffle2x128, 32, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vshufi32x4, INS_vshufi32x4, INS_vshufi64x2, INS_vshufi64x2, INS_vshuff32x4, INS_vshuff64x2}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512F_VL, TernaryLogic, -1, 4, true, {INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogq, INS_vpternlogq, INS_vpternlogd, INS_vpternlogq}, HW_Category_IMM, HW_Flag_SpecialImport|HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128UInt32WithTruncation, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2udq, INS_vcvttpd2udq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector256Double, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtudq2pd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector256Single, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtudq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector256UInt32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2udq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector256UInt32WithTruncation, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2udq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, Fixup, -1, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfixupimmps, INS_vfixupimmpd}, HW_Category_IMM, HW_Flag_SpecialImport|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, GetExponent, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vgetexpps, INS_vgetexppd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, GetMantissa, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vgetmantps, INS_vgetmantpd}, HW_Category_IMM, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, PermuteVar2x64x2, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermt2q, INS_vpermt2q, INS_invalid, INS_vpermt2pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, PermuteVar4x32x2, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermt2d, INS_vpermt2d, INS_invalid, INS_invalid, INS_vpermt2ps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, PermuteVar4x64, 32, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermq_reg, INS_vpermq_reg, INS_invalid, INS_vpermpd_reg}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, PermuteVar4x64x2, 32, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermt2q, INS_vpermt2q, INS_invalid, INS_vpermt2pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, PermuteVar8x32x2, 32, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpermt2d, INS_vpermt2d, INS_invalid, INS_invalid, INS_vpermt2ps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, Reciprocal14, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrcp14ps, INS_vrcp14pd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, ReciprocalSqrt14, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrsqrt14ps, INS_vrsqrt14pd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, RotateLeft, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprold, INS_vprold, INS_vprolq, INS_vprolq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_MaybeNoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, RotateLeftVariable, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprolvd, INS_vprolvd, INS_vprolvq, INS_vprolvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, RotateRight, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprord, INS_vprord, INS_vprorq, INS_vprorq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_MaybeNoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, RotateRightVariable, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vprorvd, INS_vprorvd, INS_vprorvq, INS_vprorvq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, RoundScale, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrndscaleps, INS_vrndscalepd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, Scale, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vscalefps, INS_vscalefpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, ShiftRightArithmetic, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsraq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, ShiftRightArithmeticVariable, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpsravq, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, Shuffle2x128, 32, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vshufi32x4, INS_vshufi32x4, INS_vshufi64x2, INS_vshufi64x2, INS_vshuff32x4, INS_vshuff64x2}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512F_VL, TernaryLogic, -1, 4, true, {INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogd, INS_vpternlogq, INS_vpternlogq, INS_vpternlogd, INS_vpternlogq}, HW_Category_IMM, HW_Flag_SpecialImport|HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags @@ -1038,121 +1057,121 @@ HARDWARE_INTRINSIC(AVX512F_X64, ConvertToUInt64WithTruncation, // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AVX512BW Intrinsics -HARDWARE_INTRINSIC(AVX512BW, Abs, 64, 1, true, {INS_pabsb, INS_invalid, INS_pabsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512BW, Add, 64, 2, true, {INS_paddb, INS_paddb, INS_paddw, INS_paddw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AVX512BW, AddSaturate, 64, 2, true, {INS_paddsb, INS_paddusb, INS_paddsw, INS_paddusw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AVX512BW, AlignRight, 64, 3, false, {INS_palignr, INS_palignr, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512BW, Average, 64, 2, true, {INS_invalid, INS_pavgb, INS_invalid, INS_pavgw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AVX512BW, BlendVariable, 64, 3, true, {INS_vpblendmb, INS_vpblendmb, INS_vpblendmw, INS_vpblendmw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(AVX512BW, Abs, 64, 1, true, {INS_pabsb, INS_invalid, INS_pabsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, Add, 64, 2, true, {INS_paddb, INS_paddb, INS_paddw, INS_paddw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, AddSaturate, 64, 2, true, {INS_paddsb, INS_paddusb, INS_paddsw, INS_paddusw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, AlignRight, 64, 3, false, {INS_palignr, INS_palignr, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, Average, 64, 2, true, {INS_invalid, INS_pavgb, INS_invalid, INS_pavgw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, BlendVariable, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(AVX512BW, BroadcastScalarToVector512, 64, 1, true, {INS_vpbroadcastb, INS_vpbroadcastb, INS_vpbroadcastw, INS_vpbroadcastw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MaybeMemoryLoad) -HARDWARE_INTRINSIC(AVX512BW, CompareEqual, 64, 2, true, {INS_vpcmpeqb, INS_vpcmpeqb, INS_vpcmpeqw, INS_vpcmpeqw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(AVX512BW, CompareGreaterThan, 64, 2, true, {INS_vpcmpgtb, INS_vpcmpub, INS_vpcmpgtw, INS_vpcmpuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512BW, CompareGreaterThanOrEqual, 64, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512BW, CompareLessThan, 64, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512BW, CompareLessThanOrEqual, 64, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512BW, CompareNotEqual, 64, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AVX512BW, CompareEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512BW, CompareGreaterThan, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512BW, CompareGreaterThanOrEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512BW, CompareLessThan, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512BW, CompareLessThanOrEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512BW, CompareNotEqual, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(AVX512BW, ConvertToVector256Byte, 64, 1, false, {INS_invalid, INS_invalid, INS_vpmovwb, INS_vpmovwb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512BW, ConvertToVector256ByteWithSaturation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_vpmovuswb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512BW, ConvertToVector256SByte, 64, 1, false, {INS_invalid, INS_invalid, INS_vpmovwb, INS_vpmovwb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512BW, ConvertToVector256SByteWithSaturation, 64, 1, false, {INS_invalid, INS_invalid, INS_vpmovswb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512BW, ConvertToVector512Int16, 64, 1, true, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(AVX512BW, ConvertToVector512UInt16, 64, 1, true, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512BW, LoadVector512, 64, 1, true, {INS_vmovdqu8, INS_vmovdqu8, INS_vmovdqu16, INS_vmovdqu16, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512BW, Max, 64, 2, true, {INS_pmaxsb, INS_pmaxub, INS_pmaxsw, INS_pmaxuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AVX512BW, Min, 64, 2, true, {INS_pminsb, INS_pminub, INS_pminsw, INS_pminuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AVX512BW, MultiplyAddAdjacent, 64, 2, true, {INS_invalid, INS_invalid, INS_pmaddubsw, INS_invalid, INS_pmaddwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512BW, MultiplyHigh, 64, 2, true, {INS_invalid, INS_invalid, INS_pmulhw, INS_pmulhuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AVX512BW, MultiplyHighRoundScale, 64, 2, false, {INS_invalid, INS_invalid, INS_pmulhrsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512BW, MultiplyLow, 64, 2, false, {INS_invalid, INS_invalid, INS_pmullw, INS_pmullw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AVX512BW, PackSignedSaturate, 64, 2, true, {INS_packsswb, INS_invalid, INS_packssdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512BW, PackUnsignedSaturate, 64, 2, true, {INS_invalid, INS_packuswb, INS_invalid, INS_packusdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512BW, PermuteVar32x16, 64, 2, false, {INS_invalid, INS_invalid, INS_vpermw, INS_vpermw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AVX512BW, PermuteVar32x16x2, 64, 3, false, {INS_invalid, INS_invalid, INS_vpermt2w, INS_vpermt2w, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(AVX512BW, ShiftLeftLogical, 64, 2, false, {INS_invalid, INS_invalid, INS_psllw, INS_psllw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX512BW, LoadVector512, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512BW, Max, 64, 2, true, {INS_pmaxsb, INS_pmaxub, INS_pmaxsw, INS_pmaxuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, Min, 64, 2, true, {INS_pminsb, INS_pminub, INS_pminsw, INS_pminuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, MultiplyAddAdjacent, 64, 2, true, {INS_invalid, INS_invalid, INS_pmaddubsw, INS_invalid, INS_pmaddwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, MultiplyHigh, 64, 2, true, {INS_invalid, INS_invalid, INS_pmulhw, INS_pmulhuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, MultiplyHighRoundScale, 64, 2, false, {INS_invalid, INS_invalid, INS_pmulhrsw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, MultiplyLow, 64, 2, false, {INS_invalid, INS_invalid, INS_pmullw, INS_pmullw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, PackSignedSaturate, 64, 2, true, {INS_packsswb, INS_invalid, INS_packssdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, PackUnsignedSaturate, 64, 2, true, {INS_invalid, INS_packuswb, INS_invalid, INS_packusdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, PermuteVar32x16, 64, 2, false, {INS_invalid, INS_invalid, INS_vpermw, INS_vpermw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, PermuteVar32x16x2, 64, 3, false, {INS_invalid, INS_invalid, INS_vpermt2w, INS_vpermt2w, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, ShiftLeftLogical, 64, 2, false, {INS_invalid, INS_invalid, INS_psllw, INS_psllw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512BW, ShiftLeftLogical128BitLane, 64, 2, false, {INS_pslldq, INS_pslldq, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512BW, ShiftLeftLogicalVariable, 64, 2, false, {INS_invalid, INS_invalid, INS_vpsllvw, INS_vpsllvw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512BW, ShiftRightArithmetic, 64, 2, false, {INS_invalid, INS_invalid, INS_psraw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512BW, ShiftRightArithmeticVariable, 64, 2, false, {INS_invalid, INS_invalid, INS_vpsravw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512BW, ShiftRightLogical, 64, 2, false, {INS_invalid, INS_invalid, INS_psrlw, INS_psrlw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX512BW, ShiftLeftLogicalVariable, 64, 2, false, {INS_invalid, INS_invalid, INS_vpsllvw, INS_vpsllvw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, ShiftRightArithmetic, 64, 2, false, {INS_invalid, INS_invalid, INS_psraw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, ShiftRightArithmeticVariable, 64, 2, false, {INS_invalid, INS_invalid, INS_vpsravw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, ShiftRightLogical, 64, 2, false, {INS_invalid, INS_invalid, INS_psrlw, INS_psrlw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512BW, ShiftRightLogical128BitLane, 64, 2, false, {INS_psrldq, INS_psrldq, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512BW, ShiftRightLogicalVariable, 64, 2, false, {INS_invalid, INS_invalid, INS_vpsrlvw, INS_vpsrlvw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512BW, Shuffle, 64, 2, false, {INS_pshufb, INS_pshufb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512BW, ShuffleHigh, 64, 2, false, {INS_invalid, INS_invalid, INS_pshufhw, INS_pshufhw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512BW, ShuffleLow, 64, 2, false, {INS_invalid, INS_invalid, INS_pshuflw, INS_pshuflw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512BW, Store, 64, 2, true, {INS_vmovdqu8, INS_vmovdqu8, INS_vmovdqu16, INS_vmovdqu16, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512BW, Subtract, 64, 2, true, {INS_psubb, INS_psubb, INS_psubw, INS_psubw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512BW, SubtractSaturate, 64, 2, true, {INS_psubsb, INS_psubusb, INS_psubsw, INS_psubusw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AVX512BW, ShiftRightLogicalVariable, 64, 2, false, {INS_invalid, INS_invalid, INS_vpsrlvw, INS_vpsrlvw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, Shuffle, 64, 2, false, {INS_pshufb, INS_pshufb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, ShuffleHigh, 64, 2, false, {INS_invalid, INS_invalid, INS_pshufhw, INS_pshufhw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, ShuffleLow, 64, 2, false, {INS_invalid, INS_invalid, INS_pshuflw, INS_pshuflw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, Store, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(AVX512BW, Subtract, 64, 2, true, {INS_psubb, INS_psubb, INS_psubw, INS_psubw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, SubtractSaturate, 64, 2, true, {INS_psubsb, INS_psubusb, INS_psubsw, INS_psubusw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512BW, SumAbsoluteDifferences, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_psadbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512BW, SumAbsoluteDifferencesInBlock32, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_vdbpsadbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512BW, UnpackHigh, 64, 2, true, {INS_punpckhbw, INS_punpckhbw, INS_punpckhwd, INS_punpckhwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512BW, UnpackLow, 64, 2, true, {INS_punpcklbw, INS_punpcklbw, INS_punpcklwd, INS_punpcklwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AVX512BW, SumAbsoluteDifferencesInBlock32, 64, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_vdbpsadbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, UnpackHigh, 64, 2, true, {INS_punpckhbw, INS_punpckhbw, INS_punpckhwd, INS_punpckhwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW, UnpackLow, 64, 2, true, {INS_punpcklbw, INS_punpcklbw, INS_punpcklwd, INS_punpcklwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AVX512BW.VL Intrinsics -HARDWARE_INTRINSIC(AVX512BW_VL, CompareGreaterThan, -1, 2, true, {INS_invalid, INS_vpcmpub, INS_invalid, INS_vpcmpuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512BW_VL, CompareGreaterThanOrEqual, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512BW_VL, CompareLessThan, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512BW_VL, CompareLessThanOrEqual, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(AVX512BW_VL, CompareNotEqual, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AVX512BW_VL, CompareGreaterThan, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512BW_VL, CompareGreaterThanOrEqual, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512BW_VL, CompareLessThan, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512BW_VL, CompareLessThanOrEqual, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(AVX512BW_VL, CompareNotEqual, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(AVX512BW_VL, ConvertToVector128Byte, -1, 1, false, {INS_invalid, INS_invalid, INS_vpmovwb, INS_vpmovwb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512BW_VL, ConvertToVector128ByteWithSaturation, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_vpmovuswb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512BW_VL, ConvertToVector128SByte, -1, 1, false, {INS_invalid, INS_invalid, INS_vpmovwb, INS_vpmovwb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AVX512BW_VL, ConvertToVector128SByteWithSaturation, -1, 1, false, {INS_invalid, INS_invalid, INS_vpmovswb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512BW_VL, PermuteVar8x16 , 16, 2, false, {INS_invalid, INS_invalid, INS_vpermw, INS_vpermw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AVX512BW_VL, PermuteVar8x16x2, 16, 3, false, {INS_invalid, INS_invalid, INS_vpermt2w, INS_vpermt2w, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(AVX512BW_VL, PermuteVar16x16, 32, 2, false, {INS_invalid, INS_invalid, INS_vpermw, INS_vpermw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AVX512BW_VL, PermuteVar16x16x2, 32, 3, false, {INS_invalid, INS_invalid, INS_vpermt2w, INS_vpermt2w, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(AVX512BW_VL, ShiftLeftLogicalVariable, -1, 2, false, {INS_invalid, INS_invalid, INS_vpsllvw, INS_vpsllvw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512BW_VL, ShiftRightArithmeticVariable, -1, 2, false, {INS_invalid, INS_invalid, INS_vpsravw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512BW_VL, ShiftRightLogicalVariable, -1, 2, false, {INS_invalid, INS_invalid, INS_vpsrlvw, INS_vpsrlvw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512BW_VL, SumAbsoluteDifferencesInBlock32, -1, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_vdbpsadbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX512BW_VL, PermuteVar8x16 , 16, 2, false, {INS_invalid, INS_invalid, INS_vpermw, INS_vpermw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW_VL, PermuteVar8x16x2, 16, 3, false, {INS_invalid, INS_invalid, INS_vpermt2w, INS_vpermt2w, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW_VL, PermuteVar16x16, 32, 2, false, {INS_invalid, INS_invalid, INS_vpermw, INS_vpermw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW_VL, PermuteVar16x16x2, 32, 3, false, {INS_invalid, INS_invalid, INS_vpermt2w, INS_vpermt2w, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW_VL, ShiftLeftLogicalVariable, -1, 2, false, {INS_invalid, INS_invalid, INS_vpsllvw, INS_vpsllvw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW_VL, ShiftRightArithmeticVariable, -1, 2, false, {INS_invalid, INS_invalid, INS_vpsravw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW_VL, ShiftRightLogicalVariable, -1, 2, false, {INS_invalid, INS_invalid, INS_vpsrlvw, INS_vpsrlvw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512BW_VL, SumAbsoluteDifferencesInBlock32, -1, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_vdbpsadbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AVX512CD Intrinsics -HARDWARE_INTRINSIC(AVX512CD, DetectConflicts, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpconflictd, INS_vpconflictd, INS_vpconflictq, INS_vpconflictq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512CD, LeadingZeroCount, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vplzcntd, INS_vplzcntd, INS_vplzcntq, INS_vplzcntq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AVX512CD, DetectConflicts, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpconflictd, INS_vpconflictd, INS_vpconflictq, INS_vpconflictq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512CD, LeadingZeroCount, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vplzcntd, INS_vplzcntd, INS_vplzcntq, INS_vplzcntq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AVX512CD.VL Intrinsics -HARDWARE_INTRINSIC(AVX512CD_VL, DetectConflicts, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpconflictd, INS_vpconflictd, INS_vpconflictq, INS_vpconflictq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512CD_VL, LeadingZeroCount, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vplzcntd, INS_vplzcntd, INS_vplzcntq, INS_vplzcntq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AVX512CD_VL, DetectConflicts, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpconflictd, INS_vpconflictd, INS_vpconflictq, INS_vpconflictq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512CD_VL, LeadingZeroCount, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vplzcntd, INS_vplzcntd, INS_vplzcntq, INS_vplzcntq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AVX512DQ Intrinsics -HARDWARE_INTRINSIC(AVX512DQ, And, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andps, INS_andpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AVX512DQ, AndNot, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andnps, INS_andnpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512DQ, And, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andps, INS_andpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ, AndNot, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andnps, INS_andnpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512DQ, BroadcastPairScalarToVector512, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vbroadcasti32x2, INS_vbroadcasti32x2, INS_invalid, INS_invalid, INS_vbroadcastf32x2, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX512DQ, BroadcastVector128ToVector512, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vbroadcasti64x2, INS_vbroadcasti64x2, INS_invalid, INS_vbroadcastf64x2}, HW_Category_MemoryLoad, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX512DQ, BroadcastVector256ToVector512, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vbroadcasti32x8, INS_vbroadcasti32x8, INS_invalid, INS_invalid, INS_vbroadcastf32x8, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512DQ, ConvertToVector256Single, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtqq2ps, INS_vcvtuqq2ps, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512DQ, ConvertToVector512Double, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtqq2pd, INS_vcvtuqq2pd, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512DQ, ConvertToVector512Int64, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2qq, INS_vcvtpd2qq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512DQ, ConvertToVector512Int64WithTruncation, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2qq, INS_vcvttpd2qq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512DQ, ConvertToVector512UInt64, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2uqq, INS_vcvtpd2uqq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbRoundingCompatible) -HARDWARE_INTRINSIC(AVX512DQ, ConvertToVector512UInt64WithTruncation, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2uqq, INS_vcvttpd2uqq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512DQ, ExtractVector128, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vextracti64x2, INS_vextracti64x2, INS_invalid, INS_vextractf64x2}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512DQ, ExtractVector256, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vextracti32x8, INS_vextracti32x8, INS_invalid, INS_invalid, INS_vextractf32x8, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512DQ, InsertVector128, 64, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vinserti64x2, INS_vinserti64x2, INS_invalid, INS_vinsertf64x2}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512DQ, InsertVector256, 64, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vinserti32x8, INS_vinserti32x8, INS_invalid, INS_invalid, INS_vinsertf32x8, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512DQ, MultiplyLow, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmullq, INS_vpmullq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX512DQ, Or, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_orps, INS_orpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) -HARDWARE_INTRINSIC(AVX512DQ, Range, 64, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrangeps, INS_vrangepd}, HW_Category_IMM, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AVX512DQ, ConvertToVector256Single, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtqq2ps, INS_vcvtuqq2ps, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_EmbRoundingCompatible) +HARDWARE_INTRINSIC(AVX512DQ, ConvertToVector512Double, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtqq2pd, INS_vcvtuqq2pd, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_EmbRoundingCompatible) +HARDWARE_INTRINSIC(AVX512DQ, ConvertToVector512Int64, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2qq, INS_vcvtpd2qq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_EmbRoundingCompatible) +HARDWARE_INTRINSIC(AVX512DQ, ConvertToVector512Int64WithTruncation, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2qq, INS_vcvttpd2qq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ, ConvertToVector512UInt64, 64, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2uqq, INS_vcvtpd2uqq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible|HW_Flag_EmbRoundingCompatible) +HARDWARE_INTRINSIC(AVX512DQ, ConvertToVector512UInt64WithTruncation, 64, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2uqq, INS_vcvttpd2uqq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ, ExtractVector128, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vextracti64x2, INS_vextracti64x2, INS_invalid, INS_vextractf64x2}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ, ExtractVector256, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vextracti32x8, INS_vextracti32x8, INS_invalid, INS_invalid, INS_vextractf32x8, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ, InsertVector128, 64, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vinserti64x2, INS_vinserti64x2, INS_invalid, INS_vinsertf64x2}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ, InsertVector256, 64, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vinserti32x8, INS_vinserti32x8, INS_invalid, INS_invalid, INS_vinsertf32x8, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ, MultiplyLow, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmullq, INS_vpmullq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ, Or, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_orps, INS_orpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ, Range, 64, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrangeps, INS_vrangepd}, HW_Category_IMM, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512DQ, RangeScalar, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrangess, INS_vrangesd}, HW_Category_IMM, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(AVX512DQ, Reduce, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vreduceps, INS_vreducepd}, HW_Category_IMM, HW_Flag_FullRangeIMM) +HARDWARE_INTRINSIC(AVX512DQ, Reduce, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vreduceps, INS_vreducepd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) HARDWARE_INTRINSIC(AVX512DQ, ReduceScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vreducess, INS_vreducesd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(AVX512DQ, Xor, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_xorps, INS_xorpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512DQ, Xor, 64, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_xorps, INS_xorpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags @@ -1161,46 +1180,46 @@ HARDWARE_INTRINSIC(AVX512DQ, Xor, // AVX512DQ.VL Intrinsics HARDWARE_INTRINSIC(AVX512DQ_VL, BroadcastPairScalarToVector128, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vbroadcasti32x2, INS_vbroadcasti32x2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AVX512DQ_VL, BroadcastPairScalarToVector256, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vbroadcasti32x2, INS_vbroadcasti32x2, INS_invalid, INS_invalid, INS_vbroadcastf32x2, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector128Double, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtqq2pd, INS_vcvtuqq2pd, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector128Int64, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2qq, INS_vcvtpd2qq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector128Int64WithTruncation, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2qq, INS_vcvttpd2qq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector128Single, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtqq2ps, INS_vcvtuqq2ps, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector128UInt64, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2uqq, INS_vcvtpd2uqq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector128UInt64WithTruncation, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2uqq, INS_vcvttpd2uqq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector256Double, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtqq2pd, INS_vcvtuqq2pd, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector256Int64, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2qq, INS_vcvtpd2qq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector256Int64WithTruncation, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2qq, INS_vcvttpd2qq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector256UInt64, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2uqq, INS_vcvtpd2uqq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector256UInt64WithTruncation, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2uqq, INS_vcvttpd2uqq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX512DQ_VL, Range, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrangeps, INS_vrangepd}, HW_Category_IMM, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512DQ_VL, Reduce, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vreduceps, INS_vreducepd}, HW_Category_IMM, HW_Flag_FullRangeIMM) -HARDWARE_INTRINSIC(AVX512DQ_VL, MultiplyLow, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmullq, INS_vpmullq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector128Double, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtqq2pd, INS_vcvtuqq2pd, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector128Int64, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2qq, INS_vcvtpd2qq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector128Int64WithTruncation, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2qq, INS_vcvttpd2qq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector128Single, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtqq2ps, INS_vcvtuqq2ps, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector128UInt64, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2uqq, INS_vcvtpd2uqq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector128UInt64WithTruncation, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2uqq, INS_vcvttpd2uqq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector256Double, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtqq2pd, INS_vcvtuqq2pd, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector256Int64, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2qq, INS_vcvtpd2qq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector256Int64WithTruncation, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2qq, INS_vcvttpd2qq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector256UInt64, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtps2uqq, INS_vcvtpd2uqq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ_VL, ConvertToVector256UInt64WithTruncation, 32, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttps2uqq, INS_vcvttpd2uqq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ_VL, Range, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vrangeps, INS_vrangepd}, HW_Category_IMM, HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ_VL, Reduce, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vreduceps, INS_vreducepd}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512DQ_VL, MultiplyLow, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmullq, INS_vpmullq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AVX512VBMI Intrinsics -HARDWARE_INTRINSIC(AVX512VBMI, PermuteVar64x8, 64, 2, false, {INS_vpermb, INS_vpermb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AVX512VBMI, PermuteVar64x8x2, 64, 3, false, {INS_vpermt2b, INS_vpermt2b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic) +HARDWARE_INTRINSIC(AVX512VBMI, PermuteVar64x8, 64, 2, false, {INS_vpermb, INS_vpermb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512VBMI, PermuteVar64x8x2, 64, 3, false, {INS_vpermt2b, INS_vpermt2b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic|HW_Flag_EmbMaskingCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AVX512VBMI.VL Intrinsics -HARDWARE_INTRINSIC(AVX512VBMI_VL, PermuteVar16x8, 16, 2, false, {INS_vpermb, INS_vpermb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AVX512VBMI_VL, PermuteVar16x8x2, 16, 3, false, {INS_vpermt2b, INS_vpermt2b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(AVX512VBMI_VL, PermuteVar32x8, 32, 2, false, {INS_vpermb, INS_vpermb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AVX512VBMI_VL, PermuteVar32x8x2, 32, 3, false, {INS_vpermt2b, INS_vpermt2b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic) +HARDWARE_INTRINSIC(AVX512VBMI_VL, PermuteVar16x8, 16, 2, false, {INS_vpermb, INS_vpermb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512VBMI_VL, PermuteVar16x8x2, 16, 3, false, {INS_vpermt2b, INS_vpermt2b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512VBMI_VL, PermuteVar32x8, 32, 2, false, {INS_vpermb, INS_vpermb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(AVX512VBMI_VL, PermuteVar32x8x2, 32, 3, false, {INS_vpermt2b, INS_vpermt2b, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_PermuteVar2x|HW_Flag_RmwIntrinsic|HW_Flag_EmbMaskingCompatible) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AVXVNNI Intrinsics -HARDWARE_INTRINSIC(AVXVNNI, MultiplyWideningAndAdd, -1, 3, true, {INS_invalid, INS_vpdpbusd, INS_vpdpwssd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFloatingPointUsed|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(AVXVNNI, MultiplyWideningAndAddSaturate, -1, 3, true, {INS_invalid, INS_vpdpbusds, INS_vpdpwssds, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFloatingPointUsed|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(AVXVNNI, MultiplyWideningAndAdd, -1, 3, true, {INS_invalid, INS_vpdpbusd, INS_vpdpwssd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVXVNNI, MultiplyWideningAndAddSaturate, -1, 3, true, {INS_invalid, INS_vpdpbusds, INS_vpdpwssds, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoEvexSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags @@ -1223,8 +1242,8 @@ HARDWARE_INTRINSIC(BMI1, AndNot, HARDWARE_INTRINSIC(BMI1, ExtractLowestSetBit, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_blsi, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(BMI1, GetMaskUpToLowestSetBit, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_blsmsk, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed) HARDWARE_INTRINSIC(BMI1, ResetLowestSetBit, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_blsr, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed) -HARDWARE_INTRINSIC(BMI1, TrailingZeroCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_tzcnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_MultiIns) -HARDWARE_INTRINSIC(BMI1, BitFieldExtract, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bextr, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_MultiIns|HW_Flag_SpecialImport|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(BMI1, TrailingZeroCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_tzcnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(BMI1, BitFieldExtract, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bextr, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_NoEvexSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags @@ -1235,8 +1254,8 @@ HARDWARE_INTRINSIC(BMI1_X64, AndNot, HARDWARE_INTRINSIC(BMI1_X64, ExtractLowestSetBit, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_blsi, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(BMI1_X64, GetMaskUpToLowestSetBit, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_blsmsk, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed) HARDWARE_INTRINSIC(BMI1_X64, ResetLowestSetBit, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_blsr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed) -HARDWARE_INTRINSIC(BMI1_X64, TrailingZeroCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_tzcnt, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_MultiIns) -HARDWARE_INTRINSIC(BMI1_X64, BitFieldExtract, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bextr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_MultiIns|HW_Flag_SpecialImport|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(BMI1_X64, TrailingZeroCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_tzcnt, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(BMI1_X64, BitFieldExtract, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bextr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_NoEvexSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags @@ -1246,7 +1265,7 @@ HARDWARE_INTRINSIC(BMI1_X64, BitFieldExtract, HARDWARE_INTRINSIC(BMI2, ParallelBitDeposit, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pdep, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(BMI2, ParallelBitExtract, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pext, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(BMI2, ZeroHighBits, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bzhi, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_SpecialImport|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(BMI2, MultiplyNoFlags, 0, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mulx, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment|HW_Flag_MaybeMemoryStore|HW_Flag_MultiIns|HW_Flag_NoFloatingPointUsed|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(BMI2, MultiplyNoFlags, 0, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mulx, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment|HW_Flag_MaybeMemoryStore|HW_Flag_SpecialCodeGen|HW_Flag_NoFloatingPointUsed|HW_Flag_NoEvexSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags @@ -1256,37 +1275,37 @@ HARDWARE_INTRINSIC(BMI2, MultiplyNoFlags, HARDWARE_INTRINSIC(BMI2_X64, ParallelBitDeposit, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pdep, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(BMI2_X64, ParallelBitExtract, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pext, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(BMI2_X64, ZeroHighBits, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bzhi, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_SpecialImport|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(BMI2_X64, MultiplyNoFlags, 0, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mulx, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment|HW_Flag_MaybeMemoryStore|HW_Flag_MultiIns|HW_Flag_NoFloatingPointUsed|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(BMI2_X64, MultiplyNoFlags, 0, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mulx, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment|HW_Flag_MaybeMemoryStore|HW_Flag_SpecialCodeGen|HW_Flag_NoFloatingPointUsed|HW_Flag_NoEvexSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // FMA Intrinsics -HARDWARE_INTRINSIC(FMA, MultiplyAdd, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmadd213ps, INS_vfmadd213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(FMA, MultiplyAddNegated, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmadd213ps, INS_vfnmadd213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(FMA, MultiplyAddNegatedScalar, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmadd213ss, INS_vfnmadd213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_CopyUpperBits|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(FMA, MultiplyAddScalar, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmadd213ss, INS_vfmadd213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_CopyUpperBits|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(FMA, MultiplyAddSubtract, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmaddsub213ps, INS_vfmaddsub213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(FMA, MultiplySubtract, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmsub213ps, INS_vfmsub213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(FMA, MultiplySubtractAdd, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmsubadd213ps, INS_vfmsubadd213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(FMA, MultiplySubtractNegated, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmsub213ps, INS_vfnmsub213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(FMA, MultiplySubtractScalar, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmsub213ss, INS_vfmsub213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_CopyUpperBits|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(FMA, MultiplySubtractNegatedScalar, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmsub213ss, INS_vfnmsub213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_CopyUpperBits|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic) +HARDWARE_INTRINSIC(FMA, MultiplyAdd, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmadd213ps, INS_vfmadd213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(FMA, MultiplyAddNegated, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmadd213ps, INS_vfnmadd213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(FMA, MultiplyAddNegatedScalar, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmadd213ss, INS_vfnmadd213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(FMA, MultiplyAddScalar, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmadd213ss, INS_vfmadd213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(FMA, MultiplyAddSubtract, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmaddsub213ps, INS_vfmaddsub213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(FMA, MultiplySubtract, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmsub213ps, INS_vfmsub213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(FMA, MultiplySubtractAdd, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmsubadd213ps, INS_vfmsubadd213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(FMA, MultiplySubtractNegated, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmsub213ps, INS_vfnmsub213pd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_EmbBroadcastCompatible|HW_Flag_EmbMaskingCompatible) +HARDWARE_INTRINSIC(FMA, MultiplySubtractScalar, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfmsub213ss, INS_vfmsub213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(FMA, MultiplySubtractNegatedScalar, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vfnmsub213ss, INS_vfnmsub213sd}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_FmaIntrinsic|HW_Flag_RmwIntrinsic|HW_Flag_CopyUpperBits) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // LZCNT Intrinsics -HARDWARE_INTRINSIC(LZCNT, LeadingZeroCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_lzcnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics|HW_Flag_MultiIns) +HARDWARE_INTRINSIC(LZCNT, LeadingZeroCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_lzcnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // LZCNT Intrinsics -HARDWARE_INTRINSIC(LZCNT_X64, LeadingZeroCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_lzcnt, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics|HW_Flag_MultiIns) +HARDWARE_INTRINSIC(LZCNT_X64, LeadingZeroCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_lzcnt, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags @@ -1300,14 +1319,14 @@ HARDWARE_INTRINSIC(PCLMULQDQ, CarrylessMultiply, // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // POPCNT Intrinsics -HARDWARE_INTRINSIC(POPCNT, PopCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_popcnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics|HW_Flag_MultiIns) +HARDWARE_INTRINSIC(POPCNT, PopCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_popcnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // POPCNT Intrinsics -HARDWARE_INTRINSIC(POPCNT_X64, PopCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_popcnt, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics|HW_Flag_MultiIns) +HARDWARE_INTRINSIC(POPCNT_X64, PopCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_popcnt, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // ISA Function name SIMD size NumArg EncodesExtraTypeArg Instructions Category Flags @@ -1330,25 +1349,26 @@ HARDWARE_INTRINSIC(SSE41, PTEST, HARDWARE_INTRINSIC(AVX, PTEST, 0, 2, false, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) HARDWARE_INTRINSIC(AVX512F, KORTEST, 0, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment) HARDWARE_INTRINSIC(AVX512F, KTEST, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment) -HARDWARE_INTRINSIC(AVX512F, PTESTM, 0, 2, false, {INS_vptestmb, INS_vptestmb, INS_vptestmw, INS_vptestmw, INS_vptestmd, INS_vptestmd, INS_vptestmq, INS_vptestmq, INS_vptestmd, INS_vptestmq}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F, PTESTNM, 0, 2, false, {INS_vptestnmb, INS_vptestnmb, INS_vptestnmw, INS_vptestnmw, INS_vptestnmd, INS_vptestnmd, INS_vptestnmq, INS_vptestnmq, INS_vptestnmd, INS_vptestnmq}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AVX512F, PTESTM, 0, 2, false, {INS_vptestmb, INS_vptestmb, INS_vptestmw, INS_vptestmw, INS_vptestmd, INS_vptestmd, INS_vptestmq, INS_vptestmq, INS_vptestmd, INS_vptestmq}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512F, PTESTNM, 0, 2, false, {INS_vptestnmb, INS_vptestnmb, INS_vptestnmw, INS_vptestnmw, INS_vptestnmd, INS_vptestnmd, INS_vptestnmq, INS_vptestnmq, INS_vptestnmd, INS_vptestnmq}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) HARDWARE_INTRINSIC(AVX512F, AddMask, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment|HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask) HARDWARE_INTRINSIC(AVX512F, AndMask, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment|HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask) HARDWARE_INTRINSIC(AVX512F, AndNotMask, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment|HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX512F, BlendVariableMask, -1, 3, true, {INS_vpblendmb, INS_vpblendmb, INS_vpblendmw, INS_vpblendmw, INS_vpblendmd, INS_vpblendmd, INS_vpblendmq, INS_vpblendmq, INS_vblendmps, INS_vblendmpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F, CompareEqualMask, -1, 2, true, {INS_vpcmpeqb, INS_vpcmpeqb, INS_vpcmpeqw, INS_vpcmpeqw, INS_vpcmpeqd, INS_vpcmpeqd, INS_vpcmpeqq, INS_vpcmpeqq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_CanBenefitFromConstantProp) -HARDWARE_INTRINSIC(AVX512F, CompareGreaterThanMask, -1, 2, true, {INS_vpcmpgtb, INS_vpcmpub, INS_vpcmpgtw, INS_vpcmpuw, INS_vpcmpgtd, INS_vpcmpud, INS_vpcmpgtq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX512F, CompareGreaterThanOrEqualMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX512F, CompareLessThanMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX512F, CompareLessThanOrEqualMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX512F, CompareNotEqualMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_CanBenefitFromConstantProp) -HARDWARE_INTRINSIC(AVX512F, CompareNotGreaterThanMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX512F, CompareNotGreaterThanOrEqualMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX512F, CompareNotLessThanMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX512F, CompareNotLessThanOrEqualMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX512F, CompareOrderedMask, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(AVX512F, CompareUnorderedMask, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask) +HARDWARE_INTRINSIC(AVX512F, BlendVariableMask, -1, 3, true, {INS_vpblendmb, INS_vpblendmb, INS_vpblendmw, INS_vpblendmw, INS_vpblendmd, INS_vpblendmd, INS_vpblendmq, INS_vpblendmq, INS_vblendmps, INS_vblendmpd}, HW_Category_SimpleSIMD, HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512F, CompareMask, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcmpps, INS_vcmppd}, HW_Category_IMM, HW_Flag_ReturnsPerElementMask|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512F, CompareEqualMask, -1, 2, true, {INS_vpcmpeqb, INS_vpcmpeqb, INS_vpcmpeqw, INS_vpcmpeqw, INS_vpcmpeqd, INS_vpcmpeqd, INS_vpcmpeqq, INS_vpcmpeqq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_EmbBroadcastCompatible|HW_Flag_Commutative|HW_Flag_CanBenefitFromConstantProp) +HARDWARE_INTRINSIC(AVX512F, CompareGreaterThanMask, -1, 2, true, {INS_vpcmpgtb, INS_vpcmpub, INS_vpcmpgtw, INS_vpcmpuw, INS_vpcmpgtd, INS_vpcmpud, INS_vpcmpgtq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512F, CompareGreaterThanOrEqualMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512F, CompareLessThanMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512F, CompareLessThanOrEqualMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512F, CompareNotEqualMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_EmbBroadcastCompatible|HW_Flag_Commutative|HW_Flag_CanBenefitFromConstantProp) +HARDWARE_INTRINSIC(AVX512F, CompareNotGreaterThanMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512F, CompareNotGreaterThanOrEqualMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512F, CompareNotLessThanMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512F, CompareNotLessThanOrEqualMask, -1, 2, true, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512F, CompareOrderedMask, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_EmbBroadcastCompatible) +HARDWARE_INTRINSIC(AVX512F, CompareUnorderedMask, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcmpps, INS_vcmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_EmbBroadcastCompatible) HARDWARE_INTRINSIC(AVX512F, ConvertMaskToVector, -1, 1, true, {INS_vpmovm2b, INS_vpmovm2b, INS_vpmovm2w, INS_vpmovm2w, INS_vpmovm2d, INS_vpmovm2d, INS_vpmovm2q, INS_vpmovm2q, INS_vpmovm2d, INS_vpmovm2q}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_ReturnsPerElementMask) HARDWARE_INTRINSIC(AVX512F, ConvertVectorToMask, -1, 1, true, {INS_vpmovb2m, INS_vpmovb2m, INS_vpmovw2m, INS_vpmovw2m, INS_vpmovd2m, INS_vpmovd2m, INS_vpmovq2m, INS_vpmovq2m, INS_vpmovd2m, INS_vpmovq2m}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_ReturnsPerElementMask) HARDWARE_INTRINSIC(AVX512F, MoveMask, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment) diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp index fc3c01e4c31d..8aaee01f4c41 100644 --- a/src/coreclr/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/jit/hwintrinsicxarch.cpp @@ -301,6 +301,8 @@ int HWIntrinsicInfo::lookupImmUpperBound(NamedIntrinsic id) { case NI_AVX_Compare: case NI_AVX_CompareScalar: + case NI_AVX512F_Compare: + case NI_AVX512F_CompareMask: { assert(!HWIntrinsicInfo::HasFullRangeImm(id)); return 31; // enum FloatComparisonMode has 32 values @@ -604,18 +606,11 @@ int HWIntrinsicInfo::lookupIval(Compiler* comp, NamedIntrinsic id, var_types sim { if (varTypeIsFloating(simdBaseType)) { - if (comp->compOpportunisticallyDependsOn(InstructionSet_AVX)) - { - return static_cast(FloatComparisonMode::OrderedGreaterThanSignaling); - } - // CompareGreaterThan is not directly supported in hardware without AVX support. - // We will return the inverted case here and lowering will itself swap the ops - // to ensure the emitted code remains correct. This simplifies the overall logic - // here and for other use cases. + // Lowering ensures we swap the operands and change to the correct ID. - assert(id != NI_AVX_CompareGreaterThan); - return static_cast(FloatComparisonMode::OrderedLessThanSignaling); + assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX)); + return static_cast(FloatComparisonMode::OrderedGreaterThanSignaling); } else if ((id == NI_AVX512F_CompareGreaterThanMask) && varTypeIsUnsigned(simdBaseType)) { @@ -653,18 +648,11 @@ int HWIntrinsicInfo::lookupIval(Compiler* comp, NamedIntrinsic id, var_types sim { if (varTypeIsFloating(simdBaseType)) { - if (comp->compOpportunisticallyDependsOn(InstructionSet_AVX)) - { - return static_cast(FloatComparisonMode::OrderedGreaterThanOrEqualSignaling); - } - // CompareGreaterThanOrEqual is not directly supported in hardware without AVX support. - // We will return the inverted case here and lowering will itself swap the ops - // to ensure the emitted code remains correct. This simplifies the overall logic - // here and for other use cases. + // Lowering ensures we swap the operands and change to the correct ID. - assert(id != NI_AVX_CompareGreaterThanOrEqual); - return static_cast(FloatComparisonMode::OrderedLessThanOrEqualSignaling); + assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX)); + return static_cast(FloatComparisonMode::OrderedGreaterThanOrEqualSignaling); } else { @@ -721,18 +709,11 @@ int HWIntrinsicInfo::lookupIval(Compiler* comp, NamedIntrinsic id, var_types sim { if (varTypeIsFloating(simdBaseType)) { - if (comp->compOpportunisticallyDependsOn(InstructionSet_AVX)) - { - return static_cast(FloatComparisonMode::UnorderedNotGreaterThanSignaling); - } - // CompareNotGreaterThan is not directly supported in hardware without AVX support. - // We will return the inverted case here and lowering will itself swap the ops - // to ensure the emitted code remains correct. This simplifies the overall logic - // here and for other use cases. + // Lowering ensures we swap the operands and change to the correct ID. - assert(id != NI_AVX_CompareGreaterThan); - return static_cast(FloatComparisonMode::UnorderedNotLessThanSignaling); + assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX)); + return static_cast(FloatComparisonMode::UnorderedNotGreaterThanSignaling); } else { @@ -770,18 +751,11 @@ int HWIntrinsicInfo::lookupIval(Compiler* comp, NamedIntrinsic id, var_types sim { if (varTypeIsFloating(simdBaseType)) { - if (comp->compOpportunisticallyDependsOn(InstructionSet_AVX)) - { - return static_cast(FloatComparisonMode::UnorderedNotGreaterThanOrEqualSignaling); - } - // CompareNotGreaterThanOrEqual is not directly supported in hardware without AVX support. - // We will return the inverted case here and lowering will itself swap the ops - // to ensure the emitted code remains correct. This simplifies the overall logic - // here and for other use cases. + // Lowering ensures we swap the operands and change to the correct ID. - assert(id != NI_AVX_CompareNotGreaterThanOrEqual); - return static_cast(FloatComparisonMode::UnorderedNotLessThanOrEqualSignaling); + assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX)); + return static_cast(FloatComparisonMode::UnorderedNotGreaterThanOrEqualSignaling); } else { @@ -983,6 +957,8 @@ GenTree* Compiler::impNonConstFallback(NamedIntrinsic intrinsic, var_types simdT // sig -- signature of the intrinsic call. // simdBaseJitType -- generic argument of the intrinsic. // retType -- return type of the intrinsic. +// mustExpand -- true if the intrinsic must return a GenTree*; otherwise, false +// // Return Value: // the expanded intrinsic. // @@ -992,7 +968,8 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, CORINFO_SIG_INFO* sig, CorInfoType simdBaseJitType, var_types retType, - unsigned simdSize) + unsigned simdSize, + bool mustExpand) { GenTree* retNode = nullptr; GenTree* op1 = nullptr; @@ -1124,7 +1101,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, { // Vector is TYP_SIMD32, so we should treat this as a call to Vector128.ToVector256 return impSpecialIntrinsic(NI_Vector128_ToVector256, clsHnd, method, sig, simdBaseJitType, retType, - simdSize); + simdSize, mustExpand); } else if (vectorTByteLength == XMM_REGSIZE_BYTES) { @@ -1234,7 +1211,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, { // Vector is TYP_SIMD32, so we should treat this as a call to Vector256.GetLower return impSpecialIntrinsic(NI_Vector256_GetLower, clsHnd, method, sig, simdBaseJitType, retType, - simdSize); + simdSize, mustExpand); } default: @@ -1274,13 +1251,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if (intrinsic == NI_Vector256_AsVector) { return impSpecialIntrinsic(NI_Vector256_GetLower, clsHnd, method, sig, simdBaseJitType, retType, - simdSize); + simdSize, mustExpand); } else { assert(intrinsic == NI_Vector256_AsVector256); return impSpecialIntrinsic(NI_Vector128_ToVector256, clsHnd, method, sig, simdBaseJitType, - retType, 16); + retType, 16, mustExpand); } } } @@ -1307,13 +1284,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if (intrinsic == NI_Vector512_AsVector) { return impSpecialIntrinsic(NI_Vector512_GetLower, clsHnd, method, sig, simdBaseJitType, retType, - simdSize); + simdSize, mustExpand); } else { assert(intrinsic == NI_Vector512_AsVector512); return impSpecialIntrinsic(NI_Vector256_ToVector512, clsHnd, method, sig, simdBaseJitType, retType, - 32); + 32, mustExpand); } break; } @@ -1327,13 +1304,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if (intrinsic == NI_Vector512_AsVector) { return impSpecialIntrinsic(NI_Vector512_GetLower128, clsHnd, method, sig, simdBaseJitType, - retType, simdSize); + retType, simdSize, mustExpand); } else { assert(intrinsic == NI_Vector512_AsVector512); return impSpecialIntrinsic(NI_Vector128_ToVector512, clsHnd, method, sig, simdBaseJitType, - retType, 16); + retType, 16, mustExpand); } } } @@ -1440,58 +1417,69 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } - case NI_Vector128_ConvertToInt64: - case NI_Vector256_ConvertToInt64: - case NI_Vector512_ConvertToInt64: + case NI_Vector128_ConvertToInt32: + case NI_Vector256_ConvertToInt32: + case NI_Vector512_ConvertToInt32: { assert(sig->numArgs == 1); - assert(simdBaseType == TYP_DOUBLE); - if (IsBaselineVector512IsaSupportedOpportunistically()) + assert(simdBaseType == TYP_FLOAT); + + if (compOpportunisticallyDependsOn(InstructionSet_SSE41)) { op1 = impSIMDPopStack(); - retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); } break; } - case NI_Vector128_ConvertToUInt32: - case NI_Vector256_ConvertToUInt32: - case NI_Vector512_ConvertToUInt32: + case NI_Vector128_ConvertToInt32Native: + case NI_Vector256_ConvertToInt32Native: + case NI_Vector512_ConvertToInt32Native: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_FLOAT); - if (IsBaselineVector512IsaSupportedOpportunistically()) + + if (BlockNonDeterministicIntrinsics(mustExpand)) { - op1 = impSIMDPopStack(); - retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); + break; } + + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); break; } - case NI_Vector128_ConvertToUInt64: - case NI_Vector256_ConvertToUInt64: - case NI_Vector512_ConvertToUInt64: + case NI_Vector128_ConvertToInt64: + case NI_Vector256_ConvertToInt64: + case NI_Vector512_ConvertToInt64: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); + if (IsBaselineVector512IsaSupportedOpportunistically()) { op1 = impSIMDPopStack(); - retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); } break; } - case NI_Vector128_ConvertToInt32: - case NI_Vector256_ConvertToInt32: - case NI_Vector512_ConvertToInt32: + case NI_Vector128_ConvertToInt64Native: + case NI_Vector256_ConvertToInt64Native: + case NI_Vector512_ConvertToInt64Native: { assert(sig->numArgs == 1); - assert(simdBaseType == TYP_FLOAT); - if (compOpportunisticallyDependsOn(InstructionSet_SSE41)) + assert(simdBaseType == TYP_DOUBLE); + + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + + if (IsBaselineVector512IsaSupportedOpportunistically()) { op1 = impSIMDPopStack(); - retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); } break; } @@ -1545,6 +1533,76 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_ConvertToUInt32: + case NI_Vector256_ConvertToUInt32: + case NI_Vector512_ConvertToUInt32: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_ConvertToUInt32Native: + case NI_Vector256_ConvertToUInt32Native: + case NI_Vector512_ConvertToUInt32Native: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_ConvertToUInt64: + case NI_Vector256_ConvertToUInt64: + case NI_Vector512_ConvertToUInt64: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_DOUBLE); + + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_ConvertToUInt64Native: + case NI_Vector256_ConvertToUInt64Native: + case NI_Vector512_ConvertToUInt64Native: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_DOUBLE); + + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); + } + break; + } + case NI_Vector128_Create: case NI_Vector256_Create: case NI_Vector512_Create: @@ -1967,9 +2025,12 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if (IsBaselineVector512IsaSupportedOpportunistically()) { op1 = impSIMDPopStack(); - op1 = - gtNewSimdHWIntrinsicNode(TYP_MASK, op1, NI_AVX512F_ConvertVectorToMask, simdBaseJitType, simdSize); + if (!varTypeIsMask(op1)) + { + op1 = gtNewSimdHWIntrinsicNode(TYP_MASK, op1, NI_AVX512F_ConvertVectorToMask, simdBaseJitType, + simdSize); + } retNode = gtNewSimdHWIntrinsicNode(retType, op1, NI_AVX512F_MoveMask, simdBaseJitType, simdSize); } break; @@ -2119,6 +2180,24 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_FusedMultiplyAdd: + case NI_Vector256_FusedMultiplyAdd: + case NI_Vector512_FusedMultiplyAdd: + { + assert(sig->numArgs == 3); + assert(varTypeIsFloating(simdBaseType)); + + if (compOpportunisticallyDependsOn(InstructionSet_FMA)) + { + op3 = impSIMDPopStack(); + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); + + retNode = gtNewSimdFmaNode(retType, op1, op2, op3, simdBaseJitType, simdSize); + } + break; + } + case NI_Vector128_get_AllBitsSet: case NI_Vector256_get_AllBitsSet: case NI_Vector512_get_AllBitsSet: @@ -2578,6 +2657,34 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_MultiplyAddEstimate: + case NI_Vector256_MultiplyAddEstimate: + case NI_Vector512_MultiplyAddEstimate: + { + assert(sig->numArgs == 3); + assert(varTypeIsFloating(simdBaseType)); + + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + break; + } + + op3 = impSIMDPopStack(); + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); + + if (compExactlyDependsOn(InstructionSet_FMA)) + { + retNode = gtNewSimdFmaNode(retType, op1, op2, op3, simdBaseJitType, simdSize); + } + else + { + GenTree* mulNode = gtNewSimdBinOpNode(GT_MUL, retType, op1, op2, simdBaseJitType, simdSize); + retNode = gtNewSimdBinOpNode(GT_ADD, retType, mulNode, op3, simdBaseJitType, simdSize); + } + break; + } + case NI_Vector128_Narrow: case NI_Vector256_Narrow: case NI_Vector512_Narrow: @@ -3339,6 +3446,38 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, op1 = impCloneExpr(op1, &clonedOp1, CHECK_SPILL_ALL, nullptr DEBUGARG("Clone op1 for Sse.CompareScalarGreaterThan")); + switch (intrinsic) + { + case NI_SSE_CompareScalarGreaterThan: + { + intrinsic = NI_SSE_CompareScalarLessThan; + break; + } + + case NI_SSE_CompareScalarGreaterThanOrEqual: + { + intrinsic = NI_SSE_CompareScalarLessThanOrEqual; + break; + } + + case NI_SSE_CompareScalarNotGreaterThan: + { + intrinsic = NI_SSE_CompareScalarNotLessThan; + break; + } + + case NI_SSE_CompareScalarNotGreaterThanOrEqual: + { + intrinsic = NI_SSE_CompareScalarNotLessThanOrEqual; + break; + } + + default: + { + unreached(); + } + } + retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op2, op1, intrinsic, simdBaseJitType, simdSize); retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, clonedOp1, retNode, NI_SSE_MoveScalar, simdBaseJitType, simdSize); @@ -3398,6 +3537,38 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, op1 = impCloneExpr(op1, &clonedOp1, CHECK_SPILL_ALL, nullptr DEBUGARG("Clone op1 for Sse2.CompareScalarGreaterThan")); + switch (intrinsic) + { + case NI_SSE2_CompareScalarGreaterThan: + { + intrinsic = NI_SSE2_CompareScalarLessThan; + break; + } + + case NI_SSE2_CompareScalarGreaterThanOrEqual: + { + intrinsic = NI_SSE2_CompareScalarLessThanOrEqual; + break; + } + + case NI_SSE2_CompareScalarNotGreaterThan: + { + intrinsic = NI_SSE2_CompareScalarNotLessThan; + break; + } + + case NI_SSE2_CompareScalarNotGreaterThanOrEqual: + { + intrinsic = NI_SSE2_CompareScalarNotLessThanOrEqual; + break; + } + + default: + { + unreached(); + } + } + retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op2, op1, intrinsic, simdBaseJitType, simdSize); retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, clonedOp1, retNode, NI_SSE2_MoveScalar, simdBaseJitType, simdSize); @@ -4033,12 +4204,32 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); - op3 = gtNewSimdHWIntrinsicNode(TYP_MASK, op3, NI_AVX512F_ConvertVectorToMask, simdBaseJitType, simdSize); + if (!varTypeIsMask(op3)) + { + op3 = + gtNewSimdHWIntrinsicNode(TYP_MASK, op3, NI_AVX512F_ConvertVectorToMask, simdBaseJitType, simdSize); + } retNode = gtNewSimdHWIntrinsicNode(retType, op1, op2, op3, NI_AVX512F_BlendVariableMask, simdBaseJitType, simdSize); break; } + case NI_AVX512F_Compare: + { + assert(sig->numArgs == 3); + + op3 = impPopStack().val; + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); + + retNode = + gtNewSimdHWIntrinsicNode(TYP_MASK, op1, op2, op3, NI_AVX512F_CompareMask, simdBaseJitType, simdSize); + retNode = + gtNewSimdHWIntrinsicNode(retType, retNode, NI_AVX512F_ConvertMaskToVector, simdBaseJitType, simdSize); + + break; + } + case NI_AVX512F_CompareEqual: case NI_AVX512BW_CompareEqual: { @@ -4315,4 +4506,27 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, return retNode; } + +//------------------------------------------------------------------------ +// getHWIntrinsicImmOps: Gets the immediate Ops for an intrinsic +// +// Arguments: +// intrinsic -- NamedIntrinsic associated with the HWIntrinsic to lookup +// sig -- signature of the intrinsic call. +// immOp1Ptr [OUT] -- The first immediate Op +// immOp2Ptr [OUT] -- The second immediate Op, if any. Otherwise unchanged. +// +void Compiler::getHWIntrinsicImmOps(NamedIntrinsic intrinsic, + CORINFO_SIG_INFO* sig, + GenTree** immOp1Ptr, + GenTree** immOp2Ptr) +{ + if ((sig->numArgs > 0) && HWIntrinsicInfo::isImmOp(intrinsic, impStackTop().val)) + { + // NOTE: The following code assumes that for all intrinsics + // taking an immediate operand, that operand will be last. + *immOp1Ptr = impStackTop().val; + } +} + #endif // FEATURE_HW_INTRINSICS diff --git a/src/coreclr/jit/ifconversion.cpp b/src/coreclr/jit/ifconversion.cpp index 6d7ead881a91..6008bb432550 100644 --- a/src/coreclr/jit/ifconversion.cpp +++ b/src/coreclr/jit/ifconversion.cpp @@ -231,7 +231,7 @@ bool OptIfConversionDsc::IfConvertCheckStmts(BasicBlock* fromBlock, IfConvertOpe for (Statement* const stmt : block->Statements()) { GenTree* tree = stmt->GetRootNode(); - switch (tree->gtOper) + switch (tree->OperGet()) { case GT_STORE_LCL_VAR: { @@ -287,7 +287,8 @@ bool OptIfConversionDsc::IfConvertCheckStmts(BasicBlock* fromBlock, IfConvertOpe case GT_RETURN: { - GenTree* op1 = tree->gtGetOp1(); + // GT_SWIFT_ERROR_RET not supported + GenTree* const retVal = tree->gtGetOp1(); // Only allow RETURNs if else conversion is being used. if (!m_doElseConversion) @@ -296,7 +297,7 @@ bool OptIfConversionDsc::IfConvertCheckStmts(BasicBlock* fromBlock, IfConvertOpe } // Only one per operation per block can be conditionally executed. - if (found || op1 == nullptr) + if (found || retVal == nullptr) { return false; } @@ -317,7 +318,7 @@ bool OptIfConversionDsc::IfConvertCheckStmts(BasicBlock* fromBlock, IfConvertOpe #endif // Ensure it won't cause any additional side effects. - if ((op1->gtFlags & (GTF_SIDE_EFFECT | GTF_ORDER_SIDEEFF)) != 0) + if ((retVal->gtFlags & (GTF_SIDE_EFFECT | GTF_ORDER_SIDEEFF)) != 0) { return false; } @@ -326,7 +327,8 @@ bool OptIfConversionDsc::IfConvertCheckStmts(BasicBlock* fromBlock, IfConvertOpe // with the condition (for example, the condition could be an explicit bounds // check and the operand could read an array element). Disallow this except // for some common cases that we know are always side effect free. - if (((m_cond->gtFlags & GTF_ORDER_SIDEEFF) != 0) && !op1->IsInvariant() && !op1->OperIsLocal()) + if (((m_cond->gtFlags & GTF_ORDER_SIDEEFF) != 0) && !retVal->IsInvariant() && + !retVal->OperIsLocal()) { return false; } @@ -634,10 +636,10 @@ bool OptIfConversionDsc::optIfConvert() else { assert(m_mainOper == GT_RETURN); - thenCost = m_thenOperation.node->gtGetOp1()->GetCostEx(); + thenCost = m_thenOperation.node->AsOp()->GetReturnValue()->GetCostEx(); if (m_doElseConversion) { - elseCost = m_elseOperation.node->gtGetOp1()->GetCostEx(); + elseCost = m_elseOperation.node->AsOp()->GetReturnValue()->GetCostEx(); } } @@ -697,8 +699,8 @@ bool OptIfConversionDsc::optIfConvert() assert(m_doElseConversion); assert(m_thenOperation.node->TypeGet() == m_elseOperation.node->TypeGet()); - selectTrueInput = m_elseOperation.node->gtGetOp1(); - selectFalseInput = m_thenOperation.node->gtGetOp1(); + selectTrueInput = m_elseOperation.node->AsOp()->GetReturnValue(); + selectFalseInput = m_thenOperation.node->AsOp()->GetReturnValue(); selectType = genActualType(m_thenOperation.node); } @@ -714,7 +716,7 @@ bool OptIfConversionDsc::optIfConvert() } else { - m_thenOperation.node->AsOp()->gtOp1 = select; + m_thenOperation.node->AsOp()->SetReturnValue(select); } m_comp->gtSetEvalOrder(m_thenOperation.node); m_comp->fgSetStmtSeq(m_thenOperation.stmt); diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 4928204635d1..402437271875 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -89,7 +89,7 @@ bool Compiler::impILConsumesAddr(const BYTE* codeAddr) // out if we need to do so. CORINFO_RESOLVED_TOKEN resolvedToken; - impResolveToken(codeAddr + sizeof(__int8), &resolvedToken, CORINFO_TOKENKIND_Field); + impResolveToken(codeAddr + sizeof(int8_t), &resolvedToken, CORINFO_TOKENKIND_Field); var_types lclTyp = JITtype2varType(info.compCompHnd->getFieldType(resolvedToken.hField)); @@ -5129,6 +5129,23 @@ void Compiler::impResetLeaveBlock(BasicBlock* block, unsigned jmpAddr) // reason we don't want to remove the block at this point is that if we call // fgInitBBLookup() again we will do it wrong as the BBJ_ALWAYS block won't be // added and the linked list length will be different than fgBBcount. + // + // Because of this incomplete cleanup. profile data may be left inconsistent. + // + if (block->hasProfileWeight()) + { + // We are unlikely to be able to repair the profile. + // For now we don't even try. + // + JITDUMP("\nimpResetLeaveBlock: Profile data could not be locally repaired. Data %s inconsistent.\n", + fgPgoConsistent ? "is now" : "was already"); + + if (fgPgoConsistent) + { + Metrics.ProfileInconsistentResetLeave++; + fgPgoConsistent = false; + } + } } /*****************************************************************************/ @@ -5140,7 +5157,7 @@ OPCODE Compiler::impGetNonPrefixOpcode(const BYTE* codeAddr, const BYTE* codeEnd while (codeAddr < codeEndp) { OPCODE opcode = (OPCODE)getU1LittleEndian(codeAddr); - codeAddr += sizeof(__int8); + codeAddr += sizeof(int8_t); if (opcode == CEE_PREFIX1) { @@ -5149,7 +5166,7 @@ OPCODE Compiler::impGetNonPrefixOpcode(const BYTE* codeAddr, const BYTE* codeEnd break; } opcode = (OPCODE)(getU1LittleEndian(codeAddr) + 256); - codeAddr += sizeof(__int8); + codeAddr += sizeof(int8_t); } switch (opcode) @@ -6120,7 +6137,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) /* Get the next opcode and the size of its parameters */ OPCODE opcode = (OPCODE)getU1LittleEndian(codeAddr); - codeAddr += sizeof(__int8); + codeAddr += sizeof(int8_t); #ifdef DEBUG impCurOpcOffs = (IL_OFFSET)(codeAddr - info.compCode - 1); @@ -6181,14 +6198,14 @@ void Compiler::impImportBlockCode(BasicBlock* block) { int intVal; float fltVal; - __int64 lngVal; + int64_t lngVal; double dblVal; } cval; case CEE_PREFIX1: opcode = (OPCODE)(getU1LittleEndian(codeAddr) + 256); opcodeOffs = (IL_OFFSET)(codeAddr - info.compCode); - codeAddr += sizeof(__int8); + codeAddr += sizeof(int8_t); goto DECODE_OPCODE; SPILL_APPEND: @@ -6607,7 +6624,11 @@ void Compiler::impImportBlockCode(BasicBlock* block) return; } - block->bbSetRunRarely(); // filters are rare + if (!fgPgoSynthesized) + { + // filters are rare + block->bbSetRunRarely(); + } if (info.compXcptnsCount == 0) { @@ -7161,12 +7182,12 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_LEAVE: val = getI4LittleEndian(codeAddr); // jump distance - jmpAddr = (IL_OFFSET)((codeAddr - info.compCode + sizeof(__int32)) + val); + jmpAddr = (IL_OFFSET)((codeAddr - info.compCode + sizeof(int32_t)) + val); goto LEAVE; case CEE_LEAVE_S: val = getI1LittleEndian(codeAddr); // jump distance - jmpAddr = (IL_OFFSET)((codeAddr - info.compCode + sizeof(__int8)) + val); + jmpAddr = (IL_OFFSET)((codeAddr - info.compCode + sizeof(int8_t)) + val); LEAVE: @@ -7295,19 +7316,73 @@ void Compiler::impImportBlockCode(BasicBlock* block) if (block->KindIs(BBJ_COND)) { - if (op1->AsIntCon()->gtIconVal) - { - JITDUMP("\nThe conditional jump becomes an unconditional jump to " FMT_BB "\n", - block->GetTrueTarget()->bbNum); - fgRemoveRefPred(block->GetFalseEdge()); - block->SetKindAndTargetEdge(BBJ_ALWAYS, block->GetTrueEdge()); - } - else + bool const isCondTrue = op1->AsIntCon()->gtIconVal != 0; + FlowEdge* const removedEdge = isCondTrue ? block->GetFalseEdge() : block->GetTrueEdge(); + FlowEdge* const retainedEdge = isCondTrue ? block->GetTrueEdge() : block->GetFalseEdge(); + + JITDUMP("\nThe conditional jump becomes an unconditional jump to " FMT_BB "\n", + retainedEdge->getDestinationBlock()->bbNum); + + fgRemoveRefPred(removedEdge); + block->SetKindAndTargetEdge(BBJ_ALWAYS, retainedEdge); + Metrics.ImporterBranchFold++; + + // If we removed an edge carrying profile, try to do a local repair. + // + if (block->hasProfileWeight()) { - assert(block->NextIs(block->GetFalseTarget())); - JITDUMP("\nThe block jumps to the next " FMT_BB "\n", block->Next()->bbNum); - fgRemoveRefPred(block->GetTrueEdge()); - block->SetKindAndTargetEdge(BBJ_ALWAYS, block->GetFalseEdge()); + bool repairWasComplete = true; + weight_t const weight = removedEdge->getLikelyWeight(); + + if (weight > 0) + { + // Target block weight will increase. + // + BasicBlock* const target = block->GetTarget(); + assert(target->hasProfileWeight()); + target->setBBProfileWeight(target->bbWeight + weight); + + // Alternate weight will decrease + // + BasicBlock* const alternate = removedEdge->getDestinationBlock(); + assert(alternate->hasProfileWeight()); + weight_t const alternateNewWeight = alternate->bbWeight - weight; + + // If profile weights are consistent, expect at worst a slight underflow. + // + if (fgPgoConsistent && (alternateNewWeight < 0)) + { + assert(fgProfileWeightsEqual(alternateNewWeight, 0)); + } + alternate->setBBProfileWeight(max(0.0, alternateNewWeight)); + + // This will affect profile transitively, so in general + // the profile will become inconsistent. + // + repairWasComplete = false; + + // But we can check for the special case where the + // block's postdominator is target's target (simple + // if/then/else/join). + // + if (target->KindIs(BBJ_ALWAYS)) + { + repairWasComplete = alternate->KindIs(BBJ_ALWAYS) && + (alternate->GetTarget() == target->GetTarget()); + } + } + + if (!repairWasComplete) + { + JITDUMP("Profile data could not be locally repaired. Data %s inconsistent.\n", + fgPgoConsistent ? "is now" : "was already"); + + if (fgPgoConsistent) + { + Metrics.ProfileInconsistentImporterBranchFold++; + fgPgoConsistent = false; + } + } } } @@ -7552,6 +7627,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) unsigned jumpCnt = block->GetSwitchTargets()->bbsCount; FlowEdge** jumpTab = block->GetSwitchTargets()->bbsDstTab; bool foundVal = false; + Metrics.ImporterSwitchFold++; for (unsigned val = 0; val < jumpCnt; val++, jumpTab++) { @@ -7585,6 +7661,20 @@ void Compiler::impImportBlockCode(BasicBlock* block) printf("\n"); } #endif + if (block->hasProfileWeight()) + { + // We are unlikely to be able to repair the profile. + // For now we don't even try. + // + JITDUMP("Profile data could not be locally repaired. Data %s inconsistent.\n", + fgPgoConsistent ? "is now" : "was already"); + + if (fgPgoConsistent) + { + Metrics.ProfileInconsistentImporterSwitchFold++; + fgPgoConsistent = false; + } + } // Create a NOP node op1 = gtNewNothingNode(); @@ -7927,6 +8017,14 @@ void Compiler::impImportBlockCode(BasicBlock* block) /* Append the value to the tree list */ goto SPILL_APPEND; } + else + { + if (op1->IsBoxedValue()) + { + JITDUMP("\n CEE_POP box...\n"); + gtTryRemoveBoxUpstreamEffects(op1); + } + } /* No side effects - just throw the thing away */ } @@ -8137,7 +8235,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) PREFIX: opcode = (OPCODE)getU1LittleEndian(codeAddr); opcodeOffs = (IL_OFFSET)(codeAddr - info.compCode); - codeAddr += sizeof(__int8); + codeAddr += sizeof(int8_t); goto DECODE_OPCODE; case CEE_VOLATILE: @@ -10070,8 +10168,11 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_THROW: - // Any block with a throw is rarely executed. - block->bbSetRunRarely(); + if (!fgPgoSynthesized) + { + // Any block with a throw is rarely executed. + block->bbSetRunRarely(); + } // Pop the exception object and create the 'throw' helper call op1 = gtNewHelperCallNode(CORINFO_HELP_THROW, TYP_VOID, impPopStack().val); @@ -10469,21 +10570,6 @@ void Compiler::impLoadArg(unsigned ilArgNum, IL_OFFSET offset) { lclNum = lvaArg0Var; } -#ifdef SWIFT_SUPPORT - else if (lclNum == lvaSwiftErrorArg) - { - // Convert any usages of the SwiftError pointer/ref parameter to pointers/refs to the SwiftError pseudolocal - // (set side effect flags so usages of references to pseudolocal aren't removed) - assert(info.compCallConv == CorInfoCallConvExtension::Swift); - assert(lvaSwiftErrorArg != BAD_VAR_NUM); - assert(lvaSwiftErrorLocal != BAD_VAR_NUM); - const var_types type = lvaGetDesc(lvaSwiftErrorArg)->TypeGet(); - GenTree* const swiftErrorLocalRef = gtNewLclVarAddrNode(lvaSwiftErrorLocal, type); - impPushOnStack(swiftErrorLocalRef, typeInfo(type)); - JITDUMP("\nCreated GT_LCL_ADDR of SwiftError pseudolocal\n"); - return; - } -#endif // SWIFT_SUPPORT impLoadVar(lclNum, offset); } diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index f5156be16fa1..950b9468ed0a 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -888,7 +888,21 @@ var_types Compiler::impImportCall(OPCODE opcode, } //------------------------------------------------------------------------- - // The main group of arguments + // The main group of arguments, and the this pointer. + + // 'this' is pushed on the IL stack before all call args, but if this is a + // constrained call 'this' is a byref that may need to be dereferenced. + // That dereference should happen _after_ all args, so we need to spill + // them if they can interfere. + bool hasThis; + hasThis = ((mflags & CORINFO_FLG_STATIC) == 0) && ((sig->callConv & CORINFO_CALLCONV_EXPLICITTHIS) == 0) && + ((opcode != CEE_NEWOBJ) || (newobjThis != nullptr)); + + if (hasThis && (constraintCallThisTransform == CORINFO_DEREF_THIS)) + { + impSpillSideEffects(false, CHECK_SPILL_ALL DEBUGARG( + "constrained call requires dereference for 'this' right before call")); + } impPopCallArgs(sig, call->AsCall()); if (extraArg.Node != nullptr) @@ -908,8 +922,7 @@ var_types Compiler::impImportCall(OPCODE opcode, //------------------------------------------------------------------------- // The "this" pointer - if (((mflags & CORINFO_FLG_STATIC) == 0) && ((sig->callConv & CORINFO_CALLCONV_EXPLICITTHIS) == 0) && - !((opcode == CEE_NEWOBJ) && (newobjThis == nullptr))) + if (hasThis) { GenTree* obj; @@ -996,6 +1009,10 @@ var_types Compiler::impImportCall(OPCODE opcode, // New inliner morph it in impImportCall. // This will allow us to inline the call to the delegate constructor. call = fgOptimizeDelegateConstructor(call->AsCall(), &exactContextHnd, ldftnInfo); + if (compDonotInline()) + { + return TYP_UNDEF; + } } if (!bIntrinsicImported) @@ -1445,8 +1462,8 @@ var_types Compiler::impImportCall(OPCODE opcode, if (call->IsCall()) { GenTreeCall* callNode = call->AsCall(); - if ((callNode->gtCallType == CT_HELPER) && (gtIsTypeHandleToRuntimeTypeHelper(callNode) || - gtIsTypeHandleToRuntimeTypeHandleHelper(callNode))) + if (callNode->IsHelperCall() && (gtIsTypeHandleToRuntimeTypeHelper(callNode) || + gtIsTypeHandleToRuntimeTypeHandleHelper(callNode))) { spillStack = false; } @@ -2370,8 +2387,8 @@ GenTree* Compiler::impInitializeArrayIntrinsic(CORINFO_SIG_INFO* sig) // // Check to see if the ldtoken helper call is what we see here. - if (fieldTokenNode->gtOper != GT_CALL || (fieldTokenNode->AsCall()->gtCallType != CT_HELPER) || - (fieldTokenNode->AsCall()->gtCallMethHnd != eeFindHelper(CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD))) + if (!fieldTokenNode->OperIs(GT_CALL) || + !fieldTokenNode->AsCall()->IsHelperCall(eeFindHelper(CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD))) { return nullptr; } @@ -2424,7 +2441,7 @@ GenTree* Compiler::impInitializeArrayIntrinsic(CORINFO_SIG_INFO* sig) // GenTree* newArrayCall = arrayLocalStore->AsLclVar()->Data(); - if ((newArrayCall->gtOper != GT_CALL) || (newArrayCall->AsCall()->gtCallType != CT_HELPER)) + if (!newArrayCall->OperIs(GT_CALL) || !newArrayCall->AsCall()->IsHelperCall()) { return nullptr; } @@ -2713,8 +2730,8 @@ GenTree* Compiler::impCreateSpanIntrinsic(CORINFO_SIG_INFO* sig) // // Check to see if the ldtoken helper call is what we see here. - if (fieldTokenNode->gtOper != GT_CALL || (fieldTokenNode->AsCall()->gtCallType != CT_HELPER) || - (fieldTokenNode->AsCall()->gtCallMethHnd != eeFindHelper(CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD))) + if (!fieldTokenNode->OperIs(GT_CALL) || + !fieldTokenNode->AsCall()->IsHelperCall(eeFindHelper(CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD))) { return nullptr; } @@ -3019,8 +3036,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, else { assert((ni > NI_PRIMITIVE_START) && (ni < NI_PRIMITIVE_END)); - assert(!mustExpand); - return impPrimitiveNamedIntrinsic(ni, clsHnd, method, sig); + return impPrimitiveNamedIntrinsic(ni, clsHnd, method, sig, mustExpand); } } @@ -3075,11 +3091,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, if (isIntrinsic) { - // These intrinsics aren't defined recursively and so they will never be mustExpand - // Instead, they provide software fallbacks that will be executed instead. - - assert(!mustExpand); - return impSimdAsHWIntrinsic(ni, clsHnd, method, sig, newobjThis); + return impSimdAsHWIntrinsic(ni, clsHnd, method, sig, newobjThis, mustExpand); } } } @@ -3184,9 +3196,9 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, break; default: - // Unsafe.* are all small enough to prefer expansions. + // Various intrinsics are all small enough to prefer expansions. + betterToExpand |= ni >= NI_SYSTEM_MATH_START && ni <= NI_SYSTEM_MATH_END; betterToExpand |= ni >= NI_SRCS_UNSAFE_START && ni <= NI_SRCS_UNSAFE_END; - // Same for these betterToExpand |= ni >= NI_PRIMITIVE_START && ni <= NI_PRIMITIVE_END; break; } @@ -3624,7 +3636,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, { GenTree* op1 = impStackTop(0).val; CorInfoHelpFunc typeHandleHelper; - if (op1->gtOper == GT_CALL && (op1->AsCall()->gtCallType == CT_HELPER) && + if (op1->gtOper == GT_CALL && op1->AsCall()->IsHelperCall() && gtIsTypeHandleToRuntimeTypeHandleHelper(op1->AsCall(), &typeHandleHelper)) { op1 = impPopStack().val; @@ -3983,13 +3995,18 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, // Vector128.CreateScalarUnsafe(z) // ).ToScalar(); - GenTree* op3 = gtNewSimdCreateScalarUnsafeNode(TYP_SIMD16, impPopStack().val, callJitType, 16); - GenTree* op2 = gtNewSimdCreateScalarUnsafeNode(TYP_SIMD16, impPopStack().val, callJitType, 16); - GenTree* op1 = gtNewSimdCreateScalarUnsafeNode(TYP_SIMD16, impPopStack().val, callJitType, 16); - GenTree* res = + GenTree* op3 = impImplicitR4orR8Cast(impPopStack().val, callType); + GenTree* op2 = impImplicitR4orR8Cast(impPopStack().val, callType); + GenTree* op1 = impImplicitR4orR8Cast(impPopStack().val, callType); + + op3 = gtNewSimdCreateScalarUnsafeNode(TYP_SIMD16, op3, callJitType, 16); + op2 = gtNewSimdCreateScalarUnsafeNode(TYP_SIMD16, op2, callJitType, 16); + op1 = gtNewSimdCreateScalarUnsafeNode(TYP_SIMD16, op1, callJitType, 16); + + retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, op2, op3, NI_FMA_MultiplyAddScalar, callJitType, 16); - retNode = gtNewSimdToScalarNode(callType, res, callJitType, 16); + retNode = gtNewSimdToScalarNode(callType, retNode, callJitType, 16); break; } #elif defined(TARGET_ARM64) @@ -4004,9 +4021,19 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, // Vector64.Create{ScalarUnsafe}(x) // ).ToScalar(); - GenTree* op3 = gtNewSimdCreateScalarUnsafeNode(TYP_SIMD8, impPopStack().val, callJitType, 8); - GenTree* op2 = gtNewSimdCreateScalarUnsafeNode(TYP_SIMD8, impPopStack().val, callJitType, 8); - GenTree* op1 = gtNewSimdCreateScalarUnsafeNode(TYP_SIMD8, impPopStack().val, callJitType, 8); + impSpillSideEffect(true, verCurrentState.esStackDepth - + 3 DEBUGARG("Spilling op1 side effects for FusedMultiplyAdd")); + + impSpillSideEffect(true, verCurrentState.esStackDepth - + 2 DEBUGARG("Spilling op2 side effects for FusedMultiplyAdd")); + + GenTree* op3 = impImplicitR4orR8Cast(impPopStack().val, callType); + GenTree* op2 = impImplicitR4orR8Cast(impPopStack().val, callType); + GenTree* op1 = impImplicitR4orR8Cast(impPopStack().val, callType); + + op3 = gtNewSimdCreateScalarUnsafeNode(TYP_SIMD8, op3, callJitType, 8); + op2 = gtNewSimdCreateScalarUnsafeNode(TYP_SIMD8, op2, callJitType, 8); + op1 = gtNewSimdCreateScalarUnsafeNode(TYP_SIMD8, op1, callJitType, 8); // Note that AdvSimd.FusedMultiplyAddScalar(op1,op2,op3) corresponds to op1 + op2 * op3 // while Math{F}.FusedMultiplyAddScalar(op1,op2,op3) corresponds to op1 * op2 + op3 @@ -4144,6 +4171,14 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, break; } + case NI_System_Math_MultiplyAddEstimate: + case NI_System_Math_ReciprocalEstimate: + case NI_System_Math_ReciprocalSqrtEstimate: + { + retNode = impEstimateIntrinsic(method, sig, callJitType, ni, mustExpand); + break; + } + case NI_System_Array_Clone: case NI_System_Collections_Generic_Comparer_get_Default: case NI_System_Collections_Generic_EqualityComparer_get_Default: @@ -4728,6 +4763,14 @@ GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic intrinsic, ClassLayout* toLayout = nullptr; var_types toType = TypeHandleToVarType(toTypeHnd, &toLayout); + if (fromType == TYP_REF || info.compCompHnd->isNullableType(fromTypeHnd) != TypeCompareState::MustNot || + toType == TYP_REF || info.compCompHnd->isNullableType(toTypeHnd) != TypeCompareState::MustNot) + { + // Fallback to the software implementation to throw when the types fail a "default(T) is not null" + // check. + return nullptr; + } + unsigned fromSize = fromLayout != nullptr ? fromLayout->GetSize() : genTypeSize(fromType); unsigned toSize = toLayout != nullptr ? toLayout->GetSize() : genTypeSize(toType); @@ -4740,8 +4783,6 @@ GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic intrinsic, return nullptr; } - assert((fromType != TYP_REF) && (toType != TYP_REF)); - GenTree* op1 = impPopStack().val; op1 = impImplicitR4orR8Cast(op1, fromType); @@ -5143,6 +5184,7 @@ GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic intrinsic, // clsHnd - handle for the intrinsic method's class // method - handle for the intrinsic method // sig - signature of the intrinsic method +// mustExpand - true if the intrinsic must return a GenTree*; otherwise, false // // Returns: // IR tree to use in place of the call, or nullptr if the jit should treat @@ -5151,17 +5193,22 @@ GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic intrinsic, GenTree* Compiler::impPrimitiveNamedIntrinsic(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig) + CORINFO_SIG_INFO* sig, + bool mustExpand) { assert(sig->sigInst.classInstCount == 0); var_types retType = JITtype2varType(sig->retType); - assert(varTypeIsArithmetic(retType)); + + if (!varTypeIsArithmetic(retType)) + { + assert((intrinsic == NI_PRIMITIVE_ConvertToInteger) || (intrinsic == NI_PRIMITIVE_ConvertToIntegerNative)); + return nullptr; + } NamedIntrinsic hwintrinsic = NI_Illegal; CORINFO_ARG_LIST_HANDLE args = sig->args; - assert((sig->numArgs == 1) || (sig->numArgs == 2)); CORINFO_CLASS_HANDLE op1ClsHnd; @@ -5172,6 +5219,121 @@ GenTree* Compiler::impPrimitiveNamedIntrinsic(NamedIntrinsic intrinsic, switch (intrinsic) { + case NI_PRIMITIVE_ConvertToIntegerNative: + { + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + return nullptr; + } + FALLTHROUGH; + } + + case NI_PRIMITIVE_ConvertToInteger: + { + assert(sig->sigInst.methInstCount == 1); + assert(varTypeIsFloating(baseType)); + + var_types tgtType = JitType2PreciseVarType(sig->retType); + retType = genActualType(retType); + bool uns = varTypeIsUnsigned(tgtType) && !varTypeIsSmall(tgtType); + + GenTree* res = nullptr; + GenTree* op1 = nullptr; + +#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) + if ((intrinsic == NI_PRIMITIVE_ConvertToIntegerNative) && IsBaselineSimdIsaSupported()) + { + NamedIntrinsic hwIntrinsicId = NI_Illegal; + + if (retType == TYP_INT) + { + if (baseType == TYP_FLOAT) + { + if (!uns) + { + hwIntrinsicId = NI_SSE_ConvertToInt32WithTruncation; + } + else if (IsBaselineVector512IsaSupportedOpportunistically()) + { + hwIntrinsicId = NI_AVX512F_ConvertToUInt32WithTruncation; + } + } + else + { + assert(baseType == TYP_DOUBLE); + + if (!uns) + { + hwIntrinsicId = NI_SSE2_ConvertToInt32WithTruncation; + } + else if (IsBaselineVector512IsaSupportedOpportunistically()) + { + hwIntrinsicId = NI_AVX512F_ConvertToUInt32WithTruncation; + } + } + } +#if defined(TARGET_AMD64) + else + { + assert(retType == TYP_LONG); + + if (baseType == TYP_FLOAT) + { + if (!uns) + { + hwIntrinsicId = NI_SSE_X64_ConvertToInt64WithTruncation; + } + else if (IsBaselineVector512IsaSupportedOpportunistically()) + { + hwIntrinsicId = NI_AVX512F_X64_ConvertToUInt64WithTruncation; + } + } + else + { + assert(baseType == TYP_DOUBLE); + + if (!uns) + { + hwIntrinsicId = NI_SSE2_X64_ConvertToInt64WithTruncation; + } + else if (IsBaselineVector512IsaSupportedOpportunistically()) + { + hwIntrinsicId = NI_AVX512F_X64_ConvertToUInt64WithTruncation; + } + } + } +#endif // TARGET_AMD64 + + if (hwIntrinsicId != NI_Illegal) + { + op1 = impPopStack().val; + res = gtNewSimdHWIntrinsicNode(retType, op1, hwIntrinsicId, baseJitType, 16); + + if (varTypeIsSmall(tgtType)) + { + res = gtNewCastNode(TYP_INT, res, /* uns */ false, tgtType); + } + return res; + } + } +#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS + + op1 = impPopStack().val; + + if (varTypeIsSmall(tgtType)) + { + res = gtNewCastNodeL(retType, op1, /* uns */ false, retType); + res = gtFoldExpr(res); + res = gtNewCastNode(TYP_INT, res, /* uns */ false, tgtType); + } + else + { + res = gtNewCastNodeL(retType, op1, /* uns */ false, tgtType); + } + + return gtFoldExpr(res); + } + case NI_PRIMITIVE_Crc32C: { assert(sig->numArgs == 2); @@ -5391,7 +5553,7 @@ GenTree* Compiler::impPrimitiveNamedIntrinsic(NamedIntrinsic intrinsic, } #if defined(FEATURE_HW_INTRINSICS) - GenTree* lzcnt = impPrimitiveNamedIntrinsic(NI_PRIMITIVE_LeadingZeroCount, clsHnd, method, sig); + GenTree* lzcnt = impPrimitiveNamedIntrinsic(NI_PRIMITIVE_LeadingZeroCount, clsHnd, method, sig, mustExpand); if (lzcnt != nullptr) { @@ -7112,7 +7274,7 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call, /* Ignore helper calls */ - if (call->gtCallType == CT_HELPER) + if (call->IsHelperCall()) { assert(!call->IsGuardedDevirtualizationCandidate()); inlineResult->NoteFatal(InlineObservation::CALLSITE_IS_CALL_TO_HELPER); @@ -7294,13 +7456,16 @@ bool Compiler::IsTargetIntrinsic(NamedIntrinsic intrinsicName) // instructions to directly compute round/ceiling/floor/truncate. case NI_System_Math_Abs: + case NI_System_Math_MultiplyAddEstimate: + case NI_System_Math_ReciprocalEstimate: + case NI_System_Math_ReciprocalSqrtEstimate: case NI_System_Math_Sqrt: return true; case NI_System_Math_Ceiling: case NI_System_Math_Floor: - case NI_System_Math_Truncate: case NI_System_Math_Round: + case NI_System_Math_Truncate: return compOpportunisticallyDependsOn(InstructionSet_SSE41); case NI_System_Math_FusedMultiplyAdd: @@ -7315,11 +7480,14 @@ bool Compiler::IsTargetIntrinsic(NamedIntrinsic intrinsicName) case NI_System_Math_Abs: case NI_System_Math_Ceiling: case NI_System_Math_Floor: - case NI_System_Math_Truncate: - case NI_System_Math_Round: - case NI_System_Math_Sqrt: case NI_System_Math_Max: case NI_System_Math_Min: + case NI_System_Math_MultiplyAddEstimate: + case NI_System_Math_ReciprocalEstimate: + case NI_System_Math_ReciprocalSqrtEstimate: + case NI_System_Math_Round: + case NI_System_Math_Sqrt: + case NI_System_Math_Truncate: return true; case NI_System_Math_FusedMultiplyAdd: @@ -7333,16 +7501,46 @@ bool Compiler::IsTargetIntrinsic(NamedIntrinsic intrinsicName) { case NI_System_Math_Abs: case NI_System_Math_Sqrt: + case NI_System_Math_MultiplyAddEstimate: + case NI_System_Math_ReciprocalEstimate: + case NI_System_Math_ReciprocalSqrtEstimate: return true; default: return false; } -#elif TARGET_WASM +#elif defined(TARGET_WASM) + switch (intrinsicName) + { + case NI_System_Math_MultiplyAddEstimate: + case NI_System_Math_ReciprocalEstimate: + case NI_System_Math_ReciprocalSqrtEstimate: + return true; + default: + break; + } + return m_llvm->IsLlvmIntrinsic(intrinsicName); #elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - // TODO-LoongArch64: add some intrinsics. - return false; + switch (intrinsicName) + { + case NI_System_Math_Abs: + case NI_System_Math_Sqrt: + case NI_System_Math_ReciprocalSqrtEstimate: + { + // TODO-LoongArch64: support these standard intrinsics + // TODO-RISCV64: support these standard intrinsics + + return false; + } + + case NI_System_Math_MultiplyAddEstimate: + case NI_System_Math_ReciprocalEstimate: + return true; + + default: + return false; + } #else // TODO: This portion of logic is not implemented for other arch. // The reason for returning true is that on all other arch the only intrinsic @@ -7395,7 +7593,10 @@ bool Compiler::IsMathIntrinsic(NamedIntrinsic intrinsicName) case NI_System_Math_MinMagnitude: case NI_System_Math_MinMagnitudeNumber: case NI_System_Math_MinNumber: + case NI_System_Math_MultiplyAddEstimate: case NI_System_Math_Pow: + case NI_System_Math_ReciprocalEstimate: + case NI_System_Math_ReciprocalSqrtEstimate: case NI_System_Math_Round: case NI_System_Math_Sin: case NI_System_Math_Sinh: @@ -7754,6 +7955,7 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, // the resulting method would be a generic method of the non-generic SZArrayHelper class. // assert(canDevirtualize); + Metrics.DevirtualizedCall++; JITDUMP(" %s; can devirtualize\n", note); @@ -7982,6 +8184,8 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, // We may end up inlining this call, so the local copy must be marked as "aliased", // making sure the inlinee importer will know when to spill references to its value. lvaGetDesc(localCopyThis->AsLclFld())->lvHasLdAddrOp = true; + Metrics.DevirtualizedCallRemovedBox++; + Metrics.DevirtualizedCallUnboxedEntry++; #if FEATURE_TAILCALL_OPT if (call->IsImplicitTailCall()) @@ -8045,6 +8249,7 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, derivedMethodAttribs = unboxedMethodAttribs; call->gtArgs.InsertInstParam(this, methodTableArg); + Metrics.DevirtualizedCallUnboxedEntry++; } } else @@ -8060,6 +8265,7 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, INDEBUG(call->gtCallDebugFlags |= GTF_CALL_MD_UNBOXED); derivedMethod = unboxedEntryMethod; pDerivedResolvedToken = &dvInfo.resolvedTokenDevirtualizedUnboxedMethod; + Metrics.DevirtualizedCallUnboxedEntry++; } } } @@ -8453,13 +8659,11 @@ void Compiler::impCheckCanInline(GenTreeCall* call, CORINFO_METHOD_HANDLE ftn = pParam->fncHandle; InlineResult* const inlineResult = pParam->result; -#ifdef DEBUG if (JitConfig.JitNoInline()) { inlineResult->NoteFatal(InlineObservation::CALLEE_IS_JIT_NOINLINE); return; } -#endif JITDUMP("\nCheckCanInline: fetching method info for inline candidate %s -- context %p\n", compiler->eeGetMethodName(ftn), compiler->dspPtr(pParam->exactContextHnd)); @@ -8608,6 +8812,264 @@ void Compiler::impCheckCanInline(GenTreeCall* call, } } +//------------------------------------------------------------------------ +// impEstimateIntrinsic: Imports one of the *Estimate intrinsics which are +// explicitly allowed to differ in result based on the hardware they're running +// against +// +// Arguments: +// method - The handle of the method being imported +// callType - The underlying type for the call +// intrinsicName - The intrinsic being imported +// mustExpand - true if the intrinsic must return a GenTree*; otherwise, false +// +GenTree* Compiler::impEstimateIntrinsic(CORINFO_METHOD_HANDLE method, + CORINFO_SIG_INFO* sig, + CorInfoType callJitType, + NamedIntrinsic intrinsicName, + bool mustExpand) +{ + var_types callType = JITtype2varType(callJitType); + assert(varTypeIsFloating(callType)); + + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + return nullptr; + } + + if (IsIntrinsicImplementedByUserCall(intrinsicName)) + { + return nullptr; + } + +#if defined(FEATURE_HW_INTRINSICS) + // We use compExactlyDependsOn since these are estimate APIs where + // the behavior is explicitly allowed to differ across machines + + var_types simdType = TYP_UNKNOWN; + NamedIntrinsic intrinsicId = NI_Illegal; + bool swapOp1AndOp3 = false; + + switch (intrinsicName) + { + case NI_System_Math_MultiplyAddEstimate: + { + assert(sig->numArgs == 3); + +#if defined(TARGET_XARCH) + if (compExactlyDependsOn(InstructionSet_FMA)) + { + simdType = TYP_SIMD16; + intrinsicId = NI_FMA_MultiplyAddScalar; + } +#elif defined(TARGET_ARM64) + if (compExactlyDependsOn(InstructionSet_AdvSimd)) + { + simdType = TYP_SIMD8; + intrinsicId = NI_AdvSimd_FusedMultiplyAddScalar; + + // AdvSimd.FusedMultiplyAdd expects (addend, left, right), while the APIs take (left, right, addend) + + impSpillSideEffect(true, verCurrentState.esStackDepth - + 3 DEBUGARG("Spilling op1 side effects for MultiplyAddEstimate")); + + impSpillSideEffect(true, verCurrentState.esStackDepth - + 2 DEBUGARG("Spilling op2 side effects for MultiplyAddEstimate")); + + swapOp1AndOp3 = true; + } +#endif // TARGET_ARM64 + break; + } + + case NI_System_Math_ReciprocalEstimate: + { + assert(sig->numArgs == 1); + +#if defined(TARGET_XARCH) + if (compExactlyDependsOn(InstructionSet_AVX512F)) + { + simdType = TYP_SIMD16; + intrinsicId = NI_AVX512F_Reciprocal14Scalar; + } + else if ((callType == TYP_FLOAT) && compExactlyDependsOn(InstructionSet_SSE)) + { + if (!IsBaselineSimdIsaSupported()) + { + // While the actual intrinsic only requires SSE, the + // ToScalar intrinsic asserts that the BaselineSimdIsa + // (SSE2) is supported to help simplify the overall logic + // it has to maintain + assert(intrinsicId == NI_Illegal); + break; + } + + simdType = TYP_SIMD16; + intrinsicId = NI_SSE_ReciprocalScalar; + } +#elif defined(TARGET_ARM64) + if (compExactlyDependsOn(InstructionSet_AdvSimd_Arm64)) + { + simdType = TYP_SIMD8; + intrinsicId = NI_AdvSimd_Arm64_ReciprocalEstimateScalar; + } +#endif // TARGET_ARM64 + break; + } + + case NI_System_Math_ReciprocalSqrtEstimate: + { + assert(sig->numArgs == 1); + +#if defined(TARGET_XARCH) + if (compExactlyDependsOn(InstructionSet_AVX512F)) + { + simdType = TYP_SIMD16; + intrinsicId = NI_AVX512F_ReciprocalSqrt14Scalar; + } + else if ((callType == TYP_FLOAT) && compExactlyDependsOn(InstructionSet_SSE)) + { + if (!IsBaselineSimdIsaSupported()) + { + // While the actual intrinsic only requires SSE, the + // ToScalar intrinsic asserts that the BaselineSimdIsa + // (SSE2) is supported to help simplify the overall logic + // it has to maintain + assert(intrinsicId == NI_Illegal); + break; + } + + simdType = TYP_SIMD16; + intrinsicId = NI_SSE_ReciprocalSqrtScalar; + } +#elif defined(TARGET_ARM64) + if (compExactlyDependsOn(InstructionSet_AdvSimd_Arm64)) + { + simdType = TYP_SIMD8; + intrinsicId = NI_AdvSimd_Arm64_ReciprocalSquareRootEstimateScalar; + } +#endif // TARGET_ARM64 + break; + } + + default: + { + unreached(); + } + } +#endif // FEATURE_HW_INTRINSICS + + GenTree* op3 = nullptr; + GenTree* op2 = nullptr; + GenTree* op1 = nullptr; + + switch (sig->numArgs) + { + case 3: + { + op3 = impImplicitR4orR8Cast(impPopStack().val, callType); + FALLTHROUGH; + } + + case 2: + { + op2 = impImplicitR4orR8Cast(impPopStack().val, callType); + FALLTHROUGH; + } + + case 1: + { + op1 = impImplicitR4orR8Cast(impPopStack().val, callType); + break; + } + + default: + { + unreached(); + } + } + +#if defined(FEATURE_HW_INTRINSICS) + if (intrinsicId != NI_Illegal) + { + unsigned simdSize; + + if (simdType == TYP_SIMD8) + { + simdSize = 8; + } + else + { + assert(simdType == TYP_SIMD16); + simdSize = 16; + } + + switch (sig->numArgs) + { + case 3: + { + if (swapOp1AndOp3) + { + std::swap(op1, op3); + } + + op3 = gtNewSimdCreateScalarUnsafeNode(simdType, op3, callJitType, simdSize); + op2 = gtNewSimdCreateScalarUnsafeNode(simdType, op2, callJitType, simdSize); + op1 = gtNewSimdCreateScalarUnsafeNode(simdType, op1, callJitType, simdSize); + + op1 = gtNewSimdHWIntrinsicNode(simdType, op1, op2, op3, intrinsicId, callJitType, simdSize); + break; + } + + case 1: + { + assert(!swapOp1AndOp3); + op1 = gtNewSimdCreateScalarUnsafeNode(simdType, op1, callJitType, simdSize); + op1 = gtNewSimdHWIntrinsicNode(simdType, op1, intrinsicId, callJitType, simdSize); + break; + } + + default: + { + unreached(); + } + } + + return gtNewSimdToScalarNode(callType, op1, callJitType, simdSize); + } + + assert(!swapOp1AndOp3); +#endif // FEATURE_HW_INTRINSICS + + callType = genActualType(callType); + + switch (intrinsicName) + { + case NI_System_Math_MultiplyAddEstimate: + { + GenTree* mulNode = gtNewOperNode(GT_MUL, callType, op1, op2); + return gtNewOperNode(GT_ADD, callType, mulNode, op3); + } + + case NI_System_Math_ReciprocalEstimate: + case NI_System_Math_ReciprocalSqrtEstimate: + { + if (intrinsicName == NI_System_Math_ReciprocalSqrtEstimate) + { + assert(!IsIntrinsicImplementedByUserCall(NI_System_Math_Sqrt)); + op1 = new (this, GT_INTRINSIC) + GenTreeIntrinsic(genActualType(callType), op1, NI_System_Math_Sqrt, nullptr); + } + return gtNewOperNode(GT_DIV, genActualType(callType), gtNewDconNode(1.0, callType), op1); + } + + default: + { + unreached(); + } + } +} + GenTree* Compiler::impMathIntrinsic(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, var_types callType, @@ -8704,8 +9166,8 @@ GenTree* Compiler::impMinMaxIntrinsic(CORINFO_METHOD_HANDLE method, GenTreeDblCon* cnsNode = nullptr; GenTree* otherNode = nullptr; - GenTree* op2 = impStackTop().val; - GenTree* op1 = impStackTop(1).val; + GenTree* op2 = impImplicitR4orR8Cast(impStackTop().val, callType); + GenTree* op1 = impImplicitR4orR8Cast(impStackTop(1).val, callType); if (op2->IsCnsFltOrDbl()) { @@ -8973,7 +9435,7 @@ GenTree* Compiler::impMinMaxIntrinsic(CORINFO_METHOD_HANDLE method, retNode->AsHWIntrinsic()->Op(2) = op1; } - return gtNewSimdToScalarNode(callType, retNode, callJitType, 16); + return gtNewSimdToScalarNode(genActualType(callType), retNode, callJitType, 16); } } #endif // FEATURE_HW_INTRINSICS && TARGET_XARCH @@ -9138,7 +9600,7 @@ GenTree* Compiler::impMinMaxIntrinsic(CORINFO_METHOD_HANDLE method, callJitType, 16); } - return gtNewSimdToScalarNode(callType, tmp, callJitType, 16); + return gtNewSimdToScalarNode(genActualType(callType), tmp, callJitType, 16); } #endif // FEATURE_HW_INTRINSICS && TARGET_XARCH @@ -10061,6 +10523,19 @@ NamedIntrinsic Compiler::lookupPrimitiveFloatNamedIntrinsic(CORINFO_METHOD_HANDL { result = NI_System_Math_Ceiling; } + else if (strncmp(methodName, "ConvertToInteger", 16) == 0) + { + methodName += 16; + + if (methodName[0] == '\0') + { + result = NI_PRIMITIVE_ConvertToInteger; + } + else if (strcmp(methodName, "Native") == 0) + { + result = NI_PRIMITIVE_ConvertToIntegerNative; + } + } else if (strncmp(methodName, "Cos", 3) == 0) { methodName += 3; @@ -10190,6 +10665,10 @@ NamedIntrinsic Compiler::lookupPrimitiveFloatNamedIntrinsic(CORINFO_METHOD_HANDL result = NI_System_Math_MinNumber; } } + else if (strcmp(methodName, "MultiplyAddEstimate") == 0) + { + result = NI_System_Math_MultiplyAddEstimate; + } break; } @@ -10204,7 +10683,20 @@ NamedIntrinsic Compiler::lookupPrimitiveFloatNamedIntrinsic(CORINFO_METHOD_HANDL case 'R': { - if (strcmp(methodName, "Round") == 0) + if (strncmp(methodName, "Reciprocal", 10) == 0) + { + methodName += 10; + + if (strcmp(methodName, "Estimate") == 0) + { + result = NI_System_Math_ReciprocalEstimate; + } + else if (strcmp(methodName, "SqrtEstimate") == 0) + { + result = NI_System_Math_ReciprocalSqrtEstimate; + } + } + else if (strcmp(methodName, "Round") == 0) { result = NI_System_Math_Round; } diff --git a/src/coreclr/jit/indirectcalltransformer.cpp b/src/coreclr/jit/indirectcalltransformer.cpp index ae9335513c9e..7719319ba227 100644 --- a/src/coreclr/jit/indirectcalltransformer.cpp +++ b/src/coreclr/jit/indirectcalltransformer.cpp @@ -516,6 +516,12 @@ class IndirectCallTransformer (GetChecksCount() == 1) && ((origCall->gtCallMoreFlags & GTF_CALL_M_GUARDED_DEVIRT_EXACT) == 0); if (canChainGdv) { + compiler->Metrics.GDV++; + if (GetChecksCount() > 1) + { + compiler->Metrics.MultiGuessGDV++; + } + const bool isChainedGdv = (origCall->gtCallMoreFlags & GTF_CALL_M_GUARDED_DEVIRT_CHAIN) != 0; if (isChainedGdv) @@ -527,6 +533,7 @@ class IndirectCallTransformer if (isChainedGdv) { + compiler->Metrics.ChainedGDV++; TransformForChainedGdv(); } @@ -698,6 +705,7 @@ class IndirectCallTransformer GenTree* targetMethodTable = compiler->gtNewIconEmbClsHndNode(clsHnd); compare = compiler->gtNewOperNode(GT_NE, TYP_INT, targetMethodTable, methodTable); + compiler->Metrics.ClassGDV++; } else { @@ -732,6 +740,7 @@ class IndirectCallTransformer GenTree* compareTarTree = CreateTreeForLookup(methHnd, lookup); compare = compiler->gtNewOperNode(GT_NE, TYP_INT, compareTarTree, tarTree); } + compiler->Metrics.MethodGDV++; } GenTree* jmpTree = compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, compare); @@ -1059,7 +1068,7 @@ class IndirectCallTransformer // thenBlock = CreateAndInsertBasicBlock(BBJ_ALWAYS, checkBlock); thenBlock->CopyFlags(currBlock, BBF_SPLIT_GAINED); - thenBlock->inheritWeight(currBlock); + thenBlock->inheritWeight(checkBlock); thenBlock->scaleBBWeight(adjustedThenLikelihood); FlowEdge* const thenRemainderEdge = compiler->fgAddRefPred(remainderBlock, thenBlock); thenBlock->SetTargetEdge(thenRemainderEdge); @@ -1221,10 +1230,59 @@ class IndirectCallTransformer checkStmt = nextStmt; } - // Finally, rewire the cold block to jump to the else block, + // Rewire the cold block to jump to the else block, // not fall through to the check block. // compiler->fgRedirectTargetEdge(coldBlock, elseBlock); + + // Update the profile data + // + if (coldBlock->hasProfileWeight()) + { + // Check block + // + FlowEdge* const coldElseEdge = compiler->fgGetPredForBlock(elseBlock, coldBlock); + weight_t newCheckWeight = checkBlock->bbWeight - coldElseEdge->getLikelyWeight(); + + if (newCheckWeight < 0) + { + // If weights were consistent, we expect at worst a slight underflow. + // + if (compiler->fgPgoConsistent) + { + bool const isReasonableUnderflow = Compiler::fgProfileWeightsEqual(newCheckWeight, 0.0); + assert(isReasonableUnderflow); + + if (!isReasonableUnderflow) + { + JITDUMP("Profile data could not be locally repaired. Data %s inconsistent.\n", + compiler->fgPgoConsistent ? "is now" : "was already"); + + if (compiler->fgPgoConsistent) + { + compiler->Metrics.ProfileInconsistentChainedGDV++; + compiler->fgPgoConsistent = false; + } + } + } + + // No matter what, the minimum weight is zero + // + newCheckWeight = 0; + } + checkBlock->setBBProfileWeight(newCheckWeight); + + // Else block + // + FlowEdge* const checkElseEdge = compiler->fgGetPredForBlock(elseBlock, checkBlock); + weight_t const newElseWeight = checkElseEdge->getLikelyWeight() + coldElseEdge->getLikelyWeight(); + elseBlock->setBBProfileWeight(newElseWeight); + + // Then block + // + FlowEdge* const checkThenEdge = compiler->fgGetPredForBlock(thenBlock, checkBlock); + thenBlock->setBBProfileWeight(checkThenEdge->getLikelyWeight()); + } } // When the current candidate has sufficiently high likelihood, scan diff --git a/src/coreclr/jit/inductionvariableopts.cpp b/src/coreclr/jit/inductionvariableopts.cpp index a1ab0c58ecd9..019067f9d6e8 100644 --- a/src/coreclr/jit/inductionvariableopts.cpp +++ b/src/coreclr/jit/inductionvariableopts.cpp @@ -33,6 +33,287 @@ #include "jitpch.h" #include "scev.h" +// Data structure that keeps track of local occurrences inside loops. +class LoopLocalOccurrences +{ + struct Occurrence + { + BasicBlock* Block; + Statement* Statement; + GenTreeLclVarCommon* Node; + Occurrence* Next; + }; + + typedef JitHashTable, Occurrence*> LocalToOccurrenceMap; + + FlowGraphNaturalLoops* m_loops; + // For every loop, we track all occurrences exclusive to that loop. + // Occurrences in descendant loops are not kept in their ancestor's maps. + LocalToOccurrenceMap** m_maps; + // Blocks whose IR we have visited to find local occurrences in. + BitVec m_visitedBlocks; + + LocalToOccurrenceMap* GetOrCreateMap(FlowGraphNaturalLoop* loop); + + template + bool VisitLoopNestMaps(FlowGraphNaturalLoop* loop, TFunc& func); +public: + LoopLocalOccurrences(FlowGraphNaturalLoops* loops); + + template + bool VisitOccurrences(FlowGraphNaturalLoop* loop, unsigned lclNum, TFunc func); + + bool HasAnyOccurrences(FlowGraphNaturalLoop* loop, unsigned lclNum); + + template + bool VisitStatementsWithOccurrences(FlowGraphNaturalLoop* loop, unsigned lclNum, TFunc func); +}; + +LoopLocalOccurrences::LoopLocalOccurrences(FlowGraphNaturalLoops* loops) + : m_loops(loops) +{ + Compiler* comp = loops->GetDfsTree()->GetCompiler(); + m_maps = loops->NumLoops() == 0 ? nullptr : new (comp, CMK_LoopOpt) LocalToOccurrenceMap* [loops->NumLoops()] {}; + BitVecTraits poTraits = loops->GetDfsTree()->PostOrderTraits(); + m_visitedBlocks = BitVecOps::MakeEmpty(&poTraits); +} + +//------------------------------------------------------------------------------ +// LoopLocalOccurrences:GetOrCreateMap: +// Get or create the map of occurrences exclusive to a single loop. +// +// Parameters: +// loop - The loop +// +// Returns: +// Map of occurrences. +// +// Remarks: +// As a precondition occurrences of all descendant loops must already have +// been found. +// +LoopLocalOccurrences::LocalToOccurrenceMap* LoopLocalOccurrences::GetOrCreateMap(FlowGraphNaturalLoop* loop) +{ + LocalToOccurrenceMap* map = m_maps[loop->GetIndex()]; + if (map != nullptr) + { + return map; + } + + BitVecTraits poTraits = m_loops->GetDfsTree()->PostOrderTraits(); + +#ifdef DEBUG + // As an invariant the map contains only the locals exclusive to each loop + // (i.e. occurrences inside descendant loops are not contained in ancestor + // loop maps). Double check that we've already computed the child maps to + // make sure we do not visit descendant blocks below. + for (FlowGraphNaturalLoop* child = loop->GetChild(); child != nullptr; child = child->GetSibling()) + { + assert(BitVecOps::IsMember(&poTraits, m_visitedBlocks, child->GetHeader()->bbPostorderNum)); + } +#endif + + Compiler* comp = m_loops->GetDfsTree()->GetCompiler(); + map = new (comp, CMK_LoopOpt) LocalToOccurrenceMap(comp->getAllocator(CMK_LoopOpt)); + m_maps[loop->GetIndex()] = map; + + loop->VisitLoopBlocksReversePostOrder([=, &poTraits](BasicBlock* block) { + if (!BitVecOps::TryAddElemD(&poTraits, m_visitedBlocks, block->bbPostorderNum)) + { + return BasicBlockVisit::Continue; + } + + for (Statement* stmt : block->NonPhiStatements()) + { + for (GenTree* node : stmt->TreeList()) + { + if (!node->OperIsAnyLocal()) + { + continue; + } + + GenTreeLclVarCommon* lcl = node->AsLclVarCommon(); + Occurrence** occurrence = map->LookupPointerOrAdd(lcl->GetLclNum(), nullptr); + + Occurrence* newOccurrence = new (comp, CMK_LoopOpt) Occurrence; + newOccurrence->Block = block; + newOccurrence->Statement = stmt; + newOccurrence->Node = lcl; + newOccurrence->Next = *occurrence; + *occurrence = newOccurrence; + } + } + + return BasicBlockVisit::Continue; + }); + + return map; +} + +//------------------------------------------------------------------------------ +// LoopLocalOccurrences:VisitLoopNestMaps: +// Visit all occurrence maps of the specified loop nest. +// +// Type parameters: +// TFunc - bool(LocalToOccurrenceMap*) functor that returns true to continue +// the visit and false to abort. +// +// Parameters: +// loop - Root loop of the nest. +// func - Functor instance +// +// Returns: +// True if the visit completed; false if "func" returned false for any map. +// +template +bool LoopLocalOccurrences::VisitLoopNestMaps(FlowGraphNaturalLoop* loop, TFunc& func) +{ + for (FlowGraphNaturalLoop* child = loop->GetChild(); child != nullptr; child = child->GetSibling()) + { + if (!VisitLoopNestMaps(child, func)) + { + return false; + } + } + + return func(GetOrCreateMap(loop)); +} + +//------------------------------------------------------------------------------ +// LoopLocalOccurrences:VisitOccurrences: +// Visit all occurrences of the specified local inside the loop. +// +// Type parameters: +// TFunc - Functor of type bool(Block*, Statement*, GenTree*) +// +// Parameters: +// loop - The loop +// lclNum - The local whose occurrences to visit +// func - Functor instance. Return true to continue the visit, and +// false to abort it. +// +// Returns: +// True if the visit completed and false if it was aborted by the functor +// returning false. +// +template +bool LoopLocalOccurrences::VisitOccurrences(FlowGraphNaturalLoop* loop, unsigned lclNum, TFunc func) +{ + auto visitor = [=, &func](LocalToOccurrenceMap* map) { + Occurrence* occurrence; + if (!map->Lookup(lclNum, &occurrence)) + { + return true; + } + + assert(occurrence != nullptr); + + do + { + if (!func(occurrence->Block, occurrence->Statement, occurrence->Node)) + { + return false; + } + + occurrence = occurrence->Next; + } while (occurrence != nullptr); + + return true; + }; + + return VisitLoopNestMaps(loop, visitor); +} + +//------------------------------------------------------------------------------ +// LoopLocalOccurrences:HasAnyOccurrences: +// Check if this loop has any occurrences of the specified local. +// +// Parameters: +// loop - The loop +// lclNum - Local to check occurrences of +// +// Returns: +// True if it does. +// +// Remarks: +// Does not take promotion into account. +// +bool LoopLocalOccurrences::HasAnyOccurrences(FlowGraphNaturalLoop* loop, unsigned lclNum) +{ + if (!VisitOccurrences(loop, lclNum, [](BasicBlock* block, Statement* stmt, GenTree* tree) { + return false; + })) + { + return true; + } + + return false; +} + +//------------------------------------------------------------------------------ +// LoopLocalOccurrences:VisitStatementsWithOccurrences: +// Visit all statements with occurrences of the specified local inside +// the loop. +// +// Type parameters: +// TFunc - Functor of type bool(Block*, Statement*) +// +// Parameters: +// loop - The loop +// lclNum - The local whose occurrences to visit +// func - Functor instance. Return true to continue the visit, and +// false to abort it. +// +// Returns: +// True if the visit completed and false if it was aborted by the functor +// returning false. +// +// Remarks: +// A statement with multiple occurrences of the local is only visited +// once. +// +template +bool LoopLocalOccurrences::VisitStatementsWithOccurrences(FlowGraphNaturalLoop* loop, unsigned lclNum, TFunc func) +{ + auto visitor = [=, &func](LocalToOccurrenceMap* map) { + Occurrence* occurrence; + if (!map->Lookup(lclNum, &occurrence)) + { + return true; + } + + assert(occurrence != nullptr); + + while (true) + { + if (!func(occurrence->Block, occurrence->Statement)) + { + return false; + } + + Statement* curStmt = occurrence->Statement; + while (true) + { + occurrence = occurrence->Next; + + if (occurrence == nullptr) + { + return true; + } + + if (occurrence->Statement != curStmt) + { + break; + } + } + } + + return true; + }; + + return VisitLoopNestMaps(loop, visitor); +} + //------------------------------------------------------------------------ // optCanSinkWidenedIV: Check to see if we are able to sink a store to the old // local into the exits of a loop if we decide to widen. @@ -118,7 +399,7 @@ bool Compiler::optCanSinkWidenedIV(unsigned lclNum, FlowGraphNaturalLoop* loop) // initBlock - The block in where the new IV would be initialized // initedToConstant - Whether or not the new IV will be initialized to a constant // loop - The loop -// ivUses - Statements in which "lclNum" appears will be added to this list +// loopLocals - Data structure tracking local uses inside the loop // // // Returns: @@ -134,11 +415,11 @@ bool Compiler::optCanSinkWidenedIV(unsigned lclNum, FlowGraphNaturalLoop* loop) // 2. We need to store the wide IV back into the narrow one in each of // the exits where the narrow IV is live-in. // -bool Compiler::optIsIVWideningProfitable(unsigned lclNum, - BasicBlock* initBlock, - bool initedToConstant, - FlowGraphNaturalLoop* loop, - ArrayStack& ivUses) +bool Compiler::optIsIVWideningProfitable(unsigned lclNum, + BasicBlock* initBlock, + bool initedToConstant, + FlowGraphNaturalLoop* loop, + LoopLocalOccurrences* loopLocals) { for (FlowGraphNaturalLoop* otherLoop : m_loops->InReversePostOrder()) { @@ -168,58 +449,33 @@ bool Compiler::optIsIVWideningProfitable(unsigned lclNum, weight_t savedCost = 0; int savedSize = 0; - loop->VisitLoopBlocks([&](BasicBlock* block) { - for (Statement* stmt : block->NonPhiStatements()) + auto measure = [=, &savedCost, &savedSize](BasicBlock* block, Statement* stmt, GenTreeLclVarCommon* lcl) { + GenTree* parent = lcl->gtGetParent(nullptr); + if ((parent == nullptr) || !parent->OperIs(GT_CAST)) { - bool hasUse = false; - int numExtensions = 0; - for (GenTree* node : stmt->TreeList()) - { - if (!node->OperIs(GT_CAST)) - { - hasUse |= node->OperIsLocal() && (node->AsLclVarCommon()->GetLclNum() == lclNum); - continue; - } - - GenTreeCast* cast = node->AsCast(); - if ((cast->gtCastType != TYP_LONG) || !cast->IsUnsigned() || cast->gtOverflow()) - { - continue; - } - - GenTree* op = cast->CastOp(); - if (!op->OperIs(GT_LCL_VAR) || (op->AsLclVarCommon()->GetLclNum() != lclNum)) - { - continue; - } - - // If this is already the source of a store then it is going to be - // free in our backends regardless. - GenTree* parent = node->gtGetParent(nullptr); - if ((parent != nullptr) && parent->OperIs(GT_STORE_LCL_VAR)) - { - continue; - } - - numExtensions++; - } - - if (hasUse) - { - ivUses.Push(stmt); - } + return true; + } - if (numExtensions > 0) - { - JITDUMP(" Found %d zero extensions in " FMT_STMT "\n", numExtensions, stmt->GetID()); + GenTreeCast* cast = parent->AsCast(); + if ((cast->gtCastType != TYP_LONG) || !cast->IsUnsigned() || cast->gtOverflow()) + { + return true; + } - savedSize += numExtensions * ExtensionSize; - savedCost += numExtensions * block->getBBWeight(this) * ExtensionCost; - } + // If this is already the source of a store then it is going to be + // free in our backends regardless. + parent = cast->gtGetParent(nullptr); + if ((parent != nullptr) && parent->OperIs(GT_STORE_LCL_VAR)) + { + return true; } - return BasicBlockVisit::Continue; - }); + savedSize += ExtensionSize; + savedCost += block->getBBWeight(this) * ExtensionCost; + return true; + }; + + loopLocals->VisitOccurrences(loop, lclNum, measure); if (!initedToConstant) { @@ -450,6 +706,161 @@ void Compiler::optBestEffortReplaceNarrowIVUses( }); } +//------------------------------------------------------------------------ +// optWidenPrimaryIV: Attempt to widen a primary IV. +// +// Parameters: +// loop - The loop +// lclNum - The primary IV +// addRec - The add recurrence for the primary IV +// loopLocals - Data structure for locals occurrences +// +bool Compiler::optWidenPrimaryIV(FlowGraphNaturalLoop* loop, + unsigned lclNum, + ScevAddRec* addRec, + LoopLocalOccurrences* loopLocals) +{ + LclVarDsc* lclDsc = lvaGetDesc(lclNum); + if (lclDsc->TypeGet() != TYP_INT) + { + JITDUMP(" Type is %s, no widening to be done\n", varTypeName(lclDsc->TypeGet())); + return false; + } + + // If the IV is not enregisterable then uses/defs are going to go + // to stack regardless. This check also filters out IVs that may be + // live into exceptional exits since those are always marked DNER. + if (lclDsc->lvDoNotEnregister) + { + JITDUMP(" V%02u is marked DNER\n", lclNum); + return false; + } + + if (!optCanSinkWidenedIV(lclNum, loop)) + { + return false; + } + + // Now figure out where we are going to init the widened version of the IV. + // We prefer to put it in the same spot as the narrow IV was initialized. + // Find that now. + // Start value should always be an SSA use from outside the loop + // since we only widen primary IVs. + assert(addRec->Start->OperIs(ScevOper::Local)); + + ScevLocal* startLocal = (ScevLocal*)addRec->Start; + int64_t startConstant = 0; + bool initToConstant = startLocal->GetConstantValue(this, &startConstant); + LclSsaVarDsc* startSsaDsc = lclDsc->GetPerSsaData(startLocal->SsaNum); + + BasicBlock* preheader = loop->EntryEdge(0)->getSourceBlock(); + BasicBlock* initBlock = preheader; + if ((startSsaDsc->GetBlock() != nullptr) && (startSsaDsc->GetDefNode() != nullptr)) + { + initBlock = startSsaDsc->GetBlock(); + } + + if (!optIsIVWideningProfitable(lclNum, initBlock, initToConstant, loop, loopLocals)) + { + return false; + } + + Statement* insertInitAfter = nullptr; + if (initBlock != preheader) + { + GenTree* narrowInitRoot = startSsaDsc->GetDefNode(); + while (true) + { + GenTree* parent = narrowInitRoot->gtGetParent(nullptr); + if (parent == nullptr) + break; + + narrowInitRoot = parent; + } + + for (Statement* stmt : initBlock->Statements()) + { + if (stmt->GetRootNode() == narrowInitRoot) + { + insertInitAfter = stmt; + break; + } + } + + assert(insertInitAfter != nullptr); + + if (insertInitAfter->IsPhiDefnStmt()) + { + while ((insertInitAfter->GetNextStmt() != nullptr) && insertInitAfter->GetNextStmt()->IsPhiDefnStmt()) + { + insertInitAfter = insertInitAfter->GetNextStmt(); + } + } + } + + Statement* initStmt = nullptr; + unsigned newLclNum = lvaGrabTemp(false DEBUGARG(printfAlloc("Widened IV V%02u", lclNum))); + INDEBUG(lclDsc = nullptr); + assert(startLocal->LclNum == lclNum); + + if (initBlock != preheader) + { + JITDUMP("Adding initialization of new widened local to same block as reaching def outside loop, " FMT_BB "\n", + initBlock->bbNum); + } + else + { + JITDUMP("Adding initialization of new widened local to preheader " FMT_BB "\n", initBlock->bbNum); + } + + GenTree* initVal; + if (initToConstant) + { + initVal = gtNewIconNode((int64_t)(uint32_t)startConstant, TYP_LONG); + } + else + { + initVal = gtNewCastNode(TYP_LONG, gtNewLclvNode(lclNum, TYP_INT), true, TYP_LONG); + } + + GenTree* widenStore = gtNewTempStore(newLclNum, initVal); + initStmt = fgNewStmtFromTree(widenStore); + if (insertInitAfter != nullptr) + { + fgInsertStmtAfter(initBlock, insertInitAfter, initStmt); + } + else + { + fgInsertStmtNearEnd(initBlock, initStmt); + } + + DISPSTMT(initStmt); + JITDUMP("\n"); + + JITDUMP(" Replacing uses of V%02u with widened version V%02u\n", lclNum, newLclNum); + + if (initStmt != nullptr) + { + JITDUMP(" Replacing on the way to the loop\n"); + optBestEffortReplaceNarrowIVUses(lclNum, startLocal->SsaNum, newLclNum, initBlock, initStmt->GetNextStmt()); + } + + JITDUMP(" Replacing inside the loop\n"); + + auto replace = [this, lclNum, newLclNum](BasicBlock* block, Statement* stmt) { + JITDUMP("Replacing V%02u -> V%02u in [%06u]\n", lclNum, newLclNum, dspTreeID(stmt->GetRootNode())); + DISPSTMT(stmt); + JITDUMP("\n"); + optReplaceWidenedIV(lclNum, SsaConfig::RESERVED_SSA_NUM, newLclNum, stmt); + return true; + }; + + loopLocals->VisitStatementsWithOccurrences(loop, lclNum, replace); + + optSinkWidenedIV(lclNum, newLclNum, loop); + return true; +} + //------------------------------------------------------------------------ // optInductionVariables: Try and optimize induction variables in the method. // @@ -485,9 +896,11 @@ PhaseStatus Compiler::optInductionVariables() m_dfsTree = fgComputeDfs(); m_loops = FlowGraphNaturalLoops::Find(m_dfsTree); + LoopLocalOccurrences loopLocals(m_loops); + ScalarEvolutionContext scevContext(this); - JITDUMP("Widening primary induction variables:\n"); - ArrayStack ivUses(getAllocator(CMK_LoopIVOpts)); + JITDUMP("Optimizing induction variables:\n"); + for (FlowGraphNaturalLoop* loop : m_loops->InReversePostOrder()) { JITDUMP("Processing "); @@ -504,26 +917,8 @@ PhaseStatus Compiler::optInductionVariables() } JITDUMP("\n"); - DISPSTMT(stmt); - GenTreeLclVarCommon* lcl = stmt->GetRootNode()->AsLclVarCommon(); - LclVarDsc* lclDsc = lvaGetDesc(lcl); - if (lclDsc->TypeGet() != TYP_INT) - { - JITDUMP(" Type is %s, no widening to be done\n", varTypeName(lclDsc->TypeGet())); - continue; - } - - // If the IV is not enregisterable then uses/defs are going to go - // to stack regardless. This check also filters out IVs that may be - // live into exceptional exits since those are always marked DNER. - if (lclDsc->lvDoNotEnregister) - { - JITDUMP(" V%02u is marked DNER\n", lcl->GetLclNum()); - continue; - } - Scev* scev = scevContext.Analyze(loop->GetHeader(), stmt->GetRootNode()); if (scev == nullptr) { @@ -531,7 +926,6 @@ PhaseStatus Compiler::optInductionVariables() continue; } - scev = scevContext.Simplify(scev); JITDUMP(" => "); DBEXEC(verbose, scev->Dump(this)); JITDUMP("\n"); @@ -543,133 +937,26 @@ PhaseStatus Compiler::optInductionVariables() ScevAddRec* addRec = (ScevAddRec*)scev; - JITDUMP(" V%02u is a primary induction variable in " FMT_LP "\n", lcl->GetLclNum(), loop->GetIndex()); + unsigned lclNum = stmt->GetRootNode()->AsLclVarCommon()->GetLclNum(); + LclVarDsc* lclDsc = lvaGetDesc(lclNum); + JITDUMP(" V%02u is a primary induction variable in " FMT_LP "\n", lclNum, loop->GetIndex()); - if (!optCanSinkWidenedIV(lcl->GetLclNum(), loop)) - { - continue; - } + assert(!lclDsc->lvPromoted); - // Start value should always be an SSA use from outside the loop - // since we only widen primary IVs. - assert(addRec->Start->OperIs(ScevOper::Local)); - ScevLocal* startLocal = (ScevLocal*)addRec->Start; - int64_t startConstant = 0; - bool initToConstant = startLocal->GetConstantValue(this, &startConstant); - LclSsaVarDsc* startSsaDsc = lclDsc->GetPerSsaData(startLocal->SsaNum); - - BasicBlock* preheader = loop->EntryEdge(0)->getSourceBlock(); - BasicBlock* initBlock = preheader; - if ((startSsaDsc->GetBlock() != nullptr) && (startSsaDsc->GetDefNode() != nullptr)) - { - initBlock = startSsaDsc->GetBlock(); - } - - ivUses.Reset(); - if (!optIsIVWideningProfitable(lcl->GetLclNum(), initBlock, initToConstant, loop, ivUses)) + // For a struct field with occurrences of the parent local we won't + // be able to do much. + if (lclDsc->lvIsStructField && loopLocals.HasAnyOccurrences(loop, lclDsc->lvParentLcl)) { + JITDUMP(" V%02u is a struct field whose parent local V%02u has occurrences inside the loop\n", lclNum, + lclDsc->lvParentLcl); continue; } - changed = true; - - Statement* insertInitAfter = nullptr; - if (initBlock != preheader) + if (optWidenPrimaryIV(loop, lclNum, addRec, &loopLocals)) { - GenTree* narrowInitRoot = startSsaDsc->GetDefNode(); - while (true) - { - GenTree* parent = narrowInitRoot->gtGetParent(nullptr); - if (parent == nullptr) - break; - - narrowInitRoot = parent; - } - - for (Statement* stmt : initBlock->Statements()) - { - if (stmt->GetRootNode() == narrowInitRoot) - { - insertInitAfter = stmt; - break; - } - } - - assert(insertInitAfter != nullptr); - - if (insertInitAfter->IsPhiDefnStmt()) - { - while ((insertInitAfter->GetNextStmt() != nullptr) && - insertInitAfter->GetNextStmt()->IsPhiDefnStmt()) - { - insertInitAfter = insertInitAfter->GetNextStmt(); - } - } - } - - Statement* initStmt = nullptr; - unsigned newLclNum = lvaGrabTemp(false DEBUGARG(printfAlloc("Widened IV V%02u", lcl->GetLclNum()))); - INDEBUG(lclDsc = nullptr); - assert(startLocal->LclNum == lcl->GetLclNum()); - - if (initBlock != preheader) - { - JITDUMP("Adding initialization of new widened local to same block as reaching def outside loop, " FMT_BB - "\n", - initBlock->bbNum); - } - else - { - JITDUMP("Adding initialization of new widened local to preheader " FMT_BB "\n", initBlock->bbNum); - } - - GenTree* initVal; - if (initToConstant) - { - initVal = gtNewIconNode((int64_t)(uint32_t)startConstant, TYP_LONG); - } - else - { - initVal = gtNewCastNode(TYP_LONG, gtNewLclvNode(lcl->GetLclNum(), TYP_INT), true, TYP_LONG); - } - - GenTree* widenStore = gtNewTempStore(newLclNum, initVal); - initStmt = fgNewStmtFromTree(widenStore); - if (insertInitAfter != nullptr) - { - fgInsertStmtAfter(initBlock, insertInitAfter, initStmt); - } - else - { - fgInsertStmtNearEnd(initBlock, initStmt); + numWidened++; + changed = true; } - - DISPSTMT(initStmt); - JITDUMP("\n"); - - JITDUMP(" Replacing uses of V%02u with widened version V%02u\n", lcl->GetLclNum(), newLclNum); - - if (initStmt != nullptr) - { - JITDUMP(" Replacing on the way to the loop\n"); - optBestEffortReplaceNarrowIVUses(lcl->GetLclNum(), startLocal->SsaNum, newLclNum, initBlock, - initStmt->GetNextStmt()); - } - - JITDUMP(" Replacing in the loop; %d statements with appearances\n", ivUses.Height()); - for (int i = 0; i < ivUses.Height(); i++) - { - Statement* stmt = ivUses.Bottom(i); - JITDUMP("Replacing V%02u -> V%02u in [%06u]\n", lcl->GetLclNum(), newLclNum, - dspTreeID(stmt->GetRootNode())); - DISPSTMT(stmt); - JITDUMP("\n"); - optReplaceWidenedIV(lcl->GetLclNum(), SsaConfig::RESERVED_SSA_NUM, newLclNum, stmt); - } - - optSinkWidenedIV(lcl->GetLclNum(), newLclNum, loop); - - numWidened++; } Metrics.WidenedIVs += numWidened; diff --git a/src/coreclr/jit/inline.cpp b/src/coreclr/jit/inline.cpp index c8831a75b39b..bebd5622d3f8 100644 --- a/src/coreclr/jit/inline.cpp +++ b/src/coreclr/jit/inline.cpp @@ -1519,8 +1519,8 @@ void InlineStrategy::DumpDataContents(FILE* file) mdMethodDef currentMethodToken = info.compCompHnd->getMethodDefFromMethod(info.compMethodHnd); // Convert time spent jitting into microseconds - unsigned microsecondsSpentJitting = 0; - unsigned __int64 compCycles = m_Compiler->getInlineCycleCount(); + unsigned microsecondsSpentJitting = 0; + uint64_t compCycles = m_Compiler->getInlineCycleCount(); if (compCycles > 0) { double countsPerSec = CachedCyclesPerSecond(); @@ -1613,8 +1613,8 @@ void InlineStrategy::DumpXml(FILE* file, unsigned indent) unsigned hash = info.compMethodHash(); // Convert time spent jitting into microseconds - unsigned microsecondsSpentJitting = 0; - unsigned __int64 compCycles = m_Compiler->getInlineCycleCount(); + unsigned microsecondsSpentJitting = 0; + uint64_t compCycles = m_Compiler->getInlineCycleCount(); if (compCycles > 0) { double countsPerSec = CachedCyclesPerSecond(); diff --git a/src/coreclr/jit/inline.h b/src/coreclr/jit/inline.h index 8c1cb56124ad..a2aeba6fed72 100644 --- a/src/coreclr/jit/inline.h +++ b/src/coreclr/jit/inline.h @@ -993,6 +993,12 @@ class InlineStrategy m_ImportCount++; } + // Return number of import attempts + unsigned GetImportCount() const + { + return m_ImportCount; + } + // Inform strategy about the inline decision for a prejit root void NotePrejitDecision(const InlineResult& r) { diff --git a/src/coreclr/jit/instr.cpp b/src/coreclr/jit/instr.cpp index 79aae2c33454..4799b8b33349 100644 --- a/src/coreclr/jit/instr.cpp +++ b/src/coreclr/jit/instr.cpp @@ -1143,27 +1143,36 @@ void CodeGen::inst_RV_RV_IV(instruction ins, emitAttr size, regNumber reg1, regN // and that returns a value in register // // Arguments: -// ins -- The instruction being emitted -// attr -- The emit attribute -// reg1 -- The first operand, a register -// rmOp -- The second operand, which may be a memory node or a node producing a register -// ival -- The immediate operand +// ins -- The instruction being emitted +// attr -- The emit attribute +// reg1 -- The first operand, a register +// rmOp -- The second operand, which may be a memory node or a node producing a register +// ival -- The immediate operand +// instOptions -- The options that modify how the instruction is generated // -void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenTree* rmOp, int ival) +void CodeGen::inst_RV_TT_IV( + instruction ins, emitAttr attr, regNumber reg1, GenTree* rmOp, int ival, insOpts instOptions) { emitter* emit = GetEmitter(); noway_assert(emit->emitVerifyEncodable(ins, EA_SIZE(attr), reg1)); +#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) + if (CodeGenInterface::IsEmbeddedBroadcastEnabled(ins, rmOp)) + { + instOptions = AddEmbBroadcastMode(instOptions); + } +#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS + OperandDesc rmOpDesc = genOperandDesc(rmOp); switch (rmOpDesc.GetKind()) { case OperandKind::ClsVar: - emit->emitIns_R_C_I(ins, attr, reg1, rmOpDesc.GetFieldHnd(), 0, ival); + emit->emitIns_R_C_I(ins, attr, reg1, rmOpDesc.GetFieldHnd(), 0, ival, instOptions); break; case OperandKind::Local: - emit->emitIns_R_S_I(ins, attr, reg1, rmOpDesc.GetVarNum(), rmOpDesc.GetLclOffset(), ival); + emit->emitIns_R_S_I(ins, attr, reg1, rmOpDesc.GetVarNum(), rmOpDesc.GetLclOffset(), ival, instOptions); break; case OperandKind::Indir: @@ -1172,12 +1181,12 @@ void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenT // temporary GT_IND to generate code with. GenTreeIndir indirForm; GenTreeIndir* indir = rmOpDesc.GetIndirForm(&indirForm); - emit->emitIns_R_A_I(ins, attr, reg1, indir, ival); + emit->emitIns_R_A_I(ins, attr, reg1, indir, ival, instOptions); } break; case OperandKind::Reg: - emit->emitIns_SIMD_R_R_I(ins, attr, reg1, rmOpDesc.GetReg(), ival); + emit->emitIns_SIMD_R_R_I(ins, attr, reg1, rmOpDesc.GetReg(), ival, instOptions); break; default: @@ -1224,7 +1233,7 @@ bool CodeGenInterface::IsEmbeddedBroadcastEnabled(instruction ins, GenTree* op) // Return Value: // The modified insOpts // -static insOpts AddEmbBroadcastMode(insOpts instOptions) +insOpts CodeGen::AddEmbBroadcastMode(insOpts instOptions) { assert((instOptions & INS_OPTS_EVEX_b_MASK) == 0); unsigned result = static_cast(instOptions); @@ -1289,7 +1298,7 @@ void CodeGen::inst_RV_RV_TT(instruction ins, } } } -#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS +#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS OperandDesc op2Desc = genOperandDesc(op2); @@ -1347,16 +1356,23 @@ void CodeGen::inst_RV_RV_TT(instruction ins, // and an immediate value. The result is returned in register // // Arguments: -// ins -- The instruction being emitted -// size -- The emit size attribute -// targetReg -- The target register -// op1Reg -- The first operand register -// op2 -- The second operand, which may be a memory node or a node producing a register -// ival -- The immediate operand -// isRMW -- true if the instruction is RMW; otherwise, false +// ins -- The instruction being emitted +// size -- The emit size attribute +// targetReg -- The target register +// op1Reg -- The first operand register +// op2 -- The second operand, which may be a memory node or a node producing a register +// ival -- The immediate operand +// isRMW -- true if the instruction is RMW; otherwise, false +// instOptions -- The options that modify how the instruction is generated // -void CodeGen::inst_RV_RV_TT_IV( - instruction ins, emitAttr size, regNumber targetReg, regNumber op1Reg, GenTree* op2, int8_t ival, bool isRMW) +void CodeGen::inst_RV_RV_TT_IV(instruction ins, + emitAttr size, + regNumber targetReg, + regNumber op1Reg, + GenTree* op2, + int8_t ival, + bool isRMW, + insOpts instOptions) { emitter* emit = GetEmitter(); noway_assert(emit->emitVerifyEncodable(ins, EA_SIZE(size), op1Reg)); @@ -1364,15 +1380,24 @@ void CodeGen::inst_RV_RV_TT_IV( // TODO-XArch-CQ: Commutative operations can have op1 be contained // TODO-XArch-CQ: Non-VEX encoded instructions can have both ops contained +#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) + if (CodeGenInterface::IsEmbeddedBroadcastEnabled(ins, op2)) + { + instOptions = AddEmbBroadcastMode(instOptions); + } +#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS + OperandDesc op2Desc = genOperandDesc(op2); + switch (op2Desc.GetKind()) { case OperandKind::ClsVar: - emit->emitIns_SIMD_R_R_C_I(ins, size, targetReg, op1Reg, op2Desc.GetFieldHnd(), 0, ival); + emit->emitIns_SIMD_R_R_C_I(ins, size, targetReg, op1Reg, op2Desc.GetFieldHnd(), 0, ival, instOptions); break; case OperandKind::Local: - emit->emitIns_SIMD_R_R_S_I(ins, size, targetReg, op1Reg, op2Desc.GetVarNum(), op2Desc.GetLclOffset(), ival); + emit->emitIns_SIMD_R_R_S_I(ins, size, targetReg, op1Reg, op2Desc.GetVarNum(), op2Desc.GetLclOffset(), ival, + instOptions); break; case OperandKind::Indir: @@ -1381,7 +1406,7 @@ void CodeGen::inst_RV_RV_TT_IV( // temporary GT_IND to generate code with. GenTreeIndir indirForm; GenTreeIndir* indir = op2Desc.GetIndirForm(&indirForm); - emit->emitIns_SIMD_R_R_A_I(ins, size, targetReg, op1Reg, indir, ival); + emit->emitIns_SIMD_R_R_A_I(ins, size, targetReg, op1Reg, indir, ival, instOptions); } break; @@ -1402,7 +1427,7 @@ void CodeGen::inst_RV_RV_TT_IV( op1Reg = targetReg; } - emit->emitIns_SIMD_R_R_R_I(ins, size, targetReg, op1Reg, op2Reg, ival); + emit->emitIns_SIMD_R_R_R_I(ins, size, targetReg, op1Reg, op2Reg, ival, instOptions); } break; @@ -1936,7 +1961,6 @@ instruction CodeGen::ins_Copy(var_types dstType) #if defined(TARGET_XARCH) return INS_kmovq_msk; #elif defined(TARGET_ARM64) - unreached(); // TODO-SVE: This needs testing return INS_sve_mov; #endif } diff --git a/src/coreclr/jit/instr.h b/src/coreclr/jit/instr.h index d9684e8f96e6..2d094f350f06 100644 --- a/src/coreclr/jit/instr.h +++ b/src/coreclr/jit/instr.h @@ -235,7 +235,7 @@ enum insOpts: unsigned INS_OPTS_EVEX_er_rz = 3, // Round towards zero - // Two-bits: 0b0001_1100 + // Three-bits: 0b0001_1100 INS_OPTS_EVEX_aaa_MASK = 0x1C, // mask for EVEX.aaa related features INS_OPTS_EVEX_em_k1 = 1 << 2, // Embedded mask uses K1 @@ -255,7 +255,7 @@ enum insOpts: unsigned // One-bit: 0b0010_0000 INS_OPTS_EVEX_z_MASK = 0x20, // mask for EVEX.z related features - INS_OPTS_EVEX_em_zero, // Embedded mask merges with zero + INS_OPTS_EVEX_em_zero = 1 << 5, // Embedded mask merges with zero }; #elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) diff --git a/src/coreclr/jit/instrsarm64sve.h b/src/coreclr/jit/instrsarm64sve.h index fb469c0bfdc1..e29899d981b6 100644 --- a/src/coreclr/jit/instrsarm64sve.h +++ b/src/coreclr/jit/instrsarm64sve.h @@ -239,10 +239,10 @@ INST7(ld1sw, "ld1sw", 0, IF_SV // LD1SW {.D }, /Z, [, .D] SVE_IU_4B_B 11000101010mmmmm 100gggnnnnnttttt C540 8000 // LD1SW {.D }, /Z, [.D{, #}] SVE_IV_3A 11000101001iiiii 100gggnnnnnttttt C520 8000 -// enum name info SVE_AE_3A SVE_BD_3A SVE_EE_1A SVE_FD_3A SVE_FD_3B SVE_FD_3C +// enum name info SVE_AA_3A SVE_AT_3A SVE_EE_1A SVE_FD_3A SVE_FD_3B SVE_FD_3C INST6(mul, "mul", 0, IF_SVE_6A, 0x04100000, 0x04206000, 0x2530C000, 0x4420F800, 0x44A0F800, 0x44E0F800 ) - // MUL ., /M, ., . SVE_AE_3A 00000100xx010000 000gggmmmmmddddd 0410 0000 - // MUL ., ., . SVE_BD_3A 00000100xx1mmmmm 011000nnnnnddddd 0420 6000 + // MUL ., /M, ., . SVE_AA_3A 00000100xx010000 000gggmmmmmddddd 0410 0000 + // MUL ., ., . SVE_AT_3A 00000100xx1mmmmm 011000nnnnnddddd 0420 6000 // MUL ., ., # SVE_EE_1A 00100101xx110000 110iiiiiiiiddddd 2530 C000 // MUL .H, .H, .H[] SVE_FD_3A 010001000i1iimmm 111110nnnnnddddd 4420 F800 // MUL .S, .S, .S[] SVE_FD_3B 01000100101iimmm 111110nnnnnddddd 44A0 F800 @@ -341,34 +341,34 @@ INST6(st1b, "st1b", 0, IF_SV // ST1B {.}, , [{, #, MUL VL}] SVE_JN_3A 111001000xx0iiii 111gggnnnnnttttt E400 E000 -// enum name info SVE_AM_2A SVE_AN_3A SVE_AO_3A SVE_BF_2A SVE_BG_3A +// enum name info SVE_AM_2A SVE_AA_3A SVE_AO_3A SVE_BF_2A SVE_BG_3A INST5(asr, "asr", RSH, IF_SVE_5A, 0x04008000, 0x04108000, 0x04188000, 0x04209000, 0x04208000 ) // ASR ., /M, ., # SVE_AM_2A 00000100xx000000 100gggxxiiiddddd 0400 8000 - // ASR ., /M, ., . SVE_AN_3A 00000100xx010000 100gggmmmmmddddd 0410 8000 + // ASR ., /M, ., . SVE_AA_3A 00000100xx010000 100gggmmmmmddddd 0410 8000 // ASR ., /M, ., .D SVE_AO_3A 00000100xx011000 100gggmmmmmddddd 0418 8000 // ASR ., ., # SVE_BF_2A 00000100xx1xxiii 100100nnnnnddddd 0420 9000 // ASR ., ., .D SVE_BG_3A 00000100xx1mmmmm 100000nnnnnddddd 0420 8000 INST5(lsl, "lsl", 0, IF_SVE_5A, 0x04038000, 0x04138000, 0x041B8000, 0x04209C00, 0x04208C00 ) // LSL ., /M, ., # SVE_AM_2A 00000100xx000011 100gggxxiiiddddd 0403 8000 - // LSL ., /M, ., . SVE_AN_3A 00000100xx010011 100gggmmmmmddddd 0413 8000 + // LSL ., /M, ., . SVE_AA_3A 00000100xx010011 100gggmmmmmddddd 0413 8000 // LSL ., /M, ., .D SVE_AO_3A 00000100xx011011 100gggmmmmmddddd 041B 8000 // LSL ., ., # SVE_BF_2A 00000100xx1xxiii 100111nnnnnddddd 0420 9C00 // LSL ., ., .D SVE_BG_3A 00000100xx1mmmmm 100011nnnnnddddd 0420 8C00 INST5(lsr, "lsr", RSH, IF_SVE_5A, 0x04018000, 0x04118000, 0x04198000, 0x04209400, 0x04208400 ) // LSR ., /M, ., # SVE_AM_2A 00000100xx000001 100gggxxiiiddddd 0401 8000 - // LSR ., /M, ., . SVE_AN_3A 00000100xx010001 100gggmmmmmddddd 0411 8000 + // LSR ., /M, ., . SVE_AA_3A 00000100xx010001 100gggmmmmmddddd 0411 8000 // LSR ., /M, ., .D SVE_AO_3A 00000100xx011001 100gggmmmmmddddd 0419 8000 // LSR ., ., # SVE_BF_2A 00000100xx1xxiii 100101nnnnnddddd 0420 9400 // LSR ., ., .D SVE_BG_3A 00000100xx1mmmmm 100001nnnnnddddd 0420 8400 -// enum name info SVE_GX_3A SVE_GX_3B SVE_HK_3A SVE_HL_3A SVE_HM_2A +// enum name info SVE_GX_3A SVE_GX_3B SVE_AT_3A SVE_HL_3A SVE_HM_2A INST5(fmul, "fmul", 0, IF_SVE_5B, 0x64A02000, 0x64E02000, 0x65000800, 0x65028000, 0x651A8000 ) // FMUL .S, .S, .S[] SVE_GX_3A 01100100101iimmm 001000nnnnnddddd 64A0 2000 // FMUL .D, .D, .D[] SVE_GX_3B 01100100111immmm 001000nnnnnddddd 64E0 2000 - // FMUL ., ., . SVE_HK_3A 01100101xx0mmmmm 000010nnnnnddddd 6500 0800 + // FMUL ., ., . SVE_AT_3A 01100101xx0mmmmm 000010nnnnnddddd 6500 0800 // FMUL ., /M, ., . SVE_HL_3A 01100101xx000010 100gggmmmmmddddd 6502 8000 // FMUL ., /M, ., SVE_HM_2A 01100101xx011010 100ggg0000iddddd 651A 8000 @@ -443,15 +443,15 @@ INST4(fmov, "fmov", 0, IF_SV -// enum name info SVE_BE_3A SVE_FI_3A SVE_FI_3B SVE_FI_3C +// enum name info SVE_AT_3A SVE_FI_3A SVE_FI_3B SVE_FI_3C INST4(sqdmulh, "sqdmulh", 0, IF_SVE_4E, 0x04207000, 0x4420F000, 0x44A0F000, 0x44E0F000 ) - // SQDMULH ., ., . SVE_BE_3A 00000100xx1mmmmm 011100nnnnnddddd 0420 7000 + // SQDMULH ., ., . SVE_AT_3A 00000100xx1mmmmm 011100nnnnnddddd 0420 7000 // SQDMULH .H, .H, .H[] SVE_FI_3A 010001000i1iimmm 111100nnnnnddddd 4420 F000 // SQDMULH .S, .S, .S[] SVE_FI_3B 01000100101iimmm 111100nnnnnddddd 44A0 F000 // SQDMULH .D, .D, .D[] SVE_FI_3C 01000100111immmm 111100nnnnnddddd 44E0 F000 INST4(sqrdmulh, "sqrdmulh", 0, IF_SVE_4E, 0x04207400, 0x4420F400, 0x44A0F400, 0x44E0F400 ) - // SQRDMULH ., ., . SVE_BE_3A 00000100xx1mmmmm 011101nnnnnddddd 0420 7400 + // SQRDMULH ., ., . SVE_AT_3A 00000100xx1mmmmm 011101nnnnnddddd 0420 7400 // SQRDMULH .H, .H, .H[] SVE_FI_3A 010001000i1iimmm 111101nnnnnddddd 4420 F400 // SQRDMULH .S, .S, .S[] SVE_FI_3B 01000100101iimmm 111101nnnnnddddd 44A0 F400 // SQRDMULH .D, .D, .D[] SVE_FI_3C 01000100111immmm 111101nnnnnddddd 44E0 F400 @@ -555,14 +555,14 @@ INST4(stnt1w, "stnt1w", 0, IF_SV // STNT1W {.S }, , [{, #, MUL VL}] SVE_JM_3A 111001010001iiii 111gggnnnnnttttt E510 E000 -// enum name info SVE_AB_3A SVE_AT_3A SVE_EC_1A +// enum name info SVE_AA_3A SVE_AT_3A SVE_EC_1A INST3(add, "add", 0, IF_SVE_3A, 0x04000000, 0x04200000, 0x2520C000 ) - // ADD ., /M, ., . SVE_AB_3A 00000100xx000000 000gggmmmmmddddd 0400 0000 + // ADD ., /M, ., . SVE_AA_3A 00000100xx000000 000gggmmmmmddddd 0400 0000 // ADD ., ., . SVE_AT_3A 00000100xx1mmmmm 000000nnnnnddddd 0420 0000 // ADD ., ., #{, } SVE_EC_1A 00100101xx100000 11hiiiiiiiiddddd 2520 C000 INST3(sub, "sub", 0, IF_SVE_3A, 0x04010000, 0x04200400, 0x2521C000 ) - // SUB ., /M, ., . SVE_AB_3A 00000100xx000001 000gggmmmmmddddd 0401 0000 + // SUB ., /M, ., . SVE_AA_3A 00000100xx000001 000gggmmmmmddddd 0401 0000 // SUB ., ., . SVE_AT_3A 00000100xx1mmmmm 000001nnnnnddddd 0420 0400 // SUB ., ., #{, } SVE_EC_1A 00100101xx100001 11hiiiiiiiiddddd 2521 C000 @@ -581,58 +581,58 @@ INST3(dup, "dup", 0, IF_SV // DUP ., #{, } SVE_EB_1A 00100101xx111000 11hiiiiiiiiddddd 2538 C000 -// enum name info SVE_BR_3A SVE_BR_3B SVE_CI_3A +// enum name info SVE_AT_3A SVE_BR_3B SVE_CI_3A INST3(trn1, "trn1", 0, IF_SVE_3D, 0x05207000, 0x05A01800, 0x05205000 ) - // TRN1 ., ., . SVE_BR_3A 00000101xx1mmmmm 011100nnnnnddddd 0520 7000 + // TRN1 ., ., . SVE_AT_3A 00000101xx1mmmmm 011100nnnnnddddd 0520 7000 // TRN1 .Q, .Q, .Q SVE_BR_3B 00000101101mmmmm 000110nnnnnddddd 05A0 1800 // TRN1 ., ., . SVE_CI_3A 00000101xx10MMMM 0101000NNNN0DDDD 0520 5000 INST3(trn2, "trn2", 0, IF_SVE_3D, 0x05207400, 0x05A01C00, 0x05205400 ) - // TRN2 ., ., . SVE_BR_3A 00000101xx1mmmmm 011101nnnnnddddd 0520 7400 + // TRN2 ., ., . SVE_AT_3A 00000101xx1mmmmm 011101nnnnnddddd 0520 7400 // TRN2 .Q, .Q, .Q SVE_BR_3B 00000101101mmmmm 000111nnnnnddddd 05A0 1C00 // TRN2 ., ., . SVE_CI_3A 00000101xx10MMMM 0101010NNNN0DDDD 0520 5400 INST3(uzp1, "uzp1", 0, IF_SVE_3D, 0x05206800, 0x05A00800, 0x05204800 ) - // UZP1 ., ., . SVE_BR_3A 00000101xx1mmmmm 011010nnnnnddddd 0520 6800 + // UZP1 ., ., . SVE_AT_3A 00000101xx1mmmmm 011010nnnnnddddd 0520 6800 // UZP1 .Q, .Q, .Q SVE_BR_3B 00000101101mmmmm 000010nnnnnddddd 05A0 0800 // UZP1 ., ., . SVE_CI_3A 00000101xx10MMMM 0100100NNNN0DDDD 0520 4800 INST3(uzp2, "uzp2", 0, IF_SVE_3D, 0x05206C00, 0x05A00C00, 0x05204C00 ) - // UZP2 ., ., . SVE_BR_3A 00000101xx1mmmmm 011011nnnnnddddd 0520 6C00 + // UZP2 ., ., . SVE_AT_3A 00000101xx1mmmmm 011011nnnnnddddd 0520 6C00 // UZP2 .Q, .Q, .Q SVE_BR_3B 00000101101mmmmm 000011nnnnnddddd 05A0 0C00 // UZP2 ., ., . SVE_CI_3A 00000101xx10MMMM 0100110NNNN0DDDD 0520 4C00 INST3(zip1, "zip1", 0, IF_SVE_3D, 0x05206000, 0x05A00000, 0x05204000 ) - // ZIP1 ., ., . SVE_BR_3A 00000101xx1mmmmm 011000nnnnnddddd 0520 6000 + // ZIP1 ., ., . SVE_AT_3A 00000101xx1mmmmm 011000nnnnnddddd 0520 6000 // ZIP1 .Q, .Q, .Q SVE_BR_3B 00000101101mmmmm 000000nnnnnddddd 05A0 0000 // ZIP1 ., ., . SVE_CI_3A 00000101xx10MMMM 0100000NNNN0DDDD 0520 4000 INST3(zip2, "zip2", 0, IF_SVE_3D, 0x05206400, 0x05A00400, 0x05204400 ) - // ZIP2 ., ., . SVE_BR_3A 00000101xx1mmmmm 011001nnnnnddddd 0520 6400 + // ZIP2 ., ., . SVE_AT_3A 00000101xx1mmmmm 011001nnnnnddddd 0520 6400 // ZIP2 .Q, .Q, .Q SVE_BR_3B 00000101101mmmmm 000001nnnnnddddd 05A0 0400 // ZIP2 ., ., . SVE_CI_3A 00000101xx10MMMM 0100010NNNN0DDDD 0520 4400 -// enum name info SVE_AT_3A SVE_EC_1A SVE_ET_3A +// enum name info SVE_AT_3A SVE_EC_1A SVE_AA_3A INST3(sqadd, "sqadd", 0, IF_SVE_3E, 0x04201000, 0x2524C000, 0x44188000 ) // SQADD ., ., . SVE_AT_3A 00000100xx1mmmmm 000100nnnnnddddd 0420 1000 // SQADD ., ., #{, } SVE_EC_1A 00100101xx100100 11hiiiiiiiiddddd 2524 C000 - // SQADD ., /M, ., . SVE_ET_3A 01000100xx011000 100gggmmmmmddddd 4418 8000 + // SQADD ., /M, ., . SVE_AA_3A 01000100xx011000 100gggmmmmmddddd 4418 8000 INST3(sqsub, "sqsub", 0, IF_SVE_3E, 0x04201800, 0x2526C000, 0x441A8000 ) // SQSUB ., ., . SVE_AT_3A 00000100xx1mmmmm 000110nnnnnddddd 0420 1800 // SQSUB ., ., #{, } SVE_EC_1A 00100101xx100110 11hiiiiiiiiddddd 2526 C000 - // SQSUB ., /M, ., . SVE_ET_3A 01000100xx011010 100gggmmmmmddddd 441A 8000 + // SQSUB ., /M, ., . SVE_AA_3A 01000100xx011010 100gggmmmmmddddd 441A 8000 INST3(uqadd, "uqadd", 0, IF_SVE_3E, 0x04201400, 0x2525C000, 0x44198000 ) // UQADD ., ., . SVE_AT_3A 00000100xx1mmmmm 000101nnnnnddddd 0420 1400 // UQADD ., ., #{, } SVE_EC_1A 00100101xx100101 11hiiiiiiiiddddd 2525 C000 - // UQADD ., /M, ., . SVE_ET_3A 01000100xx011001 100gggmmmmmddddd 4419 8000 + // UQADD ., /M, ., . SVE_AA_3A 01000100xx011001 100gggmmmmmddddd 4419 8000 INST3(uqsub, "uqsub", 0, IF_SVE_3E, 0x04201C00, 0x2527C000, 0x441B8000 ) // UQSUB ., ., . SVE_AT_3A 00000100xx1mmmmm 000111nnnnnddddd 0420 1C00 // UQSUB ., ., #{, } SVE_EC_1A 00100101xx100111 11hiiiiiiiiddddd 2527 C000 - // UQSUB ., /M, ., . SVE_ET_3A 01000100xx011011 100gggmmmmmddddd 441B 8000 + // UQSUB ., /M, ., . SVE_AA_3A 01000100xx011011 100gggmmmmmddddd 441B 8000 // enum name info SVE_GU_3A SVE_GU_3B SVE_HU_4A @@ -654,14 +654,14 @@ INST3(luti4, "luti4", 0, IF_SV // LUTI4 .H, {.H }, [] SVE_GH_3B_B 01000101ii1mmmmm 101111nnnnnddddd 4520 BC00 -// enum name info SVE_HK_3A SVE_HL_3A SVE_HM_2A +// enum name info SVE_AT_3A SVE_HL_3A SVE_HM_2A INST3(fadd, "fadd", 0, IF_SVE_3H, 0x65000000, 0x65008000, 0x65188000 ) - // FADD ., ., . SVE_HK_3A 01100101xx0mmmmm 000000nnnnnddddd 6500 0000 + // FADD ., ., . SVE_AT_3A 01100101xx0mmmmm 000000nnnnnddddd 6500 0000 // FADD ., /M, ., . SVE_HL_3A 01100101xx000000 100gggmmmmmddddd 6500 8000 // FADD ., /M, ., SVE_HM_2A 01100101xx011000 100ggg0000iddddd 6518 8000 INST3(fsub, "fsub", 0, IF_SVE_3H, 0x65000400, 0x65018000, 0x65198000 ) - // FSUB ., ., . SVE_HK_3A 01100101xx0mmmmm 000001nnnnnddddd 6500 0400 + // FSUB ., ., . SVE_AT_3A 01100101xx0mmmmm 000001nnnnnddddd 6500 0400 // FSUB ., /M, ., . SVE_HL_3A 01100101xx000001 100gggmmmmmddddd 6501 8000 // FSUB ., /M, ., SVE_HM_2A 01100101xx011001 100ggg0000iddddd 6519 8000 @@ -837,60 +837,60 @@ INST3(umlslt, "umlslt", 0, IF_SV // UMLSLT .D, .S, .S[] SVE_FG_3B 01000100111immmm 1011i1nnnnnddddd 44E0 B400 -// enum name info SVE_EO_3A SVE_FJ_3A SVE_FJ_3B +// enum name info SVE_EL_3A SVE_FJ_3A SVE_FJ_3B INST3(sqdmlalb, "sqdmlalb", 0, IF_SVE_3Q, 0x44006000, 0x44A02000, 0x44E02000 ) - // SQDMLALB ., ., . SVE_EO_3A 01000100xx0mmmmm 011000nnnnnddddd 4400 6000 + // SQDMLALB ., ., . SVE_EL_3A 01000100xx0mmmmm 011000nnnnnddddd 4400 6000 // SQDMLALB .S, .H, .H[] SVE_FJ_3A 01000100101iimmm 0010i0nnnnnddddd 44A0 2000 // SQDMLALB .D, .S, .S[] SVE_FJ_3B 01000100111immmm 0010i0nnnnnddddd 44E0 2000 INST3(sqdmlalt, "sqdmlalt", 0, IF_SVE_3Q, 0x44006400, 0x44A02400, 0x44E02400 ) - // SQDMLALT ., ., . SVE_EO_3A 01000100xx0mmmmm 011001nnnnnddddd 4400 6400 + // SQDMLALT ., ., . SVE_EL_3A 01000100xx0mmmmm 011001nnnnnddddd 4400 6400 // SQDMLALT .S, .H, .H[] SVE_FJ_3A 01000100101iimmm 0010i1nnnnnddddd 44A0 2400 // SQDMLALT .D, .S, .S[] SVE_FJ_3B 01000100111immmm 0010i1nnnnnddddd 44E0 2400 INST3(sqdmlslb, "sqdmlslb", 0, IF_SVE_3Q, 0x44006800, 0x44A03000, 0x44E03000 ) - // SQDMLSLB ., ., . SVE_EO_3A 01000100xx0mmmmm 011010nnnnnddddd 4400 6800 + // SQDMLSLB ., ., . SVE_EL_3A 01000100xx0mmmmm 011010nnnnnddddd 4400 6800 // SQDMLSLB .S, .H, .H[] SVE_FJ_3A 01000100101iimmm 0011i0nnnnnddddd 44A0 3000 // SQDMLSLB .D, .S, .S[] SVE_FJ_3B 01000100111immmm 0011i0nnnnnddddd 44E0 3000 INST3(sqdmlslt, "sqdmlslt", 0, IF_SVE_3Q, 0x44006C00, 0x44A03400, 0x44E03400 ) - // SQDMLSLT ., ., . SVE_EO_3A 01000100xx0mmmmm 011011nnnnnddddd 4400 6C00 + // SQDMLSLT ., ., . SVE_EL_3A 01000100xx0mmmmm 011011nnnnnddddd 4400 6C00 // SQDMLSLT .S, .H, .H[] SVE_FJ_3A 01000100101iimmm 0011i1nnnnnddddd 44A0 3400 // SQDMLSLT .D, .S, .S[] SVE_FJ_3B 01000100111immmm 0011i1nnnnnddddd 44E0 3400 -// enum name info SVE_FE_3A SVE_FE_3B SVE_FN_3A +// enum name info SVE_FE_3A SVE_FE_3B SVE_FL_3A INST3(smullb, "smullb", 0, IF_SVE_3R, 0x44A0C000, 0x44E0C000, 0x45007000 ) // SMULLB .S, .H, .H[] SVE_FE_3A 01000100101iimmm 1100i0nnnnnddddd 44A0 C000 // SMULLB .D, .S, .S[] SVE_FE_3B 01000100111immmm 1100i0nnnnnddddd 44E0 C000 - // SMULLB ., ., . SVE_FN_3A 01000101xx0mmmmm 011100nnnnnddddd 4500 7000 + // SMULLB ., ., . SVE_FL_3A 01000101xx0mmmmm 011100nnnnnddddd 4500 7000 INST3(smullt, "smullt", 0, IF_SVE_3R, 0x44A0C400, 0x44E0C400, 0x45007400 ) // SMULLT .S, .H, .H[] SVE_FE_3A 01000100101iimmm 1100i1nnnnnddddd 44A0 C400 // SMULLT .D, .S, .S[] SVE_FE_3B 01000100111immmm 1100i1nnnnnddddd 44E0 C400 - // SMULLT ., ., . SVE_FN_3A 01000101xx0mmmmm 011101nnnnnddddd 4500 7400 + // SMULLT ., ., . SVE_FL_3A 01000101xx0mmmmm 011101nnnnnddddd 4500 7400 INST3(umullb, "umullb", 0, IF_SVE_3R, 0x44A0D000, 0x44E0D000, 0x45007800 ) // UMULLB .S, .H, .H[] SVE_FE_3A 01000100101iimmm 1101i0nnnnnddddd 44A0 D000 // UMULLB .D, .S, .S[] SVE_FE_3B 01000100111immmm 1101i0nnnnnddddd 44E0 D000 - // UMULLB ., ., . SVE_FN_3A 01000101xx0mmmmm 011110nnnnnddddd 4500 7800 + // UMULLB ., ., . SVE_FL_3A 01000101xx0mmmmm 011110nnnnnddddd 4500 7800 INST3(umullt, "umullt", 0, IF_SVE_3R, 0x44A0D400, 0x44E0D400, 0x45007C00 ) // UMULLT .S, .H, .H[] SVE_FE_3A 01000100101iimmm 1101i1nnnnnddddd 44A0 D400 // UMULLT .D, .S, .S[] SVE_FE_3B 01000100111immmm 1101i1nnnnnddddd 44E0 D400 - // UMULLT ., ., . SVE_FN_3A 01000101xx0mmmmm 011111nnnnnddddd 4500 7C00 + // UMULLT ., ., . SVE_FL_3A 01000101xx0mmmmm 011111nnnnnddddd 4500 7C00 -// enum name info SVE_FH_3A SVE_FH_3B SVE_FN_3A +// enum name info SVE_FH_3A SVE_FH_3B SVE_FL_3A INST3(sqdmullb, "sqdmullb", 0, IF_SVE_3S, 0x44A0E000, 0x44E0E000, 0x45006000 ) // SQDMULLB .S, .H, .H[] SVE_FH_3A 01000100101iimmm 1110i0nnnnnddddd 44A0 E000 // SQDMULLB .D, .S, .S[] SVE_FH_3B 01000100111immmm 1110i0nnnnnddddd 44E0 E000 - // SQDMULLB ., ., . SVE_FN_3A 01000101xx0mmmmm 011000nnnnnddddd 4500 6000 + // SQDMULLB ., ., . SVE_FL_3A 01000101xx0mmmmm 011000nnnnnddddd 4500 6000 INST3(sqdmullt, "sqdmullt", 0, IF_SVE_3S, 0x44A0E400, 0x44E0E400, 0x45006400 ) // SQDMULLT .S, .H, .H[] SVE_FH_3A 01000100101iimmm 1110i1nnnnnddddd 44A0 E400 // SQDMULLT .D, .S, .S[] SVE_FH_3B 01000100111immmm 1110i1nnnnnddddd 44E0 E400 - // SQDMULLT ., ., . SVE_FN_3A 01000101xx0mmmmm 011001nnnnnddddd 4500 6400 + // SQDMULLT ., ., . SVE_FL_3A 01000101xx0mmmmm 011001nnnnnddddd 4500 6400 // enum name info SVE_GX_3C SVE_HK_3B SVE_HL_3B @@ -926,21 +926,21 @@ INST2(str, "str", 0, IF_SV // STR , [{, #, MUL VL}] SVE_JH_2A 1110010110iiiiii 010iiinnnnnttttt E580 4000 -// enum name info SVE_AD_3A SVE_ED_1A +// enum name info SVE_AA_3A SVE_ED_1A INST2(smax, "smax", 0, IF_SVE_2AC, 0x04080000, 0x2528C000 ) - // SMAX ., /M, ., . SVE_AD_3A 00000100xx001000 000gggmmmmmddddd 0408 0000 + // SMAX ., /M, ., . SVE_AA_3A 00000100xx001000 000gggmmmmmddddd 0408 0000 // SMAX ., ., # SVE_ED_1A 00100101xx101000 110iiiiiiiiddddd 2528 C000 INST2(smin, "smin", 0, IF_SVE_2AC, 0x040A0000, 0x252AC000 ) - // SMIN ., /M, ., . SVE_AD_3A 00000100xx001010 000gggmmmmmddddd 040A 0000 + // SMIN ., /M, ., . SVE_AA_3A 00000100xx001010 000gggmmmmmddddd 040A 0000 // SMIN ., ., # SVE_ED_1A 00100101xx101010 110iiiiiiiiddddd 252A C000 INST2(umax, "umax", 0, IF_SVE_2AC, 0x04090000, 0x2529C000 ) - // UMAX ., /M, ., . SVE_AD_3A 00000100xx001001 000gggmmmmmddddd 0409 0000 + // UMAX ., /M, ., . SVE_AA_3A 00000100xx001001 000gggmmmmmddddd 0409 0000 // UMAX ., ., # SVE_ED_1A 00100101xx101001 110iiiiiiiiddddd 2529 C000 INST2(umin, "umin", 0, IF_SVE_2AC, 0x040B0000, 0x252BC000 ) - // UMIN ., /M, ., . SVE_AD_3A 00000100xx001011 000gggmmmmmddddd 040B 0000 + // UMIN ., /M, ., . SVE_AA_3A 00000100xx001011 000gggmmmmmddddd 040B 0000 // UMIN ., ., # SVE_ED_1A 00100101xx101011 110iiiiiiiiddddd 252B C000 @@ -960,14 +960,14 @@ INST2(rev, "rev", 0, IF_SV // REV ., . SVE_CJ_2A 00000101xx110100 0100000NNNN0DDDD 0534 4000 -// enum name info SVE_AE_3A SVE_BD_3A +// enum name info SVE_AA_3A SVE_AT_3A INST2(smulh, "smulh", 0, IF_SVE_2AF, 0x04120000, 0x04206800 ) - // SMULH ., /M, ., . SVE_AE_3A 00000100xx010010 000gggmmmmmddddd 0412 0000 - // SMULH ., ., . SVE_BD_3A 00000100xx1mmmmm 011010nnnnnddddd 0420 6800 + // SMULH ., /M, ., . SVE_AA_3A 00000100xx010010 000gggmmmmmddddd 0412 0000 + // SMULH ., ., . SVE_AT_3A 00000100xx1mmmmm 011010nnnnnddddd 0420 6800 INST2(umulh, "umulh", 0, IF_SVE_2AF, 0x04130000, 0x04206C00 ) - // UMULH ., /M, ., . SVE_AE_3A 00000100xx010011 000gggmmmmmddddd 0413 0000 - // UMULH ., ., . SVE_BD_3A 00000100xx1mmmmm 011011nnnnnddddd 0420 6C00 + // UMULH ., /M, ., . SVE_AA_3A 00000100xx010011 000gggmmmmmddddd 0413 0000 + // UMULH ., ., . SVE_AT_3A 00000100xx1mmmmm 011011nnnnnddddd 0420 6C00 // enum name info SVE_BS_1A SVE_CZ_4A @@ -982,14 +982,14 @@ INST2(ext, "ext", 0, IF_SV // EXT .B, .B, .B, # SVE_BQ_2B 00000101001iiiii 000iiimmmmmddddd 0520 0000 -// enum name info SVE_AM_2A SVE_EU_3A +// enum name info SVE_AM_2A SVE_AA_3A INST2(sqshl, "sqshl", 0, IF_SVE_2AI, 0x04068000, 0x44088000 ) // SQSHL ., /M, ., # SVE_AM_2A 00000100xx000110 100gggxxiiiddddd 0406 8000 - // SQSHL ., /M, ., . SVE_EU_3A 01000100xx001000 100gggmmmmmddddd 4408 8000 + // SQSHL ., /M, ., . SVE_AA_3A 01000100xx001000 100gggmmmmmddddd 4408 8000 INST2(uqshl, "uqshl", 0, IF_SVE_2AI, 0x04078000, 0x44098000 ) // UQSHL ., /M, ., # SVE_AM_2A 00000100xx000111 100gggxxiiiddddd 0407 8000 - // UQSHL ., /M, ., . SVE_EU_3A 01000100xx001001 100gggmmmmmddddd 4409 8000 + // UQSHL ., /M, ., . SVE_AA_3A 01000100xx001001 100gggmmmmmddddd 4409 8000 // enum name info SVE_HI_3A SVE_HT_4A @@ -1094,9 +1094,9 @@ INST2(not, "not", 0, IF_SV // NOT .B, /Z, .B SVE_CZ_4A 001001010000MMMM 01gggg1NNNN0DDDD 2500 4200 -// enum name info SVE_AB_3A SVE_EC_1A +// enum name info SVE_AA_3A SVE_EC_1A INST2(subr, "subr", 0, IF_SVE_2AT, 0x04030000, 0x2523C000 ) - // SUBR ., /M, ., . SVE_AB_3A 00000100xx000011 000gggmmmmmddddd 0403 0000 + // SUBR ., /M, ., . SVE_AA_3A 00000100xx000011 000gggmmmmmddddd 0403 0000 // SUBR ., ., #{, } SVE_EC_1A 00100101xx100011 11hiiiiiiiiddddd 2523 C000 @@ -1268,13 +1268,13 @@ INST2(pext, "pext", 0, IF_SV // PEXT {., .}, [] SVE_DW_2B 00100101xx100000 0111010iNNN1DDDD 2520 7410 -// enum name info SVE_FN_3A SVE_FN_3B +// enum name info SVE_FL_3A SVE_FN_3B INST2(pmullb, "pmullb", 0, IF_SVE_2BI, 0x45006800, 0x45006800 ) - // PMULLB ., ., . SVE_FN_3A 01000101xx0mmmmm 011010nnnnnddddd 4500 6800 + // PMULLB ., ., . SVE_FL_3A 01000101xx0mmmmm 011010nnnnnddddd 4500 6800 // PMULLB .Q, .D, .D SVE_FN_3B 01000101000mmmmm 011010nnnnnddddd 4500 6800 INST2(pmullt, "pmullt", 0, IF_SVE_2BI, 0x45006C00, 0x45006C00 ) - // PMULLT ., ., . SVE_FN_3A 01000101xx0mmmmm 011011nnnnnddddd 4500 6C00 + // PMULLT ., ., . SVE_FL_3A 01000101xx0mmmmm 011011nnnnnddddd 4500 6C00 // PMULLT .Q, .D, .D SVE_FN_3B 01000101000mmmmm 011011nnnnnddddd 4500 6C00 @@ -1644,21 +1644,21 @@ INST1(fminv, "fminv", 0, IF_SV // FMINV , , . SVE_HE_3A 01100101xx000111 001gggnnnnnddddd 6507 2000 -// enum name info SVE_ER_3A -INST1(addp, "addp", 0, IF_SVE_ER_3A, 0x4411A000 ) - // ADDP ., /M, ., . SVE_ER_3A 01000100xx010001 101gggmmmmmddddd 4411 A000 +// enum name info SVE_AA_3A +INST1(addp, "addp", 0, IF_SVE_AA_3A, 0x4411A000 ) + // ADDP ., /M, ., . SVE_AA_3A 01000100xx010001 101gggmmmmmddddd 4411 A000 -INST1(smaxp, "smaxp", 0, IF_SVE_ER_3A, 0x4414A000 ) - // SMAXP ., /M, ., . SVE_ER_3A 01000100xx010100 101gggmmmmmddddd 4414 A000 +INST1(smaxp, "smaxp", 0, IF_SVE_AA_3A, 0x4414A000 ) + // SMAXP ., /M, ., . SVE_AA_3A 01000100xx010100 101gggmmmmmddddd 4414 A000 -INST1(sminp, "sminp", 0, IF_SVE_ER_3A, 0x4416A000 ) - // SMINP ., /M, ., . SVE_ER_3A 01000100xx010110 101gggmmmmmddddd 4416 A000 +INST1(sminp, "sminp", 0, IF_SVE_AA_3A, 0x4416A000 ) + // SMINP ., /M, ., . SVE_AA_3A 01000100xx010110 101gggmmmmmddddd 4416 A000 -INST1(umaxp, "umaxp", 0, IF_SVE_ER_3A, 0x4415A000 ) - // UMAXP ., /M, ., . SVE_ER_3A 01000100xx010101 101gggmmmmmddddd 4415 A000 +INST1(umaxp, "umaxp", 0, IF_SVE_AA_3A, 0x4415A000 ) + // UMAXP ., /M, ., . SVE_AA_3A 01000100xx010101 101gggmmmmmddddd 4415 A000 -INST1(uminp, "uminp", 0, IF_SVE_ER_3A, 0x4417A000 ) - // UMINP ., /M, ., . SVE_ER_3A 01000100xx010111 101gggmmmmmddddd 4417 A000 +INST1(uminp, "uminp", 0, IF_SVE_AA_3A, 0x4417A000 ) + // UMINP ., /M, ., . SVE_AA_3A 01000100xx010111 101gggmmmmmddddd 4417 A000 // enum name info SVE_GR_3A @@ -1725,36 +1725,36 @@ INST1(sri, "sri", RSH, IF_SV // SRI ., ., # SVE_FT_2A 01000101xx0xxiii 111100nnnnnddddd 4500 F000 -// enum name info SVE_EU_3A -INST1(sqrshl, "sqrshl", 0, IF_SVE_EU_3A, 0x440A8000 ) - // SQRSHL ., /M, ., . SVE_EU_3A 01000100xx001010 100gggmmmmmddddd 440A 8000 +// enum name info SVE_AA_3A +INST1(sqrshl, "sqrshl", 0, IF_SVE_AA_3A, 0x440A8000 ) + // SQRSHL ., /M, ., . SVE_AA_3A 01000100xx001010 100gggmmmmmddddd 440A 8000 -INST1(sqrshlr, "sqrshlr", 0, IF_SVE_EU_3A, 0x440E8000 ) - // SQRSHLR ., /M, ., . SVE_EU_3A 01000100xx001110 100gggmmmmmddddd 440E 8000 +INST1(sqrshlr, "sqrshlr", 0, IF_SVE_AA_3A, 0x440E8000 ) + // SQRSHLR ., /M, ., . SVE_AA_3A 01000100xx001110 100gggmmmmmddddd 440E 8000 -INST1(sqshlr, "sqshlr", 0, IF_SVE_EU_3A, 0x440C8000 ) - // SQSHLR ., /M, ., . SVE_EU_3A 01000100xx001100 100gggmmmmmddddd 440C 8000 +INST1(sqshlr, "sqshlr", 0, IF_SVE_AA_3A, 0x440C8000 ) + // SQSHLR ., /M, ., . SVE_AA_3A 01000100xx001100 100gggmmmmmddddd 440C 8000 -INST1(srshl, "srshl", 0, IF_SVE_EU_3A, 0x44028000 ) - // SRSHL ., /M, ., . SVE_EU_3A 01000100xx000010 100gggmmmmmddddd 4402 8000 +INST1(srshl, "srshl", 0, IF_SVE_AA_3A, 0x44028000 ) + // SRSHL ., /M, ., . SVE_AA_3A 01000100xx000010 100gggmmmmmddddd 4402 8000 -INST1(srshlr, "srshlr", 0, IF_SVE_EU_3A, 0x44068000 ) - // SRSHLR ., /M, ., . SVE_EU_3A 01000100xx000110 100gggmmmmmddddd 4406 8000 +INST1(srshlr, "srshlr", 0, IF_SVE_AA_3A, 0x44068000 ) + // SRSHLR ., /M, ., . SVE_AA_3A 01000100xx000110 100gggmmmmmddddd 4406 8000 -INST1(uqrshl, "uqrshl", 0, IF_SVE_EU_3A, 0x440B8000 ) - // UQRSHL ., /M, ., . SVE_EU_3A 01000100xx001011 100gggmmmmmddddd 440B 8000 +INST1(uqrshl, "uqrshl", 0, IF_SVE_AA_3A, 0x440B8000 ) + // UQRSHL ., /M, ., . SVE_AA_3A 01000100xx001011 100gggmmmmmddddd 440B 8000 -INST1(uqrshlr, "uqrshlr", 0, IF_SVE_EU_3A, 0x440F8000 ) - // UQRSHLR ., /M, ., . SVE_EU_3A 01000100xx001111 100gggmmmmmddddd 440F 8000 +INST1(uqrshlr, "uqrshlr", 0, IF_SVE_AA_3A, 0x440F8000 ) + // UQRSHLR ., /M, ., . SVE_AA_3A 01000100xx001111 100gggmmmmmddddd 440F 8000 -INST1(uqshlr, "uqshlr", 0, IF_SVE_EU_3A, 0x440D8000 ) - // UQSHLR ., /M, ., . SVE_EU_3A 01000100xx001101 100gggmmmmmddddd 440D 8000 +INST1(uqshlr, "uqshlr", 0, IF_SVE_AA_3A, 0x440D8000 ) + // UQSHLR ., /M, ., . SVE_AA_3A 01000100xx001101 100gggmmmmmddddd 440D 8000 -INST1(urshl, "urshl", 0, IF_SVE_EU_3A, 0x44038000 ) - // URSHL ., /M, ., . SVE_EU_3A 01000100xx000011 100gggmmmmmddddd 4403 8000 +INST1(urshl, "urshl", 0, IF_SVE_AA_3A, 0x44038000 ) + // URSHL ., /M, ., . SVE_AA_3A 01000100xx000011 100gggmmmmmddddd 4403 8000 -INST1(urshlr, "urshlr", 0, IF_SVE_EU_3A, 0x44078000 ) - // URSHLR ., /M, ., . SVE_EU_3A 01000100xx000111 100gggmmmmmddddd 4407 8000 +INST1(urshlr, "urshlr", 0, IF_SVE_AA_3A, 0x44078000 ) + // URSHLR ., /M, ., . SVE_AA_3A 01000100xx000111 100gggmmmmmddddd 4407 8000 // enum name info SVE_HL_3A @@ -1780,15 +1780,15 @@ INST1(fscale, "fscale", 0, IF_SV // FSCALE ., /M, ., . SVE_HL_3A 01100101xx001001 100gggmmmmmddddd 6509 8000 -// enum name info SVE_HK_3A -INST1(frecps, "frecps", 0, IF_SVE_HK_3A, 0x65001800 ) - // FRECPS ., ., . SVE_HK_3A 01100101xx0mmmmm 000110nnnnnddddd 6500 1800 +// enum name info SVE_AT_3A +INST1(frecps, "frecps", 0, IF_SVE_AT_3A, 0x65001800 ) + // FRECPS ., ., . SVE_AT_3A 01100101xx0mmmmm 000110nnnnnddddd 6500 1800 -INST1(frsqrts, "frsqrts", 0, IF_SVE_HK_3A, 0x65001C00 ) - // FRSQRTS ., ., . SVE_HK_3A 01100101xx0mmmmm 000111nnnnnddddd 6500 1C00 +INST1(frsqrts, "frsqrts", 0, IF_SVE_AT_3A, 0x65001C00 ) + // FRSQRTS ., ., . SVE_AT_3A 01100101xx0mmmmm 000111nnnnnddddd 6500 1C00 -INST1(ftsmul, "ftsmul", 0, IF_SVE_HK_3A, 0x65000C00 ) - // FTSMUL ., ., . SVE_HK_3A 01100101xx0mmmmm 000011nnnnnddddd 6500 0C00 +INST1(ftsmul, "ftsmul", 0, IF_SVE_AT_3A, 0x65000C00 ) + // FTSMUL ., ., . SVE_AT_3A 01100101xx0mmmmm 000011nnnnnddddd 6500 0C00 // enum name info SVE_HT_4A INST1(facge, "facge", 0, IF_SVE_HT_4A, 0x6500C010 ) @@ -1807,18 +1807,18 @@ INST1(fcmuo, "fcmuo", 0, IF_SV // FCMUO ., /Z, ., . SVE_HT_4A 01100101xx0mmmmm 110gggnnnnn0DDDD 6500 C000 -// enum name info SVE_ET_3A -INST1(sqsubr, "sqsubr", 0, IF_SVE_ET_3A, 0x441E8000 ) - // SQSUBR ., /M, ., . SVE_ET_3A 01000100xx011110 100gggmmmmmddddd 441E 8000 +// enum name info SVE_AA_3A +INST1(sqsubr, "sqsubr", 0, IF_SVE_AA_3A, 0x441E8000 ) + // SQSUBR ., /M, ., . SVE_AA_3A 01000100xx011110 100gggmmmmmddddd 441E 8000 -INST1(suqadd, "suqadd", 0, IF_SVE_ET_3A, 0x441C8000 ) - // SUQADD ., /M, ., . SVE_ET_3A 01000100xx011100 100gggmmmmmddddd 441C 8000 +INST1(suqadd, "suqadd", 0, IF_SVE_AA_3A, 0x441C8000 ) + // SUQADD ., /M, ., . SVE_AA_3A 01000100xx011100 100gggmmmmmddddd 441C 8000 -INST1(uqsubr, "uqsubr", 0, IF_SVE_ET_3A, 0x441F8000 ) - // UQSUBR ., /M, ., . SVE_ET_3A 01000100xx011111 100gggmmmmmddddd 441F 8000 +INST1(uqsubr, "uqsubr", 0, IF_SVE_AA_3A, 0x441F8000 ) + // UQSUBR ., /M, ., . SVE_AA_3A 01000100xx011111 100gggmmmmmddddd 441F 8000 -INST1(usqadd, "usqadd", 0, IF_SVE_ET_3A, 0x441D8000 ) - // USQADD ., /M, ., . SVE_ET_3A 01000100xx011101 100gggmmmmmddddd 441D 8000 +INST1(usqadd, "usqadd", 0, IF_SVE_AA_3A, 0x441D8000 ) + // USQADD ., /M, ., . SVE_AA_3A 01000100xx011101 100gggmmmmmddddd 441D 8000 // enum name info SVE_ES_3A @@ -1856,38 +1856,38 @@ INST1(tbx, "tbx", 0, IF_SV // TBX ., ., . SVE_BZ_3A 00000101xx1mmmmm 001011nnnnnddddd 0520 2C00 -// enum name info SVE_EP_3A -INST1(shadd, "shadd", 0, IF_SVE_EP_3A, 0x44108000 ) - // SHADD ., /M, ., . SVE_EP_3A 01000100xx010000 100gggmmmmmddddd 4410 8000 +// enum name info SVE_AA_3A +INST1(shadd, "shadd", 0, IF_SVE_AA_3A, 0x44108000 ) + // SHADD ., /M, ., . SVE_AA_3A 01000100xx010000 100gggmmmmmddddd 4410 8000 -INST1(shsub, "shsub", 0, IF_SVE_EP_3A, 0x44128000 ) - // SHSUB ., /M, ., . SVE_EP_3A 01000100xx010010 100gggmmmmmddddd 4412 8000 +INST1(shsub, "shsub", 0, IF_SVE_AA_3A, 0x44128000 ) + // SHSUB ., /M, ., . SVE_AA_3A 01000100xx010010 100gggmmmmmddddd 4412 8000 -INST1(shsubr, "shsubr", 0, IF_SVE_EP_3A, 0x44168000 ) - // SHSUBR ., /M, ., . SVE_EP_3A 01000100xx010110 100gggmmmmmddddd 4416 8000 +INST1(shsubr, "shsubr", 0, IF_SVE_AA_3A, 0x44168000 ) + // SHSUBR ., /M, ., . SVE_AA_3A 01000100xx010110 100gggmmmmmddddd 4416 8000 -INST1(srhadd, "srhadd", 0, IF_SVE_EP_3A, 0x44148000 ) - // SRHADD ., /M, ., . SVE_EP_3A 01000100xx010100 100gggmmmmmddddd 4414 8000 +INST1(srhadd, "srhadd", 0, IF_SVE_AA_3A, 0x44148000 ) + // SRHADD ., /M, ., . SVE_AA_3A 01000100xx010100 100gggmmmmmddddd 4414 8000 -INST1(uhadd, "uhadd", 0, IF_SVE_EP_3A, 0x44118000 ) - // UHADD ., /M, ., . SVE_EP_3A 01000100xx010001 100gggmmmmmddddd 4411 8000 +INST1(uhadd, "uhadd", 0, IF_SVE_AA_3A, 0x44118000 ) + // UHADD ., /M, ., . SVE_AA_3A 01000100xx010001 100gggmmmmmddddd 4411 8000 -INST1(uhsub, "uhsub", 0, IF_SVE_EP_3A, 0x44138000 ) - // UHSUB ., /M, ., . SVE_EP_3A 01000100xx010011 100gggmmmmmddddd 4413 8000 +INST1(uhsub, "uhsub", 0, IF_SVE_AA_3A, 0x44138000 ) + // UHSUB ., /M, ., . SVE_AA_3A 01000100xx010011 100gggmmmmmddddd 4413 8000 -INST1(uhsubr, "uhsubr", 0, IF_SVE_EP_3A, 0x44178000 ) - // UHSUBR ., /M, ., . SVE_EP_3A 01000100xx010111 100gggmmmmmddddd 4417 8000 +INST1(uhsubr, "uhsubr", 0, IF_SVE_AA_3A, 0x44178000 ) + // UHSUBR ., /M, ., . SVE_AA_3A 01000100xx010111 100gggmmmmmddddd 4417 8000 -INST1(urhadd, "urhadd", 0, IF_SVE_EP_3A, 0x44158000 ) - // URHADD ., /M, ., . SVE_EP_3A 01000100xx010101 100gggmmmmmddddd 4415 8000 +INST1(urhadd, "urhadd", 0, IF_SVE_AA_3A, 0x44158000 ) + // URHADD ., /M, ., . SVE_AA_3A 01000100xx010101 100gggmmmmmddddd 4415 8000 -// enum name info SVE_AD_3A -INST1(sabd, "sabd", 0, IF_SVE_AD_3A, 0x040C0000 ) - // SABD ., /M, ., . SVE_AD_3A 00000100xx001100 000gggmmmmmddddd 040C 0000 +// enum name info SVE_AA_3A +INST1(sabd, "sabd", 0, IF_SVE_AA_3A, 0x040C0000 ) + // SABD ., /M, ., . SVE_AA_3A 00000100xx001100 000gggmmmmmddddd 040C 0000 -INST1(uabd, "uabd", 0, IF_SVE_AD_3A, 0x040D0000 ) - // UABD ., /M, ., . SVE_AD_3A 00000100xx001101 000gggmmmmmddddd 040D 0000 +INST1(uabd, "uabd", 0, IF_SVE_AA_3A, 0x040D0000 ) + // UABD ., /M, ., . SVE_AA_3A 00000100xx001101 000gggmmmmmddddd 040D 0000 // enum name info SVE_FW_3A @@ -2072,15 +2072,15 @@ INST1(uminqv, "uminqv", 0, IF_SV // UMINQV ., , . SVE_AL_3A 00000100xx001111 001gggnnnnnddddd 040F 2000 -// enum name info SVE_AN_3A -INST1(asrr, "asrr", RSH, IF_SVE_AN_3A, 0x04148000 ) - // ASRR ., /M, ., . SVE_AN_3A 00000100xx010100 100gggmmmmmddddd 0414 8000 +// enum name info SVE_AA_3A +INST1(asrr, "asrr", RSH, IF_SVE_AA_3A, 0x04148000 ) + // ASRR ., /M, ., . SVE_AA_3A 00000100xx010100 100gggmmmmmddddd 0414 8000 -INST1(lslr, "lslr", RSH, IF_SVE_AN_3A, 0x04178000 ) - // LSLR ., /M, ., . SVE_AN_3A 00000100xx010111 100gggmmmmmddddd 0417 8000 +INST1(lslr, "lslr", RSH, IF_SVE_AA_3A, 0x04178000 ) + // LSLR ., /M, ., . SVE_AA_3A 00000100xx010111 100gggmmmmmddddd 0417 8000 -INST1(lsrr, "lsrr", RSH, IF_SVE_AN_3A, 0x04158000 ) - // LSRR ., /M, ., . SVE_AN_3A 00000100xx010101 100gggmmmmmddddd 0415 8000 +INST1(lsrr, "lsrr", RSH, IF_SVE_AA_3A, 0x04158000 ) + // LSRR ., /M, ., . SVE_AA_3A 00000100xx010101 100gggmmmmmddddd 0415 8000 // enum name info SVE_AS_4A @@ -2109,9 +2109,9 @@ INST1(fexpa, "fexpa", 0, IF_SV // FEXPA ., . SVE_BJ_2A 00000100xx100000 101110nnnnnddddd 0420 B800 -// enum name info SVE_BK_3A -INST1(ftssel, "ftssel", 0, IF_SVE_BK_3A, 0x0420B000 ) - // FTSSEL ., ., . SVE_BK_3A 00000100xx1mmmmm 101100nnnnnddddd 0420 B000 +// enum name info SVE_AT_3A +INST1(ftssel, "ftssel", 0, IF_SVE_AT_3A, 0x0420B000 ) + // FTSSEL ., ., . SVE_AT_3A 00000100xx1mmmmm 101100nnnnnddddd 0420 B000 // enum name info SVE_BL_1A @@ -2170,9 +2170,9 @@ INST1(extq, "extq", 0, IF_SV // EXTQ .B, .B, .B, # SVE_BY_2A 000001010110iiii 001001mmmmmddddd 0560 2400 -// enum name info SVE_CA_3A -INST1(tbxq, "tbxq", 0, IF_SVE_CA_3A, 0x05203400 ) - // TBXQ ., ., . SVE_CA_3A 00000101xx1mmmmm 001101nnnnnddddd 0520 3400 +// enum name info SVE_AT_3A +INST1(tbxq, "tbxq", 0, IF_SVE_AT_3A, 0x05203400 ) + // TBXQ ., ., . SVE_AT_3A 00000101xx1mmmmm 001101nnnnnddddd 0520 3400 // enum name info SVE_CH_2A @@ -2311,20 +2311,20 @@ INST1(fdup, "fdup", 0, IF_SV // FDUP ., # SVE_EA_1A 00100101xx111001 110iiiiiiiiddddd 2539 C000 -// enum name info SVE_EN_3A -INST1(sqdmlalbt, "sqdmlalbt", 0, IF_SVE_EN_3A, 0x44000800 ) - // SQDMLALBT ., ., . SVE_EN_3A 01000100xx0mmmmm 000010nnnnnddddd 4400 0800 +// enum name info SVE_EL_3A +INST1(sqdmlalbt, "sqdmlalbt", 0, IF_SVE_EL_3A, 0x44000800 ) + // SQDMLALBT ., ., . SVE_EL_3A 01000100xx0mmmmm 000010nnnnnddddd 4400 0800 -INST1(sqdmlslbt, "sqdmlslbt", 0, IF_SVE_EN_3A, 0x44000C00 ) - // SQDMLSLBT ., ., . SVE_EN_3A 01000100xx0mmmmm 000011nnnnnddddd 4400 0C00 +INST1(sqdmlslbt, "sqdmlslbt", 0, IF_SVE_EL_3A, 0x44000C00 ) + // SQDMLSLBT ., ., . SVE_EL_3A 01000100xx0mmmmm 000011nnnnnddddd 4400 0C00 -// enum name info SVE_EV_3A -INST1(sclamp, "sclamp", 0, IF_SVE_EV_3A, 0x4400C000 ) - // SCLAMP ., ., . SVE_EV_3A 01000100xx0mmmmm 110000nnnnnddddd 4400 C000 +// enum name info SVE_AT_3A +INST1(sclamp, "sclamp", 0, IF_SVE_AT_3A, 0x4400C000 ) + // SCLAMP ., ., . SVE_AT_3A 01000100xx0mmmmm 110000nnnnnddddd 4400 C000 -INST1(uclamp, "uclamp", 0, IF_SVE_EV_3A, 0x4400C400 ) - // UCLAMP ., ., . SVE_EV_3A 01000100xx0mmmmm 110001nnnnnddddd 4400 C400 +INST1(uclamp, "uclamp", 0, IF_SVE_AT_3A, 0x4400C400 ) + // UCLAMP ., ., . SVE_AT_3A 01000100xx0mmmmm 110001nnnnnddddd 4400 C400 // enum name info SVE_EW_3A @@ -2418,23 +2418,23 @@ INST1(usubwt, "usubwt", 0, IF_SV // USUBWT ., ., . SVE_FM_3A 01000101xx0mmmmm 010111nnnnnddddd 4500 5C00 -// enum name info SVE_FP_3A -INST1(eorbt, "eorbt", 0, IF_SVE_FP_3A, 0x45009000 ) - // EORBT ., ., . SVE_FP_3A 01000101xx0mmmmm 100100nnnnnddddd 4500 9000 +// enum name info SVE_AT_3A +INST1(eorbt, "eorbt", 0, IF_SVE_AT_3A, 0x45009000 ) + // EORBT ., ., . SVE_AT_3A 01000101xx0mmmmm 100100nnnnnddddd 4500 9000 -INST1(eortb, "eortb", 0, IF_SVE_FP_3A, 0x45009400 ) - // EORTB ., ., . SVE_FP_3A 01000101xx0mmmmm 100101nnnnnddddd 4500 9400 +INST1(eortb, "eortb", 0, IF_SVE_AT_3A, 0x45009400 ) + // EORTB ., ., . SVE_AT_3A 01000101xx0mmmmm 100101nnnnnddddd 4500 9400 -// enum name info SVE_FQ_3A -INST1(bdep, "bdep", 0, IF_SVE_FQ_3A, 0x4500B400 ) - // BDEP ., ., . SVE_FQ_3A 01000101xx0mmmmm 101101nnnnnddddd 4500 B400 +// enum name info SVE_AT_3A +INST1(bdep, "bdep", 0, IF_SVE_AT_3A, 0x4500B400 ) + // BDEP ., ., . SVE_AT_3A 01000101xx0mmmmm 101101nnnnnddddd 4500 B400 -INST1(bext, "bext", 0, IF_SVE_FQ_3A, 0x4500B000 ) - // BEXT ., ., . SVE_FQ_3A 01000101xx0mmmmm 101100nnnnnddddd 4500 B000 +INST1(bext, "bext", 0, IF_SVE_AT_3A, 0x4500B000 ) + // BEXT ., ., . SVE_AT_3A 01000101xx0mmmmm 101100nnnnnddddd 4500 B000 -INST1(bgrp, "bgrp", 0, IF_SVE_FQ_3A, 0x4500B800 ) - // BGRP ., ., . SVE_FQ_3A 01000101xx0mmmmm 101110nnnnnddddd 4500 B800 +INST1(bgrp, "bgrp", 0, IF_SVE_AT_3A, 0x4500B800 ) + // BGRP ., ., . SVE_AT_3A 01000101xx0mmmmm 101110nnnnnddddd 4500 B800 // enum name info SVE_FR_2A @@ -2451,15 +2451,15 @@ INST1(ushllt, "ushllt", 0, IF_SV // USHLLT ., ., # SVE_FR_2A 010001010x0xxiii 101011nnnnnddddd 4500 AC00 -// enum name info SVE_FS_3A -INST1(saddlbt, "saddlbt", 0, IF_SVE_FS_3A, 0x45008000 ) - // SADDLBT ., ., . SVE_FS_3A 01000101xx0mmmmm 100000nnnnnddddd 4500 8000 +// enum name info SVE_FL_3A +INST1(saddlbt, "saddlbt", 0, IF_SVE_FL_3A, 0x45008000 ) + // SADDLBT ., ., . SVE_FL_3A 01000101xx0mmmmm 100000nnnnnddddd 4500 8000 -INST1(ssublbt, "ssublbt", 0, IF_SVE_FS_3A, 0x45008800 ) - // SSUBLBT ., ., . SVE_FS_3A 01000101xx0mmmmm 100010nnnnnddddd 4500 8800 +INST1(ssublbt, "ssublbt", 0, IF_SVE_FL_3A, 0x45008800 ) + // SSUBLBT ., ., . SVE_FL_3A 01000101xx0mmmmm 100010nnnnnddddd 4500 8800 -INST1(ssubltb, "ssubltb", 0, IF_SVE_FS_3A, 0x45008C00 ) - // SSUBLTB ., ., . SVE_FS_3A 01000101xx0mmmmm 100011nnnnnddddd 4500 8C00 +INST1(ssubltb, "ssubltb", 0, IF_SVE_FL_3A, 0x45008C00 ) + // SSUBLTB ., ., . SVE_FL_3A 01000101xx0mmmmm 100011nnnnnddddd 4500 8C00 // enum name info SVE_FV_2A @@ -2470,18 +2470,18 @@ INST1(sqcadd, "sqcadd", 0, IF_SV // SQCADD ., ., ., SVE_FV_2A 01000101xx000001 11011rmmmmmddddd 4501 D800 -// enum name info SVE_FX_3A -INST1(sabalb, "sabalb", 0, IF_SVE_FX_3A, 0x4500C000 ) - // SABALB ., ., . SVE_FX_3A 01000101xx0mmmmm 110000nnnnnddddd 4500 C000 +// enum name info SVE_EL_3A +INST1(sabalb, "sabalb", 0, IF_SVE_EL_3A, 0x4500C000 ) + // SABALB ., ., . SVE_EL_3A 01000101xx0mmmmm 110000nnnnnddddd 4500 C000 -INST1(sabalt, "sabalt", 0, IF_SVE_FX_3A, 0x4500C400 ) - // SABALT ., ., . SVE_FX_3A 01000101xx0mmmmm 110001nnnnnddddd 4500 C400 +INST1(sabalt, "sabalt", 0, IF_SVE_EL_3A, 0x4500C400 ) + // SABALT ., ., . SVE_EL_3A 01000101xx0mmmmm 110001nnnnnddddd 4500 C400 -INST1(uabalb, "uabalb", 0, IF_SVE_FX_3A, 0x4500C800 ) - // UABALB ., ., . SVE_FX_3A 01000101xx0mmmmm 110010nnnnnddddd 4500 C800 +INST1(uabalb, "uabalb", 0, IF_SVE_EL_3A, 0x4500C800 ) + // UABALB ., ., . SVE_EL_3A 01000101xx0mmmmm 110010nnnnnddddd 4500 C800 -INST1(uabalt, "uabalt", 0, IF_SVE_FX_3A, 0x4500CC00 ) - // UABALT ., ., . SVE_FX_3A 01000101xx0mmmmm 110011nnnnnddddd 4500 CC00 +INST1(uabalt, "uabalt", 0, IF_SVE_EL_3A, 0x4500CC00 ) + // UABALT ., ., . SVE_EL_3A 01000101xx0mmmmm 110011nnnnnddddd 4500 CC00 // enum name info SVE_FY_3A @@ -2651,9 +2651,9 @@ INST1(fminqv, "fminqv", 0, IF_SV // FMINQV ., , . SVE_GS_3A 01100100xx010111 101gggnnnnnddddd 6417 A000 -// enum name info SVE_GW_3A -INST1(fclamp, "fclamp", 0, IF_SVE_GW_3A, 0x64202400 ) - // FCLAMP ., ., . SVE_GW_3A 01100100xx1mmmmm 001001nnnnnddddd 6420 2400 +// enum name info SVE_AT_3A +INST1(fclamp, "fclamp", 0, IF_SVE_AT_3A, 0x64202400 ) + // FCLAMP ., ., . SVE_AT_3A 01100100xx1mmmmm 001001nnnnnddddd 6420 2400 // enum name info SVE_GW_3B diff --git a/src/coreclr/jit/instrsriscv64.h b/src/coreclr/jit/instrsriscv64.h index f38f3752e278..3d8416d09e04 100644 --- a/src/coreclr/jit/instrsriscv64.h +++ b/src/coreclr/jit/instrsriscv64.h @@ -205,8 +205,8 @@ INST(fmin_d, "fmin.d", 0, 0x2a000053) INST(fmax_d, "fmax.d", 0, 0x2a001053) //// R_R -INST(fcvt_s_d, "fcvt.s.d", 0, 0x40101053) -INST(fcvt_d_s, "fcvt.d.s", 0, 0x42001053) +INST(fcvt_s_d, "fcvt.s.d", 0, 0x40100053) +INST(fcvt_d_s, "fcvt.d.s", 0, 0x42000053) //// R_R_R INST(feq_d, "feq.d", 0, 0xa2002053) @@ -215,10 +215,10 @@ INST(fle_d, "fle.d", 0, 0xa2000053) //// R_R INST(fclass_d, "fclass.d", 0, 0xe2001053) -INST(fcvt_w_d, "fcvt.w.d", 0, 0xc2001053) -INST(fcvt_wu_d, "fcvt.wu.d", 0, 0xc2101053) -INST(fcvt_d_w, "fcvt.d.w", 0, 0xd2001053) -INST(fcvt_d_wu, "fcvt.d.wu", 0, 0xd2101053) +INST(fcvt_w_d, "fcvt.w.d", 0, 0xc2000053) +INST(fcvt_wu_d, "fcvt.wu.d", 0, 0xc2100053) +INST(fcvt_d_w, "fcvt.d.w", 0, 0xd2000053) +INST(fcvt_d_wu, "fcvt.d.wu", 0, 0xd2100053) //// R_R_I INST(flw, "flw", LD, 0x00002007) diff --git a/src/coreclr/jit/instrsxarch.h b/src/coreclr/jit/instrsxarch.h index 030bcffd41c6..fb820b2c6cf9 100644 --- a/src/coreclr/jit/instrsxarch.h +++ b/src/coreclr/jit/instrsxarch.h @@ -229,15 +229,15 @@ INST3(rcpps, "rcpps", IUM_WR, BAD_CODE, BAD_CODE, INST3(rcpss, "rcpss", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x53), INS_TT_NONE, REX_WIG | Encoding_VEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Reciprocal of scalar single INST3(rsqrtps, "rsqrtps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x52), INS_TT_NONE, REX_WIG | Encoding_VEX) // Reciprocal Sqrt of packed singles INST3(rsqrtss, "rsqrtss", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x52), INS_TT_NONE, REX_WIG | Encoding_VEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Reciprocal Sqrt of scalar single -INST3(shufps, "shufps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0xC6), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) +INST3(shufps, "shufps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0xC6), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) INST3(sfence, "sfence", IUM_RD, 0x000FF8AE, BAD_CODE, BAD_CODE, INS_TT_NONE, REX_WIG) -INST3(sqrtps, "sqrtps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x51), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX) // Sqrt of packed singles +INST3(sqrtps, "sqrtps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x51), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Sqrt of packed singles INST3(sqrtss, "sqrtss", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x51), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Sqrt of scalar single INST3(subps, "subps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x5C), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Subtract packed singles INST3(subss, "subss", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x5C), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Subtract scalar singles INST3(ucomiss, "ucomiss", IUM_RD, BAD_CODE, BAD_CODE, PCKFLT(0x2E), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Writes_PF | Writes_CF) // unordered compare singles -INST3(unpckhps, "unpckhps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x15), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) -INST3(unpcklps, "unpcklps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x14), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) +INST3(unpckhps, "unpckhps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x15), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) +INST3(unpcklps, "unpcklps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x14), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) INST3(xorps, "xorps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x57), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // XOR packed singles // SSE2 @@ -248,19 +248,19 @@ INST3(andpd, "andpd", IUM_WR, BAD_CODE, BAD_CODE, INST3(cmppd, "cmppd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xC2), INS_TT_NONE, Input_64Bit | REX_WIG | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // compare packed doubles INST3(cmpsd, "cmpsd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0xC2), INS_TT_NONE, Input_64Bit | REX_WIG | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // compare scalar doubles INST3(comisd, "comisd", IUM_RD, BAD_CODE, BAD_CODE, PCKDBL(0x2F), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Writes_PF | Writes_CF) // ordered compare doubles -INST3(cvtdq2pd, "cvtdq2pd", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0xE6), INS_TT_HALF, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX) // cvt packed DWORDs to doubles -INST3(cvtdq2ps, "cvtdq2ps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x5B), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX) // cvt packed DWORDs to singles -INST3(cvtpd2dq, "cvtpd2dq", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0xE6), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX) // cvt packed doubles to DWORDs -INST3(cvtpd2ps, "cvtpd2ps", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x5A), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX) // cvt packed doubles to singles -INST3(cvtps2dq, "cvtps2dq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x5B), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX) // cvt packed singles to DWORDs -INST3(cvtps2pd, "cvtps2pd", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x5A), INS_TT_HALF, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX) // cvt packed singles to doubles +INST3(cvtdq2pd, "cvtdq2pd", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0xE6), INS_TT_HALF, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed DWORDs to doubles +INST3(cvtdq2ps, "cvtdq2ps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x5B), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed DWORDs to singles +INST3(cvtpd2dq, "cvtpd2dq", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0xE6), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed doubles to DWORDs +INST3(cvtpd2ps, "cvtpd2ps", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x5A), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed doubles to singles +INST3(cvtps2dq, "cvtps2dq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x5B), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed singles to DWORDs +INST3(cvtps2pd, "cvtps2pd", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x5A), INS_TT_HALF, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed singles to doubles INST3(cvtsd2si, "cvtsd2si", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x2D), INS_TT_TUPLE1_FIXED, Input_64Bit | REX_WX | Encoding_VEX | Encoding_EVEX) // cvt scalar double to DWORD INST3(cvtsd2ss, "cvtsd2ss", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x5A), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // cvt scalar double to scalar singles INST3(cvtsi2sd32, "cvtsi2sd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x2A), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // cvt DWORD to scalar double INST3(cvtsi2sd64, "cvtsi2sd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x2A), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // cvt QWORD to scalar double INST3(cvtss2sd, "cvtss2sd", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x5A), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // cvt scalar single to scalar doubles -INST3(cvttpd2dq, "cvttpd2dq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xE6), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX) // cvt with trunc packed doubles to DWORDs -INST3(cvttps2dq, "cvttps2dq", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x5B), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX) // cvt with trunc packed singles to DWORDs +INST3(cvttpd2dq, "cvttpd2dq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xE6), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt with trunc packed doubles to DWORDs +INST3(cvttps2dq, "cvttps2dq", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x5B), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt with trunc packed singles to DWORDs INST3(cvttsd2si32, "cvttsd2si", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x2C), INS_TT_TUPLE1_FIXED, Input_64Bit | REX_W0 | Encoding_VEX | Encoding_EVEX) // cvt with trunc scalar double to signed DWORDs INST3(cvttsd2si64, "cvttsd2si", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x2C), INS_TT_TUPLE1_FIXED, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX) // cvt with trunc scalar double to signed DWORDs INST3(divpd, "divpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x5E), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Divide packed doubles @@ -288,7 +288,7 @@ INST3(movupd, "movupd", IUM_WR, PCKDBL(0x11), BAD_CODE, INST3(mulpd, "mulpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x59), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Multiply packed doubles INST3(mulsd, "mulsd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x59), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Multiply scalar doubles INST3(orpd, "orpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x56), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Or packed doubles -INST3(packssdw, "packssdw", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x6B), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Pack (narrow) int to short with saturation +INST3(packssdw, "packssdw", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x6B), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Pack (narrow) int to short with saturation INST3(packsswb, "packsswb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x63), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Pack (narrow) short to byte with saturation INST3(packuswb, "packuswb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x67), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Pack (narrow) short to unsigned byte with saturation INST3(paddb, "paddb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xFC), INS_TT_FULL_MEM, Input_8Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Add packed byte integers @@ -320,21 +320,21 @@ INST3(pmovmskb, "pmovmskb", IUM_WR, BAD_CODE, BAD_CODE, INST3(pmulhuw, "pmulhuw", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xE4), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Multiply high the packed 16-bit unsigned integers INST3(pmulhw, "pmulhw", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xE5), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Multiply high the packed 16-bit signed integers INST3(pmullw, "pmullw", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xD5), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed multiply 16 bit unsigned integers and store lower 16 bits of each result -INST3(pmuludq, "pmuludq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xF4), INS_TT_FULL_MEM, Input_32Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // packed multiply 32-bit unsigned integers and store 64-bit result +INST3(pmuludq, "pmuludq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xF4), INS_TT_FULL, Input_32Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // packed multiply 32-bit unsigned integers and store 64-bit result INST3(por, "por", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xEB), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed bit-wise OR of two xmm regs INST3(psadbw, "psadbw", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xF6), INS_TT_FULL_MEM, Input_8Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Compute the sum of absolute differences of packed unsigned 8-bit integers -INST3(pshufd, "pshufd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x70), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX) // Packed shuffle of 32-bit integers +INST3(pshufd, "pshufd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x70), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Packed shuffle of 32-bit integers INST3(pshufhw, "pshufhw", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x70), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX) // Shuffle the high words in xmm2/m128 based on the encoding in imm8 and store the result in xmm1. INST3(pshuflw, "pshuflw", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x70), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX) // Shuffle the low words in xmm2/m128 based on the encoding in imm8 and store the result in xmm1. -INST3(pslld, "pslld", IUM_WR, BAD_CODE, PCKDBL(0x72), PCKDBL(0xF2), INS_TT_FULL | INS_TT_MEM128, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed shift left logical of 32-bit integers +INST3(pslld, "pslld", IUM_WR, BAD_CODE, PCKDBL(0x72), PCKDBL(0xF2), INS_TT_FULL | INS_TT_MEM128, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed shift left logical of 32-bit integers INST3(pslldq, "pslldq", IUM_WR, BAD_CODE, PCKDBL(0x73), BAD_CODE, INS_TT_FULL_MEM, REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Shift left logical of xmm reg by given number of bytes -INST3(psllq, "psllq", IUM_WR, BAD_CODE, PCKDBL(0x73), PCKDBL(0xF3), INS_TT_FULL | INS_TT_MEM128, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed shift left logical of 64-bit integers +INST3(psllq, "psllq", IUM_WR, BAD_CODE, PCKDBL(0x73), PCKDBL(0xF3), INS_TT_FULL | INS_TT_MEM128, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed shift left logical of 64-bit integers INST3(psllw, "psllw", IUM_WR, BAD_CODE, PCKDBL(0x71), PCKDBL(0xF1), INS_TT_FULL_MEM | INS_TT_MEM128, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed shift left logical of 16-bit integers -INST3(psrad, "psrad", IUM_WR, BAD_CODE, PCKDBL(0x72), PCKDBL(0xE2), INS_TT_FULL | INS_TT_MEM128, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed shift right arithmetic of 32-bit integers +INST3(psrad, "psrad", IUM_WR, BAD_CODE, PCKDBL(0x72), PCKDBL(0xE2), INS_TT_FULL | INS_TT_MEM128, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed shift right arithmetic of 32-bit integers INST3(psraw, "psraw", IUM_WR, BAD_CODE, PCKDBL(0x71), PCKDBL(0xE1), INS_TT_FULL_MEM | INS_TT_MEM128, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed shift right arithmetic of 16-bit integers -INST3(psrld, "psrld", IUM_WR, BAD_CODE, PCKDBL(0x72), PCKDBL(0xD2), INS_TT_FULL | INS_TT_MEM128, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed shift right logical of 32-bit integers +INST3(psrld, "psrld", IUM_WR, BAD_CODE, PCKDBL(0x72), PCKDBL(0xD2), INS_TT_FULL | INS_TT_MEM128, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed shift right logical of 32-bit integers INST3(psrldq, "psrldq", IUM_WR, BAD_CODE, PCKDBL(0x73), BAD_CODE, INS_TT_FULL_MEM, REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Shift right logical of xmm reg by given number of bytes -INST3(psrlq, "psrlq", IUM_WR, BAD_CODE, PCKDBL(0x73), PCKDBL(0xD3), INS_TT_FULL | INS_TT_MEM128, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed shift right logical of 64-bit integers +INST3(psrlq, "psrlq", IUM_WR, BAD_CODE, PCKDBL(0x73), PCKDBL(0xD3), INS_TT_FULL | INS_TT_MEM128, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed shift right logical of 64-bit integers INST3(psrlw, "psrlw", IUM_WR, BAD_CODE, PCKDBL(0x71), PCKDBL(0xD1), INS_TT_FULL_MEM | INS_TT_MEM128, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed shift right logical of 16-bit integers INST3(psubb, "psubb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xF8), INS_TT_FULL_MEM, Input_8Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Subtract packed word (16-bit) integers INST3(psubd, "psubd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xFA), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Subtract packed double-word (32-bit) integers @@ -345,22 +345,22 @@ INST3(psubsw, "psubsw", IUM_WR, BAD_CODE, BAD_CODE, INST3(psubusb, "psubusb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xD8), INS_TT_FULL_MEM, Input_8Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Subtract packed unsigned 8-bit integers in b from packed unsigned 8-bit integers in a using saturation INST3(psubusw, "psubusw", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xD9), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Subtract packed unsigned 16-bit integers in b from packed unsigned 16-bit integers in a using saturation INST3(punpckhbw, "punpckhbw", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x68), INS_TT_FULL_MEM, Input_8Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed logical (unsigned) widen ubyte to ushort (hi) -INST3(punpckhdq, "punpckhdq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x6A), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) -INST3(punpckhqdq, "punpckhqdq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x6D), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed logical (unsigned) widen uint to ulong (hi) +INST3(punpckhdq, "punpckhdq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x6A), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) +INST3(punpckhqdq, "punpckhqdq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x6D), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed logical (unsigned) widen uint to ulong (hi) INST3(punpckhwd, "punpckhwd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x69), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed logical (unsigned) widen ushort to uint (hi) INST3(punpcklbw, "punpcklbw", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x60), INS_TT_FULL_MEM, Input_8Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed logical (unsigned) widen ubyte to ushort (lo) -INST3(punpckldq, "punpckldq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x62), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) -INST3(punpcklqdq, "punpcklqdq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x6C), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed logical (unsigned) widen uint to ulong (lo) +INST3(punpckldq, "punpckldq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x62), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) +INST3(punpcklqdq, "punpcklqdq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x6C), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed logical (unsigned) widen uint to ulong (lo) INST3(punpcklwd, "punpcklwd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x61), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed logical (unsigned) widen ushort to uint (lo) INST3(pxor, "pxor", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xEF), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed bit-wise XOR of two xmm regs -INST3(shufpd, "shufpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xC6), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) -INST3(sqrtpd, "sqrtpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x51), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX) // Sqrt of packed doubles +INST3(shufpd, "shufpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xC6), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) +INST3(sqrtpd, "sqrtpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x51), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Sqrt of packed doubles INST3(sqrtsd, "sqrtsd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x51), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Sqrt of scalar double INST3(subpd, "subpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x5C), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Subtract packed doubles INST3(subsd, "subsd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x5C), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Subtract scalar doubles INST3(ucomisd, "ucomisd", IUM_RD, BAD_CODE, BAD_CODE, PCKDBL(0x2E), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Writes_PF | Writes_CF) // unordered compare doubles -INST3(unpckhpd, "unpckhpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x15), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed logical (unsigned) widen ubyte to ushort (hi) -INST3(unpcklpd, "unpcklpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x14), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed logical (unsigned) widen ubyte to ushort (hi) +INST3(unpckhpd, "unpckhpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x15), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed logical (unsigned) widen ubyte to ushort (hi) +INST3(unpcklpd, "unpcklpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x14), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed logical (unsigned) widen ubyte to ushort (hi) INST3(xorpd, "xorpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x57), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // XOR packed doubles // SSE3 @@ -377,7 +377,7 @@ INST3(movsldup, "movsldup", IUM_WR, BAD_CODE, BAD_CODE, // SSSE3 INST3(pabsb, "pabsb", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x1C), INS_TT_FULL_MEM, Input_8Bit | REX_WIG | Encoding_VEX | Encoding_EVEX) // Packed absolute value of bytes -INST3(pabsd, "pabsd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x1E), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX) // Packed absolute value of 32-bit integers +INST3(pabsd, "pabsd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x1E), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Packed absolute value of 32-bit integers INST3(pabsw, "pabsw", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x1D), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX) // Packed absolute value of 16-bit integers INST3(palignr, "palignr", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x0F), INS_TT_FULL_MEM, REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed Align Right INST3(phaddd, "phaddd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x02), INS_TT_NONE, Input_32Bit | REX_WIG | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed horizontal add @@ -413,7 +413,7 @@ INST3(extractps, "extractps", IUM_WR, SSE3A(0x17), BAD_CODE, INST3(insertps, "insertps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x21), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Insert packed single precision float value INST3(movntdqa, "movntdqa", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x2A), INS_TT_FULL_MEM, REX_W0_EVEX | Encoding_VEX | Encoding_EVEX) // Load Double Quadword Non-Temporal Aligned Hint INST3(mpsadbw, "mpsadbw", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x42), INS_TT_NONE, Input_8Bit | REX_WIG | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // Compute Multiple Packed Sums of Absolute Difference -INST3(packusdw, "packusdw", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x2B), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Pack (narrow) int to unsigned short with saturation +INST3(packusdw, "packusdw", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x2B), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Pack (narrow) int to unsigned short with saturation INST3(pblendvb, "pblendvb", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x10), INS_TT_NONE, Input_8Bit | REX_W0) // Variable Blend Packed Bytes INST3(pblendw, "pblendw", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x0E), INS_TT_NONE, Input_16Bit | REX_WIG | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // Blend Packed Words INST3(pcmpeqq, "pcmpeqq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x29), INS_TT_NONE, Input_64Bit | REX_WIG | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed compare 64-bit integers for equality @@ -448,8 +448,8 @@ INST3(pmovzxwq, "pmovzxwq", IUM_WR, BAD_CODE, BAD_CODE, INST3(pmuldq, "pmuldq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x28), INS_TT_FULL, Input_32Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // packed multiply 32-bit signed integers and store 64-bit result INST3(pmulld, "pmulld", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x40), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed multiply 32 bit unsigned integers and store lower 32 bits of each result INST3(ptest, "ptest", IUM_RD, BAD_CODE, BAD_CODE, SSE38(0x17), INS_TT_NONE, REX_WIG | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF) // Packed logical compare -INST3(roundpd, "roundpd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x09), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX) // Round packed double precision floating-point values -INST3(roundps, "roundps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x08), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX) // Round packed single precision floating-point values +INST3(roundpd, "roundpd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x09), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Round packed double precision floating-point values +INST3(roundps, "roundps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x08), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Round packed single precision floating-point values INST3(roundsd, "roundsd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x0B), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Round scalar double precision floating-point values INST3(roundss, "roundss", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x0A), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Round scalar single precision floating-point values @@ -472,10 +472,10 @@ INST3(vmaskmovpd, "maskmovpd", IUM_WR, SSE38(0x2F), BAD_CODE, INST3(vmaskmovps, "maskmovps", IUM_WR, SSE38(0x2E), BAD_CODE, SSE38(0x2C), INS_TT_NONE, Input_32Bit | REX_W0 | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // Conditional SIMD Packed Single-Precision Floating-Point Loads and Stores INST3(vpblendvb, "pblendvb", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x4C), INS_TT_NONE, Input_8Bit | REX_W0 | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // Variable Blend Packed Bytes INST3(vperm2f128, "perm2f128", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x06), INS_TT_NONE, REX_W0 | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // Permute Floating-Point Values -INST3(vpermilpd, "permilpd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x05), INS_TT_FULL, Input_64Bit | REX_WX | Encoding_VEX | Encoding_EVEX) // Permute In-Lane of Quadruples of Double-Precision Floating-Point Values -INST3(vpermilpdvar, "permilpd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x0D), INS_TT_FULL, Input_64Bit | REX_WX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Permute In-Lane of Quadruples of Double-Precision Floating-Point Values -INST3(vpermilps, "permilps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x04), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX) // Permute In-Lane of Quadruples of Single-Precision Floating-Point Values -INST3(vpermilpsvar, "permilps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x0C), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Permute In-Lane of Quadruples of Single-Precision Floating-Point Values +INST3(vpermilpd, "permilpd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x05), INS_TT_FULL, Input_64Bit | REX_WX | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Permute In-Lane of Quadruples of Double-Precision Floating-Point Values +INST3(vpermilpdvar, "permilpd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x0D), INS_TT_FULL, Input_64Bit | REX_WX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Permute In-Lane of Quadruples of Double-Precision Floating-Point Values +INST3(vpermilps, "permilps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x04), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Permute In-Lane of Quadruples of Single-Precision Floating-Point Values +INST3(vpermilpsvar, "permilps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x0C), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Permute In-Lane of Quadruples of Single-Precision Floating-Point Values INST3(vtestpd, "testpd", IUM_RD, BAD_CODE, BAD_CODE, SSE38(0x0F), INS_TT_NONE, Input_64Bit | REX_W0 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF) // Packed Bit Test INST3(vtestps, "testps", IUM_RD, BAD_CODE, BAD_CODE, SSE38(0x0E), INS_TT_NONE, Input_32Bit | REX_W0 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF) // Packed Bit Test INST3(vzeroupper, "zeroupper", IUM_WR, 0xC577F8, BAD_CODE, BAD_CODE, INS_TT_NONE, REX_WIG | Encoding_VEX) // Zero upper 128-bits of all YMM regs (includes 2-byte fixed VEX prefix) @@ -494,10 +494,10 @@ INST3(vpbroadcastd, "pbroadcastd", IUM_WR, BAD_CODE, BAD_CODE, INST3(vpbroadcastq, "pbroadcastq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x59), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_WX | Encoding_VEX | Encoding_EVEX) // Broadcast int64 value from reg/memory to entire ymm register INST3(vpbroadcastw, "pbroadcastw", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x79), INS_TT_TUPLE1_SCALAR, Input_16Bit | REX_W0 | Encoding_VEX | Encoding_EVEX) // Broadcast int16 value from reg/memory to entire ymm register INST3(vperm2i128, "perm2i128", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x46), INS_TT_NONE, REX_W0 | Encoding_VEX | INS_Flags_IsDstDstSrcAVXInstruction) // Permute 128-bit halves of input register -INST3(vpermd, "permd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x36), INS_TT_FULL, Input_64Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Permute Packed Doublewords Elements -INST3(vpermpd, "permpd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x01), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX) // Permute Double-Precision Floating-Point Values -INST3(vpermps, "permps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x16), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Permute Single-Precision Floating-Point Elements -INST3(vpermq, "permq", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x00), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX) // Permute 64-bit of input register +INST3(vpermd, "permd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x36), INS_TT_FULL, Input_64Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Permute Packed Doublewords Elements +INST3(vpermpd, "permpd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x01), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Permute Double-Precision Floating-Point Values +INST3(vpermps, "permps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x16), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Permute Single-Precision Floating-Point Elements +INST3(vpermq, "permq", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x00), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Permute 64-bit of input register INST3(vpgatherdd, "pgatherdd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x90), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Gather Packed Dword Values Using Signed Dword INST3(vpgatherdq, "pgatherdq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x90), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Gather Packed Dword with Signed Dword Indices INST3(vpgatherqd, "pgatherqd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x91), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Gather Packed Dword Values Using Signed Qword @@ -512,60 +512,60 @@ INST3(vpsrlvq, "psrlvq", IUM_WR, BAD_CODE, BAD_CODE, INST3(FIRST_FMA_INSTRUCTION, "FIRST_FMA_INSTRUCTION", IUM_WR, BAD_CODE, BAD_CODE, BAD_CODE, INS_TT_NONE, INS_FLAGS_None) // id nm um mr mi rm flags -INST3(vfmadd132pd, "fmadd132pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x98), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Multiply-Add of Packed Double-Precision Floating-Point Values -INST3(vfmadd213pd, "fmadd213pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xA8), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmadd231pd, "fmadd231pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xB8), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmadd132ps, "fmadd132ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x98), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Multiply-Add of Packed Single-Precision Floating-Point Values -INST3(vfmadd213ps, "fmadd213ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xA8), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmadd231ps, "fmadd231ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xB8), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // +INST3(vfmadd132pd, "fmadd132pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x98), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Fused Multiply-Add of Packed Double-Precision Floating-Point Values +INST3(vfmadd213pd, "fmadd213pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xA8), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfmadd231pd, "fmadd231pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xB8), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfmadd132ps, "fmadd132ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x98), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Fused Multiply-Add of Packed Single-Precision Floating-Point Values +INST3(vfmadd213ps, "fmadd213ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xA8), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfmadd231ps, "fmadd231ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xB8), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // INST3(vfmadd132sd, "fmadd132sd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x99), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values INST3(vfmadd213sd, "fmadd213sd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xA9), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // INST3(vfmadd231sd, "fmadd231sd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xB9), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // INST3(vfmadd132ss, "fmadd132ss", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x99), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values INST3(vfmadd213ss, "fmadd213ss", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xA9), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // INST3(vfmadd231ss, "fmadd231ss", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xB9), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmaddsub132pd, "fmaddsub132pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x96), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values -INST3(vfmaddsub213pd, "fmaddsub213pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xA6), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmaddsub231pd, "fmaddsub231pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xB6), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmaddsub132ps, "fmaddsub132ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x96), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values -INST3(vfmaddsub213ps, "fmaddsub213ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xA6), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmaddsub231ps, "fmaddsub231ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xB6), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmsubadd132pd, "fmsubadd132pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x97), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values -INST3(vfmsubadd213pd, "fmsubadd213pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xA7), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmsubadd231pd, "fmsubadd231pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xB7), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmsubadd132ps, "fmsubadd132ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x97), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values -INST3(vfmsubadd213ps, "fmsubadd213ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xA7), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmsubadd231ps, "fmsubadd231ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xB7), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmsub132pd, "fmsub132pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9A), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values -INST3(vfmsub213pd, "fmsub213pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAA), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmsub231pd, "fmsub231pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBA), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmsub132ps, "fmsub132ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9A), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values -INST3(vfmsub213ps, "fmsub213ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAA), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfmsub231ps, "fmsub231ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBA), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // +INST3(vfmaddsub132pd, "fmaddsub132pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x96), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values +INST3(vfmaddsub213pd, "fmaddsub213pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xA6), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfmaddsub231pd, "fmaddsub231pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xB6), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfmaddsub132ps, "fmaddsub132ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x96), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values +INST3(vfmaddsub213ps, "fmaddsub213ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xA6), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfmaddsub231ps, "fmaddsub231ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xB6), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfmsubadd132pd, "fmsubadd132pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x97), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values +INST3(vfmsubadd213pd, "fmsubadd213pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xA7), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfmsubadd231pd, "fmsubadd231pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xB7), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfmsubadd132ps, "fmsubadd132ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x97), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values +INST3(vfmsubadd213ps, "fmsubadd213ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xA7), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfmsubadd231ps, "fmsubadd231ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xB7), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfmsub132pd, "fmsub132pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9A), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values +INST3(vfmsub213pd, "fmsub213pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAA), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfmsub231pd, "fmsub231pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBA), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfmsub132ps, "fmsub132ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9A), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values +INST3(vfmsub213ps, "fmsub213ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAA), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfmsub231ps, "fmsub231ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBA), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // INST3(vfmsub132sd, "fmsub132sd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9B), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values INST3(vfmsub213sd, "fmsub213sd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAB), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // INST3(vfmsub231sd, "fmsub231sd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBB), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // INST3(vfmsub132ss, "fmsub132ss", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9B), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values INST3(vfmsub213ss, "fmsub213ss", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAB), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // INST3(vfmsub231ss, "fmsub231ss", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBB), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfnmadd132pd, "fnmadd132pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9C), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values -INST3(vfnmadd213pd, "fnmadd213pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAC), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfnmadd231pd, "fnmadd231pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBC), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfnmadd132ps, "fnmadd132ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9C), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values -INST3(vfnmadd213ps, "fnmadd213ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAC), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfnmadd231ps, "fnmadd231ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBC), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // +INST3(vfnmadd132pd, "fnmadd132pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9C), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values +INST3(vfnmadd213pd, "fnmadd213pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAC), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfnmadd231pd, "fnmadd231pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBC), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfnmadd132ps, "fnmadd132ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9C), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values +INST3(vfnmadd213ps, "fnmadd213ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAC), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfnmadd231ps, "fnmadd231ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBC), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // INST3(vfnmadd132sd, "fnmadd132sd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9D), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values INST3(vfnmadd213sd, "fnmadd213sd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAD), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // INST3(vfnmadd231sd, "fnmadd231sd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBD), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // INST3(vfnmadd132ss, "fnmadd132ss", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9D), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values INST3(vfnmadd213ss, "fnmadd213ss", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAD), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // INST3(vfnmadd231ss, "fnmadd231ss", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBD), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfnmsub132pd, "fnmsub132pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9E), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values -INST3(vfnmsub213pd, "fnmsub213pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAE), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfnmsub231pd, "fnmsub231pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBE), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfnmsub132ps, "fnmsub132ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9E), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values -INST3(vfnmsub213ps, "fnmsub213ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAE), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // -INST3(vfnmsub231ps, "fnmsub231ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBE), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // +INST3(vfnmsub132pd, "fnmsub132pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9E), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values +INST3(vfnmsub213pd, "fnmsub213pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAE), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfnmsub231pd, "fnmsub231pd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBE), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfnmsub132ps, "fnmsub132ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9E), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values +INST3(vfnmsub213ps, "fnmsub213ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAE), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // +INST3(vfnmsub231ps, "fnmsub231ps", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBE), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // INST3(vfnmsub132sd, "fnmsub132sd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0x9F), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values INST3(vfnmsub213sd, "fnmsub213sd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xAF), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // INST3(vfnmsub231sd, "fnmsub231sd", IUM_RW, BAD_CODE, BAD_CODE, SSE38(0xBF), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // @@ -610,85 +610,85 @@ INST3(LAST_AVX_INSTRUCTION, "LAST_AVX_INSTRUCTION", IUM_WR, BAD_CODE, BAD_CODE, INST3(FIRST_AVX512_INSTRUCTION, "FIRST_AVX512_INSTRUCTION", IUM_WR, BAD_CODE, BAD_CODE, BAD_CODE, INS_TT_NONE, INS_FLAGS_None) // AVX512F -INST3(kandw, "kandw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x41), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical AND masks -INST3(kandnw, "kandnw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x42), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical AND NOT masks -INST3(kmovw_gpr, "kmovw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers -INST3(kmovw_msk, "kmovw", IUM_WR, PCKFLT(0x91), BAD_CODE, PCKFLT(0x90), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers -INST3(knotw, "knotw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x44), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // NOT mask register -INST3(korw, "korw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x45), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical OR masks -INST3(kortestw, "kortestw", IUM_RD, BAD_CODE, BAD_CODE, PCKFLT(0x98), INS_TT_NONE, REX_W0 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // OR masks and set flags -INST3(kshiftlw, "kshiftlw", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x32), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Shift left mask registers -INST3(kshiftrw, "kshiftrw", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x30), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Shift right mask registers -INST3(kunpckbw, "kunpckbw", IUM_RD, BAD_CODE, BAD_CODE, PCKDBL(0x4B), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Unpack for mask registers -INST3(kxnorw, "kxnorw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x46), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical XNOR masks -INST3(kxorw, "kxorw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x47), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical XOR masks -INST3(valignd, "alignd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x03), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Align doubleword vectors -INST3(valignq, "alignq", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x03), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Align quadword vectors -INST3(vblendmpd, "blendmpd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x65), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Blend Float64 vectors using an OpMask control -INST3(vblendmps, "blendmps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x65), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Blend Float32 vectors using an OpMask control -INST3(vpblendmq, "pblendmq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x64), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Blend Int32 vectors using an OpMask control +INST3(kandw, "kandw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x41), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical AND masks +INST3(kandnw, "kandnw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x42), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical AND NOT masks +INST3(kmovw_gpr, "kmovw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers +INST3(kmovw_msk, "kmovw", IUM_WR, PCKFLT(0x91), BAD_CODE, PCKFLT(0x90), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers +INST3(knotw, "knotw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x44), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // NOT mask register +INST3(korw, "korw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x45), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical OR masks +INST3(kortestw, "kortestw", IUM_RD, BAD_CODE, BAD_CODE, PCKFLT(0x98), INS_TT_NONE, REX_W0 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // OR masks and set flags +INST3(kshiftlw, "kshiftlw", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x32), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Shift left mask registers +INST3(kshiftrw, "kshiftrw", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x30), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Shift right mask registers +INST3(kunpckbw, "kunpckbw", IUM_RD, BAD_CODE, BAD_CODE, PCKDBL(0x4B), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Unpack for mask registers +INST3(kxnorw, "kxnorw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x46), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical XNOR masks +INST3(kxorw, "kxorw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x47), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical XOR masks +INST3(valignd, "alignd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x03), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Align doubleword vectors +INST3(valignq, "alignq", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x03), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Align quadword vectors +INST3(vblendmpd, "blendmpd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x65), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Blend Float64 vectors using an OpMask control +INST3(vblendmps, "blendmps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x65), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Blend Float32 vectors using an OpMask control +INST3(vpblendmq, "pblendmq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x64), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Blend Int32 vectors using an OpMask control INST3(vpblendmb, "pblendmb", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x66), INS_TT_FULL_MEM, Input_8Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Blend Int64 vectors using an OpMask control INST3(vbroadcastf64x2, "broadcastf64x2", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x1A), INS_TT_TUPLE2, Input_64Bit | REX_W1 | Encoding_EVEX) // Broadcast packed float values read from memory to entire register INST3(vbroadcasti64x2, "broadcasti64x2", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x5A), INS_TT_TUPLE2, Input_64Bit | REX_W1 | Encoding_EVEX) // Broadcast packed integer values read from memory to entire register INST3(vbroadcastf64x4, "broadcastf64x4", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x1B), INS_TT_TUPLE2, Input_64Bit | REX_W1 | Encoding_EVEX) // Broadcast packed float values read from memory to entire register INST3(vbroadcasti64x4, "broadcasti64x4", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x5B), INS_TT_TUPLE2, Input_64Bit | REX_W1 | Encoding_EVEX) // Broadcast packed integer values read from memory to entire register -INST3(vcmpps, "cmpps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0xC2), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // compare packed singles -INST3(vcmpss, "cmpss", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0xC2), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // compare scalar singles -INST3(vcmppd, "cmppd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xC2), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // compare packed doubles -INST3(vcmpsd, "cmpsd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0xC2), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // compare scalar doubles -INST3(vcvtpd2udq, "cvtpd2udq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x79), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // cvt packed doubles to unsigned DWORDs -INST3(vcvtps2udq, "cvtps2udq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x79), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX) // cvt packed singles to unsigned DWORDs +INST3(vcmpps, "cmpps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0xC2), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // compare packed singles +INST3(vcmpss, "cmpss", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0xC2), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // compare scalar singles +INST3(vcmppd, "cmppd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xC2), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // compare packed doubles +INST3(vcmpsd, "cmpsd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0xC2), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // compare scalar doubles +INST3(vcvtpd2udq, "cvtpd2udq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x79), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed doubles to unsigned DWORDs +INST3(vcvtps2udq, "cvtps2udq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x79), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed singles to unsigned DWORDs INST3(vcvtsd2usi, "cvtsd2usi", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x79), INS_TT_TUPLE1_FIXED, Input_64Bit | REX_WX | Encoding_EVEX) // cvt scalar double to unsigned DWORD/QWORD INST3(vcvtss2usi, "cvtss2usi", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x79), INS_TT_TUPLE1_FIXED, Input_32Bit | REX_WX | Encoding_EVEX) // cvt scalar single to unsigned DWORD/QWORD -INST3(vcvttpd2udq, "cvttpd2udq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x78), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // cvt w/ truncation packed doubles to unsigned DWORDs -INST3(vcvttps2udq, "cvttps2udq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x78), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX) // cvt w/ truncation packed singles to unsigned DWORDs +INST3(vcvttpd2udq, "cvttpd2udq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x78), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt w/ truncation packed doubles to unsigned DWORDs +INST3(vcvttps2udq, "cvttps2udq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x78), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt w/ truncation packed singles to unsigned DWORDs INST3(vcvttsd2usi32, "cvttsd2usi", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x78), INS_TT_TUPLE1_FIXED, Input_64Bit | REX_W0 | Encoding_EVEX) // cvt w/ truncation scalar double to unsigned DWORD INST3(vcvttsd2usi64, "cvttsd2usi", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x78), INS_TT_TUPLE1_FIXED, Input_64Bit | REX_W1 | Encoding_EVEX) // cvt w/ truncation scalar double to unsigned QWORD INST3(vcvttss2usi32, "cvttss2usi", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x78), INS_TT_TUPLE1_FIXED, Input_32Bit | REX_W0 | Encoding_EVEX) // cvt w/ truncation scalar single to unsigned DWORD/QWORD INST3(vcvttss2usi64, "cvttss2usi", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x78), INS_TT_TUPLE1_FIXED, Input_32Bit | REX_W1 | Encoding_EVEX) // cvt w/ truncation scalar single to unsigned DWORD/QWORD -INST3(vcvtudq2pd, "cvtudq2pd", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x7A), INS_TT_HALF, Input_32Bit | REX_W0 | Encoding_EVEX) // cvt packed unsigned DWORDs to doubles -INST3(vcvtudq2ps, "cvtudq2ps", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x7A), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX) // cvt packed unsigned DWORDs to singles +INST3(vcvtudq2pd, "cvtudq2pd", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x7A), INS_TT_HALF, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed unsigned DWORDs to doubles +INST3(vcvtudq2ps, "cvtudq2ps", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x7A), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed unsigned DWORDs to singles INST3(vcvtusi2sd32, "cvtusi2sd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x7B), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // cvt scalar unsigned DWORD to double INST3(vcvtusi2sd64, "cvtusi2sd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x7B), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // cvt scalar unsigned QWORD to double INST3(vcvtusi2ss32, "cvtusi2ss", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x7B), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // cvt scalar unsigned DWORD to single INST3(vcvtusi2ss64, "cvtusi2ss", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x7B), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // cvt scalar unsigned QWORD to single INST3(vextractf64x4, "extractf64x4", IUM_WR, SSE3A(0x1B), BAD_CODE, BAD_CODE, INS_TT_TUPLE4, Input_64Bit | REX_W1 | Encoding_EVEX) // Extract 256-bit packed double-precision floating point values INST3(vextracti64x4, "extracti64x4", IUM_WR, SSE3A(0x3B), BAD_CODE, BAD_CODE, INS_TT_TUPLE4, Input_64Bit | REX_W1 | Encoding_EVEX) // Extract 256-bit packed quadword integer values -INST3(vfixupimmpd, "fixupimmpd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x54), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fixup special packed double-precision floating-point values -INST3(vfixupimmps, "fixupimmps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x54), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fixup special packed single-precision floating-point values +INST3(vfixupimmpd, "fixupimmpd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x54), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Fixup special packed double-precision floating-point values +INST3(vfixupimmps, "fixupimmps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x54), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Fixup special packed single-precision floating-point values INST3(vfixupimmsd, "fixupimmsd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x55), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fixup special scalar double-precision floating-point value INST3(vfixupimmss, "fixupimmss", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x55), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Fixup special scalar single-precision floating-point value -INST3(vgetexppd, "getexppd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x42), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // Extract exponents of packed double-precision floating-point values -INST3(vgetexpps, "getexpps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x42), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX) // Extract exponents of packed single-precision floating-point values +INST3(vgetexppd, "getexppd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x42), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Extract exponents of packed double-precision floating-point values +INST3(vgetexpps, "getexpps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x42), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Extract exponents of packed single-precision floating-point values INST3(vgetexpsd, "getexpsd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x43), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Extract exponents of scalar double-precision floating-point value INST3(vgetexpss, "getexpss", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x43), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Extract exponents of scalar single-precision floating-point value -INST3(vgetmantpd, "getmantpd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x26), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // Extract mantissas of packed double-precision floating-point values -INST3(vgetmantps, "getmantps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x26), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX) // Extract mantissas of packed single-precision floating-point values +INST3(vgetmantpd, "getmantpd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x26), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Extract mantissas of packed double-precision floating-point values +INST3(vgetmantps, "getmantps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x26), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Extract mantissas of packed single-precision floating-point values INST3(vgetmantsd, "getmantsd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x27), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Extract mantissas of scalar double-precision floating-point value INST3(vgetmantss, "getmantss", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x27), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Extract mantissas of scalar single-precision floating-point value INST3(vinsertf64x4, "insertf64x4", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x1A), INS_TT_TUPLE4, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Insert 256-bit packed double-precision floating point values INST3(vinserti64x4, "inserti64x4", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x3A), INS_TT_TUPLE4, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Insert 256-bit packed quadword integer values INST3(vmovdqa64, "movdqa64", IUM_WR, PCKDBL(0x7F), BAD_CODE, PCKDBL(0x6F), INS_TT_FULL_MEM, Input_64Bit | REX_W1 | Encoding_EVEX) INST3(vmovdqu64, "movdqu64", IUM_WR, SSEFLT(0x7F), BAD_CODE, SSEFLT(0x6F), INS_TT_FULL_MEM, Input_64Bit | REX_W1 | Encoding_EVEX) -INST3(vpabsq, "pabsq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x1F), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // Packed absolute value of 64-bit integers +INST3(vpabsq, "pabsq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x1F), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Packed absolute value of 64-bit integers INST3(vpandq, "pandq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xDB), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed bit-wise AND of two xmm regs INST3(vpandnq, "pandnq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xDF), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed bit-wise AND NOT of two xmm regs INST3(vpbroadcastd_gpr, "pbroadcastd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x7C), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX) // Broadcast int32 value from gpr to entire register INST3(vpbroadcastq_gpr, "pbroadcastq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x7C), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX) // Broadcast int64 value from gpr to entire register -INST3(vpcmpeqd, "pcmpeqd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x76), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed compare 32-bit integers for equality -INST3(vpcmpgtd, "pcmpgtd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x66), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed compare 32-bit signed integers for greater than -INST3(vpcmpeqq, "pcmpeqq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x29), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed compare 64-bit integers for equality -INST3(vpcmpgtq, "pcmpgtq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x37), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed compare 64-bit integers for equality -INST3(vpermq_reg, "permq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x36), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Permute 64-bit of input register -INST3(vpermpd_reg, "permpd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x16), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Permute 64-bit of input register -INST3(vpermi2d, "permi2d", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x76), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Full Permute From Two Tables Overwriting the Index -INST3(vpermi2pd, "permi2pd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x77), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Full Permute From Two Tables Overwriting the Index -INST3(vpermi2ps, "permi2ps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x77), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Full Permute From Two Tables Overwriting the Index -INST3(vpermi2q, "permi2q", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x76), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Full Permute From Two Tables Overwriting the Index -INST3(vpermt2d, "permt2d", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x7E), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Full Permute From Two Tables Overwriting one Table -INST3(vpermt2pd, "permt2pd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x7F), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Full Permute From Two Tables Overwriting one Table -INST3(vpermt2ps, "permt2ps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x7F), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Full Permute From Two Tables Overwriting one Table -INST3(vpermt2q, "permt2q", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x7E), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Full Permute From Two Tables Overwriting one Table +INST3(vpcmpeqd, "pcmpeqd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x76), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed compare 32-bit integers for equality +INST3(vpcmpgtd, "pcmpgtd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x66), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed compare 32-bit signed integers for greater than +INST3(vpcmpeqq, "pcmpeqq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x29), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed compare 64-bit integers for equality +INST3(vpcmpgtq, "pcmpgtq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x37), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed compare 64-bit integers for equality +INST3(vpermq_reg, "permq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x36), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Permute 64-bit of input register +INST3(vpermpd_reg, "permpd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x16), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Permute 64-bit of input register +INST3(vpermi2d, "permi2d", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x76), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Full Permute From Two Tables Overwriting the Index +INST3(vpermi2pd, "permi2pd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x77), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Full Permute From Two Tables Overwriting the Index +INST3(vpermi2ps, "permi2ps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x77), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Full Permute From Two Tables Overwriting the Index +INST3(vpermi2q, "permi2q", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x76), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Full Permute From Two Tables Overwriting the Index +INST3(vpermt2d, "permt2d", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x7E), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Full Permute From Two Tables Overwriting one Table +INST3(vpermt2pd, "permt2pd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x7F), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Full Permute From Two Tables Overwriting one Table +INST3(vpermt2ps, "permt2ps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x7F), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Full Permute From Two Tables Overwriting one Table +INST3(vpermt2q, "permt2q", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x7E), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Full Permute From Two Tables Overwriting one Table INST3(vpmaxsq, "pmaxsq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x3D), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // packed maximum 64-bit signed integers INST3(vpmaxuq, "pmaxuq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x3F), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // packed maximum 64-bit unsigned integers INST3(vpminsq, "pminsq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x39), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // packed minimum 64-bit signed integers @@ -709,82 +709,82 @@ INST3(vpmovusqb, "pmovusqb", IUM_WR, PSSE38(0xF3, 0x12), BAD_ INST3(vpmovusqd, "pmovusqd", IUM_WR, PSSE38(0xF3, 0x15), BAD_CODE, PSSE38(0xF3, 0x15), INS_TT_HALF_MEM, Input_64Bit | REX_W0 | Encoding_EVEX) INST3(vpmovusqw, "pmovusqw", IUM_WR, PSSE38(0xF3, 0x14), BAD_CODE, PSSE38(0xF3, 0x14), INS_TT_QUARTER_MEM, Input_64Bit | REX_W0 | Encoding_EVEX) INST3(vporq, "porq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xEB), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed bit-wise OR of two xmm regs -INST3(vprold, "prold", IUM_WR, BAD_CODE, PCKDBL(0x72), BAD_CODE, INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Bit rotate left -INST3(vprolq, "prolq", IUM_WR, BAD_CODE, PCKDBL(0x72), BAD_CODE, INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Bit rotate left -INST3(vprolvd, "prolvd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x15), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Bit rotate left -INST3(vprolvq, "prolvq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x15), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Bit rotate left -INST3(vprord, "prord", IUM_WR, BAD_CODE, PCKDBL(0x72), BAD_CODE, INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Bit rotate right -INST3(vprorq, "prorq", IUM_WR, BAD_CODE, PCKDBL(0x72), BAD_CODE, INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Bit rotate right -INST3(vprorvd, "prorvd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x14), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Bit rotate right -INST3(vprorvq, "prorvq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x14), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Bit rotate right -INST3(vpsraq, "psraq", IUM_WR, BAD_CODE, PCKDBL(0x72), PCKDBL(0xE2), INS_TT_FULL | INS_TT_MEM128, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed shift right arithmetic of 64-bit integers +INST3(vprold, "prold", IUM_WR, BAD_CODE, PCKDBL(0x72), BAD_CODE, INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Bit rotate left +INST3(vprolq, "prolq", IUM_WR, BAD_CODE, PCKDBL(0x72), BAD_CODE, INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Bit rotate left +INST3(vprolvd, "prolvd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x15), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Bit rotate left +INST3(vprolvq, "prolvq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x15), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Bit rotate left +INST3(vprord, "prord", IUM_WR, BAD_CODE, PCKDBL(0x72), BAD_CODE, INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Bit rotate right +INST3(vprorq, "prorq", IUM_WR, BAD_CODE, PCKDBL(0x72), BAD_CODE, INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Bit rotate right +INST3(vprorvd, "prorvd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x14), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Bit rotate right +INST3(vprorvq, "prorvq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x14), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Bit rotate right +INST3(vpsraq, "psraq", IUM_WR, BAD_CODE, PCKDBL(0x72), PCKDBL(0xE2), INS_TT_FULL | INS_TT_MEM128, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed shift right arithmetic of 64-bit integers INST3(vpsravq, "psravq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x46), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Variable Bit Shift Right Arithmetic -INST3(vpternlogd, "pternlogd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x25), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Bitwise Ternary Logic -INST3(vpternlogq, "pternlogq", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x25), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Bitwise Ternary Logic -INST3(vptestmd, "ptestmd", IUM_RD, BAD_CODE, BAD_CODE, SSE38(0x27), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Logical AND and set mask -INST3(vptestmq, "ptestmq", IUM_RD, BAD_CODE, BAD_CODE, SSE38(0x27), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Logical AND and set mask -INST3(vptestnmd, "ptestnmd", IUM_RD, BAD_CODE, BAD_CODE, PSSE38(0xF3, 0x27), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Logical NAND and set mask -INST3(vptestnmq, "ptestnmq", IUM_RD, BAD_CODE, BAD_CODE, PSSE38(0xF3, 0x27), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Logical NAND and set mask +INST3(vpternlogd, "pternlogd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x25), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Bitwise Ternary Logic +INST3(vpternlogq, "pternlogq", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x25), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Bitwise Ternary Logic +INST3(vptestmd, "ptestmd", IUM_RD, BAD_CODE, BAD_CODE, SSE38(0x27), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Logical AND and set mask +INST3(vptestmq, "ptestmq", IUM_RD, BAD_CODE, BAD_CODE, SSE38(0x27), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Logical AND and set mask +INST3(vptestnmd, "ptestnmd", IUM_RD, BAD_CODE, BAD_CODE, PSSE38(0xF3, 0x27), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Logical NAND and set mask +INST3(vptestnmq, "ptestnmq", IUM_RD, BAD_CODE, BAD_CODE, PSSE38(0xF3, 0x27), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Logical NAND and set mask INST3(vpxorq, "pxorq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xEF), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Packed bit-wise XOR of two xmm regs -INST3(vrangepd, "rangepd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x50), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Range restriction calculation from a pair of packed double-precision floating-point values -INST3(vrangeps, "rangeps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x50), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Range restriction calculation from a pair of packed single-precision floating-point values +INST3(vrangepd, "rangepd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x50), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Range restriction calculation from a pair of packed double-precision floating-point values +INST3(vrangeps, "rangeps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x50), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Range restriction calculation from a pair of packed single-precision floating-point values INST3(vrangesd, "rangesd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x51), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Range restriction calculation from a pair of scalar double-precision floating-point value INST3(vrangess, "rangess", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x51), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Range restriction calculation from a pair of scalar single-precision floating-point value -INST3(vrcp14pd, "rcp14pd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x4C), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // Compute approximate reciprocals of packed double-precision floating-point values -INST3(vrcp14ps, "rcp14ps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x4C), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX) // Compute approximate reciprocals of packed single-precision floating-point values +INST3(vrcp14pd, "rcp14pd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x4C), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Compute approximate reciprocals of packed double-precision floating-point values +INST3(vrcp14ps, "rcp14ps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x4C), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Compute approximate reciprocals of packed single-precision floating-point values INST3(vrcp14sd, "rcp14sd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x4D), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Compute approximate reciprocals of scalar double-precision floating-point value INST3(vrcp14ss, "rcp14ss", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x4D), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Compute approximate reciprocals of scalar single-precision floating-point value -INST3(vreducepd, "reducepd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x56), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // Perform a reduction transformation on packed double-precision floating-point values -INST3(vreduceps, "reduceps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x56), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX) // Perform a reduction transformation on packed single-precision floating-point values +INST3(vreducepd, "reducepd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x56), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Perform a reduction transformation on packed double-precision floating-point values +INST3(vreduceps, "reduceps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x56), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Perform a reduction transformation on packed single-precision floating-point values INST3(vreducesd, "reducesd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x57), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Perform a reduction transformation on scalar double-precision floating-point value INST3(vreducess, "reducess", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x57), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Perform a reduction transformation on scalar single-precision floating-point value -INST3(vrndscalepd, "rndscalepd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x09), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // Round packed double-precision floating-point values to include a given number of fraction bits -INST3(vrndscaleps, "rndscaleps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x08), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX) // Round packed single-precision floating-point values to include a given number of fraction bits +INST3(vrndscalepd, "rndscalepd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x09), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Round packed double-precision floating-point values to include a given number of fraction bits +INST3(vrndscaleps, "rndscaleps", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x08), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Round packed single-precision floating-point values to include a given number of fraction bits INST3(vrndscalesd, "rndscalesd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x0B), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Round scalar double-precision floating-point value to include a given number of fraction bits INST3(vrndscaless, "rndscaless", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x0A), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Round scalar single-precision floating-point value to include a given number of fraction bits -INST3(vrsqrt14pd, "rsqrt14pd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x4E), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // Compute approximate reciprocals of square roots of packed double-precision floating-point values -INST3(vrsqrt14ps, "rsqrt14ps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x4E), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX) // Compute approximate reciprocals of square roots of packed single-precision floating-point values +INST3(vrsqrt14pd, "rsqrt14pd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x4E), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Compute approximate reciprocals of square roots of packed double-precision floating-point values +INST3(vrsqrt14ps, "rsqrt14ps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x4E), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Compute approximate reciprocals of square roots of packed single-precision floating-point values INST3(vrsqrt14sd, "rsqrt14sd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x4F), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Compute approximate reciprocals of square roots of scalar double-precision floating-point value INST3(vrsqrt14ss, "rsqrt14ss", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x4F), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Compute approximate reciprocals of square roots of scalar single-precision floating-point value -INST3(vscalefpd, "scalefpd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x2C), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Scale packed double-precision floating-point values -INST3(vscalefps, "scalefps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x2C), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Scale packed single-precision floating-point values +INST3(vscalefpd, "scalefpd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x2C), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Scale packed double-precision floating-point values +INST3(vscalefps, "scalefps", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x2C), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Scale packed single-precision floating-point values INST3(vscalefsd, "scalefsd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x2D), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Scale scalar double-precision floating-point value INST3(vscalefss, "scalefss", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x2D), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Scale scalar single-precision floating-point value -INST3(vshuff32x4, "shuff32x4", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x23), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Shuffle packed values at 128-bit granularity -INST3(vshuff64x2, "shuff64x2", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x23), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Shuffle packed values at 128-bit granularity -INST3(vshufi32x4, "shufi32x4", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x43), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Shuffle packed values at 128-bit granularity -INST3(vshufi64x2, "shufi64x2", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x43), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Shuffle packed values at 128-bit granularity +INST3(vshuff32x4, "shuff32x4", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x23), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Shuffle packed values at 128-bit granularity +INST3(vshuff64x2, "shuff64x2", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x23), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Shuffle packed values at 128-bit granularity +INST3(vshufi32x4, "shufi32x4", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x43), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Shuffle packed values at 128-bit granularity +INST3(vshufi64x2, "shufi64x2", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x43), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Shuffle packed values at 128-bit granularity // AVX512BW -INST3(kaddd, "kaddd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x4A), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Add two masks -INST3(kaddq, "kaddq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x4A), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Add two masks -INST3(kandd, "kandd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x41), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical AND masks -INST3(kandq, "kandq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x41), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical AND masks -INST3(kandnd, "kandnd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x42), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical AND NOT masks -INST3(kandnq, "kandnq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x42), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical AND NOT masks -INST3(kmovd_gpr, "kmovd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers -INST3(kmovd_msk, "kmovd", IUM_WR, PCKDBL(0x91), BAD_CODE, PCKDBL(0x90), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Move from and to mask registers -INST3(kmovq_gpr, "kmovq", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x92), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Move from and to mask registers -INST3(kmovq_msk, "kmovq", IUM_WR, PCKFLT(0x91), BAD_CODE, PCKFLT(0x90), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Move from and to mask registers -INST3(knotd, "knotd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x44), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // NOT mask register -INST3(knotq, "knotq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x44), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // NOT mask register -INST3(kord, "kord", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x45), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical OR masks -INST3(korq, "korq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x45), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical OR masks -INST3(kortestd, "kortestd", IUM_RD, BAD_CODE, BAD_CODE, PCKDBL(0x98), INS_TT_NONE, REX_W1 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // OR masks and set flags -INST3(kortestq, "kortestq", IUM_RD, BAD_CODE, BAD_CODE, PCKFLT(0x98), INS_TT_NONE, REX_W1 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // OR masks and set flags -INST3(kshiftld, "kshiftld", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x33), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Shift left mask registers -INST3(kshiftlq, "kshiftlq", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x33), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Shift left mask registers -INST3(kshiftrd, "kshiftrd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x31), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Shift right mask registers -INST3(kshiftrq, "kshiftrq", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x31), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Shift right mask registers -INST3(ktestd, "ktestd", IUM_RD, BAD_CODE, BAD_CODE, PCKDBL(0x99), INS_TT_NONE, REX_W1 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // Packed bit test masks and set flags -INST3(ktestq, "ktestq", IUM_RD, BAD_CODE, BAD_CODE, PCKFLT(0x99), INS_TT_NONE, REX_W1 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // Packed bit test masks and set flags -INST3(kunpckdq, "kunpckdq", IUM_RD, BAD_CODE, BAD_CODE, PCKFLT(0x4B), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Unpack for mask registers -INST3(kunpckwd, "kunpckwd", IUM_RD, BAD_CODE, BAD_CODE, PCKFLT(0x4B), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Unpack for mask registers -INST3(kxnord, "kxnord", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x46), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical XNOR masks -INST3(kxnorq, "kxnorq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x46), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical XNOR masks -INST3(kxord, "kxord", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x47), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical XOR masks -INST3(kxorq, "kxorq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x47), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical XOR masks -INST3(vpblendmd, "pblendmd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x64), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Blend Byte vectors using an OpMask control +INST3(kaddd, "kaddd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x4A), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Add two masks +INST3(kaddq, "kaddq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x4A), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Add two masks +INST3(kandd, "kandd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x41), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical AND masks +INST3(kandq, "kandq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x41), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical AND masks +INST3(kandnd, "kandnd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x42), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical AND NOT masks +INST3(kandnq, "kandnq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x42), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical AND NOT masks +INST3(kmovd_gpr, "kmovd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers +INST3(kmovd_msk, "kmovd", IUM_WR, PCKDBL(0x91), BAD_CODE, PCKDBL(0x90), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Move from and to mask registers +INST3(kmovq_gpr, "kmovq", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x92), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Move from and to mask registers +INST3(kmovq_msk, "kmovq", IUM_WR, PCKFLT(0x91), BAD_CODE, PCKFLT(0x90), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Move from and to mask registers +INST3(knotd, "knotd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x44), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // NOT mask register +INST3(knotq, "knotq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x44), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // NOT mask register +INST3(kord, "kord", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x45), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical OR masks +INST3(korq, "korq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x45), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical OR masks +INST3(kortestd, "kortestd", IUM_RD, BAD_CODE, BAD_CODE, PCKDBL(0x98), INS_TT_NONE, REX_W1 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // OR masks and set flags +INST3(kortestq, "kortestq", IUM_RD, BAD_CODE, BAD_CODE, PCKFLT(0x98), INS_TT_NONE, REX_W1 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // OR masks and set flags +INST3(kshiftld, "kshiftld", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x33), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Shift left mask registers +INST3(kshiftlq, "kshiftlq", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x33), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Shift left mask registers +INST3(kshiftrd, "kshiftrd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x31), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Shift right mask registers +INST3(kshiftrq, "kshiftrq", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x31), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Shift right mask registers +INST3(ktestd, "ktestd", IUM_RD, BAD_CODE, BAD_CODE, PCKDBL(0x99), INS_TT_NONE, REX_W1 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // Packed bit test masks and set flags +INST3(ktestq, "ktestq", IUM_RD, BAD_CODE, BAD_CODE, PCKFLT(0x99), INS_TT_NONE, REX_W1 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // Packed bit test masks and set flags +INST3(kunpckdq, "kunpckdq", IUM_RD, BAD_CODE, BAD_CODE, PCKFLT(0x4B), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Unpack for mask registers +INST3(kunpckwd, "kunpckwd", IUM_RD, BAD_CODE, BAD_CODE, PCKFLT(0x4B), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Unpack for mask registers +INST3(kxnord, "kxnord", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x46), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical XNOR masks +INST3(kxnorq, "kxnorq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x46), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical XNOR masks +INST3(kxord, "kxord", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x47), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical XOR masks +INST3(kxorq, "kxorq", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x47), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) // Bitwise logical XOR masks +INST3(vpblendmd, "pblendmd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x64), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Blend Byte vectors using an OpMask control INST3(vpblendmw, "pblendmw", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x66), INS_TT_FULL_MEM, Input_16Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Blend Word vectors using an OpMask control INST3(vdbpsadbw, "dbpsadbw", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x42), INS_TT_FULL_MEM, Input_8Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Double block packed Sum-Absolute-Differences (SAD) on unsigned bytes INST3(vmovdqu8, "movdqu8", IUM_WR, SSEFLT(0x7F), BAD_CODE, SSEFLT(0x6F), INS_TT_FULL_MEM, Input_8Bit | REX_W0 | Encoding_EVEX) @@ -818,43 +818,43 @@ INST3(vptestnmb, "ptestnmb", IUM_RD, BAD_CODE, BAD_ INST3(vptestnmw, "ptestnmw", IUM_RD, BAD_CODE, BAD_CODE, PSSE38(0xF3, 0x26), INS_TT_FULL_MEM, Input_16Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Logical NAND and set mask // AVX512CD -INST3(vpconflictd, "pconflictd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xC4), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX) // Detect conflicts within a vector of packed dword values into dense memory/register -INST3(vpconflictq, "pconflictq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xC4), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // Detect conflicts within a vector of packed qword values into dense memory/register -INST3(vplzcntd, "plzcntd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x44), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX) // Count the number of leading zero bits for packed dword values -INST3(vplzcntq, "plzcntq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x44), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // Count the number of leading zero bits for packed qword values +INST3(vpconflictd, "pconflictd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xC4), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Detect conflicts within a vector of packed dword values into dense memory/register +INST3(vpconflictq, "pconflictq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xC4), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Detect conflicts within a vector of packed qword values into dense memory/register +INST3(vplzcntd, "plzcntd", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x44), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Count the number of leading zero bits for packed dword values +INST3(vplzcntq, "plzcntq", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x44), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // Count the number of leading zero bits for packed qword values // AVX512DQ -INST3(kaddb, "kaddb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x4A), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Add two masks -INST3(kaddw, "kaddw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x4A), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Add two masks -INST3(kandb, "kandb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x41), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical AND masks -INST3(kandnb, "kandnb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x42), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical AND NOT masks -INST3(kmovb_gpr, "kmovb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers -INST3(kmovb_msk, "kmovb", IUM_WR, PCKDBL(0x91), BAD_CODE, PCKDBL(0x90), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers -INST3(knotb, "knotb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x44), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // NOT mask register -INST3(korb, "korb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x45), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical OR masks -INST3(kortestb, "kortestb", IUM_RD, BAD_CODE, BAD_CODE, PCKDBL(0x98), INS_TT_NONE, REX_W0 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // OR masks and set flags -INST3(kshiftlb, "kshiftlb", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x32), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Shift left mask registers -INST3(kshiftrb, "kshiftrb", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x30), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Shift right mask registers -INST3(ktestb, "ktestb", IUM_RD, BAD_CODE, BAD_CODE, PCKDBL(0x99), INS_TT_NONE, REX_W0 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // Packed bit test masks and set flags -INST3(ktestw, "ktestw", IUM_RD, BAD_CODE, BAD_CODE, PCKFLT(0x99), INS_TT_NONE, REX_W0 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // Packed bit test masks and set flags -INST3(kxnorb, "kxnorb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x46), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical XNOR masks -INST3(kxorb, "kxorb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x47), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical XOR masks +INST3(kaddb, "kaddb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x4A), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Add two masks +INST3(kaddw, "kaddw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x4A), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Add two masks +INST3(kandb, "kandb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x41), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical AND masks +INST3(kandnb, "kandnb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x42), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical AND NOT masks +INST3(kmovb_gpr, "kmovb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers +INST3(kmovb_msk, "kmovb", IUM_WR, PCKDBL(0x91), BAD_CODE, PCKDBL(0x90), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Move from and to mask registers +INST3(knotb, "knotb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x44), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // NOT mask register +INST3(korb, "korb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x45), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical OR masks +INST3(kortestb, "kortestb", IUM_RD, BAD_CODE, BAD_CODE, PCKDBL(0x98), INS_TT_NONE, REX_W0 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // OR masks and set flags +INST3(kshiftlb, "kshiftlb", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x32), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Shift left mask registers +INST3(kshiftrb, "kshiftrb", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x30), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Shift right mask registers +INST3(ktestb, "ktestb", IUM_RD, BAD_CODE, BAD_CODE, PCKDBL(0x99), INS_TT_NONE, REX_W0 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // Packed bit test masks and set flags +INST3(ktestw, "ktestw", IUM_RD, BAD_CODE, BAD_CODE, PCKFLT(0x99), INS_TT_NONE, REX_W0 | Encoding_VEX | Resets_OF | Resets_SF | Writes_ZF | Resets_AF | Resets_PF | Writes_CF | KInstruction) // Packed bit test masks and set flags +INST3(kxnorb, "kxnorb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x46), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical XNOR masks +INST3(kxorb, "kxorb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x47), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) // Bitwise logical XOR masks INST3(vbroadcastf32x2, "broadcastf32x2", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x19), INS_TT_TUPLE2, Input_32Bit | REX_W0 | Encoding_EVEX) // Broadcast packed float values read from memory to entire register INST3(vbroadcasti32x2, "broadcasti32x2", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x59), INS_TT_TUPLE2, Input_32Bit | REX_W0 | Encoding_EVEX) // Broadcast packed integer values read from memory to entire register INST3(vbroadcastf32x8, "broadcastf32x8", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x1B), INS_TT_TUPLE8, Input_32Bit | REX_W0 | Encoding_EVEX) // Broadcast packed float values read from memory to entire register INST3(vbroadcasti32x8, "broadcasti32x8", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x5B), INS_TT_TUPLE8, Input_32Bit | REX_W0 | Encoding_EVEX) // Broadcast packed integer values read from memory to entire register -INST3(vcvtpd2qq, "cvtpd2qq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x7B), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // cvt packed doubles to signed QWORDs -INST3(vcvtpd2uqq, "cvtpd2uqq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x79), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // cvt packed doubles to unsigned QWORDs -INST3(vcvtps2qq, "cvtps2qq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x7B), INS_TT_HALF, Input_32Bit | REX_W0 | Encoding_EVEX) // cvt packed singles to signed QWORDs -INST3(vcvtps2uqq, "cvtps2uqq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x79), INS_TT_HALF, Input_32Bit | REX_W0 | Encoding_EVEX) // cvt packed singles to unsigned QWORDs -INST3(vcvtqq2pd, "cvtqq2pd", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0xE6), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // cvt packed signed QWORDs to doubles -INST3(vcvtqq2ps, "cvtqq2ps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x5B), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // cvt packed signed QWORDs to singles -INST3(vcvttpd2qq, "cvttpd2qq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x7A), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // cvt w/ truncation packed doubles to signed QWORDs -INST3(vcvttpd2uqq, "cvttpd2uqq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x78), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // cvt w/ truncation packed doubles to unsigned QWORDs -INST3(vcvttps2qq, "cvttps2qq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x7A), INS_TT_HALF, Input_32Bit | REX_W0 | Encoding_EVEX) // cvt w/ truncation packed singles to signed QWORDs -INST3(vcvttps2uqq, "cvttps2uqq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x78), INS_TT_HALF, Input_32Bit | REX_W0 | Encoding_EVEX) // cvt w/ truncation packed singles to unsigned QWORDs -INST3(vcvtuqq2pd, "cvtuqq2pd", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x7A), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // cvt packed signed QWORDs to doubles -INST3(vcvtuqq2ps, "cvtuqq2ps", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x7A), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX) // cvt packed signed QWORDs to singles +INST3(vcvtpd2qq, "cvtpd2qq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x7B), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed doubles to signed QWORDs +INST3(vcvtpd2uqq, "cvtpd2uqq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x79), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed doubles to unsigned QWORDs +INST3(vcvtps2qq, "cvtps2qq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x7B), INS_TT_HALF, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed singles to signed QWORDs +INST3(vcvtps2uqq, "cvtps2uqq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x79), INS_TT_HALF, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed singles to unsigned QWORDs +INST3(vcvtqq2pd, "cvtqq2pd", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0xE6), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed signed QWORDs to doubles +INST3(vcvtqq2ps, "cvtqq2ps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x5B), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed signed QWORDs to singles +INST3(vcvttpd2qq, "cvttpd2qq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x7A), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt w/ truncation packed doubles to signed QWORDs +INST3(vcvttpd2uqq, "cvttpd2uqq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x78), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt w/ truncation packed doubles to unsigned QWORDs +INST3(vcvttps2qq, "cvttps2qq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x7A), INS_TT_HALF, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt w/ truncation packed singles to signed QWORDs +INST3(vcvttps2uqq, "cvttps2uqq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x78), INS_TT_HALF, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt w/ truncation packed singles to unsigned QWORDs +INST3(vcvtuqq2pd, "cvtuqq2pd", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x7A), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed signed QWORDs to doubles +INST3(vcvtuqq2ps, "cvtuqq2ps", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x7A), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_EmbeddedBroadcastSupported) // cvt packed signed QWORDs to singles INST3(vextractf32x8, "extractf32x8", IUM_WR, SSE3A(0x1B), BAD_CODE, BAD_CODE, INS_TT_TUPLE8, Input_32Bit | REX_W0 | Encoding_EVEX) // Extract 256-bit packed double-precision floating point values INST3(vextractf64x2, "extractf64x2", IUM_WR, SSE3A(0x19), BAD_CODE, BAD_CODE, INS_TT_TUPLE2, Input_64Bit | REX_W1 | Encoding_EVEX) // Extract 256-bit packed double-precision floating point values INST3(vextracti32x8, "extracti32x8", IUM_WR, SSE3A(0x3B), BAD_CODE, BAD_CODE, INS_TT_TUPLE8, Input_32Bit | REX_W0 | Encoding_EVEX) // Extract 256-bit packed quadword integer values @@ -863,10 +863,10 @@ INST3(vinsertf32x8, "insertf32x8", IUM_WR, BAD_CODE, BAD_ INST3(vinsertf64x2, "insertf64x2", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x18), INS_TT_TUPLE2, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Insert 256-bit packed double-precision floating point values INST3(vinserti32x8, "inserti32x8", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x3A), INS_TT_TUPLE8, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Insert 256-bit packed quadword integer values INST3(vinserti64x2, "inserti64x2", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x38), INS_TT_TUPLE2, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Insert 256-bit packed quadword integer values -INST3(vpcmpd, "pcmpd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x1F), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_Is3OperandInstructionMask) -INST3(vpcmpq, "pcmpq", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x1F), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_Is3OperandInstructionMask) -INST3(vpcmpud, "pcmpud", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x1E), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_Is3OperandInstructionMask) -INST3(vpcmpuq, "pcmpuq", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x1E), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_Is3OperandInstructionMask) +INST3(vpcmpd, "pcmpd", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x1F), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_Is3OperandInstructionMask | INS_Flags_EmbeddedBroadcastSupported) +INST3(vpcmpq, "pcmpq", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x1F), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_Is3OperandInstructionMask | INS_Flags_EmbeddedBroadcastSupported) +INST3(vpcmpud, "pcmpud", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x1E), INS_TT_FULL, Input_32Bit | REX_W0 | Encoding_EVEX | INS_Flags_Is3OperandInstructionMask | INS_Flags_EmbeddedBroadcastSupported) +INST3(vpcmpuq, "pcmpuq", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x1E), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_Is3OperandInstructionMask | INS_Flags_EmbeddedBroadcastSupported) INST3(vpmovd2m, "pmovd2m", IUM_WR, BAD_CODE, BAD_CODE, PSSE38(0xF3, 0x39), INS_TT_NONE, Input_32Bit | REX_W0 | Encoding_EVEX) INST3(vpmovm2d, "pmovm2d", IUM_WR, BAD_CODE, BAD_CODE, PSSE38(0xF3, 0x38), INS_TT_NONE, Input_32Bit | REX_W0 | Encoding_EVEX) INST3(vpmovm2q, "pmovm2q", IUM_WR, BAD_CODE, BAD_CODE, PSSE38(0xF3, 0x38), INS_TT_NONE, Input_64Bit | REX_W1 | Encoding_EVEX) diff --git a/src/coreclr/jit/jit.h b/src/coreclr/jit/jit.h index f34e548a26d4..a6b6c9d16f28 100644 --- a/src/coreclr/jit/jit.h +++ b/src/coreclr/jit/jit.h @@ -486,9 +486,8 @@ class GlobalJitOptions /*****************************************************************************/ -#define CSE_INTO_HANDLERS 0 -#define DUMP_FLOWGRAPHS DEBUG // Support for creating Xml Flowgraph reports in *.fgx files -#define HANDLER_ENTRY_MUST_BE_IN_HOT_SECTION 0 // if 1 we must have all handler entry points in the Hot code section +#define CSE_INTO_HANDLERS 0 +#define DUMP_FLOWGRAPHS DEBUG // Support for creating Xml Flowgraph reports in *.fgx files /*****************************************************************************/ @@ -720,11 +719,11 @@ inline unsigned int unsigned_abs(int x) #ifdef TARGET_64BIT inline size_t unsigned_abs(ssize_t x) { - return ((size_t)std::abs((__int64)x)); + return ((size_t)std::abs((int64_t)x)); } #ifdef __APPLE__ -inline size_t unsigned_abs(__int64 x) +inline size_t unsigned_abs(int64_t x) { return ((size_t)std::abs(x)); } @@ -852,7 +851,7 @@ inline T UninitializedWord(Compiler* comp) } defaultFill = Compiler::compGetJitDefaultFill(comp); assert(defaultFill <= 0xff); - __int64 word = 0x0101010101010101LL * defaultFill; + int64_t word = 0x0101010101010101LL * defaultFill; return (T)word; } diff --git a/src/coreclr/jit/jitconfig.cpp b/src/coreclr/jit/jitconfig.cpp index 19730be75c2c..1d75fcf0aed3 100644 --- a/src/coreclr/jit/jitconfig.cpp +++ b/src/coreclr/jit/jitconfig.cpp @@ -192,9 +192,9 @@ void JitConfigValues::initialize(ICorJitHost* host) { assert(!m_isInitialized); -#define CONFIG_INTEGER(name, key, defaultValue) m_##name = host->getIntConfigValue(key, defaultValue); -#define CONFIG_STRING(name, key) m_##name = host->getStringConfigValue(key); -#define CONFIG_METHODSET(name, key) \ +#define RELEASE_CONFIG_INTEGER(name, key, defaultValue) m_##name = host->getIntConfigValue(key, defaultValue); +#define RELEASE_CONFIG_STRING(name, key) m_##name = host->getStringConfigValue(key); +#define RELEASE_CONFIG_METHODSET(name, key) \ const WCHAR* name##value = host->getStringConfigValue(key); \ m_##name.initialize(name##value, host); \ host->freeStringConfigValue(name##value); @@ -211,9 +211,9 @@ void JitConfigValues::destroy(ICorJitHost* host) return; } -#define CONFIG_INTEGER(name, key, defaultValue) -#define CONFIG_STRING(name, key) host->freeStringConfigValue(m_##name); -#define CONFIG_METHODSET(name, key) m_##name.destroy(host); +#define RELEASE_CONFIG_INTEGER(name, key, defaultValue) +#define RELEASE_CONFIG_STRING(name, key) host->freeStringConfigValue(m_##name); +#define RELEASE_CONFIG_METHODSET(name, key) m_##name.destroy(host); #include "jitconfigvalues.h" diff --git a/src/coreclr/jit/jitconfig.h b/src/coreclr/jit/jitconfig.h index bd1c552f5943..32c84f47e073 100644 --- a/src/coreclr/jit/jitconfig.h +++ b/src/coreclr/jit/jitconfig.h @@ -55,27 +55,30 @@ class JitConfigValues }; private: -#define CONFIG_INTEGER(name, key, defaultValue) int m_##name; -#define CONFIG_STRING(name, key) const WCHAR* m_##name; -#define CONFIG_METHODSET(name, key) MethodSet m_##name; + +#define RELEASE_CONFIG_INTEGER(name, key, defaultValue) int m_##name; +#define RELEASE_CONFIG_STRING(name, key) const WCHAR* m_##name; +#define RELEASE_CONFIG_METHODSET(name, key) MethodSet m_##name; + #include "jitconfigvalues.h" public: -#define CONFIG_INTEGER(name, key, defaultValue) \ +#define RELEASE_CONFIG_INTEGER(name, key, defaultValue) \ inline int name() const \ { \ return m_##name; \ } -#define CONFIG_STRING(name, key) \ +#define RELEASE_CONFIG_STRING(name, key) \ inline const WCHAR* name() const \ { \ return m_##name; \ } -#define CONFIG_METHODSET(name, key) \ +#define RELEASE_CONFIG_METHODSET(name, key) \ inline const MethodSet& name() const \ { \ return m_##name; \ } + #include "jitconfigvalues.h" private: diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index 041e29ad3823..c5406dbad0df 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -1,35 +1,55 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if !defined(CONFIG_INTEGER) || !defined(CONFIG_STRING) || !defined(CONFIG_METHODSET) -#error CONFIG_INTEGER, CONFIG_STRING, and CONFIG_METHODSET must be defined before including this file. -#endif // !defined(CONFIG_INTEGER) || !defined(CONFIG_STRING) || !defined(CONFIG_METHODSET) +#if !defined(RELEASE_CONFIG_INTEGER) || !defined(RELEASE_CONFIG_STRING) || !defined(RELEASE_CONFIG_METHODSET) +#error RELEASE_CONFIG_INTEGER, RELEASE_CONFIG_STRING, and RELEASE_CONFIG_METHODSET must be defined before including this file. +#endif #ifdef DEBUG -#define OPT_CONFIG // Enable optimization level configuration. +#define CONFIG_INTEGER(name, key, defaultValue) RELEASE_CONFIG_INTEGER(name, key, defaultValue) +#define CONFIG_STRING(name, key) RELEASE_CONFIG_STRING(name, key) +#define CONFIG_METHODSET(name, key) RELEASE_CONFIG_METHODSET(name, key) +#else +#define CONFIG_INTEGER(name, key, defaultValue) +#define CONFIG_STRING(name, key) +#define CONFIG_METHODSET(name, key) #endif -#if defined(DEBUG) +#ifdef DEBUG +#define OPT_CONFIG +#endif + +#ifdef OPT_CONFIG +#define OPT_CONFIG_INTEGER(name, key, defaultValue) RELEASE_CONFIG_INTEGER(name, key, defaultValue) +#define OPT_CONFIG_STRING(name, key) RELEASE_CONFIG_STRING(name, key) +#define OPT_CONFIG_METHODSET(name, key) RELEASE_CONFIG_METHODSET(name, key) +#else +#define OPT_CONFIG_INTEGER(name, key, defaultValue) +#define OPT_CONFIG_STRING(name, key) +#define OPT_CONFIG_METHODSET(name, key) +#endif + +// Max number of functions to use altjit for (decimal) +CONFIG_INTEGER(AltJitLimit, W("AltJitLimit"), 0) + +// If AltJit hits an assert, fall back to the fallback JIT. Useful in conjunction with DOTNET_ContinueOnAssert=1 +CONFIG_INTEGER(AltJitSkipOnAssert, W("AltJitSkipOnAssert"), 0) + +// Breaks when using internal logging on a particular token value. +CONFIG_INTEGER(BreakOnDumpToken, W("BreakOnDumpToken"), 0xffffffff) + +// Halts the jit on verification failure +CONFIG_INTEGER(DebugBreakOnVerificationFailure, W("DebugBreakOnVerificationFailure"), 0) -/// -/// JIT -/// -CONFIG_INTEGER(AltJitLimit, W("AltJitLimit"), 0) // Max number of functions to use altjit for (decimal) -CONFIG_INTEGER(AltJitSkipOnAssert, W("AltJitSkipOnAssert"), 0) // If AltJit hits an assert, fall back to the fallback - // JIT. Useful in conjunction with - // DOTNET_ContinueOnAssert=1 -CONFIG_INTEGER(BreakOnDumpToken, W("BreakOnDumpToken"), 0xffffffff) // Breaks when using internal logging on a - // particular token value. -CONFIG_INTEGER(DebugBreakOnVerificationFailure, W("DebugBreakOnVerificationFailure"), 0) // Halts the jit on - // verification failure -CONFIG_INTEGER(JitDasmWithAddress, W("JitDasmWithAddress"), 0) // Print the process address next to each instruction of - // the disassembly CONFIG_INTEGER(DisplayLoopHoistStats, W("JitLoopHoistStats"), 0) // Display JIT loop hoisting statistics -CONFIG_INTEGER(DisplayLsraStats, W("JitLsraStats"), 0) // Display JIT Linear Scan Register Allocator statistics - // If set to "1", display the stats in textual format. - // If set to "2", display the stats in csv format. - // If set to "3", display the stats in summarize format. - // Recommended to use with JitStdOutFile flag. + +// Display JIT Linear Scan Register Allocator statistics +// If set to "1", display the stats in textual format. +// If set to "2", display the stats in csv format. +// If set to "3", display the stats in summarize format. +// Recommended to use with JitStdOutFile flag. +CONFIG_INTEGER(DisplayLsraStats, W("JitLsraStats"), 0) + CONFIG_STRING(JitLsraOrdering, W("JitLsraOrdering")) // LSRA heuristics ordering CONFIG_INTEGER(EnablePCRelAddr, W("JitEnablePCRelAddr"), 1) // Whether absolute addr be encoded as PC-rel offset by // RyuJIT where possible @@ -45,34 +65,29 @@ CONFIG_INTEGER(JitDebugLogLoopCloning, W("JitDebugLogLoopCloning"), 0) // In deb // optimizations are performed on the fast path. CONFIG_INTEGER(JitDefaultFill, W("JitDefaultFill"), 0xdd) // In debug builds, initialize the memory allocated by the nra // with this byte. -CONFIG_INTEGER(JitAlignLoopMinBlockWeight, - W("JitAlignLoopMinBlockWeight"), - DEFAULT_ALIGN_LOOP_MIN_BLOCK_WEIGHT) // Minimum weight needed for the first block of a loop to make it a - // candidate for alignment. -CONFIG_INTEGER(JitAlignLoopMaxCodeSize, - W("JitAlignLoopMaxCodeSize"), - DEFAULT_MAX_LOOPSIZE_FOR_ALIGN) // For non-adaptive alignment, minimum loop size (in bytes) for which - // alignment will be done. - // Defaults to 3 blocks of 32 bytes chunks = 96 bytes. -CONFIG_INTEGER(JitAlignLoopBoundary, - W("JitAlignLoopBoundary"), - DEFAULT_ALIGN_LOOP_BOUNDARY) // For non-adaptive alignment, address boundary (power of 2) at which loop - // alignment should be done. By default, 32B. -CONFIG_INTEGER(JitAlignLoopForJcc, - W("JitAlignLoopForJcc"), - 0) // If set, for non-adaptive alignment, ensure loop jmps are not on or cross alignment boundary. - -CONFIG_INTEGER(JitAlignLoopAdaptive, - W("JitAlignLoopAdaptive"), - 1) // If set, perform adaptive loop alignment that limits number of padding based on loop size. - -CONFIG_INTEGER(JitHideAlignBehindJmp, - W("JitHideAlignBehindJmp"), - 1) // If set, try to hide align instruction (if any) behind an unconditional jump instruction (if any) - // that is present before the loop start. - -CONFIG_INTEGER(JitOptimizeStructHiddenBuffer, W("JitOptimizeStructHiddenBuffer"), 1) // Track stores to locals done - // through return buffers. + +// Minimum weight needed for the first block of a loop to make it a candidate for alignment. +CONFIG_INTEGER(JitAlignLoopMinBlockWeight, W("JitAlignLoopMinBlockWeight"), DEFAULT_ALIGN_LOOP_MIN_BLOCK_WEIGHT) + +// For non-adaptive alignment, minimum loop size (in bytes) for which alignment will be done. +// Defaults to 3 blocks of 32 bytes chunks = 96 bytes. +CONFIG_INTEGER(JitAlignLoopMaxCodeSize, W("JitAlignLoopMaxCodeSize"), DEFAULT_MAX_LOOPSIZE_FOR_ALIGN) + +// For non-adaptive alignment, address boundary (power of 2) at which loop alignment should be done. By default, 32B. +CONFIG_INTEGER(JitAlignLoopBoundary, W("JitAlignLoopBoundary"), DEFAULT_ALIGN_LOOP_BOUNDARY) + +// If set, for non-adaptive alignment, ensure loop jmps are not on or cross alignment boundary. +CONFIG_INTEGER(JitAlignLoopForJcc, W("JitAlignLoopForJcc"), 0) + +// If set, perform adaptive loop alignment that limits number of padding based on loop size. +CONFIG_INTEGER(JitAlignLoopAdaptive, W("JitAlignLoopAdaptive"), 1) + +// If set, try to hide align instruction (if any) behind an unconditional jump instruction (if any) +// that is present before the loop start. +CONFIG_INTEGER(JitHideAlignBehindJmp, W("JitHideAlignBehindJmp"), 1) + +// Track stores to locals done through return buffers. +CONFIG_INTEGER(JitOptimizeStructHiddenBuffer, W("JitOptimizeStructHiddenBuffer"), 1) CONFIG_INTEGER(JitUnrollLoopMaxIterationCount, W("JitUnrollLoopMaxIterationCount"), @@ -80,12 +95,6 @@ CONFIG_INTEGER(JitUnrollLoopMaxIterationCount, CONFIG_INTEGER(JitDirectAlloc, W("JitDirectAlloc"), 0) CONFIG_INTEGER(JitDoubleAlign, W("JitDoubleAlign"), 1) -CONFIG_INTEGER(JitDumpASCII, W("JitDumpASCII"), 1) // Uses only ASCII characters in tree dumps -CONFIG_INTEGER(JitDumpTerseLsra, W("JitDumpTerseLsra"), 1) // Produce terse dump output for LSRA -CONFIG_INTEGER(JitDumpToDebugger, W("JitDumpToDebugger"), 0) // Output JitDump output to the debugger -CONFIG_INTEGER(JitDumpVerboseSsa, W("JitDumpVerboseSsa"), 0) // Produce especially verbose dump output for SSA -CONFIG_INTEGER(JitDumpVerboseTrees, W("JitDumpVerboseTrees"), 0) // Enable more verbose tree dumps -CONFIG_INTEGER(JitDumpTreeIDs, W("JitDumpTreeIDs"), 1) // Print tree IDs in dumps CONFIG_INTEGER(JitEmitPrintRefRegs, W("JitEmitPrintRefRegs"), 0) CONFIG_INTEGER(JitEnableDevirtualization, W("JitEnableDevirtualization"), 1) // Enable devirtualization in importer CONFIG_INTEGER(JitEnableLateDevirtualization, W("JitEnableLateDevirtualization"), 1) // Enable devirtualization after @@ -99,7 +108,6 @@ CONFIG_INTEGER(JitFunctionTrace, W("JitFunctionTrace"), 0) // If non-zero, print CONFIG_INTEGER(JitGCChecks, W("JitGCChecks"), 0) CONFIG_INTEGER(JitGCInfoLogging, W("JitGCInfoLogging"), 0) // If true, prints GCInfo-related output to standard output. CONFIG_INTEGER(JitHashBreak, W("JitHashBreak"), -1) // Same as JitBreak, but for a method hash -CONFIG_INTEGER(JitHashDump, W("JitHashDump"), -1) // Same as JitDump, but for a method hash CONFIG_INTEGER(JitHashHalt, W("JitHashHalt"), -1) // Same as JitHalt, but for a method hash CONFIG_INTEGER(JitInlineAdditionalMultiplier, W("JitInlineAdditionalMultiplier"), 0) CONFIG_INTEGER(JitInlinePrintStats, W("JitInlinePrintStats"), 0) @@ -108,16 +116,21 @@ CONFIG_INTEGER(JitInlineDepth, W("JITInlineDepth"), DEFAULT_MAX_INLINE_DEPTH) CONFIG_INTEGER(JitForceInlineDepth, W("JITForceInlineDepth"), DEFAULT_MAX_FORCE_INLINE_DEPTH) CONFIG_INTEGER(JitLongAddress, W("JitLongAddress"), 0) // Force using the large pseudo instruction form for long address CONFIG_INTEGER(JitMaxUncheckedOffset, W("JitMaxUncheckedOffset"), 8) -CONFIG_INTEGER(JitMinOpts, W("JITMinOpts"), 0) // Forces MinOpts -CONFIG_INTEGER(JitMinOptsBbCount, W("JITMinOptsBbCount"), DEFAULT_MIN_OPTS_BB_COUNT) // Internal jit control of MinOpts -CONFIG_INTEGER(JitMinOptsCodeSize, W("JITMinOptsCodeSize"), DEFAULT_MIN_OPTS_CODE_SIZE) // Internal jit control of - // MinOpts -CONFIG_INTEGER(JitMinOptsInstrCount, W("JITMinOptsInstrCount"), DEFAULT_MIN_OPTS_INSTR_COUNT) // Internal jit control of - // MinOpts -CONFIG_INTEGER(JitMinOptsLvNumCount, W("JITMinOptsLvNumcount"), DEFAULT_MIN_OPTS_LV_NUM_COUNT) // Internal jit control - // of MinOpts -CONFIG_INTEGER(JitMinOptsLvRefCount, W("JITMinOptsLvRefcount"), DEFAULT_MIN_OPTS_LV_REF_COUNT) // Internal jit control - // of MinOpts + +// +// MinOpts +// + +CONFIG_INTEGER(JitMinOpts, W("JITMinOpts"), 0) // Forces MinOpts +CONFIG_METHODSET(JitMinOptsName, W("JITMinOptsName")) // Forces MinOpts for a named function + +// Internal jit control of MinOpts +CONFIG_INTEGER(JitMinOptsBbCount, W("JITMinOptsBbCount"), DEFAULT_MIN_OPTS_BB_COUNT) +CONFIG_INTEGER(JitMinOptsCodeSize, W("JITMinOptsCodeSize"), DEFAULT_MIN_OPTS_CODE_SIZE) +CONFIG_INTEGER(JitMinOptsInstrCount, W("JITMinOptsInstrCount"), DEFAULT_MIN_OPTS_INSTR_COUNT) +CONFIG_INTEGER(JitMinOptsLvNumCount, W("JITMinOptsLvNumcount"), DEFAULT_MIN_OPTS_LV_NUM_COUNT) +CONFIG_INTEGER(JitMinOptsLvRefCount, W("JITMinOptsLvRefcount"), DEFAULT_MIN_OPTS_LV_REF_COUNT) + CONFIG_INTEGER(JitNoCSE, W("JitNoCSE"), 0) CONFIG_INTEGER(JitNoCSE2, W("JitNoCSE2"), 0) CONFIG_INTEGER(JitNoForceFallback, W("JitNoForceFallback"), 0) // Set to non-zero to prevent NOWAY assert testing. @@ -125,7 +138,6 @@ CONFIG_INTEGER(JitNoForceFallback, W("JitNoForceFallback"), 0) // Set to non-zer // flags. CONFIG_INTEGER(JitNoForwardSub, W("JitNoForwardSub"), 0) // Disables forward sub CONFIG_INTEGER(JitNoHoist, W("JitNoHoist"), 0) -CONFIG_INTEGER(JitNoInline, W("JitNoInline"), 0) // Disables inlining of all methods CONFIG_INTEGER(JitNoMemoryBarriers, W("JitNoMemoryBarriers"), 0) // If 1, don't generate memory barriers CONFIG_INTEGER(JitNoStructPromotion, W("JitNoStructPromotion"), 0) // Disables struct promotion 1 - for all, 2 - for // params. @@ -138,63 +150,84 @@ CONFIG_INTEGER(JitPInvokeEnabled, W("JITPInvokeEnabled"), 1) CONFIG_INTEGER(JitHoistLimit, W("JitHoistLimit"), -1) // Specifies the maximum number of hoist candidates to hoist -// Controls verbosity for JitPrintInlinedMethods. Ignored for JitDump where -// it's always set. +// Controls verbosity for JitPrintInlinedMethods. Ignored for JitDump where it's always set. CONFIG_INTEGER(JitPrintInlinedMethodsVerbose, W("JitPrintInlinedMethodsVerboseLevel"), 0) + // Prints a tree of inlinees for a specific method (use '*' for all methods) CONFIG_METHODSET(JitPrintInlinedMethods, W("JitPrintInlinedMethods")) CONFIG_METHODSET(JitPrintDevirtualizedMethods, W("JitPrintDevirtualizedMethods")) - // -1: just do internal checks (CHECK_HASLIKELIHOOD | CHECK_LIKELIHOODSUM | RAISE_ASSERT) -// Else bitflag of ProfileChecks enum. +// Else bitflag: +// - 0x1: check edges have likelihoods +// - 0x2: check edge likelihoods sum to 1.0 +// - 0x4: fully check likelihoods +// - 0x8: assert on check failure +// - 0x10: check block profile weights CONFIG_INTEGER(JitProfileChecks, W("JitProfileChecks"), -1) CONFIG_INTEGER(JitRequired, W("JITRequired"), -1) CONFIG_INTEGER(JitStackAllocToLocalSize, W("JitStackAllocToLocalSize"), DEFAULT_MAX_LOCALLOC_TO_LOCAL_SIZE) CONFIG_INTEGER(JitSkipArrayBoundCheck, W("JitSkipArrayBoundCheck"), 0) CONFIG_INTEGER(JitSlowDebugChecksEnabled, W("JitSlowDebugChecksEnabled"), 1) // Turn on slow debug checks -CONFIG_INTEGER(JitSplitFunctionSize, W("JitSplitFunctionSize"), 0) // On ARM, use this as the maximum function/funclet - // size for creating function fragments (and creating - // multiple RUNTIME_FUNCTION entries) -CONFIG_INTEGER(JitSsaStress, W("JitSsaStress"), 0) // Perturb order of processing of blocks in SSA; 0 = no stress; 1 = - // use method hash; * = supplied value as random hash + +// On ARM, use this as the maximum function/funclet size for creating function fragments (and creating +// multiple RUNTIME_FUNCTION entries) +CONFIG_INTEGER(JitSplitFunctionSize, W("JitSplitFunctionSize"), 0) + +// Perturb order of processing of blocks in SSA; 0 = no stress; 1 = use method hash; * = supplied value as random hash +CONFIG_INTEGER(JitSsaStress, W("JitSsaStress"), 0) + CONFIG_INTEGER(JitStackChecks, W("JitStackChecks"), 0) -CONFIG_INTEGER(JitStress, W("JitStress"), 0) // Internal Jit stress mode: 0 = no stress, 2 = all stress, other = vary - // stress based on a hash of the method and this value + +// Internal Jit stress mode: 0 = no stress, 2 = all stress, other = vary stress based on a hash of the method and +// this value. +CONFIG_INTEGER(JitStress, W("JitStress"), 0) + CONFIG_INTEGER(JitStressBBProf, W("JitStressBBProf"), 0) // Internal Jit stress mode CONFIG_INTEGER(JitStressProcedureSplitting, W("JitStressProcedureSplitting"), 0) // Always split after the first basic // block. CONFIG_INTEGER(JitStressRegs, W("JitStressRegs"), 0) CONFIG_STRING(JitStressRegsRange, W("JitStressRegsRange")) // Only apply JitStressRegs to methods in this hash range -CONFIG_INTEGER(JitVNMapSelLimit, W("JitVNMapSelLimit"), 0) // If non-zero, assert if # of VNF_MapSelect applications - // considered reaches this -CONFIG_INTEGER(RunAltJitCode, W("RunAltJitCode"), 1) // If non-zero, and the compilation succeeds for an AltJit, then - // use the code. If zero, then we always throw away the generated - // code and fall back to the default compiler. +// If non-zero, assert if # of VNF_MapSelect applications considered reaches this. +CONFIG_INTEGER(JitVNMapSelLimit, W("JitVNMapSelLimit"), 0) + +// If non-zero, and the compilation succeeds for an AltJit, then use the code. If zero, then we always throw away the +// generated code and fall back to the default compiler. +CONFIG_INTEGER(RunAltJitCode, W("RunAltJitCode"), 1) + CONFIG_INTEGER(RunComponentUnitTests, W("JitComponentUnitTests"), 0) // Run JIT component unit tests CONFIG_INTEGER(ShouldInjectFault, W("InjectFault"), 0) CONFIG_INTEGER(TailcallStress, W("TailcallStress"), 0) -CONFIG_INTEGER(TreesBeforeAfterMorph, W("JitDumpBeforeAfterMorph"), 0) // If 1, display each tree before/after morphing CONFIG_METHODSET(JitBreak, W("JitBreak")) // Stops in the importer when compiling a specified method CONFIG_METHODSET(JitDebugBreak, W("JitDebugBreak")) -CONFIG_STRING(JitDisasmAssemblies, W("JitDisasmAssemblies")) // Only show JitDisasm and related info for methods - // from this semicolon-delimited list of assemblies. -CONFIG_INTEGER(JitDisasmWithGC, W("JitDisasmWithGC"), 0) // Dump interleaved GC Info for any method disassembled. -CONFIG_INTEGER(JitDisasmWithDebugInfo, W("JitDisasmWithDebugInfo"), 0) // Dump interleaved debug info for any method - // disassembled. -CONFIG_INTEGER(JitDisasmSpilled, W("JitDisasmSpilled"), 0) // Display native code when any register spilling occurs -CONFIG_METHODSET(JitDump, W("JitDump")) // Dumps trees for specified method -CONFIG_INTEGER(JitDumpTier0, W("JitDumpTier0"), 1) // Dump tier0 jit compilations -CONFIG_INTEGER(JitDumpOSR, W("JitDumpOSR"), 1) // Dump OSR jit compilations -CONFIG_INTEGER(JitDumpAtOSROffset, W("JitDumpAtOSROffset"), -1) // Dump only OSR jit compilations with this offset -CONFIG_INTEGER(JitDumpInlinePhases, W("JitDumpInlinePhases"), 1) // Dump inline compiler phases -CONFIG_INTEGER(JitDumpTerseNextBlock, W("JitDumpTerseNextBlock"), 0) // When dumping blocks, display "*" instead of - // block number for lexical "next" blocks, to - // reduce clutter. + +// +// JitDump +// + +CONFIG_METHODSET(JitDump, W("JitDump")) // Dumps trees for specified method +CONFIG_INTEGER(JitHashDump, W("JitHashDump"), -1) // Same as JitDump, but for a method hash +CONFIG_INTEGER(JitDumpTier0, W("JitDumpTier0"), 1) // Dump tier0 jit compilations +CONFIG_INTEGER(JitDumpOSR, W("JitDumpOSR"), 1) // Dump OSR jit compilations +CONFIG_INTEGER(JitDumpAtOSROffset, W("JitDumpAtOSROffset"), -1) // Dump only OSR jit compilations with this offset +CONFIG_INTEGER(JitDumpInlinePhases, W("JitDumpInlinePhases"), 1) // Dump inline compiler phases +CONFIG_INTEGER(JitDumpASCII, W("JitDumpASCII"), 1) // Uses only ASCII characters in tree dumps +CONFIG_INTEGER(JitDumpTerseLsra, W("JitDumpTerseLsra"), 1) // Produce terse dump output for LSRA +CONFIG_INTEGER(JitDumpToDebugger, W("JitDumpToDebugger"), 0) // Output JitDump output to the debugger +CONFIG_INTEGER(JitDumpVerboseSsa, W("JitDumpVerboseSsa"), 0) // Produce especially verbose dump output for SSA +CONFIG_INTEGER(JitDumpVerboseTrees, W("JitDumpVerboseTrees"), 0) // Enable more verbose tree dumps +CONFIG_INTEGER(JitDumpTreeIDs, W("JitDumpTreeIDs"), 1) // Print tree IDs in dumps +CONFIG_INTEGER(JitDumpBeforeAfterMorph, W("JitDumpBeforeAfterMorph"), 0) // If 1, display each tree before/after + // morphing + +// When dumping blocks, display "*" instead of block number for lexical "next" blocks, to reduce clutter. +CONFIG_INTEGER(JitDumpTerseNextBlock, W("JitDumpTerseNextBlock"), 0) + CONFIG_METHODSET(JitEHDump, W("JitEHDump")) // Dump the EH table for the method, as reported to the VM + CONFIG_METHODSET(JitExclude, W("JitExclude")) CONFIG_INTEGER(JitFakeProcedureSplitting, W("JitFakeProcedureSplitting"), 0) // Do code splitting independent of VM. CONFIG_METHODSET(JitForceProcedureSplitting, W("JitForceProcedureSplitting")) @@ -202,10 +235,9 @@ CONFIG_METHODSET(JitGCDump, W("JitGCDump")) CONFIG_METHODSET(JitDebugDump, W("JitDebugDump")) CONFIG_METHODSET(JitHalt, W("JitHalt")) // Emits break instruction into jitted code CONFIG_METHODSET(JitInclude, W("JitInclude")) -CONFIG_METHODSET(JitLateDisasm, W("JitLateDisasm")) // Generate late disassembly for the specified methods. -CONFIG_STRING(JitLateDisasmTo, W("JitLateDisasmTo")) // If set, sends late disassembly output to this file instead of - // stdout/JitStdOutFile. -CONFIG_METHODSET(JitMinOptsName, W("JITMinOptsName")) // Forces MinOpts for a named function +CONFIG_METHODSET(JitLateDisasm, W("JitLateDisasm")) // Generate late disassembly for the specified methods. +CONFIG_STRING(JitLateDisasmTo, W("JitLateDisasmTo")) // If set, sends late disassembly output to this file instead of + // stdout/JitStdOutFile. CONFIG_METHODSET(JitNoProcedureSplitting, W("JitNoProcedureSplitting")) // Disallow procedure splitting for specified // methods CONFIG_METHODSET(JitNoProcedureSplittingEH, W("JitNoProcedureSplittingEH")) // Disallow procedure splitting for @@ -214,6 +246,10 @@ CONFIG_METHODSET(JitNoProcedureSplittingEH, W("JitNoProcedureSplittingEH")) // D CONFIG_METHODSET(JitStressOnly, W("JitStressOnly")) // Internal Jit stress mode: stress only the specified method(s) CONFIG_METHODSET(JitUnwindDump, W("JitUnwindDump")) // Dump the unwind codes for the method +// +// JitDumpFg - dump flowgraph +// + CONFIG_METHODSET(JitDumpFg, W("JitDumpFg")) // Dumps Xml/Dot Flowgraph for specified method CONFIG_STRING(JitDumpFgDir, W("JitDumpFgDir")) // Directory for Xml/Dot flowgraph dump(s) CONFIG_STRING(JitDumpFgFile, W("JitDumpFgFile")) // Filename for Xml/Dot flowgraph dump(s) (default: "default") @@ -221,11 +257,11 @@ CONFIG_STRING(JitDumpFgPhase, W("JitDumpFgPhase")) // Phase-based Xml/Dot flowgr // phase to see the flowgraph after that phase. Leave unset to dump // after COLD-BLK (determine first cold block) or set to * for all // phases -CONFIG_STRING(JitDumpFgPrePhase, - W("JitDumpFgPrePhase")) // Same as JitDumpFgPhase, but specifies to dump pre-phase, not post-phase. -CONFIG_INTEGER(JitDumpFgDot, W("JitDumpFgDot"), 1) // 0 == dump XML format; non-zero == dump DOT format -CONFIG_INTEGER(JitDumpFgEH, W("JitDumpFgEH"), 0) // 0 == no EH regions; non-zero == include EH regions -CONFIG_INTEGER(JitDumpFgLoops, W("JitDumpFgLoops"), 0) // 0 == no loop regions; non-zero == include loop regions +CONFIG_STRING(JitDumpFgPrePhase, W("JitDumpFgPrePhase")) // Same as JitDumpFgPhase, but specifies to dump pre-phase, not + // post-phase. +CONFIG_INTEGER(JitDumpFgDot, W("JitDumpFgDot"), 1) // 0 == dump XML format; non-zero == dump DOT format +CONFIG_INTEGER(JitDumpFgEH, W("JitDumpFgEH"), 0) // 0 == no EH regions; non-zero == include EH regions +CONFIG_INTEGER(JitDumpFgLoops, W("JitDumpFgLoops"), 0) // 0 == no loop regions; non-zero == include loop regions CONFIG_INTEGER(JitDumpFgConstrained, W("JitDumpFgConstrained"), 1) // 0 == don't constrain to mostly linear layout; // non-zero == force mostly lexical block @@ -265,46 +301,73 @@ CONFIG_STRING(JitEmitUnitTestsSections, W("JitEmitUnitTestsSections")) // Genera /// CONFIG_INTEGER(EnableIncompleteISAClass, W("EnableIncompleteISAClass"), 0) // Enable testing not-yet-implemented -#endif // defined(DEBUG) +// +// JitDisasm +// + +RELEASE_CONFIG_METHODSET(JitDisasm, W("JitDisasm")) // Print codegen for given methods +RELEASE_CONFIG_INTEGER(JitDisasmTesting, W("JitDisasmTesting"), 0) // Display BEGIN METHOD/END METHOD anchors for disasm + // testing +RELEASE_CONFIG_INTEGER(JitDisasmDiffable, W("JitDisasmDiffable"), 0) // Make the disassembly diff-able +RELEASE_CONFIG_INTEGER(JitDisasmSummary, W("JitDisasmSummary"), 0) // Prints all jitted methods to the console -CONFIG_METHODSET(JitDisasm, W("JitDisasm")) // Print codegen for given methods -CONFIG_INTEGER(JitDisasmTesting, W("JitDisasmTesting"), 0) // Display BEGIN METHOD/END METHOD anchors for disasm testing -CONFIG_INTEGER(JitDisasmDiffable, W("JitDisasmDiffable"), 0) // Make the disassembly diff-able -CONFIG_INTEGER(JitDisasmSummary, W("JitDisasmSummary"), 0) // Prints all jitted methods to the console -CONFIG_INTEGER(JitDisasmOnlyOptimized, W("JitDisasmOnlyOptimized"), 0) // Hides disassembly for unoptimized codegen -CONFIG_INTEGER(JitDisasmWithAlignmentBoundaries, W("JitDisasmWithAlignmentBoundaries"), 0) // Print the alignment - // boundaries. -CONFIG_INTEGER(JitDisasmWithCodeBytes, W("JitDisasmWithCodeBytes"), 0) // Print the instruction code bytes -CONFIG_STRING(JitStdOutFile, W("JitStdOutFile")) // If set, sends JIT's stdout output to this file. +// Hides disassembly for unoptimized codegen +RELEASE_CONFIG_INTEGER(JitDisasmOnlyOptimized, W("JitDisasmOnlyOptimized"), 0) -CONFIG_INTEGER(RichDebugInfo, W("RichDebugInfo"), 0) // If 1, keep rich debug info and report it back to the EE +// Print the alignment boundaries. +RELEASE_CONFIG_INTEGER(JitDisasmWithAlignmentBoundaries, W("JitDisasmWithAlignmentBoundaries"), 0) + +// Print the instruction code bytes +RELEASE_CONFIG_INTEGER(JitDisasmWithCodeBytes, W("JitDisasmWithCodeBytes"), 0) + +// Only show JitDisasm and related info for methods from this semicolon-delimited list of assemblies. +CONFIG_STRING(JitDisasmAssemblies, W("JitDisasmAssemblies")) + +// Dump interleaved GC Info for any method disassembled. +CONFIG_INTEGER(JitDisasmWithGC, W("JitDisasmWithGC"), 0) + +// Dump interleaved debug info for any method disassembled. +CONFIG_INTEGER(JitDisasmWithDebugInfo, W("JitDisasmWithDebugInfo"), 0) + +// Display native code when any register spilling occurs +CONFIG_INTEGER(JitDisasmSpilled, W("JitDisasmSpilled"), 0) + +// Print the process address next to each instruction of the disassembly +CONFIG_INTEGER(JitDasmWithAddress, W("JitDasmWithAddress"), 0) + +RELEASE_CONFIG_STRING(JitStdOutFile, W("JitStdOutFile")) // If set, sends JIT's stdout output to this file. + +RELEASE_CONFIG_INTEGER(RichDebugInfo, W("RichDebugInfo"), 0) // If 1, keep rich debug info and report it back to the EE -#ifdef DEBUG CONFIG_STRING(WriteRichDebugInfoFile, W("WriteRichDebugInfoFile")) // Write rich debug info in JSON format to this file -#endif #if FEATURE_LOOP_ALIGN -CONFIG_INTEGER(JitAlignLoops, W("JitAlignLoops"), 1) // If set, align inner loops +RELEASE_CONFIG_INTEGER(JitAlignLoops, W("JitAlignLoops"), 1) // If set, align inner loops #else -CONFIG_INTEGER(JitAlignLoops, W("JitAlignLoops"), 0) +RELEASE_CONFIG_INTEGER(JitAlignLoops, W("JitAlignLoops"), 0) #endif // AltJitAssertOnNYI should be 0 on targets where JIT is under development or bring up stage, so as to facilitate // fallback to main JIT on hitting a NYI. -CONFIG_INTEGER(AltJitAssertOnNYI, W("AltJitAssertOnNYI"), 1) // Controls the AltJit behavior of NYI stuff - -CONFIG_INTEGER(EnableEHWriteThru, W("EnableEHWriteThru"), 1) // Enable the register allocator to support EH-write thru: - // partial enregistration of vars exposed on EH boundaries -CONFIG_INTEGER(EnableMultiRegLocals, W("EnableMultiRegLocals"), 1) // Enable the enregistration of locals that are - // defined or used in a multireg context. -#if defined(DEBUG) -CONFIG_INTEGER(JitStressEvexEncoding, W("JitStressEvexEncoding"), 0) // Enable EVEX encoding for SIMD instructions when - // AVX-512VL is available. -#endif +RELEASE_CONFIG_INTEGER(AltJitAssertOnNYI, W("AltJitAssertOnNYI"), 1) // Controls the AltJit behavior of NYI stuff + +// Enable the register allocator to support EH-write thru: partial enregistration of vars exposed on EH boundaries +RELEASE_CONFIG_INTEGER(EnableEHWriteThru, W("EnableEHWriteThru"), 1) + +// Enable the enregistration of locals that are defined or used in a multireg context. +RELEASE_CONFIG_INTEGER(EnableMultiRegLocals, W("EnableMultiRegLocals"), 1) + +// Disables inlining of all methods +RELEASE_CONFIG_INTEGER(JitNoInline, W("JitNoInline"), 0) // clang-format off -CONFIG_INTEGER(PreferredVectorBitWidth, W("PreferredVectorBitWidth"), 0) // The preferred decimal width, in bits, to use for any implicit vectorization emitted. A value less than 128 is treated as the system default. +#if defined(TARGET_AMD64) || defined(TARGET_X86) +// Enable EVEX encoding for SIMD instructions when AVX-512VL is available. +CONFIG_INTEGER(JitStressEvexEncoding, W("JitStressEvexEncoding"), 0) +#endif + +RELEASE_CONFIG_INTEGER(PreferredVectorBitWidth, W("PreferredVectorBitWidth"), 0) // The preferred decimal width, in bits, to use for any implicit vectorization emitted. A value less than 128 is treated as the system default. // // Hardware Intrinsic ISAs; keep in sync with clrconfigvalues.h @@ -312,62 +375,65 @@ CONFIG_INTEGER(PreferredVectorBitWidth, W("PreferredVectorBitWidth"), 0) / #if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) //TODO: should implement LoongArch64's features. //TODO-RISCV64-CQ: should implement RISCV64's features. -CONFIG_INTEGER(EnableHWIntrinsic, W("EnableHWIntrinsic"), 0) // Allows Base+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableHWIntrinsic, W("EnableHWIntrinsic"), 0) // Allows Base+ hardware intrinsics to be disabled #else -CONFIG_INTEGER(EnableHWIntrinsic, W("EnableHWIntrinsic"), 1) // Allows Base+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableHWIntrinsic, W("EnableHWIntrinsic"), 1) // Allows Base+ hardware intrinsics to be disabled #endif // defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) #if defined(TARGET_AMD64) || defined(TARGET_X86) -CONFIG_INTEGER(EnableAES, W("EnableAES"), 1) // Allows AES+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableAVX, W("EnableAVX"), 1) // Allows AVX+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableAVX2, W("EnableAVX2"), 1) // Allows AVX2+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableAVX512BW, W("EnableAVX512BW"), 1) // Allows AVX512BW+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableAVX512BW_VL, W("EnableAVX512BW_VL"), 1) // Allows AVX512BW+ AVX512VL+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableAVX512CD, W("EnableAVX512CD"), 1) // Allows AVX512CD+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableAVX512CD_VL, W("EnableAVX512CD_VL"), 1) // Allows AVX512CD+ AVX512VL+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableAVX512DQ, W("EnableAVX512DQ"), 1) // Allows AVX512DQ+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableAVX512DQ_VL, W("EnableAVX512DQ_VL"), 1) // Allows AVX512DQ+ AVX512VL+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableAVX512F, W("EnableAVX512F"), 1) // Allows AVX512F+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableAVX512F_VL, W("EnableAVX512F_VL"), 1) // Allows AVX512F+ AVX512VL+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableAVX512VBMI, W("EnableAVX512VBMI"), 1) // Allows AVX512VBMI+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableAVX512VBMI_VL, W("EnableAVX512VBMI_VL"), 1) // Allows AVX512VBMI_VL+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableAVX10v1, W("EnableAVX10v1"), 1) // Allows AVX10v1+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableAVXVNNI, W("EnableAVXVNNI"), 1) // Allows AVXVNNI+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableBMI1, W("EnableBMI1"), 1) // Allows BMI1+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableBMI2, W("EnableBMI2"), 1) // Allows BMI2+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableFMA, W("EnableFMA"), 1) // Allows FMA+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableLZCNT, W("EnableLZCNT"), 1) // Allows LZCNT+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnablePCLMULQDQ, W("EnablePCLMULQDQ"), 1) // Allows PCLMULQDQ+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnablePOPCNT, W("EnablePOPCNT"), 1) // Allows POPCNT+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableSSE, W("EnableSSE"), 1) // Allows SSE+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableSSE2, W("EnableSSE2"), 1) // Allows SSE2+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableSSE3, W("EnableSSE3"), 1) // Allows SSE3+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableSSE3_4, W("EnableSSE3_4"), 1) // Allows SSE3+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableSSE41, W("EnableSSE41"), 1) // Allows SSE4.1+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableSSE42, W("EnableSSE42"), 1) // Allows SSE4.2+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableSSSE3, W("EnableSSSE3"), 1) // Allows SSSE3+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAES, W("EnableAES"), 1) // Allows AES+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAVX, W("EnableAVX"), 1) // Allows AVX+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAVX2, W("EnableAVX2"), 1) // Allows AVX2+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAVX512BW, W("EnableAVX512BW"), 1) // Allows AVX512BW+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAVX512BW_VL, W("EnableAVX512BW_VL"), 1) // Allows AVX512BW+ AVX512VL+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAVX512CD, W("EnableAVX512CD"), 1) // Allows AVX512CD+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAVX512CD_VL, W("EnableAVX512CD_VL"), 1) // Allows AVX512CD+ AVX512VL+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAVX512DQ, W("EnableAVX512DQ"), 1) // Allows AVX512DQ+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAVX512DQ_VL, W("EnableAVX512DQ_VL"), 1) // Allows AVX512DQ+ AVX512VL+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAVX512F, W("EnableAVX512F"), 1) // Allows AVX512F+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAVX512F_VL, W("EnableAVX512F_VL"), 1) // Allows AVX512F+ AVX512VL+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAVX512VBMI, W("EnableAVX512VBMI"), 1) // Allows AVX512VBMI+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAVX512VBMI_VL, W("EnableAVX512VBMI_VL"), 1) // Allows AVX512VBMI_VL+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAVX10v1, W("EnableAVX10v1"), 1) // Allows AVX10v1+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableAVXVNNI, W("EnableAVXVNNI"), 1) // Allows AVXVNNI+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableBMI1, W("EnableBMI1"), 1) // Allows BMI1+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableBMI2, W("EnableBMI2"), 1) // Allows BMI2+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableFMA, W("EnableFMA"), 1) // Allows FMA+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableLZCNT, W("EnableLZCNT"), 1) // Allows LZCNT+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnablePCLMULQDQ, W("EnablePCLMULQDQ"), 1) // Allows PCLMULQDQ+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnablePOPCNT, W("EnablePOPCNT"), 1) // Allows POPCNT+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableSSE, W("EnableSSE"), 1) // Allows SSE+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableSSE2, W("EnableSSE2"), 1) // Allows SSE2+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableSSE3, W("EnableSSE3"), 1) // Allows SSE3+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableSSE3_4, W("EnableSSE3_4"), 1) // Allows SSE3+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableSSE41, W("EnableSSE41"), 1) // Allows SSE4.1+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableSSE42, W("EnableSSE42"), 1) // Allows SSE4.2+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableSSSE3, W("EnableSSSE3"), 1) // Allows SSSE3+ hardware intrinsics to be disabled #elif defined(TARGET_ARM64) -CONFIG_INTEGER(EnableArm64AdvSimd, W("EnableArm64AdvSimd"), 1) // Allows Arm64 AdvSimd+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableArm64Aes, W("EnableArm64Aes"), 1) // Allows Arm64 Aes+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableArm64Atomics, W("EnableArm64Atomics"), 1) // Allows Arm64 Atomics+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableArm64Crc32, W("EnableArm64Crc32"), 1) // Allows Arm64 Crc32+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableArm64Dczva, W("EnableArm64Dczva"), 1) // Allows Arm64 Dczva+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableArm64Dp, W("EnableArm64Dp"), 1) // Allows Arm64 Dp+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableArm64Rdm, W("EnableArm64Rdm"), 1) // Allows Arm64 Rdm+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableArm64Sha1, W("EnableArm64Sha1"), 1) // Allows Arm64 Sha1+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableArm64Sha256, W("EnableArm64Sha256"), 1) // Allows Arm64 Sha256+ hardware intrinsics to be disabled -CONFIG_INTEGER(EnableArm64Sve, W("EnableArm64Sve"), 1) // Allows Arm64 Sve+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableArm64AdvSimd, W("EnableArm64AdvSimd"), 1) // Allows Arm64 AdvSimd+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableArm64Aes, W("EnableArm64Aes"), 1) // Allows Arm64 Aes+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableArm64Atomics, W("EnableArm64Atomics"), 1) // Allows Arm64 Atomics+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableArm64Crc32, W("EnableArm64Crc32"), 1) // Allows Arm64 Crc32+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableArm64Dczva, W("EnableArm64Dczva"), 1) // Allows Arm64 Dczva+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableArm64Dp, W("EnableArm64Dp"), 1) // Allows Arm64 Dp+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableArm64Rdm, W("EnableArm64Rdm"), 1) // Allows Arm64 Rdm+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableArm64Sha1, W("EnableArm64Sha1"), 1) // Allows Arm64 Sha1+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableArm64Sha256, W("EnableArm64Sha256"), 1) // Allows Arm64 Sha256+ hardware intrinsics to be disabled +RELEASE_CONFIG_INTEGER(EnableArm64Sve, W("EnableArm64Sve"), 1) // Allows Arm64 Sve+ hardware intrinsics to be disabled #endif +RELEASE_CONFIG_INTEGER(EnableEmbeddedBroadcast, W("EnableEmbeddedBroadcast"), 1) // Allows embedded broadcasts to be disabled +RELEASE_CONFIG_INTEGER(EnableEmbeddedMasking, W("EnableEmbeddedMasking"), 1) // Allows embedded masking to be disabled + // clang-format on #ifdef FEATURE_SIMD -CONFIG_INTEGER(JitDisableSimdVN, W("JitDisableSimdVN"), 0) // Default 0, ValueNumbering of SIMD nodes and HW Intrinsic - // nodes enabled - // If 1, then disable ValueNumbering of SIMD nodes - // If 2, then disable ValueNumbering of HW Intrinsic nodes - // If 3, disable both SIMD and HW Intrinsic nodes -#endif // FEATURE_SIMD +// Default 0, ValueNumbering of SIMD nodes and HW Intrinsic nodes enabled +// If 1, then disable ValueNumbering of SIMD nodes +// If 2, then disable ValueNumbering of HW Intrinsic nodes +// If 3, disable both SIMD and HW Intrinsic nodes +RELEASE_CONFIG_INTEGER(JitDisableSimdVN, W("JitDisableSimdVN"), 0) +#endif // Default 0, enable the CSE of Constants, including nearby offsets. (only for ARM/ARM64) // If 1, disable all the CSE of Constants @@ -375,23 +441,19 @@ CONFIG_INTEGER(JitDisableSimdVN, W("JitDisableSimdVN"), 0) // Default 0, ValueNu // If 3, enable the CSE of Constants including nearby offsets. (all platforms) // If 4, enable the CSE of Constants but don't combine with nearby offsets. (all platforms) // -CONFIG_INTEGER(JitConstCSE, W("JitConstCSE"), 0) - #define CONST_CSE_ENABLE_ARM 0 #define CONST_CSE_DISABLE_ALL 1 #define CONST_CSE_ENABLE_ARM_NO_SHARING 2 #define CONST_CSE_ENABLE_ALL 3 #define CONST_CSE_ENABLE_ALL_NO_SHARING 4 +RELEASE_CONFIG_INTEGER(JitConstCSE, W("JitConstCSE"), CONST_CSE_ENABLE_ARM) // If nonzero, use the greedy RL policy. // -CONFIG_INTEGER(JitRLCSEGreedy, W("JitRLCSEGreedy"), 0) +RELEASE_CONFIG_INTEGER(JitRLCSEGreedy, W("JitRLCSEGreedy"), 0) -// If nonzero, dump out details of parameterized policy evaluation and -// gradient updates -CONFIG_INTEGER(JitRLCSEVerbose, W("JitRLCSEVerbose"), 0) - -#if defined(DEBUG) +// If nonzero, dump out details of parameterized policy evaluation and gradient updates. +RELEASE_CONFIG_INTEGER(JitRLCSEVerbose, W("JitRLCSEVerbose"), 0) // Allow fine-grained controls of CSEs done in a particular method // @@ -414,15 +476,13 @@ CONFIG_INTEGER(JitCSEHash, W("JitCSEHash"), -1) // FFFFFFFF : do all the CSEs normally done CONFIG_INTEGER(JitCSEMask, W("JitCSEMask"), 0) -// Enable metric output in jit disasm & elsewhere +// Enable metric output in jit disasm and elsewhere CONFIG_INTEGER(JitMetrics, W("JitMetrics"), 0) -// When nonzero, choose CSE candidates randomly, with hash salt -// specified by the (decimal) value of the config +// When nonzero, choose CSE candidates randomly, with hash salt specified by the (decimal) value of the config. CONFIG_INTEGER(JitRandomCSE, W("JitRandomCSE"), 0) -// When set, specifies the exact CSEs to perform -// as a sequence of CSE candidate numbers +// When set, specifies the exact CSEs to perform as a sequence of CSE candidate numbers. CONFIG_STRING(JitReplayCSE, W("JitReplayCSE")) // When set, specify the sequence of rewards from the CSE replay. @@ -437,30 +497,34 @@ CONFIG_STRING(JitReplayCSEReward, W("JitReplayCSEReward")) // evaluation/update based on the provided sequence. CONFIG_STRING(JitRLCSE, W("JitRLCSE")) -// When set, specify the alpha value (step size) to -// use in learning. +// When set, specify the alpha value (step size) to use in learning. CONFIG_STRING(JitRLCSEAlpha, W("JitRLCSEAlpha")) // If nonzero, dump candidate feature values CONFIG_INTEGER(JitRLCSECandidateFeatures, W("JitRLCSECandidateFeatures"), 0) -#endif // DEBUG +// Enable CSE_HeuristicRLHook +CONFIG_INTEGER(JitRLHook, W("JitRLHook"), 0) // If 1, emit RL callbacks + +// If 1, emit feature column names +CONFIG_INTEGER(JitRLHookEmitFeatureNames, W("JitRLHookEmitFeatureNames"), 0) + +// A list of CSEs to choose, in the order they should be applied. +CONFIG_STRING(JitRLHookCSEDecisions, W("JitRLHookCSEDecisions")) -/// -/// JIT -/// #if !defined(DEBUG) && !defined(_DEBUG) -CONFIG_INTEGER(JitEnableNoWayAssert, W("JitEnableNoWayAssert"), 0) +RELEASE_CONFIG_INTEGER(JitEnableNoWayAssert, W("JitEnableNoWayAssert"), 0) #else // defined(DEBUG) || defined(_DEBUG) -CONFIG_INTEGER(JitEnableNoWayAssert, W("JitEnableNoWayAssert"), 1) +RELEASE_CONFIG_INTEGER(JitEnableNoWayAssert, W("JitEnableNoWayAssert"), 1) #endif // !defined(DEBUG) && !defined(_DEBUG) +// Track GC roots #if defined(TARGET_AMD64) || defined(TARGET_X86) #define JitMinOptsTrackGCrefs_Default 0 // Not tracking GC refs in MinOpts is new behavior #else #define JitMinOptsTrackGCrefs_Default 1 #endif -CONFIG_INTEGER(JitMinOptsTrackGCrefs, W("JitMinOptsTrackGCrefs"), JitMinOptsTrackGCrefs_Default) // Track GC roots +RELEASE_CONFIG_INTEGER(JitMinOptsTrackGCrefs, W("JitMinOptsTrackGCrefs"), JitMinOptsTrackGCrefs_Default) // The following should be wrapped inside "#if MEASURE_MEM_ALLOC / #endif", but // some files include this one without bringing in the definitions from "jit.h" @@ -469,91 +533,86 @@ CONFIG_INTEGER(JitMinOptsTrackGCrefs, W("JitMinOptsTrackGCrefs"), JitMinOptsTrac // (normally MEASURE_MEM_ALLOC is off for release builds but if it's toggled on // for release in "jit.h" the flag would be missing for some includers). // TODO-Cleanup: need to make 'MEASURE_MEM_ALLOC' well-defined here at all times. -CONFIG_INTEGER(DisplayMemStats, W("JitMemStats"), 0) // Display JIT memory usage statistics +RELEASE_CONFIG_INTEGER(DisplayMemStats, W("JitMemStats"), 0) // Display JIT memory usage statistics -#if defined(DEBUG) CONFIG_INTEGER(JitEnregStats, W("JitEnregStats"), 0) // Display JIT enregistration statistics -#endif // DEBUG -CONFIG_INTEGER(JitAggressiveInlining, W("JitAggressiveInlining"), 0) // Aggressive inlining of all methods -CONFIG_INTEGER(JitELTHookEnabled, W("JitELTHookEnabled"), 0) // If 1, emit Enter/Leave/TailCall callbacks -CONFIG_INTEGER(JitInlineSIMDMultiplier, W("JitInlineSIMDMultiplier"), 3) +RELEASE_CONFIG_INTEGER(JitAggressiveInlining, W("JitAggressiveInlining"), 0) // Aggressive inlining of all methods +RELEASE_CONFIG_INTEGER(JitELTHookEnabled, W("JitELTHookEnabled"), 0) // If 1, emit Enter/Leave/TailCall callbacks +RELEASE_CONFIG_INTEGER(JitInlineSIMDMultiplier, W("JitInlineSIMDMultiplier"), 3) // Ex lclMAX_TRACKED constant. -CONFIG_INTEGER(JitMaxLocalsToTrack, W("JitMaxLocalsToTrack"), 0x400) +RELEASE_CONFIG_INTEGER(JitMaxLocalsToTrack, W("JitMaxLocalsToTrack"), 0x400) #if defined(FEATURE_ENABLE_NO_RANGE_CHECKS) -CONFIG_INTEGER(JitNoRngChks, W("JitNoRngChks"), 0) // If 1, don't generate range checks -#endif // defined(FEATURE_ENABLE_NO_RANGE_CHECKS) - -#if defined(OPT_CONFIG) - -CONFIG_INTEGER(JitDoAssertionProp, W("JitDoAssertionProp"), 1) // Perform assertion propagation optimization -CONFIG_INTEGER(JitDoCopyProp, W("JitDoCopyProp"), 1) // Perform copy propagation on variables that appear redundant -CONFIG_INTEGER(JitDoOptimizeIVs, W("JitDoOptimizeIVs"), 1) // Perform optimization of induction variables -CONFIG_INTEGER(JitDoEarlyProp, W("JitDoEarlyProp"), 1) // Perform Early Value Propagation -CONFIG_INTEGER(JitDoLoopHoisting, W("JitDoLoopHoisting"), 1) // Perform loop hoisting on loop invariant values -CONFIG_INTEGER(JitDoLoopInversion, W("JitDoLoopInversion"), 1) // Perform loop inversion on "for/while" loops -CONFIG_INTEGER(JitDoRangeAnalysis, W("JitDoRangeAnalysis"), 1) // Perform range check analysis -CONFIG_INTEGER(JitDoVNBasedDeadStoreRemoval, W("JitDoVNBasedDeadStoreRemoval"), 1) // Perform VN-based dead store - // removal -CONFIG_INTEGER(JitDoRedundantBranchOpts, W("JitDoRedundantBranchOpts"), 1) // Perform redundant branch optimizations -CONFIG_STRING(JitEnableRboRange, W("JitEnableRboRange")) -CONFIG_STRING(JitEnableHeadTailMergeRange, W("JitEnableHeadTailMergeRange")) -CONFIG_STRING(JitEnableVNBasedDeadStoreRemovalRange, W("JitEnableVNBasedDeadStoreRemovalRange")) -CONFIG_STRING(JitEnableEarlyLivenessRange, W("JitEnableEarlyLivenessRange")) -CONFIG_STRING(JitOnlyOptimizeRange, - W("JitOnlyOptimizeRange")) // If set, all methods that do _not_ match are forced into MinOpts -CONFIG_STRING(JitEnablePhysicalPromotionRange, W("JitEnablePhysicalPromotionRange")) -CONFIG_STRING(JitEnableCrossBlockLocalAssertionPropRange, W("JitEnableCrossBlockLocalAssertionPropRange")) -CONFIG_STRING(JitEnableInductionVariableOptsRange, W("JitEnableInductionVariableOptsRange")) - -CONFIG_INTEGER(JitDoSsa, W("JitDoSsa"), 1) // Perform Static Single Assignment (SSA) numbering on the variables -CONFIG_INTEGER(JitDoValueNumber, W("JitDoValueNumber"), 1) // Perform value numbering on method expressions - -CONFIG_STRING(JitOptRepeatRange, W("JitOptRepeatRange")) // Enable JitOptRepeat based on method hash range - -CONFIG_INTEGER(JitDoIfConversion, W("JitDoIfConversion"), 1) // Perform If conversion - -#endif // defined(OPT_CONFIG) - -CONFIG_INTEGER(JitEnableOptRepeat, W("JitEnableOptRepeat"), 1) // If zero, do not allow JitOptRepeat -CONFIG_METHODSET(JitOptRepeat, W("JitOptRepeat")) // Runs optimizer multiple times on specified methods -CONFIG_INTEGER(JitOptRepeatCount, W("JitOptRepeatCount"), 2) // Number of times to repeat opts when repeating +RELEASE_CONFIG_INTEGER(JitNoRngChks, W("JitNoRngChks"), 0) // If 1, don't generate range checks +#endif + +OPT_CONFIG_INTEGER(JitDoAssertionProp, W("JitDoAssertionProp"), 1) // Perform assertion propagation optimization +OPT_CONFIG_INTEGER(JitDoCopyProp, W("JitDoCopyProp"), 1) // Perform copy propagation on variables that appear redundant +OPT_CONFIG_INTEGER(JitDoOptimizeIVs, W("JitDoOptimizeIVs"), 1) // Perform optimization of induction variables +OPT_CONFIG_INTEGER(JitDoEarlyProp, W("JitDoEarlyProp"), 1) // Perform Early Value Propagation +OPT_CONFIG_INTEGER(JitDoLoopHoisting, W("JitDoLoopHoisting"), 1) // Perform loop hoisting on loop invariant values +OPT_CONFIG_INTEGER(JitDoLoopInversion, W("JitDoLoopInversion"), 1) // Perform loop inversion on "for/while" loops +OPT_CONFIG_INTEGER(JitDoRangeAnalysis, W("JitDoRangeAnalysis"), 1) // Perform range check analysis +OPT_CONFIG_INTEGER(JitDoVNBasedDeadStoreRemoval, W("JitDoVNBasedDeadStoreRemoval"), 1) // Perform VN-based dead store + // removal +OPT_CONFIG_INTEGER(JitDoRedundantBranchOpts, W("JitDoRedundantBranchOpts"), 1) // Perform redundant branch optimizations +OPT_CONFIG_STRING(JitEnableRboRange, W("JitEnableRboRange")) +OPT_CONFIG_STRING(JitEnableHeadTailMergeRange, W("JitEnableHeadTailMergeRange")) +OPT_CONFIG_STRING(JitEnableVNBasedDeadStoreRemovalRange, W("JitEnableVNBasedDeadStoreRemovalRange")) +OPT_CONFIG_STRING(JitEnableEarlyLivenessRange, W("JitEnableEarlyLivenessRange")) +OPT_CONFIG_STRING(JitOnlyOptimizeRange, + W("JitOnlyOptimizeRange")) // If set, all methods that do _not_ match are forced into MinOpts +OPT_CONFIG_STRING(JitEnablePhysicalPromotionRange, W("JitEnablePhysicalPromotionRange")) +OPT_CONFIG_STRING(JitEnableCrossBlockLocalAssertionPropRange, W("JitEnableCrossBlockLocalAssertionPropRange")) +OPT_CONFIG_STRING(JitEnableInductionVariableOptsRange, W("JitEnableInductionVariableOptsRange")) + +OPT_CONFIG_INTEGER(JitDoSsa, W("JitDoSsa"), 1) // Perform Static Single Assignment (SSA) numbering on the variables +OPT_CONFIG_INTEGER(JitDoValueNumber, W("JitDoValueNumber"), 1) // Perform value numbering on method expressions + +OPT_CONFIG_STRING(JitOptRepeatRange, W("JitOptRepeatRange")) // Enable JitOptRepeat based on method hash range + +OPT_CONFIG_INTEGER(JitDoIfConversion, W("JitDoIfConversion"), 1) // Perform If conversion + +RELEASE_CONFIG_INTEGER(JitEnableOptRepeat, W("JitEnableOptRepeat"), 1) // If zero, do not allow JitOptRepeat +RELEASE_CONFIG_METHODSET(JitOptRepeat, W("JitOptRepeat")) // Runs optimizer multiple times on specified methods +RELEASE_CONFIG_INTEGER(JitOptRepeatCount, W("JitOptRepeatCount"), 2) // Number of times to repeat opts when repeating // Max # of MapSelect's considered for a particular top-level invocation. -CONFIG_INTEGER(JitVNMapSelBudget, W("JitVNMapSelBudget"), DEFAULT_MAP_SELECT_BUDGET) - -CONFIG_INTEGER(TailCallLoopOpt, W("TailCallLoopOpt"), 1) // Convert recursive tail calls to loops -CONFIG_METHODSET(AltJit, W("AltJit")) // Enables AltJit and selectively limits it to the specified methods. -CONFIG_METHODSET(AltJitNgen, W("AltJitNgen")) // Enables AltJit for NGEN and selectively limits it - // to the specified methods. - -CONFIG_STRING(AltJitExcludeAssemblies, W("AltJitExcludeAssemblies")) // Do not use AltJit on this - // semicolon-delimited list of assemblies. - -CONFIG_INTEGER(JitMeasureIR, W("JitMeasureIR"), 0) // If set, measure the IR size after some phases and report it in - // the time log. - -CONFIG_STRING(JitFuncInfoFile, W("JitFuncInfoLogFile")) // If set, gather JIT function info and write to this file. -CONFIG_STRING(JitTimeLogCsv, W("JitTimeLogCsv")) // If set, gather JIT throughput data and write to a CSV file. This - // mode must be used in internal retail builds. -CONFIG_STRING(TailCallOpt, W("TailCallOpt")) -CONFIG_INTEGER(FastTailCalls, W("FastTailCalls"), 1) // If set, allow fast tail calls; otherwise allow only helper-based - // calls - // for explicit tail calls. - -CONFIG_INTEGER(JitMeasureNowayAssert, W("JitMeasureNowayAssert"), 0) // Set to 1 to measure noway_assert usage. Only - // valid if MEASURE_NOWAY is defined. -CONFIG_STRING(JitMeasureNowayAssertFile, - W("JitMeasureNowayAssertFile")) // Set to file to write noway_assert usage to a file (if not - // set: stdout). Only valid if MEASURE_NOWAY is defined. -#if defined(DEBUG) +RELEASE_CONFIG_INTEGER(JitVNMapSelBudget, W("JitVNMapSelBudget"), DEFAULT_MAP_SELECT_BUDGET) + +RELEASE_CONFIG_INTEGER(TailCallLoopOpt, W("TailCallLoopOpt"), 1) // Convert recursive tail calls to loops +RELEASE_CONFIG_METHODSET(AltJit, W("AltJit")) // Enables AltJit and selectively limits it to the specified methods. +RELEASE_CONFIG_METHODSET(AltJitNgen, W("AltJitNgen")) // Enables AltJit for NGEN and selectively limits it + // to the specified methods. + +// Do not use AltJit on this semicolon-delimited list of assemblies. +RELEASE_CONFIG_STRING(AltJitExcludeAssemblies, W("AltJitExcludeAssemblies")) + +// If set, measure the IR size after some phases and report it in the time log. +RELEASE_CONFIG_INTEGER(JitMeasureIR, W("JitMeasureIR"), 0) + +// If set, gather JIT function info and write to this file. +RELEASE_CONFIG_STRING(JitFuncInfoFile, W("JitFuncInfoLogFile")) + +// If set, gather JIT throughput data and write to a CSV file. This mode must be used in internal retail builds. +RELEASE_CONFIG_STRING(JitTimeLogCsv, W("JitTimeLogCsv")) + +RELEASE_CONFIG_STRING(TailCallOpt, W("TailCallOpt")) + +// If set, allow fast tail calls; otherwise allow only helper-based calls for explicit tail calls. +RELEASE_CONFIG_INTEGER(FastTailCalls, W("FastTailCalls"), 1) + +// Set to 1 to measure noway_assert usage. Only valid if MEASURE_NOWAY is defined. +RELEASE_CONFIG_INTEGER(JitMeasureNowayAssert, W("JitMeasureNowayAssert"), 0) + +// Set to file to write noway_assert usage to a file (if not set: stdout). Only valid if MEASURE_NOWAY is defined. +RELEASE_CONFIG_STRING(JitMeasureNowayAssertFile, W("JitMeasureNowayAssertFile")) + CONFIG_INTEGER(EnableExtraSuperPmiQueries, W("EnableExtraSuperPmiQueries"), 0) // Make extra queries to somewhat // future-proof SuperPmi method contexts. -#endif // DEBUG -#if defined(DEBUG) CONFIG_INTEGER(JitInlineDumpData, W("JitInlineDumpData"), 0) CONFIG_INTEGER(JitInlineDumpXml, W("JitInlineDumpXml"), 0) // 1 = full xml (+ failures in DEBUG) // 2 = only methods with inlines (+ failures in DEBUG) @@ -569,14 +628,13 @@ CONFIG_INTEGER(JitInlinePolicyRandom, W("JitInlinePolicyRandom"), 0) // nonzero CONFIG_INTEGER(JitInlinePolicyReplay, W("JitInlinePolicyReplay"), 0) CONFIG_STRING(JitNoInlineRange, W("JitNoInlineRange")) CONFIG_STRING(JitInlineReplayFile, W("JitInlineReplayFile")) -#endif // defined(DEBUG) // Extended version of DefaultPolicy that includes a more precise IL scan, // relies on PGO if it exists and generally is more aggressive. -CONFIG_INTEGER(JitExtDefaultPolicy, W("JitExtDefaultPolicy"), 1) -CONFIG_INTEGER(JitExtDefaultPolicyMaxIL, W("JitExtDefaultPolicyMaxIL"), 0x80) -CONFIG_INTEGER(JitExtDefaultPolicyMaxILProf, W("JitExtDefaultPolicyMaxILProf"), 0x400) -CONFIG_INTEGER(JitExtDefaultPolicyMaxBB, W("JitExtDefaultPolicyMaxBB"), 7) +RELEASE_CONFIG_INTEGER(JitExtDefaultPolicy, W("JitExtDefaultPolicy"), 1) +RELEASE_CONFIG_INTEGER(JitExtDefaultPolicyMaxIL, W("JitExtDefaultPolicyMaxIL"), 0x80) +RELEASE_CONFIG_INTEGER(JitExtDefaultPolicyMaxILProf, W("JitExtDefaultPolicyMaxILProf"), 0x400) +RELEASE_CONFIG_INTEGER(JitExtDefaultPolicyMaxBB, W("JitExtDefaultPolicyMaxBB"), 7) // Inliner uses the following formula for PGO-driven decisions: // @@ -586,134 +644,135 @@ CONFIG_INTEGER(JitExtDefaultPolicyMaxBB, W("JitExtDefaultPolicyMaxBB"), 7) // If a profile data can be trusted for 100% we can safely just give up on inlining anything inside cold blocks // (except the cases where inlining in cold blocks improves type info/escape analysis for the whole caller). // For now, it's only applied for dynamic PGO. -CONFIG_INTEGER(JitExtDefaultPolicyProfTrust, W("JitExtDefaultPolicyProfTrust"), 0x7) -CONFIG_INTEGER(JitExtDefaultPolicyProfScale, W("JitExtDefaultPolicyProfScale"), 0x2A) +RELEASE_CONFIG_INTEGER(JitExtDefaultPolicyProfTrust, W("JitExtDefaultPolicyProfTrust"), 0x7) +RELEASE_CONFIG_INTEGER(JitExtDefaultPolicyProfScale, W("JitExtDefaultPolicyProfScale"), 0x2A) -CONFIG_INTEGER(JitInlinePolicyModel, W("JitInlinePolicyModel"), 0) -CONFIG_INTEGER(JitInlinePolicyProfile, W("JitInlinePolicyProfile"), 0) -CONFIG_INTEGER(JitInlinePolicyProfileThreshold, W("JitInlinePolicyProfileThreshold"), 40) -CONFIG_INTEGER(JitObjectStackAllocation, W("JitObjectStackAllocation"), 0) +RELEASE_CONFIG_INTEGER(JitInlinePolicyModel, W("JitInlinePolicyModel"), 0) +RELEASE_CONFIG_INTEGER(JitInlinePolicyProfile, W("JitInlinePolicyProfile"), 0) +RELEASE_CONFIG_INTEGER(JitInlinePolicyProfileThreshold, W("JitInlinePolicyProfileThreshold"), 40) +RELEASE_CONFIG_INTEGER(JitObjectStackAllocation, W("JitObjectStackAllocation"), 0) -CONFIG_INTEGER(JitEECallTimingInfo, W("JitEECallTimingInfo"), 0) +RELEASE_CONFIG_INTEGER(JitEECallTimingInfo, W("JitEECallTimingInfo"), 0) -#if defined(DEBUG) CONFIG_INTEGER(JitEnableFinallyCloning, W("JitEnableFinallyCloning"), 1) CONFIG_INTEGER(JitEnableRemoveEmptyTry, W("JitEnableRemoveEmptyTry"), 1) -#endif // DEBUG // Overall master enable for Guarded Devirtualization. -CONFIG_INTEGER(JitEnableGuardedDevirtualization, W("JitEnableGuardedDevirtualization"), 1) +RELEASE_CONFIG_INTEGER(JitEnableGuardedDevirtualization, W("JitEnableGuardedDevirtualization"), 1) #define MAX_GDV_TYPE_CHECKS 5 // Number of types to probe for polymorphic virtual call-sites to devirtualize them, // Max number is MAX_GDV_TYPE_CHECKS defined above ^. -1 means it's up to JIT to decide -CONFIG_INTEGER(JitGuardedDevirtualizationMaxTypeChecks, W("JitGuardedDevirtualizationMaxTypeChecks"), -1) +RELEASE_CONFIG_INTEGER(JitGuardedDevirtualizationMaxTypeChecks, W("JitGuardedDevirtualizationMaxTypeChecks"), -1) -// Various policies for GuardedDevirtualization -CONFIG_INTEGER(JitGuardedDevirtualizationChainLikelihood, W("JitGuardedDevirtualizationChainLikelihood"), 0x4B) // 75 -CONFIG_INTEGER(JitGuardedDevirtualizationChainStatements, W("JitGuardedDevirtualizationChainStatements"), 1) -#if defined(DEBUG) +// Various policies for GuardedDevirtualization (0x4B == 75) +RELEASE_CONFIG_INTEGER(JitGuardedDevirtualizationChainLikelihood, W("JitGuardedDevirtualizationChainLikelihood"), 0x4B) +RELEASE_CONFIG_INTEGER(JitGuardedDevirtualizationChainStatements, W("JitGuardedDevirtualizationChainStatements"), 1) CONFIG_STRING(JitGuardedDevirtualizationRange, W("JitGuardedDevirtualizationRange")) CONFIG_INTEGER(JitRandomGuardedDevirtualization, W("JitRandomGuardedDevirtualization"), 0) -#endif // DEBUG // Enable insertion of patchpoints into Tier0 methods, switching to optimized where needed. #if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) -CONFIG_INTEGER(TC_OnStackReplacement, W("TC_OnStackReplacement"), 1) +RELEASE_CONFIG_INTEGER(TC_OnStackReplacement, W("TC_OnStackReplacement"), 1) #else -CONFIG_INTEGER(TC_OnStackReplacement, W("TC_OnStackReplacement"), 0) +RELEASE_CONFIG_INTEGER(TC_OnStackReplacement, W("TC_OnStackReplacement"), 0) #endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) + // Initial patchpoint counter value used by jitted code -CONFIG_INTEGER(TC_OnStackReplacement_InitialCounter, W("TC_OnStackReplacement_InitialCounter"), 1000) +RELEASE_CONFIG_INTEGER(TC_OnStackReplacement_InitialCounter, W("TC_OnStackReplacement_InitialCounter"), 1000) + // Enable partial compilation for Tier0 methods -CONFIG_INTEGER(TC_PartialCompilation, W("TC_PartialCompilation"), 0) +RELEASE_CONFIG_INTEGER(TC_PartialCompilation, W("TC_PartialCompilation"), 0) + // Patchpoint strategy: // 0 - backedge sources // 1 - backedge targets // 2 - adaptive (default) -CONFIG_INTEGER(TC_PatchpointStrategy, W("TC_PatchpointStrategy"), 2) -#if defined(DEBUG) +RELEASE_CONFIG_INTEGER(TC_PatchpointStrategy, W("TC_PatchpointStrategy"), 2) + // Randomly sprinkle patchpoints. Value is the likelihood any given stack-empty point becomes a patchpoint. CONFIG_INTEGER(JitRandomOnStackReplacement, W("JitRandomOnStackReplacement"), 0) + // Place patchpoint at the specified IL offset, if possible. Overrides random placement. CONFIG_INTEGER(JitOffsetOnStackReplacement, W("JitOffsetOnStackReplacement"), -1) -#endif // debug -#if defined(DEBUG) // EnableOsrRange allows you to limit the set of methods that will rely on OSR to escape // from Tier0 code. Methods outside the range that would normally be jitted at Tier0 // and have patchpoints will instead be switched to optimized. CONFIG_STRING(JitEnableOsrRange, W("JitEnableOsrRange")) + // EnablePatchpointRange allows you to limit the set of Tier0 methods that // will have patchpoints, and hence control which methods will create OSR methods. // Unlike EnableOsrRange, it will not alter the optimization setting for methods // outside the enabled range. CONFIG_STRING(JitEnablePatchpointRange, W("JitEnablePatchpointRange")) -#endif // Profile instrumentation options -CONFIG_INTEGER(JitInterlockedProfiling, W("JitInterlockedProfiling"), 0) -CONFIG_INTEGER(JitScalableProfiling, W("JitScalableProfiling"), 1) -CONFIG_INTEGER(JitCounterPadding, W("JitCounterPadding"), 0) // number of unused extra slots per counter -CONFIG_INTEGER(JitMinimalJitProfiling, W("JitMinimalJitProfiling"), 1) -CONFIG_INTEGER(JitMinimalPrejitProfiling, W("JitMinimalPrejitProfiling"), 0) - -CONFIG_INTEGER(JitProfileValues, W("JitProfileValues"), 1) // Value profiling, e.g. Buffer.Memmove's size -CONFIG_INTEGER(JitProfileCasts, W("JitProfileCasts"), 1) // Profile castclass/isinst -CONFIG_INTEGER(JitConsumeProfileForCasts, W("JitConsumeProfileForCasts"), 1) // Consume profile data (if any) for - // castclass/isinst - -CONFIG_INTEGER(JitClassProfiling, W("JitClassProfiling"), 1) // Profile virtual and interface calls -CONFIG_INTEGER(JitDelegateProfiling, W("JitDelegateProfiling"), 1) // Profile resolved delegate call targets -CONFIG_INTEGER(JitVTableProfiling, W("JitVTableProfiling"), 0) // Profile resolved vtable call targets -CONFIG_INTEGER(JitEdgeProfiling, W("JitEdgeProfiling"), 1) // Profile edges instead of blocks -CONFIG_INTEGER(JitCollect64BitCounts, W("JitCollect64BitCounts"), 0) // Collect counts as 64-bit values. +RELEASE_CONFIG_INTEGER(JitInterlockedProfiling, W("JitInterlockedProfiling"), 0) +RELEASE_CONFIG_INTEGER(JitScalableProfiling, W("JitScalableProfiling"), 1) +RELEASE_CONFIG_INTEGER(JitCounterPadding, W("JitCounterPadding"), 0) // number of unused extra slots per counter +RELEASE_CONFIG_INTEGER(JitMinimalJitProfiling, W("JitMinimalJitProfiling"), 1) +RELEASE_CONFIG_INTEGER(JitMinimalPrejitProfiling, W("JitMinimalPrejitProfiling"), 0) + +RELEASE_CONFIG_INTEGER(JitProfileValues, W("JitProfileValues"), 1) // Value profiling, e.g. Buffer.Memmove's size +RELEASE_CONFIG_INTEGER(JitProfileCasts, W("JitProfileCasts"), 1) // Profile castclass/isinst +RELEASE_CONFIG_INTEGER(JitConsumeProfileForCasts, W("JitConsumeProfileForCasts"), 1) // Consume profile data (if any) + // for castclass/isinst + +RELEASE_CONFIG_INTEGER(JitClassProfiling, W("JitClassProfiling"), 1) // Profile virtual and interface calls +RELEASE_CONFIG_INTEGER(JitDelegateProfiling, W("JitDelegateProfiling"), 1) // Profile resolved delegate call targets +RELEASE_CONFIG_INTEGER(JitVTableProfiling, W("JitVTableProfiling"), 0) // Profile resolved vtable call targets +RELEASE_CONFIG_INTEGER(JitEdgeProfiling, W("JitEdgeProfiling"), 1) // Profile edges instead of blocks +RELEASE_CONFIG_INTEGER(JitCollect64BitCounts, W("JitCollect64BitCounts"), 0) // Collect counts as 64-bit values. // Profile consumption options -CONFIG_INTEGER(JitDisablePGO, W("JitDisablePGO"), 0) // Ignore PGO data for all methods -#if defined(DEBUG) +RELEASE_CONFIG_INTEGER(JitDisablePGO, W("JitDisablePGO"), 0) // Ignore PGO data for all methods CONFIG_STRING(JitEnablePGORange, W("JitEnablePGORange")) // Enable PGO data for only some methods CONFIG_INTEGER(JitRandomEdgeCounts, W("JitRandomEdgeCounts"), 0) // Substitute random values for edge counts CONFIG_INTEGER(JitCrossCheckDevirtualizationAndPGO, W("JitCrossCheckDevirtualizationAndPGO"), 0) CONFIG_INTEGER(JitNoteFailedExactDevirtualization, W("JitNoteFailedExactDevirtualization"), 0) CONFIG_INTEGER(JitRandomlyCollect64BitCounts, W("JitRandomlyCollect64BitCounts"), 0) // Collect 64-bit counts randomly // for some methods. + // 1: profile synthesis for root methods // 2: profile synthesis for root methods w/o PGO data // 3: profile synthesis for root methods, blend with existing PGO data CONFIG_INTEGER(JitSynthesizeCounts, W("JitSynthesizeCounts"), 0) -// Check if synthesis left consistent counts -CONFIG_INTEGER(JitCheckSynthesizedCounts, W("JitCheckSynthesizedCounts"), 0) + // If instrumenting the method, run synthesis and save the synthesis results // as edge or block profile data. Do not actually instrument. CONFIG_INTEGER(JitPropagateSynthesizedCountsToProfileData, W("JitPropagateSynthesizedCountsToProfileData"), 0) + // Use general (gauss-seidel) solver CONFIG_INTEGER(JitSynthesisUseSolver, W("JitSynthesisUseSolver"), 1) -// Relative likelihood of exceptions for synthesis -CONFIG_STRING(JitSynthesisExceptionScale, W("JitSynthesisExceptionScale")) -#endif + +// Weight for exception regions for synthesis +CONFIG_STRING(JitSynthesisExceptionWeight, W("JitSynthesisExceptionWeight")) // Devirtualize virtual calls with getExactClasses (NativeAOT only for now) -CONFIG_INTEGER(JitEnableExactDevirtualization, W("JitEnableExactDevirtualization"), 1) +RELEASE_CONFIG_INTEGER(JitEnableExactDevirtualization, W("JitEnableExactDevirtualization"), 1) // Force the generation of CFG checks -CONFIG_INTEGER(JitForceControlFlowGuard, W("JitForceControlFlowGuard"), 0); +RELEASE_CONFIG_INTEGER(JitForceControlFlowGuard, W("JitForceControlFlowGuard"), 0); + // JitCFGUseDispatcher values: // 0: Never use dispatcher // 1: Use dispatcher on all platforms that support it // 2: Default behavior, depends on platform (yes on x64, no on arm64) -CONFIG_INTEGER(JitCFGUseDispatcher, W("JitCFGUseDispatcher"), 2) +RELEASE_CONFIG_INTEGER(JitCFGUseDispatcher, W("JitCFGUseDispatcher"), 2) // Enable head and tail merging -CONFIG_INTEGER(JitEnableHeadTailMerge, W("JitEnableHeadTailMerge"), 1) +RELEASE_CONFIG_INTEGER(JitEnableHeadTailMerge, W("JitEnableHeadTailMerge"), 1) // Enable physical promotion -CONFIG_INTEGER(JitEnablePhysicalPromotion, W("JitEnablePhysicalPromotion"), 1) +RELEASE_CONFIG_INTEGER(JitEnablePhysicalPromotion, W("JitEnablePhysicalPromotion"), 1) // Enable cross-block local assertion prop -CONFIG_INTEGER(JitEnableCrossBlockLocalAssertionProp, W("JitEnableCrossBlockLocalAssertionProp"), 1) +RELEASE_CONFIG_INTEGER(JitEnableCrossBlockLocalAssertionProp, W("JitEnableCrossBlockLocalAssertionProp"), 1) + +// Do greedy RPO-based layout in Compiler::fgReorderBlocks. +RELEASE_CONFIG_INTEGER(JitDoReversePostOrderLayout, W("JitDoReversePostOrderLayout"), 0); -#if defined(DEBUG) // JitFunctionFile: Name of a file that contains a list of functions. If the currently compiled function is in the // file, certain other JIT config variables will be active. If the currently compiled function is not in the file, // the specific JIT config variables will not be active. @@ -731,14 +790,10 @@ CONFIG_INTEGER(JitEnableCrossBlockLocalAssertionProp, W("JitEnableCrossBlockLoca // If this is unset, then the JIT config values have their normal behavior. // CONFIG_STRING(JitFunctionFile, W("JitFunctionFile")) -#endif // DEBUG -#if defined(DEBUG) CONFIG_METHODSET(JitRawHexCode, W("JitRawHexCode")) CONFIG_STRING(JitRawHexCodeFile, W("JitRawHexCodeFile")) -#endif // DEBUG -#if defined(DEBUG) #if defined(TARGET_ARM64) // JitSaveFpLrWithCalleeSavedRegisters: // 0: use default frame type decision @@ -754,20 +809,24 @@ CONFIG_INTEGER(JitSaveFpLrWithCalleeSavedRegisters, W("JitSaveFpLrWithCalleeSave // Disable emitDispIns by default CONFIG_INTEGER(JitDispIns, W("JitDispIns"), 0) #endif // defined(TARGET_LOONGARCH64) -#endif // DEBUG #ifdef TARGET_WASM -CONFIG_INTEGER(JitCheckLlvmIR, W("JitCheckLlvmIR"), 0) -CONFIG_INTEGER(JitRunLssaTests, W("JitRunLssaTests"), 0) -CONFIG_INTEGER(JitGcStress, W("JitGcStress"), 0) +RELEASE_CONFIG_INTEGER(JitCheckLlvmIR, W("JitCheckLlvmIR"), 0) +RELEASE_CONFIG_INTEGER(JitRunLssaTests, W("JitRunLssaTests"), 0) +RELEASE_CONFIG_INTEGER(JitGcStress, W("JitGcStress"), 0) -#ifdef DEBUG CONFIG_STRING(JitEnableLssaRange, W("JitEnableLssaRange")) -#endif // DEBUG #endif // TARGET_WASM -CONFIG_INTEGER(JitEnregStructLocals, W("JitEnregStructLocals"), 1) // Allow to enregister locals with struct type. +// Allow to enregister locals with struct type. +RELEASE_CONFIG_INTEGER(JitEnregStructLocals, W("JitEnregStructLocals"), 1) #undef CONFIG_INTEGER #undef CONFIG_STRING #undef CONFIG_METHODSET +#undef RELEASE_CONFIG_INTEGER +#undef RELEASE_CONFIG_STRING +#undef RELEASE_CONFIG_METHODSET +#undef OPT_CONFIG_INTEGER +#undef OPT_CONFIG_STRING +#undef OPT_CONFIG_METHODSET diff --git a/src/coreclr/jit/jitee.h b/src/coreclr/jit/jitee.h index 71f53b4e10d7..ba7c72b11706 100644 --- a/src/coreclr/jit/jitee.h +++ b/src/coreclr/jit/jitee.h @@ -84,17 +84,17 @@ class JitFlags void Set(JitFlag flag) { - m_jitFlags |= 1ULL << (unsigned __int64)flag; + m_jitFlags |= 1ULL << (uint64_t)flag; } void Clear(JitFlag flag) { - m_jitFlags &= ~(1ULL << (unsigned __int64)flag); + m_jitFlags &= ~(1ULL << (uint64_t)flag); } bool IsSet(JitFlag flag) const { - return (m_jitFlags & (1ULL << (unsigned __int64)flag)) != 0; + return (m_jitFlags & (1ULL << (uint64_t)flag)) != 0; } bool IsEmpty() const @@ -156,6 +156,6 @@ class JitFlags } private: - unsigned __int64 m_jitFlags; + uint64_t m_jitFlags; CORINFO_InstructionSetFlags m_instructionSetFlags; }; diff --git a/src/coreclr/jit/jitgcinfo.h b/src/coreclr/jit/jitgcinfo.h index f6b35bd6d75a..16729f18470c 100644 --- a/src/coreclr/jit/jitgcinfo.h +++ b/src/coreclr/jit/jitgcinfo.h @@ -187,8 +187,8 @@ class GCInfo unsigned short rpdIsThis : 1; // is it the 'this' pointer unsigned short rpdCall : 1; // is this a true call site? unsigned short : 1; // Padding bit, so next two start on a byte boundary - unsigned short rpdCallGCrefRegs : CNT_CALLEE_SAVED; // Callee-saved registers containing GC pointers. - unsigned short rpdCallByrefRegs : CNT_CALLEE_SAVED; // Callee-saved registers containing byrefs. + unsigned short rpdCallGCrefRegs : CNT_CALL_GC_REGS; // Callee-saved and return registers containing GC pointers. + unsigned short rpdCallByrefRegs : CNT_CALL_GC_REGS; // Callee-saved and return registers containing byrefs. #ifndef JIT32_GCENCODER bool rpdIsCallInstr() diff --git a/src/coreclr/jit/jithashtable.h b/src/coreclr/jit/jithashtable.h index f699c3eee19d..3cf7fdcb98cd 100644 --- a/src/coreclr/jit/jithashtable.h +++ b/src/coreclr/jit/jithashtable.h @@ -76,9 +76,9 @@ class JitPrimeInfo // Compute `numerator` / `prime` using magic division unsigned magicNumberDivide(unsigned numerator) const { - unsigned __int64 num = numerator; - unsigned __int64 mag = magic; - unsigned __int64 product = (num * mag) >> (32 + shift); + uint64_t num = numerator; + uint64_t mag = magic; + uint64_t product = (num * mag) >> (32 + shift); return (unsigned)product; } @@ -233,7 +233,7 @@ class JitHashTable } //------------------------------------------------------------------------ - // Lookup: Get a pointer to the value associated to the specified key. + // LookupPointer: Get a pointer to the value associated to the specified key. // if any. // // Arguments: @@ -261,6 +261,48 @@ class JitHashTable } } + //------------------------------------------------------------------------ + // LookupPointerOrAdd: Get a pointer to the value associated to the specified key. + // If not present, add it with the specified default value and return a pointer to it. + // + // Arguments: + // k - the key + // defaultValue - Default value to add to the table if the key was not present + // + // Return Value: + // A pointer to the value associated with the specified key. + // + Value* LookupPointerOrAdd(Key k, Value defaultValue) + { + CheckGrowth(); + + assert(m_tableSizeInfo.prime != 0); + + unsigned index = GetIndexForKey(k); + + Node* n = m_table[index]; + while (n != nullptr) + { + if (KeyFuncs::Equals(k, n->m_key)) + { + return &n->m_val; + } + + n = n->m_next; + } + + n = new (m_alloc) Node(m_table[index], k, defaultValue); + m_table[index] = n; + m_tableCount++; + return &n->m_val; + } + + enum SetKind + { + None, + Overwrite + }; + //------------------------------------------------------------------------ // Set: Associate the specified value with the specified key. // @@ -279,12 +321,6 @@ class JitHashTable // If the key already exists and kind is Normal // this method will assert // - enum SetKind - { - None, - Overwrite - }; - bool Set(Key k, Value v, SetKind kind = None) { CheckGrowth(); diff --git a/src/coreclr/jit/jitmetadata.cpp b/src/coreclr/jit/jitmetadata.cpp index 905cdb7317d8..bdf8a8d06d02 100644 --- a/src/coreclr/jit/jitmetadata.cpp +++ b/src/coreclr/jit/jitmetadata.cpp @@ -46,6 +46,20 @@ void JitMetrics::report(Compiler* comp) #include "jitmetadatalist.h" } +//------------------------------------------------------------------------ +// JitMetrics::mergeToRoot: Merge inlinee compiler metrics to root compiler instance +// +// Parameters: +// inlineeComp - inlinee compiler instance +// +void JitMetrics::mergeToRoot(Compiler* inlineeComp) +{ + Compiler* const root = inlineeComp->impInlineRoot(); +#define JITMETADATAINFO(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) root->Metrics.name += inlineeComp->Metrics.name; +#include "jitmetadatalist.h" +} + //------------------------------------------------------------------------ // printMetric: Print a double metric value to jitstdout. // diff --git a/src/coreclr/jit/jitmetadata.h b/src/coreclr/jit/jitmetadata.h index 3b4b324497cc..5dbd623a86da 100644 --- a/src/coreclr/jit/jitmetadata.h +++ b/src/coreclr/jit/jitmetadata.h @@ -23,4 +23,5 @@ class JitMetrics void report(Compiler* comp); void dump(); + void mergeToRoot(Compiler* inlineeComp); }; diff --git a/src/coreclr/jit/jitmetadatalist.h b/src/coreclr/jit/jitmetadatalist.h index f36c15ab9991..e077f9f57b25 100644 --- a/src/coreclr/jit/jitmetadatalist.h +++ b/src/coreclr/jit/jitmetadatalist.h @@ -24,25 +24,52 @@ // and int64_t types supported). Their reporting is handled automatically and // they will be propagated all the way into SPMI replay/diff results. -// Name, type flags -JITMETADATAINFO(MethodFullName, const char*, 0) -JITMETADATAINFO(TieringName, const char*, 0) -JITMETADATAMETRIC(PhysicallyPromotedFields, int, 0) -JITMETADATAMETRIC(LoopsFoundDuringOpts, int, 0) -JITMETADATAMETRIC(LoopsCloned, int, 0) -JITMETADATAMETRIC(LoopsUnrolled, int, 0) -JITMETADATAMETRIC(LoopAlignmentCandidates, int, 0) -JITMETADATAMETRIC(LoopsAligned, int, 0) -JITMETADATAMETRIC(LoopsIVWidened, int, 0) -JITMETADATAMETRIC(WidenedIVs, int, 0) -JITMETADATAMETRIC(VarsInSsa, int, 0) -JITMETADATAMETRIC(HoistedExpressions, int, 0) -JITMETADATAMETRIC(RedundantBranchesEliminated, int, JIT_METADATA_HIGHER_IS_BETTER) -JITMETADATAMETRIC(JumpThreadingsPerformed, int, JIT_METADATA_HIGHER_IS_BETTER) -JITMETADATAMETRIC(CseCount, int, 0) -JITMETADATAMETRIC(BasicBlocksAtCodegen, int, 0) -JITMETADATAMETRIC(PerfScore, double, JIT_METADATA_LOWER_IS_BETTER) -JITMETADATAMETRIC(BytesAllocated, int64_t, JIT_METADATA_LOWER_IS_BETTER) +// Name, type flags +JITMETADATAINFO(MethodFullName, const char*, 0) +JITMETADATAINFO(TieringName, const char*, 0) +JITMETADATAMETRIC(PhysicallyPromotedFields, int, 0) +JITMETADATAMETRIC(LoopsFoundDuringOpts, int, 0) +JITMETADATAMETRIC(LoopsCloned, int, 0) +JITMETADATAMETRIC(LoopsUnrolled, int, 0) +JITMETADATAMETRIC(LoopAlignmentCandidates, int, 0) +JITMETADATAMETRIC(LoopsAligned, int, 0) +JITMETADATAMETRIC(LoopsIVWidened, int, 0) +JITMETADATAMETRIC(WidenedIVs, int, 0) +JITMETADATAMETRIC(VarsInSsa, int, 0) +JITMETADATAMETRIC(HoistedExpressions, int, 0) +JITMETADATAMETRIC(RedundantBranchesEliminated, int, JIT_METADATA_HIGHER_IS_BETTER) +JITMETADATAMETRIC(JumpThreadingsPerformed, int, JIT_METADATA_HIGHER_IS_BETTER) +JITMETADATAMETRIC(CseCount, int, 0) +JITMETADATAMETRIC(BasicBlocksAtCodegen, int, 0) +JITMETADATAMETRIC(PerfScore, double, JIT_METADATA_LOWER_IS_BETTER) +JITMETADATAMETRIC(BytesAllocated, int64_t, JIT_METADATA_LOWER_IS_BETTER) +JITMETADATAMETRIC(ImporterBranchFold, int, 0) +JITMETADATAMETRIC(ImporterSwitchFold, int, 0) +JITMETADATAMETRIC(DevirtualizedCall, int, 0) +JITMETADATAMETRIC(DevirtualizedCallUnboxedEntry, int, 0) +JITMETADATAMETRIC(DevirtualizedCallRemovedBox, int, 0) +JITMETADATAMETRIC(GDV, int, 0) +JITMETADATAMETRIC(ClassGDV, int, 0) +JITMETADATAMETRIC(MethodGDV, int, 0) +JITMETADATAMETRIC(MultiGuessGDV, int, 0) +JITMETADATAMETRIC(ChainedGDV, int, 0) +JITMETADATAMETRIC(InlinerBranchFold, int, 0) +JITMETADATAMETRIC(InlineAttempt, int, 0) +JITMETADATAMETRIC(InlineCount, int, 0) +JITMETADATAMETRIC(ProfileConsistentBeforeInline, int, 0) +JITMETADATAMETRIC(ProfileConsistentAfterInline, int, 0) +JITMETADATAMETRIC(ProfileSynthesizedBlendedOrRepaired, int, 0) +JITMETADATAMETRIC(ProfileInconsistentInitially, int, 0) +JITMETADATAMETRIC(ProfileInconsistentResetLeave, int, 0) +JITMETADATAMETRIC(ProfileInconsistentImporterBranchFold, int, 0) +JITMETADATAMETRIC(ProfileInconsistentImporterSwitchFold, int, 0) +JITMETADATAMETRIC(ProfileInconsistentChainedGDV, int, 0) +JITMETADATAMETRIC(ProfileInconsistentScratchBB, int, 0) +JITMETADATAMETRIC(ProfileInconsistentInlinerBranchFold, int, 0) +JITMETADATAMETRIC(ProfileInconsistentInlineeScale, int, 0) +JITMETADATAMETRIC(ProfileInconsistentInlinee, int, 0) +JITMETADATAMETRIC(ProfileInconsistentNoReturnInlinee, int, 0) +JITMETADATAMETRIC(ProfileInconsistentMayThrowInlinee, int, 0) #undef JITMETADATA #undef JITMETADATAINFO diff --git a/src/coreclr/jit/jitstd/iterator.h b/src/coreclr/jit/jitstd/iterator.h index b97a4e71b8bb..f96d358a7dcc 100644 --- a/src/coreclr/jit/jitstd/iterator.h +++ b/src/coreclr/jit/jitstd/iterator.h @@ -117,13 +117,13 @@ struct iterator_traits }; template<> -struct iterator_traits<__int64> +struct iterator_traits { typedef int_not_an_iterator_tag iterator_category; }; template<> -struct iterator_traits +struct iterator_traits { typedef int_not_an_iterator_tag iterator_category; }; diff --git a/src/coreclr/jit/layout.cpp b/src/coreclr/jit/layout.cpp index ad4c0077c22b..8de93f838971 100644 --- a/src/coreclr/jit/layout.cpp +++ b/src/coreclr/jit/layout.cpp @@ -421,22 +421,22 @@ void ClassLayout::InitializeGCPtrs(Compiler* compiler) } //------------------------------------------------------------------------ -// HasGCByRef: does the layout contain at least one GC ByRef +// IsStackOnly: does the layout represent a block that can never be on the heap? +// +// Parameters: +// comp - The Compiler object // // Return value: -// true if at least one GC ByRef, false otherwise. +// true if the block is stack only // -bool ClassLayout::HasGCByRef() const +bool ClassLayout::IsStackOnly(Compiler* comp) const { - unsigned slots = GetSlotCount(); - for (unsigned i = 0; i < slots; i++) + // Byref-like structs are stack only + if ((m_classHandle != NO_CLASS_HANDLE) && + (((comp->info.compCompHnd->getClassAttribs(m_classHandle)) & CORINFO_FLG_BYREF_LIKE) != 0)) { - if (IsGCByRef(i)) - { - return true; - } + return true; } - return false; } diff --git a/src/coreclr/jit/layout.h b/src/coreclr/jit/layout.h index 3c6487e516b9..c2c901d1f33c 100644 --- a/src/coreclr/jit/layout.h +++ b/src/coreclr/jit/layout.h @@ -185,7 +185,7 @@ class ClassLayout return m_gcPtrCount != 0; } - bool HasGCByRef() const; + bool IsStackOnly(Compiler* comp) const; bool IsGCPtr(unsigned slot) const { diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 447b4a75f15d..a425e4c5543a 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -36,6 +36,7 @@ unsigned Compiler::s_lvaDoubleAlignedProcsCount = 0; void Compiler::lvaInit() { lvaParameterPassingInfo = nullptr; + lvaParameterStackSize = 0; /* We haven't allocated stack variables yet */ lvaRefCountState = RCS_INVALID; @@ -475,9 +476,6 @@ void Compiler::lvaInitArgs(InitVarDscInfo* varDscInfo) codeGen->floatRegState.rsCalleeRegArgCount = varDscInfo->floatRegArgNum; #endif // !TARGET_WASM - // Now we have parameters created in the right order. Figure out how they're passed. - lvaClassifyParameterABI(); - #if FEATURE_FASTTAILCALL // Save the stack usage information // We can get register usage information using codeGen->intRegState and @@ -485,6 +483,9 @@ void Compiler::lvaInitArgs(InitVarDscInfo* varDscInfo) info.compArgStackSize = varDscInfo->stackArgSize; #endif // FEATURE_FASTTAILCALL + // Now we have parameters created in the right order. Figure out how they're passed. + lvaClassifyParameterABI(); + // The total argument size must be aligned. noway_assert((compArgSize % TARGET_POINTER_SIZE) == 0); @@ -1441,7 +1442,6 @@ bool Compiler::lvaInitSpecialSwiftParam(CORINFO_ARG_LIST_HANDLE argHnd, compArgSize += TARGET_POINTER_SIZE; lvaSwiftSelfArg = varDscInfo->varNum; - lvaSetVarDoNotEnregister(lvaSwiftSelfArg DEBUGARG(DoNotEnregisterReason::NonStandardParameter)); return true; } @@ -1469,7 +1469,6 @@ bool Compiler::lvaInitSpecialSwiftParam(CORINFO_ARG_LIST_HANDLE argHnd, // Instead, all usages of the SwiftError* parameter will be redirected to this pseudolocal. lvaSwiftErrorLocal = lvaGrabTempWithImplicitUse(false DEBUGARG("SwiftError pseudolocal")); lvaSetStruct(lvaSwiftErrorLocal, typeHnd, false); - lvaSetVarAddrExposed(lvaSwiftErrorLocal DEBUGARG(AddressExposedReason::ESCAPE_ADDRESS)); return true; } @@ -1727,11 +1726,13 @@ void Compiler::lvaClassifyParameterABI(Classifier& classifier) #ifdef DEBUG if (verbose) { - printf("Parameter #%u ABI info: ", i); + printf("Parameter V%02u ABI info: ", i); lvaParameterPassingInfo[i].Dump(); } #endif } + + lvaParameterStackSize = classifier.StackSize(); } //----------------------------------------------------------------------------- @@ -1765,7 +1766,7 @@ void Compiler::lvaClassifyParameterABI() for (unsigned lclNum = 0; lclNum < info.compArgsCount; lclNum++) { LclVarDsc* dsc = lvaGetDesc(lclNum); - const ABIPassingInformation& abiInfo = lvaParameterPassingInfo[lclNum]; + const ABIPassingInformation& abiInfo = lvaGetParameterABIInfo(lclNum); if (dsc->TypeGet() == TYP_STRUCT) { @@ -1812,12 +1813,10 @@ void Compiler::lvaClassifyParameterABI() } else #endif -#if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_ARM) { PlatformClassifier classifier(cInfo); lvaClassifyParameterABI(classifier); } -#endif #ifdef DEBUG if (lvaParameterPassingInfo == nullptr) @@ -1828,7 +1827,7 @@ void Compiler::lvaClassifyParameterABI() for (unsigned lclNum = 0; lclNum < info.compArgsCount; lclNum++) { LclVarDsc* dsc = lvaGetDesc(lclNum); - const ABIPassingInformation& abiInfo = lvaParameterPassingInfo[lclNum]; + const ABIPassingInformation& abiInfo = lvaGetParameterABIInfo(lclNum); assert(abiInfo.NumSegments > 0); @@ -1880,12 +1879,20 @@ void Compiler::lvaClassifyParameterABI() { assert(reg == REG_STK); + unsigned dscStackOffset = (unsigned)dsc->GetStackOffset(); +#ifdef WINDOWS_AMD64_ABI + // The LclVarDsc value does not account for the 4 shadow slots allocated by the caller. + dscStackOffset += 32; +#endif + // On x86, varargs methods access stack args off of a base pointer, and the // first stack arg is not considered to be at offset 0. // TODO-Cleanup: Unify things so that x86 is consistent with other platforms // here and change fgMorphExpandStackArgForVarArgs to account for that. -#ifndef TARGET_X86 - assert((unsigned)dsc->GetStackOffset() == expected.GetStackOffset()); +// LLVM: staock offsets are not aligned in the classifier, if they are then this passes and +// assert(segment.Offset + segment.Size <= lvaLclExactSize(lclNum)) below fails. +#if !defined(TARGET_X86) && !defined(TARGET_WASM) + assert(dscStackOffset == expected.GetStackOffset()); #endif } } @@ -1895,6 +1902,59 @@ void Compiler::lvaClassifyParameterABI() } } } + + for (unsigned lclNum = 0; lclNum < info.compArgsCount; lclNum++) + { + const ABIPassingInformation& abiInfo = lvaGetParameterABIInfo(lclNum); + + if (lvaIsImplicitByRefLocal(lclNum)) + { + assert((abiInfo.NumSegments == 1) && (abiInfo.Segments[0].Size == TARGET_POINTER_SIZE)); + } + else + { + for (unsigned i = 0; i < abiInfo.NumSegments; i++) + { + const ABIPassingSegment& segment = abiInfo.Segments[i]; + assert(segment.Size > 0); + assert(segment.Offset + segment.Size <= lvaLclExactSize(lclNum)); + + if (i > 0) + { + assert(segment.Offset > abiInfo.Segments[i - 1].Offset); + } + + for (unsigned j = 0; j < abiInfo.NumSegments; j++) + { + if (i == j) + { + continue; + } + + const ABIPassingSegment& otherSegment = abiInfo.Segments[j]; + assert((segment.Offset + segment.Size <= otherSegment.Offset) || + (segment.Offset >= otherSegment.Offset + otherSegment.Size)); + } + } + } + } + +#if FEATURE_FASTTAILCALL + // Swift doesn't have correct ABI info computed by the old classification, + // so skip this validation there. + if (info.compCallConv != CorInfoCallConvExtension::Swift) + { + unsigned oldStackSize = info.compArgStackSize; + +#ifdef WINDOWS_AMD64_ABI + // Old info does not take 4 shadow slots on win-x64 into account. + oldStackSize += 32; +#endif + + assert(lvaParameterStackSize == roundUp(oldStackSize, TARGET_POINTER_SIZE)); + } +#endif + #endif // DEBUG } @@ -1916,7 +1976,7 @@ bool Compiler::lvaHasAnySwiftStackParamToReassemble() for (unsigned lclNum = 0; lclNum < info.compArgsCount; lclNum++) { - const ABIPassingInformation& abiInfo = lvaParameterPassingInfo[lclNum]; + const ABIPassingInformation& abiInfo = lvaGetParameterABIInfo(lclNum); if (abiInfo.HasAnyStackSegment() && !abiInfo.HasExactlyOneStackSegment()) { return true; @@ -3180,10 +3240,6 @@ void Compiler::lvaSetVarDoNotEnregister(unsigned varNum DEBUGARG(DoNotEnregister JITDUMP("Promoted struct used by a SIMD/HWI node\n"); break; - case DoNotEnregisterReason::NonStandardParameter: - JITDUMP("Non-standard parameter\n"); - break; - default: unreached(); break; @@ -3191,6 +3247,43 @@ void Compiler::lvaSetVarDoNotEnregister(unsigned varNum DEBUGARG(DoNotEnregister #endif } +//------------------------------------------------------------------------ +// lvaIsArgAccessedViaVarArgsCookie: Check if a parameter has to be accessed +// indirectly via the varargs cookie. +// +// Arguments: +// lclNum - The local in question +// +// Return Value: +// True if it does. +// +// Remarks: +// Parameters passed on the stack in x86 varargs methods require special +// treatment for accesses and GC as their offsets are not known at compile +// time. +// +bool Compiler::lvaIsArgAccessedViaVarArgsCookie(unsigned lclNum) +{ +#ifdef TARGET_X86 + if (!info.compIsVarArgs) + { + return false; + } + + LclVarDsc* varDsc = lvaGetDesc(lclNum); + if (!varDsc->lvIsParam || (lclNum == lvaVarargsHandleArg)) + { + return false; + } + + const ABIPassingInformation& abiInfo = lvaGetParameterABIInfo(lclNum); + assert(abiInfo.HasExactlyOneStackSegment() || abiInfo.HasExactlyOneRegisterSegment()); + return abiInfo.HasExactlyOneStackSegment(); +#else + return false; +#endif +} + //------------------------------------------------------------------------ // lvaIsImplicitByRefLocal: Is the local an "implicit byref" parameter? // @@ -4077,11 +4170,13 @@ void Compiler::lvaSortByRefCount() case TYP_SIMD8: case TYP_SIMD12: case TYP_SIMD16: -#if defined(TARGET_XARCH) +#ifdef TARGET_XARCH case TYP_SIMD32: case TYP_SIMD64: - case TYP_MASK: #endif // TARGET_XARCH +#ifdef FEATURE_MASKED_HW_INTRINSICS + case TYP_MASK: +#endif // FEATURE_MASKED_HW_INTRINSICS #endif // FEATURE_SIMD case TYP_STRUCT: break; @@ -4842,7 +4937,7 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers) // and not tracked. for (lclNum = 0, varDsc = lvaTable; lclNum < lvaCount; lclNum++, varDsc++) { - const bool isSpecialVarargsParam = varDsc->lvIsParam && raIsVarargsStackArg(lclNum); + const bool isSpecialVarargsParam = varDsc->lvIsParam && lvaIsArgAccessedViaVarArgsCookie(lclNum); if (isSpecialVarargsParam) { @@ -4874,7 +4969,7 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers) // Special case for some varargs params ... these must // remain unreferenced. - const bool isSpecialVarargsParam = varDsc->lvIsParam && raIsVarargsStackArg(lclNum); + const bool isSpecialVarargsParam = varDsc->lvIsParam && lvaIsArgAccessedViaVarArgsCookie(lclNum); if (!isSpecialVarargsParam) { @@ -5020,7 +5115,7 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers) // to track them for GC info (which is not possible since we // don't know their offset in the stack). See the assert at the // end of raMarkStkVars and bug #28949 for more info. - if (!raIsVarargsStackArg(lclNum)) + if (!lvaIsArgAccessedViaVarArgsCookie(lclNum)) { varDsc->lvImplicitlyReferenced = 1; } @@ -5647,23 +5742,52 @@ void Compiler::lvaFixVirtualFrameOffsets() // We set FP to be after LR, FP delta += 2 * REGSIZE_BYTES; } -#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) +#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) else { // FP is used. JITDUMP("--- delta bump %d for FP frame\n", codeGen->genTotalFrameSize() - codeGen->genSPtoFPdelta()); delta += codeGen->genTotalFrameSize() - codeGen->genSPtoFPdelta(); } -#endif // TARGET_AMD64 || TARGET_ARM64 || TARGET_LOONGARCH64 || TARGET_RISCV64 +#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) + else + { + // FP is used. + delta += (compCalleeRegsPushed << 3); + + if ((lvaMonAcquired != BAD_VAR_NUM) && !opts.IsOSR()) + { + int offset = lvaTable[lvaMonAcquired].GetStackOffset() + delta; + lvaTable[lvaMonAcquired].SetStackOffset(offset); + + if (lvaPSPSym != BAD_VAR_NUM) + { + int offset = lvaTable[lvaPSPSym].GetStackOffset() + delta; + lvaTable[lvaPSPSym].SetStackOffset(offset); + delta += TARGET_POINTER_SIZE; + } + + delta += lvaLclSize(lvaMonAcquired); + } + else if (lvaPSPSym != BAD_VAR_NUM) + { + int offset = lvaTable[lvaPSPSym].GetStackOffset() + delta; + lvaTable[lvaPSPSym].SetStackOffset(offset); + delta += TARGET_POINTER_SIZE; + } + + JITDUMP("--- delta bump %d for FP frame\n", delta); + } +#endif // !TARGET_LOONGARCH64 || !TARGET_RISCV64 if (opts.IsOSR()) { -#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) // Stack offset includes Tier0 frame. // JITDUMP("--- delta bump %d for OSR + Tier0 frame\n", info.compPatchpointInfo->TotalFrameSize()); delta += info.compPatchpointInfo->TotalFrameSize(); -#endif +#endif // TARGET_AMD64 || TARGET_ARM64 } JITDUMP("--- virtual stack offset to actual stack offset delta is %d\n", delta); @@ -5753,26 +5877,20 @@ void Compiler::lvaFixVirtualFrameOffsets() #endif // FEATURE_FIXED_OUT_ARGS -#if defined(TARGET_ARM64) +#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) // We normally add alignment below the locals between them and the outgoing // arg space area. When we store fp/lr(ra) at the bottom, however, this will // be below the alignment. So we should not apply the alignment adjustment to // them. It turns out we always store these at +0 and +8 of the FP, // so instead of dealing with skipping adjustment just for them we just set // them here always. + // For LoongArch64 and RISCV64, the RA is always at fp+8. assert(codeGen->isFramePointerUsed()); if (lvaRetAddrVar != BAD_VAR_NUM) { lvaTable[lvaRetAddrVar].SetStackOffset(REGSIZE_BYTES); } -#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - assert(codeGen->isFramePointerUsed()); - if (lvaRetAddrVar != BAD_VAR_NUM) - { - // For LoongArch64 and RISCV64, the RA is below the fp. see the `genPushCalleeSavedRegisters` - lvaTable[lvaRetAddrVar].SetStackOffset(-REGSIZE_BYTES); - } -#endif // !TARGET_LOONGARCH64 +#endif // !TARGET_ARM64 || !TARGET_LOONGARCH64 || !TARGET_RISCV64 } #ifdef TARGET_ARM @@ -5831,642 +5949,156 @@ void Compiler::lvaUpdateArgsWithInitialReg() } } -/***************************************************************************** - * lvaAssignVirtualFrameOffsetsToArgs() : Assign virtual stack offsets to the - * arguments, and implicit arguments (this ptr, return buffer, generics, - * and varargs). - */ +#if !defined(TARGET_WASM) +//----------------------------------------------------------------------------- +// lvaAssignVirtualFrameOffsetsToArgs: +// Assign virtual frame offsets to the incoming parameters. +// void Compiler::lvaAssignVirtualFrameOffsetsToArgs() { - unsigned lclNum = 0; - int argOffs = 0; -#ifdef UNIX_AMD64_ABI - int callerArgOffset = 0; -#endif // UNIX_AMD64_ABI - - /* - Assign stack offsets to arguments (in reverse order of passing). - - This means that if we pass arguments left->right, we start at - the end of the list and work backwards, for right->left we start - with the first argument and move forward. - - This is all relative to our Virtual '0' - */ - - if (info.compArgOrder == Target::ARG_ORDER_L2R) - { - argOffs = compArgSize; - } - - /* Update the argOffs to reflect arguments that are passed in registers */ - - noway_assert(codeGen->intRegState.rsCalleeRegArgCount <= MAX_REG_ARG); - noway_assert(compAppleArm64Abi() || compArgSize >= codeGen->intRegState.rsCalleeRegArgCount * REGSIZE_BYTES); - - if (info.compArgOrder == Target::ARG_ORDER_L2R) - { - argOffs -= codeGen->intRegState.rsCalleeRegArgCount * REGSIZE_BYTES; - } - - // Update the arg initial register locations. - lvaUpdateArgsWithInitialReg(); - -#ifdef SWIFT_SUPPORT - if (info.compCallConv == CorInfoCallConvExtension::Swift) - { - // We already assigned argument offsets in lvaClassifyParameterABI. - // Just get them from there. - // TODO-Cleanup: We can use similar logic for all backends once we have - // the new ABI info for all targets. - for (unsigned lclNum = 0; lclNum < info.compArgsCount; lclNum++) - { - LclVarDsc* dsc = lvaGetDesc(lclNum); - const ABIPassingInformation& abiInfo = lvaParameterPassingInfo[lclNum]; - - if (abiInfo.HasExactlyOneStackSegment()) - { - dsc->SetStackOffset(abiInfo.Segments[0].GetStackOffset()); - } - } - return; - } -#endif - - /* Is there a "this" argument? */ - - if (!info.compIsStatic) - { - noway_assert(lclNum == info.compThisArg); -#ifndef TARGET_X86 - argOffs = - lvaAssignVirtualFrameOffsetToArg(lclNum, REGSIZE_BYTES, argOffs UNIX_AMD64_ABI_ONLY_ARG(&callerArgOffset)); -#endif // TARGET_X86 - lclNum++; - } - - unsigned userArgsToSkip = 0; -#if !defined(TARGET_ARM) - // In the native instance method calling convention on Windows, - // the this parameter comes before the hidden return buffer parameter. - // So, we want to process the native "this" parameter before we process - // the native return buffer parameter. - if (TargetOS::IsWindows && callConvIsInstanceMethodCallConv(info.compCallConv)) - { -#ifdef TARGET_X86 - if (!lvaTable[lclNum].lvIsRegArg) - { - argOffs = lvaAssignVirtualFrameOffsetToArg(lclNum, REGSIZE_BYTES, argOffs); - } -#elif !defined(UNIX_AMD64_ABI) - argOffs = lvaAssignVirtualFrameOffsetToArg(lclNum, REGSIZE_BYTES, argOffs); -#endif // TARGET_X86 - lclNum++; - userArgsToSkip++; - } + int relativeZero = 0; +#ifdef TARGET_ARM + // arm32 is special and has the concept of "prespill" where we generate + // code in the callee to spill the argument registers as the very first + // thing, and consider those to be actually passed by the caller. The + // virtual 0 is actually below these prespills. + // TODO-Cleanup: Unify arm32 with arm64. arm64 also needs a similar + // mechanism for split parameters in varargs, but it does not consider the + // "virtual 0" to be below the prespills, which simplifies things + // considerably. + regMaskTP prespilled = codeGen->regSet.rsMaskPreSpillRegs(true); + JITDUMP("Prespill regs is "); + DBEXEC(VERBOSE, dspRegMask(prespilled)); + JITDUMP("\n"); + relativeZero = genCountBits(prespilled) * TARGET_POINTER_SIZE; #endif - /* if we have a hidden buffer parameter, that comes here */ - - if (info.compRetBuffArg != BAD_VAR_NUM) - { - noway_assert(lclNum == info.compRetBuffArg); - argOffs = - lvaAssignVirtualFrameOffsetToArg(lclNum, REGSIZE_BYTES, argOffs UNIX_AMD64_ABI_ONLY_ARG(&callerArgOffset)); - lclNum++; - } - -#if USER_ARGS_COME_LAST - - //@GENERICS: extra argument for instantiation info - if (info.compMethodInfo->args.callConv & CORINFO_CALLCONV_PARAMTYPE) - { - noway_assert(lclNum == info.compTypeCtxtArg); - argOffs = lvaAssignVirtualFrameOffsetToArg(lclNum++, REGSIZE_BYTES, - argOffs UNIX_AMD64_ABI_ONLY_ARG(&callerArgOffset)); - } - - if (info.compIsVarArgs) - { - argOffs = lvaAssignVirtualFrameOffsetToArg(lclNum++, REGSIZE_BYTES, - argOffs UNIX_AMD64_ABI_ONLY_ARG(&callerArgOffset)); - } - -#endif // USER_ARGS_COME_LAST - - CORINFO_ARG_LIST_HANDLE argLst = info.compMethodInfo->args.args; - unsigned argSigLen = info.compMethodInfo->args.numArgs; - // Skip any user args that we've already processed. - assert(userArgsToSkip <= argSigLen); - argSigLen -= userArgsToSkip; - for (unsigned i = 0; i < userArgsToSkip; i++, argLst = info.compCompHnd->getArgNext(argLst)) + for (unsigned lclNum = 0; lclNum < info.compArgsCount; lclNum++) { - ; - } + LclVarDsc* dsc = lvaGetDesc(lclNum); -#ifdef TARGET_ARM - // - // struct_n { int; int; ... n times }; - // - // Consider signature: - // - // Foo (float a,double b,float c,double d,float e,double f,float g,double h, - // float i,double j,float k,double l,struct_3 m) { } - // - // Basically the signature is: (all float regs full, 1 double, struct_3); - // - // The double argument occurs before pre spill in the argument iteration and - // computes an argOffset of 0. struct_3 offset becomes 8. This is wrong. - // Because struct_3 is prespilled and double occurs after prespill. - // The correct offsets are double = 16 (aligned stk), struct_3 = 0..12, - // Offset 12 will be skipped for double alignment of double. - // - // Another example is (struct_2, all float regs full, double, struct_2); - // Here, notice the order is similarly messed up because of 2 pre-spilled - // struct_2. - // - // Succinctly, - // ARG_INDEX(i) > ARG_INDEX(j) DOES NOT IMPLY |ARG_OFFSET(i)| > |ARG_OFFSET(j)| - // - // Therefore, we'll do a two pass offset calculation, one that considers pre-spill - // and the next, stack args. - // - - unsigned argLcls = 0; - - // Take care of pre spill registers first. - regMaskTP preSpillMask = codeGen->regSet.rsMaskPreSpillRegs(false); - regMaskTP tempMask = RBM_NONE; - for (unsigned i = 0, preSpillLclNum = lclNum; i < argSigLen; ++i, ++preSpillLclNum) - { - if (lvaIsPreSpilled(preSpillLclNum, preSpillMask)) + int startOffset; + if (lvaGetRelativeOffsetToCallerAllocatedSpaceForParameter(lclNum, &startOffset)) { - CORINFO_CLASS_HANDLE argClass = NO_CLASS_HANDLE; - CorInfoType argTypeJit = strip(info.compCompHnd->getArgType(&info.compMethodInfo->args, argLst, &argClass)); - unsigned argSize = eeGetArgSize(argTypeJit, argClass); - argOffs = lvaAssignVirtualFrameOffsetToArg(preSpillLclNum, argSize, argOffs); - argLcls++; + dsc->SetStackOffset(startOffset + relativeZero); + JITDUMP("Set V%02u to offset %d\n", lclNum, startOffset); - // Early out if we can. If size is 8 and base reg is 2, then the mask is 0x1100 - tempMask |= ((((1 << (roundUp(argSize, TARGET_POINTER_SIZE) / REGSIZE_BYTES))) - 1) - << lvaTable[preSpillLclNum].GetArgReg()); - if (tempMask == preSpillMask) + if (dsc->lvPromoted) { - // We won't encounter more pre-spilled registers, - // so don't bother iterating further. - break; + for (unsigned fld = 0; fld < dsc->lvFieldCnt; fld++) + { + unsigned fieldLclNum = dsc->lvFieldLclStart + fld; + LclVarDsc* fieldVarDsc = lvaGetDesc(fieldLclNum); + fieldVarDsc->SetStackOffset(dsc->GetStackOffset() + fieldVarDsc->lvFldOffset); + JITDUMP(" Set field V%02u to offset %d\n", fieldLclNum, fieldVarDsc->GetStackOffset()); + } } } - argLst = info.compCompHnd->getArgNext(argLst); - } - - // Take care of non pre-spilled stack arguments. - argLst = info.compMethodInfo->args.args; - for (unsigned i = 0, stkLclNum = lclNum; i < argSigLen; ++i, ++stkLclNum) - { - if (!lvaIsPreSpilled(stkLclNum, preSpillMask)) - { - CORINFO_CLASS_HANDLE argClass = NO_CLASS_HANDLE; - CorInfoType argTypeJit = strip(info.compCompHnd->getArgType(&info.compMethodInfo->args, argLst, &argClass)); - const unsigned argSize = eeGetArgSize(argTypeJit, argClass); - argOffs = lvaAssignVirtualFrameOffsetToArg(stkLclNum, argSize, argOffs); - argLcls++; - } - argLst = info.compCompHnd->getArgNext(argLst); - } - - lclNum += argLcls; -#else // !TARGET_ARM - for (unsigned i = 0; i < argSigLen; i++) - { - CORINFO_CLASS_HANDLE argClass = NO_CLASS_HANDLE; - CorInfoType argTypeJit = strip(info.compCompHnd->getArgType(&info.compMethodInfo->args, argLst, &argClass)); - unsigned argumentSize = eeGetArgSize(argTypeJit, argClass); - - assert(compAppleArm64Abi() || argumentSize % TARGET_POINTER_SIZE == 0); - - argOffs = - lvaAssignVirtualFrameOffsetToArg(lclNum++, argumentSize, argOffs UNIX_AMD64_ABI_ONLY_ARG(&callerArgOffset)); - argLst = info.compCompHnd->getArgNext(argLst); - } -#endif // !TARGET_ARM - -#if !USER_ARGS_COME_LAST - - //@GENERICS: extra argument for instantiation info - if (info.compMethodInfo->args.callConv & CORINFO_CALLCONV_PARAMTYPE) - { - noway_assert(lclNum == info.compTypeCtxtArg); - argOffs = lvaAssignVirtualFrameOffsetToArg(lclNum++, REGSIZE_BYTES, - argOffs UNIX_AMD64_ABI_ONLY_ARG(&callerArgOffset)); - } - - if (info.compIsVarArgs) - { - argOffs = lvaAssignVirtualFrameOffsetToArg(lclNum++, REGSIZE_BYTES, - argOffs UNIX_AMD64_ABI_ONLY_ARG(&callerArgOffset)); } - -#endif // USER_ARGS_COME_LAST } +#endif // !TARGET_WASM -#ifdef UNIX_AMD64_ABI +//----------------------------------------------------------------------------- +// lvaGetRelativeOffsetToCallerAllocatedSpaceForParameter: +// Return offset to use for a parameter local when the caller allocated space +// for (parts of) it. The offset returned is relative to the bottom of the +// space allocated by the caller (our "virtual 0", see lvaAssignFrameOffsets +// documentation). // -// lvaAssignVirtualFrameOffsetToArg() : Assign virtual stack offsets to an -// individual argument, and return the offset for the next argument. -// Note: This method only calculates the initial offset of the stack passed/spilled arguments -// (if any - the RA might decide to spill(home on the stack) register passed arguments, if rarely used.) -// The final offset is calculated in lvaFixVirtualFrameOffsets method. It accounts for FP existence, -// ret address slot, stack frame padding, alloca instructions, etc. -// Note: This is the implementation for UNIX_AMD64 System V platforms. -// -int Compiler::lvaAssignVirtualFrameOffsetToArg(unsigned lclNum, - unsigned argSize, - int argOffs UNIX_AMD64_ABI_ONLY_ARG(int* callerArgOffset)) -{ - noway_assert(lclNum < info.compArgsCount); - noway_assert(argSize); - - if (info.compArgOrder == Target::ARG_ORDER_L2R) - { - argOffs -= argSize; - } - - unsigned fieldVarNum = BAD_VAR_NUM; - - LclVarDsc* varDsc = lvaGetDesc(lclNum); - - noway_assert(varDsc->lvIsParam); - - if (varDsc->lvIsRegArg) - { - // Argument is passed in a register, don't count it - // when updating the current offset on the stack. - - if (varDsc->lvOnFrame) - { - // The offset for args needs to be set only for the stack homed arguments for System V. - varDsc->SetStackOffset(argOffs); - } - else - { - varDsc->SetStackOffset(0); - } - } - else - { - // For Windows AMD64 there are 4 slots for the register passed arguments on the top of the caller's stack. - // This is where they are always homed. So, they can be accessed with positive offset. - // On System V platforms, if the RA decides to home a register passed arg on the stack, it creates a stack - // location on the callee stack (like any other local var.) In such a case, the register passed, stack homed - // arguments are accessed using negative offsets and the stack passed arguments are accessed using positive - // offset (from the caller's stack.) - // For System V platforms if there is no frame pointer the caller stack parameter offset should include the - // callee allocated space. If frame register is used, the callee allocated space should not be included for - // accessing the caller stack parameters. The last two requirements are met in lvaFixVirtualFrameOffsets - // method, which fixes the offsets, based on frame pointer existence, existence of alloca instructions, ret - // address pushed, ets. - - varDsc->SetStackOffset(*callerArgOffset); - // Structs passed on stack could be of size less than TARGET_POINTER_SIZE. - // Make sure they get at least TARGET_POINTER_SIZE on the stack - this is required for alignment. - if (argSize > TARGET_POINTER_SIZE) - { - *callerArgOffset += (int)roundUp(argSize, TARGET_POINTER_SIZE); - } - else - { - *callerArgOffset += TARGET_POINTER_SIZE; - } - } - - // For struct promoted parameters we need to set the offsets for the field lclVars. - // - // For a promoted struct we also assign the struct fields stack offset - if (varDsc->lvPromoted) - { - unsigned firstFieldNum = varDsc->lvFieldLclStart; - int offset = varDsc->GetStackOffset(); - for (unsigned i = 0; i < varDsc->lvFieldCnt; i++) - { - LclVarDsc* fieldVarDsc = lvaGetDesc(firstFieldNum + i); - fieldVarDsc->SetStackOffset(offset + fieldVarDsc->lvFldOffset); - } - } - - if (info.compArgOrder == Target::ARG_ORDER_R2L && !varDsc->lvIsRegArg) - { - argOffs += argSize; - } - - return argOffs; -} - -#else // !UNIX_AMD64_ABI - +// Parameters: +// lclNum - Parameter local +// offset - [out] Offset to use for the parameter local. Only valid when the +// function returns true. +// +// Returns: +// true if the caller allocated space that the JIT should reuse for the +// parameter's home. // -// lvaAssignVirtualFrameOffsetToArg() : Assign virtual stack offsets to an -// individual argument, and return the offset for the next argument. -// Note: This method only calculates the initial offset of the stack passed/spilled arguments -// (if any - the RA might decide to spill(home on the stack) register passed arguments, if rarely used.) -// The final offset is calculated in lvaFixVirtualFrameOffsets method. It accounts for FP existence, -// ret address slot, stack frame padding, alloca instructions, etc. -// Note: This implementation for all the platforms but UNIX_AMD64 OSs (System V 64 bit.) -int Compiler::lvaAssignVirtualFrameOffsetToArg(unsigned lclNum, - unsigned argSize, - int argOffs UNIX_AMD64_ABI_ONLY_ARG(int* callerArgOffset)) +// Remarks: +// The most common situation is for stack parameters, but there are other +// cases where we have usable space allocated by the caller: +// - On win-x64 the caller allocates stack space even for args passed in +// registers +// - On multiple ABIs (see below) structs can be passed split across stack +// and registers, where this function may then return an offset that only +// partially reaches into caller allocated space (i.e. negative) +// - On arm32 we sometimes prespill argument registers and consider it to be +// caller allocated, making this function also return a negative offset for +// some register parameters in that case. +// +bool Compiler::lvaGetRelativeOffsetToCallerAllocatedSpaceForParameter(unsigned lclNum, int* offset) { - noway_assert(lclNum < info.compArgsCount); - noway_assert(argSize); - - if (info.compArgOrder == Target::ARG_ORDER_L2R) - { - argOffs -= argSize; - } - - unsigned fieldVarNum = BAD_VAR_NUM; - - LclVarDsc* varDsc = lvaGetDesc(lclNum); - - noway_assert(varDsc->lvIsParam); + const ABIPassingInformation& abiInfo = lvaGetParameterABIInfo(lclNum); - if (varDsc->lvIsRegArg) + for (unsigned i = 0; i < abiInfo.NumSegments; i++) { - /* Argument is passed in a register, don't count it - * when updating the current offset on the stack */ - -#if !defined(TARGET_ARMARCH) && !defined(TARGET_LOONGARCH64) && !defined(TARGET_RISCV64) -#if DEBUG - // TODO: Remove this noway_assert and replace occurrences of TARGET_POINTER_SIZE with argSize - // Also investigate why we are incrementing argOffs for X86 as this seems incorrect - // - noway_assert(argSize == TARGET_POINTER_SIZE); -#endif // DEBUG -#endif - -#if defined(TARGET_X86) - argOffs += TARGET_POINTER_SIZE; -#elif defined(TARGET_AMD64) || defined(TARGET_WASM) // TODO Wasm - // Register arguments on AMD64 also takes stack space. (in the backing store) - varDsc->SetStackOffset(argOffs); - argOffs += TARGET_POINTER_SIZE; -#elif defined(TARGET_ARM64) - // Register arguments on ARM64 only take stack space when they have a frame home. - // Unless on windows and in a vararg method. - if (compFeatureArgSplit() && this->info.compIsVarArgs) + const ABIPassingSegment& segment = abiInfo.Segments[i]; + if (!segment.IsPassedOnStack()) { - if (varDsc->lvType == TYP_STRUCT && varDsc->GetOtherArgReg() >= MAX_REG_ARG && - varDsc->GetOtherArgReg() != REG_NA) +#if defined(WINDOWS_AMD64_ABI) + if (ABIPassingInformation::GetShadowSpaceCallerOffsetForReg(segment.GetRegister(), offset)) { - // This is a split struct. It will account for an extra (8 bytes) - // of alignment. - varDsc->SetStackOffset(varDsc->GetStackOffset() + TARGET_POINTER_SIZE); - argOffs += TARGET_POINTER_SIZE; + return true; } - } - #elif defined(TARGET_ARM) - // On ARM we spill the registers in codeGen->regSet.rsMaskPreSpillRegArg - // in the prolog, so we have to do SetStackOffset() here - // - regMaskTP regMask = genRegMask(varDsc->GetArgReg()); - if (codeGen->regSet.rsMaskPreSpillRegArg & regMask) - { - // Signature: void foo(struct_8, int, struct_4) - // ------- CALLER SP ------- - // r3 struct_4 - // r2 int - not prespilled, but added for alignment. argOffs should skip this. - // r1 struct_8 - // r0 struct_8 - // ------------------------- - // If we added alignment we need to fix argOffs for all registers above alignment. - if (codeGen->regSet.rsMaskPreSpillAlign != RBM_NONE) - { - assert(genCountBits(codeGen->regSet.rsMaskPreSpillAlign) == 1); - // Is register beyond the alignment pos? - if (regMask > codeGen->regSet.rsMaskPreSpillAlign) - { - // Increment argOffs just once for the _first_ register after alignment pos - // in the prespill mask. - if (!BitsBetween(codeGen->regSet.rsMaskPreSpillRegArg, regMask, - codeGen->regSet.rsMaskPreSpillAlign)) - { - argOffs += TARGET_POINTER_SIZE; - } - } + regMaskTP prespills = codeGen->regSet.rsMaskPreSpillRegs(true); + if ((prespills & genRegMask(segment.GetRegister())) != RBM_NONE) + { + // Construct a mask with all prespills that includes the + // segment's register and all registers after it. For example: + // prespills: 1101 (i.e. prolog starts with push {r0, r2, r3} + // reg: 0100 (i.e. r2 which is at offset -8) + // higherPrespills: 1100 (=> r2, r3) + regMaskTP higherPrespills = prespills & (regMaskTP)(~((1ULL << (int)segment.GetRegister()) - 1)); + *offset = -(int)genCountBits(higherPrespills) * TARGET_POINTER_SIZE; + + // Adjust for a potential split (we currently always expect all + // split structs to be fully prespilled, but this makes the + // logic general and matches the logic below). + *offset -= segment.Offset; + return true; } +#endif - switch (varDsc->lvType) - { - case TYP_STRUCT: - if (!varDsc->lvStructDoubleAlign) - { - break; - } - FALLTHROUGH; - - case TYP_DOUBLE: - case TYP_LONG: - { - // - // Let's assign offsets to arg1, a double in r2. argOffs has to be 4 not 8. - // - // ------- CALLER SP ------- - // r3 - // r2 double -- argOffs = 4, but it doesn't need to be skipped, because there is no skipping. - // r1 VACookie -- argOffs = 0 - // ------------------------- - // - // Consider argOffs as if it accounts for number of prespilled registers before the current - // register. In the above example, for r2, it is r1 that is prespilled, but since r1 is - // accounted for by argOffs being 4, there should have been no skipping. Instead, if we didn't - // assign r1 to any variable, then argOffs would still be 0 which implies it is not accounting - // for r1, equivalently r1 is skipped. - // - // If prevRegsSize is unaccounted for by a corresponding argOffs, we must have skipped a register. - int prevRegsSize = - genCountBits(codeGen->regSet.rsMaskPreSpillRegArg & (regMask - 1)) * TARGET_POINTER_SIZE; - if (argOffs < prevRegsSize) - { - // We must align up the argOffset to a multiple of 8 to account for skipped registers. - argOffs = roundUp((unsigned)argOffs, 2 * TARGET_POINTER_SIZE); - } - // We should've skipped only a single register. - assert(argOffs == prevRegsSize); - } - break; - - default: - // No alignment of argOffs required - break; - } - varDsc->SetStackOffset(argOffs); - argOffs += argSize; + continue; } -#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - - if (varDsc->lvIsSplit) + if (info.compArgOrder == Target::ARG_ORDER_L2R) { - assert((varDsc->lvType == TYP_STRUCT) && (varDsc->GetOtherArgReg() == REG_STK)); - // This is a split struct. It will account for an extra (8 bytes) for the whole struct. - varDsc->SetStackOffset(varDsc->GetStackOffset() + TARGET_POINTER_SIZE); - argOffs += TARGET_POINTER_SIZE; + // This is the managed x86 ABI. Stack offsets saved in ABI + // information is relative to the top of the stack frame here. + assert(segment.Offset == 0); + *offset = (int)(lvaParameterStackSize - segment.GetStackOffset()); } - -#else // TARGET* -#error Unsupported or unset target architecture -#endif // TARGET* - } - else - { -#if defined(TARGET_ARM) - // Dev11 Bug 42817: incorrect codegen for DrawFlatCheckBox causes A/V in WinForms - // - // Here we have method with a signature (int a1, struct a2, struct a3, int a4, int a5). - // Struct parameter 'a2' is 16-bytes with no alignment requirements; - // it uses r1,r2,r3 and [OutArg+0] when passed. - // Struct parameter 'a3' is 16-bytes that is required to be double aligned; - // the caller skips [OutArg+4] and starts the argument at [OutArg+8]. - // Thus the caller generates the correct code to pass the arguments. - // When generating code to receive the arguments we set codeGen->regSet.rsMaskPreSpillRegArg to [r1,r2,r3] - // and spill these three registers as the first instruction in the prolog. - // Then when we layout the arguments' stack offsets we have an argOffs 0 which - // points at the location that we spilled r1 into the stack. For this first - // struct we take the lvIsRegArg path above with "codeGen->regSet.rsMaskPreSpillRegArg &" matching. - // Next when we calculate the argOffs for the second 16-byte struct we have an argOffs - // of 16, which appears to be aligned properly so we don't skip a stack slot. - // - // To fix this we must recover the actual OutArg offset by subtracting off the - // sizeof of the PreSpill register args. - // Then we align this offset to a multiple of 8 and add back the sizeof - // of the PreSpill register args. - // - // Dev11 Bug 71767: failure of assert(sizeofPreSpillRegArgs <= argOffs) - // - // We have a method with 'this' passed in r0, RetBuf arg in r1, VarArgs cookie - // in r2. The first user arg is a 144 byte struct with double alignment required, - // r3 is skipped, and the struct is passed on the stack. However, 'r3' is added - // to the codeGen->regSet.rsMaskPreSpillRegArg mask by the VarArgs cookie code, since we need to - // home all the potential varargs arguments in registers, even if we don't have - // signature type information for the variadic arguments. However, due to alignment, - // we have skipped a register that doesn't have a corresponding symbol. Make up - // for that by increasing argOffs here. - // - - int sizeofPreSpillRegArgs = genCountBits(codeGen->regSet.rsMaskPreSpillRegs(true)) * REGSIZE_BYTES; - - if (argOffs < sizeofPreSpillRegArgs) + else { - // This can only happen if we skipped the last register spot because current stk arg - // is a struct requiring alignment or a pre-spill alignment was required because the - // first reg arg needed alignment. + // Some ABIs may split parameters across registers and stack: // - // Example 1: First Stk Argument requiring alignment in vararg case (same as above comment.) - // Signature (int a0, int a1, int a2, struct {long} a3, ...) + // - On Windows, the Arm64 varargs ABI can split a 16 byte struct across x7 and stack + // - Arm32 generally allows structs to be split + // - LA64/RISCV64 both allow splitting of 16-byte structs across 1 register and stack + // - The Swift ABI can split parameters across multiple register and multiple stack segments // - // stk arg a3 --> argOffs here will be 12 (r0-r2) but pre-spill will be 16. - // ---- Caller SP ---- - // r3 --> Stack slot is skipped in this case. - // r2 int a2 - // r1 int a1 - // r0 int a0 + // Of these, Swift and RISCV64/LA64 are handled separately, by + // reassembling the split structs entirely on the local stack + // frame. Thus the offsets returned here and assigned inside + // lvaAssignVirtualFrameOffsetsToArgs are overwritten later. // - // Example 2: First Reg Argument requiring alignment in no-vararg case. - // Signature (struct {long} a0, struct {int} a1, int a2, int a3) + // For ARM64 and ARM32 we use a different strategy to reassemble + // the struct on the stack frame: we consider the local itself to + // start right before the "virtual 0", such that spilling the + // register parts will end up with the local fully reassembled and + // contiguous, without having to move any of the stack segments. + // The subtraction of the segment offset accomplishes that here. // - // stk arg --> argOffs here will be 12 {r0-r2} but pre-spill will be 16. - // ---- Caller SP ---- - // r3 int a2 --> pushed (not pre-spilled) for alignment of a0 by lvaInitUserArgs. - // r2 struct { int } a1 - // r0-r1 struct { long } a0 - -#ifdef PROFILING_SUPPORTED - // On Arm under profiler, r0-r3 are always prespilled on stack. - // It is possible to have methods that accept only HFAs as parameters e.g. Signature(struct hfa1, struct - // hfa2), in which case hfa1 and hfa2 will be en-registered in co-processor registers and will have an - // argument offset less than size of preSpill. - // - // For this reason the following conditions are asserted when not under profiler. - if (!compIsProfilerHookNeeded()) -#endif - { - bool cond = ((info.compIsVarArgs || opts.compUseSoftFP) && - // Does cur stk arg require double alignment? - ((varDsc->lvType == TYP_STRUCT && varDsc->lvStructDoubleAlign) || - (varDsc->lvType == TYP_DOUBLE) || (varDsc->lvType == TYP_LONG))) || - // Did first reg arg require alignment? - (codeGen->regSet.rsMaskPreSpillAlign & genRegMask(REG_ARG_LAST)); - - noway_assert(cond); - noway_assert(sizeofPreSpillRegArgs <= argOffs + TARGET_POINTER_SIZE); // at most one register of - // alignment - } - argOffs = sizeofPreSpillRegArgs; + *offset = (int)segment.GetStackOffset() - (int)segment.Offset; } - noway_assert(argOffs >= sizeofPreSpillRegArgs); - int argOffsWithoutPreSpillRegArgs = argOffs - sizeofPreSpillRegArgs; - - switch (varDsc->lvType) - { - case TYP_STRUCT: - if (!varDsc->lvStructDoubleAlign) - break; - - FALLTHROUGH; - - case TYP_DOUBLE: - case TYP_LONG: - // We must align up the argOffset to a multiple of 8 - argOffs = - roundUp((unsigned)argOffsWithoutPreSpillRegArgs, 2 * TARGET_POINTER_SIZE) + sizeofPreSpillRegArgs; - break; - - default: - // No alignment of argOffs required - break; - } -#endif // TARGET_ARM - const bool isFloatHfa = (varDsc->lvIsHfa() && (varDsc->GetHfaType() == TYP_FLOAT)); - const unsigned argAlignment = eeGetArgSizeAlignment(varDsc->lvType, isFloatHfa); - if (compAppleArm64Abi()) - { - argOffs = roundUp(argOffs, argAlignment); - } - - assert((argSize % argAlignment) == 0); - assert((argOffs % argAlignment) == 0); - varDsc->SetStackOffset(argOffs); - } - - // For struct promoted parameters we need to set the offsets for both LclVars. - // - // For a dependent promoted struct we also assign the struct fields stack offset - - if (varDsc->lvPromoted) - { - unsigned firstFieldNum = varDsc->lvFieldLclStart; - for (unsigned i = 0; i < varDsc->lvFieldCnt; i++) - { - LclVarDsc* fieldVarDsc = lvaGetDesc(firstFieldNum + i); - - JITDUMP("Adjusting offset of dependent V%02u of arg V%02u: parent %u field %u net %u\n", lclNum, - firstFieldNum + i, varDsc->GetStackOffset(), fieldVarDsc->lvFldOffset, - varDsc->GetStackOffset() + fieldVarDsc->lvFldOffset); - - fieldVarDsc->SetStackOffset(varDsc->GetStackOffset() + fieldVarDsc->lvFldOffset); - } - } - - if (info.compArgOrder == Target::ARG_ORDER_R2L && !varDsc->lvIsRegArg) - { - argOffs += argSize; + return true; } - return argOffs; + return false; } -#endif // !UNIX_AMD64_ABI //----------------------------------------------------------------------------- // lvaAssignVirtualFrameOffsetsToLocals: compute the virtual stack offsets for @@ -6526,9 +6158,13 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() // if (opts.IsOSR()) { +#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) + originalFrameStkOffs = info.compPatchpointInfo->TotalFrameSize(); +#else originalFrameSize = info.compPatchpointInfo->TotalFrameSize(); originalFrameStkOffs = stkOffs; stkOffs -= originalFrameSize; +#endif } #ifdef TARGET_XARCH @@ -6584,7 +6220,8 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() #elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - assert(compCalleeRegsPushed >= 2); + assert(compCalleeRegsPushed >= 2); // always FP/RA. + stkOffs -= (compCalleeRegsPushed << 3); #else // !TARGET_LOONGARCH64 && !TARGET_RISCV64 #ifdef TARGET_ARM @@ -7051,22 +6688,6 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() continue; } - // This should be low on the stack. Hence, it will be assigned later. - if (lclNum == lvaStubArgumentVar) - { -#ifdef JIT32_GCENCODER - noway_assert(codeGen->isFramePointerUsed()); -#endif - continue; - } - - // This should be low on the stack. Hence, it will be assigned later. - if (lclNum == lvaInlinedPInvokeFrameVar) - { - noway_assert(codeGen->isFramePointerUsed()); - continue; - } - if (varDsc->lvIsParam) { #ifdef TARGET_ARM64 @@ -7209,25 +6830,6 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() *------------------------------------------------------------------------- */ - // lvaInlinedPInvokeFrameVar and lvaStubArgumentVar need to be assigned last - // Important: The stack walker depends on lvaStubArgumentVar immediately - // following lvaInlinedPInvokeFrameVar in the frame. - - if (lvaStubArgumentVar != BAD_VAR_NUM) - { -#ifdef JIT32_GCENCODER - noway_assert(codeGen->isFramePointerUsed()); -#endif - stkOffs = lvaAllocLocalAndSetVirtualOffset(lvaStubArgumentVar, lvaLclSize(lvaStubArgumentVar), stkOffs); - } - - if (lvaInlinedPInvokeFrameVar != BAD_VAR_NUM) - { - noway_assert(codeGen->isFramePointerUsed()); - stkOffs = - lvaAllocLocalAndSetVirtualOffset(lvaInlinedPInvokeFrameVar, lvaLclSize(lvaInlinedPInvokeFrameVar), stkOffs); - } - #ifdef JIT32_GCENCODER // JIT32 encoder cannot handle GS cookie at fp+0 since NO_GS_COOKIE == 0. // Add some padding if it is the last allocated local. @@ -7309,14 +6911,9 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() } #endif // FEATURE_FIXED_OUT_ARGS -#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - // For LoongArch64 and RISCV64, CalleeSavedRegs are at bottom. - int pushedCount = 0; -#else // compLclFrameSize equals our negated virtual stack offset minus the pushed registers and return address // and the pushed frame pointer register which for some strange reason isn't part of 'compCalleeRegsPushed'. int pushedCount = compCalleeRegsPushed; -#endif #ifdef TARGET_ARM64 if (info.compIsVarArgs) @@ -7354,7 +6951,7 @@ bool Compiler::lvaParamHasLocalStackSpace(unsigned lclNum) #ifdef SWIFT_SUPPORT if ((info.compCallConv == CorInfoCallConvExtension::Swift) && !lvaIsImplicitByRefLocal(lclNum) && - !lvaParameterPassingInfo[lclNum].HasExactlyOneStackSegment()) + !lvaGetParameterABIInfo(lclNum).HasExactlyOneStackSegment()) { return true; } diff --git a/src/coreclr/jit/lir.cpp b/src/coreclr/jit/lir.cpp index a401bbb7dc3e..79ee5fc9a668 100644 --- a/src/coreclr/jit/lir.cpp +++ b/src/coreclr/jit/lir.cpp @@ -1824,12 +1824,11 @@ void LIR::InsertBeforeTerminator(BasicBlock* block, LIR::Range&& range) break; case BBJ_SWITCH: - assert((insertionPoint->OperGet() == GT_SWITCH) || (insertionPoint->OperGet() == GT_SWITCH_TABLE)); + assert(insertionPoint->OperIs(GT_SWITCH, GT_SWITCH_TABLE)); break; case BBJ_RETURN: - assert((insertionPoint->OperGet() == GT_RETURN) || (insertionPoint->OperGet() == GT_JMP) || - (insertionPoint->OperGet() == GT_CALL)); + assert(insertionPoint->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET, GT_JMP, GT_CALL)); break; default: diff --git a/src/coreclr/jit/liveness.cpp b/src/coreclr/jit/liveness.cpp index 060cf4aeb588..18fedbb91344 100644 --- a/src/coreclr/jit/liveness.cpp +++ b/src/coreclr/jit/liveness.cpp @@ -266,7 +266,7 @@ void Compiler::fgPerNodeLocalVarLiveness(GenTree* tree) { GenTreeCall* call = tree->AsCall(); bool modHeap = true; - if (call->gtCallType == CT_HELPER) + if (call->IsHelperCall()) { CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd); @@ -1768,8 +1768,8 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR operand->SetUnusedValue(); } - // Special-case PUTARG_STK: since this operator is not considered a value, DCE will not remove - // these nodes. + // Special-case PUTARG_STK: since this operator is not considered a value, DCE will not + // remove these nodes. if (operand->OperIs(GT_PUTARG_STK)) { operand->AsPutArgStk()->gtOp1->SetUnusedValue(); @@ -1949,6 +1949,7 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR case GT_PUTARG_STK: case GT_IL_OFFSET: case GT_KEEPALIVE: + case GT_SWIFT_ERROR_RET: // Never remove these nodes, as they are always side-effecting. // // NOTE: the only side-effect of some of these nodes (GT_CMP, GT_SUB_HI) is a write to the flags diff --git a/src/coreclr/jit/llvm.cpp b/src/coreclr/jit/llvm.cpp index 8175b61915e8..1ab4094d235d 100644 --- a/src/coreclr/jit/llvm.cpp +++ b/src/coreclr/jit/llvm.cpp @@ -394,9 +394,9 @@ bool Llvm::helperCallMayPhysicallyThrow(CorInfoHelpFunc helperFunc) const { FUNC(CORINFO_HELP_CHECKED_ASSIGN_REF) CORINFO_TYPE_VOID, { CORINFO_TYPE_PTR, CORINFO_TYPE_CLASS }, HFIF_NO_RPI_OR_GC }, { FUNC(CORINFO_HELP_ASSIGN_REF_ENSURE_NONHEAP) }, // NYI in NativeAOT. { FUNC(CORINFO_HELP_ASSIGN_BYREF) }, // Not used on WASM. + { FUNC(CORINFO_HELP_BULK_WRITEBARRIER) }, // Not used in NativeAOT (or at all in some cases). - { FUNC(CORINFO_HELP_ASSIGN_STRUCT) }, { FUNC(CORINFO_HELP_GETFIELD8) }, { FUNC(CORINFO_HELP_SETFIELD8) }, { FUNC(CORINFO_HELP_GETFIELD16) }, @@ -615,7 +615,7 @@ CorInfoType Llvm::getLlvmArgTypeForArg(CorInfoType argSigType, CORINFO_CLASS_HAN } // // WASM C ABI is documented here: https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md. - // In essense, structs are passed by reference except if they are trivial wrappers of a primitive (scalar). + // In essence, structs are passed by reference except if they are trivial wrappers of a primitive (scalar). // We follow this rule for the native calling convention as well as the managed one. // bool isByRef = false; diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 0427cf666a3b..91e52f3bad5c 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -414,8 +414,7 @@ GenTree* Lowering::LowerNode(GenTree* node) } case GT_STOREIND: - LowerStoreIndirCommon(node->AsStoreInd()); - break; + return LowerStoreIndirCommon(node->AsStoreInd()); case GT_ADD: { @@ -520,8 +519,9 @@ GenTree* Lowering::LowerNode(GenTree* node) LowerJmpMethod(node); break; + case GT_SWIFT_ERROR_RET: case GT_RETURN: - LowerRet(node->AsUnOp()); + LowerRet(node->AsOp()); break; case GT_RETURNTRAP: @@ -3590,12 +3590,8 @@ void Lowering::MoveCFGCallArgs(GenTreeCall* call) for (CallArg& arg : call->gtArgs.EarlyArgs()) { GenTree* node = arg.GetEarlyNode(); - // Non-value nodes in early args are setup nodes for late args. - if (node->IsValue()) - { - assert(node->OperIsPutArg() || node->OperIsFieldList()); - MoveCFGCallArg(call, node); - } + assert(node->OperIsPutArg() || node->OperIsFieldList()); + MoveCFGCallArg(call, node); } for (CallArg& arg : call->gtArgs.LateArgs()) @@ -4541,22 +4537,22 @@ void Lowering::LowerJmpMethod(GenTree* jmp) } } -// Lower GT_RETURN node to insert PInvoke method epilog if required. -void Lowering::LowerRet(GenTreeUnOp* ret) +// Lower GT_RETURN/GT_SWIFT_ERROR_RET node to insert PInvoke method epilog if required. +void Lowering::LowerRet(GenTreeOp* ret) { - assert(ret->OperGet() == GT_RETURN); + assert(ret->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)); - JITDUMP("lowering GT_RETURN\n"); + JITDUMP("lowering return node\n"); DISPNODE(ret); JITDUMP("============\n"); - GenTree* retVal = ret->gtGetOp1(); + GenTree* retVal = ret->GetReturnValue(); // There are two kinds of retyping: // - A simple bitcast can be inserted when: // - We're returning a floating type as an integral type or vice-versa, or // - If we're returning a struct as a primitive type, we change the type of // 'retval' in 'LowerRetStructLclVar()' - bool needBitcast = (ret->TypeGet() != TYP_VOID) && !varTypeUsesSameRegType(ret, ret->gtGetOp1()); + bool needBitcast = (ret->TypeGet() != TYP_VOID) && !varTypeUsesSameRegType(ret, retVal); bool doPrimitiveBitcast = false; if (needBitcast) { @@ -4572,7 +4568,7 @@ void Lowering::LowerRet(GenTreeUnOp* ret) #endif GenTree* bitcast = comp->gtNewBitCastNode(ret->TypeGet(), retVal); - ret->gtOp1 = bitcast; + ret->SetReturnValue(bitcast); BlockRange().InsertBefore(ret, bitcast); ContainCheckBitCast(bitcast); } @@ -4871,7 +4867,7 @@ void Lowering::LowerRetStruct(GenTreeUnOp* ret) return; } - assert(ret->OperIs(GT_RETURN)); + assert(ret->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)); assert(varTypeIsStruct(ret)); GenTree* retVal = ret->gtGetOp1(); @@ -4963,8 +4959,8 @@ void Lowering::LowerRetStruct(GenTreeUnOp* ret) void Lowering::LowerRetSingleRegStructLclVar(GenTreeUnOp* ret) { assert(!comp->compMethodReturnsMultiRegRetType()); - assert(ret->OperIs(GT_RETURN)); - GenTreeLclVarCommon* lclVar = ret->gtGetOp1()->AsLclVar(); + assert(ret->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)); + GenTreeLclVarCommon* lclVar = ret->AsOp()->GetReturnValue()->AsLclVar(); assert(lclVar->OperIs(GT_LCL_VAR)); unsigned lclNum = lclVar->GetLclNum(); LclVarDsc* varDsc = comp->lvaGetDesc(lclNum); @@ -5012,7 +5008,7 @@ void Lowering::LowerRetSingleRegStructLclVar(GenTreeUnOp* ret) if (!varTypeUsesSameRegType(ret, lclVarType)) { GenTree* bitcast = comp->gtNewBitCastNode(ret->TypeGet(), ret->gtOp1); - ret->gtOp1 = bitcast; + ret->AsOp()->SetReturnValue(bitcast); BlockRange().InsertBefore(ret, bitcast); ContainCheckBitCast(bitcast); } @@ -5200,7 +5196,7 @@ GenTreeLclVar* Lowering::SpillStructCallResult(GenTreeCall* call) const GenTree* Lowering::LowerDirectCall(GenTreeCall* call) { - noway_assert(call->gtCallType == CT_USER_FUNC || call->gtCallType == CT_HELPER); + noway_assert(call->gtCallType == CT_USER_FUNC || call->IsHelperCall()); // Non-virtual direct/indirect calls: Work out if the address of the // call is known at JIT time. If not it is either an indirect call @@ -5218,7 +5214,7 @@ GenTree* Lowering::LowerDirectCall(GenTreeCall* call) } else #endif - if (call->gtCallType == CT_HELPER) + if (call->IsHelperCall()) { noway_assert(helperNum != CORINFO_HELP_UNDEF); @@ -5514,7 +5510,7 @@ GenTree* Lowering::CreateFrameLinkUpdate(FrameLinkAction action) const CORINFO_EE_INFO* pInfo = comp->eeGetEEInfo(); const CORINFO_EE_INFO::InlinedCallFrameInfo& callFrameInfo = pInfo->inlinedCallFrameInfo; - GenTree* TCB = new (comp, GT_LCL_VAR) GenTreeLclVar(GT_LCL_VAR, TYP_I_IMPL, comp->info.compLvFrameListRoot); + GenTree* TCB = comp->gtNewLclVarNode(comp->info.compLvFrameListRoot, TYP_I_IMPL); // Thread->m_pFrame GenTree* addr = new (comp, GT_LEA) GenTreeAddrMode(TYP_I_IMPL, TCB, nullptr, 1, pInfo->offsetOfThreadFrame); @@ -5524,18 +5520,17 @@ GenTree* Lowering::CreateFrameLinkUpdate(FrameLinkAction action) if (action == PushFrame) { // Thread->m_pFrame = &inlinedCallFrame; - data = new (comp, GT_LCL_ADDR) - GenTreeLclFld(GT_LCL_ADDR, TYP_BYREF, comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); + data = comp->gtNewLclAddrNode(comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); } else { assert(action == PopFrame); // Thread->m_pFrame = inlinedCallFrame.m_pNext; - data = new (comp, GT_LCL_FLD) GenTreeLclFld(GT_LCL_FLD, TYP_BYREF, comp->lvaInlinedPInvokeFrameVar, - pInfo->inlinedCallFrameInfo.offsetOfFrameLink); + data = comp->gtNewLclFldNode(comp->lvaInlinedPInvokeFrameVar, TYP_I_IMPL, + pInfo->inlinedCallFrameInfo.offsetOfFrameLink); } - GenTree* storeInd = new (comp, GT_STOREIND) GenTreeStoreInd(TYP_I_IMPL, addr, data); + GenTree* storeInd = comp->gtNewStoreIndNode(TYP_I_IMPL, addr, data); return storeInd; } @@ -5557,28 +5552,22 @@ GenTree* Lowering::CreateFrameLinkUpdate(FrameLinkAction action) // +08h +04h vptr for class InlinedCallFrame offsetOfFrameVptr method prolog // +10h +08h m_Next offsetOfFrameLink method prolog // +18h +0Ch m_Datum offsetOfCallTarget call site -// +20h n/a m_StubSecretArg not set by JIT -// +28h +10h m_pCallSiteSP offsetOfCallSiteSP x86: call site, and zeroed in method +// +20h +10h m_pCallSiteSP offsetOfCallSiteSP x86: call site, and zeroed in method // prolog; // non-x86: method prolog (SP remains // constant in function, after prolog: no // localloc and PInvoke in same function) -// +30h +14h m_pCallerReturnAddress offsetOfReturnAddress call site -// +38h +18h m_pCalleeSavedFP offsetOfCalleeSavedFP not set by JIT -// +1Ch m_pThread +// +28h +14h m_pCallerReturnAddress offsetOfReturnAddress call site +// +30h +18h m_pCalleeSavedFP offsetOfCalleeSavedFP not set by JIT +// +38h +1Ch m_pThread // +20h m_pSPAfterProlog offsetOfSPAfterProlog arm only -// +20/24h JIT retval spill area (int) before call_gc ??? -// +24/28h JIT retval spill area (long) before call_gc ??? -// +28/2Ch Saved value of EBP method prolog ??? +// +40h +20/24h m_StubSecretArg offsetOfSecretStubArg method prolog of IL stubs with secret arg // // Note that in the VM, InlinedCallFrame is a C++ class whose objects have a 'this' pointer that points // to the InlinedCallFrame vptr (the 2nd field listed above), and the GS cookie is stored *before* // the object. When we link the InlinedCallFrame onto the Frame chain, we must point at this location, // and not at the beginning of the InlinedCallFrame local, which is actually the GS cookie. // -// Return Value: -// none -// // See the usages for USE_PER_FRAME_PINVOKE_INIT for more information. void Lowering::InsertPInvokeMethodProlog() { @@ -5600,26 +5589,30 @@ void Lowering::InsertPInvokeMethodProlog() const CORINFO_EE_INFO* pInfo = comp->eeGetEEInfo(); const CORINFO_EE_INFO::InlinedCallFrameInfo& callFrameInfo = pInfo->inlinedCallFrameInfo; -// First arg: &compiler->lvaInlinedPInvokeFrameVar + callFrameInfo.offsetOfFrameVptr -#if defined(DEBUG) - const LclVarDsc* inlinedPInvokeDsc = comp->lvaGetDesc(comp->lvaInlinedPInvokeFrameVar); - assert(inlinedPInvokeDsc->IsAddressExposed()); -#endif // DEBUG - GenTree* frameAddr = new (comp, GT_LCL_ADDR) - GenTreeLclFld(GT_LCL_ADDR, TYP_BYREF, comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); + assert(comp->lvaGetDesc(comp->lvaInlinedPInvokeFrameVar)->IsAddressExposed()); - // Call runtime helper to fill in our InlinedCallFrame and push it on the Frame list: - // TCB = CORINFO_HELP_INIT_PINVOKE_FRAME(&symFrameStart, secretArg); - GenTreeCall* call = comp->gtNewHelperCallNode(CORINFO_HELP_INIT_PINVOKE_FRAME, TYP_I_IMPL); + GenTree* const insertionPoint = firstBlockRange.FirstNonCatchArgNode(); + // Store the stub secret arg if necessary. This has to be done before the + // call to the init helper below, which links the frame into the thread + // list on 32-bit platforms. + // InlinedCallFrame.m_StubSecretArg = stubSecretArg; + if (comp->info.compPublishStubParam) + { + GenTree* value = comp->gtNewLclvNode(comp->lvaStubArgumentVar, TYP_I_IMPL); + GenTree* store = comp->gtNewStoreLclFldNode(comp->lvaInlinedPInvokeFrameVar, TYP_I_IMPL, + callFrameInfo.offsetOfSecretStubArg, value); + firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, store)); + DISPTREERANGE(firstBlockRange, store); + } + + // Call runtime helper to fill in our InlinedCallFrame and push it on the Frame list: + // TCB = CORINFO_HELP_INIT_PINVOKE_FRAME(&symFrameStart); + GenTree* frameAddr = comp->gtNewLclAddrNode(comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); NewCallArg frameAddrArg = NewCallArg::Primitive(frameAddr).WellKnown(WellKnownArg::PInvokeFrame); + + GenTreeCall* call = comp->gtNewHelperCallNode(CORINFO_HELP_INIT_PINVOKE_FRAME, TYP_I_IMPL); call->gtArgs.PushBack(comp, frameAddrArg); -// for x86/arm32 don't pass the secretArg. -#if !defined(TARGET_X86) && !defined(TARGET_ARM) - NewCallArg stubParamArg = - NewCallArg::Primitive(PhysReg(REG_SECRET_STUB_PARAM)).WellKnown(WellKnownArg::SecretStubParam); - call->gtArgs.PushBack(comp, stubParamArg); -#endif // some sanity checks on the frame list root vardsc const unsigned lclNum = comp->info.compLvFrameListRoot; @@ -5627,12 +5620,7 @@ void Lowering::InsertPInvokeMethodProlog() noway_assert(!varDsc->lvIsParam); noway_assert(varDsc->lvType == TYP_I_IMPL); - GenTree* store = new (comp, GT_STORE_LCL_VAR) GenTreeLclVar(GT_STORE_LCL_VAR, TYP_I_IMPL, lclNum); - store->AsOp()->gtOp1 = call; - store->gtFlags |= GTF_VAR_DEF; - - GenTree* const insertionPoint = firstBlockRange.FirstNonCatchArgNode(); - + GenTree* store = comp->gtNewStoreLclVarNode(lclNum, call); comp->fgMorphTree(store); firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, store)); DISPTREERANGE(firstBlockRange, store); @@ -5647,7 +5635,6 @@ void Lowering::InsertPInvokeMethodProlog() GenTree* spValue = PhysReg(REG_SPBASE); GenTreeLclFld* storeSP = comp->gtNewStoreLclFldNode(comp->lvaInlinedPInvokeFrameVar, TYP_I_IMPL, callFrameInfo.offsetOfCallSiteSP, spValue); - assert(inlinedPInvokeDsc->lvDoNotEnregister); firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, storeSP)); DISPTREERANGE(firstBlockRange, storeSP); @@ -5663,7 +5650,6 @@ void Lowering::InsertPInvokeMethodProlog() GenTree* fpValue = PhysReg(REG_FPBASE); GenTreeLclFld* storeFP = comp->gtNewStoreLclFldNode(comp->lvaInlinedPInvokeFrameVar, TYP_I_IMPL, callFrameInfo.offsetOfCalleeSavedFP, fpValue); - assert(inlinedPInvokeDsc->lvDoNotEnregister); firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, storeFP)); DISPTREERANGE(firstBlockRange, storeFP); @@ -8147,12 +8133,12 @@ void Lowering::ContainCheckLclHeap(GenTreeOp* node) // void Lowering::ContainCheckRet(GenTreeUnOp* ret) { - assert(ret->OperIs(GT_RETURN)); + assert(ret->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)); #if !defined(TARGET_64BIT) if (ret->TypeGet() == TYP_LONG) { - GenTree* op1 = ret->gtGetOp1(); + GenTree* op1 = ret->AsOp()->GetReturnValue(); noway_assert(op1->OperGet() == GT_LONG); MakeSrcContained(ret, op1); } @@ -8160,7 +8146,7 @@ void Lowering::ContainCheckRet(GenTreeUnOp* ret) #if FEATURE_MULTIREG_RET if (ret->TypeIs(TYP_STRUCT)) { - GenTree* op1 = ret->gtGetOp1(); + GenTree* op1 = ret->AsOp()->GetReturnValue(); // op1 must be either a lclvar or a multi-reg returning call if (op1->OperGet() == GT_LCL_VAR) { @@ -8203,6 +8189,117 @@ void Lowering::ContainCheckBitCast(GenTree* node) } } +//------------------------------------------------------------------------ +// TryLowerBlockStoreAsGcBulkCopyCall: Lower a block store node as a CORINFO_HELP_BULK_WRITEBARRIER call +// +// Arguments: +// blkNode - The block store node to lower +// +bool Lowering::TryLowerBlockStoreAsGcBulkCopyCall(GenTreeBlk* blk) +{ + if (comp->opts.OptimizationDisabled()) + { + return false; + } + + // Replace STORE_BLK (struct copy) with CORINFO_HELP_BULK_WRITEBARRIER which performs + // bulk copy for byrefs. + const unsigned bulkCopyThreshold = 4; + if (!blk->OperIs(GT_STORE_BLK) || blk->OperIsInitBlkOp() || blk->IsVolatile() || + (blk->GetLayout()->GetGCPtrCount() < bulkCopyThreshold)) + { + return false; + } + + GenTree* dest = blk->Addr(); + GenTree* data = blk->Data(); + + if (data->OperIs(GT_IND)) + { + if (data->AsIndir()->IsVolatile()) + { + return false; + } + + // Drop GT_IND nodes + BlockRange().Remove(data); + data = data->AsIndir()->Addr(); + } + else + { + assert(data->OperIs(GT_LCL_VAR, GT_LCL_FLD)); + + // Convert local to LCL_ADDR + unsigned lclOffset = data->AsLclVarCommon()->GetLclOffs(); + data->ChangeOper(GT_LCL_ADDR); + data->ChangeType(TYP_I_IMPL); + data->AsLclFld()->SetLclOffs(lclOffset); + data->ClearContained(); + } + + // Size is a constant + GenTreeIntCon* size = comp->gtNewIconNode((ssize_t)blk->GetLayout()->GetSize(), TYP_I_IMPL); + BlockRange().InsertBefore(data, size); + + // A hacky way to safely call fgMorphTree in Lower + GenTree* destPlaceholder = comp->gtNewZeroConNode(dest->TypeGet()); + GenTree* dataPlaceholder = comp->gtNewZeroConNode(genActualType(data)); + GenTree* sizePlaceholder = comp->gtNewZeroConNode(genActualType(size)); + + GenTreeCall* call = comp->gtNewHelperCallNode(CORINFO_HELP_BULK_WRITEBARRIER, TYP_VOID, destPlaceholder, + dataPlaceholder, sizePlaceholder); + comp->fgMorphArgs(call); + + LIR::Range range = LIR::SeqTree(comp, call); + GenTree* rangeStart = range.FirstNode(); + GenTree* rangeEnd = range.LastNode(); + + BlockRange().InsertBefore(blk, std::move(range)); + blk->gtBashToNOP(); + + LIR::Use destUse; + LIR::Use sizeUse; + BlockRange().TryGetUse(destPlaceholder, &destUse); + BlockRange().TryGetUse(sizePlaceholder, &sizeUse); + destUse.ReplaceWith(dest); + sizeUse.ReplaceWith(size); + destPlaceholder->SetUnusedValue(); + sizePlaceholder->SetUnusedValue(); + + LIR::Use dataUse; + BlockRange().TryGetUse(dataPlaceholder, &dataUse); + dataUse.ReplaceWith(data); + dataPlaceholder->SetUnusedValue(); + + LowerRange(rangeStart, rangeEnd); + + // Finally move all GT_PUTARG_* nodes + // Re-use the existing logic for CFG call args here + MoveCFGCallArgs(call); + + BlockRange().Remove(destPlaceholder); + BlockRange().Remove(sizePlaceholder); + BlockRange().Remove(dataPlaceholder); + + // Add implicit nullchecks for dest and data if needed: + // + auto wrapWithNullcheck = [&](GenTree* node) { + if (comp->fgAddrCouldBeNull(node)) + { + LIR::Use nodeUse; + BlockRange().TryGetUse(node, &nodeUse); + GenTree* nodeClone = comp->gtNewLclvNode(nodeUse.ReplaceWithLclVar(comp), genActualType(node)); + GenTree* nullcheck = comp->gtNewNullCheck(nodeClone, comp->compCurBB); + BlockRange().InsertAfter(nodeUse.Def(), nodeClone, nullcheck); + LowerNode(nullcheck); + } + }; + wrapWithNullcheck(dest); + wrapWithNullcheck(data); + + return true; +} + //------------------------------------------------------------------------ // LowerBlockStoreAsHelperCall: Lower a block store node as a memset/memcpy call // @@ -8338,54 +8435,57 @@ void Lowering::LowerBlockStoreAsHelperCall(GenTreeBlk* blkNode) #endif } -struct StoreCoalescingData -{ - var_types targetType; - GenTree* baseAddr; - GenTree* index; - GenTree* value; - uint32_t scale; - int offset; -}; - //------------------------------------------------------------------------ -// GetStoreCoalescingData: given a STOREIND node, get the data needed to perform -// store coalescing including pointer to the previous node. +// GetLoadStoreCoalescingData: given a STOREIND/IND node, get the data needed to perform +// store/load coalescing including pointer to the previous node. // // Arguments: // comp - the compiler instance -// ind - the STOREIND node -// data - [OUT] the data needed for store coalescing +// ind - the STOREIND/IND node +// data - [OUT] the data needed for store/load coalescing // // Return Value: // true if the data was successfully retrieved, false otherwise. -// Basically, false means that we definitely can't do store coalescing. // -static bool GetStoreCoalescingData(Compiler* comp, GenTreeStoreInd* ind, StoreCoalescingData* data) +bool Lowering::GetLoadStoreCoalescingData(GenTreeIndir* ind, LoadStoreCoalescingData* data) const { - // Don't merge volatile stores. + // Don't merge volatile load/stores. if (ind->IsVolatile()) { return false; } - // Data has to be INT_CNS, can be also VEC_CNS in future. - if (!ind->Data()->IsCnsIntOrI() && !ind->Data()->IsVectorConst()) - { - return false; - } + const bool isStore = ind->OperIs(GT_STOREIND, GT_STORE_BLK); + const bool isLoad = ind->OperIs(GT_IND); auto isNodeInvariant = [](Compiler* comp, GenTree* node, bool allowNull) { if (node == nullptr) { return allowNull; } + if (node->OperIsConst()) + { + return true; + } // We can allow bigger trees here, but it's not clear if it's worth it. return node->OperIs(GT_LCL_VAR) && !comp->lvaVarAddrExposed(node->AsLclVar()->GetLclNum()); }; + if (isStore) + { + // For stores, Data() is expected to be an invariant node + if (!isNodeInvariant(comp, ind->Data(), false)) + { + return false; + } + } + else if (!isLoad) + { + return false; + } + data->targetType = ind->TypeGet(); - data->value = ind->Data(); + data->value = isStore ? ind->Data() : nullptr; if (ind->Addr()->OperIs(GT_LEA)) { GenTree* base = ind->Addr()->AsAddrMode()->Base(); @@ -8421,12 +8521,24 @@ static bool GetStoreCoalescingData(Compiler* comp, GenTreeStoreInd* ind, StoreCo // Address is not LEA or local. return false; } + + bool isClosedRange = false; + // Make sure there are no other unexpected nodes in-between. + LIR::ReadOnlyRange range = BlockRange().GetTreeRange(ind, &isClosedRange); + if (!isClosedRange) + { + return false; + } + + data->rangeStart = range.FirstNode(); + data->rangeEnd = range.LastNode(); + return true; } //------------------------------------------------------------------------ -// LowerStoreIndirCoalescing: If the given STOREIND node is followed by a similar -// STOREIND node, try to merge them into a single store of a twice wider type. Example: +// LowerStoreIndirCoalescing: If the given IND/STOREIND node is followed by a similar +// IND/STOREIND node, try to merge them into a single store of a twice wider type. Example: // // * STOREIND int // +--* LCL_VAR byref V00 @@ -8450,7 +8562,7 @@ static bool GetStoreCoalescingData(Compiler* comp, GenTreeStoreInd* ind, StoreCo // Arguments: // ind - the current STOREIND node // -void Lowering::LowerStoreIndirCoalescing(GenTreeStoreInd* ind) +void Lowering::LowerStoreIndirCoalescing(GenTreeIndir* ind) { // LA, RISC-V and ARM32 more likely to recieve a terrible performance hit from // unaligned accesses making this optimization questionable. @@ -8460,12 +8572,9 @@ void Lowering::LowerStoreIndirCoalescing(GenTreeStoreInd* ind) return; } - // TODO-ARM64-CQ: enable TYP_REF if we find a case where it's beneficial. - // The algorithm does support TYP_REF (with null value), but it seems to be not worth - // it on ARM64 where it's pretty efficient to do "stp xzr, xzr, [addr]" to clear two - // items at once. Although, it may be profitable to do "stp q0, q0, [addr]". - if (!varTypeIsIntegral(ind) && !varTypeIsSIMD(ind)) + if (!ind->OperIs(GT_STOREIND, GT_STORE_BLK)) { + // Load coalescing is not yet supported return; } @@ -8483,24 +8592,16 @@ void Lowering::LowerStoreIndirCoalescing(GenTreeStoreInd* ind) // to get a single store of 8 bytes. do { - StoreCoalescingData currData; - StoreCoalescingData prevData; + LoadStoreCoalescingData currData; + LoadStoreCoalescingData prevData; // Get coalescing data for the current STOREIND - if (!GetStoreCoalescingData(comp, ind, &currData)) + if (!GetLoadStoreCoalescingData(ind, &currData)) { return; } - bool isClosedRange = false; - // Now we need to find the very first LIR node representing the current STOREIND - // and make sure that there are no other unexpected nodes in-between. - LIR::ReadOnlyRange currIndRange = BlockRange().GetTreeRange(ind, &isClosedRange); - if (!isClosedRange) - { - return; - } - GenTree* prevTree = currIndRange.FirstNode()->gtPrev; + GenTree* prevTree = currData.rangeStart->gtPrev; // Now we need to find the previous STOREIND, // we can ignore any NOPs or IL_OFFSETs in-between while ((prevTree != nullptr) && prevTree->OperIs(GT_NOP, GT_IL_OFFSET)) @@ -8508,47 +8609,51 @@ void Lowering::LowerStoreIndirCoalescing(GenTreeStoreInd* ind) prevTree = prevTree->gtPrev; } - // It's not a STOREIND - bail out. - if ((prevTree == nullptr) || !prevTree->OperIs(GT_STOREIND)) + // It's not a store - bail out. + if ((prevTree == nullptr) || !prevTree->OperIs(GT_STOREIND, GT_STORE_BLK)) { return; } // Get coalescing data for the previous STOREIND - GenTreeStoreInd* prevInd = prevTree->AsStoreInd(); - if (!GetStoreCoalescingData(comp, prevInd->AsStoreInd(), &prevData)) + GenTreeIndir* prevInd = prevTree->AsIndir(); + if (!GetLoadStoreCoalescingData(prevInd, &prevData)) { return; } - // Same for the previous STOREIND, make sure there are no unexpected nodes around. - LIR::ReadOnlyRange prevIndRange = BlockRange().GetTreeRange(prevInd, &isClosedRange); - if (!isClosedRange) + if (!currData.IsAddressEqual(prevData, /*ignoreOffset*/ true)) { + // Non-offset part of the address is not the same - bail out. return; } - // STOREIND aren't value nodes. - LIR::Use use; - assert(!BlockRange().TryGetUse(prevInd, &use) && !BlockRange().TryGetUse(ind, &use)); + // The same offset means that we're storing to the same location of the same width. + // Just remove the previous store then. + if (prevData.offset == currData.offset) + { + BlockRange().Remove(prevData.rangeStart, prevData.rangeEnd); + continue; + } - // BaseAddr, Index, Scale and Type all have to match. - if ((prevData.scale != currData.scale) || (prevData.targetType != currData.targetType) || - !GenTree::Compare(prevData.baseAddr, currData.baseAddr) || - !GenTree::Compare(prevData.index, currData.index)) + // TODO-ARM64-CQ: enable TYP_REF if we find a case where it's beneficial. + // The algorithm does support TYP_REF (with null value), but it seems to be not worth + // it on ARM64 where it's pretty efficient to do "stp xzr, xzr, [addr]" to clear two + // items at once. Although, it may be profitable to do "stp q0, q0, [addr]". + if (!varTypeIsIntegral(ind) && !varTypeIsSIMD(ind)) { return; } - // At this point we know that we have two consecutive STOREINDs with the same base address, - // index and scale, the only variable thing is the offset (constant) + assert(ind->OperIs(GT_STOREIND)); + assert(prevInd->OperIs(GT_STOREIND)); + assert(prevData.IsStore()); + assert(currData.IsStore()); - // The same offset means that we're storing to the same location of the same width. - // Just remove the previous store then. - if (prevData.offset == currData.offset) + // For now, only constants are supported for data. + if (!prevData.value->OperIsConst() || !currData.value->OperIsConst()) { - BlockRange().Remove(std::move(prevIndRange)); - continue; + return; } // Otherwise, the difference between two offsets has to match the size of the type. @@ -8693,11 +8798,11 @@ void Lowering::LowerStoreIndirCoalescing(GenTreeStoreInd* ind) } // We should not be here for stores requiring write barriers. - assert(!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(ind)); - assert(!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(prevInd)); + assert(!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(ind->AsStoreInd())); + assert(!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(prevInd->AsStoreInd())); // Delete previous STOREIND entirely - BlockRange().Remove(std::move(prevIndRange)); + BlockRange().Remove(prevData.rangeStart, prevData.rangeEnd); // It's not expected to be contained yet, but just in case... ind->Data()->ClearContained(); @@ -8789,7 +8894,10 @@ void Lowering::LowerStoreIndirCoalescing(GenTreeStoreInd* ind) // Arguments: // ind - the store indirection node we are lowering. // -void Lowering::LowerStoreIndirCommon(GenTreeStoreInd* ind) +// Return Value: +// Next node to lower. +// +GenTree* Lowering::LowerStoreIndirCommon(GenTreeStoreInd* ind) { assert(ind->TypeGet() != TYP_STRUCT); @@ -8804,28 +8912,30 @@ void Lowering::LowerStoreIndirCommon(GenTreeStoreInd* ind) #endif TryCreateAddrMode(ind->Addr(), isContainable, ind); - if (!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(ind)) + if (comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(ind)) { + return ind->gtNext; + } + #ifndef TARGET_XARCH - if (ind->Data()->IsIconHandle(GTF_ICON_OBJ_HDL)) + if (ind->Data()->IsIconHandle(GTF_ICON_OBJ_HDL)) + { + const ssize_t handle = ind->Data()->AsIntCon()->IconValue(); + if (!comp->info.compCompHnd->isObjectImmutable(reinterpret_cast(handle))) { - const ssize_t handle = ind->Data()->AsIntCon()->IconValue(); - if (!comp->info.compCompHnd->isObjectImmutable(reinterpret_cast(handle))) - { - // On platforms with weaker memory model we need to make sure we use a store with the release semantic - // when we publish a potentially mutable object - // See relevant discussions https://github.com/dotnet/runtime/pull/76135#issuecomment-1257258310 and - // https://github.com/dotnet/runtime/pull/76112#discussion_r980639782 + // On platforms with weaker memory model we need to make sure we use a store with the release semantic + // when we publish a potentially mutable object + // See relevant discussions https://github.com/dotnet/runtime/pull/76135#issuecomment-1257258310 and + // https://github.com/dotnet/runtime/pull/76112#discussion_r980639782 - // This can be relaxed to "just make sure to use stlr/memory barrier" if needed - ind->gtFlags |= GTF_IND_VOLATILE; - } + // This can be relaxed to "just make sure to use stlr/memory barrier" if needed + ind->gtFlags |= GTF_IND_VOLATILE; } + } #endif - LowerStoreIndirCoalescing(ind); - LowerStoreIndir(ind); - } + LowerStoreIndirCoalescing(ind); + return LowerStoreIndir(ind); } //------------------------------------------------------------------------ @@ -8854,6 +8964,27 @@ GenTree* Lowering::LowerIndir(GenTreeIndir* ind) } #endif +#ifdef TARGET_ARM64 + LIR::Use use; + if (ind->OperIs(GT_IND) && ind->IsVolatile() && varTypeIsFloating(ind) && BlockRange().TryGetUse(ind, &use)) + { + // Convert "IND(addr)" to "BitCast(IND(addr))" + // for volatile loads since there is no ldar for SIMD regs + var_types targetType = ind->TypeGet(); + ind->ChangeType(ind->TypeIs(TYP_DOUBLE) ? TYP_LONG : TYP_INT); + + // Now it might be eligible for some addressing modes with LDAPUR: + const bool isContainable = IsInvariantInRange(ind->Addr(), ind); + TryCreateAddrMode(ind->Addr(), isContainable, ind); + + // Wrap the resulting IND into BITCAST: + GenTree* castOp = comp->gtNewBitCastNode(targetType, ind); + BlockRange().InsertAfter(ind, castOp); + use.ReplaceWith(castOp); + return castOp; + } +#endif + // TODO-Cleanup: We're passing isContainable = true but ContainCheckIndir rejects // address containment in some cases so we end up creating trivial (reg + offfset) // or (reg + reg) LEAs that are not necessary. @@ -8887,7 +9018,7 @@ GenTree* Lowering::LowerIndir(GenTreeIndir* ind) #ifdef TARGET_ARM64 if (comp->opts.OptimizationEnabled() && ind->OperIs(GT_IND)) { - OptimizeForLdp(ind); + OptimizeForLdpStp(ind); } #endif @@ -8902,7 +9033,7 @@ GenTree* Lowering::LowerIndir(GenTreeIndir* ind) // cases passing the distance check, but 82 out of these 112 extra cases were // then rejected due to interference. So 16 seems like a good number to balance // the throughput costs. -const int LDP_REORDERING_MAX_DISTANCE = 16; +const int LDP_STP_REORDERING_MAX_DISTANCE = 16; //------------------------------------------------------------------------ // OptimizeForLdp: Record information about an indirection, and try to optimize @@ -8915,7 +9046,7 @@ const int LDP_REORDERING_MAX_DISTANCE = 16; // Returns: // True if the optimization was successful. // -bool Lowering::OptimizeForLdp(GenTreeIndir* ind) +bool Lowering::OptimizeForLdpStp(GenTreeIndir* ind) { if (!ind->TypeIs(TYP_INT, TYP_LONG, TYP_FLOAT, TYP_DOUBLE, TYP_SIMD8, TYP_SIMD16) || ind->IsVolatile()) { @@ -8933,7 +9064,7 @@ bool Lowering::OptimizeForLdp(GenTreeIndir* ind) // Every indirection takes an expected 2+ nodes, so we only expect at most // half the reordering distance to be candidates for the optimization. - int maxCount = min(m_blockIndirs.Height(), LDP_REORDERING_MAX_DISTANCE / 2); + int maxCount = min(m_blockIndirs.Height(), LDP_STP_REORDERING_MAX_DISTANCE / 2); for (int i = 0; i < maxCount; i++) { SavedIndir& prev = m_blockIndirs.TopRef(i); @@ -8948,11 +9079,22 @@ bool Lowering::OptimizeForLdp(GenTreeIndir* ind) continue; } + if (prevIndir->gtNext == nullptr) + { + // Deleted by other optimization + continue; + } + + if (prevIndir->OperIsStore() != ind->OperIsStore()) + { + continue; + } + JITDUMP("[%06u] and [%06u] are indirs off the same base with offsets +%03u and +%03u\n", Compiler::dspTreeID(ind), Compiler::dspTreeID(prevIndir), (unsigned)offs, (unsigned)prev.Offset); if (std::abs(offs - prev.Offset) == genTypeSize(ind)) { - JITDUMP(" ..and they are amenable to ldp optimization\n"); + JITDUMP(" ..and they are amenable to ldp/stp optimization\n"); if (TryMakeIndirsAdjacent(prevIndir, ind)) { // Do not let the previous one participate in @@ -8988,7 +9130,7 @@ bool Lowering::OptimizeForLdp(GenTreeIndir* ind) bool Lowering::TryMakeIndirsAdjacent(GenTreeIndir* prevIndir, GenTreeIndir* indir) { GenTree* cur = prevIndir; - for (int i = 0; i < LDP_REORDERING_MAX_DISTANCE; i++) + for (int i = 0; i < LDP_STP_REORDERING_MAX_DISTANCE; i++) { cur = cur->gtNext; if (cur == indir) @@ -9045,8 +9187,16 @@ bool Lowering::TryMakeIndirsAdjacent(GenTreeIndir* prevIndir, GenTreeIndir* indi INDEBUG(dumpWithMarks()); JITDUMP("\n"); + if ((prevIndir->gtLIRFlags & LIR::Flags::Mark) != 0) + { + JITDUMP("Previous indir is part of the data flow of current indir\n"); + UnmarkTree(indir); + return false; + } + m_scratchSideEffects.Clear(); + bool sawData = false; for (GenTree* cur = prevIndir->gtNext; cur != indir; cur = cur->gtNext) { if ((cur->gtLIRFlags & LIR::Flags::Mark) != 0) @@ -9059,6 +9209,11 @@ bool Lowering::TryMakeIndirsAdjacent(GenTreeIndir* prevIndir, GenTreeIndir* indi UnmarkTree(indir); return false; } + + if (indir->OperIsStore()) + { + sawData |= cur == indir->Data(); + } } else { @@ -9070,6 +9225,13 @@ bool Lowering::TryMakeIndirsAdjacent(GenTreeIndir* prevIndir, GenTreeIndir* indi if (m_scratchSideEffects.InterferesWith(comp, indir, true)) { + if (!indir->OperIsLoad()) + { + JITDUMP("Have conservative interference with last store. Giving up.\n"); + UnmarkTree(indir); + return false; + } + // Try a bit harder, making use of the following facts: // // 1. We know the indir is non-faulting, so we do not need to worry @@ -9166,8 +9328,39 @@ bool Lowering::TryMakeIndirsAdjacent(GenTreeIndir* prevIndir, GenTreeIndir* indi } } - JITDUMP("Interference checks passed. Moving nodes that are not part of data flow of [%06u]\n\n", - Compiler::dspTreeID(indir)); + JITDUMP("Interference checks passed: can move unrelated nodes past second indir.\n"); + + if (sawData) + { + // If the data node of 'indir' is between 'prevIndir' and 'indir' then + // try to move the previous indir up to happen after the data + // computation. We will be moving all nodes unrelated to the data flow + // past 'indir', so we only need to check interference between + // 'prevIndir' and all nodes that are part of 'indir's dataflow. + m_scratchSideEffects.Clear(); + m_scratchSideEffects.AddNode(comp, prevIndir); + + for (GenTree* cur = prevIndir->gtNext;; cur = cur->gtNext) + { + if ((cur->gtLIRFlags & LIR::Flags::Mark) != 0) + { + if (m_scratchSideEffects.InterferesWith(comp, cur, true)) + { + JITDUMP("Cannot move prev indir [%06u] up past [%06u] to get it past the data computation\n", + Compiler::dspTreeID(prevIndir), Compiler::dspTreeID(cur)); + UnmarkTree(indir); + return false; + } + } + + if (cur == indir->Data()) + { + break; + } + } + } + + JITDUMP("Moving nodes that are not part of data flow of [%06u]\n\n", Compiler::dspTreeID(indir)); GenTree* previous = prevIndir; for (GenTree* node = prevIndir->gtNext;;) @@ -9190,6 +9383,22 @@ bool Lowering::TryMakeIndirsAdjacent(GenTreeIndir* prevIndir, GenTreeIndir* indi node = next; } + if (sawData) + { + // For some reason LSRA is not able to reuse a constant if both LIR + // temps are live simultaneously, so skip moving in those cases and + // expect LSRA to reuse the constant instead. + if (indir->Data()->OperIs(GT_CNS_INT, GT_CNS_DBL) && GenTree::Compare(indir->Data(), prevIndir->Data())) + { + JITDUMP("Not moving previous indir since we are expecting constant reuse for the data\n"); + } + else + { + BlockRange().Remove(prevIndir); + BlockRange().InsertAfter(indir->Data(), prevIndir); + } + } + JITDUMP("Result:\n\n"); INDEBUG(dumpWithMarks()); JITDUMP("\n"); @@ -9404,6 +9613,7 @@ void Lowering::LowerBlockStoreCommon(GenTreeBlk* blkNode) } LowerBlockStore(blkNode); + LowerStoreIndirCoalescing(blkNode); } //------------------------------------------------------------------------ @@ -9506,6 +9716,21 @@ void Lowering::TryRetypingFloatingPointStoreToIntegerStore(GenTree* store) return; } + // Convert "STOREIND(addr, floatVal)" to "STORIND(addr, BitCast(floatVal))" + // for volatile stores since there is no stlr for SIMD regs +#ifdef TARGET_ARM64 + if (store->OperIs(GT_STOREIND) && store->AsStoreInd()->IsVolatile()) + { + GenTreeStoreInd* ind = store->AsStoreInd(); + ind->ChangeType(ind->TypeIs(TYP_DOUBLE) ? TYP_LONG : TYP_INT); + GenTree* castOp = comp->gtNewBitCastNode(ind->TypeGet(), ind->Data()); + BlockRange().InsertAfter(ind->Data(), castOp); + ind->Data() = castOp; + LowerNode(castOp); + return; + } +#endif + // We only want to transform memory stores, not definitions of candidate locals. // if (store->OperIs(GT_STORE_LCL_VAR) && !comp->lvaGetDesc(store->AsLclVar())->lvDoNotEnregister) diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h index 4813fb9a7d4a..6d9095de3e87 100644 --- a/src/coreclr/jit/lower.h +++ b/src/coreclr/jit/lower.h @@ -154,7 +154,7 @@ class Lowering final : public Phase bool TryLowerConditionToFlagsNode(GenTree* parent, GenTree* condition, GenCondition* code); GenTreeCC* LowerNodeCC(GenTree* node, GenCondition condition); void LowerJmpMethod(GenTree* jmp); - void LowerRet(GenTreeUnOp* ret); + void LowerRet(GenTreeOp* ret); void LowerStoreLocCommon(GenTreeLclVarCommon* lclVar); void LowerRetStruct(GenTreeUnOp* ret); void LowerRetSingleRegStructLclVar(GenTreeUnOp* ret); @@ -315,15 +315,44 @@ class Lowering final : public Phase } #endif // defined(TARGET_XARCH) + struct LoadStoreCoalescingData + { + var_types targetType; + GenTree* baseAddr; + GenTree* index; + GenTree* value; + uint32_t scale; + int offset; + GenTree* rangeStart; + GenTree* rangeEnd; + + bool IsStore() const + { + return value != nullptr; + } + + bool IsAddressEqual(const LoadStoreCoalescingData& other, bool ignoreOffset) const + { + if ((scale != other.scale) || (targetType != other.targetType) || + !GenTree::Compare(baseAddr, other.baseAddr) || !GenTree::Compare(index, other.index)) + { + return false; + } + return ignoreOffset || (offset == other.offset); + } + }; + + bool GetLoadStoreCoalescingData(GenTreeIndir* ind, LoadStoreCoalescingData* data) const; + // Per tree node member functions - void LowerStoreIndirCommon(GenTreeStoreInd* ind); + GenTree* LowerStoreIndirCommon(GenTreeStoreInd* ind); GenTree* LowerIndir(GenTreeIndir* ind); - bool OptimizeForLdp(GenTreeIndir* ind); + bool OptimizeForLdpStp(GenTreeIndir* ind); bool TryMakeIndirsAdjacent(GenTreeIndir* prevIndir, GenTreeIndir* indir); void MarkTree(GenTree* root); void UnmarkTree(GenTree* root); - void LowerStoreIndir(GenTreeStoreInd* node); - void LowerStoreIndirCoalescing(GenTreeStoreInd* node); + GenTree* LowerStoreIndir(GenTreeStoreInd* node); + void LowerStoreIndirCoalescing(GenTreeIndir* node); GenTree* LowerAdd(GenTreeOp* node); GenTree* LowerMul(GenTreeOp* mul); bool TryLowerAndNegativeOne(GenTreeOp* node, GenTree** nextNode); @@ -334,6 +363,7 @@ class Lowering final : public Phase void LowerBlockStore(GenTreeBlk* blkNode); void LowerBlockStoreCommon(GenTreeBlk* blkNode); void LowerBlockStoreAsHelperCall(GenTreeBlk* blkNode); + bool TryLowerBlockStoreAsGcBulkCopyCall(GenTreeBlk* blkNode); void LowerLclHeap(GenTree* node); void ContainBlockStoreAddress(GenTreeBlk* blkNode, unsigned size, GenTree* addr, GenTree* addrParent); void LowerPutArgStkOrSplit(GenTreePutArgStk* putArgNode); diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 9731331885be..91046c5474b7 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -295,6 +295,74 @@ bool Lowering::IsContainableUnaryOrBinaryOp(GenTree* parentNode, GenTree* childN return false; } + if (childNode->OperIs(GT_ROL, GT_ROR)) + { + // Find "a op (b rotate cns)" + + if (childNode->gtGetOp1()->isContained()) + { + // Cannot contain if the childs op1 is already contained + return false; + } + + GenTree* rotateAmountNode = childNode->gtGetOp2(); + + if (!rotateAmountNode->IsCnsIntOrI()) + { + // Cannot contain if the childs op2 is not a constant + return false; + } + + const ssize_t wrapAmount = (static_cast(genTypeSize(childNode)) * BITS_PER_BYTE); + assert((wrapAmount == 32) || (wrapAmount == 64)); + + // Rotation is circular, so normalize to [0, wrapAmount - 1] + ssize_t rotateAmount = rotateAmountNode->AsIntCon()->IconValue() % wrapAmount; + assert((rotateAmount >= 0) && (rotateAmount <= (wrapAmount - 1))); + + if (childNode->OperIs(GT_ROL)) + { + // The actual instructions only encode rotate right but + // since rotating left by 1 is equivalen to rotating + // right by (rotateAmount - 1), we can fix things here. + + childNode->SetOper(GT_ROR); + rotateAmount = wrapAmount - rotateAmount; + } + + rotateAmountNode->AsIntCon()->SetIconValue(rotateAmount); + assert(childNode->OperIs(GT_ROR)); + + if (parentNode->OperIs(GT_AND)) + { + // These operations can still report flags + + if (IsInvariantInRange(childNode, parentNode)) + { + assert(rotateAmountNode->isContained()); + return true; + } + } + + if ((parentNode->gtFlags & GTF_SET_FLAGS) != 0) + { + // Cannot contain if the parent operation needs to set flags + return false; + } + + if (parentNode->OperIs(GT_OR, GT_XOR)) + { + if (IsInvariantInRange(childNode, parentNode)) + { + assert(rotateAmountNode->isContained()); + return true; + } + } + + // TODO: Handle BIC/BICS, EON, MVN, ORN, TST + return false; + } + if (childNode->OperIs(GT_NEG)) { // If we have a contained LSH, RSH or RSZ, we can still contain NEG if the parent is a EQ or NE. @@ -423,11 +491,21 @@ void Lowering::LowerStoreLoc(GenTreeLclVarCommon* storeLoc) // node - The indirect store node (GT_STORE_IND) of interest // // Return Value: -// None. +// Next node to lower. // -void Lowering::LowerStoreIndir(GenTreeStoreInd* node) +GenTree* Lowering::LowerStoreIndir(GenTreeStoreInd* node) { + GenTree* next = node->gtNext; ContainCheckStoreIndir(node); + +#ifdef TARGET_ARM64 + if (comp->opts.OptimizationEnabled()) + { + OptimizeForLdpStp(node); + } +#endif + + return next; } //------------------------------------------------------------------------ @@ -657,7 +735,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) { // No write barriers are needed on the stack. // If the layout contains a byref, then we know it must live on the stack. - if (dstAddr->OperIs(GT_LCL_ADDR) || layout->HasGCByRef()) + if (dstAddr->OperIs(GT_LCL_ADDR) || layout->IsStackOnly(comp)) { // If the size is small enough to unroll then we need to mark the block as non-interruptible // to actually allow unrolling. The generated code does not report GC references loaded in the @@ -669,6 +747,12 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) if (doCpObj) { + // Try to use bulk copy helper + if (TryLowerBlockStoreAsGcBulkCopyCall(blkNode)) + { + return; + } + assert((dstAddr->TypeGet() == TYP_BYREF) || (dstAddr->TypeGet() == TYP_I_IMPL)); blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindCpObjUnroll; } @@ -1212,6 +1296,34 @@ GenTree* Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node) break; } + if (HWIntrinsicInfo::IsEmbeddedMaskedOperation(intrinsicId)) + { + LIR::Use use; + if (BlockRange().TryGetUse(node, &use)) + { + GenTree* user = use.User(); + // Wrap the intrinsic in ConditionalSelect only if it is not already inside another ConditionalSelect + if (!user->OperIsHWIntrinsic() || (user->AsHWIntrinsic()->GetHWIntrinsicId() != NI_Sve_ConditionalSelect)) + { + CorInfoType simdBaseJitType = node->GetSimdBaseJitType(); + unsigned simdSize = node->GetSimdSize(); + var_types simdType = Compiler::getSIMDTypeForSize(simdSize); + GenTree* trueMask = comp->gtNewSimdAllTrueMaskNode(simdBaseJitType, simdSize); + GenTree* trueVal = node; + GenTree* falseVal = comp->gtNewZeroConNode(simdType); + + GenTreeHWIntrinsic* condSelNode = + comp->gtNewSimdHWIntrinsicNode(simdType, trueMask, trueVal, falseVal, NI_Sve_ConditionalSelect, + simdBaseJitType, simdSize); + + BlockRange().InsertBefore(node, trueMask); + BlockRange().InsertBefore(node, falseVal); + BlockRange().InsertAfter(node, condSelNode); + use.ReplaceWith(condSelNode); + } + } + } + ContainCheckHWIntrinsic(node); return node->gtNext; } @@ -1252,7 +1364,15 @@ bool Lowering::IsValidConstForMovImm(GenTreeHWIntrinsic* node) // can catch those cases as well. castOp = op1->AsCast()->CastOp(); - op1 = castOp; + + if (varTypeIsIntegral(castOp)) + { + op1 = castOp; + } + else + { + castOp = nullptr; + } } if (op1->IsCnsIntOrI()) @@ -3199,6 +3319,10 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) case NI_Sve_CreateTrueMaskUInt16: case NI_Sve_CreateTrueMaskUInt32: case NI_Sve_CreateTrueMaskUInt64: + case NI_Sve_Count16BitElements: + case NI_Sve_Count32BitElements: + case NI_Sve_Count64BitElements: + case NI_Sve_Count8BitElements: assert(hasImmediateOperand); assert(varTypeIsIntegral(intrin.op1)); if (intrin.op1->IsCnsIntOrI()) @@ -3207,6 +3331,57 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) } break; + case NI_Sve_ConditionalSelect: + { + assert(intrin.numOperands == 3); + GenTree* op1 = intrin.op1; + GenTree* op2 = intrin.op2; + GenTree* op3 = intrin.op3; + + // Handle op1 + if (op1->IsVectorZero()) + { + // When we are merging with zero, we can specialize + // and avoid instantiating the vector constant. + MakeSrcContained(node, op1); + } + + // Handle op2 + if (op2->OperIsHWIntrinsic()) + { + uint32_t maskSize = genTypeSize(node->GetSimdBaseType()); + uint32_t operSize = genTypeSize(op2->AsHWIntrinsic()->GetSimdBaseType()); + + if ((maskSize == operSize) && IsInvariantInRange(op2, node) && + op2->isEmbeddedMaskingCompatibleHWIntrinsic()) + { + MakeSrcContained(node, op2); + op2->MakeEmbMaskOp(); + } + } + + // Handle op3 + if (op3->IsVectorZero() && op1->IsMaskAllBitsSet()) + { + // When we are merging with zero, we can specialize + // and avoid instantiating the vector constant. + // Do this only if op1 was AllTrueMask + MakeSrcContained(node, op3); + } + + break; + } + + case NI_Sve_FusedMultiplyAddBySelectedScalar: + case NI_Sve_FusedMultiplySubtractBySelectedScalar: + assert(hasImmediateOperand); + assert(varTypeIsIntegral(intrin.op4)); + if (intrin.op4->IsCnsIntOrI()) + { + MakeSrcContained(node, intrin.op4); + } + break; + default: unreached(); } diff --git a/src/coreclr/jit/lowerloongarch64.cpp b/src/coreclr/jit/lowerloongarch64.cpp index 4e826be0b225..ffdf11c44ac3 100644 --- a/src/coreclr/jit/lowerloongarch64.cpp +++ b/src/coreclr/jit/lowerloongarch64.cpp @@ -266,11 +266,12 @@ void Lowering::LowerStoreLoc(GenTreeLclVarCommon* storeLoc) // node - The indirect store node (GT_STORE_IND) of interest // // Return Value: -// None. +// Next node to lower. // -void Lowering::LowerStoreIndir(GenTreeStoreInd* node) +GenTree* Lowering::LowerStoreIndir(GenTreeStoreInd* node) { ContainCheckStoreIndir(node); + return node->gtNext; } //------------------------------------------------------------------------ @@ -357,7 +358,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) { // No write barriers are needed on the stack. // If the layout contains a byref, then we know it must live on the stack. - if (dstAddr->OperIs(GT_LCL_ADDR) || layout->HasGCByRef()) + if (dstAddr->OperIs(GT_LCL_ADDR) || layout->IsStackOnly(comp)) { // If the size is small enough to unroll then we need to mark the block as non-interruptible // to actually allow unrolling. The generated code does not report GC references loaded in the @@ -370,6 +371,12 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) // CopyObj or CopyBlk if (doCpObj) { + // Try to use bulk copy helper + if (TryLowerBlockStoreAsGcBulkCopyCall(blkNode)) + { + return; + } + assert((dstAddr->TypeGet() == TYP_BYREF) || (dstAddr->TypeGet() == TYP_I_IMPL)); blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindCpObjUnroll; } diff --git a/src/coreclr/jit/lowerriscv64.cpp b/src/coreclr/jit/lowerriscv64.cpp index aa8342ee1af5..8b74b1cc3178 100644 --- a/src/coreclr/jit/lowerriscv64.cpp +++ b/src/coreclr/jit/lowerriscv64.cpp @@ -215,11 +215,12 @@ void Lowering::LowerStoreLoc(GenTreeLclVarCommon* storeLoc) // node - The indirect store node (GT_STORE_IND) of interest // // Return Value: -// None. +// Next node to lower. // -void Lowering::LowerStoreIndir(GenTreeStoreInd* node) +GenTree* Lowering::LowerStoreIndir(GenTreeStoreInd* node) { ContainCheckStoreIndir(node); + return node->gtNext; } //------------------------------------------------------------------------ @@ -306,7 +307,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) { // No write barriers are needed on the stack. // If the layout contains a byref, then we know it must live on the stack. - if (dstAddr->OperIs(GT_LCL_ADDR) || layout->HasGCByRef()) + if (dstAddr->OperIs(GT_LCL_ADDR) || layout->IsStackOnly(comp)) { // If the size is small enough to unroll then we need to mark the block as non-interruptible // to actually allow unrolling. The generated code does not report GC references loaded in the @@ -319,6 +320,12 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) // CopyObj or CopyBlk if (doCpObj) { + // Try to use bulk copy helper + if (TryLowerBlockStoreAsGcBulkCopyCall(blkNode)) + { + return; + } + assert((dstAddr->TypeGet() == TYP_BYREF) || (dstAddr->TypeGet() == TYP_I_IMPL)); blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindCpObjUnroll; } diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 5a9b12ca4aa2..22526033478c 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -73,9 +73,9 @@ void Lowering::LowerStoreLoc(GenTreeLclVarCommon* storeLoc) // node - The indirect store node (GT_STORE_IND) of interest // // Return Value: -// None. +// Next node to lower. // -void Lowering::LowerStoreIndir(GenTreeStoreInd* node) +GenTree* Lowering::LowerStoreIndir(GenTreeStoreInd* node) { // Mark all GT_STOREIND nodes to indicate that it is not known // whether it represents a RMW memory op. @@ -92,7 +92,7 @@ void Lowering::LowerStoreIndir(GenTreeStoreInd* node) // SSE2 doesn't support RMW form of instructions. if (LowerRMWMemOp(node)) { - return; + return node->gtNext; } } @@ -109,23 +109,25 @@ void Lowering::LowerStoreIndir(GenTreeStoreInd* node) { if (!node->Data()->IsCnsVec()) { - return; + return node->gtNext; } if (!node->Data()->AsVecCon()->TypeIs(TYP_SIMD32, TYP_SIMD64)) { - return; + return node->gtNext; } if (node->Data()->IsVectorAllBitsSet() || node->Data()->IsVectorZero()) { // To avoid some unexpected regression, this optimization only applies to non-all 1/0 constant vectors. - return; + return node->gtNext; } TryCompressConstVecData(node); } #endif + + return node->gtNext; } //---------------------------------------------------------------------------------------------- @@ -443,8 +445,8 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) if (doCpObj && (size <= copyBlockUnrollLimit)) { // No write barriers are needed on the stack. - // If the layout contains a byref, then we know it must live on the stack. - if (dstAddr->OperIs(GT_LCL_ADDR) || layout->HasGCByRef()) + // If the layout is byref-like, then we know it must live on the stack. + if (dstAddr->OperIs(GT_LCL_ADDR) || layout->IsStackOnly(comp)) { // If the size is small enough to unroll then we need to mark the block as non-interruptible // to actually allow unrolling. The generated code does not report GC references loaded in the @@ -457,6 +459,12 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) if (doCpObj) { + // Try to use bulk copy helper + if (TryLowerBlockStoreAsGcBulkCopyCall(blkNode)) + { + return; + } + assert((dstAddr->TypeGet() == TYP_BYREF) || (dstAddr->TypeGet() == TYP_I_IMPL)); // If we have a long enough sequence of slots that do not require write barriers then @@ -465,7 +473,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) // the entire operation takes 20 cycles and encodes in 5 bytes (loading RCX and REP MOVSD/Q). unsigned nonGCSlots = 0; - if (dstAddr->OperIs(GT_LCL_ADDR)) + if (dstAddr->OperIs(GT_LCL_ADDR) || layout->IsStackOnly(comp)) { // If the destination is on the stack then no write barriers are needed. nonGCSlots = layout->GetSlotCount(); @@ -1913,6 +1921,68 @@ GenTree* Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node) } // pre-AVX doesn't actually support these intrinsics in hardware so we need to swap the operands around + NamedIntrinsic newIntrinsicId = NI_Illegal; + + switch (intrinsicId) + { + case NI_SSE_CompareGreaterThan: + { + newIntrinsicId = NI_SSE_CompareLessThan; + break; + } + + case NI_SSE_CompareGreaterThanOrEqual: + { + newIntrinsicId = NI_SSE_CompareLessThanOrEqual; + break; + } + + case NI_SSE_CompareNotGreaterThan: + { + newIntrinsicId = NI_SSE_CompareNotLessThan; + break; + } + + case NI_SSE_CompareNotGreaterThanOrEqual: + { + newIntrinsicId = NI_SSE_CompareNotLessThanOrEqual; + break; + } + + case NI_SSE2_CompareGreaterThan: + { + newIntrinsicId = NI_SSE2_CompareLessThan; + break; + } + + case NI_SSE2_CompareGreaterThanOrEqual: + { + newIntrinsicId = NI_SSE2_CompareLessThanOrEqual; + break; + } + + case NI_SSE2_CompareNotGreaterThan: + { + newIntrinsicId = NI_SSE2_CompareNotLessThan; + break; + } + + case NI_SSE2_CompareNotGreaterThanOrEqual: + { + newIntrinsicId = NI_SSE2_CompareNotLessThanOrEqual; + break; + } + + default: + { + unreached(); + } + } + + assert(newIntrinsicId != NI_Illegal); + assert(intrinsicId != newIntrinsicId); + + node->ChangeHWIntrinsicId(newIntrinsicId); std::swap(node->Op(1), node->Op(2)); break; } @@ -1927,7 +1997,39 @@ GenTree* Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node) } assert(varTypeIsIntegral(node->GetSimdBaseType())); - // this isn't actually supported in hardware so we need to swap the operands around + // pre-AVX512 doesn't actually support these intrinsics in hardware so we need to swap the operands around + NamedIntrinsic newIntrinsicId = NI_Illegal; + + switch (intrinsicId) + { + case NI_SSE2_CompareLessThan: + { + newIntrinsicId = NI_SSE2_CompareGreaterThan; + break; + } + + case NI_SSE42_CompareLessThan: + { + newIntrinsicId = NI_SSE42_CompareGreaterThan; + break; + } + + case NI_AVX2_CompareLessThan: + { + newIntrinsicId = NI_AVX2_CompareGreaterThan; + break; + } + + default: + { + unreached(); + } + } + + assert(newIntrinsicId != NI_Illegal); + assert(intrinsicId != newIntrinsicId); + + node->ChangeHWIntrinsicId(newIntrinsicId); std::swap(node->Op(1), node->Op(2)); break; } @@ -2153,12 +2255,18 @@ GenTree* Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cm // node = * HWINTRINSIC simd T op_Equality GenTree* op1 = node->Op(1); + GenTree* op1Msk = op1; GenTree* op2 = node->Op(2); GenCondition cmpCnd = (cmpOp == GT_EQ) ? GenCondition::EQ : GenCondition::NE; + if (op1Msk->OperIsHWIntrinsic(NI_AVX512F_ConvertMaskToVector)) + { + op1Msk = op1Msk->AsHWIntrinsic()->Op(1); + assert(varTypeIsMask(op1Msk)); + } + if (!varTypeIsFloating(simdBaseType) && (simdSize != 64) && op2->IsVectorZero() && - comp->compOpportunisticallyDependsOn(InstructionSet_SSE41) && - !op1->OperIsHWIntrinsic(NI_AVX512F_ConvertMaskToVector)) + comp->compOpportunisticallyDependsOn(InstructionSet_SSE41) && !varTypeIsMask(op1Msk)) { // On SSE4.1 or higher we can optimize comparisons against zero to // just use PTEST. We can't support it for floating-point, however, @@ -2352,7 +2460,7 @@ GenTree* Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cm // This works since the upper bits are implicitly zero and so by inverting matches also become // zero, which in turn means that `AllBitsSet` will become `Zero` and other cases become non-zero - if (op1->OperIsHWIntrinsic(NI_AVX512F_ConvertMaskToVector) && op2->IsCnsVec()) + if (varTypeIsMask(op1Msk) && op2->IsCnsVec()) { // We want to specially handle the common cases of `mask op Zero` and `mask op AllBitsSet` // @@ -2361,7 +2469,7 @@ GenTree* Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cm // simply consume the mask directly and preserve the intended comparison by tweaking the // compare condition passed down into `KORTEST` - maskNode = op1->AsHWIntrinsic()->Op(1); + maskNode = op1Msk; assert(maskNode->TypeIs(TYP_MASK)); bool isHandled = false; @@ -2544,7 +2652,12 @@ GenTree* Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cm } BlockRange().Remove(op2); - BlockRange().Remove(op1); + + if (op1Msk != op1) + { + BlockRange().Remove(op1); + } + BlockRange().Remove(node); op1 = nullptr; @@ -2970,7 +3083,7 @@ GenTree* Lowering::LowerHWIntrinsicCndSel(GenTreeHWIntrinsic* node) } //---------------------------------------------------------------------------------------------- -// Lowering::LowerHWIntrinsicCndSel: Lowers an AVX512 TernaryLogic call +// Lowering::LowerHWIntrinsicTernaryLogic: Lowers an AVX512 TernaryLogic call // // Arguments: // node - The hardware intrinsic node. @@ -3083,15 +3196,151 @@ GenTree* Lowering::LowerHWIntrinsicTernaryLogic(GenTreeHWIntrinsic* node) } } - if (!condition->OperIsHWIntrinsic(NI_AVX512F_ConvertMaskToVector)) + if (condition->OperIsHWIntrinsic(NI_AVX512F_ConvertMaskToVector)) { - break; + GenTree* tmp = condition->AsHWIntrinsic()->Op(1); + BlockRange().Remove(condition); + condition = tmp; } + else if (!varTypeIsMask(condition)) + { + if (!condition->OperIsHWIntrinsic()) + { + break; + } + + GenTreeHWIntrinsic* cndNode = condition->AsHWIntrinsic(); + NamedIntrinsic cndId = cndNode->GetHWIntrinsicId(); + + switch (cndId) + { + case NI_AVX_Compare: + { + cndId = NI_AVX512F_CompareMask; + break; + } - node->ResetHWIntrinsicId(NI_AVX512F_BlendVariableMask, comp, selectFalse, selectTrue, - condition->AsHWIntrinsic()->Op(1)); + case NI_SSE_CompareEqual: + case NI_SSE2_CompareEqual: + case NI_SSE41_CompareEqual: + case NI_AVX_CompareEqual: + case NI_AVX2_CompareEqual: + { + cndId = NI_AVX512F_CompareEqualMask; + break; + } + + case NI_SSE_CompareGreaterThan: + case NI_SSE2_CompareGreaterThan: + case NI_SSE42_CompareGreaterThan: + case NI_AVX_CompareGreaterThan: + case NI_AVX2_CompareGreaterThan: + { + cndId = NI_AVX512F_CompareGreaterThanMask; + break; + } + + case NI_SSE_CompareGreaterThanOrEqual: + case NI_SSE2_CompareGreaterThanOrEqual: + case NI_AVX_CompareGreaterThanOrEqual: + { + cndId = NI_AVX512F_CompareGreaterThanOrEqualMask; + break; + } + + case NI_SSE_CompareLessThan: + case NI_SSE2_CompareLessThan: + case NI_SSE42_CompareLessThan: + case NI_AVX_CompareLessThan: + case NI_AVX2_CompareLessThan: + { + cndId = NI_AVX512F_CompareLessThanMask; + break; + } + + case NI_SSE_CompareLessThanOrEqual: + case NI_SSE2_CompareLessThanOrEqual: + case NI_AVX_CompareLessThanOrEqual: + { + cndId = NI_AVX512F_CompareLessThanOrEqualMask; + break; + } + + case NI_SSE_CompareNotEqual: + case NI_SSE2_CompareNotEqual: + case NI_AVX_CompareNotEqual: + { + cndId = NI_AVX512F_CompareNotEqualMask; + break; + } + + case NI_SSE_CompareNotGreaterThan: + case NI_SSE2_CompareNotGreaterThan: + case NI_AVX_CompareNotGreaterThan: + { + cndId = NI_AVX512F_CompareGreaterThanMask; + break; + } + + case NI_SSE_CompareNotGreaterThanOrEqual: + case NI_SSE2_CompareNotGreaterThanOrEqual: + case NI_AVX_CompareNotGreaterThanOrEqual: + { + cndId = NI_AVX512F_CompareNotGreaterThanOrEqualMask; + break; + } + + case NI_SSE_CompareNotLessThan: + case NI_SSE2_CompareNotLessThan: + case NI_AVX_CompareNotLessThan: + { + cndId = NI_AVX512F_CompareNotLessThanMask; + break; + } - BlockRange().Remove(condition); + case NI_SSE_CompareNotLessThanOrEqual: + case NI_SSE2_CompareNotLessThanOrEqual: + case NI_AVX_CompareNotLessThanOrEqual: + { + cndId = NI_AVX512F_CompareNotLessThanOrEqualMask; + break; + } + + case NI_SSE_CompareOrdered: + case NI_SSE2_CompareOrdered: + case NI_AVX_CompareOrdered: + { + cndId = NI_AVX512F_CompareOrderedMask; + break; + } + + case NI_SSE_CompareUnordered: + case NI_SSE2_CompareUnordered: + case NI_AVX_CompareUnordered: + { + cndId = NI_AVX512F_CompareUnorderedMask; + break; + } + + default: + { + assert(!HWIntrinsicInfo::ReturnsPerElementMask(cndId)); + cndId = NI_Illegal; + break; + } + } + + if (cndId == NI_Illegal) + { + break; + } + + cndNode->gtType = TYP_MASK; + cndNode->ChangeHWIntrinsicId(cndId); + } + + assert(varTypeIsMask(condition)); + node->ResetHWIntrinsicId(NI_AVX512F_BlendVariableMask, comp, selectFalse, selectTrue, condition); BlockRange().Remove(op4); break; } @@ -8362,6 +8611,7 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* parentNode, GenTre case NI_AVX2_ShuffleLow: case NI_AVX512F_AlignRight32: case NI_AVX512F_AlignRight64: + case NI_AVX512F_CompareMask: case NI_AVX512F_Fixup: case NI_AVX512F_GetMantissa: case NI_AVX512F_Permute2x64: @@ -8830,18 +9080,16 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* parentNode, GenTre return false; } - case NI_Vector128_get_Zero: - case NI_Vector256_get_Zero: - { - // These are only containable as part of Sse41.Insert - return false; - } - case NI_SSE3_MoveAndDuplicate: case NI_AVX2_BroadcastScalarToVector128: case NI_AVX2_BroadcastScalarToVector256: case NI_AVX512F_BroadcastScalarToVector512: { + if (comp->opts.MinOpts() || !comp->canUseEmbeddedBroadcast()) + { + return false; + } + var_types parentBaseType = parentNode->GetSimdBaseType(); var_types childBaseType = hwintrinsic->GetSimdBaseType(); @@ -8924,8 +9172,15 @@ void Lowering::TryFoldCnsVecForEmbeddedBroadcast(GenTreeHWIntrinsic* parentNode, var_types simdType = parentNode->TypeGet(); var_types simdBaseType = parentNode->GetSimdBaseType(); CorInfoType simdBaseJitType = parentNode->GetSimdBaseJitType(); + unsigned simdSize = parentNode->GetSimdSize(); bool isCreatedFromScalar = true; - int elementCount = GenTreeVecCon::ElementCount(genTypeSize(simdType), simdBaseType); + + if (simdType == TYP_MASK) + { + simdType = Compiler::getSIMDTypeForSize(simdSize); + } + int elementCount = GenTreeVecCon::ElementCount(genTypeSize(simdType), simdBaseType); + switch (simdBaseType) { case TYP_FLOAT: @@ -10137,7 +10392,20 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) // contained and not a memory operand and know to invoke the special handling // so that the embedded masking can work as expected. - if (op2->isEvexEmbeddedMaskingCompatibleHWIntrinsic()) + bool isEmbeddedMask = false; + + if (op2->isEmbeddedMaskingCompatibleHWIntrinsic()) + { + isEmbeddedMask = !comp->opts.MinOpts() && comp->canUseEmbeddedMasking(); + + if (op2->isRMWHWIntrinsic(comp)) + { + // TODO-AVX512-CQ: Ensure we can support embedded operations on RMW intrinsics + isEmbeddedMask = false; + } + } + + if (isEmbeddedMask) { uint32_t maskSize = genTypeSize(simdBaseType); uint32_t operSize = genTypeSize(op2->AsHWIntrinsic()->GetSimdBaseType()); @@ -10151,6 +10419,8 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) { // When we are merging with zero, we can specialize // and avoid instantiating the vector constant. + + assert(!op2->TypeIs(TYP_MASK)); MakeSrcContained(node, op1); } break; @@ -10280,6 +10550,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) case NI_AVX2_Permute2x128: case NI_AVX512F_AlignRight32: case NI_AVX512F_AlignRight64: + case NI_AVX512F_CompareMask: case NI_AVX512F_GetMantissaScalar: case NI_AVX512F_InsertVector128: case NI_AVX512F_InsertVector256: diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 831f6c7ac194..060f5d497d37 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -271,20 +271,31 @@ regMaskTP LinearScan::lowSIMDRegs() #endif } -void LinearScan::updateNextFixedRef(RegRecord* regRecord, RefPosition* nextRefPosition) +void LinearScan::updateNextFixedRef(RegRecord* regRecord, RefPosition* nextRefPosition, RefPosition* nextKill) { - LsraLocation nextLocation; + LsraLocation nextLocation = nextRefPosition == nullptr ? MaxLocation : nextRefPosition->nodeLocation; - if (nextRefPosition == nullptr) + RefPosition* kill = nextKill; + while ((kill != nullptr) && (kill->nodeLocation < nextLocation)) + { + if ((kill->registerAssignment & genRegMask(regRecord->regNum)) != RBM_NONE) + { + nextLocation = kill->nodeLocation; + break; + } + + kill = kill->nextRefPosition; + } + + if (nextLocation == MaxLocation) { - nextLocation = MaxLocation; fixedRegs &= ~genRegMask(regRecord->regNum); } else { - nextLocation = nextRefPosition->nodeLocation; fixedRegs |= genRegMask(regRecord->regNum); } + nextFixedRef[regRecord->regNum] = nextLocation; } @@ -496,6 +507,46 @@ regMaskTP LinearScan::getConstrainedRegMask(RefPosition* refPosition, return newMask; } +//------------------------------------------------------------------------ +// When LSRA_LIMIT_SMALL_SET is specified, it is desirable to select a "mixed" set of caller- and callee-save +// registers, so as to get different coverage than limiting to callee or caller. +// At least for x86 and AMD64, and potentially other architecture that will support SIMD, +// we need a minimum of 5 fp regs in order to support the InitN intrinsic for Vector4. +// Hence the "SmallFPSet" has 5 elements. + +#if defined(TARGET_AMD64) +#ifdef UNIX_AMD64_ABI +// On System V the RDI and RSI are not callee saved. Use R12 ans R13 as callee saved registers. +static const regMaskTP LsraLimitSmallIntSet = (RBM_EAX | RBM_ECX | RBM_EBX | RBM_ETW_FRAMED_EBP | RBM_R12 | RBM_R13); +#else // !UNIX_AMD64_ABI +// On Windows Amd64 use the RDI and RSI as callee saved registers. +static const regMaskTP LsraLimitSmallIntSet = (RBM_EAX | RBM_ECX | RBM_EBX | RBM_ETW_FRAMED_EBP | RBM_ESI | RBM_EDI); +#endif // !UNIX_AMD64_ABI +static const regMaskTP LsraLimitSmallFPSet = (RBM_XMM0 | RBM_XMM1 | RBM_XMM2 | RBM_XMM6 | RBM_XMM7); +static const regMaskTP LsraLimitUpperSimdSet = + (RBM_XMM16 | RBM_XMM17 | RBM_XMM18 | RBM_XMM19 | RBM_XMM20 | RBM_XMM21 | RBM_XMM22 | RBM_XMM23 | RBM_XMM24 | + RBM_XMM25 | RBM_XMM26 | RBM_XMM27 | RBM_XMM28 | RBM_XMM29 | RBM_XMM30 | RBM_XMM31); +#elif defined(TARGET_ARM) +// On ARM, we may need two registers to set up the target register for a virtual call, so we need +// to have at least the maximum number of arg registers, plus 2. +static const regMaskTP LsraLimitSmallIntSet = (RBM_R0 | RBM_R1 | RBM_R2 | RBM_R3 | RBM_R4 | RBM_R5); +static const regMaskTP LsraLimitSmallFPSet = (RBM_F0 | RBM_F1 | RBM_F2 | RBM_F16 | RBM_F17); +#elif defined(TARGET_ARM64) +static const regMaskTP LsraLimitSmallIntSet = (RBM_R0 | RBM_R1 | RBM_R2 | RBM_R19 | RBM_R20); +static const regMaskTP LsraLimitSmallFPSet = (RBM_V0 | RBM_V1 | RBM_V2 | RBM_V8 | RBM_V9); +#elif defined(TARGET_X86) +static const regMaskTP LsraLimitSmallIntSet = (RBM_EAX | RBM_ECX | RBM_EDI); +static const regMaskTP LsraLimitSmallFPSet = (RBM_XMM0 | RBM_XMM1 | RBM_XMM2 | RBM_XMM6 | RBM_XMM7); +#elif defined(TARGET_LOONGARCH64) +static const regMaskTP LsraLimitSmallIntSet = (RBM_T1 | RBM_T3 | RBM_A0 | RBM_A1 | RBM_T0); +static const regMaskTP LsraLimitSmallFPSet = (RBM_F0 | RBM_F1 | RBM_F2 | RBM_F8 | RBM_F9); +#elif defined(TARGET_RISCV64) +static const regMaskTP LsraLimitSmallIntSet = (RBM_T1 | RBM_T3 | RBM_A0 | RBM_A1 | RBM_T0); +static const regMaskTP LsraLimitSmallFPSet = (RBM_F0 | RBM_F1 | RBM_F2 | RBM_F8 | RBM_F9); +#else +#error Unsupported or unset target architecture +#endif // target + //------------------------------------------------------------------------ // stressLimitRegs: Given a set of registers, expressed as a register mask, reduce // them based on the current stress options. @@ -712,6 +763,8 @@ LinearScan::LinearScan(Compiler* theCompiler) , intervals(theCompiler->getAllocator(CMK_LSRA_Interval)) , allocationPassComplete(false) , refPositions(theCompiler->getAllocator(CMK_LSRA_RefPosition)) + , killHead(nullptr) + , killTail(&killHead) , listNodePool(theCompiler) { availableRegCount = ACTUAL_REG_COUNT; @@ -775,6 +828,9 @@ LinearScan::LinearScan(Compiler* theCompiler) regSelector = new (theCompiler, CMK_LSRA) RegisterSelection(this); #ifdef TARGET_ARM64 + // Note: one known reason why we exclude LR is because NativeAOT has dependency on not + // using LR as a GPR. See: https://github.com/dotnet/runtime/issues/101932 + // Once that is addressed, we may consider allowing LR in availableIntRegs. availableIntRegs = (RBM_ALLINT & ~(RBM_PR | RBM_FP | RBM_LR) & ~compiler->codeGen->regSet.rsMaskResvd); #elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) availableIntRegs = (RBM_ALLINT & ~(RBM_FP | RBM_RA) & ~compiler->codeGen->regSet.rsMaskResvd); @@ -1680,21 +1736,6 @@ bool LinearScan::isRegCandidate(LclVarDsc* varDsc) return false; } - // Avoid allocating parameters that are passed in float regs into integer - // registers. We currently home float registers before integer registers, - // so that kind of enregistration can trash integer registers containing - // other parameters. - // We assume that these cases will be homed to float registers if they are - // promoted. - // TODO-CQ: Combine integer and float register homing to handle these kinds - // of conflicts. - if ((varDsc->TypeGet() == TYP_STRUCT) && varDsc->lvIsRegArg && !varDsc->lvPromoted && - varTypeUsesIntReg(varDsc->GetRegisterType()) && genIsValidFloatReg(varDsc->GetArgReg())) - { - compiler->lvaSetVarDoNotEnregister(lclNum DEBUGARG(DoNotEnregisterReason::IsStructArg)); - return false; - } - // Are we not optimizing and we have exception handlers? // if so mark all args and locals as volatile, so that they // won't ever get enregistered. @@ -1728,8 +1769,10 @@ bool LinearScan::isRegCandidate(LclVarDsc* varDsc) #if defined(TARGET_XARCH) case TYP_SIMD32: case TYP_SIMD64: - case TYP_MASK: #endif // TARGET_XARCH +#ifdef FEATURE_MASKED_HW_INTRINSICS + case TYP_MASK: +#endif // FEATURE_MASKED_HW_INTRINSICS { return !varDsc->lvPromoted; } @@ -3963,6 +4006,41 @@ void LinearScan::unassignPhysReg(RegRecord* regRec, RefPosition* spillRefPositio } } +//------------------------------------------------------------------------ +// processKills: Handle that some registers are being killed. +// +// Arguments: +// killRefPosition - The RefPosition for the kill +// +void LinearScan::processKills(RefPosition* killRefPosition) +{ + RefPosition* nextKill = killRefPosition->nextRefPosition; + + regMaskTP killedRegs = killRefPosition->registerAssignment; + while (killedRegs != RBM_NONE) + { + regNumber killedReg = genFirstRegNumFromMaskAndToggle(killedRegs); + RegRecord* regRecord = getRegisterRecord(killedReg); + Interval* assignedInterval = regRecord->assignedInterval; + if (assignedInterval != nullptr) + { + unassignPhysReg(regRecord, assignedInterval->recentRefPosition); + clearConstantReg(regRecord->regNum, assignedInterval->registerType); + makeRegAvailable(regRecord->regNum, assignedInterval->registerType); + } + + assert((nextFixedRef[killedReg] == killRefPosition->nodeLocation) || (killedReg >= AVAILABLE_REG_COUNT)); + RefPosition* regNextRefPos = regRecord->recentRefPosition == nullptr + ? regRecord->firstRefPosition + : regRecord->recentRefPosition->nextRefPosition; + updateNextFixedRef(regRecord, regNextRefPos, nextKill); + } + + regsBusyUntilKill &= ~killRefPosition->registerAssignment; + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_KILL_REGS, nullptr, REG_NA, nullptr, NONE, + killRefPosition->registerAssignment)); +} + //------------------------------------------------------------------------ // spillGCRefs: Spill any GC-type intervals that are currently in registers. // @@ -4880,7 +4958,7 @@ void LinearScan::allocateRegistersMinimal() { RegRecord* physRegRecord = getRegisterRecord(reg); physRegRecord->recentRefPosition = nullptr; - updateNextFixedRef(physRegRecord, physRegRecord->firstRefPosition); + updateNextFixedRef(physRegRecord, physRegRecord->firstRefPosition, killHead); assert(physRegRecord->assignedInterval == nullptr); } @@ -4901,7 +4979,8 @@ void LinearScan::allocateRegistersMinimal() } #endif // DEBUG - BasicBlock* currentBlock = nullptr; + BasicBlock* currentBlock = nullptr; + RefPosition* nextKill = killHead; LsraLocation prevLocation = MinLocation; regMaskTP regsToFree = RBM_NONE; @@ -4921,8 +5000,6 @@ void LinearScan::allocateRegistersMinimal() for (RefPosition& currentRefPosition : refPositions) { - RefPosition* nextRefPosition = currentRefPosition.nextRefPosition; - // TODO: Can we combine this with the freeing of registers below? It might // mess with the dump, since this was previously being done before the call below // to dumpRegRecords. @@ -5032,7 +5109,7 @@ void LinearScan::allocateRegistersMinimal() } else { - assert((refType == RefTypeBB) || (refType == RefTypeKillGCRefs)); + assert((refType == RefTypeBB) || (refType == RefTypeKill) || (refType == RefTypeKillGCRefs)); } #ifdef DEBUG @@ -5081,65 +5158,59 @@ void LinearScan::allocateRegistersMinimal() continue; } + if (refType == RefTypeKill) + { + assert(nextKill == ¤tRefPosition); + processKills(¤tRefPosition); + nextKill = nextKill->nextRefPosition; + continue; + } + if (refType == RefTypeKillGCRefs) { spillGCRefs(¤tRefPosition); continue; } - if (currentRefPosition.isPhysRegRef) + if (refType == RefTypeFixedReg) { RegRecord* regRecord = currentRefPosition.getReg(); Interval* assignedInterval = regRecord->assignedInterval; - updateNextFixedRef(regRecord, currentRefPosition.nextRefPosition); + updateNextFixedRef(regRecord, currentRefPosition.nextRefPosition, nextKill); - // If this is a FixedReg, disassociate any inactive constant interval from this register. - // Otherwise, do nothing. - if (refType == RefTypeFixedReg) + // This is a FixedReg. Disassociate any inactive constant interval from this register. + if (assignedInterval != nullptr && !assignedInterval->isActive && assignedInterval->isConstant) { - if (assignedInterval != nullptr && !assignedInterval->isActive && assignedInterval->isConstant) - { - clearConstantReg(regRecord->regNum, assignedInterval->registerType); - regRecord->assignedInterval = nullptr; - spillCost[regRecord->regNum] = 0; + clearConstantReg(regRecord->regNum, assignedInterval->registerType); + regRecord->assignedInterval = nullptr; + spillCost[regRecord->regNum] = 0; #ifdef TARGET_ARM - // Update overlapping floating point register for TYP_DOUBLE - if (assignedInterval->registerType == TYP_DOUBLE) - { - RegRecord* otherRegRecord = findAnotherHalfRegRec(regRecord); - assert(otherRegRecord->assignedInterval == assignedInterval); - otherRegRecord->assignedInterval = nullptr; - spillCost[otherRegRecord->regNum] = 0; - } -#endif // TARGET_ARM - } - regsInUseThisLocation |= currentRefPosition.registerAssignment; - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_FIXED_REG, nullptr, currentRefPosition.assignedReg())); - -#ifdef SWIFT_SUPPORT - if (currentRefPosition.delayRegFree) + // Update overlapping floating point register for TYP_DOUBLE + if (assignedInterval->registerType == TYP_DOUBLE) { - regsInUseNextLocation |= currentRefPosition.registerAssignment; + RegRecord* otherRegRecord = findAnotherHalfRegRec(regRecord); + assert(otherRegRecord->assignedInterval == assignedInterval); + otherRegRecord->assignedInterval = nullptr; + spillCost[otherRegRecord->regNum] = 0; } -#endif // SWIFT_SUPPORT +#endif // TARGET_ARM } - else + regsInUseThisLocation |= currentRefPosition.registerAssignment; + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_FIXED_REG, nullptr, currentRefPosition.assignedReg())); + +#ifdef SWIFT_SUPPORT + if (currentRefPosition.delayRegFree) { - assert(refType == RefTypeKill); - if (assignedInterval != nullptr) - { - unassignPhysReg(regRecord, assignedInterval->recentRefPosition); - clearConstantReg(regRecord->regNum, assignedInterval->registerType); - makeRegAvailable(regRecord->regNum, assignedInterval->registerType); - } - clearRegBusyUntilKill(regRecord->regNum); - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_KEPT_ALLOCATION, nullptr, regRecord->regNum)); + regsInUseNextLocation |= currentRefPosition.registerAssignment; } +#endif // SWIFT_SUPPORT continue; } + assert(!currentRefPosition.isPhysRegRef); + regNumber assignedRegister = REG_NA; assert(currentRefPosition.isIntervalRef()); @@ -5519,7 +5590,7 @@ void LinearScan::allocateRegisters() Interval* currentInterval = &interval; currentInterval->recentRefPosition = nullptr; currentInterval->isActive = false; - if (currentInterval->isLocalVar) + if (currentInterval->isLocalVar && !stressInitialParamReg()) { LclVarDsc* varDsc = currentInterval->getLocalVar(compiler); if (varDsc->lvIsRegArg && currentInterval->firstRefPosition != nullptr) @@ -5547,7 +5618,7 @@ void LinearScan::allocateRegisters() { RegRecord* physRegRecord = getRegisterRecord(reg); physRegRecord->recentRefPosition = nullptr; - updateNextFixedRef(physRegRecord, physRegRecord->firstRefPosition); + updateNextFixedRef(physRegRecord, physRegRecord->firstRefPosition, killHead); // Is this an incoming arg register? (Note that we don't, currently, consider reassigning // an incoming arg register as having spill cost.) @@ -5588,7 +5659,8 @@ void LinearScan::allocateRegisters() } #endif // DEBUG - BasicBlock* currentBlock = nullptr; + BasicBlock* currentBlock = nullptr; + RefPosition* nextKill = killHead; LsraLocation prevLocation = MinLocation; regMaskTP regsToFree = RBM_NONE; @@ -5740,7 +5812,7 @@ void LinearScan::allocateRegisters() } else { - assert((refType == RefTypeBB) || (refType == RefTypeKillGCRefs)); + assert((refType == RefTypeBB) || (refType == RefTypeKill) || (refType == RefTypeKillGCRefs)); } #ifdef DEBUG @@ -5796,65 +5868,59 @@ void LinearScan::allocateRegisters() continue; } + if (refType == RefTypeKill) + { + assert(nextKill == ¤tRefPosition); + processKills(¤tRefPosition); + nextKill = nextKill->nextRefPosition; + continue; + } + if (refType == RefTypeKillGCRefs) { spillGCRefs(¤tRefPosition); continue; } - if (currentRefPosition.isPhysRegRef) + if (refType == RefTypeFixedReg) { RegRecord* regRecord = currentRefPosition.getReg(); Interval* assignedInterval = regRecord->assignedInterval; - updateNextFixedRef(regRecord, currentRefPosition.nextRefPosition); + updateNextFixedRef(regRecord, currentRefPosition.nextRefPosition, nextKill); - // If this is a FixedReg, disassociate any inactive constant interval from this register. - // Otherwise, do nothing. - if (refType == RefTypeFixedReg) + // This is a FixedReg. Disassociate any inactive constant interval from this register. + if (assignedInterval != nullptr && !assignedInterval->isActive && assignedInterval->isConstant) { - if (assignedInterval != nullptr && !assignedInterval->isActive && assignedInterval->isConstant) - { - clearConstantReg(regRecord->regNum, assignedInterval->registerType); - regRecord->assignedInterval = nullptr; - spillCost[regRecord->regNum] = 0; + clearConstantReg(regRecord->regNum, assignedInterval->registerType); + regRecord->assignedInterval = nullptr; + spillCost[regRecord->regNum] = 0; #ifdef TARGET_ARM - // Update overlapping floating point register for TYP_DOUBLE - if (assignedInterval->registerType == TYP_DOUBLE) - { - RegRecord* otherRegRecord = findAnotherHalfRegRec(regRecord); - assert(otherRegRecord->assignedInterval == assignedInterval); - otherRegRecord->assignedInterval = nullptr; - spillCost[otherRegRecord->regNum] = 0; - } -#endif // TARGET_ARM - } - regsInUseThisLocation |= currentRefPosition.registerAssignment; - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_FIXED_REG, nullptr, currentRefPosition.assignedReg())); - -#ifdef SWIFT_SUPPORT - if (currentRefPosition.delayRegFree) + // Update overlapping floating point register for TYP_DOUBLE + if (assignedInterval->registerType == TYP_DOUBLE) { - regsInUseNextLocation |= currentRefPosition.registerAssignment; + RegRecord* otherRegRecord = findAnotherHalfRegRec(regRecord); + assert(otherRegRecord->assignedInterval == assignedInterval); + otherRegRecord->assignedInterval = nullptr; + spillCost[otherRegRecord->regNum] = 0; } -#endif // SWIFT_SUPPORT +#endif // TARGET_ARM } - else + regsInUseThisLocation |= currentRefPosition.registerAssignment; + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_FIXED_REG, nullptr, currentRefPosition.assignedReg())); + +#ifdef SWIFT_SUPPORT + if (currentRefPosition.delayRegFree) { - assert(refType == RefTypeKill); - if (assignedInterval != nullptr) - { - unassignPhysReg(regRecord, assignedInterval->recentRefPosition); - clearConstantReg(regRecord->regNum, assignedInterval->registerType); - makeRegAvailable(regRecord->regNum, assignedInterval->registerType); - } - clearRegBusyUntilKill(regRecord->regNum); - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_KEPT_ALLOCATION, nullptr, regRecord->regNum)); + regsInUseNextLocation |= currentRefPosition.registerAssignment; } +#endif // SWIFT_SUPPORT continue; } + assert(!currentRefPosition.isPhysRegRef); + // If this is an exposed use, do nothing - this is merely a placeholder to attempt to // ensure that a register is allocated for the full lifetime. The resolution logic // will take care of moving to the appropriate register if needed. @@ -7406,7 +7472,6 @@ void LinearScan::insertCopyOrReload(BasicBlock* block, GenTree* tree, unsigned m // child needs to be copied or reloaded to that reg. if (parent->IsCopyOrReload()) { - noway_assert(parent->OperGet() == oper); noway_assert(tree->IsMultiRegNode()); GenTreeCopyOrReload* copyOrReload = parent->AsCopyOrReload(); noway_assert(copyOrReload->GetRegNumByIdx(multiRegIdx) == REG_NA); @@ -7987,7 +8052,6 @@ void LinearScan::resolveRegisters() case RefTypeDef: // These are the ones we're interested in break; - case RefTypeKill: case RefTypeFixedReg: // These require no handling at resolution time assert(currentRefPosition->referent != nullptr); @@ -8003,6 +8067,7 @@ void LinearScan::resolveRegisters() currentRefPosition->getInterval()->getVarIndex(compiler))); currentRefPosition->referent->recentRefPosition = currentRefPosition; continue; + case RefTypeKill: case RefTypeKillGCRefs: // No action to take at resolution time, and no interval to update recentRefPosition for. continue; @@ -8121,7 +8186,7 @@ void LinearScan::resolveRegisters() assert(currentRefPosition->isIntervalRef()); if (currentRefPosition->getInterval()->isInternal) { - treeNode->gtRsvdRegs |= currentRefPosition->registerAssignment; + compiler->codeGen->internalRegisters.Add(treeNode, currentRefPosition->registerAssignment); } else { @@ -8515,16 +8580,16 @@ void LinearScan::insertMove( noway_assert(!blockRange.IsEmpty()); GenTree* branch = lastNode; - assert(branch->OperIsConditionalJump() || branch->OperGet() == GT_SWITCH_TABLE || - branch->OperGet() == GT_SWITCH); + assert(branch->OperIsConditionalJump() || branch->OperIs(GT_SWITCH_TABLE, GT_SWITCH)); blockRange.InsertBefore(branch, std::move(treeRange)); } else { // These block kinds don't have a branch at the end. - assert((lastNode == nullptr) || (!lastNode->OperIsConditionalJump() && - !lastNode->OperIs(GT_SWITCH_TABLE, GT_SWITCH, GT_RETURN, GT_RETFILT))); + assert((lastNode == nullptr) || + (!lastNode->OperIsConditionalJump() && + !lastNode->OperIs(GT_SWITCH_TABLE, GT_SWITCH, GT_RETURN, GT_RETFILT, GT_SWIFT_ERROR_RET))); blockRange.InsertAtEnd(std::move(treeRange)); } } @@ -8933,7 +8998,7 @@ void LinearScan::handleOutgoingCriticalEdges(BasicBlock* block) GenTree* switchTable = LIR::AsRange(block).LastNode(); assert(switchTable != nullptr && switchTable->OperGet() == GT_SWITCH_TABLE); - consumedRegs = switchTable->gtRsvdRegs; + consumedRegs = compiler->codeGen->internalRegisters.GetAll(switchTable); GenTree* op1 = switchTable->gtGetOp1(); GenTree* op2 = switchTable->gtGetOp2(); noway_assert(op1 != nullptr && op2 != nullptr); @@ -10952,7 +11017,7 @@ void LinearScan::TupleStyleDump(LsraTupleDumpMode mode) printf("\n Kill: "); killPrinted = true; } - printf(getRegName(currentRefPosition->assignedReg())); + compiler->dumpRegMask(currentRefPosition->registerAssignment); printf(" "); break; case RefTypeFixedReg: @@ -10980,8 +11045,12 @@ void LinearScan::TupleStyleDump(LsraTupleDumpMode mode) printf("\n\n"); } -void LinearScan::dumpLsraAllocationEvent( - LsraDumpEvent event, Interval* interval, regNumber reg, BasicBlock* currentBlock, RegisterScore registerScore) +void LinearScan::dumpLsraAllocationEvent(LsraDumpEvent event, + Interval* interval, + regNumber reg, + BasicBlock* currentBlock, + RegisterScore registerScore, + regMaskTP regMask) { if (!(VERBOSE)) { @@ -11186,6 +11255,15 @@ void LinearScan::dumpLsraAllocationEvent( printf("UVRes %-4s ", getRegName(reg)); break; + case LSRA_EVENT_KILL_REGS: + dumpRefPositionShort(activeRefPosition, currentBlock); + printf("None "); + dspRegMask(regMask); + printf("\n"); + dumpRefPositionShort(activeRefPosition, currentBlock); + printf(" "); + break; + // We currently don't dump anything for these events. case LSRA_EVENT_DEFUSE_FIXED_DELAY_USE: case LSRA_EVENT_SPILL_EXTENDED_LIFETIME: @@ -11575,7 +11653,7 @@ void LinearScan::dumpRefPositionShort(RefPosition* refPosition, BasicBlock* curr } else { - assert(refPosition->refType == RefTypeKillGCRefs); + assert((refPosition->refType == RefTypeKill) || (refPosition->refType == RefTypeKillGCRefs)); // There's no interval or reg name associated with this. printf(regNameFormat, " "); printf(" %s ", getRefTypeShortName(refPosition->refType)); @@ -11741,8 +11819,6 @@ void LinearScan::verifyFreeRegisters(regMaskTP regsToFree) assert(nextIntervalRef[reg] == MaxLocation); assert(spillCost[reg] == 0); } - LsraLocation thisNextFixedRef = physRegRecord->getNextRefLocation(); - assert(nextFixedRef[reg] == thisNextFixedRef); #ifdef TARGET_ARM // If this is occupied by a double interval, skip the corresponding float reg. if ((assignedInterval != nullptr) && (assignedInterval->registerType == TYP_DOUBLE)) @@ -11948,10 +12024,10 @@ void LinearScan::verifyFinalAllocation() break; case RefTypeKill: - assert(regRecord != nullptr); - assert(regRecord->assignedInterval == nullptr); - dumpLsraAllocationEvent(LSRA_EVENT_KEPT_ALLOCATION, nullptr, regRecord->regNum, currentBlock); + dumpLsraAllocationEvent(LSRA_EVENT_KILL_REGS, nullptr, REG_NA, currentBlock, NONE, + currentRefPosition.registerAssignment); break; + case RefTypeFixedReg: assert(regRecord != nullptr); dumpLsraAllocationEvent(LSRA_EVENT_KEPT_ALLOCATION, nullptr, regRecord->regNum, currentBlock); @@ -13273,18 +13349,12 @@ regMaskTP LinearScan::RegisterSelection::select(Interval* current else if (refPosition->isFixedRegRef && nextRefPos != nullptr && RefTypeIsUse(nextRefPos->refType) && !nextRefPos->isFixedRegRef && genMaxOneBit(refPosition->registerAssignment)) { - regNumber defReg = refPosition->assignedReg(); - RegRecord* defRegRecord = linearScan->getRegisterRecord(defReg); - - RefPosition* currFixedRegRefPosition = defRegRecord->recentRefPosition; - assert(currFixedRegRefPosition != nullptr && - currFixedRegRefPosition->nodeLocation == refPosition->nodeLocation); + regNumber defReg = refPosition->assignedReg(); // If there is another fixed reference to this register before the use, change the candidates // on this RefPosition to include that of nextRefPos. - RefPosition* nextFixedRegRefPosition = defRegRecord->getNextRefPosition(); - if (nextFixedRegRefPosition != nullptr && - nextFixedRegRefPosition->nodeLocation <= nextRefPos->getRefEndLocation()) + unsigned nextFixedRegRefLocation = linearScan->getNextFixedRef(defReg, currentInterval->registerType); + if (nextFixedRegRefLocation <= nextRefPos->getRefEndLocation()) { candidates |= nextRefPos->registerAssignment; if (preferences == refPosition->registerAssignment) @@ -13584,7 +13654,7 @@ regMaskTP LinearScan::RegisterSelection::select(Interval* current &overallLimitCandidates); assert(limitConsecutiveResult != RBM_NONE); - unsigned startRegister = BitOperations::BitScanForward(limitConsecutiveResult); + unsigned startRegister = BitScanForward(limitConsecutiveResult); regMaskTP registersNeededMask = (1ULL << refPosition->regCount) - 1; candidates |= (registersNeededMask << startRegister); @@ -13739,18 +13809,12 @@ regMaskTP LinearScan::RegisterSelection::selectMinimal(Interval* else if (refPosition->isFixedRegRef && nextRefPos != nullptr && RefTypeIsUse(nextRefPos->refType) && !nextRefPos->isFixedRegRef && genMaxOneBit(refPosition->registerAssignment)) { - regNumber defReg = refPosition->assignedReg(); - RegRecord* defRegRecord = linearScan->getRegisterRecord(defReg); - - RefPosition* currFixedRegRefPosition = defRegRecord->recentRefPosition; - assert(currFixedRegRefPosition != nullptr && - currFixedRegRefPosition->nodeLocation == refPosition->nodeLocation); + regNumber defReg = refPosition->assignedReg(); // If there is another fixed reference to this register before the use, change the candidates // on this RefPosition to include that of nextRefPos. - RefPosition* nextFixedRegRefPosition = defRegRecord->getNextRefPosition(); - if (nextFixedRegRefPosition != nullptr && - nextFixedRegRefPosition->nodeLocation <= nextRefPos->getRefEndLocation()) + unsigned nextFixedRegRefLocation = linearScan->getNextFixedRef(defReg, currentInterval->registerType); + if (nextFixedRegRefLocation <= nextRefPos->getRefEndLocation()) { candidates |= nextRefPos->registerAssignment; } diff --git a/src/coreclr/jit/lsra.h b/src/coreclr/jit/lsra.h index 778341361929..154d70470fe4 100644 --- a/src/coreclr/jit/lsra.h +++ b/src/coreclr/jit/lsra.h @@ -644,6 +644,8 @@ class LinearScan : public LinearScanInterface template void buildIntervals(); + void buildInitialParamDef(const LclVarDsc* varDsc, regNumber paramReg); + // This is where the actual assignment is done for scenarios where // no local var enregistration is done. void allocateRegistersMinimal(); @@ -768,47 +770,6 @@ class LinearScan : public LinearScanInterface #endif }; - // When LSRA_LIMIT_SMALL_SET is specified, it is desirable to select a "mixed" set of caller- and callee-save - // registers, so as to get different coverage than limiting to callee or caller. - // At least for x86 and AMD64, and potentially other architecture that will support SIMD, - // we need a minimum of 5 fp regs in order to support the InitN intrinsic for Vector4. - // Hence the "SmallFPSet" has 5 elements. - -#if defined(TARGET_AMD64) -#ifdef UNIX_AMD64_ABI - // On System V the RDI and RSI are not callee saved. Use R12 ans R13 as callee saved registers. - static const regMaskTP LsraLimitSmallIntSet = - (RBM_EAX | RBM_ECX | RBM_EBX | RBM_ETW_FRAMED_EBP | RBM_R12 | RBM_R13); -#else // !UNIX_AMD64_ABI - // On Windows Amd64 use the RDI and RSI as callee saved registers. - static const regMaskTP LsraLimitSmallIntSet = - (RBM_EAX | RBM_ECX | RBM_EBX | RBM_ETW_FRAMED_EBP | RBM_ESI | RBM_EDI); -#endif // !UNIX_AMD64_ABI - static const regMaskTP LsraLimitSmallFPSet = (RBM_XMM0 | RBM_XMM1 | RBM_XMM2 | RBM_XMM6 | RBM_XMM7); - static const regMaskTP LsraLimitUpperSimdSet = - (RBM_XMM16 | RBM_XMM17 | RBM_XMM18 | RBM_XMM19 | RBM_XMM20 | RBM_XMM21 | RBM_XMM22 | RBM_XMM23 | RBM_XMM24 | - RBM_XMM25 | RBM_XMM26 | RBM_XMM27 | RBM_XMM28 | RBM_XMM29 | RBM_XMM30 | RBM_XMM31); -#elif defined(TARGET_ARM) - // On ARM, we may need two registers to set up the target register for a virtual call, so we need - // to have at least the maximum number of arg registers, plus 2. - static const regMaskTP LsraLimitSmallIntSet = (RBM_R0 | RBM_R1 | RBM_R2 | RBM_R3 | RBM_R4 | RBM_R5); - static const regMaskTP LsraLimitSmallFPSet = (RBM_F0 | RBM_F1 | RBM_F2 | RBM_F16 | RBM_F17); -#elif defined(TARGET_ARM64) - static const regMaskTP LsraLimitSmallIntSet = (RBM_R0 | RBM_R1 | RBM_R2 | RBM_R19 | RBM_R20); - static const regMaskTP LsraLimitSmallFPSet = (RBM_V0 | RBM_V1 | RBM_V2 | RBM_V8 | RBM_V9); -#elif defined(TARGET_X86) - static const regMaskTP LsraLimitSmallIntSet = (RBM_EAX | RBM_ECX | RBM_EDI); - static const regMaskTP LsraLimitSmallFPSet = (RBM_XMM0 | RBM_XMM1 | RBM_XMM2 | RBM_XMM6 | RBM_XMM7); -#elif defined(TARGET_LOONGARCH64) - static const regMaskTP LsraLimitSmallIntSet = (RBM_T1 | RBM_T3 | RBM_A0 | RBM_A1 | RBM_T0); - static const regMaskTP LsraLimitSmallFPSet = (RBM_F0 | RBM_F1 | RBM_F2 | RBM_F8 | RBM_F9); -#elif defined(TARGET_RISCV64) - static const regMaskTP LsraLimitSmallIntSet = (RBM_T1 | RBM_T3 | RBM_A0 | RBM_A1 | RBM_T0); - static const regMaskTP LsraLimitSmallFPSet = (RBM_F0 | RBM_F1 | RBM_F2 | RBM_F8 | RBM_F9); -#else -#error Unsupported or unset target architecture -#endif // target - LsraStressLimitRegs getStressLimitRegs() { return (LsraStressLimitRegs)(lsraStressMask & LSRA_LIMIT_MASK); @@ -963,6 +924,11 @@ class LinearScan : public LinearScanInterface return ((lsraStressMask & (LSRA_LIMIT_MASK | LSRA_SELECT_MASK)) != 0); } + bool stressInitialParamReg() + { + return compiler->compStressCompile(Compiler::STRESS_INITIAL_PARAM_REG, 25); + } + // Dump support void dumpDefList(); void lsraDumpIntervals(const char* msg); @@ -1018,6 +984,10 @@ class LinearScan : public LinearScanInterface { return false; } + bool stressInitialParamReg() + { + return false; + } #endif // !DEBUG public: @@ -1074,15 +1044,14 @@ class LinearScan : public LinearScanInterface // insert refpositions representing prolog zero-inits which will be added later void insertZeroInitRefPositions(); - // add physreg refpositions for a tree node, based on calling convention and instruction selection predictions - void addRefsForPhysRegMask(regMaskTP mask, LsraLocation currentLoc, RefType refType, bool isLastUse); + void addKillForRegs(regMaskTP mask, LsraLocation currentLoc); void resolveConflictingDefAndUse(Interval* interval, RefPosition* defRefPosition); void buildRefPositionsForNode(GenTree* tree, LsraLocation loc); #if FEATURE_PARTIAL_SIMD_CALLEE_SAVE - void buildUpperVectorSaveRefPositions(GenTree* tree, LsraLocation currentLoc, regMaskTP fpCalleeKillSet); + void buildUpperVectorSaveRefPositions(GenTree* tree, LsraLocation currentLoc DEBUG_ARG(regMaskTP fpCalleeKillSet)); void buildUpperVectorRestoreRefPosition( Interval* lclVarInterval, LsraLocation currentLoc, GenTree* node, bool isUse, unsigned multiRegIdx); #endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE @@ -1253,6 +1222,7 @@ class LinearScan : public LinearScanInterface void setIntervalAsSplit(Interval* interval); void spillInterval(Interval* interval, RefPosition* fromRefPosition DEBUGARG(RefPosition* toRefPosition)); + void processKills(RefPosition* killRefPosition); void spillGCRefs(RefPosition* killRefPosition); /***************************************************************************** @@ -1462,6 +1432,7 @@ class LinearScan : public LinearScanInterface return nextConsecutiveRefPositionMap; } FORCEINLINE RefPosition* getNextConsecutiveRefPosition(RefPosition* refPosition); + void getLowVectorOperandAndCandidates(HWIntrinsic intrin, size_t* operandNum, regMaskTP* candidates); #endif #ifdef DEBUG @@ -1572,6 +1543,7 @@ class LinearScan : public LinearScanInterface LSRA_EVENT_FREE_REGS, LSRA_EVENT_UPPER_VECTOR_SAVE, LSRA_EVENT_UPPER_VECTOR_RESTORE, + LSRA_EVENT_KILL_REGS, // Characteristics of the current RefPosition LSRA_EVENT_INCREMENT_RANGE_END, // ??? @@ -1597,9 +1569,12 @@ class LinearScan : public LinearScanInterface Interval* interval = nullptr, regNumber reg = REG_NA, BasicBlock* currentBlock = nullptr, - RegisterScore registerScore = NONE); + RegisterScore registerScore = NONE, + regMaskTP regMask = RBM_NONE); void validateIntervals(); + + void stressSetRandomParameterPreferences(); #endif // DEBUG #if TRACK_LSRA_STATS @@ -1722,6 +1697,11 @@ class LinearScan : public LinearScanInterface // Ordered list of RefPositions RefPositionList refPositions; + // Head of linked list of RefTypeKill ref positions + RefPosition* killHead; + // Tail slot of linked list of RefTypeKill ref positions + RefPosition** killTail; + // Per-block variable location mappings: an array indexed by block number that yields a // pointer to an array of regNumber, one per variable. VarToRegMap* inVarToRegMaps; @@ -1886,7 +1866,7 @@ class LinearScan : public LinearScanInterface regMaskTP fixedRegs; LsraLocation nextFixedRef[REG_COUNT]; - void updateNextFixedRef(RegRecord* regRecord, RefPosition* nextRefPosition); + void updateNextFixedRef(RegRecord* regRecord, RefPosition* nextRefPosition, RefPosition* nextKill); LsraLocation getNextFixedRef(regNumber regNum, var_types regType) { LsraLocation loc = nextFixedRef[regNum]; @@ -2019,19 +1999,27 @@ class LinearScan : public LinearScanInterface void getTgtPrefOperands(GenTree* tree, GenTree* op1, GenTree* op2, bool* prefOp1, bool* prefOp2); bool supportsSpecialPutArg(); - int BuildSimple(GenTree* tree); - int BuildOperandUses(GenTree* node, regMaskTP candidates = RBM_NONE); - void AddDelayFreeUses(RefPosition* refPosition, GenTree* rmwNode); - int BuildDelayFreeUses(GenTree* node, - GenTree* rmwNode = nullptr, - regMaskTP candidates = RBM_NONE, - RefPosition** useRefPosition = nullptr); - int BuildIndirUses(GenTreeIndir* indirTree, regMaskTP candidates = RBM_NONE); - int BuildAddrUses(GenTree* addr, regMaskTP candidates = RBM_NONE); - void HandleFloatVarArgs(GenTreeCall* call, GenTree* argNode, bool* callHasFloatRegArgs); + int BuildSimple(GenTree* tree); + int BuildOperandUses(GenTree* node, regMaskTP candidates = RBM_NONE); + void AddDelayFreeUses(RefPosition* refPosition, GenTree* rmwNode); + int BuildDelayFreeUses(GenTree* node, + GenTree* rmwNode = nullptr, + regMaskTP candidates = RBM_NONE, + RefPosition** useRefPosition = nullptr); + int BuildIndirUses(GenTreeIndir* indirTree, regMaskTP candidates = RBM_NONE); + int BuildAddrUses(GenTree* addr, regMaskTP candidates = RBM_NONE); + void HandleFloatVarArgs(GenTreeCall* call, GenTree* argNode, bool* callHasFloatRegArgs); + RefPosition* BuildDef(GenTree* tree, regMaskTP dstCandidates = RBM_NONE, int multiRegIdx = 0); void BuildDefs(GenTree* tree, int dstCount, regMaskTP dstCandidates = RBM_NONE); - void BuildDefsWithKills(GenTree* tree, int dstCount, regMaskTP dstCandidates, regMaskTP killMask); + void BuildCallDefs(GenTree* tree, int dstCount, regMaskTP dstCandidates); + void BuildKills(GenTree* tree, regMaskTP killMask); +#if defined(TARGET_ARMARCH) || defined(TARGET_RISCV64) + void BuildDefWithKills(GenTree* tree, regMaskTP dstCandidates, regMaskTP killMask); +#else + void BuildDefWithKills(GenTree* tree, int dstCount, regMaskTP dstCandidates, regMaskTP killMask); +#endif // TARGET_ARMARCH || TARGET_RISCV64 + void BuildCallDefsWithKills(GenTree* tree, int dstCount, regMaskTP dstCandidates, regMaskTP killMask); int BuildReturn(GenTree* tree); #ifdef TARGET_XARCH @@ -2044,6 +2032,7 @@ class LinearScan : public LinearScanInterface #endif int BuildPutArgReg(GenTreeUnOp* node); int BuildCall(GenTreeCall* call); + void MarkSwiftErrorBusyForCall(GenTreeCall* call); int BuildCmp(GenTree* tree); int BuildCmpOperands(GenTree* tree); int BuildBlockStore(GenTreeBlk* blkNode); @@ -2706,7 +2695,7 @@ class RefPosition bool IsPhysRegRef() { - return ((refType == RefTypeFixedReg) || (refType == RefTypeKill)); + return (refType == RefTypeFixedReg); } void setRegOptional(bool val) diff --git a/src/coreclr/jit/lsraarm.cpp b/src/coreclr/jit/lsraarm.cpp index 2192265984d6..e653514d3c14 100644 --- a/src/coreclr/jit/lsraarm.cpp +++ b/src/coreclr/jit/lsraarm.cpp @@ -373,7 +373,7 @@ int LinearScan::BuildNode(GenTree* tree) assert(dstCount == 0); BuildUse(tree->gtGetOp1()); killMask = compiler->compHelperCallKillSet(CORINFO_HELP_STOP_FOR_GC); - BuildDefsWithKills(tree, 0, RBM_NONE, killMask); + BuildKills(tree, killMask); break; case GT_MUL: @@ -422,7 +422,7 @@ int LinearScan::BuildNode(GenTree* tree) // This kills GC refs in callee save regs srcCount = 0; assert(dstCount == 0); - BuildDefsWithKills(tree, 0, RBM_NONE, RBM_NONE); + BuildKills(tree, RBM_NONE); break; case GT_LONG: @@ -469,7 +469,7 @@ int LinearScan::BuildNode(GenTree* tree) case GT_RETURN: srcCount = BuildReturn(tree); killMask = getKillSetForReturn(); - BuildDefsWithKills(tree, 0, RBM_NONE, killMask); + BuildKills(tree, killMask); break; case GT_RETFILT: diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index 1096d7f11701..31f4d114d544 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -180,7 +180,7 @@ regMaskTP LinearScan::filterConsecutiveCandidates(regMaskTP candidates, unsigned int registersNeeded, regMaskTP* allConsecutiveCandidates) { - if (BitOperations::PopCount(candidates) < registersNeeded) + if (PopCount(candidates) < registersNeeded) { // There is no way the register demanded can be satisfied for this RefPosition // based on the candidates from which it can allocate a register. @@ -205,7 +205,7 @@ regMaskTP LinearScan::filterConsecutiveCandidates(regMaskTP candidates, do { // From LSB, find the first available register (bit `1`) - regAvailableStartIndex = BitOperations::BitScanForward(static_cast(currAvailableRegs)); + regAvailableStartIndex = BitScanForward(currAvailableRegs); regMaskTP startMask = (1ULL << regAvailableStartIndex) - 1; // Mask all the bits that are processed from LSB thru regAvailableStart until the last `1`. @@ -223,7 +223,7 @@ regMaskTP LinearScan::filterConsecutiveCandidates(regMaskTP candidates, } else { - regAvailableEndIndex = BitOperations::BitScanForward(static_cast(maskProcessed)); + regAvailableEndIndex = BitScanForward(maskProcessed); } regMaskTP endMask = (1ULL << regAvailableEndIndex) - 1; @@ -335,7 +335,7 @@ regMaskTP LinearScan::filterConsecutiveCandidatesForSpill(regMaskTP consecutiveC do { // From LSB, find the first available register (bit `1`) - regAvailableStartIndex = BitOperations::BitScanForward(static_cast(unprocessedRegs)); + regAvailableStartIndex = BitScanForward(unprocessedRegs); // For the current range, find how many registers are free vs. busy regMaskTP maskForCurRange = RBM_NONE; @@ -370,7 +370,7 @@ regMaskTP LinearScan::filterConsecutiveCandidatesForSpill(regMaskTP consecutiveC // In the given range, there are some free registers available. Calculate how many registers // will need spilling if this range is picked. - int curSpillRegs = registersNeeded - BitOperations::PopCount(maskForCurRange); + int curSpillRegs = registersNeeded - PopCount(maskForCurRange); if (curSpillRegs < maxSpillRegs) { consecutiveResultForBusy = 1ULL << regAvailableStartIndex; @@ -582,7 +582,7 @@ int LinearScan::BuildNode(GenTree* tree) { assert(!tree->isContained()); int srcCount; - int dstCount = 0; + int dstCount; regMaskTP killMask = RBM_NONE; bool isLocalDefUse = false; @@ -666,14 +666,14 @@ int LinearScan::BuildNode(GenTree* tree) srcCount = 0; assert(dstCount == 0); killMask = getKillSetForProfilerHook(); - BuildDefsWithKills(tree, 0, RBM_NONE, killMask); + BuildKills(tree, killMask); break; case GT_START_PREEMPTGC: // This kills GC refs in callee save regs srcCount = 0; assert(dstCount == 0); - BuildDefsWithKills(tree, 0, RBM_NONE, RBM_NONE); + BuildKills(tree, RBM_NONE); break; case GT_CNS_DBL: @@ -738,8 +738,18 @@ int LinearScan::BuildNode(GenTree* tree) case GT_RETURN: srcCount = BuildReturn(tree); killMask = getKillSetForReturn(); - BuildDefsWithKills(tree, 0, RBM_NONE, killMask); + BuildKills(tree, killMask); + break; + +#ifdef SWIFT_SUPPORT + case GT_SWIFT_ERROR_RET: + BuildUse(tree->gtGetOp1(), RBM_SWIFT_ERROR); + // Plus one for error register + srcCount = BuildReturn(tree) + 1; + killMask = getKillSetForReturn(); + BuildKills(tree, killMask); break; +#endif // SWIFT_SUPPORT case GT_RETFILT: assert(dstCount == 0); @@ -829,7 +839,7 @@ int LinearScan::BuildNode(GenTree* tree) srcCount = 1; assert(dstCount == 0); killMask = compiler->compHelperCallKillSet(CORINFO_HELP_STOP_FOR_GC); - BuildDefsWithKills(tree, 0, RBM_NONE, killMask); + BuildKills(tree, killMask); break; case GT_MOD: @@ -1373,13 +1383,13 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou assert(varTypeIsSIMD(indexedElementOpType)); const unsigned int indexedElementSimdSize = genTypeSize(indexedElementOpType); - HWIntrinsicInfo::lookupImmBounds(intrin.id, indexedElementSimdSize, intrin.baseType, &immLowerBound, + HWIntrinsicInfo::lookupImmBounds(intrin.id, indexedElementSimdSize, intrin.baseType, 1, &immLowerBound, &immUpperBound); } else { - HWIntrinsicInfo::lookupImmBounds(intrin.id, intrinsicTree->GetSimdSize(), intrin.baseType, &immLowerBound, - &immUpperBound); + HWIntrinsicInfo::lookupImmBounds(intrin.id, intrinsicTree->GetSimdSize(), intrin.baseType, 1, + &immLowerBound, &immUpperBound); } if ((immLowerBound != 0) || (immUpperBound != 1)) @@ -1454,6 +1464,10 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou case NI_Sve_CreateTrueMaskUInt16: case NI_Sve_CreateTrueMaskUInt32: case NI_Sve_CreateTrueMaskUInt64: + case NI_Sve_Count16BitElements: + case NI_Sve_Count32BitElements: + case NI_Sve_Count64BitElements: + case NI_Sve_Count8BitElements: needBranchTargetReg = !intrin.op1->isContainedIntOrIImmed(); break; @@ -1612,7 +1626,6 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou } } } - else if (HWIntrinsicInfo::NeedsConsecutiveRegisters(intrin.id)) { switch (intrin.id) @@ -1744,12 +1757,84 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou *pDstCount = dstCount; break; } + default: noway_assert(!"Not a supported as multiple consecutive register intrinsic"); } return srcCount; } + else if ((intrin.id == NI_Sve_ConditionalSelect) && (intrin.op2->IsEmbMaskOp()) && + (intrin.op2->isRMWHWIntrinsic(compiler))) + { + assert(intrin.op3 != nullptr); + + // For ConditionalSelect, if there is an embedded operation, and the operation has RMW semantics + // then record delay-free for operands as well as the "merge" value + GenTreeHWIntrinsic* embOp2Node = intrin.op2->AsHWIntrinsic(); + size_t numArgs = embOp2Node->GetOperandCount(); + const HWIntrinsic intrinEmb(embOp2Node); + numArgs = embOp2Node->GetOperandCount(); + + if (HWIntrinsicInfo::IsFmaIntrinsic(intrinEmb.id)) + { + assert(embOp2Node->isRMWHWIntrinsic(compiler)); + assert(numArgs == 3); + + LIR::Use use; + GenTree* user = nullptr; + + if (LIR::AsRange(blockSequence[curBBSeqNum]).TryGetUse(embOp2Node, &use)) + { + user = use.User(); + } + unsigned resultOpNum = + embOp2Node->GetResultOpNumForRmwIntrinsic(user, intrinEmb.op1, intrinEmb.op2, intrinEmb.op3); + + GenTree* emitOp1 = intrinEmb.op1; + GenTree* emitOp2 = intrinEmb.op2; + GenTree* emitOp3 = intrinEmb.op3; + + if (resultOpNum == 2) + { + // op2 = op1 + (op2 * op3) + std::swap(emitOp1, emitOp3); + std::swap(emitOp1, emitOp2); + // op1 = (op1 * op2) + op3 + } + else if (resultOpNum == 3) + { + // op3 = op1 + (op2 * op3) + std::swap(emitOp1, emitOp3); + // op1 = (op1 * op2) + op3 + } + else + { + // op1 = op1 + (op2 * op3) + // Nothing needs to be done + } + + tgtPrefUse = BuildUse(emitOp1); + srcCount += 1; + srcCount += BuildDelayFreeUses(emitOp2, emitOp1); + srcCount += BuildDelayFreeUses(emitOp3, emitOp1); + srcCount += BuildDelayFreeUses(intrin.op3, emitOp1); + } + else + { + assert((numArgs == 1) || (numArgs == 2) || (numArgs == 3)); + tgtPrefUse = BuildUse(embOp2Node->Op(1)); + srcCount += 1; + + for (size_t argNum = 2; argNum <= numArgs; argNum++) + { + srcCount += BuildDelayFreeUses(embOp2Node->Op(argNum), embOp2Node->Op(1)); + } + + srcCount += BuildDelayFreeUses(intrin.op3, embOp2Node->Op(1)); + } + } + else if (intrin.op2 != nullptr) { // RMW intrinsic operands doesn't have to be delayFree when they can be assigned the same register as op1Reg @@ -1757,7 +1842,9 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou assert(intrin.op1 != nullptr); - bool forceOp2DelayFree = false; + bool forceOp2DelayFree = false; + regMaskTP lowVectorCandidates = RBM_NONE; + size_t lowVectorOperandNum = 0; if ((intrin.id == NI_Vector64_GetElement) || (intrin.id == NI_Vector128_GetElement)) { if (!intrin.op2->IsCnsIntOrI() && (!intrin.op1->isContained() || intrin.op1->OperIsLocal())) @@ -1779,22 +1866,58 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou compiler->getSIMDInitTempVarNum(requiredSimdTempType); } } + else if (HWIntrinsicInfo::IsLowVectorOperation(intrin.id)) + { + getLowVectorOperandAndCandidates(intrin, &lowVectorOperandNum, &lowVectorCandidates); + } - if (forceOp2DelayFree) + if ((intrin.id == NI_Sve_ConditionalSelect) && (intrin.op2->IsEmbMaskOp()) && + (intrin.op2->isRMWHWIntrinsic(compiler))) { - srcCount += BuildDelayFreeUses(intrin.op2); + // For ConditionalSelect, if there is an embedded operation, and the operation has RMW semantics + // then record delay-free for them. + GenTreeHWIntrinsic* intrinEmbOp2 = intrin.op2->AsHWIntrinsic(); + size_t numArgs = intrinEmbOp2->GetOperandCount(); + assert((numArgs == 1) || (numArgs == 2)); + const HWIntrinsic intrinEmb(intrinEmbOp2); + if (HWIntrinsicInfo::IsLowVectorOperation(intrinEmb.id)) + { + getLowVectorOperandAndCandidates(intrinEmb, &lowVectorOperandNum, &lowVectorCandidates); + } + + tgtPrefUse = BuildUse(intrinEmbOp2->Op(1)); + srcCount += 1; + + for (size_t argNum = 2; argNum <= numArgs; argNum++) + { + srcCount += BuildDelayFreeUses(intrinEmbOp2->Op(argNum), intrinEmbOp2->Op(1), + (argNum == lowVectorOperandNum) ? lowVectorCandidates : RBM_NONE); + } } else { - srcCount += isRMW ? BuildDelayFreeUses(intrin.op2, intrin.op1) : BuildOperandUses(intrin.op2); + regMaskTP candidates = lowVectorOperandNum == 2 ? lowVectorCandidates : RBM_NONE; + if (forceOp2DelayFree) + { + srcCount += BuildDelayFreeUses(intrin.op2, nullptr, candidates); + } + else + { + srcCount += isRMW ? BuildDelayFreeUses(intrin.op2, intrin.op1, candidates) + : BuildOperandUses(intrin.op2, candidates); + } } if (intrin.op3 != nullptr) { - srcCount += isRMW ? BuildDelayFreeUses(intrin.op3, intrin.op1) : BuildOperandUses(intrin.op3); + regMaskTP candidates = lowVectorOperandNum == 3 ? lowVectorCandidates : RBM_NONE; + + srcCount += isRMW ? BuildDelayFreeUses(intrin.op3, intrin.op1, candidates) + : BuildOperandUses(intrin.op3, candidates); if (intrin.op4 != nullptr) { + assert(lowVectorOperandNum != 4); srcCount += isRMW ? BuildDelayFreeUses(intrin.op4, intrin.op1) : BuildOperandUses(intrin.op4); } } @@ -1804,11 +1927,11 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou if ((dstCount == 1) || (dstCount == 2)) { - BuildDef(intrinsicTree, dstCandidates); + BuildDef(intrinsicTree); if (dstCount == 2) { - BuildDef(intrinsicTree, dstCandidates, 1); + BuildDef(intrinsicTree, RBM_NONE, 1); } } else @@ -2085,8 +2208,48 @@ bool RefPosition::isLiveAtConsecutiveRegistersLoc(LsraLocation consecutiveRegist } return false; } -#endif +#endif // DEBUG -#endif +//------------------------------------------------------------------------ +// getLowVectorOperandAndCandidates: Instructions for certain intrinsics operate on low vector registers +// depending on the size of the element. The method returns the candidates based on that size and +// the operand number of the intrinsics that has the restriction. +// +// Arguments: +// intrin - Intrinsics +// operandNum (out) - The operand number having the low vector register restriction +// candidates (out) - The restricted low vector registers +// +void LinearScan::getLowVectorOperandAndCandidates(HWIntrinsic intrin, size_t* operandNum, regMaskTP* candidates) +{ + assert(HWIntrinsicInfo::IsLowVectorOperation(intrin.id)); + unsigned baseElementSize = genTypeSize(intrin.baseType); + + if (baseElementSize == 8) + { + *candidates = RBM_SVE_INDEXED_D_ELEMENT_ALLOWED_REGS; + } + else + { + assert(baseElementSize == 4); + *candidates = RBM_SVE_INDEXED_S_ELEMENT_ALLOWED_REGS; + } + + switch (intrin.id) + { + case NI_Sve_DotProductBySelectedScalar: + case NI_Sve_FusedMultiplyAddBySelectedScalar: + case NI_Sve_FusedMultiplySubtractBySelectedScalar: + *operandNum = 3; + break; + case NI_Sve_MultiplyBySelectedScalar: + *operandNum = 2; + break; + default: + unreached(); + } +} + +#endif // FEATURE_HW_INTRINSICS #endif // TARGET_ARM64 diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp index c2b8b7440658..e70de49a8e79 100644 --- a/src/coreclr/jit/lsraarmarch.cpp +++ b/src/coreclr/jit/lsraarmarch.cpp @@ -127,9 +127,9 @@ int LinearScan::BuildIndir(GenTreeIndir* indirTree) // int LinearScan::BuildCall(GenTreeCall* call) { - bool hasMultiRegRetVal = false; - const ReturnTypeDesc* retTypeDesc = nullptr; - regMaskTP dstCandidates = RBM_NONE; + bool hasMultiRegRetVal = false; + const ReturnTypeDesc* retTypeDesc = nullptr; + regMaskTP singleDstCandidates = RBM_NONE; int srcCount = 0; int dstCount = 0; @@ -181,16 +181,24 @@ int LinearScan::BuildCall(GenTreeCall* call) } else if (call->IsR2ROrVirtualStubRelativeIndir()) { - // For R2R and VSD we have stub address in REG_R2R_INDIRECT_PARAM - // and will load call address into the temp register from this register. - regMaskTP candidates = RBM_NONE; if (call->IsFastTailCall()) { - candidates = allRegs(TYP_INT) & RBM_INT_CALLEE_TRASH; + // For R2R and VSD we have stub address in REG_R2R_INDIRECT_PARAM + // and will load call address into the temp register from this register. + regMaskTP candidates = allRegs(TYP_INT) & RBM_INT_CALLEE_TRASH; assert(candidates != RBM_NONE); + buildInternalIntRegisterDefForNode(call, candidates); + } + else + { + // For arm64 we can use REG_INDIRECT_CALL_TARGET_REG (IP0) for non-tailcalls + // so we skip the internal register as a TP optimization. We could do the same for + // arm32, but loading into IP cannot be encoded in 2 bytes, so + // another register is usually better. +#ifdef TARGET_ARM + buildInternalIntRegisterDefForNode(call); +#endif } - - buildInternalIntRegisterDefForNode(call, candidates); } #ifdef TARGET_ARM else @@ -219,26 +227,24 @@ int LinearScan::BuildCall(GenTreeCall* call) { // The ARM CORINFO_HELP_INIT_PINVOKE_FRAME helper uses a custom calling convention that returns with // TCB in REG_PINVOKE_TCB. fgMorphCall() sets the correct argument registers. - dstCandidates = RBM_PINVOKE_TCB; + singleDstCandidates = RBM_PINVOKE_TCB; } else #endif // TARGET_ARM - if (hasMultiRegRetVal) - { - assert(retTypeDesc != nullptr); - dstCandidates = retTypeDesc->GetABIReturnRegs(call->GetUnmanagedCallConv()); - } - else if (varTypeUsesFloatArgReg(registerType)) + if (!hasMultiRegRetVal) { - dstCandidates = RBM_FLOATRET; - } - else if (registerType == TYP_LONG) - { - dstCandidates = RBM_LNGRET; - } - else - { - dstCandidates = RBM_INTRET; + if (varTypeUsesFloatArgReg(registerType)) + { + singleDstCandidates = RBM_FLOATRET; + } + else if (registerType == TYP_LONG) + { + singleDstCandidates = RBM_LNGRET; + } + else + { + singleDstCandidates = RBM_INTRET; + } } // First, count reg args @@ -391,28 +397,30 @@ int LinearScan::BuildCall(GenTreeCall* call) // Now generate defs and kills. regMaskTP killMask = getKillSetForCall(call); - BuildDefsWithKills(call, dstCount, dstCandidates, killMask); + if (dstCount > 0) + { + if (hasMultiRegRetVal) + { + assert(retTypeDesc != nullptr); + regMaskTP multiDstCandidates = retTypeDesc->GetABIReturnRegs(call->GetUnmanagedCallConv()); + assert(genCountBits(multiDstCandidates) > 0); + BuildCallDefsWithKills(call, dstCount, multiDstCandidates, killMask); + } + else + { + assert(dstCount == 1); + BuildDefWithKills(call, singleDstCandidates, killMask); + } + } + else + { + BuildKills(call, killMask); + } #ifdef SWIFT_SUPPORT if (call->HasSwiftErrorHandling()) { - // Tree is a Swift call with error handling; error register should have been killed - assert((killMask & RBM_SWIFT_ERROR) != 0); - - // After a Swift call that might throw returns, we expect the error register to be consumed - // by a GT_SWIFT_ERROR node. However, we want to ensure the error register won't be trashed - // before GT_SWIFT_ERROR can consume it. - // (For example, the PInvoke epilog comes before the error register store.) - // To do so, delay the freeing of the error register until the next node. - // This only works if the next node after the call is the GT_SWIFT_ERROR node. - // (InsertPInvokeCallEpilog should have moved the GT_SWIFT_ERROR node during lowering.) - assert(call->gtNext != nullptr); - assert(call->gtNext->OperIs(GT_SWIFT_ERROR)); - - // We could use RefTypeKill, but RefTypeFixedReg is used less commonly, so the check for delayRegFree - // during register allocation should be cheaper in terms of TP. - RefPosition* pos = newRefPosition(REG_SWIFT_ERROR, currentLoc, RefTypeFixedReg, call, RBM_SWIFT_ERROR); - setDelayFree(pos); + MarkSwiftErrorBusyForCall(call); } #endif // SWIFT_SUPPORT @@ -844,7 +852,7 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) buildInternalRegisterUses(); regMaskTP killMask = getKillSetForBlockStore(blkNode); - BuildDefsWithKills(blkNode, 0, RBM_NONE, killMask); + BuildKills(blkNode, killMask); return useCount; } diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 62532de8d66f..9230f20fd12e 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -498,7 +498,7 @@ void LinearScan::associateRefPosWithInterval(RefPosition* rp) } else { - assert((rp->refType == RefTypeBB) || (rp->refType == RefTypeKillGCRefs)); + assert((rp->refType == RefTypeBB) || (rp->refType == RefTypeKillGCRefs) || (rp->refType == RefTypeKill)); } } @@ -570,7 +570,7 @@ RefPosition* LinearScan::newRefPosition(Interval* theInterval, } else { - assert(theRefType == RefTypeBB || theRefType == RefTypeKillGCRefs); + assert(theRefType == RefTypeBB || theRefType == RefTypeKillGCRefs || theRefType == RefTypeKill); } #ifdef DEBUG if (theInterval != nullptr && regType(theInterval->registerType) == FloatRegisterType) @@ -689,18 +689,14 @@ bool LinearScan::isContainableMemoryOp(GenTree* node) } //------------------------------------------------------------------------ -// addRefsForPhysRegMask: Adds RefPositions of the given type for all the registers in 'mask'. +// addKillForRegs: Adds a RefTypeKill ref position for the given registers. // // Arguments: // mask - the mask (set) of registers. // currentLoc - the location at which they should be added -// refType - the type of refposition -// isLastUse - true IFF this is a last use of the register // -void LinearScan::addRefsForPhysRegMask(regMaskTP mask, LsraLocation currentLoc, RefType refType, bool isLastUse) +void LinearScan::addKillForRegs(regMaskTP mask, LsraLocation currentLoc) { - assert(refType == RefTypeKill); - // The mask identifies a set of registers that will be used during // codegen. Mark these as modified here, so when we do final frame // layout, we'll know about all these registers. This is especially @@ -712,19 +708,10 @@ void LinearScan::addRefsForPhysRegMask(regMaskTP mask, LsraLocation currentLoc, // modified until codegen, which is too late. compiler->codeGen->regSet.rsSetRegsModified(mask DEBUGARG(true)); - for (regMaskTP candidates = mask; candidates != RBM_NONE;) - { - regNumber reg = genFirstRegNumFromMaskAndToggle(candidates); - // This assumes that these are all "special" RefTypes that - // don't need to be recorded on the tree (hence treeNode is nullptr) - RefPosition* pos = newRefPosition(reg, currentLoc, refType, nullptr, - genRegMask(reg)); // This MUST occupy the physical register (obviously) + RefPosition* pos = newRefPosition((Interval*)nullptr, currentLoc, RefTypeKill, nullptr, mask); - if (isLastUse) - { - pos->lastUse = true; - } - } + *killTail = pos; + killTail = &pos->nextRefPosition; } //------------------------------------------------------------------------ @@ -1076,6 +1063,7 @@ regMaskTP LinearScan::getKillSetForNode(GenTree* tree) // profiler callback would trash these registers. See vm\amd64\asmhelpers.asm for // more details. case GT_RETURN: + case GT_SWIFT_ERROR_RET: killMask = getKillSetForReturn(); break; @@ -1127,7 +1115,7 @@ bool LinearScan::buildKillPositionsForNode(GenTree* tree, LsraLocation currentLo if (killMask != RBM_NONE) { - addRefsForPhysRegMask(killMask, currentLoc, RefTypeKill, true); + addKillForRegs(killMask, currentLoc); // TODO-CQ: It appears to be valuable for both fp and int registers to avoid killing the callee // save regs on infrequently executed paths. However, it results in a large number of asmDiffs, @@ -1472,7 +1460,8 @@ Interval* LinearScan::getUpperVectorInterval(unsigned varIndex) // But we will use as a proxy any node that kills floating point registers. // (Note that some calls are masquerading as other nodes at this point so we can't just check for calls.) // -void LinearScan::buildUpperVectorSaveRefPositions(GenTree* tree, LsraLocation currentLoc, regMaskTP fpCalleeKillSet) +void LinearScan::buildUpperVectorSaveRefPositions(GenTree* tree, + LsraLocation currentLoc DEBUG_ARG(regMaskTP fpCalleeKillSet)) { if ((tree != nullptr) && tree->IsCall()) { @@ -1730,10 +1719,6 @@ int LinearScan::ComputeAvailableSrcCount(GenTree* node) // void LinearScan::buildRefPositionsForNode(GenTree* tree, LsraLocation currentLoc) { - // The set of internal temporary registers used by this node are stored in the - // gtRsvdRegs register mask. Clear it out. - tree->gtRsvdRegs = RBM_NONE; - #ifdef DEBUG if (VERBOSE) { @@ -2303,7 +2288,7 @@ void LinearScan::buildIntervals() continue; } - const ABIPassingInformation& abiInfo = compiler->lvaParameterPassingInfo[lclNum]; + const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(lclNum); for (unsigned i = 0; i < abiInfo.NumSegments; i++) { const ABIPassingSegment& seg = abiInfo.Segments[i]; @@ -2344,20 +2329,7 @@ void LinearScan::buildIntervals() if (isCandidateVar(argDsc)) { - Interval* interval = getIntervalForLocalVar(varIndex); - const var_types regType = argDsc->GetRegisterType(); - regMaskTP mask = allRegs(regType); - if (argDsc->lvIsRegArg) - { - // Set this interval as currently assigned to that register - regNumber inArgReg = argDsc->GetArgReg(); - assert(inArgReg < REG_COUNT); - mask = genRegMask(inArgReg); - assignPhysReg(inArgReg, interval); - INDEBUG(registersToDump |= getRegMask(inArgReg, interval->registerType)); - } - RefPosition* pos = newRefPosition(interval, MinLocation, RefTypeParamDef, nullptr, mask); - pos->setRegOptional(true); + buildInitialParamDef(argDsc, argDsc->lvIsRegArg ? argDsc->GetArgReg() : REG_NA); } else if (argDsc->lvPromoted) { @@ -2368,10 +2340,7 @@ void LinearScan::buildIntervals() if (fieldVarDsc->lvLRACandidate) { assert(fieldVarDsc->lvTracked); - Interval* interval = getIntervalForLocalVar(fieldVarDsc->lvVarIndex); - RefPosition* pos = - newRefPosition(interval, MinLocation, RefTypeParamDef, nullptr, allRegs(TypeGet(fieldVarDsc))); - pos->setRegOptional(true); + buildInitialParamDef(fieldVarDsc, REG_NA); } } } @@ -2418,7 +2387,20 @@ void LinearScan::buildIntervals() if (compiler->info.compPublishStubParam) { intRegState->rsCalleeRegArgMaskLiveIn |= RBM_SECRET_STUB_PARAM; + + LclVarDsc* stubParamDsc = compiler->lvaGetDesc(compiler->lvaStubArgumentVar); + if (isCandidateVar(stubParamDsc)) + { + buildInitialParamDef(stubParamDsc, REG_SECRET_STUB_PARAM); + } + } + +#ifdef DEBUG + if (stressInitialParamReg()) + { + stressSetRandomParameterPreferences(); } +#endif numPlacedArgLocals = 0; placedArgRegs = RBM_NONE; @@ -2543,7 +2525,7 @@ void LinearScan::buildIntervals() if ((block == compiler->fgFirstBB) && compiler->lvaHasAnySwiftStackParamToReassemble()) { assert(compiler->fgFirstBBisScratch()); - addRefsForPhysRegMask(genRegMask(REG_SCRATCH), currentLoc + 1, RefTypeKill, true); + addKillForRegs(genRegMask(REG_SCRATCH), currentLoc + 1); currentLoc += 2; } @@ -2561,7 +2543,7 @@ void LinearScan::buildIntervals() // Poisoning uses REG_SCRATCH for small vars and memset helper for big vars. killed = genRegMask(REG_SCRATCH) | compiler->compHelperCallKillSet(CORINFO_HELP_NATIVE_MEMSET); #endif - addRefsForPhysRegMask(killed, currentLoc + 1, RefTypeKill, true); + addKillForRegs(killed, currentLoc + 1); currentLoc += 2; } @@ -2868,7 +2850,91 @@ void LinearScan::buildIntervals() #endif // DEBUG } +//------------------------------------------------------------------------ +// buildInitialParamDef: Build the initial definition for a parameter. +// +// Parameters: +// varDsc - LclVarDsc* for parameter +// paramReg - Register that parameter is in +// +void LinearScan::buildInitialParamDef(const LclVarDsc* varDsc, regNumber paramReg) +{ + assert(isCandidateVar(varDsc)); + + Interval* interval = getIntervalForLocalVar(varDsc->lvVarIndex); + const var_types regType = varDsc->GetRegisterType(); + regMaskTP mask = allRegs(regType); + if ((paramReg != REG_NA) && !stressInitialParamReg()) + { + // Set this interval as currently assigned to that register + assert(paramReg < REG_COUNT); + mask = genRegMask(paramReg); + assignPhysReg(paramReg, interval); + INDEBUG(registersToDump |= getRegMask(paramReg, interval->registerType)); + } + RefPosition* pos = newRefPosition(interval, MinLocation, RefTypeParamDef, nullptr, mask); + pos->setRegOptional(true); +} + #ifdef DEBUG + +//------------------------------------------------------------------------ +// stressSetRandomParameterPreferences: Randomize preferences of parameter +// intervals. +// +// Remarks: +// The intention of this stress is to make the parameter homing logic in +// genHomeRegisterParams see harder cases. +// +void LinearScan::stressSetRandomParameterPreferences() +{ + CLRRandom rng; + rng.Init(compiler->info.compMethodHash()); + regMaskTP intRegs = compiler->codeGen->intRegState.rsCalleeRegArgMaskLiveIn; + regMaskTP floatRegs = compiler->codeGen->floatRegState.rsCalleeRegArgMaskLiveIn; + + for (unsigned int varIndex = 0; varIndex < compiler->lvaTrackedCount; varIndex++) + { + LclVarDsc* argDsc = compiler->lvaGetDescByTrackedIndex(varIndex); + + if (!argDsc->lvIsParam || !isCandidateVar(argDsc)) + { + continue; + } + + Interval* interval = getIntervalForLocalVar(varIndex); + + regMaskTP* regs; + if (interval->registerType == FloatRegisterType) + { + regs = &floatRegs; + } + else + { + regs = &intRegs; + } + + // Select a random register from all possible parameter registers + // (of the right type). Preference this parameter to that register. + unsigned numBits = PopCount(*regs); + if (numBits == 0) + { + continue; + } + + int bitIndex = rng.Next((int)numBits); + regNumber prefReg = REG_NA; + regMaskTP regsLeft = *regs; + for (int i = 0; i <= bitIndex; i++) + { + prefReg = genFirstRegNumFromMaskAndToggle(regsLeft); + } + + *regs &= ~genRegMask(prefReg); + interval->mergeRegisterPreferences(genRegMask(prefReg)); + } +} + //------------------------------------------------------------------------ // validateIntervals: A DEBUG-only method that checks that: // - the lclVar RefPositions do not reflect uses of undefined values @@ -2973,7 +3039,7 @@ void setTgtPref(Interval* interval, RefPosition* tgtPrefUse) #endif // !TARGET_ARM //------------------------------------------------------------------------ -// BuildDef: Build a RefTypeDef RefPosition for the given node +// BuildDef: Build one RefTypeDef RefPosition for the given node at given index // // Arguments: // tree - The node that defines a register @@ -3066,7 +3132,7 @@ RefPosition* LinearScan::BuildDef(GenTree* tree, regMaskTP dstCandidates, int mu } //------------------------------------------------------------------------ -// BuildDef: Build one or more RefTypeDef RefPositions for the given node +// BuildDef: Build one or more RefTypeDef RefPositions for the given call node // // Arguments: // tree - The node that defines a register @@ -3076,61 +3142,76 @@ RefPosition* LinearScan::BuildDef(GenTree* tree, regMaskTP dstCandidates, int mu // Notes: // Adds the RefInfo for the definitions to the defList. // -void LinearScan::BuildDefs(GenTree* tree, int dstCount, regMaskTP dstCandidates) +void LinearScan::BuildCallDefs(GenTree* tree, int dstCount, regMaskTP dstCandidates) { - bool fixedReg = false; - if ((dstCount > 1) && (dstCandidates != RBM_NONE) && ((int)genCountBits(dstCandidates) == dstCount)) - { - fixedReg = true; - } - const ReturnTypeDesc* retTypeDesc = nullptr; - if (tree->IsMultiRegCall()) + assert(dstCount > 0); + assert((int)genCountBits(dstCandidates) == dstCount); + assert(tree->IsMultiRegCall()); + + const ReturnTypeDesc* retTypeDesc = tree->AsCall()->GetReturnTypeDesc(); + assert(retTypeDesc != nullptr); + if (retTypeDesc == nullptr) { - retTypeDesc = tree->AsCall()->GetReturnTypeDesc(); + return; } + for (int i = 0; i < dstCount; i++) { - regMaskTP thisDstCandidates; - if (fixedReg) - { - // In case of multi-reg call node, we have to query the i'th position return register. - // For all other cases of multi-reg definitions, the registers must be in sequential order. - if (retTypeDesc != nullptr) - { - thisDstCandidates = genRegMask( - tree->AsCall()->GetReturnTypeDesc()->GetABIReturnReg(i, tree->AsCall()->GetUnmanagedCallConv())); - assert((dstCandidates & thisDstCandidates) != RBM_NONE); - } - else - { - thisDstCandidates = genFindLowestBit(dstCandidates); - } - dstCandidates &= ~thisDstCandidates; - } - else - { - thisDstCandidates = dstCandidates; - } + // In case of multi-reg call node, we have to query the i'th position return register. + // For all other cases of multi-reg definitions, the registers must be in sequential order. + regMaskTP thisDstCandidates = + genRegMask(retTypeDesc->GetABIReturnReg(i, tree->AsCall()->GetUnmanagedCallConv())); + + assert((dstCandidates & thisDstCandidates) != RBM_NONE); + dstCandidates &= ~thisDstCandidates; + BuildDef(tree, thisDstCandidates, i); } } //------------------------------------------------------------------------ -// BuildDef: Build one or more RefTypeDef RefPositions for the given node, -// as well as kills as specified by the given mask. +// BuildDef: Build one or more RefTypeDef RefPositions for the given node // // Arguments: // tree - The node that defines a register // dstCount - The number of registers defined by the node -// dstCandidates - The candidate registers for the definition -// killMask - The mask of registers killed by this node +// dstCandidates - the candidate registers for the definition // // Notes: // Adds the RefInfo for the definitions to the defList. -// The def and kill functionality is folded into a single method so that the -// save and restores of upper vector registers can be bracketed around the def. +// Also, the `dstCandidates` is assumed to be of "onlyOne" type. If there are +// both gpr and float registers, use `BuildDefs` that takes `AllRegsMask` +// +void LinearScan::BuildDefs(GenTree* tree, int dstCount, regMaskTP dstCandidates) +{ + assert(dstCount > 0); + + if ((dstCandidates == RBM_NONE) || ((int)genCountBits(dstCandidates) != dstCount)) + { + // This is not fixedReg case, so just create definitions based on dstCandidates + for (int i = 0; i < dstCount; i++) + { + BuildDef(tree, dstCandidates, i); + } + return; + } + + for (int i = 0; i < dstCount; i++) + { + regMaskTP thisDstCandidates = genFindLowestBit(dstCandidates); + BuildDef(tree, thisDstCandidates, i); + dstCandidates &= ~thisDstCandidates; + } +} + +//------------------------------------------------------------------------ +// BuildDef: Build Kills RefPositions as specified by the given mask. // -void LinearScan::BuildDefsWithKills(GenTree* tree, int dstCount, regMaskTP dstCandidates, regMaskTP killMask) +// Arguments: +// tree - The node that defines a register +// killMask - The mask of registers killed by this node +// +void LinearScan::BuildKills(GenTree* tree, regMaskTP killMask) { assert(killMask == getKillSetForNode(tree)); @@ -3153,13 +3234,101 @@ void LinearScan::BuildDefsWithKills(GenTree* tree, int dstCount, regMaskTP dstCa // if ((killMask & RBM_FLT_CALLEE_TRASH) != RBM_NONE) { - buildUpperVectorSaveRefPositions(tree, currentLoc + 1, killMask); + buildUpperVectorSaveRefPositions(tree, currentLoc + 1 DEBUG_ARG(killMask & RBM_FLT_CALLEE_TRASH)); } #endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE } +} + +#if defined(TARGET_ARMARCH) || defined(TARGET_RISCV64) + +//------------------------------------------------------------------------ +// BuildDefWithKills: Build one RefTypeDef RefPositions for the given node, +// as well as kills as specified by the given mask. +// +// Arguments: +// tree - The call node that defines a register +// dstCandidates - The candidate registers for the definition +// killMask - The mask of registers killed by this node +// +// Notes: +// Adds the RefInfo for the definitions to the defList. +// The def and kill functionality is folded into a single method so that the +// save and restores of upper vector registers can be bracketed around the def. +// +void LinearScan::BuildDefWithKills(GenTree* tree, regMaskTP dstCandidates, regMaskTP killMask) +{ + assert(!tree->AsCall()->HasMultiRegRetVal()); + assert((int)genCountBits(dstCandidates) == 1); - // Now, create the Def(s) - BuildDefs(tree, dstCount, dstCandidates); + // Build the kill RefPositions + BuildKills(tree, killMask); + BuildDef(tree, dstCandidates); +} + +#else +//------------------------------------------------------------------------ +// BuildDefWithKills: Build one or two (for 32-bit) RefTypeDef RefPositions for the given node, +// as well as kills as specified by the given mask. +// +// Arguments: +// tree - The call node that defines a register +// dstCandidates - The candidate registers for the definition +// killMask - The mask of registers killed by this node +// +// Notes: +// Adds the RefInfo for the definitions to the defList. +// The def and kill functionality is folded into a single method so that the +// save and restores of upper vector registers can be bracketed around the def. +// +void LinearScan::BuildDefWithKills(GenTree* tree, int dstCount, regMaskTP dstCandidates, regMaskTP killMask) +{ + // Build the kill RefPositions + BuildKills(tree, killMask); + +#ifdef TARGET_64BIT + // For 64 bits, + assert(dstCount == 1); + BuildDef(tree, dstCandidates); +#else + if (dstCount == 1) + { + BuildDef(tree, dstCandidates); + } + else + { + assert(dstCount == 2); + BuildDefs(tree, 2, dstCandidates); + } +#endif // TARGET_64BIT +} +#endif + +//------------------------------------------------------------------------ +// BuildCallDefsWithKills: Build one or more RefTypeDef RefPositions for the given node, +// as well as kills as specified by the given mask. +// +// Arguments: +// tree - The node that defines a register +// dstCount - The number of registers defined by the node +// dstCandidates - The candidate registers for the definition +// killMask - The mask of registers killed by this node +// +// Notes: +// Adds the RefInfo for the definitions to the defList. +// The def and kill functionality is folded into a single method so that the +// save and restores of upper vector registers can be bracketed around the def. +// +void LinearScan::BuildCallDefsWithKills(GenTree* tree, int dstCount, regMaskTP dstCandidates, regMaskTP killMask) +{ + assert(dstCount > 0); + assert(dstCandidates != RBM_NONE); + + // Build the kill RefPositions + BuildKills(tree, killMask); + + // And then the Def(s) + BuildCallDefs(tree, dstCount, dstCandidates); } //------------------------------------------------------------------------ @@ -3424,6 +3593,16 @@ int LinearScan::BuildOperandUses(GenTree* node, regMaskTP candidates) if (numArgs != 1) { +#ifdef TARGET_ARM64 + if (HWIntrinsicInfo::IsScalable(hwintrinsic->GetHWIntrinsicId())) + { + for (size_t argNum = 1; argNum <= numArgs; argNum++) + { + BuildOperandUses(hwintrinsic->Op(argNum), candidates); + } + return (int)numArgs; + } +#endif assert(numArgs == 2); assert(hwintrinsic->Op(2)->isContained()); assert(hwintrinsic->Op(2)->IsCnsIntOrI()); @@ -3446,11 +3625,11 @@ int LinearScan::BuildOperandUses(GenTree* node, regMaskTP candidates) // ANDs may be contained in a chain. return BuildBinaryUses(node->AsOp(), candidates); } - if (node->OperIs(GT_NEG, GT_CAST, GT_LSH, GT_RSH, GT_RSZ)) + if (node->OperIs(GT_NEG, GT_CAST, GT_LSH, GT_RSH, GT_RSZ, GT_ROR)) { // NEG can be contained for mneg on arm64 // CAST and LSH for ADD with sign/zero extension - // LSH, RSH, and RSZ for various "shifted register" instructions on arm64 + // LSH, RSH, RSZ, and ROR for various "shifted register" instructions on arm64 return BuildOperandUses(node->gtGetOp1(), candidates); } #endif @@ -3547,7 +3726,7 @@ int LinearScan::BuildDelayFreeUses(GenTree* node, else if (node->OperIsHWIntrinsic()) { assert(node->AsHWIntrinsic()->GetOperandCount() == 1); - use = BuildUse(node->AsHWIntrinsic()->Op(1), candidates); + return BuildDelayFreeUses(node->AsHWIntrinsic()->Op(1), rmwNode, candidates, useRefPositionRef); } #endif else if (!node->OperIsIndir()) @@ -3989,7 +4168,7 @@ int LinearScan::BuildSimple(GenTree* tree) // int LinearScan::BuildReturn(GenTree* tree) { - GenTree* op1 = tree->gtGetOp1(); + GenTree* op1 = tree->AsOp()->GetReturnValue(); #if !defined(TARGET_64BIT) if (tree->TypeGet() == TYP_LONG) @@ -4421,3 +4600,36 @@ int LinearScan::BuildCmpOperands(GenTree* tree) srcCount += BuildOperandUses(op2, op2Candidates); return srcCount; } + +#ifdef SWIFT_SUPPORT +//------------------------------------------------------------------------ +// MarkSwiftErrorBusyForCall: Given a call set the appropriate RefTypeFixedReg +// RefPosition for the Swift error register as delay free to ensure the error +// register does not get allocated by LSRA before it has been consumed. +// +// Arguments: +// call - The call node +// +void LinearScan::MarkSwiftErrorBusyForCall(GenTreeCall* call) +{ + assert(call->HasSwiftErrorHandling()); + // After a Swift call that might throw returns, we expect the error register to be consumed + // by a GT_SWIFT_ERROR node. However, we want to ensure the error register won't be trashed + // before GT_SWIFT_ERROR can consume it. + // (For example, by LSRA allocating the call's result to the same register.) + // To do so, delay the freeing of the error register until the next node. + // This only works if the next node after the call is the GT_SWIFT_ERROR node. + // (LowerNonvirtPinvokeCall should have moved the GT_SWIFT_ERROR node.) + assert(call->gtNext != nullptr); + assert(call->gtNext->OperIs(GT_SWIFT_ERROR)); + + // Conveniently we model the zeroing of the register as a non-standard constant zero argument, + // which will have created a RefPosition corresponding to the use of the error at the location + // of the uses. Marking this RefPosition as delay freed has the effect of keeping the register + // busy at the location of the definition of the call. + RegRecord* swiftErrorRegRecord = getRegisterRecord(REG_SWIFT_ERROR); + assert((swiftErrorRegRecord != nullptr) && (swiftErrorRegRecord->lastRefPosition != nullptr) && + (swiftErrorRegRecord->lastRefPosition->nodeLocation == currentLoc)); + setDelayFree(swiftErrorRegRecord->lastRefPosition); +} +#endif diff --git a/src/coreclr/jit/lsraloongarch64.cpp b/src/coreclr/jit/lsraloongarch64.cpp index 1ceb61e53625..5fda31befc69 100644 --- a/src/coreclr/jit/lsraloongarch64.cpp +++ b/src/coreclr/jit/lsraloongarch64.cpp @@ -723,7 +723,7 @@ int LinearScan::BuildCall(GenTreeCall* call) { // Fast tail call - make sure that call target is always computed in volatile registers // that will not be overridden by epilog sequence. - ctrlExprCandidates = allRegs(TYP_INT) & RBM_INT_CALLEE_TRASH; + ctrlExprCandidates = (allRegs(TYP_INT) & (RBM_INT_CALLEE_TRASH & ~RBM_GSCOOKIE_TMP)); assert(ctrlExprCandidates != RBM_NONE); } } @@ -734,7 +734,7 @@ int LinearScan::BuildCall(GenTreeCall* call) regMaskTP candidates = RBM_NONE; if (call->IsFastTailCall()) { - candidates = allRegs(TYP_INT) & RBM_INT_CALLEE_TRASH; + candidates = (allRegs(TYP_INT) & (RBM_INT_CALLEE_TRASH & ~RBM_GSCOOKIE_TMP)); assert(candidates != RBM_NONE); } diff --git a/src/coreclr/jit/lsrariscv64.cpp b/src/coreclr/jit/lsrariscv64.cpp index 6af21c06ab20..d495246f9d1e 100644 --- a/src/coreclr/jit/lsrariscv64.cpp +++ b/src/coreclr/jit/lsrariscv64.cpp @@ -131,14 +131,14 @@ int LinearScan::BuildNode(GenTree* tree) srcCount = 0; assert(dstCount == 0); killMask = getKillSetForProfilerHook(); - BuildDefsWithKills(tree, 0, RBM_NONE, killMask); + BuildKills(tree, killMask); break; case GT_START_PREEMPTGC: // This kills GC refs in callee save regs srcCount = 0; assert(dstCount == 0); - BuildDefsWithKills(tree, 0, RBM_NONE, RBM_NONE); + BuildKills(tree, RBM_NONE); break; case GT_CNS_DBL: @@ -171,7 +171,7 @@ int LinearScan::BuildNode(GenTree* tree) case GT_RETURN: srcCount = BuildReturn(tree); killMask = getKillSetForReturn(); - BuildDefsWithKills(tree, 0, RBM_NONE, killMask); + BuildKills(tree, killMask); break; case GT_RETFILT: @@ -273,7 +273,7 @@ int LinearScan::BuildNode(GenTree* tree) srcCount = 1; assert(dstCount == 0); killMask = compiler->compHelperCallKillSet(CORINFO_HELP_STOP_FOR_GC); - BuildDefsWithKills(tree, 0, RBM_NONE, killMask); + BuildKills(tree, killMask); break; case GT_MUL: @@ -838,9 +838,9 @@ int LinearScan::BuildIndir(GenTreeIndir* indirTree) // int LinearScan::BuildCall(GenTreeCall* call) { - bool hasMultiRegRetVal = false; - const ReturnTypeDesc* retTypeDesc = nullptr; - regMaskTP dstCandidates = RBM_NONE; + bool hasMultiRegRetVal = false; + const ReturnTypeDesc* retTypeDesc = nullptr; + regMaskTP singleDstCandidates = RBM_NONE; int srcCount = 0; int dstCount = 0; @@ -908,22 +908,20 @@ int LinearScan::BuildCall(GenTreeCall* call) // Set destination candidates for return value of the call. - if (hasMultiRegRetVal) + if (!hasMultiRegRetVal) { - assert(retTypeDesc != nullptr); - dstCandidates = retTypeDesc->GetABIReturnRegs(call->GetUnmanagedCallConv()); - } - else if (varTypeUsesFloatArgReg(registerType)) - { - dstCandidates = RBM_FLOATRET; - } - else if (registerType == TYP_LONG) - { - dstCandidates = RBM_LNGRET; - } - else - { - dstCandidates = RBM_INTRET; + if (varTypeUsesFloatArgReg(registerType)) + { + singleDstCandidates = RBM_FLOATRET; + } + else if (registerType == TYP_LONG) + { + singleDstCandidates = RBM_LNGRET; + } + else + { + singleDstCandidates = RBM_INTRET; + } } // First, count reg args @@ -1035,7 +1033,25 @@ int LinearScan::BuildCall(GenTreeCall* call) // Now generate defs and kills. regMaskTP killMask = getKillSetForCall(call); - BuildDefsWithKills(call, dstCount, dstCandidates, killMask); + if (dstCount > 0) + { + if (hasMultiRegRetVal) + { + assert(retTypeDesc != nullptr); + regMaskTP multiDstCandidates = retTypeDesc->GetABIReturnRegs(call->GetUnmanagedCallConv()); + assert(genCountBits(multiDstCandidates) > 0); + BuildCallDefsWithKills(call, dstCount, multiDstCandidates, killMask); + } + else + { + assert(dstCount == 1); + BuildDefWithKills(call, singleDstCandidates, killMask); + } + } + else + { + BuildKills(call, killMask); + } // No args are placed in registers anymore. placedArgRegs = RBM_NONE; @@ -1345,7 +1361,7 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) buildInternalRegisterUses(); regMaskTP killMask = getKillSetForBlockStore(blkNode); - BuildDefsWithKills(blkNode, 0, RBM_NONE, killMask); + BuildKills(blkNode, killMask); return useCount; } diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index 7fe119ccfd16..a3d7647ad365 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -46,7 +46,7 @@ int LinearScan::BuildNode(GenTree* tree) { assert(!tree->isContained()); int srcCount; - int dstCount = 0; + int dstCount; regMaskTP killMask = RBM_NONE; bool isLocalDefUse = false; @@ -138,14 +138,14 @@ int LinearScan::BuildNode(GenTree* tree) // This kills GC refs in callee save regs srcCount = 0; assert(dstCount == 0); - BuildDefsWithKills(tree, 0, RBM_NONE, RBM_NONE); + BuildKills(tree, RBM_NONE); break; case GT_PROF_HOOK: srcCount = 0; assert(dstCount == 0); killMask = getKillSetForProfilerHook(); - BuildDefsWithKills(tree, 0, RBM_NONE, killMask); + BuildKills(tree, killMask); break; case GT_CNS_INT: @@ -190,9 +190,19 @@ int LinearScan::BuildNode(GenTree* tree) case GT_RETURN: srcCount = BuildReturn(tree); killMask = getKillSetForReturn(); - BuildDefsWithKills(tree, 0, RBM_NONE, killMask); + BuildKills(tree, killMask); break; +#ifdef SWIFT_SUPPORT + case GT_SWIFT_ERROR_RET: + BuildUse(tree->gtGetOp1(), RBM_SWIFT_ERROR); + // Plus one for error register + srcCount = BuildReturn(tree) + 1; + killMask = getKillSetForReturn(); + BuildKills(tree, killMask); + break; +#endif // SWIFT_SUPPORT + case GT_RETFILT: assert(dstCount == 0); if (tree->TypeGet() == TYP_VOID) @@ -296,7 +306,7 @@ int LinearScan::BuildNode(GenTree* tree) srcCount = BuildOperandUses(tree->gtGetOp1()); buildInternalRegisterUses(); killMask = compiler->compHelperCallKillSet(CORINFO_HELP_STOP_FOR_GC); - BuildDefsWithKills(tree, 0, RBM_NONE, killMask); + BuildKills(tree, killMask); } break; @@ -432,7 +442,7 @@ int LinearScan::BuildNode(GenTree* tree) // Comparand is preferenced to RAX. // The remaining two operands can be in any reg other than RAX. - const unsigned nonRaxCandidates = availableIntRegs & ~RBM_RAX; + const regMaskTP nonRaxCandidates = availableIntRegs & ~RBM_RAX; BuildUse(addr, nonRaxCandidates); BuildUse(data, varTypeIsByte(tree) ? (nonRaxCandidates & RBM_BYTE_REGS) : nonRaxCandidates); BuildUse(comparand, RBM_RAX); @@ -733,6 +743,7 @@ bool LinearScan::isRMWRegOper(GenTree* tree) #ifdef TARGET_X86 case GT_LONG: #endif + case GT_SWIFT_ERROR_RET: return false; case GT_ADD: @@ -1136,11 +1147,11 @@ int LinearScan::BuildShiftRotate(GenTree* tree) // int LinearScan::BuildCall(GenTreeCall* call) { - bool hasMultiRegRetVal = false; - const ReturnTypeDesc* retTypeDesc = nullptr; - int srcCount = 0; - int dstCount = 0; - regMaskTP dstCandidates = RBM_NONE; + bool hasMultiRegRetVal = false; + const ReturnTypeDesc* retTypeDesc = nullptr; + int srcCount = 0; + int dstCount = 0; + regMaskTP singleDstCandidates = RBM_NONE; assert(!call->isContained()); if (call->TypeGet() != TYP_VOID) @@ -1174,36 +1185,33 @@ int LinearScan::BuildCall(GenTreeCall* call) // The x86 CORINFO_HELP_INIT_PINVOKE_FRAME helper uses a custom calling convention that returns with // TCB in REG_PINVOKE_TCB. AMD64/ARM64 use the standard calling convention. fgMorphCall() sets the // correct argument registers. - dstCandidates = RBM_PINVOKE_TCB; + singleDstCandidates = RBM_PINVOKE_TCB; } else #endif // TARGET_X86 - if (hasMultiRegRetVal) - { - assert(retTypeDesc != nullptr); - dstCandidates = retTypeDesc->GetABIReturnRegs(call->GetUnmanagedCallConv()); - assert((int)genCountBits(dstCandidates) == dstCount); - } - else if (varTypeUsesFloatReg(registerType)) + if (!hasMultiRegRetVal) { + if (varTypeUsesFloatReg(registerType)) + { #ifdef TARGET_X86 - // The return value will be on the X87 stack, and we will need to move it. - dstCandidates = allRegs(registerType); + // The return value will be on the X87 stack, and we will need to move it. + singleDstCandidates = allRegs(registerType); #else // !TARGET_X86 - dstCandidates = RBM_FLOATRET; + singleDstCandidates = RBM_FLOATRET; #endif // !TARGET_X86 - } - else - { - assert(varTypeUsesIntReg(registerType)); - - if (registerType == TYP_LONG) - { - dstCandidates = RBM_LNGRET; } else { - dstCandidates = RBM_INTRET; + assert(varTypeUsesIntReg(registerType)); + + if (registerType == TYP_LONG) + { + singleDstCandidates = RBM_LNGRET; + } + else + { + singleDstCandidates = RBM_INTRET; + } } } @@ -1364,28 +1372,30 @@ int LinearScan::BuildCall(GenTreeCall* call) // Now generate defs and kills. regMaskTP killMask = getKillSetForCall(call); - BuildDefsWithKills(call, dstCount, dstCandidates, killMask); + if (dstCount > 0) + { + if (hasMultiRegRetVal) + { + assert(retTypeDesc != nullptr); + regMaskTP multiDstCandidates = retTypeDesc->GetABIReturnRegs(call->GetUnmanagedCallConv()); + assert((int)genCountBits(multiDstCandidates) == dstCount); + BuildCallDefsWithKills(call, dstCount, multiDstCandidates, killMask); + } + else + { + assert(dstCount == 1); + BuildDefWithKills(call, dstCount, singleDstCandidates, killMask); + } + } + else + { + BuildKills(call, killMask); + } #ifdef SWIFT_SUPPORT if (call->HasSwiftErrorHandling()) { - // Tree is a Swift call with error handling; error register should have been killed - assert((killMask & RBM_SWIFT_ERROR) != 0); - - // After a Swift call that might throw returns, we expect the error register to be consumed - // by a GT_SWIFT_ERROR node. However, we want to ensure the error register won't be trashed - // before GT_SWIFT_ERROR can consume it. - // (For example, the PInvoke epilog comes before the error register store.) - // To do so, delay the freeing of the error register until the next node. - // This only works if the next node after the call is the GT_SWIFT_ERROR node. - // (InsertPInvokeCallEpilog should have moved the GT_SWIFT_ERROR node during lowering.) - assert(call->gtNext != nullptr); - assert(call->gtNext->OperIs(GT_SWIFT_ERROR)); - - // We could use RefTypeKill, but RefTypeFixedReg is used less commonly, so the check for delayRegFree - // during register allocation should be cheaper in terms of TP. - RefPosition* pos = newRefPosition(REG_SWIFT_ERROR, currentLoc, RefTypeFixedReg, call, RBM_SWIFT_ERROR); - setDelayFree(pos); + MarkSwiftErrorBusyForCall(call); } #endif // SWIFT_SUPPORT @@ -1435,9 +1445,30 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) { case GenTreeBlk::BlkOpKindUnroll: { - const bool canUse16BytesSimdMov = - !blkNode->IsOnHeapAndContainsReferences() && compiler->IsBaselineSimdIsaSupported(); - const bool willUseSimdMov = canUse16BytesSimdMov && (size >= XMM_REGSIZE_BYTES); + bool willUseSimdMov = compiler->IsBaselineSimdIsaSupported() && (size >= XMM_REGSIZE_BYTES); + if (willUseSimdMov && blkNode->IsOnHeapAndContainsReferences()) + { + ClassLayout* layout = blkNode->GetLayout(); + + unsigned xmmCandidates = 0; + unsigned continuousNonGc = 0; + for (unsigned slot = 0; slot < layout->GetSlotCount(); slot++) + { + if (layout->IsGCPtr(slot)) + { + xmmCandidates += ((continuousNonGc * TARGET_POINTER_SIZE) / XMM_REGSIZE_BYTES); + continuousNonGc = 0; + } + else + { + continuousNonGc++; + } + } + xmmCandidates += ((continuousNonGc * TARGET_POINTER_SIZE) / XMM_REGSIZE_BYTES); + + // Just one XMM candidate is not profitable + willUseSimdMov = xmmCandidates > 1; + } if (willUseSimdMov) { @@ -1651,7 +1682,7 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) buildInternalRegisterUses(); regMaskTP killMask = getKillSetForBlockStore(blkNode); - BuildDefsWithKills(blkNode, 0, RBM_NONE, killMask); + BuildKills(blkNode, killMask); return useCount; } @@ -1943,7 +1974,7 @@ int LinearScan::BuildModDiv(GenTree* tree) buildInternalRegisterUses(); regMaskTP killMask = getKillSetForModDiv(tree->AsOp()); - BuildDefsWithKills(tree, 1, dstCandidates, killMask); + BuildDefWithKills(tree, 1, dstCandidates, killMask); return srcCount; } @@ -2548,7 +2579,7 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou for (GenTree* operand : op2->AsHWIntrinsic()->Operands()) { - assert(varTypeIsSIMD(operand)); + assert(varTypeIsSIMD(operand) || varTypeIsInt(operand)); srcCount += BuildDelayFreeUses(operand, op1); } } @@ -2561,7 +2592,7 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou for (GenTree* operand : op2->AsHWIntrinsic()->Operands()) { - assert(varTypeIsSIMD(operand)); + assert(varTypeIsSIMD(operand) || varTypeIsInt(operand)); srcCount += BuildOperandUses(operand); } } @@ -2794,10 +2825,11 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree, int* pDstCou if (dstCount == 1) { #if defined(TARGET_AMD64) - if (!intrinsicTree->isEvexCompatibleHWIntrinsic() && - (varTypeIsFloating(intrinsicTree->gtType) || varTypeIsSIMD(intrinsicTree->gtType))) + bool isEvexCompatible = intrinsicTree->isEvexCompatibleHWIntrinsic(); + + if (!isEvexCompatible) { - dstCandidates = lowSIMDRegs(); + dstCandidates = BuildEvexIncompatibleMask(intrinsicTree); } #endif @@ -2831,6 +2863,15 @@ int LinearScan::BuildCast(GenTreeCast* cast) const var_types srcType = genActualType(src->TypeGet()); const var_types castType = cast->gtCastType; + if ((srcType == TYP_LONG) && (castType == TYP_DOUBLE) && + !compiler->compOpportunisticallyDependsOn(InstructionSet_AVX512F)) + { + // We need two extra temp regs for LONG->DOUBLE cast + // if we don't have AVX512F available. + buildInternalIntRegisterDefForNode(cast); + buildInternalIntRegisterDefForNode(cast); + } + regMaskTP candidates = RBM_NONE; #ifdef TARGET_X86 if (varTypeIsByte(castType)) @@ -3060,7 +3101,7 @@ int LinearScan::BuildMul(GenTree* tree) containedMemOp = op2; } regMaskTP killMask = getKillSetForMul(tree->AsOp()); - BuildDefsWithKills(tree, dstCount, dstCandidates, killMask); + BuildDefWithKills(tree, dstCount, dstCandidates, killMask); return srcCount; } @@ -3106,7 +3147,9 @@ void LinearScan::SetContainsAVXFlags(unsigned sizeOfSIMDVector /* = 0*/) inline regMaskTP LinearScan::BuildEvexIncompatibleMask(GenTree* tree) { #if defined(TARGET_AMD64) - if (!(varTypeIsFloating(tree->gtType) || varTypeIsSIMD(tree->gtType))) + assert(!varTypeIsMask(tree)); + + if (!varTypeIsFloating(tree->gtType) && !varTypeIsSIMD(tree->gtType)) { return RBM_NONE; } diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index c07a412a81a6..c7d0df357a4f 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -770,8 +770,6 @@ const char* getWellKnownArgName(WellKnownArg arg) return "RetBuffer"; case WellKnownArg::PInvokeFrame: return "PInvokeFrame"; - case WellKnownArg::SecretStubParam: - return "SecretStubParam"; case WellKnownArg::WrapperDelegateCell: return "WrapperDelegateCell"; case WellKnownArg::ShiftLow: @@ -4603,10 +4601,14 @@ GenTree* Compiler::fgMorphExpandStackArgForVarArgs(GenTreeLclVarCommon* lclNode) return nullptr; } - LclVarDsc* varDsc = lvaGetDesc(lclNode); - GenTree* argsBaseAddr = gtNewLclvNode(lvaVarargsBaseOfStkArgs, TYP_I_IMPL); - ssize_t offset = - varDsc->GetStackOffset() - codeGen->intRegState.rsCalleeRegArgCount * REGSIZE_BYTES - lclNode->GetLclOffs(); + LclVarDsc* varDsc = lvaGetDesc(lclNode); + const ABIPassingInformation& abiInfo = lvaGetParameterABIInfo(lclNode->GetLclNum()); + assert(abiInfo.HasExactlyOneStackSegment()); + + GenTree* argsBaseAddr = gtNewLclvNode(lvaVarargsBaseOfStkArgs, TYP_I_IMPL); + ssize_t offset = (ssize_t)abiInfo.Segments[0].GetStackOffset() - lclNode->GetLclOffs(); + assert(abiInfo.Segments[0].GetStackOffset() == + (varDsc->GetStackOffset() - codeGen->intRegState.rsCalleeRegArgCount * REGSIZE_BYTES)); GenTree* offsetNode = gtNewIconNode(offset, TYP_I_IMPL); GenTree* argAddr = gtNewOperNode(GT_SUB, TYP_I_IMPL, argsBaseAddr, offsetNode); @@ -6496,7 +6498,7 @@ GenTree* Compiler::fgMorphTailCallViaHelpers(GenTreeCall* call, CORINFO_TAILCALL DISPTREE(call); // Don't support tail calling helper methods - assert(call->gtCallType != CT_HELPER); + assert(!call->IsHelperCall()); // We come this route only for tail prefixed calls that cannot be dispatched as // fast tail calls @@ -7049,7 +7051,7 @@ void Compiler::fgMorphTailCallViaJitHelper(GenTreeCall* call) assert(call->IsVirtual() || (call->gtCallType != CT_INDIRECT) || (call->gtCallCookie == nullptr)); // Don't support tail calling helper methods - assert(call->gtCallType != CT_HELPER); + assert(!call->IsHelperCall()); // We come this route only for tail prefixed calls that cannot be dispatched as // fast tail calls @@ -7766,7 +7768,7 @@ GenTree* Compiler::fgMorphCall(GenTreeCall* call) // Morph stelem.ref helper call to store a null value, into a store into an array without the helper. // This needs to be done after the arguments are morphed to ensure constant propagation has already taken place. - if (opts.OptimizationEnabled() && (call->gtCallType == CT_HELPER) && + if (opts.OptimizationEnabled() && call->IsHelperCall() && (call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_ARRADDR_ST))) { assert(call->gtArgs.CountArgs() == 3); @@ -8745,34 +8747,61 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA return fgMorphIntoHelperCall(tree, helper, true /* morphArgs */, op1, op2); case GT_RETURN: + case GT_SWIFT_ERROR_RET: + { + GenTree* retVal = tree->AsOp()->GetReturnValue(); + if (!tree->TypeIs(TYP_VOID)) { - if (op1->OperIs(GT_LCL_FLD)) + if (retVal->OperIs(GT_LCL_FLD)) { - op1 = fgMorphRetInd(tree->AsUnOp()); + retVal = fgMorphRetInd(tree->AsOp()); } - fgTryReplaceStructLocalWithField(op1); + fgTryReplaceStructLocalWithField(retVal); } // normalize small integer return values - if (fgGlobalMorph && varTypeIsSmall(info.compRetType) && (op1 != nullptr) && !op1->TypeIs(TYP_VOID) && - fgCastNeeded(op1, info.compRetType)) + if (fgGlobalMorph && varTypeIsSmall(info.compRetType) && (retVal != nullptr) && !retVal->TypeIs(TYP_VOID) && + fgCastNeeded(retVal, info.compRetType)) { +#ifdef SWIFT_SUPPORT + // Morph error operand if tree is a GT_SWIFT_ERROR_RET node + if (tree->OperIs(GT_SWIFT_ERROR_RET)) + { + GenTree* const errorVal = fgMorphTree(tree->gtGetOp1()); + tree->AsOp()->gtOp1 = errorVal; + + // Propagate side effect flags + tree->SetAllEffectsFlags(errorVal); + } +#endif // SWIFT_SUPPORT + // Small-typed return values are normalized by the callee - op1 = gtNewCastNode(TYP_INT, op1, false, info.compRetType); + retVal = gtNewCastNode(TYP_INT, retVal, false, info.compRetType); // Propagate GTF_COLON_COND - op1->gtFlags |= (tree->gtFlags & GTF_COLON_COND); + retVal->gtFlags |= (tree->gtFlags & GTF_COLON_COND); - tree->AsOp()->gtOp1 = fgMorphTree(op1); + retVal = fgMorphTree(retVal); + tree->AsOp()->SetReturnValue(retVal); // Propagate side effect flags - tree->SetAllEffectsFlags(tree->AsOp()->gtGetOp1()); + tree->SetAllEffectsFlags(retVal); return tree; } + + if (tree->OperIs(GT_RETURN)) + { + op1 = retVal; + } + else + { + op2 = retVal; + } break; + } case GT_EQ: case GT_NE: @@ -9639,15 +9668,18 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA break; case GT_RETURN: - - // Retry updating op1 to a field -- assertion - // prop done when morphing op1 changed the local. + case GT_SWIFT_ERROR_RET: + { + // Retry updating return operand to a field -- assertion + // prop done when morphing this operand changed the local. // - if (op1 != nullptr) + GenTree* const retVal = tree->AsOp()->GetReturnValue(); + if (retVal != nullptr) { - fgTryReplaceStructLocalWithField(op1); + fgTryReplaceStructLocalWithField(retVal); } break; + } default: break; @@ -9702,7 +9734,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA // tree - tree to examine and possibly modify // // Notes: -// Currently only called when the tree parent is a GT_RETURN. +// Currently only called when the tree parent is a GT_RETURN/GT_SWIFT_ERROR_RET. // void Compiler::fgTryReplaceStructLocalWithField(GenTree* tree) { @@ -10656,6 +10688,62 @@ GenTree* Compiler::fgOptimizeHWIntrinsic(GenTreeHWIntrinsic* node) INDEBUG(node->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); return node; } +#if defined(TARGET_ARM64) + case NI_Sve_ConvertMaskToVector: + { + GenTree* op1 = node->Op(1); + + if (!op1->OperIsHWIntrinsic(NI_Sve_ConvertVectorToMask)) + { + break; + } + + unsigned simdBaseTypeSize = genTypeSize(node->GetSimdBaseType()); + GenTreeHWIntrinsic* cvtOp1 = op1->AsHWIntrinsic(); + + if ((genTypeSize(cvtOp1->GetSimdBaseType()) != simdBaseTypeSize)) + { + // We need the operand to be the same kind of mask; otherwise + // the bitwise operation can differ in how it performs + break; + } + + GenTree* vectorNode = op1->AsHWIntrinsic()->Op(1); + + DEBUG_DESTROY_NODE(op1, node); + INDEBUG(vectorNode->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); + + return vectorNode; + } + + case NI_Sve_ConvertVectorToMask: + { + GenTree* op1 = node->Op(1); + GenTree* op2 = node->Op(2); + + if (!op1->OperIsHWIntrinsic(NI_Sve_CreateTrueMaskAll) && + !op2->OperIsHWIntrinsic(NI_Sve_ConvertMaskToVector)) + { + break; + } + + unsigned simdBaseTypeSize = genTypeSize(node->GetSimdBaseType()); + + if (!op2->OperIsHWIntrinsic() || (genTypeSize(op2->AsHWIntrinsic()->GetSimdBaseType()) != simdBaseTypeSize)) + { + // We need the operand to be the same kind of mask; otherwise + // the bitwise operation can differ in how it performs + break; + } + + GenTree* maskNode = op2->AsHWIntrinsic()->Op(1); + + DEBUG_DESTROY_NODE(op2, node); + INDEBUG(maskNode->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); + + return maskNode; + } +#endif #if defined(TARGET_XARCH) case NI_AVX512F_And: case NI_AVX512DQ_And: @@ -11554,16 +11642,16 @@ GenTree* Compiler::fgPropagateCommaThrow(GenTree* parent, GenTreeOp* commaThrow, // fgMorphRetInd: Try to get rid of extra local indirections in a return tree. // // Arguments: -// node - The return node that uses an local field. +// node - The return node that uses a local field. // // Return Value: -// the original op1 of the ret if there was no optimization or an optimized new op1. +// the original return operand if there was no optimization, or an optimized new return operand. // -GenTree* Compiler::fgMorphRetInd(GenTreeUnOp* ret) +GenTree* Compiler::fgMorphRetInd(GenTreeOp* ret) { - assert(ret->OperIs(GT_RETURN)); - assert(ret->gtGetOp1()->OperIs(GT_LCL_FLD)); - GenTreeLclFld* lclFld = ret->gtGetOp1()->AsLclFld(); + assert(ret->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)); + assert(ret->GetReturnValue()->OperIs(GT_LCL_FLD)); + GenTreeLclFld* lclFld = ret->GetReturnValue()->AsLclFld(); unsigned lclNum = lclFld->GetLclNum(); if (fgGlobalMorph && varTypeIsStruct(lclFld) && !lvaIsImplicitByRefLocal(lclNum)) @@ -13199,80 +13287,28 @@ Compiler::FoldResult Compiler::fgFoldConditional(BasicBlock* block) block->SetKindAndTargetEdge(BBJ_ALWAYS, block->GetFalseEdge()); } - if (fgHaveValidEdgeWeights) + // We examine the taken edge (block -> bTaken) + // if block has valid profile weight and bTaken does not we try to adjust bTaken's weight + // else if bTaken has valid profile weight and block does not we try to adjust block's weight + // We can only adjust the block weights when (the edge block -> bTaken) is the only edge into bTaken + // + if (block->hasProfileWeight()) { - // We are removing an edge from block to bNotTaken - // and we have already computed the edge weights, so - // we will try to adjust some of the weights - // - BasicBlock* bUpdated = nullptr; // non-NULL if we updated the weight of an internal block - - // We examine the taken edge (block -> bTaken) - // if block has valid profile weight and bTaken does not we try to adjust bTaken's weight - // else if bTaken has valid profile weight and block does not we try to adjust block's weight - // We can only adjust the block weights when (the edge block -> bTaken) is the only edge into bTaken - // - if (block->hasProfileWeight()) + if (!bTaken->hasProfileWeight()) { - // The edge weights for (block -> bTaken) are 100% of block's weight - - edgeTaken->setEdgeWeights(block->bbWeight, block->bbWeight, bTaken); - - if (!bTaken->hasProfileWeight()) + if ((bTaken->countOfInEdges() == 1) || (bTaken->bbWeight < block->bbWeight)) { - if ((bTaken->countOfInEdges() == 1) || (bTaken->bbWeight < block->bbWeight)) - { - // Update the weight of bTaken - bTaken->inheritWeight(block); - bUpdated = bTaken; - } - } - } - else if (bTaken->hasProfileWeight()) - { - if (bTaken->countOfInEdges() == 1) - { - // There is only one in edge to bTaken - edgeTaken->setEdgeWeights(bTaken->bbWeight, bTaken->bbWeight, bTaken); - - // Update the weight of block - block->inheritWeight(bTaken); - bUpdated = block; + // Update the weight of bTaken + bTaken->inheritWeight(block); } } - - if (bUpdated != nullptr) + } + else if (bTaken->hasProfileWeight()) + { + if (bTaken->countOfInEdges() == 1) { - weight_t newMinWeight; - weight_t newMaxWeight; - - FlowEdge* edge; - // Now fix the weights of the edges out of 'bUpdated' - switch (bUpdated->GetKind()) - { - case BBJ_COND: - edge = bUpdated->GetFalseEdge(); - newMaxWeight = bUpdated->bbWeight; - newMinWeight = min(edge->edgeWeightMin(), newMaxWeight); - edge->setEdgeWeights(newMinWeight, newMaxWeight, bUpdated->GetFalseTarget()); - - edge = bUpdated->GetTrueEdge(); - newMaxWeight = bUpdated->bbWeight; - newMinWeight = min(edge->edgeWeightMin(), newMaxWeight); - edge->setEdgeWeights(newMinWeight, newMaxWeight, bUpdated->GetFalseTarget()); - break; - - case BBJ_ALWAYS: - edge = bUpdated->GetTargetEdge(); - newMaxWeight = bUpdated->bbWeight; - newMinWeight = min(edge->edgeWeightMin(), newMaxWeight); - edge->setEdgeWeights(newMinWeight, newMaxWeight, bUpdated->Next()); - break; - - default: - // We don't handle BBJ_SWITCH - break; - } + // Update the weight of block + block->inheritWeight(bTaken); } } @@ -14087,7 +14123,7 @@ void Compiler::fgMergeBlockReturn(BasicBlock* block) Statement* lastStmt = block->lastStmt(); GenTree* ret = (lastStmt != nullptr) ? lastStmt->GetRootNode() : nullptr; - if ((ret != nullptr) && (ret->OperGet() == GT_RETURN) && ((ret->gtFlags & GTF_RET_MERGED) != 0)) + if ((ret != nullptr) && ret->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET) && ((ret->gtFlags & GTF_RET_MERGED) != 0)) { // This return was generated during epilog merging, so leave it alone } @@ -14108,27 +14144,40 @@ void Compiler::fgMergeBlockReturn(BasicBlock* block) fgReturnCount--; } +#ifdef SWIFT_SUPPORT + // If merging GT_SWIFT_ERROR_RET nodes, ensure the error operand is stored to the merged return error local, + // so the correct error value is retrieved in the merged return block. + if ((ret != nullptr) && ret->OperIs(GT_SWIFT_ERROR_RET)) + { + assert(genReturnErrorLocal != BAD_VAR_NUM); + const DebugInfo& di = lastStmt->GetDebugInfo(); + GenTree* swiftErrorStore = gtNewTempStore(genReturnErrorLocal, ret->gtGetOp1()); + Statement* const newStmt = gtNewStmt(swiftErrorStore, di); + fgInsertStmtBefore(block, lastStmt, newStmt); + } +#endif // SWIFT_SUPPORT + if (genReturnLocal != BAD_VAR_NUM) { - // replace the GT_RETURN node to be a STORE_LCL_VAR that stores the return value into genReturnLocal. + // replace the GT_RETURN/GT_SWIFT_ERROR_RET node to be a STORE_LCL_VAR that stores the return value into + // genReturnLocal. // Method must be returning a value other than TYP_VOID. noway_assert(compMethodHasRetVal()); - // This block must be ending with a GT_RETURN + // This block must be ending with a GT_RETURN/GT_SWIFT_ERROR_RET noway_assert(lastStmt != nullptr); noway_assert(lastStmt->GetNextStmt() == nullptr); noway_assert(ret != nullptr); - // GT_RETURN must have non-null operand as the method is returning the value assigned to + // Return node must have non-null operand as the method is returning the value assigned to // genReturnLocal - noway_assert(ret->OperGet() == GT_RETURN); - noway_assert(ret->gtGetOp1() != nullptr); + GenTree* const retVal = ret->AsOp()->GetReturnValue(); + noway_assert(retVal != nullptr); Statement* pAfterStatement = lastStmt; const DebugInfo& di = lastStmt->GetDebugInfo(); - GenTree* tree = - gtNewTempStore(genReturnLocal, ret->gtGetOp1(), CHECK_SPILL_NONE, &pAfterStatement, di, block); + GenTree* tree = gtNewTempStore(genReturnLocal, retVal, CHECK_SPILL_NONE, &pAfterStatement, di, block); if (tree->OperIsCopyBlkOp()) { tree = fgMorphCopyBlock(tree); @@ -14151,16 +14200,17 @@ void Compiler::fgMergeBlockReturn(BasicBlock* block) lastStmt = newStmt; } } - else if (ret != nullptr && ret->OperGet() == GT_RETURN) + else if ((ret != nullptr) && ret->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)) { - // This block ends with a GT_RETURN + // This block ends with a GT_RETURN/GT_SWIFT_ERROR_RET noway_assert(lastStmt != nullptr); noway_assert(lastStmt->GetNextStmt() == nullptr); - // Must be a void GT_RETURN with null operand; delete it as this block branches to oneReturn - // block + // Must be a void return node with null operand; delete it as this block branches to + // oneReturn block + GenTree* const retVal = ret->AsOp()->GetReturnValue(); noway_assert(ret->TypeGet() == TYP_VOID); - noway_assert(ret->gtGetOp1() == nullptr); + noway_assert(retVal == nullptr); if (opts.compDbgCode && lastStmt->GetDebugInfo().IsValid()) { @@ -14253,6 +14303,13 @@ void Compiler::fgSetOptions() if (info.compXcptnsCount > 0) { codeGen->setFramePointerRequiredEH(true); + + if (UsesFunclets()) + { + assert(!codeGen->isGCTypeFixed()); + // Enforce fully interruptible codegen for funclet unwinding + SetInterruptible(true); + } } #else // !TARGET_X86 @@ -14264,15 +14321,6 @@ void Compiler::fgSetOptions() #endif // TARGET_X86 -#ifdef UNIX_X86_ABI - if (info.compXcptnsCount > 0) - { - assert(!codeGen->isGCTypeFixed()); - // Enforce fully interruptible codegen for funclet unwinding - SetInterruptible(true); - } -#endif // UNIX_X86_ABI - if (compMethodRequiresPInvokeFrame()) { codeGen->setFramePointerRequired(true); // Setup of Pinvoke frame currently requires an EBP style frame @@ -14732,12 +14780,11 @@ bool Compiler::fgExpandQmarkStmt(BasicBlock* block, Statement* stmt) if (hasTrueExpr) { - if (trueExpr->OperIs(GT_CALL) && (trueExpr->AsCall()->gtCallMoreFlags & GTF_CALL_M_DOES_NOT_RETURN)) + if (trueExpr->OperIs(GT_CALL) && trueExpr->AsCall()->IsNoReturn()) { Statement* trueStmt = fgNewStmtFromTree(trueExpr, stmt->GetDebugInfo()); fgInsertStmtAtEnd(thenBlock, trueStmt); fgConvertBBToThrowBB(thenBlock); - setMethodHasNoReturnCalls(); introducedThrow = true; } else @@ -14756,12 +14803,11 @@ bool Compiler::fgExpandQmarkStmt(BasicBlock* block, Statement* stmt) // Assign the falseExpr into the dst or tmp, insert in elseBlock if (hasFalseExpr) { - if (falseExpr->OperIs(GT_CALL) && (falseExpr->AsCall()->gtCallMoreFlags & GTF_CALL_M_DOES_NOT_RETURN)) + if (falseExpr->OperIs(GT_CALL) && falseExpr->AsCall()->IsNoReturn()) { Statement* falseStmt = fgNewStmtFromTree(falseExpr, stmt->GetDebugInfo()); fgInsertStmtAtEnd(elseBlock, falseStmt); fgConvertBBToThrowBB(elseBlock); - setMethodHasNoReturnCalls(); introducedThrow = true; } else @@ -15221,7 +15267,9 @@ PhaseStatus Compiler::fgRetypeImplicitByRefArgs() if (!undoPromotion) { // Insert IR that initializes the temp from the parameter. - fgEnsureFirstBBisScratch(); + // The first BB should already be a valid insertion point, + // which is a precondition for this phase when optimizing. + assert(fgFirstBB->bbPreds == nullptr); GenTree* addr = gtNewLclvNode(lclNum, TYP_BYREF); GenTree* data = (varDsc->TypeGet() == TYP_STRUCT) ? gtNewBlkIndir(varDsc->GetLayout(), addr) : gtNewIndir(varDsc->TypeGet(), addr); diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index b3eb292677d8..de20de7bfbe5 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -50,7 +50,10 @@ enum NamedIntrinsic : unsigned short NI_System_Math_MinMagnitude, NI_System_Math_MinMagnitudeNumber, NI_System_Math_MinNumber, + NI_System_Math_MultiplyAddEstimate, NI_System_Math_Pow, + NI_System_Math_ReciprocalEstimate, + NI_System_Math_ReciprocalSqrtEstimate, NI_System_Math_Round, NI_System_Math_Sin, NI_System_Math_Sinh, @@ -227,6 +230,8 @@ enum NamedIntrinsic : unsigned short NI_PRIMITIVE_START, + NI_PRIMITIVE_ConvertToInteger, + NI_PRIMITIVE_ConvertToIntegerNative, NI_PRIMITIVE_Crc32C, NI_PRIMITIVE_LeadingZeroCount, NI_PRIMITIVE_Log2, diff --git a/src/coreclr/jit/objectalloc.cpp b/src/coreclr/jit/objectalloc.cpp index 0c995997d813..3d6206e0f723 100644 --- a/src/coreclr/jit/objectalloc.cpp +++ b/src/coreclr/jit/objectalloc.cpp @@ -637,7 +637,7 @@ bool ObjectAllocator::CanLclVarEscapeViaParentStack(ArrayStack* parent { GenTreeCall* asCall = parent->AsCall(); - if (asCall->gtCallType == CT_HELPER) + if (asCall->IsHelperCall()) { // TODO-ObjectStackAllocation: Special-case helpers here that // 1. Don't make objects escape. diff --git a/src/coreclr/jit/optcse.cpp b/src/coreclr/jit/optcse.cpp index 41b15792e24a..b3d8e2610168 100644 --- a/src/coreclr/jit/optcse.cpp +++ b/src/coreclr/jit/optcse.cpp @@ -1869,7 +1869,7 @@ bool CSE_HeuristicCommon::CanConsiderTree(GenTree* tree, bool isReturn) // more exceptions (NullRef) so we abandon this CSE. // If we don't mark CALL ALLOC_HELPER as a CSE candidate, we are able // to use GT_IND(x) in [2] as a CSE def. - if ((call->gtCallType == CT_HELPER) && + if (call->IsHelperCall() && Compiler::s_helperCallProperties.IsAllocator(m_pCompiler->eeGetHelperNum(call->gtCallMethHnd))) { return false; @@ -2973,6 +2973,298 @@ void CSE_HeuristicParameterized::DumpChoices(ArrayStack& choices, CSEdsc #ifdef DEBUG +//------------------------------------------------------------------------ +// CSE_HeuristicRLHook: a generic 'hook' for driving CSE decisions out of +// process using reinforcement learning +// +// Arguments; +// pCompiler - compiler instance +// +// Notes: +// This creates a hook to control CSE decisions from an external process +// when JitRLHook=1 is set. This will cause the JIT to emit a series of +// feature building blocks for each CSE in the method. Feature names for +// these values can be found by setting JitRLHookEmitFeatureNames=1. To +// control the CSE decisions, set JitRLHookCSEDecisions with a sequence +// of CSE indices to apply. +// +// This hook is only available in debug/checked builds, and does not +// contain any machine learning code. +// +CSE_HeuristicRLHook::CSE_HeuristicRLHook(Compiler* pCompiler) + : CSE_HeuristicCommon(pCompiler) +{ +} + +//------------------------------------------------------------------------ +// ConsiderTree: check if this tree can be a CSE candidate +// +// Arguments: +// tree - tree in question +// isReturn - true if tree is part of a return statement +// +// Returns: +// true if this tree can be a CSE +bool CSE_HeuristicRLHook::ConsiderTree(GenTree* tree, bool isReturn) +{ + return CanConsiderTree(tree, isReturn); +} + +//------------------------------------------------------------------------ +// ConsiderCandidates: examine candidates and perform CSEs. +// This simply defers to the JitRLHookCSEDecisions config value. +// +void CSE_HeuristicRLHook::ConsiderCandidates() +{ + if (JitConfig.JitRLHookCSEDecisions() != nullptr) + { + ConfigIntArray JitRLHookCSEDecisions; + JitRLHookCSEDecisions.EnsureInit(JitConfig.JitRLHookCSEDecisions()); + + unsigned cnt = m_pCompiler->optCSECandidateCount; + for (unsigned i = 0; i < JitRLHookCSEDecisions.GetLength(); i++) + { + const int index = JitRLHookCSEDecisions.GetData()[i]; + if ((index < 0) || (index >= (int)cnt)) + { + JITDUMP("Invalid candidate number %d\n", index + 1); + continue; + } + + CSEdsc* const dsc = m_pCompiler->optCSEtab[index]; + if (!dsc->IsViable()) + { + JITDUMP("Abandoned " FMT_CSE " -- not viable\n", dsc->csdIndex); + continue; + } + + const int attempt = m_pCompiler->optCSEattempt++; + CSE_Candidate candidate(this, dsc); + + JITDUMP("\nRLHook attempting " FMT_CSE "\n", candidate.CseIndex()); + JITDUMP("CSE Expression : \n"); + JITDUMPEXEC(m_pCompiler->gtDispTree(candidate.Expr())); + JITDUMP("\n"); + + PerformCSE(&candidate); + madeChanges = true; + } + } +} + +//------------------------------------------------------------------------ +// DumpMetrics: write out features for each CSE candidate +// Format: +// featureNames +// features #, +// seq +// +// Notes: +// featureNames are emitted only if JitRLHookEmitFeatureNames is set. +// features are 0 indexed, and the index is the first value, following #. +// seq is a comma separated list of CSE indices that were applied, or +// omitted if none were selected +// +void CSE_HeuristicRLHook::DumpMetrics() +{ + // Feature names, if requested + if (JitConfig.JitRLHookEmitFeatureNames() > 0) + { + printf(" featureNames "); + for (int i = 0; i < maxFeatures; i++) + { + printf("%s%s", (i == 0) ? "" : ",", s_featureNameAndType[i]); + } + } + + // features + for (unsigned i = 0; i < m_pCompiler->optCSECandidateCount; i++) + { + CSEdsc* const cse = m_pCompiler->optCSEtab[i]; + + int features[maxFeatures]; + GetFeatures(cse, features); + + printf(" features #%i", cse->csdIndex); + for (int j = 0; j < maxFeatures; j++) + { + printf(",%d", features[j]); + } + } + + // The selected sequence of CSEs that were applied + if (JitConfig.JitRLHookCSEDecisions() != nullptr) + { + ConfigIntArray JitRLHookCSEDecisions; + JitRLHookCSEDecisions.EnsureInit(JitConfig.JitRLHookCSEDecisions()); + + if (JitRLHookCSEDecisions.GetLength() > 0) + { + printf(" seq "); + for (unsigned i = 0; i < JitRLHookCSEDecisions.GetLength(); i++) + { + printf("%s%d", (i == 0) ? "" : ",", JitRLHookCSEDecisions.GetData()[i]); + } + } + } +} + +//------------------------------------------------------------------------ +// GetFeatures: extract features for this CSE +// Arguments: +// cse - cse descriptor +// features - array to fill in with feature values, this must be of length +// maxFeatures or greater +// +// Notes: +// Features are intended to be building blocks of "real" features that +// are further defined and refined in the machine learning model. That +// means that each "feature" here is a simple value and not a composite +// of multiple values. +// +// Features do not need to be stable across builds, they can be changed, +// added, or removed. However, the corresponding code needs to be updated +// to match: src/coreclr/scripts/cse_ml/jitml/method_context.py +// See src/coreclr/scripts/cse_ml/README.md for more information. +// +void CSE_HeuristicRLHook::GetFeatures(CSEdsc* cse, int* features) +{ + assert(cse != nullptr); + assert(features != nullptr); + CSE_Candidate candidate(this, cse); + + int enregCount = 0; + for (unsigned trackedIndex = 0; trackedIndex < m_pCompiler->lvaTrackedCount; trackedIndex++) + { + LclVarDsc* varDsc = m_pCompiler->lvaGetDescByTrackedIndex(trackedIndex); + var_types varTyp = varDsc->TypeGet(); + + // Locals with no references aren't enregistered + if (varDsc->lvRefCnt() == 0) + { + continue; + } + + // Some LclVars always have stack homes + if (varDsc->lvDoNotEnregister) + { + continue; + } + + if (!varTypeIsFloating(varTyp)) + { + enregCount++; // The primitive types, including TYP_SIMD types use one register + +#ifndef TARGET_64BIT + if (varTyp == TYP_LONG) + { + enregCount++; // on 32-bit targets longs use two registers + } +#endif + } + } + + const unsigned numBBs = m_pCompiler->fgBBcount; + bool isMakeCse = false; + unsigned minPostorderNum = numBBs; + unsigned maxPostorderNum = 0; + BasicBlock* minPostorderBlock = nullptr; + BasicBlock* maxPostorderBlock = nullptr; + for (treeStmtLst* treeList = cse->csdTreeList; treeList != nullptr; treeList = treeList->tslNext) + { + BasicBlock* const treeBlock = treeList->tslBlock; + unsigned postorderNum = treeBlock->bbPostorderNum; + if (postorderNum < minPostorderNum) + { + minPostorderNum = postorderNum; + minPostorderBlock = treeBlock; + } + + if (postorderNum > maxPostorderNum) + { + maxPostorderNum = postorderNum; + maxPostorderBlock = treeBlock; + } + + isMakeCse |= ((treeList->tslTree->gtFlags & GTF_MAKE_CSE) != 0); + } + + const unsigned blockSpread = maxPostorderNum - minPostorderNum; + + int type = rlHookTypeOther; + if (candidate.Expr()->TypeIs(TYP_INT)) + { + type = rlHookTypeInt; + } + else if (candidate.Expr()->TypeIs(TYP_LONG)) + { + type = rlHookTypeLong; + } + else if (candidate.Expr()->TypeIs(TYP_FLOAT)) + { + type = rlHookTypeFloat; + } + else if (candidate.Expr()->TypeIs(TYP_DOUBLE)) + { + type = rlHookTypeDouble; + } + else if (candidate.Expr()->TypeIs(TYP_STRUCT)) + { + type = rlHookTypeStruct; + } + +#ifdef FEATURE_SIMD + else if (varTypeIsSIMD(candidate.Expr()->TypeGet())) + { + type = rlHookTypeSimd; + } +#ifdef TARGET_XARCH + else if (candidate.Expr()->TypeIs(TYP_SIMD32, TYP_SIMD64)) + { + type = rlHookTypeSimd; + } +#endif +#endif + + int i = 0; + features[i++] = type; + features[i++] = cse->IsViable() ? 1 : 0; + features[i++] = cse->csdLiveAcrossCall ? 1 : 0; + features[i++] = cse->csdTree->OperIsConst() ? 1 : 0; + features[i++] = cse->csdIsSharedConst ? 1 : 0; + features[i++] = isMakeCse ? 1 : 0; + features[i++] = ((cse->csdTree->gtFlags & GTF_CALL) != 0) ? 1 : 0; + features[i++] = cse->csdTree->OperIs(GT_ADD, GT_NOT, GT_MUL, GT_LSH) ? 1 : 0; + features[i++] = cse->csdTree->GetCostEx(); + features[i++] = cse->csdTree->GetCostSz(); + features[i++] = cse->csdUseCount; + features[i++] = cse->csdDefCount; + features[i++] = (int)cse->csdUseWtCnt; + features[i++] = (int)cse->csdDefWtCnt; + features[i++] = cse->numDistinctLocals; + features[i++] = cse->numLocalOccurrences; + features[i++] = numBBs; + features[i++] = blockSpread; + features[i++] = enregCount; + + assert(i <= maxFeatures); + + for (; i < maxFeatures; i++) + { + features[i] = 0; + } +} + +// These need to match the features above, and match the field name of MethodContext +// in src/coreclr/scripts/cse_ml/jitml/method_context.py +const char* const CSE_HeuristicRLHook::s_featureNameAndType[] = { + "type", "viable", "live_across_call", "const", + "shared_const", "make_cse", "has_call", "containable", + "cost_ex", "cost_sz", "use_count", "def_count", + "use_wt_cnt", "def_wt_cnt", "distinct_locals", "local_occurrences", + "bb_count", "block_spread", "enreg_count", +}; + //------------------------------------------------------------------------ // CSE_HeuristicRL: construct RL CSE heuristic // @@ -4813,8 +5105,12 @@ void CSE_HeuristicCommon::PerformCSE(CSE_Candidate* successfulCandidate) assert(vnStore->IsVNCompareCheckedBoundArith(oldCmpVN)); vnStore->GetCompareCheckedBoundArithInfo(oldCmpVN, &info); - newCmpArgVN = vnStore->VNForFunc(vnStore->TypeOfVN(info.arrOp), (VNFunc)info.arrOper, - info.arrOp, theConservativeVN); + + ValueNum arrOp1 = info.arrOpLHS ? info.arrOp : theConservativeVN; + ValueNum arrOp2 = info.arrOpLHS ? theConservativeVN : info.arrOp; + + newCmpArgVN = + vnStore->VNForFunc(vnStore->TypeOfVN(info.arrOp), (VNFunc)info.arrOper, arrOp1, arrOp2); } ValueNum newCmpVN = vnStore->VNForFunc(vnStore->TypeOfVN(oldCmpVN), (VNFunc)info.cmpOper, info.cmpOp, newCmpArgVN); @@ -5161,9 +5457,20 @@ CSE_HeuristicCommon* Compiler::optGetCSEheuristic() // Enable optional policies // - // RL takes precedence + // RL hook takes precedence // if (optCSEheuristic == nullptr) + { + bool useRLHook = (JitConfig.JitRLHook() > 0); + + if (useRLHook) + { + optCSEheuristic = new (this, CMK_CSE) CSE_HeuristicRLHook(this); + } + } + + // then RL + if (optCSEheuristic == nullptr) { bool useRLHeuristic = (JitConfig.JitRLCSE() != nullptr); diff --git a/src/coreclr/jit/optcse.h b/src/coreclr/jit/optcse.h index b8dd9fae685d..48fba4e50e13 100644 --- a/src/coreclr/jit/optcse.h +++ b/src/coreclr/jit/optcse.h @@ -217,6 +217,49 @@ class CSE_HeuristicParameterized : public CSE_HeuristicCommon #ifdef DEBUG +// General Reinforcement Learning CSE heuristic hook. +// +// Produces a wide set of data to train a RL model. +// Consumes the decisions made by a model to perform CSEs. +// +class CSE_HeuristicRLHook : public CSE_HeuristicCommon +{ +private: + static const char* const s_featureNameAndType[]; + + void GetFeatures(CSEdsc* cse, int* features); + + enum + { + maxFeatures = 19, + }; + + enum + { + rlHookTypeOther = 0, + rlHookTypeInt = 1, + rlHookTypeLong = 2, + rlHookTypeFloat = 3, + rlHookTypeDouble = 4, + rlHookTypeStruct = 5, + rlHookTypeSimd = 6, + }; + +public: + CSE_HeuristicRLHook(Compiler*); + void ConsiderCandidates(); + bool ConsiderTree(GenTree* tree, bool isReturn); + + const char* Name() const + { + return "RL Hook CSE Heuristic"; + } + +#ifdef DEBUG + virtual void DumpMetrics(); +#endif +}; + // Reinforcement Learning CSE heuristic // // Uses a "linear" feature model with diff --git a/src/coreclr/jit/optimizebools.cpp b/src/coreclr/jit/optimizebools.cpp index 1e5d5a00b107..f915cf7c3494 100644 --- a/src/coreclr/jit/optimizebools.cpp +++ b/src/coreclr/jit/optimizebools.cpp @@ -18,15 +18,43 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX /*****************************************************************************/ //----------------------------------------------------------------------------- -// OptTestInfo: Member of OptBoolsDsc struct used to test if a GT_JTRUE or GT_RETURN node +// OptTestInfo: Member of OptBoolsDsc struct used to test if a GT_JTRUE or return node // is a boolean comparison // struct OptTestInfo { Statement* testStmt; // Last statement of the basic block - GenTree* testTree; // The root node of the testStmt (GT_JTRUE or GT_RETURN). + GenTree* testTree; // The root node of the testStmt (GT_JTRUE or GT_RETURN/GT_SWIFT_ERROR_RET). GenTree* compTree; // The compare node (i.e. GT_EQ or GT_NE node) of the testTree bool isBool; // If the compTree is boolean expression + + GenTree* GetTestOp() const + { + assert(testTree != nullptr); + + if (testTree->OperIs(GT_JTRUE)) + { + return testTree->gtGetOp1(); + } + + assert(testTree->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)); + return testTree->AsOp()->GetReturnValue(); + } + + void SetTestOp(GenTree* const op) + { + assert(testTree != nullptr); + + if (testTree->OperIs(GT_JTRUE)) + { + testTree->AsOp()->gtOp1 = op; + } + else + { + assert(testTree->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)); + testTree->AsOp()->SetReturnValue(op); + } + } }; //----------------------------------------------------------------------------- @@ -100,12 +128,12 @@ class OptBoolsDsc // For example, (x == 0 && y == 0 && z == 0) generates // B1: GT_JTRUE (BBJ_COND), jump to B4 // B2: GT_JTRUE (BBJ_COND), jump to B4 -// B3: GT_RETURN (BBJ_RETURN) -// B4: GT_RETURN (BBJ_RETURN) +// B3: GT_RETURN/GT_SWIFT_ERROR_RET (BBJ_RETURN) +// B4: GT_RETURN/GT_SWIFT_ERROR_RET (BBJ_RETURN) // and B1 and B2 are folded into B1: // B1: GT_JTRUE (BBJ_COND), jump to B4 -// B3: GT_RETURN (BBJ_RETURN) -// B4: GT_RETURN (BBJ_RETURN) +// B3: GT_RETURN/GT_SWIFT_ERROR_RET (BBJ_RETURN) +// B4: GT_RETURN/GT_SWIFT_ERROR_RET (BBJ_RETURN) // // Case 2: if B2->FalseTargetIs(B1->GetTarget()), it transforms // B1 : brtrue(t1, B3) @@ -234,8 +262,7 @@ bool OptBoolsDsc::optOptimizeBoolsCondBlock() cmpOp = GT_EQ; } else if (m_testInfo1.compTree->gtOper == GT_LT && m_testInfo2.compTree->gtOper == GT_LT && - (!m_testInfo1.testTree->AsOp()->gtOp1->IsUnsigned() && - !m_testInfo2.testTree->AsOp()->gtOp1->IsUnsigned())) + (!m_testInfo1.GetTestOp()->IsUnsigned() && !m_testInfo2.GetTestOp()->IsUnsigned())) { // t1:c1<0 t2:c2<0 ==> Branch to BX if either value < 0 // So we will branch to BX if (c1|c2)<0 @@ -297,8 +324,7 @@ bool OptBoolsDsc::optOptimizeBoolsCondBlock() cmpOp = GT_NE; } else if (m_testInfo1.compTree->gtOper == GT_LT && m_testInfo2.compTree->gtOper == GT_GE && - (!m_testInfo1.testTree->AsOp()->gtOp1->IsUnsigned() && - !m_testInfo2.testTree->AsOp()->gtOp1->IsUnsigned())) + (!m_testInfo1.GetTestOp()->IsUnsigned() && !m_testInfo2.GetTestOp()->IsUnsigned())) { // t1:c1<0 t2:c2>=0 ==> Branch to BX if both values >= 0 // So we will branch to BX if (c1|c2)>=0 @@ -1023,7 +1049,7 @@ bool OptBoolsDsc::optOptimizeCompareChainCondBlock() m_comp->gtNewOperNode(GT_NE, TYP_INT, chainedConditions, m_comp->gtNewZeroConNode(TYP_INT)); // Wire the chain into the second block - m_testInfo2.testTree->AsOp()->gtOp1 = testcondition; + m_testInfo2.SetTestOp(testcondition); m_testInfo2.testTree->AsOp()->gtFlags |= (testcondition->gtFlags & GTF_ALL_EFFECT); m_comp->gtSetEvalOrder(m_testInfo2.testTree); m_comp->fgSetStmtSeq(s2); @@ -1062,7 +1088,7 @@ bool OptBoolsDsc::optOptimizeCompareChainCondBlock() // // Notes: // This method checks if the second (and third block for cond/return/return case) contains only one statement, -// and checks if tree operators are of the right type, e.g, GT_JTRUE, GT_RETURN. +// and checks if tree operators are of the right type, e.g, GT_JTRUE, GT_RETURN, GT_SWIFT_ERROR_RET. // // On entry, m_b1, m_b2 are set and m_b3 is set for cond/return/return case. // If it passes all the conditions, m_testInfo1.testTree, m_testInfo2.testTree and m_t3 are set @@ -1091,7 +1117,7 @@ Statement* OptBoolsDsc::optOptimizeBoolsChkBlkCond() Statement* s1 = m_b1->lastStmt(); GenTree* testTree1 = s1->GetRootNode(); - assert(testTree1->gtOper == GT_JTRUE); + assert(testTree1->OperIs(GT_JTRUE)); // The second and the third block must contain a single statement @@ -1105,11 +1131,11 @@ Statement* OptBoolsDsc::optOptimizeBoolsChkBlkCond() if (!optReturnBlock) { - assert(testTree2->gtOper == GT_JTRUE); + assert(testTree2->OperIs(GT_JTRUE)); } else { - if (testTree2->gtOper != GT_RETURN) + if (!testTree2->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)) { return nullptr; } @@ -1121,7 +1147,7 @@ Statement* OptBoolsDsc::optOptimizeBoolsChkBlkCond() } GenTree* testTree3 = s3->GetRootNode(); - if (testTree3->gtOper != GT_RETURN) + if (!testTree3->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)) { return nullptr; } @@ -1132,12 +1158,13 @@ Statement* OptBoolsDsc::optOptimizeBoolsChkBlkCond() } // The third block is Return with "CNS_INT int 0/1" - if (testTree3->AsOp()->gtOp1->gtOper != GT_CNS_INT) + GenTree* const retVal = testTree3->AsOp()->GetReturnValue(); + if (!retVal->OperIs(GT_CNS_INT)) { return nullptr; } - if (testTree3->AsOp()->gtOp1->gtType != TYP_INT) + if (!retVal->TypeIs(TYP_INT)) { return nullptr; } @@ -1221,7 +1248,7 @@ void OptBoolsDsc::optOptimizeBoolsUpdateTrees() optReturnBlock = true; } - assert(m_cmpOp != NULL && m_c1 != nullptr && m_c2 != nullptr); + assert(m_cmpOp != GT_NONE && m_c1 != nullptr && m_c2 != nullptr); GenTree* cmpOp1 = m_foldOp == GT_NONE ? m_c1 : m_comp->gtNewOperNode(m_foldOp, m_foldType, m_c1, m_c2); if (m_testInfo1.isBool && m_testInfo2.isBool) @@ -1236,10 +1263,10 @@ void OptBoolsDsc::optOptimizeBoolsUpdateTrees() t1Comp->AsOp()->gtOp2->gtType = m_foldType; // Could have been varTypeIsGC() if (optReturnBlock) { - // Update tree when m_b1 is BBJ_COND and m_b2 and m_b3 are GT_RETURN (BBJ_RETURN) + // Update tree when m_b1 is BBJ_COND and m_b2 and m_b3 are GT_RETURN/GT_SWIFT_ERROR_RET (BBJ_RETURN) t1Comp->AsOp()->gtOp2->AsIntCon()->gtIconVal = 0; - m_testInfo1.testTree->gtOper = GT_RETURN; - m_testInfo1.testTree->gtType = m_testInfo2.testTree->gtType; + m_testInfo1.testTree->gtOper = m_testInfo2.testTree->OperGet(); + m_testInfo1.testTree->gtType = m_testInfo2.testTree->TypeGet(); // Update the return count of flow graph assert(m_comp->fgReturnCount >= 2); @@ -1321,11 +1348,9 @@ void OptBoolsDsc::optOptimizeBoolsUpdateTrees() (1.0 - origB1TrueLikelihood) + origB1TrueLikelihood * origB2FalseEdge->getLikelihood(); } - // Fix B1 true edge likelihood and min/max weights + // Fix B1 true edge likelihood // origB1TrueEdge->setLikelihood(newB1TrueLikelihood); - weight_t const newB1TrueWeight = m_b1->bbWeight * newB1TrueLikelihood; - origB1TrueEdge->setEdgeWeights(newB1TrueWeight, newB1TrueWeight, m_b1->GetTrueTarget()); assert(m_b1->KindIs(BBJ_COND)); assert(m_b2->KindIs(BBJ_COND)); @@ -1340,11 +1365,9 @@ void OptBoolsDsc::optOptimizeBoolsUpdateTrees() FlowEdge* const newB1FalseEdge = origB2FalseEdge; m_b1->SetFalseEdge(newB1FalseEdge); - // Fix B1 false edge likelihood and min/max weights. + // Fix B1 false edge likelihood // newB1FalseEdge->setLikelihood(1.0 - newB1TrueLikelihood); - weight_t const newB1FalseWeight = m_b1->bbWeight * (1.0 - newB1TrueLikelihood); - newB1FalseEdge->setEdgeWeights(newB1FalseWeight, newB1FalseWeight, m_b1->GetTrueTarget()); } // Get rid of the second block @@ -1388,10 +1411,10 @@ void OptBoolsDsc::optOptimizeBoolsUpdateTrees() // // For example, (x==0 && y==0) generates: // B1: GT_JTRUE (BBJ_COND), jumps to B3 -// B2: GT_RETURN (BBJ_RETURN) -// B3: GT_RETURN (BBJ_RETURN), +// B2: GT_RETURN/GT_SWIFT_ERROR (BBJ_RETURN) +// B3: GT_RETURN/GT_SWIFT_ERROR (BBJ_RETURN), // and it is folded into -// B1: GT_RETURN (BBJ_RETURN) +// B1: GT_RETURN/GT_SWIFT_ERROR (BBJ_RETURN) // bool OptBoolsDsc::optOptimizeBoolsReturnBlock(BasicBlock* b3) { @@ -1530,7 +1553,7 @@ bool OptBoolsDsc::optOptimizeBoolsReturnBlock(BasicBlock* b3) } else if ((m_testInfo1.compTree->gtOper == GT_LT && m_testInfo2.compTree->gtOper == GT_GE) && (it1val == 0 && it2val == 0 && it3val == 0) && - (!m_testInfo1.testTree->AsOp()->gtOp1->IsUnsigned() && !m_testInfo2.testTree->AsOp()->gtOp1->IsUnsigned())) + (!m_testInfo1.GetTestOp()->IsUnsigned() && !m_testInfo2.GetTestOp()->IsUnsigned())) { // Case: x >= 0 && y >= 0 // t1:c1<0 t2:c2>=0 t3:c3==0 @@ -1559,7 +1582,7 @@ bool OptBoolsDsc::optOptimizeBoolsReturnBlock(BasicBlock* b3) } else if ((m_testInfo1.compTree->gtOper == GT_LT && m_testInfo2.compTree->gtOper == GT_LT) && (it1val == 0 && it2val == 0 && it3val == 1) && - (!m_testInfo1.testTree->AsOp()->gtOp1->IsUnsigned() && !m_testInfo2.testTree->AsOp()->gtOp1->IsUnsigned())) + (!m_testInfo1.GetTestOp()->IsUnsigned() && !m_testInfo2.GetTestOp()->IsUnsigned())) { // Case: x < 0 || y < 0 // t1:c1<0 t2:c2<0 t3:c3==1 @@ -1676,7 +1699,7 @@ void OptBoolsDsc::optOptimizeBoolsGcStress() // On success, compTree is set to the compare node (i.e. GT_EQ or GT_NE or GT_LT or GT_GE) of the testTree. // isBool is set to true if the comparand (i.e., operand 1 of compTree is boolean. Otherwise, false. // -// Given a GT_JTRUE or GT_RETURN node, this method checks if it is a boolean comparison +// Given a GT_JTRUE or GT_RETURN/GT_SWIFT_ERROR_RET node, this method checks if it is a boolean comparison // of the form "if (boolVal ==/!=/>=/< 0/1)".This is translated into // a GT_EQ/GT_NE/GT_GE/GT_LT node with "opr1" being a boolean lclVar and "opr2" the const 0/1. // @@ -1687,8 +1710,8 @@ GenTree* OptBoolsDsc::optIsBoolComp(OptTestInfo* pOptTest) { pOptTest->isBool = false; - assert(pOptTest->testTree->gtOper == GT_JTRUE || pOptTest->testTree->gtOper == GT_RETURN); - GenTree* cond = pOptTest->testTree->AsOp()->gtOp1; + assert(pOptTest->testTree->OperIs(GT_JTRUE, GT_RETURN, GT_SWIFT_ERROR_RET)); + GenTree* cond = pOptTest->GetTestOp(); // The condition must be "!= 0" or "== 0" or >=0 or <= 0 or > 0 or < 0 if (!cond->OperIs(GT_EQ, GT_NE, GT_LT, GT_GT, GT_GE, GT_LE)) @@ -1749,13 +1772,13 @@ GenTree* OptBoolsDsc::optIsBoolComp(OptTestInfo* pOptTest) } //----------------------------------------------------------------------------- -// optOptimizeBools: Folds boolean conditionals for GT_JTRUE/GT_RETURN nodes +// optOptimizeBools: Folds boolean conditionals for GT_JTRUE/GT_RETURN/GT_SWIFT_ERROR_RET nodes // // Returns: // suitable phase status // // Notes: -// If the operand of GT_JTRUE/GT_RETURN node is GT_EQ/GT_NE/GT_GE/GT_LE/GT_GT/GT_LT of the form +// If the operand of GT_JTRUE/GT_RETURN/GT_SWIFT_ERROR_RET node is GT_EQ/GT_NE/GT_GE/GT_LE/GT_GT/GT_LT of the form // "if (boolVal ==/!=/>=/< 0/1)", the GT_EQ/GT_NE/GT_GE/GT_LE/GT_GT/GT_LT nodes are translated into a // GT_EQ/GT_NE/GT_GE/GT_LE/GT_GT/GT_LT node with // "op1" being a boolean GT_OR/GT_AND lclVar and diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index ebbd125c1c3c..ffec804fadc9 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -234,7 +234,7 @@ void Compiler::optScaleLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk) for (BasicBlock* const curBlk : BasicBlockRangeList(begBlk, endBlk)) { // Don't change the block weight if it came from profile data. - if (curBlk->hasProfileWeight() && fgHaveProfileData()) + if (curBlk->hasProfileWeight() && fgHaveProfileWeights()) { reportBlockWeight(curBlk, "; unchanged: has profile weight"); continue; @@ -872,8 +872,8 @@ bool Compiler::optComputeLoopRep(int constInit, { noway_assert(genActualType(iterOperType) == TYP_INT); - __int64 constInitX; - __int64 constLimitX; + int64_t constInitX; + int64_t constLimitX; unsigned loopCount; int iterSign; @@ -953,7 +953,7 @@ bool Compiler::optComputeLoopRep(int constInit, switch (testOper) { - __int64 iterAtExitX; + int64_t iterAtExitX; case GT_EQ: // Something like "for (i=init; i == lim; i++)" doesn't make any sense. @@ -2315,54 +2315,6 @@ bool Compiler::optInvertWhileLoop(BasicBlock* block) weightTop); bTest->inheritWeight(bTop); - // Determine the new edge weights. - // - // We project the next/jump ratio for block and bTest by using - // the original likelihoods out of bTest. - // - // Note "next" is the loop top block, not bTest's bbNext, - // we'll call this latter block "after". - // - weight_t const testToNextLikelihood = min(1.0, weightTop / weightTest); - weight_t const testToAfterLikelihood = 1.0 - testToNextLikelihood; - - // Adjust edges out of bTest (which now has weight weightTop) - // - weight_t const testToNextWeight = weightTop * testToNextLikelihood; - weight_t const testToAfterWeight = weightTop * testToAfterLikelihood; - - FlowEdge* const edgeTestToNext = bTest->GetTrueEdge(); - FlowEdge* const edgeTestToAfter = bTest->GetFalseEdge(); - - JITDUMP("Setting weight of " FMT_BB " -> " FMT_BB " to " FMT_WT " (iterate loop)\n", bTest->bbNum, bTop->bbNum, - testToNextWeight); - JITDUMP("Setting weight of " FMT_BB " -> " FMT_BB " to " FMT_WT " (exit loop)\n", bTest->bbNum, - bTest->Next()->bbNum, testToAfterWeight); - - edgeTestToNext->setEdgeWeights(testToNextWeight, testToNextWeight, bTop); - edgeTestToAfter->setEdgeWeights(testToAfterWeight, testToAfterWeight, bTest->GetFalseTarget()); - - // Adjust edges out of block, using the same distribution. - // - JITDUMP("Profile weight of " FMT_BB " remains unchanged at " FMT_WT "\n", block->bbNum, weightBlock); - - weight_t const blockToNextLikelihood = testToNextLikelihood; - weight_t const blockToAfterLikelihood = testToAfterLikelihood; - - weight_t const blockToNextWeight = weightBlock * blockToNextLikelihood; - weight_t const blockToAfterWeight = weightBlock * blockToAfterLikelihood; - - FlowEdge* const edgeBlockToNext = bNewCond->GetFalseEdge(); - FlowEdge* const edgeBlockToAfter = bNewCond->GetTrueEdge(); - - JITDUMP("Setting weight of " FMT_BB " -> " FMT_BB " to " FMT_WT " (enter loop)\n", bNewCond->bbNum, - bNewCond->GetFalseTarget()->bbNum, blockToNextWeight); - JITDUMP("Setting weight of " FMT_BB " -> " FMT_BB " to " FMT_WT " (avoid loop)\n", bNewCond->bbNum, - bNewCond->GetTrueTarget()->bbNum, blockToAfterWeight); - - edgeBlockToNext->setEdgeWeights(blockToNextWeight, blockToNextWeight, bNewCond->GetFalseTarget()); - edgeBlockToAfter->setEdgeWeights(blockToAfterWeight, blockToAfterWeight, bNewCond->GetTrueTarget()); - #ifdef DEBUG // If we're checking profile data, see if profile for the two target blocks is consistent. // @@ -3232,91 +3184,6 @@ bool Compiler::optCanonicalizeExit(FlowGraphNaturalLoop* loop, BasicBlock* exit) return true; } -//----------------------------------------------------------------------------- -// optEstimateEdgeLikelihood: Given a block "from" that may transfer control to -// "to", estimate the likelihood that this will happen taking profile into -// account if available. -// -// Parameters: -// from - From block -// to - To block -// fromProfile - [out] Whether or not the estimate is based on profile data -// -// Returns: -// Estimated likelihood of the edge being taken. -// -weight_t Compiler::optEstimateEdgeLikelihood(BasicBlock* from, BasicBlock* to, bool* fromProfile) -{ - *fromProfile = (from->HasFlag(BBF_PROF_WEIGHT) != BBF_EMPTY) && (to->HasFlag(BBF_PROF_WEIGHT) != BBF_EMPTY); - if (!fgIsUsingProfileWeights() || !from->HasFlag(BBF_PROF_WEIGHT) || !to->HasFlag(BBF_PROF_WEIGHT) || - from->KindIs(BBJ_ALWAYS)) - { - return 1.0 / from->NumSucc(this); - } - - bool useEdgeWeights = fgHaveValidEdgeWeights; - - weight_t takenCount = 0; - weight_t notTakenCount = 0; - - if (useEdgeWeights) - { - from->VisitRegularSuccs(this, [&, to](BasicBlock* succ) { - *fromProfile &= succ->hasProfileWeight(); - FlowEdge* edge = fgGetPredForBlock(succ, from); - weight_t edgeWeight = (edge->edgeWeightMin() + edge->edgeWeightMax()) / 2.0; - - if (succ == to) - { - takenCount += edgeWeight; - } - else - { - notTakenCount += edgeWeight; - } - return BasicBlockVisit::Continue; - }); - - // Watch out for cases where edge weights were not properly maintained - // so that it appears no profile flow goes to 'to'. - // - useEdgeWeights = !fgProfileWeightsConsistent(takenCount, BB_ZERO_WEIGHT); - } - - if (!useEdgeWeights) - { - takenCount = 0; - notTakenCount = 0; - - from->VisitRegularSuccs(this, [&, to](BasicBlock* succ) { - *fromProfile &= succ->hasProfileWeight(); - if (succ == to) - { - takenCount += succ->bbWeight; - } - else - { - notTakenCount += succ->bbWeight; - } - - return BasicBlockVisit::Continue; - }); - } - - if (!*fromProfile) - { - return 1.0 / from->NumSucc(this); - } - - if (fgProfileWeightsConsistent(takenCount, BB_ZERO_WEIGHT)) - { - return 0; - } - - weight_t likelihood = takenCount / (takenCount + notTakenCount); - return likelihood; -} - //----------------------------------------------------------------------------- // optSetWeightForPreheaderOrExit: Set the weight of a newly created preheader // or exit, after it has been added to the flowgraph. @@ -3327,52 +3194,34 @@ weight_t Compiler::optEstimateEdgeLikelihood(BasicBlock* from, BasicBlock* to, b // void Compiler::optSetWeightForPreheaderOrExit(FlowGraphNaturalLoop* loop, BasicBlock* block) { - bool hasProfWeight = true; - - assert(block->GetUniqueSucc() != nullptr); - // Inherit first estimate from the target target; optEstimateEdgeLikelihood - // may use it in its estimate if we do not have edge weights to estimate - // from (we also assume the edges into 'block' already inherited their edge - // weights from the previous edge). - block->inheritWeight(block->GetTarget()); + bool hasProfWeight = true; + weight_t newWeight = BB_ZERO_WEIGHT; - weight_t newWeight = BB_ZERO_WEIGHT; - for (FlowEdge* edge : block->PredEdges()) + for (FlowEdge* const edge : block->PredEdges()) { - BasicBlock* predBlock = edge->getSourceBlock(); - - bool fromProfile = false; - weight_t likelihood = optEstimateEdgeLikelihood(predBlock, block, &fromProfile); - hasProfWeight &= fromProfile; - - weight_t contribution = predBlock->bbWeight * likelihood; - JITDUMP(" Estimated likelihood " FMT_BB " -> " FMT_BB " to be " FMT_WT " (contribution: " FMT_WT ")\n", - predBlock->bbNum, block->bbNum, likelihood, contribution); - - newWeight += contribution; - - // Normalize pred -> new block weight - edge->setEdgeWeights(contribution, contribution, block); + newWeight += edge->getLikelyWeight(); + hasProfWeight &= edge->getSourceBlock()->hasProfileWeight(); } - block->RemoveFlags(BBF_PROF_WEIGHT | BBF_RUN_RARELY); - block->bbWeight = newWeight; + if (hasProfWeight) { block->SetFlags(BBF_PROF_WEIGHT); } + else + { + block->RemoveFlags(BBF_PROF_WEIGHT); + } if (newWeight == BB_ZERO_WEIGHT) { block->SetFlags(BBF_RUN_RARELY); - return; } - - // Normalize block -> target weight - FlowEdge* const edgeFromBlock = block->GetTargetEdge(); - assert(edgeFromBlock != nullptr); - edgeFromBlock->setEdgeWeights(block->bbWeight, block->bbWeight, block->GetTarget()); + else + { + block->RemoveFlags(BBF_RUN_RARELY); + } } /***************************************************************************** @@ -3417,8 +3266,8 @@ bool Compiler::optNarrowTree(GenTree* tree, var_types srct, var_types dstt, Valu /* Constants can usually be narrowed by changing their value */ #ifndef TARGET_64BIT - __int64 lval; - __int64 lmask; + int64_t lval; + int64_t lmask; case GT_CNS_LNG: lval = tree->AsIntConCommon()->LngValue(); @@ -4160,7 +4009,7 @@ bool Compiler::optHoistThisLoop(FlowGraphNaturalLoop* loop, LoopHoistContext* ho hoistCtxt->m_hoistedFPExprCount = 0; } -#ifdef TARGET_XARCH +#ifdef FEATURE_MASKED_HW_INTRINSICS if (!VarSetOps::IsEmpty(this, lvaMaskVars)) { VARSET_TP loopMskVars(VarSetOps::Intersection(this, loopVars, lvaMaskVars)); @@ -4191,7 +4040,7 @@ bool Compiler::optHoistThisLoop(FlowGraphNaturalLoop* loop, LoopHoistContext* ho hoistCtxt->m_loopVarInOutMskCount = 0; hoistCtxt->m_hoistedMskExprCount = 0; } -#endif // TARGET_XARCH +#endif // FEATURE_MASKED_HW_INTRINSICS // Find the set of definitely-executed blocks. // Ideally, the definitely-executed blocks are the ones that post-dominate the entry block. @@ -4313,9 +4162,9 @@ bool Compiler::optHoistThisLoop(FlowGraphNaturalLoop* loop, LoopHoistContext* ho optHoistLoopBlocks(loop, &defExec, hoistCtxt); unsigned numHoisted = hoistCtxt->m_hoistedFPExprCount + hoistCtxt->m_hoistedExprCount; -#ifdef TARGET_XARCH +#ifdef FEATURE_MASKED_HW_INTRINSICS numHoisted += hoistCtxt->m_hoistedMskExprCount; -#endif // TARGET_XARCH +#endif // FEATURE_MASKED_HW_INTRINSICS return numHoisted > 0; } @@ -4347,7 +4196,7 @@ bool Compiler::optIsProfitableToHoistTree(GenTree* tree, FlowGraphNaturalLoop* l } #endif } -#ifdef TARGET_XARCH +#ifdef FEATURE_MASKED_HW_INTRINSICS else if (varTypeUsesMaskReg(tree)) { hoistedExprCount = hoistCtxt->m_hoistedMskExprCount; @@ -4360,7 +4209,7 @@ bool Compiler::optIsProfitableToHoistTree(GenTree* tree, FlowGraphNaturalLoop* l availRegCount += CNT_CALLEE_TRASH_MASK - 1; } } -#endif // TARGET_XARCH +#endif // FEATURE_MASKED_HW_INTRINSICS else { assert(varTypeUsesFloatReg(tree)); @@ -4899,7 +4748,7 @@ void Compiler::optHoistLoopBlocks(FlowGraphNaturalLoop* loop, if (op1->OperIs(GT_CALL)) { GenTreeCall* call = op1->AsCall(); - if ((call->gtCallType == CT_HELPER) && + if (call->IsHelperCall() && s_helperCallProperties.MayRunCctor(eeGetHelperNum(call->gtCallMethHnd))) { // Hoisting the comma is ok because it would hoist the initialization along @@ -4945,7 +4794,7 @@ void Compiler::optHoistLoopBlocks(FlowGraphNaturalLoop* loop, if (treeIsHoistable && tree->IsCall()) { GenTreeCall* call = tree->AsCall(); - if (call->gtCallType != CT_HELPER) + if (!call->IsHelperCall()) { INDEBUG(failReason = "non-helper call";) treeIsHoistable = false; @@ -5027,7 +4876,7 @@ void Compiler::optHoistLoopBlocks(FlowGraphNaturalLoop* loop, // Further, if it may run a cctor, it must be labeled as "Hoistable" // (meaning it won't run a cctor because the class is not precise-init). GenTreeCall* call = tree->AsCall(); - if (call->gtCallType != CT_HELPER) + if (!call->IsHelperCall()) { m_beforeSideEffect = false; } @@ -5203,7 +5052,7 @@ void Compiler::optHoistCandidate(GenTree* tree, FlowGraphNaturalLoop* loop, LoopHoistContext* hoistCtxt) { - // It must pass the hoistable profitablity tests for this loop level + // It must pass the hoistable profitability tests for this loop level if (!optIsProfitableToHoistTree(tree, loop, hoistCtxt)) { JITDUMP(" ... not profitable to hoist\n"); @@ -5263,12 +5112,12 @@ void Compiler::optHoistCandidate(GenTree* tree, } #endif } -#ifdef TARGET_XARCH +#ifdef FEATURE_MASKED_HW_INTRINSICS else if (varTypeUsesMaskReg(tree)) { hoistCtxt->m_hoistedMskExprCount++; } -#endif // TARGET_XARCH +#endif // FEATURE_MASKED_HW_INTRINSICS else { assert(varTypeUsesFloatReg(tree)); @@ -5467,8 +5316,6 @@ PhaseStatus Compiler::fgCanonicalizeFirstBB() assert(!fgFirstBBisScratch()); fgEnsureFirstBBisScratch(); - // TODO-Quirk: Remove - fgCanonicalizedFirstBB = true; return PhaseStatus::MODIFIED_EVERYTHING; } @@ -5522,7 +5369,7 @@ void Compiler::optComputeInterestingVarSets() #ifndef TARGET_64BIT VarSetOps::AssignNoCopy(this, lvaLongVars, VarSetOps::MakeEmpty(this)); #endif -#ifdef TARGET_XARCH +#ifdef FEATURE_MASKED_HW_INTRINSICS VarSetOps::AssignNoCopy(this, lvaMaskVars, VarSetOps::MakeEmpty(this)); #endif @@ -5541,12 +5388,12 @@ void Compiler::optComputeInterestingVarSets() VarSetOps::AddElemD(this, lvaLongVars, varDsc->lvVarIndex); } #endif -#ifdef TARGET_XARCH +#ifdef FEATURE_MASKED_HW_INTRINSICS else if (varTypeUsesMaskReg(varDsc->lvType)) { VarSetOps::AddElemD(this, lvaMaskVars, varDsc->lvVarIndex); } -#endif // TARGET_XARCH +#endif // FEATURE_MASKED_HW_INTRINSICS } } } @@ -5759,7 +5606,7 @@ void Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk, FlowGraphNatura // Record that this loop contains a call AddContainsCallAllContainingLoops(mostNestedLoop); - if (call->gtCallType == CT_HELPER) + if (call->IsHelperCall()) { CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd); if (s_helperCallProperties.MutatesHeap(helpFunc)) diff --git a/src/coreclr/jit/phase.cpp b/src/coreclr/jit/phase.cpp index 199167d7d0c5..9723c123137e 100644 --- a/src/coreclr/jit/phase.cpp +++ b/src/coreclr/jit/phase.cpp @@ -152,37 +152,39 @@ void Phase::PostPhase(PhaseStatus status) if (doPostPhase && doPostPhaseChecks) { - if ((comp->activePhaseChecks & PhaseChecks::CHECK_UNIQUE) == PhaseChecks::CHECK_UNIQUE) + PhaseChecks const checks = comp->activePhaseChecks; + + if (hasFlag(checks, PhaseChecks::CHECK_UNIQUE)) { comp->fgDebugCheckNodesUniqueness(); } - if ((comp->activePhaseChecks & PhaseChecks::CHECK_FG) == PhaseChecks::CHECK_FG) + if (hasFlag(checks, PhaseChecks::CHECK_FG)) { comp->fgDebugCheckBBlist(); } - if ((comp->activePhaseChecks & PhaseChecks::CHECK_IR) == PhaseChecks::CHECK_IR) + if (hasFlag(checks, PhaseChecks::CHECK_IR)) { comp->fgDebugCheckLinks(); } - if ((comp->activePhaseChecks & PhaseChecks::CHECK_EH) == PhaseChecks::CHECK_EH) + if (hasFlag(checks, PhaseChecks::CHECK_EH)) { comp->fgVerifyHandlerTab(); } - if ((comp->activePhaseChecks & PhaseChecks::CHECK_LOOPS) == PhaseChecks::CHECK_LOOPS) + if (hasFlag(checks, PhaseChecks::CHECK_LOOPS)) { comp->fgDebugCheckLoops(); } - if ((comp->activePhaseChecks & PhaseChecks::CHECK_PROFILE) == PhaseChecks::CHECK_PROFILE) + if (hasFlag(checks, PhaseChecks::CHECK_PROFILE) || hasFlag(checks, PhaseChecks::CHECK_LIKELIHOODS)) { - comp->fgDebugCheckProfileWeights(); + comp->fgDebugCheckProfile(checks); } - if ((comp->activePhaseChecks & PhaseChecks::CHECK_LINKED_LOCALS) == PhaseChecks::CHECK_LINKED_LOCALS) + if (hasFlag(checks, PhaseChecks::CHECK_LINKED_LOCALS)) { comp->fgDebugCheckLinkedLocals(); } diff --git a/src/coreclr/jit/promotion.cpp b/src/coreclr/jit/promotion.cpp index e02a5f0e06ba..b656f1576d0d 100644 --- a/src/coreclr/jit/promotion.cpp +++ b/src/coreclr/jit/promotion.cpp @@ -1446,9 +1446,8 @@ class LocalsUseVisitor : public GenTreeVisitor flags |= AccessKindFlags::IsStoreSource; } - if (user->OperIs(GT_RETURN)) + if (user->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)) { - assert(user->gtGetOp1()->gtEffectiveVal() == lcl); flags |= AccessKindFlags::IsReturned; } #endif @@ -1927,8 +1926,8 @@ void ReplaceVisitor::StartBlock(BasicBlock* block) #endif // OSR locals and parameters may need an initial read back, which we mark - // when we start the scratch BB. - if (!m_compiler->fgBBisScratch(block)) + // when we start the initial BB. + if (block != m_compiler->fgFirstBB) { return; } @@ -1941,7 +1940,7 @@ void ReplaceVisitor::StartBlock(BasicBlock* block) continue; } - JITDUMP("Marking fields of %s V%02u as needing read-back in scratch " FMT_BB "\n", + JITDUMP("Marking fields of %s V%02u as needing read-back in entry BB " FMT_BB "\n", dsc->lvIsParam ? "parameter" : "OSR-local", agg->LclNum, block->bbNum); for (size_t i = 0; i < agg->Replacements.size(); i++) @@ -1955,7 +1954,7 @@ void ReplaceVisitor::StartBlock(BasicBlock* block) } else { - JITDUMP(" V%02u (%s) not marked (not live-in to scratch BB)\n", rep.LclNum, rep.Description); + JITDUMP(" V%02u (%s) not marked (not live-in to entry BB)\n", rep.LclNum, rep.Description); } } } @@ -2546,7 +2545,7 @@ void ReplaceVisitor::ReplaceLocal(GenTree** use, GenTree* user) JITDUMP("Processing struct use [%06u] of V%02u.[%03u..%03u)\n", Compiler::dspTreeID(lcl), lclNum, offs, offs + lcl->GetLayout(m_compiler)->GetSize()); - assert(effectiveUser->OperIs(GT_CALL, GT_RETURN)); + assert(effectiveUser->OperIs(GT_CALL, GT_RETURN, GT_SWIFT_ERROR_RET)); unsigned size = lcl->GetLayout(m_compiler)->GetSize(); WriteBackBeforeUse(use, lclNum, lcl->GetLclOffs(), size); @@ -2841,21 +2840,9 @@ PhaseStatus Promotion::Run() return PhaseStatus::MODIFIED_NOTHING; } - // Check for parameters and OSR locals that need to be read back on entry - // to the function. - for (AggregateInfo* agg : aggregates) - { - LclVarDsc* dsc = m_compiler->lvaGetDesc(agg->LclNum); - if (dsc->lvIsParam || dsc->lvIsOSRLocal) - { - // We will need an initial readback. We create the scratch BB ahead - // of time so that we get correct liveness and mark the - // parameters/OSR-locals as requiring read-back as part of - // ReplaceVisitor::StartBlock when we get to the scratch block. - m_compiler->fgEnsureFirstBBisScratch(); - break; - } - } + // We should have a proper entry BB where we can put IR that will only be + // run once into. This is a precondition of the phase. + assert(m_compiler->fgFirstBB->bbPreds == nullptr); // Compute liveness for the fields and remainders. PromotionLiveness liveness(m_compiler, aggregates); @@ -3011,8 +2998,8 @@ void Promotion::ExplicitlyZeroInitReplacementLocals(unsigned //------------------------------------------------------------------------ // Promotion::InsertInitStatement: -// Insert a new statement after the specified statement in the scratch block, -// or at the beginning of the scratch block if no other statements were +// Insert a new statement after the specified statement in the entry block, +// or at the beginning of the entry block if no other statements were // inserted yet. // // Parameters: @@ -3021,7 +3008,6 @@ void Promotion::ExplicitlyZeroInitReplacementLocals(unsigned // void Promotion::InsertInitStatement(Statement** prevStmt, GenTree* tree) { - m_compiler->fgEnsureFirstBBisScratch(); Statement* stmt = m_compiler->fgNewStmtFromTree(tree); if (*prevStmt != nullptr) { diff --git a/src/coreclr/jit/rangecheck.cpp b/src/coreclr/jit/rangecheck.cpp index 2328dba7d636..1fb068068e84 100644 --- a/src/coreclr/jit/rangecheck.cpp +++ b/src/coreclr/jit/rangecheck.cpp @@ -353,7 +353,7 @@ void RangeCheck::OptimizeRangeCheck(BasicBlock* block, Statement* stmt, GenTree* return; } - if (DoesOverflow(block, treeIndex)) + if (DoesOverflow(block, treeIndex, range)) { JITDUMP("Method determined to overflow.\n"); return; @@ -773,6 +773,22 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse isConstantAssertion = true; } + // Current assertion asserts a bounds check does not throw + else if (curAssertion->IsBoundsCheckNoThrow()) + { + ValueNum indexVN = curAssertion->op1.bnd.vnIdx; + ValueNum lenVN = curAssertion->op1.bnd.vnLen; + if (normalLclVN == indexVN) + { + isUnsigned = true; + cmpOper = GT_LT; + limit = Limit(Limit::keBinOpArray, lenVN, 0); + } + else + { + continue; + } + } // Current assertion is not supported, ignore it else { @@ -782,7 +798,8 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse assert(limit.IsBinOpArray() || limit.IsConstant()); // Make sure the assertion is of the form != 0 or == 0 if it isn't a constant assertion. - if (!isConstantAssertion && (curAssertion->op2.vn != m_pCompiler->vnStore->VNZeroForType(TYP_INT))) + if (!isConstantAssertion && (curAssertion->assertionKind != Compiler::OAK_NO_THROW) && + (curAssertion->op2.vn != m_pCompiler->vnStore->VNZeroForType(TYP_INT))) { continue; } @@ -849,10 +866,37 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse continue; } - // Doesn't tighten the current bound. So skip. - if (pRange->uLimit.IsConstant() && limit.vn != arrLenVN) + // Skip if it doesn't tighten the current bound: + if (pRange->uLimit.IsConstant() && ((cmpOper == GT_LE) || (cmpOper == GT_LT))) { - continue; + if (!limit.IsConstant() && (limit.vn != arrLenVN)) + { + // If our new limit is not constant and doesn't represent the array's length - bail out. + // NOTE: it's fine to replace the current constant limit with a non-constant arrLenVN. + continue; + } + if (limit.IsConstant() && (limit.cns > pRange->uLimit.cns)) + { + // The new constant limit doesn't tighten the current constant bound. + // E.g. current is "X < 10" and the new one is "X < 100" + continue; + } + } + // Same for the lower bound: + if (pRange->lLimit.IsConstant() && ((cmpOper == GT_GE) || (cmpOper == GT_GT))) + { + if (!limit.IsConstant() && (limit.vn != arrLenVN)) + { + // If our new limit is not constant and doesn't represent the array's length - bail out. + // NOTE: it's fine to replace the current constant limit with a non-constant arrLenVN. + continue; + } + if (limit.IsConstant() && (limit.cns < pRange->lLimit.cns)) + { + // The new constant limit doesn't tighten the current constant bound. + // E.g. current is "X > 10" and the new one is "X > 5" + continue; + } } // Check if the incoming limit from assertions tightens the existing upper limit. @@ -1235,17 +1279,17 @@ bool RangeCheck::MultiplyOverflows(Limit& limit1, Limit& limit2) } // Does the bin operation overflow. -bool RangeCheck::DoesBinOpOverflow(BasicBlock* block, GenTreeOp* binop) +bool RangeCheck::DoesBinOpOverflow(BasicBlock* block, GenTreeOp* binop, const Range& range) { GenTree* op1 = binop->gtGetOp1(); GenTree* op2 = binop->gtGetOp2(); - if (!m_pSearchPath->Lookup(op1) && DoesOverflow(block, op1)) + if (!m_pSearchPath->Lookup(op1) && DoesOverflow(block, op1, range)) { return true; } - if (!m_pSearchPath->Lookup(op2) && DoesOverflow(block, op2)) + if (!m_pSearchPath->Lookup(op2) && DoesOverflow(block, op2, range)) { return true; } @@ -1279,7 +1323,7 @@ bool RangeCheck::DoesBinOpOverflow(BasicBlock* block, GenTreeOp* binop) } // Check if the var definition the rhs involves arithmetic that overflows. -bool RangeCheck::DoesVarDefOverflow(GenTreeLclVarCommon* lcl) +bool RangeCheck::DoesVarDefOverflow(BasicBlock* block, GenTreeLclVarCommon* lcl, const Range& range) { LclSsaVarDsc* ssaDef = GetSsaDefStore(lcl); if (ssaDef == nullptr) @@ -1291,10 +1335,25 @@ bool RangeCheck::DoesVarDefOverflow(GenTreeLclVarCommon* lcl) } return true; } - return DoesOverflow(ssaDef->GetBlock(), ssaDef->GetDefNode()->Data()); + + // We can use intermediate assertions about the local to prove that any + // overflow on this path does not matter for the range computed. + Range assertionRange = Range(Limit(Limit::keUnknown)); + MergeAssertion(block, lcl, &assertionRange DEBUGARG(0)); + + // But only if the range from the assertion is more strict than the global + // range computed; otherwise we might still have used the def's value to + // tighten the range of the global range. + Range merged = RangeOps::Merge(range, assertionRange, false); + if (merged.LowerLimit().Equals(range.LowerLimit()) && merged.UpperLimit().Equals(range.UpperLimit())) + { + return false; + } + + return DoesOverflow(ssaDef->GetBlock(), ssaDef->GetDefNode()->Data(), range); } -bool RangeCheck::DoesPhiOverflow(BasicBlock* block, GenTree* expr) +bool RangeCheck::DoesPhiOverflow(BasicBlock* block, GenTree* expr, const Range& range) { for (GenTreePhi::Use& use : expr->AsPhi()->Uses()) { @@ -1303,7 +1362,7 @@ bool RangeCheck::DoesPhiOverflow(BasicBlock* block, GenTree* expr) { continue; } - if (DoesOverflow(block, arg)) + if (DoesOverflow(block, arg, range)) { return true; } @@ -1311,17 +1370,30 @@ bool RangeCheck::DoesPhiOverflow(BasicBlock* block, GenTree* expr) return false; } -bool RangeCheck::DoesOverflow(BasicBlock* block, GenTree* expr) +//------------------------------------------------------------------------ +// DoesOverflow: Check if the computation of "expr" may have overflowed. +// +// Arguments: +// block - the block that contains `expr` +// expr - expression to check overflow of +// range - range that we believe "expr" to be in without accounting for +// overflow; used to ignore potential overflow on paths where +// we can prove the value is in this range regardless. +// +// Return value: +// True if the computation may have involved an impactful overflow. +// +bool RangeCheck::DoesOverflow(BasicBlock* block, GenTree* expr, const Range& range) { bool overflows = false; if (!GetOverflowMap()->Lookup(expr, &overflows)) { - overflows = ComputeDoesOverflow(block, expr); + overflows = ComputeDoesOverflow(block, expr, range); } return overflows; } -bool RangeCheck::ComputeDoesOverflow(BasicBlock* block, GenTree* expr) +bool RangeCheck::ComputeDoesOverflow(BasicBlock* block, GenTree* expr, const Range& range) { JITDUMP("Does overflow [%06d]?\n", Compiler::dspTreeID(expr)); m_pSearchPath->Set(expr, block, SearchPath::Overwrite); @@ -1343,17 +1415,17 @@ bool RangeCheck::ComputeDoesOverflow(BasicBlock* block, GenTree* expr) } else if (expr->OperIs(GT_COMMA)) { - overflows = ComputeDoesOverflow(block, expr->gtEffectiveVal()); + overflows = ComputeDoesOverflow(block, expr->gtEffectiveVal(), range); } // Check if the var def has rhs involving arithmetic that overflows. else if (expr->IsLocal()) { - overflows = DoesVarDefOverflow(expr->AsLclVarCommon()); + overflows = DoesVarDefOverflow(block, expr->AsLclVarCommon(), range); } // Check if add overflows. else if (expr->OperIs(GT_ADD, GT_MUL)) { - overflows = DoesBinOpOverflow(block, expr->AsOp()); + overflows = DoesBinOpOverflow(block, expr->AsOp(), range); } // These operators don't overflow. // Actually, GT_LSH can overflow so it depends on the analysis done in ComputeRangeForBinOp @@ -1364,11 +1436,11 @@ bool RangeCheck::ComputeDoesOverflow(BasicBlock* block, GenTree* expr) // Walk through phi arguments to check if phi arguments involve arithmetic that overflows. else if (expr->OperIs(GT_PHI)) { - overflows = DoesPhiOverflow(block, expr); + overflows = DoesPhiOverflow(block, expr, range); } else if (expr->OperIs(GT_CAST)) { - overflows = ComputeDoesOverflow(block, expr->gtGetOp1()); + overflows = ComputeDoesOverflow(block, expr->gtGetOp1(), range); } GetOverflowMap()->Set(expr, overflows, OverflowMap::Overwrite); m_pSearchPath->Remove(expr); diff --git a/src/coreclr/jit/rangecheck.h b/src/coreclr/jit/rangecheck.h index 9d7b06438717..de44b88d3ae5 100644 --- a/src/coreclr/jit/rangecheck.h +++ b/src/coreclr/jit/rangecheck.h @@ -199,7 +199,7 @@ struct Limit return false; } - bool Equals(Limit& l) + bool Equals(const Limit& l) const { switch (type) { @@ -262,11 +262,21 @@ struct Range { } + const Limit& UpperLimit() const + { + return uLimit; + } + Limit& UpperLimit() { return uLimit; } + const Limit& LowerLimit() const + { + return lLimit; + } + Limit& LowerLimit() { return lLimit; @@ -440,12 +450,12 @@ struct RangeOps // Given two ranges "r1" and "r2", do a Phi merge. If "monIncreasing" is true, // then ignore the dependent variables for the lower bound but not for the upper bound. - static Range Merge(Range& r1, Range& r2, bool monIncreasing) + static Range Merge(const Range& r1, const Range& r2, bool monIncreasing) { - Limit& r1lo = r1.LowerLimit(); - Limit& r1hi = r1.UpperLimit(); - Limit& r2lo = r2.LowerLimit(); - Limit& r2hi = r2.UpperLimit(); + const Limit& r1lo = r1.LowerLimit(); + const Limit& r1hi = r1.UpperLimit(); + const Limit& r2lo = r2.LowerLimit(); + const Limit& r2hi = r2.UpperLimit(); // Take care of lo part. Range result = Limit(Limit::keUnknown); @@ -689,19 +699,19 @@ class RangeCheck bool MultiplyOverflows(Limit& limit1, Limit& limit2); // Does the binary operation between the operands overflow? Check recursively. - bool DoesBinOpOverflow(BasicBlock* block, GenTreeOp* binop); + bool DoesBinOpOverflow(BasicBlock* block, GenTreeOp* binop, const Range& range); // Do the phi operands involve a definition that could overflow? - bool DoesPhiOverflow(BasicBlock* block, GenTree* expr); + bool DoesPhiOverflow(BasicBlock* block, GenTree* expr, const Range& range); // Find the def of the "expr" local and recurse on the arguments if any of them involve a // calculation that overflows. - bool DoesVarDefOverflow(GenTreeLclVarCommon* lcl); + bool DoesVarDefOverflow(BasicBlock* block, GenTreeLclVarCommon* lcl, const Range& range); - bool ComputeDoesOverflow(BasicBlock* block, GenTree* expr); + bool ComputeDoesOverflow(BasicBlock* block, GenTree* expr, const Range& range); - // Does the current "expr" which is a use involve a definition, that overflows. - bool DoesOverflow(BasicBlock* block, GenTree* tree); + // Does the current "expr", which is a use, involve a definition that overflows. + bool DoesOverflow(BasicBlock* block, GenTree* tree, const Range& range); // Widen the range by first checking if the induction variable is monotonically increasing. // Requires "pRange" to be partially computed. diff --git a/src/coreclr/jit/redundantbranchopts.cpp b/src/coreclr/jit/redundantbranchopts.cpp index d4a678875848..ce5a2733f053 100644 --- a/src/coreclr/jit/redundantbranchopts.cpp +++ b/src/coreclr/jit/redundantbranchopts.cpp @@ -509,66 +509,11 @@ void Compiler::optRelopImpliesRelop(RelopImplicationInfo* rii) } } - // Given R(x, cns1) and R*(x, cns2) see if we can infer R* from R. - // We assume cns1 and cns2 are always on the RHS of the compare. - if ((treeApp.m_args[0] == domApp.m_args[0]) && vnStore->IsVNConstant(treeApp.m_args[1]) && - vnStore->IsVNConstant(domApp.m_args[1]) && varTypeIsIntOrI(vnStore->TypeOfVN(treeApp.m_args[1])) && - vnStore->TypeOfVN(domApp.m_args[0]) == vnStore->TypeOfVN(treeApp.m_args[1]) && - vnStore->TypeOfVN(domApp.m_args[1]) == vnStore->TypeOfVN(treeApp.m_args[1])) + if (((treeApp.m_args[0] == domApp.m_args[0]) || (treeApp.m_args[0] == domApp.m_args[1]) || + (treeApp.m_args[1] == domApp.m_args[0]) || (treeApp.m_args[1] == domApp.m_args[1])) && + optRelopTryInferWithOneEqualOperand(domApp, treeApp, rii)) { - // We currently don't handle VNF_relop_UN funcs here - if (ValueNumStore::VNFuncIsSignedComparison(domApp.m_func) && - ValueNumStore::VNFuncIsSignedComparison(treeApp.m_func)) - { - // Dominating "X relop CNS" - const genTreeOps domOper = static_cast(domApp.m_func); - const target_ssize_t domCns = vnStore->CoercedConstantValue(domApp.m_args[1]); - - // Dominated "X relop CNS" - const genTreeOps treeOper = static_cast(treeApp.m_func); - const target_ssize_t treeCns = vnStore->CoercedConstantValue(treeApp.m_args[1]); - - // Example: - // - // void Test(int x) - // { - // if (x > 100) - // if (x > 10) - // Console.WriteLine("Taken!"); - // } - // - - // Corresponding BB layout: - // - // BB1: - // if (x <= 100) - // goto BB4 - // - // BB2: - // // x is known to be > 100 here - // if (x <= 10) // never true - // goto BB4 - // - // BB3: - // Console.WriteLine("Taken!"); - // - // BB4: - // return; - - // Check whether the dominating compare being "false" implies the dominated compare is known - // to be either "true" or "false". - RelopResult treeOperStatus = - IsCmp2ImpliedByCmp1(GenTree::ReverseRelop(domOper), domCns, treeOper, treeCns); - if (treeOperStatus != RelopResult::Unknown) - { - rii->canInfer = true; - rii->vnRelation = ValueNumStore::VN_RELATION_KIND::VRK_Inferred; - rii->canInferFromTrue = false; - rii->canInferFromFalse = true; - rii->reverseSense = treeOperStatus == RelopResult::AlwaysTrue; - return; - } - } + return; } } @@ -646,6 +591,115 @@ void Compiler::optRelopImpliesRelop(RelopImplicationInfo* rii) } } +//------------------------------------------------------------------------ +// optRelopTryInferWithOneEqualOperand: Given a domnating relop R(x, y) and +// another relop R*(a, b) that share an operand, try to see if we can infer +// something about R*(a, b). +// +// Arguments: +// domApp - The dominating relop R*(x, y) +// treeApp - The dominated relop R*(a, b) +// rii - [out] struct with relop implication information +// +// Returns: +// True if something was inferred; otherwise false. +// +bool Compiler::optRelopTryInferWithOneEqualOperand(const VNFuncApp& domApp, + const VNFuncApp& treeApp, + RelopImplicationInfo* rii) +{ + // Canonicalize constants to be on the right. + VNFunc domFunc = domApp.m_func; + ValueNum domOp1 = domApp.m_args[0]; + ValueNum domOp2 = domApp.m_args[1]; + + VNFunc treeFunc = treeApp.m_func; + ValueNum treeOp1 = treeApp.m_args[0]; + ValueNum treeOp2 = treeApp.m_args[1]; + + if (vnStore->IsVNConstant(domOp1)) + { + std::swap(domOp1, domOp2); + domFunc = ValueNumStore::SwapRelop(domFunc); + } + + if (vnStore->IsVNConstant(treeOp1)) + { + std::swap(treeOp1, treeOp2); + treeFunc = ValueNumStore::SwapRelop(treeFunc); + } + + // Given R(x, cns1) and R*(x, cns2) see if we can infer R* from R. + if ((treeOp1 != domOp1) || !vnStore->IsVNConstant(treeOp2) || !vnStore->IsVNConstant(domOp2)) + { + return false; + } + + var_types treeOp1Type = vnStore->TypeOfVN(treeOp1); + var_types treeOp2Type = vnStore->TypeOfVN(treeOp2); + var_types domOp1Type = vnStore->TypeOfVN(domOp1); + var_types domOp2Type = vnStore->TypeOfVN(domOp2); + if (!varTypeIsIntOrI(treeOp1Type) || (domOp1Type != treeOp2Type) || (domOp2Type != treeOp2Type)) + { + return false; + } + // We currently don't handle VNF_relop_UN funcs here + if (!ValueNumStore::VNFuncIsSignedComparison(domFunc) || !ValueNumStore::VNFuncIsSignedComparison(treeFunc)) + { + return false; + } + + // Dominating "X relop CNS" + const genTreeOps domOper = static_cast(domFunc); + const target_ssize_t domCns = vnStore->CoercedConstantValue(domOp2); + + // Dominated "X relop CNS" + const genTreeOps treeOper = static_cast(treeFunc); + const target_ssize_t treeCns = vnStore->CoercedConstantValue(treeOp2); + + // Example: + // + // void Test(int x) + // { + // if (x > 100) + // if (x > 10) + // Console.WriteLine("Taken!"); + // } + // + + // Corresponding BB layout: + // + // BB1: + // if (x <= 100) + // goto BB4 + // + // BB2: + // // x is known to be > 100 here + // if (x <= 10) // never true + // goto BB4 + // + // BB3: + // Console.WriteLine("Taken!"); + // + // BB4: + // return; + + // Check whether the dominating compare being "false" implies the dominated compare is known + // to be either "true" or "false". + RelopResult treeOperStatus = IsCmp2ImpliedByCmp1(GenTree::ReverseRelop(domOper), domCns, treeOper, treeCns); + if (treeOperStatus == RelopResult::Unknown) + { + return false; + } + + rii->canInfer = true; + rii->vnRelation = ValueNumStore::VN_RELATION_KIND::VRK_Inferred; + rii->canInferFromTrue = false; + rii->canInferFromFalse = true; + rii->reverseSense = treeOperStatus == RelopResult::AlwaysTrue; + return true; +} + //------------------------------------------------------------------------ // optRedundantBranch: try and optimize a possibly redundant branch // diff --git a/src/coreclr/jit/regalloc.cpp b/src/coreclr/jit/regalloc.cpp index ea33ea50cf41..ba07086a63c2 100644 --- a/src/coreclr/jit/regalloc.cpp +++ b/src/coreclr/jit/regalloc.cpp @@ -377,7 +377,7 @@ void Compiler::raMarkStkVars() // to the GC, as the frame offsets in these local variables would // not be correct. - if (varDsc->lvIsParam && raIsVarargsStackArg(lclNum)) + if (varDsc->lvIsParam && lvaIsArgAccessedViaVarArgsCookie(lclNum)) { if (!varDsc->lvPromoted && !varDsc->lvIsStructField) { diff --git a/src/coreclr/jit/register.h b/src/coreclr/jit/register.h index 7da6372012ec..7d04cf3534ac 100644 --- a/src/coreclr/jit/register.h +++ b/src/coreclr/jit/register.h @@ -68,10 +68,10 @@ REGALIAS(EDI, RDI) #ifdef TARGET_AMD64 #define XMMBASE 16 -#define XMMMASK(x) ((__int64)(1) << ((x)+XMMBASE)) +#define XMMMASK(x) ((int64_t)(1) << ((x)+XMMBASE)) #define KBASE 48 -#define KMASK(x) ((__int64)(1) << ((x)+KBASE)) +#define KMASK(x) ((int64_t)(1) << ((x)+KBASE)) #elif defined(TARGET_WASM) #define XMMBASE 16 @@ -79,10 +79,10 @@ REGALIAS(EDI, RDI) #else // !TARGET_AMD64 #define XMMBASE 8 -#define XMMMASK(x) ((__int32)(1) << ((x)+XMMBASE)) +#define XMMMASK(x) ((int32_t)(1) << ((x)+XMMBASE)) #define KBASE 16 -#define KMASK(x) ((__int32)(1) << ((x)+KBASE)) +#define KMASK(x) ((int32_t)(1) << ((x)+KBASE)) #endif // !TARGET_AMD64 diff --git a/src/coreclr/jit/registerarm.h b/src/coreclr/jit/registerarm.h index ad70eaa211cc..dfebf8199047 100644 --- a/src/coreclr/jit/registerarm.h +++ b/src/coreclr/jit/registerarm.h @@ -32,7 +32,7 @@ REGDEF(LR, 14, 0x4000, "lr" ) REGDEF(PC, 15, 0x8000, "pc" ) #define FPBASE 16 -#define VFPMASK(x) (((__int64)1) << (x+FPBASE)) +#define VFPMASK(x) (((int64_t)1) << (x+FPBASE)) REGDEF(F0, 0+FPBASE, VFPMASK(0), "f0") REGDEF(F1, 1+FPBASE, VFPMASK(1), "f1") diff --git a/src/coreclr/jit/regset.cpp b/src/coreclr/jit/regset.cpp index 151b42fdc8ef..b1752cc9fe9a 100644 --- a/src/coreclr/jit/regset.cpp +++ b/src/coreclr/jit/regset.cpp @@ -952,21 +952,18 @@ regNumber genRegArgNext(regNumber argReg) /***************************************************************************** * - * The following table determines the order in which callee-saved registers - * are encoded in GC information at call sites (perhaps among other things). - * In any case, they establish a mapping from ordinal callee-save reg "indices" to - * register numbers and corresponding bitmaps. + * The following table determines the order in which callee registers + * are encoded in GC information at call sites. */ -const regNumber raRegCalleeSaveOrder[] = {REG_CALLEE_SAVED_ORDER}; -const regMaskTP raRbmCalleeSaveOrder[] = {RBM_CALLEE_SAVED_ORDER}; +const regMaskTP raRbmCalleeSaveOrder[] = {RBM_CALL_GC_REGS_ORDER}; regMaskSmall genRegMaskFromCalleeSavedMask(unsigned short calleeSaveMask) { regMaskSmall res = 0; - for (int i = 0; i < CNT_CALLEE_SAVED; i++) + for (int i = 0; i < CNT_CALL_GC_REGS; i++) { - if ((calleeSaveMask & ((regMaskTP)1 << i)) != 0) + if ((calleeSaveMask & (1 << i)) != 0) { res |= raRbmCalleeSaveOrder[i]; } diff --git a/src/coreclr/jit/regset.h b/src/coreclr/jit/regset.h index dae93baebad3..20b55610594f 100644 --- a/src/coreclr/jit/regset.h +++ b/src/coreclr/jit/regset.h @@ -158,8 +158,9 @@ class RegSet regMaskTP _rsMaskVars; // backing store for rsMaskVars property #if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) + // TODO: the funclet's callee-saved registers should not shared with main function. regMaskTP rsMaskCalleeSaved; // mask of the registers pushed/popped in the prolog/epilog -#endif // TARGET_ARMARCH || TARGET_LOONGARCH64 +#endif // TARGET_ARMARCH || TARGET_LOONGARCH64 || TARGET_RISCV64 public: // TODO-Cleanup: Should be private, but Compiler uses it regMaskTP rsMaskResvd; // mask of the registers that are reserved for special purposes (typically empty) diff --git a/src/coreclr/jit/scev.cpp b/src/coreclr/jit/scev.cpp index 491ee4ab06f0..ef3f86b0f133 100644 --- a/src/coreclr/jit/scev.cpp +++ b/src/coreclr/jit/scev.cpp @@ -935,7 +935,10 @@ Scev* ScalarEvolutionContext::Simplify(Scev* scev) { // TODO-Cleanup: This requires some proof that it is ok, but // currently we do not rely on this. - return op1; + ScevAddRec* addRec = (ScevAddRec*)op1; + Scev* newStart = Simplify(NewExtension(unop->Oper, TYP_LONG, addRec->Start)); + Scev* newStep = Simplify(NewExtension(unop->Oper, TYP_LONG, addRec->Step)); + return NewAddRec(newStart, newStep); } return (op1 == unop->Op1) ? unop : NewExtension(unop->Oper, unop->Type, op1); diff --git a/src/coreclr/jit/simd.h b/src/coreclr/jit/simd.h index 3a5311aaaa79..a388eecebdf3 100644 --- a/src/coreclr/jit/simd.h +++ b/src/coreclr/jit/simd.h @@ -4,6 +4,17 @@ #ifndef _SIMD_H_ #define _SIMD_H_ +template +static bool ElementsAreSame(T* array, size_t size) +{ + for (size_t i = 1; i < size; i++) + { + if (array[0] != array[i]) + return false; + } + return true; +} + struct simd8_t { union diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 9ffd3b7b011d..f2df3915088c 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -253,7 +253,8 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, - GenTree* newobjThis) + GenTree* newobjThis, + bool mustExpand) { if (!IsBaselineSimdIsaSupported()) { @@ -371,7 +372,8 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, if (hwIntrinsic == intrinsic) { // The SIMD intrinsic requires special handling outside the normal code path - return impSimdAsHWIntrinsicSpecial(intrinsic, clsHnd, sig, retType, simdBaseJitType, simdSize, newobjThis); + return impSimdAsHWIntrinsicSpecial(intrinsic, clsHnd, sig, retType, simdBaseJitType, simdSize, newobjThis, + mustExpand); } CORINFO_InstructionSet hwIntrinsicIsa = HWIntrinsicInfo::lookupIsa(hwIntrinsic); @@ -442,6 +444,7 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, // retType -- the return type of the intrinsic call // simdBaseJitType -- the base JIT type of SIMD type of the intrinsic // simdSize -- the size of the SIMD type of the intrinsic +// mustExpand -- true if the intrinsic must return a GenTree*; otherwise, false // // Return Value: // The GT_HWINTRINSIC node, or nullptr if not a supported intrinsic @@ -452,7 +455,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, var_types retType, CorInfoType simdBaseJitType, unsigned simdSize, - GenTree* newobjThis) + GenTree* newobjThis, + bool mustExpand) { var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); @@ -512,8 +516,47 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, switch (intrinsic) { + case NI_VectorT_ConvertToInt32Native: + { + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + return nullptr; + } + break; + } + + case NI_VectorT_ConvertToInt64Native: + case NI_VectorT_ConvertToUInt32Native: + case NI_VectorT_ConvertToUInt64Native: + { + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + return nullptr; + } + #if defined(TARGET_XARCH) + if (!IsBaselineVector512IsaSupportedOpportunistically()) + { + return nullptr; + } +#endif // TARGET_XARCH + + break; + } + + case NI_Vector2_MultiplyAddEstimate: + case NI_Vector3_MultiplyAddEstimate: + case NI_Vector4_MultiplyAddEstimate: + case NI_VectorT_MultiplyAddEstimate: + { + if (BlockNonDeterministicIntrinsics(mustExpand)) + { + return nullptr; + } + break; + } +#if defined(TARGET_XARCH) case NI_VectorT_ConvertToDouble: { if (IsBaselineVector512IsaSupportedOpportunistically()) @@ -523,20 +566,20 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return nullptr; } - case NI_VectorT_ConvertToInt64: - case NI_VectorT_ConvertToUInt32: - case NI_VectorT_ConvertToUInt64: + case NI_VectorT_ConvertToInt32: { - if (IsBaselineVector512IsaSupportedOpportunistically()) + if (compOpportunisticallyDependsOn(InstructionSet_SSE41)) { break; } return nullptr; } - case NI_VectorT_ConvertToInt32: + case NI_VectorT_ConvertToInt64: + case NI_VectorT_ConvertToUInt32: + case NI_VectorT_ConvertToUInt64: { - if (compOpportunisticallyDependsOn(InstructionSet_SSE41)) + if (IsBaselineVector512IsaSupportedOpportunistically()) { break; } @@ -808,6 +851,26 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, } #endif // TARGET_XARCH + case NI_Vector2_FusedMultiplyAdd: + case NI_Vector3_FusedMultiplyAdd: + case NI_Vector4_FusedMultiplyAdd: + case NI_VectorT_FusedMultiplyAdd: + { + bool isFmaAccelerated = false; + +#if defined(TARGET_XARCH) + isFmaAccelerated = compOpportunisticallyDependsOn(InstructionSet_FMA); +#elif defined(TARGET_ARM64) + isFmaAccelerated = compOpportunisticallyDependsOn(InstructionSet_AdvSimd); +#endif + + if (!isFmaAccelerated) + { + return nullptr; + } + break; + } + #if defined(TARGET_XARCH) case NI_VectorT_Multiply: case NI_VectorT_op_Multiply: @@ -1175,34 +1238,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, } #if defined(TARGET_XARCH) - - case NI_VectorT_ConvertToInt64: - { - assert(sig->numArgs == 1); - assert(simdBaseType == TYP_DOUBLE); - return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); - } - - case NI_VectorT_ConvertToUInt32: - { - assert(sig->numArgs == 1); - assert(simdBaseType == TYP_FLOAT); - return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); - } - - case NI_VectorT_ConvertToUInt64: - { - assert(sig->numArgs == 1); - assert(simdBaseType == TYP_DOUBLE); - return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); - } - - case NI_VectorT_ConvertToInt32: - { - assert(simdBaseType == TYP_FLOAT); - return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); - } - case NI_VectorT_ConvertToDouble: { assert(sig->numArgs == 1); @@ -1273,43 +1308,71 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, simdSize); } + case NI_VectorT_ConvertToSingle: + { + assert((simdBaseType == TYP_INT) || (simdBaseType == TYP_UINT)); + return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToSingle, simdBaseJitType, + simdSize); + } +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + case NI_VectorT_ConvertToInt32: { + assert(sig->numArgs == 1); assert(simdBaseType == TYP_FLOAT); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToInt32RoundToZero, simdBaseJitType, - simdSize); + return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); + } + + case NI_VectorT_ConvertToInt32Native: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + return gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); } case NI_VectorT_ConvertToInt64: { + assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_Arm64_ConvertToInt64RoundToZero, - simdBaseJitType, simdSize); + return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); } - case NI_VectorT_ConvertToSingle: + case NI_VectorT_ConvertToInt64Native: { - assert((simdBaseType == TYP_INT) || (simdBaseType == TYP_UINT)); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToSingle, simdBaseJitType, - simdSize); + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_DOUBLE); + return gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); } case NI_VectorT_ConvertToUInt32: { + assert(sig->numArgs == 1); assert(simdBaseType == TYP_FLOAT); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToUInt32RoundToZero, - simdBaseJitType, simdSize); + return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); + } + + case NI_VectorT_ConvertToUInt32Native: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + return gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); } case NI_VectorT_ConvertToUInt64: { + assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_Arm64_ConvertToUInt64RoundToZero, - simdBaseJitType, simdSize); + return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); + } + + case NI_VectorT_ConvertToUInt64Native: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_DOUBLE); + return gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); } -#else -#error Unsupported platform -#endif // !TARGET_XARCH && !TARGET_ARM64 default: { @@ -1765,6 +1828,14 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdCndSelNode(retType, op1, op2, op3, simdBaseJitType, simdSize); } + case NI_Vector2_FusedMultiplyAdd: + case NI_Vector3_FusedMultiplyAdd: + case NI_Vector4_FusedMultiplyAdd: + case NI_VectorT_FusedMultiplyAdd: + { + return gtNewSimdFmaNode(retType, op1, op2, op3, simdBaseJitType, simdSize); + } + case NI_Vector2_Lerp: case NI_Vector3_Lerp: case NI_Vector4_Lerp: @@ -1806,6 +1877,28 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdBinOpNode(GT_ADD, retType, op1, op2, simdBaseJitType, simdSize); } + case NI_Vector2_MultiplyAddEstimate: + case NI_Vector3_MultiplyAddEstimate: + case NI_Vector4_MultiplyAddEstimate: + case NI_VectorT_MultiplyAddEstimate: + { + bool isFmaAccelerated = false; + +#if defined(TARGET_XARCH) + isFmaAccelerated = compExactlyDependsOn(InstructionSet_FMA); +#elif defined(TARGET_ARM64) + isFmaAccelerated = compExactlyDependsOn(InstructionSet_AdvSimd); +#endif + + if (isFmaAccelerated) + { + return gtNewSimdFmaNode(retType, op1, op2, op3, simdBaseJitType, simdSize); + } + + GenTree* mulNode = gtNewSimdBinOpNode(GT_MUL, retType, op1, op2, simdBaseJitType, simdSize); + return gtNewSimdBinOpNode(GT_ADD, retType, mulNode, op3, simdBaseJitType, simdSize); + } + case NI_VectorT_StoreUnsafeIndex: { assert(retType == TYP_VOID); diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index cb8d702be5e7..e6f3cc0d6db4 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -88,6 +88,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, Distance, SIMD_AS_HWINTRINSIC_ID(Vector2, DistanceSquared, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, FusedMultiplyAdd, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_FusedMultiplyAdd, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector2, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector2, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -100,6 +101,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, Lerp, SIMD_AS_HWINTRINSIC_ID(Vector2, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, MultiplyAddEstimate, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_MultiplyAddEstimate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Normalize, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Normalize, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -128,6 +130,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, Distance, SIMD_AS_HWINTRINSIC_ID(Vector3, DistanceSquared, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, FusedMultiplyAdd, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_FusedMultiplyAdd, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector3, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector3, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -141,6 +144,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, Lerp, SIMD_AS_HWINTRINSIC_ID(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, MultiplyAddEstimate, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_MultiplyAddEstimate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Normalize, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Normalize, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -170,6 +174,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, Distance, SIMD_AS_HWINTRINSIC_ID(Vector4, DistanceSquared, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, FusedMultiplyAdd, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_FusedMultiplyAdd, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector4, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector4, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -184,6 +189,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, Lerp, SIMD_AS_HWINTRINSIC_ID(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, MultiplyAddEstimate, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_MultiplyAddEstimate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Normalize, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Normalize, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -224,10 +230,14 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, Ceiling, SIMD_AS_HWINTRINSIC_ID(VectorT, ConditionalSelect, 3, {NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToDouble, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToDouble, NI_VectorT_ConvertToDouble, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt32Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt32Native, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt64Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt64Native}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToSingle, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToSingle, NI_VectorT_ConvertToSingle, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt32Native, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64Native}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(VectorT, CreateBroadcast, ".ctor", 2, {NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(VectorT, CreateSequence, 2, {NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(VectorT, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_Divide, NI_VectorT_Divide}, SimdAsHWIntrinsicFlag::None) @@ -236,6 +246,7 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, Equals, SIMD_AS_HWINTRINSIC_ID(VectorT, EqualsAll, 2, {NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, EqualsAny, 2, {NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, Floor, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_Floor, NI_VectorT_Floor}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, FusedMultiplyAdd, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_FusedMultiplyAdd, NI_VectorT_FusedMultiplyAdd}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(VectorT, get_AllBitsSet, 0, {NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, get_Indices, 0, {NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, get_Item, 2, {NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) @@ -262,6 +273,7 @@ SIMD_AS_HWINTRINSIC_NM(VectorT, LoadUnsafeIndex, "LoadUnsafe", SIMD_AS_HWINTRINSIC_ID(VectorT, Max, 2, {NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, Min, 2, {NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, Multiply, 2, {NI_VectorT_Multiply, NI_VectorT_Multiply, NI_VectorT_Multiply, NI_VectorT_Multiply, NI_VectorT_Multiply, NI_VectorT_Multiply, NI_Illegal, NI_Illegal, NI_VectorT_Multiply, NI_VectorT_Multiply}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, MultiplyAddEstimate, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_MultiplyAddEstimate, NI_VectorT_MultiplyAddEstimate}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, Narrow, 2, {NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow}, SimdAsHWIntrinsicFlag::KeepBaseTypeFromRet) SIMD_AS_HWINTRINSIC_ID(VectorT, Negate, 1, {NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, OnesComplement, 2, {NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index 5cf07eff0c84..c0890478b806 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -88,6 +88,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, Distance, SIMD_AS_HWINTRINSIC_ID(Vector2, DistanceSquared, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, FusedMultiplyAdd, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_FusedMultiplyAdd, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector2, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -100,6 +101,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, Lerp, SIMD_AS_HWINTRINSIC_ID(Vector2, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, MultiplyAddEstimate, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_MultiplyAddEstimate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Normalize, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Normalize, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -128,6 +130,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, Distance, SIMD_AS_HWINTRINSIC_ID(Vector3, DistanceSquared, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, FusedMultiplyAdd, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_FusedMultiplyAdd, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector3, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -141,6 +144,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, Lerp, SIMD_AS_HWINTRINSIC_ID(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, MultiplyAddEstimate, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_MultiplyAddEstimate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Normalize, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Normalize, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -170,6 +174,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, Distance, SIMD_AS_HWINTRINSIC_ID(Vector4, DistanceSquared, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, FusedMultiplyAdd, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_FusedMultiplyAdd, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector4, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -184,6 +189,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, Lerp, SIMD_AS_HWINTRINSIC_ID(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, MultiplyAddEstimate, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_MultiplyAddEstimate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Normalize, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Normalize, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -224,10 +230,14 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, Ceiling, SIMD_AS_HWINTRINSIC_ID(VectorT, ConditionalSelect, 3, {NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToDouble, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToDouble, NI_VectorT_ConvertToDouble, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt32Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt32Native, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt64Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt64Native}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToSingle, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToSingle, NI_VectorT_ConvertToSingle, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt32Native, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64Native}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(VectorT, CreateBroadcast, ".ctor", 2, {NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(VectorT, CreateSequence, 2, {NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(VectorT, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_Divide, NI_VectorT_Divide}, SimdAsHWIntrinsicFlag::None) @@ -236,6 +246,7 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, Equals, SIMD_AS_HWINTRINSIC_ID(VectorT, EqualsAll, 2, {NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll, NI_VectorT_EqualsAll}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, EqualsAny, 2, {NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny, NI_VectorT_EqualsAny}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, Floor, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_Floor, NI_VectorT_Floor}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, FusedMultiplyAdd, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_FusedMultiplyAdd, NI_VectorT_FusedMultiplyAdd}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, get_AllBitsSet, 0, {NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet, NI_VectorT_get_AllBitsSet}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, get_Indices, 0, {NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices, NI_VectorT_get_Indices}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, get_Item, 2, {NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item, NI_VectorT_get_Item}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) @@ -262,6 +273,7 @@ SIMD_AS_HWINTRINSIC_NM(VectorT, LoadUnsafeIndex, "LoadUnsafe", SIMD_AS_HWINTRINSIC_ID(VectorT, Max, 2, {NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max, NI_VectorT_Max}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, Min, 2, {NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min, NI_VectorT_Min}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, Multiply, 2, {NI_Illegal, NI_Illegal, NI_VectorT_Multiply, NI_VectorT_Multiply, NI_VectorT_Multiply, NI_VectorT_Multiply, NI_VectorT_Multiply, NI_VectorT_Multiply, NI_VectorT_Multiply, NI_VectorT_Multiply}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, MultiplyAddEstimate, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_MultiplyAddEstimate, NI_VectorT_MultiplyAddEstimate}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, Narrow, 2, {NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow, NI_VectorT_Narrow}, SimdAsHWIntrinsicFlag::KeepBaseTypeFromRet) SIMD_AS_HWINTRINSIC_ID(VectorT, Negate, 1, {NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate, NI_VectorT_Negate}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, OnesComplement, 1, {NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement, NI_VectorT_OnesComplement}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdcodegenxarch.cpp b/src/coreclr/jit/simdcodegenxarch.cpp index d0fb1bf0aef4..57fcb5d46880 100644 --- a/src/coreclr/jit/simdcodegenxarch.cpp +++ b/src/coreclr/jit/simdcodegenxarch.cpp @@ -96,7 +96,7 @@ void CodeGen::genStoreIndTypeSimd12(GenTreeStoreInd* treeNode) } else { - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); // Extract upper 4 bytes from data emit->emitIns_R_R(INS_movhlps, EA_16BYTE, tmpReg, dataReg); @@ -168,7 +168,7 @@ void CodeGen::genLoadIndTypeSimd12(GenTreeIndir* treeNode) { // Load and insert upper 4 bytes, 0x20 inserts to index 2 and 0x8 zeros index 3 GenTreeIndir indir = indirForm(TYP_SIMD16, addr); - emit->emitIns_SIMD_R_R_A_I(INS_insertps, EA_16BYTE, tgtReg, tgtReg, &indir, 0x28); + emit->emitIns_SIMD_R_R_A_I(INS_insertps, EA_16BYTE, tgtReg, tgtReg, &indir, 0x28, INS_OPTS_NONE); } else { @@ -295,7 +295,7 @@ void CodeGen::genEmitStoreLclTypeSimd12(GenTree* store, unsigned lclNum, unsigne } else { - regNumber tmpReg = store->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(store); // Extract upper 4 bytes from data emit->emitIns_R_R(INS_movhlps, EA_16BYTE, tmpReg, dataReg); @@ -323,7 +323,7 @@ void CodeGen::genEmitLoadLclTypeSimd12(regNumber tgtReg, unsigned lclNum, unsign emit->emitIns_R_S(INS_movsd_simd, EA_8BYTE, tgtReg, lclNum, offset); // Load and insert upper 4 byte, 0x20 inserts to index 2 and 0x8 zeros index 3 - emit->emitIns_SIMD_R_R_S_I(INS_insertps, EA_16BYTE, tgtReg, tgtReg, lclNum, offset + 8, 0x28); + emit->emitIns_SIMD_R_R_S_I(INS_insertps, EA_16BYTE, tgtReg, tgtReg, lclNum, offset + 8, 0x28, INS_OPTS_NONE); } else { @@ -391,7 +391,7 @@ void CodeGen::genPutArgStkSimd12(GenTreePutArgStk* treeNode) regNumber dataReg = genConsumeReg(data); // Need an additional Xmm register to extract upper 4 bytes from data. - regNumber tmpReg = treeNode->GetSingleTempReg(); + regNumber tmpReg = internalRegisters.GetSingle(treeNode); genStoreSimd12ToStack(dataReg, tmpReg); } @@ -530,25 +530,19 @@ void CodeGen::genSimd12UpperClear(regNumber tgtReg) // COUNT_D: 0b11 - Insert into element 3 // COUNT_S: 0b11 - Insert from element 3 - GetEmitter()->emitIns_SIMD_R_R_R_I(INS_insertps, EA_16BYTE, tgtReg, tgtReg, tgtReg, static_cast(0xF8)); + GetEmitter()->emitIns_SIMD_R_R_R_I(INS_insertps, EA_16BYTE, tgtReg, tgtReg, tgtReg, static_cast(0xF8), + INS_OPTS_NONE); } else { // Preserve element 0, 1, and 2; Zero element 3 - - if (zroSimd12Elm3 == NO_FIELD_HANDLE) - { - simd16_t constValue; - - constValue.u32[0] = 0xFFFFFFFF; - constValue.u32[1] = 0xFFFFFFFF; - constValue.u32[2] = 0xFFFFFFFF; - constValue.u32[3] = 0x00000000; - - zroSimd12Elm3 = GetEmitter()->emitSimd16Const(constValue); - } - - GetEmitter()->emitIns_SIMD_R_R_C(INS_andps, EA_16BYTE, tgtReg, tgtReg, zroSimd12Elm3, 0); + simd16_t constValue; + constValue.u32[0] = 0xFFFFFFFF; + constValue.u32[1] = 0xFFFFFFFF; + constValue.u32[2] = 0xFFFFFFFF; + constValue.u32[3] = 0x00000000; + CORINFO_FIELD_HANDLE zroSimd12Elm3 = GetEmitter()->emitSimd16Const(constValue); + GetEmitter()->emitIns_SIMD_R_R_C(INS_andps, EA_16BYTE, tgtReg, tgtReg, zroSimd12Elm3, 0, INS_OPTS_NONE); } } diff --git a/src/coreclr/jit/ssabuilder.cpp b/src/coreclr/jit/ssabuilder.cpp index 8dadf691b0cb..12f2a88ee353 100644 --- a/src/coreclr/jit/ssabuilder.cpp +++ b/src/coreclr/jit/ssabuilder.cpp @@ -1174,8 +1174,8 @@ void SsaBuilder::AddPhiArgsToSuccessors(BasicBlock* block) // Walk the statements for phi nodes. for (Statement* const stmt : succ->Statements()) { - // A prefix of the statements of the block are phi definition nodes. If we complete processing - // that prefix, exit. + // A prefix of the statements of the block are phi definition nodes. If we complete + // processing that prefix, exit. if (!stmt->IsPhiDefnStmt()) { break; @@ -1206,8 +1206,9 @@ void SsaBuilder::AddPhiArgsToSuccessors(BasicBlock* block) { if ((memoryKind == GcHeap) && m_pCompiler->byrefStatesMatchGcHeapStates) { - // We've already propagated the "out" number to the phi shared with ByrefExposed, - // but still need to update bbMemorySsaPhiFunc to be in sync between GcHeap and ByrefExposed. + // We've already propagated the "out" number to the phi shared with + // ByrefExposed, but still need to update bbMemorySsaPhiFunc to be in sync + // between GcHeap and ByrefExposed. assert(memoryKind > ByrefExposed); assert(block->bbMemorySsaNumOut[memoryKind] == block->bbMemorySsaNumOut[ByrefExposed]); #if !defined(TARGET_WASM) @@ -1229,8 +1230,9 @@ void SsaBuilder::AddPhiArgsToSuccessors(BasicBlock* block) BasicBlock::MemoryPhiArg* curArg = succMemoryPhi; unsigned ssaNum = block->bbMemorySsaNumOut[memoryKind]; bool found = false; - // This is a quadratic algorithm. We might need to consider some switch over to a hash table - // representation for the arguments of a phi node, to make this linear. + // This is a quadratic algorithm. We might need to consider some switch over + // to a hash table representation for the arguments of a phi node, to make this + // linear. while (curArg != nullptr) { if (curArg->m_ssaNum == ssaNum) diff --git a/src/coreclr/jit/target.h b/src/coreclr/jit/target.h index b4693baea829..56faca4aca0a 100644 --- a/src/coreclr/jit/target.h +++ b/src/coreclr/jit/target.h @@ -126,7 +126,7 @@ enum _regNumber_enum : unsigned ACTUAL_REG_COUNT = REG_COUNT - 1 // everything but REG_STK (only real regs) }; -enum _regMask_enum : unsigned __int64 +enum _regMask_enum : uint64_t { RBM_NONE = 0, #define REGDEF(name, rnum, mask, sname) RBM_##name = mask, @@ -147,7 +147,7 @@ enum _regNumber_enum : unsigned ACTUAL_REG_COUNT = REG_COUNT - 1 // everything but REG_STK (only real regs) }; -enum _regMask_enum : unsigned __int64 +enum _regMask_enum : uint64_t { RBM_NONE = 0, #define REGDEF(name, rnum, mask, xname, wname) RBM_##name = mask, @@ -236,11 +236,8 @@ enum _regMask_enum : unsigned // In any case, we believe that is OK to freely cast between these types; no information will // be lost. -#if defined(TARGET_AMD64) || defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) -typedef unsigned __int64 regMaskTP; -#else -typedef unsigned regMaskTP; -#endif +typedef _regNumber_enum regNumber; +typedef unsigned char regNumberSmall; #if REGMASK_BITS == 8 typedef unsigned char regMaskSmall; @@ -255,13 +252,175 @@ typedef unsigned regMaskSmall; #define REG_MASK_INT_FMT "%08X" #define REG_MASK_ALL_FMT "%08X" #else -typedef unsigned __int64 regMaskSmall; +typedef uint64_t regMaskSmall; #define REG_MASK_INT_FMT "%04llX" #define REG_MASK_ALL_FMT "%016llX" #endif -typedef _regNumber_enum regNumber; -typedef unsigned char regNumberSmall; +struct regMaskTP +{ +private: + regMaskSmall low; +public: + constexpr regMaskTP(regMaskSmall regMask) + : low(regMask) + { + } + + regMaskTP() + { + } + + explicit operator bool() const + { + return low != RBM_NONE; + } + + explicit operator regMaskSmall() const + { + return (regMaskSmall)low; + } + +#ifdef TARGET_ARM + explicit operator int() const + { + return (int)low; + } + explicit operator BYTE() const + { + return (BYTE)low; + } +#endif + +#if !defined(TARGET_X86) && !defined(TARGET_WASM32) + explicit operator unsigned int() const + { + return (unsigned int)low; + } +#endif + + regMaskSmall getLow() const + { + return low; + } +}; + +static regMaskTP operator^(regMaskTP first, regMaskTP second) +{ + regMaskTP result(first.getLow() ^ second.getLow()); + return result; +} + +static regMaskTP operator&(regMaskTP first, regMaskTP second) +{ + regMaskTP result(first.getLow() & second.getLow()); + return result; +} + +static regMaskTP operator|(regMaskTP first, regMaskTP second) +{ + regMaskTP result(first.getLow() | second.getLow()); + return result; +} + +static regMaskTP operator<<(regMaskTP first, const int b) +{ + regMaskTP result(first.getLow() << b); + return result; +} + +static regMaskTP operator>>(regMaskTP first, const int b) +{ + regMaskTP result(first.getLow() >> b); + return result; +} + +static regMaskTP& operator>>=(regMaskTP& first, const int b) +{ + first = first >> b; + return first; +} + +static regMaskTP& operator|=(regMaskTP& first, regMaskTP second) +{ + first = first | second; + return first; +} + +static regMaskTP& operator^=(regMaskTP& first, regMaskTP second) +{ + first = first ^ second; + return first; +} + +static regMaskSmall operator^=(regMaskSmall& first, regMaskTP second) +{ + first ^= second.getLow(); + return first; +} + +static regMaskSmall operator&=(regMaskSmall& first, regMaskTP second) +{ + first &= second.getLow(); + return first; +} + +static regMaskSmall operator|=(regMaskSmall& first, regMaskTP second) +{ + first |= second.getLow(); + return first; +} + +static regMaskTP& operator&=(regMaskTP& first, regMaskTP second) +{ + first = first & second; + return first; +} + +static bool operator==(regMaskTP first, regMaskTP second) +{ + return (first.getLow() == second.getLow()); +} + +static bool operator!=(regMaskTP first, regMaskTP second) +{ + return (first.getLow() != second.getLow()); +} + +#ifdef TARGET_ARM +static regMaskTP operator-(regMaskTP first, regMaskTP second) +{ + regMaskTP result(first.getLow() - second.getLow()); + return result; +} + +static bool operator>(regMaskTP first, regMaskTP second) +{ + return first.getLow() > second.getLow(); +} + +static regMaskTP& operator<<=(regMaskTP& first, const int b) +{ + first = first << b; + return first; +} +#endif + +static regMaskTP operator~(regMaskTP first) +{ + regMaskTP result(~first.getLow()); + return result; +} + +static uint32_t PopCount(regMaskTP value) +{ + return BitOperations::PopCount(value.getLow()); +} + +static uint32_t BitScanForward(regMaskTP mask) +{ + return BitOperations::BitScanForward(mask.getLow()); +} /*****************************************************************************/ @@ -713,8 +872,7 @@ inline regMaskTP genRegMask(regNumber regNum, var_types type) * These arrays list the callee-saved register numbers (and bitmaps, respectively) for * the current architecture. */ -extern const regNumber raRegCalleeSaveOrder[CNT_CALLEE_SAVED]; -extern const regMaskTP raRbmCalleeSaveOrder[CNT_CALLEE_SAVED]; +extern const regMaskTP raRbmCalleeSaveOrder[CNT_CALL_GC_REGS]; // This method takes a "compact" bitset of the callee-saved registers, and "expands" it to a full register mask. regMaskSmall genRegMaskFromCalleeSavedMask(unsigned short); @@ -806,8 +964,8 @@ C_ASSERT((RBM_INT_CALLEE_SAVED & RBM_FPBASE) == RBM_NONE); #endif #ifdef TARGET_64BIT -typedef unsigned __int64 target_size_t; -typedef __int64 target_ssize_t; +typedef uint64_t target_size_t; +typedef int64_t target_ssize_t; #define TARGET_SIGN_BIT (1ULL << 63) #else // !TARGET_64BIT diff --git a/src/coreclr/jit/targetamd64.cpp b/src/coreclr/jit/targetamd64.cpp index 85b1ba6ef19a..8f3a979d7862 100644 --- a/src/coreclr/jit/targetamd64.cpp +++ b/src/coreclr/jit/targetamd64.cpp @@ -194,6 +194,45 @@ ABIPassingInformation WinX64Classifier::Classify(Compiler* comp, return ABIPassingInformation::FromSegment(comp, segment); } + +//----------------------------------------------------------------------------- +// GetShadowSpaceCallerOffsetForReg: +// Get the offset (starting at 0) at which a parameter register has shadow +// stack space allocated by the caller. +// +// Parameters: +// reg - The register +// offset - [out] Offset, starting at 0. +// +// Returns: +// True if the register is a parameter register with shadow space allocated +// by the caller; otherwise false. +// +bool ABIPassingInformation::GetShadowSpaceCallerOffsetForReg(regNumber reg, int* offset) +{ + switch (reg) + { + case REG_ECX: + case REG_XMM0: + *offset = 0; + return true; + case REG_EDX: + case REG_XMM1: + *offset = 8; + return true; + case REG_R8: + case REG_XMM2: + *offset = 16; + return true; + case REG_R9: + case REG_XMM3: + *offset = 24; + return true; + default: + return false; + } +} + #endif #endif // TARGET_AMD64 diff --git a/src/coreclr/jit/targetamd64.h b/src/coreclr/jit/targetamd64.h index 7e72da9cf2cc..1575177643eb 100644 --- a/src/coreclr/jit/targetamd64.h +++ b/src/coreclr/jit/targetamd64.h @@ -295,13 +295,14 @@ #define CNT_CALLEE_SAVED (5 + REG_ETW_FRAMED_EBP_COUNT) #define CNT_CALLEE_TRASH (9) #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED) + #define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED + 2) #define CNT_CALLEE_SAVED_FLOAT (0) #define CNT_CALLEE_TRASH_FLOAT_INIT (16) #define CNT_CALLEE_TRASH_HIGHFLOAT (16) /* NOTE: Sync with variable name defined in compiler.h */ - #define REG_CALLEE_SAVED_ORDER REG_EBX,REG_ETW_FRAMED_EBP_LIST REG_R12,REG_R13,REG_R14,REG_R15 - #define RBM_CALLEE_SAVED_ORDER RBM_EBX,RBM_ETW_FRAMED_EBP_LIST RBM_R12,RBM_R13,RBM_R14,RBM_R15 + #define RBM_CALL_GC_REGS_ORDER RBM_EBX,RBM_ETW_FRAMED_EBP_LIST RBM_R12,RBM_R13,RBM_R14,RBM_R15,RBM_INTRET,RBM_INTRET_1 + #define RBM_CALL_GC_REGS (RBM_EBX|RBM_ETW_FRAMED_EBP|RBM_R12|RBM_R13|RBM_R14|RBM_R15|RBM_INTRET|RBM_INTRET_1) // For SysV we have more volatile registers so we do not save any callee saves for EnC. #define RBM_ENC_CALLEE_SAVED 0 @@ -309,13 +310,14 @@ #define CNT_CALLEE_SAVED (7 + REG_ETW_FRAMED_EBP_COUNT) #define CNT_CALLEE_TRASH (7) #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED) + #define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED + 1) #define CNT_CALLEE_SAVED_FLOAT (10) #define CNT_CALLEE_TRASH_FLOAT_INIT (6) #define CNT_CALLEE_TRASH_HIGHFLOAT (16) /* NOTE: Sync with variable name defined in compiler.h */ - #define REG_CALLEE_SAVED_ORDER REG_EBX,REG_ESI,REG_EDI,REG_ETW_FRAMED_EBP_LIST REG_R12,REG_R13,REG_R14,REG_R15 - #define RBM_CALLEE_SAVED_ORDER RBM_EBX,RBM_ESI,RBM_EDI,RBM_ETW_FRAMED_EBP_LIST RBM_R12,RBM_R13,RBM_R14,RBM_R15 + #define RBM_CALL_GC_REGS_ORDER RBM_EBX,RBM_ESI,RBM_EDI,RBM_ETW_FRAMED_EBP_LIST RBM_R12,RBM_R13,RBM_R14,RBM_R15,RBM_INTRET + #define RBM_CALL_GC_REGS (RBM_EBX|RBM_ESI|RBM_EDI|RBM_ETW_FRAMED_EBP|RBM_R12|RBM_R13|RBM_R14|RBM_R15|RBM_INTRET) // Callee-preserved registers we always save and allow use of for EnC code, since there are quite few volatile registers. #define RBM_ENC_CALLEE_SAVED (RBM_RSI | RBM_RDI) diff --git a/src/coreclr/jit/targetarm.cpp b/src/coreclr/jit/targetarm.cpp index 037578fa67b8..675fd04230d5 100644 --- a/src/coreclr/jit/targetarm.cpp +++ b/src/coreclr/jit/targetarm.cpp @@ -85,11 +85,11 @@ ABIPassingInformation Arm32Classifier::Classify(Compiler* comp, m_nextIntReg = roundUp(m_nextIntReg, 2); } - unsigned size = type == TYP_STRUCT ? structLayout->GetSize() : genTypeSize(type); - unsigned alignedSize = roundUp(size, alignment); + unsigned size = type == TYP_STRUCT ? structLayout->GetSize() : genTypeSize(type); + unsigned numSlots = (size + 3) / 4; - unsigned numInRegs = min(alignedSize / 4, 4 - m_nextIntReg); - bool anyOnStack = numInRegs < (alignedSize / 4); + unsigned numInRegs = min(numSlots, 4 - m_nextIntReg); + bool anyOnStack = numInRegs < numSlots; // If we already passed anything on stack (due to float args) then we // cannot split an arg. @@ -116,7 +116,7 @@ ABIPassingInformation Arm32Classifier::Classify(Compiler* comp, { m_stackArgSize = roundUp(m_stackArgSize, alignment); unsigned stackSize = size - (numInRegs * 4); - info.Segments[numInRegs] = ABIPassingSegment::OnStack(m_stackArgSize, 0, stackSize); + info.Segments[numInRegs] = ABIPassingSegment::OnStack(m_stackArgSize, numInRegs * 4, stackSize); m_stackArgSize += roundUp(stackSize, 4); // As soon as any int arg goes on stack we cannot put anything else in diff --git a/src/coreclr/jit/targetarm.h b/src/coreclr/jit/targetarm.h index 0f56ebe1ce98..46c41329b056 100644 --- a/src/coreclr/jit/targetarm.h +++ b/src/coreclr/jit/targetarm.h @@ -90,12 +90,13 @@ #define RBM_LOW_REGS (RBM_R0|RBM_R1|RBM_R2|RBM_R3|RBM_R4|RBM_R5|RBM_R6|RBM_R7) #define RBM_HIGH_REGS (RBM_R8|RBM_R9|RBM_R10|RBM_R11|RBM_R12|RBM_SP|RBM_LR|RBM_PC) - #define REG_CALLEE_SAVED_ORDER REG_R4,REG_R5,REG_R6,REG_R7,REG_R8,REG_R9,REG_R10,REG_R11 - #define RBM_CALLEE_SAVED_ORDER RBM_R4,RBM_R5,RBM_R6,RBM_R7,RBM_R8,RBM_R9,RBM_R10,RBM_R11 + #define RBM_CALL_GC_REGS_ORDER RBM_R4,RBM_R5,RBM_R6,RBM_R7,RBM_R8,RBM_R9,RBM_R10,RBM_R11,RBM_INTRET + #define RBM_CALL_GC_REGS (RBM_R4|RBM_R5|RBM_R6|RBM_R7|RBM_R8|RBM_R9|RBM_R10|RBM_R11|RBM_INTRET) #define CNT_CALLEE_SAVED (8) #define CNT_CALLEE_TRASH (6) #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) + #define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED+1) #define CNT_CALLEE_SAVED_FLOAT (16) #define CNT_CALLEE_TRASH_FLOAT (16) diff --git a/src/coreclr/jit/targetarm64.cpp b/src/coreclr/jit/targetarm64.cpp index a0e4dfb5c3cf..f95663202456 100644 --- a/src/coreclr/jit/targetarm64.cpp +++ b/src/coreclr/jit/targetarm64.cpp @@ -154,7 +154,7 @@ ABIPassingInformation Arm64Classifier::Classify(Compiler* comp, { info.NumSegments = slots; info.Segments = new (comp, CMK_ABI) ABIPassingSegment[slots]; - unsigned slotSize = varTypeIsStruct(type) ? TARGET_POINTER_SIZE : genTypeSize(type); + unsigned slotSize = min(passedSize, (unsigned)TARGET_POINTER_SIZE); info.Segments[0] = ABIPassingSegment::InRegister(regs->Dequeue(), 0, slotSize); if (slots == 2) { diff --git a/src/coreclr/jit/targetarm64.h b/src/coreclr/jit/targetarm64.h index 6d33d378bcd9..8238980fa22d 100644 --- a/src/coreclr/jit/targetarm64.h +++ b/src/coreclr/jit/targetarm64.h @@ -90,7 +90,8 @@ REG_R6, REG_R7, REG_R8, REG_R9, REG_R10, \ REG_R11, REG_R13, REG_R14, \ REG_R12, REG_R15, REG_IP0, REG_IP1, \ - REG_CALLEE_SAVED_ORDER, REG_LR + REG_R19,REG_R20,REG_R21,REG_R22,REG_R23,REG_R24,REG_R25,REG_R26,REG_R27,REG_R28,\ + REG_LR #define REG_VAR_ORDER_FLT REG_V16, REG_V17, REG_V18, REG_V19, \ REG_V20, REG_V21, REG_V22, REG_V23, \ @@ -101,15 +102,18 @@ REG_V12, REG_V13, REG_V14, REG_V15, \ REG_V3, REG_V2, REG_V1, REG_V0 - #define REG_CALLEE_SAVED_ORDER REG_R19,REG_R20,REG_R21,REG_R22,REG_R23,REG_R24,REG_R25,REG_R26,REG_R27,REG_R28 - #define RBM_CALLEE_SAVED_ORDER RBM_R19,RBM_R20,RBM_R21,RBM_R22,RBM_R23,RBM_R24,RBM_R25,RBM_R26,RBM_R27,RBM_R28 + #define RBM_CALL_GC_REGS_ORDER RBM_R19,RBM_R20,RBM_R21,RBM_R22,RBM_R23,RBM_R24,RBM_R25,RBM_R26,RBM_R27,RBM_R28,RBM_INTRET,RBM_INTRET_1 + #define RBM_CALL_GC_REGS (RBM_R19|RBM_R20|RBM_R21|RBM_R22|RBM_R23|RBM_R24|RBM_R25|RBM_R26|RBM_R27|RBM_R28|RBM_INTRET|RBM_INTRET_1) #define CNT_CALLEE_SAVED (11) #define CNT_CALLEE_TRASH (17) #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) + #define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED+2) #define CNT_CALLEE_SAVED_FLOAT (8) #define CNT_CALLEE_TRASH_FLOAT (24) + #define CNT_CALLEE_SAVED_MASK (4) + #define CNT_CALLEE_TRASH_MASK (8) #define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED * REGSIZE_BYTES) #define CALLEE_SAVED_FLOAT_MAXSZ (CNT_CALLEE_SAVED_FLOAT * FPSAVE_REGSIZE_BYTES) @@ -372,9 +376,11 @@ // For arm64, this is the maximum prolog establishment pre-indexed (that is SP pre-decrement) offset. #define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 512 - // Some "Advanced SIMD scalar x indexed element" and "Advanced SIMD vector x indexed element" instructions (e.g. "MLA (by element)") + // Some "Advanced SIMD / SVE scalar x indexed element" and "Advanced SIMD / SVE vector x indexed element" instructions (e.g. "MLA (by element)") // have encoding that restricts what registers that can be used for the indexed element when the element size is H (i.e. 2 bytes). #define RBM_ASIMD_INDEXED_H_ELEMENT_ALLOWED_REGS (RBM_V0|RBM_V1|RBM_V2|RBM_V3|RBM_V4|RBM_V5|RBM_V6|RBM_V7|RBM_V8|RBM_V9|RBM_V10|RBM_V11|RBM_V12|RBM_V13|RBM_V14|RBM_V15) + #define RBM_SVE_INDEXED_S_ELEMENT_ALLOWED_REGS (RBM_V0|RBM_V1|RBM_V2|RBM_V3|RBM_V4|RBM_V5|RBM_V6|RBM_V7) + #define RBM_SVE_INDEXED_D_ELEMENT_ALLOWED_REGS RBM_ASIMD_INDEXED_H_ELEMENT_ALLOWED_REGS #define REG_ZERO_INIT_FRAME_REG1 REG_R9 #define REG_ZERO_INIT_FRAME_REG2 REG_R10 diff --git a/src/coreclr/jit/targetloongarch64.cpp b/src/coreclr/jit/targetloongarch64.cpp index e0097a1b62a1..caab31b18988 100644 --- a/src/coreclr/jit/targetloongarch64.cpp +++ b/src/coreclr/jit/targetloongarch64.cpp @@ -24,4 +24,215 @@ const regNumber fltArgRegs [] = {REG_F0, REG_F1, REG_F2, REG_F3, REG_F4, REG_F5, const regMaskTP fltArgMasks[] = {RBM_F0, RBM_F1, RBM_F2, RBM_F3, RBM_F4, RBM_F5, RBM_F6, RBM_F7 }; // clang-format on +//----------------------------------------------------------------------------- +// LoongArch64Classifier: +// Construct a new instance of the LoongArch64 ABI classifier. +// +// Parameters: +// info - Info about the method being classified. +// +LoongArch64Classifier::LoongArch64Classifier(const ClassifierInfo& info) + : m_info(info) + , m_intRegs(intArgRegs, ArrLen(intArgRegs)) + , m_floatRegs(fltArgRegs, ArrLen(fltArgRegs)) +{ +} + +//----------------------------------------------------------------------------- +// Classify: +// Classify a parameter for the LoongArch64 ABI. +// +// Parameters: +// comp - Compiler instance +// type - The type of the parameter +// structLayout - The layout of the struct. Expected to be non-null if +// varTypeIsStruct(type) is true. +// wellKnownParam - Well known type of the parameter (if it may affect its ABI classification) +// +// Returns: +// Classification information for the parameter. +// +ABIPassingInformation LoongArch64Classifier::Classify(Compiler* comp, + var_types type, + ClassLayout* structLayout, + WellKnownArg wellKnownParam) +{ + assert(!m_info.IsVarArgs); + + unsigned passedSize; + unsigned slots = 0; + var_types argRegTypeInStruct1 = TYP_UNKNOWN; + var_types argRegTypeInStruct2 = TYP_UNKNOWN; + + bool canPassArgInRegisters = false; + if (varTypeIsStruct(type)) + { + passedSize = structLayout->GetSize(); + if (passedSize > MAX_PASS_MULTIREG_BYTES) + { + slots = 1; // Passed by implicit byref + passedSize = TARGET_POINTER_SIZE; + canPassArgInRegisters = m_intRegs.Count() > 0; + } + else + { + assert(!structLayout->IsBlockLayout()); + + uint32_t floatFlags; + CORINFO_CLASS_HANDLE typeHnd = structLayout->GetClassHandle(); + + floatFlags = comp->info.compCompHnd->getLoongArch64PassStructInRegisterFlags(typeHnd); + + if ((floatFlags & STRUCT_HAS_FLOAT_FIELDS_MASK) != 0) + { + if ((floatFlags & STRUCT_FLOAT_FIELD_ONLY_ONE) != 0) + { + assert(passedSize <= TARGET_POINTER_SIZE); + + slots = 1; + canPassArgInRegisters = m_floatRegs.Count() > 0; + + argRegTypeInStruct1 = (passedSize == 8) ? TYP_DOUBLE : TYP_FLOAT; + } + else if ((floatFlags & STRUCT_FLOAT_FIELD_ONLY_TWO) != 0) + { + slots = 2; + canPassArgInRegisters = m_floatRegs.Count() >= 2; + + argRegTypeInStruct1 = (floatFlags & STRUCT_FIRST_FIELD_SIZE_IS8) ? TYP_DOUBLE : TYP_FLOAT; + argRegTypeInStruct2 = (floatFlags & STRUCT_SECOND_FIELD_SIZE_IS8) ? TYP_DOUBLE : TYP_FLOAT; + } + else if ((floatFlags & STRUCT_FLOAT_FIELD_FIRST) != 0) + { + slots = 2; + canPassArgInRegisters = (m_floatRegs.Count() > 0) && (m_intRegs.Count() > 0); + + argRegTypeInStruct1 = (floatFlags & STRUCT_FIRST_FIELD_SIZE_IS8) ? TYP_DOUBLE : TYP_FLOAT; + argRegTypeInStruct2 = (floatFlags & STRUCT_SECOND_FIELD_SIZE_IS8) ? TYP_LONG : TYP_INT; + } + else if ((floatFlags & STRUCT_FLOAT_FIELD_SECOND) != 0) + { + slots = 2; + canPassArgInRegisters = (m_floatRegs.Count() > 0) && (m_intRegs.Count() > 0); + + argRegTypeInStruct1 = (floatFlags & STRUCT_FIRST_FIELD_SIZE_IS8) ? TYP_LONG : TYP_INT; + argRegTypeInStruct2 = (floatFlags & STRUCT_SECOND_FIELD_SIZE_IS8) ? TYP_DOUBLE : TYP_FLOAT; + } + + assert((slots == 1) || (slots == 2)); + + if (!canPassArgInRegisters) + { + slots = (passedSize + TARGET_POINTER_SIZE - 1) / TARGET_POINTER_SIZE; + // On LoongArch64, if there aren't any remaining floating-point registers to pass the argument, + // integer registers (if any) are used instead. + canPassArgInRegisters = m_intRegs.Count() >= slots; + + argRegTypeInStruct1 = TYP_UNKNOWN; + argRegTypeInStruct2 = TYP_UNKNOWN; + } + } + else + { + slots = (passedSize + TARGET_POINTER_SIZE - 1) / TARGET_POINTER_SIZE; + canPassArgInRegisters = m_intRegs.Count() >= slots; + } + + if (!canPassArgInRegisters && (slots == 2)) + { + // Here a struct-arg which needs two registers but only one integer register available, + // it has to be split. + if (m_intRegs.Count() > 0) + { + canPassArgInRegisters = true; + } + } + } + } + else + { + assert(genTypeSize(type) <= TARGET_POINTER_SIZE); + + slots = 1; + passedSize = genTypeSize(type); + if (varTypeIsFloating(type)) + { + canPassArgInRegisters = m_floatRegs.Count() > 0; + if (!canPassArgInRegisters) + { + type = TYP_I_IMPL; + canPassArgInRegisters = m_intRegs.Count() > 0; + } + } + else + { + canPassArgInRegisters = m_intRegs.Count() > 0; + } + } + + ABIPassingInformation info; + if (canPassArgInRegisters) + { + info.NumSegments = slots; + info.Segments = new (comp, CMK_ABI) ABIPassingSegment[slots]; + if (argRegTypeInStruct1 != TYP_UNKNOWN) + { + RegisterQueue* regs = varTypeIsFloating(argRegTypeInStruct1) ? &m_floatRegs : &m_intRegs; + assert(regs->Count() > 0); + + passedSize = genTypeSize(argRegTypeInStruct1); + info.Segments[0] = ABIPassingSegment::InRegister(regs->Dequeue(), 0, passedSize); + + if (argRegTypeInStruct2 != TYP_UNKNOWN) + { + unsigned slotSize = genTypeSize(argRegTypeInStruct2); + + regs = varTypeIsFloating(argRegTypeInStruct2) ? &m_floatRegs : &m_intRegs; + assert(regs->Count() > 0); + + passedSize = max(passedSize, slotSize); + info.Segments[1] = ABIPassingSegment::InRegister(regs->Dequeue(), passedSize, slotSize); + } + } + else + { + RegisterQueue* regs = varTypeIsFloating(type) ? &m_floatRegs : &m_intRegs; + unsigned slotSize = min(passedSize, (unsigned)TARGET_POINTER_SIZE); + info.Segments[0] = ABIPassingSegment::InRegister(regs->Dequeue(), 0, slotSize); + if (slots == 2) + { + assert(varTypeIsStruct(type)); + assert(passedSize > TARGET_POINTER_SIZE); + unsigned tailSize = passedSize - slotSize; + if (m_intRegs.Count() > 0) + { + info.Segments[1] = ABIPassingSegment::InRegister(m_intRegs.Dequeue(), slotSize, tailSize); + } + else + { + assert(m_intRegs.Count() == 0); + assert(m_stackArgSize == 0); + info.Segments[1] = ABIPassingSegment::OnStack(0, TARGET_POINTER_SIZE, tailSize); + m_stackArgSize += TARGET_POINTER_SIZE; + } + } + } + } + else + { + assert((m_stackArgSize % TARGET_POINTER_SIZE) == 0); + + info = ABIPassingInformation::FromSegment(comp, ABIPassingSegment::OnStack(m_stackArgSize, 0, passedSize)); + + m_stackArgSize += roundUp(passedSize, TARGET_POINTER_SIZE); + + // As soon as we pass something on stack we cannot go back and + // enregister something else. + // The float had been cleared before and only integer type go here. + m_intRegs.Clear(); + } + + return info; +} + #endif // TARGET_LOONGARCH64 diff --git a/src/coreclr/jit/targetloongarch64.h b/src/coreclr/jit/targetloongarch64.h index d27bffa3aa69..2382eaa767cc 100644 --- a/src/coreclr/jit/targetloongarch64.h +++ b/src/coreclr/jit/targetloongarch64.h @@ -83,7 +83,7 @@ // REG_VAR_ORDER is: (CALLEE_TRASH & ~CALLEE_TRASH_NOGC), CALLEE_TRASH_NOGC, CALLEE_SAVED #define REG_VAR_ORDER REG_A0,REG_A1,REG_A2,REG_A3,REG_A4,REG_A5,REG_A6,REG_A7, \ REG_T0,REG_T1,REG_T2,REG_T3,REG_T4,REG_T5,REG_T6,REG_T7,REG_T8, \ - REG_CALLEE_SAVED_ORDER + REG_S0,REG_S1,REG_S2,REG_S3,REG_S4,REG_S5,REG_S6,REG_S7,REG_S8 #define REG_VAR_ORDER_FLT REG_F12,REG_F13,REG_F14,REG_F15,REG_F16,REG_F17,REG_F18,REG_F19, \ REG_F2,REG_F3,REG_F4,REG_F5,REG_F6,REG_F7,REG_F8,REG_F9,REG_F10, \ @@ -91,12 +91,13 @@ REG_F24,REG_F25,REG_F26,REG_F27,REG_F28,REG_F29,REG_F30,REG_F31, \ REG_F1,REG_F0 - #define REG_CALLEE_SAVED_ORDER REG_S0,REG_S1,REG_S2,REG_S3,REG_S4,REG_S5,REG_S6,REG_S7,REG_S8 - #define RBM_CALLEE_SAVED_ORDER RBM_S0,RBM_S1,RBM_S2,RBM_S3,RBM_S4,RBM_S5,RBM_S6,RBM_S7,RBM_S8 + #define RBM_CALL_GC_REGS_ORDER RBM_S0,RBM_S1,RBM_S2,RBM_S3,RBM_S4,RBM_S5,RBM_S6,RBM_S7,RBM_S8,RBM_INTRET,RBM_INTRET_1 + #define RBM_CALL_GC_REGS (RBM_S0|RBM_S1|RBM_S2|RBM_S3|RBM_S4|RBM_S5|RBM_S6|RBM_S7|RBM_S8|RBM_INTRET|RBM_INTRET_1) #define CNT_CALLEE_SAVED (10) //s0-s8,fp. #define CNT_CALLEE_TRASH (17) #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) + #define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED+2) #define CNT_CALLEE_SAVED_FLOAT (8) #define CNT_CALLEE_TRASH_FLOAT (24) @@ -109,6 +110,7 @@ // Temporary registers used for the GS cookie check. #define REG_GSCOOKIE_TMP_0 REG_T0 #define REG_GSCOOKIE_TMP_1 REG_T1 + #define RBM_GSCOOKIE_TMP (RBM_T0|RBM_T1) // register to hold shift amount; no special register is required on LOONGARCH64. #define REG_SHIFT REG_NA diff --git a/src/coreclr/jit/targetriscv64.cpp b/src/coreclr/jit/targetriscv64.cpp index 5c51f66f83c4..ea4c99872b79 100644 --- a/src/coreclr/jit/targetriscv64.cpp +++ b/src/coreclr/jit/targetriscv64.cpp @@ -24,4 +24,148 @@ const regNumber fltArgRegs [] = {REG_FLTARG_0, REG_FLTARG_1, REG_FLTARG_2, REG_F const regMaskTP fltArgMasks[] = {RBM_FLTARG_0, RBM_FLTARG_1, RBM_FLTARG_2, RBM_FLTARG_3, RBM_FLTARG_4, RBM_FLTARG_5, RBM_FLTARG_6, RBM_FLTARG_7 }; // clang-format on +//----------------------------------------------------------------------------- +// RiscV64Classifier: +// Construct a new instance of the RISC-V 64 ABI classifier. +// +// Parameters: +// info - Info about the method being classified. +// +RiscV64Classifier::RiscV64Classifier(const ClassifierInfo& info) + : m_info(info) + , m_intRegs(intArgRegs, ArrLen(intArgRegs)) + , m_floatRegs(fltArgRegs, ArrLen(fltArgRegs)) +{ + assert(!m_info.IsVarArgs); // TODO: varargs currently not supported on RISC-V +} + +//----------------------------------------------------------------------------- +// Classify: +// Classify a parameter for the RISC-V 64 ABI. +// +// Parameters: +// comp - Compiler instance +// type - The type of the parameter +// structLayout - The layout of the struct. Expected to be non-null if +// varTypeIsStruct(type) is true. +// wellKnownParam - Well known type of the parameter (if it may affect its ABI classification) +// +// Returns: +// Classification information for the parameter. +// +ABIPassingInformation RiscV64Classifier::Classify(Compiler* comp, + var_types type, + ClassLayout* structLayout, + WellKnownArg /*wellKnownParam*/) +{ + StructFloatFieldInfoFlags flags = STRUCT_NO_FLOAT_FIELD; + unsigned intFields = 0, floatFields = 0; + unsigned passedSize; + + if (varTypeIsStruct(type)) + { + passedSize = structLayout->GetSize(); + if (passedSize > MAX_PASS_MULTIREG_BYTES) + { + passedSize = TARGET_POINTER_SIZE; // pass by reference + } + else if (!structLayout->IsBlockLayout()) + { + flags = (StructFloatFieldInfoFlags)comp->info.compCompHnd->getRISCV64PassStructInRegisterFlags( + structLayout->GetClassHandle()); + + if ((flags & STRUCT_FLOAT_FIELD_ONLY_ONE) != 0) + { + floatFields = 1; + } + else if ((flags & STRUCT_FLOAT_FIELD_ONLY_TWO) != 0) + { + floatFields = 2; + } + else if (flags != STRUCT_NO_FLOAT_FIELD) + { + assert((flags & (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_SECOND)) != 0); + floatFields = 1; + intFields = 1; + } + } + } + else + { + passedSize = genTypeSize(type); + assert(passedSize <= TARGET_POINTER_SIZE); + floatFields = varTypeIsFloating(type) ? 1 : 0; + } + + assert((floatFields > 0) || (intFields == 0)); + + if ((floatFields > 0) && (m_floatRegs.Count() >= floatFields) && (m_intRegs.Count() >= intFields)) + { + // Hardware floating-point calling convention + if ((floatFields == 1) && (intFields == 0)) + { + if (flags == STRUCT_NO_FLOAT_FIELD) + assert(varTypeIsFloating(type)); // standalone floating-point real + else + assert((flags & STRUCT_FLOAT_FIELD_ONLY_ONE) != 0); // struct containing just one FP real + + return ABIPassingInformation::FromSegment(comp, ABIPassingSegment::InRegister(m_floatRegs.Dequeue(), 0, + passedSize)); + } + else + { + assert(varTypeIsStruct(type)); + assert((floatFields + intFields) == 2); + assert(flags != STRUCT_NO_FLOAT_FIELD); + assert((flags & STRUCT_FLOAT_FIELD_ONLY_ONE) == 0); + + unsigned firstSize = ((flags & STRUCT_FIRST_FIELD_SIZE_IS8) != 0) ? 8 : 4; + unsigned secondSize = ((flags & STRUCT_SECOND_FIELD_SIZE_IS8) != 0) ? 8 : 4; + unsigned offset = max(firstSize, secondSize); // TODO: cover empty fields and custom offsets / alignments + + bool isFirstFloat = (flags & (STRUCT_FLOAT_FIELD_ONLY_TWO | STRUCT_FLOAT_FIELD_FIRST)) != 0; + bool isSecondFloat = (flags & (STRUCT_FLOAT_FIELD_ONLY_TWO | STRUCT_FLOAT_FIELD_SECOND)) != 0; + assert(isFirstFloat || isSecondFloat); + + regNumber firstReg = (isFirstFloat ? m_floatRegs : m_intRegs).Dequeue(); + regNumber secondReg = (isSecondFloat ? m_floatRegs : m_intRegs).Dequeue(); + + return {2, new (comp, CMK_ABI) + ABIPassingSegment[2]{ABIPassingSegment::InRegister(firstReg, 0, firstSize), + ABIPassingSegment::InRegister(secondReg, offset, secondSize)}}; + } + } + else + { + // Integer calling convention + auto passSlot = [this](unsigned offset, unsigned size) -> ABIPassingSegment { + assert(size > 0); + assert(size <= TARGET_POINTER_SIZE); + if (m_intRegs.Count() > 0) + { + return ABIPassingSegment::InRegister(m_intRegs.Dequeue(), offset, size); + } + else + { + assert((m_stackArgSize % TARGET_POINTER_SIZE) == 0); + ABIPassingSegment seg = ABIPassingSegment::OnStack(m_stackArgSize, offset, size); + m_stackArgSize += TARGET_POINTER_SIZE; + return seg; + } + }; + + if (passedSize <= TARGET_POINTER_SIZE) + { + return ABIPassingInformation::FromSegment(comp, passSlot(0, passedSize)); + } + else + { + assert(varTypeIsStruct(type)); + return {2, new (comp, CMK_ABI) + ABIPassingSegment[2]{passSlot(0, TARGET_POINTER_SIZE), + passSlot(TARGET_POINTER_SIZE, passedSize - TARGET_POINTER_SIZE)}}; + } + } +} + #endif // TARGET_RISCV64 diff --git a/src/coreclr/jit/targetriscv64.h b/src/coreclr/jit/targetriscv64.h index 33c1b0d49190..a0d5254dc5d1 100644 --- a/src/coreclr/jit/targetriscv64.h +++ b/src/coreclr/jit/targetriscv64.h @@ -78,7 +78,7 @@ // REG_VAR_ORDER is: (CALLEE_TRASH & ~CALLEE_TRASH_NOGC), CALLEE_TRASH_NOGC, CALLEE_SAVED #define REG_VAR_ORDER REG_A0,REG_A1,REG_A2,REG_A3,REG_A4,REG_A5,REG_A6,REG_A7, \ REG_T0,REG_T1,REG_T2,REG_T3,REG_T4,REG_T5,REG_T6, \ - REG_CALLEE_SAVED_ORDER + REG_S1,REG_S2,REG_S3,REG_S4,REG_S5,REG_S6,REG_S7,REG_S8,REG_S9,REG_S10,REG_S11 #define REG_VAR_ORDER_FLT REG_F12,REG_F13,REG_F14,REG_F15,REG_F16,REG_F17,REG_F18,REG_F19, \ REG_F2,REG_F3,REG_F4,REG_F5,REG_F6,REG_F7,REG_F8,REG_F9,REG_F10, \ @@ -86,12 +86,13 @@ REG_F24,REG_F25,REG_F26,REG_F27,REG_F28,REG_F29,REG_F30,REG_F31, \ REG_F1,REG_F0 - #define REG_CALLEE_SAVED_ORDER REG_S1,REG_S2,REG_S3,REG_S4,REG_S5,REG_S6,REG_S7,REG_S8,REG_S9,REG_S10,REG_S11 - #define RBM_CALLEE_SAVED_ORDER RBM_S1,RBM_S2,RBM_S3,RBM_S4,RBM_S5,RBM_S6,RBM_S7,RBM_S8,RBM_S9,RBM_S10,RBM_S11 + #define RBM_CALL_GC_REGS_ORDER RBM_S1,RBM_S2,RBM_S3,RBM_S4,RBM_S5,RBM_S6,RBM_S7,RBM_S8,RBM_S9,RBM_S10,RBM_S11,RBM_INTRET,RBM_INTRET_1 + #define RBM_CALL_GC_REGS (RBM_S1|RBM_S2|RBM_S3|RBM_S4|RBM_S5|RBM_S6|RBM_S7|RBM_S8|RBM_S9|RBM_S10|RBM_S11|RBM_INTRET|RBM_INTRET_1) #define CNT_CALLEE_SAVED (11) #define CNT_CALLEE_TRASH (15) #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) + #define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED+2) #define CNT_CALLEE_SAVED_FLOAT (12) #define CNT_CALLEE_TRASH_FLOAT (20) diff --git a/src/coreclr/jit/targetwasm.cpp b/src/coreclr/jit/targetwasm.cpp index 2e7590ea5f91..268de1839bed 100644 --- a/src/coreclr/jit/targetwasm.cpp +++ b/src/coreclr/jit/targetwasm.cpp @@ -8,14 +8,61 @@ #pragma hdrstop #endif +#include "llvm.h" #include "target.h" const char* Target::g_tgtCPUName = "wasm"; const Target::ArgOrder Target::g_tgtArgOrder = ARG_ORDER_R2L; const Target::ArgOrder Target::g_tgtUnmanagedArgOrder = ARG_ORDER_R2L; -const regNumber intArgRegs [] = { REG_R0 }; -const regMaskTP intArgMasks[] = { RBM_R0 }; -const regNumber fltArgRegs [] = { REG_F0 }; -const regMaskTP fltArgMasks[] = { RBM_F0 }; // clang-format on + +const regNumber intArgRegs[] = { REG_STK }; +const regNumber fltArgRegs[] = { REG_STK }; + +//----------------------------------------------------------------------------- +// WasmClassifier: +// Construct a new instance of the Wasm ABI classifier. +// +// Parameters: +// info - Info about the method being classified. +// +WasmClassifier::WasmClassifier(const ClassifierInfo& info) + : m_info(info) +{ +} + +//----------------------------------------------------------------------------- +// Classify: +// Classify a parameter for the Wasm ABI. +// +// Parameters: +// comp - Compiler instance +// type - The type of the parameter +// structLayout - The layout of the struct. Expected to be non-null if +// varTypeIsStruct(type) is true. +// wellKnownParam - Well known type of the parameter (if it may affect its ABI classification) +// +// Returns: +// Classification information for the parameter. +// +ABIPassingInformation WasmClassifier::Classify(Compiler* comp, + var_types type, + ClassLayout* structLayout, + WellKnownArg wellKnownParam) +{ + if (type == TYP_STRUCT) + { + structPassingKind wbPassStruct; + type = comp->m_llvm->GetArgTypeForStructWasm(structLayout->GetClassHandle(), &wbPassStruct); + } + + assert(type != TYP_STRUCT); + + unsigned typeSize = genTypeSize(type); + + ABIPassingSegment segment = ABIPassingSegment::OnStack(m_stackArgSize, 0, typeSize); + m_stackArgSize += typeSize; + + return ABIPassingInformation::FromSegment(comp, segment); +} diff --git a/src/coreclr/jit/targetwasm.h b/src/coreclr/jit/targetwasm.h index fa99a91c1b7d..77353143c1fe 100644 --- a/src/coreclr/jit/targetwasm.h +++ b/src/coreclr/jit/targetwasm.h @@ -72,12 +72,15 @@ #define RBM_ALLINT RBM_R0 + #define RBM_CALL_GC_REGS_ORDER RBM_NONE + #define CNT_CALLEE_SAVED 1 #define CNT_CALLEE_TRASH 0 // This and below are only used for CSE heuristics; thus an optimistic estimate for an "average" target. #define CNT_CALLEE_ENREG 8 #define CNT_CALLEE_SAVED_FLOAT 8 #define CNT_CALLEE_TRASH_FLOAT 4 + #define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED) // This is how targetx86 is defined. #define REG_CALLEE_SAVED_ORDER REG_R0 #define RBM_CALLEE_SAVED_ORDER RBM_R0 diff --git a/src/coreclr/jit/targetx86.cpp b/src/coreclr/jit/targetx86.cpp index 5c2702d47288..eb6ced79ce1e 100644 --- a/src/coreclr/jit/targetx86.cpp +++ b/src/coreclr/jit/targetx86.cpp @@ -29,7 +29,8 @@ const regMaskTP intArgMasks[] = {RBM_ECX, RBM_EDX}; // info - Info about the method being classified. // X86Classifier::X86Classifier(const ClassifierInfo& info) - : m_regs(nullptr, 0) + : m_info(info) + , m_regs(nullptr, 0) { switch (info.CallConv) { @@ -113,8 +114,26 @@ ABIPassingInformation X86Classifier::Classify(Compiler* comp, else { assert((m_stackArgSize % TARGET_POINTER_SIZE) == 0); - segment = ABIPassingSegment::OnStack(m_stackArgSize, 0, size); - m_stackArgSize += roundUp(size, TARGET_POINTER_SIZE); + + unsigned offset; + unsigned roundedArgSize = roundUp(size, TARGET_POINTER_SIZE); + if (m_info.CallConv == CorInfoCallConvExtension::Managed) + { + // The managed ABI pushes parameters in left-to-right order. This + // means that on the stack the first parameter is at the higher + // offset (farthest away from ESP on entry). We model the stack + // offset as the value to subtract from the top of the stack for + // this ABI, see ABIPassingSegment::GetStackOffset. + m_stackArgSize += roundedArgSize; + offset = m_stackArgSize; + } + else + { + offset = m_stackArgSize; + m_stackArgSize += roundedArgSize; + } + + segment = ABIPassingSegment::OnStack(offset, 0, size); } return ABIPassingInformation::FromSegment(comp, segment); diff --git a/src/coreclr/jit/targetx86.h b/src/coreclr/jit/targetx86.h index dfeb96ae9e97..aa142f6cff0d 100644 --- a/src/coreclr/jit/targetx86.h +++ b/src/coreclr/jit/targetx86.h @@ -145,12 +145,15 @@ #define MAX_VAR_ORDER_SIZE 6 // The order here is fixed: it must agree with an order assumed in eetwain... - #define REG_CALLEE_SAVED_ORDER REG_EDI,REG_ESI,REG_EBX,REG_EBP - #define RBM_CALLEE_SAVED_ORDER RBM_EDI,RBM_ESI,RBM_EBX,RBM_EBP + // NB: x86 GC decoder does not report return registers at call sites. + #define RBM_CALL_GC_REGS_ORDER RBM_EDI,RBM_ESI,RBM_EBX,RBM_EBP + #define RBM_CALL_GC_REGS (RBM_EDI|RBM_ESI|RBM_EBX|RBM_EBP) #define CNT_CALLEE_SAVED (4) #define CNT_CALLEE_TRASH (3) #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) + // NB: x86 GC decoder does not report return registers at call sites. + #define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED) #define CNT_CALLEE_SAVED_FLOAT (0) #define CNT_CALLEE_TRASH_FLOAT (6) diff --git a/src/coreclr/jit/unwindarmarch.cpp b/src/coreclr/jit/unwindarmarch.cpp index 51af7f24889d..ac67a14428dc 100644 --- a/src/coreclr/jit/unwindarmarch.cpp +++ b/src/coreclr/jit/unwindarmarch.cpp @@ -233,12 +233,12 @@ void Compiler::unwindPushPopMaskInt(regMaskTP maskInt, bool useOpsize16) if (shortFormat) { // D0-D7 : pop {r4-rX,lr} (X=4-7) (opsize 16) - pu->AddCode(0xD0 | ((maskInt >> 12) & 0x4) | val); + pu->AddCode((BYTE)(0xD0 | ((maskInt >> 12) & 0x4) | val)); } else { // EC-ED : pop {r0-r7,lr} (opsize 16) - pu->AddCode(0xEC | ((maskInt >> 14) & 0x1), (BYTE)maskInt); + pu->AddCode((BYTE)(0xEC | ((maskInt >> 14) & 0x1)), (BYTE)maskInt); } } else @@ -272,12 +272,12 @@ void Compiler::unwindPushPopMaskInt(regMaskTP maskInt, bool useOpsize16) if (shortFormat) { // D8-DF : pop {r4-rX,lr} (X=8-11) (opsize 32) - pu->AddCode(0xD8 | ((maskInt >> 12) & 0x4) | val); + pu->AddCode((BYTE)(0xD8 | ((maskInt >> 12) & 0x4) | val)); } else { // 80-BF : pop {r0-r12,lr} (opsize 32) - pu->AddCode(0x80 | ((maskInt >> 8) & 0x1F) | ((maskInt >> 9) & 0x20), (BYTE)maskInt); + pu->AddCode((BYTE)(0x80 | ((maskInt >> 8) & 0x1F) | ((maskInt >> 9) & 0x20)), (BYTE)maskInt); } } } diff --git a/src/coreclr/jit/utils.cpp b/src/coreclr/jit/utils.cpp index 78b61131e4ca..aa507c5c89fa 100644 --- a/src/coreclr/jit/utils.cpp +++ b/src/coreclr/jit/utils.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. // =================================================================================================== @@ -417,11 +417,6 @@ const char* dspRegRange(regMaskTP regMask, size_t& minSiz, const char* sep, regN sep = " "; } - if (regBit > regMask) - { - break; - } - regPrev = regNum; } @@ -505,7 +500,7 @@ unsigned dumpSingleInstr(const BYTE* const codeAddr, IL_OFFSET offs, const char* } OPCODE opcode = (OPCODE)getU1LittleEndian(opcodePtr); - opcodePtr += sizeof(__int8); + opcodePtr += sizeof(int8_t); DECODE_OPCODE: @@ -526,12 +521,12 @@ unsigned dumpSingleInstr(const BYTE* const codeAddr, IL_OFFSET offs, const char* { case CEE_PREFIX1: opcode = OPCODE(getU1LittleEndian(opcodePtr) + 256); - opcodePtr += sizeof(__int8); + opcodePtr += sizeof(int8_t); goto DECODE_OPCODE; default: { - __int64 iOp; + int64_t iOp; double dOp; int jOp; DWORD jOp2; @@ -563,7 +558,7 @@ unsigned dumpSingleInstr(const BYTE* const codeAddr, IL_OFFSET offs, const char* goto INT_OP; case InlineI8: iOp = getU4LittleEndian(opcodePtr); - iOp |= (__int64)getU4LittleEndian(opcodePtr + 4) << 32; + iOp |= (int64_t)getU4LittleEndian(opcodePtr + 4) << 32; goto INT_OP; INT_OP: @@ -1751,7 +1746,7 @@ void HelperCallProperties::init() case CORINFO_HELP_CHECKED_ASSIGN_REF: case CORINFO_HELP_ASSIGN_REF_ENSURE_NONHEAP: case CORINFO_HELP_ASSIGN_BYREF: - case CORINFO_HELP_ASSIGN_STRUCT: + case CORINFO_HELP_BULK_WRITEBARRIER: mutatesHeap = true; break; @@ -2188,7 +2183,7 @@ CycleCount::CycleCount() { } -bool CycleCount::GetCycles(unsigned __int64* time) +bool CycleCount::GetCycles(uint64_t* time) { return CycleTimer::GetThreadCyclesS(time); } @@ -2200,7 +2195,7 @@ bool CycleCount::Start() double CycleCount::ElapsedTime() { - unsigned __int64 nowCycles; + uint64_t nowCycles; (void)GetCycles(&nowCycles); return ((double)(nowCycles - beginCycles) / cps) * 1000.0; } @@ -2259,79 +2254,20 @@ unsigned CountDigits(double num, unsigned base /* = 10 */) #endif // DEBUG -double FloatingPointUtils::convertUInt64ToDouble(unsigned __int64 uIntVal) -{ - __int64 s64 = uIntVal; - double d; - if (s64 < 0) - { -#if defined(TARGET_XARCH) - // RyuJIT codegen and clang (or gcc) may produce different results for casting uint64 to - // double, and the clang result is more accurate. For example, - // 1) (double)0x84595161401484A0UL --> 43e08b2a2c280290 (RyuJIT codegen or VC++) - // 2) (double)0x84595161401484A0UL --> 43e08b2a2c280291 (clang or gcc) - // If the folding optimization below is implemented by simple casting of (double)uint64_val - // and it is compiled by clang, casting result can be inconsistent, depending on whether - // the folding optimization is triggered or the codegen generates instructions for casting. // - // The current solution is to force the same math as the codegen does, so that casting - // result is always consistent. - - // d = (double)(int64_t)uint64 + 0x1p64 - uint64_t adjHex = 0x43F0000000000000UL; - d = (double)s64 + *(double*)&adjHex; -#else - d = (double)uIntVal; -#endif - } - else - { - d = (double)uIntVal; - } - return d; +double FloatingPointUtils::convertUInt64ToDouble(uint64_t uIntVal) +{ + return (double)uIntVal; } -float FloatingPointUtils::convertUInt64ToFloat(unsigned __int64 u64) +float FloatingPointUtils::convertUInt64ToFloat(uint64_t u64) { double d = convertUInt64ToDouble(u64); return (float)d; } -unsigned __int64 FloatingPointUtils::convertDoubleToUInt64(double d) +uint64_t FloatingPointUtils::convertDoubleToUInt64(double d) { - unsigned __int64 u64; - if (d >= 0.0) - { - // Work around a C++ issue where it doesn't properly convert large positive doubles - const double two63 = 2147483648.0 * 4294967296.0; - if (d < two63) - { - u64 = UINT64(d); - } - else - { - // subtract 0x8000000000000000, do the convert then add it back again - u64 = INT64(d - two63) + I64(0x8000000000000000); - } - return u64; - } - -#ifdef TARGET_XARCH - - // While the Ecma spec does not specifically call this out, - // the case of conversion from negative double to unsigned integer is - // effectively an overflow and therefore the result is unspecified. - // With MSVC for x86/x64, such a conversion results in the bit-equivalent - // unsigned value of the conversion to integer. Other compilers convert - // negative doubles to zero when the target is unsigned. - // To make the behavior consistent across OS's on TARGET_XARCH, - // this double cast is needed to conform MSVC behavior. - - u64 = UINT64(INT64(d)); -#else - u64 = UINT64(d); -#endif // TARGET_XARCH - - return u64; + return (uint64_t)d; } //------------------------------------------------------------------------ @@ -3465,11 +3401,6 @@ uint32_t BitOperations::Log2(uint64_t value) // Return Value: // The population count (number of bits set) of value // -#if defined(_MSC_VER) -// Disable optimizations for PopCount to avoid the compiler from generating intrinsics -// not supported on all platforms. -#pragma optimize("", off) -#endif // _MSC_VER uint32_t BitOperations::PopCount(uint32_t value) { #if defined(_MSC_VER) @@ -3522,9 +3453,6 @@ uint32_t BitOperations::PopCount(uint64_t value) return static_cast(result); #endif } -#if defined(_MSC_VER) -#pragma optimize("", on) -#endif // _MSC_VER //------------------------------------------------------------------------ // BitOperations::ReverseBits: Reverses the bits in an integer value diff --git a/src/coreclr/jit/utils.h b/src/coreclr/jit/utils.h index 6a0362bbbf06..f665a4e813ef 100644 --- a/src/coreclr/jit/utils.h +++ b/src/coreclr/jit/utils.h @@ -752,8 +752,8 @@ class MethodSet class CycleCount { private: - double cps; // cycles per second - unsigned __int64 beginCycles; // cycles at stop watch construction + double cps; // cycles per second + uint64_t beginCycles; // cycles at stop watch construction public: CycleCount(); @@ -766,7 +766,7 @@ class CycleCount private: // Return true if successful. - bool GetCycles(unsigned __int64* time); + bool GetCycles(uint64_t* time); }; // Uses win API QueryPerformanceCounter/QueryPerformanceFrequency. @@ -802,11 +802,11 @@ unsigned CountDigits(double num, unsigned base = 10); class FloatingPointUtils { public: - static double convertUInt64ToDouble(unsigned __int64 u64); + static double convertUInt64ToDouble(uint64_t u64); - static float convertUInt64ToFloat(unsigned __int64 u64); + static float convertUInt64ToFloat(uint64_t u64); - static unsigned __int64 convertDoubleToUInt64(double d); + static uint64_t convertDoubleToUInt64(double d); static double convertToDouble(float f); diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 97c3be213963..2ac65b2c4b00 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -6525,6 +6525,7 @@ bool ValueNumStore::IsVNPositiveInt32Constant(ValueNum vn) // IsVNArrLenUnsignedBound: Checks if the specified vn represents an expression // of one of the following forms: // - "(uint)i < (uint)len" that implies (0 <= i < len) +// - "(ulong)i < (ulong)len" that implies (0 <= i < len) // - "const < (uint)len" that implies "len > const" // - "const <= (uint)len" that implies "len > const - 1" // @@ -6548,49 +6549,57 @@ bool ValueNumStore::IsVNUnsignedCompareCheckedBound(ValueNum vn, UnsignedCompare if ((funcApp.m_func == VNF_LT_UN) || (funcApp.m_func == VNF_GE_UN)) { // We only care about "(uint)i < (uint)len" and its negation "(uint)i >= (uint)len" - if (IsVNCheckedBound(funcApp.m_args[1])) + // Same for (ulong) + ValueNum vnBound = funcApp.m_args[1]; + ValueNum vnIdx = funcApp.m_args[0]; + ValueNum vnCastOp = NoVN; + if (IsVNCheckedBound(vnBound) || (IsVNCastToULong(vnBound, &vnCastOp) && IsVNCheckedBound(vnCastOp))) { - info->vnIdx = funcApp.m_args[0]; + info->vnIdx = vnIdx; info->cmpOper = funcApp.m_func; - info->vnBound = funcApp.m_args[1]; + info->vnBound = (vnCastOp != NoVN) ? vnCastOp : vnBound; return true; } // We care about (uint)len < constant and its negation "(uint)len >= constant" - else if (IsVNPositiveInt32Constant(funcApp.m_args[1]) && IsVNCheckedBound(funcApp.m_args[0])) + else if (IsVNPositiveInt32Constant(vnBound) && IsVNCheckedBound(vnIdx)) { // Change constant < len into (uint)len >= (constant - 1) // to make consuming this simpler (and likewise for it's negation). - INT32 validIndex = ConstantValue(funcApp.m_args[1]) - 1; + INT32 validIndex = ConstantValue(vnBound) - 1; assert(validIndex >= 0); info->vnIdx = VNForIntCon(validIndex); info->cmpOper = (funcApp.m_func == VNF_GE_UN) ? VNF_LT_UN : VNF_GE_UN; - info->vnBound = funcApp.m_args[0]; + info->vnBound = vnIdx; return true; } } else if ((funcApp.m_func == VNF_GT_UN) || (funcApp.m_func == VNF_LE_UN)) { // We only care about "(uint)a.len > (uint)i" and its negation "(uint)a.len <= (uint)i" - if (IsVNCheckedBound(funcApp.m_args[0])) + // Same for (ulong) + ValueNum vnBound = funcApp.m_args[0]; + ValueNum vnIdx = funcApp.m_args[1]; + ValueNum vnCastOp = NoVN; + if (IsVNCheckedBound(vnBound) || (IsVNCastToULong(vnBound, &vnCastOp) && IsVNCheckedBound(vnCastOp))) { - info->vnIdx = funcApp.m_args[1]; + info->vnIdx = vnIdx; // Let's keep a consistent operand order - it's always i < len, never len > i info->cmpOper = (funcApp.m_func == VNF_GT_UN) ? VNF_LT_UN : VNF_GE_UN; - info->vnBound = funcApp.m_args[0]; + info->vnBound = (vnCastOp != NoVN) ? vnCastOp : vnBound; return true; } // Look for constant > (uint)len and its negation "constant <= (uint)len" - else if (IsVNPositiveInt32Constant(funcApp.m_args[0]) && IsVNCheckedBound(funcApp.m_args[1])) + else if (IsVNPositiveInt32Constant(vnBound) && IsVNCheckedBound(vnIdx)) { // Change constant <= (uint)len to (constant - 1) < (uint)len // to make consuming this simpler (and likewise for it's negation). - INT32 validIndex = ConstantValue(funcApp.m_args[0]) - 1; + INT32 validIndex = ConstantValue(vnBound) - 1; assert(validIndex >= 0); info->vnIdx = VNForIntCon(validIndex); info->cmpOper = (funcApp.m_func == VNF_LE_UN) ? VNF_LT_UN : VNF_GE_UN; - info->vnBound = funcApp.m_args[1]; + info->vnBound = vnIdx; return true; } } @@ -6673,15 +6682,17 @@ void ValueNumStore::GetCheckedBoundArithInfo(ValueNum vn, CompareCheckedBoundAri bool isOp1CheckedBound = IsVNCheckedBound(funcArith.m_args[1]); if (isOp1CheckedBound) { - info->arrOper = funcArith.m_func; - info->arrOp = funcArith.m_args[0]; - info->vnBound = funcArith.m_args[1]; + info->arrOper = funcArith.m_func; + info->arrOp = funcArith.m_args[0]; + info->vnBound = funcArith.m_args[1]; + info->arrOpLHS = true; } else { - info->arrOper = funcArith.m_func; - info->arrOp = funcArith.m_args[1]; - info->vnBound = funcArith.m_args[0]; + info->arrOper = funcArith.m_func; + info->arrOp = funcArith.m_args[1]; + info->vnBound = funcArith.m_args[0]; + info->arrOpLHS = false; } } @@ -6825,6 +6836,33 @@ bool ValueNumStore::IsVNCheckedBound(ValueNum vn) return false; } +//---------------------------------------------------------------------------------- +// IsVNCastToULong: checks whether the given VN represents (ulong)op cast +// +// Arguments: +// vn - VN, presumably, representing (ulong)op cast +// castedOp - [Out] VN of op being cast +// +// Return Value: +// true if the given VN represents (ulong)op cast +// +bool ValueNumStore::IsVNCastToULong(ValueNum vn, ValueNum* castedOp) +{ + VNFuncApp funcApp; + if (GetVNFunc(vn, &funcApp) && (funcApp.m_func == VNF_Cast)) + { + var_types castToType; + bool srcIsUnsigned; + GetCastOperFromVN(funcApp.m_args[1], &castToType, &srcIsUnsigned); + if (srcIsUnsigned && (castToType == TYP_LONG)) + { + *castedOp = funcApp.m_args[0]; + return true; + } + } + return false; +} + void ValueNumStore::SetVNIsCheckedBound(ValueNum vn) { // This is meant to flag VNs for lengths that aren't known at compile time, so we can @@ -9573,7 +9611,8 @@ static genTreeOps genTreeOpsIllegalAsVNFunc[] = {GT_IND, // When we do heap memo GT_NOP, // These control-flow operations need no values. - GT_JTRUE, GT_RETURN, GT_SWITCH, GT_RETFILT, GT_CKFINITE}; + GT_JTRUE, GT_RETURN, GT_SWITCH, GT_RETFILT, GT_CKFINITE, + GT_SWIFT_ERROR_RET}; void ValueNumStore::ValidateValueNumStoreStatics() { @@ -11700,6 +11739,28 @@ void Compiler::fgValueNumberTree(GenTree* tree) } break; + // GT_SWIFT_ERROR_RET is similar to GT_RETURN, but it's a binary node, and its return value is op2. + case GT_SWIFT_ERROR_RET: + if (tree->gtGetOp2() != nullptr) + { + // We have a return value and an error value. + ValueNumPair vnp; + ValueNumPair op1Xvnp; + ValueNumPair op2Xvnp; + vnStore->VNPUnpackExc(tree->gtGetOp1()->gtVNPair, &vnp, &op1Xvnp); + vnStore->VNPUnpackExc(tree->gtGetOp2()->gtVNPair, &vnp, &op2Xvnp); + + const ValueNumPair excSetPair = vnStore->VNPExcSetUnion(op1Xvnp, op2Xvnp); + tree->gtVNPair = vnStore->VNPWithExc(vnStore->VNPForVoid(), excSetPair); + } + else + { + // We only have the error value. + tree->gtVNPair = vnStore->VNPWithExc(vnStore->VNPForVoid(), + vnStore->VNPExceptionSet(tree->gtGetOp1()->gtVNPair)); + } + break; + // BOX and CKFINITE are passthrough nodes (like NOP). We'll add the exception for the latter later. case GT_BOX: case GT_CKFINITE: @@ -12687,7 +12748,7 @@ bool Compiler::fgValueNumberSpecialIntrinsic(GenTreeCall* call) void Compiler::fgValueNumberCall(GenTreeCall* call) { - if (call->gtCallType == CT_HELPER) + if (call->IsHelperCall()) { bool modHeap = fgValueNumberHelperCall(call); @@ -13148,10 +13209,101 @@ bool Compiler::fgValueNumberHelperCall(GenTreeCall* call) // InvalidCastExc for these is set in VNForCast break; + case CORINFO_HELP_READYTORUN_CHKCAST: + { + // This helper casts to a class determined by the entry point. + ssize_t addrValue = (ssize_t)call->gtEntryPoint.addr; + ValueNum callAddrVN = vnStore->VNForHandle(addrValue, GTF_ICON_FTN_ADDR); + vnpExc = vnStore->VNPExcSetSingleton( + vnStore->VNPairForFunc(TYP_REF, VNF_R2RInvalidCastExc, + vnStore->VNPNormalPair( + call->gtArgs.GetUserArgByIndex(0)->GetNode()->gtVNPair), + ValueNumPair(callAddrVN, callAddrVN))); + break; + } + + case CORINFO_HELP_GETSHARED_GCSTATIC_BASE: + case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE: + case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS: + case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS: + case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE: + case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE: + case CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS: + case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS: + case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS: + // These all take (Module*, class ID) as parameters. + // + // Strictly speaking the exact possible exception thrown by the + // static constructor depends on heap state too, but given that + // the constructor is only invoked once we can model that for + // the same class the same exceptions are thrown. Downstream + // code like CSE/copy prop that makes use VNs innately need to + // establish some form of dominance around the individual trees + // that makes this ok. + // + vnpExc = vnStore->VNPExcSetSingleton( + vnStore->VNPairForFunc(TYP_REF, VNF_ClassInitExc, + vnStore->VNPNormalPair( + call->gtArgs.GetUserArgByIndex(0)->GetNode()->gtVNPair), + vnStore->VNPNormalPair( + call->gtArgs.GetUserArgByIndex(1)->GetNode()->gtVNPair))); + break; + +#ifdef FEATURE_READYTORUN + case CORINFO_HELP_READYTORUN_GCSTATIC_BASE: + case CORINFO_HELP_READYTORUN_NONGCSTATIC_BASE: + case CORINFO_HELP_READYTORUN_THREADSTATIC_BASE: + case CORINFO_HELP_READYTORUN_NONGCTHREADSTATIC_BASE: + case CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE: + { + // These are uniquely determined by the entry point. + ssize_t addrValue = (ssize_t)call->gtEntryPoint.addr; + ValueNum callAddrVN = vnStore->VNForHandle(addrValue, GTF_ICON_FTN_ADDR); + vnpExc = vnStore->VNPExcSetSingleton( + vnStore->VNPairForFunc(TYP_REF, VNF_R2RClassInitExc, ValueNumPair(callAddrVN, callAddrVN))); + break; + } +#endif + + case CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE: + case CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE: + case CORINFO_HELP_GETGENERICS_GCSTATIC_BASE: + case CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE: + // These take class handles as parameters. + vnpExc = vnStore->VNPExcSetSingleton( + vnStore->VNPairForFunc(TYP_REF, VNF_ClassInitGenericExc, + vnStore->VNPNormalPair( + call->gtArgs.GetUserArgByIndex(0)->GetNode()->gtVNPair))); + break; + + case CORINFO_HELP_DIV: + case CORINFO_HELP_LDIV: + vnpExc = fgValueNumberDivisionExceptions(GT_DIV, call->gtArgs.GetUserArgByIndex(0)->GetNode(), + call->gtArgs.GetUserArgByIndex(1)->GetNode()); + break; + case CORINFO_HELP_MOD: + case CORINFO_HELP_LMOD: + vnpExc = fgValueNumberDivisionExceptions(GT_MOD, call->gtArgs.GetUserArgByIndex(0)->GetNode(), + call->gtArgs.GetUserArgByIndex(1)->GetNode()); + break; + case CORINFO_HELP_UDIV: + case CORINFO_HELP_ULDIV: + vnpExc = fgValueNumberDivisionExceptions(GT_UDIV, call->gtArgs.GetUserArgByIndex(0)->GetNode(), + call->gtArgs.GetUserArgByIndex(1)->GetNode()); + break; + case CORINFO_HELP_UMOD: + case CORINFO_HELP_ULMOD: + vnpExc = fgValueNumberDivisionExceptions(GT_UMOD, call->gtArgs.GetUserArgByIndex(0)->GetNode(), + call->gtArgs.GetUserArgByIndex(1)->GetNode()); + break; + default: // Setup vnpExc with the information that multiple different exceptions - // could be generated by this helper - vnpExc = vnStore->VNPExcSetSingleton(vnStore->VNPairForFunc(TYP_REF, VNF_HelperMultipleExc)); + // could be generated by this helper, in an opaque way + vnpExc = + vnStore->VNPExcSetSingleton(vnStore->VNPairForFunc(TYP_REF, VNF_HelperOpaqueExc, + vnStore->VNPairForExpr(compCurBB, TYP_I_IMPL))); + break; } } @@ -13329,10 +13481,31 @@ void Compiler::fgValueNumberAddExceptionSetForIndirection(GenTree* tree, GenTree // void Compiler::fgValueNumberAddExceptionSetForDivision(GenTree* tree) { - genTreeOps oper = tree->OperGet(); + ValueNumPair exceptions = fgValueNumberDivisionExceptions(tree->OperGet(), tree->gtGetOp1(), tree->gtGetOp2()); + // Unpack, Norm,Exc for the tree's VN + ValueNumPair vnpTreeNorm; + ValueNumPair vnpTreeExc; + vnStore->VNPUnpackExc(tree->gtVNPair, &vnpTreeNorm, &vnpTreeExc); + ValueNumPair newExcSet = vnStore->VNPExcSetUnion(vnpTreeExc, exceptions); + tree->gtVNPair = vnStore->VNPWithExc(vnpTreeNorm, newExcSet); +} + +//-------------------------------------------------------------------------------- +// fgValueNumberDivisionExceptions +// Compute exception set for a division operation +// +// Arguments: +// oper - Division operation (signed/unsigned division/modulo) +// dividend - Tree representing dividend +// divisor - Tree representing divisor +// +// Return Value: +// VNP representing exception set +// +ValueNumPair Compiler::fgValueNumberDivisionExceptions(genTreeOps oper, GenTree* dividend, GenTree* divisor) +{ // A Divide By Zero exception may be possible. - // The divisor is held in tree->AsOp()->gtOp2 // bool isUnsignedOper = (oper == GT_UDIV) || (oper == GT_UMOD); bool needDivideByZeroExcLib = true; @@ -13341,19 +13514,19 @@ void Compiler::fgValueNumberAddExceptionSetForDivision(GenTree* tree) bool needArithmeticExcCon = !isUnsignedOper; // Determine if we have a 32-bit or 64-bit divide operation - var_types typ = genActualType(tree->TypeGet()); + var_types typ = genActualType(dividend); assert((typ == TYP_INT) || (typ == TYP_LONG)); - // Retrieve the Norm VN for op2 to use it for the DivideByZeroExc - ValueNumPair vnpOp2Norm = vnStore->VNPNormalPair(tree->AsOp()->gtOp2->gtVNPair); - ValueNum vnOp2NormLib = vnpOp2Norm.GetLiberal(); - ValueNum vnOp2NormCon = vnpOp2Norm.GetConservative(); + // Retrieve the Norm VN for divisor to use it for the DivideByZeroExc + ValueNumPair vnpDisivorNorm = vnStore->VNPNormalPair(divisor->gtVNPair); + ValueNum vnDivisorNormLib = vnpDisivorNorm.GetLiberal(); + ValueNum vnDivisorNormCon = vnpDisivorNorm.GetConservative(); if (typ == TYP_INT) { - if (vnStore->IsVNConstant(vnOp2NormLib)) + if (vnStore->IsVNConstant(vnDivisorNormLib)) { - INT32 kVal = vnStore->ConstantValue(vnOp2NormLib); + INT32 kVal = vnStore->ConstantValue(vnDivisorNormLib); if (kVal != 0) { needDivideByZeroExcLib = false; @@ -13363,9 +13536,9 @@ void Compiler::fgValueNumberAddExceptionSetForDivision(GenTree* tree) needArithmeticExcLib = false; } } - if (vnStore->IsVNConstant(vnOp2NormCon)) + if (vnStore->IsVNConstant(vnDivisorNormCon)) { - INT32 kVal = vnStore->ConstantValue(vnOp2NormCon); + INT32 kVal = vnStore->ConstantValue(vnDivisorNormCon); if (kVal != 0) { needDivideByZeroExcCon = false; @@ -13378,9 +13551,9 @@ void Compiler::fgValueNumberAddExceptionSetForDivision(GenTree* tree) } else // (typ == TYP_LONG) { - if (vnStore->IsVNConstant(vnOp2NormLib)) + if (vnStore->IsVNConstant(vnDivisorNormLib)) { - INT64 kVal = vnStore->ConstantValue(vnOp2NormLib); + INT64 kVal = vnStore->ConstantValue(vnDivisorNormLib); if (kVal != 0) { needDivideByZeroExcLib = false; @@ -13390,9 +13563,9 @@ void Compiler::fgValueNumberAddExceptionSetForDivision(GenTree* tree) needArithmeticExcLib = false; } } - if (vnStore->IsVNConstant(vnOp2NormCon)) + if (vnStore->IsVNConstant(vnDivisorNormCon)) { - INT64 kVal = vnStore->ConstantValue(vnOp2NormCon); + INT64 kVal = vnStore->ConstantValue(vnDivisorNormCon); if (kVal != 0) { needDivideByZeroExcCon = false; @@ -13405,26 +13578,26 @@ void Compiler::fgValueNumberAddExceptionSetForDivision(GenTree* tree) } // Retrieve the Norm VN for op1 to use it for the ArithmeticExc - ValueNumPair vnpOp1Norm = vnStore->VNPNormalPair(tree->AsOp()->gtOp1->gtVNPair); - ValueNum vnOp1NormLib = vnpOp1Norm.GetLiberal(); - ValueNum vnOp1NormCon = vnpOp1Norm.GetConservative(); + ValueNumPair vnpDividendNorm = vnStore->VNPNormalPair(dividend->gtVNPair); + ValueNum vnDividendNormLib = vnpDividendNorm.GetLiberal(); + ValueNum vnDividendNormCon = vnpDividendNorm.GetConservative(); if (needArithmeticExcLib || needArithmeticExcCon) { if (typ == TYP_INT) { - if (vnStore->IsVNConstant(vnOp1NormLib)) + if (vnStore->IsVNConstant(vnDividendNormLib)) { - INT32 kVal = vnStore->ConstantValue(vnOp1NormLib); + INT32 kVal = vnStore->ConstantValue(vnDividendNormLib); if (!isUnsignedOper && (kVal != INT32_MIN)) { needArithmeticExcLib = false; } } - if (vnStore->IsVNConstant(vnOp1NormCon)) + if (vnStore->IsVNConstant(vnDividendNormCon)) { - INT32 kVal = vnStore->ConstantValue(vnOp1NormCon); + INT32 kVal = vnStore->ConstantValue(vnDividendNormCon); if (!isUnsignedOper && (kVal != INT32_MIN)) { @@ -13434,18 +13607,18 @@ void Compiler::fgValueNumberAddExceptionSetForDivision(GenTree* tree) } else // (typ == TYP_LONG) { - if (vnStore->IsVNConstant(vnOp1NormLib)) + if (vnStore->IsVNConstant(vnDividendNormLib)) { - INT64 kVal = vnStore->ConstantValue(vnOp1NormLib); + INT64 kVal = vnStore->ConstantValue(vnDividendNormLib); if (!isUnsignedOper && (kVal != INT64_MIN)) { needArithmeticExcLib = false; } } - if (vnStore->IsVNConstant(vnOp1NormCon)) + if (vnStore->IsVNConstant(vnDividendNormCon)) { - INT64 kVal = vnStore->ConstantValue(vnOp1NormCon); + INT64 kVal = vnStore->ConstantValue(vnDividendNormCon); if (!isUnsignedOper && (kVal != INT64_MIN)) { @@ -13456,41 +13629,31 @@ void Compiler::fgValueNumberAddExceptionSetForDivision(GenTree* tree) } // Unpack, Norm,Exc for the tree's VN - ValueNumPair vnpTreeNorm; - ValueNumPair vnpTreeExc; ValueNumPair vnpDivZeroExc = ValueNumStore::VNPForEmptyExcSet(); ValueNumPair vnpArithmExc = ValueNumStore::VNPForEmptyExcSet(); - vnStore->VNPUnpackExc(tree->gtVNPair, &vnpTreeNorm, &vnpTreeExc); - if (needDivideByZeroExcLib) { vnpDivZeroExc.SetLiberal( - vnStore->VNExcSetSingleton(vnStore->VNForFunc(TYP_REF, VNF_DivideByZeroExc, vnOp2NormLib))); + vnStore->VNExcSetSingleton(vnStore->VNForFunc(TYP_REF, VNF_DivideByZeroExc, vnDivisorNormLib))); } if (needDivideByZeroExcCon) { vnpDivZeroExc.SetConservative( - vnStore->VNExcSetSingleton(vnStore->VNForFunc(TYP_REF, VNF_DivideByZeroExc, vnOp2NormCon))); + vnStore->VNExcSetSingleton(vnStore->VNForFunc(TYP_REF, VNF_DivideByZeroExc, vnDivisorNormCon))); } if (needArithmeticExcLib) { vnpArithmExc.SetLiberal(vnStore->VNExcSetSingleton( - vnStore->VNForFuncNoFolding(TYP_REF, VNF_ArithmeticExc, vnOp1NormLib, vnOp2NormLib))); + vnStore->VNForFuncNoFolding(TYP_REF, VNF_ArithmeticExc, vnDividendNormLib, vnDivisorNormLib))); } if (needArithmeticExcCon) { vnpArithmExc.SetConservative(vnStore->VNExcSetSingleton( - vnStore->VNForFuncNoFolding(TYP_REF, VNF_ArithmeticExc, vnOp1NormLib, vnOp2NormCon))); + vnStore->VNForFuncNoFolding(TYP_REF, VNF_ArithmeticExc, vnDividendNormLib, vnDivisorNormCon))); } - // Combine vnpDivZeroExc with the exception set of tree - ValueNumPair newExcSet = vnStore->VNPExcSetUnion(vnpTreeExc, vnpDivZeroExc); - // Combine vnpArithmExc with the newExcSet - newExcSet = vnStore->VNPExcSetUnion(newExcSet, vnpArithmExc); - - // Updated VN for tree, it now includes DivideByZeroExc and/or ArithmeticExc - tree->gtVNPair = vnStore->VNPWithExc(vnpTreeNorm, newExcSet); + return vnStore->VNPExcSetUnion(vnpDivZeroExc, vnpArithmExc); } //-------------------------------------------------------------------------------- diff --git a/src/coreclr/jit/valuenum.h b/src/coreclr/jit/valuenum.h index 1f9171e13cef..5604cbafdf2b 100644 --- a/src/coreclr/jit/valuenum.h +++ b/src/coreclr/jit/valuenum.h @@ -905,6 +905,9 @@ class ValueNumStore // of the length argument to a GT_BOUNDS_CHECK node. bool IsVNCheckedBound(ValueNum vn); + // Returns true if the VN is known to be a cast to ulong + bool IsVNCastToULong(ValueNum vn, ValueNum* castedOp); + // Record that a VN is known to appear as the conservative value number of the length // argument to a GT_BOUNDS_CHECK node. void SetVNIsCheckedBound(ValueNum vn); @@ -932,12 +935,14 @@ class ValueNumStore ValueNum vnBound; unsigned arrOper; ValueNum arrOp; + bool arrOpLHS; // arrOp is on the left side of cmpOp expression unsigned cmpOper; ValueNum cmpOp; CompareCheckedBoundArithInfo() : vnBound(NoVN) , arrOper(GT_NONE) , arrOp(NoVN) + , arrOpLHS(false) , cmpOper(GT_NONE) , cmpOp(NoVN) { @@ -1576,7 +1581,7 @@ class ValueNumStore { static bool Equals(double x, double y) { - return *(__int64*)&x == *(__int64*)&y; + return *(int64_t*)&x == *(int64_t*)&y; } }; diff --git a/src/coreclr/jit/valuenumfuncs.h b/src/coreclr/jit/valuenumfuncs.h index 74dba754de9a..a1d5de334c6f 100644 --- a/src/coreclr/jit/valuenumfuncs.h +++ b/src/coreclr/jit/valuenumfuncs.h @@ -65,9 +65,14 @@ ValueNumFuncDef(ConvOverflowExc, 2, false, false, false, false) // Cast conve // - (shifted left one bit; low bit encode whether source is unsigned.) ValueNumFuncDef(DivideByZeroExc, 1, false, false, false, false) // Division by zero check. Args: 0: divisor value, throws when it is zero ValueNumFuncDef(IndexOutOfRangeExc, 2, false, false, false, false) // Array bounds check, Args: 0: array length; 1: index value, throws when the bounds check fails. -ValueNumFuncDef(InvalidCastExc, 2, false, false, false, false) // CastClass check, Args: 0: ref value being cast; 1: handle of type being cast to, throws when the cast fails. +ValueNumFuncDef(InvalidCastExc, 2, false, false, false, false) // CastClass check, Args: 0: ref value being cast; 1: handle of type being cast to +ValueNumFuncDef(R2RInvalidCastExc, 2, false, false, false, false) // CastClass check, Args: 0: ref value being cast; 1: entry point of R2R cast helper ValueNumFuncDef(NewArrOverflowExc, 1, false, false, false, false) // Raises Integer overflow when Arg 0 is negative -ValueNumFuncDef(HelperMultipleExc, 0, false, false, false, false) // Represents one or more different exceptions that could be thrown by a Jit Helper method +ValueNumFuncDef(ClassInitExc, 2, false, false, false, false) // Represents exceptions thrown by static constructor for class. Args: 0: VN of module, 1: VN of class ID +ValueNumFuncDef(R2RClassInitExc, 1, false, false, false, false) // Represents exceptions thrown by static constructor for class. Args: 0: VN of R2R entry point +ValueNumFuncDef(ClassInitGenericExc, 2, false, false, false, false)// Represents exceptions thrown by static constructor for generic class. Args: 0: VN of class handle +ValueNumFuncDef(HelperOpaqueExc, 1, false, false, false, false) // Represents opaque exceptions could be thrown by a JIT helper. + // Args: 0: Input to helper that uniquely determines exceptions thrown. ValueNumFuncDef(Abs, 1, false, false, false, false) ValueNumFuncDef(Acos, 1, false, false, false, false) diff --git a/src/coreclr/md/datasource/targettypes.cpp b/src/coreclr/md/datasource/targettypes.cpp index 76cdcb2d1b44..cdf19b1e5bca 100644 --- a/src/coreclr/md/datasource/targettypes.cpp +++ b/src/coreclr/md/datasource/targettypes.cpp @@ -78,7 +78,7 @@ m_cbRec(0) HRESULT Target_CMiniTableDef::ReadFrom(DataTargetReader & reader) { HRESULT hr = S_OK; - CORDB_ADDRESS pColDefs = NULL; + CORDB_ADDRESS pColDefs = 0; IfFailRet(reader.ReadPointer(&pColDefs)); IfFailRet(reader.Read8(&m_cCols)); IfFailRet(reader.Read8(&m_iKey)); @@ -378,7 +378,7 @@ m_rENCRecs(0) { memset(&m_pLookUpHashes, 0, TBL_COUNT*sizeof(CORDB_ADDRESS)); memset(&m_pVS, 0, TBL_COUNT*sizeof(CORDB_ADDRESS)); - memset(&m_bSortable, 0, TBL_COUNT*sizeof(BOOL)); + memset(&m_bSortable, 0, TBL_COUNT*sizeof(BYTE)); } HRESULT Target_CMiniMdRW::ReadFrom(DataTargetReader & reader) diff --git a/src/coreclr/md/enc/liteweightstgdbrw.cpp b/src/coreclr/md/enc/liteweightstgdbrw.cpp index 686ae97728f1..3b2e2db60429 100644 --- a/src/coreclr/md/enc/liteweightstgdbrw.cpp +++ b/src/coreclr/md/enc/liteweightstgdbrw.cpp @@ -568,7 +568,7 @@ HRESULT CLiteWeightStgdbRW::GetSaveSize(// S_OK or error. IfFailGo(GetPoolSaveSize(BLOB_POOL_STREAM, MDPoolBlobs, &cbSize)); cbTotal += cbSize; #ifdef FEATURE_METADATA_EMIT_PORTABLE_PDB - IfFailGo(GetPoolSaveSize(PDB_STREAM, NULL, &cbSize)); + IfFailGo(GetPoolSaveSize(PDB_STREAM, 0, &cbSize)); cbTotal += cbSize; #endif @@ -816,7 +816,7 @@ HRESULT CLiteWeightStgdbRW::SaveToStorage( IfFailGo(SavePool(GUID_POOL_STREAM, pStorage, MDPoolGuids)); IfFailGo(SavePool(BLOB_POOL_STREAM, pStorage, MDPoolBlobs)); #ifdef FEATURE_METADATA_EMIT_PORTABLE_PDB - IfFailGo(SavePool(PDB_STREAM, pStorage, NULL)); + IfFailGo(SavePool(PDB_STREAM, pStorage, 0)); #endif // Write the header to disk. diff --git a/src/coreclr/md/enc/mdinternalrw.cpp b/src/coreclr/md/enc/mdinternalrw.cpp index 487d256f8de0..a461c0ad382a 100644 --- a/src/coreclr/md/enc/mdinternalrw.cpp +++ b/src/coreclr/md/enc/mdinternalrw.cpp @@ -69,7 +69,7 @@ HRESULT TranslateSigHelper( // S_OK or error. pbSigBlob, // signature from the imported scope NULL, // Internal OID mapping structure. pqkSigEmit, // [OUT] translated signature - NULL, // start from first byte of the signature + 0, // start from first byte of the signature NULL, // don't care how many bytes consumed pcbSig); // [OUT] total number of bytes write to pqkSigEmit diff --git a/src/coreclr/md/enc/stgtiggerstorage.cpp b/src/coreclr/md/enc/stgtiggerstorage.cpp index 4c9869eb8caa..3e6afd6da2b0 100644 --- a/src/coreclr/md/enc/stgtiggerstorage.cpp +++ b/src/coreclr/md/enc/stgtiggerstorage.cpp @@ -725,7 +725,7 @@ TiggerStorage::FindStream( PSTORAGESTREAM p = m_pStreamList; SIZE_T pStartMD = (SIZE_T)(m_pStgIO->m_pData); - SIZE_T pEndMD = NULL; + SIZE_T pEndMD = 0; if (!ClrSafeInt::addition(pStartMD, m_pStgIO->m_cbData, pEndMD)) { diff --git a/src/coreclr/md/external.h b/src/coreclr/md/external.h index 990ef4a2829e..0fdc88e930d9 100644 --- a/src/coreclr/md/external.h +++ b/src/coreclr/md/external.h @@ -13,4 +13,6 @@ #include #include -#include +#include + +using std::nothrow; diff --git a/src/coreclr/md/inc/cahlprinternal.h b/src/coreclr/md/inc/cahlprinternal.h index e7235d13aa66..ed6381c708d9 100644 --- a/src/coreclr/md/inc/cahlprinternal.h +++ b/src/coreclr/md/inc/cahlprinternal.h @@ -57,17 +57,17 @@ typedef struct CaValue { union { - unsigned __int8 boolean; - signed __int8 i1; - unsigned __int8 u1; - signed __int16 i2; - unsigned __int16 u2; - signed __int32 i4; - unsigned __int32 u4; - signed __int64 i8; - unsigned __int64 u8; - float r4; - double r8; + uint8_t boolean; + int8_t i1; + uint8_t u1; + int16_t i2; + uint16_t u2; + int32_t i4; + uint32_t u4; + int64_t i8; + uint64_t u8; + float r4; + double r8; struct { diff --git a/src/coreclr/md/inc/metamodel.h b/src/coreclr/md/inc/metamodel.h index da47a62e7f36..aa22dcf727fe 100644 --- a/src/coreclr/md/inc/metamodel.h +++ b/src/coreclr/md/inc/metamodel.h @@ -259,9 +259,9 @@ class CMiniMdSchemaBase HAS_DELETE = 0x80, // If set, this metadata can contain _Delete tokens. }; - unsigned __int64 m_maskvalid; // Bit mask of present table counts. + uint64_t m_maskvalid; // Bit mask of present table counts. - unsigned __int64 m_sorted; // Bit mask of sorted tables. + uint64_t m_sorted; // Bit mask of sorted tables. FORCEINLINE bool IsSorted(ULONG ixTbl) { return m_sorted & BIT(ixTbl) ? true : false; } void SetSorted(ULONG ixTbl, int bVal) @@ -283,8 +283,8 @@ class CMiniMdSchemaBase #endif private: - FORCEINLINE unsigned __int64 BIT(ULONG ixBit) - { _ASSERTE(ixBit < (sizeof(__int64)*CHAR_BIT)); + FORCEINLINE uint64_t BIT(ULONG ixBit) + { _ASSERTE(ixBit < (sizeof(int64_t)*CHAR_BIT)); return UI64(1) << ixBit; } }; diff --git a/src/coreclr/md/runtime/mdinternalro.cpp b/src/coreclr/md/runtime/mdinternalro.cpp index 96d725584855..bbe612c643de 100644 --- a/src/coreclr/md/runtime/mdinternalro.cpp +++ b/src/coreclr/md/runtime/mdinternalro.cpp @@ -3147,7 +3147,6 @@ mdModule MDInternalRO::GetModuleFromScope(void) //***************************************************************************** // Fill a variant given a MDDefaultValue -// This routine will create a bstr if the ELEMENT_TYPE of default value is STRING //***************************************************************************** __checkReturn HRESULT _FillMDDefaultValue( @@ -3218,7 +3217,7 @@ HRESULT _FillMDDefaultValue( { IfFailGo(CLDB_E_FILE_CORRUPT); } - __int32 Value = GET_UNALIGNED_VAL32(pValue); + int32_t Value = GET_UNALIGNED_VAL32(pValue); pMDDefaultValue->m_fltValue = (float &)Value; } break; @@ -3228,7 +3227,7 @@ HRESULT _FillMDDefaultValue( { IfFailGo(CLDB_E_FILE_CORRUPT); } - __int64 Value = GET_UNALIGNED_VAL64(pValue); + int64_t Value = GET_UNALIGNED_VAL64(pValue); pMDDefaultValue->m_dblValue = (double &) Value; } break; @@ -3236,19 +3235,7 @@ HRESULT _FillMDDefaultValue( if (cbValue == 0) pValue = NULL; -#if BIGENDIAN - { - // We need to allocate and swap the string if we're on a big endian - // This allocation will be freed by the MDDefaultValue destructor. - pMDDefaultValue->m_wzValue = new WCHAR[(cbValue + 1) / sizeof (WCHAR)]; - IfNullGo(pMDDefaultValue->m_wzValue); - memcpy(const_cast(pMDDefaultValue->m_wzValue), pValue, cbValue); - _ASSERTE(cbValue % sizeof(WCHAR) == 0); - SwapStringLength(const_cast(pMDDefaultValue->m_wzValue), cbValue / sizeof(WCHAR)); - } -#else pMDDefaultValue->m_wzValue = (LPWSTR) pValue; -#endif break; case ELEMENT_TYPE_CLASS: // diff --git a/src/coreclr/md/runtime/metamodel.cpp b/src/coreclr/md/runtime/metamodel.cpp index 3cbc82b6a50a..a0d9618fd5ca 100644 --- a/src/coreclr/md/runtime/metamodel.cpp +++ b/src/coreclr/md/runtime/metamodel.cpp @@ -168,7 +168,7 @@ CMiniMdSchema::SaveTo( { ULONG ulData; // Bytes stored. CMiniMdSchema *pDest = reinterpret_cast(pvData); - const unsigned __int64 one = 1; + const uint64_t one = 1; // Make sure the tables fit in the mask. _ASSERTE((sizeof(m_maskvalid) * 8) > TBL_COUNT); @@ -244,7 +244,7 @@ CMiniMdSchema::LoadFrom( memcpy((void *)this, (void *)pvData, sizeof(CMiniMdSchemaBase)); static_cast(this)->ConvertEndianness(); - unsigned __int64 maskvalid = m_maskvalid; + uint64_t maskvalid = m_maskvalid; // Transfer the variable fields. memset(m_cRecs, 0, sizeof(m_cRecs)); @@ -943,18 +943,18 @@ CMiniMdBase::SwapConstant( case ELEMENT_TYPE_I4: case ELEMENT_TYPE_U4: _ASSERTE(ValueLength == 4); - *(__int32 *)pConstant = GET_UNALIGNED_VAL32(pBlobValue); + *(int32_t *)pConstant = GET_UNALIGNED_VAL32(pBlobValue); break; case ELEMENT_TYPE_R4: { - __int32 Value = GET_UNALIGNED_VAL32(pBlobValue); + int32_t Value = GET_UNALIGNED_VAL32(pBlobValue); *(float *)pConstant = (float &)Value; } break; case ELEMENT_TYPE_R8: { - __int64 Value = GET_UNALIGNED_VAL64(pBlobValue); + int64_t Value = GET_UNALIGNED_VAL64(pBlobValue); *(double *)pConstant = (double &) Value; } break; @@ -962,7 +962,7 @@ CMiniMdBase::SwapConstant( case ELEMENT_TYPE_I8: case ELEMENT_TYPE_U8: _ASSERTE(ValueLength == 8); - *(__int64 *)pConstant = GET_UNALIGNED_VAL64(pBlobValue); + *(int64_t *)pConstant = GET_UNALIGNED_VAL64(pBlobValue); break; case ELEMENT_TYPE_STRING: memcpy(pConstant, pBlobValue, ValueLength); diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets index d82f02fd7f17..d3dc85e04f82 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets @@ -30,7 +30,7 @@ The .NET Foundation licenses this file to you under the MIT license. libRuntime.WorkstationGC - libRuntime.ServerGC + libRuntime.ServerGC $(RuntimeIdentifier) @@ -47,9 +47,17 @@ The .NET Foundation licenses this file to you under the MIT license. gnueabihf androideabi21 musleabihf + + + + + + + - $(CrossCompileArch)-linux-$(CrossCompileAbi) + $(CrossCompileArch)-linux-$(CrossCompileAbi) + $(CrossCompileArch)-alpine-linux-$(CrossCompileAbi) $(CrossCompileArch)-unknown-freebsd12 $ORIGIN @@ -66,9 +74,8 @@ The .NET Foundation licenses this file to you under the MIT license. - 13.5 - 14.2 - 11.0 + 15.0 + 12.2 <_AppleSdkName Condition="'$(_targetOS)' == 'ios'">iphoneos <_AppleSdkName Condition="'$(_targetOS)' == 'iossimulator'">iphonesimulator @@ -88,7 +95,7 @@ The .NET Foundation licenses this file to you under the MIT license. - 11.0 + 12.0 x86_64-apple-macos$(AppleMinOSVersion) arm64-apple-macos$(AppleMinOSVersion) @@ -278,12 +285,11 @@ The .NET Foundation licenses this file to you under the MIT license. - - + - + <_LinkerVersion>$([System.Text.RegularExpressions.Regex]::Match($(_LinkerVersionString), '[1-9]\d*')) diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets index f9fb32ed669e..18c3c1f017a9 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets @@ -21,7 +21,7 @@ The .NET Foundation licenses this file to you under the MIT license. .GuardCF.obj .GuardCF.lib Runtime.WorkstationGC - Runtime.ServerGC + Runtime.ServerGC bootstrapper bootstrapperdll Runtime.VxsortEnabled diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index dbe59baa3b94..99d05624eb11 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -269,7 +269,7 @@ The .NET Foundation licenses this file to you under the MIT license. - + @@ -321,7 +321,7 @@ The .NET Foundation licenses this file to you under the MIT license. - + @@ -333,7 +333,7 @@ The .NET Foundation licenses this file to you under the MIT license. - + diff --git a/src/coreclr/nativeaot/Directory.Build.props b/src/coreclr/nativeaot/Directory.Build.props index d4e052fe4c0e..c9fb4f2f42af 100644 --- a/src/coreclr/nativeaot/Directory.Build.props +++ b/src/coreclr/nativeaot/Directory.Build.props @@ -13,7 +13,6 @@ $(NetCoreAppCurrent) Portable - true $(RuntimeBinDir)/aotsdk/ Debug;Release;Checked @@ -21,6 +20,7 @@ $(TargetArchitecture) arm + AnyCPU true false @@ -78,20 +78,15 @@ - x64 - false TARGET_64BIT;TARGET_AMD64;$(DefineConstants) - x86 TARGET_32BIT;TARGET_X86;$(DefineConstants) - arm TARGET_32BIT;TARGET_ARM;$(DefineConstants) - AnyCPU TARGET_64BIT;TARGET_ARM64;$(DefineConstants) diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs index 7ce239610a7a..8bdfb650362f 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs @@ -375,6 +375,7 @@ internal static Exception GetClasslibExceptionFromEEType(ExceptionIDs id, Method // RhExceptionHandling_ functions are used to throw exceptions out of our asm helpers. We tail-call from // the asm helpers to these functions, which performs the throw. The tail-call is important: it ensures that // the stack is crawlable from within these functions. + [StackTraceHidden] [RuntimeExport("RhExceptionHandling_ThrowClasslibOverflowException")] public static void ThrowClasslibOverflowException(IntPtr address) { @@ -384,6 +385,7 @@ public static void ThrowClasslibOverflowException(IntPtr address) throw GetClasslibException(ExceptionIDs.Overflow, address); } + [StackTraceHidden] [RuntimeExport("RhExceptionHandling_ThrowClasslibDivideByZeroException")] public static void ThrowClasslibDivideByZeroException(IntPtr address) { @@ -393,6 +395,7 @@ public static void ThrowClasslibDivideByZeroException(IntPtr address) throw GetClasslibException(ExceptionIDs.DivideByZero, address); } + [StackTraceHidden] [RuntimeExport("RhExceptionHandling_FailedAllocation")] public static void FailedAllocation(MethodTable* pEEType, bool fIsOverflow) { @@ -405,7 +408,7 @@ public static void FailedAllocation(MethodTable* pEEType, bool fIsOverflow) } #if !INPLACE_RUNTIME - private static OutOfMemoryException s_theOOMException = new OutOfMemoryException(); + private static readonly OutOfMemoryException s_theOOMException = new OutOfMemoryException(); // MRT exports GetRuntimeException for the few cases where we have a helper that throws an exception // and may be called by either MRT or other classlibs and that helper needs to throw an exception. diff --git a/src/coreclr/nativeaot/Runtime/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/CMakeLists.txt index ced34e9f63b6..81355da51fe1 100644 --- a/src/coreclr/nativeaot/Runtime/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/CMakeLists.txt @@ -263,10 +263,10 @@ add_definitions(-DFEATURE_CONSERVATIVE_GC) if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64) add_definitions(-DFEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP) add_definitions(-DFEATURE_MANUALLY_MANAGED_CARD_BUNDLES) -endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64) +endif() if(CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_WASM) add_definitions(-DFEATURE_64BIT_ALIGNMENT) -endif(CLR_CMAKE_TARGET_ARCH_ARM) +endif() add_definitions(-DFEATURE_CUSTOM_IMPORTS) add_definitions(-DFEATURE_DYNAMIC_CODE) @@ -277,7 +277,7 @@ add_definitions(-DNATIVEAOT) add_definitions(-DFEATURE_CACHED_INTERFACE_DISPATCH) if(CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM) add_definitions(-DINTERFACE_DISPATCH_CACHE_HAS_CELL_BACKPOINTER) -endif(CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM) +endif() add_definitions(-D_LIB) # there is a problem with undefined symbols when this is set diff --git a/src/coreclr/nativeaot/Runtime/CommonMacros.h b/src/coreclr/nativeaot/Runtime/CommonMacros.h index 473ddd58a9e9..fc7eb3ce7bfa 100644 --- a/src/coreclr/nativeaot/Runtime/CommonMacros.h +++ b/src/coreclr/nativeaot/Runtime/CommonMacros.h @@ -127,29 +127,6 @@ inline bool IS_ALIGNED(T* val, uintptr_t alignment); #define OS_PAGE_SIZE PalOsPageSize() -#if defined(HOST_AMD64) - -#define DATA_ALIGNMENT 8 - -#elif defined(HOST_X86) - -#define DATA_ALIGNMENT 4 - -#elif defined(HOST_ARM) - -#define DATA_ALIGNMENT 4 - -#elif defined(HOST_ARM64) - -#define DATA_ALIGNMENT 8 - -#elif defined(HOST_WASM) - -#define DATA_ALIGNMENT 4 - -#else -#error Unsupported target architecture -#endif #endif // __GCENV_BASE_INCLUDED__ #if defined(TARGET_ARM) @@ -350,7 +327,7 @@ enum STARTUP_TIMELINE_EVENT_ID }; #ifdef PROFILE_STARTUP -extern unsigned __int64 g_startupTimelineEvents[NUM_STARTUP_TIMELINE_EVENTS]; +extern uint64_t g_startupTimelineEvents[NUM_STARTUP_TIMELINE_EVENTS]; #define STARTUP_TIMELINE_EVENT(eventid) g_startupTimelineEvents[eventid] = PalQueryPerformanceCounter(); #else // PROFILE_STARTUP #define STARTUP_TIMELINE_EVENT(eventid) diff --git a/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.cpp b/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.cpp index 0154bd1fde50..b34c41c37bb3 100644 --- a/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.cpp @@ -44,17 +44,28 @@ FCIMPLEND FCIMPL3(void, RhBulkMoveWithWriteBarrier, uint8_t* pDest, uint8_t* pSrc, size_t cbDest) { - // It is possible that the bulk write is publishing object references accessible so far only - // by the current thread to shared memory. - // The memory model requires that writes performed by current thread are observable no later - // than the writes that will actually publish the references. - GCHeapMemoryBarrier(); + if (cbDest == 0 || pDest == pSrc) + return; + + const bool notInHeap = pDest < g_lowest_address || pDest >= g_highest_address; + + if (!notInHeap) + { + // It is possible that the bulk write is publishing object references accessible so far only + // by the current thread to shared memory. + // The memory model requires that writes performed by current thread are observable no later + // than the writes that will actually publish the references. + GCHeapMemoryBarrier(); + } if (pDest <= pSrc || pSrc + cbDest <= pDest) InlineForwardGCSafeCopy(pDest, pSrc, cbDest); else InlineBackwardGCSafeCopy(pDest, pSrc, cbDest); - InlinedBulkWriteBarrier(pDest, cbDest); + if (!notInHeap) + { + InlinedBulkWriteBarrier(pDest, cbDest); + } } FCIMPLEND diff --git a/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.inl b/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.inl index cb4adbfc6a27..033b83c738ce 100644 --- a/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.inl +++ b/src/coreclr/nativeaot/Runtime/GCMemoryHelpers.inl @@ -228,14 +228,9 @@ FORCEINLINE void InlineCheckedWriteBarrier(void * dst, void * ref) FORCEINLINE void InlinedBulkWriteBarrier(void* pMemStart, size_t cbMemSize) { - // Check whether the writes were even into the heap. If not there's no card update required. - // Also if the size is smaller than a pointer, no write barrier is required. - // This case can occur with universal shared generic code where the size - // is not known at compile time. - if (pMemStart < g_lowest_address || (pMemStart >= g_highest_address) || (cbMemSize < sizeof(uintptr_t))) - { - return; - } + // Caller is expected to check whether the writes were even into the heap + ASSERT(cbMemSize >= sizeof(uintptr_t)); + ASSERT((pMemStart >= g_lowest_address) && (pMemStart < g_highest_address)); #ifdef WRITE_BARRIER_CHECK // Perform shadow heap updates corresponding to the gc heap updates that immediately preceded this helper diff --git a/src/coreclr/nativeaot/Runtime/TypeManager.cpp b/src/coreclr/nativeaot/Runtime/TypeManager.cpp index 77eda2c4c604..96dc357136d9 100644 --- a/src/coreclr/nativeaot/Runtime/TypeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/TypeManager.cpp @@ -29,9 +29,12 @@ TypeManager * TypeManager::Create(HANDLE osModule, void * pModuleHeader, void** if (pReadyToRunHeader->Signature != ReadyToRunHeaderConstants::Signature) return nullptr; - // Only the current major version is supported currently - ASSERT(pReadyToRunHeader->MajorVersion == ReadyToRunHeaderConstants::CurrentMajorVersion); - if (pReadyToRunHeader->MajorVersion != ReadyToRunHeaderConstants::CurrentMajorVersion) + // Only the current version is supported currently + ASSERT((pReadyToRunHeader->MajorVersion == ReadyToRunHeaderConstants::CurrentMajorVersion) && + (pReadyToRunHeader->MinorVersion == ReadyToRunHeaderConstants::CurrentMinorVersion)); + + if ((pReadyToRunHeader->MajorVersion != ReadyToRunHeaderConstants::CurrentMajorVersion) || + (pReadyToRunHeader->MinorVersion != ReadyToRunHeaderConstants::CurrentMinorVersion)) return nullptr; return new (nothrow) TypeManager(osModule, pReadyToRunHeader, pClasslibFunctions, nClasslibFunctions); diff --git a/src/coreclr/nativeaot/Runtime/clrgc.enabled.cpp b/src/coreclr/nativeaot/Runtime/clrgc.enabled.cpp index d35127dc1b0e..678242e31cf2 100644 --- a/src/coreclr/nativeaot/Runtime/clrgc.enabled.cpp +++ b/src/coreclr/nativeaot/Runtime/clrgc.enabled.cpp @@ -58,52 +58,120 @@ HRESULT InitializeStandaloneGC() return GCHeapUtilities::InitializeStandaloneGC(); } +// Validate that the name used to load the GC is just a simple file name +// and does not contain something that could be used in a non-qualified path. +// For example, using the string "..\..\..\clrgc.dll" we might attempt to +// load a GC from the root of the drive. +// +// The minimal set of characters that we must check for and exclude are: +// On all platforms: +// '/' - (forward slash) +// On Windows: +// '\\' - (backslash) +// ':' - (colon) +// +// Returns false if we find any of these characters in 'pwzModuleName' +// Returns true if we reach the null terminator without encountering +// any of these characters. +// +bool ValidateModuleName(const char* pwzModuleName) +{ + const char* pCurChar = pwzModuleName; + char curChar; + do { + curChar = *pCurChar; + if (curChar == '/' +#ifdef TARGET_WINDOWS + || (curChar == '\\') || (curChar == ':') +#endif + ) + { + // Return false if we find any of these character in 'pwzJitName' + return false; + } + pCurChar++; + } while (curChar != 0); + + // Return true; we have reached the null terminator + // + return true; +} + HRESULT GCHeapUtilities::InitializeStandaloneGC() { char* moduleName; + char* modulePath; + + if (!RhConfig::Environment::TryGetStringValue("GCPath", &modulePath)) + { + modulePath = nullptr; + } if (!RhConfig::Environment::TryGetStringValue("GCName", &moduleName)) { - return GCHeapUtilities::InitializeDefaultGC(); + moduleName = nullptr; } - NewArrayHolder moduleNameHolder(moduleName); - HANDLE executableModule = PalGetModuleHandleFromPointer((void*)&PalGetModuleHandleFromPointer); - const TCHAR * executableModulePath = NULL; - PalGetModuleFileName(&executableModulePath, executableModule); - char* convertedExecutableModulePath = PalCopyTCharAsChar(executableModulePath); - if (!convertedExecutableModulePath) + if (!(moduleName || modulePath)) { - return E_OUTOFMEMORY; + return GCHeapUtilities::InitializeDefaultGC(); } - NewArrayHolder convertedExecutableModulePathHolder(convertedExecutableModulePath); + + NewArrayHolder moduleNameHolder(moduleName); + if (!modulePath) { - char* p = convertedExecutableModulePath; - char* q = nullptr; - while (*p != '\0') + // + // This is not a security feature. + // The libFileName originates either from an environment variable or from the runtimeconfig.json + // These are trusted locations, and therefore even if it is a relative path, there is no security risk. + // + // However, users often don't know the absolute path to their coreclr module, especially on production. + // Therefore we allow referencing it from an arbitrary location through libFilePath instead. Users, however + // are warned that they should keep the file in a secure location such that it cannot be tampered. + // + if (!ValidateModuleName(moduleName)) + { + LOG((LF_GC, LL_FATALERROR, "GC initialization failed to load the Standalone GC library.\n")); + return E_FAIL; + } + + HANDLE executableModule = PalGetModuleHandleFromPointer((void*)&PalGetModuleHandleFromPointer); + const TCHAR * executableModulePath = NULL; + PalGetModuleFileName(&executableModulePath, executableModule); + char* convertedExecutableModulePath = PalCopyTCharAsChar(executableModulePath); + if (!convertedExecutableModulePath) + { + return E_OUTOFMEMORY; + } + NewArrayHolder convertedExecutableModulePathHolder(convertedExecutableModulePath); { - if (*p == DIRECTORY_SEPARATOR_CHAR) + char* p = convertedExecutableModulePath; + char* q = nullptr; + while (*p != '\0') { - q = p; + if (*p == DIRECTORY_SEPARATOR_CHAR) + { + q = p; + } + p++; } - p++; + assert(q != nullptr); + q++; + *q = '\0'; } - assert(q != nullptr); - q++; - *q = '\0'; - } - size_t folderLength = strlen(convertedExecutableModulePath); - size_t nameLength = strlen(moduleName); - char* moduleFullPath = new (nothrow) char[folderLength + nameLength + 1]; - if (!moduleFullPath) - { - return E_OUTOFMEMORY; + size_t folderLength = strlen(convertedExecutableModulePath); + size_t nameLength = strlen(moduleName); + modulePath = new (nothrow) char[folderLength + nameLength + 1]; + if (!modulePath) + { + return E_OUTOFMEMORY; + } + strcpy(modulePath, convertedExecutableModulePath); + strcpy(modulePath + folderLength, moduleName); } - NewArrayHolder moduleFullPathHolder(moduleFullPath); - strcpy(moduleFullPath, convertedExecutableModulePath); - strcpy(moduleFullPath + folderLength, moduleName); - HANDLE hMod = PalLoadLibrary(moduleFullPath); + NewArrayHolder modulePathHolder(modulePath); + HANDLE hMod = PalLoadLibrary(modulePath); if (!hMod) { diff --git a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h index 6a3b24a39448..d4360273d28a 100644 --- a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h +++ b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h @@ -12,7 +12,7 @@ struct ReadyToRunHeaderConstants static const uint32_t Signature = 0x00525452; // 'RTR' static const uint32_t CurrentMajorVersion = 9; - static const uint32_t CurrentMinorVersion = 2; + static const uint32_t CurrentMinorVersion = 3; }; struct ReadyToRunHeader diff --git a/src/coreclr/nativeaot/Runtime/inc/stressLog.h b/src/coreclr/nativeaot/Runtime/inc/stressLog.h index 5787d0f5c54d..9c78a120bfac 100644 --- a/src/coreclr/nativeaot/Runtime/inc/stressLog.h +++ b/src/coreclr/nativeaot/Runtime/inc/stressLog.h @@ -301,8 +301,8 @@ class StressLog { PTR_ThreadStressLog logs; // the list of logs for every thread. int32_t deadCount; // count of dead threads in the log CrstStatic *pLock; // lock - unsigned __int64 tickFrequency; // number of ticks per second - unsigned __int64 startTimeStamp; // start time from when tick counter started + uint64_t tickFrequency; // number of ticks per second + uint64_t startTimeStamp; // start time from when tick counter started FILETIME startTime; // time the application started size_t moduleOffset; // Used to compute format strings. diff --git a/src/coreclr/nativeaot/Runtime/portable.cpp b/src/coreclr/nativeaot/Runtime/portable.cpp index b8e564da3a49..22425969b2ba 100644 --- a/src/coreclr/nativeaot/Runtime/portable.cpp +++ b/src/coreclr/nativeaot/Runtime/portable.cpp @@ -331,24 +331,6 @@ void * ReturnFromUniversalTransition_DebugStepTailCall; #endif // defined(USE_PORTABLE_HELPERS) && !defined(HOST_WASM) -#if defined(USE_PORTABLE_HELPERS) -// -// Return address hijacking -// -FCIMPL0(void, RhpGcStressHijack) -{ - ASSERT_UNCONDITIONALLY("NYI"); -} -FCIMPLEND - -FCIMPL0(void, RhpGcProbeHijack) -{ - ASSERT_UNCONDITIONALLY("NYI"); -} -FCIMPLEND - -#endif // defined(USE_PORTABLE_HELPERS) || defined(TARGET_UNIX) - #if defined(USE_PORTABLE_HELPERS) #ifndef HOST_WASM diff --git a/src/coreclr/nativeaot/Runtime/startup.cpp b/src/coreclr/nativeaot/Runtime/startup.cpp index 4096c61f36ed..f87bc947d970 100644 --- a/src/coreclr/nativeaot/Runtime/startup.cpp +++ b/src/coreclr/nativeaot/Runtime/startup.cpp @@ -33,7 +33,7 @@ #ifndef DACCESS_COMPILE #ifdef PROFILE_STARTUP -unsigned __int64 g_startupTimelineEvents[NUM_STARTUP_TIMELINE_EVENTS] = { 0 }; +uint64_t g_startupTimelineEvents[NUM_STARTUP_TIMELINE_EVENTS] = { 0 }; #endif // PROFILE_STARTUP #ifdef TARGET_UNIX diff --git a/src/coreclr/nativeaot/Runtime/stressLog.cpp b/src/coreclr/nativeaot/Runtime/stressLog.cpp index a04f2b8169fb..e01eddd2d913 100644 --- a/src/coreclr/nativeaot/Runtime/stressLog.cpp +++ b/src/coreclr/nativeaot/Runtime/stressLog.cpp @@ -45,7 +45,7 @@ GPTR_IMPL(StressLog, g_pStressLog /*, &StressLog::theLog*/); variable-speed CPUs (for power management), this is not accurate, but may be good enough. */ -inline __declspec(naked) unsigned __int64 getTimeStamp() { +inline __declspec(naked) uint64_t getTimeStamp() { __asm { RDTSC // read time stamp counter @@ -54,7 +54,7 @@ inline __declspec(naked) unsigned __int64 getTimeStamp() { } #else // HOST_X86 -unsigned __int64 getTimeStamp() +uint64_t getTimeStamp() { return PalQueryPerformanceCounter(); } @@ -65,7 +65,7 @@ unsigned __int64 getTimeStamp() /* Get the frequency corresponding to 'getTimeStamp'. For non-x86 architectures, this is just the performance counter frequency. */ -unsigned __int64 getTickFrequency() +uint64_t getTickFrequency() { return PalQueryPerformanceFrequency(); } @@ -73,7 +73,7 @@ unsigned __int64 getTickFrequency() #endif // DACCESS_COMPILE StressLog StressLog::theLog = { 0, 0, 0, 0, 0, 0 }; -const static unsigned __int64 RECYCLE_AGE = 0x40000000L; // after a billion cycles, we can discard old threads +const static uint64_t RECYCLE_AGE = 0x40000000L; // after a billion cycles, we can discard old threads /*********************************************************************************/ @@ -153,7 +153,7 @@ ThreadStressLog* StressLog::CreateThreadStressLogHelper(Thread * pThread) { // See if we can recycle a dead thread if (VolatileLoad(&theLog.deadCount) > 0) { - unsigned __int64 recycleStamp = getTimeStamp() - RECYCLE_AGE; + uint64_t recycleStamp = getTimeStamp() - RECYCLE_AGE; msgs = VolatileLoad(&theLog.logs); //find out oldest dead ThreadStressLog in case we can't find one within //recycle age but can't create a new chunk @@ -396,7 +396,7 @@ bool StressLog::Initialize() ThreadStressLog* logs = 0; ThreadStressLog* curThreadStressLog = this->logs; - unsigned __int64 lastTimeStamp = 0; // timestamp of last log entry + uint64_t lastTimeStamp = 0; // timestamp of last log entry while(curThreadStressLog != 0) { if (!curThreadStressLog->IsReadyForRead()) diff --git a/src/coreclr/nativeaot/Runtime/thread.cpp b/src/coreclr/nativeaot/Runtime/thread.cpp index f2b68462c608..55323661eac0 100644 --- a/src/coreclr/nativeaot/Runtime/thread.cpp +++ b/src/coreclr/nativeaot/Runtime/thread.cpp @@ -328,14 +328,6 @@ bool Thread::IsGCSpecial() return IsStateSet(TSF_IsGcSpecialThread); } -bool Thread::CatchAtSafePoint() -{ - // This is only called by the GC on a background GC worker thread that's explicitly interested in letting - // a foreground GC proceed at that point. So it's always safe to return true. - ASSERT(IsGCSpecial()); - return true; -} - uint64_t Thread::GetPalThreadIdForLogging() { return m_threadId; @@ -593,7 +585,8 @@ void Thread::GcScanRootsWorker(ScanFunc * pfnEnumCallback, ScanContext * pvCallb #ifndef DACCESS_COMPILE -EXTERN_C void FASTCALL RhpSuspendRedirected(); +#ifdef FEATURE_HIJACK + EXTERN_C void FASTCALL RhpGcProbeHijack(); EXTERN_C void FASTCALL RhpGcStressHijack(); @@ -609,7 +602,6 @@ bool Thread::IsHijackTarget(void* address) return false; } -#ifdef FEATURE_HIJACK void Thread::Hijack() { ASSERT(ThreadStore::GetCurrentThread() == ThreadStore::GetSuspendingThread()); @@ -851,6 +843,16 @@ NATIVE_CONTEXT* Thread::EnsureRedirectionContext() return m_interruptedContext; } +EXTERN_C NOINLINE void FASTCALL RhpSuspendRedirected() +{ + Thread* pThread = ThreadStore::GetCurrentThread(); + pThread->WaitForGC(INTERRUPTED_THREAD_MARKER); + + // restore execution at interrupted location + PalRestoreContext(pThread->GetInterruptedContext()); + UNREACHABLE(); +} + bool Thread::Redirect() { ASSERT(!IsDoNotTriggerGcSet()); @@ -1040,20 +1042,6 @@ EXTERN_C NOINLINE void FASTCALL RhpGcPoll2(PInvokeTransitionFrame* pFrame) RhpWaitForGC2(pFrame); } -#ifdef FEATURE_SUSPEND_REDIRECTION - -EXTERN_C NOINLINE void FASTCALL RhpSuspendRedirected() -{ - Thread* pThread = ThreadStore::GetCurrentThread(); - pThread->WaitForGC(INTERRUPTED_THREAD_MARKER); - - // restore execution at interrupted location - PalRestoreContext(pThread->GetInterruptedContext()); - UNREACHABLE(); -} - -#endif //FEATURE_SUSPEND_REDIRECTION - void Thread::PushExInfo(ExInfo * pExInfo) { ValidateExInfoStack(); diff --git a/src/coreclr/nativeaot/Runtime/thread.h b/src/coreclr/nativeaot/Runtime/thread.h index b0b270c6bf70..1e8fec5560ae 100644 --- a/src/coreclr/nativeaot/Runtime/thread.h +++ b/src/coreclr/nativeaot/Runtime/thread.h @@ -183,6 +183,10 @@ class Thread : private ThreadBuffer void HijackReturnAddress(NATIVE_CONTEXT* pSuspendCtx, HijackFunc* pfnHijackFunction); void HijackReturnAddressWorker(StackFrameIterator* frameIterator, HijackFunc* pfnHijackFunction); bool InlineSuspend(NATIVE_CONTEXT* interruptedContext); + void CrossThreadUnhijack(); + void UnhijackWorker(); +#else // FEATURE_HIJACK + void CrossThreadUnhijack() { } #endif // FEATURE_HIJACK #ifdef FEATURE_SUSPEND_REDIRECTION @@ -232,19 +236,17 @@ class Thread : private ThreadBuffer void Unhijack(); bool IsHijacked(); void* GetHijackedReturnAddress(); + static bool IsHijackTarget(void * address); +#else // FEATURE_HIJACK + void Unhijack() { } + bool IsHijacked() { return false; } + static bool IsHijackTarget(void * address) { return false; } +#endif // FEATURE_HIJACK #ifdef FEATURE_GC_STRESS static void HijackForGcStress(PAL_LIMITED_CONTEXT * pSuspendCtx); #endif // FEATURE_GC_STRESS - void CrossThreadUnhijack(); - void UnhijackWorker(); -#else // !FEATURE_HIJACK - void Unhijack() { } - bool IsHijacked() { return false; } - void CrossThreadUnhijack() { } -#endif // !FEATURE_HIJACK - bool IsSuppressGcStressSet(); void SetSuppressGcStress(); void ClearSuppressGcStress(); @@ -276,8 +278,6 @@ class Thread : private ThreadBuffer PInvokeTransitionFrame* GetTransitionFrameForStackTrace(); void * GetCurrentThreadPInvokeReturnAddress(); - static bool IsHijackTarget(void * address); - // // The set of operations used to support unmanaged code running in cooperative mode // @@ -301,7 +301,6 @@ class Thread : private ThreadBuffer // void SetGCSpecial(); bool IsGCSpecial(); - bool CatchAtSafePoint(); // // Managed/unmanaged interop transitions support APIs diff --git a/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp b/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp index 6759662d5683..3ccf59f611ec 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp @@ -193,7 +193,13 @@ bool UnixNativeCodeManager::IsSafePoint(PTR_VOID pvAddress) codeOffset ); - return decoder.IsInterruptible(); + if (decoder.IsInterruptible()) + return true; + + if (decoder.IsInterruptibleSafePoint()) + return true; + + return false; } void UnixNativeCodeManager::EnumGcRefs(MethodInfo * pMethodInfo, @@ -226,6 +232,24 @@ void UnixNativeCodeManager::EnumGcRefs(MethodInfo * pMethodInfo, codeOffset ); + if (isActiveStackFrame) + { + // CONSIDER: We can optimize this by remembering the need to adjust in IsSafePoint and propagating into here. + // Or, better yet, maybe we should change the decoder to not require this adjustment. + // The scenario that adjustment tries to handle (fallthrough into BB with random liveness) + // does not seem possible. + if (!decoder.HasInterruptibleRanges()) + { + decoder = GcInfoDecoder( + GCInfoToken(gcInfo), + GcInfoDecoderFlags(DECODE_GC_LIFETIMES | DECODE_SECURITY_OBJECT | DECODE_VARARG), + codeOffset - 1 + ); + + assert(decoder.IsInterruptibleSafePoint()); + } + } + ICodeManagerFlags flags = (ICodeManagerFlags)0; if (executionAborted) flags = ICodeManagerFlags::ExecutionAborted; diff --git a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp index cfaa373fe421..39bf9f024be6 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp @@ -777,7 +777,7 @@ libunwind::v128 Registers_REGDISPLAY::getVectorRegister(int num) const { num -= UNW_ARM64_D8; - if (num < 0 || num >= sizeof(D) / sizeof(uint64_t)) + if (num < 0 || (size_t)num >= sizeof(D) / sizeof(uint64_t)) { PORTABILITY_ASSERT("unsupported arm64 vector register"); } @@ -796,7 +796,7 @@ void Registers_REGDISPLAY::setVectorRegister(int num, libunwind::v128 value) { num -= UNW_ARM64_D8; - if (num < 0 || num >= sizeof(D) / sizeof(uint64_t)) + if (num < 0 || (size_t)num >= sizeof(D) / sizeof(uint64_t)) { PORTABILITY_ASSERT("unsupported arm64 vector register"); } diff --git a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp index 0f2aa4f73669..b0eb24759bb5 100644 --- a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp @@ -415,7 +415,13 @@ bool CoffNativeCodeManager::IsSafePoint(PTR_VOID pvAddress) codeOffset ); - return decoder.IsInterruptible(); + if (decoder.IsInterruptible()) + return true; + + if (decoder.IsInterruptibleSafePoint()) + return true; + + return false; #else // Extract the necessary information from the info block header hdrInfo info; @@ -457,7 +463,25 @@ void CoffNativeCodeManager::EnumGcRefs(MethodInfo * pMethodInfo, GCInfoToken(gcInfo), GcInfoDecoderFlags(DECODE_GC_LIFETIMES | DECODE_SECURITY_OBJECT | DECODE_VARARG), codeOffset - ); + ); + + if (isActiveStackFrame) + { + // CONSIDER: We can optimize this by remembering the need to adjust in IsSafePoint and propagating into here. + // Or, better yet, maybe we should change the decoder to not require this adjustment. + // The scenario that adjustment tries to handle (fallthrough into BB with random liveness) + // does not seem possible. + if (!decoder.HasInterruptibleRanges()) + { + decoder = GcInfoDecoder( + GCInfoToken(gcInfo), + GcInfoDecoderFlags(DECODE_GC_LIFETIMES | DECODE_SECURITY_OBJECT | DECODE_VARARG), + codeOffset - 1 + ); + + assert(decoder.IsInterruptibleSafePoint()); + } + } if (!decoder.EnumerateLiveSlots( pRegisterSet, diff --git a/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp b/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp index 0de949935d97..d61badb1536b 100644 --- a/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp @@ -30,6 +30,10 @@ #include "thread.h" #include "threadstore.h" +#ifdef FEATURE_SPECIAL_USER_MODE_APC +#include +#endif + #define REDHAWK_PALEXPORT extern "C" #define REDHAWK_PALAPI __stdcall @@ -630,12 +634,32 @@ REDHAWK_PALEXPORT void REDHAWK_PALAPI PalHijack(HANDLE hThread, _In_opt_ void* p _ASSERTE(hThread != INVALID_HANDLE_VALUE); #ifdef FEATURE_SPECIAL_USER_MODE_APC + // initialize g_pfnQueueUserAPC2Proc on demand. // Note that only one thread at a time may perform suspension (guaranteed by the thread store lock) // so simple conditional assignment is ok. if (g_pfnQueueUserAPC2Proc == QUEUE_USER_APC2_UNINITIALIZED) { - g_pfnQueueUserAPC2Proc = (QueueUserAPC2Proc)GetProcAddress(LoadKernel32dll(), "QueueUserAPC2"); +#ifdef HOST_AMD64 + HMODULE hKernel32 = LoadKernel32dll(); + + typedef BOOL (WINAPI *IsWow64Process2Proc)(HANDLE hProcess, USHORT *pProcessMachine, USHORT *pNativeMachine); + + IsWow64Process2Proc pfnIsWow64Process2Proc = (IsWow64Process2Proc)GetProcAddress(hKernel32, "IsWow64Process2"); + USHORT processMachine, hostMachine; + if (pfnIsWow64Process2Proc != nullptr && + (*pfnIsWow64Process2Proc)(GetCurrentProcess(), &processMachine, &hostMachine) && + (hostMachine == IMAGE_FILE_MACHINE_ARM64) && + !IsWindowsVersionOrGreater(10, 0, 26100)) + { + // Special user-mode APCs are broken on WOW64 processes (x64 running on Arm64 machine) with Windows older than 11.0.26100 (24H2) + g_pfnQueueUserAPC2Proc = NULL; + } + else +#endif // HOST_AMD64 + { + g_pfnQueueUserAPC2Proc = (QueueUserAPC2Proc)GetProcAddress(hKernel32, "QueueUserAPC2"); + } } if (g_pfnQueueUserAPC2Proc) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml index 9d09ab7e1059..69d5d5a83a40 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml @@ -55,11 +55,11 @@ CP0001 - T:Internal.Metadata.NativeFormat.ConstantBoxedEnumValue + T:Internal.Metadata.NativeFormat.ConstantEnumValue CP0001 - T:Internal.Metadata.NativeFormat.ConstantBoxedEnumValueHandle + T:Internal.Metadata.NativeFormat.ConstantEnumValueHandle CP0001 @@ -837,32 +837,4 @@ CP0002 M:System.Threading.Lock.#ctor(System.Boolean) - - CP0015 - M:System.Diagnostics.Tracing.EventSource.Write``1(System.String,``0):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.Write``1(System.String,System.Diagnostics.Tracing.EventSourceOptions@,``0@):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.Write``1(System.String,System.Diagnostics.Tracing.EventSourceOptions@,System.Guid@,System.Guid@,``0@):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.WriteEvent(System.Int32,System.Object[]):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.WriteEventCore(System.Int32,System.Int32,System.Diagnostics.Tracing.EventSource.EventData*):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.WriteEventWithRelatedActivityId(System.Int32,System.Guid,System.Object[]):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.WriteEventWithRelatedActivityIdCore(System.Int32,System.Guid*,System.Int32,System.Diagnostics.Tracing.EventSource.EventData*):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs index 7b3604360ca6..fb73e2a469de 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs @@ -697,7 +697,7 @@ public override int GetHashCode() internal sealed class CustomMarshallerTable : ConcurrentUnifier { - internal static CustomMarshallerTable s_customMarshallersTable = new CustomMarshallerTable(); + internal static readonly CustomMarshallerTable s_customMarshallersTable = new CustomMarshallerTable(); protected override unsafe object Factory(CustomMarshallerKey key) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs index 7ce093cfa0f6..aa9fe653cdb1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs @@ -15,195 +15,9 @@ namespace Internal.Runtime.CompilerHelpers [StackTraceHidden] internal static partial class MathHelpers { - private const double Int32MaxValueOffset = (double)int.MaxValue + 1; - private const double UInt32MaxValueOffset = (double)uint.MaxValue + 1; - - [RuntimeExport("Dbl2IntOvf")] - public static int Dbl2IntOvf(double value) - { - // Note that this expression also works properly for val = NaN case - if (value is > -Int32MaxValueOffset - 1 and < Int32MaxValueOffset) - { - return (int)value; - } - - ThrowHelper.ThrowOverflowException(); - return 0; - } - - [RuntimeExport("Dbl2UIntOvf")] - public static uint Dbl2UIntOvf(double value) - { - // Note that this expression also works properly for val = NaN case - if (value is > -1.0 and < UInt32MaxValueOffset) - { - return (uint)value; - } - - ThrowHelper.ThrowOverflowException(); - return 0; - } - - [RuntimeExport("Dbl2LngOvf")] - public static long Dbl2LngOvf(double value) - { - const double two63 = Int32MaxValueOffset * UInt32MaxValueOffset; - - // Note that this expression also works properly for val = NaN case - // We need to compare with the very next double to two63. 0x402 is epsilon to get us there. - if (value is > -two63 - 0x402 and < two63) - { - return (long)value; - } - - ThrowHelper.ThrowOverflowException(); - return 0; - } - - [RuntimeExport("Dbl2ULngOvf")] - public static ulong Dbl2ULngOvf(double value) - { - const double two64 = UInt32MaxValueOffset * UInt32MaxValueOffset; - // Note that this expression also works properly for val = NaN case - if (value is > -1.0 and < two64) - { - return (ulong)value; - } - - ThrowHelper.ThrowOverflowException(); - return 0; - } - #if !TARGET_64BIT - // - // 64-bit checked multiplication for 32-bit platforms - // - private const string RuntimeLibrary = "*"; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint High32Bits(ulong a) - { - return (uint)(a >> 32); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static ulong BigMul(uint left, uint right) - { - return (ulong)left * right; - } - - [RuntimeExport("LMulOvf")] - public static long LMulOvf(long left, long right) - { -#if DEBUG - long result = left * right; -#endif - - // Remember the sign of the result - int sign = (int)(High32Bits((ulong)left) ^ High32Bits((ulong)right)); - - // Convert to unsigned multiplication - if (left < 0) - left = -left; - if (right < 0) - right = -right; - - // Get the upper 32 bits of the numbers - uint val1High = High32Bits((ulong)left); - uint val2High = High32Bits((ulong)right); - - ulong valMid; - - if (val1High == 0) - { - // Compute the 'middle' bits of the long multiplication - valMid = BigMul(val2High, (uint)left); - } - else - { - if (val2High != 0) - goto Overflow; - // Compute the 'middle' bits of the long multiplication - valMid = BigMul(val1High, (uint)right); - } - - // See if any bits after bit 32 are set - if (High32Bits(valMid) != 0) - goto Overflow; - - long ret = (long)(BigMul((uint)left, (uint)right) + (valMid << 32)); - - // check for overflow - if (High32Bits((ulong)ret) < (uint)valMid) - goto Overflow; - - if (sign >= 0) - { - // have we spilled into the sign bit? - if (ret < 0) - goto Overflow; - } - else - { - ret = -ret; - // have we spilled into the sign bit? - if (ret > 0) - goto Overflow; - } - -#if DEBUG - Debug.Assert(ret == result, $"Multiply overflow got: {ret}, expected: {result}"); -#endif - return ret; - - Overflow: - ThrowHelper.ThrowOverflowException(); - return 0; - } - - [RuntimeExport("ULMulOvf")] - public static ulong ULMulOvf(ulong left, ulong right) - { - // Get the upper 32 bits of the numbers - uint val1High = High32Bits(left); - uint val2High = High32Bits(right); - - ulong valMid; - - if (val1High == 0) - { - if (val2High == 0) - return (ulong)(uint)left * (uint)right; - // Compute the 'middle' bits of the long multiplication - valMid = BigMul(val2High, (uint)left); - } - else - { - if (val2High != 0) - goto Overflow; - // Compute the 'middle' bits of the long multiplication - valMid = BigMul(val1High, (uint)right); - } - - // See if any bits after bit 32 are set - if (High32Bits(valMid) != 0) - goto Overflow; - - ulong ret = BigMul((uint)left, (uint)right) + (valMid << 32); - - // check for overflow - if (High32Bits(ret) < (uint)valMid) - goto Overflow; - - Debug.Assert(ret == left * right, $"Multiply overflow got: {ret}, expected: {left * right}"); - return ret; - - Overflow: - ThrowHelper.ThrowOverflowException(); - return 0; - } - [LibraryImport(RuntimeLibrary)] [SuppressGCTransition] private static partial ulong RhpULMod(ulong dividend, ulong divisor); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/ReflectionHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/ReflectionHelpers.cs index 1defad0d10f9..dbdc93b93bac 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/ReflectionHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/ReflectionHelpers.cs @@ -17,14 +17,14 @@ internal static class ReflectionHelpers // a default assembly name. public static Type GetType(string typeName, string callingAssemblyName, bool throwOnError, bool ignoreCase) { - return TypeNameParser.GetType(typeName, throwOnError: throwOnError, ignoreCase: ignoreCase, defaultAssemblyName: callingAssemblyName); + return TypeNameResolver.GetType(typeName, throwOnError: throwOnError, ignoreCase: ignoreCase, defaultAssemblyName: callingAssemblyName); } // This entry is used to implement Type.GetType()'s ability to detect the calling assembly and use it as // a default assembly name. public static Type ExtensibleGetType(string typeName, string callingAssemblyName, Func assemblyResolver, Func? typeResolver, bool throwOnError, bool ignoreCase) { - return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver, throwOnError: throwOnError, ignoreCase: ignoreCase, defaultAssemblyName: callingAssemblyName); + return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver, throwOnError: throwOnError, ignoreCase: ignoreCase, defaultAssemblyName: callingAssemblyName); } // This supports Assembly.GetExecutingAssembly() intrinsic expansion in the compiler diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/FunctionPointerOps.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/FunctionPointerOps.cs index e77a106b252b..c0bceb7963c8 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/FunctionPointerOps.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/FunctionPointerOps.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Runtime.InteropServices; -using Internal.Runtime.Augments; +using Debug = System.Diagnostics.Debug; namespace Internal.Runtime.CompilerServices { @@ -56,6 +56,8 @@ public override int GetHashCode() public static unsafe IntPtr GetGenericMethodFunctionPointer(IntPtr canonFunctionPointer, IntPtr instantiationArgument) { + Debug.Assert(canonFunctionPointer != IntPtr.Zero); + if (instantiationArgument == IntPtr.Zero) return canonFunctionPointer; @@ -79,7 +81,7 @@ public static unsafe IntPtr GetGenericMethodFunctionPointer(IntPtr canonFunction // Generate new chunk if existing chunks are insufficient if (s_genericFunctionPointerCollection.Count <= newChunkIndex) { - System.Diagnostics.Debug.Assert(newSubChunkIndex == 0); + Debug.Assert(newSubChunkIndex == 0); // New generic descriptors are allocated on the native heap and not tracked in the GC. IntPtr pNewMem = (IntPtr)NativeMemory.Alloc(c_genericDictionaryChunkSize, (nuint)sizeof(GenericMethodDescriptor)); @@ -100,8 +102,8 @@ public static unsafe IntPtr GetGenericMethodFunctionPointer(IntPtr canonFunction uint subChunkIndex = index % c_genericDictionaryChunkSize; GenericMethodDescriptor* genericFunctionPointer = &((GenericMethodDescriptor*)s_genericFunctionPointerCollection[chunkIndex])[subChunkIndex]; - System.Diagnostics.Debug.Assert(canonFunctionPointer == genericFunctionPointer->MethodFunctionPointer); - System.Diagnostics.Debug.Assert(instantiationArgument == genericFunctionPointer->InstantiationArgument); + Debug.Assert(canonFunctionPointer == genericFunctionPointer->MethodFunctionPointer); + Debug.Assert(instantiationArgument == genericFunctionPointer->InstantiationArgument); return (IntPtr)((byte*)genericFunctionPointer + FatFunctionPointerOffset); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeMethodHandleInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeMethodHandleInfo.cs index 90b0f242a418..41aa17cdcbfd 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeMethodHandleInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeMethodHandleInfo.cs @@ -12,8 +12,8 @@ namespace Internal.Runtime.CompilerServices { public class MethodNameAndSignature { - public string Name { get; private set; } - public RuntimeSignature Signature { get; private set; } + public string Name { get; } + public RuntimeSignature Signature { get; } public MethodNameAndSignature(string name, RuntimeSignature signature) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index 821f1bf2fe55..2a5d7505091e 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -1,10 +1,12 @@ true - - $(NoWarn);AD0001 + + + + @@ -527,7 +529,7 @@ - + diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Activator.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Activator.NativeAot.cs index c15fd13580e1..a3b69bf6f52f 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Activator.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Activator.NativeAot.cs @@ -63,7 +63,7 @@ public static partial class Activator else { t = default!; - RawCalliHelper.Call(defaultConstructor, ref Unsafe.As(ref t)); + RawCalliHelper.CallDefaultStructConstructor(defaultConstructor, ref Unsafe.As(ref t)); // Debugger goo so that stepping in works. Only affects debug info generation. // The call gets optimized away. diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs index 61f70e212483..2900a6666570 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs @@ -143,14 +143,14 @@ public unsafe void Initialize() if (constructorEntryPoint == IntPtr.Zero) return; - var constructorFtn = (delegate*)RuntimeAugments.TypeLoaderCallbacks.ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(constructorEntryPoint, new RuntimeTypeHandle(pElementEEType)); + IntPtr constructorFtn = RuntimeAugments.TypeLoaderCallbacks.ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(constructorEntryPoint, new RuntimeTypeHandle(pElementEEType)); ref byte arrayRef = ref MemoryMarshal.GetArrayDataReference(this); nuint elementSize = ElementSize; for (int i = 0; i < Length; i++) { - constructorFtn(ref arrayRef); + RawCalliHelper.CallDefaultStructConstructor(constructorFtn, ref arrayRef); arrayRef = ref Unsafe.Add(ref arrayRef, elementSize); } } @@ -526,255 +526,26 @@ private static unsafe void CopyImplPrimitiveTypeWithWidening(Array sourceArray, throw new ArrayTypeMismatchException(SR.ArrayTypeMismatch_ConstrainedCopy); } - fixed (byte* pSrcArray = &MemoryMarshal.GetArrayDataReference(sourceArray), pDstArray = &MemoryMarshal.GetArrayDataReference(destinationArray)) - { - byte* srcData = pSrcArray + (nuint)sourceIndex * srcElementSize; - byte* data = pDstArray + (nuint)destinationIndex * destElementSize; + ref byte srcData = ref Unsafe.AddByteOffset(ref MemoryMarshal.GetArrayDataReference(sourceArray), (nuint)sourceIndex * srcElementSize); + ref byte dstData = ref Unsafe.AddByteOffset(ref MemoryMarshal.GetArrayDataReference(destinationArray), (nuint)destinationIndex * destElementSize); - if (sourceElementType == destElementType) - { - // Multidim arrays and enum->int copies can still reach this path. - SpanHelpers.Memmove(ref *data, ref *srcData, (nuint)length * srcElementSize); - return; - } + if (sourceElementType == destElementType) + { + // Multidim arrays and enum->int copies can still reach this path. + SpanHelpers.Memmove(ref dstData, ref srcData, (nuint)length * srcElementSize); + return; + } - ulong dummyElementForZeroLengthCopies = 0; - // If the element types aren't identical and the length is zero, we're still obliged to check the types for widening compatibility. - // We do this by forcing the loop below to copy one dummy element. - if (length == 0) - { - srcData = (byte*)&dummyElementForZeroLengthCopies; - data = (byte*)&dummyElementForZeroLengthCopies; - length = 1; - } + if (!InvokeUtils.CanPrimitiveWiden(destElementType, sourceElementType)) + { + throw new ArrayTypeMismatchException(SR.ArrayTypeMismatch_CantAssignType); + } - for (int i = 0; i < length; i++, srcData += srcElementSize, data += destElementSize) - { - // We pretty much have to do some fancy datatype mangling every time here, for - // converting w/ sign extension and floating point conversions. - switch (sourceElementType) - { - case EETypeElementType.Byte: - { - switch (destElementType) - { - case EETypeElementType.Single: - *(float*)data = *(byte*)srcData; - break; - - case EETypeElementType.Double: - *(double*)data = *(byte*)srcData; - break; - - case EETypeElementType.Char: - case EETypeElementType.Int16: - case EETypeElementType.UInt16: - *(short*)data = *(byte*)srcData; - break; - - case EETypeElementType.Int32: - case EETypeElementType.UInt32: - *(int*)data = *(byte*)srcData; - break; - - case EETypeElementType.Int64: - case EETypeElementType.UInt64: - *(long*)data = *(byte*)srcData; - break; - - default: - throw new ArrayTypeMismatchException(SR.ArrayTypeMismatch_CantAssignType); - } - break; - } - - case EETypeElementType.SByte: - switch (destElementType) - { - case EETypeElementType.Int16: - *(short*)data = *(sbyte*)srcData; - break; - - case EETypeElementType.Int32: - *(int*)data = *(sbyte*)srcData; - break; - - case EETypeElementType.Int64: - *(long*)data = *(sbyte*)srcData; - break; - - case EETypeElementType.Single: - *(float*)data = *(sbyte*)srcData; - break; - - case EETypeElementType.Double: - *(double*)data = *(sbyte*)srcData; - break; - - default: - throw new ArrayTypeMismatchException(SR.ArrayTypeMismatch_CantAssignType); - } - break; - - case EETypeElementType.UInt16: - case EETypeElementType.Char: - switch (destElementType) - { - case EETypeElementType.Single: - *(float*)data = *(ushort*)srcData; - break; - - case EETypeElementType.Double: - *(double*)data = *(ushort*)srcData; - break; - - case EETypeElementType.UInt16: - case EETypeElementType.Char: - *(ushort*)data = *(ushort*)srcData; - break; - - case EETypeElementType.Int32: - case EETypeElementType.UInt32: - *(uint*)data = *(ushort*)srcData; - break; - - case EETypeElementType.Int64: - case EETypeElementType.UInt64: - *(ulong*)data = *(ushort*)srcData; - break; - - default: - throw new ArrayTypeMismatchException(SR.ArrayTypeMismatch_CantAssignType); - } - break; - - case EETypeElementType.Int16: - switch (destElementType) - { - case EETypeElementType.Int32: - *(int*)data = *(short*)srcData; - break; - - case EETypeElementType.Int64: - *(long*)data = *(short*)srcData; - break; - - case EETypeElementType.Single: - *(float*)data = *(short*)srcData; - break; - - case EETypeElementType.Double: - *(double*)data = *(short*)srcData; - break; - - default: - throw new ArrayTypeMismatchException(SR.ArrayTypeMismatch_CantAssignType); - } - break; - - case EETypeElementType.Int32: - switch (destElementType) - { - case EETypeElementType.Int64: - *(long*)data = *(int*)srcData; - break; - - case EETypeElementType.Single: - *(float*)data = (float)*(int*)srcData; - break; - - case EETypeElementType.Double: - *(double*)data = *(int*)srcData; - break; - - default: - throw new ArrayTypeMismatchException(SR.ArrayTypeMismatch_CantAssignType); - } - break; - - case EETypeElementType.UInt32: - switch (destElementType) - { - case EETypeElementType.Int64: - case EETypeElementType.UInt64: - *(long*)data = *(uint*)srcData; - break; - - case EETypeElementType.Single: - *(float*)data = (float)*(uint*)srcData; - break; - - case EETypeElementType.Double: - *(double*)data = *(uint*)srcData; - break; - - default: - throw new ArrayTypeMismatchException(SR.ArrayTypeMismatch_CantAssignType); - } - break; - - - case EETypeElementType.Int64: - switch (destElementType) - { - case EETypeElementType.Single: - *(float*)data = (float)*(long*)srcData; - break; - - case EETypeElementType.Double: - *(double*)data = (double)*(long*)srcData; - break; - - default: - throw new ArrayTypeMismatchException(SR.ArrayTypeMismatch_CantAssignType); - } - break; - - case EETypeElementType.UInt64: - switch (destElementType) - { - case EETypeElementType.Single: - - //*(float*) data = (float) *(Ulong*)srcData; - long srcValToFloat = *(long*)srcData; - float f = (float)srcValToFloat; - if (srcValToFloat < 0) - f += 4294967296.0f * 4294967296.0f; // This is 2^64 - - *(float*)data = f; - break; - - case EETypeElementType.Double: - //*(double*) data = (double) *(Ulong*)srcData; - long srcValToDouble = *(long*)srcData; - double d = (double)srcValToDouble; - if (srcValToDouble < 0) - d += 4294967296.0 * 4294967296.0; // This is 2^64 - - *(double*)data = d; - break; - - default: - throw new ArrayTypeMismatchException(SR.ArrayTypeMismatch_CantAssignType); - } - break; - - case EETypeElementType.Single: - switch (destElementType) - { - case EETypeElementType.Double: - *(double*)data = *(float*)srcData; - break; - - default: - throw new ArrayTypeMismatchException(SR.ArrayTypeMismatch_CantAssignType); - } - break; - - default: - throw new ArrayTypeMismatchException(SR.ArrayTypeMismatch_CantAssignType); - } - } + for (int i = 0; i < length; i++) + { + InvokeUtils.PrimitiveWiden(destElementType, sourceElementType, ref dstData, ref srcData); + srcData = ref Unsafe.AddByteOffset(ref srcData, srcElementSize); + dstData = ref Unsafe.AddByteOffset(ref dstData, destElementSize); } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Enum.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Enum.NativeAot.cs index baf2e424546e..d9914ad15367 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Enum.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Enum.NativeAot.cs @@ -62,10 +62,8 @@ internal static EnumInfo GetEnumInfo(RuntimeType enumType, b } #pragma warning restore - private static unsafe object InternalBoxEnum(Type enumType, long value) - { - return ToObject(enumType.TypeHandle.ToMethodTable(), value); - } + internal static unsafe object ToObject(MethodTable* mt, long value) + => InternalBoxEnum(new RuntimeTypeHandle(mt), value); private static unsafe CorElementType InternalGetCorElementType(RuntimeType rt) { @@ -151,51 +149,5 @@ internal static Type InternalGetUnderlyingType(RuntimeType enumType) return GetEnumInfo(enumType).UnderlyingType; } - - [Conditional("BIGENDIAN")] - private static unsafe void AdjustForEndianness(ref byte* pValue, MethodTable* enumEEType) - { - // On Debug builds, include the big-endian code to help deter bitrot (the "Conditional("BIGENDIAN")" will prevent it from executing on little-endian). - // On Release builds, exclude code to deter IL bloat and toolchain work. -#if BIGENDIAN || DEBUG - EETypeElementType elementType = enumEEType->ElementType; - switch (elementType) - { - case EETypeElementType.SByte: - case EETypeElementType.Byte: - pValue += sizeof(long) - sizeof(byte); - break; - - case EETypeElementType.Int16: - case EETypeElementType.UInt16: - pValue += sizeof(long) - sizeof(short); - break; - - case EETypeElementType.Int32: - case EETypeElementType.UInt32: - pValue += sizeof(long) - sizeof(int); - break; - - case EETypeElementType.Int64: - case EETypeElementType.UInt64: - break; - - default: - throw new NotSupportedException(); - } -#endif //BIGENDIAN || DEBUG - } - - #region ToObject - - internal static unsafe object ToObject(MethodTable* enumEEType, long value) - { - Debug.Assert(enumEEType->IsEnum); - - byte* pValue = (byte*)&value; - AdjustForEndianness(ref pValue, enumEEType); - return RuntimeImports.RhBox(enumEEType, ref *pValue); - } - #endregion } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/InvokeUtils.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/InvokeUtils.cs index f8825dbfc914..b6fc499829d1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/InvokeUtils.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/InvokeUtils.cs @@ -128,98 +128,225 @@ private static Exception ConvertOrWidenPrimitivesEnumsAndPointersIfPossible(obje } EETypeElementType dstElementType = dstEEType->ElementType; - if (!CanPrimitiveWiden(dstElementType, srcEEType->ElementType)) + EETypeElementType srcElementType = srcEEType->ElementType; + + if (dstElementType == srcElementType) { - dstObject = null; - return CreateChangeTypeArgumentException(srcEEType, dstEEType); + // Rebox the value if the EETypeElementTypes match + dstObject = RuntimeImports.RhBox(dstEEType, ref srcObject.GetRawData()); } - - switch (dstElementType) + else { - case EETypeElementType.Boolean: - dstObject = Convert.ToBoolean(srcObject); - break; - - case EETypeElementType.Char: - char charValue = Convert.ToChar(srcObject); - dstObject = dstEEType->IsEnum ? Enum.ToObject(dstEEType, charValue) : charValue; - break; - - case EETypeElementType.SByte: - sbyte sbyteValue = Convert.ToSByte(srcObject); - dstObject = dstEEType->IsEnum ? Enum.ToObject(dstEEType, sbyteValue) : sbyteValue; - break; + if (!CanPrimitiveWiden(dstElementType, srcElementType)) + { + dstObject = null; + return CreateChangeTypeArgumentException(srcEEType, dstEEType); + } - case EETypeElementType.Int16: - short shortValue = Convert.ToInt16(srcObject); - dstObject = dstEEType->IsEnum ? Enum.ToObject(dstEEType, shortValue) : shortValue; - break; + dstObject = RuntimeImports.RhNewObject(dstEEType); + PrimitiveWiden(dstElementType, srcElementType, ref dstObject.GetRawData(), ref srcObject.GetRawData()); + } + return null; + } - case EETypeElementType.Int32: - int intValue = Convert.ToInt32(srcObject); - dstObject = dstEEType->IsEnum ? Enum.ToObject(dstEEType, intValue) : intValue; - break; + [MethodImpl(MethodImplOptions.AggressiveInlining)] // Two callers, one of them is potentially perf sensitive + internal static void PrimitiveWiden(EETypeElementType dstType, EETypeElementType srcType, ref byte dstValue, ref byte srcValue) + { + // Caller must check that the conversion is valid and the source/destination types are different + Debug.Assert(CanPrimitiveWiden(dstType, srcType) && dstType != srcType); - case EETypeElementType.Int64: - long longValue = Convert.ToInt64(srcObject); - dstObject = dstEEType->IsEnum ? Enum.ToObject(dstEEType, longValue) : longValue; + switch (srcType) + { + case EETypeElementType.Byte: + switch (dstType) + { + case EETypeElementType.Single: + Unsafe.As(ref dstValue) = srcValue; + break; + case EETypeElementType.Double: + Unsafe.As(ref dstValue) = srcValue; + break; + case EETypeElementType.Char: + case EETypeElementType.Int16: + case EETypeElementType.UInt16: + Unsafe.As(ref dstValue) = srcValue; + break; + case EETypeElementType.Int32: + case EETypeElementType.UInt32: + Unsafe.As(ref dstValue) = srcValue; + break; + case EETypeElementType.Int64: + case EETypeElementType.UInt64: + Unsafe.As(ref dstValue) = srcValue; + break; + default: + Debug.Fail("Expected to be unreachable"); + break; + } break; - case EETypeElementType.Byte: - byte byteValue = Convert.ToByte(srcObject); - dstObject = dstEEType->IsEnum ? Enum.ToObject(dstEEType, byteValue) : byteValue; + case EETypeElementType.SByte: + switch (dstType) + { + case EETypeElementType.Int16: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + case EETypeElementType.Int32: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + case EETypeElementType.Int64: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + case EETypeElementType.Single: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + case EETypeElementType.Double: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + default: + Debug.Fail("Expected to be unreachable"); + break; + } break; case EETypeElementType.UInt16: - ushort ushortValue = Convert.ToUInt16(srcObject); - dstObject = dstEEType->IsEnum ? Enum.ToObject(dstEEType, ushortValue) : ushortValue; + case EETypeElementType.Char: + switch (dstType) + { + case EETypeElementType.Single: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + case EETypeElementType.Double: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + case EETypeElementType.UInt16: + case EETypeElementType.Char: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + case EETypeElementType.Int32: + case EETypeElementType.UInt32: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + case EETypeElementType.Int64: + case EETypeElementType.UInt64: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + default: + Debug.Fail("Expected to be unreachable"); + break; + } break; - case EETypeElementType.UInt32: - uint uintValue = Convert.ToUInt32(srcObject); - dstObject = dstEEType->IsEnum ? Enum.ToObject(dstEEType, uintValue) : uintValue; + case EETypeElementType.Int16: + switch (dstType) + { + case EETypeElementType.Int32: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + case EETypeElementType.Int64: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + case EETypeElementType.Single: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + case EETypeElementType.Double: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + default: + Debug.Fail("Expected to be unreachable"); + break; + } break; - case EETypeElementType.UInt64: - ulong ulongValue = Convert.ToUInt64(srcObject); - dstObject = dstEEType->IsEnum ? Enum.ToObject(dstEEType, (long)ulongValue) : ulongValue; + case EETypeElementType.Int32: + switch (dstType) + { + case EETypeElementType.Int64: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + case EETypeElementType.Single: + Unsafe.As(ref dstValue) = (float)Unsafe.As(ref srcValue); + break; + case EETypeElementType.Double: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + default: + Debug.Fail("Expected to be unreachable"); + break; + } break; - case EETypeElementType.Single: - if (new EETypePtr(srcEEType).CorElementType == CorElementType.ELEMENT_TYPE_CHAR) + case EETypeElementType.UInt32: + switch (dstType) { - dstObject = (float)(char)srcObject; + case EETypeElementType.Int64: + case EETypeElementType.UInt64: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + case EETypeElementType.Single: + Unsafe.As(ref dstValue) = (float)Unsafe.As(ref srcValue); + break; + case EETypeElementType.Double: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + default: + Debug.Fail("Expected to be unreachable"); + break; } - else + break; + + case EETypeElementType.Int64: + switch (dstType) { - dstObject = Convert.ToSingle(srcObject); + case EETypeElementType.Single: + Unsafe.As(ref dstValue) = (float)Unsafe.As(ref srcValue); + break; + case EETypeElementType.Double: + Unsafe.As(ref dstValue) = (double)Unsafe.As(ref srcValue); + break; + default: + Debug.Fail("Expected to be unreachable"); + break; } break; - case EETypeElementType.Double: - if (new EETypePtr(srcEEType).CorElementType == CorElementType.ELEMENT_TYPE_CHAR) + case EETypeElementType.UInt64: + switch (dstType) { - dstObject = (double)(char)srcObject; + case EETypeElementType.Single: + Unsafe.As(ref dstValue) = (float)Unsafe.As(ref srcValue); + break; + case EETypeElementType.Double: + Unsafe.As(ref dstValue) = (double)Unsafe.As(ref srcValue); + break; + default: + Debug.Fail("Expected to be unreachable"); + break; } - else + break; + + case EETypeElementType.Single: + switch (dstType) { - dstObject = Convert.ToDouble(srcObject); + case EETypeElementType.Double: + Unsafe.As(ref dstValue) = Unsafe.As(ref srcValue); + break; + default: + Debug.Fail("Expected to be unreachable"); + break; } break; default: - Debug.Fail("Unexpected CorElementType: " + dstElementType + ": Not a valid widening target."); - dstObject = null; - return CreateChangeTypeException(srcEEType, dstEEType, semantics); + Debug.Fail("Expected to be unreachable"); + break; } - - Debug.Assert(dstObject.GetMethodTable() == dstEEType); - return null; } - private static bool CanPrimitiveWiden(EETypeElementType destType, EETypeElementType srcType) + [MethodImpl(MethodImplOptions.AggressiveInlining)] // Two callers, one of them is potentially perf sensitive + internal static bool CanPrimitiveWiden(EETypeElementType dstType, EETypeElementType srcType) { - Debug.Assert(destType is < EETypeElementType.ValueType and >= EETypeElementType.Boolean); + Debug.Assert(dstType is < EETypeElementType.ValueType and >= EETypeElementType.Boolean); Debug.Assert(srcType is < EETypeElementType.ValueType and >= EETypeElementType.Boolean); ReadOnlySpan primitiveAttributes = [ @@ -232,7 +359,7 @@ private static bool CanPrimitiveWiden(EETypeElementType destType, EETypeElementT 0xC540, // Int16 (W = I2, I4, I8, R4, R8) 0xCF88, // UInt16 (W = U2, CHAR, I4, U4, I8, U8, R4, R8) 0xC500, // Int32 (W = I4, I8, R4, R8) - 0xCE00, // UInt32 (W = U4, I8, R4, R8) + 0xCE00, // UInt32 (W = U4, I8, U8, R4, R8) 0xC400, // Int64 (W = I8, R4, R8) 0xC800, // UInt64 (W = U8, R4, R8) 0x0000, // IntPtr @@ -241,7 +368,7 @@ private static bool CanPrimitiveWiden(EETypeElementType destType, EETypeElementT 0x8000, // Double (W = R8) ]; - ushort mask = (ushort)(1 << (byte)destType); + ushort mask = (ushort)(1 << (byte)dstType); return (primitiveAttributes[(int)srcType & 0xF] & mask) != 0; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs index 1697a81c72f7..3e26daa46725 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs @@ -88,7 +88,7 @@ public sealed override MethodInfo EntryPoint MetadataReader reader = scope.Reader; QualifiedMethodHandle entrypointHandle = scope.ScopeDefinition.EntryPoint; - if (!entrypointHandle.IsNull(reader)) + if (!entrypointHandle.IsNil) { QualifiedMethod entrypointMethod = entrypointHandle.GetQualifiedMethod(reader); TypeDefinitionHandle declaringTypeHandle = entrypointMethod.EnclosingType; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs index 9fb1ebe03082..99292670fa8a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs @@ -68,7 +68,7 @@ public sealed override Type GetType(string name, bool throwOnError, bool ignoreC { ArgumentException.ThrowIfNullOrEmpty(name); - return TypeNameParser.GetType(name, + return TypeNameResolver.GetType(name, throwOnError: throwOnError, ignoreCase: ignoreCase, topLevelAssembly: this); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs index eb4289695020..f9f89d734357 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs @@ -30,8 +30,8 @@ public static class NativeFormatMetadataReaderExtensions public static bool StringOrNullEquals(this ConstantStringValueHandle handle, string valueOrNull, MetadataReader reader) { if (valueOrNull == null) - return handle.IsNull(reader); - if (handle.IsNull(reader)) + return handle.IsNil; + if (handle.IsNil) return false; return handle.StringEquals(valueOrNull, reader); } @@ -141,9 +141,9 @@ public static bool IsConstructor(ref Method method, MetadataReader reader) return nameHandle.StringEquals(ConstructorInfo.ConstructorName, reader) || nameHandle.StringEquals(ConstructorInfo.TypeConstructorName, reader); } - private static Exception ParseBoxedEnumConstantValue(this ConstantBoxedEnumValueHandle handle, MetadataReader reader, out object value) + private static Exception ParseEnumConstantValue(this ConstantEnumValueHandle handle, MetadataReader reader, out object value) { - ConstantBoxedEnumValue record = handle.GetConstantBoxedEnumValue(reader); + ConstantEnumValue record = handle.GetConstantEnumValue(reader); Exception? exception = null; Type? enumType = record.Type.TryResolve(reader, new TypeContext(null, null), ref exception)?.ToType(); @@ -317,9 +317,9 @@ public static Exception TryParseConstantValue(this Handle handle, MetadataReader case HandleType.ConstantReferenceValue: value = null; return null; - case HandleType.ConstantBoxedEnumValue: + case HandleType.ConstantEnumValue: { - return handle.ToConstantBoxedEnumValueHandle(reader).ParseBoxedEnumConstantValue(reader, out value); + return handle.ToConstantEnumValueHandle(reader).ParseEnumConstantValue(reader, out value); } default: { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.cs index f25a228a6e78..3aca021e910c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.cs @@ -55,7 +55,7 @@ public static string GetString(this ConstantStringValueHandle handle, MetadataRe // Useful for namespace Name string which can be a null handle. public static string GetStringOrNull(this ConstantStringValueHandle handle, MetadataReader reader) { - if (reader.IsNull(handle)) + if (handle.IsNil) return null; return reader.GetConstantStringValue(handle).Value; } @@ -120,13 +120,10 @@ private static RuntimeAssemblyName CreateRuntimeAssemblyNameFromMetadata( ByteCollection publicKeyOrToken, global::Internal.Metadata.NativeFormat.AssemblyFlags assemblyFlags) { - AssemblyNameFlags assemblyNameFlags = AssemblyNameFlags.None; - if (0 != (assemblyFlags & global::Internal.Metadata.NativeFormat.AssemblyFlags.PublicKey)) - assemblyNameFlags |= AssemblyNameFlags.PublicKey; - if (0 != (assemblyFlags & global::Internal.Metadata.NativeFormat.AssemblyFlags.Retargetable)) - assemblyNameFlags |= AssemblyNameFlags.Retargetable; - int contentType = ((int)assemblyFlags) & 0x00000E00; - assemblyNameFlags |= (AssemblyNameFlags)contentType; + AssemblyNameFlags assemblyNameFlags = (AssemblyNameFlags)(assemblyFlags & ( + global::Internal.Metadata.NativeFormat.AssemblyFlags.PublicKey | + global::Internal.Metadata.NativeFormat.AssemblyFlags.Retargetable | + global::Internal.Metadata.NativeFormat.AssemblyFlags.ContentTypeMask)); ArrayBuilder keyOrTokenArrayBuilder = default; foreach (byte b in publicKeyOrToken) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs index 5b86da9cc8e1..1503cfdfaa38 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs @@ -11,7 +11,7 @@ internal static class DefaultValueParser { public static bool GetDefaultValueFromConstantIfAny(MetadataReader reader, Handle constantHandle, Type declaredType, bool raw, out object? defaultValue) { - if (!(constantHandle.IsNull(reader))) + if (!constantHandle.IsNil) { defaultValue = constantHandle.ParseConstantValue(reader); if ((!raw) && declaredType.IsEnum && defaultValue != null) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs index 9af098d44ca9..e07f23d3fcc2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs @@ -116,7 +116,7 @@ public NativeFormatMethodCommon(MethodHandle methodHandle, NativeFormatRuntimeNa _methodHandle = methodHandle; _contextTypeInfo = contextTypeInfo; _reader = definingTypeInfo.Reader; - _method = methodHandle.GetMethod(_reader); + _method = _reader.GetMethod(methodHandle); } public MethodAttributes Attributes @@ -214,7 +214,7 @@ public string Name { get { - return _method.Name.GetString(_reader); + return _reader.GetString(_method.Name); } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs index 3cad4287b6f4..a64e338004ea 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs @@ -62,7 +62,7 @@ public sealed override string Name { get { - if (_genericParameter.Name.IsNull(Reader)) + if (_genericParameter.Name.IsNil) return string.Empty; return _genericParameter.Name.GetString(Reader); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs index cae684153472..23c0aab5638c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs @@ -164,7 +164,7 @@ internal sealed override RuntimeTypeInfo InternalDeclaringType { RuntimeTypeInfo? declaringType = null; TypeDefinitionHandle enclosingTypeDefHandle = _typeDefinition.EnclosingType; - if (!enclosingTypeDefHandle.IsNull(_reader)) + if (!enclosingTypeDefHandle.IsNil) { declaringType = enclosingTypeDefHandle.ResolveTypeDefinition(_reader); } @@ -219,7 +219,7 @@ internal sealed override QTypeDefRefOrSpec TypeRefDefOrSpecForBaseType get { Handle baseType = _typeDefinition.BaseType; - if (baseType.IsNull(_reader)) + if (baseType.IsNil) return QTypeDefRefOrSpec.Null; return new QTypeDefRefOrSpec(_reader, baseType); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs index ee76c4a5e302..5e855eb58565 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Reflection.Metadata; namespace System.Reflection { @@ -129,6 +130,11 @@ public AssemblyName ToAssemblyName() return assemblyName; } + internal static RuntimeAssemblyName FromAssemblyNameInfo(AssemblyNameInfo source) + { + return new(source.Name, source.Version, source.CultureName, source._flags, source.PublicKeyOrToken); + } + // // Copies a RuntimeAssemblyName into a freshly allocated AssemblyName with no data aliasing to any other object. // @@ -142,10 +148,10 @@ public void CopyToAssemblyName(AssemblyName blank) // Our "Flags" contain both the classic flags and the ProcessorArchitecture + ContentType bits. The public AssemblyName has separate properties for // these. The setters for these properties quietly mask out any bits intended for the other one, so we needn't do that ourselves.. - blank.Flags = ExtractAssemblyNameFlags(this.Flags); - blank.ContentType = ExtractAssemblyContentType(this.Flags); + blank.Flags = AssemblyNameInfo.ExtractAssemblyNameFlags(this.Flags); + blank.ContentType = AssemblyNameInfo.ExtractAssemblyContentType(this.Flags); #pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete - blank.ProcessorArchitecture = ExtractProcessorArchitecture(this.Flags); + blank.ProcessorArchitecture = AssemblyNameInfo.ExtractProcessorArchitecture(this.Flags); #pragma warning restore SYSLIB0037 if (this.PublicKeyOrToken != null) @@ -168,17 +174,8 @@ public string FullName get { byte[]? pkt = (0 != (Flags & AssemblyNameFlags.PublicKey)) ? AssemblyNameHelpers.ComputePublicKeyToken(PublicKeyOrToken) : PublicKeyOrToken; - return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, ExtractAssemblyNameFlags(Flags), ExtractAssemblyContentType(Flags)); + return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, AssemblyNameInfo.ExtractAssemblyNameFlags(Flags), AssemblyNameInfo.ExtractAssemblyContentType(Flags)); } } - - private static AssemblyNameFlags ExtractAssemblyNameFlags(AssemblyNameFlags combinedFlags) - => combinedFlags & unchecked((AssemblyNameFlags)0xFFFFF10F); - - private static AssemblyContentType ExtractAssemblyContentType(AssemblyNameFlags flags) - => (AssemblyContentType)((((int)flags) >> 9) & 0x7); - - private static ProcessorArchitecture ExtractProcessorArchitecture(AssemblyNameFlags flags) - => (ProcessorArchitecture)((((int)flags) >> 4) & 0x7); } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameParser.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameParser.NativeAot.cs deleted file mode 100644 index e370cb4eed0a..000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameParser.NativeAot.cs +++ /dev/null @@ -1,242 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Reflection.Runtime.Assemblies; -using System.Reflection.Runtime.General; - -namespace System.Reflection -{ - // - // Parser for type names passed to GetType() apis. - // - internal partial struct TypeNameParser - { - private Func? _assemblyResolver; - private Func? _typeResolver; - private bool _throwOnError; - private bool _ignoreCase; - private bool _extensibleParser; - private Assembly? _topLevelAssembly; - private string? _defaultAssemblyName; - - internal static Type? GetType( - string typeName, - bool throwOnError = false, - bool ignoreCase = false, - string? defaultAssemblyName = null) - { - return GetType(typeName, assemblyResolver: null, typeResolver: null, - throwOnError: throwOnError, ignoreCase: ignoreCase, extensibleParser: false, defaultAssemblyName: defaultAssemblyName); - } - - internal static Type? GetType( - string typeName, - Func? assemblyResolver, - Func? typeResolver, - bool throwOnError = false, - bool ignoreCase = false, - bool extensibleParser = true, - string? defaultAssemblyName = null) - { - ArgumentNullException.ThrowIfNull(typeName); - - // Compat: Empty name throws TypeLoadException instead of - // the natural ArgumentException - if (typeName.Length == 0) - { - if (throwOnError) - throw new TypeLoadException(SR.Arg_TypeLoadNullStr); - return null; - } - - return new TypeNameParser(typeName) - { - _assemblyResolver = assemblyResolver, - _typeResolver = typeResolver, - _throwOnError = throwOnError, - _ignoreCase = ignoreCase, - _extensibleParser = extensibleParser, - _defaultAssemblyName = defaultAssemblyName - }.Parse(); - } - - internal static Type? GetType( - string typeName, - bool throwOnError, - bool ignoreCase, - Assembly topLevelAssembly) - { - return new TypeNameParser(typeName) - { - _throwOnError = throwOnError, - _ignoreCase = ignoreCase, - _topLevelAssembly = topLevelAssembly, - }.Parse(); - } - - private bool CheckTopLevelAssemblyQualifiedName() - { - if (_topLevelAssembly is not null) - { - if (_throwOnError) - throw new ArgumentException(SR.Argument_AssemblyGetTypeCannotSpecifyAssembly); - return false; - } - return true; - } - - private Assembly? ResolveAssembly(string assemblyName) - { - Assembly? assembly; - if (_assemblyResolver is not null) - { - assembly = _assemblyResolver(new AssemblyName(assemblyName)); - } - else - { - assembly = RuntimeAssemblyInfo.GetRuntimeAssemblyIfExists(RuntimeAssemblyName.Parse(assemblyName)); - } - - if (assembly is null && _throwOnError) - { - throw new FileNotFoundException(SR.Format(SR.FileNotFound_ResolveAssembly, assemblyName)); - } - - return assembly; - } - - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "GetType APIs are marked as RequiresUnreferencedCode.")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", - Justification = "GetType APIs are marked as RequiresUnreferencedCode.")] - private Type? GetType(string typeName, ReadOnlySpan nestedTypeNames, string? assemblyNameIfAny) - { - Assembly? assembly; - - if (assemblyNameIfAny is not null) - { - assembly = ResolveAssembly(assemblyNameIfAny); - if (assembly is null) - return null; - } - else - { - assembly = _topLevelAssembly; - } - - Type? type = null; - - // Resolve the top level type. - if (_typeResolver is not null) - { - string escapedTypeName = EscapeTypeName(typeName); - - type = _typeResolver(assembly, escapedTypeName, _ignoreCase); - - if (type is null) - { - if (_throwOnError) - { - throw new TypeLoadException(assembly is null ? - SR.Format(SR.TypeLoad_ResolveType, escapedTypeName) : - SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, escapedTypeName, assembly.FullName)); - } - return null; - } - } - else - { - if (assembly is not null) - { - if (assembly is RuntimeAssemblyInfo runtimeAssembly) - { - type = runtimeAssembly.GetTypeCore(typeName, throwOnError: _throwOnError, ignoreCase: _ignoreCase); - } - else - { - // This is a third-party Assembly object. We can emulate GetTypeCore() by calling the public GetType() - // method. This is wasteful because it'll probably reparse a type string that we've already parsed - // but it can't be helped. - type = assembly.GetType(EscapeTypeName(typeName), throwOnError: _throwOnError, ignoreCase: _ignoreCase); - } - - if (type is null) - return null; - } - else - { - RuntimeAssemblyInfo? defaultAssembly = null; - if (_defaultAssemblyName != null) - { - defaultAssembly = RuntimeAssemblyInfo.GetRuntimeAssemblyIfExists(RuntimeAssemblyName.Parse(_defaultAssemblyName)); - if (defaultAssembly != null) - { - type = defaultAssembly.GetTypeCore(typeName, throwOnError: false, ignoreCase: _ignoreCase); - } - } - - RuntimeAssemblyInfo? coreLib = null; - if (type is null) - { - coreLib = (RuntimeAssemblyInfo)typeof(object).Assembly; - if (coreLib != assembly) - { - type = coreLib.GetTypeCore(typeName, throwOnError: false, ignoreCase: _ignoreCase); - } - } - - if (type is null) - { - if (_throwOnError) - { - throw Helpers.CreateTypeLoadException(typeName, (defaultAssembly ?? coreLib).FullName); - } - return null; - } - } - } - - for (int i = 0; i < nestedTypeNames.Length; i++) - { - BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public; - if (_ignoreCase && _extensibleParser) - bindingFlags |= BindingFlags.IgnoreCase; - - Type declaringType = type; - - type = type.GetNestedType(nestedTypeNames[i], bindingFlags); - - // Compat: Non-extensible parser allows ambiguous matches with ignore case lookup - if (type is null && _ignoreCase && !_extensibleParser) - { - // Return the first name that matches. Which one gets returned on a multiple match is an implementation detail. - string lowerName = nestedTypeNames[i].ToLowerInvariant(); - foreach (Type nt in declaringType.GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Public)) - { - if (nt.Name.ToLowerInvariant() == lowerName) - { - type = nt; - break; - } - } - } - - if (type is null) - { - if (_throwOnError) - { - throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveNestedType, - nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : typeName)); - } - return null; - } - } - - return type; - } - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.NativeAot.cs new file mode 100644 index 000000000000..51129f0fda74 --- /dev/null +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.NativeAot.cs @@ -0,0 +1,246 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Reflection.Metadata; +using System.Reflection.Runtime.Assemblies; +using System.Reflection.Runtime.General; + +namespace System.Reflection +{ + // + // Resolver for type names passed to GetType() apis. + // + internal partial struct TypeNameResolver + { + private Func? _assemblyResolver; + private Func? _typeResolver; + private bool _throwOnError; + private bool _ignoreCase; + private bool _extensibleParser; + private Assembly? _topLevelAssembly; + private string? _defaultAssemblyName; + + internal static Type? GetType( + string typeName, + bool throwOnError = false, + bool ignoreCase = false, + string? defaultAssemblyName = null) + { + return GetType(typeName, assemblyResolver: null, typeResolver: null, + throwOnError: throwOnError, ignoreCase: ignoreCase, extensibleParser: false, defaultAssemblyName: defaultAssemblyName); + } + + internal static Type? GetType( + string typeName, + Func? assemblyResolver, + Func? typeResolver, + bool throwOnError = false, + bool ignoreCase = false, + bool extensibleParser = true, + string? defaultAssemblyName = null) + { + ArgumentNullException.ThrowIfNull(typeName); + + // Compat: Empty name throws TypeLoadException instead of + // the natural ArgumentException + if (typeName.Length == 0) + { + if (throwOnError) + throw new TypeLoadException(SR.Arg_TypeLoadNullStr); + return null; + } + + TypeName? parsed = TypeNameParser.Parse(typeName, throwOnError); + if (parsed is null) + { + return null; + } + + return new TypeNameResolver() + { + _assemblyResolver = assemblyResolver, + _typeResolver = typeResolver, + _throwOnError = throwOnError, + _ignoreCase = ignoreCase, + _extensibleParser = extensibleParser, + _defaultAssemblyName = defaultAssemblyName + }.Resolve(parsed); + } + + internal static Type? GetType( + string typeName, + bool throwOnError, + bool ignoreCase, + Assembly topLevelAssembly) + { + TypeName? parsed = TypeNameParser.Parse(typeName, throwOnError); + + if (parsed is null) + { + return null; + } + else if (topLevelAssembly is not null && parsed.AssemblyName is not null) + { + return throwOnError ? throw new ArgumentException(SR.Argument_AssemblyGetTypeCannotSpecifyAssembly) : null; + } + + return new TypeNameResolver() + { + _throwOnError = throwOnError, + _ignoreCase = ignoreCase, + _topLevelAssembly = topLevelAssembly, + }.Resolve(parsed); + } + + private Assembly? ResolveAssembly(Metadata.AssemblyNameInfo assemblyName) + { + Assembly? assembly; + if (_assemblyResolver is not null) + { + assembly = _assemblyResolver(assemblyName.ToAssemblyName()); + } + else + { + assembly = RuntimeAssemblyInfo.GetRuntimeAssemblyIfExists(RuntimeAssemblyName.FromAssemblyNameInfo(assemblyName)); + } + + if (assembly is null && _throwOnError) + { + throw new FileNotFoundException(SR.Format(SR.FileNotFound_ResolveAssembly, assemblyName)); + } + + return assembly; + } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "GetType APIs are marked as RequiresUnreferencedCode.")] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", + Justification = "GetType APIs are marked as RequiresUnreferencedCode.")] + private Type? GetType(string escapedTypeName, ReadOnlySpan nestedTypeNames, TypeName parsedName) + { + Assembly? assembly; + + if (parsedName.AssemblyName is not null) + { + assembly = ResolveAssembly(parsedName.AssemblyName); + if (assembly is null) + return null; + } + else + { + assembly = _topLevelAssembly; + } + + Type? type = null; + + // Resolve the top level type. + if (_typeResolver is not null) + { + type = _typeResolver(assembly, escapedTypeName, _ignoreCase); + + if (type is null) + { + if (_throwOnError) + { + throw new TypeLoadException(assembly is null ? + SR.Format(SR.TypeLoad_ResolveType, escapedTypeName) : + SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, escapedTypeName, assembly.FullName)); + } + return null; + } + } + else + { + if (assembly is not null) + { + if (assembly is RuntimeAssemblyInfo runtimeAssembly) + { + type = runtimeAssembly.GetTypeCore(TypeNameHelpers.Unescape(escapedTypeName), throwOnError: _throwOnError, ignoreCase: _ignoreCase); + } + else + { + // This is a third-party Assembly object. We can emulate GetTypeCore() by calling the public GetType() + // method. This is wasteful because it'll probably reparse a type string that we've already parsed + // but it can't be helped. + type = assembly.GetType(escapedTypeName, throwOnError: _throwOnError, ignoreCase: _ignoreCase); + } + + if (type is null) + return null; + } + else + { + string? unescapedTypeName = TypeNameHelpers.Unescape(escapedTypeName); + + RuntimeAssemblyInfo? defaultAssembly = null; + if (_defaultAssemblyName != null) + { + defaultAssembly = RuntimeAssemblyInfo.GetRuntimeAssemblyIfExists(RuntimeAssemblyName.Parse(_defaultAssemblyName)); + if (defaultAssembly != null) + { + type = defaultAssembly.GetTypeCore(unescapedTypeName, throwOnError: false, ignoreCase: _ignoreCase); + } + } + + RuntimeAssemblyInfo? coreLib = null; + if (type is null) + { + coreLib = (RuntimeAssemblyInfo)typeof(object).Assembly; + if (coreLib != assembly) + { + type = coreLib.GetTypeCore(unescapedTypeName, throwOnError: false, ignoreCase: _ignoreCase); + } + } + + if (type is null) + { + if (_throwOnError) + { + throw Helpers.CreateTypeLoadException(unescapedTypeName, (defaultAssembly ?? coreLib).FullName); + } + return null; + } + } + } + + for (int i = 0; i < nestedTypeNames.Length; i++) + { + BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public; + if (_ignoreCase && _extensibleParser) + bindingFlags |= BindingFlags.IgnoreCase; + + Type declaringType = type; + + type = type.GetNestedType(nestedTypeNames[i], bindingFlags); + + // Compat: Non-extensible parser allows ambiguous matches with ignore case lookup + if (type is null && _ignoreCase && !_extensibleParser) + { + // Return the first name that matches. Which one gets returned on a multiple match is an implementation detail. + foreach (Type nt in declaringType.GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Public)) + { + if (nt.Name.Equals(nestedTypeNames[i], StringComparison.InvariantCultureIgnoreCase)) + { + type = nt; + break; + } + } + } + + if (type is null) + { + if (_throwOnError) + { + throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveNestedType, + nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : TypeNameHelpers.Unescape(escapedTypeName))); + } + return null; + } + } + + return type; + } + } +} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs index c790682ecfcb..a2f5b48b498f 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs @@ -399,6 +399,36 @@ public static unsafe object GetUninitializedObject( return RuntimeImports.RhBox(mt, ref target); } + + /// + /// Get the size of an object of the given type. + /// + /// The type to get the size of. + /// The size of instances of the type. + /// The passed-in type is not a valid type to get the size of. + /// + /// This API returns the same value as for the type that represents. + /// + public static unsafe int SizeOf(RuntimeTypeHandle type) + { + if (type.IsNull) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.type); + + MethodTable* mt = type.ToMethodTable(); + + if (mt->ElementType == EETypeElementType.Void + || mt->IsGenericTypeDefinition) + { + throw new ArgumentException(SR.Arg_TypeNotSupported); + } + + if (mt->IsValueType) + { + return (int)mt->ValueTypeSize; + } + + return nint.Size; + } } // CLR arrays are laid out in memory as follows (multidimensional array bounds are optional): diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/TypeLoaderExports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/TypeLoaderExports.cs index 4388566b0cf0..82065e8c510f 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/TypeLoaderExports.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/TypeLoaderExports.cs @@ -10,6 +10,7 @@ using Internal.Runtime; using Internal.Runtime.Augments; +using Internal.Runtime.CompilerServices; namespace System.Runtime { @@ -162,8 +163,20 @@ private static unsafe Value CacheMiss(IntPtr context, IntPtr signature, RuntimeO internal static unsafe class RawCalliHelper { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Call(System.IntPtr pfn, ref byte data) - => ((delegate*)pfn)(ref data); + public static void CallDefaultStructConstructor(System.IntPtr pfn, ref byte data) + { + // Manually expand call of the instance method fat pointer. We cannot use a regular static C# function + // pointer call since it would not work for shared generic instance method. + if (FunctionPointerOps.IsGenericMethodPointer(pfn)) + { + GenericMethodDescriptor* gmd = FunctionPointerOps.ConvertToGenericDescriptor(pfn); + ((delegate*)gmd->MethodFunctionPointer)(ref data, gmd->InstantiationArgument); + } + else + { + ((delegate*)pfn)(ref data); + } + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T Call(System.IntPtr pfn, IntPtr arg) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs index ba8aba61a0a1..2321c5bafe14 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs @@ -32,6 +32,8 @@ private static Waiter GetWaiterForCurrentThread() private Waiter? _waitersHead; private Waiter? _waitersTail; + internal Lock AssociatedLock => _lock; + private unsafe void AssertIsInList(Waiter waiter) { Debug.Assert(_waitersHead != null && _waitersTail != null); @@ -106,6 +108,8 @@ public unsafe bool Wait(int millisecondsTimeout, object? associatedObjectForMoni if (!_lock.IsHeldByCurrentThread) throw new SynchronizationLockException(); + using ThreadBlockingInfo.Scope threadBlockingScope = new(this, millisecondsTimeout); + Waiter waiter = GetWaiterForCurrentThread(); AddWaiter(waiter); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs index 7ac43d2257e7..999d4061543e 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Lock.NativeAot.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Diagnostics.Tracing; +using System.Runtime; using System.Runtime.CompilerServices; namespace System.Threading @@ -17,13 +18,19 @@ public sealed partial class Lock private static int s_staticsInitializationStage; private static bool s_isSingleProcessor; private static short s_maxSpinCount; - private static short s_minSpinCount; + private static short s_minSpinCountForAdaptiveSpin; /// /// Initializes a new instance of the class. /// public Lock() => _spinCount = SpinCountNotInitialized; +#pragma warning disable CA1822 // can be marked as static - varies between runtimes + internal ulong OwningOSThreadId => 0; +#pragma warning restore CA1822 + + internal int OwningManagedThreadId => (int)_owningThreadId; + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal bool TryEnterOneShot(int currentManagedThreadId) { @@ -92,18 +99,6 @@ internal void Reenter(uint previousRecursionCount) _recursionCount = previousRecursionCount; } - private static bool IsFullyInitialized - { - get - { - // If NativeRuntimeEventSource is already being class-constructed by this thread earlier in the stack, Log can - // be null. This property is used to avoid going down the wait path in that case to avoid null checks in several - // other places. - Debug.Assert((StaticsInitializationStage)s_staticsInitializationStage == StaticsInitializationStage.Complete); - return NativeRuntimeEventSource.Log != null; - } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] private TryLockResult LazyInitializeOrEnter() { @@ -113,10 +108,6 @@ private TryLockResult LazyInitializeOrEnter() case StaticsInitializationStage.Complete: if (_spinCount == SpinCountNotInitialized) { - if (!IsFullyInitialized) - { - goto case StaticsInitializationStage.Started; - } _spinCount = s_maxSpinCount; } return TryLockResult.Spin; @@ -137,7 +128,7 @@ private TryLockResult LazyInitializeOrEnter() } stage = (StaticsInitializationStage)Volatile.Read(ref s_staticsInitializationStage); - if (stage == StaticsInitializationStage.Complete && IsFullyInitialized) + if (stage == StaticsInitializationStage.Complete) { goto case StaticsInitializationStage.Complete; } @@ -155,7 +146,9 @@ private TryLockResult LazyInitializeOrEnter() } default: - Debug.Assert(stage == StaticsInitializationStage.NotStarted); + Debug.Assert( + stage == StaticsInitializationStage.NotStarted || + stage == StaticsInitializationStage.PartiallyComplete); if (TryInitializeStatics()) { goto case StaticsInitializationStage.Complete; @@ -169,29 +162,53 @@ private static bool TryInitializeStatics() { // Since Lock is used to synchronize class construction, and some of the statics initialization may involve class // construction, update the stage first to avoid infinite recursion - switch ( - (StaticsInitializationStage) - Interlocked.CompareExchange( - ref s_staticsInitializationStage, - (int)StaticsInitializationStage.Started, - (int)StaticsInitializationStage.NotStarted)) + var oldStage = (StaticsInitializationStage)s_staticsInitializationStage; + while (true) { - case StaticsInitializationStage.Started: - return false; - case StaticsInitializationStage.Complete: + if (oldStage == StaticsInitializationStage.Complete) + { return true; + } + + var stageBeforeUpdate = + (StaticsInitializationStage)Interlocked.CompareExchange( + ref s_staticsInitializationStage, + (int)StaticsInitializationStage.Started, + (int)oldStage); + if (stageBeforeUpdate == StaticsInitializationStage.Started) + { + return false; + } + if (stageBeforeUpdate == oldStage) + { + Debug.Assert( + oldStage == StaticsInitializationStage.NotStarted || + oldStage == StaticsInitializationStage.PartiallyComplete); + break; + } + + oldStage = stageBeforeUpdate; } bool isFullyInitialized; try { - s_isSingleProcessor = Environment.IsSingleProcessor; - s_maxSpinCount = DetermineMaxSpinCount(); - s_minSpinCount = DetermineMinSpinCount(); + if (oldStage == StaticsInitializationStage.NotStarted) + { + // If the stage is PartiallyComplete, these will have already been initialized. + // + // Not using Environment.ProcessorCount here as it involves class construction, and if that property is + // already being constructed earlier in the stack on the same thread, it would return the default value + // here. Initialize s_isSingleProcessor first, as it may be used by other initialization afterwards. + s_isSingleProcessor = RuntimeImports.RhGetProcessCpuCount() == 1; + s_maxSpinCount = DetermineMaxSpinCount(); + s_minSpinCountForAdaptiveSpin = DetermineMinSpinCountForAdaptiveSpin(); + } // Also initialize some types that are used later to prevent potential class construction cycles. If // NativeRuntimeEventSource is already being class-constructed by this thread earlier in the stack, Log can be - // null. Avoid going down the wait path in that case to avoid null checks in several other places. + // null. Avoid going down the wait path in that case to avoid null checks in several other places. If not fully + // initialized, the stage will also be set to PartiallyComplete to try again. isFullyInitialized = NativeRuntimeEventSource.Log != null; } catch @@ -200,7 +217,11 @@ private static bool TryInitializeStatics() throw; } - Volatile.Write(ref s_staticsInitializationStage, (int)StaticsInitializationStage.Complete); + Volatile.Write( + ref s_staticsInitializationStage, + isFullyInitialized + ? (int)StaticsInitializationStage.Complete + : (int)StaticsInitializationStage.PartiallyComplete); return isFullyInitialized; } @@ -242,6 +263,7 @@ private enum StaticsInitializationStage { NotStarted, Started, + PartiallyComplete, Complete } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Monitor.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Monitor.NativeAot.cs index c9b270b716dd..bed275c1ea99 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Monitor.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Monitor.NativeAot.cs @@ -30,8 +30,8 @@ public static partial class Monitor private static Condition GetCondition(object obj) { Debug.Assert( - !(obj is Condition || obj is Lock), - "Do not use Monitor.Pulse or Wait on a Lock or Condition instance; use the methods on Condition instead."); + !(obj is Condition), + "Do not use Monitor.Pulse or Wait on a Condition instance; use the methods on Condition instead."); return s_conditionTable.GetValue(obj, s_createCondition); } #endregion diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/ObjectHeader.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/ObjectHeader.cs index 44ffec51a7e2..1d0c27751521 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/ObjectHeader.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/ObjectHeader.cs @@ -298,9 +298,6 @@ public static unsafe int TryAcquire(object obj, int currentThreadID, bool oneSho { ArgumentNullException.ThrowIfNull(obj); - Debug.Assert(!(obj is Lock), - "Do not use Monitor.Enter or TryEnter on a Lock instance; use Lock methods directly instead."); - // if thread ID is uninitialized or too big, we do "uncommon" part. if ((uint)(currentThreadID - 1) <= (uint)SBLK_MASK_LOCK_THREADID) { @@ -440,9 +437,6 @@ public static unsafe void Release(object obj) { ArgumentNullException.ThrowIfNull(obj); - Debug.Assert(!(obj is Lock), - "Do not use Monitor.Enter or TryEnter on a Lock instance; use Lock methods directly instead."); - int currentThreadID = ManagedThreadId.CurrentManagedThreadIdUnchecked; // transform uninitialized ID into -1, so it will not match any possible lock owner currentThreadID |= (currentThreadID - 1) >> 31; @@ -493,9 +487,6 @@ public static unsafe bool IsAcquired(object obj) { ArgumentNullException.ThrowIfNull(obj); - Debug.Assert(!(obj is Lock), - "Do not use Monitor.Enter or TryEnter on a Lock instance; use Lock methods directly instead."); - int currentThreadID = ManagedThreadId.CurrentManagedThreadIdUnchecked; // transform uninitialized ID into -1, so it will not match any possible lock owner currentThreadID |= (currentThreadID - 1) >> 31; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.NativeAot.cs index 9589edaab42b..d5b3c54e1fc2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.NativeAot.cs @@ -31,7 +31,7 @@ internal static unsafe RuntimeType GetTypeFromMethodTable(MethodTable* pMT) private static class AllocationLockHolder { - public static Lock AllocationLock = new Lock(useTrivialWaits: true); + public static readonly Lock AllocationLock = new Lock(useTrivialWaits: true); } [MethodImpl(MethodImplOptions.NoInlining)] @@ -95,7 +95,7 @@ internal string FormatTypeNameForReflection() [RequiresUnreferencedCode("The type might be removed")] public static Type GetType(string typeName, bool throwOnError, bool ignoreCase) { - return TypeNameParser.GetType(typeName, throwOnError: throwOnError, ignoreCase: ignoreCase); + return TypeNameResolver.GetType(typeName, throwOnError: throwOnError, ignoreCase: ignoreCase); } [Intrinsic] @@ -108,7 +108,7 @@ public static Type GetType(string typeName, bool throwOnError, bool ignoreCase) [RequiresUnreferencedCode("The type might be removed")] public static Type GetType(string typeName, Func? assemblyResolver, Func? typeResolver, bool throwOnError, bool ignoreCase) { - return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver, throwOnError: throwOnError, ignoreCase: ignoreCase); + return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver, throwOnError: throwOnError, ignoreCase: ignoreCase); } } } diff --git a/src/coreclr/nativeaot/System.Private.DisabledReflection/src/System.Private.DisabledReflection.csproj b/src/coreclr/nativeaot/System.Private.DisabledReflection/src/System.Private.DisabledReflection.csproj index dda9aca01512..365bf3356186 100644 --- a/src/coreclr/nativeaot/System.Private.DisabledReflection/src/System.Private.DisabledReflection.csproj +++ b/src/coreclr/nativeaot/System.Private.DisabledReflection/src/System.Private.DisabledReflection.csproj @@ -2,8 +2,6 @@ false - - true diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/MethodInvokerWithMethodInvokeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/MethodInvokerWithMethodInvokeInfo.cs index df5715e2d119..6bff16c340a9 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/MethodInvokerWithMethodInvokeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/MethodInvokerWithMethodInvokeInfo.cs @@ -62,6 +62,6 @@ internal static MethodBaseInvoker CreateMethodInvoker(RuntimeTypeHandle declarin return new InstanceMethodInvoker(methodInvokeInfo, declaringTypeHandle); } - internal MethodInvokeInfo MethodInvokeInfo { get; private set; } + internal MethodInvokeInfo MethodInvokeInfo { get; } } } diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj index ee7ed1e9c86a..86fb64fa5185 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj @@ -8,8 +8,6 @@ $(CompilerCommonPath)\Internal\NativeFormat false - - true diff --git a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs index 8d0314de1c9d..5e84594fc629 100644 --- a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs +++ b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs @@ -42,7 +42,7 @@ public static string FormatMethodName(MetadataReader metadataReader, Handle owni formatter._outputBuilder.Append('.'); formatter.EmitString(name); - if (!genericArguments.IsNull(metadataReader)) + if (!genericArguments.IsNil) { var args = metadataReader.GetConstantStringArray(genericArguments); bool first = true; @@ -262,7 +262,7 @@ private void EmitTypeName(Handle typeHandle, bool namespaceQualified) private void EmitNamespaceReferenceName(NamespaceReferenceHandle namespaceRefHandle) { NamespaceReference namespaceRef = _metadataReader.GetNamespaceReference(namespaceRefHandle); - if (!namespaceRef.ParentScopeOrNamespace.IsNull(_metadataReader) && + if (!namespaceRef.ParentScopeOrNamespace.IsNil && namespaceRef.ParentScopeOrNamespace.HandleType == HandleType.NamespaceReference) { int charsWritten = _outputBuilder.Length; @@ -276,7 +276,7 @@ private void EmitNamespaceReferenceName(NamespaceReferenceHandle namespaceRefHan private void EmitNamespaceDefinitionName(NamespaceDefinitionHandle namespaceDefHandle) { NamespaceDefinition namespaceDef = _metadataReader.GetNamespaceDefinition(namespaceDefHandle); - if (!namespaceDef.ParentScopeOrNamespace.IsNull(_metadataReader) && + if (!namespaceDef.ParentScopeOrNamespace.IsNil && namespaceDef.ParentScopeOrNamespace.HandleType == HandleType.NamespaceDefinition) { int charsWritten = _outputBuilder.Length; @@ -295,7 +295,7 @@ private void EmitNamespaceDefinitionName(NamespaceDefinitionHandle namespaceDefH private void EmitTypeReferenceName(TypeReferenceHandle typeRefHandle, bool namespaceQualified) { TypeReference typeRef = _metadataReader.GetTypeReference(typeRefHandle); - if (!typeRef.ParentNamespaceOrType.IsNull(_metadataReader)) + if (!typeRef.ParentNamespaceOrType.IsNil) { if (typeRef.ParentNamespaceOrType.HandleType != HandleType.NamespaceReference) { @@ -317,7 +317,7 @@ private void EmitTypeReferenceName(TypeReferenceHandle typeRefHandle, bool names private void EmitTypeDefinitionName(TypeDefinitionHandle typeDefHandle, bool namespaceQualified) { TypeDefinition typeDef = _metadataReader.GetTypeDefinition(typeDefHandle); - if (!typeDef.EnclosingType.IsNull(_metadataReader)) + if (!typeDef.EnclosingType.IsNil) { // Nested type EmitTypeName(typeDef.EnclosingType, namespaceQualified); @@ -520,7 +520,7 @@ private static object GetTypeContext(MetadataReader metadataReader, Handle handl public static SigTypeContext FromMethod(MetadataReader metadataReader, Handle enclosingTypeHandle, ConstantStringArrayHandle methodInst) { object methodContext = null; - if (!methodInst.IsNull(metadataReader)) + if (!methodInst.IsNil) methodContext = methodInst.GetConstantStringArray(metadataReader).Value; return new SigTypeContext(GetTypeContext(metadataReader, enclosingTypeHandle), methodContext); } diff --git a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/StackTraceMetadata.cs b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/StackTraceMetadata.cs index 7f9b66416c88..bed368cb664a 100644 --- a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/StackTraceMetadata.cs +++ b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/StackTraceMetadata.cs @@ -317,9 +317,9 @@ public string GetMethodNameFromRvaIfAvailable(int rva, out bool isStackTraceHidd isStackTraceHidden = data.IsHidden; - if (data.OwningType.IsNull(_metadataReader)) + if (data.OwningType.IsNil) { - Debug.Assert(data.Name.IsNull(_metadataReader) && data.Signature.IsNull(_metadataReader)); + Debug.Assert(data.Name.IsNil && data.Signature.IsNil); Debug.Assert(isStackTraceHidden); return null; } diff --git a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.csproj b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.csproj index 620a94d91c40..cc44031e9ac5 100644 --- a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.csproj +++ b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.csproj @@ -2,8 +2,6 @@ false - - true diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs index d973b0a02a70..7883e22a5e23 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs @@ -337,9 +337,19 @@ internal override IntPtr Create(TypeBuilder builder) { IntPtr result = TypeLoaderEnvironment.TryGetDefaultConstructorForType(Type); - - if (result == IntPtr.Zero) + if (result != IntPtr.Zero) + { + if (Type.IsValueType) + { + result = TypeLoaderEnvironment.ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(result, + builder.GetRuntimeTypeHandle(Type)); + } + } + else + { result = RuntimeAugments.GetFallbackDefaultConstructor(); + } + return result; } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/LockFreeObjectInterner.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/LockFreeObjectInterner.cs index 52593e30bb48..e4897f9854e3 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/LockFreeObjectInterner.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/LockFreeObjectInterner.cs @@ -8,7 +8,7 @@ namespace Internal.TypeSystem { public class LockFreeObjectInterner : LockFreeReaderHashtableOfPointers { - private static LockFreeObjectInterner s_interner = new LockFreeObjectInterner(); + private static readonly LockFreeObjectInterner s_interner = new LockFreeObjectInterner(); public static GCHandle GetInternedObjectHandle(object obj) { return s_interner.GetOrCreateValue(obj); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MetadataNameExtensions.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MetadataNameExtensions.cs index 3b998e208df7..8dcc07214219 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MetadataNameExtensions.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MetadataNameExtensions.cs @@ -84,7 +84,7 @@ public static string GetFullName(this TypeSpecificationHandle typeSpecHandle, Me { var typeSpec = typeSpecHandle.GetTypeSpecification(reader); - if (typeSpec.Signature.IsNull(reader)) + if (typeSpec.Signature.IsNil) return null; return typeSpec.Signature.GetFullName(reader); @@ -94,7 +94,7 @@ public static string GetFullName(this TypeInstantiationSignatureHandle typeInstS { var typeInstSig = typeInstSigHandle.GetTypeInstantiationSignature(reader); - if (typeInstSig.GenericType.IsNull(reader)) + if (typeInstSig.GenericType.IsNil) return null; var name = typeInstSig.GenericType.GetFullName(reader); @@ -118,11 +118,11 @@ public static void GetFullName(this TypeDefinitionHandle typeDefHandle, Metadata { var typeDef = typeDefHandle.GetTypeDefinition(reader); - Debug.Assert(!typeDef.Name.IsNull(reader)); + Debug.Assert(!typeDef.Name.IsNil); name = typeDef.Name.GetConstantStringValue(reader).Value; - enclosing = typeDef.EnclosingType.IsNull(reader) ? null : typeDef.EnclosingType.GetFullName(reader); - nspace = typeDef.NamespaceDefinition.IsNull(reader) ? null : typeDef.NamespaceDefinition.GetFullName(reader); + enclosing = typeDef.EnclosingType.IsNil ? null : typeDef.EnclosingType.GetFullName(reader); + nspace = typeDef.NamespaceDefinition.IsNil ? null : typeDef.NamespaceDefinition.GetFullName(reader); } public static string GetFullName(this TypeDefinitionHandle typeDefHandle, MetadataReader reader) @@ -144,16 +144,16 @@ public static string GetContainingModuleName(this TypeDefinitionHandle typeDefHa { var typeDef = typeDefHandle.GetTypeDefinition(reader); - Handle currentHandle = !typeDef.EnclosingType.IsNull(reader) ? (Handle)typeDef.EnclosingType : (Handle)typeDef.NamespaceDefinition; - Debug.Assert(!currentHandle.IsNull(reader)); + Handle currentHandle = !typeDef.EnclosingType.IsNil ? (Handle)typeDef.EnclosingType : (Handle)typeDef.NamespaceDefinition; + Debug.Assert(!currentHandle.IsNil); - while (!currentHandle.IsNull(reader)) + while (!currentHandle.IsNil) { switch (currentHandle.HandleType) { case HandleType.TypeDefinition: typeDef = currentHandle.ToTypeDefinitionHandle(reader).GetTypeDefinition(reader); - currentHandle = !typeDef.EnclosingType.IsNull(reader) ? (Handle)typeDef.EnclosingType : (Handle)typeDef.NamespaceDefinition; + currentHandle = !typeDef.EnclosingType.IsNil ? (Handle)typeDef.EnclosingType : (Handle)typeDef.NamespaceDefinition; break; case HandleType.NamespaceDefinition: @@ -174,11 +174,11 @@ public static string GetFullName(this NamespaceDefinitionHandle namespaceHandle, { var nspace = namespaceHandle.GetNamespaceDefinition(reader); - if (nspace.Name.IsNull(reader)) + if (nspace.Name.IsNil) return null; var name = nspace.Name.GetConstantStringValue(reader).Value; - var containingNamespace = nspace.ParentScopeOrNamespace.IsNull(reader) ? null : nspace.ParentScopeOrNamespace.GetFullName(reader); + var containingNamespace = nspace.ParentScopeOrNamespace.IsNil ? null : nspace.ParentScopeOrNamespace.GetFullName(reader); if (containingNamespace != null) return containingNamespace + "." + name; @@ -190,7 +190,7 @@ public static void GetFullName(this TypeReferenceHandle typeRefHandle, MetadataR { var typeRef = typeRefHandle.GetTypeReference(reader); - Debug.Assert(!typeRef.TypeName.IsNull(reader)); + Debug.Assert(!typeRef.TypeName.IsNil); name = typeRef.TypeName.GetConstantStringValue(reader).Value; enclosing = typeRef.ParentNamespaceOrType.HandleType == HandleType.TypeReference ? typeRef.ParentNamespaceOrType.GetFullName(reader) : null; @@ -217,9 +217,9 @@ public static string GetContainingModuleName(this TypeReferenceHandle typeRefHan var typeRef = typeRefHandle.GetTypeReference(reader); Handle currentHandle = typeRef.ParentNamespaceOrType; - Debug.Assert(!currentHandle.IsNull(reader)); + Debug.Assert(!currentHandle.IsNil); - while (!currentHandle.IsNull(reader)) + while (!currentHandle.IsNil) { switch (currentHandle.HandleType) { @@ -243,11 +243,11 @@ public static string GetFullName(this NamespaceReferenceHandle namespaceHandle, { var nspace = namespaceHandle.GetNamespaceReference(reader); - if (nspace.Name.IsNull(reader)) + if (nspace.Name.IsNil) return null; var name = nspace.Name.GetConstantStringValue(reader).Value; - var containingNamespace = nspace.ParentScopeOrNamespace.IsNull(reader) ? null : nspace.ParentScopeOrNamespace.GetFullName(reader); + var containingNamespace = nspace.ParentScopeOrNamespace.IsNil ? null : nspace.ParentScopeOrNamespace.GetFullName(reader); if (containingNamespace != null) return containingNamespace + "." + name; diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs index 3aff8131b762..c484eb6e5afd 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs @@ -20,7 +20,7 @@ public unsafe class ModuleInfo /// /// Module handle is the TypeManager associated with this module. /// - public TypeManagerHandle Handle { get; private set; } + public TypeManagerHandle Handle { get; } /// /// Initialize module info and construct per-module metadata reader. @@ -49,7 +49,7 @@ internal NativeFormatModuleInfo(TypeManagerHandle moduleHandle, IntPtr pBlob, in /// /// Module metadata reader for NativeFormat metadata /// - public MetadataReader MetadataReader { get; private set; } + public MetadataReader MetadataReader { get; } internal unsafe bool TryFindBlob(ReflectionMapBlob blobId, out byte* pBlob, out uint cbBlob) { diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs index 04958f81927a..90a2c9857c6d 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs @@ -193,18 +193,16 @@ internal MethodDesc GetMethod(ref NativeParser parser, out RuntimeSignature meth { TypeDesc[] typeArguments = GetTypeSequence(ref parser); Debug.Assert(typeArguments.Length > 0); - retVal = this._typeSystemContext.ResolveGenericMethodInstantiation(unboxingStub, containingType, nameAndSignature, new Instantiation(typeArguments), functionPointer, (flags & MethodFlags.FunctionPointerIsUSG) != 0); + retVal = this._typeSystemContext.ResolveGenericMethodInstantiation(unboxingStub, containingType, nameAndSignature, new Instantiation(typeArguments)); } else { - retVal = this._typeSystemContext.ResolveRuntimeMethod(unboxingStub, containingType, nameAndSignature, functionPointer, (flags & MethodFlags.FunctionPointerIsUSG) != 0); + retVal = this._typeSystemContext.ResolveRuntimeMethod(unboxingStub, containingType, nameAndSignature); } - if ((flags & MethodFlags.FunctionPointerIsUSG) != 0) + if ((flags & MethodFlags.HasFunctionPointer) != 0) { - // TODO, consider a change such that if a USG function pointer is passed in, but we have - // a way to get a non-usg pointer, that may be preferable - Debug.Assert(retVal.UsgFunctionPointer != IntPtr.Zero); + retVal.SetFunctionPointer(functionPointer); } return retVal; diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs index 8ee004b11d42..43ea9b81d8bf 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs @@ -300,7 +300,7 @@ internal void ParseNativeLayoutInfo(InstantiatedMethod method) if (method.UnboxingStub) { // Strip unboxing stub, note the first parameter which is false - nonTemplateMethod = (InstantiatedMethod)method.Context.ResolveGenericMethodInstantiation(false, (DefType)method.OwningType, method.NameAndSignature, method.Instantiation, IntPtr.Zero, false); + nonTemplateMethod = (InstantiatedMethod)method.Context.ResolveGenericMethodInstantiation(false, (DefType)method.OwningType, method.NameAndSignature, method.Instantiation); } uint nativeLayoutInfoToken; @@ -311,9 +311,11 @@ internal void ParseNativeLayoutInfo(InstantiatedMethod method) throw new MissingTemplateException(); } - if (templateMethod.FunctionPointer != IntPtr.Zero) + // We might have a mismatch between unboxing/non-unboxing variants so only remember it for static methods + if (TypeLoaderEnvironment.IsStaticMethodSignature(templateMethod.NameAndSignature) + && templateMethod.FunctionPointer != IntPtr.Zero) { - nonTemplateMethod.SetFunctionPointer(templateMethod.FunctionPointer, isFunctionPointerUSG: false); + nonTemplateMethod.SetFunctionPointer(templateMethod.FunctionPointer); } // Ensure that if this method is non-shareable from a normal canonical perspective, then diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs index c5f530822614..c8437c4a4e43 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs @@ -153,7 +153,7 @@ internal override bool MatchParsedEntry(ref NativeParser entryParser, ref Extern DefType parsedDeclaringType = context.ResolveRuntimeTypeHandle(parsedDeclaringTypeHandle) as DefType; Instantiation parsedArgs = context.ResolveRuntimeTypeHandles(parsedArgsHandles); - InstantiatedMethod parsedGenericMethod = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, parsedDeclaringType, nameAndSignature, parsedArgs, IntPtr.Zero, false); + InstantiatedMethod parsedGenericMethod = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, parsedDeclaringType, nameAndSignature, parsedArgs); return parsedGenericMethod == _methodToLookup; } @@ -164,7 +164,7 @@ internal override bool MatchGenericMethodEntry(GenericMethodEntry entry) DefType parsedDeclaringType = context.ResolveRuntimeTypeHandle(entry._declaringTypeHandle) as DefType; Instantiation parsedArgs = context.ResolveRuntimeTypeHandles(entry._genericMethodArgumentHandles); - InstantiatedMethod parsedGenericMethod = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, parsedDeclaringType, entry._methodNameAndSignature, parsedArgs, IntPtr.Zero, false); + InstantiatedMethod parsedGenericMethod = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, parsedDeclaringType, entry._methodNameAndSignature, parsedArgs); return parsedGenericMethod == _methodToLookup; } @@ -267,9 +267,7 @@ public bool TryGetGenericVirtualMethodPointer(InstantiatedMethod method, out Int return false; } - methodPointer = templateMethod.IsCanonicalMethod(CanonicalFormKind.Universal) ? - templateMethod.UsgFunctionPointer : - templateMethod.FunctionPointer; + methodPointer = templateMethod.FunctionPointer; if (!TryLookupGenericMethodDictionary(new MethodDescBasedGenericMethodLookup(method), out dictionaryPointer)) { diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs index d9416b328638..c73df4af62b5 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs @@ -309,7 +309,7 @@ private static InstantiatedMethod FindMatchingInterfaceSlot(NativeFormatModuleIn Debug.Assert(interfaceImplType != null); } - return (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, interfaceImplType, targetMethodNameAndSignature, slotMethod.Instantiation, IntPtr.Zero, false); + return (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, interfaceImplType, targetMethodNameAndSignature, slotMethod.Instantiation); } } } @@ -500,7 +500,7 @@ private static InstantiatedMethod ResolveGenericVirtualMethodTarget(DefType targ Debug.Assert(targetMethodNameAndSignature != null); TypeSystemContext context = slotMethod.Context; - return (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, targetType, targetMethodNameAndSignature, slotMethod.Instantiation, IntPtr.Zero, false); + return (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, targetType, targetMethodNameAndSignature, slotMethod.Instantiation); } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs index 9ddec8a39d7a..dd2bc75e3d61 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs @@ -388,10 +388,10 @@ public MethodDesc GetMethodDescForDynamicRuntimeMethodHandle(TypeSystemContext c if (genericMethodArgs != null) { Instantiation methodInst = context.ResolveRuntimeTypeHandles(genericMethodArgs); - return context.ResolveGenericMethodInstantiation(unboxingStub: false, type, nameAndSignature, methodInst, default, default); + return context.ResolveGenericMethodInstantiation(unboxingStub: false, type, nameAndSignature, methodInst); } - return context.ResolveRuntimeMethod(unboxingStub: false, type, nameAndSignature, default, default); + return context.ResolveRuntimeMethod(unboxingStub: false, type, nameAndSignature); } private unsafe bool TryGetStaticRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs) diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs index 42864c10f2eb..22c07b2e837b 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs @@ -485,7 +485,7 @@ public bool TryGetGenericMethodDictionaryForComponents(RuntimeTypeHandle declari TypeSystemContext context = TypeSystemContextFactory.Create(); DefType declaringType = (DefType)context.ResolveRuntimeTypeHandle(declaringTypeHandle); - InstantiatedMethod methodBeingLoaded = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, declaringType, nameAndSignature, context.ResolveRuntimeTypeHandles(genericMethodArgHandles), IntPtr.Zero, false); + InstantiatedMethod methodBeingLoaded = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, declaringType, nameAndSignature, context.ResolveRuntimeTypeHandles(genericMethodArgHandles)); if (TryLookupGenericMethodDictionary(new MethodDescBasedGenericMethodLookup(methodBeingLoaded), out methodDictionary)) { diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemContextFactory.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemContextFactory.cs index 410296beaf0b..06db5253c590 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemContextFactory.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemContextFactory.cs @@ -18,7 +18,7 @@ public static class TypeSystemContextFactory // This allows us to avoid recreating the type resolution context again and again, but still allows it to go away once the types are no longer being built private static GCHandle s_cachedContext = GCHandle.Alloc(null, GCHandleType.Weak); - private static Lock s_lock = new Lock(useTrivialWaits: true); + private static readonly Lock s_lock = new Lock(useTrivialWaits: true); public static TypeSystemContext Create() { diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/AssemblyNameInfo.Dummy.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/AssemblyNameInfo.Dummy.cs new file mode 100644 index 000000000000..51d07ba6a15a --- /dev/null +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/AssemblyNameInfo.Dummy.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Internal.TypeSystem +{ + // Dummy implementation of AssemlyNameInfo for runtime type system + public abstract class AssemblyNameInfo + { + public abstract string FullName { get; } + } +} diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/MethodDesc.Runtime.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/MethodDesc.Runtime.cs index 89161ce5309d..24dceff6d0f0 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/MethodDesc.Runtime.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/MethodDesc.Runtime.cs @@ -6,19 +6,18 @@ using Internal.Runtime.CompilerServices; +using Debug = System.Diagnostics.Debug; + namespace Internal.TypeSystem { public partial class MethodDesc { private IntPtr _functionPointer; - private IntPtr _usgFunctionPointer; - public void SetFunctionPointer(IntPtr functionPointer, bool isFunctionPointerUSG) + public void SetFunctionPointer(IntPtr functionPointer) { - if (isFunctionPointerUSG) - _usgFunctionPointer = functionPointer; - else - _functionPointer = functionPointer; + Debug.Assert(_functionPointer == IntPtr.Zero || _functionPointer == functionPointer); + _functionPointer = functionPointer; } /// @@ -32,17 +31,6 @@ public IntPtr FunctionPointer } } - /// - /// Pointer to function's universal shared generics code. May be IntPtr.Zero - /// - public IntPtr UsgFunctionPointer - { - get - { - return _usgFunctionPointer; - } - } - public abstract MethodNameAndSignature NameAndSignature { get; } private bool? _isNonSharableCache; diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.Canon.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.Canon.cs index 956dcdcafb97..ad12ea96f008 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.Canon.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.Canon.cs @@ -23,7 +23,7 @@ public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind) if (canonicalizedTypeOfTargetMethod == OwningType) return this; - return Context.ResolveRuntimeMethod(this.UnboxingStub, canonicalizedTypeOfTargetMethod, this.NameAndSignature, IntPtr.Zero, false); + return Context.ResolveRuntimeMethod(this.UnboxingStub, canonicalizedTypeOfTargetMethod, this.NameAndSignature); } } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.cs index f95b8561e3a9..042b1957e22b 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.cs @@ -117,7 +117,7 @@ public override MethodDesc GetTypicalMethodDefinition() } // Otherwise, find its equivalent on the type definition of the owning type - return Context.ResolveRuntimeMethod(UnboxingStub, (DefType)owningTypeDefinition, _nameAndSignature, IntPtr.Zero, false); + return Context.ResolveRuntimeMethod(UnboxingStub, (DefType)owningTypeDefinition, _nameAndSignature); } public override MethodDesc InstantiateSignature(Instantiation typeInstantiation, Instantiation methodInstantiation) @@ -127,7 +127,7 @@ public override MethodDesc InstantiateSignature(Instantiation typeInstantiation, TypeDesc owningType = method.OwningType; TypeDesc instantiatedOwningType = owningType.InstantiateSignature(typeInstantiation, methodInstantiation); if (owningType != instantiatedOwningType) - method = instantiatedOwningType.Context.ResolveRuntimeMethod(UnboxingStub, (DefType)instantiatedOwningType, _nameAndSignature, IntPtr.Zero, false); + method = instantiatedOwningType.Context.ResolveRuntimeMethod(UnboxingStub, (DefType)instantiatedOwningType, _nameAndSignature); Instantiation instantiation = method.Instantiation; TypeDesc[] clone = null; diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs index 464a370a5f7b..1e4b88855222 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs @@ -417,7 +417,7 @@ protected override MethodDesc CreateValueFromKey(RuntimeMethodKey key) // Instantiated Types always get their methods through GetMethodForInstantiatedType if (key._owningType is InstantiatedType) { - MethodDesc typicalMethod = key._owningType.Context.ResolveRuntimeMethod(key._unboxingStub, (DefType)key._owningType.GetTypeDefinition(), key._methodNameAndSignature, IntPtr.Zero, false); + MethodDesc typicalMethod = key._owningType.Context.ResolveRuntimeMethod(key._unboxingStub, (DefType)key._owningType.GetTypeDefinition(), key._methodNameAndSignature); return typicalMethod.Context.GetMethodForInstantiatedType(typicalMethod, (InstantiatedType)key._owningType); } } @@ -434,18 +434,10 @@ protected override MethodDesc CreateValueFromKey(RuntimeMethodKey key) private RuntimeMethodKey.RuntimeMethodKeyHashtable _runtimeMethods; - internal MethodDesc ResolveRuntimeMethod(bool unboxingStub, DefType owningType, MethodNameAndSignature nameAndSignature, IntPtr functionPointer, bool usgFunctionPointer) + internal MethodDesc ResolveRuntimeMethod(bool unboxingStub, DefType owningType, MethodNameAndSignature nameAndSignature) { _runtimeMethods ??= new RuntimeMethodKey.RuntimeMethodKeyHashtable(); - - MethodDesc retVal = _runtimeMethods.GetOrCreateValue(new RuntimeMethodKey(unboxingStub, owningType, nameAndSignature)); - - if (functionPointer != IntPtr.Zero) - { - retVal.SetFunctionPointer(functionPointer, usgFunctionPointer); - } - - return retVal; + return _runtimeMethods.GetOrCreateValue(new RuntimeMethodKey(unboxingStub, owningType, nameAndSignature)); } private LowLevelDictionary _genericTypeInstances; @@ -479,9 +471,9 @@ public DefType ResolveGenericInstantiation(DefType typeDef, Instantiation argume /// /// Find a method based on owner type and nativelayout name, method instantiation, and signature. /// - public MethodDesc ResolveGenericMethodInstantiation(bool unboxingStub, DefType owningType, MethodNameAndSignature nameAndSignature, Instantiation methodInstantiation, IntPtr functionPointer, bool usgFunctionPointer) + public MethodDesc ResolveGenericMethodInstantiation(bool unboxingStub, DefType owningType, MethodNameAndSignature nameAndSignature, Instantiation methodInstantiation) { - var uninstantiatedMethod = ResolveRuntimeMethod(unboxingStub, owningType, nameAndSignature, IntPtr.Zero, false); + var uninstantiatedMethod = ResolveRuntimeMethod(unboxingStub, owningType, nameAndSignature); MethodDesc returnedMethod; if (methodInstantiation.IsNull || (methodInstantiation.Length == 0)) @@ -492,12 +484,6 @@ public MethodDesc ResolveGenericMethodInstantiation(bool unboxingStub, DefType o { returnedMethod = GetInstantiatedMethod(uninstantiatedMethod, methodInstantiation); } - - if (functionPointer != IntPtr.Zero) - { - returnedMethod.SetFunctionPointer(functionPointer, usgFunctionPointer); - } - return returnedMethod; } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj index cc094a354e08..ee1285a4b9a0 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj @@ -8,8 +8,6 @@ GENERICS_FORCE_USG;$(DefineConstants) false - - true @@ -255,6 +253,7 @@ + diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/Test.CoreLib.csproj b/src/coreclr/nativeaot/Test.CoreLib/src/Test.CoreLib.csproj index 40eb0de46bab..aea036727ba3 100644 --- a/src/coreclr/nativeaot/Test.CoreLib/src/Test.CoreLib.csproj +++ b/src/coreclr/nativeaot/Test.CoreLib/src/Test.CoreLib.csproj @@ -2,7 +2,7 @@ false false - netstandard2.0 + $(NetCoreAppToolCurrent) FEATURE_GC_STRESS;$(DefineConstants) diff --git a/src/coreclr/nativeaot/docs/android-bionic.md b/src/coreclr/nativeaot/docs/android-bionic.md index a5148baa5840..da5b5c305923 100644 --- a/src/coreclr/nativeaot/docs/android-bionic.md +++ b/src/coreclr/nativeaot/docs/android-bionic.md @@ -29,12 +29,11 @@ For an example of a Native AOT shared library invoked through JNI from Java see ## Known issues -If you hit `error : version script assignment of 'V1.0' to symbol '_init' failed: symbol not defined` - this is a known issue https://github.com/dotnet/runtime/issues/92272, you can add following lines to your csproj to work around: +If you hit `error : version script assignment of 'V1.0' to symbol '_init' failed: symbol not defined` - this is a known issue with .NET 8 release https://github.com/dotnet/runtime/issues/92272, you can add following lines to your csproj to work around: ```xml - - - + + ``` diff --git a/src/coreclr/pal/inc/mbusafecrt.h b/src/coreclr/pal/inc/mbusafecrt.h index 7052b7834a17..0dfb02752e2e 100644 --- a/src/coreclr/pal/inc/mbusafecrt.h +++ b/src/coreclr/pal/inc/mbusafecrt.h @@ -60,17 +60,6 @@ extern errno_t wcsncpy_s( WCHAR* outDest, size_t inDestBufferSize, const WCHAR* extern size_t PAL_wcsnlen( const WCHAR* inString, size_t inMaxSize ); -extern errno_t _itoa_s( int inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); -extern errno_t _itow_s( int inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); - -extern errno_t _ltoa_s( long inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); -extern errno_t _ltow_s( long inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); - -extern errno_t _ultoa_s( unsigned long inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); -extern errno_t _ultow_s( unsigned long inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); - -extern errno_t _i64tow_s( long long inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); - extern errno_t _makepath_s( char* outDest, size_t inDestBufferSize, const char* inDrive, const char* inDirectory, const char* inFilename, const char* inExtension ); extern errno_t _wmakepath_s( WCHAR* outDest, size_t inDestBufferSize, const WCHAR* inDrive, const WCHAR* inDirectory, const WCHAR* inFilename, const WCHAR* inExtension ); diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index 9a1d25515bb3..c64cf8ee020a 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -184,14 +184,6 @@ extern bool g_arm64_atomics_present; #define __has_cpp_attribute(x) (0) #endif -#ifndef FALLTHROUGH -#if __has_cpp_attribute(fallthrough) -#define FALLTHROUGH [[fallthrough]] -#else // __has_cpp_attribute(fallthrough) -#define FALLTHROUGH -#endif // __has_cpp_attribute(fallthrough) -#endif // FALLTHROUGH - /******************* PAL-Specific Entrypoints *****************************/ #define IsDebuggerPresent PAL_IsDebuggerPresent @@ -3379,8 +3371,9 @@ EXTERN_C PALIMPORT inline RETURN_TYPE PALAPI METHOD_DECL \ /* Function multiversioning will never inline a method that is \ marked such. However, just to make sure that we don't see \ surprises, explicitely mark them as noinline. */ \ -__attribute__((target("lse"))) __attribute__((noinline)) \ -EXTERN_C PALIMPORT inline RETURN_TYPE PALAPI Lse_##METHOD_DECL \ +EXTERN_C PALIMPORT inline RETURN_TYPE PALAPI \ +__attribute__((target("+lse"))) __attribute__((noinline)) \ +Lse_##METHOD_DECL \ { \ return INTRINSIC_NAME; \ } \ @@ -3780,7 +3773,7 @@ PALAPI FlushProcessWriteBuffers(); typedef void (*PAL_ActivationFunction)(CONTEXT *context); -typedef BOOL (*PAL_SafeActivationCheckFunction)(SIZE_T ip, BOOL checkingCurrentThread); +typedef BOOL (*PAL_SafeActivationCheckFunction)(SIZE_T ip); PALIMPORT VOID @@ -3870,7 +3863,6 @@ PALIMPORT DLLEXPORT int __cdecl _snprintf_s(char *, size_t, size_t, const char * PALIMPORT DLLEXPORT int __cdecl vsprintf_s(char *, size_t, const char *, va_list); PALIMPORT DLLEXPORT int __cdecl sprintf_s(char *, size_t, const char *, ... ); PALIMPORT DLLEXPORT int __cdecl sscanf_s(const char *, const char *, ...); -PALIMPORT DLLEXPORT errno_t __cdecl _itow_s(int, WCHAR *, size_t, int); PALIMPORT DLLEXPORT size_t __cdecl PAL_wcslen(const WCHAR *); PALIMPORT DLLEXPORT int __cdecl PAL_wcscmp(const WCHAR*, const WCHAR*); @@ -3887,7 +3879,6 @@ PALIMPORT DLLEXPORT ULONGLONG __cdecl PAL__wcstoui64(const WCHAR *, WCHAR **, in PALIMPORT DLLEXPORT double __cdecl PAL_wcstod(const WCHAR *, WCHAR **); PALIMPORT errno_t __cdecl _wcslwr_s(WCHAR *, size_t sz); -PALIMPORT DLLEXPORT errno_t __cdecl _i64tow_s(long long, WCHAR *, size_t, int); PALIMPORT int __cdecl _wtoi(const WCHAR *); PALIMPORT FILE * __cdecl _wfopen(const WCHAR *, const WCHAR *); @@ -3970,9 +3961,6 @@ PALIMPORT DLLEXPORT int __cdecl _putenv(const char *); #define ERANGE 34 -PALIMPORT WCHAR __cdecl PAL_ToUpperInvariant(WCHAR); -PALIMPORT WCHAR __cdecl PAL_ToLowerInvariant(WCHAR); - /****************PAL Perf functions for PInvoke*********************/ #if PAL_PERF PALIMPORT @@ -4428,6 +4416,8 @@ class NativeExceptionHolderFactory #define PAL_CPP_CATCH_EXCEPTION(ident) } catch (Exception *ident) { #define PAL_CPP_CATCH_EXCEPTION_NOARG } catch (Exception *) { #define PAL_CPP_CATCH_DERIVED(type, ident) } catch (type *ident) { +#define PAL_CPP_CATCH_NON_DERIVED(type, ident) } catch (type ident) { +#define PAL_CPP_CATCH_NON_DERIVED_NOARG(type) } catch (type) { #define PAL_CPP_CATCH_ALL } catch (...) { \ try { throw; } \ catch (PAL_SEHException& ex) { ex.SecondPassDone(); } \ diff --git a/src/coreclr/pal/inc/pal_mstypes.h b/src/coreclr/pal/inc/pal_mstypes.h index d59103002d18..e3423c41f898 100644 --- a/src/coreclr/pal/inc/pal_mstypes.h +++ b/src/coreclr/pal/inc/pal_mstypes.h @@ -1,14 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -/*++ - - - - - ---*/ - //////////////////////////////////////////////////////////////////////// // Extensions to the usual posix header files //////////////////////////////////////////////////////////////////////// @@ -16,6 +8,8 @@ #ifndef __PAL_MSTYPES_H__ #define __PAL_MSTYPES_H__ +#include + #ifdef __cplusplus extern "C" { #endif @@ -31,8 +25,6 @@ extern "C" { #define EXTERN_C #endif // __cplusplus -#ifndef _MSC_VER - // Note: Win32-hosted GCC predefines __stdcall and __cdecl, but Unix- // hosted GCC does not. @@ -88,27 +80,13 @@ extern "C" { #define __forceinline inline -#endif // !_MSC_VER - -#ifdef _MSC_VER - -#if defined(PAL_IMPLEMENTATION) #define PALIMPORT -#else -#define PALIMPORT __declspec(dllimport) -#endif -#define DLLEXPORT __declspec(dllexport) -#define PAL_NORETURN __declspec(noreturn) - -#else -#define PALIMPORT #ifndef DLLEXPORT #define DLLEXPORT __attribute__((visibility("default"))) #endif -#define PAL_NORETURN __attribute__((noreturn)) -#endif +#define PAL_NORETURN __attribute__((noreturn)) #define PALAPI DLLEXPORT __cdecl #define PALAPI_NOEXPORT __cdecl @@ -147,19 +125,6 @@ extern "C" { // Misc. type helpers //////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER - -// MSVC's way of declaring large integer constants -// If you define these in one step, without the _HELPER macros, you -// get extra whitespace when composing these with other concatenating macros. -#define I64_HELPER(x) x ## i64 -#define I64(x) I64_HELPER(x) - -#define UI64_HELPER(x) x ## ui64 -#define UI64(x) UI64_HELPER(x) - -#else // _MSC_VER - // GCC's way of declaring large integer constants // If you define these in one step, without the _HELPER macros, you // get extra whitespace when composing these with other concatenating macros. @@ -169,63 +134,21 @@ extern "C" { #define UI64_HELPER(x) x ## ULL #define UI64(x) UI64_HELPER(x) -#endif // _MSC_VER - //////////////////////////////////////////////////////////////////////// // Misc. types //////////////////////////////////////////////////////////////////////// -#ifndef _MSC_VER - -// A bunch of source files (e.g. most of the ndp tree) include pal.h -// but are written to be LLP64, not LP64. (LP64 => long = 64 bits -// LLP64 => longs = 32 bits, long long = 64 bits) -// -// To handle this difference, we #define long to be int (and thus 32 bits) when -// compiling those files. (See the bottom of this file or search for -// #define long to see where we do this.) -// -// But this fix is more complicated than it seems, because we also use the -// preprocessor to #define __int64 to long for LP64 architectures (__int64 -// isn't a builtin in gcc). We don't want __int64 to be an int (by cascading -// macro rules). So we play this little trick below where we add -// __cppmungestrip before "long", which is what we're really #defining __int64 -// to. The preprocessor sees __cppmungestriplong as something different than -// long, so it doesn't replace it with int. The during the cppmunge phase, we -// remove the __cppmungestrip part, leaving long for the compiler to see. -// -// Note that we can't just use a typedef to define __int64 as long before -// #defining long because typedefed types can't be signedness-agnostic (i.e. -// they must be either signed or unsigned) and we want to be able to use -// __int64 as though it were intrinsic - -#if defined(HOST_64BIT) && !defined(__APPLE__) -#define __int64 long -#else // HOST_64BIT && !__APPLE__ -#define __int64 long long -#endif // HOST_64BIT && !__APPLE__ -#define __int32 int -#define __int16 short int -#define __int8 char // assumes char is signed - -#endif // _MSC_VER - - -#ifndef _MSC_VER - #if HOST_64BIT typedef long double LONG_DOUBLE; #endif -#endif // _MSC_VER - typedef void VOID; typedef int LONG; // NOTE: diff from windows.h, for LP64 compat typedef unsigned int ULONG; // NOTE: diff from windows.h, for LP64 compat -typedef __int64 LONGLONG; -typedef unsigned __int64 ULONGLONG; +typedef int64_t LONGLONG; +typedef uint64_t ULONGLONG; typedef ULONGLONG DWORD64; typedef DWORD64 *PDWORD64; typedef LONGLONG *PLONG64; @@ -271,286 +194,52 @@ typedef unsigned int *PUINT; typedef BYTE BOOLEAN; typedef BOOLEAN *PBOOLEAN; -typedef unsigned __int8 UINT8; -typedef signed __int8 INT8; -typedef unsigned __int16 UINT16; -typedef signed __int16 INT16; -typedef unsigned __int32 UINT32, *PUINT32; -typedef signed __int32 INT32, *PINT32; -typedef unsigned __int64 UINT64, *PUINT64; -typedef signed __int64 INT64, *PINT64; - -typedef unsigned __int32 ULONG32, *PULONG32; -typedef signed __int32 LONG32, *PLONG32; -typedef unsigned __int64 ULONG64; -typedef signed __int64 LONG64; - -#if defined(HOST_X86) && _MSC_VER >= 1300 -#define _W64 __w64 -#else -#define _W64 -#endif - -#ifdef HOST_64BIT - -#define _atoi64 (__int64)atoll - -typedef __int64 INT_PTR, *PINT_PTR; -typedef unsigned __int64 UINT_PTR, *PUINT_PTR; -typedef __int64 LONG_PTR, *PLONG_PTR; -typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; -typedef unsigned __int64 DWORD_PTR, *PDWORD_PTR; - -/* maximum signed 64 bit value */ -#define LONG_PTR_MAX I64(9223372036854775807) -/* maximum unsigned 64 bit value */ -#define ULONG_PTR_MAX UI64(0xffffffffffffffff) - -#ifndef SIZE_MAX -#define SIZE_MAX _UI64_MAX -#endif - -#define __int3264 __int64 - -#if !defined(HOST_64BIT) -__inline -unsigned long -HandleToULong( - const void *h - ) -{ - return((unsigned long) (ULONG_PTR) h ); -} - -__inline -long -HandleToLong( - const void *h - ) -{ - return((long) (LONG_PTR) h ); -} - -__inline -void * -ULongToHandle( - const unsigned long h - ) -{ - return((void *) (UINT_PTR) h ); -} - +typedef uint8_t UINT8; +typedef int8_t INT8; +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef uint32_t UINT32, *PUINT32; +typedef int32_t INT32, *PINT32; +typedef uint64_t UINT64, *PUINT64; +typedef int64_t INT64, *PINT64; -__inline -void * -LongToHandle( - const long h - ) -{ - return((void *) (INT_PTR) h ); -} +typedef uint32_t ULONG32, *PULONG32; +typedef int32_t LONG32, *PLONG32; +typedef uint64_t ULONG64; +typedef int64_t LONG64; +typedef intptr_t INT_PTR, *PINT_PTR; +typedef uintptr_t UINT_PTR, *PUINT_PTR; -__inline -unsigned long -PtrToUlong( - const void *p - ) -{ - return((unsigned long) (ULONG_PTR) p ); -} - -__inline -unsigned int -PtrToUint( - const void *p - ) -{ - return((unsigned int) (UINT_PTR) p ); -} - -__inline -unsigned short -PtrToUshort( - const void *p - ) -{ - return((unsigned short) (unsigned long) (ULONG_PTR) p ); -} - -__inline -long -PtrToLong( - const void *p - ) -{ - return((long) (LONG_PTR) p ); -} - -__inline -int -PtrToInt( - const void *p - ) -{ - return((int) (INT_PTR) p ); -} - -__inline -short -PtrToShort( - const void *p - ) -{ - return((short) (long) (LONG_PTR) p ); -} - -__inline -void * -IntToPtr( - const int i - ) -// Caution: IntToPtr() sign-extends the int value. -{ - return( (void *)(INT_PTR)i ); -} - -__inline -void * -UIntToPtr( - const unsigned int ui - ) -// Caution: UIntToPtr() zero-extends the unsigned int value. -{ - return( (void *)(UINT_PTR)ui ); -} - -__inline -void * -LongToPtr( - const long l - ) -// Caution: LongToPtr() sign-extends the long value. -{ - return( (void *)(LONG_PTR)l ); -} - -__inline -void * -ULongToPtr( - const unsigned long ul - ) -// Caution: ULongToPtr() zero-extends the unsigned long value. -{ - return( (void *)(ULONG_PTR)ul ); -} - -__inline -void * -ShortToPtr( - const short s - ) -// Caution: ShortToPtr() sign-extends the short value. -{ - return( (void *)(INT_PTR)s ); -} - -__inline -void * -UShortToPtr( - const unsigned short us - ) -// Caution: UShortToPtr() zero-extends the unsigned short value. -{ - return( (void *)(UINT_PTR)us ); -} - -#else // !defined(HOST_64BIT) -#define HandleToULong( h ) ((ULONG)(ULONG_PTR)(h) ) -#define HandleToLong( h ) ((LONG)(LONG_PTR) (h) ) -#define ULongToHandle( ul ) ((HANDLE)(ULONG_PTR) (ul) ) -#define LongToHandle( h ) ((HANDLE)(LONG_PTR) (h) ) -#define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) ) -#define PtrToLong( p ) ((LONG)(LONG_PTR) (p) ) -#define PtrToUint( p ) ((UINT)(UINT_PTR) (p) ) -#define PtrToInt( p ) ((INT)(INT_PTR) (p) ) -#define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) ) -#define PtrToShort( p ) ((short)(LONG_PTR)(p) ) -#define IntToPtr( i ) ((VOID *)(INT_PTR)((int)(i))) -#define UIntToPtr( ui ) ((VOID *)(UINT_PTR)((unsigned int)(ui))) -#define LongToPtr( l ) ((VOID *)(LONG_PTR)((long)(l))) -#define ULongToPtr( ul ) ((VOID *)(ULONG_PTR)((unsigned long)(ul))) -#define ShortToPtr( s ) ((VOID *)(INT_PTR)((short)(s))) -#define UShortToPtr( us ) ((VOID *)(UINT_PTR)((unsigned short)(s))) -#endif // !defined(HOST_64BIT) +#ifdef HOST_64BIT +#define _atoi64 (int64_t)atoll +typedef int64_t LONG_PTR, *PLONG_PTR; +typedef uint64_t ULONG_PTR, *PULONG_PTR; +typedef uint64_t DWORD_PTR, *PDWORD_PTR; #else -typedef _W64 __int32 INT_PTR; -typedef _W64 unsigned __int32 UINT_PTR; +typedef int32_t LONG_PTR, *PLONG_PTR; +typedef uint32_t ULONG_PTR, *PULONG_PTR; +typedef uint32_t DWORD_PTR, *PDWORD_PTR; -typedef _W64 __int32 LONG_PTR; -typedef _W64 unsigned __int32 ULONG_PTR, *PULONG_PTR; -typedef _W64 unsigned __int32 DWORD_PTR, *PDWORD_PTR; - -/* maximum signed 32 bit value */ -#define LONG_PTR_MAX 2147483647L -/* maximum unsigned 32 bit value */ -#define ULONG_PTR_MAX 0xffffffffUL - -#ifndef SIZE_MAX -#define SIZE_MAX UINT_MAX -#endif - -#define __int3264 __int32 - -#define HandleToULong( h ) ((ULONG)(ULONG_PTR)(h) ) -#define HandleToLong( h ) ((LONG)(LONG_PTR) (h) ) -#define ULongToHandle( ul ) ((HANDLE)(ULONG_PTR) (ul) ) -#define LongToHandle( h ) ((HANDLE)(LONG_PTR) (h) ) -#define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) ) -#define PtrToLong( p ) ((LONG)(LONG_PTR) (p) ) -#define PtrToUint( p ) ((UINT)(UINT_PTR) (p) ) -#define PtrToInt( p ) ((INT)(INT_PTR) (p) ) -#define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) ) -#define PtrToShort( p ) ((short)(LONG_PTR)(p) ) -#define IntToPtr( i ) ((VOID *)(INT_PTR)((int)i)) -#define UIntToPtr( ui ) ((VOID *)(UINT_PTR)((unsigned int)ui)) -#define LongToPtr( l ) ((VOID *)(LONG_PTR)((long)l)) -#define ULongToPtr( ul ) ((VOID *)(ULONG_PTR)((unsigned long)ul)) -#define ShortToPtr( s ) ((VOID *)(INT_PTR)((short)s)) -#define UShortToPtr( us ) ((VOID *)(UINT_PTR)((unsigned short)s)) - -#endif - -#define HandleToUlong(h) HandleToULong(h) -#define UlongToHandle(ul) ULongToHandle(ul) -#define UlongToPtr(ul) ULongToPtr(ul) -#define UintToPtr(ui) UIntToPtr(ui) - -#ifdef HOST_64BIT -typedef unsigned long SIZE_T; -typedef long SSIZE_T; -#else -typedef unsigned int SIZE_T; -typedef int SSIZE_T; #endif -static_assert(sizeof(SIZE_T) == sizeof(void*), "SIZE_T should be pointer sized"); -static_assert(sizeof(SSIZE_T) == sizeof(void*), "SSIZE_T should be pointer sized"); +typedef uintptr_t SIZE_T; +typedef intptr_t SSIZE_T; #ifndef SIZE_T_MAX -#define SIZE_T_MAX ULONG_PTR_MAX +#define SIZE_T_MAX UINTPTR_MAX #endif // SIZE_T_MAX #ifndef SSIZE_T_MAX -#define SSIZE_T_MAX LONG_PTR_MAX +#define SSIZE_T_MAX INTPTR_MAX #endif #ifndef SSIZE_T_MIN -#define SSIZE_T_MIN (ssize_t)I64(0x8000000000000000) +#define SSIZE_T_MIN INTPTR_MIN #endif typedef LONG_PTR LPARAM; diff --git a/src/coreclr/pal/prebuilt/corerror/mscorurt.rc b/src/coreclr/pal/prebuilt/corerror/mscorurt.rc index 67c5f9d48fec..df0e680abdd4 100644 --- a/src/coreclr/pal/prebuilt/corerror/mscorurt.rc +++ b/src/coreclr/pal/prebuilt/corerror/mscorurt.rc @@ -14,7 +14,6 @@ BEGIN MSG_FOR_URT_HR(HOST_E_INVALIDOPERATION) "Invalid operation." MSG_FOR_URT_HR(HOST_E_CLRNOTAVAILABLE) "CLR has been disabled due to unrecoverable error." MSG_FOR_URT_HR(FUSION_E_REF_DEF_MISMATCH) "The located assembly's manifest definition does not match the assembly reference." - MSG_FOR_URT_HR(FUSION_E_PRIVATE_ASM_DISALLOWED) "A strongly-named assembly is required." MSG_FOR_URT_HR(FUSION_E_INVALID_NAME) "The given assembly name was invalid." MSG_FOR_URT_HR(FUSION_E_APP_DOMAIN_LOCKED) "The requested assembly version conflicts with what is already bound in the app domain or specified in the manifest." MSG_FOR_URT_HR(COR_E_LOADING_REFERENCE_ASSEMBLY) "Reference assemblies cannot be loaded for execution." diff --git a/src/coreclr/pal/prebuilt/idl/cordebug_i.cpp b/src/coreclr/pal/prebuilt/idl/cordebug_i.cpp index 6bfe487fd5ff..811cd6512fa0 100644 --- a/src/coreclr/pal/prebuilt/idl/cordebug_i.cpp +++ b/src/coreclr/pal/prebuilt/idl/cordebug_i.cpp @@ -474,6 +474,9 @@ MIDL_DEFINE_GUID(IID, IID_ICorDebugExceptionObjectCallStackEnum,0xED775530,0x4DC MIDL_DEFINE_GUID(IID, IID_ICorDebugExceptionObjectValue,0xAE4CA65D,0x59DD,0x42A2,0x83,0xA5,0x57,0xE8,0xA0,0x8D,0x87,0x19); +MIDL_DEFINE_GUID(IID, IID_ICorDebugExceptionObjectValue2,0xe3b2f332,0xcc46,0x4f1e,0xab,0x4e,0x54,0x00,0xe3,0x32,0x19,0x5e); + + MIDL_DEFINE_GUID(IID, LIBID_CORDBLib,0x53D13620,0xF417,0x11d1,0x97,0x62,0xA6,0x38,0x26,0xA4,0xF2,0x55); diff --git a/src/coreclr/pal/prebuilt/inc/cordebug.h b/src/coreclr/pal/prebuilt/inc/cordebug.h index 6d74b1a412f8..78b86c69ee96 100644 --- a/src/coreclr/pal/prebuilt/inc/cordebug.h +++ b/src/coreclr/pal/prebuilt/inc/cordebug.h @@ -5,10 +5,10 @@ /* File created by MIDL compiler version 8.01.0628 */ /* Compiler settings for cordebug.idl: - Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0628 + Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0628 protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() */ @@ -49,7 +49,7 @@ #endif #endif -/* Forward Declarations */ +/* Forward Declarations */ #ifndef __ICorDebugDataTarget_FWD_DEFINED__ #define __ICorDebugDataTarget_FWD_DEFINED__ @@ -1003,6 +1003,13 @@ typedef interface ICorDebugExceptionObjectValue ICorDebugExceptionObjectValue; #endif /* __ICorDebugExceptionObjectValue_FWD_DEFINED__ */ +#ifndef __ICorDebugExceptionObjectValue2_FWD_DEFINED__ +#define __ICorDebugExceptionObjectValue2_FWD_DEFINED__ +typedef interface ICorDebugExceptionObjectValue2 ICorDebugExceptionObjectValue2; + +#endif /* __ICorDebugExceptionObjectValue2_FWD_DEFINED__ */ + + #ifndef __CorDebug_FWD_DEFINED__ #define __CorDebug_FWD_DEFINED__ @@ -1264,11 +1271,11 @@ typedef interface ICorDebugModule3 ICorDebugModule3; #ifdef __cplusplus extern "C"{ -#endif +#endif /* interface __MIDL_itf_cordebug_0000_0000 */ -/* [local] */ +/* [local] */ #if 0 typedef UINT32 mdToken; @@ -1322,7 +1329,7 @@ typedef struct _COR_IL_MAP #endif //_COR_IL_MAP #ifndef _COR_DEBUG_IL_TO_NATIVE_MAP_ #define _COR_DEBUG_IL_TO_NATIVE_MAP_ -typedef +typedef enum CorDebugIlToNativeMappingTypes { NO_MAPPING = -1, @@ -1339,7 +1346,7 @@ typedef struct COR_DEBUG_IL_TO_NATIVE_MAP #endif // _COR_DEBUG_IL_TO_NATIVE_MAP_ #define REMOTE_DEBUGGING_DLL_ENTRY L"Software\\Microsoft\\.NETFramework\\Debugger\\ActivateRemoteDebugging" -typedef +typedef enum CorDebugJITCompilerFlags { CORDEBUG_JIT_DEFAULT = 0x1, @@ -1347,20 +1354,20 @@ enum CorDebugJITCompilerFlags CORDEBUG_JIT_ENABLE_ENC = 0x7 } CorDebugJITCompilerFlags; -typedef +typedef enum CorDebugJITCompilerFlagsDecprecated { CORDEBUG_JIT_TRACK_DEBUG_INFO = 0x1 } CorDebugJITCompilerFlagsDeprecated; -typedef +typedef enum CorDebugNGENPolicy { DISABLE_LOCAL_NIC = 1 } CorDebugNGENPolicy; #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) @@ -1435,7 +1442,7 @@ typedef ULONG64 CORDB_REGISTER; typedef DWORD CORDB_CONTINUE_STATUS; -typedef +typedef enum CorDebugBlockingReason { BLOCKING_NONE = 0, @@ -1473,9 +1480,9 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0000_v0_0_s_ifspec; #define __ICorDebugDataTarget_INTERFACE_DEFINED__ /* interface ICorDebugDataTarget */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugPlatform { CORDB_PLATFORM_WINDOWS_X86 = 0, @@ -1491,78 +1498,78 @@ enum CorDebugPlatform CORDB_PLATFORM_POSIX_ARM = ( CORDB_PLATFORM_POSIX_X86 + 1 ) , CORDB_PLATFORM_POSIX_ARM64 = ( CORDB_PLATFORM_POSIX_ARM + 1 ) , CORDB_PLATFORM_POSIX_LOONGARCH64 = ( CORDB_PLATFORM_POSIX_ARM64 + 1 ) , - CORDB_PLATFORM_POSIX_RISCV64 = ( CORDB_PLATFORM_POSIX_LOONGARCH64 + 1 ) + CORDB_PLATFORM_POSIX_RISCV64 = ( CORDB_PLATFORM_POSIX_LOONGARCH64 + 1 ) } CorDebugPlatform; EXTERN_C const IID IID_ICorDebugDataTarget; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("FE06DC28-49FB-4636-A4A3-E80DB4AE116C") ICorDebugDataTarget : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetPlatform( + virtual HRESULT STDMETHODCALLTYPE GetPlatform( /* [out] */ CorDebugPlatform *pTargetPlatform) = 0; - - virtual HRESULT STDMETHODCALLTYPE ReadVirtual( + + virtual HRESULT STDMETHODCALLTYPE ReadVirtual( /* [in] */ CORDB_ADDRESS address, /* [length_is][size_is][out] */ BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *pBytesRead) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetThreadContext( + + virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE *pContext) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugDataTargetVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDataTarget * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDataTarget * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDataTarget * This); - + DECLSPEC_XFGVIRT(ICorDebugDataTarget, GetPlatform) - HRESULT ( STDMETHODCALLTYPE *GetPlatform )( + HRESULT ( STDMETHODCALLTYPE *GetPlatform )( ICorDebugDataTarget * This, /* [out] */ CorDebugPlatform *pTargetPlatform); - + DECLSPEC_XFGVIRT(ICorDebugDataTarget, ReadVirtual) - HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( + HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( ICorDebugDataTarget * This, /* [in] */ CORDB_ADDRESS address, /* [length_is][size_is][out] */ BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *pBytesRead); - + DECLSPEC_XFGVIRT(ICorDebugDataTarget, GetThreadContext) - HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorDebugDataTarget * This, /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE *pContext); - + END_INTERFACE } ICorDebugDataTargetVtbl; @@ -1571,29 +1578,29 @@ EXTERN_C const IID IID_ICorDebugDataTarget; CONST_VTBL struct ICorDebugDataTargetVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugDataTarget_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDataTarget_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDataTarget_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDataTarget_GetPlatform(This,pTargetPlatform) \ - ( (This)->lpVtbl -> GetPlatform(This,pTargetPlatform) ) + ( (This)->lpVtbl -> GetPlatform(This,pTargetPlatform) ) #define ICorDebugDataTarget_ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) \ - ( (This)->lpVtbl -> ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) ) + ( (This)->lpVtbl -> ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) ) #define ICorDebugDataTarget_GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) \ - ( (This)->lpVtbl -> GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) ) + ( (This)->lpVtbl -> GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) ) #endif /* COBJMACROS */ @@ -1610,69 +1617,69 @@ EXTERN_C const IID IID_ICorDebugDataTarget; #define __ICorDebugStaticFieldSymbol_INTERFACE_DEFINED__ /* interface ICorDebugStaticFieldSymbol */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugStaticFieldSymbol; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CBF9DA63-F68D-4BBB-A21C-15A45EAADF5B") ICorDebugStaticFieldSymbol : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetName( + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcbSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAddress( + + virtual HRESULT STDMETHODCALLTYPE GetAddress( /* [out] */ CORDB_ADDRESS *pRVA) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugStaticFieldSymbolVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStaticFieldSymbol * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStaticFieldSymbol * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStaticFieldSymbol * This); - + DECLSPEC_XFGVIRT(ICorDebugStaticFieldSymbol, GetName) - HRESULT ( STDMETHODCALLTYPE *GetName )( + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugStaticFieldSymbol * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - + DECLSPEC_XFGVIRT(ICorDebugStaticFieldSymbol, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugStaticFieldSymbol * This, /* [out] */ ULONG32 *pcbSize); - + DECLSPEC_XFGVIRT(ICorDebugStaticFieldSymbol, GetAddress) - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugStaticFieldSymbol * This, /* [out] */ CORDB_ADDRESS *pRVA); - + END_INTERFACE } ICorDebugStaticFieldSymbolVtbl; @@ -1681,29 +1688,29 @@ EXTERN_C const IID IID_ICorDebugStaticFieldSymbol; CONST_VTBL struct ICorDebugStaticFieldSymbolVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugStaticFieldSymbol_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStaticFieldSymbol_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStaticFieldSymbol_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStaticFieldSymbol_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugStaticFieldSymbol_GetSize(This,pcbSize) \ - ( (This)->lpVtbl -> GetSize(This,pcbSize) ) + ( (This)->lpVtbl -> GetSize(This,pcbSize) ) #define ICorDebugStaticFieldSymbol_GetAddress(This,pRVA) \ - ( (This)->lpVtbl -> GetAddress(This,pRVA) ) + ( (This)->lpVtbl -> GetAddress(This,pRVA) ) #endif /* COBJMACROS */ @@ -1720,69 +1727,69 @@ EXTERN_C const IID IID_ICorDebugStaticFieldSymbol; #define __ICorDebugInstanceFieldSymbol_INTERFACE_DEFINED__ /* interface ICorDebugInstanceFieldSymbol */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugInstanceFieldSymbol; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("A074096B-3ADC-4485-81DA-68C7A4EA52DB") ICorDebugInstanceFieldSymbol : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetName( + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcbSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetOffset( + + virtual HRESULT STDMETHODCALLTYPE GetOffset( /* [out] */ ULONG32 *pcbOffset) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugInstanceFieldSymbolVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugInstanceFieldSymbol * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugInstanceFieldSymbol * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugInstanceFieldSymbol * This); - + DECLSPEC_XFGVIRT(ICorDebugInstanceFieldSymbol, GetName) - HRESULT ( STDMETHODCALLTYPE *GetName )( + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugInstanceFieldSymbol * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - + DECLSPEC_XFGVIRT(ICorDebugInstanceFieldSymbol, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugInstanceFieldSymbol * This, /* [out] */ ULONG32 *pcbSize); - + DECLSPEC_XFGVIRT(ICorDebugInstanceFieldSymbol, GetOffset) - HRESULT ( STDMETHODCALLTYPE *GetOffset )( + HRESULT ( STDMETHODCALLTYPE *GetOffset )( ICorDebugInstanceFieldSymbol * This, /* [out] */ ULONG32 *pcbOffset); - + END_INTERFACE } ICorDebugInstanceFieldSymbolVtbl; @@ -1791,29 +1798,29 @@ EXTERN_C const IID IID_ICorDebugInstanceFieldSymbol; CONST_VTBL struct ICorDebugInstanceFieldSymbolVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugInstanceFieldSymbol_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugInstanceFieldSymbol_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugInstanceFieldSymbol_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugInstanceFieldSymbol_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugInstanceFieldSymbol_GetSize(This,pcbSize) \ - ( (This)->lpVtbl -> GetSize(This,pcbSize) ) + ( (This)->lpVtbl -> GetSize(This,pcbSize) ) #define ICorDebugInstanceFieldSymbol_GetOffset(This,pcbOffset) \ - ( (This)->lpVtbl -> GetOffset(This,pcbOffset) ) + ( (This)->lpVtbl -> GetOffset(This,pcbOffset) ) #endif /* COBJMACROS */ @@ -1830,82 +1837,82 @@ EXTERN_C const IID IID_ICorDebugInstanceFieldSymbol; #define __ICorDebugVariableSymbol_INTERFACE_DEFINED__ /* interface ICorDebugVariableSymbol */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugVariableSymbol; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("707E8932-1163-48D9-8A93-F5B1F480FBB7") ICorDebugVariableSymbol : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetName( + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcbValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetValue( + + virtual HRESULT STDMETHODCALLTYPE GetValue( /* [in] */ ULONG32 offset, /* [in] */ ULONG32 cbContext, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 cbValue, /* [out] */ ULONG32 *pcbValue, /* [length_is][size_is][out] */ BYTE pValue[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetValue( + + virtual HRESULT STDMETHODCALLTYPE SetValue( /* [in] */ ULONG32 offset, /* [in] */ DWORD threadID, /* [in] */ ULONG32 cbContext, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 cbValue, /* [size_is][in] */ BYTE pValue[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSlotIndex( + + virtual HRESULT STDMETHODCALLTYPE GetSlotIndex( /* [out] */ ULONG32 *pSlotIndex) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugVariableSymbolVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugVariableSymbol * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugVariableSymbol * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugVariableSymbol * This); - + DECLSPEC_XFGVIRT(ICorDebugVariableSymbol, GetName) - HRESULT ( STDMETHODCALLTYPE *GetName )( + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugVariableSymbol * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - + DECLSPEC_XFGVIRT(ICorDebugVariableSymbol, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugVariableSymbol * This, /* [out] */ ULONG32 *pcbValue); - + DECLSPEC_XFGVIRT(ICorDebugVariableSymbol, GetValue) - HRESULT ( STDMETHODCALLTYPE *GetValue )( + HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugVariableSymbol * This, /* [in] */ ULONG32 offset, /* [in] */ ULONG32 cbContext, @@ -1913,9 +1920,9 @@ EXTERN_C const IID IID_ICorDebugVariableSymbol; /* [in] */ ULONG32 cbValue, /* [out] */ ULONG32 *pcbValue, /* [length_is][size_is][out] */ BYTE pValue[ ]); - + DECLSPEC_XFGVIRT(ICorDebugVariableSymbol, SetValue) - HRESULT ( STDMETHODCALLTYPE *SetValue )( + HRESULT ( STDMETHODCALLTYPE *SetValue )( ICorDebugVariableSymbol * This, /* [in] */ ULONG32 offset, /* [in] */ DWORD threadID, @@ -1923,12 +1930,12 @@ EXTERN_C const IID IID_ICorDebugVariableSymbol; /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 cbValue, /* [size_is][in] */ BYTE pValue[ ]); - + DECLSPEC_XFGVIRT(ICorDebugVariableSymbol, GetSlotIndex) - HRESULT ( STDMETHODCALLTYPE *GetSlotIndex )( + HRESULT ( STDMETHODCALLTYPE *GetSlotIndex )( ICorDebugVariableSymbol * This, /* [out] */ ULONG32 *pSlotIndex); - + END_INTERFACE } ICorDebugVariableSymbolVtbl; @@ -1937,35 +1944,35 @@ EXTERN_C const IID IID_ICorDebugVariableSymbol; CONST_VTBL struct ICorDebugVariableSymbolVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugVariableSymbol_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugVariableSymbol_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugVariableSymbol_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugVariableSymbol_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugVariableSymbol_GetSize(This,pcbValue) \ - ( (This)->lpVtbl -> GetSize(This,pcbValue) ) + ( (This)->lpVtbl -> GetSize(This,pcbValue) ) #define ICorDebugVariableSymbol_GetValue(This,offset,cbContext,context,cbValue,pcbValue,pValue) \ - ( (This)->lpVtbl -> GetValue(This,offset,cbContext,context,cbValue,pcbValue,pValue) ) + ( (This)->lpVtbl -> GetValue(This,offset,cbContext,context,cbValue,pcbValue,pValue) ) #define ICorDebugVariableSymbol_SetValue(This,offset,threadID,cbContext,context,cbValue,pValue) \ - ( (This)->lpVtbl -> SetValue(This,offset,threadID,cbContext,context,cbValue,pValue) ) + ( (This)->lpVtbl -> SetValue(This,offset,threadID,cbContext,context,cbValue,pValue) ) #define ICorDebugVariableSymbol_GetSlotIndex(This,pSlotIndex) \ - ( (This)->lpVtbl -> GetSlotIndex(This,pSlotIndex) ) + ( (This)->lpVtbl -> GetSlotIndex(This,pSlotIndex) ) #endif /* COBJMACROS */ @@ -1982,57 +1989,57 @@ EXTERN_C const IID IID_ICorDebugVariableSymbol; #define __ICorDebugMemoryBuffer_INTERFACE_DEFINED__ /* interface ICorDebugMemoryBuffer */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugMemoryBuffer; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("677888B3-D160-4B8C-A73B-D79E6AAA1D13") ICorDebugMemoryBuffer : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetStartAddress( + virtual HRESULT STDMETHODCALLTYPE GetStartAddress( /* [out] */ LPCVOID *address) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcbBufferLength) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugMemoryBufferVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMemoryBuffer * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMemoryBuffer * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMemoryBuffer * This); - + DECLSPEC_XFGVIRT(ICorDebugMemoryBuffer, GetStartAddress) - HRESULT ( STDMETHODCALLTYPE *GetStartAddress )( + HRESULT ( STDMETHODCALLTYPE *GetStartAddress )( ICorDebugMemoryBuffer * This, /* [out] */ LPCVOID *address); - + DECLSPEC_XFGVIRT(ICorDebugMemoryBuffer, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugMemoryBuffer * This, /* [out] */ ULONG32 *pcbBufferLength); - + END_INTERFACE } ICorDebugMemoryBufferVtbl; @@ -2041,26 +2048,26 @@ EXTERN_C const IID IID_ICorDebugMemoryBuffer; CONST_VTBL struct ICorDebugMemoryBufferVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugMemoryBuffer_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMemoryBuffer_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMemoryBuffer_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMemoryBuffer_GetStartAddress(This,address) \ - ( (This)->lpVtbl -> GetStartAddress(This,address) ) + ( (This)->lpVtbl -> GetStartAddress(This,address) ) #define ICorDebugMemoryBuffer_GetSize(This,pcbBufferLength) \ - ( (This)->lpVtbl -> GetSize(This,pcbBufferLength) ) + ( (This)->lpVtbl -> GetSize(This,pcbBufferLength) ) #endif /* COBJMACROS */ @@ -2077,111 +2084,111 @@ EXTERN_C const IID IID_ICorDebugMemoryBuffer; #define __ICorDebugMergedAssemblyRecord_INTERFACE_DEFINED__ /* interface ICorDebugMergedAssemblyRecord */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugMergedAssemblyRecord; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("FAA8637B-3BBE-4671-8E26-3B59875B922A") ICorDebugMergedAssemblyRecord : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetSimpleName( + virtual HRESULT STDMETHODCALLTYPE GetSimpleName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetVersion( + + virtual HRESULT STDMETHODCALLTYPE GetVersion( /* [out] */ USHORT *pMajor, /* [out] */ USHORT *pMinor, /* [out] */ USHORT *pBuild, /* [out] */ USHORT *pRevision) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCulture( + + virtual HRESULT STDMETHODCALLTYPE GetCulture( /* [in] */ ULONG32 cchCulture, /* [out] */ ULONG32 *pcchCulture, /* [length_is][size_is][out] */ WCHAR szCulture[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetPublicKey( + + virtual HRESULT STDMETHODCALLTYPE GetPublicKey( /* [in] */ ULONG32 cbPublicKey, /* [out] */ ULONG32 *pcbPublicKey, /* [length_is][size_is][out] */ BYTE pbPublicKey[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetPublicKeyToken( + + virtual HRESULT STDMETHODCALLTYPE GetPublicKeyToken( /* [in] */ ULONG32 cbPublicKeyToken, /* [out] */ ULONG32 *pcbPublicKeyToken, /* [length_is][size_is][out] */ BYTE pbPublicKeyToken[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetIndex( + + virtual HRESULT STDMETHODCALLTYPE GetIndex( /* [out] */ ULONG32 *pIndex) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugMergedAssemblyRecordVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMergedAssemblyRecord * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMergedAssemblyRecord * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMergedAssemblyRecord * This); - + DECLSPEC_XFGVIRT(ICorDebugMergedAssemblyRecord, GetSimpleName) - HRESULT ( STDMETHODCALLTYPE *GetSimpleName )( + HRESULT ( STDMETHODCALLTYPE *GetSimpleName )( ICorDebugMergedAssemblyRecord * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - + DECLSPEC_XFGVIRT(ICorDebugMergedAssemblyRecord, GetVersion) - HRESULT ( STDMETHODCALLTYPE *GetVersion )( + HRESULT ( STDMETHODCALLTYPE *GetVersion )( ICorDebugMergedAssemblyRecord * This, /* [out] */ USHORT *pMajor, /* [out] */ USHORT *pMinor, /* [out] */ USHORT *pBuild, /* [out] */ USHORT *pRevision); - + DECLSPEC_XFGVIRT(ICorDebugMergedAssemblyRecord, GetCulture) - HRESULT ( STDMETHODCALLTYPE *GetCulture )( + HRESULT ( STDMETHODCALLTYPE *GetCulture )( ICorDebugMergedAssemblyRecord * This, /* [in] */ ULONG32 cchCulture, /* [out] */ ULONG32 *pcchCulture, /* [length_is][size_is][out] */ WCHAR szCulture[ ]); - + DECLSPEC_XFGVIRT(ICorDebugMergedAssemblyRecord, GetPublicKey) - HRESULT ( STDMETHODCALLTYPE *GetPublicKey )( + HRESULT ( STDMETHODCALLTYPE *GetPublicKey )( ICorDebugMergedAssemblyRecord * This, /* [in] */ ULONG32 cbPublicKey, /* [out] */ ULONG32 *pcbPublicKey, /* [length_is][size_is][out] */ BYTE pbPublicKey[ ]); - + DECLSPEC_XFGVIRT(ICorDebugMergedAssemblyRecord, GetPublicKeyToken) - HRESULT ( STDMETHODCALLTYPE *GetPublicKeyToken )( + HRESULT ( STDMETHODCALLTYPE *GetPublicKeyToken )( ICorDebugMergedAssemblyRecord * This, /* [in] */ ULONG32 cbPublicKeyToken, /* [out] */ ULONG32 *pcbPublicKeyToken, /* [length_is][size_is][out] */ BYTE pbPublicKeyToken[ ]); - + DECLSPEC_XFGVIRT(ICorDebugMergedAssemblyRecord, GetIndex) - HRESULT ( STDMETHODCALLTYPE *GetIndex )( + HRESULT ( STDMETHODCALLTYPE *GetIndex )( ICorDebugMergedAssemblyRecord * This, /* [out] */ ULONG32 *pIndex); - + END_INTERFACE } ICorDebugMergedAssemblyRecordVtbl; @@ -2190,38 +2197,38 @@ EXTERN_C const IID IID_ICorDebugMergedAssemblyRecord; CONST_VTBL struct ICorDebugMergedAssemblyRecordVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugMergedAssemblyRecord_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMergedAssemblyRecord_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMergedAssemblyRecord_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMergedAssemblyRecord_GetSimpleName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetSimpleName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetSimpleName(This,cchName,pcchName,szName) ) #define ICorDebugMergedAssemblyRecord_GetVersion(This,pMajor,pMinor,pBuild,pRevision) \ - ( (This)->lpVtbl -> GetVersion(This,pMajor,pMinor,pBuild,pRevision) ) + ( (This)->lpVtbl -> GetVersion(This,pMajor,pMinor,pBuild,pRevision) ) #define ICorDebugMergedAssemblyRecord_GetCulture(This,cchCulture,pcchCulture,szCulture) \ - ( (This)->lpVtbl -> GetCulture(This,cchCulture,pcchCulture,szCulture) ) + ( (This)->lpVtbl -> GetCulture(This,cchCulture,pcchCulture,szCulture) ) #define ICorDebugMergedAssemblyRecord_GetPublicKey(This,cbPublicKey,pcbPublicKey,pbPublicKey) \ - ( (This)->lpVtbl -> GetPublicKey(This,cbPublicKey,pcbPublicKey,pbPublicKey) ) + ( (This)->lpVtbl -> GetPublicKey(This,cbPublicKey,pcbPublicKey,pbPublicKey) ) #define ICorDebugMergedAssemblyRecord_GetPublicKeyToken(This,cbPublicKeyToken,pcbPublicKeyToken,pbPublicKeyToken) \ - ( (This)->lpVtbl -> GetPublicKeyToken(This,cbPublicKeyToken,pcbPublicKeyToken,pbPublicKeyToken) ) + ( (This)->lpVtbl -> GetPublicKeyToken(This,cbPublicKeyToken,pcbPublicKeyToken,pbPublicKeyToken) ) #define ICorDebugMergedAssemblyRecord_GetIndex(This,pIndex) \ - ( (This)->lpVtbl -> GetIndex(This,pIndex) ) + ( (This)->lpVtbl -> GetIndex(This,pIndex) ) #endif /* COBJMACROS */ @@ -2238,147 +2245,147 @@ EXTERN_C const IID IID_ICorDebugMergedAssemblyRecord; #define __ICorDebugSymbolProvider_INTERFACE_DEFINED__ /* interface ICorDebugSymbolProvider */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugSymbolProvider; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("3948A999-FD8A-4C38-A708-8A71E9B04DBB") ICorDebugSymbolProvider : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetStaticFieldSymbols( + virtual HRESULT STDMETHODCALLTYPE GetStaticFieldSymbols( /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugStaticFieldSymbol *pSymbols[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetInstanceFieldSymbols( + + virtual HRESULT STDMETHODCALLTYPE GetInstanceFieldSymbols( /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugInstanceFieldSymbol *pSymbols[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMethodLocalSymbols( + + virtual HRESULT STDMETHODCALLTYPE GetMethodLocalSymbols( /* [in] */ ULONG32 nativeRVA, /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMethodParameterSymbols( + + virtual HRESULT STDMETHODCALLTYPE GetMethodParameterSymbols( /* [in] */ ULONG32 nativeRVA, /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMergedAssemblyRecords( + + virtual HRESULT STDMETHODCALLTYPE GetMergedAssemblyRecords( /* [in] */ ULONG32 cRequestedRecords, /* [out] */ ULONG32 *pcFetchedRecords, /* [length_is][size_is][out] */ ICorDebugMergedAssemblyRecord *pRecords[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMethodProps( + + virtual HRESULT STDMETHODCALLTYPE GetMethodProps( /* [in] */ ULONG32 codeRva, /* [out] */ mdToken *pMethodToken, /* [out] */ ULONG32 *pcGenericParams, /* [in] */ ULONG32 cbSignature, /* [out] */ ULONG32 *pcbSignature, /* [length_is][size_is][out] */ BYTE signature[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetTypeProps( + + virtual HRESULT STDMETHODCALLTYPE GetTypeProps( /* [in] */ ULONG32 vtableRva, /* [in] */ ULONG32 cbSignature, /* [out] */ ULONG32 *pcbSignature, /* [length_is][size_is][out] */ BYTE signature[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCodeRange( + + virtual HRESULT STDMETHODCALLTYPE GetCodeRange( /* [in] */ ULONG32 codeRva, /* [out] */ ULONG32 *pCodeStartAddress, ULONG32 *pCodeSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAssemblyImageBytes( + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyImageBytes( /* [in] */ CORDB_ADDRESS rva, /* [in] */ ULONG32 length, /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetObjectSize( + + virtual HRESULT STDMETHODCALLTYPE GetObjectSize( /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [out] */ ULONG32 *pObjectSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAssemblyImageMetadata( + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyImageMetadata( /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugSymbolProviderVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugSymbolProvider * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugSymbolProvider * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugSymbolProvider * This); - + DECLSPEC_XFGVIRT(ICorDebugSymbolProvider, GetStaticFieldSymbols) - HRESULT ( STDMETHODCALLTYPE *GetStaticFieldSymbols )( + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldSymbols )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugStaticFieldSymbol *pSymbols[ ]); - + DECLSPEC_XFGVIRT(ICorDebugSymbolProvider, GetInstanceFieldSymbols) - HRESULT ( STDMETHODCALLTYPE *GetInstanceFieldSymbols )( + HRESULT ( STDMETHODCALLTYPE *GetInstanceFieldSymbols )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugInstanceFieldSymbol *pSymbols[ ]); - + DECLSPEC_XFGVIRT(ICorDebugSymbolProvider, GetMethodLocalSymbols) - HRESULT ( STDMETHODCALLTYPE *GetMethodLocalSymbols )( + HRESULT ( STDMETHODCALLTYPE *GetMethodLocalSymbols )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 nativeRVA, /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]); - + DECLSPEC_XFGVIRT(ICorDebugSymbolProvider, GetMethodParameterSymbols) - HRESULT ( STDMETHODCALLTYPE *GetMethodParameterSymbols )( + HRESULT ( STDMETHODCALLTYPE *GetMethodParameterSymbols )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 nativeRVA, /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]); - + DECLSPEC_XFGVIRT(ICorDebugSymbolProvider, GetMergedAssemblyRecords) - HRESULT ( STDMETHODCALLTYPE *GetMergedAssemblyRecords )( + HRESULT ( STDMETHODCALLTYPE *GetMergedAssemblyRecords )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 cRequestedRecords, /* [out] */ ULONG32 *pcFetchedRecords, /* [length_is][size_is][out] */ ICorDebugMergedAssemblyRecord *pRecords[ ]); - + DECLSPEC_XFGVIRT(ICorDebugSymbolProvider, GetMethodProps) - HRESULT ( STDMETHODCALLTYPE *GetMethodProps )( + HRESULT ( STDMETHODCALLTYPE *GetMethodProps )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 codeRva, /* [out] */ mdToken *pMethodToken, @@ -2386,41 +2393,41 @@ EXTERN_C const IID IID_ICorDebugSymbolProvider; /* [in] */ ULONG32 cbSignature, /* [out] */ ULONG32 *pcbSignature, /* [length_is][size_is][out] */ BYTE signature[ ]); - + DECLSPEC_XFGVIRT(ICorDebugSymbolProvider, GetTypeProps) - HRESULT ( STDMETHODCALLTYPE *GetTypeProps )( + HRESULT ( STDMETHODCALLTYPE *GetTypeProps )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 vtableRva, /* [in] */ ULONG32 cbSignature, /* [out] */ ULONG32 *pcbSignature, /* [length_is][size_is][out] */ BYTE signature[ ]); - + DECLSPEC_XFGVIRT(ICorDebugSymbolProvider, GetCodeRange) - HRESULT ( STDMETHODCALLTYPE *GetCodeRange )( + HRESULT ( STDMETHODCALLTYPE *GetCodeRange )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 codeRva, /* [out] */ ULONG32 *pCodeStartAddress, ULONG32 *pCodeSize); - + DECLSPEC_XFGVIRT(ICorDebugSymbolProvider, GetAssemblyImageBytes) - HRESULT ( STDMETHODCALLTYPE *GetAssemblyImageBytes )( + HRESULT ( STDMETHODCALLTYPE *GetAssemblyImageBytes )( ICorDebugSymbolProvider * This, /* [in] */ CORDB_ADDRESS rva, /* [in] */ ULONG32 length, /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer); - + DECLSPEC_XFGVIRT(ICorDebugSymbolProvider, GetObjectSize) - HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [out] */ ULONG32 *pObjectSize); - + DECLSPEC_XFGVIRT(ICorDebugSymbolProvider, GetAssemblyImageMetadata) - HRESULT ( STDMETHODCALLTYPE *GetAssemblyImageMetadata )( + HRESULT ( STDMETHODCALLTYPE *GetAssemblyImageMetadata )( ICorDebugSymbolProvider * This, /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer); - + END_INTERFACE } ICorDebugSymbolProviderVtbl; @@ -2429,53 +2436,53 @@ EXTERN_C const IID IID_ICorDebugSymbolProvider; CONST_VTBL struct ICorDebugSymbolProviderVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugSymbolProvider_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugSymbolProvider_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugSymbolProvider_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugSymbolProvider_GetStaticFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ - ( (This)->lpVtbl -> GetStaticFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) + ( (This)->lpVtbl -> GetStaticFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) #define ICorDebugSymbolProvider_GetInstanceFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ - ( (This)->lpVtbl -> GetInstanceFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) + ( (This)->lpVtbl -> GetInstanceFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) #define ICorDebugSymbolProvider_GetMethodLocalSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ - ( (This)->lpVtbl -> GetMethodLocalSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) + ( (This)->lpVtbl -> GetMethodLocalSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) #define ICorDebugSymbolProvider_GetMethodParameterSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ - ( (This)->lpVtbl -> GetMethodParameterSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) + ( (This)->lpVtbl -> GetMethodParameterSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) #define ICorDebugSymbolProvider_GetMergedAssemblyRecords(This,cRequestedRecords,pcFetchedRecords,pRecords) \ - ( (This)->lpVtbl -> GetMergedAssemblyRecords(This,cRequestedRecords,pcFetchedRecords,pRecords) ) + ( (This)->lpVtbl -> GetMergedAssemblyRecords(This,cRequestedRecords,pcFetchedRecords,pRecords) ) #define ICorDebugSymbolProvider_GetMethodProps(This,codeRva,pMethodToken,pcGenericParams,cbSignature,pcbSignature,signature) \ - ( (This)->lpVtbl -> GetMethodProps(This,codeRva,pMethodToken,pcGenericParams,cbSignature,pcbSignature,signature) ) + ( (This)->lpVtbl -> GetMethodProps(This,codeRva,pMethodToken,pcGenericParams,cbSignature,pcbSignature,signature) ) #define ICorDebugSymbolProvider_GetTypeProps(This,vtableRva,cbSignature,pcbSignature,signature) \ - ( (This)->lpVtbl -> GetTypeProps(This,vtableRva,cbSignature,pcbSignature,signature) ) + ( (This)->lpVtbl -> GetTypeProps(This,vtableRva,cbSignature,pcbSignature,signature) ) #define ICorDebugSymbolProvider_GetCodeRange(This,codeRva,pCodeStartAddress,pCodeSize) \ - ( (This)->lpVtbl -> GetCodeRange(This,codeRva,pCodeStartAddress,pCodeSize) ) + ( (This)->lpVtbl -> GetCodeRange(This,codeRva,pCodeStartAddress,pCodeSize) ) #define ICorDebugSymbolProvider_GetAssemblyImageBytes(This,rva,length,ppMemoryBuffer) \ - ( (This)->lpVtbl -> GetAssemblyImageBytes(This,rva,length,ppMemoryBuffer) ) + ( (This)->lpVtbl -> GetAssemblyImageBytes(This,rva,length,ppMemoryBuffer) ) #define ICorDebugSymbolProvider_GetObjectSize(This,cbSignature,typeSig,pObjectSize) \ - ( (This)->lpVtbl -> GetObjectSize(This,cbSignature,typeSig,pObjectSize) ) + ( (This)->lpVtbl -> GetObjectSize(This,cbSignature,typeSig,pObjectSize) ) #define ICorDebugSymbolProvider_GetAssemblyImageMetadata(This,ppMemoryBuffer) \ - ( (This)->lpVtbl -> GetAssemblyImageMetadata(This,ppMemoryBuffer) ) + ( (This)->lpVtbl -> GetAssemblyImageMetadata(This,ppMemoryBuffer) ) #endif /* COBJMACROS */ @@ -2492,61 +2499,61 @@ EXTERN_C const IID IID_ICorDebugSymbolProvider; #define __ICorDebugSymbolProvider2_INTERFACE_DEFINED__ /* interface ICorDebugSymbolProvider2 */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugSymbolProvider2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("F9801807-4764-4330-9E67-4F685094165E") ICorDebugSymbolProvider2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetGenericDictionaryInfo( + virtual HRESULT STDMETHODCALLTYPE GetGenericDictionaryInfo( /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFrameProps( + + virtual HRESULT STDMETHODCALLTYPE GetFrameProps( /* [in] */ ULONG32 codeRva, /* [out] */ ULONG32 *pCodeStartRva, /* [out] */ ULONG32 *pParentFrameStartRva) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugSymbolProvider2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugSymbolProvider2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugSymbolProvider2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugSymbolProvider2 * This); - + DECLSPEC_XFGVIRT(ICorDebugSymbolProvider2, GetGenericDictionaryInfo) - HRESULT ( STDMETHODCALLTYPE *GetGenericDictionaryInfo )( + HRESULT ( STDMETHODCALLTYPE *GetGenericDictionaryInfo )( ICorDebugSymbolProvider2 * This, /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer); - + DECLSPEC_XFGVIRT(ICorDebugSymbolProvider2, GetFrameProps) - HRESULT ( STDMETHODCALLTYPE *GetFrameProps )( + HRESULT ( STDMETHODCALLTYPE *GetFrameProps )( ICorDebugSymbolProvider2 * This, /* [in] */ ULONG32 codeRva, /* [out] */ ULONG32 *pCodeStartRva, /* [out] */ ULONG32 *pParentFrameStartRva); - + END_INTERFACE } ICorDebugSymbolProvider2Vtbl; @@ -2555,26 +2562,26 @@ EXTERN_C const IID IID_ICorDebugSymbolProvider2; CONST_VTBL struct ICorDebugSymbolProvider2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugSymbolProvider2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugSymbolProvider2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugSymbolProvider2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugSymbolProvider2_GetGenericDictionaryInfo(This,ppMemoryBuffer) \ - ( (This)->lpVtbl -> GetGenericDictionaryInfo(This,ppMemoryBuffer) ) + ( (This)->lpVtbl -> GetGenericDictionaryInfo(This,ppMemoryBuffer) ) #define ICorDebugSymbolProvider2_GetFrameProps(This,codeRva,pCodeStartRva,pParentFrameStartRva) \ - ( (This)->lpVtbl -> GetFrameProps(This,codeRva,pCodeStartRva,pParentFrameStartRva) ) + ( (This)->lpVtbl -> GetFrameProps(This,codeRva,pCodeStartRva,pParentFrameStartRva) ) #endif /* COBJMACROS */ @@ -2591,61 +2598,61 @@ EXTERN_C const IID IID_ICorDebugSymbolProvider2; #define __ICorDebugVirtualUnwinder_INTERFACE_DEFINED__ /* interface ICorDebugVirtualUnwinder */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugVirtualUnwinder; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("F69126B7-C787-4F6B-AE96-A569786FC670") ICorDebugVirtualUnwinder : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetContext( + virtual HRESULT STDMETHODCALLTYPE GetContext( /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 cbContextBuf, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]) = 0; - + virtual HRESULT STDMETHODCALLTYPE Next( void) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugVirtualUnwinderVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugVirtualUnwinder * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugVirtualUnwinder * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugVirtualUnwinder * This); - + DECLSPEC_XFGVIRT(ICorDebugVirtualUnwinder, GetContext) - HRESULT ( STDMETHODCALLTYPE *GetContext )( + HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugVirtualUnwinder * This, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 cbContextBuf, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]); - + DECLSPEC_XFGVIRT(ICorDebugVirtualUnwinder, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugVirtualUnwinder * This); - + END_INTERFACE } ICorDebugVirtualUnwinderVtbl; @@ -2654,26 +2661,26 @@ EXTERN_C const IID IID_ICorDebugVirtualUnwinder; CONST_VTBL struct ICorDebugVirtualUnwinderVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugVirtualUnwinder_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugVirtualUnwinder_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugVirtualUnwinder_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugVirtualUnwinder_GetContext(This,contextFlags,cbContextBuf,contextSize,contextBuf) \ - ( (This)->lpVtbl -> GetContext(This,contextFlags,cbContextBuf,contextSize,contextBuf) ) + ( (This)->lpVtbl -> GetContext(This,contextFlags,cbContextBuf,contextSize,contextBuf) ) #define ICorDebugVirtualUnwinder_Next(This) \ - ( (This)->lpVtbl -> Next(This) ) + ( (This)->lpVtbl -> Next(This) ) #endif /* COBJMACROS */ @@ -2690,105 +2697,105 @@ EXTERN_C const IID IID_ICorDebugVirtualUnwinder; #define __ICorDebugDataTarget2_INTERFACE_DEFINED__ /* interface ICorDebugDataTarget2 */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugDataTarget2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("2eb364da-605b-4e8d-b333-3394c4828d41") ICorDebugDataTarget2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetImageFromPointer( + virtual HRESULT STDMETHODCALLTYPE GetImageFromPointer( /* [in] */ CORDB_ADDRESS addr, /* [out] */ CORDB_ADDRESS *pImageBase, /* [out] */ ULONG32 *pSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetImageLocation( + + virtual HRESULT STDMETHODCALLTYPE GetImageLocation( /* [in] */ CORDB_ADDRESS baseAddress, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSymbolProviderForImage( + + virtual HRESULT STDMETHODCALLTYPE GetSymbolProviderForImage( /* [in] */ CORDB_ADDRESS imageBaseAddress, /* [out] */ ICorDebugSymbolProvider **ppSymProvider) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateThreadIDs( + + virtual HRESULT STDMETHODCALLTYPE EnumerateThreadIDs( /* [in] */ ULONG32 cThreadIds, /* [out] */ ULONG32 *pcThreadIds, /* [length_is][size_is][out] */ ULONG32 pThreadIds[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateVirtualUnwinder( + + virtual HRESULT STDMETHODCALLTYPE CreateVirtualUnwinder( /* [in] */ DWORD nativeThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 cbContext, /* [size_is][in] */ BYTE initialContext[ ], /* [out] */ ICorDebugVirtualUnwinder **ppUnwinder) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugDataTarget2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDataTarget2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDataTarget2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDataTarget2 * This); - + DECLSPEC_XFGVIRT(ICorDebugDataTarget2, GetImageFromPointer) - HRESULT ( STDMETHODCALLTYPE *GetImageFromPointer )( + HRESULT ( STDMETHODCALLTYPE *GetImageFromPointer )( ICorDebugDataTarget2 * This, /* [in] */ CORDB_ADDRESS addr, /* [out] */ CORDB_ADDRESS *pImageBase, /* [out] */ ULONG32 *pSize); - + DECLSPEC_XFGVIRT(ICorDebugDataTarget2, GetImageLocation) - HRESULT ( STDMETHODCALLTYPE *GetImageLocation )( + HRESULT ( STDMETHODCALLTYPE *GetImageLocation )( ICorDebugDataTarget2 * This, /* [in] */ CORDB_ADDRESS baseAddress, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - + DECLSPEC_XFGVIRT(ICorDebugDataTarget2, GetSymbolProviderForImage) - HRESULT ( STDMETHODCALLTYPE *GetSymbolProviderForImage )( + HRESULT ( STDMETHODCALLTYPE *GetSymbolProviderForImage )( ICorDebugDataTarget2 * This, /* [in] */ CORDB_ADDRESS imageBaseAddress, /* [out] */ ICorDebugSymbolProvider **ppSymProvider); - + DECLSPEC_XFGVIRT(ICorDebugDataTarget2, EnumerateThreadIDs) - HRESULT ( STDMETHODCALLTYPE *EnumerateThreadIDs )( + HRESULT ( STDMETHODCALLTYPE *EnumerateThreadIDs )( ICorDebugDataTarget2 * This, /* [in] */ ULONG32 cThreadIds, /* [out] */ ULONG32 *pcThreadIds, /* [length_is][size_is][out] */ ULONG32 pThreadIds[ ]); - + DECLSPEC_XFGVIRT(ICorDebugDataTarget2, CreateVirtualUnwinder) - HRESULT ( STDMETHODCALLTYPE *CreateVirtualUnwinder )( + HRESULT ( STDMETHODCALLTYPE *CreateVirtualUnwinder )( ICorDebugDataTarget2 * This, /* [in] */ DWORD nativeThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 cbContext, /* [size_is][in] */ BYTE initialContext[ ], /* [out] */ ICorDebugVirtualUnwinder **ppUnwinder); - + END_INTERFACE } ICorDebugDataTarget2Vtbl; @@ -2797,35 +2804,35 @@ EXTERN_C const IID IID_ICorDebugDataTarget2; CONST_VTBL struct ICorDebugDataTarget2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugDataTarget2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDataTarget2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDataTarget2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDataTarget2_GetImageFromPointer(This,addr,pImageBase,pSize) \ - ( (This)->lpVtbl -> GetImageFromPointer(This,addr,pImageBase,pSize) ) + ( (This)->lpVtbl -> GetImageFromPointer(This,addr,pImageBase,pSize) ) #define ICorDebugDataTarget2_GetImageLocation(This,baseAddress,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetImageLocation(This,baseAddress,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetImageLocation(This,baseAddress,cchName,pcchName,szName) ) #define ICorDebugDataTarget2_GetSymbolProviderForImage(This,imageBaseAddress,ppSymProvider) \ - ( (This)->lpVtbl -> GetSymbolProviderForImage(This,imageBaseAddress,ppSymProvider) ) + ( (This)->lpVtbl -> GetSymbolProviderForImage(This,imageBaseAddress,ppSymProvider) ) #define ICorDebugDataTarget2_EnumerateThreadIDs(This,cThreadIds,pcThreadIds,pThreadIds) \ - ( (This)->lpVtbl -> EnumerateThreadIDs(This,cThreadIds,pcThreadIds,pThreadIds) ) + ( (This)->lpVtbl -> EnumerateThreadIDs(This,cThreadIds,pcThreadIds,pThreadIds) ) #define ICorDebugDataTarget2_CreateVirtualUnwinder(This,nativeThreadID,contextFlags,cbContext,initialContext,ppUnwinder) \ - ( (This)->lpVtbl -> CreateVirtualUnwinder(This,nativeThreadID,contextFlags,cbContext,initialContext,ppUnwinder) ) + ( (This)->lpVtbl -> CreateVirtualUnwinder(This,nativeThreadID,contextFlags,cbContext,initialContext,ppUnwinder) ) #endif /* COBJMACROS */ @@ -2842,69 +2849,69 @@ EXTERN_C const IID IID_ICorDebugDataTarget2; #define __ICorDebugLoadedModule_INTERFACE_DEFINED__ /* interface ICorDebugLoadedModule */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugLoadedModule; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("817F343A-6630-4578-96C5-D11BC0EC5EE2") ICorDebugLoadedModule : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetBaseAddress( + virtual HRESULT STDMETHODCALLTYPE GetBaseAddress( /* [out] */ CORDB_ADDRESS *pAddress) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetName( + + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcBytes) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugLoadedModuleVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugLoadedModule * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugLoadedModule * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugLoadedModule * This); - + DECLSPEC_XFGVIRT(ICorDebugLoadedModule, GetBaseAddress) - HRESULT ( STDMETHODCALLTYPE *GetBaseAddress )( + HRESULT ( STDMETHODCALLTYPE *GetBaseAddress )( ICorDebugLoadedModule * This, /* [out] */ CORDB_ADDRESS *pAddress); - + DECLSPEC_XFGVIRT(ICorDebugLoadedModule, GetName) - HRESULT ( STDMETHODCALLTYPE *GetName )( + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugLoadedModule * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - + DECLSPEC_XFGVIRT(ICorDebugLoadedModule, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugLoadedModule * This, /* [out] */ ULONG32 *pcBytes); - + END_INTERFACE } ICorDebugLoadedModuleVtbl; @@ -2913,29 +2920,29 @@ EXTERN_C const IID IID_ICorDebugLoadedModule; CONST_VTBL struct ICorDebugLoadedModuleVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugLoadedModule_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugLoadedModule_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugLoadedModule_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugLoadedModule_GetBaseAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetBaseAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetBaseAddress(This,pAddress) ) #define ICorDebugLoadedModule_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugLoadedModule_GetSize(This,pcBytes) \ - ( (This)->lpVtbl -> GetSize(This,pcBytes) ) + ( (This)->lpVtbl -> GetSize(This,pcBytes) ) #endif /* COBJMACROS */ @@ -2952,53 +2959,53 @@ EXTERN_C const IID IID_ICorDebugLoadedModule; #define __ICorDebugDataTarget3_INTERFACE_DEFINED__ /* interface ICorDebugDataTarget3 */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugDataTarget3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("D05E60C3-848C-4E7D-894E-623320FF6AFA") ICorDebugDataTarget3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetLoadedModules( + virtual HRESULT STDMETHODCALLTYPE GetLoadedModules( /* [in] */ ULONG32 cRequestedModules, /* [out] */ ULONG32 *pcFetchedModules, /* [length_is][size_is][out] */ ICorDebugLoadedModule *pLoadedModules[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugDataTarget3Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDataTarget3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDataTarget3 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDataTarget3 * This); - + DECLSPEC_XFGVIRT(ICorDebugDataTarget3, GetLoadedModules) - HRESULT ( STDMETHODCALLTYPE *GetLoadedModules )( + HRESULT ( STDMETHODCALLTYPE *GetLoadedModules )( ICorDebugDataTarget3 * This, /* [in] */ ULONG32 cRequestedModules, /* [out] */ ULONG32 *pcFetchedModules, /* [length_is][size_is][out] */ ICorDebugLoadedModule *pLoadedModules[ ]); - + END_INTERFACE } ICorDebugDataTarget3Vtbl; @@ -3007,23 +3014,23 @@ EXTERN_C const IID IID_ICorDebugDataTarget3; CONST_VTBL struct ICorDebugDataTarget3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugDataTarget3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDataTarget3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDataTarget3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDataTarget3_GetLoadedModules(This,cRequestedModules,pcFetchedModules,pLoadedModules) \ - ( (This)->lpVtbl -> GetLoadedModules(This,cRequestedModules,pcFetchedModules,pLoadedModules) ) + ( (This)->lpVtbl -> GetLoadedModules(This,cRequestedModules,pcFetchedModules,pLoadedModules) ) #endif /* COBJMACROS */ @@ -3040,53 +3047,53 @@ EXTERN_C const IID IID_ICorDebugDataTarget3; #define __ICorDebugDataTarget4_INTERFACE_DEFINED__ /* interface ICorDebugDataTarget4 */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugDataTarget4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("E799DC06-E099-4713-BDD9-906D3CC02CF2") ICorDebugDataTarget4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE VirtualUnwind( + virtual HRESULT STDMETHODCALLTYPE VirtualUnwind( /* [in] */ DWORD threadId, /* [in] */ ULONG32 contextSize, /* [size_is][out][in] */ BYTE *context) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugDataTarget4Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDataTarget4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDataTarget4 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDataTarget4 * This); - + DECLSPEC_XFGVIRT(ICorDebugDataTarget4, VirtualUnwind) - HRESULT ( STDMETHODCALLTYPE *VirtualUnwind )( + HRESULT ( STDMETHODCALLTYPE *VirtualUnwind )( ICorDebugDataTarget4 * This, /* [in] */ DWORD threadId, /* [in] */ ULONG32 contextSize, /* [size_is][out][in] */ BYTE *context); - + END_INTERFACE } ICorDebugDataTarget4Vtbl; @@ -3095,23 +3102,23 @@ EXTERN_C const IID IID_ICorDebugDataTarget4; CONST_VTBL struct ICorDebugDataTarget4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugDataTarget4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDataTarget4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDataTarget4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDataTarget4_VirtualUnwind(This,threadId,contextSize,context) \ - ( (This)->lpVtbl -> VirtualUnwind(This,threadId,contextSize,context) ) + ( (This)->lpVtbl -> VirtualUnwind(This,threadId,contextSize,context) ) #endif /* COBJMACROS */ @@ -3128,96 +3135,96 @@ EXTERN_C const IID IID_ICorDebugDataTarget4; #define __ICorDebugMutableDataTarget_INTERFACE_DEFINED__ /* interface ICorDebugMutableDataTarget */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugMutableDataTarget; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("A1B8A756-3CB6-4CCB-979F-3DF999673A59") ICorDebugMutableDataTarget : public ICorDebugDataTarget { public: - virtual HRESULT STDMETHODCALLTYPE WriteVirtual( + virtual HRESULT STDMETHODCALLTYPE WriteVirtual( /* [in] */ CORDB_ADDRESS address, /* [size_is][in] */ const BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetThreadContext( + + virtual HRESULT STDMETHODCALLTYPE SetThreadContext( /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ const BYTE *pContext) = 0; - - virtual HRESULT STDMETHODCALLTYPE ContinueStatusChanged( + + virtual HRESULT STDMETHODCALLTYPE ContinueStatusChanged( /* [in] */ DWORD dwThreadId, /* [in] */ CORDB_CONTINUE_STATUS continueStatus) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugMutableDataTargetVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMutableDataTarget * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMutableDataTarget * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMutableDataTarget * This); - + DECLSPEC_XFGVIRT(ICorDebugDataTarget, GetPlatform) - HRESULT ( STDMETHODCALLTYPE *GetPlatform )( + HRESULT ( STDMETHODCALLTYPE *GetPlatform )( ICorDebugMutableDataTarget * This, /* [out] */ CorDebugPlatform *pTargetPlatform); - + DECLSPEC_XFGVIRT(ICorDebugDataTarget, ReadVirtual) - HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( + HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( ICorDebugMutableDataTarget * This, /* [in] */ CORDB_ADDRESS address, /* [length_is][size_is][out] */ BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *pBytesRead); - + DECLSPEC_XFGVIRT(ICorDebugDataTarget, GetThreadContext) - HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorDebugMutableDataTarget * This, /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE *pContext); - + DECLSPEC_XFGVIRT(ICorDebugMutableDataTarget, WriteVirtual) - HRESULT ( STDMETHODCALLTYPE *WriteVirtual )( + HRESULT ( STDMETHODCALLTYPE *WriteVirtual )( ICorDebugMutableDataTarget * This, /* [in] */ CORDB_ADDRESS address, /* [size_is][in] */ const BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested); - + DECLSPEC_XFGVIRT(ICorDebugMutableDataTarget, SetThreadContext) - HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( + HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( ICorDebugMutableDataTarget * This, /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ const BYTE *pContext); - + DECLSPEC_XFGVIRT(ICorDebugMutableDataTarget, ContinueStatusChanged) - HRESULT ( STDMETHODCALLTYPE *ContinueStatusChanged )( + HRESULT ( STDMETHODCALLTYPE *ContinueStatusChanged )( ICorDebugMutableDataTarget * This, /* [in] */ DWORD dwThreadId, /* [in] */ CORDB_CONTINUE_STATUS continueStatus); - + END_INTERFACE } ICorDebugMutableDataTargetVtbl; @@ -3226,39 +3233,39 @@ EXTERN_C const IID IID_ICorDebugMutableDataTarget; CONST_VTBL struct ICorDebugMutableDataTargetVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugMutableDataTarget_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMutableDataTarget_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMutableDataTarget_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMutableDataTarget_GetPlatform(This,pTargetPlatform) \ - ( (This)->lpVtbl -> GetPlatform(This,pTargetPlatform) ) + ( (This)->lpVtbl -> GetPlatform(This,pTargetPlatform) ) #define ICorDebugMutableDataTarget_ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) \ - ( (This)->lpVtbl -> ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) ) + ( (This)->lpVtbl -> ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) ) #define ICorDebugMutableDataTarget_GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) \ - ( (This)->lpVtbl -> GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) ) + ( (This)->lpVtbl -> GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) ) #define ICorDebugMutableDataTarget_WriteVirtual(This,address,pBuffer,bytesRequested) \ - ( (This)->lpVtbl -> WriteVirtual(This,address,pBuffer,bytesRequested) ) + ( (This)->lpVtbl -> WriteVirtual(This,address,pBuffer,bytesRequested) ) #define ICorDebugMutableDataTarget_SetThreadContext(This,dwThreadID,contextSize,pContext) \ - ( (This)->lpVtbl -> SetThreadContext(This,dwThreadID,contextSize,pContext) ) + ( (This)->lpVtbl -> SetThreadContext(This,dwThreadID,contextSize,pContext) ) #define ICorDebugMutableDataTarget_ContinueStatusChanged(This,dwThreadId,continueStatus) \ - ( (This)->lpVtbl -> ContinueStatusChanged(This,dwThreadId,continueStatus) ) + ( (This)->lpVtbl -> ContinueStatusChanged(This,dwThreadId,continueStatus) ) #endif /* COBJMACROS */ @@ -3275,63 +3282,63 @@ EXTERN_C const IID IID_ICorDebugMutableDataTarget; #define __ICorDebugMetaDataLocator_INTERFACE_DEFINED__ /* interface ICorDebugMetaDataLocator */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugMetaDataLocator; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("7cef8ba9-2ef7-42bf-973f-4171474f87d9") ICorDebugMetaDataLocator : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetMetaData( + virtual HRESULT STDMETHODCALLTYPE GetMetaData( /* [in] */ LPCWSTR wszImagePath, /* [in] */ DWORD dwImageTimeStamp, /* [in] */ DWORD dwImageSize, /* [in] */ ULONG32 cchPathBuffer, - /* [annotation][out] */ + /* [annotation][out] */ _Out_ ULONG32 *pcchPathBuffer, - /* [annotation][length_is][size_is][out] */ + /* [annotation][length_is][size_is][out] */ _Out_writes_to_(cchPathBuffer, *pcchPathBuffer) WCHAR wszPathBuffer[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugMetaDataLocatorVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMetaDataLocator * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMetaDataLocator * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMetaDataLocator * This); - + DECLSPEC_XFGVIRT(ICorDebugMetaDataLocator, GetMetaData) - HRESULT ( STDMETHODCALLTYPE *GetMetaData )( + HRESULT ( STDMETHODCALLTYPE *GetMetaData )( ICorDebugMetaDataLocator * This, /* [in] */ LPCWSTR wszImagePath, /* [in] */ DWORD dwImageTimeStamp, /* [in] */ DWORD dwImageSize, /* [in] */ ULONG32 cchPathBuffer, - /* [annotation][out] */ + /* [annotation][out] */ _Out_ ULONG32 *pcchPathBuffer, - /* [annotation][length_is][size_is][out] */ + /* [annotation][length_is][size_is][out] */ _Out_writes_to_(cchPathBuffer, *pcchPathBuffer) WCHAR wszPathBuffer[ ]); - + END_INTERFACE } ICorDebugMetaDataLocatorVtbl; @@ -3340,23 +3347,23 @@ EXTERN_C const IID IID_ICorDebugMetaDataLocator; CONST_VTBL struct ICorDebugMetaDataLocatorVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugMetaDataLocator_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMetaDataLocator_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMetaDataLocator_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMetaDataLocator_GetMetaData(This,wszImagePath,dwImageTimeStamp,dwImageSize,cchPathBuffer,pcchPathBuffer,wszPathBuffer) \ - ( (This)->lpVtbl -> GetMetaData(This,wszImagePath,dwImageTimeStamp,dwImageSize,cchPathBuffer,pcchPathBuffer,wszPathBuffer) ) + ( (This)->lpVtbl -> GetMetaData(This,wszImagePath,dwImageTimeStamp,dwImageSize,cchPathBuffer,pcchPathBuffer,wszPathBuffer) ) #endif /* COBJMACROS */ @@ -3370,10 +3377,10 @@ EXTERN_C const IID IID_ICorDebugMetaDataLocator; /* interface __MIDL_itf_cordebug_0000_0015 */ -/* [local] */ +/* [local] */ #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0015_v0_0_c_ifspec; @@ -3383,9 +3390,9 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0015_v0_0_s_ifspec; #define __ICorDebugManagedCallback_INTERFACE_DEFINED__ /* interface ICorDebugManagedCallback */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugStepReason { STEP_NORMAL = 0, @@ -3394,10 +3401,10 @@ enum CorDebugStepReason STEP_EXCEPTION_FILTER = ( STEP_CALL + 1 ) , STEP_EXCEPTION_HANDLER = ( STEP_EXCEPTION_FILTER + 1 ) , STEP_INTERCEPT = ( STEP_EXCEPTION_HANDLER + 1 ) , - STEP_EXIT = ( STEP_INTERCEPT + 1 ) + STEP_EXIT = ( STEP_INTERCEPT + 1 ) } CorDebugStepReason; -typedef +typedef enum LoggingLevelEnum { LTraceLevel0 = 0, @@ -3415,273 +3422,273 @@ enum LoggingLevelEnum LPanicLevel = 100 } LoggingLevelEnum; -typedef +typedef enum LogSwitchCallReason { SWITCH_CREATE = 0, SWITCH_MODIFY = ( SWITCH_CREATE + 1 ) , - SWITCH_DELETE = ( SWITCH_MODIFY + 1 ) + SWITCH_DELETE = ( SWITCH_MODIFY + 1 ) } LogSwitchCallReason; EXTERN_C const IID IID_ICorDebugManagedCallback; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("3d6f5f60-7538-11d3-8d5b-00104b35e7ef") ICorDebugManagedCallback : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE Breakpoint( + virtual HRESULT STDMETHODCALLTYPE Breakpoint( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugBreakpoint *pBreakpoint) = 0; - - virtual HRESULT STDMETHODCALLTYPE StepComplete( + + virtual HRESULT STDMETHODCALLTYPE StepComplete( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugStepper *pStepper, /* [in] */ CorDebugStepReason reason) = 0; - - virtual HRESULT STDMETHODCALLTYPE Break( + + virtual HRESULT STDMETHODCALLTYPE Break( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread) = 0; - - virtual HRESULT STDMETHODCALLTYPE Exception( + + virtual HRESULT STDMETHODCALLTYPE Exception( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ BOOL unhandled) = 0; - - virtual HRESULT STDMETHODCALLTYPE EvalComplete( + + virtual HRESULT STDMETHODCALLTYPE EvalComplete( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugEval *pEval) = 0; - - virtual HRESULT STDMETHODCALLTYPE EvalException( + + virtual HRESULT STDMETHODCALLTYPE EvalException( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugEval *pEval) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateProcess( + + virtual HRESULT STDMETHODCALLTYPE CreateProcess( /* [in] */ ICorDebugProcess *pProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE ExitProcess( + + virtual HRESULT STDMETHODCALLTYPE ExitProcess( /* [in] */ ICorDebugProcess *pProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateThread( + + virtual HRESULT STDMETHODCALLTYPE CreateThread( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread) = 0; - - virtual HRESULT STDMETHODCALLTYPE ExitThread( + + virtual HRESULT STDMETHODCALLTYPE ExitThread( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread) = 0; - - virtual HRESULT STDMETHODCALLTYPE LoadModule( + + virtual HRESULT STDMETHODCALLTYPE LoadModule( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule) = 0; - - virtual HRESULT STDMETHODCALLTYPE UnloadModule( + + virtual HRESULT STDMETHODCALLTYPE UnloadModule( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule) = 0; - - virtual HRESULT STDMETHODCALLTYPE LoadClass( + + virtual HRESULT STDMETHODCALLTYPE LoadClass( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugClass *c) = 0; - - virtual HRESULT STDMETHODCALLTYPE UnloadClass( + + virtual HRESULT STDMETHODCALLTYPE UnloadClass( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugClass *c) = 0; - - virtual HRESULT STDMETHODCALLTYPE DebuggerError( + + virtual HRESULT STDMETHODCALLTYPE DebuggerError( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ HRESULT errorHR, /* [in] */ DWORD errorCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE LogMessage( + + virtual HRESULT STDMETHODCALLTYPE LogMessage( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ LONG lLevel, /* [in] */ WCHAR *pLogSwitchName, /* [in] */ WCHAR *pMessage) = 0; - - virtual HRESULT STDMETHODCALLTYPE LogSwitch( + + virtual HRESULT STDMETHODCALLTYPE LogSwitch( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ LONG lLevel, /* [in] */ ULONG ulReason, /* [in] */ WCHAR *pLogSwitchName, /* [in] */ WCHAR *pParentName) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateAppDomain( + + virtual HRESULT STDMETHODCALLTYPE CreateAppDomain( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugAppDomain *pAppDomain) = 0; - - virtual HRESULT STDMETHODCALLTYPE ExitAppDomain( + + virtual HRESULT STDMETHODCALLTYPE ExitAppDomain( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugAppDomain *pAppDomain) = 0; - - virtual HRESULT STDMETHODCALLTYPE LoadAssembly( + + virtual HRESULT STDMETHODCALLTYPE LoadAssembly( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugAssembly *pAssembly) = 0; - - virtual HRESULT STDMETHODCALLTYPE UnloadAssembly( + + virtual HRESULT STDMETHODCALLTYPE UnloadAssembly( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugAssembly *pAssembly) = 0; - - virtual HRESULT STDMETHODCALLTYPE ControlCTrap( + + virtual HRESULT STDMETHODCALLTYPE ControlCTrap( /* [in] */ ICorDebugProcess *pProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE NameChange( + + virtual HRESULT STDMETHODCALLTYPE NameChange( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread) = 0; - - virtual HRESULT STDMETHODCALLTYPE UpdateModuleSymbols( + + virtual HRESULT STDMETHODCALLTYPE UpdateModuleSymbols( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule, /* [in] */ IStream *pSymbolStream) = 0; - - virtual HRESULT STDMETHODCALLTYPE EditAndContinueRemap( + + virtual HRESULT STDMETHODCALLTYPE EditAndContinueRemap( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pFunction, /* [in] */ BOOL fAccurate) = 0; - - virtual HRESULT STDMETHODCALLTYPE BreakpointSetError( + + virtual HRESULT STDMETHODCALLTYPE BreakpointSetError( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugBreakpoint *pBreakpoint, /* [in] */ DWORD dwError) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugManagedCallbackVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugManagedCallback * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugManagedCallback * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugManagedCallback * This); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, Breakpoint) - HRESULT ( STDMETHODCALLTYPE *Breakpoint )( + HRESULT ( STDMETHODCALLTYPE *Breakpoint )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugBreakpoint *pBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, StepComplete) - HRESULT ( STDMETHODCALLTYPE *StepComplete )( + HRESULT ( STDMETHODCALLTYPE *StepComplete )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugStepper *pStepper, /* [in] */ CorDebugStepReason reason); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, Break) - HRESULT ( STDMETHODCALLTYPE *Break )( + HRESULT ( STDMETHODCALLTYPE *Break )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, Exception) - HRESULT ( STDMETHODCALLTYPE *Exception )( + HRESULT ( STDMETHODCALLTYPE *Exception )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ BOOL unhandled); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, EvalComplete) - HRESULT ( STDMETHODCALLTYPE *EvalComplete )( + HRESULT ( STDMETHODCALLTYPE *EvalComplete )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugEval *pEval); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, EvalException) - HRESULT ( STDMETHODCALLTYPE *EvalException )( + HRESULT ( STDMETHODCALLTYPE *EvalException )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugEval *pEval); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, CreateProcess) - HRESULT ( STDMETHODCALLTYPE *CreateProcess )( + HRESULT ( STDMETHODCALLTYPE *CreateProcess )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, ExitProcess) - HRESULT ( STDMETHODCALLTYPE *ExitProcess )( + HRESULT ( STDMETHODCALLTYPE *ExitProcess )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, CreateThread) - HRESULT ( STDMETHODCALLTYPE *CreateThread )( + HRESULT ( STDMETHODCALLTYPE *CreateThread )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, ExitThread) - HRESULT ( STDMETHODCALLTYPE *ExitThread )( + HRESULT ( STDMETHODCALLTYPE *ExitThread )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, LoadModule) - HRESULT ( STDMETHODCALLTYPE *LoadModule )( + HRESULT ( STDMETHODCALLTYPE *LoadModule )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, UnloadModule) - HRESULT ( STDMETHODCALLTYPE *UnloadModule )( + HRESULT ( STDMETHODCALLTYPE *UnloadModule )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, LoadClass) - HRESULT ( STDMETHODCALLTYPE *LoadClass )( + HRESULT ( STDMETHODCALLTYPE *LoadClass )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugClass *c); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, UnloadClass) - HRESULT ( STDMETHODCALLTYPE *UnloadClass )( + HRESULT ( STDMETHODCALLTYPE *UnloadClass )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugClass *c); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, DebuggerError) - HRESULT ( STDMETHODCALLTYPE *DebuggerError )( + HRESULT ( STDMETHODCALLTYPE *DebuggerError )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ HRESULT errorHR, /* [in] */ DWORD errorCode); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, LogMessage) - HRESULT ( STDMETHODCALLTYPE *LogMessage )( + HRESULT ( STDMETHODCALLTYPE *LogMessage )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ LONG lLevel, /* [in] */ WCHAR *pLogSwitchName, /* [in] */ WCHAR *pMessage); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, LogSwitch) - HRESULT ( STDMETHODCALLTYPE *LogSwitch )( + HRESULT ( STDMETHODCALLTYPE *LogSwitch )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, @@ -3689,65 +3696,65 @@ EXTERN_C const IID IID_ICorDebugManagedCallback; /* [in] */ ULONG ulReason, /* [in] */ WCHAR *pLogSwitchName, /* [in] */ WCHAR *pParentName); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, CreateAppDomain) - HRESULT ( STDMETHODCALLTYPE *CreateAppDomain )( + HRESULT ( STDMETHODCALLTYPE *CreateAppDomain )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugAppDomain *pAppDomain); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, ExitAppDomain) - HRESULT ( STDMETHODCALLTYPE *ExitAppDomain )( + HRESULT ( STDMETHODCALLTYPE *ExitAppDomain )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugAppDomain *pAppDomain); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, LoadAssembly) - HRESULT ( STDMETHODCALLTYPE *LoadAssembly )( + HRESULT ( STDMETHODCALLTYPE *LoadAssembly )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugAssembly *pAssembly); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, UnloadAssembly) - HRESULT ( STDMETHODCALLTYPE *UnloadAssembly )( + HRESULT ( STDMETHODCALLTYPE *UnloadAssembly )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugAssembly *pAssembly); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, ControlCTrap) - HRESULT ( STDMETHODCALLTYPE *ControlCTrap )( + HRESULT ( STDMETHODCALLTYPE *ControlCTrap )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, NameChange) - HRESULT ( STDMETHODCALLTYPE *NameChange )( + HRESULT ( STDMETHODCALLTYPE *NameChange )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, UpdateModuleSymbols) - HRESULT ( STDMETHODCALLTYPE *UpdateModuleSymbols )( + HRESULT ( STDMETHODCALLTYPE *UpdateModuleSymbols )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule, /* [in] */ IStream *pSymbolStream); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, EditAndContinueRemap) - HRESULT ( STDMETHODCALLTYPE *EditAndContinueRemap )( + HRESULT ( STDMETHODCALLTYPE *EditAndContinueRemap )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pFunction, /* [in] */ BOOL fAccurate); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback, BreakpointSetError) - HRESULT ( STDMETHODCALLTYPE *BreakpointSetError )( + HRESULT ( STDMETHODCALLTYPE *BreakpointSetError )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugBreakpoint *pBreakpoint, /* [in] */ DWORD dwError); - + END_INTERFACE } ICorDebugManagedCallbackVtbl; @@ -3756,98 +3763,98 @@ EXTERN_C const IID IID_ICorDebugManagedCallback; CONST_VTBL struct ICorDebugManagedCallbackVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugManagedCallback_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugManagedCallback_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugManagedCallback_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugManagedCallback_Breakpoint(This,pAppDomain,pThread,pBreakpoint) \ - ( (This)->lpVtbl -> Breakpoint(This,pAppDomain,pThread,pBreakpoint) ) + ( (This)->lpVtbl -> Breakpoint(This,pAppDomain,pThread,pBreakpoint) ) #define ICorDebugManagedCallback_StepComplete(This,pAppDomain,pThread,pStepper,reason) \ - ( (This)->lpVtbl -> StepComplete(This,pAppDomain,pThread,pStepper,reason) ) + ( (This)->lpVtbl -> StepComplete(This,pAppDomain,pThread,pStepper,reason) ) #define ICorDebugManagedCallback_Break(This,pAppDomain,thread) \ - ( (This)->lpVtbl -> Break(This,pAppDomain,thread) ) + ( (This)->lpVtbl -> Break(This,pAppDomain,thread) ) #define ICorDebugManagedCallback_Exception(This,pAppDomain,pThread,unhandled) \ - ( (This)->lpVtbl -> Exception(This,pAppDomain,pThread,unhandled) ) + ( (This)->lpVtbl -> Exception(This,pAppDomain,pThread,unhandled) ) #define ICorDebugManagedCallback_EvalComplete(This,pAppDomain,pThread,pEval) \ - ( (This)->lpVtbl -> EvalComplete(This,pAppDomain,pThread,pEval) ) + ( (This)->lpVtbl -> EvalComplete(This,pAppDomain,pThread,pEval) ) #define ICorDebugManagedCallback_EvalException(This,pAppDomain,pThread,pEval) \ - ( (This)->lpVtbl -> EvalException(This,pAppDomain,pThread,pEval) ) + ( (This)->lpVtbl -> EvalException(This,pAppDomain,pThread,pEval) ) #define ICorDebugManagedCallback_CreateProcess(This,pProcess) \ - ( (This)->lpVtbl -> CreateProcess(This,pProcess) ) + ( (This)->lpVtbl -> CreateProcess(This,pProcess) ) #define ICorDebugManagedCallback_ExitProcess(This,pProcess) \ - ( (This)->lpVtbl -> ExitProcess(This,pProcess) ) + ( (This)->lpVtbl -> ExitProcess(This,pProcess) ) #define ICorDebugManagedCallback_CreateThread(This,pAppDomain,thread) \ - ( (This)->lpVtbl -> CreateThread(This,pAppDomain,thread) ) + ( (This)->lpVtbl -> CreateThread(This,pAppDomain,thread) ) #define ICorDebugManagedCallback_ExitThread(This,pAppDomain,thread) \ - ( (This)->lpVtbl -> ExitThread(This,pAppDomain,thread) ) + ( (This)->lpVtbl -> ExitThread(This,pAppDomain,thread) ) #define ICorDebugManagedCallback_LoadModule(This,pAppDomain,pModule) \ - ( (This)->lpVtbl -> LoadModule(This,pAppDomain,pModule) ) + ( (This)->lpVtbl -> LoadModule(This,pAppDomain,pModule) ) #define ICorDebugManagedCallback_UnloadModule(This,pAppDomain,pModule) \ - ( (This)->lpVtbl -> UnloadModule(This,pAppDomain,pModule) ) + ( (This)->lpVtbl -> UnloadModule(This,pAppDomain,pModule) ) #define ICorDebugManagedCallback_LoadClass(This,pAppDomain,c) \ - ( (This)->lpVtbl -> LoadClass(This,pAppDomain,c) ) + ( (This)->lpVtbl -> LoadClass(This,pAppDomain,c) ) #define ICorDebugManagedCallback_UnloadClass(This,pAppDomain,c) \ - ( (This)->lpVtbl -> UnloadClass(This,pAppDomain,c) ) + ( (This)->lpVtbl -> UnloadClass(This,pAppDomain,c) ) #define ICorDebugManagedCallback_DebuggerError(This,pProcess,errorHR,errorCode) \ - ( (This)->lpVtbl -> DebuggerError(This,pProcess,errorHR,errorCode) ) + ( (This)->lpVtbl -> DebuggerError(This,pProcess,errorHR,errorCode) ) #define ICorDebugManagedCallback_LogMessage(This,pAppDomain,pThread,lLevel,pLogSwitchName,pMessage) \ - ( (This)->lpVtbl -> LogMessage(This,pAppDomain,pThread,lLevel,pLogSwitchName,pMessage) ) + ( (This)->lpVtbl -> LogMessage(This,pAppDomain,pThread,lLevel,pLogSwitchName,pMessage) ) #define ICorDebugManagedCallback_LogSwitch(This,pAppDomain,pThread,lLevel,ulReason,pLogSwitchName,pParentName) \ - ( (This)->lpVtbl -> LogSwitch(This,pAppDomain,pThread,lLevel,ulReason,pLogSwitchName,pParentName) ) + ( (This)->lpVtbl -> LogSwitch(This,pAppDomain,pThread,lLevel,ulReason,pLogSwitchName,pParentName) ) #define ICorDebugManagedCallback_CreateAppDomain(This,pProcess,pAppDomain) \ - ( (This)->lpVtbl -> CreateAppDomain(This,pProcess,pAppDomain) ) + ( (This)->lpVtbl -> CreateAppDomain(This,pProcess,pAppDomain) ) #define ICorDebugManagedCallback_ExitAppDomain(This,pProcess,pAppDomain) \ - ( (This)->lpVtbl -> ExitAppDomain(This,pProcess,pAppDomain) ) + ( (This)->lpVtbl -> ExitAppDomain(This,pProcess,pAppDomain) ) #define ICorDebugManagedCallback_LoadAssembly(This,pAppDomain,pAssembly) \ - ( (This)->lpVtbl -> LoadAssembly(This,pAppDomain,pAssembly) ) + ( (This)->lpVtbl -> LoadAssembly(This,pAppDomain,pAssembly) ) #define ICorDebugManagedCallback_UnloadAssembly(This,pAppDomain,pAssembly) \ - ( (This)->lpVtbl -> UnloadAssembly(This,pAppDomain,pAssembly) ) + ( (This)->lpVtbl -> UnloadAssembly(This,pAppDomain,pAssembly) ) #define ICorDebugManagedCallback_ControlCTrap(This,pProcess) \ - ( (This)->lpVtbl -> ControlCTrap(This,pProcess) ) + ( (This)->lpVtbl -> ControlCTrap(This,pProcess) ) #define ICorDebugManagedCallback_NameChange(This,pAppDomain,pThread) \ - ( (This)->lpVtbl -> NameChange(This,pAppDomain,pThread) ) + ( (This)->lpVtbl -> NameChange(This,pAppDomain,pThread) ) #define ICorDebugManagedCallback_UpdateModuleSymbols(This,pAppDomain,pModule,pSymbolStream) \ - ( (This)->lpVtbl -> UpdateModuleSymbols(This,pAppDomain,pModule,pSymbolStream) ) + ( (This)->lpVtbl -> UpdateModuleSymbols(This,pAppDomain,pModule,pSymbolStream) ) #define ICorDebugManagedCallback_EditAndContinueRemap(This,pAppDomain,pThread,pFunction,fAccurate) \ - ( (This)->lpVtbl -> EditAndContinueRemap(This,pAppDomain,pThread,pFunction,fAccurate) ) + ( (This)->lpVtbl -> EditAndContinueRemap(This,pAppDomain,pThread,pFunction,fAccurate) ) #define ICorDebugManagedCallback_BreakpointSetError(This,pAppDomain,pThread,pBreakpoint,dwError) \ - ( (This)->lpVtbl -> BreakpointSetError(This,pAppDomain,pThread,pBreakpoint,dwError) ) + ( (This)->lpVtbl -> BreakpointSetError(This,pAppDomain,pThread,pBreakpoint,dwError) ) #endif /* COBJMACROS */ @@ -3861,7 +3868,7 @@ EXTERN_C const IID IID_ICorDebugManagedCallback; /* interface __MIDL_itf_cordebug_0000_0016 */ -/* [local] */ +/* [local] */ #pragma warning(pop) #pragma warning(push) @@ -3874,51 +3881,51 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0016_v0_0_s_ifspec; #define __ICorDebugManagedCallback3_INTERFACE_DEFINED__ /* interface ICorDebugManagedCallback3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugManagedCallback3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("264EA0FC-2591-49AA-868E-835E6515323F") ICorDebugManagedCallback3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CustomNotification( + virtual HRESULT STDMETHODCALLTYPE CustomNotification( /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugAppDomain *pAppDomain) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugManagedCallback3Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugManagedCallback3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugManagedCallback3 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugManagedCallback3 * This); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback3, CustomNotification) - HRESULT ( STDMETHODCALLTYPE *CustomNotification )( + HRESULT ( STDMETHODCALLTYPE *CustomNotification )( ICorDebugManagedCallback3 * This, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugAppDomain *pAppDomain); - + END_INTERFACE } ICorDebugManagedCallback3Vtbl; @@ -3927,23 +3934,23 @@ EXTERN_C const IID IID_ICorDebugManagedCallback3; CONST_VTBL struct ICorDebugManagedCallback3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugManagedCallback3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugManagedCallback3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugManagedCallback3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugManagedCallback3_CustomNotification(This,pThread,pAppDomain) \ - ( (This)->lpVtbl -> CustomNotification(This,pThread,pAppDomain) ) + ( (This)->lpVtbl -> CustomNotification(This,pThread,pAppDomain) ) #endif /* COBJMACROS */ @@ -3960,71 +3967,71 @@ EXTERN_C const IID IID_ICorDebugManagedCallback3; #define __ICorDebugManagedCallback4_INTERFACE_DEFINED__ /* interface ICorDebugManagedCallback4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugManagedCallback4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("322911AE-16A5-49BA-84A3-ED69678138A3") ICorDebugManagedCallback4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE BeforeGarbageCollection( + virtual HRESULT STDMETHODCALLTYPE BeforeGarbageCollection( /* [in] */ ICorDebugProcess *pProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE AfterGarbageCollection( + + virtual HRESULT STDMETHODCALLTYPE AfterGarbageCollection( /* [in] */ ICorDebugProcess *pProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE DataBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE DataBreakpoint( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugThread *pThread, /* [in] */ BYTE *pContext, /* [in] */ ULONG32 contextSize) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugManagedCallback4Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugManagedCallback4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugManagedCallback4 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugManagedCallback4 * This); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback4, BeforeGarbageCollection) - HRESULT ( STDMETHODCALLTYPE *BeforeGarbageCollection )( + HRESULT ( STDMETHODCALLTYPE *BeforeGarbageCollection )( ICorDebugManagedCallback4 * This, /* [in] */ ICorDebugProcess *pProcess); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback4, AfterGarbageCollection) - HRESULT ( STDMETHODCALLTYPE *AfterGarbageCollection )( + HRESULT ( STDMETHODCALLTYPE *AfterGarbageCollection )( ICorDebugManagedCallback4 * This, /* [in] */ ICorDebugProcess *pProcess); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback4, DataBreakpoint) - HRESULT ( STDMETHODCALLTYPE *DataBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *DataBreakpoint )( ICorDebugManagedCallback4 * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugThread *pThread, /* [in] */ BYTE *pContext, /* [in] */ ULONG32 contextSize); - + END_INTERFACE } ICorDebugManagedCallback4Vtbl; @@ -4033,29 +4040,29 @@ EXTERN_C const IID IID_ICorDebugManagedCallback4; CONST_VTBL struct ICorDebugManagedCallback4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugManagedCallback4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugManagedCallback4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugManagedCallback4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugManagedCallback4_BeforeGarbageCollection(This,pProcess) \ - ( (This)->lpVtbl -> BeforeGarbageCollection(This,pProcess) ) + ( (This)->lpVtbl -> BeforeGarbageCollection(This,pProcess) ) #define ICorDebugManagedCallback4_AfterGarbageCollection(This,pProcess) \ - ( (This)->lpVtbl -> AfterGarbageCollection(This,pProcess) ) + ( (This)->lpVtbl -> AfterGarbageCollection(This,pProcess) ) #define ICorDebugManagedCallback4_DataBreakpoint(This,pProcess,pThread,pContext,contextSize) \ - ( (This)->lpVtbl -> DataBreakpoint(This,pProcess,pThread,pContext,contextSize) ) + ( (This)->lpVtbl -> DataBreakpoint(This,pProcess,pThread,pContext,contextSize) ) #endif /* COBJMACROS */ @@ -4069,9 +4076,9 @@ EXTERN_C const IID IID_ICorDebugManagedCallback4; /* interface __MIDL_itf_cordebug_0000_0018 */ -/* [local] */ +/* [local] */ -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0018_v0_0_c_ifspec; @@ -4081,9 +4088,9 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0018_v0_0_s_ifspec; #define __ICorDebugManagedCallback2_INTERFACE_DEFINED__ /* interface ICorDebugManagedCallback2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugExceptionCallbackType { DEBUG_EXCEPTION_FIRST_CHANCE = 1, @@ -4092,14 +4099,14 @@ enum CorDebugExceptionCallbackType DEBUG_EXCEPTION_UNHANDLED = 4 } CorDebugExceptionCallbackType; -typedef +typedef enum CorDebugExceptionFlags { DEBUG_EXCEPTION_NONE = 0, DEBUG_EXCEPTION_CAN_BE_INTERCEPTED = 0x1 } CorDebugExceptionFlags; -typedef +typedef enum CorDebugExceptionUnwindCallbackType { DEBUG_EXCEPTION_UNWIND_BEGIN = 1, @@ -4110,109 +4117,109 @@ enum CorDebugExceptionUnwindCallbackType EXTERN_C const IID IID_ICorDebugManagedCallback2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("250E5EEA-DB5C-4C76-B6F3-8C46F12E3203") ICorDebugManagedCallback2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE FunctionRemapOpportunity( + virtual HRESULT STDMETHODCALLTYPE FunctionRemapOpportunity( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pOldFunction, /* [in] */ ICorDebugFunction *pNewFunction, /* [in] */ ULONG32 oldILOffset) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateConnection( + + virtual HRESULT STDMETHODCALLTYPE CreateConnection( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId, /* [in] */ WCHAR *pConnName) = 0; - - virtual HRESULT STDMETHODCALLTYPE ChangeConnection( + + virtual HRESULT STDMETHODCALLTYPE ChangeConnection( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId) = 0; - - virtual HRESULT STDMETHODCALLTYPE DestroyConnection( + + virtual HRESULT STDMETHODCALLTYPE DestroyConnection( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId) = 0; - - virtual HRESULT STDMETHODCALLTYPE Exception( + + virtual HRESULT STDMETHODCALLTYPE Exception( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFrame *pFrame, /* [in] */ ULONG32 nOffset, /* [in] */ CorDebugExceptionCallbackType dwEventType, /* [in] */ DWORD dwFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE ExceptionUnwind( + + virtual HRESULT STDMETHODCALLTYPE ExceptionUnwind( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ CorDebugExceptionUnwindCallbackType dwEventType, /* [in] */ DWORD dwFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE FunctionRemapComplete( + + virtual HRESULT STDMETHODCALLTYPE FunctionRemapComplete( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pFunction) = 0; - - virtual HRESULT STDMETHODCALLTYPE MDANotification( + + virtual HRESULT STDMETHODCALLTYPE MDANotification( /* [in] */ ICorDebugController *pController, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugMDA *pMDA) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugManagedCallback2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugManagedCallback2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugManagedCallback2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugManagedCallback2 * This); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback2, FunctionRemapOpportunity) - HRESULT ( STDMETHODCALLTYPE *FunctionRemapOpportunity )( + HRESULT ( STDMETHODCALLTYPE *FunctionRemapOpportunity )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pOldFunction, /* [in] */ ICorDebugFunction *pNewFunction, /* [in] */ ULONG32 oldILOffset); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback2, CreateConnection) - HRESULT ( STDMETHODCALLTYPE *CreateConnection )( + HRESULT ( STDMETHODCALLTYPE *CreateConnection )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId, /* [in] */ WCHAR *pConnName); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback2, ChangeConnection) - HRESULT ( STDMETHODCALLTYPE *ChangeConnection )( + HRESULT ( STDMETHODCALLTYPE *ChangeConnection )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback2, DestroyConnection) - HRESULT ( STDMETHODCALLTYPE *DestroyConnection )( + HRESULT ( STDMETHODCALLTYPE *DestroyConnection )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback2, Exception) - HRESULT ( STDMETHODCALLTYPE *Exception )( + HRESULT ( STDMETHODCALLTYPE *Exception )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, @@ -4220,29 +4227,29 @@ EXTERN_C const IID IID_ICorDebugManagedCallback2; /* [in] */ ULONG32 nOffset, /* [in] */ CorDebugExceptionCallbackType dwEventType, /* [in] */ DWORD dwFlags); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback2, ExceptionUnwind) - HRESULT ( STDMETHODCALLTYPE *ExceptionUnwind )( + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwind )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ CorDebugExceptionUnwindCallbackType dwEventType, /* [in] */ DWORD dwFlags); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback2, FunctionRemapComplete) - HRESULT ( STDMETHODCALLTYPE *FunctionRemapComplete )( + HRESULT ( STDMETHODCALLTYPE *FunctionRemapComplete )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pFunction); - + DECLSPEC_XFGVIRT(ICorDebugManagedCallback2, MDANotification) - HRESULT ( STDMETHODCALLTYPE *MDANotification )( + HRESULT ( STDMETHODCALLTYPE *MDANotification )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugController *pController, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugMDA *pMDA); - + END_INTERFACE } ICorDebugManagedCallback2Vtbl; @@ -4251,44 +4258,44 @@ EXTERN_C const IID IID_ICorDebugManagedCallback2; CONST_VTBL struct ICorDebugManagedCallback2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugManagedCallback2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugManagedCallback2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugManagedCallback2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugManagedCallback2_FunctionRemapOpportunity(This,pAppDomain,pThread,pOldFunction,pNewFunction,oldILOffset) \ - ( (This)->lpVtbl -> FunctionRemapOpportunity(This,pAppDomain,pThread,pOldFunction,pNewFunction,oldILOffset) ) + ( (This)->lpVtbl -> FunctionRemapOpportunity(This,pAppDomain,pThread,pOldFunction,pNewFunction,oldILOffset) ) #define ICorDebugManagedCallback2_CreateConnection(This,pProcess,dwConnectionId,pConnName) \ - ( (This)->lpVtbl -> CreateConnection(This,pProcess,dwConnectionId,pConnName) ) + ( (This)->lpVtbl -> CreateConnection(This,pProcess,dwConnectionId,pConnName) ) #define ICorDebugManagedCallback2_ChangeConnection(This,pProcess,dwConnectionId) \ - ( (This)->lpVtbl -> ChangeConnection(This,pProcess,dwConnectionId) ) + ( (This)->lpVtbl -> ChangeConnection(This,pProcess,dwConnectionId) ) #define ICorDebugManagedCallback2_DestroyConnection(This,pProcess,dwConnectionId) \ - ( (This)->lpVtbl -> DestroyConnection(This,pProcess,dwConnectionId) ) + ( (This)->lpVtbl -> DestroyConnection(This,pProcess,dwConnectionId) ) #define ICorDebugManagedCallback2_Exception(This,pAppDomain,pThread,pFrame,nOffset,dwEventType,dwFlags) \ - ( (This)->lpVtbl -> Exception(This,pAppDomain,pThread,pFrame,nOffset,dwEventType,dwFlags) ) + ( (This)->lpVtbl -> Exception(This,pAppDomain,pThread,pFrame,nOffset,dwEventType,dwFlags) ) #define ICorDebugManagedCallback2_ExceptionUnwind(This,pAppDomain,pThread,dwEventType,dwFlags) \ - ( (This)->lpVtbl -> ExceptionUnwind(This,pAppDomain,pThread,dwEventType,dwFlags) ) + ( (This)->lpVtbl -> ExceptionUnwind(This,pAppDomain,pThread,dwEventType,dwFlags) ) #define ICorDebugManagedCallback2_FunctionRemapComplete(This,pAppDomain,pThread,pFunction) \ - ( (This)->lpVtbl -> FunctionRemapComplete(This,pAppDomain,pThread,pFunction) ) + ( (This)->lpVtbl -> FunctionRemapComplete(This,pAppDomain,pThread,pFunction) ) #define ICorDebugManagedCallback2_MDANotification(This,pController,pThread,pMDA) \ - ( (This)->lpVtbl -> MDANotification(This,pController,pThread,pMDA) ) + ( (This)->lpVtbl -> MDANotification(This,pController,pThread,pMDA) ) #endif /* COBJMACROS */ @@ -4302,7 +4309,7 @@ EXTERN_C const IID IID_ICorDebugManagedCallback2; /* interface __MIDL_itf_cordebug_0000_0019 */ -/* [local] */ +/* [local] */ #pragma warning(pop) @@ -4314,51 +4321,51 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0019_v0_0_s_ifspec; #define __ICorDebugUnmanagedCallback_INTERFACE_DEFINED__ /* interface ICorDebugUnmanagedCallback */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugUnmanagedCallback; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("5263E909-8CB5-11d3-BD2F-0000F80849BD") ICorDebugUnmanagedCallback : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE DebugEvent( + virtual HRESULT STDMETHODCALLTYPE DebugEvent( /* [in] */ LPDEBUG_EVENT pDebugEvent, /* [in] */ BOOL fOutOfBand) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugUnmanagedCallbackVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugUnmanagedCallback * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugUnmanagedCallback * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugUnmanagedCallback * This); - + DECLSPEC_XFGVIRT(ICorDebugUnmanagedCallback, DebugEvent) - HRESULT ( STDMETHODCALLTYPE *DebugEvent )( + HRESULT ( STDMETHODCALLTYPE *DebugEvent )( ICorDebugUnmanagedCallback * This, /* [in] */ LPDEBUG_EVENT pDebugEvent, /* [in] */ BOOL fOutOfBand); - + END_INTERFACE } ICorDebugUnmanagedCallbackVtbl; @@ -4367,23 +4374,23 @@ EXTERN_C const IID IID_ICorDebugUnmanagedCallback; CONST_VTBL struct ICorDebugUnmanagedCallbackVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugUnmanagedCallback_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugUnmanagedCallback_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugUnmanagedCallback_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugUnmanagedCallback_DebugEvent(This,pDebugEvent,fOutOfBand) \ - ( (This)->lpVtbl -> DebugEvent(This,pDebugEvent,fOutOfBand) ) + ( (This)->lpVtbl -> DebugEvent(This,pDebugEvent,fOutOfBand) ) #endif /* COBJMACROS */ @@ -4397,15 +4404,15 @@ EXTERN_C const IID IID_ICorDebugUnmanagedCallback; /* interface __MIDL_itf_cordebug_0000_0020 */ -/* [local] */ +/* [local] */ -typedef +typedef enum CorDebugCreateProcessFlags { DEBUG_NO_SPECIAL_OPTIONS = 0 } CorDebugCreateProcessFlags; -typedef +typedef enum CorDebugHandleType { HANDLE_STRONG = 1, @@ -4414,7 +4421,7 @@ enum CorDebugHandleType } CorDebugHandleType; #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0020_v0_0_c_ifspec; @@ -4424,28 +4431,28 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0020_v0_0_s_ifspec; #define __ICorDebug_INTERFACE_DEFINED__ /* interface ICorDebug */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebug; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("3d6f5f61-7538-11d3-8d5b-00104b35e7ef") ICorDebug : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Initialize( void) = 0; - + virtual HRESULT STDMETHODCALLTYPE Terminate( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetManagedHandler( + + virtual HRESULT STDMETHODCALLTYPE SetManagedHandler( /* [in] */ ICorDebugManagedCallback *pCallback) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetUnmanagedHandler( + + virtual HRESULT STDMETHODCALLTYPE SetUnmanagedHandler( /* [in] */ ICorDebugUnmanagedCallback *pCallback) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateProcess( + + virtual HRESULT STDMETHODCALLTYPE CreateProcess( /* [in] */ LPCWSTR lpApplicationName, /* [in] */ LPWSTR lpCommandLine, /* [in] */ LPSECURITY_ATTRIBUTES lpProcessAttributes, @@ -4458,67 +4465,67 @@ EXTERN_C const IID IID_ICorDebug; /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, /* [in] */ CorDebugCreateProcessFlags debuggingFlags, /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE DebugActiveProcess( + + virtual HRESULT STDMETHODCALLTYPE DebugActiveProcess( /* [in] */ DWORD id, /* [in] */ BOOL win32Attach, /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateProcesses( + + virtual HRESULT STDMETHODCALLTYPE EnumerateProcesses( /* [out] */ ICorDebugProcessEnum **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetProcess( + + virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [in] */ DWORD dwProcessId, /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE CanLaunchOrAttach( + + virtual HRESULT STDMETHODCALLTYPE CanLaunchOrAttach( /* [in] */ DWORD dwProcessId, /* [in] */ BOOL win32DebuggingEnabled) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebug * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebug * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebug * This); - + DECLSPEC_XFGVIRT(ICorDebug, Initialize) - HRESULT ( STDMETHODCALLTYPE *Initialize )( + HRESULT ( STDMETHODCALLTYPE *Initialize )( ICorDebug * This); - + DECLSPEC_XFGVIRT(ICorDebug, Terminate) - HRESULT ( STDMETHODCALLTYPE *Terminate )( + HRESULT ( STDMETHODCALLTYPE *Terminate )( ICorDebug * This); - + DECLSPEC_XFGVIRT(ICorDebug, SetManagedHandler) - HRESULT ( STDMETHODCALLTYPE *SetManagedHandler )( + HRESULT ( STDMETHODCALLTYPE *SetManagedHandler )( ICorDebug * This, /* [in] */ ICorDebugManagedCallback *pCallback); - + DECLSPEC_XFGVIRT(ICorDebug, SetUnmanagedHandler) - HRESULT ( STDMETHODCALLTYPE *SetUnmanagedHandler )( + HRESULT ( STDMETHODCALLTYPE *SetUnmanagedHandler )( ICorDebug * This, /* [in] */ ICorDebugUnmanagedCallback *pCallback); - + DECLSPEC_XFGVIRT(ICorDebug, CreateProcess) - HRESULT ( STDMETHODCALLTYPE *CreateProcess )( + HRESULT ( STDMETHODCALLTYPE *CreateProcess )( ICorDebug * This, /* [in] */ LPCWSTR lpApplicationName, /* [in] */ LPWSTR lpCommandLine, @@ -4532,31 +4539,31 @@ EXTERN_C const IID IID_ICorDebug; /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, /* [in] */ CorDebugCreateProcessFlags debuggingFlags, /* [out] */ ICorDebugProcess **ppProcess); - + DECLSPEC_XFGVIRT(ICorDebug, DebugActiveProcess) - HRESULT ( STDMETHODCALLTYPE *DebugActiveProcess )( + HRESULT ( STDMETHODCALLTYPE *DebugActiveProcess )( ICorDebug * This, /* [in] */ DWORD id, /* [in] */ BOOL win32Attach, /* [out] */ ICorDebugProcess **ppProcess); - + DECLSPEC_XFGVIRT(ICorDebug, EnumerateProcesses) - HRESULT ( STDMETHODCALLTYPE *EnumerateProcesses )( + HRESULT ( STDMETHODCALLTYPE *EnumerateProcesses )( ICorDebug * This, /* [out] */ ICorDebugProcessEnum **ppProcess); - + DECLSPEC_XFGVIRT(ICorDebug, GetProcess) - HRESULT ( STDMETHODCALLTYPE *GetProcess )( + HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebug * This, /* [in] */ DWORD dwProcessId, /* [out] */ ICorDebugProcess **ppProcess); - + DECLSPEC_XFGVIRT(ICorDebug, CanLaunchOrAttach) - HRESULT ( STDMETHODCALLTYPE *CanLaunchOrAttach )( + HRESULT ( STDMETHODCALLTYPE *CanLaunchOrAttach )( ICorDebug * This, /* [in] */ DWORD dwProcessId, /* [in] */ BOOL win32DebuggingEnabled); - + END_INTERFACE } ICorDebugVtbl; @@ -4565,47 +4572,47 @@ EXTERN_C const IID IID_ICorDebug; CONST_VTBL struct ICorDebugVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebug_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebug_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebug_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebug_Initialize(This) \ - ( (This)->lpVtbl -> Initialize(This) ) + ( (This)->lpVtbl -> Initialize(This) ) #define ICorDebug_Terminate(This) \ - ( (This)->lpVtbl -> Terminate(This) ) + ( (This)->lpVtbl -> Terminate(This) ) #define ICorDebug_SetManagedHandler(This,pCallback) \ - ( (This)->lpVtbl -> SetManagedHandler(This,pCallback) ) + ( (This)->lpVtbl -> SetManagedHandler(This,pCallback) ) #define ICorDebug_SetUnmanagedHandler(This,pCallback) \ - ( (This)->lpVtbl -> SetUnmanagedHandler(This,pCallback) ) + ( (This)->lpVtbl -> SetUnmanagedHandler(This,pCallback) ) #define ICorDebug_CreateProcess(This,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) \ - ( (This)->lpVtbl -> CreateProcess(This,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) ) + ( (This)->lpVtbl -> CreateProcess(This,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) ) #define ICorDebug_DebugActiveProcess(This,id,win32Attach,ppProcess) \ - ( (This)->lpVtbl -> DebugActiveProcess(This,id,win32Attach,ppProcess) ) + ( (This)->lpVtbl -> DebugActiveProcess(This,id,win32Attach,ppProcess) ) #define ICorDebug_EnumerateProcesses(This,ppProcess) \ - ( (This)->lpVtbl -> EnumerateProcesses(This,ppProcess) ) + ( (This)->lpVtbl -> EnumerateProcesses(This,ppProcess) ) #define ICorDebug_GetProcess(This,dwProcessId,ppProcess) \ - ( (This)->lpVtbl -> GetProcess(This,dwProcessId,ppProcess) ) + ( (This)->lpVtbl -> GetProcess(This,dwProcessId,ppProcess) ) #define ICorDebug_CanLaunchOrAttach(This,dwProcessId,win32DebuggingEnabled) \ - ( (This)->lpVtbl -> CanLaunchOrAttach(This,dwProcessId,win32DebuggingEnabled) ) + ( (This)->lpVtbl -> CanLaunchOrAttach(This,dwProcessId,win32DebuggingEnabled) ) #endif /* COBJMACROS */ @@ -4619,7 +4626,7 @@ EXTERN_C const IID IID_ICorDebug; /* interface __MIDL_itf_cordebug_0000_0021 */ -/* [local] */ +/* [local] */ #pragma warning(pop) @@ -4631,57 +4638,57 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0021_v0_0_s_ifspec; #define __ICorDebugRemoteTarget_INTERFACE_DEFINED__ /* interface ICorDebugRemoteTarget */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugRemoteTarget; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("C3ED8383-5A49-4cf5-B4B7-01864D9E582D") ICorDebugRemoteTarget : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetHostName( + virtual HRESULT STDMETHODCALLTYPE GetHostName( /* [in] */ ULONG32 cchHostName, - /* [annotation][out] */ + /* [annotation][out] */ _Out_ ULONG32 *pcchHostName, - /* [annotation][length_is][size_is][out] */ + /* [annotation][length_is][size_is][out] */ _Out_writes_to_opt_(cchHostName, *pcchHostName) WCHAR szHostName[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugRemoteTargetVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRemoteTarget * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRemoteTarget * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRemoteTarget * This); - + DECLSPEC_XFGVIRT(ICorDebugRemoteTarget, GetHostName) - HRESULT ( STDMETHODCALLTYPE *GetHostName )( + HRESULT ( STDMETHODCALLTYPE *GetHostName )( ICorDebugRemoteTarget * This, /* [in] */ ULONG32 cchHostName, - /* [annotation][out] */ + /* [annotation][out] */ _Out_ ULONG32 *pcchHostName, - /* [annotation][length_is][size_is][out] */ + /* [annotation][length_is][size_is][out] */ _Out_writes_to_opt_(cchHostName, *pcchHostName) WCHAR szHostName[ ]); - + END_INTERFACE } ICorDebugRemoteTargetVtbl; @@ -4690,23 +4697,23 @@ EXTERN_C const IID IID_ICorDebugRemoteTarget; CONST_VTBL struct ICorDebugRemoteTargetVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugRemoteTarget_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRemoteTarget_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRemoteTarget_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRemoteTarget_GetHostName(This,cchHostName,pcchHostName,szHostName) \ - ( (This)->lpVtbl -> GetHostName(This,cchHostName,pcchHostName,szHostName) ) + ( (This)->lpVtbl -> GetHostName(This,cchHostName,pcchHostName,szHostName) ) #endif /* COBJMACROS */ @@ -4723,21 +4730,21 @@ EXTERN_C const IID IID_ICorDebugRemoteTarget; #define __ICorDebugRemote_INTERFACE_DEFINED__ /* interface ICorDebugRemote */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugRemote; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("D5EBB8E2-7BBE-4c1d-98A6-A3C04CBDEF64") ICorDebugRemote : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CreateProcessEx( + virtual HRESULT STDMETHODCALLTYPE CreateProcessEx( /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, /* [in] */ LPCWSTR lpApplicationName, - /* [annotation][in] */ + /* [annotation][in] */ _In_ LPWSTR lpCommandLine, /* [in] */ LPSECURITY_ATTRIBUTES lpProcessAttributes, /* [in] */ LPSECURITY_ATTRIBUTES lpThreadAttributes, @@ -4749,43 +4756,43 @@ EXTERN_C const IID IID_ICorDebugRemote; /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, /* [in] */ CorDebugCreateProcessFlags debuggingFlags, /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE DebugActiveProcessEx( + + virtual HRESULT STDMETHODCALLTYPE DebugActiveProcessEx( /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, /* [in] */ DWORD dwProcessId, /* [in] */ BOOL fWin32Attach, /* [out] */ ICorDebugProcess **ppProcess) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugRemoteVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRemote * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRemote * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRemote * This); - + DECLSPEC_XFGVIRT(ICorDebugRemote, CreateProcessEx) - HRESULT ( STDMETHODCALLTYPE *CreateProcessEx )( + HRESULT ( STDMETHODCALLTYPE *CreateProcessEx )( ICorDebugRemote * This, /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, /* [in] */ LPCWSTR lpApplicationName, - /* [annotation][in] */ + /* [annotation][in] */ _In_ LPWSTR lpCommandLine, /* [in] */ LPSECURITY_ATTRIBUTES lpProcessAttributes, /* [in] */ LPSECURITY_ATTRIBUTES lpThreadAttributes, @@ -4797,15 +4804,15 @@ EXTERN_C const IID IID_ICorDebugRemote; /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, /* [in] */ CorDebugCreateProcessFlags debuggingFlags, /* [out] */ ICorDebugProcess **ppProcess); - + DECLSPEC_XFGVIRT(ICorDebugRemote, DebugActiveProcessEx) - HRESULT ( STDMETHODCALLTYPE *DebugActiveProcessEx )( + HRESULT ( STDMETHODCALLTYPE *DebugActiveProcessEx )( ICorDebugRemote * This, /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, /* [in] */ DWORD dwProcessId, /* [in] */ BOOL fWin32Attach, /* [out] */ ICorDebugProcess **ppProcess); - + END_INTERFACE } ICorDebugRemoteVtbl; @@ -4814,26 +4821,26 @@ EXTERN_C const IID IID_ICorDebugRemote; CONST_VTBL struct ICorDebugRemoteVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugRemote_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRemote_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRemote_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRemote_CreateProcessEx(This,pRemoteTarget,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) \ - ( (This)->lpVtbl -> CreateProcessEx(This,pRemoteTarget,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) ) + ( (This)->lpVtbl -> CreateProcessEx(This,pRemoteTarget,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) ) #define ICorDebugRemote_DebugActiveProcessEx(This,pRemoteTarget,dwProcessId,fWin32Attach,ppProcess) \ - ( (This)->lpVtbl -> DebugActiveProcessEx(This,pRemoteTarget,dwProcessId,fWin32Attach,ppProcess) ) + ( (This)->lpVtbl -> DebugActiveProcessEx(This,pRemoteTarget,dwProcessId,fWin32Attach,ppProcess) ) #endif /* COBJMACROS */ @@ -4847,7 +4854,7 @@ EXTERN_C const IID IID_ICorDebugRemote; /* interface __MIDL_itf_cordebug_0000_0023 */ -/* [local] */ +/* [local] */ typedef struct _COR_VERSION { @@ -4866,9 +4873,9 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0023_v0_0_s_ifspec; #define __ICorDebug2_INTERFACE_DEFINED__ /* interface ICorDebug2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugInterfaceVersion { CorDebugInvalidVersion = 0, @@ -4962,35 +4969,35 @@ enum CorDebugInterfaceVersion EXTERN_C const IID IID_ICorDebug2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("ECCCCF2E-B286-4b3e-A983-860A8793D105") ICorDebug2 : public IUnknown { public: }; - - + + #else /* C style interface */ typedef struct ICorDebug2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebug2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebug2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebug2 * This); - + END_INTERFACE } ICorDebug2Vtbl; @@ -4999,19 +5006,19 @@ EXTERN_C const IID IID_ICorDebug2; CONST_VTBL struct ICorDebug2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebug2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebug2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebug2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #endif /* COBJMACROS */ @@ -5026,13 +5033,13 @@ EXTERN_C const IID IID_ICorDebug2; /* interface __MIDL_itf_cordebug_0000_0024 */ -/* [local] */ +/* [local] */ -typedef +typedef enum CorDebugThreadState { THREAD_RUN = 0, - THREAD_SUSPEND = ( THREAD_RUN + 1 ) + THREAD_SUSPEND = ( THREAD_RUN + 1 ) } CorDebugThreadState; @@ -5044,131 +5051,131 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0024_v0_0_s_ifspec; #define __ICorDebugController_INTERFACE_DEFINED__ /* interface ICorDebugController */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugController; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("3d6f5f62-7538-11d3-8d5b-00104b35e7ef") ICorDebugController : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE Stop( + virtual HRESULT STDMETHODCALLTYPE Stop( /* [in] */ DWORD dwTimeoutIgnored) = 0; - - virtual HRESULT STDMETHODCALLTYPE Continue( + + virtual HRESULT STDMETHODCALLTYPE Continue( /* [in] */ BOOL fIsOutOfBand) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsRunning( + + virtual HRESULT STDMETHODCALLTYPE IsRunning( /* [out] */ BOOL *pbRunning) = 0; - - virtual HRESULT STDMETHODCALLTYPE HasQueuedCallbacks( + + virtual HRESULT STDMETHODCALLTYPE HasQueuedCallbacks( /* [in] */ ICorDebugThread *pThread, /* [out] */ BOOL *pbQueued) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateThreads( + + virtual HRESULT STDMETHODCALLTYPE EnumerateThreads( /* [out] */ ICorDebugThreadEnum **ppThreads) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetAllThreadsDebugState( + + virtual HRESULT STDMETHODCALLTYPE SetAllThreadsDebugState( /* [in] */ CorDebugThreadState state, /* [in] */ ICorDebugThread *pExceptThisThread) = 0; - + virtual HRESULT STDMETHODCALLTYPE Detach( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE Terminate( + + virtual HRESULT STDMETHODCALLTYPE Terminate( /* [in] */ UINT exitCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE CanCommitChanges( + + virtual HRESULT STDMETHODCALLTYPE CanCommitChanges( /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError) = 0; - - virtual HRESULT STDMETHODCALLTYPE CommitChanges( + + virtual HRESULT STDMETHODCALLTYPE CommitChanges( /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugControllerVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugController * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugController * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugController * This); - + DECLSPEC_XFGVIRT(ICorDebugController, Stop) - HRESULT ( STDMETHODCALLTYPE *Stop )( + HRESULT ( STDMETHODCALLTYPE *Stop )( ICorDebugController * This, /* [in] */ DWORD dwTimeoutIgnored); - + DECLSPEC_XFGVIRT(ICorDebugController, Continue) - HRESULT ( STDMETHODCALLTYPE *Continue )( + HRESULT ( STDMETHODCALLTYPE *Continue )( ICorDebugController * This, /* [in] */ BOOL fIsOutOfBand); - + DECLSPEC_XFGVIRT(ICorDebugController, IsRunning) - HRESULT ( STDMETHODCALLTYPE *IsRunning )( + HRESULT ( STDMETHODCALLTYPE *IsRunning )( ICorDebugController * This, /* [out] */ BOOL *pbRunning); - + DECLSPEC_XFGVIRT(ICorDebugController, HasQueuedCallbacks) - HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( + HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( ICorDebugController * This, /* [in] */ ICorDebugThread *pThread, /* [out] */ BOOL *pbQueued); - + DECLSPEC_XFGVIRT(ICorDebugController, EnumerateThreads) - HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( + HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( ICorDebugController * This, /* [out] */ ICorDebugThreadEnum **ppThreads); - + DECLSPEC_XFGVIRT(ICorDebugController, SetAllThreadsDebugState) - HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( + HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( ICorDebugController * This, /* [in] */ CorDebugThreadState state, /* [in] */ ICorDebugThread *pExceptThisThread); - + DECLSPEC_XFGVIRT(ICorDebugController, Detach) - HRESULT ( STDMETHODCALLTYPE *Detach )( + HRESULT ( STDMETHODCALLTYPE *Detach )( ICorDebugController * This); - + DECLSPEC_XFGVIRT(ICorDebugController, Terminate) - HRESULT ( STDMETHODCALLTYPE *Terminate )( + HRESULT ( STDMETHODCALLTYPE *Terminate )( ICorDebugController * This, /* [in] */ UINT exitCode); - + DECLSPEC_XFGVIRT(ICorDebugController, CanCommitChanges) - HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( + HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( ICorDebugController * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); - + DECLSPEC_XFGVIRT(ICorDebugController, CommitChanges) - HRESULT ( STDMETHODCALLTYPE *CommitChanges )( + HRESULT ( STDMETHODCALLTYPE *CommitChanges )( ICorDebugController * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); - + END_INTERFACE } ICorDebugControllerVtbl; @@ -5177,50 +5184,50 @@ EXTERN_C const IID IID_ICorDebugController; CONST_VTBL struct ICorDebugControllerVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugController_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugController_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugController_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugController_Stop(This,dwTimeoutIgnored) \ - ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) + ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) #define ICorDebugController_Continue(This,fIsOutOfBand) \ - ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) + ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) #define ICorDebugController_IsRunning(This,pbRunning) \ - ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) + ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) #define ICorDebugController_HasQueuedCallbacks(This,pThread,pbQueued) \ - ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) + ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) #define ICorDebugController_EnumerateThreads(This,ppThreads) \ - ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) + ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) #define ICorDebugController_SetAllThreadsDebugState(This,state,pExceptThisThread) \ - ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) + ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) #define ICorDebugController_Detach(This) \ - ( (This)->lpVtbl -> Detach(This) ) + ( (This)->lpVtbl -> Detach(This) ) #define ICorDebugController_Terminate(This,exitCode) \ - ( (This)->lpVtbl -> Terminate(This,exitCode) ) + ( (This)->lpVtbl -> Terminate(This,exitCode) ) #define ICorDebugController_CanCommitChanges(This,cSnapshots,pSnapshots,pError) \ - ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) + ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugController_CommitChanges(This,cSnapshots,pSnapshots,pError) \ - ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) + ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) #endif /* COBJMACROS */ @@ -5234,10 +5241,10 @@ EXTERN_C const IID IID_ICorDebugController; /* interface __MIDL_itf_cordebug_0000_0025 */ -/* [local] */ +/* [local] */ #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0025_v0_0_c_ifspec; @@ -5247,180 +5254,180 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0025_v0_0_s_ifspec; #define __ICorDebugAppDomain_INTERFACE_DEFINED__ /* interface ICorDebugAppDomain */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomain; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("3d6f5f63-7538-11d3-8d5b-00104b35e7ef") ICorDebugAppDomain : public ICorDebugController { public: - virtual HRESULT STDMETHODCALLTYPE GetProcess( + virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateAssemblies( + + virtual HRESULT STDMETHODCALLTYPE EnumerateAssemblies( /* [out] */ ICorDebugAssemblyEnum **ppAssemblies) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetModuleFromMetaDataInterface( + + virtual HRESULT STDMETHODCALLTYPE GetModuleFromMetaDataInterface( /* [in] */ IUnknown *pIMetaData, /* [out] */ ICorDebugModule **ppModule) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateBreakpoints( + + virtual HRESULT STDMETHODCALLTYPE EnumerateBreakpoints( /* [out] */ ICorDebugBreakpointEnum **ppBreakpoints) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateSteppers( + + virtual HRESULT STDMETHODCALLTYPE EnumerateSteppers( /* [out] */ ICorDebugStepperEnum **ppSteppers) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsAttached( + + virtual HRESULT STDMETHODCALLTYPE IsAttached( /* [out] */ BOOL *pbAttached) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetName( + + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetObject( + + virtual HRESULT STDMETHODCALLTYPE GetObject( /* [out] */ ICorDebugValue **ppObject) = 0; - + virtual HRESULT STDMETHODCALLTYPE Attach( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetID( + + virtual HRESULT STDMETHODCALLTYPE GetID( /* [out] */ ULONG32 *pId) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAppDomainVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomain * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomain * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomain * This); - + DECLSPEC_XFGVIRT(ICorDebugController, Stop) - HRESULT ( STDMETHODCALLTYPE *Stop )( + HRESULT ( STDMETHODCALLTYPE *Stop )( ICorDebugAppDomain * This, /* [in] */ DWORD dwTimeoutIgnored); - + DECLSPEC_XFGVIRT(ICorDebugController, Continue) - HRESULT ( STDMETHODCALLTYPE *Continue )( + HRESULT ( STDMETHODCALLTYPE *Continue )( ICorDebugAppDomain * This, /* [in] */ BOOL fIsOutOfBand); - + DECLSPEC_XFGVIRT(ICorDebugController, IsRunning) - HRESULT ( STDMETHODCALLTYPE *IsRunning )( + HRESULT ( STDMETHODCALLTYPE *IsRunning )( ICorDebugAppDomain * This, /* [out] */ BOOL *pbRunning); - + DECLSPEC_XFGVIRT(ICorDebugController, HasQueuedCallbacks) - HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( + HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( ICorDebugAppDomain * This, /* [in] */ ICorDebugThread *pThread, /* [out] */ BOOL *pbQueued); - + DECLSPEC_XFGVIRT(ICorDebugController, EnumerateThreads) - HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( + HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( ICorDebugAppDomain * This, /* [out] */ ICorDebugThreadEnum **ppThreads); - + DECLSPEC_XFGVIRT(ICorDebugController, SetAllThreadsDebugState) - HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( + HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( ICorDebugAppDomain * This, /* [in] */ CorDebugThreadState state, /* [in] */ ICorDebugThread *pExceptThisThread); - + DECLSPEC_XFGVIRT(ICorDebugController, Detach) - HRESULT ( STDMETHODCALLTYPE *Detach )( + HRESULT ( STDMETHODCALLTYPE *Detach )( ICorDebugAppDomain * This); - + DECLSPEC_XFGVIRT(ICorDebugController, Terminate) - HRESULT ( STDMETHODCALLTYPE *Terminate )( + HRESULT ( STDMETHODCALLTYPE *Terminate )( ICorDebugAppDomain * This, /* [in] */ UINT exitCode); - + DECLSPEC_XFGVIRT(ICorDebugController, CanCommitChanges) - HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( + HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( ICorDebugAppDomain * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); - + DECLSPEC_XFGVIRT(ICorDebugController, CommitChanges) - HRESULT ( STDMETHODCALLTYPE *CommitChanges )( + HRESULT ( STDMETHODCALLTYPE *CommitChanges )( ICorDebugAppDomain * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain, GetProcess) - HRESULT ( STDMETHODCALLTYPE *GetProcess )( + HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebugAppDomain * This, /* [out] */ ICorDebugProcess **ppProcess); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain, EnumerateAssemblies) - HRESULT ( STDMETHODCALLTYPE *EnumerateAssemblies )( + HRESULT ( STDMETHODCALLTYPE *EnumerateAssemblies )( ICorDebugAppDomain * This, /* [out] */ ICorDebugAssemblyEnum **ppAssemblies); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain, GetModuleFromMetaDataInterface) - HRESULT ( STDMETHODCALLTYPE *GetModuleFromMetaDataInterface )( + HRESULT ( STDMETHODCALLTYPE *GetModuleFromMetaDataInterface )( ICorDebugAppDomain * This, /* [in] */ IUnknown *pIMetaData, /* [out] */ ICorDebugModule **ppModule); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain, EnumerateBreakpoints) - HRESULT ( STDMETHODCALLTYPE *EnumerateBreakpoints )( + HRESULT ( STDMETHODCALLTYPE *EnumerateBreakpoints )( ICorDebugAppDomain * This, /* [out] */ ICorDebugBreakpointEnum **ppBreakpoints); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain, EnumerateSteppers) - HRESULT ( STDMETHODCALLTYPE *EnumerateSteppers )( + HRESULT ( STDMETHODCALLTYPE *EnumerateSteppers )( ICorDebugAppDomain * This, /* [out] */ ICorDebugStepperEnum **ppSteppers); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain, IsAttached) - HRESULT ( STDMETHODCALLTYPE *IsAttached )( + HRESULT ( STDMETHODCALLTYPE *IsAttached )( ICorDebugAppDomain * This, /* [out] */ BOOL *pbAttached); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain, GetName) - HRESULT ( STDMETHODCALLTYPE *GetName )( + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugAppDomain * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain, GetObject) - HRESULT ( STDMETHODCALLTYPE *GetObject )( + HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugAppDomain * This, /* [out] */ ICorDebugValue **ppObject); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain, Attach) - HRESULT ( STDMETHODCALLTYPE *Attach )( + HRESULT ( STDMETHODCALLTYPE *Attach )( ICorDebugAppDomain * This); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain, GetID) - HRESULT ( STDMETHODCALLTYPE *GetID )( + HRESULT ( STDMETHODCALLTYPE *GetID )( ICorDebugAppDomain * This, /* [out] */ ULONG32 *pId); - + END_INTERFACE } ICorDebugAppDomainVtbl; @@ -5429,81 +5436,81 @@ EXTERN_C const IID IID_ICorDebugAppDomain; CONST_VTBL struct ICorDebugAppDomainVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAppDomain_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomain_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomain_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomain_Stop(This,dwTimeoutIgnored) \ - ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) + ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) #define ICorDebugAppDomain_Continue(This,fIsOutOfBand) \ - ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) + ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) #define ICorDebugAppDomain_IsRunning(This,pbRunning) \ - ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) + ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) #define ICorDebugAppDomain_HasQueuedCallbacks(This,pThread,pbQueued) \ - ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) + ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) #define ICorDebugAppDomain_EnumerateThreads(This,ppThreads) \ - ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) + ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) #define ICorDebugAppDomain_SetAllThreadsDebugState(This,state,pExceptThisThread) \ - ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) + ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) #define ICorDebugAppDomain_Detach(This) \ - ( (This)->lpVtbl -> Detach(This) ) + ( (This)->lpVtbl -> Detach(This) ) #define ICorDebugAppDomain_Terminate(This,exitCode) \ - ( (This)->lpVtbl -> Terminate(This,exitCode) ) + ( (This)->lpVtbl -> Terminate(This,exitCode) ) #define ICorDebugAppDomain_CanCommitChanges(This,cSnapshots,pSnapshots,pError) \ - ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) + ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugAppDomain_CommitChanges(This,cSnapshots,pSnapshots,pError) \ - ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) + ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugAppDomain_GetProcess(This,ppProcess) \ - ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) + ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) #define ICorDebugAppDomain_EnumerateAssemblies(This,ppAssemblies) \ - ( (This)->lpVtbl -> EnumerateAssemblies(This,ppAssemblies) ) + ( (This)->lpVtbl -> EnumerateAssemblies(This,ppAssemblies) ) #define ICorDebugAppDomain_GetModuleFromMetaDataInterface(This,pIMetaData,ppModule) \ - ( (This)->lpVtbl -> GetModuleFromMetaDataInterface(This,pIMetaData,ppModule) ) + ( (This)->lpVtbl -> GetModuleFromMetaDataInterface(This,pIMetaData,ppModule) ) #define ICorDebugAppDomain_EnumerateBreakpoints(This,ppBreakpoints) \ - ( (This)->lpVtbl -> EnumerateBreakpoints(This,ppBreakpoints) ) + ( (This)->lpVtbl -> EnumerateBreakpoints(This,ppBreakpoints) ) #define ICorDebugAppDomain_EnumerateSteppers(This,ppSteppers) \ - ( (This)->lpVtbl -> EnumerateSteppers(This,ppSteppers) ) + ( (This)->lpVtbl -> EnumerateSteppers(This,ppSteppers) ) #define ICorDebugAppDomain_IsAttached(This,pbAttached) \ - ( (This)->lpVtbl -> IsAttached(This,pbAttached) ) + ( (This)->lpVtbl -> IsAttached(This,pbAttached) ) #define ICorDebugAppDomain_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugAppDomain_GetObject(This,ppObject) \ - ( (This)->lpVtbl -> GetObject(This,ppObject) ) + ( (This)->lpVtbl -> GetObject(This,ppObject) ) #define ICorDebugAppDomain_Attach(This) \ - ( (This)->lpVtbl -> Attach(This) ) + ( (This)->lpVtbl -> Attach(This) ) #define ICorDebugAppDomain_GetID(This,pId) \ - ( (This)->lpVtbl -> GetID(This,pId) ) + ( (This)->lpVtbl -> GetID(This,pId) ) #endif /* COBJMACROS */ @@ -5517,7 +5524,7 @@ EXTERN_C const IID IID_ICorDebugAppDomain; /* interface __MIDL_itf_cordebug_0000_0026 */ -/* [local] */ +/* [local] */ #pragma warning(pop) @@ -5529,67 +5536,67 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0026_v0_0_s_ifspec; #define __ICorDebugAppDomain2_INTERFACE_DEFINED__ /* interface ICorDebugAppDomain2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomain2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("096E81D5-ECDA-4202-83F5-C65980A9EF75") ICorDebugAppDomain2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetArrayOrPointerType( + virtual HRESULT STDMETHODCALLTYPE GetArrayOrPointerType( /* [in] */ CorElementType elementType, /* [in] */ ULONG32 nRank, /* [in] */ ICorDebugType *pTypeArg, /* [out] */ ICorDebugType **ppType) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunctionPointerType( + + virtual HRESULT STDMETHODCALLTYPE GetFunctionPointerType( /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [out] */ ICorDebugType **ppType) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAppDomain2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomain2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomain2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomain2 * This); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain2, GetArrayOrPointerType) - HRESULT ( STDMETHODCALLTYPE *GetArrayOrPointerType )( + HRESULT ( STDMETHODCALLTYPE *GetArrayOrPointerType )( ICorDebugAppDomain2 * This, /* [in] */ CorElementType elementType, /* [in] */ ULONG32 nRank, /* [in] */ ICorDebugType *pTypeArg, /* [out] */ ICorDebugType **ppType); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain2, GetFunctionPointerType) - HRESULT ( STDMETHODCALLTYPE *GetFunctionPointerType )( + HRESULT ( STDMETHODCALLTYPE *GetFunctionPointerType )( ICorDebugAppDomain2 * This, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [out] */ ICorDebugType **ppType); - + END_INTERFACE } ICorDebugAppDomain2Vtbl; @@ -5598,26 +5605,26 @@ EXTERN_C const IID IID_ICorDebugAppDomain2; CONST_VTBL struct ICorDebugAppDomain2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAppDomain2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomain2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomain2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomain2_GetArrayOrPointerType(This,elementType,nRank,pTypeArg,ppType) \ - ( (This)->lpVtbl -> GetArrayOrPointerType(This,elementType,nRank,pTypeArg,ppType) ) + ( (This)->lpVtbl -> GetArrayOrPointerType(This,elementType,nRank,pTypeArg,ppType) ) #define ICorDebugAppDomain2_GetFunctionPointerType(This,nTypeArgs,ppTypeArgs,ppType) \ - ( (This)->lpVtbl -> GetFunctionPointerType(This,nTypeArgs,ppTypeArgs,ppType) ) + ( (This)->lpVtbl -> GetFunctionPointerType(This,nTypeArgs,ppTypeArgs,ppType) ) #endif /* COBJMACROS */ @@ -5634,71 +5641,71 @@ EXTERN_C const IID IID_ICorDebugAppDomain2; #define __ICorDebugEnum_INTERFACE_DEFINED__ /* interface ICorDebugEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB01-8A68-11d2-983C-0000F808342D") ICorDebugEnum : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE Skip( + virtual HRESULT STDMETHODCALLTYPE Skip( /* [in] */ ULONG celt) = 0; - + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE Clone( + + virtual HRESULT STDMETHODCALLTYPE Clone( /* [out] */ ICorDebugEnum **ppEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCount( + + virtual HRESULT STDMETHODCALLTYPE GetCount( /* [out] */ ULONG *pcelt) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugEnum * This, /* [out] */ ULONG *pcelt); - + END_INTERFACE } ICorDebugEnumVtbl; @@ -5707,32 +5714,32 @@ EXTERN_C const IID IID_ICorDebugEnum; CONST_VTBL struct ICorDebugEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #endif /* COBJMACROS */ @@ -5749,72 +5756,72 @@ EXTERN_C const IID IID_ICorDebugEnum; #define __ICorDebugGuidToTypeEnum_INTERFACE_DEFINED__ /* interface ICorDebugGuidToTypeEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugGuidToTypeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("6164D242-1015-4BD6-8CBE-D0DBD4B8275A") ICorDebugGuidToTypeEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugGuidToTypeMapping values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugGuidToTypeEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugGuidToTypeEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugGuidToTypeEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugGuidToTypeEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugGuidToTypeEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugGuidToTypeEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugGuidToTypeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugGuidToTypeEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugGuidToTypeEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugGuidToTypeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugGuidToTypeMapping values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugGuidToTypeEnumVtbl; @@ -5823,36 +5830,36 @@ EXTERN_C const IID IID_ICorDebugGuidToTypeEnum; CONST_VTBL struct ICorDebugGuidToTypeEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugGuidToTypeEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugGuidToTypeEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugGuidToTypeEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugGuidToTypeEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugGuidToTypeEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugGuidToTypeEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugGuidToTypeEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugGuidToTypeEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -5869,61 +5876,61 @@ EXTERN_C const IID IID_ICorDebugGuidToTypeEnum; #define __ICorDebugAppDomain3_INTERFACE_DEFINED__ /* interface ICorDebugAppDomain3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomain3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("8CB96A16-B588-42E2-B71C-DD849FC2ECCC") ICorDebugAppDomain3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetCachedWinRTTypesForIIDs( + virtual HRESULT STDMETHODCALLTYPE GetCachedWinRTTypesForIIDs( /* [in] */ ULONG32 cReqTypes, /* [size_is][in] */ GUID *iidsToResolve, /* [out] */ ICorDebugTypeEnum **ppTypesEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCachedWinRTTypes( + + virtual HRESULT STDMETHODCALLTYPE GetCachedWinRTTypes( /* [out] */ ICorDebugGuidToTypeEnum **ppGuidToTypeEnum) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAppDomain3Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomain3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomain3 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomain3 * This); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain3, GetCachedWinRTTypesForIIDs) - HRESULT ( STDMETHODCALLTYPE *GetCachedWinRTTypesForIIDs )( + HRESULT ( STDMETHODCALLTYPE *GetCachedWinRTTypesForIIDs )( ICorDebugAppDomain3 * This, /* [in] */ ULONG32 cReqTypes, /* [size_is][in] */ GUID *iidsToResolve, /* [out] */ ICorDebugTypeEnum **ppTypesEnum); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain3, GetCachedWinRTTypes) - HRESULT ( STDMETHODCALLTYPE *GetCachedWinRTTypes )( + HRESULT ( STDMETHODCALLTYPE *GetCachedWinRTTypes )( ICorDebugAppDomain3 * This, /* [out] */ ICorDebugGuidToTypeEnum **ppGuidToTypeEnum); - + END_INTERFACE } ICorDebugAppDomain3Vtbl; @@ -5932,26 +5939,26 @@ EXTERN_C const IID IID_ICorDebugAppDomain3; CONST_VTBL struct ICorDebugAppDomain3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAppDomain3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomain3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomain3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomain3_GetCachedWinRTTypesForIIDs(This,cReqTypes,iidsToResolve,ppTypesEnum) \ - ( (This)->lpVtbl -> GetCachedWinRTTypesForIIDs(This,cReqTypes,iidsToResolve,ppTypesEnum) ) + ( (This)->lpVtbl -> GetCachedWinRTTypesForIIDs(This,cReqTypes,iidsToResolve,ppTypesEnum) ) #define ICorDebugAppDomain3_GetCachedWinRTTypes(This,ppGuidToTypeEnum) \ - ( (This)->lpVtbl -> GetCachedWinRTTypes(This,ppGuidToTypeEnum) ) + ( (This)->lpVtbl -> GetCachedWinRTTypes(This,ppGuidToTypeEnum) ) #endif /* COBJMACROS */ @@ -5968,51 +5975,51 @@ EXTERN_C const IID IID_ICorDebugAppDomain3; #define __ICorDebugAppDomain4_INTERFACE_DEFINED__ /* interface ICorDebugAppDomain4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomain4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("FB99CC40-83BE-4724-AB3B-768E796EBAC2") ICorDebugAppDomain4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetObjectForCCW( + virtual HRESULT STDMETHODCALLTYPE GetObjectForCCW( /* [in] */ CORDB_ADDRESS ccwPointer, /* [out] */ ICorDebugValue **ppManagedObject) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAppDomain4Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomain4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomain4 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomain4 * This); - + DECLSPEC_XFGVIRT(ICorDebugAppDomain4, GetObjectForCCW) - HRESULT ( STDMETHODCALLTYPE *GetObjectForCCW )( + HRESULT ( STDMETHODCALLTYPE *GetObjectForCCW )( ICorDebugAppDomain4 * This, /* [in] */ CORDB_ADDRESS ccwPointer, /* [out] */ ICorDebugValue **ppManagedObject); - + END_INTERFACE } ICorDebugAppDomain4Vtbl; @@ -6021,23 +6028,23 @@ EXTERN_C const IID IID_ICorDebugAppDomain4; CONST_VTBL struct ICorDebugAppDomain4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAppDomain4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomain4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomain4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomain4_GetObjectForCCW(This,ccwPointer,ppManagedObject) \ - ( (This)->lpVtbl -> GetObjectForCCW(This,ccwPointer,ppManagedObject) ) + ( (This)->lpVtbl -> GetObjectForCCW(This,ccwPointer,ppManagedObject) ) #endif /* COBJMACROS */ @@ -6051,10 +6058,10 @@ EXTERN_C const IID IID_ICorDebugAppDomain4; /* interface __MIDL_itf_cordebug_0000_0030 */ -/* [local] */ +/* [local] */ #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0030_v0_0_c_ifspec; @@ -6064,89 +6071,89 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0030_v0_0_s_ifspec; #define __ICorDebugAssembly_INTERFACE_DEFINED__ /* interface ICorDebugAssembly */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAssembly; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("df59507c-d47a-459e-bce2-6427eac8fd06") ICorDebugAssembly : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetProcess( + virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAppDomain( + + virtual HRESULT STDMETHODCALLTYPE GetAppDomain( /* [out] */ ICorDebugAppDomain **ppAppDomain) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateModules( + + virtual HRESULT STDMETHODCALLTYPE EnumerateModules( /* [out] */ ICorDebugModuleEnum **ppModules) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCodeBase( + + virtual HRESULT STDMETHODCALLTYPE GetCodeBase( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetName( + + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAssemblyVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAssembly * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAssembly * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAssembly * This); - + DECLSPEC_XFGVIRT(ICorDebugAssembly, GetProcess) - HRESULT ( STDMETHODCALLTYPE *GetProcess )( + HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebugAssembly * This, /* [out] */ ICorDebugProcess **ppProcess); - + DECLSPEC_XFGVIRT(ICorDebugAssembly, GetAppDomain) - HRESULT ( STDMETHODCALLTYPE *GetAppDomain )( + HRESULT ( STDMETHODCALLTYPE *GetAppDomain )( ICorDebugAssembly * This, /* [out] */ ICorDebugAppDomain **ppAppDomain); - + DECLSPEC_XFGVIRT(ICorDebugAssembly, EnumerateModules) - HRESULT ( STDMETHODCALLTYPE *EnumerateModules )( + HRESULT ( STDMETHODCALLTYPE *EnumerateModules )( ICorDebugAssembly * This, /* [out] */ ICorDebugModuleEnum **ppModules); - + DECLSPEC_XFGVIRT(ICorDebugAssembly, GetCodeBase) - HRESULT ( STDMETHODCALLTYPE *GetCodeBase )( + HRESULT ( STDMETHODCALLTYPE *GetCodeBase )( ICorDebugAssembly * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - + DECLSPEC_XFGVIRT(ICorDebugAssembly, GetName) - HRESULT ( STDMETHODCALLTYPE *GetName )( + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugAssembly * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - + END_INTERFACE } ICorDebugAssemblyVtbl; @@ -6155,35 +6162,35 @@ EXTERN_C const IID IID_ICorDebugAssembly; CONST_VTBL struct ICorDebugAssemblyVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAssembly_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAssembly_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAssembly_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAssembly_GetProcess(This,ppProcess) \ - ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) + ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) #define ICorDebugAssembly_GetAppDomain(This,ppAppDomain) \ - ( (This)->lpVtbl -> GetAppDomain(This,ppAppDomain) ) + ( (This)->lpVtbl -> GetAppDomain(This,ppAppDomain) ) #define ICorDebugAssembly_EnumerateModules(This,ppModules) \ - ( (This)->lpVtbl -> EnumerateModules(This,ppModules) ) + ( (This)->lpVtbl -> EnumerateModules(This,ppModules) ) #define ICorDebugAssembly_GetCodeBase(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetCodeBase(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetCodeBase(This,cchName,pcchName,szName) ) #define ICorDebugAssembly_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #endif /* COBJMACROS */ @@ -6197,7 +6204,7 @@ EXTERN_C const IID IID_ICorDebugAssembly; /* interface __MIDL_itf_cordebug_0000_0031 */ -/* [local] */ +/* [local] */ #pragma warning(pop) @@ -6209,49 +6216,49 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0031_v0_0_s_ifspec; #define __ICorDebugAssembly2_INTERFACE_DEFINED__ /* interface ICorDebugAssembly2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAssembly2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("426d1f9e-6dd4-44c8-aec7-26cdbaf4e398") ICorDebugAssembly2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE IsFullyTrusted( + virtual HRESULT STDMETHODCALLTYPE IsFullyTrusted( /* [out] */ BOOL *pbFullyTrusted) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAssembly2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAssembly2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAssembly2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAssembly2 * This); - + DECLSPEC_XFGVIRT(ICorDebugAssembly2, IsFullyTrusted) - HRESULT ( STDMETHODCALLTYPE *IsFullyTrusted )( + HRESULT ( STDMETHODCALLTYPE *IsFullyTrusted )( ICorDebugAssembly2 * This, /* [out] */ BOOL *pbFullyTrusted); - + END_INTERFACE } ICorDebugAssembly2Vtbl; @@ -6260,23 +6267,23 @@ EXTERN_C const IID IID_ICorDebugAssembly2; CONST_VTBL struct ICorDebugAssembly2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAssembly2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAssembly2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAssembly2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAssembly2_IsFullyTrusted(This,pbFullyTrusted) \ - ( (This)->lpVtbl -> IsFullyTrusted(This,pbFullyTrusted) ) + ( (This)->lpVtbl -> IsFullyTrusted(This,pbFullyTrusted) ) #endif /* COBJMACROS */ @@ -6293,57 +6300,57 @@ EXTERN_C const IID IID_ICorDebugAssembly2; #define __ICorDebugAssembly3_INTERFACE_DEFINED__ /* interface ICorDebugAssembly3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAssembly3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("76361AB2-8C86-4FE9-96F2-F73D8843570A") ICorDebugAssembly3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetContainerAssembly( + virtual HRESULT STDMETHODCALLTYPE GetContainerAssembly( ICorDebugAssembly **ppAssembly) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateContainedAssemblies( + + virtual HRESULT STDMETHODCALLTYPE EnumerateContainedAssemblies( ICorDebugAssemblyEnum **ppAssemblies) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAssembly3Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAssembly3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAssembly3 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAssembly3 * This); - + DECLSPEC_XFGVIRT(ICorDebugAssembly3, GetContainerAssembly) - HRESULT ( STDMETHODCALLTYPE *GetContainerAssembly )( + HRESULT ( STDMETHODCALLTYPE *GetContainerAssembly )( ICorDebugAssembly3 * This, ICorDebugAssembly **ppAssembly); - + DECLSPEC_XFGVIRT(ICorDebugAssembly3, EnumerateContainedAssemblies) - HRESULT ( STDMETHODCALLTYPE *EnumerateContainedAssemblies )( + HRESULT ( STDMETHODCALLTYPE *EnumerateContainedAssemblies )( ICorDebugAssembly3 * This, ICorDebugAssemblyEnum **ppAssemblies); - + END_INTERFACE } ICorDebugAssembly3Vtbl; @@ -6352,26 +6359,26 @@ EXTERN_C const IID IID_ICorDebugAssembly3; CONST_VTBL struct ICorDebugAssembly3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAssembly3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAssembly3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAssembly3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAssembly3_GetContainerAssembly(This,ppAssembly) \ - ( (This)->lpVtbl -> GetContainerAssembly(This,ppAssembly) ) + ( (This)->lpVtbl -> GetContainerAssembly(This,ppAssembly) ) #define ICorDebugAssembly3_EnumerateContainedAssemblies(This,ppAssemblies) \ - ( (This)->lpVtbl -> EnumerateContainedAssemblies(This,ppAssemblies) ) + ( (This)->lpVtbl -> EnumerateContainedAssemblies(This,ppAssemblies) ) #endif /* COBJMACROS */ @@ -6385,7 +6392,7 @@ EXTERN_C const IID IID_ICorDebugAssembly3; /* interface __MIDL_itf_cordebug_0000_0033 */ -/* [local] */ +/* [local] */ #ifndef _DEF_COR_TYPEID_ #define _DEF_COR_TYPEID_ @@ -6412,72 +6419,72 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0033_v0_0_s_ifspec; #define __ICorDebugHeapEnum_INTERFACE_DEFINED__ /* interface ICorDebugHeapEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("76D7DAB8-D044-11DF-9A15-7E29DFD72085") ICorDebugHeapEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_HEAPOBJECT objects[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugHeapEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugHeapEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugHeapEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugHeapEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugHeapEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugHeapEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugHeapEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_HEAPOBJECT objects[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugHeapEnumVtbl; @@ -6486,36 +6493,36 @@ EXTERN_C const IID IID_ICorDebugHeapEnum; CONST_VTBL struct ICorDebugHeapEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugHeapEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugHeapEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugHeapEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugHeapEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugHeapEnum_Next(This,celt,objects,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) #endif /* COBJMACROS */ @@ -6529,9 +6536,9 @@ EXTERN_C const IID IID_ICorDebugHeapEnum; /* interface __MIDL_itf_cordebug_0000_0034 */ -/* [local] */ +/* [local] */ -typedef +typedef enum CorDebugGenerationTypes { CorDebug_Gen0 = 0, @@ -6550,11 +6557,11 @@ typedef struct _COR_SEGMENT ULONG heap; } COR_SEGMENT; -typedef +typedef enum CorDebugGCType { CorDebugWorkstationGC = 0, - CorDebugServerGC = ( CorDebugWorkstationGC + 1 ) + CorDebugServerGC = ( CorDebugWorkstationGC + 1 ) } CorDebugGCType; typedef struct _COR_HEAPINFO @@ -6575,72 +6582,72 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0034_v0_0_s_ifspec; #define __ICorDebugHeapSegmentEnum_INTERFACE_DEFINED__ /* interface ICorDebugHeapSegmentEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapSegmentEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("A2FA0F8E-D045-11DF-AC8E-CE2ADFD72085") ICorDebugHeapSegmentEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_SEGMENT segments[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugHeapSegmentEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapSegmentEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapSegmentEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapSegmentEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugHeapSegmentEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugHeapSegmentEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugHeapSegmentEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugHeapSegmentEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugHeapSegmentEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugHeapSegmentEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_SEGMENT segments[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugHeapSegmentEnumVtbl; @@ -6649,36 +6656,36 @@ EXTERN_C const IID IID_ICorDebugHeapSegmentEnum; CONST_VTBL struct ICorDebugHeapSegmentEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugHeapSegmentEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapSegmentEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapSegmentEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapSegmentEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugHeapSegmentEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugHeapSegmentEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugHeapSegmentEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugHeapSegmentEnum_Next(This,celt,segments,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,segments,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,segments,pceltFetched) ) #endif /* COBJMACROS */ @@ -6692,9 +6699,9 @@ EXTERN_C const IID IID_ICorDebugHeapSegmentEnum; /* interface __MIDL_itf_cordebug_0000_0035 */ -/* [local] */ +/* [local] */ -typedef +typedef enum CorGCReferenceType { CorHandleStrong = ( 1 << 0 ) , @@ -6735,72 +6742,72 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0035_v0_0_s_ifspec; #define __ICorDebugGCReferenceEnum_INTERFACE_DEFINED__ /* interface ICorDebugGCReferenceEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugGCReferenceEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("7F3C24D3-7E1D-4245-AC3A-F72F8859C80C") ICorDebugGCReferenceEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_GC_REFERENCE roots[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugGCReferenceEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugGCReferenceEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugGCReferenceEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugGCReferenceEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugGCReferenceEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugGCReferenceEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugGCReferenceEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugGCReferenceEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugGCReferenceEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugGCReferenceEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_GC_REFERENCE roots[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugGCReferenceEnumVtbl; @@ -6809,36 +6816,36 @@ EXTERN_C const IID IID_ICorDebugGCReferenceEnum; CONST_VTBL struct ICorDebugGCReferenceEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugGCReferenceEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugGCReferenceEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugGCReferenceEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugGCReferenceEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugGCReferenceEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugGCReferenceEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugGCReferenceEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugGCReferenceEnum_Next(This,celt,roots,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,roots,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,roots,pceltFetched) ) #endif /* COBJMACROS */ @@ -6852,7 +6859,7 @@ EXTERN_C const IID IID_ICorDebugGCReferenceEnum; /* interface __MIDL_itf_cordebug_0000_0036 */ -/* [local] */ +/* [local] */ #ifndef _DEF_COR_ARRAY_LAYOUT_ #define _DEF_COR_ARRAY_LAYOUT_ @@ -6893,7 +6900,7 @@ typedef struct COR_FIELD #endif // _DEF_COR_FIELD_ #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0036_v0_0_c_ifspec; @@ -6903,264 +6910,264 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0036_v0_0_s_ifspec; #define __ICorDebugProcess_INTERFACE_DEFINED__ /* interface ICorDebugProcess */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("3d6f5f64-7538-11d3-8d5b-00104b35e7ef") ICorDebugProcess : public ICorDebugController { public: - virtual HRESULT STDMETHODCALLTYPE GetID( + virtual HRESULT STDMETHODCALLTYPE GetID( /* [out] */ DWORD *pdwProcessId) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetHandle( + + virtual HRESULT STDMETHODCALLTYPE GetHandle( /* [out] */ HPROCESS *phProcessHandle) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetThread( + + virtual HRESULT STDMETHODCALLTYPE GetThread( /* [in] */ DWORD dwThreadId, /* [out] */ ICorDebugThread **ppThread) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateObjects( + + virtual HRESULT STDMETHODCALLTYPE EnumerateObjects( /* [out] */ ICorDebugObjectEnum **ppObjects) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsTransitionStub( + + virtual HRESULT STDMETHODCALLTYPE IsTransitionStub( /* [in] */ CORDB_ADDRESS address, /* [out] */ BOOL *pbTransitionStub) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsOSSuspended( + + virtual HRESULT STDMETHODCALLTYPE IsOSSuspended( /* [in] */ DWORD threadID, /* [out] */ BOOL *pbSuspended) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetThreadContext( + + virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ DWORD threadID, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][out][in] */ BYTE context[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetThreadContext( + + virtual HRESULT STDMETHODCALLTYPE SetThreadContext( /* [in] */ DWORD threadID, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][in] */ BYTE context[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE ReadMemory( + + virtual HRESULT STDMETHODCALLTYPE ReadMemory( /* [in] */ CORDB_ADDRESS address, /* [in] */ DWORD size, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ SIZE_T *read) = 0; - - virtual HRESULT STDMETHODCALLTYPE WriteMemory( + + virtual HRESULT STDMETHODCALLTYPE WriteMemory( /* [in] */ CORDB_ADDRESS address, /* [in] */ DWORD size, /* [size_is][in] */ BYTE buffer[ ], /* [out] */ SIZE_T *written) = 0; - - virtual HRESULT STDMETHODCALLTYPE ClearCurrentException( + + virtual HRESULT STDMETHODCALLTYPE ClearCurrentException( /* [in] */ DWORD threadID) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnableLogMessages( + + virtual HRESULT STDMETHODCALLTYPE EnableLogMessages( /* [in] */ BOOL fOnOff) = 0; - - virtual HRESULT STDMETHODCALLTYPE ModifyLogSwitch( - /* [annotation][in] */ + + virtual HRESULT STDMETHODCALLTYPE ModifyLogSwitch( + /* [annotation][in] */ _In_ WCHAR *pLogSwitchName, /* [in] */ LONG lLevel) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateAppDomains( + + virtual HRESULT STDMETHODCALLTYPE EnumerateAppDomains( /* [out] */ ICorDebugAppDomainEnum **ppAppDomains) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetObject( + + virtual HRESULT STDMETHODCALLTYPE GetObject( /* [out] */ ICorDebugValue **ppObject) = 0; - - virtual HRESULT STDMETHODCALLTYPE ThreadForFiberCookie( + + virtual HRESULT STDMETHODCALLTYPE ThreadForFiberCookie( /* [in] */ DWORD fiberCookie, /* [out] */ ICorDebugThread **ppThread) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetHelperThreadID( + + virtual HRESULT STDMETHODCALLTYPE GetHelperThreadID( /* [out] */ DWORD *pThreadID) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcessVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess * This); - + DECLSPEC_XFGVIRT(ICorDebugController, Stop) - HRESULT ( STDMETHODCALLTYPE *Stop )( + HRESULT ( STDMETHODCALLTYPE *Stop )( ICorDebugProcess * This, /* [in] */ DWORD dwTimeoutIgnored); - + DECLSPEC_XFGVIRT(ICorDebugController, Continue) - HRESULT ( STDMETHODCALLTYPE *Continue )( + HRESULT ( STDMETHODCALLTYPE *Continue )( ICorDebugProcess * This, /* [in] */ BOOL fIsOutOfBand); - + DECLSPEC_XFGVIRT(ICorDebugController, IsRunning) - HRESULT ( STDMETHODCALLTYPE *IsRunning )( + HRESULT ( STDMETHODCALLTYPE *IsRunning )( ICorDebugProcess * This, /* [out] */ BOOL *pbRunning); - + DECLSPEC_XFGVIRT(ICorDebugController, HasQueuedCallbacks) - HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( + HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( ICorDebugProcess * This, /* [in] */ ICorDebugThread *pThread, /* [out] */ BOOL *pbQueued); - + DECLSPEC_XFGVIRT(ICorDebugController, EnumerateThreads) - HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( + HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( ICorDebugProcess * This, /* [out] */ ICorDebugThreadEnum **ppThreads); - + DECLSPEC_XFGVIRT(ICorDebugController, SetAllThreadsDebugState) - HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( + HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( ICorDebugProcess * This, /* [in] */ CorDebugThreadState state, /* [in] */ ICorDebugThread *pExceptThisThread); - + DECLSPEC_XFGVIRT(ICorDebugController, Detach) - HRESULT ( STDMETHODCALLTYPE *Detach )( + HRESULT ( STDMETHODCALLTYPE *Detach )( ICorDebugProcess * This); - + DECLSPEC_XFGVIRT(ICorDebugController, Terminate) - HRESULT ( STDMETHODCALLTYPE *Terminate )( + HRESULT ( STDMETHODCALLTYPE *Terminate )( ICorDebugProcess * This, /* [in] */ UINT exitCode); - + DECLSPEC_XFGVIRT(ICorDebugController, CanCommitChanges) - HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( + HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( ICorDebugProcess * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); - + DECLSPEC_XFGVIRT(ICorDebugController, CommitChanges) - HRESULT ( STDMETHODCALLTYPE *CommitChanges )( + HRESULT ( STDMETHODCALLTYPE *CommitChanges )( ICorDebugProcess * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); - + DECLSPEC_XFGVIRT(ICorDebugProcess, GetID) - HRESULT ( STDMETHODCALLTYPE *GetID )( + HRESULT ( STDMETHODCALLTYPE *GetID )( ICorDebugProcess * This, /* [out] */ DWORD *pdwProcessId); - + DECLSPEC_XFGVIRT(ICorDebugProcess, GetHandle) - HRESULT ( STDMETHODCALLTYPE *GetHandle )( + HRESULT ( STDMETHODCALLTYPE *GetHandle )( ICorDebugProcess * This, /* [out] */ HPROCESS *phProcessHandle); - + DECLSPEC_XFGVIRT(ICorDebugProcess, GetThread) - HRESULT ( STDMETHODCALLTYPE *GetThread )( + HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugProcess * This, /* [in] */ DWORD dwThreadId, /* [out] */ ICorDebugThread **ppThread); - + DECLSPEC_XFGVIRT(ICorDebugProcess, EnumerateObjects) - HRESULT ( STDMETHODCALLTYPE *EnumerateObjects )( + HRESULT ( STDMETHODCALLTYPE *EnumerateObjects )( ICorDebugProcess * This, /* [out] */ ICorDebugObjectEnum **ppObjects); - + DECLSPEC_XFGVIRT(ICorDebugProcess, IsTransitionStub) - HRESULT ( STDMETHODCALLTYPE *IsTransitionStub )( + HRESULT ( STDMETHODCALLTYPE *IsTransitionStub )( ICorDebugProcess * This, /* [in] */ CORDB_ADDRESS address, /* [out] */ BOOL *pbTransitionStub); - + DECLSPEC_XFGVIRT(ICorDebugProcess, IsOSSuspended) - HRESULT ( STDMETHODCALLTYPE *IsOSSuspended )( + HRESULT ( STDMETHODCALLTYPE *IsOSSuspended )( ICorDebugProcess * This, /* [in] */ DWORD threadID, /* [out] */ BOOL *pbSuspended); - + DECLSPEC_XFGVIRT(ICorDebugProcess, GetThreadContext) - HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorDebugProcess * This, /* [in] */ DWORD threadID, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][out][in] */ BYTE context[ ]); - + DECLSPEC_XFGVIRT(ICorDebugProcess, SetThreadContext) - HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( + HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( ICorDebugProcess * This, /* [in] */ DWORD threadID, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][in] */ BYTE context[ ]); - + DECLSPEC_XFGVIRT(ICorDebugProcess, ReadMemory) - HRESULT ( STDMETHODCALLTYPE *ReadMemory )( + HRESULT ( STDMETHODCALLTYPE *ReadMemory )( ICorDebugProcess * This, /* [in] */ CORDB_ADDRESS address, /* [in] */ DWORD size, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ SIZE_T *read); - + DECLSPEC_XFGVIRT(ICorDebugProcess, WriteMemory) - HRESULT ( STDMETHODCALLTYPE *WriteMemory )( + HRESULT ( STDMETHODCALLTYPE *WriteMemory )( ICorDebugProcess * This, /* [in] */ CORDB_ADDRESS address, /* [in] */ DWORD size, /* [size_is][in] */ BYTE buffer[ ], /* [out] */ SIZE_T *written); - + DECLSPEC_XFGVIRT(ICorDebugProcess, ClearCurrentException) - HRESULT ( STDMETHODCALLTYPE *ClearCurrentException )( + HRESULT ( STDMETHODCALLTYPE *ClearCurrentException )( ICorDebugProcess * This, /* [in] */ DWORD threadID); - + DECLSPEC_XFGVIRT(ICorDebugProcess, EnableLogMessages) - HRESULT ( STDMETHODCALLTYPE *EnableLogMessages )( + HRESULT ( STDMETHODCALLTYPE *EnableLogMessages )( ICorDebugProcess * This, /* [in] */ BOOL fOnOff); - + DECLSPEC_XFGVIRT(ICorDebugProcess, ModifyLogSwitch) - HRESULT ( STDMETHODCALLTYPE *ModifyLogSwitch )( + HRESULT ( STDMETHODCALLTYPE *ModifyLogSwitch )( ICorDebugProcess * This, - /* [annotation][in] */ + /* [annotation][in] */ _In_ WCHAR *pLogSwitchName, /* [in] */ LONG lLevel); - + DECLSPEC_XFGVIRT(ICorDebugProcess, EnumerateAppDomains) - HRESULT ( STDMETHODCALLTYPE *EnumerateAppDomains )( + HRESULT ( STDMETHODCALLTYPE *EnumerateAppDomains )( ICorDebugProcess * This, /* [out] */ ICorDebugAppDomainEnum **ppAppDomains); - + DECLSPEC_XFGVIRT(ICorDebugProcess, GetObject) - HRESULT ( STDMETHODCALLTYPE *GetObject )( + HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugProcess * This, /* [out] */ ICorDebugValue **ppObject); - + DECLSPEC_XFGVIRT(ICorDebugProcess, ThreadForFiberCookie) - HRESULT ( STDMETHODCALLTYPE *ThreadForFiberCookie )( + HRESULT ( STDMETHODCALLTYPE *ThreadForFiberCookie )( ICorDebugProcess * This, /* [in] */ DWORD fiberCookie, /* [out] */ ICorDebugThread **ppThread); - + DECLSPEC_XFGVIRT(ICorDebugProcess, GetHelperThreadID) - HRESULT ( STDMETHODCALLTYPE *GetHelperThreadID )( + HRESULT ( STDMETHODCALLTYPE *GetHelperThreadID )( ICorDebugProcess * This, /* [out] */ DWORD *pThreadID); - + END_INTERFACE } ICorDebugProcessVtbl; @@ -7169,102 +7176,102 @@ EXTERN_C const IID IID_ICorDebugProcess; CONST_VTBL struct ICorDebugProcessVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess_Stop(This,dwTimeoutIgnored) \ - ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) + ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) #define ICorDebugProcess_Continue(This,fIsOutOfBand) \ - ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) + ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) #define ICorDebugProcess_IsRunning(This,pbRunning) \ - ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) + ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) #define ICorDebugProcess_HasQueuedCallbacks(This,pThread,pbQueued) \ - ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) + ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) #define ICorDebugProcess_EnumerateThreads(This,ppThreads) \ - ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) + ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) #define ICorDebugProcess_SetAllThreadsDebugState(This,state,pExceptThisThread) \ - ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) + ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) #define ICorDebugProcess_Detach(This) \ - ( (This)->lpVtbl -> Detach(This) ) + ( (This)->lpVtbl -> Detach(This) ) #define ICorDebugProcess_Terminate(This,exitCode) \ - ( (This)->lpVtbl -> Terminate(This,exitCode) ) + ( (This)->lpVtbl -> Terminate(This,exitCode) ) #define ICorDebugProcess_CanCommitChanges(This,cSnapshots,pSnapshots,pError) \ - ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) + ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugProcess_CommitChanges(This,cSnapshots,pSnapshots,pError) \ - ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) + ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugProcess_GetID(This,pdwProcessId) \ - ( (This)->lpVtbl -> GetID(This,pdwProcessId) ) + ( (This)->lpVtbl -> GetID(This,pdwProcessId) ) #define ICorDebugProcess_GetHandle(This,phProcessHandle) \ - ( (This)->lpVtbl -> GetHandle(This,phProcessHandle) ) + ( (This)->lpVtbl -> GetHandle(This,phProcessHandle) ) #define ICorDebugProcess_GetThread(This,dwThreadId,ppThread) \ - ( (This)->lpVtbl -> GetThread(This,dwThreadId,ppThread) ) + ( (This)->lpVtbl -> GetThread(This,dwThreadId,ppThread) ) #define ICorDebugProcess_EnumerateObjects(This,ppObjects) \ - ( (This)->lpVtbl -> EnumerateObjects(This,ppObjects) ) + ( (This)->lpVtbl -> EnumerateObjects(This,ppObjects) ) #define ICorDebugProcess_IsTransitionStub(This,address,pbTransitionStub) \ - ( (This)->lpVtbl -> IsTransitionStub(This,address,pbTransitionStub) ) + ( (This)->lpVtbl -> IsTransitionStub(This,address,pbTransitionStub) ) #define ICorDebugProcess_IsOSSuspended(This,threadID,pbSuspended) \ - ( (This)->lpVtbl -> IsOSSuspended(This,threadID,pbSuspended) ) + ( (This)->lpVtbl -> IsOSSuspended(This,threadID,pbSuspended) ) #define ICorDebugProcess_GetThreadContext(This,threadID,contextSize,context) \ - ( (This)->lpVtbl -> GetThreadContext(This,threadID,contextSize,context) ) + ( (This)->lpVtbl -> GetThreadContext(This,threadID,contextSize,context) ) #define ICorDebugProcess_SetThreadContext(This,threadID,contextSize,context) \ - ( (This)->lpVtbl -> SetThreadContext(This,threadID,contextSize,context) ) + ( (This)->lpVtbl -> SetThreadContext(This,threadID,contextSize,context) ) #define ICorDebugProcess_ReadMemory(This,address,size,buffer,read) \ - ( (This)->lpVtbl -> ReadMemory(This,address,size,buffer,read) ) + ( (This)->lpVtbl -> ReadMemory(This,address,size,buffer,read) ) #define ICorDebugProcess_WriteMemory(This,address,size,buffer,written) \ - ( (This)->lpVtbl -> WriteMemory(This,address,size,buffer,written) ) + ( (This)->lpVtbl -> WriteMemory(This,address,size,buffer,written) ) #define ICorDebugProcess_ClearCurrentException(This,threadID) \ - ( (This)->lpVtbl -> ClearCurrentException(This,threadID) ) + ( (This)->lpVtbl -> ClearCurrentException(This,threadID) ) #define ICorDebugProcess_EnableLogMessages(This,fOnOff) \ - ( (This)->lpVtbl -> EnableLogMessages(This,fOnOff) ) + ( (This)->lpVtbl -> EnableLogMessages(This,fOnOff) ) #define ICorDebugProcess_ModifyLogSwitch(This,pLogSwitchName,lLevel) \ - ( (This)->lpVtbl -> ModifyLogSwitch(This,pLogSwitchName,lLevel) ) + ( (This)->lpVtbl -> ModifyLogSwitch(This,pLogSwitchName,lLevel) ) #define ICorDebugProcess_EnumerateAppDomains(This,ppAppDomains) \ - ( (This)->lpVtbl -> EnumerateAppDomains(This,ppAppDomains) ) + ( (This)->lpVtbl -> EnumerateAppDomains(This,ppAppDomains) ) #define ICorDebugProcess_GetObject(This,ppObject) \ - ( (This)->lpVtbl -> GetObject(This,ppObject) ) + ( (This)->lpVtbl -> GetObject(This,ppObject) ) #define ICorDebugProcess_ThreadForFiberCookie(This,fiberCookie,ppThread) \ - ( (This)->lpVtbl -> ThreadForFiberCookie(This,fiberCookie,ppThread) ) + ( (This)->lpVtbl -> ThreadForFiberCookie(This,fiberCookie,ppThread) ) #define ICorDebugProcess_GetHelperThreadID(This,pThreadID) \ - ( (This)->lpVtbl -> GetHelperThreadID(This,pThreadID) ) + ( (This)->lpVtbl -> GetHelperThreadID(This,pThreadID) ) #endif /* COBJMACROS */ @@ -7278,7 +7285,7 @@ EXTERN_C const IID IID_ICorDebugProcess; /* interface __MIDL_itf_cordebug_0000_0037 */ -/* [local] */ +/* [local] */ #pragma warning(pop) @@ -7290,107 +7297,107 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0037_v0_0_s_ifspec; #define __ICorDebugProcess2_INTERFACE_DEFINED__ /* interface ICorDebugProcess2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("AD1B3588-0EF0-4744-A496-AA09A9F80371") ICorDebugProcess2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetThreadForTaskID( + virtual HRESULT STDMETHODCALLTYPE GetThreadForTaskID( /* [in] */ TASKID taskid, /* [out] */ ICorDebugThread2 **ppThread) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetVersion( + + virtual HRESULT STDMETHODCALLTYPE GetVersion( /* [out] */ COR_VERSION *version) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetUnmanagedBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE SetUnmanagedBreakpoint( /* [in] */ CORDB_ADDRESS address, /* [in] */ ULONG32 bufsize, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ ULONG32 *bufLen) = 0; - - virtual HRESULT STDMETHODCALLTYPE ClearUnmanagedBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE ClearUnmanagedBreakpoint( /* [in] */ CORDB_ADDRESS address) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetDesiredNGENCompilerFlags( + + virtual HRESULT STDMETHODCALLTYPE SetDesiredNGENCompilerFlags( /* [in] */ DWORD pdwFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDesiredNGENCompilerFlags( + + virtual HRESULT STDMETHODCALLTYPE GetDesiredNGENCompilerFlags( /* [out] */ DWORD *pdwFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetReferenceValueFromGCHandle( + + virtual HRESULT STDMETHODCALLTYPE GetReferenceValueFromGCHandle( /* [in] */ UINT_PTR handle, /* [out] */ ICorDebugReferenceValue **pOutValue) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess2 * This); - + DECLSPEC_XFGVIRT(ICorDebugProcess2, GetThreadForTaskID) - HRESULT ( STDMETHODCALLTYPE *GetThreadForTaskID )( + HRESULT ( STDMETHODCALLTYPE *GetThreadForTaskID )( ICorDebugProcess2 * This, /* [in] */ TASKID taskid, /* [out] */ ICorDebugThread2 **ppThread); - + DECLSPEC_XFGVIRT(ICorDebugProcess2, GetVersion) - HRESULT ( STDMETHODCALLTYPE *GetVersion )( + HRESULT ( STDMETHODCALLTYPE *GetVersion )( ICorDebugProcess2 * This, /* [out] */ COR_VERSION *version); - + DECLSPEC_XFGVIRT(ICorDebugProcess2, SetUnmanagedBreakpoint) - HRESULT ( STDMETHODCALLTYPE *SetUnmanagedBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *SetUnmanagedBreakpoint )( ICorDebugProcess2 * This, /* [in] */ CORDB_ADDRESS address, /* [in] */ ULONG32 bufsize, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ ULONG32 *bufLen); - + DECLSPEC_XFGVIRT(ICorDebugProcess2, ClearUnmanagedBreakpoint) - HRESULT ( STDMETHODCALLTYPE *ClearUnmanagedBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *ClearUnmanagedBreakpoint )( ICorDebugProcess2 * This, /* [in] */ CORDB_ADDRESS address); - + DECLSPEC_XFGVIRT(ICorDebugProcess2, SetDesiredNGENCompilerFlags) - HRESULT ( STDMETHODCALLTYPE *SetDesiredNGENCompilerFlags )( + HRESULT ( STDMETHODCALLTYPE *SetDesiredNGENCompilerFlags )( ICorDebugProcess2 * This, /* [in] */ DWORD pdwFlags); - + DECLSPEC_XFGVIRT(ICorDebugProcess2, GetDesiredNGENCompilerFlags) - HRESULT ( STDMETHODCALLTYPE *GetDesiredNGENCompilerFlags )( + HRESULT ( STDMETHODCALLTYPE *GetDesiredNGENCompilerFlags )( ICorDebugProcess2 * This, /* [out] */ DWORD *pdwFlags); - + DECLSPEC_XFGVIRT(ICorDebugProcess2, GetReferenceValueFromGCHandle) - HRESULT ( STDMETHODCALLTYPE *GetReferenceValueFromGCHandle )( + HRESULT ( STDMETHODCALLTYPE *GetReferenceValueFromGCHandle )( ICorDebugProcess2 * This, /* [in] */ UINT_PTR handle, /* [out] */ ICorDebugReferenceValue **pOutValue); - + END_INTERFACE } ICorDebugProcess2Vtbl; @@ -7399,41 +7406,41 @@ EXTERN_C const IID IID_ICorDebugProcess2; CONST_VTBL struct ICorDebugProcess2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess2_GetThreadForTaskID(This,taskid,ppThread) \ - ( (This)->lpVtbl -> GetThreadForTaskID(This,taskid,ppThread) ) + ( (This)->lpVtbl -> GetThreadForTaskID(This,taskid,ppThread) ) #define ICorDebugProcess2_GetVersion(This,version) \ - ( (This)->lpVtbl -> GetVersion(This,version) ) + ( (This)->lpVtbl -> GetVersion(This,version) ) #define ICorDebugProcess2_SetUnmanagedBreakpoint(This,address,bufsize,buffer,bufLen) \ - ( (This)->lpVtbl -> SetUnmanagedBreakpoint(This,address,bufsize,buffer,bufLen) ) + ( (This)->lpVtbl -> SetUnmanagedBreakpoint(This,address,bufsize,buffer,bufLen) ) #define ICorDebugProcess2_ClearUnmanagedBreakpoint(This,address) \ - ( (This)->lpVtbl -> ClearUnmanagedBreakpoint(This,address) ) + ( (This)->lpVtbl -> ClearUnmanagedBreakpoint(This,address) ) #define ICorDebugProcess2_SetDesiredNGENCompilerFlags(This,pdwFlags) \ - ( (This)->lpVtbl -> SetDesiredNGENCompilerFlags(This,pdwFlags) ) + ( (This)->lpVtbl -> SetDesiredNGENCompilerFlags(This,pdwFlags) ) #define ICorDebugProcess2_GetDesiredNGENCompilerFlags(This,pdwFlags) \ - ( (This)->lpVtbl -> GetDesiredNGENCompilerFlags(This,pdwFlags) ) + ( (This)->lpVtbl -> GetDesiredNGENCompilerFlags(This,pdwFlags) ) #define ICorDebugProcess2_GetReferenceValueFromGCHandle(This,handle,pOutValue) \ - ( (This)->lpVtbl -> GetReferenceValueFromGCHandle(This,handle,pOutValue) ) + ( (This)->lpVtbl -> GetReferenceValueFromGCHandle(This,handle,pOutValue) ) #endif /* COBJMACROS */ @@ -7450,51 +7457,51 @@ EXTERN_C const IID IID_ICorDebugProcess2; #define __ICorDebugProcess3_INTERFACE_DEFINED__ /* interface ICorDebugProcess3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("2EE06488-C0D4-42B1-B26D-F3795EF606FB") ICorDebugProcess3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE SetEnableCustomNotification( + virtual HRESULT STDMETHODCALLTYPE SetEnableCustomNotification( ICorDebugClass *pClass, BOOL fEnable) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess3Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess3 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess3 * This); - + DECLSPEC_XFGVIRT(ICorDebugProcess3, SetEnableCustomNotification) - HRESULT ( STDMETHODCALLTYPE *SetEnableCustomNotification )( + HRESULT ( STDMETHODCALLTYPE *SetEnableCustomNotification )( ICorDebugProcess3 * This, ICorDebugClass *pClass, BOOL fEnable); - + END_INTERFACE } ICorDebugProcess3Vtbl; @@ -7503,23 +7510,23 @@ EXTERN_C const IID IID_ICorDebugProcess3; CONST_VTBL struct ICorDebugProcess3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess3_SetEnableCustomNotification(This,pClass,fEnable) \ - ( (This)->lpVtbl -> SetEnableCustomNotification(This,pClass,fEnable) ) + ( (This)->lpVtbl -> SetEnableCustomNotification(This,pClass,fEnable) ) #endif /* COBJMACROS */ @@ -7536,157 +7543,157 @@ EXTERN_C const IID IID_ICorDebugProcess3; #define __ICorDebugProcess5_INTERFACE_DEFINED__ /* interface ICorDebugProcess5 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess5; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("21e9d9c0-fcb8-11df-8cff-0800200c9a66") ICorDebugProcess5 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetGCHeapInformation( + virtual HRESULT STDMETHODCALLTYPE GetGCHeapInformation( /* [out] */ COR_HEAPINFO *pHeapInfo) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateHeap( + + virtual HRESULT STDMETHODCALLTYPE EnumerateHeap( /* [out] */ ICorDebugHeapEnum **ppObjects) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateHeapRegions( + + virtual HRESULT STDMETHODCALLTYPE EnumerateHeapRegions( /* [out] */ ICorDebugHeapSegmentEnum **ppRegions) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetObject( + + virtual HRESULT STDMETHODCALLTYPE GetObject( /* [in] */ CORDB_ADDRESS addr, /* [out] */ ICorDebugObjectValue **pObject) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateGCReferences( + + virtual HRESULT STDMETHODCALLTYPE EnumerateGCReferences( /* [in] */ BOOL enumerateWeakReferences, /* [out] */ ICorDebugGCReferenceEnum **ppEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateHandles( + + virtual HRESULT STDMETHODCALLTYPE EnumerateHandles( /* [in] */ CorGCReferenceType types, /* [out] */ ICorDebugGCReferenceEnum **ppEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetTypeID( + + virtual HRESULT STDMETHODCALLTYPE GetTypeID( /* [in] */ CORDB_ADDRESS obj, /* [out] */ COR_TYPEID *pId) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetTypeForTypeID( + + virtual HRESULT STDMETHODCALLTYPE GetTypeForTypeID( /* [in] */ COR_TYPEID id, /* [out] */ ICorDebugType **ppType) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetArrayLayout( + + virtual HRESULT STDMETHODCALLTYPE GetArrayLayout( /* [in] */ COR_TYPEID id, /* [out] */ COR_ARRAY_LAYOUT *pLayout) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetTypeLayout( + + virtual HRESULT STDMETHODCALLTYPE GetTypeLayout( /* [in] */ COR_TYPEID id, /* [out] */ COR_TYPE_LAYOUT *pLayout) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetTypeFields( + + virtual HRESULT STDMETHODCALLTYPE GetTypeFields( /* [in] */ COR_TYPEID id, ULONG32 celt, COR_FIELD fields[ ], ULONG32 *pceltNeeded) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnableNGENPolicy( + + virtual HRESULT STDMETHODCALLTYPE EnableNGENPolicy( /* [in] */ CorDebugNGENPolicy ePolicy) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess5Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess5 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess5 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess5 * This); - + DECLSPEC_XFGVIRT(ICorDebugProcess5, GetGCHeapInformation) - HRESULT ( STDMETHODCALLTYPE *GetGCHeapInformation )( + HRESULT ( STDMETHODCALLTYPE *GetGCHeapInformation )( ICorDebugProcess5 * This, /* [out] */ COR_HEAPINFO *pHeapInfo); - + DECLSPEC_XFGVIRT(ICorDebugProcess5, EnumerateHeap) - HRESULT ( STDMETHODCALLTYPE *EnumerateHeap )( + HRESULT ( STDMETHODCALLTYPE *EnumerateHeap )( ICorDebugProcess5 * This, /* [out] */ ICorDebugHeapEnum **ppObjects); - + DECLSPEC_XFGVIRT(ICorDebugProcess5, EnumerateHeapRegions) - HRESULT ( STDMETHODCALLTYPE *EnumerateHeapRegions )( + HRESULT ( STDMETHODCALLTYPE *EnumerateHeapRegions )( ICorDebugProcess5 * This, /* [out] */ ICorDebugHeapSegmentEnum **ppRegions); - + DECLSPEC_XFGVIRT(ICorDebugProcess5, GetObject) - HRESULT ( STDMETHODCALLTYPE *GetObject )( + HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugProcess5 * This, /* [in] */ CORDB_ADDRESS addr, /* [out] */ ICorDebugObjectValue **pObject); - + DECLSPEC_XFGVIRT(ICorDebugProcess5, EnumerateGCReferences) - HRESULT ( STDMETHODCALLTYPE *EnumerateGCReferences )( + HRESULT ( STDMETHODCALLTYPE *EnumerateGCReferences )( ICorDebugProcess5 * This, /* [in] */ BOOL enumerateWeakReferences, /* [out] */ ICorDebugGCReferenceEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugProcess5, EnumerateHandles) - HRESULT ( STDMETHODCALLTYPE *EnumerateHandles )( + HRESULT ( STDMETHODCALLTYPE *EnumerateHandles )( ICorDebugProcess5 * This, /* [in] */ CorGCReferenceType types, /* [out] */ ICorDebugGCReferenceEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugProcess5, GetTypeID) - HRESULT ( STDMETHODCALLTYPE *GetTypeID )( + HRESULT ( STDMETHODCALLTYPE *GetTypeID )( ICorDebugProcess5 * This, /* [in] */ CORDB_ADDRESS obj, /* [out] */ COR_TYPEID *pId); - + DECLSPEC_XFGVIRT(ICorDebugProcess5, GetTypeForTypeID) - HRESULT ( STDMETHODCALLTYPE *GetTypeForTypeID )( + HRESULT ( STDMETHODCALLTYPE *GetTypeForTypeID )( ICorDebugProcess5 * This, /* [in] */ COR_TYPEID id, /* [out] */ ICorDebugType **ppType); - + DECLSPEC_XFGVIRT(ICorDebugProcess5, GetArrayLayout) - HRESULT ( STDMETHODCALLTYPE *GetArrayLayout )( + HRESULT ( STDMETHODCALLTYPE *GetArrayLayout )( ICorDebugProcess5 * This, /* [in] */ COR_TYPEID id, /* [out] */ COR_ARRAY_LAYOUT *pLayout); - + DECLSPEC_XFGVIRT(ICorDebugProcess5, GetTypeLayout) - HRESULT ( STDMETHODCALLTYPE *GetTypeLayout )( + HRESULT ( STDMETHODCALLTYPE *GetTypeLayout )( ICorDebugProcess5 * This, /* [in] */ COR_TYPEID id, /* [out] */ COR_TYPE_LAYOUT *pLayout); - + DECLSPEC_XFGVIRT(ICorDebugProcess5, GetTypeFields) - HRESULT ( STDMETHODCALLTYPE *GetTypeFields )( + HRESULT ( STDMETHODCALLTYPE *GetTypeFields )( ICorDebugProcess5 * This, /* [in] */ COR_TYPEID id, ULONG32 celt, COR_FIELD fields[ ], ULONG32 *pceltNeeded); - + DECLSPEC_XFGVIRT(ICorDebugProcess5, EnableNGENPolicy) - HRESULT ( STDMETHODCALLTYPE *EnableNGENPolicy )( + HRESULT ( STDMETHODCALLTYPE *EnableNGENPolicy )( ICorDebugProcess5 * This, /* [in] */ CorDebugNGENPolicy ePolicy); - + END_INTERFACE } ICorDebugProcess5Vtbl; @@ -7695,56 +7702,56 @@ EXTERN_C const IID IID_ICorDebugProcess5; CONST_VTBL struct ICorDebugProcess5Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess5_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess5_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess5_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess5_GetGCHeapInformation(This,pHeapInfo) \ - ( (This)->lpVtbl -> GetGCHeapInformation(This,pHeapInfo) ) + ( (This)->lpVtbl -> GetGCHeapInformation(This,pHeapInfo) ) #define ICorDebugProcess5_EnumerateHeap(This,ppObjects) \ - ( (This)->lpVtbl -> EnumerateHeap(This,ppObjects) ) + ( (This)->lpVtbl -> EnumerateHeap(This,ppObjects) ) #define ICorDebugProcess5_EnumerateHeapRegions(This,ppRegions) \ - ( (This)->lpVtbl -> EnumerateHeapRegions(This,ppRegions) ) + ( (This)->lpVtbl -> EnumerateHeapRegions(This,ppRegions) ) #define ICorDebugProcess5_GetObject(This,addr,pObject) \ - ( (This)->lpVtbl -> GetObject(This,addr,pObject) ) + ( (This)->lpVtbl -> GetObject(This,addr,pObject) ) #define ICorDebugProcess5_EnumerateGCReferences(This,enumerateWeakReferences,ppEnum) \ - ( (This)->lpVtbl -> EnumerateGCReferences(This,enumerateWeakReferences,ppEnum) ) + ( (This)->lpVtbl -> EnumerateGCReferences(This,enumerateWeakReferences,ppEnum) ) #define ICorDebugProcess5_EnumerateHandles(This,types,ppEnum) \ - ( (This)->lpVtbl -> EnumerateHandles(This,types,ppEnum) ) + ( (This)->lpVtbl -> EnumerateHandles(This,types,ppEnum) ) #define ICorDebugProcess5_GetTypeID(This,obj,pId) \ - ( (This)->lpVtbl -> GetTypeID(This,obj,pId) ) + ( (This)->lpVtbl -> GetTypeID(This,obj,pId) ) #define ICorDebugProcess5_GetTypeForTypeID(This,id,ppType) \ - ( (This)->lpVtbl -> GetTypeForTypeID(This,id,ppType) ) + ( (This)->lpVtbl -> GetTypeForTypeID(This,id,ppType) ) #define ICorDebugProcess5_GetArrayLayout(This,id,pLayout) \ - ( (This)->lpVtbl -> GetArrayLayout(This,id,pLayout) ) + ( (This)->lpVtbl -> GetArrayLayout(This,id,pLayout) ) #define ICorDebugProcess5_GetTypeLayout(This,id,pLayout) \ - ( (This)->lpVtbl -> GetTypeLayout(This,id,pLayout) ) + ( (This)->lpVtbl -> GetTypeLayout(This,id,pLayout) ) #define ICorDebugProcess5_GetTypeFields(This,id,celt,fields,pceltNeeded) \ - ( (This)->lpVtbl -> GetTypeFields(This,id,celt,fields,pceltNeeded) ) + ( (This)->lpVtbl -> GetTypeFields(This,id,celt,fields,pceltNeeded) ) #define ICorDebugProcess5_EnableNGENPolicy(This,ePolicy) \ - ( (This)->lpVtbl -> EnableNGENPolicy(This,ePolicy) ) + ( (This)->lpVtbl -> EnableNGENPolicy(This,ePolicy) ) #endif /* COBJMACROS */ @@ -7758,22 +7765,22 @@ EXTERN_C const IID IID_ICorDebugProcess5; /* interface __MIDL_itf_cordebug_0000_0040 */ -/* [local] */ +/* [local] */ -typedef +typedef enum CorDebugRecordFormat { FORMAT_WINDOWS_EXCEPTIONRECORD32 = 1, FORMAT_WINDOWS_EXCEPTIONRECORD64 = 2 } CorDebugRecordFormat; -typedef +typedef enum CorDebugDecodeEventFlagsWindows { IS_FIRST_CHANCE = 1 } CorDebugDecodeEventFlagsWindows; -typedef +typedef enum CorDebugDebugEventKind { DEBUG_EVENT_KIND_MODULE_LOADED = 1, @@ -7784,7 +7791,7 @@ enum CorDebugDebugEventKind DEBUG_EVENT_KIND_MANAGED_EXCEPTION_UNHANDLED = 6 } CorDebugDebugEventKind; -typedef +typedef enum CorDebugStateChange { PROCESS_RUNNING = 0x1, @@ -7800,57 +7807,57 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0040_v0_0_s_ifspec; #define __ICorDebugDebugEvent_INTERFACE_DEFINED__ /* interface ICorDebugDebugEvent */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugDebugEvent; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("41BD395D-DE99-48F1-BF7A-CC0F44A6D281") ICorDebugDebugEvent : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetEventKind( + virtual HRESULT STDMETHODCALLTYPE GetEventKind( /* [out] */ CorDebugDebugEventKind *pDebugEventKind) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetThread( + + virtual HRESULT STDMETHODCALLTYPE GetThread( /* [out] */ ICorDebugThread **ppThread) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugDebugEventVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDebugEvent * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDebugEvent * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDebugEvent * This); - + DECLSPEC_XFGVIRT(ICorDebugDebugEvent, GetEventKind) - HRESULT ( STDMETHODCALLTYPE *GetEventKind )( + HRESULT ( STDMETHODCALLTYPE *GetEventKind )( ICorDebugDebugEvent * This, /* [out] */ CorDebugDebugEventKind *pDebugEventKind); - + DECLSPEC_XFGVIRT(ICorDebugDebugEvent, GetThread) - HRESULT ( STDMETHODCALLTYPE *GetThread )( + HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugDebugEvent * This, /* [out] */ ICorDebugThread **ppThread); - + END_INTERFACE } ICorDebugDebugEventVtbl; @@ -7859,26 +7866,26 @@ EXTERN_C const IID IID_ICorDebugDebugEvent; CONST_VTBL struct ICorDebugDebugEventVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugDebugEvent_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDebugEvent_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDebugEvent_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDebugEvent_GetEventKind(This,pDebugEventKind) \ - ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) + ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) #define ICorDebugDebugEvent_GetThread(This,ppThread) \ - ( (This)->lpVtbl -> GetThread(This,ppThread) ) + ( (This)->lpVtbl -> GetThread(This,ppThread) ) #endif /* COBJMACROS */ @@ -7892,23 +7899,23 @@ EXTERN_C const IID IID_ICorDebugDebugEvent; /* interface __MIDL_itf_cordebug_0000_0041 */ -/* [local] */ +/* [local] */ -typedef +typedef enum CorDebugCodeInvokeKind { CODE_INVOKE_KIND_NONE = 0, CODE_INVOKE_KIND_RETURN = ( CODE_INVOKE_KIND_NONE + 1 ) , - CODE_INVOKE_KIND_TAILCALL = ( CODE_INVOKE_KIND_RETURN + 1 ) + CODE_INVOKE_KIND_TAILCALL = ( CODE_INVOKE_KIND_RETURN + 1 ) } CorDebugCodeInvokeKind; -typedef +typedef enum CorDebugCodeInvokePurpose { CODE_INVOKE_PURPOSE_NONE = 0, CODE_INVOKE_PURPOSE_NATIVE_TO_MANAGED_TRANSITION = ( CODE_INVOKE_PURPOSE_NONE + 1 ) , CODE_INVOKE_PURPOSE_CLASS_INIT = ( CODE_INVOKE_PURPOSE_NATIVE_TO_MANAGED_TRANSITION + 1 ) , - CODE_INVOKE_PURPOSE_INTERFACE_DISPATCH = ( CODE_INVOKE_PURPOSE_CLASS_INIT + 1 ) + CODE_INVOKE_PURPOSE_INTERFACE_DISPATCH = ( CODE_INVOKE_PURPOSE_CLASS_INIT + 1 ) } CorDebugCodeInvokePurpose; @@ -7920,69 +7927,69 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0041_v0_0_s_ifspec; #define __ICorDebugProcess6_INTERFACE_DEFINED__ /* interface ICorDebugProcess6 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess6; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("11588775-7205-4CEB-A41A-93753C3153E9") ICorDebugProcess6 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE DecodeEvent( + virtual HRESULT STDMETHODCALLTYPE DecodeEvent( /* [size_is][length_is][in] */ const BYTE pRecord[ ], /* [in] */ DWORD countBytes, /* [in] */ CorDebugRecordFormat format, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwThreadId, /* [out] */ ICorDebugDebugEvent **ppEvent) = 0; - - virtual HRESULT STDMETHODCALLTYPE ProcessStateChanged( + + virtual HRESULT STDMETHODCALLTYPE ProcessStateChanged( /* [in] */ CorDebugStateChange change) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCode( + + virtual HRESULT STDMETHODCALLTYPE GetCode( /* [in] */ CORDB_ADDRESS codeAddress, /* [out] */ ICorDebugCode **ppCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnableVirtualModuleSplitting( + + virtual HRESULT STDMETHODCALLTYPE EnableVirtualModuleSplitting( BOOL enableSplitting) = 0; - - virtual HRESULT STDMETHODCALLTYPE MarkDebuggerAttached( + + virtual HRESULT STDMETHODCALLTYPE MarkDebuggerAttached( BOOL fIsAttached) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetExportStepInfo( + + virtual HRESULT STDMETHODCALLTYPE GetExportStepInfo( /* [in] */ LPCWSTR pszExportName, /* [out] */ CorDebugCodeInvokeKind *pInvokeKind, /* [out] */ CorDebugCodeInvokePurpose *pInvokePurpose) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess6Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess6 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess6 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess6 * This); - + DECLSPEC_XFGVIRT(ICorDebugProcess6, DecodeEvent) - HRESULT ( STDMETHODCALLTYPE *DecodeEvent )( + HRESULT ( STDMETHODCALLTYPE *DecodeEvent )( ICorDebugProcess6 * This, /* [size_is][length_is][in] */ const BYTE pRecord[ ], /* [in] */ DWORD countBytes, @@ -7990,35 +7997,35 @@ EXTERN_C const IID IID_ICorDebugProcess6; /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwThreadId, /* [out] */ ICorDebugDebugEvent **ppEvent); - + DECLSPEC_XFGVIRT(ICorDebugProcess6, ProcessStateChanged) - HRESULT ( STDMETHODCALLTYPE *ProcessStateChanged )( + HRESULT ( STDMETHODCALLTYPE *ProcessStateChanged )( ICorDebugProcess6 * This, /* [in] */ CorDebugStateChange change); - + DECLSPEC_XFGVIRT(ICorDebugProcess6, GetCode) - HRESULT ( STDMETHODCALLTYPE *GetCode )( + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugProcess6 * This, /* [in] */ CORDB_ADDRESS codeAddress, /* [out] */ ICorDebugCode **ppCode); - + DECLSPEC_XFGVIRT(ICorDebugProcess6, EnableVirtualModuleSplitting) - HRESULT ( STDMETHODCALLTYPE *EnableVirtualModuleSplitting )( + HRESULT ( STDMETHODCALLTYPE *EnableVirtualModuleSplitting )( ICorDebugProcess6 * This, BOOL enableSplitting); - + DECLSPEC_XFGVIRT(ICorDebugProcess6, MarkDebuggerAttached) - HRESULT ( STDMETHODCALLTYPE *MarkDebuggerAttached )( + HRESULT ( STDMETHODCALLTYPE *MarkDebuggerAttached )( ICorDebugProcess6 * This, BOOL fIsAttached); - + DECLSPEC_XFGVIRT(ICorDebugProcess6, GetExportStepInfo) - HRESULT ( STDMETHODCALLTYPE *GetExportStepInfo )( + HRESULT ( STDMETHODCALLTYPE *GetExportStepInfo )( ICorDebugProcess6 * This, /* [in] */ LPCWSTR pszExportName, /* [out] */ CorDebugCodeInvokeKind *pInvokeKind, /* [out] */ CorDebugCodeInvokePurpose *pInvokePurpose); - + END_INTERFACE } ICorDebugProcess6Vtbl; @@ -8027,38 +8034,38 @@ EXTERN_C const IID IID_ICorDebugProcess6; CONST_VTBL struct ICorDebugProcess6Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess6_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess6_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess6_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess6_DecodeEvent(This,pRecord,countBytes,format,dwFlags,dwThreadId,ppEvent) \ - ( (This)->lpVtbl -> DecodeEvent(This,pRecord,countBytes,format,dwFlags,dwThreadId,ppEvent) ) + ( (This)->lpVtbl -> DecodeEvent(This,pRecord,countBytes,format,dwFlags,dwThreadId,ppEvent) ) #define ICorDebugProcess6_ProcessStateChanged(This,change) \ - ( (This)->lpVtbl -> ProcessStateChanged(This,change) ) + ( (This)->lpVtbl -> ProcessStateChanged(This,change) ) #define ICorDebugProcess6_GetCode(This,codeAddress,ppCode) \ - ( (This)->lpVtbl -> GetCode(This,codeAddress,ppCode) ) + ( (This)->lpVtbl -> GetCode(This,codeAddress,ppCode) ) #define ICorDebugProcess6_EnableVirtualModuleSplitting(This,enableSplitting) \ - ( (This)->lpVtbl -> EnableVirtualModuleSplitting(This,enableSplitting) ) + ( (This)->lpVtbl -> EnableVirtualModuleSplitting(This,enableSplitting) ) #define ICorDebugProcess6_MarkDebuggerAttached(This,fIsAttached) \ - ( (This)->lpVtbl -> MarkDebuggerAttached(This,fIsAttached) ) + ( (This)->lpVtbl -> MarkDebuggerAttached(This,fIsAttached) ) #define ICorDebugProcess6_GetExportStepInfo(This,pszExportName,pInvokeKind,pInvokePurpose) \ - ( (This)->lpVtbl -> GetExportStepInfo(This,pszExportName,pInvokeKind,pInvokePurpose) ) + ( (This)->lpVtbl -> GetExportStepInfo(This,pszExportName,pInvokeKind,pInvokePurpose) ) #endif /* COBJMACROS */ @@ -8072,13 +8079,13 @@ EXTERN_C const IID IID_ICorDebugProcess6; /* interface __MIDL_itf_cordebug_0000_0042 */ -/* [local] */ +/* [local] */ -typedef +typedef enum WriteableMetadataUpdateMode { LegacyCompatPolicy = 0, - AlwaysShowUpdates = ( LegacyCompatPolicy + 1 ) + AlwaysShowUpdates = ( LegacyCompatPolicy + 1 ) } WriteableMetadataUpdateMode; @@ -8090,49 +8097,49 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0042_v0_0_s_ifspec; #define __ICorDebugProcess7_INTERFACE_DEFINED__ /* interface ICorDebugProcess7 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess7; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("9B2C54E4-119F-4D6F-B402-527603266D69") ICorDebugProcess7 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE SetWriteableMetadataUpdateMode( + virtual HRESULT STDMETHODCALLTYPE SetWriteableMetadataUpdateMode( WriteableMetadataUpdateMode flags) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess7Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess7 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess7 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess7 * This); - + DECLSPEC_XFGVIRT(ICorDebugProcess7, SetWriteableMetadataUpdateMode) - HRESULT ( STDMETHODCALLTYPE *SetWriteableMetadataUpdateMode )( + HRESULT ( STDMETHODCALLTYPE *SetWriteableMetadataUpdateMode )( ICorDebugProcess7 * This, WriteableMetadataUpdateMode flags); - + END_INTERFACE } ICorDebugProcess7Vtbl; @@ -8141,23 +8148,23 @@ EXTERN_C const IID IID_ICorDebugProcess7; CONST_VTBL struct ICorDebugProcess7Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess7_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess7_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess7_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess7_SetWriteableMetadataUpdateMode(This,flags) \ - ( (This)->lpVtbl -> SetWriteableMetadataUpdateMode(This,flags) ) + ( (This)->lpVtbl -> SetWriteableMetadataUpdateMode(This,flags) ) #endif /* COBJMACROS */ @@ -8174,49 +8181,49 @@ EXTERN_C const IID IID_ICorDebugProcess7; #define __ICorDebugProcess8_INTERFACE_DEFINED__ /* interface ICorDebugProcess8 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess8; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("2E6F28C1-85EB-4141-80AD-0A90944B9639") ICorDebugProcess8 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE EnableExceptionCallbacksOutsideOfMyCode( + virtual HRESULT STDMETHODCALLTYPE EnableExceptionCallbacksOutsideOfMyCode( /* [in] */ BOOL enableExceptionsOutsideOfJMC) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess8Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess8 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess8 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess8 * This); - + DECLSPEC_XFGVIRT(ICorDebugProcess8, EnableExceptionCallbacksOutsideOfMyCode) - HRESULT ( STDMETHODCALLTYPE *EnableExceptionCallbacksOutsideOfMyCode )( + HRESULT ( STDMETHODCALLTYPE *EnableExceptionCallbacksOutsideOfMyCode )( ICorDebugProcess8 * This, /* [in] */ BOOL enableExceptionsOutsideOfJMC); - + END_INTERFACE } ICorDebugProcess8Vtbl; @@ -8225,23 +8232,23 @@ EXTERN_C const IID IID_ICorDebugProcess8; CONST_VTBL struct ICorDebugProcess8Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess8_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess8_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess8_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess8_EnableExceptionCallbacksOutsideOfMyCode(This,enableExceptionsOutsideOfJMC) \ - ( (This)->lpVtbl -> EnableExceptionCallbacksOutsideOfMyCode(This,enableExceptionsOutsideOfJMC) ) + ( (This)->lpVtbl -> EnableExceptionCallbacksOutsideOfMyCode(This,enableExceptionsOutsideOfJMC) ) #endif /* COBJMACROS */ @@ -8258,49 +8265,49 @@ EXTERN_C const IID IID_ICorDebugProcess8; #define __ICorDebugProcess10_INTERFACE_DEFINED__ /* interface ICorDebugProcess10 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess10; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("8F378F6F-1017-4461-9890-ECF64C54079F") ICorDebugProcess10 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE EnableGCNotificationEvents( + virtual HRESULT STDMETHODCALLTYPE EnableGCNotificationEvents( BOOL fEnable) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess10Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess10 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess10 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess10 * This); - + DECLSPEC_XFGVIRT(ICorDebugProcess10, EnableGCNotificationEvents) - HRESULT ( STDMETHODCALLTYPE *EnableGCNotificationEvents )( + HRESULT ( STDMETHODCALLTYPE *EnableGCNotificationEvents )( ICorDebugProcess10 * This, BOOL fEnable); - + END_INTERFACE } ICorDebugProcess10Vtbl; @@ -8309,23 +8316,23 @@ EXTERN_C const IID IID_ICorDebugProcess10; CONST_VTBL struct ICorDebugProcess10Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess10_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess10_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess10_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess10_EnableGCNotificationEvents(This,fEnable) \ - ( (This)->lpVtbl -> EnableGCNotificationEvents(This,fEnable) ) + ( (This)->lpVtbl -> EnableGCNotificationEvents(This,fEnable) ) #endif /* COBJMACROS */ @@ -8339,7 +8346,7 @@ EXTERN_C const IID IID_ICorDebugProcess10; /* interface __MIDL_itf_cordebug_0000_0045 */ -/* [local] */ +/* [local] */ typedef struct _COR_MEMORY_RANGE { @@ -8356,72 +8363,72 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0045_v0_0_s_ifspec; #define __ICorDebugMemoryRangeEnum_INTERFACE_DEFINED__ /* interface ICorDebugMemoryRangeEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugMemoryRangeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("D1A0BCFC-5865-4437-BE3F-36F022951F8A") ICorDebugMemoryRangeEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_MEMORY_RANGE objects[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugMemoryRangeEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMemoryRangeEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMemoryRangeEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMemoryRangeEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugMemoryRangeEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugMemoryRangeEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugMemoryRangeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugMemoryRangeEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugMemoryRangeEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugMemoryRangeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_MEMORY_RANGE objects[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugMemoryRangeEnumVtbl; @@ -8430,36 +8437,36 @@ EXTERN_C const IID IID_ICorDebugMemoryRangeEnum; CONST_VTBL struct ICorDebugMemoryRangeEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugMemoryRangeEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMemoryRangeEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMemoryRangeEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMemoryRangeEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugMemoryRangeEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugMemoryRangeEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugMemoryRangeEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugMemoryRangeEnum_Next(This,celt,objects,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) #endif /* COBJMACROS */ @@ -8476,49 +8483,49 @@ EXTERN_C const IID IID_ICorDebugMemoryRangeEnum; #define __ICorDebugProcess11_INTERFACE_DEFINED__ /* interface ICorDebugProcess11 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess11; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("344B37AA-F2C0-4D3B-9909-91CCF787DA8C") ICorDebugProcess11 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE EnumerateLoaderHeapMemoryRegions( + virtual HRESULT STDMETHODCALLTYPE EnumerateLoaderHeapMemoryRegions( /* [out] */ ICorDebugMemoryRangeEnum **ppRanges) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess11Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess11 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess11 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess11 * This); - + DECLSPEC_XFGVIRT(ICorDebugProcess11, EnumerateLoaderHeapMemoryRegions) - HRESULT ( STDMETHODCALLTYPE *EnumerateLoaderHeapMemoryRegions )( + HRESULT ( STDMETHODCALLTYPE *EnumerateLoaderHeapMemoryRegions )( ICorDebugProcess11 * This, /* [out] */ ICorDebugMemoryRangeEnum **ppRanges); - + END_INTERFACE } ICorDebugProcess11Vtbl; @@ -8527,23 +8534,23 @@ EXTERN_C const IID IID_ICorDebugProcess11; CONST_VTBL struct ICorDebugProcess11Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess11_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess11_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess11_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess11_EnumerateLoaderHeapMemoryRegions(This,ppRanges) \ - ( (This)->lpVtbl -> EnumerateLoaderHeapMemoryRegions(This,ppRanges) ) + ( (This)->lpVtbl -> EnumerateLoaderHeapMemoryRegions(This,ppRanges) ) #endif /* COBJMACROS */ @@ -8560,59 +8567,59 @@ EXTERN_C const IID IID_ICorDebugProcess11; #define __ICorDebugModuleDebugEvent_INTERFACE_DEFINED__ /* interface ICorDebugModuleDebugEvent */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModuleDebugEvent; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("51A15E8D-9FFF-4864-9B87-F4FBDEA747A2") ICorDebugModuleDebugEvent : public ICorDebugDebugEvent { public: - virtual HRESULT STDMETHODCALLTYPE GetModule( + virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **ppModule) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugModuleDebugEventVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModuleDebugEvent * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModuleDebugEvent * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModuleDebugEvent * This); - + DECLSPEC_XFGVIRT(ICorDebugDebugEvent, GetEventKind) - HRESULT ( STDMETHODCALLTYPE *GetEventKind )( + HRESULT ( STDMETHODCALLTYPE *GetEventKind )( ICorDebugModuleDebugEvent * This, /* [out] */ CorDebugDebugEventKind *pDebugEventKind); - + DECLSPEC_XFGVIRT(ICorDebugDebugEvent, GetThread) - HRESULT ( STDMETHODCALLTYPE *GetThread )( + HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugModuleDebugEvent * This, /* [out] */ ICorDebugThread **ppThread); - + DECLSPEC_XFGVIRT(ICorDebugModuleDebugEvent, GetModule) - HRESULT ( STDMETHODCALLTYPE *GetModule )( + HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugModuleDebugEvent * This, /* [out] */ ICorDebugModule **ppModule); - + END_INTERFACE } ICorDebugModuleDebugEventVtbl; @@ -8621,30 +8628,30 @@ EXTERN_C const IID IID_ICorDebugModuleDebugEvent; CONST_VTBL struct ICorDebugModuleDebugEventVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugModuleDebugEvent_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModuleDebugEvent_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModuleDebugEvent_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModuleDebugEvent_GetEventKind(This,pDebugEventKind) \ - ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) + ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) #define ICorDebugModuleDebugEvent_GetThread(This,ppThread) \ - ( (This)->lpVtbl -> GetThread(This,ppThread) ) + ( (This)->lpVtbl -> GetThread(This,ppThread) ) #define ICorDebugModuleDebugEvent_GetModule(This,ppModule) \ - ( (This)->lpVtbl -> GetModule(This,ppModule) ) + ( (This)->lpVtbl -> GetModule(This,ppModule) ) #endif /* COBJMACROS */ @@ -8661,75 +8668,75 @@ EXTERN_C const IID IID_ICorDebugModuleDebugEvent; #define __ICorDebugExceptionDebugEvent_INTERFACE_DEFINED__ /* interface ICorDebugExceptionDebugEvent */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugExceptionDebugEvent; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("AF79EC94-4752-419C-A626-5FB1CC1A5AB7") ICorDebugExceptionDebugEvent : public ICorDebugDebugEvent { public: - virtual HRESULT STDMETHODCALLTYPE GetStackPointer( + virtual HRESULT STDMETHODCALLTYPE GetStackPointer( /* [out] */ CORDB_ADDRESS *pStackPointer) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetNativeIP( + + virtual HRESULT STDMETHODCALLTYPE GetNativeIP( /* [out] */ CORDB_ADDRESS *pIP) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFlags( + + virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [out] */ CorDebugExceptionFlags *pdwFlags) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugExceptionDebugEventVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugExceptionDebugEvent * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugExceptionDebugEvent * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugExceptionDebugEvent * This); - + DECLSPEC_XFGVIRT(ICorDebugDebugEvent, GetEventKind) - HRESULT ( STDMETHODCALLTYPE *GetEventKind )( + HRESULT ( STDMETHODCALLTYPE *GetEventKind )( ICorDebugExceptionDebugEvent * This, /* [out] */ CorDebugDebugEventKind *pDebugEventKind); - + DECLSPEC_XFGVIRT(ICorDebugDebugEvent, GetThread) - HRESULT ( STDMETHODCALLTYPE *GetThread )( + HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugExceptionDebugEvent * This, /* [out] */ ICorDebugThread **ppThread); - + DECLSPEC_XFGVIRT(ICorDebugExceptionDebugEvent, GetStackPointer) - HRESULT ( STDMETHODCALLTYPE *GetStackPointer )( + HRESULT ( STDMETHODCALLTYPE *GetStackPointer )( ICorDebugExceptionDebugEvent * This, /* [out] */ CORDB_ADDRESS *pStackPointer); - + DECLSPEC_XFGVIRT(ICorDebugExceptionDebugEvent, GetNativeIP) - HRESULT ( STDMETHODCALLTYPE *GetNativeIP )( + HRESULT ( STDMETHODCALLTYPE *GetNativeIP )( ICorDebugExceptionDebugEvent * This, /* [out] */ CORDB_ADDRESS *pIP); - + DECLSPEC_XFGVIRT(ICorDebugExceptionDebugEvent, GetFlags) - HRESULT ( STDMETHODCALLTYPE *GetFlags )( + HRESULT ( STDMETHODCALLTYPE *GetFlags )( ICorDebugExceptionDebugEvent * This, /* [out] */ CorDebugExceptionFlags *pdwFlags); - + END_INTERFACE } ICorDebugExceptionDebugEventVtbl; @@ -8738,36 +8745,36 @@ EXTERN_C const IID IID_ICorDebugExceptionDebugEvent; CONST_VTBL struct ICorDebugExceptionDebugEventVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugExceptionDebugEvent_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugExceptionDebugEvent_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugExceptionDebugEvent_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugExceptionDebugEvent_GetEventKind(This,pDebugEventKind) \ - ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) + ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) #define ICorDebugExceptionDebugEvent_GetThread(This,ppThread) \ - ( (This)->lpVtbl -> GetThread(This,ppThread) ) + ( (This)->lpVtbl -> GetThread(This,ppThread) ) #define ICorDebugExceptionDebugEvent_GetStackPointer(This,pStackPointer) \ - ( (This)->lpVtbl -> GetStackPointer(This,pStackPointer) ) + ( (This)->lpVtbl -> GetStackPointer(This,pStackPointer) ) #define ICorDebugExceptionDebugEvent_GetNativeIP(This,pIP) \ - ( (This)->lpVtbl -> GetNativeIP(This,pIP) ) + ( (This)->lpVtbl -> GetNativeIP(This,pIP) ) #define ICorDebugExceptionDebugEvent_GetFlags(This,pdwFlags) \ - ( (This)->lpVtbl -> GetFlags(This,pdwFlags) ) + ( (This)->lpVtbl -> GetFlags(This,pdwFlags) ) #endif /* COBJMACROS */ @@ -8784,57 +8791,57 @@ EXTERN_C const IID IID_ICorDebugExceptionDebugEvent; #define __ICorDebugBreakpoint_INTERFACE_DEFINED__ /* interface ICorDebugBreakpoint */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugBreakpoint; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAE8-8A68-11d2-983C-0000F808342D") ICorDebugBreakpoint : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE Activate( + virtual HRESULT STDMETHODCALLTYPE Activate( /* [in] */ BOOL bActive) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsActive( + + virtual HRESULT STDMETHODCALLTYPE IsActive( /* [out] */ BOOL *pbActive) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugBreakpointVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugBreakpoint * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugBreakpoint * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugBreakpoint * This); - + DECLSPEC_XFGVIRT(ICorDebugBreakpoint, Activate) - HRESULT ( STDMETHODCALLTYPE *Activate )( + HRESULT ( STDMETHODCALLTYPE *Activate )( ICorDebugBreakpoint * This, /* [in] */ BOOL bActive); - + DECLSPEC_XFGVIRT(ICorDebugBreakpoint, IsActive) - HRESULT ( STDMETHODCALLTYPE *IsActive )( + HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugBreakpoint * This, /* [out] */ BOOL *pbActive); - + END_INTERFACE } ICorDebugBreakpointVtbl; @@ -8843,26 +8850,26 @@ EXTERN_C const IID IID_ICorDebugBreakpoint; CONST_VTBL struct ICorDebugBreakpointVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugBreakpoint_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugBreakpoint_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugBreakpoint_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugBreakpoint_Activate(This,bActive) \ - ( (This)->lpVtbl -> Activate(This,bActive) ) + ( (This)->lpVtbl -> Activate(This,bActive) ) #define ICorDebugBreakpoint_IsActive(This,pbActive) \ - ( (This)->lpVtbl -> IsActive(This,pbActive) ) + ( (This)->lpVtbl -> IsActive(This,pbActive) ) #endif /* COBJMACROS */ @@ -8879,67 +8886,67 @@ EXTERN_C const IID IID_ICorDebugBreakpoint; #define __ICorDebugFunctionBreakpoint_INTERFACE_DEFINED__ /* interface ICorDebugFunctionBreakpoint */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunctionBreakpoint; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAE9-8A68-11d2-983C-0000F808342D") ICorDebugFunctionBreakpoint : public ICorDebugBreakpoint { public: - virtual HRESULT STDMETHODCALLTYPE GetFunction( + virtual HRESULT STDMETHODCALLTYPE GetFunction( /* [out] */ ICorDebugFunction **ppFunction) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetOffset( + + virtual HRESULT STDMETHODCALLTYPE GetOffset( /* [out] */ ULONG32 *pnOffset) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFunctionBreakpointVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunctionBreakpoint * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunctionBreakpoint * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunctionBreakpoint * This); - + DECLSPEC_XFGVIRT(ICorDebugBreakpoint, Activate) - HRESULT ( STDMETHODCALLTYPE *Activate )( + HRESULT ( STDMETHODCALLTYPE *Activate )( ICorDebugFunctionBreakpoint * This, /* [in] */ BOOL bActive); - + DECLSPEC_XFGVIRT(ICorDebugBreakpoint, IsActive) - HRESULT ( STDMETHODCALLTYPE *IsActive )( + HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugFunctionBreakpoint * This, /* [out] */ BOOL *pbActive); - + DECLSPEC_XFGVIRT(ICorDebugFunctionBreakpoint, GetFunction) - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugFunctionBreakpoint * This, /* [out] */ ICorDebugFunction **ppFunction); - + DECLSPEC_XFGVIRT(ICorDebugFunctionBreakpoint, GetOffset) - HRESULT ( STDMETHODCALLTYPE *GetOffset )( + HRESULT ( STDMETHODCALLTYPE *GetOffset )( ICorDebugFunctionBreakpoint * This, /* [out] */ ULONG32 *pnOffset); - + END_INTERFACE } ICorDebugFunctionBreakpointVtbl; @@ -8948,33 +8955,33 @@ EXTERN_C const IID IID_ICorDebugFunctionBreakpoint; CONST_VTBL struct ICorDebugFunctionBreakpointVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFunctionBreakpoint_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunctionBreakpoint_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunctionBreakpoint_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunctionBreakpoint_Activate(This,bActive) \ - ( (This)->lpVtbl -> Activate(This,bActive) ) + ( (This)->lpVtbl -> Activate(This,bActive) ) #define ICorDebugFunctionBreakpoint_IsActive(This,pbActive) \ - ( (This)->lpVtbl -> IsActive(This,pbActive) ) + ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugFunctionBreakpoint_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugFunctionBreakpoint_GetOffset(This,pnOffset) \ - ( (This)->lpVtbl -> GetOffset(This,pnOffset) ) + ( (This)->lpVtbl -> GetOffset(This,pnOffset) ) #endif /* COBJMACROS */ @@ -8991,59 +8998,59 @@ EXTERN_C const IID IID_ICorDebugFunctionBreakpoint; #define __ICorDebugModuleBreakpoint_INTERFACE_DEFINED__ /* interface ICorDebugModuleBreakpoint */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModuleBreakpoint; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAEA-8A68-11d2-983C-0000F808342D") ICorDebugModuleBreakpoint : public ICorDebugBreakpoint { public: - virtual HRESULT STDMETHODCALLTYPE GetModule( + virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **ppModule) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugModuleBreakpointVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModuleBreakpoint * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModuleBreakpoint * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModuleBreakpoint * This); - + DECLSPEC_XFGVIRT(ICorDebugBreakpoint, Activate) - HRESULT ( STDMETHODCALLTYPE *Activate )( + HRESULT ( STDMETHODCALLTYPE *Activate )( ICorDebugModuleBreakpoint * This, /* [in] */ BOOL bActive); - + DECLSPEC_XFGVIRT(ICorDebugBreakpoint, IsActive) - HRESULT ( STDMETHODCALLTYPE *IsActive )( + HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugModuleBreakpoint * This, /* [out] */ BOOL *pbActive); - + DECLSPEC_XFGVIRT(ICorDebugModuleBreakpoint, GetModule) - HRESULT ( STDMETHODCALLTYPE *GetModule )( + HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugModuleBreakpoint * This, /* [out] */ ICorDebugModule **ppModule); - + END_INTERFACE } ICorDebugModuleBreakpointVtbl; @@ -9052,30 +9059,30 @@ EXTERN_C const IID IID_ICorDebugModuleBreakpoint; CONST_VTBL struct ICorDebugModuleBreakpointVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugModuleBreakpoint_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModuleBreakpoint_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModuleBreakpoint_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModuleBreakpoint_Activate(This,bActive) \ - ( (This)->lpVtbl -> Activate(This,bActive) ) + ( (This)->lpVtbl -> Activate(This,bActive) ) #define ICorDebugModuleBreakpoint_IsActive(This,pbActive) \ - ( (This)->lpVtbl -> IsActive(This,pbActive) ) + ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugModuleBreakpoint_GetModule(This,ppModule) \ - ( (This)->lpVtbl -> GetModule(This,ppModule) ) + ( (This)->lpVtbl -> GetModule(This,ppModule) ) #endif /* COBJMACROS */ @@ -9092,59 +9099,59 @@ EXTERN_C const IID IID_ICorDebugModuleBreakpoint; #define __ICorDebugValueBreakpoint_INTERFACE_DEFINED__ /* interface ICorDebugValueBreakpoint */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValueBreakpoint; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAEB-8A68-11d2-983C-0000F808342D") ICorDebugValueBreakpoint : public ICorDebugBreakpoint { public: - virtual HRESULT STDMETHODCALLTYPE GetValue( + virtual HRESULT STDMETHODCALLTYPE GetValue( /* [out] */ ICorDebugValue **ppValue) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugValueBreakpointVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValueBreakpoint * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValueBreakpoint * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValueBreakpoint * This); - + DECLSPEC_XFGVIRT(ICorDebugBreakpoint, Activate) - HRESULT ( STDMETHODCALLTYPE *Activate )( + HRESULT ( STDMETHODCALLTYPE *Activate )( ICorDebugValueBreakpoint * This, /* [in] */ BOOL bActive); - + DECLSPEC_XFGVIRT(ICorDebugBreakpoint, IsActive) - HRESULT ( STDMETHODCALLTYPE *IsActive )( + HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugValueBreakpoint * This, /* [out] */ BOOL *pbActive); - + DECLSPEC_XFGVIRT(ICorDebugValueBreakpoint, GetValue) - HRESULT ( STDMETHODCALLTYPE *GetValue )( + HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugValueBreakpoint * This, /* [out] */ ICorDebugValue **ppValue); - + END_INTERFACE } ICorDebugValueBreakpointVtbl; @@ -9153,30 +9160,30 @@ EXTERN_C const IID IID_ICorDebugValueBreakpoint; CONST_VTBL struct ICorDebugValueBreakpointVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugValueBreakpoint_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValueBreakpoint_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValueBreakpoint_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValueBreakpoint_Activate(This,bActive) \ - ( (This)->lpVtbl -> Activate(This,bActive) ) + ( (This)->lpVtbl -> Activate(This,bActive) ) #define ICorDebugValueBreakpoint_IsActive(This,pbActive) \ - ( (This)->lpVtbl -> IsActive(This,pbActive) ) + ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugValueBreakpoint_GetValue(This,ppValue) \ - ( (This)->lpVtbl -> GetValue(This,ppValue) ) + ( (This)->lpVtbl -> GetValue(This,ppValue) ) #endif /* COBJMACROS */ @@ -9193,9 +9200,9 @@ EXTERN_C const IID IID_ICorDebugValueBreakpoint; #define __ICorDebugStepper_INTERFACE_DEFINED__ /* interface ICorDebugStepper */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugIntercept { INTERCEPT_NONE = 0, @@ -9207,7 +9214,7 @@ enum CorDebugIntercept INTERCEPT_ALL = 0xffff } CorDebugIntercept; -typedef +typedef enum CorDebugUnmappedStop { STOP_NONE = 0, @@ -9229,99 +9236,99 @@ typedef struct COR_DEBUG_STEP_RANGE EXTERN_C const IID IID_ICorDebugStepper; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAEC-8A68-11d2-983C-0000F808342D") ICorDebugStepper : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE IsActive( + virtual HRESULT STDMETHODCALLTYPE IsActive( /* [out] */ BOOL *pbActive) = 0; - + virtual HRESULT STDMETHODCALLTYPE Deactivate( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetInterceptMask( + + virtual HRESULT STDMETHODCALLTYPE SetInterceptMask( /* [in] */ CorDebugIntercept mask) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetUnmappedStopMask( + + virtual HRESULT STDMETHODCALLTYPE SetUnmappedStopMask( /* [in] */ CorDebugUnmappedStop mask) = 0; - - virtual HRESULT STDMETHODCALLTYPE Step( + + virtual HRESULT STDMETHODCALLTYPE Step( /* [in] */ BOOL bStepIn) = 0; - - virtual HRESULT STDMETHODCALLTYPE StepRange( + + virtual HRESULT STDMETHODCALLTYPE StepRange( /* [in] */ BOOL bStepIn, /* [size_is][in] */ COR_DEBUG_STEP_RANGE ranges[ ], /* [in] */ ULONG32 cRangeCount) = 0; - + virtual HRESULT STDMETHODCALLTYPE StepOut( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetRangeIL( + + virtual HRESULT STDMETHODCALLTYPE SetRangeIL( /* [in] */ BOOL bIL) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugStepperVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStepper * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStepper * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStepper * This); - + DECLSPEC_XFGVIRT(ICorDebugStepper, IsActive) - HRESULT ( STDMETHODCALLTYPE *IsActive )( + HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugStepper * This, /* [out] */ BOOL *pbActive); - + DECLSPEC_XFGVIRT(ICorDebugStepper, Deactivate) - HRESULT ( STDMETHODCALLTYPE *Deactivate )( + HRESULT ( STDMETHODCALLTYPE *Deactivate )( ICorDebugStepper * This); - + DECLSPEC_XFGVIRT(ICorDebugStepper, SetInterceptMask) - HRESULT ( STDMETHODCALLTYPE *SetInterceptMask )( + HRESULT ( STDMETHODCALLTYPE *SetInterceptMask )( ICorDebugStepper * This, /* [in] */ CorDebugIntercept mask); - + DECLSPEC_XFGVIRT(ICorDebugStepper, SetUnmappedStopMask) - HRESULT ( STDMETHODCALLTYPE *SetUnmappedStopMask )( + HRESULT ( STDMETHODCALLTYPE *SetUnmappedStopMask )( ICorDebugStepper * This, /* [in] */ CorDebugUnmappedStop mask); - + DECLSPEC_XFGVIRT(ICorDebugStepper, Step) - HRESULT ( STDMETHODCALLTYPE *Step )( + HRESULT ( STDMETHODCALLTYPE *Step )( ICorDebugStepper * This, /* [in] */ BOOL bStepIn); - + DECLSPEC_XFGVIRT(ICorDebugStepper, StepRange) - HRESULT ( STDMETHODCALLTYPE *StepRange )( + HRESULT ( STDMETHODCALLTYPE *StepRange )( ICorDebugStepper * This, /* [in] */ BOOL bStepIn, /* [size_is][in] */ COR_DEBUG_STEP_RANGE ranges[ ], /* [in] */ ULONG32 cRangeCount); - + DECLSPEC_XFGVIRT(ICorDebugStepper, StepOut) - HRESULT ( STDMETHODCALLTYPE *StepOut )( + HRESULT ( STDMETHODCALLTYPE *StepOut )( ICorDebugStepper * This); - + DECLSPEC_XFGVIRT(ICorDebugStepper, SetRangeIL) - HRESULT ( STDMETHODCALLTYPE *SetRangeIL )( + HRESULT ( STDMETHODCALLTYPE *SetRangeIL )( ICorDebugStepper * This, /* [in] */ BOOL bIL); - + END_INTERFACE } ICorDebugStepperVtbl; @@ -9330,44 +9337,44 @@ EXTERN_C const IID IID_ICorDebugStepper; CONST_VTBL struct ICorDebugStepperVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugStepper_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStepper_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStepper_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStepper_IsActive(This,pbActive) \ - ( (This)->lpVtbl -> IsActive(This,pbActive) ) + ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugStepper_Deactivate(This) \ - ( (This)->lpVtbl -> Deactivate(This) ) + ( (This)->lpVtbl -> Deactivate(This) ) #define ICorDebugStepper_SetInterceptMask(This,mask) \ - ( (This)->lpVtbl -> SetInterceptMask(This,mask) ) + ( (This)->lpVtbl -> SetInterceptMask(This,mask) ) #define ICorDebugStepper_SetUnmappedStopMask(This,mask) \ - ( (This)->lpVtbl -> SetUnmappedStopMask(This,mask) ) + ( (This)->lpVtbl -> SetUnmappedStopMask(This,mask) ) #define ICorDebugStepper_Step(This,bStepIn) \ - ( (This)->lpVtbl -> Step(This,bStepIn) ) + ( (This)->lpVtbl -> Step(This,bStepIn) ) #define ICorDebugStepper_StepRange(This,bStepIn,ranges,cRangeCount) \ - ( (This)->lpVtbl -> StepRange(This,bStepIn,ranges,cRangeCount) ) + ( (This)->lpVtbl -> StepRange(This,bStepIn,ranges,cRangeCount) ) #define ICorDebugStepper_StepOut(This) \ - ( (This)->lpVtbl -> StepOut(This) ) + ( (This)->lpVtbl -> StepOut(This) ) #define ICorDebugStepper_SetRangeIL(This,bIL) \ - ( (This)->lpVtbl -> SetRangeIL(This,bIL) ) + ( (This)->lpVtbl -> SetRangeIL(This,bIL) ) #endif /* COBJMACROS */ @@ -9384,49 +9391,49 @@ EXTERN_C const IID IID_ICorDebugStepper; #define __ICorDebugStepper2_INTERFACE_DEFINED__ /* interface ICorDebugStepper2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugStepper2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("C5B6E9C3-E7D1-4a8e-873B-7F047F0706F7") ICorDebugStepper2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE SetJMC( + virtual HRESULT STDMETHODCALLTYPE SetJMC( /* [in] */ BOOL fIsJMCStepper) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugStepper2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStepper2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStepper2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStepper2 * This); - + DECLSPEC_XFGVIRT(ICorDebugStepper2, SetJMC) - HRESULT ( STDMETHODCALLTYPE *SetJMC )( + HRESULT ( STDMETHODCALLTYPE *SetJMC )( ICorDebugStepper2 * This, /* [in] */ BOOL fIsJMCStepper); - + END_INTERFACE } ICorDebugStepper2Vtbl; @@ -9435,23 +9442,23 @@ EXTERN_C const IID IID_ICorDebugStepper2; CONST_VTBL struct ICorDebugStepper2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugStepper2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStepper2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStepper2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStepper2_SetJMC(This,fIsJMCStepper) \ - ( (This)->lpVtbl -> SetJMC(This,fIsJMCStepper) ) + ( (This)->lpVtbl -> SetJMC(This,fIsJMCStepper) ) #endif /* COBJMACROS */ @@ -9468,9 +9475,9 @@ EXTERN_C const IID IID_ICorDebugStepper2; #define __ICorDebugRegisterSet_INTERFACE_DEFINED__ /* interface ICorDebugRegisterSet */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugRegister { REGISTER_INSTRUCTION_POINTER = 0, @@ -9776,87 +9783,87 @@ enum CorDebugRegister EXTERN_C const IID IID_ICorDebugRegisterSet; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB0B-8A68-11d2-983C-0000F808342D") ICorDebugRegisterSet : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetRegistersAvailable( + virtual HRESULT STDMETHODCALLTYPE GetRegistersAvailable( /* [out] */ ULONG64 *pAvailable) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRegisters( + + virtual HRESULT STDMETHODCALLTYPE GetRegisters( /* [in] */ ULONG64 mask, /* [in] */ ULONG32 regCount, /* [length_is][size_is][out] */ CORDB_REGISTER regBuffer[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetRegisters( + + virtual HRESULT STDMETHODCALLTYPE SetRegisters( /* [in] */ ULONG64 mask, /* [in] */ ULONG32 regCount, /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetThreadContext( + + virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ ULONG32 contextSize, /* [size_is][length_is][out][in] */ BYTE context[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetThreadContext( + + virtual HRESULT STDMETHODCALLTYPE SetThreadContext( /* [in] */ ULONG32 contextSize, /* [size_is][length_is][in] */ BYTE context[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugRegisterSetVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRegisterSet * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRegisterSet * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRegisterSet * This); - + DECLSPEC_XFGVIRT(ICorDebugRegisterSet, GetRegistersAvailable) - HRESULT ( STDMETHODCALLTYPE *GetRegistersAvailable )( + HRESULT ( STDMETHODCALLTYPE *GetRegistersAvailable )( ICorDebugRegisterSet * This, /* [out] */ ULONG64 *pAvailable); - + DECLSPEC_XFGVIRT(ICorDebugRegisterSet, GetRegisters) - HRESULT ( STDMETHODCALLTYPE *GetRegisters )( + HRESULT ( STDMETHODCALLTYPE *GetRegisters )( ICorDebugRegisterSet * This, /* [in] */ ULONG64 mask, /* [in] */ ULONG32 regCount, /* [length_is][size_is][out] */ CORDB_REGISTER regBuffer[ ]); - + DECLSPEC_XFGVIRT(ICorDebugRegisterSet, SetRegisters) - HRESULT ( STDMETHODCALLTYPE *SetRegisters )( + HRESULT ( STDMETHODCALLTYPE *SetRegisters )( ICorDebugRegisterSet * This, /* [in] */ ULONG64 mask, /* [in] */ ULONG32 regCount, /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]); - + DECLSPEC_XFGVIRT(ICorDebugRegisterSet, GetThreadContext) - HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorDebugRegisterSet * This, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][out][in] */ BYTE context[ ]); - + DECLSPEC_XFGVIRT(ICorDebugRegisterSet, SetThreadContext) - HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( + HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( ICorDebugRegisterSet * This, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][in] */ BYTE context[ ]); - + END_INTERFACE } ICorDebugRegisterSetVtbl; @@ -9865,35 +9872,35 @@ EXTERN_C const IID IID_ICorDebugRegisterSet; CONST_VTBL struct ICorDebugRegisterSetVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugRegisterSet_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRegisterSet_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRegisterSet_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRegisterSet_GetRegistersAvailable(This,pAvailable) \ - ( (This)->lpVtbl -> GetRegistersAvailable(This,pAvailable) ) + ( (This)->lpVtbl -> GetRegistersAvailable(This,pAvailable) ) #define ICorDebugRegisterSet_GetRegisters(This,mask,regCount,regBuffer) \ - ( (This)->lpVtbl -> GetRegisters(This,mask,regCount,regBuffer) ) + ( (This)->lpVtbl -> GetRegisters(This,mask,regCount,regBuffer) ) #define ICorDebugRegisterSet_SetRegisters(This,mask,regCount,regBuffer) \ - ( (This)->lpVtbl -> SetRegisters(This,mask,regCount,regBuffer) ) + ( (This)->lpVtbl -> SetRegisters(This,mask,regCount,regBuffer) ) #define ICorDebugRegisterSet_GetThreadContext(This,contextSize,context) \ - ( (This)->lpVtbl -> GetThreadContext(This,contextSize,context) ) + ( (This)->lpVtbl -> GetThreadContext(This,contextSize,context) ) #define ICorDebugRegisterSet_SetThreadContext(This,contextSize,context) \ - ( (This)->lpVtbl -> SetThreadContext(This,contextSize,context) ) + ( (This)->lpVtbl -> SetThreadContext(This,contextSize,context) ) #endif /* COBJMACROS */ @@ -9910,79 +9917,79 @@ EXTERN_C const IID IID_ICorDebugRegisterSet; #define __ICorDebugRegisterSet2_INTERFACE_DEFINED__ /* interface ICorDebugRegisterSet2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugRegisterSet2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("6DC7BA3F-89BA-4459-9EC1-9D60937B468D") ICorDebugRegisterSet2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetRegistersAvailable( + virtual HRESULT STDMETHODCALLTYPE GetRegistersAvailable( /* [in] */ ULONG32 numChunks, /* [size_is][out] */ BYTE availableRegChunks[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRegisters( + + virtual HRESULT STDMETHODCALLTYPE GetRegisters( /* [in] */ ULONG32 maskCount, /* [size_is][in] */ BYTE mask[ ], /* [in] */ ULONG32 regCount, /* [size_is][out] */ CORDB_REGISTER regBuffer[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetRegisters( + + virtual HRESULT STDMETHODCALLTYPE SetRegisters( /* [in] */ ULONG32 maskCount, /* [size_is][in] */ BYTE mask[ ], /* [in] */ ULONG32 regCount, /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugRegisterSet2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRegisterSet2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRegisterSet2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRegisterSet2 * This); - + DECLSPEC_XFGVIRT(ICorDebugRegisterSet2, GetRegistersAvailable) - HRESULT ( STDMETHODCALLTYPE *GetRegistersAvailable )( + HRESULT ( STDMETHODCALLTYPE *GetRegistersAvailable )( ICorDebugRegisterSet2 * This, /* [in] */ ULONG32 numChunks, /* [size_is][out] */ BYTE availableRegChunks[ ]); - + DECLSPEC_XFGVIRT(ICorDebugRegisterSet2, GetRegisters) - HRESULT ( STDMETHODCALLTYPE *GetRegisters )( + HRESULT ( STDMETHODCALLTYPE *GetRegisters )( ICorDebugRegisterSet2 * This, /* [in] */ ULONG32 maskCount, /* [size_is][in] */ BYTE mask[ ], /* [in] */ ULONG32 regCount, /* [size_is][out] */ CORDB_REGISTER regBuffer[ ]); - + DECLSPEC_XFGVIRT(ICorDebugRegisterSet2, SetRegisters) - HRESULT ( STDMETHODCALLTYPE *SetRegisters )( + HRESULT ( STDMETHODCALLTYPE *SetRegisters )( ICorDebugRegisterSet2 * This, /* [in] */ ULONG32 maskCount, /* [size_is][in] */ BYTE mask[ ], /* [in] */ ULONG32 regCount, /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]); - + END_INTERFACE } ICorDebugRegisterSet2Vtbl; @@ -9991,29 +9998,29 @@ EXTERN_C const IID IID_ICorDebugRegisterSet2; CONST_VTBL struct ICorDebugRegisterSet2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugRegisterSet2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRegisterSet2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRegisterSet2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRegisterSet2_GetRegistersAvailable(This,numChunks,availableRegChunks) \ - ( (This)->lpVtbl -> GetRegistersAvailable(This,numChunks,availableRegChunks) ) + ( (This)->lpVtbl -> GetRegistersAvailable(This,numChunks,availableRegChunks) ) #define ICorDebugRegisterSet2_GetRegisters(This,maskCount,mask,regCount,regBuffer) \ - ( (This)->lpVtbl -> GetRegisters(This,maskCount,mask,regCount,regBuffer) ) + ( (This)->lpVtbl -> GetRegisters(This,maskCount,mask,regCount,regBuffer) ) #define ICorDebugRegisterSet2_SetRegisters(This,maskCount,mask,regCount,regBuffer) \ - ( (This)->lpVtbl -> SetRegisters(This,maskCount,mask,regCount,regBuffer) ) + ( (This)->lpVtbl -> SetRegisters(This,maskCount,mask,regCount,regBuffer) ) #endif /* COBJMACROS */ @@ -10030,9 +10037,9 @@ EXTERN_C const IID IID_ICorDebugRegisterSet2; #define __ICorDebugThread_INTERFACE_DEFINED__ /* interface ICorDebugThread */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugUserState { USER_STOP_REQUESTED = 0x1, @@ -10050,161 +10057,161 @@ enum CorDebugUserState EXTERN_C const IID IID_ICorDebugThread; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("938c6d66-7fb6-4f69-b389-425b8987329b") ICorDebugThread : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetProcess( + virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetID( + + virtual HRESULT STDMETHODCALLTYPE GetID( /* [out] */ DWORD *pdwThreadId) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetHandle( + + virtual HRESULT STDMETHODCALLTYPE GetHandle( /* [out] */ HTHREAD *phThreadHandle) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAppDomain( + + virtual HRESULT STDMETHODCALLTYPE GetAppDomain( /* [out] */ ICorDebugAppDomain **ppAppDomain) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetDebugState( + + virtual HRESULT STDMETHODCALLTYPE SetDebugState( /* [in] */ CorDebugThreadState state) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDebugState( + + virtual HRESULT STDMETHODCALLTYPE GetDebugState( /* [out] */ CorDebugThreadState *pState) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetUserState( + + virtual HRESULT STDMETHODCALLTYPE GetUserState( /* [out] */ CorDebugUserState *pState) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCurrentException( + + virtual HRESULT STDMETHODCALLTYPE GetCurrentException( /* [out] */ ICorDebugValue **ppExceptionObject) = 0; - + virtual HRESULT STDMETHODCALLTYPE ClearCurrentException( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateStepper( + + virtual HRESULT STDMETHODCALLTYPE CreateStepper( /* [out] */ ICorDebugStepper **ppStepper) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateChains( + + virtual HRESULT STDMETHODCALLTYPE EnumerateChains( /* [out] */ ICorDebugChainEnum **ppChains) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetActiveChain( + + virtual HRESULT STDMETHODCALLTYPE GetActiveChain( /* [out] */ ICorDebugChain **ppChain) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetActiveFrame( + + virtual HRESULT STDMETHODCALLTYPE GetActiveFrame( /* [out] */ ICorDebugFrame **ppFrame) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( + + virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( /* [out] */ ICorDebugRegisterSet **ppRegisters) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateEval( + + virtual HRESULT STDMETHODCALLTYPE CreateEval( /* [out] */ ICorDebugEval **ppEval) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetObject( + + virtual HRESULT STDMETHODCALLTYPE GetObject( /* [out] */ ICorDebugValue **ppObject) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugThreadVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThread * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThread * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThread * This); - + DECLSPEC_XFGVIRT(ICorDebugThread, GetProcess) - HRESULT ( STDMETHODCALLTYPE *GetProcess )( + HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebugThread * This, /* [out] */ ICorDebugProcess **ppProcess); - + DECLSPEC_XFGVIRT(ICorDebugThread, GetID) - HRESULT ( STDMETHODCALLTYPE *GetID )( + HRESULT ( STDMETHODCALLTYPE *GetID )( ICorDebugThread * This, /* [out] */ DWORD *pdwThreadId); - + DECLSPEC_XFGVIRT(ICorDebugThread, GetHandle) - HRESULT ( STDMETHODCALLTYPE *GetHandle )( + HRESULT ( STDMETHODCALLTYPE *GetHandle )( ICorDebugThread * This, /* [out] */ HTHREAD *phThreadHandle); - + DECLSPEC_XFGVIRT(ICorDebugThread, GetAppDomain) - HRESULT ( STDMETHODCALLTYPE *GetAppDomain )( + HRESULT ( STDMETHODCALLTYPE *GetAppDomain )( ICorDebugThread * This, /* [out] */ ICorDebugAppDomain **ppAppDomain); - + DECLSPEC_XFGVIRT(ICorDebugThread, SetDebugState) - HRESULT ( STDMETHODCALLTYPE *SetDebugState )( + HRESULT ( STDMETHODCALLTYPE *SetDebugState )( ICorDebugThread * This, /* [in] */ CorDebugThreadState state); - + DECLSPEC_XFGVIRT(ICorDebugThread, GetDebugState) - HRESULT ( STDMETHODCALLTYPE *GetDebugState )( + HRESULT ( STDMETHODCALLTYPE *GetDebugState )( ICorDebugThread * This, /* [out] */ CorDebugThreadState *pState); - + DECLSPEC_XFGVIRT(ICorDebugThread, GetUserState) - HRESULT ( STDMETHODCALLTYPE *GetUserState )( + HRESULT ( STDMETHODCALLTYPE *GetUserState )( ICorDebugThread * This, /* [out] */ CorDebugUserState *pState); - + DECLSPEC_XFGVIRT(ICorDebugThread, GetCurrentException) - HRESULT ( STDMETHODCALLTYPE *GetCurrentException )( + HRESULT ( STDMETHODCALLTYPE *GetCurrentException )( ICorDebugThread * This, /* [out] */ ICorDebugValue **ppExceptionObject); - + DECLSPEC_XFGVIRT(ICorDebugThread, ClearCurrentException) - HRESULT ( STDMETHODCALLTYPE *ClearCurrentException )( + HRESULT ( STDMETHODCALLTYPE *ClearCurrentException )( ICorDebugThread * This); - + DECLSPEC_XFGVIRT(ICorDebugThread, CreateStepper) - HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugThread * This, /* [out] */ ICorDebugStepper **ppStepper); - + DECLSPEC_XFGVIRT(ICorDebugThread, EnumerateChains) - HRESULT ( STDMETHODCALLTYPE *EnumerateChains )( + HRESULT ( STDMETHODCALLTYPE *EnumerateChains )( ICorDebugThread * This, /* [out] */ ICorDebugChainEnum **ppChains); - + DECLSPEC_XFGVIRT(ICorDebugThread, GetActiveChain) - HRESULT ( STDMETHODCALLTYPE *GetActiveChain )( + HRESULT ( STDMETHODCALLTYPE *GetActiveChain )( ICorDebugThread * This, /* [out] */ ICorDebugChain **ppChain); - + DECLSPEC_XFGVIRT(ICorDebugThread, GetActiveFrame) - HRESULT ( STDMETHODCALLTYPE *GetActiveFrame )( + HRESULT ( STDMETHODCALLTYPE *GetActiveFrame )( ICorDebugThread * This, /* [out] */ ICorDebugFrame **ppFrame); - + DECLSPEC_XFGVIRT(ICorDebugThread, GetRegisterSet) - HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( + HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( ICorDebugThread * This, /* [out] */ ICorDebugRegisterSet **ppRegisters); - + DECLSPEC_XFGVIRT(ICorDebugThread, CreateEval) - HRESULT ( STDMETHODCALLTYPE *CreateEval )( + HRESULT ( STDMETHODCALLTYPE *CreateEval )( ICorDebugThread * This, /* [out] */ ICorDebugEval **ppEval); - + DECLSPEC_XFGVIRT(ICorDebugThread, GetObject) - HRESULT ( STDMETHODCALLTYPE *GetObject )( + HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugThread * This, /* [out] */ ICorDebugValue **ppObject); - + END_INTERFACE } ICorDebugThreadVtbl; @@ -10213,68 +10220,68 @@ EXTERN_C const IID IID_ICorDebugThread; CONST_VTBL struct ICorDebugThreadVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugThread_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThread_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThread_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThread_GetProcess(This,ppProcess) \ - ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) + ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) #define ICorDebugThread_GetID(This,pdwThreadId) \ - ( (This)->lpVtbl -> GetID(This,pdwThreadId) ) + ( (This)->lpVtbl -> GetID(This,pdwThreadId) ) #define ICorDebugThread_GetHandle(This,phThreadHandle) \ - ( (This)->lpVtbl -> GetHandle(This,phThreadHandle) ) + ( (This)->lpVtbl -> GetHandle(This,phThreadHandle) ) #define ICorDebugThread_GetAppDomain(This,ppAppDomain) \ - ( (This)->lpVtbl -> GetAppDomain(This,ppAppDomain) ) + ( (This)->lpVtbl -> GetAppDomain(This,ppAppDomain) ) #define ICorDebugThread_SetDebugState(This,state) \ - ( (This)->lpVtbl -> SetDebugState(This,state) ) + ( (This)->lpVtbl -> SetDebugState(This,state) ) #define ICorDebugThread_GetDebugState(This,pState) \ - ( (This)->lpVtbl -> GetDebugState(This,pState) ) + ( (This)->lpVtbl -> GetDebugState(This,pState) ) #define ICorDebugThread_GetUserState(This,pState) \ - ( (This)->lpVtbl -> GetUserState(This,pState) ) + ( (This)->lpVtbl -> GetUserState(This,pState) ) #define ICorDebugThread_GetCurrentException(This,ppExceptionObject) \ - ( (This)->lpVtbl -> GetCurrentException(This,ppExceptionObject) ) + ( (This)->lpVtbl -> GetCurrentException(This,ppExceptionObject) ) #define ICorDebugThread_ClearCurrentException(This) \ - ( (This)->lpVtbl -> ClearCurrentException(This) ) + ( (This)->lpVtbl -> ClearCurrentException(This) ) #define ICorDebugThread_CreateStepper(This,ppStepper) \ - ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #define ICorDebugThread_EnumerateChains(This,ppChains) \ - ( (This)->lpVtbl -> EnumerateChains(This,ppChains) ) + ( (This)->lpVtbl -> EnumerateChains(This,ppChains) ) #define ICorDebugThread_GetActiveChain(This,ppChain) \ - ( (This)->lpVtbl -> GetActiveChain(This,ppChain) ) + ( (This)->lpVtbl -> GetActiveChain(This,ppChain) ) #define ICorDebugThread_GetActiveFrame(This,ppFrame) \ - ( (This)->lpVtbl -> GetActiveFrame(This,ppFrame) ) + ( (This)->lpVtbl -> GetActiveFrame(This,ppFrame) ) #define ICorDebugThread_GetRegisterSet(This,ppRegisters) \ - ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) + ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) #define ICorDebugThread_CreateEval(This,ppEval) \ - ( (This)->lpVtbl -> CreateEval(This,ppEval) ) + ( (This)->lpVtbl -> CreateEval(This,ppEval) ) #define ICorDebugThread_GetObject(This,ppObject) \ - ( (This)->lpVtbl -> GetObject(This,ppObject) ) + ( (This)->lpVtbl -> GetObject(This,ppObject) ) #endif /* COBJMACROS */ @@ -10291,7 +10298,7 @@ EXTERN_C const IID IID_ICorDebugThread; #define __ICorDebugThread2_INTERFACE_DEFINED__ /* interface ICorDebugThread2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ typedef struct _COR_ACTIVE_FUNCTION { @@ -10306,79 +10313,79 @@ typedef struct _COR_ACTIVE_FUNCTION EXTERN_C const IID IID_ICorDebugThread2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("2BD956D9-7B07-4bef-8A98-12AA862417C5") ICorDebugThread2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetActiveFunctions( + virtual HRESULT STDMETHODCALLTYPE GetActiveFunctions( /* [in] */ ULONG32 cFunctions, /* [out] */ ULONG32 *pcFunctions, /* [length_is][size_is][out][in] */ COR_ACTIVE_FUNCTION pFunctions[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetConnectionID( + + virtual HRESULT STDMETHODCALLTYPE GetConnectionID( /* [out] */ CONNID *pdwConnectionId) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetTaskID( + + virtual HRESULT STDMETHODCALLTYPE GetTaskID( /* [out] */ TASKID *pTaskId) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetVolatileOSThreadID( + + virtual HRESULT STDMETHODCALLTYPE GetVolatileOSThreadID( /* [out] */ DWORD *pdwTid) = 0; - - virtual HRESULT STDMETHODCALLTYPE InterceptCurrentException( + + virtual HRESULT STDMETHODCALLTYPE InterceptCurrentException( /* [in] */ ICorDebugFrame *pFrame) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugThread2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThread2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThread2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThread2 * This); - + DECLSPEC_XFGVIRT(ICorDebugThread2, GetActiveFunctions) - HRESULT ( STDMETHODCALLTYPE *GetActiveFunctions )( + HRESULT ( STDMETHODCALLTYPE *GetActiveFunctions )( ICorDebugThread2 * This, /* [in] */ ULONG32 cFunctions, /* [out] */ ULONG32 *pcFunctions, /* [length_is][size_is][out][in] */ COR_ACTIVE_FUNCTION pFunctions[ ]); - + DECLSPEC_XFGVIRT(ICorDebugThread2, GetConnectionID) - HRESULT ( STDMETHODCALLTYPE *GetConnectionID )( + HRESULT ( STDMETHODCALLTYPE *GetConnectionID )( ICorDebugThread2 * This, /* [out] */ CONNID *pdwConnectionId); - + DECLSPEC_XFGVIRT(ICorDebugThread2, GetTaskID) - HRESULT ( STDMETHODCALLTYPE *GetTaskID )( + HRESULT ( STDMETHODCALLTYPE *GetTaskID )( ICorDebugThread2 * This, /* [out] */ TASKID *pTaskId); - + DECLSPEC_XFGVIRT(ICorDebugThread2, GetVolatileOSThreadID) - HRESULT ( STDMETHODCALLTYPE *GetVolatileOSThreadID )( + HRESULT ( STDMETHODCALLTYPE *GetVolatileOSThreadID )( ICorDebugThread2 * This, /* [out] */ DWORD *pdwTid); - + DECLSPEC_XFGVIRT(ICorDebugThread2, InterceptCurrentException) - HRESULT ( STDMETHODCALLTYPE *InterceptCurrentException )( + HRESULT ( STDMETHODCALLTYPE *InterceptCurrentException )( ICorDebugThread2 * This, /* [in] */ ICorDebugFrame *pFrame); - + END_INTERFACE } ICorDebugThread2Vtbl; @@ -10387,35 +10394,35 @@ EXTERN_C const IID IID_ICorDebugThread2; CONST_VTBL struct ICorDebugThread2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugThread2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThread2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThread2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThread2_GetActiveFunctions(This,cFunctions,pcFunctions,pFunctions) \ - ( (This)->lpVtbl -> GetActiveFunctions(This,cFunctions,pcFunctions,pFunctions) ) + ( (This)->lpVtbl -> GetActiveFunctions(This,cFunctions,pcFunctions,pFunctions) ) #define ICorDebugThread2_GetConnectionID(This,pdwConnectionId) \ - ( (This)->lpVtbl -> GetConnectionID(This,pdwConnectionId) ) + ( (This)->lpVtbl -> GetConnectionID(This,pdwConnectionId) ) #define ICorDebugThread2_GetTaskID(This,pTaskId) \ - ( (This)->lpVtbl -> GetTaskID(This,pTaskId) ) + ( (This)->lpVtbl -> GetTaskID(This,pTaskId) ) #define ICorDebugThread2_GetVolatileOSThreadID(This,pdwTid) \ - ( (This)->lpVtbl -> GetVolatileOSThreadID(This,pdwTid) ) + ( (This)->lpVtbl -> GetVolatileOSThreadID(This,pdwTid) ) #define ICorDebugThread2_InterceptCurrentException(This,pFrame) \ - ( (This)->lpVtbl -> InterceptCurrentException(This,pFrame) ) + ( (This)->lpVtbl -> InterceptCurrentException(This,pFrame) ) #endif /* COBJMACROS */ @@ -10432,61 +10439,61 @@ EXTERN_C const IID IID_ICorDebugThread2; #define __ICorDebugThread3_INTERFACE_DEFINED__ /* interface ICorDebugThread3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugThread3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("F8544EC3-5E4E-46c7-8D3E-A52B8405B1F5") ICorDebugThread3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CreateStackWalk( + virtual HRESULT STDMETHODCALLTYPE CreateStackWalk( /* [out] */ ICorDebugStackWalk **ppStackWalk) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetActiveInternalFrames( + + virtual HRESULT STDMETHODCALLTYPE GetActiveInternalFrames( /* [in] */ ULONG32 cInternalFrames, /* [out] */ ULONG32 *pcInternalFrames, /* [length_is][size_is][out][in] */ ICorDebugInternalFrame2 *ppInternalFrames[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugThread3Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThread3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThread3 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThread3 * This); - + DECLSPEC_XFGVIRT(ICorDebugThread3, CreateStackWalk) - HRESULT ( STDMETHODCALLTYPE *CreateStackWalk )( + HRESULT ( STDMETHODCALLTYPE *CreateStackWalk )( ICorDebugThread3 * This, /* [out] */ ICorDebugStackWalk **ppStackWalk); - + DECLSPEC_XFGVIRT(ICorDebugThread3, GetActiveInternalFrames) - HRESULT ( STDMETHODCALLTYPE *GetActiveInternalFrames )( + HRESULT ( STDMETHODCALLTYPE *GetActiveInternalFrames )( ICorDebugThread3 * This, /* [in] */ ULONG32 cInternalFrames, /* [out] */ ULONG32 *pcInternalFrames, /* [length_is][size_is][out][in] */ ICorDebugInternalFrame2 *ppInternalFrames[ ]); - + END_INTERFACE } ICorDebugThread3Vtbl; @@ -10495,26 +10502,26 @@ EXTERN_C const IID IID_ICorDebugThread3; CONST_VTBL struct ICorDebugThread3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugThread3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThread3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThread3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThread3_CreateStackWalk(This,ppStackWalk) \ - ( (This)->lpVtbl -> CreateStackWalk(This,ppStackWalk) ) + ( (This)->lpVtbl -> CreateStackWalk(This,ppStackWalk) ) #define ICorDebugThread3_GetActiveInternalFrames(This,cInternalFrames,pcInternalFrames,ppInternalFrames) \ - ( (This)->lpVtbl -> GetActiveInternalFrames(This,cInternalFrames,pcInternalFrames,ppInternalFrames) ) + ( (This)->lpVtbl -> GetActiveInternalFrames(This,cInternalFrames,pcInternalFrames,ppInternalFrames) ) #endif /* COBJMACROS */ @@ -10531,63 +10538,63 @@ EXTERN_C const IID IID_ICorDebugThread3; #define __ICorDebugThread4_INTERFACE_DEFINED__ /* interface ICorDebugThread4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugThread4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("1A1F204B-1C66-4637-823F-3EE6C744A69C") ICorDebugThread4 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE HasUnhandledException( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetBlockingObjects( + + virtual HRESULT STDMETHODCALLTYPE GetBlockingObjects( /* [out] */ ICorDebugBlockingObjectEnum **ppBlockingObjectEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCurrentCustomDebuggerNotification( + + virtual HRESULT STDMETHODCALLTYPE GetCurrentCustomDebuggerNotification( /* [out] */ ICorDebugValue **ppNotificationObject) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugThread4Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThread4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThread4 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThread4 * This); - + DECLSPEC_XFGVIRT(ICorDebugThread4, HasUnhandledException) - HRESULT ( STDMETHODCALLTYPE *HasUnhandledException )( + HRESULT ( STDMETHODCALLTYPE *HasUnhandledException )( ICorDebugThread4 * This); - + DECLSPEC_XFGVIRT(ICorDebugThread4, GetBlockingObjects) - HRESULT ( STDMETHODCALLTYPE *GetBlockingObjects )( + HRESULT ( STDMETHODCALLTYPE *GetBlockingObjects )( ICorDebugThread4 * This, /* [out] */ ICorDebugBlockingObjectEnum **ppBlockingObjectEnum); - + DECLSPEC_XFGVIRT(ICorDebugThread4, GetCurrentCustomDebuggerNotification) - HRESULT ( STDMETHODCALLTYPE *GetCurrentCustomDebuggerNotification )( + HRESULT ( STDMETHODCALLTYPE *GetCurrentCustomDebuggerNotification )( ICorDebugThread4 * This, /* [out] */ ICorDebugValue **ppNotificationObject); - + END_INTERFACE } ICorDebugThread4Vtbl; @@ -10596,29 +10603,29 @@ EXTERN_C const IID IID_ICorDebugThread4; CONST_VTBL struct ICorDebugThread4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugThread4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThread4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThread4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThread4_HasUnhandledException(This) \ - ( (This)->lpVtbl -> HasUnhandledException(This) ) + ( (This)->lpVtbl -> HasUnhandledException(This) ) #define ICorDebugThread4_GetBlockingObjects(This,ppBlockingObjectEnum) \ - ( (This)->lpVtbl -> GetBlockingObjects(This,ppBlockingObjectEnum) ) + ( (This)->lpVtbl -> GetBlockingObjects(This,ppBlockingObjectEnum) ) #define ICorDebugThread4_GetCurrentCustomDebuggerNotification(This,ppNotificationObject) \ - ( (This)->lpVtbl -> GetCurrentCustomDebuggerNotification(This,ppNotificationObject) ) + ( (This)->lpVtbl -> GetCurrentCustomDebuggerNotification(This,ppNotificationObject) ) #endif /* COBJMACROS */ @@ -10635,51 +10642,51 @@ EXTERN_C const IID IID_ICorDebugThread4; #define __ICorDebugThread5_INTERFACE_DEFINED__ /* interface ICorDebugThread5 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugThread5; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("F98421C4-E506-4D24-916F-0237EE853EC6") ICorDebugThread5 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetBytesAllocated( + virtual HRESULT STDMETHODCALLTYPE GetBytesAllocated( /* [out] */ ULONG64 *pSohAllocatedBytes, /* [out] */ ULONG64 *pUohAllocatedBytes) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugThread5Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThread5 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThread5 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThread5 * This); - + DECLSPEC_XFGVIRT(ICorDebugThread5, GetBytesAllocated) - HRESULT ( STDMETHODCALLTYPE *GetBytesAllocated )( + HRESULT ( STDMETHODCALLTYPE *GetBytesAllocated )( ICorDebugThread5 * This, /* [out] */ ULONG64 *pSohAllocatedBytes, /* [out] */ ULONG64 *pUohAllocatedBytes); - + END_INTERFACE } ICorDebugThread5Vtbl; @@ -10688,23 +10695,23 @@ EXTERN_C const IID IID_ICorDebugThread5; CONST_VTBL struct ICorDebugThread5Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugThread5_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThread5_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThread5_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThread5_GetBytesAllocated(This,pSohAllocatedBytes,pUohAllocatedBytes) \ - ( (This)->lpVtbl -> GetBytesAllocated(This,pSohAllocatedBytes,pUohAllocatedBytes) ) + ( (This)->lpVtbl -> GetBytesAllocated(This,pSohAllocatedBytes,pUohAllocatedBytes) ) #endif /* COBJMACROS */ @@ -10721,9 +10728,9 @@ EXTERN_C const IID IID_ICorDebugThread5; #define __ICorDebugStackWalk_INTERFACE_DEFINED__ /* interface ICorDebugStackWalk */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugSetContextFlag { SET_CONTEXT_FLAG_ACTIVE_FRAME = 0x1, @@ -10734,75 +10741,75 @@ enum CorDebugSetContextFlag EXTERN_C const IID IID_ICorDebugStackWalk; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("A0647DE9-55DE-4816-929C-385271C64CF7") ICorDebugStackWalk : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetContext( + virtual HRESULT STDMETHODCALLTYPE GetContext( /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextBufSize, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetContext( + + virtual HRESULT STDMETHODCALLTYPE SetContext( /* [in] */ CorDebugSetContextFlag flag, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE context[ ]) = 0; - + virtual HRESULT STDMETHODCALLTYPE Next( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFrame( + + virtual HRESULT STDMETHODCALLTYPE GetFrame( /* [out] */ ICorDebugFrame **pFrame) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugStackWalkVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStackWalk * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStackWalk * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStackWalk * This); - + DECLSPEC_XFGVIRT(ICorDebugStackWalk, GetContext) - HRESULT ( STDMETHODCALLTYPE *GetContext )( + HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugStackWalk * This, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextBufSize, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]); - + DECLSPEC_XFGVIRT(ICorDebugStackWalk, SetContext) - HRESULT ( STDMETHODCALLTYPE *SetContext )( + HRESULT ( STDMETHODCALLTYPE *SetContext )( ICorDebugStackWalk * This, /* [in] */ CorDebugSetContextFlag flag, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE context[ ]); - + DECLSPEC_XFGVIRT(ICorDebugStackWalk, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugStackWalk * This); - + DECLSPEC_XFGVIRT(ICorDebugStackWalk, GetFrame) - HRESULT ( STDMETHODCALLTYPE *GetFrame )( + HRESULT ( STDMETHODCALLTYPE *GetFrame )( ICorDebugStackWalk * This, /* [out] */ ICorDebugFrame **pFrame); - + END_INTERFACE } ICorDebugStackWalkVtbl; @@ -10811,32 +10818,32 @@ EXTERN_C const IID IID_ICorDebugStackWalk; CONST_VTBL struct ICorDebugStackWalkVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugStackWalk_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStackWalk_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStackWalk_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStackWalk_GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) \ - ( (This)->lpVtbl -> GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) ) + ( (This)->lpVtbl -> GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) ) #define ICorDebugStackWalk_SetContext(This,flag,contextSize,context) \ - ( (This)->lpVtbl -> SetContext(This,flag,contextSize,context) ) + ( (This)->lpVtbl -> SetContext(This,flag,contextSize,context) ) #define ICorDebugStackWalk_Next(This) \ - ( (This)->lpVtbl -> Next(This) ) + ( (This)->lpVtbl -> Next(This) ) #define ICorDebugStackWalk_GetFrame(This,pFrame) \ - ( (This)->lpVtbl -> GetFrame(This,pFrame) ) + ( (This)->lpVtbl -> GetFrame(This,pFrame) ) #endif /* COBJMACROS */ @@ -10853,9 +10860,9 @@ EXTERN_C const IID IID_ICorDebugStackWalk; #define __ICorDebugChain_INTERFACE_DEFINED__ /* interface ICorDebugChain */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugChainReason { CHAIN_NONE = 0, @@ -10877,133 +10884,133 @@ enum CorDebugChainReason EXTERN_C const IID IID_ICorDebugChain; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAEE-8A68-11d2-983C-0000F808342D") ICorDebugChain : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetThread( + virtual HRESULT STDMETHODCALLTYPE GetThread( /* [out] */ ICorDebugThread **ppThread) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStackRange( + + virtual HRESULT STDMETHODCALLTYPE GetStackRange( /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetContext( + + virtual HRESULT STDMETHODCALLTYPE GetContext( /* [out] */ ICorDebugContext **ppContext) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCaller( + + virtual HRESULT STDMETHODCALLTYPE GetCaller( /* [out] */ ICorDebugChain **ppChain) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCallee( + + virtual HRESULT STDMETHODCALLTYPE GetCallee( /* [out] */ ICorDebugChain **ppChain) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetPrevious( + + virtual HRESULT STDMETHODCALLTYPE GetPrevious( /* [out] */ ICorDebugChain **ppChain) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetNext( + + virtual HRESULT STDMETHODCALLTYPE GetNext( /* [out] */ ICorDebugChain **ppChain) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsManaged( + + virtual HRESULT STDMETHODCALLTYPE IsManaged( /* [out] */ BOOL *pManaged) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateFrames( + + virtual HRESULT STDMETHODCALLTYPE EnumerateFrames( /* [out] */ ICorDebugFrameEnum **ppFrames) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetActiveFrame( + + virtual HRESULT STDMETHODCALLTYPE GetActiveFrame( /* [out] */ ICorDebugFrame **ppFrame) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( + + virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( /* [out] */ ICorDebugRegisterSet **ppRegisters) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetReason( + + virtual HRESULT STDMETHODCALLTYPE GetReason( /* [out] */ CorDebugChainReason *pReason) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugChainVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugChain * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugChain * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugChain * This); - + DECLSPEC_XFGVIRT(ICorDebugChain, GetThread) - HRESULT ( STDMETHODCALLTYPE *GetThread )( + HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugChain * This, /* [out] */ ICorDebugThread **ppThread); - + DECLSPEC_XFGVIRT(ICorDebugChain, GetStackRange) - HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugChain * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); - + DECLSPEC_XFGVIRT(ICorDebugChain, GetContext) - HRESULT ( STDMETHODCALLTYPE *GetContext )( + HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugChain * This, /* [out] */ ICorDebugContext **ppContext); - + DECLSPEC_XFGVIRT(ICorDebugChain, GetCaller) - HRESULT ( STDMETHODCALLTYPE *GetCaller )( + HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugChain * This, /* [out] */ ICorDebugChain **ppChain); - + DECLSPEC_XFGVIRT(ICorDebugChain, GetCallee) - HRESULT ( STDMETHODCALLTYPE *GetCallee )( + HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugChain * This, /* [out] */ ICorDebugChain **ppChain); - + DECLSPEC_XFGVIRT(ICorDebugChain, GetPrevious) - HRESULT ( STDMETHODCALLTYPE *GetPrevious )( + HRESULT ( STDMETHODCALLTYPE *GetPrevious )( ICorDebugChain * This, /* [out] */ ICorDebugChain **ppChain); - + DECLSPEC_XFGVIRT(ICorDebugChain, GetNext) - HRESULT ( STDMETHODCALLTYPE *GetNext )( + HRESULT ( STDMETHODCALLTYPE *GetNext )( ICorDebugChain * This, /* [out] */ ICorDebugChain **ppChain); - + DECLSPEC_XFGVIRT(ICorDebugChain, IsManaged) - HRESULT ( STDMETHODCALLTYPE *IsManaged )( + HRESULT ( STDMETHODCALLTYPE *IsManaged )( ICorDebugChain * This, /* [out] */ BOOL *pManaged); - + DECLSPEC_XFGVIRT(ICorDebugChain, EnumerateFrames) - HRESULT ( STDMETHODCALLTYPE *EnumerateFrames )( + HRESULT ( STDMETHODCALLTYPE *EnumerateFrames )( ICorDebugChain * This, /* [out] */ ICorDebugFrameEnum **ppFrames); - + DECLSPEC_XFGVIRT(ICorDebugChain, GetActiveFrame) - HRESULT ( STDMETHODCALLTYPE *GetActiveFrame )( + HRESULT ( STDMETHODCALLTYPE *GetActiveFrame )( ICorDebugChain * This, /* [out] */ ICorDebugFrame **ppFrame); - + DECLSPEC_XFGVIRT(ICorDebugChain, GetRegisterSet) - HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( + HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( ICorDebugChain * This, /* [out] */ ICorDebugRegisterSet **ppRegisters); - + DECLSPEC_XFGVIRT(ICorDebugChain, GetReason) - HRESULT ( STDMETHODCALLTYPE *GetReason )( + HRESULT ( STDMETHODCALLTYPE *GetReason )( ICorDebugChain * This, /* [out] */ CorDebugChainReason *pReason); - + END_INTERFACE } ICorDebugChainVtbl; @@ -11012,56 +11019,56 @@ EXTERN_C const IID IID_ICorDebugChain; CONST_VTBL struct ICorDebugChainVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugChain_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugChain_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugChain_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugChain_GetThread(This,ppThread) \ - ( (This)->lpVtbl -> GetThread(This,ppThread) ) + ( (This)->lpVtbl -> GetThread(This,ppThread) ) #define ICorDebugChain_GetStackRange(This,pStart,pEnd) \ - ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugChain_GetContext(This,ppContext) \ - ( (This)->lpVtbl -> GetContext(This,ppContext) ) + ( (This)->lpVtbl -> GetContext(This,ppContext) ) #define ICorDebugChain_GetCaller(This,ppChain) \ - ( (This)->lpVtbl -> GetCaller(This,ppChain) ) + ( (This)->lpVtbl -> GetCaller(This,ppChain) ) #define ICorDebugChain_GetCallee(This,ppChain) \ - ( (This)->lpVtbl -> GetCallee(This,ppChain) ) + ( (This)->lpVtbl -> GetCallee(This,ppChain) ) #define ICorDebugChain_GetPrevious(This,ppChain) \ - ( (This)->lpVtbl -> GetPrevious(This,ppChain) ) + ( (This)->lpVtbl -> GetPrevious(This,ppChain) ) #define ICorDebugChain_GetNext(This,ppChain) \ - ( (This)->lpVtbl -> GetNext(This,ppChain) ) + ( (This)->lpVtbl -> GetNext(This,ppChain) ) #define ICorDebugChain_IsManaged(This,pManaged) \ - ( (This)->lpVtbl -> IsManaged(This,pManaged) ) + ( (This)->lpVtbl -> IsManaged(This,pManaged) ) #define ICorDebugChain_EnumerateFrames(This,ppFrames) \ - ( (This)->lpVtbl -> EnumerateFrames(This,ppFrames) ) + ( (This)->lpVtbl -> EnumerateFrames(This,ppFrames) ) #define ICorDebugChain_GetActiveFrame(This,ppFrame) \ - ( (This)->lpVtbl -> GetActiveFrame(This,ppFrame) ) + ( (This)->lpVtbl -> GetActiveFrame(This,ppFrame) ) #define ICorDebugChain_GetRegisterSet(This,ppRegisters) \ - ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) + ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) #define ICorDebugChain_GetReason(This,pReason) \ - ( (This)->lpVtbl -> GetReason(This,pReason) ) + ( (This)->lpVtbl -> GetReason(This,pReason) ) #endif /* COBJMACROS */ @@ -11078,107 +11085,107 @@ EXTERN_C const IID IID_ICorDebugChain; #define __ICorDebugFrame_INTERFACE_DEFINED__ /* interface ICorDebugFrame */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFrame; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAEF-8A68-11d2-983C-0000F808342D") ICorDebugFrame : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetChain( + virtual HRESULT STDMETHODCALLTYPE GetChain( /* [out] */ ICorDebugChain **ppChain) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCode( + + virtual HRESULT STDMETHODCALLTYPE GetCode( /* [out] */ ICorDebugCode **ppCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunction( + + virtual HRESULT STDMETHODCALLTYPE GetFunction( /* [out] */ ICorDebugFunction **ppFunction) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunctionToken( + + virtual HRESULT STDMETHODCALLTYPE GetFunctionToken( /* [out] */ mdMethodDef *pToken) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStackRange( + + virtual HRESULT STDMETHODCALLTYPE GetStackRange( /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCaller( + + virtual HRESULT STDMETHODCALLTYPE GetCaller( /* [out] */ ICorDebugFrame **ppFrame) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCallee( + + virtual HRESULT STDMETHODCALLTYPE GetCallee( /* [out] */ ICorDebugFrame **ppFrame) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateStepper( + + virtual HRESULT STDMETHODCALLTYPE CreateStepper( /* [out] */ ICorDebugStepper **ppStepper) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFrameVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFrame * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFrame * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFrame * This); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetChain) - HRESULT ( STDMETHODCALLTYPE *GetChain )( + HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugFrame * This, /* [out] */ ICorDebugChain **ppChain); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCode) - HRESULT ( STDMETHODCALLTYPE *GetCode )( + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugFrame * This, /* [out] */ ICorDebugCode **ppCode); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetFunction) - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugFrame * This, /* [out] */ ICorDebugFunction **ppFunction); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetFunctionToken) - HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugFrame * This, /* [out] */ mdMethodDef *pToken); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetStackRange) - HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCaller) - HRESULT ( STDMETHODCALLTYPE *GetCaller )( + HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCallee) - HRESULT ( STDMETHODCALLTYPE *GetCallee )( + HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - + DECLSPEC_XFGVIRT(ICorDebugFrame, CreateStepper) - HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugFrame * This, /* [out] */ ICorDebugStepper **ppStepper); - + END_INTERFACE } ICorDebugFrameVtbl; @@ -11187,44 +11194,44 @@ EXTERN_C const IID IID_ICorDebugFrame; CONST_VTBL struct ICorDebugFrameVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFrame_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFrame_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFrame_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFrame_GetChain(This,ppChain) \ - ( (This)->lpVtbl -> GetChain(This,ppChain) ) + ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugFrame_GetCode(This,ppCode) \ - ( (This)->lpVtbl -> GetCode(This,ppCode) ) + ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugFrame_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugFrame_GetFunctionToken(This,pToken) \ - ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugFrame_GetStackRange(This,pStart,pEnd) \ - ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugFrame_GetCaller(This,ppFrame) \ - ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugFrame_GetCallee(This,ppFrame) \ - ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugFrame_CreateStepper(This,ppStepper) \ - ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #endif /* COBJMACROS */ @@ -11241,9 +11248,9 @@ EXTERN_C const IID IID_ICorDebugFrame; #define __ICorDebugInternalFrame_INTERFACE_DEFINED__ /* interface ICorDebugInternalFrame */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugInternalFrameType { STUBFRAME_NONE = 0, @@ -11263,84 +11270,84 @@ enum CorDebugInternalFrameType EXTERN_C const IID IID_ICorDebugInternalFrame; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("B92CC7F7-9D2D-45c4-BC2B-621FCC9DFBF4") ICorDebugInternalFrame : public ICorDebugFrame { public: - virtual HRESULT STDMETHODCALLTYPE GetFrameType( + virtual HRESULT STDMETHODCALLTYPE GetFrameType( /* [out] */ CorDebugInternalFrameType *pType) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugInternalFrameVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugInternalFrame * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugInternalFrame * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugInternalFrame * This); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetChain) - HRESULT ( STDMETHODCALLTYPE *GetChain )( + HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugChain **ppChain); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCode) - HRESULT ( STDMETHODCALLTYPE *GetCode )( + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugCode **ppCode); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetFunction) - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugFunction **ppFunction); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetFunctionToken) - HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugInternalFrame * This, /* [out] */ mdMethodDef *pToken); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetStackRange) - HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugInternalFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCaller) - HRESULT ( STDMETHODCALLTYPE *GetCaller )( + HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCallee) - HRESULT ( STDMETHODCALLTYPE *GetCallee )( + HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - + DECLSPEC_XFGVIRT(ICorDebugFrame, CreateStepper) - HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugStepper **ppStepper); - + DECLSPEC_XFGVIRT(ICorDebugInternalFrame, GetFrameType) - HRESULT ( STDMETHODCALLTYPE *GetFrameType )( + HRESULT ( STDMETHODCALLTYPE *GetFrameType )( ICorDebugInternalFrame * This, /* [out] */ CorDebugInternalFrameType *pType); - + END_INTERFACE } ICorDebugInternalFrameVtbl; @@ -11349,48 +11356,48 @@ EXTERN_C const IID IID_ICorDebugInternalFrame; CONST_VTBL struct ICorDebugInternalFrameVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugInternalFrame_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugInternalFrame_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugInternalFrame_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugInternalFrame_GetChain(This,ppChain) \ - ( (This)->lpVtbl -> GetChain(This,ppChain) ) + ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugInternalFrame_GetCode(This,ppCode) \ - ( (This)->lpVtbl -> GetCode(This,ppCode) ) + ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugInternalFrame_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugInternalFrame_GetFunctionToken(This,pToken) \ - ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugInternalFrame_GetStackRange(This,pStart,pEnd) \ - ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugInternalFrame_GetCaller(This,ppFrame) \ - ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugInternalFrame_GetCallee(This,ppFrame) \ - ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugInternalFrame_CreateStepper(This,ppStepper) \ - ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #define ICorDebugInternalFrame_GetFrameType(This,pType) \ - ( (This)->lpVtbl -> GetFrameType(This,pType) ) + ( (This)->lpVtbl -> GetFrameType(This,pType) ) #endif /* COBJMACROS */ @@ -11407,59 +11414,59 @@ EXTERN_C const IID IID_ICorDebugInternalFrame; #define __ICorDebugInternalFrame2_INTERFACE_DEFINED__ /* interface ICorDebugInternalFrame2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugInternalFrame2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("C0815BDC-CFAB-447e-A779-C116B454EB5B") ICorDebugInternalFrame2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetAddress( + virtual HRESULT STDMETHODCALLTYPE GetAddress( /* [out] */ CORDB_ADDRESS *pAddress) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsCloserToLeaf( + + virtual HRESULT STDMETHODCALLTYPE IsCloserToLeaf( /* [in] */ ICorDebugFrame *pFrameToCompare, /* [out] */ BOOL *pIsCloser) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugInternalFrame2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugInternalFrame2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugInternalFrame2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugInternalFrame2 * This); - + DECLSPEC_XFGVIRT(ICorDebugInternalFrame2, GetAddress) - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugInternalFrame2 * This, /* [out] */ CORDB_ADDRESS *pAddress); - + DECLSPEC_XFGVIRT(ICorDebugInternalFrame2, IsCloserToLeaf) - HRESULT ( STDMETHODCALLTYPE *IsCloserToLeaf )( + HRESULT ( STDMETHODCALLTYPE *IsCloserToLeaf )( ICorDebugInternalFrame2 * This, /* [in] */ ICorDebugFrame *pFrameToCompare, /* [out] */ BOOL *pIsCloser); - + END_INTERFACE } ICorDebugInternalFrame2Vtbl; @@ -11468,26 +11475,26 @@ EXTERN_C const IID IID_ICorDebugInternalFrame2; CONST_VTBL struct ICorDebugInternalFrame2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugInternalFrame2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugInternalFrame2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugInternalFrame2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugInternalFrame2_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugInternalFrame2_IsCloserToLeaf(This,pFrameToCompare,pIsCloser) \ - ( (This)->lpVtbl -> IsCloserToLeaf(This,pFrameToCompare,pIsCloser) ) + ( (This)->lpVtbl -> IsCloserToLeaf(This,pFrameToCompare,pIsCloser) ) #endif /* COBJMACROS */ @@ -11504,9 +11511,9 @@ EXTERN_C const IID IID_ICorDebugInternalFrame2; #define __ICorDebugILFrame_INTERFACE_DEFINED__ /* interface ICorDebugILFrame */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugMappingResult { MAPPING_PROLOG = 0x1, @@ -11521,156 +11528,156 @@ enum CorDebugMappingResult EXTERN_C const IID IID_ICorDebugILFrame; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("03E26311-4F76-11d3-88C6-006097945418") ICorDebugILFrame : public ICorDebugFrame { public: - virtual HRESULT STDMETHODCALLTYPE GetIP( + virtual HRESULT STDMETHODCALLTYPE GetIP( /* [out] */ ULONG32 *pnOffset, /* [out] */ CorDebugMappingResult *pMappingResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetIP( + + virtual HRESULT STDMETHODCALLTYPE SetIP( /* [in] */ ULONG32 nOffset) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateLocalVariables( + + virtual HRESULT STDMETHODCALLTYPE EnumerateLocalVariables( /* [out] */ ICorDebugValueEnum **ppValueEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalVariable( + + virtual HRESULT STDMETHODCALLTYPE GetLocalVariable( /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateArguments( + + virtual HRESULT STDMETHODCALLTYPE EnumerateArguments( /* [out] */ ICorDebugValueEnum **ppValueEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetArgument( + + virtual HRESULT STDMETHODCALLTYPE GetArgument( /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStackDepth( + + virtual HRESULT STDMETHODCALLTYPE GetStackDepth( /* [out] */ ULONG32 *pDepth) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStackValue( + + virtual HRESULT STDMETHODCALLTYPE GetStackValue( /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE CanSetIP( + + virtual HRESULT STDMETHODCALLTYPE CanSetIP( /* [in] */ ULONG32 nOffset) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugILFrameVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILFrame * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILFrame * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILFrame * This); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetChain) - HRESULT ( STDMETHODCALLTYPE *GetChain )( + HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugILFrame * This, /* [out] */ ICorDebugChain **ppChain); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCode) - HRESULT ( STDMETHODCALLTYPE *GetCode )( + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugILFrame * This, /* [out] */ ICorDebugCode **ppCode); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetFunction) - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugILFrame * This, /* [out] */ ICorDebugFunction **ppFunction); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetFunctionToken) - HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugILFrame * This, /* [out] */ mdMethodDef *pToken); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetStackRange) - HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugILFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCaller) - HRESULT ( STDMETHODCALLTYPE *GetCaller )( + HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugILFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCallee) - HRESULT ( STDMETHODCALLTYPE *GetCallee )( + HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugILFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - + DECLSPEC_XFGVIRT(ICorDebugFrame, CreateStepper) - HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugILFrame * This, /* [out] */ ICorDebugStepper **ppStepper); - + DECLSPEC_XFGVIRT(ICorDebugILFrame, GetIP) - HRESULT ( STDMETHODCALLTYPE *GetIP )( + HRESULT ( STDMETHODCALLTYPE *GetIP )( ICorDebugILFrame * This, /* [out] */ ULONG32 *pnOffset, /* [out] */ CorDebugMappingResult *pMappingResult); - + DECLSPEC_XFGVIRT(ICorDebugILFrame, SetIP) - HRESULT ( STDMETHODCALLTYPE *SetIP )( + HRESULT ( STDMETHODCALLTYPE *SetIP )( ICorDebugILFrame * This, /* [in] */ ULONG32 nOffset); - + DECLSPEC_XFGVIRT(ICorDebugILFrame, EnumerateLocalVariables) - HRESULT ( STDMETHODCALLTYPE *EnumerateLocalVariables )( + HRESULT ( STDMETHODCALLTYPE *EnumerateLocalVariables )( ICorDebugILFrame * This, /* [out] */ ICorDebugValueEnum **ppValueEnum); - + DECLSPEC_XFGVIRT(ICorDebugILFrame, GetLocalVariable) - HRESULT ( STDMETHODCALLTYPE *GetLocalVariable )( + HRESULT ( STDMETHODCALLTYPE *GetLocalVariable )( ICorDebugILFrame * This, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugILFrame, EnumerateArguments) - HRESULT ( STDMETHODCALLTYPE *EnumerateArguments )( + HRESULT ( STDMETHODCALLTYPE *EnumerateArguments )( ICorDebugILFrame * This, /* [out] */ ICorDebugValueEnum **ppValueEnum); - + DECLSPEC_XFGVIRT(ICorDebugILFrame, GetArgument) - HRESULT ( STDMETHODCALLTYPE *GetArgument )( + HRESULT ( STDMETHODCALLTYPE *GetArgument )( ICorDebugILFrame * This, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugILFrame, GetStackDepth) - HRESULT ( STDMETHODCALLTYPE *GetStackDepth )( + HRESULT ( STDMETHODCALLTYPE *GetStackDepth )( ICorDebugILFrame * This, /* [out] */ ULONG32 *pDepth); - + DECLSPEC_XFGVIRT(ICorDebugILFrame, GetStackValue) - HRESULT ( STDMETHODCALLTYPE *GetStackValue )( + HRESULT ( STDMETHODCALLTYPE *GetStackValue )( ICorDebugILFrame * This, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugILFrame, CanSetIP) - HRESULT ( STDMETHODCALLTYPE *CanSetIP )( + HRESULT ( STDMETHODCALLTYPE *CanSetIP )( ICorDebugILFrame * This, /* [in] */ ULONG32 nOffset); - + END_INTERFACE } ICorDebugILFrameVtbl; @@ -11679,72 +11686,72 @@ EXTERN_C const IID IID_ICorDebugILFrame; CONST_VTBL struct ICorDebugILFrameVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugILFrame_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILFrame_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILFrame_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILFrame_GetChain(This,ppChain) \ - ( (This)->lpVtbl -> GetChain(This,ppChain) ) + ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugILFrame_GetCode(This,ppCode) \ - ( (This)->lpVtbl -> GetCode(This,ppCode) ) + ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugILFrame_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugILFrame_GetFunctionToken(This,pToken) \ - ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugILFrame_GetStackRange(This,pStart,pEnd) \ - ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugILFrame_GetCaller(This,ppFrame) \ - ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugILFrame_GetCallee(This,ppFrame) \ - ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugILFrame_CreateStepper(This,ppStepper) \ - ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #define ICorDebugILFrame_GetIP(This,pnOffset,pMappingResult) \ - ( (This)->lpVtbl -> GetIP(This,pnOffset,pMappingResult) ) + ( (This)->lpVtbl -> GetIP(This,pnOffset,pMappingResult) ) #define ICorDebugILFrame_SetIP(This,nOffset) \ - ( (This)->lpVtbl -> SetIP(This,nOffset) ) + ( (This)->lpVtbl -> SetIP(This,nOffset) ) #define ICorDebugILFrame_EnumerateLocalVariables(This,ppValueEnum) \ - ( (This)->lpVtbl -> EnumerateLocalVariables(This,ppValueEnum) ) + ( (This)->lpVtbl -> EnumerateLocalVariables(This,ppValueEnum) ) #define ICorDebugILFrame_GetLocalVariable(This,dwIndex,ppValue) \ - ( (This)->lpVtbl -> GetLocalVariable(This,dwIndex,ppValue) ) + ( (This)->lpVtbl -> GetLocalVariable(This,dwIndex,ppValue) ) #define ICorDebugILFrame_EnumerateArguments(This,ppValueEnum) \ - ( (This)->lpVtbl -> EnumerateArguments(This,ppValueEnum) ) + ( (This)->lpVtbl -> EnumerateArguments(This,ppValueEnum) ) #define ICorDebugILFrame_GetArgument(This,dwIndex,ppValue) \ - ( (This)->lpVtbl -> GetArgument(This,dwIndex,ppValue) ) + ( (This)->lpVtbl -> GetArgument(This,dwIndex,ppValue) ) #define ICorDebugILFrame_GetStackDepth(This,pDepth) \ - ( (This)->lpVtbl -> GetStackDepth(This,pDepth) ) + ( (This)->lpVtbl -> GetStackDepth(This,pDepth) ) #define ICorDebugILFrame_GetStackValue(This,dwIndex,ppValue) \ - ( (This)->lpVtbl -> GetStackValue(This,dwIndex,ppValue) ) + ( (This)->lpVtbl -> GetStackValue(This,dwIndex,ppValue) ) #define ICorDebugILFrame_CanSetIP(This,nOffset) \ - ( (This)->lpVtbl -> CanSetIP(This,nOffset) ) + ( (This)->lpVtbl -> CanSetIP(This,nOffset) ) #endif /* COBJMACROS */ @@ -11761,57 +11768,57 @@ EXTERN_C const IID IID_ICorDebugILFrame; #define __ICorDebugILFrame2_INTERFACE_DEFINED__ /* interface ICorDebugILFrame2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugILFrame2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("5D88A994-6C30-479b-890F-BCEF88B129A5") ICorDebugILFrame2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE RemapFunction( + virtual HRESULT STDMETHODCALLTYPE RemapFunction( /* [in] */ ULONG32 newILOffset) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateTypeParameters( + + virtual HRESULT STDMETHODCALLTYPE EnumerateTypeParameters( /* [out] */ ICorDebugTypeEnum **ppTyParEnum) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugILFrame2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILFrame2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILFrame2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILFrame2 * This); - + DECLSPEC_XFGVIRT(ICorDebugILFrame2, RemapFunction) - HRESULT ( STDMETHODCALLTYPE *RemapFunction )( + HRESULT ( STDMETHODCALLTYPE *RemapFunction )( ICorDebugILFrame2 * This, /* [in] */ ULONG32 newILOffset); - + DECLSPEC_XFGVIRT(ICorDebugILFrame2, EnumerateTypeParameters) - HRESULT ( STDMETHODCALLTYPE *EnumerateTypeParameters )( + HRESULT ( STDMETHODCALLTYPE *EnumerateTypeParameters )( ICorDebugILFrame2 * This, /* [out] */ ICorDebugTypeEnum **ppTyParEnum); - + END_INTERFACE } ICorDebugILFrame2Vtbl; @@ -11820,26 +11827,26 @@ EXTERN_C const IID IID_ICorDebugILFrame2; CONST_VTBL struct ICorDebugILFrame2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugILFrame2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILFrame2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILFrame2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILFrame2_RemapFunction(This,newILOffset) \ - ( (This)->lpVtbl -> RemapFunction(This,newILOffset) ) + ( (This)->lpVtbl -> RemapFunction(This,newILOffset) ) #define ICorDebugILFrame2_EnumerateTypeParameters(This,ppTyParEnum) \ - ( (This)->lpVtbl -> EnumerateTypeParameters(This,ppTyParEnum) ) + ( (This)->lpVtbl -> EnumerateTypeParameters(This,ppTyParEnum) ) #endif /* COBJMACROS */ @@ -11856,51 +11863,51 @@ EXTERN_C const IID IID_ICorDebugILFrame2; #define __ICorDebugILFrame3_INTERFACE_DEFINED__ /* interface ICorDebugILFrame3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugILFrame3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("9A9E2ED6-04DF-4FE0-BB50-CAB64126AD24") ICorDebugILFrame3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetReturnValueForILOffset( + virtual HRESULT STDMETHODCALLTYPE GetReturnValueForILOffset( ULONG32 ILoffset, /* [out] */ ICorDebugValue **ppReturnValue) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugILFrame3Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILFrame3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILFrame3 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILFrame3 * This); - + DECLSPEC_XFGVIRT(ICorDebugILFrame3, GetReturnValueForILOffset) - HRESULT ( STDMETHODCALLTYPE *GetReturnValueForILOffset )( + HRESULT ( STDMETHODCALLTYPE *GetReturnValueForILOffset )( ICorDebugILFrame3 * This, ULONG32 ILoffset, /* [out] */ ICorDebugValue **ppReturnValue); - + END_INTERFACE } ICorDebugILFrame3Vtbl; @@ -11909,23 +11916,23 @@ EXTERN_C const IID IID_ICorDebugILFrame3; CONST_VTBL struct ICorDebugILFrame3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugILFrame3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILFrame3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILFrame3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILFrame3_GetReturnValueForILOffset(This,ILoffset,ppReturnValue) \ - ( (This)->lpVtbl -> GetReturnValueForILOffset(This,ILoffset,ppReturnValue) ) + ( (This)->lpVtbl -> GetReturnValueForILOffset(This,ILoffset,ppReturnValue) ) #endif /* COBJMACROS */ @@ -11939,9 +11946,9 @@ EXTERN_C const IID IID_ICorDebugILFrame3; /* interface __MIDL_itf_cordebug_0000_0070 */ -/* [local] */ +/* [local] */ -typedef +typedef enum ILCodeKind { ILCODE_ORIGINAL_IL = 0x1, @@ -11957,73 +11964,73 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0070_v0_0_s_ifspec; #define __ICorDebugILFrame4_INTERFACE_DEFINED__ /* interface ICorDebugILFrame4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugILFrame4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("AD914A30-C6D1-4AC5-9C5E-577F3BAA8A45") ICorDebugILFrame4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE EnumerateLocalVariablesEx( + virtual HRESULT STDMETHODCALLTYPE EnumerateLocalVariablesEx( /* [in] */ ILCodeKind flags, /* [out] */ ICorDebugValueEnum **ppValueEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalVariableEx( + + virtual HRESULT STDMETHODCALLTYPE GetLocalVariableEx( /* [in] */ ILCodeKind flags, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCodeEx( + + virtual HRESULT STDMETHODCALLTYPE GetCodeEx( /* [in] */ ILCodeKind flags, /* [out] */ ICorDebugCode **ppCode) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugILFrame4Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILFrame4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILFrame4 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILFrame4 * This); - + DECLSPEC_XFGVIRT(ICorDebugILFrame4, EnumerateLocalVariablesEx) - HRESULT ( STDMETHODCALLTYPE *EnumerateLocalVariablesEx )( + HRESULT ( STDMETHODCALLTYPE *EnumerateLocalVariablesEx )( ICorDebugILFrame4 * This, /* [in] */ ILCodeKind flags, /* [out] */ ICorDebugValueEnum **ppValueEnum); - + DECLSPEC_XFGVIRT(ICorDebugILFrame4, GetLocalVariableEx) - HRESULT ( STDMETHODCALLTYPE *GetLocalVariableEx )( + HRESULT ( STDMETHODCALLTYPE *GetLocalVariableEx )( ICorDebugILFrame4 * This, /* [in] */ ILCodeKind flags, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugILFrame4, GetCodeEx) - HRESULT ( STDMETHODCALLTYPE *GetCodeEx )( + HRESULT ( STDMETHODCALLTYPE *GetCodeEx )( ICorDebugILFrame4 * This, /* [in] */ ILCodeKind flags, /* [out] */ ICorDebugCode **ppCode); - + END_INTERFACE } ICorDebugILFrame4Vtbl; @@ -12032,29 +12039,29 @@ EXTERN_C const IID IID_ICorDebugILFrame4; CONST_VTBL struct ICorDebugILFrame4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugILFrame4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILFrame4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILFrame4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILFrame4_EnumerateLocalVariablesEx(This,flags,ppValueEnum) \ - ( (This)->lpVtbl -> EnumerateLocalVariablesEx(This,flags,ppValueEnum) ) + ( (This)->lpVtbl -> EnumerateLocalVariablesEx(This,flags,ppValueEnum) ) #define ICorDebugILFrame4_GetLocalVariableEx(This,flags,dwIndex,ppValue) \ - ( (This)->lpVtbl -> GetLocalVariableEx(This,flags,dwIndex,ppValue) ) + ( (This)->lpVtbl -> GetLocalVariableEx(This,flags,dwIndex,ppValue) ) #define ICorDebugILFrame4_GetCodeEx(This,flags,ppCode) \ - ( (This)->lpVtbl -> GetCodeEx(This,flags,ppCode) ) + ( (This)->lpVtbl -> GetCodeEx(This,flags,ppCode) ) #endif /* COBJMACROS */ @@ -12071,190 +12078,190 @@ EXTERN_C const IID IID_ICorDebugILFrame4; #define __ICorDebugNativeFrame_INTERFACE_DEFINED__ /* interface ICorDebugNativeFrame */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugNativeFrame; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("03E26314-4F76-11d3-88C6-006097945418") ICorDebugNativeFrame : public ICorDebugFrame { public: - virtual HRESULT STDMETHODCALLTYPE GetIP( + virtual HRESULT STDMETHODCALLTYPE GetIP( /* [out] */ ULONG32 *pnOffset) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetIP( + + virtual HRESULT STDMETHODCALLTYPE SetIP( /* [in] */ ULONG32 nOffset) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( + + virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( /* [out] */ ICorDebugRegisterSet **ppRegisters) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalRegisterValue( + + virtual HRESULT STDMETHODCALLTYPE GetLocalRegisterValue( /* [in] */ CorDebugRegister reg, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalDoubleRegisterValue( + + virtual HRESULT STDMETHODCALLTYPE GetLocalDoubleRegisterValue( /* [in] */ CorDebugRegister highWordReg, /* [in] */ CorDebugRegister lowWordReg, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalMemoryValue( + + virtual HRESULT STDMETHODCALLTYPE GetLocalMemoryValue( /* [in] */ CORDB_ADDRESS address, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalRegisterMemoryValue( + + virtual HRESULT STDMETHODCALLTYPE GetLocalRegisterMemoryValue( /* [in] */ CorDebugRegister highWordReg, /* [in] */ CORDB_ADDRESS lowWordAddress, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalMemoryRegisterValue( + + virtual HRESULT STDMETHODCALLTYPE GetLocalMemoryRegisterValue( /* [in] */ CORDB_ADDRESS highWordAddress, /* [in] */ CorDebugRegister lowWordRegister, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE CanSetIP( + + virtual HRESULT STDMETHODCALLTYPE CanSetIP( /* [in] */ ULONG32 nOffset) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugNativeFrameVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugNativeFrame * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugNativeFrame * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugNativeFrame * This); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetChain) - HRESULT ( STDMETHODCALLTYPE *GetChain )( + HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugChain **ppChain); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCode) - HRESULT ( STDMETHODCALLTYPE *GetCode )( + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugCode **ppCode); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetFunction) - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugFunction **ppFunction); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetFunctionToken) - HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugNativeFrame * This, /* [out] */ mdMethodDef *pToken); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetStackRange) - HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugNativeFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCaller) - HRESULT ( STDMETHODCALLTYPE *GetCaller )( + HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCallee) - HRESULT ( STDMETHODCALLTYPE *GetCallee )( + HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - + DECLSPEC_XFGVIRT(ICorDebugFrame, CreateStepper) - HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugStepper **ppStepper); - + DECLSPEC_XFGVIRT(ICorDebugNativeFrame, GetIP) - HRESULT ( STDMETHODCALLTYPE *GetIP )( + HRESULT ( STDMETHODCALLTYPE *GetIP )( ICorDebugNativeFrame * This, /* [out] */ ULONG32 *pnOffset); - + DECLSPEC_XFGVIRT(ICorDebugNativeFrame, SetIP) - HRESULT ( STDMETHODCALLTYPE *SetIP )( + HRESULT ( STDMETHODCALLTYPE *SetIP )( ICorDebugNativeFrame * This, /* [in] */ ULONG32 nOffset); - + DECLSPEC_XFGVIRT(ICorDebugNativeFrame, GetRegisterSet) - HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( + HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugRegisterSet **ppRegisters); - + DECLSPEC_XFGVIRT(ICorDebugNativeFrame, GetLocalRegisterValue) - HRESULT ( STDMETHODCALLTYPE *GetLocalRegisterValue )( + HRESULT ( STDMETHODCALLTYPE *GetLocalRegisterValue )( ICorDebugNativeFrame * This, /* [in] */ CorDebugRegister reg, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugNativeFrame, GetLocalDoubleRegisterValue) - HRESULT ( STDMETHODCALLTYPE *GetLocalDoubleRegisterValue )( + HRESULT ( STDMETHODCALLTYPE *GetLocalDoubleRegisterValue )( ICorDebugNativeFrame * This, /* [in] */ CorDebugRegister highWordReg, /* [in] */ CorDebugRegister lowWordReg, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugNativeFrame, GetLocalMemoryValue) - HRESULT ( STDMETHODCALLTYPE *GetLocalMemoryValue )( + HRESULT ( STDMETHODCALLTYPE *GetLocalMemoryValue )( ICorDebugNativeFrame * This, /* [in] */ CORDB_ADDRESS address, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugNativeFrame, GetLocalRegisterMemoryValue) - HRESULT ( STDMETHODCALLTYPE *GetLocalRegisterMemoryValue )( + HRESULT ( STDMETHODCALLTYPE *GetLocalRegisterMemoryValue )( ICorDebugNativeFrame * This, /* [in] */ CorDebugRegister highWordReg, /* [in] */ CORDB_ADDRESS lowWordAddress, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugNativeFrame, GetLocalMemoryRegisterValue) - HRESULT ( STDMETHODCALLTYPE *GetLocalMemoryRegisterValue )( + HRESULT ( STDMETHODCALLTYPE *GetLocalMemoryRegisterValue )( ICorDebugNativeFrame * This, /* [in] */ CORDB_ADDRESS highWordAddress, /* [in] */ CorDebugRegister lowWordRegister, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugNativeFrame, CanSetIP) - HRESULT ( STDMETHODCALLTYPE *CanSetIP )( + HRESULT ( STDMETHODCALLTYPE *CanSetIP )( ICorDebugNativeFrame * This, /* [in] */ ULONG32 nOffset); - + END_INTERFACE } ICorDebugNativeFrameVtbl; @@ -12263,72 +12270,72 @@ EXTERN_C const IID IID_ICorDebugNativeFrame; CONST_VTBL struct ICorDebugNativeFrameVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugNativeFrame_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugNativeFrame_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugNativeFrame_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugNativeFrame_GetChain(This,ppChain) \ - ( (This)->lpVtbl -> GetChain(This,ppChain) ) + ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugNativeFrame_GetCode(This,ppCode) \ - ( (This)->lpVtbl -> GetCode(This,ppCode) ) + ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugNativeFrame_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugNativeFrame_GetFunctionToken(This,pToken) \ - ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugNativeFrame_GetStackRange(This,pStart,pEnd) \ - ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugNativeFrame_GetCaller(This,ppFrame) \ - ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugNativeFrame_GetCallee(This,ppFrame) \ - ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugNativeFrame_CreateStepper(This,ppStepper) \ - ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #define ICorDebugNativeFrame_GetIP(This,pnOffset) \ - ( (This)->lpVtbl -> GetIP(This,pnOffset) ) + ( (This)->lpVtbl -> GetIP(This,pnOffset) ) #define ICorDebugNativeFrame_SetIP(This,nOffset) \ - ( (This)->lpVtbl -> SetIP(This,nOffset) ) + ( (This)->lpVtbl -> SetIP(This,nOffset) ) #define ICorDebugNativeFrame_GetRegisterSet(This,ppRegisters) \ - ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) + ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) #define ICorDebugNativeFrame_GetLocalRegisterValue(This,reg,cbSigBlob,pvSigBlob,ppValue) \ - ( (This)->lpVtbl -> GetLocalRegisterValue(This,reg,cbSigBlob,pvSigBlob,ppValue) ) + ( (This)->lpVtbl -> GetLocalRegisterValue(This,reg,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_GetLocalDoubleRegisterValue(This,highWordReg,lowWordReg,cbSigBlob,pvSigBlob,ppValue) \ - ( (This)->lpVtbl -> GetLocalDoubleRegisterValue(This,highWordReg,lowWordReg,cbSigBlob,pvSigBlob,ppValue) ) + ( (This)->lpVtbl -> GetLocalDoubleRegisterValue(This,highWordReg,lowWordReg,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_GetLocalMemoryValue(This,address,cbSigBlob,pvSigBlob,ppValue) \ - ( (This)->lpVtbl -> GetLocalMemoryValue(This,address,cbSigBlob,pvSigBlob,ppValue) ) + ( (This)->lpVtbl -> GetLocalMemoryValue(This,address,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_GetLocalRegisterMemoryValue(This,highWordReg,lowWordAddress,cbSigBlob,pvSigBlob,ppValue) \ - ( (This)->lpVtbl -> GetLocalRegisterMemoryValue(This,highWordReg,lowWordAddress,cbSigBlob,pvSigBlob,ppValue) ) + ( (This)->lpVtbl -> GetLocalRegisterMemoryValue(This,highWordReg,lowWordAddress,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_GetLocalMemoryRegisterValue(This,highWordAddress,lowWordRegister,cbSigBlob,pvSigBlob,ppValue) \ - ( (This)->lpVtbl -> GetLocalMemoryRegisterValue(This,highWordAddress,lowWordRegister,cbSigBlob,pvSigBlob,ppValue) ) + ( (This)->lpVtbl -> GetLocalMemoryRegisterValue(This,highWordAddress,lowWordRegister,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_CanSetIP(This,nOffset) \ - ( (This)->lpVtbl -> CanSetIP(This,nOffset) ) + ( (This)->lpVtbl -> CanSetIP(This,nOffset) ) #endif /* COBJMACROS */ @@ -12342,10 +12349,10 @@ EXTERN_C const IID IID_ICorDebugNativeFrame; /* interface __MIDL_itf_cordebug_0000_0072 */ -/* [local] */ +/* [local] */ #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0072_v0_0_c_ifspec; @@ -12355,67 +12362,67 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0072_v0_0_s_ifspec; #define __ICorDebugNativeFrame2_INTERFACE_DEFINED__ /* interface ICorDebugNativeFrame2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugNativeFrame2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("35389FF1-3684-4c55-A2EE-210F26C60E5E") ICorDebugNativeFrame2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE IsChild( + virtual HRESULT STDMETHODCALLTYPE IsChild( /* [out] */ BOOL *pIsChild) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsMatchingParentFrame( + + virtual HRESULT STDMETHODCALLTYPE IsMatchingParentFrame( /* [in] */ ICorDebugNativeFrame2 *pPotentialParentFrame, /* [out] */ BOOL *pIsParent) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStackParameterSize( + + virtual HRESULT STDMETHODCALLTYPE GetStackParameterSize( /* [out] */ ULONG32 *pSize) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugNativeFrame2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugNativeFrame2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugNativeFrame2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugNativeFrame2 * This); - + DECLSPEC_XFGVIRT(ICorDebugNativeFrame2, IsChild) - HRESULT ( STDMETHODCALLTYPE *IsChild )( + HRESULT ( STDMETHODCALLTYPE *IsChild )( ICorDebugNativeFrame2 * This, /* [out] */ BOOL *pIsChild); - + DECLSPEC_XFGVIRT(ICorDebugNativeFrame2, IsMatchingParentFrame) - HRESULT ( STDMETHODCALLTYPE *IsMatchingParentFrame )( + HRESULT ( STDMETHODCALLTYPE *IsMatchingParentFrame )( ICorDebugNativeFrame2 * This, /* [in] */ ICorDebugNativeFrame2 *pPotentialParentFrame, /* [out] */ BOOL *pIsParent); - + DECLSPEC_XFGVIRT(ICorDebugNativeFrame2, GetStackParameterSize) - HRESULT ( STDMETHODCALLTYPE *GetStackParameterSize )( + HRESULT ( STDMETHODCALLTYPE *GetStackParameterSize )( ICorDebugNativeFrame2 * This, /* [out] */ ULONG32 *pSize); - + END_INTERFACE } ICorDebugNativeFrame2Vtbl; @@ -12424,29 +12431,29 @@ EXTERN_C const IID IID_ICorDebugNativeFrame2; CONST_VTBL struct ICorDebugNativeFrame2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugNativeFrame2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugNativeFrame2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugNativeFrame2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugNativeFrame2_IsChild(This,pIsChild) \ - ( (This)->lpVtbl -> IsChild(This,pIsChild) ) + ( (This)->lpVtbl -> IsChild(This,pIsChild) ) #define ICorDebugNativeFrame2_IsMatchingParentFrame(This,pPotentialParentFrame,pIsParent) \ - ( (This)->lpVtbl -> IsMatchingParentFrame(This,pPotentialParentFrame,pIsParent) ) + ( (This)->lpVtbl -> IsMatchingParentFrame(This,pPotentialParentFrame,pIsParent) ) #define ICorDebugNativeFrame2_GetStackParameterSize(This,pSize) \ - ( (This)->lpVtbl -> GetStackParameterSize(This,pSize) ) + ( (This)->lpVtbl -> GetStackParameterSize(This,pSize) ) #endif /* COBJMACROS */ @@ -12463,51 +12470,51 @@ EXTERN_C const IID IID_ICorDebugNativeFrame2; #define __ICorDebugModule3_INTERFACE_DEFINED__ /* interface ICorDebugModule3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModule3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("86F012BF-FF15-4372-BD30-B6F11CAAE1DD") ICorDebugModule3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CreateReaderForInMemorySymbols( + virtual HRESULT STDMETHODCALLTYPE CreateReaderForInMemorySymbols( /* [in] */ REFIID riid, /* [iid_is][out] */ void **ppObj) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugModule3Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModule3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModule3 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModule3 * This); - + DECLSPEC_XFGVIRT(ICorDebugModule3, CreateReaderForInMemorySymbols) - HRESULT ( STDMETHODCALLTYPE *CreateReaderForInMemorySymbols )( + HRESULT ( STDMETHODCALLTYPE *CreateReaderForInMemorySymbols )( ICorDebugModule3 * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void **ppObj); - + END_INTERFACE } ICorDebugModule3Vtbl; @@ -12516,23 +12523,23 @@ EXTERN_C const IID IID_ICorDebugModule3; CONST_VTBL struct ICorDebugModule3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugModule3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModule3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModule3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModule3_CreateReaderForInMemorySymbols(This,riid,ppObj) \ - ( (This)->lpVtbl -> CreateReaderForInMemorySymbols(This,riid,ppObj) ) + ( (This)->lpVtbl -> CreateReaderForInMemorySymbols(This,riid,ppObj) ) #endif /* COBJMACROS */ @@ -12549,49 +12556,49 @@ EXTERN_C const IID IID_ICorDebugModule3; #define __ICorDebugModule4_INTERFACE_DEFINED__ /* interface ICorDebugModule4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModule4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("FF8B8EAF-25CD-4316-8859-84416DE4402E") ICorDebugModule4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE IsMappedLayout( + virtual HRESULT STDMETHODCALLTYPE IsMappedLayout( /* [out] */ BOOL *pIsMapped) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugModule4Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModule4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModule4 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModule4 * This); - + DECLSPEC_XFGVIRT(ICorDebugModule4, IsMappedLayout) - HRESULT ( STDMETHODCALLTYPE *IsMappedLayout )( + HRESULT ( STDMETHODCALLTYPE *IsMappedLayout )( ICorDebugModule4 * This, /* [out] */ BOOL *pIsMapped); - + END_INTERFACE } ICorDebugModule4Vtbl; @@ -12600,23 +12607,23 @@ EXTERN_C const IID IID_ICorDebugModule4; CONST_VTBL struct ICorDebugModule4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugModule4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModule4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModule4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModule4_IsMappedLayout(This,pIsMapped) \ - ( (This)->lpVtbl -> IsMappedLayout(This,pIsMapped) ) + ( (This)->lpVtbl -> IsMappedLayout(This,pIsMapped) ) #endif /* COBJMACROS */ @@ -12633,82 +12640,82 @@ EXTERN_C const IID IID_ICorDebugModule4; #define __ICorDebugRuntimeUnwindableFrame_INTERFACE_DEFINED__ /* interface ICorDebugRuntimeUnwindableFrame */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugRuntimeUnwindableFrame; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("879CAC0A-4A53-4668-B8E3-CB8473CB187F") ICorDebugRuntimeUnwindableFrame : public ICorDebugFrame { public: }; - - + + #else /* C style interface */ typedef struct ICorDebugRuntimeUnwindableFrameVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRuntimeUnwindableFrame * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRuntimeUnwindableFrame * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRuntimeUnwindableFrame * This); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetChain) - HRESULT ( STDMETHODCALLTYPE *GetChain )( + HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugChain **ppChain); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCode) - HRESULT ( STDMETHODCALLTYPE *GetCode )( + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugCode **ppCode); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetFunction) - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugFunction **ppFunction); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetFunctionToken) - HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ mdMethodDef *pToken); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetStackRange) - HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCaller) - HRESULT ( STDMETHODCALLTYPE *GetCaller )( + HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - + DECLSPEC_XFGVIRT(ICorDebugFrame, GetCallee) - HRESULT ( STDMETHODCALLTYPE *GetCallee )( + HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - + DECLSPEC_XFGVIRT(ICorDebugFrame, CreateStepper) - HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugStepper **ppStepper); - + END_INTERFACE } ICorDebugRuntimeUnwindableFrameVtbl; @@ -12717,44 +12724,44 @@ EXTERN_C const IID IID_ICorDebugRuntimeUnwindableFrame; CONST_VTBL struct ICorDebugRuntimeUnwindableFrameVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugRuntimeUnwindableFrame_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRuntimeUnwindableFrame_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRuntimeUnwindableFrame_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRuntimeUnwindableFrame_GetChain(This,ppChain) \ - ( (This)->lpVtbl -> GetChain(This,ppChain) ) + ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugRuntimeUnwindableFrame_GetCode(This,ppCode) \ - ( (This)->lpVtbl -> GetCode(This,ppCode) ) + ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugRuntimeUnwindableFrame_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugRuntimeUnwindableFrame_GetFunctionToken(This,pToken) \ - ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugRuntimeUnwindableFrame_GetStackRange(This,pStart,pEnd) \ - ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugRuntimeUnwindableFrame_GetCaller(This,ppFrame) \ - ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugRuntimeUnwindableFrame_GetCallee(This,ppFrame) \ - ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugRuntimeUnwindableFrame_CreateStepper(This,ppStepper) \ - ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #endif /* COBJMACROS */ @@ -12772,193 +12779,193 @@ EXTERN_C const IID IID_ICorDebugRuntimeUnwindableFrame; #define __ICorDebugModule_INTERFACE_DEFINED__ /* interface ICorDebugModule */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModule; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("dba2d8c1-e5c5-4069-8c13-10a7c6abf43d") ICorDebugModule : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetProcess( + virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetBaseAddress( + + virtual HRESULT STDMETHODCALLTYPE GetBaseAddress( /* [out] */ CORDB_ADDRESS *pAddress) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAssembly( + + virtual HRESULT STDMETHODCALLTYPE GetAssembly( /* [out] */ ICorDebugAssembly **ppAssembly) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetName( + + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnableJITDebugging( + + virtual HRESULT STDMETHODCALLTYPE EnableJITDebugging( /* [in] */ BOOL bTrackJITInfo, /* [in] */ BOOL bAllowJitOpts) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnableClassLoadCallbacks( + + virtual HRESULT STDMETHODCALLTYPE EnableClassLoadCallbacks( /* [in] */ BOOL bClassLoadCallbacks) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunctionFromToken( + + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromToken( /* [in] */ mdMethodDef methodDef, /* [out] */ ICorDebugFunction **ppFunction) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunctionFromRVA( + + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromRVA( /* [in] */ CORDB_ADDRESS rva, /* [out] */ ICorDebugFunction **ppFunction) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetClassFromToken( + + virtual HRESULT STDMETHODCALLTYPE GetClassFromToken( /* [in] */ mdTypeDef typeDef, /* [out] */ ICorDebugClass **ppClass) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( /* [out] */ ICorDebugModuleBreakpoint **ppBreakpoint) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetEditAndContinueSnapshot( + + virtual HRESULT STDMETHODCALLTYPE GetEditAndContinueSnapshot( /* [out] */ ICorDebugEditAndContinueSnapshot **ppEditAndContinueSnapshot) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMetaDataInterface( + + virtual HRESULT STDMETHODCALLTYPE GetMetaDataInterface( /* [in] */ REFIID riid, /* [out] */ IUnknown **ppObj) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetToken( + + virtual HRESULT STDMETHODCALLTYPE GetToken( /* [out] */ mdModule *pToken) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsDynamic( + + virtual HRESULT STDMETHODCALLTYPE IsDynamic( /* [out] */ BOOL *pDynamic) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetGlobalVariableValue( + + virtual HRESULT STDMETHODCALLTYPE GetGlobalVariableValue( /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcBytes) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsInMemory( + + virtual HRESULT STDMETHODCALLTYPE IsInMemory( /* [out] */ BOOL *pInMemory) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugModuleVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModule * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModule * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModule * This); - + DECLSPEC_XFGVIRT(ICorDebugModule, GetProcess) - HRESULT ( STDMETHODCALLTYPE *GetProcess )( + HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebugModule * This, /* [out] */ ICorDebugProcess **ppProcess); - + DECLSPEC_XFGVIRT(ICorDebugModule, GetBaseAddress) - HRESULT ( STDMETHODCALLTYPE *GetBaseAddress )( + HRESULT ( STDMETHODCALLTYPE *GetBaseAddress )( ICorDebugModule * This, /* [out] */ CORDB_ADDRESS *pAddress); - + DECLSPEC_XFGVIRT(ICorDebugModule, GetAssembly) - HRESULT ( STDMETHODCALLTYPE *GetAssembly )( + HRESULT ( STDMETHODCALLTYPE *GetAssembly )( ICorDebugModule * This, /* [out] */ ICorDebugAssembly **ppAssembly); - + DECLSPEC_XFGVIRT(ICorDebugModule, GetName) - HRESULT ( STDMETHODCALLTYPE *GetName )( + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugModule * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - + DECLSPEC_XFGVIRT(ICorDebugModule, EnableJITDebugging) - HRESULT ( STDMETHODCALLTYPE *EnableJITDebugging )( + HRESULT ( STDMETHODCALLTYPE *EnableJITDebugging )( ICorDebugModule * This, /* [in] */ BOOL bTrackJITInfo, /* [in] */ BOOL bAllowJitOpts); - + DECLSPEC_XFGVIRT(ICorDebugModule, EnableClassLoadCallbacks) - HRESULT ( STDMETHODCALLTYPE *EnableClassLoadCallbacks )( + HRESULT ( STDMETHODCALLTYPE *EnableClassLoadCallbacks )( ICorDebugModule * This, /* [in] */ BOOL bClassLoadCallbacks); - + DECLSPEC_XFGVIRT(ICorDebugModule, GetFunctionFromToken) - HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorDebugModule * This, /* [in] */ mdMethodDef methodDef, /* [out] */ ICorDebugFunction **ppFunction); - + DECLSPEC_XFGVIRT(ICorDebugModule, GetFunctionFromRVA) - HRESULT ( STDMETHODCALLTYPE *GetFunctionFromRVA )( + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromRVA )( ICorDebugModule * This, /* [in] */ CORDB_ADDRESS rva, /* [out] */ ICorDebugFunction **ppFunction); - + DECLSPEC_XFGVIRT(ICorDebugModule, GetClassFromToken) - HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorDebugModule * This, /* [in] */ mdTypeDef typeDef, /* [out] */ ICorDebugClass **ppClass); - + DECLSPEC_XFGVIRT(ICorDebugModule, CreateBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugModule * This, /* [out] */ ICorDebugModuleBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugModule, GetEditAndContinueSnapshot) - HRESULT ( STDMETHODCALLTYPE *GetEditAndContinueSnapshot )( + HRESULT ( STDMETHODCALLTYPE *GetEditAndContinueSnapshot )( ICorDebugModule * This, /* [out] */ ICorDebugEditAndContinueSnapshot **ppEditAndContinueSnapshot); - + DECLSPEC_XFGVIRT(ICorDebugModule, GetMetaDataInterface) - HRESULT ( STDMETHODCALLTYPE *GetMetaDataInterface )( + HRESULT ( STDMETHODCALLTYPE *GetMetaDataInterface )( ICorDebugModule * This, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppObj); - + DECLSPEC_XFGVIRT(ICorDebugModule, GetToken) - HRESULT ( STDMETHODCALLTYPE *GetToken )( + HRESULT ( STDMETHODCALLTYPE *GetToken )( ICorDebugModule * This, /* [out] */ mdModule *pToken); - + DECLSPEC_XFGVIRT(ICorDebugModule, IsDynamic) - HRESULT ( STDMETHODCALLTYPE *IsDynamic )( + HRESULT ( STDMETHODCALLTYPE *IsDynamic )( ICorDebugModule * This, /* [out] */ BOOL *pDynamic); - + DECLSPEC_XFGVIRT(ICorDebugModule, GetGlobalVariableValue) - HRESULT ( STDMETHODCALLTYPE *GetGlobalVariableValue )( + HRESULT ( STDMETHODCALLTYPE *GetGlobalVariableValue )( ICorDebugModule * This, /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugModule, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugModule * This, /* [out] */ ULONG32 *pcBytes); - + DECLSPEC_XFGVIRT(ICorDebugModule, IsInMemory) - HRESULT ( STDMETHODCALLTYPE *IsInMemory )( + HRESULT ( STDMETHODCALLTYPE *IsInMemory )( ICorDebugModule * This, /* [out] */ BOOL *pInMemory); - + END_INTERFACE } ICorDebugModuleVtbl; @@ -12967,71 +12974,71 @@ EXTERN_C const IID IID_ICorDebugModule; CONST_VTBL struct ICorDebugModuleVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugModule_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModule_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModule_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModule_GetProcess(This,ppProcess) \ - ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) + ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) #define ICorDebugModule_GetBaseAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetBaseAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetBaseAddress(This,pAddress) ) #define ICorDebugModule_GetAssembly(This,ppAssembly) \ - ( (This)->lpVtbl -> GetAssembly(This,ppAssembly) ) + ( (This)->lpVtbl -> GetAssembly(This,ppAssembly) ) #define ICorDebugModule_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugModule_EnableJITDebugging(This,bTrackJITInfo,bAllowJitOpts) \ - ( (This)->lpVtbl -> EnableJITDebugging(This,bTrackJITInfo,bAllowJitOpts) ) + ( (This)->lpVtbl -> EnableJITDebugging(This,bTrackJITInfo,bAllowJitOpts) ) #define ICorDebugModule_EnableClassLoadCallbacks(This,bClassLoadCallbacks) \ - ( (This)->lpVtbl -> EnableClassLoadCallbacks(This,bClassLoadCallbacks) ) + ( (This)->lpVtbl -> EnableClassLoadCallbacks(This,bClassLoadCallbacks) ) #define ICorDebugModule_GetFunctionFromToken(This,methodDef,ppFunction) \ - ( (This)->lpVtbl -> GetFunctionFromToken(This,methodDef,ppFunction) ) + ( (This)->lpVtbl -> GetFunctionFromToken(This,methodDef,ppFunction) ) #define ICorDebugModule_GetFunctionFromRVA(This,rva,ppFunction) \ - ( (This)->lpVtbl -> GetFunctionFromRVA(This,rva,ppFunction) ) + ( (This)->lpVtbl -> GetFunctionFromRVA(This,rva,ppFunction) ) #define ICorDebugModule_GetClassFromToken(This,typeDef,ppClass) \ - ( (This)->lpVtbl -> GetClassFromToken(This,typeDef,ppClass) ) + ( (This)->lpVtbl -> GetClassFromToken(This,typeDef,ppClass) ) #define ICorDebugModule_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugModule_GetEditAndContinueSnapshot(This,ppEditAndContinueSnapshot) \ - ( (This)->lpVtbl -> GetEditAndContinueSnapshot(This,ppEditAndContinueSnapshot) ) + ( (This)->lpVtbl -> GetEditAndContinueSnapshot(This,ppEditAndContinueSnapshot) ) #define ICorDebugModule_GetMetaDataInterface(This,riid,ppObj) \ - ( (This)->lpVtbl -> GetMetaDataInterface(This,riid,ppObj) ) + ( (This)->lpVtbl -> GetMetaDataInterface(This,riid,ppObj) ) #define ICorDebugModule_GetToken(This,pToken) \ - ( (This)->lpVtbl -> GetToken(This,pToken) ) + ( (This)->lpVtbl -> GetToken(This,pToken) ) #define ICorDebugModule_IsDynamic(This,pDynamic) \ - ( (This)->lpVtbl -> IsDynamic(This,pDynamic) ) + ( (This)->lpVtbl -> IsDynamic(This,pDynamic) ) #define ICorDebugModule_GetGlobalVariableValue(This,fieldDef,ppValue) \ - ( (This)->lpVtbl -> GetGlobalVariableValue(This,fieldDef,ppValue) ) + ( (This)->lpVtbl -> GetGlobalVariableValue(This,fieldDef,ppValue) ) #define ICorDebugModule_GetSize(This,pcBytes) \ - ( (This)->lpVtbl -> GetSize(This,pcBytes) ) + ( (This)->lpVtbl -> GetSize(This,pcBytes) ) #define ICorDebugModule_IsInMemory(This,pInMemory) \ - ( (This)->lpVtbl -> IsInMemory(This,pInMemory) ) + ( (This)->lpVtbl -> IsInMemory(This,pInMemory) ) #endif /* COBJMACROS */ @@ -13045,7 +13052,7 @@ EXTERN_C const IID IID_ICorDebugModule; /* interface __MIDL_itf_cordebug_0000_0077 */ -/* [local] */ +/* [local] */ #pragma warning(pop) @@ -13057,93 +13064,93 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0077_v0_0_s_ifspec; #define __ICorDebugModule2_INTERFACE_DEFINED__ /* interface ICorDebugModule2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModule2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("7FCC5FB5-49C0-41de-9938-3B88B5B9ADD7") ICorDebugModule2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( + virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( /* [in] */ BOOL bIsJustMyCode, /* [in] */ ULONG32 cTokens, /* [size_is][in] */ mdToken pTokens[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE ApplyChanges( + + virtual HRESULT STDMETHODCALLTYPE ApplyChanges( /* [in] */ ULONG cbMetadata, /* [size_is][in] */ BYTE pbMetadata[ ], /* [in] */ ULONG cbIL, /* [size_is][in] */ BYTE pbIL[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetJITCompilerFlags( + + virtual HRESULT STDMETHODCALLTYPE SetJITCompilerFlags( /* [in] */ DWORD dwFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetJITCompilerFlags( + + virtual HRESULT STDMETHODCALLTYPE GetJITCompilerFlags( /* [out] */ DWORD *pdwFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE ResolveAssembly( + + virtual HRESULT STDMETHODCALLTYPE ResolveAssembly( /* [in] */ mdToken tkAssemblyRef, /* [out] */ ICorDebugAssembly **ppAssembly) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugModule2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModule2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModule2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModule2 * This); - + DECLSPEC_XFGVIRT(ICorDebugModule2, SetJMCStatus) - HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( + HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( ICorDebugModule2 * This, /* [in] */ BOOL bIsJustMyCode, /* [in] */ ULONG32 cTokens, /* [size_is][in] */ mdToken pTokens[ ]); - + DECLSPEC_XFGVIRT(ICorDebugModule2, ApplyChanges) - HRESULT ( STDMETHODCALLTYPE *ApplyChanges )( + HRESULT ( STDMETHODCALLTYPE *ApplyChanges )( ICorDebugModule2 * This, /* [in] */ ULONG cbMetadata, /* [size_is][in] */ BYTE pbMetadata[ ], /* [in] */ ULONG cbIL, /* [size_is][in] */ BYTE pbIL[ ]); - + DECLSPEC_XFGVIRT(ICorDebugModule2, SetJITCompilerFlags) - HRESULT ( STDMETHODCALLTYPE *SetJITCompilerFlags )( + HRESULT ( STDMETHODCALLTYPE *SetJITCompilerFlags )( ICorDebugModule2 * This, /* [in] */ DWORD dwFlags); - + DECLSPEC_XFGVIRT(ICorDebugModule2, GetJITCompilerFlags) - HRESULT ( STDMETHODCALLTYPE *GetJITCompilerFlags )( + HRESULT ( STDMETHODCALLTYPE *GetJITCompilerFlags )( ICorDebugModule2 * This, /* [out] */ DWORD *pdwFlags); - + DECLSPEC_XFGVIRT(ICorDebugModule2, ResolveAssembly) - HRESULT ( STDMETHODCALLTYPE *ResolveAssembly )( + HRESULT ( STDMETHODCALLTYPE *ResolveAssembly )( ICorDebugModule2 * This, /* [in] */ mdToken tkAssemblyRef, /* [out] */ ICorDebugAssembly **ppAssembly); - + END_INTERFACE } ICorDebugModule2Vtbl; @@ -13152,35 +13159,35 @@ EXTERN_C const IID IID_ICorDebugModule2; CONST_VTBL struct ICorDebugModule2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugModule2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModule2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModule2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModule2_SetJMCStatus(This,bIsJustMyCode,cTokens,pTokens) \ - ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode,cTokens,pTokens) ) + ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode,cTokens,pTokens) ) #define ICorDebugModule2_ApplyChanges(This,cbMetadata,pbMetadata,cbIL,pbIL) \ - ( (This)->lpVtbl -> ApplyChanges(This,cbMetadata,pbMetadata,cbIL,pbIL) ) + ( (This)->lpVtbl -> ApplyChanges(This,cbMetadata,pbMetadata,cbIL,pbIL) ) #define ICorDebugModule2_SetJITCompilerFlags(This,dwFlags) \ - ( (This)->lpVtbl -> SetJITCompilerFlags(This,dwFlags) ) + ( (This)->lpVtbl -> SetJITCompilerFlags(This,dwFlags) ) #define ICorDebugModule2_GetJITCompilerFlags(This,pdwFlags) \ - ( (This)->lpVtbl -> GetJITCompilerFlags(This,pdwFlags) ) + ( (This)->lpVtbl -> GetJITCompilerFlags(This,pdwFlags) ) #define ICorDebugModule2_ResolveAssembly(This,tkAssemblyRef,ppAssembly) \ - ( (This)->lpVtbl -> ResolveAssembly(This,tkAssemblyRef,ppAssembly) ) + ( (This)->lpVtbl -> ResolveAssembly(This,tkAssemblyRef,ppAssembly) ) #endif /* COBJMACROS */ @@ -13197,105 +13204,105 @@ EXTERN_C const IID IID_ICorDebugModule2; #define __ICorDebugFunction_INTERFACE_DEFINED__ /* interface ICorDebugFunction */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunction; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAF3-8A68-11d2-983C-0000F808342D") ICorDebugFunction : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetModule( + virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **ppModule) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetClass( + + virtual HRESULT STDMETHODCALLTYPE GetClass( /* [out] */ ICorDebugClass **ppClass) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetToken( + + virtual HRESULT STDMETHODCALLTYPE GetToken( /* [out] */ mdMethodDef *pMethodDef) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetILCode( + + virtual HRESULT STDMETHODCALLTYPE GetILCode( /* [out] */ ICorDebugCode **ppCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetNativeCode( + + virtual HRESULT STDMETHODCALLTYPE GetNativeCode( /* [out] */ ICorDebugCode **ppCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalVarSigToken( + + virtual HRESULT STDMETHODCALLTYPE GetLocalVarSigToken( /* [out] */ mdSignature *pmdSig) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCurrentVersionNumber( + + virtual HRESULT STDMETHODCALLTYPE GetCurrentVersionNumber( /* [out] */ ULONG32 *pnCurrentVersion) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFunctionVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunction * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunction * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunction * This); - + DECLSPEC_XFGVIRT(ICorDebugFunction, GetModule) - HRESULT ( STDMETHODCALLTYPE *GetModule )( + HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugFunction * This, /* [out] */ ICorDebugModule **ppModule); - + DECLSPEC_XFGVIRT(ICorDebugFunction, GetClass) - HRESULT ( STDMETHODCALLTYPE *GetClass )( + HRESULT ( STDMETHODCALLTYPE *GetClass )( ICorDebugFunction * This, /* [out] */ ICorDebugClass **ppClass); - + DECLSPEC_XFGVIRT(ICorDebugFunction, GetToken) - HRESULT ( STDMETHODCALLTYPE *GetToken )( + HRESULT ( STDMETHODCALLTYPE *GetToken )( ICorDebugFunction * This, /* [out] */ mdMethodDef *pMethodDef); - + DECLSPEC_XFGVIRT(ICorDebugFunction, GetILCode) - HRESULT ( STDMETHODCALLTYPE *GetILCode )( + HRESULT ( STDMETHODCALLTYPE *GetILCode )( ICorDebugFunction * This, /* [out] */ ICorDebugCode **ppCode); - + DECLSPEC_XFGVIRT(ICorDebugFunction, GetNativeCode) - HRESULT ( STDMETHODCALLTYPE *GetNativeCode )( + HRESULT ( STDMETHODCALLTYPE *GetNativeCode )( ICorDebugFunction * This, /* [out] */ ICorDebugCode **ppCode); - + DECLSPEC_XFGVIRT(ICorDebugFunction, CreateBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugFunction * This, /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugFunction, GetLocalVarSigToken) - HRESULT ( STDMETHODCALLTYPE *GetLocalVarSigToken )( + HRESULT ( STDMETHODCALLTYPE *GetLocalVarSigToken )( ICorDebugFunction * This, /* [out] */ mdSignature *pmdSig); - + DECLSPEC_XFGVIRT(ICorDebugFunction, GetCurrentVersionNumber) - HRESULT ( STDMETHODCALLTYPE *GetCurrentVersionNumber )( + HRESULT ( STDMETHODCALLTYPE *GetCurrentVersionNumber )( ICorDebugFunction * This, /* [out] */ ULONG32 *pnCurrentVersion); - + END_INTERFACE } ICorDebugFunctionVtbl; @@ -13304,44 +13311,44 @@ EXTERN_C const IID IID_ICorDebugFunction; CONST_VTBL struct ICorDebugFunctionVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFunction_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunction_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunction_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunction_GetModule(This,ppModule) \ - ( (This)->lpVtbl -> GetModule(This,ppModule) ) + ( (This)->lpVtbl -> GetModule(This,ppModule) ) #define ICorDebugFunction_GetClass(This,ppClass) \ - ( (This)->lpVtbl -> GetClass(This,ppClass) ) + ( (This)->lpVtbl -> GetClass(This,ppClass) ) #define ICorDebugFunction_GetToken(This,pMethodDef) \ - ( (This)->lpVtbl -> GetToken(This,pMethodDef) ) + ( (This)->lpVtbl -> GetToken(This,pMethodDef) ) #define ICorDebugFunction_GetILCode(This,ppCode) \ - ( (This)->lpVtbl -> GetILCode(This,ppCode) ) + ( (This)->lpVtbl -> GetILCode(This,ppCode) ) #define ICorDebugFunction_GetNativeCode(This,ppCode) \ - ( (This)->lpVtbl -> GetNativeCode(This,ppCode) ) + ( (This)->lpVtbl -> GetNativeCode(This,ppCode) ) #define ICorDebugFunction_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugFunction_GetLocalVarSigToken(This,pmdSig) \ - ( (This)->lpVtbl -> GetLocalVarSigToken(This,pmdSig) ) + ( (This)->lpVtbl -> GetLocalVarSigToken(This,pmdSig) ) #define ICorDebugFunction_GetCurrentVersionNumber(This,pnCurrentVersion) \ - ( (This)->lpVtbl -> GetCurrentVersionNumber(This,pnCurrentVersion) ) + ( (This)->lpVtbl -> GetCurrentVersionNumber(This,pnCurrentVersion) ) #endif /* COBJMACROS */ @@ -13358,73 +13365,73 @@ EXTERN_C const IID IID_ICorDebugFunction; #define __ICorDebugFunction2_INTERFACE_DEFINED__ /* interface ICorDebugFunction2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunction2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("EF0C490B-94C3-4e4d-B629-DDC134C532D8") ICorDebugFunction2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( + virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( /* [in] */ BOOL bIsJustMyCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetJMCStatus( + + virtual HRESULT STDMETHODCALLTYPE GetJMCStatus( /* [out] */ BOOL *pbIsJustMyCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateNativeCode( + + virtual HRESULT STDMETHODCALLTYPE EnumerateNativeCode( /* [out] */ ICorDebugCodeEnum **ppCodeEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetVersionNumber( + + virtual HRESULT STDMETHODCALLTYPE GetVersionNumber( /* [out] */ ULONG32 *pnVersion) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFunction2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunction2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunction2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunction2 * This); - + DECLSPEC_XFGVIRT(ICorDebugFunction2, SetJMCStatus) - HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( + HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( ICorDebugFunction2 * This, /* [in] */ BOOL bIsJustMyCode); - + DECLSPEC_XFGVIRT(ICorDebugFunction2, GetJMCStatus) - HRESULT ( STDMETHODCALLTYPE *GetJMCStatus )( + HRESULT ( STDMETHODCALLTYPE *GetJMCStatus )( ICorDebugFunction2 * This, /* [out] */ BOOL *pbIsJustMyCode); - + DECLSPEC_XFGVIRT(ICorDebugFunction2, EnumerateNativeCode) - HRESULT ( STDMETHODCALLTYPE *EnumerateNativeCode )( + HRESULT ( STDMETHODCALLTYPE *EnumerateNativeCode )( ICorDebugFunction2 * This, /* [out] */ ICorDebugCodeEnum **ppCodeEnum); - + DECLSPEC_XFGVIRT(ICorDebugFunction2, GetVersionNumber) - HRESULT ( STDMETHODCALLTYPE *GetVersionNumber )( + HRESULT ( STDMETHODCALLTYPE *GetVersionNumber )( ICorDebugFunction2 * This, /* [out] */ ULONG32 *pnVersion); - + END_INTERFACE } ICorDebugFunction2Vtbl; @@ -13433,32 +13440,32 @@ EXTERN_C const IID IID_ICorDebugFunction2; CONST_VTBL struct ICorDebugFunction2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFunction2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunction2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunction2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunction2_SetJMCStatus(This,bIsJustMyCode) \ - ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode) ) + ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode) ) #define ICorDebugFunction2_GetJMCStatus(This,pbIsJustMyCode) \ - ( (This)->lpVtbl -> GetJMCStatus(This,pbIsJustMyCode) ) + ( (This)->lpVtbl -> GetJMCStatus(This,pbIsJustMyCode) ) #define ICorDebugFunction2_EnumerateNativeCode(This,ppCodeEnum) \ - ( (This)->lpVtbl -> EnumerateNativeCode(This,ppCodeEnum) ) + ( (This)->lpVtbl -> EnumerateNativeCode(This,ppCodeEnum) ) #define ICorDebugFunction2_GetVersionNumber(This,pnVersion) \ - ( (This)->lpVtbl -> GetVersionNumber(This,pnVersion) ) + ( (This)->lpVtbl -> GetVersionNumber(This,pnVersion) ) #endif /* COBJMACROS */ @@ -13475,49 +13482,49 @@ EXTERN_C const IID IID_ICorDebugFunction2; #define __ICorDebugFunction3_INTERFACE_DEFINED__ /* interface ICorDebugFunction3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunction3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("09B70F28-E465-482D-99E0-81A165EB0532") ICorDebugFunction3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetActiveReJitRequestILCode( + virtual HRESULT STDMETHODCALLTYPE GetActiveReJitRequestILCode( ICorDebugILCode **ppReJitedILCode) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFunction3Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunction3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunction3 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunction3 * This); - + DECLSPEC_XFGVIRT(ICorDebugFunction3, GetActiveReJitRequestILCode) - HRESULT ( STDMETHODCALLTYPE *GetActiveReJitRequestILCode )( + HRESULT ( STDMETHODCALLTYPE *GetActiveReJitRequestILCode )( ICorDebugFunction3 * This, ICorDebugILCode **ppReJitedILCode); - + END_INTERFACE } ICorDebugFunction3Vtbl; @@ -13526,23 +13533,23 @@ EXTERN_C const IID IID_ICorDebugFunction3; CONST_VTBL struct ICorDebugFunction3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFunction3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunction3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunction3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunction3_GetActiveReJitRequestILCode(This,ppReJitedILCode) \ - ( (This)->lpVtbl -> GetActiveReJitRequestILCode(This,ppReJitedILCode) ) + ( (This)->lpVtbl -> GetActiveReJitRequestILCode(This,ppReJitedILCode) ) #endif /* COBJMACROS */ @@ -13559,49 +13566,49 @@ EXTERN_C const IID IID_ICorDebugFunction3; #define __ICorDebugFunction4_INTERFACE_DEFINED__ /* interface ICorDebugFunction4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunction4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("72965963-34fd-46e9-9434-b817fe6e7f43") ICorDebugFunction4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CreateNativeBreakpoint( + virtual HRESULT STDMETHODCALLTYPE CreateNativeBreakpoint( ICorDebugFunctionBreakpoint **ppBreakpoint) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFunction4Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunction4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunction4 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunction4 * This); - + DECLSPEC_XFGVIRT(ICorDebugFunction4, CreateNativeBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateNativeBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateNativeBreakpoint )( ICorDebugFunction4 * This, ICorDebugFunctionBreakpoint **ppBreakpoint); - + END_INTERFACE } ICorDebugFunction4Vtbl; @@ -13610,23 +13617,23 @@ EXTERN_C const IID IID_ICorDebugFunction4; CONST_VTBL struct ICorDebugFunction4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFunction4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunction4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunction4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunction4_CreateNativeBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateNativeBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateNativeBreakpoint(This,ppBreakpoint) ) #endif /* COBJMACROS */ @@ -13643,55 +13650,55 @@ EXTERN_C const IID IID_ICorDebugFunction4; #define __ICorDebugFunction5_INTERFACE_DEFINED__ /* interface ICorDebugFunction5 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunction5; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("9D4DAB7B-3401-4F37-BD08-CA09F3FDF10F") ICorDebugFunction5 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE DisableOptimizations( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE AreOptimizationsDisabled( + + virtual HRESULT STDMETHODCALLTYPE AreOptimizationsDisabled( BOOL *pOptimizationsDisabled) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFunction5Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunction5 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunction5 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunction5 * This); - + DECLSPEC_XFGVIRT(ICorDebugFunction5, DisableOptimizations) - HRESULT ( STDMETHODCALLTYPE *DisableOptimizations )( + HRESULT ( STDMETHODCALLTYPE *DisableOptimizations )( ICorDebugFunction5 * This); - + DECLSPEC_XFGVIRT(ICorDebugFunction5, AreOptimizationsDisabled) - HRESULT ( STDMETHODCALLTYPE *AreOptimizationsDisabled )( + HRESULT ( STDMETHODCALLTYPE *AreOptimizationsDisabled )( ICorDebugFunction5 * This, BOOL *pOptimizationsDisabled); - + END_INTERFACE } ICorDebugFunction5Vtbl; @@ -13700,26 +13707,26 @@ EXTERN_C const IID IID_ICorDebugFunction5; CONST_VTBL struct ICorDebugFunction5Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFunction5_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunction5_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunction5_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunction5_DisableOptimizations(This) \ - ( (This)->lpVtbl -> DisableOptimizations(This) ) + ( (This)->lpVtbl -> DisableOptimizations(This) ) #define ICorDebugFunction5_AreOptimizationsDisabled(This,pOptimizationsDisabled) \ - ( (This)->lpVtbl -> AreOptimizationsDisabled(This,pOptimizationsDisabled) ) + ( (This)->lpVtbl -> AreOptimizationsDisabled(This,pOptimizationsDisabled) ) #endif /* COBJMACROS */ @@ -13736,131 +13743,131 @@ EXTERN_C const IID IID_ICorDebugFunction5; #define __ICorDebugCode_INTERFACE_DEFINED__ /* interface ICorDebugCode */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugCode; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAF4-8A68-11d2-983C-0000F808342D") ICorDebugCode : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE IsIL( + virtual HRESULT STDMETHODCALLTYPE IsIL( /* [out] */ BOOL *pbIL) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunction( + + virtual HRESULT STDMETHODCALLTYPE GetFunction( /* [out] */ ICorDebugFunction **ppFunction) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAddress( + + virtual HRESULT STDMETHODCALLTYPE GetAddress( /* [out] */ CORDB_ADDRESS *pStart) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcBytes) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( /* [in] */ ULONG32 offset, /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCode( + + virtual HRESULT STDMETHODCALLTYPE GetCode( /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset, /* [in] */ ULONG32 cBufferAlloc, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ ULONG32 *pcBufferSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetVersionNumber( + + virtual HRESULT STDMETHODCALLTYPE GetVersionNumber( /* [out] */ ULONG32 *nVersion) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping( + + virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping( /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetEnCRemapSequencePoints( + + virtual HRESULT STDMETHODCALLTYPE GetEnCRemapSequencePoints( /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ ULONG32 offsets[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugCodeVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCode * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCode * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCode * This); - + DECLSPEC_XFGVIRT(ICorDebugCode, IsIL) - HRESULT ( STDMETHODCALLTYPE *IsIL )( + HRESULT ( STDMETHODCALLTYPE *IsIL )( ICorDebugCode * This, /* [out] */ BOOL *pbIL); - + DECLSPEC_XFGVIRT(ICorDebugCode, GetFunction) - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugCode * This, /* [out] */ ICorDebugFunction **ppFunction); - + DECLSPEC_XFGVIRT(ICorDebugCode, GetAddress) - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugCode * This, /* [out] */ CORDB_ADDRESS *pStart); - + DECLSPEC_XFGVIRT(ICorDebugCode, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugCode * This, /* [out] */ ULONG32 *pcBytes); - + DECLSPEC_XFGVIRT(ICorDebugCode, CreateBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugCode * This, /* [in] */ ULONG32 offset, /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugCode, GetCode) - HRESULT ( STDMETHODCALLTYPE *GetCode )( + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugCode * This, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset, /* [in] */ ULONG32 cBufferAlloc, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ ULONG32 *pcBufferSize); - + DECLSPEC_XFGVIRT(ICorDebugCode, GetVersionNumber) - HRESULT ( STDMETHODCALLTYPE *GetVersionNumber )( + HRESULT ( STDMETHODCALLTYPE *GetVersionNumber )( ICorDebugCode * This, /* [out] */ ULONG32 *nVersion); - + DECLSPEC_XFGVIRT(ICorDebugCode, GetILToNativeMapping) - HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorDebugCode * This, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); - + DECLSPEC_XFGVIRT(ICorDebugCode, GetEnCRemapSequencePoints) - HRESULT ( STDMETHODCALLTYPE *GetEnCRemapSequencePoints )( + HRESULT ( STDMETHODCALLTYPE *GetEnCRemapSequencePoints )( ICorDebugCode * This, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ ULONG32 offsets[ ]); - + END_INTERFACE } ICorDebugCodeVtbl; @@ -13869,47 +13876,47 @@ EXTERN_C const IID IID_ICorDebugCode; CONST_VTBL struct ICorDebugCodeVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugCode_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCode_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCode_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCode_IsIL(This,pbIL) \ - ( (This)->lpVtbl -> IsIL(This,pbIL) ) + ( (This)->lpVtbl -> IsIL(This,pbIL) ) #define ICorDebugCode_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugCode_GetAddress(This,pStart) \ - ( (This)->lpVtbl -> GetAddress(This,pStart) ) + ( (This)->lpVtbl -> GetAddress(This,pStart) ) #define ICorDebugCode_GetSize(This,pcBytes) \ - ( (This)->lpVtbl -> GetSize(This,pcBytes) ) + ( (This)->lpVtbl -> GetSize(This,pcBytes) ) #define ICorDebugCode_CreateBreakpoint(This,offset,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,offset,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,offset,ppBreakpoint) ) #define ICorDebugCode_GetCode(This,startOffset,endOffset,cBufferAlloc,buffer,pcBufferSize) \ - ( (This)->lpVtbl -> GetCode(This,startOffset,endOffset,cBufferAlloc,buffer,pcBufferSize) ) + ( (This)->lpVtbl -> GetCode(This,startOffset,endOffset,cBufferAlloc,buffer,pcBufferSize) ) #define ICorDebugCode_GetVersionNumber(This,nVersion) \ - ( (This)->lpVtbl -> GetVersionNumber(This,nVersion) ) + ( (This)->lpVtbl -> GetVersionNumber(This,nVersion) ) #define ICorDebugCode_GetILToNativeMapping(This,cMap,pcMap,map) \ - ( (This)->lpVtbl -> GetILToNativeMapping(This,cMap,pcMap,map) ) + ( (This)->lpVtbl -> GetILToNativeMapping(This,cMap,pcMap,map) ) #define ICorDebugCode_GetEnCRemapSequencePoints(This,cMap,pcMap,offsets) \ - ( (This)->lpVtbl -> GetEnCRemapSequencePoints(This,cMap,pcMap,offsets) ) + ( (This)->lpVtbl -> GetEnCRemapSequencePoints(This,cMap,pcMap,offsets) ) #endif /* COBJMACROS */ @@ -13926,7 +13933,7 @@ EXTERN_C const IID IID_ICorDebugCode; #define __ICorDebugCode2_INTERFACE_DEFINED__ /* interface ICorDebugCode2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ typedef struct _CodeChunkInfo { @@ -13938,55 +13945,55 @@ typedef struct _CodeChunkInfo EXTERN_C const IID IID_ICorDebugCode2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("5F696509-452F-4436-A3FE-4D11FE7E2347") ICorDebugCode2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetCodeChunks( + virtual HRESULT STDMETHODCALLTYPE GetCodeChunks( /* [in] */ ULONG32 cbufSize, /* [out] */ ULONG32 *pcnumChunks, /* [length_is][size_is][out] */ CodeChunkInfo chunks[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCompilerFlags( + + virtual HRESULT STDMETHODCALLTYPE GetCompilerFlags( /* [out] */ DWORD *pdwFlags) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugCode2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCode2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCode2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCode2 * This); - + DECLSPEC_XFGVIRT(ICorDebugCode2, GetCodeChunks) - HRESULT ( STDMETHODCALLTYPE *GetCodeChunks )( + HRESULT ( STDMETHODCALLTYPE *GetCodeChunks )( ICorDebugCode2 * This, /* [in] */ ULONG32 cbufSize, /* [out] */ ULONG32 *pcnumChunks, /* [length_is][size_is][out] */ CodeChunkInfo chunks[ ]); - + DECLSPEC_XFGVIRT(ICorDebugCode2, GetCompilerFlags) - HRESULT ( STDMETHODCALLTYPE *GetCompilerFlags )( + HRESULT ( STDMETHODCALLTYPE *GetCompilerFlags )( ICorDebugCode2 * This, /* [out] */ DWORD *pdwFlags); - + END_INTERFACE } ICorDebugCode2Vtbl; @@ -13995,26 +14002,26 @@ EXTERN_C const IID IID_ICorDebugCode2; CONST_VTBL struct ICorDebugCode2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugCode2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCode2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCode2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCode2_GetCodeChunks(This,cbufSize,pcnumChunks,chunks) \ - ( (This)->lpVtbl -> GetCodeChunks(This,cbufSize,pcnumChunks,chunks) ) + ( (This)->lpVtbl -> GetCodeChunks(This,cbufSize,pcnumChunks,chunks) ) #define ICorDebugCode2_GetCompilerFlags(This,pdwFlags) \ - ( (This)->lpVtbl -> GetCompilerFlags(This,pdwFlags) ) + ( (This)->lpVtbl -> GetCompilerFlags(This,pdwFlags) ) #endif /* COBJMACROS */ @@ -14031,55 +14038,55 @@ EXTERN_C const IID IID_ICorDebugCode2; #define __ICorDebugCode3_INTERFACE_DEFINED__ /* interface ICorDebugCode3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugCode3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("D13D3E88-E1F2-4020-AA1D-3D162DCBE966") ICorDebugCode3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetReturnValueLiveOffset( + virtual HRESULT STDMETHODCALLTYPE GetReturnValueLiveOffset( /* [in] */ ULONG32 ILoffset, /* [in] */ ULONG32 bufferSize, /* [out] */ ULONG32 *pFetched, /* [length_is][size_is][out] */ ULONG32 pOffsets[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugCode3Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCode3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCode3 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCode3 * This); - + DECLSPEC_XFGVIRT(ICorDebugCode3, GetReturnValueLiveOffset) - HRESULT ( STDMETHODCALLTYPE *GetReturnValueLiveOffset )( + HRESULT ( STDMETHODCALLTYPE *GetReturnValueLiveOffset )( ICorDebugCode3 * This, /* [in] */ ULONG32 ILoffset, /* [in] */ ULONG32 bufferSize, /* [out] */ ULONG32 *pFetched, /* [length_is][size_is][out] */ ULONG32 pOffsets[ ]); - + END_INTERFACE } ICorDebugCode3Vtbl; @@ -14088,23 +14095,23 @@ EXTERN_C const IID IID_ICorDebugCode3; CONST_VTBL struct ICorDebugCode3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugCode3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCode3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCode3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCode3_GetReturnValueLiveOffset(This,ILoffset,bufferSize,pFetched,pOffsets) \ - ( (This)->lpVtbl -> GetReturnValueLiveOffset(This,ILoffset,bufferSize,pFetched,pOffsets) ) + ( (This)->lpVtbl -> GetReturnValueLiveOffset(This,ILoffset,bufferSize,pFetched,pOffsets) ) #endif /* COBJMACROS */ @@ -14121,49 +14128,49 @@ EXTERN_C const IID IID_ICorDebugCode3; #define __ICorDebugCode4_INTERFACE_DEFINED__ /* interface ICorDebugCode4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugCode4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("18221fa4-20cb-40fa-b19d-9f91c4fa8c14") ICorDebugCode4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE EnumerateVariableHomes( + virtual HRESULT STDMETHODCALLTYPE EnumerateVariableHomes( /* [out] */ ICorDebugVariableHomeEnum **ppEnum) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugCode4Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCode4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCode4 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCode4 * This); - + DECLSPEC_XFGVIRT(ICorDebugCode4, EnumerateVariableHomes) - HRESULT ( STDMETHODCALLTYPE *EnumerateVariableHomes )( + HRESULT ( STDMETHODCALLTYPE *EnumerateVariableHomes )( ICorDebugCode4 * This, /* [out] */ ICorDebugVariableHomeEnum **ppEnum); - + END_INTERFACE } ICorDebugCode4Vtbl; @@ -14172,23 +14179,23 @@ EXTERN_C const IID IID_ICorDebugCode4; CONST_VTBL struct ICorDebugCode4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugCode4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCode4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCode4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCode4_EnumerateVariableHomes(This,ppEnum) \ - ( (This)->lpVtbl -> EnumerateVariableHomes(This,ppEnum) ) + ( (This)->lpVtbl -> EnumerateVariableHomes(This,ppEnum) ) #endif /* COBJMACROS */ @@ -14205,7 +14212,7 @@ EXTERN_C const IID IID_ICorDebugCode4; #define __ICorDebugILCode_INTERFACE_DEFINED__ /* interface ICorDebugILCode */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ typedef struct _CorDebugEHClause { @@ -14222,47 +14229,47 @@ typedef struct _CorDebugEHClause EXTERN_C const IID IID_ICorDebugILCode; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("598D46C2-C877-42A7-89D2-3D0C7F1C1264") ICorDebugILCode : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetEHClauses( + virtual HRESULT STDMETHODCALLTYPE GetEHClauses( /* [in] */ ULONG32 cClauses, /* [out] */ ULONG32 *pcClauses, /* [length_is][size_is][out] */ CorDebugEHClause clauses[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugILCodeVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILCode * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILCode * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILCode * This); - + DECLSPEC_XFGVIRT(ICorDebugILCode, GetEHClauses) - HRESULT ( STDMETHODCALLTYPE *GetEHClauses )( + HRESULT ( STDMETHODCALLTYPE *GetEHClauses )( ICorDebugILCode * This, /* [in] */ ULONG32 cClauses, /* [out] */ ULONG32 *pcClauses, /* [length_is][size_is][out] */ CorDebugEHClause clauses[ ]); - + END_INTERFACE } ICorDebugILCodeVtbl; @@ -14271,23 +14278,23 @@ EXTERN_C const IID IID_ICorDebugILCode; CONST_VTBL struct ICorDebugILCodeVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugILCode_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILCode_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILCode_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILCode_GetEHClauses(This,cClauses,pcClauses,clauses) \ - ( (This)->lpVtbl -> GetEHClauses(This,cClauses,pcClauses,clauses) ) + ( (This)->lpVtbl -> GetEHClauses(This,cClauses,pcClauses,clauses) ) #endif /* COBJMACROS */ @@ -14304,61 +14311,61 @@ EXTERN_C const IID IID_ICorDebugILCode; #define __ICorDebugILCode2_INTERFACE_DEFINED__ /* interface ICorDebugILCode2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugILCode2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("46586093-D3F5-4DB6-ACDB-955BCE228C15") ICorDebugILCode2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetLocalVarSigToken( + virtual HRESULT STDMETHODCALLTYPE GetLocalVarSigToken( /* [out] */ mdSignature *pmdSig) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetInstrumentedILMap( + + virtual HRESULT STDMETHODCALLTYPE GetInstrumentedILMap( /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_IL_MAP map[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugILCode2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILCode2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILCode2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILCode2 * This); - + DECLSPEC_XFGVIRT(ICorDebugILCode2, GetLocalVarSigToken) - HRESULT ( STDMETHODCALLTYPE *GetLocalVarSigToken )( + HRESULT ( STDMETHODCALLTYPE *GetLocalVarSigToken )( ICorDebugILCode2 * This, /* [out] */ mdSignature *pmdSig); - + DECLSPEC_XFGVIRT(ICorDebugILCode2, GetInstrumentedILMap) - HRESULT ( STDMETHODCALLTYPE *GetInstrumentedILMap )( + HRESULT ( STDMETHODCALLTYPE *GetInstrumentedILMap )( ICorDebugILCode2 * This, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_IL_MAP map[ ]); - + END_INTERFACE } ICorDebugILCode2Vtbl; @@ -14367,26 +14374,26 @@ EXTERN_C const IID IID_ICorDebugILCode2; CONST_VTBL struct ICorDebugILCode2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugILCode2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILCode2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILCode2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILCode2_GetLocalVarSigToken(This,pmdSig) \ - ( (This)->lpVtbl -> GetLocalVarSigToken(This,pmdSig) ) + ( (This)->lpVtbl -> GetLocalVarSigToken(This,pmdSig) ) #define ICorDebugILCode2_GetInstrumentedILMap(This,cMap,pcMap,map) \ - ( (This)->lpVtbl -> GetInstrumentedILMap(This,cMap,pcMap,map) ) + ( (This)->lpVtbl -> GetInstrumentedILMap(This,cMap,pcMap,map) ) #endif /* COBJMACROS */ @@ -14403,69 +14410,69 @@ EXTERN_C const IID IID_ICorDebugILCode2; #define __ICorDebugClass_INTERFACE_DEFINED__ /* interface ICorDebugClass */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugClass; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAF5-8A68-11d2-983C-0000F808342D") ICorDebugClass : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetModule( + virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **pModule) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetToken( + + virtual HRESULT STDMETHODCALLTYPE GetToken( /* [out] */ mdTypeDef *pTypeDef) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStaticFieldValue( + + virtual HRESULT STDMETHODCALLTYPE GetStaticFieldValue( /* [in] */ mdFieldDef fieldDef, /* [in] */ ICorDebugFrame *pFrame, /* [out] */ ICorDebugValue **ppValue) = 0; - + }; - - -#else /* C style interface */ + + +#else /* C style interface */ typedef struct ICorDebugClassVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugClass * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugClass * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugClass * This); - + DECLSPEC_XFGVIRT(ICorDebugClass, GetModule) - HRESULT ( STDMETHODCALLTYPE *GetModule )( + HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugClass * This, /* [out] */ ICorDebugModule **pModule); - + DECLSPEC_XFGVIRT(ICorDebugClass, GetToken) - HRESULT ( STDMETHODCALLTYPE *GetToken )( + HRESULT ( STDMETHODCALLTYPE *GetToken )( ICorDebugClass * This, /* [out] */ mdTypeDef *pTypeDef); - + DECLSPEC_XFGVIRT(ICorDebugClass, GetStaticFieldValue) - HRESULT ( STDMETHODCALLTYPE *GetStaticFieldValue )( + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldValue )( ICorDebugClass * This, /* [in] */ mdFieldDef fieldDef, /* [in] */ ICorDebugFrame *pFrame, /* [out] */ ICorDebugValue **ppValue); - + END_INTERFACE } ICorDebugClassVtbl; @@ -14474,29 +14481,29 @@ EXTERN_C const IID IID_ICorDebugClass; CONST_VTBL struct ICorDebugClassVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugClass_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugClass_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugClass_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugClass_GetModule(This,pModule) \ - ( (This)->lpVtbl -> GetModule(This,pModule) ) + ( (This)->lpVtbl -> GetModule(This,pModule) ) #define ICorDebugClass_GetToken(This,pTypeDef) \ - ( (This)->lpVtbl -> GetToken(This,pTypeDef) ) + ( (This)->lpVtbl -> GetToken(This,pTypeDef) ) #define ICorDebugClass_GetStaticFieldValue(This,fieldDef,pFrame,ppValue) \ - ( (This)->lpVtbl -> GetStaticFieldValue(This,fieldDef,pFrame,ppValue) ) + ( (This)->lpVtbl -> GetStaticFieldValue(This,fieldDef,pFrame,ppValue) ) #endif /* COBJMACROS */ @@ -14513,63 +14520,63 @@ EXTERN_C const IID IID_ICorDebugClass; #define __ICorDebugClass2_INTERFACE_DEFINED__ /* interface ICorDebugClass2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugClass2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("B008EA8D-7AB1-43f7-BB20-FBB5A04038AE") ICorDebugClass2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetParameterizedType( + virtual HRESULT STDMETHODCALLTYPE GetParameterizedType( /* [in] */ CorElementType elementType, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [out] */ ICorDebugType **ppType) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( + + virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( /* [in] */ BOOL bIsJustMyCode) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugClass2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugClass2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugClass2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugClass2 * This); - + DECLSPEC_XFGVIRT(ICorDebugClass2, GetParameterizedType) - HRESULT ( STDMETHODCALLTYPE *GetParameterizedType )( + HRESULT ( STDMETHODCALLTYPE *GetParameterizedType )( ICorDebugClass2 * This, /* [in] */ CorElementType elementType, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [out] */ ICorDebugType **ppType); - + DECLSPEC_XFGVIRT(ICorDebugClass2, SetJMCStatus) - HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( + HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( ICorDebugClass2 * This, /* [in] */ BOOL bIsJustMyCode); - + END_INTERFACE } ICorDebugClass2Vtbl; @@ -14578,26 +14585,26 @@ EXTERN_C const IID IID_ICorDebugClass2; CONST_VTBL struct ICorDebugClass2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugClass2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugClass2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugClass2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugClass2_GetParameterizedType(This,elementType,nTypeArgs,ppTypeArgs,ppType) \ - ( (This)->lpVtbl -> GetParameterizedType(This,elementType,nTypeArgs,ppTypeArgs,ppType) ) + ( (This)->lpVtbl -> GetParameterizedType(This,elementType,nTypeArgs,ppTypeArgs,ppType) ) #define ICorDebugClass2_SetJMCStatus(This,bIsJustMyCode) \ - ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode) ) + ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode) ) #endif /* COBJMACROS */ @@ -14614,139 +14621,139 @@ EXTERN_C const IID IID_ICorDebugClass2; #define __ICorDebugEval_INTERFACE_DEFINED__ /* interface ICorDebugEval */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEval; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAF6-8A68-11d2-983C-0000F808342D") ICorDebugEval : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CallFunction( + virtual HRESULT STDMETHODCALLTYPE CallFunction( /* [in] */ ICorDebugFunction *pFunction, /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewObject( + + virtual HRESULT STDMETHODCALLTYPE NewObject( /* [in] */ ICorDebugFunction *pConstructor, /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewObjectNoConstructor( + + virtual HRESULT STDMETHODCALLTYPE NewObjectNoConstructor( /* [in] */ ICorDebugClass *pClass) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewString( + + virtual HRESULT STDMETHODCALLTYPE NewString( /* [in] */ LPCWSTR string) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewArray( + + virtual HRESULT STDMETHODCALLTYPE NewArray( /* [in] */ CorElementType elementType, /* [in] */ ICorDebugClass *pElementClass, /* [in] */ ULONG32 rank, /* [size_is][in] */ ULONG32 dims[ ], /* [size_is][in] */ ULONG32 lowBounds[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsActive( + + virtual HRESULT STDMETHODCALLTYPE IsActive( /* [out] */ BOOL *pbActive) = 0; - + virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetResult( + + virtual HRESULT STDMETHODCALLTYPE GetResult( /* [out] */ ICorDebugValue **ppResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetThread( + + virtual HRESULT STDMETHODCALLTYPE GetThread( /* [out] */ ICorDebugThread **ppThread) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateValue( + + virtual HRESULT STDMETHODCALLTYPE CreateValue( /* [in] */ CorElementType elementType, /* [in] */ ICorDebugClass *pElementClass, /* [out] */ ICorDebugValue **ppValue) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugEvalVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEval * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEval * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEval * This); - + DECLSPEC_XFGVIRT(ICorDebugEval, CallFunction) - HRESULT ( STDMETHODCALLTYPE *CallFunction )( + HRESULT ( STDMETHODCALLTYPE *CallFunction )( ICorDebugEval * This, /* [in] */ ICorDebugFunction *pFunction, /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); - + DECLSPEC_XFGVIRT(ICorDebugEval, NewObject) - HRESULT ( STDMETHODCALLTYPE *NewObject )( + HRESULT ( STDMETHODCALLTYPE *NewObject )( ICorDebugEval * This, /* [in] */ ICorDebugFunction *pConstructor, /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); - + DECLSPEC_XFGVIRT(ICorDebugEval, NewObjectNoConstructor) - HRESULT ( STDMETHODCALLTYPE *NewObjectNoConstructor )( + HRESULT ( STDMETHODCALLTYPE *NewObjectNoConstructor )( ICorDebugEval * This, /* [in] */ ICorDebugClass *pClass); - + DECLSPEC_XFGVIRT(ICorDebugEval, NewString) - HRESULT ( STDMETHODCALLTYPE *NewString )( + HRESULT ( STDMETHODCALLTYPE *NewString )( ICorDebugEval * This, /* [in] */ LPCWSTR string); - + DECLSPEC_XFGVIRT(ICorDebugEval, NewArray) - HRESULT ( STDMETHODCALLTYPE *NewArray )( + HRESULT ( STDMETHODCALLTYPE *NewArray )( ICorDebugEval * This, /* [in] */ CorElementType elementType, /* [in] */ ICorDebugClass *pElementClass, /* [in] */ ULONG32 rank, /* [size_is][in] */ ULONG32 dims[ ], /* [size_is][in] */ ULONG32 lowBounds[ ]); - + DECLSPEC_XFGVIRT(ICorDebugEval, IsActive) - HRESULT ( STDMETHODCALLTYPE *IsActive )( + HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugEval * This, /* [out] */ BOOL *pbActive); - + DECLSPEC_XFGVIRT(ICorDebugEval, Abort) - HRESULT ( STDMETHODCALLTYPE *Abort )( + HRESULT ( STDMETHODCALLTYPE *Abort )( ICorDebugEval * This); - + DECLSPEC_XFGVIRT(ICorDebugEval, GetResult) - HRESULT ( STDMETHODCALLTYPE *GetResult )( + HRESULT ( STDMETHODCALLTYPE *GetResult )( ICorDebugEval * This, /* [out] */ ICorDebugValue **ppResult); - + DECLSPEC_XFGVIRT(ICorDebugEval, GetThread) - HRESULT ( STDMETHODCALLTYPE *GetThread )( + HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugEval * This, /* [out] */ ICorDebugThread **ppThread); - + DECLSPEC_XFGVIRT(ICorDebugEval, CreateValue) - HRESULT ( STDMETHODCALLTYPE *CreateValue )( + HRESULT ( STDMETHODCALLTYPE *CreateValue )( ICorDebugEval * This, /* [in] */ CorElementType elementType, /* [in] */ ICorDebugClass *pElementClass, /* [out] */ ICorDebugValue **ppValue); - + END_INTERFACE } ICorDebugEvalVtbl; @@ -14755,50 +14762,50 @@ EXTERN_C const IID IID_ICorDebugEval; CONST_VTBL struct ICorDebugEvalVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugEval_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEval_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEval_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEval_CallFunction(This,pFunction,nArgs,ppArgs) \ - ( (This)->lpVtbl -> CallFunction(This,pFunction,nArgs,ppArgs) ) + ( (This)->lpVtbl -> CallFunction(This,pFunction,nArgs,ppArgs) ) #define ICorDebugEval_NewObject(This,pConstructor,nArgs,ppArgs) \ - ( (This)->lpVtbl -> NewObject(This,pConstructor,nArgs,ppArgs) ) + ( (This)->lpVtbl -> NewObject(This,pConstructor,nArgs,ppArgs) ) #define ICorDebugEval_NewObjectNoConstructor(This,pClass) \ - ( (This)->lpVtbl -> NewObjectNoConstructor(This,pClass) ) + ( (This)->lpVtbl -> NewObjectNoConstructor(This,pClass) ) #define ICorDebugEval_NewString(This,string) \ - ( (This)->lpVtbl -> NewString(This,string) ) + ( (This)->lpVtbl -> NewString(This,string) ) #define ICorDebugEval_NewArray(This,elementType,pElementClass,rank,dims,lowBounds) \ - ( (This)->lpVtbl -> NewArray(This,elementType,pElementClass,rank,dims,lowBounds) ) + ( (This)->lpVtbl -> NewArray(This,elementType,pElementClass,rank,dims,lowBounds) ) #define ICorDebugEval_IsActive(This,pbActive) \ - ( (This)->lpVtbl -> IsActive(This,pbActive) ) + ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugEval_Abort(This) \ - ( (This)->lpVtbl -> Abort(This) ) + ( (This)->lpVtbl -> Abort(This) ) #define ICorDebugEval_GetResult(This,ppResult) \ - ( (This)->lpVtbl -> GetResult(This,ppResult) ) + ( (This)->lpVtbl -> GetResult(This,ppResult) ) #define ICorDebugEval_GetThread(This,ppThread) \ - ( (This)->lpVtbl -> GetThread(This,ppThread) ) + ( (This)->lpVtbl -> GetThread(This,ppThread) ) #define ICorDebugEval_CreateValue(This,elementType,pElementClass,ppValue) \ - ( (This)->lpVtbl -> CreateValue(This,elementType,pElementClass,ppValue) ) + ( (This)->lpVtbl -> CreateValue(This,elementType,pElementClass,ppValue) ) #endif /* COBJMACROS */ @@ -14815,125 +14822,125 @@ EXTERN_C const IID IID_ICorDebugEval; #define __ICorDebugEval2_INTERFACE_DEFINED__ /* interface ICorDebugEval2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEval2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("FB0D9CE7-BE66-4683-9D32-A42A04E2FD91") ICorDebugEval2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CallParameterizedFunction( + virtual HRESULT STDMETHODCALLTYPE CallParameterizedFunction( /* [in] */ ICorDebugFunction *pFunction, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateValueForType( + + virtual HRESULT STDMETHODCALLTYPE CreateValueForType( /* [in] */ ICorDebugType *pType, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewParameterizedObject( + + virtual HRESULT STDMETHODCALLTYPE NewParameterizedObject( /* [in] */ ICorDebugFunction *pConstructor, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewParameterizedObjectNoConstructor( + + virtual HRESULT STDMETHODCALLTYPE NewParameterizedObjectNoConstructor( /* [in] */ ICorDebugClass *pClass, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewParameterizedArray( + + virtual HRESULT STDMETHODCALLTYPE NewParameterizedArray( /* [in] */ ICorDebugType *pElementType, /* [in] */ ULONG32 rank, /* [size_is][in] */ ULONG32 dims[ ], /* [size_is][in] */ ULONG32 lowBounds[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewStringWithLength( + + virtual HRESULT STDMETHODCALLTYPE NewStringWithLength( /* [in] */ LPCWSTR string, /* [in] */ UINT uiLength) = 0; - + virtual HRESULT STDMETHODCALLTYPE RudeAbort( void) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugEval2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEval2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEval2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEval2 * This); - + DECLSPEC_XFGVIRT(ICorDebugEval2, CallParameterizedFunction) - HRESULT ( STDMETHODCALLTYPE *CallParameterizedFunction )( + HRESULT ( STDMETHODCALLTYPE *CallParameterizedFunction )( ICorDebugEval2 * This, /* [in] */ ICorDebugFunction *pFunction, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); - + DECLSPEC_XFGVIRT(ICorDebugEval2, CreateValueForType) - HRESULT ( STDMETHODCALLTYPE *CreateValueForType )( + HRESULT ( STDMETHODCALLTYPE *CreateValueForType )( ICorDebugEval2 * This, /* [in] */ ICorDebugType *pType, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugEval2, NewParameterizedObject) - HRESULT ( STDMETHODCALLTYPE *NewParameterizedObject )( + HRESULT ( STDMETHODCALLTYPE *NewParameterizedObject )( ICorDebugEval2 * This, /* [in] */ ICorDebugFunction *pConstructor, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); - + DECLSPEC_XFGVIRT(ICorDebugEval2, NewParameterizedObjectNoConstructor) - HRESULT ( STDMETHODCALLTYPE *NewParameterizedObjectNoConstructor )( + HRESULT ( STDMETHODCALLTYPE *NewParameterizedObjectNoConstructor )( ICorDebugEval2 * This, /* [in] */ ICorDebugClass *pClass, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ]); - + DECLSPEC_XFGVIRT(ICorDebugEval2, NewParameterizedArray) - HRESULT ( STDMETHODCALLTYPE *NewParameterizedArray )( + HRESULT ( STDMETHODCALLTYPE *NewParameterizedArray )( ICorDebugEval2 * This, /* [in] */ ICorDebugType *pElementType, /* [in] */ ULONG32 rank, /* [size_is][in] */ ULONG32 dims[ ], /* [size_is][in] */ ULONG32 lowBounds[ ]); - + DECLSPEC_XFGVIRT(ICorDebugEval2, NewStringWithLength) - HRESULT ( STDMETHODCALLTYPE *NewStringWithLength )( + HRESULT ( STDMETHODCALLTYPE *NewStringWithLength )( ICorDebugEval2 * This, /* [in] */ LPCWSTR string, /* [in] */ UINT uiLength); - + DECLSPEC_XFGVIRT(ICorDebugEval2, RudeAbort) - HRESULT ( STDMETHODCALLTYPE *RudeAbort )( + HRESULT ( STDMETHODCALLTYPE *RudeAbort )( ICorDebugEval2 * This); - + END_INTERFACE } ICorDebugEval2Vtbl; @@ -14942,41 +14949,41 @@ EXTERN_C const IID IID_ICorDebugEval2; CONST_VTBL struct ICorDebugEval2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugEval2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEval2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEval2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEval2_CallParameterizedFunction(This,pFunction,nTypeArgs,ppTypeArgs,nArgs,ppArgs) \ - ( (This)->lpVtbl -> CallParameterizedFunction(This,pFunction,nTypeArgs,ppTypeArgs,nArgs,ppArgs) ) + ( (This)->lpVtbl -> CallParameterizedFunction(This,pFunction,nTypeArgs,ppTypeArgs,nArgs,ppArgs) ) #define ICorDebugEval2_CreateValueForType(This,pType,ppValue) \ - ( (This)->lpVtbl -> CreateValueForType(This,pType,ppValue) ) + ( (This)->lpVtbl -> CreateValueForType(This,pType,ppValue) ) #define ICorDebugEval2_NewParameterizedObject(This,pConstructor,nTypeArgs,ppTypeArgs,nArgs,ppArgs) \ - ( (This)->lpVtbl -> NewParameterizedObject(This,pConstructor,nTypeArgs,ppTypeArgs,nArgs,ppArgs) ) + ( (This)->lpVtbl -> NewParameterizedObject(This,pConstructor,nTypeArgs,ppTypeArgs,nArgs,ppArgs) ) #define ICorDebugEval2_NewParameterizedObjectNoConstructor(This,pClass,nTypeArgs,ppTypeArgs) \ - ( (This)->lpVtbl -> NewParameterizedObjectNoConstructor(This,pClass,nTypeArgs,ppTypeArgs) ) + ( (This)->lpVtbl -> NewParameterizedObjectNoConstructor(This,pClass,nTypeArgs,ppTypeArgs) ) #define ICorDebugEval2_NewParameterizedArray(This,pElementType,rank,dims,lowBounds) \ - ( (This)->lpVtbl -> NewParameterizedArray(This,pElementType,rank,dims,lowBounds) ) + ( (This)->lpVtbl -> NewParameterizedArray(This,pElementType,rank,dims,lowBounds) ) #define ICorDebugEval2_NewStringWithLength(This,string,uiLength) \ - ( (This)->lpVtbl -> NewStringWithLength(This,string,uiLength) ) + ( (This)->lpVtbl -> NewStringWithLength(This,string,uiLength) ) #define ICorDebugEval2_RudeAbort(This) \ - ( (This)->lpVtbl -> RudeAbort(This) ) + ( (This)->lpVtbl -> RudeAbort(This) ) #endif /* COBJMACROS */ @@ -14993,73 +15000,73 @@ EXTERN_C const IID IID_ICorDebugEval2; #define __ICorDebugValue_INTERFACE_DEFINED__ /* interface ICorDebugValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAF7-8A68-11d2-983C-0000F808342D") ICorDebugValue : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetType( + virtual HRESULT STDMETHODCALLTYPE GetType( /* [out] */ CorElementType *pType) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAddress( + + virtual HRESULT STDMETHODCALLTYPE GetAddress( /* [out] */ CORDB_ADDRESS *pAddress) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugValueVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValue * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValue * This); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetType) - HRESULT ( STDMETHODCALLTYPE *GetType )( + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugValue * This, /* [out] */ CorElementType *pType); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugValue * This, /* [out] */ ULONG32 *pSize); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetAddress) - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - + DECLSPEC_XFGVIRT(ICorDebugValue, CreateBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + END_INTERFACE } ICorDebugValueVtbl; @@ -15068,32 +15075,32 @@ EXTERN_C const IID IID_ICorDebugValue; CONST_VTBL struct ICorDebugValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #endif /* COBJMACROS */ @@ -15110,49 +15117,49 @@ EXTERN_C const IID IID_ICorDebugValue; #define __ICorDebugValue2_INTERFACE_DEFINED__ /* interface ICorDebugValue2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValue2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("5E0B54E7-D88A-4626-9420-A691E0A78B49") ICorDebugValue2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetExactType( + virtual HRESULT STDMETHODCALLTYPE GetExactType( /* [out] */ ICorDebugType **ppType) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugValue2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValue2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValue2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValue2 * This); - + DECLSPEC_XFGVIRT(ICorDebugValue2, GetExactType) - HRESULT ( STDMETHODCALLTYPE *GetExactType )( + HRESULT ( STDMETHODCALLTYPE *GetExactType )( ICorDebugValue2 * This, /* [out] */ ICorDebugType **ppType); - + END_INTERFACE } ICorDebugValue2Vtbl; @@ -15161,23 +15168,23 @@ EXTERN_C const IID IID_ICorDebugValue2; CONST_VTBL struct ICorDebugValue2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugValue2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValue2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValue2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValue2_GetExactType(This,ppType) \ - ( (This)->lpVtbl -> GetExactType(This,ppType) ) + ( (This)->lpVtbl -> GetExactType(This,ppType) ) #endif /* COBJMACROS */ @@ -15194,49 +15201,49 @@ EXTERN_C const IID IID_ICorDebugValue2; #define __ICorDebugValue3_INTERFACE_DEFINED__ /* interface ICorDebugValue3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValue3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("565005FC-0F8A-4F3E-9EDB-83102B156595") ICorDebugValue3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetSize64( + virtual HRESULT STDMETHODCALLTYPE GetSize64( /* [out] */ ULONG64 *pSize) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugValue3Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValue3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValue3 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValue3 * This); - + DECLSPEC_XFGVIRT(ICorDebugValue3, GetSize64) - HRESULT ( STDMETHODCALLTYPE *GetSize64 )( + HRESULT ( STDMETHODCALLTYPE *GetSize64 )( ICorDebugValue3 * This, /* [out] */ ULONG64 *pSize); - + END_INTERFACE } ICorDebugValue3Vtbl; @@ -15245,23 +15252,23 @@ EXTERN_C const IID IID_ICorDebugValue3; CONST_VTBL struct ICorDebugValue3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugValue3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValue3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValue3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValue3_GetSize64(This,pSize) \ - ( (This)->lpVtbl -> GetSize64(This,pSize) ) + ( (This)->lpVtbl -> GetSize64(This,pSize) ) #endif /* COBJMACROS */ @@ -15278,77 +15285,77 @@ EXTERN_C const IID IID_ICorDebugValue3; #define __ICorDebugGenericValue_INTERFACE_DEFINED__ /* interface ICorDebugGenericValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugGenericValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAF8-8A68-11d2-983C-0000F808342D") ICorDebugGenericValue : public ICorDebugValue { public: - virtual HRESULT STDMETHODCALLTYPE GetValue( + virtual HRESULT STDMETHODCALLTYPE GetValue( /* [out] */ void *pTo) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetValue( + + virtual HRESULT STDMETHODCALLTYPE SetValue( /* [in] */ void *pFrom) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugGenericValueVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugGenericValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugGenericValue * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugGenericValue * This); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetType) - HRESULT ( STDMETHODCALLTYPE *GetType )( + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugGenericValue * This, /* [out] */ CorElementType *pType); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugGenericValue * This, /* [out] */ ULONG32 *pSize); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetAddress) - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugGenericValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - + DECLSPEC_XFGVIRT(ICorDebugValue, CreateBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugGenericValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugGenericValue, GetValue) - HRESULT ( STDMETHODCALLTYPE *GetValue )( + HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugGenericValue * This, /* [out] */ void *pTo); - + DECLSPEC_XFGVIRT(ICorDebugGenericValue, SetValue) - HRESULT ( STDMETHODCALLTYPE *SetValue )( + HRESULT ( STDMETHODCALLTYPE *SetValue )( ICorDebugGenericValue * This, /* [in] */ void *pFrom); - + END_INTERFACE } ICorDebugGenericValueVtbl; @@ -15357,39 +15364,39 @@ EXTERN_C const IID IID_ICorDebugGenericValue; CONST_VTBL struct ICorDebugGenericValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugGenericValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugGenericValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugGenericValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugGenericValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugGenericValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugGenericValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugGenericValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugGenericValue_GetValue(This,pTo) \ - ( (This)->lpVtbl -> GetValue(This,pTo) ) + ( (This)->lpVtbl -> GetValue(This,pTo) ) #define ICorDebugGenericValue_SetValue(This,pFrom) \ - ( (This)->lpVtbl -> SetValue(This,pFrom) ) + ( (This)->lpVtbl -> SetValue(This,pFrom) ) #endif /* COBJMACROS */ @@ -15406,101 +15413,101 @@ EXTERN_C const IID IID_ICorDebugGenericValue; #define __ICorDebugReferenceValue_INTERFACE_DEFINED__ /* interface ICorDebugReferenceValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugReferenceValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAF9-8A68-11d2-983C-0000F808342D") ICorDebugReferenceValue : public ICorDebugValue { public: - virtual HRESULT STDMETHODCALLTYPE IsNull( + virtual HRESULT STDMETHODCALLTYPE IsNull( /* [out] */ BOOL *pbNull) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetValue( + + virtual HRESULT STDMETHODCALLTYPE GetValue( /* [out] */ CORDB_ADDRESS *pValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetValue( + + virtual HRESULT STDMETHODCALLTYPE SetValue( /* [in] */ CORDB_ADDRESS value) = 0; - - virtual HRESULT STDMETHODCALLTYPE Dereference( + + virtual HRESULT STDMETHODCALLTYPE Dereference( /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE DereferenceStrong( + + virtual HRESULT STDMETHODCALLTYPE DereferenceStrong( /* [out] */ ICorDebugValue **ppValue) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugReferenceValueVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugReferenceValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugReferenceValue * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugReferenceValue * This); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetType) - HRESULT ( STDMETHODCALLTYPE *GetType )( + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugReferenceValue * This, /* [out] */ CorElementType *pType); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugReferenceValue * This, /* [out] */ ULONG32 *pSize); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetAddress) - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugReferenceValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - + DECLSPEC_XFGVIRT(ICorDebugValue, CreateBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugReferenceValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugReferenceValue, IsNull) - HRESULT ( STDMETHODCALLTYPE *IsNull )( + HRESULT ( STDMETHODCALLTYPE *IsNull )( ICorDebugReferenceValue * This, /* [out] */ BOOL *pbNull); - + DECLSPEC_XFGVIRT(ICorDebugReferenceValue, GetValue) - HRESULT ( STDMETHODCALLTYPE *GetValue )( + HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugReferenceValue * This, /* [out] */ CORDB_ADDRESS *pValue); - + DECLSPEC_XFGVIRT(ICorDebugReferenceValue, SetValue) - HRESULT ( STDMETHODCALLTYPE *SetValue )( + HRESULT ( STDMETHODCALLTYPE *SetValue )( ICorDebugReferenceValue * This, /* [in] */ CORDB_ADDRESS value); - + DECLSPEC_XFGVIRT(ICorDebugReferenceValue, Dereference) - HRESULT ( STDMETHODCALLTYPE *Dereference )( + HRESULT ( STDMETHODCALLTYPE *Dereference )( ICorDebugReferenceValue * This, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugReferenceValue, DereferenceStrong) - HRESULT ( STDMETHODCALLTYPE *DereferenceStrong )( + HRESULT ( STDMETHODCALLTYPE *DereferenceStrong )( ICorDebugReferenceValue * This, /* [out] */ ICorDebugValue **ppValue); - + END_INTERFACE } ICorDebugReferenceValueVtbl; @@ -15509,48 +15516,48 @@ EXTERN_C const IID IID_ICorDebugReferenceValue; CONST_VTBL struct ICorDebugReferenceValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugReferenceValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugReferenceValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugReferenceValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugReferenceValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugReferenceValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugReferenceValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugReferenceValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugReferenceValue_IsNull(This,pbNull) \ - ( (This)->lpVtbl -> IsNull(This,pbNull) ) + ( (This)->lpVtbl -> IsNull(This,pbNull) ) #define ICorDebugReferenceValue_GetValue(This,pValue) \ - ( (This)->lpVtbl -> GetValue(This,pValue) ) + ( (This)->lpVtbl -> GetValue(This,pValue) ) #define ICorDebugReferenceValue_SetValue(This,value) \ - ( (This)->lpVtbl -> SetValue(This,value) ) + ( (This)->lpVtbl -> SetValue(This,value) ) #define ICorDebugReferenceValue_Dereference(This,ppValue) \ - ( (This)->lpVtbl -> Dereference(This,ppValue) ) + ( (This)->lpVtbl -> Dereference(This,ppValue) ) #define ICorDebugReferenceValue_DereferenceStrong(This,ppValue) \ - ( (This)->lpVtbl -> DereferenceStrong(This,ppValue) ) + ( (This)->lpVtbl -> DereferenceStrong(This,ppValue) ) #endif /* COBJMACROS */ @@ -15567,77 +15574,77 @@ EXTERN_C const IID IID_ICorDebugReferenceValue; #define __ICorDebugHeapValue_INTERFACE_DEFINED__ /* interface ICorDebugHeapValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAFA-8A68-11d2-983C-0000F808342D") ICorDebugHeapValue : public ICorDebugValue { public: - virtual HRESULT STDMETHODCALLTYPE IsValid( + virtual HRESULT STDMETHODCALLTYPE IsValid( /* [out] */ BOOL *pbValid) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateRelocBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE CreateRelocBreakpoint( /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugHeapValueVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapValue * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapValue * This); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetType) - HRESULT ( STDMETHODCALLTYPE *GetType )( + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugHeapValue * This, /* [out] */ CorElementType *pType); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugHeapValue * This, /* [out] */ ULONG32 *pSize); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetAddress) - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugHeapValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - + DECLSPEC_XFGVIRT(ICorDebugValue, CreateBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugHeapValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugHeapValue, IsValid) - HRESULT ( STDMETHODCALLTYPE *IsValid )( + HRESULT ( STDMETHODCALLTYPE *IsValid )( ICorDebugHeapValue * This, /* [out] */ BOOL *pbValid); - + DECLSPEC_XFGVIRT(ICorDebugHeapValue, CreateRelocBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( ICorDebugHeapValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + END_INTERFACE } ICorDebugHeapValueVtbl; @@ -15646,39 +15653,39 @@ EXTERN_C const IID IID_ICorDebugHeapValue; CONST_VTBL struct ICorDebugHeapValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugHeapValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugHeapValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugHeapValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugHeapValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugHeapValue_IsValid(This,pbValid) \ - ( (This)->lpVtbl -> IsValid(This,pbValid) ) + ( (This)->lpVtbl -> IsValid(This,pbValid) ) #define ICorDebugHeapValue_CreateRelocBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) #endif /* COBJMACROS */ @@ -15695,51 +15702,51 @@ EXTERN_C const IID IID_ICorDebugHeapValue; #define __ICorDebugHeapValue2_INTERFACE_DEFINED__ /* interface ICorDebugHeapValue2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapValue2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("E3AC4D6C-9CB7-43e6-96CC-B21540E5083C") ICorDebugHeapValue2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CreateHandle( + virtual HRESULT STDMETHODCALLTYPE CreateHandle( /* [in] */ CorDebugHandleType type, /* [out] */ ICorDebugHandleValue **ppHandle) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugHeapValue2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapValue2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapValue2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapValue2 * This); - + DECLSPEC_XFGVIRT(ICorDebugHeapValue2, CreateHandle) - HRESULT ( STDMETHODCALLTYPE *CreateHandle )( + HRESULT ( STDMETHODCALLTYPE *CreateHandle )( ICorDebugHeapValue2 * This, /* [in] */ CorDebugHandleType type, /* [out] */ ICorDebugHandleValue **ppHandle); - + END_INTERFACE } ICorDebugHeapValue2Vtbl; @@ -15748,23 +15755,23 @@ EXTERN_C const IID IID_ICorDebugHeapValue2; CONST_VTBL struct ICorDebugHeapValue2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugHeapValue2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapValue2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapValue2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapValue2_CreateHandle(This,type,ppHandle) \ - ( (This)->lpVtbl -> CreateHandle(This,type,ppHandle) ) + ( (This)->lpVtbl -> CreateHandle(This,type,ppHandle) ) #endif /* COBJMACROS */ @@ -15781,59 +15788,59 @@ EXTERN_C const IID IID_ICorDebugHeapValue2; #define __ICorDebugHeapValue3_INTERFACE_DEFINED__ /* interface ICorDebugHeapValue3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapValue3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("A69ACAD8-2374-46e9-9FF8-B1F14120D296") ICorDebugHeapValue3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetThreadOwningMonitorLock( + virtual HRESULT STDMETHODCALLTYPE GetThreadOwningMonitorLock( /* [out] */ ICorDebugThread **ppThread, /* [out] */ DWORD *pAcquisitionCount) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMonitorEventWaitList( + + virtual HRESULT STDMETHODCALLTYPE GetMonitorEventWaitList( /* [out] */ ICorDebugThreadEnum **ppThreadEnum) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugHeapValue3Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapValue3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapValue3 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapValue3 * This); - + DECLSPEC_XFGVIRT(ICorDebugHeapValue3, GetThreadOwningMonitorLock) - HRESULT ( STDMETHODCALLTYPE *GetThreadOwningMonitorLock )( + HRESULT ( STDMETHODCALLTYPE *GetThreadOwningMonitorLock )( ICorDebugHeapValue3 * This, /* [out] */ ICorDebugThread **ppThread, /* [out] */ DWORD *pAcquisitionCount); - + DECLSPEC_XFGVIRT(ICorDebugHeapValue3, GetMonitorEventWaitList) - HRESULT ( STDMETHODCALLTYPE *GetMonitorEventWaitList )( + HRESULT ( STDMETHODCALLTYPE *GetMonitorEventWaitList )( ICorDebugHeapValue3 * This, /* [out] */ ICorDebugThreadEnum **ppThreadEnum); - + END_INTERFACE } ICorDebugHeapValue3Vtbl; @@ -15842,26 +15849,26 @@ EXTERN_C const IID IID_ICorDebugHeapValue3; CONST_VTBL struct ICorDebugHeapValue3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugHeapValue3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapValue3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapValue3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapValue3_GetThreadOwningMonitorLock(This,ppThread,pAcquisitionCount) \ - ( (This)->lpVtbl -> GetThreadOwningMonitorLock(This,ppThread,pAcquisitionCount) ) + ( (This)->lpVtbl -> GetThreadOwningMonitorLock(This,ppThread,pAcquisitionCount) ) #define ICorDebugHeapValue3_GetMonitorEventWaitList(This,ppThreadEnum) \ - ( (This)->lpVtbl -> GetMonitorEventWaitList(This,ppThreadEnum) ) + ( (This)->lpVtbl -> GetMonitorEventWaitList(This,ppThreadEnum) ) #endif /* COBJMACROS */ @@ -15878,49 +15885,49 @@ EXTERN_C const IID IID_ICorDebugHeapValue3; #define __ICorDebugHeapValue4_INTERFACE_DEFINED__ /* interface ICorDebugHeapValue4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapValue4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("B35DD495-A555-463B-9BE9-C55338486BB8") ICorDebugHeapValue4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CreatePinnedHandle( + virtual HRESULT STDMETHODCALLTYPE CreatePinnedHandle( /* [out] */ ICorDebugHandleValue **ppHandle) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugHeapValue4Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapValue4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapValue4 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapValue4 * This); - + DECLSPEC_XFGVIRT(ICorDebugHeapValue4, CreatePinnedHandle) - HRESULT ( STDMETHODCALLTYPE *CreatePinnedHandle )( + HRESULT ( STDMETHODCALLTYPE *CreatePinnedHandle )( ICorDebugHeapValue4 * This, /* [out] */ ICorDebugHandleValue **ppHandle); - + END_INTERFACE } ICorDebugHeapValue4Vtbl; @@ -15929,23 +15936,23 @@ EXTERN_C const IID IID_ICorDebugHeapValue4; CONST_VTBL struct ICorDebugHeapValue4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugHeapValue4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapValue4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapValue4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapValue4_CreatePinnedHandle(This,ppHandle) \ - ( (This)->lpVtbl -> CreatePinnedHandle(This,ppHandle) ) + ( (This)->lpVtbl -> CreatePinnedHandle(This,ppHandle) ) #endif /* COBJMACROS */ @@ -15962,123 +15969,123 @@ EXTERN_C const IID IID_ICorDebugHeapValue4; #define __ICorDebugObjectValue_INTERFACE_DEFINED__ /* interface ICorDebugObjectValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugObjectValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("18AD3D6E-B7D2-11d2-BD04-0000F80849BD") ICorDebugObjectValue : public ICorDebugValue { public: - virtual HRESULT STDMETHODCALLTYPE GetClass( + virtual HRESULT STDMETHODCALLTYPE GetClass( /* [out] */ ICorDebugClass **ppClass) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFieldValue( + + virtual HRESULT STDMETHODCALLTYPE GetFieldValue( /* [in] */ ICorDebugClass *pClass, /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetVirtualMethod( + + virtual HRESULT STDMETHODCALLTYPE GetVirtualMethod( /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetContext( + + virtual HRESULT STDMETHODCALLTYPE GetContext( /* [out] */ ICorDebugContext **ppContext) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsValueClass( + + virtual HRESULT STDMETHODCALLTYPE IsValueClass( /* [out] */ BOOL *pbIsValueClass) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetManagedCopy( + + virtual HRESULT STDMETHODCALLTYPE GetManagedCopy( /* [out] */ IUnknown **ppObject) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetFromManagedCopy( + + virtual HRESULT STDMETHODCALLTYPE SetFromManagedCopy( /* [in] */ IUnknown *pObject) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugObjectValueVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugObjectValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugObjectValue * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugObjectValue * This); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetType) - HRESULT ( STDMETHODCALLTYPE *GetType )( + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugObjectValue * This, /* [out] */ CorElementType *pType); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugObjectValue * This, /* [out] */ ULONG32 *pSize); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetAddress) - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugObjectValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - + DECLSPEC_XFGVIRT(ICorDebugValue, CreateBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugObjectValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue, GetClass) - HRESULT ( STDMETHODCALLTYPE *GetClass )( + HRESULT ( STDMETHODCALLTYPE *GetClass )( ICorDebugObjectValue * This, /* [out] */ ICorDebugClass **ppClass); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue, GetFieldValue) - HRESULT ( STDMETHODCALLTYPE *GetFieldValue )( + HRESULT ( STDMETHODCALLTYPE *GetFieldValue )( ICorDebugObjectValue * This, /* [in] */ ICorDebugClass *pClass, /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue, GetVirtualMethod) - HRESULT ( STDMETHODCALLTYPE *GetVirtualMethod )( + HRESULT ( STDMETHODCALLTYPE *GetVirtualMethod )( ICorDebugObjectValue * This, /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue, GetContext) - HRESULT ( STDMETHODCALLTYPE *GetContext )( + HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugObjectValue * This, /* [out] */ ICorDebugContext **ppContext); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue, IsValueClass) - HRESULT ( STDMETHODCALLTYPE *IsValueClass )( + HRESULT ( STDMETHODCALLTYPE *IsValueClass )( ICorDebugObjectValue * This, /* [out] */ BOOL *pbIsValueClass); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue, GetManagedCopy) - HRESULT ( STDMETHODCALLTYPE *GetManagedCopy )( + HRESULT ( STDMETHODCALLTYPE *GetManagedCopy )( ICorDebugObjectValue * This, /* [out] */ IUnknown **ppObject); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue, SetFromManagedCopy) - HRESULT ( STDMETHODCALLTYPE *SetFromManagedCopy )( + HRESULT ( STDMETHODCALLTYPE *SetFromManagedCopy )( ICorDebugObjectValue * This, /* [in] */ IUnknown *pObject); - + END_INTERFACE } ICorDebugObjectValueVtbl; @@ -16087,54 +16094,54 @@ EXTERN_C const IID IID_ICorDebugObjectValue; CONST_VTBL struct ICorDebugObjectValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugObjectValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugObjectValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugObjectValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugObjectValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugObjectValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugObjectValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugObjectValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugObjectValue_GetClass(This,ppClass) \ - ( (This)->lpVtbl -> GetClass(This,ppClass) ) + ( (This)->lpVtbl -> GetClass(This,ppClass) ) #define ICorDebugObjectValue_GetFieldValue(This,pClass,fieldDef,ppValue) \ - ( (This)->lpVtbl -> GetFieldValue(This,pClass,fieldDef,ppValue) ) + ( (This)->lpVtbl -> GetFieldValue(This,pClass,fieldDef,ppValue) ) #define ICorDebugObjectValue_GetVirtualMethod(This,memberRef,ppFunction) \ - ( (This)->lpVtbl -> GetVirtualMethod(This,memberRef,ppFunction) ) + ( (This)->lpVtbl -> GetVirtualMethod(This,memberRef,ppFunction) ) #define ICorDebugObjectValue_GetContext(This,ppContext) \ - ( (This)->lpVtbl -> GetContext(This,ppContext) ) + ( (This)->lpVtbl -> GetContext(This,ppContext) ) #define ICorDebugObjectValue_IsValueClass(This,pbIsValueClass) \ - ( (This)->lpVtbl -> IsValueClass(This,pbIsValueClass) ) + ( (This)->lpVtbl -> IsValueClass(This,pbIsValueClass) ) #define ICorDebugObjectValue_GetManagedCopy(This,ppObject) \ - ( (This)->lpVtbl -> GetManagedCopy(This,ppObject) ) + ( (This)->lpVtbl -> GetManagedCopy(This,ppObject) ) #define ICorDebugObjectValue_SetFromManagedCopy(This,pObject) \ - ( (This)->lpVtbl -> SetFromManagedCopy(This,pObject) ) + ( (This)->lpVtbl -> SetFromManagedCopy(This,pObject) ) #endif /* COBJMACROS */ @@ -16151,53 +16158,53 @@ EXTERN_C const IID IID_ICorDebugObjectValue; #define __ICorDebugObjectValue2_INTERFACE_DEFINED__ /* interface ICorDebugObjectValue2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugObjectValue2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("49E4A320-4A9B-4eca-B105-229FB7D5009F") ICorDebugObjectValue2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetVirtualMethodAndType( + virtual HRESULT STDMETHODCALLTYPE GetVirtualMethodAndType( /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction, /* [out] */ ICorDebugType **ppType) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugObjectValue2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugObjectValue2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugObjectValue2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugObjectValue2 * This); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue2, GetVirtualMethodAndType) - HRESULT ( STDMETHODCALLTYPE *GetVirtualMethodAndType )( + HRESULT ( STDMETHODCALLTYPE *GetVirtualMethodAndType )( ICorDebugObjectValue2 * This, /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction, /* [out] */ ICorDebugType **ppType); - + END_INTERFACE } ICorDebugObjectValue2Vtbl; @@ -16206,23 +16213,23 @@ EXTERN_C const IID IID_ICorDebugObjectValue2; CONST_VTBL struct ICorDebugObjectValue2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugObjectValue2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugObjectValue2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugObjectValue2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugObjectValue2_GetVirtualMethodAndType(This,memberRef,ppFunction,ppType) \ - ( (This)->lpVtbl -> GetVirtualMethodAndType(This,memberRef,ppFunction,ppType) ) + ( (This)->lpVtbl -> GetVirtualMethodAndType(This,memberRef,ppFunction,ppType) ) #endif /* COBJMACROS */ @@ -16239,57 +16246,57 @@ EXTERN_C const IID IID_ICorDebugObjectValue2; #define __ICorDebugDelegateObjectValue_INTERFACE_DEFINED__ /* interface ICorDebugDelegateObjectValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugDelegateObjectValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("3AF70CC7-6047-47F6-A5C5-090A1A622638") ICorDebugDelegateObjectValue : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetTarget( + virtual HRESULT STDMETHODCALLTYPE GetTarget( /* [out] */ ICorDebugReferenceValue **ppObject) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunction( + + virtual HRESULT STDMETHODCALLTYPE GetFunction( /* [out] */ ICorDebugFunction **ppFunction) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugDelegateObjectValueVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDelegateObjectValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDelegateObjectValue * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDelegateObjectValue * This); - + DECLSPEC_XFGVIRT(ICorDebugDelegateObjectValue, GetTarget) - HRESULT ( STDMETHODCALLTYPE *GetTarget )( + HRESULT ( STDMETHODCALLTYPE *GetTarget )( ICorDebugDelegateObjectValue * This, /* [out] */ ICorDebugReferenceValue **ppObject); - + DECLSPEC_XFGVIRT(ICorDebugDelegateObjectValue, GetFunction) - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugDelegateObjectValue * This, /* [out] */ ICorDebugFunction **ppFunction); - + END_INTERFACE } ICorDebugDelegateObjectValueVtbl; @@ -16298,26 +16305,26 @@ EXTERN_C const IID IID_ICorDebugDelegateObjectValue; CONST_VTBL struct ICorDebugDelegateObjectValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugDelegateObjectValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDelegateObjectValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDelegateObjectValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDelegateObjectValue_GetTarget(This,ppObject) \ - ( (This)->lpVtbl -> GetTarget(This,ppObject) ) + ( (This)->lpVtbl -> GetTarget(This,ppObject) ) #define ICorDebugDelegateObjectValue_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #endif /* COBJMACROS */ @@ -16334,79 +16341,79 @@ EXTERN_C const IID IID_ICorDebugDelegateObjectValue; #define __ICorDebugBoxValue_INTERFACE_DEFINED__ /* interface ICorDebugBoxValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugBoxValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAFC-8A68-11d2-983C-0000F808342D") ICorDebugBoxValue : public ICorDebugHeapValue { public: - virtual HRESULT STDMETHODCALLTYPE GetObject( + virtual HRESULT STDMETHODCALLTYPE GetObject( /* [out] */ ICorDebugObjectValue **ppObject) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugBoxValueVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugBoxValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugBoxValue * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugBoxValue * This); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetType) - HRESULT ( STDMETHODCALLTYPE *GetType )( + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugBoxValue * This, /* [out] */ CorElementType *pType); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugBoxValue * This, /* [out] */ ULONG32 *pSize); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetAddress) - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugBoxValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - + DECLSPEC_XFGVIRT(ICorDebugValue, CreateBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugBoxValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugHeapValue, IsValid) - HRESULT ( STDMETHODCALLTYPE *IsValid )( + HRESULT ( STDMETHODCALLTYPE *IsValid )( ICorDebugBoxValue * This, /* [out] */ BOOL *pbValid); - + DECLSPEC_XFGVIRT(ICorDebugHeapValue, CreateRelocBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( ICorDebugBoxValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugBoxValue, GetObject) - HRESULT ( STDMETHODCALLTYPE *GetObject )( + HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugBoxValue * This, /* [out] */ ICorDebugObjectValue **ppObject); - + END_INTERFACE } ICorDebugBoxValueVtbl; @@ -16415,43 +16422,43 @@ EXTERN_C const IID IID_ICorDebugBoxValue; CONST_VTBL struct ICorDebugBoxValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugBoxValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugBoxValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugBoxValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugBoxValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugBoxValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugBoxValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugBoxValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugBoxValue_IsValid(This,pbValid) \ - ( (This)->lpVtbl -> IsValid(This,pbValid) ) + ( (This)->lpVtbl -> IsValid(This,pbValid) ) #define ICorDebugBoxValue_CreateRelocBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) #define ICorDebugBoxValue_GetObject(This,ppObject) \ - ( (This)->lpVtbl -> GetObject(This,ppObject) ) + ( (This)->lpVtbl -> GetObject(This,ppObject) ) #endif /* COBJMACROS */ @@ -16465,10 +16472,10 @@ EXTERN_C const IID IID_ICorDebugBoxValue; /* interface __MIDL_itf_cordebug_0000_0106 */ -/* [local] */ +/* [local] */ #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0106_v0_0_c_ifspec; @@ -16478,91 +16485,91 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0106_v0_0_s_ifspec; #define __ICorDebugStringValue_INTERFACE_DEFINED__ /* interface ICorDebugStringValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugStringValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAFD-8A68-11d2-983C-0000F808342D") ICorDebugStringValue : public ICorDebugHeapValue { public: - virtual HRESULT STDMETHODCALLTYPE GetLength( + virtual HRESULT STDMETHODCALLTYPE GetLength( /* [out] */ ULONG32 *pcchString) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetString( + + virtual HRESULT STDMETHODCALLTYPE GetString( /* [in] */ ULONG32 cchString, /* [out] */ ULONG32 *pcchString, /* [length_is][size_is][out] */ WCHAR szString[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugStringValueVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStringValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStringValue * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStringValue * This); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetType) - HRESULT ( STDMETHODCALLTYPE *GetType )( + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugStringValue * This, /* [out] */ CorElementType *pType); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugStringValue * This, /* [out] */ ULONG32 *pSize); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetAddress) - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugStringValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - + DECLSPEC_XFGVIRT(ICorDebugValue, CreateBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugStringValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugHeapValue, IsValid) - HRESULT ( STDMETHODCALLTYPE *IsValid )( + HRESULT ( STDMETHODCALLTYPE *IsValid )( ICorDebugStringValue * This, /* [out] */ BOOL *pbValid); - + DECLSPEC_XFGVIRT(ICorDebugHeapValue, CreateRelocBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( ICorDebugStringValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugStringValue, GetLength) - HRESULT ( STDMETHODCALLTYPE *GetLength )( + HRESULT ( STDMETHODCALLTYPE *GetLength )( ICorDebugStringValue * This, /* [out] */ ULONG32 *pcchString); - + DECLSPEC_XFGVIRT(ICorDebugStringValue, GetString) - HRESULT ( STDMETHODCALLTYPE *GetString )( + HRESULT ( STDMETHODCALLTYPE *GetString )( ICorDebugStringValue * This, /* [in] */ ULONG32 cchString, /* [out] */ ULONG32 *pcchString, /* [length_is][size_is][out] */ WCHAR szString[ ]); - + END_INTERFACE } ICorDebugStringValueVtbl; @@ -16571,46 +16578,46 @@ EXTERN_C const IID IID_ICorDebugStringValue; CONST_VTBL struct ICorDebugStringValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugStringValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStringValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStringValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStringValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugStringValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugStringValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugStringValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugStringValue_IsValid(This,pbValid) \ - ( (This)->lpVtbl -> IsValid(This,pbValid) ) + ( (This)->lpVtbl -> IsValid(This,pbValid) ) #define ICorDebugStringValue_CreateRelocBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) #define ICorDebugStringValue_GetLength(This,pcchString) \ - ( (This)->lpVtbl -> GetLength(This,pcchString) ) + ( (This)->lpVtbl -> GetLength(This,pcchString) ) #define ICorDebugStringValue_GetString(This,cchString,pcchString,szString) \ - ( (This)->lpVtbl -> GetString(This,cchString,pcchString,szString) ) + ( (This)->lpVtbl -> GetString(This,cchString,pcchString,szString) ) #endif /* COBJMACROS */ @@ -16624,7 +16631,7 @@ EXTERN_C const IID IID_ICorDebugStringValue; /* interface __MIDL_itf_cordebug_0000_0107 */ -/* [local] */ +/* [local] */ #pragma warning(pop) @@ -16636,145 +16643,145 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0107_v0_0_s_ifspec; #define __ICorDebugArrayValue_INTERFACE_DEFINED__ /* interface ICorDebugArrayValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugArrayValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("0405B0DF-A660-11d2-BD02-0000F80849BD") ICorDebugArrayValue : public ICorDebugHeapValue { public: - virtual HRESULT STDMETHODCALLTYPE GetElementType( + virtual HRESULT STDMETHODCALLTYPE GetElementType( /* [out] */ CorElementType *pType) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRank( + + virtual HRESULT STDMETHODCALLTYPE GetRank( /* [out] */ ULONG32 *pnRank) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCount( + + virtual HRESULT STDMETHODCALLTYPE GetCount( /* [out] */ ULONG32 *pnCount) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDimensions( + + virtual HRESULT STDMETHODCALLTYPE GetDimensions( /* [in] */ ULONG32 cdim, /* [length_is][size_is][out] */ ULONG32 dims[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE HasBaseIndicies( + + virtual HRESULT STDMETHODCALLTYPE HasBaseIndicies( /* [out] */ BOOL *pbHasBaseIndicies) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetBaseIndicies( + + virtual HRESULT STDMETHODCALLTYPE GetBaseIndicies( /* [in] */ ULONG32 cdim, /* [length_is][size_is][out] */ ULONG32 indices[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetElement( + + virtual HRESULT STDMETHODCALLTYPE GetElement( /* [in] */ ULONG32 cdim, /* [length_is][size_is][in] */ ULONG32 indices[ ], /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetElementAtPosition( + + virtual HRESULT STDMETHODCALLTYPE GetElementAtPosition( /* [in] */ ULONG32 nPosition, /* [out] */ ICorDebugValue **ppValue) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugArrayValueVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugArrayValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugArrayValue * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugArrayValue * This); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetType) - HRESULT ( STDMETHODCALLTYPE *GetType )( + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugArrayValue * This, /* [out] */ CorElementType *pType); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugArrayValue * This, /* [out] */ ULONG32 *pSize); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetAddress) - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugArrayValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - + DECLSPEC_XFGVIRT(ICorDebugValue, CreateBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugArrayValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugHeapValue, IsValid) - HRESULT ( STDMETHODCALLTYPE *IsValid )( + HRESULT ( STDMETHODCALLTYPE *IsValid )( ICorDebugArrayValue * This, /* [out] */ BOOL *pbValid); - + DECLSPEC_XFGVIRT(ICorDebugHeapValue, CreateRelocBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( ICorDebugArrayValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugArrayValue, GetElementType) - HRESULT ( STDMETHODCALLTYPE *GetElementType )( + HRESULT ( STDMETHODCALLTYPE *GetElementType )( ICorDebugArrayValue * This, /* [out] */ CorElementType *pType); - + DECLSPEC_XFGVIRT(ICorDebugArrayValue, GetRank) - HRESULT ( STDMETHODCALLTYPE *GetRank )( + HRESULT ( STDMETHODCALLTYPE *GetRank )( ICorDebugArrayValue * This, /* [out] */ ULONG32 *pnRank); - + DECLSPEC_XFGVIRT(ICorDebugArrayValue, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugArrayValue * This, /* [out] */ ULONG32 *pnCount); - + DECLSPEC_XFGVIRT(ICorDebugArrayValue, GetDimensions) - HRESULT ( STDMETHODCALLTYPE *GetDimensions )( + HRESULT ( STDMETHODCALLTYPE *GetDimensions )( ICorDebugArrayValue * This, /* [in] */ ULONG32 cdim, /* [length_is][size_is][out] */ ULONG32 dims[ ]); - + DECLSPEC_XFGVIRT(ICorDebugArrayValue, HasBaseIndicies) - HRESULT ( STDMETHODCALLTYPE *HasBaseIndicies )( + HRESULT ( STDMETHODCALLTYPE *HasBaseIndicies )( ICorDebugArrayValue * This, /* [out] */ BOOL *pbHasBaseIndicies); - + DECLSPEC_XFGVIRT(ICorDebugArrayValue, GetBaseIndicies) - HRESULT ( STDMETHODCALLTYPE *GetBaseIndicies )( + HRESULT ( STDMETHODCALLTYPE *GetBaseIndicies )( ICorDebugArrayValue * This, /* [in] */ ULONG32 cdim, /* [length_is][size_is][out] */ ULONG32 indices[ ]); - + DECLSPEC_XFGVIRT(ICorDebugArrayValue, GetElement) - HRESULT ( STDMETHODCALLTYPE *GetElement )( + HRESULT ( STDMETHODCALLTYPE *GetElement )( ICorDebugArrayValue * This, /* [in] */ ULONG32 cdim, /* [length_is][size_is][in] */ ULONG32 indices[ ], /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugArrayValue, GetElementAtPosition) - HRESULT ( STDMETHODCALLTYPE *GetElementAtPosition )( + HRESULT ( STDMETHODCALLTYPE *GetElementAtPosition )( ICorDebugArrayValue * This, /* [in] */ ULONG32 nPosition, /* [out] */ ICorDebugValue **ppValue); - + END_INTERFACE } ICorDebugArrayValueVtbl; @@ -16783,64 +16790,64 @@ EXTERN_C const IID IID_ICorDebugArrayValue; CONST_VTBL struct ICorDebugArrayValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugArrayValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugArrayValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugArrayValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugArrayValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugArrayValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugArrayValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugArrayValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugArrayValue_IsValid(This,pbValid) \ - ( (This)->lpVtbl -> IsValid(This,pbValid) ) + ( (This)->lpVtbl -> IsValid(This,pbValid) ) #define ICorDebugArrayValue_CreateRelocBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) #define ICorDebugArrayValue_GetElementType(This,pType) \ - ( (This)->lpVtbl -> GetElementType(This,pType) ) + ( (This)->lpVtbl -> GetElementType(This,pType) ) #define ICorDebugArrayValue_GetRank(This,pnRank) \ - ( (This)->lpVtbl -> GetRank(This,pnRank) ) + ( (This)->lpVtbl -> GetRank(This,pnRank) ) #define ICorDebugArrayValue_GetCount(This,pnCount) \ - ( (This)->lpVtbl -> GetCount(This,pnCount) ) + ( (This)->lpVtbl -> GetCount(This,pnCount) ) #define ICorDebugArrayValue_GetDimensions(This,cdim,dims) \ - ( (This)->lpVtbl -> GetDimensions(This,cdim,dims) ) + ( (This)->lpVtbl -> GetDimensions(This,cdim,dims) ) #define ICorDebugArrayValue_HasBaseIndicies(This,pbHasBaseIndicies) \ - ( (This)->lpVtbl -> HasBaseIndicies(This,pbHasBaseIndicies) ) + ( (This)->lpVtbl -> HasBaseIndicies(This,pbHasBaseIndicies) ) #define ICorDebugArrayValue_GetBaseIndicies(This,cdim,indices) \ - ( (This)->lpVtbl -> GetBaseIndicies(This,cdim,indices) ) + ( (This)->lpVtbl -> GetBaseIndicies(This,cdim,indices) ) #define ICorDebugArrayValue_GetElement(This,cdim,indices,ppValue) \ - ( (This)->lpVtbl -> GetElement(This,cdim,indices,ppValue) ) + ( (This)->lpVtbl -> GetElement(This,cdim,indices,ppValue) ) #define ICorDebugArrayValue_GetElementAtPosition(This,nPosition,ppValue) \ - ( (This)->lpVtbl -> GetElementAtPosition(This,nPosition,ppValue) ) + ( (This)->lpVtbl -> GetElementAtPosition(This,nPosition,ppValue) ) #endif /* COBJMACROS */ @@ -16857,107 +16864,107 @@ EXTERN_C const IID IID_ICorDebugArrayValue; #define __ICorDebugVariableHome_INTERFACE_DEFINED__ /* interface ICorDebugVariableHome */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum VariableLocationType { VLT_REGISTER = 0, VLT_REGISTER_RELATIVE = ( VLT_REGISTER + 1 ) , - VLT_INVALID = ( VLT_REGISTER_RELATIVE + 1 ) + VLT_INVALID = ( VLT_REGISTER_RELATIVE + 1 ) } VariableLocationType; EXTERN_C const IID IID_ICorDebugVariableHome; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("50847b8d-f43f-41b0-924c-6383a5f2278b") ICorDebugVariableHome : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetCode( + virtual HRESULT STDMETHODCALLTYPE GetCode( /* [out] */ ICorDebugCode **ppCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSlotIndex( + + virtual HRESULT STDMETHODCALLTYPE GetSlotIndex( /* [out] */ ULONG32 *pSlotIndex) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetArgumentIndex( + + virtual HRESULT STDMETHODCALLTYPE GetArgumentIndex( /* [out] */ ULONG32 *pArgumentIndex) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLiveRange( + + virtual HRESULT STDMETHODCALLTYPE GetLiveRange( /* [out] */ ULONG32 *pStartOffset, /* [out] */ ULONG32 *pEndOffset) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocationType( + + virtual HRESULT STDMETHODCALLTYPE GetLocationType( /* [out] */ VariableLocationType *pLocationType) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRegister( + + virtual HRESULT STDMETHODCALLTYPE GetRegister( /* [out] */ CorDebugRegister *pRegister) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetOffset( + + virtual HRESULT STDMETHODCALLTYPE GetOffset( /* [out] */ LONG *pOffset) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugVariableHomeVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugVariableHome * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugVariableHome * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugVariableHome * This); - + DECLSPEC_XFGVIRT(ICorDebugVariableHome, GetCode) - HRESULT ( STDMETHODCALLTYPE *GetCode )( + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugVariableHome * This, /* [out] */ ICorDebugCode **ppCode); - + DECLSPEC_XFGVIRT(ICorDebugVariableHome, GetSlotIndex) - HRESULT ( STDMETHODCALLTYPE *GetSlotIndex )( + HRESULT ( STDMETHODCALLTYPE *GetSlotIndex )( ICorDebugVariableHome * This, /* [out] */ ULONG32 *pSlotIndex); - + DECLSPEC_XFGVIRT(ICorDebugVariableHome, GetArgumentIndex) - HRESULT ( STDMETHODCALLTYPE *GetArgumentIndex )( + HRESULT ( STDMETHODCALLTYPE *GetArgumentIndex )( ICorDebugVariableHome * This, /* [out] */ ULONG32 *pArgumentIndex); - + DECLSPEC_XFGVIRT(ICorDebugVariableHome, GetLiveRange) - HRESULT ( STDMETHODCALLTYPE *GetLiveRange )( + HRESULT ( STDMETHODCALLTYPE *GetLiveRange )( ICorDebugVariableHome * This, /* [out] */ ULONG32 *pStartOffset, /* [out] */ ULONG32 *pEndOffset); - + DECLSPEC_XFGVIRT(ICorDebugVariableHome, GetLocationType) - HRESULT ( STDMETHODCALLTYPE *GetLocationType )( + HRESULT ( STDMETHODCALLTYPE *GetLocationType )( ICorDebugVariableHome * This, /* [out] */ VariableLocationType *pLocationType); - + DECLSPEC_XFGVIRT(ICorDebugVariableHome, GetRegister) - HRESULT ( STDMETHODCALLTYPE *GetRegister )( + HRESULT ( STDMETHODCALLTYPE *GetRegister )( ICorDebugVariableHome * This, /* [out] */ CorDebugRegister *pRegister); - + DECLSPEC_XFGVIRT(ICorDebugVariableHome, GetOffset) - HRESULT ( STDMETHODCALLTYPE *GetOffset )( + HRESULT ( STDMETHODCALLTYPE *GetOffset )( ICorDebugVariableHome * This, /* [out] */ LONG *pOffset); - + END_INTERFACE } ICorDebugVariableHomeVtbl; @@ -16966,41 +16973,41 @@ EXTERN_C const IID IID_ICorDebugVariableHome; CONST_VTBL struct ICorDebugVariableHomeVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugVariableHome_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugVariableHome_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugVariableHome_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugVariableHome_GetCode(This,ppCode) \ - ( (This)->lpVtbl -> GetCode(This,ppCode) ) + ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugVariableHome_GetSlotIndex(This,pSlotIndex) \ - ( (This)->lpVtbl -> GetSlotIndex(This,pSlotIndex) ) + ( (This)->lpVtbl -> GetSlotIndex(This,pSlotIndex) ) #define ICorDebugVariableHome_GetArgumentIndex(This,pArgumentIndex) \ - ( (This)->lpVtbl -> GetArgumentIndex(This,pArgumentIndex) ) + ( (This)->lpVtbl -> GetArgumentIndex(This,pArgumentIndex) ) #define ICorDebugVariableHome_GetLiveRange(This,pStartOffset,pEndOffset) \ - ( (This)->lpVtbl -> GetLiveRange(This,pStartOffset,pEndOffset) ) + ( (This)->lpVtbl -> GetLiveRange(This,pStartOffset,pEndOffset) ) #define ICorDebugVariableHome_GetLocationType(This,pLocationType) \ - ( (This)->lpVtbl -> GetLocationType(This,pLocationType) ) + ( (This)->lpVtbl -> GetLocationType(This,pLocationType) ) #define ICorDebugVariableHome_GetRegister(This,pRegister) \ - ( (This)->lpVtbl -> GetRegister(This,pRegister) ) + ( (This)->lpVtbl -> GetRegister(This,pRegister) ) #define ICorDebugVariableHome_GetOffset(This,pOffset) \ - ( (This)->lpVtbl -> GetOffset(This,pOffset) ) + ( (This)->lpVtbl -> GetOffset(This,pOffset) ) #endif /* COBJMACROS */ @@ -17017,100 +17024,100 @@ EXTERN_C const IID IID_ICorDebugVariableHome; #define __ICorDebugHandleValue_INTERFACE_DEFINED__ /* interface ICorDebugHandleValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHandleValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("029596E8-276B-46a1-9821-732E96BBB00B") ICorDebugHandleValue : public ICorDebugReferenceValue { public: - virtual HRESULT STDMETHODCALLTYPE GetHandleType( + virtual HRESULT STDMETHODCALLTYPE GetHandleType( /* [out] */ CorDebugHandleType *pType) = 0; - + virtual HRESULT STDMETHODCALLTYPE Dispose( void) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugHandleValueVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHandleValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHandleValue * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHandleValue * This); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetType) - HRESULT ( STDMETHODCALLTYPE *GetType )( + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugHandleValue * This, /* [out] */ CorElementType *pType); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugHandleValue * This, /* [out] */ ULONG32 *pSize); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetAddress) - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugHandleValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - + DECLSPEC_XFGVIRT(ICorDebugValue, CreateBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugHandleValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugReferenceValue, IsNull) - HRESULT ( STDMETHODCALLTYPE *IsNull )( + HRESULT ( STDMETHODCALLTYPE *IsNull )( ICorDebugHandleValue * This, /* [out] */ BOOL *pbNull); - + DECLSPEC_XFGVIRT(ICorDebugReferenceValue, GetValue) - HRESULT ( STDMETHODCALLTYPE *GetValue )( + HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugHandleValue * This, /* [out] */ CORDB_ADDRESS *pValue); - + DECLSPEC_XFGVIRT(ICorDebugReferenceValue, SetValue) - HRESULT ( STDMETHODCALLTYPE *SetValue )( + HRESULT ( STDMETHODCALLTYPE *SetValue )( ICorDebugHandleValue * This, /* [in] */ CORDB_ADDRESS value); - + DECLSPEC_XFGVIRT(ICorDebugReferenceValue, Dereference) - HRESULT ( STDMETHODCALLTYPE *Dereference )( + HRESULT ( STDMETHODCALLTYPE *Dereference )( ICorDebugHandleValue * This, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugReferenceValue, DereferenceStrong) - HRESULT ( STDMETHODCALLTYPE *DereferenceStrong )( + HRESULT ( STDMETHODCALLTYPE *DereferenceStrong )( ICorDebugHandleValue * This, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugHandleValue, GetHandleType) - HRESULT ( STDMETHODCALLTYPE *GetHandleType )( + HRESULT ( STDMETHODCALLTYPE *GetHandleType )( ICorDebugHandleValue * This, /* [out] */ CorDebugHandleType *pType); - + DECLSPEC_XFGVIRT(ICorDebugHandleValue, Dispose) - HRESULT ( STDMETHODCALLTYPE *Dispose )( + HRESULT ( STDMETHODCALLTYPE *Dispose )( ICorDebugHandleValue * This); - + END_INTERFACE } ICorDebugHandleValueVtbl; @@ -17119,55 +17126,55 @@ EXTERN_C const IID IID_ICorDebugHandleValue; CONST_VTBL struct ICorDebugHandleValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugHandleValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHandleValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHandleValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHandleValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugHandleValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugHandleValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugHandleValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugHandleValue_IsNull(This,pbNull) \ - ( (This)->lpVtbl -> IsNull(This,pbNull) ) + ( (This)->lpVtbl -> IsNull(This,pbNull) ) #define ICorDebugHandleValue_GetValue(This,pValue) \ - ( (This)->lpVtbl -> GetValue(This,pValue) ) + ( (This)->lpVtbl -> GetValue(This,pValue) ) #define ICorDebugHandleValue_SetValue(This,value) \ - ( (This)->lpVtbl -> SetValue(This,value) ) + ( (This)->lpVtbl -> SetValue(This,value) ) #define ICorDebugHandleValue_Dereference(This,ppValue) \ - ( (This)->lpVtbl -> Dereference(This,ppValue) ) + ( (This)->lpVtbl -> Dereference(This,ppValue) ) #define ICorDebugHandleValue_DereferenceStrong(This,ppValue) \ - ( (This)->lpVtbl -> DereferenceStrong(This,ppValue) ) + ( (This)->lpVtbl -> DereferenceStrong(This,ppValue) ) #define ICorDebugHandleValue_GetHandleType(This,pType) \ - ( (This)->lpVtbl -> GetHandleType(This,pType) ) + ( (This)->lpVtbl -> GetHandleType(This,pType) ) #define ICorDebugHandleValue_Dispose(This) \ - ( (This)->lpVtbl -> Dispose(This) ) + ( (This)->lpVtbl -> Dispose(This) ) #endif /* COBJMACROS */ @@ -17184,99 +17191,99 @@ EXTERN_C const IID IID_ICorDebugHandleValue; #define __ICorDebugContext_INTERFACE_DEFINED__ /* interface ICorDebugContext */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugContext; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB00-8A68-11d2-983C-0000F808342D") ICorDebugContext : public ICorDebugObjectValue { public: }; - - + + #else /* C style interface */ typedef struct ICorDebugContextVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugContext * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugContext * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugContext * This); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetType) - HRESULT ( STDMETHODCALLTYPE *GetType )( + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugContext * This, /* [out] */ CorElementType *pType); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetSize) - HRESULT ( STDMETHODCALLTYPE *GetSize )( + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugContext * This, /* [out] */ ULONG32 *pSize); - + DECLSPEC_XFGVIRT(ICorDebugValue, GetAddress) - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugContext * This, /* [out] */ CORDB_ADDRESS *pAddress); - + DECLSPEC_XFGVIRT(ICorDebugValue, CreateBreakpoint) - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugContext * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue, GetClass) - HRESULT ( STDMETHODCALLTYPE *GetClass )( + HRESULT ( STDMETHODCALLTYPE *GetClass )( ICorDebugContext * This, /* [out] */ ICorDebugClass **ppClass); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue, GetFieldValue) - HRESULT ( STDMETHODCALLTYPE *GetFieldValue )( + HRESULT ( STDMETHODCALLTYPE *GetFieldValue )( ICorDebugContext * This, /* [in] */ ICorDebugClass *pClass, /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue, GetVirtualMethod) - HRESULT ( STDMETHODCALLTYPE *GetVirtualMethod )( + HRESULT ( STDMETHODCALLTYPE *GetVirtualMethod )( ICorDebugContext * This, /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue, GetContext) - HRESULT ( STDMETHODCALLTYPE *GetContext )( + HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugContext * This, /* [out] */ ICorDebugContext **ppContext); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue, IsValueClass) - HRESULT ( STDMETHODCALLTYPE *IsValueClass )( + HRESULT ( STDMETHODCALLTYPE *IsValueClass )( ICorDebugContext * This, /* [out] */ BOOL *pbIsValueClass); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue, GetManagedCopy) - HRESULT ( STDMETHODCALLTYPE *GetManagedCopy )( + HRESULT ( STDMETHODCALLTYPE *GetManagedCopy )( ICorDebugContext * This, /* [out] */ IUnknown **ppObject); - + DECLSPEC_XFGVIRT(ICorDebugObjectValue, SetFromManagedCopy) - HRESULT ( STDMETHODCALLTYPE *SetFromManagedCopy )( + HRESULT ( STDMETHODCALLTYPE *SetFromManagedCopy )( ICorDebugContext * This, /* [in] */ IUnknown *pObject); - + END_INTERFACE } ICorDebugContextVtbl; @@ -17285,54 +17292,54 @@ EXTERN_C const IID IID_ICorDebugContext; CONST_VTBL struct ICorDebugContextVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugContext_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugContext_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugContext_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugContext_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugContext_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugContext_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugContext_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugContext_GetClass(This,ppClass) \ - ( (This)->lpVtbl -> GetClass(This,ppClass) ) + ( (This)->lpVtbl -> GetClass(This,ppClass) ) #define ICorDebugContext_GetFieldValue(This,pClass,fieldDef,ppValue) \ - ( (This)->lpVtbl -> GetFieldValue(This,pClass,fieldDef,ppValue) ) + ( (This)->lpVtbl -> GetFieldValue(This,pClass,fieldDef,ppValue) ) #define ICorDebugContext_GetVirtualMethod(This,memberRef,ppFunction) \ - ( (This)->lpVtbl -> GetVirtualMethod(This,memberRef,ppFunction) ) + ( (This)->lpVtbl -> GetVirtualMethod(This,memberRef,ppFunction) ) #define ICorDebugContext_GetContext(This,ppContext) \ - ( (This)->lpVtbl -> GetContext(This,ppContext) ) + ( (This)->lpVtbl -> GetContext(This,ppContext) ) #define ICorDebugContext_IsValueClass(This,pbIsValueClass) \ - ( (This)->lpVtbl -> IsValueClass(This,pbIsValueClass) ) + ( (This)->lpVtbl -> IsValueClass(This,pbIsValueClass) ) #define ICorDebugContext_GetManagedCopy(This,ppObject) \ - ( (This)->lpVtbl -> GetManagedCopy(This,ppObject) ) + ( (This)->lpVtbl -> GetManagedCopy(This,ppObject) ) #define ICorDebugContext_SetFromManagedCopy(This,pObject) \ - ( (This)->lpVtbl -> SetFromManagedCopy(This,pObject) ) + ( (This)->lpVtbl -> SetFromManagedCopy(This,pObject) ) #endif /* COBJMACROS */ @@ -17350,65 +17357,65 @@ EXTERN_C const IID IID_ICorDebugContext; #define __ICorDebugComObjectValue_INTERFACE_DEFINED__ /* interface ICorDebugComObjectValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugComObjectValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("5F69C5E5-3E12-42DF-B371-F9D761D6EE24") ICorDebugComObjectValue : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetCachedInterfaceTypes( + virtual HRESULT STDMETHODCALLTYPE GetCachedInterfaceTypes( /* [in] */ BOOL bIInspectableOnly, /* [out] */ ICorDebugTypeEnum **ppInterfacesEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCachedInterfacePointers( + + virtual HRESULT STDMETHODCALLTYPE GetCachedInterfacePointers( /* [in] */ BOOL bIInspectableOnly, /* [in] */ ULONG32 celt, /* [out] */ ULONG32 *pcEltFetched, /* [length_is][size_is][out] */ CORDB_ADDRESS *ptrs) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugComObjectValueVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugComObjectValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugComObjectValue * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugComObjectValue * This); - + DECLSPEC_XFGVIRT(ICorDebugComObjectValue, GetCachedInterfaceTypes) - HRESULT ( STDMETHODCALLTYPE *GetCachedInterfaceTypes )( + HRESULT ( STDMETHODCALLTYPE *GetCachedInterfaceTypes )( ICorDebugComObjectValue * This, /* [in] */ BOOL bIInspectableOnly, /* [out] */ ICorDebugTypeEnum **ppInterfacesEnum); - + DECLSPEC_XFGVIRT(ICorDebugComObjectValue, GetCachedInterfacePointers) - HRESULT ( STDMETHODCALLTYPE *GetCachedInterfacePointers )( + HRESULT ( STDMETHODCALLTYPE *GetCachedInterfacePointers )( ICorDebugComObjectValue * This, /* [in] */ BOOL bIInspectableOnly, /* [in] */ ULONG32 celt, /* [out] */ ULONG32 *pcEltFetched, /* [length_is][size_is][out] */ CORDB_ADDRESS *ptrs); - + END_INTERFACE } ICorDebugComObjectValueVtbl; @@ -17417,26 +17424,26 @@ EXTERN_C const IID IID_ICorDebugComObjectValue; CONST_VTBL struct ICorDebugComObjectValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugComObjectValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugComObjectValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugComObjectValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugComObjectValue_GetCachedInterfaceTypes(This,bIInspectableOnly,ppInterfacesEnum) \ - ( (This)->lpVtbl -> GetCachedInterfaceTypes(This,bIInspectableOnly,ppInterfacesEnum) ) + ( (This)->lpVtbl -> GetCachedInterfaceTypes(This,bIInspectableOnly,ppInterfacesEnum) ) #define ICorDebugComObjectValue_GetCachedInterfacePointers(This,bIInspectableOnly,celt,pcEltFetched,ptrs) \ - ( (This)->lpVtbl -> GetCachedInterfacePointers(This,bIInspectableOnly,celt,pcEltFetched,ptrs) ) + ( (This)->lpVtbl -> GetCachedInterfacePointers(This,bIInspectableOnly,celt,pcEltFetched,ptrs) ) #endif /* COBJMACROS */ @@ -17453,72 +17460,72 @@ EXTERN_C const IID IID_ICorDebugComObjectValue; #define __ICorDebugObjectEnum_INTERFACE_DEFINED__ /* interface ICorDebugObjectEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugObjectEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB02-8A68-11d2-983C-0000F808342D") ICorDebugObjectEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CORDB_ADDRESS objects[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugObjectEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugObjectEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugObjectEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugObjectEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugObjectEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugObjectEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugObjectEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugObjectEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugObjectEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugObjectEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CORDB_ADDRESS objects[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugObjectEnumVtbl; @@ -17527,36 +17534,36 @@ EXTERN_C const IID IID_ICorDebugObjectEnum; CONST_VTBL struct ICorDebugObjectEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugObjectEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugObjectEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugObjectEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugObjectEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugObjectEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugObjectEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugObjectEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugObjectEnum_Next(This,celt,objects,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) #endif /* COBJMACROS */ @@ -17573,72 +17580,72 @@ EXTERN_C const IID IID_ICorDebugObjectEnum; #define __ICorDebugBreakpointEnum_INTERFACE_DEFINED__ /* interface ICorDebugBreakpointEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugBreakpointEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB03-8A68-11d2-983C-0000F808342D") ICorDebugBreakpointEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugBreakpoint *breakpoints[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugBreakpointEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugBreakpointEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugBreakpointEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugBreakpointEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugBreakpointEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugBreakpointEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugBreakpointEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugBreakpointEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugBreakpointEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugBreakpointEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugBreakpoint *breakpoints[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugBreakpointEnumVtbl; @@ -17647,36 +17654,36 @@ EXTERN_C const IID IID_ICorDebugBreakpointEnum; CONST_VTBL struct ICorDebugBreakpointEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugBreakpointEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugBreakpointEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugBreakpointEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugBreakpointEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugBreakpointEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugBreakpointEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugBreakpointEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugBreakpointEnum_Next(This,celt,breakpoints,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,breakpoints,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,breakpoints,pceltFetched) ) #endif /* COBJMACROS */ @@ -17693,72 +17700,72 @@ EXTERN_C const IID IID_ICorDebugBreakpointEnum; #define __ICorDebugStepperEnum_INTERFACE_DEFINED__ /* interface ICorDebugStepperEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugStepperEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB04-8A68-11d2-983C-0000F808342D") ICorDebugStepperEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugStepper *steppers[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugStepperEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStepperEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStepperEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStepperEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugStepperEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugStepperEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugStepperEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugStepperEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugStepperEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugStepperEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugStepper *steppers[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugStepperEnumVtbl; @@ -17767,36 +17774,36 @@ EXTERN_C const IID IID_ICorDebugStepperEnum; CONST_VTBL struct ICorDebugStepperEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugStepperEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStepperEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStepperEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStepperEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugStepperEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugStepperEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugStepperEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugStepperEnum_Next(This,celt,steppers,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,steppers,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,steppers,pceltFetched) ) #endif /* COBJMACROS */ @@ -17813,72 +17820,72 @@ EXTERN_C const IID IID_ICorDebugStepperEnum; #define __ICorDebugProcessEnum_INTERFACE_DEFINED__ /* interface ICorDebugProcessEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcessEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB05-8A68-11d2-983C-0000F808342D") ICorDebugProcessEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugProcess *processes[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcessEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcessEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcessEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcessEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugProcessEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugProcessEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugProcessEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugProcessEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugProcessEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugProcessEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugProcess *processes[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugProcessEnumVtbl; @@ -17887,36 +17894,36 @@ EXTERN_C const IID IID_ICorDebugProcessEnum; CONST_VTBL struct ICorDebugProcessEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcessEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcessEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcessEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcessEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugProcessEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugProcessEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugProcessEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugProcessEnum_Next(This,celt,processes,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,processes,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,processes,pceltFetched) ) #endif /* COBJMACROS */ @@ -17933,72 +17940,72 @@ EXTERN_C const IID IID_ICorDebugProcessEnum; #define __ICorDebugThreadEnum_INTERFACE_DEFINED__ /* interface ICorDebugThreadEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugThreadEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB06-8A68-11d2-983C-0000F808342D") ICorDebugThreadEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugThread *threads[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugThreadEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThreadEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThreadEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThreadEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugThreadEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugThreadEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugThreadEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugThreadEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugThreadEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugThreadEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugThread *threads[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugThreadEnumVtbl; @@ -18007,36 +18014,36 @@ EXTERN_C const IID IID_ICorDebugThreadEnum; CONST_VTBL struct ICorDebugThreadEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugThreadEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThreadEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThreadEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThreadEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugThreadEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugThreadEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugThreadEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugThreadEnum_Next(This,celt,threads,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,threads,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,threads,pceltFetched) ) #endif /* COBJMACROS */ @@ -18053,72 +18060,72 @@ EXTERN_C const IID IID_ICorDebugThreadEnum; #define __ICorDebugFrameEnum_INTERFACE_DEFINED__ /* interface ICorDebugFrameEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFrameEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB07-8A68-11d2-983C-0000F808342D") ICorDebugFrameEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugFrame *frames[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFrameEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFrameEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFrameEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFrameEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugFrameEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugFrameEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugFrameEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugFrameEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugFrameEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugFrameEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugFrame *frames[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugFrameEnumVtbl; @@ -18127,36 +18134,36 @@ EXTERN_C const IID IID_ICorDebugFrameEnum; CONST_VTBL struct ICorDebugFrameEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFrameEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFrameEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFrameEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFrameEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugFrameEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugFrameEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugFrameEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugFrameEnum_Next(This,celt,frames,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,frames,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,frames,pceltFetched) ) #endif /* COBJMACROS */ @@ -18173,72 +18180,72 @@ EXTERN_C const IID IID_ICorDebugFrameEnum; #define __ICorDebugChainEnum_INTERFACE_DEFINED__ /* interface ICorDebugChainEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugChainEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB08-8A68-11d2-983C-0000F808342D") ICorDebugChainEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugChain *chains[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugChainEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugChainEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugChainEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugChainEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugChainEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugChainEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugChainEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugChainEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugChainEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugChainEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugChain *chains[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugChainEnumVtbl; @@ -18247,36 +18254,36 @@ EXTERN_C const IID IID_ICorDebugChainEnum; CONST_VTBL struct ICorDebugChainEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugChainEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugChainEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugChainEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugChainEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugChainEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugChainEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugChainEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugChainEnum_Next(This,celt,chains,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,chains,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,chains,pceltFetched) ) #endif /* COBJMACROS */ @@ -18293,72 +18300,72 @@ EXTERN_C const IID IID_ICorDebugChainEnum; #define __ICorDebugModuleEnum_INTERFACE_DEFINED__ /* interface ICorDebugModuleEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModuleEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB09-8A68-11d2-983C-0000F808342D") ICorDebugModuleEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugModule *modules[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugModuleEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModuleEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModuleEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModuleEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugModuleEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugModuleEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugModuleEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugModuleEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugModuleEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugModuleEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugModule *modules[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugModuleEnumVtbl; @@ -18367,36 +18374,36 @@ EXTERN_C const IID IID_ICorDebugModuleEnum; CONST_VTBL struct ICorDebugModuleEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugModuleEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModuleEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModuleEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModuleEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugModuleEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugModuleEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugModuleEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugModuleEnum_Next(This,celt,modules,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,modules,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,modules,pceltFetched) ) #endif /* COBJMACROS */ @@ -18413,72 +18420,72 @@ EXTERN_C const IID IID_ICorDebugModuleEnum; #define __ICorDebugValueEnum_INTERFACE_DEFINED__ /* interface ICorDebugValueEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValueEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB0A-8A68-11d2-983C-0000F808342D") ICorDebugValueEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugValue *values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugValueEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValueEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValueEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValueEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugValueEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugValueEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugValueEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugValueEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugValueEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugValueEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugValue *values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugValueEnumVtbl; @@ -18487,36 +18494,36 @@ EXTERN_C const IID IID_ICorDebugValueEnum; CONST_VTBL struct ICorDebugValueEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugValueEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValueEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValueEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValueEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugValueEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugValueEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugValueEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugValueEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -18533,72 +18540,72 @@ EXTERN_C const IID IID_ICorDebugValueEnum; #define __ICorDebugVariableHomeEnum_INTERFACE_DEFINED__ /* interface ICorDebugVariableHomeEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugVariableHomeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("e76b7a57-4f7a-4309-85a7-5d918c3deaf7") ICorDebugVariableHomeEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugVariableHome *homes[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugVariableHomeEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugVariableHomeEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugVariableHomeEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugVariableHomeEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugVariableHomeEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugVariableHomeEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugVariableHomeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugVariableHomeEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugVariableHomeEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugVariableHomeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugVariableHome *homes[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugVariableHomeEnumVtbl; @@ -18607,36 +18614,36 @@ EXTERN_C const IID IID_ICorDebugVariableHomeEnum; CONST_VTBL struct ICorDebugVariableHomeEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugVariableHomeEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugVariableHomeEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugVariableHomeEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugVariableHomeEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugVariableHomeEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugVariableHomeEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugVariableHomeEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugVariableHomeEnum_Next(This,celt,homes,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,homes,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,homes,pceltFetched) ) #endif /* COBJMACROS */ @@ -18653,72 +18660,72 @@ EXTERN_C const IID IID_ICorDebugVariableHomeEnum; #define __ICorDebugCodeEnum_INTERFACE_DEFINED__ /* interface ICorDebugCodeEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugCodeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("55E96461-9645-45e4-A2FF-0367877ABCDE") ICorDebugCodeEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugCode *values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugCodeEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCodeEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCodeEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCodeEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugCodeEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugCodeEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugCodeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugCodeEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugCodeEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugCodeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugCode *values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugCodeEnumVtbl; @@ -18727,36 +18734,36 @@ EXTERN_C const IID IID_ICorDebugCodeEnum; CONST_VTBL struct ICorDebugCodeEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugCodeEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCodeEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCodeEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCodeEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugCodeEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugCodeEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugCodeEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugCodeEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -18773,72 +18780,72 @@ EXTERN_C const IID IID_ICorDebugCodeEnum; #define __ICorDebugTypeEnum_INTERFACE_DEFINED__ /* interface ICorDebugTypeEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugTypeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("10F27499-9DF2-43ce-8333-A321D7C99CB4") ICorDebugTypeEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugType *values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugTypeEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugTypeEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugTypeEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugTypeEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugTypeEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugTypeEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugTypeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugTypeEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugTypeEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugTypeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugType *values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugTypeEnumVtbl; @@ -18847,36 +18854,36 @@ EXTERN_C const IID IID_ICorDebugTypeEnum; CONST_VTBL struct ICorDebugTypeEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugTypeEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugTypeEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugTypeEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugTypeEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugTypeEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugTypeEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugTypeEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugTypeEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -18893,101 +18900,101 @@ EXTERN_C const IID IID_ICorDebugTypeEnum; #define __ICorDebugType_INTERFACE_DEFINED__ /* interface ICorDebugType */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugType; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("D613F0BB-ACE1-4c19-BD72-E4C08D5DA7F5") ICorDebugType : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetType( + virtual HRESULT STDMETHODCALLTYPE GetType( /* [out] */ CorElementType *ty) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetClass( + + virtual HRESULT STDMETHODCALLTYPE GetClass( /* [out] */ ICorDebugClass **ppClass) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateTypeParameters( + + virtual HRESULT STDMETHODCALLTYPE EnumerateTypeParameters( /* [out] */ ICorDebugTypeEnum **ppTyParEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFirstTypeParameter( + + virtual HRESULT STDMETHODCALLTYPE GetFirstTypeParameter( /* [out] */ ICorDebugType **value) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetBase( + + virtual HRESULT STDMETHODCALLTYPE GetBase( /* [out] */ ICorDebugType **pBase) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStaticFieldValue( + + virtual HRESULT STDMETHODCALLTYPE GetStaticFieldValue( /* [in] */ mdFieldDef fieldDef, /* [in] */ ICorDebugFrame *pFrame, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRank( + + virtual HRESULT STDMETHODCALLTYPE GetRank( /* [out] */ ULONG32 *pnRank) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugTypeVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugType * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugType * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugType * This); - + DECLSPEC_XFGVIRT(ICorDebugType, GetType) - HRESULT ( STDMETHODCALLTYPE *GetType )( + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugType * This, /* [out] */ CorElementType *ty); - + DECLSPEC_XFGVIRT(ICorDebugType, GetClass) - HRESULT ( STDMETHODCALLTYPE *GetClass )( + HRESULT ( STDMETHODCALLTYPE *GetClass )( ICorDebugType * This, /* [out] */ ICorDebugClass **ppClass); - + DECLSPEC_XFGVIRT(ICorDebugType, EnumerateTypeParameters) - HRESULT ( STDMETHODCALLTYPE *EnumerateTypeParameters )( + HRESULT ( STDMETHODCALLTYPE *EnumerateTypeParameters )( ICorDebugType * This, /* [out] */ ICorDebugTypeEnum **ppTyParEnum); - + DECLSPEC_XFGVIRT(ICorDebugType, GetFirstTypeParameter) - HRESULT ( STDMETHODCALLTYPE *GetFirstTypeParameter )( + HRESULT ( STDMETHODCALLTYPE *GetFirstTypeParameter )( ICorDebugType * This, /* [out] */ ICorDebugType **value); - + DECLSPEC_XFGVIRT(ICorDebugType, GetBase) - HRESULT ( STDMETHODCALLTYPE *GetBase )( + HRESULT ( STDMETHODCALLTYPE *GetBase )( ICorDebugType * This, /* [out] */ ICorDebugType **pBase); - + DECLSPEC_XFGVIRT(ICorDebugType, GetStaticFieldValue) - HRESULT ( STDMETHODCALLTYPE *GetStaticFieldValue )( + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldValue )( ICorDebugType * This, /* [in] */ mdFieldDef fieldDef, /* [in] */ ICorDebugFrame *pFrame, /* [out] */ ICorDebugValue **ppValue); - + DECLSPEC_XFGVIRT(ICorDebugType, GetRank) - HRESULT ( STDMETHODCALLTYPE *GetRank )( + HRESULT ( STDMETHODCALLTYPE *GetRank )( ICorDebugType * This, /* [out] */ ULONG32 *pnRank); - + END_INTERFACE } ICorDebugTypeVtbl; @@ -18996,41 +19003,41 @@ EXTERN_C const IID IID_ICorDebugType; CONST_VTBL struct ICorDebugTypeVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugType_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugType_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugType_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugType_GetType(This,ty) \ - ( (This)->lpVtbl -> GetType(This,ty) ) + ( (This)->lpVtbl -> GetType(This,ty) ) #define ICorDebugType_GetClass(This,ppClass) \ - ( (This)->lpVtbl -> GetClass(This,ppClass) ) + ( (This)->lpVtbl -> GetClass(This,ppClass) ) #define ICorDebugType_EnumerateTypeParameters(This,ppTyParEnum) \ - ( (This)->lpVtbl -> EnumerateTypeParameters(This,ppTyParEnum) ) + ( (This)->lpVtbl -> EnumerateTypeParameters(This,ppTyParEnum) ) #define ICorDebugType_GetFirstTypeParameter(This,value) \ - ( (This)->lpVtbl -> GetFirstTypeParameter(This,value) ) + ( (This)->lpVtbl -> GetFirstTypeParameter(This,value) ) #define ICorDebugType_GetBase(This,pBase) \ - ( (This)->lpVtbl -> GetBase(This,pBase) ) + ( (This)->lpVtbl -> GetBase(This,pBase) ) #define ICorDebugType_GetStaticFieldValue(This,fieldDef,pFrame,ppValue) \ - ( (This)->lpVtbl -> GetStaticFieldValue(This,fieldDef,pFrame,ppValue) ) + ( (This)->lpVtbl -> GetStaticFieldValue(This,fieldDef,pFrame,ppValue) ) #define ICorDebugType_GetRank(This,pnRank) \ - ( (This)->lpVtbl -> GetRank(This,pnRank) ) + ( (This)->lpVtbl -> GetRank(This,pnRank) ) #endif /* COBJMACROS */ @@ -19047,49 +19054,49 @@ EXTERN_C const IID IID_ICorDebugType; #define __ICorDebugType2_INTERFACE_DEFINED__ /* interface ICorDebugType2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugType2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("e6e91d79-693d-48bc-b417-8284b4f10fb5") ICorDebugType2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetTypeID( + virtual HRESULT STDMETHODCALLTYPE GetTypeID( /* [out] */ COR_TYPEID *id) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugType2Vtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugType2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugType2 * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugType2 * This); - + DECLSPEC_XFGVIRT(ICorDebugType2, GetTypeID) - HRESULT ( STDMETHODCALLTYPE *GetTypeID )( + HRESULT ( STDMETHODCALLTYPE *GetTypeID )( ICorDebugType2 * This, /* [out] */ COR_TYPEID *id); - + END_INTERFACE } ICorDebugType2Vtbl; @@ -19098,23 +19105,23 @@ EXTERN_C const IID IID_ICorDebugType2; CONST_VTBL struct ICorDebugType2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugType2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugType2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugType2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugType2_GetTypeID(This,id) \ - ( (This)->lpVtbl -> GetTypeID(This,id) ) + ( (This)->lpVtbl -> GetTypeID(This,id) ) #endif /* COBJMACROS */ @@ -19131,72 +19138,72 @@ EXTERN_C const IID IID_ICorDebugType2; #define __ICorDebugErrorInfoEnum_INTERFACE_DEFINED__ /* interface ICorDebugErrorInfoEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugErrorInfoEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("F0E18809-72B5-11d2-976F-00A0C9B4D50C") ICorDebugErrorInfoEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugEditAndContinueErrorInfo *errors[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugErrorInfoEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugErrorInfoEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugErrorInfoEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugErrorInfoEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugErrorInfoEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugErrorInfoEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugErrorInfoEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugErrorInfoEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugErrorInfoEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugErrorInfoEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugEditAndContinueErrorInfo *errors[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugErrorInfoEnumVtbl; @@ -19205,36 +19212,36 @@ EXTERN_C const IID IID_ICorDebugErrorInfoEnum; CONST_VTBL struct ICorDebugErrorInfoEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugErrorInfoEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugErrorInfoEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugErrorInfoEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugErrorInfoEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugErrorInfoEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugErrorInfoEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugErrorInfoEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugErrorInfoEnum_Next(This,celt,errors,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,errors,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,errors,pceltFetched) ) #endif /* COBJMACROS */ @@ -19251,72 +19258,72 @@ EXTERN_C const IID IID_ICorDebugErrorInfoEnum; #define __ICorDebugAppDomainEnum_INTERFACE_DEFINED__ /* interface ICorDebugAppDomainEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomainEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("63ca1b24-4359-4883-bd57-13f815f58744") ICorDebugAppDomainEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugAppDomain *values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAppDomainEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomainEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomainEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomainEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugAppDomainEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugAppDomainEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugAppDomainEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugAppDomainEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugAppDomainEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugAppDomainEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugAppDomain *values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugAppDomainEnumVtbl; @@ -19325,36 +19332,36 @@ EXTERN_C const IID IID_ICorDebugAppDomainEnum; CONST_VTBL struct ICorDebugAppDomainEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAppDomainEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomainEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomainEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomainEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugAppDomainEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugAppDomainEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugAppDomainEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugAppDomainEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -19371,72 +19378,72 @@ EXTERN_C const IID IID_ICorDebugAppDomainEnum; #define __ICorDebugAssemblyEnum_INTERFACE_DEFINED__ /* interface ICorDebugAssemblyEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAssemblyEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("4a2a1ec9-85ec-4bfb-9f15-a89fdfe0fe83") ICorDebugAssemblyEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugAssembly *values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAssemblyEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAssemblyEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAssemblyEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAssemblyEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugAssemblyEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugAssemblyEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugAssemblyEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugAssemblyEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugAssemblyEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugAssemblyEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugAssembly *values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugAssemblyEnumVtbl; @@ -19445,36 +19452,36 @@ EXTERN_C const IID IID_ICorDebugAssemblyEnum; CONST_VTBL struct ICorDebugAssemblyEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAssemblyEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAssemblyEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAssemblyEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAssemblyEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugAssemblyEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugAssemblyEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugAssemblyEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugAssemblyEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -19491,72 +19498,72 @@ EXTERN_C const IID IID_ICorDebugAssemblyEnum; #define __ICorDebugBlockingObjectEnum_INTERFACE_DEFINED__ /* interface ICorDebugBlockingObjectEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugBlockingObjectEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("976A6278-134A-4a81-81A3-8F277943F4C3") ICorDebugBlockingObjectEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugBlockingObject values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugBlockingObjectEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugBlockingObjectEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugBlockingObjectEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugBlockingObjectEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugBlockingObjectEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugBlockingObjectEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugBlockingObjectEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugBlockingObjectEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugBlockingObjectEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugBlockingObjectEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugBlockingObject values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugBlockingObjectEnumVtbl; @@ -19565,36 +19572,36 @@ EXTERN_C const IID IID_ICorDebugBlockingObjectEnum; CONST_VTBL struct ICorDebugBlockingObjectEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugBlockingObjectEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugBlockingObjectEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugBlockingObjectEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugBlockingObjectEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugBlockingObjectEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugBlockingObjectEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugBlockingObjectEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugBlockingObjectEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -19608,7 +19615,7 @@ EXTERN_C const IID IID_ICorDebugBlockingObjectEnum; /* interface __MIDL_itf_cordebug_0000_0131 */ -/* [local] */ +/* [local] */ #pragma warning(push) #pragma warning(disable:28718) @@ -19621,9 +19628,9 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0131_v0_0_s_ifspec; #define __ICorDebugMDA_INTERFACE_DEFINED__ /* interface ICorDebugMDA */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugMDAFlags { MDA_FLAG_SLIP = 0x2 @@ -19633,87 +19640,87 @@ enum CorDebugMDAFlags EXTERN_C const IID IID_ICorDebugMDA; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC726F2F-1DB7-459b-B0EC-05F01D841B42") ICorDebugMDA : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetName( + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDescription( + + virtual HRESULT STDMETHODCALLTYPE GetDescription( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetXML( + + virtual HRESULT STDMETHODCALLTYPE GetXML( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFlags( + + virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [in] */ CorDebugMDAFlags *pFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetOSThreadId( + + virtual HRESULT STDMETHODCALLTYPE GetOSThreadId( /* [out] */ DWORD *pOsTid) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugMDAVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMDA * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMDA * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMDA * This); - + DECLSPEC_XFGVIRT(ICorDebugMDA, GetName) - HRESULT ( STDMETHODCALLTYPE *GetName )( + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugMDA * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - + DECLSPEC_XFGVIRT(ICorDebugMDA, GetDescription) - HRESULT ( STDMETHODCALLTYPE *GetDescription )( + HRESULT ( STDMETHODCALLTYPE *GetDescription )( ICorDebugMDA * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - + DECLSPEC_XFGVIRT(ICorDebugMDA, GetXML) - HRESULT ( STDMETHODCALLTYPE *GetXML )( + HRESULT ( STDMETHODCALLTYPE *GetXML )( ICorDebugMDA * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - + DECLSPEC_XFGVIRT(ICorDebugMDA, GetFlags) - HRESULT ( STDMETHODCALLTYPE *GetFlags )( + HRESULT ( STDMETHODCALLTYPE *GetFlags )( ICorDebugMDA * This, /* [in] */ CorDebugMDAFlags *pFlags); - + DECLSPEC_XFGVIRT(ICorDebugMDA, GetOSThreadId) - HRESULT ( STDMETHODCALLTYPE *GetOSThreadId )( + HRESULT ( STDMETHODCALLTYPE *GetOSThreadId )( ICorDebugMDA * This, /* [out] */ DWORD *pOsTid); - + END_INTERFACE } ICorDebugMDAVtbl; @@ -19722,35 +19729,35 @@ EXTERN_C const IID IID_ICorDebugMDA; CONST_VTBL struct ICorDebugMDAVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugMDA_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMDA_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMDA_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMDA_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugMDA_GetDescription(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetDescription(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetDescription(This,cchName,pcchName,szName) ) #define ICorDebugMDA_GetXML(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetXML(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetXML(This,cchName,pcchName,szName) ) #define ICorDebugMDA_GetFlags(This,pFlags) \ - ( (This)->lpVtbl -> GetFlags(This,pFlags) ) + ( (This)->lpVtbl -> GetFlags(This,pFlags) ) #define ICorDebugMDA_GetOSThreadId(This,pOsTid) \ - ( (This)->lpVtbl -> GetOSThreadId(This,pOsTid) ) + ( (This)->lpVtbl -> GetOSThreadId(This,pOsTid) ) #endif /* COBJMACROS */ @@ -19764,11 +19771,11 @@ EXTERN_C const IID IID_ICorDebugMDA; /* interface __MIDL_itf_cordebug_0000_0132 */ -/* [local] */ +/* [local] */ #pragma warning(pop) #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0132_v0_0_c_ifspec; @@ -19778,77 +19785,77 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0132_v0_0_s_ifspec; #define __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__ /* interface ICorDebugEditAndContinueErrorInfo */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEditAndContinueErrorInfo; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("8D600D41-F4F6-4cb3-B7EC-7BD164944036") ICorDebugEditAndContinueErrorInfo : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetModule( + virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **ppModule) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetToken( + + virtual HRESULT STDMETHODCALLTYPE GetToken( /* [out] */ mdToken *pToken) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetErrorCode( + + virtual HRESULT STDMETHODCALLTYPE GetErrorCode( /* [out] */ HRESULT *pHr) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetString( + + virtual HRESULT STDMETHODCALLTYPE GetString( /* [in] */ ULONG32 cchString, /* [out] */ ULONG32 *pcchString, /* [length_is][size_is][out] */ WCHAR szString[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugEditAndContinueErrorInfoVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEditAndContinueErrorInfo * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEditAndContinueErrorInfo * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEditAndContinueErrorInfo * This); - + DECLSPEC_XFGVIRT(ICorDebugEditAndContinueErrorInfo, GetModule) - HRESULT ( STDMETHODCALLTYPE *GetModule )( + HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugEditAndContinueErrorInfo * This, /* [out] */ ICorDebugModule **ppModule); - + DECLSPEC_XFGVIRT(ICorDebugEditAndContinueErrorInfo, GetToken) - HRESULT ( STDMETHODCALLTYPE *GetToken )( + HRESULT ( STDMETHODCALLTYPE *GetToken )( ICorDebugEditAndContinueErrorInfo * This, /* [out] */ mdToken *pToken); - + DECLSPEC_XFGVIRT(ICorDebugEditAndContinueErrorInfo, GetErrorCode) - HRESULT ( STDMETHODCALLTYPE *GetErrorCode )( + HRESULT ( STDMETHODCALLTYPE *GetErrorCode )( ICorDebugEditAndContinueErrorInfo * This, /* [out] */ HRESULT *pHr); - + DECLSPEC_XFGVIRT(ICorDebugEditAndContinueErrorInfo, GetString) - HRESULT ( STDMETHODCALLTYPE *GetString )( + HRESULT ( STDMETHODCALLTYPE *GetString )( ICorDebugEditAndContinueErrorInfo * This, /* [in] */ ULONG32 cchString, /* [out] */ ULONG32 *pcchString, /* [length_is][size_is][out] */ WCHAR szString[ ]); - + END_INTERFACE } ICorDebugEditAndContinueErrorInfoVtbl; @@ -19857,32 +19864,32 @@ EXTERN_C const IID IID_ICorDebugEditAndContinueErrorInfo; CONST_VTBL struct ICorDebugEditAndContinueErrorInfoVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugEditAndContinueErrorInfo_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEditAndContinueErrorInfo_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEditAndContinueErrorInfo_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEditAndContinueErrorInfo_GetModule(This,ppModule) \ - ( (This)->lpVtbl -> GetModule(This,ppModule) ) + ( (This)->lpVtbl -> GetModule(This,ppModule) ) #define ICorDebugEditAndContinueErrorInfo_GetToken(This,pToken) \ - ( (This)->lpVtbl -> GetToken(This,pToken) ) + ( (This)->lpVtbl -> GetToken(This,pToken) ) #define ICorDebugEditAndContinueErrorInfo_GetErrorCode(This,pHr) \ - ( (This)->lpVtbl -> GetErrorCode(This,pHr) ) + ( (This)->lpVtbl -> GetErrorCode(This,pHr) ) #define ICorDebugEditAndContinueErrorInfo_GetString(This,cchString,pcchString,szString) \ - ( (This)->lpVtbl -> GetString(This,cchString,pcchString,szString) ) + ( (This)->lpVtbl -> GetString(This,cchString,pcchString,szString) ) #endif /* COBJMACROS */ @@ -19896,7 +19903,7 @@ EXTERN_C const IID IID_ICorDebugEditAndContinueErrorInfo; /* interface __MIDL_itf_cordebug_0000_0133 */ -/* [local] */ +/* [local] */ #pragma warning(pop) @@ -19908,103 +19915,103 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0133_v0_0_s_ifspec; #define __ICorDebugEditAndContinueSnapshot_INTERFACE_DEFINED__ /* interface ICorDebugEditAndContinueSnapshot */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEditAndContinueSnapshot; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("6DC3FA01-D7CB-11d2-8A95-0080C792E5D8") ICorDebugEditAndContinueSnapshot : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CopyMetaData( + virtual HRESULT STDMETHODCALLTYPE CopyMetaData( /* [in] */ IStream *pIStream, /* [out] */ GUID *pMvid) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMvid( + + virtual HRESULT STDMETHODCALLTYPE GetMvid( /* [out] */ GUID *pMvid) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRoDataRVA( + + virtual HRESULT STDMETHODCALLTYPE GetRoDataRVA( /* [out] */ ULONG32 *pRoDataRVA) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRwDataRVA( + + virtual HRESULT STDMETHODCALLTYPE GetRwDataRVA( /* [out] */ ULONG32 *pRwDataRVA) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetPEBytes( + + virtual HRESULT STDMETHODCALLTYPE SetPEBytes( /* [in] */ IStream *pIStream) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetILMap( + + virtual HRESULT STDMETHODCALLTYPE SetILMap( /* [in] */ mdToken mdFunction, /* [in] */ ULONG cMapSize, /* [size_is][in] */ COR_IL_MAP map[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetPESymbolBytes( + + virtual HRESULT STDMETHODCALLTYPE SetPESymbolBytes( /* [in] */ IStream *pIStream) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugEditAndContinueSnapshotVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEditAndContinueSnapshot * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEditAndContinueSnapshot * This); - + DECLSPEC_XFGVIRT(ICorDebugEditAndContinueSnapshot, CopyMetaData) - HRESULT ( STDMETHODCALLTYPE *CopyMetaData )( + HRESULT ( STDMETHODCALLTYPE *CopyMetaData )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ IStream *pIStream, /* [out] */ GUID *pMvid); - + DECLSPEC_XFGVIRT(ICorDebugEditAndContinueSnapshot, GetMvid) - HRESULT ( STDMETHODCALLTYPE *GetMvid )( + HRESULT ( STDMETHODCALLTYPE *GetMvid )( ICorDebugEditAndContinueSnapshot * This, /* [out] */ GUID *pMvid); - + DECLSPEC_XFGVIRT(ICorDebugEditAndContinueSnapshot, GetRoDataRVA) - HRESULT ( STDMETHODCALLTYPE *GetRoDataRVA )( + HRESULT ( STDMETHODCALLTYPE *GetRoDataRVA )( ICorDebugEditAndContinueSnapshot * This, /* [out] */ ULONG32 *pRoDataRVA); - + DECLSPEC_XFGVIRT(ICorDebugEditAndContinueSnapshot, GetRwDataRVA) - HRESULT ( STDMETHODCALLTYPE *GetRwDataRVA )( + HRESULT ( STDMETHODCALLTYPE *GetRwDataRVA )( ICorDebugEditAndContinueSnapshot * This, /* [out] */ ULONG32 *pRwDataRVA); - + DECLSPEC_XFGVIRT(ICorDebugEditAndContinueSnapshot, SetPEBytes) - HRESULT ( STDMETHODCALLTYPE *SetPEBytes )( + HRESULT ( STDMETHODCALLTYPE *SetPEBytes )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ IStream *pIStream); - + DECLSPEC_XFGVIRT(ICorDebugEditAndContinueSnapshot, SetILMap) - HRESULT ( STDMETHODCALLTYPE *SetILMap )( + HRESULT ( STDMETHODCALLTYPE *SetILMap )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ mdToken mdFunction, /* [in] */ ULONG cMapSize, /* [size_is][in] */ COR_IL_MAP map[ ]); - + DECLSPEC_XFGVIRT(ICorDebugEditAndContinueSnapshot, SetPESymbolBytes) - HRESULT ( STDMETHODCALLTYPE *SetPESymbolBytes )( + HRESULT ( STDMETHODCALLTYPE *SetPESymbolBytes )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ IStream *pIStream); - + END_INTERFACE } ICorDebugEditAndContinueSnapshotVtbl; @@ -20013,41 +20020,41 @@ EXTERN_C const IID IID_ICorDebugEditAndContinueSnapshot; CONST_VTBL struct ICorDebugEditAndContinueSnapshotVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugEditAndContinueSnapshot_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEditAndContinueSnapshot_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEditAndContinueSnapshot_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEditAndContinueSnapshot_CopyMetaData(This,pIStream,pMvid) \ - ( (This)->lpVtbl -> CopyMetaData(This,pIStream,pMvid) ) + ( (This)->lpVtbl -> CopyMetaData(This,pIStream,pMvid) ) #define ICorDebugEditAndContinueSnapshot_GetMvid(This,pMvid) \ - ( (This)->lpVtbl -> GetMvid(This,pMvid) ) + ( (This)->lpVtbl -> GetMvid(This,pMvid) ) #define ICorDebugEditAndContinueSnapshot_GetRoDataRVA(This,pRoDataRVA) \ - ( (This)->lpVtbl -> GetRoDataRVA(This,pRoDataRVA) ) + ( (This)->lpVtbl -> GetRoDataRVA(This,pRoDataRVA) ) #define ICorDebugEditAndContinueSnapshot_GetRwDataRVA(This,pRwDataRVA) \ - ( (This)->lpVtbl -> GetRwDataRVA(This,pRwDataRVA) ) + ( (This)->lpVtbl -> GetRwDataRVA(This,pRwDataRVA) ) #define ICorDebugEditAndContinueSnapshot_SetPEBytes(This,pIStream) \ - ( (This)->lpVtbl -> SetPEBytes(This,pIStream) ) + ( (This)->lpVtbl -> SetPEBytes(This,pIStream) ) #define ICorDebugEditAndContinueSnapshot_SetILMap(This,mdFunction,cMapSize,map) \ - ( (This)->lpVtbl -> SetILMap(This,mdFunction,cMapSize,map) ) + ( (This)->lpVtbl -> SetILMap(This,mdFunction,cMapSize,map) ) #define ICorDebugEditAndContinueSnapshot_SetPESymbolBytes(This,pIStream) \ - ( (This)->lpVtbl -> SetPESymbolBytes(This,pIStream) ) + ( (This)->lpVtbl -> SetPESymbolBytes(This,pIStream) ) #endif /* COBJMACROS */ @@ -20064,72 +20071,72 @@ EXTERN_C const IID IID_ICorDebugEditAndContinueSnapshot; #define __ICorDebugExceptionObjectCallStackEnum_INTERFACE_DEFINED__ /* interface ICorDebugExceptionObjectCallStackEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugExceptionObjectCallStackEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("ED775530-4DC4-41F7-86D0-9E2DEF7DFC66") ICorDebugExceptionObjectCallStackEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugExceptionObjectStackFrame values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugExceptionObjectCallStackEnumVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugExceptionObjectCallStackEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugExceptionObjectCallStackEnum * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugExceptionObjectCallStackEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Skip) - HRESULT ( STDMETHODCALLTYPE *Skip )( + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugExceptionObjectCallStackEnum * This, /* [in] */ ULONG celt); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Reset) - HRESULT ( STDMETHODCALLTYPE *Reset )( + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugExceptionObjectCallStackEnum * This); - + DECLSPEC_XFGVIRT(ICorDebugEnum, Clone) - HRESULT ( STDMETHODCALLTYPE *Clone )( + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugExceptionObjectCallStackEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - + DECLSPEC_XFGVIRT(ICorDebugEnum, GetCount) - HRESULT ( STDMETHODCALLTYPE *GetCount )( + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugExceptionObjectCallStackEnum * This, /* [out] */ ULONG *pcelt); - + DECLSPEC_XFGVIRT(ICorDebugExceptionObjectCallStackEnum, Next) - HRESULT ( STDMETHODCALLTYPE *Next )( + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugExceptionObjectCallStackEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugExceptionObjectStackFrame values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugExceptionObjectCallStackEnumVtbl; @@ -20138,36 +20145,36 @@ EXTERN_C const IID IID_ICorDebugExceptionObjectCallStackEnum; CONST_VTBL struct ICorDebugExceptionObjectCallStackEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugExceptionObjectCallStackEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugExceptionObjectCallStackEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugExceptionObjectCallStackEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugExceptionObjectCallStackEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugExceptionObjectCallStackEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugExceptionObjectCallStackEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugExceptionObjectCallStackEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugExceptionObjectCallStackEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -20184,49 +20191,49 @@ EXTERN_C const IID IID_ICorDebugExceptionObjectCallStackEnum; #define __ICorDebugExceptionObjectValue_INTERFACE_DEFINED__ /* interface ICorDebugExceptionObjectValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugExceptionObjectValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("AE4CA65D-59DD-42A2-83A5-57E8A08D8719") ICorDebugExceptionObjectValue : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE EnumerateExceptionCallStack( + virtual HRESULT STDMETHODCALLTYPE EnumerateExceptionCallStack( /* [out] */ ICorDebugExceptionObjectCallStackEnum **ppCallStackEnum) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugExceptionObjectValueVtbl { BEGIN_INTERFACE - + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugExceptionObjectValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - + DECLSPEC_XFGVIRT(IUnknown, AddRef) - ULONG ( STDMETHODCALLTYPE *AddRef )( + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugExceptionObjectValue * This); - + DECLSPEC_XFGVIRT(IUnknown, Release) - ULONG ( STDMETHODCALLTYPE *Release )( + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugExceptionObjectValue * This); - + DECLSPEC_XFGVIRT(ICorDebugExceptionObjectValue, EnumerateExceptionCallStack) - HRESULT ( STDMETHODCALLTYPE *EnumerateExceptionCallStack )( + HRESULT ( STDMETHODCALLTYPE *EnumerateExceptionCallStack )( ICorDebugExceptionObjectValue * This, /* [out] */ ICorDebugExceptionObjectCallStackEnum **ppCallStackEnum); - + END_INTERFACE } ICorDebugExceptionObjectValueVtbl; @@ -20235,23 +20242,23 @@ EXTERN_C const IID IID_ICorDebugExceptionObjectValue; CONST_VTBL struct ICorDebugExceptionObjectValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugExceptionObjectValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugExceptionObjectValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugExceptionObjectValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugExceptionObjectValue_EnumerateExceptionCallStack(This,ppCallStackEnum) \ - ( (This)->lpVtbl -> EnumerateExceptionCallStack(This,ppCallStackEnum) ) + ( (This)->lpVtbl -> EnumerateExceptionCallStack(This,ppCallStackEnum) ) #endif /* COBJMACROS */ @@ -20264,12 +20271,96 @@ EXTERN_C const IID IID_ICorDebugExceptionObjectValue; #endif /* __ICorDebugExceptionObjectValue_INTERFACE_DEFINED__ */ +#ifndef __ICorDebugExceptionObjectValue2_INTERFACE_DEFINED__ +#define __ICorDebugExceptionObjectValue2_INTERFACE_DEFINED__ + +/* interface ICorDebugExceptionObjectValue2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugExceptionObjectValue2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("e3b2f332-cc46-4f1e-ab4e-5400e332195e") + ICorDebugExceptionObjectValue2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ForceCatchHandlerFoundEvents( + /* [in] */ BOOL enableEvents) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugExceptionObjectValue2Vtbl + { + BEGIN_INTERFACE + + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugExceptionObjectValue2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + DECLSPEC_XFGVIRT(IUnknown, AddRef) + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugExceptionObjectValue2 * This); + + DECLSPEC_XFGVIRT(IUnknown, Release) + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugExceptionObjectValue2 * This); + + DECLSPEC_XFGVIRT(ICorDebugExceptionObjectValue2, ForceCatchHandlerFoundEvents) + HRESULT ( STDMETHODCALLTYPE *ForceCatchHandlerFoundEvents )( + ICorDebugExceptionObjectValue2 * This, + /* [in] */ BOOL enableEvents); + + END_INTERFACE + } ICorDebugExceptionObjectValue2Vtbl; + + interface ICorDebugExceptionObjectValue2 + { + CONST_VTBL struct ICorDebugExceptionObjectValue2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugExceptionObjectValue2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugExceptionObjectValue2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugExceptionObjectValue2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugExceptionObjectValue2_ForceCatchHandlerFoundEvents(This,enableEvents) \ + ( (This)->lpVtbl -> ForceCatchHandlerFoundEvents(This,enableEvents) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugExceptionObjectValue2_INTERFACE_DEFINED__ */ + + #ifndef __CORDBLib_LIBRARY_DEFINED__ #define __CORDBLib_LIBRARY_DEFINED__ /* library CORDBLib */ -/* [helpstring][version][uuid] */ +/* [helpstring][version][uuid] */ diff --git a/src/coreclr/pal/prebuilt/inc/corerror.h b/src/coreclr/pal/prebuilt/inc/corerror.h index 12d3490aaf09..0b475679050f 100644 --- a/src/coreclr/pal/prebuilt/inc/corerror.h +++ b/src/coreclr/pal/prebuilt/inc/corerror.h @@ -41,7 +41,6 @@ #define HOST_E_INVALIDOPERATION EMAKEHR(0x1022) #define HOST_E_CLRNOTAVAILABLE EMAKEHR(0x1023) #define FUSION_E_REF_DEF_MISMATCH EMAKEHR(0x1040) -#define FUSION_E_PRIVATE_ASM_DISALLOWED EMAKEHR(0x1044) #define FUSION_E_INVALID_NAME EMAKEHR(0x1047) #define FUSION_E_APP_DOMAIN_LOCKED EMAKEHR(0x1053) #define COR_E_LOADING_REFERENCE_ASSEMBLY EMAKEHR(0x1058) diff --git a/src/coreclr/pal/src/CMakeLists.txt b/src/coreclr/pal/src/CMakeLists.txt index cb3693655dca..2398334e8998 100644 --- a/src/coreclr/pal/src/CMakeLists.txt +++ b/src/coreclr/pal/src/CMakeLists.txt @@ -144,8 +144,8 @@ set(SOURCES init/sxs.cpp loader/module.cpp locale/unicode.cpp - locale/unicodedata.cpp ${CLR_SRC_NATIVE_DIR}/minipal/utf8.c + ${CLR_SRC_NATIVE_DIR}/minipal/unicodedata.c map/common.cpp map/map.cpp map/virtual.cpp @@ -185,8 +185,6 @@ set(SOURCES safecrt/wcsncat_s.cpp safecrt/wcsncpy_s.cpp safecrt/wmakepath_s.cpp - safecrt/xtoa_s.cpp - safecrt/xtow_s.cpp sharedmemory/sharedmemory.cpp shmemory/shmemory.cpp sync/cs.cpp diff --git a/src/coreclr/pal/src/arch/arm/context2.S b/src/coreclr/pal/src/arch/arm/context2.S index e292ca26fe2a..bb41b0ff589b 100644 --- a/src/coreclr/pal/src/arch/arm/context2.S +++ b/src/coreclr/pal/src/arch/arm/context2.S @@ -160,25 +160,28 @@ LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT): ldr R2, [r0, #(CONTEXT_Cpsr)] msr APSR, r2 - // Ideally, we would like to use `ldmia r0, {r0-r12, sp, lr, pc}` here, - // but clang 3.6 and later, as per ARM recommendation, disallows using - // Sp in the register list, and Pc and Lr simultaneously. - // So we are going to use the IPC register r12 to copy Sp, Lr and Pc - // which should be ok -- TODO: Is this really ok? + ldr r1, [r0, #(CONTEXT_Sp)] + ldr r2, [r0, #(CONTEXT_Pc)] + str r2, [r1, #-4] + ldr r2, [r0, #(CONTEXT_R12)] + str r2, [r1, #-8] add r12, r0, CONTEXT_R0 ldm r12, {r0-r11} - ldr sp, [r12, #(CONTEXT_Sp - (CONTEXT_R0))] ldr lr, [r12, #(CONTEXT_Lr - (CONTEXT_R0))] - ldr pc, [r12, #(CONTEXT_Pc - (CONTEXT_R0))] + ldr r12, [r12, #(CONTEXT_Sp - (CONTEXT_R0))] + sub r12, r12, #8 + mov sp, r12 + pop {r12, pc} LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): ldr r2, [r0, #(CONTEXT_Cpsr)] msr APSR, r2 - ldr sp, [r0, #(CONTEXT_Sp)] ldr lr, [r0, #(CONTEXT_Lr)] - ldr pc, [r0, #(CONTEXT_Pc)] + ldr r2, [r0, #(CONTEXT_Pc)] + ldr sp, [r0, #(CONTEXT_Sp)] + bx r2 LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): ldr r2, [r0, #(CONTEXT_ContextFlags)] diff --git a/src/coreclr/pal/src/arch/i386/context2.S b/src/coreclr/pal/src/arch/i386/context2.S index cf5b464c27d0..35768ea6232a 100644 --- a/src/coreclr/pal/src/arch/i386/context2.S +++ b/src/coreclr/pal/src/arch/i386/context2.S @@ -115,11 +115,12 @@ LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT): movdqu xmm7, [eax + CONTEXT_Xmm7] LOCAL_LABEL(Done_Restore_CONTEXT_EXTENDED_REGISTERS): - // Restore Stack - mov esp, [eax + CONTEXT_Esp] - // Create a minimal frame - push DWORD PTR [eax + CONTEXT_Eip] + mov ebx, [eax + CONTEXT_Esp] + mov ecx, [eax + CONTEXT_Eip] + mov edx, [eax + CONTEXT_Eax] + mov [ebx - 4], ecx + mov [ebx - 8], edx // Restore register(s) mov ebp, [eax + CONTEXT_Ebp] @@ -128,7 +129,13 @@ LOCAL_LABEL(Done_Restore_CONTEXT_EXTENDED_REGISTERS): mov edx, [eax + CONTEXT_Edx] mov ecx, [eax + CONTEXT_Ecx] mov ebx, [eax + CONTEXT_Ebx] - mov eax, [eax + CONTEXT_Eax] + + // Restore Stack + mov eax, [eax + CONTEXT_Esp] + sub eax, 8 + mov esp, eax + + pop eax // Resume ret diff --git a/src/coreclr/pal/src/arch/loongarch64/asmconstants.h b/src/coreclr/pal/src/arch/loongarch64/asmconstants.h index 57cf8b585ca3..3676b16fcc67 100644 --- a/src/coreclr/pal/src/arch/loongarch64/asmconstants.h +++ b/src/coreclr/pal/src/arch/loongarch64/asmconstants.h @@ -45,8 +45,8 @@ #define CONTEXT_T6 CONTEXT_T5+SIZEOF_LOONGARCH_GPR #define CONTEXT_T7 CONTEXT_T6+SIZEOF_LOONGARCH_GPR #define CONTEXT_T8 CONTEXT_T7+SIZEOF_LOONGARCH_GPR -#define CONTEXT_X0 CONTEXT_T8+SIZEOF_LOONGARCH_GPR -#define CONTEXT_Fp CONTEXT_X0+SIZEOF_LOONGARCH_GPR +#define CONTEXT_R21 CONTEXT_T8+SIZEOF_LOONGARCH_GPR +#define CONTEXT_Fp CONTEXT_R21+SIZEOF_LOONGARCH_GPR #define CONTEXT_S0 CONTEXT_Fp+SIZEOF_LOONGARCH_GPR #define CONTEXT_S1 CONTEXT_S0+SIZEOF_LOONGARCH_GPR #define CONTEXT_S2 CONTEXT_S1+SIZEOF_LOONGARCH_GPR diff --git a/src/coreclr/pal/src/arch/loongarch64/context2.S b/src/coreclr/pal/src/arch/loongarch64/context2.S index b337edb250e2..dda4f1922feb 100644 --- a/src/coreclr/pal/src/arch/loongarch64/context2.S +++ b/src/coreclr/pal/src/arch/loongarch64/context2.S @@ -132,13 +132,14 @@ LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): ld.d $ra, $t4, CONTEXT_Ra ld.d $fp, $t4, CONTEXT_Fp - ld.d $sp, $t4, CONTEXT_Sp ld.d $r21, $t4, CONTEXT_Pc - ld.d $t4, $t4, CONTEXT_T4 + ld.d $sp, $t4, CONTEXT_Sp + // NOTE: the r21 and t4 had been trashed. jirl $r0, $r21, 0 LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): + ld.d $r21, $t4, CONTEXT_R21 ld.d $t4, $t4, CONTEXT_T4 jirl $r0, $ra, 0 LEAF_END RtlRestoreContext, _TEXT @@ -202,7 +203,7 @@ LOCAL_LABEL(Done_CONTEXT_CONTROL): st.d $t6, $a0, CONTEXT_T6 st.d $t7, $a0, CONTEXT_T7 st.d $t8, $a0, CONTEXT_T8 - st.d $r21,$a0, CONTEXT_X0 + st.d $r21,$a0, CONTEXT_R21 st.d $s0, $a0, CONTEXT_S0 st.d $s1, $a0, CONTEXT_S1 st.d $s2, $a0, CONTEXT_S2 diff --git a/src/coreclr/pal/src/arch/s390x/context2.S b/src/coreclr/pal/src/arch/s390x/context2.S index a44d81c19a2e..3e7c71d5d065 100644 --- a/src/coreclr/pal/src/arch/s390x/context2.S +++ b/src/coreclr/pal/src/arch/s390x/context2.S @@ -61,7 +61,17 @@ LEAF_END RtlCaptureContext, _TEXT LEAF_ENTRY RtlRestoreContext, _TEXT + // Set %r1 and %r0 to hold the target return address and stack pointer. + // These will be installed only at the very end, to avoid potentially + // clobbering the context structure on the local stack. lgr %r1, %r14 + lgr %r0, %r15 + tm CONTEXT_ContextFlags+3(%r2), CONTEXT_CONTROL + je LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL) + // We do *not* attempt to restore the PSW mask here! + lg %r1, CONTEXT_PSWAddr(%r2) + lg %r0, CONTEXT_R15(%r2) +LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL): tm CONTEXT_ContextFlags+3(%r2), CONTEXT_FLOATING_POINT je LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT) @@ -83,19 +93,13 @@ LEAF_ENTRY RtlRestoreContext, _TEXT ld %f15, CONTEXT_F15(%r2) LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT): - tm CONTEXT_ContextFlags+3(%r2), CONTEXT_CONTROL - je LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL) - // We do *not* attempt to restore the PSW mask here! - lg %r1, CONTEXT_PSWAddr(%r2) - lg %r15, CONTEXT_R15(%r2) -LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL): - tm CONTEXT_ContextFlags+3(%r2), CONTEXT_INTEGER je LOCAL_LABEL(Done_Restore_CONTEXT_INTEGER) // We do *not* restore %r0 and %r1 here! lmg %r2, %r14, CONTEXT_R2(%r2) LOCAL_LABEL(Done_Restore_CONTEXT_INTEGER): + lgr %r15, %r0 br %r1 LEAF_END RtlRestoreContext, _TEXT diff --git a/src/coreclr/pal/src/cruntime/wchar.cpp b/src/coreclr/pal/src/cruntime/wchar.cpp index 88340538ebca..fb24f6e35c78 100644 --- a/src/coreclr/pal/src/cruntime/wchar.cpp +++ b/src/coreclr/pal/src/cruntime/wchar.cpp @@ -24,7 +24,6 @@ Module Name: #include "config.h" #endif -#include #include #include diff --git a/src/coreclr/pal/src/exception/signal.cpp b/src/coreclr/pal/src/exception/signal.cpp index 0da7f05001b9..c9112432f8d9 100644 --- a/src/coreclr/pal/src/exception/signal.cpp +++ b/src/coreclr/pal/src/exception/signal.cpp @@ -833,7 +833,7 @@ static void inject_activation_handler(int code, siginfo_t *siginfo, void *contex &winContext, contextFlags); - if (g_safeActivationCheckFunction(CONTEXTGetPC(&winContext), /* checkingCurrentThread */ TRUE)) + if (g_safeActivationCheckFunction(CONTEXTGetPC(&winContext))) { g_inject_activation_context_locvar_offset = (int)((char*)&winContext - (char*)__builtin_frame_address(0)); int savedErrNo = errno; // Make sure that errno is not modified diff --git a/src/coreclr/pal/src/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index 1712be93f698..23910c83fe0c 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -1985,8 +1985,8 @@ InternalSetFilePointerForUnixFd( { PAL_ERROR palError = NO_ERROR; int seek_whence = 0; - __int64 seek_offset = 0LL; - __int64 seek_res = 0LL; + int64_t seek_offset = 0LL; + int64_t seek_res = 0LL; off_t old_offset; switch( dwMoveMethod ) @@ -2015,7 +2015,7 @@ InternalSetFilePointerForUnixFd( if ( lpDistanceToMoveHigh ) { /* set the high 32 bits of the offset */ - seek_offset = ((__int64)*lpDistanceToMoveHigh << 32); + seek_offset = ((int64_t)*lpDistanceToMoveHigh << 32); /* set the low 32 bits */ /* cast to unsigned long to avoid sign extension */ @@ -2072,7 +2072,7 @@ InternalSetFilePointerForUnixFd( } } - seek_res = (__int64)lseek( iUnixFd, + seek_res = (int64_t)lseek( iUnixFd, seek_offset, seek_whence ); if ( seek_res < 0 ) diff --git a/src/coreclr/pal/src/file/filetime.cpp b/src/coreclr/pal/src/file/filetime.cpp index d038c9f29eb5..edff44949d6a 100644 --- a/src/coreclr/pal/src/file/filetime.cpp +++ b/src/coreclr/pal/src/file/filetime.cpp @@ -95,11 +95,11 @@ SET_DEFAULT_DEBUG_CHANNEL(FILE); This result is also confirmed in the MSDN documentation on how to convert a time_t value to a win32 FILETIME. */ -static const __int64 SECS_BETWEEN_1601_AND_1970_EPOCHS = 11644473600LL; -static const __int64 SECS_TO_100NS = 10000000; /* 10^7 */ +static const int64_t SECS_BETWEEN_1601_AND_1970_EPOCHS = 11644473600LL; +static const int64_t SECS_TO_100NS = 10000000; /* 10^7 */ #ifdef __APPLE__ -static const __int64 SECS_BETWEEN_1601_AND_2001_EPOCHS = 12622780800LL; +static const int64_t SECS_BETWEEN_1601_AND_2001_EPOCHS = 12622780800LL; #endif // __APPLE__ /*++ @@ -114,8 +114,8 @@ CompareFileTime( IN CONST FILETIME *lpFileTime1, IN CONST FILETIME *lpFileTime2) { - __int64 First; - __int64 Second; + int64_t First; + int64_t Second; long Ret; @@ -123,9 +123,9 @@ CompareFileTime( ENTRY("CompareFileTime(lpFileTime1=%p lpFileTime2=%p)\n", lpFileTime1, lpFileTime2); - First = ((__int64)lpFileTime1->dwHighDateTime << 32) + + First = ((int64_t)lpFileTime1->dwHighDateTime << 32) + lpFileTime1->dwLowDateTime; - Second = ((__int64)lpFileTime2->dwHighDateTime << 32) + + Second = ((int64_t)lpFileTime2->dwHighDateTime << 32) + lpFileTime2->dwLowDateTime; if ( First < Second ) @@ -200,10 +200,10 @@ MSDN documentation. time_t is the number of seconds elapsed since --*/ FILETIME FILEUnixTimeToFileTime( time_t sec, long nsec ) { - __int64 Result; + int64_t Result; FILETIME Ret; - Result = ((__int64)sec + SECS_BETWEEN_1601_AND_1970_EPOCHS) * SECS_TO_100NS + + Result = ((int64_t)sec + SECS_BETWEEN_1601_AND_1970_EPOCHS) * SECS_TO_100NS + (nsec / 100); Ret.dwLowDateTime = (DWORD)Result; diff --git a/src/coreclr/pal/src/include/pal/unicodedata.h b/src/coreclr/pal/src/include/pal/unicodedata.h deleted file mode 100644 index c7e9347fe066..000000000000 --- a/src/coreclr/pal/src/include/pal/unicodedata.h +++ /dev/null @@ -1,31 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#ifndef _PAL_UNICODEDATA_H_ -#define _PAL_UNICODEDATA_H_ - -#include "pal/palinternal.h" - -#ifdef __cplusplus -extern "C" -{ -#endif // __cplusplus - -#define UPPER_CASE 1 -#define LOWER_CASE 2 - -typedef struct -{ - WCHAR nUnicodeValue; - WORD nFlag; - WCHAR nOpposingCase; -} UnicodeDataRec; - -extern CONST UnicodeDataRec UnicodeData[]; -extern CONST UINT UNICODE_DATA_SIZE; - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif /* _UNICODE_DATA_H_ */ diff --git a/src/coreclr/pal/src/locale/unicode.cpp b/src/coreclr/pal/src/locale/unicode.cpp index 862f98a6b212..e966e22821ba 100644 --- a/src/coreclr/pal/src/locale/unicode.cpp +++ b/src/coreclr/pal/src/locale/unicode.cpp @@ -2,21 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. /*++ - - - Module Name: - unicode.cpp Abstract: - Implementation of all functions related to Unicode support - -Revision History: - - - --*/ #include "pal/thread.hpp" @@ -27,7 +17,6 @@ Revision History: #include #include "pal/cruntime.h" #include "pal/stackstring.hpp" -#include "pal/unicodedata.h" #include #include @@ -39,138 +28,6 @@ using namespace CorUnix; SET_DEFAULT_DEBUG_CHANNEL(UNICODE); -/*++ -Function: -UnicodeDataComp -This is the comparison function used by the bsearch function to search -for unicode characters in the UnicodeData array. - -Parameter: -pnKey -The unicode character value to search for. -elem -A pointer to a UnicodeDataRec. - -Return value: -<0 if pnKey < elem->nUnicodeValue -0 if pnKey == elem->nUnicodeValue ->0 if pnKey > elem->nUnicodeValue ---*/ -static int UnicodeDataComp(const void *pnKey, const void *elem) -{ - WCHAR uValue = ((UnicodeDataRec*)elem)->nUnicodeValue; - - if (*((INT*)pnKey) < uValue) - { - return -1; - } - else if (*((INT*)pnKey) > uValue) - { - return 1; - } - else - { - return 0; - } -} - -/*++ -Function: -GetUnicodeData -This function is used to get information about a Unicode character. - -Parameters: -nUnicodeValue -The numeric value of the Unicode character to get information about. -pDataRec -The UnicodeDataRec to fill in with the data for the Unicode character. - -Return value: -TRUE if the Unicode character was found. - ---*/ -BOOL GetUnicodeData(INT nUnicodeValue, UnicodeDataRec *pDataRec) -{ - BOOL bRet; - - UnicodeDataRec *dataRec; - INT nNumOfChars = UNICODE_DATA_SIZE; - dataRec = (UnicodeDataRec *) bsearch(&nUnicodeValue, UnicodeData, nNumOfChars, - sizeof(UnicodeDataRec), UnicodeDataComp); - if (dataRec == NULL) - { - bRet = FALSE; - } - else - { - bRet = TRUE; - *pDataRec = *dataRec; - } - return bRet; -} - -char16_t -__cdecl -PAL_ToUpperInvariant( char16_t c ) -{ - UnicodeDataRec dataRec; - - PERF_ENTRY(PAL_ToUpperInvariant); - ENTRY("PAL_ToUpperInvariant (c=%d)\n", c); - - if (!GetUnicodeData(c, &dataRec)) - { - TRACE( "Unable to retrieve unicode data for the character %c.\n", c ); - LOGEXIT("PAL_ToUpperInvariant returns int %d\n", c ); - PERF_EXIT(PAL_ToUpperInvariant); - return c; - } - - if ( dataRec.nFlag != LOWER_CASE ) - { - LOGEXIT("PAL_ToUpperInvariant returns int %d\n", c ); - PERF_EXIT(PAL_ToUpperInvariant); - return c; - } - else - { - LOGEXIT("PAL_ToUpperInvariant returns int %d\n", dataRec.nOpposingCase ); - PERF_EXIT(PAL_ToUpperInvariant); - return dataRec.nOpposingCase; - } -} - -char16_t -__cdecl -PAL_ToLowerInvariant( char16_t c ) -{ - UnicodeDataRec dataRec; - - PERF_ENTRY(PAL_ToLowerInvariant); - ENTRY("PAL_ToLowerInvariant (c=%d)\n", c); - - if (!GetUnicodeData(c, &dataRec)) - { - TRACE( "Unable to retrieve unicode data for the character %c.\n", c ); - LOGEXIT("PAL_ToLowerInvariant returns int %d\n", c ); - PERF_EXIT(PAL_ToLowerInvariant); - return c; - } - - if ( dataRec.nFlag != UPPER_CASE ) - { - LOGEXIT("PAL_ToLowerInvariant returns int %d\n", c ); - PERF_EXIT(PAL_ToLowerInvariant); - return c; - } - else - { - LOGEXIT("PAL_ToLowerInvariant returns int %d\n", dataRec.nOpposingCase ); - PERF_EXIT(PAL_ToLowerInvariant); - return dataRec.nOpposingCase; - } -} - /*++ Function: GetConsoleOutputCP diff --git a/src/coreclr/pal/src/locale/unicodedata.cpp b/src/coreclr/pal/src/locale/unicodedata.cpp deleted file mode 100644 index 74ae79819bb6..000000000000 --- a/src/coreclr/pal/src/locale/unicodedata.cpp +++ /dev/null @@ -1,2372 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "pal/unicodedata.h" - -// -// THIS FILE IS GENERATED. DO NOT HAND EDIT. -// IF YOU NEED TO UPDATE UNICODE VERSION FOLLOW THE GUIDE AT src/libraries/System.Private.CoreLib/Tools/GenUnicodeProp/Updating-Unicode-Versions.md -// - -CONST UnicodeDataRec UnicodeData[] = { - { 0x41, UPPER_CASE, 0x61 }, - { 0x42, UPPER_CASE, 0x62 }, - { 0x43, UPPER_CASE, 0x63 }, - { 0x44, UPPER_CASE, 0x64 }, - { 0x45, UPPER_CASE, 0x65 }, - { 0x46, UPPER_CASE, 0x66 }, - { 0x47, UPPER_CASE, 0x67 }, - { 0x48, UPPER_CASE, 0x68 }, - { 0x49, UPPER_CASE, 0x69 }, - { 0x4A, UPPER_CASE, 0x6A }, - { 0x4B, UPPER_CASE, 0x6B }, - { 0x4C, UPPER_CASE, 0x6C }, - { 0x4D, UPPER_CASE, 0x6D }, - { 0x4E, UPPER_CASE, 0x6E }, - { 0x4F, UPPER_CASE, 0x6F }, - { 0x50, UPPER_CASE, 0x70 }, - { 0x51, UPPER_CASE, 0x71 }, - { 0x52, UPPER_CASE, 0x72 }, - { 0x53, UPPER_CASE, 0x73 }, - { 0x54, UPPER_CASE, 0x74 }, - { 0x55, UPPER_CASE, 0x75 }, - { 0x56, UPPER_CASE, 0x76 }, - { 0x57, UPPER_CASE, 0x77 }, - { 0x58, UPPER_CASE, 0x78 }, - { 0x59, UPPER_CASE, 0x79 }, - { 0x5A, UPPER_CASE, 0x7A }, - { 0x61, LOWER_CASE, 0x41 }, - { 0x62, LOWER_CASE, 0x42 }, - { 0x63, LOWER_CASE, 0x43 }, - { 0x64, LOWER_CASE, 0x44 }, - { 0x65, LOWER_CASE, 0x45 }, - { 0x66, LOWER_CASE, 0x46 }, - { 0x67, LOWER_CASE, 0x47 }, - { 0x68, LOWER_CASE, 0x48 }, - { 0x69, LOWER_CASE, 0x49 }, - { 0x6A, LOWER_CASE, 0x4A }, - { 0x6B, LOWER_CASE, 0x4B }, - { 0x6C, LOWER_CASE, 0x4C }, - { 0x6D, LOWER_CASE, 0x4D }, - { 0x6E, LOWER_CASE, 0x4E }, - { 0x6F, LOWER_CASE, 0x4F }, - { 0x70, LOWER_CASE, 0x50 }, - { 0x71, LOWER_CASE, 0x51 }, - { 0x72, LOWER_CASE, 0x52 }, - { 0x73, LOWER_CASE, 0x53 }, - { 0x74, LOWER_CASE, 0x54 }, - { 0x75, LOWER_CASE, 0x55 }, - { 0x76, LOWER_CASE, 0x56 }, - { 0x77, LOWER_CASE, 0x57 }, - { 0x78, LOWER_CASE, 0x58 }, - { 0x79, LOWER_CASE, 0x59 }, - { 0x7A, LOWER_CASE, 0x5A }, - { 0xB5, LOWER_CASE, 0x39C }, - { 0xC0, UPPER_CASE, 0xE0 }, - { 0xC1, UPPER_CASE, 0xE1 }, - { 0xC2, UPPER_CASE, 0xE2 }, - { 0xC3, UPPER_CASE, 0xE3 }, - { 0xC4, UPPER_CASE, 0xE4 }, - { 0xC5, UPPER_CASE, 0xE5 }, - { 0xC6, UPPER_CASE, 0xE6 }, - { 0xC7, UPPER_CASE, 0xE7 }, - { 0xC8, UPPER_CASE, 0xE8 }, - { 0xC9, UPPER_CASE, 0xE9 }, - { 0xCA, UPPER_CASE, 0xEA }, - { 0xCB, UPPER_CASE, 0xEB }, - { 0xCC, UPPER_CASE, 0xEC }, - { 0xCD, UPPER_CASE, 0xED }, - { 0xCE, UPPER_CASE, 0xEE }, - { 0xCF, UPPER_CASE, 0xEF }, - { 0xD0, UPPER_CASE, 0xF0 }, - { 0xD1, UPPER_CASE, 0xF1 }, - { 0xD2, UPPER_CASE, 0xF2 }, - { 0xD3, UPPER_CASE, 0xF3 }, - { 0xD4, UPPER_CASE, 0xF4 }, - { 0xD5, UPPER_CASE, 0xF5 }, - { 0xD6, UPPER_CASE, 0xF6 }, - { 0xD8, UPPER_CASE, 0xF8 }, - { 0xD9, UPPER_CASE, 0xF9 }, - { 0xDA, UPPER_CASE, 0xFA }, - { 0xDB, UPPER_CASE, 0xFB }, - { 0xDC, UPPER_CASE, 0xFC }, - { 0xDD, UPPER_CASE, 0xFD }, - { 0xDE, UPPER_CASE, 0xFE }, - { 0xE0, LOWER_CASE, 0xC0 }, - { 0xE1, LOWER_CASE, 0xC1 }, - { 0xE2, LOWER_CASE, 0xC2 }, - { 0xE3, LOWER_CASE, 0xC3 }, - { 0xE4, LOWER_CASE, 0xC4 }, - { 0xE5, LOWER_CASE, 0xC5 }, - { 0xE6, LOWER_CASE, 0xC6 }, - { 0xE7, LOWER_CASE, 0xC7 }, - { 0xE8, LOWER_CASE, 0xC8 }, - { 0xE9, LOWER_CASE, 0xC9 }, - { 0xEA, LOWER_CASE, 0xCA }, - { 0xEB, LOWER_CASE, 0xCB }, - { 0xEC, LOWER_CASE, 0xCC }, - { 0xED, LOWER_CASE, 0xCD }, - { 0xEE, LOWER_CASE, 0xCE }, - { 0xEF, LOWER_CASE, 0xCF }, - { 0xF0, LOWER_CASE, 0xD0 }, - { 0xF1, LOWER_CASE, 0xD1 }, - { 0xF2, LOWER_CASE, 0xD2 }, - { 0xF3, LOWER_CASE, 0xD3 }, - { 0xF4, LOWER_CASE, 0xD4 }, - { 0xF5, LOWER_CASE, 0xD5 }, - { 0xF6, LOWER_CASE, 0xD6 }, - { 0xF8, LOWER_CASE, 0xD8 }, - { 0xF9, LOWER_CASE, 0xD9 }, - { 0xFA, LOWER_CASE, 0xDA }, - { 0xFB, LOWER_CASE, 0xDB }, - { 0xFC, LOWER_CASE, 0xDC }, - { 0xFD, LOWER_CASE, 0xDD }, - { 0xFE, LOWER_CASE, 0xDE }, - { 0xFF, LOWER_CASE, 0x178 }, - { 0x100, UPPER_CASE, 0x101 }, - { 0x101, LOWER_CASE, 0x100 }, - { 0x102, UPPER_CASE, 0x103 }, - { 0x103, LOWER_CASE, 0x102 }, - { 0x104, UPPER_CASE, 0x105 }, - { 0x105, LOWER_CASE, 0x104 }, - { 0x106, UPPER_CASE, 0x107 }, - { 0x107, LOWER_CASE, 0x106 }, - { 0x108, UPPER_CASE, 0x109 }, - { 0x109, LOWER_CASE, 0x108 }, - { 0x10A, UPPER_CASE, 0x10B }, - { 0x10B, LOWER_CASE, 0x10A }, - { 0x10C, UPPER_CASE, 0x10D }, - { 0x10D, LOWER_CASE, 0x10C }, - { 0x10E, UPPER_CASE, 0x10F }, - { 0x10F, LOWER_CASE, 0x10E }, - { 0x110, UPPER_CASE, 0x111 }, - { 0x111, LOWER_CASE, 0x110 }, - { 0x112, UPPER_CASE, 0x113 }, - { 0x113, LOWER_CASE, 0x112 }, - { 0x114, UPPER_CASE, 0x115 }, - { 0x115, LOWER_CASE, 0x114 }, - { 0x116, UPPER_CASE, 0x117 }, - { 0x117, LOWER_CASE, 0x116 }, - { 0x118, UPPER_CASE, 0x119 }, - { 0x119, LOWER_CASE, 0x118 }, - { 0x11A, UPPER_CASE, 0x11B }, - { 0x11B, LOWER_CASE, 0x11A }, - { 0x11C, UPPER_CASE, 0x11D }, - { 0x11D, LOWER_CASE, 0x11C }, - { 0x11E, UPPER_CASE, 0x11F }, - { 0x11F, LOWER_CASE, 0x11E }, - { 0x120, UPPER_CASE, 0x121 }, - { 0x121, LOWER_CASE, 0x120 }, - { 0x122, UPPER_CASE, 0x123 }, - { 0x123, LOWER_CASE, 0x122 }, - { 0x124, UPPER_CASE, 0x125 }, - { 0x125, LOWER_CASE, 0x124 }, - { 0x126, UPPER_CASE, 0x127 }, - { 0x127, LOWER_CASE, 0x126 }, - { 0x128, UPPER_CASE, 0x129 }, - { 0x129, LOWER_CASE, 0x128 }, - { 0x12A, UPPER_CASE, 0x12B }, - { 0x12B, LOWER_CASE, 0x12A }, - { 0x12C, UPPER_CASE, 0x12D }, - { 0x12D, LOWER_CASE, 0x12C }, - { 0x12E, UPPER_CASE, 0x12F }, - { 0x12F, LOWER_CASE, 0x12E }, - { 0x130, UPPER_CASE, 0x69 }, - { 0x131, LOWER_CASE, 0x49 }, - { 0x132, UPPER_CASE, 0x133 }, - { 0x133, LOWER_CASE, 0x132 }, - { 0x134, UPPER_CASE, 0x135 }, - { 0x135, LOWER_CASE, 0x134 }, - { 0x136, UPPER_CASE, 0x137 }, - { 0x137, LOWER_CASE, 0x136 }, - { 0x139, UPPER_CASE, 0x13A }, - { 0x13A, LOWER_CASE, 0x139 }, - { 0x13B, UPPER_CASE, 0x13C }, - { 0x13C, LOWER_CASE, 0x13B }, - { 0x13D, UPPER_CASE, 0x13E }, - { 0x13E, LOWER_CASE, 0x13D }, - { 0x13F, UPPER_CASE, 0x140 }, - { 0x140, LOWER_CASE, 0x13F }, - { 0x141, UPPER_CASE, 0x142 }, - { 0x142, LOWER_CASE, 0x141 }, - { 0x143, UPPER_CASE, 0x144 }, - { 0x144, LOWER_CASE, 0x143 }, - { 0x145, UPPER_CASE, 0x146 }, - { 0x146, LOWER_CASE, 0x145 }, - { 0x147, UPPER_CASE, 0x148 }, - { 0x148, LOWER_CASE, 0x147 }, - { 0x14A, UPPER_CASE, 0x14B }, - { 0x14B, LOWER_CASE, 0x14A }, - { 0x14C, UPPER_CASE, 0x14D }, - { 0x14D, LOWER_CASE, 0x14C }, - { 0x14E, UPPER_CASE, 0x14F }, - { 0x14F, LOWER_CASE, 0x14E }, - { 0x150, UPPER_CASE, 0x151 }, - { 0x151, LOWER_CASE, 0x150 }, - { 0x152, UPPER_CASE, 0x153 }, - { 0x153, LOWER_CASE, 0x152 }, - { 0x154, UPPER_CASE, 0x155 }, - { 0x155, LOWER_CASE, 0x154 }, - { 0x156, UPPER_CASE, 0x157 }, - { 0x157, LOWER_CASE, 0x156 }, - { 0x158, UPPER_CASE, 0x159 }, - { 0x159, LOWER_CASE, 0x158 }, - { 0x15A, UPPER_CASE, 0x15B }, - { 0x15B, LOWER_CASE, 0x15A }, - { 0x15C, UPPER_CASE, 0x15D }, - { 0x15D, LOWER_CASE, 0x15C }, - { 0x15E, UPPER_CASE, 0x15F }, - { 0x15F, LOWER_CASE, 0x15E }, - { 0x160, UPPER_CASE, 0x161 }, - { 0x161, LOWER_CASE, 0x160 }, - { 0x162, UPPER_CASE, 0x163 }, - { 0x163, LOWER_CASE, 0x162 }, - { 0x164, UPPER_CASE, 0x165 }, - { 0x165, LOWER_CASE, 0x164 }, - { 0x166, UPPER_CASE, 0x167 }, - { 0x167, LOWER_CASE, 0x166 }, - { 0x168, UPPER_CASE, 0x169 }, - { 0x169, LOWER_CASE, 0x168 }, - { 0x16A, UPPER_CASE, 0x16B }, - { 0x16B, LOWER_CASE, 0x16A }, - { 0x16C, UPPER_CASE, 0x16D }, - { 0x16D, LOWER_CASE, 0x16C }, - { 0x16E, UPPER_CASE, 0x16F }, - { 0x16F, LOWER_CASE, 0x16E }, - { 0x170, UPPER_CASE, 0x171 }, - { 0x171, LOWER_CASE, 0x170 }, - { 0x172, UPPER_CASE, 0x173 }, - { 0x173, LOWER_CASE, 0x172 }, - { 0x174, UPPER_CASE, 0x175 }, - { 0x175, LOWER_CASE, 0x174 }, - { 0x176, UPPER_CASE, 0x177 }, - { 0x177, LOWER_CASE, 0x176 }, - { 0x178, UPPER_CASE, 0xFF }, - { 0x179, UPPER_CASE, 0x17A }, - { 0x17A, LOWER_CASE, 0x179 }, - { 0x17B, UPPER_CASE, 0x17C }, - { 0x17C, LOWER_CASE, 0x17B }, - { 0x17D, UPPER_CASE, 0x17E }, - { 0x17E, LOWER_CASE, 0x17D }, - { 0x17F, LOWER_CASE, 0x53 }, - { 0x180, LOWER_CASE, 0x243 }, - { 0x181, UPPER_CASE, 0x253 }, - { 0x182, UPPER_CASE, 0x183 }, - { 0x183, LOWER_CASE, 0x182 }, - { 0x184, UPPER_CASE, 0x185 }, - { 0x185, LOWER_CASE, 0x184 }, - { 0x186, UPPER_CASE, 0x254 }, - { 0x187, UPPER_CASE, 0x188 }, - { 0x188, LOWER_CASE, 0x187 }, - { 0x189, UPPER_CASE, 0x256 }, - { 0x18A, UPPER_CASE, 0x257 }, - { 0x18B, UPPER_CASE, 0x18C }, - { 0x18C, LOWER_CASE, 0x18B }, - { 0x18E, UPPER_CASE, 0x1DD }, - { 0x18F, UPPER_CASE, 0x259 }, - { 0x190, UPPER_CASE, 0x25B }, - { 0x191, UPPER_CASE, 0x192 }, - { 0x192, LOWER_CASE, 0x191 }, - { 0x193, UPPER_CASE, 0x260 }, - { 0x194, UPPER_CASE, 0x263 }, - { 0x195, LOWER_CASE, 0x1F6 }, - { 0x196, UPPER_CASE, 0x269 }, - { 0x197, UPPER_CASE, 0x268 }, - { 0x198, UPPER_CASE, 0x199 }, - { 0x199, LOWER_CASE, 0x198 }, - { 0x19A, LOWER_CASE, 0x23D }, - { 0x19C, UPPER_CASE, 0x26F }, - { 0x19D, UPPER_CASE, 0x272 }, - { 0x19E, LOWER_CASE, 0x220 }, - { 0x19F, UPPER_CASE, 0x275 }, - { 0x1A0, UPPER_CASE, 0x1A1 }, - { 0x1A1, LOWER_CASE, 0x1A0 }, - { 0x1A2, UPPER_CASE, 0x1A3 }, - { 0x1A3, LOWER_CASE, 0x1A2 }, - { 0x1A4, UPPER_CASE, 0x1A5 }, - { 0x1A5, LOWER_CASE, 0x1A4 }, - { 0x1A6, UPPER_CASE, 0x280 }, - { 0x1A7, UPPER_CASE, 0x1A8 }, - { 0x1A8, LOWER_CASE, 0x1A7 }, - { 0x1A9, UPPER_CASE, 0x283 }, - { 0x1AC, UPPER_CASE, 0x1AD }, - { 0x1AD, LOWER_CASE, 0x1AC }, - { 0x1AE, UPPER_CASE, 0x288 }, - { 0x1AF, UPPER_CASE, 0x1B0 }, - { 0x1B0, LOWER_CASE, 0x1AF }, - { 0x1B1, UPPER_CASE, 0x28A }, - { 0x1B2, UPPER_CASE, 0x28B }, - { 0x1B3, UPPER_CASE, 0x1B4 }, - { 0x1B4, LOWER_CASE, 0x1B3 }, - { 0x1B5, UPPER_CASE, 0x1B6 }, - { 0x1B6, LOWER_CASE, 0x1B5 }, - { 0x1B7, UPPER_CASE, 0x292 }, - { 0x1B8, UPPER_CASE, 0x1B9 }, - { 0x1B9, LOWER_CASE, 0x1B8 }, - { 0x1BC, UPPER_CASE, 0x1BD }, - { 0x1BD, LOWER_CASE, 0x1BC }, - { 0x1BF, LOWER_CASE, 0x1F7 }, - { 0x1C4, UPPER_CASE, 0x1C6 }, - { 0x1C5, LOWER_CASE, 0x1C4 }, - { 0x1C6, LOWER_CASE, 0x1C4 }, - { 0x1C7, UPPER_CASE, 0x1C9 }, - { 0x1C8, LOWER_CASE, 0x1C7 }, - { 0x1C9, LOWER_CASE, 0x1C7 }, - { 0x1CA, UPPER_CASE, 0x1CC }, - { 0x1CB, LOWER_CASE, 0x1CA }, - { 0x1CC, LOWER_CASE, 0x1CA }, - { 0x1CD, UPPER_CASE, 0x1CE }, - { 0x1CE, LOWER_CASE, 0x1CD }, - { 0x1CF, UPPER_CASE, 0x1D0 }, - { 0x1D0, LOWER_CASE, 0x1CF }, - { 0x1D1, UPPER_CASE, 0x1D2 }, - { 0x1D2, LOWER_CASE, 0x1D1 }, - { 0x1D3, UPPER_CASE, 0x1D4 }, - { 0x1D4, LOWER_CASE, 0x1D3 }, - { 0x1D5, UPPER_CASE, 0x1D6 }, - { 0x1D6, LOWER_CASE, 0x1D5 }, - { 0x1D7, UPPER_CASE, 0x1D8 }, - { 0x1D8, LOWER_CASE, 0x1D7 }, - { 0x1D9, UPPER_CASE, 0x1DA }, - { 0x1DA, LOWER_CASE, 0x1D9 }, - { 0x1DB, UPPER_CASE, 0x1DC }, - { 0x1DC, LOWER_CASE, 0x1DB }, - { 0x1DD, LOWER_CASE, 0x18E }, - { 0x1DE, UPPER_CASE, 0x1DF }, - { 0x1DF, LOWER_CASE, 0x1DE }, - { 0x1E0, UPPER_CASE, 0x1E1 }, - { 0x1E1, LOWER_CASE, 0x1E0 }, - { 0x1E2, UPPER_CASE, 0x1E3 }, - { 0x1E3, LOWER_CASE, 0x1E2 }, - { 0x1E4, UPPER_CASE, 0x1E5 }, - { 0x1E5, LOWER_CASE, 0x1E4 }, - { 0x1E6, UPPER_CASE, 0x1E7 }, - { 0x1E7, LOWER_CASE, 0x1E6 }, - { 0x1E8, UPPER_CASE, 0x1E9 }, - { 0x1E9, LOWER_CASE, 0x1E8 }, - { 0x1EA, UPPER_CASE, 0x1EB }, - { 0x1EB, LOWER_CASE, 0x1EA }, - { 0x1EC, UPPER_CASE, 0x1ED }, - { 0x1ED, LOWER_CASE, 0x1EC }, - { 0x1EE, UPPER_CASE, 0x1EF }, - { 0x1EF, LOWER_CASE, 0x1EE }, - { 0x1F1, UPPER_CASE, 0x1F3 }, - { 0x1F2, LOWER_CASE, 0x1F1 }, - { 0x1F3, LOWER_CASE, 0x1F1 }, - { 0x1F4, UPPER_CASE, 0x1F5 }, - { 0x1F5, LOWER_CASE, 0x1F4 }, - { 0x1F6, UPPER_CASE, 0x195 }, - { 0x1F7, UPPER_CASE, 0x1BF }, - { 0x1F8, UPPER_CASE, 0x1F9 }, - { 0x1F9, LOWER_CASE, 0x1F8 }, - { 0x1FA, UPPER_CASE, 0x1FB }, - { 0x1FB, LOWER_CASE, 0x1FA }, - { 0x1FC, UPPER_CASE, 0x1FD }, - { 0x1FD, LOWER_CASE, 0x1FC }, - { 0x1FE, UPPER_CASE, 0x1FF }, - { 0x1FF, LOWER_CASE, 0x1FE }, - { 0x200, UPPER_CASE, 0x201 }, - { 0x201, LOWER_CASE, 0x200 }, - { 0x202, UPPER_CASE, 0x203 }, - { 0x203, LOWER_CASE, 0x202 }, - { 0x204, UPPER_CASE, 0x205 }, - { 0x205, LOWER_CASE, 0x204 }, - { 0x206, UPPER_CASE, 0x207 }, - { 0x207, LOWER_CASE, 0x206 }, - { 0x208, UPPER_CASE, 0x209 }, - { 0x209, LOWER_CASE, 0x208 }, - { 0x20A, UPPER_CASE, 0x20B }, - { 0x20B, LOWER_CASE, 0x20A }, - { 0x20C, UPPER_CASE, 0x20D }, - { 0x20D, LOWER_CASE, 0x20C }, - { 0x20E, UPPER_CASE, 0x20F }, - { 0x20F, LOWER_CASE, 0x20E }, - { 0x210, UPPER_CASE, 0x211 }, - { 0x211, LOWER_CASE, 0x210 }, - { 0x212, UPPER_CASE, 0x213 }, - { 0x213, LOWER_CASE, 0x212 }, - { 0x214, UPPER_CASE, 0x215 }, - { 0x215, LOWER_CASE, 0x214 }, - { 0x216, UPPER_CASE, 0x217 }, - { 0x217, LOWER_CASE, 0x216 }, - { 0x218, UPPER_CASE, 0x219 }, - { 0x219, LOWER_CASE, 0x218 }, - { 0x21A, UPPER_CASE, 0x21B }, - { 0x21B, LOWER_CASE, 0x21A }, - { 0x21C, UPPER_CASE, 0x21D }, - { 0x21D, LOWER_CASE, 0x21C }, - { 0x21E, UPPER_CASE, 0x21F }, - { 0x21F, LOWER_CASE, 0x21E }, - { 0x220, UPPER_CASE, 0x19E }, - { 0x222, UPPER_CASE, 0x223 }, - { 0x223, LOWER_CASE, 0x222 }, - { 0x224, UPPER_CASE, 0x225 }, - { 0x225, LOWER_CASE, 0x224 }, - { 0x226, UPPER_CASE, 0x227 }, - { 0x227, LOWER_CASE, 0x226 }, - { 0x228, UPPER_CASE, 0x229 }, - { 0x229, LOWER_CASE, 0x228 }, - { 0x22A, UPPER_CASE, 0x22B }, - { 0x22B, LOWER_CASE, 0x22A }, - { 0x22C, UPPER_CASE, 0x22D }, - { 0x22D, LOWER_CASE, 0x22C }, - { 0x22E, UPPER_CASE, 0x22F }, - { 0x22F, LOWER_CASE, 0x22E }, - { 0x230, UPPER_CASE, 0x231 }, - { 0x231, LOWER_CASE, 0x230 }, - { 0x232, UPPER_CASE, 0x233 }, - { 0x233, LOWER_CASE, 0x232 }, - { 0x23A, UPPER_CASE, 0x2C65 }, - { 0x23B, UPPER_CASE, 0x23C }, - { 0x23C, LOWER_CASE, 0x23B }, - { 0x23D, UPPER_CASE, 0x19A }, - { 0x23E, UPPER_CASE, 0x2C66 }, - { 0x23F, LOWER_CASE, 0x2C7E }, - { 0x240, LOWER_CASE, 0x2C7F }, - { 0x241, UPPER_CASE, 0x242 }, - { 0x242, LOWER_CASE, 0x241 }, - { 0x243, UPPER_CASE, 0x180 }, - { 0x244, UPPER_CASE, 0x289 }, - { 0x245, UPPER_CASE, 0x28C }, - { 0x246, UPPER_CASE, 0x247 }, - { 0x247, LOWER_CASE, 0x246 }, - { 0x248, UPPER_CASE, 0x249 }, - { 0x249, LOWER_CASE, 0x248 }, - { 0x24A, UPPER_CASE, 0x24B }, - { 0x24B, LOWER_CASE, 0x24A }, - { 0x24C, UPPER_CASE, 0x24D }, - { 0x24D, LOWER_CASE, 0x24C }, - { 0x24E, UPPER_CASE, 0x24F }, - { 0x24F, LOWER_CASE, 0x24E }, - { 0x250, LOWER_CASE, 0x2C6F }, - { 0x251, LOWER_CASE, 0x2C6D }, - { 0x252, LOWER_CASE, 0x2C70 }, - { 0x253, LOWER_CASE, 0x181 }, - { 0x254, LOWER_CASE, 0x186 }, - { 0x256, LOWER_CASE, 0x189 }, - { 0x257, LOWER_CASE, 0x18A }, - { 0x259, LOWER_CASE, 0x18F }, - { 0x25B, LOWER_CASE, 0x190 }, - { 0x25C, LOWER_CASE, 0xA7AB }, - { 0x260, LOWER_CASE, 0x193 }, - { 0x261, LOWER_CASE, 0xA7AC }, - { 0x263, LOWER_CASE, 0x194 }, - { 0x265, LOWER_CASE, 0xA78D }, - { 0x266, LOWER_CASE, 0xA7AA }, - { 0x268, LOWER_CASE, 0x197 }, - { 0x269, LOWER_CASE, 0x196 }, - { 0x26A, LOWER_CASE, 0xA7AE }, - { 0x26B, LOWER_CASE, 0x2C62 }, - { 0x26C, LOWER_CASE, 0xA7AD }, - { 0x26F, LOWER_CASE, 0x19C }, - { 0x271, LOWER_CASE, 0x2C6E }, - { 0x272, LOWER_CASE, 0x19D }, - { 0x275, LOWER_CASE, 0x19F }, - { 0x27D, LOWER_CASE, 0x2C64 }, - { 0x280, LOWER_CASE, 0x1A6 }, - { 0x282, LOWER_CASE, 0xA7C5 }, - { 0x283, LOWER_CASE, 0x1A9 }, - { 0x287, LOWER_CASE, 0xA7B1 }, - { 0x288, LOWER_CASE, 0x1AE }, - { 0x289, LOWER_CASE, 0x244 }, - { 0x28A, LOWER_CASE, 0x1B1 }, - { 0x28B, LOWER_CASE, 0x1B2 }, - { 0x28C, LOWER_CASE, 0x245 }, - { 0x292, LOWER_CASE, 0x1B7 }, - { 0x29D, LOWER_CASE, 0xA7B2 }, - { 0x29E, LOWER_CASE, 0xA7B0 }, - { 0x345, LOWER_CASE, 0x399 }, - { 0x370, UPPER_CASE, 0x371 }, - { 0x371, LOWER_CASE, 0x370 }, - { 0x372, UPPER_CASE, 0x373 }, - { 0x373, LOWER_CASE, 0x372 }, - { 0x376, UPPER_CASE, 0x377 }, - { 0x377, LOWER_CASE, 0x376 }, - { 0x37B, LOWER_CASE, 0x3FD }, - { 0x37C, LOWER_CASE, 0x3FE }, - { 0x37D, LOWER_CASE, 0x3FF }, - { 0x37F, UPPER_CASE, 0x3F3 }, - { 0x386, UPPER_CASE, 0x3AC }, - { 0x388, UPPER_CASE, 0x3AD }, - { 0x389, UPPER_CASE, 0x3AE }, - { 0x38A, UPPER_CASE, 0x3AF }, - { 0x38C, UPPER_CASE, 0x3CC }, - { 0x38E, UPPER_CASE, 0x3CD }, - { 0x38F, UPPER_CASE, 0x3CE }, - { 0x391, UPPER_CASE, 0x3B1 }, - { 0x392, UPPER_CASE, 0x3B2 }, - { 0x393, UPPER_CASE, 0x3B3 }, - { 0x394, UPPER_CASE, 0x3B4 }, - { 0x395, UPPER_CASE, 0x3B5 }, - { 0x396, UPPER_CASE, 0x3B6 }, - { 0x397, UPPER_CASE, 0x3B7 }, - { 0x398, UPPER_CASE, 0x3B8 }, - { 0x399, UPPER_CASE, 0x3B9 }, - { 0x39A, UPPER_CASE, 0x3BA }, - { 0x39B, UPPER_CASE, 0x3BB }, - { 0x39C, UPPER_CASE, 0x3BC }, - { 0x39D, UPPER_CASE, 0x3BD }, - { 0x39E, UPPER_CASE, 0x3BE }, - { 0x39F, UPPER_CASE, 0x3BF }, - { 0x3A0, UPPER_CASE, 0x3C0 }, - { 0x3A1, UPPER_CASE, 0x3C1 }, - { 0x3A3, UPPER_CASE, 0x3C3 }, - { 0x3A4, UPPER_CASE, 0x3C4 }, - { 0x3A5, UPPER_CASE, 0x3C5 }, - { 0x3A6, UPPER_CASE, 0x3C6 }, - { 0x3A7, UPPER_CASE, 0x3C7 }, - { 0x3A8, UPPER_CASE, 0x3C8 }, - { 0x3A9, UPPER_CASE, 0x3C9 }, - { 0x3AA, UPPER_CASE, 0x3CA }, - { 0x3AB, UPPER_CASE, 0x3CB }, - { 0x3AC, LOWER_CASE, 0x386 }, - { 0x3AD, LOWER_CASE, 0x388 }, - { 0x3AE, LOWER_CASE, 0x389 }, - { 0x3AF, LOWER_CASE, 0x38A }, - { 0x3B1, LOWER_CASE, 0x391 }, - { 0x3B2, LOWER_CASE, 0x392 }, - { 0x3B3, LOWER_CASE, 0x393 }, - { 0x3B4, LOWER_CASE, 0x394 }, - { 0x3B5, LOWER_CASE, 0x395 }, - { 0x3B6, LOWER_CASE, 0x396 }, - { 0x3B7, LOWER_CASE, 0x397 }, - { 0x3B8, LOWER_CASE, 0x398 }, - { 0x3B9, LOWER_CASE, 0x399 }, - { 0x3BA, LOWER_CASE, 0x39A }, - { 0x3BB, LOWER_CASE, 0x39B }, - { 0x3BC, LOWER_CASE, 0x39C }, - { 0x3BD, LOWER_CASE, 0x39D }, - { 0x3BE, LOWER_CASE, 0x39E }, - { 0x3BF, LOWER_CASE, 0x39F }, - { 0x3C0, LOWER_CASE, 0x3A0 }, - { 0x3C1, LOWER_CASE, 0x3A1 }, - { 0x3C2, LOWER_CASE, 0x3A3 }, - { 0x3C3, LOWER_CASE, 0x3A3 }, - { 0x3C4, LOWER_CASE, 0x3A4 }, - { 0x3C5, LOWER_CASE, 0x3A5 }, - { 0x3C6, LOWER_CASE, 0x3A6 }, - { 0x3C7, LOWER_CASE, 0x3A7 }, - { 0x3C8, LOWER_CASE, 0x3A8 }, - { 0x3C9, LOWER_CASE, 0x3A9 }, - { 0x3CA, LOWER_CASE, 0x3AA }, - { 0x3CB, LOWER_CASE, 0x3AB }, - { 0x3CC, LOWER_CASE, 0x38C }, - { 0x3CD, LOWER_CASE, 0x38E }, - { 0x3CE, LOWER_CASE, 0x38F }, - { 0x3CF, UPPER_CASE, 0x3D7 }, - { 0x3D0, LOWER_CASE, 0x392 }, - { 0x3D1, LOWER_CASE, 0x398 }, - { 0x3D5, LOWER_CASE, 0x3A6 }, - { 0x3D6, LOWER_CASE, 0x3A0 }, - { 0x3D7, LOWER_CASE, 0x3CF }, - { 0x3D8, UPPER_CASE, 0x3D9 }, - { 0x3D9, LOWER_CASE, 0x3D8 }, - { 0x3DA, UPPER_CASE, 0x3DB }, - { 0x3DB, LOWER_CASE, 0x3DA }, - { 0x3DC, UPPER_CASE, 0x3DD }, - { 0x3DD, LOWER_CASE, 0x3DC }, - { 0x3DE, UPPER_CASE, 0x3DF }, - { 0x3DF, LOWER_CASE, 0x3DE }, - { 0x3E0, UPPER_CASE, 0x3E1 }, - { 0x3E1, LOWER_CASE, 0x3E0 }, - { 0x3E2, UPPER_CASE, 0x3E3 }, - { 0x3E3, LOWER_CASE, 0x3E2 }, - { 0x3E4, UPPER_CASE, 0x3E5 }, - { 0x3E5, LOWER_CASE, 0x3E4 }, - { 0x3E6, UPPER_CASE, 0x3E7 }, - { 0x3E7, LOWER_CASE, 0x3E6 }, - { 0x3E8, UPPER_CASE, 0x3E9 }, - { 0x3E9, LOWER_CASE, 0x3E8 }, - { 0x3EA, UPPER_CASE, 0x3EB }, - { 0x3EB, LOWER_CASE, 0x3EA }, - { 0x3EC, UPPER_CASE, 0x3ED }, - { 0x3ED, LOWER_CASE, 0x3EC }, - { 0x3EE, UPPER_CASE, 0x3EF }, - { 0x3EF, LOWER_CASE, 0x3EE }, - { 0x3F0, LOWER_CASE, 0x39A }, - { 0x3F1, LOWER_CASE, 0x3A1 }, - { 0x3F2, LOWER_CASE, 0x3F9 }, - { 0x3F3, LOWER_CASE, 0x37F }, - { 0x3F4, UPPER_CASE, 0x3B8 }, - { 0x3F5, LOWER_CASE, 0x395 }, - { 0x3F7, UPPER_CASE, 0x3F8 }, - { 0x3F8, LOWER_CASE, 0x3F7 }, - { 0x3F9, UPPER_CASE, 0x3F2 }, - { 0x3FA, UPPER_CASE, 0x3FB }, - { 0x3FB, LOWER_CASE, 0x3FA }, - { 0x3FD, UPPER_CASE, 0x37B }, - { 0x3FE, UPPER_CASE, 0x37C }, - { 0x3FF, UPPER_CASE, 0x37D }, - { 0x400, UPPER_CASE, 0x450 }, - { 0x401, UPPER_CASE, 0x451 }, - { 0x402, UPPER_CASE, 0x452 }, - { 0x403, UPPER_CASE, 0x453 }, - { 0x404, UPPER_CASE, 0x454 }, - { 0x405, UPPER_CASE, 0x455 }, - { 0x406, UPPER_CASE, 0x456 }, - { 0x407, UPPER_CASE, 0x457 }, - { 0x408, UPPER_CASE, 0x458 }, - { 0x409, UPPER_CASE, 0x459 }, - { 0x40A, UPPER_CASE, 0x45A }, - { 0x40B, UPPER_CASE, 0x45B }, - { 0x40C, UPPER_CASE, 0x45C }, - { 0x40D, UPPER_CASE, 0x45D }, - { 0x40E, UPPER_CASE, 0x45E }, - { 0x40F, UPPER_CASE, 0x45F }, - { 0x410, UPPER_CASE, 0x430 }, - { 0x411, UPPER_CASE, 0x431 }, - { 0x412, UPPER_CASE, 0x432 }, - { 0x413, UPPER_CASE, 0x433 }, - { 0x414, UPPER_CASE, 0x434 }, - { 0x415, UPPER_CASE, 0x435 }, - { 0x416, UPPER_CASE, 0x436 }, - { 0x417, UPPER_CASE, 0x437 }, - { 0x418, UPPER_CASE, 0x438 }, - { 0x419, UPPER_CASE, 0x439 }, - { 0x41A, UPPER_CASE, 0x43A }, - { 0x41B, UPPER_CASE, 0x43B }, - { 0x41C, UPPER_CASE, 0x43C }, - { 0x41D, UPPER_CASE, 0x43D }, - { 0x41E, UPPER_CASE, 0x43E }, - { 0x41F, UPPER_CASE, 0x43F }, - { 0x420, UPPER_CASE, 0x440 }, - { 0x421, UPPER_CASE, 0x441 }, - { 0x422, UPPER_CASE, 0x442 }, - { 0x423, UPPER_CASE, 0x443 }, - { 0x424, UPPER_CASE, 0x444 }, - { 0x425, UPPER_CASE, 0x445 }, - { 0x426, UPPER_CASE, 0x446 }, - { 0x427, UPPER_CASE, 0x447 }, - { 0x428, UPPER_CASE, 0x448 }, - { 0x429, UPPER_CASE, 0x449 }, - { 0x42A, UPPER_CASE, 0x44A }, - { 0x42B, UPPER_CASE, 0x44B }, - { 0x42C, UPPER_CASE, 0x44C }, - { 0x42D, UPPER_CASE, 0x44D }, - { 0x42E, UPPER_CASE, 0x44E }, - { 0x42F, UPPER_CASE, 0x44F }, - { 0x430, LOWER_CASE, 0x410 }, - { 0x431, LOWER_CASE, 0x411 }, - { 0x432, LOWER_CASE, 0x412 }, - { 0x433, LOWER_CASE, 0x413 }, - { 0x434, LOWER_CASE, 0x414 }, - { 0x435, LOWER_CASE, 0x415 }, - { 0x436, LOWER_CASE, 0x416 }, - { 0x437, LOWER_CASE, 0x417 }, - { 0x438, LOWER_CASE, 0x418 }, - { 0x439, LOWER_CASE, 0x419 }, - { 0x43A, LOWER_CASE, 0x41A }, - { 0x43B, LOWER_CASE, 0x41B }, - { 0x43C, LOWER_CASE, 0x41C }, - { 0x43D, LOWER_CASE, 0x41D }, - { 0x43E, LOWER_CASE, 0x41E }, - { 0x43F, LOWER_CASE, 0x41F }, - { 0x440, LOWER_CASE, 0x420 }, - { 0x441, LOWER_CASE, 0x421 }, - { 0x442, LOWER_CASE, 0x422 }, - { 0x443, LOWER_CASE, 0x423 }, - { 0x444, LOWER_CASE, 0x424 }, - { 0x445, LOWER_CASE, 0x425 }, - { 0x446, LOWER_CASE, 0x426 }, - { 0x447, LOWER_CASE, 0x427 }, - { 0x448, LOWER_CASE, 0x428 }, - { 0x449, LOWER_CASE, 0x429 }, - { 0x44A, LOWER_CASE, 0x42A }, - { 0x44B, LOWER_CASE, 0x42B }, - { 0x44C, LOWER_CASE, 0x42C }, - { 0x44D, LOWER_CASE, 0x42D }, - { 0x44E, LOWER_CASE, 0x42E }, - { 0x44F, LOWER_CASE, 0x42F }, - { 0x450, LOWER_CASE, 0x400 }, - { 0x451, LOWER_CASE, 0x401 }, - { 0x452, LOWER_CASE, 0x402 }, - { 0x453, LOWER_CASE, 0x403 }, - { 0x454, LOWER_CASE, 0x404 }, - { 0x455, LOWER_CASE, 0x405 }, - { 0x456, LOWER_CASE, 0x406 }, - { 0x457, LOWER_CASE, 0x407 }, - { 0x458, LOWER_CASE, 0x408 }, - { 0x459, LOWER_CASE, 0x409 }, - { 0x45A, LOWER_CASE, 0x40A }, - { 0x45B, LOWER_CASE, 0x40B }, - { 0x45C, LOWER_CASE, 0x40C }, - { 0x45D, LOWER_CASE, 0x40D }, - { 0x45E, LOWER_CASE, 0x40E }, - { 0x45F, LOWER_CASE, 0x40F }, - { 0x460, UPPER_CASE, 0x461 }, - { 0x461, LOWER_CASE, 0x460 }, - { 0x462, UPPER_CASE, 0x463 }, - { 0x463, LOWER_CASE, 0x462 }, - { 0x464, UPPER_CASE, 0x465 }, - { 0x465, LOWER_CASE, 0x464 }, - { 0x466, UPPER_CASE, 0x467 }, - { 0x467, LOWER_CASE, 0x466 }, - { 0x468, UPPER_CASE, 0x469 }, - { 0x469, LOWER_CASE, 0x468 }, - { 0x46A, UPPER_CASE, 0x46B }, - { 0x46B, LOWER_CASE, 0x46A }, - { 0x46C, UPPER_CASE, 0x46D }, - { 0x46D, LOWER_CASE, 0x46C }, - { 0x46E, UPPER_CASE, 0x46F }, - { 0x46F, LOWER_CASE, 0x46E }, - { 0x470, UPPER_CASE, 0x471 }, - { 0x471, LOWER_CASE, 0x470 }, - { 0x472, UPPER_CASE, 0x473 }, - { 0x473, LOWER_CASE, 0x472 }, - { 0x474, UPPER_CASE, 0x475 }, - { 0x475, LOWER_CASE, 0x474 }, - { 0x476, UPPER_CASE, 0x477 }, - { 0x477, LOWER_CASE, 0x476 }, - { 0x478, UPPER_CASE, 0x479 }, - { 0x479, LOWER_CASE, 0x478 }, - { 0x47A, UPPER_CASE, 0x47B }, - { 0x47B, LOWER_CASE, 0x47A }, - { 0x47C, UPPER_CASE, 0x47D }, - { 0x47D, LOWER_CASE, 0x47C }, - { 0x47E, UPPER_CASE, 0x47F }, - { 0x47F, LOWER_CASE, 0x47E }, - { 0x480, UPPER_CASE, 0x481 }, - { 0x481, LOWER_CASE, 0x480 }, - { 0x48A, UPPER_CASE, 0x48B }, - { 0x48B, LOWER_CASE, 0x48A }, - { 0x48C, UPPER_CASE, 0x48D }, - { 0x48D, LOWER_CASE, 0x48C }, - { 0x48E, UPPER_CASE, 0x48F }, - { 0x48F, LOWER_CASE, 0x48E }, - { 0x490, UPPER_CASE, 0x491 }, - { 0x491, LOWER_CASE, 0x490 }, - { 0x492, UPPER_CASE, 0x493 }, - { 0x493, LOWER_CASE, 0x492 }, - { 0x494, UPPER_CASE, 0x495 }, - { 0x495, LOWER_CASE, 0x494 }, - { 0x496, UPPER_CASE, 0x497 }, - { 0x497, LOWER_CASE, 0x496 }, - { 0x498, UPPER_CASE, 0x499 }, - { 0x499, LOWER_CASE, 0x498 }, - { 0x49A, UPPER_CASE, 0x49B }, - { 0x49B, LOWER_CASE, 0x49A }, - { 0x49C, UPPER_CASE, 0x49D }, - { 0x49D, LOWER_CASE, 0x49C }, - { 0x49E, UPPER_CASE, 0x49F }, - { 0x49F, LOWER_CASE, 0x49E }, - { 0x4A0, UPPER_CASE, 0x4A1 }, - { 0x4A1, LOWER_CASE, 0x4A0 }, - { 0x4A2, UPPER_CASE, 0x4A3 }, - { 0x4A3, LOWER_CASE, 0x4A2 }, - { 0x4A4, UPPER_CASE, 0x4A5 }, - { 0x4A5, LOWER_CASE, 0x4A4 }, - { 0x4A6, UPPER_CASE, 0x4A7 }, - { 0x4A7, LOWER_CASE, 0x4A6 }, - { 0x4A8, UPPER_CASE, 0x4A9 }, - { 0x4A9, LOWER_CASE, 0x4A8 }, - { 0x4AA, UPPER_CASE, 0x4AB }, - { 0x4AB, LOWER_CASE, 0x4AA }, - { 0x4AC, UPPER_CASE, 0x4AD }, - { 0x4AD, LOWER_CASE, 0x4AC }, - { 0x4AE, UPPER_CASE, 0x4AF }, - { 0x4AF, LOWER_CASE, 0x4AE }, - { 0x4B0, UPPER_CASE, 0x4B1 }, - { 0x4B1, LOWER_CASE, 0x4B0 }, - { 0x4B2, UPPER_CASE, 0x4B3 }, - { 0x4B3, LOWER_CASE, 0x4B2 }, - { 0x4B4, UPPER_CASE, 0x4B5 }, - { 0x4B5, LOWER_CASE, 0x4B4 }, - { 0x4B6, UPPER_CASE, 0x4B7 }, - { 0x4B7, LOWER_CASE, 0x4B6 }, - { 0x4B8, UPPER_CASE, 0x4B9 }, - { 0x4B9, LOWER_CASE, 0x4B8 }, - { 0x4BA, UPPER_CASE, 0x4BB }, - { 0x4BB, LOWER_CASE, 0x4BA }, - { 0x4BC, UPPER_CASE, 0x4BD }, - { 0x4BD, LOWER_CASE, 0x4BC }, - { 0x4BE, UPPER_CASE, 0x4BF }, - { 0x4BF, LOWER_CASE, 0x4BE }, - { 0x4C0, UPPER_CASE, 0x4CF }, - { 0x4C1, UPPER_CASE, 0x4C2 }, - { 0x4C2, LOWER_CASE, 0x4C1 }, - { 0x4C3, UPPER_CASE, 0x4C4 }, - { 0x4C4, LOWER_CASE, 0x4C3 }, - { 0x4C5, UPPER_CASE, 0x4C6 }, - { 0x4C6, LOWER_CASE, 0x4C5 }, - { 0x4C7, UPPER_CASE, 0x4C8 }, - { 0x4C8, LOWER_CASE, 0x4C7 }, - { 0x4C9, UPPER_CASE, 0x4CA }, - { 0x4CA, LOWER_CASE, 0x4C9 }, - { 0x4CB, UPPER_CASE, 0x4CC }, - { 0x4CC, LOWER_CASE, 0x4CB }, - { 0x4CD, UPPER_CASE, 0x4CE }, - { 0x4CE, LOWER_CASE, 0x4CD }, - { 0x4CF, LOWER_CASE, 0x4C0 }, - { 0x4D0, UPPER_CASE, 0x4D1 }, - { 0x4D1, LOWER_CASE, 0x4D0 }, - { 0x4D2, UPPER_CASE, 0x4D3 }, - { 0x4D3, LOWER_CASE, 0x4D2 }, - { 0x4D4, UPPER_CASE, 0x4D5 }, - { 0x4D5, LOWER_CASE, 0x4D4 }, - { 0x4D6, UPPER_CASE, 0x4D7 }, - { 0x4D7, LOWER_CASE, 0x4D6 }, - { 0x4D8, UPPER_CASE, 0x4D9 }, - { 0x4D9, LOWER_CASE, 0x4D8 }, - { 0x4DA, UPPER_CASE, 0x4DB }, - { 0x4DB, LOWER_CASE, 0x4DA }, - { 0x4DC, UPPER_CASE, 0x4DD }, - { 0x4DD, LOWER_CASE, 0x4DC }, - { 0x4DE, UPPER_CASE, 0x4DF }, - { 0x4DF, LOWER_CASE, 0x4DE }, - { 0x4E0, UPPER_CASE, 0x4E1 }, - { 0x4E1, LOWER_CASE, 0x4E0 }, - { 0x4E2, UPPER_CASE, 0x4E3 }, - { 0x4E3, LOWER_CASE, 0x4E2 }, - { 0x4E4, UPPER_CASE, 0x4E5 }, - { 0x4E5, LOWER_CASE, 0x4E4 }, - { 0x4E6, UPPER_CASE, 0x4E7 }, - { 0x4E7, LOWER_CASE, 0x4E6 }, - { 0x4E8, UPPER_CASE, 0x4E9 }, - { 0x4E9, LOWER_CASE, 0x4E8 }, - { 0x4EA, UPPER_CASE, 0x4EB }, - { 0x4EB, LOWER_CASE, 0x4EA }, - { 0x4EC, UPPER_CASE, 0x4ED }, - { 0x4ED, LOWER_CASE, 0x4EC }, - { 0x4EE, UPPER_CASE, 0x4EF }, - { 0x4EF, LOWER_CASE, 0x4EE }, - { 0x4F0, UPPER_CASE, 0x4F1 }, - { 0x4F1, LOWER_CASE, 0x4F0 }, - { 0x4F2, UPPER_CASE, 0x4F3 }, - { 0x4F3, LOWER_CASE, 0x4F2 }, - { 0x4F4, UPPER_CASE, 0x4F5 }, - { 0x4F5, LOWER_CASE, 0x4F4 }, - { 0x4F6, UPPER_CASE, 0x4F7 }, - { 0x4F7, LOWER_CASE, 0x4F6 }, - { 0x4F8, UPPER_CASE, 0x4F9 }, - { 0x4F9, LOWER_CASE, 0x4F8 }, - { 0x4FA, UPPER_CASE, 0x4FB }, - { 0x4FB, LOWER_CASE, 0x4FA }, - { 0x4FC, UPPER_CASE, 0x4FD }, - { 0x4FD, LOWER_CASE, 0x4FC }, - { 0x4FE, UPPER_CASE, 0x4FF }, - { 0x4FF, LOWER_CASE, 0x4FE }, - { 0x500, UPPER_CASE, 0x501 }, - { 0x501, LOWER_CASE, 0x500 }, - { 0x502, UPPER_CASE, 0x503 }, - { 0x503, LOWER_CASE, 0x502 }, - { 0x504, UPPER_CASE, 0x505 }, - { 0x505, LOWER_CASE, 0x504 }, - { 0x506, UPPER_CASE, 0x507 }, - { 0x507, LOWER_CASE, 0x506 }, - { 0x508, UPPER_CASE, 0x509 }, - { 0x509, LOWER_CASE, 0x508 }, - { 0x50A, UPPER_CASE, 0x50B }, - { 0x50B, LOWER_CASE, 0x50A }, - { 0x50C, UPPER_CASE, 0x50D }, - { 0x50D, LOWER_CASE, 0x50C }, - { 0x50E, UPPER_CASE, 0x50F }, - { 0x50F, LOWER_CASE, 0x50E }, - { 0x510, UPPER_CASE, 0x511 }, - { 0x511, LOWER_CASE, 0x510 }, - { 0x512, UPPER_CASE, 0x513 }, - { 0x513, LOWER_CASE, 0x512 }, - { 0x514, UPPER_CASE, 0x515 }, - { 0x515, LOWER_CASE, 0x514 }, - { 0x516, UPPER_CASE, 0x517 }, - { 0x517, LOWER_CASE, 0x516 }, - { 0x518, UPPER_CASE, 0x519 }, - { 0x519, LOWER_CASE, 0x518 }, - { 0x51A, UPPER_CASE, 0x51B }, - { 0x51B, LOWER_CASE, 0x51A }, - { 0x51C, UPPER_CASE, 0x51D }, - { 0x51D, LOWER_CASE, 0x51C }, - { 0x51E, UPPER_CASE, 0x51F }, - { 0x51F, LOWER_CASE, 0x51E }, - { 0x520, UPPER_CASE, 0x521 }, - { 0x521, LOWER_CASE, 0x520 }, - { 0x522, UPPER_CASE, 0x523 }, - { 0x523, LOWER_CASE, 0x522 }, - { 0x524, UPPER_CASE, 0x525 }, - { 0x525, LOWER_CASE, 0x524 }, - { 0x526, UPPER_CASE, 0x527 }, - { 0x527, LOWER_CASE, 0x526 }, - { 0x528, UPPER_CASE, 0x529 }, - { 0x529, LOWER_CASE, 0x528 }, - { 0x52A, UPPER_CASE, 0x52B }, - { 0x52B, LOWER_CASE, 0x52A }, - { 0x52C, UPPER_CASE, 0x52D }, - { 0x52D, LOWER_CASE, 0x52C }, - { 0x52E, UPPER_CASE, 0x52F }, - { 0x52F, LOWER_CASE, 0x52E }, - { 0x531, UPPER_CASE, 0x561 }, - { 0x532, UPPER_CASE, 0x562 }, - { 0x533, UPPER_CASE, 0x563 }, - { 0x534, UPPER_CASE, 0x564 }, - { 0x535, UPPER_CASE, 0x565 }, - { 0x536, UPPER_CASE, 0x566 }, - { 0x537, UPPER_CASE, 0x567 }, - { 0x538, UPPER_CASE, 0x568 }, - { 0x539, UPPER_CASE, 0x569 }, - { 0x53A, UPPER_CASE, 0x56A }, - { 0x53B, UPPER_CASE, 0x56B }, - { 0x53C, UPPER_CASE, 0x56C }, - { 0x53D, UPPER_CASE, 0x56D }, - { 0x53E, UPPER_CASE, 0x56E }, - { 0x53F, UPPER_CASE, 0x56F }, - { 0x540, UPPER_CASE, 0x570 }, - { 0x541, UPPER_CASE, 0x571 }, - { 0x542, UPPER_CASE, 0x572 }, - { 0x543, UPPER_CASE, 0x573 }, - { 0x544, UPPER_CASE, 0x574 }, - { 0x545, UPPER_CASE, 0x575 }, - { 0x546, UPPER_CASE, 0x576 }, - { 0x547, UPPER_CASE, 0x577 }, - { 0x548, UPPER_CASE, 0x578 }, - { 0x549, UPPER_CASE, 0x579 }, - { 0x54A, UPPER_CASE, 0x57A }, - { 0x54B, UPPER_CASE, 0x57B }, - { 0x54C, UPPER_CASE, 0x57C }, - { 0x54D, UPPER_CASE, 0x57D }, - { 0x54E, UPPER_CASE, 0x57E }, - { 0x54F, UPPER_CASE, 0x57F }, - { 0x550, UPPER_CASE, 0x580 }, - { 0x551, UPPER_CASE, 0x581 }, - { 0x552, UPPER_CASE, 0x582 }, - { 0x553, UPPER_CASE, 0x583 }, - { 0x554, UPPER_CASE, 0x584 }, - { 0x555, UPPER_CASE, 0x585 }, - { 0x556, UPPER_CASE, 0x586 }, - { 0x561, LOWER_CASE, 0x531 }, - { 0x562, LOWER_CASE, 0x532 }, - { 0x563, LOWER_CASE, 0x533 }, - { 0x564, LOWER_CASE, 0x534 }, - { 0x565, LOWER_CASE, 0x535 }, - { 0x566, LOWER_CASE, 0x536 }, - { 0x567, LOWER_CASE, 0x537 }, - { 0x568, LOWER_CASE, 0x538 }, - { 0x569, LOWER_CASE, 0x539 }, - { 0x56A, LOWER_CASE, 0x53A }, - { 0x56B, LOWER_CASE, 0x53B }, - { 0x56C, LOWER_CASE, 0x53C }, - { 0x56D, LOWER_CASE, 0x53D }, - { 0x56E, LOWER_CASE, 0x53E }, - { 0x56F, LOWER_CASE, 0x53F }, - { 0x570, LOWER_CASE, 0x540 }, - { 0x571, LOWER_CASE, 0x541 }, - { 0x572, LOWER_CASE, 0x542 }, - { 0x573, LOWER_CASE, 0x543 }, - { 0x574, LOWER_CASE, 0x544 }, - { 0x575, LOWER_CASE, 0x545 }, - { 0x576, LOWER_CASE, 0x546 }, - { 0x577, LOWER_CASE, 0x547 }, - { 0x578, LOWER_CASE, 0x548 }, - { 0x579, LOWER_CASE, 0x549 }, - { 0x57A, LOWER_CASE, 0x54A }, - { 0x57B, LOWER_CASE, 0x54B }, - { 0x57C, LOWER_CASE, 0x54C }, - { 0x57D, LOWER_CASE, 0x54D }, - { 0x57E, LOWER_CASE, 0x54E }, - { 0x57F, LOWER_CASE, 0x54F }, - { 0x580, LOWER_CASE, 0x550 }, - { 0x581, LOWER_CASE, 0x551 }, - { 0x582, LOWER_CASE, 0x552 }, - { 0x583, LOWER_CASE, 0x553 }, - { 0x584, LOWER_CASE, 0x554 }, - { 0x585, LOWER_CASE, 0x555 }, - { 0x586, LOWER_CASE, 0x556 }, - { 0x10A0, UPPER_CASE, 0x2D00 }, - { 0x10A1, UPPER_CASE, 0x2D01 }, - { 0x10A2, UPPER_CASE, 0x2D02 }, - { 0x10A3, UPPER_CASE, 0x2D03 }, - { 0x10A4, UPPER_CASE, 0x2D04 }, - { 0x10A5, UPPER_CASE, 0x2D05 }, - { 0x10A6, UPPER_CASE, 0x2D06 }, - { 0x10A7, UPPER_CASE, 0x2D07 }, - { 0x10A8, UPPER_CASE, 0x2D08 }, - { 0x10A9, UPPER_CASE, 0x2D09 }, - { 0x10AA, UPPER_CASE, 0x2D0A }, - { 0x10AB, UPPER_CASE, 0x2D0B }, - { 0x10AC, UPPER_CASE, 0x2D0C }, - { 0x10AD, UPPER_CASE, 0x2D0D }, - { 0x10AE, UPPER_CASE, 0x2D0E }, - { 0x10AF, UPPER_CASE, 0x2D0F }, - { 0x10B0, UPPER_CASE, 0x2D10 }, - { 0x10B1, UPPER_CASE, 0x2D11 }, - { 0x10B2, UPPER_CASE, 0x2D12 }, - { 0x10B3, UPPER_CASE, 0x2D13 }, - { 0x10B4, UPPER_CASE, 0x2D14 }, - { 0x10B5, UPPER_CASE, 0x2D15 }, - { 0x10B6, UPPER_CASE, 0x2D16 }, - { 0x10B7, UPPER_CASE, 0x2D17 }, - { 0x10B8, UPPER_CASE, 0x2D18 }, - { 0x10B9, UPPER_CASE, 0x2D19 }, - { 0x10BA, UPPER_CASE, 0x2D1A }, - { 0x10BB, UPPER_CASE, 0x2D1B }, - { 0x10BC, UPPER_CASE, 0x2D1C }, - { 0x10BD, UPPER_CASE, 0x2D1D }, - { 0x10BE, UPPER_CASE, 0x2D1E }, - { 0x10BF, UPPER_CASE, 0x2D1F }, - { 0x10C0, UPPER_CASE, 0x2D20 }, - { 0x10C1, UPPER_CASE, 0x2D21 }, - { 0x10C2, UPPER_CASE, 0x2D22 }, - { 0x10C3, UPPER_CASE, 0x2D23 }, - { 0x10C4, UPPER_CASE, 0x2D24 }, - { 0x10C5, UPPER_CASE, 0x2D25 }, - { 0x10C7, UPPER_CASE, 0x2D27 }, - { 0x10CD, UPPER_CASE, 0x2D2D }, - { 0x10D0, LOWER_CASE, 0x1C90 }, - { 0x10D1, LOWER_CASE, 0x1C91 }, - { 0x10D2, LOWER_CASE, 0x1C92 }, - { 0x10D3, LOWER_CASE, 0x1C93 }, - { 0x10D4, LOWER_CASE, 0x1C94 }, - { 0x10D5, LOWER_CASE, 0x1C95 }, - { 0x10D6, LOWER_CASE, 0x1C96 }, - { 0x10D7, LOWER_CASE, 0x1C97 }, - { 0x10D8, LOWER_CASE, 0x1C98 }, - { 0x10D9, LOWER_CASE, 0x1C99 }, - { 0x10DA, LOWER_CASE, 0x1C9A }, - { 0x10DB, LOWER_CASE, 0x1C9B }, - { 0x10DC, LOWER_CASE, 0x1C9C }, - { 0x10DD, LOWER_CASE, 0x1C9D }, - { 0x10DE, LOWER_CASE, 0x1C9E }, - { 0x10DF, LOWER_CASE, 0x1C9F }, - { 0x10E0, LOWER_CASE, 0x1CA0 }, - { 0x10E1, LOWER_CASE, 0x1CA1 }, - { 0x10E2, LOWER_CASE, 0x1CA2 }, - { 0x10E3, LOWER_CASE, 0x1CA3 }, - { 0x10E4, LOWER_CASE, 0x1CA4 }, - { 0x10E5, LOWER_CASE, 0x1CA5 }, - { 0x10E6, LOWER_CASE, 0x1CA6 }, - { 0x10E7, LOWER_CASE, 0x1CA7 }, - { 0x10E8, LOWER_CASE, 0x1CA8 }, - { 0x10E9, LOWER_CASE, 0x1CA9 }, - { 0x10EA, LOWER_CASE, 0x1CAA }, - { 0x10EB, LOWER_CASE, 0x1CAB }, - { 0x10EC, LOWER_CASE, 0x1CAC }, - { 0x10ED, LOWER_CASE, 0x1CAD }, - { 0x10EE, LOWER_CASE, 0x1CAE }, - { 0x10EF, LOWER_CASE, 0x1CAF }, - { 0x10F0, LOWER_CASE, 0x1CB0 }, - { 0x10F1, LOWER_CASE, 0x1CB1 }, - { 0x10F2, LOWER_CASE, 0x1CB2 }, - { 0x10F3, LOWER_CASE, 0x1CB3 }, - { 0x10F4, LOWER_CASE, 0x1CB4 }, - { 0x10F5, LOWER_CASE, 0x1CB5 }, - { 0x10F6, LOWER_CASE, 0x1CB6 }, - { 0x10F7, LOWER_CASE, 0x1CB7 }, - { 0x10F8, LOWER_CASE, 0x1CB8 }, - { 0x10F9, LOWER_CASE, 0x1CB9 }, - { 0x10FA, LOWER_CASE, 0x1CBA }, - { 0x10FD, LOWER_CASE, 0x1CBD }, - { 0x10FE, LOWER_CASE, 0x1CBE }, - { 0x10FF, LOWER_CASE, 0x1CBF }, - { 0x13A0, UPPER_CASE, 0xAB70 }, - { 0x13A1, UPPER_CASE, 0xAB71 }, - { 0x13A2, UPPER_CASE, 0xAB72 }, - { 0x13A3, UPPER_CASE, 0xAB73 }, - { 0x13A4, UPPER_CASE, 0xAB74 }, - { 0x13A5, UPPER_CASE, 0xAB75 }, - { 0x13A6, UPPER_CASE, 0xAB76 }, - { 0x13A7, UPPER_CASE, 0xAB77 }, - { 0x13A8, UPPER_CASE, 0xAB78 }, - { 0x13A9, UPPER_CASE, 0xAB79 }, - { 0x13AA, UPPER_CASE, 0xAB7A }, - { 0x13AB, UPPER_CASE, 0xAB7B }, - { 0x13AC, UPPER_CASE, 0xAB7C }, - { 0x13AD, UPPER_CASE, 0xAB7D }, - { 0x13AE, UPPER_CASE, 0xAB7E }, - { 0x13AF, UPPER_CASE, 0xAB7F }, - { 0x13B0, UPPER_CASE, 0xAB80 }, - { 0x13B1, UPPER_CASE, 0xAB81 }, - { 0x13B2, UPPER_CASE, 0xAB82 }, - { 0x13B3, UPPER_CASE, 0xAB83 }, - { 0x13B4, UPPER_CASE, 0xAB84 }, - { 0x13B5, UPPER_CASE, 0xAB85 }, - { 0x13B6, UPPER_CASE, 0xAB86 }, - { 0x13B7, UPPER_CASE, 0xAB87 }, - { 0x13B8, UPPER_CASE, 0xAB88 }, - { 0x13B9, UPPER_CASE, 0xAB89 }, - { 0x13BA, UPPER_CASE, 0xAB8A }, - { 0x13BB, UPPER_CASE, 0xAB8B }, - { 0x13BC, UPPER_CASE, 0xAB8C }, - { 0x13BD, UPPER_CASE, 0xAB8D }, - { 0x13BE, UPPER_CASE, 0xAB8E }, - { 0x13BF, UPPER_CASE, 0xAB8F }, - { 0x13C0, UPPER_CASE, 0xAB90 }, - { 0x13C1, UPPER_CASE, 0xAB91 }, - { 0x13C2, UPPER_CASE, 0xAB92 }, - { 0x13C3, UPPER_CASE, 0xAB93 }, - { 0x13C4, UPPER_CASE, 0xAB94 }, - { 0x13C5, UPPER_CASE, 0xAB95 }, - { 0x13C6, UPPER_CASE, 0xAB96 }, - { 0x13C7, UPPER_CASE, 0xAB97 }, - { 0x13C8, UPPER_CASE, 0xAB98 }, - { 0x13C9, UPPER_CASE, 0xAB99 }, - { 0x13CA, UPPER_CASE, 0xAB9A }, - { 0x13CB, UPPER_CASE, 0xAB9B }, - { 0x13CC, UPPER_CASE, 0xAB9C }, - { 0x13CD, UPPER_CASE, 0xAB9D }, - { 0x13CE, UPPER_CASE, 0xAB9E }, - { 0x13CF, UPPER_CASE, 0xAB9F }, - { 0x13D0, UPPER_CASE, 0xABA0 }, - { 0x13D1, UPPER_CASE, 0xABA1 }, - { 0x13D2, UPPER_CASE, 0xABA2 }, - { 0x13D3, UPPER_CASE, 0xABA3 }, - { 0x13D4, UPPER_CASE, 0xABA4 }, - { 0x13D5, UPPER_CASE, 0xABA5 }, - { 0x13D6, UPPER_CASE, 0xABA6 }, - { 0x13D7, UPPER_CASE, 0xABA7 }, - { 0x13D8, UPPER_CASE, 0xABA8 }, - { 0x13D9, UPPER_CASE, 0xABA9 }, - { 0x13DA, UPPER_CASE, 0xABAA }, - { 0x13DB, UPPER_CASE, 0xABAB }, - { 0x13DC, UPPER_CASE, 0xABAC }, - { 0x13DD, UPPER_CASE, 0xABAD }, - { 0x13DE, UPPER_CASE, 0xABAE }, - { 0x13DF, UPPER_CASE, 0xABAF }, - { 0x13E0, UPPER_CASE, 0xABB0 }, - { 0x13E1, UPPER_CASE, 0xABB1 }, - { 0x13E2, UPPER_CASE, 0xABB2 }, - { 0x13E3, UPPER_CASE, 0xABB3 }, - { 0x13E4, UPPER_CASE, 0xABB4 }, - { 0x13E5, UPPER_CASE, 0xABB5 }, - { 0x13E6, UPPER_CASE, 0xABB6 }, - { 0x13E7, UPPER_CASE, 0xABB7 }, - { 0x13E8, UPPER_CASE, 0xABB8 }, - { 0x13E9, UPPER_CASE, 0xABB9 }, - { 0x13EA, UPPER_CASE, 0xABBA }, - { 0x13EB, UPPER_CASE, 0xABBB }, - { 0x13EC, UPPER_CASE, 0xABBC }, - { 0x13ED, UPPER_CASE, 0xABBD }, - { 0x13EE, UPPER_CASE, 0xABBE }, - { 0x13EF, UPPER_CASE, 0xABBF }, - { 0x13F0, UPPER_CASE, 0x13F8 }, - { 0x13F1, UPPER_CASE, 0x13F9 }, - { 0x13F2, UPPER_CASE, 0x13FA }, - { 0x13F3, UPPER_CASE, 0x13FB }, - { 0x13F4, UPPER_CASE, 0x13FC }, - { 0x13F5, UPPER_CASE, 0x13FD }, - { 0x13F8, LOWER_CASE, 0x13F0 }, - { 0x13F9, LOWER_CASE, 0x13F1 }, - { 0x13FA, LOWER_CASE, 0x13F2 }, - { 0x13FB, LOWER_CASE, 0x13F3 }, - { 0x13FC, LOWER_CASE, 0x13F4 }, - { 0x13FD, LOWER_CASE, 0x13F5 }, - { 0x1C80, LOWER_CASE, 0x412 }, - { 0x1C81, LOWER_CASE, 0x414 }, - { 0x1C82, LOWER_CASE, 0x41E }, - { 0x1C83, LOWER_CASE, 0x421 }, - { 0x1C84, LOWER_CASE, 0x422 }, - { 0x1C85, LOWER_CASE, 0x422 }, - { 0x1C86, LOWER_CASE, 0x42A }, - { 0x1C87, LOWER_CASE, 0x462 }, - { 0x1C88, LOWER_CASE, 0xA64A }, - { 0x1C90, UPPER_CASE, 0x10D0 }, - { 0x1C91, UPPER_CASE, 0x10D1 }, - { 0x1C92, UPPER_CASE, 0x10D2 }, - { 0x1C93, UPPER_CASE, 0x10D3 }, - { 0x1C94, UPPER_CASE, 0x10D4 }, - { 0x1C95, UPPER_CASE, 0x10D5 }, - { 0x1C96, UPPER_CASE, 0x10D6 }, - { 0x1C97, UPPER_CASE, 0x10D7 }, - { 0x1C98, UPPER_CASE, 0x10D8 }, - { 0x1C99, UPPER_CASE, 0x10D9 }, - { 0x1C9A, UPPER_CASE, 0x10DA }, - { 0x1C9B, UPPER_CASE, 0x10DB }, - { 0x1C9C, UPPER_CASE, 0x10DC }, - { 0x1C9D, UPPER_CASE, 0x10DD }, - { 0x1C9E, UPPER_CASE, 0x10DE }, - { 0x1C9F, UPPER_CASE, 0x10DF }, - { 0x1CA0, UPPER_CASE, 0x10E0 }, - { 0x1CA1, UPPER_CASE, 0x10E1 }, - { 0x1CA2, UPPER_CASE, 0x10E2 }, - { 0x1CA3, UPPER_CASE, 0x10E3 }, - { 0x1CA4, UPPER_CASE, 0x10E4 }, - { 0x1CA5, UPPER_CASE, 0x10E5 }, - { 0x1CA6, UPPER_CASE, 0x10E6 }, - { 0x1CA7, UPPER_CASE, 0x10E7 }, - { 0x1CA8, UPPER_CASE, 0x10E8 }, - { 0x1CA9, UPPER_CASE, 0x10E9 }, - { 0x1CAA, UPPER_CASE, 0x10EA }, - { 0x1CAB, UPPER_CASE, 0x10EB }, - { 0x1CAC, UPPER_CASE, 0x10EC }, - { 0x1CAD, UPPER_CASE, 0x10ED }, - { 0x1CAE, UPPER_CASE, 0x10EE }, - { 0x1CAF, UPPER_CASE, 0x10EF }, - { 0x1CB0, UPPER_CASE, 0x10F0 }, - { 0x1CB1, UPPER_CASE, 0x10F1 }, - { 0x1CB2, UPPER_CASE, 0x10F2 }, - { 0x1CB3, UPPER_CASE, 0x10F3 }, - { 0x1CB4, UPPER_CASE, 0x10F4 }, - { 0x1CB5, UPPER_CASE, 0x10F5 }, - { 0x1CB6, UPPER_CASE, 0x10F6 }, - { 0x1CB7, UPPER_CASE, 0x10F7 }, - { 0x1CB8, UPPER_CASE, 0x10F8 }, - { 0x1CB9, UPPER_CASE, 0x10F9 }, - { 0x1CBA, UPPER_CASE, 0x10FA }, - { 0x1CBD, UPPER_CASE, 0x10FD }, - { 0x1CBE, UPPER_CASE, 0x10FE }, - { 0x1CBF, UPPER_CASE, 0x10FF }, - { 0x1D79, LOWER_CASE, 0xA77D }, - { 0x1D7D, LOWER_CASE, 0x2C63 }, - { 0x1D8E, LOWER_CASE, 0xA7C6 }, - { 0x1E00, UPPER_CASE, 0x1E01 }, - { 0x1E01, LOWER_CASE, 0x1E00 }, - { 0x1E02, UPPER_CASE, 0x1E03 }, - { 0x1E03, LOWER_CASE, 0x1E02 }, - { 0x1E04, UPPER_CASE, 0x1E05 }, - { 0x1E05, LOWER_CASE, 0x1E04 }, - { 0x1E06, UPPER_CASE, 0x1E07 }, - { 0x1E07, LOWER_CASE, 0x1E06 }, - { 0x1E08, UPPER_CASE, 0x1E09 }, - { 0x1E09, LOWER_CASE, 0x1E08 }, - { 0x1E0A, UPPER_CASE, 0x1E0B }, - { 0x1E0B, LOWER_CASE, 0x1E0A }, - { 0x1E0C, UPPER_CASE, 0x1E0D }, - { 0x1E0D, LOWER_CASE, 0x1E0C }, - { 0x1E0E, UPPER_CASE, 0x1E0F }, - { 0x1E0F, LOWER_CASE, 0x1E0E }, - { 0x1E10, UPPER_CASE, 0x1E11 }, - { 0x1E11, LOWER_CASE, 0x1E10 }, - { 0x1E12, UPPER_CASE, 0x1E13 }, - { 0x1E13, LOWER_CASE, 0x1E12 }, - { 0x1E14, UPPER_CASE, 0x1E15 }, - { 0x1E15, LOWER_CASE, 0x1E14 }, - { 0x1E16, UPPER_CASE, 0x1E17 }, - { 0x1E17, LOWER_CASE, 0x1E16 }, - { 0x1E18, UPPER_CASE, 0x1E19 }, - { 0x1E19, LOWER_CASE, 0x1E18 }, - { 0x1E1A, UPPER_CASE, 0x1E1B }, - { 0x1E1B, LOWER_CASE, 0x1E1A }, - { 0x1E1C, UPPER_CASE, 0x1E1D }, - { 0x1E1D, LOWER_CASE, 0x1E1C }, - { 0x1E1E, UPPER_CASE, 0x1E1F }, - { 0x1E1F, LOWER_CASE, 0x1E1E }, - { 0x1E20, UPPER_CASE, 0x1E21 }, - { 0x1E21, LOWER_CASE, 0x1E20 }, - { 0x1E22, UPPER_CASE, 0x1E23 }, - { 0x1E23, LOWER_CASE, 0x1E22 }, - { 0x1E24, UPPER_CASE, 0x1E25 }, - { 0x1E25, LOWER_CASE, 0x1E24 }, - { 0x1E26, UPPER_CASE, 0x1E27 }, - { 0x1E27, LOWER_CASE, 0x1E26 }, - { 0x1E28, UPPER_CASE, 0x1E29 }, - { 0x1E29, LOWER_CASE, 0x1E28 }, - { 0x1E2A, UPPER_CASE, 0x1E2B }, - { 0x1E2B, LOWER_CASE, 0x1E2A }, - { 0x1E2C, UPPER_CASE, 0x1E2D }, - { 0x1E2D, LOWER_CASE, 0x1E2C }, - { 0x1E2E, UPPER_CASE, 0x1E2F }, - { 0x1E2F, LOWER_CASE, 0x1E2E }, - { 0x1E30, UPPER_CASE, 0x1E31 }, - { 0x1E31, LOWER_CASE, 0x1E30 }, - { 0x1E32, UPPER_CASE, 0x1E33 }, - { 0x1E33, LOWER_CASE, 0x1E32 }, - { 0x1E34, UPPER_CASE, 0x1E35 }, - { 0x1E35, LOWER_CASE, 0x1E34 }, - { 0x1E36, UPPER_CASE, 0x1E37 }, - { 0x1E37, LOWER_CASE, 0x1E36 }, - { 0x1E38, UPPER_CASE, 0x1E39 }, - { 0x1E39, LOWER_CASE, 0x1E38 }, - { 0x1E3A, UPPER_CASE, 0x1E3B }, - { 0x1E3B, LOWER_CASE, 0x1E3A }, - { 0x1E3C, UPPER_CASE, 0x1E3D }, - { 0x1E3D, LOWER_CASE, 0x1E3C }, - { 0x1E3E, UPPER_CASE, 0x1E3F }, - { 0x1E3F, LOWER_CASE, 0x1E3E }, - { 0x1E40, UPPER_CASE, 0x1E41 }, - { 0x1E41, LOWER_CASE, 0x1E40 }, - { 0x1E42, UPPER_CASE, 0x1E43 }, - { 0x1E43, LOWER_CASE, 0x1E42 }, - { 0x1E44, UPPER_CASE, 0x1E45 }, - { 0x1E45, LOWER_CASE, 0x1E44 }, - { 0x1E46, UPPER_CASE, 0x1E47 }, - { 0x1E47, LOWER_CASE, 0x1E46 }, - { 0x1E48, UPPER_CASE, 0x1E49 }, - { 0x1E49, LOWER_CASE, 0x1E48 }, - { 0x1E4A, UPPER_CASE, 0x1E4B }, - { 0x1E4B, LOWER_CASE, 0x1E4A }, - { 0x1E4C, UPPER_CASE, 0x1E4D }, - { 0x1E4D, LOWER_CASE, 0x1E4C }, - { 0x1E4E, UPPER_CASE, 0x1E4F }, - { 0x1E4F, LOWER_CASE, 0x1E4E }, - { 0x1E50, UPPER_CASE, 0x1E51 }, - { 0x1E51, LOWER_CASE, 0x1E50 }, - { 0x1E52, UPPER_CASE, 0x1E53 }, - { 0x1E53, LOWER_CASE, 0x1E52 }, - { 0x1E54, UPPER_CASE, 0x1E55 }, - { 0x1E55, LOWER_CASE, 0x1E54 }, - { 0x1E56, UPPER_CASE, 0x1E57 }, - { 0x1E57, LOWER_CASE, 0x1E56 }, - { 0x1E58, UPPER_CASE, 0x1E59 }, - { 0x1E59, LOWER_CASE, 0x1E58 }, - { 0x1E5A, UPPER_CASE, 0x1E5B }, - { 0x1E5B, LOWER_CASE, 0x1E5A }, - { 0x1E5C, UPPER_CASE, 0x1E5D }, - { 0x1E5D, LOWER_CASE, 0x1E5C }, - { 0x1E5E, UPPER_CASE, 0x1E5F }, - { 0x1E5F, LOWER_CASE, 0x1E5E }, - { 0x1E60, UPPER_CASE, 0x1E61 }, - { 0x1E61, LOWER_CASE, 0x1E60 }, - { 0x1E62, UPPER_CASE, 0x1E63 }, - { 0x1E63, LOWER_CASE, 0x1E62 }, - { 0x1E64, UPPER_CASE, 0x1E65 }, - { 0x1E65, LOWER_CASE, 0x1E64 }, - { 0x1E66, UPPER_CASE, 0x1E67 }, - { 0x1E67, LOWER_CASE, 0x1E66 }, - { 0x1E68, UPPER_CASE, 0x1E69 }, - { 0x1E69, LOWER_CASE, 0x1E68 }, - { 0x1E6A, UPPER_CASE, 0x1E6B }, - { 0x1E6B, LOWER_CASE, 0x1E6A }, - { 0x1E6C, UPPER_CASE, 0x1E6D }, - { 0x1E6D, LOWER_CASE, 0x1E6C }, - { 0x1E6E, UPPER_CASE, 0x1E6F }, - { 0x1E6F, LOWER_CASE, 0x1E6E }, - { 0x1E70, UPPER_CASE, 0x1E71 }, - { 0x1E71, LOWER_CASE, 0x1E70 }, - { 0x1E72, UPPER_CASE, 0x1E73 }, - { 0x1E73, LOWER_CASE, 0x1E72 }, - { 0x1E74, UPPER_CASE, 0x1E75 }, - { 0x1E75, LOWER_CASE, 0x1E74 }, - { 0x1E76, UPPER_CASE, 0x1E77 }, - { 0x1E77, LOWER_CASE, 0x1E76 }, - { 0x1E78, UPPER_CASE, 0x1E79 }, - { 0x1E79, LOWER_CASE, 0x1E78 }, - { 0x1E7A, UPPER_CASE, 0x1E7B }, - { 0x1E7B, LOWER_CASE, 0x1E7A }, - { 0x1E7C, UPPER_CASE, 0x1E7D }, - { 0x1E7D, LOWER_CASE, 0x1E7C }, - { 0x1E7E, UPPER_CASE, 0x1E7F }, - { 0x1E7F, LOWER_CASE, 0x1E7E }, - { 0x1E80, UPPER_CASE, 0x1E81 }, - { 0x1E81, LOWER_CASE, 0x1E80 }, - { 0x1E82, UPPER_CASE, 0x1E83 }, - { 0x1E83, LOWER_CASE, 0x1E82 }, - { 0x1E84, UPPER_CASE, 0x1E85 }, - { 0x1E85, LOWER_CASE, 0x1E84 }, - { 0x1E86, UPPER_CASE, 0x1E87 }, - { 0x1E87, LOWER_CASE, 0x1E86 }, - { 0x1E88, UPPER_CASE, 0x1E89 }, - { 0x1E89, LOWER_CASE, 0x1E88 }, - { 0x1E8A, UPPER_CASE, 0x1E8B }, - { 0x1E8B, LOWER_CASE, 0x1E8A }, - { 0x1E8C, UPPER_CASE, 0x1E8D }, - { 0x1E8D, LOWER_CASE, 0x1E8C }, - { 0x1E8E, UPPER_CASE, 0x1E8F }, - { 0x1E8F, LOWER_CASE, 0x1E8E }, - { 0x1E90, UPPER_CASE, 0x1E91 }, - { 0x1E91, LOWER_CASE, 0x1E90 }, - { 0x1E92, UPPER_CASE, 0x1E93 }, - { 0x1E93, LOWER_CASE, 0x1E92 }, - { 0x1E94, UPPER_CASE, 0x1E95 }, - { 0x1E95, LOWER_CASE, 0x1E94 }, - { 0x1E9B, LOWER_CASE, 0x1E60 }, - { 0x1E9E, UPPER_CASE, 0xDF }, - { 0x1EA0, UPPER_CASE, 0x1EA1 }, - { 0x1EA1, LOWER_CASE, 0x1EA0 }, - { 0x1EA2, UPPER_CASE, 0x1EA3 }, - { 0x1EA3, LOWER_CASE, 0x1EA2 }, - { 0x1EA4, UPPER_CASE, 0x1EA5 }, - { 0x1EA5, LOWER_CASE, 0x1EA4 }, - { 0x1EA6, UPPER_CASE, 0x1EA7 }, - { 0x1EA7, LOWER_CASE, 0x1EA6 }, - { 0x1EA8, UPPER_CASE, 0x1EA9 }, - { 0x1EA9, LOWER_CASE, 0x1EA8 }, - { 0x1EAA, UPPER_CASE, 0x1EAB }, - { 0x1EAB, LOWER_CASE, 0x1EAA }, - { 0x1EAC, UPPER_CASE, 0x1EAD }, - { 0x1EAD, LOWER_CASE, 0x1EAC }, - { 0x1EAE, UPPER_CASE, 0x1EAF }, - { 0x1EAF, LOWER_CASE, 0x1EAE }, - { 0x1EB0, UPPER_CASE, 0x1EB1 }, - { 0x1EB1, LOWER_CASE, 0x1EB0 }, - { 0x1EB2, UPPER_CASE, 0x1EB3 }, - { 0x1EB3, LOWER_CASE, 0x1EB2 }, - { 0x1EB4, UPPER_CASE, 0x1EB5 }, - { 0x1EB5, LOWER_CASE, 0x1EB4 }, - { 0x1EB6, UPPER_CASE, 0x1EB7 }, - { 0x1EB7, LOWER_CASE, 0x1EB6 }, - { 0x1EB8, UPPER_CASE, 0x1EB9 }, - { 0x1EB9, LOWER_CASE, 0x1EB8 }, - { 0x1EBA, UPPER_CASE, 0x1EBB }, - { 0x1EBB, LOWER_CASE, 0x1EBA }, - { 0x1EBC, UPPER_CASE, 0x1EBD }, - { 0x1EBD, LOWER_CASE, 0x1EBC }, - { 0x1EBE, UPPER_CASE, 0x1EBF }, - { 0x1EBF, LOWER_CASE, 0x1EBE }, - { 0x1EC0, UPPER_CASE, 0x1EC1 }, - { 0x1EC1, LOWER_CASE, 0x1EC0 }, - { 0x1EC2, UPPER_CASE, 0x1EC3 }, - { 0x1EC3, LOWER_CASE, 0x1EC2 }, - { 0x1EC4, UPPER_CASE, 0x1EC5 }, - { 0x1EC5, LOWER_CASE, 0x1EC4 }, - { 0x1EC6, UPPER_CASE, 0x1EC7 }, - { 0x1EC7, LOWER_CASE, 0x1EC6 }, - { 0x1EC8, UPPER_CASE, 0x1EC9 }, - { 0x1EC9, LOWER_CASE, 0x1EC8 }, - { 0x1ECA, UPPER_CASE, 0x1ECB }, - { 0x1ECB, LOWER_CASE, 0x1ECA }, - { 0x1ECC, UPPER_CASE, 0x1ECD }, - { 0x1ECD, LOWER_CASE, 0x1ECC }, - { 0x1ECE, UPPER_CASE, 0x1ECF }, - { 0x1ECF, LOWER_CASE, 0x1ECE }, - { 0x1ED0, UPPER_CASE, 0x1ED1 }, - { 0x1ED1, LOWER_CASE, 0x1ED0 }, - { 0x1ED2, UPPER_CASE, 0x1ED3 }, - { 0x1ED3, LOWER_CASE, 0x1ED2 }, - { 0x1ED4, UPPER_CASE, 0x1ED5 }, - { 0x1ED5, LOWER_CASE, 0x1ED4 }, - { 0x1ED6, UPPER_CASE, 0x1ED7 }, - { 0x1ED7, LOWER_CASE, 0x1ED6 }, - { 0x1ED8, UPPER_CASE, 0x1ED9 }, - { 0x1ED9, LOWER_CASE, 0x1ED8 }, - { 0x1EDA, UPPER_CASE, 0x1EDB }, - { 0x1EDB, LOWER_CASE, 0x1EDA }, - { 0x1EDC, UPPER_CASE, 0x1EDD }, - { 0x1EDD, LOWER_CASE, 0x1EDC }, - { 0x1EDE, UPPER_CASE, 0x1EDF }, - { 0x1EDF, LOWER_CASE, 0x1EDE }, - { 0x1EE0, UPPER_CASE, 0x1EE1 }, - { 0x1EE1, LOWER_CASE, 0x1EE0 }, - { 0x1EE2, UPPER_CASE, 0x1EE3 }, - { 0x1EE3, LOWER_CASE, 0x1EE2 }, - { 0x1EE4, UPPER_CASE, 0x1EE5 }, - { 0x1EE5, LOWER_CASE, 0x1EE4 }, - { 0x1EE6, UPPER_CASE, 0x1EE7 }, - { 0x1EE7, LOWER_CASE, 0x1EE6 }, - { 0x1EE8, UPPER_CASE, 0x1EE9 }, - { 0x1EE9, LOWER_CASE, 0x1EE8 }, - { 0x1EEA, UPPER_CASE, 0x1EEB }, - { 0x1EEB, LOWER_CASE, 0x1EEA }, - { 0x1EEC, UPPER_CASE, 0x1EED }, - { 0x1EED, LOWER_CASE, 0x1EEC }, - { 0x1EEE, UPPER_CASE, 0x1EEF }, - { 0x1EEF, LOWER_CASE, 0x1EEE }, - { 0x1EF0, UPPER_CASE, 0x1EF1 }, - { 0x1EF1, LOWER_CASE, 0x1EF0 }, - { 0x1EF2, UPPER_CASE, 0x1EF3 }, - { 0x1EF3, LOWER_CASE, 0x1EF2 }, - { 0x1EF4, UPPER_CASE, 0x1EF5 }, - { 0x1EF5, LOWER_CASE, 0x1EF4 }, - { 0x1EF6, UPPER_CASE, 0x1EF7 }, - { 0x1EF7, LOWER_CASE, 0x1EF6 }, - { 0x1EF8, UPPER_CASE, 0x1EF9 }, - { 0x1EF9, LOWER_CASE, 0x1EF8 }, - { 0x1EFA, UPPER_CASE, 0x1EFB }, - { 0x1EFB, LOWER_CASE, 0x1EFA }, - { 0x1EFC, UPPER_CASE, 0x1EFD }, - { 0x1EFD, LOWER_CASE, 0x1EFC }, - { 0x1EFE, UPPER_CASE, 0x1EFF }, - { 0x1EFF, LOWER_CASE, 0x1EFE }, - { 0x1F00, LOWER_CASE, 0x1F08 }, - { 0x1F01, LOWER_CASE, 0x1F09 }, - { 0x1F02, LOWER_CASE, 0x1F0A }, - { 0x1F03, LOWER_CASE, 0x1F0B }, - { 0x1F04, LOWER_CASE, 0x1F0C }, - { 0x1F05, LOWER_CASE, 0x1F0D }, - { 0x1F06, LOWER_CASE, 0x1F0E }, - { 0x1F07, LOWER_CASE, 0x1F0F }, - { 0x1F08, UPPER_CASE, 0x1F00 }, - { 0x1F09, UPPER_CASE, 0x1F01 }, - { 0x1F0A, UPPER_CASE, 0x1F02 }, - { 0x1F0B, UPPER_CASE, 0x1F03 }, - { 0x1F0C, UPPER_CASE, 0x1F04 }, - { 0x1F0D, UPPER_CASE, 0x1F05 }, - { 0x1F0E, UPPER_CASE, 0x1F06 }, - { 0x1F0F, UPPER_CASE, 0x1F07 }, - { 0x1F10, LOWER_CASE, 0x1F18 }, - { 0x1F11, LOWER_CASE, 0x1F19 }, - { 0x1F12, LOWER_CASE, 0x1F1A }, - { 0x1F13, LOWER_CASE, 0x1F1B }, - { 0x1F14, LOWER_CASE, 0x1F1C }, - { 0x1F15, LOWER_CASE, 0x1F1D }, - { 0x1F18, UPPER_CASE, 0x1F10 }, - { 0x1F19, UPPER_CASE, 0x1F11 }, - { 0x1F1A, UPPER_CASE, 0x1F12 }, - { 0x1F1B, UPPER_CASE, 0x1F13 }, - { 0x1F1C, UPPER_CASE, 0x1F14 }, - { 0x1F1D, UPPER_CASE, 0x1F15 }, - { 0x1F20, LOWER_CASE, 0x1F28 }, - { 0x1F21, LOWER_CASE, 0x1F29 }, - { 0x1F22, LOWER_CASE, 0x1F2A }, - { 0x1F23, LOWER_CASE, 0x1F2B }, - { 0x1F24, LOWER_CASE, 0x1F2C }, - { 0x1F25, LOWER_CASE, 0x1F2D }, - { 0x1F26, LOWER_CASE, 0x1F2E }, - { 0x1F27, LOWER_CASE, 0x1F2F }, - { 0x1F28, UPPER_CASE, 0x1F20 }, - { 0x1F29, UPPER_CASE, 0x1F21 }, - { 0x1F2A, UPPER_CASE, 0x1F22 }, - { 0x1F2B, UPPER_CASE, 0x1F23 }, - { 0x1F2C, UPPER_CASE, 0x1F24 }, - { 0x1F2D, UPPER_CASE, 0x1F25 }, - { 0x1F2E, UPPER_CASE, 0x1F26 }, - { 0x1F2F, UPPER_CASE, 0x1F27 }, - { 0x1F30, LOWER_CASE, 0x1F38 }, - { 0x1F31, LOWER_CASE, 0x1F39 }, - { 0x1F32, LOWER_CASE, 0x1F3A }, - { 0x1F33, LOWER_CASE, 0x1F3B }, - { 0x1F34, LOWER_CASE, 0x1F3C }, - { 0x1F35, LOWER_CASE, 0x1F3D }, - { 0x1F36, LOWER_CASE, 0x1F3E }, - { 0x1F37, LOWER_CASE, 0x1F3F }, - { 0x1F38, UPPER_CASE, 0x1F30 }, - { 0x1F39, UPPER_CASE, 0x1F31 }, - { 0x1F3A, UPPER_CASE, 0x1F32 }, - { 0x1F3B, UPPER_CASE, 0x1F33 }, - { 0x1F3C, UPPER_CASE, 0x1F34 }, - { 0x1F3D, UPPER_CASE, 0x1F35 }, - { 0x1F3E, UPPER_CASE, 0x1F36 }, - { 0x1F3F, UPPER_CASE, 0x1F37 }, - { 0x1F40, LOWER_CASE, 0x1F48 }, - { 0x1F41, LOWER_CASE, 0x1F49 }, - { 0x1F42, LOWER_CASE, 0x1F4A }, - { 0x1F43, LOWER_CASE, 0x1F4B }, - { 0x1F44, LOWER_CASE, 0x1F4C }, - { 0x1F45, LOWER_CASE, 0x1F4D }, - { 0x1F48, UPPER_CASE, 0x1F40 }, - { 0x1F49, UPPER_CASE, 0x1F41 }, - { 0x1F4A, UPPER_CASE, 0x1F42 }, - { 0x1F4B, UPPER_CASE, 0x1F43 }, - { 0x1F4C, UPPER_CASE, 0x1F44 }, - { 0x1F4D, UPPER_CASE, 0x1F45 }, - { 0x1F51, LOWER_CASE, 0x1F59 }, - { 0x1F53, LOWER_CASE, 0x1F5B }, - { 0x1F55, LOWER_CASE, 0x1F5D }, - { 0x1F57, LOWER_CASE, 0x1F5F }, - { 0x1F59, UPPER_CASE, 0x1F51 }, - { 0x1F5B, UPPER_CASE, 0x1F53 }, - { 0x1F5D, UPPER_CASE, 0x1F55 }, - { 0x1F5F, UPPER_CASE, 0x1F57 }, - { 0x1F60, LOWER_CASE, 0x1F68 }, - { 0x1F61, LOWER_CASE, 0x1F69 }, - { 0x1F62, LOWER_CASE, 0x1F6A }, - { 0x1F63, LOWER_CASE, 0x1F6B }, - { 0x1F64, LOWER_CASE, 0x1F6C }, - { 0x1F65, LOWER_CASE, 0x1F6D }, - { 0x1F66, LOWER_CASE, 0x1F6E }, - { 0x1F67, LOWER_CASE, 0x1F6F }, - { 0x1F68, UPPER_CASE, 0x1F60 }, - { 0x1F69, UPPER_CASE, 0x1F61 }, - { 0x1F6A, UPPER_CASE, 0x1F62 }, - { 0x1F6B, UPPER_CASE, 0x1F63 }, - { 0x1F6C, UPPER_CASE, 0x1F64 }, - { 0x1F6D, UPPER_CASE, 0x1F65 }, - { 0x1F6E, UPPER_CASE, 0x1F66 }, - { 0x1F6F, UPPER_CASE, 0x1F67 }, - { 0x1F70, LOWER_CASE, 0x1FBA }, - { 0x1F71, LOWER_CASE, 0x1FBB }, - { 0x1F72, LOWER_CASE, 0x1FC8 }, - { 0x1F73, LOWER_CASE, 0x1FC9 }, - { 0x1F74, LOWER_CASE, 0x1FCA }, - { 0x1F75, LOWER_CASE, 0x1FCB }, - { 0x1F76, LOWER_CASE, 0x1FDA }, - { 0x1F77, LOWER_CASE, 0x1FDB }, - { 0x1F78, LOWER_CASE, 0x1FF8 }, - { 0x1F79, LOWER_CASE, 0x1FF9 }, - { 0x1F7A, LOWER_CASE, 0x1FEA }, - { 0x1F7B, LOWER_CASE, 0x1FEB }, - { 0x1F7C, LOWER_CASE, 0x1FFA }, - { 0x1F7D, LOWER_CASE, 0x1FFB }, - { 0x1F80, LOWER_CASE, 0x1F88 }, - { 0x1F81, LOWER_CASE, 0x1F89 }, - { 0x1F82, LOWER_CASE, 0x1F8A }, - { 0x1F83, LOWER_CASE, 0x1F8B }, - { 0x1F84, LOWER_CASE, 0x1F8C }, - { 0x1F85, LOWER_CASE, 0x1F8D }, - { 0x1F86, LOWER_CASE, 0x1F8E }, - { 0x1F87, LOWER_CASE, 0x1F8F }, - { 0x1F88, UPPER_CASE, 0x1F80 }, - { 0x1F89, UPPER_CASE, 0x1F81 }, - { 0x1F8A, UPPER_CASE, 0x1F82 }, - { 0x1F8B, UPPER_CASE, 0x1F83 }, - { 0x1F8C, UPPER_CASE, 0x1F84 }, - { 0x1F8D, UPPER_CASE, 0x1F85 }, - { 0x1F8E, UPPER_CASE, 0x1F86 }, - { 0x1F8F, UPPER_CASE, 0x1F87 }, - { 0x1F90, LOWER_CASE, 0x1F98 }, - { 0x1F91, LOWER_CASE, 0x1F99 }, - { 0x1F92, LOWER_CASE, 0x1F9A }, - { 0x1F93, LOWER_CASE, 0x1F9B }, - { 0x1F94, LOWER_CASE, 0x1F9C }, - { 0x1F95, LOWER_CASE, 0x1F9D }, - { 0x1F96, LOWER_CASE, 0x1F9E }, - { 0x1F97, LOWER_CASE, 0x1F9F }, - { 0x1F98, UPPER_CASE, 0x1F90 }, - { 0x1F99, UPPER_CASE, 0x1F91 }, - { 0x1F9A, UPPER_CASE, 0x1F92 }, - { 0x1F9B, UPPER_CASE, 0x1F93 }, - { 0x1F9C, UPPER_CASE, 0x1F94 }, - { 0x1F9D, UPPER_CASE, 0x1F95 }, - { 0x1F9E, UPPER_CASE, 0x1F96 }, - { 0x1F9F, UPPER_CASE, 0x1F97 }, - { 0x1FA0, LOWER_CASE, 0x1FA8 }, - { 0x1FA1, LOWER_CASE, 0x1FA9 }, - { 0x1FA2, LOWER_CASE, 0x1FAA }, - { 0x1FA3, LOWER_CASE, 0x1FAB }, - { 0x1FA4, LOWER_CASE, 0x1FAC }, - { 0x1FA5, LOWER_CASE, 0x1FAD }, - { 0x1FA6, LOWER_CASE, 0x1FAE }, - { 0x1FA7, LOWER_CASE, 0x1FAF }, - { 0x1FA8, UPPER_CASE, 0x1FA0 }, - { 0x1FA9, UPPER_CASE, 0x1FA1 }, - { 0x1FAA, UPPER_CASE, 0x1FA2 }, - { 0x1FAB, UPPER_CASE, 0x1FA3 }, - { 0x1FAC, UPPER_CASE, 0x1FA4 }, - { 0x1FAD, UPPER_CASE, 0x1FA5 }, - { 0x1FAE, UPPER_CASE, 0x1FA6 }, - { 0x1FAF, UPPER_CASE, 0x1FA7 }, - { 0x1FB0, LOWER_CASE, 0x1FB8 }, - { 0x1FB1, LOWER_CASE, 0x1FB9 }, - { 0x1FB3, LOWER_CASE, 0x1FBC }, - { 0x1FB8, UPPER_CASE, 0x1FB0 }, - { 0x1FB9, UPPER_CASE, 0x1FB1 }, - { 0x1FBA, UPPER_CASE, 0x1F70 }, - { 0x1FBB, UPPER_CASE, 0x1F71 }, - { 0x1FBC, UPPER_CASE, 0x1FB3 }, - { 0x1FBE, LOWER_CASE, 0x399 }, - { 0x1FC3, LOWER_CASE, 0x1FCC }, - { 0x1FC8, UPPER_CASE, 0x1F72 }, - { 0x1FC9, UPPER_CASE, 0x1F73 }, - { 0x1FCA, UPPER_CASE, 0x1F74 }, - { 0x1FCB, UPPER_CASE, 0x1F75 }, - { 0x1FCC, UPPER_CASE, 0x1FC3 }, - { 0x1FD0, LOWER_CASE, 0x1FD8 }, - { 0x1FD1, LOWER_CASE, 0x1FD9 }, - { 0x1FD8, UPPER_CASE, 0x1FD0 }, - { 0x1FD9, UPPER_CASE, 0x1FD1 }, - { 0x1FDA, UPPER_CASE, 0x1F76 }, - { 0x1FDB, UPPER_CASE, 0x1F77 }, - { 0x1FE0, LOWER_CASE, 0x1FE8 }, - { 0x1FE1, LOWER_CASE, 0x1FE9 }, - { 0x1FE5, LOWER_CASE, 0x1FEC }, - { 0x1FE8, UPPER_CASE, 0x1FE0 }, - { 0x1FE9, UPPER_CASE, 0x1FE1 }, - { 0x1FEA, UPPER_CASE, 0x1F7A }, - { 0x1FEB, UPPER_CASE, 0x1F7B }, - { 0x1FEC, UPPER_CASE, 0x1FE5 }, - { 0x1FF3, LOWER_CASE, 0x1FFC }, - { 0x1FF8, UPPER_CASE, 0x1F78 }, - { 0x1FF9, UPPER_CASE, 0x1F79 }, - { 0x1FFA, UPPER_CASE, 0x1F7C }, - { 0x1FFB, UPPER_CASE, 0x1F7D }, - { 0x1FFC, UPPER_CASE, 0x1FF3 }, - { 0x2126, UPPER_CASE, 0x3C9 }, - { 0x212A, UPPER_CASE, 0x6B }, - { 0x212B, UPPER_CASE, 0xE5 }, - { 0x2132, UPPER_CASE, 0x214E }, - { 0x214E, LOWER_CASE, 0x2132 }, - { 0x2160, UPPER_CASE, 0x2170 }, - { 0x2161, UPPER_CASE, 0x2171 }, - { 0x2162, UPPER_CASE, 0x2172 }, - { 0x2163, UPPER_CASE, 0x2173 }, - { 0x2164, UPPER_CASE, 0x2174 }, - { 0x2165, UPPER_CASE, 0x2175 }, - { 0x2166, UPPER_CASE, 0x2176 }, - { 0x2167, UPPER_CASE, 0x2177 }, - { 0x2168, UPPER_CASE, 0x2178 }, - { 0x2169, UPPER_CASE, 0x2179 }, - { 0x216A, UPPER_CASE, 0x217A }, - { 0x216B, UPPER_CASE, 0x217B }, - { 0x216C, UPPER_CASE, 0x217C }, - { 0x216D, UPPER_CASE, 0x217D }, - { 0x216E, UPPER_CASE, 0x217E }, - { 0x216F, UPPER_CASE, 0x217F }, - { 0x2170, LOWER_CASE, 0x2160 }, - { 0x2171, LOWER_CASE, 0x2161 }, - { 0x2172, LOWER_CASE, 0x2162 }, - { 0x2173, LOWER_CASE, 0x2163 }, - { 0x2174, LOWER_CASE, 0x2164 }, - { 0x2175, LOWER_CASE, 0x2165 }, - { 0x2176, LOWER_CASE, 0x2166 }, - { 0x2177, LOWER_CASE, 0x2167 }, - { 0x2178, LOWER_CASE, 0x2168 }, - { 0x2179, LOWER_CASE, 0x2169 }, - { 0x217A, LOWER_CASE, 0x216A }, - { 0x217B, LOWER_CASE, 0x216B }, - { 0x217C, LOWER_CASE, 0x216C }, - { 0x217D, LOWER_CASE, 0x216D }, - { 0x217E, LOWER_CASE, 0x216E }, - { 0x217F, LOWER_CASE, 0x216F }, - { 0x2183, UPPER_CASE, 0x2184 }, - { 0x2184, LOWER_CASE, 0x2183 }, - { 0x24B6, UPPER_CASE, 0x24D0 }, - { 0x24B7, UPPER_CASE, 0x24D1 }, - { 0x24B8, UPPER_CASE, 0x24D2 }, - { 0x24B9, UPPER_CASE, 0x24D3 }, - { 0x24BA, UPPER_CASE, 0x24D4 }, - { 0x24BB, UPPER_CASE, 0x24D5 }, - { 0x24BC, UPPER_CASE, 0x24D6 }, - { 0x24BD, UPPER_CASE, 0x24D7 }, - { 0x24BE, UPPER_CASE, 0x24D8 }, - { 0x24BF, UPPER_CASE, 0x24D9 }, - { 0x24C0, UPPER_CASE, 0x24DA }, - { 0x24C1, UPPER_CASE, 0x24DB }, - { 0x24C2, UPPER_CASE, 0x24DC }, - { 0x24C3, UPPER_CASE, 0x24DD }, - { 0x24C4, UPPER_CASE, 0x24DE }, - { 0x24C5, UPPER_CASE, 0x24DF }, - { 0x24C6, UPPER_CASE, 0x24E0 }, - { 0x24C7, UPPER_CASE, 0x24E1 }, - { 0x24C8, UPPER_CASE, 0x24E2 }, - { 0x24C9, UPPER_CASE, 0x24E3 }, - { 0x24CA, UPPER_CASE, 0x24E4 }, - { 0x24CB, UPPER_CASE, 0x24E5 }, - { 0x24CC, UPPER_CASE, 0x24E6 }, - { 0x24CD, UPPER_CASE, 0x24E7 }, - { 0x24CE, UPPER_CASE, 0x24E8 }, - { 0x24CF, UPPER_CASE, 0x24E9 }, - { 0x24D0, LOWER_CASE, 0x24B6 }, - { 0x24D1, LOWER_CASE, 0x24B7 }, - { 0x24D2, LOWER_CASE, 0x24B8 }, - { 0x24D3, LOWER_CASE, 0x24B9 }, - { 0x24D4, LOWER_CASE, 0x24BA }, - { 0x24D5, LOWER_CASE, 0x24BB }, - { 0x24D6, LOWER_CASE, 0x24BC }, - { 0x24D7, LOWER_CASE, 0x24BD }, - { 0x24D8, LOWER_CASE, 0x24BE }, - { 0x24D9, LOWER_CASE, 0x24BF }, - { 0x24DA, LOWER_CASE, 0x24C0 }, - { 0x24DB, LOWER_CASE, 0x24C1 }, - { 0x24DC, LOWER_CASE, 0x24C2 }, - { 0x24DD, LOWER_CASE, 0x24C3 }, - { 0x24DE, LOWER_CASE, 0x24C4 }, - { 0x24DF, LOWER_CASE, 0x24C5 }, - { 0x24E0, LOWER_CASE, 0x24C6 }, - { 0x24E1, LOWER_CASE, 0x24C7 }, - { 0x24E2, LOWER_CASE, 0x24C8 }, - { 0x24E3, LOWER_CASE, 0x24C9 }, - { 0x24E4, LOWER_CASE, 0x24CA }, - { 0x24E5, LOWER_CASE, 0x24CB }, - { 0x24E6, LOWER_CASE, 0x24CC }, - { 0x24E7, LOWER_CASE, 0x24CD }, - { 0x24E8, LOWER_CASE, 0x24CE }, - { 0x24E9, LOWER_CASE, 0x24CF }, - { 0x2C00, UPPER_CASE, 0x2C30 }, - { 0x2C01, UPPER_CASE, 0x2C31 }, - { 0x2C02, UPPER_CASE, 0x2C32 }, - { 0x2C03, UPPER_CASE, 0x2C33 }, - { 0x2C04, UPPER_CASE, 0x2C34 }, - { 0x2C05, UPPER_CASE, 0x2C35 }, - { 0x2C06, UPPER_CASE, 0x2C36 }, - { 0x2C07, UPPER_CASE, 0x2C37 }, - { 0x2C08, UPPER_CASE, 0x2C38 }, - { 0x2C09, UPPER_CASE, 0x2C39 }, - { 0x2C0A, UPPER_CASE, 0x2C3A }, - { 0x2C0B, UPPER_CASE, 0x2C3B }, - { 0x2C0C, UPPER_CASE, 0x2C3C }, - { 0x2C0D, UPPER_CASE, 0x2C3D }, - { 0x2C0E, UPPER_CASE, 0x2C3E }, - { 0x2C0F, UPPER_CASE, 0x2C3F }, - { 0x2C10, UPPER_CASE, 0x2C40 }, - { 0x2C11, UPPER_CASE, 0x2C41 }, - { 0x2C12, UPPER_CASE, 0x2C42 }, - { 0x2C13, UPPER_CASE, 0x2C43 }, - { 0x2C14, UPPER_CASE, 0x2C44 }, - { 0x2C15, UPPER_CASE, 0x2C45 }, - { 0x2C16, UPPER_CASE, 0x2C46 }, - { 0x2C17, UPPER_CASE, 0x2C47 }, - { 0x2C18, UPPER_CASE, 0x2C48 }, - { 0x2C19, UPPER_CASE, 0x2C49 }, - { 0x2C1A, UPPER_CASE, 0x2C4A }, - { 0x2C1B, UPPER_CASE, 0x2C4B }, - { 0x2C1C, UPPER_CASE, 0x2C4C }, - { 0x2C1D, UPPER_CASE, 0x2C4D }, - { 0x2C1E, UPPER_CASE, 0x2C4E }, - { 0x2C1F, UPPER_CASE, 0x2C4F }, - { 0x2C20, UPPER_CASE, 0x2C50 }, - { 0x2C21, UPPER_CASE, 0x2C51 }, - { 0x2C22, UPPER_CASE, 0x2C52 }, - { 0x2C23, UPPER_CASE, 0x2C53 }, - { 0x2C24, UPPER_CASE, 0x2C54 }, - { 0x2C25, UPPER_CASE, 0x2C55 }, - { 0x2C26, UPPER_CASE, 0x2C56 }, - { 0x2C27, UPPER_CASE, 0x2C57 }, - { 0x2C28, UPPER_CASE, 0x2C58 }, - { 0x2C29, UPPER_CASE, 0x2C59 }, - { 0x2C2A, UPPER_CASE, 0x2C5A }, - { 0x2C2B, UPPER_CASE, 0x2C5B }, - { 0x2C2C, UPPER_CASE, 0x2C5C }, - { 0x2C2D, UPPER_CASE, 0x2C5D }, - { 0x2C2E, UPPER_CASE, 0x2C5E }, - { 0x2C2F, UPPER_CASE, 0x2C5F }, - { 0x2C30, LOWER_CASE, 0x2C00 }, - { 0x2C31, LOWER_CASE, 0x2C01 }, - { 0x2C32, LOWER_CASE, 0x2C02 }, - { 0x2C33, LOWER_CASE, 0x2C03 }, - { 0x2C34, LOWER_CASE, 0x2C04 }, - { 0x2C35, LOWER_CASE, 0x2C05 }, - { 0x2C36, LOWER_CASE, 0x2C06 }, - { 0x2C37, LOWER_CASE, 0x2C07 }, - { 0x2C38, LOWER_CASE, 0x2C08 }, - { 0x2C39, LOWER_CASE, 0x2C09 }, - { 0x2C3A, LOWER_CASE, 0x2C0A }, - { 0x2C3B, LOWER_CASE, 0x2C0B }, - { 0x2C3C, LOWER_CASE, 0x2C0C }, - { 0x2C3D, LOWER_CASE, 0x2C0D }, - { 0x2C3E, LOWER_CASE, 0x2C0E }, - { 0x2C3F, LOWER_CASE, 0x2C0F }, - { 0x2C40, LOWER_CASE, 0x2C10 }, - { 0x2C41, LOWER_CASE, 0x2C11 }, - { 0x2C42, LOWER_CASE, 0x2C12 }, - { 0x2C43, LOWER_CASE, 0x2C13 }, - { 0x2C44, LOWER_CASE, 0x2C14 }, - { 0x2C45, LOWER_CASE, 0x2C15 }, - { 0x2C46, LOWER_CASE, 0x2C16 }, - { 0x2C47, LOWER_CASE, 0x2C17 }, - { 0x2C48, LOWER_CASE, 0x2C18 }, - { 0x2C49, LOWER_CASE, 0x2C19 }, - { 0x2C4A, LOWER_CASE, 0x2C1A }, - { 0x2C4B, LOWER_CASE, 0x2C1B }, - { 0x2C4C, LOWER_CASE, 0x2C1C }, - { 0x2C4D, LOWER_CASE, 0x2C1D }, - { 0x2C4E, LOWER_CASE, 0x2C1E }, - { 0x2C4F, LOWER_CASE, 0x2C1F }, - { 0x2C50, LOWER_CASE, 0x2C20 }, - { 0x2C51, LOWER_CASE, 0x2C21 }, - { 0x2C52, LOWER_CASE, 0x2C22 }, - { 0x2C53, LOWER_CASE, 0x2C23 }, - { 0x2C54, LOWER_CASE, 0x2C24 }, - { 0x2C55, LOWER_CASE, 0x2C25 }, - { 0x2C56, LOWER_CASE, 0x2C26 }, - { 0x2C57, LOWER_CASE, 0x2C27 }, - { 0x2C58, LOWER_CASE, 0x2C28 }, - { 0x2C59, LOWER_CASE, 0x2C29 }, - { 0x2C5A, LOWER_CASE, 0x2C2A }, - { 0x2C5B, LOWER_CASE, 0x2C2B }, - { 0x2C5C, LOWER_CASE, 0x2C2C }, - { 0x2C5D, LOWER_CASE, 0x2C2D }, - { 0x2C5E, LOWER_CASE, 0x2C2E }, - { 0x2C5F, LOWER_CASE, 0x2C2F }, - { 0x2C60, UPPER_CASE, 0x2C61 }, - { 0x2C61, LOWER_CASE, 0x2C60 }, - { 0x2C62, UPPER_CASE, 0x26B }, - { 0x2C63, UPPER_CASE, 0x1D7D }, - { 0x2C64, UPPER_CASE, 0x27D }, - { 0x2C65, LOWER_CASE, 0x23A }, - { 0x2C66, LOWER_CASE, 0x23E }, - { 0x2C67, UPPER_CASE, 0x2C68 }, - { 0x2C68, LOWER_CASE, 0x2C67 }, - { 0x2C69, UPPER_CASE, 0x2C6A }, - { 0x2C6A, LOWER_CASE, 0x2C69 }, - { 0x2C6B, UPPER_CASE, 0x2C6C }, - { 0x2C6C, LOWER_CASE, 0x2C6B }, - { 0x2C6D, UPPER_CASE, 0x251 }, - { 0x2C6E, UPPER_CASE, 0x271 }, - { 0x2C6F, UPPER_CASE, 0x250 }, - { 0x2C70, UPPER_CASE, 0x252 }, - { 0x2C72, UPPER_CASE, 0x2C73 }, - { 0x2C73, LOWER_CASE, 0x2C72 }, - { 0x2C75, UPPER_CASE, 0x2C76 }, - { 0x2C76, LOWER_CASE, 0x2C75 }, - { 0x2C7E, UPPER_CASE, 0x23F }, - { 0x2C7F, UPPER_CASE, 0x240 }, - { 0x2C80, UPPER_CASE, 0x2C81 }, - { 0x2C81, LOWER_CASE, 0x2C80 }, - { 0x2C82, UPPER_CASE, 0x2C83 }, - { 0x2C83, LOWER_CASE, 0x2C82 }, - { 0x2C84, UPPER_CASE, 0x2C85 }, - { 0x2C85, LOWER_CASE, 0x2C84 }, - { 0x2C86, UPPER_CASE, 0x2C87 }, - { 0x2C87, LOWER_CASE, 0x2C86 }, - { 0x2C88, UPPER_CASE, 0x2C89 }, - { 0x2C89, LOWER_CASE, 0x2C88 }, - { 0x2C8A, UPPER_CASE, 0x2C8B }, - { 0x2C8B, LOWER_CASE, 0x2C8A }, - { 0x2C8C, UPPER_CASE, 0x2C8D }, - { 0x2C8D, LOWER_CASE, 0x2C8C }, - { 0x2C8E, UPPER_CASE, 0x2C8F }, - { 0x2C8F, LOWER_CASE, 0x2C8E }, - { 0x2C90, UPPER_CASE, 0x2C91 }, - { 0x2C91, LOWER_CASE, 0x2C90 }, - { 0x2C92, UPPER_CASE, 0x2C93 }, - { 0x2C93, LOWER_CASE, 0x2C92 }, - { 0x2C94, UPPER_CASE, 0x2C95 }, - { 0x2C95, LOWER_CASE, 0x2C94 }, - { 0x2C96, UPPER_CASE, 0x2C97 }, - { 0x2C97, LOWER_CASE, 0x2C96 }, - { 0x2C98, UPPER_CASE, 0x2C99 }, - { 0x2C99, LOWER_CASE, 0x2C98 }, - { 0x2C9A, UPPER_CASE, 0x2C9B }, - { 0x2C9B, LOWER_CASE, 0x2C9A }, - { 0x2C9C, UPPER_CASE, 0x2C9D }, - { 0x2C9D, LOWER_CASE, 0x2C9C }, - { 0x2C9E, UPPER_CASE, 0x2C9F }, - { 0x2C9F, LOWER_CASE, 0x2C9E }, - { 0x2CA0, UPPER_CASE, 0x2CA1 }, - { 0x2CA1, LOWER_CASE, 0x2CA0 }, - { 0x2CA2, UPPER_CASE, 0x2CA3 }, - { 0x2CA3, LOWER_CASE, 0x2CA2 }, - { 0x2CA4, UPPER_CASE, 0x2CA5 }, - { 0x2CA5, LOWER_CASE, 0x2CA4 }, - { 0x2CA6, UPPER_CASE, 0x2CA7 }, - { 0x2CA7, LOWER_CASE, 0x2CA6 }, - { 0x2CA8, UPPER_CASE, 0x2CA9 }, - { 0x2CA9, LOWER_CASE, 0x2CA8 }, - { 0x2CAA, UPPER_CASE, 0x2CAB }, - { 0x2CAB, LOWER_CASE, 0x2CAA }, - { 0x2CAC, UPPER_CASE, 0x2CAD }, - { 0x2CAD, LOWER_CASE, 0x2CAC }, - { 0x2CAE, UPPER_CASE, 0x2CAF }, - { 0x2CAF, LOWER_CASE, 0x2CAE }, - { 0x2CB0, UPPER_CASE, 0x2CB1 }, - { 0x2CB1, LOWER_CASE, 0x2CB0 }, - { 0x2CB2, UPPER_CASE, 0x2CB3 }, - { 0x2CB3, LOWER_CASE, 0x2CB2 }, - { 0x2CB4, UPPER_CASE, 0x2CB5 }, - { 0x2CB5, LOWER_CASE, 0x2CB4 }, - { 0x2CB6, UPPER_CASE, 0x2CB7 }, - { 0x2CB7, LOWER_CASE, 0x2CB6 }, - { 0x2CB8, UPPER_CASE, 0x2CB9 }, - { 0x2CB9, LOWER_CASE, 0x2CB8 }, - { 0x2CBA, UPPER_CASE, 0x2CBB }, - { 0x2CBB, LOWER_CASE, 0x2CBA }, - { 0x2CBC, UPPER_CASE, 0x2CBD }, - { 0x2CBD, LOWER_CASE, 0x2CBC }, - { 0x2CBE, UPPER_CASE, 0x2CBF }, - { 0x2CBF, LOWER_CASE, 0x2CBE }, - { 0x2CC0, UPPER_CASE, 0x2CC1 }, - { 0x2CC1, LOWER_CASE, 0x2CC0 }, - { 0x2CC2, UPPER_CASE, 0x2CC3 }, - { 0x2CC3, LOWER_CASE, 0x2CC2 }, - { 0x2CC4, UPPER_CASE, 0x2CC5 }, - { 0x2CC5, LOWER_CASE, 0x2CC4 }, - { 0x2CC6, UPPER_CASE, 0x2CC7 }, - { 0x2CC7, LOWER_CASE, 0x2CC6 }, - { 0x2CC8, UPPER_CASE, 0x2CC9 }, - { 0x2CC9, LOWER_CASE, 0x2CC8 }, - { 0x2CCA, UPPER_CASE, 0x2CCB }, - { 0x2CCB, LOWER_CASE, 0x2CCA }, - { 0x2CCC, UPPER_CASE, 0x2CCD }, - { 0x2CCD, LOWER_CASE, 0x2CCC }, - { 0x2CCE, UPPER_CASE, 0x2CCF }, - { 0x2CCF, LOWER_CASE, 0x2CCE }, - { 0x2CD0, UPPER_CASE, 0x2CD1 }, - { 0x2CD1, LOWER_CASE, 0x2CD0 }, - { 0x2CD2, UPPER_CASE, 0x2CD3 }, - { 0x2CD3, LOWER_CASE, 0x2CD2 }, - { 0x2CD4, UPPER_CASE, 0x2CD5 }, - { 0x2CD5, LOWER_CASE, 0x2CD4 }, - { 0x2CD6, UPPER_CASE, 0x2CD7 }, - { 0x2CD7, LOWER_CASE, 0x2CD6 }, - { 0x2CD8, UPPER_CASE, 0x2CD9 }, - { 0x2CD9, LOWER_CASE, 0x2CD8 }, - { 0x2CDA, UPPER_CASE, 0x2CDB }, - { 0x2CDB, LOWER_CASE, 0x2CDA }, - { 0x2CDC, UPPER_CASE, 0x2CDD }, - { 0x2CDD, LOWER_CASE, 0x2CDC }, - { 0x2CDE, UPPER_CASE, 0x2CDF }, - { 0x2CDF, LOWER_CASE, 0x2CDE }, - { 0x2CE0, UPPER_CASE, 0x2CE1 }, - { 0x2CE1, LOWER_CASE, 0x2CE0 }, - { 0x2CE2, UPPER_CASE, 0x2CE3 }, - { 0x2CE3, LOWER_CASE, 0x2CE2 }, - { 0x2CEB, UPPER_CASE, 0x2CEC }, - { 0x2CEC, LOWER_CASE, 0x2CEB }, - { 0x2CED, UPPER_CASE, 0x2CEE }, - { 0x2CEE, LOWER_CASE, 0x2CED }, - { 0x2CF2, UPPER_CASE, 0x2CF3 }, - { 0x2CF3, LOWER_CASE, 0x2CF2 }, - { 0x2D00, LOWER_CASE, 0x10A0 }, - { 0x2D01, LOWER_CASE, 0x10A1 }, - { 0x2D02, LOWER_CASE, 0x10A2 }, - { 0x2D03, LOWER_CASE, 0x10A3 }, - { 0x2D04, LOWER_CASE, 0x10A4 }, - { 0x2D05, LOWER_CASE, 0x10A5 }, - { 0x2D06, LOWER_CASE, 0x10A6 }, - { 0x2D07, LOWER_CASE, 0x10A7 }, - { 0x2D08, LOWER_CASE, 0x10A8 }, - { 0x2D09, LOWER_CASE, 0x10A9 }, - { 0x2D0A, LOWER_CASE, 0x10AA }, - { 0x2D0B, LOWER_CASE, 0x10AB }, - { 0x2D0C, LOWER_CASE, 0x10AC }, - { 0x2D0D, LOWER_CASE, 0x10AD }, - { 0x2D0E, LOWER_CASE, 0x10AE }, - { 0x2D0F, LOWER_CASE, 0x10AF }, - { 0x2D10, LOWER_CASE, 0x10B0 }, - { 0x2D11, LOWER_CASE, 0x10B1 }, - { 0x2D12, LOWER_CASE, 0x10B2 }, - { 0x2D13, LOWER_CASE, 0x10B3 }, - { 0x2D14, LOWER_CASE, 0x10B4 }, - { 0x2D15, LOWER_CASE, 0x10B5 }, - { 0x2D16, LOWER_CASE, 0x10B6 }, - { 0x2D17, LOWER_CASE, 0x10B7 }, - { 0x2D18, LOWER_CASE, 0x10B8 }, - { 0x2D19, LOWER_CASE, 0x10B9 }, - { 0x2D1A, LOWER_CASE, 0x10BA }, - { 0x2D1B, LOWER_CASE, 0x10BB }, - { 0x2D1C, LOWER_CASE, 0x10BC }, - { 0x2D1D, LOWER_CASE, 0x10BD }, - { 0x2D1E, LOWER_CASE, 0x10BE }, - { 0x2D1F, LOWER_CASE, 0x10BF }, - { 0x2D20, LOWER_CASE, 0x10C0 }, - { 0x2D21, LOWER_CASE, 0x10C1 }, - { 0x2D22, LOWER_CASE, 0x10C2 }, - { 0x2D23, LOWER_CASE, 0x10C3 }, - { 0x2D24, LOWER_CASE, 0x10C4 }, - { 0x2D25, LOWER_CASE, 0x10C5 }, - { 0x2D27, LOWER_CASE, 0x10C7 }, - { 0x2D2D, LOWER_CASE, 0x10CD }, - { 0xA640, UPPER_CASE, 0xA641 }, - { 0xA641, LOWER_CASE, 0xA640 }, - { 0xA642, UPPER_CASE, 0xA643 }, - { 0xA643, LOWER_CASE, 0xA642 }, - { 0xA644, UPPER_CASE, 0xA645 }, - { 0xA645, LOWER_CASE, 0xA644 }, - { 0xA646, UPPER_CASE, 0xA647 }, - { 0xA647, LOWER_CASE, 0xA646 }, - { 0xA648, UPPER_CASE, 0xA649 }, - { 0xA649, LOWER_CASE, 0xA648 }, - { 0xA64A, UPPER_CASE, 0xA64B }, - { 0xA64B, LOWER_CASE, 0xA64A }, - { 0xA64C, UPPER_CASE, 0xA64D }, - { 0xA64D, LOWER_CASE, 0xA64C }, - { 0xA64E, UPPER_CASE, 0xA64F }, - { 0xA64F, LOWER_CASE, 0xA64E }, - { 0xA650, UPPER_CASE, 0xA651 }, - { 0xA651, LOWER_CASE, 0xA650 }, - { 0xA652, UPPER_CASE, 0xA653 }, - { 0xA653, LOWER_CASE, 0xA652 }, - { 0xA654, UPPER_CASE, 0xA655 }, - { 0xA655, LOWER_CASE, 0xA654 }, - { 0xA656, UPPER_CASE, 0xA657 }, - { 0xA657, LOWER_CASE, 0xA656 }, - { 0xA658, UPPER_CASE, 0xA659 }, - { 0xA659, LOWER_CASE, 0xA658 }, - { 0xA65A, UPPER_CASE, 0xA65B }, - { 0xA65B, LOWER_CASE, 0xA65A }, - { 0xA65C, UPPER_CASE, 0xA65D }, - { 0xA65D, LOWER_CASE, 0xA65C }, - { 0xA65E, UPPER_CASE, 0xA65F }, - { 0xA65F, LOWER_CASE, 0xA65E }, - { 0xA660, UPPER_CASE, 0xA661 }, - { 0xA661, LOWER_CASE, 0xA660 }, - { 0xA662, UPPER_CASE, 0xA663 }, - { 0xA663, LOWER_CASE, 0xA662 }, - { 0xA664, UPPER_CASE, 0xA665 }, - { 0xA665, LOWER_CASE, 0xA664 }, - { 0xA666, UPPER_CASE, 0xA667 }, - { 0xA667, LOWER_CASE, 0xA666 }, - { 0xA668, UPPER_CASE, 0xA669 }, - { 0xA669, LOWER_CASE, 0xA668 }, - { 0xA66A, UPPER_CASE, 0xA66B }, - { 0xA66B, LOWER_CASE, 0xA66A }, - { 0xA66C, UPPER_CASE, 0xA66D }, - { 0xA66D, LOWER_CASE, 0xA66C }, - { 0xA680, UPPER_CASE, 0xA681 }, - { 0xA681, LOWER_CASE, 0xA680 }, - { 0xA682, UPPER_CASE, 0xA683 }, - { 0xA683, LOWER_CASE, 0xA682 }, - { 0xA684, UPPER_CASE, 0xA685 }, - { 0xA685, LOWER_CASE, 0xA684 }, - { 0xA686, UPPER_CASE, 0xA687 }, - { 0xA687, LOWER_CASE, 0xA686 }, - { 0xA688, UPPER_CASE, 0xA689 }, - { 0xA689, LOWER_CASE, 0xA688 }, - { 0xA68A, UPPER_CASE, 0xA68B }, - { 0xA68B, LOWER_CASE, 0xA68A }, - { 0xA68C, UPPER_CASE, 0xA68D }, - { 0xA68D, LOWER_CASE, 0xA68C }, - { 0xA68E, UPPER_CASE, 0xA68F }, - { 0xA68F, LOWER_CASE, 0xA68E }, - { 0xA690, UPPER_CASE, 0xA691 }, - { 0xA691, LOWER_CASE, 0xA690 }, - { 0xA692, UPPER_CASE, 0xA693 }, - { 0xA693, LOWER_CASE, 0xA692 }, - { 0xA694, UPPER_CASE, 0xA695 }, - { 0xA695, LOWER_CASE, 0xA694 }, - { 0xA696, UPPER_CASE, 0xA697 }, - { 0xA697, LOWER_CASE, 0xA696 }, - { 0xA698, UPPER_CASE, 0xA699 }, - { 0xA699, LOWER_CASE, 0xA698 }, - { 0xA69A, UPPER_CASE, 0xA69B }, - { 0xA69B, LOWER_CASE, 0xA69A }, - { 0xA722, UPPER_CASE, 0xA723 }, - { 0xA723, LOWER_CASE, 0xA722 }, - { 0xA724, UPPER_CASE, 0xA725 }, - { 0xA725, LOWER_CASE, 0xA724 }, - { 0xA726, UPPER_CASE, 0xA727 }, - { 0xA727, LOWER_CASE, 0xA726 }, - { 0xA728, UPPER_CASE, 0xA729 }, - { 0xA729, LOWER_CASE, 0xA728 }, - { 0xA72A, UPPER_CASE, 0xA72B }, - { 0xA72B, LOWER_CASE, 0xA72A }, - { 0xA72C, UPPER_CASE, 0xA72D }, - { 0xA72D, LOWER_CASE, 0xA72C }, - { 0xA72E, UPPER_CASE, 0xA72F }, - { 0xA72F, LOWER_CASE, 0xA72E }, - { 0xA732, UPPER_CASE, 0xA733 }, - { 0xA733, LOWER_CASE, 0xA732 }, - { 0xA734, UPPER_CASE, 0xA735 }, - { 0xA735, LOWER_CASE, 0xA734 }, - { 0xA736, UPPER_CASE, 0xA737 }, - { 0xA737, LOWER_CASE, 0xA736 }, - { 0xA738, UPPER_CASE, 0xA739 }, - { 0xA739, LOWER_CASE, 0xA738 }, - { 0xA73A, UPPER_CASE, 0xA73B }, - { 0xA73B, LOWER_CASE, 0xA73A }, - { 0xA73C, UPPER_CASE, 0xA73D }, - { 0xA73D, LOWER_CASE, 0xA73C }, - { 0xA73E, UPPER_CASE, 0xA73F }, - { 0xA73F, LOWER_CASE, 0xA73E }, - { 0xA740, UPPER_CASE, 0xA741 }, - { 0xA741, LOWER_CASE, 0xA740 }, - { 0xA742, UPPER_CASE, 0xA743 }, - { 0xA743, LOWER_CASE, 0xA742 }, - { 0xA744, UPPER_CASE, 0xA745 }, - { 0xA745, LOWER_CASE, 0xA744 }, - { 0xA746, UPPER_CASE, 0xA747 }, - { 0xA747, LOWER_CASE, 0xA746 }, - { 0xA748, UPPER_CASE, 0xA749 }, - { 0xA749, LOWER_CASE, 0xA748 }, - { 0xA74A, UPPER_CASE, 0xA74B }, - { 0xA74B, LOWER_CASE, 0xA74A }, - { 0xA74C, UPPER_CASE, 0xA74D }, - { 0xA74D, LOWER_CASE, 0xA74C }, - { 0xA74E, UPPER_CASE, 0xA74F }, - { 0xA74F, LOWER_CASE, 0xA74E }, - { 0xA750, UPPER_CASE, 0xA751 }, - { 0xA751, LOWER_CASE, 0xA750 }, - { 0xA752, UPPER_CASE, 0xA753 }, - { 0xA753, LOWER_CASE, 0xA752 }, - { 0xA754, UPPER_CASE, 0xA755 }, - { 0xA755, LOWER_CASE, 0xA754 }, - { 0xA756, UPPER_CASE, 0xA757 }, - { 0xA757, LOWER_CASE, 0xA756 }, - { 0xA758, UPPER_CASE, 0xA759 }, - { 0xA759, LOWER_CASE, 0xA758 }, - { 0xA75A, UPPER_CASE, 0xA75B }, - { 0xA75B, LOWER_CASE, 0xA75A }, - { 0xA75C, UPPER_CASE, 0xA75D }, - { 0xA75D, LOWER_CASE, 0xA75C }, - { 0xA75E, UPPER_CASE, 0xA75F }, - { 0xA75F, LOWER_CASE, 0xA75E }, - { 0xA760, UPPER_CASE, 0xA761 }, - { 0xA761, LOWER_CASE, 0xA760 }, - { 0xA762, UPPER_CASE, 0xA763 }, - { 0xA763, LOWER_CASE, 0xA762 }, - { 0xA764, UPPER_CASE, 0xA765 }, - { 0xA765, LOWER_CASE, 0xA764 }, - { 0xA766, UPPER_CASE, 0xA767 }, - { 0xA767, LOWER_CASE, 0xA766 }, - { 0xA768, UPPER_CASE, 0xA769 }, - { 0xA769, LOWER_CASE, 0xA768 }, - { 0xA76A, UPPER_CASE, 0xA76B }, - { 0xA76B, LOWER_CASE, 0xA76A }, - { 0xA76C, UPPER_CASE, 0xA76D }, - { 0xA76D, LOWER_CASE, 0xA76C }, - { 0xA76E, UPPER_CASE, 0xA76F }, - { 0xA76F, LOWER_CASE, 0xA76E }, - { 0xA779, UPPER_CASE, 0xA77A }, - { 0xA77A, LOWER_CASE, 0xA779 }, - { 0xA77B, UPPER_CASE, 0xA77C }, - { 0xA77C, LOWER_CASE, 0xA77B }, - { 0xA77D, UPPER_CASE, 0x1D79 }, - { 0xA77E, UPPER_CASE, 0xA77F }, - { 0xA77F, LOWER_CASE, 0xA77E }, - { 0xA780, UPPER_CASE, 0xA781 }, - { 0xA781, LOWER_CASE, 0xA780 }, - { 0xA782, UPPER_CASE, 0xA783 }, - { 0xA783, LOWER_CASE, 0xA782 }, - { 0xA784, UPPER_CASE, 0xA785 }, - { 0xA785, LOWER_CASE, 0xA784 }, - { 0xA786, UPPER_CASE, 0xA787 }, - { 0xA787, LOWER_CASE, 0xA786 }, - { 0xA78B, UPPER_CASE, 0xA78C }, - { 0xA78C, LOWER_CASE, 0xA78B }, - { 0xA78D, UPPER_CASE, 0x265 }, - { 0xA790, UPPER_CASE, 0xA791 }, - { 0xA791, LOWER_CASE, 0xA790 }, - { 0xA792, UPPER_CASE, 0xA793 }, - { 0xA793, LOWER_CASE, 0xA792 }, - { 0xA794, LOWER_CASE, 0xA7C4 }, - { 0xA796, UPPER_CASE, 0xA797 }, - { 0xA797, LOWER_CASE, 0xA796 }, - { 0xA798, UPPER_CASE, 0xA799 }, - { 0xA799, LOWER_CASE, 0xA798 }, - { 0xA79A, UPPER_CASE, 0xA79B }, - { 0xA79B, LOWER_CASE, 0xA79A }, - { 0xA79C, UPPER_CASE, 0xA79D }, - { 0xA79D, LOWER_CASE, 0xA79C }, - { 0xA79E, UPPER_CASE, 0xA79F }, - { 0xA79F, LOWER_CASE, 0xA79E }, - { 0xA7A0, UPPER_CASE, 0xA7A1 }, - { 0xA7A1, LOWER_CASE, 0xA7A0 }, - { 0xA7A2, UPPER_CASE, 0xA7A3 }, - { 0xA7A3, LOWER_CASE, 0xA7A2 }, - { 0xA7A4, UPPER_CASE, 0xA7A5 }, - { 0xA7A5, LOWER_CASE, 0xA7A4 }, - { 0xA7A6, UPPER_CASE, 0xA7A7 }, - { 0xA7A7, LOWER_CASE, 0xA7A6 }, - { 0xA7A8, UPPER_CASE, 0xA7A9 }, - { 0xA7A9, LOWER_CASE, 0xA7A8 }, - { 0xA7AA, UPPER_CASE, 0x266 }, - { 0xA7AB, UPPER_CASE, 0x25C }, - { 0xA7AC, UPPER_CASE, 0x261 }, - { 0xA7AD, UPPER_CASE, 0x26C }, - { 0xA7AE, UPPER_CASE, 0x26A }, - { 0xA7B0, UPPER_CASE, 0x29E }, - { 0xA7B1, UPPER_CASE, 0x287 }, - { 0xA7B2, UPPER_CASE, 0x29D }, - { 0xA7B3, UPPER_CASE, 0xAB53 }, - { 0xA7B4, UPPER_CASE, 0xA7B5 }, - { 0xA7B5, LOWER_CASE, 0xA7B4 }, - { 0xA7B6, UPPER_CASE, 0xA7B7 }, - { 0xA7B7, LOWER_CASE, 0xA7B6 }, - { 0xA7B8, UPPER_CASE, 0xA7B9 }, - { 0xA7B9, LOWER_CASE, 0xA7B8 }, - { 0xA7BA, UPPER_CASE, 0xA7BB }, - { 0xA7BB, LOWER_CASE, 0xA7BA }, - { 0xA7BC, UPPER_CASE, 0xA7BD }, - { 0xA7BD, LOWER_CASE, 0xA7BC }, - { 0xA7BE, UPPER_CASE, 0xA7BF }, - { 0xA7BF, LOWER_CASE, 0xA7BE }, - { 0xA7C0, UPPER_CASE, 0xA7C1 }, - { 0xA7C1, LOWER_CASE, 0xA7C0 }, - { 0xA7C2, UPPER_CASE, 0xA7C3 }, - { 0xA7C3, LOWER_CASE, 0xA7C2 }, - { 0xA7C4, UPPER_CASE, 0xA794 }, - { 0xA7C5, UPPER_CASE, 0x282 }, - { 0xA7C6, UPPER_CASE, 0x1D8E }, - { 0xA7C7, UPPER_CASE, 0xA7C8 }, - { 0xA7C8, LOWER_CASE, 0xA7C7 }, - { 0xA7C9, UPPER_CASE, 0xA7CA }, - { 0xA7CA, LOWER_CASE, 0xA7C9 }, - { 0xA7D0, UPPER_CASE, 0xA7D1 }, - { 0xA7D1, LOWER_CASE, 0xA7D0 }, - { 0xA7D6, UPPER_CASE, 0xA7D7 }, - { 0xA7D7, LOWER_CASE, 0xA7D6 }, - { 0xA7D8, UPPER_CASE, 0xA7D9 }, - { 0xA7D9, LOWER_CASE, 0xA7D8 }, - { 0xA7F5, UPPER_CASE, 0xA7F6 }, - { 0xA7F6, LOWER_CASE, 0xA7F5 }, - { 0xAB53, LOWER_CASE, 0xA7B3 }, - { 0xAB70, LOWER_CASE, 0x13A0 }, - { 0xAB71, LOWER_CASE, 0x13A1 }, - { 0xAB72, LOWER_CASE, 0x13A2 }, - { 0xAB73, LOWER_CASE, 0x13A3 }, - { 0xAB74, LOWER_CASE, 0x13A4 }, - { 0xAB75, LOWER_CASE, 0x13A5 }, - { 0xAB76, LOWER_CASE, 0x13A6 }, - { 0xAB77, LOWER_CASE, 0x13A7 }, - { 0xAB78, LOWER_CASE, 0x13A8 }, - { 0xAB79, LOWER_CASE, 0x13A9 }, - { 0xAB7A, LOWER_CASE, 0x13AA }, - { 0xAB7B, LOWER_CASE, 0x13AB }, - { 0xAB7C, LOWER_CASE, 0x13AC }, - { 0xAB7D, LOWER_CASE, 0x13AD }, - { 0xAB7E, LOWER_CASE, 0x13AE }, - { 0xAB7F, LOWER_CASE, 0x13AF }, - { 0xAB80, LOWER_CASE, 0x13B0 }, - { 0xAB81, LOWER_CASE, 0x13B1 }, - { 0xAB82, LOWER_CASE, 0x13B2 }, - { 0xAB83, LOWER_CASE, 0x13B3 }, - { 0xAB84, LOWER_CASE, 0x13B4 }, - { 0xAB85, LOWER_CASE, 0x13B5 }, - { 0xAB86, LOWER_CASE, 0x13B6 }, - { 0xAB87, LOWER_CASE, 0x13B7 }, - { 0xAB88, LOWER_CASE, 0x13B8 }, - { 0xAB89, LOWER_CASE, 0x13B9 }, - { 0xAB8A, LOWER_CASE, 0x13BA }, - { 0xAB8B, LOWER_CASE, 0x13BB }, - { 0xAB8C, LOWER_CASE, 0x13BC }, - { 0xAB8D, LOWER_CASE, 0x13BD }, - { 0xAB8E, LOWER_CASE, 0x13BE }, - { 0xAB8F, LOWER_CASE, 0x13BF }, - { 0xAB90, LOWER_CASE, 0x13C0 }, - { 0xAB91, LOWER_CASE, 0x13C1 }, - { 0xAB92, LOWER_CASE, 0x13C2 }, - { 0xAB93, LOWER_CASE, 0x13C3 }, - { 0xAB94, LOWER_CASE, 0x13C4 }, - { 0xAB95, LOWER_CASE, 0x13C5 }, - { 0xAB96, LOWER_CASE, 0x13C6 }, - { 0xAB97, LOWER_CASE, 0x13C7 }, - { 0xAB98, LOWER_CASE, 0x13C8 }, - { 0xAB99, LOWER_CASE, 0x13C9 }, - { 0xAB9A, LOWER_CASE, 0x13CA }, - { 0xAB9B, LOWER_CASE, 0x13CB }, - { 0xAB9C, LOWER_CASE, 0x13CC }, - { 0xAB9D, LOWER_CASE, 0x13CD }, - { 0xAB9E, LOWER_CASE, 0x13CE }, - { 0xAB9F, LOWER_CASE, 0x13CF }, - { 0xABA0, LOWER_CASE, 0x13D0 }, - { 0xABA1, LOWER_CASE, 0x13D1 }, - { 0xABA2, LOWER_CASE, 0x13D2 }, - { 0xABA3, LOWER_CASE, 0x13D3 }, - { 0xABA4, LOWER_CASE, 0x13D4 }, - { 0xABA5, LOWER_CASE, 0x13D5 }, - { 0xABA6, LOWER_CASE, 0x13D6 }, - { 0xABA7, LOWER_CASE, 0x13D7 }, - { 0xABA8, LOWER_CASE, 0x13D8 }, - { 0xABA9, LOWER_CASE, 0x13D9 }, - { 0xABAA, LOWER_CASE, 0x13DA }, - { 0xABAB, LOWER_CASE, 0x13DB }, - { 0xABAC, LOWER_CASE, 0x13DC }, - { 0xABAD, LOWER_CASE, 0x13DD }, - { 0xABAE, LOWER_CASE, 0x13DE }, - { 0xABAF, LOWER_CASE, 0x13DF }, - { 0xABB0, LOWER_CASE, 0x13E0 }, - { 0xABB1, LOWER_CASE, 0x13E1 }, - { 0xABB2, LOWER_CASE, 0x13E2 }, - { 0xABB3, LOWER_CASE, 0x13E3 }, - { 0xABB4, LOWER_CASE, 0x13E4 }, - { 0xABB5, LOWER_CASE, 0x13E5 }, - { 0xABB6, LOWER_CASE, 0x13E6 }, - { 0xABB7, LOWER_CASE, 0x13E7 }, - { 0xABB8, LOWER_CASE, 0x13E8 }, - { 0xABB9, LOWER_CASE, 0x13E9 }, - { 0xABBA, LOWER_CASE, 0x13EA }, - { 0xABBB, LOWER_CASE, 0x13EB }, - { 0xABBC, LOWER_CASE, 0x13EC }, - { 0xABBD, LOWER_CASE, 0x13ED }, - { 0xABBE, LOWER_CASE, 0x13EE }, - { 0xABBF, LOWER_CASE, 0x13EF }, - { 0xFF21, UPPER_CASE, 0xFF41 }, - { 0xFF22, UPPER_CASE, 0xFF42 }, - { 0xFF23, UPPER_CASE, 0xFF43 }, - { 0xFF24, UPPER_CASE, 0xFF44 }, - { 0xFF25, UPPER_CASE, 0xFF45 }, - { 0xFF26, UPPER_CASE, 0xFF46 }, - { 0xFF27, UPPER_CASE, 0xFF47 }, - { 0xFF28, UPPER_CASE, 0xFF48 }, - { 0xFF29, UPPER_CASE, 0xFF49 }, - { 0xFF2A, UPPER_CASE, 0xFF4A }, - { 0xFF2B, UPPER_CASE, 0xFF4B }, - { 0xFF2C, UPPER_CASE, 0xFF4C }, - { 0xFF2D, UPPER_CASE, 0xFF4D }, - { 0xFF2E, UPPER_CASE, 0xFF4E }, - { 0xFF2F, UPPER_CASE, 0xFF4F }, - { 0xFF30, UPPER_CASE, 0xFF50 }, - { 0xFF31, UPPER_CASE, 0xFF51 }, - { 0xFF32, UPPER_CASE, 0xFF52 }, - { 0xFF33, UPPER_CASE, 0xFF53 }, - { 0xFF34, UPPER_CASE, 0xFF54 }, - { 0xFF35, UPPER_CASE, 0xFF55 }, - { 0xFF36, UPPER_CASE, 0xFF56 }, - { 0xFF37, UPPER_CASE, 0xFF57 }, - { 0xFF38, UPPER_CASE, 0xFF58 }, - { 0xFF39, UPPER_CASE, 0xFF59 }, - { 0xFF3A, UPPER_CASE, 0xFF5A }, - { 0xFF41, LOWER_CASE, 0xFF21 }, - { 0xFF42, LOWER_CASE, 0xFF22 }, - { 0xFF43, LOWER_CASE, 0xFF23 }, - { 0xFF44, LOWER_CASE, 0xFF24 }, - { 0xFF45, LOWER_CASE, 0xFF25 }, - { 0xFF46, LOWER_CASE, 0xFF26 }, - { 0xFF47, LOWER_CASE, 0xFF27 }, - { 0xFF48, LOWER_CASE, 0xFF28 }, - { 0xFF49, LOWER_CASE, 0xFF29 }, - { 0xFF4A, LOWER_CASE, 0xFF2A }, - { 0xFF4B, LOWER_CASE, 0xFF2B }, - { 0xFF4C, LOWER_CASE, 0xFF2C }, - { 0xFF4D, LOWER_CASE, 0xFF2D }, - { 0xFF4E, LOWER_CASE, 0xFF2E }, - { 0xFF4F, LOWER_CASE, 0xFF2F }, - { 0xFF50, LOWER_CASE, 0xFF30 }, - { 0xFF51, LOWER_CASE, 0xFF31 }, - { 0xFF52, LOWER_CASE, 0xFF32 }, - { 0xFF53, LOWER_CASE, 0xFF33 }, - { 0xFF54, LOWER_CASE, 0xFF34 }, - { 0xFF55, LOWER_CASE, 0xFF35 }, - { 0xFF56, LOWER_CASE, 0xFF36 }, - { 0xFF57, LOWER_CASE, 0xFF37 }, - { 0xFF58, LOWER_CASE, 0xFF38 }, - { 0xFF59, LOWER_CASE, 0xFF39 }, - { 0xFF5A, LOWER_CASE, 0xFF3A }, -}; -CONST UINT UNICODE_DATA_SIZE = sizeof(UnicodeData)/sizeof(UnicodeDataRec); diff --git a/src/coreclr/pal/src/locale/unicodedata.cs b/src/coreclr/pal/src/locale/unicodedata.cs deleted file mode 100644 index 955b96fe955d..000000000000 --- a/src/coreclr/pal/src/locale/unicodedata.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; - -class Program -{ - static void Main(string[] args) - { - Console.WriteLine("// Licensed to the .NET Foundation under one or more agreements."); - Console.WriteLine("// The .NET Foundation licenses this file to you under the MIT license."); - Console.WriteLine(); - - Console.WriteLine("#include \"pal/unicodedata.h\""); - - Console.WriteLine(); - Console.WriteLine("//"); - Console.WriteLine("// THIS FILE IS GENERATED. DO NOT HAND EDIT."); - Console.WriteLine("// IF YOU NEED TO UPDATE UNICODE VERSION FOLLOW THE GUIDE AT src/libraries/System.Private.CoreLib/Tools/GenUnicodeProp/Updating-Unicode-Versions.md"); - Console.WriteLine("//"); - Console.WriteLine(); - - Console.WriteLine("CONST UnicodeDataRec UnicodeData[] = {"); - - string sourceFileName = args[0]; - - using (StreamReader sourceFile = File.OpenText(sourceFileName)) - while (sourceFile.ReadLine() is string line) - { - var fields = line.Split(';'); - - var code = int.Parse(fields[0], NumberStyles.HexNumber); - - bool hasUpperCaseMapping = fields[12].Length != 0; - bool hasLowerCaseMapping = fields[13].Length != 0; - - if (!hasLowerCaseMapping && !hasUpperCaseMapping) - continue; - - - int opposingCase = hasUpperCaseMapping ? - int.Parse(fields[12], NumberStyles.HexNumber) : - int.Parse(fields[13], NumberStyles.HexNumber); - - // These won't fit in 16 bits - no point carrying them - if (code > 0xFFFF) - continue; - - Debug.Assert(opposingCase <= 0xFFFF); - - string specifier = hasUpperCaseMapping ? "LOWER_CASE" : "UPPER_CASE"; - - Console.WriteLine($" {{ 0x{code:X}, {specifier}, 0x{opposingCase:X} }},"); - } - - Console.WriteLine("};"); - - Console.WriteLine("CONST UINT UNICODE_DATA_SIZE = sizeof(UnicodeData)/sizeof(UnicodeDataRec);"); - } -} diff --git a/src/coreclr/pal/src/misc/dbgmsg.cpp b/src/coreclr/pal/src/misc/dbgmsg.cpp index a5f98a0b0d32..38f101d147f6 100644 --- a/src/coreclr/pal/src/misc/dbgmsg.cpp +++ b/src/coreclr/pal/src/misc/dbgmsg.cpp @@ -670,10 +670,10 @@ int DBG_change_entrylevel(int new_level) { return 0; } - old_level = PtrToInt(pthread_getspecific(entry_level_key)); + old_level = (int)(intptr_t)pthread_getspecific(entry_level_key); if(-1 != new_level) { - if ((ret = pthread_setspecific(entry_level_key,(LPVOID)(IntToPtr(new_level)))) != 0) + if ((ret = pthread_setspecific(entry_level_key,(LPVOID)(intptr_t)new_level)) != 0) { fprintf(stderr, "ERROR : pthread_setspecific() failed " "error:%d (%s)\n", ret, strerror(ret)); diff --git a/src/coreclr/pal/src/misc/perftrace.cpp b/src/coreclr/pal/src/misc/perftrace.cpp index 9419005099f4..691c9048cb57 100644 --- a/src/coreclr/pal/src/misc/perftrace.cpp +++ b/src/coreclr/pal/src/misc/perftrace.cpp @@ -1021,7 +1021,7 @@ PERFLogFunctionEntry(unsigned int pal_api_id, ULONGLONG *pal_perf_start_tick ) pal_perf_thread_info * local_info=NULL; pal_perf_api_info * table; char * write_buf; - __int32 buf_off; + int32_t buf_off; short bufused = 0; diff --git a/src/coreclr/pal/src/safecrt/input.inl b/src/coreclr/pal/src/safecrt/input.inl index 556fafa6f6b4..1ee887c2ad73 100644 --- a/src/coreclr/pal/src/safecrt/input.inl +++ b/src/coreclr/pal/src/safecrt/input.inl @@ -28,8 +28,6 @@ #define _INTEGRAL_MAX_BITS 64 #endif /* _INTEGRAL_MAX_BITS */ -// typedef __int64_t __int64; - #ifndef FALSE #define FALSE 0 #endif @@ -373,14 +371,14 @@ static int __check_float_string(size_t nFloatStrUsed, (*(format + 1) == _T('x')) || (*(format + 1) == _T('X')) ) { - if (sizeof(void*) == sizeof(__int64)) + if (sizeof(void*) == sizeof(int64_t)) { ++integer64; num64 = 0; } break; } - if (sizeof(void*) == sizeof(__int64)) + if (sizeof(void*) == sizeof(int64_t)) { ++integer64; num64 = 0; @@ -901,7 +899,7 @@ getnum: } /* end of WHILE loop */ if (negative) - num64 = (uint64_t )(-(__int64)num64); + num64 = (uint64_t )(-(int64_t)num64); } else { #endif /* _INTEGRAL_MAX_BITS >= 64 */ @@ -958,7 +956,7 @@ getnum: assign_num: #if _INTEGRAL_MAX_BITS >= 64 if ( integer64 ) - *(__int64 UNALIGNED *)pointer = ( uint64_t )num64; + *(int64_t UNALIGNED *)pointer = ( uint64_t )num64; else #endif /* _INTEGRAL_MAX_BITS >= 64 */ if (longone) diff --git a/src/coreclr/pal/src/safecrt/mbusafecrt.cpp b/src/coreclr/pal/src/safecrt/mbusafecrt.cpp index e2f3d0403342..03c9495155d7 100644 --- a/src/coreclr/pal/src/safecrt/mbusafecrt.cpp +++ b/src/coreclr/pal/src/safecrt/mbusafecrt.cpp @@ -144,49 +144,6 @@ int _ungetwc_nolock( char16_t inChar, miniFILE* inStream ) } -/*** -* _safecrt_cfltcvt - convert a float to an ascii string. -****/ - -/* routine used for floating-point output */ -#define FORMATSIZE 30 - -// taken from output.inl -#define FL_ALTERNATE 0x00080 /* alternate form requested */ - -errno_t _safecrt_cfltcvt(double *arg, char *buffer, size_t sizeInBytes, int type, int precision, int flags) -{ - char format[FORMATSIZE]; - size_t formatlen = 0; - int retvalue; - - if (flags & 1) - { - type -= 'a' - 'A'; - } - formatlen = 0; - format[formatlen++] = '%'; - if (flags & FL_ALTERNATE) - { - format[formatlen++] = '#'; - } - format[formatlen++] = '.'; - _itoa_s(precision, format + formatlen, FORMATSIZE - formatlen, 10); - formatlen = strlen(format); - format[formatlen++] = (char)type; - format[formatlen] = 0; - - buffer[sizeInBytes - 1] = 0; - retvalue = snprintf(buffer, sizeInBytes, format, *arg); - if (buffer[sizeInBytes - 1] != 0 || retvalue <= 0) - { - buffer[0] = 0; - return EINVAL; - } - return 0; -} - - /*** * _safecrt_fassign - convert a string into a float or double. ****/ diff --git a/src/coreclr/pal/src/safecrt/mbusafecrt_internal.h b/src/coreclr/pal/src/safecrt/mbusafecrt_internal.h index 9929ae280666..c8b14e9f49d3 100644 --- a/src/coreclr/pal/src/safecrt/mbusafecrt_internal.h +++ b/src/coreclr/pal/src/safecrt/mbusafecrt_internal.h @@ -80,8 +80,6 @@ int _getwc_nolock( miniFILE* inStream ); int _ungetc_nolock( char inChar, miniFILE* inStream ); int _ungetwc_nolock( char16_t inChar, miniFILE* inStream ); -errno_t _safecrt_cfltcvt(double *arg, char *buffer, size_t sizeInBytes, int type, int precision, int flags); - void _safecrt_fassign(int flag, void* argument, char * number ); void _safecrt_wfassign(int flag, void* argument, char16_t * number ); diff --git a/src/coreclr/pal/src/safecrt/wcslwr_s.cpp b/src/coreclr/pal/src/safecrt/wcslwr_s.cpp index 184776f21ee9..85936d840e68 100644 --- a/src/coreclr/pal/src/safecrt/wcslwr_s.cpp +++ b/src/coreclr/pal/src/safecrt/wcslwr_s.cpp @@ -11,10 +11,10 @@ * *******************************************************************************/ -#include #include #include #include +#include #include "internal_securecrt.h" #include "mbusafecrt_internal.h" @@ -30,7 +30,7 @@ DLLEXPORT errno_t __cdecl _wcslwr_s(char16_t *string, size_t sz) for (int i = 0; string[i] != 0; i++) { - string[i] = (char16_t)towlower(string[i]); + string[i] = (char16_t)minipal_tolower_invariant(string[i]); } _FILL_STRING(string, sz, length + 1); diff --git a/src/coreclr/pal/src/safecrt/xtoa_s.cpp b/src/coreclr/pal/src/safecrt/xtoa_s.cpp deleted file mode 100644 index d930adb15644..000000000000 --- a/src/coreclr/pal/src/safecrt/xtoa_s.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*** -*xtoa_s.c - convert integers to ASCII strings -* - -* -*Purpose: -* defines _*tox_s() functions - convert integers to ASCII strings -* -*******************************************************************************/ -#include "pal/palinternal.h" -#include -#include -#include -#include "internal_securecrt.h" - -#include "mbusafecrt_internal.h" - -//#define __int64 long long - -#define _SECURE_ITOA - -#define TCHAR char -#define _T(x) x -#include "xtox_s.inl" diff --git a/src/coreclr/pal/src/safecrt/xtow_s.cpp b/src/coreclr/pal/src/safecrt/xtow_s.cpp deleted file mode 100644 index 127a1e766fb7..000000000000 --- a/src/coreclr/pal/src/safecrt/xtow_s.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*** -*xtow_s.c - convert integers to UTF-16 strings -* - -* -*Purpose: -* defines _*tox_s() functions - convert integers to UTF-16 strings -* -*******************************************************************************/ - -#include -#include -#include -#include "internal_securecrt.h" - -#include "mbusafecrt_internal.h" - -#define _SECURE_ITOA - -#define _UNICODE -#define TCHAR char16_t -#define _T(x) L##x -#include "xtox_s.inl" diff --git a/src/coreclr/pal/src/safecrt/xtox_s.inl b/src/coreclr/pal/src/safecrt/xtox_s.inl deleted file mode 100644 index f2284fa4ab50..000000000000 --- a/src/coreclr/pal/src/safecrt/xtox_s.inl +++ /dev/null @@ -1,414 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*** -*xtoa.c - convert integers/longs to ASCII string -* - -* -*Purpose: -* The module has code to convert integers/longs to ASCII strings. See -* -*******************************************************************************/ - -#ifdef _UNICODE -#define xtox_s xtow_s -#define _itox_s _itow_s -#define _ltox_s _ltow_s -#define _ultox_s _ultow_s -#define _i64tox_s _i64tow_s -#define xtox xtow -#define _ltox _ltow -#define _ultox _ultow -#else /* _UNICODE */ -#define xtox_s xtoa_s -#define _itox_s _itoa_s -#define _ltox_s _ltoa_s -#define _ultox_s _ultoa_s -#define _i64tox_s _i64toa_s -#define xtox xtoa -#define _ltox _ltoa -#define _ultox _ultoa -#endif /* _UNICODE */ - -/*** -*char *_itoa_s, *_ltoa_s, *_ultoa_s(val, buf, sizeInTChars, radix) - convert binary int to ASCII -* string -* -*Purpose: -* Converts an int to a character string. -* -*Entry: -* val - number to be converted (int, long or unsigned long) -* char *buf - ptr to buffer to place result -* size_t sizeInTChars - size of the destination buffer -* int radix - base to convert into -* -*Exit: -* Fills in space pointed to by buf with string result. -* Returns the errno_t: err != 0 means that something went wrong, and -* an empty string (buf[0] = 0) is returned. -* -*Exceptions: -* Input parameters and buffer length are validated. -* Refer to the validation section of the function. -* -*******************************************************************************/ - -/* helper routine that does the main job. */ -#ifdef _SECURE_ITOA -static errno_t __stdcall xtox_s - ( - unsigned long val, - TCHAR *buf, - size_t sizeInTChars, - unsigned radix, - int is_neg - ) -#else /* _SECURE_ITOA */ -static void __stdcall xtox - ( - unsigned long val, - TCHAR *buf, - unsigned radix, - int is_neg - ) -#endif /* _SECURE_ITOA */ -{ - TCHAR *p; /* pointer to traverse string */ - TCHAR *firstdig; /* pointer to first digit */ - TCHAR temp; /* temp char */ - unsigned digval; /* value of digit */ -#ifdef _SECURE_ITOA - size_t length; /* current length of the string */ - - /* validation section */ - _VALIDATE_RETURN_ERRCODE(buf != NULL, EINVAL); - _VALIDATE_RETURN_ERRCODE(sizeInTChars > 0, EINVAL); - _RESET_STRING(buf, sizeInTChars); - _VALIDATE_RETURN_ERRCODE(sizeInTChars > (size_t)(is_neg ? 2 : 1), ERANGE); - _VALIDATE_RETURN_ERRCODE(2 <= radix && radix <= 36, EINVAL); - length = 0; - -#endif /* _SECURE_ITOA */ - p = buf; - - if (is_neg) { - /* negative, so output '-' and negate */ - *p++ = _T('-'); -#ifdef _SECURE_ITOA - length++; -#endif /* _SECURE_ITOA */ - val = (unsigned long)(-(long)val); - } - - firstdig = p; /* save pointer to first digit */ - - do { - digval = (unsigned) (val % radix); - val /= radix; /* get next digit */ - - /* convert to ascii and store */ - if (digval > 9) - *p++ = (TCHAR) (digval - 10 + _T('a')); /* a letter */ - else - *p++ = (TCHAR) (digval + _T('0')); /* a digit */ -#ifndef _SECURE_ITOA - } while (val > 0); -#else /* _SECURE_ITOA */ - length++; - } while (val > 0 && length < sizeInTChars); - - /* Check for buffer overrun */ - if (length >= sizeInTChars) - { - buf[0] = '\0'; - _VALIDATE_RETURN_ERRCODE(length < sizeInTChars, ERANGE); - } -#endif /* _SECURE_ITOA */ - /* We now have the digit of the number in the buffer, but in reverse - order. Thus we reverse them now. */ - - *p-- = _T('\0'); /* terminate string; p points to last digit */ - - do { - temp = *p; - *p = *firstdig; - *firstdig = temp; /* swap *p and *firstdig */ - --p; - ++firstdig; /* advance to next two digits */ - } while (firstdig < p); /* repeat until halfway */ -#ifdef _SECURE_ITOA - return 0; -#endif /* _SECURE_ITOA */ -} - -/* Actual functions just call conversion helper with neg flag set correctly, - and return pointer to buffer. */ - -#ifdef _SECURE_ITOA -DLLEXPORT errno_t __cdecl _itox_s ( - int val, - TCHAR *buf, - size_t sizeInTChars, - int radix - ) -{ - errno_t e = 0; - - if (radix == 10 && val < 0) - e = xtox_s((unsigned long)val, buf, sizeInTChars, radix, 1); - else - e = xtox_s((unsigned long)(unsigned int)val, buf, sizeInTChars, radix, 0); - - return e; -} - -errno_t __cdecl _ltox_s ( - long val, - TCHAR *buf, - size_t sizeInTChars, - int radix - ) -{ - return xtox_s((unsigned long)val, buf, sizeInTChars, radix, (radix == 10 && val < 0)); -} - -errno_t __cdecl _ultox_s ( - unsigned long val, - TCHAR *buf, - size_t sizeInTChars, - int radix - ) -{ - return xtox_s(val, buf, sizeInTChars, radix, 0); -} - -#else /* _SECURE_ITOA */ - -/*** -*char *_itoa, *_ltoa, *_ultoa(val, buf, radix) - convert binary int to ASCII -* string -* -*Purpose: -* Converts an int to a character string. -* -*Entry: -* val - number to be converted (int, long or unsigned long) -* int radix - base to convert into -* char *buf - ptr to buffer to place result -* -*Exit: -* fills in space pointed to by buf with string result -* returns a pointer to this buffer -* -*Exceptions: -* Input parameters are validated. The buffer is assumed to be big enough to -* contain the string. Refer to the validation section of the function. -* -*******************************************************************************/ - -/* Actual functions just call conversion helper with neg flag set correctly, - and return pointer to buffer. */ - -TCHAR * __cdecl _ltox ( - long val, - TCHAR *buf, - int radix - ) -{ - xtox((unsigned long)val, buf, radix, (radix == 10 && val < 0)); - return buf; -} - -TCHAR * __cdecl _ultox ( - unsigned long val, - TCHAR *buf, - int radix - ) -{ - xtox(val, buf, radix, 0); - return buf; -} - -#endif /* _SECURE_ITOA */ - -#ifndef _NO_INT64 - -/*** -*char *_i64toa_s(val, buf, sizeInTChars, radix) - convert binary int to ASCII -* string -* -*Purpose: -* Converts an int64 to a character string. -* -*Entry: -* val - number to be converted -* char *buf - ptr to buffer to place result -* size_t sizeInTChars - size of the destination buffer -* int radix - base to convert into -* -*Exit: -* Fills in space pointed to by buf with string result. -* Returns the errno_t: err != 0 means that something went wrong, and -* an empty string (buf[0] = 0) is returned. -* -*Exceptions: -* Input parameters and buffer length are validated. -* Refer to the validation section of the function. -* -*******************************************************************************/ - -#ifdef _SECURE_ITOA -static errno_t __fastcall x64tox_s - (/* stdcall is faster and smaller... Might as well use it for the helper. */ - unsigned __int64 val, - TCHAR *buf, - size_t sizeInTChars, - unsigned radix, - int is_neg - ) -#else /* _SECURE_ITOA */ -static void __fastcall x64tox - (/* stdcall is faster and smaller... Might as well use it for the helper. */ - unsigned __int64 val, - TCHAR *buf, - unsigned radix, - int is_neg - ) -#endif /* _SECURE_ITOA */ -{ - TCHAR *p; /* pointer to traverse string */ - TCHAR *firstdig; /* pointer to first digit */ - TCHAR temp; /* temp char */ - unsigned digval; /* value of digit */ -#ifdef _SECURE_ITOA - size_t length; /* current length of the string */ - - /* validation section */ - _VALIDATE_RETURN_ERRCODE(buf != NULL, EINVAL); - _VALIDATE_RETURN_ERRCODE(sizeInTChars > 0, EINVAL); - _RESET_STRING(buf, sizeInTChars); - _VALIDATE_RETURN_ERRCODE(sizeInTChars > (size_t)(is_neg ? 2 : 1), ERANGE); - _VALIDATE_RETURN_ERRCODE(2 <= radix && radix <= 36, EINVAL); - length = 0; -#endif /* _SECURE_ITOA */ - p = buf; - - if ( is_neg ) - { - *p++ = _T('-'); /* negative, so output '-' and negate */ -#ifdef _SECURE_ITOA - length++; -#endif /* _SECURE_ITOA */ - val = (unsigned __int64)(-(__int64)val); - } - - firstdig = p; /* save pointer to first digit */ - - do { - digval = (unsigned) (val % radix); - val /= radix; /* get next digit */ - - /* convert to ascii and store */ - if (digval > 9) - *p++ = (TCHAR) (digval - 10 + _T('a')); /* a letter */ - else - *p++ = (TCHAR) (digval + _T('0')); /* a digit */ - -#ifndef _SECURE_ITOA - } while (val > 0); -#else /* _SECURE_ITOA */ - length++; - } while (val > 0 && length < sizeInTChars); - - /* Check for buffer overrun */ - if (length >= sizeInTChars) - { - buf[0] = '\0'; - _VALIDATE_RETURN_ERRCODE(length < sizeInTChars, ERANGE); - } -#endif /* _SECURE_ITOA */ - /* We now have the digit of the number in the buffer, but in reverse - order. Thus we reverse them now. */ - - *p-- = _T('\0'); /* terminate string; p points to last digit */ - - do { - temp = *p; - *p = *firstdig; - *firstdig = temp; /* swap *p and *firstdig */ - --p; - ++firstdig; /* advance to next two digits */ - } while (firstdig < p); /* repeat until halfway */ - -#ifdef _SECURE_ITOA - return 0; -#endif /* _SECURE_ITOA */ -} - -#ifdef _SECURE_ITOA - -/* Actual functions just call conversion helper with neg flag set correctly, - and return pointer to buffer. */ - -DLLEXPORT errno_t __cdecl _i64tox_s ( - long long val, - TCHAR *buf, - size_t sizeInTChars, - int radix - ) -{ - return x64tox_s((unsigned __int64)val, buf, sizeInTChars, radix, (radix == 10 && val < 0)); -} - -errno_t __cdecl _ui64tox_s ( - unsigned long long val, - TCHAR *buf, - size_t sizeInTChars, - int radix - ) -{ - return x64tox_s(val, buf, sizeInTChars, radix, 0); -} - -#else /* _SECURE_ITOA */ - -/*** -*char *_i64toa(val, buf, radix) - convert binary int to ASCII -* string -* -*Purpose: -* Converts an int64 to a character string. -* -*Entry: -* val - number to be converted -* int radix - base to convert into -* char *buf - ptr to buffer to place result -* -*Exit: -* fills in space pointed to by buf with string result -* returns a pointer to this buffer -* -*Exceptions: -* Input parameters are validated. The buffer is assumed to be big enough to -* contain the string. Refer to the validation section of the function. -* -*******************************************************************************/ - -/* Actual functions just call conversion helper with neg flag set correctly, - and return pointer to buffer. */ - -TCHAR * __cdecl _ui64tox ( - unsigned __int64 val, - TCHAR *buf, - int radix - ) -{ - x64tox(val, buf, radix, 0); - return buf; -} - -#endif /* _SECURE_ITOA */ - -#endif /* _NO_INT64 */ diff --git a/src/coreclr/pal/src/thread/thread.cpp b/src/coreclr/pal/src/thread/thread.cpp index d388521da160..07be09edaf25 100644 --- a/src/coreclr/pal/src/thread/thread.cpp +++ b/src/coreclr/pal/src/thread/thread.cpp @@ -1231,7 +1231,7 @@ CorUnix::GetThreadTimesInternal( OUT LPFILETIME lpKernelTime, OUT LPFILETIME lpUserTime) { - __int64 calcTime; + int64_t calcTime; BOOL retval = FALSE; #if HAVE_MACH_THREADS @@ -1281,15 +1281,15 @@ CorUnix::GetThreadTimesInternal( } /* Get the time of user mode execution, in nanoseconds */ - calcTime = (__int64)resUsage.user_time.seconds * SECS_TO_NS; - calcTime += (__int64)resUsage.user_time.microseconds * USECS_TO_NS; + calcTime = (int64_t)resUsage.user_time.seconds * SECS_TO_NS; + calcTime += (int64_t)resUsage.user_time.microseconds * USECS_TO_NS; /* Assign the time into lpUserTime */ lpUserTime->dwLowDateTime = (DWORD)calcTime; lpUserTime->dwHighDateTime = (DWORD)(calcTime >> 32); /* Get the time of kernel mode execution, in nanoseconds */ - calcTime = (__int64)resUsage.system_time.seconds * SECS_TO_NS; - calcTime += (__int64)resUsage.system_time.microseconds * USECS_TO_NS; + calcTime = (int64_t)resUsage.system_time.seconds * SECS_TO_NS; + calcTime += (int64_t)resUsage.system_time.microseconds * USECS_TO_NS; /* Assign the time into lpKernelTime */ lpKernelTime->dwLowDateTime = (DWORD)calcTime; lpKernelTime->dwHighDateTime = (DWORD)(calcTime >> 32); @@ -1368,8 +1368,8 @@ CorUnix::GetThreadTimesInternal( kvm_close(kd); - calcTime = (__int64) klwp[i].l_rtime_sec * SECS_TO_NS; - calcTime += (__int64) klwp[i].l_rtime_usec * USECS_TO_NS; + calcTime = (int64_t) klwp[i].l_rtime_sec * SECS_TO_NS; + calcTime += (int64_t) klwp[i].l_rtime_usec * USECS_TO_NS; lpUserTime->dwLowDateTime = (DWORD)calcTime; lpUserTime->dwHighDateTime = (DWORD)(calcTime >> 32); @@ -1458,8 +1458,8 @@ CorUnix::GetThreadTimesInternal( pTargetThread->Unlock(pThread); /* Calculate time in nanoseconds and assign to user time */ - calcTime = (__int64) ts.tv_sec * SECS_TO_NS; - calcTime += (__int64) ts.tv_nsec; + calcTime = (int64_t) ts.tv_sec * SECS_TO_NS; + calcTime += (int64_t) ts.tv_nsec; lpUserTime->dwLowDateTime = (DWORD)calcTime; lpUserTime->dwHighDateTime = (DWORD)(calcTime >> 32); diff --git a/src/coreclr/pal/tests/palsuite/CMakeLists.txt b/src/coreclr/pal/tests/palsuite/CMakeLists.txt index 3d5dc9a74908..5c65aa5c52fa 100644 --- a/src/coreclr/pal/tests/palsuite/CMakeLists.txt +++ b/src/coreclr/pal/tests/palsuite/CMakeLists.txt @@ -132,9 +132,6 @@ add_executable_clr(paltests c_runtime/wcstoul/test5/test5.cpp c_runtime/wcstoul/test6/test6.cpp c_runtime/_alloca/test1/test1.cpp - #c_runtime/_gcvt/test1/_gcvt.cpp - #c_runtime/_gcvt/test2/test2.cpp - c_runtime/_itow/test1/test1.cpp c_runtime/_putenv/test1/test1.cpp c_runtime/_putenv/test2/test2.cpp c_runtime/_putenv/test3/test3.cpp @@ -416,7 +413,6 @@ add_executable_clr(paltests miscellaneous/SetEnvironmentVariableW/test3/test3.cpp miscellaneous/SetEnvironmentVariableW/test4/test4.cpp miscellaneous/SetLastError/test1/test.cpp - miscellaneous/_i64tow/test1/test1.cpp # pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.cpp pal_specific/PAL_Initialize_Terminate/test1/PAL_Initialize_Terminate.cpp pal_specific/PAL_Initialize_Terminate/test2/pal_initialize_twice.cpp diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/_gcvt/test1/_gcvt.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/_gcvt/test1/_gcvt.cpp deleted file mode 100644 index ea2c1b02ade4..000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/_gcvt/test1/_gcvt.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================= -** -** Source: _gcvt.c -** -** Purpose: Positive test the _gcvt API. -** Call _gcvt to convert a floatable value to a string -** with specified sigficant digits stored -** -** -**============================================================*/ -#include - -PALTEST(c_runtime__gcvt_test1_paltest_gcvt_test1, "c_runtime/_gcvt/test1/paltest_gcvt_test1") -{ - int err; - double dValue = -3.1415926535; - char buffer[1024]; - char *pChar7 = "-3.141593"; - - /*Initialize the PAL environment*/ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - - /* zero the buffer */ - memset(buffer, 0, 1024); - - - /* - - Testing - ======= - - To convert a floating-point value to - a string to save 7 significant digits - */ - _gcvt(dValue, 7, buffer); - if(strcmp(pChar7, buffer)) - { - Fail("\nFailed to call _gcvt to convert a floating-point value " - "to a string with 7 sigficants digits stored\n"); - } - - - /* - Clean up and exit - */ - - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/_gcvt/test2/test2.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/_gcvt/test2/test2.cpp deleted file mode 100644 index af41769786f8..000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/_gcvt/test2/test2.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: test2.c -** -** Purpose: Call the _gcvt function on a number of cases. Check that it -** handles negatives, exponents and hex digits properly. Also check that -** the 'digit' specification works. (And that it doesn't truncate negative -** signs or decimals) -** -** -**===================================================================*/ - -#include - -struct testCase -{ - double Value; - int Digits; - char WinCorrectResult[128]; - char BsdCorrectResult[128]; /* for the odd case where bsd sprintf - varies from windows sprintf */ -}; - -PALTEST(c_runtime__gcvt_test2_paltest_gcvt_test2, "c_runtime/_gcvt/test2/paltest_gcvt_test2") -{ - char result[128]; - int i=0; - - struct testCase testCases[] = - { - {1234567, 7, "1234567"}, - {1234.123, 7, "1234.123"}, - {1234.1234, 7, "1234.123"}, - {12.325678e+2, 7, "1232.568"}, - {-12.3233333, 8, "-12.323333"}, - {-12.32, 8, "-12.32"}, - {-12.32e+2, 8, "-1232.", "-1232" }, - {0x21DDFABC, 8, "5.6819577e+008", "5.6819577e+08" }, - {123456789012345.0, 15, "123456789012345" }, - {12340000.0, 8, "12340000"}, - {12340000000000000.0, 15, "1.234e+016", "1.234e+16" }, - {12340000000000000.0, 17, "12340000000000000" }, - - }; - - if (0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Loop through each case. Call _gcvt on each test case and check the - result. - */ - - for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) - { - _gcvt(testCases[i].Value, testCases[i].Digits, result); - - if (strcmp(testCases[i].WinCorrectResult, result) != 0 && - - ( testCases[i].BsdCorrectResult && - strcmp(testCases[i].BsdCorrectResult, result) != 0 ) ) - { - Fail("ERROR: _gcvt attempted to convert %f with %d digits " - "signifigant, which resulted in " - "the string '%s' instead of the correct(Win) string '%s' or the" - "correct(bsd) string '%s'.\n", - testCases[i].Value, - testCases[i].Digits, - result, - testCases[i].WinCorrectResult, - testCases[i].BsdCorrectResult); - } - - memset(result, '\0', 128); - } - PAL_Terminate(); - return PASS; -} diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/_itow/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/_itow/test1/test1.cpp deleted file mode 100644 index 15e6aa201799..000000000000 --- a/src/coreclr/pal/tests/palsuite/c_runtime/_itow/test1/test1.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: test1.c -** -** Purpose: Tests the PAL implementation of the _itow_s function. -** Test a number of ints with different radix on each, -** to ensure that the string returned is correct. -** -** -**===================================================================*/ - -#define UNICODE - -#include - -struct testCase -{ - char16_t *CorrectResult; - int value; - int radix; -}; - -PALTEST(c_runtime__itow_test1_paltest_itow_test1, "c_runtime/_itow/test1/paltest_itow_test1") -{ - - char16_t result[20]; - char16_t *pResult = NULL; - char *PrintResult = NULL; /* Use with convertC so we can */ - char *PrintCorrectResult = NULL; /* print out the results */ - int i = 0; - - WCHAR case1[] = {'5','0','\0'}; - WCHAR case2[] = {'5','5','5','\0'}; - WCHAR case3[] = {'1','0','1','0','\0'}; - WCHAR case4[] = {'2','2','\0'}; - WCHAR case5[] = {'a','\0'}; - WCHAR case6[] = {'c','g','\0'}; - - /* Correct Result, Value to Convert, Radix to use */ - struct testCase testCases[] = - { - {case1, 50, 10}, - {case2,555,10}, - {case3,10,2}, - {case4,10,4}, - {case5,10,16}, - {case6,400,32} - }; - - /* - * Initialize the PAL and return FAIL if this fails - */ - if (0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Loop through each case. Convert the ints to strings. Check - to ensure they were converted properly. - */ - - for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) - { - errno_t err = _itow_s(testCases[i].value, result, sizeof(result) / sizeof(result[0]), testCases[i].radix); - - if(err != 0) - { - Fail("ERROR: _itow_s didn't return success, error code %d.\n", err); - } - - if (0 != wcscmp(testCases[i].CorrectResult, result)) - { - PrintResult = convertC(pResult); - PrintCorrectResult = convertC(testCases[i].CorrectResult); - Fail("ERROR: _itow_s was called on %i, returning the string %s " - "when it should have returned the string %s.\n" - , testCases[i].value, PrintResult, PrintCorrectResult); - } - - } - - PAL_Terminate(); - return PASS; -} - - - - - - - - - - - - - diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/llabs/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/llabs/test1/test1.cpp index d3455045d73d..09bf0670bf47 100644 --- a/src/coreclr/pal/tests/palsuite/c_runtime/llabs/test1/test1.cpp +++ b/src/coreclr/pal/tests/palsuite/c_runtime/llabs/test1/test1.cpp @@ -6,7 +6,7 @@ ** Source: test1.c ** ** Purpose: Call llabs on a series of values -- negative, positive, -** zero, and the largest negative value of an __int64. Ensure that +** zero, and the largest negative value of an int64_t. Ensure that ** they are all changed properly to their absolute value. ** ** @@ -16,14 +16,14 @@ struct testCase { - __int64 LongLongValue; - __int64 AbsoluteLongLongValue; + int64_t LongLongValue; + int64_t AbsoluteLongLongValue; }; PALTEST(c_runtime_llabs_test1_paltest_llabs_test1, "c_runtime/llabs/test1/paltest_llabs_test1") { - __int64 result=0; + int64_t result=0; int i=0; struct testCase testCases[] = @@ -40,13 +40,13 @@ PALTEST(c_runtime_llabs_test1_paltest_llabs_test1, "c_runtime/llabs/test1/paltes return FAIL; } - /* Loop through each case. Call llabs on each __int64 and ensure that + /* Loop through each case. Call llabs on each int64_t and ensure that the resulting value is correct. */ for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) { - /* Absolute value on an __int64 */ + /* Absolute value on an int64_t */ result = llabs(testCases[i].LongLongValue); if (testCases[i].AbsoluteLongLongValue != result) diff --git a/src/coreclr/pal/tests/palsuite/compilableTests.txt b/src/coreclr/pal/tests/palsuite/compilableTests.txt index 4d865fc63417..593faa173f1b 100644 --- a/src/coreclr/pal/tests/palsuite/compilableTests.txt +++ b/src/coreclr/pal/tests/palsuite/compilableTests.txt @@ -76,7 +76,6 @@ c_runtime/wcstoul/test4/paltest_wcstoul_test4 c_runtime/wcstoul/test5/paltest_wcstoul_test5 c_runtime/wcstoul/test6/paltest_wcstoul_test6 c_runtime/_alloca/test1/paltest_alloca_test1 -c_runtime/_itow/test1/paltest_itow_test1 c_runtime/_putenv/test1/paltest_putenv_test1 c_runtime/_putenv/test2/paltest_putenv_test2 c_runtime/_putenv/test3/paltest_putenv_test3 @@ -321,7 +320,6 @@ miscellaneous/SetEnvironmentVariableW/test2/paltest_setenvironmentvariablew_test miscellaneous/SetEnvironmentVariableW/test3/paltest_setenvironmentvariablew_test3 miscellaneous/SetEnvironmentVariableW/test4/paltest_setenvironmentvariablew_test4 miscellaneous/SetLastError/test1/paltest_setlasterror_test1 -miscellaneous/_i64tow/test1/paltest_i64tow_test1 pal_specific/PAL_GetUserTempDirectoryW/test1/paltest_pal_getusertempdirectoryw_test1 pal_specific/PAL_Initialize_Terminate/test1/paltest_pal_initialize_terminate_test1 pal_specific/PAL_Initialize_Terminate/test2/paltest_pal_initialize_terminate_test2 diff --git a/src/coreclr/pal/tests/palsuite/compileDisabledTests.txt b/src/coreclr/pal/tests/palsuite/compileDisabledTests.txt index 6d6a48788057..1a14daf4564a 100644 --- a/src/coreclr/pal/tests/palsuite/compileDisabledTests.txt +++ b/src/coreclr/pal/tests/palsuite/compileDisabledTests.txt @@ -12,8 +12,6 @@ composite/threading/threadsuspension_switchthread/paltest_threading_threadsuspen composite/wfmo/paltest_composite_wfmo c_runtime/iswprint/test1/paltest_iswprint_test1 c_runtime/vprintf/test1/paltest_vprintf_test1 -c_runtime/_gcvt/test1/paltest_gcvt_test1 -c_runtime/_gcvt/test2/paltest_gcvt_test2 debug_api/DebugBreak/test1/paltest_debugbreak_test1 debug_api/WriteProcessMemory/test1/paltest_writeprocessmemory_test1 debug_api/WriteProcessMemory/test3/paltest_writeprocessmemory_test3 diff --git a/src/coreclr/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.cpp b/src/coreclr/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.cpp index f228f9c6a69d..8c5ddfb0bec3 100644 --- a/src/coreclr/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.cpp +++ b/src/coreclr/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.cpp @@ -19,7 +19,10 @@ char* writeBuffer_WriteFile_test2; #define szWritableFile "Writeable.txt" #define szResultsFile "Results.txt" -const int PAGESIZE = 4096; + +#ifndef PAGESIZE +#define PAGESIZE 4096 +#endif // PAGESIZE BOOL writeTest_WriteFile_test2(DWORD dwByteCount, DWORD dwBytesWrittenResult, BOOL bResult) { @@ -29,23 +32,23 @@ BOOL writeTest_WriteFile_test2(DWORD dwByteCount, DWORD dwBytesWrittenResult, BO /* create the test file */ remove(szWritableFile); - hFile = CreateFile(szWritableFile, GENERIC_WRITE, FILE_SHARE_WRITE, + hFile = CreateFile(szWritableFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == INVALID_HANDLE_VALUE) { - Trace("WriteFile: ERROR -> Unable to create file \"%s\".\n", + Trace("WriteFile: ERROR -> Unable to create file \"%s\".\n", szWritableFile); return FALSE; } - + bRc = WriteFile(hFile, writeBuffer_WriteFile_test2, dwByteCount, &dwBytesWritten, NULL); CloseHandle(hFile); if ((bRc != bResult) || (dwBytesWrittenResult != dwBytesWritten)) { Trace("WriteFile returned BOOL:%d and dwWritten:%d what we do expect is" - " BOOL:%d and dwWritten:%d\n", bRc, dwBytesWritten, bResult, + " BOOL:%d and dwWritten:%d\n", bRc, dwBytesWritten, bResult, dwBytesWrittenResult); return FALSE; } @@ -57,11 +60,11 @@ PALTEST(file_io_WriteFile_test2_paltest_writefile_test2, "file_io/WriteFile/test { const char * testString = "The quick fox jumped over the lazy dog's back."; const int testStringLen = strlen(testString); - + DWORD dwByteCount[4] = {-1, 10, testStringLen, 0}; DWORD dwByteWritten[4] = {0, 10, testStringLen, 0}; BOOL bResults[] = {FALSE, TRUE, TRUE, TRUE}; - + const int BUFFER_SIZE = 2 * PAGESIZE; int j; BOOL bRc = FALSE; @@ -73,23 +76,23 @@ PALTEST(file_io_WriteFile_test2_paltest_writefile_test2, "file_io/WriteFile/test } /* allocate read-write memery for writeBuffer_WriteFile_test2 */ - if (!(writeBuffer_WriteFile_test2 = (char*) VirtualAlloc(NULL, BUFFER_SIZE, MEM_COMMIT, + if (!(writeBuffer_WriteFile_test2 = (char*) VirtualAlloc(NULL, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE))) - { - Fail("VirtualAlloc failed: GetLastError returns %d\n", GetLastError()); - return FAIL; - } - + { + Fail("VirtualAlloc failed: GetLastError returns %d\n", GetLastError()); + return FAIL; + } + memset((void*) writeBuffer_WriteFile_test2, '.', BUFFER_SIZE); strcpy(writeBuffer_WriteFile_test2, testString); - + /* write protect the second page of writeBuffer_WriteFile_test2 */ - if (!VirtualProtect(&writeBuffer_WriteFile_test2[PAGESIZE], PAGESIZE, PAGE_NOACCESS, &oldProt)) - { - Fail("VirtualProtect failed: GetLastError returns %d\n", GetLastError()); - return FAIL; - } - + if (!VirtualProtect(&writeBuffer_WriteFile_test2[PAGESIZE], PAGESIZE, PAGE_NOACCESS, &oldProt)) + { + Fail("VirtualProtect failed: GetLastError returns %d\n", GetLastError()); + return FAIL; + } + for (j = 0; j< 4; j++) { bRc = writeTest_WriteFile_test2(dwByteCount[j], dwByteWritten[j], bResults[j]); diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.cpp deleted file mode 100644 index 2a44813cde4f..000000000000 --- a/src/coreclr/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================= -** -** Source: test1.c -** -** Purpose: Tests _i64tow_s with normal values and different radices, negative -** values, as well as the highest and lowest values. -** -** -**============================================================*/ - -#include - -typedef struct -{ - INT64 value; - int radix; - char *result; -} testCase; - - -PALTEST(miscellaneous__i64tow_test1_paltest_i64tow_test1, "miscellaneous/_i64tow/test1/paltest_i64tow_test1") -{ - WCHAR buffer[256]; - WCHAR *testStr; - WCHAR *ret; - int i; - testCase testCases[] = - { - {42, 10, "42"}, - {42, 2, "101010"}, - {29, 32, "t"}, - {-1, 10, "-1"}, - {-1, 8, "1777777777777777777777"}, - {-1, 32, "fvvvvvvvvvvvv"}, - {I64(0x7FFFFFFFFFFFFFFF), 10, "9223372036854775807"}, - {I64(0x8000000000000000), 10, "-9223372036854775808"}, - {0,2,"0"}, - {0,16,"0"}, - {3,16,"3"}, - {15,16,"f"}, - {16,16,"10"}, - - }; - - - if (0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - for (i=0; i + diff --git a/src/coreclr/runtime.proj b/src/coreclr/runtime.proj index 600a3bc6d130..dce3f8beb612 100644 --- a/src/coreclr/runtime.proj +++ b/src/coreclr/runtime.proj @@ -50,6 +50,20 @@ <_CoreClrBuildArg Condition="'$(HostCrossOS)' != ''" Include="-hostos $(HostCrossOS)" /> <_CoreClrBuildArg Include="-outputrid $(OutputRID)" /> <_CoreClrBuildArg Condition="'$(BuildSubdirectory)' != ''" Include="-subdir $(BuildSubdirectory)" /> + <_CoreClrBuildArg Include="-cmakeargs "-DCLR_DOTNET_HOST_PATH=$(DOTNET_HOST_PATH)"" /> + <_CoreClrBuildArg Include="-cmakeargs "-DCDAC_BUILD_TOOL_BINARY_PATH=$(RuntimeBinDir)cdac-build-tool\cdac-build-tool.dll"" /> + + + + <_CoreClrBuildArg Include="-cmakeargs -DCLR_CMAKE_CXX_STANDARD_LIBRARY=$(CxxStandardLibrary)" /> + + + + <_CoreClrBuildArg Include="-cmakeargs -DCLR_CMAKE_CXX_STANDARD_LIBRARY_STATIC=ON" /> + + + + <_CoreClrBuildArg Include="-cmakeargs -DCLR_CMAKE_CXX_ABI_LIBRARY=$(CxxAbiLibrary)" /> diff --git a/src/coreclr/scripts/genEventing.py b/src/coreclr/scripts/genEventing.py index 503b8c52835a..a69f155bbdfc 100644 --- a/src/coreclr/scripts/genEventing.py +++ b/src/coreclr/scripts/genEventing.py @@ -51,7 +51,7 @@ def __init__(self, runtime): coreCLRPalDataTypeMapping={ #constructed types "win:null" :" ", - "win:Int64" :"const __int64", + "win:Int64" :"const int64_t", "win:ULong" :"const ULONG", "win:count" :"*", "win:Struct" :"const void", @@ -62,7 +62,7 @@ def __init__(self, runtime): "win:Double" :"const double", "win:Int32" :"const signed int", "win:Boolean" :"const BOOL", - "win:UInt64" :"const unsigned __int64", + "win:UInt64" :"const uint64_t", "win:UInt32" :"const unsigned int", "win:UInt16" :"const unsigned short", "win:UInt8" :"const unsigned char", @@ -115,7 +115,7 @@ def __init__(self, runtime): aotPalDataTypeMapping={ #constructed types "win:null" :" ", - "win:Int64" :"const __int64", + "win:Int64" :"const int64_t", "win:ULong" :"const ULONG", "win:count" :"*", "win:Struct" :"const void", @@ -126,7 +126,7 @@ def __init__(self, runtime): "win:Double" :"const double", "win:Int32" :"const signed int", "win:Boolean" :"const BOOL", - "win:UInt64" :"const unsigned __int64", + "win:UInt64" :"const uint64_t", "win:UInt32" :"const unsigned int", "win:UInt16" :"const unsigned short", "win:UInt8" :"const unsigned char", diff --git a/src/coreclr/scripts/genEventingTests.py b/src/coreclr/scripts/genEventingTests.py index 6bd8423166e8..39fbd731431c 100644 --- a/src/coreclr/scripts/genEventingTests.py +++ b/src/coreclr/scripts/genEventingTests.py @@ -130,8 +130,8 @@ def generateSanityTest(sClrEtwAllMan,testDir): double win_Double =34.04; ULONG win_ULong = 34; BOOL win_Boolean = FALSE; -unsigned __int64 win_UInt64 = 114; -__int64 win_Int64 = 114; +uint64_t win_UInt64 = 114; +int64_t win_Int64 = 114; unsigned int win_UInt32 = 4; unsigned short win_UInt16 = 12; unsigned char win_UInt8 = 9; diff --git a/src/coreclr/scripts/genLttngProvider.py b/src/coreclr/scripts/genLttngProvider.py index fc93f240315c..24030925a22c 100644 --- a/src/coreclr/scripts/genLttngProvider.py +++ b/src/coreclr/scripts/genLttngProvider.py @@ -69,7 +69,7 @@ coreCLRLttngDataTypeMapping ={ #constructed types "win:null" :" ", - "win:Int64" :"const __int64", + "win:Int64" :"const int64_t", "win:ULong" :"const ULONG", "win:count" :"*", "win:Struct" :"const BYTE *", @@ -80,7 +80,7 @@ "win:Double" :"const double", "win:Int32" :"const signed int", "win:Boolean" :"const BOOL", - "win:UInt64" :"const unsigned __int64", + "win:UInt64" :"const uint64_t", "win:UInt32" :"const unsigned int", "win:UInt16" :"const unsigned short", "win:UInt8" :"const unsigned char", diff --git a/src/coreclr/scripts/superpmi_aspnet.py b/src/coreclr/scripts/superpmi_aspnet.py index 1ac379289458..8125184104ea 100644 --- a/src/coreclr/scripts/superpmi_aspnet.py +++ b/src/coreclr/scripts/superpmi_aspnet.py @@ -17,6 +17,7 @@ import sys import zipfile import stat +import tempfile from os import path from coreclr_arguments import * @@ -124,39 +125,23 @@ def build_and_run(coreclr_args): checked_root = path.join(source_directory, "artifacts", "bin", "coreclr", target_os + "." + coreclr_args.arch + ".Checked") release_root = path.join(source_directory, "artifacts", "bin", "coreclr", target_os + "." + coreclr_args.arch + ".Release") - spmi_temp = path.join(source_directory, "artifacts", "spmi_aspnet_collection") - - # Set up/clean up temp dir - if not os.path.exists(spmi_temp): - os.makedirs(spmi_temp) - - def remove_readonly(func, path, _): - "Clear the readonly bit and reattempt the removal" - os.chmod(path, stat.S_IWRITE) - func(path) - - spmi_temp_items = [os.path.join(spmi_temp, item) for item in os.listdir(spmi_temp)] - for item in spmi_temp_items: - if os.path.isdir(item): - shutil.rmtree(item, onerror=remove_readonly) - else: - os.remove(item) # We'll use repo script to install dotnet dotnet_install_script_name = "dotnet-install.cmd" if is_windows else "dotnet-install.sh" dotnet_install_script_path = path.join(source_directory, "eng", "common", dotnet_install_script_name) - with TempDir(spmi_temp, skip_cleanup=True) as temp_location: + with tempfile.TemporaryDirectory() as temp_location: print ("Executing in " + temp_location) + os.chdir(temp_location) - # install dotnet 6.0 - run_command([dotnet_install_script_path, "-Version", "7.0.2"], temp_location, _exit_on_fail=True) + # install dotnet 8.0 + run_command([dotnet_install_script_path, "-Version", "8.0.0"], temp_location, _exit_on_fail=True) os.environ['DOTNET_MULTILEVEL_LOOKUP'] = '0' os.environ['DOTNET_SKIP_FIRST_TIME_EXPERIENCE'] = '1' dotnet_path = path.join(source_directory, ".dotnet") dotnet_exe = path.join(dotnet_path, "dotnet.exe") if is_windows else path.join(dotnet_path, "dotnet") - run_command([dotnet_exe, "--info"], temp_location, _exit_on_fail=True) + # run_command([dotnet_exe, "--info"], temp_location, _exit_on_fail=True) os.environ['DOTNET_ROOT'] = dotnet_path ## install crank as local tool @@ -190,24 +175,27 @@ def remove_readonly(func, path, _): ("proxy", "proxy-yarp"), ("staticfiles", "static"), ("websocket", "websocket"), - ("orchard", "about-sqlite") + ("orchard", "about-sqlite"), + ("signalr", "signalr"), + ("grpc", "grpcaspnetcoreserver-grpcnetclient"), + ("efcore", "NavigationsQuery"), + ("efcore", "Funcletization") ] - # configname_scenario_list = [("platform", "plaintext")] + # configname_scenario_list = [("quic", "read-write")] # note tricks to get one element tuples runtime_options_list = [ ("Dummy=0",), ("TieredCompilation=0", ), - ("TieredPGO=1",), + ("TieredPGO=0",), ("TieredPGO=1", "ReadyToRun=0"), ("ReadyToRun=0", "OSR_HitLimit=0", "TC_OnStackReplacement_InitialCounter=10"), - ("TieredPGO=1", "ReadyToRun=0", "OSR_HitLimit=0", "TC_OnStackReplacement_InitialCounter=10"), ("TC_PartialCompilation=1",) ] - # runtime_options_list = [("TieredCompilation=0", )] + # runtime_options_list = [("Dummy=0", )] mch_file = path.join(coreclr_args.output_mch_path, "aspnet.run." + target_os + "." + target_arch + ".checked.mch") benchmark_machine = determine_benchmark_machine(coreclr_args) @@ -288,6 +276,8 @@ def remove_readonly(func, path, _): command = [mcs_path, "-jitflags", mch_file] run_command(command, temp_location) + os.chdir(source_directory ) + def main(main_args): """ Main entry point diff --git a/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs b/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs index e708130f6fc3..8ecd0fb034d2 100644 --- a/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs +++ b/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs @@ -98,7 +98,7 @@ public IReadOnlyDictionary ReferenceFilePaths set; } - public override ModuleDesc ResolveAssembly(System.Reflection.AssemblyName name, bool throwIfNotFound) + public override ModuleDesc ResolveAssembly(AssemblyNameInfo name, bool throwIfNotFound) { // TODO: catch typesystem BadImageFormatException and throw a new one that also captures the // assembly name that caused the failure. (Along with the reason, which makes this rather annoying). diff --git a/src/coreclr/tools/Common/Compiler/Dataflow/GenericParameterProxy.cs b/src/coreclr/tools/Common/Compiler/Dataflow/GenericParameterProxy.cs index b04e245ee50e..cb9bbeadbc77 100644 --- a/src/coreclr/tools/Common/Compiler/Dataflow/GenericParameterProxy.cs +++ b/src/coreclr/tools/Common/Compiler/Dataflow/GenericParameterProxy.cs @@ -15,6 +15,17 @@ internal readonly partial struct GenericParameterProxy internal partial bool HasDefaultConstructorConstraint() => GenericParameter.HasDefaultConstructorConstraint; + internal partial bool HasEnumConstraint() + { + foreach (TypeDesc constraint in GenericParameter.TypeConstraints) + { + if (constraint.IsWellKnownType(Internal.TypeSystem.WellKnownType.Enum)) + return true; + } + + return false; + } + public readonly GenericParameterDesc GenericParameter; public override string ToString() => GenericParameter.ToString(); diff --git a/src/coreclr/tools/Common/Compiler/Dataflow/MethodProxy.cs b/src/coreclr/tools/Common/Compiler/Dataflow/MethodProxy.cs index 3e282dfc76dc..cfb4bb129029 100644 --- a/src/coreclr/tools/Common/Compiler/Dataflow/MethodProxy.cs +++ b/src/coreclr/tools/Common/Compiler/Dataflow/MethodProxy.cs @@ -66,6 +66,8 @@ internal partial ImmutableArray GetGenericParameters() return builder.ToImmutableArray(); } + internal partial bool IsConstructor() => Method.IsConstructor; + internal partial bool IsStatic() => Method.Signature.IsStatic; internal partial bool HasImplicitThis() => !Method.Signature.IsStatic; diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs index b5128ff27fb1..53e4671b57a5 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Buffers.Binary; using System.Collections.Generic; using Internal.TypeSystem; @@ -85,42 +86,27 @@ public void EmitByte(byte emit) public void EmitShort(short emit) { - EmitByte((byte)(emit & 0xFF)); - EmitByte((byte)((emit >> 8) & 0xFF)); + BinaryPrimitives.WriteInt16LittleEndian(_data.AppendSpan(sizeof(short)), emit); } public void EmitUShort(ushort emit) { - EmitByte((byte)(emit & 0xFF)); - EmitByte((byte)((emit >> 8) & 0xFF)); + BinaryPrimitives.WriteUInt16LittleEndian(_data.AppendSpan(sizeof(ushort)), emit); } public void EmitInt(int emit) { - EmitByte((byte)(emit & 0xFF)); - EmitByte((byte)((emit >> 8) & 0xFF)); - EmitByte((byte)((emit >> 16) & 0xFF)); - EmitByte((byte)((emit >> 24) & 0xFF)); + BinaryPrimitives.WriteInt32LittleEndian(_data.AppendSpan(sizeof(int)), emit); } public void EmitUInt(uint emit) { - EmitByte((byte)(emit & 0xFF)); - EmitByte((byte)((emit >> 8) & 0xFF)); - EmitByte((byte)((emit >> 16) & 0xFF)); - EmitByte((byte)((emit >> 24) & 0xFF)); + BinaryPrimitives.WriteUInt32LittleEndian(_data.AppendSpan(sizeof(uint)), emit); } public void EmitLong(long emit) { - EmitByte((byte)(emit & 0xFF)); - EmitByte((byte)((emit >> 8) & 0xFF)); - EmitByte((byte)((emit >> 16) & 0xFF)); - EmitByte((byte)((emit >> 24) & 0xFF)); - EmitByte((byte)((emit >> 32) & 0xFF)); - EmitByte((byte)((emit >> 40) & 0xFF)); - EmitByte((byte)((emit >> 48) & 0xFF)); - EmitByte((byte)((emit >> 56) & 0xFF)); + BinaryPrimitives.WriteInt64LittleEndian(_data.AppendSpan(sizeof(long)), emit); } public void EmitNaturalInt(int emit) @@ -245,8 +231,7 @@ public Reservation ReserveShort() public void EmitShort(Reservation reservation, short emit) { int offset = ReturnReservationTicket(reservation); - _data[offset] = (byte)(emit & 0xFF); - _data[offset + 1] = (byte)((emit >> 8) & 0xFF); + BinaryPrimitives.WriteInt16LittleEndian(_data.AsSpan(offset), emit); } public Reservation ReserveInt() @@ -257,19 +242,13 @@ public Reservation ReserveInt() public void EmitInt(Reservation reservation, int emit) { int offset = ReturnReservationTicket(reservation); - _data[offset] = (byte)(emit & 0xFF); - _data[offset + 1] = (byte)((emit >> 8) & 0xFF); - _data[offset + 2] = (byte)((emit >> 16) & 0xFF); - _data[offset + 3] = (byte)((emit >> 24) & 0xFF); + BinaryPrimitives.WriteInt32LittleEndian(_data.AsSpan(offset), emit); } public void EmitUInt(Reservation reservation, uint emit) { int offset = ReturnReservationTicket(reservation); - _data[offset] = (byte)(emit & 0xFF); - _data[offset + 1] = (byte)((emit >> 8) & 0xFF); - _data[offset + 2] = (byte)((emit >> 16) & 0xFF); - _data[offset + 3] = (byte)((emit >> 24) & 0xFF); + BinaryPrimitives.WriteUInt32LittleEndian(_data.AsSpan(offset), emit); } public void EmitReloc(ISymbolNode symbol, RelocType relocType, int delta = 0) diff --git a/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs b/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs index fde027a32622..fcbd86902be0 100644 --- a/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs +++ b/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs @@ -101,6 +101,10 @@ public static string GetHardwareIntrinsicId(TargetArchitecture architecture, Typ { return ""; // No "hardware" for Wasm at all. } + else if (architecture == TargetArchitecture.LoongArch64) + { + return ""; + } else if (architecture == TargetArchitecture.RiscV64) { return ""; diff --git a/src/coreclr/tools/Common/Compiler/NativeAotNameMangler.cs b/src/coreclr/tools/Common/Compiler/NativeAotNameMangler.cs index 844cf58f20bd..66f9e02a54f6 100644 --- a/src/coreclr/tools/Common/Compiler/NativeAotNameMangler.cs +++ b/src/coreclr/tools/Common/Compiler/NativeAotNameMangler.cs @@ -202,6 +202,8 @@ private string ComputeMangledTypeName(TypeDesc type) containingType = containingType.ContainingType; } + name = prependAssemblyName + "_" + SanitizeName(name, true); + // If this is one of the well known types, use a shorter name // We know this won't conflict because all the other types are // prefixed by the assembly name. @@ -231,10 +233,6 @@ private string ComputeMangledTypeName(TypeDesc type) break; } } - else - { - name = prependAssemblyName + "_" + SanitizeName(name, true); - } // Ensure that name is unique and update our tables accordingly. name = DisambiguateName(name, deduplicator); @@ -344,7 +342,7 @@ public override Utf8String GetMangledMethodName(MethodDesc method) Utf8StringBuilder sb = new Utf8StringBuilder(); sb.Append(GetMangledTypeName(method.OwningType)); - sb.Append("__"); + sb.Append("__"u8); sb.Append(GetUnqualifiedMangledMethodName(method)); utf8MangledName = sb.ToUtf8String(); @@ -391,7 +389,7 @@ private Utf8String GetPrefixMangledSignatureName(IPrefixMangledSignature prefixM for (int i = 0; i < signature.Length; i++) { - sb.Append("__"); + sb.Append("__"u8); string sigArgName = GetMangledTypeName(signature[i]); sb.Append(sigArgName); } @@ -451,7 +449,7 @@ private Utf8String ComputeUnqualifiedMangledMethodName(MethodDesc method) { string instArgName = GetMangledTypeName(inst[i]); if (i > 0) - sb.Append("__"); + sb.Append("__"u8); sb.Append(instArgName); } diff --git a/src/coreclr/tools/Common/Compiler/ProcessLinkerXmlBase.cs b/src/coreclr/tools/Common/Compiler/ProcessLinkerXmlBase.cs index ba6b1f0694d0..07b78f196d2e 100644 --- a/src/coreclr/tools/Common/Compiler/ProcessLinkerXmlBase.cs +++ b/src/coreclr/tools/Common/Compiler/ProcessLinkerXmlBase.cs @@ -128,7 +128,7 @@ protected virtual void ProcessXml(bool ignoreResource) protected virtual AllowedAssemblies AllowedAssemblySelector { get => _owningModule != null ? AllowedAssemblies.ContainingAssembly : AllowedAssemblies.AnyAssembly; } - private bool ShouldProcessAllAssemblies(XPathNavigator nav, [NotNullWhen(false)] out AssemblyName? assemblyName) + private bool ShouldProcessAllAssemblies(XPathNavigator nav, [NotNullWhen(false)] out AssemblyNameInfo? assemblyName) { assemblyName = null; if (GetFullName(nav) == AllAssembliesFullName) @@ -147,7 +147,7 @@ protected virtual void ProcessAssemblies(XPathNavigator nav) // Errors for invalid assembly names should show up even if this element will be // skipped due to feature conditions. - bool processAllAssemblies = ShouldProcessAllAssemblies(assemblyNav, out AssemblyName? name); + bool processAllAssemblies = ShouldProcessAllAssemblies(assemblyNav, out AssemblyNameInfo? name); if (processAllAssemblies && !_globalAttributeRemoval) { #if !READYTORUN @@ -175,7 +175,7 @@ protected virtual void ProcessAssemblies(XPathNavigator nav) if (_owningModule.Assembly.GetName().Name != name!.Name) { #if !READYTORUN - LogWarning(assemblyNav, DiagnosticId.AssemblyWithEmbeddedXmlApplyToAnotherAssembly, _owningModule.Assembly.GetName().Name ?? "", name.ToString()); + LogWarning(assemblyNav, DiagnosticId.AssemblyWithEmbeddedXmlApplyToAnotherAssembly, _owningModule.Assembly.GetName().Name, name.FullName); #endif continue; } @@ -188,7 +188,7 @@ protected virtual void ProcessAssemblies(XPathNavigator nav) if (assembly == null) { #if !READYTORUN - LogWarning(assemblyNav, DiagnosticId.XmlCouldNotResolveAssembly, name!.Name ?? ""); + LogWarning(assemblyNav, DiagnosticId.XmlCouldNotResolveAssembly, name!.Name); #endif continue; } @@ -217,9 +217,10 @@ protected virtual void ProcessTypes(ModuleDesc assembly, XPathNavigator nav, boo continue; } - // TODO: Process exported types + MetadataType? type = CecilCompatibleTypeParser.GetType(assembly, fullname); - TypeDesc? type = CecilCompatibleTypeParser.GetType(assembly, fullname); + if (type != null && type.Module != assembly) + type = ProcessExportedType(type, assembly, typeNav); if (type == null) { @@ -234,6 +235,8 @@ protected virtual void ProcessTypes(ModuleDesc assembly, XPathNavigator nav, boo } } + protected virtual MetadataType? ProcessExportedType(MetadataType exported, ModuleDesc assembly, XPathNavigator nav) => exported; + private void MatchType(TypeDesc type, Regex regex, XPathNavigator nav) { StringBuilder sb = new StringBuilder(); @@ -499,9 +502,9 @@ protected virtual void ProcessProperty(TypeDesc type, XPathNavigator nav, object protected virtual void ProcessProperty(TypeDesc type, PropertyPseudoDesc property, XPathNavigator nav, object? customData, bool fromSignature) { } - protected virtual AssemblyName GetAssemblyName(XPathNavigator nav) + protected virtual AssemblyNameInfo GetAssemblyName(XPathNavigator nav) { - return new AssemblyName(GetFullName(nav)); + return AssemblyNameInfo.Parse(GetFullName(nav)); } protected static string GetFullName(XPathNavigator nav) @@ -759,7 +762,7 @@ public bool TryConvertValue(string value, TypeDesc type, out object? result) public class CecilCompatibleTypeParser { - public static TypeDesc? GetType(ModuleDesc assembly, string fullName) + public static MetadataType? GetType(ModuleDesc assembly, string fullName) { Debug.Assert(!string.IsNullOrEmpty(fullName)); var position = fullName.IndexOf('/'); diff --git a/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs index bb0a5bc71a62..1f3722ab019b 100644 --- a/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs @@ -58,6 +58,11 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp // 16-byte alignment for __m256. alignment = new LayoutInt(16); } + else if (defType.Context.Target.Architecture == TargetArchitecture.LoongArch64) + { + // TODO-LoongArch64: Update alignment to proper value when implement LoongArch64 intrinsic. + alignment = new LayoutInt(16); + } else if (defType.Context.Target.Architecture == TargetArchitecture.RiscV64) { // TODO-RISCV64: Update alignment to proper value when we implement RISC-V intrinsic. @@ -86,6 +91,11 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp // 16-byte alignment for __m256. alignment = new LayoutInt(16); } + else if (defType.Context.Target.Architecture == TargetArchitecture.LoongArch64) + { + // TODO-LoongArch64: Update alignment to proper value when implement LoongArch64 intrinsic. + alignment = new LayoutInt(16); + } else if (defType.Context.Target.Architecture == TargetArchitecture.RiscV64) { // TODO-RISCV64: Update alignment to proper value when we implement RISC-V intrinsic. diff --git a/src/coreclr/tools/Common/InstructionSetHelpers.cs b/src/coreclr/tools/Common/InstructionSetHelpers.cs index 718053f13d0c..8a7303f15f37 100644 --- a/src/coreclr/tools/Common/InstructionSetHelpers.cs +++ b/src/coreclr/tools/Common/InstructionSetHelpers.cs @@ -122,7 +122,7 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru string[] instructionSetParamsInput = instructionSet.Split(','); for (int i = 0; i < instructionSetParamsInput.Length; i++) { - instructionSet = instructionSetParamsInput[i]; + instructionSet = instructionSetParamsInput[i].Trim(); if (string.IsNullOrEmpty(instructionSet)) throw new CommandLineException(string.Format(mustNotBeMessage, "")); diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs index 572f5e20bac5..c7fc7bec8602 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs @@ -65,16 +65,31 @@ public void EmitSource() private void EmitRecord(RecordDef record) { WriteTypeAttributesForCoreLib(); - OpenScope($"public partial struct {record.Name}"); + OpenScope($"public readonly partial struct {record.Name}"); - WriteLine("internal MetadataReader _reader;"); - WriteLine($"internal {record.Name}Handle _handle;"); + WriteLine("private readonly MetadataReader _reader;"); + WriteLine($"private readonly {record.Name}Handle _handle;"); - OpenScope($"public {record.Name}Handle Handle"); - OpenScope("get"); - WriteLine("return _handle;"); + OpenScope($"internal {record.Name}(MetadataReader reader, {record.Name}Handle handle)"); + if (record.Name == "ConstantStringValue") + { + WriteLine("if (handle.IsNil)"); + WriteLine(" return;"); + } + WriteLine("_reader = reader;"); + WriteLine("_handle = handle;"); + WriteLine("uint offset = (uint)handle.Offset;"); + WriteLine("NativeReader streamReader = reader._streamReader;"); + foreach (var member in record.Members) + { + if ((member.Flags & MemberDefFlags.NotPersisted) != 0) + continue; + WriteLine($"offset = streamReader.Read(offset, out {member.GetMemberFieldName()});"); + } CloseScope(); - CloseScope("Handle"); + + WriteLineIfNeeded(); + WriteLine($"public {record.Name}Handle Handle => _handle;"); foreach (var member in record.Members) { @@ -86,20 +101,15 @@ private void EmitRecord(RecordDef record) string fieldName = member.GetMemberFieldName(); + WriteLineIfNeeded(); + string description = member.GetMemberDescription(); if (description != null) WriteDocComment(description); - OpenScope($"public {memberType} {member.Name}"); - OpenScope("get"); - if (fieldType != memberType) - WriteLine($"return ({memberType}){fieldName};"); - else - WriteLine($"return {fieldName};"); - CloseScope(); - CloseScope(member.Name); + string optionalCast = (fieldType != memberType) ? $"({memberType})" : ""; + WriteLine($"public {memberType} {member.Name} => {optionalCast}{fieldName};"); - WriteLineIfNeeded(); - WriteLine($"internal {fieldType} {fieldName};"); + WriteLine($"private readonly {fieldType} {fieldName};"); } CloseScope(record.Name); @@ -110,31 +120,9 @@ private void EmitHandle(RecordDef record) string handleName = $"{record.Name}Handle"; WriteTypeAttributesForCoreLib(); - OpenScope($"public partial struct {handleName}"); + OpenScope($"public readonly partial struct {handleName}"); - OpenScope("public override bool Equals(object obj)"); - WriteLine($"if (obj is {handleName})"); - WriteLine($" return _value == (({handleName})obj)._value;"); - WriteLine("else if (obj is Handle)"); - WriteLine(" return _value == ((Handle)obj)._value;"); - WriteLine("else"); - WriteLine(" return false;"); - CloseScope("Equals"); - - OpenScope($"public bool Equals({handleName} handle)"); - WriteLine("return _value == handle._value;"); - CloseScope("Equals"); - - OpenScope("public bool Equals(Handle handle)"); - WriteLine("return _value == handle._value;"); - CloseScope("Equals"); - - OpenScope("public override int GetHashCode()"); - WriteLine("return (int)_value;"); - CloseScope("GetHashCode"); - - WriteLineIfNeeded(); - WriteLine("internal int _value;"); + WriteLine("internal readonly int _value;"); OpenScope($"internal {handleName}(Handle handle) : this(handle._value)"); CloseScope(); @@ -146,37 +134,46 @@ private void EmitHandle(RecordDef record) WriteLine("_Validate();"); CloseScope(); - OpenScope($"public static implicit operator Handle({handleName} handle)"); - WriteLine("return new Handle(handle._value);"); - CloseScope("Handle"); + OpenScope("public override bool Equals(object obj)"); + WriteLine($"if (obj is {handleName})"); + WriteLine($" return _value == (({handleName})obj)._value;"); + WriteLine("else if (obj is Handle)"); + WriteLine(" return _value == ((Handle)obj)._value;"); + WriteLine("else"); + WriteLine(" return false;"); + CloseScope("Equals"); - OpenScope("internal int Offset"); - OpenScope("get"); - WriteLine("return (this._value & 0x00FFFFFF);"); - CloseScope(); - CloseScope("Offset"); + WriteLineIfNeeded(); + WriteLine($"public bool Equals({handleName} handle) => _value == handle._value;"); - OpenScope($"public {record.Name} Get{record.Name}(MetadataReader reader)"); - WriteLine($"return reader.Get{record.Name}(this);"); - CloseScope($"Get{record.Name}"); + WriteLineIfNeeded(); + WriteLine("public bool Equals(Handle handle) => _value == handle._value;"); + + WriteLineIfNeeded(); + WriteLine("public override int GetHashCode() => (int)_value;"); + + WriteLineIfNeeded(); + WriteLine($"public static implicit operator Handle({handleName} handle)"); + WriteLine(" => new Handle(handle._value);"); - OpenScope("public bool IsNull(MetadataReader reader)"); - WriteLine("return reader.IsNull(this);"); - CloseScope("IsNull"); + WriteLineIfNeeded(); + WriteLine("internal int Offset => (_value & 0x00FFFFFF);"); - OpenScope("public Handle ToHandle(MetadataReader reader)"); - WriteLine("return reader.ToHandle(this);"); - CloseScope("ToHandle"); + WriteLineIfNeeded(); + WriteLine($"public {record.Name} Get{record.Name}(MetadataReader reader)"); + WriteLine($" => new {record.Name}(reader, this);"); + WriteLineIfNeeded(); + WriteLine("public bool IsNil => (_value & 0x00FFFFFF) == 0;"); + WriteScopeAttribute("[System.Diagnostics.Conditional(\"DEBUG\")]"); OpenScope("internal void _Validate()"); WriteLine($"if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.{record.Name})"); WriteLine(" throw new ArgumentException();"); CloseScope("_Validate"); - OpenScope("public override string ToString()"); - WriteLine("return string.Format(\"{0:X8}\", _value);"); - CloseScope("ToString"); + WriteLineIfNeeded(); + WriteLine("public override string ToString() => string.Format(\"{0:X8}\", _value);"); CloseScope(handleName); } @@ -184,10 +181,10 @@ private void EmitHandle(RecordDef record) private void EmitCollection(string collectionTypeName, string elementTypeName) { WriteTypeAttributesForCoreLib(); - OpenScope($"public partial struct {collectionTypeName}"); + OpenScope($"public readonly partial struct {collectionTypeName}"); - WriteLine("private NativeReader _reader;"); - WriteLine("private uint _offset;"); + WriteLine("private readonly NativeReader _reader;"); + WriteLine("private readonly uint _offset;"); OpenScope($"internal {collectionTypeName}(NativeReader reader, uint offset)"); WriteLine("_offset = offset;"); @@ -209,7 +206,7 @@ private void EmitCollection(string collectionTypeName, string elementTypeName) WriteTypeAttributesForCoreLib(); OpenScope($"public struct Enumerator"); - WriteLine("private NativeReader _reader;"); + WriteLine("private readonly NativeReader _reader;"); WriteLine("private uint _offset;"); WriteLine("private uint _remaining;"); WriteLine($"private {elementTypeName} _current;"); @@ -245,7 +242,7 @@ private void EmitCollection(string collectionTypeName, string elementTypeName) private void EmitOpaqueHandle() { WriteTypeAttributesForCoreLib(); - OpenScope("public partial struct Handle"); + OpenScope("public readonly partial struct Handle"); foreach (var record in SchemaDef.RecordSchema) { @@ -267,48 +264,10 @@ private void EmitMetadataReader() foreach (var record in SchemaDef.RecordSchema) { OpenScope($"public {record.Name} Get{record.Name}({record.Name}Handle handle)"); - if (record.Name == "ConstantStringValue") - { - WriteLine("if (IsNull(handle))"); - WriteLine(" return new ConstantStringValue();"); - } - WriteLine($"{record.Name} record;"); - WriteLine("record._reader = this;"); - WriteLine("record._handle = handle;"); - WriteLine("var offset = (uint)handle.Offset;"); - foreach (var member in record.Members) - { - if ((member.Flags & MemberDefFlags.NotPersisted) != 0) - continue; - WriteLine($"offset = _streamReader.Read(offset, out record.{member.GetMemberFieldName()});"); - } - WriteLine("return record;"); + WriteLine($"return new {record.Name}(this, handle);"); CloseScope($"Get{record.Name}"); } - foreach (var record in SchemaDef.RecordSchema) - { - OpenScope($"internal Handle ToHandle({record.Name}Handle handle)"); - WriteLine("return new Handle(handle._value);"); - CloseScope("ToHandle"); - } - - foreach (var record in SchemaDef.RecordSchema) - { - string handleName = $"{record.Name}Handle"; - - OpenScope($"internal {handleName} To{handleName}(Handle handle)"); - WriteLine($"return new {handleName}(handle._value);"); - CloseScope($"To{handleName}"); - } - - foreach (var record in SchemaDef.RecordSchema) - { - OpenScope($"internal bool IsNull({record.Name}Handle handle)"); - WriteLine("return (handle._value & 0x00FFFFFF) == 0;"); - CloseScope("IsNull"); - } - CloseScope("MetadataReader"); } } diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/SchemaDef.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/SchemaDef.cs index daea57e6e4a1..371b9488a7d3 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/SchemaDef.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/SchemaDef.cs @@ -315,6 +315,13 @@ from primitiveType in PrimitiveTypes members: new MemberDef[] { new MemberDef(name: "Value", typeName: "string") } + ), + new RecordDef( + name: "ConstantEnumValue", + members: new MemberDef[] { + new MemberDef("Value", EnumConstantValue, MemberDefFlags.RecordRef | MemberDefFlags.Child), + new MemberDef("Type", TypeDefOrRefOrSpec, MemberDefFlags.RecordRef) + } ) } ) @@ -630,13 +637,6 @@ from primitiveType in PrimitiveTypes new MemberDef("Value", TypeDefOrRefOrSpecOrConstant, MemberDefFlags.RecordRef), } ), - new RecordDef( - name: "ConstantBoxedEnumValue", - members: new MemberDef[] { - new MemberDef("Value", EnumConstantValue, MemberDefFlags.RecordRef | MemberDefFlags.Child), - new MemberDef("Type", TypeDefOrRefOrSpec, MemberDefFlags.RecordRef) - } - ), new RecordDef( name: "GenericParameter", members: new MemberDef[] { diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/MdBinaryReaderGen.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/MdBinaryReaderGen.cs index bbac55d70830..6f0d97a9c388 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/MdBinaryReaderGen.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/MdBinaryReaderGen.cs @@ -300,15 +300,6 @@ public static uint Read(this NativeReader reader, uint offset, out ConstantBoole return offset; } // Read - public static uint Read(this NativeReader reader, uint offset, out ConstantBoxedEnumValueHandle handle) - { - uint value; - offset = reader.DecodeUnsigned(offset, out value); - handle = new ConstantBoxedEnumValueHandle((int)value); - handle._Validate(); - return offset; - } // Read - public static uint Read(this NativeReader reader, uint offset, out ConstantByteArrayHandle handle) { uint value; @@ -372,6 +363,15 @@ public static uint Read(this NativeReader reader, uint offset, out ConstantEnumA return offset; } // Read + public static uint Read(this NativeReader reader, uint offset, out ConstantEnumValueHandle handle) + { + uint value; + offset = reader.DecodeUnsigned(offset, out value); + handle = new ConstantEnumValueHandle((int)value); + handle._Validate(); + return offset; + } // Read + public static uint Read(this NativeReader reader, uint offset, out ConstantHandleArrayHandle handle) { uint value; diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderCommonGen.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderCommonGen.cs index bb7fefd7816c..5e25a0827864 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderCommonGen.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderCommonGen.cs @@ -14,6 +14,7 @@ namespace Internal.Metadata.NativeFormat { + // Internal clone of System.Reflection.AssemblyFlags from System.Reflection.Metadata [Flags] #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] @@ -26,13 +27,12 @@ public enum AssemblyFlags : uint /// The implementation of this assembly used at runtime is not expected to match the version seen at compile time. Retargetable = 0x100, - /// Reserved. - DisableJITcompileOptimizer = 0x4000, + /// Content type mask. Masked bits correspond to values of System.Reflection.AssemblyContentType + ContentTypeMask = 0x00000e00, - /// Reserved. - EnableJITcompileTracking = 0x8000, } // AssemblyFlags + // Internal clone of System.Reflection.AssemblyHashAlgorithm from System.Reflection.Metadata #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif @@ -94,14 +94,14 @@ public enum HandleType : byte ByReferenceSignature = 0x2, ConstantBooleanArray = 0x3, ConstantBooleanValue = 0x4, - ConstantBoxedEnumValue = 0x5, - ConstantByteArray = 0x6, - ConstantByteValue = 0x7, - ConstantCharArray = 0x8, - ConstantCharValue = 0x9, - ConstantDoubleArray = 0xa, - ConstantDoubleValue = 0xb, - ConstantEnumArray = 0xc, + ConstantByteArray = 0x5, + ConstantByteValue = 0x6, + ConstantCharArray = 0x7, + ConstantCharValue = 0x8, + ConstantDoubleArray = 0x9, + ConstantDoubleValue = 0xa, + ConstantEnumArray = 0xb, + ConstantEnumValue = 0xc, ConstantHandleArray = 0xd, ConstantInt16Array = 0xe, ConstantInt16Value = 0xf, diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs index 7bf0d91f44e5..958e605b1282 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs @@ -24,92 +24,45 @@ namespace Internal.Metadata.NativeFormat #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ArraySignature + public readonly partial struct ArraySignature { - internal MetadataReader _reader; - internal ArraySignatureHandle _handle; + private readonly MetadataReader _reader; + private readonly ArraySignatureHandle _handle; - public ArraySignatureHandle Handle + internal ArraySignature(MetadataReader reader, ArraySignatureHandle handle) { - get - { - return _handle; - } - } // Handle - /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType - - public Handle ElementType - { - get - { - return _elementType; - } - } // ElementType - - internal Handle _elementType; - - public int Rank - { - get - { - return _rank; - } - } // Rank + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _elementType); + offset = streamReader.Read(offset, out _rank); + offset = streamReader.Read(offset, out _sizes); + offset = streamReader.Read(offset, out _lowerBounds); + } - internal int _rank; + public ArraySignatureHandle Handle => _handle; - public Int32Collection Sizes - { - get - { - return _sizes; - } - } // Sizes + /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + public Handle ElementType => _elementType; + private readonly Handle _elementType; - internal Int32Collection _sizes; + public int Rank => _rank; + private readonly int _rank; - public Int32Collection LowerBounds - { - get - { - return _lowerBounds; - } - } // LowerBounds + public Int32Collection Sizes => _sizes; + private readonly Int32Collection _sizes; - internal Int32Collection _lowerBounds; + public Int32Collection LowerBounds => _lowerBounds; + private readonly Int32Collection _lowerBounds; } // ArraySignature #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ArraySignatureHandle + public readonly partial struct ArraySignatureHandle { - public override bool Equals(object obj) - { - if (obj is ArraySignatureHandle) - return _value == ((ArraySignatureHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ArraySignatureHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ArraySignatureHandle(Handle handle) : this(handle._value) { @@ -123,33 +76,31 @@ internal ArraySignatureHandle(int value) _Validate(); } - public static implicit operator Handle(ArraySignatureHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ArraySignatureHandle) + return _value == ((ArraySignatureHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ArraySignatureHandle handle) => _value == handle._value; - public ArraySignature GetArraySignature(MetadataReader reader) - { - return reader.GetArraySignature(this); - } // GetArraySignature + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ArraySignatureHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ArraySignature GetArraySignature(MetadataReader reader) + => new ArraySignature(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -158,71 +109,39 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ArraySignatureHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ByReferenceSignature + public readonly partial struct ByReferenceSignature { - internal MetadataReader _reader; - internal ByReferenceSignatureHandle _handle; + private readonly MetadataReader _reader; + private readonly ByReferenceSignatureHandle _handle; - public ByReferenceSignatureHandle Handle + internal ByReferenceSignature(MetadataReader reader, ByReferenceSignatureHandle handle) { - get - { - return _handle; - } - } // Handle - /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _type); + } - public Handle Type - { - get - { - return _type; - } - } // Type + public ByReferenceSignatureHandle Handle => _handle; - internal Handle _type; + /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + public Handle Type => _type; + private readonly Handle _type; } // ByReferenceSignature #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ByReferenceSignatureHandle + public readonly partial struct ByReferenceSignatureHandle { - public override bool Equals(object obj) - { - if (obj is ByReferenceSignatureHandle) - return _value == ((ByReferenceSignatureHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ByReferenceSignatureHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ByReferenceSignatureHandle(Handle handle) : this(handle._value) { @@ -236,33 +155,31 @@ internal ByReferenceSignatureHandle(int value) _Validate(); } - public static implicit operator Handle(ByReferenceSignatureHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ByReferenceSignatureHandle) + return _value == ((ByReferenceSignatureHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ByReferenceSignatureHandle handle) => _value == handle._value; - public ByReferenceSignature GetByReferenceSignature(MetadataReader reader) - { - return reader.GetByReferenceSignature(this); - } // GetByReferenceSignature + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ByReferenceSignatureHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ByReferenceSignature GetByReferenceSignature(MetadataReader reader) + => new ByReferenceSignature(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -271,70 +188,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ByReferenceSignatureHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantBooleanArray + public readonly partial struct ConstantBooleanArray { - internal MetadataReader _reader; - internal ConstantBooleanArrayHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantBooleanArrayHandle _handle; - public ConstantBooleanArrayHandle Handle + internal ConstantBooleanArray(MetadataReader reader, ConstantBooleanArrayHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public BooleanCollection Value - { - get - { - return _value; - } - } // Value + public ConstantBooleanArrayHandle Handle => _handle; - internal BooleanCollection _value; + public BooleanCollection Value => _value; + private readonly BooleanCollection _value; } // ConstantBooleanArray #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantBooleanArrayHandle + public readonly partial struct ConstantBooleanArrayHandle { - public override bool Equals(object obj) - { - if (obj is ConstantBooleanArrayHandle) - return _value == ((ConstantBooleanArrayHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantBooleanArrayHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantBooleanArrayHandle(Handle handle) : this(handle._value) { @@ -348,33 +233,31 @@ internal ConstantBooleanArrayHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantBooleanArrayHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantBooleanArrayHandle) + return _value == ((ConstantBooleanArrayHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantBooleanArrayHandle handle) => _value == handle._value; - public ConstantBooleanArray GetConstantBooleanArray(MetadataReader reader) - { - return reader.GetConstantBooleanArray(this); - } // GetConstantBooleanArray + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantBooleanArrayHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantBooleanArray GetConstantBooleanArray(MetadataReader reader) + => new ConstantBooleanArray(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -383,70 +266,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantBooleanArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantBooleanValue + public readonly partial struct ConstantBooleanValue { - internal MetadataReader _reader; - internal ConstantBooleanValueHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantBooleanValueHandle _handle; - public ConstantBooleanValueHandle Handle + internal ConstantBooleanValue(MetadataReader reader, ConstantBooleanValueHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public bool Value - { - get - { - return _value; - } - } // Value + public ConstantBooleanValueHandle Handle => _handle; - internal bool _value; + public bool Value => _value; + private readonly bool _value; } // ConstantBooleanValue #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantBooleanValueHandle + public readonly partial struct ConstantBooleanValueHandle { - public override bool Equals(object obj) - { - if (obj is ConstantBooleanValueHandle) - return _value == ((ConstantBooleanValueHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantBooleanValueHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantBooleanValueHandle(Handle handle) : this(handle._value) { @@ -460,33 +311,31 @@ internal ConstantBooleanValueHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantBooleanValueHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantBooleanValueHandle) + return _value == ((ConstantBooleanValueHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantBooleanValueHandle handle) => _value == handle._value; - public ConstantBooleanValue GetConstantBooleanValue(MetadataReader reader) - { - return reader.GetConstantBooleanValue(this); - } // GetConstantBooleanValue + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantBooleanValueHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantBooleanValue GetConstantBooleanValue(MetadataReader reader) + => new ConstantBooleanValue(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -495,280 +344,129 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantBooleanValueHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantBoxedEnumValue + public readonly partial struct ConstantByteArray { - internal MetadataReader _reader; - internal ConstantBoxedEnumValueHandle _handle; - - public ConstantBoxedEnumValueHandle Handle - { - get - { - return _handle; - } - } // Handle - /// One of: ConstantByteValue, ConstantSByteValue, ConstantInt16Value, ConstantUInt16Value, ConstantInt32Value, ConstantUInt32Value, ConstantInt64Value, ConstantUInt64Value + private readonly MetadataReader _reader; + private readonly ConstantByteArrayHandle _handle; - public Handle Value + internal ConstantByteArray(MetadataReader reader, ConstantByteArrayHandle handle) { - get - { - return _value; - } - } // Value - - internal Handle _value; - /// One of: TypeDefinition, TypeReference, TypeSpecification + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public Handle Type - { - get - { - return _type; - } - } // Type + public ConstantByteArrayHandle Handle => _handle; - internal Handle _type; - } // ConstantBoxedEnumValue + public ByteCollection Value => _value; + private readonly ByteCollection _value; + } // ConstantByteArray #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantBoxedEnumValueHandle + public readonly partial struct ConstantByteArrayHandle { + internal readonly int _value; + + internal ConstantByteArrayHandle(Handle handle) : this(handle._value) + { + } + + internal ConstantByteArrayHandle(int value) + { + HandleType hType = (HandleType)(value >> 24); + Debug.Assert(hType == 0 || hType == HandleType.ConstantByteArray || hType == HandleType.Null); + _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantByteArray) << 24); + _Validate(); + } + public override bool Equals(object obj) { - if (obj is ConstantBoxedEnumValueHandle) - return _value == ((ConstantBoxedEnumValueHandle)obj)._value; + if (obj is ConstantByteArrayHandle) + return _value == ((ConstantByteArrayHandle)obj)._value; else if (obj is Handle) return _value == ((Handle)obj)._value; else return false; } // Equals - public bool Equals(ConstantBoxedEnumValueHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; - - internal ConstantBoxedEnumValueHandle(Handle handle) : this(handle._value) - { - } + public bool Equals(ConstantByteArrayHandle handle) => _value == handle._value; - internal ConstantBoxedEnumValueHandle(int value) - { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantBoxedEnumValue || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantBoxedEnumValue) << 24); - _Validate(); - } + public bool Equals(Handle handle) => _value == handle._value; - public static implicit operator Handle(ConstantBoxedEnumValueHandle handle) - { - return new Handle(handle._value); - } // Handle + public override int GetHashCode() => (int)_value; - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public static implicit operator Handle(ConstantByteArrayHandle handle) + => new Handle(handle._value); - public ConstantBoxedEnumValue GetConstantBoxedEnumValue(MetadataReader reader) - { - return reader.GetConstantBoxedEnumValue(this); - } // GetConstantBoxedEnumValue + internal int Offset => (_value & 0x00FFFFFF); - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public ConstantByteArray GetConstantByteArray(MetadataReader reader) + => new ConstantByteArray(reader, this); - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantBoxedEnumValue) + if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantByteArray) throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString - } // ConstantBoxedEnumValueHandle + public override string ToString() => string.Format("{0:X8}", _value); + } // ConstantByteArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantByteArray + public readonly partial struct ConstantByteValue { - internal MetadataReader _reader; - internal ConstantByteArrayHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantByteValueHandle _handle; - public ConstantByteArrayHandle Handle + internal ConstantByteValue(MetadataReader reader, ConstantByteValueHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public ByteCollection Value - { - get - { - return _value; - } - } // Value + public ConstantByteValueHandle Handle => _handle; - internal ByteCollection _value; - } // ConstantByteArray + public byte Value => _value; + private readonly byte _value; + } // ConstantByteValue #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantByteArrayHandle + public readonly partial struct ConstantByteValueHandle { - public override bool Equals(object obj) - { - if (obj is ConstantByteArrayHandle) - return _value == ((ConstantByteArrayHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantByteArrayHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; - internal ConstantByteArrayHandle(Handle handle) : this(handle._value) + internal ConstantByteValueHandle(Handle handle) : this(handle._value) { } - internal ConstantByteArrayHandle(int value) + internal ConstantByteValueHandle(int value) { HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantByteArray || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantByteArray) << 24); + Debug.Assert(hType == 0 || hType == HandleType.ConstantByteValue || hType == HandleType.Null); + _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantByteValue) << 24); _Validate(); } - public static implicit operator Handle(ConstantByteArrayHandle handle) - { - return new Handle(handle._value); - } // Handle - - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset - - public ConstantByteArray GetConstantByteArray(MetadataReader reader) - { - return reader.GetConstantByteArray(this); - } // GetConstantByteArray - - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull - - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle - - [System.Diagnostics.Conditional("DEBUG")] - internal void _Validate() - { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantByteArray) - throw new ArgumentException(); - } // _Validate - - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString - } // ConstantByteArrayHandle - -#if SYSTEM_PRIVATE_CORELIB - [CLSCompliant(false)] -#endif - public partial struct ConstantByteValue - { - internal MetadataReader _reader; - internal ConstantByteValueHandle _handle; - - public ConstantByteValueHandle Handle - { - get - { - return _handle; - } - } // Handle - - public byte Value - { - get - { - return _value; - } - } // Value - - internal byte _value; - } // ConstantByteValue - -#if SYSTEM_PRIVATE_CORELIB - [CLSCompliant(false)] -#endif - public partial struct ConstantByteValueHandle - { public override bool Equals(object obj) { if (obj is ConstantByteValueHandle) @@ -779,62 +477,21 @@ public override bool Equals(object obj) return false; } // Equals - public bool Equals(ConstantByteValueHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + public bool Equals(ConstantByteValueHandle handle) => _value == handle._value; - internal ConstantByteValueHandle(Handle handle) : this(handle._value) - { - } + public bool Equals(Handle handle) => _value == handle._value; - internal ConstantByteValueHandle(int value) - { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantByteValue || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantByteValue) << 24); - _Validate(); - } + public override int GetHashCode() => (int)_value; public static implicit operator Handle(ConstantByteValueHandle handle) - { - return new Handle(handle._value); - } // Handle + => new Handle(handle._value); - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + internal int Offset => (_value & 0x00FFFFFF); public ConstantByteValue GetConstantByteValue(MetadataReader reader) - { - return reader.GetConstantByteValue(this); - } // GetConstantByteValue + => new ConstantByteValue(reader, this); - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull - - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -843,70 +500,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantByteValueHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantCharArray + public readonly partial struct ConstantCharArray { - internal MetadataReader _reader; - internal ConstantCharArrayHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantCharArrayHandle _handle; - public ConstantCharArrayHandle Handle + internal ConstantCharArray(MetadataReader reader, ConstantCharArrayHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public CharCollection Value - { - get - { - return _value; - } - } // Value + public ConstantCharArrayHandle Handle => _handle; - internal CharCollection _value; + public CharCollection Value => _value; + private readonly CharCollection _value; } // ConstantCharArray #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantCharArrayHandle + public readonly partial struct ConstantCharArrayHandle { - public override bool Equals(object obj) - { - if (obj is ConstantCharArrayHandle) - return _value == ((ConstantCharArrayHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantCharArrayHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantCharArrayHandle(Handle handle) : this(handle._value) { @@ -920,33 +545,31 @@ internal ConstantCharArrayHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantCharArrayHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantCharArrayHandle) + return _value == ((ConstantCharArrayHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantCharArrayHandle handle) => _value == handle._value; - public ConstantCharArray GetConstantCharArray(MetadataReader reader) - { - return reader.GetConstantCharArray(this); - } // GetConstantCharArray + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantCharArrayHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantCharArray GetConstantCharArray(MetadataReader reader) + => new ConstantCharArray(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -955,70 +578,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantCharArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantCharValue + public readonly partial struct ConstantCharValue { - internal MetadataReader _reader; - internal ConstantCharValueHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantCharValueHandle _handle; - public ConstantCharValueHandle Handle + internal ConstantCharValue(MetadataReader reader, ConstantCharValueHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public char Value - { - get - { - return _value; - } - } // Value + public ConstantCharValueHandle Handle => _handle; - internal char _value; + public char Value => _value; + private readonly char _value; } // ConstantCharValue #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantCharValueHandle + public readonly partial struct ConstantCharValueHandle { - public override bool Equals(object obj) - { - if (obj is ConstantCharValueHandle) - return _value == ((ConstantCharValueHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantCharValueHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantCharValueHandle(Handle handle) : this(handle._value) { @@ -1032,33 +623,31 @@ internal ConstantCharValueHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantCharValueHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantCharValueHandle) + return _value == ((ConstantCharValueHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantCharValueHandle handle) => _value == handle._value; - public ConstantCharValue GetConstantCharValue(MetadataReader reader) - { - return reader.GetConstantCharValue(this); - } // GetConstantCharValue + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantCharValueHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantCharValue GetConstantCharValue(MetadataReader reader) + => new ConstantCharValue(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -1067,72 +656,40 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantCharValueHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantDoubleArray + public readonly partial struct ConstantDoubleArray { - internal MetadataReader _reader; - internal ConstantDoubleArrayHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantDoubleArrayHandle _handle; - public ConstantDoubleArrayHandle Handle + internal ConstantDoubleArray(MetadataReader reader, ConstantDoubleArrayHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public DoubleCollection Value - { - get - { - return _value; - } - } // Value + public ConstantDoubleArrayHandle Handle => _handle; - internal DoubleCollection _value; + public DoubleCollection Value => _value; + private readonly DoubleCollection _value; } // ConstantDoubleArray #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantDoubleArrayHandle + public readonly partial struct ConstantDoubleArrayHandle { - public override bool Equals(object obj) - { - if (obj is ConstantDoubleArrayHandle) - return _value == ((ConstantDoubleArrayHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantDoubleArrayHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; - - internal ConstantDoubleArrayHandle(Handle handle) : this(handle._value) + internal readonly int _value; + + internal ConstantDoubleArrayHandle(Handle handle) : this(handle._value) { } @@ -1144,33 +701,31 @@ internal ConstantDoubleArrayHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantDoubleArrayHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantDoubleArrayHandle) + return _value == ((ConstantDoubleArrayHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantDoubleArrayHandle handle) => _value == handle._value; - public ConstantDoubleArray GetConstantDoubleArray(MetadataReader reader) - { - return reader.GetConstantDoubleArray(this); - } // GetConstantDoubleArray + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantDoubleArrayHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantDoubleArray GetConstantDoubleArray(MetadataReader reader) + => new ConstantDoubleArray(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -1179,70 +734,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantDoubleArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantDoubleValue + public readonly partial struct ConstantDoubleValue { - internal MetadataReader _reader; - internal ConstantDoubleValueHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantDoubleValueHandle _handle; - public ConstantDoubleValueHandle Handle + internal ConstantDoubleValue(MetadataReader reader, ConstantDoubleValueHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public double Value - { - get - { - return _value; - } - } // Value + public ConstantDoubleValueHandle Handle => _handle; - internal double _value; + public double Value => _value; + private readonly double _value; } // ConstantDoubleValue #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantDoubleValueHandle + public readonly partial struct ConstantDoubleValueHandle { - public override bool Equals(object obj) - { - if (obj is ConstantDoubleValueHandle) - return _value == ((ConstantDoubleValueHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantDoubleValueHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantDoubleValueHandle(Handle handle) : this(handle._value) { @@ -1256,33 +779,31 @@ internal ConstantDoubleValueHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantDoubleValueHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantDoubleValueHandle) + return _value == ((ConstantDoubleValueHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantDoubleValueHandle handle) => _value == handle._value; - public ConstantDoubleValue GetConstantDoubleValue(MetadataReader reader) - { - return reader.GetConstantDoubleValue(this); - } // GetConstantDoubleValue + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantDoubleValueHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantDoubleValue GetConstantDoubleValue(MetadataReader reader) + => new ConstantDoubleValue(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -1291,80 +812,42 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantDoubleValueHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantEnumArray + public readonly partial struct ConstantEnumArray { - internal MetadataReader _reader; - internal ConstantEnumArrayHandle _handle; - - public ConstantEnumArrayHandle Handle - { - get - { - return _handle; - } - } // Handle + private readonly MetadataReader _reader; + private readonly ConstantEnumArrayHandle _handle; - public Handle ElementType + internal ConstantEnumArray(MetadataReader reader, ConstantEnumArrayHandle handle) { - get - { - return _elementType; - } - } // ElementType + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _elementType); + offset = streamReader.Read(offset, out _value); + } - internal Handle _elementType; + public ConstantEnumArrayHandle Handle => _handle; - public Handle Value - { - get - { - return _value; - } - } // Value + public Handle ElementType => _elementType; + private readonly Handle _elementType; - internal Handle _value; + public Handle Value => _value; + private readonly Handle _value; } // ConstantEnumArray #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantEnumArrayHandle + public readonly partial struct ConstantEnumArrayHandle { - public override bool Equals(object obj) - { - if (obj is ConstantEnumArrayHandle) - return _value == ((ConstantEnumArrayHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantEnumArrayHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantEnumArrayHandle(Handle handle) : this(handle._value) { @@ -1378,33 +861,31 @@ internal ConstantEnumArrayHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantEnumArrayHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantEnumArrayHandle) + return _value == ((ConstantEnumArrayHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantEnumArrayHandle handle) => _value == handle._value; - public ConstantEnumArray GetConstantEnumArray(MetadataReader reader) - { - return reader.GetConstantEnumArray(this); - } // GetConstantEnumArray + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantEnumArrayHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantEnumArray GetConstantEnumArray(MetadataReader reader) + => new ConstantEnumArray(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -1413,70 +894,120 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantEnumArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantHandleArray + public readonly partial struct ConstantEnumValue { - internal MetadataReader _reader; - internal ConstantHandleArrayHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantEnumValueHandle _handle; - public ConstantHandleArrayHandle Handle + internal ConstantEnumValue(MetadataReader reader, ConstantEnumValueHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + offset = streamReader.Read(offset, out _type); + } - public HandleCollection Value - { - get - { - return _value; - } - } // Value + public ConstantEnumValueHandle Handle => _handle; - internal HandleCollection _value; - } // ConstantHandleArray + public Handle Value => _value; + private readonly Handle _value; + + public Handle Type => _type; + private readonly Handle _type; + } // ConstantEnumValue #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantHandleArrayHandle + public readonly partial struct ConstantEnumValueHandle { + internal readonly int _value; + + internal ConstantEnumValueHandle(Handle handle) : this(handle._value) + { + } + + internal ConstantEnumValueHandle(int value) + { + HandleType hType = (HandleType)(value >> 24); + Debug.Assert(hType == 0 || hType == HandleType.ConstantEnumValue || hType == HandleType.Null); + _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantEnumValue) << 24); + _Validate(); + } + public override bool Equals(object obj) { - if (obj is ConstantHandleArrayHandle) - return _value == ((ConstantHandleArrayHandle)obj)._value; + if (obj is ConstantEnumValueHandle) + return _value == ((ConstantEnumValueHandle)obj)._value; else if (obj is Handle) return _value == ((Handle)obj)._value; else return false; } // Equals - public bool Equals(ConstantHandleArrayHandle handle) - { - return _value == handle._value; - } // Equals + public bool Equals(ConstantEnumValueHandle handle) => _value == handle._value; + + public bool Equals(Handle handle) => _value == handle._value; + + public override int GetHashCode() => (int)_value; + + public static implicit operator Handle(ConstantEnumValueHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); - public bool Equals(Handle handle) + public ConstantEnumValue GetConstantEnumValue(MetadataReader reader) + => new ConstantEnumValue(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; + + [System.Diagnostics.Conditional("DEBUG")] + internal void _Validate() { - return _value == handle._value; - } // Equals + if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantEnumValue) + throw new ArgumentException(); + } // _Validate + + public override string ToString() => string.Format("{0:X8}", _value); + } // ConstantEnumValueHandle - public override int GetHashCode() +#if SYSTEM_PRIVATE_CORELIB + [CLSCompliant(false)] +#endif + public readonly partial struct ConstantHandleArray + { + private readonly MetadataReader _reader; + private readonly ConstantHandleArrayHandle _handle; + + internal ConstantHandleArray(MetadataReader reader, ConstantHandleArrayHandle handle) { - return (int)_value; - } // GetHashCode + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } + + public ConstantHandleArrayHandle Handle => _handle; - internal int _value; + public HandleCollection Value => _value; + private readonly HandleCollection _value; + } // ConstantHandleArray + +#if SYSTEM_PRIVATE_CORELIB + [CLSCompliant(false)] +#endif + public readonly partial struct ConstantHandleArrayHandle + { + internal readonly int _value; internal ConstantHandleArrayHandle(Handle handle) : this(handle._value) { @@ -1490,33 +1021,31 @@ internal ConstantHandleArrayHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantHandleArrayHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantHandleArrayHandle) + return _value == ((ConstantHandleArrayHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantHandleArrayHandle handle) => _value == handle._value; - public ConstantHandleArray GetConstantHandleArray(MetadataReader reader) - { - return reader.GetConstantHandleArray(this); - } // GetConstantHandleArray + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantHandleArrayHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantHandleArray GetConstantHandleArray(MetadataReader reader) + => new ConstantHandleArray(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -1525,44 +1054,51 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantHandleArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantInt16Array + public readonly partial struct ConstantInt16Array { - internal MetadataReader _reader; - internal ConstantInt16ArrayHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantInt16ArrayHandle _handle; - public ConstantInt16ArrayHandle Handle + internal ConstantInt16Array(MetadataReader reader, ConstantInt16ArrayHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public Int16Collection Value - { - get - { - return _value; - } - } // Value + public ConstantInt16ArrayHandle Handle => _handle; - internal Int16Collection _value; + public Int16Collection Value => _value; + private readonly Int16Collection _value; } // ConstantInt16Array #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantInt16ArrayHandle + public readonly partial struct ConstantInt16ArrayHandle { + internal readonly int _value; + + internal ConstantInt16ArrayHandle(Handle handle) : this(handle._value) + { + } + + internal ConstantInt16ArrayHandle(int value) + { + HandleType hType = (HandleType)(value >> 24); + Debug.Assert(hType == 0 || hType == HandleType.ConstantInt16Array || hType == HandleType.Null); + _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantInt16Array) << 24); + _Validate(); + } + public override bool Equals(object obj) { if (obj is ConstantInt16ArrayHandle) @@ -1573,62 +1109,21 @@ public override bool Equals(object obj) return false; } // Equals - public bool Equals(ConstantInt16ArrayHandle handle) - { - return _value == handle._value; - } // Equals + public bool Equals(ConstantInt16ArrayHandle handle) => _value == handle._value; - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals + public bool Equals(Handle handle) => _value == handle._value; - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode + public override int GetHashCode() => (int)_value; - internal int _value; + public static implicit operator Handle(ConstantInt16ArrayHandle handle) + => new Handle(handle._value); - internal ConstantInt16ArrayHandle(Handle handle) : this(handle._value) - { - } - - internal ConstantInt16ArrayHandle(int value) - { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantInt16Array || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantInt16Array) << 24); - _Validate(); - } - - public static implicit operator Handle(ConstantInt16ArrayHandle handle) - { - return new Handle(handle._value); - } // Handle - - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + internal int Offset => (_value & 0x00FFFFFF); public ConstantInt16Array GetConstantInt16Array(MetadataReader reader) - { - return reader.GetConstantInt16Array(this); - } // GetConstantInt16Array - - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + => new ConstantInt16Array(reader, this); - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -1637,70 +1132,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantInt16ArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantInt16Value + public readonly partial struct ConstantInt16Value { - internal MetadataReader _reader; - internal ConstantInt16ValueHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantInt16ValueHandle _handle; - public ConstantInt16ValueHandle Handle + internal ConstantInt16Value(MetadataReader reader, ConstantInt16ValueHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public short Value - { - get - { - return _value; - } - } // Value + public ConstantInt16ValueHandle Handle => _handle; - internal short _value; + public short Value => _value; + private readonly short _value; } // ConstantInt16Value #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantInt16ValueHandle + public readonly partial struct ConstantInt16ValueHandle { - public override bool Equals(object obj) - { - if (obj is ConstantInt16ValueHandle) - return _value == ((ConstantInt16ValueHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantInt16ValueHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantInt16ValueHandle(Handle handle) : this(handle._value) { @@ -1714,33 +1177,31 @@ internal ConstantInt16ValueHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantInt16ValueHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantInt16ValueHandle) + return _value == ((ConstantInt16ValueHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantInt16ValueHandle handle) => _value == handle._value; - public ConstantInt16Value GetConstantInt16Value(MetadataReader reader) - { - return reader.GetConstantInt16Value(this); - } // GetConstantInt16Value + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantInt16ValueHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantInt16Value GetConstantInt16Value(MetadataReader reader) + => new ConstantInt16Value(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -1749,70 +1210,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantInt16ValueHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantInt32Array + public readonly partial struct ConstantInt32Array { - internal MetadataReader _reader; - internal ConstantInt32ArrayHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantInt32ArrayHandle _handle; - public ConstantInt32ArrayHandle Handle + internal ConstantInt32Array(MetadataReader reader, ConstantInt32ArrayHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public Int32Collection Value - { - get - { - return _value; - } - } // Value + public ConstantInt32ArrayHandle Handle => _handle; - internal Int32Collection _value; + public Int32Collection Value => _value; + private readonly Int32Collection _value; } // ConstantInt32Array #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantInt32ArrayHandle + public readonly partial struct ConstantInt32ArrayHandle { - public override bool Equals(object obj) - { - if (obj is ConstantInt32ArrayHandle) - return _value == ((ConstantInt32ArrayHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantInt32ArrayHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantInt32ArrayHandle(Handle handle) : this(handle._value) { @@ -1826,33 +1255,31 @@ internal ConstantInt32ArrayHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantInt32ArrayHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantInt32ArrayHandle) + return _value == ((ConstantInt32ArrayHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantInt32ArrayHandle handle) => _value == handle._value; - public ConstantInt32Array GetConstantInt32Array(MetadataReader reader) - { - return reader.GetConstantInt32Array(this); - } // GetConstantInt32Array + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantInt32ArrayHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantInt32Array GetConstantInt32Array(MetadataReader reader) + => new ConstantInt32Array(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -1861,70 +1288,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantInt32ArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantInt32Value + public readonly partial struct ConstantInt32Value { - internal MetadataReader _reader; - internal ConstantInt32ValueHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantInt32ValueHandle _handle; - public ConstantInt32ValueHandle Handle + internal ConstantInt32Value(MetadataReader reader, ConstantInt32ValueHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public int Value - { - get - { - return _value; - } - } // Value + public ConstantInt32ValueHandle Handle => _handle; - internal int _value; + public int Value => _value; + private readonly int _value; } // ConstantInt32Value #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantInt32ValueHandle + public readonly partial struct ConstantInt32ValueHandle { - public override bool Equals(object obj) - { - if (obj is ConstantInt32ValueHandle) - return _value == ((ConstantInt32ValueHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantInt32ValueHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantInt32ValueHandle(Handle handle) : this(handle._value) { @@ -1938,33 +1333,31 @@ internal ConstantInt32ValueHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantInt32ValueHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantInt32ValueHandle) + return _value == ((ConstantInt32ValueHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantInt32ValueHandle handle) => _value == handle._value; - public ConstantInt32Value GetConstantInt32Value(MetadataReader reader) - { - return reader.GetConstantInt32Value(this); - } // GetConstantInt32Value + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantInt32ValueHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantInt32Value GetConstantInt32Value(MetadataReader reader) + => new ConstantInt32Value(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -1973,70 +1366,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantInt32ValueHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantInt64Array + public readonly partial struct ConstantInt64Array { - internal MetadataReader _reader; - internal ConstantInt64ArrayHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantInt64ArrayHandle _handle; - public ConstantInt64ArrayHandle Handle + internal ConstantInt64Array(MetadataReader reader, ConstantInt64ArrayHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public Int64Collection Value - { - get - { - return _value; - } - } // Value + public ConstantInt64ArrayHandle Handle => _handle; - internal Int64Collection _value; + public Int64Collection Value => _value; + private readonly Int64Collection _value; } // ConstantInt64Array #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantInt64ArrayHandle + public readonly partial struct ConstantInt64ArrayHandle { - public override bool Equals(object obj) - { - if (obj is ConstantInt64ArrayHandle) - return _value == ((ConstantInt64ArrayHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantInt64ArrayHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantInt64ArrayHandle(Handle handle) : this(handle._value) { @@ -2050,33 +1411,31 @@ internal ConstantInt64ArrayHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantInt64ArrayHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantInt64ArrayHandle) + return _value == ((ConstantInt64ArrayHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantInt64ArrayHandle handle) => _value == handle._value; - public ConstantInt64Array GetConstantInt64Array(MetadataReader reader) - { - return reader.GetConstantInt64Array(this); - } // GetConstantInt64Array + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantInt64ArrayHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantInt64Array GetConstantInt64Array(MetadataReader reader) + => new ConstantInt64Array(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -2085,44 +1444,51 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantInt64ArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantInt64Value + public readonly partial struct ConstantInt64Value { - internal MetadataReader _reader; - internal ConstantInt64ValueHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantInt64ValueHandle _handle; - public ConstantInt64ValueHandle Handle + internal ConstantInt64Value(MetadataReader reader, ConstantInt64ValueHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public long Value - { - get - { - return _value; - } - } // Value + public ConstantInt64ValueHandle Handle => _handle; - internal long _value; + public long Value => _value; + private readonly long _value; } // ConstantInt64Value #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantInt64ValueHandle + public readonly partial struct ConstantInt64ValueHandle { + internal readonly int _value; + + internal ConstantInt64ValueHandle(Handle handle) : this(handle._value) + { + } + + internal ConstantInt64ValueHandle(int value) + { + HandleType hType = (HandleType)(value >> 24); + Debug.Assert(hType == 0 || hType == HandleType.ConstantInt64Value || hType == HandleType.Null); + _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantInt64Value) << 24); + _Validate(); + } + public override bool Equals(object obj) { if (obj is ConstantInt64ValueHandle) @@ -2133,62 +1499,21 @@ public override bool Equals(object obj) return false; } // Equals - public bool Equals(ConstantInt64ValueHandle handle) - { - return _value == handle._value; - } // Equals + public bool Equals(ConstantInt64ValueHandle handle) => _value == handle._value; - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals + public bool Equals(Handle handle) => _value == handle._value; - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode + public override int GetHashCode() => (int)_value; - internal int _value; + public static implicit operator Handle(ConstantInt64ValueHandle handle) + => new Handle(handle._value); - internal ConstantInt64ValueHandle(Handle handle) : this(handle._value) - { - } - - internal ConstantInt64ValueHandle(int value) - { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantInt64Value || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantInt64Value) << 24); - _Validate(); - } - - public static implicit operator Handle(ConstantInt64ValueHandle handle) - { - return new Handle(handle._value); - } // Handle - - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + internal int Offset => (_value & 0x00FFFFFF); public ConstantInt64Value GetConstantInt64Value(MetadataReader reader) - { - return reader.GetConstantInt64Value(this); - } // GetConstantInt64Value + => new ConstantInt64Value(reader, this); - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull - - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -2197,60 +1522,34 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantInt64ValueHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantReferenceValue + public readonly partial struct ConstantReferenceValue { - internal MetadataReader _reader; - internal ConstantReferenceValueHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantReferenceValueHandle _handle; - public ConstantReferenceValueHandle Handle + internal ConstantReferenceValue(MetadataReader reader, ConstantReferenceValueHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + } + + public ConstantReferenceValueHandle Handle => _handle; } // ConstantReferenceValue #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantReferenceValueHandle + public readonly partial struct ConstantReferenceValueHandle { - public override bool Equals(object obj) - { - if (obj is ConstantReferenceValueHandle) - return _value == ((ConstantReferenceValueHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantReferenceValueHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantReferenceValueHandle(Handle handle) : this(handle._value) { @@ -2264,33 +1563,31 @@ internal ConstantReferenceValueHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantReferenceValueHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantReferenceValueHandle) + return _value == ((ConstantReferenceValueHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantReferenceValueHandle handle) => _value == handle._value; - public ConstantReferenceValue GetConstantReferenceValue(MetadataReader reader) - { - return reader.GetConstantReferenceValue(this); - } // GetConstantReferenceValue + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantReferenceValueHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantReferenceValue GetConstantReferenceValue(MetadataReader reader) + => new ConstantReferenceValue(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -2299,70 +1596,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantReferenceValueHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantSByteArray + public readonly partial struct ConstantSByteArray { - internal MetadataReader _reader; - internal ConstantSByteArrayHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantSByteArrayHandle _handle; - public ConstantSByteArrayHandle Handle + internal ConstantSByteArray(MetadataReader reader, ConstantSByteArrayHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public SByteCollection Value - { - get - { - return _value; - } - } // Value + public ConstantSByteArrayHandle Handle => _handle; - internal SByteCollection _value; + public SByteCollection Value => _value; + private readonly SByteCollection _value; } // ConstantSByteArray #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantSByteArrayHandle + public readonly partial struct ConstantSByteArrayHandle { - public override bool Equals(object obj) - { - if (obj is ConstantSByteArrayHandle) - return _value == ((ConstantSByteArrayHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantSByteArrayHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantSByteArrayHandle(Handle handle) : this(handle._value) { @@ -2376,33 +1641,31 @@ internal ConstantSByteArrayHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantSByteArrayHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantSByteArrayHandle) + return _value == ((ConstantSByteArrayHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantSByteArrayHandle handle) => _value == handle._value; - public ConstantSByteArray GetConstantSByteArray(MetadataReader reader) - { - return reader.GetConstantSByteArray(this); - } // GetConstantSByteArray + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantSByteArrayHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantSByteArray GetConstantSByteArray(MetadataReader reader) + => new ConstantSByteArray(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -2411,70 +1674,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantSByteArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantSByteValue + public readonly partial struct ConstantSByteValue { - internal MetadataReader _reader; - internal ConstantSByteValueHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantSByteValueHandle _handle; - public ConstantSByteValueHandle Handle + internal ConstantSByteValue(MetadataReader reader, ConstantSByteValueHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public sbyte Value - { - get - { - return _value; - } - } // Value + public ConstantSByteValueHandle Handle => _handle; - internal sbyte _value; + public sbyte Value => _value; + private readonly sbyte _value; } // ConstantSByteValue #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantSByteValueHandle + public readonly partial struct ConstantSByteValueHandle { - public override bool Equals(object obj) - { - if (obj is ConstantSByteValueHandle) - return _value == ((ConstantSByteValueHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantSByteValueHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantSByteValueHandle(Handle handle) : this(handle._value) { @@ -2488,33 +1719,31 @@ internal ConstantSByteValueHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantSByteValueHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantSByteValueHandle) + return _value == ((ConstantSByteValueHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantSByteValueHandle handle) => _value == handle._value; - public ConstantSByteValue GetConstantSByteValue(MetadataReader reader) - { - return reader.GetConstantSByteValue(this); - } // GetConstantSByteValue + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantSByteValueHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantSByteValue GetConstantSByteValue(MetadataReader reader) + => new ConstantSByteValue(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -2523,70 +1752,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantSByteValueHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantSingleArray + public readonly partial struct ConstantSingleArray { - internal MetadataReader _reader; - internal ConstantSingleArrayHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantSingleArrayHandle _handle; - public ConstantSingleArrayHandle Handle + internal ConstantSingleArray(MetadataReader reader, ConstantSingleArrayHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public SingleCollection Value - { - get - { - return _value; - } - } // Value + public ConstantSingleArrayHandle Handle => _handle; - internal SingleCollection _value; + public SingleCollection Value => _value; + private readonly SingleCollection _value; } // ConstantSingleArray #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantSingleArrayHandle + public readonly partial struct ConstantSingleArrayHandle { - public override bool Equals(object obj) - { - if (obj is ConstantSingleArrayHandle) - return _value == ((ConstantSingleArrayHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantSingleArrayHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantSingleArrayHandle(Handle handle) : this(handle._value) { @@ -2600,33 +1797,31 @@ internal ConstantSingleArrayHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantSingleArrayHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantSingleArrayHandle) + return _value == ((ConstantSingleArrayHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantSingleArrayHandle handle) => _value == handle._value; - public ConstantSingleArray GetConstantSingleArray(MetadataReader reader) - { - return reader.GetConstantSingleArray(this); - } // GetConstantSingleArray + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantSingleArrayHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantSingleArray GetConstantSingleArray(MetadataReader reader) + => new ConstantSingleArray(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -2635,44 +1830,51 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantSingleArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantSingleValue + public readonly partial struct ConstantSingleValue { - internal MetadataReader _reader; - internal ConstantSingleValueHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantSingleValueHandle _handle; - public ConstantSingleValueHandle Handle + internal ConstantSingleValue(MetadataReader reader, ConstantSingleValueHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public float Value - { - get - { - return _value; - } - } // Value + public ConstantSingleValueHandle Handle => _handle; - internal float _value; + public float Value => _value; + private readonly float _value; } // ConstantSingleValue #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantSingleValueHandle + public readonly partial struct ConstantSingleValueHandle { + internal readonly int _value; + + internal ConstantSingleValueHandle(Handle handle) : this(handle._value) + { + } + + internal ConstantSingleValueHandle(int value) + { + HandleType hType = (HandleType)(value >> 24); + Debug.Assert(hType == 0 || hType == HandleType.ConstantSingleValue || hType == HandleType.Null); + _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantSingleValue) << 24); + _Validate(); + } + public override bool Equals(object obj) { if (obj is ConstantSingleValueHandle) @@ -2683,62 +1885,21 @@ public override bool Equals(object obj) return false; } // Equals - public bool Equals(ConstantSingleValueHandle handle) - { - return _value == handle._value; - } // Equals + public bool Equals(ConstantSingleValueHandle handle) => _value == handle._value; - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals + public bool Equals(Handle handle) => _value == handle._value; - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode + public override int GetHashCode() => (int)_value; - internal int _value; + public static implicit operator Handle(ConstantSingleValueHandle handle) + => new Handle(handle._value); - internal ConstantSingleValueHandle(Handle handle) : this(handle._value) - { - } - - internal ConstantSingleValueHandle(int value) - { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantSingleValue || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantSingleValue) << 24); - _Validate(); - } - - public static implicit operator Handle(ConstantSingleValueHandle handle) - { - return new Handle(handle._value); - } // Handle - - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + internal int Offset => (_value & 0x00FFFFFF); public ConstantSingleValue GetConstantSingleValue(MetadataReader reader) - { - return reader.GetConstantSingleValue(this); - } // GetConstantSingleValue - - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + => new ConstantSingleValue(reader, this); - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -2747,71 +1908,39 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantSingleValueHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantStringArray + public readonly partial struct ConstantStringArray { - internal MetadataReader _reader; - internal ConstantStringArrayHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantStringArrayHandle _handle; - public ConstantStringArrayHandle Handle + internal ConstantStringArray(MetadataReader reader, ConstantStringArrayHandle handle) { - get - { - return _handle; - } - } // Handle - /// One of: ConstantStringValue, ConstantReferenceValue + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public HandleCollection Value - { - get - { - return _value; - } - } // Value + public ConstantStringArrayHandle Handle => _handle; - internal HandleCollection _value; + /// One of: ConstantStringValue, ConstantReferenceValue + public HandleCollection Value => _value; + private readonly HandleCollection _value; } // ConstantStringArray #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantStringArrayHandle + public readonly partial struct ConstantStringArrayHandle { - public override bool Equals(object obj) - { - if (obj is ConstantStringArrayHandle) - return _value == ((ConstantStringArrayHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantStringArrayHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantStringArrayHandle(Handle handle) : this(handle._value) { @@ -2825,33 +1954,31 @@ internal ConstantStringArrayHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantStringArrayHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantStringArrayHandle) + return _value == ((ConstantStringArrayHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantStringArrayHandle handle) => _value == handle._value; - public ConstantStringArray GetConstantStringArray(MetadataReader reader) - { - return reader.GetConstantStringArray(this); - } // GetConstantStringArray + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantStringArrayHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantStringArray GetConstantStringArray(MetadataReader reader) + => new ConstantStringArray(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -2860,70 +1987,40 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantStringArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantStringValue + public readonly partial struct ConstantStringValue { - internal MetadataReader _reader; - internal ConstantStringValueHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantStringValueHandle _handle; - public ConstantStringValueHandle Handle + internal ConstantStringValue(MetadataReader reader, ConstantStringValueHandle handle) { - get - { - return _handle; - } - } // Handle + if (handle.IsNil) + return; + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public string Value - { - get - { - return _value; - } - } // Value + public ConstantStringValueHandle Handle => _handle; - internal string _value; + public string Value => _value; + private readonly string _value; } // ConstantStringValue #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantStringValueHandle + public readonly partial struct ConstantStringValueHandle { - public override bool Equals(object obj) - { - if (obj is ConstantStringValueHandle) - return _value == ((ConstantStringValueHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantStringValueHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantStringValueHandle(Handle handle) : this(handle._value) { @@ -2937,33 +2034,31 @@ internal ConstantStringValueHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantStringValueHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantStringValueHandle) + return _value == ((ConstantStringValueHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantStringValueHandle handle) => _value == handle._value; - public ConstantStringValue GetConstantStringValue(MetadataReader reader) - { - return reader.GetConstantStringValue(this); - } // GetConstantStringValue + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantStringValueHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantStringValue GetConstantStringValue(MetadataReader reader) + => new ConstantStringValue(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -2972,70 +2067,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantStringValueHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantUInt16Array + public readonly partial struct ConstantUInt16Array { - internal MetadataReader _reader; - internal ConstantUInt16ArrayHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantUInt16ArrayHandle _handle; - public ConstantUInt16ArrayHandle Handle + internal ConstantUInt16Array(MetadataReader reader, ConstantUInt16ArrayHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public UInt16Collection Value - { - get - { - return _value; - } - } // Value + public ConstantUInt16ArrayHandle Handle => _handle; - internal UInt16Collection _value; + public UInt16Collection Value => _value; + private readonly UInt16Collection _value; } // ConstantUInt16Array #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantUInt16ArrayHandle + public readonly partial struct ConstantUInt16ArrayHandle { - public override bool Equals(object obj) - { - if (obj is ConstantUInt16ArrayHandle) - return _value == ((ConstantUInt16ArrayHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantUInt16ArrayHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantUInt16ArrayHandle(Handle handle) : this(handle._value) { @@ -3049,33 +2112,31 @@ internal ConstantUInt16ArrayHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantUInt16ArrayHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantUInt16ArrayHandle) + return _value == ((ConstantUInt16ArrayHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantUInt16ArrayHandle handle) => _value == handle._value; - public ConstantUInt16Array GetConstantUInt16Array(MetadataReader reader) - { - return reader.GetConstantUInt16Array(this); - } // GetConstantUInt16Array + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantUInt16ArrayHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantUInt16Array GetConstantUInt16Array(MetadataReader reader) + => new ConstantUInt16Array(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -3084,70 +2145,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantUInt16ArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantUInt16Value + public readonly partial struct ConstantUInt16Value { - internal MetadataReader _reader; - internal ConstantUInt16ValueHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantUInt16ValueHandle _handle; - public ConstantUInt16ValueHandle Handle + internal ConstantUInt16Value(MetadataReader reader, ConstantUInt16ValueHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public ushort Value - { - get - { - return _value; - } - } // Value + public ConstantUInt16ValueHandle Handle => _handle; - internal ushort _value; + public ushort Value => _value; + private readonly ushort _value; } // ConstantUInt16Value #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantUInt16ValueHandle + public readonly partial struct ConstantUInt16ValueHandle { - public override bool Equals(object obj) - { - if (obj is ConstantUInt16ValueHandle) - return _value == ((ConstantUInt16ValueHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantUInt16ValueHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantUInt16ValueHandle(Handle handle) : this(handle._value) { @@ -3161,33 +2190,31 @@ internal ConstantUInt16ValueHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantUInt16ValueHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantUInt16ValueHandle) + return _value == ((ConstantUInt16ValueHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantUInt16ValueHandle handle) => _value == handle._value; - public ConstantUInt16Value GetConstantUInt16Value(MetadataReader reader) - { - return reader.GetConstantUInt16Value(this); - } // GetConstantUInt16Value + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantUInt16ValueHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantUInt16Value GetConstantUInt16Value(MetadataReader reader) + => new ConstantUInt16Value(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -3196,44 +2223,51 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantUInt16ValueHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantUInt32Array + public readonly partial struct ConstantUInt32Array { - internal MetadataReader _reader; - internal ConstantUInt32ArrayHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantUInt32ArrayHandle _handle; - public ConstantUInt32ArrayHandle Handle + internal ConstantUInt32Array(MetadataReader reader, ConstantUInt32ArrayHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public UInt32Collection Value - { - get - { - return _value; - } - } // Value + public ConstantUInt32ArrayHandle Handle => _handle; - internal UInt32Collection _value; + public UInt32Collection Value => _value; + private readonly UInt32Collection _value; } // ConstantUInt32Array #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantUInt32ArrayHandle + public readonly partial struct ConstantUInt32ArrayHandle { + internal readonly int _value; + + internal ConstantUInt32ArrayHandle(Handle handle) : this(handle._value) + { + } + + internal ConstantUInt32ArrayHandle(int value) + { + HandleType hType = (HandleType)(value >> 24); + Debug.Assert(hType == 0 || hType == HandleType.ConstantUInt32Array || hType == HandleType.Null); + _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantUInt32Array) << 24); + _Validate(); + } + public override bool Equals(object obj) { if (obj is ConstantUInt32ArrayHandle) @@ -3244,62 +2278,21 @@ public override bool Equals(object obj) return false; } // Equals - public bool Equals(ConstantUInt32ArrayHandle handle) - { - return _value == handle._value; - } // Equals + public bool Equals(ConstantUInt32ArrayHandle handle) => _value == handle._value; - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals + public bool Equals(Handle handle) => _value == handle._value; - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode + public override int GetHashCode() => (int)_value; - internal int _value; + public static implicit operator Handle(ConstantUInt32ArrayHandle handle) + => new Handle(handle._value); - internal ConstantUInt32ArrayHandle(Handle handle) : this(handle._value) - { - } - - internal ConstantUInt32ArrayHandle(int value) - { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantUInt32Array || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantUInt32Array) << 24); - _Validate(); - } - - public static implicit operator Handle(ConstantUInt32ArrayHandle handle) - { - return new Handle(handle._value); - } // Handle - - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + internal int Offset => (_value & 0x00FFFFFF); public ConstantUInt32Array GetConstantUInt32Array(MetadataReader reader) - { - return reader.GetConstantUInt32Array(this); - } // GetConstantUInt32Array - - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + => new ConstantUInt32Array(reader, this); - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -3308,70 +2301,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantUInt32ArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantUInt32Value + public readonly partial struct ConstantUInt32Value { - internal MetadataReader _reader; - internal ConstantUInt32ValueHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantUInt32ValueHandle _handle; - public ConstantUInt32ValueHandle Handle + internal ConstantUInt32Value(MetadataReader reader, ConstantUInt32ValueHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public uint Value - { - get - { - return _value; - } - } // Value + public ConstantUInt32ValueHandle Handle => _handle; - internal uint _value; + public uint Value => _value; + private readonly uint _value; } // ConstantUInt32Value #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantUInt32ValueHandle + public readonly partial struct ConstantUInt32ValueHandle { - public override bool Equals(object obj) - { - if (obj is ConstantUInt32ValueHandle) - return _value == ((ConstantUInt32ValueHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantUInt32ValueHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantUInt32ValueHandle(Handle handle) : this(handle._value) { @@ -3385,33 +2346,31 @@ internal ConstantUInt32ValueHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantUInt32ValueHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantUInt32ValueHandle) + return _value == ((ConstantUInt32ValueHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantUInt32ValueHandle handle) => _value == handle._value; - public ConstantUInt32Value GetConstantUInt32Value(MetadataReader reader) - { - return reader.GetConstantUInt32Value(this); - } // GetConstantUInt32Value + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantUInt32ValueHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantUInt32Value GetConstantUInt32Value(MetadataReader reader) + => new ConstantUInt32Value(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -3420,70 +2379,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantUInt32ValueHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantUInt64Array + public readonly partial struct ConstantUInt64Array { - internal MetadataReader _reader; - internal ConstantUInt64ArrayHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantUInt64ArrayHandle _handle; - public ConstantUInt64ArrayHandle Handle + internal ConstantUInt64Array(MetadataReader reader, ConstantUInt64ArrayHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public UInt64Collection Value - { - get - { - return _value; - } - } // Value + public ConstantUInt64ArrayHandle Handle => _handle; - internal UInt64Collection _value; + public UInt64Collection Value => _value; + private readonly UInt64Collection _value; } // ConstantUInt64Array #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantUInt64ArrayHandle + public readonly partial struct ConstantUInt64ArrayHandle { - public override bool Equals(object obj) - { - if (obj is ConstantUInt64ArrayHandle) - return _value == ((ConstantUInt64ArrayHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantUInt64ArrayHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantUInt64ArrayHandle(Handle handle) : this(handle._value) { @@ -3497,33 +2424,31 @@ internal ConstantUInt64ArrayHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantUInt64ArrayHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantUInt64ArrayHandle) + return _value == ((ConstantUInt64ArrayHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantUInt64ArrayHandle handle) => _value == handle._value; - public ConstantUInt64Array GetConstantUInt64Array(MetadataReader reader) - { - return reader.GetConstantUInt64Array(this); - } // GetConstantUInt64Array + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantUInt64ArrayHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantUInt64Array GetConstantUInt64Array(MetadataReader reader) + => new ConstantUInt64Array(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -3532,70 +2457,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantUInt64ArrayHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantUInt64Value + public readonly partial struct ConstantUInt64Value { - internal MetadataReader _reader; - internal ConstantUInt64ValueHandle _handle; + private readonly MetadataReader _reader; + private readonly ConstantUInt64ValueHandle _handle; - public ConstantUInt64ValueHandle Handle + internal ConstantUInt64Value(MetadataReader reader, ConstantUInt64ValueHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _value); + } - public ulong Value - { - get - { - return _value; - } - } // Value + public ConstantUInt64ValueHandle Handle => _handle; - internal ulong _value; + public ulong Value => _value; + private readonly ulong _value; } // ConstantUInt64Value #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ConstantUInt64ValueHandle + public readonly partial struct ConstantUInt64ValueHandle { - public override bool Equals(object obj) - { - if (obj is ConstantUInt64ValueHandle) - return _value == ((ConstantUInt64ValueHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ConstantUInt64ValueHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ConstantUInt64ValueHandle(Handle handle) : this(handle._value) { @@ -3609,33 +2502,31 @@ internal ConstantUInt64ValueHandle(int value) _Validate(); } - public static implicit operator Handle(ConstantUInt64ValueHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ConstantUInt64ValueHandle) + return _value == ((ConstantUInt64ValueHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ConstantUInt64ValueHandle handle) => _value == handle._value; - public ConstantUInt64Value GetConstantUInt64Value(MetadataReader reader) - { - return reader.GetConstantUInt64Value(this); - } // GetConstantUInt64Value + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ConstantUInt64ValueHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ConstantUInt64Value GetConstantUInt64Value(MetadataReader reader) + => new ConstantUInt64Value(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -3644,92 +2535,48 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ConstantUInt64ValueHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct CustomAttribute + public readonly partial struct CustomAttribute { - internal MetadataReader _reader; - internal CustomAttributeHandle _handle; - - public CustomAttributeHandle Handle - { - get - { - return _handle; - } - } // Handle - /// One of: QualifiedMethod, MemberReference + private readonly MetadataReader _reader; + private readonly CustomAttributeHandle _handle; - public Handle Constructor + internal CustomAttribute(MetadataReader reader, CustomAttributeHandle handle) { - get - { - return _constructor; - } - } // Constructor - - internal Handle _constructor; - /// One of: TypeDefinition, TypeReference, TypeSpecification, ConstantBooleanArray, ConstantBooleanValue, ConstantByteArray, ConstantByteValue, ConstantCharArray, ConstantCharValue, ConstantDoubleArray, ConstantDoubleValue, ConstantEnumArray, ConstantHandleArray, ConstantInt16Array, ConstantInt16Value, ConstantInt32Array, ConstantInt32Value, ConstantInt64Array, ConstantInt64Value, ConstantReferenceValue, ConstantSByteArray, ConstantSByteValue, ConstantSingleArray, ConstantSingleValue, ConstantStringArray, ConstantStringValue, ConstantUInt16Array, ConstantUInt16Value, ConstantUInt32Array, ConstantUInt32Value, ConstantUInt64Array, ConstantUInt64Value + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _constructor); + offset = streamReader.Read(offset, out _fixedArguments); + offset = streamReader.Read(offset, out _namedArguments); + } - public HandleCollection FixedArguments - { - get - { - return _fixedArguments; - } - } // FixedArguments + public CustomAttributeHandle Handle => _handle; - internal HandleCollection _fixedArguments; + /// One of: QualifiedMethod, MemberReference + public Handle Constructor => _constructor; + private readonly Handle _constructor; - public NamedArgumentHandleCollection NamedArguments - { - get - { - return _namedArguments; - } - } // NamedArguments + /// One of: TypeDefinition, TypeReference, TypeSpecification, ConstantBooleanArray, ConstantBooleanValue, ConstantByteArray, ConstantByteValue, ConstantCharArray, ConstantCharValue, ConstantDoubleArray, ConstantDoubleValue, ConstantEnumArray, ConstantEnumValue, ConstantHandleArray, ConstantInt16Array, ConstantInt16Value, ConstantInt32Array, ConstantInt32Value, ConstantInt64Array, ConstantInt64Value, ConstantReferenceValue, ConstantSByteArray, ConstantSByteValue, ConstantSingleArray, ConstantSingleValue, ConstantStringArray, ConstantStringValue, ConstantUInt16Array, ConstantUInt16Value, ConstantUInt32Array, ConstantUInt32Value, ConstantUInt64Array, ConstantUInt64Value + public HandleCollection FixedArguments => _fixedArguments; + private readonly HandleCollection _fixedArguments; - internal NamedArgumentHandleCollection _namedArguments; + public NamedArgumentHandleCollection NamedArguments => _namedArguments; + private readonly NamedArgumentHandleCollection _namedArguments; } // CustomAttribute #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct CustomAttributeHandle + public readonly partial struct CustomAttributeHandle { - public override bool Equals(object obj) - { - if (obj is CustomAttributeHandle) - return _value == ((CustomAttributeHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(CustomAttributeHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal CustomAttributeHandle(Handle handle) : this(handle._value) { @@ -3743,33 +2590,31 @@ internal CustomAttributeHandle(int value) _Validate(); } - public static implicit operator Handle(CustomAttributeHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is CustomAttributeHandle) + return _value == ((CustomAttributeHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(CustomAttributeHandle handle) => _value == handle._value; - public CustomAttribute GetCustomAttribute(MetadataReader reader) - { - return reader.GetCustomAttribute(this); - } // GetCustomAttribute + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(CustomAttributeHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public CustomAttribute GetCustomAttribute(MetadataReader reader) + => new CustomAttribute(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -3778,111 +2623,55 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // CustomAttributeHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct Event + public readonly partial struct Event { - internal MetadataReader _reader; - internal EventHandle _handle; + private readonly MetadataReader _reader; + private readonly EventHandle _handle; - public EventHandle Handle + internal Event(MetadataReader reader, EventHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _flags); + offset = streamReader.Read(offset, out _name); + offset = streamReader.Read(offset, out _type); + offset = streamReader.Read(offset, out _methodSemantics); + offset = streamReader.Read(offset, out _customAttributes); + } - public EventAttributes Flags - { - get - { - return _flags; - } - } // Flags + public EventHandle Handle => _handle; - internal EventAttributes _flags; + public EventAttributes Flags => _flags; + private readonly EventAttributes _flags; - public ConstantStringValueHandle Name - { - get - { - return _name; - } - } // Name + public ConstantStringValueHandle Name => _name; + private readonly ConstantStringValueHandle _name; - internal ConstantStringValueHandle _name; /// One of: TypeDefinition, TypeReference, TypeSpecification + public Handle Type => _type; + private readonly Handle _type; - public Handle Type - { - get - { - return _type; - } - } // Type + public MethodSemanticsHandleCollection MethodSemantics => _methodSemantics; + private readonly MethodSemanticsHandleCollection _methodSemantics; - internal Handle _type; - - public MethodSemanticsHandleCollection MethodSemantics - { - get - { - return _methodSemantics; - } - } // MethodSemantics - - internal MethodSemanticsHandleCollection _methodSemantics; - - public CustomAttributeHandleCollection CustomAttributes - { - get - { - return _customAttributes; - } - } // CustomAttributes - - internal CustomAttributeHandleCollection _customAttributes; - } // Event + public CustomAttributeHandleCollection CustomAttributes => _customAttributes; + private readonly CustomAttributeHandleCollection _customAttributes; + } // Event #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct EventHandle + public readonly partial struct EventHandle { - public override bool Equals(object obj) - { - if (obj is EventHandle) - return _value == ((EventHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(EventHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal EventHandle(Handle handle) : this(handle._value) { @@ -3896,33 +2685,31 @@ internal EventHandle(int value) _Validate(); } - public static implicit operator Handle(EventHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is EventHandle) + return _value == ((EventHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(EventHandle handle) => _value == handle._value; - public Event GetEvent(MetadataReader reader) - { - return reader.GetEvent(this); - } // GetEvent + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(EventHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public Event GetEvent(MetadataReader reader) + => new Event(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -3931,121 +2718,59 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // EventHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct Field + public readonly partial struct Field { - internal MetadataReader _reader; - internal FieldHandle _handle; - - public FieldHandle Handle - { - get - { - return _handle; - } - } // Handle - - public FieldAttributes Flags - { - get - { - return _flags; - } - } // Flags + private readonly MetadataReader _reader; + private readonly FieldHandle _handle; - internal FieldAttributes _flags; - - public ConstantStringValueHandle Name - { - get - { - return _name; - } - } // Name - - internal ConstantStringValueHandle _name; - - public FieldSignatureHandle Signature + internal Field(MetadataReader reader, FieldHandle handle) { - get - { - return _signature; - } - } // Signature + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _flags); + offset = streamReader.Read(offset, out _name); + offset = streamReader.Read(offset, out _signature); + offset = streamReader.Read(offset, out _defaultValue); + offset = streamReader.Read(offset, out _offset); + offset = streamReader.Read(offset, out _customAttributes); + } - internal FieldSignatureHandle _signature; - /// One of: TypeDefinition, TypeReference, TypeSpecification, ConstantBooleanArray, ConstantBooleanValue, ConstantByteArray, ConstantByteValue, ConstantCharArray, ConstantCharValue, ConstantDoubleArray, ConstantDoubleValue, ConstantEnumArray, ConstantHandleArray, ConstantInt16Array, ConstantInt16Value, ConstantInt32Array, ConstantInt32Value, ConstantInt64Array, ConstantInt64Value, ConstantReferenceValue, ConstantSByteArray, ConstantSByteValue, ConstantSingleArray, ConstantSingleValue, ConstantStringArray, ConstantStringValue, ConstantUInt16Array, ConstantUInt16Value, ConstantUInt32Array, ConstantUInt32Value, ConstantUInt64Array, ConstantUInt64Value + public FieldHandle Handle => _handle; - public Handle DefaultValue - { - get - { - return _defaultValue; - } - } // DefaultValue + public FieldAttributes Flags => _flags; + private readonly FieldAttributes _flags; - internal Handle _defaultValue; + public ConstantStringValueHandle Name => _name; + private readonly ConstantStringValueHandle _name; - public uint Offset - { - get - { - return _offset; - } - } // Offset + public FieldSignatureHandle Signature => _signature; + private readonly FieldSignatureHandle _signature; - internal uint _offset; + /// One of: TypeDefinition, TypeReference, TypeSpecification, ConstantBooleanArray, ConstantBooleanValue, ConstantByteArray, ConstantByteValue, ConstantCharArray, ConstantCharValue, ConstantDoubleArray, ConstantDoubleValue, ConstantEnumArray, ConstantEnumValue, ConstantHandleArray, ConstantInt16Array, ConstantInt16Value, ConstantInt32Array, ConstantInt32Value, ConstantInt64Array, ConstantInt64Value, ConstantReferenceValue, ConstantSByteArray, ConstantSByteValue, ConstantSingleArray, ConstantSingleValue, ConstantStringArray, ConstantStringValue, ConstantUInt16Array, ConstantUInt16Value, ConstantUInt32Array, ConstantUInt32Value, ConstantUInt64Array, ConstantUInt64Value + public Handle DefaultValue => _defaultValue; + private readonly Handle _defaultValue; - public CustomAttributeHandleCollection CustomAttributes - { - get - { - return _customAttributes; - } - } // CustomAttributes + public uint Offset => _offset; + private readonly uint _offset; - internal CustomAttributeHandleCollection _customAttributes; + public CustomAttributeHandleCollection CustomAttributes => _customAttributes; + private readonly CustomAttributeHandleCollection _customAttributes; } // Field #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct FieldHandle + public readonly partial struct FieldHandle { - public override bool Equals(object obj) - { - if (obj is FieldHandle) - return _value == ((FieldHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(FieldHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal FieldHandle(Handle handle) : this(handle._value) { @@ -4059,33 +2784,31 @@ internal FieldHandle(int value) _Validate(); } - public static implicit operator Handle(FieldHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is FieldHandle) + return _value == ((FieldHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(FieldHandle handle) => _value == handle._value; - public Field GetField(MetadataReader reader) - { - return reader.GetField(this); - } // GetField + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(FieldHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public Field GetField(MetadataReader reader) + => new Field(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -4094,71 +2817,39 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // FieldHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct FieldSignature + public readonly partial struct FieldSignature { - internal MetadataReader _reader; - internal FieldSignatureHandle _handle; + private readonly MetadataReader _reader; + private readonly FieldSignatureHandle _handle; - public FieldSignatureHandle Handle + internal FieldSignature(MetadataReader reader, FieldSignatureHandle handle) { - get - { - return _handle; - } - } // Handle - /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _type); + } - public Handle Type - { - get - { - return _type; - } - } // Type + public FieldSignatureHandle Handle => _handle; - internal Handle _type; + /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + public Handle Type => _type; + private readonly Handle _type; } // FieldSignature #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct FieldSignatureHandle + public readonly partial struct FieldSignatureHandle { - public override bool Equals(object obj) - { - if (obj is FieldSignatureHandle) - return _value == ((FieldSignatureHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(FieldSignatureHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal FieldSignatureHandle(Handle handle) : this(handle._value) { @@ -4172,33 +2863,31 @@ internal FieldSignatureHandle(int value) _Validate(); } - public static implicit operator Handle(FieldSignatureHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is FieldSignatureHandle) + return _value == ((FieldSignatureHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(FieldSignatureHandle handle) => _value == handle._value; - public FieldSignature GetFieldSignature(MetadataReader reader) - { - return reader.GetFieldSignature(this); - } // GetFieldSignature + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(FieldSignatureHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public FieldSignature GetFieldSignature(MetadataReader reader) + => new FieldSignature(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -4207,70 +2896,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // FieldSignatureHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct FunctionPointerSignature + public readonly partial struct FunctionPointerSignature { - internal MetadataReader _reader; - internal FunctionPointerSignatureHandle _handle; + private readonly MetadataReader _reader; + private readonly FunctionPointerSignatureHandle _handle; - public FunctionPointerSignatureHandle Handle + internal FunctionPointerSignature(MetadataReader reader, FunctionPointerSignatureHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _signature); + } - public MethodSignatureHandle Signature - { - get - { - return _signature; - } - } // Signature + public FunctionPointerSignatureHandle Handle => _handle; - internal MethodSignatureHandle _signature; + public MethodSignatureHandle Signature => _signature; + private readonly MethodSignatureHandle _signature; } // FunctionPointerSignature #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct FunctionPointerSignatureHandle + public readonly partial struct FunctionPointerSignatureHandle { - public override bool Equals(object obj) - { - if (obj is FunctionPointerSignatureHandle) - return _value == ((FunctionPointerSignatureHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(FunctionPointerSignatureHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal FunctionPointerSignatureHandle(Handle handle) : this(handle._value) { @@ -4284,33 +2941,31 @@ internal FunctionPointerSignatureHandle(int value) _Validate(); } - public static implicit operator Handle(FunctionPointerSignatureHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is FunctionPointerSignatureHandle) + return _value == ((FunctionPointerSignatureHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(FunctionPointerSignatureHandle handle) => _value == handle._value; - public FunctionPointerSignature GetFunctionPointerSignature(MetadataReader reader) - { - return reader.GetFunctionPointerSignature(this); - } // GetFunctionPointerSignature + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(FunctionPointerSignatureHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public FunctionPointerSignature GetFunctionPointerSignature(MetadataReader reader) + => new FunctionPointerSignature(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -4319,121 +2974,59 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // FunctionPointerSignatureHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct GenericParameter + public readonly partial struct GenericParameter { - internal MetadataReader _reader; - internal GenericParameterHandle _handle; + private readonly MetadataReader _reader; + private readonly GenericParameterHandle _handle; - public GenericParameterHandle Handle + internal GenericParameter(MetadataReader reader, GenericParameterHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _number); + offset = streamReader.Read(offset, out _flags); + offset = streamReader.Read(offset, out _kind); + offset = streamReader.Read(offset, out _name); + offset = streamReader.Read(offset, out _constraints); + offset = streamReader.Read(offset, out _customAttributes); + } - public ushort Number - { - get - { - return _number; - } - } // Number + public GenericParameterHandle Handle => _handle; - internal ushort _number; + public ushort Number => _number; + private readonly ushort _number; - public GenericParameterAttributes Flags - { - get - { - return _flags; - } - } // Flags + public GenericParameterAttributes Flags => _flags; + private readonly GenericParameterAttributes _flags; - internal GenericParameterAttributes _flags; + public GenericParameterKind Kind => _kind; + private readonly GenericParameterKind _kind; - public GenericParameterKind Kind - { - get - { - return _kind; - } - } // Kind + public ConstantStringValueHandle Name => _name; + private readonly ConstantStringValueHandle _name; - internal GenericParameterKind _kind; + /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + public HandleCollection Constraints => _constraints; + private readonly HandleCollection _constraints; - public ConstantStringValueHandle Name - { - get - { - return _name; - } - } // Name - - internal ConstantStringValueHandle _name; - /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType - - public HandleCollection Constraints - { - get - { - return _constraints; - } - } // Constraints - - internal HandleCollection _constraints; - - public CustomAttributeHandleCollection CustomAttributes - { - get - { - return _customAttributes; - } - } // CustomAttributes - - internal CustomAttributeHandleCollection _customAttributes; + public CustomAttributeHandleCollection CustomAttributes => _customAttributes; + private readonly CustomAttributeHandleCollection _customAttributes; } // GenericParameter #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct GenericParameterHandle + public readonly partial struct GenericParameterHandle { - public override bool Equals(object obj) - { - if (obj is GenericParameterHandle) - return _value == ((GenericParameterHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(GenericParameterHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal GenericParameterHandle(Handle handle) : this(handle._value) { @@ -4447,33 +3040,31 @@ internal GenericParameterHandle(int value) _Validate(); } - public static implicit operator Handle(GenericParameterHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is GenericParameterHandle) + return _value == ((GenericParameterHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(GenericParameterHandle handle) => _value == handle._value; - public GenericParameter GetGenericParameter(MetadataReader reader) - { - return reader.GetGenericParameter(this); - } // GetGenericParameter + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(GenericParameterHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public GenericParameter GetGenericParameter(MetadataReader reader) + => new GenericParameter(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -4482,92 +3073,48 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // GenericParameterHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct MemberReference + public readonly partial struct MemberReference { - internal MetadataReader _reader; - internal MemberReferenceHandle _handle; + private readonly MetadataReader _reader; + private readonly MemberReferenceHandle _handle; - public MemberReferenceHandle Handle + internal MemberReference(MetadataReader reader, MemberReferenceHandle handle) { - get - { - return _handle; - } - } // Handle - /// One of: TypeDefinition, TypeReference, TypeSpecification + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _parent); + offset = streamReader.Read(offset, out _name); + offset = streamReader.Read(offset, out _signature); + } - public Handle Parent - { - get - { - return _parent; - } - } // Parent + public MemberReferenceHandle Handle => _handle; - internal Handle _parent; + /// One of: TypeDefinition, TypeReference, TypeSpecification + public Handle Parent => _parent; + private readonly Handle _parent; - public ConstantStringValueHandle Name - { - get - { - return _name; - } - } // Name + public ConstantStringValueHandle Name => _name; + private readonly ConstantStringValueHandle _name; - internal ConstantStringValueHandle _name; /// One of: MethodSignature, FieldSignature - - public Handle Signature - { - get - { - return _signature; - } - } // Signature - - internal Handle _signature; + public Handle Signature => _signature; + private readonly Handle _signature; } // MemberReference #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct MemberReferenceHandle + public readonly partial struct MemberReferenceHandle { - public override bool Equals(object obj) - { - if (obj is MemberReferenceHandle) - return _value == ((MemberReferenceHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(MemberReferenceHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal MemberReferenceHandle(Handle handle) : this(handle._value) { @@ -4581,33 +3128,31 @@ internal MemberReferenceHandle(int value) _Validate(); } - public static implicit operator Handle(MemberReferenceHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is MemberReferenceHandle) + return _value == ((MemberReferenceHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(MemberReferenceHandle handle) => _value == handle._value; - public MemberReference GetMemberReference(MetadataReader reader) - { - return reader.GetMemberReference(this); - } // GetMemberReference + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(MemberReferenceHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public MemberReference GetMemberReference(MetadataReader reader) + => new MemberReference(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -4616,130 +3161,62 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // MemberReferenceHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct Method + public readonly partial struct Method { - internal MetadataReader _reader; - internal MethodHandle _handle; - - public MethodHandle Handle - { - get - { - return _handle; - } - } // Handle - - public MethodAttributes Flags - { - get - { - return _flags; - } - } // Flags - - internal MethodAttributes _flags; - - public MethodImplAttributes ImplFlags - { - get - { - return _implFlags; - } - } // ImplFlags - - internal MethodImplAttributes _implFlags; + private readonly MetadataReader _reader; + private readonly MethodHandle _handle; - public ConstantStringValueHandle Name + internal Method(MetadataReader reader, MethodHandle handle) { - get - { - return _name; - } - } // Name - - internal ConstantStringValueHandle _name; + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _flags); + offset = streamReader.Read(offset, out _implFlags); + offset = streamReader.Read(offset, out _name); + offset = streamReader.Read(offset, out _signature); + offset = streamReader.Read(offset, out _parameters); + offset = streamReader.Read(offset, out _genericParameters); + offset = streamReader.Read(offset, out _customAttributes); + } - public MethodSignatureHandle Signature - { - get - { - return _signature; - } - } // Signature + public MethodHandle Handle => _handle; - internal MethodSignatureHandle _signature; + public MethodAttributes Flags => _flags; + private readonly MethodAttributes _flags; - public ParameterHandleCollection Parameters - { - get - { - return _parameters; - } - } // Parameters + public MethodImplAttributes ImplFlags => _implFlags; + private readonly MethodImplAttributes _implFlags; - internal ParameterHandleCollection _parameters; + public ConstantStringValueHandle Name => _name; + private readonly ConstantStringValueHandle _name; - public GenericParameterHandleCollection GenericParameters - { - get - { - return _genericParameters; - } - } // GenericParameters + public MethodSignatureHandle Signature => _signature; + private readonly MethodSignatureHandle _signature; - internal GenericParameterHandleCollection _genericParameters; + public ParameterHandleCollection Parameters => _parameters; + private readonly ParameterHandleCollection _parameters; - public CustomAttributeHandleCollection CustomAttributes - { - get - { - return _customAttributes; - } - } // CustomAttributes + public GenericParameterHandleCollection GenericParameters => _genericParameters; + private readonly GenericParameterHandleCollection _genericParameters; - internal CustomAttributeHandleCollection _customAttributes; + public CustomAttributeHandleCollection CustomAttributes => _customAttributes; + private readonly CustomAttributeHandleCollection _customAttributes; } // Method #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct MethodHandle + public readonly partial struct MethodHandle { - public override bool Equals(object obj) - { - if (obj is MethodHandle) - return _value == ((MethodHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(MethodHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal MethodHandle(Handle handle) : this(handle._value) { @@ -4753,33 +3230,31 @@ internal MethodHandle(int value) _Validate(); } - public static implicit operator Handle(MethodHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is MethodHandle) + return _value == ((MethodHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(MethodHandle handle) => _value == handle._value; - public Method GetMethod(MetadataReader reader) - { - return reader.GetMethod(this); - } // GetMethod + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(MethodHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public Method GetMethod(MetadataReader reader) + => new Method(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -4788,82 +3263,44 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // MethodHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct MethodInstantiation + public readonly partial struct MethodInstantiation { - internal MetadataReader _reader; - internal MethodInstantiationHandle _handle; + private readonly MetadataReader _reader; + private readonly MethodInstantiationHandle _handle; - public MethodInstantiationHandle Handle + internal MethodInstantiation(MetadataReader reader, MethodInstantiationHandle handle) { - get - { - return _handle; - } - } // Handle - /// One of: QualifiedMethod, MemberReference - - public Handle Method - { - get - { - return _method; - } - } // Method + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _method); + offset = streamReader.Read(offset, out _genericTypeArguments); + } - internal Handle _method; - /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + public MethodInstantiationHandle Handle => _handle; - public HandleCollection GenericTypeArguments - { - get - { - return _genericTypeArguments; - } - } // GenericTypeArguments + /// One of: QualifiedMethod, MemberReference + public Handle Method => _method; + private readonly Handle _method; - internal HandleCollection _genericTypeArguments; + /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + public HandleCollection GenericTypeArguments => _genericTypeArguments; + private readonly HandleCollection _genericTypeArguments; } // MethodInstantiation #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct MethodInstantiationHandle + public readonly partial struct MethodInstantiationHandle { - public override bool Equals(object obj) - { - if (obj is MethodInstantiationHandle) - return _value == ((MethodInstantiationHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(MethodInstantiationHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal MethodInstantiationHandle(Handle handle) : this(handle._value) { @@ -4877,115 +3314,75 @@ internal MethodInstantiationHandle(int value) _Validate(); } - public static implicit operator Handle(MethodInstantiationHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is MethodInstantiationHandle) + return _value == ((MethodInstantiationHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(MethodInstantiationHandle handle) => _value == handle._value; - public MethodInstantiation GetMethodInstantiation(MetadataReader reader) - { - return reader.GetMethodInstantiation(this); - } // GetMethodInstantiation + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(MethodInstantiationHandle handle) + => new Handle(handle._value); - [System.Diagnostics.Conditional("DEBUG")] + internal int Offset => (_value & 0x00FFFFFF); + + public MethodInstantiation GetMethodInstantiation(MetadataReader reader) + => new MethodInstantiation(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; + + [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.MethodInstantiation) throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // MethodInstantiationHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct MethodSemantics + public readonly partial struct MethodSemantics { - internal MetadataReader _reader; - internal MethodSemanticsHandle _handle; - - public MethodSemanticsHandle Handle - { - get - { - return _handle; - } - } // Handle + private readonly MetadataReader _reader; + private readonly MethodSemanticsHandle _handle; - public MethodSemanticsAttributes Attributes + internal MethodSemantics(MetadataReader reader, MethodSemanticsHandle handle) { - get - { - return _attributes; - } - } // Attributes + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _attributes); + offset = streamReader.Read(offset, out _method); + } - internal MethodSemanticsAttributes _attributes; + public MethodSemanticsHandle Handle => _handle; - public MethodHandle Method - { - get - { - return _method; - } - } // Method + public MethodSemanticsAttributes Attributes => _attributes; + private readonly MethodSemanticsAttributes _attributes; - internal MethodHandle _method; + public MethodHandle Method => _method; + private readonly MethodHandle _method; } // MethodSemantics #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct MethodSemanticsHandle + public readonly partial struct MethodSemanticsHandle { - public override bool Equals(object obj) - { - if (obj is MethodSemanticsHandle) - return _value == ((MethodSemanticsHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(MethodSemanticsHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal MethodSemanticsHandle(Handle handle) : this(handle._value) { @@ -4999,33 +3396,31 @@ internal MethodSemanticsHandle(int value) _Validate(); } - public static implicit operator Handle(MethodSemanticsHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is MethodSemanticsHandle) + return _value == ((MethodSemanticsHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(MethodSemanticsHandle handle) => _value == handle._value; - public MethodSemantics GetMethodSemantics(MetadataReader reader) - { - return reader.GetMethodSemantics(this); - } // GetMethodSemantics + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(MethodSemanticsHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public MethodSemantics GetMethodSemantics(MetadataReader reader) + => new MethodSemantics(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -5034,113 +3429,57 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // MethodSemanticsHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct MethodSignature + public readonly partial struct MethodSignature { - internal MetadataReader _reader; - internal MethodSignatureHandle _handle; + private readonly MetadataReader _reader; + private readonly MethodSignatureHandle _handle; - public MethodSignatureHandle Handle + internal MethodSignature(MetadataReader reader, MethodSignatureHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _callingConvention); + offset = streamReader.Read(offset, out _genericParameterCount); + offset = streamReader.Read(offset, out _returnType); + offset = streamReader.Read(offset, out _parameters); + offset = streamReader.Read(offset, out _varArgParameters); + } - public SignatureCallingConvention CallingConvention - { - get - { - return _callingConvention; - } - } // CallingConvention + public MethodSignatureHandle Handle => _handle; - internal SignatureCallingConvention _callingConvention; + public SignatureCallingConvention CallingConvention => _callingConvention; + private readonly SignatureCallingConvention _callingConvention; - public int GenericParameterCount - { - get - { - return _genericParameterCount; - } - } // GenericParameterCount + public int GenericParameterCount => _genericParameterCount; + private readonly int _genericParameterCount; - internal int _genericParameterCount; /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + public Handle ReturnType => _returnType; + private readonly Handle _returnType; - public Handle ReturnType - { - get - { - return _returnType; - } - } // ReturnType - - internal Handle _returnType; /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + public HandleCollection Parameters => _parameters; + private readonly HandleCollection _parameters; - public HandleCollection Parameters - { - get - { - return _parameters; - } - } // Parameters - - internal HandleCollection _parameters; /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType - - public HandleCollection VarArgParameters - { - get - { - return _varArgParameters; - } - } // VarArgParameters - - internal HandleCollection _varArgParameters; + public HandleCollection VarArgParameters => _varArgParameters; + private readonly HandleCollection _varArgParameters; } // MethodSignature #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct MethodSignatureHandle + public readonly partial struct MethodSignatureHandle { - public override bool Equals(object obj) - { - if (obj is MethodSignatureHandle) - return _value == ((MethodSignatureHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(MethodSignatureHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal MethodSignatureHandle(Handle handle) : this(handle._value) { @@ -5154,33 +3493,31 @@ internal MethodSignatureHandle(int value) _Validate(); } - public static implicit operator Handle(MethodSignatureHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is MethodSignatureHandle) + return _value == ((MethodSignatureHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(MethodSignatureHandle handle) => _value == handle._value; - public MethodSignature GetMethodSignature(MetadataReader reader) - { - return reader.GetMethodSignature(this); - } // GetMethodSignature + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(MethodSignatureHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public MethodSignature GetMethodSignature(MetadataReader reader) + => new MethodSignature(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -5189,70 +3526,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // MethodSignatureHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct MethodTypeVariableSignature + public readonly partial struct MethodTypeVariableSignature { - internal MetadataReader _reader; - internal MethodTypeVariableSignatureHandle _handle; + private readonly MetadataReader _reader; + private readonly MethodTypeVariableSignatureHandle _handle; - public MethodTypeVariableSignatureHandle Handle + internal MethodTypeVariableSignature(MetadataReader reader, MethodTypeVariableSignatureHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _number); + } - public int Number - { - get - { - return _number; - } - } // Number + public MethodTypeVariableSignatureHandle Handle => _handle; - internal int _number; + public int Number => _number; + private readonly int _number; } // MethodTypeVariableSignature #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct MethodTypeVariableSignatureHandle + public readonly partial struct MethodTypeVariableSignatureHandle { - public override bool Equals(object obj) - { - if (obj is MethodTypeVariableSignatureHandle) - return _value == ((MethodTypeVariableSignatureHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(MethodTypeVariableSignatureHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal MethodTypeVariableSignatureHandle(Handle handle) : this(handle._value) { @@ -5266,33 +3571,31 @@ internal MethodTypeVariableSignatureHandle(int value) _Validate(); } - public static implicit operator Handle(MethodTypeVariableSignatureHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is MethodTypeVariableSignatureHandle) + return _value == ((MethodTypeVariableSignatureHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(MethodTypeVariableSignatureHandle handle) => _value == handle._value; - public MethodTypeVariableSignature GetMethodTypeVariableSignature(MetadataReader reader) - { - return reader.GetMethodTypeVariableSignature(this); - } // GetMethodTypeVariableSignature + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(MethodTypeVariableSignatureHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public MethodTypeVariableSignature GetMethodTypeVariableSignature(MetadataReader reader) + => new MethodTypeVariableSignature(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -5301,92 +3604,48 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // MethodTypeVariableSignatureHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ModifiedType + public readonly partial struct ModifiedType { - internal MetadataReader _reader; - internal ModifiedTypeHandle _handle; + private readonly MetadataReader _reader; + private readonly ModifiedTypeHandle _handle; - public ModifiedTypeHandle Handle + internal ModifiedType(MetadataReader reader, ModifiedTypeHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _isOptional); + offset = streamReader.Read(offset, out _modifierType); + offset = streamReader.Read(offset, out _type); + } - public bool IsOptional - { - get - { - return _isOptional; - } - } // IsOptional + public ModifiedTypeHandle Handle => _handle; - internal bool _isOptional; - /// One of: TypeDefinition, TypeReference, TypeSpecification + public bool IsOptional => _isOptional; + private readonly bool _isOptional; - public Handle ModifierType - { - get - { - return _modifierType; - } - } // ModifierType + /// One of: TypeDefinition, TypeReference, TypeSpecification + public Handle ModifierType => _modifierType; + private readonly Handle _modifierType; - internal Handle _modifierType; /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType - - public Handle Type - { - get - { - return _type; - } - } // Type - - internal Handle _type; + public Handle Type => _type; + private readonly Handle _type; } // ModifiedType #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ModifiedTypeHandle + public readonly partial struct ModifiedTypeHandle { - public override bool Equals(object obj) - { - if (obj is ModifiedTypeHandle) - return _value == ((ModifiedTypeHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ModifiedTypeHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ModifiedTypeHandle(Handle handle) : this(handle._value) { @@ -5400,33 +3659,31 @@ internal ModifiedTypeHandle(int value) _Validate(); } - public static implicit operator Handle(ModifiedTypeHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ModifiedTypeHandle) + return _value == ((ModifiedTypeHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ModifiedTypeHandle handle) => _value == handle._value; - public ModifiedType GetModifiedType(MetadataReader reader) - { - return reader.GetModifiedType(this); - } // GetModifiedType + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ModifiedTypeHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ModifiedType GetModifiedType(MetadataReader reader) + => new ModifiedType(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -5435,102 +3692,52 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ModifiedTypeHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct NamedArgument + public readonly partial struct NamedArgument { - internal MetadataReader _reader; - internal NamedArgumentHandle _handle; + private readonly MetadataReader _reader; + private readonly NamedArgumentHandle _handle; - public NamedArgumentHandle Handle + internal NamedArgument(MetadataReader reader, NamedArgumentHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _flags); + offset = streamReader.Read(offset, out _name); + offset = streamReader.Read(offset, out _type); + offset = streamReader.Read(offset, out _value); + } - public NamedArgumentMemberKind Flags - { - get - { - return _flags; - } - } // Flags + public NamedArgumentHandle Handle => _handle; - internal NamedArgumentMemberKind _flags; + public NamedArgumentMemberKind Flags => _flags; + private readonly NamedArgumentMemberKind _flags; - public ConstantStringValueHandle Name - { - get - { - return _name; - } - } // Name + public ConstantStringValueHandle Name => _name; + private readonly ConstantStringValueHandle _name; - internal ConstantStringValueHandle _name; /// One of: TypeDefinition, TypeReference, TypeSpecification + public Handle Type => _type; + private readonly Handle _type; - public Handle Type - { - get - { - return _type; - } - } // Type - - internal Handle _type; - /// One of: TypeDefinition, TypeReference, TypeSpecification, ConstantBooleanArray, ConstantBooleanValue, ConstantByteArray, ConstantByteValue, ConstantCharArray, ConstantCharValue, ConstantDoubleArray, ConstantDoubleValue, ConstantEnumArray, ConstantHandleArray, ConstantInt16Array, ConstantInt16Value, ConstantInt32Array, ConstantInt32Value, ConstantInt64Array, ConstantInt64Value, ConstantReferenceValue, ConstantSByteArray, ConstantSByteValue, ConstantSingleArray, ConstantSingleValue, ConstantStringArray, ConstantStringValue, ConstantUInt16Array, ConstantUInt16Value, ConstantUInt32Array, ConstantUInt32Value, ConstantUInt64Array, ConstantUInt64Value - - public Handle Value - { - get - { - return _value; - } - } // Value - - internal Handle _value; + /// One of: TypeDefinition, TypeReference, TypeSpecification, ConstantBooleanArray, ConstantBooleanValue, ConstantByteArray, ConstantByteValue, ConstantCharArray, ConstantCharValue, ConstantDoubleArray, ConstantDoubleValue, ConstantEnumArray, ConstantEnumValue, ConstantHandleArray, ConstantInt16Array, ConstantInt16Value, ConstantInt32Array, ConstantInt32Value, ConstantInt64Array, ConstantInt64Value, ConstantReferenceValue, ConstantSByteArray, ConstantSByteValue, ConstantSingleArray, ConstantSingleValue, ConstantStringArray, ConstantStringValue, ConstantUInt16Array, ConstantUInt16Value, ConstantUInt32Array, ConstantUInt32Value, ConstantUInt64Array, ConstantUInt64Value + public Handle Value => _value; + private readonly Handle _value; } // NamedArgument #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct NamedArgumentHandle + public readonly partial struct NamedArgumentHandle { - public override bool Equals(object obj) - { - if (obj is NamedArgumentHandle) - return _value == ((NamedArgumentHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(NamedArgumentHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal NamedArgumentHandle(Handle handle) : this(handle._value) { @@ -5544,33 +3751,31 @@ internal NamedArgumentHandle(int value) _Validate(); } - public static implicit operator Handle(NamedArgumentHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is NamedArgumentHandle) + return _value == ((NamedArgumentHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(NamedArgumentHandle handle) => _value == handle._value; - public NamedArgument GetNamedArgument(MetadataReader reader) - { - return reader.GetNamedArgument(this); - } // GetNamedArgument + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(NamedArgumentHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public NamedArgument GetNamedArgument(MetadataReader reader) + => new NamedArgument(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -5579,111 +3784,55 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // NamedArgumentHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct NamespaceDefinition + public readonly partial struct NamespaceDefinition { - internal MetadataReader _reader; - internal NamespaceDefinitionHandle _handle; - - public NamespaceDefinitionHandle Handle - { - get - { - return _handle; - } - } // Handle - /// One of: NamespaceDefinition, ScopeDefinition - - public Handle ParentScopeOrNamespace - { - get - { - return _parentScopeOrNamespace; - } - } // ParentScopeOrNamespace + private readonly MetadataReader _reader; + private readonly NamespaceDefinitionHandle _handle; - internal Handle _parentScopeOrNamespace; - - public ConstantStringValueHandle Name + internal NamespaceDefinition(MetadataReader reader, NamespaceDefinitionHandle handle) { - get - { - return _name; - } - } // Name - - internal ConstantStringValueHandle _name; + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _parentScopeOrNamespace); + offset = streamReader.Read(offset, out _name); + offset = streamReader.Read(offset, out _typeDefinitions); + offset = streamReader.Read(offset, out _typeForwarders); + offset = streamReader.Read(offset, out _namespaceDefinitions); + } - public TypeDefinitionHandleCollection TypeDefinitions - { - get - { - return _typeDefinitions; - } - } // TypeDefinitions + public NamespaceDefinitionHandle Handle => _handle; - internal TypeDefinitionHandleCollection _typeDefinitions; + /// One of: NamespaceDefinition, ScopeDefinition + public Handle ParentScopeOrNamespace => _parentScopeOrNamespace; + private readonly Handle _parentScopeOrNamespace; - public TypeForwarderHandleCollection TypeForwarders - { - get - { - return _typeForwarders; - } - } // TypeForwarders + public ConstantStringValueHandle Name => _name; + private readonly ConstantStringValueHandle _name; - internal TypeForwarderHandleCollection _typeForwarders; + public TypeDefinitionHandleCollection TypeDefinitions => _typeDefinitions; + private readonly TypeDefinitionHandleCollection _typeDefinitions; - public NamespaceDefinitionHandleCollection NamespaceDefinitions - { - get - { - return _namespaceDefinitions; - } - } // NamespaceDefinitions + public TypeForwarderHandleCollection TypeForwarders => _typeForwarders; + private readonly TypeForwarderHandleCollection _typeForwarders; - internal NamespaceDefinitionHandleCollection _namespaceDefinitions; + public NamespaceDefinitionHandleCollection NamespaceDefinitions => _namespaceDefinitions; + private readonly NamespaceDefinitionHandleCollection _namespaceDefinitions; } // NamespaceDefinition #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct NamespaceDefinitionHandle + public readonly partial struct NamespaceDefinitionHandle { - public override bool Equals(object obj) - { - if (obj is NamespaceDefinitionHandle) - return _value == ((NamespaceDefinitionHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(NamespaceDefinitionHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal NamespaceDefinitionHandle(Handle handle) : this(handle._value) { @@ -5697,33 +3846,31 @@ internal NamespaceDefinitionHandle(int value) _Validate(); } - public static implicit operator Handle(NamespaceDefinitionHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is NamespaceDefinitionHandle) + return _value == ((NamespaceDefinitionHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(NamespaceDefinitionHandle handle) => _value == handle._value; - public NamespaceDefinition GetNamespaceDefinition(MetadataReader reader) - { - return reader.GetNamespaceDefinition(this); - } // GetNamespaceDefinition + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(NamespaceDefinitionHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public NamespaceDefinition GetNamespaceDefinition(MetadataReader reader) + => new NamespaceDefinition(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -5732,81 +3879,43 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // NamespaceDefinitionHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct NamespaceReference + public readonly partial struct NamespaceReference { - internal MetadataReader _reader; - internal NamespaceReferenceHandle _handle; - - public NamespaceReferenceHandle Handle - { - get - { - return _handle; - } - } // Handle - /// One of: NamespaceReference, ScopeReference + private readonly MetadataReader _reader; + private readonly NamespaceReferenceHandle _handle; - public Handle ParentScopeOrNamespace + internal NamespaceReference(MetadataReader reader, NamespaceReferenceHandle handle) { - get - { - return _parentScopeOrNamespace; - } - } // ParentScopeOrNamespace + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _parentScopeOrNamespace); + offset = streamReader.Read(offset, out _name); + } - internal Handle _parentScopeOrNamespace; + public NamespaceReferenceHandle Handle => _handle; - public ConstantStringValueHandle Name - { - get - { - return _name; - } - } // Name + /// One of: NamespaceReference, ScopeReference + public Handle ParentScopeOrNamespace => _parentScopeOrNamespace; + private readonly Handle _parentScopeOrNamespace; - internal ConstantStringValueHandle _name; + public ConstantStringValueHandle Name => _name; + private readonly ConstantStringValueHandle _name; } // NamespaceReference #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct NamespaceReferenceHandle + public readonly partial struct NamespaceReferenceHandle { - public override bool Equals(object obj) - { - if (obj is NamespaceReferenceHandle) - return _value == ((NamespaceReferenceHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(NamespaceReferenceHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal NamespaceReferenceHandle(Handle handle) : this(handle._value) { @@ -5820,33 +3929,31 @@ internal NamespaceReferenceHandle(int value) _Validate(); } - public static implicit operator Handle(NamespaceReferenceHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is NamespaceReferenceHandle) + return _value == ((NamespaceReferenceHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(NamespaceReferenceHandle handle) => _value == handle._value; - public NamespaceReference GetNamespaceReference(MetadataReader reader) - { - return reader.GetNamespaceReference(this); - } // GetNamespaceReference + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(NamespaceReferenceHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public NamespaceReference GetNamespaceReference(MetadataReader reader) + => new NamespaceReference(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -5855,111 +3962,55 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // NamespaceReferenceHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct Parameter + public readonly partial struct Parameter { - internal MetadataReader _reader; - internal ParameterHandle _handle; - - public ParameterHandle Handle - { - get - { - return _handle; - } - } // Handle - - public ParameterAttributes Flags - { - get - { - return _flags; - } - } // Flags + private readonly MetadataReader _reader; + private readonly ParameterHandle _handle; - internal ParameterAttributes _flags; - - public ushort Sequence + internal Parameter(MetadataReader reader, ParameterHandle handle) { - get - { - return _sequence; - } - } // Sequence - - internal ushort _sequence; + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _flags); + offset = streamReader.Read(offset, out _sequence); + offset = streamReader.Read(offset, out _name); + offset = streamReader.Read(offset, out _defaultValue); + offset = streamReader.Read(offset, out _customAttributes); + } - public ConstantStringValueHandle Name - { - get - { - return _name; - } - } // Name + public ParameterHandle Handle => _handle; - internal ConstantStringValueHandle _name; - /// One of: TypeDefinition, TypeReference, TypeSpecification, ConstantBooleanArray, ConstantBooleanValue, ConstantByteArray, ConstantByteValue, ConstantCharArray, ConstantCharValue, ConstantDoubleArray, ConstantDoubleValue, ConstantEnumArray, ConstantHandleArray, ConstantInt16Array, ConstantInt16Value, ConstantInt32Array, ConstantInt32Value, ConstantInt64Array, ConstantInt64Value, ConstantReferenceValue, ConstantSByteArray, ConstantSByteValue, ConstantSingleArray, ConstantSingleValue, ConstantStringArray, ConstantStringValue, ConstantUInt16Array, ConstantUInt16Value, ConstantUInt32Array, ConstantUInt32Value, ConstantUInt64Array, ConstantUInt64Value + public ParameterAttributes Flags => _flags; + private readonly ParameterAttributes _flags; - public Handle DefaultValue - { - get - { - return _defaultValue; - } - } // DefaultValue + public ushort Sequence => _sequence; + private readonly ushort _sequence; - internal Handle _defaultValue; + public ConstantStringValueHandle Name => _name; + private readonly ConstantStringValueHandle _name; - public CustomAttributeHandleCollection CustomAttributes - { - get - { - return _customAttributes; - } - } // CustomAttributes + /// One of: TypeDefinition, TypeReference, TypeSpecification, ConstantBooleanArray, ConstantBooleanValue, ConstantByteArray, ConstantByteValue, ConstantCharArray, ConstantCharValue, ConstantDoubleArray, ConstantDoubleValue, ConstantEnumArray, ConstantEnumValue, ConstantHandleArray, ConstantInt16Array, ConstantInt16Value, ConstantInt32Array, ConstantInt32Value, ConstantInt64Array, ConstantInt64Value, ConstantReferenceValue, ConstantSByteArray, ConstantSByteValue, ConstantSingleArray, ConstantSingleValue, ConstantStringArray, ConstantStringValue, ConstantUInt16Array, ConstantUInt16Value, ConstantUInt32Array, ConstantUInt32Value, ConstantUInt64Array, ConstantUInt64Value + public Handle DefaultValue => _defaultValue; + private readonly Handle _defaultValue; - internal CustomAttributeHandleCollection _customAttributes; + public CustomAttributeHandleCollection CustomAttributes => _customAttributes; + private readonly CustomAttributeHandleCollection _customAttributes; } // Parameter #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ParameterHandle + public readonly partial struct ParameterHandle { - public override bool Equals(object obj) - { - if (obj is ParameterHandle) - return _value == ((ParameterHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ParameterHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ParameterHandle(Handle handle) : this(handle._value) { @@ -5973,106 +4024,72 @@ internal ParameterHandle(int value) _Validate(); } - public static implicit operator Handle(ParameterHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ParameterHandle) + return _value == ((ParameterHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ParameterHandle handle) => _value == handle._value; - public Parameter GetParameter(MetadataReader reader) - { - return reader.GetParameter(this); - } // GetParameter + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ParameterHandle handle) + => new Handle(handle._value); - [System.Diagnostics.Conditional("DEBUG")] - internal void _Validate() + internal int Offset => (_value & 0x00FFFFFF); + + public Parameter GetParameter(MetadataReader reader) + => new Parameter(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; + + [System.Diagnostics.Conditional("DEBUG")] + internal void _Validate() { if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.Parameter) throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ParameterHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct PointerSignature + public readonly partial struct PointerSignature { - internal MetadataReader _reader; - internal PointerSignatureHandle _handle; + private readonly MetadataReader _reader; + private readonly PointerSignatureHandle _handle; - public PointerSignatureHandle Handle + internal PointerSignature(MetadataReader reader, PointerSignatureHandle handle) { - get - { - return _handle; - } - } // Handle - /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _type); + } - public Handle Type - { - get - { - return _type; - } - } // Type + public PointerSignatureHandle Handle => _handle; - internal Handle _type; + /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + public Handle Type => _type; + private readonly Handle _type; } // PointerSignature #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct PointerSignatureHandle + public readonly partial struct PointerSignatureHandle { - public override bool Equals(object obj) - { - if (obj is PointerSignatureHandle) - return _value == ((PointerSignatureHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(PointerSignatureHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal PointerSignatureHandle(Handle handle) : this(handle._value) { @@ -6086,33 +4103,31 @@ internal PointerSignatureHandle(int value) _Validate(); } - public static implicit operator Handle(PointerSignatureHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is PointerSignatureHandle) + return _value == ((PointerSignatureHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(PointerSignatureHandle handle) => _value == handle._value; - public PointerSignature GetPointerSignature(MetadataReader reader) - { - return reader.GetPointerSignature(this); - } // GetPointerSignature + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(PointerSignatureHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public PointerSignature GetPointerSignature(MetadataReader reader) + => new PointerSignature(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -6121,121 +4136,59 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // PointerSignatureHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct Property + public readonly partial struct Property { - internal MetadataReader _reader; - internal PropertyHandle _handle; - - public PropertyHandle Handle - { - get - { - return _handle; - } - } // Handle - - public PropertyAttributes Flags - { - get - { - return _flags; - } - } // Flags - - internal PropertyAttributes _flags; - - public ConstantStringValueHandle Name - { - get - { - return _name; - } - } // Name + private readonly MetadataReader _reader; + private readonly PropertyHandle _handle; - internal ConstantStringValueHandle _name; - - public PropertySignatureHandle Signature + internal Property(MetadataReader reader, PropertyHandle handle) { - get - { - return _signature; - } - } // Signature + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _flags); + offset = streamReader.Read(offset, out _name); + offset = streamReader.Read(offset, out _signature); + offset = streamReader.Read(offset, out _methodSemantics); + offset = streamReader.Read(offset, out _defaultValue); + offset = streamReader.Read(offset, out _customAttributes); + } - internal PropertySignatureHandle _signature; + public PropertyHandle Handle => _handle; - public MethodSemanticsHandleCollection MethodSemantics - { - get - { - return _methodSemantics; - } - } // MethodSemantics + public PropertyAttributes Flags => _flags; + private readonly PropertyAttributes _flags; - internal MethodSemanticsHandleCollection _methodSemantics; - /// One of: TypeDefinition, TypeReference, TypeSpecification, ConstantBooleanArray, ConstantBooleanValue, ConstantByteArray, ConstantByteValue, ConstantCharArray, ConstantCharValue, ConstantDoubleArray, ConstantDoubleValue, ConstantEnumArray, ConstantHandleArray, ConstantInt16Array, ConstantInt16Value, ConstantInt32Array, ConstantInt32Value, ConstantInt64Array, ConstantInt64Value, ConstantReferenceValue, ConstantSByteArray, ConstantSByteValue, ConstantSingleArray, ConstantSingleValue, ConstantStringArray, ConstantStringValue, ConstantUInt16Array, ConstantUInt16Value, ConstantUInt32Array, ConstantUInt32Value, ConstantUInt64Array, ConstantUInt64Value + public ConstantStringValueHandle Name => _name; + private readonly ConstantStringValueHandle _name; - public Handle DefaultValue - { - get - { - return _defaultValue; - } - } // DefaultValue + public PropertySignatureHandle Signature => _signature; + private readonly PropertySignatureHandle _signature; - internal Handle _defaultValue; + public MethodSemanticsHandleCollection MethodSemantics => _methodSemantics; + private readonly MethodSemanticsHandleCollection _methodSemantics; - public CustomAttributeHandleCollection CustomAttributes - { - get - { - return _customAttributes; - } - } // CustomAttributes + /// One of: TypeDefinition, TypeReference, TypeSpecification, ConstantBooleanArray, ConstantBooleanValue, ConstantByteArray, ConstantByteValue, ConstantCharArray, ConstantCharValue, ConstantDoubleArray, ConstantDoubleValue, ConstantEnumArray, ConstantEnumValue, ConstantHandleArray, ConstantInt16Array, ConstantInt16Value, ConstantInt32Array, ConstantInt32Value, ConstantInt64Array, ConstantInt64Value, ConstantReferenceValue, ConstantSByteArray, ConstantSByteValue, ConstantSingleArray, ConstantSingleValue, ConstantStringArray, ConstantStringValue, ConstantUInt16Array, ConstantUInt16Value, ConstantUInt32Array, ConstantUInt32Value, ConstantUInt64Array, ConstantUInt64Value + public Handle DefaultValue => _defaultValue; + private readonly Handle _defaultValue; - internal CustomAttributeHandleCollection _customAttributes; + public CustomAttributeHandleCollection CustomAttributes => _customAttributes; + private readonly CustomAttributeHandleCollection _customAttributes; } // Property #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct PropertyHandle + public readonly partial struct PropertyHandle { - public override bool Equals(object obj) - { - if (obj is PropertyHandle) - return _value == ((PropertyHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(PropertyHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal PropertyHandle(Handle handle) : this(handle._value) { @@ -6249,33 +4202,31 @@ internal PropertyHandle(int value) _Validate(); } - public static implicit operator Handle(PropertyHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is PropertyHandle) + return _value == ((PropertyHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(PropertyHandle handle) => _value == handle._value; - public Property GetProperty(MetadataReader reader) - { - return reader.GetProperty(this); - } // GetProperty + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(PropertyHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public Property GetProperty(MetadataReader reader) + => new Property(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -6284,92 +4235,48 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // PropertyHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct PropertySignature + public readonly partial struct PropertySignature { - internal MetadataReader _reader; - internal PropertySignatureHandle _handle; + private readonly MetadataReader _reader; + private readonly PropertySignatureHandle _handle; - public PropertySignatureHandle Handle + internal PropertySignature(MetadataReader reader, PropertySignatureHandle handle) { - get - { - return _handle; - } - } // Handle - - public CallingConventions CallingConvention - { - get - { - return _callingConvention; - } - } // CallingConvention + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _callingConvention); + offset = streamReader.Read(offset, out _type); + offset = streamReader.Read(offset, out _parameters); + } - internal CallingConventions _callingConvention; - /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + public PropertySignatureHandle Handle => _handle; - public Handle Type - { - get - { - return _type; - } - } // Type + public CallingConventions CallingConvention => _callingConvention; + private readonly CallingConventions _callingConvention; - internal Handle _type; /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + public Handle Type => _type; + private readonly Handle _type; - public HandleCollection Parameters - { - get - { - return _parameters; - } - } // Parameters - - internal HandleCollection _parameters; + /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + public HandleCollection Parameters => _parameters; + private readonly HandleCollection _parameters; } // PropertySignature #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct PropertySignatureHandle + public readonly partial struct PropertySignatureHandle { - public override bool Equals(object obj) - { - if (obj is PropertySignatureHandle) - return _value == ((PropertySignatureHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(PropertySignatureHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal PropertySignatureHandle(Handle handle) : this(handle._value) { @@ -6383,33 +4290,31 @@ internal PropertySignatureHandle(int value) _Validate(); } - public static implicit operator Handle(PropertySignatureHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is PropertySignatureHandle) + return _value == ((PropertySignatureHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(PropertySignatureHandle handle) => _value == handle._value; - public PropertySignature GetPropertySignature(MetadataReader reader) - { - return reader.GetPropertySignature(this); - } // GetPropertySignature + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(PropertySignatureHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public PropertySignature GetPropertySignature(MetadataReader reader) + => new PropertySignature(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -6418,80 +4323,42 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // PropertySignatureHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct QualifiedField + public readonly partial struct QualifiedField { - internal MetadataReader _reader; - internal QualifiedFieldHandle _handle; - - public QualifiedFieldHandle Handle - { - get - { - return _handle; - } - } // Handle + private readonly MetadataReader _reader; + private readonly QualifiedFieldHandle _handle; - public FieldHandle Field + internal QualifiedField(MetadataReader reader, QualifiedFieldHandle handle) { - get - { - return _field; - } - } // Field + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _field); + offset = streamReader.Read(offset, out _enclosingType); + } - internal FieldHandle _field; + public QualifiedFieldHandle Handle => _handle; - public TypeDefinitionHandle EnclosingType - { - get - { - return _enclosingType; - } - } // EnclosingType + public FieldHandle Field => _field; + private readonly FieldHandle _field; - internal TypeDefinitionHandle _enclosingType; + public TypeDefinitionHandle EnclosingType => _enclosingType; + private readonly TypeDefinitionHandle _enclosingType; } // QualifiedField #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct QualifiedFieldHandle + public readonly partial struct QualifiedFieldHandle { - public override bool Equals(object obj) - { - if (obj is QualifiedFieldHandle) - return _value == ((QualifiedFieldHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(QualifiedFieldHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal QualifiedFieldHandle(Handle handle) : this(handle._value) { @@ -6505,33 +4372,31 @@ internal QualifiedFieldHandle(int value) _Validate(); } - public static implicit operator Handle(QualifiedFieldHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is QualifiedFieldHandle) + return _value == ((QualifiedFieldHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(QualifiedFieldHandle handle) => _value == handle._value; - public QualifiedField GetQualifiedField(MetadataReader reader) - { - return reader.GetQualifiedField(this); - } // GetQualifiedField + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(QualifiedFieldHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public QualifiedField GetQualifiedField(MetadataReader reader) + => new QualifiedField(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -6540,80 +4405,42 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // QualifiedFieldHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct QualifiedMethod + public readonly partial struct QualifiedMethod { - internal MetadataReader _reader; - internal QualifiedMethodHandle _handle; + private readonly MetadataReader _reader; + private readonly QualifiedMethodHandle _handle; - public QualifiedMethodHandle Handle + internal QualifiedMethod(MetadataReader reader, QualifiedMethodHandle handle) { - get - { - return _handle; - } - } // Handle - - public MethodHandle Method - { - get - { - return _method; - } - } // Method + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _method); + offset = streamReader.Read(offset, out _enclosingType); + } - internal MethodHandle _method; + public QualifiedMethodHandle Handle => _handle; - public TypeDefinitionHandle EnclosingType - { - get - { - return _enclosingType; - } - } // EnclosingType + public MethodHandle Method => _method; + private readonly MethodHandle _method; - internal TypeDefinitionHandle _enclosingType; + public TypeDefinitionHandle EnclosingType => _enclosingType; + private readonly TypeDefinitionHandle _enclosingType; } // QualifiedMethod #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct QualifiedMethodHandle + public readonly partial struct QualifiedMethodHandle { - public override bool Equals(object obj) - { - if (obj is QualifiedMethodHandle) - return _value == ((QualifiedMethodHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(QualifiedMethodHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal QualifiedMethodHandle(Handle handle) : this(handle._value) { @@ -6627,33 +4454,31 @@ internal QualifiedMethodHandle(int value) _Validate(); } - public static implicit operator Handle(QualifiedMethodHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is QualifiedMethodHandle) + return _value == ((QualifiedMethodHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(QualifiedMethodHandle handle) => _value == handle._value; - public QualifiedMethod GetQualifiedMethod(MetadataReader reader) - { - return reader.GetQualifiedMethod(this); - } // GetQualifiedMethod + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(QualifiedMethodHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public QualifiedMethod GetQualifiedMethod(MetadataReader reader) + => new QualifiedMethod(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -6662,71 +4487,39 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // QualifiedMethodHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct SZArraySignature + public readonly partial struct SZArraySignature { - internal MetadataReader _reader; - internal SZArraySignatureHandle _handle; + private readonly MetadataReader _reader; + private readonly SZArraySignatureHandle _handle; - public SZArraySignatureHandle Handle + internal SZArraySignature(MetadataReader reader, SZArraySignatureHandle handle) { - get - { - return _handle; - } - } // Handle - /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _elementType); + } - public Handle ElementType - { - get - { - return _elementType; - } - } // ElementType + public SZArraySignatureHandle Handle => _handle; - internal Handle _elementType; + /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType + public Handle ElementType => _elementType; + private readonly Handle _elementType; } // SZArraySignature #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct SZArraySignatureHandle + public readonly partial struct SZArraySignatureHandle { - public override bool Equals(object obj) - { - if (obj is SZArraySignatureHandle) - return _value == ((SZArraySignatureHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(SZArraySignatureHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal SZArraySignatureHandle(Handle handle) : this(handle._value) { @@ -6740,33 +4533,31 @@ internal SZArraySignatureHandle(int value) _Validate(); } - public static implicit operator Handle(SZArraySignatureHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is SZArraySignatureHandle) + return _value == ((SZArraySignatureHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(SZArraySignatureHandle handle) => _value == handle._value; - public SZArraySignature GetSZArraySignature(MetadataReader reader) - { - return reader.GetSZArraySignature(this); - } // GetSZArraySignature + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(SZArraySignatureHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public SZArraySignature GetSZArraySignature(MetadataReader reader) + => new SZArraySignature(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -6775,220 +4566,98 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // SZArraySignatureHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ScopeDefinition + public readonly partial struct ScopeDefinition { - internal MetadataReader _reader; - internal ScopeDefinitionHandle _handle; - - public ScopeDefinitionHandle Handle - { - get - { - return _handle; - } - } // Handle - - public AssemblyFlags Flags - { - get - { - return _flags; - } - } // Flags - - internal AssemblyFlags _flags; - - public ConstantStringValueHandle Name - { - get - { - return _name; - } - } // Name - - internal ConstantStringValueHandle _name; - - public AssemblyHashAlgorithm HashAlgorithm - { - get - { - return _hashAlgorithm; - } - } // HashAlgorithm - - internal AssemblyHashAlgorithm _hashAlgorithm; - - public ushort MajorVersion - { - get - { - return _majorVersion; - } - } // MajorVersion - - internal ushort _majorVersion; - - public ushort MinorVersion - { - get - { - return _minorVersion; - } - } // MinorVersion - - internal ushort _minorVersion; - - public ushort BuildNumber - { - get - { - return _buildNumber; - } - } // BuildNumber - - internal ushort _buildNumber; - - public ushort RevisionNumber - { - get - { - return _revisionNumber; - } - } // RevisionNumber + private readonly MetadataReader _reader; + private readonly ScopeDefinitionHandle _handle; - internal ushort _revisionNumber; - - public ByteCollection PublicKey + internal ScopeDefinition(MetadataReader reader, ScopeDefinitionHandle handle) { - get - { - return _publicKey; - } - } // PublicKey + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _flags); + offset = streamReader.Read(offset, out _name); + offset = streamReader.Read(offset, out _hashAlgorithm); + offset = streamReader.Read(offset, out _majorVersion); + offset = streamReader.Read(offset, out _minorVersion); + offset = streamReader.Read(offset, out _buildNumber); + offset = streamReader.Read(offset, out _revisionNumber); + offset = streamReader.Read(offset, out _publicKey); + offset = streamReader.Read(offset, out _culture); + offset = streamReader.Read(offset, out _rootNamespaceDefinition); + offset = streamReader.Read(offset, out _entryPoint); + offset = streamReader.Read(offset, out _globalModuleType); + offset = streamReader.Read(offset, out _customAttributes); + offset = streamReader.Read(offset, out _moduleName); + offset = streamReader.Read(offset, out _mvid); + offset = streamReader.Read(offset, out _moduleCustomAttributes); + } - internal ByteCollection _publicKey; + public ScopeDefinitionHandle Handle => _handle; - public ConstantStringValueHandle Culture - { - get - { - return _culture; - } - } // Culture + public AssemblyFlags Flags => _flags; + private readonly AssemblyFlags _flags; - internal ConstantStringValueHandle _culture; + public ConstantStringValueHandle Name => _name; + private readonly ConstantStringValueHandle _name; - public NamespaceDefinitionHandle RootNamespaceDefinition - { - get - { - return _rootNamespaceDefinition; - } - } // RootNamespaceDefinition + public AssemblyHashAlgorithm HashAlgorithm => _hashAlgorithm; + private readonly AssemblyHashAlgorithm _hashAlgorithm; - internal NamespaceDefinitionHandle _rootNamespaceDefinition; + public ushort MajorVersion => _majorVersion; + private readonly ushort _majorVersion; - public QualifiedMethodHandle EntryPoint - { - get - { - return _entryPoint; - } - } // EntryPoint + public ushort MinorVersion => _minorVersion; + private readonly ushort _minorVersion; - internal QualifiedMethodHandle _entryPoint; + public ushort BuildNumber => _buildNumber; + private readonly ushort _buildNumber; - public TypeDefinitionHandle GlobalModuleType - { - get - { - return _globalModuleType; - } - } // GlobalModuleType + public ushort RevisionNumber => _revisionNumber; + private readonly ushort _revisionNumber; - internal TypeDefinitionHandle _globalModuleType; + public ByteCollection PublicKey => _publicKey; + private readonly ByteCollection _publicKey; - public CustomAttributeHandleCollection CustomAttributes - { - get - { - return _customAttributes; - } - } // CustomAttributes + public ConstantStringValueHandle Culture => _culture; + private readonly ConstantStringValueHandle _culture; - internal CustomAttributeHandleCollection _customAttributes; + public NamespaceDefinitionHandle RootNamespaceDefinition => _rootNamespaceDefinition; + private readonly NamespaceDefinitionHandle _rootNamespaceDefinition; - public ConstantStringValueHandle ModuleName - { - get - { - return _moduleName; - } - } // ModuleName + public QualifiedMethodHandle EntryPoint => _entryPoint; + private readonly QualifiedMethodHandle _entryPoint; - internal ConstantStringValueHandle _moduleName; + public TypeDefinitionHandle GlobalModuleType => _globalModuleType; + private readonly TypeDefinitionHandle _globalModuleType; - public ByteCollection Mvid - { - get - { - return _mvid; - } - } // Mvid + public CustomAttributeHandleCollection CustomAttributes => _customAttributes; + private readonly CustomAttributeHandleCollection _customAttributes; - internal ByteCollection _mvid; + public ConstantStringValueHandle ModuleName => _moduleName; + private readonly ConstantStringValueHandle _moduleName; - public CustomAttributeHandleCollection ModuleCustomAttributes - { - get - { - return _moduleCustomAttributes; - } - } // ModuleCustomAttributes + public ByteCollection Mvid => _mvid; + private readonly ByteCollection _mvid; - internal CustomAttributeHandleCollection _moduleCustomAttributes; + public CustomAttributeHandleCollection ModuleCustomAttributes => _moduleCustomAttributes; + private readonly CustomAttributeHandleCollection _moduleCustomAttributes; } // ScopeDefinition #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ScopeDefinitionHandle + public readonly partial struct ScopeDefinitionHandle { - public override bool Equals(object obj) - { - if (obj is ScopeDefinitionHandle) - return _value == ((ScopeDefinitionHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ScopeDefinitionHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ScopeDefinitionHandle(Handle handle) : this(handle._value) { @@ -7002,33 +4671,31 @@ internal ScopeDefinitionHandle(int value) _Validate(); } - public static implicit operator Handle(ScopeDefinitionHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ScopeDefinitionHandle) + return _value == ((ScopeDefinitionHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ScopeDefinitionHandle handle) => _value == handle._value; - public ScopeDefinition GetScopeDefinition(MetadataReader reader) - { - return reader.GetScopeDefinition(this); - } // GetScopeDefinition + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ScopeDefinitionHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ScopeDefinition GetScopeDefinition(MetadataReader reader) + => new ScopeDefinition(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -7037,140 +4704,66 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ScopeDefinitionHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ScopeReference + public readonly partial struct ScopeReference { - internal MetadataReader _reader; - internal ScopeReferenceHandle _handle; + private readonly MetadataReader _reader; + private readonly ScopeReferenceHandle _handle; - public ScopeReferenceHandle Handle + internal ScopeReference(MetadataReader reader, ScopeReferenceHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _flags); + offset = streamReader.Read(offset, out _name); + offset = streamReader.Read(offset, out _majorVersion); + offset = streamReader.Read(offset, out _minorVersion); + offset = streamReader.Read(offset, out _buildNumber); + offset = streamReader.Read(offset, out _revisionNumber); + offset = streamReader.Read(offset, out _publicKeyOrToken); + offset = streamReader.Read(offset, out _culture); + } - public AssemblyFlags Flags - { - get - { - return _flags; - } - } // Flags + public ScopeReferenceHandle Handle => _handle; - internal AssemblyFlags _flags; + public AssemblyFlags Flags => _flags; + private readonly AssemblyFlags _flags; - public ConstantStringValueHandle Name - { - get - { - return _name; - } - } // Name + public ConstantStringValueHandle Name => _name; + private readonly ConstantStringValueHandle _name; - internal ConstantStringValueHandle _name; + public ushort MajorVersion => _majorVersion; + private readonly ushort _majorVersion; - public ushort MajorVersion - { - get - { - return _majorVersion; - } - } // MajorVersion + public ushort MinorVersion => _minorVersion; + private readonly ushort _minorVersion; - internal ushort _majorVersion; + public ushort BuildNumber => _buildNumber; + private readonly ushort _buildNumber; - public ushort MinorVersion - { - get - { - return _minorVersion; - } - } // MinorVersion + public ushort RevisionNumber => _revisionNumber; + private readonly ushort _revisionNumber; - internal ushort _minorVersion; + public ByteCollection PublicKeyOrToken => _publicKeyOrToken; + private readonly ByteCollection _publicKeyOrToken; - public ushort BuildNumber - { - get - { - return _buildNumber; - } - } // BuildNumber - - internal ushort _buildNumber; - - public ushort RevisionNumber - { - get - { - return _revisionNumber; - } - } // RevisionNumber - - internal ushort _revisionNumber; - - public ByteCollection PublicKeyOrToken - { - get - { - return _publicKeyOrToken; - } - } // PublicKeyOrToken - - internal ByteCollection _publicKeyOrToken; - - public ConstantStringValueHandle Culture - { - get - { - return _culture; - } - } // Culture - - internal ConstantStringValueHandle _culture; + public ConstantStringValueHandle Culture => _culture; + private readonly ConstantStringValueHandle _culture; } // ScopeReference #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ScopeReferenceHandle + public readonly partial struct ScopeReferenceHandle { - public override bool Equals(object obj) - { - if (obj is ScopeReferenceHandle) - return _value == ((ScopeReferenceHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(ScopeReferenceHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal ScopeReferenceHandle(Handle handle) : this(handle._value) { @@ -7184,33 +4777,31 @@ internal ScopeReferenceHandle(int value) _Validate(); } - public static implicit operator Handle(ScopeReferenceHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is ScopeReferenceHandle) + return _value == ((ScopeReferenceHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(ScopeReferenceHandle handle) => _value == handle._value; - public ScopeReference GetScopeReference(MetadataReader reader) - { - return reader.GetScopeReference(this); - } // GetScopeReference + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(ScopeReferenceHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public ScopeReference GetScopeReference(MetadataReader reader) + => new ScopeReference(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -7219,212 +4810,96 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // ScopeReferenceHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct TypeDefinition + public readonly partial struct TypeDefinition { - internal MetadataReader _reader; - internal TypeDefinitionHandle _handle; + private readonly MetadataReader _reader; + private readonly TypeDefinitionHandle _handle; - public TypeDefinitionHandle Handle + internal TypeDefinition(MetadataReader reader, TypeDefinitionHandle handle) { - get - { - return _handle; - } - } // Handle - - public TypeAttributes Flags - { - get - { - return _flags; - } - } // Flags + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _flags); + offset = streamReader.Read(offset, out _baseType); + offset = streamReader.Read(offset, out _namespaceDefinition); + offset = streamReader.Read(offset, out _name); + offset = streamReader.Read(offset, out _size); + offset = streamReader.Read(offset, out _packingSize); + offset = streamReader.Read(offset, out _enclosingType); + offset = streamReader.Read(offset, out _nestedTypes); + offset = streamReader.Read(offset, out _methods); + offset = streamReader.Read(offset, out _fields); + offset = streamReader.Read(offset, out _properties); + offset = streamReader.Read(offset, out _events); + offset = streamReader.Read(offset, out _genericParameters); + offset = streamReader.Read(offset, out _interfaces); + offset = streamReader.Read(offset, out _customAttributes); + } + + public TypeDefinitionHandle Handle => _handle; + + public TypeAttributes Flags => _flags; + private readonly TypeAttributes _flags; - internal TypeAttributes _flags; /// One of: TypeDefinition, TypeReference, TypeSpecification + public Handle BaseType => _baseType; + private readonly Handle _baseType; - public Handle BaseType - { - get - { - return _baseType; - } - } // BaseType - - internal Handle _baseType; - - public NamespaceDefinitionHandle NamespaceDefinition - { - get - { - return _namespaceDefinition; - } - } // NamespaceDefinition - - internal NamespaceDefinitionHandle _namespaceDefinition; - - public ConstantStringValueHandle Name - { - get - { - return _name; - } - } // Name - - internal ConstantStringValueHandle _name; - - public uint Size - { - get - { - return _size; - } - } // Size - - internal uint _size; + public NamespaceDefinitionHandle NamespaceDefinition => _namespaceDefinition; + private readonly NamespaceDefinitionHandle _namespaceDefinition; - public ushort PackingSize - { - get - { - return _packingSize; - } - } // PackingSize - - internal ushort _packingSize; - - public TypeDefinitionHandle EnclosingType - { - get - { - return _enclosingType; - } - } // EnclosingType - - internal TypeDefinitionHandle _enclosingType; - - public TypeDefinitionHandleCollection NestedTypes - { - get - { - return _nestedTypes; - } - } // NestedTypes + public ConstantStringValueHandle Name => _name; + private readonly ConstantStringValueHandle _name; - internal TypeDefinitionHandleCollection _nestedTypes; + public uint Size => _size; + private readonly uint _size; - public MethodHandleCollection Methods - { - get - { - return _methods; - } - } // Methods + public ushort PackingSize => _packingSize; + private readonly ushort _packingSize; - internal MethodHandleCollection _methods; - - public FieldHandleCollection Fields - { - get - { - return _fields; - } - } // Fields + public TypeDefinitionHandle EnclosingType => _enclosingType; + private readonly TypeDefinitionHandle _enclosingType; - internal FieldHandleCollection _fields; + public TypeDefinitionHandleCollection NestedTypes => _nestedTypes; + private readonly TypeDefinitionHandleCollection _nestedTypes; - public PropertyHandleCollection Properties - { - get - { - return _properties; - } - } // Properties + public MethodHandleCollection Methods => _methods; + private readonly MethodHandleCollection _methods; - internal PropertyHandleCollection _properties; + public FieldHandleCollection Fields => _fields; + private readonly FieldHandleCollection _fields; - public EventHandleCollection Events - { - get - { - return _events; - } - } // Events + public PropertyHandleCollection Properties => _properties; + private readonly PropertyHandleCollection _properties; - internal EventHandleCollection _events; + public EventHandleCollection Events => _events; + private readonly EventHandleCollection _events; - public GenericParameterHandleCollection GenericParameters - { - get - { - return _genericParameters; - } - } // GenericParameters + public GenericParameterHandleCollection GenericParameters => _genericParameters; + private readonly GenericParameterHandleCollection _genericParameters; - internal GenericParameterHandleCollection _genericParameters; /// One of: TypeDefinition, TypeReference, TypeSpecification + public HandleCollection Interfaces => _interfaces; + private readonly HandleCollection _interfaces; - public HandleCollection Interfaces - { - get - { - return _interfaces; - } - } // Interfaces - - internal HandleCollection _interfaces; - - public CustomAttributeHandleCollection CustomAttributes - { - get - { - return _customAttributes; - } - } // CustomAttributes - - internal CustomAttributeHandleCollection _customAttributes; + public CustomAttributeHandleCollection CustomAttributes => _customAttributes; + private readonly CustomAttributeHandleCollection _customAttributes; } // TypeDefinition #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct TypeDefinitionHandle + public readonly partial struct TypeDefinitionHandle { - public override bool Equals(object obj) - { - if (obj is TypeDefinitionHandle) - return _value == ((TypeDefinitionHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(TypeDefinitionHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal TypeDefinitionHandle(Handle handle) : this(handle._value) { @@ -7438,33 +4913,31 @@ internal TypeDefinitionHandle(int value) _Validate(); } - public static implicit operator Handle(TypeDefinitionHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is TypeDefinitionHandle) + return _value == ((TypeDefinitionHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(TypeDefinitionHandle handle) => _value == handle._value; - public TypeDefinition GetTypeDefinition(MetadataReader reader) - { - return reader.GetTypeDefinition(this); - } // GetTypeDefinition + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(TypeDefinitionHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public TypeDefinition GetTypeDefinition(MetadataReader reader) + => new TypeDefinition(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -7473,90 +4946,46 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // TypeDefinitionHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct TypeForwarder + public readonly partial struct TypeForwarder { - internal MetadataReader _reader; - internal TypeForwarderHandle _handle; - - public TypeForwarderHandle Handle - { - get - { - return _handle; - } - } // Handle + private readonly MetadataReader _reader; + private readonly TypeForwarderHandle _handle; - public ScopeReferenceHandle Scope + internal TypeForwarder(MetadataReader reader, TypeForwarderHandle handle) { - get - { - return _scope; - } - } // Scope - - internal ScopeReferenceHandle _scope; + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _scope); + offset = streamReader.Read(offset, out _name); + offset = streamReader.Read(offset, out _nestedTypes); + } - public ConstantStringValueHandle Name - { - get - { - return _name; - } - } // Name + public TypeForwarderHandle Handle => _handle; - internal ConstantStringValueHandle _name; + public ScopeReferenceHandle Scope => _scope; + private readonly ScopeReferenceHandle _scope; - public TypeForwarderHandleCollection NestedTypes - { - get - { - return _nestedTypes; - } - } // NestedTypes + public ConstantStringValueHandle Name => _name; + private readonly ConstantStringValueHandle _name; - internal TypeForwarderHandleCollection _nestedTypes; + public TypeForwarderHandleCollection NestedTypes => _nestedTypes; + private readonly TypeForwarderHandleCollection _nestedTypes; } // TypeForwarder #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct TypeForwarderHandle + public readonly partial struct TypeForwarderHandle { - public override bool Equals(object obj) - { - if (obj is TypeForwarderHandle) - return _value == ((TypeForwarderHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(TypeForwarderHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal TypeForwarderHandle(Handle handle) : this(handle._value) { @@ -7570,33 +4999,31 @@ internal TypeForwarderHandle(int value) _Validate(); } - public static implicit operator Handle(TypeForwarderHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is TypeForwarderHandle) + return _value == ((TypeForwarderHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(TypeForwarderHandle handle) => _value == handle._value; - public TypeForwarder GetTypeForwarder(MetadataReader reader) - { - return reader.GetTypeForwarder(this); - } // GetTypeForwarder + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(TypeForwarderHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public TypeForwarder GetTypeForwarder(MetadataReader reader) + => new TypeForwarder(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -7605,82 +5032,44 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // TypeForwarderHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct TypeInstantiationSignature + public readonly partial struct TypeInstantiationSignature { - internal MetadataReader _reader; - internal TypeInstantiationSignatureHandle _handle; + private readonly MetadataReader _reader; + private readonly TypeInstantiationSignatureHandle _handle; - public TypeInstantiationSignatureHandle Handle + internal TypeInstantiationSignature(MetadataReader reader, TypeInstantiationSignatureHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _genericType); + offset = streamReader.Read(offset, out _genericTypeArguments); + } + + public TypeInstantiationSignatureHandle Handle => _handle; + /// One of: TypeDefinition, TypeReference, TypeSpecification + public Handle GenericType => _genericType; + private readonly Handle _genericType; - public Handle GenericType - { - get - { - return _genericType; - } - } // GenericType - - internal Handle _genericType; /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType - - public HandleCollection GenericTypeArguments - { - get - { - return _genericTypeArguments; - } - } // GenericTypeArguments - - internal HandleCollection _genericTypeArguments; + public HandleCollection GenericTypeArguments => _genericTypeArguments; + private readonly HandleCollection _genericTypeArguments; } // TypeInstantiationSignature #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct TypeInstantiationSignatureHandle + public readonly partial struct TypeInstantiationSignatureHandle { - public override bool Equals(object obj) - { - if (obj is TypeInstantiationSignatureHandle) - return _value == ((TypeInstantiationSignatureHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(TypeInstantiationSignatureHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal TypeInstantiationSignatureHandle(Handle handle) : this(handle._value) { @@ -7694,33 +5083,31 @@ internal TypeInstantiationSignatureHandle(int value) _Validate(); } - public static implicit operator Handle(TypeInstantiationSignatureHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is TypeInstantiationSignatureHandle) + return _value == ((TypeInstantiationSignatureHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(TypeInstantiationSignatureHandle handle) => _value == handle._value; - public TypeInstantiationSignature GetTypeInstantiationSignature(MetadataReader reader) - { - return reader.GetTypeInstantiationSignature(this); - } // GetTypeInstantiationSignature + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(TypeInstantiationSignatureHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public TypeInstantiationSignature GetTypeInstantiationSignature(MetadataReader reader) + => new TypeInstantiationSignature(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -7729,81 +5116,43 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // TypeInstantiationSignatureHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct TypeReference + public readonly partial struct TypeReference { - internal MetadataReader _reader; - internal TypeReferenceHandle _handle; - - public TypeReferenceHandle Handle - { - get - { - return _handle; - } - } // Handle - /// One of: NamespaceReference, TypeReference + private readonly MetadataReader _reader; + private readonly TypeReferenceHandle _handle; - public Handle ParentNamespaceOrType + internal TypeReference(MetadataReader reader, TypeReferenceHandle handle) { - get - { - return _parentNamespaceOrType; - } - } // ParentNamespaceOrType + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _parentNamespaceOrType); + offset = streamReader.Read(offset, out _typeName); + } - internal Handle _parentNamespaceOrType; + public TypeReferenceHandle Handle => _handle; - public ConstantStringValueHandle TypeName - { - get - { - return _typeName; - } - } // TypeName + /// One of: NamespaceReference, TypeReference + public Handle ParentNamespaceOrType => _parentNamespaceOrType; + private readonly Handle _parentNamespaceOrType; - internal ConstantStringValueHandle _typeName; + public ConstantStringValueHandle TypeName => _typeName; + private readonly ConstantStringValueHandle _typeName; } // TypeReference #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct TypeReferenceHandle + public readonly partial struct TypeReferenceHandle { - public override bool Equals(object obj) - { - if (obj is TypeReferenceHandle) - return _value == ((TypeReferenceHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(TypeReferenceHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal TypeReferenceHandle(Handle handle) : this(handle._value) { @@ -7817,33 +5166,31 @@ internal TypeReferenceHandle(int value) _Validate(); } - public static implicit operator Handle(TypeReferenceHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is TypeReferenceHandle) + return _value == ((TypeReferenceHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(TypeReferenceHandle handle) => _value == handle._value; - public TypeReference GetTypeReference(MetadataReader reader) - { - return reader.GetTypeReference(this); - } // GetTypeReference + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(TypeReferenceHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public TypeReference GetTypeReference(MetadataReader reader) + => new TypeReference(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -7852,71 +5199,39 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // TypeReferenceHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct TypeSpecification + public readonly partial struct TypeSpecification { - internal MetadataReader _reader; - internal TypeSpecificationHandle _handle; + private readonly MetadataReader _reader; + private readonly TypeSpecificationHandle _handle; - public TypeSpecificationHandle Handle + internal TypeSpecification(MetadataReader reader, TypeSpecificationHandle handle) { - get - { - return _handle; - } - } // Handle - /// One of: TypeDefinition, TypeReference, TypeInstantiationSignature, SZArraySignature, ArraySignature, PointerSignature, FunctionPointerSignature, ByReferenceSignature, TypeVariableSignature, MethodTypeVariableSignature + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _signature); + } - public Handle Signature - { - get - { - return _signature; - } - } // Signature + public TypeSpecificationHandle Handle => _handle; - internal Handle _signature; + /// One of: TypeDefinition, TypeReference, TypeInstantiationSignature, SZArraySignature, ArraySignature, PointerSignature, FunctionPointerSignature, ByReferenceSignature, TypeVariableSignature, MethodTypeVariableSignature + public Handle Signature => _signature; + private readonly Handle _signature; } // TypeSpecification #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct TypeSpecificationHandle + public readonly partial struct TypeSpecificationHandle { - public override bool Equals(object obj) - { - if (obj is TypeSpecificationHandle) - return _value == ((TypeSpecificationHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(TypeSpecificationHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal TypeSpecificationHandle(Handle handle) : this(handle._value) { @@ -7930,33 +5245,31 @@ internal TypeSpecificationHandle(int value) _Validate(); } - public static implicit operator Handle(TypeSpecificationHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is TypeSpecificationHandle) + return _value == ((TypeSpecificationHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(TypeSpecificationHandle handle) => _value == handle._value; - public TypeSpecification GetTypeSpecification(MetadataReader reader) - { - return reader.GetTypeSpecification(this); - } // GetTypeSpecification + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(TypeSpecificationHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public TypeSpecification GetTypeSpecification(MetadataReader reader) + => new TypeSpecification(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -7965,70 +5278,38 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // TypeSpecificationHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct TypeVariableSignature + public readonly partial struct TypeVariableSignature { - internal MetadataReader _reader; - internal TypeVariableSignatureHandle _handle; + private readonly MetadataReader _reader; + private readonly TypeVariableSignatureHandle _handle; - public TypeVariableSignatureHandle Handle + internal TypeVariableSignature(MetadataReader reader, TypeVariableSignatureHandle handle) { - get - { - return _handle; - } - } // Handle + _reader = reader; + _handle = handle; + uint offset = (uint)handle.Offset; + NativeReader streamReader = reader._streamReader; + offset = streamReader.Read(offset, out _number); + } - public int Number - { - get - { - return _number; - } - } // Number + public TypeVariableSignatureHandle Handle => _handle; - internal int _number; + public int Number => _number; + private readonly int _number; } // TypeVariableSignature #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct TypeVariableSignatureHandle + public readonly partial struct TypeVariableSignatureHandle { - public override bool Equals(object obj) - { - if (obj is TypeVariableSignatureHandle) - return _value == ((TypeVariableSignatureHandle)obj)._value; - else if (obj is Handle) - return _value == ((Handle)obj)._value; - else - return false; - } // Equals - - public bool Equals(TypeVariableSignatureHandle handle) - { - return _value == handle._value; - } // Equals - - public bool Equals(Handle handle) - { - return _value == handle._value; - } // Equals - - public override int GetHashCode() - { - return (int)_value; - } // GetHashCode - - internal int _value; + internal readonly int _value; internal TypeVariableSignatureHandle(Handle handle) : this(handle._value) { @@ -8042,33 +5323,31 @@ internal TypeVariableSignatureHandle(int value) _Validate(); } - public static implicit operator Handle(TypeVariableSignatureHandle handle) + public override bool Equals(object obj) { - return new Handle(handle._value); - } // Handle + if (obj is TypeVariableSignatureHandle) + return _value == ((TypeVariableSignatureHandle)obj)._value; + else if (obj is Handle) + return _value == ((Handle)obj)._value; + else + return false; + } // Equals - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } // Offset + public bool Equals(TypeVariableSignatureHandle handle) => _value == handle._value; - public TypeVariableSignature GetTypeVariableSignature(MetadataReader reader) - { - return reader.GetTypeVariableSignature(this); - } // GetTypeVariableSignature + public bool Equals(Handle handle) => _value == handle._value; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } // IsNull + public override int GetHashCode() => (int)_value; - public Handle ToHandle(MetadataReader reader) - { - return reader.ToHandle(this); - } // ToHandle + public static implicit operator Handle(TypeVariableSignatureHandle handle) + => new Handle(handle._value); + + internal int Offset => (_value & 0x00FFFFFF); + + public TypeVariableSignature GetTypeVariableSignature(MetadataReader reader) + => new TypeVariableSignature(reader, this); + + public bool IsNil => (_value & 0x00FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() @@ -8077,19 +5356,16 @@ internal void _Validate() throw new ArgumentException(); } // _Validate - public override string ToString() - { - return string.Format("{0:X8}", _value); - } // ToString + public override string ToString() => string.Format("{0:X8}", _value); } // TypeVariableSignatureHandle #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct NamedArgumentHandleCollection + public readonly partial struct NamedArgumentHandleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal NamedArgumentHandleCollection(NativeReader reader, uint offset) { @@ -8117,7 +5393,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private NamedArgumentHandle _current; @@ -8155,10 +5431,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct MethodSemanticsHandleCollection + public readonly partial struct MethodSemanticsHandleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal MethodSemanticsHandleCollection(NativeReader reader, uint offset) { @@ -8186,7 +5462,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private MethodSemanticsHandle _current; @@ -8224,10 +5500,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct CustomAttributeHandleCollection + public readonly partial struct CustomAttributeHandleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal CustomAttributeHandleCollection(NativeReader reader, uint offset) { @@ -8255,7 +5531,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private CustomAttributeHandle _current; @@ -8293,10 +5569,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ParameterHandleCollection + public readonly partial struct ParameterHandleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal ParameterHandleCollection(NativeReader reader, uint offset) { @@ -8324,7 +5600,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private ParameterHandle _current; @@ -8362,10 +5638,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct GenericParameterHandleCollection + public readonly partial struct GenericParameterHandleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal GenericParameterHandleCollection(NativeReader reader, uint offset) { @@ -8393,7 +5669,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private GenericParameterHandle _current; @@ -8431,10 +5707,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct TypeDefinitionHandleCollection + public readonly partial struct TypeDefinitionHandleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal TypeDefinitionHandleCollection(NativeReader reader, uint offset) { @@ -8462,7 +5738,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private TypeDefinitionHandle _current; @@ -8500,10 +5776,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct TypeForwarderHandleCollection + public readonly partial struct TypeForwarderHandleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal TypeForwarderHandleCollection(NativeReader reader, uint offset) { @@ -8531,7 +5807,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private TypeForwarderHandle _current; @@ -8569,10 +5845,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct NamespaceDefinitionHandleCollection + public readonly partial struct NamespaceDefinitionHandleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal NamespaceDefinitionHandleCollection(NativeReader reader, uint offset) { @@ -8600,7 +5876,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private NamespaceDefinitionHandle _current; @@ -8638,10 +5914,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct MethodHandleCollection + public readonly partial struct MethodHandleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal MethodHandleCollection(NativeReader reader, uint offset) { @@ -8669,7 +5945,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private MethodHandle _current; @@ -8707,10 +5983,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct FieldHandleCollection + public readonly partial struct FieldHandleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal FieldHandleCollection(NativeReader reader, uint offset) { @@ -8738,7 +6014,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private FieldHandle _current; @@ -8776,10 +6052,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct PropertyHandleCollection + public readonly partial struct PropertyHandleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal PropertyHandleCollection(NativeReader reader, uint offset) { @@ -8807,7 +6083,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private PropertyHandle _current; @@ -8845,10 +6121,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct EventHandleCollection + public readonly partial struct EventHandleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal EventHandleCollection(NativeReader reader, uint offset) { @@ -8876,7 +6152,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private EventHandle _current; @@ -8914,10 +6190,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ScopeDefinitionHandleCollection + public readonly partial struct ScopeDefinitionHandleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal ScopeDefinitionHandleCollection(NativeReader reader, uint offset) { @@ -8945,7 +6221,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private ScopeDefinitionHandle _current; @@ -8983,10 +6259,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct BooleanCollection + public readonly partial struct BooleanCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal BooleanCollection(NativeReader reader, uint offset) { @@ -9014,7 +6290,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private bool _current; @@ -9052,10 +6328,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct CharCollection + public readonly partial struct CharCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal CharCollection(NativeReader reader, uint offset) { @@ -9083,7 +6359,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private char _current; @@ -9121,10 +6397,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct ByteCollection + public readonly partial struct ByteCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal ByteCollection(NativeReader reader, uint offset) { @@ -9152,7 +6428,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private byte _current; @@ -9190,10 +6466,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct SByteCollection + public readonly partial struct SByteCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal SByteCollection(NativeReader reader, uint offset) { @@ -9221,7 +6497,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private sbyte _current; @@ -9259,10 +6535,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct Int16Collection + public readonly partial struct Int16Collection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal Int16Collection(NativeReader reader, uint offset) { @@ -9290,7 +6566,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private short _current; @@ -9328,10 +6604,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct UInt16Collection + public readonly partial struct UInt16Collection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal UInt16Collection(NativeReader reader, uint offset) { @@ -9359,7 +6635,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private ushort _current; @@ -9397,10 +6673,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct Int32Collection + public readonly partial struct Int32Collection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal Int32Collection(NativeReader reader, uint offset) { @@ -9428,7 +6704,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private int _current; @@ -9466,10 +6742,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct UInt32Collection + public readonly partial struct UInt32Collection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal UInt32Collection(NativeReader reader, uint offset) { @@ -9497,7 +6773,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private uint _current; @@ -9535,10 +6811,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct Int64Collection + public readonly partial struct Int64Collection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal Int64Collection(NativeReader reader, uint offset) { @@ -9566,7 +6842,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private long _current; @@ -9604,10 +6880,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct UInt64Collection + public readonly partial struct UInt64Collection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal UInt64Collection(NativeReader reader, uint offset) { @@ -9635,7 +6911,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private ulong _current; @@ -9673,10 +6949,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct SingleCollection + public readonly partial struct SingleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal SingleCollection(NativeReader reader, uint offset) { @@ -9704,7 +6980,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private float _current; @@ -9742,10 +7018,10 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct DoubleCollection + public readonly partial struct DoubleCollection { - private NativeReader _reader; - private uint _offset; + private readonly NativeReader _reader; + private readonly uint _offset; internal DoubleCollection(NativeReader reader, uint offset) { @@ -9773,7 +7049,7 @@ public Enumerator GetEnumerator() #endif public struct Enumerator { - private NativeReader _reader; + private readonly NativeReader _reader; private uint _offset; private uint _remaining; private double _current; @@ -9811,7 +7087,7 @@ public void Dispose() #if SYSTEM_PRIVATE_CORELIB [CLSCompliant(false)] #endif - public partial struct Handle + public readonly partial struct Handle { public ArraySignatureHandle ToArraySignatureHandle(MetadataReader reader) { @@ -9833,11 +7109,6 @@ public ConstantBooleanValueHandle ToConstantBooleanValueHandle(MetadataReader re return new ConstantBooleanValueHandle(this); } // ToConstantBooleanValueHandle - public ConstantBoxedEnumValueHandle ToConstantBoxedEnumValueHandle(MetadataReader reader) - { - return new ConstantBoxedEnumValueHandle(this); - } // ToConstantBoxedEnumValueHandle - public ConstantByteArrayHandle ToConstantByteArrayHandle(MetadataReader reader) { return new ConstantByteArrayHandle(this); @@ -9873,6 +7144,11 @@ public ConstantEnumArrayHandle ToConstantEnumArrayHandle(MetadataReader reader) return new ConstantEnumArrayHandle(this); } // ToConstantEnumArrayHandle + public ConstantEnumValueHandle ToConstantEnumValueHandle(MetadataReader reader) + { + return new ConstantEnumValueHandle(this); + } // ToConstantEnumValueHandle + public ConstantHandleArrayHandle ToConstantHandleArrayHandle(MetadataReader reader) { return new ConstantHandleArrayHandle(this); @@ -9975,1906 +7251,547 @@ public ConstantUInt64ValueHandle ToConstantUInt64ValueHandle(MetadataReader read public CustomAttributeHandle ToCustomAttributeHandle(MetadataReader reader) { - return new CustomAttributeHandle(this); - } // ToCustomAttributeHandle - - public EventHandle ToEventHandle(MetadataReader reader) - { - return new EventHandle(this); - } // ToEventHandle - - public FieldHandle ToFieldHandle(MetadataReader reader) - { - return new FieldHandle(this); - } // ToFieldHandle - - public FieldSignatureHandle ToFieldSignatureHandle(MetadataReader reader) - { - return new FieldSignatureHandle(this); - } // ToFieldSignatureHandle - - public FunctionPointerSignatureHandle ToFunctionPointerSignatureHandle(MetadataReader reader) - { - return new FunctionPointerSignatureHandle(this); - } // ToFunctionPointerSignatureHandle - - public GenericParameterHandle ToGenericParameterHandle(MetadataReader reader) - { - return new GenericParameterHandle(this); - } // ToGenericParameterHandle - - public MemberReferenceHandle ToMemberReferenceHandle(MetadataReader reader) - { - return new MemberReferenceHandle(this); - } // ToMemberReferenceHandle - - public MethodHandle ToMethodHandle(MetadataReader reader) - { - return new MethodHandle(this); - } // ToMethodHandle - - public MethodInstantiationHandle ToMethodInstantiationHandle(MetadataReader reader) - { - return new MethodInstantiationHandle(this); - } // ToMethodInstantiationHandle - - public MethodSemanticsHandle ToMethodSemanticsHandle(MetadataReader reader) - { - return new MethodSemanticsHandle(this); - } // ToMethodSemanticsHandle - - public MethodSignatureHandle ToMethodSignatureHandle(MetadataReader reader) - { - return new MethodSignatureHandle(this); - } // ToMethodSignatureHandle - - public MethodTypeVariableSignatureHandle ToMethodTypeVariableSignatureHandle(MetadataReader reader) - { - return new MethodTypeVariableSignatureHandle(this); - } // ToMethodTypeVariableSignatureHandle - - public ModifiedTypeHandle ToModifiedTypeHandle(MetadataReader reader) - { - return new ModifiedTypeHandle(this); - } // ToModifiedTypeHandle - - public NamedArgumentHandle ToNamedArgumentHandle(MetadataReader reader) - { - return new NamedArgumentHandle(this); - } // ToNamedArgumentHandle - - public NamespaceDefinitionHandle ToNamespaceDefinitionHandle(MetadataReader reader) - { - return new NamespaceDefinitionHandle(this); - } // ToNamespaceDefinitionHandle - - public NamespaceReferenceHandle ToNamespaceReferenceHandle(MetadataReader reader) - { - return new NamespaceReferenceHandle(this); - } // ToNamespaceReferenceHandle - - public ParameterHandle ToParameterHandle(MetadataReader reader) - { - return new ParameterHandle(this); - } // ToParameterHandle - - public PointerSignatureHandle ToPointerSignatureHandle(MetadataReader reader) - { - return new PointerSignatureHandle(this); - } // ToPointerSignatureHandle - - public PropertyHandle ToPropertyHandle(MetadataReader reader) - { - return new PropertyHandle(this); - } // ToPropertyHandle - - public PropertySignatureHandle ToPropertySignatureHandle(MetadataReader reader) - { - return new PropertySignatureHandle(this); - } // ToPropertySignatureHandle - - public QualifiedFieldHandle ToQualifiedFieldHandle(MetadataReader reader) - { - return new QualifiedFieldHandle(this); - } // ToQualifiedFieldHandle - - public QualifiedMethodHandle ToQualifiedMethodHandle(MetadataReader reader) - { - return new QualifiedMethodHandle(this); - } // ToQualifiedMethodHandle - - public SZArraySignatureHandle ToSZArraySignatureHandle(MetadataReader reader) - { - return new SZArraySignatureHandle(this); - } // ToSZArraySignatureHandle - - public ScopeDefinitionHandle ToScopeDefinitionHandle(MetadataReader reader) - { - return new ScopeDefinitionHandle(this); - } // ToScopeDefinitionHandle - - public ScopeReferenceHandle ToScopeReferenceHandle(MetadataReader reader) - { - return new ScopeReferenceHandle(this); - } // ToScopeReferenceHandle - - public TypeDefinitionHandle ToTypeDefinitionHandle(MetadataReader reader) - { - return new TypeDefinitionHandle(this); - } // ToTypeDefinitionHandle - - public TypeForwarderHandle ToTypeForwarderHandle(MetadataReader reader) - { - return new TypeForwarderHandle(this); - } // ToTypeForwarderHandle - - public TypeInstantiationSignatureHandle ToTypeInstantiationSignatureHandle(MetadataReader reader) - { - return new TypeInstantiationSignatureHandle(this); - } // ToTypeInstantiationSignatureHandle - - public TypeReferenceHandle ToTypeReferenceHandle(MetadataReader reader) - { - return new TypeReferenceHandle(this); - } // ToTypeReferenceHandle - - public TypeSpecificationHandle ToTypeSpecificationHandle(MetadataReader reader) - { - return new TypeSpecificationHandle(this); - } // ToTypeSpecificationHandle - - public TypeVariableSignatureHandle ToTypeVariableSignatureHandle(MetadataReader reader) - { - return new TypeVariableSignatureHandle(this); - } // ToTypeVariableSignatureHandle - } // Handle - -#if SYSTEM_PRIVATE_CORELIB - [CLSCompliant(false)] -#endif - public partial struct HandleCollection - { - private NativeReader _reader; - private uint _offset; - - internal HandleCollection(NativeReader reader, uint offset) - { - _offset = offset; - _reader = reader; - } - - public int Count - { - get - { - uint count; - _reader.DecodeUnsigned(_offset, out count); - return (int)count; - } - } // Count - - public Enumerator GetEnumerator() - { - return new Enumerator(_reader, _offset); - } // GetEnumerator - -#if SYSTEM_PRIVATE_CORELIB - [CLSCompliant(false)] -#endif - public struct Enumerator - { - private NativeReader _reader; - private uint _offset; - private uint _remaining; - private Handle _current; - - internal Enumerator(NativeReader reader, uint offset) - { - _reader = reader; - _offset = reader.DecodeUnsigned(offset, out _remaining); - _current = default(Handle); - } - - public Handle Current - { - get - { - return _current; - } - } // Current - - public bool MoveNext() - { - if (_remaining == 0) - return false; - _remaining--; - _offset = _reader.Read(_offset, out _current); - return true; - } // MoveNext - - public void Dispose() - { - } // Dispose - } // Enumerator - } // HandleCollection - -#if SYSTEM_PRIVATE_CORELIB - [CLSCompliant(false)] -#endif - public partial class MetadataReader - { - public ArraySignature GetArraySignature(ArraySignatureHandle handle) - { - ArraySignature record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._elementType); - offset = _streamReader.Read(offset, out record._rank); - offset = _streamReader.Read(offset, out record._sizes); - offset = _streamReader.Read(offset, out record._lowerBounds); - return record; - } // GetArraySignature - - public ByReferenceSignature GetByReferenceSignature(ByReferenceSignatureHandle handle) - { - ByReferenceSignature record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._type); - return record; - } // GetByReferenceSignature - - public ConstantBooleanArray GetConstantBooleanArray(ConstantBooleanArrayHandle handle) - { - ConstantBooleanArray record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantBooleanArray - - public ConstantBooleanValue GetConstantBooleanValue(ConstantBooleanValueHandle handle) - { - ConstantBooleanValue record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantBooleanValue - - public ConstantBoxedEnumValue GetConstantBoxedEnumValue(ConstantBoxedEnumValueHandle handle) - { - ConstantBoxedEnumValue record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - offset = _streamReader.Read(offset, out record._type); - return record; - } // GetConstantBoxedEnumValue - - public ConstantByteArray GetConstantByteArray(ConstantByteArrayHandle handle) - { - ConstantByteArray record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantByteArray - - public ConstantByteValue GetConstantByteValue(ConstantByteValueHandle handle) - { - ConstantByteValue record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantByteValue - - public ConstantCharArray GetConstantCharArray(ConstantCharArrayHandle handle) - { - ConstantCharArray record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantCharArray - - public ConstantCharValue GetConstantCharValue(ConstantCharValueHandle handle) - { - ConstantCharValue record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantCharValue - - public ConstantDoubleArray GetConstantDoubleArray(ConstantDoubleArrayHandle handle) - { - ConstantDoubleArray record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantDoubleArray - - public ConstantDoubleValue GetConstantDoubleValue(ConstantDoubleValueHandle handle) - { - ConstantDoubleValue record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantDoubleValue - - public ConstantEnumArray GetConstantEnumArray(ConstantEnumArrayHandle handle) - { - ConstantEnumArray record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._elementType); - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantEnumArray - - public ConstantHandleArray GetConstantHandleArray(ConstantHandleArrayHandle handle) - { - ConstantHandleArray record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantHandleArray - - public ConstantInt16Array GetConstantInt16Array(ConstantInt16ArrayHandle handle) - { - ConstantInt16Array record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantInt16Array - - public ConstantInt16Value GetConstantInt16Value(ConstantInt16ValueHandle handle) - { - ConstantInt16Value record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantInt16Value - - public ConstantInt32Array GetConstantInt32Array(ConstantInt32ArrayHandle handle) - { - ConstantInt32Array record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantInt32Array - - public ConstantInt32Value GetConstantInt32Value(ConstantInt32ValueHandle handle) - { - ConstantInt32Value record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantInt32Value - - public ConstantInt64Array GetConstantInt64Array(ConstantInt64ArrayHandle handle) - { - ConstantInt64Array record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantInt64Array - - public ConstantInt64Value GetConstantInt64Value(ConstantInt64ValueHandle handle) - { - ConstantInt64Value record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantInt64Value - - public ConstantReferenceValue GetConstantReferenceValue(ConstantReferenceValueHandle handle) - { - ConstantReferenceValue record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - return record; - } // GetConstantReferenceValue - - public ConstantSByteArray GetConstantSByteArray(ConstantSByteArrayHandle handle) - { - ConstantSByteArray record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantSByteArray - - public ConstantSByteValue GetConstantSByteValue(ConstantSByteValueHandle handle) - { - ConstantSByteValue record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantSByteValue - - public ConstantSingleArray GetConstantSingleArray(ConstantSingleArrayHandle handle) - { - ConstantSingleArray record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantSingleArray - - public ConstantSingleValue GetConstantSingleValue(ConstantSingleValueHandle handle) - { - ConstantSingleValue record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantSingleValue - - public ConstantStringArray GetConstantStringArray(ConstantStringArrayHandle handle) - { - ConstantStringArray record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantStringArray - - public ConstantStringValue GetConstantStringValue(ConstantStringValueHandle handle) - { - if (IsNull(handle)) - return new ConstantStringValue(); - ConstantStringValue record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantStringValue - - public ConstantUInt16Array GetConstantUInt16Array(ConstantUInt16ArrayHandle handle) - { - ConstantUInt16Array record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantUInt16Array - - public ConstantUInt16Value GetConstantUInt16Value(ConstantUInt16ValueHandle handle) - { - ConstantUInt16Value record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantUInt16Value - - public ConstantUInt32Array GetConstantUInt32Array(ConstantUInt32ArrayHandle handle) - { - ConstantUInt32Array record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantUInt32Array - - public ConstantUInt32Value GetConstantUInt32Value(ConstantUInt32ValueHandle handle) - { - ConstantUInt32Value record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantUInt32Value - - public ConstantUInt64Array GetConstantUInt64Array(ConstantUInt64ArrayHandle handle) - { - ConstantUInt64Array record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantUInt64Array - - public ConstantUInt64Value GetConstantUInt64Value(ConstantUInt64ValueHandle handle) - { - ConstantUInt64Value record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetConstantUInt64Value - - public CustomAttribute GetCustomAttribute(CustomAttributeHandle handle) - { - CustomAttribute record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._constructor); - offset = _streamReader.Read(offset, out record._fixedArguments); - offset = _streamReader.Read(offset, out record._namedArguments); - return record; - } // GetCustomAttribute - - public Event GetEvent(EventHandle handle) - { - Event record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._flags); - offset = _streamReader.Read(offset, out record._name); - offset = _streamReader.Read(offset, out record._type); - offset = _streamReader.Read(offset, out record._methodSemantics); - offset = _streamReader.Read(offset, out record._customAttributes); - return record; - } // GetEvent - - public Field GetField(FieldHandle handle) - { - Field record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._flags); - offset = _streamReader.Read(offset, out record._name); - offset = _streamReader.Read(offset, out record._signature); - offset = _streamReader.Read(offset, out record._defaultValue); - offset = _streamReader.Read(offset, out record._offset); - offset = _streamReader.Read(offset, out record._customAttributes); - return record; - } // GetField - - public FieldSignature GetFieldSignature(FieldSignatureHandle handle) - { - FieldSignature record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._type); - return record; - } // GetFieldSignature - - public FunctionPointerSignature GetFunctionPointerSignature(FunctionPointerSignatureHandle handle) - { - FunctionPointerSignature record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._signature); - return record; - } // GetFunctionPointerSignature - - public GenericParameter GetGenericParameter(GenericParameterHandle handle) - { - GenericParameter record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._number); - offset = _streamReader.Read(offset, out record._flags); - offset = _streamReader.Read(offset, out record._kind); - offset = _streamReader.Read(offset, out record._name); - offset = _streamReader.Read(offset, out record._constraints); - offset = _streamReader.Read(offset, out record._customAttributes); - return record; - } // GetGenericParameter - - public MemberReference GetMemberReference(MemberReferenceHandle handle) - { - MemberReference record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._parent); - offset = _streamReader.Read(offset, out record._name); - offset = _streamReader.Read(offset, out record._signature); - return record; - } // GetMemberReference - - public Method GetMethod(MethodHandle handle) - { - Method record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._flags); - offset = _streamReader.Read(offset, out record._implFlags); - offset = _streamReader.Read(offset, out record._name); - offset = _streamReader.Read(offset, out record._signature); - offset = _streamReader.Read(offset, out record._parameters); - offset = _streamReader.Read(offset, out record._genericParameters); - offset = _streamReader.Read(offset, out record._customAttributes); - return record; - } // GetMethod - - public MethodInstantiation GetMethodInstantiation(MethodInstantiationHandle handle) - { - MethodInstantiation record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._method); - offset = _streamReader.Read(offset, out record._genericTypeArguments); - return record; - } // GetMethodInstantiation - - public MethodSemantics GetMethodSemantics(MethodSemanticsHandle handle) - { - MethodSemantics record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._attributes); - offset = _streamReader.Read(offset, out record._method); - return record; - } // GetMethodSemantics - - public MethodSignature GetMethodSignature(MethodSignatureHandle handle) - { - MethodSignature record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._callingConvention); - offset = _streamReader.Read(offset, out record._genericParameterCount); - offset = _streamReader.Read(offset, out record._returnType); - offset = _streamReader.Read(offset, out record._parameters); - offset = _streamReader.Read(offset, out record._varArgParameters); - return record; - } // GetMethodSignature - - public MethodTypeVariableSignature GetMethodTypeVariableSignature(MethodTypeVariableSignatureHandle handle) - { - MethodTypeVariableSignature record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._number); - return record; - } // GetMethodTypeVariableSignature - - public ModifiedType GetModifiedType(ModifiedTypeHandle handle) - { - ModifiedType record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._isOptional); - offset = _streamReader.Read(offset, out record._modifierType); - offset = _streamReader.Read(offset, out record._type); - return record; - } // GetModifiedType - - public NamedArgument GetNamedArgument(NamedArgumentHandle handle) - { - NamedArgument record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._flags); - offset = _streamReader.Read(offset, out record._name); - offset = _streamReader.Read(offset, out record._type); - offset = _streamReader.Read(offset, out record._value); - return record; - } // GetNamedArgument - - public NamespaceDefinition GetNamespaceDefinition(NamespaceDefinitionHandle handle) - { - NamespaceDefinition record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._parentScopeOrNamespace); - offset = _streamReader.Read(offset, out record._name); - offset = _streamReader.Read(offset, out record._typeDefinitions); - offset = _streamReader.Read(offset, out record._typeForwarders); - offset = _streamReader.Read(offset, out record._namespaceDefinitions); - return record; - } // GetNamespaceDefinition - - public NamespaceReference GetNamespaceReference(NamespaceReferenceHandle handle) - { - NamespaceReference record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._parentScopeOrNamespace); - offset = _streamReader.Read(offset, out record._name); - return record; - } // GetNamespaceReference - - public Parameter GetParameter(ParameterHandle handle) - { - Parameter record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._flags); - offset = _streamReader.Read(offset, out record._sequence); - offset = _streamReader.Read(offset, out record._name); - offset = _streamReader.Read(offset, out record._defaultValue); - offset = _streamReader.Read(offset, out record._customAttributes); - return record; - } // GetParameter - - public PointerSignature GetPointerSignature(PointerSignatureHandle handle) - { - PointerSignature record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._type); - return record; - } // GetPointerSignature - - public Property GetProperty(PropertyHandle handle) - { - Property record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._flags); - offset = _streamReader.Read(offset, out record._name); - offset = _streamReader.Read(offset, out record._signature); - offset = _streamReader.Read(offset, out record._methodSemantics); - offset = _streamReader.Read(offset, out record._defaultValue); - offset = _streamReader.Read(offset, out record._customAttributes); - return record; - } // GetProperty - - public PropertySignature GetPropertySignature(PropertySignatureHandle handle) - { - PropertySignature record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._callingConvention); - offset = _streamReader.Read(offset, out record._type); - offset = _streamReader.Read(offset, out record._parameters); - return record; - } // GetPropertySignature - - public QualifiedField GetQualifiedField(QualifiedFieldHandle handle) - { - QualifiedField record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._field); - offset = _streamReader.Read(offset, out record._enclosingType); - return record; - } // GetQualifiedField - - public QualifiedMethod GetQualifiedMethod(QualifiedMethodHandle handle) - { - QualifiedMethod record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._method); - offset = _streamReader.Read(offset, out record._enclosingType); - return record; - } // GetQualifiedMethod - - public SZArraySignature GetSZArraySignature(SZArraySignatureHandle handle) - { - SZArraySignature record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._elementType); - return record; - } // GetSZArraySignature - - public ScopeDefinition GetScopeDefinition(ScopeDefinitionHandle handle) - { - ScopeDefinition record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._flags); - offset = _streamReader.Read(offset, out record._name); - offset = _streamReader.Read(offset, out record._hashAlgorithm); - offset = _streamReader.Read(offset, out record._majorVersion); - offset = _streamReader.Read(offset, out record._minorVersion); - offset = _streamReader.Read(offset, out record._buildNumber); - offset = _streamReader.Read(offset, out record._revisionNumber); - offset = _streamReader.Read(offset, out record._publicKey); - offset = _streamReader.Read(offset, out record._culture); - offset = _streamReader.Read(offset, out record._rootNamespaceDefinition); - offset = _streamReader.Read(offset, out record._entryPoint); - offset = _streamReader.Read(offset, out record._globalModuleType); - offset = _streamReader.Read(offset, out record._customAttributes); - offset = _streamReader.Read(offset, out record._moduleName); - offset = _streamReader.Read(offset, out record._mvid); - offset = _streamReader.Read(offset, out record._moduleCustomAttributes); - return record; - } // GetScopeDefinition - - public ScopeReference GetScopeReference(ScopeReferenceHandle handle) - { - ScopeReference record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._flags); - offset = _streamReader.Read(offset, out record._name); - offset = _streamReader.Read(offset, out record._majorVersion); - offset = _streamReader.Read(offset, out record._minorVersion); - offset = _streamReader.Read(offset, out record._buildNumber); - offset = _streamReader.Read(offset, out record._revisionNumber); - offset = _streamReader.Read(offset, out record._publicKeyOrToken); - offset = _streamReader.Read(offset, out record._culture); - return record; - } // GetScopeReference - - public TypeDefinition GetTypeDefinition(TypeDefinitionHandle handle) - { - TypeDefinition record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._flags); - offset = _streamReader.Read(offset, out record._baseType); - offset = _streamReader.Read(offset, out record._namespaceDefinition); - offset = _streamReader.Read(offset, out record._name); - offset = _streamReader.Read(offset, out record._size); - offset = _streamReader.Read(offset, out record._packingSize); - offset = _streamReader.Read(offset, out record._enclosingType); - offset = _streamReader.Read(offset, out record._nestedTypes); - offset = _streamReader.Read(offset, out record._methods); - offset = _streamReader.Read(offset, out record._fields); - offset = _streamReader.Read(offset, out record._properties); - offset = _streamReader.Read(offset, out record._events); - offset = _streamReader.Read(offset, out record._genericParameters); - offset = _streamReader.Read(offset, out record._interfaces); - offset = _streamReader.Read(offset, out record._customAttributes); - return record; - } // GetTypeDefinition - - public TypeForwarder GetTypeForwarder(TypeForwarderHandle handle) - { - TypeForwarder record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._scope); - offset = _streamReader.Read(offset, out record._name); - offset = _streamReader.Read(offset, out record._nestedTypes); - return record; - } // GetTypeForwarder - - public TypeInstantiationSignature GetTypeInstantiationSignature(TypeInstantiationSignatureHandle handle) - { - TypeInstantiationSignature record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._genericType); - offset = _streamReader.Read(offset, out record._genericTypeArguments); - return record; - } // GetTypeInstantiationSignature - - public TypeReference GetTypeReference(TypeReferenceHandle handle) - { - TypeReference record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._parentNamespaceOrType); - offset = _streamReader.Read(offset, out record._typeName); - return record; - } // GetTypeReference - - public TypeSpecification GetTypeSpecification(TypeSpecificationHandle handle) - { - TypeSpecification record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._signature); - return record; - } // GetTypeSpecification - - public TypeVariableSignature GetTypeVariableSignature(TypeVariableSignatureHandle handle) - { - TypeVariableSignature record; - record._reader = this; - record._handle = handle; - var offset = (uint)handle.Offset; - offset = _streamReader.Read(offset, out record._number); - return record; - } // GetTypeVariableSignature - - internal Handle ToHandle(ArraySignatureHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ByReferenceSignatureHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantBooleanArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantBooleanValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantBoxedEnumValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantByteArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantByteValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantCharArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantCharValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantDoubleArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantDoubleValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantEnumArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantHandleArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantInt16ArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantInt16ValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantInt32ArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantInt32ValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantInt64ArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantInt64ValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantReferenceValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantSByteArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantSByteValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantSingleArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantSingleValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantStringArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantStringValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantUInt16ArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantUInt16ValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantUInt32ArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantUInt32ValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantUInt64ArrayHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ConstantUInt64ValueHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(CustomAttributeHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(EventHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(FieldHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(FieldSignatureHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(FunctionPointerSignatureHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(GenericParameterHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(MemberReferenceHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(MethodHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(MethodInstantiationHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(MethodSemanticsHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(MethodSignatureHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(MethodTypeVariableSignatureHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ModifiedTypeHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(NamedArgumentHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(NamespaceDefinitionHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(NamespaceReferenceHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ParameterHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(PointerSignatureHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(PropertyHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(PropertySignatureHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(QualifiedFieldHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(QualifiedMethodHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(SZArraySignatureHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ScopeDefinitionHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(ScopeReferenceHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(TypeDefinitionHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(TypeForwarderHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(TypeInstantiationSignatureHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(TypeReferenceHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(TypeSpecificationHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal Handle ToHandle(TypeVariableSignatureHandle handle) - { - return new Handle(handle._value); - } // ToHandle - - internal ArraySignatureHandle ToArraySignatureHandle(Handle handle) - { - return new ArraySignatureHandle(handle._value); - } // ToArraySignatureHandle - - internal ByReferenceSignatureHandle ToByReferenceSignatureHandle(Handle handle) - { - return new ByReferenceSignatureHandle(handle._value); - } // ToByReferenceSignatureHandle - - internal ConstantBooleanArrayHandle ToConstantBooleanArrayHandle(Handle handle) - { - return new ConstantBooleanArrayHandle(handle._value); - } // ToConstantBooleanArrayHandle - - internal ConstantBooleanValueHandle ToConstantBooleanValueHandle(Handle handle) - { - return new ConstantBooleanValueHandle(handle._value); - } // ToConstantBooleanValueHandle - - internal ConstantBoxedEnumValueHandle ToConstantBoxedEnumValueHandle(Handle handle) - { - return new ConstantBoxedEnumValueHandle(handle._value); - } // ToConstantBoxedEnumValueHandle - - internal ConstantByteArrayHandle ToConstantByteArrayHandle(Handle handle) - { - return new ConstantByteArrayHandle(handle._value); - } // ToConstantByteArrayHandle - - internal ConstantByteValueHandle ToConstantByteValueHandle(Handle handle) - { - return new ConstantByteValueHandle(handle._value); - } // ToConstantByteValueHandle - - internal ConstantCharArrayHandle ToConstantCharArrayHandle(Handle handle) - { - return new ConstantCharArrayHandle(handle._value); - } // ToConstantCharArrayHandle - - internal ConstantCharValueHandle ToConstantCharValueHandle(Handle handle) - { - return new ConstantCharValueHandle(handle._value); - } // ToConstantCharValueHandle - - internal ConstantDoubleArrayHandle ToConstantDoubleArrayHandle(Handle handle) - { - return new ConstantDoubleArrayHandle(handle._value); - } // ToConstantDoubleArrayHandle - - internal ConstantDoubleValueHandle ToConstantDoubleValueHandle(Handle handle) - { - return new ConstantDoubleValueHandle(handle._value); - } // ToConstantDoubleValueHandle - - internal ConstantEnumArrayHandle ToConstantEnumArrayHandle(Handle handle) - { - return new ConstantEnumArrayHandle(handle._value); - } // ToConstantEnumArrayHandle - - internal ConstantHandleArrayHandle ToConstantHandleArrayHandle(Handle handle) - { - return new ConstantHandleArrayHandle(handle._value); - } // ToConstantHandleArrayHandle - - internal ConstantInt16ArrayHandle ToConstantInt16ArrayHandle(Handle handle) - { - return new ConstantInt16ArrayHandle(handle._value); - } // ToConstantInt16ArrayHandle - - internal ConstantInt16ValueHandle ToConstantInt16ValueHandle(Handle handle) - { - return new ConstantInt16ValueHandle(handle._value); - } // ToConstantInt16ValueHandle - - internal ConstantInt32ArrayHandle ToConstantInt32ArrayHandle(Handle handle) - { - return new ConstantInt32ArrayHandle(handle._value); - } // ToConstantInt32ArrayHandle - - internal ConstantInt32ValueHandle ToConstantInt32ValueHandle(Handle handle) - { - return new ConstantInt32ValueHandle(handle._value); - } // ToConstantInt32ValueHandle - - internal ConstantInt64ArrayHandle ToConstantInt64ArrayHandle(Handle handle) - { - return new ConstantInt64ArrayHandle(handle._value); - } // ToConstantInt64ArrayHandle - - internal ConstantInt64ValueHandle ToConstantInt64ValueHandle(Handle handle) - { - return new ConstantInt64ValueHandle(handle._value); - } // ToConstantInt64ValueHandle - - internal ConstantReferenceValueHandle ToConstantReferenceValueHandle(Handle handle) - { - return new ConstantReferenceValueHandle(handle._value); - } // ToConstantReferenceValueHandle - - internal ConstantSByteArrayHandle ToConstantSByteArrayHandle(Handle handle) - { - return new ConstantSByteArrayHandle(handle._value); - } // ToConstantSByteArrayHandle - - internal ConstantSByteValueHandle ToConstantSByteValueHandle(Handle handle) - { - return new ConstantSByteValueHandle(handle._value); - } // ToConstantSByteValueHandle - - internal ConstantSingleArrayHandle ToConstantSingleArrayHandle(Handle handle) - { - return new ConstantSingleArrayHandle(handle._value); - } // ToConstantSingleArrayHandle - - internal ConstantSingleValueHandle ToConstantSingleValueHandle(Handle handle) - { - return new ConstantSingleValueHandle(handle._value); - } // ToConstantSingleValueHandle - - internal ConstantStringArrayHandle ToConstantStringArrayHandle(Handle handle) - { - return new ConstantStringArrayHandle(handle._value); - } // ToConstantStringArrayHandle - - internal ConstantStringValueHandle ToConstantStringValueHandle(Handle handle) - { - return new ConstantStringValueHandle(handle._value); - } // ToConstantStringValueHandle - - internal ConstantUInt16ArrayHandle ToConstantUInt16ArrayHandle(Handle handle) - { - return new ConstantUInt16ArrayHandle(handle._value); - } // ToConstantUInt16ArrayHandle - - internal ConstantUInt16ValueHandle ToConstantUInt16ValueHandle(Handle handle) - { - return new ConstantUInt16ValueHandle(handle._value); - } // ToConstantUInt16ValueHandle - - internal ConstantUInt32ArrayHandle ToConstantUInt32ArrayHandle(Handle handle) - { - return new ConstantUInt32ArrayHandle(handle._value); - } // ToConstantUInt32ArrayHandle - - internal ConstantUInt32ValueHandle ToConstantUInt32ValueHandle(Handle handle) - { - return new ConstantUInt32ValueHandle(handle._value); - } // ToConstantUInt32ValueHandle - - internal ConstantUInt64ArrayHandle ToConstantUInt64ArrayHandle(Handle handle) - { - return new ConstantUInt64ArrayHandle(handle._value); - } // ToConstantUInt64ArrayHandle - - internal ConstantUInt64ValueHandle ToConstantUInt64ValueHandle(Handle handle) - { - return new ConstantUInt64ValueHandle(handle._value); - } // ToConstantUInt64ValueHandle - - internal CustomAttributeHandle ToCustomAttributeHandle(Handle handle) - { - return new CustomAttributeHandle(handle._value); + return new CustomAttributeHandle(this); } // ToCustomAttributeHandle - internal EventHandle ToEventHandle(Handle handle) + public EventHandle ToEventHandle(MetadataReader reader) { - return new EventHandle(handle._value); + return new EventHandle(this); } // ToEventHandle - internal FieldHandle ToFieldHandle(Handle handle) + public FieldHandle ToFieldHandle(MetadataReader reader) { - return new FieldHandle(handle._value); + return new FieldHandle(this); } // ToFieldHandle - internal FieldSignatureHandle ToFieldSignatureHandle(Handle handle) + public FieldSignatureHandle ToFieldSignatureHandle(MetadataReader reader) { - return new FieldSignatureHandle(handle._value); + return new FieldSignatureHandle(this); } // ToFieldSignatureHandle - internal FunctionPointerSignatureHandle ToFunctionPointerSignatureHandle(Handle handle) + public FunctionPointerSignatureHandle ToFunctionPointerSignatureHandle(MetadataReader reader) { - return new FunctionPointerSignatureHandle(handle._value); + return new FunctionPointerSignatureHandle(this); } // ToFunctionPointerSignatureHandle - internal GenericParameterHandle ToGenericParameterHandle(Handle handle) + public GenericParameterHandle ToGenericParameterHandle(MetadataReader reader) { - return new GenericParameterHandle(handle._value); + return new GenericParameterHandle(this); } // ToGenericParameterHandle - internal MemberReferenceHandle ToMemberReferenceHandle(Handle handle) + public MemberReferenceHandle ToMemberReferenceHandle(MetadataReader reader) { - return new MemberReferenceHandle(handle._value); + return new MemberReferenceHandle(this); } // ToMemberReferenceHandle - internal MethodHandle ToMethodHandle(Handle handle) + public MethodHandle ToMethodHandle(MetadataReader reader) { - return new MethodHandle(handle._value); + return new MethodHandle(this); } // ToMethodHandle - internal MethodInstantiationHandle ToMethodInstantiationHandle(Handle handle) + public MethodInstantiationHandle ToMethodInstantiationHandle(MetadataReader reader) { - return new MethodInstantiationHandle(handle._value); + return new MethodInstantiationHandle(this); } // ToMethodInstantiationHandle - internal MethodSemanticsHandle ToMethodSemanticsHandle(Handle handle) + public MethodSemanticsHandle ToMethodSemanticsHandle(MetadataReader reader) { - return new MethodSemanticsHandle(handle._value); + return new MethodSemanticsHandle(this); } // ToMethodSemanticsHandle - internal MethodSignatureHandle ToMethodSignatureHandle(Handle handle) + public MethodSignatureHandle ToMethodSignatureHandle(MetadataReader reader) { - return new MethodSignatureHandle(handle._value); + return new MethodSignatureHandle(this); } // ToMethodSignatureHandle - internal MethodTypeVariableSignatureHandle ToMethodTypeVariableSignatureHandle(Handle handle) + public MethodTypeVariableSignatureHandle ToMethodTypeVariableSignatureHandle(MetadataReader reader) { - return new MethodTypeVariableSignatureHandle(handle._value); + return new MethodTypeVariableSignatureHandle(this); } // ToMethodTypeVariableSignatureHandle - internal ModifiedTypeHandle ToModifiedTypeHandle(Handle handle) + public ModifiedTypeHandle ToModifiedTypeHandle(MetadataReader reader) { - return new ModifiedTypeHandle(handle._value); + return new ModifiedTypeHandle(this); } // ToModifiedTypeHandle - internal NamedArgumentHandle ToNamedArgumentHandle(Handle handle) + public NamedArgumentHandle ToNamedArgumentHandle(MetadataReader reader) { - return new NamedArgumentHandle(handle._value); + return new NamedArgumentHandle(this); } // ToNamedArgumentHandle - internal NamespaceDefinitionHandle ToNamespaceDefinitionHandle(Handle handle) + public NamespaceDefinitionHandle ToNamespaceDefinitionHandle(MetadataReader reader) { - return new NamespaceDefinitionHandle(handle._value); + return new NamespaceDefinitionHandle(this); } // ToNamespaceDefinitionHandle - internal NamespaceReferenceHandle ToNamespaceReferenceHandle(Handle handle) + public NamespaceReferenceHandle ToNamespaceReferenceHandle(MetadataReader reader) { - return new NamespaceReferenceHandle(handle._value); + return new NamespaceReferenceHandle(this); } // ToNamespaceReferenceHandle - internal ParameterHandle ToParameterHandle(Handle handle) + public ParameterHandle ToParameterHandle(MetadataReader reader) { - return new ParameterHandle(handle._value); + return new ParameterHandle(this); } // ToParameterHandle - internal PointerSignatureHandle ToPointerSignatureHandle(Handle handle) + public PointerSignatureHandle ToPointerSignatureHandle(MetadataReader reader) { - return new PointerSignatureHandle(handle._value); + return new PointerSignatureHandle(this); } // ToPointerSignatureHandle - internal PropertyHandle ToPropertyHandle(Handle handle) + public PropertyHandle ToPropertyHandle(MetadataReader reader) { - return new PropertyHandle(handle._value); + return new PropertyHandle(this); } // ToPropertyHandle - internal PropertySignatureHandle ToPropertySignatureHandle(Handle handle) + public PropertySignatureHandle ToPropertySignatureHandle(MetadataReader reader) { - return new PropertySignatureHandle(handle._value); + return new PropertySignatureHandle(this); } // ToPropertySignatureHandle - internal QualifiedFieldHandle ToQualifiedFieldHandle(Handle handle) + public QualifiedFieldHandle ToQualifiedFieldHandle(MetadataReader reader) { - return new QualifiedFieldHandle(handle._value); + return new QualifiedFieldHandle(this); } // ToQualifiedFieldHandle - internal QualifiedMethodHandle ToQualifiedMethodHandle(Handle handle) + public QualifiedMethodHandle ToQualifiedMethodHandle(MetadataReader reader) { - return new QualifiedMethodHandle(handle._value); + return new QualifiedMethodHandle(this); } // ToQualifiedMethodHandle - internal SZArraySignatureHandle ToSZArraySignatureHandle(Handle handle) + public SZArraySignatureHandle ToSZArraySignatureHandle(MetadataReader reader) { - return new SZArraySignatureHandle(handle._value); + return new SZArraySignatureHandle(this); } // ToSZArraySignatureHandle - internal ScopeDefinitionHandle ToScopeDefinitionHandle(Handle handle) + public ScopeDefinitionHandle ToScopeDefinitionHandle(MetadataReader reader) { - return new ScopeDefinitionHandle(handle._value); + return new ScopeDefinitionHandle(this); } // ToScopeDefinitionHandle - internal ScopeReferenceHandle ToScopeReferenceHandle(Handle handle) + public ScopeReferenceHandle ToScopeReferenceHandle(MetadataReader reader) { - return new ScopeReferenceHandle(handle._value); + return new ScopeReferenceHandle(this); } // ToScopeReferenceHandle - internal TypeDefinitionHandle ToTypeDefinitionHandle(Handle handle) + public TypeDefinitionHandle ToTypeDefinitionHandle(MetadataReader reader) { - return new TypeDefinitionHandle(handle._value); + return new TypeDefinitionHandle(this); } // ToTypeDefinitionHandle - internal TypeForwarderHandle ToTypeForwarderHandle(Handle handle) + public TypeForwarderHandle ToTypeForwarderHandle(MetadataReader reader) { - return new TypeForwarderHandle(handle._value); + return new TypeForwarderHandle(this); } // ToTypeForwarderHandle - internal TypeInstantiationSignatureHandle ToTypeInstantiationSignatureHandle(Handle handle) + public TypeInstantiationSignatureHandle ToTypeInstantiationSignatureHandle(MetadataReader reader) { - return new TypeInstantiationSignatureHandle(handle._value); + return new TypeInstantiationSignatureHandle(this); } // ToTypeInstantiationSignatureHandle - internal TypeReferenceHandle ToTypeReferenceHandle(Handle handle) + public TypeReferenceHandle ToTypeReferenceHandle(MetadataReader reader) { - return new TypeReferenceHandle(handle._value); + return new TypeReferenceHandle(this); } // ToTypeReferenceHandle - internal TypeSpecificationHandle ToTypeSpecificationHandle(Handle handle) + public TypeSpecificationHandle ToTypeSpecificationHandle(MetadataReader reader) { - return new TypeSpecificationHandle(handle._value); + return new TypeSpecificationHandle(this); } // ToTypeSpecificationHandle - internal TypeVariableSignatureHandle ToTypeVariableSignatureHandle(Handle handle) + public TypeVariableSignatureHandle ToTypeVariableSignatureHandle(MetadataReader reader) { - return new TypeVariableSignatureHandle(handle._value); + return new TypeVariableSignatureHandle(this); } // ToTypeVariableSignatureHandle + } // Handle + +#if SYSTEM_PRIVATE_CORELIB + [CLSCompliant(false)] +#endif + public readonly partial struct HandleCollection + { + private readonly NativeReader _reader; + private readonly uint _offset; + + internal HandleCollection(NativeReader reader, uint offset) + { + _offset = offset; + _reader = reader; + } + + public int Count + { + get + { + uint count; + _reader.DecodeUnsigned(_offset, out count); + return (int)count; + } + } // Count + + public Enumerator GetEnumerator() + { + return new Enumerator(_reader, _offset); + } // GetEnumerator + +#if SYSTEM_PRIVATE_CORELIB + [CLSCompliant(false)] +#endif + public struct Enumerator + { + private readonly NativeReader _reader; + private uint _offset; + private uint _remaining; + private Handle _current; + + internal Enumerator(NativeReader reader, uint offset) + { + _reader = reader; + _offset = reader.DecodeUnsigned(offset, out _remaining); + _current = default(Handle); + } + + public Handle Current + { + get + { + return _current; + } + } // Current - internal bool IsNull(ArraySignatureHandle handle) + public bool MoveNext() + { + if (_remaining == 0) + return false; + _remaining--; + _offset = _reader.Read(_offset, out _current); + return true; + } // MoveNext + + public void Dispose() + { + } // Dispose + } // Enumerator + } // HandleCollection + +#if SYSTEM_PRIVATE_CORELIB + [CLSCompliant(false)] +#endif + public partial class MetadataReader + { + public ArraySignature GetArraySignature(ArraySignatureHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ArraySignature(this, handle); + } // GetArraySignature - internal bool IsNull(ByReferenceSignatureHandle handle) + public ByReferenceSignature GetByReferenceSignature(ByReferenceSignatureHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ByReferenceSignature(this, handle); + } // GetByReferenceSignature - internal bool IsNull(ConstantBooleanArrayHandle handle) + public ConstantBooleanArray GetConstantBooleanArray(ConstantBooleanArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantBooleanArray(this, handle); + } // GetConstantBooleanArray - internal bool IsNull(ConstantBooleanValueHandle handle) + public ConstantBooleanValue GetConstantBooleanValue(ConstantBooleanValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantBooleanValue(this, handle); + } // GetConstantBooleanValue - internal bool IsNull(ConstantBoxedEnumValueHandle handle) + public ConstantByteArray GetConstantByteArray(ConstantByteArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantByteArray(this, handle); + } // GetConstantByteArray - internal bool IsNull(ConstantByteArrayHandle handle) + public ConstantByteValue GetConstantByteValue(ConstantByteValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantByteValue(this, handle); + } // GetConstantByteValue - internal bool IsNull(ConstantByteValueHandle handle) + public ConstantCharArray GetConstantCharArray(ConstantCharArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantCharArray(this, handle); + } // GetConstantCharArray - internal bool IsNull(ConstantCharArrayHandle handle) + public ConstantCharValue GetConstantCharValue(ConstantCharValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantCharValue(this, handle); + } // GetConstantCharValue - internal bool IsNull(ConstantCharValueHandle handle) + public ConstantDoubleArray GetConstantDoubleArray(ConstantDoubleArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantDoubleArray(this, handle); + } // GetConstantDoubleArray - internal bool IsNull(ConstantDoubleArrayHandle handle) + public ConstantDoubleValue GetConstantDoubleValue(ConstantDoubleValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantDoubleValue(this, handle); + } // GetConstantDoubleValue - internal bool IsNull(ConstantDoubleValueHandle handle) + public ConstantEnumArray GetConstantEnumArray(ConstantEnumArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantEnumArray(this, handle); + } // GetConstantEnumArray - internal bool IsNull(ConstantEnumArrayHandle handle) + public ConstantEnumValue GetConstantEnumValue(ConstantEnumValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantEnumValue(this, handle); + } // GetConstantEnumValue - internal bool IsNull(ConstantHandleArrayHandle handle) + public ConstantHandleArray GetConstantHandleArray(ConstantHandleArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantHandleArray(this, handle); + } // GetConstantHandleArray - internal bool IsNull(ConstantInt16ArrayHandle handle) + public ConstantInt16Array GetConstantInt16Array(ConstantInt16ArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantInt16Array(this, handle); + } // GetConstantInt16Array - internal bool IsNull(ConstantInt16ValueHandle handle) + public ConstantInt16Value GetConstantInt16Value(ConstantInt16ValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantInt16Value(this, handle); + } // GetConstantInt16Value - internal bool IsNull(ConstantInt32ArrayHandle handle) + public ConstantInt32Array GetConstantInt32Array(ConstantInt32ArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantInt32Array(this, handle); + } // GetConstantInt32Array - internal bool IsNull(ConstantInt32ValueHandle handle) + public ConstantInt32Value GetConstantInt32Value(ConstantInt32ValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantInt32Value(this, handle); + } // GetConstantInt32Value - internal bool IsNull(ConstantInt64ArrayHandle handle) + public ConstantInt64Array GetConstantInt64Array(ConstantInt64ArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantInt64Array(this, handle); + } // GetConstantInt64Array - internal bool IsNull(ConstantInt64ValueHandle handle) + public ConstantInt64Value GetConstantInt64Value(ConstantInt64ValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantInt64Value(this, handle); + } // GetConstantInt64Value - internal bool IsNull(ConstantReferenceValueHandle handle) + public ConstantReferenceValue GetConstantReferenceValue(ConstantReferenceValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantReferenceValue(this, handle); + } // GetConstantReferenceValue - internal bool IsNull(ConstantSByteArrayHandle handle) + public ConstantSByteArray GetConstantSByteArray(ConstantSByteArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantSByteArray(this, handle); + } // GetConstantSByteArray - internal bool IsNull(ConstantSByteValueHandle handle) + public ConstantSByteValue GetConstantSByteValue(ConstantSByteValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantSByteValue(this, handle); + } // GetConstantSByteValue - internal bool IsNull(ConstantSingleArrayHandle handle) + public ConstantSingleArray GetConstantSingleArray(ConstantSingleArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantSingleArray(this, handle); + } // GetConstantSingleArray - internal bool IsNull(ConstantSingleValueHandle handle) + public ConstantSingleValue GetConstantSingleValue(ConstantSingleValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantSingleValue(this, handle); + } // GetConstantSingleValue - internal bool IsNull(ConstantStringArrayHandle handle) + public ConstantStringArray GetConstantStringArray(ConstantStringArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantStringArray(this, handle); + } // GetConstantStringArray - internal bool IsNull(ConstantStringValueHandle handle) + public ConstantStringValue GetConstantStringValue(ConstantStringValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantStringValue(this, handle); + } // GetConstantStringValue - internal bool IsNull(ConstantUInt16ArrayHandle handle) + public ConstantUInt16Array GetConstantUInt16Array(ConstantUInt16ArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantUInt16Array(this, handle); + } // GetConstantUInt16Array - internal bool IsNull(ConstantUInt16ValueHandle handle) + public ConstantUInt16Value GetConstantUInt16Value(ConstantUInt16ValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantUInt16Value(this, handle); + } // GetConstantUInt16Value - internal bool IsNull(ConstantUInt32ArrayHandle handle) + public ConstantUInt32Array GetConstantUInt32Array(ConstantUInt32ArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantUInt32Array(this, handle); + } // GetConstantUInt32Array - internal bool IsNull(ConstantUInt32ValueHandle handle) + public ConstantUInt32Value GetConstantUInt32Value(ConstantUInt32ValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantUInt32Value(this, handle); + } // GetConstantUInt32Value - internal bool IsNull(ConstantUInt64ArrayHandle handle) + public ConstantUInt64Array GetConstantUInt64Array(ConstantUInt64ArrayHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantUInt64Array(this, handle); + } // GetConstantUInt64Array - internal bool IsNull(ConstantUInt64ValueHandle handle) + public ConstantUInt64Value GetConstantUInt64Value(ConstantUInt64ValueHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ConstantUInt64Value(this, handle); + } // GetConstantUInt64Value - internal bool IsNull(CustomAttributeHandle handle) + public CustomAttribute GetCustomAttribute(CustomAttributeHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new CustomAttribute(this, handle); + } // GetCustomAttribute - internal bool IsNull(EventHandle handle) + public Event GetEvent(EventHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new Event(this, handle); + } // GetEvent - internal bool IsNull(FieldHandle handle) + public Field GetField(FieldHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new Field(this, handle); + } // GetField - internal bool IsNull(FieldSignatureHandle handle) + public FieldSignature GetFieldSignature(FieldSignatureHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new FieldSignature(this, handle); + } // GetFieldSignature - internal bool IsNull(FunctionPointerSignatureHandle handle) + public FunctionPointerSignature GetFunctionPointerSignature(FunctionPointerSignatureHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new FunctionPointerSignature(this, handle); + } // GetFunctionPointerSignature - internal bool IsNull(GenericParameterHandle handle) + public GenericParameter GetGenericParameter(GenericParameterHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new GenericParameter(this, handle); + } // GetGenericParameter - internal bool IsNull(MemberReferenceHandle handle) + public MemberReference GetMemberReference(MemberReferenceHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new MemberReference(this, handle); + } // GetMemberReference - internal bool IsNull(MethodHandle handle) + public Method GetMethod(MethodHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new Method(this, handle); + } // GetMethod - internal bool IsNull(MethodInstantiationHandle handle) + public MethodInstantiation GetMethodInstantiation(MethodInstantiationHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new MethodInstantiation(this, handle); + } // GetMethodInstantiation - internal bool IsNull(MethodSemanticsHandle handle) + public MethodSemantics GetMethodSemantics(MethodSemanticsHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new MethodSemantics(this, handle); + } // GetMethodSemantics - internal bool IsNull(MethodSignatureHandle handle) + public MethodSignature GetMethodSignature(MethodSignatureHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new MethodSignature(this, handle); + } // GetMethodSignature - internal bool IsNull(MethodTypeVariableSignatureHandle handle) + public MethodTypeVariableSignature GetMethodTypeVariableSignature(MethodTypeVariableSignatureHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new MethodTypeVariableSignature(this, handle); + } // GetMethodTypeVariableSignature - internal bool IsNull(ModifiedTypeHandle handle) + public ModifiedType GetModifiedType(ModifiedTypeHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ModifiedType(this, handle); + } // GetModifiedType - internal bool IsNull(NamedArgumentHandle handle) + public NamedArgument GetNamedArgument(NamedArgumentHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new NamedArgument(this, handle); + } // GetNamedArgument - internal bool IsNull(NamespaceDefinitionHandle handle) + public NamespaceDefinition GetNamespaceDefinition(NamespaceDefinitionHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new NamespaceDefinition(this, handle); + } // GetNamespaceDefinition - internal bool IsNull(NamespaceReferenceHandle handle) + public NamespaceReference GetNamespaceReference(NamespaceReferenceHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new NamespaceReference(this, handle); + } // GetNamespaceReference - internal bool IsNull(ParameterHandle handle) + public Parameter GetParameter(ParameterHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new Parameter(this, handle); + } // GetParameter - internal bool IsNull(PointerSignatureHandle handle) + public PointerSignature GetPointerSignature(PointerSignatureHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new PointerSignature(this, handle); + } // GetPointerSignature - internal bool IsNull(PropertyHandle handle) + public Property GetProperty(PropertyHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new Property(this, handle); + } // GetProperty - internal bool IsNull(PropertySignatureHandle handle) + public PropertySignature GetPropertySignature(PropertySignatureHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new PropertySignature(this, handle); + } // GetPropertySignature - internal bool IsNull(QualifiedFieldHandle handle) + public QualifiedField GetQualifiedField(QualifiedFieldHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new QualifiedField(this, handle); + } // GetQualifiedField - internal bool IsNull(QualifiedMethodHandle handle) + public QualifiedMethod GetQualifiedMethod(QualifiedMethodHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new QualifiedMethod(this, handle); + } // GetQualifiedMethod - internal bool IsNull(SZArraySignatureHandle handle) + public SZArraySignature GetSZArraySignature(SZArraySignatureHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new SZArraySignature(this, handle); + } // GetSZArraySignature - internal bool IsNull(ScopeDefinitionHandle handle) + public ScopeDefinition GetScopeDefinition(ScopeDefinitionHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ScopeDefinition(this, handle); + } // GetScopeDefinition - internal bool IsNull(ScopeReferenceHandle handle) + public ScopeReference GetScopeReference(ScopeReferenceHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new ScopeReference(this, handle); + } // GetScopeReference - internal bool IsNull(TypeDefinitionHandle handle) + public TypeDefinition GetTypeDefinition(TypeDefinitionHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new TypeDefinition(this, handle); + } // GetTypeDefinition - internal bool IsNull(TypeForwarderHandle handle) + public TypeForwarder GetTypeForwarder(TypeForwarderHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new TypeForwarder(this, handle); + } // GetTypeForwarder - internal bool IsNull(TypeInstantiationSignatureHandle handle) + public TypeInstantiationSignature GetTypeInstantiationSignature(TypeInstantiationSignatureHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new TypeInstantiationSignature(this, handle); + } // GetTypeInstantiationSignature - internal bool IsNull(TypeReferenceHandle handle) + public TypeReference GetTypeReference(TypeReferenceHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new TypeReference(this, handle); + } // GetTypeReference - internal bool IsNull(TypeSpecificationHandle handle) + public TypeSpecification GetTypeSpecification(TypeSpecificationHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new TypeSpecification(this, handle); + } // GetTypeSpecification - internal bool IsNull(TypeVariableSignatureHandle handle) + public TypeVariableSignature GetTypeVariableSignature(TypeVariableSignatureHandle handle) { - return (handle._value & 0x00FFFFFF) == 0; - } // IsNull + return new TypeVariableSignature(this, handle); + } // GetTypeVariableSignature } // MetadataReader } // Internal.Metadata.NativeFormat diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs index 40b68f760b93..91c7b47d3c69 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs @@ -62,7 +62,7 @@ public enum PInvokeAttributes MaxValue = 0xFFFF, } - public partial struct Handle + public readonly partial struct Handle { public override bool Equals(object obj) { @@ -109,38 +109,17 @@ public Handle(HandleType type, int offset) _value = (int)type << 24 | (int)offset; } - public HandleType HandleType - { - get - { - return (HandleType)(_value >> 24); - } - } + public HandleType HandleType => (HandleType)(_value >> 24); - internal int Offset - { - get - { - return (this._value & 0x00FFFFFF); - } - } + internal int Offset => _value & 0x00FFFFFF; - public bool IsNull(MetadataReader reader) - { - return reader.IsNull(this); - } + public bool IsNil => (_value & 0x00FFFFFF) == 0; - public int ToIntToken() - { - return _value; - } + public int ToIntToken() => _value; - public static Handle FromIntToken(int value) - { - return new Handle(value); - } + public static Handle FromIntToken(int value) => new Handle(value); - internal int _value; + internal readonly int _value; #if DEBUG public override string ToString() @@ -165,14 +144,14 @@ public static string GetString(this MetadataReader reader, ConstantStringValueHa /// ConstantReferenceValue can only be used to encapsulate null reference values, /// and therefore does not actually store the value. /// - public partial struct ConstantReferenceValue + public readonly partial struct ConstantReferenceValue { /// Always returns null value. public object Value { get { return null; } } } // ConstantReferenceValue - public partial struct ConstantStringValueHandle + public readonly partial struct ConstantStringValueHandle { public bool StringEquals(string value, MetadataReader reader) { @@ -215,7 +194,7 @@ public Handle NullHandle { get { - return new Handle() { _value = ((int)HandleType.Null) << 24 }; + return new Handle(((int)HandleType.Null) << 24); } } diff --git a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs index 6fc5d9542e16..8420c9a4803b 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs @@ -16,7 +16,7 @@ internal struct ReadyToRunHeaderConstants public const uint Signature = 0x00525452; // 'RTR' public const ushort CurrentMajorVersion = 9; - public const ushort CurrentMinorVersion = 2; + public const ushort CurrentMinorVersion = 3; } #if READYTORUN #pragma warning disable 0169 diff --git a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs index c6b11a70fff0..5182525088ba 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs @@ -233,6 +233,7 @@ public enum ReadyToRunHelper WriteBarrier = 0x30, CheckedWriteBarrier = 0x31, ByRefWriteBarrier = 0x32, + BulkWriteBarrier = 0x33, // Array helpers Stelem_Ref = 0x38, diff --git a/src/coreclr/tools/Common/Internal/Text/Utf8String.cs b/src/coreclr/tools/Common/Internal/Text/Utf8String.cs index 360aa3d27e94..3614639fc99c 100644 --- a/src/coreclr/tools/Common/Internal/Text/Utf8String.cs +++ b/src/coreclr/tools/Common/Internal/Text/Utf8String.cs @@ -7,9 +7,9 @@ namespace Internal.Text { - public struct Utf8String : IEquatable, IComparable + public readonly struct Utf8String : IEquatable, IComparable { - private byte[] _value; + private readonly byte[] _value; public Utf8String(byte[] underlyingArray) { @@ -21,8 +21,6 @@ public Utf8String(string s) _value = Encoding.UTF8.GetBytes(s); } - // TODO: This should return ReadOnlySpan instead once available - public byte[] UnderlyingArray => _value; public int Length => _value.Length; // For now, define implicit conversions between string and Utf8String to aid the transition @@ -32,6 +30,8 @@ public static implicit operator Utf8String(string s) return new Utf8String(s); } + public ReadOnlySpan AsSpan() => _value; + public override string ToString() { return Encoding.UTF8.GetString(_value); @@ -39,7 +39,7 @@ public override string ToString() public override bool Equals(object obj) { - return (obj is Utf8String) && Equals((Utf8String)obj); + return (obj is Utf8String utf8String) && Equals(utf8String); } public override unsafe int GetHashCode() @@ -72,67 +72,12 @@ public override unsafe int GetHashCode() public bool Equals(Utf8String other) { - int length = _value.Length; - if (length != other.Length) - return false; - - if (_value == other._value) - return true; - - unsafe - { - fixed (byte* ap = _value) fixed (byte* bp = other._value) - { - byte* a = ap; - byte* b = bp; - - while (length >= 4) - { - if (*(int*)a != *(int*)b) return false; - a += 4; b += 4; length -= 4; - } - if (length >= 2) - { - if (*(short*)a != *(short*)b) return false; - a += 2; b += 2; length -= 2; - } - if (length > 0) - { - if (*a != *b) return false; - } - return true; - } - } + return AsSpan().SequenceEqual(other.AsSpan()); } private static int Compare(Utf8String strA, Utf8String strB) { - int length = Math.Min(strA.Length, strB.Length); - - unsafe - { - fixed (byte* ap = strA._value) - fixed (byte* bp = strB._value) - { - byte* a = ap; - byte* b = bp; - - while (length > 0) - { - if (*a != *b) - return *a - *b; - a += 1; - b += 1; - length -= 1; - } - - // At this point, we have compared all the characters in at least one string. - // The longer string will be larger. - // We could optimize and compare lengths before iterating strings, but we want - // Foo and Foo1 to be sorted adjacent to eachother. - return strA.Length - strB.Length; - } - } + return strA.AsSpan().SequenceCompareTo(strB.AsSpan()); } public int CompareTo(Utf8String other) diff --git a/src/coreclr/tools/Common/Internal/Text/Utf8StringBuilder.cs b/src/coreclr/tools/Common/Internal/Text/Utf8StringBuilder.cs index 5356a488e2f5..9a9d798d5ba9 100644 --- a/src/coreclr/tools/Common/Internal/Text/Utf8StringBuilder.cs +++ b/src/coreclr/tools/Common/Internal/Text/Utf8StringBuilder.cs @@ -16,10 +16,11 @@ public Utf8StringBuilder() { } - // TODO: This should return ReadOnlySpan instead once available public byte[] UnderlyingArray => _buffer; public int Length => _length; + public ReadOnlySpan AsSpan() => _buffer.AsSpan(0, _length); + public Utf8StringBuilder Clear() { _length = 0; @@ -35,39 +36,33 @@ public Utf8StringBuilder Truncate(int newLength) public Utf8StringBuilder Append(Utf8String value) { - return Append(value.UnderlyingArray); + return Append(value.AsSpan()); } public Utf8StringBuilder Append(ReadOnlySpan value) { Ensure(value.Length); - value.CopyTo(_buffer.AsSpan(_length, value.Length)); + value.CopyTo(_buffer.AsSpan(_length)); _length += value.Length; return this; } public Utf8StringBuilder Append(char value) { + Debug.Assert(Ascii.IsValid(value)); + Ensure(1); - if (value > 0x7F) - return Append(Encoding.UTF8.GetBytes(new char[] { value })); _buffer[_length++] = (byte)value; return this; } public Utf8StringBuilder Append(string value) { - Ensure(value.Length); + int length = Encoding.UTF8.GetByteCount(value); + Ensure(length); - byte[] buffer = _buffer; - for (int i = 0; i < value.Length; i++) - { - char c = value[i]; - if (c > 0x7F) - return Append(Encoding.UTF8.GetBytes(value)); - buffer[_length+i] = (byte)c; - } - _length += value.Length; + Encoding.UTF8.GetBytes(value, _buffer.AsSpan(_length)); + _length += length; return this; } @@ -84,9 +79,7 @@ public string ToString(int start) public Utf8String ToUtf8String() { - var ret = new byte[_length]; - Buffer.BlockCopy(_buffer, 0, ret, 0, _length); - return new Utf8String(ret); + return new Utf8String(AsSpan().ToArray()); } private void Ensure(int extraSpace) @@ -99,53 +92,8 @@ private void Grow(int extraSpace) { int newSize = Math.Max(2 * _buffer.Length, _length + extraSpace); byte[] newBuffer = new byte[newSize]; - Buffer.BlockCopy(_buffer, 0, newBuffer, 0, _length); + AsSpan().CopyTo(newBuffer); _buffer = newBuffer; } - - // Find the boundary of the last character prior to a position - // If pos points to the last byte of a char, then return pos; Otherwise, - // return the position of the last byte of the preceding char. - public int LastCharBoundary(int pos) - { - Debug.Assert(pos < _length); - - if (_buffer[pos] < 128 /*10000000*/) - { - // This is a single byte character - return pos; - } - - int origPos = pos; - - // Skip following bytes of a multi-byte character until the first byte is seen - while (_buffer[pos] < 192 /*11000000*/) - { - pos--; - } - - if (pos == origPos - 3) - { - // We just skipped a four-byte character - Debug.Assert(_buffer[pos] >= 240 /*11110000*/); - return origPos; - } - - if (pos == origPos - 2 && _buffer[pos] < 240 && _buffer[pos] >= 224 /*11100000*/) - { - // We just skipped a three-byte character - return origPos; - } - - if (pos == origPos - 1 && _buffer[pos] < 224) - { - // We just skipped a two-byte character - Debug.Assert(_buffer[pos] >= 192 /*11000000*/); - return origPos; - } - - // We were in the middle of a multi-byte character - return pos - 1; - } } } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs index 80632204e915..f47a3decb806 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs @@ -139,7 +139,7 @@ which is the right helper to use to allocate an object of a given type. */ CORINFO_HELP_ASSIGN_REF_ENSURE_NONHEAP, // Do the store, and ensure that the target was not in the heap. CORINFO_HELP_ASSIGN_BYREF, - CORINFO_HELP_ASSIGN_STRUCT, + CORINFO_HELP_BULK_WRITEBARRIER, /* Accessing fields */ diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index f4f381a6df65..2d51533393db 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -418,9 +418,10 @@ private CompilationResult CompileMethodInternal(IMethodNode methodCodeNodeNeedin if (_code != null && codeSize < _code.Length) { if (_compilation.TypeSystemContext.Target.Architecture != TargetArchitecture.ARM64 + && _compilation.TypeSystemContext.Target.Architecture != TargetArchitecture.LoongArch64 && _compilation.TypeSystemContext.Target.Architecture != TargetArchitecture.RiscV64) { - // For xarch/arm32/RiscV64, the generated code is sometimes smaller than the memory allocated. + // For xarch/arm32/LoongArch64/RiscV64, the generated code is sometimes smaller than the memory allocated. // In that case, trim the codeBlock to the actual value. // // For arm64, the allocation request of `hotCodeSize` also includes the roData size @@ -2943,6 +2944,14 @@ private bool isExactType(CORINFO_CLASS_STRUCT_* cls) return _compilation.IsEffectivelySealed(type); } + private TypeCompareState isNullableType(CORINFO_CLASS_STRUCT_* cls) + { + TypeDesc type = HandleToObject(cls); + Debug.Assert(!type.IsGenericParameter); + + return type.IsNullable ? TypeCompareState.Must : TypeCompareState.MustNot; + } + private TypeCompareState isEnum(CORINFO_CLASS_STRUCT_* cls, CORINFO_CLASS_STRUCT_** underlyingType) { Debug.Assert(cls != null); @@ -2953,11 +2962,7 @@ private TypeCompareState isEnum(CORINFO_CLASS_STRUCT_* cls, CORINFO_CLASS_STRUCT } TypeDesc type = HandleToObject(cls); - - if (type.IsGenericParameter) - { - return TypeCompareState.May; - } + Debug.Assert(!type.IsGenericParameter); if (type.IsEnum) { @@ -3280,7 +3285,7 @@ private void getEEInfo(ref CORINFO_EE_INFO pEEInfoOut) // In debug, write some bogus data to the struct to ensure we have filled everything // properly. fixed (CORINFO_EE_INFO* tmp = &pEEInfoOut) - MemoryHelper.FillMemory((byte*)tmp, 0xcc, Marshal.SizeOf()); + NativeMemory.Fill(tmp, (nuint)sizeof(CORINFO_EE_INFO), 0xcc); #endif int pointerSize = this.PointerSize; @@ -4272,7 +4277,7 @@ public static void ComputeJitPgoInstrumentationSchema(Func objec } private HRESULT getPgoInstrumentationResults(CORINFO_METHOD_STRUCT_* ftnHnd, ref PgoInstrumentationSchema* pSchema, ref uint countSchemaItems, byte** pInstrumentationData, - ref PgoSource pPgoSource) + ref PgoSource pPgoSource, ref bool pDynamicPgo) { MethodDesc methodDesc = HandleToObject(ftnHnd); @@ -4319,6 +4324,7 @@ private HRESULT getPgoInstrumentationResults(CORINFO_METHOD_STRUCT_* ftnHnd, ref countSchemaItems = pgoResults.countSchemaItems; *pInstrumentationData = pgoResults.pInstrumentationData; pPgoSource = PgoSource.Static; + pDynamicPgo = false; return pgoResults.hr; } #if READYTORUN diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index 09ea54f989fd..e4ef2264da25 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -1210,6 +1210,21 @@ private static byte _isExactType(IntPtr thisHandle, IntPtr* ppException, CORINFO } } + [UnmanagedCallersOnly] + private static TypeCompareState _isNullableType(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls) + { + var _this = GetThis(thisHandle); + try + { + return _this.isNullableType(cls); + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + return default; + } + } + [UnmanagedCallersOnly] private static TypeCompareState _isEnum(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls, CORINFO_CLASS_STRUCT_** underlyingType) { @@ -2474,12 +2489,12 @@ private static void _reportFatalError(IntPtr thisHandle, IntPtr* ppException, Co } [UnmanagedCallersOnly] - private static HRESULT _getPgoInstrumentationResults(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* ftnHnd, PgoInstrumentationSchema** pSchema, uint* pCountSchemaItems, byte** pInstrumentationData, PgoSource* pgoSource) + private static HRESULT _getPgoInstrumentationResults(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* ftnHnd, PgoInstrumentationSchema** pSchema, uint* pCountSchemaItems, byte** pInstrumentationData, PgoSource* pPgoSource, bool* pDynamicPgo) { var _this = GetThis(thisHandle); try { - return _this.getPgoInstrumentationResults(ftnHnd, ref *pSchema, ref *pCountSchemaItems, pInstrumentationData, ref *pgoSource); + return _this.getPgoInstrumentationResults(ftnHnd, ref *pSchema, ref *pCountSchemaItems, pInstrumentationData, ref *pPgoSource, ref *pDynamicPgo); } catch (Exception ex) { @@ -2579,7 +2594,7 @@ private static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_ private static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 174); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 175); callbacks[0] = (delegate* unmanaged)&_isIntrinsic; callbacks[1] = (delegate* unmanaged)&_notifyMethodInfoUsage; @@ -2662,99 +2677,100 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[78] = (delegate* unmanaged)&_compareTypesForEquality; callbacks[79] = (delegate* unmanaged)&_isMoreSpecificType; callbacks[80] = (delegate* unmanaged)&_isExactType; - callbacks[81] = (delegate* unmanaged)&_isEnum; - callbacks[82] = (delegate* unmanaged)&_getParentType; - callbacks[83] = (delegate* unmanaged)&_getChildType; - callbacks[84] = (delegate* unmanaged)&_isSDArray; - callbacks[85] = (delegate* unmanaged)&_getArrayRank; - callbacks[86] = (delegate* unmanaged)&_getArrayIntrinsicID; - callbacks[87] = (delegate* unmanaged)&_getArrayInitializationData; - callbacks[88] = (delegate* unmanaged)&_canAccessClass; - callbacks[89] = (delegate* unmanaged)&_printFieldName; - callbacks[90] = (delegate* unmanaged)&_getFieldClass; - callbacks[91] = (delegate* unmanaged)&_getFieldType; - callbacks[92] = (delegate* unmanaged)&_getFieldOffset; - callbacks[93] = (delegate* unmanaged)&_getFieldInfo; - callbacks[94] = (delegate* unmanaged)&_getThreadLocalFieldInfo; - callbacks[95] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; - callbacks[96] = (delegate* unmanaged)&_getThreadLocalStaticInfo_NativeAOT; - callbacks[97] = (delegate* unmanaged)&_isFieldStatic; - callbacks[98] = (delegate* unmanaged)&_getArrayOrStringLength; - callbacks[99] = (delegate* unmanaged)&_getBoundaries; - callbacks[100] = (delegate* unmanaged)&_setBoundaries; - callbacks[101] = (delegate* unmanaged)&_getVars; - callbacks[102] = (delegate* unmanaged)&_setVars; - callbacks[103] = (delegate* unmanaged)&_reportRichMappings; - callbacks[104] = (delegate* unmanaged)&_reportMetadata; - callbacks[105] = (delegate* unmanaged)&_allocateArray; - callbacks[106] = (delegate* unmanaged)&_freeArray; - callbacks[107] = (delegate* unmanaged)&_getArgNext; - callbacks[108] = (delegate* unmanaged)&_getArgType; - callbacks[109] = (delegate* unmanaged)&_getExactClasses; - callbacks[110] = (delegate* unmanaged)&_getArgClass; - callbacks[111] = (delegate* unmanaged)&_getHFAType; - callbacks[112] = (delegate* unmanaged)&_runWithErrorTrap; - callbacks[113] = (delegate* unmanaged)&_runWithSPMIErrorTrap; - callbacks[114] = (delegate* unmanaged)&_getEEInfo; - callbacks[115] = (delegate* unmanaged)&_getJitTimeLogFilename; - callbacks[116] = (delegate* unmanaged)&_getMethodDefFromMethod; - callbacks[117] = (delegate* unmanaged)&_printMethodName; - callbacks[118] = (delegate* unmanaged)&_getMethodNameFromMetadata; - callbacks[119] = (delegate* unmanaged)&_getMethodHash; - callbacks[120] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; - callbacks[121] = (delegate* unmanaged)&_getSwiftLowering; - callbacks[122] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; - callbacks[123] = (delegate* unmanaged)&_getRISCV64PassStructInRegisterFlags; - callbacks[124] = (delegate* unmanaged)&_getThreadTLSIndex; - callbacks[125] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; - callbacks[126] = (delegate* unmanaged)&_getHelperFtn; - callbacks[127] = (delegate* unmanaged)&_getFunctionEntryPoint; - callbacks[128] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; - callbacks[129] = (delegate* unmanaged)&_getMethodSync; - callbacks[130] = (delegate* unmanaged)&_getLazyStringLiteralHelper; - callbacks[131] = (delegate* unmanaged)&_embedModuleHandle; - callbacks[132] = (delegate* unmanaged)&_embedClassHandle; - callbacks[133] = (delegate* unmanaged)&_embedMethodHandle; - callbacks[134] = (delegate* unmanaged)&_embedFieldHandle; - callbacks[135] = (delegate* unmanaged)&_embedGenericHandle; - callbacks[136] = (delegate* unmanaged)&_getLocationOfThisType; - callbacks[137] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; - callbacks[138] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; - callbacks[139] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; - callbacks[140] = (delegate* unmanaged)&_getJustMyCodeHandle; - callbacks[141] = (delegate* unmanaged)&_GetProfilingHandle; - callbacks[142] = (delegate* unmanaged)&_getCallInfo; - callbacks[143] = (delegate* unmanaged)&_getClassDomainID; - callbacks[144] = (delegate* unmanaged)&_getStaticFieldContent; - callbacks[145] = (delegate* unmanaged)&_getObjectContent; - callbacks[146] = (delegate* unmanaged)&_getStaticFieldCurrentClass; - callbacks[147] = (delegate* unmanaged)&_getVarArgsHandle; - callbacks[148] = (delegate* unmanaged)&_canGetVarArgsHandle; - callbacks[149] = (delegate* unmanaged)&_constructStringLiteral; - callbacks[150] = (delegate* unmanaged)&_emptyStringLiteral; - callbacks[151] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; - callbacks[152] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[153] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[154] = (delegate* unmanaged)&_getTailCallHelpers; - callbacks[155] = (delegate* unmanaged)&_convertPInvokeCalliToCall; - callbacks[156] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[157] = (delegate* unmanaged)&_updateEntryPointForTailCall; - callbacks[158] = (delegate* unmanaged)&_allocMem; - callbacks[159] = (delegate* unmanaged)&_reserveUnwindInfo; - callbacks[160] = (delegate* unmanaged)&_allocUnwindInfo; - callbacks[161] = (delegate* unmanaged)&_allocGCInfo; - callbacks[162] = (delegate* unmanaged)&_setEHcount; - callbacks[163] = (delegate* unmanaged)&_setEHinfo; - callbacks[164] = (delegate* unmanaged)&_logMsg; - callbacks[165] = (delegate* unmanaged)&_doAssert; - callbacks[166] = (delegate* unmanaged)&_reportFatalError; - callbacks[167] = (delegate* unmanaged)&_getPgoInstrumentationResults; - callbacks[168] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; - callbacks[169] = (delegate* unmanaged)&_recordCallSite; - callbacks[170] = (delegate* unmanaged)&_recordRelocation; - callbacks[171] = (delegate* unmanaged)&_getRelocTypeHint; - callbacks[172] = (delegate* unmanaged)&_getExpectedTargetArchitecture; - callbacks[173] = (delegate* unmanaged)&_getJitFlags; + callbacks[81] = (delegate* unmanaged)&_isNullableType; + callbacks[82] = (delegate* unmanaged)&_isEnum; + callbacks[83] = (delegate* unmanaged)&_getParentType; + callbacks[84] = (delegate* unmanaged)&_getChildType; + callbacks[85] = (delegate* unmanaged)&_isSDArray; + callbacks[86] = (delegate* unmanaged)&_getArrayRank; + callbacks[87] = (delegate* unmanaged)&_getArrayIntrinsicID; + callbacks[88] = (delegate* unmanaged)&_getArrayInitializationData; + callbacks[89] = (delegate* unmanaged)&_canAccessClass; + callbacks[90] = (delegate* unmanaged)&_printFieldName; + callbacks[91] = (delegate* unmanaged)&_getFieldClass; + callbacks[92] = (delegate* unmanaged)&_getFieldType; + callbacks[93] = (delegate* unmanaged)&_getFieldOffset; + callbacks[94] = (delegate* unmanaged)&_getFieldInfo; + callbacks[95] = (delegate* unmanaged)&_getThreadLocalFieldInfo; + callbacks[96] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; + callbacks[97] = (delegate* unmanaged)&_getThreadLocalStaticInfo_NativeAOT; + callbacks[98] = (delegate* unmanaged)&_isFieldStatic; + callbacks[99] = (delegate* unmanaged)&_getArrayOrStringLength; + callbacks[100] = (delegate* unmanaged)&_getBoundaries; + callbacks[101] = (delegate* unmanaged)&_setBoundaries; + callbacks[102] = (delegate* unmanaged)&_getVars; + callbacks[103] = (delegate* unmanaged)&_setVars; + callbacks[104] = (delegate* unmanaged)&_reportRichMappings; + callbacks[105] = (delegate* unmanaged)&_reportMetadata; + callbacks[106] = (delegate* unmanaged)&_allocateArray; + callbacks[107] = (delegate* unmanaged)&_freeArray; + callbacks[108] = (delegate* unmanaged)&_getArgNext; + callbacks[109] = (delegate* unmanaged)&_getArgType; + callbacks[110] = (delegate* unmanaged)&_getExactClasses; + callbacks[111] = (delegate* unmanaged)&_getArgClass; + callbacks[112] = (delegate* unmanaged)&_getHFAType; + callbacks[113] = (delegate* unmanaged)&_runWithErrorTrap; + callbacks[114] = (delegate* unmanaged)&_runWithSPMIErrorTrap; + callbacks[115] = (delegate* unmanaged)&_getEEInfo; + callbacks[116] = (delegate* unmanaged)&_getJitTimeLogFilename; + callbacks[117] = (delegate* unmanaged)&_getMethodDefFromMethod; + callbacks[118] = (delegate* unmanaged)&_printMethodName; + callbacks[119] = (delegate* unmanaged)&_getMethodNameFromMetadata; + callbacks[120] = (delegate* unmanaged)&_getMethodHash; + callbacks[121] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; + callbacks[122] = (delegate* unmanaged)&_getSwiftLowering; + callbacks[123] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; + callbacks[124] = (delegate* unmanaged)&_getRISCV64PassStructInRegisterFlags; + callbacks[125] = (delegate* unmanaged)&_getThreadTLSIndex; + callbacks[126] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; + callbacks[127] = (delegate* unmanaged)&_getHelperFtn; + callbacks[128] = (delegate* unmanaged)&_getFunctionEntryPoint; + callbacks[129] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; + callbacks[130] = (delegate* unmanaged)&_getMethodSync; + callbacks[131] = (delegate* unmanaged)&_getLazyStringLiteralHelper; + callbacks[132] = (delegate* unmanaged)&_embedModuleHandle; + callbacks[133] = (delegate* unmanaged)&_embedClassHandle; + callbacks[134] = (delegate* unmanaged)&_embedMethodHandle; + callbacks[135] = (delegate* unmanaged)&_embedFieldHandle; + callbacks[136] = (delegate* unmanaged)&_embedGenericHandle; + callbacks[137] = (delegate* unmanaged)&_getLocationOfThisType; + callbacks[138] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; + callbacks[139] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; + callbacks[140] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; + callbacks[141] = (delegate* unmanaged)&_getJustMyCodeHandle; + callbacks[142] = (delegate* unmanaged)&_GetProfilingHandle; + callbacks[143] = (delegate* unmanaged)&_getCallInfo; + callbacks[144] = (delegate* unmanaged)&_getClassDomainID; + callbacks[145] = (delegate* unmanaged)&_getStaticFieldContent; + callbacks[146] = (delegate* unmanaged)&_getObjectContent; + callbacks[147] = (delegate* unmanaged)&_getStaticFieldCurrentClass; + callbacks[148] = (delegate* unmanaged)&_getVarArgsHandle; + callbacks[149] = (delegate* unmanaged)&_canGetVarArgsHandle; + callbacks[150] = (delegate* unmanaged)&_constructStringLiteral; + callbacks[151] = (delegate* unmanaged)&_emptyStringLiteral; + callbacks[152] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; + callbacks[153] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[154] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[155] = (delegate* unmanaged)&_getTailCallHelpers; + callbacks[156] = (delegate* unmanaged)&_convertPInvokeCalliToCall; + callbacks[157] = (delegate* unmanaged)&_notifyInstructionSetUsage; + callbacks[158] = (delegate* unmanaged)&_updateEntryPointForTailCall; + callbacks[159] = (delegate* unmanaged)&_allocMem; + callbacks[160] = (delegate* unmanaged)&_reserveUnwindInfo; + callbacks[161] = (delegate* unmanaged)&_allocUnwindInfo; + callbacks[162] = (delegate* unmanaged)&_allocGCInfo; + callbacks[163] = (delegate* unmanaged)&_setEHcount; + callbacks[164] = (delegate* unmanaged)&_setEHinfo; + callbacks[165] = (delegate* unmanaged)&_logMsg; + callbacks[166] = (delegate* unmanaged)&_doAssert; + callbacks[167] = (delegate* unmanaged)&_reportFatalError; + callbacks[168] = (delegate* unmanaged)&_getPgoInstrumentationResults; + callbacks[169] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; + callbacks[170] = (delegate* unmanaged)&_recordCallSite; + callbacks[171] = (delegate* unmanaged)&_recordRelocation; + callbacks[172] = (delegate* unmanaged)&_getRelocTypeHint; + callbacks[173] = (delegate* unmanaged)&_getExpectedTargetArchitecture; + callbacks[174] = (delegate* unmanaged)&_getJitFlags; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs index 2276c5cdc9a7..3eba98954c1c 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs @@ -836,6 +836,9 @@ public struct InlinedCallFrameInfo // Size of the Frame structure public uint size; + // Size of the Frame structure inside IL stubs that include secret stub arg in the frame + public uint sizeWithSecretStubArg; + public uint offsetOfGSCookie; public uint offsetOfFrameVptr; public uint offsetOfFrameLink; @@ -843,6 +846,7 @@ public struct InlinedCallFrameInfo public uint offsetOfCalleeSavedFP; public uint offsetOfCallTarget; public uint offsetOfReturnAddress; + public uint offsetOfSecretStubArg; public uint offsetOfSPAfterProlog; } public InlinedCallFrameInfo inlinedCallFrameInfo; @@ -1235,6 +1239,7 @@ public struct SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR // bit 5: `1` means the second field's size is 8. // // Note that bit 0 and 3 cannot both be set. + [Flags] public enum StructFloatFieldInfoFlags { STRUCT_NO_FLOAT_FIELD = 0x0, diff --git a/src/coreclr/tools/Common/JitInterface/LoongArch64PassStructInRegister.cs b/src/coreclr/tools/Common/JitInterface/LoongArch64PassStructInRegister.cs index b0c193d09500..250ea428c44d 100644 --- a/src/coreclr/tools/Common/JitInterface/LoongArch64PassStructInRegister.cs +++ b/src/coreclr/tools/Common/JitInterface/LoongArch64PassStructInRegister.cs @@ -1,198 +1,127 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; using System.Diagnostics; using ILCompiler; using Internal.TypeSystem; +using static Internal.JitInterface.StructFloatFieldInfoFlags; namespace Internal.JitInterface { - internal static class LoongArch64PassStructInRegister { - public static uint GetLoongArch64PassStructInRegisterFlags(TypeDesc typeDesc) + private const int + ENREGISTERED_PARAMTYPE_MAXSIZE = 16, + TARGET_POINTER_SIZE = 8; + + private static bool HandleInlineArray(int elementTypeIndex, int nElements, Span types, ref int typeIndex) { - FieldDesc firstField = null; - uint floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; - int numIntroducedFields = 0; - foreach (FieldDesc field in typeDesc.GetFields()) - { - if (!field.IsStatic) - { - firstField ??= field; - numIntroducedFields++; - } - } + int nFlattenedFieldsPerElement = typeIndex - elementTypeIndex; + if (nFlattenedFieldsPerElement == 0) + return true; + + Debug.Assert(nFlattenedFieldsPerElement == 1 || nFlattenedFieldsPerElement == 2); - if ((numIntroducedFields == 0) || (numIntroducedFields > 2) || (typeDesc.GetElementSize().AsInt > 16)) + if (nElements > 2) + return false; + + if (nElements == 2) { - return (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; + if (typeIndex + nFlattenedFieldsPerElement > 2) + return false; + + Debug.Assert(elementTypeIndex == 0); + Debug.Assert(typeIndex == 1); + types[typeIndex++] = types[elementTypeIndex]; // duplicate the array element type } + return true; + } - //// The SIMD Intrinsic types are meant to be handled specially and should not be passed as struct registers - if (typeDesc.IsIntrinsic) + private static bool FlattenFieldTypes(TypeDesc td, Span types, ref int typeIndex) + { + IEnumerable fields = td.GetFields(); + int nFields = 0; + int elementTypeIndex = typeIndex; + FieldDesc prevField = null; + foreach (FieldDesc field in fields) { - throw new NotImplementedException("For LoongArch64, SIMD would be implemented later"); - } + if (field.IsStatic) + continue; + nFields++; - MetadataType mdType = typeDesc as MetadataType; - Debug.Assert(mdType != null); + if (prevField != null && prevField.Offset.AsInt + prevField.FieldType.GetElementSize().AsInt > field.Offset.AsInt) + return false; // overlapping fields - TypeDesc firstFieldElementType = firstField.FieldType; - int firstFieldSize = firstFieldElementType.GetElementSize().AsInt; + prevField = field; - bool hasImpliedRepeatedFields = mdType.HasImpliedRepeatedFields(); + TypeFlags category = field.FieldType.Category; + if (category == TypeFlags.ValueType) + { + TypeDesc nested = field.FieldType; + if (!FlattenFieldTypes(nested, types, ref typeIndex)) + return false; + } + else if (field.FieldType.GetElementSize().AsInt <= TARGET_POINTER_SIZE) + { + if (typeIndex >= 2) + return false; - if (hasImpliedRepeatedFields) - { - numIntroducedFields = typeDesc.GetElementSize().AsInt / firstFieldSize; - if (numIntroducedFields > 2) + StructFloatFieldInfoFlags type = + (category is TypeFlags.Single or TypeFlags.Double ? STRUCT_FLOAT_FIELD_FIRST : (StructFloatFieldInfoFlags)0) | + (field.FieldType.GetElementSize().AsInt == TARGET_POINTER_SIZE ? STRUCT_FIRST_FIELD_SIZE_IS8 : (StructFloatFieldInfoFlags)0); + types[typeIndex++] = type; + } + else { - return (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; + return false; } } - int fieldIndex = 0; - foreach (FieldDesc field in typeDesc.GetFields()) + if ((td as MetadataType).HasImpliedRepeatedFields()) { - if (field.IsStatic) - { - continue; - } + Debug.Assert(nFields == 1); + int nElements = td.GetElementSize().AsInt / prevField.FieldType.GetElementSize().AsInt; + if (!HandleInlineArray(elementTypeIndex, nElements, types, ref typeIndex)) + return false; + } + return true; + } - Debug.Assert(fieldIndex < numIntroducedFields); + public static uint GetLoongArch64PassStructInRegisterFlags(TypeDesc td) + { + if (td.GetElementSize().AsInt > ENREGISTERED_PARAMTYPE_MAXSIZE) + return (uint)STRUCT_NO_FLOAT_FIELD; - switch (field.FieldType.Category) - { - case TypeFlags.Double: - { - if (numIntroducedFields == 1) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_ONLY_ONE; - } - else if (fieldIndex == 0) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_FIRST_FIELD_DOUBLE; - } - else if ((floatFieldFlags & (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST) != 0) - { - floatFieldFlags ^= (uint)StructFloatFieldInfoFlags.STRUCT_MERGE_FIRST_SECOND_8; - } - else - { - floatFieldFlags |= (uint)StructFloatFieldInfoFlags.STRUCT_SECOND_FIELD_DOUBLE; - } - } - break; - - case TypeFlags.Single: - { - if (numIntroducedFields == 1) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_ONLY_ONE; - } - else if (fieldIndex == 0) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST; - } - else if ((floatFieldFlags & (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST) != 0) - { - floatFieldFlags ^= (uint)StructFloatFieldInfoFlags.STRUCT_MERGE_FIRST_SECOND; - } - else - { - floatFieldFlags |= (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND; - } - } - break; - - case TypeFlags.ValueType: - //case TypeFlags.Class: - //case TypeFlags.Array: - //case TypeFlags.SzArray: - { - uint floatFieldFlags2 = GetLoongArch64PassStructInRegisterFlags(field.FieldType); - if (numIntroducedFields == 1) - { - floatFieldFlags = floatFieldFlags2; - } - else if (field.FieldType.GetElementSize().AsInt > 8) - { - return (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; - } - else if (fieldIndex == 0) - { - if ((floatFieldFlags2 & (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_ONLY_ONE) != 0) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST; - } - if (field.FieldType.GetElementSize().AsInt == 8) - { - floatFieldFlags |= (uint)StructFloatFieldInfoFlags.STRUCT_FIRST_FIELD_SIZE_IS8; - } - } - else - { - Debug.Assert(fieldIndex == 1); - if ((floatFieldFlags2 & (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_ONLY_ONE) != 0) - { - floatFieldFlags |= (uint)StructFloatFieldInfoFlags.STRUCT_MERGE_FIRST_SECOND; - } - if (field.FieldType.GetElementSize().AsInt == 8) - { - floatFieldFlags |= (uint)StructFloatFieldInfoFlags.STRUCT_SECOND_FIELD_SIZE_IS8; - } - - floatFieldFlags2 = floatFieldFlags & ((uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST | (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND); - if (floatFieldFlags2 == 0) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; - } - else if (floatFieldFlags2 == ((uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST | (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND)) - { - floatFieldFlags ^= ((uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_ONLY_TWO | (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST | (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND); - } - } - } - break; - - default: - { - if ((numIntroducedFields == 2) && (field.FieldType.Category == TypeFlags.Class)) - { - return (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; - } - - if (field.FieldType.GetElementSize().AsInt == 8) - { - if (numIntroducedFields > 1) - { - if (fieldIndex == 0) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_FIRST_FIELD_SIZE_IS8; - } - else if ((floatFieldFlags & (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST) != 0) - { - floatFieldFlags |= (uint)StructFloatFieldInfoFlags.STRUCT_SECOND_FIELD_SIZE_IS8; - } - else - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; - } - } - } - else if (fieldIndex == 1) - { - floatFieldFlags = (floatFieldFlags & (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST) > 0 ? floatFieldFlags : (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; - } - break; - } - } + Span types = stackalloc StructFloatFieldInfoFlags[] { + STRUCT_NO_FLOAT_FIELD, STRUCT_NO_FLOAT_FIELD + }; + int nFields = 0; + if (!FlattenFieldTypes(td, types, ref nFields) || nFields == 0) + return (uint)STRUCT_NO_FLOAT_FIELD; - fieldIndex++; - } + Debug.Assert(nFields == 1 || nFields == 2); + + Debug.Assert((uint)(STRUCT_FLOAT_FIELD_SECOND | STRUCT_SECOND_FIELD_SIZE_IS8) + == (uint)(STRUCT_FLOAT_FIELD_FIRST | STRUCT_FIRST_FIELD_SIZE_IS8) << 1, + "SECOND flags need to be FIRST shifted by 1"); + StructFloatFieldInfoFlags flags = types[0] | (StructFloatFieldInfoFlags)((uint)types[1] << 1); + + const StructFloatFieldInfoFlags bothFloat = STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_SECOND; + if ((flags & bothFloat) == 0) + return (uint)STRUCT_NO_FLOAT_FIELD; - return floatFieldFlags; + if ((flags & bothFloat) == bothFloat) + { + Debug.Assert(nFields == 2); + flags ^= (bothFloat | STRUCT_FLOAT_FIELD_ONLY_TWO); // replace bothFloat with ONLY_TWO + } + else if (nFields == 1) + { + Debug.Assert((flags & STRUCT_FLOAT_FIELD_FIRST) != 0); + flags ^= (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_ONLY_ONE); // replace FIRST with ONLY_ONE + } + return (uint)flags; } } } diff --git a/src/coreclr/tools/Common/JitInterface/MemoryHelper.cs b/src/coreclr/tools/Common/JitInterface/MemoryHelper.cs deleted file mode 100644 index ac009bcd17da..000000000000 --- a/src/coreclr/tools/Common/JitInterface/MemoryHelper.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace Internal.JitInterface -{ - internal static unsafe class MemoryHelper - { - public static void FillMemory(byte* dest, byte fill, int count) - { - for (; count > 0; count--) - { - *dest = fill; - dest++; - } - } - } -} diff --git a/src/coreclr/tools/Common/JitInterface/RISCV64PassStructInRegister.cs b/src/coreclr/tools/Common/JitInterface/RISCV64PassStructInRegister.cs index d6c820b8f904..fae694f8768f 100644 --- a/src/coreclr/tools/Common/JitInterface/RISCV64PassStructInRegister.cs +++ b/src/coreclr/tools/Common/JitInterface/RISCV64PassStructInRegister.cs @@ -1,210 +1,127 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; using System.Diagnostics; using ILCompiler; using Internal.TypeSystem; +using static Internal.JitInterface.StructFloatFieldInfoFlags; namespace Internal.JitInterface { - internal static class RISCV64PassStructInRegister { - public static uint GetRISCV64PassStructInRegisterFlags(TypeDesc typeDesc) + private const int + ENREGISTERED_PARAMTYPE_MAXSIZE = 16, + TARGET_POINTER_SIZE = 8; + + private static bool HandleInlineArray(int elementTypeIndex, int nElements, Span types, ref int typeIndex) { - FieldDesc firstField = null; - uint floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; - int numIntroducedFields = 0; - foreach (FieldDesc field in typeDesc.GetFields()) + int nFlattenedFieldsPerElement = typeIndex - elementTypeIndex; + if (nFlattenedFieldsPerElement == 0) + return true; + + Debug.Assert(nFlattenedFieldsPerElement == 1 || nFlattenedFieldsPerElement == 2); + + if (nElements > 2) + return false; + + if (nElements == 2) { - if (!field.IsStatic) - { - firstField ??= field; - numIntroducedFields++; - } + if (typeIndex + nFlattenedFieldsPerElement > 2) + return false; + + Debug.Assert(elementTypeIndex == 0); + Debug.Assert(typeIndex == 1); + types[typeIndex++] = types[elementTypeIndex]; // duplicate the array element type } + return true; + } - if ((numIntroducedFields == 0) || (numIntroducedFields > 2) || (typeDesc.GetElementSize().AsInt > 16)) + private static bool FlattenFieldTypes(TypeDesc td, Span types, ref int typeIndex) + { + IEnumerable fields = td.GetFields(); + int nFields = 0; + int elementTypeIndex = typeIndex; + FieldDesc prevField = null; + foreach (FieldDesc field in fields) { - return (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; - } + if (field.IsStatic) + continue; + nFields++; - MetadataType mdType = typeDesc as MetadataType; - Debug.Assert(mdType != null); + if (prevField != null && prevField.Offset.AsInt + prevField.FieldType.GetElementSize().AsInt > field.Offset.AsInt) + return false; // overlapping fields - TypeDesc firstFieldElementType = firstField.FieldType; - int firstFieldSize = firstFieldElementType.GetElementSize().AsInt; - bool hasImpliedRepeatedFields = mdType.HasImpliedRepeatedFields(); + prevField = field; - if (hasImpliedRepeatedFields) - { - numIntroducedFields = typeDesc.GetElementSize().AsInt / firstFieldSize; - if (numIntroducedFields > 2) + TypeFlags category = field.FieldType.Category; + if (category == TypeFlags.ValueType) { - return (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; + TypeDesc nested = field.FieldType; + if (!FlattenFieldTypes(nested, types, ref typeIndex)) + return false; } - } - - int fieldIndex = 0; - foreach (FieldDesc field in typeDesc.GetFields()) - { - if (fieldIndex > 1) + else if (field.FieldType.GetElementSize().AsInt <= TARGET_POINTER_SIZE) { - return (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; + if (typeIndex >= 2) + return false; + + StructFloatFieldInfoFlags type = + (category is TypeFlags.Single or TypeFlags.Double ? STRUCT_FLOAT_FIELD_FIRST : (StructFloatFieldInfoFlags)0) | + (field.FieldType.GetElementSize().AsInt == TARGET_POINTER_SIZE ? STRUCT_FIRST_FIELD_SIZE_IS8 : (StructFloatFieldInfoFlags)0); + types[typeIndex++] = type; } - else if (field.IsStatic) + else { - continue; + return false; } + } - Debug.Assert(fieldIndex < numIntroducedFields); + if ((td as MetadataType).HasImpliedRepeatedFields()) + { + Debug.Assert(nFields == 1); + int nElements = td.GetElementSize().AsInt / prevField.FieldType.GetElementSize().AsInt; + if (!HandleInlineArray(elementTypeIndex, nElements, types, ref typeIndex)) + return false; + } + return true; + } - switch (field.FieldType.Category) - { - case TypeFlags.Double: - { - if (numIntroducedFields == 1) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_ONLY_ONE; - } - else if (fieldIndex == 0) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_FIRST_FIELD_DOUBLE; - } - else if ((floatFieldFlags & (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST) != 0) - { - floatFieldFlags ^= (uint)StructFloatFieldInfoFlags.STRUCT_MERGE_FIRST_SECOND_8; - } - else - { - floatFieldFlags |= (uint)StructFloatFieldInfoFlags.STRUCT_SECOND_FIELD_DOUBLE; - } - - // Pass with two integer registers in `struct {int a, int b, float/double c}` cases - if (fieldIndex == 1 && - (floatFieldFlags | - (uint)StructFloatFieldInfoFlags.STRUCT_FIRST_FIELD_SIZE_IS8 | - (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND) == - floatFieldFlags) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; - } - } - break; - - case TypeFlags.Single: - { - if (numIntroducedFields == 1) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_ONLY_ONE; - } - else if (fieldIndex == 0) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST; - } - else if ((floatFieldFlags & (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST) != 0) - { - floatFieldFlags ^= (uint)StructFloatFieldInfoFlags.STRUCT_MERGE_FIRST_SECOND; - } - else - { - floatFieldFlags |= (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND; - } - - // Pass with two integer registers in `struct {int a, int b, float/double c}` cases - if (fieldIndex == 1 && - (floatFieldFlags | - (uint)StructFloatFieldInfoFlags.STRUCT_FIRST_FIELD_SIZE_IS8 | - (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND) == - floatFieldFlags) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; - } - } - break; - - case TypeFlags.ValueType: - //case TypeFlags.Class: - //case TypeFlags.Array: - //case TypeFlags.SzArray: - { - uint floatFieldFlags2 = GetRISCV64PassStructInRegisterFlags(field.FieldType); - if (numIntroducedFields == 1) - { - floatFieldFlags = floatFieldFlags2; - } - else if (field.FieldType.GetElementSize().AsInt > 8) - { - return (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; - } - else if (fieldIndex == 0) - { - if ((floatFieldFlags2 & (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_ONLY_ONE) != 0) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST; - } - if (field.FieldType.GetElementSize().AsInt == 8) - { - floatFieldFlags |= (uint)StructFloatFieldInfoFlags.STRUCT_FIRST_FIELD_SIZE_IS8; - } - } - else - { - Debug.Assert(fieldIndex == 1); - if ((floatFieldFlags2 & (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_ONLY_ONE) != 0) - { - floatFieldFlags |= (uint)StructFloatFieldInfoFlags.STRUCT_MERGE_FIRST_SECOND; - } - if (field.FieldType.GetElementSize().AsInt == 8) - { - floatFieldFlags |= (uint)StructFloatFieldInfoFlags.STRUCT_SECOND_FIELD_SIZE_IS8; - } - - floatFieldFlags2 = floatFieldFlags & ((uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST | (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND); - if (floatFieldFlags2 == 0) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; - } - else if (floatFieldFlags2 == ((uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST | (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND)) - { - floatFieldFlags ^= ((uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_ONLY_TWO | (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST | (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND); - } - } - } - break; - - default: - { - if (field.FieldType.GetElementSize().AsInt == 8) - { - if (numIntroducedFields > 1) - { - if (fieldIndex == 0) - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_FIRST_FIELD_SIZE_IS8; - } - else if ((floatFieldFlags & (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST) != 0) - { - floatFieldFlags |= (uint)StructFloatFieldInfoFlags.STRUCT_SECOND_FIELD_SIZE_IS8; - } - else - { - floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; - } - } - } - else if (fieldIndex == 1) - { - floatFieldFlags = (floatFieldFlags & (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST) > 0 ? floatFieldFlags : (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; - } - break; - } - } + public static uint GetRISCV64PassStructInRegisterFlags(TypeDesc td) + { + if (td.GetElementSize().AsInt > ENREGISTERED_PARAMTYPE_MAXSIZE) + return (uint)STRUCT_NO_FLOAT_FIELD; - fieldIndex++; - } + Span types = stackalloc StructFloatFieldInfoFlags[] { + STRUCT_NO_FLOAT_FIELD, STRUCT_NO_FLOAT_FIELD + }; + int nFields = 0; + if (!FlattenFieldTypes(td, types, ref nFields) || nFields == 0) + return (uint)STRUCT_NO_FLOAT_FIELD; + + Debug.Assert(nFields == 1 || nFields == 2); + + Debug.Assert((uint)(STRUCT_FLOAT_FIELD_SECOND | STRUCT_SECOND_FIELD_SIZE_IS8) + == (uint)(STRUCT_FLOAT_FIELD_FIRST | STRUCT_FIRST_FIELD_SIZE_IS8) << 1, + "SECOND flags need to be FIRST shifted by 1"); + StructFloatFieldInfoFlags flags = types[0] | (StructFloatFieldInfoFlags)((uint)types[1] << 1); + + const StructFloatFieldInfoFlags bothFloat = STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_SECOND; + if ((flags & bothFloat) == 0) + return (uint)STRUCT_NO_FLOAT_FIELD; - return floatFieldFlags; + if ((flags & bothFloat) == bothFloat) + { + Debug.Assert(nFields == 2); + flags ^= (bothFloat | STRUCT_FLOAT_FIELD_ONLY_TWO); // replace bothFloat with ONLY_TWO + } + else if (nFields == 1) + { + Debug.Assert((flags & STRUCT_FLOAT_FIELD_FIRST) != 0); + flags ^= (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_ONLY_ONE); // replace FIRST with ONLY_ONE + } + return (uint)flags; } } } diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 8d6ecabaa77c..2b78b2354743 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -244,6 +244,7 @@ FUNCTIONS TypeCompareState compareTypesForEquality(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) bool isMoreSpecificType(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) bool isExactType(CORINFO_CLASS_HANDLE cls) + TypeCompareState isNullableType(CORINFO_CLASS_HANDLE cls) TypeCompareState isEnum(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType) CORINFO_CLASS_HANDLE getParentType(CORINFO_CLASS_HANDLE cls) CorInfoType getChildType(CORINFO_CLASS_HANDLE clsHnd, CORINFO_CLASS_HANDLE* clsRet) @@ -330,7 +331,7 @@ FUNCTIONS bool logMsg(unsigned level, const char* fmt, va_list args) int doAssert(const char* szFile, int iLine, const char* szExpr) void reportFatalError(CorJitResult result) - JITINTERFACE_HRESULT getPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t**pInstrumentationData, ICorJitInfo::PgoSource* pgoSource) + JITINTERFACE_HRESULT getPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t**pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource, bool* pDynamicPgo) JITINTERFACE_HRESULT allocPgoInstrumentationBySchema(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, uint32_t countSchemaItems, uint8_t** pInstrumentationData) void recordCallSite(uint32_t instrOffset, CORINFO_SIG_INFO* callSig, CORINFO_METHOD_HANDLE methodHandle) void recordRelocation(void* location, void* locationRW, void* target, uint16_t fRelocType, int32_t addlDelta) diff --git a/src/coreclr/tools/Common/Pgo/PgoFormat.cs b/src/coreclr/tools/Common/Pgo/PgoFormat.cs index b62383584583..b0222f8a0c8f 100644 --- a/src/coreclr/tools/Common/Pgo/PgoFormat.cs +++ b/src/coreclr/tools/Common/Pgo/PgoFormat.cs @@ -516,7 +516,7 @@ public static void EncodePgoData(IEnumerable sche private sealed class PgoSchemaMergeComparer : IComparer, IEqualityComparer { - public static PgoSchemaMergeComparer Singleton = new PgoSchemaMergeComparer(); + public static readonly PgoSchemaMergeComparer Singleton = new PgoSchemaMergeComparer(); public int Compare(PgoSchemaElem x, PgoSchemaElem y) { diff --git a/src/coreclr/tools/Common/System/Collections/Generic/ArrayBuilder.cs b/src/coreclr/tools/Common/System/Collections/Generic/ArrayBuilder.cs index 32023e27c19f..0005f5474782 100644 --- a/src/coreclr/tools/Common/System/Collections/Generic/ArrayBuilder.cs +++ b/src/coreclr/tools/Common/System/Collections/Generic/ArrayBuilder.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.CompilerServices; + using Debug = System.Diagnostics.Debug; namespace System.Collections.Generic @@ -29,6 +31,19 @@ public void Add(T item) _items[_count++] = item; } +#if NET + public readonly Span AsSpan(int start) => _items.AsSpan(start); + + public Span AppendSpan(int length) + { + int origCount = _count; + EnsureCapacity(origCount + length); + + _count = origCount + length; + return _items.AsSpan(origCount, length); + } +#endif + public void Append(T[] newItems) { Append(newItems, 0, newItems.Length); @@ -67,32 +82,26 @@ public void EnsureCapacity(int requestedCapacity) { if (requestedCapacity > ((_items != null) ? _items.Length : 0)) { - int newCount = Math.Max(2 * _count + 1, requestedCapacity); - Array.Resize(ref _items, newCount); + Grow(requestedCapacity); } } - public int Count + [MethodImpl(MethodImplOptions.NoInlining)] + private void Grow(int requestedCapacity) { - get - { - return _count; - } + int newCount = Math.Max(2 * _count + 1, requestedCapacity); + Array.Resize(ref _items, newCount); } - public T this[int index] + public readonly int Count => _count; + + public readonly T this[int index] { - get - { - return _items[index]; - } - set - { - _items[index] = value; - } + get => _items[index]; + set => _items[index] = value; } - public bool Contains(T t) + public readonly bool Contains(T t) { for (int i = 0; i < _count; i++) { @@ -105,7 +114,7 @@ public bool Contains(T t) return false; } - public bool Any(Func func) + public readonly bool Any(Func func) { for (int i = 0; i < _count; i++) { diff --git a/src/coreclr/tools/Common/TypeSystem/Common/BaseTypeRuntimeInterfacesAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/BaseTypeRuntimeInterfacesAlgorithm.cs index 0835048af5f9..deebe50f195c 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/BaseTypeRuntimeInterfacesAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/BaseTypeRuntimeInterfacesAlgorithm.cs @@ -9,7 +9,7 @@ namespace Internal.TypeSystem /// public sealed class BaseTypeRuntimeInterfacesAlgorithm : RuntimeInterfacesAlgorithm { - private static RuntimeInterfacesAlgorithm _singleton = new BaseTypeRuntimeInterfacesAlgorithm(); + private static readonly RuntimeInterfacesAlgorithm _singleton = new BaseTypeRuntimeInterfacesAlgorithm(); private BaseTypeRuntimeInterfacesAlgorithm() { } diff --git a/src/coreclr/tools/Common/TypeSystem/Common/IAssemblyDesc.cs b/src/coreclr/tools/Common/TypeSystem/Common/IAssemblyDesc.cs index be0f346f391d..c64e7e380865 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/IAssemblyDesc.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/IAssemblyDesc.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Reflection; +using System.Reflection.Metadata; namespace Internal.TypeSystem { @@ -13,6 +13,6 @@ public interface IAssemblyDesc /// /// Gets the assembly name. /// - AssemblyName GetName(); + AssemblyNameInfo GetName(); } } diff --git a/src/coreclr/tools/Common/TypeSystem/Common/IModuleResolver.cs b/src/coreclr/tools/Common/TypeSystem/Common/IModuleResolver.cs index 0acc7ee8b9e1..391cd6f066bd 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/IModuleResolver.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/IModuleResolver.cs @@ -1,13 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Reflection; +using System.Reflection.Metadata; namespace Internal.TypeSystem { public interface IModuleResolver { - ModuleDesc ResolveAssembly(AssemblyName name, bool throwIfNotFound = true); + ModuleDesc ResolveAssembly(AssemblyNameInfo name, bool throwIfNotFound = true); ModuleDesc ResolveModule(IAssemblyDesc referencingModule, string fileName, bool throwIfNotFound = true); } } diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs index 6879089f8982..c15cb3dc6ec2 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs @@ -967,7 +967,7 @@ private static SizeAndAlignment ComputeInstanceSize(MetadataType type, LayoutInt { SizeAndAlignment result; - // Pad the length of structs to be 1 if they are empty so we have no zero-length structures + // Pad the length of structs to be 1 if they are empty, so we have no zero-length structures if (type.IsValueType && instanceSize == LayoutInt.Zero) { instanceSize = LayoutInt.One; @@ -975,25 +975,29 @@ private static SizeAndAlignment ComputeInstanceSize(MetadataType type, LayoutInt TargetDetails target = type.Context.Target; - if (classLayoutSize != 0) + if (type.IsValueType) { - LayoutInt parentSize; - if (type.IsValueType) - parentSize = new LayoutInt(0); - else - parentSize = type.BaseType.InstanceByteCountUnaligned; - - LayoutInt specifiedInstanceSize = parentSize + new LayoutInt(classLayoutSize); + if (classLayoutSize != 0) + { + instanceSize = LayoutInt.Max(new LayoutInt(classLayoutSize), instanceSize); - instanceSize = LayoutInt.Max(specifiedInstanceSize, instanceSize); - } - else - { - if (type.IsValueType) + // Size of a struct with gc references is always expected to be aligned to pointer size + if (type.ContainsGCPointers) + { + instanceSize = LayoutInt.AlignUp(instanceSize, new LayoutInt(target.PointerSize), target); + } + } + else { instanceSize = LayoutInt.AlignUp(instanceSize, alignment, target); } } + else if (classLayoutSize != 0 && type.IsSequentialLayout && !type.ContainsGCPointers) + { + // For classes, we respect classLayoutSize only for SequentialLayout + no gc fields + LayoutInt specifiedInstanceSize = type.BaseType.InstanceByteCountUnaligned + new LayoutInt(classLayoutSize); + instanceSize = LayoutInt.Max(specifiedInstanceSize, instanceSize); + } if (type.IsValueType) { diff --git a/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemContext.Resolution.cs b/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemContext.Resolution.cs index 806bf66e94e2..1e475ed7e1b2 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemContext.Resolution.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemContext.Resolution.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Reflection; +using System.Reflection.Metadata; using Internal.NativeFormat; @@ -24,7 +24,7 @@ protected void InitializeSystemModule(ModuleDesc systemModule) SystemModule = systemModule; } - public virtual ModuleDesc ResolveAssembly(AssemblyName name, bool throwIfNotFound = true) + public virtual ModuleDesc ResolveAssembly(AssemblyNameInfo name, bool throwIfNotFound = true) { if (throwIfNotFound) throw new NotSupportedException(); diff --git a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs index a52a68f0028a..7f19644ad10d 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs @@ -3,16 +3,18 @@ using System; using System.Collections.Generic; -using System.Text; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Reflection.Metadata; using Internal.TypeSystem; -#nullable disable - namespace Internal.TypeSystem { public static class CustomAttributeTypeNameParser { + private static readonly TypeNameParseOptions s_typeNameParseOptions = new() { MaxNodes = int.MaxValue }; + /// /// Parses the string '' and returns the type corresponding to the parsed type name. /// The type name string should be in the 'SerString' format as defined by the ECMA-335 standard. @@ -21,104 +23,169 @@ public static class CustomAttributeTypeNameParser public static TypeDesc GetTypeByCustomAttributeTypeName(this ModuleDesc module, string name, bool throwIfNotFound = true, Func canonResolver = null) { - return System.Reflection.TypeNameParser.ResolveType(module, name, throwIfNotFound, canonResolver); - } - } -} + if (!TypeName.TryParse(name.AsSpan(), out TypeName parsed, s_typeNameParseOptions)) + ThrowHelper.ThrowTypeLoadException(name, module); -namespace System.Reflection -{ - internal partial struct TypeNameParser - { - private ModuleDesc _module; - private bool _throwIfNotFound; - private Func _canonResolver; - - public static TypeDesc ResolveType(ModuleDesc module, string name, bool throwIfNotFound, - Func canonResolver) - { - return new TypeNameParser(name.AsSpan()) + return new TypeNameResolver() { + _context = module.Context, _module = module, _throwIfNotFound = throwIfNotFound, _canonResolver = canonResolver - }.Parse()?.Value; + }.Resolve(parsed); } - private sealed class Type + public static TypeDesc GetTypeByCustomAttributeTypeNameForDataFlow(string name, ModuleDesc callingModule, + TypeSystemContext context, List referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary) { - public Type(TypeDesc type) => Value = type; - public TypeDesc Value { get; } + typeWasNotFoundInAssemblyNorBaseLibrary = false; - public Type MakeArrayType() => new Type(Value.MakeArrayType()); - public Type MakeArrayType(int rank) => new Type(Value.MakeArrayType(rank)); - public Type MakePointerType() => new Type(Value.MakePointerType()); - public Type MakeByRefType() => new Type(Value.MakeByRefType()); + if (!TypeName.TryParse(name.AsSpan(), out TypeName parsed, s_typeNameParseOptions)) + return null; - public Type MakeGenericType(Type[] typeArguments) + TypeNameResolver resolver = new() { - TypeDesc[] instantiation = new TypeDesc[typeArguments.Length]; - for (int i = 0; i < typeArguments.Length; i++) - instantiation[i] = typeArguments[i].Value; - return new Type(((MetadataType)Value).MakeInstantiatedType(instantiation)); - } - } + _context = context, + _module = callingModule, + _referencedModules = referencedModules + }; - private static bool CheckTopLevelAssemblyQualifiedName() => true; + TypeDesc type = resolver.Resolve(parsed); - private Type GetType(string typeName, ReadOnlySpan nestedTypeNames, string assemblyNameIfAny) + typeWasNotFoundInAssemblyNorBaseLibrary = resolver._typeWasNotFoundInAssemblyNorBaseLibrary; + return type; + } + + private struct TypeNameResolver { - ModuleDesc module = (assemblyNameIfAny == null) ? _module : - _module.Context.ResolveAssembly(new AssemblyName(assemblyNameIfAny), throwIfNotFound: _throwIfNotFound); + internal TypeSystemContext _context; + internal ModuleDesc _module; + internal bool _throwIfNotFound; + internal Func _canonResolver; - if (_canonResolver != null && nestedTypeNames.IsEmpty) - { - MetadataType canonType = _canonResolver(module, typeName); - if (canonType != null) - return new Type(canonType); - } + internal List _referencedModules; + internal bool _typeWasNotFoundInAssemblyNorBaseLibrary; - if (module != null) + internal TypeDesc Resolve(TypeName typeName) { - Type type = GetTypeCore(module, typeName, nestedTypeNames); - if (type != null) - return type; - } + if (typeName.IsSimple) + { + return GetSimpleType(typeName); + } - // If it didn't resolve and wasn't assembly-qualified, we also try core library - if (assemblyNameIfAny == null) - { - Type type = GetTypeCore(module.Context.SystemModule, typeName, nestedTypeNames); - if (type != null) - return type; - } + if (typeName.IsConstructedGenericType) + { + return GetGenericType(typeName); + } - if (_throwIfNotFound) - ThrowHelper.ThrowTypeLoadException(EscapeTypeName(typeName, nestedTypeNames), module); - return null; - } + if (typeName.IsArray || typeName.IsPointer || typeName.IsByRef) + { + TypeDesc type = Resolve(typeName.GetElementType()); + if (type == null) + return null; - private static Type GetTypeCore(ModuleDesc module, string typeName, ReadOnlySpan nestedTypeNames) - { - (string typeNamespace, string name) = SplitFullTypeName(typeName); + if (typeName.IsArray) + return typeName.IsSZArray ? type.MakeArrayType() : type.MakeArrayType(rank: typeName.GetArrayRank()); + + if (typeName.IsPointer) + return type.MakePointerType(); - MetadataType type = module.GetType(typeNamespace, name, throwIfNotFound: false); - if (type == null) + if (typeName.IsByRef) + return type.MakeByRefType(); + } + + Debug.Fail("Expected to be unreachable"); return null; + } - for (int i = 0; i < nestedTypeNames.Length; i++) + private TypeDesc GetSimpleType(TypeName typeName) { - type = type.GetNestedType(nestedTypeNames[i]); - if (type == null) - return null; + TypeName topLevelTypeName = typeName; + while (topLevelTypeName.IsNested) + { + topLevelTypeName = topLevelTypeName.DeclaringType; + } + + ModuleDesc module = _module; + if (topLevelTypeName.AssemblyName != null) + { + module = _context.ResolveAssembly(typeName.AssemblyName, throwIfNotFound: _throwIfNotFound); + if (module == null) + return null; + } + + if (module != null) + { + TypeDesc type = GetSimpleTypeFromModule(typeName, module); + if (type != null) + { + _referencedModules?.Add(module); + return type; + } + } + + // If it didn't resolve and wasn't assembly-qualified, we also try core library + if (topLevelTypeName.AssemblyName == null) + { + if (module != _context.SystemModule) + { + TypeDesc type = GetSimpleTypeFromModule(typeName, _context.SystemModule); + if (type != null) + { + _referencedModules?.Add(_context.SystemModule); + return type; + } + } + + _typeWasNotFoundInAssemblyNorBaseLibrary = true; + } + + if (_throwIfNotFound) + ThrowHelper.ThrowTypeLoadException(typeName.FullName, module); + return null; } - return new Type(type); - } + private TypeDesc GetSimpleTypeFromModule(TypeName typeName, ModuleDesc module) + { + if (typeName.IsNested) + { + TypeDesc type = GetSimpleTypeFromModule(typeName.DeclaringType, module); + if (type == null) + return null; + return ((MetadataType)type).GetNestedType(TypeNameHelpers.Unescape(typeName.Name)); + } + + string fullName = TypeNameHelpers.Unescape(typeName.FullName); + + if (_canonResolver != null) + { + MetadataType canonType = _canonResolver(module, fullName); + if (canonType != null) + return canonType; + } + + (string typeNamespace, string name) = TypeNameHelpers.Split(fullName); + + return module.GetType(typeNamespace, name, throwIfNotFound: false); + } - private void ParseError() - { - ThrowHelper.ThrowTypeLoadException(_input.ToString(), _module); + private TypeDesc GetGenericType(TypeName typeName) + { + TypeDesc typeDefinition = Resolve(typeName.GetGenericTypeDefinition()); + if (typeDefinition == null) + return null; + + ImmutableArray typeArguments = typeName.GetGenericArguments(); + TypeDesc[] instantiation = new TypeDesc[typeArguments.Length]; + for (int i = 0; i < typeArguments.Length; i++) + { + TypeDesc type = Resolve(typeArguments[i]); + if (type == null) + return null; + instantiation[i] = type; + } + return ((MetadataType)typeDefinition).MakeInstantiatedType(instantiation); + } } } } diff --git a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/LockFreeReaderHashtable.cs b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/LockFreeReaderHashtable.cs index 613ec30fa01d..1b772684dc1c 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/LockFreeReaderHashtable.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/LockFreeReaderHashtable.cs @@ -367,7 +367,7 @@ public TValue AddOrGetExisting(TValue value) private TValue AddOrGetExistingInner(TValue value, out bool addedValue) { -#if NET5_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(value); #else if (value == null) @@ -596,7 +596,7 @@ public bool Contains(TKey key) /// Value from the hashtable if found, otherwise null. public TValue GetValueIfExists(TValue value) { -#if NET5_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(value); #else if (value == null) diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaAssembly.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaAssembly.cs index 5a281d21ba11..c59d2b5fee55 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaAssembly.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaAssembly.cs @@ -9,7 +9,7 @@ namespace Internal.TypeSystem.Ecma { public sealed partial class EcmaAssembly : EcmaModule, IAssemblyDesc { - private AssemblyName _assemblyName; + private AssemblyNameInfo _assemblyName; private AssemblyDefinition _assemblyDefinition; public AssemblyDefinition AssemblyDefinition @@ -39,20 +39,21 @@ public EcmaAssembly(TypeSystemContext context, PEReader peReader, MetadataReader _assemblyDefinition = metadataReader.GetAssemblyDefinition(); } - // Returns cached copy of the name. Caller has to create a clone before mutating the name. - public AssemblyName GetName() + public AssemblyNameInfo GetName() { if (_assemblyName == null) { MetadataReader metadataReader = this.MetadataReader; - AssemblyName an = new AssemblyName(); - an.Name = metadataReader.GetString(_assemblyDefinition.Name); - an.Version = _assemblyDefinition.Version; - an.SetPublicKey(metadataReader.GetBlobBytes(_assemblyDefinition.PublicKey)); - - an.CultureName = metadataReader.GetString(_assemblyDefinition.Culture); - an.ContentType = GetContentTypeFromAssemblyFlags(_assemblyDefinition.Flags); + AssemblyNameInfo an = new AssemblyNameInfo + ( + name: metadataReader.GetString(_assemblyDefinition.Name), + version: _assemblyDefinition.Version, + cultureName: metadataReader.GetString(_assemblyDefinition.Culture), + flags: (AssemblyNameFlags) + ((_assemblyDefinition.Flags & AssemblyFlags.ContentTypeMask) | AssemblyFlags.PublicKey), + publicKeyOrToken: metadataReader.GetBlobContent(_assemblyDefinition.PublicKey) + ); _assemblyName = an; } diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaModule.Sorting.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaModule.Sorting.cs index ec4e9709459d..8b189245e27c 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaModule.Sorting.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaModule.Sorting.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Reflection; +using System.Reflection.Metadata; using Debug = System.Diagnostics.Debug; @@ -20,8 +20,8 @@ public int CompareTo(EcmaModule other) if (thisAssembly != otherAssembly) { // Each module comes from a different assembly: compare the assemblies - AssemblyName thisAssemblyName = thisAssembly.GetName(); - AssemblyName otherAssemblyName = otherAssembly.GetName(); + AssemblyNameInfo thisAssemblyName = thisAssembly.GetName(); + AssemblyNameInfo otherAssemblyName = otherAssembly.GetName(); int compare = StringComparer.Ordinal.Compare(thisAssemblyName.Name, otherAssemblyName.Name); if (compare != 0) diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaModule.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaModule.cs index 1da6806aea42..6758f4a54986 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaModule.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaModule.cs @@ -615,22 +615,14 @@ private object ResolveAssemblyReference(AssemblyReferenceHandle handle) { AssemblyReference assemblyReference = _metadataReader.GetAssemblyReference(handle); - AssemblyName an = new AssemblyName(); - an.Name = _metadataReader.GetString(assemblyReference.Name); - an.Version = assemblyReference.Version; - - var publicKeyOrToken = _metadataReader.GetBlobBytes(assemblyReference.PublicKeyOrToken); - if ((assemblyReference.Flags & AssemblyFlags.PublicKey) != 0) - { - an.SetPublicKey(publicKeyOrToken); - } - else - { - an.SetPublicKeyToken(publicKeyOrToken); - } - - an.CultureName = _metadataReader.GetString(assemblyReference.Culture); - an.ContentType = GetContentTypeFromAssemblyFlags(assemblyReference.Flags); + AssemblyNameInfo an = new AssemblyNameInfo + ( + name: _metadataReader.GetString(assemblyReference.Name), + version: assemblyReference.Version, + cultureName: _metadataReader.GetString(assemblyReference.Culture), + flags: (AssemblyNameFlags)assemblyReference.Flags, + publicKeyOrToken: _metadataReader.GetBlobContent(assemblyReference.PublicKeyOrToken) + ); var assembly = _moduleResolver.ResolveAssembly(an, throwIfNotFound: false); if (assembly == null) @@ -687,11 +679,6 @@ public sealed override MetadataType GetGlobalModuleType() return (MetadataType)GetType(MetadataTokens.EntityHandle(0x02000001 /* COR_GLOBAL_PARENT_TOKEN */)); } - protected static AssemblyContentType GetContentTypeFromAssemblyFlags(AssemblyFlags flags) - { - return (AssemblyContentType)(((int)flags & 0x0E00) >> 9); - } - public string GetUserString(UserStringHandle userStringHandle) { // String literals are not cached diff --git a/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs b/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs index 6c9befb3a9ad..e4c4ddb42d31 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/ILImporter.cs @@ -188,10 +188,7 @@ private void FindJumpTargets() int delta = (sbyte)ReadILByte(); int target = _currentOffset + delta; if ((uint)target < (uint)_basicBlocks.Length) - { CreateBasicBlock(target); - OnLeaveTargetCreated(target); - } else ReportInvalidBranchTarget(target); } @@ -224,10 +221,7 @@ private void FindJumpTargets() int delta = (int)ReadILUInt32(); int target = _currentOffset + delta; if ((uint)target < (uint)_basicBlocks.Length) - { CreateBasicBlock(target); - OnLeaveTargetCreated(target); - } else ReportInvalidBranchTarget(target); } @@ -276,8 +270,6 @@ private void FindJumpTargets() } } - partial void OnLeaveTargetCreated(int target); - private void FindEHTargets() { for (int i = 0; i < _exceptionRegions.Length; i++) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateThunks.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateThunks.cs index 3845514eb4db..b12db35c7b59 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateThunks.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateThunks.cs @@ -686,7 +686,7 @@ public override MethodSignature Signature TypeDesc intPtrType = context.GetWellKnownType(WellKnownType.IntPtr); TypeDesc int32Type = context.GetWellKnownType(WellKnownType.Int32); - _signature = new MethodSignature(0, 0, intPtrType, new[] { int32Type }); + _signature = new MethodSignature(0, 0, intPtrType, [ int32Type ]); } return _signature; diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/ValueTypeGetFieldHelperMethodOverride.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/ValueTypeGetFieldHelperMethodOverride.cs index a66ce62ea00e..a4c967fbf967 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/ValueTypeGetFieldHelperMethodOverride.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/ValueTypeGetFieldHelperMethodOverride.cs @@ -48,10 +48,7 @@ public override MethodSignature Signature TypeDesc int32Type = context.GetWellKnownType(WellKnownType.Int32); TypeDesc eeTypePtrType = context.SystemModule.GetKnownType("Internal.Runtime", "MethodTable").MakePointerType(); - _signature = new MethodSignature(0, 0, int32Type, new[] { - int32Type, - eeTypePtrType.MakeByRefType() - }); + _signature = new MethodSignature(0, 0, int32Type, [ int32Type, eeTypePtrType.MakeByRefType() ]); } return _signature; diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs index f35e028ff49f..0dff54cd75a1 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs @@ -1170,7 +1170,7 @@ private ILLocalVariable InitializeMarshallerVariable() var customMarshallerType = Context.SystemModule.GetKnownType("System.Runtime.InteropServices", "ICustomMarshaler"); var getInstanceMethod = marshallerType.GetMethod( "GetInstance", - new MethodSignature(MethodSignatureFlags.Static, 0, customMarshallerType, new[] { Context.GetWellKnownType(WellKnownType.String) })); + new MethodSignature(MethodSignatureFlags.Static, 0, customMarshallerType, [ Context.GetWellKnownType(WellKnownType.String) ])); if (ManagedType.IsValueType || ManagedType.IsPointer || ManagedType.IsFunctionPointer) { ThrowHelper.ThrowMarshalDirectiveException(); @@ -1210,7 +1210,7 @@ protected override void TransformManagedToNative(ILCodeStream codeStream) ILEmitter emitter = _ilCodeStreams.Emitter; var manageToNativeMethod = customMarshallerType.GetKnownMethod( "MarshalManagedToNative", - new MethodSignature(MethodSignatureFlags.None, 0, Context.GetWellKnownType(WellKnownType.IntPtr), new[] { Context.GetWellKnownType(WellKnownType.Object) })); + new MethodSignature(MethodSignatureFlags.None, 0, Context.GetWellKnownType(WellKnownType.IntPtr), [ Context.GetWellKnownType(WellKnownType.Object) ])); codeStream.EmitLdLoc(lMarshaller); LoadManagedValue(codeStream); @@ -1239,7 +1239,7 @@ protected override void TransformNativeToManaged(ILCodeStream codeStream) ILEmitter emitter = _ilCodeStreams.Emitter; var marshalNativeToManagedMethod = customMarshallerType.GetKnownMethod( "MarshalNativeToManaged", - new MethodSignature(MethodSignatureFlags.None, 0, Context.GetWellKnownType(WellKnownType.Object), new[] { Context.GetWellKnownType(WellKnownType.IntPtr) })); + new MethodSignature(MethodSignatureFlags.None, 0, Context.GetWellKnownType(WellKnownType.Object), [ Context.GetWellKnownType(WellKnownType.IntPtr) ])); codeStream.EmitLdLoc(lMarshaller); LoadNativeValue(codeStream); @@ -1257,7 +1257,7 @@ protected void EmitCleanUpManagedData(ILCodeStream codeStream) // Call CleanUpManagedData on cleanup code stream. var cleanupManagedDataMethod = customMarshallerType.GetKnownMethod( "CleanUpManagedData", - new MethodSignature(MethodSignatureFlags.None, 0, Context.GetWellKnownType(WellKnownType.Void), new[] { Context.GetWellKnownType(WellKnownType.Object) })); + new MethodSignature(MethodSignatureFlags.None, 0, Context.GetWellKnownType(WellKnownType.Void), [ Context.GetWellKnownType(WellKnownType.Object) ])); codeStream.EmitLdLoc(lMarshaller); LoadManagedValue(codeStream); @@ -1274,7 +1274,7 @@ protected void EmitCleanUpNativeData(ILCodeStream codeStream) // Call CleanUpNativeData on cleanup code stream. var cleanupNativeDataMethod = customMarshallerType.GetKnownMethod( "CleanUpNativeData", - new MethodSignature(MethodSignatureFlags.None, 0, Context.GetWellKnownType(WellKnownType.Void), new[] { Context.GetWellKnownType(WellKnownType.IntPtr) })); + new MethodSignature(MethodSignatureFlags.None, 0, Context.GetWellKnownType(WellKnownType.Void), [ Context.GetWellKnownType(WellKnownType.IntPtr) ])); codeStream.EmitLdLoc(lMarshaller); LoadNativeValue(codeStream); diff --git a/src/coreclr/tools/Common/TypeSystem/MetadataEmitter/TypeSystemMetadataEmitter.cs b/src/coreclr/tools/Common/TypeSystem/MetadataEmitter/TypeSystemMetadataEmitter.cs index 62b86c968c60..76582ef0e29a 100644 --- a/src/coreclr/tools/Common/TypeSystem/MetadataEmitter/TypeSystemMetadataEmitter.cs +++ b/src/coreclr/tools/Common/TypeSystem/MetadataEmitter/TypeSystemMetadataEmitter.cs @@ -9,6 +9,7 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; +using System.Runtime.InteropServices; namespace Internal.TypeSystem { @@ -28,7 +29,7 @@ internal class TypeSystemMetadataEmitter private BlobHandle _noArgsVoidReturnStaticMethodSigHandle; protected TypeSystemContext _typeSystemContext; - public TypeSystemMetadataEmitter(AssemblyName assemblyName, TypeSystemContext context, AssemblyFlags flags = default(AssemblyFlags), byte[] publicKeyArray = null) + public TypeSystemMetadataEmitter(AssemblyNameInfo assemblyName, TypeSystemContext context, AssemblyFlags flags = default(AssemblyFlags), byte[] publicKeyArray = null) { _typeSystemContext = context; _metadataBuilder = new MetadataBuilder(); @@ -118,26 +119,27 @@ public byte[] EmitToMetadataBlob() return metadataBlobBuilder.ToArray(); } - public AssemblyReferenceHandle GetAssemblyRef(AssemblyName name) + public AssemblyReferenceHandle GetAssemblyRef(AssemblyNameInfo name) { + // References use a public key token instead of full public key. + if ((name.Flags & AssemblyNameFlags.PublicKey) != 0) + { + // Use AssemblyName to convert PublicKey to PublicKeyToken to avoid calling crypto APIs directly + AssemblyName an = new(); + an.SetPublicKey(ImmutableCollectionsMarshal.AsArray(name.PublicKeyOrToken)); + name = new AssemblyNameInfo(name.Name, name.Version, name.CultureName, name.Flags & ~AssemblyNameFlags.PublicKey, ImmutableCollectionsMarshal.AsImmutableArray(an.GetPublicKeyToken())); + } + if (!_assemblyRefNameHandles.TryGetValue(name.FullName, out var handle)) { StringHandle assemblyName = _metadataBuilder.GetOrAddString(name.Name); StringHandle cultureName = (name.CultureName != null) ? _metadataBuilder.GetOrAddString(name.CultureName) : default(StringHandle); - BlobHandle publicTokenBlob = name.GetPublicKeyToken() != null ? _metadataBuilder.GetOrAddBlob(name.GetPublicKeyToken()) : default(BlobHandle); - AssemblyFlags flags = default(AssemblyFlags); - if (name.Flags.HasFlag(AssemblyNameFlags.Retargetable)) - { - flags |= AssemblyFlags.Retargetable; - } - if (name.ContentType == AssemblyContentType.WindowsRuntime) - { - flags |= AssemblyFlags.WindowsRuntime; - } - Version version = name.Version; - if (version == null) - version = new Version(0, 0); + BlobHandle publicTokenBlob = name.PublicKeyOrToken.IsDefault ? default : _metadataBuilder.GetOrAddBlob(name.PublicKeyOrToken); + + AssemblyFlags flags = (AssemblyFlags)name.Flags & (AssemblyFlags.Retargetable | AssemblyFlags.ContentTypeMask); + + Version version = name.Version ?? new Version(0, 0); handle = _metadataBuilder.AddAssemblyReference(assemblyName, version, cultureName, publicTokenBlob, flags, default(BlobHandle)); @@ -152,7 +154,7 @@ public AssemblyReferenceHandle GetAssemblyRef(IAssemblyDesc assemblyDesc) { return handle; } - AssemblyName name = assemblyDesc.GetName(); + AssemblyNameInfo name = assemblyDesc.GetName(); var referenceHandle = GetAssemblyRef(name); _assemblyRefs.Add(assemblyDesc, referenceHandle); return referenceHandle; @@ -489,7 +491,7 @@ private sealed class EmbeddedSignatureDataEmitter private Stack _indexStack = new Stack(); private TypeSystemMetadataEmitter _metadataEmitter; - public static EmbeddedSignatureDataEmitter EmptySingleton = new EmbeddedSignatureDataEmitter(null, null); + public static readonly EmbeddedSignatureDataEmitter EmptySingleton = new EmbeddedSignatureDataEmitter(null, null); public EmbeddedSignatureDataEmitter(EmbeddedSignatureData[] embeddedData, TypeSystemMetadataEmitter metadataEmitter) { diff --git a/src/coreclr/tools/ILVerification/AccessVerificationHelpers.cs b/src/coreclr/tools/ILVerification/AccessVerificationHelpers.cs index ef694cbc8251..81cc18f0c778 100644 --- a/src/coreclr/tools/ILVerification/AccessVerificationHelpers.cs +++ b/src/coreclr/tools/ILVerification/AccessVerificationHelpers.cs @@ -2,8 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Immutable; using System.Diagnostics; +using System.Linq; using System.Reflection; +using System.Reflection.Metadata; +using System.Runtime.InteropServices; + using Internal.TypeSystem; using Internal.TypeSystem.Ecma; @@ -244,37 +249,31 @@ private static bool GrantsFriendAccessTo(this ModuleDesc module, ModuleDesc frie foreach (var attribute in assembly.GetDecodedCustomAttributes("System.Runtime.CompilerServices", "InternalsVisibleToAttribute")) { - AssemblyName friendAttributeName = new AssemblyName((string)attribute.FixedArguments[0].Value); + AssemblyNameInfo friendAttributeName = AssemblyNameInfo.Parse(((string)attribute.FixedArguments[0].Value).AsSpan()); if (!friendName.Name.Equals(friendAttributeName.Name, StringComparison.OrdinalIgnoreCase)) continue; - // Comparing PublicKeyToken, since GetPublicKey returns null due to a bug - if (IsSamePublicKey(friendAttributeName.GetPublicKeyToken(), friendName.GetPublicKeyToken())) + // Comparing PublicKeyToken for simplicity + if (GetPublicKeyToken(friendAttributeName).SequenceEqual(GetPublicKeyToken(friendName))) return true; + + static ReadOnlySpan GetPublicKeyToken(AssemblyNameInfo assemblyName) + { + ImmutableArray publicKeyOrToken = assemblyName.PublicKeyOrToken; + if ((assemblyName.Flags & AssemblyNameFlags.PublicKey) != 0) + { + // Use AssemblyName to convert PublicKey to PublicKeyToken to avoid calling crypto APIs directly + AssemblyName an = new(); + an.SetPublicKey(ImmutableCollectionsMarshal.AsArray(publicKeyOrToken)); + publicKeyOrToken = ImmutableCollectionsMarshal.AsImmutableArray(an.GetPublicKeyToken()); + } + return publicKeyOrToken.AsSpan(); + } } } return false; } - private static bool IsSamePublicKey(byte[] key1, byte[] key2) - { - if (key1 == null) - return key2 == null || key2.Length == 0; - if (key2 == null) - return key1 == null || key1.Length == 0; - - if (key1.Length != key2.Length) - return false; - - for (int i = 0; i < key1.Length; ++i) - { - if (key1[i] != key2[i]) - return false; - } - - return true; - } - private static MethodAttributes NestedToMethodAccessAttribute(TypeAttributes nestedVisibility) { switch (nestedVisibility & TypeAttributes.VisibilityMask) diff --git a/src/coreclr/tools/ILVerification/ILVerification.projitems b/src/coreclr/tools/ILVerification/ILVerification.projitems index 81ce9f65d113..fc02753d6010 100644 --- a/src/coreclr/tools/ILVerification/ILVerification.projitems +++ b/src/coreclr/tools/ILVerification/ILVerification.projitems @@ -66,8 +66,8 @@ Utilities\CustomAttributeTypeNameParser.cs - - Utilities\TypeNameParser.cs + + Utilities\TypeNameHelpers.cs Utilities\ValueStringBuilder.cs diff --git a/src/coreclr/tools/ILVerification/ILVerifyTypeSystemContext.cs b/src/coreclr/tools/ILVerification/ILVerifyTypeSystemContext.cs index 52d6d43edb7c..05a4a3bbc559 100644 --- a/src/coreclr/tools/ILVerification/ILVerifyTypeSystemContext.cs +++ b/src/coreclr/tools/ILVerification/ILVerifyTypeSystemContext.cs @@ -28,7 +28,7 @@ public ILVerifyTypeSystemContext(IResolver resolver) _resolver = resolver; } - public override ModuleDesc ResolveAssembly(AssemblyName name, bool throwIfNotFound = true) + public override ModuleDesc ResolveAssembly(AssemblyNameInfo name, bool throwIfNotFound = true) { return CacheResolvedAssemblyOrNetmodule(_resolver.ResolveAssembly(name), name.Name, null, throwIfNotFound); } diff --git a/src/coreclr/tools/ILVerification/IResolver.cs b/src/coreclr/tools/ILVerification/IResolver.cs index 1fd03d02756c..751aad4c05ae 100644 --- a/src/coreclr/tools/ILVerification/IResolver.cs +++ b/src/coreclr/tools/ILVerification/IResolver.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; -using System.Reflection; +using System.Reflection.Metadata; using System.Reflection.PortableExecutable; namespace ILVerify @@ -12,11 +12,11 @@ public interface IResolver /// /// Resolve assembly to PEReader. This method should return the same instance when queried multiple times. /// - PEReader ResolveAssembly(AssemblyName assemblyName); + PEReader ResolveAssembly(AssemblyNameInfo assemblyName); /// /// Resolve module to PEReader. This method should return the same instance when queried multiple times. /// - PEReader ResolveModule(AssemblyName referencingAssembly, string fileName); + PEReader ResolveModule(AssemblyNameInfo referencingAssembly, string fileName); } } diff --git a/src/coreclr/tools/ILVerification/Verifier.cs b/src/coreclr/tools/ILVerification/Verifier.cs index 46610485d2da..5283521515ad 100644 --- a/src/coreclr/tools/ILVerification/Verifier.cs +++ b/src/coreclr/tools/ILVerification/Verifier.cs @@ -34,7 +34,7 @@ internal Verifier(ILVerifyTypeSystemContext context, VerifierOptions verifierOpt _verifierOptions = verifierOptions ?? new VerifierOptions(); } - public void SetSystemModuleName(AssemblyName name) + public void SetSystemModuleName(AssemblyNameInfo name) { PEReader peReader = _typeSystemContext._resolver.ResolveAssembly(name); if (peReader is null) diff --git a/src/coreclr/tools/ILVerify/ILVerify.csproj b/src/coreclr/tools/ILVerify/ILVerify.csproj index e1915c65d6f2..804f32ddc7bc 100644 --- a/src/coreclr/tools/ILVerify/ILVerify.csproj +++ b/src/coreclr/tools/ILVerify/ILVerify.csproj @@ -17,6 +17,7 @@ + diff --git a/src/coreclr/tools/ILVerify/Program.cs b/src/coreclr/tools/ILVerify/Program.cs index 908de5b701f3..88da48f50fb0 100644 --- a/src/coreclr/tools/ILVerify/Program.cs +++ b/src/coreclr/tools/ILVerify/Program.cs @@ -113,13 +113,13 @@ public int Run() IncludeMetadataTokensInErrorMessages = Get(_command.Tokens), SanityChecks = Get(_command.SanityChecks) }); - _verifier.SetSystemModuleName(new AssemblyName(Get(_command.SystemModule) ?? "mscorlib")); + _verifier.SetSystemModuleName(new AssemblyNameInfo(Get(_command.SystemModule) ?? "mscorlib")); int numErrors = 0; foreach (var kvp in _inputFilePaths) { - numErrors += VerifyAssembly(new AssemblyName(kvp.Key), kvp.Value); + numErrors += VerifyAssembly(new AssemblyNameInfo(kvp.Key), kvp.Value); } if (numErrors > 0) @@ -224,7 +224,7 @@ private static void PrintMethod(EcmaMethod method) Write(")"); } - private int VerifyAssembly(AssemblyName name, string path) + private int VerifyAssembly(AssemblyNameInfo name, string path) { PEReader peReader = Resolve(name.Name); EcmaModule module = _verifier.GetModule(peReader); @@ -451,10 +451,10 @@ private bool ShouldIgnoreVerificationResult(VerificationResult result) return false; } - PEReader IResolver.ResolveAssembly(AssemblyName assemblyName) + PEReader IResolver.ResolveAssembly(AssemblyNameInfo assemblyName) => Resolve(assemblyName.Name); - PEReader IResolver.ResolveModule(AssemblyName referencingModule, string fileName) + PEReader IResolver.ResolveModule(AssemblyNameInfo referencingModule, string fileName) => Resolve(Path.GetFileNameWithoutExtension(fileName)); public PEReader Resolve(string simpleName) diff --git a/src/coreclr/tools/StressLogAnalyzer/StressLogDump.cpp b/src/coreclr/tools/StressLogAnalyzer/StressLogDump.cpp index eadc27e2557c..379f6e3ccaf0 100644 --- a/src/coreclr/tools/StressLogAnalyzer/StressLogDump.cpp +++ b/src/coreclr/tools/StressLogAnalyzer/StressLogDump.cpp @@ -50,9 +50,9 @@ static const char* getTime(const FILETIME* time, _Out_writes_ (buffLen) char* bu } /*********************************************************************************/ -static inline __int64& toInt64(FILETIME& t) +static inline int64_t& toInt64(FILETIME& t) { - return *((__int64 *) &t); + return *((int64_t *) &t); } /*********************************************************************************/ @@ -362,7 +362,7 @@ HRESULT StressLog::Dump(ULONG64 outProcLog, const char* fileName, struct IDebugD ThreadStressLog* inProcPtr; ThreadStressLog** logsPtr = &logs; int threadCtr = 0; - unsigned __int64 lastTimeStamp = 0;// timestamp of last log entry + uint64_t lastTimeStamp = 0;// timestamp of last log entry while(outProcPtr != 0) { inProcPtr = new ThreadStressLog; @@ -381,7 +381,7 @@ HRESULT StressLog::Dump(ULONG64 outProcLog, const char* fileName, struct IDebugD do { StressLogChunk * inProcChunkPtr = new StressLogChunk; - hr = memCallBack->ReadVirtual (outProcChunkPtr, inProcChunkPtr, sizeof (*inProcChunkPtr), NULL); + hr = memCallBack->ReadVirtual (outProcChunkPtr, inProcChunkPtr, sizeof (*inProcChunkPtr), 0); if (hr != S_OK || !inProcChunkPtr->IsValid ()) { if (hr != S_OK) @@ -459,7 +459,7 @@ HRESULT StressLog::Dump(ULONG64 outProcLog, const char* fileName, struct IDebugD FILETIME endTime; double totalSecs; totalSecs = ((double) (lastTimeStamp - inProcLog.startTimeStamp)) / inProcLog.tickFrequency; - toInt64(endTime) = toInt64(inProcLog.startTime) + ((__int64) (totalSecs * 1.0E7)); + toInt64(endTime) = toInt64(inProcLog.startTime) + ((int64_t) (totalSecs * 1.0E7)); char timeBuff[64]; vDoOut(bDoGcHist, file, " Clock frequency = %5.3f GHz\n", inProcLog.tickFrequency / 1.0E9); diff --git a/src/coreclr/tools/aot/AotCompilerCommon.props b/src/coreclr/tools/aot/AotCompilerCommon.props index 09d3cfdc92ed..cc1064820581 100644 --- a/src/coreclr/tools/aot/AotCompilerCommon.props +++ b/src/coreclr/tools/aot/AotCompilerCommon.props @@ -4,6 +4,8 @@ false true Speed + Guard + true diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj index 575f785c05dc..2e0b217160f9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj @@ -5,7 +5,7 @@ false false true - netstandard2.0 + $(NetCoreAppToolCurrent) true false diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs index 979ade817b3d..0cf8ec163879 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs @@ -40,7 +40,7 @@ protected override void ProcessAssembly(ModuleDesc assembly, XPathNavigator nav, ProcessTypes(assembly, nav, warnOnUnresolvedTypes); } - // protected override TypeDesc? ProcessExportedType(ExportedType exported, ModuleDesc assembly, XPathNavigator nav) => null; + protected override MetadataType ProcessExportedType(MetadataType exported, ModuleDesc assembly, XPathNavigator nav) => null; protected override bool ProcessTypePattern(string fullname, ModuleDesc assembly, XPathNavigator nav) => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs index 31c868a77f00..bf0ea7662fec 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs @@ -326,7 +326,7 @@ public ISymbolNode ComputeConstantLookup(ReadyToRunHelperId lookupKind, object t { var type = (TypeDesc)targetOfLookup; MethodDesc ctor = GetConstructorForCreateInstanceIntrinsic(type); - return NodeFactory.CanonicalEntrypoint(ctor); + return type.IsValueType ? NodeFactory.ExactCallableAddress(ctor) : NodeFactory.CanonicalEntrypoint(ctor); } case ReadyToRunHelperId.ObjectAllocator: { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerTypeSystemContext.GeneratedAssembly.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerTypeSystemContext.GeneratedAssembly.cs index aa2da8a6cd17..fc2299858626 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerTypeSystemContext.GeneratedAssembly.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerTypeSystemContext.GeneratedAssembly.cs @@ -3,12 +3,12 @@ using System; using System.Collections.Generic; +using System.Reflection.Metadata; using Internal.TypeSystem; using TypeHashingAlgorithms = Internal.NativeFormat.TypeHashingAlgorithms; using Interlocked = System.Threading.Interlocked; -using AssemblyName = System.Reflection.AssemblyName; using Debug = System.Diagnostics.Debug; namespace ILCompiler @@ -52,9 +52,9 @@ public override MetadataType GetGlobalModuleType() return _globalModuleType; } - public AssemblyName GetName() + public AssemblyNameInfo GetName() { - return new AssemblyName("System.Private.CompilerGenerated"); + return new AssemblyNameInfo("System.Private.CompilerGenerated"); } public override object GetType(string nameSpace, string name, NotFoundBehavior notFoundBehavior) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs index c978db72f5f6..fd8094bc7028 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs @@ -253,7 +253,7 @@ public bool ShouldWarnWhenAccessedForReflection(FieldDesc field) public static bool IsTypeInterestingForDataflow(TypeDesc type) { - // NOTE: this method is not particulary fast. It's assumed that the caller limits + // NOTE: this method is not particularly fast. It's assumed that the caller limits // calls to this method as much as possible. if (type.IsWellKnownType(WellKnownType.String)) @@ -951,12 +951,12 @@ internal partial bool MethodRequiresDataFlowAnalysis(MethodProxy method) => RequiresDataflowAnalysisDueToSignature(method.Method); #pragma warning disable CA1822 // Other partial implementations are not in the ilc project - internal partial MethodReturnValue GetMethodReturnValue(MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + internal partial MethodReturnValue GetMethodReturnValue(MethodProxy method, bool isNewObj, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) #pragma warning restore CA1822 // Mark members as static - => new MethodReturnValue(method.Method, dynamicallyAccessedMemberTypes); + => new MethodReturnValue(method.Method, isNewObj, dynamicallyAccessedMemberTypes); - internal partial MethodReturnValue GetMethodReturnValue(MethodProxy method) - => GetMethodReturnValue(method, GetReturnParameterAnnotation(method.Method)); + internal partial MethodReturnValue GetMethodReturnValue(MethodProxy method, bool isNewObj) + => GetMethodReturnValue(method, isNewObj, GetReturnParameterAnnotation(method.Method)); internal partial GenericParameterValue GetGenericParameterValue(GenericParameterProxy genericParameter) => new GenericParameterValue(genericParameter.GenericParameter, GetGenericParameterAnnotation(genericParameter.GenericParameter)); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs index f09a76221ef3..7207efb6d03f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs @@ -2,12 +2,18 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics; using System.Reflection; using ILCompiler; using ILCompiler.Dataflow; +using ILCompiler.DependencyAnalysis; +using ILCompiler.DependencyAnalysisFramework; using ILLink.Shared.TypeSystemProxy; using Internal.TypeSystem; +using Internal.IL; +using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; +using MultiValue = ILLink.Shared.DataFlow.ValueSet; using WellKnownType = ILLink.Shared.TypeSystemProxy.WellKnownType; #nullable enable @@ -19,17 +25,21 @@ internal partial struct HandleCallAction #pragma warning disable CA1822 // Mark members as static - the other partial implementations might need to be instance methods private readonly ReflectionMarker _reflectionMarker; + private ILOpcode _operation; private readonly MethodDesc _callingMethod; private readonly string _reason; public HandleCallAction( FlowAnnotations annotations, + ILOpcode operation, ReflectionMarker reflectionMarker, in DiagnosticContext diagnosticContext, MethodDesc callingMethod, string reason) { _reflectionMarker = reflectionMarker; + _operation = operation; + _isNewObj = operation == ILOpcode.newobj; _diagnosticContext = diagnosticContext; _callingMethod = callingMethod; _annotations = annotations; @@ -37,6 +47,518 @@ public HandleCallAction( _requireDynamicallyAccessedMembersAction = new(reflectionMarker, diagnosticContext, reason); } + private partial bool TryHandleIntrinsic ( + MethodProxy calledMethod, + MultiValue instanceValue, + IReadOnlyList argumentValues, + IntrinsicId intrinsicId, + out MultiValue? methodReturnValue) + { + MultiValue? maybeMethodReturnValue = methodReturnValue = null; + + switch (intrinsicId) + { + case IntrinsicId.Type_MakeGenericType: + { + bool triggersWarning = false; + + if (!instanceValue.IsEmpty() && !argumentValues[0].IsEmpty()) + { + foreach (var value in instanceValue.AsEnumerable()) + { + if (value is SystemTypeValue typeValue) + { + TypeDesc typeInstantiated = typeValue.RepresentedType.Type; + if (!typeInstantiated.IsGenericDefinition) + { + // Nothing to do, will fail at runtime + } + else if (TryGetMakeGenericInstantiation(_callingMethod, argumentValues[0], out Instantiation inst, out bool isExact)) + { + if (inst.Length == typeInstantiated.Instantiation.Length) + { + typeInstantiated = ((MetadataType)typeInstantiated).MakeInstantiatedType(inst); + + if (isExact) + { + _reflectionMarker.MarkType(_diagnosticContext.Origin, typeInstantiated, "MakeGenericType"); + } + else + { + _reflectionMarker.RuntimeDeterminedDependencies.Add(new MakeGenericTypeSite(typeInstantiated)); + } + } + } + else + { + triggersWarning = true; + } + + } + else if (value == NullValue.Instance) + { + // Nothing to do + } + else + { + // We don't know what type the `MakeGenericType` was called on + triggersWarning = true; + } + } + } + + if (triggersWarning) + { + ReflectionMethodBodyScanner.CheckAndReportRequires(_diagnosticContext, calledMethod.Method, DiagnosticUtilities.RequiresDynamicCodeAttribute); + } + + // This intrinsic is relevant to both trimming and AOT - call into trimming logic as well. + return TryHandleSharedIntrinsic(calledMethod, instanceValue, argumentValues, intrinsicId, out methodReturnValue); + } + + case IntrinsicId.MethodInfo_MakeGenericMethod: + { + bool triggersWarning = false; + + if (!instanceValue.IsEmpty()) + { + foreach (var methodValue in instanceValue.AsEnumerable()) + { + if (methodValue is SystemReflectionMethodBaseValue methodBaseValue) + { + MethodDesc methodInstantiated = methodBaseValue.RepresentedMethod.Method; + if (!methodInstantiated.IsGenericMethodDefinition) + { + // Nothing to do, will fail at runtime + } + else if (!methodInstantiated.OwningType.IsGenericDefinition + && TryGetMakeGenericInstantiation(_callingMethod, argumentValues[0], out Instantiation inst, out bool isExact)) + { + if (inst.Length == methodInstantiated.Instantiation.Length) + { + methodInstantiated = methodInstantiated.MakeInstantiatedMethod(inst); + + if (isExact) + { + _reflectionMarker.MarkMethod(_diagnosticContext.Origin, methodInstantiated, "MakeGenericMethod"); + } + else + { + _reflectionMarker.RuntimeDeterminedDependencies.Add(new MakeGenericMethodSite(methodInstantiated)); + } + } + } + else + { + // If the owning type is a generic definition, we can't help much. + triggersWarning = true; + } + } + else if (methodValue == NullValue.Instance) + { + // Nothing to do + } + else + { + // We don't know what method the `MakeGenericMethod` was called on + triggersWarning = true; + } + } + } + + if (triggersWarning) + { + ReflectionMethodBodyScanner.CheckAndReportRequires(_diagnosticContext, calledMethod.Method, DiagnosticUtilities.RequiresDynamicCodeAttribute); + } + + // This intrinsic is relevant to both trimming and AOT - call into trimming logic as well. + return TryHandleSharedIntrinsic(calledMethod, instanceValue, argumentValues, intrinsicId, out methodReturnValue); + } + + case IntrinsicId.None: + { + if (ReflectionMethodBodyScanner.IsPInvokeDangerous(calledMethod.Method, out bool comDangerousMethod, out bool aotUnsafeDelegate)) + { + if (aotUnsafeDelegate) + { + _diagnosticContext.AddDiagnostic(DiagnosticId.CorrectnessOfAbstractDelegatesCannotBeGuaranteed, calledMethod.GetDisplayName()); + } + + if (comDangerousMethod) + { + _diagnosticContext.AddDiagnostic(DiagnosticId.CorrectnessOfCOMCannotBeGuaranteed, calledMethod.GetDisplayName()); + } + } + + ReflectionMethodBodyScanner.CheckAndReportAllRequires(_diagnosticContext, calledMethod.Method); + + return TryHandleSharedIntrinsic(calledMethod, instanceValue, argumentValues, intrinsicId, out methodReturnValue); + } + + case IntrinsicId.TypeDelegator_Ctor: + { + // This is an identity function for analysis purposes + if (_operation == ILOpcode.newobj) + AddReturnValue(argumentValues[0]); + } + break; + + case IntrinsicId.Array_Empty: + { + AddReturnValue(ArrayValue.Create(0, calledMethod.Method.Instantiation[0])); + } + break; + + // + // System.Array + // + // CreateInstance (Type, Int32) + // + case IntrinsicId.Array_CreateInstance: + { + // We could try to analyze if the type is known, but for now making sure this works for canonical arrays is enough. + TypeDesc canonArrayType = _reflectionMarker.Factory.TypeSystemContext.CanonType.MakeArrayType(); + _reflectionMarker.MarkType(_diagnosticContext.Origin, canonArrayType, "Array.CreateInstance was called"); + } + break; + + // + // System.Enum + // + // static GetValues (Type) + // + case IntrinsicId.Enum_GetValues: + { + // Enum.GetValues returns System.Array, but it's the array of the enum type under the hood + // and people depend on this undocumented detail (could have returned enum of the underlying + // type instead). + // + // At least until we have shared enum code, this needs extra handling to get it right. + foreach (var value in argumentValues[0].AsEnumerable ()) + { + if (value is SystemTypeValue systemTypeValue + && !systemTypeValue.RepresentedType.Type.IsGenericDefinition + && !systemTypeValue.RepresentedType.Type.ContainsSignatureVariables(treatGenericParameterLikeSignatureVariable: true)) + { + if (systemTypeValue.RepresentedType.Type.IsEnum) + { + _reflectionMarker.Dependencies.Add(_reflectionMarker.Factory.ReflectedType(systemTypeValue.RepresentedType.Type.MakeArrayType()), "Enum.GetValues"); + } + } + else + ReflectionMethodBodyScanner.CheckAndReportRequires(_diagnosticContext, calledMethod.Method, DiagnosticUtilities.RequiresDynamicCodeAttribute); + } + } + break; + + // + // System.Runtime.InteropServices.Marshal + // + // static SizeOf (Type) + // static PtrToStructure (IntPtr, Type) + // static DestroyStructure (IntPtr, Type) + // static OffsetOf (Type, string) + // + case IntrinsicId.Marshal_SizeOf: + case IntrinsicId.Marshal_PtrToStructure: + case IntrinsicId.Marshal_DestroyStructure: + case IntrinsicId.Marshal_OffsetOf: + { + int paramIndex = intrinsicId == IntrinsicId.Marshal_SizeOf + || intrinsicId == IntrinsicId.Marshal_OffsetOf + ? 0 : 1; + + // We need the data to do struct marshalling. + foreach (var value in argumentValues[paramIndex].AsEnumerable ()) + { + if (value is SystemTypeValue systemTypeValue + && !systemTypeValue.RepresentedType.Type.IsGenericDefinition + && !systemTypeValue.RepresentedType.Type.ContainsSignatureVariables(treatGenericParameterLikeSignatureVariable: true)) + { + if (systemTypeValue.RepresentedType.Type.IsDefType) + { + _reflectionMarker.Dependencies.Add(_reflectionMarker.Factory.StructMarshallingData((DefType)systemTypeValue.RepresentedType.Type), "Marshal API"); + if (intrinsicId == IntrinsicId.Marshal_PtrToStructure + && systemTypeValue.RepresentedType.Type.GetParameterlessConstructor() is MethodDesc ctorMethod + && !_reflectionMarker.Factory.MetadataManager.IsReflectionBlocked(ctorMethod)) + { + _reflectionMarker.Dependencies.Add(_reflectionMarker.Factory.ReflectedMethod(ctorMethod.GetCanonMethodTarget(CanonicalFormKind.Specific)), "Marshal API"); + } + } + } + else + ReflectionMethodBodyScanner.CheckAndReportRequires(_diagnosticContext, calledMethod.Method, DiagnosticUtilities.RequiresDynamicCodeAttribute); + } + } + break; + + // + // System.Runtime.InteropServices.Marshal + // + // static GetDelegateForFunctionPointer (IntPtr, Type) + // + case IntrinsicId.Marshal_GetDelegateForFunctionPointer: + { + // We need the data to do delegate marshalling. + foreach (var value in argumentValues[1].AsEnumerable ()) + { + if (value is SystemTypeValue systemTypeValue + && !systemTypeValue.RepresentedType.Type.IsGenericDefinition + && !systemTypeValue.RepresentedType.Type.ContainsSignatureVariables(treatGenericParameterLikeSignatureVariable: true)) + { + if (systemTypeValue.RepresentedType.Type.IsDelegate) + { + _reflectionMarker.Dependencies.Add(_reflectionMarker.Factory.DelegateMarshallingData((DefType)systemTypeValue.RepresentedType.Type), "Marshal API"); + } + } + else + ReflectionMethodBodyScanner.CheckAndReportRequires(_diagnosticContext, calledMethod.Method, DiagnosticUtilities.RequiresDynamicCodeAttribute); + } + } + break; + + // + // System.Delegate + // + // get_Method () + // + // System.Reflection.RuntimeReflectionExtensions + // + // GetMethodInfo (System.Delegate) + // + case IntrinsicId.RuntimeReflectionExtensions_GetMethodInfo: + case IntrinsicId.Delegate_get_Method: + { + // Find the parameter: first is an instance method, second is an extension method. + MultiValue param = intrinsicId == IntrinsicId.RuntimeReflectionExtensions_GetMethodInfo + ? argumentValues[0] : instanceValue; + + // If this is Delegate.Method accessed from RuntimeReflectionExtensions.GetMethodInfo, ignore + // because we handle the callsites to that one here as well. + if (Intrinsics.GetIntrinsicIdForMethod(_callingMethod) == IntrinsicId.RuntimeReflectionExtensions_GetMethodInfo) + break; + + foreach (var valueNode in param.AsEnumerable()) + { + TypeDesc? staticType = (valueNode as IValueWithStaticType)?.StaticType?.Type; + if (staticType is null || !staticType.IsDelegate) + { + // The static type is unknown or something useless like Delegate or MulticastDelegate. + _reflectionMarker.Dependencies.Add(_reflectionMarker.Factory.ReflectedDelegate(null), "Delegate.Method access on unknown delegate type"); + } + else + { + if (staticType.ContainsSignatureVariables(treatGenericParameterLikeSignatureVariable: true)) + _reflectionMarker.Dependencies.Add(_reflectionMarker.Factory.ReflectedDelegate(staticType.GetTypeDefinition()), "Delegate.Method access (on inexact type)"); + else + _reflectionMarker.Dependencies.Add(_reflectionMarker.Factory.ReflectedDelegate(staticType.ConvertToCanonForm(CanonicalFormKind.Specific)), "Delegate.Method access"); + } + } + } + break; + + // + // System.Object + // + // GetType() + // + case IntrinsicId.Object_GetType: + { + foreach (var valueNode in instanceValue.AsEnumerable ()) + { + // Note that valueNode can be statically typed in IL as some generic argument type. + // For example: + // void Method(T instance) { instance.GetType().... } + // Currently this case will end up with null StaticType - since there's no typedef for the generic argument type. + // But it could be that T is annotated with for example PublicMethods: + // void Method<[DAM(PublicMethods)] T>(T instance) { instance.GetType().GetMethod("Test"); } + // In this case it's in theory possible to handle it, by treating the T basically as a base class + // for the actual type of "instance". But the analysis for this would be pretty complicated (as the marking + // has to happen on the callsite, which doesn't know that GetType() will be used...). + // For now we're intentionally ignoring this case - it will produce a warning. + // The counter example is: + // Method(new Derived); + // In this case to get correct results, trimmer would have to mark all public methods on Derived. Which + // currently it won't do. + + TypeDesc? staticType = (valueNode as IValueWithStaticType)?.StaticType?.Type; + if (staticType is null || (!staticType.IsDefType && !staticType.IsArray)) + { + // We don't know anything about the type GetType was called on. Track this as a usual "result of a method call without any annotations" + AddReturnValue(_reflectionMarker.Annotations.GetMethodReturnValue(calledMethod, _isNewObj)); + } + else if (staticType.IsSealed() || staticType.IsTypeOf("System", "Delegate")) + { + // We can treat this one the same as if it was a typeof() expression + + // We can allow Object.GetType to be modeled as System.Delegate because we keep all methods + // on delegates anyway so reflection on something this approximation would miss is actually safe. + + // We ignore the fact that the type can be annotated (see below for handling of annotated types) + // This means the annotations (if any) won't be applied - instead we rely on the exact knowledge + // of the type. So for example even if the type is annotated with PublicMethods + // but the code calls GetProperties on it - it will work - mark properties, don't mark methods + // since we ignored the fact that it's annotated. + // This can be seen a little bit as a violation of the annotation, but we already have similar cases + // where a parameter is annotated and if something in the method sets a specific known type to it + // we will also make it just work, even if the annotation doesn't match the usage. + AddReturnValue(new SystemTypeValue(staticType)); + } + else + { + Debug.Assert(staticType is MetadataType || staticType.IsArray); + MetadataType closestMetadataType = staticType is MetadataType mdType ? + mdType : (MetadataType)_reflectionMarker.Factory.TypeSystemContext.GetWellKnownType(Internal.TypeSystem.WellKnownType.Array); + + var annotation = _reflectionMarker.Annotations.GetTypeAnnotation(staticType); + + if (annotation != default) + { + _reflectionMarker.Dependencies.Add(_reflectionMarker.Factory.ObjectGetTypeFlowDependencies(closestMetadataType), "GetType called on this type"); + } + + // Return a value which is "unknown type" with annotation. For now we'll use the return value node + // for the method, which means we're loosing the information about which staticType this + // started with. For now we don't need it, but we can add it later on. + AddReturnValue(_reflectionMarker.Annotations.GetMethodReturnValue(calledMethod, _isNewObj, annotation)); + } + } + } + break; + + // + // string System.Reflection.Assembly.Location getter + // string System.Reflection.AssemblyName.CodeBase getter + // string System.Reflection.AssemblyName.EscapedCodeBase getter + // + case IntrinsicId.Assembly_get_Location: + case IntrinsicId.AssemblyName_get_CodeBase: + case IntrinsicId.AssemblyName_get_EscapedCodeBase: + _diagnosticContext.AddDiagnostic(DiagnosticId.AvoidAssemblyLocationInSingleFile, calledMethod.GetDisplayName()); + break; + + // + // string System.Reflection.Assembly.GetFile(string) + // string System.Reflection.Assembly.GetFiles() + // string System.Reflection.Assembly.GetFiles(bool) + // + case IntrinsicId.Assembly_GetFile: + case IntrinsicId.Assembly_GetFiles: + _diagnosticContext.AddDiagnostic(DiagnosticId.AvoidAssemblyGetFilesInSingleFile, calledMethod.GetDisplayName()); + break; + + default: + return false; + } + + methodReturnValue = maybeMethodReturnValue; + return true; + + void AddReturnValue(MultiValue value) + { + maybeMethodReturnValue = (maybeMethodReturnValue is null) ? value : MultiValueLattice.Meet((MultiValue)maybeMethodReturnValue, value); + } + } + + private static bool TryGetMakeGenericInstantiation( + MethodDesc contextMethod, + in MultiValue genericParametersArray, + out Instantiation inst, + out bool isExact) + { + // We support calling MakeGeneric APIs with a very concrete instantiation array. + // Only the form of `new Type[] { typeof(Foo), typeof(T), typeof(Foo) }` is supported. + + inst = default; + isExact = true; + Debug.Assert(contextMethod.GetTypicalMethodDefinition() == contextMethod); + + var typesValue = genericParametersArray.AsSingleValue(); + if (typesValue is NullValue) + { + // This will fail at runtime but no warning needed + inst = Instantiation.Empty; + return true; + } + + // Is this an array we model? + if (typesValue is not ArrayValue array) + { + return false; + } + + int? size = array.Size.AsConstInt(); + if (size == null) + { + return false; + } + + TypeDesc[]? sigInst = null; + TypeDesc[]? defInst = null; + + ArrayBuilder result = default; + for (int i = 0; i < size.Value; i++) + { + // Go over each element of the array. If the value is unknown, bail. + if (!array.TryGetValueByIndex(i, out MultiValue value)) + { + return false; + } + + var singleValue = value.AsSingleValue(); + + TypeDesc? type = singleValue switch + { + SystemTypeValue systemType => systemType.RepresentedType.Type, + GenericParameterValue genericParamType => genericParamType.GenericParameter.GenericParameter, + NullableSystemTypeValue nullableSystemType => nullableSystemType.NullableType.Type, + _ => null + }; + + if (type is null) + { + return false; + } + + // type is now some type. + // Because dataflow analysis oddly operates on method bodies instantiated over + // generic parameters (as opposed to instantiated over signature variables) + // We need to swap generic parameters (T, U,...) for signature variables (!0, !!1,...). + // We need to do this for both generic parameters of the owning type, and generic + // parameters of the owning method. + if (type.ContainsSignatureVariables(treatGenericParameterLikeSignatureVariable: true)) + { + if (sigInst == null) + { + TypeDesc contextType = contextMethod.OwningType; + sigInst = new TypeDesc[contextType.Instantiation.Length + contextMethod.Instantiation.Length]; + defInst = new TypeDesc[contextType.Instantiation.Length + contextMethod.Instantiation.Length]; + TypeSystemContext context = type.Context; + for (int j = 0; j < contextType.Instantiation.Length; j++) + { + sigInst[j] = context.GetSignatureVariable(j, method: false); + defInst[j] = contextType.Instantiation[j]; + } + for (int j = 0; j < contextMethod.Instantiation.Length; j++) + { + sigInst[j + contextType.Instantiation.Length] = context.GetSignatureVariable(j, method: true); + defInst[j + contextType.Instantiation.Length] = contextMethod.Instantiation[j]; + } + } + + isExact = false; + + // defInst is [T, U, V], sigInst is `[!0, !!0, !!1]`. + type = type.ReplaceTypesInConstructionOfType(defInst, sigInst); + } + + result.Add(type); + } + + inst = new Instantiation(result.ToArray()); + return true; + } + private partial bool MethodIsTypeConstructor(MethodProxy method) { if (!method.Method.IsConstructor) @@ -124,5 +646,34 @@ private partial bool MarkAssociatedProperty(MethodProxy method) } private partial string GetContainingSymbolDisplayName() => _callingMethod.GetDisplayName(); + + private sealed class MakeGenericMethodSite : INodeWithRuntimeDeterminedDependencies + { + private readonly MethodDesc _method; + + public MakeGenericMethodSite(MethodDesc method) => _method = method; + + public IEnumerable.DependencyListEntry> InstantiateDependencies(NodeFactory factory, Instantiation typeInstantiation, Instantiation methodInstantiation) + { + var list = new DependencyList(); + RootingHelpers.TryGetDependenciesForReflectedMethod(ref list, factory, _method.InstantiateSignature(typeInstantiation, methodInstantiation), "MakeGenericMethod"); + return list; + } + } + + private sealed class MakeGenericTypeSite : INodeWithRuntimeDeterminedDependencies + { + private readonly TypeDesc _type; + + public MakeGenericTypeSite(TypeDesc type) => _type = type; + + public IEnumerable.DependencyListEntry> InstantiateDependencies(NodeFactory factory, Instantiation typeInstantiation, Instantiation methodInstantiation) + { + var list = new DependencyList(); + RootingHelpers.TryGetDependenciesForReflectedType(ref list, factory, _type.InstantiateSignature(typeInstantiation, methodInstantiation), "MakeGenericType"); + return list; + } + } + } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs index 87764b54a3d7..76da7a29ab8c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs @@ -1156,11 +1156,8 @@ private ValueNodeList PopCallArguments( Stack currentStack, MethodDesc methodCalled, MethodIL containingMethodBody, - bool isNewObj, int ilOffset, - out SingleValue? newObjValue) + bool isNewObj, int ilOffset) { - newObjValue = null; - int countToPop = 0; if (!isNewObj && !methodCalled.Signature.IsStatic) countToPop++; @@ -1175,8 +1172,7 @@ private ValueNodeList PopCallArguments( if (isNewObj) { - newObjValue = UnknownValue.Instance; - methodParams.Add(newObjValue); + methodParams.Add(UnknownValue.Instance); } methodParams.Reverse(); return methodParams; @@ -1275,9 +1271,7 @@ private void HandleCall( { bool isNewObj = opcode == ILOpcode.newobj; - SingleValue? newObjValue; - ValueNodeList methodArguments = PopCallArguments(currentStack, calledMethod, callingMethodBody, isNewObj, - offset, out newObjValue); + ValueNodeList methodArguments = PopCallArguments(currentStack, calledMethod, callingMethodBody, isNewObj, offset); // Multi-dimensional array access is represented as a call to a special Get method on the array (runtime provided method) // We don't track multi-dimensional arrays in any way, so return unknown value. @@ -1290,33 +1284,12 @@ private void HandleCall( var dereferencedMethodParams = new List(); foreach (var argument in methodArguments) dereferencedMethodParams.Add(DereferenceValue(callingMethodBody, offset, argument, locals, ref interproceduralState)); - MultiValue methodReturnValue; - bool handledFunction = HandleCall( + MultiValue methodReturnValue = HandleCall( callingMethodBody, calledMethod, opcode, offset, - new ValueNodeList(dereferencedMethodParams), - out methodReturnValue); - - // Handle the return value or newobj result - if (!handledFunction) - { - if (isNewObj) - { - if (newObjValue == null) - methodReturnValue = UnknownValue.Instance; - else - methodReturnValue = newObjValue; - } - else - { - if (!calledMethod.Signature.ReturnType.IsVoid) - { - methodReturnValue = UnknownValue.Instance; - } - } - } + new ValueNodeList(dereferencedMethodParams)); if (isNewObj || !calledMethod.Signature.ReturnType.IsVoid) currentStack.Push(new StackSlot(methodReturnValue)); @@ -1335,13 +1308,12 @@ private void HandleCall( } } - public abstract bool HandleCall( + public abstract MultiValue HandleCall( MethodIL callingMethodBody, MethodDesc calledMethod, ILOpcode operation, int offset, - ValueNodeList methodParams, - out MultiValue methodReturnValue); + ValueNodeList methodParams); // Limit tracking array values to 32 values for performance reasons. There are many arrays much longer than 32 elements in .NET, but the interesting ones for trimming are nearly always less than 32 elements. private const int MaxTrackedArrayValues = 32; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodReturnValue.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodReturnValue.cs index 7bb244d8d2bf..7b90ffe64045 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodReturnValue.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodReturnValue.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using ILCompiler.Dataflow; using ILLink.Shared.DataFlow; @@ -16,9 +17,10 @@ namespace ILLink.Shared.TrimAnalysis /// internal partial record MethodReturnValue { - public MethodReturnValue(MethodDesc method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + public MethodReturnValue(MethodDesc method, bool isNewObj, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) { - StaticType = method.Signature.ReturnType; + Debug.Assert(!isNewObj || method.IsConstructor, "isNewObj can only be true for constructors"); + StaticType = isNewObj ? method.OwningType : method.Signature.ReturnType; Method = method; DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs index 279418b2fac3..f297a7cb7392 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs @@ -88,7 +88,7 @@ internal bool TryResolveTypeNameAndMark(string typeName, in DiagnosticContext di ModuleDesc? callingModule = (diagnosticContext.Origin.MemberDefinition.GetOwningType() as MetadataType)?.Module; List referencedModules = new(); - TypeDesc foundType = System.Reflection.TypeNameParser.ResolveType(typeName, callingModule, diagnosticContext.Origin.MemberDefinition!.Context, + TypeDesc foundType = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeNameForDataFlow(typeName, callingModule, diagnosticContext.Origin.MemberDefinition!.Context, referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary); if (foundType == null) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs index 1340d8669ca0..6a00b2df9657 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs @@ -118,7 +118,7 @@ protected override void Scan(MethodIL methodBody, ref InterproceduralState inter if (!methodBody.OwningMethod.Signature.ReturnType.IsVoid) { var method = methodBody.OwningMethod; - var methodReturnValue = _annotations.GetMethodReturnValue(method); + var methodReturnValue = _annotations.GetMethodReturnValue(method, isNewObj: false); if (methodReturnValue.DynamicallyAccessedMemberTypes != 0) HandleAssignmentPattern(_origin, ReturnValue, methodReturnValue, method.GetDisplayName()); } @@ -261,7 +261,7 @@ protected override void HandleFieldTokenAccess(MethodIL methodBody, int offset, ProcessGenericArgumentDataFlow(accessedField); } - public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMethod, ILOpcode operation, int offset, ValueNodeList methodParams, out MultiValue methodReturnValue) + public override MultiValue HandleCall(MethodIL callingMethodBody, MethodDesc calledMethod, ILOpcode operation, int offset, ValueNodeList methodParams) { Debug.Assert(callingMethodBody.OwningMethod == _origin.MemberDefinition); @@ -300,610 +300,32 @@ public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMet instanceValue, arguments, diagnosticContext, - _reflectionMarker, - out methodReturnValue); + _reflectionMarker); } - public static bool HandleCall( + public static MultiValue HandleCall( MethodIL callingMethodBody, MethodDesc calledMethod, ILOpcode operation, MultiValue instanceValue, ImmutableArray argumentValues, DiagnosticContext diagnosticContext, - ReflectionMarker reflectionMarker, - out MultiValue methodReturnValue) + ReflectionMarker reflectionMarker) { var callingMethodDefinition = callingMethodBody.OwningMethod; Debug.Assert(callingMethodDefinition == diagnosticContext.Origin.MemberDefinition); - var annotatedMethodReturnValue = reflectionMarker.Annotations.GetMethodReturnValue(calledMethod); + bool isNewObj = operation == ILOpcode.newobj; + var annotatedMethodReturnValue = reflectionMarker.Annotations.GetMethodReturnValue(calledMethod, isNewObj); Debug.Assert( RequiresReflectionMethodBodyScannerForCallSite(reflectionMarker.Annotations, calledMethod) || annotatedMethodReturnValue.DynamicallyAccessedMemberTypes == DynamicallyAccessedMemberTypes.None); - MultiValue? maybeMethodReturnValue = null; - - var handleCallAction = new HandleCallAction(reflectionMarker.Annotations, reflectionMarker, diagnosticContext, callingMethodDefinition, calledMethod.GetDisplayName()); - + var handleCallAction = new HandleCallAction(reflectionMarker.Annotations, operation, reflectionMarker, diagnosticContext, callingMethodDefinition, calledMethod.GetDisplayName()); var intrinsicId = Intrinsics.GetIntrinsicIdForMethod(calledMethod); - switch (intrinsicId) - { - case IntrinsicId.IntrospectionExtensions_GetTypeInfo: - case IntrinsicId.TypeInfo_AsType: - case IntrinsicId.Type_get_UnderlyingSystemType: - case IntrinsicId.Type_GetTypeFromHandle: - case IntrinsicId.Type_get_TypeHandle: - case IntrinsicId.Type_GetInterface: - case IntrinsicId.Type_get_AssemblyQualifiedName: - case IntrinsicId.RuntimeHelpers_RunClassConstructor: - case IntrinsicId.Type_GetConstructors__BindingFlags: - case IntrinsicId.Type_GetMethods__BindingFlags: - case IntrinsicId.Type_GetFields__BindingFlags: - case IntrinsicId.Type_GetProperties__BindingFlags: - case IntrinsicId.Type_GetEvents__BindingFlags: - case IntrinsicId.Type_GetNestedTypes__BindingFlags: - case IntrinsicId.Type_GetMembers__BindingFlags: - case IntrinsicId.Type_GetField: - case IntrinsicId.Type_GetProperty: - case IntrinsicId.Type_GetEvent: - case IntrinsicId.RuntimeReflectionExtensions_GetRuntimeEvent: - case IntrinsicId.RuntimeReflectionExtensions_GetRuntimeField: - case IntrinsicId.RuntimeReflectionExtensions_GetRuntimeMethod: - case IntrinsicId.RuntimeReflectionExtensions_GetRuntimeProperty: - case IntrinsicId.Type_GetMember: - case IntrinsicId.Type_GetMethod: - case IntrinsicId.Type_GetNestedType: - case IntrinsicId.Nullable_GetUnderlyingType: - case IntrinsicId.Expression_Property: - case IntrinsicId.Expression_Field: - case IntrinsicId.Type_get_BaseType: - case IntrinsicId.Type_GetConstructor: - case IntrinsicId.MethodBase_GetMethodFromHandle: - case IntrinsicId.MethodBase_get_MethodHandle: - case IntrinsicId.Expression_Call: - case IntrinsicId.Expression_New: - case IntrinsicId.Type_GetType: - case IntrinsicId.Activator_CreateInstance__Type: - case IntrinsicId.Activator_CreateInstance__AssemblyName_TypeName: - case IntrinsicId.Activator_CreateInstanceFrom: - case IntrinsicId.AppDomain_CreateInstance: - case IntrinsicId.AppDomain_CreateInstanceAndUnwrap: - case IntrinsicId.AppDomain_CreateInstanceFrom: - case IntrinsicId.AppDomain_CreateInstanceFromAndUnwrap: - case IntrinsicId.Assembly_CreateInstance: - { - return handleCallAction.Invoke(calledMethod, instanceValue, argumentValues, intrinsicId, out methodReturnValue); - } - - case IntrinsicId.Type_MakeGenericType: - { - bool triggersWarning = false; - - if (!instanceValue.IsEmpty() && !argumentValues[0].IsEmpty()) - { - foreach (var value in instanceValue.AsEnumerable()) - { - if (value is SystemTypeValue typeValue) - { - TypeDesc typeInstantiated = typeValue.RepresentedType.Type; - if (!typeInstantiated.IsGenericDefinition) - { - // Nothing to do, will fail at runtime - } - else if (TryGetMakeGenericInstantiation(callingMethodDefinition, argumentValues[0], out Instantiation inst, out bool isExact)) - { - if (inst.Length == typeInstantiated.Instantiation.Length) - { - typeInstantiated = ((MetadataType)typeInstantiated).MakeInstantiatedType(inst); - - if (isExact) - { - reflectionMarker.MarkType(diagnosticContext.Origin, typeInstantiated, "MakeGenericType"); - } - else - { - reflectionMarker.RuntimeDeterminedDependencies.Add(new MakeGenericTypeSite(typeInstantiated)); - } - } - } - else - { - triggersWarning = true; - } - - } - else if (value == NullValue.Instance) - { - // Nothing to do - } - else - { - // We don't know what type the `MakeGenericType` was called on - triggersWarning = true; - } - } - } - - if (triggersWarning) - { - CheckAndReportRequires(diagnosticContext, calledMethod, DiagnosticUtilities.RequiresDynamicCodeAttribute); - } - - // This intrinsic is relevant to both trimming and AOT - call into trimming logic as well. - return handleCallAction.Invoke(calledMethod, instanceValue, argumentValues, intrinsicId, out methodReturnValue); - } - - case IntrinsicId.MethodInfo_MakeGenericMethod: - { - bool triggersWarning = false; - - if (!instanceValue.IsEmpty()) - { - foreach (var methodValue in instanceValue.AsEnumerable()) - { - if (methodValue is SystemReflectionMethodBaseValue methodBaseValue) - { - MethodDesc methodInstantiated = methodBaseValue.RepresentedMethod.Method; - if (!methodInstantiated.IsGenericMethodDefinition) - { - // Nothing to do, will fail at runtime - } - else if (!methodInstantiated.OwningType.IsGenericDefinition - && TryGetMakeGenericInstantiation(callingMethodDefinition, argumentValues[0], out Instantiation inst, out bool isExact)) - { - if (inst.Length == methodInstantiated.Instantiation.Length) - { - methodInstantiated = methodInstantiated.MakeInstantiatedMethod(inst); - - if (isExact) - { - reflectionMarker.MarkMethod(diagnosticContext.Origin, methodInstantiated, "MakeGenericMethod"); - } - else - { - reflectionMarker.RuntimeDeterminedDependencies.Add(new MakeGenericMethodSite(methodInstantiated)); - } - } - } - else - { - // If the owning type is a generic definition, we can't help much. - triggersWarning = true; - } - } - else if (methodValue == NullValue.Instance) - { - // Nothing to do - } - else - { - // We don't know what method the `MakeGenericMethod` was called on - triggersWarning = true; - } - } - } - - if (triggersWarning) - { - CheckAndReportRequires(diagnosticContext, calledMethod, DiagnosticUtilities.RequiresDynamicCodeAttribute); - } - - // This intrinsic is relevant to both trimming and AOT - call into trimming logic as well. - return handleCallAction.Invoke(calledMethod, instanceValue, argumentValues, intrinsicId, out methodReturnValue); - } - - case IntrinsicId.None: - { - if (IsPInvokeDangerous(calledMethod, out bool comDangerousMethod, out bool aotUnsafeDelegate)) - { - if (aotUnsafeDelegate) - { - diagnosticContext.AddDiagnostic(DiagnosticId.CorrectnessOfAbstractDelegatesCannotBeGuaranteed, calledMethod.GetDisplayName()); - } - - if (comDangerousMethod) - { - diagnosticContext.AddDiagnostic(DiagnosticId.CorrectnessOfCOMCannotBeGuaranteed, calledMethod.GetDisplayName()); - } - } - - CheckAndReportAllRequires(diagnosticContext, calledMethod); - - return handleCallAction.Invoke(calledMethod, instanceValue, argumentValues, intrinsicId, out methodReturnValue); - } - - case IntrinsicId.TypeDelegator_Ctor: - { - // This is an identity function for analysis purposes - if (operation == ILOpcode.newobj) - AddReturnValue(argumentValues[0]); - } - break; - - case IntrinsicId.Array_Empty: - { - AddReturnValue(ArrayValue.Create(0, calledMethod.Instantiation[0])); - } - break; - - // - // System.Array - // - // CreateInstance (Type, Int32) - // - case IntrinsicId.Array_CreateInstance: - { - // We could try to analyze if the type is known, but for now making sure this works for canonical arrays is enough. - TypeDesc canonArrayType = reflectionMarker.Factory.TypeSystemContext.CanonType.MakeArrayType(); - reflectionMarker.Dependencies.Add(reflectionMarker.Factory.NativeLayout.TemplateTypeLayout(canonArrayType), "Array.CreateInstance was called"); - goto case IntrinsicId.None; - } - - // - // System.Enum - // - // static GetValues (Type) - // - case IntrinsicId.Enum_GetValues: - { - // Enum.GetValues returns System.Array, but it's the array of the enum type under the hood - // and people depend on this undocumented detail (could have returned enum of the underlying - // type instead). - // - // At least until we have shared enum code, this needs extra handling to get it right. - foreach (var value in argumentValues[0].AsEnumerable ()) - { - if (value is SystemTypeValue systemTypeValue - && !systemTypeValue.RepresentedType.Type.IsGenericDefinition - && !systemTypeValue.RepresentedType.Type.ContainsSignatureVariables(treatGenericParameterLikeSignatureVariable: true)) - { - if (systemTypeValue.RepresentedType.Type.IsEnum) - { - reflectionMarker.Dependencies.Add(reflectionMarker.Factory.ReflectedType(systemTypeValue.RepresentedType.Type.MakeArrayType()), "Enum.GetValues"); - } - } - else - CheckAndReportRequires(diagnosticContext, calledMethod, DiagnosticUtilities.RequiresDynamicCodeAttribute); - } - } - break; - - // - // System.Runtime.InteropServices.Marshal - // - // static SizeOf (Type) - // static PtrToStructure (IntPtr, Type) - // static DestroyStructure (IntPtr, Type) - // static OffsetOf (Type, string) - // - case IntrinsicId.Marshal_SizeOf: - case IntrinsicId.Marshal_PtrToStructure: - case IntrinsicId.Marshal_DestroyStructure: - case IntrinsicId.Marshal_OffsetOf: - { - int paramIndex = intrinsicId == IntrinsicId.Marshal_SizeOf - || intrinsicId == IntrinsicId.Marshal_OffsetOf - ? 0 : 1; - - // We need the data to do struct marshalling. - foreach (var value in argumentValues[paramIndex].AsEnumerable ()) - { - if (value is SystemTypeValue systemTypeValue - && !systemTypeValue.RepresentedType.Type.IsGenericDefinition - && !systemTypeValue.RepresentedType.Type.ContainsSignatureVariables(treatGenericParameterLikeSignatureVariable: true)) - { - if (systemTypeValue.RepresentedType.Type.IsDefType) - { - reflectionMarker.Dependencies.Add(reflectionMarker.Factory.StructMarshallingData((DefType)systemTypeValue.RepresentedType.Type), "Marshal API"); - if (intrinsicId == IntrinsicId.Marshal_PtrToStructure - && systemTypeValue.RepresentedType.Type.GetParameterlessConstructor() is MethodDesc ctorMethod - && !reflectionMarker.Factory.MetadataManager.IsReflectionBlocked(ctorMethod)) - { - reflectionMarker.Dependencies.Add(reflectionMarker.Factory.ReflectedMethod(ctorMethod.GetCanonMethodTarget(CanonicalFormKind.Specific)), "Marshal API"); - } - } - } - else - CheckAndReportRequires(diagnosticContext, calledMethod, DiagnosticUtilities.RequiresDynamicCodeAttribute); - } - } - break; - - // - // System.Runtime.InteropServices.Marshal - // - // static GetDelegateForFunctionPointer (IntPtr, Type) - // - case IntrinsicId.Marshal_GetDelegateForFunctionPointer: - { - // We need the data to do delegate marshalling. - foreach (var value in argumentValues[1].AsEnumerable ()) - { - if (value is SystemTypeValue systemTypeValue - && !systemTypeValue.RepresentedType.Type.IsGenericDefinition - && !systemTypeValue.RepresentedType.Type.ContainsSignatureVariables(treatGenericParameterLikeSignatureVariable: true)) - { - if (systemTypeValue.RepresentedType.Type.IsDelegate) - { - reflectionMarker.Dependencies.Add(reflectionMarker.Factory.DelegateMarshallingData((DefType)systemTypeValue.RepresentedType.Type), "Marshal API"); - } - } - else - CheckAndReportRequires(diagnosticContext, calledMethod, DiagnosticUtilities.RequiresDynamicCodeAttribute); - } - } - break; - - // - // System.Delegate - // - // get_Method () - // - // System.Reflection.RuntimeReflectionExtensions - // - // GetMethodInfo (System.Delegate) - // - case IntrinsicId.RuntimeReflectionExtensions_GetMethodInfo: - case IntrinsicId.Delegate_get_Method: - { - // Find the parameter: first is an instance method, second is an extension method. - MultiValue param = intrinsicId == IntrinsicId.RuntimeReflectionExtensions_GetMethodInfo - ? argumentValues[0] : instanceValue; - - // If this is Delegate.Method accessed from RuntimeReflectionExtensions.GetMethodInfo, ignore - // because we handle the callsites to that one here as well. - if (Intrinsics.GetIntrinsicIdForMethod(callingMethodDefinition) == IntrinsicId.RuntimeReflectionExtensions_GetMethodInfo) - break; - - foreach (var valueNode in param.AsEnumerable()) - { - TypeDesc? staticType = (valueNode as IValueWithStaticType)?.StaticType?.Type; - if (staticType is null || !staticType.IsDelegate) - { - // The static type is unknown or something useless like Delegate or MulticastDelegate. - reflectionMarker.Dependencies.Add(reflectionMarker.Factory.ReflectedDelegate(null), "Delegate.Method access on unknown delegate type"); - } - else - { - if (staticType.ContainsSignatureVariables(treatGenericParameterLikeSignatureVariable: true)) - reflectionMarker.Dependencies.Add(reflectionMarker.Factory.ReflectedDelegate(staticType.GetTypeDefinition()), "Delegate.Method access (on inexact type)"); - else - reflectionMarker.Dependencies.Add(reflectionMarker.Factory.ReflectedDelegate(staticType.ConvertToCanonForm(CanonicalFormKind.Specific)), "Delegate.Method access"); - } - } - } - break; - - // - // System.Object - // - // GetType() - // - case IntrinsicId.Object_GetType: - { - foreach (var valueNode in instanceValue.AsEnumerable ()) - { - // Note that valueNode can be statically typed in IL as some generic argument type. - // For example: - // void Method(T instance) { instance.GetType().... } - // Currently this case will end up with null StaticType - since there's no typedef for the generic argument type. - // But it could be that T is annotated with for example PublicMethods: - // void Method<[DAM(PublicMethods)] T>(T instance) { instance.GetType().GetMethod("Test"); } - // In this case it's in theory possible to handle it, by treating the T basically as a base class - // for the actual type of "instance". But the analysis for this would be pretty complicated (as the marking - // has to happen on the callsite, which doesn't know that GetType() will be used...). - // For now we're intentionally ignoring this case - it will produce a warning. - // The counter example is: - // Method(new Derived); - // In this case to get correct results, trimmer would have to mark all public methods on Derived. Which - // currently it won't do. - - TypeDesc? staticType = (valueNode as IValueWithStaticType)?.StaticType?.Type; - if (staticType is null || (!staticType.IsDefType && !staticType.IsArray)) - { - // We don't know anything about the type GetType was called on. Track this as a usual "result of a method call without any annotations" - AddReturnValue(reflectionMarker.Annotations.GetMethodReturnValue(calledMethod)); - } - else if (staticType.IsSealed() || staticType.IsTypeOf("System", "Delegate")) - { - // We can treat this one the same as if it was a typeof() expression - - // We can allow Object.GetType to be modeled as System.Delegate because we keep all methods - // on delegates anyway so reflection on something this approximation would miss is actually safe. - - // We ignore the fact that the type can be annotated (see below for handling of annotated types) - // This means the annotations (if any) won't be applied - instead we rely on the exact knowledge - // of the type. So for example even if the type is annotated with PublicMethods - // but the code calls GetProperties on it - it will work - mark properties, don't mark methods - // since we ignored the fact that it's annotated. - // This can be seen a little bit as a violation of the annotation, but we already have similar cases - // where a parameter is annotated and if something in the method sets a specific known type to it - // we will also make it just work, even if the annotation doesn't match the usage. - AddReturnValue(new SystemTypeValue(staticType)); - } - else - { - Debug.Assert(staticType is MetadataType || staticType.IsArray); - MetadataType closestMetadataType = staticType is MetadataType mdType ? - mdType : (MetadataType)reflectionMarker.Factory.TypeSystemContext.GetWellKnownType(Internal.TypeSystem.WellKnownType.Array); - - var annotation = reflectionMarker.Annotations.GetTypeAnnotation(staticType); - - if (annotation != default) - { - reflectionMarker.Dependencies.Add(reflectionMarker.Factory.ObjectGetTypeFlowDependencies(closestMetadataType), "GetType called on this type"); - } - - // Return a value which is "unknown type" with annotation. For now we'll use the return value node - // for the method, which means we're loosing the information about which staticType this - // started with. For now we don't need it, but we can add it later on. - AddReturnValue(reflectionMarker.Annotations.GetMethodReturnValue(calledMethod, annotation)); - } - } - } - break; - - // - // string System.Reflection.Assembly.Location getter - // string System.Reflection.AssemblyName.CodeBase getter - // string System.Reflection.AssemblyName.EscapedCodeBase getter - // - case IntrinsicId.Assembly_get_Location: - case IntrinsicId.AssemblyName_get_CodeBase: - case IntrinsicId.AssemblyName_get_EscapedCodeBase: - diagnosticContext.AddDiagnostic(DiagnosticId.AvoidAssemblyLocationInSingleFile, calledMethod.GetDisplayName()); - break; - - // - // string System.Reflection.Assembly.GetFile(string) - // string System.Reflection.Assembly.GetFiles() - // string System.Reflection.Assembly.GetFiles(bool) - // - case IntrinsicId.Assembly_GetFile: - case IntrinsicId.Assembly_GetFiles: - diagnosticContext.AddDiagnostic(DiagnosticId.AvoidAssemblyGetFilesInSingleFile, calledMethod.GetDisplayName()); - break; - - default: - throw new NotImplementedException("Unhandled intrinsic"); - } - - // If we get here, we handled this as an intrinsic. As a convenience, if the code above - // didn't set the return value (and the method has a return value), we will set it to be an - // unknown value with the return type of the method. - bool returnsVoid = calledMethod.Signature.ReturnType.IsVoid; - methodReturnValue = maybeMethodReturnValue ?? (returnsVoid ? - MultiValueLattice.Top : - annotatedMethodReturnValue); - - // Validate that the return value has the correct annotations as per the method return value annotations - if (annotatedMethodReturnValue.DynamicallyAccessedMemberTypes != 0) - { - foreach (var uniqueValue in methodReturnValue.AsEnumerable ()) - { - if (uniqueValue is ValueWithDynamicallyAccessedMembers methodReturnValueWithMemberTypes) - { - if (!methodReturnValueWithMemberTypes.DynamicallyAccessedMemberTypes.HasFlag(annotatedMethodReturnValue.DynamicallyAccessedMemberTypes)) - throw new InvalidOperationException($"Internal trimming error: processing of call from {callingMethodDefinition.GetDisplayName()} to {calledMethod.GetDisplayName()} returned value which is not correctly annotated with the expected dynamic member access kinds."); - } - else if (uniqueValue is SystemTypeValue) - { - // SystemTypeValue can fulfill any requirement, so it's always valid - // The requirements will be applied at the point where it's consumed (passed as a method parameter, set as field value, returned from the method) - } - else - { - throw new InvalidOperationException($"Internal trimming error: processing of call from {callingMethodDefinition.GetDisplayName()} to {calledMethod.GetDisplayName()} returned value which is not correctly annotated with the expected dynamic member access kinds."); - } - } - } - - return true; - - void AddReturnValue(MultiValue value) - { - maybeMethodReturnValue = (maybeMethodReturnValue is null) ? value : MultiValueLattice.Meet((MultiValue)maybeMethodReturnValue, value); - } - } - - private static bool TryGetMakeGenericInstantiation( - MethodDesc contextMethod, - in MultiValue genericParametersArray, - out Instantiation inst, - out bool isExact) - { - // We support calling MakeGeneric APIs with a very concrete instantiation array. - // Only the form of `new Type[] { typeof(Foo), typeof(T), typeof(Foo) }` is supported. - - inst = default; - isExact = true; - Debug.Assert(contextMethod.GetTypicalMethodDefinition() == contextMethod); - - var typesValue = genericParametersArray.AsSingleValue(); - if (typesValue is NullValue) - { - // This will fail at runtime but no warning needed - inst = Instantiation.Empty; - return true; - } - - // Is this an array we model? - if (typesValue is not ArrayValue array) - { - return false; - } - - int? size = array.Size.AsConstInt(); - if (size == null) - { - return false; - } - - TypeDesc[]? sigInst = null; - TypeDesc[]? defInst = null; - - ArrayBuilder result = default; - for (int i = 0; i < size.Value; i++) - { - // Go over each element of the array. If the value is unknown, bail. - if (!array.TryGetValueByIndex(i, out MultiValue value)) - { - return false; - } - - var singleValue = value.AsSingleValue(); - - TypeDesc? type = singleValue switch - { - SystemTypeValue systemType => systemType.RepresentedType.Type, - GenericParameterValue genericParamType => genericParamType.GenericParameter.GenericParameter, - NullableSystemTypeValue nullableSystemType => nullableSystemType.NullableType.Type, - _ => null - }; - - if (type is null) - { - return false; - } - - // type is now some type. - // Because dataflow analysis oddly operates on method bodies instantiated over - // generic parameters (as opposed to instantiated over signature variables) - // We need to swap generic parameters (T, U,...) for signature variables (!0, !!1,...). - // We need to do this for both generic parameters of the owning type, and generic - // parameters of the owning method. - if (type.ContainsSignatureVariables(treatGenericParameterLikeSignatureVariable: true)) - { - if (sigInst == null) - { - TypeDesc contextType = contextMethod.OwningType; - sigInst = new TypeDesc[contextType.Instantiation.Length + contextMethod.Instantiation.Length]; - defInst = new TypeDesc[contextType.Instantiation.Length + contextMethod.Instantiation.Length]; - TypeSystemContext context = type.Context; - for (int j = 0; j < contextType.Instantiation.Length; j++) - { - sigInst[j] = context.GetSignatureVariable(j, method: false); - defInst[j] = contextType.Instantiation[j]; - } - for (int j = 0; j < contextMethod.Instantiation.Length; j++) - { - sigInst[j + contextType.Instantiation.Length] = context.GetSignatureVariable(j, method: true); - defInst[j + contextType.Instantiation.Length] = contextMethod.Instantiation[j]; - } - } - - isExact = false; - - // defInst is [T, U, V], sigInst is `[!0, !!0, !!1]`. - type = type.ReplaceTypesInConstructionOfType(defInst, sigInst); - } - - result.Add(type); - } - - inst = new Instantiation(result.ToArray()); - return true; + if (!handleCallAction.Invoke(calledMethod, instanceValue, argumentValues, intrinsicId, out MultiValue methodReturnValue)) + throw new NotImplementedException($"Unhandled intrinsic {intrinsicId}"); + return methodReturnValue; } private static bool IsAotUnsafeDelegate(TypeDesc parameterType) @@ -1036,7 +458,7 @@ private void ProcessGenericArgumentDataFlow(TypeDesc type) } } - private static bool IsPInvokeDangerous(MethodDesc calledMethod, out bool comDangerousMethod, out bool aotUnsafeDelegate) + internal static bool IsPInvokeDangerous(MethodDesc calledMethod, out bool comDangerousMethod, out bool aotUnsafeDelegate) { if (!calledMethod.IsPInvoke) { @@ -1066,33 +488,5 @@ private static bool IsPInvokeDangerous(MethodDesc calledMethod, out bool comDang return aotUnsafeDelegate || comDangerousMethod; } - - private sealed class MakeGenericMethodSite : INodeWithRuntimeDeterminedDependencies - { - private readonly MethodDesc _method; - - public MakeGenericMethodSite(MethodDesc method) => _method = method; - - public IEnumerable.DependencyListEntry> InstantiateDependencies(NodeFactory factory, Instantiation typeInstantiation, Instantiation methodInstantiation) - { - var list = new DependencyList(); - RootingHelpers.TryGetDependenciesForReflectedMethod(ref list, factory, _method.InstantiateSignature(typeInstantiation, methodInstantiation), "MakeGenericMethod"); - return list; - } - } - - private sealed class MakeGenericTypeSite : INodeWithRuntimeDeterminedDependencies - { - private readonly TypeDesc _type; - - public MakeGenericTypeSite(TypeDesc type) => _type = type; - - public IEnumerable.DependencyListEntry> InstantiateDependencies(NodeFactory factory, Instantiation typeInstantiation, Instantiation methodInstantiation) - { - var list = new DependencyList(); - RootingHelpers.TryGetDependenciesForReflectedType(ref list, factory, _type.InstantiateSignature(typeInstantiation, methodInstantiation), "MakeGenericType"); - return list; - } - } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/RequireDynamicallyAccessedMembersAction.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/RequireDynamicallyAccessedMembersAction.cs index 43e01852b31a..a1ae67004fc2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/RequireDynamicallyAccessedMembersAction.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/RequireDynamicallyAccessedMembersAction.cs @@ -29,6 +29,11 @@ public partial bool TryResolveTypeNameAndMark(string typeName, bool needsAssembl { if (_reflectionMarker.TryResolveTypeNameAndMark(typeName, _diagnosticContext, needsAssemblyName, _reason, out TypeDesc? foundType)) { + if (foundType.HasInstantiation && _reflectionMarker.Annotations.HasGenericParameterAnnotation(foundType)) + { + GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(_diagnosticContext, _reflectionMarker, foundType); + } + type = new(foundType); return true; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisMethodCallPattern.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisMethodCallPattern.cs index 9f2caf292999..48b0bbf5aff6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisMethodCallPattern.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TrimAnalysisMethodCallPattern.cs @@ -86,8 +86,7 @@ public void MarkAndProduceDiagnostics(ReflectionMarker reflectionMarker, Logger logger); ReflectionMethodBodyScanner.HandleCall(MethodBody, CalledMethod, Operation, Instance, Arguments, diagnosticContext, - reflectionMarker, - out MultiValue _); + reflectionMarker); } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeNameParser.Dataflow.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeNameParser.Dataflow.cs deleted file mode 100644 index 90b63f39c9f0..000000000000 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeNameParser.Dataflow.cs +++ /dev/null @@ -1,135 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Reflection; - -using Internal.TypeSystem; - -namespace System.Reflection -{ - internal partial struct TypeNameParser - { - private TypeSystemContext _context; - private ModuleDesc _callingModule; - private List _referencedModules; - private bool _typeWasNotFoundInAssemblyNorBaseLibrary; - - public static TypeDesc ResolveType(string name, ModuleDesc callingModule, - TypeSystemContext context, List referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary) - { - var parser = new TypeNameParser(name) - { - _context = context, - _callingModule = callingModule, - _referencedModules = referencedModules - }; - - TypeDesc result = parser.Parse()?.Value; - - typeWasNotFoundInAssemblyNorBaseLibrary = parser._typeWasNotFoundInAssemblyNorBaseLibrary; - return result; - } - - private sealed class Type - { - public Type(TypeDesc type) => Value = type; - public TypeDesc Value { get; } - - public Type MakeArrayType() => new Type(Value.MakeArrayType()); - public Type MakeArrayType(int rank) => new Type(Value.MakeArrayType(rank)); - public Type MakePointerType() => new Type(Value.MakePointerType()); - public Type MakeByRefType() => new Type(Value.MakeByRefType()); - - public Type MakeGenericType(Type[] typeArguments) - { - TypeDesc[] instantiation = new TypeDesc[typeArguments.Length]; - for (int i = 0; i < typeArguments.Length; i++) - instantiation[i] = typeArguments[i].Value; - return new Type(((MetadataType)Value).MakeInstantiatedType(instantiation)); - } - } - - private static bool CheckTopLevelAssemblyQualifiedName() => true; - - private Type GetType(string typeName, ReadOnlySpan nestedTypeNames, string assemblyNameIfAny) - { - ModuleDesc module; - - if (assemblyNameIfAny != null) - { - module = (TryParseAssemblyName(assemblyNameIfAny) is AssemblyName an) ? - _context.ResolveAssembly(an, throwIfNotFound: false) : null; - } - else - { - module = _callingModule; - } - - if (module != null) - { - Type type = GetTypeCore(module, typeName, nestedTypeNames); - if (type != null) - { - _referencedModules?.Add(module); - return type; - } - } - - // If it didn't resolve and wasn't assembly-qualified, we also try core library - if (assemblyNameIfAny == null) - { - Type type = GetTypeCore(_context.SystemModule, typeName, nestedTypeNames); - if (type != null) - { - _referencedModules?.Add(_context.SystemModule); - return type; - } - - _typeWasNotFoundInAssemblyNorBaseLibrary = true; - } - - return null; - } - - private static AssemblyName TryParseAssemblyName(string assemblyName) - { - try - { - return new AssemblyName(assemblyName); - } - catch (FileLoadException) - { - return null; - } - catch (ArgumentException) - { - return null; - } - } - - private static Type GetTypeCore(ModuleDesc module, string typeName, ReadOnlySpan nestedTypeNames) - { - (string typeNamespace, string name) = SplitFullTypeName(typeName); - - MetadataType type = module.GetType(typeNamespace, name, throwIfNotFound: false); - if (type == null) - return null; - - for (int i = 0; i < nestedTypeNames.Length; i++) - { - type = type.GetNestedType(nestedTypeNames[i]); - if (type == null) - return null; - } - - return new Type(type); - } - - private static void ParseError() - { - } - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DelegateCreationInfo.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DelegateCreationInfo.cs index 981d7a183b14..9a40ecdb31f0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DelegateCreationInfo.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DelegateCreationInfo.cs @@ -306,20 +306,20 @@ public static DelegateCreationInfo Create(TypeDesc delegateType, MethodDesc targ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("__DelegateCtor_"); + sb.Append("__DelegateCtor_"u8); if (TargetNeedsVTableLookup) - sb.Append("FromVtbl_"); + sb.Append("FromVtbl_"u8); Constructor.AppendMangledName(nameMangler, sb); - sb.Append("__"); + sb.Append("__"u8); sb.Append(nameMangler.GetMangledMethodName(_targetMethod)); if (_constrainedType != null) { - sb.Append("__"); + sb.Append("__"u8); nameMangler.GetMangledTypeName(_constrainedType); } if (Thunk != null) { - sb.Append("__"); + sb.Append("__"u8); Thunk.AppendMangledName(nameMangler, sb); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayMapNode.cs index f8207e8454f9..19e7b8866f5b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayMapNode.cs @@ -26,7 +26,7 @@ public ArrayMapNode(ExternalReferencesTableNode externalReferences) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__array_type_map"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__array_type_map"u8); } public int Offset => 0; public override bool IsShareable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs index a2bc613dcbd4..e8f08aa357f2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs @@ -114,7 +114,7 @@ public EmbeddedPointerIndirectionWithSymbolNode(ArrayOfEmbeddedPointersNode _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) - => sb.Append(nameMangler.CompilationUnitPrefix).Append("__FrozenSegmentStart"); + => sb.Append(nameMangler.CompilationUnitPrefix).Append("__FrozenSegmentStart"u8); public int Offset => 0; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ByRefTypeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ByRefTypeMapNode.cs index b1a97f9d5bf7..9f23b8a85cc3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ByRefTypeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ByRefTypeMapNode.cs @@ -25,7 +25,7 @@ public ByRefTypeMapNode(ExternalReferencesTableNode externalReferences) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__byref_type_map"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__byref_type_map"u8); } public int Offset => 0; public override bool IsShareable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs index ec0e16236769..a12e604b44cd 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs @@ -25,7 +25,7 @@ public ClassConstructorContextMap(ExternalReferencesTableNode externalReferences public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__type_to_cctorContext_map"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__type_to_cctorContext_map"u8); } public int Offset => 0; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs index 68e8b5f6f0c3..a18251e401fc 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Collections.Immutable; using System.Diagnostics; using System.Reflection.Metadata; @@ -151,6 +152,12 @@ private static void AddDependenciesDueToCustomAttributes(ref DependencyList depe // worth the hassle: the input was invalid. The most important thing is that we // don't crash the compilation. } + catch (BadImageFormatException) + { + // System.Reflection.Metadata will throw BadImageFormatException if the blob is malformed. + // This can happen if e.g. underlying type of an enum changes between versions and + // we can no longer decode the custom attribute blob. + } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DehydratedDataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DehydratedDataNode.cs index d2490fea2fc5..1b762d533c68 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DehydratedDataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DehydratedDataNode.cs @@ -46,7 +46,7 @@ internal sealed class DehydratedDataNode : ObjectNode, ISymbolDefinitionNode, IN public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__dehydrated_data"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__dehydrated_data"u8); } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs index 2111f081a697..7ea248989915 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs @@ -28,7 +28,7 @@ public DelegateMarshallingStubMapNode(ExternalReferencesTableNode externalRefere public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__delegate_marshalling_stub_map"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__delegate_marshalling_stub_map"u8); } public int Offset => 0; public override bool IsShareable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DynamicDependencyAttributesOnEntityNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DynamicDependencyAttributesOnEntityNode.cs index 7c07dfd53eb6..31b54535294a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DynamicDependencyAttributesOnEntityNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DynamicDependencyAttributesOnEntityNode.cs @@ -122,7 +122,7 @@ static MetadataType Linkerify(TypeDesc type) // DynamicDependencyAttribute(String, String, String) case 3 when fixedArgs[1].Value is string typeStringFromAttribute && fixedArgs[2].Value is string assemblyStringFromAttribute: - ModuleDesc asm = factory.TypeSystemContext.ResolveAssembly(new System.Reflection.AssemblyName(assemblyStringFromAttribute), throwIfNotFound: false); + ModuleDesc asm = factory.TypeSystemContext.ResolveAssembly(AssemblyNameInfo.Parse(assemblyStringFromAttribute), throwIfNotFound: false); if (asm == null) { metadataManager.Logger.LogWarning( @@ -171,7 +171,7 @@ static MetadataType Linkerify(TypeDesc type) && fixedArgs[2].Value is string assemblyStringFromAttribute) { // DynamicDependencyAttribute(DynamicallyAccessedMemberTypes, String, String) - ModuleDesc asm = factory.TypeSystemContext.ResolveAssembly(new System.Reflection.AssemblyName(assemblyStringFromAttribute), throwIfNotFound: false); + ModuleDesc asm = factory.TypeSystemContext.ResolveAssembly(AssemblyNameInfo.Parse(assemblyStringFromAttribute), throwIfNotFound: false); if (asm == null) { metadataManager.Logger.LogWarning( diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs index f0a837fdfc21..e94790552aa7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs @@ -1469,7 +1469,7 @@ public override ObjectNodeSection GetSection(NodeFactory factory) public override bool StaticDependenciesAreComputed => true; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) - => sb.Append("__writableData").Append(nameMangler.GetMangledTypeName(_type.Type)); + => sb.Append("__writableData"u8).Append(nameMangler.GetMangledTypeName(_type.Type)); public int Offset => 0; public override bool IsShareable => true; public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => _type.ShouldSkipEmittingObjectNode(factory); @@ -1484,7 +1484,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) // If the whole program view contains a reference to a preallocated RuntimeType // instance for this type, generate a reference to it. // Otherwise, generate as zero to save size. - if (_type.GetFrozenRuntimeTypeNode(factory) is { Marked: true } runtimeTypeObject) + if (!_type.Type.IsCanonicalSubtype(CanonicalFormKind.Any) + && _type.GetFrozenRuntimeTypeNode(factory) is { Marked: true } runtimeTypeObject) { builder.EmitPointerReloc(runtimeTypeObject); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs index cb10e790d417..592e674e5f5b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs @@ -26,7 +26,7 @@ public override ObjectNodeSection GetSection(NodeFactory factory) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("__optionalfields_"); + sb.Append("__optionalfields_"u8); _owner.AppendMangledName(nameMangler, sb); } public int Offset => 0; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs index 20be29d3e01f..e707e28af611 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs @@ -49,7 +49,7 @@ public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory f public virtual void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("_embedded_ptr_"); + sb.Append("_embedded_ptr_"u8); Target.AppendMangledName(nameMangler, sb); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs index 46d38a7b9857..3e6e12b9b0e6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs @@ -25,7 +25,7 @@ public ExactMethodInstantiationsNode(ExternalReferencesTableNode externalReferen public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__exact_method_instantiations"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__exact_method_instantiations"u8); } int INodeWithSize.Size => _size.Value; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenRuntimeTypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenRuntimeTypeNode.cs index 907b602e4279..df38758e7dee 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenRuntimeTypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenRuntimeTypeNode.cs @@ -16,13 +16,14 @@ public sealed class FrozenRuntimeTypeNode : FrozenObjectNode public FrozenRuntimeTypeNode(TypeDesc type, bool constructed) { + Debug.Assert(!type.IsCanonicalSubtype(CanonicalFormKind.Any)); _type = type; _constructed = constructed; } public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__RuntimeType_").Append(nameMangler.GetMangledTypeName(_type)); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__RuntimeType_"u8).Append(nameMangler.GetMangledTypeName(_type)); } protected override int ContentSize => ObjectType.InstanceByteCount.AsInt; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs index f00c508f2652..a115db34764b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs @@ -19,7 +19,7 @@ public FrozenStringNode(string data, CompilerTypeSystemContext context) public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__Str_").Append(nameMangler.GetMangledStringName(_data)); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__Str_"u8).Append(nameMangler.GetMangledStringName(_data)); } protected override int ContentSize => _stringType.Context.Target.PointerSize + sizeof(int) + (_data.Length + 1) * sizeof(char); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FunctionPointerMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FunctionPointerMapNode.cs index 979b8d4ef618..5273c447780a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FunctionPointerMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FunctionPointerMapNode.cs @@ -26,7 +26,7 @@ public FunctionPointerMapNode(ExternalReferencesTableNode externalReferences) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__fnptr_type_map"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__fnptr_type_map"u8); } public int Offset => 0; public override bool IsShareable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GCStaticEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GCStaticEETypeNode.cs index f8217164be84..62df97532764 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GCStaticEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GCStaticEETypeNode.cs @@ -41,7 +41,7 @@ protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("__GCStaticEEType_").Append(_gcMap.ToString()); + sb.Append("__GCStaticEEType_"u8).Append(_gcMap.ToString()); } int ISymbolDefinitionNode.Offset diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericCompositionNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericCompositionNode.cs index 447bbfa7b392..7432bc7ad1f6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericCompositionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericCompositionNode.cs @@ -20,7 +20,7 @@ internal GenericCompositionNode(Instantiation details) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("__GenericInstance"); + sb.Append("__GenericInstance"u8); foreach (TypeDesc instArg in _details) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs index 17f717d49bb5..237f33495c03 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs @@ -187,7 +187,7 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("TypeHandle_"); + sb.Append("TypeHandle_"u8); sb.Append(nameMangler.GetMangledTypeName(_type)); } @@ -245,7 +245,7 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("UnwrapNullable_"); + sb.Append("UnwrapNullable_"u8); sb.Append(nameMangler.GetMangledTypeName(_type)); } @@ -296,7 +296,7 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("MethodHandle_"); + sb.Append("MethodHandle_"u8); sb.Append(nameMangler.GetMangledMethodName(_method)); } @@ -346,7 +346,7 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("FieldHandle_"); + sb.Append("FieldHandle_"u8); sb.Append(nameMangler.GetMangledFieldName(_field)); } @@ -399,7 +399,7 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("MethodDictionary_"); + sb.Append("MethodDictionary_"u8); sb.Append(nameMangler.GetMangledMethodName(_method)); } @@ -453,9 +453,9 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { if (!_isUnboxingThunk) - sb.Append("MethodEntry_"); + sb.Append("MethodEntry_"u8); else - sb.Append("UnboxMethodEntry_"); + sb.Append("UnboxMethodEntry_"u8); sb.Append(nameMangler.GetMangledMethodName(_method)); } @@ -534,7 +534,7 @@ contextOwner is TypeDesc ? public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("DispatchCell_"); + sb.Append("DispatchCell_"u8); sb.Append(nameMangler.GetMangledMethodName(_method)); } @@ -585,7 +585,7 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("NonGCStaticBase_"); + sb.Append("NonGCStaticBase_"u8); sb.Append(nameMangler.GetMangledTypeName(_type)); } @@ -636,7 +636,7 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("ThreadStaticBase_"); + sb.Append("ThreadStaticBase_"u8); sb.Append(nameMangler.GetMangledTypeName(_type)); } @@ -687,7 +687,7 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("GCStaticBase_"); + sb.Append("GCStaticBase_"u8); sb.Append(nameMangler.GetMangledTypeName(_type)); } @@ -738,7 +738,7 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("AllocObject_"); + sb.Append("AllocObject_"u8); sb.Append(nameMangler.GetMangledTypeName(_type)); } @@ -781,12 +781,12 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo { TypeDesc instantiatedType = _type.GetNonRuntimeDeterminedTypeFromRuntimeDeterminedSubtypeViaSubstitution(dictionary.TypeInstantiation, dictionary.MethodInstantiation); MethodDesc defaultCtor = Compilation.GetConstructorForCreateInstanceIntrinsic(instantiatedType); - return factory.CanonicalEntrypoint(defaultCtor); + return instantiatedType.IsValueType ? factory.ExactCallableAddress(defaultCtor) : factory.CanonicalEntrypoint(defaultCtor); } public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("DefaultCtor_"); + sb.Append("DefaultCtor_"u8); sb.Append(nameMangler.GetMangledTypeName(_type)); } @@ -903,11 +903,11 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("ConstrainedMethodUseLookupResult_"); + sb.Append("ConstrainedMethodUseLookupResult_"u8); sb.Append(nameMangler.GetMangledTypeName(_constraintType)); sb.Append(nameMangler.GetMangledMethodName(_constrainedMethod)); if (_directCall) - sb.Append("Direct"); + sb.Append("Direct"u8); } public override string ToString() => $"ConstrainedMethodUseLookupResult: {_constraintType} {_constrainedMethod} {_directCall}"; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs index 5a3ee2304e26..04d62dbad554 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs @@ -25,7 +25,7 @@ public GenericMethodsHashtableNode(ExternalReferencesTableNode externalReference public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__generic_methods_hashtable"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__generic_methods_hashtable"u8); } int INodeWithSize.Size => _size.Value; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs index 6230518cf2b2..d0e038240975 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs @@ -25,7 +25,7 @@ public GenericMethodsTemplateMap(ExternalReferencesTableNode externalReferences) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__GenericMethodsTemplateMap"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__GenericMethodsTemplateMap"u8); } int INodeWithSize.Size => _size.Value; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs index fa1a70b3544a..3c2835ed9210 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs @@ -24,7 +24,7 @@ public GenericTypesHashtableNode(ExternalReferencesTableNode externalReferences) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__generic_types_hashtable"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__generic_types_hashtable"u8); } int INodeWithSize.Size => _size.Value; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs index 80f44e60948d..1e2495ccacb9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs @@ -25,7 +25,7 @@ public GenericTypesTemplateMap(ExternalReferencesTableNode externalReferences) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__GenericTypesTemplateMap"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__GenericTypesTemplateMap"u8); } int INodeWithSize.Size => _size.Value; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVarianceNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVarianceNode.cs index 7fedd00acc87..3023b166ba91 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVarianceNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVarianceNode.cs @@ -25,7 +25,7 @@ internal GenericVarianceNode(GenericVarianceDetails details) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("__GenericVariance"); + sb.Append("__GenericVariance"u8); for (int i = 0; i < _details.Variance.Length; i++) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs index 7769b2b6a608..210293d94358 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs @@ -28,7 +28,7 @@ public GenericVirtualMethodTableNode(ExternalReferencesTableNode externalReferen public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__gvm_table"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__gvm_table"u8); } int INodeWithSize.Size => _size.Value; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs index 5d22535ce5e7..523386d13030 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs @@ -30,7 +30,7 @@ public InterfaceDispatchCellNode(MethodDesc targetMethod, ISortableSymbolNode ca public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(nameMangler.CompilationUnitPrefix) - .Append("__InterfaceDispatchCell_") + .Append("__InterfaceDispatchCell_"u8) .Append(nameMangler.GetMangledMethodName(_targetMethod)); if (_callSiteIdentifier != null) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellSectionNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellSectionNode.cs index 72391f7ddc74..8c611951e99d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellSectionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellSectionNode.cs @@ -86,7 +86,7 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo } public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) - => sb.Append(nameMangler.CompilationUnitPrefix).Append("__InterfaceDispatchCellSection_Start"); + => sb.Append(nameMangler.CompilationUnitPrefix).Append("__InterfaceDispatchCellSection_Start"u8); protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory) => ObjectNodeSection.DataSection; protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs index 45cc7ca69680..74aee3c3dd5d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs @@ -31,7 +31,7 @@ public InterfaceDispatchMapNode(NodeFactory factory, TypeDesc type) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__InterfaceDispatchMap_").Append(nameMangler.SanitizeName(nameMangler.GetMangledTypeName(_type))); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__InterfaceDispatchMap_"u8).Append(nameMangler.SanitizeName(nameMangler.GetMangledTypeName(_type))); } public int Offset => 0; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs index 74de063bbd70..a5df57f1f0d3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs @@ -31,7 +31,7 @@ public InterfaceGenericVirtualMethodTableNode(ExternalReferencesTableNode extern public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__interface_gvm_table"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__interface_gvm_table"u8); } int INodeWithSize.Size => _size.Value; public int Offset => 0; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MetadataNode.cs index ad84d1bd81ed..a6c7507fc3f5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MetadataNode.cs @@ -19,7 +19,7 @@ public sealed class MetadataNode : ObjectNode, ISymbolDefinitionNode, INodeWithS public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__embedded_metadata"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__embedded_metadata"u8); } public int Offset => 0; public override bool IsShareable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodAssociatedDataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodAssociatedDataNode.cs index df661ea1ad64..17e61805721e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodAssociatedDataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodAssociatedDataNode.cs @@ -48,7 +48,7 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer public virtual void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("_associatedData_").Append(nameMangler.GetMangledMethodName(_methodNode.Method)); + sb.Append("_associatedData_"u8).Append(nameMangler.GetMangledMethodName(_methodNode.Method)); } public static bool MethodHasAssociatedData(IMethodNode methodNode) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleInitializerListNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleInitializerListNode.cs index c85f1494437a..6ba102b11ee0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleInitializerListNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleInitializerListNode.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Reflection.Metadata; using Internal.Text; using Internal.TypeSystem; @@ -18,7 +19,7 @@ internal sealed class ModuleInitializerListNode : ObjectNode, ISymbolDefinitionN public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__module_initializers"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__module_initializers"u8); } public int Offset => 0; @@ -203,7 +204,7 @@ public ModuleGraphNode GetNode(ModuleDesc module) try { - var reference = module.Context.ResolveAssembly(new System.Reflection.AssemblyName(assemblyName)); + var reference = module.Context.ResolveAssembly(new AssemblyNameInfo(assemblyName)); referencedAssemblies.Add(reference); } catch (TypeSystemException) { } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModulesSectionNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModulesSectionNode.cs index 3474a6058232..3bc379eea93a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModulesSectionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModulesSectionNode.cs @@ -25,7 +25,7 @@ public override ObjectNodeSection GetSection(NodeFactory factory) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__Module"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__Module"u8); } public int Offset => 0; public override bool IsShareable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs index 95e731685675..8e5b9c4734f4 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs @@ -42,7 +42,7 @@ public NativeLayoutInfoNode(ExternalReferencesTableNode externalReferences, Exte public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__nativelayoutinfo"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__nativelayoutinfo"u8); } int INodeWithSize.Size => _size.Value; public int Offset => 0; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs index 866c5d0341bf..dae41bc1a770 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs @@ -29,7 +29,7 @@ public PInvokeMethodFixupNode(PInvokeMethodData pInvokeMethodData) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("__pinvoke_"); + sb.Append("__pinvoke_"u8); _pInvokeMethodData.AppendMangledName(nameMangler, sb); } public int Offset => 0; @@ -230,11 +230,11 @@ public int CompareTo(PInvokeMethodData other, CompilerComparer comparer) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { ModuleData.AppendMangledName(nameMangler, sb); - sb.Append("__"); + sb.Append("__"u8); sb.Append(EntryPointName); if (CharSetMangling != default) { - sb.Append("__"); + sb.Append("__"u8); sb.Append(CharSetMangling.ToString()); } if (SignatureBytes >= 0) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeModuleFixupNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeModuleFixupNode.cs index d696e0075b33..0adb9c4f1ab3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeModuleFixupNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeModuleFixupNode.cs @@ -26,7 +26,7 @@ public PInvokeModuleFixupNode(PInvokeModuleData pInvokeModuleData) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("__nativemodule_"); + sb.Append("__nativemodule_"u8); _pInvokeModuleData.AppendMangledName(nameMangler, sb); } public int Offset => 0; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PointerTypeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PointerTypeMapNode.cs index bf2ecfb4c716..bd54793580f7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PointerTypeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PointerTypeMapNode.cs @@ -25,7 +25,7 @@ public PointerTypeMapNode(ExternalReferencesTableNode externalReferences) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__ptr_type_map"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__ptr_type_map"u8); } public int Offset => 0; public override bool IsShareable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs index 8ba2e0876318..332a75b2c6ce 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs @@ -335,7 +335,7 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde else mangledContextName = nameMangler.GetMangledTypeName((TypeDesc)_dictionaryOwner); - sb.Append("__GenericLookupFromDict_").Append(mangledContextName).Append("_"); + sb.Append("__GenericLookupFromDict_"u8).Append(mangledContextName).Append("_"u8); AppendLookupSignatureMangledName(nameMangler, sb); } @@ -357,7 +357,7 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde else mangledContextName = nameMangler.GetMangledTypeName((TypeDesc)_dictionaryOwner); - sb.Append("__GenericLookupFromType_").Append(mangledContextName).Append("_"); + sb.Append("__GenericLookupFromType_"u8).Append(mangledContextName).Append("_"u8); AppendLookupSignatureMangledName(nameMangler, sb); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.cs index e92c6804bbef..bb5f35f4f8fa 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.cs @@ -34,7 +34,7 @@ public void Add(ReadyToRunSectionType id, T node) where T : ObjectNode, ISymb public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(nameMangler.CompilationUnitPrefix); - sb.Append("__ReadyToRunHeader"); + sb.Append("__ReadyToRunHeader"u8); } public int Offset => 0; public override bool IsShareable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs index ab9ccafa2db9..24bda5bb71cd 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs @@ -92,19 +92,19 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde switch (_id) { case ReadyToRunHelperId.GetNonGCStaticBase: - sb.Append("__GetNonGCStaticBase_").Append(nameMangler.GetMangledTypeName((TypeDesc)_target)); + sb.Append("__GetNonGCStaticBase_"u8).Append(nameMangler.GetMangledTypeName((TypeDesc)_target)); break; case ReadyToRunHelperId.GetGCStaticBase: - sb.Append("__GetGCStaticBase_").Append(nameMangler.GetMangledTypeName((TypeDesc)_target)); + sb.Append("__GetGCStaticBase_"u8).Append(nameMangler.GetMangledTypeName((TypeDesc)_target)); break; case ReadyToRunHelperId.GetThreadStaticBase: - sb.Append("__GetThreadStaticBase_").Append(nameMangler.GetMangledTypeName((TypeDesc)_target)); + sb.Append("__GetThreadStaticBase_"u8).Append(nameMangler.GetMangledTypeName((TypeDesc)_target)); break; case ReadyToRunHelperId.DelegateCtor: ((DelegateCreationInfo)_target).AppendMangledName(nameMangler, sb); break; case ReadyToRunHelperId.ResolveVirtualFunction: - sb.Append("__ResolveVirtualFunction_"); + sb.Append("__ResolveVirtualFunction_"u8); sb.Append(nameMangler.GetMangledMethodName((MethodDesc)_target)); break; default: diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedTypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedTypeNode.cs index fa37372f4c6d..0a6327db7e54 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedTypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedTypeNode.cs @@ -34,10 +34,17 @@ public ReflectedTypeNode(TypeDesc type) public override IEnumerable GetStaticDependencies(NodeFactory factory) { - return new DependencyListEntry[] - { - new DependencyListEntry(factory.MaximallyConstructableType(_type), "Reflection target"), - }; + var result = new DependencyList + { + new DependencyListEntry(factory.MaximallyConstructableType(_type), "Reflection target"), + }; + + if (_type.IsCanonicalSubtype(CanonicalFormKind.Any)) + { + GenericTypesTemplateMap.GetTemplateTypeDependencies(ref result, factory, _type); + } + + return result; } protected override string GetName(NodeFactory factory) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs index c657327d5478..09835d6ba607 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs @@ -28,7 +28,7 @@ public ReflectionFieldMapNode(ExternalReferencesTableNode externalReferences) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__field_to_offset_map"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__field_to_offset_map"u8); } public int Offset => 0; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs index e9d5b45d3ee8..a8a4713dcd9a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs @@ -29,7 +29,7 @@ public ReflectionInvokeMapNode(ExternalReferencesTableNode externalReferences) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__method_to_entrypoint_map"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__method_to_entrypoint_map"u8); } public int Offset => 0; public override bool IsShareable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs index 9c49be270bdd..fa6bd51940aa 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs @@ -29,7 +29,7 @@ public ReflectionVirtualInvokeMapNode(ExternalReferencesTableNode externalRefere public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__VirtualInvokeMap"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__VirtualInvokeMap"u8); } int INodeWithSize.Size => _size.Value; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ResourceDataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ResourceDataNode.cs index 6aaac5cd2149..3193d1f8368a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ResourceDataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ResourceDataNode.cs @@ -40,7 +40,7 @@ internal sealed class ResourceDataNode : ObjectNode, ISymbolDefinitionNode, INod public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__embedded_resourcedata"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__embedded_resourcedata"u8); } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ResourceIndexNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ResourceIndexNode.cs index 50e496584ead..5909fe3f20bf 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ResourceIndexNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ResourceIndexNode.cs @@ -2,6 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Reflection; +using System.Reflection.Metadata; +using System.Runtime.InteropServices; using Internal.NativeFormat; using Internal.Text; @@ -34,7 +37,7 @@ public ResourceIndexNode(ResourceDataNode resourceDataNode) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__embedded_resourceindex"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__embedded_resourceindex"u8); } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); @@ -74,7 +77,19 @@ private byte[] GenerateIndexBlob(NodeFactory factory) foreach (ResourceIndexData indexData in _resourceDataNode.GetOrCreateIndexData(factory)) { - string assemblyName = indexData.Assembly.GetName().FullName; + AssemblyNameInfo name = indexData.Assembly.GetName(); + + // References use a public key token instead of full public key. + if ((name.Flags & AssemblyNameFlags.PublicKey) != 0) + { + // Use AssemblyName to convert PublicKey to PublicKeyToken to avoid calling crypto APIs directly + AssemblyName an = new(); + an.SetPublicKey(ImmutableCollectionsMarshal.AsArray(name.PublicKeyOrToken)); + name = new AssemblyNameInfo(name.Name, name.Version, name.CultureName, name.Flags & ~AssemblyNameFlags.PublicKey, ImmutableCollectionsMarshal.AsImmutableArray(an.GetPublicKeyToken())); + } + + string assemblyName = name.FullName; + Vertex asmName = nativeWriter.GetStringConstant(assemblyName); Vertex resourceName = nativeWriter.GetStringConstant(indexData.ResourceName); Vertex offsetVertex = nativeWriter.GetUnsignedConstant((uint)indexData.NativeOffset); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs index 644bc136b590..ddb94c51c9df 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs @@ -22,7 +22,7 @@ public RuntimeFieldHandleNode(FieldDesc targetField) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(nameMangler.CompilationUnitPrefix) - .Append("__RuntimeFieldHandle_") + .Append("__RuntimeFieldHandle_"u8) .Append(nameMangler.GetMangledFieldName(_targetField)); } public int Offset => 0; @@ -38,7 +38,7 @@ protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory) return ObjectNodeSection.DataSection; } - private static Utf8String s_NativeLayoutSignaturePrefix = new Utf8String("__RFHSignature_"); + private static readonly Utf8String s_NativeLayoutSignaturePrefix = new Utf8String("__RFHSignature_"); protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs index eab08b1bcafd..6e20a964a64f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs @@ -28,7 +28,7 @@ public RuntimeMethodHandleNode(MethodDesc targetMethod) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(nameMangler.CompilationUnitPrefix) - .Append("__RuntimeMethodHandle_") + .Append("__RuntimeMethodHandle_"u8) .Append(nameMangler.GetMangledMethodName(_targetMethod)); } public int Offset => 0; @@ -66,7 +66,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact return dependencies; } - private static Utf8String s_NativeLayoutSignaturePrefix = new Utf8String("__RMHSignature_"); + private static readonly Utf8String s_NativeLayoutSignaturePrefix = new Utf8String("__RMHSignature_"); protected override ObjectData GetDehydratableData(NodeFactory factory, bool relocsOnly = false) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs index 725ea9db9e3e..fbe021414800 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs @@ -32,7 +32,7 @@ public SerializedFrozenObjectNode(MetadataType owningType, int allocationSiteId, public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__FrozenObj_") + sb.Append(nameMangler.CompilationUnitPrefix).Append("__FrozenObj_"u8) .Append(nameMangler.GetMangledTypeName(_owningType)) .Append(_allocationSiteId.ToStringInvariant()); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StackTraceMethodMappingNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StackTraceMethodMappingNode.cs index 1c5fc8658e8b..5c26019f81b8 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StackTraceMethodMappingNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StackTraceMethodMappingNode.cs @@ -34,7 +34,7 @@ public sealed class StackTraceMethodMappingNode : ObjectNode, ISymbolDefinitionN public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("_stacktrace_methodRVA_to_token_mapping"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("_stacktrace_methodRVA_to_token_mapping"u8); } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs index 4a1d8d94f3e9..befd99b90945 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs @@ -29,7 +29,7 @@ public StaticsInfoHashtableNode(ExternalReferencesTableNode externalReferences, public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("_StaticsInfoHashtableNode"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("_StaticsInfoHashtableNode"u8); } public int Offset => 0; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs index ed0c278aa115..02089b56ae0d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs @@ -30,7 +30,7 @@ public StructMarshallingStubMapNode(ExternalReferencesTableNode externalReferenc public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__struct_marshalling_stub_map"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__struct_marshalling_stub_map"u8); } public int Offset => 0; public override bool IsShareable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMInitialInterfaceDispatchStubNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMInitialInterfaceDispatchStubNode.cs index f0c2f941e67e..0dc6df46653f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMInitialInterfaceDispatchStubNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMInitialInterfaceDispatchStubNode.cs @@ -26,7 +26,7 @@ public partial class InitialInterfaceDispatchStubNode : AssemblyStubNode public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("_InitialInterfaceDispatchStub"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("_InitialInterfaceDispatchStub"u8); } public override bool IsShareable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TlsRootNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TlsRootNode.cs index a26ff9bec28f..21d9e315ab52 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TlsRootNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TlsRootNode.cs @@ -9,7 +9,7 @@ public class TlsRootNode : ObjectNode, ISymbolDefinitionNode { public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("tls_InlinedThreadStatics"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("tls_InlinedThreadStatics"u8); } public int Offset => 0; public override bool IsShareable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeManagerIndirectionNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeManagerIndirectionNode.cs index 5aac937956b1..37240280b95d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeManagerIndirectionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeManagerIndirectionNode.cs @@ -9,7 +9,7 @@ public class TypeManagerIndirectionNode : ObjectNode, ISymbolDefinitionNode { public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__typemanager_indirection"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__typemanager_indirection"u8); } public int Offset => 0; public override bool IsShareable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs index a23f5e4540df..adc76085ea89 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs @@ -25,7 +25,7 @@ public TypeMetadataMapNode(ExternalReferencesTableNode externalReferences) public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append(nameMangler.CompilationUnitPrefix).Append("__type_to_metadata_map"); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__type_to_metadata_map"u8); } public int Offset => 0; public override bool IsShareable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/UnboxingStubNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/UnboxingStubNode.cs index cc131875e487..6bafdd0f77fe 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/UnboxingStubNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/UnboxingStubNode.cs @@ -38,7 +38,7 @@ public IMethodNode GetUnderlyingMethodEntrypoint(NodeFactory factory) public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - sb.Append("unbox_").Append(nameMangler.GetMangledMethodName(Method)); + sb.Append("unbox_"u8).Append(nameMangler.GetMangledMethodName(Method)); } public static string GetMangledName(NameMangler nameMangler, MethodDesc method) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DescriptorMarker.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DescriptorMarker.cs index e86c20c31a78..32514dccc5ee 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DescriptorMarker.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DescriptorMarker.cs @@ -162,6 +162,14 @@ private void MarkAndPreserve(TypeDesc type, XPathNavigator nav, TypePreserve pre } #endif + protected override MetadataType? ProcessExportedType(MetadataType exported, ModuleDesc assembly, XPathNavigator nav) + { + // Rooting module metadata roots type forwarder metadata for all types in the module that are reflection visible. + // (We don't track individual type forwarders right now.) + _dependencies.Add(_factory.ModuleMetadata(assembly), "Type used through forwarder"); + return base.ProcessExportedType(exported, assembly, nav); + } + protected override void ProcessType(TypeDesc type, XPathNavigator nav) { Debug.Assert(ShouldProcessElement(nav)); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ExportsFileWriter.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ExportsFileWriter.cs index 5a837262cbd2..2e63ca109b18 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ExportsFileWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ExportsFileWriter.cs @@ -58,7 +58,7 @@ public void EmitExportedMethods() else { streamWriter.WriteLine("V1.0 {"); - streamWriter.WriteLine(" global: _init; _fini;"); + streamWriter.WriteLine(" global:"); foreach (string symbol in _exportSymbols) streamWriter.WriteLine($" {symbol};"); foreach (var method in _methods) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs index 4b6f2f4914a4..7822b9c91ac7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs @@ -70,6 +70,9 @@ public static void GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id, case ReadyToRunHelper.CheckedWriteBarrier: mangledName = context.Target.Architecture == TargetArchitecture.ARM64 ? "RhpCheckedAssignRefArm64" : "RhpCheckedAssignRef"; break; + case ReadyToRunHelper.BulkWriteBarrier: + mangledName = "RhBuffer_BulkMoveWithWriteBarrier"; + break; case ReadyToRunHelper.ByRefWriteBarrier: mangledName = context.Target.Architecture == TargetArchitecture.ARM64 ? "RhpByRefAssignRefArm64" : "RhpByRefAssignRef"; break; @@ -188,16 +191,16 @@ public static void GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id, break; case ReadyToRunHelper.Dbl2IntOvf: - methodDesc = context.GetHelperEntryPoint("MathHelpers", "Dbl2IntOvf"); + methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("ConvertToInt32Checked", null); break; case ReadyToRunHelper.Dbl2UIntOvf: - methodDesc = context.GetHelperEntryPoint("MathHelpers", "Dbl2UIntOvf"); + methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("ConvertToUInt32Checked", null); break; case ReadyToRunHelper.Dbl2LngOvf: - methodDesc = context.GetHelperEntryPoint("MathHelpers", "Dbl2LngOvf"); + methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("ConvertToInt64Checked", null); break; case ReadyToRunHelper.Dbl2ULngOvf: - methodDesc = context.GetHelperEntryPoint("MathHelpers", "Dbl2ULngOvf"); + methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("ConvertToUInt64Checked", null); break; case ReadyToRunHelper.DblRem: @@ -211,10 +214,18 @@ public static void GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id, mangledName = "RhpLMul"; break; case ReadyToRunHelper.LMulOfv: - methodDesc = context.GetHelperEntryPoint("MathHelpers", "LMulOvf"); + { + TypeDesc t = context.GetWellKnownType(WellKnownType.Int64); + methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("MultiplyChecked", + new MethodSignature(MethodSignatureFlags.Static, 0, t, [t, t])); + } break; case ReadyToRunHelper.ULMulOvf: - methodDesc = context.GetHelperEntryPoint("MathHelpers", "ULMulOvf"); + { + TypeDesc t = context.GetWellKnownType(WellKnownType.UInt64); + methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("MultiplyChecked", + new MethodSignature(MethodSignatureFlags.Static, 0, t, [t, t])); + } break; case ReadyToRunHelper.Mod: diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs index b758f89e9478..ebb6e87bd292 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs @@ -1068,7 +1068,12 @@ public bool IsReflectionBlocked(TypeDesc type) case TypeFlags.Array: case TypeFlags.Pointer: case TypeFlags.ByRef: - return IsReflectionBlocked(((ParameterizedType)type).ParameterType); + TypeDesc parameterType = ((ParameterizedType)type).ParameterType; + + if (parameterType.IsCanonicalDefinitionType(CanonicalFormKind.Any)) + return false; + + return IsReflectionBlocked(parameterType); case TypeFlags.FunctionPointer: MethodSignature pointerSignature = ((FunctionPointerType)type).Signature; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MstatObjectDumper.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MstatObjectDumper.cs index 6217fad3c8c4..341be9932824 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MstatObjectDumper.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MstatObjectDumper.cs @@ -19,7 +19,6 @@ using Debug = System.Diagnostics.Debug; using ObjectData = ILCompiler.DependencyAnalysis.ObjectNode.ObjectData; -using AssemblyName = System.Reflection.AssemblyName; namespace ILCompiler { @@ -45,8 +44,8 @@ public class MstatObjectDumper : ObjectDumper public MstatObjectDumper(string fileName, TypeSystemContext context) { _fileName = fileName; - var asmName = new AssemblyName(Path.GetFileName(fileName)); - asmName.Version = new Version(VersionMajor, VersionMinor); + var asmName = new AssemblyNameInfo(Path.GetFileName(fileName), + version: new Version(VersionMajor, VersionMinor)); _emitter = new MstatEmitter(asmName, context); _emitter.AllowUseOfAddGlobalMethod(); } @@ -186,7 +185,7 @@ private sealed class MstatEmitter : TypeSystemMetadataEmitter { private readonly List<(string Name, BlobBuilder Content)> _customSections = new(); - public MstatEmitter(AssemblyName assemblyName, TypeSystemContext context, AssemblyFlags flags = default(AssemblyFlags), byte[] publicKeyArray = null) + public MstatEmitter(AssemblyNameInfo assemblyName, TypeSystemContext context, AssemblyFlags flags = default(AssemblyFlags), byte[] publicKeyArray = null) : base(assemblyName, context, flags, publicKeyArray) { } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/Dwarf/DwarfEhFrame.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/Dwarf/DwarfEhFrame.cs index 1705a10dd1ab..3e207ffe2961 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/Dwarf/DwarfEhFrame.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/Dwarf/DwarfEhFrame.cs @@ -81,7 +81,7 @@ private void WriteCie(DwarfCie cie) 4u + // Length 4u + // CIE Offset (0) 1u + // Version - (uint)augmentationString.Length + 1u + + (uint)augmentationString.Length + 1u + // null-terminator DwarfHelper.SizeOfULEB128(cie.CodeAlignFactor) + DwarfHelper.SizeOfSLEB128(cie.DataAlignFactor) + DwarfHelper.SizeOfULEB128(cie.ReturnAddressRegister) + @@ -93,7 +93,8 @@ private void WriteCie(DwarfCie cie) _sectionWriter.WriteLittleEndian(0); _sectionWriter.WriteByte(cie.ReturnAddressRegister < 0x7F ? (byte)1u : (byte)3u); // Version - _sectionWriter.Write(augmentationString.UnderlyingArray); + _sectionWriter.Write(augmentationString.AsSpan()); + _sectionWriter.WriteByte(0); // null-terminator _sectionWriter.WriteULEB128(cie.CodeAlignFactor); _sectionWriter.WriteSLEB128(cie.DataAlignFactor); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/MachObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/MachObjectWriter.cs index 86ac433262f9..e65f7c889dd1 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/MachObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/MachObjectWriter.cs @@ -244,16 +244,12 @@ private protected override void EmitObjectFile(string objectFilePath) { case TargetOS.OSX: buildVersion.Platform = PLATFORM_MACOS; - buildVersion.MinimumPlatformVersion = 0x0A_0C_00; // 10.12.0 + buildVersion.MinimumPlatformVersion = 0x0C_00_00; // 12.0.0 break; case TargetOS.MacCatalyst: buildVersion.Platform = PLATFORM_MACCATALYST; - buildVersion.MinimumPlatformVersion = _cpuType switch - { - CPU_TYPE_X86_64 => 0x0D_05_00u, // 13.5.0 - _ => 0x0E_02_00u, // 14.2.0 - }; + buildVersion.MinimumPlatformVersion = 0x0F_02_00; // 15.0.0 break; case TargetOS.iOS: @@ -268,7 +264,7 @@ private protected override void EmitObjectFile(string objectFilePath) TargetOS.tvOSSimulator => PLATFORM_TVOSSIMULATOR, _ => 0, }; - buildVersion.MinimumPlatformVersion = 0x0B_00_00; // 11.0.0 + buildVersion.MinimumPlatformVersion = 0x0C_02_00; // 12.2.0 break; } buildVersion.Write(outputFileStream); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/SubstitutedILProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/SubstitutedILProvider.cs index 09c54b96c5e8..a875e55b82ba 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/SubstitutedILProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/SubstitutedILProvider.cs @@ -673,10 +673,10 @@ private bool TryGetConstantArgument(MethodIL methodIL, byte[] body, OpcodeFlags[ { return true; } - else if (method.IsIntrinsic && method.Name is "get_IsValueType" + else if (method.IsIntrinsic && method.Name is "get_IsValueType" or "get_IsEnum" && method.OwningType is MetadataType mdt && mdt.Name == "Type" && mdt.Namespace == "System" && mdt.Module == mdt.Context.SystemModule - && TryExpandTypeIsValueType(methodIL, body, flags, currentOffset, out constant)) + && TryExpandTypeIs(methodIL, body, flags, currentOffset, method.Name, out constant)) { return true; } @@ -819,7 +819,7 @@ private bool TryGetConstantArgument(MethodIL methodIL, byte[] body, OpcodeFlags[ return false; } - private static bool TryExpandTypeIsValueType(MethodIL methodIL, byte[] body, OpcodeFlags[] flags, int offset, out int constant) + private static bool TryExpandTypeIs(MethodIL methodIL, byte[] body, OpcodeFlags[] flags, int offset, string name, out int constant) { // We expect to see a sequence: // ldtoken Foo @@ -848,7 +848,12 @@ private static bool TryExpandTypeIsValueType(MethodIL methodIL, byte[] body, Opc if (type.IsSignatureVariable) return false; - constant = type.IsValueType ? 1 : 0; + constant = name switch + { + "get_IsValueType" => type.IsValueType ? 1 : 0, + "get_IsEnum" => type.IsEnum ? 1 : 0, + _ => throw new Exception(), + }; return true; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index 2f94045c153a..c612e86dfad6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -535,8 +535,14 @@ private Status TryScanMethod(MethodIL methodIL, Value[] parameters, Stack - - - Compiler\Dataflow\TypeNameParser.cs + + Utilities\TypeNameHelpers.cs Utilities\ValueStringBuilder.cs @@ -736,9 +735,6 @@ JitInterface\CorInfoTypes.VarInfo.cs - - JitInterface\MemoryHelper.cs - TypeSystem\TypesDebugInfoWriter\TypesDebugInfoWriter.cs diff --git a/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/ILCompiler.DependencyAnalysisFramework.csproj b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/ILCompiler.DependencyAnalysisFramework.csproj index 28aa33b5afe7..763d6bfbc27b 100644 --- a/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/ILCompiler.DependencyAnalysisFramework.csproj +++ b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/ILCompiler.DependencyAnalysisFramework.csproj @@ -1,4 +1,8 @@ - + + + AnyCPU + + Library ILCompiler.DependencyAnalysisFramework @@ -8,6 +12,10 @@ x64;x86 AnyCPU false + + <_RequiresLiveILLink>false + + true - $(RuntimeIdentifiers);freebsd-x64;freebsd-arm64 Debug;Release;Checked true false diff --git a/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj b/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj index 657ac23590a0..12c95db67944 100644 --- a/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj +++ b/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj @@ -4,6 +4,17 @@ <_IsPublishing>true + + <_ComObjectDescriptorSupport>false + + + + + + diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index 754394f16ee9..905ddd41d82b 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -92,6 +92,7 @@ struct JitInterfaceCallbacks TypeCompareState (* compareTypesForEquality)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2); bool (* isMoreSpecificType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2); bool (* isExactType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); + TypeCompareState (* isNullableType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); TypeCompareState (* isEnum)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType); CORINFO_CLASS_HANDLE (* getParentType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CorInfoType (* getChildType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE clsHnd, CORINFO_CLASS_HANDLE* clsRet); @@ -178,7 +179,7 @@ struct JitInterfaceCallbacks bool (* logMsg)(void * thisHandle, CorInfoExceptionClass** ppException, unsigned level, const char* fmt, va_list args); int (* doAssert)(void * thisHandle, CorInfoExceptionClass** ppException, const char* szFile, int iLine, const char* szExpr); void (* reportFatalError)(void * thisHandle, CorInfoExceptionClass** ppException, CorJitResult result); - JITINTERFACE_HRESULT (* getPgoInstrumentationResults)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, ICorJitInfo::PgoSource* pgoSource); + JITINTERFACE_HRESULT (* getPgoInstrumentationResults)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource, bool* pDynamicPgo); JITINTERFACE_HRESULT (* allocPgoInstrumentationBySchema)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, uint32_t countSchemaItems, uint8_t** pInstrumentationData); void (* recordCallSite)(void * thisHandle, CorInfoExceptionClass** ppException, uint32_t instrOffset, CORINFO_SIG_INFO* callSig, CORINFO_METHOD_HANDLE methodHandle); void (* recordRelocation)(void * thisHandle, CorInfoExceptionClass** ppException, void* location, void* locationRW, void* target, uint16_t fRelocType, int32_t addlDelta); @@ -992,6 +993,15 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } + virtual TypeCompareState isNullableType( + CORINFO_CLASS_HANDLE cls) +{ + CorInfoExceptionClass* pException = nullptr; + TypeCompareState temp = _callbacks->isNullableType(_thisHandle, &pException, cls); + if (pException != nullptr) throw pException; + return temp; +} + virtual TypeCompareState isEnum( CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType) @@ -1833,10 +1843,11 @@ class JitInterfaceWrapper : public ICorJitInfo ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, - ICorJitInfo::PgoSource* pgoSource) + ICorJitInfo::PgoSource* pPgoSource, + bool* pDynamicPgo) { CorInfoExceptionClass* pException = nullptr; - JITINTERFACE_HRESULT temp = _callbacks->getPgoInstrumentationResults(_thisHandle, &pException, ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pgoSource); + JITINTERFACE_HRESULT temp = _callbacks->getPgoInstrumentationResults(_thisHandle, &pException, ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, pDynamicPgo); if (pException != nullptr) throw pException; return temp; } diff --git a/src/coreclr/tools/cdac-build-tool/ComposeCommand.cs b/src/coreclr/tools/cdac-build-tool/ComposeCommand.cs new file mode 100644 index 000000000000..226244a88872 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/ComposeCommand.cs @@ -0,0 +1,91 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.CommandLine; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +internal sealed class ComposeCommand : CliCommand +{ + private readonly CliArgument inputFiles = new("INPUT [INPUTS...]") { Arity = ArgumentArity.OneOrMore, Description = "One or more input files" }; + private readonly CliOption outputFile = new("-o") { Arity = ArgumentArity.ExactlyOne, HelpName = "OUTPUT", Required = true, Description = "Output file" }; + private readonly CliOption contractFile = new("-c") { Arity = ArgumentArity.ZeroOrMore, HelpName = "CONTRACT", Description = "Contract file (may be specified multiple times)" }; + private readonly CliOption _verboseOption; + public ComposeCommand(CliOption verboseOption) : base("compose") + { + _verboseOption = verboseOption; + Add(inputFiles); + Add(outputFile); + Add(contractFile); + SetAction(Run); + } + + private async Task Run(ParseResult parse, CancellationToken token = default) + { + var inputs = parse.GetValue(inputFiles); + if (inputs == null || inputs.Length == 0) + { + Console.Error.WriteLine("No input files specified"); + return 1; + } + var output = parse.GetValue(outputFile); + if (output == null) + { + Console.Error.WriteLine("No output file specified"); + return 1; + } + var contracts = parse.GetValue(contractFile); + var verbose = parse.GetValue(_verboseOption); + var builder = new DataDescriptorModel.Builder(); + var scraper = new ObjectFileScraper(verbose, builder); + foreach (var input in inputs) + { + token.ThrowIfCancellationRequested(); + if (!await scraper.ScrapeInput(input, token).ConfigureAwait(false)) + { + Console.Error.WriteLine($"could not scrape payload in {input}"); + return 1; + } + } + if (contracts != null) + { + var contractReader = new ContractReader(builder); + foreach (var contract in contracts) + { + if (!await contractReader.ParseContracts(contract, token).ConfigureAwait(false)) + { + Console.Error.WriteLine($"could not parse contracts in {contract}"); + return 1; + } + } + } + + var model = builder.Build(); + if (verbose) + { + model.DumpModel(); + } + EnsureDirectoryExists(output); + using var writer = new System.IO.StreamWriter(output); + var emitter = new ContractDescriptorSourceFileEmitter(); + emitter.SetPlatformFlags(model.PlatformFlags); + emitter.SetPointerDataCount(model.PointerDataCount); + emitter.SetJsonDescriptor(model.ToJson()); + emitter.Emit(writer); + await writer.FlushAsync(token).ConfigureAwait(false); + return 0; + } + + private static void EnsureDirectoryExists(string outputPath) + { + var directory = System.IO.Path.GetDirectoryName(outputPath); + if (directory == null) + { + return; + } + System.IO.Directory.CreateDirectory(directory); + } +} diff --git a/src/coreclr/tools/cdac-build-tool/ContractDescriptorSourceFileEmitter.cs b/src/coreclr/tools/cdac-build-tool/ContractDescriptorSourceFileEmitter.cs new file mode 100644 index 000000000000..dde27a6858c6 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/ContractDescriptorSourceFileEmitter.cs @@ -0,0 +1,81 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; + +namespace Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +public partial class ContractDescriptorSourceFileEmitter +{ + public const string TemplateResourceName = "Microsoft.DotNet.Diagnostics.DataContract.Resources.contract-descriptor.c.in"; + private const string JsonDescriptorKey = "jsonDescriptor"; + private const string JsonDescriptorSizeKey = "jsonDescriptorSize"; + private const string PointerDataCount = "pointerDataCount"; + private const string PlatformFlags = "platformFlags"; + + + [GeneratedRegex("%%([a-zA-Z0-9_]+)%%", RegexOptions.CultureInvariant)] + private static partial Regex FindTemplatePlaceholderRegex(); + + internal static Stream GetTemplateStream() + { + return typeof(ContractDescriptorSourceFileEmitter).Assembly.GetManifestResourceStream(TemplateResourceName)!; + } + + internal static string GetTemplateString() + { + using var reader = new StreamReader(GetTemplateStream(), System.Text.Encoding.UTF8); + return reader.ReadToEnd(); + } + + public void SetPointerDataCount(int count) + { + Elements[PointerDataCount] = count.ToString(); + } + + public void SetPlatformFlags(uint platformFlags) + { + Elements[PlatformFlags] = $"0x{platformFlags:x8}"; + } + + /// The jsonDescriptor should not be C escaped + public void SetJsonDescriptor(string jsonDescriptor) + { + var count = jsonDescriptor.Length; // return the length before escaping + var escaped = CStringEscape().Replace(jsonDescriptor, "\\$1"); + Elements[JsonDescriptorKey] = escaped; + Elements[JsonDescriptorSizeKey] = count.ToString(); + } + + [GeneratedRegex("(\")", RegexOptions.CultureInvariant)] + private static partial Regex CStringEscape(); + + public Dictionary Elements { get; } = new(); + + public void Emit(TextWriter dest) + { + var template = GetTemplateString(); + var matches = FindTemplatePlaceholderRegex().Matches(template); + var prevPos = 0; + foreach (Match match in matches) + { + // copy everything from the end of the last match (prevPos) to just before the current match to the output + dest.Write(template.AsSpan(prevPos, match.Index - prevPos)); + + // lookup the capture key and write it out + + var key = match.Groups[1].Captures[0].Value; + if (!Elements.TryGetValue(key, out string? result)) + { + throw new InvalidOperationException ($"no replacement for {key}"); + } + dest.Write(result); + prevPos = match.Index + match.Length; + } + // write everything from the prevPos to the end of the template + dest.Write(template.AsSpan(prevPos)); + } +} diff --git a/src/coreclr/tools/cdac-build-tool/ContractReader.cs b/src/coreclr/tools/cdac-build-tool/ContractReader.cs new file mode 100644 index 000000000000..3bd8ec0c77e7 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/ContractReader.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +public class ContractReader +{ + private readonly DataDescriptorModel.Builder _builder; + + private static readonly JsonSerializerOptions s_jsonSerializerOptions = new() { PropertyNameCaseInsensitive = false, ReadCommentHandling = JsonCommentHandling.Skip }; + + public ContractReader(DataDescriptorModel.Builder builder) + { + _builder = builder; + } + + public async Task ParseContracts(string contractFilePath, CancellationToken token = default) + { + string? contents = await File.ReadAllTextAsync(contractFilePath, token).ConfigureAwait(false); + var contracts = JsonSerializer.Deserialize>(contents, s_jsonSerializerOptions); + if (contracts is null) + return false; + _builder.AddOrupdateContracts(contracts); + return true; + } +} diff --git a/src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs b/src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs new file mode 100644 index 000000000000..d9d802d35997 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs @@ -0,0 +1,385 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.DotNet.Diagnostics.DataContract.JsonConverter; + +namespace Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +public class DataDescriptorModel +{ + public int Version => 0; + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public string Baseline { get; } + public IReadOnlyDictionary Types { get; } + public IReadOnlyDictionary Globals { get; } + public IReadOnlyDictionary Contracts { get; } + [JsonIgnore] + public uint PlatformFlags { get; } + // The number of indirect globals plus 1 for the placeholder at index 0 + [JsonIgnore] + public int PointerDataCount => 1 + Globals.Values.Count(g => g.Value.Indirect); + + private DataDescriptorModel(string baseline, IReadOnlyDictionary types, IReadOnlyDictionary globals, IReadOnlyDictionary contracts, uint platformFlags) + { + Baseline = baseline; + Types = types; + Globals = globals; + Contracts = contracts; + PlatformFlags = platformFlags; + } + + public const string PointerTypeName = "pointer"; + + internal void DumpModel() + { + Console.WriteLine("\nData Descriptor Model:"); + Console.WriteLine($"Platform Flags: 0x{PlatformFlags:x8}"); + Console.WriteLine($"Baseline: {Baseline}"); + foreach (var (typeName, type) in Types) + { + Console.WriteLine($"Type: {typeName}"); + if (type.Size != null) + { + Console.WriteLine($" Size: 0x{type.Size:x8}"); + } + foreach (var (fieldName, field) in type.Fields) + { + Console.WriteLine($" Field: {fieldName}"); + Console.WriteLine($" Type: {field.Type}"); + Console.WriteLine($" Offset: 0x{field.Offset:x8}"); + } + } + foreach (var (globalName, global) in Globals) + { + Console.WriteLine($"Global: {globalName}"); + Console.WriteLine($" Type: {global.Type}"); + Console.WriteLine($" Value: {global.Value}"); + } + foreach (var (contractName, contract) in Contracts) + { + Console.WriteLine($"Contract: {contractName}"); + Console.WriteLine($" Version: {contract}"); + } + } + + private static JsonSerializerOptions s_jsonSerializerOptions = new JsonSerializerOptions + { + WriteIndented = false, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + DictionaryKeyPolicy = null, // leave unchanged + }; + public string ToJson() + { + // always writes the "compact" format, see data_descriptor.md + return JsonSerializer.Serialize(this, s_jsonSerializerOptions); + } + + public class Builder + { + private string _baseline; + private bool _baselineParsed; + private readonly Dictionary _types = new(); + private readonly Dictionary _globals = new(); + private readonly Dictionary _contracts = new(); + public Builder() + { + _baseline = string.Empty; + _baselineParsed = false; + } + + public uint PlatformFlags {get; set;} + + public TypeModelBuilder AddOrUpdateType(string name, int? size) + { + if (!_baselineParsed) + { + throw new InvalidOperationException("Baseline must be set before adding types"); + } + if (!_types.TryGetValue(name, out var type)) + { + type = new TypeModelBuilder(); + _types[name] = type; + } + type.Size = size; + return type; + } + + public GlobalBuilder AddOrUpdateGlobal(string name, string type, GlobalValue? value) + { + if (!_baselineParsed) + { + throw new InvalidOperationException("Baseline must be set before adding globals"); + } + if (!_globals.TryGetValue(name, out var global)) + { + global = new GlobalBuilder(); + _globals[name] = global; + } + global.Type = type; + global.Value = value; + return global; + } + + public void AddOrUpdateContract(string name, int version) + { + if (!_contracts.TryGetValue(name, out var contract)) + { + contract = new ContractBuilder(); + _contracts[name] = contract; + } + contract.Version = version; + } + + public void AddOrupdateContracts(IEnumerable> contracts) + { + foreach (var (name, version) in contracts) + { + AddOrUpdateContract(name, version); + } + } + + public void SetBaseline(string baseline) + { + if (_baseline != string.Empty && _baseline != baseline) + { + throw new InvalidOperationException($"Baseline already set to {_baseline} cannot set to {baseline}"); + } + if (EmbeddedBaselines.BaselineNames.Contains(baseline)) + { + _baseline = baseline; + } + else + { + throw new InvalidOperationException($"Baseline '{baseline}' not known"); + } + _baseline = baseline; + if (!_baselineParsed) + { + _baselineParsed = true; // kind of a hack - set it before parsing the baseline, so we can call AddOrUpdateType + ParseBaseline(); + } + } + + private void ParseBaseline() + { + if (_baseline != "empty") + { + throw new InvalidOperationException("TODO: [cdac] - implement baseline parsing"); + } + } + + public DataDescriptorModel Build() + { + var types = new Dictionary(); + foreach (var (typeName, typeBuilder) in _types) + { + types[typeName] = typeBuilder.Build(typeName); + } + var globals = new Dictionary(); + foreach (var (globalName, globalBuilder) in _globals) + { + GlobalValue? v = globalBuilder.Value; + if (v == null) + { + throw new InvalidOperationException($"Value must be set for global {globalName}"); + } + globals[globalName] = new GlobalModel { Type = globalBuilder.Type, Value = v.Value }; + } + var contracts = new Dictionary(); + foreach (var (contractName, contractBuilder) in _contracts) + { + contracts[contractName] = contractBuilder.Build(); + } + return new DataDescriptorModel(_baseline, types, globals, contracts, PlatformFlags); + } + } + + public class TypeModelBuilder + { + private readonly Dictionary _fields = new(); + private int? _size; + public TypeModelBuilder() { } + + public int? Size + { + get => _size; + set + { + if (_size != null && (value == null || _size != (int)value)) + { + throw new InvalidOperationException($"Size already set to {_size} cannot set to {value}"); + } + _size = value; + } + } + + public void AddOrUpdateField(string name, string type, int? offset) + { + if (!_fields.TryGetValue(name, out var field)) + { + field = new FieldBuilder(); + _fields[name] = field; + } + field.Type = type; + field.Offset = offset; + } + + public TypeModel Build(string typeName) + { + var fields = new Dictionary(); + foreach (var (fieldName, fieldBuilder) in _fields) + { + fields.Add(fieldName, fieldBuilder.Build(typeName, fieldName)); + } + return new TypeModel { Size = _size, Fields = fields }; + } + } + + public class GlobalBuilder + { + private string _type = string.Empty; + private GlobalValue? _value; + public string Type + { + get => _type; + set + { + if (_type != string.Empty && _type != value) + { + throw new InvalidOperationException($"Type already set to {_type} cannot set to {value}"); + } + _type = value; + } + } + public GlobalValue? Value + { + get => _value; + set + { + if (_value != null && _value != value) + { + throw new InvalidOperationException($"Value already set to {_value} cannot set to {value}"); + } + _value = value; + } + } + } + internal sealed class FieldBuilder + { + private string _type = string.Empty; + private int? _offset; + public string Type + { + get => _type; + set + { + if (_type != string.Empty && _type != value) + { + throw new InvalidOperationException($"Type already set to {_type} cannot set to {value}"); + } + _type = value; + } + } + + public int? Offset + { + get => _offset; + set + { + if (_offset != null && (value == null || _offset != (int)value)) + { + throw new InvalidOperationException($"Offset already set to {_offset} cannot set to {value}"); + } + _offset = value; + } + } + + public FieldModel Build(string typeName, string fieldName) + { + if (_offset == null) + { + throw new InvalidOperationException($"Offset must be set for {typeName}.{fieldName}"); + } + return new FieldModel { Type = _type, Offset = (int)_offset }; + } + } + + [JsonConverter(typeof(FieldModelJsonConverter))] + public readonly struct FieldModel + { + public string Type { get; init; } + public int Offset { get; init; } + } + + [JsonConverter(typeof(TypeModelJsonConverter))] + public readonly struct TypeModel + { + public int? Size { get; init; } + public IReadOnlyDictionary Fields { get; init; } + } + + [JsonConverter(typeof(GlobalValueJsonConverter))] + public readonly struct GlobalValue : IEquatable + { + public bool Indirect { get; private init; } + public ulong Value { get; } + public static GlobalValue MakeDirect(ulong value) => new GlobalValue(value); + public static GlobalValue MakeIndirect(uint auxDataIdx) => new GlobalValue((ulong)auxDataIdx) { Indirect = true }; + private GlobalValue(ulong value) { Value = value; } + + public static bool operator ==(GlobalValue left, GlobalValue right) => left.Value == right.Value && left.Indirect == right.Indirect; + public static bool operator !=(GlobalValue left, GlobalValue right) => !(left == right); + + public bool Equals(GlobalValue other) => this == other; + public override bool Equals(object? obj) => obj is GlobalValue value && this == value; + public override int GetHashCode() => HashCode.Combine(Value, Indirect); + public override string ToString() => Indirect ? $"Indirect({Value})" : $"0x{Value:x}"; + } + + [JsonConverter(typeof(GlobalModelJsonConverter))] + public readonly struct GlobalModel + { + public string Type { get; init; } + public GlobalValue Value { get; init; } + } + + public class ContractBuilder + { + private int? _version; + public ContractBuilder() + { + } + + public int? Version + { + get => _version; + set + { + if (_version != null && _version != value) + { + throw new InvalidOperationException($"Version already set to {_version} cannot set to {value}"); + } + _version = value; + } + } + + // There is no ContractModel right now because the only info we keep is the version. + // As a result it is convenient to use a Dictionary for the contracts since + // the JSON serialization coincides with what we want. + public int Build() + { + if (_version == null) + { + throw new InvalidOperationException("Version must be set for contract"); + } + return _version.Value; + } + } +} diff --git a/src/coreclr/tools/cdac-build-tool/Directory.Build.props b/src/coreclr/tools/cdac-build-tool/Directory.Build.props new file mode 100644 index 000000000000..465a55954dfe --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/Directory.Build.props @@ -0,0 +1,7 @@ + + + + <_RequiresLiveILLink>false + + + diff --git a/src/coreclr/tools/cdac-build-tool/EmbeddedBaselines.cs b/src/coreclr/tools/cdac-build-tool/EmbeddedBaselines.cs new file mode 100644 index 000000000000..ac9cea8b6615 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/EmbeddedBaselines.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; + +namespace Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +public partial class EmbeddedBaselines +{ + public const string TemplateResourceNamePrefix = "Microsoft.DotNet.Diagnostics.DataContract.Baseline:"; + public const string TemplateResourceNameEscapePrefix = @"Microsoft\.DotNet\.Diagnostics\.DataContract\.Baseline:"; + public const string TemplateResourceNameExt = ".jsonc"; + public const string TemplateResourceNameEscapeExt = @"\.jsonc"; + + [GeneratedRegex("^" + TemplateResourceNameEscapePrefix + "(.+)" + TemplateResourceNameEscapeExt + "$", RegexOptions.CultureInvariant)] + private static partial Regex BaselineRegex(); + + private static string[] GetBaselineNames() + { + var assembly = typeof(EmbeddedBaselines).Assembly; + var resources = assembly.GetManifestResourceNames(); + var baselineNames = new List(); + foreach (var resource in resources) + { + var match = BaselineRegex().Match(resource); + if (match.Success) + { + baselineNames.Add(match.Groups[1].Value); + } + } + return baselineNames.ToArray(); + } + + private static readonly Lazy> _baselineNames = new(GetBaselineNames); + public static IReadOnlyList BaselineNames => _baselineNames.Value; + + public static string GetBaselineContent(string name) + { + var assembly = typeof(EmbeddedBaselines).Assembly; + var resourceName = TemplateResourceNamePrefix + name + TemplateResourceNameExt; + using var stream = assembly.GetManifestResourceStream(resourceName); + if (stream == null) + { + throw new InvalidOperationException($"Baseline '{name}' not found"); + } + using var reader = new StreamReader(stream); + return reader.ReadToEnd(); + } +} diff --git a/src/coreclr/tools/cdac-build-tool/JsonConverter/FieldModelJsonConverter.cs b/src/coreclr/tools/cdac-build-tool/JsonConverter/FieldModelJsonConverter.cs new file mode 100644 index 000000000000..e86d76c18d23 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/JsonConverter/FieldModelJsonConverter.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +namespace Microsoft.DotNet.Diagnostics.DataContract.JsonConverter; + +/// +/// Writes a FieldModel in the compact form of [offset, type] or just offset if type is null. +/// . +/// +public class FieldModelJsonConverter : JsonConverter +{ + public override DataDescriptorModel.FieldModel Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, DataDescriptorModel.FieldModel value, JsonSerializerOptions options) + { + if (string.IsNullOrEmpty(value.Type)) + { + writer.WriteNumberValue(value.Offset); + } + else + { + writer.WriteStartArray(); + writer.WriteNumberValue(value.Offset); + writer.WriteStringValue(value.Type); + writer.WriteEndArray(); + } + } +} diff --git a/src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalModelJsonConverter.cs b/src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalModelJsonConverter.cs new file mode 100644 index 000000000000..310d02730e1a --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalModelJsonConverter.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +namespace Microsoft.DotNet.Diagnostics.DataContract.JsonConverter; +public class GlobalModelJsonConverter : JsonConverter +{ + public override DataDescriptorModel.GlobalModel Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, DataDescriptorModel.GlobalModel value, JsonSerializerOptions options) + { + if (string.IsNullOrEmpty(value.Type)) + { + // no type: just write 'value' or '[value]' + JsonSerializer.Serialize(writer, value.Value, options); + } + else + { + // there's a type. Write: [value, type] or [[value], type] + writer.WriteStartArray(); + JsonSerializer.Serialize(writer, value.Value, options); + writer.WriteStringValue(value.Type); + writer.WriteEndArray(); + } + } +} diff --git a/src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalValueJsonConverter.cs b/src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalValueJsonConverter.cs new file mode 100644 index 000000000000..429f6cc69792 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalValueJsonConverter.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +namespace Microsoft.DotNet.Diagnostics.DataContract.JsonConverter; +public class GlobalValueJsonConverter : JsonConverter +{ + public override DataDescriptorModel.GlobalValue Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, DataDescriptorModel.GlobalValue value, JsonSerializerOptions options) + { + if (!value.Indirect) + { + // no type: just write value as a number. + // we always write as a string containing a hex number + writer.WriteStringValue($"0x{value.Value:x}"); + } + else + { + // pointer data index. write as a 1-element array containing a decimal number + writer.WriteStartArray(); + writer.WriteNumberValue(value.Value); + writer.WriteEndArray(); + } + } +} diff --git a/src/coreclr/tools/cdac-build-tool/JsonConverter/TypeModelJsonConverter.cs b/src/coreclr/tools/cdac-build-tool/JsonConverter/TypeModelJsonConverter.cs new file mode 100644 index 000000000000..bf400253d5dd --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/JsonConverter/TypeModelJsonConverter.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +namespace Microsoft.DotNet.Diagnostics.DataContract.JsonConverter; +public class TypeModelJsonConverter : JsonConverter +{ + public const string SizePropertyname = "!"; + + public override DataDescriptorModel.TypeModel Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, DataDescriptorModel.TypeModel value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + if (value.Size is not null) + { + writer.WriteNumber(SizePropertyname, value.Size.Value); + } + foreach (var (fieldName, field) in value.Fields) + { + writer.WritePropertyName(fieldName); + JsonSerializer.Serialize(writer, field, options); + } + writer.WriteEndObject(); + } +} diff --git a/src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs b/src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs new file mode 100644 index 000000000000..42b0b004c898 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs @@ -0,0 +1,519 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +public class ObjectFileScraper +{ + public static readonly ReadOnlyMemory MagicLE = new byte[8] { 0x44, 0x41, 0x43, 0x42, 0x4C, 0x4F, 0x42, 0x00 }; // "DACBLOB\0" + public static readonly ReadOnlyMemory MagicBE = new byte[8] { 0x00, 0x42, 0x4F, 0x4C, 0x42, 0x43, 0x41, 0x44 }; + + private readonly DataDescriptorModel.Builder _builder; + + public bool Verbose {get;} + public ObjectFileScraper(bool verbose, DataDescriptorModel.Builder builder) + { + Verbose = verbose; + _builder = builder; + } + + public async Task ScrapeInput(string inputPath, CancellationToken token) + { + var bytes = await File.ReadAllBytesAsync(inputPath, token).ConfigureAwait(false); + if (!ScraperState.CreateScraperState(bytes, out var state)) + { + return false; + } + if (Verbose) + { + Console.WriteLine($"Magic starts at 0x{state.MagicStart:x8} in {inputPath}"); + } + var header = ReadHeader(state); + if (Verbose) + { + DumpHeaderDirectory(header); + } + var content = ReadContent(state, header); + content.AddToModel(_builder); + if (Verbose) + { + Console.WriteLine($"\nFinished scraping content from {inputPath}"); + } + return true; + } + + private sealed class ScraperState + { + public ReadOnlyMemory Data { get; } + public bool LittleEndian { get; } + private long _position; + + // expect MagicLE and MagicBE to have the same length + public long MagicStart => HeaderStart - MagicLE.Length; + public long HeaderStart { get; } + + private ScraperState(ReadOnlyMemory data, bool isLittleEndian, long headerStart) + { + Data = data; + LittleEndian = isLittleEndian; + HeaderStart = headerStart; + _position = headerStart; + } + + public static bool CreateScraperState(ReadOnlyMemory bytes, [NotNullWhen(true)] out ScraperState? scraperState) + { + if (FindMagic(bytes.Span, out int offset, out bool isLittleEndian)) + { + scraperState = new ScraperState(bytes, isLittleEndian, offset + MagicLE.Length); + return true; + } + scraperState = null; + return false; + } + + private static bool FindMagic(ReadOnlySpan buffer, out int offset, out bool isLittleEndian) + { + int start = buffer.IndexOf(MagicLE.Span); + if (start != -1) + { + offset = start; + isLittleEndian = true; + return true; + } + start = buffer.IndexOf(MagicBE.Span); + if (start != -1) + { + offset = start; + isLittleEndian = false; + return true; + } + offset = 0; + isLittleEndian = false; + return false; + } + + public ulong GetUInt64(long offset) => LittleEndian ? BinaryPrimitives.ReadUInt64LittleEndian(Data.Span.Slice((int)offset)) : BinaryPrimitives.ReadUInt64BigEndian(Data.Span.Slice((int)offset)); + public uint GetUInt32(long offset) => LittleEndian ? BinaryPrimitives.ReadUInt32LittleEndian(Data.Span.Slice((int)offset)) : BinaryPrimitives.ReadUInt32BigEndian(Data.Span.Slice((int)offset)); + public ushort GetUInt16(long offset) => LittleEndian ? BinaryPrimitives.ReadUInt16LittleEndian(Data.Span.Slice((int)offset)) : BinaryPrimitives.ReadUInt16BigEndian(Data.Span.Slice((int)offset)); + public byte GetByte(long offset) => Data.Span[(int)offset]; + + public ReadOnlySpan GetBytes(long offset, int length) => Data.Span.Slice((int)offset, length); + + public void ResetPosition(long position) + { + _position = position; + } + + public ulong ReadUInt64() + { + var value = GetUInt64(_position); + _position += sizeof(ulong); + return value; + } + public uint ReadUInt32() + { + var value = GetUInt32(_position); + _position += sizeof(uint); + return value; + } + public ushort ReadUInt16() + { + var value = GetUInt16(_position); + _position += sizeof(ushort); + return value; + } + + public byte ReadByte() + { + var value = GetByte(_position); + _position += sizeof(byte); + return value; + } + public void ReadBytes(Span buffer) + { + GetBytes(_position, buffer.Length).CopyTo(buffer); + _position += buffer.Length; + } + + public void Skip(int count) + { + _position += count; + } + } + + // see typedef Directory in data-descriptor-blob.md + private struct HeaderDirectory + { + public uint FlagsAndBaselineStart; + public uint TypesStart; + + public uint FieldsPoolStart; + public uint GlobalLiteralValuesStart; + + public uint GlobalPointersStart; + public uint NamesStart; + + public uint TypesCount; + public uint FieldsPoolCount; + + public uint GlobalLiteralValuesCount; + public uint GlobalPointerValuesCount; + + public uint NamesPoolCount; + + public byte TypeSpecSize; + public byte FieldSpecSize; + public byte GlobalLiteralSpecSize; + public byte GlobalPointerSpecSize; + }; + + private static void DumpHeaderDirectory(HeaderDirectory headerDirectory) + { + Console.WriteLine($""" + Scaped Header Directory: + + Baseline Start = 0x{headerDirectory.FlagsAndBaselineStart:x8} + Types Start = 0x{headerDirectory.TypesStart:x8} + Fields Pool Start = 0x{headerDirectory.FieldsPoolStart:x8} + Global Literals Start = 0x{headerDirectory.GlobalLiteralValuesStart:x8} + Global Pointers Start = 0x{headerDirectory.GlobalPointersStart:x8} + Names Pool Start = 0x{headerDirectory.NamesStart:x8} + + Types Count = {headerDirectory.TypesCount} + Fields Pool Count = {headerDirectory.FieldsPoolCount} + Global Literal Values Count = {headerDirectory.GlobalLiteralValuesCount} + Global Pointer Values Count = {headerDirectory.GlobalPointerValuesCount} + Names Pool Count = {headerDirectory.NamesPoolCount} + + """); + } + + private static HeaderDirectory ReadHeader(ScraperState state) + { + state.ResetPosition(state.HeaderStart); + var baselineStart = state.ReadUInt32(); + var typesStart = state.ReadUInt32(); + + var fieldPoolStart = state.ReadUInt32(); + var globalLiteralValuesStart = state.ReadUInt32(); + + var globalPointersStart = state.ReadUInt32(); + var namesStart = state.ReadUInt32(); + + var typeCount = state.ReadUInt32(); + var fieldPoolCount = state.ReadUInt32(); + + var globalLiteralValuesCount = state.ReadUInt32(); + var globalPointerValuesCount = state.ReadUInt32(); + + var namesPoolCount = state.ReadUInt32(); + + var typeSpecSize = state.ReadByte(); + var fieldSpecSize = state.ReadByte(); + var globalLiteralSpecSize = state.ReadByte(); + var globalPointerSpecSize = state.ReadByte(); + + return new HeaderDirectory { + FlagsAndBaselineStart = baselineStart, + TypesStart = typesStart, + FieldsPoolStart = fieldPoolStart, + GlobalLiteralValuesStart = globalLiteralValuesStart, + GlobalPointersStart = globalPointersStart, + NamesStart = namesStart, + + TypesCount = typeCount, + FieldsPoolCount = fieldPoolCount, + + GlobalLiteralValuesCount = globalLiteralValuesCount, + GlobalPointerValuesCount = globalPointerValuesCount, + + NamesPoolCount = namesPoolCount, + + TypeSpecSize = typeSpecSize, + FieldSpecSize = fieldSpecSize, + GlobalLiteralSpecSize = globalLiteralSpecSize, + GlobalPointerSpecSize = globalPointerSpecSize, + }; + } + + private struct TypeSpec + { + public uint NameIdx; + public uint FieldsIdx; + public ushort? Size; + } + + private struct FieldSpec + { + public uint NameIdx; + public uint TypeNameIdx; + public ushort FieldOffset; + } + + // Like a FieldSpec but with names resolved + private struct FieldEntry + { + public string Name; + public string Type; + public ushort Offset; + } + + private struct GlobalLiteralSpec + { + public uint NameIdx; + public uint TypeNameIdx; + public ulong Value; + } + + private struct GlobalPointerSpec + { + public uint NameIdx; + public uint AuxDataIdx; + } + + private sealed class Content + { + public required bool Verbose {get; init; } + public required uint PlatformFlags { get; init; } + public required uint Baseline { get; init; } + public required IReadOnlyList TypeSpecs { get; init; } + public required IReadOnlyList FieldSpecs { get; init; } + public required IReadOnlyList GlobaLiteralSpecs { get; init; } + public required IReadOnlyList GlobalPointerSpecs { get; init; } + public required ReadOnlyMemory NamesPool { get; init; } + + internal string GetPoolString(uint stringIdx) + { + var nameStart = NamesPool.Span.Slice((int)stringIdx); + var end = nameStart.IndexOf((byte)0); // find the first nul after index + if (end == -1) + throw new InvalidOperationException("expected a nul-terminated name"); + var nameBytes = nameStart.Slice(0, end); + return System.Text.Encoding.UTF8.GetString(nameBytes); + } + + public void AddToModel(DataDescriptorModel.Builder builder) + { + WriteVerbose("\nAdding scraped content to model"); + builder.PlatformFlags = PlatformFlags; + string baseline = GetPoolString(Baseline); + WriteVerbose($"Baseline Name = {baseline}"); + builder.SetBaseline(baseline); + + + FieldEntry[] fields = FieldSpecs.Select((fieldSpec) => + (fieldSpec.NameIdx != 0) ? + new FieldEntry + { + Name = GetPoolString(fieldSpec.NameIdx), + Type = GetPoolString(fieldSpec.TypeNameIdx), + Offset = fieldSpec.FieldOffset + } : + default + ).ToArray(); + + foreach (var typeSpec in TypeSpecs) + { + string typeName = GetPoolString(typeSpec.NameIdx); + var typeBuilder = builder.AddOrUpdateType(typeName, typeSpec.Size); + uint j = typeSpec.FieldsIdx; // convert byte offset to index; + WriteVerbose($"Type {typeName} has fields starting at index {j}"); + while (j < fields.Length && !string.IsNullOrEmpty(fields[j].Name)) + { + typeBuilder.AddOrUpdateField(fields[j].Name, fields[j].Type, fields[j].Offset); + WriteVerbose($"Type {typeName} has field {fields[j].Name} with offset {fields[j].Offset}"); + j++; + } + if (typeSpec.Size is not null) + { + WriteVerbose($"Type {typeName} has size {typeSpec.Size}"); + } + else + { + WriteVerbose($"Type {typeName} has indeterminate size"); + } + } + + foreach (var globalSpec in GlobaLiteralSpecs) + { + var globalName = GetPoolString(globalSpec.NameIdx); + var globalType = GetPoolString(globalSpec.TypeNameIdx); + var globalValue = DataDescriptorModel.GlobalValue.MakeDirect(globalSpec.Value); + builder.AddOrUpdateGlobal(globalName, globalType, globalValue); + WriteVerbose($"Global {globalName} has type {globalType} with value {globalValue}"); + } + + foreach (var globalPointer in GlobalPointerSpecs) + { + var globalName = GetPoolString(globalPointer.NameIdx); + var auxDataIdx = globalPointer.AuxDataIdx; + var globalValue = DataDescriptorModel.GlobalValue.MakeIndirect(auxDataIdx); + builder.AddOrUpdateGlobal(globalName, DataDescriptorModel.PointerTypeName, globalValue); + WriteVerbose($"Global pointer {globalName} has index {globalValue}"); + } + } + + private void WriteVerbose(string msg) + { + if (Verbose) + Console.WriteLine(msg); + } + } + + private Content ReadContent(ScraperState state, HeaderDirectory header) + { + WriteVerbose("\nReading scraped content"); + state.ResetPosition(state.HeaderStart + header.FlagsAndBaselineStart); + var platformFlags = state.ReadUInt32(); + var baselineNameIdx = state.ReadUInt32(); + WriteVerbose($"flags = 0x{platformFlags:x8}, baseline Name Idx = {baselineNameIdx}"); + + TypeSpec[] typeSpecs = ReadTypeSpecs(state, header); + FieldSpec[] fieldSpecs = ReadFieldSpecs(state, header); + GlobalLiteralSpec[] globalLiteralSpecs = ReadGlobalLiteralSpecs(state, header); + GlobalPointerSpec[] globalPointerSpecs = ReadGlobalPointerSpecs(state, header); + byte[] namesPool = ReadNamesPool(state, header); + + byte[] endMagic = new byte[4]; + state.ReadBytes(endMagic.AsSpan()); + if (!CheckEndMagic(endMagic)) + { + throw new InvalidOperationException($"expected endMagic, got 0x{endMagic[0]:x} 0x{endMagic[1]:x} 0x{endMagic[2]:x} 0x{endMagic[3]:x}"); + } + else + { + WriteVerbose("\nFound correct endMagic at end of content"); + } + return new Content + { + Verbose = Verbose, + PlatformFlags = platformFlags, + Baseline = baselineNameIdx, + TypeSpecs = typeSpecs, + FieldSpecs = fieldSpecs, + GlobaLiteralSpecs = globalLiteralSpecs, + GlobalPointerSpecs = globalPointerSpecs, + NamesPool = namesPool + }; + } + + private TypeSpec[] ReadTypeSpecs(ScraperState state, HeaderDirectory header) + { + TypeSpec[] typeSpecs = new TypeSpec[header.TypesCount]; + + state.ResetPosition(state.HeaderStart + (long)header.TypesStart); + for (int i = 0; i < header.TypesCount; i++) + { + int bytesRead = 0; + typeSpecs[i].NameIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + typeSpecs[i].FieldsIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + ushort size = state.ReadUInt16(); + bytesRead += sizeof(ushort); + if (size != 0) + { + typeSpecs[i].Size = size; + } + WriteVerbose($"TypeSpec[{i}]: NameIdx = {typeSpecs[i].NameIdx}, FieldsIdx = {typeSpecs[i].FieldsIdx}, Size = {typeSpecs[i].Size}"); + // skip padding + if (bytesRead < header.TypeSpecSize) + { + state.Skip(header.TypeSpecSize - bytesRead); + } + } + return typeSpecs; + } + + private static FieldSpec[] ReadFieldSpecs(ScraperState state, HeaderDirectory header) + { + state.ResetPosition(state.HeaderStart + (long)header.FieldsPoolStart); + FieldSpec[] fieldSpecs = new FieldSpec[header.FieldsPoolCount]; + for (int i = 0; i < header.FieldsPoolCount; i++) + { + int bytesRead = 0; + fieldSpecs[i].NameIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + fieldSpecs[i].TypeNameIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + fieldSpecs[i].FieldOffset = state.ReadUInt16(); + bytesRead += sizeof(ushort); + // skip padding + if (bytesRead < header.FieldSpecSize) + { + state.Skip(header.FieldSpecSize - bytesRead); + } + } + return fieldSpecs; + } + + private static GlobalLiteralSpec[] ReadGlobalLiteralSpecs(ScraperState state, HeaderDirectory header) + { + GlobalLiteralSpec[] globalSpecs = new GlobalLiteralSpec[header.GlobalLiteralValuesCount]; + state.ResetPosition(state.HeaderStart + (long)header.GlobalLiteralValuesStart); + for (int i = 0; i < header.GlobalLiteralValuesCount; i++) + { + int bytesRead = 0; + globalSpecs[i].NameIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + globalSpecs[i].TypeNameIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + globalSpecs[i].Value = state.ReadUInt64(); + bytesRead += sizeof(ulong); + // skip padding + if (bytesRead < header.GlobalLiteralSpecSize) + { + state.Skip(header.GlobalLiteralSpecSize - bytesRead); + } + } + return globalSpecs; + } + + private static GlobalPointerSpec[] ReadGlobalPointerSpecs(ScraperState state, HeaderDirectory header) + { + GlobalPointerSpec[] globalSpecs = new GlobalPointerSpec[header.GlobalPointerValuesCount]; + state.ResetPosition(state.HeaderStart + (long)header.GlobalPointersStart); + for (int i = 0; i < header.GlobalPointerValuesCount; i++) + { + int bytesRead = 0; + globalSpecs[i].NameIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + globalSpecs[i].AuxDataIdx = state.ReadUInt32(); + bytesRead += sizeof(uint); + // skip padding + if (bytesRead < header.GlobalPointerSpecSize) + { + state.Skip(header.GlobalPointerSpecSize - bytesRead); + } + } + return globalSpecs; + } + + private static byte[] ReadNamesPool(ScraperState state, HeaderDirectory header) + { + byte[] namesPool = new byte[header.NamesPoolCount]; + state.ResetPosition(state.HeaderStart + (long)header.NamesStart); + state.ReadBytes(namesPool.AsSpan()); + return namesPool; + } + + private static bool CheckEndMagic(ReadOnlySpan bytes) + { + return (bytes[0] == 0x01 && bytes[1] == 0x02 && bytes[2] == 0x03 && bytes[3] == 0x04); + } + + private void WriteVerbose(string msg) + { + if (Verbose) + Console.WriteLine(msg); + } +} diff --git a/src/coreclr/tools/cdac-build-tool/Program.cs b/src/coreclr/tools/cdac-build-tool/Program.cs new file mode 100644 index 000000000000..132c13d30fa1 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/Program.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.CommandLine; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Diagnostics.DataContract.BuildTool; + +public class Program +{ + public static async Task Main(string[] args) + { + CliRootCommand rootCommand = new (); + var verboseOption = new CliOption("-v", "--verbose") {Recursive = true, Description = "Verbose"}; + rootCommand.Add(verboseOption); + rootCommand.Add(new DiagramDirective()); + rootCommand.Add(new ComposeCommand(verboseOption)); + return await rootCommand.Parse(args).InvokeAsync().ConfigureAwait(true); + } +} diff --git a/src/coreclr/tools/cdac-build-tool/README.md b/src/coreclr/tools/cdac-build-tool/README.md new file mode 100644 index 000000000000..512026a29860 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/README.md @@ -0,0 +1,134 @@ +# cDAC Build Tool + +## Summary + +The purpose of `cdac-build-tool` is to generate a `.c` file that contains a JSON cDAC contract descriptor. + +It works by processing one or more object files containing data descriptors and zero or more text +files that specify contracts. + +## Running + +```console +% cdac-build-tool compose [-v] -o contractdescriptor.c -c contracts.txt datadescriptor.o +``` +## .NET runtime build integration + +`cdac-build-tool` is meant to run as a CMake custom command. +It consumes a target platform object file and emits a C source +file that contains a JSON contract descriptor. The C source +is then included in the normal build and link steps to create the runtime. + +The contract descriptor source file depends on `contractpointerdata.c` which is a source file that contains +the definitions of the "indirect pointer data" that is referenced by the data descriptor. This is typically the addresses of important global variables in the runtime. +Constants and build flags are embedded directly in the JSON payload. + +Multiple data descriptor source files may be specified (for example if they are produced by different components of the runtime, or by different source languages). The final JSON payload will be a composition of all the data descriptors. + +Multiple contracts text files may be specified. This may be useful if some contracts are conditionally included (for example if they are platform-specific). The final JSON payload will be a composition of all the contracts files. + +In the C/C++ data descriptor, we use a single header file `datadescriptor.h` together with the C preprocessor to produce `datadescriptor.c` and `contractpointerdata.c`. +This is an implementation detail. For data structures defined in other languages, other tools can be used to produce the object file and indirect pointer data. + +```mermaid +flowchart TB + headers("runtime headers") + data_header("datadescriptor.h") + data_src("datadescriptor.c") + compile_data["clang"] + data_obj("datadescriptor.o") + contracts("contracts.txt") + globals("contractpointerdata.c") + build[["cdac-build-tool"]] + descriptor_src("contractdescriptor.c") + vm("runtime sources") + compile_runtime["clang"] + runtime_lib(["libcoreclr.so"]) + + headers -.-> data_src + headers ~~~ data_header + data_header -.-> data_src + headers -.-> globals + headers -.-> vm + data_src --> compile_data --> data_obj --> build + contracts ---> build + build --> descriptor_src + descriptor_src --> compile_runtime + data_header -.-> globals ----> compile_runtime + vm ----> compile_runtime --> runtime_lib +``` + + +## Specifying data descriptors + +The sample in the `sample` dir uses the following syntax (see [sample/sample.data.h](sample/sample.data.h)) to specify the data descriptor: + +```c +CDAC_BASELINE("empty") +CDAC_TYPES_BEGIN() + +CDAC_TYPE_BEGIN(ManagedThread) +CDAC_TYPE_INDETERMINATE(ManagedThread) +CDAC_TYPE_FIELD(ManagedThread, GCHandle, GCHandle, offsetof(ManagedThread,m_gcHandle)) +CDAC_TYPE_FIELD(ManagedThread, pointer, Next, offsetof(ManagedThread,m_next)) +CDAC_TYPE_END(ManagedThread) + +CDAC_TYPE_BEGIN(GCHandle) +CDAC_TYPE_SIZE(sizeof(intptr_t)) +CDAC_TYPE_END(GCHandle) + +CDAC_TYPES_END() + +CDAC_GLOBALS_BEGIN() +CDAC_GLOBAL_POINTER(ManagedThreadStore, &g_managedThreadStore) +#if FEATURE_EH_FUNCLETS +CDAC_GLOBAL(FeatureEHFunclets, uint8, 1) +#else +CDAC_GLOBAL(FeatureEHFunclets, uint8, 0) +#endif +CDAC_GLOBAL(SomeMagicNumber, uint32, 42) +CDAC_GLOBALS_END() +``` + +The file is included multiple times with the macros variously defined in order to generate the +data descriptor blob. + +## Implementation Details + +See [data-descriptor-blob.md](./data-descriptor-blob.md) + +## Workflow + +### Porting and extending the data blob scraper + +When porting to a new architecture, or extending the blob contents, it is recommended to +first work with the sample blob, rather than the full CoreCLR descriptor. + +For example, if your target platform has a clang toolchain, something like this will provide a suitable +input for `cdac-build-tool`: + +```console +$ clang -target wasm32-unknown-unknown -c -o /tmp/sample.o src/coreclr/tools/cdac-build-tool/sample/sample.blob.c +``` + +If you are modifying the preprocessor macros, using `-E` to emit the preprocessed output is helpful as well. + +```console +$ clang -target x86_64-unknown-linux-gnu -E -o /tmp/sample.i .src/coreclr/tools/cdac-build-tool/sample/sample.blob.c +``` + +Running the `cdac-build-tool` with the `-v` verbose option will show progress + +```console +$ ./dotnet.sh run --project src/coreclr/tools/cdac-build-tool/cdac-build-tool.csproj -- compose -v -o /tmp/contract.c /tmp/sample.o +``` + +It is also helpful to run the `cdac-build-tool` under a debugger with a breakpoint in `ObjectFileScraper.ScrapeInput` + +**Release runtime builds** When building Release builds of the runtime, the build infrastructure +may turn on whole program optimizations. On some toolchains this may produce object files that +are a serialization of the internal compiler state, rather than a native object format. This may break +assumptions of the `cdac-build-tool` about global symbol initialization, for example constants and string literals might not be stored as binary integers or as byte sequences. In such cases, it may be +necessary to turn off global optimizations when compiling `datadescriptor.cpp`. This is okay to do because `datadescriptor.cpp` is not shipped as part of the runtime build - and in fact it has no executable functions at all. It is just used to gather type layout and size information. + +It is conceivable that some future C/C++ compiler with whole program optimizations turned on may remove unused struct fields. (Such that separately compiling `datadescriptor.cpp` would produce incorrect offsets). In that case, `cdac-build-tool` will need to use another technique to collect offsets for a runtime built with such a compiler. As of 2024, no compilers do this, however. diff --git a/src/coreclr/tools/cdac-build-tool/Resources/contract-descriptor.c.in b/src/coreclr/tools/cdac-build-tool/Resources/contract-descriptor.c.in new file mode 100644 index 000000000000..c1f0edd7a66f --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/Resources/contract-descriptor.c.in @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include + +#ifdef _MSC_VER +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT __attribute__((visibility("default"))) +#endif + +struct DotNetRuntimeContractDescriptor +{ + uint64_t magic; + uint32_t flags; + const uint32_t descriptor_size; + const char *descriptor; + const uint32_t pointer_data_count; + uint32_t pad0; + const uintptr_t *pointer_data; +}; + +extern const uintptr_t contractDescriptorPointerData[]; + +DLLEXPORT struct DotNetRuntimeContractDescriptor DotNetRuntimeContractDescriptor; + +DLLEXPORT struct DotNetRuntimeContractDescriptor DotNetRuntimeContractDescriptor = { + .magic = 0x0043414443434e44ull, // "DNCCDAC\0" + .flags = %%platformFlags%%, + .descriptor_size = %%jsonDescriptorSize%%, + .descriptor = "%%jsonDescriptor%%", + .pointer_data_count = %%pointerDataCount%%, + .pointer_data = &contractDescriptorPointerData[0], +}; diff --git a/src/coreclr/tools/cdac-build-tool/cdac-build-tool.csproj b/src/coreclr/tools/cdac-build-tool/cdac-build-tool.csproj new file mode 100644 index 000000000000..427a1eb4e9c9 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/cdac-build-tool.csproj @@ -0,0 +1,32 @@ + + + + cdac-build-tool + Exe + enable + AnyCPU + $(NetCoreAppToolCurrent) + true + $(RuntimeBinDir)/cdac-build-tool + true + false + false + false + .NET runtime data contract build tool + Microsoft.DotNet.Diagnostics.DataContract + + + + + + + + Microsoft.DotNet.Diagnostics.DataContract.Baseline: + + + + + + + + diff --git a/src/coreclr/tools/cdac-build-tool/data-descriptor-blob.md b/src/coreclr/tools/cdac-build-tool/data-descriptor-blob.md new file mode 100644 index 000000000000..b7321edd12c9 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/data-descriptor-blob.md @@ -0,0 +1,203 @@ +## On-disk target object binary blob descriptor + +### Summary + +This is an internal implemetnation detail allowing tooling to read target architecture structure sizes and offsets without understanding target architecture object formats. + +### Design requirements + +The design of the physical binary blob descriptor is constrained by the following requirements: +* The binary blob should be easy to process by examining an object file on disk - even if the object + file is for a foreign architecture/OS. It should be possible to read the binary blob purely by + looking at the bytes. Tooling should be able to analyze the blob without having to understand + relocation entries, dwarf debug info, symbols etc. +* It should be possible to produce the blob using the native C/C++/NativeAOT compiler for a given + target/architecture. In particular for a runtime written in C, the binary blob should be + constructible using C idioms. If the C compiler needs to pad or align the data, the blob format + should provide a way to iterate the blob contents without having to know anything about the target + platform ABI or C compiler conventions. +* It should be possible to create separate subsets of the physical descriptor (in the target runtime + object format) using separate toolchains (for example: in NativeAOT some of the struct layouts may + be described by the NativeAOT compiler, while some might be described by the C/C++ toolchain) and + to run a build host (not target architecture) tool to read and compose them into a single physical + binary blob before embedding it into the final NativeAOT runtime binary. + +This leads to the following overall strategy for the design: +* The physical blob is "self-contained": indirections are encoded as offsets from the beginning of + the blob (or other base offsets), whereas using pointers would mean that the encoding of the blob + would have relocations applied to it, which would preclude reading the blob out of of an object + file without understanding the object file format. +* The physical blob must be "self-describing": If the C compiler adds padding or alignment, the blob + descriptor must contain information for how to skip the padding/alignment data. +* The physical blob must be constructible using "lowest common denominator" target toolchain + tooling - the C preprocessor. That doesn't mean that tooling _must_ use the C preprocessor to + generate the blob, but the format must not exceed the capabilities of the C preprocessor. + + +### Blob + +Multi-byte values are in the target platform endianness. + +The blob's job is to encode descriptions of the .NET runtime's implementation types and their fields, +as well as globals. + +When encoding strings, we create a "string pool" in the data blob: a massive string literal +that concatentates all the names that we might need, separated by `"\0"` nul characters. To encode a name into another data structure, we write the offset of the name from the beginning of the string pool. We reserve the offset 0 to designate empty or invalid names. + +When encoding the fields of a type, we create a "field pool" in the data blob: a collection of field +descriptors delimited by an "empty field descriptor" (a field descriptor of a name index of 0). All +the fields for a single type are encoded as a contiguous run from a given field pool index until the next empty field descriptor. + +We're interested in encoding the following kinds of information: + +```c +// A type: +// We encode a data contract name and a collection of fields, and the size of the type. +struct TypeSpec +{ + uint32_t Name; + uint32_t Fields; + uint16_t Size; +}; + +// A field: +// We encode the field name, the type (or an empty name) and the offset of the field in the native +// struct. The size of the field is not part of the data descriptor. +struct FieldSpec +{ + uint32_t Name; + uint32_t TypeName; + uint16_t FieldOffset; +}; + +// A literal global value such as a constant, some flags bitmap, or the value of a preprocessor define: +// we record the name, an optional type name, and a value as an unsigned 64-bit value +struct GlobalLiteralSpec +{ + uint32_t Name; + uint32_t TypeName; + uint64_t Value; +}; + +// A global pointer value such as the addrress of some important datastructure: +// We record the name and the index of the global in the auxiliarly "pointer data" global which +// is compiled into the .NET runtime and contains the addresses of all the globals that are referenced +// from the data descriptor. +struct GlobalPointerSpec +{ + uint32_t Name; + uint32_t PointerDataIndex; +}; +``` + +The main data we want to emit to the object file is an instance of the following structure: + +```c +// The main payload of the object file. +struct BinaryBlobDataDescriptor +{ + // A directory giving the offsets of all the other content, + // the number of types, fields, global literals and pointers, and + // the sizes of the "Spec" structs, above, in order to account for any padding added + // by the C/C++ compiler. + struct Directory { + uint32_t FlagsAndBaselineStart; + uint32_t TypesStart; + + uint32_t FieldPoolStart; + uint32_t GlobalLiteralValuesStart; + + uint32_t GlobalPointersStart; + uint32_t NamesStart; + + uint32_t TypeCount; + uint32_t FieldPoolCount; + + uint32_t GlobalLiteralValuesCount; + uint32_t GlobalPointerValuesCount; + + uint32_t NamesPoolCount; + + uint8_t TypeSpecSize; + uint8_t FieldSpecSize; + uint8_t GlobalLiteralSpecSize; + uint8_t GlobalPointerSpecSize; + } Directory; + // Platform flags (primarily pointer size) + uint32_t PlatformFlags; + // a well-known name of the baseline data descriptor. the current descriptor + // records changes from this baseline. + uint32_t BaselineName; + // an array of type specs + struct TypeSpec Types[CDacBlobTypesCount]; + // all of the field specs - contiguous runs are all owned by the same type + struct FieldSpec FieldPool[CDacBlobFieldPoolCount]; + // an array of literal globals + struct GlobalLiteralSpec GlobalLiteralValues[CDacBlobGlobalLiteralsCount]; + // an array of pointer globals + struct GlobalPointerSpec GlobalPointerValues[CDacBlobGlobalPointersCount]; + // all of the names that might be referenced from elsewhere in BinaryBlobDataDescriptor, + // delimited by "\0" + uint8_t NamesPool[sizeof(struct CDacStringPoolSizes)]; + // an end magic value to validate that the name pool is of the expected length + uint8_t EndMagic[4]; // the bytes 0x01 0x02 0x03 0x04 +}; +``` + +Finally, the value that we write to the object file has this form: + +```c +struct MagicAndBlob { + // the magic value that we look for in the object file + // 0x00424F4C42434144ull - in little endian this is "DACBLOB\0" + uint64_t magic; + // the blob payload, described above + struct BinaryBlobDataDescriptor Blob; +}; +``` + +The `BinaryBlobDataDescriptor` begins with a directory that gives the relative offsets of the `PlatformFlags`, `Types`, `FieldPool`, +`GlobalLiteralValues`, `GlobalPointerValues` and `Names` fields of the blob. The number of elements of each of the arrays is +next. This is followed by the sizes of the spec structs. + +Rationale: If a `BinaryBlobDataDescriptor` is created via C macros, we want to embed the `offsetof` +and `sizeof` of the components of the blob into the blob itself without having to account for any +padding that the C compiler may introduce to enforce alignment. Additionally the `Directory` tries +to follow a common C alignment rule (we don't want padding introduced in the directory itself): +N-byte members are aligned to start on N-byte boundaries. + +The baseline is specified as an offset into the names pool. + +The types are given as an array of `TypeSpec` elements. Each one contains an offset into the +`NamesPool` giving the name of the type, An offset into the fields pool indicating the first +specified field of the type, and the size of the type in bytes or 0 if it is indeterminate. + +The fields pool is given as a sequence of `FieldSpec` elements. The fields for each type are given +in a contiguous subsequence and are terminated by a marker `FieldSpec` with a `Name` offset of 0. +(Thus if a type has an empty sequence of fields it just points to a marker field spec directly.) +For each field there is a name that gives an offset in the name pool and an offset indicating the +field's offset. + +The global constants are given as a sequence of `GlobalLiteralSpec` elements. Each global has a +name, type and a value. Globals that are the addresses in target memory, are in `GlobalPointerSpec` +elements. Each pointer element has a name and an index in a separately compiled pointer structure +that is linked into runtime . See +[contract-descriptor.md](/docs/design/datacontracts/contract-descriptor.md) + +The `NamesPool` is a single sequence of utf-8 bytes comprising the concatenation of all the type +field and global names including a terminating nul byte for each name. The same name may occur +multiple times. The names could be referenced by multiple type or multiple fields. (That is, a +clever blob emitter may pool strings). The first name in the name pool is the empty string (with +its nul byte). + +Rationale: we want to reserve the offset 0 as a marker. + +Names are referenced by giving their offset from the beginning of the `NamesPool`. Each name +extends until the first nul byte encountered at or past the beginning of the name. + + +## Example + +An example C header describing some data types is given in [sample.data.h](./sample/sample.data.h). And +example series of C macro preprocessor definitions that produces a constant blob `Blob` is given in +[sample.blob.c](./sample/sample.blob.c) diff --git a/src/coreclr/tools/cdac-build-tool/sample/sample.blob.c b/src/coreclr/tools/cdac-build-tool/sample/sample.blob.c new file mode 100644 index 000000000000..b90b7eca0e93 --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/sample/sample.blob.c @@ -0,0 +1,553 @@ +#include +#include + +// example structures + +typedef struct ManagedThread ManagedThread; + +struct ManagedThread { + uint32_t garbage0; + uint32_t m_gcHandle; + uint32_t garbage1; + ManagedThread *m_next; +}; + +typedef struct ManagedThreadStore { + ManagedThread *threads; +} ManagedThreadStore; + +static ManagedThreadStore g_managedThreadStore; + +// end example structures + +// begin blob definition + +struct TypeSpec +{ + uint32_t Name; + uint32_t Fields; + uint16_t Size; +}; + +struct FieldSpec +{ + uint32_t Name; + uint32_t TypeName; + uint16_t FieldOffset; +}; + +struct GlobalLiteralSpec +{ + uint32_t Name; + uint32_t TypeName; + uint64_t Value; +}; + +struct GlobalPointerSpec +{ + uint32_t Name; + uint32_t AuxIndex; +}; + +#define CONCAT(token1,token2) token1 ## token2 +#define CONCAT4(token1, token2, token3, token4) token1 ## token2 ## token3 ## token4 + +#define MAKE_TYPELEN_NAME(tyname) CONCAT(cdac_string_pool_typename__, tyname) +#define MAKE_FIELDLEN_NAME(tyname,membername) CONCAT4(cdac_string_pool_membername__, tyname, __, membername) +#define MAKE_FIELDTYPELEN_NAME(tyname,membername) CONCAT4(cdac_string_pool_membertypename__, tyname, __, membername) +#define MAKE_GLOBALLEN_NAME(globalname) CONCAT(cdac_string_pool_globalname__, globalname) +#define MAKE_GLOBALTYPELEN_NAME(globalname) CONCAT(cdac_string_pool_globaltypename__, globalname) + +// define a struct where the size of each field is the length of some string. we will use offsetof to get +// the offset of each struct element, which will be equal to the offset of the beginning of that string in the +// string pool. +struct CDacStringPoolSizes +{ + char cdac_string_pool_nil; // make the first real string start at offset 1 +#define DECL_LEN(membername,len) char membername[(len)]; +#define CDAC_BASELINE(name) DECL_LEN(cdac_string_pool_baseline_, (sizeof(name))) +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) DECL_LEN(MAKE_TYPELEN_NAME(name), sizeof(#name)) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) DECL_LEN(MAKE_FIELDLEN_NAME(tyname,membername), sizeof(#membername)) \ + DECL_LEN(MAKE_FIELDTYPELEN_NAME(tyname,membername), sizeof(#membertyname)) +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name)) +#define CDAC_GLOBAL(name,tyname,value) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name)) \ + DECL_LEN(MAKE_GLOBALTYPELEN_NAME(name), sizeof(#tyname)) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END +}; + +#define GET_TYPE_NAME(name) offsetof(struct CDacStringPoolSizes, MAKE_TYPELEN_NAME(name)) +#define GET_FIELD_NAME(tyname,membername) offsetof(struct CDacStringPoolSizes, MAKE_FIELDLEN_NAME(tyname,membername)) +#define GET_FIELDTYPE_NAME(tyname,membername) offsetof(struct CDacStringPoolSizes, MAKE_FIELDTYPELEN_NAME(tyname,membername)) +#define GET_GLOBAL_NAME(globalname) offsetof(struct CDacStringPoolSizes, MAKE_GLOBALLEN_NAME(globalname)) +#define GET_GLOBALTYPE_NAME(globalname) offsetof(struct CDacStringPoolSizes, MAKE_GLOBALTYPELEN_NAME(globalname)) + +// count the types +enum +{ + CDacBlobTypesCount = +#define CDAC_BASELINE(name) 0 +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) + 1 +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + , +}; + +// count the field pool size. +// there's 1 placeholder element at the start, and 1 endmarker after each type +enum +{ + CDacBlobFieldsPoolCount = +#define CDAC_BASELINE(name) 1 +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) + 1 +#define CDAC_TYPE_END(name) + 1 +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + , +}; + +// count the literal globals +enum +{ + CDacBlobGlobalLiteralsCount = +#define CDAC_BASELINE(name) 0 +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) +#define CDAC_GLOBAL(name,tyname,value) + 1 +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + , +}; + +// count the aux vector globals +enum +{ + CDacBlobGlobalPointersCount = +#define CDAC_BASELINE(name) 0 +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) + 1 +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + , +}; + + +#define MAKE_TYPEFIELDS_TYNAME(tyname) CONCAT(CDacFieldsPoolTypeStart__, tyname) + +// index of each run of fields. +// we make a struct containing one 1-byte field for each field in the run, and then take the offset of the +// struct to get the index of the run of fields. +// this looks like +// +// struct CDacFieldsPoolSizes { +// char cdac_field_pool_start_placeholder__; +// struct CDacFieldsPoolTypeStart__MethodTable { +// char cdac_fields_pool_member__MethodTable__GCHandle; +// char cdac_fields_pool_member__MethodTable_endmarker; +// } CDacFieldsPoolTypeStart__MethodTable; +// ... +// }; +// +// so that offsetof(struct CDacFieldsPoolSizes, CDacFieldsPoolTypeStart__MethodTable) will give the offset of the +// method table field descriptors in the run of fields +struct CDacFieldsPoolSizes +{ +#define DECL_LEN(membername) char membername; +#define CDAC_BASELINE(name) DECL_LEN(cdac_fields_pool_start_placeholder__) +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) struct MAKE_TYPEFIELDS_TYNAME(name) { +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) DECL_LEN(CONCAT4(cdac_fields_pool_member__, tyname, __, membername)) +#define CDAC_TYPE_END(name) DECL_LEN(CONCAT4(cdac_fields_pool_member__, tyname, _, endmarker)) \ + } MAKE_TYPEFIELDS_TYNAME(name); +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END +#undef DECL_LEN +}; + +#define GET_TYPE_FIELDS(tyname) offsetof(struct CDacFieldsPoolSizes, MAKE_TYPEFIELDS_TYNAME(tyname)) + +// index of each global pointer +// +// struct CDacGlobalPointerIndex +// { +// char placeholder; +// char firstGlobalPointerName; +// char secondGlobalPointerName; +// ... +//} +// +// offsetof (CDACGlobalPointerIndex, NAME) returns the index of the global +struct CDacGlobalPointerIndex +{ +#define DECL_LEN(membername) char membername; +#define CDAC_BASELINE(name) DECL_LEN(cdac_global_pointer_index_start_placeholder__) +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) DECL_LEN(CONCAT(cdac_global_pointer_index__, name)) +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END +}; + +#define GET_GLOBAL_POINTER_INDEX(name) offsetof(struct CDacGlobalPointerIndex, CONCAT(cdac_global_pointer_index__, name)) + +struct BinaryBlobDataDescriptor +{ + // see data-descriptor-blob.md + struct Directory { + uint32_t FlagsAndBaselineStart; + uint32_t TypesStart; + + uint32_t FieldsPoolStart; + uint32_t GlobalLiteralValuesStart; + + uint32_t GlobalPointersStart; + uint32_t NamesPoolStart; + + uint32_t TypeCount; + uint32_t FieldsPoolCount; + + uint32_t GlobalLiteralValuesCount; + uint32_t GlobalPointerValuesCount; + + uint32_t NamesPoolCount; + + uint8_t TypeSpecSize; + uint8_t FieldSpecSize; + uint8_t GlobalLiteralSpecSize; + uint8_t GlobalPointerSpecSize; + } Directory; + uint32_t PlatformFlags; + uint32_t BaselineName; + struct TypeSpec Types[CDacBlobTypesCount]; + struct FieldSpec FieldsPool[CDacBlobFieldsPoolCount]; + struct GlobalLiteralSpec GlobalLiteralValues[CDacBlobGlobalLiteralsCount]; + struct GlobalPointerSpec GlobalPointerValues[CDacBlobGlobalPointersCount]; + uint8_t NamesPool[sizeof(struct CDacStringPoolSizes)]; + uint8_t EndMagic[4]; +}; + +struct MagicAndBlob { + uint64_t magic; + struct BinaryBlobDataDescriptor Blob; +}; + +const struct MagicAndBlob Blob = { + .magic = 0x00424F4C42434144ull,// "DACBLOB", + .Blob = { + .Directory = { + .FlagsAndBaselineStart = offsetof(struct BinaryBlobDataDescriptor, PlatformFlags), + .TypesStart = offsetof(struct BinaryBlobDataDescriptor, Types), + .FieldsPoolStart = offsetof(struct BinaryBlobDataDescriptor, FieldsPool), + .GlobalLiteralValuesStart = offsetof(struct BinaryBlobDataDescriptor, GlobalLiteralValues), + .GlobalPointersStart = offsetof(struct BinaryBlobDataDescriptor, GlobalPointerValues), + .NamesPoolStart = offsetof(struct BinaryBlobDataDescriptor, NamesPool), + .TypeCount = CDacBlobTypesCount, + .FieldsPoolCount = CDacBlobFieldsPoolCount, + .GlobalLiteralValuesCount = CDacBlobGlobalLiteralsCount, + .GlobalPointerValuesCount = CDacBlobGlobalPointersCount, + .NamesPoolCount = sizeof(struct CDacStringPoolSizes), + .TypeSpecSize = sizeof(struct TypeSpec), + .FieldSpecSize = sizeof(struct FieldSpec), + .GlobalLiteralSpecSize = sizeof(struct GlobalLiteralSpec), + .GlobalPointerSpecSize = sizeof(struct GlobalPointerSpec), + }, + .EndMagic = { 0x01, 0x02, 0x03, 0x04 }, + .PlatformFlags = 0x01 | (sizeof(void*) == 4 ? 0x02 : 0), + .BaselineName = offsetof(struct CDacStringPoolSizes, cdac_string_pool_baseline_), + + .NamesPool = ("\0" // starts with a nul +#define CDAC_BASELINE(name) name "\0" +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) #name "\0" +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) #membername "\0" #membertyname "\0" +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) #name "\0" +#define CDAC_GLOBAL(name,tyname,value) #name "\0" #tyname "\0" +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + ), + + .FieldsPool = { +#define CDAC_BASELINE(name) {0,}, +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) { \ + .Name = GET_FIELD_NAME(tyname,membername), \ + .TypeName = GET_FIELDTYPE_NAME(tyname,membername), \ + .FieldOffset = offset, \ +}, +#define CDAC_TYPE_END(name) { 0, }, +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + }, + + .Types = { +#define CDAC_BASELINE(name) +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) { \ + .Name = GET_TYPE_NAME(name), \ + .Fields = GET_TYPE_FIELDS(name), +#define CDAC_TYPE_INDETERMINATE(name) .Size = 0, +#define CDAC_TYPE_SIZE(size) .Size = size, +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) +#define CDAC_TYPE_END(name) }, +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + }, + + .GlobalLiteralValues = { +#define CDAC_BASELINE(name) +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) +#define CDAC_GLOBAL(name,tyname,value) { .Name = GET_GLOBAL_NAME(name), .TypeName = GET_GLOBALTYPE_NAME(name), .Value = value }, +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + }, + + .GlobalPointerValues = { +#define CDAC_BASELINE(name) +#define CDAC_TYPES_BEGIN() +#define CDAC_TYPE_BEGIN(name) +#define CDAC_TYPE_INDETERMINATE(name) +#define CDAC_TYPE_SIZE(size) +#define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) +#define CDAC_TYPE_END(name) +#define CDAC_TYPES_END() +#define CDAC_GLOBALS_BEGIN() +#define CDAC_GLOBAL_POINTER(name,value) { .Name = GET_GLOBAL_NAME(name), .AuxIndex = GET_GLOBAL_POINTER_INDEX(name) }, +#define CDAC_GLOBAL(name,tyname,value) +#define CDAC_GLOBALS_END() +#include "sample.data.h" +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPES_END +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef DECL_LEN +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL +#undef CDAC_GLOBALS_END + }, + } +}; + +// end blob definition diff --git a/src/coreclr/tools/cdac-build-tool/sample/sample.data.h b/src/coreclr/tools/cdac-build-tool/sample/sample.data.h new file mode 100644 index 000000000000..e4b8bff98b5e --- /dev/null +++ b/src/coreclr/tools/cdac-build-tool/sample/sample.data.h @@ -0,0 +1,24 @@ +CDAC_BASELINE("empty") +CDAC_TYPES_BEGIN() + +CDAC_TYPE_BEGIN(ManagedThread) +CDAC_TYPE_INDETERMINATE(ManagedThread) +CDAC_TYPE_FIELD(ManagedThread, GCHandle, GCHandle, offsetof(ManagedThread,m_gcHandle)) +CDAC_TYPE_FIELD(ManagedThread, pointer, Next, offsetof(ManagedThread,m_next)) +CDAC_TYPE_END(ManagedThread) + +CDAC_TYPE_BEGIN(GCHandle) +CDAC_TYPE_SIZE(sizeof(intptr_t)) +CDAC_TYPE_END(GCHandle) + +CDAC_TYPES_END() + +CDAC_GLOBALS_BEGIN() +CDAC_GLOBAL_POINTER(ManagedThreadStore, &g_managedThreadStore) +#if FEATURE_EH_FUNCLETS +CDAC_GLOBAL(FeatureEHFunclets, uint8, 1) +#else +CDAC_GLOBAL(FeatureEHFunclets, uint8, 0) +#endif +CDAC_GLOBAL(SomeMagicNumber, uint32, 42) +CDAC_GLOBALS_END() diff --git a/src/coreclr/tools/dotnet-pgo/MibcEmitter.cs b/src/coreclr/tools/dotnet-pgo/MibcEmitter.cs index 8491a25991c0..2379a45e31f3 100644 --- a/src/coreclr/tools/dotnet-pgo/MibcEmitter.cs +++ b/src/coreclr/tools/dotnet-pgo/MibcEmitter.cs @@ -244,7 +244,7 @@ public static void GenerateConfigData(MibcConfig config, TypeSystemMetadataEmitt public static int GenerateMibcFile(MibcConfig config, TypeSystemContext tsc, FileInfo outputFileName, IEnumerable methodsToAttemptToPlaceIntoProfileData, bool validate, bool uncompressed) { - TypeSystemMetadataEmitter emitter = new TypeSystemMetadataEmitter(new AssemblyName(outputFileName.Name), tsc); + TypeSystemMetadataEmitter emitter = new TypeSystemMetadataEmitter(new AssemblyNameInfo(outputFileName.Name), tsc); emitter.InjectSystemPrivateCanon(); emitter.AllowUseOfAddGlobalMethod(); diff --git a/src/coreclr/tools/dotnet-pgo/PgoRootCommand.cs b/src/coreclr/tools/dotnet-pgo/PgoRootCommand.cs index bf674406e123..f7a7b7edd66c 100644 --- a/src/coreclr/tools/dotnet-pgo/PgoRootCommand.cs +++ b/src/coreclr/tools/dotnet-pgo/PgoRootCommand.cs @@ -9,7 +9,7 @@ using System.CommandLine.Parsing; using System.Diagnostics; using System.IO; -using System.Reflection; +using System.Reflection.Metadata; namespace Microsoft.Diagnostics.Tools.Pgo { @@ -61,7 +61,7 @@ internal sealed class PgoRootCommand : CliRootCommand new("--dump-worst-overlap-graphs-to") { Description = "Number of graphs to dump to .dot format in dump-worst-overlap-graphs-to directory" }; public CliOption AutomaticReferences { get; } = new("--automatic-references") { DefaultValueFactory = _ => true, Description = "Attempt to find references by using paths embedded in the trace file. Defaults to true" }; - public CliOption IncludedAssemblies { get; } = + public CliOption IncludedAssemblies { get; } = new("--include-reference") { CustomParser = MakeAssemblyNameArray, DefaultValueFactory = MakeAssemblyNameArray, Description = "If specified, include in Mibc file only references to the specified assemblies. Assemblies are specified as assembly names, not filenames. For instance, `System.Private.CoreLib` not `System.Private.CoreLib.dll`. Multiple --include-reference options may be specified." }; private CliOption _includeReadyToRun { get; } = @@ -285,16 +285,16 @@ public static IEnumerable> GetExtendedHelp(HelpContext c } } - private static AssemblyName[] MakeAssemblyNameArray(ArgumentResult result) + private static AssemblyNameInfo[] MakeAssemblyNameArray(ArgumentResult result) { if (result.Tokens.Count > 0) { - var includedAssemblies = new List(); + var includedAssemblies = new List(); foreach (CliToken token in result.Tokens) { try { - includedAssemblies.Add(new AssemblyName(token.Value)); + includedAssemblies.Add(new AssemblyNameInfo(token.Value)); } catch { @@ -304,7 +304,7 @@ private static AssemblyName[] MakeAssemblyNameArray(ArgumentResult result) return includedAssemblies.ToArray(); } - return Array.Empty(); + return Array.Empty(); } } } diff --git a/src/coreclr/tools/dotnet-pgo/Program.cs b/src/coreclr/tools/dotnet-pgo/Program.cs index e5ce52f1b995..af0765d4c0ac 100644 --- a/src/coreclr/tools/dotnet-pgo/Program.cs +++ b/src/coreclr/tools/dotnet-pgo/Program.cs @@ -414,7 +414,7 @@ private int InnerMergeMain() } HashSet assemblyNamesInBubble = null; - AssemblyName[] assemblies = Get(_command.IncludedAssemblies); + AssemblyNameInfo[] assemblies = Get(_command.IncludedAssemblies); if (assemblies.Length > 0) { assemblyNamesInBubble = new HashSet(); diff --git a/src/coreclr/tools/dotnet-pgo/TraceRuntimeDescToTypeSystemDesc.cs b/src/coreclr/tools/dotnet-pgo/TraceRuntimeDescToTypeSystemDesc.cs index 8ed1857045d0..380aa017d9a7 100644 --- a/src/coreclr/tools/dotnet-pgo/TraceRuntimeDescToTypeSystemDesc.cs +++ b/src/coreclr/tools/dotnet-pgo/TraceRuntimeDescToTypeSystemDesc.cs @@ -291,7 +291,7 @@ public ModuleDesc ResolveModuleID(long handle, bool throwIfNotFound = true) return null; } - minfo.Module = _context.ResolveAssembly(new AssemblyName(minfo.AssemblyName), throwIfNotFound); + minfo.Module = _context.ResolveAssembly(new AssemblyNameInfo(minfo.AssemblyName), throwIfNotFound); return minfo.Module; } else diff --git a/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs b/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs index 3e0948c9392a..33e11d92d023 100644 --- a/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs +++ b/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs @@ -95,7 +95,7 @@ protected override ModuleData CreateValueFromKey(EcmaModule key) private readonly Dictionary _simpleNameHashtable = new Dictionary(StringComparer.OrdinalIgnoreCase); - public override ModuleDesc ResolveAssembly(System.Reflection.AssemblyName name, bool throwIfNotFound) + public override ModuleDesc ResolveAssembly(AssemblyNameInfo name, bool throwIfNotFound) { // TODO: catch typesystem BadImageFormatException and throw a new one that also captures the // assembly name that caused the failure. (Along with the reason, which makes this rather annoying). diff --git a/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemContext.cs b/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemContext.cs index 31a5caee14c2..6c496e90d684 100644 --- a/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemContext.cs +++ b/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemContext.cs @@ -42,7 +42,7 @@ public TypeRefTypeSystemContext(IEnumerable refReaders) { _refReaders = refReaders.ToArray(); - TypeRefTypeSystemModule coreLibModule = new TypeRefTypeSystemModule(this, new System.Reflection.AssemblyName("System.Private.CoreLib")); + TypeRefTypeSystemModule coreLibModule = new TypeRefTypeSystemModule(this, new AssemblyNameInfo("System.Private.CoreLib")); foreach (string name in MetadataTypeSystemContext.WellKnownTypeNames) { coreLibModule.GetOrAddType("System", name); @@ -198,7 +198,7 @@ private TypeRefTypeSystemType ResolveTypeRef(PEInfo peInfo, TypeReferenceHandle string assemblyName = peInfo.reader.GetString(assemblyReference.Name); if (!_typeRefModules.TryGetValue(assemblyName, out module)) { - module = new TypeRefTypeSystemModule(this, new System.Reflection.AssemblyName(assemblyName)); + module = new TypeRefTypeSystemModule(this, new AssemblyNameInfo(assemblyName)); _typeRefModules.Add(module.Assembly.GetName().Name, module); } peInfo.assemblyLookup.Add(asmRefHandle, module); @@ -219,7 +219,7 @@ private TypeRefTypeSystemType ResolveTypeRef(PEInfo peInfo, TypeReferenceHandle return type; } - public override ModuleDesc ResolveAssembly(AssemblyName name, bool throwIfNotFound = true) + public override ModuleDesc ResolveAssembly(AssemblyNameInfo name, bool throwIfNotFound = true) { if (_typeRefModules.TryGetValue(name.Name, out TypeRefTypeSystemModule foundModule)) { diff --git a/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemModule.cs b/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemModule.cs index 701263024246..0b3b788c49c4 100644 --- a/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemModule.cs +++ b/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemModule.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; +using System.Reflection.Metadata; using System.Text; using System.Threading.Tasks; using Internal.TypeSystem; @@ -13,12 +13,12 @@ namespace Microsoft.Diagnostics.Tools.Pgo.TypeRefTypeSystem { class TypeRefTypeSystemModule : ModuleDesc, IAssemblyDesc { - AssemblyName _name; + AssemblyNameInfo _name; List _types = new List(); Dictionary _nonNamespacedTypes = new Dictionary(); Dictionary> _namespacedTypes = new Dictionary>(); - public TypeRefTypeSystemModule(TypeSystemContext tsc, AssemblyName name) : base(tsc, null) + public TypeRefTypeSystemModule(TypeSystemContext tsc, AssemblyNameInfo name) : base(tsc, null) { _name = name; } @@ -51,7 +51,7 @@ public TypeRefTypeSystemType GetOrAddType(string nameSpace, string name) public override IEnumerable GetAllTypes() => _types; public override MetadataType GetGlobalModuleType() => throw new NotImplementedException(); - public AssemblyName GetName() => _name; + public AssemblyNameInfo GetName() => _name; private TypeRefTypeSystemType GetTypeInternal(string nameSpace, string name) { Dictionary nameToTypeDictionary = _nonNamespacedTypes; diff --git a/src/coreclr/tools/metainfo/mdinfo.cpp b/src/coreclr/tools/metainfo/mdinfo.cpp index 84d7f8d50f26..4ac5babae6b0 100644 --- a/src/coreclr/tools/metainfo/mdinfo.cpp +++ b/src/coreclr/tools/metainfo/mdinfo.cpp @@ -1991,7 +1991,7 @@ void MDInfo::DisplayCustomAttributeInfo(mdCustomAttribute inValue, const char *p UINT16 u2 = 0; UINT32 u4 = 0; UINT64 u8 = 0; - unsigned __int64 uI64; + uint64_t uI64; double dblVal; ULONG cbVal; LPCUTF8 pStr; @@ -3012,14 +3012,14 @@ HRESULT _FillVariant( case ELEMENT_TYPE_R4: { V_VT(pvar) = VT_R4; - __int32 Value = GET_UNALIGNED_VAL32(pValue); + int32_t Value = GET_UNALIGNED_VAL32(pValue); V_R4(pvar) = (float &)Value; } break; case ELEMENT_TYPE_R8: { V_VT(pvar) = VT_R8; - __int64 Value = GET_UNALIGNED_VAL64(pValue); + int64_t Value = GET_UNALIGNED_VAL64(pValue); V_R8(pvar) = (double &) Value; } @@ -3947,8 +3947,8 @@ void MDInfo::DumpRaw(int iDump, bool bunused) BYTE m_minor; BYTE m_heaps; // Bits for heap sizes. BYTE m_rid; // log-base-2 of largest rid. - unsigned __int64 m_maskvalid; // Bit mask of present table counts. - unsigned __int64 m_sorted; // Bit mask of sorted tables. }; + uint64_t m_maskvalid; // Bit mask of present table counts. + uint64_t m_sorted; // Bit mask of sorted tables. }; }; const MD *pMd; diff --git a/src/coreclr/tools/r2rdump/CoreDisTools.cs b/src/coreclr/tools/r2rdump/CoreDisTools.cs index 32e88ae8d39d..2eefbdaa4ecd 100644 --- a/src/coreclr/tools/r2rdump/CoreDisTools.cs +++ b/src/coreclr/tools/r2rdump/CoreDisTools.cs @@ -353,12 +353,16 @@ public int GetInstruction(RuntimeFunction rtf, int imageOffset, int rtfOffset, o break; case Machine.LoongArch64: - //TODO-LoongArch64: maybe should add ProbeLoongArch64Quirks. At least it's unused now. + ProbeLoongArch64Quirks(rtf, imageOffset, rtfOffset, ref fixedTranslatedLine); break; case Machine.ArmThumb2: break; + case Machine.RiscV64: + ProbeRiscV64Quirks(rtf, imageOffset, rtfOffset, ref fixedTranslatedLine); + break; + default: break; } @@ -1209,6 +1213,391 @@ private static bool IsAnotherRuntimeFunctionWithinMethod(int rva, RuntimeFunctio return false; } + /// + /// Improves disassembler output for RiscV64 by adding comments at the end of instructions. + /// + /// Runtime function + /// Offset within the image byte array + /// Offset within the runtime function + /// Textual representation of the instruction + private void ProbeRiscV64Quirks(RuntimeFunction rtf, int imageOffset, int rtfOffset, ref string instruction) + { + const int InstructionSize = 4; + uint instr = BitConverter.ToUInt32(_reader.Image, imageOffset + rtfOffset); + + if (IsRiscV64JalrInstruction(instr)) + { + /* + Supported patterns: + auipc + addi + ld + jalr + + auipc + ld + jalr + + auipc + addi + ld + ld + jalr + + Irrelevant instructions for calle address calculations are skiped. + */ + + AnalyzeRiscV64Itype(instr, out uint rd, out uint rs1, out int imm); + uint register = rs1; + int target = imm; + + bool isFound = false; + int currentInstrOffset = rtfOffset - InstructionSize; + int currentPC = rtf.StartAddress + currentInstrOffset; + do + { + instr = BitConverter.ToUInt32(_reader.Image, imageOffset + currentInstrOffset); + + if (IsRiscV64LdInstruction(instr)) + { + AnalyzeRiscV64Itype(instr, out rd, out rs1, out imm); + if (rd == register) + { + target = imm; + register = rs1; + } + } + else if (IsRiscV64AddiInstruction(instr)) + { + AnalyzeRiscV64Itype(instr, out rd, out rs1, out imm); + if (rd == register) + { + target =+ imm; + register = rs1; + } + } + else if (IsRiscV64AuipcInstruction(instr)) + { + AnalyzeRiscV64Utype(instr, out rd, out imm); + if (rd == register) + { + target += currentPC + imm; + isFound = true; + break; + } + } + else + { + // check if callee address is calculated using an unsupported instruction + rd = (instr >> 7) & 0b_11111U; + if (rd == register) + { + break; + } + } + + currentInstrOffset -= InstructionSize; + currentPC -= InstructionSize; + } while (currentInstrOffset > 0); + + if (isFound) + { + if (!TryGetImportCellName(target, out string targetName) || string.IsNullOrWhiteSpace(targetName)) + { + return; + } + + instruction = $"{instruction} // {targetName}"; + } + } + } + + /// + /// Checks if instruction is auipc. + /// + /// Assembly code of instruction + /// It returns true if instruction is auipc. Otherwise false + private bool IsRiscV64AuipcInstruction(uint instruction) + { + const uint OpcodeAuipc = 0b_0010111; + return (instruction & 0x7f) == OpcodeAuipc; + } + + /// + /// Checks if instruction is jalr. + /// + /// Assembly code of instruction + /// It returns true if instruction is jalr. Otherwise false + private bool IsRiscV64JalrInstruction(uint instruction) + { + const uint OpcodeJalr = 0b_1100111; + const uint Funct3Jalr = 0b_000; + return (instruction & 0x7f) == OpcodeJalr && + ((instruction >> 12) & 0b_111) == Funct3Jalr; + } + + /// + /// Checks if instruction is addi. + /// + /// Assembly code of instruction + /// It returns true if instruction is addi. Otherwise false + private bool IsRiscV64AddiInstruction(uint instruction) + { + const uint OpcodeAddi = 0b_0010011; + const uint Funct3Addi = 0b_000; + return (instruction & 0x7f) == OpcodeAddi && + ((instruction >> 12) & 0b_111) == Funct3Addi; + } + + /// + /// Checks if instruction is ld. + /// + /// Assembly code of instruction + /// It returns true if instruction is ld. Otherwise false + private bool IsRiscV64LdInstruction(uint instruction) + { + const uint OpcodeLd = 0b_0000011; + const uint Funct3Ld = 0b_011; + return (instruction & 0x7f) == OpcodeLd && + ((instruction >> 12) & 0b_111) == Funct3Ld; + } + + /// + /// Retrieves output register and immediate value from U-type instruction. + /// + /// Assembly code of instruction + /// Output register + /// Immediate value + private void AnalyzeRiscV64Utype(uint instruction, out uint rd, out int imm) + { + // U-type 31 12 11 7 6 0 + // [ imm ] [ rd ] [ opcode ] + rd = (instruction >> 7) & 0b_11111U; + imm = unchecked((int)(instruction & (0xfffff << 12))); + } + + /// + /// Retrieves output register, resource register and immediate value from U-type instruction. + /// + /// Assembly code of instruction + /// Output register + /// Resource register + /// Immediate value + private void AnalyzeRiscV64Itype(uint instruction, out uint rd, out uint rs1, out int imm) + { + // I-type 31 20 19 15 14 12 11 7 6 0 + // [ imm ] [ rs1 ] [ funct3 ] [ rd ] [ opcode ] + rd = (instruction >> 7) & 0b_11111U; + rs1 = (instruction >> 15) & 0b_11111U; + imm = unchecked((int)instruction) >> 20; + } + + /// + /// Improves disassembler output for LoongArch64. + /// + /// Runtime function + /// Offset within the image byte array + /// Offset within the runtime function + /// Textual representation of the instruction + private void ProbeLoongArch64Quirks(RuntimeFunction rtf, int imageOffset, int rtfOffset, ref string instruction) + { + const int InstructionSize = 4; + uint instr = BitConverter.ToUInt32(_reader.Image, imageOffset + rtfOffset); + + // The list of PC-relative instructions: BCond(BEQ, BNE, BLT[U], BGE[U]), BEQZ, BNEZ, BCEQZ, BCNEZ, B, BL, JIRL. + + // Handle a B, BL, BCond(BEQ, BNE, BLT[U], BGE[U]), BZ(BEQZ, BNEZ, BCEQZ, BCNEZ) instruction + if (IsLoongArch64BCondInstruction(instr, out int offs) || + IsLoongArch64BOrBlInstruction(instr, out offs) || + IsLoongArch64BZInstruction(instr, out offs)) + { + ReplaceRelativeOffset(ref instruction, rtf.StartAddress + rtfOffset + offs, rtf); + } + else if (IsLoongArch64JirlRAInstruction(instr, out uint rj, out int imm)) + { + // Common Pattern: + // pcaddu12i + // ld.d + // jirl ra, rj, 0 + // + // pcaddu12i + // addi.d + // ld.d + // jirl ra, rj, 0 + // There may exist some irrelevant instructions between pcaddu12i and jirl. + // We need to find relevant instructions based on rj to calculate the jump address. + uint register = rj; + int immediate = imm; + bool isFound = false; + int currentInsOffs = rtfOffset - InstructionSize; + int currentPC = rtf.StartAddress + currentInsOffs; + + do + { + instr = BitConverter.ToUInt32(_reader.Image, imageOffset + currentInsOffs); + + if (IsLoongArch64Ld_dOrAddi_dInstruction(instr, out uint rd, out rj, out imm)) + { + if (rd == register) + { + register = rj; + immediate += imm; + } + } + else if (IsLoongArch64Pcaddu12iInstruction(instr, out rd, out imm)) + { + if (rd == register) + { + immediate += currentPC + imm; + isFound = true; + break; + } + } + else + { + // check if target register is using by an unexpected instruction. + rd = (instr & 0x1f); + if ((rd == register) && !IsLoongArch64Fld_dInstruction(instr)) + { + break; + } + } + + currentInsOffs -= InstructionSize; + currentPC -= InstructionSize; + } while (currentInsOffs > 0); + + if (isFound) + { + if (!TryGetImportCellName(immediate, out string targetName) || string.IsNullOrWhiteSpace(targetName)) + { + return; + } + + instruction = $"{instruction} // {targetName}"; + } + } + } + + /// + /// Determine whether a given instruction is a BCond(BEQ, BNE, BLT[U], BGE[U]). + /// + /// Assembly code of instruction + private bool IsLoongArch64BCondInstruction(uint ins, out int offs) + { + uint Opcode = (ins >> 26) & 0x3f; + offs = 0; + if ((Opcode == 0x16) || (Opcode == 0x17) || (Opcode == 0x18) || (Opcode == 0x19) || (Opcode == 0x1a) || (Opcode == 0x1b)) + { + offs = (short)((ins >> 10) & 0xffff); + offs <<= 2; + return true; + } + return false; + } + + /// + /// Determine whether a given instruction is a B or a BL. + /// + /// Assembly code of instruction + private bool IsLoongArch64BOrBlInstruction(uint ins, out int offs) + { + uint Opcode = (ins >> 26) & 0x3f; + offs = 0; + if ((Opcode == 0x14) || (Opcode == 0x15)) + { + offs = (int)(((ins >> 10) & 0xffff) | ((ins & 0x3ff) << 16)) << 6; + offs >>= 4; + return true; + } + return false; + } + + /// + /// Determine whether a given instruction is a BZ(BEQZ, BNEZ, BCEQZ, BCNEZ). + /// + /// Assembly code of instruction + private bool IsLoongArch64BZInstruction(uint ins, out int offs) + { + uint Opcode = (ins >> 26) & 0x3f; + offs = 0; + if ((Opcode == 0x10) || (Opcode == 0x11) || (Opcode == 0x12)) + { + offs = (int)((((ins >> 10) & 0xffff) | ((ins & 0x1f) << 16)) << 11); + offs >>= 9; + return true; + } + return false; + } + + /// + /// Determine whether a given instruction is a JIRL RA. + /// + /// Assembly code of instruction + private bool IsLoongArch64JirlRAInstruction(uint ins, out uint rj, out int offs) + { + rj = 0; + offs = 0; + if ((((ins >> 26) & 0x3f) == 0x13) && ((ins & 0x1f) == 1)) + { + rj = (ins >> 5) & 0x1f; + offs = (short)((ins >> 10) & 0xffff); + offs <<= 2; + return true; + } + return false; + } + + /// + /// Determine whether a given instruction is a PCADDU12I. + /// + /// Assembly code of instruction + private bool IsLoongArch64Pcaddu12iInstruction(uint ins, out uint rd, out int imm) + { + rd = 0; + imm = 0; + if (((ins >> 25) & 0x3f) == 0xe) + { + rd = ins & 0x1f; + imm = (int)((ins >> 5) & 0xfffff) << 12; + return true; + } + return false; + } + + /// + /// Determine whether a given instruction is a LD.D or ADDI.D. + /// + /// Assembly code of instruction + private bool IsLoongArch64Ld_dOrAddi_dInstruction(uint ins, out uint rd, out uint rj, out int imm) + { + imm = 0; + rd = rj = 0; + + if ((((ins >> 22) & 0x3ff) == 0xa3) || (((ins >> 22) & 0x3ff) == 0xb)) + { + rd = ins & 0x1f; + rj = (ins >> 5) & 0x1f; + imm = (int)((ins >> 10) & 0xfff) << 20; + imm >>= 20; + return true; + } + return false; + } + + /// + /// Determine whether a given instruction is a FLD.D. + /// + /// Assembly code of instruction + private bool IsLoongArch64Fld_dInstruction(uint ins) + { + if (((ins >> 22) & 0x3ff) == 0xae) + { + return true; + } + return false; + } + /// /// Determine whether a given character is an ASCII digit. /// diff --git a/src/coreclr/tools/superpmi/mcs/verbtoc.cpp b/src/coreclr/tools/superpmi/mcs/verbtoc.cpp index 7ca9df5c77d9..d2a384388c12 100644 --- a/src/coreclr/tools/superpmi/mcs/verbtoc.cpp +++ b/src/coreclr/tools/superpmi/mcs/verbtoc.cpp @@ -14,7 +14,7 @@ class TOCElementNode TOCElementNode* Next; TOCElement tocElement; - TOCElementNode(int number, __int64 offset) : Next(nullptr), tocElement(number, offset) + TOCElementNode(int number, int64_t offset) : Next(nullptr), tocElement(number, offset) { } }; diff --git a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h index 104a7ae1fabd..7f382f4d967b 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h @@ -172,6 +172,7 @@ struct Agnostic_CORINFO_EE_INFO struct Agnostic_InlinedCallFrameInfo { DWORD size; + DWORD sizeWithSecretStubArg; DWORD offsetOfGSCookie; DWORD offsetOfFrameVptr; DWORD offsetOfFrameLink; @@ -179,6 +180,8 @@ struct Agnostic_CORINFO_EE_INFO DWORD offsetOfCalleeSavedFP; DWORD offsetOfCallTarget; DWORD offsetOfReturnAddress; + DWORD offsetOfSecretStubArg; + DWORD offsetOfSPAfterProlog; } inlinedCallFrameInfo; DWORD offsetOfThreadFrame; DWORD offsetOfGCState; @@ -519,6 +522,7 @@ struct Agnostic_GetPgoInstrumentationResults DWORD dataByteCount; DWORD result; DWORD pgoSource; + DWORD dynamicPgo; }; struct Agnostic_GetProfilingHandle diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index c3445291eeb9..75c1ac1b6f52 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -158,6 +158,7 @@ LWM(PrintMethodName, DWORDLONG, Agnostic_PrintResult) LWM(IsValueClass, DWORDLONG, DWORD) LWM(IsMoreSpecificType, DLDL, DWORD) LWM(IsExactType, DWORDLONG, DWORD) +LWM(IsNullableType, DWORDLONG, DWORD) LWM(IsEnum, DWORDLONG, DLD) LWM(PInvokeMarshalingRequired, MethodOrSigInfoValue, DWORD) LWM(ResolveToken, Agnostic_CORINFO_RESOLVED_TOKENin, ResolveTokenValue) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 7b0ddc8ded5a..0500096cef9d 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -4305,6 +4305,7 @@ void MethodContext::recGetEEInfo(CORINFO_EE_INFO* pEEInfoOut) Agnostic_CORINFO_EE_INFO value; value.inlinedCallFrameInfo.size = (DWORD)pEEInfoOut->inlinedCallFrameInfo.size; + value.inlinedCallFrameInfo.sizeWithSecretStubArg = (DWORD)pEEInfoOut->inlinedCallFrameInfo.sizeWithSecretStubArg; value.inlinedCallFrameInfo.offsetOfGSCookie = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfGSCookie; value.inlinedCallFrameInfo.offsetOfFrameVptr = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameVptr; value.inlinedCallFrameInfo.offsetOfFrameLink = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameLink; @@ -4312,6 +4313,8 @@ void MethodContext::recGetEEInfo(CORINFO_EE_INFO* pEEInfoOut) value.inlinedCallFrameInfo.offsetOfCalleeSavedFP = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfCalleeSavedFP; value.inlinedCallFrameInfo.offsetOfCallTarget = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfCallTarget; value.inlinedCallFrameInfo.offsetOfReturnAddress = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfReturnAddress; + value.inlinedCallFrameInfo.offsetOfSecretStubArg = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfSecretStubArg; + value.inlinedCallFrameInfo.offsetOfSPAfterProlog = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfSPAfterProlog; value.offsetOfThreadFrame = (DWORD)pEEInfoOut->offsetOfThreadFrame; value.offsetOfGCState = (DWORD)pEEInfoOut->offsetOfGCState; value.offsetOfDelegateInstance = (DWORD)pEEInfoOut->offsetOfDelegateInstance; @@ -4328,12 +4331,14 @@ void MethodContext::recGetEEInfo(CORINFO_EE_INFO* pEEInfoOut) } void MethodContext::dmpGetEEInfo(DWORD key, const Agnostic_CORINFO_EE_INFO& value) { - printf("GetEEInfo key %u, value icfi{sz-%u ogs-%u ofv-%u ofl-%u ocsp-%u ocsfp-%u oct-%u ora-%u} " + printf("GetEEInfo key %u, value icfi{sz-%u sz-witharg-%u ogs-%u ofv-%u ofl-%u ocsp-%u ocsfp-%u oct-%u ora-%u ossa-%u osap-%u} " "otf-%u ogcs-%u odi-%u odft-%u osdic-%u srpf-%u osps-%u muono-%u tabi-%u osType-%u", - key, value.inlinedCallFrameInfo.size, value.inlinedCallFrameInfo.offsetOfGSCookie, + key, value.inlinedCallFrameInfo.size, value.inlinedCallFrameInfo.sizeWithSecretStubArg, + value.inlinedCallFrameInfo.offsetOfGSCookie, value.inlinedCallFrameInfo.offsetOfFrameVptr, value.inlinedCallFrameInfo.offsetOfFrameLink, value.inlinedCallFrameInfo.offsetOfCallSiteSP, value.inlinedCallFrameInfo.offsetOfCalleeSavedFP, value.inlinedCallFrameInfo.offsetOfCallTarget, value.inlinedCallFrameInfo.offsetOfReturnAddress, + value.inlinedCallFrameInfo.offsetOfSecretStubArg, value.inlinedCallFrameInfo.offsetOfSPAfterProlog, value.offsetOfThreadFrame, value.offsetOfGCState, value.offsetOfDelegateInstance, value.offsetOfDelegateFirstTarget, value.offsetOfWrapperDelegateIndirectCell, value.sizeOfReversePInvokeFrame, value.osPageSize, value.maxUncheckedOffsetForNullObject, value.targetAbi, @@ -4341,64 +4346,33 @@ void MethodContext::dmpGetEEInfo(DWORD key, const Agnostic_CORINFO_EE_INFO& valu } void MethodContext::repGetEEInfo(CORINFO_EE_INFO* pEEInfoOut) { - Agnostic_CORINFO_EE_INFO value; - - int index = -1; - if (GetEEInfo != nullptr) - index = GetEEInfo->GetIndex((DWORD)0); - if (index >= 0) - { - value = GetEEInfo->Get(0); - DEBUG_REP(dmpGetEEInfo(0, value)); - - pEEInfoOut->inlinedCallFrameInfo.size = (unsigned)value.inlinedCallFrameInfo.size; - pEEInfoOut->inlinedCallFrameInfo.offsetOfGSCookie = (unsigned)value.inlinedCallFrameInfo.offsetOfGSCookie; - pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameVptr = (unsigned)value.inlinedCallFrameInfo.offsetOfFrameVptr; - pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameLink = (unsigned)value.inlinedCallFrameInfo.offsetOfFrameLink; - pEEInfoOut->inlinedCallFrameInfo.offsetOfCallSiteSP = (unsigned)value.inlinedCallFrameInfo.offsetOfCallSiteSP; - pEEInfoOut->inlinedCallFrameInfo.offsetOfCalleeSavedFP = - (unsigned)value.inlinedCallFrameInfo.offsetOfCalleeSavedFP; - pEEInfoOut->inlinedCallFrameInfo.offsetOfCallTarget = (unsigned)value.inlinedCallFrameInfo.offsetOfCallTarget; - pEEInfoOut->inlinedCallFrameInfo.offsetOfReturnAddress = - (unsigned)value.inlinedCallFrameInfo.offsetOfReturnAddress; - pEEInfoOut->offsetOfThreadFrame = (unsigned)value.offsetOfThreadFrame; - pEEInfoOut->offsetOfGCState = (unsigned)value.offsetOfGCState; - pEEInfoOut->offsetOfDelegateInstance = (unsigned)value.offsetOfDelegateInstance; - pEEInfoOut->offsetOfDelegateFirstTarget = (unsigned)value.offsetOfDelegateFirstTarget; - pEEInfoOut->offsetOfWrapperDelegateIndirectCell= (unsigned)value.offsetOfWrapperDelegateIndirectCell; - pEEInfoOut->sizeOfReversePInvokeFrame = (unsigned)value.sizeOfReversePInvokeFrame; - pEEInfoOut->osPageSize = (size_t)value.osPageSize; - pEEInfoOut->maxUncheckedOffsetForNullObject = (size_t)value.maxUncheckedOffsetForNullObject; - pEEInfoOut->targetAbi = (CORINFO_RUNTIME_ABI)value.targetAbi; - pEEInfoOut->osType = (CORINFO_OS)value.osType; - } - else - { - pEEInfoOut->inlinedCallFrameInfo.size = (unsigned)0x40; - pEEInfoOut->inlinedCallFrameInfo.offsetOfGSCookie = (unsigned)0; - pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameVptr = (unsigned)0x8; - pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameLink = (unsigned)0x10; - pEEInfoOut->inlinedCallFrameInfo.offsetOfCallSiteSP = (unsigned)0x28; - pEEInfoOut->inlinedCallFrameInfo.offsetOfCalleeSavedFP = (unsigned)0x38; - pEEInfoOut->inlinedCallFrameInfo.offsetOfCallTarget = (unsigned)0x18; - pEEInfoOut->inlinedCallFrameInfo.offsetOfReturnAddress = (unsigned)0x30; - pEEInfoOut->offsetOfThreadFrame = (unsigned)0x10; - pEEInfoOut->offsetOfGCState = (unsigned)0xc; - pEEInfoOut->offsetOfDelegateInstance = (unsigned)0x8; - pEEInfoOut->offsetOfDelegateFirstTarget = (unsigned)0x18; - pEEInfoOut->offsetOfWrapperDelegateIndirectCell = (unsigned)0x40; - pEEInfoOut->sizeOfReversePInvokeFrame = (unsigned)0x8; - pEEInfoOut->osPageSize = (size_t)0x1000; - pEEInfoOut->maxUncheckedOffsetForNullObject = (size_t)((32 * 1024) - 1); - pEEInfoOut->targetAbi = CORINFO_CORECLR_ABI; -#ifdef TARGET_OSX - pEEInfoOut->osType = CORINFO_APPLE; -#elif defined(TARGET_UNIX) - pEEInfoOut->osType = CORINFO_UNIX; -#else - pEEInfoOut->osType = CORINFO_WINNT; -#endif - } + Agnostic_CORINFO_EE_INFO value = LookupByKeyOrMissNoMessage(GetEEInfo, 0); + + DEBUG_REP(dmpGetEEInfo(0, value)); + + pEEInfoOut->inlinedCallFrameInfo.size = (unsigned)value.inlinedCallFrameInfo.size; + pEEInfoOut->inlinedCallFrameInfo.sizeWithSecretStubArg = (unsigned)value.inlinedCallFrameInfo.sizeWithSecretStubArg; + pEEInfoOut->inlinedCallFrameInfo.offsetOfGSCookie = (unsigned)value.inlinedCallFrameInfo.offsetOfGSCookie; + pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameVptr = (unsigned)value.inlinedCallFrameInfo.offsetOfFrameVptr; + pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameLink = (unsigned)value.inlinedCallFrameInfo.offsetOfFrameLink; + pEEInfoOut->inlinedCallFrameInfo.offsetOfCallSiteSP = (unsigned)value.inlinedCallFrameInfo.offsetOfCallSiteSP; + pEEInfoOut->inlinedCallFrameInfo.offsetOfCalleeSavedFP = + (unsigned)value.inlinedCallFrameInfo.offsetOfCalleeSavedFP; + pEEInfoOut->inlinedCallFrameInfo.offsetOfCallTarget = (unsigned)value.inlinedCallFrameInfo.offsetOfCallTarget; + pEEInfoOut->inlinedCallFrameInfo.offsetOfReturnAddress = + (unsigned)value.inlinedCallFrameInfo.offsetOfReturnAddress; + pEEInfoOut->inlinedCallFrameInfo.offsetOfSecretStubArg = (unsigned)value.inlinedCallFrameInfo.offsetOfSecretStubArg; + pEEInfoOut->inlinedCallFrameInfo.offsetOfSPAfterProlog = (unsigned)value.inlinedCallFrameInfo.offsetOfSPAfterProlog; + pEEInfoOut->offsetOfThreadFrame = (unsigned)value.offsetOfThreadFrame; + pEEInfoOut->offsetOfGCState = (unsigned)value.offsetOfGCState; + pEEInfoOut->offsetOfDelegateInstance = (unsigned)value.offsetOfDelegateInstance; + pEEInfoOut->offsetOfDelegateFirstTarget = (unsigned)value.offsetOfDelegateFirstTarget; + pEEInfoOut->offsetOfWrapperDelegateIndirectCell= (unsigned)value.offsetOfWrapperDelegateIndirectCell; + pEEInfoOut->sizeOfReversePInvokeFrame = (unsigned)value.sizeOfReversePInvokeFrame; + pEEInfoOut->osPageSize = (size_t)value.osPageSize; + pEEInfoOut->maxUncheckedOffsetForNullObject = (size_t)value.maxUncheckedOffsetForNullObject; + pEEInfoOut->targetAbi = (CORINFO_RUNTIME_ABI)value.targetAbi; + pEEInfoOut->osType = (CORINFO_OS)value.osType; } void MethodContext::recGetGSCookie(GSCookie* pCookieVal, GSCookie** ppCookieVal) @@ -5640,10 +5614,11 @@ HRESULT MethodContext::repAllocPgoInstrumentationBySchema( UINT32 countSchemaItems, BYTE** pInstrumentationData) { - if (repAllocPgoInstrumentationBySchemaRecorded(ftnHnd, pSchema, countSchemaItems, pInstrumentationData)) + HRESULT result; + if (repAllocPgoInstrumentationBySchemaRecorded(ftnHnd, pSchema, countSchemaItems, pInstrumentationData, &result)) { // Matching case: return same layout as recorded EE. - return S_OK; + return result; } // Do our own layout. @@ -5676,7 +5651,8 @@ bool MethodContext::repAllocPgoInstrumentationBySchemaRecorded( CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, UINT32 countSchemaItems, - BYTE** pInstrumentationData) + BYTE** pInstrumentationData, + HRESULT* result) { if (AllocPgoInstrumentationBySchema == nullptr) return false; @@ -5716,6 +5692,7 @@ bool MethodContext::repAllocPgoInstrumentationBySchemaRecorded( // We assume JIT does not write or read from this buffer, only generate // code that uses it. *pInstrumentationData = (BYTE*)value.instrumentationDataAddress; + *result = value.result; return true; } @@ -5724,6 +5701,7 @@ void MethodContext::recGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd UINT32* pCountSchemaItems, BYTE** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource, + bool* pDynamicPgo, HRESULT result) { if (GetPgoInstrumentationResults == nullptr) @@ -5754,6 +5732,7 @@ void MethodContext::recGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd value.dataByteCount = (unsigned)maxOffset; value.result = (DWORD)result; value.pgoSource = (DWORD)*pPgoSource; + value.dynamicPgo = (DWORD)*pDynamicPgo; DWORDLONG key = CastHandle(ftnHnd); GetPgoInstrumentationResults->Add(key, value); @@ -5761,8 +5740,8 @@ void MethodContext::recGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd } void MethodContext::dmpGetPgoInstrumentationResults(DWORDLONG key, const Agnostic_GetPgoInstrumentationResults& value) { - printf("GetPgoInstrumentationResults key ftn-%016" PRIX64 ", value res-%08X schemaCnt-%u profileBufSize-%u source-%u schema{", - key, value.result, value.countSchemaItems, value.dataByteCount, value.pgoSource); + printf("GetPgoInstrumentationResults key ftn-%016" PRIX64 ", value res-%08X schemaCnt-%u profileBufSize-%u source-%u dynamic-%u schema{", + key, value.result, value.countSchemaItems, value.dataByteCount, value.pgoSource, value.dynamicPgo); if (value.countSchemaItems > 0) { @@ -5820,7 +5799,7 @@ void MethodContext::dmpGetPgoInstrumentationResults(DWORDLONG key, const Agnosti case ICorJitInfo::PgoInstrumentationKind::GetLikelyMethod: { // (N)umber, (L)ikelihood, (H)andle - printf("N %u L %u H %016" PRIX64 "", (unsigned)(pBuf[i].Other >> 8), (unsigned)(pBuf[i].Other && 0xFF), CastHandle(*(uintptr_t*)(pInstrumentationData + pBuf[i].Offset))); + printf("N %u L %u H %016" PRIX64 "", (unsigned)(pBuf[i].Other >> 8), (unsigned)(pBuf[i].Other & 0xFF), CastHandle(*(uintptr_t*)(pInstrumentationData + pBuf[i].Offset))); } break; default: @@ -5838,7 +5817,8 @@ HRESULT MethodContext::repGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftn ICorJitInfo::PgoInstrumentationSchema** pSchema, UINT32* pCountSchemaItems, BYTE** pInstrumentationData, - ICorJitInfo::PgoSource* pPgoSource) + ICorJitInfo::PgoSource* pPgoSource, + bool* pDynamicPgo) { DWORDLONG key = CastHandle(ftnHnd); Agnostic_GetPgoInstrumentationResults tempValue = LookupByKeyOrMiss(GetPgoInstrumentationResults, key, ": key %016" PRIX64 "", key); @@ -5848,6 +5828,7 @@ HRESULT MethodContext::repGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftn *pCountSchemaItems = (UINT32)tempValue.countSchemaItems; *pInstrumentationData = (BYTE*)GetPgoInstrumentationResults->GetBuffer(tempValue.data_index); *pPgoSource = (ICorJitInfo::PgoSource)tempValue.pgoSource; + *pDynamicPgo = (bool)tempValue.dynamicPgo; ICorJitInfo::PgoInstrumentationSchema* pOutSchema = (ICorJitInfo::PgoInstrumentationSchema*)AllocJitTempBuffer(tempValue.countSchemaItems * sizeof(ICorJitInfo::PgoInstrumentationSchema)); @@ -5920,6 +5901,28 @@ bool MethodContext::repIsExactType(CORINFO_CLASS_HANDLE cls) return value != 0; } +void MethodContext::recIsNullableType(CORINFO_CLASS_HANDLE cls, TypeCompareState result) +{ + if (IsNullableType == nullptr) + IsNullableType = new LightWeightMap(); + + DWORDLONG key = CastHandle(cls); + DWORD value = (DWORD)result; + IsNullableType->Add(key, value); + DEBUG_REC(dmpIsNullableType(key, value)); +} +void MethodContext::dmpIsNullableType(DWORDLONG key, DWORD value) +{ + printf("IsNullableType key cls-%016" PRIX64 ", value res-%d", key, value); +} +TypeCompareState MethodContext::repIsNullableType(CORINFO_CLASS_HANDLE cls) +{ + DWORDLONG key = CastHandle(cls); + DWORD value = LookupByKeyOrMiss(IsNullableType, key, ": key %016" PRIX64 "", key); + DEBUG_REP(dmpIsNullableType(key, value)); + return (TypeCompareState)value; +} + void MethodContext::recIsEnum(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE underlyingType, TypeCompareState result) { if (IsEnum == nullptr) @@ -6223,13 +6226,13 @@ bool MethodContext::repGetSystemVAmd64PassStructInRegisterDescriptor( DEBUG_REP(dmpGetSystemVAmd64PassStructInRegisterDescriptor(key, value)); structPassInRegDescPtr->passedInRegisters = value.passedInRegisters ? true : false; - structPassInRegDescPtr->eightByteCount = (unsigned __int8)value.eightByteCount; + structPassInRegDescPtr->eightByteCount = (uint8_t)value.eightByteCount; for (int i = 0; i < CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS; i++) { structPassInRegDescPtr->eightByteClassifications[i] = (SystemVClassificationType)value.eightByteClassifications[i]; - structPassInRegDescPtr->eightByteSizes[i] = (unsigned __int8)value.eightByteSizes[i]; - structPassInRegDescPtr->eightByteOffsets[i] = (unsigned __int8)value.eightByteOffsets[i]; + structPassInRegDescPtr->eightByteSizes[i] = (uint8_t)value.eightByteSizes[i]; + structPassInRegDescPtr->eightByteOffsets[i] = (uint8_t)value.eightByteOffsets[i]; } return value.result ? true : false; @@ -7161,7 +7164,8 @@ int MethodContext::dumpMethodIdentityInfoToBuffer(char* buff, int len, bool igno UINT32 schemaCount = 0; BYTE* schemaData = nullptr; ICorJitInfo::PgoSource pgoSource = ICorJitInfo::PgoSource::Unknown; - HRESULT pgoHR = repGetPgoInstrumentationResults(pInfo->ftn, &schema, &schemaCount, &schemaData, &pgoSource); + bool dynamicPgo = false; + HRESULT pgoHR = repGetPgoInstrumentationResults(pInfo->ftn, &schema, &schemaCount, &schemaData, &pgoSource, &dynamicPgo); size_t minOffset = (size_t) ~0; size_t maxOffset = 0; @@ -7259,7 +7263,8 @@ bool MethodContext::hasPgoData(bool& hasEdgeProfile, bool& hasClassProfile, bool ICorJitInfo::PgoInstrumentationSchema* schema = nullptr; UINT32 schemaCount = 0; BYTE* schemaData = nullptr; - HRESULT pgoHR = repGetPgoInstrumentationResults(info.ftn, &schema, &schemaCount, &schemaData, &pgoSource); + bool dynamicPgo; + HRESULT pgoHR = repGetPgoInstrumentationResults(info.ftn, &schema, &schemaCount, &schemaData, &pgoSource, &dynamicPgo); if (SUCCEEDED(pgoHR)) { diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index cf9c235ae987..2c85988aa32e 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -709,11 +709,11 @@ class MethodContext void recAllocPgoInstrumentationBySchema(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, UINT32 countSchemaItems, BYTE** pInstrumentationData, HRESULT result); void dmpAllocPgoInstrumentationBySchema(DWORDLONG key, const Agnostic_AllocPgoInstrumentationBySchema& value); HRESULT repAllocPgoInstrumentationBySchema(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, UINT32 countSchemaItems, BYTE** pInstrumentationData); - bool repAllocPgoInstrumentationBySchemaRecorded(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, UINT32 countSchemaItems, BYTE** pInstrumentationData); + bool repAllocPgoInstrumentationBySchemaRecorded(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, UINT32 countSchemaItems, BYTE** pInstrumentationData, HRESULT* result); - void recGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, UINT32* pCountSchemaItems, BYTE** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource, HRESULT result); + void recGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, UINT32* pCountSchemaItems, BYTE** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource, bool* pDynamicPgo, HRESULT result); void dmpGetPgoInstrumentationResults(DWORDLONG key, const Agnostic_GetPgoInstrumentationResults& value); - HRESULT repGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, UINT32* pCountSchemaItems, BYTE** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource); + HRESULT repGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, UINT32* pCountSchemaItems, BYTE** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource, bool* pDynamicPgo); void recIsMoreSpecificType(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2, bool result); void dmpIsMoreSpecificType(DLDL key, DWORD value); @@ -723,6 +723,10 @@ class MethodContext void dmpIsExactType(DWORDLONG key, DWORD value); bool repIsExactType(CORINFO_CLASS_HANDLE cls); + void recIsNullableType(CORINFO_CLASS_HANDLE cls, TypeCompareState result); + void dmpIsNullableType(DWORDLONG key, DWORD value); + TypeCompareState repIsNullableType(CORINFO_CLASS_HANDLE cls); + void recIsEnum(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE underlyingType, TypeCompareState result); void dmpIsEnum(DWORDLONG key, DLD value); TypeCompareState repIsEnum(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType); @@ -1165,6 +1169,7 @@ enum mcPackets Packet_NotifyMethodInfoUsage = 214, Packet_IsExactType = 215, Packet_GetSwiftLowering = 216, + Packet_IsNullableType = 217, }; void SetDebugDumpVariables(); diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontextiterator.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextiterator.h index fd32e95451eb..f45e85ea6e39 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontextiterator.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextiterator.h @@ -71,7 +71,7 @@ class MethodContextIterator } // Return the file position offset of the current method context. - __int64 CurrentPos() + int64_t CurrentPos() { return m_pos.QuadPart; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp index 14f1d37dde61..bcad854f0906 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp @@ -143,7 +143,7 @@ void MethodContextReader::ReleaseLock() bool MethodContextReader::atEof() { - __int64 pos = 0; + int64_t pos = 0; SetFilePointerEx(this->fileHandle, *(PLARGE_INTEGER)&pos, (PLARGE_INTEGER)&pos, FILE_CURRENT); // LARGE_INTEGER is a crime against humanity return pos == this->fileSize; @@ -163,7 +163,7 @@ MethodContextBuffer MethodContextReader::ReadMethodContextNoLock(bool justSkip) memcpy(&totalLen, &buff[2], sizeof(unsigned int)); if (justSkip) { - __int64 pos = totalLen + 2; + int64_t pos = totalLen + 2; // Just move the file pointer ahead the correct number of bytes AssertMsg(SetFilePointerEx(this->fileHandle, *(PLARGE_INTEGER)&pos, (PLARGE_INTEGER)&pos, FILE_CURRENT) == TRUE, "SetFilePointerEx failed (Error %X)", GetLastError()); @@ -424,7 +424,7 @@ double MethodContextReader::Progress() else { this->AcquireLock(); - __int64 pos = 0; + int64_t pos = 0; SetFilePointerEx(this->fileHandle, *(PLARGE_INTEGER)&pos, (PLARGE_INTEGER)&pos, FILE_CURRENT); this->ReleaseLock(); return (double)pos; @@ -465,7 +465,7 @@ double MethodContextReader::PercentComplete() // Returns -1 for not found, or -2 for not indexed // Interview question alert: hurray for CLR headers incompatibility with STL :-( // Note that TOC is 0 based and MC# are 1 based! -__int64 MethodContextReader::GetOffset(unsigned int methodNumber) +int64_t MethodContextReader::GetOffset(unsigned int methodNumber) { if (!this->hasTOC()) return -2; @@ -487,7 +487,7 @@ __int64 MethodContextReader::GetOffset(unsigned int methodNumber) MethodContextBuffer MethodContextReader::GetSpecificMethodContext(unsigned int methodNumber) { - __int64 pos = this->GetOffset(methodNumber); + int64_t pos = this->GetOffset(methodNumber); if (pos < 0) { return MethodContextBuffer(-3); @@ -538,7 +538,7 @@ void MethodContextReader::ReadExcludedMethods(std::string mchFileName) HANDLE excludeFileHandle = OpenFile(excludeFileName.c_str()); if (excludeFileHandle != INVALID_HANDLE_VALUE) { - __int64 excludeFileSizeLong; + int64_t excludeFileSizeLong; GetFileSizeEx(excludeFileHandle, (PLARGE_INTEGER)&excludeFileSizeLong); unsigned excludeFileSize = (unsigned)excludeFileSizeLong; @@ -622,9 +622,13 @@ bool MethodContextReader::IsMethodExcluded(MethodContext* mc) void MethodContextReader::Reset(const int* newIndexes, int newIndexCount) { - Indexes = newIndexes; - IndexCount = newIndexCount; + int64_t pos = 0; + BOOL result = SetFilePointerEx(fileHandle, *(PLARGE_INTEGER)&pos, NULL, FILE_BEGIN); + assert(result); + + Indexes = newIndexes; + IndexCount = newIndexCount; curIndexPos = 0; - curMCIndex = 0; + curMCIndex = 0; curTOCIndex = 0; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.h index b3c77e1637ef..df3ca7b31653 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.h @@ -50,7 +50,7 @@ class MethodContextReader HANDLE fileHandle; // The size of the MC/MCH file - __int64 fileSize; + int64_t fileSize; // Current MC index in the input MC/MCH file int curMCIndex; @@ -90,7 +90,7 @@ class MethodContextReader // Binary search to get this method number from the index // Returns -1 for not found, or -2 for not indexed - __int64 GetOffset(unsigned int methodNumber); + int64_t GetOffset(unsigned int methodNumber); // Just a helper... static HANDLE OpenFile(const char* inputFile, DWORD flags = FILE_ATTRIBUTE_NORMAL); diff --git a/src/coreclr/tools/superpmi/superpmi-shared/tocfile.h b/src/coreclr/tools/superpmi/superpmi-shared/tocfile.h index 93401f3e225b..0f010fda8246 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/tocfile.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/tocfile.h @@ -12,7 +12,7 @@ class TOCElement { public: - __int64 Offset; + int64_t Offset; int Number; char Hash[MM3_HASH_BUFFER_SIZE]; @@ -20,7 +20,7 @@ class TOCElement { } - TOCElement(int number, __int64 offset) : Offset(offset), Number(number) + TOCElement(int number, int64_t offset) : Offset(offset), Number(number) { } }; diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index d53002a42914..ac8efbddcfee 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -914,6 +914,15 @@ bool interceptor_ICJI::isExactType(CORINFO_CLASS_HANDLE cls) return temp; } +// Returns whether a class handle represents a Nullable type, if that can be statically determined. +TypeCompareState interceptor_ICJI::isNullableType(CORINFO_CLASS_HANDLE cls) +{ + mc->cr->AddCall("isNullableType"); + TypeCompareState temp = original_ICorJitInfo->isNullableType(cls); + mc->recIsNullableType(cls, temp); + return temp; +} + // Returns TypeCompareState::Must if cls is known to be an enum. // For enums with known exact type returns the underlying // type in underlyingType when the provided pointer is @@ -1938,11 +1947,12 @@ HRESULT interceptor_ICJI::getPgoInstrumentationResults(CORINFO_METHOD_HANDLE PgoInstrumentationSchema **pSchema, // pointer to the schema table which describes the instrumentation results (pointer will not remain valid after jit completes) uint32_t * pCountSchemaItems, // pointer to the count schema items uint8_t ** pInstrumentationData, // pointer to the actual instrumentation data (pointer will not remain valid after jit completes) - PgoSource* pPgoSource) + PgoSource* pPgoSource, + bool* pDynamicPgo) { mc->cr->AddCall("getPgoInstrumentationResults"); - HRESULT temp = original_ICorJitInfo->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource); - mc->recGetPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, temp); + HRESULT temp = original_ICorJitInfo->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, pDynamicPgo); + mc->recGetPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, pDynamicPgo, temp); return temp; } diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp index ef1b277e8053..a365cdb111e2 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -659,6 +659,13 @@ bool interceptor_ICJI::isExactType( return original_ICorJitInfo->isExactType(cls); } +TypeCompareState interceptor_ICJI::isNullableType( + CORINFO_CLASS_HANDLE cls) +{ + mcs->AddCall("isNullableType"); + return original_ICorJitInfo->isNullableType(cls); +} + TypeCompareState interceptor_ICJI::isEnum( CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType) @@ -1367,10 +1374,11 @@ JITINTERFACE_HRESULT interceptor_ICJI::getPgoInstrumentationResults( ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, - ICorJitInfo::PgoSource* pgoSource) + ICorJitInfo::PgoSource* pPgoSource, + bool* pDynamicPgo) { mcs->AddCall("getPgoInstrumentationResults"); - return original_ICorJitInfo->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pgoSource); + return original_ICorJitInfo->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, pDynamicPgo); } JITINTERFACE_HRESULT interceptor_ICJI::allocPgoInstrumentationBySchema( diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp index 55aef6512734..0d80993f52b6 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -578,6 +578,12 @@ bool interceptor_ICJI::isExactType( return original_ICorJitInfo->isExactType(cls); } +TypeCompareState interceptor_ICJI::isNullableType( + CORINFO_CLASS_HANDLE cls) +{ + return original_ICorJitInfo->isNullableType(cls); +} + TypeCompareState interceptor_ICJI::isEnum( CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType) @@ -1200,9 +1206,10 @@ JITINTERFACE_HRESULT interceptor_ICJI::getPgoInstrumentationResults( ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, - ICorJitInfo::PgoSource* pgoSource) + ICorJitInfo::PgoSource* pPgoSource, + bool* pDynamicPgo) { - return original_ICorJitInfo->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pgoSource); + return original_ICorJitInfo->getPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, pDynamicPgo); } JITINTERFACE_HRESULT interceptor_ICJI::allocPgoInstrumentationBySchema( diff --git a/src/coreclr/tools/superpmi/superpmi/cycletimer.cpp b/src/coreclr/tools/superpmi/superpmi/cycletimer.cpp index 6d9677d38da2..d5f44c2f67c0 100644 --- a/src/coreclr/tools/superpmi/superpmi/cycletimer.cpp +++ b/src/coreclr/tools/superpmi/superpmi/cycletimer.cpp @@ -37,16 +37,16 @@ void CycleTimer::Stop() } } -unsigned __int64 CycleTimer::GetCycles() +uint64_t CycleTimer::GetCycles() { return stop - start - overhead; } -unsigned __int64 CycleTimer::QueryOverhead() +uint64_t CycleTimer::QueryOverhead() { - unsigned __int64 tot = 0; - unsigned __int64 startCycles; - unsigned __int64 endCycles; + uint64_t tot = 0; + uint64_t startCycles; + uint64_t endCycles; const int N = 1000; for (int i = 0; i < N; i++) { diff --git a/src/coreclr/tools/superpmi/superpmi/cycletimer.h b/src/coreclr/tools/superpmi/superpmi/cycletimer.h index ce69f3fc69b0..8f89a879fa4a 100644 --- a/src/coreclr/tools/superpmi/superpmi/cycletimer.h +++ b/src/coreclr/tools/superpmi/superpmi/cycletimer.h @@ -14,13 +14,13 @@ class CycleTimer void Start(); void Stop(); - unsigned __int64 GetCycles(); - unsigned __int64 QueryOverhead(); + uint64_t GetCycles(); + uint64_t QueryOverhead(); private: // Cycles - unsigned __int64 start; - unsigned __int64 stop; - unsigned __int64 overhead; + uint64_t start; + uint64_t stop; + uint64_t overhead; }; #endif diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index f23c8e12f866..b263c1cafdeb 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -764,6 +764,13 @@ bool MyICJI::isExactType(CORINFO_CLASS_HANDLE cls) return jitInstance->mc->repIsExactType(cls); } +// Returns true if a class handle represents a Nullable type. +TypeCompareState MyICJI::isNullableType(CORINFO_CLASS_HANDLE cls) +{ + jitInstance->mc->cr->AddCall("isNullableType"); + return jitInstance->mc->repIsNullableType(cls); +} + // Returns TypeCompareState::Must if cls is known to be an enum. // For enums with known exact type returns the underlying // type in underlyingType when the provided pointer is @@ -1799,11 +1806,12 @@ HRESULT MyICJI::getPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, PgoInstrumentationSchema **pSchema, // pointer to the schema table which describes the instrumentation results (pointer will not remain valid after jit completes) uint32_t * pCountSchemaItems, // pointer to the count schema items uint8_t ** pInstrumentationData, // pointer to the actual instrumentation data (pointer will not remain valid after jit completes) - PgoSource* pPgoSource) + PgoSource* pPgoSource, + bool* pDynamicPgo) { jitInstance->mc->cr->AddCall("getPgoInstrumentationResults"); - return jitInstance->mc->repGetPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource); + return jitInstance->mc->repGetPgoInstrumentationResults(ftnHnd, pSchema, pCountSchemaItems, pInstrumentationData, pPgoSource, pDynamicPgo); } // Associates a native call site, identified by its offset in the native code stream, with diff --git a/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp b/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp index 8eb0e69e8b2e..2f085b2610d8 100644 --- a/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp +++ b/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp @@ -475,7 +475,7 @@ void JitInstance::timeResult(CORINFO_METHOD_INFO info, unsigned flags) int sampleSize = 10; // Save 2 smallest times. To help reduce noise, we will look at the closest pair of these. - unsigned __int64 time; + uint64_t time; for (int i = 0; i < sampleSize; i++) { diff --git a/src/coreclr/unwinder/arm64/unwinder.cpp b/src/coreclr/unwinder/arm64/unwinder.cpp index 8096204dffa6..c7d04a70255f 100644 --- a/src/coreclr/unwinder/arm64/unwinder.cpp +++ b/src/coreclr/unwinder/arm64/unwinder.cpp @@ -794,7 +794,7 @@ RtlpExpandCompactToFull ( // or registers to lave left. // - for (intreg = 0; intreg < ((fnent_pdata->RegI / 2) * 2); intreg += 2) { + for (intreg = 0; intreg < (ULONG)((fnent_pdata->RegI / 2) * 2); intreg += 2) { if (!sav_predec_done) { DBG_OP("save_regp_x\t(%s, %s, %i)\n", int_reg_names[intreg], int_reg_names[intreg + 1], -savsz * 8); emit_save_regp_x(&op_buffer, intreg, -savsz * 8); @@ -1484,7 +1484,7 @@ Return Value: Fpcr = MEMORY_READ_DWORD(UnwindParams, SourceAddress); SourceAddress = VfpStateAddress + FIELD_OFFSET(KARM64_VFP_STATE, Fpsr); Fpsr = MEMORY_READ_DWORD(UnwindParams, SourceAddress); - if (Fpcr != -1 && Fpsr != -1) { + if (Fpcr != (ULONG)-1 && Fpsr != (ULONG)-1) { ContextRecord->Fpcr = Fpcr; ContextRecord->Fpsr = Fpsr; diff --git a/src/coreclr/unwinder/baseunwinder.cpp b/src/coreclr/unwinder/baseunwinder.cpp index e059b936c340..b00c2aa11483 100644 --- a/src/coreclr/unwinder/baseunwinder.cpp +++ b/src/coreclr/unwinder/baseunwinder.cpp @@ -28,7 +28,7 @@ HRESULT OOPStackUnwinder::GetModuleBase( DWORD64 address, _Out_ PDWORD64 pdwBase) { GetRuntimeStackWalkInfo(address, reinterpret_cast(pdwBase), NULL); - return ((*pdwBase == NULL) ? E_FAIL : S_OK); + return ((*pdwBase == 0) ? E_FAIL : S_OK); } //--------------------------------------------------------------------------------------- diff --git a/src/coreclr/utilcode/arraylist.cpp b/src/coreclr/utilcode/arraylist.cpp index c6e538fd38da..ecdf1e314488 100644 --- a/src/coreclr/utilcode/arraylist.cpp +++ b/src/coreclr/utilcode/arraylist.cpp @@ -35,7 +35,7 @@ void ArrayListBase::Clear() delete [] block; block = next; } - m_firstBlock.m_next = 0; + m_firstBlock.m_next = nullptr; m_count = 0; } diff --git a/src/coreclr/utilcode/clrhost.cpp b/src/coreclr/utilcode/clrhost.cpp index 0bf016eb8834..05291cabea38 100644 --- a/src/coreclr/utilcode/clrhost.cpp +++ b/src/coreclr/utilcode/clrhost.cpp @@ -39,79 +39,6 @@ void* GetClrModuleBase() thread_local int t_CantAllocCount; -#ifdef FAILPOINTS_ENABLED -typedef int (*FHashStack) (); - -static FHashStack fHashStack = 0; -static _TEB *HashStackSetupThread = NULL; -static _TEB *RFSCustomDataSetupThread = NULL; - -static void SetupHashStack () -{ - CANNOT_HAVE_CONTRACT; - - FHashStack oldValue = InterlockedCompareExchangeT(&fHashStack, - reinterpret_cast(1), reinterpret_cast(0)); - if ((size_t) oldValue >= 2) { - return; - } - else if ((size_t) oldValue == 0) { - // We are the first thread to initialize - HashStackSetupThread = NtCurrentTeb(); - - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_HashStack) == 0) { - fHashStack = (FHashStack) 2; - return; - } - - PAL_TRY(void *, unused, NULL) { - FHashStack func; - HMODULE hmod = WszLoadLibrary(W("mscorrfs.dll"), NULL, 0); - if (hmod) { - func = (FHashStack)GetProcAddress (hmod, "HashStack"); - if (func == 0) { - func = (FHashStack)2; - } - } - else - func = (FHashStack)2; - fHashStack = func; - } - PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - fHashStack = (FHashStack) 2; - } - PAL_ENDTRY; - } - else if (NtCurrentTeb() == HashStackSetupThread) { - // We get here while initializing - return; - } - else { - // All other threads will wait - while (fHashStack == (FHashStack) 1) { - ClrSleepEx (100, FALSE); - } - } -} - -int RFS_HashStack () -{ - CANNOT_HAVE_CONTRACT; - - if ((size_t)fHashStack < 2) { - SetupHashStack (); - } - - if ((size_t)fHashStack <= 2) { - return 0; - } - else - return fHashStack (); -} - -#endif // FAILPOINTS_ENABLED - DWORD GetClrModulePathName(SString& buffer) { #ifdef HOST_WINDOWS diff --git a/src/coreclr/utilcode/clrhost_nodependencies.cpp b/src/coreclr/utilcode/clrhost_nodependencies.cpp index 7aceae763c43..766081eab813 100644 --- a/src/coreclr/utilcode/clrhost_nodependencies.cpp +++ b/src/coreclr/utilcode/clrhost_nodependencies.cpp @@ -12,44 +12,6 @@ #include "clrnt.h" #include "contract.h" -#ifdef _DEBUG_IMPL - -// -// I'd very much like for this to go away. Its used to disable all THROWS contracts within whatever DLL this -// function is called from. That's obviously very, very bad, since there's no validation of those macros. But it -// can be difficult to remove this without actually fixing every violation at the same time. -// -// When this flag is finally removed, remove RealCLRThrowsExceptionWorker() too and put CONTRACT_THROWS() in place -// of it. -// -// -static BOOL dbg_fDisableThrowCheck = FALSE; - -void DisableThrowCheck() -{ - LIMITED_METHOD_CONTRACT; - - dbg_fDisableThrowCheck = TRUE; -} - -#define CLRThrowsExceptionWorker() RealCLRThrowsExceptionWorker(__FUNCTION__, __FILE__, __LINE__) - -static void RealCLRThrowsExceptionWorker(_In_z_ const char *szFunction, - _In_z_ const char *szFile, - int lineNum) -{ - WRAPPER_NO_CONTRACT; - - if (dbg_fDisableThrowCheck) - { - return; - } - - CONTRACT_THROWSEX(szFunction, szFile, lineNum); -} - -#endif //_DEBUG_IMPL - #if defined(_DEBUG_IMPL) && defined(ENABLE_CONTRACTS_IMPL) thread_local ClrDebugState* t_pClrDebugState; @@ -202,341 +164,13 @@ ClrDebugState *CLRInitDebugState() #endif //defined(_DEBUG_IMPL) && defined(ENABLE_CONTRACTS_IMPL) -const NoThrow nothrow = { 0 }; - -#if defined(HAS_ADDRESS_SANITIZER) || defined(DACCESS_COMPILE) -// use standard heap functions for address sanitizer -#else - -#ifdef _DEBUG -#ifdef TARGET_X86 -#define OS_HEAP_ALIGN 8 -#else -#define OS_HEAP_ALIGN 16 -#endif -#define CLRALLOC_TAG 0x2ce145f1 -#endif - -#ifdef HOST_WINDOWS -static HANDLE g_hProcessHeap; -#endif - -FORCEINLINE void* ClrMalloc(size_t size) -{ - STATIC_CONTRACT_NOTHROW; - -#ifdef FAILPOINTS_ENABLED - if (RFS_HashStack()) - return NULL; -#endif - - void* p; - -#ifdef _DEBUG - size += OS_HEAP_ALIGN; -#endif - -#ifdef HOST_WINDOWS - HANDLE hHeap = g_hProcessHeap; - if (hHeap == NULL) - { - InterlockedCompareExchangeT(&g_hProcessHeap, ::GetProcessHeap(), NULL); - hHeap = g_hProcessHeap; - } - - p = HeapAlloc(hHeap, 0, size); -#else - if (size == 0) - { - // Allocate at least one byte. - size = 1; - } - p = malloc(size); -#endif - -#ifdef _DEBUG - // Store the tag to detect heap contamination - if (p != NULL) - { - *((DWORD*)p) = CLRALLOC_TAG; - p = (BYTE*)p + OS_HEAP_ALIGN; - } -#endif - -#ifndef SELF_NO_HOST - if (p == NULL - // If we have not created StressLog ring buffer, we should not try to use it. - // StressLog is going to do a memory allocation. We may enter an endless loop. - && StressLog::t_pCurrentThreadLog != NULL) - { - STRESS_LOG_OOM_STACK(size); - } -#endif - - return p; -} - -FORCEINLINE void ClrFree(void* p) -{ - STATIC_CONTRACT_NOTHROW; - -#ifdef _DEBUG - if (p != NULL) - { - // Check the heap handle to detect heap contamination - p = (BYTE*)p - OS_HEAP_ALIGN; - if (*((DWORD*)p) != CLRALLOC_TAG) - _ASSERTE(!"Heap contamination detected! HeapFree was called on a heap other than the one that memory was allocated from.\n" - "Possible cause: you used new (executable) to allocate the memory, but didn't use DeleteExecutable() to free it."); - } -#endif - -#ifdef HOST_WINDOWS - if (p != NULL) - HeapFree(g_hProcessHeap, 0, p); -#else - free(p); -#endif -} - -void * __cdecl -operator new(size_t n) -{ -#ifdef _DEBUG_IMPL - CLRThrowsExceptionWorker(); -#endif - - STATIC_CONTRACT_THROWS; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_FAULT; - STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; - - void* result = ClrMalloc(n); - if (result == NULL) { - ThrowOutOfMemory(); - } - TRASH_LASTERROR; - return result; -} - -void * __cdecl -operator new[](size_t n) -{ -#ifdef _DEBUG_IMPL - CLRThrowsExceptionWorker(); -#endif - - STATIC_CONTRACT_THROWS; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_FAULT; - STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; - - void* result = ClrMalloc(n); - if (result == NULL) { - ThrowOutOfMemory(); - } - TRASH_LASTERROR; - return result; -}; - -#endif // HAS_ADDRESS_SANITIZER || DACCESS_COMPILE - -void * __cdecl operator new(size_t n, const NoThrow&) NOEXCEPT -{ -#if defined(HAS_ADDRESS_SANITIZER) || defined(DACCESS_COMPILE) - // use standard heap functions for address sanitizer (which doesn't provide for NoThrow) - void * result = operator new(n); -#else - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_FAULT; - STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; - - INCONTRACT(_ASSERTE(!ARE_FAULTS_FORBIDDEN())); - - void* result = ClrMalloc(n); -#endif // HAS_ADDRESS_SANITIZER || DACCESS_COMPILE - TRASH_LASTERROR; - return result; -} - -void * __cdecl operator new[](size_t n, const NoThrow&) NOEXCEPT -{ -#if defined(HAS_ADDRESS_SANITIZER) || defined(DACCESS_COMPILE) - // use standard heap functions for address sanitizer (which doesn't provide for NoThrow) - void * result = operator new[](n); -#else - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_FAULT; - STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; - - INCONTRACT(_ASSERTE(!ARE_FAULTS_FORBIDDEN())); - - void* result = ClrMalloc(n); -#endif // HAS_ADDRESS_SANITIZER || DACCESS_COMPILE - TRASH_LASTERROR; - return result; -} - -#if defined(HAS_ADDRESS_SANITIZER) || defined(DACCESS_COMPILE) -// use standard heap functions for address sanitizer -#else -void __cdecl -operator delete(void *p) NOEXCEPT -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; - - ClrFree(p); - - TRASH_LASTERROR; -} - -void __cdecl -operator delete[](void *p) NOEXCEPT -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; - - ClrFree(p); - TRASH_LASTERROR; -} - -#endif // HAS_ADDRESS_SANITIZER || DACCESS_COMPILE - -/* ------------------------------------------------------------------------ * - * New operator overloading for the executable heap - * ------------------------------------------------------------------------ */ - -#ifdef HOST_WINDOWS - -HANDLE ClrGetProcessExecutableHeap() -{ - // Note: this can be called a little early for real contracts, so we use static contracts instead. - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - - static HANDLE g_ExecutableHeapHandle; - - // - // Create the executable heap lazily - // - if (g_ExecutableHeapHandle == NULL) - { - - HANDLE ExecutableHeapHandle = HeapCreate( - HEAP_CREATE_ENABLE_EXECUTE, // heap allocation attributes - 0, // initial heap size - 0 // maximum heap size; 0 == growable - ); - - if (ExecutableHeapHandle == NULL) - return NULL; - - HANDLE ExistingValue = InterlockedCompareExchangeT(&g_ExecutableHeapHandle, ExecutableHeapHandle, NULL); - if (ExistingValue != NULL) - { - HeapDestroy(ExecutableHeapHandle); - } - } - - return g_ExecutableHeapHandle; -} - -const CExecutable executable = { 0 }; - -void * __cdecl operator new(size_t n, const CExecutable&) -{ -#if defined(_DEBUG_IMPL) - CLRThrowsExceptionWorker(); -#endif - - STATIC_CONTRACT_THROWS; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_FAULT; - - HANDLE hExecutableHeap = ClrGetProcessExecutableHeap(); - if (hExecutableHeap == NULL) { - ThrowOutOfMemory(); - } - - void * result = HeapAlloc(hExecutableHeap, 0, n); - if (result == NULL) { - ThrowOutOfMemory(); - } - TRASH_LASTERROR; - return result; -} - -void * __cdecl operator new[](size_t n, const CExecutable&) -{ -#if defined(_DEBUG_IMPL) - CLRThrowsExceptionWorker(); -#endif - - STATIC_CONTRACT_THROWS; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_FAULT; - - HANDLE hExecutableHeap = ClrGetProcessExecutableHeap(); - if (hExecutableHeap == NULL) { - ThrowOutOfMemory(); - } - - void * result = HeapAlloc(hExecutableHeap, 0, n); - if (result == NULL) { - ThrowOutOfMemory(); - } - TRASH_LASTERROR; - return result; -} - -void * __cdecl operator new(size_t n, const CExecutable&, const NoThrow&) -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_FAULT; - - INCONTRACT(_ASSERTE(!ARE_FAULTS_FORBIDDEN())); - - HANDLE hExecutableHeap = ClrGetProcessExecutableHeap(); - if (hExecutableHeap == NULL) - return NULL; - - void * result = HeapAlloc(hExecutableHeap, 0, n); - TRASH_LASTERROR; - return result; -} - -void * __cdecl operator new[](size_t n, const CExecutable&, const NoThrow&) -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_FAULT; - - INCONTRACT(_ASSERTE(!ARE_FAULTS_FORBIDDEN())); - - HANDLE hExecutableHeap = ClrGetProcessExecutableHeap(); - if (hExecutableHeap == NULL) - return NULL; - - void * result = HeapAlloc(hExecutableHeap, 0, n); - TRASH_LASTERROR; - return result; -} - -#endif // HOST_WINDOWS - #ifdef _DEBUG // This is a DEBUG routing to verify that a memory region complies with executable requirements BOOL DbgIsExecutable(LPVOID lpMem, SIZE_T length) { #if defined(TARGET_UNIX) - // No NX support on PAL or for crossgen compilations. + // No NX support on PAL return TRUE; #else // !(TARGET_UNIX) BYTE *regionStart = (BYTE*) ALIGN_DOWN((BYTE*)lpMem, GetOsPageSize()); diff --git a/src/coreclr/utilcode/corimage.cpp b/src/coreclr/utilcode/corimage.cpp index 1838eb9e9d1a..7eb3adb7a07b 100644 --- a/src/coreclr/utilcode/corimage.cpp +++ b/src/coreclr/utilcode/corimage.cpp @@ -255,5 +255,5 @@ EXTERN_C DWORD Cor_RtlImageRvaToOffset(PTR_IMAGE_NT_HEADERS NtHeaders, return ((Rva - VAL32(NtSection->VirtualAddress)) + VAL32(NtSection->PointerToRawData)); else - return NULL; + return 0; } diff --git a/src/coreclr/utilcode/cycletimer.cpp b/src/coreclr/utilcode/cycletimer.cpp index 642ce22e630c..946c72b278e2 100644 --- a/src/coreclr/utilcode/cycletimer.cpp +++ b/src/coreclr/utilcode/cycletimer.cpp @@ -9,7 +9,7 @@ #include "assert.h" #include "utilcode.h" -bool CycleTimer::GetThreadCyclesS(unsigned __int64* cycles) +bool CycleTimer::GetThreadCyclesS(uint64_t* cycles) { BOOL res = FALSE; res = QueryThreadCycleTime(GetCurrentThread(), cycles); @@ -30,7 +30,7 @@ double CycleTimer::CyclesPerSecond() if (!QueryPerformanceFrequency(&lpFrequency)) return 0.0; // Otherwise... LARGE_INTEGER qpcStart; - unsigned __int64 cycleStart; + uint64_t cycleStart; if (!QueryPerformanceCounter(&qpcStart)) return 0.0; if (!GetThreadCyclesS(&cycleStart)) return 0.0; volatile int sum = 0; @@ -40,7 +40,7 @@ double CycleTimer::CyclesPerSecond() } LARGE_INTEGER qpcEnd; if (!QueryPerformanceCounter(&qpcEnd)) return 0.0; - unsigned __int64 cycleEnd; + uint64_t cycleEnd; if (!GetThreadCyclesS(&cycleEnd)) return 0.0; double qpcTicks = ((double)qpcEnd.QuadPart) - ((double)qpcStart.QuadPart); @@ -50,11 +50,11 @@ double CycleTimer::CyclesPerSecond() } // static -unsigned __int64 CycleTimer::QueryOverhead() +uint64_t CycleTimer::QueryOverhead() { - unsigned __int64 tot = 0; - unsigned __int64 startCycles; - unsigned __int64 endCycles; + uint64_t tot = 0; + uint64_t startCycles; + uint64_t endCycles; const int N = 1000; bool b = GetThreadCyclesS(&startCycles); assert(b); for (int i = 0; i < N; i++) @@ -67,18 +67,18 @@ unsigned __int64 CycleTimer::QueryOverhead() } // static -void CycleTimer::InterlockedAddU64(unsigned __int64* loc, unsigned __int64 amount) +void CycleTimer::InterlockedAddU64(uint64_t* loc, uint64_t amount) { - volatile __int64* vloc = (volatile __int64*)loc; - unsigned __int64 prev = *vloc; + volatile int64_t* vloc = (volatile int64_t*)loc; + uint64_t prev = *vloc; for (;;) { - unsigned __int64 next = prev + amount; - __int64 snext = (__int64)next; - __int64 sprev = (__int64)prev; - __int64 res = InterlockedCompareExchange64(vloc, snext, sprev); + uint64_t next = prev + amount; + int64_t snext = (int64_t)next; + int64_t sprev = (int64_t)prev; + int64_t res = InterlockedCompareExchange64(vloc, snext, sprev); if (res == sprev) return; - else prev = (unsigned __int64)res; + else prev = (uint64_t)res; } } diff --git a/src/coreclr/utilcode/ex.cpp b/src/coreclr/utilcode/ex.cpp index 7b65514b83d0..adee9ba55618 100644 --- a/src/coreclr/utilcode/ex.cpp +++ b/src/coreclr/utilcode/ex.cpp @@ -574,7 +574,6 @@ LPCSTR Exception::GetHRSymbolicName(HRESULT hr) CASE_HRESULT(COR_E_CANNOTUNLOADAPPDOMAIN) CASE_HRESULT(MSEE_E_ASSEMBLYLOADINPROGRESS) CASE_HRESULT(FUSION_E_REF_DEF_MISMATCH) - CASE_HRESULT(FUSION_E_PRIVATE_ASM_DISALLOWED) CASE_HRESULT(FUSION_E_INVALID_NAME) CASE_HRESULT(CLDB_E_FILE_BADREAD) CASE_HRESULT(CLDB_E_FILE_BADWRITE) diff --git a/src/coreclr/utilcode/executableallocator.cpp b/src/coreclr/utilcode/executableallocator.cpp index 65802615fc6a..09a4801d2d5d 100644 --- a/src/coreclr/utilcode/executableallocator.cpp +++ b/src/coreclr/utilcode/executableallocator.cpp @@ -3,6 +3,7 @@ #include "pedecoder.h" #include "executableallocator.h" +#include #if USE_LAZY_PREFERRED_RANGE // Preferred region to allocate the code in. @@ -260,7 +261,7 @@ HRESULT ExecutableAllocator::StaticInitialize(FatalErrorHandler fatalErrorHandle #endif g_fatalErrorHandler = fatalErrorHandler; - g_isWXorXEnabled = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_EnableWriteXorExecute) != 0; + g_isWXorXEnabled = Configuration::GetKnobBooleanValue(W("System.Runtime.EnableWriteXorExecute"), CLRConfig::EXTERNAL_EnableWriteXorExecute); g_instance = new (nothrow) ExecutableAllocator(); if (g_instance == NULL) { diff --git a/src/coreclr/utilcode/hostimpl.cpp b/src/coreclr/utilcode/hostimpl.cpp index c1e4b53b065a..4ba20554c824 100644 --- a/src/coreclr/utilcode/hostimpl.cpp +++ b/src/coreclr/utilcode/hostimpl.cpp @@ -43,10 +43,6 @@ DWORD ClrSleepEx(DWORD dwMilliseconds, BOOL bAlertable) LPVOID ClrVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) { -#ifdef FAILPOINTS_ENABLED - if (RFS_HashStack ()) - return NULL; -#endif return VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect); } diff --git a/src/coreclr/utilcode/ilformatter.cpp b/src/coreclr/utilcode/ilformatter.cpp index 9c8011dc666f..baf4f5b56c97 100644 --- a/src/coreclr/utilcode/ilformatter.cpp +++ b/src/coreclr/utilcode/ilformatter.cpp @@ -196,7 +196,7 @@ void ILFormatter::formatInstrArgs(OpInfo op, OpArgsVal arg, OutString* out, size _ASSERTE(curILOffset != INVALID_IL_OFFSET); size_t target = curILOffset + arg.i; setTarget(target, stackDepth()); - *out << "IL_"; out->hex(static_cast(target), 4, OutString::zeroFill); + *out << "IL_"; out->hex(static_cast(target), 4, OutString::zeroFill); } break; case InlineI8: out->hex(arg.i, 0, OutString::put0x); @@ -273,7 +273,7 @@ void ILFormatter::formatInstrArgs(OpInfo op, OpArgsVal arg, OutString* out, size for (i = 0; i < count; i++) { size_t target = curILOffset + GET_UNALIGNED_VAL32(&arg.switch_.targets[i]); setTarget(target, stackDepth()-1); - *out << "IL_"; out->hex(static_cast(target), 4, OutString::zeroFill); + *out << "IL_"; out->hex(static_cast(target), 4, OutString::zeroFill); *out << ' '; } } break; @@ -478,7 +478,7 @@ const BYTE* ILFormatter::formatStatement(const BYTE* instrPtr, OutString* out) { DO_BR: { size_t target = (instrPtr - start) + inlineArg.i; setTarget(target, stackDepth()); - result << "goto IL_"; result.hex(static_cast(target), 4, OutString::zeroFill); + result << "goto IL_"; result.hex(static_cast(target), 4, OutString::zeroFill); } goto DO_STMT; case CEE_BRFALSE_S: diff --git a/src/coreclr/utilcode/loaderheap.cpp b/src/coreclr/utilcode/loaderheap.cpp index 985df665be6f..252f7afb237e 100644 --- a/src/coreclr/utilcode/loaderheap.cpp +++ b/src/coreclr/utilcode/loaderheap.cpp @@ -76,7 +76,7 @@ void RangeList::InitBlock(RangeListBlock *b) Range *r = b->ranges; Range *rEnd = r + RANGE_COUNT; while (r < rEnd) - r++->id = NULL; + r++->id = (TADDR)NULL; b->next = NULL; } @@ -102,7 +102,7 @@ BOOL RangeList::AddRangeWorker(const BYTE *start, const BYTE *end, void *id) { while (r < rEnd) { - if (r->id == NULL) + if (r->id == (TADDR)NULL) { r->start = (TADDR)start; r->end = (TADDR)end; @@ -177,7 +177,7 @@ void RangeList::RemoveRangesWorker(void *id, const BYTE* start, const BYTE* end) while (r < rEnd) { - if (r->id != NULL) + if (r->id != (TADDR)NULL) { if (start != NULL) { @@ -188,12 +188,12 @@ void RangeList::RemoveRangesWorker(void *id, const BYTE* start, const BYTE* end) CONSISTENCY_CHECK_MSGF(r->end >= (TADDR)start && r->end <= (TADDR)end, ("r: %p start: %p end: %p", r, start, end)); - r->id = NULL; + r->id = (TADDR)NULL; } } else if (r->id == (TADDR)id) { - r->id = NULL; + r->id = (TADDR)NULL; } } @@ -249,7 +249,7 @@ BOOL RangeList::IsInRangeWorker(TADDR address, TADDR *pID /* = NULL */) { while (r < rEnd) { - if (r->id != NULL && + if (r->id != (TADDR)NULL && address >= r->start && address < r->end) { @@ -326,7 +326,7 @@ RangeList::RangeListBlock::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) for (i=0; iranges[i]); - if (range->id == NULL || range->start == NULL || range->end == NULL || + if (range->id == (TADDR)NULL || range->start == (TADDR)NULL || range->end == (TADDR)NULL || // just looking at the lower 4bytes is good enough on WIN64 range->start == BADFOOD || range->end == BADFOOD) { diff --git a/src/coreclr/utilcode/namespaceutil.cpp b/src/coreclr/utilcode/namespaceutil.cpp index 4596776fbb87..4ad2751798a1 100644 --- a/src/coreclr/utilcode/namespaceutil.cpp +++ b/src/coreclr/utilcode/namespaceutil.cpp @@ -529,7 +529,7 @@ bool ns::MakeAssemblyQualifiedName( // tr int iCopyMax = 0; _ASSERTE(pBuffer); - *pBuffer = NULL; + *pBuffer = W('\0'); if (szTypeName && *szTypeName != W('\0')) { diff --git a/src/coreclr/utilcode/opinfo.cpp b/src/coreclr/utilcode/opinfo.cpp index 0a2efdf28f1b..0dc1086b4090 100644 --- a/src/coreclr/utilcode/opinfo.cpp +++ b/src/coreclr/utilcode/opinfo.cpp @@ -97,7 +97,7 @@ const BYTE* OpInfo::fetch(const BYTE* instrPtr, OpArgsVal* args) { args->i8 = GET_UNALIGNED_VAL64(instrPtr); instrPtr +=8; break; case InlineR: { - __int64 d = GET_UNALIGNED_VAL64(instrPtr); instrPtr +=8; + int64_t d = GET_UNALIGNED_VAL64(instrPtr); instrPtr +=8; args->r = *((double*) (&d)); } break; case InlineSwitch: diff --git a/src/coreclr/utilcode/outstring.cpp b/src/coreclr/utilcode/outstring.cpp index a6b345fe7e66..8962bd48d375 100644 --- a/src/coreclr/utilcode/outstring.cpp +++ b/src/coreclr/utilcode/outstring.cpp @@ -119,7 +119,7 @@ OutString& OutString::dec(int i, size_t minWidth) { } /*****************************************************************/ -OutString& OutString::hex(unsigned __int64 i, int minWidth, unsigned flags) { +OutString& OutString::hex(uint64_t i, int minWidth, unsigned flags) { unsigned hi = unsigned(i >> 32); unsigned low = unsigned(i); diff --git a/src/coreclr/utilcode/pedecoder.cpp b/src/coreclr/utilcode/pedecoder.cpp index ee92bfaeedbf..8aae56853d3a 100644 --- a/src/coreclr/utilcode/pedecoder.cpp +++ b/src/coreclr/utilcode/pedecoder.cpp @@ -35,8 +35,6 @@ CHECK PEDecoder::CheckFormat() const if (IsILOnly()) CHECK(CheckILOnly()); - - CHECK(CheckWillCreateGuardPage()); } } @@ -573,7 +571,7 @@ CHECK PEDecoder::CheckOffset(COUNT_T fileOffset, IsNullOK ok) const } CONTRACT_CHECK_END; - if (fileOffset == NULL) + if (fileOffset == 0) CHECK_MSG(ok == NULL_OK, "Null pointer illegal"); else { @@ -842,7 +840,7 @@ TADDR PEDecoder::GetRvaData(RVA rva, IsNullOK ok /*= NULL_NOT_OK*/) const CONTRACT_END; if ((rva == 0)&&(ok == NULL_NOT_OK)) - RETURN NULL; + RETURN (TADDR)NULL; RVA offset; if (IsMapped()) @@ -869,7 +867,7 @@ RVA PEDecoder::GetDataRva(const TADDR data) const } CONTRACT_END; - if (data == NULL) + if (data == (TADDR)NULL) RETURN 0; COUNT_T offset = (COUNT_T) (data - m_base); @@ -917,7 +915,7 @@ TADDR PEDecoder::GetOffsetData(COUNT_T fileOffset, IsNullOK ok /*= NULL_NOT_OK*/ CONTRACT_END; if ((fileOffset == 0)&&(ok == NULL_NOT_OK)) - RETURN NULL; + RETURN (TADDR)NULL; RETURN GetRvaData(OffsetToRva(fileOffset)); } @@ -1085,7 +1083,7 @@ CHECK PEDecoder::CheckCorHeader() const COUNT_T ctMD = (COUNT_T)VAL32(pDirMD->Size); TADDR pcMD = (TADDR)GetDirectoryData(pDirMD); - if(pcMD != NULL) + if(pcMD != (TADDR)NULL) { // Storage signature checks CHECK(ctMD >= sizeof(STORAGESIGNATURE)); @@ -2435,44 +2433,6 @@ PTR_CVOID PEDecoder::GetNativeManifestMetadata(COUNT_T *pSize) const RETURN dac_cast(GetDirectoryData(pDir)); } -// Get the SizeOfStackReserve and SizeOfStackCommit from the PE file that was used to create -// the calling process (.exe file). -void PEDecoder::GetEXEStackSizes(SIZE_T *PE_SizeOfStackReserve, SIZE_T *PE_SizeOfStackCommit) const -{ - CONTRACTL { - PRECONDITION(!IsDll()); // This routine should only be called for EXE files. - NOTHROW; - GC_NOTRIGGER; - } CONTRACTL_END; - - * PE_SizeOfStackReserve = GetSizeOfStackReserve(); - * PE_SizeOfStackCommit = GetSizeOfStackCommit(); -} - -CHECK PEDecoder::CheckWillCreateGuardPage() const -{ - CONTRACT_CHECK - { - PRECONDITION(CheckNTHeaders()); - NOTHROW; - GC_NOTRIGGER; - } - CONTRACT_CHECK_END; - - if (!IsDll()) - { - SIZE_T sizeReservedStack = 0; - SIZE_T sizeCommittedStack = 0; - - GetEXEStackSizes(&sizeReservedStack, &sizeCommittedStack); - - CHECK(ThreadWillCreateGuardPage(sizeReservedStack, sizeCommittedStack)); - - } - - CHECK_OK; -} - BOOL PEDecoder::HasNativeEntryPoint() const { CONTRACTL { diff --git a/src/coreclr/utilcode/prettyprintsig.cpp b/src/coreclr/utilcode/prettyprintsig.cpp index cfd9c917295f..59f6e88c26df 100644 --- a/src/coreclr/utilcode/prettyprintsig.cpp +++ b/src/coreclr/utilcode/prettyprintsig.cpp @@ -179,7 +179,7 @@ static PCCOR_SIGNATURE PrettyPrintType( const WCHAR * str; WCHAR rcname[MAX_CLASS_NAME]; HRESULT hr; - unsigned __int8 elt = *typePtr++; + uint8_t elt = *typePtr++; PCCOR_SIGNATURE typeEnd = typePtr + typeLen; switch(elt) @@ -583,7 +583,7 @@ static HRESULT PrettyPrintTypeA( HRESULT hr; // A result. PCCOR_SIGNATURE typeEnd = typePtr + typeLen; // End of the signature. - unsigned __int8 elt = *typePtr++; + uint8_t elt = *typePtr++; switch(elt) { case ELEMENT_TYPE_VOID: diff --git a/src/coreclr/utilcode/sstring.cpp b/src/coreclr/utilcode/sstring.cpp index d87efd8e10f0..1c7cab4c2c2b 100644 --- a/src/coreclr/utilcode/sstring.cpp +++ b/src/coreclr/utilcode/sstring.cpp @@ -10,7 +10,7 @@ #include "sstring.h" #include "ex.h" #include "holder.h" - +#include #if defined(_MSC_VER) #pragma inline_depth (25) @@ -87,7 +87,7 @@ static WCHAR MapChar(WCHAR wc, DWORD dwFlags) #ifdef SELF_NO_HOST toupper(wc); #else - PAL_ToUpperInvariant(wc); + minipal_toupper_invariant(wc); #endif } else @@ -97,7 +97,7 @@ static WCHAR MapChar(WCHAR wc, DWORD dwFlags) #ifdef SELF_NO_HOST tolower(wc); #else - PAL_ToLowerInvariant(wc); + minipal_tolower_invariant(wc); #endif } #endif // !TARGET_UNIX diff --git a/src/coreclr/utilcode/stresslog.cpp b/src/coreclr/utilcode/stresslog.cpp index 37abeb2cb92f..5e1fb037e144 100644 --- a/src/coreclr/utilcode/stresslog.cpp +++ b/src/coreclr/utilcode/stresslog.cpp @@ -34,7 +34,7 @@ thread_local bool t_triedToCreateThreadStressLog; variable-speed CPUs (for power management), this is not accurate, but may be good enough. */ -__forceinline __declspec(naked) unsigned __int64 getTimeStamp() { +__forceinline __declspec(naked) uint64_t getTimeStamp() { STATIC_CONTRACT_LEAF; __asm { @@ -44,7 +44,7 @@ __forceinline __declspec(naked) unsigned __int64 getTimeStamp() { } #else // HOST_X86 -unsigned __int64 getTimeStamp() { +uint64_t getTimeStamp() { STATIC_CONTRACT_LEAF; LARGE_INTEGER ret; @@ -64,14 +64,14 @@ unsigned __int64 getTimeStamp() { frequency of the RDTSC instruction, which is just the clock rate of the CPU. This can vary due to power management, so this is at best a rough approximation. */ -unsigned __int64 getTickFrequency() +uint64_t getTickFrequency() { // // At startup, the OS calculates the CPU clock frequency and makes it available // at HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0 // - unsigned __int64 hz = 0; + uint64_t hz = 0; HKEY hKey; if (ERROR_SUCCESS == RegOpenKeyExW( @@ -95,7 +95,7 @@ unsigned __int64 getTickFrequency() _ASSERTE(REG_DWORD == mhzType); _ASSERTE((DWORD)sizeof(mhz) == cbMhz); - hz = (unsigned __int64)mhz * 1000000; + hz = (uint64_t)mhz * 1000000; } RegCloseKey(hKey); @@ -111,7 +111,7 @@ unsigned __int64 getTickFrequency() /* Get the frequency corresponding to 'getTimeStamp'. For non-x86 architectures, this is just the performance counter frequency. */ -unsigned __int64 getTickFrequency() +uint64_t getTickFrequency() { LARGE_INTEGER ret; ZeroMemory(&ret, sizeof(LARGE_INTEGER)); @@ -124,7 +124,7 @@ unsigned __int64 getTickFrequency() #ifdef STRESS_LOG StressLog StressLog::theLog = { 0, 0, 0, 0, 0, 0, TLS_OUT_OF_INDEXES, 0, 0, 0 }; -const static unsigned __int64 RECYCLE_AGE = 0x40000000L; // after a billion cycles, we can discard old threads +const static uint64_t RECYCLE_AGE = 0x40000000L; // after a billion cycles, we can discard old threads /*********************************************************************************/ void StressLog::Enter(CRITSEC_COOKIE) { @@ -159,7 +159,7 @@ void ReplacePid(LPCWSTR original, LPWSTR replaced, size_t replacedLength) // append the string representation of the PID DWORD pid = GetCurrentProcessId(); WCHAR pidStr[20]; - _itow_s(pid, pidStr, ARRAY_SIZE(pidStr), 10); + FormatInteger(pidStr, ARRAY_SIZE(pidStr), "%u", pid); wcscat_s(replaced, replacedLength, pidStr); // append the rest of the filename @@ -483,6 +483,12 @@ ThreadStressLog* StressLog::CreateThreadStressLog() { // we fail. t_pCurrentThreadLog = NULL; } +#pragma warning(suppress: 4101) + PAL_CPP_CATCH_NON_DERIVED(const std::bad_alloc&, obj) + { + // Just leave on any exception. Note: can't goto or return from within EX_CATCH... + noFLSNow = TRUE; + } #pragma warning(suppress: 4101) PAL_CPP_CATCH_DERIVED(OutOfMemoryException, obj) { @@ -513,7 +519,7 @@ ThreadStressLog* StressLog::CreateThreadStressLogHelper() { // See if we can recycle a dead thread if (theLog.deadCount > 0) { - unsigned __int64 recycleStamp = getTimeStamp() - RECYCLE_AGE; + uint64_t recycleStamp = getTimeStamp() - RECYCLE_AGE; msgs = theLog.logs; //find out oldest dead ThreadStressLog in case we can't find one within //recycle age but can't create a new chunk @@ -963,7 +969,7 @@ void* StressLog::AllocMemoryMapped(size_t n) return nullptr; } -void* __cdecl ThreadStressLog::operator new(size_t n, const NoThrow&) NOEXCEPT +void* __cdecl ThreadStressLog::operator new(size_t n, const std::nothrow_t&) noexcept { if (StressLogChunk::s_memoryMapped) return StressLog::AllocMemoryMapped(n); diff --git a/src/coreclr/utilcode/util.cpp b/src/coreclr/utilcode/util.cpp index 1819f38e0a43..88317684fe88 100644 --- a/src/coreclr/utilcode/util.cpp +++ b/src/coreclr/utilcode/util.cpp @@ -32,6 +32,45 @@ bool g_arm64_atomics_present = false; #endif //!DACCESS_COMPILE +// Validate that the name used to load the JIT/GC is just a simple file name +// and does not contain something that could be used in a non-qualified path. +// For example, using the string "..\..\..\myjit.dll" we might attempt to +// load a JIT from the root of the drive. +// +// The minimal set of characters that we must check for and exclude are: +// On all platforms: +// '/' - (forward slash) +// On Windows: +// '\\' - (backslash) +// ':' - (colon) +// +// Returns false if we find any of these characters in 'pwzModuleName' +// Returns true if we reach the null terminator without encountering +// any of these characters. +// +bool ValidateModuleName(LPCWSTR pwzModuleName) +{ + LPCWSTR pCurChar = pwzModuleName; + wchar_t curChar; + do { + curChar = *pCurChar; + if (curChar == '/' +#ifdef TARGET_WINDOWS + || (curChar == '\\') || (curChar == ':') +#endif + ) + { + // Return false if we find any of these character in 'pwzJitName' + return false; + } + pCurChar++; + } while (curChar != 0); + + // Return true; we have reached the null terminator + // + return true; +} + //***************************************************************************** // Convert a string of hex digits into a hex value of the specified # of bytes. //***************************************************************************** diff --git a/src/coreclr/utilcode/util_nodependencies.cpp b/src/coreclr/utilcode/util_nodependencies.cpp index 39bf51a02a4a..c4b79ec832a4 100644 --- a/src/coreclr/utilcode/util_nodependencies.cpp +++ b/src/coreclr/utilcode/util_nodependencies.cpp @@ -730,45 +730,3 @@ void OutputDebugStringUtf8(LPCUTF8 utf8DebugMsg) OutputDebugStringW(wideDebugMsg); #endif // !TARGET_UNIX } - -BOOL ThreadWillCreateGuardPage(SIZE_T sizeReservedStack, SIZE_T sizeCommittedStack) -{ - // We need to make sure there will be a reserved but never committed page at the end - // of the stack. We do here the check NT does when it creates the user stack to decide - // if there is going to be a guard page. However, that is not enough, as if we only - // have a guard page, we have nothing to protect us from going pass it. Well, in - // fact, there is something that we will protect you, there are certain places - // (RTLUnwind) in NT that will check that the current frame is within stack limits. - // If we are not it will bomb out. We will also bomb out if we touch the hard guard - // page. - // - // For situation B, teb->StackLimit is at the beginning of the user stack (ie - // before updating StackLimit it checks if it was able to create a new guard page, - // in this case, it can't), which makes the check fail in RtlUnwind. - // - // Situation A [ Hard guard page | Guard page | user stack] - // - // Situation B [ Guard page | User stack ] - // - // Situation C [ User stack ( no room for guard page) ] - // - // Situation D (W9x) : Guard page or not, w9x has a 64k reserved region below - // the stack, we don't need any checks at all - // - // We really want to be in situation A all the time, so we add one more page - // to our requirements (we require guard page + hard guard) - - SYSTEM_INFO sysInfo; - ::GetSystemInfo(&sysInfo); - - // OS rounds up sizes the following way to decide if it marks a guard page - sizeReservedStack = ALIGN(sizeReservedStack, ((size_t)sysInfo.dwAllocationGranularity)); // Allocation granularity - sizeCommittedStack = ALIGN(sizeCommittedStack, ((size_t)sysInfo.dwPageSize)); // Page Size - - // OS wont create guard page, we can't execute managed code safely. - // We also have to make sure we have a 'hard' guard, thus we add another - // page to the memory we would need comitted. - // That is, the following code will check if sizeReservedStack is at least 2 pages - // more than sizeCommittedStack. - return (sizeReservedStack > sizeCommittedStack + ((size_t)sysInfo.dwPageSize)); -} // ThreadWillCreateGuardPage diff --git a/src/coreclr/vm/.vscode/c_cpp_properties.json b/src/coreclr/vm/.vscode/c_cpp_properties.json index 4192e236e354..ae1a019f9c05 100644 --- a/src/coreclr/vm/.vscode/c_cpp_properties.json +++ b/src/coreclr/vm/.vscode/c_cpp_properties.json @@ -22,7 +22,6 @@ ], "defines": [ "HOST_AMD64", - "_BLD_CLR", "_CRT_SECURE_NO_WARNINGS", "_DBG", "_SECURE_SCL=0", diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 345d5ac35f00..f60713ef587e 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -103,7 +103,6 @@ set(VM_SOURCES_DAC_AND_WKS_COMMON peassembly.cpp peimage.cpp perfmap.cpp - perfinfo.cpp pgo.cpp precode.cpp prestub.cpp @@ -206,7 +205,6 @@ set(VM_HEADERS_DAC_AND_WKS_COMMON peimagelayout.h peimagelayout.inl perfmap.h - perfinfo.h pgo.h precode.h rejit.h @@ -391,6 +389,7 @@ set(VM_HEADERS_WKS callhelpers.h callsiteinspect.h callconvbuilder.hpp + cdacoffsets.h ceemain.h clrconfignative.h clrex.h diff --git a/src/coreclr/vm/amd64/Context.S b/src/coreclr/vm/amd64/Context.S index 0721c45f5672..1eda47f0f9dc 100644 --- a/src/coreclr/vm/amd64/Context.S +++ b/src/coreclr/vm/amd64/Context.S @@ -51,8 +51,9 @@ NESTED_ENTRY ClrRestoreNonvolatileContextWorker, _TEXT, NoHandler // exception handling, iret and ret can't be used because their shadow stack enforcement would not allow that transition, // and using them would require writing to the shadow stack, which is not preferable. Instead, iret is partially // simulated. + mov rax, [r10 + OFFSETOF__CONTEXT__Rip] mov rsp, [r10 + OFFSETOF__CONTEXT__Rsp] - jmp qword ptr [r10 + OFFSETOF__CONTEXT__Rip] + jmp rax Done_Restore_CONTEXT_CONTROL: // The function was not asked to restore the control registers so we return back to the caller diff --git a/src/coreclr/vm/amd64/Context.asm b/src/coreclr/vm/amd64/Context.asm index a7165983cf4f..a2dbbda0b309 100644 --- a/src/coreclr/vm/amd64/Context.asm +++ b/src/coreclr/vm/amd64/Context.asm @@ -63,8 +63,9 @@ NESTED_ENTRY ClrRestoreNonvolatileContextWorker, _TEXT mov eax, [r10 + OFFSETOF__CONTEXT__EFlags] push rax popfq + mov rax, [r10 + OFFSETOF__CONTEXT__Rip] mov rsp, [r10 + OFFSETOF__CONTEXT__Rsp] - jmp qword ptr [r10 + OFFSETOF__CONTEXT__Rip] + jmp rax Done_Restore_CONTEXT_CONTROL: ; The function was not asked to restore the control registers so we return back to the caller diff --git a/src/coreclr/vm/amd64/RedirectedHandledJITCase.asm b/src/coreclr/vm/amd64/RedirectedHandledJITCase.asm index 61146cc6fbe5..4aeb705922ab 100644 --- a/src/coreclr/vm/amd64/RedirectedHandledJITCase.asm +++ b/src/coreclr/vm/amd64/RedirectedHandledJITCase.asm @@ -217,7 +217,8 @@ NESTED_ENTRY ApcActivationCallbackStub, _TEXT, FixRedirectContextHandler .errnz REDIRECTSTUB_ESTABLISHER_OFFSET_RBP, REDIRECTSTUB_ESTABLISHER_OFFSET_RBP has changed - update asm stubs END_PROLOGUE - ; Save the pointer to the interrupted context on the stack for the stack walker + ; Save a copy of the redirect CONTEXT*. + ; This is needed for the debugger to unwind the stack. mov rax, [rcx + OFFSETOF__APC_CALLBACK_DATA__ContextRecord] mov [rbp + 20h], rax .errnz REDIRECTSTUB_RBP_OFFSET_CONTEXT - 20h, REDIRECTSTUB_RBP_OFFSET_CONTEXT has changed - update asm stubs diff --git a/src/coreclr/vm/amd64/asmconstants.h b/src/coreclr/vm/amd64/asmconstants.h index 47cca560d7bb..b51088a6b479 100644 --- a/src/coreclr/vm/amd64/asmconstants.h +++ b/src/coreclr/vm/amd64/asmconstants.h @@ -98,14 +98,6 @@ ASMCONSTANTS_C_ASSERT(SIZEOF__ComPrestubMethodFrame ASMCONSTANTS_C_ASSERT(SIZEOF__ComMethodFrame == sizeof(ComMethodFrame)); -#define OFFSETOF__ComPlusCallMethodDesc__m_pComPlusCallInfo DBG_FRE(0x30, 0x08) -ASMCONSTANTS_C_ASSERT(OFFSETOF__ComPlusCallMethodDesc__m_pComPlusCallInfo - == offsetof(ComPlusCallMethodDesc, m_pComPlusCallInfo)); - -#define OFFSETOF__ComPlusCallInfo__m_pILStub 0x0 -ASMCONSTANTS_C_ASSERT(OFFSETOF__ComPlusCallInfo__m_pILStub - == offsetof(ComPlusCallInfo, m_pILStub)); - #endif // FEATURE_COMINTEROP #define OFFSETOF__Thread__m_fPreemptiveGCDisabled 0x04 @@ -119,10 +111,10 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_pFrame #define Thread_m_pFrame OFFSETOF__Thread__m_pFrame -#define OFFSET__Thread__m_alloc_context__alloc_ptr 0x50 +#define OFFSET__Thread__m_alloc_context__alloc_ptr 0x48 ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_ptr == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_ptr)); -#define OFFSET__Thread__m_alloc_context__alloc_limit 0x58 +#define OFFSET__Thread__m_alloc_context__alloc_limit 0x50 ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_limit == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_limit)); #define OFFSETOF__gc_alloc_context__alloc_ptr 0x0 @@ -278,9 +270,6 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__LazyMachState__m_CaptureRip ASMCONSTANTS_C_ASSERT(OFFSETOF__LazyMachState__m_CaptureRsp == offsetof(LazyMachState, m_CaptureRsp)); -#define OFFSETOF__MethodDesc__m_wFlags DBG_FRE(0x2E, 0x06) -ASMCONSTANTS_C_ASSERT(OFFSETOF__MethodDesc__m_wFlags == offsetof(MethodDesc, m_wFlags)); - #define OFFSETOF__VASigCookie__pNDirectILStub 0x8 ASMCONSTANTS_C_ASSERT(OFFSETOF__VASigCookie__pNDirectILStub == offsetof(VASigCookie, pNDirectILStub)); @@ -504,19 +493,19 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__StringObject__m_StringLength ASMCONSTANTS_C_ASSERT(OFFSETOF__InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum)); -#define OFFSETOF__InlinedCallFrame__m_pCallSiteSP 0x20 +#define OFFSETOF__InlinedCallFrame__m_pCallSiteSP 0x18 ASMCONSTANTS_C_ASSERT(OFFSETOF__InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP)); -#define OFFSETOF__InlinedCallFrame__m_pCallerReturnAddress 0x28 +#define OFFSETOF__InlinedCallFrame__m_pCallerReturnAddress 0x20 ASMCONSTANTS_C_ASSERT(OFFSETOF__InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress)); -#define OFFSETOF__InlinedCallFrame__m_pCalleeSavedFP 0x30 +#define OFFSETOF__InlinedCallFrame__m_pCalleeSavedFP 0x28 ASMCONSTANTS_C_ASSERT(OFFSETOF__InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP)); -#define OFFSETOF__InlinedCallFrame__m_pThread 0x38 +#define OFFSETOF__InlinedCallFrame__m_pThread 0x30 ASMCONSTANTS_C_ASSERT(OFFSETOF__InlinedCallFrame__m_pThread == offsetof(InlinedCallFrame, m_pThread)); diff --git a/src/coreclr/vm/amd64/cgenamd64.cpp b/src/coreclr/vm/amd64/cgenamd64.cpp index 8e136612c8c8..91982948b8b7 100644 --- a/src/coreclr/vm/amd64/cgenamd64.cpp +++ b/src/coreclr/vm/amd64/cgenamd64.cpp @@ -418,7 +418,7 @@ BOOL GetAnyThunkTarget (CONTEXT *pctx, TADDR *pTarget, TADDR *pTargetMethodDesc) { TADDR pThunk = GetIP(pctx); - *pTargetMethodDesc = NULL; + *pTargetMethodDesc = (TADDR)NULL; // // Check for something generated by emitJump. @@ -652,7 +652,7 @@ INT32 rel32UsingJumpStub(INT32 UNALIGNED * pRel32, PCODE target, MethodDesc *pMe (BYTE *)hiAddr, pLoaderAllocator, /* throwOnOutOfMemoryWithinRange */ false); - if (jumpStubAddr == NULL) + if (jumpStubAddr == (PCODE)NULL) { if (!throwOnOutOfMemoryWithinRange) return 0; diff --git a/src/coreclr/vm/amd64/cgencpu.h b/src/coreclr/vm/amd64/cgencpu.h index 5c6b3cf3c4b2..08fb63d44e82 100644 --- a/src/coreclr/vm/amd64/cgencpu.h +++ b/src/coreclr/vm/amd64/cgencpu.h @@ -504,7 +504,7 @@ inline PCODE decodeBackToBackJump(PCODE pCode) if (isJumpRel64(pCode)) return decodeJump64(pCode); else - return NULL; + return (PCODE)0; } extern "C" void setFPReturn(int fpSize, INT64 retVal); diff --git a/src/coreclr/vm/amd64/excepamd64.cpp b/src/coreclr/vm/amd64/excepamd64.cpp index d155ceecc5a3..282a84c7d788 100644 --- a/src/coreclr/vm/amd64/excepamd64.cpp +++ b/src/coreclr/vm/amd64/excepamd64.cpp @@ -200,7 +200,7 @@ RtlVirtualUnwind_Worker ( BOOL InEpilogue = FALSE; BOOL HasManagedBreakpoint = FALSE; BOOL HasUnmanagedBreakpoint = FALSE; - UCHAR TempOpcode = NULL; + UCHAR TempOpcode = 0; PUCHAR NextByte; ULONG CurrentOffset; ULONG FrameRegister; diff --git a/src/coreclr/vm/amd64/gmscpu.h b/src/coreclr/vm/amd64/gmscpu.h index 4154fd995d1c..411f1cf0c71b 100644 --- a/src/coreclr/vm/amd64/gmscpu.h +++ b/src/coreclr/vm/amd64/gmscpu.h @@ -34,7 +34,7 @@ struct MachState INDEBUG(memset((void*)this, 0xCC, sizeof(MachState));) } - bool isValid() { LIMITED_METHOD_DAC_CONTRACT; _ASSERTE(dac_cast(_pRetAddr) != INVALID_POINTER_CC); return(_pRetAddr != 0); } + bool isValid() { LIMITED_METHOD_DAC_CONTRACT; _ASSERTE(dac_cast(_pRetAddr) != INVALID_POINTER_CC); return(_pRetAddr != nullptr); } TADDR* pRetAddr() { LIMITED_METHOD_DAC_CONTRACT; _ASSERTE(isValid()); return(_pRetAddr); } TADDR GetRetAddr() { LIMITED_METHOD_DAC_CONTRACT; _ASSERTE(isValid()); return *_pRetAddr; } #ifndef DACCESS_COMPILE diff --git a/src/coreclr/vm/amd64/virtualcallstubcpu.hpp b/src/coreclr/vm/amd64/virtualcallstubcpu.hpp index 7afd9228fcf4..7388c4549a24 100644 --- a/src/coreclr/vm/amd64/virtualcallstubcpu.hpp +++ b/src/coreclr/vm/amd64/virtualcallstubcpu.hpp @@ -707,7 +707,7 @@ void ResolveHolder::InitializeStatic() resolveInit.part1 [ 9] = 0xC2; resolveInit.part1 [10] = 0x48; resolveInit.part1 [11] = 0x35; -// Review truncation from unsigned __int64 to UINT32 of a constant value. +// Review truncation from uint64_t to UINT32 of a constant value. #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable:4305 4309) diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 07f24361dccc..489f2ebc2280 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1158,6 +1158,13 @@ void SystemDomain::Init() // Finish loading CoreLib now. m_pSystemAssembly->GetDomainAssembly()->EnsureActive(); + + // Set AwareLock's offset of the holding OS thread ID field into ThreadBlockingInfo's static field. That can be used + // when doing managed debugging to get the OS ID of the thread holding the lock. The offset is currently not zero, and + // zero is used in managed code to determine if the static variable has been initialized. + _ASSERTE(AwareLock::GetOffsetOfHoldingOSThreadId() != 0); + CoreLibBinder::GetField(FIELD__THREAD_BLOCKING_INFO__OFFSET_OF_LOCK_OWNER_OS_THREAD_ID) + ->SetStaticValue32(AwareLock::GetOffsetOfHoldingOSThreadId()); } #ifdef _DEBUG @@ -3854,8 +3861,6 @@ AppDomain::RaiseUnhandledExceptionEvent(OBJECTREF *pThrowable, BOOL isTerminatin _ASSERTE(pThrowable != NULL && IsProtectedByGCFrame(pThrowable)); - _ASSERTE(this == GetThread()->GetDomain()); - OBJECTREF orDelegate = CoreLibBinder::GetField(FIELD__APPCONTEXT__UNHANDLED_EXCEPTION)->GetStaticOBJECTREF(); if (orDelegate == NULL) return FALSE; @@ -4528,13 +4533,6 @@ AppDomain::RaiseAssemblyResolveEvent( } GCPROTECT_END(); - if (pAssembly != NULL) - { - // Check that the public key token matches the one specified in the spec - // MatchPublicKeys throws as appropriate - pSpec->MatchPublicKeys(pAssembly); - } - RETURN pAssembly; } // AppDomain::RaiseAssemblyResolveEvent diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index 1c400154c760..e72080f914e9 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -1038,6 +1038,12 @@ class BaseDomain return ::CreatePinningHandle(m_handleStore, object); } + OBJECTHANDLE CreateWeakInteriorHandle(OBJECTREF object, void* pInteriorPointerLocation) + { + WRAPPER_NO_CONTRACT; + return ::CreateWeakInteriorHandle(m_handleStore, object, pInteriorPointerLocation); + } + OBJECTHANDLE CreateSizedRefHandle(OBJECTREF object) { WRAPPER_NO_CONTRACT; @@ -1534,7 +1540,7 @@ class AppDomain : public BaseDomain virtual PTR_AppDomain AsAppDomain() { LIMITED_METHOD_CONTRACT; return dac_cast(this); } OBJECTREF GetRawExposedObject() { LIMITED_METHOD_CONTRACT; return NULL; } - OBJECTHANDLE GetRawExposedObjectHandleForDebugger() { LIMITED_METHOD_DAC_CONTRACT; return NULL; } + OBJECTHANDLE GetRawExposedObjectHandleForDebugger() { LIMITED_METHOD_DAC_CONTRACT; return (OBJECTHANDLE)NULL; } #ifndef DACCESS_COMPILE PTR_NativeImage GetNativeImage(LPCUTF8 compositeFileName); diff --git a/src/coreclr/vm/argslot.h b/src/coreclr/vm/argslot.h index d24fe656d629..1cf6bad8dbde 100644 --- a/src/coreclr/vm/argslot.h +++ b/src/coreclr/vm/argslot.h @@ -13,7 +13,7 @@ // The ARG_SLOT must be big enough to represent all pointer and basic types (except for 80-bit fp values). // So, it's guaranteed to be at least 64-bit. -typedef unsigned __int64 ARG_SLOT; +typedef uint64_t ARG_SLOT; #define SIZEOF_ARG_SLOT 8 #if BIGENDIAN diff --git a/src/coreclr/vm/arm/asmconstants.h b/src/coreclr/vm/arm/asmconstants.h index 5c92427008bb..7d6106104fbf 100644 --- a/src/coreclr/vm/arm/asmconstants.h +++ b/src/coreclr/vm/arm/asmconstants.h @@ -114,13 +114,6 @@ ASMCONSTANTS_C_ASSERT(SIZEOF__FloatArgumentRegisters == sizeof(FloatArgumentRegi #define ASM_ENREGISTERED_RETURNTYPE_MAXSIZE 0x20 ASMCONSTANTS_C_ASSERT(ASM_ENREGISTERED_RETURNTYPE_MAXSIZE == ENREGISTERED_RETURNTYPE_MAXSIZE) - -#define MethodDesc__m_wFlags DBG_FRE(0x1A, 0x06) -ASMCONSTANTS_C_ASSERT(MethodDesc__m_wFlags == offsetof(MethodDesc, m_wFlags)) - -#define MethodDesc__mdcClassification 0x7 -ASMCONSTANTS_C_ASSERT(MethodDesc__mdcClassification == mdcClassification) - #ifdef FEATURE_COMINTEROP #define Stub__m_pCode DBG_FRE(0x10, 0x0c) diff --git a/src/coreclr/vm/arm/stubs.cpp b/src/coreclr/vm/arm/stubs.cpp index 5f8e3bf445e7..ab18568159e0 100644 --- a/src/coreclr/vm/arm/stubs.cpp +++ b/src/coreclr/vm/arm/stubs.cpp @@ -98,7 +98,7 @@ class ThumbCondJump : public InstructionFormat //Encoding 1|0|1|1|op|0|i|1|imm5|Rn //op = Bit3(variation) //Rn = Bits2-0(variation) - virtual VOID EmitInstruction(UINT refsize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refsize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { LIMITED_METHOD_CONTRACT @@ -138,7 +138,7 @@ class ThumbNearJump : public InstructionFormat return 0; } - virtual VOID EmitInstruction(UINT refsize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT cond, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refsize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT cond, BYTE *pDataBuffer) { LIMITED_METHOD_CONTRACT diff --git a/src/coreclr/vm/arm64/asmconstants.h b/src/coreclr/vm/arm64/asmconstants.h index 262fa6860df7..c0d6012aab9e 100644 --- a/src/coreclr/vm/arm64/asmconstants.h +++ b/src/coreclr/vm/arm64/asmconstants.h @@ -157,6 +157,9 @@ ASMCONSTANTS_C_ASSERT(UnmanagedToManagedFrame__m_pvDatum == offsetof(UnmanagedTo #endif // FEATURE_COMINTEROP +#ifdef FEATURE_SPECIAL_USER_MODE_APC +#define OFFSETOF__APC_CALLBACK_DATA__ContextRecord 0x8 +#endif #define REDIRECTSTUB_SP_OFFSET_CONTEXT 0 @@ -201,16 +204,16 @@ ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next)) #define InlinedCallFrame__m_Datum 0x10 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum)) -#define InlinedCallFrame__m_pCallSiteSP 0x20 +#define InlinedCallFrame__m_pCallSiteSP 0x18 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP)) -#define InlinedCallFrame__m_pCallerReturnAddress 0x28 +#define InlinedCallFrame__m_pCallerReturnAddress 0x20 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress)) -#define InlinedCallFrame__m_pCalleeSavedFP 0x30 +#define InlinedCallFrame__m_pCalleeSavedFP 0x28 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP)) -#define InlinedCallFrame__m_pThread 0x38 +#define InlinedCallFrame__m_pThread 0x30 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pThread == offsetof(InlinedCallFrame, m_pThread)) #define FixupPrecodeData__Target 0x00 diff --git a/src/coreclr/vm/arm64/asmhelpers.asm b/src/coreclr/vm/arm64/asmhelpers.asm index bc88d15ee330..ec2887960718 100644 --- a/src/coreclr/vm/arm64/asmhelpers.asm +++ b/src/coreclr/vm/arm64/asmhelpers.asm @@ -1174,5 +1174,39 @@ __HelperNakedFuncName SETS "$helper":CC:"Naked" br x9 LEAF_END +#ifdef FEATURE_SPECIAL_USER_MODE_APC + + IMPORT |?ApcActivationCallback@Thread@@CAX_K@Z| + + ; extern "C" void NTAPI ApcActivationCallbackStub(ULONG_PTR Parameter); + NESTED_ENTRY ApcActivationCallbackStub + + PROLOG_SAVE_REG_PAIR fp, lr, #-16! + PROLOG_STACK_ALLOC 16 ; stack slot for CONTEXT* and padding + + ;REDIRECTSTUB_SP_OFFSET_CONTEXT is defined in asmconstants.h and is used in GetCONTEXTFromRedirectedStubStackFrame + ;If CONTEXT is not saved at 0 offset from SP it must be changed as well. + ASSERT REDIRECTSTUB_SP_OFFSET_CONTEXT == 0 + + ; Save a copy of the redirect CONTEXT*. + ; This is needed for the debugger to unwind the stack. + ldr x17, [x0, OFFSETOF__APC_CALLBACK_DATA__ContextRecord] + str x17, [sp] + + bl |?ApcActivationCallback@Thread@@CAX_K@Z| + + EPILOG_STACK_FREE 16 ; undo stack slot for CONTEXT* and padding + EPILOG_RESTORE_REG_PAIR fp, lr, #16! + EPILOG_RETURN + +; Put a label here to tell the debugger where the end of this function is. + PATCH_LABEL ApcActivationCallbackStubEnd + EXPORT ApcActivationCallbackStubEnd + + NESTED_END + +#endif ; FEATURE_SPECIAL_USER_MODE_APC + + ; Must be at very end of file END diff --git a/src/coreclr/vm/arm64/cgencpu.h b/src/coreclr/vm/arm64/cgencpu.h index 700221aa8696..045598ed9718 100644 --- a/src/coreclr/vm/arm64/cgencpu.h +++ b/src/coreclr/vm/arm64/cgencpu.h @@ -27,7 +27,9 @@ CALLEE_SAVED_REGISTER(X23) \ CALLEE_SAVED_REGISTER(X24) \ CALLEE_SAVED_REGISTER(X25) \ - CALLEE_SAVED_REGISTER(X26) + CALLEE_SAVED_REGISTER(X26) \ + CALLEE_SAVED_REGISTER(X27) \ + CALLEE_SAVED_REGISTER(X28) #define ENUM_FP_CALLEE_SAVED_REGISTERS() \ CALLEE_SAVED_REGISTER(V[8].Low) \ diff --git a/src/coreclr/vm/arm64/stubs.cpp b/src/coreclr/vm/arm64/stubs.cpp index 623938dfba61..ead7a01e975c 100644 --- a/src/coreclr/vm/arm64/stubs.cpp +++ b/src/coreclr/vm/arm64/stubs.cpp @@ -58,7 +58,7 @@ class ConditionalBranchInstructionFormat : public InstructionFormat // Encoding 0|1|0|1|0|1|0|0|imm19|0|cond // cond = Bits3-0(variation) // imm19 = bits19-0(fixedUpReference/4), will be SignExtended - virtual VOID EmitInstruction(UINT refSize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refSize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { LIMITED_METHOD_CONTRACT; @@ -148,14 +148,14 @@ class BranchInstructionFormat : public InstructionFormat } } - virtual VOID EmitInstruction(UINT refSize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refSize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { LIMITED_METHOD_CONTRACT; if (IsIndirect(variationCode)) { _ASSERTE(((UINT_PTR)pDataBuffer & 7) == 0); - __int64 dataOffset = pDataBuffer - pOutBufferRW; + int64_t dataOffset = pDataBuffer - pOutBufferRW; if (dataOffset < -1048576 || dataOffset > 1048572) COMPlusThrow(kNotSupportedException); @@ -177,13 +177,13 @@ class BranchInstructionFormat : public InstructionFormat } - *((__int64*)pDataBuffer) = fixedUpReference + (__int64)pOutBufferRX; + *((int64_t*)pDataBuffer) = fixedUpReference + (int64_t)pOutBufferRX; } else { _ASSERTE(((UINT_PTR)pDataBuffer & 7) == 0); - __int64 dataOffset = pDataBuffer - pOutBufferRW; + int64_t dataOffset = pDataBuffer - pOutBufferRW; if (dataOffset < -1048576 || dataOffset > 1048572) COMPlusThrow(kNotSupportedException); @@ -202,9 +202,9 @@ class BranchInstructionFormat : public InstructionFormat *((DWORD*)(pOutBufferRW+4)) = 0xD61F0200; // br x16 } - if (!ClrSafeInt<__int64>::addition(fixedUpReference, (__int64)pOutBufferRX, fixedUpReference)) + if (!ClrSafeInt::addition(fixedUpReference, (int64_t)pOutBufferRX, fixedUpReference)) COMPlusThrowArithmetic(); - *((__int64*)pDataBuffer) = fixedUpReference; + *((int64_t*)pDataBuffer) = fixedUpReference; } } @@ -239,7 +239,7 @@ class LoadFromLabelInstructionFormat : public InstructionFormat return fExternal; } - virtual VOID EmitInstruction(UINT refSize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refSize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { LIMITED_METHOD_CONTRACT; // VariationCode is used to indicate the register the label is going to be loaded diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index 7f156f991c30..73911ab8e56e 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -1426,9 +1426,8 @@ INT32 Assembly::ExecuteMainMethod(PTRARRAYREF *stringArgs, BOOL waitForOtherThre // Set the root assembly as the assembly that is containing the main method // The root assembly is used in the GetEntryAssembly method that on CoreCLR is used // to get the TargetFrameworkMoniker for the app - AppDomain * pDomain = pThread->GetDomain(); Assembly* pRootAssembly = pMeth->GetAssembly(); - pDomain->SetRootAssembly(pRootAssembly); + AppDomain::GetCurrentDomain()->SetRootAssembly(pRootAssembly); #ifdef FEATURE_READYTORUN { if (pRootAssembly->GetModule()->IsReadyToRun()) diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index bf549e77346b..b7fdcd6a21bf 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -280,7 +280,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssembl { #ifdef DEBUGGING_SUPPORTED // If we were given symbols, save a copy of them. - if (ptrSymbolArray != NULL) + if (ptrSymbolArray != 0) { PBYTE pSymbolArray = reinterpret_cast(ptrSymbolArray); pLoadedAssembly->GetModule()->SetSymbolBytes(pSymbolArray, (DWORD)cbSymbolArrayLength); @@ -1197,7 +1197,7 @@ extern "C" INT_PTR QCALLTYPE AssemblyNative_InitializeAssemblyLoadContext(INT_PT { QCALL_CONTRACT; - INT_PTR ptrNativeAssemblyBinder = NULL; + INT_PTR ptrNativeAssemblyBinder = 0; BEGIN_QCALL; @@ -1287,7 +1287,7 @@ extern "C" INT_PTR QCALLTYPE AssemblyNative_GetLoadContextForAssembly(QCall::Ass { QCALL_CONTRACT; - INT_PTR ptrManagedAssemblyLoadContext = NULL; + INT_PTR ptrManagedAssemblyLoadContext = 0; BEGIN_QCALL; diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index 6144f000a8e0..a4872b732097 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -295,55 +295,6 @@ void AssemblySpec::InitializeAssemblyNameRef(_In_ BINDER_SPACE::AssemblyName* as spec.AssemblyNameInit(assemblyNameRef); } - -// Check if the supplied assembly's public key matches up with the one in the Spec, if any -// Throws an appropriate exception in case of a mismatch -void AssemblySpec::MatchPublicKeys(Assembly *pAssembly) -{ - CONTRACTL - { - INSTANCE_CHECK; - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - // Check that the public keys are the same as in the AR. - if (!IsStrongNamed()) - return; - - const void *pbPublicKey; - DWORD cbPublicKey; - pbPublicKey = pAssembly->GetPublicKey(&cbPublicKey); - if (cbPublicKey == 0) - ThrowHR(FUSION_E_PRIVATE_ASM_DISALLOWED); - - if (IsAfPublicKey(m_dwFlags)) - { - if ((m_cbPublicKeyOrToken != cbPublicKey) || - memcmp(m_pbPublicKeyOrToken, pbPublicKey, m_cbPublicKeyOrToken)) - { - ThrowHR(FUSION_E_REF_DEF_MISMATCH); - } - } - else - { - // Ref has a token - StrongNameToken strongNameToken; - - IfFailThrow(StrongNameTokenFromPublicKey((BYTE*)pbPublicKey, - cbPublicKey, - &strongNameToken)); - - if ((m_cbPublicKeyOrToken != StrongNameToken::SIZEOF_TOKEN) || - memcmp(m_pbPublicKeyOrToken, &strongNameToken, StrongNameToken::SIZEOF_TOKEN)) - { - ThrowHR(FUSION_E_REF_DEF_MISMATCH); - } - } -} - Assembly *AssemblySpec::LoadAssembly(FileLoadLevel targetLevel, BOOL fThrowOnFileNotFound) { CONTRACTL diff --git a/src/coreclr/vm/assemblyspec.hpp b/src/coreclr/vm/assemblyspec.hpp index a39b71235971..23a7c96e6475 100644 --- a/src/coreclr/vm/assemblyspec.hpp +++ b/src/coreclr/vm/assemblyspec.hpp @@ -193,8 +193,6 @@ class AssemblySpec : public BaseAssemblySpec static void InitializeAssemblyNameRef(_In_ BINDER_SPACE::AssemblyName* assemblyName, _Out_ ASSEMBLYNAMEREF* assemblyNameRef); public: - void MatchPublicKeys(Assembly *pAssembly); - AppDomain *GetAppDomain() { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/baseassemblyspec.inl b/src/coreclr/vm/baseassemblyspec.inl index 125e31a592a9..31833695de6c 100644 --- a/src/coreclr/vm/baseassemblyspec.inl +++ b/src/coreclr/vm/baseassemblyspec.inl @@ -356,7 +356,7 @@ inline HRESULT BaseAssemblySpec::Init(mdToken tkAssemblyRef, NULL, // [OUT] Count of bytes in the public key or token. NULL, // [OUT] Hash Algorithm NULL, // [OUT] Buffer to fill with name. - NULL, // [IN] Size of buffer in wide chars. + 0, // [IN] Size of buffer in wide chars. &cchName, // [OUT] Actual # of wide chars in name. &sContext, // [OUT] Assembly MetaData. NULL)); // [OUT] Flags. @@ -380,7 +380,7 @@ inline HRESULT BaseAssemblySpec::Init(mdToken tkAssemblyRef, NULL, // [OUT] Pointer to the public key or token. NULL, // [OUT] Count of bytes in the public key or token. NULL, // [OUT] Buffer to fill with name. - NULL, // [IN] Size of buffer in wide chars. + 0, // [IN] Size of buffer in wide chars. &cchName, // [OUT] Actual # of wide chars in name. &sContext, // [OUT] Assembly MetaData. NULL, // [OUT] Hash blob. diff --git a/src/coreclr/vm/callcounting.cpp b/src/coreclr/vm/callcounting.cpp index a6577fd42de3..af48f0a79b7c 100644 --- a/src/coreclr/vm/callcounting.cpp +++ b/src/coreclr/vm/callcounting.cpp @@ -758,7 +758,7 @@ PCODE CallCountingManager::OnCallCountThresholdReached(TransitionBlock *transiti STATIC_CONTRACT_GC_TRIGGERS; STATIC_CONTRACT_MODE_COOPERATIVE; - PCODE codeEntryPoint = NULL; + PCODE codeEntryPoint = 0; BEGIN_PRESERVE_LAST_ERROR; @@ -925,7 +925,7 @@ void CallCountingManager::CompleteCallCounting() if (!activeCodeVersion.IsNull()) { PCODE activeNativeCode = activeCodeVersion.GetNativeCode(); - if (activeNativeCode != NULL) + if (activeNativeCode != 0) { methodDesc->SetCodeEntryPoint(activeNativeCode); break; diff --git a/src/coreclr/vm/callhelpers.h b/src/coreclr/vm/callhelpers.h index 77373075728e..f6dd105263b2 100644 --- a/src/coreclr/vm/callhelpers.h +++ b/src/coreclr/vm/callhelpers.h @@ -554,9 +554,9 @@ enum DispatchCallSimpleFlags DWORD __dwDispatchCallSimpleFlags = 0; \ #define PREPARE_NONVIRTUAL_CALLSITE(id) \ - static PCODE s_pAddr##id = NULL; \ + static PCODE s_pAddr##id = 0; \ PCODE __pSlot = VolatileLoad(&s_pAddr##id); \ - if ( __pSlot == NULL ) \ + if ( __pSlot == 0 ) \ { \ MethodDesc *pMeth = CoreLibBinder::GetMethod(id); \ _ASSERTE(pMeth); \ diff --git a/src/coreclr/vm/callingconvention.h b/src/coreclr/vm/callingconvention.h index 12b935996b1a..7ec2525d48ef 100644 --- a/src/coreclr/vm/callingconvention.h +++ b/src/coreclr/vm/callingconvention.h @@ -1692,17 +1692,7 @@ int ArgIteratorTemplate::GetNextOffset() } else { - MethodTable* pMethodTable = nullptr; - - if (!thValueType.IsTypeDesc()) - pMethodTable = thValueType.AsMethodTable(); - else - { - _ASSERTE(thValueType.IsNativeValueType()); - pMethodTable = thValueType.AsNativeValueType(); - } - _ASSERTE(pMethodTable != nullptr); - flags = MethodTable::GetLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); + flags = MethodTable::GetLoongArch64PassStructInRegisterFlags(thValueType); if (flags & STRUCT_HAS_FLOAT_FIELDS_MASK) { cFPRegs = (flags & STRUCT_FLOAT_FIELD_ONLY_TWO) ? 2 : 1; @@ -1816,17 +1806,7 @@ int ArgIteratorTemplate::GetNextOffset() } else { - MethodTable* pMethodTable = nullptr; - - if (!thValueType.IsTypeDesc()) - pMethodTable = thValueType.AsMethodTable(); - else - { - _ASSERTE(thValueType.IsNativeValueType()); - pMethodTable = thValueType.AsNativeValueType(); - } - _ASSERTE(pMethodTable != nullptr); - flags = MethodTable::GetRiscV64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); + flags = MethodTable::GetRiscV64PassStructInRegisterFlags(thValueType); if (flags & STRUCT_HAS_FLOAT_FIELDS_MASK) { cFPRegs = (flags & STRUCT_FLOAT_FIELD_ONLY_TWO) ? 2 : 1; @@ -2029,18 +2009,14 @@ void ArgIteratorTemplate::ComputeReturnFlags() if (size <= ENREGISTERED_RETURNTYPE_INTEGER_MAXSIZE) { assert(!thValueType.IsTypeDesc()); - - MethodTable *pMethodTable = thValueType.AsMethodTable(); - flags = (MethodTable::GetLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable) & 0xff) << RETURN_FP_SIZE_SHIFT; + flags = (MethodTable::GetLoongArch64PassStructInRegisterFlags(thValueType) & 0xff) << RETURN_FP_SIZE_SHIFT; break; } #elif defined(TARGET_RISCV64) if (size <= ENREGISTERED_RETURNTYPE_INTEGER_MAXSIZE) { assert(!thValueType.IsTypeDesc()); - - MethodTable *pMethodTable = thValueType.AsMethodTable(); - flags = (MethodTable::GetRiscV64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable) & 0xff) << RETURN_FP_SIZE_SHIFT; + flags = (MethodTable::GetRiscV64PassStructInRegisterFlags(thValueType) & 0xff) << RETURN_FP_SIZE_SHIFT; break; } #else diff --git a/src/coreclr/vm/cdacoffsets.h b/src/coreclr/vm/cdacoffsets.h new file mode 100644 index 000000000000..317ef41f7360 --- /dev/null +++ b/src/coreclr/vm/cdacoffsets.h @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef CDACOFFSETS_H__ +#define CDACOFFSETS_H__ + +// See data-descriptor.h +// +// If the offset of some field F in class C must be provided to cDAC, but the field is private, the +// class C should declare cdac_offsets as a friend: +// +// friend template struct cdac_offsets; +// +// and provide a specialization cdac_offsets with a constexpr size_t member providing the offset: +// +// template<> struct cdac_offsets { +// static constexpr size_t F_Offset = offsetof(C, F); +// }; +template +struct cdac_offsets +{ +}; + +#endif// CDACOFFSETS_H__ diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index 0696635e9027..76fe10e2be8d 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -1807,6 +1807,7 @@ void Module::AllocateMaps() m_TypeRefToMethodTableMap.dwCount = TYPEREF_MAP_INITIAL_SIZE; m_MemberRefMap.dwCount = MEMBERREF_MAP_INITIAL_SIZE; m_MethodDefToDescMap.dwCount = MEMBERDEF_MAP_INITIAL_SIZE; + m_ILCodeVersioningStateMap.dwCount = MEMBERDEF_MAP_INITIAL_SIZE; m_FieldDefToDescMap.dwCount = MEMBERDEF_MAP_INITIAL_SIZE; m_GenericParamToDescMap.dwCount = GENERICPARAM_MAP_INITIAL_SIZE; m_ManifestModuleReferencesMap.dwCount = ASSEMBLYREFERENCES_MAP_INITIAL_SIZE; @@ -1827,6 +1828,9 @@ void Module::AllocateMaps() // Get # MethodDefs m_MethodDefToDescMap.dwCount = pImport->GetCountWithTokenKind(mdtMethodDef)+1; + // IL code versions are relatively rare so keep small. + m_ILCodeVersioningStateMap.dwCount = 1; + // Get # FieldDefs m_FieldDefToDescMap.dwCount = pImport->GetCountWithTokenKind(mdtFieldDef)+1; @@ -1843,6 +1847,7 @@ void Module::AllocateMaps() nTotal += m_TypeRefToMethodTableMap.dwCount; nTotal += m_MemberRefMap.dwCount; nTotal += m_MethodDefToDescMap.dwCount; + nTotal += m_ILCodeVersioningStateMap.dwCount; nTotal += m_FieldDefToDescMap.dwCount; nTotal += m_GenericParamToDescMap.dwCount; nTotal += m_ManifestModuleReferencesMap.dwCount; @@ -1869,9 +1874,13 @@ void Module::AllocateMaps() m_MethodDefToDescMap.supportedFlags = METHOD_DEF_MAP_ALL_FLAGS; m_MethodDefToDescMap.pTable = &m_MemberRefMap.pTable[m_MemberRefMap.dwCount]; + m_ILCodeVersioningStateMap.pNext = NULL; + m_ILCodeVersioningStateMap.supportedFlags = METHOD_DEF_MAP_ALL_FLAGS; + m_ILCodeVersioningStateMap.pTable = &m_MethodDefToDescMap.pTable[m_MethodDefToDescMap.dwCount]; + m_FieldDefToDescMap.pNext = NULL; m_FieldDefToDescMap.supportedFlags = FIELD_DEF_MAP_ALL_FLAGS; - m_FieldDefToDescMap.pTable = &m_MethodDefToDescMap.pTable[m_MethodDefToDescMap.dwCount]; + m_FieldDefToDescMap.pTable = &m_ILCodeVersioningStateMap.pTable[m_ILCodeVersioningStateMap.dwCount]; m_GenericParamToDescMap.pNext = NULL; m_GenericParamToDescMap.supportedFlags = GENERIC_PARAM_MAP_ALL_FLAGS; @@ -2580,7 +2589,7 @@ TADDR Module::GetIL(DWORD target) SUPPORTS_DAC; if (target == 0) - return NULL; + return (TADDR)NULL; return m_pPEAssembly->GetIL(target); } @@ -3911,7 +3920,7 @@ void Module::FixupVTables() FillMemory(uMThunkMarshInfoWriterHolder.GetRW(), sizeof(UMThunkMarshInfo), 0); uMThunkMarshInfoWriterHolder.GetRW()->LoadTimeInit(pMD); - uMEntryThunkWriterHolder.GetRW()->LoadTimeInit(pUMEntryThunk, NULL, NULL, pUMThunkMarshInfo, pMD); + uMEntryThunkWriterHolder.GetRW()->LoadTimeInit(pUMEntryThunk, (PCODE)0, NULL, pUMThunkMarshInfo, pMD); SetTargetForVTableEntry(hInstThis, (BYTE **)&pPointers[iMethod], (BYTE *)pUMEntryThunk->GetCode()); @@ -4187,14 +4196,14 @@ BOOL Module::FixupNativeEntry(READYTORUN_IMPORT_SECTION* pSection, SIZE_T fixupI // Ensure that the compiler won't fetch the value twice SIZE_T fixup = VolatileLoadWithoutBarrier(fixupCell); - if (fixup == NULL) + if (fixup == 0) { PTR_DWORD pSignatures = dac_cast(GetReadyToRunImage()->GetRvaData(pSection->Signatures)); if (!LoadDynamicInfoEntry(this, pSignatures[fixupIndex], fixupCell, mayUsePrecompiledNDirectMethods)) return FALSE; - _ASSERTE(*fixupCell != NULL); + _ASSERTE(*fixupCell != 0); } return TRUE; @@ -4611,7 +4620,7 @@ TADDR ReflectionModule::GetIL(RVA il) // virtual #else // DACCESS_COMPILE SUPPORTS_DAC; DacNotImpl(); - return NULL; + return (TADDR)NULL; #endif // DACCESS_COMPILE } @@ -4807,7 +4816,7 @@ VASigCookie *Module::GetVASigCookieWorker(Module* pDefiningModule, Module* pLoad INJECT_FAULT(COMPlusThrowOM()); } CONTRACT_END; - + VASigCookieBlock *pBlock; VASigCookie *pCookie; @@ -4855,7 +4864,7 @@ VASigCookie *Module::GetVASigCookieWorker(Module* pDefiningModule, Module* pLoad } } } - + if (!pCookie) { // If not, time to make a new one. @@ -4905,13 +4914,13 @@ VASigCookie *Module::GetVASigCookieWorker(Module* pDefiningModule, Module* pLoad // Now, fill in the new cookie (assuming we had enough memory to create one.) pCookie->pModule = pDefiningModule; - pCookie->pNDirectILStub = NULL; + pCookie->pNDirectILStub = 0; pCookie->sizeOfArgs = sizeOfArgs; pCookie->signature = vaSignature; pCookie->pLoaderModule = pLoaderModule; AllocMemTracker amt; - + if (classInstCount != 0) { TypeHandle* pClassInst = (TypeHandle*)(void*)amt.Track(pLoaderAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(classInstCount) * S_SIZE_T(sizeof(TypeHandle)))); @@ -4931,7 +4940,7 @@ VASigCookie *Module::GetVASigCookieWorker(Module* pDefiningModule, Module* pLoad } pCookie->methodInst = Instantiation(pMethodInst, methodInstCount); } - + amt.SuppressRelease(); // Finally, now that it's safe for asynchronous readers to see it, diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h index f85f4eab8d31..e0a7d142e304 100644 --- a/src/coreclr/vm/ceeload.h +++ b/src/coreclr/vm/ceeload.h @@ -41,6 +41,7 @@ #endif #include "ilinstrumentation.h" +#include "codeversion.h" class Stub; class MethodDesc; @@ -63,7 +64,6 @@ class SString; class Pending; class MethodTable; class DynamicMethodTable; -class CodeVersionManager; class TieredCompilationManager; class JITInlineTrackingMap; @@ -581,8 +581,7 @@ class ModuleBase }; -// A code:Module represents a DLL or EXE file loaded from the disk. It could either be a IL module or a -// Native code (NGEN module). A module live in a code:Assembly +// A code:Module represents a DLL or EXE file loaded from the disk. A module live in a code:Assembly // // Some important fields are // * code:Module.m_pPEAssembly - this points at a code:PEAssembly that understands the layout of a PE assembly. The most @@ -727,6 +726,10 @@ class Module : public ModuleBase // For generic methods, IsGenericTypeDefinition() is true i.e. instantiation at formals LookupMap m_MethodDefToDescMap; + // Linear mapping from MethodDef token to ILCodeVersioningState * + // This is used for Code Versioning logic + LookupMap m_ILCodeVersioningStateMap; + // Linear mapping from FieldDef token to FieldDesc* LookupMap m_FieldDefToDescMap; @@ -1215,7 +1218,7 @@ class Module : public ModuleBase } #endif // !DACCESS_COMPILE - MethodDesc *LookupMethodDef(mdMethodDef token); + PTR_MethodDesc LookupMethodDef(mdMethodDef token); #ifndef DACCESS_COMPILE void EnsureMethodDefCanBeStored(mdMethodDef token) @@ -1233,6 +1236,25 @@ class Module : public ModuleBase } #endif // !DACCESS_COMPILE + PTR_ILCodeVersioningState LookupILCodeVersioningState(mdMethodDef token); + +#ifndef DACCESS_COMPILE + void EnsureILCodeVersioningStateCanBeStored(mdMethodDef token) + { + WRAPPER_NO_CONTRACT; // THROWS/GC_NOTRIGGER/INJECT_FAULT()/MODE_ANY + _ASSERTE(CodeVersionManager::IsLockOwnedByCurrentThread()); + m_ILCodeVersioningStateMap.EnsureElementCanBeStored(this, RidFromToken(token)); + } + + void EnsuredStoreILCodeVersioningState(mdMethodDef token, PTR_ILCodeVersioningState value) + { + WRAPPER_NO_CONTRACT; // NOTHROW/GC_NOTRIGGER/FORBID_FAULT/MODE_ANY + _ASSERTE(CodeVersionManager::IsLockOwnedByCurrentThread()); + _ASSERTE(TypeFromToken(token) == mdtMethodDef); + m_ILCodeVersioningStateMap.SetElement(RidFromToken(token), value); + } +#endif // !DACCESS_COMPILE + #ifndef DACCESS_COMPILE FieldDesc *LookupFieldDef(mdFieldDef token) { diff --git a/src/coreclr/vm/ceeload.inl b/src/coreclr/vm/ceeload.inl index 18d7557d6e85..8de79fd3cb00 100644 --- a/src/coreclr/vm/ceeload.inl +++ b/src/coreclr/vm/ceeload.inl @@ -76,7 +76,7 @@ TYPE LookupMap::GetElement(DWORD rid, TADDR* pFlags) SUPPORTS_DAC; PTR_TADDR pElement = GetElementPtr(rid); - return (pElement != NULL) ? GetValueAt(pElement, pFlags, supportedFlags) : NULL; + return (pElement != NULL) ? GetValueAt(pElement, pFlags, supportedFlags) : (TYPE)(TADDR)0; } // Stores an association in a map that has been previously grown to @@ -117,7 +117,7 @@ BOOL LookupMap::TrySetElement(DWORD rid, TYPE value, TADDR flags) _ASSERTE(oldValue == NULL || (oldValue == value && oldFlags == flags)); #endif // Avoid unnecessary writes - do not overwrite existing value - if (*pElement == NULL) + if (*pElement == 0) { SetValueAt(pElement, value, flags); } @@ -149,7 +149,7 @@ void LookupMap::AddElement(ModuleBase * pModule, DWORD rid, TYPE value, TA _ASSERTE(oldValue == NULL || (oldValue == value && oldFlags == flags)); #endif // Avoid unnecessary writes - do not overwrite existing value - if (*pElement == NULL) + if (*pElement == 0) { SetValueAt(pElement, value, flags); } @@ -259,7 +259,7 @@ inline PTR_Assembly Module::GetAssembly() const return m_pAssembly; } -inline MethodDesc *Module::LookupMethodDef(mdMethodDef token) +inline PTR_MethodDesc Module::LookupMethodDef(mdMethodDef token) { CONTRACTL { @@ -274,6 +274,22 @@ inline MethodDesc *Module::LookupMethodDef(mdMethodDef token) return m_MethodDefToDescMap.GetElement(RidFromToken(token)); } +inline PTR_ILCodeVersioningState Module::LookupILCodeVersioningState(mdMethodDef token) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + SUPPORTS_DAC; + } + CONTRACTL_END + + _ASSERTE(CodeVersionManager::IsLockOwnedByCurrentThread()); + _ASSERTE(TypeFromToken(token) == mdtMethodDef); + return m_ILCodeVersioningStateMap.GetElement(RidFromToken(token)); +} + inline MethodDesc *Module::LookupMemberRefAsMethod(mdMemberRef token) { LIMITED_METHOD_DAC_CONTRACT; diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index 1c29942942c0..ba2db68bf64a 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -544,7 +544,11 @@ void EESocketCleanupHelper(bool isExecutingOnAltStack) if (isExecutingOnAltStack) { - GetThread()->SetExecutingOnAltStack(); + Thread *pThread = GetThreadNULLOk(); + if (pThread) + { + pThread->SetExecutingOnAltStack(); + } } // Close the debugger transport socket first @@ -1244,6 +1248,8 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) // This will check a flag and do nothing if not enabled. Interpreter::PrintPostMortemData(); #endif // FEATURE_INTERPRETER + VirtualCallStubManager::LogFinalStats(); + WriteJitHelperCountToSTRESSLOG(); #ifdef PROFILING_SUPPORTED // If profiling is enabled, then notify of shutdown first so that the @@ -1345,11 +1351,6 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) TerminateDebugger(); #endif // DEBUGGING_SUPPORTED - //@TODO: find the right place for this - VirtualCallStubManager::UninitStatic(); - - WriteJitHelperCountToSTRESSLOG(); - STRESS_LOG0(LF_STARTUP, LL_INFO10, "EEShutdown shutting down logging"); #if 0 // Dont clean up the stress log, so that even at process exit we have a log (after all the process is going away diff --git a/src/coreclr/vm/classcompat.cpp b/src/coreclr/vm/classcompat.cpp index b089dad7fdaf..ece9384703b2 100644 --- a/src/coreclr/vm/classcompat.cpp +++ b/src/coreclr/vm/classcompat.cpp @@ -869,7 +869,7 @@ VOID MethodTableBuilder::BuildInteropVTable_PlaceMembers( bmtMethod->ppMethodDescList[i] = pNewMD; // Make sure that fcalls have a 0 rva. This is assumed by the prejit fixup logic - _ASSERTE(((Classification & ~mdcMethodImpl) != mcFCall) || dwDescrOffset == 0); + _ASSERTE(((Classification & ~mdfMethodImpl) != mcFCall) || dwDescrOffset == 0); // Non-virtual method if (IsMdStatic(dwMemberAttrs) || @@ -938,7 +938,7 @@ VOID MethodTableBuilder::BuildInteropVTable_PlaceMembers( } } - if (Classification & mdcMethodImpl) + if (Classification & mdfMethodImpl) { // If this method serves as the BODY of a MethodImpl specification, then // we should iterate all the MethodImpl's for this class and see just how many // of them this method participates in as the BODY. @@ -2797,7 +2797,7 @@ VOID MethodTableBuilder::EnumerateClassMethods() } // Generic methods should always be mcInstantiated - if (!((numGenericMethodArgs == 0) || ((Classification & mdcClassification) == mcInstantiated))) + if (!((numGenericMethodArgs == 0) || ((Classification & mdfClassification) == mcInstantiated))) { BuildMethodTableThrowException(BFA_GENERIC_METHODS_INST); } @@ -2806,7 +2806,7 @@ VOID MethodTableBuilder::EnumerateClassMethods() // from the overrides. for(DWORD impls = 0; impls < bmtMethodImpl->dwNumberMethodImpls; impls++) { if ((bmtMethodImpl->rgMethodImplTokens[impls].methodBody == tok) && !IsMdStatic(dwMemberAttrs)) { - Classification |= mdcMethodImpl; + Classification |= mdfMethodImpl; break; } } @@ -2830,7 +2830,7 @@ VOID MethodTableBuilder::EnumerateClassMethods() // Set the index into the storage locations BYTE impl; - if (Classification & mdcMethodImpl) + if (Classification & mdfMethodImpl) { impl = METHOD_IMPL; } @@ -2840,25 +2840,25 @@ VOID MethodTableBuilder::EnumerateClassMethods() } BYTE type; - if ((Classification & mdcClassification) == mcNDirect) + if ((Classification & mdfClassification) == mcNDirect) { type = METHOD_TYPE_NDIRECT; } - else if ((Classification & mdcClassification) == mcFCall) + else if ((Classification & mdfClassification) == mcFCall) { type = METHOD_TYPE_FCALL; } - else if ((Classification & mdcClassification) == mcEEImpl) + else if ((Classification & mdfClassification) == mcEEImpl) { type = METHOD_TYPE_EEIMPL; } #ifdef FEATURE_COMINTEROP - else if ((Classification & mdcClassification) == mcComInterop) + else if ((Classification & mdfClassification) == mcComInterop) { type = METHOD_TYPE_INTEROP; } #endif // FEATURE_COMINTEROP - else if ((Classification & mdcClassification) == mcInstantiated) + else if ((Classification & mdfClassification) == mcInstantiated) { type = METHOD_TYPE_INSTANTIATED; } diff --git a/src/coreclr/vm/classhash.inl b/src/coreclr/vm/classhash.inl index 554c0c2005c4..ff1c25d93a93 100644 --- a/src/coreclr/vm/classhash.inl +++ b/src/coreclr/vm/classhash.inl @@ -34,7 +34,7 @@ inline PTR_VOID EEClassHashTable::CompressClassDef(mdToken cl) case mdtExportedType: return (PTR_VOID)(EECLASSHASH_MDEXPORT_DISCR | (((ULONG_PTR)cl & 0x00ffffff) << 1) | EECLASSHASH_TYPEHANDLE_DISCR); default: _ASSERTE(!"Can't get here."); - return 0; + return nullptr; } } diff --git a/src/coreclr/vm/clrex.h b/src/coreclr/vm/clrex.h index 3a17cd2e7208..586798f397fa 100644 --- a/src/coreclr/vm/clrex.h +++ b/src/coreclr/vm/clrex.h @@ -934,7 +934,7 @@ LONG CLRNoCatchHandler(EXCEPTION_POINTERS* pExceptionInfo, PVOID pv); // --------------------------------------------------------------------------- inline CLRException::CLRException() - : m_throwableHandle(NULL) + : m_throwableHandle{} { LIMITED_METHOD_CONTRACT; } diff --git a/src/coreclr/vm/clsload.hpp b/src/coreclr/vm/clsload.hpp index 251a76a8f78e..fb79f0dfc810 100644 --- a/src/coreclr/vm/clsload.hpp +++ b/src/coreclr/vm/clsload.hpp @@ -134,7 +134,7 @@ class NameHandle NameHandle() { LIMITED_METHOD_CONTRACT; - memset((void*) this, NULL, sizeof(*this)); + memset((void*) this, 0, sizeof(*this)); } NameHandle(LPCUTF8 nameSpace, LPCUTF8 name) : diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index 228c65f00412..0885ec6d3b8e 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -1669,45 +1669,6 @@ struct JIT_LOAD_DATA // Here's the global data for JIT load and initialization state. JIT_LOAD_DATA g_JitLoadData; -// Validate that the name used to load the JIT is just a simple file name -// and does not contain something that could be used in a non-qualified path. -// For example, using the string "..\..\..\myjit.dll" we might attempt to -// load a JIT from the root of the drive. -// -// The minimal set of characters that we must check for and exclude are: -// On all platforms: -// '/' - (forward slash) -// On Windows: -// '\\' - (backslash) -// ':' - (colon) -// -// Returns false if we find any of these characters in 'pwzJitName' -// Returns true if we reach the null terminator without encountering -// any of these characters. -// -static bool ValidateJitName(LPCWSTR pwzJitName) -{ - LPCWSTR pCurChar = pwzJitName; - wchar_t curChar; - do { - curChar = *pCurChar; - if (curChar == '/' -#ifdef TARGET_WINDOWS - || (curChar == '\\') || (curChar == ':') -#endif - ) - { - // Return false if we find any of these character in 'pwzJitName' - return false; - } - pCurChar++; - } while (curChar != 0); - - // Return true; we have reached the null terminator - // - return true; -} - CORINFO_OS getClrVmOs(); #define LogJITInitializationError(...) \ @@ -1770,7 +1731,7 @@ static void LoadAndInitializeJIT(LPCWSTR pwzJitName DEBUGARG(LPCWSTR pwzJitPath) return; } - if (ValidateJitName(pwzJitName)) + if (ValidateModuleName(pwzJitName)) { // Load JIT from next to CoreCLR binary PathString CoreClrFolderHolder; @@ -3300,7 +3261,7 @@ unsigned EEJitManager::InitializeEHEnumeration(const METHODTOKEN& MethodToken, E EE_ILEXCEPTION * EHInfo = GetCodeHeader(MethodToken)->GetEHInfo(); pEnumState->iCurrentPos = 0; // since the EH info is not compressed, the clause number is used to do the enumeration - pEnumState->pExceptionClauseArray = NULL; + pEnumState->pExceptionClauseArray = 0; if (!EHInfo) return 0; @@ -4005,7 +3966,7 @@ TADDR EEJitManager::FindMethodCode(RangeSection * pRangeSection, PCODE currentPC if ((currentPC < pHp->startAddress) || (currentPC > pHp->endAddress)) { - return NULL; + return 0; } TADDR base = pHp->mapBase; @@ -4052,7 +4013,7 @@ TADDR EEJitManager::FindMethodCode(RangeSection * pRangeSection, PCODE currentPC // previous DWORD, unless we are already on the first DWORD if (startPos < NIBBLES_PER_DWORD) - return NULL; + return 0; startPos = ((startPos >> LOG2_NIBBLES_PER_DWORD) << LOG2_NIBBLES_PER_DWORD) - 1; @@ -4066,7 +4027,7 @@ TADDR EEJitManager::FindMethodCode(RangeSection * pRangeSection, PCODE currentPC // This helps to catch degenerate error cases. This relies on the fact that // startPos cannot ever be bigger than MAX_UINT if (((INT_PTR)startPos) < 0) - return NULL; + return 0; // Find the nibble with the header in the DWORD @@ -4077,7 +4038,7 @@ TADDR EEJitManager::FindMethodCode(RangeSection * pRangeSection, PCODE currentPC } if (startPos == 0 && tmp == 0) - return NULL; + return 0; return base + POSOFF2ADDR(startPos, tmp & NIBBLE_MASK); } @@ -4217,12 +4178,12 @@ void GetUnmanagedStackWalkInfo(IN ULONG64 ControlPc, if (pModuleBase) { - *pModuleBase = NULL; + *pModuleBase = 0; } if (pFuncEntry) { - *pFuncEntry = NULL; + *pFuncEntry = 0; } PEDecoder peDecoder(DacGlobalBase()); @@ -4246,7 +4207,7 @@ void GetUnmanagedStackWalkInfo(IN ULONG64 ControlPc, COUNT_T cbSize = 0; TADDR pExceptionDir = peDecoder.GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_EXCEPTION, &cbSize); - if (pExceptionDir != NULL) + if (pExceptionDir != 0) { // Do a binary search on the static function table of mscorwks.dll. HRESULT hr = E_FAIL; @@ -4320,9 +4281,9 @@ extern "C" void GetRuntimeStackWalkInfo(IN ULONG64 ControlPc, BEGIN_PRESERVE_LAST_ERROR; if (pModuleBase) - *pModuleBase = NULL; + *pModuleBase = 0; if (pFuncEntry) - *pFuncEntry = NULL; + *pFuncEntry = 0; EECodeInfo codeInfo((PCODE)ControlPc); if (!codeInfo.IsValid()) @@ -4467,7 +4428,7 @@ PCODE ExecutionManager::GetCodeStartAddress(PCODE currentPC) EECodeInfo codeInfo(currentPC); if (!codeInfo.IsValid()) - return NULL; + return (PCODE)NULL; return PINSTRToPCODE(codeInfo.GetStartAddress()); } @@ -5555,7 +5516,7 @@ UINT32 ReadyToRunJitManager::JitTokenToGCInfoVersion(const METHODTOKEN& MethodTo READYTORUN_HEADER * header = JitTokenToReadyToRunInfo(MethodToken)->GetReadyToRunHeader(); - return GCInfoToken::ReadyToRunVersionToGcInfoVersion(header->MajorVersion); + return GCInfoToken::ReadyToRunVersionToGcInfoVersion(header->MajorVersion, header->MinorVersion); } PTR_RUNTIME_FUNCTION ReadyToRunJitManager::JitTokenToRuntimeFunction(const METHODTOKEN& MethodToken) diff --git a/src/coreclr/vm/codeman.h b/src/coreclr/vm/codeman.h index 3319d3e0c300..7d874c6ba7e6 100644 --- a/src/coreclr/vm/codeman.h +++ b/src/coreclr/vm/codeman.h @@ -2210,9 +2210,9 @@ class ExecutionManager #endif } - static const element_t Null() { LIMITED_METHOD_CONTRACT; JumpStubEntry e; e.m_target = NULL; e.m_jumpStub = NULL; return e; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.m_target == NULL; } - static const element_t Deleted() { LIMITED_METHOD_CONTRACT; JumpStubEntry e; e.m_target = (PCODE)-1; e.m_jumpStub = NULL; return e; } + static const element_t Null() { LIMITED_METHOD_CONTRACT; JumpStubEntry e; e.m_target = 0; e.m_jumpStub = 0; return e; } + static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.m_target == 0; } + static const element_t Deleted() { LIMITED_METHOD_CONTRACT; JumpStubEntry e; e.m_target = (PCODE)-1; e.m_jumpStub = 0; return e; } static bool IsDeleted(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.m_target == (PCODE)-1; } }; typedef SHash JumpStubTable; diff --git a/src/coreclr/vm/codeversion.cpp b/src/coreclr/vm/codeversion.cpp index 741fe0390bb5..a6d22cb6a3d5 100644 --- a/src/coreclr/vm/codeversion.cpp +++ b/src/coreclr/vm/codeversion.cpp @@ -60,7 +60,7 @@ NativeCodeVersionNode::NativeCodeVersionNode( PatchpointInfo* patchpointInfo, unsigned ilOffset) : - m_pNativeCode(NULL), + m_pNativeCode{}, m_pMethodDesc(pMethodDesc), m_parentId(parentId), m_pNextMethodDescSibling(NULL), @@ -303,7 +303,7 @@ void NativeCodeVersion::SetActiveChildFlag(BOOL isActive) { if (isActive && !CodeVersionManager::InitialNativeCodeVersionMayNotBeTheDefaultNativeCodeVersion() && - GetMethodDesc()->GetNativeCode() == NULL) + GetMethodDesc()->GetNativeCode() == (PCODE)NULL) { CodeVersionManager::SetInitialNativeCodeVersionMayNotBeTheDefaultNativeCodeVersion(); } @@ -1306,40 +1306,47 @@ void ILCodeVersioningState::LinkILCodeVersionNode(ILCodeVersionNode* pILCodeVers bool CodeVersionManager::s_initialNativeCodeVersionMayNotBeTheDefaultNativeCodeVersion = false; #endif -CodeVersionManager::CodeVersionManager() -{} - PTR_ILCodeVersioningState CodeVersionManager::GetILCodeVersioningState(PTR_Module pModule, mdMethodDef methodDef) const { LIMITED_METHOD_DAC_CONTRACT; - ILCodeVersioningState::Key key = ILCodeVersioningState::Key(pModule, methodDef); - return m_ilCodeVersioningStateMap.Lookup(key); + return pModule->LookupILCodeVersioningState(methodDef); } PTR_MethodDescVersioningState CodeVersionManager::GetMethodDescVersioningState(PTR_MethodDesc pClosedMethodDesc) const { LIMITED_METHOD_DAC_CONTRACT; - return m_methodDescVersioningStateMap.Lookup(pClosedMethodDesc); + return pClosedMethodDesc->GetMethodDescVersionState(); } +SVAL_IMPL_INIT(BOOL, CodeVersionManager, s_HasNonDefaultILVersions, FALSE); + #ifndef DACCESS_COMPILE HRESULT CodeVersionManager::GetOrCreateILCodeVersioningState(Module* pModule, mdMethodDef methodDef, ILCodeVersioningState** ppILCodeVersioningState) { - LIMITED_METHOD_CONTRACT; - HRESULT hr = S_OK; - ILCodeVersioningState* pILCodeVersioningState = GetILCodeVersioningState(pModule, methodDef); + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + PRECONDITION(IsLockOwnedByCurrentThread()); + PRECONDITION(pModule != NULL); + PRECONDITION(methodDef != mdTokenNil); + PRECONDITION(ppILCodeVersioningState != NULL); + } + CONTRACTL_END; + + LOG((LF_TIEREDCOMPILATION, LL_INFO100, "CVM::GetOrCreateILCodeVersioningState Module=%p MethodDef=0x%08x\n", pModule, methodDef)); + + ILCodeVersioningState* pILCodeVersioningState = pModule->LookupILCodeVersioningState(methodDef); if (pILCodeVersioningState == NULL) { pILCodeVersioningState = new (nothrow) ILCodeVersioningState(pModule, methodDef); if (pILCodeVersioningState == NULL) - { return E_OUTOFMEMORY; - } + + HRESULT hr = S_OK; EX_TRY { - // This throws when out of memory, but remains internally - // consistent (without adding the new element) - m_ilCodeVersioningStateMap.Add(pILCodeVersioningState); + pModule->EnsureILCodeVersioningStateCanBeStored(methodDef); } EX_CATCH_HRESULT(hr); if (FAILED(hr)) @@ -1347,6 +1354,12 @@ HRESULT CodeVersionManager::GetOrCreateILCodeVersioningState(Module* pModule, md delete pILCodeVersioningState; return hr; } + pModule->EnsuredStoreILCodeVersioningState(methodDef, pILCodeVersioningState); + + LOG((LF_TIEREDCOMPILATION, LL_INFO100, "CVM::GetOrCreateILCodeVersioningState Created state: %p\n", pILCodeVersioningState)); + + // Record that we've created at least one IL version. + s_HasNonDefaultILVersions = TRUE; } *ppILCodeVersioningState = pILCodeVersioningState; return S_OK; @@ -1354,42 +1367,42 @@ HRESULT CodeVersionManager::GetOrCreateILCodeVersioningState(Module* pModule, md HRESULT CodeVersionManager::GetOrCreateMethodDescVersioningState(MethodDesc* pMethod, MethodDescVersioningState** ppMethodVersioningState) { - LIMITED_METHOD_CONTRACT; - HRESULT hr = S_OK; - MethodDescVersioningState* pMethodVersioningState = m_methodDescVersioningStateMap.Lookup(pMethod); + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + PRECONDITION(pMethod != NULL); + PRECONDITION(ppMethodVersioningState != NULL); + } + CONTRACTL_END; + + HRESULT hr; + MethodDescVersioningState* pMethodVersioningState = pMethod->GetMethodDescVersionState(); if (pMethodVersioningState == NULL) { pMethodVersioningState = new (nothrow) MethodDescVersioningState(pMethod); if (pMethodVersioningState == NULL) - { return E_OUTOFMEMORY; - } - EX_TRY - { - // This throws when out of memory, but remains internally - // consistent (without adding the new element) - m_methodDescVersioningStateMap.Add(pMethodVersioningState); - } - EX_CATCH_HRESULT(hr); - if (FAILED(hr)) - { + + IfFailRet(pMethod->SetMethodDescVersionState(pMethodVersioningState)); + if (hr == S_FALSE) delete pMethodVersioningState; - return hr; - } + + pMethodVersioningState = pMethod->GetMethodDescVersionState(); } *ppMethodVersioningState = pMethodVersioningState; return S_OK; } #endif // DACCESS_COMPILE -DWORD CodeVersionManager::GetNonDefaultILVersionCount() +BOOL CodeVersionManager::HasNonDefaultILVersions() { LIMITED_METHOD_DAC_CONTRACT; //This function is legal to call WITHOUT taking the lock //It is used to do a quick check if work might be needed without paying the overhead //of acquiring the lock and doing dictionary lookups - return m_ilCodeVersioningStateMap.GetCount(); + return s_HasNonDefaultILVersions; } ILCodeVersionCollection CodeVersionManager::GetILCodeVersions(PTR_MethodDesc pMethod) @@ -1690,7 +1703,7 @@ PCODE CodeVersionManager::PublishVersionableCodeIfNecessary( // CodeVersionManager is set (not a typical case, may be possible with profilers). So, if the flag is not set and the // default native code version does not have native code, then it must be the active code version. pCode = pMethodDesc->GetNativeCode(); - if (pCode == NULL && !CodeVersionManager::InitialNativeCodeVersionMayNotBeTheDefaultNativeCodeVersion()) + if (pCode == (PCODE)NULL && !CodeVersionManager::InitialNativeCodeVersionMayNotBeTheDefaultNativeCodeVersion()) { activeVersion = NativeCodeVersion(pMethodDesc); break; @@ -1699,7 +1712,7 @@ PCODE CodeVersionManager::PublishVersionableCodeIfNecessary( if (!pMethodDesc->IsPointingToPrestub()) { *doFullBackpatchRef = true; - return NULL; + return (PCODE)NULL; } LockHolder codeVersioningLockHolder; @@ -1713,7 +1726,7 @@ PCODE CodeVersionManager::PublishVersionableCodeIfNecessary( _ASSERTE(hr == E_OUTOFMEMORY); ReportCodePublishError(pMethodDesc, hr); *doBackpatchRef = false; - return pCode != NULL ? pCode : pMethodDesc->PrepareInitialCode(callerGCMode); + return pCode != (PCODE)NULL ? pCode : pMethodDesc->PrepareInitialCode(callerGCMode); } while (false); while (true) @@ -1724,7 +1737,7 @@ PCODE CodeVersionManager::PublishVersionableCodeIfNecessary( bool profilerMayHaveActivatedNonDefaultCodeVersion = false; // Compile the code if needed - if (pCode == NULL) + if (pCode == (PCODE)NULL) { PrepareCodeConfigBuffer configBuffer(activeVersion); PrepareCodeConfig *config = configBuffer.GetConfig(); @@ -1916,36 +1929,38 @@ HRESULT CodeVersionManager::PublishNativeCodeVersion(MethodDesc* pMethod, Native _ASSERTE(!pMethod->MayHaveEntryPointSlotsToBackpatch() || MethodDescBackpatchInfoTracker::IsLockOwnedByCurrentThread()); _ASSERTE(IsLockOwnedByCurrentThread()); - _ASSERTE(pMethod->IsVersionable()); + + if (!pMethod->IsVersionable()) + { + _ASSERTE(!"This method doesn't support versioning but was requested to be versioned."); + return E_FAIL; + } HRESULT hr = S_OK; - PCODE pCode = nativeCodeVersion.IsNull() ? NULL : nativeCodeVersion.GetNativeCode(); - if (pMethod->IsVersionable()) + PCODE pCode = nativeCodeVersion.IsNull() ? (PCODE)NULL : nativeCodeVersion.GetNativeCode(); + EX_TRY { - EX_TRY + if (pCode == (PCODE)NULL) { - if (pCode == NULL) - { - pMethod->ResetCodeEntryPoint(); - } - else - { - #ifdef FEATURE_TIERED_COMPILATION - bool wasSet = CallCountingManager::SetCodeEntryPoint(nativeCodeVersion, pCode, false, nullptr); - _ASSERTE(wasSet); - #else - pMethod->SetCodeEntryPoint(pCode); - #endif - } + LOG((LF_TIEREDCOMPILATION, LL_INFO100, "CVM::PublishNativeCodeVersion pMethod=%p - Resetting\n", pMethod)); + pMethod->ResetCodeEntryPoint(); + } + else + { + LOG((LF_TIEREDCOMPILATION, LL_INFO100, "CVM::PublishNativeCodeVersion pMethod=%p - Set to ver=%u\n", + pMethod, + nativeCodeVersion.GetVersionId())); + + #ifdef FEATURE_TIERED_COMPILATION + bool wasSet = CallCountingManager::SetCodeEntryPoint(nativeCodeVersion, pCode, false, nullptr); + _ASSERTE(wasSet); + #else + pMethod->SetCodeEntryPoint(pCode); + #endif } - EX_CATCH_HRESULT(hr); - return hr; - } - else - { - _ASSERTE(!"This method doesn't support versioning but was requested to be versioned."); - return E_FAIL; } + EX_CATCH_HRESULT(hr); + return hr; } // static diff --git a/src/coreclr/vm/codeversion.h b/src/coreclr/vm/codeversion.h index 7b536fb071a6..bd778bd47d7b 100644 --- a/src/coreclr/vm/codeversion.h +++ b/src/coreclr/vm/codeversion.h @@ -68,7 +68,7 @@ class NativeCodeVersion #endif #ifndef DACCESS_COMPILE - BOOL SetNativeCodeInterlocked(PCODE pCode, PCODE pExpected = NULL); + BOOL SetNativeCodeInterlocked(PCODE pCode, PCODE pExpected = 0); #endif // NOTE: Don't change existing values to avoid breaking changes in event tracing @@ -475,36 +475,6 @@ class MethodDescVersioningState PTR_NativeCodeVersionNode m_pFirstVersionNode; }; -class MethodDescVersioningStateHashTraits : public NoRemoveSHashTraits> -{ -public: - typedef typename DefaultSHashTraits::element_t element_t; - typedef typename DefaultSHashTraits::count_t count_t; - - typedef const PTR_MethodDesc key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e->GetMethodDesc(); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)dac_cast(k); - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return dac_cast(nullptr); } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } -}; - -typedef SHash MethodDescVersioningStateHash; - class ILCodeVersioningState { public: @@ -537,44 +507,17 @@ class ILCodeVersioningState mdMethodDef m_methodDef; }; -class ILCodeVersioningStateHashTraits : public NoRemoveSHashTraits> -{ -public: - typedef typename DefaultSHashTraits::element_t element_t; - typedef typename DefaultSHashTraits::count_t count_t; - - typedef const ILCodeVersioningState::Key key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e->GetKey(); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)k.Hash(); - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return dac_cast(nullptr); } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } -}; - -typedef SHash ILCodeVersioningStateHash; - class CodeVersionManager { friend class ILCodeVersion; + friend struct _DacGlobals; + + SVAL_DECL(BOOL, s_HasNonDefaultILVersions); public: - CodeVersionManager(); + CodeVersionManager() = default; - DWORD GetNonDefaultILVersionCount(); + BOOL HasNonDefaultILVersions(); ILCodeVersionCollection GetILCodeVersions(PTR_MethodDesc pMethod); ILCodeVersionCollection GetILCodeVersions(PTR_Module pModule, mdMethodDef methodDef); ILCodeVersion GetActiveILCodeVersion(PTR_MethodDesc pMethod); @@ -602,9 +545,13 @@ class CodeVersionManager CallerGCMode callerGCMode, bool *doBackpatchRef, bool *doFullBackpatchRef); + +private: HRESULT PublishNativeCodeVersion(MethodDesc* pMethodDesc, NativeCodeVersion nativeCodeVersion); HRESULT GetOrCreateMethodDescVersioningState(MethodDesc* pMethod, MethodDescVersioningState** ppMethodDescVersioningState); HRESULT GetOrCreateILCodeVersioningState(Module* pModule, mdMethodDef methodDef, ILCodeVersioningState** ppILCodeVersioningState); + +public: HRESULT SetActiveILCodeVersions(ILCodeVersion* pActiveVersions, DWORD cActiveVersions, CDynArray * pPublishErrors); static HRESULT AddCodePublishError(Module* pModule, mdMethodDef methodDef, MethodDesc* pMD, HRESULT hrStatus, CDynArray * pErrors); static HRESULT AddCodePublishError(NativeCodeVersion nativeCodeVersion, HRESULT hrStatus, CDynArray * pErrors); @@ -645,12 +592,6 @@ class CodeVersionManager static bool s_initialNativeCodeVersionMayNotBeTheDefaultNativeCodeVersion; #endif - //Module,MethodDef -> ILCodeVersioningState - ILCodeVersioningStateHash m_ilCodeVersioningStateMap; - - //closed MethodDesc -> MethodDescVersioningState - MethodDescVersioningStateHash m_methodDescVersioningStateMap; - private: static CrstStatic s_lock; diff --git a/src/coreclr/vm/comcallablewrapper.cpp b/src/coreclr/vm/comcallablewrapper.cpp index 8bad0356112e..b80c2442c909 100644 --- a/src/coreclr/vm/comcallablewrapper.cpp +++ b/src/coreclr/vm/comcallablewrapper.cpp @@ -553,11 +553,11 @@ FORCEINLINE void CPListDoNothing(CPArray*) LIMITED_METHOD_CONTRACT; } -class CPListHolder : public Wrapper +class CPListHolder : public Wrapper { public: CPListHolder(CPArray* p = NULL) - : Wrapper(p) + : Wrapper(p) { WRAPPER_NO_CONTRACT; } @@ -565,7 +565,7 @@ class CPListHolder : public Wrapper::operator=(p); + Wrapper::operator=(p); } }; diff --git a/src/coreclr/vm/comcallablewrapper.h b/src/coreclr/vm/comcallablewrapper.h index 71b79ca00299..f032204e54ce 100644 --- a/src/coreclr/vm/comcallablewrapper.h +++ b/src/coreclr/vm/comcallablewrapper.h @@ -343,7 +343,7 @@ inline void ComCallWrapperTemplateRelease(ComCallWrapperTemplate *value) } } -typedef Wrapper, ComCallWrapperTemplateRelease, NULL> ComCallWrapperTemplateHolder; +typedef Wrapper, ComCallWrapperTemplateRelease, 0> ComCallWrapperTemplateHolder; //-------------------------------------------------------------------------------- @@ -1041,11 +1041,11 @@ FORCEINLINE void CCWRelease(ComCallWrapper* p) p->Release(); } -class CCWHolder : public Wrapper +class CCWHolder : public Wrapper { public: CCWHolder(ComCallWrapper* p = NULL) - : Wrapper(p) + : Wrapper(p) { WRAPPER_NO_CONTRACT; } @@ -1054,7 +1054,7 @@ class CCWHolder : public Wrapper::operator=(p); + Wrapper::operator=(p); } }; // diff --git a/src/coreclr/vm/comconnectionpoints.h b/src/coreclr/vm/comconnectionpoints.h index c8d338634722..f4b90a16d36c 100644 --- a/src/coreclr/vm/comconnectionpoints.h +++ b/src/coreclr/vm/comconnectionpoints.h @@ -82,11 +82,11 @@ FORCEINLINE void ConnectionCookieRelease(ConnectionCookie* p) } // Connection cookie holder used to ensure the cookies are deleted when required. -class ConnectionCookieHolder : public Wrapper +class ConnectionCookieHolder : public Wrapper { public: ConnectionCookieHolder(ConnectionCookie* p = NULL) - : Wrapper(p) + : Wrapper(p) { WRAPPER_NO_CONTRACT; } @@ -94,7 +94,7 @@ class ConnectionCookieHolder : public Wrapper::operator=(p); + Wrapper::operator=(p); } }; diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index ef4021039a66..77664d54f96a 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1172,7 +1172,7 @@ void COMDelegate::BindToMethod(DELEGATEREF *pRefThis, } else { - PCODE pTargetCode = NULL; + PCODE pTargetCode = (PCODE)NULL; // For virtual methods we can (and should) virtualize the call now (so we don't have to insert a thunk to do so at runtime). // @@ -1283,7 +1283,7 @@ LPVOID COMDelegate::ConvertToCallback(OBJECTREF pDelegateObj) _ASSERTE(objhnd != NULL); // This target should not ever be used. We are storing it in the thunk for better diagnostics of "call on collected delegate" crashes. - PCODE pManagedTargetForDiagnostics = (pDelegate->GetMethodPtrAux() != NULL) ? pDelegate->GetMethodPtrAux() : pDelegate->GetMethodPtr(); + PCODE pManagedTargetForDiagnostics = (pDelegate->GetMethodPtrAux() != (PCODE)NULL) ? pDelegate->GetMethodPtrAux() : pDelegate->GetMethodPtr(); ExecutableWriterHolder uMEntryThunkWriterHolder(pUMEntryThunk, sizeof(UMEntryThunk)); @@ -1380,14 +1380,14 @@ OBJECTREF COMDelegate::ConvertToDelegate(LPVOID pCallback, MethodTable* pMT) // PCODE pMarshalStub = pClass->m_pMarshalStub; - if (pMarshalStub == NULL) + if (pMarshalStub == (PCODE)NULL) { GCX_PREEMP(); pMarshalStub = GetStubForInteropMethod(pMD); // Save this new stub on the DelegateEEClass. - InterlockedCompareExchangeT(&pClass->m_pMarshalStub, pMarshalStub, NULL); + InterlockedCompareExchangeT(&pClass->m_pMarshalStub, pMarshalStub, (PCODE)NULL); pMarshalStub = pClass->m_pMarshalStub; } @@ -1595,7 +1595,7 @@ FCIMPL3(void, COMDelegate::DelegateConstruct, Object* refThisUNSAFE, Object* tar // via reflection you can pass in just about any value for the method. // we can do some basic verification up front to prevent EE exceptions. - if (method == NULL) + if (method == (PCODE)NULL) COMPlusThrowArgumentNull(W("method")); _ASSERTE(gc.refThis); @@ -1798,7 +1798,7 @@ MethodDesc *COMDelegate::GetMethodDesc(OBJECTREF orDelegate) // Next, check for an open delegate PCODE code = thisDel->GetMethodPtrAux(); - if (code != NULL) + if (code != (PCODE)NULL) { // Note that MethodTable::GetMethodDescForSlotAddress is significantly faster than Entry2MethodDesc pMethodHandle = MethodTable::GetMethodDescForSlotAddress(code); @@ -1936,7 +1936,7 @@ PCODE COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) } CONTRACT_END; - PCODE ret = NULL; + PCODE ret = (PCODE)NULL; MethodTable * pDelMT = pMD->GetMethodTable(); DelegateEEClass* pClass = (DelegateEEClass*) pDelMT->GetClass(); diff --git a/src/coreclr/vm/comsynchronizable.cpp b/src/coreclr/vm/comsynchronizable.cpp index 520bd3c14f05..7cfee71b92c9 100644 --- a/src/coreclr/vm/comsynchronizable.cpp +++ b/src/coreclr/vm/comsynchronizable.cpp @@ -507,7 +507,7 @@ FCIMPL1(void, ThreadNative::Initialize, ThreadBaseObject* pThisUNSAFE) PREFIX_ASSUME(unstarted != NULL); - if (GetThread()->GetDomain()->IgnoreUnhandledExceptions()) + if (AppDomain::GetCurrentDomain()->IgnoreUnhandledExceptions()) { unstarted->SetThreadStateNC(Thread::TSNC_IgnoreUnhandledExceptions); } @@ -913,25 +913,6 @@ void ThreadNative::InformThreadNameChange(Thread* pThread, LPCWSTR name, INT32 l #endif // DEBUGGING_SUPPORTED } -extern "C" UINT64 QCALLTYPE ThreadNative_GetProcessDefaultStackSize() -{ - QCALL_CONTRACT; - - SIZE_T reserve = 0; - SIZE_T commit = 0; - - BEGIN_QCALL; - - if (!Thread::GetProcessDefaultStackSize(&reserve, &commit)) - reserve = 1024 * 1024; - - END_QCALL; - - return (UINT64)reserve; -} - - - FCIMPL1(FC_BOOL_RET, ThreadNative::IsThreadpoolThread, ThreadBaseObject* thread) { FCALL_CONTRACT; diff --git a/src/coreclr/vm/comsynchronizable.h b/src/coreclr/vm/comsynchronizable.h index 4d14461602d5..b0f5b72295a1 100644 --- a/src/coreclr/vm/comsynchronizable.h +++ b/src/coreclr/vm/comsynchronizable.h @@ -90,7 +90,6 @@ friend class ThreadBaseObject; extern "C" void QCALLTYPE ThreadNative_Start(QCall::ThreadHandle thread, int threadStackSize, int priority, PCWSTR pThreadName); extern "C" void QCALLTYPE ThreadNative_SetIsBackground(QCall::ThreadHandle thread, BOOL value); extern "C" void QCALLTYPE ThreadNative_InformThreadNameChange(QCall::ThreadHandle thread, LPCWSTR name, INT32 len); -extern "C" UINT64 QCALLTYPE ThreadNative_GetProcessDefaultStackSize(); extern "C" BOOL QCALLTYPE ThreadNative_YieldThread(); extern "C" UINT64 QCALLTYPE ThreadNative_GetCurrentOSThreadId(); extern "C" void QCALLTYPE ThreadNative_Abort(QCall::ThreadHandle thread); diff --git a/src/coreclr/vm/comtoclrcall.cpp b/src/coreclr/vm/comtoclrcall.cpp index 215b6c61bb58..925372cbe3ad 100644 --- a/src/coreclr/vm/comtoclrcall.cpp +++ b/src/coreclr/vm/comtoclrcall.cpp @@ -515,7 +515,7 @@ extern "C" UINT64 __stdcall COMToCLRWorker(Thread *pThread, ComMethodFrame* pFra // we have additional checks for thread abort that are performed only when // g_TrapReturningThreads is set. pThread->m_fPreemptiveGCDisabled.StoreWithoutBarrier(1); - if (g_TrapReturningThreads.LoadWithoutBarrier()) + if (g_TrapReturningThreads) { hr = StubRareDisableHRWorker(pThread); if (S_OK != hr) @@ -1339,14 +1339,12 @@ Stub* ComCall::CreateGenericComCallStub(BOOL isFieldAccess) // ends up throwing an OOM exception. CodeLabel* rgRareLabels[] = { - psl->NewCodeLabel(), psl->NewCodeLabel(), psl->NewCodeLabel() }; CodeLabel* rgRejoinLabels[] = { - psl->NewCodeLabel(), psl->NewCodeLabel(), psl->NewCodeLabel() }; diff --git a/src/coreclr/vm/contractimpl.h b/src/coreclr/vm/contractimpl.h index 3f76abfd91f1..786139745dfd 100644 --- a/src/coreclr/vm/contractimpl.h +++ b/src/coreclr/vm/contractimpl.h @@ -47,11 +47,11 @@ struct DispatchSlot //------------------------------------------------------------------------ inline BOOL IsNull() - { LIMITED_METHOD_CONTRACT; return (m_slot == NULL); } + { LIMITED_METHOD_CONTRACT; return (m_slot == 0); } //------------------------------------------------------------------------ inline void SetNull() - { LIMITED_METHOD_CONTRACT; m_slot = NULL; } + { LIMITED_METHOD_CONTRACT; m_slot = 0; } //------------------------------------------------------------------------ inline PCODE GetTarget() diff --git a/src/coreclr/vm/corelib.cpp b/src/coreclr/vm/corelib.cpp index c0a217593adc..e172f6a5423e 100644 --- a/src/coreclr/vm/corelib.cpp +++ b/src/coreclr/vm/corelib.cpp @@ -47,7 +47,6 @@ #ifdef FEATURE_COMINTEROP #include "variant.h" -#include "oavariant.h" #include "mngstdinterfaces.h" #endif // FEATURE_COMINTEROP diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index c14fc7a69ecb..17f74503bdc2 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -261,6 +261,14 @@ DEFINE_CLASS(UINT128, System, UInt128) DEFINE_CLASS(MATH, System, Math) DEFINE_METHOD(MATH, ROUND, Round, SM_Dbl_RetDbl) +#ifndef TARGET_64BIT +DEFINE_METHOD(MATH, MULTIPLY_CHECKED_INT64, MultiplyChecked, SM_Long_Long_RetLong) +DEFINE_METHOD(MATH, MULTIPLY_CHECKED_UINT64, MultiplyChecked, SM_ULong_ULong_RetULong) +#endif +DEFINE_METHOD(MATH, CONVERT_TO_INT32_CHECKED, ConvertToInt32Checked, NoSig) +DEFINE_METHOD(MATH, CONVERT_TO_UINT32_CHECKED, ConvertToUInt32Checked, NoSig) +DEFINE_METHOD(MATH, CONVERT_TO_INT64_CHECKED, ConvertToInt64Checked, NoSig) +DEFINE_METHOD(MATH, CONVERT_TO_UINT64_CHECKED, ConvertToUInt64Checked, NoSig) DEFINE_CLASS(MATHF, System, MathF) DEFINE_METHOD(MATHF, ROUND, Round, SM_Flt_RetFlt) @@ -337,8 +345,8 @@ DEFINE_METHOD(RT_TYPE_HANDLE, ALLOCATECOMOBJECT, AllocateComObject, #endif DEFINE_FIELD(RT_TYPE_HANDLE, M_TYPE, m_type) -DEFINE_CLASS(TYPE_NAME_PARSER, Reflection, TypeNameParser) -DEFINE_METHOD(TYPE_NAME_PARSER, GET_TYPE_HELPER, GetTypeHelper, SM_Type_CharPtr_RuntimeAssembly_Bool_Bool_RetRuntimeType) +DEFINE_CLASS(TYPE_NAME_RESOLVER, Reflection, TypeNameResolver) +DEFINE_METHOD(TYPE_NAME_RESOLVER, GET_TYPE_HELPER, GetTypeHelper, SM_Type_CharPtr_RuntimeAssembly_Bool_Bool_RetRuntimeType) DEFINE_CLASS_U(Reflection, RtFieldInfo, NoClass) DEFINE_FIELD_U(m_fieldHandle, ReflectFieldObject, m_pFD) @@ -583,6 +591,10 @@ END_ILLINK_FEATURE_SWITCH() DEFINE_CLASS(MONITOR, Threading, Monitor) DEFINE_METHOD(MONITOR, ENTER, Enter, SM_Obj_RetVoid) +DEFINE_CLASS(THREAD_BLOCKING_INFO, Threading, ThreadBlockingInfo) +DEFINE_FIELD(THREAD_BLOCKING_INFO, OFFSET_OF_LOCK_OWNER_OS_THREAD_ID, s_monitorObjectOffsetOfLockOwnerOSThreadId) +DEFINE_FIELD(THREAD_BLOCKING_INFO, FIRST, t_first) + DEFINE_CLASS(PARAMETER, Reflection, ParameterInfo) DEFINE_CLASS(PARAMETER_MODIFIER, Reflection, ParameterModifier) @@ -604,11 +616,6 @@ DEFINE_METHOD(PROPERTY, GET_GETTER, GetGetMethod, DEFINE_CLASS(PROPERTY_INFO, Reflection, PropertyInfo) - - -DEFINE_CLASS(METADATA_IMPORT, Reflection, MetadataImport) -DEFINE_METHOD(METADATA_IMPORT, THROW_ERROR, ThrowError, SM_Int_RetVoid) - DEFINE_CLASS(RESOLVER, System, Resolver) DEFINE_METHOD(RESOLVER, GET_JIT_CONTEXT, GetJitContext, IM_RefInt_RetRuntimeType) DEFINE_METHOD(RESOLVER, GET_CODE_INFO, GetCodeInfo, IM_RefInt_RefInt_RefInt_RetArrByte) @@ -892,6 +899,7 @@ DEFINE_METHOD(DEBUGGER, BREAK, Break, DEFINE_CLASS(BUFFER, System, Buffer) DEFINE_METHOD(BUFFER, MEMCPY_PTRBYTE_ARRBYTE, Memcpy, SM_PtrByte_Int_ArrByte_Int_Int_RetVoid) DEFINE_METHOD(BUFFER, MEMCPY, Memcpy, SM_PtrByte_PtrByte_Int_RetVoid) +DEFINE_METHOD(BUFFER, MEMCOPYGC, BulkMoveWithWriteBarrier, SM_RefByte_RefByte_UIntPtr_RetVoid) DEFINE_CLASS(STUBHELPERS, StubHelpers, StubHelpers) DEFINE_METHOD(STUBHELPERS, GET_DELEGATE_TARGET, GetDelegateTarget, SM_Delegate_RetIntPtr) diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index b85331e00ce8..c0e4091af38a 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -691,9 +691,9 @@ HRESULT CorHost2::CreateDelegate( EMPTY_STRING_TO_NULL(wszClassName); EMPTY_STRING_TO_NULL(wszMethodName); - if (fnPtr == NULL) + if (fnPtr == 0) return E_POINTER; - *fnPtr = NULL; + *fnPtr = 0; if(wszAssemblyName == NULL) return E_INVALIDARG; diff --git a/src/coreclr/vm/crossloaderallocatorhash.h b/src/coreclr/vm/crossloaderallocatorhash.h index d23ddc0db225..735f20382b80 100644 --- a/src/coreclr/vm/crossloaderallocatorhash.h +++ b/src/coreclr/vm/crossloaderallocatorhash.h @@ -21,8 +21,8 @@ class NoRemoveDefaultCrossLoaderAllocatorHashTraits static const bool s_supports_remove = false; // CrossLoaderAllocatorHash requires that a particular null value exist, which represents an empty value slot - static bool IsNullValue(const TValue &value) { return value == NULL; } - static TValue NullValue() { return NULL; } + static bool IsNullValue(const TValue &value) { return value == (TValue)NULL; } + static TValue NullValue() { return (TValue)NULL; } static BOOL KeyEquals(const TKey &k1, const TKey &k2) { return k1 == k2; } static BOOL ValueEquals(const TValue &v1, const TValue &v2) { return v1 == v2; } diff --git a/src/coreclr/vm/custommarshalerinfo.cpp b/src/coreclr/vm/custommarshalerinfo.cpp index 81c4122512e6..4c7a93441fcf 100644 --- a/src/coreclr/vm/custommarshalerinfo.cpp +++ b/src/coreclr/vm/custommarshalerinfo.cpp @@ -25,7 +25,7 @@ CustomMarshalerInfo::CustomMarshalerInfo(LoaderAllocator *pLoaderAllocator, Type : m_NativeSize(0) , m_hndManagedType(hndManagedType) , m_pLoaderAllocator(pLoaderAllocator) -, m_hndCustomMarshaler(NULL) +, m_hndCustomMarshaler{} , m_pMarshalNativeToManagedMD(NULL) , m_pMarshalManagedToNativeMD(NULL) , m_pCleanUpNativeDataMD(NULL) @@ -139,7 +139,7 @@ CustomMarshalerInfo::~CustomMarshalerInfo() // been collected already. m_pLoaderAllocator->FreeHandle(m_hndCustomMarshaler); } - m_hndCustomMarshaler = NULL; + m_hndCustomMarshaler = 0; } @@ -639,7 +639,7 @@ CustomMarshalerInfo *SharedCustomMarshalerHelper::GetCustomMarshalerInfo() CONTRACTL_END; // Retrieve the marshalling data for the current app domain. - EEMarshalingData *pMarshalingData = GetThread()->GetDomain()->GetLoaderAllocator()->GetMarshalingData(); + EEMarshalingData *pMarshalingData = AppDomain::GetCurrentDomain()->GetLoaderAllocator()->GetMarshalingData(); // Retrieve the custom marshaling information for the current shared custom // marshaling helper. diff --git a/src/coreclr/vm/dacenumerablehash.inl b/src/coreclr/vm/dacenumerablehash.inl index 93d63116e0f4..eb8bd5df6a9c 100644 --- a/src/coreclr/vm/dacenumerablehash.inl +++ b/src/coreclr/vm/dacenumerablehash.inl @@ -540,7 +540,7 @@ void DacEnumerableHashTable::BaseInitIterator(BaseIterator * LIMITED_METHOD_DAC_CONTRACT; pIterator->m_pTable = dac_cast)>(this); - pIterator->m_pEntry = NULL; + pIterator->m_pEntry = (TADDR)0; //+2 to skip "length" and "next" slots pIterator->m_dwBucket = SKIP_SPECIAL_SLOTS; } @@ -564,7 +564,7 @@ DPTR(VALUE) DacEnumerableHashTable::BaseIterator::Next() while (m_dwBucket < cBuckets + SKIP_SPECIAL_SLOTS) { - if (m_pEntry == NULL) + if (m_pEntry == (TADDR)0) { // This is our first lookup for a particular bucket, return the first // entry in that bucket. @@ -583,7 +583,7 @@ DPTR(VALUE) DacEnumerableHashTable::BaseIterator::Next() // Otherwise we found the end of a bucket chain. Increment the current bucket and, if there are // buckets left to scan go back around again. - m_pEntry = NULL; + m_pEntry = (TADDR)0; m_dwBucket++; } diff --git a/src/coreclr/vm/debugdebugger.cpp b/src/coreclr/vm/debugdebugger.cpp index a6bdd075afc4..96cc3d1f2043 100644 --- a/src/coreclr/vm/debugdebugger.cpp +++ b/src/coreclr/vm/debugdebugger.cpp @@ -765,7 +765,7 @@ extern MethodDesc* QCALLTYPE StackFrame_GetMethodDescFromNativeIP(LPVOID ip) } FORCEINLINE void HolderDestroyStrongHandle(OBJECTHANDLE h) { if (h != NULL) DestroyStrongHandle(h); } -typedef Wrapper, HolderDestroyStrongHandle, NULL> StrongHandleHolder; +typedef Wrapper, HolderDestroyStrongHandle, 0> StrongHandleHolder; // receives a custom notification object from the target and sends it to the RS via // code:Debugger::SendCustomDebuggerNotification @@ -787,7 +787,7 @@ FCIMPL1(void, DebugDebugger::CustomNotification, Object * dataUNSAFE) HELPER_METHOD_FRAME_BEGIN_PROTECT(pData); Thread * pThread = GetThread(); - AppDomain * pAppDomain = pThread->GetDomain(); + AppDomain * pAppDomain = AppDomain::GetCurrentDomain(); StrongHandleHolder objHandle = pAppDomain->CreateStrongHandle(pData); MethodTable * pMT = pData->GetGCSafeMethodTable(); @@ -977,7 +977,7 @@ StackWalkAction DebugStackTrace::GetStackFramesCallback(CrawlFrame* pCf, VOID* d } else { - ip = NULL; + ip = (PCODE)NULL; dwNativeOffset = 0; } @@ -1162,7 +1162,7 @@ void DebugStackTrace::DebugStackTraceElement::InitPass2() #ifdef DEBUGGING_SUPPORTED // Calculate the IL offset using the debugging services - if ((this->ip != NULL) && g_pDebugInterface) + if ((this->ip != (PCODE)NULL) && g_pDebugInterface) { // To get the source line number of the actual code that threw an exception, the dwOffset needs to be // adjusted in certain cases when calculating the IL offset. diff --git a/src/coreclr/vm/debuginfostore.cpp b/src/coreclr/vm/debuginfostore.cpp index 41978c952dbe..84269d8b7b0a 100644 --- a/src/coreclr/vm/debuginfostore.cpp +++ b/src/coreclr/vm/debuginfostore.cpp @@ -1036,7 +1036,7 @@ void DebugInfoManager::EnumMemoryRegionsForMethodDebugInfo(CLRDataEnumMemoryFlag CONTRACTL_END; PCODE addrCode = pMD->GetNativeCode(); - if (addrCode == NULL) + if (addrCode == (PCODE)NULL) { return; } diff --git a/src/coreclr/vm/decodemd.cpp b/src/coreclr/vm/decodemd.cpp index e1f7e8e3877a..e3ba6907488e 100644 --- a/src/coreclr/vm/decodemd.cpp +++ b/src/coreclr/vm/decodemd.cpp @@ -72,7 +72,7 @@ const BYTE decoded_10[2] = {10, END_DECODED }; #define DECODING_BITS(partial, got, header) (DOING_BITS+((partial)<<8)+((got)<<16)+((header)<<24)) #define DECODING_ERROR ((unsigned) -1) #define MASK(len) (~(~0u <<(len))) -#define MASK64(len) ((~((~((unsigned __int64)0))<<(len)))) +#define MASK64(len) ((~((~((uint64_t)0))<<(len)))) const Decoder::Decode emptyDecode = {decoded_end, DECODING_HEADER(0)}; @@ -415,8 +415,8 @@ void Encoder::Encode(unsigned value) } if (value < BASE_6) { - unsigned __int64 value64 = (unsigned __int64) value; - Add64((((unsigned __int64)0x1f)<<(1+BIT_LENGTH_5))+(value64-BASE_5), 6+BIT_LENGTH_5); + uint64_t value64 = (uint64_t) value; + Add64((((uint64_t)0x1f)<<(1+BIT_LENGTH_5))+(value64-BASE_5), 6+BIT_LENGTH_5); return; } _ASSERTE(!"Too big"); @@ -461,7 +461,7 @@ void Encoder::Add(unsigned value, unsigned length) } // -------------------------------------------------------- -void Encoder::Add64(unsigned __int64 value, unsigned length) +void Encoder::Add64(uint64_t value, unsigned length) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; diff --git a/src/coreclr/vm/decodemd.h b/src/coreclr/vm/decodemd.h index 7499f429e090..af430cb338f0 100644 --- a/src/coreclr/vm/decodemd.h +++ b/src/coreclr/vm/decodemd.h @@ -61,7 +61,7 @@ class Encoder void Encode(unsigned value); void Encode(signed value, BOOL isSigned); void Add(unsigned value, unsigned length); - void Add64(unsigned __int64 value, unsigned length); + void Add64(uint64_t value, unsigned length); void Done(); unsigned Contents(BYTE** contents); unsigned Length(); diff --git a/src/coreclr/vm/dispatchinfo.cpp b/src/coreclr/vm/dispatchinfo.cpp index 8b769c71bcc0..cdac9f523262 100644 --- a/src/coreclr/vm/dispatchinfo.cpp +++ b/src/coreclr/vm/dispatchinfo.cpp @@ -1256,7 +1256,7 @@ void DispatchInfo::InvokeMemberWorker(DispatchMemberInfo* pDispMemberInfo, EnumMemberTypes MemberType; Thread* pThread = GetThread(); - AppDomain* pAppDomain = pThread->GetDomain(); + AppDomain* pAppDomain = AppDomain::GetCurrentDomain(); SafeArrayPtrHolder pSA = NULL; VARIANT safeArrayVar; diff --git a/src/coreclr/vm/dispparammarshaler.cpp b/src/coreclr/vm/dispparammarshaler.cpp index 8bf08febd8dc..9286bd1ec39f 100644 --- a/src/coreclr/vm/dispparammarshaler.cpp +++ b/src/coreclr/vm/dispparammarshaler.cpp @@ -101,7 +101,7 @@ void DispParamOleColorMarshaler::MarshalNativeToManaged(VARIANT *pSrcVar, OBJECT // Box the System.Drawing.Color value class and give back the boxed object. TypeHandle hndColorType = - GetThread()->GetDomain()->GetLoaderAllocator()->GetMarshalingData()->GetOleColorMarshalingInfo()->GetColorType(); + AppDomain::GetCurrentDomain()->GetLoaderAllocator()->GetMarshalingData()->GetOleColorMarshalingInfo()->GetColorType(); *pDestObj = hndColorType.GetMethodTable()->Box(&MngColor); } diff --git a/src/coreclr/vm/dllimport.cpp b/src/coreclr/vm/dllimport.cpp index 208db4b2ea2d..830fbe5a6e1d 100644 --- a/src/coreclr/vm/dllimport.cpp +++ b/src/coreclr/vm/dllimport.cpp @@ -5610,7 +5610,7 @@ PCODE NDirect::GetStubForILStub(NDirectMethodDesc* pNMD, MethodDesc** ppStubMD, { STANDARD_VM_CONTRACT; - PCODE pStub = NULL; + PCODE pStub = (PCODE)NULL; CONSISTENCY_CHECK(*ppStubMD == NULL); @@ -5620,7 +5620,7 @@ PCODE NDirect::GetStubForILStub(NDirectMethodDesc* pNMD, MethodDesc** ppStubMD, *ppStubMD = NDirect::GetILStubMethodDesc(pNMD, &sigInfo, dwStubFlags); if (SF_IsForNumParamBytes(dwStubFlags)) - return NULL; + return (PCODE)NULL; if (*ppStubMD) { @@ -5667,7 +5667,7 @@ PCODE JitILStub(MethodDesc* pStubMD) PCODE pCode = pStubMD->GetNativeCode(); - if (pCode == NULL) + if (pCode == (PCODE)NULL) { /////////////////////////////// // @@ -5720,7 +5720,7 @@ PCODE GetStubForInteropMethod(MethodDesc* pMD, DWORD dwStubFlags) } CONTRACT_END; - PCODE pStub = NULL; + PCODE pStub = (PCODE)NULL; MethodDesc* pStubMD = NULL; if (pMD->IsNDirect()) @@ -6022,7 +6022,7 @@ PCODE GetILStubForCalli(VASigCookie *pVASigCookie, MethodDesc *pMD) } CONTRACT_END; - PCODE pTempILStub = NULL; + PCODE pTempILStub = (PCODE)NULL; INSTALL_MANAGED_EXCEPTION_DISPATCHER; // this function is called by CLR to native assembly stubs which are called by @@ -6125,7 +6125,7 @@ PCODE GetILStubForCalli(VASigCookie *pVASigCookie, MethodDesc *pMD) InterlockedCompareExchangeT(&pVASigCookie->pNDirectILStub, pTempILStub, - NULL); + (PCODE)NULL); UNINSTALL_UNWIND_AND_CONTINUE_HANDLER; UNINSTALL_MANAGED_EXCEPTION_DISPATCHER; diff --git a/src/coreclr/vm/dllimportcallback.cpp b/src/coreclr/vm/dllimportcallback.cpp index 4eeab74f68d8..b9befb2d4c5e 100644 --- a/src/coreclr/vm/dllimportcallback.cpp +++ b/src/coreclr/vm/dllimportcallback.cpp @@ -166,7 +166,7 @@ UMEntryThunk *UMEntryThunkCache::GetUMEntryThunk(MethodDesc *pMD) marshInfoWriterHolder.GetRW()->LoadTimeInit(pMD); ExecutableWriterHolder thunkWriterHolder(pThunk, sizeof(UMEntryThunk)); - thunkWriterHolder.GetRW()->LoadTimeInit(pThunk, NULL, NULL, pMarshInfo, pMD); + thunkWriterHolder.GetRW()->LoadTimeInit(pThunk, (PCODE)NULL, NULL, pMarshInfo, pMD); // add it to the cache CacheElement element; diff --git a/src/coreclr/vm/domainassembly.cpp b/src/coreclr/vm/domainassembly.cpp index 823348d32f23..75995f477a32 100644 --- a/src/coreclr/vm/domainassembly.cpp +++ b/src/coreclr/vm/domainassembly.cpp @@ -23,10 +23,6 @@ #include "dllimportcallback.h" #include "peimagelayout.inl" -#ifdef FEATURE_PERFMAP -#include "perfmap.h" -#endif // FEATURE_PERFMAP - #ifndef DACCESS_COMPILE DomainAssembly::DomainAssembly(PEAssembly* pPEAssembly, LoaderAllocator* pLoaderAllocator) : m_pAssembly(NULL), @@ -37,8 +33,8 @@ DomainAssembly::DomainAssembly(PEAssembly* pPEAssembly, LoaderAllocator* pLoader m_pLoaderAllocator(pLoaderAllocator), m_level(FILE_LOAD_CREATE), m_loading(TRUE), - m_hExposedModuleObject(NULL), - m_hExposedAssemblyObject(NULL), + m_hExposedModuleObject{}, + m_hExposedAssemblyObject{}, m_pError(NULL), m_bDisableActivationCheck(FALSE), m_fHostAssemblyPublished(FALSE), @@ -332,26 +328,26 @@ OBJECTREF DomainAssembly::GetExposedModuleObject() LoaderAllocator * pLoaderAllocator = GetLoaderAllocator(); - if (m_hExposedModuleObject == NULL) + if (m_hExposedModuleObject == (LOADERHANDLE)NULL) { // Atomically create a handle LOADERHANDLE handle = pLoaderAllocator->AllocateHandle(NULL); - InterlockedCompareExchangeT(&m_hExposedModuleObject, handle, static_cast(NULL)); + InterlockedCompareExchangeT(&m_hExposedModuleObject, handle, static_cast(0)); } if (pLoaderAllocator->GetHandleValue(m_hExposedModuleObject) == NULL) { REFLECTMODULEBASEREF refClass = NULL; - // Will be TRUE only if LoaderAllocator managed object was already collected and therefore we should + // Will be true only if LoaderAllocator managed object was already collected and therefore we should // return NULL - BOOL fIsLoaderAllocatorCollected = FALSE; + bool fIsLoaderAllocatorCollected = false; GCPROTECT_BEGIN(refClass); refClass = (REFLECTMODULEBASEREF) AllocateObject(CoreLibBinder::GetClass(CLASS__MODULE)); - refClass->SetModule(m_pModule); + refClass->SetModule(GetModule()); // Attach the reference to the assembly to keep the LoaderAllocator for this collectible type // alive as long as a reference to the module is kept alive. @@ -360,7 +356,7 @@ OBJECTREF DomainAssembly::GetExposedModuleObject() OBJECTREF refAssembly = GetModule()->GetAssembly()->GetExposedObject(); if ((refAssembly == NULL) && GetModule()->GetAssembly()->IsCollectible()) { - fIsLoaderAllocatorCollected = TRUE; + fIsLoaderAllocatorCollected = true; } refClass->SetAssembly(refAssembly); } @@ -558,11 +554,6 @@ void DomainAssembly::FinishLoad() // Set a bit to indicate that the module has been loaded in some domain, and therefore // typeloads can involve types from this module. (Used for candidate instantiations.) GetModule()->SetIsReadyForTypeLoad(); - -#ifdef FEATURE_PERFMAP - // Notify the perfmap of the IL image load. - PerfMap::LogImageLoad(m_pPEAssembly); -#endif } void DomainAssembly::Activate() @@ -648,13 +639,13 @@ OBJECTREF DomainAssembly::GetExposedAssemblyObject() return NULL; } - if (m_hExposedAssemblyObject == NULL) + if (m_hExposedAssemblyObject == (LOADERHANDLE)NULL) { // Atomically create a handle LOADERHANDLE handle = pLoaderAllocator->AllocateHandle(NULL); - InterlockedCompareExchangeT(&m_hExposedAssemblyObject, handle, static_cast(NULL)); + InterlockedCompareExchangeT(&m_hExposedAssemblyObject, handle, static_cast(0)); } if (pLoaderAllocator->GetHandleValue(m_hExposedAssemblyObject) == NULL) diff --git a/src/coreclr/vm/dynamicmethod.cpp b/src/coreclr/vm/dynamicmethod.cpp index beeb0cd64b2a..12c5d6f0386f 100644 --- a/src/coreclr/vm/dynamicmethod.cpp +++ b/src/coreclr/vm/dynamicmethod.cpp @@ -898,7 +898,7 @@ void DynamicMethodDesc::Destroy() delete[] pszMethodName; } - if (pSig != NULL) + if (pSig != (PCODE)NULL) { delete[] (BYTE*)pSig; } diff --git a/src/coreclr/vm/ecall.cpp b/src/coreclr/vm/ecall.cpp index 35a5d36eae4d..d3e8415d6ade 100644 --- a/src/coreclr/vm/ecall.cpp +++ b/src/coreclr/vm/ecall.cpp @@ -157,6 +157,36 @@ void ECall::PopulateManagedHelpers() pDest = pMD->GetMultiCallableAddrOfCode(); SetJitHelperFunction(CORINFO_HELP_MEMCPY, pDest); + pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__BUFFER__MEMCOPYGC)); + pDest = pMD->GetMultiCallableAddrOfCode(); + SetJitHelperFunction(CORINFO_HELP_BULK_WRITEBARRIER, pDest); + +#ifndef TARGET_64BIT + pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__MATH__MULTIPLY_CHECKED_INT64)); + pDest = pMD->GetMultiCallableAddrOfCode(); + SetJitHelperFunction(CORINFO_HELP_LMUL_OVF, pDest); + + pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__MATH__MULTIPLY_CHECKED_UINT64)); + pDest = pMD->GetMultiCallableAddrOfCode(); + SetJitHelperFunction(CORINFO_HELP_ULMUL_OVF, pDest); +#endif + + pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__MATH__CONVERT_TO_INT32_CHECKED)); + pDest = pMD->GetMultiCallableAddrOfCode(); + SetJitHelperFunction(CORINFO_HELP_DBL2INT_OVF, pDest); + + pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__MATH__CONVERT_TO_UINT32_CHECKED)); + pDest = pMD->GetMultiCallableAddrOfCode(); + SetJitHelperFunction(CORINFO_HELP_DBL2UINT_OVF, pDest); + + pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__MATH__CONVERT_TO_INT64_CHECKED)); + pDest = pMD->GetMultiCallableAddrOfCode(); + SetJitHelperFunction(CORINFO_HELP_DBL2LNG_OVF, pDest); + + pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__MATH__CONVERT_TO_UINT64_CHECKED)); + pDest = pMD->GetMultiCallableAddrOfCode(); + SetJitHelperFunction(CORINFO_HELP_DBL2ULNG_OVF, pDest); + pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__MATH__ROUND)); pDest = pMD->GetMultiCallableAddrOfCode(); SetJitHelperFunction(CORINFO_HELP_DBLROUND, pDest); diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index fa4f8cb48568..98a38b860341 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -56,7 +56,6 @@ FCFuncEnd() FCFuncStart(gEnumFuncs) FCFuncElement("InternalGetCorElementType", ReflectionEnum::InternalGetCorElementType) - FCFuncElement("InternalBoxEnum", ReflectionEnum::InternalBoxEnum) FCFuncEnd() FCFuncStart(gObjectFuncs) @@ -114,9 +113,7 @@ FCFuncEnd() FCFuncStart(gSystem_RuntimeType) FCFuncElement("GetGUID", ReflectionInvocation::GetGUID) - FCFuncElement("_CreateEnum", ReflectionInvocation::CreateEnum) FCFuncElement("CanValueSpecialCast", ReflectionInvocation::CanValueSpecialCast) - FCFuncElement("AllocateValueType", ReflectionInvocation::AllocateValueType) #if defined(FEATURE_COMINTEROP) FCFuncElement("InvokeDispMethod", ReflectionInvocation::InvokeDispMethod) #endif // defined(FEATURE_COMINTEROP) @@ -140,7 +137,6 @@ FCFuncStart(gCOMTypeHandleFuncs) FCFuncElement("GetFields", RuntimeTypeHandle::GetFields) FCFuncElement("GetInterfaces", RuntimeTypeHandle::GetInterfaces) FCFuncElement("GetAttributes", RuntimeTypeHandle::GetAttributes) - FCFuncElement("_GetMetadataImport", RuntimeTypeHandle::GetMetadataImport) FCFuncElement("GetNumVirtuals", RuntimeTypeHandle::GetNumVirtuals) FCFuncElement("GetNumVirtualsAndStaticVirtuals", RuntimeTypeHandle::GetNumVirtualsAndStaticVirtuals) FCFuncElement("CanCastTo", RuntimeTypeHandle::CanCastTo) @@ -159,31 +155,31 @@ FCFuncStart(gCOMTypeHandleFuncs) FCFuncEnd() FCFuncStart(gMetaDataImport) - FCFuncElement("_GetDefaultValue", MetaDataImport::GetDefaultValue) - FCFuncElement("_GetName", MetaDataImport::GetName) - FCFuncElement("_GetUserString", MetaDataImport::GetUserString) - FCFuncElement("_GetScopeProps", MetaDataImport::GetScopeProps) - FCFuncElement("_GetClassLayout", MetaDataImport::GetClassLayout) - FCFuncElement("_GetSignatureFromToken", MetaDataImport::GetSignatureFromToken) - FCFuncElement("_GetNamespace", MetaDataImport::GetNamespace) - FCFuncElement("_GetEventProps", MetaDataImport::GetEventProps) - FCFuncElement("_GetFieldDefProps", MetaDataImport::GetFieldDefProps) - FCFuncElement("_GetPropertyProps", MetaDataImport::GetPropertyProps) - FCFuncElement("_GetParentToken", MetaDataImport::GetParentToken) - FCFuncElement("_GetParamDefProps", MetaDataImport::GetParamDefProps) - FCFuncElement("_GetGenericParamProps", MetaDataImport::GetGenericParamProps) - - FCFuncElement("_Enum", MetaDataImport::Enum) - FCFuncElement("_GetMemberRefProps", MetaDataImport::GetMemberRefProps) - FCFuncElement("_GetCustomAttributeProps", MetaDataImport::GetCustomAttributeProps) - FCFuncElement("_GetFieldOffset", MetaDataImport::GetFieldOffset) - - FCFuncElement("_GetSigOfFieldDef", MetaDataImport::GetSigOfFieldDef) - FCFuncElement("_GetSigOfMethodDef", MetaDataImport::GetSigOfMethodDef) - FCFuncElement("_GetFieldMarshal", MetaDataImport::GetFieldMarshal) - FCFuncElement("_GetPInvokeMap", MetaDataImport::GetPinvokeMap) - FCFuncElement("_IsValidToken", MetaDataImport::IsValidToken) - FCFuncElement("_GetMarshalAs", MetaDataImport::GetMarshalAs) + FCFuncElement("GetMetadataImport", MetaDataImport::GetMetadataImport) + FCFuncElement("GetDefaultValue", MetaDataImport::GetDefaultValue) + FCFuncElement("GetName", MetaDataImport::GetName) + FCFuncElement("GetUserString", MetaDataImport::GetUserString) + FCFuncElement("GetScopeProps", MetaDataImport::GetScopeProps) + FCFuncElement("GetClassLayout", MetaDataImport::GetClassLayout) + FCFuncElement("GetSignatureFromToken", MetaDataImport::GetSignatureFromToken) + FCFuncElement("GetNamespace", MetaDataImport::GetNamespace) + FCFuncElement("GetEventProps", MetaDataImport::GetEventProps) + FCFuncElement("GetFieldDefProps", MetaDataImport::GetFieldDefProps) + FCFuncElement("GetPropertyProps", MetaDataImport::GetPropertyProps) + FCFuncElement("GetParentToken", MetaDataImport::GetParentToken) + FCFuncElement("GetParamDefProps", MetaDataImport::GetParamDefProps) + FCFuncElement("GetGenericParamProps", MetaDataImport::GetGenericParamProps) + + FCFuncElement("GetMemberRefProps", MetaDataImport::GetMemberRefProps) + FCFuncElement("GetCustomAttributeProps", MetaDataImport::GetCustomAttributeProps) + FCFuncElement("GetFieldOffset", MetaDataImport::GetFieldOffset) + + FCFuncElement("GetSigOfFieldDef", MetaDataImport::GetSigOfFieldDef) + FCFuncElement("GetSigOfMethodDef", MetaDataImport::GetSigOfMethodDef) + FCFuncElement("GetFieldMarshal", MetaDataImport::GetFieldMarshal) + FCFuncElement("GetPInvokeMap", MetaDataImport::GetPInvokeMap) + FCFuncElement("IsValidToken", MetaDataImport::IsValidToken) + FCFuncElement("GetMarshalAs", MetaDataImport::GetMarshalAs) FCFuncEnd() FCFuncStart(gSignatureNative) @@ -240,7 +236,6 @@ FCFuncEnd() FCFuncStart(gCOMModuleHandleFuncs) FCFuncElement("GetToken", ModuleHandle::GetToken) FCFuncElement("GetDynamicMethod", ModuleHandle::GetDynamicMethod) - FCFuncElement("_GetMetadataImport", ModuleHandle::GetMetadataImport) FCFuncElement("GetMDStreamVersion", ModuleHandle::GetMDStreamVersion) FCFuncEnd() diff --git a/src/coreclr/vm/eedbginterfaceimpl.cpp b/src/coreclr/vm/eedbginterfaceimpl.cpp index 08adac721334..822a46a536e3 100644 --- a/src/coreclr/vm/eedbginterfaceimpl.cpp +++ b/src/coreclr/vm/eedbginterfaceimpl.cpp @@ -546,11 +546,11 @@ void EEDbgInterfaceImpl::GetMethodRegionInfo(const PCODE pStart, } CONTRACTL_END; - IJitManager::MethodRegionInfo methodRegionInfo = {NULL, 0, NULL, 0}; + IJitManager::MethodRegionInfo methodRegionInfo = {(TADDR)NULL, 0, (TADDR)NULL, 0}; EECodeInfo codeInfo(pStart); - if (codeInfo.IsValid() != NULL) + if (codeInfo.IsValid() != (TADDR)NULL) { codeInfo.GetMethodRegionInfo(&methodRegionInfo); } @@ -611,7 +611,7 @@ size_t EEDbgInterfaceImpl::GetFunctionSize(MethodDesc *pFD) PCODE methodStart = pFD->GetNativeCode(); - if (methodStart == NULL) + if (methodStart == (PCODE)NULL) return 0; EECodeInfo codeInfo(methodStart); @@ -652,7 +652,7 @@ void EEDbgInterfaceImpl::EnablePreemptiveGC(void) CONTRACTL { NOTHROW; - DISABLED(GC_TRIGGERS); // Disabled because disabled in RareEnablePreemptiveGC() + GC_NOTRIGGER; } CONTRACTL_END; diff --git a/src/coreclr/vm/eetoprofinterfaceimpl.cpp b/src/coreclr/vm/eetoprofinterfaceimpl.cpp index 81614183fb5d..c57c3b897afd 100644 --- a/src/coreclr/vm/eetoprofinterfaceimpl.cpp +++ b/src/coreclr/vm/eetoprofinterfaceimpl.cpp @@ -1092,7 +1092,7 @@ UINT_PTR EEToProfInterfaceImpl::EEFunctionIDMapper(FunctionID funcId, BOOL * pbH // which means either m_pProfilersFuncIDMapper or m_pProfilersFuncIDMapper2 should not be NULL; _ASSERTE((m_pProfilersFuncIDMapper != NULL) || (m_pProfilersFuncIDMapper2 != NULL)); - UINT_PTR clientId = NULL; + UINT_PTR clientId = 0; if (m_pProfilersFuncIDMapper2 != NULL) { @@ -5762,7 +5762,7 @@ HRESULT EEToProfInterfaceImpl::HandleCreated(UINT_PTR handleId, ObjectID initial // switch to preemptive (as we normally do in callbacks) and must not trigger, // as this would really tick off some of our callers (as well as invalidating // initialObjectId). - if (initialObjectId != NULL) + if (initialObjectId != 0) { MODE_COOPERATIVE; } diff --git a/src/coreclr/vm/eetoprofinterfaceimpl.h b/src/coreclr/vm/eetoprofinterfaceimpl.h index 995daad9a02e..6c14c4150d43 100644 --- a/src/coreclr/vm/eetoprofinterfaceimpl.h +++ b/src/coreclr/vm/eetoprofinterfaceimpl.h @@ -657,16 +657,16 @@ class EEToProfInterfaceImpl { LIMITED_METHOD_CONTRACT; FunctionIDAndClientID functionIDAndClientID; - functionIDAndClientID.functionID = NULL; - functionIDAndClientID.clientID = NULL; + functionIDAndClientID.functionID = 0; + functionIDAndClientID.clientID = 0; return functionIDAndClientID; } static bool IsNull(const FunctionIDAndClientID &functionIDAndClientID) { LIMITED_METHOD_CONTRACT; - _ASSERTE((functionIDAndClientID.functionID != NULL) || (functionIDAndClientID.clientID == NULL)); - return functionIDAndClientID.functionID == NULL; + _ASSERTE((functionIDAndClientID.functionID != 0) || (functionIDAndClientID.clientID == 0)); + return functionIDAndClientID.functionID == 0; } }; diff --git a/src/coreclr/vm/eetoprofinterfaceimpl.inl b/src/coreclr/vm/eetoprofinterfaceimpl.inl index 1ed73db1f583..2791f9a7b2aa 100644 --- a/src/coreclr/vm/eetoprofinterfaceimpl.inl +++ b/src/coreclr/vm/eetoprofinterfaceimpl.inl @@ -222,7 +222,7 @@ inline UINT_PTR EEToProfInterfaceImpl::LookupClientIDFromCache(FunctionID functi } else { - return NULL; + return 0; } } diff --git a/src/coreclr/vm/eetwain.cpp b/src/coreclr/vm/eetwain.cpp index 4cdfc0852a6a..42a6776123f1 100644 --- a/src/coreclr/vm/eetwain.cpp +++ b/src/coreclr/vm/eetwain.cpp @@ -843,7 +843,22 @@ bool EECodeManager::IsGcSafe( EECodeInfo *pCodeInfo, dwRelOffset ); - return gcInfoDecoder.IsInterruptible(); + if (gcInfoDecoder.IsInterruptible()) + return true; + + if (InterruptibleSafePointsEnabled() && gcInfoDecoder.IsInterruptibleSafePoint()) + return true; + + return false; +} + +bool EECodeManager::InterruptibleSafePointsEnabled() +{ + LIMITED_METHOD_CONTRACT; + + // zero initialized + static ConfigDWORD interruptibleCallSitesEnabled; + return interruptibleCallSitesEnabled.val(CLRConfig::INTERNAL_InterruptibleCallSites) != 0; } #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) @@ -1421,7 +1436,8 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pRD, DECODE_INTERRUPTIBILITY, curOffs ); - if(!_gcInfoDecoder.IsInterruptible()) + if(!_gcInfoDecoder.IsInterruptible() && + !(InterruptibleSafePointsEnabled() && _gcInfoDecoder.IsInterruptibleSafePoint())) { // This must be the offset after a call #ifdef _DEBUG @@ -1441,7 +1457,8 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pRD, DECODE_INTERRUPTIBILITY, curOffs ); - _ASSERTE(_gcInfoDecoder.IsInterruptible()); + _ASSERTE(_gcInfoDecoder.IsInterruptible() || + (InterruptibleSafePointsEnabled() && _gcInfoDecoder.IsInterruptibleSafePoint())); } #endif @@ -1530,6 +1547,24 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pRD, curOffs ); + if ((flags & ActiveStackFrame) != 0) + { + // CONSIDER: We can optimize this by remembering the need to adjust in IsSafePoint and propagating into here. + // Or, better yet, maybe we should change the decoder to not require this adjustment. + // The scenario that adjustment tries to handle (fallthrough into BB with random liveness) + // does not seem possible. + if (!gcInfoDecoder.HasInterruptibleRanges()) + { + gcInfoDecoder = GcInfoDecoder( + gcInfoToken, + GcInfoDecoderFlags(DECODE_GC_LIFETIMES | DECODE_SECURITY_OBJECT | DECODE_VARARG), + curOffs - 1 + ); + + _ASSERTE((InterruptibleSafePointsEnabled() && gcInfoDecoder.IsInterruptibleSafePoint())); + } + } + if (!gcInfoDecoder.EnumerateLiveSlots( pRD, reportScratchSlots, @@ -2010,7 +2045,7 @@ void * EECodeManager::GetGSCookieAddr(PREGDISPLAY pContext, // Detect the end of GS cookie scope by comparing its address with SP // gcInfoDecoder.GetGSCookieValidRangeEnd() is not accurate. It does not // account for GS cookie going out of scope inside epilog or multiple epilogs. - return (LPVOID) ((ptr >= pContext->SP) ? ptr : NULL); + return (ptr >= pContext->SP) ? (LPVOID)ptr : nullptr; } } return NULL; diff --git a/src/coreclr/vm/encee.cpp b/src/coreclr/vm/encee.cpp index 9b6c487c11a3..7dec6bc20458 100644 --- a/src/coreclr/vm/encee.cpp +++ b/src/coreclr/vm/encee.cpp @@ -535,7 +535,7 @@ PCODE EditAndContinueModule::JitUpdatedFunction( MethodDesc *pMD, LOG((LF_ENC, LL_INFO100, "EnCModule::JitUpdatedFunction for %s::%s\n", pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName)); - PCODE jittedCode = NULL; + PCODE jittedCode = (PCODE)NULL; GCX_COOP(); @@ -648,7 +648,7 @@ HRESULT EditAndContinueModule::ResumeInUpdatedFunction( // JIT-compile the updated version of the method PCODE jittedCode = JitUpdatedFunction(pMD, pOrigContext); - if ( jittedCode == NULL ) + if ( jittedCode == (PCODE)NULL ) return CORDBG_E_ENC_JIT_CANT_UPDATE; GCX_COOP(); diff --git a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.cpp b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.cpp index 8542b2d0a904..b9443711b4aa 100644 --- a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.cpp +++ b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.cpp @@ -49,14 +49,14 @@ stack_walk_callback ( // Get the IP. UINT_PTR control_pc = (UINT_PTR)frame->GetRegisterSet ()->ControlPC; - if (control_pc == NULL) { + if (control_pc == 0) { if (ep_stack_contents_get_length (stack_contents) == 0) { // This happens for pinvoke stubs on the top of the stack. return SWA_CONTINUE; } } - EP_ASSERT (control_pc != NULL); + EP_ASSERT (control_pc != 0); // Add the IP to the captured stack. ep_stack_contents_append (stack_contents, control_pc, frame->GetFunction ()); diff --git a/src/coreclr/vm/eventpipeinternal.cpp b/src/coreclr/vm/eventpipeinternal.cpp index 57cf10ff30a1..29ad71677a3e 100644 --- a/src/coreclr/vm/eventpipeinternal.cpp +++ b/src/coreclr/vm/eventpipeinternal.cpp @@ -104,7 +104,7 @@ extern "C" INT_PTR QCALLTYPE EventPipeInternal_CreateProvider( extern "C" INT_PTR QCALLTYPE EventPipeInternal_DefineEvent( INT_PTR provHandle, UINT32 eventID, - __int64 keywords, + int64_t keywords, UINT32 eventVersion, UINT32 level, void *pMetadata, @@ -146,7 +146,7 @@ extern "C" void QCALLTYPE EventPipeInternal_DeleteProvider(INT_PTR provHandle) QCALL_CONTRACT; BEGIN_QCALL; - if (provHandle != NULL) + if (provHandle != 0) { EventPipeProvider *pProvider = reinterpret_cast(provHandle); EventPipeAdapter::DeleteProvider(pProvider); diff --git a/src/coreclr/vm/eventpipeinternal.h b/src/coreclr/vm/eventpipeinternal.h index 1ecbb79162e8..24740c821c78 100644 --- a/src/coreclr/vm/eventpipeinternal.h +++ b/src/coreclr/vm/eventpipeinternal.h @@ -61,7 +61,7 @@ extern "C" INT_PTR QCALLTYPE EventPipeInternal_CreateProvider( extern "C" INT_PTR QCALLTYPE EventPipeInternal_DefineEvent( INT_PTR provHandle, UINT32 eventID, - __int64 keywords, + int64_t keywords, UINT32 eventVersion, UINT32 level, void *pMetadata, diff --git a/src/coreclr/vm/eventtrace.cpp b/src/coreclr/vm/eventtrace.cpp index 1bac59f998fd..86da0269b379 100644 --- a/src/coreclr/vm/eventtrace.cpp +++ b/src/coreclr/vm/eventtrace.cpp @@ -577,7 +577,7 @@ VOID ETW::ThreadLog::FireThreadCreated(Thread * pThread) FireEtwThreadCreated( (ULONGLONG)pThread, - (ULONGLONG)pThread->GetDomain(), + (ULONGLONG)AppDomain::GetCurrentDomain(), GetEtwThreadFlags(pThread), pThread->GetThreadId(), pThread->GetOSThreadId(), @@ -590,7 +590,7 @@ VOID ETW::ThreadLog::FireThreadDC(Thread * pThread) FireEtwThreadDC( (ULONGLONG)pThread, - (ULONGLONG)pThread->GetDomain(), + (ULONGLONG)AppDomain::GetCurrentDomain(), GetEtwThreadFlags(pThread), pThread->GetThreadId(), pThread->GetOSThreadId(), @@ -643,7 +643,7 @@ class LoggedTypesFromModuleTraits : public NoRemoveSHashTraits< DefaultSHashTrai static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; - return (e.th.AsTAddr() == NULL); + return (e.th.AsTAddr() == 0); } static const element_t Null() @@ -4211,7 +4211,7 @@ static void GetCodeViewInfo(Module * pModule, CV_INFO_PDB70 * pCvInfoIL, CV_INFO // Some compilers set PointerToRawData but not AddressOfRawData as they put the // data at the end of the file in an unmapped part of the file - RVA rvaOfRawData = (rgDebugEntries[i].AddressOfRawData != NULL) ? + RVA rvaOfRawData = (rgDebugEntries[i].AddressOfRawData != 0) ? rgDebugEntries[i].AddressOfRawData : pLayout->OffsetToRva(rgDebugEntries[i].PointerToRawData); diff --git a/src/coreclr/vm/eventtrace_bulktype.cpp b/src/coreclr/vm/eventtrace_bulktype.cpp index 8e5a24e00c89..64a98988daad 100644 --- a/src/coreclr/vm/eventtrace_bulktype.cpp +++ b/src/coreclr/vm/eventtrace_bulktype.cpp @@ -425,12 +425,12 @@ void BulkStaticsLogger::FireBulkStaticsEvent() _ASSERTE(m_domain != NULL); unsigned short instance = GetClrInstanceId(); - unsigned __int64 appDomain = (unsigned __int64)m_domain; + uint64_t appDomain = (uint64_t)m_domain; #if !defined(HOST_UNIX) EVENT_DATA_DESCRIPTOR eventData[4]; EventDataDescCreate(&eventData[0], &m_count, sizeof(const unsigned int) ); - EventDataDescCreate(&eventData[1], &appDomain, sizeof(unsigned __int64) ); + EventDataDescCreate(&eventData[1], &appDomain, sizeof(uint64_t) ); EventDataDescCreate(&eventData[2], &instance, sizeof(const unsigned short) ); EventDataDescCreate(&eventData[3], m_buffer, m_used); diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index 7437a7988ada..cb1fe1e30a44 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -4742,7 +4742,7 @@ LONG InternalUnhandledExceptionFilter_Worker( // ignoring unhandled exceptions cannot be set on the default domain. if (IsFinalizerThread() || (pParam->pThread->IsThreadPoolThread())) - fIsProcessTerminating = !(pParam->pThread->GetDomain()->IgnoreUnhandledExceptions()); + fIsProcessTerminating = !(AppDomain::GetCurrentDomain()->IgnoreUnhandledExceptions()); else fIsProcessTerminating = !(pParam->pThread->HasThreadStateNC(Thread::TSNC_IgnoreUnhandledExceptions)); @@ -5787,7 +5787,7 @@ LPVOID COMPlusCheckForAbort(UINT_PTR uTryCatchResumeAddress) // Reverse COM interop IL stubs map all exceptions to HRESULTs and must not propagate Thread.Abort // to their unmanaged callers. - if (uTryCatchResumeAddress != NULL) + if (uTryCatchResumeAddress != (UINT_PTR)NULL) { MethodDesc * pMDResumeMethod = ExecutionManager::GetCodeMethodDesc((PCODE)uTryCatchResumeAddress); if (pMDResumeMethod->IsILStub()) @@ -6767,12 +6767,19 @@ VEH_ACTION WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_RETURN_ADDRESS_HIJACK_ATTEMPT) { + if (pThread == NULL || !pThread->PreemptiveGCDisabled()) + { + // We are not running managed code, so this cannot be our hijack + // Perhaps some other runtime is responsible. + return VEH_CONTINUE_SEARCH; + } + HijackArgs hijackArgs; hijackArgs.Rax = pExceptionInfo->ContextRecord->Rax; hijackArgs.Rsp = pExceptionInfo->ContextRecord->Rsp; - bool areCetShadowStacksEnabled = Thread::AreCetShadowStacksEnabled(); - if (areCetShadowStacksEnabled) + bool areShadowStacksEnabled = Thread::AreShadowStacksEnabled(); + if (areShadowStacksEnabled) { // When the CET is enabled, the return address is still on stack, so we need to set the Rsp as // if it was popped. @@ -6790,7 +6797,7 @@ VEH_ACTION WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo #undef CALLEE_SAVED_REGISTER pExceptionInfo->ContextRecord->Rax = hijackArgs.Rax; - if (areCetShadowStacksEnabled) + if (areShadowStacksEnabled) { // The context refers to the return instruction // Set the return address on the stack to the original one @@ -7894,10 +7901,10 @@ LONG NotifyOfCHFFilterWrapper( (pThread->GetExceptionState()->GetContextRecord() == NULL) || (GetSP(pThread->GetExceptionState()->GetContextRecord()) != GetSP(pExceptionInfo->ContextRecord) ) ) { - LOG((LF_EH, LL_INFO1000, "NotifyOfCHFFilterWrapper: not sending notices. pThread: %0x8", pThread)); + LOG((LF_EH, LL_INFO1000, "NotifyOfCHFFilterWrapper: not sending notices. pThread: %p", pThread)); if (pThread) { - LOG((LF_EH, LL_INFO1000, ", Thread SP: %0x8, Exception SP: %08x", + LOG((LF_EH, LL_INFO1000, ", Thread SP: %p, Exception SP: %p", pThread->GetExceptionState()->GetContextRecord() ? GetSP(pThread->GetExceptionState()->GetContextRecord()) : NULL, pExceptionInfo->ContextRecord ? GetSP(pExceptionInfo->ContextRecord) : NULL )); } diff --git a/src/coreclr/vm/excep.h b/src/coreclr/vm/excep.h index b84f0ef93e34..8e8ddacabe6b 100644 --- a/src/coreclr/vm/excep.h +++ b/src/coreclr/vm/excep.h @@ -503,7 +503,7 @@ extern "C" BOOL ExceptionIsOfRightType(TypeHandle clauseType, TypeHandle thrownT // Specify NULL for uTryCatchResumeAddress when not checking for a InducedThreadRedirectAtEndOfCatch -EXTERN_C LPVOID COMPlusCheckForAbort(UINT_PTR uTryCatchResumeAddress = NULL); +EXTERN_C LPVOID COMPlusCheckForAbort(UINT_PTR uTryCatchResumeAddress = 0); BOOL IsThreadHijackedForThreadStop(Thread* pThread, EXCEPTION_RECORD* pExceptionRecord); void AdjustContextForThreadStop(Thread* pThread, T_CONTEXT* pContext); diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index e4901303f186..6033dd4ad02f 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -867,7 +867,7 @@ UINT_PTR ExceptionTracker::FinishSecondPass( void CleanUpForSecondPass(Thread* pThread, bool fIsSO, LPVOID MemoryStackFpForFrameChain, LPVOID MemoryStackFp); -static void PopExplicitFrames(Thread *pThread, void *targetSp) +static void PopExplicitFrames(Thread *pThread, void *targetSp, void *targetCallerSp) { Frame* pFrame = pThread->GetFrame(); while (pFrame < targetSp) @@ -877,6 +877,39 @@ static void PopExplicitFrames(Thread *pThread, void *targetSp) pFrame = pThread->GetFrame(); } + // Check if the pFrame is an active InlinedCallFrame inside of the target frame. It needs to be popped or inactivated depending + // on the target architecture / ready to run + if ((pFrame < targetCallerSp) && InlinedCallFrame::FrameHasActiveCall(pFrame)) + { + InlinedCallFrame* pInlinedCallFrame = (InlinedCallFrame*)pFrame; + // When unwinding an exception in ReadyToRun, the JIT_PInvokeEnd helper which unlinks the ICF from + // the thread will be skipped. This is because unlike jitted code, each pinvoke is wrapped by calls + // to the JIT_PInvokeBegin and JIT_PInvokeEnd helpers, which push and pop the ICF on the thread. The + // ICF is not linked at the method prolog and unlined at the epilog when running R2R code. Since the + // JIT_PInvokeEnd helper will be skipped, we need to unlink the ICF here. If the executing method + // has another pinvoke, it will re-link the ICF again when the JIT_PInvokeBegin helper is called. + TADDR returnAddress = pInlinedCallFrame->m_pCallerReturnAddress; +#ifdef USE_PER_FRAME_PINVOKE_INIT + // If we're setting up the frame for each P/Invoke for the given platform, + // then we do this for all P/Invokes except ones in IL stubs. + // IL stubs link the frame in for the whole stub, so if an exception is thrown during marshalling, + // the ICF will be on the frame chain and inactive. + if (!ExecutionManager::GetCodeMethodDesc(returnAddress)->IsILStub()) +#else + // If we aren't setting up the frame for each P/Invoke (instead setting up once per method), + // then ReadyToRun code is the only code using the per-P/Invoke logic. + if (ExecutionManager::IsReadyToRunCode(returnAddress)) +#endif + { + pFrame->ExceptionUnwind(); + pFrame->Pop(pThread); + } + else + { + pInlinedCallFrame->Reset(); + } + } + GCFrame* pGCFrame = pThread->GetGCFrame(); while (pGCFrame && pGCFrame < targetSp) { @@ -907,8 +940,8 @@ ProcessCLRExceptionNew(IN PEXCEPTION_RECORD pExceptionRecord, if ((pExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING)) { GCX_COOP(); - PopExplicitFrames(pThread, (void*)GetSP(pContextRecord)); - ExInfo::PopExInfos(pThread, (void*)GetSP(pContextRecord)); + PopExplicitFrames(pThread, (void*)pDispatcherContext->EstablisherFrame, (void*)GetSP(pDispatcherContext->ContextRecord)); + ExInfo::PopExInfos(pThread, (void*)pDispatcherContext->EstablisherFrame); } return ExceptionContinueSearch; } @@ -1667,7 +1700,7 @@ void ExceptionTracker::InitializeCrawlFrame(CrawlFrame* pcfThisFrame, Thread* pT pcfThisFrame->isFrameless = false; pcfThisFrame->pFunc = NULL; - *puMethodStartPC = NULL; + *puMethodStartPC = 0; } pcfThisFrame->pThread = pThread; @@ -1962,7 +1995,7 @@ CLRUnwindStatus ExceptionTracker::ProcessOSExceptionNotification( // then we do this for all P/Invokes except ones in IL stubs. // IL stubs link the frame in for the whole stub, so if an exception is thrown during marshalling, // the ICF will be on the frame chain and inactive. - if (returnAddress != NULL && !ExecutionManager::GetCodeMethodDesc(returnAddress)->IsILStub()) + if (returnAddress != (TADDR)NULL && !ExecutionManager::GetCodeMethodDesc(returnAddress)->IsILStub()) #else // If we aren't setting up the frame for each P/Invoke (instead setting up once per method), // then ReadyToRun code is the only code using the per-P/Invoke logic. @@ -2156,7 +2189,7 @@ CLRUnwindStatus ExceptionTracker::ProcessOSExceptionNotification( // If we are unwinding and the exception was not caught in managed code and we have reached the // topmost frame we saw in the first pass, then reset thread abort state if this is the last managed // code personality routine on the stack. - if ((fIsFirstPass == false) && (this->GetTopmostStackFrameFromFirstPass() == sf) && (GetCatchToCallPC() == NULL)) + if ((fIsFirstPass == false) && (this->GetTopmostStackFrameFromFirstPass() == sf) && (GetCatchToCallPC() == 0)) { ExceptionTracker::ResetThreadAbortStatus(pThread, &cfThisFrame, sf); } @@ -2443,7 +2476,7 @@ CLRUnwindStatus ExceptionTracker::ProcessExplicitFrame( // // Update stack trace // - m_StackTraceInfo.AppendElement(CanAllocateMemory(), NULL, sf.SP, pMD, pcfThisFrame); + m_StackTraceInfo.AppendElement(CanAllocateMemory(), 0, sf.SP, pMD, pcfThisFrame); m_StackTraceInfo.SaveStackTrace(CanAllocateMemory(), m_hThrowable, bReplaceStack, bSkipLastElement); // @@ -2690,7 +2723,7 @@ CLRUnwindStatus ExceptionTracker::ProcessManagedCallFrame( if (!fIgnoreThisFrame) { BOOL fFoundHandler = FALSE; - DWORD_PTR dwHandlerStartPC = NULL; + DWORD_PTR dwHandlerStartPC = 0; BOOL bReplaceStack = FALSE; BOOL bSkipLastElement = FALSE; @@ -3006,7 +3039,7 @@ CLRUnwindStatus ExceptionTracker::ProcessManagedCallFrame( // reset all the information we have saved when we find the handler. m_ExceptionFlags.ResetUnwindingToFindResumeFrame(); - m_uCatchToCallPC = NULL; + m_uCatchToCallPC = 0; m_pClauseForCatchToken = NULL; m_sfResumeStackFrame.Clear(); @@ -4564,7 +4597,7 @@ VOID UnwindManagedExceptionPass2(PAL_SEHException& ex, CONTEXT* unwindStartConte CONTEXT contextStorage; DISPATCHER_CONTEXT dispatcherContext; EECodeInfo codeInfo; - UINT_PTR establisherFrame = NULL; + ULONG_PTR establisherFrame = 0; PVOID handlerData; // Indicate that we are performing second pass. @@ -4747,7 +4780,7 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex, CONTEXT DISPATCHER_CONTEXT dispatcherContext; EECodeInfo codeInfo; UINT_PTR controlPc; - UINT_PTR establisherFrame = NULL; + ULONG_PTR establisherFrame = 0; PVOID handlerData; #ifdef FEATURE_HIJACK @@ -5655,8 +5688,6 @@ VOID DECLSPEC_NORETURN DispatchManagedException(OBJECTREF throwable, CONTEXT* pE args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(throwable); args[ARGNUM_1] = PTR_TO_ARGHOLDER(&exInfo); - FirstChanceExceptionNotification(); - pThread->IncPreventAbort(); //Ex.RhThrowEx(throwable, &exInfo) @@ -7217,7 +7248,7 @@ StackFrame ExceptionTracker::FindParentStackFrameHelper(CrawlFrame* pCF, { sfResult = (StackFrame)pCurrentExInfo->m_csfEnclosingClause; break; - } + } } goto lExit; @@ -7561,7 +7592,7 @@ void MarkInlinedCallFrameAsFuncletCall(Frame* pFrame) { _ASSERTE(pFrame->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr()); InlinedCallFrame* pInlinedCallFrame = (InlinedCallFrame*)pFrame; - pInlinedCallFrame->m_Datum = (PTR_NDirectMethodDesc)((TADDR)pInlinedCallFrame->m_Datum | (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper | (TADDR)InlinedCallFrameMarker::SecondPassFuncletCaller); + pInlinedCallFrame->m_Datum = (PTR_NDirectMethodDesc)((TADDR)pInlinedCallFrame->m_Datum | (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper | (TADDR)InlinedCallFrameMarker::SecondPassFuncletCaller); } // Mark the pinvoke frame as invoking any exception handling helper @@ -7584,7 +7615,7 @@ static TADDR GetSpForDiagnosticReporting(REGDISPLAY *pRD) extern "C" void QCALLTYPE AppendExceptionStackFrame(QCall::ObjectHandleOnStack exceptionObj, SIZE_T ip, SIZE_T sp, int flags, ExInfo *pExInfo) { QCALL_CONTRACT; - + BEGIN_QCALL; Thread* pThread = GET_THREAD(); @@ -7624,7 +7655,7 @@ extern "C" void QCALLTYPE AppendExceptionStackFrame(QCall::ObjectHandleOnStack e UINT_PTR GetEstablisherFrame(REGDISPLAY* pvRegDisplay, ExInfo* exInfo) { -#ifdef HOST_AMD64 +#ifdef HOST_AMD64 _ASSERTE(exInfo->m_frameIter.m_crawl.GetRegisterSet() == pvRegDisplay); if (exInfo->m_frameIter.m_crawl.GetCodeInfo()->HasFrameRegister()) { @@ -7645,7 +7676,7 @@ UINT_PTR GetEstablisherFrame(REGDISPLAY* pvRegDisplay, ExInfo* exInfo) return pvRegDisplay->SP; #elif defined(HOST_LOONGARCH64) return pvRegDisplay->SP; -#endif +#endif } extern "C" void * QCALLTYPE CallCatchFunclet(QCall::ObjectHandleOnStack exceptionObj, BYTE* pHandlerIP, REGDISPLAY* pvRegDisplay, ExInfo* exInfo) @@ -7663,6 +7694,7 @@ extern "C" void * QCALLTYPE CallCatchFunclet(QCall::ObjectHandleOnStack exceptio HandlerFn* pfnHandler = (HandlerFn*)pHandlerIP; exInfo->m_ScannedStackRange.ExtendUpperBound(exInfo->m_frameIter.m_crawl.GetRegisterSet()->SP); DWORD_PTR dwResumePC = 0; + UINT_PTR callerTargetSp = 0; if (pHandlerIP != NULL) { @@ -7671,7 +7703,7 @@ extern "C" void * QCALLTYPE CallCatchFunclet(QCall::ObjectHandleOnStack exceptio throwable = PossiblyUnwrapThrowable(throwable, exInfo->m_frameIter.m_crawl.GetAssembly()); UINT_PTR establisherFrame = GetEstablisherFrame(pvRegDisplay, exInfo); - + exInfo->m_csfEHClause = CallerStackFrame((UINT_PTR)GetCurrentSP()); exInfo->m_csfEnclosingClause = CallerStackFrame::FromRegDisplay(exInfo->m_frameIter.m_crawl.GetRegisterSet()); @@ -7681,7 +7713,7 @@ extern "C" void * QCALLTYPE CallCatchFunclet(QCall::ObjectHandleOnStack exceptio exInfo->MakeCallbacksRelatedToHandler(true, pThread, pMD, &exInfo->m_ClauseForCatch, (DWORD_PTR)pHandlerIP, spForDebugger); #ifdef USE_FUNCLET_CALL_HELPER - // Invoke the catch funclet. + // Invoke the catch funclet. // Since the actual caller of the funclet is the assembly helper, pass the reference // to the CallerStackFrame instance so that it can be updated. CallerStackFrame* pCallerStackFrame = &exInfo->m_csfEHClause; @@ -7692,14 +7724,15 @@ extern "C" void * QCALLTYPE CallCatchFunclet(QCall::ObjectHandleOnStack exceptio pFuncletCallerSP); #else dwResumePC = pfnHandler(establisherFrame, OBJECTREFToObject(throwable)); -#endif +#endif // Profiler, debugger and ETW events exInfo->MakeCallbacksRelatedToHandler(false, pThread, pMD, &exInfo->m_ClauseForCatch, (DWORD_PTR)pHandlerIP, spForDebugger); SetIP(pvRegDisplay->pCurrentContext, dwResumePC); + callerTargetSp = CallerStackFrame::FromRegDisplay(pvRegDisplay).SP; } UINT_PTR targetSp = GetSP(pvRegDisplay->pCurrentContext); - PopExplicitFrames(pThread, (void*)targetSp); + PopExplicitFrames(pThread, (void*)targetSp, (void*)callerTargetSp); ExInfo* pExInfo = (PTR_ExInfo)pThread->GetExceptionState()->GetCurrentExceptionTracker(); @@ -7788,7 +7821,7 @@ extern "C" void * QCALLTYPE CallCatchFunclet(QCall::ObjectHandleOnStack exceptio { if (fIntercepted) { - ClrRestoreNonvolatileContext(pvRegDisplay->pCurrentContext); + ClrRestoreNonvolatileContext(pvRegDisplay->pCurrentContext); } #ifdef HOST_UNIX if (propagateExceptionCallback) @@ -7820,7 +7853,7 @@ extern "C" void * QCALLTYPE CallCatchFunclet(QCall::ObjectHandleOnStack exceptio SetSP(pvRegDisplay->pCurrentContext, targetSp - 8); #elif defined(HOST_X86) SetSP(pvRegDisplay->pCurrentContext, targetSp - 4); -#endif +#endif #ifdef HOST_AMD64 #ifdef UNIX_AMD64_ABI #define FIRST_ARG_REG Rdi @@ -7852,13 +7885,14 @@ extern "C" void QCALLTYPE ResumeAtInterceptionLocation(REGDISPLAY* pvRegDisplay) Frame* pFrame = pThread->GetFrame(); MarkInlinedCallFrameAsFuncletCall(pFrame); - + UINT_PTR targetSp = GetSP(pvRegDisplay->pCurrentContext); ExInfo *pExInfo = (PTR_ExInfo)pThread->GetExceptionState()->GetCurrentExceptionTracker(); pExInfo->m_ScannedStackRange.ExtendUpperBound(targetSp); - PopExplicitFrames(pThread, (void*)targetSp); + EECodeManager::EnsureCallerContextIsValid(pvRegDisplay); + PopExplicitFrames(pThread, (void*)targetSp, (void*)CallerStackFrame::FromRegDisplay(pvRegDisplay).SP); // This must be done before we pop the ExInfos. BOOL fIntercepted = pThread->GetExceptionState()->GetFlags()->DebuggerInterceptInfo(); @@ -7885,7 +7919,7 @@ extern "C" void QCALLTYPE ResumeAtInterceptionLocation(REGDISPLAY* pvRegDisplay) uResumePC = codeInfo.GetJitManager()->GetCodeAddressForRelOffset(codeInfo.GetMethodToken(), static_cast(ulRelOffset)); SetIP(pvRegDisplay->pCurrentContext, uResumePC); - ClrRestoreNonvolatileContext(pvRegDisplay->pCurrentContext); + ClrRestoreNonvolatileContext(pvRegDisplay->pCurrentContext); } extern "C" void QCALLTYPE CallFinallyFunclet(BYTE* pHandlerIP, REGDISPLAY* pvRegDisplay, ExInfo* exInfo) @@ -7910,7 +7944,7 @@ extern "C" void QCALLTYPE CallFinallyFunclet(BYTE* pHandlerIP, REGDISPLAY* pvReg TADDR spForDebugger = GetSpForDiagnosticReporting(pvRegDisplay); exInfo->MakeCallbacksRelatedToHandler(true, pThread, pMD, &exInfo->m_CurrentClause, (DWORD_PTR)pHandlerIP, spForDebugger); #ifdef USE_FUNCLET_CALL_HELPER - // Invoke the finally funclet. + // Invoke the finally funclet. // Since the actual caller of the funclet is the assembly helper, pass the reference // to the CallerStackFrame instance so that it can be updated. CallerStackFrame* pCallerStackFrame = &exInfo->m_csfEHClause; @@ -7921,7 +7955,7 @@ extern "C" void QCALLTYPE CallFinallyFunclet(BYTE* pHandlerIP, REGDISPLAY* pvReg pFuncletCallerSP); #else DWORD_PTR dwResumePC = pfnHandler(establisherFrame, NULL); -#endif +#endif pThread->IncPreventAbort(); @@ -7958,7 +7992,7 @@ extern "C" BOOL QCALLTYPE CallFilterFunclet(QCall::ObjectHandleOnStack exception EX_TRY { #ifdef USE_FUNCLET_CALL_HELPER - // Invoke the filter funclet. + // Invoke the filter funclet. // Since the actual caller of the funclet is the assembly helper, pass the reference // to the CallerStackFrame instance so that it can be updated. CallerStackFrame* pCallerStackFrame = &pExInfo->m_csfEHClause; @@ -8127,6 +8161,7 @@ static void NotifyExceptionPassStarted(StackFrameIterator *pThis, Thread *pThrea { GCX_COOP(); pThread->SafeSetThrowables(pExInfo->m_exception); + FirstChanceExceptionNotification(); EEToProfilerExceptionInterfaceWrapper::ExceptionThrown(pThread); } else // pExInfo->m_passNumber == 2 @@ -8182,6 +8217,26 @@ static void NotifyExceptionPassStarted(StackFrameIterator *pThis, Thread *pThrea pExInfo->m_ExceptionFlags.SetUnwindHasStarted(); EEToDebuggerExceptionInterfaceWrapper::ManagedExceptionUnwindBegin(pThread); } + else + { + // The debugger explicitly checks that the notification refers to a FuncEvalFrame in case an exception becomes unhandled in a func eval. + // We need to do the notification here before we start propagating the exception through native frames, since that will remove + // all managed frames from the stack and the debugger would not see the failure location. + if (pThis->GetFrameState() == StackFrameIterator::SFITER_FRAME_FUNCTION) + { + Frame* pFrame = pThis->m_crawl.GetFrame(); + // If the frame is ProtectValueClassFrame, move to the next one as we want to report the FuncEvalFrame + if (pFrame->GetVTablePtr() == ProtectValueClassFrame::GetMethodFrameVPtr()) + { + pFrame = pFrame->PtrNextFrame(); + _ASSERTE(pFrame != FRAME_TOP); + } + if ((pFrame->GetVTablePtr() == FuncEvalFrame::GetMethodFrameVPtr()) || (pFrame->GetVTablePtr() == DebuggerU2MCatchHandlerFrame::GetMethodFrameVPtr())) + { + EEToDebuggerExceptionInterfaceWrapper::NotifyOfCHFFilter((EXCEPTION_POINTERS *)&pExInfo->m_ptrs, pFrame); + } + } + } } } @@ -8258,7 +8313,7 @@ extern "C" bool QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStackwalk bool canAllocateMemory = !(pExInfo->m_exception == CLRException::GetPreallocatedOutOfMemoryException()) && !(pExInfo->m_exception == CLRException::GetPreallocatedStackOverflowException()); - pExInfo->m_StackTraceInfo.AppendElement(canAllocateMemory, NULL, GetRegdisplaySP(pExInfo->m_frameIter.m_crawl.GetRegisterSet()), pMD, &pExInfo->m_frameIter.m_crawl); + pExInfo->m_StackTraceInfo.AppendElement(canAllocateMemory, 0, GetRegdisplaySP(pExInfo->m_frameIter.m_crawl.GetRegisterSet()), pMD, &pExInfo->m_frameIter.m_crawl); pExInfo->m_StackTraceInfo.SaveStackTrace(canAllocateMemory, pExInfo->m_hThrowable, /*bReplaceStack*/FALSE, /*bSkipLastElement*/FALSE); #if defined(DEBUGGING_SUPPORTED) @@ -8404,7 +8459,7 @@ extern "C" bool QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollideCla else { // TODO-NewEH: Currently there are two other cases of internal VM->managed transitions. The FastCallFinalize and COMToCLRDispatchHelperWithStack - // Either add handling those here as well or rewrite all these perf critical places in C#, so that CallDescrWorker is the only path that + // Either add handling those here as well or rewrite all these perf critical places in C#, so that CallDescrWorker is the only path that // needs to be handled here. size_t CallDescrWorkerInternalReturnAddress = (size_t)CallDescrWorkerInternal + CallDescrWorkerInternalReturnAddressOffset; if (GetIP(pThis->m_crawl.GetRegisterSet()->pCallerContext) == CallDescrWorkerInternalReturnAddress) @@ -8491,7 +8546,7 @@ extern "C" bool QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollideCla { // Unwind the CallCatchFunclet retVal = MoveToNextNonSkippedFrame(pThis); - + if (retVal == SWA_FAILED) { _ASSERTE_MSG(FALSE, "StackFrameIterator::Next failed"); @@ -8528,7 +8583,7 @@ extern "C" bool QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollideCla bool canAllocateMemory = !(pTopExInfo->m_exception == CLRException::GetPreallocatedOutOfMemoryException()) && !(pTopExInfo->m_exception == CLRException::GetPreallocatedStackOverflowException()); - pTopExInfo->m_StackTraceInfo.AppendElement(canAllocateMemory, NULL, GetRegdisplaySP(pTopExInfo->m_frameIter.m_crawl.GetRegisterSet()), pMD, &pTopExInfo->m_frameIter.m_crawl); + pTopExInfo->m_StackTraceInfo.AppendElement(canAllocateMemory, 0, GetRegdisplaySP(pTopExInfo->m_frameIter.m_crawl.GetRegisterSet()), pMD, &pTopExInfo->m_frameIter.m_crawl); pTopExInfo->m_StackTraceInfo.SaveStackTrace(canAllocateMemory, pTopExInfo->m_hThrowable, /*bReplaceStack*/FALSE, /*bSkipLastElement*/FALSE); #if defined(DEBUGGING_SUPPORTED) diff --git a/src/coreclr/vm/exceptionhandling.h b/src/coreclr/vm/exceptionhandling.h index 7be99adfd202..3977587a76b9 100644 --- a/src/coreclr/vm/exceptionhandling.h +++ b/src/coreclr/vm/exceptionhandling.h @@ -132,7 +132,7 @@ struct ExceptionTrackerBase ExceptionTrackerBase(PTR_EXCEPTION_RECORD pExceptionRecord, PTR_CONTEXT pExceptionContext, PTR_ExceptionTrackerBase pPrevNestedInfo) : m_pPrevNestedInfo(pPrevNestedInfo), - m_hThrowable(NULL), + m_hThrowable{}, m_ptrs({pExceptionRecord, pExceptionContext}), m_fDeliveredFirstChanceNotification(FALSE), m_ExceptionCode((pExceptionRecord != PTR_NULL) ? pExceptionRecord->ExceptionCode : 0) @@ -164,7 +164,7 @@ struct ExceptionTrackerBase } CONTRACTL_END; - if (NULL != m_hThrowable) + if (0 != m_hThrowable) { return ObjectFromHandle(m_hThrowable); } @@ -265,7 +265,7 @@ class ExceptionTracker : public ExceptionTrackerBase PTR_CONTEXT pContextRecord) : ExceptionTrackerBase(pExceptionRecord, pContextRecord, PTR_NULL), m_pThread(GetThread()), - m_uCatchToCallPC(NULL), + m_uCatchToCallPC{}, m_pSkipToParentFunctionMD(NULL), // these members were added for resume frame processing m_pClauseForCatchToken(NULL) diff --git a/src/coreclr/vm/exceptmacros.h b/src/coreclr/vm/exceptmacros.h index d19966c609d3..9b7137ca9086 100644 --- a/src/coreclr/vm/exceptmacros.h +++ b/src/coreclr/vm/exceptmacros.h @@ -353,6 +353,14 @@ VOID DECLSPEC_NORETURN DispatchManagedException(PAL_SEHException& ex, bool isHar DEBUG_ASSURE_NO_RETURN_END(IUACH) \ SCAN_EHMARKER_END_TRY(); \ } \ + PAL_CPP_CATCH_NON_DERIVED_NOARG (const std::bad_alloc&) \ + { \ + SCAN_EHMARKER_CATCH(); \ + __pUnCException = Exception::GetOOMException(); \ + UnwindAndContinueRethrowHelperInsideCatch(__pUnCEntryFrame, __pUnCException); \ + __fExceptionCaught = true; \ + SCAN_EHMARKER_END_CATCH(); \ + } \ PAL_CPP_CATCH_DERIVED (Exception, __pException) \ { \ SCAN_EHMARKER_CATCH(); \ diff --git a/src/coreclr/vm/exinfo.cpp b/src/coreclr/vm/exinfo.cpp index 8731a20ba585..49287d3957e9 100644 --- a/src/coreclr/vm/exinfo.cpp +++ b/src/coreclr/vm/exinfo.cpp @@ -317,7 +317,7 @@ ExInfo::ExInfo(Thread *pThread, EXCEPTION_RECORD *pExceptionRecord, CONTEXT *pEx m_kind(exceptionKind), m_passNumber(1), m_idxCurClause(0xffffffff), - m_notifyDebuggerSP(NULL), + m_notifyDebuggerSP{}, m_pFrame(pThread->GetFrame()), m_ClauseForCatch({}), #ifdef HOST_UNIX diff --git a/src/coreclr/vm/exstate.cpp b/src/coreclr/vm/exstate.cpp index b9b1ddc05fd5..1f245eedd802 100644 --- a/src/coreclr/vm/exstate.cpp +++ b/src/coreclr/vm/exstate.cpp @@ -23,7 +23,7 @@ OBJECTHANDLE ThreadExceptionState::GetThrowableAsHandle() return m_pCurrentTracker->m_hThrowable; } - return NULL; + return (OBJECTHANDLE)NULL; #else // FEATURE_EH_FUNCLETS return m_currentExInfo.m_hThrowable; #endif // FEATURE_EH_FUNCLETS @@ -155,7 +155,7 @@ void ThreadExceptionState::SetThrowable(OBJECTREF throwable DEBUG_ARG(SetThrowab } else { - AppDomain* pDomain = GetMyThread()->GetDomain(); + AppDomain* pDomain = AppDomain::GetCurrentDomain(); PREFIX_ASSUME(pDomain != NULL); hNewThrowable = pDomain->CreateHandle(throwable); } diff --git a/src/coreclr/vm/fcall.cpp b/src/coreclr/vm/fcall.cpp index 20461bef7988..80f163c19b37 100644 --- a/src/coreclr/vm/fcall.cpp +++ b/src/coreclr/vm/fcall.cpp @@ -129,7 +129,7 @@ NOINLINE Object* FC_GCPoll(void* __me, Object* objToProtect) INCONTRACT(FCallCheck __fCallCheck(__FILE__, __LINE__)); Thread *thread = GetThread(); - if (thread->CatchAtSafePointOpportunistic()) // Does someone want this thread stopped? + if (thread->CatchAtSafePoint()) // Does someone want this thread stopped? { HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_CAPTURE_DEPTH_2, objToProtect); @@ -158,13 +158,13 @@ NOINLINE Object* FC_GCPoll(void* __me, Object* objToProtect) /**************************************************************************************/ #if defined(TARGET_X86) && defined(ENABLE_PERF_COUNTERS) -static __int64 getCycleCount() { +static int64_t getCycleCount() { LIMITED_METHOD_CONTRACT; return GET_CYCLE_COUNT(); } #else -static __int64 getCycleCount() { LIMITED_METHOD_CONTRACT; return(0); } +static int64_t getCycleCount() { LIMITED_METHOD_CONTRACT; return(0); } #endif /**************************************************************************************/ diff --git a/src/coreclr/vm/fcall.h b/src/coreclr/vm/fcall.h index bbb5ba9ca532..15c4d1e5ec3b 100644 --- a/src/coreclr/vm/fcall.h +++ b/src/coreclr/vm/fcall.h @@ -809,7 +809,7 @@ Object* FC_GCPoll(void* me, Object* objToProtect = NULL); { \ INCONTRACT(Thread::TriggersGC(GetThread());) \ INCONTRACT(__fCallCheck.SetDidPoll();) \ - if (g_TrapReturningThreads.LoadWithoutBarrier()) \ + if (g_TrapReturningThreads) \ { \ if (FC_GCPoll(__me)) \ return ret; \ @@ -824,7 +824,7 @@ Object* FC_GCPoll(void* me, Object* objToProtect = NULL); { \ INCONTRACT(__fCallCheck.SetDidPoll();) \ Object* __temp = OBJECTREFToObject(obj); \ - if (g_TrapReturningThreads.LoadWithoutBarrier()) \ + if (g_TrapReturningThreads) \ { \ __temp = FC_GCPoll(__me, __temp); \ while (0 == FC_NO_TAILCALL) { }; /* side effect the compile can't remove */ \ @@ -865,7 +865,7 @@ class FCallCheck : public ForbidGC { #endif bool didGCPoll; // GC poll was done bool notNeeded; // GC poll not needed - unsigned __int64 startTicks; // tick count at beginning of FCall + uint64_t startTicks; // tick count at beginning of FCall }; // FC_COMMON_PROLOG is used for both FCalls and HCalls diff --git a/src/coreclr/vm/field.cpp b/src/coreclr/vm/field.cpp index c2eab291cc42..0b6d91359b73 100644 --- a/src/coreclr/vm/field.cpp +++ b/src/coreclr/vm/field.cpp @@ -620,17 +620,17 @@ VOID FieldDesc::SetValue8(OBJECTREF o, DWORD dwValue) } #endif // #ifndef DACCESS_COMPILE -__int64 FieldDesc::GetValue64(OBJECTREF o) +int64_t FieldDesc::GetValue64(OBJECTREF o) { WRAPPER_NO_CONTRACT; - __int64 val; + int64_t val; GetInstanceField(o, (LPVOID)&val); return val; } #ifndef DACCESS_COMPILE -VOID FieldDesc::SetValue64(OBJECTREF o, __int64 value) +VOID FieldDesc::SetValue64(OBJECTREF o, int64_t value) { CONTRACTL { diff --git a/src/coreclr/vm/field.h b/src/coreclr/vm/field.h index c37fa4244dad..f8de9d969cec 100644 --- a/src/coreclr/vm/field.h +++ b/src/coreclr/vm/field.h @@ -186,7 +186,7 @@ class FieldDesc // As of 4/11/2012 I could repro this by turning on the COMPLUS log and // the LOG() at line methodtablebuilder.cpp:7845 // MethodTableBuilder::PlaceRegularStaticFields() calls GetOffset() - if((DWORD)(DWORD_PTR&)m_pMTOfEnclosingClass > 16) + if((DWORD)reinterpret_cast(m_pMTOfEnclosingClass) > 16) { _ASSERTE(!this->IsRVA() || (m_dwOffset == OutOfLine_BigRVAOffset())); } @@ -352,8 +352,8 @@ class FieldDesc VOID SetValue16(OBJECTREF o, DWORD dwValue); BYTE GetValue8(OBJECTREF o); VOID SetValue8(OBJECTREF o, DWORD dwValue); - __int64 GetValue64(OBJECTREF o); - VOID SetValue64(OBJECTREF o, __int64 value); + int64_t GetValue64(OBJECTREF o); + VOID SetValue64(OBJECTREF o, int64_t value); PTR_MethodTable GetApproxEnclosingMethodTable() { @@ -489,16 +489,16 @@ class FieldDesc *(BYTE*)GetCurrentStaticAddress() = (BYTE)dwValue; } - __int64 GetStaticValue64() + int64_t GetStaticValue64() { WRAPPER_NO_CONTRACT; - return *(__int64*)GetCurrentStaticAddress(); + return *(int64_t*)GetCurrentStaticAddress(); } - VOID SetStaticValue64(__int64 qwValue) + VOID SetStaticValue64(int64_t qwValue) { WRAPPER_NO_CONTRACT; - *(__int64*)GetCurrentStaticAddress() = qwValue; + *(int64_t*)GetCurrentStaticAddress() = qwValue; } void* GetCurrentStaticAddress() diff --git a/src/coreclr/vm/fptrstubs.cpp b/src/coreclr/vm/fptrstubs.cpp index 05c4fedf22d7..051f00cfb6e7 100644 --- a/src/coreclr/vm/fptrstubs.cpp +++ b/src/coreclr/vm/fptrstubs.cpp @@ -79,7 +79,7 @@ PCODE FuncPtrStubs::GetFuncPtrStub(MethodDesc * pMD, PrecodeType type) return pPrecode->GetEntryPoint(); } - PCODE target = NULL; + PCODE target = (PCODE)NULL; bool setTargetAfterAddingToHashTable = false; if (type != GetDefaultType(pMD) && @@ -123,7 +123,7 @@ PCODE FuncPtrStubs::GetFuncPtrStub(MethodDesc * pMD, PrecodeType type) AllocMemTracker amt; Precode* pNewPrecode = Precode::Allocate(type, pMD, pMD->GetLoaderAllocator(), &amt); - if (target != NULL) + if (target != (PCODE)NULL) { pNewPrecode->SetTargetInterlocked(target); } diff --git a/src/coreclr/vm/frames.cpp b/src/coreclr/vm/frames.cpp index cfd8eb11a7a9..b4fbf4a7fb4f 100644 --- a/src/coreclr/vm/frames.cpp +++ b/src/coreclr/vm/frames.cpp @@ -592,7 +592,7 @@ StubDispatchFrame::StubDispatchFrame(TransitionBlock * pTransitionBlock) m_representativeSlot = 0; m_pZapModule = NULL; - m_pIndirection = NULL; + m_pIndirection = (TADDR)NULL; m_pGCRefMap = NULL; } @@ -668,7 +668,7 @@ PTR_BYTE StubDispatchFrame::GetGCRefMap() if (pGCRefMap == NULL) { - if (m_pIndirection != NULL) + if (m_pIndirection != (TADDR)NULL) { if (m_pZapModule == NULL) { @@ -688,7 +688,7 @@ PTR_BYTE StubDispatchFrame::GetGCRefMap() else { // Clear the indirection to avoid retrying - m_pIndirection = NULL; + m_pIndirection = (TADDR)NULL; } #endif } @@ -770,7 +770,7 @@ ExternalMethodFrame::ExternalMethodFrame(TransitionBlock * pTransitionBlock) { LIMITED_METHOD_CONTRACT; - m_pIndirection = NULL; + m_pIndirection = (TADDR)NULL; m_pZapModule = NULL; m_pGCRefMap = NULL; @@ -798,7 +798,7 @@ PTR_BYTE ExternalMethodFrame::GetGCRefMap() if (pGCRefMap == NULL) { - if (m_pIndirection != NULL) + if (m_pIndirection != (TADDR)NULL) { pGCRefMap = FindGCRefMap(m_pZapModule, m_pIndirection); #ifndef DACCESS_COMPILE @@ -1995,7 +1995,7 @@ VOID InlinedCallFrame::Init() m_Datum = NULL; m_pCallSiteSP = NULL; - m_pCallerReturnAddress = NULL; + m_pCallerReturnAddress = (TADDR)NULL; } diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index ea7eb1e19413..68706cd52304 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -464,7 +464,7 @@ class Frame : public FrameBase virtual TADDR GetReturnAddressPtr() { LIMITED_METHOD_DAC_CONTRACT; - return NULL; + return 0; } // ASAN doesn't like us messing with the return address. @@ -472,7 +472,7 @@ class Frame : public FrameBase { WRAPPER_NO_CONTRACT; TADDR ptr = GetReturnAddressPtr(); - return (ptr != NULL) ? *PTR_PCODE(ptr) : NULL; + return (ptr != 0) ? *PTR_PCODE(ptr) : 0; } #ifndef DACCESS_COMPILE @@ -604,13 +604,13 @@ class Frame : public FrameBase { LIMITED_METHOD_CONTRACT; if (ip) - *ip = NULL; + *ip = 0; if (returnIP) - *returnIP = NULL; + *returnIP = 0; if (returnSP) - *returnSP = NULL; + *returnSP = 0; } // Return where the frame will execute next - the result is filled @@ -730,7 +730,7 @@ class Frame : public FrameBase friend LONG WINAPI CLRVectoredExceptionHandlerShim(PEXCEPTION_POINTERS pExceptionInfo); #endif #ifdef HOST_64BIT - friend Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame, PTR_VOID StubSecretArg); + friend Thread * JIT_InitPInvokeFrame(InlinedCallFrame *pFrame); #endif #ifdef FEATURE_EH_FUNCLETS friend class ExceptionTracker; @@ -1258,7 +1258,7 @@ class HelperMethodFrame : public Frame return unwoundState.GetRetAddr(); #else // !DACCESS_COMPILE _ASSERTE(!"HMF's should always be initialized in the non-DAC world."); - return NULL; + return 0; #endif // !DACCESS_COMPILE } @@ -1332,7 +1332,7 @@ class HelperMethodFrame : public Frame FORCEINLINE void Poll() { WRAPPER_NO_CONTRACT; - if (m_pThread->CatchAtSafePointOpportunistic()) + if (m_pThread->CatchAtSafePoint()) CommonTripThread(); } #endif // DACCESS_COMPILE @@ -2730,13 +2730,13 @@ class DebuggerExitFrame : public Frame { LIMITED_METHOD_CONTRACT; if (ip) - *ip = NULL; + *ip = 0; if (returnIP) - *returnIP = NULL; + *returnIP = 0; if (returnSP) - *returnSP = NULL; + *returnSP = 0; } // Keep as last entry in class @@ -2838,7 +2838,7 @@ class InlinedCallFrame : public Frame return PTR_HOST_MEMBER_TADDR(InlinedCallFrame, this, m_pCallerReturnAddress); else - return NULL; + return 0; } virtual BOOL NeedsUpdateRegDisplay() @@ -2852,31 +2852,10 @@ class InlinedCallFrame : public Frame // method if the current InlinedCallFrame is inactive. PTR_MethodDesc GetActualInteropMethodDesc() { -#if defined(TARGET_X86) || defined(TARGET_ARM) - // Important: This code relies on the way JIT lays out frames. Keep it in sync - // with code:Compiler.lvaAssignFrameOffsets. - // - // | ... | - // +--------------------+ - // | lvaStubArgumentVar | <= filled with EAX in prolog | - // +--------------------+ | - // | | | - // | InlinedCallFrame | | - // | | <= m_pCrawl.pFrame | to lower addresses - // +--------------------+ V - // | ... | - // - // Extract the actual MethodDesc to report from the InlinedCallFrame. + // The VM instructs the JIT to publish the secret stub arg at the end + // of the InlinedCallFrame structure when it exists. TADDR addr = dac_cast(this) + sizeof(InlinedCallFrame); return PTR_MethodDesc(*PTR_TADDR(addr)); -#elif defined(HOST_64BIT) - // On 64bit, the actual interop MethodDesc is saved off in a field off the InlinedCrawlFrame - // which is populated by the JIT. Refer to JIT_InitPInvokeFrame for details. - return PTR_MethodDesc(m_StubSecretArg); -#else - _ASSERTE(!"NYI - Interop method reporting for this architecture!"); - return NULL; -#endif // defined(TARGET_X86) || defined(TARGET_ARM) } virtual void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false); @@ -2890,13 +2869,6 @@ class InlinedCallFrame : public Frame // See code:HasFunction. PTR_NDirectMethodDesc m_Datum; -#ifdef HOST_64BIT - // IL stubs fill this field with the incoming secret argument when they erect - // InlinedCallFrame so we know which interop method was invoked even if the frame - // is not active at the moment. - PTR_VOID m_StubSecretArg; -#endif // HOST_64BIT - // X86: ESP after pushing the outgoing arguments, and just before calling // out to unmanaged code. // Other platforms: the field stays set throughout the declaring method. @@ -2943,13 +2915,13 @@ class InlinedCallFrame : public Frame return pFrame && pFrame != FRAME_TOP && InlinedCallFrame::GetMethodFrameVPtr() == pFrame->GetVTablePtr() && - dac_cast(dac_cast(pFrame)->m_pCallerReturnAddress) != NULL; + dac_cast(dac_cast(pFrame)->m_pCallerReturnAddress) != 0; } // Marks the frame as inactive. void Reset() { - m_pCallerReturnAddress = NULL; + m_pCallerReturnAddress = 0; } int GetFrameType() diff --git a/src/coreclr/vm/gc_unwind_x86.inl b/src/coreclr/vm/gc_unwind_x86.inl index 5b308911bc0b..33604336d28c 100644 --- a/src/coreclr/vm/gc_unwind_x86.inl +++ b/src/coreclr/vm/gc_unwind_x86.inl @@ -1519,10 +1519,10 @@ unsigned scanArgRegTableI(PTR_CBYTE table, bool hasPartialArgInfo; -#ifndef UNIX_X86_ABI +#ifndef FEATURE_EH_FUNCLETS hasPartialArgInfo = info->ebpFrame; #else - // For x86/Linux, interruptible code always has full arg info + // For funclets, interruptible code always has full arg info // // This should be aligned with emitFullArgInfo setting at // emitter::emitEndCodeGen (in JIT) @@ -1670,10 +1670,7 @@ unsigned scanArgRegTableI(PTR_CBYTE table, { thisPtrReg = REGI_NA; } - if (iptrRegs & regMask) - { - iptrRegs &= ~regMask; - } + iptrRegs &= ~regMask; } iptr = isThis = false; continue; diff --git a/src/coreclr/vm/gccover.cpp b/src/coreclr/vm/gccover.cpp index 44ccfd4c46be..70ab39ea681b 100644 --- a/src/coreclr/vm/gccover.cpp +++ b/src/coreclr/vm/gccover.cpp @@ -37,7 +37,7 @@ MethodDesc* AsMethodDesc(size_t addr); static PBYTE getTargetOfCall(PBYTE instrPtr, PCONTEXT regs, PBYTE*nextInstr); #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) -static void replaceSafePointInstructionWithGcStressInstr(UINT32 safePointOffset, LPVOID codeStart); +static void replaceSafePointInstructionWithGcStressInstr(GcInfoDecoder* decoder, UINT32 safePointOffset, LPVOID codeStart); static bool replaceInterruptibleRangesWithGcStressInstr (UINT32 startOffset, UINT32 stopOffset, LPVOID codeStart); #endif @@ -544,11 +544,16 @@ void GCCoverageInfo::SprinkleBreakpoints( _ASSERTE(len > 0); _ASSERTE(len <= (size_t)(codeEnd-cur)); + // For non-fully interruptible code, we want to at least + // patch the return sites after the call instructions. + // Specially so that we can verify stack-walking through the call site via a simulated hijack. + // We would need to know the return kind of the callee, so this may not always be possible. switch(instructionType) { case InstructionType::Call_IndirectUnconditional: #ifdef TARGET_AMD64 - if(safePointDecoder.IsSafePoint((UINT32)(cur + len - codeStart + regionOffsetAdj))) + if(!(EECodeManager::InterruptibleSafePointsEnabled() && safePointDecoder.AreSafePointsInterruptible()) && + safePointDecoder.IsSafePoint((UINT32)(cur + len - codeStart + regionOffsetAdj))) #endif { *(cur + writeableOffset) = INTERRUPT_INSTR_CALL; // return value. May need to protect @@ -559,7 +564,8 @@ void GCCoverageInfo::SprinkleBreakpoints( if(fGcStressOnDirectCalls.val(CLRConfig::INTERNAL_GcStressOnDirectCalls)) { #ifdef TARGET_AMD64 - if(safePointDecoder.IsSafePoint((UINT32)(cur + len - codeStart + regionOffsetAdj))) + if(!(EECodeManager::InterruptibleSafePointsEnabled() && safePointDecoder.AreSafePointsInterruptible()) && + safePointDecoder.IsSafePoint((UINT32)(cur + len - codeStart + regionOffsetAdj))) #endif { PBYTE nextInstr; @@ -589,10 +595,8 @@ void GCCoverageInfo::SprinkleBreakpoints( ReplaceInstrAfterCall(cur + writeableOffset, prevDirectCallTargetMD); } - // For fully interruptible code, we end up whacking every instruction - // to INTERRUPT_INSTR. For non-fully interruptible code, we end - // up only touching the call instructions (specially so that we - // can really do the GC on the instruction just after the call). + // For fully interruptible locations, we end up whacking every instruction + // to INTERRUPT_INSTR. size_t dwRelOffset = (cur - codeStart) + regionOffsetAdj; _ASSERTE(FitsIn(dwRelOffset)); if (codeMan->IsGcSafe(&codeInfo, static_cast(dwRelOffset))) @@ -689,7 +693,7 @@ enum #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED -void replaceSafePointInstructionWithGcStressInstr(UINT32 safePointOffset, LPVOID pGCCover) +void replaceSafePointInstructionWithGcStressInstr(GcInfoDecoder* decoder, UINT32 safePointOffset, LPVOID pGCCover) { PCODE pCode = NULL; IJitManager::MethodRegionInfo *ptr = &(((GCCoverageInfo*)pGCCover)->methodRegion); @@ -712,6 +716,28 @@ void replaceSafePointInstructionWithGcStressInstr(UINT32 safePointOffset, LPVOID PBYTE instrPtr = (BYTE*)PCODEToPINSTR(pCode); + // if this is an interruptible safe point, just replace it with an interrupt instr and we are done. + if (EECodeManager::InterruptibleSafePointsEnabled() && decoder->AreSafePointsInterruptible()) + { + // The instruction about to be replaced cannot already be a gcstress instruction + _ASSERTE(!IsGcCoverageInterruptInstruction(instrPtr)); + + ExecutableWriterHolder instrPtrWriterHolder(instrPtr, sizeof(DWORD)); +#if defined(TARGET_ARM) + size_t instrLen = GetARMInstructionLength(instrPtr); + + if (instrLen == 2) + *((WORD*)instrPtrWriterHolder.GetRW()) = INTERRUPT_INSTR; + else + { + *((DWORD*)instrPtrWriterHolder.GetRW()) = INTERRUPT_INSTR_32; + } +#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) + *((DWORD*)instrPtrWriterHolder.GetRW()) = INTERRUPT_INSTR; +#endif // TARGET_XXXX_ + return; + } + // For code sequences of the type // BL func1 // BL func2 // Safe point 1 diff --git a/src/coreclr/vm/gchandleutilities.h b/src/coreclr/vm/gchandleutilities.h index 1f0e7013f22b..a5079f38399a 100644 --- a/src/coreclr/vm/gchandleutilities.h +++ b/src/coreclr/vm/gchandleutilities.h @@ -53,7 +53,7 @@ inline BOOL IsHandleNullUnchecked(OBJECTHANDLE handle) { LIMITED_METHOD_CONTRACT; - return (handle == NULL || (*(_UNCHECKED_OBJECTREF *)handle) == NULL); + return (handle == (OBJECTHANDLE)NULL || (*(_UNCHECKED_OBJECTREF *)handle) == NULL); } inline BOOL ObjectHandleIsNull(OBJECTHANDLE handle) @@ -147,6 +147,18 @@ inline OBJECTHANDLE CreateDependentHandle(IGCHandleStore* store, OBJECTREF prima return hnd; } +inline OBJECTHANDLE CreateWeakInteriorHandle(IGCHandleStore* store, OBJECTREF primary, void* interiorPointerLocation) +{ + OBJECTHANDLE hnd = store->CreateHandleWithExtraInfo(OBJECTREFToObject(primary), HNDTYPE_WEAK_INTERIOR_POINTER, interiorPointerLocation); + if (!hnd) + { + COMPlusThrowOM(); + } + + DiagHandleCreated(hnd, primary); + return hnd; +} + // Global handle creation convenience functions inline OBJECTHANDLE CreateGlobalHandleCommon(OBJECTREF object, HandleType type) { @@ -321,6 +333,11 @@ inline void DestroyGlobalRefcountedHandle(OBJECTHANDLE handle) DestroyHandleCommon(handle, HNDTYPE_REFCOUNTED); } +inline void DestroyWeakInteriorHandle(OBJECTHANDLE handle) +{ + DestroyHandleCommon(handle, HNDTYPE_WEAK_INTERIOR_POINTER); +} + inline void DestroyTypedHandle(OBJECTHANDLE handle) { DiagHandleDestroyed(handle); @@ -331,13 +348,14 @@ inline void DestroyTypedHandle(OBJECTHANDLE handle) #ifndef FEATURE_NATIVEAOT typedef Wrapper, DestroyHandle> OHWrapper; -typedef Wrapper, DestroyPinningHandle, NULL> PinningHandleHolder; -typedef Wrapper, DestroyAsyncPinningHandle, NULL> AsyncPinningHandleHolder; +typedef Wrapper, DestroyPinningHandle, 0> PinningHandleHolder; +typedef Wrapper, DestroyAsyncPinningHandle, 0> AsyncPinningHandleHolder; typedef Wrapper, DestroyRefcountedHandle> RefCountedOHWrapper; typedef Holder, DestroyLongWeakHandle> LongWeakHandleHolder; typedef Holder, DestroyGlobalStrongHandle> GlobalStrongHandleHolder; typedef Holder, DestroyGlobalShortWeakHandle> GlobalShortWeakHandleHolder; +typedef Holder, DestroyWeakInteriorHandle> WeakInteriorHandleHolder; typedef Holder, ResetOBJECTHANDLE> ObjectInHandleHolder; class RCOBJECTHANDLEHolder : public RefCountedOHWrapper diff --git a/src/coreclr/vm/gcheaputilities.cpp b/src/coreclr/vm/gcheaputilities.cpp index 1eeca5d999db..2f588ae6bdae 100644 --- a/src/coreclr/vm/gcheaputilities.cpp +++ b/src/coreclr/vm/gcheaputilities.cpp @@ -5,6 +5,7 @@ #include "configuration.h" #include "gcheaputilities.h" #include "appdomain.hpp" +#include "hostinformation.h" #include "../gc/env/gcenv.ee.h" #include "../gc/env/gctoeeinterface.standalone.inl" @@ -85,7 +86,6 @@ PTR_VOID GCHeapUtilities::GetGCModuleBase() namespace { - // This block of code contains all of the state necessary to handle incoming // EtwCallbacks before the GC has been initialized. This is a tricky problem // because EtwCallbacks can appear at any time, even when we are just about @@ -161,18 +161,56 @@ void StashKeywordAndLevel(bool isPublicProvider, GCEventKeyword keywords, GCEven } #ifdef FEATURE_STANDALONE_GC -HMODULE LoadStandaloneGc(LPCWSTR libFileName) +HMODULE LoadStandaloneGc(LPCWSTR libFileName, LPCWSTR libFilePath) { LIMITED_METHOD_CONTRACT; + HMODULE result = nullptr; + + if (libFilePath) + { + return CLRLoadLibrary(libFilePath); + } - // Look for the standalone GC module next to the clr binary - PathString libPath = GetInternalSystemDirectory(); - libPath.Append(libFileName); + // + // This is not a security feature. + // The libFileName originates either from an environment variable or from the runtimeconfig.json + // These are trusted locations, and therefore even if it is a relative path, there is no security risk. + // + // However, users often don't know the absolute path to their coreclr module, especially on production. + // Therefore we allow referencing it from an arbitrary location through libFilePath instead. Users, however + // are warned that they should keep the file in a secure location such that it cannot be tampered. + // + if (!ValidateModuleName(libFileName)) + { + LOG((LF_GC, LL_INFO100, "Invalid GC name found %s\n", libFileName)); + return nullptr; + } + + SString appBase; + if (HostInformation::GetProperty("APP_CONTEXT_BASE_DIRECTORY", appBase)) + { + PathString libPath = appBase.GetUnicode(); + libPath.Append(libFileName); - LOG((LF_GC, LL_INFO100, "Loading standalone GC from path %s\n", libPath.GetUTF8())); + LOG((LF_GC, LL_INFO100, "Loading standalone GC from appBase %s\n", libPath.GetUTF8())); + + LPCWSTR libraryName = libPath.GetUnicode(); + result = CLRLoadLibrary(libraryName); + } + + if (result == nullptr) + { + // Look for the standalone GC module next to the clr binary + PathString libPath = GetInternalSystemDirectory(); + libPath.Append(libFileName); + + LOG((LF_GC, LL_INFO100, "Loading standalone GC by coreclr %s\n", libPath.GetUTF8())); + + LPCWSTR libraryName = libPath.GetUnicode(); + result = CLRLoadLibrary(libraryName); + } - LPCWSTR libraryName = libPath.GetUnicode(); - return CLRLoadLibrary(libraryName); + return result; } #endif // FEATURE_STANDALONE_GC @@ -182,7 +220,7 @@ HMODULE LoadStandaloneGc(LPCWSTR libFileName) // // See Documentation/design-docs/standalone-gc-loading.md for details // on the loading protocol in use here. -HRESULT LoadAndInitializeGC(LPCWSTR standaloneGcLocation) +HRESULT LoadAndInitializeGC(LPCWSTR standaloneGCName, LPCWSTR standaloneGCPath) { LIMITED_METHOD_CONTRACT; @@ -190,13 +228,16 @@ HRESULT LoadAndInitializeGC(LPCWSTR standaloneGcLocation) LOG((LF_GC, LL_FATALERROR, "EE not built with the ability to load standalone GCs")); return E_FAIL; #else - HMODULE hMod = LoadStandaloneGc(standaloneGcLocation); + HMODULE hMod = LoadStandaloneGc(standaloneGCName, standaloneGCPath); if (!hMod) { HRESULT err = GetLastError(); #ifdef LOGGING - MAKE_UTF8PTR_FROMWIDE(standaloneGcLocationUtf8, standaloneGcLocation); - LOG((LF_GC, LL_FATALERROR, "Load of %s failed\n", standaloneGcLocationUtf8)); + LPCWSTR standaloneGCNameLogging = standaloneGCName ? standaloneGCName : W(""); + LPCWSTR standaloneGCPathLogging = standaloneGCPath ? standaloneGCPath : W(""); + MAKE_UTF8PTR_FROMWIDE(standaloneGCNameUtf8, standaloneGCNameLogging); + MAKE_UTF8PTR_FROMWIDE(standaloneGCPathUtf8, standaloneGCPathLogging); + LOG((LF_GC, LL_FATALERROR, "Load of %s or %s failed\n", standaloneGCNameUtf8, standaloneGCPathUtf8)); #endif // LOGGING return __HRESULT_FROM_WIN32(err); } @@ -344,16 +385,17 @@ HRESULT GCHeapUtilities::LoadAndInitialize() assert(g_gc_load_status == GC_LOAD_STATUS_BEFORE_START); g_gc_load_status = GC_LOAD_STATUS_START; - LPCWSTR standaloneGcLocation = Configuration::GetKnobStringValue(W("System.GC.Name"), CLRConfig::EXTERNAL_GCName); + LPCWSTR standaloneGCName = Configuration::GetKnobStringValue(W("System.GC.Name"), CLRConfig::EXTERNAL_GCName); + LPCWSTR standaloneGCPath = Configuration::GetKnobStringValue(W("System.GC.Path"), CLRConfig::EXTERNAL_GCPath); g_gc_dac_vars.major_version_number = GC_INTERFACE_MAJOR_VERSION; g_gc_dac_vars.minor_version_number = GC_INTERFACE_MINOR_VERSION; - if (!standaloneGcLocation) + if (!standaloneGCName && !standaloneGCPath) { return InitializeDefaultGC(); } else { - return LoadAndInitializeGC(standaloneGcLocation); + return LoadAndInitializeGC(standaloneGCName, standaloneGCPath); } } diff --git a/src/coreclr/vm/gchelpers.cpp b/src/coreclr/vm/gchelpers.cpp index ecbf8f09ce29..63754563b496 100644 --- a/src/coreclr/vm/gchelpers.cpp +++ b/src/coreclr/vm/gchelpers.cpp @@ -1484,39 +1484,4 @@ void ErectWriteBarrierForMT(MethodTable **dst, MethodTable *ref) } } } -} - -//---------------------------------------------------------------------------- -// -// Write Barrier Support for bulk copy ("Clone") operations -// -// StartPoint is the target bulk copy start point -// len is the length of the bulk copy (in bytes) -// -// -// Performance Note: -// -// This is implemented somewhat "conservatively", that is we -// assume that all the contents of the bulk copy are object -// references. If they are not, and the value lies in the -// ephemeral range, we will set false positives in the card table. -// -// We could use the pointer maps and do this more accurately if necessary - -#if defined(_MSC_VER) && defined(TARGET_X86) -#pragma optimize("y", on) // Small critical routines, don't put in EBP frame -#endif //_MSC_VER && TARGET_X86 - -void -SetCardsAfterBulkCopy(Object **start, size_t len) -{ - // If the size is smaller than a pointer, no write barrier is required. - if (len >= sizeof(uintptr_t)) - { - InlinedSetCardsAfterBulkCopyHelper(start, len); - } -} - -#if defined(_MSC_VER) && defined(TARGET_X86) -#pragma optimize("", on) // Go back to command line default optimizations -#endif //_MSC_VER && TARGET_X86 +} \ No newline at end of file diff --git a/src/coreclr/vm/gchelpers.h b/src/coreclr/vm/gchelpers.h index 242a0156964d..6e5a696dd2cc 100644 --- a/src/coreclr/vm/gchelpers.h +++ b/src/coreclr/vm/gchelpers.h @@ -87,7 +87,6 @@ extern void ThrowOutOfMemoryDimensionsExceeded(); //======================================================================== void ErectWriteBarrier(OBJECTREF* dst, OBJECTREF ref); -void SetCardsAfterBulkCopy(Object **start, size_t len); void PublishFrozenObject(Object*& orObject); diff --git a/src/coreclr/vm/gchelpers.inl b/src/coreclr/vm/gchelpers.inl index e56bcd16a1ed..60b93bfad94d 100644 --- a/src/coreclr/vm/gchelpers.inl +++ b/src/coreclr/vm/gchelpers.inl @@ -31,13 +31,9 @@ FORCEINLINE void InlinedSetCardsAfterBulkCopyHelper(Object **start, size_t len) { - // Check whether the writes were even into the heap. If not there's no card update required. - // Also if the size is smaller than a pointer, no write barrier is required. + // Caller is expected to check whether the writes were even into the heap _ASSERTE(len >= sizeof(uintptr_t)); - if ((BYTE*)start < g_lowest_address || (BYTE*)start >= g_highest_address) - { - return; - } + _ASSERTE(((BYTE*)start >= g_lowest_address) && ((BYTE*)start < g_highest_address)); // Don't optimize the Generation 0 case if we are checking for write barrier violations // since we need to update the shadow heap even in the generation 0 case. diff --git a/src/coreclr/vm/gcinfodecoder.cpp b/src/coreclr/vm/gcinfodecoder.cpp index 855aa24f627f..66347d8bf8d2 100644 --- a/src/coreclr/vm/gcinfodecoder.cpp +++ b/src/coreclr/vm/gcinfodecoder.cpp @@ -363,14 +363,18 @@ GcInfoDecoder::GcInfoDecoder( } #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED - if(flags & (DECODE_GC_LIFETIMES)) + if(flags & (DECODE_GC_LIFETIMES | DECODE_INTERRUPTIBILITY)) { if(m_NumSafePoints) { - m_SafePointIndex = FindSafePoint(m_InstructionOffset); + // Safepoints are encoded with a -1 adjustment + // DECODE_GC_LIFETIMES adjusts the offset accordingly, but DECODE_INTERRUPTIBILITY does not + // adjust here + UINT32 offset = flags & DECODE_INTERRUPTIBILITY ? m_InstructionOffset - 1 : m_InstructionOffset; + m_SafePointIndex = FindSafePoint(offset); } } - else if(flags & (DECODE_FOR_RANGES_CALLBACK | DECODE_INTERRUPTIBILITY)) + else if(flags & DECODE_FOR_RANGES_CALLBACK) { // Note that normalization as a code offset can be different than // normalization as code length @@ -381,7 +385,13 @@ GcInfoDecoder::GcInfoDecoder( } #endif - if(!m_IsInterruptible && (flags & DECODE_INTERRUPTIBILITY)) + // we do not support both DECODE_INTERRUPTIBILITY and DECODE_FOR_RANGES_CALLBACK at the same time + // as both will enumerate and consume interruptible ranges. + _ASSERTE((flags & (DECODE_INTERRUPTIBILITY | DECODE_FOR_RANGES_CALLBACK)) != + (DECODE_INTERRUPTIBILITY | DECODE_FOR_RANGES_CALLBACK)); + + _ASSERTE(!m_IsInterruptible); + if(flags & DECODE_INTERRUPTIBILITY) { EnumerateInterruptibleRanges(&SetIsInterruptibleCB, this); } @@ -393,6 +403,28 @@ bool GcInfoDecoder::IsInterruptible() return m_IsInterruptible; } +bool GcInfoDecoder::HasInterruptibleRanges() +{ + _ASSERTE(m_Flags & (DECODE_INTERRUPTIBILITY | DECODE_GC_LIFETIMES)); + return m_NumInterruptibleRanges > 0; +} + +bool GcInfoDecoder::IsSafePoint() +{ + _ASSERTE(m_Flags & (DECODE_INTERRUPTIBILITY | DECODE_GC_LIFETIMES)); + return m_SafePointIndex != m_NumSafePoints; +} + +bool GcInfoDecoder::AreSafePointsInterruptible() +{ + return m_Version >= 3; +} + +bool GcInfoDecoder::IsInterruptibleSafePoint() +{ + return IsSafePoint() && AreSafePointsInterruptible(); +} + bool GcInfoDecoder::HasMethodDescGenericsInstContext() { _ASSERTE( m_Flags & DECODE_GENERICS_INST_CONTEXT ); @@ -515,7 +547,7 @@ void GcInfoDecoder::EnumerateSafePoints(EnumerateSafePointsCallback *pCallback, offset--; #endif - pCallback(offset, hCallback); + pCallback(this, offset, hCallback); } } #endif diff --git a/src/coreclr/vm/genmeth.cpp b/src/coreclr/vm/genmeth.cpp index 507eb4122a2e..a4d28d12eff6 100644 --- a/src/coreclr/vm/genmeth.cpp +++ b/src/coreclr/vm/genmeth.cpp @@ -903,7 +903,7 @@ MethodDesc::FindOrCreateAssociatedMethodDesc(MethodDesc* pDefMD, // Indicate that this is a stub method which takes a BOXed this pointer. // An BoxedEntryPointStub may still be an InstantiatedMethodDesc pResultMD->SetIsUnboxingStub(); - pResultMD->AsInstantiatedMethodDesc()->SetupWrapperStubWithInstantiations(pMDescInCanonMT, NULL, NULL); + pResultMD->AsInstantiatedMethodDesc()->SetupWrapperStubWithInstantiations(pMDescInCanonMT, 0, NULL); pResultMD->SetTemporaryEntryPoint(pAllocator, &amt); diff --git a/src/coreclr/vm/hash.cpp b/src/coreclr/vm/hash.cpp index 749783c6ccfb..54791c5fff9b 100644 --- a/src/coreclr/vm/hash.cpp +++ b/src/coreclr/vm/hash.cpp @@ -780,7 +780,7 @@ UPTR HashMap::Gethash (UPTR key) STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_FORBID_FAULT; - return LookupValue(key,NULL); + return LookupValue(key,0); } diff --git a/src/coreclr/vm/hosting.cpp b/src/coreclr/vm/hosting.cpp index 3482781620be..065b254dee40 100644 --- a/src/coreclr/vm/hosting.cpp +++ b/src/coreclr/vm/hosting.cpp @@ -16,12 +16,6 @@ LPVOID ClrVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, } CONTRACTL_END; -#ifdef FAILPOINTS_ENABLED - if (RFS_HashStack ()) - return NULL; -#endif - - #ifdef _DEBUG if (g_fEEStarted) { // On Debug build we make sure that a thread is not going to do memory allocation diff --git a/src/coreclr/vm/i386/asmconstants.h b/src/coreclr/vm/i386/asmconstants.h index edafbdf72ae7..c1a577caa0f8 100644 --- a/src/coreclr/vm/i386/asmconstants.h +++ b/src/coreclr/vm/i386/asmconstants.h @@ -233,14 +233,7 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__FrameHandlerExRecord__m_pEntryFrame == offsetof( #endif - -#define MethodDesc_m_wFlags DBG_FRE(0x1a, 0x06) -ASMCONSTANTS_C_ASSERT(MethodDesc_m_wFlags == offsetof(MethodDesc, m_wFlags)) - -#define MethodDesc_mdcClassification 7 -ASMCONSTANTS_C_ASSERT(MethodDesc_mdcClassification == mdcClassification) - -#define ComPlusCallMethodDesc__m_pComPlusCallInfo DBG_FRE(0x1C, 0x8) +#define ComPlusCallMethodDesc__m_pComPlusCallInfo DBG_FRE(0x20, 0xC) ASMCONSTANTS_C_ASSERT(ComPlusCallMethodDesc__m_pComPlusCallInfo == offsetof(ComPlusCallMethodDesc, m_pComPlusCallInfo)) #define ComPlusCallInfo__m_pRetThunk 0x10 diff --git a/src/coreclr/vm/i386/asmhelpers.S b/src/coreclr/vm/i386/asmhelpers.S index ff777550bfab..54f58fd75bb6 100644 --- a/src/coreclr/vm/i386/asmhelpers.S +++ b/src/coreclr/vm/i386/asmhelpers.S @@ -126,31 +126,6 @@ LEAF_ENTRY RestoreFPUContext, _TEXT ret 4 LEAF_END RestoreFPUContext, _TEXT -// ----------------------------------------------------------------------- -// The out-of-line portion of the code to enable preemptive GC. -// After the work is done, the code jumps back to the "pRejoinPoint" -// which should be emitted right after the inline part is generated. -// -// Assumptions: -// ebx = Thread -// Preserves -// all registers except ecx. -// -// ----------------------------------------------------------------------- -NESTED_ENTRY StubRareEnable, _TEXT, NoHandler - push eax - push edx - - push ebx - - CHECK_STACK_ALIGNMENT - call C_FUNC(StubRareEnableWorker) - - pop edx - pop eax - ret -NESTED_END StubRareEnable, _TEXT - NESTED_ENTRY StubRareDisableTHROW, _TEXT, NoHandler push eax push edx diff --git a/src/coreclr/vm/i386/asmhelpers.asm b/src/coreclr/vm/i386/asmhelpers.asm index 1d02fc48f8d8..5f03683f588f 100644 --- a/src/coreclr/vm/i386/asmhelpers.asm +++ b/src/coreclr/vm/i386/asmhelpers.asm @@ -24,7 +24,6 @@ EXTERN __imp__RtlUnwind@16:DWORD ifdef _DEBUG EXTERN _HelperMethodFrameConfirmState@20:PROC endif -EXTERN _StubRareEnableWorker@4:PROC ifdef FEATURE_COMINTEROP EXTERN _StubRareDisableHRWorker@4:PROC endif ; FEATURE_COMINTEROP @@ -394,29 +393,6 @@ endif retn 8 _CallJitEHFinallyHelper@8 ENDP -;----------------------------------------------------------------------- -; The out-of-line portion of the code to enable preemptive GC. -; After the work is done, the code jumps back to the "pRejoinPoint" -; which should be emitted right after the inline part is generated. -; -; Assumptions: -; ebx = Thread -; Preserves -; all registers except ecx. -; -;----------------------------------------------------------------------- -_StubRareEnable proc public - push eax - push edx - - push ebx - call _StubRareEnableWorker@4 - - pop edx - pop eax - retn -_StubRareEnable ENDP - ifdef FEATURE_COMINTEROP _StubRareDisableHR proc public push edx diff --git a/src/coreclr/vm/i386/cgenx86.cpp b/src/coreclr/vm/i386/cgenx86.cpp index 108bc66a99b1..d9dc22d14819 100644 --- a/src/coreclr/vm/i386/cgenx86.cpp +++ b/src/coreclr/vm/i386/cgenx86.cpp @@ -911,18 +911,6 @@ Stub *GenerateInitPInvokeFrameHelper() RETURN psl->Link(SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()); } - -extern "C" VOID STDCALL StubRareEnableWorker(Thread *pThread) -{ - WRAPPER_NO_CONTRACT; - - //printf("RareEnable\n"); - pThread->RareEnablePreemptiveGC(); -} - - - - // Disable when calling into managed code from a place that fails via Exceptions extern "C" VOID STDCALL StubRareDisableTHROWWorker(Thread *pThread) { diff --git a/src/coreclr/vm/i386/gmsx86.cpp b/src/coreclr/vm/i386/gmsx86.cpp index ca3b45b5b4ea..e329d7bf9750 100644 --- a/src/coreclr/vm/i386/gmsx86.cpp +++ b/src/coreclr/vm/i386/gmsx86.cpp @@ -150,7 +150,7 @@ static bool shouldEnterCall(PTR_BYTE ip) { // xxxx starts with a JMP [] then do what you would do for jmp XXXX if (*ip == 0xE9 && callsInstrumented()) { // jmp helper PTR_BYTE tmpIp = ip + 5; - PTR_BYTE target = tmpIp + (__int32)*((PTR_TADDR)(PTR_TO_TADDR(tmpIp) - 4)); + PTR_BYTE target = tmpIp + (int32_t)*((PTR_TADDR)(PTR_TO_TADDR(tmpIp) - 4)); if (target[0] == 0xFF && target[1] == 0x25) { // jmp [xxxx] (to external dll) ip = PTR_BYTE(*((PTR_TADDR)(PTR_TO_TADDR(ip) - 4))); } @@ -278,11 +278,11 @@ static bool shouldEnterCall(PTR_BYTE ip) { break; case 0xEB: // jmp - ip += (signed __int8) ip[1] + 2; + ip += (int8_t) ip[1] + 2; break; case 0xE9: // jmp - ip += (__int32)*PTR_DWORD(PTR_TO_TADDR(ip) + 1) + 5; + ip += (int32_t)*PTR_DWORD(PTR_TO_TADDR(ip) + 1) + 5; break; case 0xF7: // test r/m32, imm32 @@ -302,7 +302,7 @@ static bool shouldEnterCall(PTR_BYTE ip) { // Magellan code coverage build // We always follow forward jump to avoid possible looping. { - PTR_BYTE tmpIp = ip + (TADDR)(signed __int8) ip[1] + 2; + PTR_BYTE tmpIp = ip + (TADDR)(int8_t) ip[1] + 2; if (tmpIp > ip) { ip = tmpIp; // follow forwards jump } @@ -494,12 +494,12 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, goto incIp1; case 0xEB: // jmp - ip += (signed __int8) ip[1] + 2; + ip += (int8_t) ip[1] + 2; break; case 0x72: // jb for gcc. { - PTR_BYTE tmpIp = ip + (int)(signed __int8)ip[1] + 2; + PTR_BYTE tmpIp = ip + (int)(int8_t)ip[1] + 2; if (tmpIp > ip) ip = tmpIp; else @@ -511,7 +511,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, ip += 5; if (epilogCallRet == 0) { - PTR_BYTE target = ip + (__int32)*PTR_DWORD(PTR_TO_TADDR(ip) - 4); // calculate target + PTR_BYTE target = ip + (int32_t)*PTR_DWORD(PTR_TO_TADDR(ip) - 4); // calculate target if (shouldEnterCall(target)) { @@ -525,7 +525,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, case 0xE9: // jmp { PTR_BYTE tmpIp = ip - + ((__int32)*dac_cast(ip + 1) + 5); + + ((int32_t)*dac_cast(ip + 1) + 5); ip = tmpIp; } break; @@ -575,7 +575,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, else if (bFirstCondJmp) { bFirstCondJmp = FALSE; if (ip[1] == 0x85) // jne - ip += (__int32)*dac_cast(ip + 2) + 6; + ip += (int32_t)*dac_cast(ip + 2) + 6; else if (ip[1] >= 0x80 && ip[1] <= 0x8F) // jcc ip += 6; else @@ -583,7 +583,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, } else { if ((ip[1] >= 0x80) && (ip[1] <= 0x8F)) { - PTR_BYTE tmpIp = ip + (__int32)*dac_cast(ip + 2) + 6; + PTR_BYTE tmpIp = ip + (int32_t)*dac_cast(ip + 2) + 6; if ((tmpIp > ip) == (lastCondJmpIp != ip)) { lastCondJmpIp = ip; @@ -623,7 +623,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, // xxxx starts with a JMP [] then do what you would do for call XXXX if ((*ip & 0xFE) == 0xE8 && callsInstrumented()) { // It is a call or a jump (E8 or E9) PTR_BYTE tmpIp = ip + 5; - PTR_BYTE target = tmpIp + (__int32)*PTR_DWORD(PTR_TO_TADDR(tmpIp) - 4); + PTR_BYTE target = tmpIp + (int32_t)*PTR_DWORD(PTR_TO_TADDR(tmpIp) - 4); if (target[0] == 0xFF && target[1] == 0x25) { // jmp [xxxx] (to external dll) target = PTR_BYTE(*PTR_TADDR(PTR_TO_TADDR(ip) - 4)); if (*ip == 0xE9) { // Do logic for jmp @@ -652,7 +652,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, // if (bFirstCondJmp) { bFirstCondJmp = FALSE; - ip += (signed __int8) ip[1] + 2; // follow the non-zero path + ip += (int8_t) ip[1] + 2; // follow the non-zero path break; } goto condJumpDisp8; @@ -666,7 +666,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, condJumpDisp8: { - PTR_BYTE tmpIp = ip + (TADDR)(signed __int8) ip[1] + 2; + PTR_BYTE tmpIp = ip + (TADDR)(int8_t) ip[1] + 2; if ((tmpIp > ip) == (lastCondJmpIp != ip)) { lastCondJmpIp = ip; ip = tmpIp; @@ -712,7 +712,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, if ((ip[1] & 7) == ((ip[1] >> 3) & 7)) { // reg1 == reg2? if (ip[2] == 0x85 && ip[3] == ip[1]) { // TEST reg, reg if (ip[4] == 0x74) { - ip += (signed __int8) ip[5] + 6; // follow the non-zero path + ip += (int8_t) ip[5] + 6; // follow the non-zero path break; } _ASSERTE(ip[4] != 0x0f || ((ip[5] & 0xF0)!=0x80)); // If this goes off, we need the big jumps @@ -721,7 +721,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, { if (ip[2]==0x74) { - ip += (signed __int8) ip[3] + 4; + ip += (int8_t) ip[3] + 4; break; } _ASSERTE(ip[2] != 0x0f || ((ip[3] & 0xF0)!=0x80)); // If this goes off, we need the big jumps @@ -876,11 +876,11 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, case 0x81: // OP r/m32, if (!b16bit && ip[1] == 0xC4) { // ADD ESP, ESP = dac_cast(dac_cast(ESP) + - (__int32)*dac_cast(ip + 2)); + (int32_t)*dac_cast(ip + 2)); ip += 6; break; } else if (!b16bit && ip[1] == 0xC5) { // ADD EBP, - lazyState->_ebp += (__int32)*dac_cast(ip + 2); + lazyState->_ebp += (int32_t)*dac_cast(ip + 2); ip += 6; break; } @@ -903,22 +903,22 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, goto decodeRM; case 0x83: // OP r/m32, if (ip[1] == 0xC4) { // ADD ESP, - ESP = dac_cast(dac_cast(ESP) + (signed __int8)ip[2]); + ESP = dac_cast(dac_cast(ESP) + (int8_t)ip[2]); ip += 3; break; } if (ip[1] == 0xec) { // SUB ESP, - ESP = PTR_TADDR(PTR_TO_TADDR(ESP) - (signed __int8)ip[2]); + ESP = PTR_TADDR(PTR_TO_TADDR(ESP) - (int8_t)ip[2]); ip += 3; break; } if (ip[1] == 0xe4) { // AND ESP, - ESP = PTR_TADDR(PTR_TO_TADDR(ESP) & (signed __int8)ip[2]); + ESP = PTR_TADDR(PTR_TO_TADDR(ESP) & (int8_t)ip[2]); ip += 3; break; } if (ip[1] == 0xc5) { // ADD EBP, - lazyState->_ebp += (signed __int8)ip[2]; + lazyState->_ebp += (int8_t)ip[2]; ip += 3; break; } @@ -965,15 +965,15 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, if ((ip[1] & 0xc7) == 0x44 && ip[2] == 0x24) // move reg, [esp+imm8] { if ( ip[1] == 0x5C ) { // MOV EBX, [ESP+XX] - lazyState->_pEbx = PTR_TADDR(PTR_TO_TADDR(ESP) + (signed __int8)ip[3]); + lazyState->_pEbx = PTR_TADDR(PTR_TO_TADDR(ESP) + (int8_t)ip[3]); lazyState->_ebx = *lazyState->_pEbx ; } else if ( ip[1] == 0x74 ) { // MOV ESI, [ESP+XX] - lazyState->_pEsi = PTR_TADDR(PTR_TO_TADDR(ESP) + (signed __int8)ip[3]); + lazyState->_pEsi = PTR_TADDR(PTR_TO_TADDR(ESP) + (int8_t)ip[3]); lazyState->_esi = *lazyState->_pEsi; } else if ( ip[1] == 0x7C ) { // MOV EDI, [ESP+XX] - lazyState->_pEdi = PTR_TADDR(PTR_TO_TADDR(ESP) + (signed __int8)ip[3]); + lazyState->_pEdi = PTR_TADDR(PTR_TO_TADDR(ESP) + (int8_t)ip[3]); lazyState->_edi = *lazyState->_pEdi; } else if ( ip[1] == 0x64 /*ESP*/ || ip[1] == 0x6C /*EBP*/) @@ -987,15 +987,15 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, // gcc sometimes restores callee-preserved registers // via 'mov reg, [ebp-xx]' instead of 'pop reg' if ( ip[1] == 0x5D ) { // MOV EBX, [EBP+XX] - lazyState->_pEbx = PTR_TADDR(lazyState->_ebp + (signed __int8)ip[2]); + lazyState->_pEbx = PTR_TADDR(lazyState->_ebp + (int8_t)ip[2]); lazyState->_ebx = *lazyState->_pEbx ; } else if ( ip[1] == 0x75 ) { // MOV ESI, [EBP+XX] - lazyState->_pEsi = PTR_TADDR(lazyState->_ebp + (signed __int8)ip[2]); + lazyState->_pEsi = PTR_TADDR(lazyState->_ebp + (int8_t)ip[2]); lazyState->_esi = *lazyState->_pEsi; } else if ( ip[1] == 0x7D ) { // MOV EDI, [EBP+XX] - lazyState->_pEdi = PTR_TADDR(lazyState->_ebp + (signed __int8)ip[2]); + lazyState->_pEdi = PTR_TADDR(lazyState->_ebp + (int8_t)ip[2]); lazyState->_edi = *lazyState->_pEdi; } else if ( ip[1] == 0x65 /*ESP*/ || ip[1] == 0x6D /*EBP*/) @@ -1011,15 +1011,15 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, // gcc sometimes restores callee-preserved registers // via 'mov reg, [ebp-xx]' instead of 'pop reg' if ( ip[1] == 0xDD ) { // MOV EBX, [EBP+XXXXXXXX] - lazyState->_pEbx = PTR_TADDR(lazyState->_ebp + (__int32)*dac_cast(ip + 2)); + lazyState->_pEbx = PTR_TADDR(lazyState->_ebp + (int32_t)*dac_cast(ip + 2)); lazyState->_ebx = *lazyState->_pEbx ; } else if ( ip[1] == 0xF5 ) { // MOV ESI, [EBP+XXXXXXXX] - lazyState->_pEsi = PTR_TADDR(lazyState->_ebp + (__int32)*dac_cast(ip + 2)); + lazyState->_pEsi = PTR_TADDR(lazyState->_ebp + (int32_t)*dac_cast(ip + 2)); lazyState->_esi = *lazyState->_pEsi; } else if ( ip[1] == 0xFD ) { // MOV EDI, [EBP+XXXXXXXX] - lazyState->_pEdi = PTR_TADDR(lazyState->_ebp + (__int32)*dac_cast(ip + 2)); + lazyState->_pEdi = PTR_TADDR(lazyState->_ebp + (int32_t)*dac_cast(ip + 2)); lazyState->_edi = *lazyState->_pEdi; } else if ( ip[1] == 0xE5 /*ESP*/ || ip[1] == 0xED /*EBP*/) @@ -1035,9 +1035,9 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, case 0x8D: // LEA if ((ip[1] & 0x38) == 0x20) { // Don't allow ESP to be updated if (ip[1] == 0xA5) // LEA ESP, [EBP+XXXX] - ESP = PTR_TADDR(lazyState->_ebp + (__int32)*dac_cast(ip + 2)); + ESP = PTR_TADDR(lazyState->_ebp + (int32_t)*dac_cast(ip + 2)); else if (ip[1] == 0x65) // LEA ESP, [EBP+XX] - ESP = PTR_TADDR(lazyState->_ebp + (signed __int8) ip[2]); + ESP = PTR_TADDR(lazyState->_ebp + (int8_t) ip[2]); else if (ip[1] == 0x24 && ip[2] == 0x24) // LEA ESP, [ESP] ; else if (ip[1] == 0xa4 && ip[2] == 0x24 && *((DWORD *)(&ip[3])) == 0) // Another form of: LEA ESP, [ESP] @@ -1070,7 +1070,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, case 0xC2: // ret N { - unsigned __int16 disp = *dac_cast(ip + 1); + uint16_t disp = *dac_cast(ip + 1); ip = PTR_BYTE(*ESP); lazyState->_pRetAddr = ESP++; _ASSERTE(disp < 64); // sanity check (although strictly speaking not impossible) diff --git a/src/coreclr/vm/i386/jitinterfacex86.cpp b/src/coreclr/vm/i386/jitinterfacex86.cpp index bfc7c0abc674..67decfd147f9 100644 --- a/src/coreclr/vm/i386/jitinterfacex86.cpp +++ b/src/coreclr/vm/i386/jitinterfacex86.cpp @@ -813,7 +813,7 @@ void EmitFastGetSharedStaticBase(CPUSTUBLINKER *psl, CodeLabel *init, bool bCCto if (bGCStatic) { // Indirect to get the pointer to the first GC Static - psl->X86EmitIndexRegLoad(kEAX, kEAX, (__int32) DomainLocalModule::GetOffsetOfGCStaticPointer()); + psl->X86EmitIndexRegLoad(kEAX, kEAX, (int32_t) DomainLocalModule::GetOffsetOfGCStaticPointer()); } // ret diff --git a/src/coreclr/vm/i386/stublinkerx86.cpp b/src/coreclr/vm/i386/stublinkerx86.cpp index 76d888c0c527..8fb36cc501c3 100644 --- a/src/coreclr/vm/i386/stublinkerx86.cpp +++ b/src/coreclr/vm/i386/stublinkerx86.cpp @@ -45,8 +45,6 @@ #ifndef DACCESS_COMPILE - -extern "C" VOID __cdecl StubRareEnable(Thread *pThread); #ifdef FEATURE_COMINTEROP extern "C" HRESULT __cdecl StubRareDisableHR(Thread *pThread); #endif // FEATURE_COMINTEROP @@ -144,7 +142,7 @@ class X64NearJumpSetup : public InstructionFormat } } - virtual VOID EmitInstruction(UINT refsize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refsize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { LIMITED_METHOD_CONTRACT if (k8 == refsize) @@ -273,18 +271,18 @@ class X64NearJumpExecute : public InstructionFormat } } - virtual VOID EmitInstruction(UINT refsize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refsize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { LIMITED_METHOD_CONTRACT if (k8 == refsize) { pOutBufferRW[0] = 0xeb; - *((__int8*)(pOutBufferRW+1)) = (__int8)fixedUpReference; + *((int8_t*)(pOutBufferRW+1)) = (int8_t)fixedUpReference; } else if (k32 == refsize) { pOutBufferRW[0] = 0xe9; - *((__int32*)(pOutBufferRW+1)) = (__int32)fixedUpReference; + *((int32_t*)(pOutBufferRW+1)) = (int32_t)fixedUpReference; } else if (k64Small == refsize) { @@ -409,18 +407,18 @@ class X86NearJump : public InstructionFormat } } - virtual VOID EmitInstruction(UINT refsize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refsize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { LIMITED_METHOD_CONTRACT if (k8 == refsize) { pOutBufferRW[0] = 0xeb; - *((__int8*)(pOutBufferRW+1)) = (__int8)fixedUpReference; + *((int8_t*)(pOutBufferRW+1)) = (int8_t)fixedUpReference; } else if (k32 == refsize) { pOutBufferRW[0] = 0xe9; - *((__int32*)(pOutBufferRW+1)) = (__int32)fixedUpReference; + *((int32_t*)(pOutBufferRW+1)) = (int32_t)fixedUpReference; } #ifdef TARGET_AMD64 else if (k64Small == refsize) @@ -543,19 +541,19 @@ class X86CondJump : public InstructionFormat return (refsize == k8 ? 2 : 6); } - virtual VOID EmitInstruction(UINT refsize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refsize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { LIMITED_METHOD_CONTRACT if (refsize == k8) { pOutBufferRW[0] = static_cast(0x70 | variationCode); - *((__int8*)(pOutBufferRW+1)) = (__int8)fixedUpReference; + *((int8_t*)(pOutBufferRW+1)) = (int8_t)fixedUpReference; } else { pOutBufferRW[0] = 0x0f; pOutBufferRW[1] = static_cast(0x80 | variationCode); - *((__int32*)(pOutBufferRW+2)) = (__int32)fixedUpReference; + *((int32_t*)(pOutBufferRW+2)) = (int32_t)fixedUpReference; } } }; @@ -600,7 +598,7 @@ class X86Call : public InstructionFormat } } - virtual VOID EmitInstruction(UINT refsize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refsize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { LIMITED_METHOD_CONTRACT @@ -608,7 +606,7 @@ class X86Call : public InstructionFormat { case k32: pOutBufferRW[0] = 0xE8; - *((__int32*)(1+pOutBufferRW)) = (__int32)fixedUpReference; + *((int32_t*)(1+pOutBufferRW)) = (int32_t)fixedUpReference; break; #ifdef TARGET_AMD64 @@ -719,14 +717,14 @@ class X86PushImm32 : public InstructionFormat return 5; } - virtual VOID EmitInstruction(UINT refsize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refsize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { LIMITED_METHOD_CONTRACT; pOutBufferRW[0] = 0x68; // only support absolute pushimm32 of the label address. The fixedUpReference is // the offset to the label from the current point, so add to get address - *((__int32*)(1+pOutBufferRW)) = (__int32)(fixedUpReference); + *((int32_t*)(1+pOutBufferRW)) = (int32_t)(fixedUpReference); } }; @@ -789,7 +787,7 @@ class X64LeaRIP : public InstructionFormat } } - virtual VOID EmitInstruction(UINT refsize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refsize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { LIMITED_METHOD_CONTRACT; @@ -807,7 +805,7 @@ class X64LeaRIP : public InstructionFormat pOutBufferRW[2] = (BYTE)(0x05 | (reg << 3)); // only support absolute pushimm32 of the label address. The fixedUpReference is // the offset to the label from the current point, so add to get address - *((__int32*)(3+pOutBufferRW)) = (__int32)(fixedUpReference); + *((int32_t*)(3+pOutBufferRW)) = (int32_t)(fixedUpReference); } }; @@ -1301,7 +1299,7 @@ VOID StubLinkerCPU::X86EmitPopRegs(unsigned regSet) //--------------------------------------------------------------- VOID StubLinkerCPU::X86EmitIndexRegLoad(X86Reg dstreg, X86Reg srcreg, - __int32 ofs) + int32_t ofs) { STANDARD_VM_CONTRACT; X86EmitOffsetModRM(0x8b, dstreg, srcreg, ofs); @@ -1317,7 +1315,7 @@ VOID StubLinkerCPU::X86EmitIndexRegLoad(X86Reg dstreg, // using X86EmitIndexRegStoreRSP. //--------------------------------------------------------------- VOID StubLinkerCPU::X86EmitIndexRegStore(X86Reg dstreg, - __int32 ofs, + int32_t ofs, X86Reg srcreg) { STANDARD_VM_CONTRACT; @@ -1336,7 +1334,7 @@ VOID StubLinkerCPU::X86EmitIndexRegStore(X86Reg dstreg, // It marks the instruction has 64bit so that the processor // performs a 8byte data move to a RSP based stack location. //--------------------------------------------------------------- -VOID StubLinkerCPU::X86EmitIndexRegStoreRSP(__int32 ofs, +VOID StubLinkerCPU::X86EmitIndexRegStoreRSP(int32_t ofs, X86Reg srcreg) { STANDARD_VM_CONTRACT; @@ -1351,7 +1349,7 @@ VOID StubLinkerCPU::X86EmitIndexRegStoreRSP(__int32 ofs, // It marks the instruction has 64bit so that the processor // performs a 8byte data move to a R12 based stack location. //--------------------------------------------------------------- -VOID StubLinkerCPU::X86EmitIndexRegStoreR12(__int32 ofs, +VOID StubLinkerCPU::X86EmitIndexRegStoreR12(int32_t ofs, X86Reg srcreg) { STANDARD_VM_CONTRACT; @@ -1364,7 +1362,7 @@ VOID StubLinkerCPU::X86EmitIndexRegStoreR12(__int32 ofs, // Emits: // push dword ptr [ + ] //--------------------------------------------------------------- -VOID StubLinkerCPU::X86EmitIndexPush(X86Reg srcreg, __int32 ofs) +VOID StubLinkerCPU::X86EmitIndexPush(X86Reg srcreg, int32_t ofs) { STANDARD_VM_CONTRACT; @@ -1383,8 +1381,8 @@ VOID StubLinkerCPU::X86EmitIndexPush(X86Reg srcreg, __int32 ofs) VOID StubLinkerCPU::X86EmitBaseIndexPush( X86Reg baseReg, X86Reg indexReg, - __int32 scale, - __int32 ofs) + int32_t scale, + int32_t ofs) { STANDARD_VM_CONTRACT; @@ -1396,12 +1394,12 @@ VOID StubLinkerCPU::X86EmitBaseIndexPush( // Emits: // push dword ptr [ESP + ] //--------------------------------------------------------------- -VOID StubLinkerCPU::X86EmitSPIndexPush(__int32 ofs) +VOID StubLinkerCPU::X86EmitSPIndexPush(int32_t ofs) { STANDARD_VM_CONTRACT; - __int8 ofs8 = (__int8) ofs; - if (ofs == (__int32) ofs8) + int8_t ofs8 = (int8_t) ofs; + if (ofs == (int32_t) ofs8) { // The offset can be expressed in a byte (can use the byte // form of the push esp instruction) @@ -1415,7 +1413,7 @@ VOID StubLinkerCPU::X86EmitSPIndexPush(__int32 ofs) // of the push esp instruction) BYTE code[] = {0xff, 0xb4, 0x24, 0x0, 0x0, 0x0, 0x0}; - *(__int32 *)(&code[3]) = ofs; + *(int32_t *)(&code[3]) = ofs; EmitBytes(code, sizeof(code)); } @@ -1427,7 +1425,7 @@ VOID StubLinkerCPU::X86EmitSPIndexPush(__int32 ofs) // Emits: // pop dword ptr [ + ] //--------------------------------------------------------------- -VOID StubLinkerCPU::X86EmitIndexPop(X86Reg srcreg, __int32 ofs) +VOID StubLinkerCPU::X86EmitIndexPop(X86Reg srcreg, int32_t ofs) { STANDARD_VM_CONTRACT; @@ -1443,7 +1441,7 @@ VOID StubLinkerCPU::X86EmitIndexPop(X86Reg srcreg, __int32 ofs) // Emits: // lea , [ + //--------------------------------------------------------------- -VOID StubLinkerCPU::X86EmitIndexLea(X86Reg dstreg, X86Reg srcreg, __int32 ofs) +VOID StubLinkerCPU::X86EmitIndexLea(X86Reg dstreg, X86Reg srcreg, int32_t ofs) { CONTRACTL { @@ -1457,7 +1455,7 @@ VOID StubLinkerCPU::X86EmitIndexLea(X86Reg dstreg, X86Reg srcreg, __int32 ofs) } #if defined(TARGET_AMD64) -VOID StubLinkerCPU::X86EmitIndexLeaRSP(X86Reg dstreg, X86Reg srcreg, __int32 ofs) +VOID StubLinkerCPU::X86EmitIndexLeaRSP(X86Reg dstreg, X86Reg srcreg, int32_t ofs) { STANDARD_VM_CONTRACT; @@ -1680,7 +1678,7 @@ VOID StubLinkerCPU::X64EmitMovXmmXmm(X86Reg destXmmreg, X86Reg srcXmmReg) //--------------------------------------------------------------- // movdqa XmmN, [baseReg + offset] //--------------------------------------------------------------- -VOID StubLinkerCPU::X64EmitMovdqaFromMem(X86Reg Xmmreg, X86Reg baseReg, __int32 ofs) +VOID StubLinkerCPU::X64EmitMovdqaFromMem(X86Reg Xmmreg, X86Reg baseReg, int32_t ofs) { STANDARD_VM_CONTRACT; X64EmitMovXmmWorker(0x66, 0x6F, Xmmreg, baseReg, ofs); @@ -1689,7 +1687,7 @@ VOID StubLinkerCPU::X64EmitMovdqaFromMem(X86Reg Xmmreg, X86Reg baseReg, __int32 //--------------------------------------------------------------- // movdqa [baseReg + offset], XmmN //--------------------------------------------------------------- -VOID StubLinkerCPU::X64EmitMovdqaToMem(X86Reg Xmmreg, X86Reg baseReg, __int32 ofs) +VOID StubLinkerCPU::X64EmitMovdqaToMem(X86Reg Xmmreg, X86Reg baseReg, int32_t ofs) { STANDARD_VM_CONTRACT; X64EmitMovXmmWorker(0x66, 0x7F, Xmmreg, baseReg, ofs); @@ -1698,7 +1696,7 @@ VOID StubLinkerCPU::X64EmitMovdqaToMem(X86Reg Xmmreg, X86Reg baseReg, __int32 of //--------------------------------------------------------------- // movsd XmmN, [baseReg + offset] //--------------------------------------------------------------- -VOID StubLinkerCPU::X64EmitMovSDFromMem(X86Reg Xmmreg, X86Reg baseReg, __int32 ofs) +VOID StubLinkerCPU::X64EmitMovSDFromMem(X86Reg Xmmreg, X86Reg baseReg, int32_t ofs) { STANDARD_VM_CONTRACT; X64EmitMovXmmWorker(0xF2, 0x10, Xmmreg, baseReg, ofs); @@ -1707,7 +1705,7 @@ VOID StubLinkerCPU::X64EmitMovSDFromMem(X86Reg Xmmreg, X86Reg baseReg, __int32 o //--------------------------------------------------------------- // movsd [baseReg + offset], XmmN //--------------------------------------------------------------- -VOID StubLinkerCPU::X64EmitMovSDToMem(X86Reg Xmmreg, X86Reg baseReg, __int32 ofs) +VOID StubLinkerCPU::X64EmitMovSDToMem(X86Reg Xmmreg, X86Reg baseReg, int32_t ofs) { STANDARD_VM_CONTRACT; X64EmitMovXmmWorker(0xF2, 0x11, Xmmreg, baseReg, ofs); @@ -1716,7 +1714,7 @@ VOID StubLinkerCPU::X64EmitMovSDToMem(X86Reg Xmmreg, X86Reg baseReg, __int32 ofs //--------------------------------------------------------------- // movss XmmN, [baseReg + offset] //--------------------------------------------------------------- -VOID StubLinkerCPU::X64EmitMovSSFromMem(X86Reg Xmmreg, X86Reg baseReg, __int32 ofs) +VOID StubLinkerCPU::X64EmitMovSSFromMem(X86Reg Xmmreg, X86Reg baseReg, int32_t ofs) { STANDARD_VM_CONTRACT; X64EmitMovXmmWorker(0xF3, 0x10, Xmmreg, baseReg, ofs); @@ -1725,7 +1723,7 @@ VOID StubLinkerCPU::X64EmitMovSSFromMem(X86Reg Xmmreg, X86Reg baseReg, __int32 o //--------------------------------------------------------------- // movss [baseReg + offset], XmmN //--------------------------------------------------------------- -VOID StubLinkerCPU::X64EmitMovSSToMem(X86Reg Xmmreg, X86Reg baseReg, __int32 ofs) +VOID StubLinkerCPU::X64EmitMovSSToMem(X86Reg Xmmreg, X86Reg baseReg, int32_t ofs) { STANDARD_VM_CONTRACT; X64EmitMovXmmWorker(0xF3, 0x11, Xmmreg, baseReg, ofs); @@ -1777,7 +1775,7 @@ VOID StubLinkerCPU::X64EmitMovqWorker(BYTE opcode, X86Reg Xmmreg, X86Reg reg) //--------------------------------------------------------------- // Helper method for emitting of XMM from/to memory moves //--------------------------------------------------------------- -VOID StubLinkerCPU::X64EmitMovXmmWorker(BYTE prefix, BYTE opcode, X86Reg Xmmreg, X86Reg baseReg, __int32 ofs) +VOID StubLinkerCPU::X64EmitMovXmmWorker(BYTE prefix, BYTE opcode, X86Reg Xmmreg, X86Reg baseReg, int32_t ofs) { STANDARD_VM_CONTRACT; @@ -1835,7 +1833,7 @@ VOID StubLinkerCPU::X64EmitMovXmmWorker(BYTE prefix, BYTE opcode, X86Reg Xmmreg, } else { - *((__int32*)(codeBuffer+nBytes)) = ofs; + *((int32_t*)(codeBuffer+nBytes)) = ofs; nBytes += 4; } @@ -1850,7 +1848,7 @@ VOID StubLinkerCPU::X64EmitMovXmmWorker(BYTE prefix, BYTE opcode, X86Reg Xmmreg, //--------------------------------------------------------------- // Emits a MOD/RM for accessing a dword at [ + ofs32] //--------------------------------------------------------------- -VOID StubLinkerCPU::X86EmitOffsetModRM(BYTE opcode, X86Reg opcodereg, X86Reg indexreg, __int32 ofs) +VOID StubLinkerCPU::X86EmitOffsetModRM(BYTE opcode, X86Reg opcodereg, X86Reg indexreg, int32_t ofs) { STANDARD_VM_CONTRACT; @@ -1898,7 +1896,7 @@ VOID StubLinkerCPU::X86EmitOffsetModRM(BYTE opcode, X86Reg opcodereg, X86Reg ind else { code[1] = 0x80|modrm; - *((__int32*)(2+code)) = ofs; + *((int32_t*)(2+code)) = ofs; nBytes += 5; EmitBytes(codeBuffer, nBytes); } @@ -1907,7 +1905,7 @@ VOID StubLinkerCPU::X86EmitOffsetModRM(BYTE opcode, X86Reg opcodereg, X86Reg ind //--------------------------------------------------------------- // Emits a MOD/RM for accessing a dword at [ + * + ofs32] //--------------------------------------------------------------- -VOID StubLinkerCPU::X86EmitOffsetModRmSIB(BYTE opcode, X86Reg opcodeOrReg, X86Reg baseReg, X86Reg indexReg, __int32 scale, __int32 ofs) +VOID StubLinkerCPU::X86EmitOffsetModRmSIB(BYTE opcode, X86Reg opcodeOrReg, X86Reg baseReg, X86Reg indexReg, int32_t scale, int32_t ofs) { CONTRACTL { @@ -1951,7 +1949,7 @@ VOID StubLinkerCPU::X86EmitOffsetModRmSIB(BYTE opcode, X86Reg opcodeOrReg, X86Re { code[1] = static_cast(0x84 | (opcodeOrReg << 3)); code[2] = sib; - *(__int32*)(&code[3]) = ofs; + *(int32_t*)(&code[3]) = ofs; nBytes += 6; EmitBytes(codeBuffer, nBytes); } @@ -2022,7 +2020,7 @@ VOID StubLinkerCPU::X86EmitRegLoad(X86Reg reg, UINT_PTR imm) VOID StubLinkerCPU::X86EmitOp(WORD opcode, X86Reg altreg, X86Reg basereg, - __int32 ofs /*=0*/, + int32_t ofs /*=0*/, X86Reg scaledreg /*=0*/, BYTE scale /*=0*/ AMD64_ARG(X86OperandSize OperandSize /*= k32BitOp*/)) @@ -2149,7 +2147,7 @@ VOID StubLinkerCPU::X86EmitOp(WORD opcode, switch (ofssize) { case 0: break; - case 1: Emit8( (__int8)ofs ); break; + case 1: Emit8( (int8_t)ofs ); break; case 2: Emit32( ofs ); break; default: _ASSERTE(!"Can't get here."); } @@ -2224,7 +2222,7 @@ VOID StubLinkerCPU::X86EmitR2ROp (WORD opcode, //--------------------------------------------------------------- VOID StubLinkerCPU::X86EmitEspOffset(BYTE opcode, X86Reg altreg, - __int32 ofs + int32_t ofs AMD64_ARG(X86OperandSize OperandSize /*= k64BitOp*/) ) { @@ -2277,7 +2275,7 @@ VOID StubLinkerCPU::X86EmitEspOffset(BYTE opcode, { code[1] = 0x80|modrm; code[2] = 0044; - *((__int32*)(3+code)) = ofs; + *((int32_t*)(3+code)) = ofs; EmitBytes(codeBuffer, 7 + nBytes); } @@ -2506,9 +2504,9 @@ void StubLinkerCPU::EmitComMethodStubProlog(TADDR pFrameVptr, STANDARD_VM_CHECK; PRECONDITION(rgRareLabels != NULL); - PRECONDITION(rgRareLabels[0] != NULL && rgRareLabels[1] != NULL && rgRareLabels[2] != NULL); + PRECONDITION(rgRareLabels[0] != NULL && rgRareLabels[1] != NULL); PRECONDITION(rgRejoinLabels != NULL); - PRECONDITION(rgRejoinLabels[0] != NULL && rgRejoinLabels[1] != NULL && rgRejoinLabels[2] != NULL); + PRECONDITION(rgRejoinLabels[0] != NULL && rgRejoinLabels[1] != NULL); } CONTRACTL_END; @@ -2612,9 +2610,11 @@ void StubLinkerCPU::EmitComMethodStubEpilog(TADDR pFrameVptr, STANDARD_VM_CHECK; PRECONDITION(rgRareLabels != NULL); - PRECONDITION(rgRareLabels[0] != NULL && rgRareLabels[1] != NULL && rgRareLabels[2] != NULL); + PRECONDITION(rgRareLabels[0] != NULL && rgRareLabels[1] != NULL); PRECONDITION(rgRejoinLabels != NULL); - PRECONDITION(rgRejoinLabels[0] != NULL && rgRejoinLabels[1] != NULL && rgRejoinLabels[2] != NULL); + PRECONDITION(rgRejoinLabels[0] != NULL && rgRejoinLabels[1] != NULL); + PRECONDITION(4 == sizeof( ((Thread*)0)->m_State )); + PRECONDITION(4 == sizeof( ((Thread*)0)->m_fPreemptiveGCDisabled )); } CONTRACTL_END; @@ -2623,11 +2623,9 @@ void StubLinkerCPU::EmitComMethodStubEpilog(TADDR pFrameVptr, // mov [ebx + Thread.GetFrame()], edi ;; restore previous frame X86EmitIndexRegStore(kEBX, Thread::GetOffsetOfCurrentFrame(), kEDI); - //----------------------------------------------------------------------- - // Generate the inline part of disabling preemptive GC - //----------------------------------------------------------------------- - EmitEnable(rgRareLabels[2]); // rare gc - EmitLabel(rgRejoinLabels[2]); // rejoin for rare gc + // move byte ptr [ebx + Thread.m_fPreemptiveGCDisabled],0 + X86EmitOffsetModRM(0xc6, (X86Reg)0, kEBX, Thread::GetOffsetOfGCFlag()); + Emit8(0); // add esp, popstack X86EmitAddEsp(sizeof(GSCookie) + UnmanagedToManagedFrame::GetOffsetOfCalleeSavedRegisters()); @@ -2651,12 +2649,6 @@ void StubLinkerCPU::EmitComMethodStubEpilog(TADDR pFrameVptr, // keeps on going past the previous "jmp eax". X86EmitReturn(0); - //----------------------------------------------------------------------- - // The out-of-line portion of enabling preemptive GC - rarely executed - //----------------------------------------------------------------------- - EmitLabel(rgRareLabels[2]); // label for rare enable gc - EmitRareEnable(rgRejoinLabels[2]); // emit rare enable gc - //----------------------------------------------------------------------- // The out-of-line portion of disabling preemptive GC - rarely executed //----------------------------------------------------------------------- @@ -2733,9 +2725,11 @@ void StubLinkerCPU::EmitSharedComMethodStubEpilog(TADDR pFrameVptr, STANDARD_VM_CHECK; PRECONDITION(rgRareLabels != NULL); - PRECONDITION(rgRareLabels[0] != NULL && rgRareLabels[1] != NULL && rgRareLabels[2] != NULL); + PRECONDITION(rgRareLabels[0] != NULL && rgRareLabels[1] != NULL); PRECONDITION(rgRejoinLabels != NULL); - PRECONDITION(rgRejoinLabels[0] != NULL && rgRejoinLabels[1] != NULL && rgRejoinLabels[2] != NULL); + PRECONDITION(rgRejoinLabels[0] != NULL && rgRejoinLabels[1] != NULL); + PRECONDITION(4 == sizeof( ((Thread*)0)->m_State )); + PRECONDITION(4 == sizeof( ((Thread*)0)->m_fPreemptiveGCDisabled )); } CONTRACTL_END; @@ -2748,12 +2742,13 @@ void StubLinkerCPU::EmitSharedComMethodStubEpilog(TADDR pFrameVptr, X86EmitIndexRegStore(kEBX, Thread::GetOffsetOfCurrentFrame(), kEDI); //----------------------------------------------------------------------- - // Generate the inline part of enabling preemptive GC + // Generate enabling preemptive GC //----------------------------------------------------------------------- EmitLabel(NoEntryLabel); // need to enable preemp mode even when we fail the disable as rare disable will return in coop mode - EmitEnable(rgRareLabels[2]); // rare enable gc - EmitLabel(rgRejoinLabels[2]); // rejoin for rare enable gc + // move byte ptr [ebx + Thread.m_fPreemptiveGCDisabled],0 + X86EmitOffsetModRM(0xc6, (X86Reg)0, kEBX, Thread::GetOffsetOfGCFlag()); + Emit8(0); #ifdef PROFILING_SUPPORTED // If profiling is active, emit code to notify profiler of transition @@ -2800,12 +2795,6 @@ void StubLinkerCPU::EmitSharedComMethodStubEpilog(TADDR pFrameVptr, // keeps on going past the previous "jmp ecx". X86EmitReturn(0); - //----------------------------------------------------------------------- - // The out-of-line portion of enabling preemptive GC - rarely executed - //----------------------------------------------------------------------- - EmitLabel(rgRareLabels[2]); // label for rare enable gc - EmitRareEnable(rgRejoinLabels[2]); // emit rare enable gc - //----------------------------------------------------------------------- // The out-of-line portion of disabling preemptive GC - rarely executed //----------------------------------------------------------------------- @@ -3335,77 +3324,6 @@ VOID StubLinkerCPU::EmitUnwindInfoCheckSubfunction() #if defined(FEATURE_COMINTEROP) && defined(TARGET_X86) -//----------------------------------------------------------------------- -// Generates the inline portion of the code to enable preemptive GC. Hopefully, -// the inline code is all that will execute most of the time. If this code -// path is entered at certain times, however, it will need to jump out to -// a separate out-of-line path which is more expensive. The "pForwardRef" -// label indicates the start of the out-of-line path. -// -// Assumptions: -// ebx = Thread -// Preserves -// all registers except ecx. -// -//----------------------------------------------------------------------- -VOID StubLinkerCPU::EmitEnable(CodeLabel *pForwardRef) -{ - CONTRACTL - { - STANDARD_VM_CHECK; - - PRECONDITION(4 == sizeof( ((Thread*)0)->m_State )); - PRECONDITION(4 == sizeof( ((Thread*)0)->m_fPreemptiveGCDisabled )); - } - CONTRACTL_END; - - // move byte ptr [ebx + Thread.m_fPreemptiveGCDisabled],0 - X86EmitOffsetModRM(0xc6, (X86Reg)0, kEBX, Thread::GetOffsetOfGCFlag()); - Emit8(0); - - _ASSERTE(FitsInI1(Thread::TS_CatchAtSafePoint)); - - // test byte ptr [ebx + Thread.m_State], TS_CatchAtSafePoint - X86EmitOffsetModRM(0xf6, (X86Reg)0, kEBX, Thread::GetOffsetOfState()); - Emit8(Thread::TS_CatchAtSafePoint); - - // jnz RarePath - X86EmitCondJump(pForwardRef, X86CondCode::kJNZ); - -#ifdef _DEBUG - X86EmitDebugTrashReg(kECX); -#endif - -} - - -//----------------------------------------------------------------------- -// Generates the out-of-line portion of the code to enable preemptive GC. -// After the work is done, the code jumps back to the "pRejoinPoint" -// which should be emitted right after the inline part is generated. -// -// Assumptions: -// ebx = Thread -// Preserves -// all registers except ecx. -// -//----------------------------------------------------------------------- -VOID StubLinkerCPU::EmitRareEnable(CodeLabel *pRejoinPoint) -{ - STANDARD_VM_CONTRACT; - - X86EmitCall(NewExternalCodeLabel((LPVOID) StubRareEnable), 0); -#ifdef _DEBUG - X86EmitDebugTrashReg(kECX); -#endif - if (pRejoinPoint) - { - X86EmitNearJump(pRejoinPoint); - } - -} - - //----------------------------------------------------------------------- // Generates the inline portion of the code to disable preemptive GC. Hopefully, // the inline code is all that will execute most of the time. If this code diff --git a/src/coreclr/vm/i386/stublinkerx86.h b/src/coreclr/vm/i386/stublinkerx86.h index 922babee24a2..35aec1598fd5 100644 --- a/src/coreclr/vm/i386/stublinkerx86.h +++ b/src/coreclr/vm/i386/stublinkerx86.h @@ -186,24 +186,24 @@ class StubLinkerCPU : public StubLinker VOID X64EmitCmp32RegIndexImm32(X86Reg reg, INT32 offs, INT32 imm32); // cmp dword ptr [reg+offs], imm32 VOID X64EmitMovXmmXmm(X86Reg destXmmreg, X86Reg srcXmmReg); - VOID X64EmitMovdqaFromMem(X86Reg Xmmreg, X86Reg baseReg, __int32 ofs = 0); - VOID X64EmitMovdqaToMem(X86Reg Xmmreg, X86Reg baseReg, __int32 ofs = 0); - VOID X64EmitMovSDFromMem(X86Reg Xmmreg, X86Reg baseReg, __int32 ofs = 0); - VOID X64EmitMovSDToMem(X86Reg Xmmreg, X86Reg baseReg, __int32 ofs = 0); - VOID X64EmitMovSSFromMem(X86Reg Xmmreg, X86Reg baseReg, __int32 ofs = 0); - VOID X64EmitMovSSToMem(X86Reg Xmmreg, X86Reg baseReg, __int32 ofs = 0); + VOID X64EmitMovdqaFromMem(X86Reg Xmmreg, X86Reg baseReg, int32_t ofs = 0); + VOID X64EmitMovdqaToMem(X86Reg Xmmreg, X86Reg baseReg, int32_t ofs = 0); + VOID X64EmitMovSDFromMem(X86Reg Xmmreg, X86Reg baseReg, int32_t ofs = 0); + VOID X64EmitMovSDToMem(X86Reg Xmmreg, X86Reg baseReg, int32_t ofs = 0); + VOID X64EmitMovSSFromMem(X86Reg Xmmreg, X86Reg baseReg, int32_t ofs = 0); + VOID X64EmitMovSSToMem(X86Reg Xmmreg, X86Reg baseReg, int32_t ofs = 0); VOID X64EmitMovqRegXmm(X86Reg reg, X86Reg Xmmreg); VOID X64EmitMovqXmmReg(X86Reg Xmmreg, X86Reg reg); - VOID X64EmitMovXmmWorker(BYTE prefix, BYTE opcode, X86Reg Xmmreg, X86Reg baseReg, __int32 ofs = 0); + VOID X64EmitMovXmmWorker(BYTE prefix, BYTE opcode, X86Reg Xmmreg, X86Reg baseReg, int32_t ofs = 0); VOID X64EmitMovqWorker(BYTE opcode, X86Reg Xmmreg, X86Reg reg); #endif VOID X86EmitZeroOutReg(X86Reg reg); VOID X86EmitJumpReg(X86Reg reg); - VOID X86EmitOffsetModRM(BYTE opcode, X86Reg altreg, X86Reg indexreg, __int32 ofs); - VOID X86EmitOffsetModRmSIB(BYTE opcode, X86Reg opcodeOrReg, X86Reg baseReg, X86Reg indexReg, __int32 scale, __int32 ofs); + VOID X86EmitOffsetModRM(BYTE opcode, X86Reg altreg, X86Reg indexreg, int32_t ofs); + VOID X86EmitOffsetModRmSIB(BYTE opcode, X86Reg opcodeOrReg, X86Reg baseReg, X86Reg indexReg, int32_t scale, int32_t ofs); VOID X86EmitTailcallWithESPAdjust(CodeLabel *pTarget, INT32 imm32); VOID X86EmitTailcallWithSinglePop(CodeLabel *pTarget, X86Reg reg); @@ -218,27 +218,27 @@ class StubLinkerCPU : public StubLinker VOID X86EmitCurrentThreadFetch(X86Reg dstreg, unsigned preservedRegSet); - VOID X86EmitIndexRegLoad(X86Reg dstreg, X86Reg srcreg, __int32 ofs = 0); - VOID X86EmitIndexRegStore(X86Reg dstreg, __int32 ofs, X86Reg srcreg); + VOID X86EmitIndexRegLoad(X86Reg dstreg, X86Reg srcreg, int32_t ofs = 0); + VOID X86EmitIndexRegStore(X86Reg dstreg, int32_t ofs, X86Reg srcreg); #if defined(TARGET_AMD64) - VOID X86EmitIndexRegStoreRSP(__int32 ofs, X86Reg srcreg); - VOID X86EmitIndexRegStoreR12(__int32 ofs, X86Reg srcreg); + VOID X86EmitIndexRegStoreRSP(int32_t ofs, X86Reg srcreg); + VOID X86EmitIndexRegStoreR12(int32_t ofs, X86Reg srcreg); #endif // defined(TARGET_AMD64) - VOID X86EmitIndexPush(X86Reg srcreg, __int32 ofs); - VOID X86EmitBaseIndexPush(X86Reg baseReg, X86Reg indexReg, __int32 scale, __int32 ofs); - VOID X86EmitIndexPop(X86Reg srcreg, __int32 ofs); - VOID X86EmitIndexLea(X86Reg dstreg, X86Reg srcreg, __int32 ofs); + VOID X86EmitIndexPush(X86Reg srcreg, int32_t ofs); + VOID X86EmitBaseIndexPush(X86Reg baseReg, X86Reg indexReg, int32_t scale, int32_t ofs); + VOID X86EmitIndexPop(X86Reg srcreg, int32_t ofs); + VOID X86EmitIndexLea(X86Reg dstreg, X86Reg srcreg, int32_t ofs); #if defined(TARGET_AMD64) - VOID X86EmitIndexLeaRSP(X86Reg dstreg, X86Reg srcreg, __int32 ofs); + VOID X86EmitIndexLeaRSP(X86Reg dstreg, X86Reg srcreg, int32_t ofs); #endif // defined(TARGET_AMD64) - VOID X86EmitSPIndexPush(__int32 ofs); + VOID X86EmitSPIndexPush(int32_t ofs); VOID X86EmitSubEsp(INT32 imm32); VOID X86EmitAddEsp(INT32 imm32); VOID X86EmitEspOffset(BYTE opcode, X86Reg altreg, - __int32 ofs + int32_t ofs AMD64_ARG(X86OperandSize OperandSize = k64BitOp) ); VOID X86EmitPushEBPframe(); @@ -266,7 +266,7 @@ class StubLinkerCPU : public StubLinker VOID X86EmitOp(WORD opcode, X86Reg altreg, X86Reg basereg, - __int32 ofs = 0, + int32_t ofs = 0, X86Reg scaledreg = (X86Reg)0, BYTE scale = 0 AMD64_ARG(X86OperandSize OperandSize = k32BitOp) @@ -277,7 +277,7 @@ class StubLinkerCPU : public StubLinker VOID X86EmitOp(WORD opcode, X86Reg altreg, X86Reg basereg, - __int32 ofs, + int32_t ofs, X86OperandSize OperandSize ) { @@ -306,7 +306,7 @@ class StubLinkerCPU : public StubLinker VOID X86EmitRegLoad(X86Reg reg, UINT_PTR imm); - VOID X86EmitRegSave(X86Reg altreg, __int32 ofs) + VOID X86EmitRegSave(X86Reg altreg, int32_t ofs) { LIMITED_METHOD_CONTRACT; X86EmitEspOffset(0x89, altreg, ofs); @@ -323,9 +323,6 @@ class StubLinkerCPU : public StubLinker } #if defined(FEATURE_COMINTEROP) && defined(TARGET_X86) - VOID EmitEnable(CodeLabel *pForwardRef); - VOID EmitRareEnable(CodeLabel *pRejoinPoint); - VOID EmitDisable(CodeLabel *pForwardRef, BOOL fCallIn, X86Reg ThreadReg); VOID EmitRareDisable(CodeLabel *pRejoinPoint); VOID EmitRareDisableHRESULT(CodeLabel *pRejoinPoint, CodeLabel *pExitPoint); diff --git a/src/coreclr/vm/ilstubresolver.cpp b/src/coreclr/vm/ilstubresolver.cpp index 1efb9c2975e1..980d62032a4c 100644 --- a/src/coreclr/vm/ilstubresolver.cpp +++ b/src/coreclr/vm/ilstubresolver.cpp @@ -116,7 +116,7 @@ OBJECTHANDLE ILStubResolver::ConstructStringLiteral(mdToken token) { STANDARD_VM_CONTRACT; _ASSERTE(FALSE); - return NULL; + return (OBJECTHANDLE)NULL; } BOOL ILStubResolver::IsValidStringRef(mdToken metaTok) diff --git a/src/coreclr/vm/ilstubresolver.h b/src/coreclr/vm/ilstubresolver.h index ea823e7f7738..72372b21e0e3 100644 --- a/src/coreclr/vm/ilstubresolver.h +++ b/src/coreclr/vm/ilstubresolver.h @@ -76,7 +76,7 @@ class ILStubResolver : DynamicResolver enum CompileTimeStatePtrSpecialValues { - ILNotYetGenerated = NULL, + ILNotYetGenerated = 0, ILGeneratedAndFreed = 1, }; @@ -106,7 +106,7 @@ class ILStubResolver : DynamicResolver PTR_LoaderHeap m_loaderHeap; }; -typedef Holder, ILStubResolver::StubGenFailed, NULL> ILStubGenHolder; +typedef Holder, ILStubResolver::StubGenFailed, 0> ILStubGenHolder; #endif // __ILSTUBRESOLVER_H__ diff --git a/src/coreclr/vm/interoputil.cpp b/src/coreclr/vm/interoputil.cpp index 7a91cd41f7c1..e5e10b0fecae 100644 --- a/src/coreclr/vm/interoputil.cpp +++ b/src/coreclr/vm/interoputil.cpp @@ -3026,11 +3026,11 @@ FORCEINLINE void DispParamHolderRelease(VARIANT* value) } } -class DispParamHolder : public Wrapper +class DispParamHolder : public Wrapper { public: DispParamHolder(VARIANT* p = NULL) - : Wrapper(p) + : Wrapper(p) { WRAPPER_NO_CONTRACT; } @@ -3038,7 +3038,7 @@ class DispParamHolder : public Wrapper::operator=(p); + Wrapper::operator=(p); } }; diff --git a/src/coreclr/vm/interpreter.cpp b/src/coreclr/vm/interpreter.cpp index 2edb5948d72e..f8d36e5e37e2 100644 --- a/src/coreclr/vm/interpreter.cpp +++ b/src/coreclr/vm/interpreter.cpp @@ -1952,7 +1952,7 @@ static void MonitorEnter(Object* obj, BYTE* pbLockTaken) GCPROTECT_BEGININTERIOR(pbLockTaken); - if (GET_THREAD()->CatchAtSafePointOpportunistic()) + if (GET_THREAD()->CatchAtSafePoint()) { GET_THREAD()->PulseGCMode(); } @@ -7987,14 +7987,14 @@ void Interpreter::EnsureClassInit(MethodTable* pMT) pMT->CheckRestore(); // This is tantamount to a call, so exempt it from the cycle count. #if INTERP_ILCYCLE_PROFILE - unsigned __int64 startCycles; + uint64_t startCycles; bool b = CycleTimer::GetThreadCyclesS(&startCycles); _ASSERTE(b); #endif // INTERP_ILCYCLE_PROFILE pMT->CheckRunClassInitThrowing(); #if INTERP_ILCYCLE_PROFILE - unsigned __int64 endCycles; + uint64_t endCycles; b = CycleTimer::GetThreadCyclesS(&endCycles); _ASSERTE(b); m_exemptCycles += (endCycles - startCycles); #endif // INTERP_ILCYCLE_PROFILE @@ -9117,9 +9117,9 @@ void Interpreter::DoCallWork(bool virtualCall, void* thisArg, CORINFO_RESOLVED_T #if INTERP_ILCYCLE_PROFILE #if 0 // XXX - unsigned __int64 callStartCycles; + uint64_t callStartCycles; bool b = CycleTimer::GetThreadCyclesS(&callStartCycles); _ASSERTE(b); - unsigned __int64 callStartExemptCycles = m_exemptCycles; + uint64_t callStartExemptCycles = m_exemptCycles; #endif #endif // INTERP_ILCYCLE_PROFILE @@ -9191,9 +9191,9 @@ void Interpreter::DoCallWork(bool virtualCall, void* thisArg, CORINFO_RESOLVED_T #if 0 if (virtualCall) { - unsigned __int64 callEndCycles; + uint64_t callEndCycles; b = CycleTimer::GetThreadCyclesS(&callEndCycles); _ASSERTE(b); - unsigned __int64 delta = (callEndCycles - callStartCycles); + uint64_t delta = (callEndCycles - callStartCycles); delta -= (m_exemptCycles - callStartExemptCycles); s_callCycles += delta; s_calls++; @@ -9976,7 +9976,7 @@ void Interpreter::DoCallWork(bool virtualCall, void* thisArg, CORINFO_RESOLVED_T Frame* topFrameBefore = thr->GetFrame(); #if INTERP_ILCYCLE_PROFILE - unsigned __int64 startCycles; + uint64_t startCycles; #endif // INTERP_ILCYCLE_PROFILE // CYCLE PROFILE: BEFORE MDCS CREATION. @@ -10063,7 +10063,7 @@ void Interpreter::DoCallWork(bool virtualCall, void* thisArg, CORINFO_RESOLVED_T } } #if INTERP_ILCYCLE_PROFILE - unsigned __int64 endCycles; + uint64_t endCycles; bool b = CycleTimer::GetThreadCyclesS(&endCycles); _ASSERTE(b); m_exemptCycles += (endCycles - startCycles); #endif // INTERP_ILCYCLE_PROFILE @@ -11481,19 +11481,19 @@ int Interpreter::s_ILInstrExecs[256] = {0, }; int Interpreter::s_ILInstrExecsByCategory[512] = {0, }; int Interpreter::s_ILInstr2ByteExecs[Interpreter::CountIlInstr2Byte] = {0, }; #if INTERP_ILCYCLE_PROFILE -unsigned __int64 Interpreter::s_ILInstrCycles[512] = { 0, }; -unsigned __int64 Interpreter::s_ILInstrCyclesByCategory[512] = { 0, }; +uint64_t Interpreter::s_ILInstrCycles[512] = { 0, }; +uint64_t Interpreter::s_ILInstrCyclesByCategory[512] = { 0, }; // XXX -unsigned __int64 Interpreter::s_callCycles = 0; +uint64_t Interpreter::s_callCycles = 0; unsigned Interpreter::s_calls = 0; void Interpreter::UpdateCycleCount() { - unsigned __int64 endCycles; + uint64_t endCycles; bool b = CycleTimer::GetThreadCyclesS(&endCycles); _ASSERTE(b); if (m_instr != CEE_COUNT) { - unsigned __int64 delta = (endCycles - m_startCycles); + uint64_t delta = (endCycles - m_startCycles); if (m_exemptCycles > 0) { delta = delta - m_exemptCycles; @@ -12215,7 +12215,7 @@ const int MIL = 1000000; // Leaving this disabled for now. #if 0 -unsigned __int64 ForceSigWalkCycles = 0; +uint64_t ForceSigWalkCycles = 0; #endif void Interpreter::PrintPostMortemData() @@ -12381,15 +12381,15 @@ void Interpreter::PrintPostMortemData() // First, classify by categories. unsigned totInstrs = 0; #if INTERP_ILCYCLE_PROFILE - unsigned __int64 totCycles = 0; - unsigned __int64 perMeasurementOverhead = CycleTimer::QueryOverhead(); + uint64_t totCycles = 0; + uint64_t perMeasurementOverhead = CycleTimer::QueryOverhead(); #endif // INTERP_ILCYCLE_PROFILE for (unsigned i = 0; i < 256; i++) { s_ILInstrExecsByCategory[s_ILInstrCategories[i]] += s_ILInstrExecs[i]; totInstrs += s_ILInstrExecs[i]; #if INTERP_ILCYCLE_PROFILE - unsigned __int64 cycles = s_ILInstrCycles[i]; + uint64_t cycles = s_ILInstrCycles[i]; if (cycles > s_ILInstrExecs[i] * perMeasurementOverhead) cycles -= s_ILInstrExecs[i] * perMeasurementOverhead; else cycles = 0; s_ILInstrCycles[i] = cycles; @@ -12399,7 +12399,7 @@ void Interpreter::PrintPostMortemData() } unsigned totInstrs2Byte = 0; #if INTERP_ILCYCLE_PROFILE - unsigned __int64 totCycles2Byte = 0; + uint64_t totCycles2Byte = 0; #endif // INTERP_ILCYCLE_PROFILE for (unsigned i = 0; i < CountIlInstr2Byte; i++) { @@ -12408,7 +12408,7 @@ void Interpreter::PrintPostMortemData() totInstrs += s_ILInstr2ByteExecs[i]; totInstrs2Byte += s_ILInstr2ByteExecs[i]; #if INTERP_ILCYCLE_PROFILE - unsigned __int64 cycles = s_ILInstrCycles[ind]; + uint64_t cycles = s_ILInstrCycles[ind]; if (cycles > s_ILInstrExecs[ind] * perMeasurementOverhead) cycles -= s_ILInstrExecs[ind] * perMeasurementOverhead; else cycles = 0; s_ILInstrCycles[i] = cycles; @@ -12453,7 +12453,7 @@ void Interpreter::PrintPostMortemData() fprintf(GetLogFile(), " MCycles (%lld total, %lld 1-byte, %lld calls (%d calls, %10.2f cyc/call):\n", totCycles/MIL, (totCycles - totCycles2Byte)/MIL, s_callCycles/MIL, s_calls, float(s_callCycles)/float(s_calls)); #if 0 - extern unsigned __int64 MetaSigCtor1Cycles; + extern uint64_t MetaSigCtor1Cycles; fprintf(GetLogFile(), " MetaSig(MethodDesc, TypeHandle) ctor: %lld MCycles.\n", MetaSigCtor1Cycles/MIL); fprintf(GetLogFile(), " ForceSigWalk: %lld MCycles.\n", @@ -12527,7 +12527,7 @@ const int K = 1000; // static void Interpreter::PrintILProfile(Interpreter::InstrExecRecord *recs, unsigned int totInstrs #if INTERP_ILCYCLE_PROFILE - , unsigned __int64 totCycles + , uint64_t totCycles #endif // INTERP_ILCYCLE_PROFILE ) { diff --git a/src/coreclr/vm/interpreter.h b/src/coreclr/vm/interpreter.h index 7f7eed175dea..1169905dea23 100644 --- a/src/coreclr/vm/interpreter.h +++ b/src/coreclr/vm/interpreter.h @@ -1402,8 +1402,8 @@ class Interpreter #if INTERP_ILCYCLE_PROFILE // Cycles we want to delete from the current instructions cycle count; e.g., // cycles spent in a callee. - unsigned __int64 m_exemptCycles; - unsigned __int64 m_startCycles; + uint64_t m_exemptCycles; + uint64_t m_startCycles; unsigned short m_instr; void UpdateCycleCount(); @@ -1533,16 +1533,16 @@ class Interpreter static int s_ILInstrExecs[256]; static int s_ILInstrExecsByCategory[512]; #if INTERP_ILCYCLE_PROFILE - static unsigned __int64 s_ILInstrCyclesByCategory[512]; + static uint64_t s_ILInstrCyclesByCategory[512]; #endif // INTERP_ILCYCLE_PROFILE static const unsigned CountIlInstr2Byte = 0x22; static int s_ILInstr2ByteExecs[CountIlInstr2Byte]; #if INTERP_ILCYCLE_PROFILE - static unsigned __int64 s_ILInstrCycles[512]; + static uint64_t s_ILInstrCycles[512]; // XXX - static unsigned __int64 s_callCycles; + static uint64_t s_callCycles; static unsigned s_calls; #endif // INTERP_ILCYCLE_PROFILE #endif // INTERP_ILINSTR_PROFILE @@ -1935,7 +1935,7 @@ class Interpreter bool m_is2byte; unsigned m_execs; #if INTERP_ILCYCLE_PROFILE - unsigned __int64 m_cycles; + uint64_t m_cycles; #endif // INTERP_ILCYCLE_PROFILE static int _cdecl Compare(const void* v0, const void* v1) @@ -1956,7 +1956,7 @@ class Interpreter // Prints the given array "recs", assumed to already be sorted. static void PrintILProfile(InstrExecRecord* recs, unsigned totInstrs #if INTERP_ILCYCLE_PROFILE - , unsigned __int64 totCycles + , uint64_t totCycles #endif // INTERP_ILCYCLE_PROFILE ); #endif // INTERP_ILINSTR_PROFILE diff --git a/src/coreclr/vm/interpreter.hpp b/src/coreclr/vm/interpreter.hpp index 1c18fdd81294..819df89ef245 100644 --- a/src/coreclr/vm/interpreter.hpp +++ b/src/coreclr/vm/interpreter.hpp @@ -397,7 +397,7 @@ void Interpreter::ResolveToken(CORINFO_RESOLVED_TOKEN* resTok, mdToken token, Co resTok->token = token; resTok->tokenType = tokenType; #if INTERP_ILCYCLE_PROFILE - unsigned __int64 startCycles; + uint64_t startCycles; bool b = CycleTimer::GetThreadCyclesS(&startCycles); assert(b); #endif // INTERP_ILCYCLE_PROFILE m_interpCeeInfo.resolveToken(resTok); @@ -422,7 +422,7 @@ void Interpreter::ResolveToken(CORINFO_RESOLVED_TOKEN* resTok, mdToken token, Co } #endif #if INTERP_ILCYCLE_PROFILE - unsigned __int64 endCycles; + uint64_t endCycles; b = CycleTimer::GetThreadCyclesS(&endCycles); assert(b); m_exemptCycles += (endCycles - startCycles); #endif // INTERP_ILCYCLE_PROFILE diff --git a/src/coreclr/vm/invokeutil.cpp b/src/coreclr/vm/invokeutil.cpp index 7d0c8f80becd..cfec2c5259a5 100644 --- a/src/coreclr/vm/invokeutil.cpp +++ b/src/coreclr/vm/invokeutil.cpp @@ -692,7 +692,7 @@ OBJECTREF InvokeUtil::CreateTargetExcept(OBJECTREF* except) { } else { - args[1] = NULL; + args[1] = 0; } ctor.Call(args); diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 3aae4a155fc7..13fbeaab2332 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -55,8 +55,8 @@ #ifndef FEATURE_EH_FUNCLETS #include "excep.h" #endif - #include "exinfo.h" +#include "arraynative.inl" using std::isfinite; using std::isnan; @@ -109,20 +109,6 @@ using std::isnan; // #define Is32BitSigned(a) (Hi32Bits(a) == Hi32Bits((INT64)(INT32)(a))) -// -// helper function to shift the result by 32-bits -// -inline UINT64 ShiftToHi32Bits(UINT32 x) -{ - // The shift compiles into slow multiplication by 2^32! VSWhidbey 360736 - // return ((UINT64)x) << 32; - - ULARGE_INTEGER ret; - ret.u.HighPart = x; - ret.u.LowPart = 0; - return ret.QuadPart; -} - #if !defined(TARGET_X86) || defined(TARGET_UNIX) /*********************************************************************/ HCIMPL2_VV(INT64, JIT_LMul, INT64 val1, INT64 val2) @@ -140,117 +126,6 @@ HCIMPL2_VV(INT64, JIT_LMul, INT64 val1, INT64 val2) HCIMPLEND #endif // !TARGET_X86 || TARGET_UNIX -/*********************************************************************/ -HCIMPL2_VV(INT64, JIT_LMulOvf, INT64 val1, INT64 val2) -{ - FCALL_CONTRACT; - - // This short-cut does not actually help since the multiplication - // of two 32-bit signed ints compiles into the call to a slow helper - // if (Is32BitSigned(val1) && Is32BitSigned(val2)) - // return (INT64)(INT32)val1 * (INT64)(INT32)val2; - - INDEBUG(INT64 expected = val1 * val2;) - INT64 ret; - - // Remember the sign of the result - INT32 sign = Hi32Bits(val1) ^ Hi32Bits(val2); - - // Convert to unsigned multiplication - if (val1 < 0) val1 = -val1; - if (val2 < 0) val2 = -val2; - - // Get the upper 32 bits of the numbers - UINT32 val1High = Hi32Bits(val1); - UINT32 val2High = Hi32Bits(val2); - - UINT64 valMid; - - if (val1High == 0) { - // Compute the 'middle' bits of the long multiplication - valMid = Mul32x32To64(val2High, val1); - } - else { - if (val2High != 0) - goto ThrowExcep; - // Compute the 'middle' bits of the long multiplication - valMid = Mul32x32To64(val1High, val2); - } - - // See if any bits after bit 32 are set - if (Hi32Bits(valMid) != 0) - goto ThrowExcep; - - ret = Mul32x32To64(val1, val2) + ShiftToHi32Bits((UINT32)(valMid)); - - // check for overflow - if (Hi32Bits(ret) < (UINT32)valMid) - goto ThrowExcep; - - if (sign >= 0) { - // have we spilled into the sign bit? - if (ret < 0) - goto ThrowExcep; - } - else { - ret = -ret; - // have we spilled into the sign bit? - if (ret > 0) - goto ThrowExcep; - } - _ASSERTE(ret == expected); - return ret; - -ThrowExcep: - FCThrow(kOverflowException); -} -HCIMPLEND - -/*********************************************************************/ -HCIMPL2_VV(UINT64, JIT_ULMulOvf, UINT64 val1, UINT64 val2) -{ - FCALL_CONTRACT; - - INDEBUG(UINT64 expected = val1 * val2;) - UINT64 ret; - - // Get the upper 32 bits of the numbers - UINT32 val1High = Hi32Bits(val1); - UINT32 val2High = Hi32Bits(val2); - - UINT64 valMid; - - if (val1High == 0) { - if (val2High == 0) - return Mul32x32To64(val1, val2); - // Compute the 'middle' bits of the long multiplication - valMid = Mul32x32To64(val2High, val1); - } - else { - if (val2High != 0) - goto ThrowExcep; - // Compute the 'middle' bits of the long multiplication - valMid = Mul32x32To64(val1High, val2); - } - - // See if any bits after bit 32 are set - if (Hi32Bits(valMid) != 0) - goto ThrowExcep; - - ret = Mul32x32To64(val1, val2) + ShiftToHi32Bits((UINT32)(valMid)); - - // check for overflow - if (Hi32Bits(ret) < (UINT32)valMid) - goto ThrowExcep; - - _ASSERTE(ret == expected); - return ret; - -ThrowExcep: - FCThrow(kOverflowException); - } -HCIMPLEND - /*********************************************************************/ HCIMPL2(INT32, JIT_Div, INT32 dividend, INT32 divisor) { @@ -522,62 +397,6 @@ HCIMPL1_V(int64_t, JIT_Dbl2Lng, double val) HCIMPLEND /*********************************************************************/ -HCIMPL1_V(uint32_t, JIT_Dbl2UIntOvf, double val) -{ - FCALL_CONTRACT; - - // Note that this expression also works properly for val = NaN case - if (val > -1.0 && val < 4294967296.0) - return (uint32_t)val; - - FCThrow(kOverflowException); -} -HCIMPLEND - -/*********************************************************************/ -HCIMPL1_V(int, JIT_Dbl2IntOvf, double val) -{ - FCALL_CONTRACT; - - const double two31 = 2147483648.0; - // Note that this expression also works properly for val = NaN case - if (val > -two31 - 1 && val < two31) - return (int32_t)val; - - FCThrow(kOverflowException); -} -HCIMPLEND - -/*********************************************************************/ -HCIMPL1_V(int64_t, JIT_Dbl2LngOvf, double val) -{ - FCALL_CONTRACT; - - const double two63 = 2147483648.0 * 4294967296.0; - - // Note that this expression also works properly for val = NaN case - // We need to compare with the very next double to two63. 0x402 is epsilon to get us there. - if (val > -two63 - 0x402 && val < two63) - return (int64_t)val; - - FCThrow(kOverflowException); -} -HCIMPLEND - -/*********************************************************************/ -HCIMPL1_V(uint64_t, JIT_Dbl2ULngOvf, double val) -{ - FCALL_CONTRACT; - - const double two64 = 4294967296.0 * 4294967296.0; - // Note that this expression also works properly for val = NaN case - if (val > -1.0 && val < two64) - return (uint64_t)val; - - FCThrow(kOverflowException); -} -HCIMPLEND - HCIMPL1_V(uint32_t, JIT_Dbl2UInt, double val) { FCALL_CONTRACT; @@ -2935,7 +2754,7 @@ HCIMPL2(LPVOID, Unbox_Helper, CORINFO_CLASS_HANDLE type, Object* obj) if (pMT1->GetInternalCorElementType() == pMT2->GetInternalCorElementType() && (pMT1->IsEnum() || pMT1->IsTruePrimitive()) && (pMT2->IsEnum() || pMT2->IsTruePrimitive()) && - g_TrapReturningThreads.LoadWithoutBarrier() == 0) + g_TrapReturningThreads == 0) { return obj->GetData(); } @@ -3518,7 +3337,7 @@ NOINLINE HCIMPL1(Object*, JIT_GetRuntimeType_Framed, CORINFO_CLASS_HANDLE type) TypeHandle typeHandle(type); // Array/other type handle case. - OBJECTREF refType = typeHandle.GetManagedClassObjectFast(); + OBJECTREF refType = typeHandle.GetManagedClassObjectIfExists(); if (refType == NULL) { HELPER_METHOD_FRAME_BEGIN_RET_1(refType); @@ -3651,7 +3470,7 @@ NOINLINE static void JIT_MonEnter_Helper(Object* obj, BYTE* pbLockTaken, LPVOID GCPROTECT_BEGININTERIOR(pbLockTaken); - if (GET_THREAD()->CatchAtSafePointOpportunistic()) + if (GET_THREAD()->CatchAtSafePoint()) { GET_THREAD()->PulseGCMode(); } @@ -3730,7 +3549,7 @@ NOINLINE static void JIT_MonTryEnter_Helper(Object* obj, INT32 timeOut, BYTE* pb GCPROTECT_BEGININTERIOR(pbLockTaken); - if (GET_THREAD()->CatchAtSafePointOpportunistic()) + if (GET_THREAD()->CatchAtSafePoint()) { GET_THREAD()->PulseGCMode(); } @@ -3764,7 +3583,7 @@ HCIMPL3(void, JIT_MonTryEnter_Portable, Object* obj, INT32 timeOut, BYTE* pbLock pCurThread = GetThread(); - if (pCurThread->CatchAtSafePointOpportunistic()) + if (pCurThread->CatchAtSafePoint()) { goto FramedLockHelper; } @@ -3936,7 +3755,7 @@ HCIMPL_MONHELPER(JIT_MonEnterStatic_Portable, AwareLock *lock) MONHELPER_STATE(_ASSERTE(pbLockTaken != NULL && *pbLockTaken == 0)); Thread *pCurThread = GetThread(); - if (pCurThread->CatchAtSafePointOpportunistic()) + if (pCurThread->CatchAtSafePoint()) { goto FramedLockHelper; } @@ -4779,21 +4598,6 @@ HCIMPLEND // //======================================================================== -/*************************************************************/ -HCIMPL3(VOID, JIT_StructWriteBarrier, void *dest, void* src, CORINFO_CLASS_HANDLE typeHnd_) -{ - FCALL_CONTRACT; - - TypeHandle typeHnd(typeHnd_); - MethodTable *pMT = typeHnd.AsMethodTable(); - - HELPER_METHOD_FRAME_BEGIN_NOPOLL(); // Set up a frame - CopyValueClass(dest, src, pMT); - HELPER_METHOD_FRAME_END_POLL(); - -} -HCIMPLEND - /*************************************************************/ // Slow helper to tailcall from the fast one NOINLINE HCIMPL0(void, JIT_PollGC_Framed) @@ -4826,11 +4630,11 @@ HCIMPL0(VOID, JIT_PollGC) FCALL_CONTRACT; // As long as we can have GCPOLL_CALL polls, it would not hurt to check the trap flag. - if (!g_TrapReturningThreads.LoadWithoutBarrier()) + if (!g_TrapReturningThreads) return; // Does someone want this thread stopped? - if (!GetThread()->CatchAtSafePointOpportunistic()) + if (!GetThread()->CatchAtSafePoint()) return; // Tailcall to the slow helper @@ -5038,7 +4842,7 @@ HCIMPLEND static PCODE JitPatchpointWorker(MethodDesc* pMD, EECodeInfo& codeInfo, int ilOffset) { STANDARD_VM_CONTRACT; - PCODE osrVariant = NULL; + PCODE osrVariant = (PCODE)NULL; // Fetch the patchpoint info for the current method EEJitManager* jitMgr = ExecutionManager::GetEEJitManager(); @@ -5050,7 +4854,7 @@ static PCODE JitPatchpointWorker(MethodDesc* pMD, EECodeInfo& codeInfo, int ilOf { // Unexpected, but not fatal STRESS_LOG1(LF_TIEREDCOMPILATION, LL_WARNING, "JitPatchpointWorker: failed to restore patchpoint info for Method=0x%pM\n", pMD); - return NULL; + return (PCODE)NULL; } // Set up a new native code version for the OSR variant of this method. @@ -5065,7 +4869,7 @@ static PCODE JitPatchpointWorker(MethodDesc* pMD, EECodeInfo& codeInfo, int ilOf { // Unexpected, but not fatal STRESS_LOG1(LF_TIEREDCOMPILATION, LL_WARNING, "JitPatchpointWorker: failed to add native code version for Method=0x%pM\n", pMD); - return NULL; + return (PCODE)NULL; } } @@ -5083,7 +4887,7 @@ static PCODE JitPatchpointWorker(MethodDesc* pMD, EECodeInfo& codeInfo, int ilOf // Helper method wrapper to set up a frame so we can invoke methods that might GC HCIMPL3(PCODE, JIT_Patchpoint_Framed, MethodDesc* pMD, EECodeInfo& codeInfo, int ilOffset) { - PCODE result = NULL; + PCODE result = (PCODE)NULL; HELPER_METHOD_FRAME_BEGIN_RET_0(); @@ -5125,7 +4929,7 @@ void JIT_Patchpoint(int* counter, int ilOffset) LoaderAllocator* allocator = pMD->GetLoaderAllocator(); OnStackReplacementManager* manager = allocator->GetOnStackReplacementManager(); PerPatchpointInfo * ppInfo = manager->GetPerPatchpointInfo(ip); - PCODE osrMethodCode = NULL; + PCODE osrMethodCode = (PCODE)NULL; bool isNewMethod = false; // In the current prototype, counter is shared by all patchpoints @@ -5144,7 +4948,7 @@ void JIT_Patchpoint(int* counter, int ilOffset) const int counterBump = g_pConfig->OSR_CounterBump(); *counter = counterBump; -#if _DEBUG +#ifdef _DEBUG const int ppId = ppInfo->m_patchpointId; #endif @@ -5160,7 +4964,7 @@ void JIT_Patchpoint(int* counter, int ilOffset) // See if we have an OSR method for this patchpoint. osrMethodCode = ppInfo->m_osrMethodCode; - if (osrMethodCode == NULL) + if (osrMethodCode == (PCODE)NULL) { // No OSR method yet, let's see if we should create one. // @@ -5262,7 +5066,7 @@ void JIT_Patchpoint(int* counter, int ilOffset) osrMethodCode = HCCALL3(JIT_Patchpoint_Framed, pMD, codeInfo, ilOffset); // If that failed, mark the patchpoint as invalid. - if (osrMethodCode == NULL) + if (osrMethodCode == (PCODE)NULL) { // Unexpected, but not fatal STRESS_LOG3(LF_TIEREDCOMPILATION, LL_WARNING, "Jit_Patchpoint: patchpoint (0x%p) OSR method creation failed," @@ -5297,7 +5101,7 @@ void JIT_Patchpoint(int* counter, int ilOffset) DWORD contextSize = 0; ULONG64 xStateCompactionMask = 0; DWORD contextFlags = CONTEXT_FULL; - if (Thread::AreCetShadowStacksEnabled()) + if (Thread::AreShadowStacksEnabled()) { xStateCompactionMask = XSTATE_MASK_CET_U; contextFlags |= CONTEXT_XSTATE; @@ -5325,7 +5129,7 @@ void JIT_Patchpoint(int* counter, int ilOffset) RtlCaptureContext(pFrameContext); #if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) - if (Thread::AreCetShadowStacksEnabled()) + if (Thread::AreShadowStacksEnabled()) { pFrameContext->ContextFlags |= CONTEXT_XSTATE; SetXStateFeaturesMask(pFrameContext, xStateCompactionMask); @@ -5389,6 +5193,12 @@ void JIT_Patchpoint(int* counter, int ilOffset) // Install new entry point as IP SetIP(pFrameContext, osrMethodCode); +#ifdef _DEBUG + // Keep this context around to aid in debugging OSR transition problems + static CONTEXT s_lastOSRTransitionContext; + s_lastOSRTransitionContext = *pFrameContext; +#endif + // Restore last error (since call below does not return) // END_PRESERVE_LAST_ERROR; ::SetLastError(dwLastError); @@ -5425,7 +5235,7 @@ HCIMPL1(VOID, JIT_PartialCompilationPatchpoint, int ilOffset) // Patchpoint identity is the helper return address PCODE ip = (PCODE)_ReturnAddress(); -#if _DEBUG +#ifdef _DEBUG // Friendly ID number int ppId = 0; #endif @@ -5439,7 +5249,7 @@ HCIMPL1(VOID, JIT_PartialCompilationPatchpoint, int ilOffset) OnStackReplacementManager* manager = allocator->GetOnStackReplacementManager(); ppInfo = manager->GetPerPatchpointInfo(ip); -#if _DEBUG +#ifdef _DEBUG ppId = ppInfo->m_patchpointId; #endif @@ -5450,7 +5260,7 @@ HCIMPL1(VOID, JIT_PartialCompilationPatchpoint, int ilOffset) { GCX_PREEMP(); - while (ppInfo->m_osrMethodCode == NULL) + while (ppInfo->m_osrMethodCode == (PCODE)NULL) { // Invalid patchpoints are fatal, for partial compilation patchpoints // @@ -5496,7 +5306,7 @@ HCIMPL1(VOID, JIT_PartialCompilationPatchpoint, int ilOffset) // If that failed, mark the patchpoint as invalid. // This is fatal, for partial compilation patchpoints // - if (newMethodCode == NULL) + if (newMethodCode == (PCODE)NULL) { STRESS_LOG3(LF_TIEREDCOMPILATION, LL_WARNING, "Jit_PartialCompilationPatchpoint: patchpoint (0x%p) OSR method creation failed," " marking patchpoint invalid for Method=0x%pM il offset %d\n", ip, pMD, ilOffset); @@ -5805,7 +5615,7 @@ HCIMPL2(void, JIT_DelegateProfile32, Object *obj, ICorJitInfo::HandleHistogram32 // MethodDesc* pRecordedMD = (MethodDesc*)DEFAULT_UNKNOWN_HANDLE; DELEGATEREF del = (DELEGATEREF)objRef; - if ((del->GetInvocationCount() == 0) && (del->GetMethodPtrAux() == NULL)) + if ((del->GetInvocationCount() == 0) && (del->GetMethodPtrAux() == (PCODE)NULL)) { MethodDesc* pMD = NonVirtualEntry2MethodDesc(del->GetMethodPtr()); if ((pMD != nullptr) && !pMD->GetLoaderAllocator()->IsCollectible() && !pMD->IsDynamicMethod()) @@ -5852,7 +5662,7 @@ HCIMPL2(void, JIT_DelegateProfile64, Object *obj, ICorJitInfo::HandleHistogram64 // MethodDesc* pRecordedMD = (MethodDesc*)DEFAULT_UNKNOWN_HANDLE; DELEGATEREF del = (DELEGATEREF)objRef; - if ((del->GetInvocationCount() == 0) && (del->GetMethodPtrAux() == NULL)) + if ((del->GetInvocationCount() == 0) && (del->GetMethodPtrAux() == (PCODE)NULL)) { MethodDesc* pMD = NonVirtualEntry2MethodDesc(del->GetMethodPtr()); if ((pMD != nullptr) && !pMD->GetLoaderAllocator()->IsCollectible() && !pMD->IsDynamicMethod()) @@ -6049,7 +5859,7 @@ HCIMPLEND /* Fills out portions of an InlinedCallFrame for JIT64 */ /* The idea here is to allocate and initialize the frame to only once, */ /* regardless of how many PInvokes there are in the method */ -Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame, PTR_VOID StubSecretArg) +Thread * JIT_InitPInvokeFrame(InlinedCallFrame *pFrame) { CONTRACTL { @@ -6063,7 +5873,6 @@ Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame, PTR_VOID StubS _ASSERTE(pFrame != pThread->GetFrame()); pFrame->Init(); - pFrame->m_StubSecretArg = StubSecretArg; pFrame->m_Next = pThread->GetFrame(); return pThread; @@ -6165,7 +5974,7 @@ HCIMPL3_RAW(void, JIT_ReversePInvokeEnterTrackTransitions, ReversePInvokeFrame* // Manually inline the fast path in Thread::DisablePreemptiveGC(). thread->m_fPreemptiveGCDisabled.StoreWithoutBarrier(1); - if (g_TrapReturningThreads.LoadWithoutBarrier() != 0) + if (g_TrapReturningThreads != 0) { // If we're in an IL stub, we want to trace the address of the target method, // not the next instruction in the stub. @@ -6202,7 +6011,7 @@ HCIMPL1_RAW(void, JIT_ReversePInvokeEnter, ReversePInvokeFrame* frame) // Manually inline the fast path in Thread::DisablePreemptiveGC(). thread->m_fPreemptiveGCDisabled.StoreWithoutBarrier(1); - if (g_TrapReturningThreads.LoadWithoutBarrier() != 0) + if (g_TrapReturningThreads != 0) { JIT_ReversePInvokeEnterRare2(frame, _ReturnAddress()); } diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 0889e131f037..442bdd01627a 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -823,7 +823,7 @@ CHECK CheckContext(CORINFO_MODULE_HANDLE scopeHnd, CORINFO_CONTEXT_HANDLE contex if (context != METHOD_BEING_COMPILED_CONTEXT()) { CHECK_MSG(scopeHnd != NULL, "Illegal null scope"); - CHECK_MSG(((size_t)context & ~CORINFO_CONTEXTFLAGS_MASK) != NULL, "Illegal null context"); + CHECK_MSG(((size_t)context & ~CORINFO_CONTEXTFLAGS_MASK) != 0, "Illegal null context"); if (((size_t)context & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_CLASS) { TypeHandle handle((CORINFO_CLASS_HANDLE)((size_t)context & ~CORINFO_CONTEXTFLAGS_MASK)); @@ -869,9 +869,9 @@ void CEEInfo::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken _ASSERTE(CheckContext(pResolvedToken->tokenScope, pResolvedToken->tokenContext)); pResolvedToken->pTypeSpec = NULL; - pResolvedToken->cbTypeSpec = NULL; + pResolvedToken->cbTypeSpec = 0; pResolvedToken->pMethodSpec = NULL; - pResolvedToken->cbMethodSpec = NULL; + pResolvedToken->cbMethodSpec = 0; TypeHandle th; MethodDesc * pMD = NULL; @@ -4658,6 +4658,31 @@ bool CEEInfo::isExactType(CORINFO_CLASS_HANDLE cls) return result; } +// Returns whether a class handle represents a Nullable type, if that can be statically determined. +TypeCompareState CEEInfo::isNullableType(CORINFO_CLASS_HANDLE cls) +{ + CONTRACTL { + THROWS; + GC_TRIGGERS; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + TypeHandle typeHandle = TypeHandle(); + + TypeCompareState result = TypeCompareState::May; + + JIT_TO_EE_TRANSITION(); + + if (typeHandle != TypeHandle(g_pCanonMethodTableClass)) + { + TypeHandle VMClsHnd(cls); + result = Nullable::IsNullableType(VMClsHnd) ? TypeCompareState::Must : TypeCompareState::MustNot; + } + + EE_TO_JIT_TRANSITION(); + return result; +} + /*********************************************************************/ // Returns TypeCompareState::Must if cls is known to be an enum. // For enums with known exact type returns the underlying @@ -5405,12 +5430,8 @@ void CEEInfo::getCallInfo( // (c) constraint calls that require runtime context lookup are never resolved // to underlying shared generic code - bool unresolvedLdVirtFtn = (flags & CORINFO_CALLINFO_LDFTN) && (flags & CORINFO_CALLINFO_CALLVIRT) && !resolvedCallVirt; - if (((pResult->exactContextNeedsRuntimeLookup && pTargetMD->IsInstantiatingStub() && (!allowInstParam || fResolvedConstraint)) || fForceUseRuntimeLookup)) { - _ASSERTE(!m_pMethodBeingCompiled->IsDynamicMethod()); - pResult->kind = CORINFO_CALL_CODE_POINTER; DictionaryEntryKind entryKind; @@ -5477,8 +5498,6 @@ void CEEInfo::getCallInfo( if (pResult->exactContextNeedsRuntimeLookup) { - _ASSERTE(!m_pMethodBeingCompiled->IsDynamicMethod()); - ComputeRuntimeLookupForSharedGenericToken(fIsStaticVirtualMethod ? ConstrainedMethodEntrySlot : DispatchStubAddrSlot, pResolvedToken, pConstrainedResolvedToken, @@ -9486,7 +9505,7 @@ CORINFO_ARG_LIST_HANDLE CEEInfo::getArgNext(CORINFO_ARG_LIST_HANDLE args) JIT_TO_EE_TRANSITION(); - SigPointer ptr((unsigned __int8*) args); + SigPointer ptr((uint8_t*) args); IfFailThrow(ptr.SkipExactlyOne()); result = (CORINFO_ARG_LIST_HANDLE) ptr.GetPtr(); @@ -9519,7 +9538,7 @@ CorInfoTypeWithMod CEEInfo::getArgType ( _ASSERTE((BYTE*) sig->args <= (BYTE*) args); INDEBUG(*vcTypeRet = CORINFO_CLASS_HANDLE((size_t)INVALID_POINTER_CC)); - SigPointer ptr((unsigned __int8*) args); + SigPointer ptr((uint8_t*) args); CorElementType eType; IfFailThrow(ptr.PeekElemType(&eType)); while (eType == ELEMENT_TYPE_PINNED) @@ -9613,7 +9632,7 @@ uint32_t CEEInfo::getLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE c uint32_t size = STRUCT_NO_FLOAT_FIELD; #if defined(TARGET_LOONGARCH64) - size = (uint32_t)MethodTable::GetLoongArch64PassStructInRegisterFlags(cls); + size = (uint32_t)MethodTable::GetLoongArch64PassStructInRegisterFlags(TypeHandle(cls)); #endif EE_TO_JIT_TRANSITION_LEAF(); @@ -9634,7 +9653,7 @@ uint32_t CEEInfo::getRISCV64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE cls) uint32_t size = STRUCT_NO_FLOAT_FIELD; #if defined(TARGET_RISCV64) - size = (uint32_t)MethodTable::GetRiscV64PassStructInRegisterFlags(cls); + size = (uint32_t)MethodTable::GetRiscV64PassStructInRegisterFlags(TypeHandle(cls)); #endif // TARGET_RISCV64 EE_TO_JIT_TRANSITION_LEAF(); @@ -9689,7 +9708,7 @@ CORINFO_CLASS_HANDLE CEEInfo::getArgClass ( Module* pModule = GetModule(sig->scope); - SigPointer ptr((unsigned __int8*) args); + SigPointer ptr((uint8_t*) args); CorElementType eType; IfFailThrow(ptr.PeekElemType(&eType)); @@ -10059,6 +10078,7 @@ void InlinedCallFrame::GetEEInfo(CORINFO_EE_INFO::InlinedCallFrameInfo *pInfo) LIMITED_METHOD_CONTRACT; pInfo->size = sizeof(GSCookie) + sizeof(InlinedCallFrame); + pInfo->sizeWithSecretStubArg = sizeof(GSCookie) + sizeof(InlinedCallFrame) + sizeof(PTR_VOID); pInfo->offsetOfGSCookie = 0; pInfo->offsetOfFrameVptr = sizeof(GSCookie); @@ -10067,6 +10087,7 @@ void InlinedCallFrame::GetEEInfo(CORINFO_EE_INFO::InlinedCallFrameInfo *pInfo) pInfo->offsetOfCalleeSavedFP = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pCalleeSavedFP); pInfo->offsetOfCallTarget = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_Datum); pInfo->offsetOfReturnAddress = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pCallerReturnAddress); + pInfo->offsetOfSecretStubArg = sizeof(GSCookie) + sizeof(InlinedCallFrame); #ifdef TARGET_ARM pInfo->offsetOfSPAfterProlog = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pSPAfterProlog); #endif // TARGET_ARM @@ -10705,7 +10726,14 @@ void* CEEJitInfo::getHelperFtn(CorInfoHelpFunc ftnNum, /* IN */ dynamicFtnNum == DYNAMIC_CORINFO_HELP_LDELEMA_REF || dynamicFtnNum == DYNAMIC_CORINFO_HELP_MEMSET || dynamicFtnNum == DYNAMIC_CORINFO_HELP_MEMZERO || - dynamicFtnNum == DYNAMIC_CORINFO_HELP_MEMCPY) + dynamicFtnNum == DYNAMIC_CORINFO_HELP_MEMCPY || + dynamicFtnNum == DYNAMIC_CORINFO_HELP_BULK_WRITEBARRIER || + IN_TARGET_32BIT(dynamicFtnNum == DYNAMIC_CORINFO_HELP_LMUL_OVF ||) + IN_TARGET_32BIT(dynamicFtnNum == DYNAMIC_CORINFO_HELP_ULMUL_OVF ||) + dynamicFtnNum == DYNAMIC_CORINFO_HELP_DBL2INT_OVF || + dynamicFtnNum == DYNAMIC_CORINFO_HELP_DBL2LNG_OVF || + dynamicFtnNum == DYNAMIC_CORINFO_HELP_DBL2UINT_OVF || + dynamicFtnNum == DYNAMIC_CORINFO_HELP_DBL2ULNG_OVF) { Precode* pPrecode = Precode::GetPrecodeFromEntryPoint((PCODE)hlpDynamicFuncTable[dynamicFtnNum].pfnHelper); _ASSERTE(pPrecode->GetType() == PRECODE_FIXUP); @@ -12056,23 +12084,6 @@ HRESULT CEEJitInfo::allocPgoInstrumentationBySchema( JIT_TO_EE_TRANSITION(); - // We need to know the code size. Typically we can get the code size - // from m_ILHeader. For dynamic methods, m_ILHeader will be NULL, so - // for that case we need to use DynamicResolver to get the code size. - - unsigned codeSize = 0; - if (m_pMethodBeingCompiled->IsDynamicMethod()) - { - unsigned stackSize, ehSize; - CorInfoOptions options; - DynamicResolver * pResolver = m_pMethodBeingCompiled->AsDynamicMethodDesc()->GetResolver(); - pResolver->GetCodeInfo(&codeSize, &stackSize, &options, &ehSize); - } - else - { - codeSize = m_ILHeader->GetCodeSize(); - } - #ifdef FEATURE_PGO hr = PgoManager::allocPgoInstrumentationBySchema(m_pMethodBeingCompiled, pSchema, countSchemaItems, pInstrumentationData); #else @@ -12092,7 +12103,8 @@ HRESULT CEEJitInfo::getPgoInstrumentationResults( PgoInstrumentationSchema **pSchema, // pointer to the schema table which describes the instrumentation results (pointer will not remain valid after jit completes) uint32_t * pCountSchemaItems, // pointer to the count schema items uint8_t ** pInstrumentationData, // pointer to the actual instrumentation data (pointer will not remain valid after jit completes) - PgoSource * pPgoSource // source of pgo data + PgoSource * pPgoSource, // source of pgo data + bool * pDynamicPgo // true if Dynamic PGO is enabled ) { CONTRACTL { @@ -12105,6 +12117,7 @@ HRESULT CEEJitInfo::getPgoInstrumentationResults( *pCountSchemaItems = 0; *pInstrumentationData = NULL; *pPgoSource = PgoSource::Unknown; + *pDynamicPgo = g_pConfig->TieredPGO(); JIT_TO_EE_TRANSITION(); @@ -12388,7 +12401,7 @@ void CEEJitInfo::setEHinfo ( if (m_pMethodBeingCompiled->IsDynamicMethod() && ((pEHClause->Flags & COR_ILEXCEPTION_CLAUSE_FILTER) == 0) && - (clause->ClassToken != NULL)) + (clause->ClassToken != mdTokenNil)) { ResolvedToken resolved{}; m_pMethodBeingCompiled->AsDynamicMethodDesc()->GetResolver()->ResolveToken(clause->ClassToken, &resolved); @@ -12878,7 +12891,7 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, NativeCodeVersion nativeCodeVersion = config->GetCodeVersion(); MethodDesc* ftn = nativeCodeVersion.GetMethodDesc(); - PCODE ret = NULL; + PCODE ret = (PCODE)NULL; NormalizedTimer timer; int64_t c100nsTicksInJit = 0; @@ -14398,7 +14411,8 @@ HRESULT CEEInfo::getPgoInstrumentationResults( PgoInstrumentationSchema **pSchema, // pointer to the schema table which describes the instrumentation results (pointer will not remain valid after jit completes) uint32_t * pCountSchemaItems, // pointer to the count schema items uint8_t ** pInstrumentationData, // pointer to the actual instrumentation data (pointer will not remain valid after jit completes) - PgoSource * pPgoSource + PgoSource * pPgoSource, + bool * pDynamicPgo ) { LIMITED_METHOD_CONTRACT; @@ -14511,7 +14525,7 @@ EECodeInfo::EECodeInfo() { WRAPPER_NO_CONTRACT; - m_codeAddress = NULL; + m_codeAddress = (PCODE)NULL; m_pJM = NULL; m_pMD = NULL; diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 7429352a47de..51e2b959d6f6 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -643,7 +643,8 @@ class CEEJitInfo : public CEEInfo PgoInstrumentationSchema** pSchema, /* OUT */ uint32_t* pCountSchemaItems, /* OUT */ uint8_t**pInstrumentationData, /* OUT */ - PgoSource *pPgoSource /* OUT */ + PgoSource *pPgoSource, /* OUT */ + bool* pDynamicPgo /* OUT */ ) override final; void recordCallSite( @@ -709,7 +710,7 @@ class CEEJitInfo : public CEEInfo #endif #ifdef FEATURE_EH_FUNCLETS - m_moduleBase = NULL; + m_moduleBase = (TADDR)0; m_totalUnwindSize = 0; m_usedUnwindSize = 0; m_theUnwindBlock = NULL; @@ -792,7 +793,7 @@ class CEEJitInfo : public CEEInfo m_pCodeHeap(NULL), m_ILHeader(header), #ifdef FEATURE_EH_FUNCLETS - m_moduleBase(NULL), + m_moduleBase(0), m_totalUnwindSize(0), m_usedUnwindSize(0), m_theUnwindBlock(NULL), @@ -1082,7 +1083,7 @@ EXTERN_C TypeHandle::CastResult STDCALL ObjIsInstanceOfCached(Object *pObject, T #ifdef HOST_64BIT class InlinedCallFrame; -Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame, PTR_VOID StubSecretArg); +Thread * JIT_InitPInvokeFrame(InlinedCallFrame *pFrame); #endif #ifdef _DEBUG diff --git a/src/coreclr/vm/listlock.h b/src/coreclr/vm/listlock.h index 8ad1fe4c967a..c062c68fc087 100644 --- a/src/coreclr/vm/listlock.h +++ b/src/coreclr/vm/listlock.h @@ -65,7 +65,7 @@ class ListLockEntryBase m_pNext(NULL), m_dwRefCount(1), m_hrResultCode(S_FALSE), - m_hInitException(NULL), + m_hInitException{}, m_pLoaderAllocator(dac_cast(nullptr)) { WRAPPER_NO_CONTRACT; diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp index 53e5b679cfb6..4f625e592e8d 100644 --- a/src/coreclr/vm/loaderallocator.cpp +++ b/src/coreclr/vm/loaderallocator.cpp @@ -34,7 +34,7 @@ LoaderAllocator::LoaderAllocator(bool collectible) : m_pDynamicHelpersHeap = NULL; #endif m_pFuncPtrStubs = NULL; - m_hLoaderAllocatorObjectHandle = NULL; + m_hLoaderAllocatorObjectHandle = (OBJECTHANDLE)NULL; m_pStringLiteralMap = NULL; m_cReferences = (UINT32)-1; @@ -759,7 +759,7 @@ LOADERHANDLE LoaderAllocator::AllocateHandle(OBJECTREF value) gc.loaderAllocator = (LOADERALLOCATORREF)ObjectFromHandle(m_hLoaderAllocatorObjectHandle); if (gc.loaderAllocator == NULL) { // The managed LoaderAllocator is already collected, we cannot allocate any exposed managed objects for it - retVal = NULL; + retVal = (LOADERHANDLE)NULL; } else { @@ -1833,9 +1833,9 @@ void AssemblyLoaderAllocator::RegisterHandleForCleanup(OBJECTHANDLE objHandle) { CONTRACTL { - GC_TRIGGERS; + GC_NOTRIGGER; THROWS; - MODE_ANY; + MODE_COOPERATIVE; CAN_TAKE_LOCK; PRECONDITION(CheckPointer(objHandle)); INJECT_FAULT(COMPlusThrowOM();); @@ -1849,6 +1849,25 @@ void AssemblyLoaderAllocator::RegisterHandleForCleanup(OBJECTHANDLE objHandle) m_handleCleanupList.InsertTail(new (pItem) HandleCleanupListItem(objHandle)); } +void AssemblyLoaderAllocator::RegisterHandleForCleanupLocked(OBJECTHANDLE objHandle) +{ + CONTRACTL + { + GC_NOTRIGGER; + THROWS; + MODE_COOPERATIVE; + CAN_TAKE_LOCK; + PRECONDITION(CheckPointer(objHandle)); + INJECT_FAULT(COMPlusThrowOM();); + } + CONTRACTL_END; + + void * pItem = GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(HandleCleanupListItem))); + // InsertTail must be protected by a lock. Just use the loader allocator lock + _ASSERTE(m_crstLoaderAllocator.OwnedByCurrentThread()); + m_handleCleanupList.InsertTail(new (pItem) HandleCleanupListItem(objHandle)); +} + void AssemblyLoaderAllocator::UnregisterHandleFromCleanup(OBJECTHANDLE objHandle) { CONTRACTL @@ -2198,3 +2217,56 @@ PTR_OnStackReplacementManager LoaderAllocator::GetOnStackReplacementManager() #endif // #endif // FEATURE_ON_STACK_REPLACEMENT + +#ifndef DACCESS_COMPILE +bool LoaderAllocator::InsertObjectIntoFieldWithLifetimeOfCollectibleLoaderAllocator(OBJECTREF value, Object** pField) +{ + CONTRACTL { + + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; + INJECT_FAULT(COMPlusThrowOM()); + //REENTRANT + } + CONTRACTL_END; + + _ASSERTE(IsCollectible()); + bool result = false; + + GCPROTECT_BEGIN(value); + LOADERHANDLEHolder keepAliveForCollectibleLifetime(AllocateHandle(value), this); + + // At this point we are no longer allowed to trigger a GC. + GCX_FORBID(); + { + CrstHolder cs(&m_crstLoaderAllocator); + if (*pField == NULL) + { + // Allocating a weak interior handle is a tricky thing. + // 1. If there are multiple weak interior handles that point at a given interior pointer location, there will be heap corruption + // 2. If the interior handle is created, but not registered for cleanup, it is a memory leak + // 3. Since the weak interior handle doesn't actually keep the object alive, it needs to be kept alive by some other means + // + // We work around these details by the following means + // 1. We use a LOADERHANDLE to keep the object alive until the LoaderAllocator is freed. + // 2. We hold the crstLoaderAllocatorLock lock, and double check to ensure that the data is ready to be filled in + // 3. We create the weak interior handle, and register it for cleanup (which can fail with an OOM) before updating the statics data to have the pointer + // 4. Registration for cleanup cannot trigger a GC + // 5. We then unconditionally set the statics pointer. + WeakInteriorHandleHolder weakHandleHolder = GetAppDomain()->CreateWeakInteriorHandle(value, pField); + RegisterHandleForCleanupLocked(weakHandleHolder.GetValue()); + + // Cannot fail after here + VolatileStore(pField, OBJECTREFToObject(value)); + + weakHandleHolder.SuppressRelease(); + keepAliveForCollectibleLifetime.SuppressRelease(); + result = true; + } + } + GCPROTECT_END(); + return result; +} + +#endif \ No newline at end of file diff --git a/src/coreclr/vm/loaderallocator.hpp b/src/coreclr/vm/loaderallocator.hpp index 365063b0b522..0b3efdc2c7bf 100644 --- a/src/coreclr/vm/loaderallocator.hpp +++ b/src/coreclr/vm/loaderallocator.hpp @@ -633,6 +633,7 @@ class LoaderAllocator LOADERALLOCATORREF GetExposedObject(); #ifndef DACCESS_COMPILE + bool InsertObjectIntoFieldWithLifetimeOfCollectibleLoaderAllocator(OBJECTREF value, Object** pField); LOADERHANDLE AllocateHandle(OBJECTREF value); void SetHandleValue(LOADERHANDLE handle, OBJECTREF value); @@ -641,6 +642,7 @@ class LoaderAllocator // The default implementation is a no-op. Only collectible loader allocators implement this method. virtual void RegisterHandleForCleanup(OBJECTHANDLE /* objHandle */) { } + virtual void RegisterHandleForCleanupLocked(OBJECTHANDLE /* objHandle*/ ) {} virtual void UnregisterHandleFromCleanup(OBJECTHANDLE /* objHandle */) { } virtual void CleanupHandles() { } @@ -896,6 +898,7 @@ class AssemblyLoaderAllocator : public LoaderAllocator #if !defined(DACCESS_COMPILE) virtual void RegisterHandleForCleanup(OBJECTHANDLE objHandle); + virtual void RegisterHandleForCleanupLocked(OBJECTHANDLE objHandle); virtual void UnregisterHandleFromCleanup(OBJECTHANDLE objHandle); virtual void CleanupHandles(); CustomAssemblyBinder* GetBinder() @@ -941,6 +944,41 @@ class AssemblyLoaderAllocator : public LoaderAllocator typedef VPTR(AssemblyLoaderAllocator) PTR_AssemblyLoaderAllocator; +#ifndef DACCESS_COMPILE +class LOADERHANDLEHolder +{ + LOADERHANDLE _handle; + LoaderAllocator* _pLoaderAllocator; + +public: + + LOADERHANDLEHolder(LOADERHANDLE handle, LoaderAllocator* pLoaderAllocator) + { + _handle = handle; + _pLoaderAllocator = pLoaderAllocator; + _ASSERTE(_pLoaderAllocator != NULL); + } + + LOADERHANDLEHolder(const LOADERHANDLEHolder&) = delete; + + LOADERHANDLE GetValue() const + { + return _handle; + } + + void SuppressRelease() + { + _pLoaderAllocator = NULL; + } + + ~LOADERHANDLEHolder() + { + if (_pLoaderAllocator != NULL) + _pLoaderAllocator->FreeHandle(_handle); + } +}; +#endif + #include "loaderallocator.inl" #endif // __LoaderAllocator_h__ diff --git a/src/coreclr/vm/loongarch64/asmconstants.h b/src/coreclr/vm/loongarch64/asmconstants.h index 6828eec7505e..8d53c8c3173a 100644 --- a/src/coreclr/vm/loongarch64/asmconstants.h +++ b/src/coreclr/vm/loongarch64/asmconstants.h @@ -218,16 +218,16 @@ ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next)) #define InlinedCallFrame__m_Datum 0x10 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum)) -#define InlinedCallFrame__m_pCallSiteSP 0x20 +#define InlinedCallFrame__m_pCallSiteSP 0x18 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP)) -#define InlinedCallFrame__m_pCallerReturnAddress 0x28 +#define InlinedCallFrame__m_pCallerReturnAddress 0x20 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress)) -#define InlinedCallFrame__m_pCalleeSavedFP 0x30 +#define InlinedCallFrame__m_pCalleeSavedFP 0x28 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP)) -#define InlinedCallFrame__m_pThread 0x38 +#define InlinedCallFrame__m_pThread 0x30 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pThread == offsetof(InlinedCallFrame, m_pThread)) #define FixupPrecodeData__Target 0x00 diff --git a/src/coreclr/vm/loongarch64/stubs.cpp b/src/coreclr/vm/loongarch64/stubs.cpp index 56581498f003..4de3341abdcc 100644 --- a/src/coreclr/vm/loongarch64/stubs.cpp +++ b/src/coreclr/vm/loongarch64/stubs.cpp @@ -61,7 +61,7 @@ class ConditionalBranchInstructionFormat : public InstructionFormat // Encoding 0|1|0|1|0|1|0|0|imm19|0|cond // cond = Bits3-0(variation) // imm19 = bits19-0(fixedUpReference/4), will be SignExtended - virtual VOID EmitInstruction(UINT refSize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refSize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { _ASSERTE(!"LOONGARCH64: not implementation on loongarch64!!!"); LIMITED_METHOD_CONTRACT; @@ -152,7 +152,7 @@ class BranchInstructionFormat : public InstructionFormat } } - virtual VOID EmitInstruction(UINT refSize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refSize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { LIMITED_METHOD_CONTRACT; @@ -160,7 +160,7 @@ class BranchInstructionFormat : public InstructionFormat { _ASSERTE(((UINT_PTR)pDataBuffer & 7) == 0); - __int64 dataOffset = pDataBuffer - pOutBufferRW; + int64_t dataOffset = pDataBuffer - pOutBufferRW; if ((dataOffset < -(0x80000000L)) || (dataOffset > 0x7fffffff)) COMPlusThrow(kNotSupportedException); @@ -183,13 +183,13 @@ class BranchInstructionFormat : public InstructionFormat *(DWORD*)(pOutBufferRW+12) = 0x4c0002a0;//jirl $r0,$r21,0 } - *((__int64*)pDataBuffer) = fixedUpReference + (__int64)pOutBufferRX; + *((int64_t*)pDataBuffer) = fixedUpReference + (int64_t)pOutBufferRX; } else { _ASSERTE(((UINT_PTR)pDataBuffer & 7) == 0); - __int64 dataOffset = pDataBuffer - pOutBufferRW; + int64_t dataOffset = pDataBuffer - pOutBufferRW; if ((dataOffset < -(0x80000000L)) || (dataOffset > 0x7fffffff)) COMPlusThrow(kNotSupportedException); @@ -210,9 +210,9 @@ class BranchInstructionFormat : public InstructionFormat *((DWORD*)(pOutBufferRW+8)) = 0x4c0002a0;//jirl $r0,$r21,0 } - if (!ClrSafeInt<__int64>::addition(fixedUpReference, (__int64)pOutBufferRX, fixedUpReference)) + if (!ClrSafeInt::addition(fixedUpReference, (int64_t)pOutBufferRX, fixedUpReference)) COMPlusThrowArithmetic(); - *((__int64*)pDataBuffer) = fixedUpReference; + *((int64_t*)pDataBuffer) = fixedUpReference; } } @@ -248,7 +248,7 @@ class LoadFromLabelInstructionFormat : public InstructionFormat return fExternal; } - virtual VOID EmitInstruction(UINT refSize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refSize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { _ASSERTE(!"LOONGARCH64: not implementation on loongarch64!!!"); LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/managedmdimport.cpp b/src/coreclr/vm/managedmdimport.cpp index 622e74edb994..8ab00a85f532 100644 --- a/src/coreclr/vm/managedmdimport.cpp +++ b/src/coreclr/vm/managedmdimport.cpp @@ -7,281 +7,169 @@ #include "managedmdimport.hpp" #include "wrappers.h" -void ThrowMetaDataImportException(HRESULT hr) -{ - WRAPPER_NO_CONTRACT; - - if (hr == CLDB_E_RECORD_NOTFOUND) - return; - - MethodDescCallSite throwError(METHOD__METADATA_IMPORT__THROW_ERROR); - - ARG_SLOT args[] = { (ARG_SLOT)hr }; - throwError.Call(args); -} - // // MetaDataImport // extern BOOL ParseNativeTypeInfo(NativeTypeParamInfo* pInfo, PCCOR_SIGNATURE pvNativeType, ULONG cbNativeType); -FCIMPL11(void, MetaDataImport::GetMarshalAs, - BYTE* pvNativeType, - ULONG cbNativeType, - INT32* unmanagedType, - INT32* safeArraySubType, - STRINGREF* safeArrayUserDefinedSubType, - INT32* arraySubType, - INT32* sizeParamIndex, - INT32* sizeConst, - STRINGREF* marshalType, - STRINGREF* marshalCookie, - INT32* iidParamIndex) +FCIMPL11(FC_BOOL_RET, MetaDataImport::GetMarshalAs, + BYTE* pvNativeType, + ULONG cbNativeType, + INT32* unmanagedType, + INT32* safeArraySubType, + LPUTF8* safeArrayUserDefinedSubType, + INT32* arraySubType, + INT32* sizeParamIndex, + INT32* sizeConst, + LPUTF8* marshalType, + LPUTF8* marshalCookie, + INT32* iidParamIndex) { FCALL_CONTRACT; - HELPER_METHOD_FRAME_BEGIN_0(); - { - NativeTypeParamInfo info; - - ZeroMemory(&info, sizeof(NativeTypeParamInfo)); + NativeTypeParamInfo info{}; - if (!ParseNativeTypeInfo(&info, pvNativeType, cbNativeType)) - { - ThrowMetaDataImportException(E_FAIL); - } + // The zeroing out of memory is important. The Reflection API's + // instantiation of MarshalAsAttribute doesn't reflect the default + // values the interop subsystem uses. This means NativeTypeParamInfo's + // constructor initialization values need to be overridden by zero + // initialization. + ZeroMemory(&info, sizeof(info)); + if (!ParseNativeTypeInfo(&info, pvNativeType, cbNativeType)) + { + FC_RETURN_BOOL(FALSE); + } - *unmanagedType = info.m_NativeType; - *sizeParamIndex = info.m_CountParamIdx; - *sizeConst = info.m_Additive; - *arraySubType = info.m_ArrayElementType; + *unmanagedType = info.m_NativeType; + *sizeParamIndex = info.m_CountParamIdx; + *sizeConst = info.m_Additive; + *arraySubType = info.m_ArrayElementType; #ifdef FEATURE_COMINTEROP - *iidParamIndex = info.m_IidParamIndex; + *iidParamIndex = info.m_IidParamIndex; - *safeArraySubType = info.m_SafeArrayElementVT; + *safeArraySubType = info.m_SafeArrayElementVT; - *safeArrayUserDefinedSubType = info.m_strSafeArrayUserDefTypeName == NULL ? NULL : - StringObject::NewString(info.m_strSafeArrayUserDefTypeName, info.m_cSafeArrayUserDefTypeNameBytes); + *safeArrayUserDefinedSubType = info.m_strSafeArrayUserDefTypeName; #else - *iidParamIndex = 0; + *iidParamIndex = 0; - *safeArraySubType = VT_EMPTY; + *safeArraySubType = VT_EMPTY; - *safeArrayUserDefinedSubType = NULL; + *safeArrayUserDefinedSubType = NULL; #endif - *marshalType = info.m_strCMMarshalerTypeName == NULL ? NULL : - StringObject::NewString(info.m_strCMMarshalerTypeName, info.m_cCMMarshalerTypeNameBytes); + *marshalType = info.m_strCMMarshalerTypeName; - *marshalCookie = info.m_strCMCookie == NULL ? NULL : - StringObject::NewString(info.m_strCMCookie, info.m_cCMCookieStrBytes); - } - HELPER_METHOD_FRAME_END(); + *marshalCookie = info.m_strCMCookie; + + FC_RETURN_BOOL(TRUE); } FCIMPLEND -MDImpl4(Object *, MetaDataImport::GetDefaultValue, mdToken tk, INT64* pDefaultValue, INT32* pLength, INT32* pCorElementType) +FCIMPL1(IMDInternalImport*, MetaDataImport::GetMetadataImport, ReflectModuleBaseObject * pModuleUNSAFE) { FCALL_CONTRACT; - HRESULT hr = S_OK; - Object *pRetVal = NULL; + REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE); + Module *pModule = refModule->GetModule(); + return pModule->GetMDImport(); +} +FCIMPLEND + +FCIMPL6(HRESULT, MetaDataImport::GetDefaultValue, IMDInternalImport* pScope, mdToken tk, INT64* pDefaultValue, LPCWSTR* pStringValue, INT32* pLength, INT32* pCorElementType) +{ + FCALL_CONTRACT; - IMDInternalImport *_pScope = pScope; + HRESULT hr = S_OK; MDDefaultValue value; - IfFailGo(_pScope->GetDefaultValue(tk, &value)); - - // We treat string values differently. That's because on big-endian architectures we can't return a - // pointer to static string data in the metadata, we have to buffer the string in order to byte-swap - // all the unicode characters. MDDefaultValue therefore has a destructor on big-endian machines which - // reclaims this buffer, implying we can't safely return the embedded pointer to managed code. - // The easiest thing for us to do is to construct the managed string object here, in the context of - // the still valid MDDefaultValue. We can't return a managed object via the normal out parameter - // because it won't be GC protected, so in this special case null the output parameter and return - // the string via the protected return result (which is null for all other cases). + IfFailGo(pScope->GetDefaultValue(tk, &value)); + if (value.m_bType == ELEMENT_TYPE_STRING) { - HELPER_METHOD_FRAME_BEGIN_RET_0(); *pDefaultValue = 0; - STRINGREF refRetval = StringObject::NewString(value.m_wzValue, value.m_cbSize / sizeof(WCHAR)); - pRetVal = STRINGREFToObject(refRetval); - HELPER_METHOD_FRAME_END(); + *pStringValue = value.m_wzValue; + *pLength = (INT32)value.m_cbSize / sizeof(WCHAR); // Length of string in character units } else { *pDefaultValue = value.m_ullValue; + *pStringValue = NULL; + *pLength = (INT32)value.m_cbSize; } - *pCorElementType = (UINT32)value.m_bType; - *pLength = (INT32)value.m_cbSize; -ErrExit: - if (FAILED(hr)) - { - FCThrow(kBadImageFormatException); - } - return pRetVal; +ErrExit: + return hr; } FCIMPLEND -MDImpl3(void, MetaDataImport::GetCustomAttributeProps, mdCustomAttribute cv, mdToken* ptkType, ConstArray* ppBlob) +FCIMPL4(HRESULT, MetaDataImport::GetCustomAttributeProps, IMDInternalImport* pScope, mdCustomAttribute cv, mdToken* ptkType, ConstArray* ppBlob) { FCALL_CONTRACT; HRESULT hr = S_OK; - IMDInternalImport *_pScope = pScope; - - IfFailGo(_pScope->GetCustomAttributeProps(cv, ptkType)); - IfFailGo(_pScope->GetCustomAttributeAsBlob(cv, (const void **)&ppBlob->m_array, (ULONG *)&ppBlob->m_count)); + IfFailGo(pScope->GetCustomAttributeProps(cv, ptkType)); + IfFailGo(pScope->GetCustomAttributeAsBlob(cv, (const void **)&ppBlob->m_array, (ULONG *)&ppBlob->m_count)); ErrExit: - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } -} -FCIMPLEND - -static int * EnsureResultSize(MetadataEnumResult * pResult, ULONG length) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - } - CONTRACTL_END; - - int * p; - - if (length >= ARRAY_SIZE(pResult->smallResult) || DbgRandomOnExe(.01)) - { - pResult->largeResult = (I4Array *)OBJECTREFToObject(AllocatePrimitiveArray(ELEMENT_TYPE_I4, length)); - p = pResult->largeResult->GetDirectPointerToNonObjectElements(); - } - else - { - ZeroMemory(pResult->smallResult, sizeof(pResult->smallResult)); - pResult->largeResult = NULL; - p = pResult->smallResult; - } - - pResult->length = length; - return p; -} - -MDImpl3(void, MetaDataImport::Enum, mdToken type, mdToken tkParent, MetadataEnumResult * pResult) -{ - CONTRACTL { - FCALL_CHECK; - PRECONDITION(pResult != NULL); - } - CONTRACTL_END; - - HELPER_METHOD_FRAME_BEGIN_0(); - { - IMDInternalImport *_pScope = pScope; - - if (type == mdtTypeDef) - { - ULONG nestedClassesCount; - IfFailThrow(_pScope->GetCountNestedClasses(tkParent, &nestedClassesCount)); - - mdTypeDef* arToken = (mdTypeDef*)EnsureResultSize(pResult, nestedClassesCount); - IfFailThrow(_pScope->GetNestedClasses(tkParent, arToken, nestedClassesCount, &nestedClassesCount)); - } - else if (type == mdtMethodDef && (TypeFromToken(tkParent) == mdtProperty || TypeFromToken(tkParent) == mdtEvent)) - { - HENUMInternalHolder hEnum(pScope); - hEnum.EnumAssociateInit(tkParent); - - ULONG associatesCount = hEnum.EnumGetCount(); - - static_assert_no_msg(sizeof(ASSOCIATE_RECORD) == 2 * sizeof(int)); - - ASSOCIATE_RECORD* arAssocRecord = (ASSOCIATE_RECORD*)EnsureResultSize(pResult, 2 * associatesCount); - IfFailThrow(_pScope->GetAllAssociates(&hEnum, arAssocRecord, associatesCount)); - } - else - { - HENUMInternalHolder hEnum(pScope); - hEnum.EnumInit(type, tkParent); - - ULONG count = hEnum.EnumGetCount(); - - mdToken* arToken = (mdToken*)EnsureResultSize(pResult, count); - for(COUNT_T i = 0; i < count && _pScope->EnumNext(&hEnum, &arToken[i]); i++); - } - } - HELPER_METHOD_FRAME_END(); + return hr; } FCIMPLEND #if defined(_MSC_VER) && defined(TARGET_X86) -#pragma optimize("y", on) // Small critical routines, don't put in EBP frame +#pragma optimize("y", on) // Small critical routines, don't put in EBP frame #endif -MDImpl1(FC_BOOL_RET, MetaDataImport::IsValidToken, mdToken tk) +FCIMPL2(FC_BOOL_RET, MetaDataImport::IsValidToken, IMDInternalImport* pScope, mdToken tk) { FCALL_CONTRACT; - IMDInternalImport *_pScope = pScope; - - FC_RETURN_BOOL(_pScope->IsValidToken(tk)); + FC_RETURN_BOOL(pScope->IsValidToken(tk)); } FCIMPLEND - -MDImpl3(void, MetaDataImport::GetClassLayout, mdTypeDef td, DWORD* pdwPackSize, ULONG* pulClassSize) +FCIMPL4(HRESULT, MetaDataImport::GetClassLayout, IMDInternalImport* pScope, mdTypeDef td, DWORD* pdwPackSize, ULONG* pulClassSize) { FCALL_CONTRACT; HRESULT hr = S_OK; + if (pdwPackSize != NULL) { - IMDInternalImport *_pScope = pScope; - - if (pdwPackSize != NULL) + hr = pScope->GetClassPackSize(td, (ULONG *)pdwPackSize); + if (hr == CLDB_E_RECORD_NOTFOUND) { - hr = _pScope->GetClassPackSize(td, (ULONG *)pdwPackSize); - if (hr == CLDB_E_RECORD_NOTFOUND) - { - *pdwPackSize = 0; - hr = S_OK; - } - IfFailGo(hr); + *pdwPackSize = 0; + hr = S_OK; } + IfFailGo(hr); + } - if (pulClassSize != NULL) + if (pulClassSize != NULL) + { + hr = pScope->GetClassTotalSize(td, pulClassSize); + if (hr == CLDB_E_RECORD_NOTFOUND) { - hr = _pScope->GetClassTotalSize(td, pulClassSize); - if (hr == CLDB_E_RECORD_NOTFOUND) - { - *pulClassSize = 0; - hr = S_OK; - } - IfFailGo(hr); + *pulClassSize = 0; + hr = S_OK; } + IfFailGo(hr); } ErrExit: - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return hr; } FCIMPLEND -MDImpl3(FC_BOOL_RET, MetaDataImport::GetFieldOffset, mdTypeDef td, mdFieldDef target, DWORD* pdwFieldOffset) +FCIMPL5(HRESULT, MetaDataImport::GetFieldOffset, IMDInternalImport* pScope, mdTypeDef td, mdFieldDef target, DWORD* pdwFieldOffset, CLR_BOOL* found) { FCALL_CONTRACT; HRESULT hr = S_OK; - IMDInternalImport *_pScope = pScope; MD_CLASS_LAYOUT layout; - BOOL retVal = FALSE; + *found = FALSE; - IfFailGo(_pScope->GetClassLayoutInit(td, &layout)); + IfFailGo(pScope->GetClassLayoutInit(td, &layout)); ULONG cFieldOffset; cFieldOffset = layout.m_ridFieldEnd - layout.m_ridFieldCur; @@ -290,147 +178,108 @@ MDImpl3(FC_BOOL_RET, MetaDataImport::GetFieldOffset, mdTypeDef td, mdFieldDef ta { mdFieldDef fd; ULONG offset; - IfFailGo(_pScope->GetClassLayoutNext(&layout, &fd, &offset)); + IfFailGo(pScope->GetClassLayoutNext(&layout, &fd, &offset)); if (fd == target) { *pdwFieldOffset = offset; - retVal = TRUE; + *found = TRUE; break; } } ErrExit: - if (FAILED(hr)) - { - FCThrow(kBadImageFormatException); - } - FC_RETURN_BOOL(retVal); + return hr; } FCIMPLEND -MDImpl3(void, MetaDataImport::GetUserString, mdToken tk, LPCSTR* pszName, ULONG* pCount) +FCIMPL4(HRESULT, MetaDataImport::GetUserString, IMDInternalImport* pScope, mdToken tk, LPCWSTR* pszName, ULONG* pCount) { FCALL_CONTRACT; - HRESULT hr; - IMDInternalImport *_pScope = pScope; BOOL bHasExtendedChars; - - hr = _pScope->GetUserString(tk, pCount, &bHasExtendedChars, (LPCWSTR *)pszName); - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return pScope->GetUserString(tk, pCount, &bHasExtendedChars, pszName); } FCIMPLEND -MDImpl2(void, MetaDataImport::GetName, mdToken tk, LPCSTR* pszName) +FCIMPL3(HRESULT, MetaDataImport::GetName, IMDInternalImport* pScope, mdToken tk, LPCSTR* pszName) { FCALL_CONTRACT; HRESULT hr = S_OK; - IMDInternalImport *_pScope = pScope; if (TypeFromToken(tk) == mdtMethodDef) { - hr = _pScope->GetNameOfMethodDef(tk, pszName); + hr = pScope->GetNameOfMethodDef(tk, pszName); } else if (TypeFromToken(tk) == mdtParamDef) { USHORT seq; DWORD attr; - hr = _pScope->GetParamDefProps(tk, &seq, &attr, pszName); + hr = pScope->GetParamDefProps(tk, &seq, &attr, pszName); } else if (TypeFromToken(tk) == mdtFieldDef) { - hr = _pScope->GetNameOfFieldDef(tk, pszName); + hr = pScope->GetNameOfFieldDef(tk, pszName); } else if (TypeFromToken(tk) == mdtProperty) { - hr = _pScope->GetPropertyProps(tk, pszName, NULL, NULL, NULL); + hr = pScope->GetPropertyProps(tk, pszName, NULL, NULL, NULL); } else if (TypeFromToken(tk) == mdtEvent) { - hr = _pScope->GetEventProps(tk, pszName, NULL, NULL); + hr = pScope->GetEventProps(tk, pszName, NULL, NULL); } else if (TypeFromToken(tk) == mdtModule) { - hr = _pScope->GetModuleRefProps(tk, pszName); + hr = pScope->GetModuleRefProps(tk, pszName); } else if (TypeFromToken(tk) == mdtTypeDef) { LPCSTR szNamespace = NULL; - hr = _pScope->GetNameOfTypeDef(tk, pszName, &szNamespace); + hr = pScope->GetNameOfTypeDef(tk, pszName, &szNamespace); } else { hr = E_FAIL; } - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return hr; } FCIMPLEND -MDImpl2(void, MetaDataImport::GetNamespace, mdToken tk, LPCSTR* pszName) +FCIMPL3(HRESULT, MetaDataImport::GetNamespace, IMDInternalImport* pScope, mdToken tk, LPCSTR* pszName) { FCALL_CONTRACT; - HRESULT hr; - IMDInternalImport *_pScope = pScope; LPCSTR szName = NULL; - - hr = _pScope->GetNameOfTypeDef(tk, &szName, pszName); - - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return pScope->GetNameOfTypeDef(tk, &szName, pszName); } FCIMPLEND - -MDImpl2(void, MetaDataImport::GetGenericParamProps, mdToken tk, DWORD* pAttributes) +FCIMPL3(HRESULT, MetaDataImport::GetGenericParamProps, IMDInternalImport* pScope, mdToken tk, DWORD* pAttributes) { FCALL_CONTRACT; - HRESULT hr; - IMDInternalImport *_pScope = pScope; - - hr = _pScope->GetGenericParamProps(tk, NULL, pAttributes, NULL, NULL, NULL); - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return pScope->GetGenericParamProps(tk, NULL, pAttributes, NULL, NULL, NULL); } FCIMPLEND -MDImpl3(void, MetaDataImport::GetEventProps, mdToken tk, LPCSTR* pszName, INT32 *pdwEventFlags) +FCIMPL4(HRESULT, MetaDataImport::GetEventProps, IMDInternalImport* pScope, mdToken tk, LPCSTR* pszName, INT32 *pdwEventFlags) { FCALL_CONTRACT; - HRESULT hr; - IMDInternalImport *_pScope = pScope; - - hr = _pScope->GetEventProps(tk, pszName, (DWORD*)pdwEventFlags, NULL); - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return pScope->GetEventProps(tk, pszName, (DWORD*)pdwEventFlags, NULL); } FCIMPLEND -MDImpl4(void, MetaDataImport::GetPinvokeMap, mdToken tk, DWORD* pMappingFlags, LPCSTR* pszImportName, LPCSTR* pszImportDll) +FCIMPL5(HRESULT, MetaDataImport::GetPInvokeMap, IMDInternalImport* pScope, mdToken tk, DWORD* pMappingFlags, LPCSTR* pszImportName, LPCSTR* pszImportDll) { FCALL_CONTRACT; HRESULT hr; - IMDInternalImport *_pScope = pScope; mdModule tkModule; - hr = _pScope->GetPinvokeMap(tk, pMappingFlags, pszImportName, &tkModule); + hr = pScope->GetPinvokeMap(tk, pMappingFlags, pszImportName, &tkModule); if (FAILED(hr)) { *pMappingFlags = 0; @@ -440,29 +289,24 @@ MDImpl4(void, MetaDataImport::GetPinvokeMap, mdToken tk, DWORD* pMappingFlags, L } else { - hr = _pScope->GetModuleRefProps(tkModule, pszImportDll); - } - - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); + hr = pScope->GetModuleRefProps(tkModule, pszImportDll); } + return hr; } FCIMPLEND -MDImpl3(void, MetaDataImport::GetParamDefProps, mdToken tk, INT32* pSequence, INT32* pAttributes) +FCIMPL4(HRESULT, MetaDataImport::GetParamDefProps, IMDInternalImport* pScope, mdToken tk, INT32* pSequence, INT32* pAttributes) { FCALL_CONTRACT; HRESULT hr; - IMDInternalImport *_pScope = pScope; USHORT usSequence = 0; // Is this a valid token? - if (_pScope->IsValidToken((mdParamDef)tk)) + if (pScope->IsValidToken((mdParamDef)tk)) { LPCSTR szParamName; - hr = _pScope->GetParamDefProps(tk, &usSequence, (DWORD *)pAttributes, &szParamName); + hr = pScope->GetParamDefProps(tk, &usSequence, (DWORD *)pAttributes, &szParamName); } else { @@ -471,51 +315,33 @@ MDImpl3(void, MetaDataImport::GetParamDefProps, mdToken tk, INT32* pSequence, IN } *pSequence = (INT32) usSequence; - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return hr; } FCIMPLEND -MDImpl2(void, MetaDataImport::GetFieldDefProps, mdToken tk, INT32 *pdwFieldFlags) +FCIMPL3(HRESULT, MetaDataImport::GetFieldDefProps, IMDInternalImport* pScope, mdToken tk, INT32 *pdwFieldFlags) { FCALL_CONTRACT; - HRESULT hr; - IMDInternalImport *_pScope = pScope; - - hr = _pScope->GetFieldDefProps(tk, (DWORD *)pdwFieldFlags); - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return pScope->GetFieldDefProps(tk, (DWORD *)pdwFieldFlags); } FCIMPLEND -MDImpl4(void, MetaDataImport::GetPropertyProps, mdToken tk, LPCSTR* pszName, INT32 *pdwPropertyFlags, ConstArray* ppValue) +FCIMPL5(HRESULT, MetaDataImport::GetPropertyProps, IMDInternalImport* pScope, mdToken tk, LPCSTR* pszName, INT32 *pdwPropertyFlags, ConstArray* ppValue) { FCALL_CONTRACT; - HRESULT hr; - IMDInternalImport *_pScope = pScope; - - hr = _pScope->GetPropertyProps(tk, pszName, (DWORD*)pdwPropertyFlags, (PCCOR_SIGNATURE*)&ppValue->m_array, (ULONG*)&ppValue->m_count); - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } -} -FCIMPLEND + return pScope->GetPropertyProps(tk, pszName, (DWORD*)pdwPropertyFlags, (PCCOR_SIGNATURE*)&ppValue->m_array, (ULONG*)&ppValue->m_count); + } + FCIMPLEND -MDImpl2(void, MetaDataImport::GetFieldMarshal, mdToken tk, ConstArray* ppValue) +FCIMPL3(HRESULT, MetaDataImport::GetFieldMarshal, IMDInternalImport* pScope, mdToken tk, ConstArray* ppValue) { FCALL_CONTRACT; HRESULT hr; - IMDInternalImport *_pScope = pScope; - hr = _pScope->GetFieldMarshal(tk, (PCCOR_SIGNATURE *)&ppValue->m_array, (ULONG *)&ppValue->m_count); + hr = pScope->GetFieldMarshal(tk, (PCCOR_SIGNATURE *)&ppValue->m_array, (ULONG *)&ppValue->m_count); if (hr == CLDB_E_RECORD_NOTFOUND) { ppValue->m_array = NULL; @@ -523,69 +349,44 @@ MDImpl2(void, MetaDataImport::GetFieldMarshal, mdToken tk, ConstArray* ppValue) hr = S_OK; } - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return hr; } FCIMPLEND -MDImpl2(void, MetaDataImport::GetSigOfMethodDef, mdToken tk, ConstArray* ppValue) +FCIMPL3(HRESULT, MetaDataImport::GetSigOfMethodDef, IMDInternalImport* pScope, mdToken tk, ConstArray* ppValue) { FCALL_CONTRACT; - HRESULT hr; - IMDInternalImport *_pScope = pScope; - - hr = _pScope->GetSigOfMethodDef(tk, (ULONG*)&ppValue->m_count, (PCCOR_SIGNATURE *)&ppValue->m_array); - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return pScope->GetSigOfMethodDef(tk, (ULONG*)&ppValue->m_count, (PCCOR_SIGNATURE *)&ppValue->m_array); } FCIMPLEND -MDImpl2(void, MetaDataImport::GetSignatureFromToken, mdToken tk, ConstArray* ppValue) +FCIMPL3(HRESULT, MetaDataImport::GetSignatureFromToken, IMDInternalImport* pScope, mdToken tk, ConstArray* ppValue) { FCALL_CONTRACT; - HRESULT hr; - IMDInternalImport *_pScope = pScope; - - hr = _pScope->GetSigFromToken(tk, (ULONG*)&ppValue->m_count, (PCCOR_SIGNATURE *)&(ppValue->m_array)); - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return pScope->GetSigFromToken(tk, (ULONG*)&ppValue->m_count, (PCCOR_SIGNATURE *)&(ppValue->m_array)); } FCIMPLEND -MDImpl2(void, MetaDataImport::GetSigOfFieldDef, mdToken tk, ConstArray* ppValue) +FCIMPL3(HRESULT, MetaDataImport::GetSigOfFieldDef, IMDInternalImport* pScope, mdToken tk, ConstArray* ppValue) { FCALL_CONTRACT; - HRESULT hr; - IMDInternalImport *_pScope = pScope; - - hr = _pScope->GetSigOfFieldDef(tk, (ULONG*)&ppValue->m_count, (PCCOR_SIGNATURE *)&ppValue->m_array); - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return pScope->GetSigOfFieldDef(tk, (ULONG*)&ppValue->m_count, (PCCOR_SIGNATURE *)&ppValue->m_array); } FCIMPLEND -MDImpl2(void, MetaDataImport::GetParentToken, mdToken tk, mdToken* ptk) +FCIMPL3(HRESULT, MetaDataImport::GetParentToken, IMDInternalImport* pScope, mdToken tk, mdToken* ptk) { FCALL_CONTRACT; HRESULT hr; - IMDInternalImport *_pScope = pScope; switch (TypeFromToken(tk)) { case mdtTypeDef: - hr = _pScope->GetNestedClassProps(tk, ptk); + hr = pScope->GetNestedClassProps(tk, ptk); if (hr == CLDB_E_RECORD_NOTFOUND) { *ptk = mdTypeDefNil; @@ -594,7 +395,7 @@ MDImpl2(void, MetaDataImport::GetParentToken, mdToken tk, mdToken* ptk) break; case mdtGenericParam: - hr = _pScope->GetGenericParamProps(tk, NULL, NULL, ptk, NULL, NULL); + hr = pScope->GetGenericParamProps(tk, NULL, NULL, ptk, NULL, NULL); break; case mdtMethodDef: @@ -605,7 +406,7 @@ MDImpl2(void, MetaDataImport::GetParentToken, mdToken tk, mdToken* ptk) case mdtCustomAttribute: case mdtEvent: case mdtProperty: - hr = _pScope->GetParentToken(tk, ptk); + hr = pScope->GetParentToken(tk, ptk); break; default: @@ -613,49 +414,176 @@ MDImpl2(void, MetaDataImport::GetParentToken, mdToken tk, mdToken* ptk) break; } - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return hr; } FCIMPLEND -MDImpl1(void, MetaDataImport::GetScopeProps, GUID* pmvid) +FCIMPL2(HRESULT, MetaDataImport::GetScopeProps, IMDInternalImport* pScope, GUID* pmvid) { FCALL_CONTRACT; - HRESULT hr; LPCSTR szName; - - IMDInternalImport *_pScope = pScope; - hr = _pScope->GetScopeProps(&szName, pmvid); - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return pScope->GetScopeProps(&szName, pmvid); } FCIMPLEND -MDImpl2(void, MetaDataImport::GetMemberRefProps, +FCIMPL3(HRESULT, MetaDataImport::GetMemberRefProps, + IMDInternalImport* pScope, mdMemberRef mr, ConstArray* ppvSigBlob) { FCALL_CONTRACT; - HRESULT hr; - IMDInternalImport *_pScope = pScope; LPCSTR szName_Ignore; - - hr = _pScope->GetNameAndSigOfMemberRef(mr, (PCCOR_SIGNATURE*)&ppvSigBlob->m_array, (ULONG*)&ppvSigBlob->m_count, &szName_Ignore); - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return pScope->GetNameAndSigOfMemberRef(mr, (PCCOR_SIGNATURE*)&ppvSigBlob->m_array, (ULONG*)&ppvSigBlob->m_count, &szName_Ignore); } FCIMPLEND #if defined(_MSC_VER) && defined(TARGET_X86) -#pragma optimize("", on) // restore command line optimization defaults +#pragma optimize("", on) // restore command line optimization defaults #endif +class ResultMemory final +{ + INT32 _length; + INT32* _alloc; + +public: + ResultMemory() = default; + + ~ResultMemory() + { + STANDARD_VM_CONTRACT; + delete[] _alloc; + } + + INT32* AllocateUnmanagedArray(INT32 length) + { + CONTRACT(INT32*) + { + THROWS; + MODE_PREEMPTIVE; + PRECONDITION(_alloc == NULL); + POSTCONDITION((length == _length)); + POSTCONDITION((RETVAL != NULL)); + } + CONTRACT_END; + + _alloc = new INT32[length]; + _length = length; + RETURN _alloc; + } + + void AllocateManagedArray(QCall::ObjectHandleOnStack& longResult) + { + CONTRACTL + { + THROWS; + MODE_PREEMPTIVE; + PRECONDITION(_alloc != NULL); + } + CONTRACTL_END; + + { + GCX_COOP(); + longResult.Set(AllocatePrimitiveArray(ELEMENT_TYPE_I4, _length)); + void* p = ((I4Array*)OBJECTREFToObject(longResult.Get()))->GetDirectPointerToNonObjectElements(); + memcpyNoGCRefs(p, _alloc, (size_t)_length * sizeof(INT32)); + } + } +}; + +static void* EnsureResultSize( + INT32 resultLength, + INT32 shortResultLen, + INT32* shortResult, + ResultMemory& resultMemory) +{ + CONTRACT(void*) + { + THROWS; + MODE_PREEMPTIVE; + PRECONDITION(shortResultLen > 0); + PRECONDITION(shortResult != NULL); + POSTCONDITION((RETVAL != NULL)); + } + CONTRACT_END; + + void* p; + if (resultLength <= shortResultLen) + { + p = shortResult; + } + else + { + _ASSERTE(resultLength > 0); + p = resultMemory.AllocateUnmanagedArray(resultLength); + } + ZeroMemory(p, (size_t)resultLength * sizeof(INT32)); + RETURN p; +} + +extern "C" void QCALLTYPE MetadataImport_Enum( + IMDInternalImport* pScope, + mdToken type, + mdToken tkParent, + /* in/out */ INT32* length, + INT32* shortResult, + QCall::ObjectHandleOnStack longResult) +{ + CONTRACTL + { + QCALL_CHECK; + PRECONDITION(pScope != NULL); + PRECONDITION(length != NULL); + PRECONDITION(shortResult != NULL); + } + CONTRACTL_END; + + BEGIN_QCALL; + + ResultMemory memory{}; + ULONG resultLength; + INT32 shortResultLen = *length; + if (type == mdtTypeDef) + { + IfFailThrow(pScope->GetCountNestedClasses(tkParent, &resultLength)); + + mdTypeDef* arToken = (mdTypeDef*)EnsureResultSize(resultLength, shortResultLen, shortResult, memory); + IfFailThrow(pScope->GetNestedClasses(tkParent, arToken, resultLength, &resultLength)); + } + else if (type == mdtMethodDef && (TypeFromToken(tkParent) == mdtProperty || TypeFromToken(tkParent) == mdtEvent)) + { + HENUMInternalHolder hEnum(pScope); + hEnum.EnumAssociateInit(tkParent); + + ULONG associatesCount = hEnum.EnumGetCount(); + + // The ASSOCIATE_RECORD is a pair of integers. + // This means we require a size of 2x the returned length. + resultLength = associatesCount * 2; + static_assert_no_msg(sizeof(ASSOCIATE_RECORD) == 2 * sizeof(INT32)); + + ASSOCIATE_RECORD* arAssocRecord = (ASSOCIATE_RECORD*)EnsureResultSize(resultLength, shortResultLen, shortResult, memory); + IfFailThrow(pScope->GetAllAssociates(&hEnum, arAssocRecord, associatesCount)); + } + else + { + HENUMInternalHolder hEnum(pScope); + hEnum.EnumInit(type, tkParent); + + resultLength = hEnum.EnumGetCount(); + + mdToken* arToken = (mdToken*)EnsureResultSize(resultLength, shortResultLen, shortResult, memory); + for(COUNT_T i = 0; i < resultLength && pScope->EnumNext(&hEnum, &arToken[i]); i++); + } + + // If the result was longer than the short, we need to allocate an array. + if (resultLength > (ULONG)shortResultLen) + memory.AllocateManagedArray(longResult); + + *length = resultLength; + + END_QCALL; +} diff --git a/src/coreclr/vm/managedmdimport.hpp b/src/coreclr/vm/managedmdimport.hpp index 72e3703c376d..4db05291d6fd 100644 --- a/src/coreclr/vm/managedmdimport.hpp +++ b/src/coreclr/vm/managedmdimport.hpp @@ -24,95 +24,57 @@ typedef struct void* m_array; } ConstArray; -typedef struct -{ - I4Array * largeResult; - int length; - int smallResult[16]; -} MetadataEnumResult; - -#define MDDecl0(RET, NAME) static FCDECL1(RET, NAME, IMDInternalImport* pScope) -#define MDDecl1(RET, NAME, arg0) static FCDECL2(RET, NAME, IMDInternalImport* pScope, arg0) -#define MDDecl2(RET, NAME, arg0, arg1) static FCDECL3(RET, NAME, IMDInternalImport* pScope, arg0, arg1) -#define MDDecl3(RET, NAME, arg0, arg1, arg2) static FCDECL4(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2) -#define MDDecl4(RET, NAME, arg0, arg1, arg2, arg3) static FCDECL5(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2, arg3) -#define MDDecl5(RET, NAME, arg0, arg1, arg2, arg3, arg4) static FCDECL6(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2, arg3, arg4) -#define MDDecl6(RET, NAME, arg0, arg1, arg2, arg3, arg4, arg5) static FCDECL7(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2, arg3, arg4, arg5) -#define MDDecl7(RET, NAME, arg0, arg1, arg2, arg3, arg4, arg5, arg6) static FCDECL8(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2, arg3, arg4, arg5, arg6) -#define MDDecl8(RET, NAME, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) static FCDECL9(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) -#define MDDecl9(RET, NAME, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) static FCDECL10(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) -#define MDDecl10(RET, NAME, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) static FCDECL11(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) - -#define MDImpl0(RET, NAME) FCIMPL1(RET, NAME, IMDInternalImport* pScope) -#define MDImpl1(RET, NAME, arg0) FCIMPL2(RET, NAME, IMDInternalImport* pScope, arg0) -#define MDImpl2(RET, NAME, arg0, arg1) FCIMPL3(RET, NAME, IMDInternalImport* pScope, arg0, arg1) -#define MDImpl3(RET, NAME, arg0, arg1, arg2) FCIMPL4(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2) -#define MDImpl4(RET, NAME, arg0, arg1, arg2, arg3) FCIMPL5(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2, arg3) -#define MDImpl5(RET, NAME, arg0, arg1, arg2, arg3, arg4) FCIMPL6(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2, arg3, arg4) -#define MDImpl6(RET, NAME, arg0, arg1, arg2, arg3, arg4, arg5) FCIMPL7(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2, arg3, arg4, arg5) -#define MDImpl7(RET, NAME, arg0, arg1, arg2, arg3, arg4, arg5, arg6) FCIMPL8(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2, arg3, arg4, arg5, arg6) -#define MDImpl8(RET, NAME, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) FCIMPL9(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) -#define MDImpl9(RET, NAME, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) FCIMPL10(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) -#define MDImpl10(RET, NAME, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) FCIMPL11(RET, NAME, IMDInternalImport* pScope, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) - class MetaDataImport { public: - // - // GetXXXProps - // - MDDecl1(void, GetScopeProps, GUID* pmvid); - MDDecl4(void, GetTypeDefProps, mdTypeDef td, STRINGREF* pszTypeDef, DWORD* pdwTypeDefFlags, mdToken* ptkExtends); - MDDecl2(void, GetMemberRefProps, mdMemberRef mr, ConstArray* ppvSigBlob); - - - //// - //// EnumXXX - //// - MDDecl3(void, Enum, mdToken type, mdToken tkParent, MetadataEnumResult * pResult); - MDDecl3(void, GetCustomAttributeProps, mdCustomAttribute cv, mdToken* ptkType, ConstArray* ppBlob); - - //// - //// Misc - //// - - MDDecl4(Object *, GetDefaultValue, mdToken tk, INT64* pDefaultValue, INT32* pLength, INT32* pCorElementType); - MDDecl2(void, GetName, mdToken tk, LPCSTR* pszName); - MDDecl3(void, GetUserString, mdToken tk, LPCSTR* pszName, ULONG* pCount); - MDDecl2(void, GetNamespace, mdToken tk, LPCSTR* pszName); - MDDecl2(void, GetParentToken, mdToken tk, mdToken* ptk); - MDDecl3(void, GetParamDefProps, mdToken tk, INT32* pSequence, INT32* pAttributes); - MDDecl4(void, GetPinvokeMap, mdToken tk, DWORD* pMappingFlags, LPCSTR* pszImportName, LPCSTR* pszImportDll); - - MDDecl3(void, GetClassLayout, mdTypeDef td, DWORD* pdwPackSize, ULONG* pulClassSize); - MDDecl3(FC_BOOL_RET, GetFieldOffset, mdTypeDef td, mdFieldDef target, DWORD* pdwFieldOffset); - - MDDecl3(void, GetEventProps, mdToken tk, LPCSTR* pszName, INT32 *pdwEventFlags); - MDDecl2(void, GetGenericParamProps, mdToken tk, DWORD* pAttributes); - MDDecl2(void, GetFieldDefProps, mdToken tk, INT32 *pdwFieldFlags); - MDDecl4(void, GetPropertyProps, mdToken tk, LPCSTR* pszName, INT32 *pdwPropertyFlags, ConstArray* ppvSigBlob); - - MDDecl2(void, GetSignatureFromToken, mdToken tk, ConstArray* pSig); - MDDecl2(void, GetSigOfFieldDef, mdToken tk, ConstArray* pMarshalInfo); - MDDecl2(void, GetSigOfMethodDef, mdToken tk, ConstArray* pMarshalInfo); - MDDecl2(void, GetFieldMarshal, mdToken tk, ConstArray* pMarshalInfo); - MDDecl2(mdParamDef, GetParamForMethodIndex, mdMethodDef md, ULONG ulParamSeq); - MDDecl1(FC_BOOL_RET, IsValidToken, mdToken tk); - MDDecl1(mdTypeDef, GetNestedClassProps, mdTypeDef tdNestedClass); - MDDecl1(ULONG, GetNativeCallConvFromSig, ConstArray sig); - - static FCDECL11(void, GetMarshalAs, - BYTE* pvNativeType, - ULONG cbNativeType, - INT32* unmanagedType, - INT32* safeArraySubType, - STRINGREF* safeArrayUserDefinedSubType, - INT32* arraySubType, - INT32* sizeParamIndex, - INT32* sizeConst, - STRINGREF* marshalType, - STRINGREF* marshalCookie, - INT32* iidParamIndex); + static FCDECL1(IMDInternalImport*, GetMetadataImport, ReflectModuleBaseObject* pModuleUNSAFE); + static FCDECL2(HRESULT, GetScopeProps, IMDInternalImport* pScope, GUID* pmvid); + static FCDECL3(HRESULT, GetMemberRefProps, IMDInternalImport* pScope, mdMemberRef mr, ConstArray* ppvSigBlob); + + static FCDECL4(HRESULT, GetCustomAttributeProps, IMDInternalImport* pScope, mdCustomAttribute cv, mdToken* ptkType, ConstArray* ppBlob); + + static FCDECL6(HRESULT, GetDefaultValue, IMDInternalImport* pScope, mdToken tk, INT64* pDefaultValue, LPCWSTR* pStringValue, INT32* pLength, INT32* pCorElementType); + static FCDECL3(HRESULT, GetName, IMDInternalImport* pScope, mdToken tk, LPCSTR* pszName); + static FCDECL4(HRESULT, GetUserString, IMDInternalImport* pScope, mdToken tk, LPCWSTR* pszName, ULONG* pCount); + static FCDECL3(HRESULT, GetNamespace, IMDInternalImport* pScope, mdToken tk, LPCSTR* pszName); + static FCDECL3(HRESULT, GetParentToken, IMDInternalImport* pScope, mdToken tk, mdToken* ptk); + static FCDECL4(HRESULT, GetParamDefProps, IMDInternalImport* pScope, mdToken tk, INT32* pSequence, INT32* pAttributes); + static FCDECL5(HRESULT, GetPInvokeMap, IMDInternalImport* pScope, mdToken tk, DWORD* pMappingFlags, LPCSTR* pszImportName, LPCSTR* pszImportDll); + + static FCDECL4(HRESULT, GetClassLayout, IMDInternalImport* pScope, mdTypeDef td, DWORD* pdwPackSize, ULONG* pulClassSize); + static FCDECL5(HRESULT, GetFieldOffset, IMDInternalImport* pScope, mdTypeDef td, mdFieldDef target, DWORD* pdwFieldOffsetGetFieldOffset, CLR_BOOL* found); + + static FCDECL4(HRESULT, GetEventProps, IMDInternalImport* pScope, mdToken tk, LPCSTR* pszName, INT32 *pdwEventFlags); + static FCDECL3(HRESULT, GetGenericParamProps, IMDInternalImport* pScope, mdToken tk, DWORD* pAttributes); + static FCDECL3(HRESULT, GetFieldDefProps, IMDInternalImport* pScope, mdToken tk, INT32 *pdwFieldFlags); + static FCDECL5(HRESULT, GetPropertyProps, IMDInternalImport* pScope, mdToken tk, LPCSTR* pszName, INT32 *pdwPropertyFlags, ConstArray* ppvSigBlob); + + static FCDECL3(HRESULT, GetSignatureFromToken, IMDInternalImport* pScope, mdToken tk, ConstArray* pSig); + static FCDECL3(HRESULT, GetSigOfFieldDef, IMDInternalImport* pScope, mdToken tk, ConstArray* pMarshalInfo); + static FCDECL3(HRESULT, GetSigOfMethodDef, IMDInternalImport* pScope, mdToken tk, ConstArray* pMarshalInfo); + static FCDECL3(HRESULT, GetFieldMarshal, IMDInternalImport* pScope, mdToken tk, ConstArray* pMarshalInfo); + static FCDECL2(FC_BOOL_RET, IsValidToken, IMDInternalImport* pScope, mdToken tk); + + static FCDECL11(FC_BOOL_RET, GetMarshalAs, + BYTE* pvNativeType, + ULONG cbNativeType, + INT32* unmanagedType, + INT32* safeArraySubType, + LPUTF8* safeArrayUserDefinedSubType, + INT32* arraySubType, + INT32* sizeParamIndex, + INT32* sizeConst, + LPUTF8* marshalType, + LPUTF8* marshalCookie, + INT32* iidParamIndex); }; +extern "C" void QCALLTYPE MetadataImport_Enum( + IMDInternalImport* pScope, + mdToken type, + mdToken tkParent, + INT32* length, + INT32* shortResult, + QCall::ObjectHandleOnStack longResult); + #endif diff --git a/src/coreclr/vm/marshalnative.cpp b/src/coreclr/vm/marshalnative.cpp index 40fc30849c3b..a71ec7d00c49 100644 --- a/src/coreclr/vm/marshalnative.cpp +++ b/src/coreclr/vm/marshalnative.cpp @@ -104,7 +104,7 @@ extern "C" BOOL QCALLTYPE MarshalNative_TryGetStructMarshalStub(void* enregister if (th.IsBlittable()) { - *pStructMarshalStub = NULL; + *pStructMarshalStub = (PCODE)NULL; *pSize = th.GetMethodTable()->GetNativeSize(); ret = TRUE; } @@ -131,7 +131,7 @@ extern "C" BOOL QCALLTYPE MarshalNative_TryGetStructMarshalStub(void* enregister } else { - *pStructMarshalStub = NULL; + *pStructMarshalStub = (PCODE)NULL; *pSize = 0; } @@ -536,6 +536,33 @@ extern "C" IDispatch* QCALLTYPE MarshalNative_GetIDispatchForObject(QCall::Objec return retVal; } +//==================================================================== +// return the IUnknown* or IDispatch* for an Object. +//==================================================================== +extern "C" void* QCALLTYPE MarshalNative_GetIUnknownOrIDispatchForObject(QCall::ObjectHandleOnStack o, BOOL* isIDispatch) +{ + QCALL_CONTRACT; + + void* retVal = NULL; + + BEGIN_QCALL; + + // Ensure COM is started up. + EnsureComStarted(); + + GCX_COOP(); + + OBJECTREF oref = o.Get(); + GCPROTECT_BEGIN(oref); + ComIpType fetchedIpType = ComIpType_None; + retVal = GetComIPFromObjectRef(&oref, ComIpType_Both, &fetchedIpType); + *isIDispatch = fetchedIpType == ComIpType_Dispatch; + GCPROTECT_END(); + + END_QCALL; + return retVal; +} + //==================================================================== // return the IUnknown* representing the interface for the Object // Object o should support Type T diff --git a/src/coreclr/vm/marshalnative.h b/src/coreclr/vm/marshalnative.h index f88b689baa5a..ed9f67c0dc50 100644 --- a/src/coreclr/vm/marshalnative.h +++ b/src/coreclr/vm/marshalnative.h @@ -77,6 +77,11 @@ extern "C" IUnknown* QCALLTYPE MarshalNative_GetIUnknownForObject(QCall::ObjectH //==================================================================== extern "C" IDispatch* QCALLTYPE MarshalNative_GetIDispatchForObject(QCall::ObjectHandleOnStack o); +//==================================================================== +// return the IUnknown* or IDispatch* for an Object. +//==================================================================== +extern "C" void* QCALLTYPE MarshalNative_GetIUnknownOrIDispatchForObject(QCall::ObjectHandleOnStack o, BOOL* isIDispatch); + //==================================================================== // return the IUnknown* representing the interface for the Object // Object o should support Type T diff --git a/src/coreclr/vm/memberload.cpp b/src/coreclr/vm/memberload.cpp index 83a062f8f182..83d662568d91 100644 --- a/src/coreclr/vm/memberload.cpp +++ b/src/coreclr/vm/memberload.cpp @@ -153,7 +153,7 @@ void MemberLoader::GetDescFromMemberRef(ModuleBase * pModule, BOOL fIsMethod; TADDR pDatum = pModule->LookupMemberRef(MemberRef, &fIsMethod); - if (pDatum != NULL) + if (pDatum != (TADDR)NULL) { if (!fIsMethod) { @@ -190,7 +190,7 @@ void MemberLoader::GetDescFromMemberRef(ModuleBase * pModule, if (TypeFromToken(parent) == mdtMethodDef) { // Return now if actualTypeRequired was set and the desc was cached - if (pDatum != NULL) + if (pDatum != (TADDR)NULL) { *ppTH = dac_cast(pDatum)->GetMethodTable(); return; @@ -329,7 +329,7 @@ void MemberLoader::GetDescFromMemberRef(ModuleBase * pModule, } // Return now if actualTypeRequired was set and the desc was cached - if (pDatum != NULL) + if (pDatum != (TADDR)NULL) { *ppTH = typeHnd; return; diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index 7ab9d6015e03..35e6472b4b8d 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -259,6 +259,8 @@ DEFINE_METASIG(SM(Flt_RetFlt, f, f)) DEFINE_METASIG(SM(Dbl_RetDbl, d, d)) DEFINE_METASIG(SM(RefDbl_Dbl_RetDbl, r(d) d, d)) DEFINE_METASIG(SM(RefDbl_Dbl_Dbl_RetDbl, r(d) d d, d)) +DEFINE_METASIG(SM(Long_Long_RetLong, l l, l)) +DEFINE_METASIG(SM(ULong_ULong_RetULong, L L, L)) DEFINE_METASIG(SM(RefLong_Long_RetLong, r(l) l, l)) DEFINE_METASIG(SM(RefLong_Long_Long_RetLong, r(l) l l, l)) DEFINE_METASIG(SM(RefFlt_Flt_RetFlt, r(f) f, f)) diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index 66296c4e06e1..474a7f5b4b09 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -120,10 +120,10 @@ SIZE_T MethodDesc::SizeOf() LIMITED_METHOD_DAC_CONTRACT; SIZE_T size = s_ClassificationSizeTable[m_wFlags & - (mdcClassification - | mdcHasNonVtableSlot - | mdcMethodImpl - | mdcHasNativeCodeSlot)]; + (mdfClassification + | mdfHasNonVtableSlot + | mdfMethodImpl + | mdfHasNativeCodeSlot)]; return size; } @@ -209,8 +209,55 @@ LoaderAllocator * MethodDesc::GetDomainSpecificLoaderAllocator() } +HRESULT MethodDesc::EnsureCodeDataExists() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (m_codeData != NULL) + return S_OK; + + LoaderHeap* heap = GetLoaderAllocator()->GetHighFrequencyHeap(); + + AllocMemTracker amTracker; + MethodDescCodeData* alloc = (MethodDescCodeData*)amTracker.Track_NoThrow(heap->AllocMem_NoThrow(S_SIZE_T(sizeof(MethodDescCodeData)))); + if (alloc == NULL) + return E_OUTOFMEMORY; + + // Try to set the field. Suppress clean-up if we win the race. + if (InterlockedCompareExchangeT(&m_codeData, (MethodDescCodeData*)alloc, NULL) == NULL) + amTracker.SuppressRelease(); + + return S_OK; +} + +HRESULT MethodDesc::SetMethodDescVersionState(PTR_MethodDescVersioningState state) +{ + WRAPPER_NO_CONTRACT; + + HRESULT hr; + IfFailRet(EnsureCodeDataExists()); + + _ASSERTE(m_codeData != NULL); + if (InterlockedCompareExchangeT(&m_codeData->VersioningState, state, NULL) != NULL) + return S_FALSE; + + return S_OK; +} + #endif //!DACCESS_COMPILE +PTR_MethodDescVersioningState MethodDesc::GetMethodDescVersionState() +{ + WRAPPER_NO_CONTRACT; + if (m_codeData == NULL) + return NULL; + return m_codeData->VersioningState; +} //******************************************************************************* LPCUTF8 MethodDesc::GetNameThrowing() @@ -902,7 +949,7 @@ PCODE MethodDesc::GetNativeCode() } if (!HasStableEntryPoint() || HasPrecode()) - return NULL; + return (PCODE)NULL; return GetStableEntryPoint(); } @@ -913,7 +960,7 @@ PCODE MethodDesc::GetNativeCodeAnyVersion() SUPPORTS_DAC; PCODE pDefaultCode = GetNativeCode(); - if (pDefaultCode != NULL) + if (pDefaultCode != (PCODE)NULL) { return pDefaultCode; } @@ -929,13 +976,13 @@ PCODE MethodDesc::GetNativeCodeAnyVersion() for (NativeCodeVersionIterator curNative = nativeCollection.Begin(), endNative = nativeCollection.End(); curNative != endNative; curNative++) { PCODE native = curNative->GetNativeCode(); - if(native != NULL) + if(native != (PCODE)NULL) { return native; } } } - return NULL; + return (PCODE)NULL; } } @@ -946,7 +993,7 @@ PTR_PCODE MethodDesc::GetAddrOfNativeCodeSlot() _ASSERTE(HasNativeCodeSlot()); - SIZE_T size = s_ClassificationSizeTable[m_wFlags & (mdcClassification | mdcHasNonVtableSlot | mdcMethodImpl)]; + SIZE_T size = s_ClassificationSizeTable[m_wFlags & (mdfClassification | mdfHasNonVtableSlot | mdfMethodImpl)]; return (PTR_PCODE)(dac_cast(this) + size); } @@ -1049,7 +1096,7 @@ COR_ILMETHOD* MethodDesc::GetILHeader() // Always pickup overrides like reflection emit, EnC, etc. TADDR pIL = pModule->GetDynamicIL(GetMemberDef()); - if (pIL == NULL) + if (pIL == (TADDR)NULL) { pIL = pModule->GetIL(GetRVA()); } @@ -1069,7 +1116,7 @@ COR_ILMETHOD* MethodDesc::GetILHeader() #endif #ifdef DACCESS_COMPILE - return (pIL != NULL) ? DacGetIlMethod(pIL) : NULL; + return (pIL != (TADDR)NULL) ? DacGetIlMethod(pIL) : NULL; #else // !DACCESS_COMPILE return PTR_COR_ILMETHOD(pIL); #endif // !DACCESS_COMPILE @@ -1915,7 +1962,7 @@ PCODE MethodDesc::GetMultiCallableAddrOfCode(CORINFO_ACCESS_FLAGS accessFlags /* PCODE ret = TryGetMultiCallableAddrOfCode(accessFlags); - if (ret == NULL) + if (ret == (PCODE)NULL) { GCX_COOP(); @@ -2023,7 +2070,7 @@ PCODE MethodDesc::TryGetMultiCallableAddrOfCode(CORINFO_ACCESS_FLAGS accessFlags if (IsVersionableWithVtableSlotBackpatch()) { // Caller has to call via slot or allocate funcptr stub - return NULL; + return (PCODE)NULL; } // Force the creation of the precode if we would eventually got one anyway @@ -2210,7 +2257,7 @@ void MethodDesc::Reset() if (HasNativeCodeSlot()) { - *GetAddrOfNativeCodeSlot() = NULL; + *GetAddrOfNativeCodeSlot() = (PCODE)NULL; } _ASSERTE(!HasNativeCode()); } @@ -2252,7 +2299,7 @@ MethodImpl *MethodDesc::GetMethodImpl() } CONTRACTL_END - SIZE_T size = s_ClassificationSizeTable[m_wFlags & (mdcClassification | mdcHasNonVtableSlot)]; + SIZE_T size = s_ClassificationSizeTable[m_wFlags & (mdfClassification | mdfHasNonVtableSlot)]; return PTR_MethodImpl(dac_cast(this) + size); } @@ -3253,7 +3300,7 @@ void MethodDesc::ResetCodeEntryPointForEnC() PCODE pCode = *ppCode; LOG((LF_CORDB, LL_INFO1000000, "MD::RCEPFENC: %p -> %p\n", ppCode, pCode)); - *ppCode = NULL; + *ppCode = (PCODE)NULL; } } diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index f7f98b9f7331..06ceb7357a23 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -35,7 +35,6 @@ class Dictionary; class GCCoverageInfo; class DynamicMethodDesc; class ReJitManager; -class CodeVersionManager; class PrepareCodeConfig; typedef DPTR(FCallMethodDesc) PTR_FCallMethodDesc; @@ -101,15 +100,6 @@ enum MethodClassification // for both shared and unshared code (see InstantiatedMethodDesc) #ifdef FEATURE_COMINTEROP - // This needs a little explanation. There are MethodDescs on MethodTables - // which are Interfaces. These have the mdcInterface bit set. Then there - // are MethodDescs on MethodTables that are Classes, where the method is - // exposed through an interface. These do not have the mdcInterface bit set. - // - // So, today, a dispatch through an 'mdcInterface' MethodDesc is either an - // error (someone forgot to look up the method in a class' VTable) or it is - // a case of COM Interop. - mcComInterop = 6, #endif // FEATURE_COMINTEROP mcDynamic = 7, // for method desc with no metadata behind @@ -119,57 +109,63 @@ enum MethodClassification // All flags in the MethodDesc now reside in a single 16-bit field. -enum MethodDescClassification +enum MethodDescFlags { // Method is IL, FCall etc., see MethodClassification above. - mdcClassification = 0x0007, - mdcClassificationCount = mdcClassification+1, + mdfClassification = 0x0007, + mdfClassificationCount = mdfClassification+1, // Note that layout of code:MethodDesc::s_ClassificationSizeTable depends on the exact values - // of mdcHasNonVtableSlot and mdcMethodImpl + // of mdfHasNonVtableSlot and mdfMethodImpl // Has local slot (vs. has real slot in MethodTable) - mdcHasNonVtableSlot = 0x0008, + mdfHasNonVtableSlot = 0x0008, // Method is a body for a method impl (MI_MethodDesc, MI_NDirectMethodDesc, etc) // where the function explicitly implements IInterface.foo() instead of foo(). - mdcMethodImpl = 0x0010, + mdfMethodImpl = 0x0010, // Has slot for native code - mdcHasNativeCodeSlot = 0x0020, + mdfHasNativeCodeSlot = 0x0020, // Method was added via Edit And Continue - mdcEnCAddedMethod = 0x0040, + mdfEnCAddedMethod = 0x0040, // Method is static - mdcStatic = 0x0080, + mdfStatic = 0x0080, - mdcValueTypeParametersWalked = 0x0100, // Indicates that all typeref's in the signature of the method have been resolved + mdfValueTypeParametersWalked = 0x0100, // Indicates that all typeref's in the signature of the method have been resolved // to typedefs (or that process failed). - mdcValueTypeParametersLoaded = 0x0200, // Indicates if the valuetype parameter types have been loaded. + mdfValueTypeParametersLoaded = 0x0200, // Indicates if the valuetype parameter types have been loaded. // Duplicate method. When a method needs to be placed in multiple slots in the // method table, because it could not be packed into one slot. For eg, a method // providing implementation for two interfaces, MethodImpl, etc - mdcDuplicate = 0x0400, + mdfDuplicate = 0x0400, - mdcDoesNotHaveEquivalentValuetypeParameters = 0x0800, // Indicates that we have verified that there are no equivalent valuetype parameters + mdfDoesNotHaveEquivalentValuetypeParameters = 0x0800, // Indicates that we have verified that there are no equivalent valuetype parameters // for this method. - mdcRequiresCovariantReturnTypeChecking = 0x1000, + mdfRequiresCovariantReturnTypeChecking = 0x1000, // Is this method ineligible for inlining? - mdcNotInline = 0x2000, + mdfNotInline = 0x2000, // Is the method synchronized - mdcSynchronized = 0x4000, + mdfSynchronized = 0x4000, - mdcIsIntrinsic = 0x8000 // Jit may expand method as an intrinsic + mdfIsIntrinsic = 0x8000 // Jit may expand method as an intrinsic }; -#define METHOD_MAX_RVA 0x7FFFFFFF +// Used for storing additional items related to native code +struct MethodDescCodeData final +{ + PTR_MethodDescVersioningState VersioningState; + // [TODO] Move temporary entry points here. +}; +using PTR_MethodDescCodeData = DPTR(MethodDescCodeData); // The size of this structure needs to be a multiple of MethodDesc::ALIGNMENT // @@ -189,18 +185,6 @@ enum MethodDescClassification // It also knows how to get at its IL code (code:IMAGE_COR_ILMETHOD) class MethodDesc { - friend class EEClass; - friend class MethodTableBuilder; - friend class ArrayClass; - friend class NDirect; - friend class MethodDescChunk; - friend class InstantiatedMethodDesc; - friend class MethodImpl; - friend class CheckAsmOffsets; - friend class ClrDataAccess; - - friend class MethodDescCallSite; - public: #ifdef TARGET_64BIT @@ -211,20 +195,6 @@ class MethodDesc static const size_t ALIGNMENT = (1 << ALIGNMENT_SHIFT); static const size_t ALIGNMENT_MASK = (ALIGNMENT - 1); -#ifdef _DEBUG - - // These are set only for MethodDescs but every time we want to use the debugger - // to examine these fields, the code has the thing stored in a MethodDesc*. - // So... - LPCUTF8 m_pszDebugMethodName; - LPCUTF8 m_pszDebugClassName; - LPCUTF8 m_pszDebugMethodSignature; - PTR_MethodTable m_pDebugMethodTable; - - PTR_GCCoverageInfo m_GcCover; - -#endif // _DEBUG - inline BOOL HasStableEntryPoint() { LIMITED_METHOD_DAC_CONTRACT; @@ -390,13 +360,13 @@ class MethodDesc inline void SetHasMethodImplSlot() { - m_wFlags |= mdcMethodImpl; + m_wFlags |= mdfMethodImpl; } inline BOOL HasMethodImplSlot() { LIMITED_METHOD_DAC_CONTRACT; - return (mdcMethodImpl & m_wFlags); + return (mdfMethodImpl & m_wFlags); } FORCEINLINE BOOL IsMethodImpl() @@ -415,21 +385,21 @@ class MethodDesc // accesses metadata that is not compatible with contracts of this method. The metadata access can fail, the metadata // are not available during shutdown, the metadata access can take locks. It is not worth it to code around all these // just for the assert. - // _ASSERTE((((m_wFlags & mdcStatic) != 0) == (IsMdStatic(flags) != 0))); + // _ASSERTE((((m_wFlags & mdfStatic) != 0) == (IsMdStatic(flags) != 0))); - return (m_wFlags & mdcStatic) != 0; + return (m_wFlags & mdfStatic) != 0; } inline void SetStatic() { LIMITED_METHOD_CONTRACT; - m_wFlags |= mdcStatic; + m_wFlags |= mdfStatic; } inline void ClearStatic() { LIMITED_METHOD_CONTRACT; - m_wFlags &= ~mdcStatic; + m_wFlags &= ~mdfStatic; } inline BOOL IsIL() @@ -662,13 +632,13 @@ class MethodDesc inline BOOL IsNotInline() { LIMITED_METHOD_CONTRACT; - return (m_wFlags & mdcNotInline); + return (m_wFlags & mdfNotInline); } inline void SetNotInline(BOOL set) { WRAPPER_NO_CONTRACT; - InterlockedUpdateFlags(mdcNotInline, set); + InterlockedUpdateFlags(mdfNotInline, set); } #ifndef DACCESS_COMPILE @@ -897,13 +867,13 @@ class MethodDesc inline void SetSynchronized() { LIMITED_METHOD_CONTRACT; - m_wFlags |= mdcSynchronized; + m_wFlags |= mdfSynchronized; } inline DWORD IsSynchronized() { LIMITED_METHOD_DAC_CONTRACT; - return (m_wFlags & mdcSynchronized) != 0; + return (m_wFlags & mdfSynchronized) != 0; } //================================================================== @@ -942,14 +912,14 @@ class MethodDesc void SetHasNonVtableSlot() { LIMITED_METHOD_CONTRACT; - m_wFlags |= mdcHasNonVtableSlot; + m_wFlags |= mdfHasNonVtableSlot; } // duplicate methods inline BOOL IsDuplicate() { LIMITED_METHOD_CONTRACT; - return (m_wFlags & mdcDuplicate) == mdcDuplicate; + return (m_wFlags & mdfDuplicate) == mdfDuplicate; } void SetDuplicate() @@ -957,7 +927,7 @@ class MethodDesc LIMITED_METHOD_CONTRACT; // method table is not setup yet //_ASSERTE(!GetClass()->IsInterface()); - m_wFlags |= mdcDuplicate; + m_wFlags |= mdfDuplicate; } //================================================================== @@ -1368,7 +1338,7 @@ class MethodDesc { LIMITED_METHOD_DAC_CONTRACT; - return GetNativeCode() != NULL; + return GetNativeCode() != (PCODE)0; } // Perf warning: takes the CodeVersionManagerLock on every call @@ -1376,10 +1346,10 @@ class MethodDesc { LIMITED_METHOD_DAC_CONTRACT; - return GetNativeCodeAnyVersion() != NULL; + return GetNativeCodeAnyVersion() != (PCODE)0; } - BOOL SetNativeCodeInterlocked(PCODE addr, PCODE pExpected = NULL); + BOOL SetNativeCodeInterlocked(PCODE addr, PCODE pExpected = 0); PTR_PCODE GetAddrOfNativeCodeSlot(); @@ -1616,6 +1586,20 @@ class MethodDesc //================================================================ // The actual data stored in a MethodDesc follows. +#ifdef _DEBUG +public: + // These are set only for MethodDescs but every time we want to use the debugger + // to examine these fields, the code has the thing stored in a MethodDesc*. + // So... + LPCUTF8 m_pszDebugMethodName; + LPCUTF8 m_pszDebugClassName; + LPCUTF8 m_pszDebugMethodSignature; + PTR_MethodTable m_pDebugMethodTable; + + PTR_GCCoverageInfo m_GcCover; + +#endif // _DEBUG + protected: enum { // There are flags available for use here (currently 4 flags bits are available); however, new bits are hard to come by, so any new flags bits should @@ -1634,9 +1618,9 @@ class MethodDesc BYTE m_chunkIndex; BYTE m_methodIndex; // Used to hold the index into the chunk of this MethodDesc. Currently all 8 bits are used, but we could likely work with only 7 bits - // The slot number of this MethodDesc in the vtable array. - WORD m_wSlotNumber; - WORD m_wFlags; + WORD m_wSlotNumber; // The slot number of this MethodDesc in the vtable array. + WORD m_wFlags; // See MethodDescFlags + PTR_MethodDescCodeData m_codeData; public: #ifdef DACCESS_COMPILE @@ -1645,53 +1629,63 @@ class MethodDesc BYTE GetMethodDescIndex() { + LIMITED_METHOD_CONTRACT; return m_methodIndex; } void SetMethodDescIndex(COUNT_T index) { + LIMITED_METHOD_CONTRACT; _ASSERTE(index <= 255); m_methodIndex = (BYTE)index; } +#ifndef DACCESS_COMPILE + HRESULT EnsureCodeDataExists(); + + HRESULT SetMethodDescVersionState(PTR_MethodDescVersioningState state); +#endif //!DACCESS_COMPILE + + PTR_MethodDescVersioningState GetMethodDescVersionState(); + public: inline DWORD GetClassification() const { LIMITED_METHOD_DAC_CONTRACT; - return (m_wFlags & mdcClassification); + return (m_wFlags & mdfClassification); } inline void SetClassification(DWORD classification) { LIMITED_METHOD_CONTRACT; - _ASSERTE((m_wFlags & mdcClassification) == 0); + _ASSERTE((m_wFlags & mdfClassification) == 0); m_wFlags |= classification; } inline BOOL HasNativeCodeSlot() { LIMITED_METHOD_DAC_CONTRACT; - return (m_wFlags & mdcHasNativeCodeSlot) != 0; + return (m_wFlags & mdfHasNativeCodeSlot) != 0; } inline void SetHasNativeCodeSlot() { LIMITED_METHOD_CONTRACT; - m_wFlags |= mdcHasNativeCodeSlot; + m_wFlags |= mdfHasNativeCodeSlot; } #ifdef FEATURE_METADATA_UPDATER inline BOOL IsEnCAddedMethod() { LIMITED_METHOD_DAC_CONTRACT; - return (m_wFlags & mdcEnCAddedMethod) != 0; + return (m_wFlags & mdfEnCAddedMethod) != 0; } inline void SetIsEnCAddedMethod() { LIMITED_METHOD_CONTRACT; - m_wFlags |= mdcEnCAddedMethod; + m_wFlags |= mdfEnCAddedMethod; } #else inline BOOL IsEnCAddedMethod() @@ -1704,26 +1698,26 @@ class MethodDesc inline BOOL IsIntrinsic() { LIMITED_METHOD_DAC_CONTRACT; - return (m_wFlags & mdcIsIntrinsic) != 0; + return (m_wFlags & mdfIsIntrinsic) != 0; } inline void SetIsIntrinsic() { LIMITED_METHOD_CONTRACT; - m_wFlags |= mdcIsIntrinsic; + m_wFlags |= mdfIsIntrinsic; } BOOL RequiresCovariantReturnTypeChecking() { LIMITED_METHOD_DAC_CONTRACT; - return (m_wFlags & mdcRequiresCovariantReturnTypeChecking) != 0; + return (m_wFlags & mdfRequiresCovariantReturnTypeChecking) != 0; } void SetRequiresCovariantReturnTypeChecking() { LIMITED_METHOD_CONTRACT; - m_wFlags |= mdcRequiresCovariantReturnTypeChecking; + m_wFlags |= mdfRequiresCovariantReturnTypeChecking; } static const BYTE s_ClassificationSizeTable[]; @@ -1731,7 +1725,7 @@ class MethodDesc static SIZE_T GetBaseSize(DWORD classification) { LIMITED_METHOD_DAC_CONTRACT; - _ASSERTE(classification < mdcClassificationCount); + _ASSERTE(classification < mdfClassificationCount); return s_ClassificationSizeTable[classification]; } @@ -1748,38 +1742,38 @@ class MethodDesc inline BOOL HaveValueTypeParametersBeenWalked() { LIMITED_METHOD_DAC_CONTRACT; - return (m_wFlags & mdcValueTypeParametersWalked) != 0; + return (m_wFlags & mdfValueTypeParametersWalked) != 0; } inline void SetValueTypeParametersWalked() { LIMITED_METHOD_CONTRACT; - InterlockedUpdateFlags(mdcValueTypeParametersWalked, TRUE); + InterlockedUpdateFlags(mdfValueTypeParametersWalked, TRUE); } inline BOOL HaveValueTypeParametersBeenLoaded() { LIMITED_METHOD_DAC_CONTRACT; - return (m_wFlags & mdcValueTypeParametersLoaded) != 0; + return (m_wFlags & mdfValueTypeParametersLoaded) != 0; } inline void SetValueTypeParametersLoaded() { LIMITED_METHOD_CONTRACT; - InterlockedUpdateFlags(mdcValueTypeParametersLoaded, TRUE); + InterlockedUpdateFlags(mdfValueTypeParametersLoaded, TRUE); } #ifdef FEATURE_TYPEEQUIVALENCE inline BOOL DoesNotHaveEquivalentValuetypeParameters() { LIMITED_METHOD_DAC_CONTRACT; - return (m_wFlags & mdcDoesNotHaveEquivalentValuetypeParameters) != 0; + return (m_wFlags & mdfDoesNotHaveEquivalentValuetypeParameters) != 0; } inline void SetDoesNotHaveEquivalentValuetypeParameters() { LIMITED_METHOD_CONTRACT; - InterlockedUpdateFlags(mdcDoesNotHaveEquivalentValuetypeParameters, TRUE); + InterlockedUpdateFlags(mdfDoesNotHaveEquivalentValuetypeParameters, TRUE); } #endif // FEATURE_TYPEEQUIVALENCE @@ -2121,7 +2115,6 @@ class MulticoreJitPrepareCodeConfig : public PrepareCodeConfig class MethodDescChunk { friend class MethodDesc; - friend class CheckAsmOffsets; enum { enum_flag_TokenRangeMask = 0x0FFF, // This must equal METHOD_TOKEN_RANGE_MASK calculated higher in this file @@ -2162,7 +2155,7 @@ class MethodDescChunk } CONTRACTL_END; - if (GetTemporaryEntryPoints() == NULL) + if (GetTemporaryEntryPoints() == (TADDR)0) CreateTemporaryEntryPoints(pLoaderAllocator, pamTracker); } @@ -2356,7 +2349,7 @@ class StoredSigMethodDesc : public MethodDesc bool HasStoredMethodSig(void) { LIMITED_METHOD_DAC_CONTRACT; - return m_pSig != NULL; + return m_pSig != 0; } PCCOR_SIGNATURE GetStoredMethodSig(DWORD* sigLen = NULL) { @@ -2424,9 +2417,7 @@ typedef DPTR(DynamicResolver) PTR_DynamicResolver; class DynamicMethodDesc : public StoredSigMethodDesc { friend class ILStubCache; - friend class ILStubState; friend class DynamicMethodTable; - friend class MethodDesc; protected: PTR_CUTF8 m_pszMethodName; @@ -3493,7 +3484,7 @@ inline BOOL MethodDesc::HasNonVtableSlot() { LIMITED_METHOD_DAC_CONTRACT; - return (m_wFlags & mdcHasNonVtableSlot) != 0; + return (m_wFlags & mdfHasNonVtableSlot) != 0; } inline Instantiation MethodDesc::GetMethodInstantiation() const diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index 67903433833b..51b7d3b1d381 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -1931,7 +1931,7 @@ MethodDesc *MethodTable::GetMethodDescForInterfaceMethod(TypeHandle ownerType, M PCODE pTgt = VirtualCallStubManager::GetTarget( pInterfaceMT->GetLoaderAllocator()->GetDispatchToken(pInterfaceMT->GetTypeID(), pInterfaceMD->GetSlot()), this, throwOnConflict); - if (pTgt == NULL) + if (pTgt == (PCODE)NULL) { _ASSERTE(!throwOnConflict); return NULL; @@ -2085,6 +2085,11 @@ namespace } DWORD numIntroducedFields = pMT->GetNumIntroducedInstanceFields(); + if (numIntroducedFields != 1) + { + return false; + } + FieldDesc *pFieldStart = pMT->GetApproxFieldDescListRaw(); CorElementType firstFieldElementType = pFieldStart->GetFieldType(); @@ -2095,8 +2100,7 @@ namespace // instead of adding additional padding at the end of a one-field structure. // We do this check here to save looking up the FixedBufferAttribute when loading the field // from metadata. - return numIntroducedFields == 1 - && ( CorTypeInfo::IsPrimitiveType_NoThrow(firstFieldElementType) + return (CorTypeInfo::IsPrimitiveType_NoThrow(firstFieldElementType) || firstFieldElementType == ELEMENT_TYPE_VALUETYPE) && (pFieldStart->GetOffset() == 0) && pMT->HasLayout() @@ -2809,1179 +2813,191 @@ void MethodTable::AssignClassifiedEightByteTypes(SystemVStructRegisterPassingHe #endif // defined(UNIX_AMD64_ABI_ITF) -#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) -bool MethodTable::IsOnlyOneField(MethodTable * pMT) +#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) +static bool HandleInlineArray(int elementTypeIndex, int nElements, StructFloatFieldInfoFlags types[2], int& typeIndex) { - TypeHandle th(pMT); + int nFlattenedFieldsPerElement = typeIndex - elementTypeIndex; + if (nFlattenedFieldsPerElement == 0) + return true; + + assert(nFlattenedFieldsPerElement == 1 || nFlattenedFieldsPerElement == 2); - bool ret = false; + if (nElements > 2) + return false; - if (!th.IsTypeDesc()) + if (nElements == 2) { - MethodTable* pMethodTable = th.AsMethodTable(); - if (th.GetSize() <= 16 /*MAX_PASS_MULTIREG_BYTES*/) - { - DWORD numIntroducedFields = pMethodTable->GetNumIntroducedInstanceFields(); + if (typeIndex + nFlattenedFieldsPerElement > 2) + return false; - if (numIntroducedFields == 1) - { - FieldDesc *pFieldStart = pMethodTable->GetApproxFieldDescListRaw(); + assert(elementTypeIndex == 0); + assert(typeIndex == 1); + types[typeIndex] = types[elementTypeIndex]; // duplicate the array element type + } + return true; +} - CorElementType fieldType = pFieldStart[0].GetFieldType(); +static bool FlattenFieldTypes(TypeHandle th, StructFloatFieldInfoFlags types[2], int& typeIndex) +{ + bool isManaged = !th.IsTypeDesc(); + MethodTable* pMT = isManaged ? th.AsMethodTable() : th.AsNativeValueType(); + int nFields = isManaged ? pMT->GetNumIntroducedInstanceFields() : pMT->GetNativeLayoutInfo()->GetNumFields(); - // InlineArray types and fixed buffer types have implied repeated fields. - // Checking if a type is an InlineArray type is cheap, so we'll do that first. - bool hasImpliedRepeatedFields = HasImpliedRepeatedFields(pMethodTable); + // TODO: templatize isManaged and use if constexpr for differences when we migrate to C++17 + // because the logic for both branches is nearly the same. + if (isManaged) + { + FieldDesc* fields = pMT->GetApproxFieldDescListRaw(); + int elementTypeIndex = typeIndex; + for (int i = 0; i < nFields; ++i) + { + if (i > 0 && fields[i-1].GetOffset() + fields[i-1].GetSize() > fields[i].GetOffset()) + return false; // overlapping fields - if (hasImpliedRepeatedFields) - { - numIntroducedFields = pMethodTable->GetNumInstanceFieldBytes() / pFieldStart->GetSize(); - if (numIntroducedFields != 1) - { - goto _End_arg; - } - } + CorElementType type = fields[i].GetFieldType(); + if (type == ELEMENT_TYPE_VALUETYPE) + { + MethodTable* nested = fields[i].GetApproxFieldTypeHandleThrowing().GetMethodTable(); + if (!FlattenFieldTypes(TypeHandle(nested), types, typeIndex)) + return false; + } + else if (fields[i].GetSize() <= TARGET_POINTER_SIZE) + { + if (typeIndex >= 2) + return false; - if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - ret = true; - } - else if (fieldType == ELEMENT_TYPE_VALUETYPE) - { - pMethodTable = pFieldStart->GetApproxFieldTypeHandleThrowing().GetMethodTable(); - if (pMethodTable->GetNumIntroducedInstanceFields() == 1) - { - ret = IsOnlyOneField(pMethodTable); - } - } + StructFloatFieldInfoFlags retType = StructFloatFieldInfoFlags( + (CorTypeInfo::IsFloat_NoThrow(type) ? STRUCT_FLOAT_FIELD_FIRST : 0) | + (CorTypeInfo::Size_NoThrow(type) == TARGET_POINTER_SIZE ? STRUCT_FIRST_FIELD_SIZE_IS8 : 0)); + types[typeIndex++] = retType; + } + else + { + return false; } } + + if (HasImpliedRepeatedFields(pMT)) // inline array or fixed buffer + { + assert(nFields == 1); + int nElements = pMT->GetNumInstanceFieldBytes() / fields[0].GetSize(); + if (!HandleInlineArray(elementTypeIndex, nElements, types, typeIndex)) + return false; + } } - else + else // native layout { - MethodTable* pMethodTable = th.AsNativeValueType(); - - if (th.GetSize() <= 16 /*MAX_PASS_MULTIREG_BYTES*/) + const NativeFieldDescriptor* fields = pMT->GetNativeLayoutInfo()->GetNativeFieldDescriptors(); + for (int i = 0; i < nFields; ++i) { - DWORD numIntroducedFields = pMethodTable->GetNativeLayoutInfo()->GetNumFields(); - FieldDesc *pFieldStart = nullptr; + if (i > 0 && fields[i-1].GetExternalOffset() + fields[i-1].NativeSize() > fields[i].GetExternalOffset()) + return false; // overlapping fields - if (numIntroducedFields == 1) + NativeFieldCategory category = fields[i].GetCategory(); + if (category == NativeFieldCategory::NESTED) { - pFieldStart = pMethodTable->GetApproxFieldDescListRaw(); - - CorElementType fieldType = pFieldStart->GetFieldType(); + int elementTypeIndex = typeIndex; - // InlineArray types and fixed buffer types have implied repeated fields. - // Checking if a type is an InlineArray type is cheap, so we'll do that first. - bool hasImpliedRepeatedFields = HasImpliedRepeatedFields(pMethodTable); + MethodTable* nested = fields[i].GetNestedNativeMethodTable(); + if (!FlattenFieldTypes(TypeHandle(nested), types, typeIndex)) + return false; - if (hasImpliedRepeatedFields) - { - numIntroducedFields = pMethodTable->GetNumInstanceFieldBytes() / pFieldStart->GetSize(); - if (numIntroducedFields != 1) - { - goto _End_arg; - } - } + // In native layout fixed arrays are marked as NESTED just like structs + int nElements = fields[i].GetNumElements(); + if (!HandleInlineArray(elementTypeIndex, nElements, types, typeIndex)) + return false; + } + else if (fields[i].NativeSize() <= TARGET_POINTER_SIZE) + { + if (typeIndex >= 2) + return false; - if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - ret = true; - } - else if (fieldType == ELEMENT_TYPE_VALUETYPE) - { - const NativeFieldDescriptor *pNativeFieldDescs = pMethodTable->GetNativeLayoutInfo()->GetNativeFieldDescriptors(); - NativeFieldCategory nfc = pNativeFieldDescs->GetCategory(); - if (nfc == NativeFieldCategory::NESTED) - { - pMethodTable = pNativeFieldDescs->GetNestedNativeMethodTable(); - ret = IsOnlyOneField(pMethodTable); - } - else if (nfc != NativeFieldCategory::ILLEGAL) - { - ret = true; - } - } + StructFloatFieldInfoFlags type = StructFloatFieldInfoFlags( + (category == NativeFieldCategory::FLOAT ? STRUCT_FLOAT_FIELD_FIRST : 0) | + (fields[i].NativeSize() == TARGET_POINTER_SIZE ? STRUCT_FIRST_FIELD_SIZE_IS8 : 0)); + types[typeIndex++] = type; } else { - ret = false; + return false; } } } -_End_arg: - - return ret; + return true; } #endif #if defined(TARGET_LOONGARCH64) -int MethodTable::GetLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE cls) +int MethodTable::GetLoongArch64PassStructInRegisterFlags(TypeHandle th) { - TypeHandle th(cls); - - int size = STRUCT_NO_FLOAT_FIELD; + if (th.GetSize() > ENREGISTERED_PARAMTYPE_MAXSIZE) + return STRUCT_NO_FLOAT_FIELD; - if (!th.IsTypeDesc()) - { - MethodTable* pMethodTable = th.AsMethodTable(); - if (th.GetSize() <= 16 /*MAX_PASS_MULTIREG_BYTES*/) - { - DWORD numIntroducedFields = pMethodTable->GetNumIntroducedInstanceFields(); - - if (numIntroducedFields == 1) - { - FieldDesc *pFieldStart = pMethodTable->GetApproxFieldDescListRaw(); - - CorElementType fieldType = pFieldStart[0].GetFieldType(); - - // InlineArray types and fixed buffer types have implied repeated fields. - // Checking if a type is an InlineArray type is cheap, so we'll do that first. - bool hasImpliedRepeatedFields = HasImpliedRepeatedFields(pMethodTable); - - if (hasImpliedRepeatedFields) - { - numIntroducedFields = pMethodTable->GetNumInstanceFieldBytes() / pFieldStart->GetSize(); - if (numIntroducedFields > 2) - { - goto _End_arg; - } - - if (fieldType == ELEMENT_TYPE_R4) - { - if (numIntroducedFields == 1) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE; - } - else if (numIntroducedFields == 2) - { - size = STRUCT_FLOAT_FIELD_ONLY_TWO; - } - goto _End_arg; - } - else if (fieldType == ELEMENT_TYPE_R8) - { - if (numIntroducedFields == 1) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE | STRUCT_FIRST_FIELD_SIZE_IS8; - } - else if (numIntroducedFields == 2) - { - size = STRUCT_FIELD_TWO_DOUBLES; - } - goto _End_arg; - } - } - - if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - if (fieldType == ELEMENT_TYPE_R4) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE; - } - else if (fieldType == ELEMENT_TYPE_R8) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE | STRUCT_FIRST_FIELD_SIZE_IS8; - } - } - else if (fieldType == ELEMENT_TYPE_VALUETYPE) - { - pMethodTable = pFieldStart->GetApproxFieldTypeHandleThrowing().GetMethodTable(); - size = GetLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); - } - } - else if (numIntroducedFields == 2) - { - FieldDesc *pFieldSecond; - FieldDesc *pFieldFirst = pMethodTable->GetApproxFieldDescListRaw(); - if (pFieldFirst->GetOffset() == 0) - { - pFieldSecond = pFieldFirst + 1; - } - else - { - pFieldSecond = pFieldFirst; - pFieldFirst = pFieldFirst + 1; - } - assert(pFieldFirst->GetOffset() == 0); + StructFloatFieldInfoFlags types[2] = {STRUCT_NO_FLOAT_FIELD, STRUCT_NO_FLOAT_FIELD}; + int nFields = 0; + if (!FlattenFieldTypes(th, types, nFields) || nFields == 0) + return STRUCT_NO_FLOAT_FIELD; - if (pFieldFirst->GetSize() > 8) - { - goto _End_arg; - } - - if (pFieldFirst->GetSize() > pFieldSecond->GetOffset()) - { - goto _End_arg; - } + assert(nFields == 1 || nFields == 2); - CorElementType fieldType = pFieldFirst[0].GetFieldType(); - if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - if (fieldType == ELEMENT_TYPE_R4) - { - size = STRUCT_FLOAT_FIELD_FIRST; - } - else if (fieldType == ELEMENT_TYPE_R8) - { - size = STRUCT_FIRST_FIELD_DOUBLE; - } - else if (pFieldFirst[0].GetSize() == 8) - { - size = STRUCT_FIRST_FIELD_SIZE_IS8; - } + static_assert((STRUCT_FLOAT_FIELD_SECOND | STRUCT_SECOND_FIELD_SIZE_IS8) + == (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FIRST_FIELD_SIZE_IS8) << 1, + "SECOND flags need to be FIRST shifted by 1"); + int flags = types[0] | (types[1] << 1); - } - else if (fieldType == ELEMENT_TYPE_VALUETYPE) - { - pMethodTable = pFieldFirst->GetApproxFieldTypeHandleThrowing().GetMethodTable(); - if (IsOnlyOneField(pMethodTable)) - { - size = GetLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); - if ((size & STRUCT_FLOAT_FIELD_ONLY_ONE) != 0) - { - size = pFieldFirst[0].GetSize() == 8 ? STRUCT_FIRST_FIELD_DOUBLE : STRUCT_FLOAT_FIELD_FIRST; - } - else if (size == STRUCT_NO_FLOAT_FIELD) - { - size = pFieldFirst[0].GetSize() == 8 ? STRUCT_FIRST_FIELD_SIZE_IS8: 0; - } - else - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - } - else - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - } - else if (pFieldFirst[0].GetSize() == 8) - { - size = STRUCT_FIRST_FIELD_SIZE_IS8; - } + static const int bothFloat = STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_SECOND; + if ((flags & bothFloat) == 0) + return STRUCT_NO_FLOAT_FIELD; - fieldType = pFieldSecond[0].GetFieldType(); - if (pFieldSecond[0].GetSize() > 8) - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - else if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - if (fieldType == ELEMENT_TYPE_R4) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); - } - else if (fieldType == ELEMENT_TYPE_R8) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (pFieldSecond[0].GetSize() == 8) - { - size |= STRUCT_SECOND_FIELD_SIZE_IS8; - } - } - else if (fieldType == ELEMENT_TYPE_VALUETYPE) - { - pMethodTable = pFieldSecond[0].GetApproxFieldTypeHandleThrowing().GetMethodTable(); - if (IsOnlyOneField(pMethodTable)) - { - int size2 = GetLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); - if ((size2 & STRUCT_FLOAT_FIELD_ONLY_ONE) != 0) - { - if (pFieldSecond[0].GetSize() == 8) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); - } - else - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); - } - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (size2 == STRUCT_NO_FLOAT_FIELD) - { - size |= pFieldSecond[0].GetSize() == 8 ? STRUCT_SECOND_FIELD_SIZE_IS8 : 0; - } - else - { - size = STRUCT_NO_FLOAT_FIELD; - } - } - else - { - size = STRUCT_NO_FLOAT_FIELD; - } - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (pFieldSecond[0].GetSize() == 8) - { - size |= STRUCT_SECOND_FIELD_SIZE_IS8; - } - } - } + if ((flags & bothFloat) == bothFloat) + { + assert(nFields == 2); + flags ^= (bothFloat | STRUCT_FLOAT_FIELD_ONLY_TWO); // replace bothFloat with ONLY_TWO } - else + else if (nFields == 1) { - MethodTable* pMethodTable = th.AsNativeValueType(); - if (th.GetSize() <= 16 /*MAX_PASS_MULTIREG_BYTES*/) - { - DWORD numIntroducedFields = pMethodTable->GetNativeLayoutInfo()->GetNumFields(); - FieldDesc *pFieldStart = nullptr; - - if (numIntroducedFields == 1) - { - pFieldStart = pMethodTable->GetApproxFieldDescListRaw(); - - CorElementType fieldType = pFieldStart->GetFieldType(); - - // InlineArray types and fixed buffer types have implied repeated fields. - // Checking if a type is an InlineArray type is cheap, so we'll do that first. - bool hasImpliedRepeatedFields = HasImpliedRepeatedFields(pMethodTable); - - if (hasImpliedRepeatedFields) - { - numIntroducedFields = pMethodTable->GetNumInstanceFieldBytes() / pFieldStart->GetSize(); - if (numIntroducedFields > 2) - { - goto _End_arg; - } - - if (fieldType == ELEMENT_TYPE_R4) - { - if (numIntroducedFields == 1) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE; - } - else if (numIntroducedFields == 2) - { - size = STRUCT_FLOAT_FIELD_ONLY_TWO; - } - goto _End_arg; - } - else if (fieldType == ELEMENT_TYPE_R8) - { - if (numIntroducedFields == 1) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE | STRUCT_FIRST_FIELD_SIZE_IS8; - } - else if (numIntroducedFields == 2) - { - size = STRUCT_FIELD_TWO_DOUBLES; - } - goto _End_arg; - } - } - - if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - if (fieldType == ELEMENT_TYPE_R4) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE; - } - else if (fieldType == ELEMENT_TYPE_R8) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE | STRUCT_FIRST_FIELD_SIZE_IS8; - } - } - else if (fieldType == ELEMENT_TYPE_VALUETYPE) - { - const NativeFieldDescriptor *pNativeFieldDescs = pMethodTable->GetNativeLayoutInfo()->GetNativeFieldDescriptors(); - NativeFieldCategory nfc = pNativeFieldDescs->GetCategory(); - if (nfc == NativeFieldCategory::NESTED) - { - pMethodTable = pNativeFieldDescs->GetNestedNativeMethodTable(); - size = GetLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); - return size; - } - else if (nfc == NativeFieldCategory::FLOAT) - { - if (pFieldStart->GetSize() == 4) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE; - } - else if (pFieldStart->GetSize() == 8) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE | STRUCT_FIRST_FIELD_SIZE_IS8; - } - } - } - } - else if (numIntroducedFields == 2) - { - pFieldStart = pMethodTable->GetApproxFieldDescListRaw(); - - if (pFieldStart->GetSize() > 8) - { - goto _End_arg; - } - - if (pFieldStart->GetOffset() || !pFieldStart[1].GetOffset() || (pFieldStart[0].GetSize() > pFieldStart[1].GetOffset())) - { - goto _End_arg; - } + assert((flags & STRUCT_FLOAT_FIELD_FIRST) != 0); + flags ^= (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_ONLY_ONE); // replace FIRST with ONLY_ONE + } - CorElementType fieldType = pFieldStart[0].GetFieldType(); - if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - if (fieldType == ELEMENT_TYPE_R4) - { - size = STRUCT_FLOAT_FIELD_FIRST; - } - else if (fieldType == ELEMENT_TYPE_R8) - { - size = STRUCT_FIRST_FIELD_DOUBLE; - } - else if (pFieldStart[0].GetSize() == 8) - { - size = STRUCT_FIRST_FIELD_SIZE_IS8; - } + return flags; +} +#endif - fieldType = pFieldStart[1].GetFieldType(); - if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - if (fieldType == ELEMENT_TYPE_R4) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); - } - else if (fieldType == ELEMENT_TYPE_R8) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (pFieldStart[1].GetSize() == 8) - { - size |= STRUCT_SECOND_FIELD_SIZE_IS8; - } - goto _End_arg; - } - } - else if (fieldType == ELEMENT_TYPE_VALUETYPE) - { - const NativeFieldDescriptor *pNativeFieldDescs = pMethodTable->GetNativeLayoutInfo()->GetNativeFieldDescriptors(); +#if defined(TARGET_RISCV64) +int MethodTable::GetRiscV64PassStructInRegisterFlags(TypeHandle th) +{ + if (th.GetSize() > ENREGISTERED_PARAMTYPE_MAXSIZE) + return STRUCT_NO_FLOAT_FIELD; - NativeFieldCategory nfc = pNativeFieldDescs->GetCategory(); + StructFloatFieldInfoFlags types[2] = {STRUCT_NO_FLOAT_FIELD, STRUCT_NO_FLOAT_FIELD}; + int nFields = 0; + if (!FlattenFieldTypes(th, types, nFields) || nFields == 0) + return STRUCT_NO_FLOAT_FIELD; - if (nfc == NativeFieldCategory::NESTED) - { - if (pNativeFieldDescs->GetNumElements() != 1) - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } + assert(nFields == 1 || nFields == 2); - MethodTable* pMethodTable2 = pNativeFieldDescs->GetNestedNativeMethodTable(); + static_assert((STRUCT_FLOAT_FIELD_SECOND | STRUCT_SECOND_FIELD_SIZE_IS8) + == (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FIRST_FIELD_SIZE_IS8) << 1, + "SECOND flags need to be FIRST shifted by 1"); + int flags = types[0] | (types[1] << 1); - if (!IsOnlyOneField(pMethodTable2)) - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } + static const int bothFloat = STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_SECOND; + if ((flags & bothFloat) == 0) + return STRUCT_NO_FLOAT_FIELD; - size = GetLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable2); - if ((size & STRUCT_FLOAT_FIELD_ONLY_ONE) != 0) - { - if (pFieldStart->GetSize() == 8) - { - size = STRUCT_FIRST_FIELD_DOUBLE; - } - else - { - size = STRUCT_FLOAT_FIELD_FIRST; - } - } - else if (pFieldStart->GetSize() == 8) - { - size = STRUCT_FIRST_FIELD_SIZE_IS8; - } - else - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - } - else if (nfc == NativeFieldCategory::FLOAT) - { - if (pFieldStart[0].GetSize() == 4) - { - size = STRUCT_FLOAT_FIELD_FIRST; - } - else if (pFieldStart[0].GetSize() == 8) - { - _ASSERTE((pMethodTable->GetNativeSize() == 8) || (pMethodTable->GetNativeSize() == 16)); - size = STRUCT_FIRST_FIELD_DOUBLE; - } - } - else if (pFieldStart[0].GetSize() == 8) - { - size = STRUCT_FIRST_FIELD_SIZE_IS8; - } - } - else if (fieldType == ELEMENT_TYPE_CLASS) - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - else if (pFieldStart[0].GetSize() == 8) - { - size = STRUCT_FIRST_FIELD_SIZE_IS8; - } - - fieldType = pFieldStart[1].GetFieldType(); - if (pFieldStart[1].GetSize() > 8) - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - else if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - if (fieldType == ELEMENT_TYPE_R4) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); - } - else if (fieldType == ELEMENT_TYPE_R8) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (pFieldStart[1].GetSize() == 8) - { - size |= STRUCT_SECOND_FIELD_SIZE_IS8; - } - } - else if (fieldType == ELEMENT_TYPE_VALUETYPE) - { - const NativeFieldDescriptor *pNativeFieldDescs = pMethodTable->GetNativeLayoutInfo()->GetNativeFieldDescriptors(); - NativeFieldCategory nfc = pNativeFieldDescs[1].GetCategory(); - - if (nfc == NativeFieldCategory::NESTED) - { - if (pNativeFieldDescs[1].GetNumElements() != 1) - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - - MethodTable* pMethodTable2 = pNativeFieldDescs[1].GetNestedNativeMethodTable(); - - if (!IsOnlyOneField(pMethodTable2)) - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - - if ((GetLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable2) & STRUCT_FLOAT_FIELD_ONLY_ONE) != 0) - { - if (pFieldStart[1].GetSize() == 4) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); - } - else if (pFieldStart[1].GetSize() == 8) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); - } - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (pFieldStart[1].GetSize() == 8) - { - size |= STRUCT_SECOND_FIELD_SIZE_IS8; - } - } - else if (nfc == NativeFieldCategory::FLOAT) - { - if (pFieldStart[1].GetSize() == 4) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); - } - else if (pFieldStart[1].GetSize() == 8) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); - } - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (pFieldStart[1].GetSize() == 8) - { - size |= STRUCT_SECOND_FIELD_SIZE_IS8; - } - } - else if (fieldType == ELEMENT_TYPE_CLASS) - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (pFieldStart[1].GetSize() == 8) - { - size |= STRUCT_SECOND_FIELD_SIZE_IS8; - } - } - } - } -_End_arg: - - return size; -} -#endif - -#if defined(TARGET_RISCV64) -int MethodTable::GetRiscV64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE cls) -{ - TypeHandle th(cls); - - int size = STRUCT_NO_FLOAT_FIELD; - - if (!th.IsTypeDesc()) + if ((flags & bothFloat) == bothFloat) { - MethodTable* pMethodTable = th.AsMethodTable(); - if (th.GetSize() <= 16 /*MAX_PASS_MULTIREG_BYTES*/) - { - DWORD numIntroducedFields = pMethodTable->GetNumIntroducedInstanceFields(); - - if (numIntroducedFields == 1) - { - FieldDesc *pFieldStart = pMethodTable->GetApproxFieldDescListRaw(); - - CorElementType fieldType = pFieldStart[0].GetFieldType(); - - // InlineArray types and fixed buffer types have implied repeated fields. - // Checking if a type is an InlineArray type is cheap, so we'll do that first. - bool hasImpliedRepeatedFields = HasImpliedRepeatedFields(pMethodTable); - - if (hasImpliedRepeatedFields) - { - numIntroducedFields = pMethodTable->GetNumInstanceFieldBytes() / pFieldStart->GetSize(); - if (numIntroducedFields > 2) - { - goto _End_arg; - } - - if (fieldType == ELEMENT_TYPE_R4) - { - if (numIntroducedFields == 1) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE; - } - else if (numIntroducedFields == 2) - { - size = STRUCT_FLOAT_FIELD_ONLY_TWO; - } - goto _End_arg; - } - else if (fieldType == ELEMENT_TYPE_R8) - { - if (numIntroducedFields == 1) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE | STRUCT_FIRST_FIELD_SIZE_IS8; - } - else if (numIntroducedFields == 2) - { - size = STRUCT_FIELD_TWO_DOUBLES; - } - goto _End_arg; - } - } - - if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - if (fieldType == ELEMENT_TYPE_R4) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE; - } - else if (fieldType == ELEMENT_TYPE_R8) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE | STRUCT_FIRST_FIELD_SIZE_IS8; - } - } - else if (fieldType == ELEMENT_TYPE_VALUETYPE) - { - pMethodTable = pFieldStart->GetApproxFieldTypeHandleThrowing().GetMethodTable(); - size = GetRiscV64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); - } - } - else if (numIntroducedFields == 2) - { - FieldDesc *pFieldSecond; - FieldDesc *pFieldFirst = pMethodTable->GetApproxFieldDescListRaw(); - if (pFieldFirst->GetOffset() == 0) - { - pFieldSecond = pFieldFirst + 1; - } - else - { - pFieldSecond = pFieldFirst; - pFieldFirst = pFieldFirst + 1; - } - assert(pFieldFirst->GetOffset() == 0); - - if (pFieldFirst->GetSize() > 8) - { - goto _End_arg; - } - - if (pFieldFirst->GetSize() > pFieldSecond->GetOffset()) - { - goto _End_arg; - } - - CorElementType fieldType = pFieldFirst[0].GetFieldType(); - if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - if (fieldType == ELEMENT_TYPE_R4) - { - size = STRUCT_FLOAT_FIELD_FIRST; - } - else if (fieldType == ELEMENT_TYPE_R8) - { - size = STRUCT_FIRST_FIELD_DOUBLE; - } - else if (pFieldFirst[0].GetSize() == 8) - { - size = STRUCT_FIRST_FIELD_SIZE_IS8; - } - - } - else if (fieldType == ELEMENT_TYPE_VALUETYPE) - { - pMethodTable = pFieldFirst->GetApproxFieldTypeHandleThrowing().GetMethodTable(); - if (IsOnlyOneField(pMethodTable)) - { - size = GetRiscV64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); - if ((size & STRUCT_FLOAT_FIELD_ONLY_ONE) != 0) - { - size = pFieldFirst[0].GetSize() == 8 ? STRUCT_FIRST_FIELD_DOUBLE : STRUCT_FLOAT_FIELD_FIRST; - } - else if (size == STRUCT_NO_FLOAT_FIELD) - { - size = pFieldFirst[0].GetSize() == 8 ? STRUCT_FIRST_FIELD_SIZE_IS8: 0; - } - else - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - } - else - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - } - else if (pFieldFirst[0].GetSize() == 8) - { - size = STRUCT_FIRST_FIELD_SIZE_IS8; - } - - fieldType = pFieldSecond[0].GetFieldType(); - if (pFieldSecond[0].GetSize() > 8) - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - else if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - if (fieldType == ELEMENT_TYPE_R4) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); - } - else if (fieldType == ELEMENT_TYPE_R8) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (pFieldSecond[0].GetSize() == 8) - { - size |= STRUCT_SECOND_FIELD_SIZE_IS8; - } - } - else if (fieldType == ELEMENT_TYPE_VALUETYPE) - { - pMethodTable = pFieldSecond[0].GetApproxFieldTypeHandleThrowing().GetMethodTable(); - if (IsOnlyOneField(pMethodTable)) - { - int size2 = GetRiscV64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); - if ((size2 & STRUCT_FLOAT_FIELD_ONLY_ONE) != 0) - { - if (pFieldSecond[0].GetSize() == 8) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); - } - else - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); - } - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (size2 == STRUCT_NO_FLOAT_FIELD) - { - size |= pFieldSecond[0].GetSize() == 8 ? STRUCT_SECOND_FIELD_SIZE_IS8 : 0; - } - else - { - size = STRUCT_NO_FLOAT_FIELD; - } - } - else - { - size = STRUCT_NO_FLOAT_FIELD; - } - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (pFieldSecond[0].GetSize() == 8) - { - size |= STRUCT_SECOND_FIELD_SIZE_IS8; - } - } - } + assert(nFields == 2); + flags ^= (bothFloat | STRUCT_FLOAT_FIELD_ONLY_TWO); // replace bothFloat with ONLY_TWO } - else + else if (nFields == 1) { - MethodTable* pMethodTable = th.AsNativeValueType(); - - if (th.GetSize() <= 16 /*MAX_PASS_MULTIREG_BYTES*/) - { - DWORD numIntroducedFields = pMethodTable->GetNativeLayoutInfo()->GetNumFields(); - FieldDesc *pFieldStart = nullptr; - - if (numIntroducedFields == 1) - { - pFieldStart = pMethodTable->GetApproxFieldDescListRaw(); - - CorElementType fieldType = pFieldStart->GetFieldType(); - - // InlineArray types and fixed buffer types have implied repeated fields. - // Checking if a type is an InlineArray type is cheap, so we'll do that first. - bool hasImpliedRepeatedFields = HasImpliedRepeatedFields(pMethodTable); - - if (hasImpliedRepeatedFields) - { - numIntroducedFields = pMethodTable->GetNumInstanceFieldBytes() / pFieldStart->GetSize(); - if (numIntroducedFields > 2) - { - goto _End_arg; - } - - if (fieldType == ELEMENT_TYPE_R4) - { - if (numIntroducedFields == 1) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE; - } - else if (numIntroducedFields == 2) - { - size = STRUCT_FLOAT_FIELD_ONLY_TWO; - } - goto _End_arg; - } - else if (fieldType == ELEMENT_TYPE_R8) - { - if (numIntroducedFields == 1) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE | STRUCT_FIRST_FIELD_SIZE_IS8; - } - else if (numIntroducedFields == 2) - { - size = STRUCT_FIELD_TWO_DOUBLES; - } - goto _End_arg; - } - } - - if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - if (fieldType == ELEMENT_TYPE_R4) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE; - } - else if (fieldType == ELEMENT_TYPE_R8) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE | STRUCT_FIRST_FIELD_SIZE_IS8; - } - } - else if (fieldType == ELEMENT_TYPE_VALUETYPE) - { - const NativeFieldDescriptor *pNativeFieldDescs = pMethodTable->GetNativeLayoutInfo()->GetNativeFieldDescriptors(); - NativeFieldCategory nfc = pNativeFieldDescs->GetCategory(); - if (nfc == NativeFieldCategory::NESTED) - { - pMethodTable = pNativeFieldDescs->GetNestedNativeMethodTable(); - size = GetRiscV64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); - return size; - } - else if (nfc == NativeFieldCategory::FLOAT) - { - if (pFieldStart->GetSize() == 4) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE; - } - else if (pFieldStart->GetSize() == 8) - { - size = STRUCT_FLOAT_FIELD_ONLY_ONE | STRUCT_FIRST_FIELD_SIZE_IS8; - } - } - } - } - else if (numIntroducedFields == 2) - { - pFieldStart = pMethodTable->GetApproxFieldDescListRaw(); - - if (pFieldStart->GetSize() > 8) - { - goto _End_arg; - } - - if (pFieldStart->GetOffset() || !pFieldStart[1].GetOffset() || (pFieldStart[0].GetSize() > pFieldStart[1].GetOffset())) - { - goto _End_arg; - } - - CorElementType fieldType = pFieldStart[0].GetFieldType(); - if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - if (fieldType == ELEMENT_TYPE_R4) - { - size = STRUCT_FLOAT_FIELD_FIRST; - } - else if (fieldType == ELEMENT_TYPE_R8) - { - size = STRUCT_FIRST_FIELD_DOUBLE; - } - else if (pFieldStart[0].GetSize() == 8) - { - size = STRUCT_FIRST_FIELD_SIZE_IS8; - } - - fieldType = pFieldStart[1].GetFieldType(); - if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - if (fieldType == ELEMENT_TYPE_R4) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); - } - else if (fieldType == ELEMENT_TYPE_R8) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (pFieldStart[1].GetSize() == 8) - { - size |= STRUCT_SECOND_FIELD_SIZE_IS8; - } - goto _End_arg; - } - } - else if (fieldType == ELEMENT_TYPE_VALUETYPE) - { - const NativeFieldDescriptor *pNativeFieldDescs = pMethodTable->GetNativeLayoutInfo()->GetNativeFieldDescriptors(); - - NativeFieldCategory nfc = pNativeFieldDescs->GetCategory(); - - if (nfc == NativeFieldCategory::NESTED) - { - if (pNativeFieldDescs->GetNumElements() != 1) - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - - MethodTable* pMethodTable2 = pNativeFieldDescs->GetNestedNativeMethodTable(); - - if (!IsOnlyOneField(pMethodTable2)) - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - - size = GetRiscV64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable2); - if ((size & STRUCT_FLOAT_FIELD_ONLY_ONE) != 0) - { - if (pFieldStart->GetSize() == 8) - { - size = STRUCT_FIRST_FIELD_DOUBLE; - } - else - { - size = STRUCT_FLOAT_FIELD_FIRST; - } - } - else if (pFieldStart->GetSize() == 8) - { - size = STRUCT_FIRST_FIELD_SIZE_IS8; - } - else - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - } - else if (nfc == NativeFieldCategory::FLOAT) - { - if (pFieldStart[0].GetSize() == 4) - { - size = STRUCT_FLOAT_FIELD_FIRST; - } - else if (pFieldStart[0].GetSize() == 8) - { - _ASSERTE((pMethodTable->GetNativeSize() == 8) || (pMethodTable->GetNativeSize() == 16)); - size = STRUCT_FIRST_FIELD_DOUBLE; - } - } - else if (pFieldStart[0].GetSize() == 8) - { - size = STRUCT_FIRST_FIELD_SIZE_IS8; - } - } - else if (pFieldStart[0].GetSize() == 8) - { - size = STRUCT_FIRST_FIELD_SIZE_IS8; - } - - fieldType = pFieldStart[1].GetFieldType(); - if (pFieldStart[1].GetSize() > 8) - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - else if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) - { - if (fieldType == ELEMENT_TYPE_R4) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); - } - else if (fieldType == ELEMENT_TYPE_R8) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (pFieldStart[1].GetSize() == 8) - { - size |= STRUCT_SECOND_FIELD_SIZE_IS8; - } - - // Pass with two integer registers in `struct {int a, int b, float/double c}` cases - if ((size | STRUCT_FIRST_FIELD_SIZE_IS8 | STRUCT_FLOAT_FIELD_SECOND) == size) - { - size = STRUCT_NO_FLOAT_FIELD; - } - } - else if (fieldType == ELEMENT_TYPE_VALUETYPE) - { - const NativeFieldDescriptor *pNativeFieldDescs = pMethodTable->GetNativeLayoutInfo()->GetNativeFieldDescriptors(); - NativeFieldCategory nfc = pNativeFieldDescs[1].GetCategory(); - - if (nfc == NativeFieldCategory::NESTED) - { - if (pNativeFieldDescs[1].GetNumElements() != 1) - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - - MethodTable* pMethodTable2 = pNativeFieldDescs[1].GetNestedNativeMethodTable(); - - if (!IsOnlyOneField(pMethodTable2)) - { - size = STRUCT_NO_FLOAT_FIELD; - goto _End_arg; - } - - if ((GetRiscV64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable2) & STRUCT_FLOAT_FIELD_ONLY_ONE) != 0) - { - if (pFieldStart[1].GetSize() == 4) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); - } - else if (pFieldStart[1].GetSize() == 8) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); - } - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (pFieldStart[1].GetSize() == 8) - { - size |= STRUCT_SECOND_FIELD_SIZE_IS8; - } - } - else if (nfc == NativeFieldCategory::FLOAT) - { - if (pFieldStart[1].GetSize() == 4) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); - } - else if (pFieldStart[1].GetSize() == 8) - { - size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); - } - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (pFieldStart[1].GetSize() == 8) - { - size |= STRUCT_SECOND_FIELD_SIZE_IS8; - } - } - else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) - { - size = STRUCT_NO_FLOAT_FIELD; - } - else if (pFieldStart[1].GetSize() == 8) - { - size |= STRUCT_SECOND_FIELD_SIZE_IS8; - } - } - } + assert((flags & STRUCT_FLOAT_FIELD_FIRST) != 0); + flags ^= (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_ONLY_ONE); // replace FIRST with ONLY_ONE } -_End_arg: - return size; + return flags; } #endif @@ -4657,7 +3673,7 @@ void MethodTable::DoRunClassInitThrowing() } else { // if the stored exception is a preallocated one we cannot store the new Exception object in it. // we'll attempt to create a new handle for the new TypeInitializationException object - LOADERHANDLE hNewInitException = NULL; + LOADERHANDLE hNewInitException = 0; // CreateHandle can throw due to OOM. We need to catch this so that we make sure to set the // init error. Whatever exception was thrown will be rethrown below, so no worries. EX_TRY { @@ -4667,7 +3683,7 @@ void MethodTable::DoRunClassInitThrowing() } EX_END_CATCH(SwallowAllExceptions); // if two threads are racing to set m_hInitException, clear the handle created by the loser - if (hNewInitException != NULL && + if (hNewInitException != 0 && InterlockedCompareExchangeT((&pEntry->m_hInitException), hNewInitException, hOrigInitException) != hOrigInitException) { pEntry->m_pLoaderAllocator->FreeHandle(hNewInitException); @@ -5161,7 +4177,7 @@ OBJECTREF MethodTable::GetManagedClassObject() GCStress::MaybeTrigger(); #endif // _DEBUG - if (GetAuxiliaryData()->m_hExposedClassObject == NULL) + if (GetAuxiliaryData()->m_hExposedClassObject == 0) { // Make sure that we have been restored CheckRestore(); @@ -6099,7 +5115,7 @@ MethodTable::FindEncodedMapDispatchEntry( CONSISTENCY_CHECK(HasDispatchMap()); - MethodTable * dispatchTokenType = GetThread()->GetDomain()->LookupType(typeID); + MethodTable * dispatchTokenType = AppDomain::GetCurrentDomain()->LookupType(typeID); // Search for an exact type match. { @@ -6319,12 +5335,12 @@ MethodTable::FindDispatchImpl( #ifndef DACCESS_COMPILE if (typeID != TYPE_ID_THIS_CLASS) { - INDEBUG(dbg_pMTTok = GetThread()->GetDomain()->LookupType(typeID)); + INDEBUG(dbg_pMTTok = AppDomain::GetCurrentDomain()->LookupType(typeID)); DispatchMapEntry e; if (!FindDispatchEntry(typeID, slotNumber, &e)) { // Figure out the interface being called - MethodTable *pIfcMT = GetThread()->GetDomain()->LookupType(typeID); + MethodTable *pIfcMT = AppDomain::GetCurrentDomain()->LookupType(typeID); // Figure out which method of the interface the caller requested. MethodDesc * pIfcMD = pIfcMT->GetMethodDescForSlot(slotNumber); @@ -6837,7 +5853,7 @@ DispatchSlot MethodTable::FindDispatchSlot(UINT32 typeID, UINT32 slotNumber, BOO } CONTRACTL_END; - DispatchSlot implSlot(NULL); + DispatchSlot implSlot(0); FindDispatchImpl(typeID, slotNumber, &implSlot, throwOnConflict); return implSlot; } @@ -8102,7 +7118,7 @@ DispatchSlot MethodTable::MethodDataInterfaceImpl::GetImplSlot(UINT32 slotNumber WRAPPER_NO_CONTRACT; UINT32 implSlotNumber = MapToImplSlotNumber(slotNumber); if (implSlotNumber == INVALID_SLOT_NUMBER) { - return DispatchSlot(NULL); + return DispatchSlot(0); } return m_pImpl->GetImplSlot(implSlotNumber); } @@ -8664,7 +7680,7 @@ MethodTable::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) EnumMemoryRegionsForExtraInterfaceInfo(); } - if (HasPerInstInfo() != NULL) + if (HasPerInstInfo() != FALSE) { DacEnumMemoryRegion(dac_cast(GetPerInstInfo()) - sizeof(GenericsDictInfo), GetPerInstInfoSize() + sizeof(GenericsDictInfo)); } diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index 703508e2126b..cb8a7ce9f9c2 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -824,13 +824,10 @@ class MethodTable // during object construction. void CheckRunClassInitAsIfConstructingThrowing(); -#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - static bool IsOnlyOneField(MethodTable * pMT); #if defined(TARGET_LOONGARCH64) - static int GetLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE clh); + static int GetLoongArch64PassStructInRegisterFlags(TypeHandle th); #elif defined(TARGET_RISCV64) - static int GetRiscV64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE clh); -#endif + static int GetRiscV64PassStructInRegisterFlags(TypeHandle th); #endif #if defined(UNIX_AMD64_ABI_ITF) @@ -2819,7 +2816,7 @@ public : MethodDesc *m_pMD; // The MethodDesc for this slot public: - inline MethodDataEntry() : m_slot(NULL) + inline MethodDataEntry() : m_slot((PCODE)NULL) { WRAPPER_NO_CONTRACT; Init(); } inline void Init() @@ -2827,7 +2824,7 @@ public : LIMITED_METHOD_CONTRACT; m_chainDeltaAndTableIndex = INVALID_CHAIN_AND_INDEX; m_implSlotNum = INVALID_IMPL_SLOT_NUM; - m_slot = NULL; + m_slot = (PCODE)NULL; m_pMD = NULL; } diff --git a/src/coreclr/vm/methodtable.inl b/src/coreclr/vm/methodtable.inl index b2816fccc2c0..d0c9b889f2f0 100644 --- a/src/coreclr/vm/methodtable.inl +++ b/src/coreclr/vm/methodtable.inl @@ -1331,15 +1331,7 @@ FORCEINLINE OBJECTREF MethodTable::GetManagedClassObjectIfExists() LIMITED_METHOD_CONTRACT; const RUNTIMETYPEHANDLE handle = GetAuxiliaryData()->m_hExposedClassObject; - - OBJECTREF retVal; - if (!TypeHandle::GetManagedClassObjectFromHandleFast(handle, &retVal) && - !GetLoaderAllocator()->GetHandleValueFastPhase2(handle, &retVal)) - { - return NULL; - } - - COMPILER_ASSUME(retVal != NULL); + OBJECTREF retVal = ObjectToOBJECTREF(handle); return retVal; } #endif diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 69d2a105ecd8..69d2ab17c275 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -7039,8 +7039,9 @@ VOID MethodTableBuilder::AllocAndInitMethodDescChunk(COUNT_T startIndex, COUNT_T PRECONDITION(sizeOfMethodDescs <= MethodDescChunk::MaxSizeOfMethodDescs); } CONTRACTL_END; + PTR_LoaderHeap pHeap = GetLoaderAllocator()->GetHighFrequencyHeap(); void * pMem = GetMemTracker()->Track( - GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(TADDR) + sizeof(MethodDescChunk) + sizeOfMethodDescs))); + pHeap->AllocMem(S_SIZE_T(sizeof(TADDR) + sizeof(MethodDescChunk) + sizeOfMethodDescs))); // Skip pointer to temporary entrypoints MethodDescChunk * pChunk = (MethodDescChunk *)((BYTE*)pMem + sizeof(TADDR)); @@ -10051,6 +10052,9 @@ void MethodTableBuilder::CheckForSystemTypes() // The Procedure Call Standard for ARM 64-bit (with SVE support) defaults to // 16-byte alignment for __m256. + pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; + #elif defined(TARGET_LOONGARCH64) + // TODO-LoongArch64: Update alignment to proper value when implement LoongArch64 intrinsic. pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; #elif defined(TARGET_RISCV64) // TODO-RISCV64: Update alignment to proper value when we implement RISC-V intrinsic. @@ -10074,6 +10078,9 @@ void MethodTableBuilder::CheckForSystemTypes() pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; + #elif defined(TARGET_LOONGARCH64) + // TODO-LoongArch64: Update alignment to proper value when implement LoongArch64 intrinsic. + pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; #elif defined(TARGET_RISCV64) // TODO-RISCV64: Update alignment to proper value when we implement RISC-V intrinsic. // RISC-V Vector Extenstion Intrinsic Document diff --git a/src/coreclr/vm/methodtablebuilder.h b/src/coreclr/vm/methodtablebuilder.h index 121e15089722..507e163d29f7 100644 --- a/src/coreclr/vm/methodtablebuilder.h +++ b/src/coreclr/vm/methodtablebuilder.h @@ -38,7 +38,7 @@ class MethodTableBuilder BOOL fSharedByGenericInstantiations; // TRUE if this is canonical type shared by instantiations BOOL fContainsGenericVariables; // TRUE if this is an open type - inline bmtGenericsInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } + inline bmtGenericsInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, 0, sizeof(*this)); } inline DWORD GetNumGenericArgs() const { LIMITED_METHOD_CONTRACT; return typeContext.m_classInst.GetNumArgs(); } inline BOOL HasInstantiation() const { LIMITED_METHOD_CONTRACT; return typeContext.m_classInst.GetNumArgs() != 0; } inline BOOL IsTypicalTypeDefinition() const { LIMITED_METHOD_CONTRACT; return !HasInstantiation() || fTypicalInstantiation; } @@ -1300,7 +1300,7 @@ class MethodTableBuilder DWORD dwNonGCRegularStaticFieldBytes; DWORD dwNonGCThreadStaticFieldBytes; - inline bmtProperties() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } + inline bmtProperties() { LIMITED_METHOD_CONTRACT; memset((void *)this, 0, sizeof(*this)); } }; // struct bmtProperties // -------------------------------------------------------------------------------------------- @@ -1552,7 +1552,7 @@ class MethodTableBuilder DWORD NumParentPointerSeries; MethodNameHash *pParentMethodHash; - inline bmtParentInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } + inline bmtParentInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, 0, sizeof(*this)); } }; // struct bmtParentInfo // -------------------------------------------------------------------------------------------- @@ -1834,7 +1834,7 @@ class MethodTableBuilder //----------------------------------------------------------------------------------------- // Constructor - inline bmtInterfaceInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } + inline bmtInterfaceInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, 0, sizeof(*this)); } }; // struct bmtInterfaceInfo // -------------------------------------------------------------------------------------------- @@ -1863,7 +1863,7 @@ class MethodTableBuilder inline bmtEnumFieldInfo(IMDInternalImport *pInternalImport) { LIMITED_METHOD_CONTRACT; - memset((void *)this, NULL, sizeof(*this)); + memset((void *)this, 0, sizeof(*this)); m_pInternalImport = pInternalImport; } }; // struct bmtEnumFieldInfo @@ -1886,7 +1886,7 @@ class MethodTableBuilder //----------------------------------------------------------------------------------------- // Constructor inline bmtMethodInfo() - { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } + { LIMITED_METHOD_CONTRACT; memset((void *)this, 0, sizeof(*this)); } //----------------------------------------------------------------------------------------- // Add a declared method to the array @@ -1966,7 +1966,7 @@ class MethodTableBuilder bool fHasCovariantOverride; //----------------------------------------------------------------------------------------- - inline bmtMetaDataInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } + inline bmtMetaDataInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, 0, sizeof(*this)); } }; // struct bmtMetaDataInfo // -------------------------------------------------------------------------------------------- @@ -1979,7 +1979,7 @@ class MethodTableBuilder //----------------------------------------------------------------------------------------- - inline bmtMethAndFieldDescs() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } + inline bmtMethAndFieldDescs() { LIMITED_METHOD_CONTRACT; memset((void *)this, 0, sizeof(*this)); } }; // struct bmtMethAndFieldDescs // -------------------------------------------------------------------------------------------- @@ -2038,7 +2038,7 @@ class MethodTableBuilder //----------------------------------------------------------------------------------------- // Constructor - inline bmtInternalInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } + inline bmtInternalInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, 0, sizeof(*this)); } }; // struct bmtInternalInfo @@ -2141,7 +2141,7 @@ class MethodTableBuilder //----------------------------------------------------------------------------------------- // Constructor inline bmtMethodImplInfo() - { LIMITED_METHOD_CONTRACT; memset((void*) this, NULL, sizeof(*this)); } + { LIMITED_METHOD_CONTRACT; memset((void*) this, 0, sizeof(*this)); } //----------------------------------------------------------------------------------------- // Returns TRUE if tok acts as a body for any methodImpl entry. FALSE, otherwise. @@ -2399,7 +2399,7 @@ class MethodTableBuilder Substitution * pInterfaceSubstitution; SigTypeContext typeContext; // Exact type context used to supply final instantiation to substitution chains - inline bmtExactInterfaceInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } + inline bmtExactInterfaceInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, 0, sizeof(*this)); } }; // struct bmtExactInterfaceInfo private: @@ -2449,7 +2449,7 @@ class MethodTableBuilder Substitution **ppInterfaceSubstitutionChains; SigTypeContext typeContext; - inline bmtInterfaceAmbiguityCheckInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } + inline bmtInterfaceAmbiguityCheckInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, 0, sizeof(*this)); } }; // struct bmtInterfaceAmbiguityCheckInfo static void diff --git a/src/coreclr/vm/multicorejit.h b/src/coreclr/vm/multicorejit.h index 7a61c22fd8b4..37eea5782156 100644 --- a/src/coreclr/vm/multicorejit.h +++ b/src/coreclr/vm/multicorejit.h @@ -92,7 +92,7 @@ class MulticoreJitCodeInfo TADDR m_entryPointAndTierInfo; public: - MulticoreJitCodeInfo() : m_entryPointAndTierInfo(NULL) + MulticoreJitCodeInfo() : m_entryPointAndTierInfo{} { LIMITED_METHOD_CONTRACT; } @@ -109,13 +109,13 @@ class MulticoreJitCodeInfo bool IsNull() const { LIMITED_METHOD_CONTRACT; - return m_entryPointAndTierInfo == NULL; + return m_entryPointAndTierInfo == 0; } PCODE GetEntryPoint() const { WRAPPER_NO_CONTRACT; - return IsNull() ? NULL : PINSTRToPCODE(m_entryPointAndTierInfo & ~(TADDR)TierInfo::Mask); + return IsNull() ? (PCODE)0 : PINSTRToPCODE(m_entryPointAndTierInfo & ~(TADDR)TierInfo::Mask); } bool WasTier0() const diff --git a/src/coreclr/vm/multicorejitplayer.cpp b/src/coreclr/vm/multicorejitplayer.cpp index 2b8a0a1ba809..49f7c4a0527a 100644 --- a/src/coreclr/vm/multicorejitplayer.cpp +++ b/src/coreclr/vm/multicorejitplayer.cpp @@ -966,7 +966,7 @@ void MulticoreJitProfilePlayer::CompileMethodInfoRecord(Module *pModule, MethodD } } - if (pMethod->GetNativeCode() == NULL && !GetAppDomain()->GetMulticoreJitManager().GetMulticoreJitCodeStorage().LookupMethodCode(pMethod)) + if (pMethod->GetNativeCode() == (PCODE)NULL && !GetAppDomain()->GetMulticoreJitManager().GetMulticoreJitCodeStorage().LookupMethodCode(pMethod)) { if (CompileMethodDesc(pModule, pMethod)) { diff --git a/src/coreclr/vm/nativelibrary.cpp b/src/coreclr/vm/nativelibrary.cpp index c4460d91a5c0..7acdce8b37df 100644 --- a/src/coreclr/vm/nativelibrary.cpp +++ b/src/coreclr/vm/nativelibrary.cpp @@ -295,11 +295,11 @@ INT_PTR NativeLibrary::GetNativeLibraryExport(NATIVE_LIBRARY_HANDLE handle, LPCW #ifndef TARGET_UNIX INT_PTR address = reinterpret_cast(GetProcAddress((HMODULE)handle, lpstr)); - if ((address == NULL) && throwOnError) + if ((address == 0) && throwOnError) COMPlusThrow(kEntryPointNotFoundException, IDS_EE_NDIRECT_GETPROCADDR_WIN_DLL, symbolName); #else // !TARGET_UNIX INT_PTR address = reinterpret_cast(PAL_GetProcAddressDirect(handle, lpstr)); - if ((address == NULL) && throwOnError) + if ((address == 0) && throwOnError) COMPlusThrow(kEntryPointNotFoundException, IDS_EE_NDIRECT_GETPROCADDR_UNIX_SO, symbolName); #endif // !TARGET_UNIX @@ -386,7 +386,7 @@ namespace STANDARD_VM_CONTRACT; INT_PTR ptrManagedAssemblyLoadContext = GetManagedAssemblyLoadContext(pAssembly); - if (ptrManagedAssemblyLoadContext == NULL) + if (ptrManagedAssemblyLoadContext == 0) { return NULL; } diff --git a/src/coreclr/vm/nativelibrarynative.cpp b/src/coreclr/vm/nativelibrarynative.cpp index c4594521cf09..1aeff462f4b3 100644 --- a/src/coreclr/vm/nativelibrarynative.cpp +++ b/src/coreclr/vm/nativelibrarynative.cpp @@ -60,7 +60,7 @@ extern "C" INT_PTR QCALLTYPE NativeLibrary_GetSymbol(INT_PTR handle, LPCWSTR sym { QCALL_CONTRACT; - INT_PTR address = NULL; + INT_PTR address = 0; BEGIN_QCALL; diff --git a/src/coreclr/vm/object.cpp b/src/coreclr/vm/object.cpp index 2207b728ce1e..cf4110344184 100644 --- a/src/coreclr/vm/object.cpp +++ b/src/coreclr/vm/object.cpp @@ -21,6 +21,18 @@ SVAL_IMPL(INT32, ArrayBase, s_arrayBoundsZero); +static DWORD GetGlobalNewHashCode() +{ + LIMITED_METHOD_CONTRACT; + // Used for generating hash codes for exceptions to determine whether the + // Catch_Handler_Found_Event should be reported. See Thread::GetNewHashCode. + // Using linear congruential generator from Knuth Vol. 2, p. 102, line 24 + static DWORD dwHashCodeSeed = 123456789U * 1566083941U + 1; + const DWORD multiplier = 1*4 + 5; //same as the GetNewHashCode method + dwHashCodeSeed = dwHashCodeSeed*multiplier + 1; + return dwHashCodeSeed; +} + // follow the necessary rules to get a new valid hashcode for an object DWORD Object::ComputeHashCode() { @@ -29,10 +41,18 @@ DWORD Object::ComputeHashCode() // note that this algorithm now uses at most HASHCODE_BITS so that it will // fit into the objheader if the hashcode has to be moved back into the objheader // such as for an object that is being frozen + Thread *pThread = GetThreadNULLOk(); do { - // we use the high order bits in this case because they're more random - hashCode = GetThread()->GetNewHashCode() >> (32-HASHCODE_BITS); + if (pThread == NULL) + { + hashCode = (GetGlobalNewHashCode() >> (32-HASHCODE_BITS)); + } + else + { + // we use the high order bits in this case because they're more random + hashCode = pThread->GetNewHashCode() >> (32-HASHCODE_BITS); + } } while (hashCode == 0); // need to enforce hashCode != 0 @@ -42,6 +62,18 @@ DWORD Object::ComputeHashCode() return hashCode; } +DWORD Object::GetGlobalNewHashCode() +{ + LIMITED_METHOD_CONTRACT; + // Used for generating hash codes for exceptions to determine whether the + // Catch_Handler_Found_Event should be reported. See Thread::GetNewHashCode. + // Using linear congruential generator from Knuth Vol. 2, p. 102, line 24 + static DWORD dwHashCodeSeed = 123456789U * 1566083941U + 1; + const DWORD multiplier = 1*4 + 5; //same as the GetNewHashCode method + dwHashCodeSeed = dwHashCodeSeed*multiplier + 1; + return dwHashCodeSeed; +} + #ifndef DACCESS_COMPILE INT32 Object::GetHashCodeEx() { diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index c0774cae0d81..c486177ee318 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -263,6 +263,7 @@ class Object } static DWORD ComputeHashCode(); + static DWORD GetGlobalNewHashCode(); #ifndef DACCESS_COMPILE INT32 GetHashCodeEx(); @@ -382,10 +383,10 @@ class Object return * PTR_BYTE(GetData() + dwOffset); } - __int64 GetOffset64(DWORD dwOffset) + int64_t GetOffset64(DWORD dwOffset) { WRAPPER_NO_CONTRACT; - return (__int64) * PTR_ULONG64(GetData() + dwOffset); + return (int64_t) * PTR_ULONG64(GetData() + dwOffset); } void *GetPtrOffset(DWORD dwOffset) @@ -422,10 +423,10 @@ class Object *(BYTE *) &GetData()[dwOffset] = (BYTE) dwValue; } - void SetOffset64(DWORD dwOffset, __int64 qwValue) + void SetOffset64(DWORD dwOffset, int64_t qwValue) { WRAPPER_NO_CONTRACT; - *(__int64 *) &GetData()[dwOffset] = qwValue; + *(int64_t *) &GetData()[dwOffset] = qwValue; } #endif // #ifndef DACCESS_COMPILE @@ -1853,7 +1854,7 @@ class DelegateObject : public Object friend class CoreLibBinder; public: - BOOL IsWrapperDelegate() { LIMITED_METHOD_CONTRACT; return _methodPtrAux == NULL; } + BOOL IsWrapperDelegate() { LIMITED_METHOD_CONTRACT; return _methodPtrAux == 0; } OBJECTREF GetTarget() { LIMITED_METHOD_CONTRACT; return _target; } void SetTarget(OBJECTREF target) { WRAPPER_NO_CONTRACT; SetObjectReference(&_target, target); } @@ -2324,7 +2325,7 @@ class ExceptionObject : public Object { LIMITED_METHOD_CONTRACT; - return (_ipForWatsonBuckets != NULL); + return (_ipForWatsonBuckets != 0); } // This method returns the IP for Watson Buckets. @@ -2455,7 +2456,7 @@ class Nullable { static BOOL UnBox(void* dest, OBJECTREF boxedVal, MethodTable* destMT); static BOOL UnBoxNoGC(void* dest, OBJECTREF boxedVal, MethodTable* destMT); static void UnBoxNoCheck(void* dest, OBJECTREF boxedVal, MethodTable* destMT); - static OBJECTREF BoxedNullableNull(TypeHandle nullableType) { return 0; } + static OBJECTREF BoxedNullableNull(TypeHandle nullableType) { return NULL; } // if 'Obj' is a true boxed nullable, return the form we want (either null or a boxed T) static OBJECTREF NormalizeBox(OBJECTREF obj); diff --git a/src/coreclr/vm/object.inl b/src/coreclr/vm/object.inl index 491aab1d4c87..c78222529c30 100644 --- a/src/coreclr/vm/object.inl +++ b/src/coreclr/vm/object.inl @@ -114,7 +114,7 @@ FORCEINLINE bool Object::TryEnterObjMonitorSpinHelper() } CONTRACTL_END; Thread *pCurThread = GetThread(); - if (pCurThread->CatchAtSafePointOpportunistic()) + if (pCurThread->CatchAtSafePoint()) { return false; } diff --git a/src/coreclr/vm/olevariant.cpp b/src/coreclr/vm/olevariant.cpp index 40e039a1648e..5f7913b07b72 100644 --- a/src/coreclr/vm/olevariant.cpp +++ b/src/coreclr/vm/olevariant.cpp @@ -1175,11 +1175,11 @@ void SafeVariantClear(VARIANT* pVar) } } -class VariantEmptyHolder : public Wrapper, SafeVariantClear, NULL> +class VariantEmptyHolder : public Wrapper, SafeVariantClear, 0> { public: VariantEmptyHolder(VARIANT* p = NULL) : - Wrapper, SafeVariantClear, NULL>(p) + Wrapper, SafeVariantClear, 0>(p) { WRAPPER_NO_CONTRACT; } @@ -1188,7 +1188,7 @@ class VariantEmptyHolder : public Wrapper, SafeV { WRAPPER_NO_CONTRACT; - Wrapper, SafeVariantClear, NULL>::operator=(p); + Wrapper, SafeVariantClear, 0>::operator=(p); } }; @@ -1205,11 +1205,11 @@ FORCEINLINE void RecordVariantRelease(VARIANT* value) } } -class RecordVariantHolder : public Wrapper, RecordVariantRelease, NULL> +class RecordVariantHolder : public Wrapper, RecordVariantRelease, 0> { public: RecordVariantHolder(VARIANT* p = NULL) - : Wrapper, RecordVariantRelease, NULL>(p) + : Wrapper, RecordVariantRelease, 0>(p) { WRAPPER_NO_CONTRACT; } @@ -1217,7 +1217,7 @@ class RecordVariantHolder : public Wrapper, Reco FORCEINLINE void operator=(VARIANT* p) { WRAPPER_NO_CONTRACT; - Wrapper, RecordVariantRelease, NULL>::operator=(p); + Wrapper, RecordVariantRelease, 0>::operator=(p); } }; #endif // FEATURE_COMINTEROP @@ -4731,11 +4731,8 @@ void OleVariant::ConvertValueClassToVariant(OBJECTREF *pBoxedValueClass, VARIANT // Marshal the contents of the value class into the record. MethodDesc* pStructMarshalStub; { - GCPROTECT_BEGIN(*pBoxedValueClass); GCX_PREEMP(); - pStructMarshalStub = NDirect::CreateStructMarshalILStub(pValueClassMT); - GCPROTECT_END(); } MarshalStructViaILStub(pStructMarshalStub, (*pBoxedValueClass)->GetData(), (BYTE*)V_RECORD(pRecHolder), StructMarshalStubs::MarshalOperation::Marshal); diff --git a/src/coreclr/vm/peassembly.inl b/src/coreclr/vm/peassembly.inl index 3a805bea6300..23af8bd7a094 100644 --- a/src/coreclr/vm/peassembly.inl +++ b/src/coreclr/vm/peassembly.inl @@ -775,7 +775,7 @@ inline BOOL PEAssembly::IsStrongNamed() DWORD flags = 0; IfFailThrow(GetMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, NULL, &flags)); - return (flags & afPublicKey) != NULL; + return (flags & afPublicKey) != 0; } diff --git a/src/coreclr/vm/peimagelayout.cpp b/src/coreclr/vm/peimagelayout.cpp index 3feaf538dbf8..500f97ff7a4d 100644 --- a/src/coreclr/vm/peimagelayout.cpp +++ b/src/coreclr/vm/peimagelayout.cpp @@ -416,7 +416,7 @@ void ConvertedImageLayout::FreeImageParts() CLRUnmapViewOfFile(PtrFromPart(imagePart)); } - this->m_imageParts[i] = NULL; + this->m_imageParts[i] = 0; } } diff --git a/src/coreclr/vm/peimagelayout.inl b/src/coreclr/vm/peimagelayout.inl index 038b17be1eb2..21bb137449cb 100644 --- a/src/coreclr/vm/peimagelayout.inl +++ b/src/coreclr/vm/peimagelayout.inl @@ -80,7 +80,7 @@ inline BOOL PEImageLayout::CompareBase(UPTR base, UPTR mapping) MODE_ANY; } CONTRACTL_END; - if (base==NULL) //we were searching for 'Any' + if (base==0) //we were searching for 'Any' return TRUE; return ((PEImageLayout*)mapping)->GetBase()==((PEImageLayout*)(base<<1))->GetBase(); diff --git a/src/coreclr/vm/perfinfo.cpp b/src/coreclr/vm/perfinfo.cpp deleted file mode 100644 index 98fc667661a5..000000000000 --- a/src/coreclr/vm/perfinfo.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// =========================================================================== -// File: perfinfo.cpp -// - -#include "common.h" - -#if defined(FEATURE_PERFMAP) && !defined(DACCESS_COMPILE) -#include "perfinfo.h" -#include "pal.h" - -PerfInfo::PerfInfo(int pid, const char* basePath) - : m_Stream(nullptr) -{ - LIMITED_METHOD_CONTRACT; - - SString path; - path.Printf("%s/perfinfo-%d.map", basePath, pid); - OpenFile(path); -} - -// Logs image loads into the process' perfinfo-%d.map file -void PerfInfo::LogImage(PEAssembly* pPEAssembly, CHAR* guid) -{ - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - MODE_PREEMPTIVE; - PRECONDITION(pPEAssembly != nullptr); - PRECONDITION(guid != nullptr); - } CONTRACTL_END; - - // Nothing to log if the assembly path isn't present. - SString path{ pPEAssembly->GetPath() }; - if (path.IsEmpty()) - { - return; - } - - SIZE_T baseAddr = 0; - if (pPEAssembly->IsReadyToRun()) - { - PEImageLayout *pLoadedLayout = pPEAssembly->GetLoadedLayout(); - if (pLoadedLayout) - { - baseAddr = (SIZE_T)pLoadedLayout->GetBase(); - } - } - - SString value; - value.Printf("%s%c%s%c%p", path.GetUTF8(), sDelimiter, guid, sDelimiter, baseAddr); - - SString command{ SString::Literal, "ImageLoad" }; - WriteLine(command, value); -} - -// Writes a command line, with "type" being the type of command, with "value" as the command's corresponding instructions/values. This is to be used to log specific information, e.g. LogImage -void PerfInfo::WriteLine(SString& type, SString& value) -{ - - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - if (m_Stream == nullptr) - { - return; - } - - SString line; - line.Printf("%s%c%s%c\n", - type.GetUTF8(), sDelimiter, value.GetUTF8(), sDelimiter); - - EX_TRY - { - const char* strLine = line.GetUTF8(); - ULONG inCount = line.GetCount(); - ULONG outCount; - - m_Stream->Write(strLine, inCount, &outCount); - - if (inCount != outCount) - { - // error encountered - } - } - EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); -} - -// Opens a file ready to be written in. -void PerfInfo::OpenFile(SString& path) -{ - STANDARD_VM_CONTRACT; - - m_Stream = new (nothrow) CFileStream(); - - if (m_Stream != nullptr) - { - HRESULT hr = m_Stream->OpenForWrite(path.GetUnicode()); - if (FAILED(hr)) - { - delete m_Stream; - m_Stream = nullptr; - } - } -} - -PerfInfo::~PerfInfo() -{ - LIMITED_METHOD_CONTRACT; - - delete m_Stream; - m_Stream = nullptr; -} - - -#endif - - - - - - - - - - diff --git a/src/coreclr/vm/perfinfo.h b/src/coreclr/vm/perfinfo.h deleted file mode 100644 index ce54cc19faee..000000000000 --- a/src/coreclr/vm/perfinfo.h +++ /dev/null @@ -1,39 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// =========================================================================== -// File: perfinfo.h -// - -#ifndef PERFINFO_H -#define PERFINFO_H - - -#include "sstring.h" -#include "fstream.h" - -/* - A perfinfo-%d.map is created for every process that is created with manage code, the %d - being repaced with the process ID. - Every line in the perfinfo-%d.map is a type and value, separated by sDelimiter character: type;value - type represents what the user might want to do with its given value. value has a format chosen by - the user for parsing later on. -*/ -class PerfInfo { -public: - PerfInfo(int pid, const char* basePath); - ~PerfInfo(); - void LogImage(PEAssembly* pPEAssembly, CHAR* guid); - -private: - CFileStream* m_Stream; - - const char sDelimiter = ';'; - - void OpenFile(SString& path); - - void WriteLine(SString& type, SString& value); - -}; - - -#endif diff --git a/src/coreclr/vm/perfmap.cpp b/src/coreclr/vm/perfmap.cpp index d032dc6031dc..2d823e546fca 100644 --- a/src/coreclr/vm/perfmap.cpp +++ b/src/coreclr/vm/perfmap.cpp @@ -9,7 +9,6 @@ #if defined(FEATURE_PERFMAP) && !defined(DACCESS_COMPILE) #include #include "perfmap.h" -#include "perfinfo.h" #include "pal.h" @@ -113,7 +112,6 @@ void PerfMap::Enable(PerfMapType type, bool sendExisting) while (assemblyIterator.Next(pDomainAssembly.This())) { CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetAssembly(); - PerfMap::LogImageLoad(pAssembly->GetPEAssembly()); // PerfMap does not log R2R methods so only proceed if we are emitting jitdumps if (type == PerfMapType::ALL || type == PerfMapType::JITDUMP) @@ -127,7 +125,7 @@ void PerfMap::Enable(PerfMapType type, bool sendExisting) { // Call GetMethodDesc_NoRestore instead of GetMethodDesc to avoid restoring methods. MethodDesc *hotDesc = (MethodDesc *)mi.GetMethodDesc_NoRestore(); - if (hotDesc != nullptr && hotDesc->GetNativeCode() != NULL) + if (hotDesc != nullptr && hotDesc->GetNativeCode() != (PCODE)NULL) { PerfMap::LogPreCompiledMethod(hotDesc, hotDesc->GetNativeCode()); } @@ -204,7 +202,6 @@ PerfMap::PerfMap() // Initialize with no failures. m_ErrorEncountered = false; - m_PerfInfo = nullptr; } // Clean-up resources. @@ -214,9 +211,6 @@ PerfMap::~PerfMap() delete m_FileStream; m_FileStream = nullptr; - - delete m_PerfInfo; - m_PerfInfo = nullptr; } void PerfMap::OpenFileForPid(int pid, const char* basePath) @@ -226,8 +220,6 @@ void PerfMap::OpenFileForPid(int pid, const char* basePath) // Open the map file for writing. OpenFile(fullPath); - - m_PerfInfo = new PerfInfo(pid, basePath); } // Open the specified destination map file. @@ -281,43 +273,6 @@ void PerfMap::WriteLine(SString& line) EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); } -void PerfMap::LogImageLoad(PEAssembly * pPEAssembly) -{ - CrstHolder ch(&(s_csPerfMap)); - - if (s_enabled && s_Current != nullptr) - { - s_Current->LogImage(pPEAssembly); - } -} - -// Log an image load to the map. -void PerfMap::LogImage(PEAssembly * pPEAssembly) -{ - CONTRACTL{ - THROWS; - GC_NOTRIGGER; - MODE_PREEMPTIVE; - PRECONDITION(pPEAssembly != nullptr); - } CONTRACTL_END; - - - if (m_FileStream == nullptr || m_ErrorEncountered) - { - // A failure occurred, do not log. - return; - } - - EX_TRY - { - CHAR szSignature[GUID_STR_BUFFER_LEN]; - GetNativeImageSignature(pPEAssembly, szSignature, ARRAY_SIZE(szSignature)); - - m_PerfInfo->LogImage(pPEAssembly, szSignature); - } - EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); -} - void PerfMap::LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, PrepareCodeConfig *pConfig) { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/perfmap.h b/src/coreclr/vm/perfmap.h index ffc7f3228b2c..f6eb8cfc7383 100644 --- a/src/coreclr/vm/perfmap.h +++ b/src/coreclr/vm/perfmap.h @@ -10,8 +10,6 @@ #include "fstream.h" #include "volatile.h" -class PerfInfo; - // Generates a perfmap file. class PerfMap { @@ -32,9 +30,6 @@ class PerfMap // The file stream to write the map to. CFileStream * m_FileStream; - // The perfinfo file to log images to. - PerfInfo * m_PerfInfo; - // Set to true if an error is encountered when writing to the file. bool m_ErrorEncountered; @@ -57,9 +52,6 @@ class PerfMap // Does the actual work to log a method to the map. void LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, const char *optimizationTier); - // Does the actual work to log an image - void LogImage(PEAssembly * pPEAssembly); - // Get the image signature and store it as a string. static void GetNativeImageSignature(PEAssembly * pPEAssembly, CHAR * pszSig, unsigned int nSigSize); @@ -87,9 +79,6 @@ class PerfMap static void Enable(PerfMapType type, bool sendExisting); - // Log a native image load to the map. - static void LogImageLoad(PEAssembly * pPEAssembly); - static void LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, PrepareCodeConfig *pConfig); // Log a pre-compiled method to the map. diff --git a/src/coreclr/vm/precode.cpp b/src/coreclr/vm/precode.cpp index 3edc093add6b..9e9b36ede97b 100644 --- a/src/coreclr/vm/precode.cpp +++ b/src/coreclr/vm/precode.cpp @@ -74,7 +74,7 @@ PCODE Precode::GetTarget() LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; - PCODE target = NULL; + PCODE target = 0; PrecodeType precodeType = GetType(); switch (precodeType) @@ -108,7 +108,7 @@ MethodDesc* Precode::GetMethodDesc(BOOL fSpeculative /*= FALSE*/) SUPPORTS_DAC; } CONTRACTL_END; - TADDR pMD = NULL; + TADDR pMD = (TADDR)NULL; PrecodeType precodeType = GetType(); switch (precodeType) @@ -136,7 +136,7 @@ MethodDesc* Precode::GetMethodDesc(BOOL fSpeculative /*= FALSE*/) break; } - if (pMD == NULL) + if (pMD == (TADDR)NULL) { if (fSpeculative) return NULL; @@ -196,9 +196,7 @@ PCODE Precode::TryToSkipFixupPrecode(PCODE addr) GC_NOTRIGGER; } CONTRACTL_END; - PCODE pTarget = NULL; - - return pTarget; + return 0; } Precode* Precode::GetPrecodeForTemporaryEntryPoint(TADDR temporaryEntryPoints, int index) @@ -444,15 +442,7 @@ TADDR Precode::AllocateTemporaryEntryPoints(MethodDescChunk * pChunk, #ifdef HAS_FIXUP_PRECODE // Default to faster fixup precode if possible - if (!pFirstMD->RequiresMethodDescCallingConvention(count > 1)) - { - t = PRECODE_FIXUP; - - } - else - { - _ASSERTE(!pFirstMD->IsLCGMethod()); - } + t = PRECODE_FIXUP; #endif // HAS_FIXUP_PRECODE SIZE_T totalSize = SizeOfTemporaryEntryPoints(t, count); @@ -570,7 +560,7 @@ void StubPrecode::Init(StubPrecode* pPrecodeRX, MethodDesc* pMD, LoaderAllocator { // Use pMD == NULL in all precode initialization methods to allocate the initial jump stub in non-dynamic heap // that has the same lifetime like as the precode itself - if (target == NULL) + if (target == (TADDR)NULL) target = GetPreStubEntryPoint(); pStubData->Target = target; } diff --git a/src/coreclr/vm/precode.h b/src/coreclr/vm/precode.h index 3f6a2f532c4e..fac2433c7428 100644 --- a/src/coreclr/vm/precode.h +++ b/src/coreclr/vm/precode.h @@ -117,7 +117,7 @@ struct StubPrecode static void (*StubPrecodeCode_End)(); #endif - void Init(StubPrecode* pPrecodeRX, MethodDesc* pMD, LoaderAllocator *pLoaderAllocator = NULL, BYTE type = StubPrecode::Type, TADDR target = NULL); + void Init(StubPrecode* pPrecodeRX, MethodDesc* pMD, LoaderAllocator *pLoaderAllocator = NULL, BYTE type = StubPrecode::Type, TADDR target = 0); static void StaticInitialize(); diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index 64638b96cddf..685bfba70f50 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -344,7 +344,7 @@ bool MayUsePrecompiledILStub() PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig) { STANDARD_VM_CONTRACT; - PCODE pCode = NULL; + PCODE pCode = (PCODE)NULL; bool shouldTier = false; #if defined(FEATURE_TIERED_COMPILATION) @@ -398,7 +398,7 @@ PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig) if (pTargetMD != NULL) { pCode = pTargetMD->GetPrecompiledR2RCode(pConfig); - if (pCode != NULL) + if (pCode != (PCODE)NULL) { LOG_USING_R2R_CODE(this); pConfig->SetNativeCode(pCode, &pCode); @@ -409,24 +409,24 @@ PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig) } #endif // FEATURE_READYTORUN - if (pCode == NULL) + if (pCode == (PCODE)NULL) { pCode = GetPrecompiledCode(pConfig, shouldTier); } #ifdef FEATURE_PERFMAP - if (pCode != NULL) + if (pCode != (PCODE)NULL) PerfMap::LogPreCompiledMethod(this, pCode); #endif } - if (pConfig->IsForMulticoreJit() && pCode == NULL && pConfig->ReadyToRunRejectedPrecompiledCode()) + if (pConfig->IsForMulticoreJit() && pCode == (PCODE)NULL && pConfig->ReadyToRunRejectedPrecompiledCode()) { // Was unable to load code from r2r image in mcj thread, don't try to jit it, this method will be loaded later - return NULL; + return (PCODE)NULL; } - if (pCode == NULL) + if (pCode == (PCODE)NULL) { LOG((LF_CLASSLOADER, LL_INFO1000000, " In PrepareILBasedCode, calling JitCompileCode\n")); @@ -443,11 +443,11 @@ PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig) PCODE MethodDesc::GetPrecompiledCode(PrepareCodeConfig* pConfig, bool shouldTier) { STANDARD_VM_CONTRACT; - PCODE pCode = NULL; + PCODE pCode = (PCODE)NULL; #ifdef FEATURE_READYTORUN pCode = GetPrecompiledR2RCode(pConfig); - if (pCode != NULL) + if (pCode != (PCODE)NULL) { LOG_USING_R2R_CODE(this); @@ -499,7 +499,7 @@ PCODE MethodDesc::GetPrecompiledR2RCode(PrepareCodeConfig* pConfig) { STANDARD_VM_CONTRACT; - PCODE pCode = NULL; + PCODE pCode = (PCODE)NULL; #ifdef FEATURE_READYTORUN ReadyToRunInfo* pAlreadyExaminedInfos[2] = {NULL, NULL}; Module * pModule = GetModule(); @@ -510,7 +510,7 @@ PCODE MethodDesc::GetPrecompiledR2RCode(PrepareCodeConfig* pConfig) } // Generics may be located in several places - if (pCode == NULL && HasClassOrMethodInstantiation()) + if (pCode == (PCODE)NULL && HasClassOrMethodInstantiation()) { // Generics have an alternative location that is looked up which is based on the first generic // argument that the crossgen2 compiler will consider as requiring the cross module compilation logic to kick in. @@ -521,13 +521,13 @@ PCODE MethodDesc::GetPrecompiledR2RCode(PrepareCodeConfig* pConfig) pCode = pAlreadyExaminedInfos[1]->GetEntryPoint(this, pConfig, TRUE /* fFixups */); } - if (pCode == NULL) + if (pCode == (PCODE)NULL) { // R2R also supports a concept of R2R code that has code for "Unrelated" generics embedded within it // A linked list of these are formed as those modules are loaded, and this restricted set of modules // is examined for all generic method lookups ReadyToRunInfo* pUnrelatedInfo = ReadyToRunInfo::GetUnrelatedR2RModules(); - for (;pUnrelatedInfo != NULL && pCode == NULL; pUnrelatedInfo = pUnrelatedInfo->GetNextUnrelatedR2RModule()) + for (;pUnrelatedInfo != NULL && pCode == (PCODE)NULL; pUnrelatedInfo = pUnrelatedInfo->GetNextUnrelatedR2RModule()) { if (pUnrelatedInfo == pAlreadyExaminedInfos[0]) continue; if (pUnrelatedInfo == pAlreadyExaminedInfos[1]) continue; @@ -604,7 +604,7 @@ PCODE MethodDesc::JitCompileCode(PrepareCodeConfig* pConfig) CheckStacksAndPitch(); #endif - PCODE pCode = NULL; + PCODE pCode = (PCODE)NULL; { // Enter the global lock which protects the list of all functions being JITd JitListLock::LockHolder pJitLock(AppDomain::GetCurrentDomain()->GetJitLock()); @@ -680,7 +680,7 @@ PCODE MethodDesc::JitCompileCode(PrepareCodeConfig* pConfig) { bool wasTier0 = false; pCode = GetMulticoreJitCode(pConfig, &wasTier0); - if (pCode != NULL) + if (pCode != (PCODE)NULL) { #ifdef FEATURE_TIERED_COMPILATION // Finalize the optimization tier before SetNativeCode() is called @@ -760,7 +760,7 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J { STANDARD_VM_CONTRACT; - PCODE pCode = NULL; + PCODE pCode = (PCODE)NULL; ULONG sizeOfCode = 0; #ifdef PROFILING_SUPPORTED @@ -928,9 +928,9 @@ PCODE MethodDesc::JitCompileCodeLocked(PrepareCodeConfig* pConfig, COR_ILMETHOD_ { STANDARD_VM_CONTRACT; - PCODE pCode = NULL; + PCODE pCode = (PCODE)NULL; CORJIT_FLAGS jitFlags; - PCODE pOtherCode = NULL; + PCODE pOtherCode = (PCODE)NULL; EX_TRY { @@ -961,7 +961,7 @@ PCODE MethodDesc::JitCompileCodeLocked(PrepareCodeConfig* pConfig, COR_ILMETHOD_ } EX_END_CATCH(RethrowTerminalExceptions) - if (pOtherCode != NULL) + if (pOtherCode != (PCODE)NULL) { // Somebody finished jitting recursively while we were jitting the method. // Just use their method & leak the one we finished. (Normally we hope @@ -1087,7 +1087,7 @@ namespace CaNamedArg namedArgs[1]; CaType namedArgTypes[1]; namedArgTypes[0].Init(SERIALIZATION_TYPE_STRING); - namedArgs[0].Init("Name", SERIALIZATION_TYPE_PROPERTY, namedArgTypes[0], NULL); + namedArgs[0].Init("Name", SERIALIZATION_TYPE_PROPERTY, namedArgTypes[0]); if (FAILED(::ParseKnownCaNamedArgs(ca, namedArgs, ARRAY_SIZE(namedArgs)))) return false; @@ -1862,7 +1862,7 @@ BOOL PrepareCodeConfig::SetNativeCode(PCODE pCode, PCODE * ppAlternateCodeToUse) { LIMITED_METHOD_CONTRACT; - if (m_nativeCodeVersion.SetNativeCodeInterlocked(pCode, NULL)) + if (m_nativeCodeVersion.SetNativeCodeInterlocked(pCode, (PCODE)NULL)) { return TRUE; } @@ -2519,7 +2519,7 @@ static PCODE PreStubWorker_Preemptive( { _ASSERTE(pMD->HasUnmanagedCallersOnlyAttribute()); - PCODE pbRetVal = NULL; + PCODE pbRetVal = (PCODE)NULL; STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_TRIGGERS; @@ -2571,7 +2571,7 @@ static PCODE PreStubWorker_Preemptive( //============================================================================= extern "C" PCODE STDCALL PreStubWorker(TransitionBlock* pTransitionBlock, MethodDesc* pMD) { - PCODE pbRetVal = NULL; + PCODE pbRetVal = (PCODE)NULL; BEGIN_PRESERVE_LAST_ERROR; @@ -2731,7 +2731,7 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT, CallerGCMode callerGCMo CONTRACT_END; Stub *pStub = NULL; - PCODE pCode = NULL; + PCODE pCode = (PCODE)NULL; Thread *pThread = GetThread(); @@ -2874,13 +2874,13 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT, CallerGCMode callerGCMo // a stub, we'll use it directly instead and avoid emitting an IL stub. PrepareCodeConfig config(NativeCodeVersion(this), TRUE, TRUE); pCode = GetPrecompiledR2RCode(&config); - if (pCode != NULL) + if (pCode != (PCODE)NULL) { LOG_USING_R2R_CODE(this); } } - if (pCode == NULL) + if (pCode == (PCODE)NULL) { pCode = GetStubForInteropMethod(this); } @@ -2935,7 +2935,7 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT, CallerGCMode callerGCMo MemoryBarrier(); #endif - if (pCode != NULL) + if (pCode != (PCODE)NULL) { _ASSERTE(!MayHaveEntryPointSlotsToBackpatch()); // This path doesn't lock the MethodDescBackpatchTracker as it should only // happen for jump-stampable or non-versionable methods @@ -3036,7 +3036,7 @@ static PCODE PatchNonVirtualExternalMethod(MethodDesc * pMD, PCODE pCode, PTR_RE && pMD->IsNativeCodeStableAfterInit()) { PCODE pDirectTarget = pMD->IsFCall() ? ECall::GetFCallImpl(pMD) : pMD->GetNativeCode(); - if (pDirectTarget != NULL) + if (pDirectTarget != (PCODE)NULL) pCode = pDirectTarget; } #endif //HAS_FIXUP_PRECODE @@ -3080,7 +3080,7 @@ EXTERN_C PCODE STDCALL ExternalMethodFixupWorker(TransitionBlock * pTransitionBl // the value of the Last Error before it could be retrieved and saved. // - PCODE pCode = NULL; + PCODE pCode = (PCODE)NULL; BEGIN_PRESERVE_LAST_ERROR; @@ -3095,7 +3095,7 @@ EXTERN_C PCODE STDCALL ExternalMethodFixupWorker(TransitionBlock * pTransitionBl #if defined(TARGET_X86) || defined(TARGET_AMD64) // Decode indirection cell from callsite if it is not present - if (pIndirection == NULL) + if (pIndirection == (PCODE)NULL) { // Assume that the callsite is call [xxxxxxxx] PCODE retAddr = pEMFrame->GetReturnAddress(); @@ -3369,7 +3369,7 @@ static PCODE getHelperForInitializedStatic(Module * pModule, CORCOMPILE_FIXUP_BL { STANDARD_VM_CONTRACT; - PCODE pHelper = NULL; + PCODE pHelper = (PCODE)NULL; switch (kind) { @@ -3780,7 +3780,7 @@ PCODE DynamicHelperFixup(TransitionBlock * pTransitionBlock, TADDR * pCell, DWOR ThrowHR(COR_E_BADIMAGEFORMAT); } - PCODE pHelper = NULL; + PCODE pHelper = (PCODE)NULL; if (fReliable) { @@ -3883,7 +3883,7 @@ PCODE DynamicHelperFixup(TransitionBlock * pTransitionBlock, TADDR * pCell, DWOR UNREACHABLE(); } - if (pHelper != NULL) + if (pHelper != (PCODE)NULL) { *(TADDR *)pCell = pHelper; } @@ -3926,7 +3926,7 @@ PCODE DynamicHelperFixup(TransitionBlock * pTransitionBlock, TADDR * pCell, DWOR TADDR pArgument = GetFirstArgumentRegisterValuePtr(pTransitionBlock); - if (pArgument != NULL) + if (pArgument != (TADDR)NULL) { pDelegateType = (*(Object **)pArgument)->GetMethodTable(); _ASSERTE(pDelegateType->IsDelegate()); @@ -3953,7 +3953,7 @@ PCODE DynamicHelperFixup(TransitionBlock * pTransitionBlock, TADDR * pCell, DWOR } } - TADDR target = NULL; + TADDR target = (TADDR)NULL; if (pDelegateCtor != NULL) { @@ -3988,7 +3988,7 @@ PCODE DynamicHelperFixup(TransitionBlock * pTransitionBlock, TADDR * pCell, DWOR UNREACHABLE(); } - if (pHelper != NULL) + if (pHelper != (PCODE)NULL) { *(TADDR *)pCell = pHelper; } @@ -4004,8 +4004,8 @@ PCODE DynamicHelperFixup(TransitionBlock * pTransitionBlock, TADDR * pCell, DWOR extern "C" SIZE_T STDCALL DynamicHelperWorker(TransitionBlock * pTransitionBlock, TADDR * pCell, DWORD sectionIndex, Module * pModule, INT frameFlags) { - PCODE pHelper = NULL; - SIZE_T result = NULL; + PCODE pHelper = (PCODE)NULL; + SIZE_T result = 0; STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_TRIGGERS; @@ -4051,7 +4051,7 @@ extern "C" SIZE_T STDCALL DynamicHelperWorker(TransitionBlock * pTransitionBlock pHelper = DynamicHelperFixup(pTransitionBlock, pCell, sectionIndex, pModule, &kind, &th, &pMD, &pFD); } - if (pHelper == NULL) + if (pHelper == (PCODE)NULL) { TADDR pArgument = GetFirstArgumentRegisterValuePtr(pTransitionBlock); @@ -4068,7 +4068,7 @@ extern "C" SIZE_T STDCALL DynamicHelperWorker(TransitionBlock * pTransitionBlock else { _ASSERTE (!throwInvalidCast); - result = NULL; + result = 0; } } break; @@ -4126,7 +4126,7 @@ extern "C" SIZE_T STDCALL DynamicHelperWorker(TransitionBlock * pTransitionBlock pFrame->Pop(CURRENT_THREAD); - if (pHelper == NULL) + if (pHelper == (PCODE)NULL) *(SIZE_T *)((TADDR)pTransitionBlock + TransitionBlock::GetOffsetOfArgumentRegisters()) = result; return pHelper; } diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index e57cba3c597d..c70d50db81e8 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -341,7 +341,7 @@ static ClassID NonGenericTypeHandleToClassID(TypeHandle th) if ((!th.IsNull()) && (th.HasInstantiation())) { - return NULL; + return 0; } return TypeHandleToClassID(th); @@ -1067,7 +1067,7 @@ ClassID SafeGetClassIDFromObject(Object * pObj) TypeHandle th = pObj->GetGCSafeTypeHandleIfPossible(); if(th == NULL) { - return NULL; + return 0; } return TypeHandleToClassID(th); @@ -1635,7 +1635,7 @@ HRESULT ProfToEEInterfaceImpl::GetObjectSize(ObjectID objectId, ULONG *pcSize) "**PROF: GetObjectSize 0x%p.\n", objectId)); - if (objectId == NULL) + if (objectId == 0) { return E_INVALIDARG; } @@ -1699,7 +1699,7 @@ HRESULT ProfToEEInterfaceImpl::GetObjectSize2(ObjectID objectId, SIZE_T *pcSize) "**PROF: GetObjectSize2 0x%p.\n", objectId)); - if (objectId == NULL) + if (objectId == 0) { return E_INVALIDARG; } @@ -1763,7 +1763,7 @@ HRESULT ProfToEEInterfaceImpl::IsArrayClass( HRESULT hr; - if (classId == NULL) + if (classId == 0) { return E_INVALIDARG; } @@ -1801,7 +1801,7 @@ HRESULT ProfToEEInterfaceImpl::IsArrayClass( { if (pBaseClassId != NULL) { - *pBaseClassId = NULL; + *pBaseClassId = 0; } // This is not an array, S_FALSE indicates so. @@ -2130,7 +2130,7 @@ HRESULT ProfToEEInterfaceImpl::GetTokenAndMetaDataFromFunction( "**PROF: GetTokenAndMetaDataFromFunction 0x%p.\n", functionId)); - if (functionId == NULL) + if (functionId == 0) { return E_INVALIDARG; } @@ -2259,7 +2259,7 @@ HRESULT GetCodeInfoFromCodeStart( HRESULT hr; - if (start == NULL) + if (start == (PCODE)NULL) { return CORPROF_E_FUNCTION_NOT_COMPILED; } @@ -2310,7 +2310,7 @@ HRESULT GetCodeInfoFromCodeStart( codeInfos[0].size = methodRegionInfo.coldSize; } - if (NULL != methodRegionInfo.coldStartAddress) + if ((PCODE)NULL != methodRegionInfo.coldStartAddress) { if (cCodeInfos > 1) { @@ -2333,7 +2333,7 @@ HRESULT GetCodeInfoFromCodeStart( if (NULL != pcCodeInfos) { - *pcCodeInfos = (NULL != methodRegionInfo.coldStartAddress) ? 2 : 1; + *pcCodeInfos = ((PCODE)NULL != methodRegionInfo.coldStartAddress) ? 2 : 1; } @@ -2534,7 +2534,7 @@ HRESULT ProfToEEInterfaceImpl::GetCodeInfo3(FunctionID functionId, hr = ValidateParametersForGetCodeInfo(pMethodDesc, cCodeInfos, codeInfos); if (SUCCEEDED(hr)) { - PCODE pCodeStart = NULL; + PCODE pCodeStart = (PCODE)NULL; CodeVersionManager* pCodeVersionManager = pMethodDesc->GetCodeVersionManager(); { CodeVersionManager::LockHolder codeVersioningLockHolder; @@ -2755,7 +2755,7 @@ HRESULT ProfToEEInterfaceImpl::GetArrayObjectInfo(ObjectID objectId, "**PROF: GetArrayObjectInfo 0x%p.\n", objectId)); - if (objectId == NULL) + if (objectId == 0) { return E_INVALIDARG; } @@ -2886,7 +2886,7 @@ HRESULT ProfToEEInterfaceImpl::GetBoxClassLayout(ClassID classId, return E_INVALIDARG; } - if (classId == NULL) + if (classId == 0) { return E_INVALIDARG; } @@ -2949,7 +2949,7 @@ HRESULT ProfToEEInterfaceImpl::GetThreadAppDomain(ThreadID threadId, Thread *pThread; - if (threadId == NULL) + if (threadId == 0) { pThread = GetThreadNULLOk(); } @@ -2967,7 +2967,7 @@ HRESULT ProfToEEInterfaceImpl::GetThreadAppDomain(ThreadID threadId, return CORPROF_E_NOT_MANAGED_THREAD; } - *pAppDomainId = (AppDomainID)pThread->GetDomain(); + *pAppDomainId = (AppDomainID)AppDomain::GetCurrentDomain(); return S_OK; } @@ -3021,7 +3021,7 @@ HRESULT ProfToEEInterfaceImpl::GetRVAStaticAddress(ClassID classId, // // Check for NULL parameters // - if ((classId == NULL) || (ppAddress == NULL)) + if ((classId == 0) || (ppAddress == NULL)) { return E_INVALIDARG; } @@ -3139,7 +3139,7 @@ HRESULT ProfToEEInterfaceImpl::GetAppDomainStaticAddress(ClassID classId, // // Check for NULL parameters // - if ((classId == NULL) || (appDomainId == NULL) || (ppAddress == NULL)) + if ((classId == 0) || (appDomainId == 0) || (ppAddress == NULL)) { return E_INVALIDARG; } @@ -3285,7 +3285,7 @@ HRESULT ProfToEEInterfaceImpl::GetThreadStaticAddress(ClassID classId, // // Verify the value of threadId, which must be the current thread ID or NULL, which means using curernt thread ID. // - if ((threadId != NULL) && (threadId != ((ThreadID)GetThreadNULLOk()))) + if ((threadId != 0) && (threadId != ((ThreadID)GetThreadNULLOk()))) { return E_INVALIDARG; } @@ -3296,7 +3296,7 @@ HRESULT ProfToEEInterfaceImpl::GetThreadStaticAddress(ClassID classId, // // Check for NULL parameters // - if ((classId == NULL) || (ppAddress == NULL) || !IsManagedThread(threadId) || (appDomainId == NULL)) + if ((classId == 0) || (ppAddress == NULL) || !IsManagedThread(threadId) || (appDomainId == 0)) { return E_INVALIDARG; } @@ -3360,7 +3360,7 @@ HRESULT ProfToEEInterfaceImpl::GetThreadStaticAddress2(ClassID classId, threadId)); - if (threadId == NULL) + if (threadId == 0) { if (GetThreadNULLOk() == NULL) { @@ -3373,7 +3373,7 @@ HRESULT ProfToEEInterfaceImpl::GetThreadStaticAddress2(ClassID classId, // // Check for NULL parameters // - if ((classId == NULL) || (ppAddress == NULL) || !IsManagedThread(threadId) || (appDomainId == NULL)) + if ((classId == 0) || (ppAddress == NULL) || !IsManagedThread(threadId) || (appDomainId == 0)) { return E_INVALIDARG; } @@ -3539,7 +3539,7 @@ HRESULT ProfToEEInterfaceImpl::GetAppDomainsContainingModule(ModuleID moduleId, // // Check for NULL parameters // - if ((moduleId == NULL) || ((appDomainIds == NULL) && (cAppDomainIds != 0)) || (pcAppDomainIds == NULL)) + if ((moduleId == 0) || ((appDomainIds == NULL) && (cAppDomainIds != 0)) || (pcAppDomainIds == NULL)) { return E_INVALIDARG; } @@ -3614,7 +3614,7 @@ HRESULT ProfToEEInterfaceImpl::GetStaticFieldInfo(ClassID classId, // // Check for NULL parameters // - if ((classId == NULL) || (pFieldInfo == NULL)) + if ((classId == 0) || (pFieldInfo == NULL)) { return E_INVALIDARG; } @@ -3717,7 +3717,7 @@ HRESULT ProfToEEInterfaceImpl::GetClassIDInfo2(ClassID classId, // // Verify parameters. // - if (classId == NULL) + if (classId == 0) { return E_INVALIDARG; } @@ -3736,7 +3736,7 @@ HRESULT ProfToEEInterfaceImpl::GetClassIDInfo2(ClassID classId, { if (pParentClassId != NULL) { - *pParentClassId = NULL; + *pParentClassId = 0; } if (pModuleId != NULL) @@ -3779,7 +3779,7 @@ HRESULT ProfToEEInterfaceImpl::GetClassIDInfo2(ClassID classId, } else { - *pParentClassId = NULL; + *pParentClassId = 0; } } @@ -3996,7 +3996,7 @@ HRESULT ProfToEEInterfaceImpl::GetModuleInfo2(ModuleID moduleId, "**PROF: GetModuleInfo2 0x%p.\n", moduleId)); - if (moduleId == NULL) + if (moduleId == 0) { return E_INVALIDARG; } @@ -4149,7 +4149,7 @@ HRESULT ProfToEEInterfaceImpl::GetModuleMetaData(ModuleID moduleId, moduleId, dwOpenFlags)); - if (moduleId == NULL) + if (moduleId == 0) { return E_INVALIDARG; } @@ -4236,7 +4236,7 @@ HRESULT ProfToEEInterfaceImpl::GetILFunctionBody(ModuleID moduleId, ULONG RVA; // Return RVA of the method body. DWORD dwImplFlags; // Flags for the item. - if ((moduleId == NULL) || + if ((moduleId == 0) || (methodId == mdMethodDefNil) || (methodId == 0) || (TypeFromToken(methodId) != mdtMethodDef)) @@ -4359,7 +4359,7 @@ HRESULT ProfToEEInterfaceImpl::GetILFunctionBodyAllocator(ModuleID modul "**PROF: GetILFunctionBodyAllocator 0x%p.\n", moduleId)); - if ((moduleId == NULL) || (ppMalloc == NULL)) + if ((moduleId == 0) || (ppMalloc == NULL)) { return E_INVALIDARG; } @@ -4414,7 +4414,7 @@ HRESULT ProfToEEInterfaceImpl::SetILFunctionBody(ModuleID moduleId, moduleId, methodId)); - if ((moduleId == NULL) || + if ((moduleId == 0) || (methodId == mdMethodDefNil) || (TypeFromToken(methodId) != mdtMethodDef) || (pbNewILMethodHeader == NULL)) @@ -4489,7 +4489,7 @@ HRESULT ProfToEEInterfaceImpl::SetILInstrumentedCodeMap(FunctionID functionId, functionId, fStartJit)); - if (functionId == NULL) + if (functionId == 0) { return E_INVALIDARG; } @@ -4650,11 +4650,8 @@ HRESULT ProfToEEInterfaceImpl::GetThreadContext(ThreadID threadId, return E_INVALIDARG; } - // Cast to right type - Thread *pThread = reinterpret_cast(threadId); - // Get the context for the Thread* provided - AppDomain *pContext = pThread->GetDomain(); // Context is same as AppDomain in CoreCLR + AppDomain *pContext = AppDomain::GetCurrentDomain(); // Context is same as AppDomain in CoreCLR _ASSERTE(pContext); // If there's no current context, return incomplete info @@ -4698,19 +4695,19 @@ HRESULT ProfToEEInterfaceImpl::GetClassIDInfo(ClassID classId, "**PROF: GetClassIDInfo 0x%p.\n", classId)); - if (classId == NULL) + if (classId == 0) { return E_INVALIDARG; } if (pModuleId != NULL) { - *pModuleId = NULL; + *pModuleId = 0; } if (pTypeDefToken != NULL) { - *pTypeDefToken = NULL; + *pTypeDefToken = 0; } // Handle globals which don't have the instances. @@ -4726,7 +4723,7 @@ HRESULT ProfToEEInterfaceImpl::GetClassIDInfo(ClassID classId, *pTypeDefToken = mdTokenNil; } } - else if (classId == NULL) + else if (classId == 0) { return E_INVALIDARG; } @@ -4786,7 +4783,7 @@ HRESULT ProfToEEInterfaceImpl::GetFunctionInfo(FunctionID functionId, "**PROF: GetFunctionInfo 0x%p.\n", functionId)); - if (functionId == NULL) + if (functionId == 0) { return E_INVALIDARG; } @@ -4892,7 +4889,7 @@ HRESULT ProfToEEInterfaceImpl::GetILToNativeMapping2(FunctionID functionId, "**PROF: GetILToNativeMapping2 0x%p 0x%p.\n", functionId, reJitId)); - if (functionId == NULL) + if (functionId == 0) { return E_INVALIDARG; } @@ -4923,7 +4920,7 @@ HRESULT ProfToEEInterfaceImpl::GetILToNativeMapping2(FunctionID functionId, } else { - PCODE pCodeStart = NULL; + PCODE pCodeStart = (PCODE)NULL; CodeVersionManager *pCodeVersionManager = pMD->GetCodeVersionManager(); ILCodeVersion ilCodeVersion = NULL; { @@ -4981,7 +4978,7 @@ HRESULT ProfToEEInterfaceImpl::GetClassFromObject(ObjectID objectId, "**PROF: GetClassFromObject 0x%p.\n", objectId)); - if (objectId == NULL) + if (objectId == 0) { return E_INVALIDARG; } @@ -5037,7 +5034,7 @@ HRESULT ProfToEEInterfaceImpl::GetClassFromToken(ModuleID moduleId, moduleId, typeDef)); - if ((moduleId == NULL) || (typeDef == mdTypeDefNil) || (typeDef == NULL)) + if ((moduleId == 0) || (typeDef == mdTypeDefNil) || (typeDef == mdTokenNil)) { return E_INVALIDARG; } @@ -5087,7 +5084,7 @@ HRESULT ProfToEEInterfaceImpl::GetClassFromToken(ModuleID moduleId, // ClassID classId = NonGenericTypeHandleToClassID(th); - if (classId == NULL) + if (classId == 0) { return CORPROF_E_TYPE_IS_PARAMETERIZED; } @@ -5270,7 +5267,7 @@ HRESULT ProfToEEInterfaceImpl::GetFunctionFromToken(ModuleID moduleId, moduleId, typeDef)); - if ((moduleId == NULL) || (typeDef == mdTokenNil)) + if ((moduleId == 0) || (typeDef == mdTokenNil)) { return E_INVALIDARG; } @@ -5473,7 +5470,7 @@ HRESULT ProfToEEInterfaceImpl::GetAppDomainInfo(AppDomainID appDomainId, "**PROF: GetAppDomainInfo 0x%p.\n", appDomainId)); - if (appDomainId == NULL) + if (appDomainId == 0) { return E_INVALIDARG; } @@ -5584,7 +5581,7 @@ HRESULT ProfToEEInterfaceImpl::GetAssemblyInfo(AssemblyID assemblyId, "**PROF: GetAssemblyInfo 0x%p.\n", assemblyId)); - if (assemblyId == NULL) + if (assemblyId == 0) { return E_INVALIDARG; } @@ -5981,7 +5978,7 @@ HRESULT ProfToEEInterfaceImpl::GetFunctionInfo2(FunctionID funcId, // COR_PRF_FRAME_INFO_INTERNAL *pFrameInfo = (COR_PRF_FRAME_INFO_INTERNAL *)frameInfo; - if ((funcId == NULL) || + if ((funcId == 0) || ((pFrameInfo != NULL) && (pFrameInfo->funcID != funcId))) { return E_INVALIDARG; @@ -6005,7 +6002,7 @@ HRESULT ProfToEEInterfaceImpl::GetFunctionInfo2(FunctionID funcId, TypeHandle specificClass; MethodDesc* pActualMethod; - ClassID classId = NULL; + ClassID classId = 0; if (pMethDesc->IsSharedByGenericInstantiations()) { @@ -6056,7 +6053,7 @@ HRESULT ProfToEEInterfaceImpl::GetFunctionInfo2(FunctionID funcId, // // We could not get any class information. // - classId = NULL; + classId = 0; } } else @@ -6191,7 +6188,7 @@ HRESULT ProfToEEInterfaceImpl::IsFunctionDynamic(FunctionID functionId, BOOL *is // Verify parameters. // - if (functionId == NULL) + if (functionId == 0) { return E_INVALIDARG; } @@ -6346,7 +6343,7 @@ HRESULT ProfToEEInterfaceImpl::GetDynamicFunctionInfo(FunctionID functionId, // Verify parameters. // - if (functionId == NULL) + if (functionId == 0) { return E_INVALIDARG; } @@ -6453,7 +6450,7 @@ HRESULT ProfToEEInterfaceImpl::GetNativeCodeStartAddresses(FunctionID functionID } CONTRACTL_END; - if (functionID == NULL) + if (functionID == 0) { return E_INVALIDARG; } @@ -6491,7 +6488,7 @@ HRESULT ProfToEEInterfaceImpl::GetNativeCodeStartAddresses(FunctionID functionID { PCODE codeStart = (*iter).GetNativeCode(); - if (codeStart != NULL) + if (codeStart != (PCODE)NULL) { addresses.Append(codeStart); ++trueLen; @@ -6564,7 +6561,7 @@ HRESULT ProfToEEInterfaceImpl::GetILToNativeMapping3(UINT_PTR pNativeCodeStartAd "**PROF: GetILToNativeMapping3 0x%p.\n", pNativeCodeStartAddress)); - if (pNativeCodeStartAddress == NULL) + if (pNativeCodeStartAddress == (PCODE)NULL) { return E_INVALIDARG; } @@ -7409,7 +7406,7 @@ HRESULT ProfToEEInterfaceImpl::CreateHandle( LL_INFO1000, "**PROF: CreateHandle.\n")); - if (object == NULL) + if (object == 0) { return E_INVALIDARG; } @@ -7833,7 +7830,7 @@ HRESULT ProfToEEInterfaceImpl::GetClassLayout(ClassID classID, // // Verify parameters // - if ((pcFieldOffset == NULL) || (classID == NULL)) + if ((pcFieldOffset == NULL) || (classID == 0)) { return E_INVALIDARG; } @@ -8030,7 +8027,7 @@ StackWalkAction ProfilerStackWalkCallback(CrawlFrame *pCf, PROFILER_STACK_WALK_D } else { - frameInfo.funcID = NULL; + frameInfo.funcID = 0; frameInfo.extraArg = NULL; } @@ -8542,7 +8539,7 @@ HRESULT ProfToEEInterfaceImpl::DoStackSnapshot(ThreadID thread, return CORPROF_E_INCONSISTENT_WITH_FLAGS; } - if (thread == NULL) + if (thread == 0) { pThreadToSnapshot = pCurrentThread; } @@ -9732,7 +9729,7 @@ HRESULT ProfilingGetFunctionEnter3Info(FunctionID functionId, } CONTRACTL_END; - if ((functionId == NULL) || (eltInfo == NULL)) + if ((functionId == 0) || (eltInfo == 0)) { return E_INVALIDARG; } @@ -9931,7 +9928,7 @@ HRESULT ProfilingGetFunctionLeave3Info(FunctionID functionId, } CONTRACTL_END; - if ((pFrameInfo == NULL) || (eltInfo == NULL)) + if ((pFrameInfo == NULL) || (eltInfo == 0)) { return E_INVALIDARG; } @@ -10093,7 +10090,7 @@ HRESULT ProfilingGetFunctionTailcall3Info(FunctionID functionId, } CONTRACTL_END; - if ((functionId == NULL) || (eltInfo == NULL) || (pFrameInfo == NULL)) + if ((functionId == 0) || (eltInfo == 0) || (pFrameInfo == NULL)) { return E_INVALIDARG; } @@ -10540,7 +10537,7 @@ HRESULT ProfToEEInterfaceImpl::ApplyMetaData( PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach | kP2EETriggers, (LF_CORPROF, LL_INFO1000, "**PROF: ApplyMetaData.\n")); - if (moduleId == NULL) + if (moduleId == 0) { return E_INVALIDARG; } @@ -10734,7 +10731,7 @@ HCIMPL_PROLOG(ProfileEnter) g_profControlBlock.mainProfilerInfo.pProfInterface->GetEnter2Hook()( functionId, clientData, - NULL, + 0, NULL); goto LExit; } @@ -10744,7 +10741,7 @@ HCIMPL_PROLOG(ProfileEnter) // ProfileSetFunctionIDInPlatformSpecificHandle(platformSpecificHandle, functionId); - COR_PRF_FRAME_INFO frameInfo = NULL; + COR_PRF_FRAME_INFO frameInfo = 0; COR_PRF_FUNCTION_ARGUMENT_INFO * pArgumentInfo = NULL; ULONG ulArgInfoSize = 0; @@ -10908,7 +10905,7 @@ HCIMPL_PROLOG(ProfileLeave) g_profControlBlock.mainProfilerInfo.pProfInterface->GetLeave2Hook()( functionId, clientData, - NULL, + 0, NULL); goto LExit; } @@ -10916,7 +10913,7 @@ HCIMPL_PROLOG(ProfileLeave) // // Whidbey Slow-Path ELT // - COR_PRF_FRAME_INFO frameInfo = NULL; + COR_PRF_FRAME_INFO frameInfo = 0; COR_PRF_FUNCTION_ARGUMENT_RANGE argumentRange; HRESULT hr = ProfilingGetFunctionLeave3Info(functionId, (COR_PRF_ELT_INFO)&eltInfo, &frameInfo, &argumentRange); @@ -11040,14 +11037,14 @@ HCIMPL2(EXTERN_C void, ProfileTailcall, UINT_PTR clientData, void * platformSpec g_profControlBlock.mainProfilerInfo.pProfInterface->GetTailcall2Hook()( functionId, clientData, - NULL); + 0); goto LExit; } // // Whidbey Slow-Path ELT // - COR_PRF_FRAME_INFO frameInfo = NULL; + COR_PRF_FRAME_INFO frameInfo = 0; HRESULT hr = ProfilingGetFunctionTailcall3Info(functionId, (COR_PRF_ELT_INFO)&eltInfo, &frameInfo); _ASSERTE(hr == S_OK); diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 1150c55aa36d..e038db62831d 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -43,7 +43,6 @@ #ifdef FEATURE_COMINTEROP #include "variant.h" -#include "oavariant.h" #include "mngstdinterfaces.h" #endif // FEATURE_COMINTEROP @@ -285,6 +284,7 @@ static const Entry s_QCall[] = DllImportEntry(MarshalNative_GetTypeFromCLSID) DllImportEntry(MarshalNative_GetIUnknownForObject) DllImportEntry(MarshalNative_GetIDispatchForObject) + DllImportEntry(MarshalNative_GetIUnknownOrIDispatchForObject) DllImportEntry(MarshalNative_GetComInterfaceForObject) DllImportEntry(MarshalNative_GetObjectForIUnknown) DllImportEntry(MarshalNative_GetUniqueObjectForIUnknown) @@ -318,7 +318,8 @@ static const Entry s_QCall[] = DllImportEntry(MngdSafeArrayMarshaler_ConvertSpaceToManaged) DllImportEntry(MngdSafeArrayMarshaler_ConvertContentsToManaged) DllImportEntry(MngdSafeArrayMarshaler_ClearNative) - DllImportEntry(OAVariant_ChangeType) + DllImportEntry(Variant_ConvertSystemColorToOleColor) + DllImportEntry(Variant_ConvertOleColorToSystemColor) #endif // FEATURE_COMINTEROP DllImportEntry(NativeLibrary_LoadFromPath) DllImportEntry(NativeLibrary_LoadByName) @@ -333,10 +334,12 @@ static const Entry s_QCall[] = DllImportEntry(Monitor_Pulse) DllImportEntry(Monitor_PulseAll) DllImportEntry(Monitor_GetLockContentionCount) + DllImportEntry(MetadataImport_Enum) DllImportEntry(ReflectionInvocation_RunClassConstructor) DllImportEntry(ReflectionInvocation_RunModuleConstructor) DllImportEntry(ReflectionInvocation_CompileMethod) DllImportEntry(ReflectionInvocation_PrepareMethod) + DllImportEntry(ReflectionInvocation_SizeOf) DllImportEntry(ReflectionSerialization_GetCreateUninitializedObjectInfo) #if defined(FEATURE_COMWRAPPERS) DllImportEntry(ComWrappers_GetIUnknownImpl) diff --git a/src/coreclr/vm/readytoruninfo.cpp b/src/coreclr/vm/readytoruninfo.cpp index a047e17ffa3d..4facca3a37bf 100644 --- a/src/coreclr/vm/readytoruninfo.cpp +++ b/src/coreclr/vm/readytoruninfo.cpp @@ -1019,7 +1019,7 @@ bool ReadyToRunInfo::GetPgoInstrumentationData(MethodDesc * pMD, BYTE** pAllocat { STANDARD_VM_CONTRACT; - PCODE pEntryPoint = NULL; + PCODE pEntryPoint = (PCODE)NULL; #ifdef PROFILING_SUPPORTED BOOL fShouldSearchCache = TRUE; #endif // PROFILING_SUPPORTED @@ -1092,7 +1092,7 @@ PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, PrepareCodeConfig* pConfig bool printedStart = false; #endif - PCODE pEntryPoint = NULL; + PCODE pEntryPoint = (PCODE)NULL; #ifdef PROFILING_SUPPORTED BOOL fShouldSearchCache = TRUE; #endif // PROFILING_SUPPORTED diff --git a/src/coreclr/vm/reflectioninvocation.cpp b/src/coreclr/vm/reflectioninvocation.cpp index a7f88289d037..f57e21801253 100644 --- a/src/coreclr/vm/reflectioninvocation.cpp +++ b/src/coreclr/vm/reflectioninvocation.cpp @@ -113,54 +113,6 @@ FCIMPL2(FC_BOOL_RET, ReflectionInvocation::CanValueSpecialCast, ReflectClassBase } FCIMPLEND -/// -/// Allocate the value type and copy the optional value into it. -/// -FCIMPL2(Object*, ReflectionInvocation::AllocateValueType, ReflectClassBaseObject *pTargetTypeUNSAFE, Object *valueUNSAFE) { - CONTRACTL - { - FCALL_CHECK; - PRECONDITION(CheckPointer(pTargetTypeUNSAFE)); - PRECONDITION(CheckPointer(valueUNSAFE, NULL_OK)); - } - CONTRACTL_END; - - struct _gc - { - REFLECTCLASSBASEREF refTargetType; - OBJECTREF value; - OBJECTREF obj; - }gc; - - gc.value = ObjectToOBJECTREF(valueUNSAFE); - gc.obj = gc.value; - gc.refTargetType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTargetTypeUNSAFE); - - HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); - - TypeHandle targetType = gc.refTargetType->GetType(); - - // This method is only intended for value types; it is not called directly by any public APIs - // so we don't expect validation issues here. - _ASSERTE(targetType.IsValueType()); - - MethodTable* allocMT = targetType.AsMethodTable(); - _ASSERTE(!allocMT->IsByRefLike()); - - gc.obj = allocMT->Allocate(); - _ASSERTE(gc.obj != NULL); - - if (gc.value != NULL) { - _ASSERTE(allocMT->IsEquivalentTo(gc.value->GetMethodTable())); - CopyValueClass(gc.obj->UnBox(), gc.value->UnBox(), allocMT); - } - - HELPER_METHOD_FRAME_END(); - - return OBJECTREFToObject(gc.obj); -} -FCIMPLEND - FCIMPL6(void, RuntimeFieldHandle::SetValue, ReflectFieldObject *pFieldUNSAFE, Object *targetUNSAFE, Object *valueUNSAFE, ReflectClassBaseObject *pFieldTypeUNSAFE, ReflectClassBaseObject *pDeclaringTypeUNSAFE, CLR_BOOL *pIsClassInitialized) { CONTRACTL { @@ -1095,7 +1047,7 @@ FCIMPL5(void, RuntimeFieldHandle::SetValueDirect, ReflectFieldObject *pFieldUNSA Assembly *pAssem = pField->GetModule()->GetAssembly(); BYTE *pDst = NULL; - ARG_SLOT value = NULL; + ARG_SLOT value = 0; CorElementType fieldElType; HELPER_METHOD_FRAME_BEGIN_PROTECT(gc); @@ -1535,24 +1487,6 @@ FCIMPL4(void, ReflectionInvocation::MakeTypedReference, TypedByRef * value, Obje } FCIMPLEND -FCIMPL2_IV(Object*, ReflectionInvocation::CreateEnum, ReflectClassBaseObject *pTypeUNSAFE, INT64 value) { - FCALL_CONTRACT; - - REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE); - - TypeHandle typeHandle = refType->GetType(); - _ASSERTE(typeHandle.IsEnum()); - OBJECTREF obj = NULL; - HELPER_METHOD_FRAME_BEGIN_RET_1(refType); - MethodTable *pEnumMT = typeHandle.AsMethodTable(); - obj = pEnumMT->Box(ArgSlotEndiannessFixup ((ARG_SLOT*)&value, - pEnumMT->GetNumInstanceFieldBytes())); - - HELPER_METHOD_FRAME_END(); - return OBJECTREFToObject(obj); -} -FCIMPLEND - #ifdef FEATURE_COMINTEROP FCIMPL8(Object*, ReflectionInvocation::InvokeDispMethod, ReflectClassBaseObject* refThisUNSAFE, StringObject* nameUNSAFE, @@ -1835,9 +1769,9 @@ extern "C" void QCALLTYPE RuntimeTypeHandle_GetActivationInfo( if (pMT->IsNullable()) { // CreateInstance returns null given Nullable - *ppfnAllocator = NULL; + *ppfnAllocator = (PCODE)NULL; *pvAllocatorFirstArg = NULL; - *ppfnCtor = NULL; + *ppfnCtor = (PCODE)NULL; *pfCtorIsPublic = TRUE; // no ctor call needed => assume 'public' equivalent } else @@ -1855,14 +1789,14 @@ extern "C" void QCALLTYPE RuntimeTypeHandle_GetActivationInfo( _ASSERTE(pMD != NULL); PCODE pCode = pMD->GetMultiCallableAddrOfCode(); - _ASSERTE(pCode != NULL); + _ASSERTE(pCode != (PCODE)NULL); *ppfnCtor = pCode; *pfCtorIsPublic = pMD->IsPublic(); } else if (pMT->IsValueType()) { - *ppfnCtor = NULL; // no ctor call needed; we're creating a boxed default(T) + *ppfnCtor = (PCODE)NULL; // no ctor call needed; we're creating a boxed default(T) *pfCtorIsPublic = TRUE; // no ctor call needed => assume 'public' equivalent } else @@ -1965,7 +1899,7 @@ extern "C" void QCALLTYPE ReflectionSerialization_GetCreateUninitializedObjectIn bool fHasSideEffectsUnused; *ppfnAllocator = CEEJitInfo::getHelperFtnStatic(CEEInfo::getNewHelperStatic(pMT, &fHasSideEffectsUnused)); *pvAllocatorFirstArg = pMT; - + pMT->EnsureInstanceActive(); if (pMT->HasPreciseInitCctors()) @@ -2050,6 +1984,7 @@ extern "C" void QCALLTYPE Enum_GetValuesAndNames(QCall::TypeHandle pEnumType, QC MDDefaultValue defaultValue = { }; IfFailThrow(pImport->GetDefaultValue(field, &defaultValue)); + _ASSERTE(defaultValue.m_bType != ELEMENT_TYPE_STRING); // Strings in metadata are little-endian. // The following code assumes that the address of all union members is the same. static_assert_no_msg(offsetof(MDDefaultValue, m_byteValue) == offsetof(MDDefaultValue, m_usValue)); @@ -2105,18 +2040,15 @@ extern "C" void QCALLTYPE Enum_GetValuesAndNames(QCall::TypeHandle pEnumType, QC END_QCALL; } -FCIMPL2_IV(Object*, ReflectionEnum::InternalBoxEnum, ReflectClassBaseObject* target, INT64 value) { - FCALL_CONTRACT; - - VALIDATEOBJECT(target); - OBJECTREF ret = NULL; +extern "C" int32_t QCALLTYPE ReflectionInvocation_SizeOf(QCall::TypeHandle pType) +{ + QCALL_CONTRACT_NO_GC_TRANSITION; - MethodTable* pMT = target->GetType().AsMethodTable(); - HELPER_METHOD_FRAME_BEGIN_RET_0(); + TypeHandle handle = pType.AsTypeHandle(); - ret = pMT->Box(ArgSlotEndiannessFixup((ARG_SLOT*)&value, pMT->GetNumInstanceFieldBytes())); + // -1 is the same sentinel value returned by GetSize for an invalid type. + if (handle.ContainsGenericVariables()) + return -1; - HELPER_METHOD_FRAME_END(); - return OBJECTREFToObject(ret); + return handle.GetSize(); } -FCIMPLEND diff --git a/src/coreclr/vm/reflectioninvocation.h b/src/coreclr/vm/reflectioninvocation.h index 967e9744790e..3bbf1d57bb1e 100644 --- a/src/coreclr/vm/reflectioninvocation.h +++ b/src/coreclr/vm/reflectioninvocation.h @@ -57,11 +57,9 @@ class ReflectionInvocation { static FCDECL8(Object*, InvokeDispMethod, ReflectClassBaseObject* refThisUNSAFE, StringObject* nameUNSAFE, INT32 invokeAttr, Object* targetUNSAFE, PTRArray* argsUNSAFE, PTRArray* byrefModifiersUNSAFE, LCID lcid, PTRArray* namedParametersUNSAFE); #endif // FEATURE_COMINTEROP static FCDECL2(void, GetGUID, ReflectClassBaseObject* refThisUNSAFE, GUID * result); - static FCDECL2_IV(Object*, CreateEnum, ReflectClassBaseObject *pTypeUNSAFE, INT64 value); // helper fcalls for invocation static FCDECL2(FC_BOOL_RET, CanValueSpecialCast, ReflectClassBaseObject *valueType, ReflectClassBaseObject *targetType); - static FCDECL2(Object*, AllocateValueType, ReflectClassBaseObject *targetType, Object *valueUNSAFE); }; extern "C" void QCALLTYPE ReflectionInvocation_CompileMethod(MethodDesc * pMD); @@ -77,9 +75,10 @@ extern "C" void QCALLTYPE ReflectionSerialization_GetCreateUninitializedObjectIn class ReflectionEnum { public: static FCDECL1(INT32, InternalGetCorElementType, MethodTable* pMT); - static FCDECL2_IV(Object*, InternalBoxEnum, ReflectClassBaseObject* pEnumType, INT64 value); }; extern "C" void QCALLTYPE Enum_GetValuesAndNames(QCall::TypeHandle pEnumType, QCall::ObjectHandleOnStack pReturnValues, QCall::ObjectHandleOnStack pReturnNames, BOOL fGetNames); +extern "C" int32_t QCALLTYPE ReflectionInvocation_SizeOf(QCall::TypeHandle pType); + #endif // _REFLECTIONINVOCATION_H_ diff --git a/src/coreclr/vm/rejit.cpp b/src/coreclr/vm/rejit.cpp index 071fddacb3f4..5b92be45104a 100644 --- a/src/coreclr/vm/rejit.cpp +++ b/src/coreclr/vm/rejit.cpp @@ -1134,7 +1134,7 @@ ReJITID ReJitManager::GetReJitId(PTR_MethodDesc pMD, PCODE pCodeStart) // of a lock to impact our caller (the prestub worker) as little as possible. If the // map is nonempty, we'll acquire the lock at that point and do the lookup for real. CodeVersionManager* pCodeVersionManager = pMD->GetCodeVersionManager(); - if (pCodeVersionManager->GetNonDefaultILVersionCount() == 0) + if (!pCodeVersionManager->HasNonDefaultILVersions()) { return 0; } diff --git a/src/coreclr/vm/rexcep.h b/src/coreclr/vm/rexcep.h index 3f2c1cee117a..648a08865d73 100644 --- a/src/coreclr/vm/rexcep.h +++ b/src/coreclr/vm/rexcep.h @@ -144,7 +144,6 @@ DEFINE_EXCEPTION(g_SystemNS, FieldAccessException, false, C DEFINE_EXCEPTION(g_IONS, FileLoadException, true, COR_E_FILELOAD, FUSION_E_INVALID_NAME, - FUSION_E_PRIVATE_ASM_DISALLOWED, FUSION_E_REF_DEF_MISMATCH, HRESULT_FROM_WIN32(ERROR_TOO_MANY_OPEN_FILES), HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), HRESULT_FROM_WIN32(ERROR_LOCK_VIOLATION), diff --git a/src/coreclr/vm/riscv64/asmconstants.h b/src/coreclr/vm/riscv64/asmconstants.h index 8076ee94f213..d10d2d4dabc9 100644 --- a/src/coreclr/vm/riscv64/asmconstants.h +++ b/src/coreclr/vm/riscv64/asmconstants.h @@ -214,16 +214,16 @@ ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next)) #define InlinedCallFrame__m_Datum 0x10 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum)) -#define InlinedCallFrame__m_pCallSiteSP 0x20 +#define InlinedCallFrame__m_pCallSiteSP 0x18 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP)) -#define InlinedCallFrame__m_pCallerReturnAddress 0x28 +#define InlinedCallFrame__m_pCallerReturnAddress 0x20 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress)) -#define InlinedCallFrame__m_pCalleeSavedFP 0x30 +#define InlinedCallFrame__m_pCalleeSavedFP 0x28 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP)) -#define InlinedCallFrame__m_pThread 0x38 +#define InlinedCallFrame__m_pThread 0x30 ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pThread == offsetof(InlinedCallFrame, m_pThread)) #define FixupPrecodeData__Target 0x00 diff --git a/src/coreclr/vm/riscv64/asmhelpers.S b/src/coreclr/vm/riscv64/asmhelpers.S index b64ac8725e15..8035a64f7769 100644 --- a/src/coreclr/vm/riscv64/asmhelpers.S +++ b/src/coreclr/vm/riscv64/asmhelpers.S @@ -382,7 +382,7 @@ NESTED_ENTRY ThePreStub, _TEXT, NoHandler EPILOG_BRANCH_REG t4 NESTED_END ThePreStub, _TEXT -// ------------------------------------------------------------------\ +// ------------------------------------------------------------------ // EXTERN_C int __fastcall HelperMethodFrameRestoreState( // INDEBUG_COMMA(HelperMethodFrame *pFrame) diff --git a/src/coreclr/vm/riscv64/profiler.cpp b/src/coreclr/vm/riscv64/profiler.cpp index 1cff4dfaa45e..fc8eff484563 100644 --- a/src/coreclr/vm/riscv64/profiler.cpp +++ b/src/coreclr/vm/riscv64/profiler.cpp @@ -112,10 +112,10 @@ LPVOID ProfileArgIterator::CopyStructFromRegisters(const ArgLocDesc* sir) PROFILE_PLATFORM_SPECIFIC_DATA* pData = reinterpret_cast(m_handle); struct { bool isFloat, is8; } fields[] = { - { sir->m_structFields & (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_ONLY_TWO | STRUCT_FLOAT_FIELD_ONLY_ONE), - sir->m_structFields & STRUCT_FIRST_FIELD_SIZE_IS8 }, - { sir->m_structFields & (STRUCT_FLOAT_FIELD_SECOND | STRUCT_FLOAT_FIELD_ONLY_TWO), - sir->m_structFields & STRUCT_SECOND_FIELD_SIZE_IS8 }, + { (bool) (sir->m_structFields & (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_ONLY_TWO | STRUCT_FLOAT_FIELD_ONLY_ONE)), + (bool) (sir->m_structFields & STRUCT_FIRST_FIELD_SIZE_IS8) }, + { (bool) (sir->m_structFields & (STRUCT_FLOAT_FIELD_SECOND | STRUCT_FLOAT_FIELD_ONLY_TWO)), + (bool) (sir->m_structFields & STRUCT_SECOND_FIELD_SIZE_IS8) }, }; int fieldCount = (sir->m_structFields & STRUCT_FLOAT_FIELD_ONLY_ONE) ? 1 : 2; UINT64 bufferPosBegin = m_bufferPos; @@ -191,11 +191,11 @@ LPVOID ProfileArgIterator::GetNextArgAddr() } } - int argSize = m_argIterator.IsArgPassedByRef() ? sizeof(void*) : m_argIterator.GetArgSize(); + int argSize = m_argIterator.IsArgPassedByRef() ? (int)sizeof(void*) : m_argIterator.GetArgSize(); if (TransitionBlock::IsFloatArgumentRegisterOffset(argOffset)) { int offset = argOffset - TransitionBlock::GetOffsetOfFloatArgumentRegisters(); - _ASSERTE(offset + argSize <= sizeof(pData->floatArgumentRegisters)); + _ASSERTE(offset + argSize <= (int)sizeof(pData->floatArgumentRegisters)); return (LPBYTE)&pData->floatArgumentRegisters + offset; } @@ -204,7 +204,7 @@ LPVOID ProfileArgIterator::GetNextArgAddr() if (TransitionBlock::IsArgumentRegisterOffset(argOffset)) { int offset = argOffset - TransitionBlock::GetOffsetOfArgumentRegisters(); - if (offset + argSize > sizeof(pData->argumentRegisters)) + if (offset + argSize > (int)sizeof(pData->argumentRegisters)) { // Struct partially spilled on stack const int regIndex = NUM_ARGUMENT_REGISTERS - 1; // first part of struct must be in last register diff --git a/src/coreclr/vm/riscv64/stubs.cpp b/src/coreclr/vm/riscv64/stubs.cpp index ebc0d0495c2a..078fb9950073 100644 --- a/src/coreclr/vm/riscv64/stubs.cpp +++ b/src/coreclr/vm/riscv64/stubs.cpp @@ -88,7 +88,7 @@ class BranchInstructionFormat : public InstructionFormat } } - virtual VOID EmitInstruction(UINT refSize, __int64 fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) + virtual VOID EmitInstruction(UINT refSize, int64_t fixedUpReference, BYTE *pOutBufferRX, BYTE *pOutBufferRW, UINT variationCode, BYTE *pDataBuffer) { LIMITED_METHOD_CONTRACT; @@ -96,7 +96,7 @@ class BranchInstructionFormat : public InstructionFormat { _ASSERTE(((UINT_PTR)pDataBuffer & 7) == 0); - __int64 dataOffset = pDataBuffer - pOutBufferRW; + int64_t dataOffset = pDataBuffer - pOutBufferRW; if ((dataOffset < -(0x80000000L)) || (dataOffset > 0x7fffffff)) COMPlusThrow(kNotSupportedException); @@ -119,13 +119,13 @@ class BranchInstructionFormat : public InstructionFormat *(DWORD*)(pOutBufferRW + 12) = 0x00030067 ;// jalr x0, t1,0 } - *((__int64*)pDataBuffer) = fixedUpReference + (__int64)pOutBufferRX; + *((int64_t*)pDataBuffer) = fixedUpReference + (int64_t)pOutBufferRX; } else { _ASSERTE(((UINT_PTR)pDataBuffer & 7) == 0); - __int64 dataOffset = pDataBuffer - pOutBufferRW; + int64_t dataOffset = pDataBuffer - pOutBufferRW; if ((dataOffset < -(0x80000000L)) || (dataOffset > 0x7fffffff)) COMPlusThrow(kNotSupportedException); @@ -146,9 +146,9 @@ class BranchInstructionFormat : public InstructionFormat *(DWORD*)(pOutBufferRW + 8) = 0x00030067 ;// jalr x0, t1,0 } - if (!ClrSafeInt<__int64>::addition(fixedUpReference, (__int64)pOutBufferRX, fixedUpReference)) + if (!ClrSafeInt::addition(fixedUpReference, (int64_t)pOutBufferRX, fixedUpReference)) COMPlusThrowArithmetic(); - *((__int64*)pDataBuffer) = fixedUpReference; + *((int64_t*)pDataBuffer) = fixedUpReference; } } }; @@ -1070,7 +1070,7 @@ void StubLinkerCPU::EmitMovConstant(IntReg reg, UINT64 imm) if (high31 & 0x800) { // EmitAddImm does not allow negative immediate values, so use EmitSubImm. - EmitSubImm(reg, reg, ~high31 + 1 & 0xFFF); + EmitSubImm(reg, reg, (~high31 + 1) & 0xFFF); } else { diff --git a/src/coreclr/vm/runtimecallablewrapper.h b/src/coreclr/vm/runtimecallablewrapper.h index 0be5aaf97c05..229966e307fd 100644 --- a/src/coreclr/vm/runtimecallablewrapper.h +++ b/src/coreclr/vm/runtimecallablewrapper.h @@ -788,11 +788,11 @@ FORCEINLINE void NewRCWHolderRelease(RCW* p) } }; -class NewRCWHolder : public Wrapper +class NewRCWHolder : public Wrapper { public: NewRCWHolder(RCW* p = NULL) - : Wrapper(p) + : Wrapper(p) { WRAPPER_NO_CONTRACT; } @@ -800,7 +800,7 @@ class NewRCWHolder : public Wrapper::operator=(p); + Wrapper::operator=(p); } }; @@ -1424,11 +1424,11 @@ FORCEINLINE void CtxEntryHolderRelease(CtxEntry *p) } } -class CtxEntryHolder : public Wrapper +class CtxEntryHolder : public Wrapper { public: CtxEntryHolder(CtxEntry *p = NULL) - : Wrapper(p) + : Wrapper(p) { WRAPPER_NO_CONTRACT; } @@ -1437,7 +1437,7 @@ class CtxEntryHolder : public Wrapper::operator=(p); + Wrapper::operator=(p); } }; diff --git a/src/coreclr/vm/runtimehandles.cpp b/src/coreclr/vm/runtimehandles.cpp index 8b07e6d42ed3..c660763f1157 100644 --- a/src/coreclr/vm/runtimehandles.cpp +++ b/src/coreclr/vm/runtimehandles.cpp @@ -147,7 +147,7 @@ NOINLINE static ReflectClassBaseObject* GetRuntimeTypeHelper(LPVOID __me, TypeHa // RuntimeTypeHandle::GetRuntimeType has picked off the most common case, but does not cover array types. // Before we do the really heavy weight option of setting up a helper method frame, check if we have to. - OBJECTREF refType = typeHandle.GetManagedClassObjectFast(); + OBJECTREF refType = typeHandle.GetManagedClassObjectIfExists(); if (refType != NULL) return (ReflectClassBaseObject*)OBJECTREFToObject(refType); @@ -1488,21 +1488,6 @@ FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::ContainsGenericVariables, PTR_ReflectCla } FCIMPLEND -FCIMPL1(IMDInternalImport*, RuntimeTypeHandle::GetMetadataImport, ReflectClassBaseObject * pTypeUNSAFE) -{ - FCALL_CONTRACT; - - REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE); - - if (refType == NULL) - FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); - - Module *pModule = refType->GetType().GetModule(); - - return pModule->GetMDImport(); -} -FCIMPLEND - extern "C" void* QCALLTYPE RuntimeTypeHandle_AllocateTypeAssociatedMemory(QCall::TypeHandle type, uint32_t size) { QCALL_CONTRACT; @@ -2790,20 +2775,6 @@ FCIMPL1(INT32, ModuleHandle::GetToken, ReflectModuleBaseObject * pModuleUNSAFE) } FCIMPLEND -FCIMPL1(IMDInternalImport*, ModuleHandle::GetMetadataImport, ReflectModuleBaseObject * pModuleUNSAFE) -{ - FCALL_CONTRACT; - - REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE); - - if (refModule == NULL) - FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); - - Module *pModule = refModule->GetModule(); - return pModule->GetMDImport(); -} -FCIMPLEND - extern "C" void QCALLTYPE ModuleHandle_ResolveType(QCall::ModuleHandle pModule, INT32 tkType, TypeHandle *typeArgs, INT32 typeArgsCount, TypeHandle *methodArgs, INT32 methodArgsCount, QCall::ObjectHandleOnStack retType) { QCALL_CONTRACT; diff --git a/src/coreclr/vm/runtimehandles.h b/src/coreclr/vm/runtimehandles.h index 6b0d995977c6..56bb2df245f9 100644 --- a/src/coreclr/vm/runtimehandles.h +++ b/src/coreclr/vm/runtimehandles.h @@ -163,8 +163,6 @@ class RuntimeTypeHandle { static FCDECL1(MethodDesc *, GetFirstIntroducedMethod, ReflectClassBaseObject* pType); static FCDECL1(void, GetNextIntroducedMethod, MethodDesc **ppMethod); - static FCDECL1(IMDInternalImport*, GetMetadataImport, ReflectClassBaseObject * pModuleUNSAFE); - // Helper methods not called by managed code static void ValidateTypeAbleToBeInstantiated(TypeHandle typeHandle, bool fGetUninitializedObject); @@ -316,13 +314,7 @@ class ModuleHandle { public: static FCDECL5(ReflectMethodObject*, GetDynamicMethod, ReflectMethodObject *pMethodUNSAFE, ReflectModuleBaseObject *pModuleUNSAFE, StringObject *name, U1Array *sig, Object *resolver); static FCDECL1(INT32, GetToken, ReflectModuleBaseObject *pModuleUNSAFE); - - static - FCDECL1(IMDInternalImport*, GetMetadataImport, ReflectModuleBaseObject * pModuleUNSAFE); - - static - FCDECL1(INT32, GetMDStreamVersion, ReflectModuleBaseObject * pModuleUNSAFE); - + static FCDECL1(INT32, GetMDStreamVersion, ReflectModuleBaseObject * pModuleUNSAFE); }; extern "C" void QCALLTYPE ModuleHandle_GetModuleType(QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retType); diff --git a/src/coreclr/vm/siginfo.cpp b/src/coreclr/vm/siginfo.cpp index 531f6d95f686..108e95cc39e5 100644 --- a/src/coreclr/vm/siginfo.cpp +++ b/src/coreclr/vm/siginfo.cpp @@ -4360,7 +4360,7 @@ MetaSig::CompareMethodSigs( return FALSE; } - __int8 callConv = *pSig1; + int8_t callConv = *pSig1; pSig1++; pSig2++; diff --git a/src/coreclr/vm/stackingallocator.cpp b/src/coreclr/vm/stackingallocator.cpp index 7db829eb1b44..c5d1ea2ad79d 100644 --- a/src/coreclr/vm/stackingallocator.cpp +++ b/src/coreclr/vm/stackingallocator.cpp @@ -399,7 +399,7 @@ void * __cdecl operator new[](size_t n, StackingAllocator * alloc) return retval; } -void * __cdecl operator new(size_t n, StackingAllocator * alloc, const NoThrow&) throw() +void * __cdecl operator new(size_t n, StackingAllocator * alloc, const std::nothrow_t&) noexcept { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; @@ -412,7 +412,7 @@ void * __cdecl operator new(size_t n, StackingAllocator * alloc, const NoThrow&) return alloc->UnsafeAllocNoThrow((unsigned)n); } -void * __cdecl operator new[](size_t n, StackingAllocator * alloc, const NoThrow&) throw() +void * __cdecl operator new[](size_t n, StackingAllocator * alloc, const std::nothrow_t&) noexcept { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; diff --git a/src/coreclr/vm/stackingallocator.h b/src/coreclr/vm/stackingallocator.h index c306e1b482d3..1878433a7748 100644 --- a/src/coreclr/vm/stackingallocator.h +++ b/src/coreclr/vm/stackingallocator.h @@ -271,8 +271,8 @@ class StackingAllocatorHolder void * __cdecl operator new(size_t n, StackingAllocator *alloc); void * __cdecl operator new[](size_t n, StackingAllocator *alloc); -void * __cdecl operator new(size_t n, StackingAllocator *alloc, const NoThrow&) throw(); -void * __cdecl operator new[](size_t n, StackingAllocator *alloc, const NoThrow&) throw(); +void * __cdecl operator new(size_t n, StackingAllocator *alloc, const std::nothrow_t&) noexcept; +void * __cdecl operator new[](size_t n, StackingAllocator *alloc, const std::nothrow_t&) noexcept; #ifdef _MSC_VER #pragma warning(pop) diff --git a/src/coreclr/vm/stackwalk.cpp b/src/coreclr/vm/stackwalk.cpp index 56e76cdf4949..20ce86000d72 100644 --- a/src/coreclr/vm/stackwalk.cpp +++ b/src/coreclr/vm/stackwalk.cpp @@ -175,7 +175,7 @@ TADDR CrawlFrame::GetAmbientSPFromCrawlFrame() #elif defined(TARGET_ARM) return GetRegisterSet()->pCurrentContext->Sp; #else - return NULL; + return 0; #endif } @@ -553,6 +553,17 @@ PCODE Thread::VirtualUnwindCallFrame(T_CONTEXT* pContext, UINT_PTR uImageBase; PT_RUNTIME_FUNCTION pFunctionEntry; +#if !defined(TARGET_UNIX) && defined(TARGET_ARM64) + // We don't adjust the control PC when we have a code info, as the code info is always created from an unadjusted one + // and the debug sanity check below would fail in case when a managed method was represented by multiple + // RUNTIME_FUNCTION entries and the control PC and adjusted control PC happened to be represented by different + // RUNTIME_FUNCTION entries. + if ((pCodeInfo == NULL) && ((pContext->ContextFlags & CONTEXT_UNWOUND_TO_CALL) != 0)) + { + uControlPc -= STACKWALK_CONTROLPC_ADJUST_OFFSET; + } +#endif // !TARGET_UNIX && TARGET_ARM64 + if (pCodeInfo == NULL) { #ifndef TARGET_UNIX @@ -592,7 +603,23 @@ PCODE Thread::VirtualUnwindCallFrame(T_CONTEXT* pContext, if (pFunctionEntry) { - uControlPc = VirtualUnwindNonLeafCallFrame(pContext, pContextPointers, pFunctionEntry, uImageBase); + #ifdef HOST_64BIT + UINT64 EstablisherFrame; + #else // HOST_64BIT + DWORD EstablisherFrame; + #endif // HOST_64BIT + PVOID HandlerData; + + RtlVirtualUnwind(0, + uImageBase, + uControlPc, + pFunctionEntry, + pContext, + &HandlerData, + &EstablisherFrame, + pContextPointers); + + uControlPc = GetIP(pContext); } else { @@ -661,54 +688,6 @@ PCODE Thread::VirtualUnwindLeafCallFrame(T_CONTEXT* pContext) return uControlPc; } -// static -PCODE Thread::VirtualUnwindNonLeafCallFrame(T_CONTEXT* pContext, KNONVOLATILE_CONTEXT_POINTERS* pContextPointers, - PT_RUNTIME_FUNCTION pFunctionEntry, UINT_PTR uImageBase) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - PRECONDITION(CheckPointer(pContext, NULL_NOT_OK)); - PRECONDITION(CheckPointer(pContextPointers, NULL_OK)); - PRECONDITION(CheckPointer(pFunctionEntry, NULL_OK)); - } - CONTRACTL_END; - - PCODE uControlPc = GetIP(pContext); -#ifdef HOST_64BIT - UINT64 EstablisherFrame; -#else // HOST_64BIT - DWORD EstablisherFrame; -#endif // HOST_64BIT - PVOID HandlerData; - - if (NULL == pFunctionEntry) - { -#ifndef TARGET_UNIX - pFunctionEntry = RtlLookupFunctionEntry(uControlPc, - ARM_ONLY((DWORD*))(&uImageBase), - NULL); -#endif - if (NULL == pFunctionEntry) - { - return NULL; - } - } - - RtlVirtualUnwind(NULL, - uImageBase, - uControlPc, - pFunctionEntry, - pContext, - &HandlerData, - &EstablisherFrame, - pContextPointers); - - uControlPc = GetIP(pContext); - return uControlPc; -} - extern void* g_hostingApiReturnAddress; // static @@ -1158,9 +1137,8 @@ BOOL StackFrameIterator::Init(Thread * pThread, #endif // FEATURE_HIJACK - // FRAME_TOP and NULL must be distinct values. This assert - // will fire if someone changes this. - static_assert_no_msg(FRAME_TOP_VALUE != NULL); + // FRAME_TOP must not be 0/NULL. + static_assert_no_msg(FRAME_TOP_VALUE != 0); m_frameState = SFITER_UNINITIALIZED; @@ -1454,7 +1432,7 @@ void StackFrameIterator::ResetCrawlFrame() m_crawl.isProfilerDoStackSnapshot = !!(this->m_flags & PROFILER_DO_STACK_SNAPSHOT); m_crawl.isNoFrameTransition = false; - m_crawl.taNoFrameTransitionMarker = NULL; + m_crawl.taNoFrameTransitionMarker = (TADDR)NULL; #if defined(FEATURE_EH_FUNCLETS) m_crawl.isFilterFunclet = false; diff --git a/src/coreclr/vm/stackwalk.h b/src/coreclr/vm/stackwalk.h index 736ca2653ee7..eda0f70bda04 100644 --- a/src/coreclr/vm/stackwalk.h +++ b/src/coreclr/vm/stackwalk.h @@ -247,7 +247,7 @@ class CrawlFrame LIMITED_METHOD_DAC_CONTRACT; _ASSERTE((int)isNoFrameTransition != 0xcc); - return (isNoFrameTransition ? taNoFrameTransitionMarker : NULL); + return (isNoFrameTransition ? taNoFrameTransitionMarker : 0); } /* Has the IP been adjusted to a point where it is safe to do GC ? diff --git a/src/coreclr/vm/stackwalktypes.h b/src/coreclr/vm/stackwalktypes.h index 2263740e67c2..26764372994b 100644 --- a/src/coreclr/vm/stackwalktypes.h +++ b/src/coreclr/vm/stackwalktypes.h @@ -39,7 +39,7 @@ struct METHODTOKEN BOOL IsNull() const { - return m_pCodeHeader == NULL; + return m_pCodeHeader == 0; } }; diff --git a/src/coreclr/vm/stringliteralmap.cpp b/src/coreclr/vm/stringliteralmap.cpp index 55d2267f02c8..34f4eecea501 100644 --- a/src/coreclr/vm/stringliteralmap.cpp +++ b/src/coreclr/vm/stringliteralmap.cpp @@ -49,7 +49,7 @@ #define EEHASH_MEMORY_POOL_GROW_COUNT 128 StringLiteralEntryArray *StringLiteralEntry::s_EntryList = NULL; -DWORD StringLiteralEntry::s_UsedEntries = NULL; +DWORD StringLiteralEntry::s_UsedEntries = 0; StringLiteralEntry *StringLiteralEntry::s_FreeEntryList = NULL; StringLiteralMap::StringLiteralMap() diff --git a/src/coreclr/vm/stubgen.cpp b/src/coreclr/vm/stubgen.cpp index 5ecb723b68c5..29595b9414d5 100644 --- a/src/coreclr/vm/stubgen.cpp +++ b/src/coreclr/vm/stubgen.cpp @@ -2044,7 +2044,7 @@ LocalSigBuilder::GetSig( } else { - return NULL; + return 0; } } @@ -2239,7 +2239,7 @@ FunctionSigBuilder::GetSig( } else { - return NULL; + return 0; } } diff --git a/src/coreclr/vm/stubhelpers.cpp b/src/coreclr/vm/stubhelpers.cpp index 95a5650a199f..27be9617ac3e 100644 --- a/src/coreclr/vm/stubhelpers.cpp +++ b/src/coreclr/vm/stubhelpers.cpp @@ -432,7 +432,7 @@ FCIMPLEND FCIMPL1(void*, StubHelpers::GetDelegateTarget, DelegateObject *pThisUNSAFE) { - PCODE pEntryPoint = NULL; + PCODE pEntryPoint = (PCODE)NULL; #ifdef _DEBUG BEGIN_PRESERVE_LAST_ERROR; @@ -506,7 +506,7 @@ FCIMPL3(SIZE_T, StubHelpers::ProfilerBeginTransitionCallback, SIZE_T pSecretPara // even if the profiler doesn't want to track transitions. if (!CORProfilerTrackTransitions()) { - return NULL; + return 0; } MethodDesc* pRealMD = NULL; diff --git a/src/coreclr/vm/stublink.cpp b/src/coreclr/vm/stublink.cpp index 7bdf203faad8..d7facfbb6b83 100644 --- a/src/coreclr/vm/stublink.cpp +++ b/src/coreclr/vm/stublink.cpp @@ -434,7 +434,7 @@ VOID StubLinker::EmitBytes(const BYTE *pBytes, UINT numBytes) //--------------------------------------------------------------- // Append code bytes. //--------------------------------------------------------------- -VOID StubLinker::Emit8 (unsigned __int8 val) +VOID StubLinker::Emit8 (uint8_t val) { CONTRACTL { @@ -445,7 +445,7 @@ VOID StubLinker::Emit8 (unsigned __int8 val) CodeRun *pCodeRun = GetLastCodeRunIfAny(); if (pCodeRun && (CODERUNSIZE - pCodeRun->m_numcodebytes) >= sizeof(val)) { - *((unsigned __int8 *)(pCodeRun->m_codebytes + pCodeRun->m_numcodebytes)) = val; + *((uint8_t *)(pCodeRun->m_codebytes + pCodeRun->m_numcodebytes)) = val; pCodeRun->m_numcodebytes += sizeof(val); } else { EmitBytes((BYTE*)&val, sizeof(val)); @@ -455,7 +455,7 @@ VOID StubLinker::Emit8 (unsigned __int8 val) //--------------------------------------------------------------- // Append code bytes. //--------------------------------------------------------------- -VOID StubLinker::Emit16(unsigned __int16 val) +VOID StubLinker::Emit16(uint16_t val) { CONTRACTL { @@ -476,7 +476,7 @@ VOID StubLinker::Emit16(unsigned __int16 val) //--------------------------------------------------------------- // Append code bytes. //--------------------------------------------------------------- -VOID StubLinker::Emit32(unsigned __int32 val) +VOID StubLinker::Emit32(uint32_t val) { CONTRACTL { @@ -497,7 +497,7 @@ VOID StubLinker::Emit32(unsigned __int32 val) //--------------------------------------------------------------- // Append code bytes. //--------------------------------------------------------------- -VOID StubLinker::Emit64(unsigned __int64 val) +VOID StubLinker::Emit64(uint64_t val) { CONTRACTL { @@ -1054,7 +1054,7 @@ bool StubLinker::EmitStub(Stub* pStub, int globalsize, int totalSize, LoaderHeap case CodeElement::kLabelRef: { LabelRef *pLabelRef = (LabelRef*)pCodeElem; InstructionFormat *pIF = pLabelRef->m_pInstructionFormat; - __int64 fixupval; + int64_t fixupval; LPBYTE srcglobaladdr = pCode + pLabelRef->m_globaloffset + @@ -1069,9 +1069,9 @@ bool StubLinker::EmitStub(Stub* pStub, int globalsize, int totalSize, LoaderHeap targetglobaladdr = (LPBYTE)(pLabelRef->m_target->e.m_pExternalAddress); } if ((pLabelRef->m_target->m_fAbsolute)) { - fixupval = (__int64)(size_t)targetglobaladdr; + fixupval = (int64_t)(size_t)targetglobaladdr; } else - fixupval = (__int64)(targetglobaladdr - srcglobaladdr); + fixupval = (int64_t)(targetglobaladdr - srcglobaladdr); pLabelRef->m_pInstructionFormat->EmitInstruction( pLabelRef->m_refsize, @@ -2307,7 +2307,7 @@ ArgBasedStubCache::ArgBasedStubCache(UINT fixedSlots) m_aStub = new Stub * [m_numFixedSlots]; _ASSERTE(m_aStub != NULL); - for (unsigned __int32 i = 0; i < m_numFixedSlots; i++) { + for (uint32_t i = 0; i < m_numFixedSlots; i++) { m_aStub[i] = NULL; } m_pSlotEntries = NULL; @@ -2326,7 +2326,7 @@ ArgBasedStubCache::~ArgBasedStubCache() } CONTRACTL_END; - for (unsigned __int32 i = 0; i < m_numFixedSlots; i++) { + for (uint32_t i = 0; i < m_numFixedSlots; i++) { Stub *pStub = m_aStub[i]; if (pStub) { pStub->DecRef(); diff --git a/src/coreclr/vm/stublink.h b/src/coreclr/vm/stublink.h index 8189fac7a36a..a665e2b56662 100644 --- a/src/coreclr/vm/stublink.h +++ b/src/coreclr/vm/stublink.h @@ -160,10 +160,10 @@ class StubLinker // Append code bytes. //--------------------------------------------------------------- VOID EmitBytes(const BYTE *pBytes, UINT numBytes); - VOID Emit8 (unsigned __int8 u8); - VOID Emit16(unsigned __int16 u16); - VOID Emit32(unsigned __int32 u32); - VOID Emit64(unsigned __int64 u64); + VOID Emit8 (uint8_t u8); + VOID Emit16(uint16_t u16); + VOID Emit32(uint32_t u32); + VOID Emit64(uint64_t u64); VOID EmitPtr(const VOID *pval); //--------------------------------------------------------------- @@ -914,7 +914,7 @@ class Stub // // // VOID RRT.EmitInstruction(UINT refsize, -// __int64 fixedUpReference, +// int64_t fixedUpReference, // BYTE *pOutBuffer, // UINT variationCode, // BYTE *pDataBuffer) @@ -930,10 +930,10 @@ class Stub // // if (refsize==k8) { // pOutBuffer[0] = 0xeb; -// pOutBuffer[1] = (__int8)fixedUpReference; +// pOutBuffer[1] = (int8_t)fixedUpReference; // } else if (refsize == k32) { // pOutBuffer[0] = 0xe9; -// *((__int32*)(1+pOutBuffer)) = (__int32)fixedUpReference; +// *((int32_t*)(1+pOutBuffer)) = (int32_t)fixedUpReference; // } else { // CRASH("Bad input."); // } @@ -952,7 +952,7 @@ class Stub // method that does exactly this so X86 need not override this at all. // // -// The extra "variationCode" argument is an __int32 that StubLinker receives +// The extra "variationCode" argument is an int32_t that StubLinker receives // from EmitLabelRef() and passes uninterpreted to each RRT method. // This allows one RRT to handle a family of related instructions, // for example, the family of conditional jumps on the X86. @@ -1027,7 +1027,7 @@ class InstructionFormat } virtual UINT GetSizeOfInstruction(UINT refsize, UINT variationCode) = 0; - virtual VOID EmitInstruction(UINT refsize, __int64 fixedUpReference, BYTE *pCodeBufferRX, BYTE *pCodeBufferRW, UINT variationCode, BYTE *pDataBuffer) = 0; + virtual VOID EmitInstruction(UINT refsize, int64_t fixedUpReference, BYTE *pCodeBufferRX, BYTE *pCodeBufferRW, UINT variationCode, BYTE *pDataBuffer) = 0; virtual UINT GetHotSpotOffset(UINT refsize, UINT variationCode) { WRAPPER_NO_CONTRACT; diff --git a/src/coreclr/vm/stubmgr.cpp b/src/coreclr/vm/stubmgr.cpp index 68af3ecf200a..84ae3e1fd0d7 100644 --- a/src/coreclr/vm/stubmgr.cpp +++ b/src/coreclr/vm/stubmgr.cpp @@ -428,7 +428,7 @@ BOOL StubManager::CheckIsStub_Worker(PCODE stubStartAddress) // @todo - consider having a single check for null right up front. // Though this may cover bugs where stub-managers don't handle bad addresses. // And someone could just as easily pass (0x01) as NULL. - if (stubStartAddress == NULL) + if (stubStartAddress == (PCODE)NULL) { return FALSE; } @@ -1037,7 +1037,7 @@ BOOL PrecodeStubManager::DoTraceStub(PCODE stubStartAddress, #ifndef DACCESS_COMPILE trace->InitForUnmanaged(GetEEFuncEntryPoint(NDirectImportThunk)); #else - trace->InitForOther(NULL); + trace->InitForOther((PCODE)NULL); #endif LOG_TRACE_DESTINATION(trace, stubStartAddress, "PrecodeStubManager::DoTraceStub - NDirect import"); return TRUE; @@ -1330,8 +1330,8 @@ static PCODE GetStubTarget(PTR_MethodDesc pTargetMD) targetCode = NativeCodeVersion(pTargetMD); #endif - if (targetCode.IsNull() || targetCode.GetNativeCode() == NULL) - return NULL; + if (targetCode.IsNull() || targetCode.GetNativeCode() == (PCODE)NULL) + return (PCODE)NULL; return targetCode.GetNativeCode(); } @@ -1460,7 +1460,7 @@ BOOL StubLinkStubManager::TraceManager(Thread *thread, _ASSERTE(pMD != NULL); PCODE target = GetStubTarget(pMD); - if (target == NULL) + if (target == (PCODE)NULL) { LOG((LF_CORDB,LL_INFO10000, "SLSM:TM Unable to determine stub target, pMD %p\n", pMD)); trace->InitForUnjittedMethod(pMD); @@ -1808,7 +1808,7 @@ BOOL ILStubManager::DoTraceStub(PCODE stubStartAddress, #ifndef DACCESS_COMPILE - PCODE traceDestination = NULL; + PCODE traceDestination = (PCODE)NULL; #ifdef FEATURE_MULTICASTSTUB_AS_IL MethodDesc* pStubMD = ExecutionManager::GetCodeMethodDesc(stubStartAddress); @@ -1829,7 +1829,7 @@ BOOL ILStubManager::DoTraceStub(PCODE stubStartAddress, return TRUE; #else // !DACCESS_COMPILE - trace->InitForOther(NULL); + trace->InitForOther((PCODE)NULL); return FALSE; #endif // !DACCESS_COMPILE @@ -1887,7 +1887,7 @@ BOOL ILStubManager::TraceManager(Thread *thread, pStubMD, arg, pThis)); // See code:ILStubCache.CreateNewMethodDesc for the code that sets flags on stub MDs - PCODE target = NULL; + PCODE target = (PCODE)NULL; #ifdef FEATURE_MULTICASTSTUB_AS_IL if (pStubMD->IsMulticastStub()) @@ -1965,7 +1965,7 @@ BOOL ILStubManager::TraceManager(Thread *thread, LOG((LF_CORDB, LL_INFO1000, "ILSM::TraceManager: Step through to target - 0x%p\n", pTargetMD)); target = GetStubTarget(pTargetMD); - if (target == NULL) + if (target == (PCODE)NULL) return FALSE; trace->InitForManaged(target); @@ -2094,7 +2094,7 @@ BOOL InteropDispatchStubManager::DoTraceStub(PCODE stubStartAddress, TraceDestin return TRUE; #else // !DACCESS_COMPILE - trace->InitForOther(NULL); + trace->InitForOther((PCODE)NULL); return FALSE; #endif // !DACCESS_COMPILE diff --git a/src/coreclr/vm/stubmgr.h b/src/coreclr/vm/stubmgr.h index 9da4f61f6d2a..36955761bff1 100644 --- a/src/coreclr/vm/stubmgr.h +++ b/src/coreclr/vm/stubmgr.h @@ -215,7 +215,7 @@ class StubManager static BOOL IsStub(PCODE stubAddress) { WRAPPER_NO_CONTRACT; - return FindStubManager(stubAddress) != NULL; + return FindStubManager(stubAddress) != nullptr; } // Find stub manager for given code address diff --git a/src/coreclr/vm/syncblk.cpp b/src/coreclr/vm/syncblk.cpp index eb0b29fafdd0..482b9da36644 100644 --- a/src/coreclr/vm/syncblk.cpp +++ b/src/coreclr/vm/syncblk.cpp @@ -598,7 +598,7 @@ void SyncBlockCache::CleanupSyncBlocks() pParam->psb = NULL; // pulse GC mode to allow GC to perform its work - if (FinalizerThread::GetFinalizerThread()->CatchAtSafePointOpportunistic()) + if (FinalizerThread::GetFinalizerThread()->CatchAtSafePoint()) { FinalizerThread::GetFinalizerThread()->PulseGCMode(); } @@ -2108,7 +2108,7 @@ void VoidDeleteSyncBlockMemory(SyncBlock* psb) SyncBlockCache::GetSyncBlockCache()->DeleteSyncBlockMemory(psb); } -typedef Wrapper, VoidDeleteSyncBlockMemory, NULL> SyncBlockMemoryHolder; +typedef Wrapper, VoidDeleteSyncBlockMemory, 0> SyncBlockMemoryHolder; // get the sync block for an existing object @@ -2851,15 +2851,9 @@ BOOL SyncBlock::Wait(INT32 timeOut) _ASSERTE ((SyncBlock*)((DWORD_PTR)walk->m_Next->m_WaitSB & ~1)== this); - PendingSync syncState(walk); - - OBJECTREF obj = m_Monitor.GetOwningObject(); - syncState.m_Object = OBJECTREFToObject(obj); - - m_Monitor.IncrementTransientPrecious(); - // While we are in this frame the thread is considered blocked on the - // event of the monitor lock according to the debugger + // event of the monitor lock according to the debugger. DebugBlockingItemHolder + // can trigger a GC, so set it up before accessing the owning object. DebugBlockingItem blockingMonitorInfo; blockingMonitorInfo.dwTimeout = timeOut; blockingMonitorInfo.pMonitor = &m_Monitor; @@ -2867,6 +2861,13 @@ BOOL SyncBlock::Wait(INT32 timeOut) blockingMonitorInfo.type = DebugBlock_MonitorEvent; DebugBlockingItemHolder holder(pCurThread, &blockingMonitorInfo); + PendingSync syncState(walk); + + OBJECTREF obj = m_Monitor.GetOwningObject(); + syncState.m_Object = OBJECTREFToObject(obj); + + m_Monitor.IncrementTransientPrecious(); + GCPROTECT_BEGIN(obj); { GCX_PREEMP(); diff --git a/src/coreclr/vm/syncblk.h b/src/coreclr/vm/syncblk.h index 2ddec7531597..029ee9337d7a 100644 --- a/src/coreclr/vm/syncblk.h +++ b/src/coreclr/vm/syncblk.h @@ -602,6 +602,12 @@ class AwareLock LIMITED_METHOD_CONTRACT; return m_HoldingThread; } + + static int GetOffsetOfHoldingOSThreadId() + { + LIMITED_METHOD_CONTRACT; + return (int)offsetof(AwareLock, m_HoldingOSThreadId); + } }; #ifdef FEATURE_COMINTEROP diff --git a/src/coreclr/vm/threaddebugblockinginfo.cpp b/src/coreclr/vm/threaddebugblockinginfo.cpp index 876709156689..8f4f3831b351 100644 --- a/src/coreclr/vm/threaddebugblockinginfo.cpp +++ b/src/coreclr/vm/threaddebugblockinginfo.cpp @@ -72,9 +72,37 @@ VOID ThreadDebugBlockingInfo::VisitBlockingItems(DebugBlockingItemVisitor visito // Holder constructor pushes a blocking item on the blocking info stack #ifndef DACCESS_COMPILE DebugBlockingItemHolder::DebugBlockingItemHolder(Thread *pThread, DebugBlockingItem *pItem) : -m_pThread(pThread) + m_pThread(pThread), m_ppFirstBlockingInfo(nullptr) { - LIMITED_METHOD_CONTRACT; + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; + } + CONTRACTL_END; + + // Try to get the address of the thread-local slot for the managed ThreadBlockingInfo.t_first + EX_TRY + { + FieldDesc *pFD = CoreLibBinder::GetField(FIELD__THREAD_BLOCKING_INFO__FIRST); + m_ppFirstBlockingInfo = (ThreadBlockingInfo **)Thread::GetStaticFieldAddress(pFD); + } + EX_CATCH + { + } + EX_END_CATCH(RethrowTerminalExceptions); + + if (m_ppFirstBlockingInfo != nullptr) + { + // Push info for the managed ThreadBlockingInfo + m_blockingInfo.objectPtr = pItem->pMonitor; + m_blockingInfo.objectKind = (ThreadBlockingInfo::ObjectKind)pItem->type; + m_blockingInfo.timeoutMs = (INT32)pItem->dwTimeout; + m_blockingInfo.next = *m_ppFirstBlockingInfo; + *m_ppFirstBlockingInfo = &m_blockingInfo; + } + pThread->DebugBlockingInfo.PushBlockingItem(pItem); } #endif //DACCESS_COMPILE @@ -84,6 +112,17 @@ m_pThread(pThread) DebugBlockingItemHolder::~DebugBlockingItemHolder() { LIMITED_METHOD_CONTRACT; + m_pThread->DebugBlockingInfo.PopBlockingItem(); + + if (m_ppFirstBlockingInfo != nullptr) + { + // Pop info for the managed ThreadBlockingInfo + _ASSERTE( + m_ppFirstBlockingInfo == + (void *)m_pThread->GetStaticFieldAddrNoCreate(CoreLibBinder::GetField(FIELD__THREAD_BLOCKING_INFO__FIRST))); + _ASSERTE(*m_ppFirstBlockingInfo == &m_blockingInfo); + *m_ppFirstBlockingInfo = m_blockingInfo.next; + } } #endif //DACCESS_COMPILE diff --git a/src/coreclr/vm/threaddebugblockinginfo.h b/src/coreclr/vm/threaddebugblockinginfo.h index 9a2815b3a0c7..c0d035dd88f0 100644 --- a/src/coreclr/vm/threaddebugblockinginfo.h +++ b/src/coreclr/vm/threaddebugblockinginfo.h @@ -14,8 +14,8 @@ // Different ways thread can block that the debugger will expose enum DebugBlockingItemType { - DebugBlock_MonitorCriticalSection, - DebugBlock_MonitorEvent, + DebugBlock_MonitorCriticalSection, // maps to ThreadBlockingInfo.ObjectKind.MonitorLock below and in managed code + DebugBlock_MonitorEvent, // maps to ThreadBlockingInfo.ObjectKind.MonitorWait below and in managed code }; typedef DPTR(struct DebugBlockingItem) PTR_DebugBlockingItem; @@ -65,15 +65,35 @@ class ThreadDebugBlockingInfo }; #ifndef DACCESS_COMPILE + +// This is the equivalent of the managed ThreadBlockingInfo (see ThreadBlockingInfo.cs), which is used for tracking blocking +// info from the managed side, similarly to DebugBlockingItem +struct ThreadBlockingInfo +{ + enum class ObjectKind : INT32 + { + MonitorLock, // maps to DebugBlockingItemType::DebugBlock_MonitorCriticalSection + MonitorWait // maps to DebugBlockingItemType::DebugBlock_MonitorEvent + }; + + void *objectPtr; + ObjectKind objectKind; + INT32 timeoutMs; + ThreadBlockingInfo *next; +}; + class DebugBlockingItemHolder { private: Thread *m_pThread; + ThreadBlockingInfo **m_ppFirstBlockingInfo; + ThreadBlockingInfo m_blockingInfo; public: DebugBlockingItemHolder(Thread *pThread, DebugBlockingItem *pItem); ~DebugBlockingItemHolder(); }; + #endif //!DACCESS_COMPILE #endif // __ThreadBlockingInfo__ diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp index f519ff758fbc..7411d62a285f 100644 --- a/src/coreclr/vm/threads.cpp +++ b/src/coreclr/vm/threads.cpp @@ -45,6 +45,7 @@ #ifdef FEATURE_SPECIAL_USER_MODE_APC #include "asmconstants.h" +#include #endif static const PortableTailCallFrame g_sentinelTailCallFrame = { NULL, NULL }; @@ -260,14 +261,14 @@ void Thread::SetFrame(Frame *pFrame) // PRIVATE GLOBALS //************************************************************************ -extern unsigned __int64 getTimeStamp(); +extern uint64_t getTimeStamp(); -extern unsigned __int64 getTickFrequency(); +extern uint64_t getTickFrequency(); -unsigned __int64 tgetFrequency() { - static unsigned __int64 cachedFreq = (unsigned __int64) -1; +uint64_t tgetFrequency() { + static uint64_t cachedFreq = (uint64_t) -1; - if (cachedFreq != (unsigned __int64) -1) + if (cachedFreq != (uint64_t) -1) return cachedFreq; else { cachedFreq = getTickFrequency(); @@ -330,7 +331,7 @@ bool Thread::DetectHandleILStubsForDebugger() // Check for M2U transition frames. See the comment at the beginning of this function. else if (pFrame->GetFrameType() == Frame::TYPE_EXIT) { - if (pFrame->GetReturnAddress() == NULL) + if (pFrame->GetReturnAddress() == (PCODE)NULL) { // If the return address is NULL, then the frame has not been initialized yet. // We may see InlinedCallFrame in ordinary methods as well. Have to do @@ -371,13 +372,9 @@ void SetThread(Thread* t) { EnsureTlsDestructionMonitor(); } -} - -void SetAppDomain(AppDomain* ad) -{ - LIMITED_METHOD_CONTRACT - gCurrentThreadInfo.m_pAppDomain = ad; + // Clear or set the app domain to the one domain based on if the thread is being nulled out or set + gCurrentThreadInfo.m_pAppDomain = t == NULL ? NULL : AppDomain::GetCurrentDomain(); } BOOL Thread::Alert () @@ -594,7 +591,6 @@ static void DeleteThread(Thread* pThread) //_ASSERTE (pThread == GetThread()); SetThread(NULL); - SetAppDomain(NULL); if (pThread->HasThreadStateNC(Thread::TSNC_ExistInThreadStore)) { @@ -727,7 +723,6 @@ Thread* SetupThread() ThreadStore::AddThread(pThread); SetThread(pThread); - SetAppDomain(pThread->GetDomain()); #ifdef FEATURE_INTEROP_DEBUGGING // Ensure that debugger word slot is allocated @@ -1010,7 +1005,6 @@ HRESULT Thread::DetachThread(BOOL fDLLThreadDetach) // We need to make sure that TLS are touched last here. SetThread(NULL); - SetAppDomain(NULL); SetThreadState((Thread::ThreadState)(Thread::TS_Detached | Thread::TS_ReportDead)); // Do not touch Thread object any more. It may be destroyed. @@ -1399,13 +1393,6 @@ Thread::Thread() #ifdef _DEBUG m_ulForbidTypeLoad = 0; m_GCOnTransitionsOK = TRUE; -#endif - -#ifdef ENABLE_CONTRACTS - m_ulEnablePreemptiveGCCount = 0; -#endif - -#ifdef _DEBUG dbg_m_cSuspendedThreads = 0; dbg_m_cSuspendedThreadsWithoutOSLock = 0; m_Creator.Clear(); @@ -1585,8 +1572,6 @@ Thread::Thread() m_monitorLockContentionCount = 0; - m_pDomain = SystemDomain::System()->DefaultDomain(); - // Do not expose thread until it is fully constructed g_pThinLockThreadIdDispenser->NewId(this, this->m_ThreadId); @@ -1846,7 +1831,6 @@ BOOL Thread::HasStarted() PrepareApartmentAndContext(); SetThread(this); - SetAppDomain(m_pDomain); ThreadStore::TransferStartedThread(this); @@ -1945,7 +1929,6 @@ BOOL Thread::HasStarted() ThreadStore::CheckForEEShutdown(); DecExternalCount(/*holdingLock*/ HasThreadStateNC(Thread::TSNC_TSLTakenForStartup)); SetThread(NULL); - SetAppDomain(NULL); return FALSE; } @@ -2190,66 +2173,6 @@ SIZE_T GetDefaultStackSizeSetting() return (SIZE_T) value; } -BOOL Thread::GetProcessDefaultStackSize(SIZE_T* reserveSize, SIZE_T* commitSize) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - // - // Let's get the stack sizes from the PE file that started process. - // - static SIZE_T ExeSizeOfStackReserve = 0; - static SIZE_T ExeSizeOfStackCommit = 0; - - static BOOL fSizesGot = FALSE; - - if (!fSizesGot) - { - SIZE_T defaultStackSizeSetting = GetDefaultStackSizeSetting(); - - if (defaultStackSizeSetting != 0) - { - ExeSizeOfStackReserve = defaultStackSizeSetting; - ExeSizeOfStackCommit = defaultStackSizeSetting; - fSizesGot = TRUE; - } - } - -#ifndef TARGET_UNIX - if (!fSizesGot) - { - HINSTANCE hInst = WszGetModuleHandle(NULL); - _ASSERTE(hInst); // WszGetModuleHandle should never fail on the module that started the process. - EX_TRY - { - PEDecoder pe(hInst); - pe.GetEXEStackSizes(&ExeSizeOfStackReserve, &ExeSizeOfStackCommit); - fSizesGot = TRUE; - } - EX_CATCH - { - fSizesGot = FALSE; - } - EX_END_CATCH(SwallowAllExceptions); - } -#endif // !TARGET_UNIX - - if (!fSizesGot) { - //return some somewhat-reasonable numbers - if (NULL != reserveSize) *reserveSize = 256*1024; - if (NULL != commitSize) *commitSize = 256*1024; - return FALSE; - } - - if (NULL != reserveSize) *reserveSize = ExeSizeOfStackReserve; - if (NULL != commitSize) *commitSize = ExeSizeOfStackCommit; - return TRUE; -} - BOOL Thread::CreateNewOSThread(SIZE_T sizeToCommitOrReserve, LPTHREAD_START_ROUTINE start, void *args) { CONTRACTL { @@ -3092,7 +3015,6 @@ void Thread::OnThreadTerminate(BOOL holdingLock) // right thread. But this will only happen during a shutdown. And we've made // a "best effort" to reduce to a single thread before we begin the shutdown. SetThread(NULL); - SetAppDomain(NULL); } if (!holdingLock) @@ -3309,7 +3231,7 @@ DWORD Thread::DoAppropriateAptStateWait(int numWaiters, HANDLE* pHandles, BOOL b BOOL alertable = (mode & WaitMode_Alertable) != 0; #ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT - if (alertable && !GetDomain()->MustForceTrivialWaitOperations()) + if (alertable && !AppDomain::GetCurrentDomain()->MustForceTrivialWaitOperations()) { ApartmentState as = GetFinalApartment(); if (AS_InMTA != as) @@ -3389,7 +3311,7 @@ DWORD Thread::DoAppropriateWaitWorker(int countHandles, HANDLE *handles, BOOL wa // which will make mode != WaitMode_Alertable. BOOL ignoreSyncCtx = (mode != WaitMode_Alertable); - if (GetDomain()->MustForceTrivialWaitOperations()) + if (AppDomain::GetCurrentDomain()->MustForceTrivialWaitOperations()) ignoreSyncCtx = TRUE; // Unless the ignoreSyncCtx flag is set, first check to see if there is a synchronization @@ -3693,7 +3615,7 @@ DWORD Thread::DoAppropriateWaitWorker(AppropriateWaitFunc func, void *args, option = WAIT_ALERTABLE; #ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT ApartmentState as = GetFinalApartment(); - if ((AS_InMTA != as) && !GetDomain()->MustForceTrivialWaitOperations()) + if ((AS_InMTA != as) && !AppDomain::GetCurrentDomain()->MustForceTrivialWaitOperations()) { option |= WAIT_MSGPUMP; } @@ -4408,7 +4330,7 @@ void Thread::SetLastThrownObject(OBJECTREF throwable, BOOL isUnhandled) } else { - m_LastThrownObjectHandle = GetDomain()->CreateHandle(throwable); + m_LastThrownObjectHandle = AppDomain::GetCurrentDomain()->CreateHandle(throwable); } _ASSERTE(m_LastThrownObjectHandle != NULL); @@ -5184,9 +5106,6 @@ void ThreadStore::InitThreadStore() g_pThinLockThreadIdDispenser = new IdDispenser(); - ThreadSuspend::g_pGCSuspendEvent = new CLREvent(); - ThreadSuspend::g_pGCSuspendEvent->CreateManualEvent(FALSE); - s_pWaitForStackCrawlEvent = new CLREvent(); s_pWaitForStackCrawlEvent->CreateManualEvent(FALSE); @@ -5772,7 +5691,7 @@ BOOL ThreadStore::DbgFindThread(Thread *target) // Cache the current change stamp for g_TrapReturningThreads LONG chgStamp = g_trtChgStamp; - STRESS_LOG3(LF_STORE, LL_INFO100, "ThreadStore::DbgFindThread - [thread=%p]. trt=%d. chgStamp=%d\n", GetThreadNULLOk(), g_TrapReturningThreads.Load(), chgStamp); + STRESS_LOG3(LF_STORE, LL_INFO100, "ThreadStore::DbgFindThread - [thread=%p]. trt=%d. chgStamp=%d\n", GetThreadNULLOk(), g_TrapReturningThreads, chgStamp); #if 0 // g_TrapReturningThreads debug code. int iRetry = 0; @@ -5845,7 +5764,7 @@ BOOL ThreadStore::DbgFindThread(Thread *target) } #endif // g_TrapReturningThreads debug code. - STRESS_LOG4(LF_STORE, LL_INFO100, "ThreadStore::DbgFindThread - [thread=%p]. trt=%d. chg=%d. cnt=%d\n", GetThreadNULLOk(), g_TrapReturningThreads.Load(), g_trtChgStamp.Load(), cntReturn); + STRESS_LOG4(LF_STORE, LL_INFO100, "ThreadStore::DbgFindThread - [thread=%p]. trt=%d. chg=%d. cnt=%d\n", GetThreadNULLOk(), g_TrapReturningThreads, g_trtChgStamp.Load(), cntReturn); // Because of race conditions and the fact that the GC places its // own count, I can't assert this precisely. But I do want to be @@ -5860,11 +5779,11 @@ BOOL ThreadStore::DbgFindThread(Thread *target) // return). // // Note: we don't actually assert this if - // ThreadStore::TrapReturningThreads() updated g_TrapReturningThreads + // ThreadStore::IncrementTrapReturningThreads() updated g_TrapReturningThreads // between the beginning of this function and the moment of the assert. // *** The order of evaluation in the if condition is important *** _ASSERTE( - (g_trtChgInFlight != 0 || (cntReturn + 2 >= g_TrapReturningThreads) || chgStamp != g_trtChgStamp) || + (g_trtChgInFlight != 0 || (cntReturn + 2 >= g_TrapReturningThreads / 2) || chgStamp != g_trtChgStamp) || g_fEEShutDown); return found; @@ -7075,22 +6994,20 @@ void CommonTripThread() CONTRACTL { THROWS; GC_TRIGGERS; + MODE_COOPERATIVE; } CONTRACTL_END; Thread *thread = GetThread(); - thread->HandleThreadAbort (); + thread->HandleThreadAbort(); - if (thread->CatchAtSafePoint()) - { - _ASSERTE(!ThreadStore::HoldingThreadStore(thread)); + _ASSERTE(!ThreadStore::HoldingThreadStore(thread)); #ifdef FEATURE_HIJACK - thread->UnhijackThread(); + thread->UnhijackThread(); #endif // FEATURE_HIJACK - // Trap - thread->PulseGCMode(); - } + // Trap + thread->PulseGCMode(); #else DacNotImpl(); #endif // #ifndef DACCESS_COMPILE @@ -7129,11 +7046,6 @@ void Thread::ClearContext() if (GetThreadNULLOk()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);} } CONTRACTL_END; - - if (!m_pDomain) - return; - - m_pDomain = NULL; #ifdef FEATURE_COMINTEROP m_fDisableComObjectEagerCleanup = false; #endif //FEATURE_COMINTEROP @@ -7648,7 +7560,7 @@ TADDR Thread::GetStaticFieldAddrNoCreate(FieldDesc *pFD) } if (base == NULL) - return NULL; + return (TADDR)NULL; DWORD offset = pFD->GetOffset(); _ASSERTE(offset <= FIELD_OFFSET_LAST_REAL_OFFSET); @@ -7662,7 +7574,7 @@ TADDR Thread::GetStaticFieldAddrNoCreate(FieldDesc *pFD) _ASSERTE(result != NULL); PTR_Object obj = *PTR_UNCHECKED_OBJECTREF(result); if (obj == NULL) - return NULL; + return (TADDR)NULL; result = dac_cast(obj->GetData()); } @@ -8198,8 +8110,8 @@ void Thread::StaticInitialize() #ifdef FEATURE_SPECIAL_USER_MODE_APC InitializeSpecialUserModeApc(); - // When CET shadow stacks are enabled, support for special user-mode APCs with the necessary functionality is required - _ASSERTE_ALL_BUILDS(!AreCetShadowStacksEnabled() || UseSpecialUserModeApc()); + // When shadow stacks are enabled, support for special user-mode APCs with the necessary functionality is required + _ASSERTE_ALL_BUILDS(!AreShadowStacksEnabled() || UseSpecialUserModeApc()); #endif } @@ -8219,6 +8131,21 @@ void Thread::InitializeSpecialUserModeApc() HMODULE hKernel32 = WszLoadLibrary(WINDOWS_KERNEL32_DLLNAME_W, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); +#ifdef HOST_AMD64 + typedef BOOL (WINAPI *IsWow64Process2Proc)(HANDLE hProcess, USHORT *pProcessMachine, USHORT *pNativeMachine); + + IsWow64Process2Proc pfnIsWow64Process2Proc = (IsWow64Process2Proc)GetProcAddress(hKernel32, "IsWow64Process2"); + USHORT processMachine, hostMachine; + if (pfnIsWow64Process2Proc != nullptr && + (*pfnIsWow64Process2Proc)(GetCurrentProcess(), &processMachine, &hostMachine) && + (hostMachine == IMAGE_FILE_MACHINE_ARM64) && + !IsWindowsVersionOrGreater(10, 0, 26100)) + { + // Special user-mode APCs are broken on WOW64 processes (x64 running on Arm64 machine) with Windows older than 11.0.26100 (24H2) + return; + } +#endif // HOST_AMD64 + // See if QueueUserAPC2 exists QueueUserAPC2Proc pfnQueueUserAPC2Proc = (QueueUserAPC2Proc)GetProcAddress(hKernel32, "QueueUserAPC2"); if (pfnQueueUserAPC2Proc == nullptr) @@ -8276,10 +8203,7 @@ Thread::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) DAC_ENUM_DTHIS(); if (flags != CLRDATA_ENUM_MEM_MINI && flags != CLRDATA_ENUM_MEM_TRIAGE && flags != CLRDATA_ENUM_MEM_HEAP2) { - if (m_pDomain.IsValid()) - { - m_pDomain->EnumMemoryRegions(flags, true); - } + AppDomain::GetCurrentDomain()->EnumMemoryRegions(flags, true); } if (m_debuggerFilterContext.IsValid()) diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h index b9472590fc8b..c84fd8a4dec3 100644 --- a/src/coreclr/vm/threads.h +++ b/src/coreclr/vm/threads.h @@ -121,6 +121,7 @@ #include "gchandleutilities.h" #include "gcinfotypes.h" #include +#include "cdacoffsets.h" class Thread; class ThreadStore; @@ -520,14 +521,11 @@ class TailCallTls // structure through the OS TLS slot see code:#RuntimeThreadLocals for more information. class Thread { - friend struct ThreadQueue; // used to enqueue & dequeue threads onto SyncBlocks friend class ThreadStore; friend class ThreadSuspend; friend class SyncBlock; friend struct PendingSync; - friend class AppDomain; friend class ThreadNative; - friend class DeadlockAwareLock; #ifdef _DEBUG friend class EEContract; #endif @@ -547,6 +545,7 @@ class Thread friend void STDCALL OnHijackWorker(HijackArgs * pArgs); #ifdef FEATURE_THREAD_ACTIVATION friend void HandleSuspensionForInterruptedThread(CONTEXT *interruptedContext); + friend BOOL CheckActivationSafePoint(SIZE_T ip); #endif // FEATURE_THREAD_ACTIVATION #endif // FEATURE_HIJACK @@ -562,15 +561,11 @@ class Thread #endif // DACCESS_COMPILE friend class ProfToEEInterfaceImpl; // HRESULT ProfToEEInterfaceImpl::GetHandleFromThread(ThreadID threadId, HANDLE *phThread); - friend class CheckAsmOffsets; - friend class ExceptionTracker; friend class ThreadExceptionState; friend class StackFrameIterator; - friend class ThreadStatics; - public: enum SetThreadStackGuaranteeScope { STSGuarantee_Force, STSGuarantee_OnlyIfEnabled }; static BOOL IsSetThreadStackGuaranteeInUse(SetThreadStackGuaranteeScope fScope = STSGuarantee_OnlyIfEnabled) @@ -590,7 +585,7 @@ class Thread public: // If we are trying to suspend a thread, we set the appropriate pending bit to - // indicate why we want to suspend it (TS_GCSuspendPending or TS_DebugSuspendPending). + // indicate why we want to suspend it (TS_AbortRequested or TS_DebugSuspendPending). // // If instead the thread has blocked itself, via WaitSuspendEvent, we indicate // this with TS_SyncSuspended. However, we need to know whether the synchronous @@ -606,9 +601,8 @@ class Thread TS_AbortRequested = 0x00000001, // Abort the thread - TS_GCSuspendPending = 0x00000002, // ThreadSuspend::SuspendRuntime watches this thread to leave coop mode. + // unused = 0x00000002, TS_GCSuspendRedirected = 0x00000004, // ThreadSuspend::SuspendRuntime has redirected the thread to suspention routine. - TS_GCSuspendFlags = TS_GCSuspendPending | TS_GCSuspendRedirected, // used to track suspension progress. Only SuspendRuntime writes/resets these. TS_DebugSuspendPending = 0x00000008, // Is the debugger suspending threads? TS_GCOnTransitions = 0x00000010, // Force a GC on stub transitions (GCStress only) @@ -669,8 +663,7 @@ class Thread // enum is changed, we also need to update SOS to reflect this. // We require (and assert) that the following bits are less than 0x100. - TS_CatchAtSafePoint = (TS_AbortRequested | TS_GCSuspendPending | - TS_DebugSuspendPending | TS_GCOnTransitions), + TS_CatchAtSafePoint = (TS_AbortRequested | TS_DebugSuspendPending | TS_GCOnTransitions), }; // Thread flags that aren't really states in themselves but rather things the thread @@ -937,14 +930,16 @@ class Thread #ifndef DACCESS_COMPILE DWORD CatchAtSafePoint() { - LIMITED_METHOD_CONTRACT; - return (m_State & TS_CatchAtSafePoint); - } + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_COOPERATIVE; + } + CONTRACTL_END; - DWORD CatchAtSafePointOpportunistic() - { - LIMITED_METHOD_CONTRACT; - return HasThreadStateOpportunistic(TS_CatchAtSafePoint); + return g_TrapReturningThreads & 1 || + HasThreadStateOpportunistic(TS_CatchAtSafePoint); } #endif // DACCESS_COMPILE @@ -1010,13 +1005,6 @@ class Thread Volatile m_fPreemptiveGCDisabled; PTR_Frame m_pFrame; // The Current Frame - - //----------------------------------------------------------- - // If the thread has wandered in from the outside this is - // its Domain. - //----------------------------------------------------------- - PTR_AppDomain m_pDomain; - // Unique thread id used for thin locks - kept as small as possible, as we have limited space // in the object header to store it. DWORD m_ThreadId; @@ -1369,7 +1357,7 @@ class Thread m_fPreemptiveGCDisabled.StoreWithoutBarrier(1); - if (g_TrapReturningThreads.LoadWithoutBarrier()) + if (g_TrapReturningThreads) { RareDisablePreemptiveGC(); } @@ -1401,11 +1389,6 @@ class Thread // holding a spin lock in coop mode and transit to preemp mode will cause deadlock on GC _ASSERTE ((m_StateNC & Thread::TSNC_OwnsSpinLock) == 0); -#ifdef ENABLE_CONTRACTS_IMPL - _ASSERTE(!GCForbidden()); - TriggersGC(this); -#endif - // ------------------------------------------------------------------------ // ** WARNING ** WARNING ** WARNING ** WARNING ** WARNING ** WARNING ** | // ------------------------------------------------------------------------ @@ -1418,19 +1401,12 @@ class Thread // ------------------------------------------------------------------------ m_fPreemptiveGCDisabled.StoreWithoutBarrier(0); -#ifdef ENABLE_CONTRACTS - m_ulEnablePreemptiveGCCount ++; -#endif // _DEBUG - - if (CatchAtSafePoint()) - RareEnablePreemptiveGC(); #endif } #if defined(STRESS_HEAP) && defined(_DEBUG) void PerformPreemptiveGC(); #endif - void RareEnablePreemptiveGC(); void PulseGCMode(); //-------------------------------------------------------------- @@ -1668,12 +1644,6 @@ class Thread void ClearContext(); public: - PTR_AppDomain GetDomain(INDEBUG(BOOL fMidContextTransitionOK = FALSE)) - { - LIMITED_METHOD_DAC_CONTRACT; - - return m_pDomain; - } //--------------------------------------------------------------- // Track use of the thread block. See the general comments on @@ -1809,6 +1779,8 @@ class Thread STR_NoStressLog, }; + void Hijack(); + #ifdef FEATURE_THREAD_ACTIVATION enum class ActivationReason { @@ -2397,8 +2369,6 @@ class Thread static UINT_PTR VirtualUnwindCallFrame(PREGDISPLAY pRD, EECodeInfo * pCodeInfo = NULL); #ifndef DACCESS_COMPILE static PCODE VirtualUnwindLeafCallFrame(T_CONTEXT* pContext); - static PCODE VirtualUnwindNonLeafCallFrame(T_CONTEXT* pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers = NULL, - PT_RUNTIME_FUNCTION pFunctionEntry = NULL, UINT_PTR uImageBase = NULL); static UINT_PTR VirtualUnwindToFirstManagedCallFrame(T_CONTEXT* pContext); #endif // DACCESS_COMPILE #endif // FEATURE_EH_FUNCLETS @@ -2663,7 +2633,7 @@ class Thread // For suspends. The thread waits on this event. A client sets the event to cause // the thread to resume. - void WaitSuspendEvents(BOOL fDoWait = TRUE); + void WaitSuspendEvents(); BOOL WaitSuspendEventsHelper(void); // Helpers to ensure that the bits for suspension and the number of active @@ -2806,11 +2776,6 @@ class Thread #endif // TRACK_SYNC -private: -#ifdef ENABLE_CONTRACTS_DATA - ULONG m_ulEnablePreemptiveGCCount; -#endif // _DEBUG - private: // For suspends: CLREvent m_DebugSuspendEvent; @@ -2886,7 +2851,6 @@ class Thread DWORD m_Priority; // initialized to INVALID_THREAD_PRIORITY, set to actual priority when a // thread does a busy wait for GC, reset to INVALID_THREAD_PRIORITY after wait is over - friend class NDirect; // Quick access to thread stub creation #ifdef HAVE_GCCOVER friend void DoGcStress (PT_CONTEXT regs, NativeCodeVersion nativeCodeVersion); // Needs to call UnhijackThread @@ -2918,13 +2882,13 @@ class Thread public: - BOOL IsLastThrownObjectNull() { WRAPPER_NO_CONTRACT; return (m_LastThrownObjectHandle == NULL); } + BOOL IsLastThrownObjectNull() { WRAPPER_NO_CONTRACT; return (m_LastThrownObjectHandle == (OBJECTHANDLE)0); } OBJECTREF LastThrownObject() { WRAPPER_NO_CONTRACT; - if (m_LastThrownObjectHandle == NULL) + if (m_LastThrownObjectHandle == (OBJECTHANDLE)0) { return NULL; } @@ -3240,8 +3204,6 @@ class Thread if (SuspendSucceeded) UnhijackThread(); #endif // FEATURE_HIJACK - - _ASSERTE(!HasThreadStateOpportunistic(Thread::TS_GCSuspendPending)); } static LPVOID GetStaticFieldAddress(FieldDesc *pFD); @@ -3682,14 +3644,6 @@ class Thread #endif // defined(GCCOVER_TOLERATE_SPURIOUS_AV) #endif // HAVE_GCCOVER -public: - static BOOL CheckThreadStackSize(SIZE_T *SizeToCommitOrReserve, - BOOL isSizeToReserve // When TRUE, the previous argument is the stack size to reserve. - // Otherwise, it is the size to commit. - ); - - static BOOL GetProcessDefaultStackSize(SIZE_T* reserveSize, SIZE_T* commitSize); - private: // Although this is a pointer, it is used as a flag to indicate the current context is unsafe @@ -4016,15 +3970,20 @@ class Thread public: static void StaticInitialize(); -#if defined(TARGET_AMD64) && defined(TARGET_WINDOWS) - static bool AreCetShadowStacksEnabled() +#if defined(TARGET_WINDOWS) + static bool AreShadowStacksEnabled() { LIMITED_METHOD_CONTRACT; +#if defined(TARGET_AMD64) // The SSP is null when CET shadow stacks are not enabled. On processors that don't support shadow stacks, this is a // no-op and the intrinsic returns 0. CET shadow stacks are enabled or disabled for all threads, so the result is the // same from any thread. return _rdsspq() != 0; +#else + // When implementing AreShadowStacksEnabled() on other architectures, review all the places where this is used. + return false; +#endif } #endif @@ -4076,6 +4035,15 @@ class Thread private: bool m_hasPendingActivation; + + template friend struct ::cdac_offsets; +}; + +template<> +struct cdac_offsets +{ + static constexpr size_t ExposedObject = offsetof(Thread, m_ExposedObject); + static constexpr size_t Link = offsetof(Thread, m_Link); }; // End of class Thread @@ -4157,14 +4125,19 @@ class ThreadStore == m_BackgroundThreadCount); } - // If you want to trap threads re-entering the EE (be this for GC, or debugging, - // or Thread.Suspend() or whatever, you need to TrapReturningThreads(TRUE). When - // you are finished snagging threads, call TrapReturningThreads(FALSE). This + // If you want to trap threads re-entering the EE (for debugging, + // or Thread.Suspend() or whatever, you need to IncrementTrapReturningThreads(). When + // you are finished snagging threads, call DecrementTrapReturningThreads(). This // counts internally. // // Of course, you must also fix RareDisablePreemptiveGC to do the right thing // when the trap occurs. - static void TrapReturningThreads(BOOL yes); + static void IncrementTrapReturningThreads(); + static void DecrementTrapReturningThreads(); + + static void SetThreadTrapForSuspension(); + static void UnsetThreadTrapForSuspension(); + static bool IsTrappingThreadsForSuspension(); private: @@ -4325,11 +4298,20 @@ class ThreadStore void OnMaxGenerationGCStarted(); bool ShouldTriggerGCForDeadThreads(); void TriggerGCForDeadThreadsIfNecessary(); + + template friend struct ::cdac_offsets; +}; + +template<> +struct cdac_offsets +{ + static constexpr size_t ThreadList = offsetof(ThreadStore, m_ThreadList); + static constexpr size_t ThreadCount = offsetof(ThreadStore, m_ThreadCount); }; struct TSSuspendHelper { - static void SetTrap() { ThreadStore::TrapReturningThreads(TRUE); } - static void UnsetTrap() { ThreadStore::TrapReturningThreads(FALSE); } + static void SetTrap() { ThreadStore::IncrementTrapReturningThreads(); } + static void UnsetTrap() { ThreadStore::DecrementTrapReturningThreads(); } }; typedef StateHolder TSSuspendHolder; @@ -4520,7 +4502,7 @@ inline void Thread::MarkForDebugSuspend(void) if (!HasThreadState(TS_DebugSuspendPending)) { SetThreadState(TS_DebugSuspendPending); - ThreadStore::TrapReturningThreads(TRUE); + ThreadStore::IncrementTrapReturningThreads(); } } @@ -4531,13 +4513,13 @@ inline void Thread::IncrementTraceCallCount() { WRAPPER_NO_CONTRACT; InterlockedIncrement(&m_TraceCallCount); - ThreadStore::TrapReturningThreads(TRUE); + ThreadStore::IncrementTrapReturningThreads(); } inline void Thread::DecrementTraceCallCount() { WRAPPER_NO_CONTRACT; - ThreadStore::TrapReturningThreads(FALSE); + ThreadStore::DecrementTrapReturningThreads(); InterlockedDecrement(&m_TraceCallCount); } diff --git a/src/coreclr/vm/threads.inl b/src/coreclr/vm/threads.inl index c64382d4bbd0..b15b7bef0895 100644 --- a/src/coreclr/vm/threads.inl +++ b/src/coreclr/vm/threads.inl @@ -108,7 +108,7 @@ inline void Thread::ClearThreadCurrNotification() } CONTRACTL_END; - m_hCurrNotification = NULL; + m_hCurrNotification = (OBJECTHANDLE)NULL; } diff --git a/src/coreclr/vm/threadstatics.cpp b/src/coreclr/vm/threadstatics.cpp index 6a8a43a0821e..74d2eb08a3dc 100644 --- a/src/coreclr/vm/threadstatics.cpp +++ b/src/coreclr/vm/threadstatics.cpp @@ -52,11 +52,11 @@ void ThreadLocalBlock::FreeTLM(SIZE_T i, BOOL isThreadShuttingdown) ThreadLocalModule::CollectibleDynamicEntry *entry = (ThreadLocalModule::CollectibleDynamicEntry*)pThreadLocalModule->m_pDynamicClassTable[k].m_pDynamicEntry; PTR_LoaderAllocator pLoaderAllocator = entry->m_pLoaderAllocator; - if (entry->m_hGCStatics != NULL) + if (entry->m_hGCStatics != 0) { pLoaderAllocator->FreeHandle(entry->m_hGCStatics); } - if (entry->m_hNonGCStatics != NULL) + if (entry->m_hNonGCStatics != 0) { pLoaderAllocator->FreeHandle(entry->m_hNonGCStatics); } diff --git a/src/coreclr/vm/threadstatics.h b/src/coreclr/vm/threadstatics.h index f002f0059ce6..8c0c87998bf1 100644 --- a/src/coreclr/vm/threadstatics.h +++ b/src/coreclr/vm/threadstatics.h @@ -96,8 +96,8 @@ struct ThreadLocalModule LIMITED_METHOD_CONTRACT; } - LOADERHANDLE m_hGCStatics = NULL; - LOADERHANDLE m_hNonGCStatics = NULL; + LOADERHANDLE m_hGCStatics = (LOADERHANDLE)0; + LOADERHANDLE m_hNonGCStatics = (LOADERHANDLE)0; PTR_LoaderAllocator m_pLoaderAllocator = NULL; }; typedef DPTR(CollectibleDynamicEntry) PTR_CollectibleDynamicEntry; diff --git a/src/coreclr/vm/threadsuspend.cpp b/src/coreclr/vm/threadsuspend.cpp index f79193888480..40ae02264804 100644 --- a/src/coreclr/vm/threadsuspend.cpp +++ b/src/coreclr/vm/threadsuspend.cpp @@ -21,11 +21,9 @@ bool ThreadSuspend::s_fSuspendRuntimeInProgress = false; bool ThreadSuspend::s_fSuspended = false; -CLREvent* ThreadSuspend::g_pGCSuspendEvent = NULL; - ThreadSuspend::SUSPEND_REASON ThreadSuspend::m_suspendReason; -#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) +#if defined(TARGET_WINDOWS) void* ThreadSuspend::g_returnAddressHijackTarget = NULL; #endif @@ -58,11 +56,6 @@ extern "C" void RedirectedHandledJITCaseForGCStress_Stub(void); #endif // HAVE_GCCOVER && USE_REDIRECT_FOR_GCSTRESS #endif // TARGET_AMD64 || TARGET_ARM -// Every PING_JIT_TIMEOUT ms, check to see if a thread in JITted code has wandered -// into some fully interruptible code (or should have a different hijack to improve -// our chances of snagging it at a safe spot). -#define PING_JIT_TIMEOUT 1 - // When we find a thread in a spot that's not safe to abort -- how long to wait before // we try again. #define ABORT_POLL_TIMEOUT 10 @@ -1302,7 +1295,7 @@ Thread::UserAbort(EEPolicy::ThreadAbortTypes abortType, DWORD timeout) // The thread being aborted may clear the TS_AbortRequested bit and the matching increment // of g_TrapReturningThreads behind our back. Increment g_TrapReturningThreads here // to ensure that we stop for the stack crawl even if the TS_AbortRequested bit is cleared. - ThreadStore::TrapReturningThreads(TRUE); + ThreadStore::IncrementTrapReturningThreads(); } void NeedStackCrawl() { @@ -1317,7 +1310,7 @@ Thread::UserAbort(EEPolicy::ThreadAbortTypes abortType, DWORD timeout) if (m_NeedRelease) { m_NeedRelease = FALSE; - ThreadStore::TrapReturningThreads(FALSE); + ThreadStore::DecrementTrapReturningThreads(); ThreadStore::SetStackCrawlEvent(); m_pThread->ResetThreadState(TS_StackCrawlNeeded); if (!m_fHoldingThreadStoreLock) @@ -1762,7 +1755,7 @@ void Thread::SetAbortRequestBit() } if (InterlockedCompareExchange((LONG*)&m_State, curValue|TS_AbortRequested, curValue) == curValue) { - ThreadStore::TrapReturningThreads(TRUE); + ThreadStore::IncrementTrapReturningThreads(); break; } @@ -1778,7 +1771,7 @@ void Thread::RemoveAbortRequestBit() #ifdef _DEBUG // There's a race between removing the TS_AbortRequested bit and decrementing g_TrapReturningThreads - // We may remove the bit, but before we have a chance to call ThreadStore::TrapReturningThreads(FALSE) + // We may remove the bit, but before we have a chance to call ThreadStore::DecrementTrapReturningThreads() // DbgFindThread() may execute, and find too few threads with the bit set. // To ensure the assert in DbgFindThread does not fire under such a race we set the ChgInFlight before hand. CounterHolder trtHolder(&g_trtChgInFlight); @@ -1792,7 +1785,7 @@ void Thread::RemoveAbortRequestBit() } if (InterlockedCompareExchange((LONG*)&m_State, curValue&(~TS_AbortRequested), curValue) == curValue) { - ThreadStore::TrapReturningThreads(FALSE); + ThreadStore::DecrementTrapReturningThreads(); break; } @@ -2053,7 +2046,6 @@ extern void WaitForEndOfShutdown(); //---------------------------------------------------------------------------- // A note on SUSPENSIONS. -// // We must not suspend a thread while it is holding the ThreadStore lock, or // the lock on the thread. Why? Because we need those locks to resume the // thread (and to perform a GC, use the debugger, spawn or kill threads, etc.) @@ -2099,10 +2091,11 @@ void Thread::RareDisablePreemptiveGC() goto Exit; } + _ASSERTE (m_fPreemptiveGCDisabled); + // Holding a spin lock in preemp mode and switch to coop mode could cause other threads spinning // waiting for GC _ASSERTE ((m_StateNC & Thread::TSNC_OwnsSpinLock) == 0); - _ASSERTE(!MethodDescBackpatchInfoTracker::IsLockOwnedByCurrentThread() || IsInForbidSuspendForDebuggerRegion()); if (!GCHeapUtilities::IsGCHeapInitialized()) @@ -2112,91 +2105,129 @@ void Thread::RareDisablePreemptiveGC() if (ThreadStore::HoldingThreadStore(this)) { + // A thread that performs GC may switch modes inside GC and come here. We would not want to + // suspend the thread that is responsible for the suspension. + // Ideally that would be the only the case when a thread that holds thread store lock + // may want to enter coop mode, but we have a number of other scenarios where TSL is acquired + // in coop mode or when TSL-owning thread tries to swtch to coop. + // We will handle all cases in the same way - by allowing the thread into coop mode without a wait. goto Exit; } - // Note IsGCInProgress is also true for say Pause (anywhere SuspendEE happens) and GCThread is the - // thread that did the Pause. While in Pause if another thread attempts Rev/Pinvoke it should get inside the following and - // block until resume - if ((GCHeapUtilities::IsGCInProgress() && (this != ThreadSuspend::GetSuspensionThread())) || - ((m_State & TS_DebugSuspendPending) && !IsInForbidSuspendForDebuggerRegion()) || - (m_State & TS_StackCrawlNeeded)) - { - STRESS_LOG1(LF_SYNC, LL_INFO1000, "RareDisablePreemptiveGC: entering. Thread state = %x\n", m_State.Load()); + STRESS_LOG1(LF_SYNC, LL_INFO1000, "RareDisablePreemptiveGC: entering. Thread state = %x\n", m_State.Load()); - DWORD dwSwitchCount = 0; +#if defined(STRESS_HEAP) && defined(_DEBUG) + if (GCStressPolicy::IsEnabled() && GCStress::IsEnabled() && !IsDetached()) + { + EnablePreemptiveGC(); + PerformPreemptiveGC(); + // disable preemptive gc. + m_fPreemptiveGCDisabled.StoreWithoutBarrier(1); + } +#endif - while (true) + // The general strategy of this loop: + // - we check for additional conditions while in coop mode. + // - if there is something, we had to do before going to coop mode (such as wait for GC), we + // - revert to preempt + // - perform additional work + // - set coop mode and do the loop again + // + // NOTE: It is important that the check is done in coop mode, at least for the GC handshake, + // as per contract with the setter of the conditions, we have to check the condition _before_ + // switching to coop mode. + while (true) + { +#ifdef DEBUGGING_SUPPORTED + // If debugger wants the thread to suspend, give the debugger precedence. + if (HasThreadStateOpportunistic(TS_DebugSuspendPending) && !IsInForbidSuspendForDebuggerRegion()) { EnablePreemptiveGC(); - // Cannot use GCX_PREEMP_NO_DTOR here because we're inside of the thread - // PREEMP->COOP switch mechanism and GCX_PREEMP's assert's will fire. - // Instead we use BEGIN_GCX_ASSERT_PREEMP to inform Scan of the mode - // change here. - BEGIN_GCX_ASSERT_PREEMP; + // We don't notify the debugger that this thread is now suspended. We'll just + // let the debugger's helper thread sweep and pick it up. + +#ifdef FEATURE_HIJACK + // Remove any hijacks we might have. + UnhijackThread(); +#endif // FEATURE_HIJACK - // just wait until the GC is over. - if (this != ThreadSuspend::GetSuspensionThread()) +#ifdef LOGGING { + LOG((LF_CORDB, LL_INFO1000, "[0x%x] SUSPEND: debug suspended while switching to coop mode.\n", GetThreadId())); + } +#endif + // unsets TS_DebugSuspendPending | TS_SyncSuspended + WaitSuspendEvents(); + + // disable preemptive gc. + m_fPreemptiveGCDisabled.StoreWithoutBarrier(1); + + // check again if we have something to do + continue; + } +#endif // DEBUGGING_SUPPORTED + + if (ThreadStore::IsTrappingThreadsForSuspension()) + { + EnablePreemptiveGC(); + #ifdef PROFILING_SUPPORTED - // If profiler desires GC events, notify it that this thread is waiting until the GC is over - // Do not send suspend notifications for debugger suspensions + // If profiler desires GC events, notify it that this thread is waiting until the GC is over + // Do not send suspend notifications for debugger suspensions + { + BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends()); + if (!(m_State & TS_DebugSuspendPending)) { - BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends()); - if (!(m_State & TS_DebugSuspendPending)) - { - (&g_profControlBlock)->RuntimeThreadSuspended((ThreadID)this); - } - END_PROFILER_CALLBACK(); + (&g_profControlBlock)->RuntimeThreadSuspended((ThreadID)this); } + END_PROFILER_CALLBACK(); + } #endif // PROFILING_SUPPORTED - DWORD status = GCHeapUtilities::GetGCHeap()->WaitUntilGCComplete(); - if (status != S_OK) - { - EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, W("Waiting for GC completion failed")); - } +#if defined(FEATURE_HIJACK) && !defined(TARGET_UNIX) + ResetThreadState(Thread::TS_GCSuspendRedirected); +#endif - if (!GCHeapUtilities::IsGCInProgress()) - { - if (HasThreadState(TS_StackCrawlNeeded)) - { - ThreadStore::WaitForStackCrawlEvent(); - } - } + DWORD status = GCHeapUtilities::GetGCHeap()->WaitUntilGCComplete(); + if (status != S_OK) + { + EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, W("Waiting for GC completion failed")); + } #ifdef PROFILING_SUPPORTED - // Let the profiler know that this thread is resuming - { - BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends()); - (&g_profControlBlock)->RuntimeThreadResumed((ThreadID)this); - END_PROFILER_CALLBACK(); - } -#endif // PROFILING_SUPPORTED + // Let the profiler know that this thread is resuming + { + BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends()); + (&g_profControlBlock)->RuntimeThreadResumed((ThreadID)this); + END_PROFILER_CALLBACK(); } +#endif // PROFILING_SUPPORTED + + // disable preemptive gc. + m_fPreemptiveGCDisabled.StoreWithoutBarrier(1); - END_GCX_ASSERT_PREEMP; + // check again if we have something to do + continue; + } + + if (HasThreadStateOpportunistic(TS_StackCrawlNeeded)) + { + EnablePreemptiveGC(); + ThreadStore::WaitForStackCrawlEvent(); // disable preemptive gc. - InterlockedOr((LONG*)&m_fPreemptiveGCDisabled, 1); - - // The fact that we check whether 'this' is the GC thread may seem - // strange. After all, we determined this before entering the method. - // However, it is possible for the current thread to become the GC - // thread while in this loop. This happens if you use the COM+ - // debugger to suspend this thread and then release it. - if (! ((GCHeapUtilities::IsGCInProgress() && (this != ThreadSuspend::GetSuspensionThread())) || - ((m_State & TS_DebugSuspendPending) && !IsInForbidSuspendForDebuggerRegion()) || - (m_State & TS_StackCrawlNeeded)) ) - { - break; - } + m_fPreemptiveGCDisabled.StoreWithoutBarrier(1); - __SwitchToThread(0, ++dwSwitchCount); + // check again if we have something to do + continue; } - STRESS_LOG0(LF_SYNC, LL_INFO1000, "RareDisablePreemptiveGC: leaving\n"); + + // nothing else to do + break; } + + STRESS_LOG0(LF_SYNC, LL_INFO1000, "RareDisablePreemptiveGC: leaving\n"); Exit: ; END_PRESERVE_LAST_ERROR; @@ -2278,7 +2309,7 @@ void Thread::PreWorkForThreadAbort() #if defined(STRESS_HEAP) && defined(_DEBUG) -// This function is for GC stress testing. Before we enable preemptive GC, let us do a GC +// This function is for GC stress testing. Before we disable preemptive GC, let us do a GC // because GC may happen while the thread is in preemptive GC mode. void Thread::PerformPreemptiveGC() { @@ -2336,81 +2367,6 @@ void Thread::PerformPreemptiveGC() } #endif // STRESS_HEAP && DEBUG -// To leave cooperative mode and enter preemptive mode, if a GC is in progress, we -// no longer care to suspend this thread. But if we are trying to suspend the thread -// for other reasons (e.g. Thread.Suspend()), now is a good time. -// -// Note that it is possible for an N/Direct call to leave the EE without explicitly -// enabling preemptive GC. -void Thread::RareEnablePreemptiveGC() -{ - CONTRACTL { - NOTHROW; - DISABLED(GC_TRIGGERS); // I think this is actually wrong: prevents a p->c->p mode switch inside a NOTRIGGER region. - } - CONTRACTL_END; - - // @todo - Needs a hard SO probe - CONTRACT_VIOLATION(GCViolation|FaultViolation); - - // If we have already received our PROCESS_DETACH during shutdown, there is only one thread in the - // process and no coordination is necessary. - if (IsAtProcessExit()) - return; - - _ASSERTE (!m_fPreemptiveGCDisabled); - - // holding a spin lock in coop mode and transit to preemp mode will cause deadlock on GC - _ASSERTE ((m_StateNC & Thread::TSNC_OwnsSpinLock) == 0); - - _ASSERTE(!MethodDescBackpatchInfoTracker::IsLockOwnedByCurrentThread() || IsInForbidSuspendForDebuggerRegion()); - -#if defined(STRESS_HEAP) && defined(_DEBUG) - if (!IsDetached()) - PerformPreemptiveGC(); -#endif - - STRESS_LOG1(LF_SYNC, LL_INFO100000, "RareEnablePreemptiveGC: entering. Thread state = %x\n", m_State.Load()); - if (!ThreadStore::HoldingThreadStore(this)) - { -#ifdef FEATURE_HIJACK - // Remove any hijacks we might have. - UnhijackThread(); -#endif // FEATURE_HIJACK - - // EnablePreemptiveGC already set us to preemptive mode before triggering the Rare path. - // the Rare path implies that someone else is observing us (e.g. SuspendRuntime). - // we have changed to preemptive mode, so signal that there was a suspension progress. - ThreadSuspend::g_pGCSuspendEvent->Set(); - - // for GC, the fact that we are leaving the EE means that it no longer needs to - // suspend us. But if we are doing a non-GC suspend, we need to block now. - // Give the debugger precedence over user suspensions: - while ((m_State & TS_DebugSuspendPending) && !IsInForbidSuspendForDebuggerRegion()) - { - -#ifdef DEBUGGING_SUPPORTED - // We don't notify the debugger that this thread is now suspended. We'll just - // let the debugger's helper thread sweep and pick it up. - // We also never take the TSL in here either. - // Life's much simpler this way... - - -#endif // DEBUGGING_SUPPORTED - -#ifdef LOGGING - { - LOG((LF_CORDB, LL_INFO1000, "[0x%x] SUSPEND: suspended while enabling gc.\n", GetThreadId())); - } -#endif - - WaitSuspendEvents(); // sets bits, too - - } - } - STRESS_LOG0(LF_SYNC, LL_INFO100000, "RareEnablePreemptiveGC: leaving.\n"); -} - // Called when we are passing through a safe point in CommonTripThread or // HandleSuspensionForInterruptedThread. Do the right thing with this thread, // which can either mean waiting for the GC to complete, or performing a @@ -2425,7 +2381,7 @@ void Thread::PulseGCMode() _ASSERTE(this == GetThread()); - if (PreemptiveGCDisabled() && CatchAtSafePoint()) + if (PreemptiveGCDisabled()) { EnablePreemptiveGC(); DisablePreemptiveGC(); @@ -2435,7 +2391,7 @@ void Thread::PulseGCMode() // Indicate whether threads should be trapped when returning to the EE (i.e. disabling // preemptive GC mode) Volatile g_fTrapReturningThreadsLock; -void ThreadStore::TrapReturningThreads(BOOL yes) +void ThreadStore::IncrementTrapReturningThreads() { CONTRACTL { NOTHROW; @@ -2458,31 +2414,73 @@ void ThreadStore::TrapReturningThreads(BOOL yes) suspend.Acquire(); } - if (yes) - { #ifdef _DEBUG - CounterHolder trtHolder(&g_trtChgInFlight); - InterlockedIncrement(&g_trtChgStamp); + CounterHolder trtHolder(&g_trtChgInFlight); + InterlockedIncrement(&g_trtChgStamp); #endif - GCHeapUtilities::GetGCHeap()->SetSuspensionPending(true); - InterlockedIncrement ((LONG *)&g_TrapReturningThreads); - _ASSERTE(g_TrapReturningThreads > 0); + InterlockedAdd ((LONG *)&g_TrapReturningThreads, 2); + _ASSERTE(g_TrapReturningThreads > 0); #ifdef _DEBUG - trtHolder.Release(); + trtHolder.Release(); #endif - } - else + + g_fTrapReturningThreadsLock = 0; +} + +void ThreadStore::DecrementTrapReturningThreads() +{ + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + } CONTRACTL_END; + + // make sure that a thread doesn't get suspended holding g_fTrapReturningThreadsLock + // if a suspended thread held this lock and then the suspending thread called in + // here (which it does) the suspending thread would deadlock causing the suspension + // as a whole to deadlock + ForbidSuspendThreadHolder suspend; + + DWORD dwSwitchCount = 0; + while (1 == InterlockedExchange(&g_fTrapReturningThreadsLock, 1)) { - InterlockedDecrement ((LONG *)&g_TrapReturningThreads); - GCHeapUtilities::GetGCHeap()->SetSuspensionPending(false); - _ASSERTE(g_TrapReturningThreads >= 0); + // we can't forbid suspension while we are sleeping and don't hold the lock + // this will trigger an assert on SQLCLR but is a general issue + suspend.Release(); + __SwitchToThread(0, ++dwSwitchCount); + suspend.Acquire(); } + InterlockedAdd ((LONG *)&g_TrapReturningThreads, -2); + _ASSERTE(g_TrapReturningThreads >= 0); + g_fTrapReturningThreadsLock = 0; } +void ThreadStore::SetThreadTrapForSuspension() +{ + _ASSERTE(ThreadStore::HoldingThreadStore()); + + _ASSERTE(!IsTrappingThreadsForSuspension()); + GCHeapUtilities::GetGCHeap()->SetSuspensionPending(true); + InterlockedIncrement((LONG *)&g_TrapReturningThreads); +} + +void ThreadStore::UnsetThreadTrapForSuspension() +{ + _ASSERTE(ThreadStore::HoldingThreadStore()); + + _ASSERTE(IsTrappingThreadsForSuspension()); + InterlockedDecrement((LONG *)&g_TrapReturningThreads); + GCHeapUtilities::GetGCHeap()->SetSuspensionPending(false); +} + +bool ThreadStore::IsTrappingThreadsForSuspension() +{ + return (g_TrapReturningThreads & 1) != 0; +} + #ifdef FEATURE_HIJACK void RedirectedThreadFrame::ExceptionUnwind() @@ -3209,6 +3207,44 @@ COR_PRF_SUSPEND_REASON GCSuspendReasonToProfSuspendReason(ThreadSuspend::SUSPEND } #endif // PROFILING_SUPPORTED +static int64_t QueryPerformanceCounter() +{ + LARGE_INTEGER ts; + QueryPerformanceCounter(&ts); + return ts.QuadPart; +} + +static int64_t QueryPerformanceFrequency() +{ + LARGE_INTEGER ts; + QueryPerformanceFrequency(&ts); + return ts.QuadPart; +} + +// exponential spinwait with an approximate time limit for waiting in microsecond range. +// when iteration == -1, only usecLimit is used +void SpinWait(int iteration, int usecLimit) +{ + int64_t startTicks = QueryPerformanceCounter(); + int64_t ticksPerSecond = QueryPerformanceFrequency(); + int64_t endTicks = startTicks + (usecLimit * ticksPerSecond) / 1000000; + + int l = iteration >= 0 ? min(iteration, 30): 30; + for (int i = 0; i < l; i++) + { + for (int j = 0; j < (1 << i); j++) + { + System_YieldProcessor(); + } + + int64_t currentTicks = QueryPerformanceCounter(); + if (currentTicks > endTicks) + { + break; + } + } +} + //************************************************************************************ // // SuspendRuntime is responsible for ensuring that all managed threads reach a @@ -3247,7 +3283,7 @@ COR_PRF_SUSPEND_REASON GCSuspendReasonToProfSuspendReason(ThreadSuspend::SUSPEND // which leaves cooperative mode and waits for the GC to complete. // // See code:Thread#SuspendingTheRuntime for more -void ThreadSuspend::SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason) +void ThreadSuspend::SuspendAllThreads() { CONTRACTL { NOTHROW; @@ -3262,61 +3298,36 @@ void ThreadSuspend::SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason) } CONTRACTL_END; - // This thread - Thread *pCurThread = GetThreadNULLOk(); + STRESS_LOG(LF_SYNC, LL_INFO1000, "Thread::SuspendAllThreads()\n"); + + // From this point until the end of the function, consider all active thread + // suspension to be in progress. This is mainly to give the profiler API a hint + // that trying to suspend a thread (in order to walk its stack) could delay the + // overall EE suspension. So the profiler API would early-abort the stackwalk + // in such a case. + SuspendRuntimeInProgressHolder hldSuspendRuntimeInProgress; // Caller is expected to be holding the ThreadStore lock. Also, caller must // have set GcInProgress before coming here, or things will break; _ASSERTE(ThreadStore::HoldingThreadStore() || IsAtProcessExit()); - _ASSERTE(GCHeapUtilities::IsGCInProgress() ); - STRESS_LOG1(LF_SYNC, LL_INFO1000, "Thread::SuspendRuntime(reason=0x%x)\n", reason); - - -#ifdef PROFILING_SUPPORTED - // If the profiler desires information about GCs, then let it know that one - // is starting. - { - BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends()); - _ASSERTE(reason != ThreadSuspend::SUSPEND_FOR_DEBUGGER); - _ASSERTE(reason != ThreadSuspend::SUSPEND_FOR_DEBUGGER_SWEEP); + // This thread + Thread *pCurThread = GetThreadNULLOk(); - { - (&g_profControlBlock)->RuntimeSuspendStarted( - GCSuspendReasonToProfSuspendReason(reason)); - } - if (pCurThread) - { - // Notify the profiler that the thread that is actually doing the GC is 'suspended', - // meaning that it is doing stuff other than run the managed code it was before the - // GC started. - (&g_profControlBlock)->RuntimeThreadSuspended((ThreadID)pCurThread); - } - END_PROFILER_CALLBACK(); - } -#endif // PROFILING_SUPPORTED + // + // Remember that we're the one suspending the EE + // + g_pSuspensionThread = pCurThread; // - // If this thread is running at low priority, boost its priority. We remember the old - // priority so that we can restore it in ResumeRuntime. + // First, we reset the event that we're about to tell other threads to wait for. // - if (pCurThread) // concurrent GC occurs on threads we don't know about - { - _ASSERTE(pCurThread->m_Priority == INVALID_THREAD_PRIORITY); - int priority = pCurThread->GetThreadPriority(); - if (priority < THREAD_PRIORITY_NORMAL) - { - pCurThread->m_Priority = priority; - pCurThread->SetThreadPriority(THREAD_PRIORITY_NORMAL); - } - } + GCHeapUtilities::GetGCHeap()->ResetWaitForGCEvent(); - // From this point until the end of the function, consider all active thread - // suspension to be in progress. This is mainly to give the profiler API a hint - // that trying to suspend a thread (in order to walk its stack) could delay the - // overall EE suspension. So the profiler API would early-abort the stackwalk - // in such a case. - SuspendRuntimeInProgressHolder hldSuspendRuntimeInProgress; + // + // Tell all threads, globally, to wait for WaitForGCEvent. + // + ThreadStore::SetThreadTrapForSuspension(); // Flush the store buffers on all CPUs, to ensure two things: // - we get a reliable reading of the threads' m_fPreemptiveGCDisabled state @@ -3324,374 +3335,204 @@ void ThreadSuspend::SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason) // See VSW 475315 and 488918 for details. ::FlushProcessWriteBuffers(); - // - // Make a pass through all threads. We do a couple of things here: - // 1) we count the number of threads that are observed to be in cooperative mode. - // 2) for threads currently running managed code, we try to redirect/jihack them. - - // counts of cooperative threads - int previousCount = 0; - int countThreads = 0; - - // we will iterate over threads and check which are left in coop mode - // while checking, we also will try suspending and hijacking - // unless we have just done that, then we can observeOnly and see if situation improves - // we do not on uniprocessor though (spin-checking is pointless on uniprocessor) + int retries = 0; + int prevRemaining = 0; + int remaining = 0; bool observeOnly = false; - _ASSERTE(!pCurThread || !pCurThread->HasThreadState(Thread::TS_GCSuspendFlags)); -#ifdef _DEBUG - DWORD dbgStartTimeout = GetTickCount(); -#endif - - while (true) + while(true) { - Thread* thread = NULL; - while ((thread = ThreadStore::GetThreadList(thread)) != NULL) + prevRemaining = remaining; + remaining = 0; + + Thread* pTargetThread = NULL; + while ((pTargetThread = ThreadStore::GetThreadList(pTargetThread)) != NULL) { - if (thread == pCurThread) + if (pTargetThread == pCurThread) continue; - // on the first iteration check m_fPreemptiveGCDisabled unconditionally and - // mark interesting threads as TS_GCSuspendPending - if (previousCount == 0) + if (pTargetThread->m_fPreemptiveGCDisabled.LoadWithoutBarrier()) { - STRESS_LOG3(LF_SYNC, LL_INFO10000, " Inspecting thread 0x%x ID 0x%x coop mode = %d\n", - thread, thread->GetThreadId(), thread->m_fPreemptiveGCDisabled.LoadWithoutBarrier()); - - - // ::FlushProcessWriteBuffers above guarantees that the state that we see here - // is after the trap flag is visible to the other thread. - // - // In other words: any threads seen in preemptive mode are no longer interesting to us. - // if they try switch to cooperative, they would see the flag set. -#ifdef FEATURE_PERFTRACING - // Mark that the thread is currently in managed code. - thread->SaveGCModeOnSuspension(); -#endif // FEATURE_PERFTRACING - if (!thread->m_fPreemptiveGCDisabled.LoadWithoutBarrier()) - { - _ASSERTE(!thread->HasThreadState(Thread::TS_GCSuspendFlags)); - continue; - } - else + remaining++; + if (!observeOnly) { - countThreads++; - thread->SetThreadState(Thread::TS_GCSuspendPending); + pTargetThread->Hijack(); } } + } - if (!thread->HasThreadStateOpportunistic(Thread::TS_GCSuspendPending)) - { - continue; - } + if (!remaining) + break; + + // if we see progress or have just done a hijacking pass + // do not hijack in the next iteration + if (remaining < prevRemaining || !observeOnly) + { + // 5 usec delay, then check for more progress + SpinWait(-1, 5); + observeOnly = true; + } + else + { + SpinWait(retries++, 100); + observeOnly = false; - if (!thread->m_fPreemptiveGCDisabled.LoadWithoutBarrier()) + // make sure our spining is not starving other threads, but not too often, + // this can cause a 1-15 msec delay, depending on OS, and that is a lot while + // very rarely needed, since threads are supposed to be releasing their CPUs + if ((retries & 127) == 0) { - STRESS_LOG1(LF_SYNC, LL_INFO1000, " Thread %x went preemptive it is at a GC safe point\n", thread); - countThreads--; - thread->ResetThreadState(Thread::TS_GCSuspendFlags); - continue; - } - - if (observeOnly) - { - continue; + SwitchToThread(); } + } + } - if (thread->IsGCSpecial()) - { - // GC threads can not be forced to run preemptively, so we will not try. - continue; - } +#if defined(TARGET_ARM) || defined(TARGET_ARM64) + // Flush the store buffers on all CPUs, to ensure that all changes made so far are seen + // by the GC threads. This only matters on weak memory ordered processors as + // the strong memory ordered processors wouldn't have reordered the relevant writes. + // This is needed to synchronize threads that were running in preemptive mode thus were + // left alone by suspension to flush their writes that they made before they switched to + // preemptive mode. + ::FlushProcessWriteBuffers(); +#endif //TARGET_ARM || TARGET_ARM64 - // this is an interesting thread in cooperative mode, let's guide it to preemptive + STRESS_LOG0(LF_SYNC, LL_INFO1000, "Thread::SuspendAllThreads() - Success\n"); +} - if (!Thread::UseContextBasedThreadRedirection()) - { - // On platforms that do not support safe thread suspension, we do one of the following: - // - // - If we're on a Unix platform where hijacking is enabled, we attempt - // to inject an activation which will try to redirect or hijack the - // thread to get it to a safe point. - // - // - Similarly to above, if we're on a Windows platform where the special - // user-mode APC is available, that is used if redirection is necessary. - // - // - Otherwise, we rely on the GCPOLL mechanism enabled by - // TrapReturningThreads. +void Thread::Hijack() +{ + if (IsGCSpecial()) + { + // GC threads can not be forced to run preemptively, so we will not try. + return; + } + if (!Thread::UseContextBasedThreadRedirection()) + { + // On platforms that have signal-like API, we do one of the following: + // - If we're on a Unix platform where hijacking is enabled, we attempt + // to inject an activation which will try to redirect or hijack the + // thread to get it to a safe point. + // + // - Similarly to above, if we're on a Windows platform where the special + // user-mode APC is available, that is used if redirection is necessary. + // + // - Otherwise, we rely on the GCPOLL mechanism enabled by + // TrapReturningThreads. #ifdef FEATURE_THREAD_ACTIVATION - bool success = thread->InjectActivation(Thread::ActivationReason::SuspendForGC); - if (!success) - { - STRESS_LOG1(LF_SYNC, LL_INFO1000, "Thread::SuspendRuntime() - Failed to inject an activation for thread %p.\n", thread); - } + bool success = InjectActivation(Thread::ActivationReason::SuspendForGC); + if (!success) + { + STRESS_LOG1(LF_SYNC, LL_INFO1000, "Thread::Hijack() - Failed to inject an activation for thread %p.\n", this); + } #endif // FEATURE_THREAD_ACTIVATION - - continue; - } + return; + } #ifndef DISABLE_THREADSUSPEND - - if (thread->HasThreadStateOpportunistic(Thread::TS_GCSuspendRedirected)) - { - // We have seen this thead before and have redirected it. - // No point in suspending it again. It will not run hijackable code until it parks itself. - continue; - } + if (HasThreadStateOpportunistic(Thread::TS_GCSuspendRedirected)) + { + // We have seen this thead before and have redirected it. + // No point in suspending it again. It will not run hijackable code until it blocks on GC event. + return; + } #ifdef TIME_SUSPEND - DWORD startSuspend = g_SuspendStatistics.GetTime(); + DWORD startSuspend = g_SuspendStatistics.GetTime(); #endif - // - // Suspend the native thread. - // + // + // Suspend the native thread. + // - // We can not allocate memory after we suspend a thread. - // Otherwise, we may deadlock the process, because the thread we just suspended - // might hold locks we would need to acquire while allocating. - ThreadStore::AllocateOSContext(); - Thread::SuspendThreadResult str = thread->SuspendThread(/*fOneTryOnly*/ TRUE); + // We can not allocate memory after we suspend a thread. + // Otherwise, we may deadlock the process, because the thread we just suspended + // might hold locks we would need to acquire while allocating. + ThreadStore::AllocateOSContext(); + Thread::SuspendThreadResult str = SuspendThread(/*fOneTryOnly*/ TRUE); - // We should just always build with this TIME_SUSPEND stuff, and report the results via ETW. + // We should just always build with this TIME_SUSPEND stuff, and report the results via ETW. #ifdef TIME_SUSPEND - g_SuspendStatistics.osSuspend.Accumulate( - SuspendStatistics::GetElapsed(startSuspend, - g_SuspendStatistics.GetTime())); + g_SuspendStatistics.osSuspend.Accumulate( + SuspendStatistics::GetElapsed(startSuspend, + g_SuspendStatistics.GetTime())); - if (str == Thread::STR_Success) - g_SuspendStatistics.cntOSSuspendResume++; - else - g_SuspendStatistics.cntFailedSuspends++; + if (str == Thread::STR_Success) + g_SuspendStatistics.cntOSSuspendResume++; + else + g_SuspendStatistics.cntFailedSuspends++; #endif - switch (str) - { - case Thread::STR_Success: - // let's check the state of this one. - break; - - case Thread::STR_Forbidden: - STRESS_LOG1(LF_SYNC, LL_INFO1000, " Suspending thread 0x%x forbidden\n", thread); - continue; + switch (str) + { + case Thread::STR_Success: + // let's check the state of this one. + break; - case Thread::STR_NoStressLog: - STRESS_LOG2(LF_SYNC, LL_ERROR, " ERROR: Could not suspend thread 0x%x, result = %d\n", thread, str); - continue; + case Thread::STR_Forbidden: + STRESS_LOG1(LF_SYNC, LL_INFO1000, " Suspending thread 0x%x forbidden\n", this); + return; - case Thread::STR_UnstartedOrDead: - case Thread::STR_Failure: - STRESS_LOG3(LF_SYNC, LL_ERROR, " ERROR: Could not suspend thread 0x%x, result = %d, lastError = 0x%x\n", thread, str, GetLastError()); - continue; - } + case Thread::STR_NoStressLog: + STRESS_LOG2(LF_SYNC, LL_ERROR, " ERROR: Could not suspend thread 0x%x, result = %d\n", this, str); + return; - // the thread is suspended here, we can hijack, if platform supports. + case Thread::STR_UnstartedOrDead: + case Thread::STR_Failure: + STRESS_LOG3(LF_SYNC, LL_ERROR, " ERROR: Could not suspend thread 0x%x, result = %d, lastError = 0x%x\n", this, str, GetLastError()); + return; + } - if (!thread->m_fPreemptiveGCDisabled.LoadWithoutBarrier()) - { - // actually, we are done with this one - STRESS_LOG1(LF_SYNC, LL_INFO1000, " Thread %x went preemptive while suspending it is at a GC safe point\n", thread); - countThreads--; - thread->ResetThreadState(Thread::TS_GCSuspendFlags); - thread->ResumeThread(); - continue; - } + // the thread is suspended here, we can hijack, if it is stopped in hijackable location + if (!m_fPreemptiveGCDisabled.LoadWithoutBarrier()) + { + // actually, we are done with this one + STRESS_LOG1(LF_SYNC, LL_INFO1000, " Thread %x went preemptive while suspending it is at a GC safe point\n", this); + ResumeThread(); + return; + } - // We now know for sure that the thread is still in cooperative mode. If it's in JIT'd code, here - // is where we try to hijack/redirect the thread. If it's in VM code, we have to just let the VM - // finish what it's doing. + // We now know for sure that the thread is still in cooperative mode. If it's in JIT'd code, here + // is where we try to hijack/redirect the thread. If it's in VM code, we have to just let the VM + // finish what it's doing. #if defined(FEATURE_HIJACK) && !defined(TARGET_UNIX) - { - Thread::WorkingOnThreadContextHolder workingOnThreadContext(thread); - - // Note that thread->HandledJITCase is not a simple predicate - it actually will hijack the thread if that's possible. - // So HandledJITCase can do one of these: - // - Return TRUE, in which case it's our responsibility to redirect the thread - // - Return FALSE after hijacking the thread - we shouldn't try to redirect - // - Return FALSE but not hijack the thread - there's nothing we can do either - if (workingOnThreadContext.Acquired() && thread->HandledJITCase()) - { - // Thread is in cooperative state and stopped in interruptible code. - // Redirect thread so we can capture a good thread context - // (GetThreadContext is not sufficient, due to an OS bug). - if (!thread->CheckForAndDoRedirectForGC()) - { -#ifdef TIME_SUSPEND - g_SuspendStatistics.cntFailedRedirections++; -#endif - STRESS_LOG1(LF_SYNC, LL_INFO1000, "Failed to CheckForAndDoRedirectForGC(). Thread %p\n", thread); - } - else - { -#ifdef TIME_SUSPEND - g_SuspendStatistics.cntRedirections++; -#endif - thread->SetThreadState(Thread::TS_GCSuspendRedirected); - STRESS_LOG1(LF_SYNC, LL_INFO1000, "Thread::SuspendRuntime() - Thread %p redirected().\n", thread); - } - } - } -#endif // FEATURE_HIJACK && !TARGET_UNIX - - thread->ResumeThread(); - STRESS_LOG1(LF_SYNC, LL_INFO1000, " Thread 0x%x is in cooperative needs to rendezvous\n", thread); -#endif // !DISABLE_THREADSUSPEND - } - - if (countThreads == 0) - { - // SUCCESS!! - break; - } - - bool hasProgress = previousCount != countThreads; - previousCount = countThreads; + { + Thread::WorkingOnThreadContextHolder workingOnThreadContext(this); - // If we have just updated hijacks/redirects, then do a pass while only observing. - // Repeat observing only as long as we see progress. Most threads react to hijack/redirect very fast and - // typically we can avoid waiting on an event. (except on uniprocessor where we do not spin) - // - // Otherwise redo hijacks, but check g_pGCSuspendEvent event on the way. - // Re-hijacking unconditionally is likely to execute exactly the same hijacks, - // while not letting the other threads to run much. - // Thus we require either PING_JIT_TIMEOUT or some progress between active suspension attempts. - if (g_SystemInfo.dwNumberOfProcessors > 1 && (hasProgress || !observeOnly)) + // Note that pTargetThread->HandledJITCase is not a simple predicate - it actually will hijack the thread if that's possible. + // So HandledJITCase can do one of these: + // - Return TRUE, in which case it's our responsibility to redirect the thread + // - Return FALSE after hijacking the thread - we shouldn't try to redirect + // - Return FALSE but not hijack the thread - there's nothing we can do either + if (workingOnThreadContext.Acquired() && HandledJITCase()) { - // small pause - YieldProcessorNormalized(); - - STRESS_LOG1(LF_SYNC, LL_INFO1000, "Spinning, %d threads remaining\n", countThreads); - observeOnly = true; - continue; - } - + // Thread is in cooperative state and stopped in interruptible code. + // Redirect thread so we can capture a good thread context + // (GetThreadContext is not sufficient, due to an OS bug). + if (!CheckForAndDoRedirectForGC()) + { #ifdef TIME_SUSPEND - DWORD startWait = g_SuspendStatistics.GetTime(); + g_SuspendStatistics.cntFailedRedirections++; #endif - - // Wait for at least one thread to tell us it's left cooperative mode. - // we do this by waiting on g_pGCSuspendEvent. We cannot simply wait forever, because we - // might have done return-address hijacking on a thread, and that thread might not - // return from the method we hijacked (maybe it calls into some other managed code that - // executes a long loop, for example). We wait with a timeout, and retry hijacking/redirection. - // - // This is unfortunate, because it means that in some cases we wait for PING_JIT_TIMEOUT - // milliseconds, causing long GC pause times. - - STRESS_LOG1(LF_SYNC, LL_INFO1000, "Waiting for suspend event %d threads remaining\n", countThreads); - DWORD res = g_pGCSuspendEvent->Wait(PING_JIT_TIMEOUT, FALSE); - + STRESS_LOG1(LF_SYNC, LL_INFO1000, "Failed to CheckForAndDoRedirectForGC(). Thread %p\n", this); + } + else + { #ifdef TIME_SUSPEND - g_SuspendStatistics.wait.Accumulate( - SuspendStatistics::GetElapsed(startWait, - g_SuspendStatistics.GetTime())); - - g_SuspendStatistics.cntWaits++; - if (res == WAIT_TIMEOUT) - g_SuspendStatistics.cntWaitTimeouts++; + g_SuspendStatistics.cntRedirections++; #endif - - if (res == WAIT_TIMEOUT || res == WAIT_IO_COMPLETION) - { - STRESS_LOG1(LF_SYNC, LL_INFO1000, " Timed out waiting for rendezvous event %d threads remaining\n", countThreads); -#ifdef _DEBUG - DWORD dbgEndTimeout = GetTickCount(); - - if ((dbgEndTimeout > dbgStartTimeout) && - (dbgEndTimeout - dbgStartTimeout > g_pConfig->SuspendDeadlockTimeout())) - { - // Do not change this to _ASSERTE. - // We want to catch the state of the machine at the - // time when we can not suspend some threads. - // It takes too long for _ASSERTE to stop the process. - DebugBreak(); - _ASSERTE(!"Timed out trying to suspend EE due to thread"); - char message[256]; - - Thread* thread = NULL; - while ((thread = ThreadStore::GetThreadList(thread)) != NULL) - { - if (thread == pCurThread) - continue; - - if ((thread->m_State & Thread::TS_GCSuspendPending) == 0) - continue; - - if (thread->m_fPreemptiveGCDisabled) - { - DWORD id = (DWORD) thread->m_OSThreadId; - if (id == 0xbaadf00d) - { - sprintf_s (message, ARRAY_SIZE(message), "Thread CLR ID=%x cannot be suspended", - thread->GetThreadId()); - } - else - { - sprintf_s (message, ARRAY_SIZE(message), "Thread OS ID=%x cannot be suspended", - id); - } - DbgAssertDialog(__FILE__, __LINE__, message); - } - } - // if we continue from the assert we'll reset the time - dbgStartTimeout = GetTickCount(); + SetThreadState(Thread::TS_GCSuspendRedirected); + STRESS_LOG1(LF_SYNC, LL_INFO1000, "Thread::Hijack() - Thread %p redirected().\n", this); } -#endif - } - else if (res == WAIT_OBJECT_0) - { } - else - { - // No WAIT_FAILED, WAIT_ABANDONED, etc. - _ASSERTE(!"unexpected wait termination during gc suspension"); - } - - observeOnly = false; - g_pGCSuspendEvent->Reset(); - } - -#ifdef PROFILING_SUPPORTED - // If a profiler is keeping track of GC events, notify it - { - BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends()); - (&g_profControlBlock)->RuntimeSuspendFinished(); - END_PROFILER_CALLBACK(); - } -#endif // PROFILING_SUPPORTED - -#ifdef _DEBUG - if (reason == ThreadSuspend::SUSPEND_FOR_GC) - { - Thread* thread = NULL; - while ((thread = ThreadStore::GetThreadList(thread)) != NULL) - { - thread->DisableStressHeap(); - _ASSERTE(!thread->HasThreadState(Thread::TS_GCSuspendPending)); - } - } -#endif - - // We know all threads are in preemptive mode, so go ahead and reset the event. - g_pGCSuspendEvent->Reset(); - -#ifdef HAVE_GCCOVER - // - // Now that the EE has been suspended, let's see if any oustanding - // gcstress instruction updates need to occur. Each thread can - // have only one pending at a time. - // - Thread* thread = NULL; - while ((thread = ThreadStore::GetThreadList(thread)) != NULL) - { - thread->CommitGCStressInstructionUpdate(); } -#endif // HAVE_GCCOVER +#endif // FEATURE_HIJACK && !TARGET_UNIX - STRESS_LOG0(LF_SYNC, LL_INFO1000, "Thread::SuspendRuntime() - Success\n"); + ResumeThread(); + STRESS_LOG1(LF_SYNC, LL_INFO1000, " Thread 0x%x is in cooperative needs to rendezvous\n", this); +#endif // !DISABLE_THREADSUSPEND } #ifdef HAVE_GCCOVER @@ -3752,9 +3593,7 @@ void EnableStressHeapHelper() } #endif -// We're done with our GC. Let all the threads run again. -// By this point we've already unblocked most threads. This just releases the ThreadStore lock. -void ThreadSuspend::ResumeRuntime(BOOL bFinishedGC, BOOL SuspendSucceeded) +void ThreadSuspend::ResumeAllThreads(BOOL SuspendSucceeded) { CONTRACTL { NOTHROW; @@ -3762,72 +3601,48 @@ void ThreadSuspend::ResumeRuntime(BOOL bFinishedGC, BOOL SuspendSucceeded) } CONTRACTL_END; - Thread *pCurThread = GetThreadNULLOk(); - - // Caller is expected to be holding the ThreadStore lock. But they must have - // reset GcInProgress, or threads will continue to suspend themselves and won't - // be resumed until the next GC. - _ASSERTE(IsGCSpecialThread() || ThreadStore::HoldingThreadStore()); - _ASSERTE(!GCHeapUtilities::IsGCInProgress() ); - - STRESS_LOG2(LF_SYNC, LL_INFO1000, "Thread::ResumeRuntime(finishedGC=%d, SuspendSucceeded=%d) - Start\n", bFinishedGC, SuspendSucceeded); - + // Caller is expected to be holding the ThreadStore lock since we will be iterating threads. + _ASSERTE(ThreadStore::HoldingThreadStore()); // - // Notify everyone who cares, that this suspension is over, and this thread is going to go do other things. + // Unhijack all threads, and reset their "suspend pending" flags. // - - -#ifdef PROFILING_SUPPORTED - // Need to give resume event for the GC thread + Thread *thread = NULL; + while ((thread = ThreadStore::GetThreadList(thread)) != NULL) { - BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends()); - if (pCurThread) - { - (&g_profControlBlock)->RuntimeThreadResumed((ThreadID)pCurThread); - } - END_PROFILER_CALLBACK(); + thread->PrepareForEERestart(SuspendSucceeded); } -#endif // PROFILING_SUPPORTED -#ifdef TIME_SUSPEND - DWORD startRelease = g_SuspendStatistics.GetTime(); -#endif +#if defined(TARGET_ARM) || defined(TARGET_ARM64) + // Flush the store buffers on all CPUs, to ensure that they all see changes made + // by the GC threads. This only matters on weak memory ordered processors as + // the strong memory ordered processors wouldn't have reordered the relevant reads. + // This is needed to synchronize threads that were running in preemptive mode while + // the runtime was suspended and that will return to cooperative mode after the runtime + // is restarted. + ::FlushProcessWriteBuffers(); +#endif //TARGET_ARM || TARGET_ARM64 // - // Unlock the thread store. At this point, all threads should be allowed to run. - // - ThreadSuspend::UnlockThreadStore(); - -#ifdef TIME_SUSPEND - g_SuspendStatistics.releaseTSL.Accumulate(SuspendStatistics::GetElapsed(startRelease, - g_SuspendStatistics.GetTime())); -#endif - -#ifdef PROFILING_SUPPORTED + // Allow threads to enter COOP mode (though we still need to wake the ones + // that we hijacked). // - // This thread is logically "resuming" from a GC now. Tell the profiler. + // Note: this is the last barrier that keeps managed threads + // from entering cooperative mode. If the sequence changes, + // you may have to change routine GCHeapUtilities::SafeToRestartManagedThreads + // as well. // - { - BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends()); - GCX_PREEMP(); - (&g_profControlBlock)->RuntimeResumeFinished(); - END_PROFILER_CALLBACK(); - } -#endif // PROFILING_SUPPORTED + ThreadStore::UnsetThreadTrapForSuspension(); + g_pSuspensionThread = 0; // - // If we raised this thread's priority in SuspendRuntime, we restore it here. + // Any threads that are waiting in WaitUntilGCComplete will continue now. // - if (pCurThread) - { - if (pCurThread->m_Priority != INVALID_THREAD_PRIORITY) - { - pCurThread->SetThreadPriority(pCurThread->m_Priority); - pCurThread->m_Priority = INVALID_THREAD_PRIORITY; - } - } + GCHeapUtilities::GetGCHeap()->SetWaitForGCEvent(); + _ASSERTE(IsGCSpecialThread() || ThreadStore::HoldingThreadStore()); - STRESS_LOG0(LF_SYNC, LL_INFO1000, "Thread::ResumeRuntime() - End\n"); + + STRESS_LOG1(LF_SYNC, LL_INFO1000, "ResumeAllThreads(SuspendSucceeded=%d) - Start\n", SuspendSucceeded); + STRESS_LOG0(LF_SYNC, LL_INFO1000, "ResumeAllThreads() - End\n"); } #ifndef TARGET_UNIX @@ -4031,7 +3846,7 @@ BOOL Thread::HandleJITCaseForAbort() // Threads suspended by ClrSuspendThread() are resumed in two ways. If we // suspended them in error, they are resumed via ClrResumeThread(). But if // this is the HandledJIT() case and the thread is in fully interruptible code, we -// can resume them under special control. ResumeRuntime and UserResume are cases +// can resume them under special control. ResumeAllThreads and UserResume are cases // of this. // // The suspension has done its work (e.g. GC or user thread suspension). But during @@ -4154,7 +3969,7 @@ bool Thread::SysStartSuspendForDebug(AppDomain *pAppDomain) } LOG((LF_CORDB, LL_INFO1000, "[0x%x] SUSPEND: starting suspend. Trap count: %d\n", - pCurThread ? pCurThread->GetThreadId() : (DWORD) -1, g_TrapReturningThreads.Load())); + pCurThread ? pCurThread->GetThreadId() : (DWORD) -1, g_TrapReturningThreads)); // Caller is expected to be holding the ThreadStore lock _ASSERTE(ThreadStore::HoldingThreadStore() || IsAtProcessExit()); @@ -4569,14 +4384,6 @@ void Thread::SysResumeFromDebug(AppDomain *pAppDomain) while ((thread = ThreadStore::GetThreadList(thread)) != NULL) { - // Only consider resuming threads if they're in the correct appdomain - if (pAppDomain != NULL && thread->GetDomain() != pAppDomain) - { - LOG((LF_CORDB, LL_INFO1000, "RESUME: Not resuming thread 0x%x, since it's " - "in appdomain 0x%x.\n", thread, pAppDomain)); - continue; - } - // If the user wants to keep the thread suspended, then // don't release the thread. if (!(thread->m_StateNC & TSNC_DebuggerUserSuspend)) @@ -4613,7 +4420,7 @@ void Thread::SysResumeFromDebug(AppDomain *pAppDomain) } } - LOG((LF_CORDB, LL_INFO1000, "RESUME: resume complete. Trap count: %d\n", g_TrapReturningThreads.Load())); + LOG((LF_CORDB, LL_INFO1000, "RESUME: resume complete. Trap count: %d\n", g_TrapReturningThreads)); } /* @@ -4672,7 +4479,7 @@ BOOL Thread::WaitSuspendEventsHelper(void) // There's a bit of a workaround here -void Thread::WaitSuspendEvents(BOOL fDoWait) +void Thread::WaitSuspendEvents() { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; @@ -4681,35 +4488,29 @@ void Thread::WaitSuspendEvents(BOOL fDoWait) _ASSERTE((m_State & TS_SyncSuspended) == 0); // Let us do some useful work before suspending ourselves. - - // If we're required to perform a wait, do so. Typically, this is - // skipped if this thread is a Debugger Special Thread. - if (fDoWait) + while (TRUE) { - while (TRUE) - { - WaitSuspendEventsHelper(); + WaitSuspendEventsHelper(); - ThreadState oldState = m_State; + ThreadState oldState = m_State; + // + // If all reasons to suspend are off, we think we can exit + // this loop, but we need to check atomically. + // + if ((oldState & TS_DebugSuspendPending) == 0) + { // - // If all reasons to suspend are off, we think we can exit - // this loop, but we need to check atomically. + // Construct the destination state we desire - all suspension bits turned off. // - if ((oldState & TS_DebugSuspendPending) == 0) + ThreadState newState = (ThreadState)(oldState & ~(TS_DebugSuspendPending | TS_SyncSuspended)); + + if (InterlockedCompareExchange((LONG *)&m_State, newState, oldState) == (LONG)oldState) { // - // Construct the destination state we desire - all suspension bits turned off. + // We are done. // - ThreadState newState = (ThreadState)(oldState & ~(TS_DebugSuspendPending | TS_SyncSuspended)); - - if (InterlockedCompareExchange((LONG *)&m_State, newState, oldState) == (LONG)oldState) - { - // - // We are done. - // - break; - } + break; } } } @@ -4747,13 +4548,13 @@ void Thread::HijackThread(ReturnKind returnKind, ExecutionState *esb) VOID *pvHijackAddr = reinterpret_cast(OnHijackTripThread); -#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) +#if defined(TARGET_WINDOWS) void* returnAddressHijackTarget = ThreadSuspend::GetReturnAddressHijackTarget(); if (returnAddressHijackTarget != NULL) { pvHijackAddr = returnAddressHijackTarget; } -#endif // TARGET_WINDOWS && TARGET_AMD64 +#endif // TARGET_WINDOWS #ifdef TARGET_X86 if (returnKind == RT_Float) @@ -5545,7 +5346,7 @@ void Thread::MarkForSuspension(ULONG bit) _ASSERTE((m_State & bit) == 0); InterlockedOr((LONG*)&m_State, bit); - ThreadStore::TrapReturningThreads(TRUE); + ThreadStore::IncrementTrapReturningThreads(); } void Thread::UnmarkForSuspension(ULONG mask) @@ -5564,7 +5365,7 @@ void Thread::UnmarkForSuspension(ULONG mask) _ASSERTE((m_State & ~mask) != 0); // we decrement the global first to be able to satisfy the assert from DbgFindThread - ThreadStore::TrapReturningThreads(FALSE); + ThreadStore::DecrementTrapReturningThreads(); InterlockedAnd((LONG*)&m_State, mask); } @@ -5616,41 +5417,69 @@ void ThreadSuspend::RestartEE(BOOL bFinishedGC, BOOL SuspendSucceeded) } #endif // PROFILING_SUPPORTED - // - // Unhijack all threads, and reset their "suspend pending" flags. Why isn't this in - // Thread::ResumeRuntime? - // - Thread *thread = NULL; - while ((thread = ThreadStore::GetThreadList(thread)) != NULL) - { - thread->PrepareForEERestart(SuspendSucceeded); - } - // // Revert to being a normal thread // ClrFlsClearThreadType (ThreadType_DynamicSuspendEE); GCHeapUtilities::GetGCHeap()->SetGCInProgress(false); + ResumeAllThreads(SuspendSucceeded); + // - // Allow threads to enter COOP mode (though we still need to wake the ones - // that we hijacked). + // Notify everyone who cares, that this suspension is over, and this thread is going to go do other things. // - // Note: this is the last barrier that keeps managed threads - // from entering cooperative mode. If the sequence changes, - // you may have to change routine GCHeapUtilities::SafeToRestartManagedThreads - // as well. + + Thread *pCurThread = GetThreadNULLOk(); + +#ifdef PROFILING_SUPPORTED + // Need to give resume event for the GC thread + { + BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends()); + if (pCurThread) + { + (&g_profControlBlock)->RuntimeThreadResumed((ThreadID)pCurThread); + } + END_PROFILER_CALLBACK(); + } +#endif // PROFILING_SUPPORTED + +#ifdef TIME_SUSPEND + DWORD startRelease = g_SuspendStatistics.GetTime(); +#endif + // - ThreadStore::TrapReturningThreads(FALSE); - g_pSuspensionThread = 0; + // Unlock the thread store. At this point, all threads should be allowed to run. + // + ThreadSuspend::UnlockThreadStore(); +#ifdef TIME_SUSPEND + g_SuspendStatistics.releaseTSL.Accumulate(SuspendStatistics::GetElapsed(startRelease, + g_SuspendStatistics.GetTime())); +#endif + +#ifdef PROFILING_SUPPORTED // - // Any threads that are waiting in WaitUntilGCComplete will continue now. + // This thread is logically "resuming" from a GC now. Tell the profiler. // - GCHeapUtilities::GetGCHeap()->SetWaitForGCEvent(); - _ASSERTE(IsGCSpecialThread() || ThreadStore::HoldingThreadStore()); + { + BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends()); + GCX_PREEMP(); + (&g_profControlBlock)->RuntimeResumeFinished(); + END_PROFILER_CALLBACK(); + } +#endif // PROFILING_SUPPORTED - ResumeRuntime(bFinishedGC, SuspendSucceeded); + // + // If we raised this thread's priority in SuspendRuntime, we restore it here. + // + if (pCurThread) + { + if (pCurThread->m_Priority != INVALID_THREAD_PRIORITY) + { + pCurThread->SetThreadPriority(pCurThread->m_Priority); + pCurThread->m_Priority = INVALID_THREAD_PRIORITY; + } + } FireEtwGCRestartEEEnd_V1(GetClrInstanceId()); @@ -5664,13 +5493,13 @@ void ThreadSuspend::RestartEE(BOOL bFinishedGC, BOOL SuspendSucceeded) // SuspendEE: // LockThreadStore // SetGCInProgress -// SuspendRuntime +// SuspendAllThreads // // ... perform the GC ... // // RestartEE: // SetGCDone -// ResumeRuntime +// ResumeAllThreads // calls UnlockThreadStore // // Note that this is intentionally *not* symmetrical. The EE will assert that the @@ -5724,24 +5553,6 @@ void ThreadSuspend::SuspendEE(SUSPEND_REASON reason) g_SuspendStatistics.GetTime())); #endif - // - // Now we're going to acquire an exclusive lock on managed code execution (including - // "manually managed" code in GCX_COOP regions). - // - // First, we reset the event that we're about to tell other threads to wait for. - // - GCHeapUtilities::GetGCHeap()->ResetWaitForGCEvent(); - - // - // Remember that we're the one suspending the EE - // - g_pSuspensionThread = pCurThread; - - // - // Tell all threads, globally, to wait for WaitForGCEvent. - // - ThreadStore::TrapReturningThreads(TRUE); - // // Remember why we're doing this. // @@ -5759,13 +5570,84 @@ void ThreadSuspend::SuspendEE(SUSPEND_REASON reason) _ASSERTE(ThreadStore::HoldingThreadStore() || g_fProcessDetach); +#ifdef PROFILING_SUPPORTED + // If the profiler desires information about GCs, then let it know that one + // is starting. + { + BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends()); + _ASSERTE(reason != ThreadSuspend::SUSPEND_FOR_DEBUGGER); + _ASSERTE(reason != ThreadSuspend::SUSPEND_FOR_DEBUGGER_SWEEP); + + { + (&g_profControlBlock)->RuntimeSuspendStarted( + GCSuspendReasonToProfSuspendReason(reason)); + } + if (pCurThread) + { + // Notify the profiler that the thread that is actually doing the GC is 'suspended', + // meaning that it is doing stuff other than run the managed code it was before the + // GC started. + (&g_profControlBlock)->RuntimeThreadSuspended((ThreadID)pCurThread); + } + END_PROFILER_CALLBACK(); + } +#endif // PROFILING_SUPPORTED + + // + // If this thread is running at low priority, boost its priority. We remember the old + // priority so that we can restore it in ResumeEE. + // + if (pCurThread) // concurrent GC occurs on threads we don't know about + { + _ASSERTE(pCurThread->m_Priority == INVALID_THREAD_PRIORITY); + int priority = pCurThread->GetThreadPriority(); + if (priority < THREAD_PRIORITY_NORMAL) + { + pCurThread->m_Priority = priority; + pCurThread->SetThreadPriority(THREAD_PRIORITY_NORMAL); + } + } + // // Now that we've instructed all threads to please stop, // go interrupt the ones that are running managed code and force them to stop. // This does not return until all threads have acknowledged that they // will not run managed code. // - SuspendRuntime(reason); + SuspendAllThreads(); + +#ifdef PROFILING_SUPPORTED + // If a profiler is keeping track of GC events, notify it + { + BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends()); + (&g_profControlBlock)->RuntimeSuspendFinished(); + END_PROFILER_CALLBACK(); + } +#endif // PROFILING_SUPPORTED + +#ifdef _DEBUG + if (reason == ThreadSuspend::SUSPEND_FOR_GC) + { + Thread* thread = NULL; + while ((thread = ThreadStore::GetThreadList(thread)) != NULL) + { + thread->DisableStressHeap(); + } + } +#endif + +#ifdef HAVE_GCCOVER + // + // Now that the EE has been suspended, let's see if any oustanding + // gcstress instruction updates need to occur. Each thread can + // have only one pending at a time. + // + Thread* thread = NULL; + while ((thread = ThreadStore::GetThreadList(thread)) != NULL) + { + thread->CommitGCStressInstructionUpdate(); + } +#endif // HAVE_GCCOVER #ifdef DEBUGGING_SUPPORTED // If the debugging services are attached, then its possible @@ -5803,8 +5685,8 @@ void ThreadSuspend::SuspendEE(SUSPEND_REASON reason) LOG((LF_GCROOTS | LF_GC | LF_CORDB, LL_INFO10, "The EE is free now...\n")); - // If someone's trying to suspent *this* thread, this is a good opportunity. - if (pCurThread && pCurThread->CatchAtSafePointOpportunistic()) + // If someone's trying to suspend *this* thread, this is a good opportunity. + if (pCurThread && pCurThread->CatchAtSafePoint()) { pCurThread->PulseGCMode(); // Go suspend myself. } @@ -5826,32 +5708,31 @@ void ThreadSuspend::SuspendEE(SUSPEND_REASON reason) g_SuspendStatistics.EndSuspend(reason == SUSPEND_FOR_GC || reason == SUSPEND_FOR_GC_PREP); #endif //TIME_SUSPEND ThreadSuspend::s_fSuspended = true; - -#if defined(TARGET_ARM) || defined(TARGET_ARM64) - // Flush the store buffers on all CPUs, to ensure that all changes made so far are seen - // by the GC threads. This only matters on weak memory ordered processors as - // the strong memory ordered processors wouldn't have reordered the relevant writes. - // This is needed to synchronize threads that were running in preemptive mode thus were - // left alone by suspension to flush their writes that they made before they switched to - // preemptive mode. - ::FlushProcessWriteBuffers(); -#endif //TARGET_ARM || TARGET_ARM64 } #ifdef FEATURE_THREAD_ACTIVATION // This function is called by a thread activation to check if the specified instruction pointer // is in a function where we can safely handle an activation. -BOOL CheckActivationSafePoint(SIZE_T ip, BOOL checkingCurrentThread) +// WARNING: This method is called by suspension while one thread is interrupted +// in a random location, possibly holding random locks. +// It is unsafe to use blocking APIs or allocate in this method. +BOOL CheckActivationSafePoint(SIZE_T ip) { Thread *pThread = GetThreadNULLOk(); - // It is safe to call the ExecutionManager::IsManagedCode only if we are making the check for - // a thread different from the current one or if the current thread is in the cooperative mode. - // Otherwise ExecutionManager::IsManagedCode could deadlock if the activation happened when the - // thread was holding the ExecutionManager's writer lock. - // When the thread is in preemptive mode, we know for sure that it is not executing managed code. - BOOL checkForManagedCode = !checkingCurrentThread || (pThread != NULL && pThread->PreemptiveGCDisabled()); - return checkForManagedCode && ExecutionManager::IsManagedCode(ip); + + // The criteria for safe activation is to be running managed code. + // Also we are not interested in handling interruption if we are already in preemptive mode. + BOOL isActivationSafePoint = pThread != NULL && + pThread->PreemptiveGCDisabled() && + ExecutionManager::IsManagedCode(ip); + + if (!isActivationSafePoint) + { + pThread->m_hasPendingActivation = false; + } + + return isActivationSafePoint; } // This function is called when thread suspension is pending. It tries to ensure that the current @@ -5871,6 +5752,14 @@ BOOL CheckActivationSafePoint(SIZE_T ip, BOOL checkingCurrentThread) // void HandleSuspensionForInterruptedThread(CONTEXT *interruptedContext) { + struct AutoClearPendingThreadActivation + { + ~AutoClearPendingThreadActivation() + { + GetThread()->m_hasPendingActivation = false; + } + } autoClearPendingThreadActivation; + Thread *pThread = GetThread(); if (pThread->PreemptiveGCDisabled() != TRUE) @@ -5880,7 +5769,7 @@ void HandleSuspensionForInterruptedThread(CONTEXT *interruptedContext) // This function can only be called when the interrupted thread is in // an activation safe point. - _ASSERTE(CheckActivationSafePoint(ip, /* checkingCurrentThread */ TRUE)); + _ASSERTE(CheckActivationSafePoint(ip)); Thread::WorkingOnThreadContextHolder workingOnThreadContext(pThread); if (!workingOnThreadContext.Acquired()) @@ -5984,15 +5873,7 @@ void Thread::ApcActivationCallback(ULONG_PTR Parameter) ActivationReason reason = (ActivationReason)pData->Parameter; PCONTEXT pContext = pData->ContextRecord; - struct AutoClearPendingThreadActivation - { - ~AutoClearPendingThreadActivation() - { - GetThread()->m_hasPendingActivation = false; - } - } autoClearPendingThreadActivation; - - if (!CheckActivationSafePoint(GetIP(pContext), true /* checkingCurrentThread */)) + if (!CheckActivationSafePoint(GetIP(pContext))) { return; } @@ -6013,15 +5894,17 @@ void Thread::ApcActivationCallback(ULONG_PTR Parameter) bool Thread::InjectActivation(ActivationReason reason) { -#ifdef FEATURE_SPECIAL_USER_MODE_APC - _ASSERTE(UseSpecialUserModeApc()); - + // Try to avoid sending signals/APCs when another one is in progress, + // as they may interrupt one another or queue up. + // Just one at a time is enough. More is not better here. if (m_hasPendingActivation) { - // Try to avoid nesting special user-mode APCs, as they can interrupt one another return true; } +#ifdef FEATURE_SPECIAL_USER_MODE_APC + _ASSERTE(UseSpecialUserModeApc()); + HANDLE hThread = GetThreadHandle(); if (hThread == INVALID_HANDLE_VALUE) { @@ -6041,12 +5924,15 @@ bool Thread::InjectActivation(ActivationReason reason) _ASSERTE((reason == ActivationReason::SuspendForGC) || (reason == ActivationReason::ThreadAbort) || (reason == ActivationReason::SuspendForDebugger)); static ConfigDWORD injectionEnabled; - if (injectionEnabled.val(CLRConfig::INTERNAL_ThreadSuspendInjection) == 0) - return false; - - HANDLE hThread = GetThreadHandle(); - if (hThread != INVALID_HANDLE_VALUE) - return ::PAL_InjectActivation(hThread); + if (injectionEnabled.val(CLRConfig::INTERNAL_ThreadSuspendInjection) != 0) + { + HANDLE hThread = GetThreadHandle(); + if (hThread != INVALID_HANDLE_VALUE) + { + m_hasPendingActivation = true; + return ::PAL_InjectActivation(hThread); + } + } return false; #else @@ -6062,22 +5948,26 @@ void ThreadSuspend::Initialize() #ifdef FEATURE_HIJACK #if defined(TARGET_UNIX) ::PAL_SetActivationFunction(HandleSuspensionForInterruptedThread, CheckActivationSafePoint); -#elif defined(TARGET_WINDOWS) && defined(TARGET_AMD64) - // Only versions of Windows that have the special user mode APC have a correct implementation of the return address hijack handling - if (Thread::UseSpecialUserModeApc()) +#elif defined(TARGET_WINDOWS) + if (Thread::AreShadowStacksEnabled()) { HMODULE hModNtdll = WszLoadLibrary(W("ntdll.dll")); if (hModNtdll != NULL) { - typedef ULONG_PTR (NTAPI *PFN_RtlGetReturnAddressHijackTarget)(); - PFN_RtlGetReturnAddressHijackTarget pfnRtlGetReturnAddressHijackTarget = (PFN_RtlGetReturnAddressHijackTarget)GetProcAddress(hModNtdll, "RtlGetReturnAddressHijackTarget"); - if (pfnRtlGetReturnAddressHijackTarget != NULL) + typedef void* (*PFN_RtlGetReturnAddressHijackTarget)(void); + + void* rtlGetReturnAddressHijackTarget = GetProcAddress(hModNtdll, "RtlGetReturnAddressHijackTarget"); + if (rtlGetReturnAddressHijackTarget != NULL) { - g_returnAddressHijackTarget = (void*)pfnRtlGetReturnAddressHijackTarget(); + g_returnAddressHijackTarget = ((PFN_RtlGetReturnAddressHijackTarget)rtlGetReturnAddressHijackTarget)(); } } + if (g_returnAddressHijackTarget == NULL) + { + _ASSERTE_ALL_BUILDS(!"RtlGetReturnAddressHijackTarget must provide a target when shadow stacks are enabled"); + } } -#endif // TARGET_WINDOWS && TARGET_AMD64 +#endif // TARGET_WINDOWS #endif // FEATURE_HIJACK } @@ -6284,7 +6174,6 @@ void SuspendStatistics::DisplayAndUpdate() releaseTSL.DisplayAndUpdate(logFile, "Unlock ", &g_LastSuspendStatistics.releaseTSL, cntSuspends, g_LastSuspendStatistics.cntSuspends); osSuspend.DisplayAndUpdate (logFile, "OS Susp", &g_LastSuspendStatistics.osSuspend, cntOSSuspendResume, g_LastSuspendStatistics.cntOSSuspendResume); crawl.DisplayAndUpdate (logFile, "Crawl", &g_LastSuspendStatistics.crawl, cntHijackCrawl, g_LastSuspendStatistics.cntHijackCrawl); - wait.DisplayAndUpdate (logFile, "Wait", &g_LastSuspendStatistics.wait, cntWaits, g_LastSuspendStatistics.cntWaits); fprintf(logFile, "OS Suspend Failures %d (%d), Wait Timeouts %d (%d), Hijack traps %d (%d)\n", cntFailedSuspends - g_LastSuspendStatistics.cntFailedSuspends, cntFailedSuspends, diff --git a/src/coreclr/vm/threadsuspend.h b/src/coreclr/vm/threadsuspend.h index 6d034b91a199..0b27c77bfd2c 100644 --- a/src/coreclr/vm/threadsuspend.h +++ b/src/coreclr/vm/threadsuspend.h @@ -108,9 +108,6 @@ struct SuspendStatistics /////////////////////////////////////////////////////////////////////////////////////////////// // There are some interesting events that are worth counting, because they show where the time is going: - // number of times we waited on g_pGCSuspendEvent while trying to suspend the EE - int cntWaits; - // and the number of times those Waits timed out rather than being signalled by a cooperating thread int cntWaitTimeouts; @@ -185,18 +182,17 @@ class ThreadSuspend private: static SUSPEND_REASON m_suspendReason; // This contains the reason why the runtime is suspended - static void SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason); - static void ResumeRuntime(BOOL bFinishedGC, BOOL SuspendSucceeded); + static void SuspendAllThreads(); + static void ResumeAllThreads(BOOL SuspendSucceeded); public: // Initialize thread suspension support static void Initialize(); private: - static CLREvent * g_pGCSuspendEvent; -#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) +#if defined(TARGET_WINDOWS) static void* g_returnAddressHijackTarget; -#endif // TARGET_WINDOWS && TARGET_AMD64 +#endif // TARGET_WINDOWS // This is true iff we're currently in the process of suspending threads. Once the // threads have been suspended, this is false. This is set via an instance of @@ -251,12 +247,12 @@ class ThreadSuspend return g_pSuspensionThread; } -#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) +#if defined(TARGET_WINDOWS) static void* GetReturnAddressHijackTarget() { return g_returnAddressHijackTarget; } -#endif // TARGET_WINDOWS && TARGET_AMD64 +#endif // TARGET_WINDOWS private: static LONG m_DebugWillSyncCount; diff --git a/src/coreclr/vm/tieredcompilation.cpp b/src/coreclr/vm/tieredcompilation.cpp index 586f1945f5bd..6160a7aaac6a 100644 --- a/src/coreclr/vm/tieredcompilation.cpp +++ b/src/coreclr/vm/tieredcompilation.cpp @@ -645,7 +645,7 @@ bool TieredCompilationManager::TryDeactivateTieringDelay() } PCODE codeEntryPoint = activeCodeVersion.GetNativeCode(); - if (codeEntryPoint == NULL) + if (codeEntryPoint == (PCODE)NULL) { // The active IL/native code version has changed since the method was queued, and the currently active version // doesn't have a code entry point yet @@ -944,7 +944,7 @@ BOOL TieredCompilationManager::CompileCodeVersion(NativeCodeVersion nativeCodeVe { STANDARD_VM_CONTRACT; - PCODE pCode = NULL; + PCODE pCode = (PCODE)NULL; MethodDesc* pMethod = nativeCodeVersion.GetMethodDesc(); EX_TRY { @@ -968,7 +968,7 @@ BOOL TieredCompilationManager::CompileCodeVersion(NativeCodeVersion nativeCodeVe // point. // TODO: In the future, we should get some feedback from images containing pregenerated code and from tier 0 JIT // indicating that the method would not benefit from a rejit and avoid the rejit altogether. - pCode = NULL; + pCode = (PCODE)NULL; } } EX_CATCH @@ -979,7 +979,7 @@ BOOL TieredCompilationManager::CompileCodeVersion(NativeCodeVersion nativeCodeVe } EX_END_CATCH(RethrowTerminalExceptions) - return pCode != NULL; + return pCode != (PCODE)NULL; } // Updates the MethodDesc and precode so that future invocations of a method will diff --git a/src/coreclr/vm/typedesc.cpp b/src/coreclr/vm/typedesc.cpp index 72bc9e50c29b..d920e7864fbc 100644 --- a/src/coreclr/vm/typedesc.cpp +++ b/src/coreclr/vm/typedesc.cpp @@ -509,7 +509,7 @@ TypeHandle TypeDesc::GetParent() { #ifndef DACCESS_COMPILE -OBJECTREF ParamTypeDesc::GetManagedClassObject() +OBJECTREF TypeDesc::GetManagedClassObject() { CONTRACTL { THROWS; @@ -517,39 +517,10 @@ OBJECTREF ParamTypeDesc::GetManagedClassObject() MODE_COOPERATIVE; INJECT_FAULT(COMPlusThrowOM()); - - PRECONDITION(GetInternalCorElementType() == ELEMENT_TYPE_ARRAY || - GetInternalCorElementType() == ELEMENT_TYPE_SZARRAY || - GetInternalCorElementType() == ELEMENT_TYPE_BYREF || - GetInternalCorElementType() == ELEMENT_TYPE_PTR); } CONTRACTL_END; - if (m_hExposedClassObject == NULL) - { - TypeHandle(this).AllocateManagedClassObject(&m_hExposedClassObject); - } - return GetManagedClassObjectIfExists(); -} - -#endif // #ifndef DACCESS_COMPILE - -#ifndef DACCESS_COMPILE - -OBJECTREF FnPtrTypeDesc::GetManagedClassObject() -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - - INJECT_FAULT(COMPlusThrowOM()); - - PRECONDITION(GetInternalCorElementType() == ELEMENT_TYPE_FNPTR); - } - CONTRACTL_END; - - if (m_hExposedClassObject == NULL) + if (m_hExposedClassObject == 0) { TypeHandle(this).AllocateManagedClassObject(&m_hExposedClassObject); } @@ -1616,26 +1587,6 @@ BOOL TypeVarTypeDesc::SatisfiesConstraints(SigTypeContext *pTypeContextOfConstra return TRUE; } -OBJECTREF TypeVarTypeDesc::GetManagedClassObject() -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - - INJECT_FAULT(COMPlusThrowOM()); - - PRECONDITION(IsGenericVariable()); - } - CONTRACTL_END; - - if (m_hExposedClassObject == NULL) - { - TypeHandle(this).AllocateManagedClassObject(&m_hExposedClassObject); - } - return GetManagedClassObjectIfExists(); -} - #endif //!DACCESS_COMPILE TypeHandle * diff --git a/src/coreclr/vm/typedesc.h b/src/coreclr/vm/typedesc.h index f5c04af41afb..94f7e99517cc 100644 --- a/src/coreclr/vm/typedesc.h +++ b/src/coreclr/vm/typedesc.h @@ -163,6 +163,25 @@ class TypeDesc BOOL ContainsGenericVariables(BOOL methodOnly); +#ifndef DACCESS_COMPILE + OBJECTREF GetManagedClassObject(); + + OBJECTREF GetManagedClassObjectIfExists() const + { + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_COOPERATIVE; + } + CONTRACTL_END; + + const RUNTIMETYPEHANDLE handle = m_hExposedClassObject; + OBJECTREF retVal = ObjectToOBJECTREF(handle); + return retVal; + } +#endif + protected: // See methodtable.h for details of the flags with the same name there enum @@ -182,6 +201,9 @@ class TypeDesc // The remaining bits are available for flags // DWORD m_typeAndFlags; + + // internal RuntimeType object handle + RUNTIMETYPEHANDLE m_hExposedClassObject; }; @@ -200,7 +222,7 @@ class ParamTypeDesc : public TypeDesc { public: #ifndef DACCESS_COMPILE ParamTypeDesc(CorElementType type, TypeHandle arg) - : TypeDesc(type), m_Arg(arg), m_hExposedClassObject(0) { + : TypeDesc(type), m_Arg(arg) { LIMITED_METHOD_CONTRACT; @@ -219,46 +241,6 @@ class ParamTypeDesc : public TypeDesc { INDEBUGIMPL(BOOL Verify();) -#ifndef DACCESS_COMPILE - OBJECTREF GetManagedClassObject(); - - OBJECTREF GetManagedClassObjectIfExists() - { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_COOPERATIVE; - } - CONTRACTL_END; - - const RUNTIMETYPEHANDLE handle = m_hExposedClassObject; - - OBJECTREF retVal; - if (!TypeHandle::GetManagedClassObjectFromHandleFast(handle, &retVal) && - !GetLoaderAllocator()->GetHandleValueFastPhase2(handle, &retVal)) - { - return NULL; - } - - COMPILER_ASSUME(retVal != NULL); - return retVal; - } - - OBJECTREF GetManagedClassObjectFast() - { - LIMITED_METHOD_CONTRACT; - - OBJECTREF objRef; - if (!TypeHandle::GetManagedClassObjectFromHandleFast(m_hExposedClassObject, &objRef)) - { - return FALSE; - } - COMPILER_ASSUME(objRef != NULL); - return objRef; - } -#endif - TypeHandle GetModifiedType() { LIMITED_METHOD_CONTRACT; @@ -283,10 +265,6 @@ class ParamTypeDesc : public TypeDesc { // The type that is being modified TypeHandle m_Arg; - - // Non-unloadable context: internal RuntimeType object handle - // Unloadable context: slot index in LoaderAllocator's pinned table - RUNTIMETYPEHANDLE m_hExposedClassObject; }; /*************************************************************************/ @@ -319,7 +297,6 @@ class TypeVarTypeDesc : public TypeDesc m_typeOrMethodDef = typeOrMethodDef; m_token = token; m_index = index; - m_hExposedClassObject = 0; m_constraints = NULL; m_numConstraints = (DWORD)-1; } @@ -357,45 +334,6 @@ class TypeVarTypeDesc : public TypeDesc return m_typeOrMethodDef; } -#ifndef DACCESS_COMPILE - OBJECTREF GetManagedClassObject(); - OBJECTREF GetManagedClassObjectIfExists() - { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_COOPERATIVE; - } - CONTRACTL_END; - - const RUNTIMETYPEHANDLE handle = m_hExposedClassObject; - - OBJECTREF retVal; - if (!TypeHandle::GetManagedClassObjectFromHandleFast(handle, &retVal) && - !GetLoaderAllocator()->GetHandleValueFastPhase2(handle, &retVal)) - { - return NULL; - } - - COMPILER_ASSUME(retVal != NULL); - return retVal; - } - - OBJECTREF GetManagedClassObjectFast() - { - LIMITED_METHOD_CONTRACT; - - OBJECTREF objRef; - if (!TypeHandle::GetManagedClassObjectFromHandleFast(m_hExposedClassObject, &objRef)) - { - return FALSE; - } - COMPILER_ASSUME(objRef != NULL); - return objRef; - } -#endif - // Load the owning type. Note that the result is not guaranteed to be full loaded MethodDesc * LoadOwnerMethod(); TypeHandle LoadOwnerType(); @@ -440,10 +378,6 @@ class TypeVarTypeDesc : public TypeDesc Volatile m_numConstraints; // -1 until number has been determined PTR_TypeHandle m_constraints; - // Non-unloadable context: internal RuntimeType object handle - // Unloadable context: slot index in LoaderAllocator's pinned table - RUNTIMETYPEHANDLE m_hExposedClassObject; - // token for GenericParam entry mdGenericParam m_token; @@ -526,51 +460,7 @@ class FnPtrTypeDesc : public TypeDesc void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); #endif //DACCESS_COMPILE -#ifndef DACCESS_COMPILE - OBJECTREF GetManagedClassObject(); - - OBJECTREF GetManagedClassObjectIfExists() - { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_COOPERATIVE; - } - CONTRACTL_END; - - const RUNTIMETYPEHANDLE handle = m_hExposedClassObject; - - OBJECTREF retVal; - if (!TypeHandle::GetManagedClassObjectFromHandleFast(handle, &retVal) && - !GetLoaderAllocator()->GetHandleValueFastPhase2(handle, &retVal)) - { - return NULL; - } - - COMPILER_ASSUME(retVal != NULL); - return retVal; - } - - OBJECTREF GetManagedClassObjectFast() - { - LIMITED_METHOD_CONTRACT; - - OBJECTREF objRef; - if (!TypeHandle::GetManagedClassObjectFromHandleFast(m_hExposedClassObject, &objRef)) - { - return FALSE; - } - COMPILER_ASSUME(objRef != NULL); - return objRef; - } -#endif - protected: - // Non-unloadable context: internal RuntimeType object handle - // Unloadable context: slot index in LoaderAllocator's pinned table - RUNTIMETYPEHANDLE m_hExposedClassObject; - // Number of arguments DWORD m_NumArgs; diff --git a/src/coreclr/vm/typehandle.cpp b/src/coreclr/vm/typehandle.cpp index 91c6013bb527..d53b17a27ed6 100644 --- a/src/coreclr/vm/typehandle.cpp +++ b/src/coreclr/vm/typehandle.cpp @@ -337,7 +337,7 @@ void TypeHandle::AllocateManagedClassObject(RUNTIMETYPEHANDLE* pDest) // Take a lock here since we don't want to allocate redundant objects which won't be collected CrstHolder exposedClassLock(AppDomain::GetMethodTableExposedClassObjectLock()); - if (VolatileLoad(pDest) == NULL) + if (VolatileLoad(pDest) == 0) { FrozenObjectHeapManager* foh = SystemDomain::GetFrozenObjectHeapManager(); Object* obj = foh->TryAllocateObject(g_pRuntimeTypeClass, g_pRuntimeTypeClass->GetBaseSize()); @@ -347,8 +347,6 @@ void TypeHandle::AllocateManagedClassObject(RUNTIMETYPEHANDLE* pDest) refClass = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(obj); refClass->SetType(*this); RUNTIMETYPEHANDLE handle = (RUNTIMETYPEHANDLE)obj; - // Set the bit to 1 (we'll have to reset it before use) - handle |= 1; VolatileStore(pDest, handle); } } @@ -357,17 +355,8 @@ void TypeHandle::AllocateManagedClassObject(RUNTIMETYPEHANDLE* pDest) GCPROTECT_BEGIN(refClass); refClass = (REFLECTCLASSBASEREF)AllocateObject(g_pRuntimeTypeClass); refClass->SetKeepAlive(allocator->GetExposedObject()); - LOADERHANDLE exposedClassObjectHandle = allocator->AllocateHandle(refClass); - _ASSERTE((exposedClassObjectHandle & 1) == 0); refClass->SetType(*this); - - // Let all threads fight over who wins using InterlockedCompareExchange. - // Only the winner can set m_ExposedClassObject from NULL. - if (InterlockedCompareExchangeT(pDest, exposedClassObjectHandle, static_cast(NULL))) - { - // GC will collect unused instance - allocator->FreeHandle(exposedClassObjectHandle); - } + allocator->InsertObjectIntoFieldWithLifetimeOfCollectibleLoaderAllocator(refClass, (Object**)pDest); GCPROTECT_END(); } } @@ -1076,25 +1065,7 @@ OBJECTREF TypeHandle::GetManagedClassObject() const } else { - switch(GetInternalCorElementType()) - { - case ELEMENT_TYPE_ARRAY: - case ELEMENT_TYPE_SZARRAY: - case ELEMENT_TYPE_BYREF: - case ELEMENT_TYPE_PTR: - return ((ParamTypeDesc*)AsTypeDesc())->GetManagedClassObject(); - - case ELEMENT_TYPE_VAR: - case ELEMENT_TYPE_MVAR: - return ((TypeVarTypeDesc*)AsTypeDesc())->GetManagedClassObject(); - - case ELEMENT_TYPE_FNPTR: - return ((FnPtrTypeDesc*)AsTypeDesc())->GetManagedClassObject(); - - default: - _ASSERTE(!"Bad Element Type"); - return NULL; - } + return AsTypeDesc()->GetManagedClassObject(); } } diff --git a/src/coreclr/vm/typehandle.h b/src/coreclr/vm/typehandle.h index f0f5a4604ab2..1acecf307c84 100644 --- a/src/coreclr/vm/typehandle.h +++ b/src/coreclr/vm/typehandle.h @@ -331,22 +331,6 @@ class TypeHandle // so the direct reference will be stored to the pDest argument. In case of unloadable // context, an index to the pinned table will be saved. void AllocateManagedClassObject(RUNTIMETYPEHANDLE* pDest); - - FORCEINLINE static bool GetManagedClassObjectFromHandleFast(RUNTIMETYPEHANDLE handle, OBJECTREF* pRef) - { - LIMITED_METHOD_CONTRACT; - - // For a non-unloadable context, handle is expected to be either null (is not cached yet) - // or be a direct pointer to a frozen RuntimeType object - - if (handle & 1) - { - // Clear the "is pinned object" bit from the managed reference - *pRef = (OBJECTREF)(handle - 1); - return true; - } - return false; - } #endif // Similar to IsCanonicalSubtype, but applied to a vector. @@ -518,7 +502,7 @@ class TypeHandle #endif OBJECTREF GetManagedClassObject() const; - OBJECTREF GetManagedClassObjectFast() const; + OBJECTREF GetManagedClassObjectIfExists() const; static TypeHandle MergeArrayTypeHandlesToCommonParent( TypeHandle ta, TypeHandle tb); diff --git a/src/coreclr/vm/typehandle.inl b/src/coreclr/vm/typehandle.inl index dca823aff6d1..b64ff0109b14 100644 --- a/src/coreclr/vm/typehandle.inl +++ b/src/coreclr/vm/typehandle.inl @@ -233,7 +233,7 @@ inline void TypeHandle::ForEachComponentMethodTable(T &callback) const } #ifndef DACCESS_COMPILE -FORCEINLINE OBJECTREF TypeHandle::GetManagedClassObjectFast() const +FORCEINLINE OBJECTREF TypeHandle::GetManagedClassObjectIfExists() const { CONTRACTL { @@ -252,26 +252,7 @@ FORCEINLINE OBJECTREF TypeHandle::GetManagedClassObjectFast() const } else { - switch (AsTypeDesc()->GetInternalCorElementType()) - { - case ELEMENT_TYPE_BYREF: - case ELEMENT_TYPE_PTR: - o = dac_cast(AsTypeDesc())->GetManagedClassObjectFast(); - break; - - case ELEMENT_TYPE_VAR: - case ELEMENT_TYPE_MVAR: - o = dac_cast(AsTypeDesc())->GetManagedClassObjectFast(); - break; - - case ELEMENT_TYPE_FNPTR: - o = dac_cast(AsTypeDesc())->GetManagedClassObjectFast(); - break; - - default: - _ASSERTE(!"Bad Element Type"); - return NULL; - } + return AsTypeDesc()->GetManagedClassObjectIfExists(); } return o; diff --git a/src/coreclr/vm/typeparse.cpp b/src/coreclr/vm/typeparse.cpp index 3f6acfafdf47..5a9947042928 100644 --- a/src/coreclr/vm/typeparse.cpp +++ b/src/coreclr/vm/typeparse.cpp @@ -31,7 +31,7 @@ static TypeHandle GetTypeHelper(LPCWSTR szTypeName, Assembly* pRequestingAssembl OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED); - PREPARE_NONVIRTUAL_CALLSITE(METHOD__TYPE_NAME_PARSER__GET_TYPE_HELPER); + PREPARE_NONVIRTUAL_CALLSITE(METHOD__TYPE_NAME_RESOLVER__GET_TYPE_HELPER); DECLARE_ARGHOLDER_ARRAY(args, 4); args[ARGNUM_0] = PTR_TO_ARGHOLDER(szTypeName); args[ARGNUM_1] = OBJECTREF_TO_ARGHOLDER(objRequestingAssembly); diff --git a/src/coreclr/vm/util.cpp b/src/coreclr/vm/util.cpp index 58dc2d28ee37..d03ecb732607 100644 --- a/src/coreclr/vm/util.cpp +++ b/src/coreclr/vm/util.cpp @@ -384,13 +384,13 @@ SIZE_T DereferenceByRefVar(SIZE_T addr) { STATIC_CONTRACT_WRAPPER; - SIZE_T result = NULL; + SIZE_T result = 0; #if defined(DACCESS_COMPILE) HRESULT hr = DacReadAll(addr, &result, sizeof(result), false); if (FAILED(hr)) { - result = NULL; + result = 0; } #else // !DACCESS_COMPILE @@ -1070,7 +1070,7 @@ BOOL JITNotifications::SetAllNotifications(TADDR clrModule,USHORT NType,BOOL *ch { JITNotification *pCurrent = m_jitTable + i; if (!pCurrent->IsFree() && - ((clrModule == NULL) || (pCurrent->clrModule == clrModule))&& + ((clrModule == (TADDR)NULL) || (pCurrent->clrModule == clrModule))&& pCurrent->state != NType) { pCurrent->state = NType; @@ -1102,7 +1102,7 @@ BOOL JITNotifications::SetNotification(TADDR clrModule, mdToken token, USHORT NT return FALSE; } - if (clrModule == NULL) + if (clrModule == (TADDR)NULL) { return FALSE; } @@ -1255,7 +1255,7 @@ BOOL UpdateOutOfProcTable(__GlobalPtr(pHostTable) == NULL) + if (dac_cast(pHostTable) == (TADDR)NULL) { // The table has not been initialized in the target. Allocate space for it and update the pointer // in the target so that we'll use this allocated memory from now on. Note that we never free this @@ -1492,14 +1492,14 @@ void DACNotifyExceptionHelper(TADDR *args, UINT argCount) DACRaiseException(args, argCount); - g_clrNotificationArguments[0] = NULL; + g_clrNotificationArguments[0] = 0; } } void InitializeClrNotifications() { g_clrNotificationCrst.Init(CrstClrNotification, CRST_UNSAFE_ANYMODE); - g_clrNotificationArguments[0] = NULL; + g_clrNotificationArguments[0] = 0; } // FIX IN BETA 2 diff --git a/src/coreclr/vm/util.hpp b/src/coreclr/vm/util.hpp index ef05074b186a..a025e86e0768 100644 --- a/src/coreclr/vm/util.hpp +++ b/src/coreclr/vm/util.hpp @@ -43,40 +43,40 @@ void * __cdecl _alloca(size_t); #pragma warning(disable:6255) #endif // _PREFAST_ -BOOL inline FitsInI1(__int64 val) +BOOL inline FitsInI1(int64_t val) { LIMITED_METHOD_DAC_CONTRACT; - return val == (__int64)(__int8)val; + return val == (int64_t)(int8_t)val; } -BOOL inline FitsInI2(__int64 val) +BOOL inline FitsInI2(int64_t val) { LIMITED_METHOD_CONTRACT; - return val == (__int64)(__int16)val; + return val == (int64_t)(int16_t)val; } -BOOL inline FitsInI4(__int64 val) +BOOL inline FitsInI4(int64_t val) { LIMITED_METHOD_DAC_CONTRACT; - return val == (__int64)(__int32)val; + return val == (int64_t)(int32_t)val; } -BOOL inline FitsInU1(unsigned __int64 val) +BOOL inline FitsInU1(uint64_t val) { LIMITED_METHOD_CONTRACT; - return val == (unsigned __int64)(unsigned __int8)val; + return val == (uint64_t)(uint8_t)val; } -BOOL inline FitsInU2(unsigned __int64 val) +BOOL inline FitsInU2(uint64_t val) { LIMITED_METHOD_CONTRACT; - return val == (unsigned __int64)(unsigned __int16)val; + return val == (uint64_t)(uint16_t)val; } -BOOL inline FitsInU4(unsigned __int64 val) +BOOL inline FitsInU4(uint64_t val) { LIMITED_METHOD_DAC_CONTRACT; - return val == (unsigned __int64)(unsigned __int32)val; + return val == (uint64_t)(uint32_t)val; } #if defined(DACCESS_COMPILE) @@ -542,7 +542,7 @@ FORCEINLINE void VoidFreeNativeLibrary(NATIVE_LIBRARY_HANDLE h) #endif } -typedef Wrapper, VoidFreeNativeLibrary, NULL> NativeLibraryHandleHolder; +typedef Wrapper, VoidFreeNativeLibrary, 0> NativeLibraryHandleHolder; extern thread_local size_t t_CantStopCount; @@ -587,7 +587,7 @@ struct JITNotification JITNotification() { SetFree(); } BOOL IsFree() { return state == CLRDATA_METHNOTIFY_NONE; } - void SetFree() { state = CLRDATA_METHNOTIFY_NONE; clrModule = NULL; methodToken = 0; } + void SetFree() { state = CLRDATA_METHNOTIFY_NONE; clrModule = 0; methodToken = 0; } void SetState(TADDR moduleIn, mdToken tokenIn, USHORT NType) { _ASSERTE(IsValidMethodCodeNotification(NType)); diff --git a/src/coreclr/vm/vars.cpp b/src/coreclr/vm/vars.cpp index f6a029539063..a5a92e1f115d 100644 --- a/src/coreclr/vm/vars.cpp +++ b/src/coreclr/vm/vars.cpp @@ -21,7 +21,7 @@ const char g_psBaseLibrary[] = CoreLibName_IL_A; const char g_psBaseLibraryName[] = CoreLibName_A; const char g_psBaseLibrarySatelliteAssemblyName[] = CoreLibSatelliteName_A; -Volatile g_TrapReturningThreads; +volatile int32_t g_TrapReturningThreads; #ifdef _DEBUG // next two variables are used to enforce an ASSERT in Thread::DbgFindThread diff --git a/src/coreclr/vm/vars.hpp b/src/coreclr/vm/vars.hpp index 51533187c8b6..3c5d82f73848 100644 --- a/src/coreclr/vm/vars.hpp +++ b/src/coreclr/vm/vars.hpp @@ -50,7 +50,7 @@ class RCWCleanupList; #endif // FEATURE_COMINTEROP typedef TADDR LOADERHANDLE; -typedef TADDR RUNTIMETYPEHANDLE; +typedef Object* RUNTIMETYPEHANDLE; #ifdef DACCESS_COMPILE void OBJECTHANDLE_EnumMemoryRegions(OBJECTHANDLE handle); @@ -163,6 +163,26 @@ class OBJECTREF { //------------------------------------------------------------- OBJECTREF& operator=(const OBJECTREF &objref); OBJECTREF& operator=(TADDR nul); + + // We use this delayed check to avoid ambiguous overload issues with TADDR + // on platforms where NULL is defined as anything other than a uintptr_t constant + // or nullptr_t exactly. + // Without this, any valid "null pointer constant" that is not directly either type + // will be implicitly convertible to both TADDR and std::nullptr_t, causing ambiguity. + // With this, this constructor (and all similarly declared operators) drop out of + // consideration when used with NULL (and not nullptr_t). + // With this workaround, we get identical behavior between the Checked OBJECTREF builds + // and the release builds. + template::value>::type> + OBJECTREF(T) + : OBJECTREF(TADDR(0)) + { + } + template::value>::type> + OBJECTREF& operator=(T) + { + return *this = TADDR(0); + } // allow explicit casts explicit OBJECTREF(Object *pObject); @@ -183,17 +203,8 @@ template class REF : public OBJECTREF { public: - - //------------------------------------------------------------- - // Default constructor, for non-initializing declarations: - // - // OBJECTREF or; - //------------------------------------------------------------- - REF() :OBJECTREF () - { - LIMITED_METHOD_CONTRACT; - // no op - } + REF() = default; + using OBJECTREF::OBJECTREF; //------------------------------------------------------------- // Copy constructor, for passing OBJECTREF's as function arguments. @@ -204,16 +215,6 @@ class REF : public OBJECTREF //no op } - - //------------------------------------------------------------- - // To allow NULL to be used as an OBJECTREF. - //------------------------------------------------------------- - REF(TADDR nul) : OBJECTREF (nul) - { - LIMITED_METHOD_CONTRACT; - // no op - } - explicit REF(T* pObject) : OBJECTREF(pObject) { LIMITED_METHOD_CONTRACT; @@ -294,7 +295,18 @@ class Module; // For [ g_TrapReturningThreads; +// g_TrapReturningThreads == 0 disables thread polling/traping. +// This allows to short-circuit further examining of thread states in the most +// common scenario - when we are not interested in trapping anything. +// +// The bit #1 is reserved for controlling thread suspension. +// Setting bit #1 allows to atomically indicate/check that EE suspension is in progress. +// There could be only one EE suspension in progress at a time. (it requires holding ThreadStore lock) +// . +// Other bits are used as a counter to enable thread trapping for other reasons, such as ThreadAbort. +// There could be several active reasons for thread trapping at a time, like aborting multiple threads, +// thus g_TrapReturningThreads value could be > 3. +extern "C" volatile int32_t g_TrapReturningThreads; #ifdef _DEBUG // next two variables are used to enforce an ASSERT in Thread::DbgFindThread diff --git a/src/coreclr/vm/virtualcallstub.cpp b/src/coreclr/vm/virtualcallstub.cpp index a87eac54f607..17bb48613440 100644 --- a/src/coreclr/vm/virtualcallstub.cpp +++ b/src/coreclr/vm/virtualcallstub.cpp @@ -769,9 +769,7 @@ void VirtualCallStubManager::InitStatic() VirtualCallStubManagerManager::InitStatic(); } -// Static shutdown code. -// At the moment, this doesn't do anything more than log statistics. -void VirtualCallStubManager::UninitStatic() +void VirtualCallStubManager::LogFinalStats() { CONTRACTL { @@ -1311,7 +1309,7 @@ PCODE VSD_ResolveWorker(TransitionBlock * pTransitionBlock, _ASSERTE(protectedObj != NULL); OBJECTREF pObj = *protectedObj; - PCODE target = NULL; + PCODE target = (PCODE)NULL; if (pObj == NULL) { pSDFrame->SetForNullReferenceException(); @@ -1349,7 +1347,7 @@ PCODE VSD_ResolveWorker(TransitionBlock * pTransitionBlock, MethodTable * pRepresentativeMT = pObj->GetMethodTable(); if (representativeToken.IsTypedToken()) { - pRepresentativeMT = CURRENT_THREAD->GetDomain()->LookupType(representativeToken.GetTypeID()); + pRepresentativeMT = AppDomain::GetCurrentDomain()->LookupType(representativeToken.GetTypeID()); CONSISTENCY_CHECK(CheckPointer(pRepresentativeMT)); } @@ -1506,7 +1504,7 @@ PCODE VirtualCallStubManager::ResolveWorker(StubCallSite* pCallSite, bCallToShorterLivedTarget ? "bCallToShorterLivedTarget" : "" )); PCODE stub = CALL_STUB_EMPTY_ENTRY; - PCODE target = NULL; + PCODE target = (PCODE)NULL; BOOL patch = FALSE; // This code can throw an OOM, but we do not want to fail in this case because @@ -1539,7 +1537,7 @@ PCODE VirtualCallStubManager::ResolveWorker(StubCallSite* pCallSite, ///////////////////////////////////////////////////////////////////////////////////// // Second see if we can find a ResolveCacheElem for this token and type. // If a match is found, use the target stored in the entry. - if (target == NULL) + if (target == (PCODE)NULL) { ResolveCacheElem * elem = NULL; ResolveCacheEntry entryRC; @@ -1564,7 +1562,7 @@ PCODE VirtualCallStubManager::ResolveWorker(StubCallSite* pCallSite, // If we failed to find a target in either the resolver or cache entry hash tables, // we need to perform a full resolution of the token and type. //@TODO: Would be nice to add assertion code to ensure we only ever call Resolver once per . - if (target == NULL) + if (target == (PCODE)NULL) { CONSISTENCY_CHECK(stub == CALL_STUB_EMPTY_ENTRY); patch = Resolver(objectType, token, protectedObj, &target, TRUE /* throwOnConflict */); @@ -1610,7 +1608,7 @@ PCODE VirtualCallStubManager::ResolveWorker(StubCallSite* pCallSite, DispatchCache::InsertKind insertKind = DispatchCache::IK_NONE; - if (target != NULL) + if (target != (PCODE)NULL) { if (patch) { @@ -1630,7 +1628,7 @@ PCODE VirtualCallStubManager::ResolveWorker(StubCallSite* pCallSite, // Only X86 implementation needs a BackPatch function pBackPatchFcn = (PCODE) GetEEFuncEntryPoint(BackPatchWorkerAsmStub); #else // !TARGET_X86 - pBackPatchFcn = NULL; + pBackPatchFcn = (PCODE)NULL; #endif // !TARGET_X86 #ifdef CHAIN_LOOKUP @@ -1886,7 +1884,7 @@ VirtualCallStubManager::Resolver( MethodDesc * dbg_pTokenMD = NULL; if (token.IsTypedToken()) { - dbg_pTokenMT = GetThread()->GetDomain()->LookupType(token.GetTypeID()); + dbg_pTokenMT = AppDomain::GetCurrentDomain()->LookupType(token.GetTypeID()); dbg_pTokenMD = dbg_pTokenMT->FindDispatchSlot(TYPE_ID_THIS_CLASS, token.GetSlotNumber(), throwOnConflict).GetMethodDesc(); } #endif // _DEBUG @@ -1932,7 +1930,7 @@ VirtualCallStubManager::Resolver( { // Skip fixup precode jump for better perf PCODE pDirectTarget = Precode::TryToSkipFixupPrecode(implSlot.GetTarget()); - if (pDirectTarget != NULL) + if (pDirectTarget != (PCODE)NULL) implSlot = DispatchSlot(pDirectTarget); // Only patch to a target if it's not going to call the prestub. @@ -2042,7 +2040,7 @@ VirtualCallStubManager::Resolver( MethodDesc * pTokenMD = NULL; if (token.IsTypedToken()) { - pTokenMT = GetThread()->GetDomain()->LookupType(token.GetTypeID()); + pTokenMT = AppDomain::GetCurrentDomain()->LookupType(token.GetTypeID()); pTokenMD = pTokenMT->FindDispatchSlot(TYPE_ID_THIS_CLASS, token.GetSlotNumber(), throwOnConflict).GetMethodDesc(); } @@ -2060,7 +2058,7 @@ VirtualCallStubManager::Resolver( if (!throwOnConflict) { // Assume we got null because there was a default interface method conflict - *ppTarget = NULL; + *ppTarget = (PCODE)NULL; return FALSE; } else @@ -2101,8 +2099,8 @@ BOOL VirtualCallStubManager::IsInterfaceToken(DispatchToken token) } CONTRACT_END; BOOL ret = token.IsTypedToken(); // For now, only interfaces have typed dispatch tokens. - CONSISTENCY_CHECK(!ret || CheckPointer(GetThread()->GetDomain()->LookupType(token.GetTypeID()))); - CONSISTENCY_CHECK(!ret || GetThread()->GetDomain()->LookupType(token.GetTypeID())->IsInterface()); + CONSISTENCY_CHECK(!ret || CheckPointer(AppDomain::GetCurrentDomain()->LookupType(token.GetTypeID()))); + CONSISTENCY_CHECK(!ret || AppDomain::GetCurrentDomain()->LookupType(token.GetTypeID())->IsInterface()); RETURN (ret); } @@ -2128,7 +2126,7 @@ VirtualCallStubManager::GetRepresentativeMethodDescFromToken( if (token.IsTypedToken()) { - pMT = GetThread()->GetDomain()->LookupType(token.GetTypeID()); + pMT = AppDomain::GetCurrentDomain()->LookupType(token.GetTypeID()); CONSISTENCY_CHECK(CheckPointer(pMT)); token = DispatchToken::CreateDispatchToken(token.GetSlotNumber()); } @@ -2143,7 +2141,7 @@ MethodTable *VirtualCallStubManager::GetTypeFromToken(DispatchToken token) NOTHROW; WRAPPER(GC_TRIGGERS); } CONTRACTL_END; - MethodTable *pMT = GetThread()->GetDomain()->LookupType(token.GetTypeID()); + MethodTable *pMT = AppDomain::GetCurrentDomain()->LookupType(token.GetTypeID()); _ASSERTE(pMT != NULL); _ASSERTE(pMT->LookupTypeID() == token.GetTypeID()); return pMT; @@ -2220,11 +2218,11 @@ VirtualCallStubManager::GetTarget( GCX_COOP(); // This is necessary for BucketTable synchronization - PCODE target = NULL; + PCODE target = (PCODE)NULL; #ifndef STUB_DISPATCH_PORTABLE target = CacheLookup(token.To_SIZE_T(), DispatchCache::INVALID_HASH, pMT); - if (target != NULL) + if (target != (PCODE)NULL) return target; #endif // !STUB_DISPATCH_PORTABLE @@ -3810,7 +3808,7 @@ MethodDesc *VirtualCallStubManagerManager::Entry2MethodDesc( // Do the full resolve DispatchToken token(VirtualCallStubManager::GetTokenFromStubQuick(pMgr, stubStartAddress, sk)); - PCODE target = NULL; + PCODE target = (PCODE)NULL; // TODO: passing NULL as protectedObj here can lead to incorrect behavior for ICastable objects // We need to review if this is the case and refactor this code if we want ICastable to become officially supported VirtualCallStubManager::Resolver(pMT, token, NULL, &target, TRUE /* throwOnConflict */); diff --git a/src/coreclr/vm/virtualcallstub.h b/src/coreclr/vm/virtualcallstub.h index 156353b6c186..da7583ecdab0 100644 --- a/src/coreclr/vm/virtualcallstub.h +++ b/src/coreclr/vm/virtualcallstub.h @@ -236,13 +236,13 @@ class VirtualCallStubManager : public StubManager // Set up static data structures - called during EEStartup static void InitStatic(); - static void UninitStatic(); + static void LogFinalStats(); // Per instance initialization - called during AppDomain::Init and ::Uninit and for collectible loader allocators void Init(BaseDomain* pDomain, LoaderAllocator *pLoaderAllocator); void Uninit(); - //@TODO: the logging should be tied into the VMs normal loggin mechanisms, + //@TODO: the logging should be tied into the VMs normal logging mechanisms, //@TODO: for now we just always write a short log file called "StubLog_.log" static void StartupLogging(); static void LoggingDump(); diff --git a/src/coreclr/vm/wrappers.h b/src/coreclr/vm/wrappers.h index 15be566391e8..ff032765684a 100644 --- a/src/coreclr/vm/wrappers.h +++ b/src/coreclr/vm/wrappers.h @@ -152,11 +152,11 @@ FORCEINLINE void VariantPtrRelease(VARIANT* value) } } -class VariantPtrHolder : public Wrapper +class VariantPtrHolder : public Wrapper { public: VariantPtrHolder(VARIANT* p = NULL) - : Wrapper(p) + : Wrapper(p) { LIMITED_METHOD_CONTRACT; } @@ -165,7 +165,7 @@ class VariantPtrHolder : public Wrapper::operator=(p); + Wrapper::operator=(p); } }; @@ -194,11 +194,11 @@ FORCEINLINE void SafeArrayPtrRelease(SAFEARRAY* value) } } -class SafeArrayPtrHolder : public Wrapper +class SafeArrayPtrHolder : public Wrapper { public: SafeArrayPtrHolder(SAFEARRAY* p = NULL) - : Wrapper(p) + : Wrapper(p) { LIMITED_METHOD_CONTRACT; } @@ -207,7 +207,7 @@ class SafeArrayPtrHolder : public Wrapper::operator=(p); + Wrapper::operator=(p); } }; @@ -230,11 +230,11 @@ FORCEINLINE void ZeroRelease(VOID* value) } } -class ZeroHolder : public Wrapper +class ZeroHolder : public Wrapper { public: ZeroHolder(VOID* p = NULL) - : Wrapper(p) + : Wrapper(p) { LIMITED_METHOD_CONTRACT; } @@ -243,7 +243,7 @@ class ZeroHolder : public Wrapper { WRAPPER_NO_CONTRACT; - Wrapper::operator=(p); + Wrapper::operator=(p); } }; diff --git a/src/installer/managed/Microsoft.NET.HostModel/Microsoft.NET.HostModel.csproj b/src/installer/managed/Microsoft.NET.HostModel/Microsoft.NET.HostModel.csproj index fec324d46ccc..55a33eb7e242 100644 --- a/src/installer/managed/Microsoft.NET.HostModel/Microsoft.NET.HostModel.csproj +++ b/src/installer/managed/Microsoft.NET.HostModel/Microsoft.NET.HostModel.csproj @@ -20,7 +20,7 @@ - + @@ -35,5 +35,3 @@ - - diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props index e1e1ef7c08ae..0de334e7ff21 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -234,6 +234,7 @@ + diff --git a/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-arm64.xml b/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-arm64.xml index 1b0dca06e409..2d501b307316 100644 --- a/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-arm64.xml +++ b/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-arm64.xml @@ -7,7 +7,7 @@ - + diff --git a/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-x64.xml b/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-x64.xml index 419795e0f348..538f475d5d58 100644 --- a/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-x64.xml +++ b/src/installer/pkg/sfx/bundle/shared-framework-distribution-template-x64.xml @@ -7,7 +7,7 @@ - + diff --git a/src/installer/pkg/snap/6.0/snapcraft.yaml b/src/installer/pkg/snap/6.0/snapcraft.yaml deleted file mode 100644 index c9c25e012149..000000000000 --- a/src/installer/pkg/snap/6.0/snapcraft.yaml +++ /dev/null @@ -1,43 +0,0 @@ -name: dotnet-runtime-60 -base: core18 -version: 6.0.16 -summary: Cross-Platform .NET Core Runtime. -description: | - .NET Core runtimes and libraries which are optimized for running .NET Core apps in production. See https://dot.net/core. - .NET Core is a general purpose development platform maintained by Microsoft. - -grade: stable -confinement: strict - -apps: - dotnet: - command: dotnet - plugs: - - network - - network-bind - - removable-media - - home - -slots: - dotnet-runtime: - content: dotnet-runtime-60 - interface: content - read: [/] - -parts: - dotnet-runtime: - plugin: dump - source: https://download.visualstudio.microsoft.com/download/pr/45395f1b-8928-41c5-9585-f01d949b2afb/0911c4025fffc0f51c3ab535695c6ca6/dotnet-runtime-6.0.16-linux-x64.tar.gz - source-checksum: sha512/c8891b791a51e7d2c3164470dfd2af2ce59af3c26404e84075277e307df7dcd1e3ccf1a1a3c2655fe2eea8a30f8349b7adbbe5de4cedfee52da06729a505d8f5 - stage-packages: - - libicu60 - - libssl1.0.0 - - libcurl3 - - libgssapi-krb5-2 - - liblttng-ust0 - - libstdc++6 - - zlib1g - - libgcc1 - - libtinfo5 - - libdb5.3 - - libc6 diff --git a/src/installer/pkg/snap/7.0/snapcraft.yaml b/src/installer/pkg/snap/7.0/snapcraft.yaml deleted file mode 100644 index 691b7886a88c..000000000000 --- a/src/installer/pkg/snap/7.0/snapcraft.yaml +++ /dev/null @@ -1,44 +0,0 @@ -name: dotnet-runtime-70 -base: core18 -version: 7.0.5 -summary: Cross-Platform .NET Core Runtime. -description: | - .NET Core runtimes and libraries which are optimized for running .NET Core apps in production. See https://dot.net/core. - .NET Core is a general purpose development platform maintained by Microsoft. - -grade: stable -confinement: strict - -apps: - dotnet: - command: dotnet - plugs: - - network - - network-bind - - removable-media - - home - -slots: - dotnet-runtime: - content: dotnet-runtime-70 - interface: content - read: [/] - -parts: - dotnet-runtime: - plugin: dump - source: https://download.visualstudio.microsoft.com/download/pr/e577f9c3-cf57-4f3c-aa2f-2c0c9ce7b9c2/16911adb0b0ac64ece205a8cf96a061d/dotnet-runtime-7.0.5-linux-x64.tar.gz - source-checksum: sha512/68014bdbf55bf455f59549c7d9d61ccc051e09fe74a975ca6b46d3269278d77c9cd167ba05760aef8ab413df4212f4f5cebdd1533779b49caf517eb4ec50cce5 - stage-packages: - - libicu60 - - libssl1.0.0 - - libcurl3 - - libgssapi-krb5-2 - - liblttng-ust0 - - libstdc++6 - - zlib1g - - libgcc1 - - libtinfo5 - - libdb5.3 - - libc6 - diff --git a/src/installer/pkg/snap/8.0/snapcraft.yaml b/src/installer/pkg/snap/8.0/snapcraft.yaml deleted file mode 100644 index 9668cb6a0a48..000000000000 --- a/src/installer/pkg/snap/8.0/snapcraft.yaml +++ /dev/null @@ -1,44 +0,0 @@ -name: dotnet-runtime-80 -base: core18 -version: 8.0.0-preview.3.23174.8 -summary: Cross-Platform .NET Core Runtime. -description: | - .NET Core runtimes and libraries which are optimized for running .NET Core apps in production. See https://dot.net/core. - .NET Core is a general purpose development platform maintained by Microsoft. - -grade: stable -confinement: strict - -apps: - dotnet: - command: dotnet - plugs: - - network - - network-bind - - removable-media - - home - -slots: - dotnet-runtime: - content: dotnet-runtime-80 - interface: content - read: [/] - -parts: - dotnet-runtime: - plugin: dump - source: https://download.visualstudio.microsoft.com/download/pr/6c4d4118-bc92-4601-b42b-2b6e91fc28f6/7b3a642aab860b394982d48bf5681243/dotnet-runtime-8.0.0-preview.3.23174.8-linux-x64.tar.gz - source-checksum: sha512/d0da20d48448c654ee548668a585b2272c661eb84ec6f845b3a49c0143ba1bfa83865f69da6bb607353a571e8c84b8e63650edf816641b1c5a55fa77a59e09be - stage-packages: - - libicu60 - - libssl1.0.0 - - libcurl3 - - libgssapi-krb5-2 - - liblttng-ust0 - - libstdc++6 - - zlib1g - - libgcc1 - - libtinfo5 - - libdb5.3 - - libc6 - diff --git a/src/installer/pkg/snap/snapcraft.yaml b/src/installer/pkg/snap/snapcraft.yaml deleted file mode 100644 index cf27a7455063..000000000000 --- a/src/installer/pkg/snap/snapcraft.yaml +++ /dev/null @@ -1,43 +0,0 @@ -name: dotnet-runtime-60 -base: core18 -version: 6.0.0-preview.2.21154.6 -summary: Cross-Platform .NET Core Runtime. -description: | - .NET Core runtimes and libraries which are optimized for running .NET Core apps in production. See https://dot.net/core. - .NET Core is a general purpose development platform maintained by Microsoft. - -grade: stable -confinement: strict - -apps: - dotnet: - command: dotnet - plugs: - - network - - network-bind - - removable-media - - home - -slots: - dotnet-runtime: - content: dotnet-runtime-60 - interface: content - read: [/] - -parts: - dotnet-runtime: - plugin: dump - source: https://download.visualstudio.microsoft.com/download/pr/2c88db43-4d92-433d-b95f-81bc9118a67e/08ec34f28dca0af4e8cf551299aa4367/dotnet-runtime-6.0.0-preview.2.21154.6-linux-x64.tar.gz - source-checksum: sha512/88ba8c4fe252fb76e0c40a4dcd2fe3e9c2960f445dd97a8044be9900f3641f18b2687ec10a36545a141a1e6820bb61278d2047cacd93365954a124c92463b17b - stage-packages: - - libicu60 - - libssl1.0.0 - - libcurl3 - - libgssapi-krb5-2 - - liblttng-ust0 - - libstdc++6 - - zlib1g - - libgcc1 - - libtinfo5 - - libdb5.3 - - libc6 \ No newline at end of file diff --git a/src/installer/prepare-artifacts.proj b/src/installer/prepare-artifacts.proj index 56249a2135c8..20b592d57580 100644 --- a/src/installer/prepare-artifacts.proj +++ b/src/installer/prepare-artifacts.proj @@ -58,8 +58,8 @@ - @@ -145,10 +145,6 @@ $(InstallersRelativePath)workloads/%(Filename)%(Extension) true - - - - diff --git a/src/installer/tests/Assets/Projects/HostApiInvokerApp/HostFXR.cs b/src/installer/tests/Assets/Projects/HostApiInvokerApp/HostFXR.cs index 3dc91d5ea69f..1a67e91e1d8c 100644 --- a/src/installer/tests/Assets/Projects/HostApiInvokerApp/HostFXR.cs +++ b/src/installer/tests/Assets/Projects/HostApiInvokerApp/HostFXR.cs @@ -8,7 +8,7 @@ namespace HostApiInvokerApp { - public static class HostFXR + public static unsafe class HostFXR { internal static class hostfxr { @@ -59,6 +59,34 @@ internal struct hostfxr_dotnet_environment_info internal IntPtr frameworks; } + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + internal struct hostfxr_framework_result + { + public nuint size; + public string name; + public string requested_version; + public string resolved_version; + public string resolved_path; + }; + + [StructLayout(LayoutKind.Sequential)] + internal struct hostfxr_resolve_frameworks_result + { + public nuint size; + public nuint resolved_count; + public IntPtr resolved_frameworks; + public nuint unresolved_count; + public IntPtr unresolved_frameworks; + }; + + [StructLayout(LayoutKind.Sequential)] + internal struct hostfxr_initialize_parameters + { + public nuint size; + public IntPtr host_path; + public IntPtr dotnet_root; + } + [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)] internal delegate void hostfxr_resolve_sdk2_result_fn( hostfxr_resolve_sdk2_result_key_t key, @@ -101,6 +129,18 @@ internal static extern int hostfxr_get_dotnet_environment_info( IntPtr reserved, hostfxr_get_dotnet_environment_info_result_fn result, IntPtr result_context); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void hostfxr_resolve_frameworks_result_fn( + IntPtr result, + IntPtr result_context); + + [DllImport(nameof(hostfxr), CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] + internal static extern int hostfxr_resolve_frameworks_for_runtime_config( + string runtime_config_path, + hostfxr_initialize_parameters* parameters, + hostfxr_resolve_frameworks_result_fn callback, + IntPtr result_context); } /// @@ -250,6 +290,85 @@ static void Test_hostfxr_get_dotnet_environment_info(string[] args) Console.WriteLine($"{api} framework paths:[{string.Join(";", frameworks.Select(f => f.path).ToList())}]"); } + /// + /// Test that invokes hostfxr_resolve_frameworks_for_runtime_config. + /// + /// Path to runtime config file + /// (Optional) Path to the directory with dotnet.exe + static unsafe void Test_hostfxr_resolve_frameworks_for_runtime_config(string[] args) + { + if (args.Length < 1) + throw new ArgumentException($"Invalid arguments. Expected: {nameof(hostfxr.hostfxr_resolve_frameworks_for_runtime_config)} []"); + + string runtimeConfigPath = args[0]; + string dotnetRoot = null; + if (args.Length >= 2) + dotnetRoot = args[1]; + + List resolved = new(); + List unresolved = new(); + + IntPtr resultContext = new IntPtr(123); + + hostfxr.hostfxr_resolve_frameworks_result_fn callback = (IntPtr resultPtr, IntPtr contextPtr) => + { + hostfxr.hostfxr_resolve_frameworks_result result = Marshal.PtrToStructure(resultPtr); + + if (result.size != (nuint)sizeof(hostfxr.hostfxr_resolve_frameworks_result)) + throw new Exception($"Unexpected {nameof(hostfxr.hostfxr_resolve_frameworks_result)}.size: {result.size}. Expected: {sizeof(hostfxr.hostfxr_resolve_frameworks_result)}."); + + if (contextPtr != resultContext) + throw new Exception($"Unexpected result_context value: {contextPtr}. Expected: {resultContext}."); + + for (int i = 0; i < (int)result.resolved_count; i++) + { + nint ptr = result.resolved_frameworks + i * Marshal.SizeOf(); + resolved.Add(Marshal.PtrToStructure(ptr)); + } + + for (int i = 0; i < (int)result.unresolved_count; i++) + { + nint ptr = result.unresolved_frameworks + i * Marshal.SizeOf(); + unresolved.Add(Marshal.PtrToStructure(ptr)); + } + }; + + int rc; + hostfxr.hostfxr_initialize_parameters parameters = new() + { + size = (nuint)sizeof(hostfxr.hostfxr_initialize_parameters), + host_path = IntPtr.Zero, + dotnet_root = dotnetRoot != null ? Marshal.StringToCoTaskMemAuto(dotnetRoot) : IntPtr.Zero + }; + try + { + rc = hostfxr.hostfxr_resolve_frameworks_for_runtime_config( + runtime_config_path: runtimeConfigPath, + parameters: ¶meters, + callback: callback, + result_context: resultContext); + } + finally + { + Marshal.FreeCoTaskMem(parameters.dotnet_root); + } + + string api = nameof(hostfxr.hostfxr_resolve_frameworks_for_runtime_config); + LogResult(api, rc); + + Console.WriteLine($"{api} resolved_count: {resolved.Count}"); + foreach (var framework in resolved) + { + Console.WriteLine($"{api} resolved_framework: name={framework.name}, version={framework.resolved_version}, path=[{framework.resolved_path}]"); + } + + Console.WriteLine($"{api} unresolved_count: {unresolved.Count}"); + foreach (var framework in unresolved) + { + Console.WriteLine($"{api} unresolved_framework: name={framework.name}, requested_version={framework.requested_version}, path=[{framework.resolved_path}]"); + } + } + private static void LogResult(string apiName, int rc) => Console.WriteLine(rc == 0 ? $"{apiName}:Success" : $"{apiName}:Fail[0x{rc:x}]"); @@ -269,6 +388,9 @@ public static bool RunTest(string apiToTest, string[] args) case nameof(hostfxr.hostfxr_get_dotnet_environment_info): Test_hostfxr_get_dotnet_environment_info(args); break; + case nameof(hostfxr.hostfxr_resolve_frameworks_for_runtime_config): + Test_hostfxr_resolve_frameworks_for_runtime_config(args); + break; default: return false; } diff --git a/src/installer/tests/Assets/Projects/HostApiInvokerApp/Program.cs b/src/installer/tests/Assets/Projects/HostApiInvokerApp/Program.cs index f14003995e6a..7f72753f7296 100644 --- a/src/installer/tests/Assets/Projects/HostApiInvokerApp/Program.cs +++ b/src/installer/tests/Assets/Projects/HostApiInvokerApp/Program.cs @@ -28,8 +28,12 @@ public static int Main(string[] args) public static void MainCore(string[] args) { - Console.WriteLine("Hello World!"); - Console.WriteLine(string.Join(Environment.NewLine, args)); + if (args.Length == 0) + throw new Exception($"{nameof(HostApiInvokerApp)} requires at least one argument specifying the API to test."); + + Console.WriteLine("Arguments:"); + foreach (string arg in args) + Console.WriteLine($" {arg}"); // If requested, test multilevel lookup using fake Global SDK directories: // 1. using a fake ProgramFiles location @@ -39,22 +43,30 @@ public static void MainCore(string[] args) string testMultilevelLookupProgramFiles = Environment.GetEnvironmentVariable("TEST_MULTILEVEL_LOOKUP_PROGRAM_FILES"); string testMultilevelLookupSelfRegistered = Environment.GetEnvironmentVariable("TEST_MULTILEVEL_LOOKUP_SELF_REGISTERED"); + string hostfxrPath; if (testMultilevelLookupProgramFiles != null && testMultilevelLookupSelfRegistered != null) { Environment.SetEnvironmentVariable("_DOTNET_TEST_GLOBALLY_REGISTERED_PATH", testMultilevelLookupSelfRegistered); Environment.SetEnvironmentVariable("ProgramFiles", testMultilevelLookupProgramFiles); Environment.SetEnvironmentVariable("ProgramFiles(x86)", testMultilevelLookupProgramFiles); Environment.SetEnvironmentVariable("DOTNET_MULTILEVEL_LOOKUP", "1"); + hostfxrPath = AppContext.GetData("HOSTFXR_PATH_TEST_BEHAVIOR") as string; } else { // never rely on machine state in test if we're not faking the multi-level lookup Environment.SetEnvironmentVariable("DOTNET_MULTILEVEL_LOOKUP", "0"); + hostfxrPath = AppContext.GetData("HOSTFXR_PATH") as string; } - if (args.Length == 0) + if (hostfxrPath is not null) { - throw new Exception("Invalid number of arguments passed"); + NativeLibrary.SetDllImportResolver(typeof(Program).Assembly, (libraryName, assembly, searchPath) => + { + return libraryName == nameof(HostFXR.hostfxr) + ? NativeLibrary.Load(libraryName, assembly, searchPath) + : default; + }); } string apiToTest = args[0]; diff --git a/src/installer/tests/HostActivation.Tests/NativeHostApis.cs b/src/installer/tests/HostActivation.Tests/NativeHostApis.cs index c865567ec23c..685d7e1404da 100644 --- a/src/installer/tests/HostActivation.Tests/NativeHostApis.cs +++ b/src/installer/tests/HostActivation.Tests/NativeHostApis.cs @@ -11,6 +11,14 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation { + internal class ApiNames + { + public const string hostfxr_get_available_sdks = nameof(hostfxr_get_available_sdks); + public const string hostfxr_resolve_sdk2 = nameof(hostfxr_resolve_sdk2); + public const string hostfxr_get_dotnet_environment_info = nameof(hostfxr_get_dotnet_environment_info); + public const string hostfxr_resolve_frameworks_for_runtime_config = nameof(hostfxr_resolve_frameworks_for_runtime_config); + } + public class NativeHostApis : IClassFixture { private SharedTestState sharedTestState; @@ -20,13 +28,6 @@ public NativeHostApis(SharedTestState fixture) sharedTestState = fixture; } - private class ApiNames - { - public const string hostfxr_get_available_sdks = nameof(hostfxr_get_available_sdks); - public const string hostfxr_resolve_sdk2 = nameof(hostfxr_resolve_sdk2); - public const string hostfxr_get_dotnet_environment_info = nameof(hostfxr_get_dotnet_environment_info); - } - internal sealed class SdkAndFrameworkFixture : IDisposable { private readonly TestArtifact _artifact; @@ -410,6 +411,316 @@ public void Hostfxr_get_dotnet_environment_info_reserved_is_not_nullptr_fails() .And.HaveStdErrContaining($"{api} received an invalid argument: reserved should be null."); } + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Hostfxr_resolve_frameworks_for_runtime_config(bool isMissing) + { + string api = ApiNames.hostfxr_resolve_frameworks_for_runtime_config; + using (TestArtifact artifact = TestArtifact.Create(api)) + { + (string Name, string Version) requested = ("Framework", "1.2.3"); + string configPath = Path.Combine(artifact.Location, "test.runtimeconfig.json"); + RuntimeConfig.FromFile(configPath) + .WithFramework(requested.Name, requested.Version) + .Save(); + + var builder = new DotNetBuilder(artifact.Location, TestContext.BuiltDotNet.BinPath, "dotnet"); + if (!isMissing) + builder.AddFramework(requested.Name, requested.Version, c => { }); + + DotNetCli dotnet = builder.Build(); + var result = TestContext.BuiltDotNet.Exec(sharedTestState.HostApiInvokerApp.AppDll, api, configPath, dotnet.BinPath) + .CaptureStdOut() + .CaptureStdErr() + .Execute(); + result.Should().Pass() + .And.NotHaveStdErr() + .And.ReturnStatusCode(api, isMissing ? Constants.ErrorCode.FrameworkMissingFailure : Constants.ErrorCode.Success); + if (isMissing) + { + result.Should().ReturnUnresolvedFramework(requested.Name, requested.Version); + } + else + { + result.Should().ReturnResolvedFramework(requested.Name, requested.Version, GetFrameworkPath(requested.Name, requested.Version, dotnet.BinPath)); + } + } + } + + [Fact] + public void Hostfxr_resolve_frameworks_for_runtime_config_SelfContained() + { + string api = ApiNames.hostfxr_resolve_frameworks_for_runtime_config; + using (TestArtifact artifact = TestArtifact.Create(api)) + { + (string Name, string Version)[] includedFrameworks = new[] { ("Framework", "1.0.0"), ("OtherFramework", "2.3.4"), ("Another", "5.6.7") }; + string configPath = Path.Combine(artifact.Location, "test.runtimeconfig.json"); + RuntimeConfig config = RuntimeConfig.FromFile(configPath); + foreach (var framework in includedFrameworks) + { + config.WithIncludedFramework(framework.Name, framework.Version); + } + + config.Save(); + + var result = TestContext.BuiltDotNet.Exec(sharedTestState.HostApiInvokerApp.AppDll, api, configPath) + .CaptureStdOut() + .CaptureStdErr() + .Execute(); + result.Should().Pass() + .And.NotHaveStdErr() + .And.ReturnStatusCode(api, Constants.ErrorCode.Success); + foreach (var framework in includedFrameworks) + { + // All frameworks included in a self-contained config are resolved to be next to the config + result.Should().ReturnResolvedFramework(framework.Name, framework.Version, artifact.Location); + } + } + } + + // This test only does basic validation the host API with roll-forward settings. Logic is shared for this API + // and framework resolution for running an app. More complex scenarios are covered in FrameworkResolution tests. + [Theory] + [InlineData(false, Constants.RollForwardSetting.Disable)] + [InlineData(false, Constants.RollForwardSetting.LatestPatch)] + [InlineData(false, Constants.RollForwardSetting.Minor)] + [InlineData(false, Constants.RollForwardSetting.LatestMinor)] + [InlineData(false, Constants.RollForwardSetting.Major)] + [InlineData(false, Constants.RollForwardSetting.LatestMajor)] + [InlineData(false, null)] // Default: Minor + [InlineData(true, Constants.RollForwardSetting.Disable)] + [InlineData(true, Constants.RollForwardSetting.LatestPatch)] + [InlineData(true, Constants.RollForwardSetting.Minor)] + [InlineData(true, Constants.RollForwardSetting.LatestMinor)] + [InlineData(true, Constants.RollForwardSetting.Major)] + [InlineData(true, Constants.RollForwardSetting.LatestMajor)] + [InlineData(true, null)] // Default: Minor + public void Hostfxr_resolve_frameworks_for_runtime_config_RollForward(bool isMissing, string rollForward) + { + string api = ApiNames.hostfxr_resolve_frameworks_for_runtime_config; + using (TestArtifact artifact = TestArtifact.Create(api)) + { + (string Name, string Version) requested = ("Framework", "1.2.3"); + string configPath = Path.Combine(artifact.Location, "test.runtimeconfig.json"); + RuntimeConfig.FromFile(configPath) + .WithFramework(requested.Name, requested.Version) + .WithRollForward(rollForward) + .Save(); + + // Use version that matches or doesn't based on roll-forward settings and expected result + Version requestedVersion = Version.Parse(requested.Version); + Version version = rollForward switch + { + Constants.RollForwardSetting.Disable + => isMissing + ? new (requestedVersion.Major, requestedVersion.Minor, requestedVersion.Build + 1) + : requestedVersion, + Constants.RollForwardSetting.LatestPatch + => isMissing + ? new (requestedVersion.Major, requestedVersion.Minor + 1, requestedVersion.Build) + : new (requestedVersion.Major, requestedVersion.Minor, requestedVersion.Build + 1), + Constants.RollForwardSetting.Minor or Constants.RollForwardSetting.LatestMinor or null + => isMissing + ? new (requestedVersion.Major + 1, requestedVersion.Minor, requestedVersion.Build) + : new (requestedVersion.Major, requestedVersion.Minor + 1, requestedVersion.Build), + Constants.RollForwardSetting.Major or Constants.RollForwardSetting.LatestMajor + => isMissing + ? new (requestedVersion.Major - 1, requestedVersion.Minor, requestedVersion.Build) + : new (requestedVersion.Major + 1, requestedVersion.Minor, requestedVersion.Build), + _ => throw new ArgumentException($"Invalid roll forward setting: {rollForward}") + }; + + string actualVersion = version.ToString(3); + DotNetCli dotnet = new DotNetBuilder(artifact.Location, TestContext.BuiltDotNet.BinPath, "dotnet") + .AddFramework(requested.Name, actualVersion, c => { }) + .Build(); + + var result = TestContext.BuiltDotNet.Exec(sharedTestState.HostApiInvokerApp.AppDll, api, configPath, dotnet.BinPath) + .CaptureStdOut() + .CaptureStdErr() + .Execute(); + result.Should().Pass() + .And.NotHaveStdErr() + .And.ReturnStatusCode(api, isMissing ? Constants.ErrorCode.FrameworkMissingFailure : Constants.ErrorCode.Success); + if (isMissing) + { + result.Should().ReturnUnresolvedFramework(requested.Name, requested.Version); + } + else + { + result.Should().ReturnResolvedFramework(requested.Name, actualVersion, GetFrameworkPath(requested.Name, actualVersion, dotnet.BinPath)); + } + } + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Hostfxr_resolve_frameworks_for_runtime_config_NoDotnetRoot(bool isMissing) + { + string api = ApiNames.hostfxr_resolve_frameworks_for_runtime_config; + using (TestArtifact artifact = TestArtifact.Create(api)) + { + string requestedVersion; + if (isMissing) + { + // Request a higher major framework version than the one available relative to the running hostfxr + Version existingVersion = Version.Parse(TestContext.MicrosoftNETCoreAppVersion.Contains('-') + ? TestContext.MicrosoftNETCoreAppVersion[..TestContext.MicrosoftNETCoreAppVersion.IndexOf('-')] + : TestContext.MicrosoftNETCoreAppVersion); + Version newerVersion = new Version(existingVersion.Major + 1, existingVersion.Minor, existingVersion.Build); + requestedVersion = newerVersion.ToString(3); + } + else + { + // Request the framework version that is available relative to the running hostfxr + requestedVersion = TestContext.MicrosoftNETCoreAppVersion; + } + + (string Name, string Version) requested = (Constants.MicrosoftNETCoreApp, requestedVersion); + + + string configPath = Path.Combine(artifact.Location, "test.runtimeconfig.json"); + RuntimeConfig.FromFile(configPath) + .WithFramework(requested.Name, requested.Version) + .Save(); + + // API should use the running hostfxr when dotnet root is not specified + var result = TestContext.BuiltDotNet.Exec(sharedTestState.HostApiInvokerApp.AppDll, api, configPath) + .CaptureStdOut() + .CaptureStdErr() + .Execute(); + result.Should().Pass() + .And.NotHaveStdErr() + .And.ReturnStatusCode(api, isMissing ? Constants.ErrorCode.FrameworkMissingFailure : Constants.ErrorCode.Success); + if (isMissing) + { + result.Should().ReturnUnresolvedFramework(requested.Name, requested.Version); + } + else + { + result.Should().ReturnResolvedFramework(requested.Name, requested.Version, GetFrameworkPath(requested.Name, requested.Version, TestContext.BuiltDotNet.BinPath)); + } + } + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Hostfxr_resolve_frameworks_for_runtime_config_MultipleFrameworks(bool isMissing) + { + string api = ApiNames.hostfxr_resolve_frameworks_for_runtime_config; + using (TestArtifact artifact = TestArtifact.Create(api)) + { + (string Name, string Version)[] requestedFrameworks = new[] { ("Framework", "1.0.0"), ("OtherFramework", "2.3.4"), ("Another", "5.6.7") }; + (string Name, string Version)[] expectedFrameworks = isMissing ? requestedFrameworks[..^1] : requestedFrameworks; + + string configPath = Path.Combine(artifact.Location, "test.runtimeconfig.json"); + RuntimeConfig config = RuntimeConfig.FromFile(configPath); + foreach (var framework in requestedFrameworks) + { + config.WithFramework(framework.Name, framework.Version); + } + + config.Save(); + + var builder = new DotNetBuilder(artifact.Location, TestContext.BuiltDotNet.BinPath, "dotnet"); + foreach (var framework in expectedFrameworks) + { + builder.AddFramework(framework.Name, framework.Version, c => { }); + } + + DotNetCli dotnet = builder.Build(); + + var result = TestContext.BuiltDotNet.Exec(sharedTestState.HostApiInvokerApp.AppDll, api, configPath, dotnet.BinPath) + .CaptureStdOut() + .CaptureStdErr() + .Execute(); + result.Should().Pass() + .And.NotHaveStdErr() + .And.ReturnStatusCode(api, isMissing ? Constants.ErrorCode.FrameworkMissingFailure : Constants.ErrorCode.Success); + foreach (var framework in expectedFrameworks) + { + result.Should().ReturnResolvedFramework(framework.Name, framework.Version, GetFrameworkPath(framework.Name, framework.Version, dotnet.BinPath)); + } + + if (isMissing) + { + var missingFramework = requestedFrameworks[^1]; + result.Should().ReturnUnresolvedFramework(missingFramework.Name, missingFramework.Version); + } + } + } + + [Fact] + public void Hostfxr_resolve_frameworks_for_runtime_config_IncompatibleFrameworks() + { + string api = ApiNames.hostfxr_resolve_frameworks_for_runtime_config; + using (TestArtifact artifact = TestArtifact.Create(api)) + { + (string Name, string Version) incompatibleLower = ("OtherFramework", "1.2.3"); + (string Name, string Version) incompatibleHigher = (incompatibleLower.Name, "2.0.0"); + (string Name, string Version)[] requested = new[] { ("Framework", "3.0.0"), incompatibleLower }; + + string configPath = Path.Combine(artifact.Location, "test.runtimeconfig.json"); + RuntimeConfig config = RuntimeConfig.FromFile(configPath); + foreach (var framework in requested) + { + config.WithFramework(framework.Name, framework.Version); + } + + config.Save(); + + var expectedFramework = requested[0]; + DotNetCli dotnet = new DotNetBuilder(artifact.Location, TestContext.BuiltDotNet.BinPath, "dotnet") + .AddFramework(expectedFramework.Name, expectedFramework.Version, + c => c.WithFramework(incompatibleHigher.Name, incompatibleHigher.Version)) + .Build(); + + TestContext.BuiltDotNet.Exec(sharedTestState.HostApiInvokerApp.AppDll, api, configPath, dotnet.BinPath) + .CaptureStdOut() + .CaptureStdErr() + .Execute() + .Should().Pass() + .And.NotHaveStdErr() + .And.ReturnStatusCode(api, Constants.ErrorCode.FrameworkCompatFailure) + .And.ReturnResolvedFramework(expectedFramework.Name, expectedFramework.Version, GetFrameworkPath(expectedFramework.Name, expectedFramework.Version, dotnet.BinPath)) + .And.ReturnUnresolvedFramework(incompatibleLower.Name, incompatibleLower.Version) + .And.ReturnUnresolvedFramework(incompatibleHigher.Name, incompatibleHigher.Version); + } + } + + [Fact] + public void Hostfxr_resolve_frameworks_for_runtime_config_InvalidConfig() + { + string api = ApiNames.hostfxr_resolve_frameworks_for_runtime_config; + using (TestArtifact artifact = TestArtifact.Create(api)) + { + (string Name, string Version) requested = ("Framework", "1.2.3"); + string configPath = Path.Combine(artifact.Location, "test.runtimeconfig.json"); + RuntimeConfig.FromFile(configPath) + .WithFramework(requested.Name, requested.Version) + .Save(); + + DotNetCli dotnet = new DotNetBuilder(artifact.Location, TestContext.BuiltDotNet.BinPath, "dotnet") + .AddFramework(requested.Name, requested.Version, c => { }) + .Build(); + + string frameworkPath = Path.Combine(dotnet.BinPath, "shared", requested.Name, requested.Version); + File.WriteAllText(Path.Combine(frameworkPath, $"{requested.Name}.runtimeconfig.json"), "{}"); + + TestContext.BuiltDotNet.Exec(sharedTestState.HostApiInvokerApp.AppDll, api, configPath, dotnet.BinPath) + .CaptureStdOut() + .CaptureStdErr() + .Execute() + .Should().Pass() + .And.NotHaveStdErr() + .And.ReturnStatusCode(api, Constants.ErrorCode.InvalidConfigFile) + .And.ReturnUnresolvedFramework(requested.Name, requested.Version, frameworkPath); + } + } + [Fact] public void Hostpolicy_corehost_set_error_writer_test() { @@ -443,6 +754,9 @@ public void HostRuntimeContract_bundle_probe() .And.HaveStdOutContaining("host_runtime_contract.bundle_probe is not set"); } + private static string GetFrameworkPath(string name, string version, string dotnetRoot) + => Path.Combine(dotnetRoot, "shared", name, version); + public class SharedTestState : IDisposable { public TestApp HostApiInvokerApp { get; } @@ -454,14 +768,6 @@ public class SharedTestState : IDisposable public SharedTestState() { - HostApiInvokerApp = TestApp.CreateFromBuiltAssets("HostApiInvokerApp"); - - if (!OperatingSystem.IsWindows()) - { - // On non-Windows, we can't just P/Invoke to already loaded hostfxr, so copy it next to the app dll. - File.Copy(Binaries.HostFxr.FilePath, Path.Combine(HostApiInvokerApp.Location, Binaries.HostFxr.FileName)); - } - // Make a copy of the built .NET, as we will enable test-only behaviour copiedDotnet = TestArtifact.CreateFromCopy(nameof(NativeHostApis), TestContext.BuiltDotNet.BinPath); TestBehaviorEnabledDotNet = new DotNetCli(copiedDotnet.Location); @@ -470,6 +776,14 @@ public SharedTestState() // as we just delete the entire copy after the tests run. _ = TestOnlyProductBehavior.Enable(TestBehaviorEnabledDotNet.GreatestVersionHostFxrFilePath); + HostApiInvokerApp = TestApp.CreateFromBuiltAssets("HostApiInvokerApp"); + + // On non-Windows, we can't just P/Invoke to already loaded hostfxr, so provide the app with + // paths to hostfxr so that it can handle resolving the library. + RuntimeConfig.FromFile(HostApiInvokerApp.RuntimeConfigJson) + .WithProperty("HOSTFXR_PATH", TestContext.BuiltDotNet.GreatestVersionHostFxrFilePath) + .WithProperty("HOSTFXR_PATH_TEST_BEHAVIOR", TestBehaviorEnabledDotNet.GreatestVersionHostFxrFilePath); + SdkAndFrameworkFixture = new SdkAndFrameworkFixture(); } @@ -490,5 +804,17 @@ public static AndConstraint ReturnStatusCode(this Comma ? assertion.HaveStdOutContaining($"{apiName}:Success") : assertion.HaveStdOutContaining($"{apiName}:Fail[0x{statusCode:x}]"); } + + public static AndConstraint ReturnResolvedFramework(this CommandResultAssertions assertion, string name, string version, string path) + { + string api = ApiNames.hostfxr_resolve_frameworks_for_runtime_config; + return assertion.HaveStdOutContaining($"{api} resolved_framework: name={name}, version={version}, path=[{path}]"); + } + public static AndConstraint ReturnUnresolvedFramework(this CommandResultAssertions assertion, string name, string version, string path = "") + { + string api = ApiNames.hostfxr_resolve_frameworks_for_runtime_config; + return assertion.HaveStdOutContaining($"{api} unresolved_framework: name={name}, requested_version={version}, path=[{path}]") + .And.NotHaveStdOutContaining($"{api} resolved_framework: name={name}"); + } } } diff --git a/src/installer/tests/TestUtils/Constants.cs b/src/installer/tests/TestUtils/Constants.cs index 2a5ce2f53f55..f79889dc17ae 100644 --- a/src/installer/tests/TestUtils/Constants.cs +++ b/src/installer/tests/TestUtils/Constants.cs @@ -119,8 +119,10 @@ public static class ErrorCode public const int ResolverInitFailure = unchecked((int)0x8000808b); public const int ResolverResolveFailure = unchecked((int)0x8000808c); public const int LibHostInvalidArgs = unchecked((int)0x80008092); + public const int InvalidConfigFile = unchecked((int)0x80008093); public const int AppArgNotRunnable = unchecked((int)0x80008094); public const int FrameworkMissingFailure = unchecked((int)0x80008096); + public const int FrameworkCompatFailure = unchecked((int)0x8000809c); public const int BundleExtractionFailure = unchecked((int)0x8000809f); public const int COMPlusException = unchecked((int)0xe0434352); diff --git a/src/libraries/Common/src/Extensions/ChangeCallbackRegistrar.cs b/src/libraries/Common/src/Extensions/ChangeCallbackRegistrar.cs index eecd1fa8c1e5..aa7899a64136 100644 --- a/src/libraries/Common/src/Extensions/ChangeCallbackRegistrar.cs +++ b/src/libraries/Common/src/Extensions/ChangeCallbackRegistrar.cs @@ -21,7 +21,7 @@ internal static class ChangeCallbackRegistrar /// The registration. internal static IDisposable UnsafeRegisterChangeCallback(Action callback, object? state, CancellationToken token, Action onFailure, T onFailureState) { -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 try { return token.UnsafeRegister(callback, state); diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.cs index e94a88249a1d..59e93080c562 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.cs @@ -56,6 +56,21 @@ internal static unsafe int EvpDigestCurrentXOF(SafeEvpMdCtxHandle ctx, Span destination) + { + _ = ctx; + _ = destination; + Debug.Fail("Should have validated that XOF is not supported before getting here."); + throw new UnreachableException(); + } + internal static readonly int EVP_MAX_MD_SIZE = GetMaxMdSize(); } } diff --git a/src/libraries/Common/src/Interop/Browser/Interop.Calendar.cs b/src/libraries/Common/src/Interop/Browser/Interop.Calendar.cs index 2a7b1d02ad21..73fbfa924d14 100644 --- a/src/libraries/Common/src/Interop/Browser/Interop.Calendar.cs +++ b/src/libraries/Common/src/Interop/Browser/Interop.Calendar.cs @@ -9,6 +9,6 @@ internal static partial class Interop internal static unsafe partial class JsGlobalization { [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int GetCalendarInfo(in string culture, CalendarId calendarId, char* buffer, int bufferLength, out int exceptionalResult, out object result); + internal static extern unsafe nint GetCalendarInfo(char* culture, int cultureLength, CalendarId calendarId, char* buffer, int bufferMaxLength, out int bufferLength); } } diff --git a/src/libraries/Common/src/Interop/Browser/Interop.CompareInfo.cs b/src/libraries/Common/src/Interop/Browser/Interop.CompareInfo.cs index cb7edf5b380a..638934edb416 100644 --- a/src/libraries/Common/src/Interop/Browser/Interop.CompareInfo.cs +++ b/src/libraries/Common/src/Interop/Browser/Interop.CompareInfo.cs @@ -8,15 +8,15 @@ internal static partial class Interop internal static unsafe partial class JsGlobalization { [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int CompareString(in string culture, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, out int exceptionalResult, out object result); + internal static extern unsafe nint CompareString(char* culture, int cultureLength, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, out int resultPtr); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe bool StartsWith(in string culture, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, out int exceptionalResult, out object result); + internal static extern unsafe nint StartsWith(char* culture, int cultureLength, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, out bool resultPtr); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe bool EndsWith(in string culture, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, out int exceptionalResult, out object result); + internal static extern unsafe nint EndsWith(char* culture, int cultureLength, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, out bool resultPtr); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int IndexOf(in string culture, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, bool fromBeginning, out int exceptionalResult, out object result); + internal static extern unsafe nint IndexOf(char* culture, int cultureLength, char* str1, int str1Len, char* str2, int str2Len, global::System.Globalization.CompareOptions options, bool fromBeginning, out int resultPtr); } } diff --git a/src/libraries/Common/src/Interop/Browser/Interop.Locale.cs b/src/libraries/Common/src/Interop/Browser/Interop.Locale.cs index b831e72e70cd..b2dc0db99c00 100644 --- a/src/libraries/Common/src/Interop/Browser/Interop.Locale.cs +++ b/src/libraries/Common/src/Interop/Browser/Interop.Locale.cs @@ -8,12 +8,12 @@ internal static partial class Interop internal static unsafe partial class JsGlobalization { [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int GetCultureInfo(in string culture, char* buffer, int bufferLength, out int exceptionalResult, out object result); + internal static extern unsafe nint GetCultureInfo(char* culture, int cultureLength, char* buffer, int bufferMaxLength, out int resultLength); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int GetFirstDayOfWeek(in string culture, out int exceptionalResult, out object result); + internal static extern unsafe nint GetFirstDayOfWeek(char* culture, int cultureLength, out int resultPtr); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int GetFirstWeekOfYear(in string culture, out int exceptionalResult, out object result); + internal static extern unsafe nint GetFirstWeekOfYear(char* culture, int cultureLength, out int resultPtr); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int GetLocaleInfo(in string locale, in string culture, char* buffer, int bufferLength, out int exceptionalResult, out object result); + internal static extern unsafe nint GetLocaleInfo(char* locale, int localeLength, char* culture, int cultureLength, char* buffer, int bufferLength, out int resultLength); } } diff --git a/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs b/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs index 518a4ff53bee..aa35d57828ee 100644 --- a/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs +++ b/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs @@ -69,6 +69,6 @@ internal static unsafe partial class Runtime [MethodImpl(MethodImplOptions.InternalCall)] public static extern void BindAssemblyExports(IntPtr assemblyNamePtr); [MethodImpl(MethodImplOptions.InternalCall)] - public static extern void GetAssemblyExport(IntPtr assemblyNamePtr, IntPtr namespacePtr, IntPtr classnamePtr, IntPtr methodNamePtr, IntPtr* monoMethodPtrPtr); + public static extern void GetAssemblyExport(IntPtr assemblyNamePtr, IntPtr namespacePtr, IntPtr classnamePtr, IntPtr methodNamePtr, int signatureHash, IntPtr* monoMethodPtrPtr); } } diff --git a/src/libraries/Common/src/Interop/Browser/Interop.TextInfo.cs b/src/libraries/Common/src/Interop/Browser/Interop.TextInfo.cs index ff157eb45f26..a10d2897f75b 100644 --- a/src/libraries/Common/src/Interop/Browser/Interop.TextInfo.cs +++ b/src/libraries/Common/src/Interop/Browser/Interop.TextInfo.cs @@ -8,8 +8,8 @@ internal static partial class Interop internal static unsafe partial class JsGlobalization { [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe void ChangeCaseInvariant(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper, out int exceptionalResult, out object result); + internal static extern unsafe nint ChangeCaseInvariant(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe void ChangeCase(in string culture, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper, out int exceptionalResult, out object result); + internal static extern unsafe nint ChangeCase(char* culture, int cultureLen, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper); } } diff --git a/src/libraries/Common/src/Interop/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Interop.Ldap.cs index 7fb63a1d3c5e..4020dd0fe89b 100644 --- a/src/libraries/Common/src/Interop/Interop.Ldap.cs +++ b/src/libraries/Common/src/Interop/Interop.Ldap.cs @@ -4,7 +4,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif using System.Security.Authentication; @@ -31,7 +31,7 @@ internal readonly struct Luid public int HighPart => _highPart; } -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #endif [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] @@ -49,7 +49,7 @@ internal struct SEC_WINNT_AUTH_IDENTITY_EX public string packageList; public int packageListLength; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(SEC_WINNT_AUTH_IDENTITY_EX), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] internal static class Marshaller { @@ -176,7 +176,7 @@ internal struct LDAP_TIMEVAL public int tv_usec; } -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(PinningMarshaller))] #endif [StructLayout(LayoutKind.Sequential)] @@ -185,7 +185,7 @@ internal sealed class BerVal public int bv_len; public IntPtr bv_val = IntPtr.Zero; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(BerVal), MarshalMode.ManagedToUnmanagedIn, typeof(PinningMarshaller))] internal static unsafe class PinningMarshaller { @@ -207,7 +207,7 @@ internal sealed class LdapControl public LdapControl() { } } -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #endif [StructLayout(LayoutKind.Sequential)] @@ -217,7 +217,7 @@ internal struct LdapReferralCallback public QUERYFORCONNECTIONInternal query; public NOTIFYOFNEWCONNECTIONInternal notify; public DEREFERENCECONNECTIONInternal dereference; -#if NET7_0_OR_GREATER +#if NET public static readonly unsafe int Size = sizeof(Marshaller.MarshalValue.Native); [CustomMarshaller(typeof(LdapReferralCallback), MarshalMode.ManagedToUnmanagedIn, typeof(MarshalValue))] diff --git a/src/libraries/Common/src/Interop/Interop.Odbc.cs b/src/libraries/Common/src/Interop/Interop.Odbc.cs index 250ef4371298..3e7518562620 100644 --- a/src/libraries/Common/src/Interop/Interop.Odbc.cs +++ b/src/libraries/Common/src/Interop/Interop.Odbc.cs @@ -5,7 +5,7 @@ using System.Data.Odbc; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif using System.Runtime.Versioning; @@ -38,7 +38,7 @@ internal static partial ODBC32.SQLRETURN SQLAllocHandle( /*SQLUSMALLINT*/ushort ColumnNumber, /*SQLSMALLINT*/ODBC32.SQL_C TargetType, /*SQLPOINTER*/ -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef TargetValue, @@ -64,13 +64,13 @@ internal static partial ODBC32.SQLRETURN SQLBindCol( /*SQLULEN*/IntPtr cbColDef, /*SQLSMALLINT*/IntPtr ibScale, /*SQLPOINTER*/ -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef rgbValue, /*SQLLEN*/IntPtr BufferLength, /*SQLLEN* */ -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef StrLen_or_Ind); @@ -326,7 +326,7 @@ internal static partial ODBC32.SQLRETURN SQLSetConnectAttrW( /*SQLSMALLINT*/short ColumnNumber, /*SQLSMALLINT*/ODBC32.SQL_DESC FieldIdentifier, /*SQLPOINTER*/ -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef CharacterAttribute, diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IOVector.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IOVector.cs index 9cbf1ee2c347..a55e2ca19f0e 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IOVector.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IOVector.cs @@ -2,11 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Runtime.InteropServices; internal static partial class Interop { internal static partial class Sys { + [StructLayout(LayoutKind.Sequential)] internal unsafe struct IOVector { public byte* Base; diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReceiveSocketError.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReceiveSocketError.cs new file mode 100644 index 000000000000..be4888bbfb74 --- /dev/null +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReceiveSocketError.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Net.Sockets; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + [LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReceiveSocketError")] + internal static unsafe partial SocketError ReceiveSocketError(SafeHandle socket, MessageHeader* messageHeader); + } +} diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs index 088ee79ab025..f9fd00f227f4 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs @@ -9,6 +9,9 @@ internal static partial class Interop { internal static partial class Crypto { + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMdCtxCopyEx")] + internal static partial SafeEvpMdCtxHandle EvpMdCtxCopyEx(SafeEvpMdCtxHandle ctx); + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMdCtxCreate")] internal static partial SafeEvpMdCtxHandle EvpMdCtxCreate(IntPtr type); @@ -18,6 +21,13 @@ internal static partial class Crypto [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestReset")] internal static partial int EvpDigestReset(SafeEvpMdCtxHandle ctx, IntPtr type); + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestSqueeze")] + private static partial int EvpDigestSqueeze( + SafeEvpMdCtxHandle ctx, + Span md, + uint len, + [MarshalAs(UnmanagedType.Bool)] out bool haveFeature); + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestUpdate")] internal static partial int EvpDigestUpdate(SafeEvpMdCtxHandle ctx, ReadOnlySpan d, int cnt); @@ -89,6 +99,18 @@ internal static unsafe int EvpDigestXOFOneShot(IntPtr type, ReadOnlySpan s return EvpDigestXOFOneShot(type, source, source.Length, destination, (uint)destination.Length); } + internal static int EvpDigestSqueeze(SafeEvpMdCtxHandle ctx, Span destination) + { + int ret = EvpDigestSqueeze(ctx, destination, (uint)destination.Length, out bool haveFeature); + + if (!haveFeature) + { + throw new PlatformNotSupportedException(); + } + + return ret; + } + internal static readonly int EVP_MAX_MD_SIZE = GetMaxMdSize(); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs index 310981b194d0..171980d0a765 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs @@ -21,10 +21,6 @@ internal static partial class Interop { internal static partial class OpenSsl { -#if DEBUG - private static readonly string? s_keyLogFile = Environment.GetEnvironmentVariable("SSLKEYLOGFILE"); - private static readonly FileStream? s_fileStream = s_keyLogFile != null ? File.Open(s_keyLogFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite) : null; -#endif private const string TlsCacheSizeCtxName = "System.Net.Security.TlsCacheSize"; private const string TlsCacheSizeEnvironmentVariable = "DOTNET_SYSTEM_NET_SECURITY_TLSCACHESIZE"; private const SslProtocols FakeAlpnSslProtocol = (SslProtocols)1; // used to distinguish server sessions with ALPN @@ -209,12 +205,10 @@ internal static unsafe SafeSslContextHandle AllocateSslContext(SslAuthentication Ssl.SslCtxSetDefaultOcspCallback(sslCtx); } } -#if DEBUG - if (s_fileStream != null) + if (SslKeyLogger.IsEnabled) { Ssl.SslCtxSetKeylogCallback(sslCtx, &KeyLogCallback); } -#endif } catch { @@ -754,26 +748,15 @@ private static unsafe void RemoveSessionCallback(IntPtr ctx, IntPtr session) IntPtr name = Ssl.SessionGetHostname(session); Debug.Assert(name != IntPtr.Zero); - ctxHandle.RemoveSession(name); + ctxHandle.RemoveSession(name, session); } -#if DEBUG [UnmanagedCallersOnly] private static unsafe void KeyLogCallback(IntPtr ssl, char* line) { - Debug.Assert(s_fileStream != null); ReadOnlySpan data = MemoryMarshal.CreateReadOnlySpanFromNullTerminated((byte*)line); - if (data.Length > 0) - { - lock (s_fileStream) - { - s_fileStream.Write(data); - s_fileStream.WriteByte((byte)'\n'); - s_fileStream.Flush(); - } - } + SslKeyLogger.WriteLineRaw(data); } -#endif private static int BioRead(SafeBioHandle bio, Span buffer, int count) { diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs index 5baa776d9d5a..d92e15e940e6 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs @@ -39,6 +39,9 @@ internal static partial class Ssl [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetCaching")] internal static unsafe partial int SslCtxSetCaching(SafeSslContextHandle ctx, int mode, int cacheSize, int contextIdLength, Span contextId, delegate* unmanaged neewSessionCallback, delegate* unmanaged removeSessionCallback); + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxRemoveSession")] + internal static unsafe partial void SslCtxRemoveSession(SafeSslContextHandle ctx, IntPtr session); + internal static bool AddExtraChainCertificates(SafeSslContextHandle ctx, ReadOnlyCollection chain) { // send pre-computed list of intermediates. @@ -142,27 +145,38 @@ internal bool TryAddSession(IntPtr namePtr, IntPtr session) // This will use strdup() so it is safe to pass in raw pointer. Interop.Ssl.SessionSetHostname(session, namePtr); + IntPtr oldSession = IntPtr.Zero; + lock (_sslSessions) { if (!_sslSessions.TryAdd(targetName, session)) { - if (_sslSessions.Remove(targetName, out IntPtr oldSession)) - { - Interop.Ssl.SessionFree(oldSession); - } - + // session to this target host exists, replace it + _sslSessions.Remove(targetName, out oldSession); bool added = _sslSessions.TryAdd(targetName, session); Debug.Assert(added); } } + if (oldSession != IntPtr.Zero) + { + // remove old session also from the internal OpenSSL cache + // and drop reference count. Since SSL_CTX_remove_session + // will call session_remove_cb, we need to do this outside + // of _sslSessions lock to avoid deadlock with another thread + // which could be holding SSL_CTX lock and trying to acquire + // _sslSessions lock. + Interop.Ssl.SslCtxRemoveSession(this, oldSession); + Interop.Ssl.SessionFree(oldSession); + } + return true; } return false; } - internal void RemoveSession(IntPtr namePtr) + internal void RemoveSession(IntPtr namePtr, IntPtr session) { Debug.Assert(_sslSessions != null); @@ -171,11 +185,14 @@ internal void RemoveSession(IntPtr namePtr) if (_sslSessions != null && targetName != null) { - IntPtr oldSession; - bool removed; + IntPtr oldSession = IntPtr.Zero; + bool removed = false; lock (_sslSessions) { - removed = _sslSessions.Remove(targetName, out oldSession); + if (_sslSessions.TryGetValue(targetName, out IntPtr existingSession) && existingSession == session) + { + removed = _sslSessions.Remove(targetName, out oldSession); + } } if (removed) @@ -209,7 +226,6 @@ internal bool TrySetSession(SafeSslHandle sslHandle, string name) // This will increase reference count on the session as needed. // We need to hold lock here to prevent session being deleted before the call is done. Interop.Ssl.SslSetSession(sslHandle, session); - return true; } } diff --git a/src/libraries/Common/src/Interop/Windows/CryptUI/Interop.CryptUIDlgCertificate.cs b/src/libraries/Common/src/Interop/Windows/CryptUI/Interop.CryptUIDlgCertificate.cs index e58a0b497dc4..97b5d4bba726 100644 --- a/src/libraries/Common/src/Interop/Windows/CryptUI/Interop.CryptUIDlgCertificate.cs +++ b/src/libraries/Common/src/Interop/Windows/CryptUI/Interop.CryptUIDlgCertificate.cs @@ -4,7 +4,7 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif using Microsoft.Win32.SafeHandles; @@ -13,7 +13,7 @@ internal static partial class Interop { internal static partial class CryptUI { -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #else [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] @@ -39,7 +39,7 @@ internal struct CRYPTUI_VIEWCERTIFICATE_STRUCTW internal IntPtr rgPropSheetPages; internal uint nStartPage; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW), MarshalMode.Default, typeof(Marshaller))] public static class Marshaller { @@ -127,7 +127,7 @@ public CRYPTUI_VIEWCERTIFICATE_STRUCTW ToManaged() #endif } -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #else [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] @@ -151,7 +151,7 @@ internal struct CRYPTUI_SELECTCERTIFICATE_STRUCTW internal IntPtr rgPropSheetPages; internal IntPtr hSelectedCertStore; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(CRYPTUI_SELECTCERTIFICATE_STRUCTW), MarshalMode.Default, typeof(Marshaller))] public static class Marshaller { diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.AbortDoc.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.AbortDoc.cs index cca83bef74b6..0326ead026c3 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.AbortDoc.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.AbortDoc.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -12,7 +12,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int AbortDoc( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateCompatibleBitmap.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateCompatibleBitmap.cs index e051d8f8d700..fdfc84cddf58 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateCompatibleBitmap.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateCompatibleBitmap.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,7 +13,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial IntPtr CreateCompatibleBitmap( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC, int width, int height); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateDIBSection.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateDIBSection.cs index ca024801b428..2654d0e653ad 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateDIBSection.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.CreateDIBSection.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,7 +13,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial IntPtr CreateDIBSection( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hdc, ref BITMAPINFO_FLAT bmi, int iUsage, ref IntPtr ppvBits, IntPtr hSection, int dwOffset); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.DEVMODE.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.DEVMODE.cs index aa26afa85665..bb0fa59f7712 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.DEVMODE.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.DEVMODE.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndDoc.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndDoc.cs index b65d8106b343..2bd8ad724163 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndDoc.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndDoc.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -12,7 +12,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int EndDoc( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndPage.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndPage.cs index f09232b01fba..0349c5044ba1 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndPage.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.EndPage.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -12,7 +12,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int EndPage( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ExtEscape.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ExtEscape.cs index 449ba1b934b3..6ade151f8b06 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ExtEscape.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ExtEscape.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -16,14 +16,14 @@ internal static partial class Gdi32 [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int ExtEscape( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC, int nEscape, int cbInput, ref int inData, int cbOutput, out int outData); [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int ExtEscape( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC, int nEscape, int cbInput, byte[] inData, int cbOutput, out int outData); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetDIBits.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetDIBits.cs index 03cbc74a846d..11900ac16602 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetDIBits.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetDIBits.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,11 +13,11 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32)] internal static partial int GetDIBits( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hdc, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hbm, int arg1, int arg2, IntPtr arg3, ref BITMAPINFO_FLAT bmi, int arg5); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetObject.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetObject.cs index 83fcfa6f9d23..afb88d5bd14a 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetObject.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetObject.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,20 +13,20 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, EntryPoint = "GetObjectW", SetLastError = true)] internal static partial int GetObject( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hObject, int nSize, ref BITMAP bm); [LibraryImport(Libraries.Gdi32, EntryPoint = "GetObjectW", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)] internal static partial int GetObject( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hObject, int nSize, ref Interop.User32.LOGFONT lf); internal static unsafe int GetObject( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hObject, ref Interop.User32.LOGFONT lp) diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetPaletteEntries.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetPaletteEntries.cs index 4f2f2ed80359..ab2ad0b6ea33 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetPaletteEntries.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.GetPaletteEntries.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -12,7 +12,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32)] internal static partial uint GetPaletteEntries( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hpal, int iStartIndex, int nEntries, byte[] lppe); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.IntersectClipRect.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.IntersectClipRect.cs index a82d6c5514ed..0084bcd62652 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.IntersectClipRect.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.IntersectClipRect.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,7 +13,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int IntersectClipRect( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC, int x1, int y1, int x2, int y2); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ResetDC.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ResetDC.cs index 3737f3f46699..e26750aa2895 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ResetDC.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.ResetDC.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,11 +13,11 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, EntryPoint = "ResetDCW", SetLastError = true)] internal static partial IntPtr /*HDC*/ ResetDC( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef /*DEVMODE*/ lpDevMode); diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartDoc.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartDoc.cs index c62da1844b8e..8199ff3f217f 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartDoc.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartDoc.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,12 +13,12 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, EntryPoint = "StartDocW", SetLastError = true)] internal static partial int StartDoc( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC, in DOCINFO lpDocInfo); -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #endif [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] @@ -32,7 +32,7 @@ internal struct DOCINFO public DOCINFO() { } -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(DOCINFO), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] public static class Marshaller { diff --git a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartPage.cs b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartPage.cs index 00ecc844d7e8..549151d43337 100644 --- a/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartPage.cs +++ b/src/libraries/Common/src/Interop/Windows/Gdi32/Interop.StartPage.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -12,7 +12,7 @@ internal static partial class Gdi32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial int StartPage( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC); diff --git a/src/libraries/Common/src/Interop/Windows/HttpApi/Interop.HttpApi.cs b/src/libraries/Common/src/Interop/Windows/HttpApi/Interop.HttpApi.cs index 011087bba391..d87b5c14c33f 100644 --- a/src/libraries/Common/src/Interop/Windows/HttpApi/Interop.HttpApi.cs +++ b/src/libraries/Common/src/Interop/Windows/HttpApi/Interop.HttpApi.cs @@ -16,8 +16,8 @@ internal static partial class HttpApi { internal static readonly HTTPAPI_VERSION s_version = new HTTPAPI_VERSION() { HttpApiMajorVersion = 2, HttpApiMinorVersion = 0 }; internal static readonly bool s_supported = InitHttpApi(s_version); - internal static IPEndPoint s_any = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort); - internal static IPEndPoint s_ipv6Any = new IPEndPoint(IPAddress.IPv6Any, IPEndPoint.MinPort); + internal static readonly IPEndPoint s_any = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort); + internal static readonly IPEndPoint s_ipv6Any = new IPEndPoint(IPAddress.IPv6Any, IPEndPoint.MinPort); internal const int IPv4AddressSize = 16; internal const int IPv6AddressSize = 28; diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SelectObject.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SelectObject.cs index efcc90a00fb2..da8fb34e900a 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SelectObject.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SelectObject.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,11 +13,11 @@ internal static partial class Kernel32 { [LibraryImport(Libraries.Gdi32, SetLastError = true)] internal static partial IntPtr SelectObject( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hdc, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef obj); diff --git a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Properties.cs b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Properties.cs index 41c079d5ad14..ec001c0b55a9 100644 --- a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Properties.cs +++ b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Properties.cs @@ -56,7 +56,7 @@ internal static unsafe ErrorCode NCryptGetIntProperty(SafeNCryptHandle hObject, { fixed (int* pResult = &result) { -#if NETSTANDARD || NETCOREAPP +#if NETSTANDARD || NET Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); #endif diff --git a/src/libraries/Common/src/Interop/Windows/OleAut32/Interop.VariantChangeTypeEx.cs b/src/libraries/Common/src/Interop/Windows/OleAut32/Interop.VariantChangeTypeEx.cs new file mode 100644 index 000000000000..edb77c858b38 --- /dev/null +++ b/src/libraries/Common/src/Interop/Windows/OleAut32/Interop.VariantChangeTypeEx.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class OleAut32 + { + [LibraryImport(Libraries.OleAut32)] + internal static unsafe partial int VariantChangeTypeEx(void* pVarRes, void* pVarSrc, int lcid, short wFlags, ushort vt); + } +} diff --git a/src/libraries/Common/src/Interop/Windows/Shell32/Interop.ExtractAssociatedIcon.cs b/src/libraries/Common/src/Interop/Windows/Shell32/Interop.ExtractAssociatedIcon.cs index 6162795d061e..d71fc5b7a083 100644 --- a/src/libraries/Common/src/Interop/Windows/Shell32/Interop.ExtractAssociatedIcon.cs +++ b/src/libraries/Common/src/Interop/Windows/Shell32/Interop.ExtractAssociatedIcon.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,7 +13,7 @@ internal static partial class Shell32 { [LibraryImport(Libraries.Shell32, EntryPoint = "ExtractAssociatedIconW")] internal static unsafe partial IntPtr ExtractAssociatedIcon( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hInst, char* iconPath, ref int index); diff --git a/src/libraries/Common/src/Interop/Windows/SspiCli/SecuritySafeHandles.cs b/src/libraries/Common/src/Interop/Windows/SspiCli/SecuritySafeHandles.cs index 589bc56352bb..ed40ac83a8a4 100644 --- a/src/libraries/Common/src/Interop/Windows/SspiCli/SecuritySafeHandles.cs +++ b/src/libraries/Common/src/Interop/Windows/SspiCli/SecuritySafeHandles.cs @@ -335,13 +335,12 @@ internal sealed class SafeFreeCredential_SECURITY : SafeFreeCredentials { #pragma warning disable 0649 // This is used only by SslStream but it is included elsewhere - public X509Certificate? LocalCertificate; + public bool HasLocalCertificate; #pragma warning restore 0649 public SafeFreeCredential_SECURITY() : base() { } protected override bool ReleaseHandle() { - LocalCertificate?.Dispose(); return Interop.SspiCli.FreeCredentialsHandle(ref _handle) == 0; } } diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.CopyImage.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.CopyImage.cs index 4211c156c365..b971b3730931 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.CopyImage.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.CopyImage.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,7 +13,7 @@ internal static partial class User32 { [LibraryImport(Libraries.User32, SetLastError = true)] internal static partial IntPtr CopyImage( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hImage, int uType, int cxDesired, int cyDesired, int fuFlags); diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.CreateIconFromResourceEx.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.CreateIconFromResourceEx.cs index a295619f2ac4..9c11ee7eba90 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.CreateIconFromResourceEx.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.CreateIconFromResourceEx.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.DestroyIcon.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.DestroyIcon.cs index 1528c6ae181e..782dbcec0e7f 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.DestroyIcon.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.DestroyIcon.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -14,7 +14,7 @@ internal static partial class User32 [LibraryImport(Libraries.User32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static partial bool DestroyIcon( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hIcon); diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.DrawIconEx.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.DrawIconEx.cs index 6ac69016bde6..9c0a0bfee89e 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.DrawIconEx.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.DrawIconEx.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -14,15 +14,15 @@ internal static partial class User32 [LibraryImport(Libraries.User32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static partial bool DrawIconEx( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hDC, int x, int y, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hIcon, int width, int height, int iStepIfAniCursor, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hBrushFlickerFree, int diFlags); diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.GetIconInfo.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetIconInfo.cs index e97f54e2e8f6..faa505574e6b 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.GetIconInfo.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetIconInfo.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -14,7 +14,7 @@ internal static partial class User32 [LibraryImport(Libraries.User32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static partial bool GetIconInfo( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hIcon, ref ICONINFO info); diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.GetSystemMetrics.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetSystemMetrics.cs index 761e69a4a2c8..4232c4348719 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.GetSystemMetrics.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetSystemMetrics.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.LoadIcon.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.LoadIcon.cs index f391366d89b1..378129442bf1 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.LoadIcon.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.LoadIcon.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,7 +13,7 @@ internal static partial class User32 { [LibraryImport(Libraries.User32, EntryPoint = "LoadIconW", SetLastError = true)] internal static partial IntPtr LoadIcon( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hInst, IntPtr iconId); diff --git a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs index 7e1010013c35..69457b973007 100644 --- a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs +++ b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif using System.Text; @@ -45,7 +45,7 @@ public static partial SafeWinHttpHandle WinHttpOpenRequest( [return: MarshalAs(UnmanagedType.Bool)] public static partial bool WinHttpAddRequestHeaders( SafeWinHttpHandle requestHandle, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(SimpleStringBufferMarshaller))] StringBuilder headers, #else #pragma warning disable CA1838 // Uses pooled StringBuilder @@ -55,7 +55,7 @@ public static partial bool WinHttpAddRequestHeaders( uint headersLength, uint modifiers); -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(StringBuilder), MarshalMode.ManagedToUnmanagedIn, typeof(SimpleStringBufferMarshaller))] private static unsafe class SimpleStringBufferMarshaller { diff --git a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs index 1cbdfa79d596..e76fa9b67e5b 100644 --- a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs +++ b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif using System.Text; @@ -247,7 +247,7 @@ public delegate void WINHTTP_STATUS_CALLBACK( IntPtr statusInformation, uint statusInformationLength); -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #endif [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] @@ -261,7 +261,7 @@ public struct WINHTTP_AUTOPROXY_OPTIONS public uint Reserved2; [MarshalAs(UnmanagedType.Bool)] public bool AutoLoginIfChallenged; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(WINHTTP_AUTOPROXY_OPTIONS), MarshalMode.Default, typeof(Marshaller))] public static class Marshaller { diff --git a/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs b/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs index a9ebcba2950c..954101a9c3cb 100644 --- a/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs +++ b/src/libraries/Common/src/Interop/Windows/WinMm/Interop.waveOutGetDevCaps.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -12,7 +12,7 @@ internal static partial class Interop internal static partial class WinMM { #pragma warning disable CA1823 // unused fields -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #endif internal struct WAVEOUTCAPS @@ -27,7 +27,7 @@ internal struct WAVEOUTCAPS private ushort wChannels; private ushort wReserved1; private ushort dwSupport; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(WAVEOUTCAPS), MarshalMode.Default, typeof(Marshaller))] public static class Marshaller { diff --git a/src/libraries/Common/src/Interop/Windows/Winspool/Interop.DocumentProperties.cs b/src/libraries/Common/src/Interop/Windows/Winspool/Interop.DocumentProperties.cs index bf54cfb1b5b9..8e7b6ce0c9d7 100644 --- a/src/libraries/Common/src/Interop/Windows/Winspool/Interop.DocumentProperties.cs +++ b/src/libraries/Common/src/Interop/Windows/Winspool/Interop.DocumentProperties.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif @@ -13,26 +13,26 @@ internal static partial class Winspool { [LibraryImport(Libraries.Winspool, EntryPoint = "DocumentPropertiesW", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)] internal static partial int DocumentProperties( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hwnd, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hPrinter, string pDeviceName, IntPtr /*DEVMODE*/ pDevModeOutput, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef /*DEVMODE*/ pDevModeInput, int fMode); [LibraryImport(Libraries.Winspool, EntryPoint = "DocumentPropertiesW", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)] internal static partial int DocumentProperties( -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hwnd, -#if NET7_0_OR_GREATER +#if NET [MarshalUsing(typeof(HandleRefMarshaller))] #endif HandleRef hPrinter, string pDeviceName, IntPtr /*DEVMODE*/ pDevModeOutput, IntPtr /*DEVMODE*/ pDevModeInput, int fMode); diff --git a/src/libraries/Common/src/Interop/Windows/Winspool/Interop.EnumPrinters.cs b/src/libraries/Common/src/Interop/Windows/Winspool/Interop.EnumPrinters.cs index ca967e11d16d..baeed522bb0c 100644 --- a/src/libraries/Common/src/Interop/Windows/Winspool/Interop.EnumPrinters.cs +++ b/src/libraries/Common/src/Interop/Windows/Winspool/Interop.EnumPrinters.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif diff --git a/src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeHandleCache.cs b/src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeHandleCache.cs index 2ce8fbf1b378..76e58eeaf7e7 100644 --- a/src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeHandleCache.cs +++ b/src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeHandleCache.cs @@ -21,11 +21,13 @@ internal static class SafeHandleCache where T : SafeHandle /// internal static T GetInvalidHandle(Func invalidHandleFactory) { - T? currentHandle = Volatile.Read(ref s_invalidHandle); - if (currentHandle == null) + return s_invalidHandle ?? CreateInvalidHandle(invalidHandleFactory); + + static T CreateInvalidHandle(Func invalidHandleFactory) { T newHandle = invalidHandleFactory(); - currentHandle = Interlocked.CompareExchange(ref s_invalidHandle, newHandle, null); + T? currentHandle = Interlocked.CompareExchange(ref s_invalidHandle, newHandle, null); + if (currentHandle == null) { GC.SuppressFinalize(newHandle); @@ -35,9 +37,10 @@ internal static T GetInvalidHandle(Func invalidHandleFactory) { newHandle.Dispose(); } + + Debug.Assert(currentHandle.IsInvalid); + return currentHandle; } - Debug.Assert(currentHandle.IsInvalid); - return currentHandle; } /// Gets whether the specified handle is invalid handle. @@ -46,7 +49,7 @@ internal static T GetInvalidHandle(Func invalidHandleFactory) internal static bool IsCachedInvalidHandle(SafeHandle handle) { Debug.Assert(handle != null); - bool isCachedInvalidHandle = ReferenceEquals(handle, Volatile.Read(ref s_invalidHandle)); + bool isCachedInvalidHandle = ReferenceEquals(handle, s_invalidHandle); Debug.Assert(!isCachedInvalidHandle || handle.IsInvalid, "The cached invalid handle must still be invalid."); return isCachedInvalidHandle; } diff --git a/src/libraries/Common/src/System/CodeDom/CodeTypeReference.cs b/src/libraries/Common/src/System/CodeDom/CodeTypeReference.cs index 615d6017e37e..cb75ff887f68 100644 --- a/src/libraries/Common/src/System/CodeDom/CodeTypeReference.cs +++ b/src/libraries/Common/src/System/CodeDom/CodeTypeReference.cs @@ -42,7 +42,7 @@ public CodeTypeReference() public CodeTypeReference(Type type) { -#if NET5_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(type); #else if (type is null) @@ -271,7 +271,7 @@ private void Initialize(string? typeName, CodeTypeReferenceOptions options) } // Now see if we have some arity. baseType could be null if this is an array type. -#if NET5_0_OR_GREATER +#if NET if (_baseType != null && _baseType.Contains('`')) // string.Contains(char) is .NetCore2.1+ specific #else if (_baseType != null && _baseType.IndexOf('`') != -1) // string.Contains(char) is .NetCore2.1+ specific diff --git a/src/libraries/Common/src/System/CodeDom/CodeTypeReferenceCollection.cs b/src/libraries/Common/src/System/CodeDom/CodeTypeReferenceCollection.cs index 21b2ae857366..55119bc72066 100644 --- a/src/libraries/Common/src/System/CodeDom/CodeTypeReferenceCollection.cs +++ b/src/libraries/Common/src/System/CodeDom/CodeTypeReferenceCollection.cs @@ -41,7 +41,7 @@ public CodeTypeReference this[int index] public void AddRange(CodeTypeReference[] value) { -#if NET5_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(value); #else if (value is null) @@ -58,7 +58,7 @@ public void AddRange(CodeTypeReference[] value) public void AddRange(CodeTypeReferenceCollection value) { -#if NET5_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(value); #else if (value is null) diff --git a/src/libraries/Common/src/System/Data/Common/DbConnectionOptions.Common.cs b/src/libraries/Common/src/System/Data/Common/DbConnectionOptions.Common.cs index 936c81c094e4..da3b254f99eb 100644 --- a/src/libraries/Common/src/System/Data/Common/DbConnectionOptions.Common.cs +++ b/src/libraries/Common/src/System/Data/Common/DbConnectionOptions.Common.cs @@ -50,7 +50,7 @@ internal partial class DbConnectionOptions private static readonly Regex s_connectionStringRegex = CreateConnectionStringRegex(); private static readonly Regex s_connectionStringRegexOdbc = CreateConnectionStringRegexOdbc(); -#if NET7_0_OR_GREATER +#if NET [GeneratedRegex(ConnectionStringPattern, RegexOptions.ExplicitCapture)] private static partial Regex CreateConnectionStringRegex(); @@ -67,7 +67,7 @@ internal partial class DbConnectionOptions private static readonly Regex s_connectionStringQuoteValueRegex = CreateConnectionStringQuoteValueRegex(); // generally do not quote the value if it matches the pattern private static readonly Regex s_connectionStringQuoteOdbcValueRegex = CreateConnectionStringQuoteOdbcValueRegex(); // do not quote odbc value if it matches this pattern -#if NET7_0_OR_GREATER +#if NET [GeneratedRegex("^(?![;\\s])[^\\p{Cc}]+(? + { + public readonly Uri UriPrefix; + public readonly int UriPrefixLength = -1; + public readonly string AuthenticationType; + + internal CredentialCacheKey(Uri uriPrefix, string authenticationType) + { + Debug.Assert(uriPrefix != null); + Debug.Assert(authenticationType != null); + + UriPrefix = uriPrefix; + UriPrefixLength = UriPrefix.AbsolutePath.LastIndexOf('/'); + AuthenticationType = authenticationType; + } + + internal bool Match(Uri uri, string authenticationType) + { + if (uri == null || authenticationType == null) + { + return false; + } + + // If the protocols don't match, this credential is not applicable for the given Uri. + if (!string.Equals(authenticationType, AuthenticationType, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Match({UriPrefix} & {uri})"); + + return IsPrefix(uri, UriPrefix); + } + + // IsPrefix (Uri) + // + // Determines whether is a prefix of this URI. A prefix + // match is defined as: + // + // scheme match + // + host match + // + port match, if any + // + path is a prefix of path, if any + // + // Returns: + // True if is a prefix of this URI + private static bool IsPrefix(Uri uri, Uri prefixUri) + { + Debug.Assert(uri != null); + Debug.Assert(prefixUri != null); + + if (prefixUri.Scheme != uri.Scheme || prefixUri.Host != uri.Host || prefixUri.Port != uri.Port) + { + return false; + } + + int prefixLen = prefixUri.AbsolutePath.LastIndexOf('/'); + if (prefixLen > uri.AbsolutePath.LastIndexOf('/')) + { + return false; + } + + return string.Compare(uri.AbsolutePath, 0, prefixUri.AbsolutePath, 0, prefixLen, StringComparison.OrdinalIgnoreCase) == 0; + } + + public override int GetHashCode() => + StringComparer.OrdinalIgnoreCase.GetHashCode(AuthenticationType) ^ + UriPrefix.GetHashCode(); + + public bool Equals([NotNullWhen(true)] CredentialCacheKey? other) + { + if (other == null) + { + return false; + } + + bool equals = + string.Equals(AuthenticationType, other.AuthenticationType, StringComparison.OrdinalIgnoreCase) && + UriPrefix.Equals(other.UriPrefix); + + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Equals({this},{other}) returns {equals}"); + + return equals; + } + + public override bool Equals([NotNullWhen(true)] object? obj) => Equals(obj as CredentialCacheKey); + + public override string ToString() => + string.Create(CultureInfo.InvariantCulture, $"[{UriPrefixLength}]:{UriPrefix}:{AuthenticationType}"); + } + + internal static class CredentialCacheHelper + { + public static bool TryGetCredential(Dictionary cache, Uri uriPrefix, string authType, [NotNullWhen(true)] out Uri? mostSpecificMatchUri, [NotNullWhen(true)] out NetworkCredential? mostSpecificMatch) + { + int longestMatchPrefix = -1; + mostSpecificMatch = null; + mostSpecificMatchUri = null; + + // Enumerate through every credential in the cache + foreach ((CredentialCacheKey key, NetworkCredential value) in cache) + { + // Determine if this credential is applicable to the current Uri/AuthType + if (key.Match(uriPrefix, authType)) + { + int prefixLen = key.UriPrefixLength; + + // Check if the match is better than the current-most-specific match + if (prefixLen > longestMatchPrefix) + { + // Yes: update the information about currently preferred match + longestMatchPrefix = prefixLen; + mostSpecificMatch = value; + mostSpecificMatchUri = key.UriPrefix; + } + } + } + + return mostSpecificMatch != null; + } + } +} diff --git a/src/libraries/Common/src/System/Net/Http/HttpHandlerDefaults.cs b/src/libraries/Common/src/System/Net/Http/HttpHandlerDefaults.cs index a9a9beeced8e..9924612c8e13 100644 --- a/src/libraries/Common/src/System/Net/Http/HttpHandlerDefaults.cs +++ b/src/libraries/Common/src/System/Net/Http/HttpHandlerDefaults.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Threading; +using System.Security.Principal; namespace System.Net.Http { @@ -23,6 +24,7 @@ internal static partial class HttpHandlerDefaults public const bool DefaultUseProxy = true; public const bool DefaultUseDefaultCredentials = false; public const bool DefaultCheckCertificateRevocationList = false; + public const TokenImpersonationLevel DefaultImpersonationLevel = TokenImpersonationLevel.None; public static readonly TimeSpan DefaultPooledConnectionLifetime = Timeout.InfiniteTimeSpan; public static readonly TimeSpan DefaultPooledConnectionIdleTimeout = TimeSpan.FromMinutes(1); public static readonly TimeSpan DefaultExpect100ContinueTimeout = TimeSpan.FromSeconds(1); diff --git a/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/Frames/Http3ErrorCode.cs b/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/Frames/Http3ErrorCode.cs index fdfe04cee158..ebaa96f12cdc 100644 --- a/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/Frames/Http3ErrorCode.cs +++ b/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/Frames/Http3ErrorCode.cs @@ -91,5 +91,20 @@ internal enum Http3ErrorCode : long /// The requested operation cannot be served over HTTP/3. The peer should retry over HTTP/1.1. /// VersionFallback = 0x110, + /// + /// H3_QPACK_DECOMPRESSION_FAILED (0x200): + /// The decoder failed to interpret an encoded field section and is not able to continue decoding that field section. + /// + QPackDecompressionFailed = 0x200, + /// + /// H3_QPACK_ENCODER_STREAM_ERROR (0x201): + /// The decoder failed to interpret an encoder instruction received on the encoder stream. + /// + QPackEncoderStreamError = 0x201, + /// + /// H3_QPACK_DECODER_STREAM_ERROR (0x202): + /// The encoder failed to interpret an decoder instruction received on the decoder stream. + /// + QPackDecoderStreamError = 0x202, } } diff --git a/src/libraries/Common/src/System/Net/Security/SslKeyLogger.cs b/src/libraries/Common/src/System/Net/Security/SslKeyLogger.cs new file mode 100644 index 000000000000..e6e9d9cd0392 --- /dev/null +++ b/src/libraries/Common/src/System/Net/Security/SslKeyLogger.cs @@ -0,0 +1,134 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.IO; +using System.Net; + +internal static class SslKeyLogger +{ + private static readonly string? s_keyLogFile = Environment.GetEnvironmentVariable("SSLKEYLOGFILE"); + private static readonly FileStream? s_fileStream; + +#pragma warning disable CA1810 // Initialize all static fields when declared and remove cctor + static SslKeyLogger() + { + s_fileStream = null; + + try + { +#if DEBUG + bool isEnabled = true; +#else + bool isEnabled = AppContext.TryGetSwitch("System.Net.EnableSslKeyLogging", out bool enabled) && enabled; +#endif + + if (isEnabled && s_keyLogFile != null) + { + s_fileStream = File.Open(s_keyLogFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite); + } + } + catch (Exception ex) + { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Error(null, $"Failed to open SSL key log file '{s_keyLogFile}': {ex}"); + } + } + } +#pragma warning restore CA1810 + + public static bool IsEnabled => s_fileStream != null; + + public static void WriteLineRaw(ReadOnlySpan data) + { + Debug.Assert(s_fileStream != null); + if (s_fileStream == null) + { + return; + } + + if (data.Length > 0) + { + lock (s_fileStream) + { + s_fileStream.Write(data); + s_fileStream.WriteByte((byte)'\n'); + s_fileStream.Flush(); + } + } + } + + public static void WriteSecrets( + ReadOnlySpan clientRandom, + ReadOnlySpan clientHandshakeTrafficSecret, + ReadOnlySpan serverHandshakeTrafficSecret, + ReadOnlySpan clientTrafficSecret0, + ReadOnlySpan serverTrafficSecret0, + ReadOnlySpan clientEarlyTrafficSecret) + { + Debug.Assert(s_fileStream != null); + Debug.Assert(!clientRandom.IsEmpty); + + if (s_fileStream == null || + clientRandom.IsEmpty || + + // return early if there is nothing to log + (clientHandshakeTrafficSecret.IsEmpty && + serverHandshakeTrafficSecret.IsEmpty && + clientTrafficSecret0.IsEmpty && + serverTrafficSecret0.IsEmpty && + clientEarlyTrafficSecret.IsEmpty)) + { + return; + } + + Span clientRandomUtf8 = clientRandom.Length <= 1024 ? stackalloc byte[clientRandom.Length * 2] : new byte[clientRandom.Length * 2]; + HexEncode(clientRandom, clientRandomUtf8); + + lock (s_fileStream) + { + WriteSecretCore("CLIENT_HANDSHAKE_TRAFFIC_SECRET"u8, clientRandomUtf8, clientHandshakeTrafficSecret); + WriteSecretCore("SERVER_HANDSHAKE_TRAFFIC_SECRET"u8, clientRandomUtf8, serverHandshakeTrafficSecret); + WriteSecretCore("CLIENT_TRAFFIC_SECRET_0"u8, clientRandomUtf8, clientTrafficSecret0); + WriteSecretCore("SERVER_TRAFFIC_SECRET_0"u8, clientRandomUtf8, serverTrafficSecret0); + WriteSecretCore("CLIENT_EARLY_TRAFFIC_SECRET"u8, clientRandomUtf8, clientEarlyTrafficSecret); + + s_fileStream.Flush(); + } + } + + private static void WriteSecretCore(ReadOnlySpan labelUtf8, ReadOnlySpan clientRandomUtf8, ReadOnlySpan secret) + { + if (secret.Length == 0) + { + return; + } + + // write the secret line in the format {label} {client_random (hex)} {secret (hex)} e.g. + // SERVER_HANDSHAKE_TRAFFIC_SECRET bae582227f0f46ca663cb8c3d62e68cec38c2b947e7c4a9ec6f4e262b5ed5354 48f6bd5b0c8447d97129c6dad080f34c7f9f11ade8eeabb011f33811543411d7ab1013b1374bcd81bfface6a2deef539 + int totalLength = labelUtf8.Length + 1 + clientRandomUtf8.Length + 1 + 2 * secret.Length + 1; + Span line = totalLength <= 1024 ? stackalloc byte[totalLength] : new byte[totalLength]; + + labelUtf8.CopyTo(line); + line[labelUtf8.Length] = (byte)' '; + + clientRandomUtf8.CopyTo(line.Slice(labelUtf8.Length + 1)); + line[labelUtf8.Length + 1 + clientRandomUtf8.Length] = (byte)' '; + + HexEncode(secret, line.Slice(labelUtf8.Length + 1 + clientRandomUtf8.Length + 1)); + line[^1] = (byte)'\n'; + + s_fileStream!.Write(line); + } + + private static void HexEncode(ReadOnlySpan source, Span destination) + { + for (int i = 0; i < source.Length; i++) + { + HexConverter.ToBytesBuffer(source[i], destination.Slice(i * 2)); + } + } + +} diff --git a/src/libraries/Common/src/System/Number.Formatting.Common.cs b/src/libraries/Common/src/System/Number.Formatting.Common.cs index 4caa59472eae..672ff2402682 100644 --- a/src/libraries/Common/src/System/Number.Formatting.Common.cs +++ b/src/libraries/Common/src/System/Number.Formatting.Common.cs @@ -12,6 +12,8 @@ namespace System { internal static partial class Number { + private const int CharStackBufferSize = 32; + private const int DefaultPrecisionExponentialFormat = 6; private const int MaxUInt32DecDigits = 10; diff --git a/src/libraries/Common/src/System/Obsoletions.cs b/src/libraries/Common/src/System/Obsoletions.cs index 677ffd66b34b..318a466f8406 100644 --- a/src/libraries/Common/src/System/Obsoletions.cs +++ b/src/libraries/Common/src/System/Obsoletions.cs @@ -174,5 +174,11 @@ internal static class Obsoletions internal const string ThreadVolatileReadWriteMessage = "Thread.VolatileRead and Thread.VolatileWrite are obsolete. Use Volatile.Read or Volatile.Write respectively instead."; internal const string ThreadVolatileReadWriteDiagId = "SYSLIB0054"; + + internal const string ArmIntrinsicPerformsUnsignedOperationMessage = "The underlying hardware instruction does not perform a signed saturate narrowing operation, and it always returns an unsigned result. Use the unsigned overload instead."; + internal const string ArmIntrinsicPerformsUnsignedOperationDiagId = "SYSLIB0055"; + + internal const string LoadFromHashAlgorithmMessage = "LoadFrom with a custom AssemblyHashAlgorithm is obsolete. Use overloads without an AssemblyHashAlgorithm."; + internal const string LoadFromHashAlgorithmDiagId = "SYSLIB0056"; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameFormatter.cs b/src/libraries/Common/src/System/Reflection/AssemblyNameFormatter.cs similarity index 93% rename from src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameFormatter.cs rename to src/libraries/Common/src/System/Reflection/AssemblyNameFormatter.cs index c1a810db5075..41598ddc5310 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameFormatter.cs +++ b/src/libraries/Common/src/System/Reflection/AssemblyNameFormatter.cs @@ -91,7 +91,8 @@ private static void AppendQuoted(this ref ValueStringBuilder vsb, string s) // App-compat: You can use double or single quotes to quote a name, and Fusion (or rather the IdentityAuthority) picks one // by some algorithm. Rather than guess at it, we use double quotes consistently. - if (s != s.Trim() || s.Contains('\"') || s.Contains('\'')) + ReadOnlySpan span = s.AsSpan(); + if (s.Length != span.Trim().Length || span.IndexOfAny('\"', '\'') >= 0) needsQuoting = true; if (needsQuoting) @@ -125,5 +126,12 @@ private static void AppendQuoted(this ref ValueStringBuilder vsb, string s) if (needsQuoting) vsb.Append(quoteChar); } + +#if !NET + private static void AppendSpanFormattable(this ref ValueStringBuilder vsb, ushort value) + { + vsb.Append(value.ToString()); + } +#endif } } diff --git a/src/libraries/Common/src/System/Reflection/AssemblyNameParser.cs b/src/libraries/Common/src/System/Reflection/AssemblyNameParser.cs new file mode 100644 index 000000000000..1c9f55d4087f --- /dev/null +++ b/src/libraries/Common/src/System/Reflection/AssemblyNameParser.cs @@ -0,0 +1,504 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.IO; +using System.Runtime.CompilerServices; +using System.Text; + +namespace System.Reflection +{ + /// + /// Parses an assembly name. + /// + internal ref partial struct AssemblyNameParser + { + public readonly struct AssemblyNameParts + { + public AssemblyNameParts(string name, Version? version, string? cultureName, AssemblyNameFlags flags, byte[]? publicKeyOrToken) + { + _name = name; + _version = version; + _cultureName = cultureName; + _flags = flags; + _publicKeyOrToken = publicKeyOrToken; + } + + public readonly string _name; + public readonly Version? _version; + public readonly string? _cultureName; + public readonly AssemblyNameFlags _flags; + public readonly byte[]? _publicKeyOrToken; + } + + /// + /// Token categories for the lexer. + /// + private enum Token + { + Equals = 1, + Comma = 2, + String = 3, + End = 4, + } + + private enum AttributeKind + { + Version = 1, + Culture = 2, + PublicKeyOrToken = 4, + ProcessorArchitecture = 8, + Retargetable = 16, + ContentType = 32 + } + + private readonly ReadOnlySpan _input; + private int _index; + + private AssemblyNameParser(ReadOnlySpan input) + { +#if SYSTEM_PRIVATE_CORELIB + if (input.Length == 0) + throw new ArgumentException(SR.Format_StringZeroLength); +#else + Debug.Assert(input.Length > 0); +#endif + + _input = input; + _index = 0; + } + +#if SYSTEM_PRIVATE_CORELIB + public static AssemblyNameParts Parse(string name) => Parse(name.AsSpan()); + + public static AssemblyNameParts Parse(ReadOnlySpan name) + { + AssemblyNameParser parser = new(name); + AssemblyNameParts result = default; + if (parser.TryParse(ref result)) + { + return result; + } + throw new FileLoadException(SR.InvalidAssemblyName, name.ToString()); + } +#endif + + internal static bool TryParse(ReadOnlySpan name, ref AssemblyNameParts parts) + { + AssemblyNameParser parser = new(name); + return parser.TryParse(ref parts); + } + + private static bool TryRecordNewSeen(scoped ref AttributeKind seenAttributes, AttributeKind newAttribute) + { + if ((seenAttributes & newAttribute) != 0) + { + return false; + } + seenAttributes |= newAttribute; + return true; + } + + private bool TryParse(ref AssemblyNameParts result) + { + // Name must come first. + if (!TryGetNextToken(out string name, out Token token) || token != Token.String || string.IsNullOrEmpty(name)) + return false; + + Version? version = null; + string? cultureName = null; + byte[]? pkt = null; + AssemblyNameFlags flags = 0; + + AttributeKind alreadySeen = default; + if (!TryGetNextToken(out _, out token)) + return false; + + while (token != Token.End) + { + if (token != Token.Comma) + return false; + + if (!TryGetNextToken(out string attributeName, out token) || token != Token.String) + return false; + + if (!TryGetNextToken(out _, out token) || token != Token.Equals) + return false; + + if (!TryGetNextToken(out string attributeValue, out token) || token != Token.String) + return false; + + if (attributeName == string.Empty) + return false; + + if (IsAttribute(attributeName, "Version")) + { + if (!TryRecordNewSeen(ref alreadySeen, AttributeKind.Version)) + { + return false; + } + if (!TryParseVersion(attributeValue, ref version)) + { + return false; + } + } + else if (IsAttribute(attributeName, "Culture")) + { + if (!TryRecordNewSeen(ref alreadySeen, AttributeKind.Culture)) + { + return false; + } + if (!TryParseCulture(attributeValue, out cultureName)) + { + return false; + } + } + else if (IsAttribute(attributeName, "PublicKeyToken")) + { + if (!TryRecordNewSeen(ref alreadySeen, AttributeKind.PublicKeyOrToken)) + { + return false; + } + if (!TryParsePKT(attributeValue, isToken: true, out pkt)) + { + return false; + } + } + else if (IsAttribute(attributeName, "PublicKey")) + { + if (!TryRecordNewSeen(ref alreadySeen, AttributeKind.PublicKeyOrToken)) + { + return false; + } + if (!TryParsePKT(attributeValue, isToken: false, out pkt)) + { + return false; + } + flags |= AssemblyNameFlags.PublicKey; + } + else if (IsAttribute(attributeName, "ProcessorArchitecture")) + { + if (!TryRecordNewSeen(ref alreadySeen, AttributeKind.ProcessorArchitecture)) + { + return false; + } + if (!TryParseProcessorArchitecture(attributeValue, out ProcessorArchitecture arch)) + { + return false; + } + flags |= (AssemblyNameFlags)(((int)arch) << 4); + } + else if (IsAttribute(attributeName, "Retargetable")) + { + if (!TryRecordNewSeen(ref alreadySeen, AttributeKind.Retargetable)) + { + return false; + } + + if (attributeValue.Equals("Yes", StringComparison.OrdinalIgnoreCase)) + { + flags |= AssemblyNameFlags.Retargetable; + } + else if (attributeValue.Equals("No", StringComparison.OrdinalIgnoreCase)) + { + // nothing to do + } + else + { + return false; + } + } + else if (IsAttribute(attributeName, "ContentType")) + { + if (!TryRecordNewSeen(ref alreadySeen, AttributeKind.ContentType)) + { + return false; + } + + if (attributeValue.Equals("WindowsRuntime", StringComparison.OrdinalIgnoreCase)) + { + flags |= (AssemblyNameFlags)(((int)AssemblyContentType.WindowsRuntime) << 9); + } + else + { + return false; + } + } + else + { + // Desktop compat: If we got here, the attribute name is unknown to us. Ignore it. + } + + if (!TryGetNextToken(out _, out token)) + { + return false; + } + } + + result = new AssemblyNameParts(name, version, cultureName, flags, pkt); + return true; + } + + private static bool IsAttribute(string candidate, string attributeKind) + => candidate.Equals(attributeKind, StringComparison.OrdinalIgnoreCase); + + private static bool TryParseVersion(string attributeValue, ref Version? version) + { +#if NET8_0_OR_GREATER + ReadOnlySpan attributeValueSpan = attributeValue; + Span parts = stackalloc Range[5]; + parts = parts.Slice(0, attributeValueSpan.Split(parts, '.')); +#else + string[] parts = attributeValue.Split('.'); +#endif + if (parts.Length is < 2 or > 4) + { + return false; + } + + Span versionNumbers = stackalloc ushort[4] { ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue }; + for (int i = 0; i < parts.Length; i++) + { + if (!ushort.TryParse( +#if NET8_0_OR_GREATER + attributeValueSpan[parts[i]], +#else + parts[i], +#endif + NumberStyles.None, NumberFormatInfo.InvariantInfo, out versionNumbers[i])) + { + return false; + } + } + + if (versionNumbers[0] == ushort.MaxValue || + versionNumbers[1] == ushort.MaxValue) + { + return false; + } + + version = + versionNumbers[2] == ushort.MaxValue ? new Version(versionNumbers[0], versionNumbers[1]) : + versionNumbers[3] == ushort.MaxValue ? new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2]) : + new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2], versionNumbers[3]); + + return true; + } + + private static bool TryParseCulture(string attributeValue, out string? result) + { + if (attributeValue.Equals("Neutral", StringComparison.OrdinalIgnoreCase)) + { + result = ""; + return true; + } + + result = attributeValue; + return true; + } + + private static bool TryParsePKT(string attributeValue, bool isToken, out byte[]? result) + { + if (attributeValue.Equals("null", StringComparison.OrdinalIgnoreCase) || attributeValue == string.Empty) + { + result = Array.Empty(); + return true; + } + + if (attributeValue.Length % 2 != 0 || (isToken && attributeValue.Length != 8 * 2)) + { + result = null; + return false; + } + + byte[] pkt = new byte[attributeValue.Length / 2]; + if (!HexConverter.TryDecodeFromUtf16(attributeValue.AsSpan(), pkt, out int _)) + { + result = null; + return false; + } + + result = pkt; + return true; + } + + private static bool TryParseProcessorArchitecture(string attributeValue, out ProcessorArchitecture result) + { + result = attributeValue switch + { + _ when attributeValue.Equals("msil", StringComparison.OrdinalIgnoreCase) => ProcessorArchitecture.MSIL, + _ when attributeValue.Equals("x86", StringComparison.OrdinalIgnoreCase) => ProcessorArchitecture.X86, + _ when attributeValue.Equals("ia64", StringComparison.OrdinalIgnoreCase) => ProcessorArchitecture.IA64, + _ when attributeValue.Equals("amd64", StringComparison.OrdinalIgnoreCase) => ProcessorArchitecture.Amd64, + _ when attributeValue.Equals("arm", StringComparison.OrdinalIgnoreCase) => ProcessorArchitecture.Arm, + _ when attributeValue.Equals("msil", StringComparison.OrdinalIgnoreCase) => ProcessorArchitecture.MSIL, + _ => ProcessorArchitecture.None + }; + return result != ProcessorArchitecture.None; + } + + private static bool IsWhiteSpace(char ch) + => ch is '\n' or '\r' or ' ' or '\t'; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private bool TryGetNextChar(out char ch) + { + if (_index < _input.Length) + { + ch = _input[_index++]; + if (ch == '\0') + { + return false; + } + } + else + { + ch = '\0'; + } + + return true; + } + + // + // Return the next token in assembly name. If the result is Token.String, + // sets "tokenString" to the tokenized string. + // + private bool TryGetNextToken(out string tokenString, out Token token) + { + tokenString = string.Empty; + char c; + + while (true) + { + if (!TryGetNextChar(out c)) + { + token = default; + return false; + } + + switch (c) + { + case ',': + { + token = Token.Comma; + return true; + } + case '=': + { + token = Token.Equals; + return true; + } + case '\0': + { + token = Token.End; + return true; + } + } + + if (!IsWhiteSpace(c)) + { + break; + } + } + + using ValueStringBuilder sb = new ValueStringBuilder(stackalloc char[64]); + + char quoteChar = '\0'; + if (c is '\'' or '\"') + { + quoteChar = c; + if (!TryGetNextChar(out c)) + { + token = default; + return false; + } + } + + for (; ; ) + { + if (c == 0) + { + if (quoteChar != 0) + { + // EOS and unclosed quotes is an error + token = default; + return false; + } + // Reached end of input and therefore of string + break; + } + + if (quoteChar != 0 && c == quoteChar) + break; // Terminate: Found closing quote of quoted string. + + if (quoteChar == 0 && (c is ',' or '=')) + { + _index--; + break; // Terminate: Found start of a new ',' or '=' token. + } + + if (quoteChar == 0 && (c is '\'' or '\"')) + { + token = default; + return false; + } + + if (c is '\\') + { + if (!TryGetNextChar(out c)) + { + token = default; + return false; + } + + switch (c) + { + case '\\': + case ',': + case '=': + case '\'': + case '"': + sb.Append(c); + break; + case 't': + sb.Append('\t'); + break; + case 'r': + sb.Append('\r'); + break; + case 'n': + sb.Append('\n'); + break; + default: + token = default; + return false; + } + } + else + { + sb.Append(c); + } + + if (!TryGetNextChar(out c)) + { + token = default; + return false; + } + } + + + int length = sb.Length; + if (quoteChar == 0) + { + while (length > 0 && IsWhiteSpace(sb[length - 1])) + length--; + } + + tokenString = sb.AsSpan(0, length).ToString(); + token = Token.String; + return true; + } + } +} diff --git a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameHelpers.cs b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameHelpers.cs new file mode 100644 index 000000000000..f43a04fadfd5 --- /dev/null +++ b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameHelpers.cs @@ -0,0 +1,79 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Reflection.Metadata; +using System.Text; + +namespace System.Reflection.Metadata +{ + internal static class TypeNameHelpers + { + private const char EscapeCharacter = '\\'; + + /// + /// Removes escape characters from the string (if there were any found). + /// + internal static string Unescape(string name) + { + int indexOfEscapeCharacter = name.IndexOf(EscapeCharacter); + if (indexOfEscapeCharacter < 0) + { + return name; + } + + return Unescape(name, indexOfEscapeCharacter); + + static string Unescape(string name, int indexOfEscapeCharacter) + { + // this code path is executed very rarely (IL Emit or pure IL with chars not allowed in C# or F#) + var sb = new ValueStringBuilder(stackalloc char[64]); + sb.EnsureCapacity(name.Length); + sb.Append(name.AsSpan(0, indexOfEscapeCharacter)); + + for (int i = indexOfEscapeCharacter; i < name.Length;) + { + char c = name[i++]; + + if (c != EscapeCharacter) + { + sb.Append(c); + } + else if (i < name.Length && name[i] == EscapeCharacter) // escaped escape character ;) + { + sb.Append(c); + // Consume the escaped escape character, it's important for edge cases + // like escaped escape character followed by another escaped char (example: "\\\\\\+") + i++; + } + } + + return sb.ToString(); + } + } + + internal static (string typeNamespace, string name) Split(string typeName) + { + string typeNamespace, name; + + // Matches algorithm from ns::FindSep in src\coreclr\utilcode\namespaceutil.cpp + // This could result in the type name beginning with a '.' character. + int separator = typeName.LastIndexOf('.'); + if (separator <= 0) + { + typeNamespace = ""; + name = typeName; + } + else + { + if (typeName[separator - 1] == '.') + separator--; + typeNamespace = typeName.Substring(0, separator); + name = typeName.Substring(separator + 1); + } + + return (typeNamespace, name); + } + } +} diff --git a/src/libraries/Common/src/System/Reflection/TypeNameParser.cs b/src/libraries/Common/src/System/Reflection/TypeNameParser.cs deleted file mode 100644 index 0b69e4e18aaa..000000000000 --- a/src/libraries/Common/src/System/Reflection/TypeNameParser.cs +++ /dev/null @@ -1,701 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; -using System.Text; - -#nullable enable - -namespace System.Reflection -{ - // - // Parser for type names passed to GetType() apis. - // - [StructLayout(LayoutKind.Auto)] - internal ref partial struct TypeNameParser - { - private ReadOnlySpan _input; - private int _index; - private int _errorIndex; // Position for error reporting - - private TypeNameParser(ReadOnlySpan name) - { - _input = name; - _errorIndex = _index = 0; - } - - // - // Parses a type name. The type name may be optionally postpended with a "," followed by a legal assembly name. - // - private Type? Parse() - { - TypeName? typeName = ParseNonQualifiedTypeName(); - if (typeName is null) - return null; - - string? assemblyName = null; - - TokenType token = GetNextToken(); - if (token != TokenType.End) - { - if (token != TokenType.Comma) - { - ParseError(); - return null; - } - - if (!CheckTopLevelAssemblyQualifiedName()) - return null; - - assemblyName = GetNextAssemblyName(); - if (assemblyName is null) - return null; - Debug.Assert(Peek == TokenType.End); - } - - return typeName.ResolveType(ref this, assemblyName); - } - - // - // Parses a type name without any assembly name qualification. - // - private TypeName? ParseNonQualifiedTypeName() - { - // Parse the named type or constructed generic type part first. - TypeName? typeName = ParseNamedOrConstructedGenericTypeName(); - if (typeName is null) - return null; - - // Iterate through any "has-element" qualifiers ([], &, *). - while (true) - { - TokenType token = Peek; - if (token == TokenType.End) - break; - if (token == TokenType.Asterisk) - { - Skip(); - typeName = new ModifierTypeName(typeName, ModifierTypeName.Pointer); - } - else if (token == TokenType.Ampersand) - { - Skip(); - typeName = new ModifierTypeName(typeName, ModifierTypeName.ByRef); - } - else if (token == TokenType.OpenSqBracket) - { - Skip(); - token = GetNextToken(); - if (token == TokenType.Asterisk) - { - typeName = new ModifierTypeName(typeName, 1); - token = GetNextToken(); - } - else - { - int rank = 1; - while (token == TokenType.Comma) - { - token = GetNextToken(); - rank++; - } - if (rank == 1) - typeName = new ModifierTypeName(typeName, ModifierTypeName.Array); - else - typeName = new ModifierTypeName(typeName, rank); - } - if (token != TokenType.CloseSqBracket) - { - ParseError(); - return null; - } - } - else - { - break; - } - } - return typeName; - } - - // - // Foo or Foo+Inner or Foo[String] or Foo+Inner[String] - // - private TypeName? ParseNamedOrConstructedGenericTypeName() - { - TypeName? namedType = ParseNamedTypeName(); - if (namedType is null) - return null; - - // Because "[" is used both for generic arguments and array indexes, we must peek two characters deep. - if (!(Peek is TokenType.OpenSqBracket && (PeekSecond is TokenType.Other or TokenType.OpenSqBracket))) - return namedType; - - Skip(); - - TypeName[] typeArguments = new TypeName[2]; - int typeArgumentsCount = 0; - while (true) - { - TypeName? typeArgument = ParseGenericTypeArgument(); - if (typeArgument is null) - return null; - if (typeArgumentsCount >= typeArguments.Length) - Array.Resize(ref typeArguments, 2 * typeArgumentsCount); - typeArguments[typeArgumentsCount++] = typeArgument; - TokenType token = GetNextToken(); - if (token == TokenType.CloseSqBracket) - break; - if (token != TokenType.Comma) - { - ParseError(); - return null; - } - } - - return new GenericTypeName(namedType, typeArguments, typeArgumentsCount); - } - - // - // Foo or Foo+Inner - // - private TypeName? ParseNamedTypeName() - { - string? fullName = GetNextIdentifier(); - if (fullName is null) - return null; - - fullName = ApplyLeadingDotCompatQuirk(fullName); - - if (Peek == TokenType.Plus) - { - string[] nestedNames = new string[1]; - int nestedNamesCount = 0; - - do - { - Skip(); - - string? nestedName = GetNextIdentifier(); - if (nestedName is null) - return null; - - nestedName = ApplyLeadingDotCompatQuirk(nestedName); - - if (nestedNamesCount >= nestedNames.Length) - Array.Resize(ref nestedNames, 2 * nestedNamesCount); - nestedNames[nestedNamesCount++] = nestedName; - } - while (Peek == TokenType.Plus); - - return new NestedNamespaceTypeName(fullName, nestedNames, nestedNamesCount); - } - else - { - return new NamespaceTypeName(fullName); - } - - // Compat: Ignore leading '.' for type names without namespace. .NET Framework historically ignored leading '.' here. It is likely - // that code out there depends on this behavior. For example, type names formed by concatenating namespace and name, without checking for - // empty namespace (bug), are going to have superfluous leading '.'. - // This behavior means that types that start with '.' are not round-trippable via type name. - static string ApplyLeadingDotCompatQuirk(string typeName) - { -#if NETCOREAPP - return (typeName.StartsWith('.') && !typeName.AsSpan(1).Contains('.')) ? typeName.Substring(1) : typeName; -#else - return ((typeName.Length > 0) && (typeName[0] == '.') && typeName.LastIndexOf('.') == 0) ? typeName.Substring(1) : typeName; -#endif - } - } - - // - // Parse a generic argument. In particular, generic arguments can take the special form [,]. - // - private TypeName? ParseGenericTypeArgument() - { - TokenType token = GetNextToken(); - if (token == TokenType.Other) - { - return ParseNonQualifiedTypeName(); - } - if (token != TokenType.OpenSqBracket) - { - ParseError(); - return null; - } - string? assemblyName = null; - TypeName? typeName = ParseNonQualifiedTypeName(); - if (typeName is null) - return null; - - token = GetNextToken(); - if (token == TokenType.Comma) - { - assemblyName = GetNextEmbeddedAssemblyName(); - token = GetNextToken(); - } - if (token != TokenType.CloseSqBracket) - { - ParseError(); - return null; - } - - return (assemblyName != null) ? new AssemblyQualifiedTypeName(typeName, assemblyName) : typeName; - } - - // - // String tokenizer for type names passed to the GetType() APIs. - // - - private TokenType Peek - { - get - { - SkipWhiteSpace(); - char c = (_index < _input.Length) ? _input[_index] : '\0'; - return CharToToken(c); - } - } - - private TokenType PeekSecond - { - get - { - SkipWhiteSpace(); - int index = _index + 1; - while (index < _input.Length && char.IsWhiteSpace(_input[index])) - index++; - char c = (index < _input.Length) ? _input[index] : '\0'; - return CharToToken(c); - } - } - - private void Skip() - { - SkipWhiteSpace(); - if (_index < _input.Length) - _index++; - } - - // Return the next token and skip index past it unless already at end of string - // or the token is not a reserved token. - private TokenType GetNextToken() - { - _errorIndex = _index; - - TokenType tokenType = Peek; - if (tokenType == TokenType.End || tokenType == TokenType.Other) - return tokenType; - Skip(); - return tokenType; - } - - // - // Lex the next segment as part of a type name. (Do not use for assembly names.) - // - // Note that unescaped "."'s do NOT terminate the identifier, but unescaped "+"'s do. - // - // Terminated by the first non-escaped reserved character ('[', ']', '+', '&', '*' or ',') - // - private string? GetNextIdentifier() - { - SkipWhiteSpace(); - - ValueStringBuilder sb = new ValueStringBuilder(stackalloc char[64]); - - int src = _index; - while (true) - { - if (src >= _input.Length) - break; - char c = _input[src]; - TokenType token = CharToToken(c); - if (token != TokenType.Other) - break; - src++; - if (c == '\\') // Check for escaped character - { - // Update error location - _errorIndex = src - 1; - - c = (src < _input.Length) ? _input[src++] : '\0'; - - if (!NeedsEscapingInTypeName(c)) - { - // If we got here, a backslash was used to escape a character that is not legal to escape inside a type name. - ParseError(); - return null; - } - } - sb.Append(c); - } - _index = src; - - if (sb.Length == 0) - { - // The identifier has to be non-empty - _errorIndex = src; - ParseError(); - return null; - } - - return sb.ToString(); - } - - // - // Lex the next segment as the assembly name at the end of an assembly-qualified type name. (Do not use for - // assembly names embedded inside generic type arguments.) - // - private string? GetNextAssemblyName() - { - if (!StartAssemblyName()) - return null; - - string assemblyName = _input.Slice(_index).ToString(); - _index = _input.Length; - return assemblyName; - } - - // - // Lex the next segment as an assembly name embedded inside a generic argument type. - // - // Terminated by an unescaped ']'. - // - private string? GetNextEmbeddedAssemblyName() - { - if (!StartAssemblyName()) - return null; - - ValueStringBuilder sb = new ValueStringBuilder(stackalloc char[64]); - - int src = _index; - while (true) - { - if (src >= _input.Length) - { - ParseError(); - return null; - } - char c = _input[src]; - if (c == ']') - break; - src++; - - // Backslash can be used to escape a ']' - any other backslash character is left alone (along with the backslash) - // for the AssemblyName parser to handle. - if (c == '\\' && (src < _input.Length) && _input[src] == ']') - { - c = _input[src++]; - } - sb.Append(c); - } - _index = src; - - if (sb.Length == 0) - { - // The assembly name has to be non-empty - _errorIndex = src; - ParseError(); - return null; - } - - return sb.ToString(); - } - - private bool StartAssemblyName() - { - // Compat: Treat invalid starting token of assembly name as type name parsing error instead of assembly name parsing error. This only affects - // exception returned by the parser. - if (Peek is TokenType.End or TokenType.Comma) - { - ParseError(); - return false; - } - return true; - } - - // - // Classify a character as a TokenType. (Fortunately, all tokens in type name strings other than identifiers are single-character tokens.) - // - private static TokenType CharToToken(char c) - { - return c switch - { - '\0' => TokenType.End, - '[' => TokenType.OpenSqBracket, - ']' => TokenType.CloseSqBracket, - ',' => TokenType.Comma, - '+' => TokenType.Plus, - '*' => TokenType.Asterisk, - '&' => TokenType.Ampersand, - _ => TokenType.Other, - }; - } - - // - // The type name parser has a strange attitude towards whitespace. It throws away whitespace between punctuation tokens and whitespace - // preceding identifiers or assembly names (and this cannot be escaped away). But whitespace between the end of an identifier - // and the punctuation that ends it is *not* ignored. - // - // In other words, GetType(" Foo") searches for "Foo" but GetType("Foo ") searches for "Foo ". - // - // Whitespace between the end of an assembly name and the punction mark that ends it is also not ignored by this parser, - // but this is irrelevant since the assembly name is then turned over to AssemblyName for parsing, which *does* ignore trailing whitespace. - // - private void SkipWhiteSpace() - { - while (_index < _input.Length && char.IsWhiteSpace(_input[_index])) - _index++; - } - - private enum TokenType - { - End = 0, //At end of string - OpenSqBracket = 1, //'[' - CloseSqBracket = 2, //']' - Comma = 3, //',' - Plus = 4, //'+' - Asterisk = 5, //'*' - Ampersand = 6, //'&' - Other = 7, //Type identifier, AssemblyName or embedded AssemblyName. - } - - // - // The TypeName class is the base class for a family of types that represent the nodes in a parse tree for - // assembly-qualified type names. - // - private abstract class TypeName - { - /// - /// Helper for the Type.GetType() family of APIs. "containingAssemblyIsAny" is the assembly to search for (as determined - /// by a qualifying assembly string in the original type string passed to Type.GetType(). If null, it means the type stream - /// didn't specify an assembly name. How to respond to that is up to the type resolver delegate in getTypeOptions - this class - /// is just a middleman. - /// - public abstract Type? ResolveType(ref TypeNameParser parser, string? containingAssemblyIfAny); - } - - // - // Represents a parse of a type name qualified by an assembly name. - // - private sealed class AssemblyQualifiedTypeName : TypeName - { - private readonly string _assemblyName; - private readonly TypeName _nonQualifiedTypeName; - - public AssemblyQualifiedTypeName(TypeName nonQualifiedTypeName, string assemblyName) - { - _nonQualifiedTypeName = nonQualifiedTypeName; - _assemblyName = assemblyName; - } - - public override Type? ResolveType(ref TypeNameParser parser, string? containingAssemblyIfAny) - { - return _nonQualifiedTypeName.ResolveType(ref parser, _assemblyName); - } - } - - // - // Non-nested named type. The full name is the namespace-qualified name. For example, the FullName for - // System.Collections.Generic.IList<> is "System.Collections.Generic.IList`1". - // - private sealed partial class NamespaceTypeName : TypeName - { - private readonly string _fullName; - public NamespaceTypeName(string fullName) - { - _fullName = fullName; - } - - public override Type? ResolveType(ref TypeNameParser parser, string? containingAssemblyIfAny) - { - return parser.GetType(_fullName, default, containingAssemblyIfAny); - } - } - - // - // Nested type name. - // - private sealed partial class NestedNamespaceTypeName : TypeName - { - private readonly string _fullName; - private readonly string[] _nestedNames; - private readonly int _nestedNamesCount; - - public NestedNamespaceTypeName(string fullName, string[] nestedNames, int nestedNamesCount) - { - _fullName = fullName; - _nestedNames = nestedNames; - _nestedNamesCount = nestedNamesCount; - } - - public override Type? ResolveType(ref TypeNameParser parser, string? containingAssemblyIfAny) - { - return parser.GetType(_fullName, _nestedNames.AsSpan(0, _nestedNamesCount), containingAssemblyIfAny); - } - } - - // - // Array, byref or pointer type name. - // - private sealed class ModifierTypeName : TypeName - { - private readonly TypeName _elementTypeName; - - // Positive value is multi-dimensional array rank. - // Negative value is modifier encoded using constants below. - private readonly int _rankOrModifier; - - public const int Array = -1; - public const int Pointer = -2; - public const int ByRef = -3; - - public ModifierTypeName(TypeName elementTypeName, int rankOrModifier) - { - _elementTypeName = elementTypeName; - _rankOrModifier = rankOrModifier; - } - -#if NETCOREAPP - [UnconditionalSuppressMessage("AotAnalysis", "IL3050:AotUnfriendlyApi", - Justification = "Used to implement resolving types from strings.")] -#endif - public override Type? ResolveType(ref TypeNameParser parser, string? containingAssemblyIfAny) - { - Type? elementType = _elementTypeName.ResolveType(ref parser, containingAssemblyIfAny); - if (elementType is null) - return null; - - return _rankOrModifier switch - { - Array => elementType.MakeArrayType(), - Pointer => elementType.MakePointerType(), - ByRef => elementType.MakeByRefType(), - _ => elementType.MakeArrayType(_rankOrModifier) - }; - } - } - - // - // Constructed generic type name. - // - private sealed class GenericTypeName : TypeName - { - private readonly TypeName _typeDefinition; - private readonly TypeName[] _typeArguments; - private readonly int _typeArgumentsCount; - - public GenericTypeName(TypeName genericTypeDefinition, TypeName[] typeArguments, int typeArgumentsCount) - { - _typeDefinition = genericTypeDefinition; - _typeArguments = typeArguments; - _typeArgumentsCount = typeArgumentsCount; - } - -#if NETCOREAPP - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern", - Justification = "Used to implement resolving types from strings.")] - [UnconditionalSuppressMessage("AotAnalysis", "IL3050:AotUnfriendlyApi", - Justification = "Used to implement resolving types from strings.")] -#endif - public override Type? ResolveType(ref TypeNameParser parser, string? containingAssemblyIfAny) - { - Type? typeDefinition = _typeDefinition.ResolveType(ref parser, containingAssemblyIfAny); - if (typeDefinition is null) - return null; - - Type[] arguments = new Type[_typeArgumentsCount]; - for (int i = 0; i < arguments.Length; i++) - { - Type? typeArgument = _typeArguments[i].ResolveType(ref parser, null); - if (typeArgument is null) - return null; - arguments[i] = typeArgument; - } - - return typeDefinition.MakeGenericType(arguments); - } - } - - // - // Type name escaping helpers - // - -#if NETCOREAPP - private static ReadOnlySpan CharsToEscape => "\\[]+*&,"; - - private static bool NeedsEscapingInTypeName(char c) - => CharsToEscape.Contains(c); -#else - private static char[] CharsToEscape { get; } = "\\[]+*&,".ToCharArray(); - - private static bool NeedsEscapingInTypeName(char c) - => Array.IndexOf(CharsToEscape, c) >= 0; -#endif - - private static string EscapeTypeName(string name) - { - if (name.AsSpan().IndexOfAny(CharsToEscape) < 0) - return name; - - var sb = new ValueStringBuilder(stackalloc char[64]); - foreach (char c in name) - { - if (NeedsEscapingInTypeName(c)) - sb.Append('\\'); - sb.Append(c); - } - - return sb.ToString(); - } - - private static string EscapeTypeName(string typeName, ReadOnlySpan nestedTypeNames) - { - string fullName = EscapeTypeName(typeName); - if (nestedTypeNames.Length > 0) - { - var sb = new StringBuilder(fullName); - for (int i = 0; i < nestedTypeNames.Length; i++) - { - sb.Append('+'); - sb.Append(EscapeTypeName(nestedTypeNames[i])); - } - fullName = sb.ToString(); - } - return fullName; - } - - private static (string typeNamespace, string name) SplitFullTypeName(string typeName) - { - string typeNamespace, name; - - // Matches algorithm from ns::FindSep in src\coreclr\utilcode\namespaceutil.cpp - int separator = typeName.LastIndexOf('.'); - if (separator <= 0) - { - typeNamespace = ""; - name = typeName; - } - else - { - if (typeName[separator - 1] == '.') - separator--; - typeNamespace = typeName.Substring(0, separator); - name = typeName.Substring(separator + 1); - } - - return (typeNamespace, name); - } - -#if SYSTEM_PRIVATE_CORELIB - private void ParseError() - { - if (_throwOnError) - throw new ArgumentException(SR.Arg_ArgumentException, $"typeName@{_errorIndex}"); - } -#endif - } -} diff --git a/src/libraries/Common/src/System/Resources/ResourceWriter.cs b/src/libraries/Common/src/System/Resources/ResourceWriter.cs index 1f93de277639..81a70e7ae2f5 100644 --- a/src/libraries/Common/src/System/Resources/ResourceWriter.cs +++ b/src/libraries/Common/src/System/Resources/ResourceWriter.cs @@ -488,7 +488,7 @@ private static ResourceTypeCode FindTypeCode(object? value, List types) if (typeName.StartsWith("ResourceTypeCode.", StringComparison.Ordinal)) { typeName = typeName.Substring(17); // Remove through '.' -#if NETCOREAPP +#if NET ResourceTypeCode typeCode = Enum.Parse(typeName); #else ResourceTypeCode typeCode = (ResourceTypeCode)Enum.Parse(typeof(ResourceTypeCode), typeName); diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1/AsnXml.targets b/src/libraries/Common/src/System/Security/Cryptography/Asn1/AsnXml.targets index 940c73ca5723..eb285cc2cfc2 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Asn1/AsnXml.targets +++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1/AsnXml.targets @@ -1,9 +1,6 @@ - <_AsnXmlDiffCmd>%24%28command -v diff%29 -q -a - <_AsnXmlDiffCmd Condition="$([MSBuild]::IsOsPlatform('windows')) == 'true'">$(SystemRoot)\System32\fc.exe /a - <_AsnXmlDiffCmd Condition="$([MSBuild]::IsOsPlatform('osx')) == 'true'">diff @@ -11,6 +8,27 @@ + + + + + + + + + + + + + + + - - - + + + - + diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1/AttributeAsn.manual.cs b/src/libraries/Common/src/System/Security/Cryptography/Asn1/AttributeAsn.manual.cs index 71b8fe421f58..da7c9d3d8d0d 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Asn1/AttributeAsn.manual.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1/AttributeAsn.manual.cs @@ -7,7 +7,7 @@ internal partial struct AttributeAsn { public AttributeAsn(AsnEncodedData attribute) { -#if NET5_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(attribute); #else if (attribute is null) diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs b/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs index f299c9362325..38e60abcebc6 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs @@ -63,7 +63,7 @@ internal bool VerifyMac( throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } -#if NETCOREAPP +#if NET Debug.Assert(expectedOutputSize <= 64); // SHA512 is the largest digest size we know about Span derived = stackalloc byte[expectedOutputSize]; #else diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1/X509ExtensionAsn.manual.cs b/src/libraries/Common/src/System/Security/Cryptography/Asn1/X509ExtensionAsn.manual.cs index e4d19d760700..543656905c4f 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Asn1/X509ExtensionAsn.manual.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1/X509ExtensionAsn.manual.cs @@ -9,7 +9,7 @@ internal partial struct X509ExtensionAsn { public X509ExtensionAsn(X509Extension extension) { -#if NET5_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(extension); #else if (extension is null) diff --git a/src/libraries/Common/src/System/Security/Cryptography/CryptoPool.cs b/src/libraries/Common/src/System/Security/Cryptography/CryptoPool.cs index dd3a37c32237..e4b71ded239f 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/CryptoPool.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/CryptoPool.cs @@ -27,7 +27,7 @@ internal static void Return(byte[] array, int clearSize = ClearAll) if (!clearWholeArray && clearSize != 0) { -#if (NETCOREAPP || NETSTANDARD2_1) && !CP_NO_ZEROMEMORY +#if (NET || NETSTANDARD2_1) && !CP_NO_ZEROMEMORY CryptographicOperations.ZeroMemory(array.AsSpan(0, clearSize)); #else Array.Clear(array, 0, clearSize); diff --git a/src/libraries/Common/src/System/Security/Cryptography/CryptoThrowHelper.Windows.cs b/src/libraries/Common/src/System/Security/Cryptography/CryptoThrowHelper.Windows.cs index 3081a8bc239b..e7cd24e0eeb1 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/CryptoThrowHelper.Windows.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/CryptoThrowHelper.Windows.cs @@ -5,7 +5,7 @@ using System.ComponentModel; using System.Security.Cryptography; -#if !NETCOREAPP3_1_OR_GREATER +#if !NET using System.Diagnostics; using System.Runtime.Serialization; #endif @@ -25,7 +25,7 @@ public static CryptographicException ToCryptographicException(this int hr) hr = (hr & 0x0000FFFF) | unchecked((int)0x80070000); } -#if NETCOREAPP3_1_OR_GREATER +#if NET return new CryptographicException(message) { HResult = hr @@ -40,7 +40,7 @@ public static CryptographicException ToCryptographicException(this int hr) #endif } -#if !NETCOREAPP3_1_OR_GREATER +#if !NET [Serializable] private sealed class WindowsCryptographicException : CryptographicException { diff --git a/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs b/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs index 0071c345d1d2..462e4d26a8f6 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs @@ -12,13 +12,13 @@ internal static partial class Helpers { [UnsupportedOSPlatformGuard("browser")] internal static bool HasSymmetricEncryption { get; } = -#if NETCOREAPP +#if NET !OperatingSystem.IsBrowser(); #else true; #endif -#if NETCOREAPP +#if NET [UnsupportedOSPlatformGuard("ios")] [UnsupportedOSPlatformGuard("tvos")] public static bool IsDSASupported => !OperatingSystem.IsIOS() && !OperatingSystem.IsTvOS(); @@ -26,7 +26,7 @@ internal static partial class Helpers public static bool IsDSASupported => true; #endif -#if NETCOREAPP +#if NET [UnsupportedOSPlatformGuard("android")] [UnsupportedOSPlatformGuard("browser")] public static bool IsRC2Supported => !OperatingSystem.IsAndroid() && !OperatingSystem.IsBrowser(); @@ -36,7 +36,7 @@ internal static partial class Helpers [UnsupportedOSPlatformGuard("browser")] internal static bool HasMD5 { get; } = -#if NETCOREAPP +#if NET !OperatingSystem.IsBrowser(); #else true; diff --git a/src/libraries/Common/src/System/Security/Cryptography/Oids.Shared.cs b/src/libraries/Common/src/System/Security/Cryptography/Oids.Shared.cs index 59ad3a9e71c3..2f584a0bbfd7 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Oids.Shared.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Oids.Shared.cs @@ -8,38 +8,38 @@ namespace System.Security.Cryptography { internal static partial class Oids { - private static volatile Oid? s_rsaOid; - private static volatile Oid? s_ecPublicKeyOid; - private static volatile Oid? s_tripleDesCbcOid; - private static volatile Oid? s_aes256CbcOid; - private static volatile Oid? s_secp256R1Oid; - private static volatile Oid? s_secp384R1Oid; - private static volatile Oid? s_secp521R1Oid; - private static volatile Oid? s_sha256Oid; - private static volatile Oid? s_pkcs7DataOid; - private static volatile Oid? s_contentTypeOid; - private static volatile Oid? s_documentDescriptionOid; - private static volatile Oid? s_documentNameOid; - private static volatile Oid? s_localKeyIdOid; - private static volatile Oid? s_messageDigestOid; - private static volatile Oid? s_signingTimeOid; - private static volatile Oid? s_pkcs9ExtensionRequestOid; - private static volatile Oid? s_basicConstraints2Oid; - private static volatile Oid? s_enhancedKeyUsageOid; - private static volatile Oid? s_keyUsageOid; - private static volatile Oid? s_subjectAltNameOid; - private static volatile Oid? s_subjectKeyIdentifierOid; - private static volatile Oid? s_authorityKeyIdentifierOid; - private static volatile Oid? s_authorityInformationAccessOid; - private static volatile Oid? s_crlNumberOid; - private static volatile Oid? s_crlDistributionPointOid; - private static volatile Oid? s_commonNameOid; - private static volatile Oid? s_countryOrRegionOid; - private static volatile Oid? s_localityNameOid; - private static volatile Oid? s_stateOrProvinceNameOid; - private static volatile Oid? s_organizationOid; - private static volatile Oid? s_organizationalUnitOid; - private static volatile Oid? s_emailAddressOid; + private static Oid? s_rsaOid; + private static Oid? s_ecPublicKeyOid; + private static Oid? s_tripleDesCbcOid; + private static Oid? s_aes256CbcOid; + private static Oid? s_secp256R1Oid; + private static Oid? s_secp384R1Oid; + private static Oid? s_secp521R1Oid; + private static Oid? s_sha256Oid; + private static Oid? s_pkcs7DataOid; + private static Oid? s_contentTypeOid; + private static Oid? s_documentDescriptionOid; + private static Oid? s_documentNameOid; + private static Oid? s_localKeyIdOid; + private static Oid? s_messageDigestOid; + private static Oid? s_signingTimeOid; + private static Oid? s_pkcs9ExtensionRequestOid; + private static Oid? s_basicConstraints2Oid; + private static Oid? s_enhancedKeyUsageOid; + private static Oid? s_keyUsageOid; + private static Oid? s_subjectAltNameOid; + private static Oid? s_subjectKeyIdentifierOid; + private static Oid? s_authorityKeyIdentifierOid; + private static Oid? s_authorityInformationAccessOid; + private static Oid? s_crlNumberOid; + private static Oid? s_crlDistributionPointOid; + private static Oid? s_commonNameOid; + private static Oid? s_countryOrRegionOid; + private static Oid? s_localityNameOid; + private static Oid? s_stateOrProvinceNameOid; + private static Oid? s_organizationOid; + private static Oid? s_organizationalUnitOid; + private static Oid? s_emailAddressOid; internal static Oid RsaOid => s_rsaOid ??= InitializeOid(Rsa); internal static Oid EcPublicKeyOid => s_ecPublicKeyOid ??= InitializeOid(EcPublicKey); @@ -72,10 +72,10 @@ internal static partial class Oids internal static Oid CommonNameOid => s_commonNameOid ??= InitializeOid(CommonName); internal static Oid CountryOrRegionNameOid => s_countryOrRegionOid ??= InitializeOid(CountryOrRegionName); internal static Oid LocalityNameOid => s_localityNameOid ??= InitializeOid(LocalityName); - internal static Oid StateOrProvinceNameOid = s_stateOrProvinceNameOid ??= InitializeOid(StateOrProvinceName); - internal static Oid OrganizationOid = s_organizationOid ??= InitializeOid(Organization); - internal static Oid OrganizationalUnitOid = s_organizationalUnitOid ??= InitializeOid(OrganizationalUnit); - internal static Oid EmailAddressOid = s_emailAddressOid ??= InitializeOid(EmailAddress); + internal static Oid StateOrProvinceNameOid => s_stateOrProvinceNameOid ??= InitializeOid(StateOrProvinceName); + internal static Oid OrganizationOid => s_organizationOid ??= InitializeOid(Organization); + internal static Oid OrganizationalUnitOid => s_organizationalUnitOid ??= InitializeOid(OrganizationalUnit); + internal static Oid EmailAddressOid => s_emailAddressOid ??= InitializeOid(EmailAddress); private static Oid InitializeOid(string oidValue) { diff --git a/src/libraries/Common/src/System/Security/Cryptography/SP800108HmacCounterKdfImplementationManaged.cs b/src/libraries/Common/src/System/Security/Cryptography/SP800108HmacCounterKdfImplementationManaged.cs index f7928c692515..60c64aa520e4 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/SP800108HmacCounterKdfImplementationManaged.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/SP800108HmacCounterKdfImplementationManaged.cs @@ -10,9 +10,6 @@ namespace System.Security.Cryptography { -#if !NET7_0_OR_GREATER && NET - [UnsupportedOSPlatform("browser")] -#endif internal sealed partial class SP800108HmacCounterKdfImplementationManaged : SP800108HmacCounterKdfImplementationBase { private byte[] _key; diff --git a/src/libraries/Common/src/System/Text/Json/PooledByteBufferWriter.cs b/src/libraries/Common/src/System/Text/Json/PooledByteBufferWriter.cs index 75424aed0d3c..51e1cccb43e3 100644 --- a/src/libraries/Common/src/System/Text/Json/PooledByteBufferWriter.cs +++ b/src/libraries/Common/src/System/Text/Json/PooledByteBufferWriter.cs @@ -27,7 +27,7 @@ internal sealed class PooledByteBufferWriter : IBufferWriter, IDisposable private PooledByteBufferWriter() { -#if NETCOREAPP +#if NET // Ensure we are in sync with the Array.MaxLength implementation. Debug.Assert(MaximumBufferSize == Array.MaxLength); #endif @@ -147,7 +147,7 @@ public Span GetSpan(int sizeHint = MinimumBufferSize) return _rentedBuffer.AsSpan(_index); } -#if NETCOREAPP +#if NET internal ValueTask WriteToStreamAsync(Stream destination, CancellationToken cancellationToken) { return destination.WriteAsync(WrittenMemory, cancellationToken); diff --git a/src/libraries/Common/src/System/Text/ValueStringBuilder.cs b/src/libraries/Common/src/System/Text/ValueStringBuilder.cs index a0844b046642..14aa77db3e57 100644 --- a/src/libraries/Common/src/System/Text/ValueStringBuilder.cs +++ b/src/libraries/Common/src/System/Text/ValueStringBuilder.cs @@ -161,7 +161,7 @@ public void Insert(int index, string? s) int remaining = _pos - index; _chars.Slice(index, remaining).CopyTo(_chars.Slice(index + count)); s -#if !NETCOREAPP +#if !NET .AsSpan() #endif .CopyTo(_chars.Slice(index)); @@ -213,7 +213,7 @@ private void AppendSlow(string s) } s -#if !NETCOREAPP +#if !NET .AsSpan() #endif .CopyTo(_chars.Slice(pos)); diff --git a/src/libraries/Common/src/System/Threading/Tasks/TaskToAsyncResult.cs b/src/libraries/Common/src/System/Threading/Tasks/TaskToAsyncResult.cs index 0075f897ff46..7c9bd9073e6d 100644 --- a/src/libraries/Common/src/System/Threading/Tasks/TaskToAsyncResult.cs +++ b/src/libraries/Common/src/System/Threading/Tasks/TaskToAsyncResult.cs @@ -31,7 +31,7 @@ static class TaskToAsyncResult /// public static IAsyncResult Begin(Task task, AsyncCallback? callback, object? state) { -#if NET6_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(task); #else if (task is null) @@ -68,7 +68,7 @@ public static TResult End(IAsyncResult asyncResult) => /// was not produced by a call to . public static Task Unwrap(IAsyncResult asyncResult) { -#if NET6_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(asyncResult); #else if (asyncResult is null) @@ -97,7 +97,7 @@ public static Task Unwrap(IAsyncResult asyncResult) /// public static Task Unwrap(IAsyncResult asyncResult) { -#if NET6_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(asyncResult); #else if (asyncResult is null) diff --git a/src/libraries/Common/src/System/ThrowHelper.cs b/src/libraries/Common/src/System/ThrowHelper.cs index 4257c05891e3..098b83214927 100644 --- a/src/libraries/Common/src/System/ThrowHelper.cs +++ b/src/libraries/Common/src/System/ThrowHelper.cs @@ -15,7 +15,7 @@ internal static partial class ThrowHelper /// The reference type argument to validate as non-null. /// The name of the parameter with which corresponds. internal static void ThrowIfNull( -#if NETCOREAPP3_0_OR_GREATER +#if NET [NotNull] #endif object? argument, @@ -27,7 +27,7 @@ internal static void ThrowIfNull( } } -#if NETCOREAPP3_0_OR_GREATER +#if NET [DoesNotReturn] #endif private static void Throw(string? paramName) => throw new ArgumentNullException(paramName); @@ -40,17 +40,17 @@ internal static void ThrowIfNull( /// The name of the parameter being checked. /// The original value of . [MethodImpl(MethodImplOptions.AggressiveInlining)] -#if NETCOREAPP3_0_OR_GREATER +#if NET [return: NotNull] #endif public static string IfNullOrWhitespace( -#if NETCOREAPP3_0_OR_GREATER +#if NET [NotNull] #endif string? argument, [CallerArgumentExpression(nameof(argument))] string paramName = "") { -#if !NETCOREAPP3_1_OR_GREATER +#if !NET if (argument == null) { throw new ArgumentNullException(paramName); @@ -74,7 +74,7 @@ public static string IfNullOrWhitespace( } } -#if !NETCOREAPP3_0_OR_GREATER +#if !NET namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] diff --git a/src/libraries/Common/tests/SourceGenerators/RoslynTestUtils.cs b/src/libraries/Common/tests/SourceGenerators/RoslynTestUtils.cs index e67289721d8a..e1c53d3b8aa1 100644 --- a/src/libraries/Common/tests/SourceGenerators/RoslynTestUtils.cs +++ b/src/libraries/Common/tests/SourceGenerators/RoslynTestUtils.cs @@ -349,7 +349,7 @@ private static async Task RecreateDocumentAsync(Document document) } private static string ReplaceLineEndings(string text) => -#if NETCOREAPP +#if NET text.ReplaceLineEndings("\n"); #else text.Replace("\r\n", "\n"); diff --git a/src/libraries/Common/tests/System/Collections/TestBase.Generic.cs b/src/libraries/Common/tests/System/Collections/TestBase.Generic.cs index 73d382893d28..0a22540b6588 100644 --- a/src/libraries/Common/tests/System/Collections/TestBase.Generic.cs +++ b/src/libraries/Common/tests/System/Collections/TestBase.Generic.cs @@ -255,7 +255,7 @@ protected IEnumerable CreateHashSet(IEnumerable enumerableToMatchTo, int c return set; } -#if NETCOREAPP +#if NET /// /// Create a HashSet with a specific initial capacity and fill it with a specific number of elements. /// diff --git a/src/libraries/Common/tests/System/GenericMathHelpers.cs b/src/libraries/Common/tests/System/GenericMathHelpers.cs index 277580dc5920..a02f8a4e162a 100644 --- a/src/libraries/Common/tests/System/GenericMathHelpers.cs +++ b/src/libraries/Common/tests/System/GenericMathHelpers.cs @@ -151,6 +151,12 @@ public static class FloatingPointHelper { public static TSelf Ceiling(TSelf x) => TSelf.Ceiling(x); + public static TInteger ConvertToInteger(TSelf x) + where TInteger : IBinaryInteger => TSelf.ConvertToInteger(x); + + public static TInteger ConvertToIntegerNative(TSelf x) + where TInteger : IBinaryInteger => TSelf.ConvertToIntegerNative(x); + public static TSelf Floor(TSelf x) => TSelf.Floor(x); public static TSelf Round(TSelf x) => TSelf.Round(x); diff --git a/src/libraries/Common/tests/System/IO/Compression/ZipTestHelper.cs b/src/libraries/Common/tests/System/IO/Compression/ZipTestHelper.cs index 6d194788762f..9666a16e2fb3 100644 --- a/src/libraries/Common/tests/System/IO/Compression/ZipTestHelper.cs +++ b/src/libraries/Common/tests/System/IO/Compression/ZipTestHelper.cs @@ -233,7 +233,7 @@ public static void IsZipSameAsDir(Stream archiveFile, string directory, ZipArchi using (Stream entrystream = entry.Open()) { ReadAllBytes(entrystream, buffer, 0, buffer.Length); -#if NETCOREAPP +#if NET uint zipcrc = entry.Crc32; Assert.Equal(CRC.CalculateCRC(buffer), zipcrc); #endif diff --git a/src/libraries/Common/tests/System/Net/Capability.Security.Unix.cs b/src/libraries/Common/tests/System/Net/Capability.Security.Unix.cs index bad2ddd2dd73..3bbba47040b0 100644 --- a/src/libraries/Common/tests/System/Net/Capability.Security.Unix.cs +++ b/src/libraries/Common/tests/System/Net/Capability.Security.Unix.cs @@ -9,6 +9,10 @@ public static partial class Capability { public static bool IsNtlmInstalled() { + if (OperatingSystem.IsBrowser()) + { + return false; + } return // Linux bionic uses managed NTLM implementation (OperatingSystem.IsLinux() && RuntimeInformation.RuntimeIdentifier.StartsWith("linux-bionic-", StringComparison.Ordinal)) || diff --git a/src/libraries/Common/tests/System/Net/Configuration.Http.cs b/src/libraries/Common/tests/System/Net/Configuration.Http.cs index ae1481c56061..460b7893cc63 100644 --- a/src/libraries/Common/tests/System/Net/Configuration.Http.cs +++ b/src/libraries/Common/tests/System/Net/Configuration.Http.cs @@ -58,12 +58,19 @@ public static partial class Http public static readonly Uri RemoteEchoServer = new Uri("http://" + Host + "/" + EchoHandler); public static readonly Uri SecureRemoteEchoServer = new Uri("https://" + SecureHost + "/" + EchoHandler); public static readonly Uri Http2RemoteEchoServer = new Uri("https://" + Http2Host + "/" + EchoHandler); - public static readonly Uri[] EchoServerList = new Uri[] { RemoteEchoServer, SecureRemoteEchoServer, Http2RemoteEchoServer }; + public static Uri[] GetEchoServerList() + { + if (PlatformDetection.IsFirefox) + { + // https://github.com/dotnet/runtime/issues/101115 + return [RemoteEchoServer]; + } + return [RemoteEchoServer, SecureRemoteEchoServer, Http2RemoteEchoServer]; + } public static readonly Uri RemoteVerifyUploadServer = new Uri("http://" + Host + "/" + VerifyUploadHandler); public static readonly Uri SecureRemoteVerifyUploadServer = new Uri("https://" + SecureHost + "/" + VerifyUploadHandler); public static readonly Uri Http2RemoteVerifyUploadServer = new Uri("https://" + Http2Host + "/" + VerifyUploadHandler); - public static readonly Uri[] VerifyUploadServerList = new Uri[] { RemoteVerifyUploadServer, SecureRemoteVerifyUploadServer, Http2RemoteVerifyUploadServer }; public static readonly Uri RemoteEmptyContentServer = new Uri("http://" + Host + "/" + EmptyContentHandler); public static readonly Uri RemoteDeflateServer = new Uri("http://" + Host + "/" + DeflateHandler); @@ -72,7 +79,7 @@ public static partial class Http public static readonly Uri Http2RemoteGZipServer = new Uri("https://" + Http2Host + "/" + GZipHandler); public static Uri RemoteLoopServer => new Uri("ws://" + RemoteLoopHost + "/" + RemoteLoopHandler); - public static readonly object[][] EchoServers = EchoServerList.Select(x => new object[] { x }).ToArray(); + public static readonly object[][] EchoServers = GetEchoServerList().Select(x => new object[] { x }).ToArray(); public static readonly object[][] VerifyUploadServers = { new object[] { RemoteVerifyUploadServer }, new object[] { SecureRemoteVerifyUploadServer }, new object[] { Http2RemoteVerifyUploadServer } }; public static readonly object[][] CompressedServers = { new object[] { RemoteDeflateServer }, new object[] { RemoteGZipServer }, new object[] { Http2RemoteDeflateServer }, new object[] { Http2RemoteGZipServer } }; @@ -83,9 +90,17 @@ public static partial class Http public static readonly RemoteServer RemoteSecureHttp11Server = new RemoteServer(new Uri("https://" + SecureHost + "/"), HttpVersion.Version11); public static readonly RemoteServer RemoteHttp2Server = new RemoteServer(new Uri("https://" + Http2Host + "/"), new Version(2, 0)); - public static readonly IEnumerable RemoteServers = new RemoteServer[] { RemoteHttp11Server, RemoteSecureHttp11Server, RemoteHttp2Server }; + public static IEnumerable GetRemoteServers() + { + if (PlatformDetection.IsFirefox) + { + // https://github.com/dotnet/runtime/issues/101115 + return new RemoteServer[] { RemoteHttp11Server }; + } + return new RemoteServer[] { RemoteHttp11Server, RemoteSecureHttp11Server, RemoteHttp2Server }; + } - public static readonly IEnumerable RemoteServersMemberData = RemoteServers.Select(s => new object[] { s }); + public static readonly IEnumerable RemoteServersMemberData = GetRemoteServers().Select(s => new object[] { s }); public sealed class RemoteServer { diff --git a/src/libraries/Common/tests/System/Net/Configuration.WebSockets.cs b/src/libraries/Common/tests/System/Net/Configuration.WebSockets.cs index a24512ce3b4a..c5686be67b4e 100644 --- a/src/libraries/Common/tests/System/Net/Configuration.WebSockets.cs +++ b/src/libraries/Common/tests/System/Net/Configuration.WebSockets.cs @@ -22,8 +22,35 @@ public static partial class WebSockets public static readonly Uri RemoteEchoHeadersServer = new Uri("ws://" + Host + "/" + EchoHeadersHandler); public static readonly Uri SecureRemoteEchoHeadersServer = new Uri("wss://" + SecureHost + "/" + EchoHeadersHandler); - public static readonly object[][] EchoServers = { new object[] { RemoteEchoServer }, new object[] { SecureRemoteEchoServer } }; - public static readonly object[][] EchoHeadersServers = { new object[] { RemoteEchoHeadersServer }, new object[] { SecureRemoteEchoHeadersServer } }; + public static object[][] GetEchoServers() + { + if (PlatformDetection.IsFirefox) + { + // https://github.com/dotnet/runtime/issues/101115 + return new object[][] { + new object[] { RemoteEchoServer }, + }; + } + return new object[][] { + new object[] { RemoteEchoServer }, + new object[] { SecureRemoteEchoServer }, + }; + } + + public static object[][] GetEchoHeadersServers() + { + if (PlatformDetection.IsFirefox) + { + // https://github.com/dotnet/runtime/issues/101115 + return new object[][] { + new object[] { RemoteEchoHeadersServer }, + }; + } + return new object[][] { + new object[] { RemoteEchoHeadersServer }, + new object[] { SecureRemoteEchoHeadersServer }, + }; + } } } } diff --git a/src/libraries/Common/tests/System/Net/Http/ByteAtATimeContent.cs b/src/libraries/Common/tests/System/Net/Http/ByteAtATimeContent.cs index d1b54ece613d..e0407d918acc 100644 --- a/src/libraries/Common/tests/System/Net/Http/ByteAtATimeContent.cs +++ b/src/libraries/Common/tests/System/Net/Http/ByteAtATimeContent.cs @@ -24,7 +24,7 @@ public ByteAtATimeContent(int length, Task waitToSend, TaskCompletionSource SerializeToStreamAsync(stream, context).GetAwaiter().GetResult(); #endif diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs index 9d6fef5fb3a7..5635b753a5f6 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs @@ -198,7 +198,6 @@ public async Task DisposeCurrentStream() await _currentStream.DisposeAsync().ConfigureAwait(false); _openStreams.Remove((int)_currentStreamId); _currentStream = null; - _currentStreamId = -4; } public override async Task ReadRequestBodyAsync() diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs index b19c02b52ebc..430cfeb2d472 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs @@ -546,7 +546,7 @@ public static IEnumerable ServerUsesWindowsAuthentication_MemberData() public static IEnumerable EchoServersData() { - foreach (Uri serverUri in Configuration.Http.EchoServerList) + foreach (Uri serverUri in Configuration.Http.GetEchoServerList()) { yield return new object[] { serverUri }; } diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ClientCertificates.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ClientCertificates.cs index 04a7414d0469..373928b90792 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ClientCertificates.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ClientCertificates.cs @@ -185,7 +185,6 @@ await LoopbackServer.CreateServerAsync(async (server, url) => }, options); } - [ActiveIssue("https://github.com/dotnet/runtime/issues/29419")] [Theory] [InlineData(ClientCertificateOption.Manual)] [InlineData(ClientCertificateOption.Automatic)] diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs index b2f03bfbc930..6ecd7261ca2d 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs @@ -44,7 +44,7 @@ private static CookieContainer CreateSingleCookieContainer(Uri uri, string cooki private static string GetCookieHeaderValue(string cookieName, string cookieValue) => $"{cookieName}={cookieValue}"; [Fact] - public async Task GetAsync_DefaultCoookieContainer_NoCookieSent() + public virtual async Task GetAsync_DefaultCoookieContainer_NoCookieSent() { await LoopbackServerFactory.CreateClientAndServerAsync( async uri => @@ -216,10 +216,15 @@ private string GetCookieValue(HttpRequestData request) return cookieHeaderValue; } - [Fact] + [ConditionalFact] [SkipOnPlatform(TestPlatforms.Browser, "CookieContainer is not supported on Browser")] public async Task GetAsync_SetCookieContainerAndCookieHeader_BothCookiesSent() { + if (UseVersion == HttpVersion30) + { + throw new SkipTestException("https://github.com/dotnet/runtime/issues/101377"); + } + await LoopbackServerFactory.CreateServerAsync(async (server, url) => { HttpClientHandler handler = CreateHttpClientHandler(); @@ -313,7 +318,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async url => using (HttpClient client = CreateHttpClient(handler)) { client.DefaultRequestHeaders.ConnectionClose = true; // to avoid issues with connection pooling - await client.GetAsync(url1); + await client.GetAsync(url1); } }, async server => diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs index 4da9edc2ca21..f45206e9941d 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs @@ -200,7 +200,7 @@ await server.AcceptConnectionAsync(async connection => } [Theory] -#if NETCOREAPP +#if NET [InlineData(DecompressionMethods.Brotli, "br", "")] [InlineData(DecompressionMethods.Brotli, "br", "br")] [InlineData(DecompressionMethods.Brotli, "br", "gzip")] @@ -264,7 +264,7 @@ await LoopbackServer.CreateServerAsync(async (server, url) => } [Theory] -#if NETCOREAPP +#if NET [InlineData(DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.Brotli, "gzip; q=1.0, deflate; q=1.0, br; q=1.0", "")] #endif [InlineData(DecompressionMethods.GZip | DecompressionMethods.Deflate, "gzip; q=1.0, deflate; q=1.0", "")] diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs index a264482a5549..dd9db9bbe1f0 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs @@ -47,7 +47,7 @@ private static IEnumerable GetMethods(params string[] methods) { foreach (string method in methods) { - foreach (Uri serverUri in Configuration.Http.EchoServerList) + foreach (Uri serverUri in Configuration.Http.GetEchoServerList()) { yield return new object[] { method, serverUri }; } @@ -164,6 +164,7 @@ public async Task GetAsync_ServerNeedsAuthAndSetCredential_StatusCodeOK(Configur [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))] [Theory, MemberData(nameof(RemoteServersMemberData))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task GetAsync_ServerNeedsAuthAndNoCredential_StatusCodeUnauthorized(Configuration.Http.RemoteServer remoteServer) { using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer)) @@ -275,7 +276,7 @@ public static IEnumerable RemoteServersHeaderValuesAndUris() public static IEnumerable<(Configuration.Http.RemoteServer remoteServer, Uri uri)> RemoteServersAndHeaderEchoUris() { - foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers) + foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.GetRemoteServers()) { yield return (remoteServer, remoteServer.EchoUri); yield return (remoteServer, remoteServer.RedirectUriForDestinationUri( @@ -464,7 +465,7 @@ public static IEnumerable VerifyUploadServersStreamsAndExpectedData { get { - foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers) // target server + foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.GetRemoteServers()) // target server foreach (bool syncCopy in BoolValues) // force the content copy to happen via Read/Write or ReadAsync/WriteAsync { byte[] data = new byte[1234]; @@ -868,7 +869,7 @@ public async Task SendAsync_SendRequestUsingNoBodyMethodToEchoServerWithContent_ public static IEnumerable SendAsync_SendSameRequestMultipleTimesDirectlyOnHandler_Success_MemberData() { - foreach (var server in Configuration.Http.RemoteServers) + foreach (var server in Configuration.Http.GetRemoteServers()) { yield return new object[] { server, "12345678910", 0 }; yield return new object[] { server, "12345678910", 5 }; @@ -909,7 +910,7 @@ public async Task SendAsync_SendSameRequestMultipleTimesDirectlyOnHandler_Succes public static IEnumerable RemoteServersAndRedirectStatusCodes() { - foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers) + foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.GetRemoteServers()) { yield return new object[] { remoteServer, 300 }; yield return new object[] { remoteServer, 301 }; @@ -1228,7 +1229,7 @@ public async Task DefaultHeaders_SetCredentials_ClearedOnRedirect(Configuration. public static IEnumerable RemoteServersAndCompressionUris() { - foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers) + foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.GetRemoteServers()) { yield return new object[] { remoteServer, remoteServer.GZipUri }; @@ -1329,6 +1330,7 @@ public async Task GetAsync_SetAutomaticDecompression_HeadersRemoved(Configuratio [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))] [Theory] [MemberData(nameof(Http2Servers))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task SendAsync_RequestVersion20_ResponseVersion20IfHttp2Supported(Uri server) { // Sync API supported only up to HTTP/1.1 diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs index eca2101b78ed..236af85b2603 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs @@ -116,7 +116,7 @@ public async Task UseCallback_NotSecureConnection_CallbackNotCalled() public static IEnumerable UseCallback_ValidCertificate_ExpectedValuesDuringCallback_Urls() { - foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers) + foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.GetRemoteServers()) { if (remoteServer.IsSecure) { diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs index 0ffd0d4ae82e..31d8d9f154fc 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs @@ -6,6 +6,9 @@ using System.Linq; using System.Net.Http.Headers; using System.Net.Sockets; +#if !NETFRAMEWORK +using System.Net.Quic; +#endif using System.Net.Test.Common; using System.Security.Authentication; using System.Security.Cryptography; @@ -267,7 +270,7 @@ await LoopbackServer.CreateClientAndServerAsync(async proxyUri => public static IEnumerable SecureAndNonSecure_IPBasedUri_MemberData() => from address in new[] { IPAddress.Loopback, IPAddress.IPv6Loopback } from useSsl in BoolValues - // we could not create SslStream in browser, [ActiveIssue("https://github.com/dotnet/runtime/issues/37669", TestPlatforms.Browser)] + // we could not create SslStream in browser, [ActiveIssue("https://github.com/dotnet/runtime/issues/37669", TestPlatforms.Browser)] where PlatformDetection.IsNotBrowser || !useSsl select new object[] { address, useSsl }; @@ -409,6 +412,7 @@ await LoopbackServer.CreateClientAndServerAsync(async uri => [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/86317", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task PostAsync_ManyDifferentRequestHeaders_SentCorrectly() { if (IsWinHttpHandler && UseVersion >= HttpVersion20.Value) @@ -823,6 +827,7 @@ await TestHelper.WhenAllCompletedOrAnyFailed( [InlineData("7gibberish")] // valid size then gibberish [InlineData("7\v\f")] // unacceptable whitespace [ActiveIssue("https://github.com/dotnet/runtime/issues/86317", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task GetAsync_InvalidChunkSize_ThrowsHttpRequestException(string chunkSize) { if (UseVersion != HttpVersion.Version11) @@ -856,6 +861,7 @@ await LoopbackServer.CreateServerAsync(async (server, url) => [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/86317", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task GetAsync_InvalidChunkTerminator_ThrowsHttpRequestException() { if (UseVersion != HttpVersion.Version11) @@ -877,14 +883,15 @@ await LoopbackServer.CreateClientAndServerAsync(async url => "\r\n" + "5\r\n" + "hello" + // missing \r\n terminator - //"5\r\n" + - //"world" + // missing \r\n terminator + //"5\r\n" + + //"world" + // missing \r\n terminator "0\r\n" + "\r\n")); } [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/86317", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task GetAsync_InfiniteChunkSize_ThrowsHttpRequestException() { if (UseVersion != HttpVersion.Version11) @@ -982,7 +989,7 @@ await connection.WriteStringAsync( }); } - [Theory] + [ConditionalTheory] [InlineData(true, true, true)] [InlineData(true, true, false)] [InlineData(true, false, false)] @@ -992,6 +999,11 @@ await connection.WriteStringAsync( [ActiveIssue("https://github.com/dotnet/runtime/issues/65429", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] public async Task ReadAsStreamAsync_HandlerProducesWellBehavedResponseStream(bool? chunked, bool enableWasmStreaming, bool slowChunks) { + if (UseVersion == HttpVersion30) + { + throw new SkipTestException("https://github.com/dotnet/runtime/issues/91757"); + } + if (IsWinHttpHandler && UseVersion >= HttpVersion20.Value) { return; @@ -1003,9 +1015,9 @@ public async Task ReadAsStreamAsync_HandlerProducesWellBehavedResponseStream(boo return; } - if (enableWasmStreaming && !PlatformDetection.IsBrowser) + if (enableWasmStreaming && !PlatformDetection.IsChromium) { - // enableWasmStreaming makes only sense on Browser platform + // enableWasmStreaming makes only sense on Chrome return; } @@ -1091,7 +1103,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => if (PlatformDetection.IsBrowser) { #if !NETFRAMEWORK - if(slowChunks) + if (slowChunks) { Assert.Equal(1, await responseStream.ReadAsync(new Memory(buffer2))); Assert.Equal((byte)'h', buffer2[0]); @@ -1201,7 +1213,7 @@ await server.AcceptConnectionAsync(async connection => { case true: await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] { new HttpHeaderData("Transfer-Encoding", "chunked") }, isFinal: false); - if(PlatformDetection.IsBrowser && slowChunks) + if (PlatformDetection.IsBrowser && slowChunks) { await connection.SendResponseBodyAsync("1\r\nh\r\n", false); await tcs.Task; @@ -1216,12 +1228,12 @@ await server.AcceptConnectionAsync(async connection => break; case false: - await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] { new HttpHeaderData("Content-Length", "11")}, content: "hello world"); + await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] { new HttpHeaderData("Content-Length", "11") }, content: "hello world"); break; case null: // This inject Content-Length header with null value to hint Loopback code to not include one automatically. - await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] { new HttpHeaderData("Content-Length", null)}, isFinal: false); + await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] { new HttpHeaderData("Content-Length", null) }, isFinal: false); await connection.SendResponseBodyAsync("hello world"); break; } @@ -1323,7 +1335,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => server => server.AcceptConnectionSendResponseAndCloseAsync()); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsChromium))] [ActiveIssue("https://github.com/dotnet/runtime/issues/65429", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] public async Task ReadAsStreamAsync_StreamingCancellation() { @@ -1396,6 +1408,12 @@ await server.AcceptConnectionAsync(async connection => await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] { new HttpHeaderData("Transfer-Encoding", "chunked") }, isFinal: false); await connection.SendResponseBodyAsync("1\r\nh\r\n", false); } +#if !NETFRAMEWORK + catch (QuicException ex) when (ex.ApplicationErrorCode == 0x10c /*H3_REQUEST_CANCELLED*/) + { + // The request was cancelled before we sent the body, ignore + } +#endif catch (IOException ex) { // when testing in the browser, we are using the WebSocket for the loopback @@ -1411,6 +1429,7 @@ await server.AcceptConnectionAsync(async connection => } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task Dispose_DisposingHandlerCancelsActiveOperationsWithoutResponses() { if (IsWinHttpHandler && UseVersion >= HttpVersion20.Value) @@ -1450,10 +1469,10 @@ await LoopbackServerFactory.CreateServerAsync(async (server3, url3) => Task serverTask3 = server3.AcceptConnectionAsync(async connection3 => { await connection3.ReadRequestDataAsync(); - await connection3.SendResponseAsync(HttpStatusCode.OK, new HttpHeaderData[] { new HttpHeaderData("Content-Length", "20") }, isFinal : false); - await connection3.SendResponseBodyAsync("1234567890", isFinal : false); + await connection3.SendResponseAsync(HttpStatusCode.OK, new HttpHeaderData[] { new HttpHeaderData("Content-Length", "20") }, isFinal: false); + await connection3.SendResponseBodyAsync("1234567890", isFinal: false); await unblockServers.Task; - await connection3.SendResponseBodyAsync("1234567890", isFinal : true); + await connection3.SendResponseBodyAsync("1234567890", isFinal: true); }); // Make three requests @@ -1527,7 +1546,7 @@ public async Task GetAsync_UnicodeHostName_SuccessStatusCodeInResponse() } } -#region Post Methods Tests + #region Post Methods Tests [Fact] [SkipOnPlatform(TestPlatforms.Browser, "ExpectContinue not supported on Browser")] @@ -1571,13 +1590,13 @@ await server.AcceptConnectionAsync(async connection => public static IEnumerable Interim1xxStatusCode() { - yield return new object[] { (HttpStatusCode) 100 }; // 100 Continue. + yield return new object[] { (HttpStatusCode)100 }; // 100 Continue. // 101 SwitchingProtocols will be treated as a final status code. - yield return new object[] { (HttpStatusCode) 102 }; // 102 Processing. - yield return new object[] { (HttpStatusCode) 103 }; // 103 EarlyHints. - yield return new object[] { (HttpStatusCode) 150 }; - yield return new object[] { (HttpStatusCode) 180 }; - yield return new object[] { (HttpStatusCode) 199 }; + yield return new object[] { (HttpStatusCode)102 }; // 102 Processing. + yield return new object[] { (HttpStatusCode)103 }; // 103 EarlyHints. + yield return new object[] { (HttpStatusCode)150 }; + yield return new object[] { (HttpStatusCode)180 }; + yield return new object[] { (HttpStatusCode)199 }; } [Theory] @@ -1638,7 +1657,7 @@ await server.AcceptConnectionAsync(async connection => new HttpHeaderData("Content-type", "text/xml"), new HttpHeaderData("Set-Cookie", SetCookieIgnored1)}, isFinal: false); - await connection.SendResponseAsync(responseStatusCode, headers: new HttpHeaderData[] { + await connection.SendResponseAsync(responseStatusCode, headers: new HttpHeaderData[] { new HttpHeaderData("Cookie", "ignore_cookie=choco2"), new HttpHeaderData("Content-type", "text/plain"), new HttpHeaderData("Set-Cookie", SetCookieIgnored2)}, isFinal: false); @@ -1742,7 +1761,7 @@ await server.AcceptConnectionAsync(async connection => { await connection.ReadRequestDataAsync(readBody: false); // Send multiple 100-Continue responses. - for (int count = 0 ; count < 4; count++) + for (int count = 0; count < 4; count++) { await connection.SendResponseAsync(HttpStatusCode.Continue, isFinal: false); } @@ -1846,7 +1865,7 @@ await server.AcceptConnectionAsync(async connection => { await connection.ReadRequestDataAsync(readBody: false); - await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] {new HttpHeaderData("Content-Length", $"{ResponseString.Length}")}, isFinal : false); + await connection.SendResponseAsync(HttpStatusCode.OK, headers: new HttpHeaderData[] { new HttpHeaderData("Content-Length", $"{ResponseString.Length}") }, isFinal: false); byte[] body = await connection.ReadRequestBodyAsync(); Assert.Equal(RequestString, Encoding.ASCII.GetString(body)); @@ -2127,7 +2146,7 @@ await LoopbackServerFactory.CreateServerAsync(async (server, rootUrl) => } }); } -#endregion + #endregion [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowserDomSupported))] public async Task GetAsync_InvalidUrl_ExpectedExceptionThrown() diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs index fdf301a809b8..689a6d6821eb 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; -#if !NETCOREAPP +#if !NET using System.Diagnostics; #endif using System.IO; @@ -90,7 +90,7 @@ public VersionCheckerHttpHandler(HttpMessageHandler innerHandler, Version expect _expectedVersion = expectedVersion; } -#if NETCOREAPP +#if NET protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) { if (request.Version != _expectedVersion) @@ -138,7 +138,7 @@ public static Task SendAsync(this HttpClient client, bool a } else { -#if NETCOREAPP +#if NET // Note that the sync call must be done on a different thread because it blocks until the server replies. // However, the server-side of the request handling is in many cases invoked after the client, thus deadlocking the test. return Task.Run(() => client.Send(request, completionOption, cancellationToken)); @@ -159,7 +159,7 @@ public static Task SendAsync(this HttpMessageInvoker invoke } else { -#if NETCOREAPP +#if NET // Note that the sync call must be done on a different thread because it blocks until the server replies. // However, the server-side of the request handling is in many cases invoked after the client, thus deadlocking the test. return Task.Run(() => invoker.Send(request, cancellationToken)); @@ -176,7 +176,7 @@ public static Task ReadAsStreamAsync(this HttpContent content, bool asyn { if (async) { -#if NETCOREAPP +#if NET // No CancellationToken accepting overload on NETFX. return content.ReadAsStreamAsync(cancellationToken); #else @@ -186,7 +186,7 @@ public static Task ReadAsStreamAsync(this HttpContent content, bool asyn } else { -#if NETCOREAPP +#if NET return Task.FromResult(content.ReadAsStream(cancellationToken)); #else // Framework won't ever have the sync API. @@ -199,7 +199,7 @@ public static Task ReadAsStreamAsync(this HttpContent content, bool asyn public static Task GetByteArrayAsync(this HttpClient client, bool async, bool useCopyTo, Uri uri) { -#if NETCOREAPP +#if NET return Task.Run(async () => { var m = new HttpRequestMessage(HttpMethod.Get, uri); diff --git a/src/libraries/Common/tests/System/Net/Http/HttpMessageHandlerLoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/HttpMessageHandlerLoopbackServer.cs index 9d9d412511ac..4b6a326cf6f5 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpMessageHandlerLoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpMessageHandlerLoopbackServer.cs @@ -60,7 +60,7 @@ public LoopbackServerHttpMessageHandler(Func RemoteServersAndLargeContentSizes() { - foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers) + foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.GetRemoteServers()) { yield return new object[] { remoteServer, 5 * 1024 }; yield return new object[] { remoteServer, 63 * 1024 }; diff --git a/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs b/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs index e38204ffc031..6e532aa23d95 100644 --- a/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs @@ -21,7 +21,7 @@ public ResponseStreamTest(ITestOutputHelper output) : base(output) { } public static IEnumerable RemoteServersAndReadModes() { - foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers) + foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.GetRemoteServers()) { for (int i = 0; i < 8; i++) { @@ -228,9 +228,9 @@ await client.GetAsync(remoteServer.EchoUri, HttpCompletionOption.ResponseHeaders } } -#if NETCOREAPP +#if NET - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsChromium))] public async Task BrowserHttpHandler_Streaming() { var WebAssemblyEnableStreamingRequestKey = new HttpRequestOptionsKey("WebAssemblyEnableStreamingRequest"); @@ -287,7 +287,7 @@ public async Task BrowserHttpHandler_Streaming() } [OuterLoop] - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsChromium))] public async Task BrowserHttpHandler_StreamingRequest() { var WebAssemblyEnableStreamingRequestKey = new HttpRequestOptionsKey("WebAssemblyEnableStreamingRequest"); @@ -330,7 +330,7 @@ public async Task BrowserHttpHandler_StreamingRequest() // Duplicate of PostAsync_ThrowFromContentCopy_RequestFails using remote server [OuterLoop] - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsChromium))] [InlineData(false)] [InlineData(true)] public async Task BrowserHttpHandler_StreamingRequest_ThrowFromContentCopy_RequestFails(bool syncFailure) @@ -368,7 +368,7 @@ public static TheoryData CancelRequestReadFunctions }; [OuterLoop] - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsChromium))] [MemberData(nameof(CancelRequestReadFunctions))] public async Task BrowserHttpHandler_StreamingRequest_CancelRequest(bool cancelAsync, Func> readFunc) { @@ -438,7 +438,7 @@ public async Task BrowserHttpHandler_StreamingRequest_Http1Fails() } [OuterLoop] - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsChromium))] public async Task BrowserHttpHandler_StreamingResponse() { var WebAssemblyEnableStreamingResponseKey = new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"); @@ -477,6 +477,7 @@ public async Task BrowserHttpHandler_StreamingResponse() [InlineData(TransferType.ContentLength, TransferError.ContentLengthTooLarge)] [InlineData(TransferType.Chunked, TransferError.MissingChunkTerminator)] [InlineData(TransferType.Chunked, TransferError.ChunkSizeTooLarge)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task ReadAsStreamAsync_InvalidServerResponse_ThrowsIOException( TransferType transferType, TransferError transferError) diff --git a/src/libraries/Common/tests/System/Net/Http/TestHelper.cs b/src/libraries/Common/tests/System/Net/Http/TestHelper.cs index c1d7a047070e..455f9581df33 100644 --- a/src/libraries/Common/tests/System/Net/Http/TestHelper.cs +++ b/src/libraries/Common/tests/System/Net/Http/TestHelper.cs @@ -96,7 +96,7 @@ public static Task WhenAllCompletedOrAnyFailedWithTimeout(int timeoutInMilliseco return TaskTimeoutExtensions.WhenAllOrAnyFailed(tasks, timeoutInMilliseconds); } -#if NETCOREAPP +#if NET public static Func AllowAllCertificates = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; #else public static Func AllowAllCertificates = (_, __, ___, ____) => true; @@ -149,7 +149,7 @@ public static X509Certificate2 CreateServerSelfSignedCertificate(string name = " } } -#if NETCOREAPP +#if NET public static SocketsHttpHandler CreateSocketsHttpHandler(bool allowAllCertificates = false) { var handler = new SocketsHttpHandler(); diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/LocalEchoServer.helix.targets b/src/libraries/Common/tests/System/Net/Prerequisites/LocalEchoServer.helix.targets index 80f1eb750e10..9db6642a48fe 100644 --- a/src/libraries/Common/tests/System/Net/Prerequisites/LocalEchoServer.helix.targets +++ b/src/libraries/Common/tests/System/Net/Prerequisites/LocalEchoServer.helix.targets @@ -1,7 +1,9 @@ + ('$(Scenario)' == 'WasmTestOnV8' or + '$(Scenario)' == 'WasmTestOnChrome' or + '$(Scenario)' == 'WasmTestOnFirefox' or + '$(Scenario)' == 'WasmTestOnNodeJS')"> $(HelixExtensionTargets);_AddMiddlewarePayload $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'bin', 'NetCoreServer', '$(Configuration)', '$(AspNetCoreAppCurrent)')) diff --git a/src/libraries/Common/tests/System/Runtime/Intrinsics/VectorTestMemberData.cs b/src/libraries/Common/tests/System/Runtime/Intrinsics/VectorTestMemberData.cs new file mode 100644 index 000000000000..ab2381a97967 --- /dev/null +++ b/src/libraries/Common/tests/System/Runtime/Intrinsics/VectorTestMemberData.cs @@ -0,0 +1,442 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; + +namespace System.Runtime.Intrinsics.Tests.Vectors +{ + internal static class VectorTestMemberData + { + // binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this + // is slightly too accurate when writing tests meant to run against libm implementations + // for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. + // + // The tests themselves will take CrossPlatformMachineEpsilon and adjust it according to the expected result + // so that the delta used for comparison will compare the most significant digits and ignore + // any digits that are outside the double precision range (15-17 digits). + // + // For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use + // CrossPlatformMachineEpsilon for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx + // will use CrossPlatformMachineEpsilon / 10 and expected result in the format of x.xxxxxxxxxxxxxxxx will + // use CrossPlatformMachineEpsilon * 10. + internal const double DoubleCrossPlatformMachineEpsilon = 8.8817841970012523e-16; + + // binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this + // is slightly too accurate when writing tests meant to run against libm implementations + // for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. + // + // The tests themselves will take CrossPlatformMachineEpsilon and adjust it according to the expected result + // so that the delta used for comparison will compare the most significant digits and ignore + // any digits that are outside the single precision range (6-9 digits). + // + // For example, a test with an expect result in the format of 0.xxxxxxxxx will use + // CrossPlatformMachineEpsilon for the variance, while an expected result in the format of 0.0xxxxxxxxx + // will use CrossPlatformMachineEpsilon / 10 and expected result in the format of x.xxxxxx will + // use CrossPlatformMachineEpsilon * 10. + private const float SingleCrossPlatformMachineEpsilon = 4.76837158e-07f; + + public static IEnumerable ExpDouble + { + get + { + yield return new object[] { double.NegativeInfinity, 0.0, 0.0 }; + yield return new object[] { -3.1415926535897932, 0.043213918263772250, DoubleCrossPlatformMachineEpsilon / 10 }; // value: -(pi) + yield return new object[] { -2.7182818284590452, 0.065988035845312537, DoubleCrossPlatformMachineEpsilon / 10 }; // value: -(e) + yield return new object[] { -2.3025850929940457, 0.1, DoubleCrossPlatformMachineEpsilon }; // value: -(ln(10)) + yield return new object[] { -1.5707963267948966, 0.20787957635076191, DoubleCrossPlatformMachineEpsilon }; // value: -(pi / 2) + yield return new object[] { -1.4426950408889634, 0.23629008834452270, DoubleCrossPlatformMachineEpsilon }; // value: -(log2(e)) + yield return new object[] { -1.4142135623730950, 0.24311673443421421, DoubleCrossPlatformMachineEpsilon }; // value: -(sqrt(2)) + yield return new object[] { -1.1283791670955126, 0.32355726390307110, DoubleCrossPlatformMachineEpsilon }; // value: -(2 / sqrt(pi)) + yield return new object[] { -1.0, 0.36787944117144232, DoubleCrossPlatformMachineEpsilon }; + yield return new object[] { -0.78539816339744831, 0.45593812776599624, DoubleCrossPlatformMachineEpsilon }; // value: -(pi / 4) + yield return new object[] { -0.70710678118654752, 0.49306869139523979, DoubleCrossPlatformMachineEpsilon }; // value: -(1 / sqrt(2)) + yield return new object[] { -0.69314718055994531, 0.5, 0.0 }; // value: -(ln(2)) + yield return new object[] { -0.63661977236758134, 0.52907780826773535, DoubleCrossPlatformMachineEpsilon }; // value: -(2 / pi) + yield return new object[] { -0.43429448190325183, 0.64772148514180065, DoubleCrossPlatformMachineEpsilon }; // value: -(log10(e)) + yield return new object[] { -0.31830988618379067, 0.72737734929521647, DoubleCrossPlatformMachineEpsilon }; // value: -(1 / pi) + yield return new object[] { -0.0, 1.0, 0.0 }; + yield return new object[] { double.NaN, double.NaN, 0.0 }; + yield return new object[] { 0.0, 1.0, 0.0 }; + yield return new object[] { 0.31830988618379067, 1.3748022274393586, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (1 / pi) + yield return new object[] { 0.43429448190325183, 1.5438734439711811, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (log10(e)) + yield return new object[] { 0.63661977236758134, 1.8900811645722220, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (2 / pi) + yield return new object[] { 0.69314718055994531, 2.0, 0.0 }; // value: (ln(2)) + yield return new object[] { 0.70710678118654752, 2.0281149816474725, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (1 / sqrt(2)) + yield return new object[] { 0.78539816339744831, 2.1932800507380155, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 4) + yield return new object[] { 1.0, 2.7182818284590452, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (e) + yield return new object[] { 1.1283791670955126, 3.0906430223107976, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (2 / sqrt(pi)) + yield return new object[] { 1.4142135623730950, 4.1132503787829275, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (sqrt(2)) + yield return new object[] { 1.4426950408889634, 4.2320861065570819, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (log2(e)) + yield return new object[] { 1.5707963267948966, 4.8104773809653517, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 2) + yield return new object[] { 2.3025850929940457, 10.0, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (ln(10)) + yield return new object[] { 2.7182818284590452, 15.154262241479264, DoubleCrossPlatformMachineEpsilon * 100 }; // value: (e) + yield return new object[] { 3.1415926535897932, 23.140692632779269, DoubleCrossPlatformMachineEpsilon * 100 }; // value: (pi) + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.0 }; + } + } + + public static IEnumerable ExpSingle + { + get + { + yield return new object[] { float.NegativeInfinity, 0.0f, 0.0f }; + yield return new object[] { -3.14159265f, 0.0432139183f, SingleCrossPlatformMachineEpsilon / 10 }; // value: -(pi) + yield return new object[] { -2.71828183f, 0.0659880358f, SingleCrossPlatformMachineEpsilon / 10 }; // value: -(e) + yield return new object[] { -2.30258509f, 0.1f, SingleCrossPlatformMachineEpsilon }; // value: -(ln(10)) + yield return new object[] { -1.57079633f, 0.207879576f, SingleCrossPlatformMachineEpsilon }; // value: -(pi / 2) + yield return new object[] { -1.44269504f, 0.236290088f, SingleCrossPlatformMachineEpsilon }; // value: -(log2(e)) + yield return new object[] { -1.41421356f, 0.243116734f, SingleCrossPlatformMachineEpsilon }; // value: -(sqrt(2)) + yield return new object[] { -1.12837917f, 0.323557264f, SingleCrossPlatformMachineEpsilon }; // value: -(2 / sqrt(pi)) + yield return new object[] { -1.0f, 0.367879441f, SingleCrossPlatformMachineEpsilon }; + yield return new object[] { -0.785398163f, 0.455938128f, SingleCrossPlatformMachineEpsilon }; // value: -(pi / 4) + yield return new object[] { -0.707106781f, 0.493068691f, SingleCrossPlatformMachineEpsilon }; // value: -(1 / sqrt(2)) + yield return new object[] { -0.693147181f, 0.5f, SingleCrossPlatformMachineEpsilon }; // value: -(ln(2)) + yield return new object[] { -0.636619772f, 0.529077808f, SingleCrossPlatformMachineEpsilon }; // value: -(2 / pi) + yield return new object[] { -0.434294482f, 0.647721485f, SingleCrossPlatformMachineEpsilon }; // value: -(log10(e)) + yield return new object[] { -0.318309886f, 0.727377349f, SingleCrossPlatformMachineEpsilon }; // value: -(1 / pi) + yield return new object[] { -0.0f, 1.0f, SingleCrossPlatformMachineEpsilon * 10 }; + yield return new object[] { float.NaN, float.NaN, 0.0f }; + yield return new object[] { 0.0f, 1.0f, SingleCrossPlatformMachineEpsilon * 10 }; + yield return new object[] { 0.318309886f, 1.37480223f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (1 / pi) + yield return new object[] { 0.434294482f, 1.54387344f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (log10(e)) + yield return new object[] { 0.636619772f, 1.89008116f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (2 / pi) + yield return new object[] { 0.693147181f, 2.0f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (ln(2)) + yield return new object[] { 0.707106781f, 2.02811498f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (1 / sqrt(2)) + yield return new object[] { 0.785398163f, 2.19328005f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 4) + yield return new object[] { 1.0f, 2.71828183f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (e) + yield return new object[] { 1.12837917f, 3.09064302f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (2 / sqrt(pi)) + yield return new object[] { 1.41421356f, 4.11325038f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (sqrt(2)) + yield return new object[] { 1.44269504f, 4.23208611f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (log2(e)) + yield return new object[] { 1.57079633f, 4.81047738f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 2) + yield return new object[] { 2.30258509f, 10.0f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (ln(10)) + yield return new object[] { 2.71828183f, 15.1542622f, SingleCrossPlatformMachineEpsilon * 100 }; // value: (e) + yield return new object[] { 3.14159265f, 23.1406926f, SingleCrossPlatformMachineEpsilon * 100 }; // value: (pi) + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.0f }; + } + } + + public static IEnumerable LogDouble + { + get + { + yield return new object[] { double.NegativeInfinity, double.NaN, 0.0 }; + yield return new object[] { -3.1415926535897932, double.NaN, 0.0 }; // value: -(pi) + yield return new object[] { -2.7182818284590452, double.NaN, 0.0 }; // value: -(e) + yield return new object[] { -1.4142135623730950, double.NaN, 0.0 }; // value: -(sqrt(2)) + yield return new object[] { -1.0, double.NaN, 0.0 }; + yield return new object[] { -0.69314718055994531, double.NaN, 0.0 }; // value: -(ln(2)) + yield return new object[] { -0.43429448190325183, double.NaN, 0.0 }; // value: -(log10(e)) + yield return new object[] { -0.0, double.NegativeInfinity, 0.0 }; + yield return new object[] { double.NaN, double.NaN, 0.0 }; + yield return new object[] { 0.0, double.NegativeInfinity, 0.0 }; + yield return new object[] { 0.043213918263772250, -3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) + yield return new object[] { 0.065988035845312537, -2.7182818284590452, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) + yield return new object[] { 0.1, -2.3025850929940457, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) + yield return new object[] { 0.20787957635076191, -1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) + yield return new object[] { 0.23629008834452270, -1.4426950408889634, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) + yield return new object[] { 0.24311673443421421, -1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) + yield return new object[] { 0.32355726390307110, -1.1283791670955126, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) + yield return new object[] { 0.36787944117144232, -1.0, 0.0f }; + yield return new object[] { 0.45593812776599624, -0.78539816339744831, DoubleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) + yield return new object[] { 0.49306869139523979, -0.70710678118654752, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) + yield return new object[] { 0.5, -0.69314718055994531, DoubleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) + yield return new object[] { 0.52907780826773535, -0.63661977236758134, DoubleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) + yield return new object[] { 0.64772148514180065, -0.43429448190325183, DoubleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) + yield return new object[] { 0.72737734929521647, -0.31830988618379067, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) + yield return new object[] { 1.0, 0.0, 0.0 }; + yield return new object[] { 1.3748022274393586, 0.31830988618379067, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / pi) + yield return new object[] { 1.5438734439711811, 0.43429448190325183, DoubleCrossPlatformMachineEpsilon }; // expected: (log10(e)) + yield return new object[] { 1.8900811645722220, 0.63661977236758134, DoubleCrossPlatformMachineEpsilon }; // expected: (2 / pi) + yield return new object[] { 2.0, 0.69314718055994531, DoubleCrossPlatformMachineEpsilon }; // expected: (ln(2)) + yield return new object[] { 2.0281149816474725, 0.70710678118654752, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) + yield return new object[] { 2.1932800507380155, 0.78539816339744831, DoubleCrossPlatformMachineEpsilon }; // expected: (pi / 4) + yield return new object[] { 2.7182818284590452, 1.0, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (e) + yield return new object[] { 3.0906430223107976, 1.1283791670955126, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) + yield return new object[] { 4.1132503787829275, 1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) + yield return new object[] { 4.2320861065570819, 1.4426950408889634, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) + yield return new object[] { 4.8104773809653517, 1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) + yield return new object[] { 10.0, 2.3025850929940457, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) + yield return new object[] { 15.154262241479264, 2.7182818284590452, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (e) + yield return new object[] { 23.140692632779269, 3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.0 }; + } + } + + public static IEnumerable LogSingle + { + get + { + yield return new object[] { float.NegativeInfinity, float.NaN, 0.0f }; + yield return new object[] { -3.14159265f, float.NaN, 0.0f }; // value: -(pi) + yield return new object[] { -2.71828183f, float.NaN, 0.0f }; // value: -(e) + yield return new object[] { -1.41421356f, float.NaN, 0.0f }; // value: -(sqrt(2)) + yield return new object[] { -1.0f, float.NaN, 0.0f }; + yield return new object[] { -0.693147181f, float.NaN, 0.0f }; // value: -(ln(2)) + yield return new object[] { -0.434294482f, float.NaN, 0.0f }; // value: -(log10(e)) + yield return new object[] { -0.0f, float.NegativeInfinity, 0.0f }; + yield return new object[] { float.NaN, float.NaN, 0.0f }; + yield return new object[] { 0.0f, float.NegativeInfinity, 0.0f }; + yield return new object[] { 0.0432139183f, -3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) + yield return new object[] { 0.0659880358f, -2.71828183f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) + yield return new object[] { 0.1f, -2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) + yield return new object[] { 0.207879576f, -1.57079633f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) + yield return new object[] { 0.236290088f, -1.44269504f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) + yield return new object[] { 0.243116734f, -1.41421356f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) + yield return new object[] { 0.323557264f, -1.12837917f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) + yield return new object[] { 0.367879441f, -1.0f, 0.0f }; + yield return new object[] { 0.455938128f, -0.785398163f, SingleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) + yield return new object[] { 0.493068691f, -0.707106781f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) + yield return new object[] { 0.5f, -0.693147181f, SingleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) + yield return new object[] { 0.529077808f, -0.636619772f, SingleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) + yield return new object[] { 0.647721485f, -0.434294482f, SingleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) + yield return new object[] { 0.727377349f, -0.318309886f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) + yield return new object[] { 1.0f, 0.0f, 0.0f }; + yield return new object[] { 1.37480223f, 0.318309886f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / pi) + yield return new object[] { 1.54387344f, 0.434294482f, SingleCrossPlatformMachineEpsilon }; // expected: (log10(e)) + yield return new object[] { 1.89008116f, 0.636619772f, SingleCrossPlatformMachineEpsilon }; // expected: (2 / pi) + yield return new object[] { 2.0f, 0.693147181f, SingleCrossPlatformMachineEpsilon }; // expected: (ln(2)) + yield return new object[] { 2.02811498f, 0.707106781f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) + yield return new object[] { 2.19328005f, 0.785398163f, SingleCrossPlatformMachineEpsilon }; // expected: (pi / 4) + yield return new object[] { 2.71828183f, 1.0f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (e) + yield return new object[] { 3.09064302f, 1.12837917f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) + yield return new object[] { 4.11325038f, 1.41421356f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) + yield return new object[] { 4.23208611f, 1.44269504f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) + yield return new object[] { 4.81047738f, 1.57079633f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) + yield return new object[] { 10.0f, 2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) + yield return new object[] { 15.1542622f, 2.71828183f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (e) + yield return new object[] { 23.1406926f, 3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.0f }; + } + } + + public static IEnumerable Log2Double + { + get + { + yield return new object[] { double.NegativeInfinity, double.NaN, 0.0 }; + yield return new object[] {-0.11331473229676087, double.NaN, 0.0 }; + yield return new object[] {-0.0, double.NegativeInfinity, 0.0 }; + yield return new object[] { double.NaN, double.NaN, 0.0 }; + yield return new object[] { 0.0, double.NegativeInfinity, 0.0 }; + yield return new object[] { 0.11331473229676087, -3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) + yield return new object[] { 0.15195522325791297, -2.7182818284590453, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) + yield return new object[] { 0.20269956628651730, -2.3025850929940460, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) + yield return new object[] { 0.33662253682241906, -1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) + yield return new object[] { 0.36787944117144232, -1.4426950408889634, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) + yield return new object[] { 0.37521422724648177, -1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) + yield return new object[] { 0.45742934732229695, -1.1283791670955126, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) + yield return new object[] { 0.5, -1.0, 0.0f }; + yield return new object[] { 0.58019181037172444, -0.78539816339744840, DoubleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) + yield return new object[] { 0.61254732653606592, -0.70710678118654750, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) + yield return new object[] { 0.61850313780157598, -0.69314718055994537, DoubleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) + yield return new object[] { 0.64321824193300488, -0.63661977236758126, DoubleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) + yield return new object[] { 0.74005557395545179, -0.43429448190325190, DoubleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) + yield return new object[] { 0.80200887896145195, -0.31830988618379073, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) + yield return new object[] { 1, 0.0, 0.0 }; + yield return new object[] { 1.2468689889006383, 0.31830988618379073, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / pi) + yield return new object[] { 1.3512498725672678, 0.43429448190325226, DoubleCrossPlatformMachineEpsilon }; // expected: (log10(e)) + yield return new object[] { 1.5546822754821001, 0.63661977236758126, DoubleCrossPlatformMachineEpsilon }; // expected: (2 / pi) + yield return new object[] { 1.6168066722416747, 0.69314718055994537, DoubleCrossPlatformMachineEpsilon }; // expected: (ln(2)) + yield return new object[] { 1.6325269194381528, 0.70710678118654750, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) + yield return new object[] { 1.7235679341273495, 0.78539816339744830, DoubleCrossPlatformMachineEpsilon }; // expected: (pi / 4) + yield return new object[] { 2, 1.0, 0.0 }; // value: (e) + yield return new object[] { 2.1861299583286618, 1.1283791670955128, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) + yield return new object[] { 2.6651441426902252, 1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) + yield return new object[] { 2.7182818284590452, 1.4426950408889632, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) + yield return new object[] { 2.9706864235520193, 1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) + yield return new object[] { 4.9334096679145963, 2.3025850929940460, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) + yield return new object[] { 6.5808859910179210, 2.7182818284590455, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (e) + yield return new object[] { 8.8249778270762876, 3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.0 }; + } + } + + public static IEnumerable Log2Single + { + get + { + yield return new object[] { float.NegativeInfinity, float.NaN, 0.0f }; + yield return new object[] { -0.113314732f, float.NaN, 0.0f }; + yield return new object[] { -0.0f, float.NegativeInfinity, 0.0f }; + yield return new object[] { float.NaN, float.NaN, 0.0f }; + yield return new object[] { 0.0f, float.NegativeInfinity, 0.0f }; + yield return new object[] { 0.113314732f, -3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) + yield return new object[] { 0.151955223f, -2.71828200f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) + yield return new object[] { 0.202699566f, -2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) + yield return new object[] { 0.336622537f, -1.57079630f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) + yield return new object[] { 0.367879441f, -1.44269500f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) + yield return new object[] { 0.375214227f, -1.41421360f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) + yield return new object[] { 0.457429347f, -1.12837910f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) + yield return new object[] { 0.5f, -1.0f, 0.0f }; + yield return new object[] { 0.580191810f, -0.785398211f, SingleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) + yield return new object[] { 0.612547327f, -0.707106700f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) + yield return new object[] { 0.618503138f, -0.693147144f, SingleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) + yield return new object[] { 0.643218242f, -0.636619823f, SingleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) + yield return new object[] { 0.740055574f, -0.434294550f, SingleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) + yield return new object[] { 0.802008879f, -0.318309900f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) + yield return new object[] { 1, 0.0f, 0.0f }; + yield return new object[] { 1.24686899f, 0.318309870f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / pi) + yield return new object[] { 1.35124987f, 0.434294340f, SingleCrossPlatformMachineEpsilon }; // expected: (log10(e)) + yield return new object[] { 1.55468228f, 0.636619823f, SingleCrossPlatformMachineEpsilon }; // expected: (2 / pi) + yield return new object[] { 1.61680667f, 0.693147144f, SingleCrossPlatformMachineEpsilon }; // expected: (ln(2)) + yield return new object[] { 1.63252692f, 0.707106700f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) + yield return new object[] { 1.72356793f, 0.785398211f, SingleCrossPlatformMachineEpsilon }; // expected: (pi / 4) + yield return new object[] { 2, 1.0f, 0.0f }; // value: (e) + yield return new object[] { 2.18612996f, 1.12837920f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) + yield return new object[] { 2.66514414f, 1.41421360f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) + yield return new object[] { 2.71828183f, 1.44269490f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) + yield return new object[] { 2.97068642f, 1.57079630f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) + yield return new object[] { 4.93340967f, 2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) + yield return new object[] { 6.58088599f, 2.71828170f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (e) + yield return new object[] { 8.82497783f, 3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.0f }; + } + } + + public static IEnumerable MultiplyAddDouble + { + get + { + yield return new object[] { double.NegativeInfinity, double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { double.NegativeInfinity, -0.0, double.NegativeInfinity }; + yield return new object[] { double.NegativeInfinity, -0.0, -3.1415926535897932 }; + yield return new object[] { double.NegativeInfinity, -0.0, -0.0 }; + yield return new object[] { double.NegativeInfinity, -0.0, double.NaN }; + yield return new object[] { double.NegativeInfinity, -0.0, 0.0 }; + yield return new object[] { double.NegativeInfinity, -0.0, 3.1415926535897932 }; + yield return new object[] { double.NegativeInfinity, -0.0, double.PositiveInfinity }; + yield return new object[] { double.NegativeInfinity, 0.0, double.NegativeInfinity }; + yield return new object[] { double.NegativeInfinity, 0.0, -3.1415926535897932 }; + yield return new object[] { double.NegativeInfinity, 0.0, -0.0 }; + yield return new object[] { double.NegativeInfinity, 0.0, double.NaN }; + yield return new object[] { double.NegativeInfinity, 0.0, 0.0 }; + yield return new object[] { double.NegativeInfinity, 0.0, 3.1415926535897932 }; + yield return new object[] { double.NegativeInfinity, 0.0, double.PositiveInfinity }; + yield return new object[] { double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] {-1e308, 2.0, 1e308 }; + yield return new object[] {-1e308, 2.0, double.PositiveInfinity }; + yield return new object[] {-5, 4, -3 }; + yield return new object[] {-0.0, double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] {-0.0, double.NegativeInfinity, -3.1415926535897932 }; + yield return new object[] {-0.0, double.NegativeInfinity, -0.0 }; + yield return new object[] {-0.0, double.NegativeInfinity, double.NaN }; + yield return new object[] {-0.0, double.NegativeInfinity, 0.0 }; + yield return new object[] {-0.0, double.NegativeInfinity, 3.1415926535897932 }; + yield return new object[] {-0.0, double.NegativeInfinity, double.PositiveInfinity }; + yield return new object[] {-0.0, double.PositiveInfinity, double.NegativeInfinity }; + yield return new object[] {-0.0, double.PositiveInfinity, -3.1415926535897932 }; + yield return new object[] {-0.0, double.PositiveInfinity, -0.0 }; + yield return new object[] {-0.0, double.PositiveInfinity, double.NaN }; + yield return new object[] {-0.0, double.PositiveInfinity, 0.0 }; + yield return new object[] {-0.0, double.PositiveInfinity, 3.1415926535897932 }; + yield return new object[] {-0.0, double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] { 0.0, double.NegativeInfinity, double.NegativeInfinity }; + yield return new object[] { 0.0, double.NegativeInfinity, -3.1415926535897932 }; + yield return new object[] { 0.0, double.NegativeInfinity, -0.0 }; + yield return new object[] { 0.0, double.NegativeInfinity, double.NaN }; + yield return new object[] { 0.0, double.NegativeInfinity, 0.0 }; + yield return new object[] { 0.0, double.NegativeInfinity, 3.1415926535897932 }; + yield return new object[] { 0.0, double.NegativeInfinity, double.PositiveInfinity }; + yield return new object[] { 0.0, double.PositiveInfinity, double.NegativeInfinity }; + yield return new object[] { 0.0, double.PositiveInfinity, -3.1415926535897932 }; + yield return new object[] { 0.0, double.PositiveInfinity, -0.0 }; + yield return new object[] { 0.0, double.PositiveInfinity, double.NaN }; + yield return new object[] { 0.0, double.PositiveInfinity, 0.0 }; + yield return new object[] { 0.0, double.PositiveInfinity, 3.1415926535897932 }; + yield return new object[] { 0.0, double.PositiveInfinity, double.PositiveInfinity }; + yield return new object[] { 5, 4, 3 }; + yield return new object[] { 1e308, 2.0, -1e308 }; + yield return new object[] { 1e308, 2.0, double.NegativeInfinity }; + yield return new object[] { double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity }; + yield return new object[] { double.PositiveInfinity, -0.0, double.NegativeInfinity }; + yield return new object[] { double.PositiveInfinity, -0.0, -3.1415926535897932 }; + yield return new object[] { double.PositiveInfinity, -0.0, -0.0 }; + yield return new object[] { double.PositiveInfinity, -0.0, double.NaN }; + yield return new object[] { double.PositiveInfinity, -0.0, 0.0 }; + yield return new object[] { double.PositiveInfinity, -0.0, 3.1415926535897932 }; + yield return new object[] { double.PositiveInfinity, -0.0, double.PositiveInfinity }; + yield return new object[] { double.PositiveInfinity, 0.0, double.NegativeInfinity }; + yield return new object[] { double.PositiveInfinity, 0.0, -3.1415926535897932 }; + yield return new object[] { double.PositiveInfinity, 0.0, -0.0 }; + yield return new object[] { double.PositiveInfinity, 0.0, double.NaN }; + yield return new object[] { double.PositiveInfinity, 0.0, 0.0 }; + yield return new object[] { double.PositiveInfinity, 0.0, 3.1415926535897932 }; + yield return new object[] { double.PositiveInfinity, 0.0, double.PositiveInfinity }; + yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, double.NegativeInfinity }; + } + } + + public static IEnumerable MultiplyAddSingle + { + get + { + yield return new object[] { float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { float.NegativeInfinity, -0.0f, float.NegativeInfinity }; + yield return new object[] { float.NegativeInfinity, -0.0f, -3.14159265f }; + yield return new object[] { float.NegativeInfinity, -0.0f, -0.0f }; + yield return new object[] { float.NegativeInfinity, -0.0f, float.NaN }; + yield return new object[] { float.NegativeInfinity, -0.0f, 0.0f }; + yield return new object[] { float.NegativeInfinity, -0.0f, 3.14159265f }; + yield return new object[] { float.NegativeInfinity, -0.0f, float.PositiveInfinity }; + yield return new object[] { float.NegativeInfinity, 0.0f, float.NegativeInfinity }; + yield return new object[] { float.NegativeInfinity, 0.0f, -3.14159265f }; + yield return new object[] { float.NegativeInfinity, 0.0f, -0.0f }; + yield return new object[] { float.NegativeInfinity, 0.0f, float.NaN }; + yield return new object[] { float.NegativeInfinity, 0.0f, 0.0f }; + yield return new object[] { float.NegativeInfinity, 0.0f, 3.14159265f }; + yield return new object[] { float.NegativeInfinity, 0.0f, float.PositiveInfinity }; + yield return new object[] { float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { -1e38f, 2.0f, 1e38f }; + yield return new object[] { -1e38f, 2.0f, float.PositiveInfinity }; + yield return new object[] { -5, 4, -3 }; + yield return new object[] { -0.0f, float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { -0.0f, float.NegativeInfinity, -3.14159265f }; + yield return new object[] { -0.0f, float.NegativeInfinity, -0.0f }; + yield return new object[] { -0.0f, float.NegativeInfinity, float.NaN }; + yield return new object[] { -0.0f, float.NegativeInfinity, 0.0f }; + yield return new object[] { -0.0f, float.NegativeInfinity, 3.14159265f }; + yield return new object[] { -0.0f, float.NegativeInfinity, float.PositiveInfinity }; + yield return new object[] { -0.0f, float.PositiveInfinity, float.NegativeInfinity }; + yield return new object[] { -0.0f, float.PositiveInfinity, -3.14159265f }; + yield return new object[] { -0.0f, float.PositiveInfinity, -0.0f }; + yield return new object[] { -0.0f, float.PositiveInfinity, float.NaN }; + yield return new object[] { -0.0f, float.PositiveInfinity, 0.0f }; + yield return new object[] { -0.0f, float.PositiveInfinity, 3.14159265f }; + yield return new object[] { -0.0f, float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { 0.0f, float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { 0.0f, float.NegativeInfinity, -3.14159265f }; + yield return new object[] { 0.0f, float.NegativeInfinity, -0.0f }; + yield return new object[] { 0.0f, float.NegativeInfinity, float.NaN }; + yield return new object[] { 0.0f, float.NegativeInfinity, 0.0f }; + yield return new object[] { 0.0f, float.NegativeInfinity, 3.14159265f }; + yield return new object[] { 0.0f, float.NegativeInfinity, float.PositiveInfinity }; + yield return new object[] { 0.0f, float.PositiveInfinity, float.NegativeInfinity }; + yield return new object[] { 0.0f, float.PositiveInfinity, -3.14159265f }; + yield return new object[] { 0.0f, float.PositiveInfinity, -0.0f }; + yield return new object[] { 0.0f, float.PositiveInfinity, float.NaN }; + yield return new object[] { 0.0f, float.PositiveInfinity, 0.0f }; + yield return new object[] { 0.0f, float.PositiveInfinity, 3.14159265f }; + yield return new object[] { 0.0f, float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { 5, 4, 3 }; + yield return new object[] { 1e38f, 2.0f, -1e38f }; + yield return new object[] { 1e38f, 2.0f, float.NegativeInfinity }; + yield return new object[] { float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity }; + yield return new object[] { float.PositiveInfinity, -0.0f, float.NegativeInfinity }; + yield return new object[] { float.PositiveInfinity, -0.0f, -3.14159265f }; + yield return new object[] { float.PositiveInfinity, -0.0f, -0.0f }; + yield return new object[] { float.PositiveInfinity, -0.0f, float.NaN }; + yield return new object[] { float.PositiveInfinity, -0.0f, 0.0f }; + yield return new object[] { float.PositiveInfinity, -0.0f, 3.14159265f }; + yield return new object[] { float.PositiveInfinity, -0.0f, float.PositiveInfinity }; + yield return new object[] { float.PositiveInfinity, 0.0f, float.NegativeInfinity }; + yield return new object[] { float.PositiveInfinity, 0.0f, -3.14159265f }; + yield return new object[] { float.PositiveInfinity, 0.0f, -0.0f }; + yield return new object[] { float.PositiveInfinity, 0.0f, float.NaN }; + yield return new object[] { float.PositiveInfinity, 0.0f, 0.0f }; + yield return new object[] { float.PositiveInfinity, 0.0f, 3.14159265f }; + yield return new object[] { float.PositiveInfinity, 0.0f, float.PositiveInfinity }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, float.NegativeInfinity }; + } + } + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs index cd8bf922227c..6ad596a040c4 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs @@ -75,7 +75,7 @@ public void InvalidArrayArguments_Throws() } } -#if NETCOREAPP +#if NET [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst, "Not supported on Browser/iOS/tvOS/MacCatalyst")] public sealed class DSASignVerify_Span : DSASignVerify { diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/CurveDef.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/CurveDef.cs index a49b2c3329b7..b0c5823145a8 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/CurveDef.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/CurveDef.cs @@ -5,7 +5,7 @@ namespace System.Security.Cryptography.Tests { public class CurveDef { -#if NETCOREAPP +#if NET public CurveDef() { } public ECCurve Curve; public ECCurve.ECCurveType CurveType; diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/EccTestBase.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/EccTestBase.cs index 5f9dae4c8fce..8cc2391ba8dc 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/EccTestBase.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/EccTestBase.cs @@ -15,7 +15,7 @@ namespace System.Security.Cryptography.Tests /// public abstract class EccTestBase { -#if NETCOREAPP +#if NET internal const string ECDSA_P224_OID_VALUE = "1.3.132.0.33"; // Also called nistP224 or secP224r1 internal const string ECDSA_P256_OID_VALUE = "1.2.840.10045.3.1.7"; // Also called nistP256, secP256r1 or prime256v1(OpenSsl) internal const string ECDSA_P384_OID_VALUE = "1.3.132.0.34"; // Also called nistP384 or secP384r1 diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanFactory.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanFactory.cs index 84bbea4587ee..9a2de091ab3b 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanFactory.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanFactory.cs @@ -7,7 +7,7 @@ public interface IECDiffieHellmanProvider { ECDiffieHellman Create(); ECDiffieHellman Create(int keySize); -#if NETCOREAPP +#if NET ECDiffieHellman Create(ECCurve curve); #endif bool IsCurveValid(Oid oid); @@ -29,7 +29,7 @@ public static ECDiffieHellman Create(int keySize) return s_provider.Create(keySize); } -#if NETCOREAPP +#if NET public static ECDiffieHellman Create(ECCurve curve) { return s_provider.Create(curve); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hash.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hash.cs index 0065092e52aa..ae8d32b02cc6 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hash.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hash.cs @@ -290,7 +290,7 @@ public static IEnumerable HashDerivationTestCases() } } -#if NETCOREAPP +#if NET [Theory] [MemberData(nameof(HashDerivationTestCases))] public static void HashDerivation_KnownResults( diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hmac.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hmac.cs index f95fb64aafd3..575a9d853fe2 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hmac.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Hmac.cs @@ -349,7 +349,7 @@ public static IEnumerable HmacDerivationTestCases() } } -#if NETCOREAPP +#if NET [Theory] [MemberData(nameof(HmacDerivationTestCases))] public static void HmacDerivation_KnownResults( diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs index 82f78094bb10..1c507beee0d8 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs @@ -8,7 +8,7 @@ namespace System.Security.Cryptography.EcDiffieHellman.Tests { -#if NETCOREAPP +#if NET public partial class ECDiffieHellmanTests { // On CentOS, secp224r1 (also called nistP224) appears to be disabled. To prevent test failures on that platform, diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.NistValidation.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.NistValidation.cs index d79d8de3edba..ce07c475bec5 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.NistValidation.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.NistValidation.cs @@ -8,7 +8,7 @@ namespace System.Security.Cryptography.EcDiffieHellman.Tests { -#if NETCOREAPP +#if NET // These test cases are from http://csrc.nist.gov/groups/STM/cavp/component-testing.html#test-vectors // SP 800-56A ECCCDH Primitive test vectors // ecccdhtestvectors.zip diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Tls.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Tls.cs index 4bffb87b2dd1..d8c6e8f0ff06 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Tls.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.Tls.cs @@ -189,7 +189,7 @@ public static IEnumerable TlsDerivationTestCases() }; } -#if NETCOREAPP +#if NET [Theory] [MemberData(nameof(TlsDerivationTestCases))] public static void TlsDerivation_KnownResults(string labelText, string answerHex) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.cs index 0b41aa08ea28..dc7a757d6e53 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.cs @@ -172,7 +172,7 @@ public static void UseAfterDispose(bool importKey) pubKey.Dispose(); } -#if NETCOREAPP +#if NET private static ECDiffieHellman OpenKnownKey() { ECParameters ecParams = new ECParameters diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaFactory.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaFactory.cs index 59d45d3de99c..01e5dfe6701f 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaFactory.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaFactory.cs @@ -7,7 +7,7 @@ public interface IECDsaProvider { ECDsa Create(); ECDsa Create(int keySize); -#if NETCOREAPP +#if NET ECDsa Create(ECCurve curve); #endif bool IsCurveValid(Oid oid); @@ -26,7 +26,7 @@ public static ECDsa Create(int keySize) return s_provider.Create(keySize); } -#if NETCOREAPP +#if NET public static ECDsa Create(ECCurve curve) { return s_provider.Create(curve); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs index 1925320e66ab..058b626c62c8 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs @@ -15,7 +15,7 @@ public class ECDsaImportExportTests : ECDsaTestsBase internal static bool CanDeriveNewPublicKey { get; } = EcDiffieHellman.Tests.ECDiffieHellmanFactory.CanDeriveNewPublicKey; -#if NETCOREAPP +#if NET [Fact] public static void DiminishedCoordsRoundtrip() { diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaStub.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaStub.cs index b40f4e721a49..43c44b71a2a2 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaStub.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaStub.cs @@ -30,7 +30,7 @@ protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) throw new NotImplementedException(); } -#if NETCOREAPP +#if NET public override void ImportParameters(ECParameters parameters) { throw new NotImplementedException(); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.NistValidation.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.NistValidation.cs index d0c596935ef0..e0da3f3e75a8 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.NistValidation.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.NistValidation.cs @@ -13,7 +13,7 @@ public abstract partial class ECDsaTests : ECDsaTestsBase // FIPS 186-4 ECDSA test vectors // 186-3ecdsatestvectors.zip // SigGen.txt -#if NETCOREAPP +#if NET [Fact] public void ValidateNistP256Sha256() { diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs index 9da985adfd21..9c2e3fc0b44a 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs @@ -15,7 +15,7 @@ namespace System.Security.Cryptography.EcDsa.Tests [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] public abstract class ECDsaTestsBase : EccTestBase { -#if NETCOREAPP +#if NET internal static void Verify256(ECDsa e, bool expected) { byte[] sig = ("998791331eb2e1f4259297f5d9cb82fa20dec98e1cb0900e6b8f014a406c3d02cbdbf5238bde471c3155fc25565524301429" diff --git a/src/libraries/Common/tests/System/Security/Cryptography/PlatformSupport.cs b/src/libraries/Common/tests/System/Security/Cryptography/PlatformSupport.cs index ae9f09caf23a..7be1321023e2 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/PlatformSupport.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/PlatformSupport.cs @@ -74,7 +74,7 @@ static bool DetermineAlgorithmFunctional(CngAlgorithm algorithm) // Whether or not the current platform supports RC2 internal static readonly bool IsRC2Supported = !PlatformDetection.IsAndroid; -#if NETCOREAPP +#if NET internal static readonly bool IsAndroidVersionAtLeast31 = OperatingSystem.IsAndroidVersionAtLeast(31); #else internal static readonly bool IsAndroidVersionAtLeast31 = false; diff --git a/src/libraries/Common/tests/System/TimeProviderTests.cs b/src/libraries/Common/tests/System/TimeProviderTests.cs index 7a0cb33eb74d..428c5b13fecc 100644 --- a/src/libraries/Common/tests/System/TimeProviderTests.cs +++ b/src/libraries/Common/tests/System/TimeProviderTests.cs @@ -214,7 +214,7 @@ private static void CancelAfter(TimeProvider provider, CancellationTokenSource c } #endif // NETFRAMEWORK - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [MemberData(nameof(TimersProvidersListData))] public static void CancellationTokenSourceWithTimer(TimeProvider provider) { diff --git a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs index 232c05afb8d2..cdab35da2b13 100644 --- a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs +++ b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if NET6_0_OR_GREATER +#if NET using System.Runtime.Intrinsics; #endif using System.Threading; @@ -27,7 +27,7 @@ public static class AssertExtensions public static void ThrowsOnAot(Action action) where T : Exception { -#if NETCOREAPP // Dynamic code is always supported on .NET Framework +#if NET // Dynamic code is always supported on .NET Framework if (!RuntimeFeature.IsDynamicCodeSupported) { Assert.Throws(action); @@ -710,7 +710,7 @@ static unsafe bool IsPositiveZero(double value) return (*(ulong*)(&value)) == 0x0000000000000000; } -#if NET6_0_OR_GREATER +#if NET static unsafe bool IsNegativeZero(Half value) { return (*(ushort*)(&value)) == 0x8000; @@ -780,7 +780,7 @@ static string ToStringPadded(double value) } } -#if NET6_0_OR_GREATER +#if NET static string ToStringPadded(Half value) { if (Half.IsNaN(value)) @@ -1036,7 +1036,7 @@ public static void Equal(float expected, float actual, float variance) } } -#if NET6_0_OR_GREATER +#if NET /// Verifies that two values are equal, within the . /// The expected value /// The value to be compared against @@ -1196,7 +1196,7 @@ static unsafe int SingleToInt32Bits(float value) throw EqualException.ForMismatchedValues(ToStringPadded(expected), ToStringPadded(actual)); } -#if NET6_0_OR_GREATER +#if NET /// Verifies that two values's binary representations are identical. /// The expected value /// The value to be compared against diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index 62523b568175..d008034e43b5 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -126,7 +126,7 @@ public static int SlowRuntimeTimeoutModifier public static bool IsCaseInsensitiveOS => IsWindows || IsOSX || IsMacCatalyst; public static bool IsCaseSensitiveOS => !IsCaseInsensitiveOS; -#if NETCOREAPP +#if NET public static bool FileCreateCaseSensitive => IsCaseSensitiveOS && !RuntimeInformation.RuntimeIdentifier.StartsWith("iossimulator") && !RuntimeInformation.RuntimeIdentifier.StartsWith("tvossimulator"); #else @@ -136,10 +136,6 @@ public static int SlowRuntimeTimeoutModifier public static bool IsThreadingSupported => (!IsWasi && !IsBrowser) || IsWasmThreadingSupported; public static bool IsWasmThreadingSupported => IsBrowser && IsEnvironmentVariableTrue("IsBrowserThreadingSupported"); public static bool IsNotWasmThreadingSupported => !IsWasmThreadingSupported; - public static bool IsWasmBackgroundExec => IsBrowser && IsEnvironmentVariableTrue("IsWasmBackgroundExec"); - public static bool IsThreadingSupportedNotBrowserBackgroundExec => IsWasmThreadingSupported && !IsWasmBackgroundExec; - public static bool IsWasmBackgroundExecOrSingleThread => IsWasmBackgroundExec || IsNotWasmThreadingSupported; - public static bool IsThreadingSupportedOrBrowserBackgroundExec => IsWasmBackgroundExec || !IsBrowser; public static bool IsBinaryFormatterSupported => IsNotMobile && !IsNativeAot; public static bool IsStartingProcessesSupported => !IsiOS && !IstvOS; @@ -153,6 +149,8 @@ public static int SlowRuntimeTimeoutModifier public static bool IsNotBrowserDomSupported => !IsBrowserDomSupported; public static bool IsWebSocketSupported => IsEnvironmentVariableTrue("IsWebSocketSupported"); public static bool IsNodeJS => IsEnvironmentVariableTrue("IsNodeJS"); + public static bool IsFirefox => IsEnvironmentVariableTrue("IsFirefox"); + public static bool IsChromium => IsEnvironmentVariableTrue("IsChromium"); public static bool IsNotNodeJS => !IsNodeJS; public static bool IsNodeJSOnWindows => GetNodeJSPlatform() == "win32"; public static bool LocalEchoServerIsNotAvailable => !LocalEchoServerIsAvailable; @@ -180,7 +178,7 @@ private static bool GetLinqExpressionsBuiltWithIsInterpretingOnly() public static bool IsNotInContainer => !IsInContainer; public static bool SupportsComInterop => IsWindows && IsNotMonoRuntime && !IsNativeAot; // matches definitions in clr.featuredefines.props -#if NETCOREAPP +#if NET public static bool IsBuiltInComEnabled => SupportsComInterop && (AppContext.TryGetSwitch("System.Runtime.InteropServices.BuiltInComInterop.IsSupported", out bool isEnabled) ? isEnabled @@ -197,7 +195,7 @@ private static bool GetLinqExpressionsBuiltWithIsInterpretingOnly() public static bool SupportsSsl3 => GetSsl3Support(); public static bool SupportsSsl2 => IsWindows && !PlatformDetection.IsWindows10Version1607OrGreater; -#if NETCOREAPP +#if NET public static bool IsReflectionEmitSupported => RuntimeFeature.IsDynamicCodeSupported; public static bool IsNotReflectionEmitSupported => !IsReflectionEmitSupported; #else @@ -284,7 +282,7 @@ public static bool IsMetadataTokenSupported public static bool UsesMobileAppleCrypto => IsMacCatalyst || IsiOS || IstvOS; // Changed to `true` when trimming - public static bool IsBuiltWithAggressiveTrimming => IsNativeAot; + public static bool IsBuiltWithAggressiveTrimming => IsNativeAot || IsAppleMobile; public static bool IsNotBuiltWithAggressiveTrimming => !IsBuiltWithAggressiveTrimming; public static bool IsTrimmedWithILLink => IsBuiltWithAggressiveTrimming && !IsNativeAot; @@ -667,7 +665,7 @@ private static bool GetSendsCAListByDefault() private static bool GetIsRunningOnMonoInterpreter() { -#if NETCOREAPP +#if NET return IsMonoRuntime && RuntimeFeature.IsDynamicCodeSupported && !RuntimeFeature.IsDynamicCodeCompiled; #else return false; diff --git a/src/libraries/Common/tests/TestUtilities/System/Runtime/InteropServices/SafeBufferUtil.cs b/src/libraries/Common/tests/TestUtilities/System/Runtime/InteropServices/SafeBufferUtil.cs index f667b1e26cec..d3ff55aa5156 100644 --- a/src/libraries/Common/tests/TestUtilities/System/Runtime/InteropServices/SafeBufferUtil.cs +++ b/src/libraries/Common/tests/TestUtilities/System/Runtime/InteropServices/SafeBufferUtil.cs @@ -19,7 +19,7 @@ private sealed class AllocHGlobalSafeHandle : SafeBuffer { public AllocHGlobalSafeHandle(nuint cb) : base(ownsHandle: true) { -#if !NETCOREAPP +#if !NET RuntimeHelpers.PrepareConstrainedRegions(); #endif try diff --git a/src/libraries/Common/tests/TestUtilities/System/WindowsIdentityFixture.cs b/src/libraries/Common/tests/TestUtilities/System/WindowsIdentityFixture.cs index b4d9be2a5274..2817d305e6d0 100644 --- a/src/libraries/Common/tests/TestUtilities/System/WindowsIdentityFixture.cs +++ b/src/libraries/Common/tests/TestUtilities/System/WindowsIdentityFixture.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Net; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif using System.Security.Cryptography; @@ -127,7 +127,7 @@ private void CreateUser() [LibraryImport("netapi32.dll")] internal static partial uint NetUserDel([MarshalAs(UnmanagedType.LPWStr)] string servername, [MarshalAs(UnmanagedType.LPWStr)] string username); -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(USER_INFO_1.Marshaller))] #endif [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] @@ -142,7 +142,7 @@ internal struct USER_INFO_1 public uint usri1_flags; public string usri1_script_path; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(USER_INFO_1), MarshalMode.Default, typeof(Marshaller))] public static class Marshaller { diff --git a/src/libraries/Common/tests/TestUtilities/TestEventListener.cs b/src/libraries/Common/tests/TestUtilities/TestEventListener.cs index bd7b633ba6f8..8cb70ee3cbd8 100644 --- a/src/libraries/Common/tests/TestUtilities/TestEventListener.cs +++ b/src/libraries/Common/tests/TestUtilities/TestEventListener.cs @@ -55,41 +55,51 @@ public TestEventListener(ITestOutputHelper output, params string[] sourceNames) public TestEventListener(Action writeFunc, params string[] sourceNames) { + List eventSources = _eventSources; + lock (this) { _writeFunc = writeFunc; _sourceNames = new HashSet(sourceNames); - foreach (EventSource eventSource in _eventSources) + _eventSources = null; + } + + // eventSources were populated in the base ctor and are now owned by this thread, enable them now. + foreach (EventSource eventSource in eventSources) + { + if (_sourceNames.Contains(eventSource.Name)) { - OnEventSourceCreated(eventSource); + EnableEvents(eventSource, EventLevel.LogAlways); } - _eventSources = null; } } protected override void OnEventSourceCreated(EventSource eventSource) { - lock (this) + // We're likely called from base ctor, if so, just save the event source for later initialization. + if (_sourceNames is null) { - // We're called from base ctor, just save the event source for later initialization. - if (_sourceNames is null) + lock (this) { - _eventSources.Add(eventSource); - return; + if (_sourceNames is null) + { + _eventSources.Add(eventSource); + return; + } } + } - // Second pass called from our ctor, allow logging for specified source names. - if (_sourceNames.Contains(eventSource.Name)) - { - EnableEvents(eventSource, EventLevel.LogAlways); - } + // Second pass called after our ctor, allow logging for specified source names. + if (_sourceNames.Contains(eventSource.Name)) + { + EnableEvents(eventSource, EventLevel.LogAlways); } } protected override void OnEventWritten(EventWrittenEventArgs eventData) { StringBuilder sb = new StringBuilder(). -#if NETCOREAPP2_2_OR_GREATER || NETSTANDARD2_1_OR_GREATER +#if NET || NETSTANDARD2_1_OR_GREATER Append($"{eventData.TimeStamp:HH:mm:ss.fffffff}[{eventData.EventName}] "); #else Append($"[{eventData.EventName}] "); @@ -102,7 +112,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) } try { - _writeFunc(sb.ToString()); + _writeFunc?.Invoke(sb.ToString()); } catch { } } diff --git a/src/libraries/Common/tests/Tests/System/StringTests.cs b/src/libraries/Common/tests/Tests/System/StringTests.cs index f21dbe3baad6..8e465475a520 100644 --- a/src/libraries/Common/tests/Tests/System/StringTests.cs +++ b/src/libraries/Common/tests/Tests/System/StringTests.cs @@ -314,6 +314,7 @@ void Validate(string result) } Validate(string.Concat(values)); + Validate(string.Concat((ReadOnlySpan)values)); Validate(string.Concat((IEnumerable)values)); Validate(string.Concat((IEnumerable)values)); // Call the generic IEnumerable-based overload } @@ -418,6 +419,7 @@ public static void Concat_Objects(object[] values, string expected) Assert.Equal(expected, string.Concat(values[0], values[1], values[2], values[3])); } Assert.Equal(expected, string.Concat(values)); + Assert.Equal(expected, string.Concat((ReadOnlySpan)values)); Assert.Equal(expected, string.Concat((IEnumerable)values)); } @@ -2730,9 +2732,11 @@ public static IEnumerable Format_Valid_TestData() public static void Format_Valid(IFormatProvider provider, string format, object[] values, string expected) { Assert.Equal(expected, string.Format(provider, format, values)); + Assert.Equal(expected, string.Format(provider, format, (ReadOnlySpan)values)); if (provider is null) { Assert.Equal(expected, string.Format(format, values)); + Assert.Equal(expected, string.Format(format, (ReadOnlySpan)values)); } switch (values.Length) @@ -3967,6 +3971,7 @@ public static void Join_StringArray(string separator, string[] values, int start if (startIndex + count == values.Length && count != 0) { Assert.Equal(expected, string.Join(separator, values)); + Assert.Equal(expected, string.Join(separator, (ReadOnlySpan)values)); var iEnumerableStringOptimized = new List(values); Assert.Equal(expected, string.Join(separator, iEnumerableStringOptimized)); @@ -3984,6 +3989,44 @@ public static void Join_StringArray(string separator, string[] values, int start { var arrayOfObjects = (object[])values; Assert.Equal(expected, string.Join(separator, arrayOfObjects)); + Assert.Equal(expected, string.Join(separator, (ReadOnlySpan)arrayOfObjects)); + } + } + Assert.Equal(expected, string.Join(separator, values, startIndex, count)); + } + + [Theory] + [InlineData('$', new string[] { }, 0, 0, "")] + [InlineData('$', new string[] { null }, 0, 1, "")] + [InlineData('$', new string[] { null, "Bar", null }, 0, 3, "$Bar$")] + [InlineData('$', new string[] { "", "", "" }, 0, 3, "$$")] + [InlineData('$', new string[] { "Foo", "Bar", "Baz" }, 0, 3, "Foo$Bar$Baz")] + [InlineData('$', new string[] { "Foo", "Bar", "Baz" }, 3, 0, "")] + [InlineData('$', new string[] { "Foo", "Bar", "Baz" }, 1, 1, "Bar")] + public static void Join_CharSeparator_StringArray(char separator, string[] values, int startIndex, int count, string expected) + { + if (startIndex + count == values.Length && count != 0) + { + Assert.Equal(expected, string.Join(separator, values)); + Assert.Equal(expected, string.Join(separator, (ReadOnlySpan)values)); + + var iEnumerableStringOptimized = new List(values); + Assert.Equal(expected, string.Join(separator, iEnumerableStringOptimized)); + Assert.Equal(expected, string.Join(separator, iEnumerableStringOptimized)); // Call the generic IEnumerable-based overload + + var iEnumerableStringNotOptimized = new Queue(values); + Assert.Equal(expected, string.Join(separator, iEnumerableStringNotOptimized)); + Assert.Equal(expected, string.Join(separator, iEnumerableStringNotOptimized)); + + var iEnumerableObject = new List(values); + Assert.Equal(expected, string.Join(separator, iEnumerableObject)); + + // Bug/Documented behavior: Join(string, object[]) returns "" when the first item in the array is null + if (values.Length == 0 || values[0] != null) + { + var arrayOfObjects = (object[])values; + Assert.Equal(expected, string.Join(separator, arrayOfObjects)); + Assert.Equal(expected, string.Join(separator, (ReadOnlySpan)arrayOfObjects)); } } Assert.Equal(expected, string.Join(separator, values, startIndex, count)); @@ -4038,6 +4081,31 @@ public static void Join_ObjectArray(string separator, object[] values, string ex { Assert.Equal(expected, string.Join(separator, values)); Assert.Equal(expected, string.Join(separator, (IEnumerable)values)); + Assert.Equal(expected, string.Join(separator, (ReadOnlySpan)values)); + } + + public static IEnumerable Join_CharSeparator_ObjectArray_TestData() + { + yield return new object[] { '$', new object[] { }, "" }; + yield return new object[] { '$', new object[] { new ObjectWithNullToString() }, "" }; + yield return new object[] { '$', new object[] { "Foo" }, "Foo" }; + yield return new object[] { '$', new object[] { "Foo", "Bar", "Baz" }, "Foo$Bar$Baz" }; + yield return new object[] { '$', new object[] { "Foo", null, "Baz" }, "Foo$$Baz" }; + + // Test join when first value is null + yield return new object[] { '$', new object[] { null, "Bar", "Baz" }, "$Bar$Baz" }; + + // Join should ignore objects that have a null ToString() value + yield return new object[] { "|", new object[] { new ObjectWithNullToString(), "Foo", new ObjectWithNullToString(), "Bar", new ObjectWithNullToString() }, "|Foo||Bar|" }; + } + + [Theory] + [MemberData(nameof(Join_CharSeparator_ObjectArray_TestData))] + public static void Join_CharSeparator_ObjectArray(char separator, object[] values, string expected) + { + Assert.Equal(expected, string.Join(separator, values)); + Assert.Equal(expected, string.Join(separator, (IEnumerable)values)); + Assert.Equal(expected, string.Join(separator, (ReadOnlySpan)values)); } [Fact] @@ -6098,6 +6166,7 @@ public static void Trim(string s, char[] trimChars, string expected) } Assert.Equal(expected, s.Trim(trimChars)); + Assert.Equal(expected, s.Trim((ReadOnlySpan)trimChars)); Assert.Equal(expected, s.AsSpan().Trim(trimChars).ToString()); } @@ -6128,6 +6197,7 @@ public static void TrimEnd(string s, char[] trimChars, string expected) } Assert.Equal(expected, s.TrimEnd(trimChars)); + Assert.Equal(expected, s.TrimEnd((ReadOnlySpan)trimChars)); Assert.Equal(expected, s.AsSpan().TrimEnd(trimChars).ToString()); } @@ -6158,6 +6228,7 @@ public static void TrimStart(string s, char[] trimChars, string expected) } Assert.Equal(expected, s.TrimStart(trimChars)); + Assert.Equal(expected, s.TrimStart((ReadOnlySpan)trimChars)); Assert.Equal(expected, s.AsSpan().TrimStart(trimChars).ToString()); } @@ -6388,18 +6459,27 @@ public static void ZeroLengthTrimCharacters() Assert.True(s1.SequenceEqual(s1.Trim(trimCharsString))); Assert.True(s1.SequenceEqual(s1.TrimStart(trimCharsString))); Assert.True(s1.SequenceEqual(s1.TrimEnd(trimCharsString))); + Assert.True(s1.SequenceEqual(s1.Trim((ReadOnlySpan)trimCharsString))); + Assert.True(s1.SequenceEqual(s1.TrimStart((ReadOnlySpan)trimCharsString))); + Assert.True(s1.SequenceEqual(s1.TrimEnd((ReadOnlySpan)trimCharsString))); char[] chars = { 'a', 'b', 'c', 'd', 'e' }; trimCharsString = chars; Assert.True(s1.SequenceEqual(s1.Trim(trimCharsString))); Assert.True(s1.SequenceEqual(s1.TrimStart(trimCharsString))); Assert.True(s1.SequenceEqual(s1.TrimEnd(trimCharsString))); + Assert.True(s1.SequenceEqual(s1.Trim((ReadOnlySpan)trimCharsString))); + Assert.True(s1.SequenceEqual(s1.TrimStart((ReadOnlySpan)trimCharsString))); + Assert.True(s1.SequenceEqual(s1.TrimEnd((ReadOnlySpan)trimCharsString))); string emptyString = string.Empty; char[] trimCharsArrayFromString = "abcde".ToCharArray(); Assert.True(emptyString.SequenceEqual(emptyString.Trim(trimCharsArrayFromString))); Assert.True(emptyString.SequenceEqual(emptyString.TrimStart(trimCharsArrayFromString))); Assert.True(emptyString.SequenceEqual(emptyString.TrimEnd(trimCharsArrayFromString))); + Assert.True(emptyString.SequenceEqual(emptyString.Trim((ReadOnlySpan)trimCharsArrayFromString))); + Assert.True(emptyString.SequenceEqual(emptyString.TrimStart((ReadOnlySpan)trimCharsArrayFromString))); + Assert.True(emptyString.SequenceEqual(emptyString.TrimEnd((ReadOnlySpan)trimCharsArrayFromString))); ReadOnlySpan span = s1.AsSpan(); ReadOnlySpan trimChars = trimCharsString.AsSpan(); @@ -6435,6 +6515,9 @@ public static void NoTrimCharacters() Assert.True(s1.SequenceEqual(s1.Trim(trimCharsString))); Assert.True(s1.SequenceEqual(s1.TrimStart(trimCharsString))); Assert.True(s1.SequenceEqual(s1.TrimEnd(trimCharsString))); + Assert.True(s1.SequenceEqual(s1.Trim((ReadOnlySpan)trimCharsString))); + Assert.True(s1.SequenceEqual(s1.TrimStart((ReadOnlySpan)trimCharsString))); + Assert.True(s1.SequenceEqual(s1.TrimEnd((ReadOnlySpan)trimCharsString))); ReadOnlySpan span = s1.AsSpan(); Assert.True(span.SequenceEqual(span.Trim(trimChars))); @@ -6454,6 +6537,9 @@ public static void NoTrimCharacters() Assert.True(s2.SequenceEqual(s2.Trim(chars))); Assert.True(s2.SequenceEqual(s2.TrimStart(chars))); Assert.True(s2.SequenceEqual(s2.TrimEnd(chars))); + Assert.True(s2.SequenceEqual(s2.Trim((ReadOnlySpan)chars))); + Assert.True(s2.SequenceEqual(s2.TrimStart((ReadOnlySpan)chars))); + Assert.True(s2.SequenceEqual(s2.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan span = s2.AsSpan(); Assert.True(span.SequenceEqual(span.Trim(chars))); @@ -6466,6 +6552,9 @@ public static void NoTrimCharacters() Assert.True(s3.SequenceEqual(s3.Trim(trimCharsFromString))); Assert.True(s3.SequenceEqual(s3.TrimStart(trimCharsFromString))); Assert.True(s3.SequenceEqual(s3.TrimEnd(trimCharsFromString))); + Assert.True(s3.SequenceEqual(s3.Trim((ReadOnlySpan)trimCharsFromString))); + Assert.True(s3.SequenceEqual(s3.TrimStart((ReadOnlySpan)trimCharsFromString))); + Assert.True(s3.SequenceEqual(s3.TrimEnd((ReadOnlySpan)trimCharsFromString))); ReadOnlySpan stringSpan = s3.AsSpan(); ReadOnlySpan trimCharsFromStringSpan = trimCharsFromString.AsSpan(); @@ -6490,6 +6579,9 @@ public static void OnlyTrimCharacters() Assert.True(string.Empty.SequenceEqual(s1.Trim(chars)), "G: " + length); Assert.True(string.Empty.SequenceEqual(s1.TrimStart(chars)), "H: " + length); Assert.True(string.Empty.SequenceEqual(s1.TrimEnd(chars)), "I: " + length); + Assert.True(string.Empty.SequenceEqual(s1.Trim((ReadOnlySpan)chars)), "G: " + length); + Assert.True(string.Empty.SequenceEqual(s1.TrimStart((ReadOnlySpan)chars)), "H: " + length); + Assert.True(string.Empty.SequenceEqual(s1.TrimEnd((ReadOnlySpan)chars)), "I: " + length); ReadOnlySpan span = s1.AsSpan(); Assert.True(ReadOnlySpan.Empty.SequenceEqual(span.Trim(chars)), "G: " + length); @@ -6502,6 +6594,9 @@ public static void OnlyTrimCharacters() Assert.True(string.Empty.SequenceEqual(s2.Trim(trimCharsString)), "J"); Assert.True(string.Empty.SequenceEqual(s2.TrimStart(trimCharsString)), "K"); Assert.True(string.Empty.SequenceEqual(s2.TrimEnd(trimCharsString)), "L"); + Assert.True(string.Empty.SequenceEqual(s2.Trim((ReadOnlySpan)trimCharsString)), "J"); + Assert.True(string.Empty.SequenceEqual(s2.TrimStart((ReadOnlySpan)trimCharsString)), "K"); + Assert.True(string.Empty.SequenceEqual(s2.TrimEnd((ReadOnlySpan)trimCharsString)), "L"); ReadOnlySpan stringSpan = s2.AsSpan(); ReadOnlySpan trimChars = trimCharsString.AsSpan(); @@ -6526,6 +6621,9 @@ public static void TrimCharactersAtStart() Assert.True(s1.Substring(1).SequenceEqual(s1.Trim(chars)), "A: " + length); Assert.True(s1.Substring(1).SequenceEqual(s1.TrimStart(chars)), "B: " + length); Assert.True(s1.SequenceEqual(s1.TrimEnd(chars)), "C: " + length); + Assert.True(s1.Substring(1).SequenceEqual(s1.Trim((ReadOnlySpan)chars)), "A: " + length); + Assert.True(s1.Substring(1).SequenceEqual(s1.TrimStart((ReadOnlySpan)chars)), "B: " + length); + Assert.True(s1.SequenceEqual(s1.TrimEnd((ReadOnlySpan)chars)), "C: " + length); ReadOnlySpan span = s1.AsSpan(); Assert.True(span.Slice(1).SequenceEqual(span.Trim(chars)), "A: " + length); @@ -6538,6 +6636,9 @@ public static void TrimCharactersAtStart() Assert.True(s2.Substring(3).SequenceEqual(s2.Trim(trimCharsString)), "D"); Assert.True(s2.Substring(3).SequenceEqual(s2.TrimStart(trimCharsString)), "E"); Assert.True(s2.SequenceEqual(s2.TrimEnd(trimCharsString)), "F"); + Assert.True(s2.Substring(3).SequenceEqual(s2.Trim((ReadOnlySpan)trimCharsString)), "D"); + Assert.True(s2.Substring(3).SequenceEqual(s2.TrimStart((ReadOnlySpan)trimCharsString)), "E"); + Assert.True(s2.SequenceEqual(s2.TrimEnd((ReadOnlySpan)trimCharsString)), "F"); ReadOnlySpan stringSpan = s2.AsSpan(); ReadOnlySpan trimChars = trimCharsString.AsSpan(); @@ -6563,6 +6664,9 @@ public static void TrimCharactersAtEnd() Assert.True(s1.Substring(0, length - 1).SequenceEqual(s1.Trim(chars))); Assert.True(s1.SequenceEqual(s1.TrimStart(chars))); Assert.True(s1.Substring(0, length - 1).SequenceEqual(s1.TrimEnd(chars))); + Assert.True(s1.Substring(0, length - 1).SequenceEqual(s1.Trim((ReadOnlySpan)chars))); + Assert.True(s1.SequenceEqual(s1.TrimStart((ReadOnlySpan)chars))); + Assert.True(s1.Substring(0, length - 1).SequenceEqual(s1.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan span = new ReadOnlySpan(a); Assert.True(span.Slice(0, length - 1).SequenceEqual(span.Trim(chars))); @@ -6600,6 +6704,9 @@ public static void TrimCharactersAtStartAndEnd() Assert.True(s1.Substring(1, length - 2).SequenceEqual(s1.Trim(chars))); Assert.True(s1.Substring(1).SequenceEqual(s1.TrimStart(chars))); Assert.True(s1.Substring(0, length - 1).SequenceEqual(s1.TrimEnd(chars))); + Assert.True(s1.Substring(1, length - 2).SequenceEqual(s1.Trim((ReadOnlySpan)chars))); + Assert.True(s1.Substring(1).SequenceEqual(s1.TrimStart((ReadOnlySpan)chars))); + Assert.True(s1.Substring(0, length - 1).SequenceEqual(s1.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan span = s1.AsSpan(); Assert.True(span.Slice(1, length - 2).SequenceEqual(span.Trim(chars))); @@ -6608,13 +6715,15 @@ public static void TrimCharactersAtStartAndEnd() } string s2 = "ccedafffffbdaa"; - char[] trimCharsString = "abcde".ToCharArray(); - Assert.True(s2.Substring(5, 5).SequenceEqual(s2.Trim(trimCharsString))); - Assert.True(s2.Substring(5).SequenceEqual(s2.TrimStart(trimCharsString))); - Assert.True(s2.Substring(0, 10).SequenceEqual(s2.TrimEnd(trimCharsString))); + Assert.True(s2.Substring(5, 5).SequenceEqual(s2.Trim(chars))); + Assert.True(s2.Substring(5).SequenceEqual(s2.TrimStart(chars))); + Assert.True(s2.Substring(0, 10).SequenceEqual(s2.TrimEnd(chars))); + Assert.True(s2.Substring(5, 5).SequenceEqual(s2.Trim((ReadOnlySpan)chars))); + Assert.True(s2.Substring(5).SequenceEqual(s2.TrimStart((ReadOnlySpan)chars))); + Assert.True(s2.Substring(0, 10).SequenceEqual(s2.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan stringSpan = s2.AsSpan(); - ReadOnlySpan trimChars = trimCharsString.AsSpan(); + ReadOnlySpan trimChars = chars.AsSpan(); Assert.True(stringSpan.Slice(5, 5).SequenceEqual(stringSpan.Trim(trimChars))); Assert.True(stringSpan.Slice(5).SequenceEqual(stringSpan.TrimStart(trimChars))); Assert.True(stringSpan.Slice(0, 10).SequenceEqual(stringSpan.TrimEnd(trimChars))); @@ -6637,6 +6746,9 @@ public static void TrimCharactersInMiddle() Assert.True(s1.SequenceEqual(s1.Trim(chars))); Assert.True(s1.SequenceEqual(s1.TrimStart(chars))); Assert.True(s1.SequenceEqual(s1.TrimEnd(chars))); + Assert.True(s1.SequenceEqual(s1.Trim((ReadOnlySpan)chars))); + Assert.True(s1.SequenceEqual(s1.TrimStart((ReadOnlySpan)chars))); + Assert.True(s1.SequenceEqual(s1.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan span = s1.AsSpan(); Assert.True(span.SequenceEqual(span.Trim(chars))); @@ -6645,13 +6757,15 @@ public static void TrimCharactersInMiddle() } string s2 = "fabbacddeeddef"; - char[] trimCharsString = "abcde".ToCharArray(); - Assert.True(s2.SequenceEqual(s2.Trim(trimCharsString))); - Assert.True(s2.SequenceEqual(s2.TrimStart(trimCharsString))); - Assert.True(s2.SequenceEqual(s2.TrimEnd(trimCharsString))); + Assert.True(s2.SequenceEqual(s2.Trim(chars))); + Assert.True(s2.SequenceEqual(s2.TrimStart(chars))); + Assert.True(s2.SequenceEqual(s2.TrimEnd(chars))); + Assert.True(s2.SequenceEqual(s2.Trim((ReadOnlySpan)chars))); + Assert.True(s2.SequenceEqual(s2.TrimStart((ReadOnlySpan)chars))); + Assert.True(s2.SequenceEqual(s2.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan stringSpan = s2.AsSpan(); - ReadOnlySpan trimChars = trimCharsString.AsSpan(); + ReadOnlySpan trimChars = chars.AsSpan(); Assert.True(stringSpan.SequenceEqual(stringSpan.Trim(trimChars))); Assert.True(stringSpan.SequenceEqual(stringSpan.TrimStart(trimChars))); Assert.True(stringSpan.SequenceEqual(stringSpan.TrimEnd(trimChars))); @@ -6684,6 +6798,19 @@ public static void TrimCharactersMultipleTimes() Assert.True(trimStartResultString.SequenceEqual(trimStartResultString.TrimStart(chars))); Assert.True(trimEndResultString.SequenceEqual(trimEndResultString.TrimEnd(chars))); + s1 = new string(a); + trimResultString = s1.Trim((ReadOnlySpan)chars); + trimStartResultString = s1.TrimStart((ReadOnlySpan)chars); + trimEndResultString = s1.TrimEnd((ReadOnlySpan)chars); + Assert.True(s1.Substring(1, length - 2).SequenceEqual(trimResultString)); + Assert.True(s1.Substring(1).SequenceEqual(trimStartResultString)); + Assert.True(s1.Substring(0, length - 1).SequenceEqual(trimEndResultString)); + + // 2nd attempt should do nothing + Assert.True(trimResultString.SequenceEqual(trimResultString.Trim((ReadOnlySpan)chars))); + Assert.True(trimStartResultString.SequenceEqual(trimStartResultString.TrimStart((ReadOnlySpan)chars))); + Assert.True(trimEndResultString.SequenceEqual(trimEndResultString.TrimEnd((ReadOnlySpan)chars))); + ReadOnlySpan span = s1.AsSpan(); ReadOnlySpan trimResult = span.Trim(chars); ReadOnlySpan trimStartResult = span.TrimStart(chars); @@ -6699,21 +6826,33 @@ public static void TrimCharactersMultipleTimes() } string s2 = "ccedafffffbdaa"; - char[] trimCharsString = "abcde".ToCharArray(); - string trimStringResultString = s2.Trim(trimCharsString); - string trimStartStringResultString = s2.TrimStart(trimCharsString); - string trimEndStringResultString = s2.TrimEnd(trimCharsString); + string trimStringResultString = s2.Trim(chars); + string trimStartStringResultString = s2.TrimStart(chars); + string trimEndStringResultString = s2.TrimEnd(chars); + Assert.True(s2.Substring(5, 5).SequenceEqual(trimStringResultString)); + Assert.True(s2.Substring(5).SequenceEqual(trimStartStringResultString)); + Assert.True(s2.Substring(0, 10).SequenceEqual(trimEndStringResultString)); + + // 2nd attempt should do nothing + Assert.True(trimStringResultString.SequenceEqual(trimStringResultString.Trim(chars))); + Assert.True(trimStartStringResultString.SequenceEqual(trimStartStringResultString.TrimStart(chars))); + Assert.True(trimEndStringResultString.SequenceEqual(trimEndStringResultString.TrimEnd(chars))); + + s2 = "ccedafffffbdaa"; + trimStringResultString = s2.Trim((ReadOnlySpan)chars); + trimStartStringResultString = s2.TrimStart((ReadOnlySpan)chars); + trimEndStringResultString = s2.TrimEnd((ReadOnlySpan)chars); Assert.True(s2.Substring(5, 5).SequenceEqual(trimStringResultString)); Assert.True(s2.Substring(5).SequenceEqual(trimStartStringResultString)); Assert.True(s2.Substring(0, 10).SequenceEqual(trimEndStringResultString)); // 2nd attempt should do nothing - Assert.True(trimStringResultString.SequenceEqual(trimStringResultString.Trim(trimCharsString))); - Assert.True(trimStartStringResultString.SequenceEqual(trimStartStringResultString.TrimStart(trimCharsString))); - Assert.True(trimEndStringResultString.SequenceEqual(trimEndStringResultString.TrimEnd(trimCharsString))); + Assert.True(trimStringResultString.SequenceEqual(trimStringResultString.Trim((ReadOnlySpan)chars))); + Assert.True(trimStartStringResultString.SequenceEqual(trimStartStringResultString.TrimStart((ReadOnlySpan)chars))); + Assert.True(trimEndStringResultString.SequenceEqual(trimEndStringResultString.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan stringSpan = s2.AsSpan(); - ReadOnlySpan trimChars = trimCharsString.AsSpan(); + ReadOnlySpan trimChars = chars.AsSpan(); ReadOnlySpan trimStringResult = stringSpan.Trim(trimChars); ReadOnlySpan trimStartStringResult = stringSpan.TrimStart(trimChars); @@ -6739,27 +6878,31 @@ public static void MakeSureNoTrimCharactersChecksGoOutOfRange() first[length - 1] = 'f'; string s1 = new string(first, 1, length - 2); Assert.Equal(s1.ToArray().Length, s1.Trim(chars).ToArray().Length); - Assert.True(s1.SequenceEqual(s1.Trim(chars)), "A : " + s1.Length); - Assert.True(s1.SequenceEqual(s1.TrimStart(chars)), "B :" + s1.Length); - Assert.True(s1.SequenceEqual(s1.TrimEnd(chars))); + Assert.True(s1.SequenceEqual(s1.Trim(chars)), "A: " + s1.Length); + Assert.True(s1.SequenceEqual(s1.TrimStart(chars)), "B: " + s1.Length); + Assert.True(s1.SequenceEqual(s1.TrimEnd(chars)), "C: " + s1.Length); ReadOnlySpan span = s1.AsSpan(); Assert.Equal(span.ToArray().Length, span.Trim(chars).ToArray().Length); - Assert.True(span.SequenceEqual(span.Trim(chars)), "A : " + span.Length); - Assert.True(span.SequenceEqual(span.TrimStart(chars)), "B :" + span.Length); - Assert.True(span.SequenceEqual(span.TrimEnd(chars))); + Assert.True(span.SequenceEqual(span.Trim(chars)), "A: " + span.Length); + Assert.True(span.SequenceEqual(span.TrimStart(chars)), "B: " + span.Length); + Assert.True(span.SequenceEqual(span.TrimEnd(chars)), "C: " + s1.Length); } string testString = "afghijklmnopqrstfe"; string s2 = testString.Substring(1, testString.Length - 2); - char[] trimCharsString = "abcde".ToCharArray(); - Assert.True(s2.SequenceEqual(s2.Trim(trimCharsString))); - Assert.True(s2.SequenceEqual(s2.TrimStart(trimCharsString))); - Assert.True(s2.SequenceEqual(s2.TrimEnd(trimCharsString))); + Assert.True(s2.SequenceEqual(s2.Trim(chars))); + Assert.True(s2.SequenceEqual(s2.TrimStart(chars))); + Assert.True(s2.SequenceEqual(s2.TrimEnd(chars))); + + s2 = testString.Substring(1, testString.Length - 2); + Assert.True(s2.SequenceEqual(s2.Trim((ReadOnlySpan)chars))); + Assert.True(s2.SequenceEqual(s2.TrimStart((ReadOnlySpan)chars))); + Assert.True(s2.SequenceEqual(s2.TrimEnd((ReadOnlySpan)chars))); ReadOnlySpan stringSpan = s2.AsSpan(); - ReadOnlySpan trimChars = trimCharsString.AsSpan(); + ReadOnlySpan trimChars = chars.AsSpan(); Assert.True(stringSpan.SequenceEqual(stringSpan.Trim(trimChars))); Assert.True(stringSpan.SequenceEqual(stringSpan.TrimStart(trimChars))); Assert.True(stringSpan.SequenceEqual(stringSpan.TrimEnd(trimChars))); diff --git a/src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.cs b/src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.cs index 738ec5bcec38..32ca91a37c9c 100644 --- a/src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.cs +++ b/src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.cs @@ -35,7 +35,6 @@ public static async Task Main(string[] args) var includedNamespaces = new List(); var includedClasses = new List(); var includedMethods = new List(); - var backgroundExec = false; var untilFailed = false; for (int i = index; i < args.Length; i++) @@ -63,9 +62,6 @@ public static async Task Main(string[] args) includedMethods.Add(args[i + 1]); i++; break; - case "-backgroundExec": - backgroundExec = true; - break; case "-untilFailed": untilFailed = true; break; @@ -102,14 +98,7 @@ public static async Task Main(string[] args) var res = 0; do { - if (backgroundExec) - { - res = await Task.Run(() => runner.Run()); - } - else - { - res = await runner.Run(); - } + res = await runner.Run(); } while(res == 0 && untilFailed); diff --git a/src/libraries/Directory.Build.props b/src/libraries/Directory.Build.props index c8d1737bea13..7ccc19377a2e 100644 --- a/src/libraries/Directory.Build.props +++ b/src/libraries/Directory.Build.props @@ -25,7 +25,7 @@ - + diff --git a/src/libraries/Directory.Build.targets b/src/libraries/Directory.Build.targets index b219e7cf41a9..5a3fff449e7b 100644 --- a/src/libraries/Directory.Build.targets +++ b/src/libraries/Directory.Build.targets @@ -131,7 +131,7 @@ - + @@ -170,6 +170,7 @@ diff --git a/src/libraries/Fuzzing/.gitignore b/src/libraries/Fuzzing/.gitignore new file mode 100644 index 000000000000..fb0bb057a399 --- /dev/null +++ b/src/libraries/Fuzzing/.gitignore @@ -0,0 +1,5 @@ +TempNugetCache +publish +deployment +inputs +crash-* diff --git a/src/libraries/Fuzzing/Directory.Build.props b/src/libraries/Fuzzing/Directory.Build.props new file mode 100644 index 000000000000..e21857f2f894 --- /dev/null +++ b/src/libraries/Fuzzing/Directory.Build.props @@ -0,0 +1,8 @@ + + + 9.0 + net$(NetCoreAppCurrentVersion) + $(NetCoreAppCurrentVersion).0 + ..\..\Common\tests\TestUtilities + + diff --git a/src/libraries/Fuzzing/Directory.Build.targets b/src/libraries/Fuzzing/Directory.Build.targets new file mode 100644 index 000000000000..c1df2220ddc6 --- /dev/null +++ b/src/libraries/Fuzzing/Directory.Build.targets @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/src/libraries/Fuzzing/DotnetFuzzing.sln b/src/libraries/Fuzzing/DotnetFuzzing.sln new file mode 100644 index 000000000000..367a6baee630 --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.34807.36 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotnetFuzzing", "DotnetFuzzing\DotnetFuzzing.csproj", "{002673BF-11AE-4072-9CBE-FC312BF68613}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6DDAE3F1-325F-468C-92DB-5947A3AD757E}" + ProjectSection(SolutionItems) = preProject + .gitignore = .gitignore + ..\..\..\eng\pipelines\libraries\fuzzing\deploy-to-onefuzz.yml = ..\..\..\eng\pipelines\libraries\fuzzing\deploy-to-onefuzz.yml + Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets + nuget.config = nuget.config + README.md = README.md + OneFuzz.md = OneFuzz.md + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {002673BF-11AE-4072-9CBE-FC312BF68613}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {002673BF-11AE-4072-9CBE-FC312BF68613}.Debug|Any CPU.Build.0 = Debug|Any CPU + {002673BF-11AE-4072-9CBE-FC312BF68613}.Release|Any CPU.ActiveCfg = Release|Any CPU + {002673BF-11AE-4072-9CBE-FC312BF68613}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0BAD3B6E-67D4-418D-A45F-49B3F79168DF} + EndGlobalSection +EndGlobal diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Assert.cs b/src/libraries/Fuzzing/DotnetFuzzing/Assert.cs new file mode 100644 index 000000000000..810174ccbc13 --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing/Assert.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace DotnetFuzzing; + +internal static class Assert +{ + // Feel free to add any other helpers as needed. + + public static void Equal(T expected, T actual) + { + if (!EqualityComparer.Default.Equals(expected, actual)) + { + Throw(expected, actual); + } + + static void Throw(T expected, T actual) => + throw new Exception($"Expected={expected} Actual={actual}"); + } + + public static void SequenceEqual(ReadOnlySpan expected, ReadOnlySpan actual) + { + if (!expected.SequenceEqual(actual)) + { + Throw(expected, actual); + } + + static void Throw(ReadOnlySpan expected, ReadOnlySpan actual) + { + Equal(expected.Length, actual.Length); + + int diffIndex = expected.CommonPrefixLength(actual); + + throw new Exception($"Expected={expected[diffIndex]} Actual={actual[diffIndex]} at index {diffIndex}"); + } + } +} diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Dictionaries/json.dict b/src/libraries/Fuzzing/DotnetFuzzing/Dictionaries/json.dict new file mode 100644 index 000000000000..b0d0ba46a059 --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing/Dictionaries/json.dict @@ -0,0 +1,73 @@ +"0" +"7" +"," +":" +"2.1e24" + +"true" +"false" +"null" + +"\"\"" +"\"\":" + +"{}" +",{}" +":{}" +"{\"\":0}" +"{{}}" + +"[]" +",[]" +":[]" +"[0]" +"[[]]" + +"''" +"\\" +"\\b" +"\\f" +"\\n" +"\\r" +"\\t" +"\\u0000" +"\\x00" +"\\0" +"\\uD800\\uDC00" +"\\uDBFF\\uDFFF" + +"\"\":0" +"//" +"/**/" + + +# Things like geojson, json-ld, ... +"$ref" +"type" +"coordinates" +"@context" +"@id" +"@type" + +# Strings with truncated special values +"{\"foo\":fa" +"{\"foo\":t" +"{\"foo\":nul" + +"{" +"}" +"\"qty\": 1, \"qty\": -1" +"\"qty\": 1, \"qty\\ud800\": -1" +"\"qty\": 1, \"qt\\y\": -1" +"/*" +"*/" +"\"" +"1.7976931348623157e+308" +"5e-324" +"9007199254740991" +"-9007199254740991" + +"}=" + +",," +"{\"\":" diff --git a/src/libraries/Fuzzing/DotnetFuzzing/DotnetFuzzing.csproj b/src/libraries/Fuzzing/DotnetFuzzing/DotnetFuzzing.csproj new file mode 100644 index 000000000000..fa571fbbf969 --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing/DotnetFuzzing.csproj @@ -0,0 +1,33 @@ + + + + Exe + $(NetCoreAppCurrent)-windows + true + enable + enable + True + CA2252 + true + + + + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/HttpHeadersFuzzer.cs b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/HttpHeadersFuzzer.cs new file mode 100644 index 000000000000..a7cf06395ac0 --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/HttpHeadersFuzzer.cs @@ -0,0 +1,80 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Net.Http.Headers; +using System.Runtime.InteropServices; + +namespace DotnetFuzzing.Fuzzers; + +internal sealed class HttpHeadersFuzzer : IFuzzer +{ + public string[] TargetAssemblies { get; } = ["System.Net.Http"]; + public string[] TargetCoreLibPrefixes => []; + + // https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.Http/src/System/Net/Http/Headers/KnownHeaders.cs + private static readonly string[] s_knownHeaderNames = [ + ":status", "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language", "Accept-Patch", + "Accept-Ranges", "Access-Control-Allow-Credentials", "Access-Control-Allow-Headers", + "Access-Control-Allow-Methods", "Access-Control-Allow-Origin", "Access-Control-Expose-Headers", + "Access-Control-Max-Age", "Age", "Allow", "Alt-Svc", "Alt-Used", "Authorization", "Cache-Control", + "Connection", "Content-Disposition", "Content-Encoding", "Content-Language", "Content-Length", + "Content-Location", "Content-MD5", "Content-Range", "Content-Security-Policy", "Content-Type", + "Cookie", "Cookie2", "Date", "ETag", "Expect", "Expect-CT", "Expires", "From", "grpc-encoding", + "grpc-message", "grpc-status", "Host", "If-Match", "If-Modified-Since", "If-None-Match", + "If-Range", "If-Unmodified-Since", "Keep-Alive", "Last-Modified", "Link", "Location", + "Max-Forwards", "Origin", "P3P", "Pragma", "Proxy-Authenticate", "Proxy-Authorization", + "Proxy-Connection", "Proxy-Support", "Public-Key-Pins", "Range", "Referer", "Referrer-Policy", + "Refresh", "Retry-After", "Sec-WebSocket-Accept", "Sec-WebSocket-Extensions", "Sec-WebSocket-Key", + "Sec-WebSocket-Protocol", "Sec-WebSocket-Version", "Server", "Server-Timing", "Set-Cookie", + "Set-Cookie2", "Strict-Transport-Security", "TE", "TSV", "Trailer", "Transfer-Encoding", + "Upgrade", "Upgrade-Insecure-Requests", "User-Agent", "Vary", "Via", "WWW-Authenticate", + "Warning", "X-AspNet-Version", "X-Cache", "X-Content-Duration", "X-Content-Type-Options", + "X-Frame-Options", "X-MSEdge-Ref", "X-Powered-By", "X-Request-ID", "X-UA-Compatible", "X-XSS-Protection" + ]; + + private static readonly HttpRequestHeaders s_requestHeaders = new HttpRequestMessage().Headers; + private static readonly HttpContentHeaders s_contentHeaders = new ByteArrayContent([]).Headers; + private static readonly HttpResponseHeaders s_responseHeaders = new HttpResponseMessage().Headers; + + public void FuzzTarget(ReadOnlySpan bytes) + { + if (bytes.Length < 2) + { + return; + } + + // We use the first byte to select a known header name. + // The rest of the input is used as the UTF-16 header value. + // The second byte is skipped to keep the value chars 2-byte aligned. + string name = s_knownHeaderNames[bytes[0] % s_knownHeaderNames.Length]; + string value = MemoryMarshal.Cast(bytes.Slice(2)).ToString(); + + Test(s_requestHeaders, name, value); + Test(s_contentHeaders, name, value); + Test(s_responseHeaders, name, value); + + static void Test(HttpHeaders headers, string name, string value) + { + headers.Clear(); + + if (headers.TryAddWithoutValidation(name, value)) + { + // Enumerating the header collection should never throw, + // even if invalid values were added without validation. + foreach (var _ in headers) { } + + headers.Clear(); + + // If the value is invalid, we should only throw FormatException. + try + { + headers.Add(name, value); + headers.Add(name, value); + } + catch (FormatException) { } + + foreach (var _ in headers) { } + } + } + } +} diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/JsonDocumentFuzzer.cs b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/JsonDocumentFuzzer.cs new file mode 100644 index 000000000000..1cc8146b954a --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/JsonDocumentFuzzer.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Text.Json; + +namespace DotnetFuzzing.Fuzzers; + +internal sealed class JsonDocumentFuzzer : IFuzzer +{ + public string[] TargetAssemblies { get; } = ["System.Text.Json"]; + public string[] TargetCoreLibPrefixes => []; + public string Dictionary => "json.dict"; + + public void FuzzTarget(ReadOnlySpan bytes) + { + if (bytes.IsEmpty) + { + return; + } + + // The first byte is used to select various options. + // The rest of the input is used as the UTF-8 JSON payload. + byte optionsByte = bytes[0]; + bytes = bytes.Slice(1); + + var options = new JsonDocumentOptions + { + AllowTrailingCommas = (optionsByte & 1) != 0, + CommentHandling = (optionsByte & 2) != 0 ? JsonCommentHandling.Skip : JsonCommentHandling.Disallow, + }; + + using var poisonAfter = PooledBoundedMemory.Rent(bytes, PoisonPagePlacement.After); + + try + { + JsonDocument.Parse(poisonAfter.Memory, options); + } + catch (JsonException) { } + } +} diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/SearchValuesByteCharFuzzer.cs b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/SearchValuesByteCharFuzzer.cs new file mode 100644 index 000000000000..f01a9eff2bae --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/SearchValuesByteCharFuzzer.cs @@ -0,0 +1,131 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace DotnetFuzzing.Fuzzers; + +internal sealed class SearchValuesByteCharFuzzer : IFuzzer +{ + public string[] TargetAssemblies => []; + public string[] TargetCoreLibPrefixes { get; } = ["System.Buffers", "System.SpanHelpers", "System.PackedSpanHelpers"]; + + public unsafe void FuzzTarget(ReadOnlySpan bytes) + { + int newLine = bytes.IndexOf((byte)'\n'); + if (newLine < 0) + { + return; + } + + ReadOnlySpan haystack = bytes.Slice(newLine + 1); + ReadOnlySpan values = bytes.Slice(0, newLine); + + using var byteHaystack0 = PooledBoundedMemory.Rent(haystack, PoisonPagePlacement.Before); + using var byteHaystack1 = PooledBoundedMemory.Rent(haystack, PoisonPagePlacement.After); + + Test(byteHaystack0.Span, byteHaystack1.Span, values, SearchValues.Create(values)); + + if ((nuint)Unsafe.AsPointer(ref MemoryMarshal.GetReference(haystack)) % 2 != 0 && !haystack.IsEmpty) + { + // Ensure that the haystack is 2-byte aligned now that we're about to cast it to chars. + haystack = haystack.Slice(1); + } + + using var charHaystack0 = PooledBoundedMemory.Rent(MemoryMarshal.Cast(haystack), PoisonPagePlacement.Before); + using var charHaystack1 = PooledBoundedMemory.Rent(MemoryMarshal.Cast(haystack), PoisonPagePlacement.After); + + ReadOnlySpan charValues = MemoryMarshal.Cast(values); + Test(charHaystack0.Span, charHaystack1.Span, charValues, SearchValues.Create(charValues)); + } + + private static void Test(ReadOnlySpan haystack, ReadOnlySpan haystackCopy, ReadOnlySpan values, SearchValues searchValues) + where T : struct, INumber, IMinMaxValue + { + int indexOfAny = haystack.IndexOfAny(searchValues); + int indexOfAnyExcept = haystack.IndexOfAnyExcept(searchValues); + int lastIndexOfAny = haystack.LastIndexOfAny(searchValues); + int lastIndexOfAnyExcept = haystack.LastIndexOfAnyExcept(searchValues); + + Assert.Equal(indexOfAny, haystackCopy.IndexOfAny(searchValues)); + Assert.Equal(indexOfAnyExcept, haystackCopy.IndexOfAnyExcept(searchValues)); + Assert.Equal(lastIndexOfAny, haystackCopy.LastIndexOfAny(searchValues)); + Assert.Equal(lastIndexOfAnyExcept, haystackCopy.LastIndexOfAnyExcept(searchValues)); + + Assert.Equal(IndexOfAnyScalar(haystack, searchValues), indexOfAny); + Assert.Equal(IndexOfAnyExceptScalar(haystack, searchValues), indexOfAnyExcept); + Assert.Equal(LastIndexOfAnyScalar(haystack, searchValues), lastIndexOfAny); + Assert.Equal(LastIndexOfAnyExceptScalar(haystack, searchValues), lastIndexOfAnyExcept); + + Assert.Equal(indexOfAny >= 0, lastIndexOfAny >= 0); + Assert.Equal(indexOfAnyExcept >= 0, lastIndexOfAnyExcept >= 0); + + Assert.Equal(indexOfAny >= 0, haystack.ContainsAny(searchValues)); + Assert.Equal(indexOfAnyExcept >= 0, haystack.ContainsAnyExcept(searchValues)); + + if (!values.IsEmpty) + { + Assert.Equal(0, values.IndexOfAny(searchValues)); + Assert.Equal(-1, values.IndexOfAnyExcept(searchValues)); + } + } + + private static int IndexOfAnyScalar(ReadOnlySpan haystack, SearchValues values) + where T : IEquatable + { + for (int i = 0; i < haystack.Length; i++) + { + if (values.Contains(haystack[i])) + { + return i; + } + } + + return -1; + } + + private static int IndexOfAnyExceptScalar(ReadOnlySpan haystack, SearchValues values) + where T : IEquatable + { + for (int i = 0; i < haystack.Length; i++) + { + if (!values.Contains(haystack[i])) + { + return i; + } + } + + return -1; + } + + private static int LastIndexOfAnyScalar(ReadOnlySpan haystack, SearchValues values) + where T : IEquatable + { + for (int i = haystack.Length - 1; i >= 0; i--) + { + if (values.Contains(haystack[i])) + { + return i; + } + } + + return -1; + } + + private static int LastIndexOfAnyExceptScalar(ReadOnlySpan haystack, SearchValues values) + where T : IEquatable + { + for (int i = haystack.Length - 1; i >= 0; i--) + { + if (!values.Contains(haystack[i])) + { + return i; + } + } + + return -1; + } +} diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/SearchValuesStringFuzzer.cs b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/SearchValuesStringFuzzer.cs new file mode 100644 index 000000000000..a99c6c3a4a47 --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/SearchValuesStringFuzzer.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Runtime.InteropServices; + +namespace DotnetFuzzing.Fuzzers; + +internal sealed class SearchValuesStringFuzzer : IFuzzer +{ + public string[] TargetAssemblies => []; + public string[] TargetCoreLibPrefixes { get; } = ["System.Buffers", "System.Globalization"]; + + public void FuzzTarget(ReadOnlySpan bytes) + { + ReadOnlySpan chars = MemoryMarshal.Cast(bytes); + + int newLine = chars.IndexOf('\n'); + if (newLine < 0) + { + return; + } + + ReadOnlySpan haystack = chars.Slice(newLine + 1); + string[] needles = chars.Slice(0, newLine).ToString().Split(','); + + using var haystack0 = PooledBoundedMemory.Rent(haystack, PoisonPagePlacement.Before); + using var haystack1 = PooledBoundedMemory.Rent(haystack, PoisonPagePlacement.After); + + Test(haystack0.Span, haystack1.Span, needles, StringComparison.Ordinal); + Test(haystack0.Span, haystack1.Span, needles, StringComparison.OrdinalIgnoreCase); + } + + private static void Test(ReadOnlySpan haystack, ReadOnlySpan haystackCopy, string[] needles, StringComparison comparisonType) + { + SearchValues searchValues = SearchValues.Create(needles, comparisonType); + + int index = haystack.IndexOfAny(searchValues); + Assert.Equal(index, haystackCopy.IndexOfAny(searchValues)); + Assert.Equal(index, IndexOfAnyReferenceImpl(haystack, needles, comparisonType)); + } + + private static int IndexOfAnyReferenceImpl(ReadOnlySpan haystack, string[] needles, StringComparison comparisonType) + { + int minIndex = int.MaxValue; + + foreach (string needle in needles) + { + int i = haystack.IndexOf(needle, comparisonType); + if ((uint)i < minIndex) + { + minIndex = i; + } + } + + return minIndex == int.MaxValue ? -1 : minIndex; + } +} diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/UTF8Fuzzer.cs b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/UTF8Fuzzer.cs new file mode 100644 index 000000000000..b42adc6a70e4 --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/UTF8Fuzzer.cs @@ -0,0 +1,154 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Text.Unicode; +using System.Text; + +namespace DotnetFuzzing.Fuzzers; + +// Adapted from https://github.com/GrabYourPitchforks/utf8fuzz +internal sealed class UTF8Fuzzer : IFuzzer +{ + public string[] TargetAssemblies => []; + public string[] TargetCoreLibPrefixes { get; } = ["System.Text"]; + + private static readonly Encoding s_encodingWithCustomReplacement = + Encoding.GetEncoding("utf-8", EncoderFallback.ExceptionFallback, new DecoderReplacementFallback("{BAD}")); + + private static readonly ArrayBufferWriter s_replacementBufferWriter = new(4096); + + public void FuzzTarget(ReadOnlySpan bytes) + { + using var poisonAfter = PooledBoundedMemory.Rent(bytes, PoisonPagePlacement.After); + + Test(poisonAfter.Span); + } + + private static void Test(ReadOnlySpan input) + { + int charCount = Encoding.UTF8.GetCharCount(input); + + Assert.Equal(charCount, GetCharCountFromRunes(input)); + + using var chars = PooledBoundedMemory.Rent(charCount, PoisonPagePlacement.After); + using var chars2 = PooledBoundedMemory.Rent(charCount + 1024, PoisonPagePlacement.After); + + Assert.Equal(charCount, Encoding.UTF8.GetChars(input, chars.Span)); + + CompareUtf8AndUtf16RuneEnumeration(input, chars.Span); + + // ToUtf16 with replace=true and exact size buffer. + { + OperationStatus opStatus = Utf8.ToUtf16(input, chars2.Span.Slice(0, charCount), out int bytesReadJustNow, out int charsWrittenJustNow, replaceInvalidSequences: true, isFinalBlock: true); + + Assert.Equal(OperationStatus.Done, opStatus); + Assert.Equal(input.Length, bytesReadJustNow); + Assert.Equal(charCount, charsWrittenJustNow); + Assert.SequenceEqual(chars.Span, chars2.Span.Slice(0, charCount)); + } + + // ToUtf16 with replace=true and extra large buffer. + { + OperationStatus opStatus = Utf8.ToUtf16(input, chars2.Span, out int bytesReadJustNow, out int charsWrittenJustNow, replaceInvalidSequences: true, isFinalBlock: true); + + Assert.Equal(OperationStatus.Done, opStatus); + Assert.Equal(input.Length, bytesReadJustNow); + Assert.Equal(charCount, charsWrittenJustNow); + Assert.SequenceEqual(chars.Span, chars2.Span.Slice(0, charCount)); + } + + // Running ToUtf16 with replace=false and extra large buffer. + { + ReadOnlySpan utf8 = input; + Span output = chars2.Span; + output.Clear(); + + while (!utf8.IsEmpty) + { + OperationStatus opStatus = Utf8.ToUtf16(utf8, output, out int bytesReadJustNow, out int charsWrittenJustNow, replaceInvalidSequences: false, isFinalBlock: true); + + CompareUtf8AndUtf16RuneEnumeration(utf8.Slice(0, bytesReadJustNow), output.Slice(0, charsWrittenJustNow), expectIsValid: true); + + utf8 = utf8.Slice(bytesReadJustNow); + + if (opStatus != OperationStatus.Done) + { + Assert.Equal(OperationStatus.InvalidData, opStatus); + + // Skip over invalid data + Rune.DecodeFromUtf8(utf8, out _, out int bytesToSkip); + utf8 = utf8.Slice(bytesToSkip); + } + } + } + + // Trying a custom decoder replacement. + { + ReadOnlySpan utf8 = input; + + string decoded = s_encodingWithCustomReplacement.GetString(utf8); + + using var decodedChars = PooledBoundedMemory.Rent(decoded.Length, PoisonPagePlacement.After); + + s_replacementBufferWriter.ResetWrittenCount(); + + while (!utf8.IsEmpty) + { + OperationStatus opStatus = Utf8.ToUtf16(utf8, decodedChars.Span, out int bytesReadJustNow, out int charsWrittenJustNow, replaceInvalidSequences: false, isFinalBlock: true); + s_replacementBufferWriter.Write(decodedChars.Span.Slice(0, charsWrittenJustNow)); + + utf8 = utf8.Slice(bytesReadJustNow); + + if (opStatus != OperationStatus.Done) + { + Assert.Equal(OperationStatus.InvalidData, opStatus); + + // Skip over invalid data + Rune.DecodeFromUtf8(utf8, out _, out int bytesToSkip); + utf8 = utf8.Slice(bytesToSkip); + + s_replacementBufferWriter.Write("{BAD}"); + } + } + + Assert.SequenceEqual(decoded, s_replacementBufferWriter.WrittenSpan); + } + } + + private static int GetCharCountFromRunes(ReadOnlySpan utf8) + { + int charCount = 0; + + while (!utf8.IsEmpty) + { + Rune.DecodeFromUtf8(utf8, out Rune thisRune, out int bytesConsumed); + charCount += thisRune.Utf16SequenceLength; // ok if U+FFFD replacement + utf8 = utf8.Slice(bytesConsumed); + } + + return charCount; + } + + private static void CompareUtf8AndUtf16RuneEnumeration(ReadOnlySpan utf8, ReadOnlySpan utf16, bool expectIsValid = false) + { + while (!utf8.IsEmpty && !utf16.IsEmpty) + { + OperationStatus utf8Status = Rune.DecodeFromUtf8(utf8, out Rune inputUtf8Rune, out int bytesConsumed); + OperationStatus utf16Status = Rune.DecodeFromUtf16(utf16, out Rune inputUtf16Rune, out int charsConsumed); + + if (expectIsValid) + { + Assert.Equal(OperationStatus.Done, utf8Status); + Assert.Equal(OperationStatus.Done, utf16Status); + } + + Assert.Equal(inputUtf8Rune, inputUtf16Rune); + + utf8 = utf8.Slice(bytesConsumed); + utf16 = utf16.Slice(charsConsumed); + } + + Assert.Equal(utf8.Length, utf16.Length); + } +} diff --git a/src/libraries/Fuzzing/DotnetFuzzing/IFuzzer.cs b/src/libraries/Fuzzing/DotnetFuzzing/IFuzzer.cs new file mode 100644 index 000000000000..c4c6fc4f9db5 --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing/IFuzzer.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace DotnetFuzzing; + +internal interface IFuzzer +{ + /// Friendly name to identify this fuzz target in OneFuzz configuration. + string Name => GetType().Name; + + /// List of assemblies that should be instrumented. + /// If the code under test is only in CoreLib, you may return an empty array. + string[] TargetAssemblies { get; } + + /// List of prefixes (CoreLib namespaces/types) that should be instrumented. + /// If the code under test is outside CoreLib, you may return an empty array. + string[] TargetCoreLibPrefixes { get; } + + /// Optional name of the dictionary to use to better guide the fuzzer. + string? Dictionary => null; + + /// Entry point for the fuzzer. Should exercise code paths in and/or . + void FuzzTarget(ReadOnlySpan bytes); +} diff --git a/src/libraries/Fuzzing/DotnetFuzzing/PooledBoundedMemory.cs b/src/libraries/Fuzzing/DotnetFuzzing/PooledBoundedMemory.cs new file mode 100644 index 000000000000..50e6e610c0d8 --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing/PooledBoundedMemory.cs @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; + +namespace DotnetFuzzing; + +internal sealed class PooledBoundedMemory : IDisposable where T : unmanaged +{ + // Default libFuzzer max_len for inputs is 4096. + private const int MaxLength = 4096 * 2; + + private static readonly PooledBoundedMemory?[] s_memoryWithPoisonBefore = new PooledBoundedMemory?[MaxLength + 1]; + private static readonly PooledBoundedMemory?[] s_memoryWithPoisonAfter = new PooledBoundedMemory?[MaxLength + 1]; + + private readonly BoundedMemory _memory; + private readonly PooledBoundedMemory?[]? _pool; + + private PooledBoundedMemory(PooledBoundedMemory?[]? pool, int elementCount, PoisonPagePlacement placement) + { + _pool = pool; + _memory = BoundedMemory.Allocate(elementCount, placement); + } + + public BoundedMemory InnerMemory => _memory; + public Memory Memory => _memory.Memory; + public Span Span => _memory.Span; + + public void Dispose() + { + if (_pool is null || + Interlocked.CompareExchange(ref _pool[_memory.Length], this, null) is not null) + { + _memory.Dispose(); + } + } + + public static PooledBoundedMemory Rent(int elementCount, PoisonPagePlacement placement) + { + if ((uint)elementCount >= MaxLength) + { + return new PooledBoundedMemory(null, elementCount, placement); + } + + PooledBoundedMemory?[] pool = placement switch + { + PoisonPagePlacement.Before => s_memoryWithPoisonBefore, + PoisonPagePlacement.After => s_memoryWithPoisonAfter, + _ => throw new ArgumentOutOfRangeException(nameof(placement)) + }; + + return + Interlocked.Exchange(ref pool[elementCount], null) ?? + new PooledBoundedMemory(pool, elementCount, placement); + } + + public static PooledBoundedMemory Rent(ReadOnlySpan data, PoisonPagePlacement placement) + { + PooledBoundedMemory memory = Rent(data.Length, placement); + data.CopyTo(memory.Span); + return memory; + } +} diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Program.cs b/src/libraries/Fuzzing/DotnetFuzzing/Program.cs new file mode 100644 index 000000000000..5215fc91f648 --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing/Program.cs @@ -0,0 +1,380 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using SharpFuzz; +using System.Buffers; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; + +namespace DotnetFuzzing; + +public static class Program +{ + public static async Task Main(string[] args) + { + IFuzzer[] fuzzers = typeof(Program).Assembly.GetTypes() + .Where(t => t.IsClass && !t.IsAbstract) + .Where(t => t.GetInterfaces().Contains(typeof(IFuzzer))) + .Select(t => (IFuzzer)Activator.CreateInstance(t)!) + .OrderBy(f => f.Name, StringComparer.OrdinalIgnoreCase) + .ToArray(); + + void PrintUsage() + { + Console.Error.WriteLine( + $""" + Usage: + DotnetFuzzing [input file/directory] + DotnetFuzzing prepare-onefuzz + + Fuzzers available: {string.Join(", ", fuzzers.Select(t => t.Name))} + """); + } + + if (args.Length == 0) + { + PrintUsage(); + return; + } + + if (args[0].Equals("prepare-onefuzz", StringComparison.OrdinalIgnoreCase)) + { + if (args.Length != 2) + { + PrintUsage(); + return; + } + + string publishDirectory = Path.GetDirectoryName(typeof(Program).Assembly.Location) ?? Environment.CurrentDirectory; + + await PrepareOneFuzzDeploymentAsync(fuzzers, publishDirectory, args[1]); + return; + } + + IFuzzer? fuzzer = fuzzers + .Where(f => f.Name.Equals(args[0], StringComparison.OrdinalIgnoreCase)) + .FirstOrDefault(); + + if (fuzzer is null) + { + Console.Error.WriteLine($"Fuzzer '{args[0]}' not found. Available: {string.Join(", ", fuzzers.Select(t => t.Name))}"); + return; + } + + RunFuzzer(fuzzer, inputFiles: args.Length > 1 ? args[1] : null); + } + + private static unsafe void RunFuzzer(IFuzzer fuzzer, string? inputFiles) + { + if (!string.IsNullOrEmpty(inputFiles)) + { + string[] files = Directory.Exists(inputFiles) + ? Directory.GetFiles(inputFiles) + : [inputFiles]; + + foreach (string inputFile in files) + { + fuzzer.FuzzTarget(File.ReadAllBytes(inputFile)); + } + + return; + } + + Fuzzer.LibFuzzer.Run(bytes => + { + // Some fuzzers assume that the input is at least 2-byte aligned. + ArgumentOutOfRangeException.ThrowIfNotEqual((nuint)Unsafe.AsPointer(ref MemoryMarshal.GetReference(bytes)) % 8, 0U); + + fuzzer.FuzzTarget(bytes); + }); + } + + private static async Task PrepareOneFuzzDeploymentAsync(IFuzzer[] fuzzers, string publishDirectory, string outputDirectory) + { + string[] dictionaries = Directory.GetFiles(Path.Combine(publishDirectory, "Dictionaries")) + .Select(Path.GetFileName) + .ToArray()!; + + if (dictionaries.FirstOrDefault(dict => !fuzzers.Any(f => f.Dictionary == dict)) is { } unusedDictionary) + { + throw new Exception($"Dictionary '{unusedDictionary}' is not referenced by any fuzzer."); + } + + Directory.CreateDirectory(outputDirectory); + + await DownloadArtifactAsync( + Path.Combine(publishDirectory, "libfuzzer-dotnet.exe"), + "https://github.com/Metalnem/libfuzzer-dotnet/releases/download/v2023.06.26.1359/libfuzzer-dotnet-windows.exe", + "cbc1f510caaec01b17b5e89fc780f426710acee7429151634bbf4d0c57583458"); + + foreach (IFuzzer fuzzer in fuzzers) + { + Console.WriteLine(); + Console.WriteLine($"Preparing {fuzzer.Name} ..."); + + string fuzzerDirectory = Path.Combine(outputDirectory, fuzzer.Name); + Directory.CreateDirectory(fuzzerDirectory); + + Console.WriteLine($"Copying artifacts to {fuzzerDirectory}"); + // NOTE: The expected fuzzer directory structure is currently flat. + // If we ever need to support subdirectories, OneFuzzConfig.json must also be updated to use PreservePathsJobDependencies. + foreach (string file in Directory.GetFiles(publishDirectory)) + { + File.Copy(file, Path.Combine(fuzzerDirectory, Path.GetFileName(file)), overwrite: true); + } + + if (fuzzer.Dictionary is string dict) + { + if (!dictionaries.Contains(dict, StringComparer.Ordinal)) + { + throw new Exception($"Fuzzer '{fuzzer.Name}' is referencing a dictionary '{fuzzer.Dictionary}' that does not exist in the publish directory."); + } + + File.Copy(Path.Combine(publishDirectory, "Dictionaries", dict), Path.Combine(fuzzerDirectory, "dictionary"), overwrite: true); + } + + InstrumentAssemblies(fuzzer, fuzzerDirectory); + + Console.WriteLine("Generating OneFuzzConfig.json"); + File.WriteAllText(Path.Combine(fuzzerDirectory, "OneFuzzConfig.json"), GenerateOneFuzzConfigJson(fuzzer)); + + Console.WriteLine("Generating local-run.bat"); + File.WriteAllText(Path.Combine(fuzzerDirectory, "local-run.bat"), GenerateLocalRunHelperScript(fuzzer)); + } + + WorkaroundOneFuzzTaskNotAcceptingMultipleJobs(fuzzers); + } + + private static IEnumerable<(string Assembly, string? Prefixes)> GetInstrumentationTargets(IFuzzer fuzzer) + { + bool instrumentCoreLib = fuzzer.TargetCoreLibPrefixes.Length > 0; + + if (!instrumentCoreLib && fuzzer.TargetAssemblies.Length == 0) + { + throw new Exception($"Specify at least one target in {nameof(IFuzzer.TargetAssemblies)} or {nameof(IFuzzer.TargetCoreLibPrefixes)}."); + } + + foreach (string assembly in fuzzer.TargetAssemblies) + { + string path = assembly; + if (!path.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) + { + path += ".dll"; + } + + if (path == "System.Private.CoreLib.dll") + { + if (!instrumentCoreLib) + { + throw new Exception($"To instrument System.Private.CoreLib, specify {nameof(IFuzzer.TargetCoreLibPrefixes)}."); + } + + continue; + } + + yield return (path, null); + } + + if (instrumentCoreLib) + { + yield return ("System.Private.CoreLib.dll", string.Join(' ', fuzzer.TargetCoreLibPrefixes)); + } + } + + private static void InstrumentAssemblies(IFuzzer fuzzer, string fuzzerDirectory) + { + foreach (var (assembly, prefixes) in GetInstrumentationTargets(fuzzer)) + { + Console.WriteLine($"Instrumenting {assembly} {(prefixes is null ? "" : $"({prefixes})")}"); + + string path = Path.Combine(fuzzerDirectory, assembly); + if (!File.Exists(path)) + { + throw new Exception($"Assembly {path} not found. Make sure to run the tool from the publish directory."); + } + + byte[] current = File.ReadAllBytes(path); + string previousOriginal = $"{path}.original"; + string previousInstrumented = $"{path}.instrumented"; + + if (!string.IsNullOrEmpty(prefixes)) + { + // Don't use the cached assembly if the prefixes have changed. + previousInstrumented += Convert.ToHexStringLower(SHA256.HashData(Encoding.UTF8.GetBytes(prefixes))); + } + + if (File.Exists(previousOriginal) && + File.Exists(previousInstrumented) && + File.ReadAllBytes(previousOriginal).AsSpan().SequenceEqual(current)) + { + // The assembly hasn't changed since the previous invocation of SharpFuzz. + File.Copy(previousInstrumented, path, overwrite: true); + continue; + } + + File.Delete(previousOriginal); + File.Delete(previousInstrumented); + + using Process sharpfuzz = new() + { + StartInfo = new ProcessStartInfo + { + FileName = "sharpfuzz", + Arguments = $"{path} {prefixes}", + UseShellExecute = false, + } + }; + + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // https://github.com/Metalnem/sharpfuzz/blob/9e44048d8821da942d00c2c125bb59d039d55673/src/SharpFuzz/Options.cs#L37-L41 + throw new Exception("SHARPFUZZ_INSTRUMENT_MIXED_MODE_ASSEMBLIES is only supported on Windows."); + } + + sharpfuzz.StartInfo.EnvironmentVariables.Add("SHARPFUZZ_INSTRUMENT_MIXED_MODE_ASSEMBLIES", "1"); + + sharpfuzz.Start(); + sharpfuzz.WaitForExit(); + + if (sharpfuzz.ExitCode != 0) + { + throw new Exception($"Failed to instrument {path}"); + } + + File.WriteAllBytes(previousOriginal, current); + File.Copy(path, previousInstrumented); + } + } + + private static async Task DownloadArtifactAsync(string path, string url, string hash) + { + if (!File.Exists(path)) + { + Console.WriteLine($"Downloading {Path.GetFileName(path)}"); + + using var client = new HttpClient(); + byte[] bytes = await client.GetByteArrayAsync(url); + + if (!Convert.ToHexString(SHA256.HashData(bytes)).Equals(hash, StringComparison.OrdinalIgnoreCase)) + { + throw new Exception($"{path} checksum mismatch"); + } + + File.WriteAllBytes(path, bytes); + } + } + + private static string GenerateOneFuzzConfigJson(IFuzzer fuzzer) + { + // {setup_dir} is replaced by OneFuzz with the path to the fuzzer directory. + string? dictionaryArgument = fuzzer.Dictionary is not null + ? "\"-dict={setup_dir}/dictionary\"" + : null; + + // Make it easier to distinguish between long-running CI jobs and short-lived test submissions. + string nameSuffix = Environment.GetEnvironmentVariable("TF_BUILD") is null ? "-local" : ""; + + return + $$""" + { + "ConfigVersion": 3, + "Entries": [ + { + "JobNotificationEmail": "dotnet-fuzz-updates@microsoft.com", + "Skip": false, + "Fuzzer": { + "$type": "libfuzzer", + "FuzzingHarnessExecutableName": "libfuzzer-dotnet.exe", + "FuzzingTargetBinaries": [ + {{string.Join(", ", GetInstrumentationTargets(fuzzer).Select(t => $"\"{t.Assembly}\""))}} + ], + "CheckFuzzerHelp": false + }, + "FuzzerTimeoutInSeconds": 60, + "OneFuzzJobs": [ + { + "ProjectName": "DotnetFuzzing", + "TargetName": "{{fuzzer.Name}}{{nameSuffix}}", + "TargetOptions": [ + "--target_path=DotnetFuzzing.exe", + "--target_arg={{fuzzer.Name}}" + ], + "FuzzingTargetOptions": [ + {{dictionaryArgument}} + ] + } + ], + "JobDependencies": [ + ".\\*" + ], + "AdoTemplate": { + "Org": "dnceng", + "Project": "internal", + "AssignedTo": "mizupan@microsoft.com", + "AreaPath": "internal\\.NET Libraries", + "IterationPath": "internal" + } + } + ] + } + """; + } + + private static string GenerateLocalRunHelperScript(IFuzzer fuzzer) + { + string script = $"%~dp0/libfuzzer-dotnet.exe --target_path=%~dp0/DotnetFuzzing.exe --target_arg={fuzzer.Name}"; + + if (fuzzer.Dictionary is not null) + { + script += " -dict=%~dp0dictionary"; + } + + // Pass any additional arguments to the fuzzer. + script += " %*"; + + return script; + } + + private static void WorkaroundOneFuzzTaskNotAcceptingMultipleJobs(IFuzzer[] fuzzers) + { + string yamlPath = Environment.CurrentDirectory; + while (!File.Exists(Path.Combine(yamlPath, "DotnetFuzzing.sln"))) + { + yamlPath = Path.GetDirectoryName(yamlPath) ?? throw new Exception("Couldn't find DotnetFuzzing.sln"); + } + + yamlPath = Path.Combine(yamlPath, "../../../eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml"); + + string yaml = File.ReadAllText(yamlPath); + + // At the moment OneFuzz can't handle a single deployment where multiple jobs share similar assemblies/pdbs. + // Generate a separate step for each fuzzer instead as a workaround. + string tasks = string.Join("\n\n", fuzzers.Select(fuzzer => + { + return + $$""" + - task: onefuzz-task@0 + inputs: + onefuzzOSes: 'Windows' + env: + onefuzzDropDirectory: $(fuzzerProject)/deployment/{{fuzzer.Name}} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + displayName: Send {{fuzzer.Name}} to OneFuzz + """; + })); + + const string StartMarker = "# ONEFUZZ_TASK_WORKAROUND_START"; + const string EndMarker = "# ONEFUZZ_TASK_WORKAROUND_END"; + + int start = yaml.IndexOf(StartMarker, StringComparison.Ordinal) + StartMarker.Length; + int end = yaml.IndexOf(EndMarker, start, StringComparison.Ordinal); + + yaml = string.Concat(yaml.AsSpan(0, start), $"\n{tasks}\n", yaml.AsSpan(end)); + yaml = yaml.ReplaceLineEndings("\r\n"); + + File.WriteAllText(yamlPath, yaml); + } +} diff --git a/src/libraries/Fuzzing/OneFuzz.md b/src/libraries/Fuzzing/OneFuzz.md new file mode 100644 index 000000000000..3ad2c0d0267a --- /dev/null +++ b/src/libraries/Fuzzing/OneFuzz.md @@ -0,0 +1,65 @@ +> [!NOTE] +> These instructions require access to internal Microsoft resources. +> You **do not** need to read this to add new fuzzing targets / run them locally. +> This is meant to help anyone diagnosing issues if the OneFuzz pipeline starts failing. + +Prerequisites: +- Follow [OneFuzz onboarding instructions] to get access to OneFuzz and download the tools (OIP, OneFuzz) +- Join the `dotnet-fuzz-updates` distribution group to receive notifications about started/failing jobs + +Useful links: +- [OneFuzz Documentation](https://aka.ms/onefuzz) +- [OneFuzzConfig.json format docs] +- [deploy-to-onefuzz.yml](../../../eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml) +- [Internal pipeline](https://dev.azure.com/dnceng/internal/_build?definitionId=1381) + +Work items for issues identified by OneFuzz will be filed in https://dev.azure.com/dnceng/internal/_workitems +under the ".NET Libraries" area. Filter on the `OneFuzz` tag. + +--- + +OneFuzz has support for native libFuzzer targets, where you supply the target harness that includes libFuzzer, +and dotnet-based targets, where you only supply the target managed assembly (library) with a well-known entry method. + +Because we want to test the latest .NET runtime and libraries, we can't use the built-in dotnet target support in OneFuzz. +We need the flexibility to use the latest .NET version, as well as the ability to use custom builds of dotnet/runtime (such as using a checked CLR). + +To get around this, we effectively supply the native target by bundling in [`libfuzzer-dotnet.exe`](https://github.com/Metalnem/libfuzzer-dotnet) ourselves, +which is a native libFuzzer harness that can talk with targets that were instrumented using [`SharpFuzz`](https://github.com/Metalnem/sharpfuzz). +Note that we also run `sharpfuzz` on target assemblies ourselves (e.g. `System.Text.Json.dll` in this example) before submitting jobs to OneFuzz. + +When fuzzing, we (or the OneFuzz automation) launch `libfuzzer-dotnet`, and pass it the path to the managed target: +```bash +libfuzzer-dotnet.exe --target_path=DotnetFuzzing.exe --target_arg=JsonSerializerFuzzer -dict=dictionary -workers=1 +``` +This is what the generated `local-run.bat` script does, and what the configuration in `OneFuzzConfig.json` specifies as well. + +In this case, `libfuzzer-dotnet` will use `target_path` and `target_arg` to start this project (`DotnetFuzzing`) with a single `JsonSerializerFuzzer` argument. +All other arguments (e.g. `dict`, `workers`) are only visible to `libfuzzer-dotnet`. + +--- + +After following instructions in the README on how to run the fuzzer locally, you can deploy the same directory to OneFuzz as a test job. + +When testing locally, consider changing the `JobNotificationEmail` in `Program.cs` to your own alias to avoid spamming the preset notification DG. + +```bash +:: Submit a test job that runs for 12 hours (run from one of the deployment subfolders) +oip submit --config .\OneFuzzConfig.json --drop-path . --do-not-file-bugs --duration 12 --platform windows +``` + +Job notification emails will contain job ID GUIDs. Use the commands below to query the status and download artifacts: + +```bash +:: Get the list of tasks and their status +onefuzz jobs get + +:: Download all containers (setup, crashes, inputs, ...) +onefuzz containers download_job + +:: Download logs for all tasks +onefuzz debug logs get --job_id +``` + +[OneFuzz onboarding instructions]: https://eng.ms/docs/cloud-ai-platform/azure-edge-platform-aep/aep-security/epsf-edge-and-platform-security-fundamentals/the-onefuzz-service/onefuzz/faq/onefuzz/onefuzz_access#:~:text=with%20these%20permissions.-,For%20the%20developer%20who%20will%20be%20fuzzing,-Access%20to%20the +[OneFuzzConfig.json format docs]: https://eng.ms/docs/cloud-ai-platform/azure-edge-platform-aep/aep-security/epsf-edge-and-platform-security-fundamentals/the-onefuzz-service/onefuzz/onefuzzconfig/onefuzzconfigv3 diff --git a/src/libraries/Fuzzing/README.md b/src/libraries/Fuzzing/README.md new file mode 100644 index 000000000000..66f945708309 --- /dev/null +++ b/src/libraries/Fuzzing/README.md @@ -0,0 +1,94 @@ +# Fuzzing .NET libraries + +This project contains fuzzing targets for various .NET libraries, as well as supporting code for generating OneFuzz deployments from them. +Targets are instrumented using [SharpFuzz](https://github.com/Metalnem/sharpfuzz), and ran using [libFuzzer](https://llvm.org/docs/LibFuzzer.html). + +The runtime and fuzzing targets are periodically rebuilt and published to OneFuzz via [deploy-to-onefuzz.yml](../../../eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml). + +Useful links: +- [libFuzzer documentation](https://llvm.org/docs/LibFuzzer.html) +- [libFuzzer tutorial with examples](https://github.com/google/fuzzing/blob/master/tutorial/libFuzzerTutorial.md) +- [More SharpFuzz samples](https://github.com/Metalnem/dotnet-fuzzers) +- [OneFuzz documentation](https://aka.ms/onefuzz) + +## Running locally + +> [!NOTE] +> The instructions assume you are running on Windows as that is what the continuous fuzzing runs currently use. + +### Prerequisites + +Build the runtime with the following arguments: +```cmd +./build.cmd clr+libs+packs+host -rc Checked -c Debug +``` +and install the SharpFuzz command line tool: +```cmd +dotnet tool install --global SharpFuzz.CommandLine +``` + +> [!TIP] +> The project uses a checked runtime + debug libraries configuration by default. +> If you want to use a different configuration, make sure to also adjust the artifact paths in `nuget.config`. + +### Running against a sample input + +The program accepts two arguments: the name of the fuzzer and the path to a sample input file / directory. +To run the HttpHeaders target against the `inputs` directory, use the following command: + +```cmd +cd src/libraries/Fuzzing/DotnetFuzzing + +dotnet run HttpHeadersFuzzer inputs +``` + +### Fuzzing locally + +The `prepare-onefuzz` command will create separate directories for each fuzzing target, instrument the relevant assemblies, and generate a helper script for running them locally. +Note that this command must be ran on the published artifacts (won't work with `dotnet run`). + +```cmd +cd src/libraries/Fuzzing/DotnetFuzzing + +dotnet publish -o publish && publish/DotnetFuzzing.exe prepare-onefuzz deployment +``` + +You can now start fuzzing by running the `local-run.bat` script in the folder of the fuzzer you are interested in. +```cmd +deployment/HttpHeadersFuzzer/local-run.bat +``` + +See the [libFuzzer options](https://llvm.org/docs/LibFuzzer.html#options) documentation for more information on how to customize the fuzzing process. +For example, here is how you can run the fuzzer against a `header-inputs` corpus directory for 10 minutes, running multiple instances in parallel: +```cmd +deployment/HttpHeadersFuzzer/local-run.bat header-inputs -timeout=30 -max_total_time=600 -jobs=5 +``` + +## Creating a new fuzzing target + +To create a new fuzzing target, you need to create a new class that implements the `IFuzzer` interface. +See existing implementations in the `Fuzzers` directory for reference. + +As an example, let's test that `IPAddress.TryParse` never throws on invalid input, and doesn't access any bytes after the end of `bytes`: +```c# +internal sealed class IPAddressFuzzer : IFuzzer +{ + public string[] TargetAssemblies => ["System.Net.Primitives"]; // Assembly where IPAddress lives + public string[] TargetCoreLibPrefixes => []; + + public void FuzzTarget(ReadOnlySpan bytes) + { + // PooledBoundedMemory is a helper class that ensures reading past the end of the buffer will trigger an access violation. + using var chars = PooledBoundedMemory.Rent(MemoryMarshal.Cast(bytes), PoisonPagePlacement.After); + + _ = IPAddress.TryParse(chars.Span, out _); + } +} +``` + +- `TargetAssemblies` is a list of assemblies where the tested code lives and that must be instrumented. +- `TargetCoreLibPrefixes` is the same, but for types/namespaces in `System.Private.CoreLib`. +- `FuzzTarget` is the logic that the fuzzer will run for every test input. It should exercise code from the target assemblies. + +Once you've created the new target, you can follow instructions above to run it locally. +Targets are discovered via reflection, so they will automatically become available for local runs and continuous fuzzing in CI. diff --git a/src/libraries/Fuzzing/nuget.config b/src/libraries/Fuzzing/nuget.config new file mode 100644 index 000000000000..9aa79050d312 --- /dev/null +++ b/src/libraries/Fuzzing/nuget.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs b/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs index 128a3174ad0c..505bc6668897 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs +++ b/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs @@ -38,7 +38,7 @@ public static class MathF /// public const float E = 2.71828183f; - private static float NegativeZero = Int32BitsToSingle(unchecked((int)0x80000000)); + private static readonly float NegativeZero = Int32BitsToSingle(unchecked((int)0x80000000)); private static unsafe float Int32BitsToSingle(int value) { diff --git a/src/libraries/Microsoft.Extensions.Caching.Abstractions/src/IMemoryCache.cs b/src/libraries/Microsoft.Extensions.Caching.Abstractions/src/IMemoryCache.cs index ccce249b23d9..8388a9f0433e 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Abstractions/src/IMemoryCache.cs +++ b/src/libraries/Microsoft.Extensions.Caching.Abstractions/src/IMemoryCache.cs @@ -31,7 +31,7 @@ public interface IMemoryCache : IDisposable /// An object identifying the entry. void Remove(object key); -#if NET6_0_OR_GREATER +#if NET /// /// Gets a snapshot of the cache statistics if available. /// diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/tests/MemoryCacheGetCurrentStatisticsTests.cs b/src/libraries/Microsoft.Extensions.Caching.Memory/tests/MemoryCacheGetCurrentStatisticsTests.cs index cee6245f3e9c..576b7e103aeb 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Memory/tests/MemoryCacheGetCurrentStatisticsTests.cs +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/tests/MemoryCacheGetCurrentStatisticsTests.cs @@ -106,7 +106,7 @@ public void GetCurrentStatistics_UpdateAfterExistingItemExpired_CurrentEstimated } } -#if NET6_0_OR_GREATER +#if NET [Fact] public void GetCurrentStatistics_DIMReturnsNull() { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs index d8c5a8925b46..1dceb31a0cc8 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs @@ -15,6 +15,7 @@ private sealed partial class Emitter private readonly TypeIndex _typeIndex; private readonly bool _emitEnumParseMethod; private readonly bool _emitGenericParseEnum; + private readonly bool _emitNotNullIfNotNull; private readonly bool _emitThrowIfNullMethod; private readonly SourceWriter _writer = new(); @@ -26,6 +27,7 @@ public Emitter(SourceGenerationSpec sourceGenSpec) _typeIndex = new TypeIndex(sourceGenSpec.ConfigTypes); _emitEnumParseMethod = sourceGenSpec.EmitEnumParseMethod; _emitGenericParseEnum = sourceGenSpec.EmitGenericParseEnum; + _emitNotNullIfNotNull = sourceGenSpec.EmitNotNullIfNotNull; _emitThrowIfNullMethod = sourceGenSpec.EmitThrowIfNullMethod; } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs index a569be384367..3d6e2b650310 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs @@ -57,6 +57,7 @@ internal sealed partial class Parser(CompilationData compilationData) ConfigTypes = _createdTypeSpecs.Values.OrderBy(s => s.TypeRef.FullyQualifiedName).ToImmutableEquatableArray(), EmitEnumParseMethod = _emitEnumParseMethod, EmitGenericParseEnum = _emitGenericParseEnum, + EmitNotNullIfNotNull = _typeSymbols.NotNullIfNotNullAttribute is not null, EmitThrowIfNullMethod = IsThrowIfNullMethodToBeEmitted() }; } @@ -660,6 +661,12 @@ private ObjectSpec CreateObjectSpec(TypeParseInfo typeParseInfo) if (member is IPropertySymbol { IsIndexer: false, IsImplicitlyDeclared: false } property && !IsUnsupportedType(property.Type)) { string propertyName = property.Name; + + if (property.IsOverride || properties?.ContainsKey(propertyName) is true) + { + continue; + } + TypeRef propertyTypeRef = EnqueueTransitiveType(typeParseInfo, property.Type, DiagnosticDescriptors.PropertyNotSupported, propertyName); AttributeData? attributeData = property.GetAttributes().FirstOrDefault(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, _typeSymbols.ConfigurationKeyNameAttribute)); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/ConfigurationBinder.cs index c6f23779ec93..f49cabc8bfc0 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/ConfigurationBinder.cs @@ -73,6 +73,7 @@ private void EmitGetValueMethods() if (ShouldEmitMethods(MethodsToGen.ConfigBinder_GetValue_T_key_defaultValue)) { EmitStartDefinition_Get_Or_GetValue_Overload(MethodsToGen.ConfigBinder_GetValue_T_key_defaultValue, documentation); + EmitNotNullIfNotNull(Identifier.defaultValue); _writer.WriteLine($"public static T? {Identifier.GetValue}(this {Identifier.IConfiguration} {Identifier.configuration}, string {Identifier.key}, T {Identifier.defaultValue}) => " + $"(T?)({expressionForGetValueCore}({Identifier.configuration}, typeof(T), {Identifier.key}) ?? {Identifier.defaultValue});"); } @@ -87,11 +88,20 @@ private void EmitGetValueMethods() if (ShouldEmitMethods(MethodsToGen.ConfigBinder_GetValue_TypeOf_key_defaultValue)) { EmitStartDefinition_Get_Or_GetValue_Overload(MethodsToGen.ConfigBinder_GetValue_TypeOf_key_defaultValue, documentation); + EmitNotNullIfNotNull(Identifier.defaultValue); _writer.WriteLine($"public static object? {Identifier.GetValue}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}, string {Identifier.key}, object? {Identifier.defaultValue}) => " + $"{expressionForGetValueCore}({Identifier.configuration}, {Identifier.type}, {Identifier.key}) ?? {Identifier.defaultValue};"); } } + private void EmitNotNullIfNotNull(string parameterName) + { + if (_emitNotNullIfNotNull) + { + _writer.WriteLine($"[return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof({parameterName}))]"); + } + } + private void EmitBindMethods_ConfigurationBinder() { if (!ShouldEmitMethods(MethodsToGen.ConfigBinder_Bind)) diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/CoreBindingHelpers.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/CoreBindingHelpers.cs index 49b7dd144c0e..179b7a65b78d 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/CoreBindingHelpers.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/CoreBindingHelpers.cs @@ -569,11 +569,11 @@ private void EmitGetBinderOptionsHelper() private void EmitEnumParseMethod() { - string exceptionArg1 = string.Format(ExceptionMessages.FailedBinding, $"{{{Identifier.getPath}()}}", $"{{typeof(T)}}"); + string exceptionArg1 = string.Format(ExceptionMessages.FailedBinding, $"{{{Identifier.path}}}", $"{{typeof(T)}}"); string parseEnumCall = _emitGenericParseEnum ? "Enum.Parse(value, ignoreCase: true)" : "(T)Enum.Parse(typeof(T), value, ignoreCase: true)"; _writer.WriteLine($$""" - public static T ParseEnum(string value, Func getPath) where T : struct + public static T ParseEnum(string value, string? path) where T : struct { try { @@ -639,9 +639,9 @@ private void EmitPrimitiveParseMethod(ParsableFromStringSpec type) } } - string exceptionArg1 = string.Format(ExceptionMessages.FailedBinding, $"{{{Identifier.getPath}()}}", $"{{typeof({typeFQN})}}"); + string exceptionArg1 = string.Format(ExceptionMessages.FailedBinding, $"{{{Identifier.path}}}", $"{{typeof({typeFQN})}}"); - EmitStartBlock($"public static {typeFQN} {TypeIndex.GetParseMethodName(type)}(string {Identifier.value}, Func {Identifier.getPath})"); + EmitStartBlock($"public static {typeFQN} {TypeIndex.GetParseMethodName(type)}(string {Identifier.value}, string? {Identifier.path})"); EmitEndBlock($$""" try { @@ -1084,8 +1084,8 @@ private void EmitBindingLogic( string parsedValueExpr = typeKind switch { StringParsableTypeKind.AssignFromSectionValue => stringValueToParse_Expr, - StringParsableTypeKind.Enum => $"ParseEnum<{type.TypeRef.FullyQualifiedName}>({stringValueToParse_Expr}, () => {sectionPathExpr})", - _ => $"{TypeIndex.GetParseMethodName(type)}({stringValueToParse_Expr}, () => {sectionPathExpr})", + StringParsableTypeKind.Enum => $"ParseEnum<{type.TypeRef.FullyQualifiedName}>({stringValueToParse_Expr}, {sectionPathExpr})", + _ => $"{TypeIndex.GetParseMethodName(type)}({stringValueToParse_Expr}, {sectionPathExpr})", }; if (!checkForNullSectionValue) diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/Helpers.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/Helpers.cs index 3a0200d68430..cf56aae81ba4 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/Helpers.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/Helpers.cs @@ -71,12 +71,12 @@ private static class Identifier public const string element = nameof(element); public const string enumValue = nameof(enumValue); public const string exception = nameof(exception); - public const string getPath = nameof(getPath); public const string key = nameof(key); public const string name = nameof(name); public const string instance = nameof(instance); public const string optionsBuilder = nameof(optionsBuilder); public const string originalCount = nameof(originalCount); + public const string path = nameof(path); public const string section = nameof(section); public const string sectionKey = nameof(sectionKey); public const string services = nameof(services); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Parser/KnownTypeSymbols.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Parser/KnownTypeSymbols.cs index 89ff70db196b..2f084ec7bdfc 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Parser/KnownTypeSymbols.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Parser/KnownTypeSymbols.cs @@ -64,6 +64,7 @@ internal sealed class KnownTypeSymbols public INamedTypeSymbol? MemberInfo { get; } public INamedTypeSymbol? ParameterInfo { get; } public INamedTypeSymbol? Delegate { get; } + public INamedTypeSymbol? NotNullIfNotNullAttribute { get; } public KnownTypeSymbols(CSharpCompilation compilation) { @@ -132,6 +133,9 @@ public KnownTypeSymbols(CSharpCompilation compilation) IntPtr = Compilation.GetSpecialType(SpecialType.System_IntPtr); UIntPtr = Compilation.GetSpecialType(SpecialType.System_UIntPtr); Delegate = Compilation.GetSpecialType(SpecialType.System_Delegate); + + // Only generate nullable attributes if available + NotNullIfNotNullAttribute = compilation.GetBestTypeByMetadataName("System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute"); } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/SourceGenerationSpec.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/SourceGenerationSpec.cs index c4fc5a6079ad..e435ffa0cd0b 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/SourceGenerationSpec.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/SourceGenerationSpec.cs @@ -12,6 +12,7 @@ public sealed record SourceGenerationSpec public required ImmutableEquatableArray ConfigTypes { get; init; } public required bool EmitEnumParseMethod { get; set; } public required bool EmitGenericParseEnum { get; set; } + public required bool EmitNotNullIfNotNull { get; set; } public required bool EmitThrowIfNullMethod { get; set; } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.cs index 0f28d4f2fb9a..c0ee592ed6b8 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.cs @@ -32,10 +32,12 @@ public static void Bind(this Microsoft.Extensions.Configuration.IConfiguration c [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] public static object? GetValue(this Microsoft.Extensions.Configuration.IConfiguration configuration, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, string key) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))] public static object? GetValue(this Microsoft.Extensions.Configuration.IConfiguration configuration, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, string key, object? defaultValue) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] public static T? GetValue<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] T>(this Microsoft.Extensions.Configuration.IConfiguration configuration, string key) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))] public static T? GetValue<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] T>(this Microsoft.Extensions.Configuration.IConfiguration configuration, string key, T defaultValue) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs index c6783555ca47..060d1f55d72a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs @@ -167,6 +167,7 @@ public static void Bind(this IConfiguration configuration, object? instance, Act /// The default value to use if no value is found. /// The converted value. [RequiresUnreferencedCode(TrimmingWarningMessage)] + [return: NotNullIfNotNull(nameof(defaultValue))] public static T? GetValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(this IConfiguration configuration, string key, T defaultValue) { return (T?)GetValue(configuration, typeof(T), key, defaultValue); @@ -198,6 +199,7 @@ public static void Bind(this IConfiguration configuration, object? instance, Act /// The default value to use if no value is found. /// The converted value. [RequiresUnreferencedCode(TrimmingWarningMessage)] + [return: NotNullIfNotNull(nameof(defaultValue))] public static object? GetValue( this IConfiguration configuration, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] @@ -950,7 +952,7 @@ private static bool TypeIsASetInterface(Type type) Type genericTypeDefinition = type.GetGenericTypeDefinition(); return genericTypeDefinition == typeof(ISet<>) -#if NETCOREAPP +#if NET || genericTypeDefinition == typeof(IReadOnlySet<>) #endif ; diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Collections.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Collections.cs index 73afe160f28f..06b44553ab9f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Collections.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Collections.cs @@ -1532,7 +1532,7 @@ public void CanBindISetNoSetter() Assert.Equal("Yo2", options.ISetNoSetter.ElementAt(1)); } -#if NETCOREAPP +#if NET [Fact] public void CanBindInstantiatedIReadOnlySet() { @@ -2291,7 +2291,7 @@ public void TestOptionsWithDifferentCollectionInterfaces() Assert.True(3 == options.UnInstantiatedISet.Count(), $"UnInstantiatedISet count is {options.UnInstantiatedISet.Count()} .. {options.UnInstantiatedISet.ElementAt(options.UnInstantiatedISet.Count() - 1)}"); Assert.Equal(new string[] { "a", "A", "B" }, options.UnInstantiatedISet); -#if NETCOREAPP +#if NET Assert.True(3 == options.InstantiatedIReadOnlySet.Count(), $"InstantiatedIReadOnlySet count is {options.InstantiatedIReadOnlySet.Count()} .. {options.InstantiatedIReadOnlySet.ElementAt(options.InstantiatedIReadOnlySet.Count() - 1)}"); Assert.Equal(new string[] { "a", "b", "Z" }, options.InstantiatedIReadOnlySet); Assert.False(options.IsSameInstantiatedIReadOnlySet()); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Helpers.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Helpers.cs index d6521ed86dfd..488e9b81c99d 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Helpers.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.Helpers.cs @@ -109,7 +109,7 @@ public string ReadOnly public ISet UninstantiatedHashSetWithUnsupportedKey { get; set; } -#if NETCOREAPP +#if NET public IReadOnlySet InstantiatedIReadOnlySet { get; set; } = new HashSet(); public IReadOnlySet InstantiatedIReadOnlySetWithSomeValues { get; set; } = new HashSet(new[] { "existing1", "existing2" }); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.Collections.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.Collections.cs index c8f672eb7fdb..30d1fc8dc5b8 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.Collections.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.Collections.cs @@ -354,7 +354,7 @@ public class OptionsWithDifferentCollectionInterfaces public ISet InstantiatedISet { get; set; } = s_instantiatedISet; public bool IsSameInstantiatedISet() => object.ReferenceEquals(s_instantiatedISet, InstantiatedISet); -#if NETCOREAPP +#if NET private static IReadOnlySet s_instantiatedIReadOnlySet = new HashSet(StringComparer.OrdinalIgnoreCase) { "a", "A", "b" }; public IReadOnlySet InstantiatedIReadOnlySet { get; set; } = s_instantiatedIReadOnlySet; public bool IsSameInstantiatedIReadOnlySet() => object.ReferenceEquals(s_instantiatedIReadOnlySet, InstantiatedIReadOnlySet); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs index 9aad9566463a..b7ef3cba018e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs @@ -743,7 +743,7 @@ public record RecordWithPrimitives public Uri Prop25 { get; set; } public Version Prop26 { get; set; } public DayOfWeek Prop27 { get; set; } -#if NETCOREAPP +#if NET public Int128 Prop7 { get; set; } public Half Prop11 { get; set; } public UInt128 Prop12 { get; set; } @@ -930,5 +930,64 @@ public class SimplePoco public string B { get; set; } } + public class BaseForHiddenMembers + { + public string A { get; set; } + public string B { get; set; } + public TestSettingsEnum E {get; set;} + + public virtual string C { get => CBase; set => CBase = value; } + + public string CBase; + + public virtual string D { get; } + + public virtual string F { get => FBase; set => FBase = value; } + public string FBase; + + + public virtual int X { get => XBase; set => XBase = value; } + public int XBase; + } + + public enum TestSettingsEnum2 + { + // Note - the reflection binder will try to bind to every member + Option1 = TestSettingsEnum.Option1, + Option2 = TestSettingsEnum.Option2, + } + + public class IntermediateDerivedClass : BaseForHiddenMembers + { + public new virtual string D { get => DBase; set => DBase = value; } + public string DBase; + + public override string F { get => "IF"; } + + } + + public class DerivedClassWithHiddenMembers : IntermediateDerivedClass + { + public new string A { get; } = "ADerived"; + public new int B { get; set; } + public new TestSettingsEnum2 E + { + get => (TestSettingsEnum2)base.E; + set => base.E = (TestSettingsEnum)value; + } + + // only override get + public override string C { get => "DC"; } + + // override new only get + public override string D { get => "DD"; } + + // two overrides of only get + public override string F { get => "DF"; } + + // override only set + public override int X { set => base.X = value + 1; } + } + } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs index 366c7ed44d82..4986778a87ce 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs @@ -326,11 +326,15 @@ public void CanBindToObjectProperty() [Fact] public void GetNullValue() { - var dic = new Dictionary + #nullable enable + #pragma warning disable IDE0004 // Cast is redundant + + var dic = new Dictionary { {"Integer", null}, {"Boolean", null}, {"Nested:Integer", null}, + {"String", null}, {"Object", null } }; var configurationBuilder = new ConfigurationBuilder(); @@ -341,13 +345,16 @@ public void GetNullValue() Assert.False(config.GetValue("Boolean")); Assert.Equal(0, config.GetValue("Integer")); Assert.Equal(0, config.GetValue("Nested:Integer")); + Assert.Null(config.GetValue("String")); Assert.Null(config.GetValue("Object")); // Generic overloads with default value. - Assert.True(config.GetValue("Boolean", true)); - Assert.Equal(1, config.GetValue("Integer", 1)); - Assert.Equal(1, config.GetValue("Nested:Integer", 1)); - Assert.Equal(new NestedConfig(""), config.GetValue("Object", new NestedConfig(""))); + Assert.True((bool)config.GetValue("Boolean", true)); + Assert.Equal(1, (int)config.GetValue("Integer", 1)); + Assert.Equal(1, (int)config.GetValue("Nested:Integer", 1)); + // [NotNullIfNotNull] avoids CS8600: Converting possible null value to non-nullable type. + Assert.Equal("s", (string)config.GetValue("String", "s")); + Assert.Equal(new NestedConfig(""), (NestedConfig)config.GetValue("Object", new NestedConfig(""))); // Type overloads. Assert.Null(config.GetValue(typeof(bool), "Boolean")); @@ -356,16 +363,22 @@ public void GetNullValue() Assert.Null(config.GetValue(typeof(ComplexOptions), "Object")); // Type overloads with default value. + // [NotNullIfNotNull] avoids CS8605: Unboxing a possibly null value. Assert.True((bool)config.GetValue(typeof(bool), "Boolean", true)); Assert.Equal(1, (int)config.GetValue(typeof(int), "Integer", 1)); Assert.Equal(1, (int)config.GetValue(typeof(int), "Nested:Integer", 1)); - Assert.Equal(new NestedConfig(""), config.GetValue("Object", new NestedConfig(""))); + // [NotNullIfNotNull] avoids CS8600: Converting possible null value to non-nullable type. + Assert.Equal("s", (string)config.GetValue(typeof(string), "String", "s")); + Assert.Equal(new NestedConfig(""), (NestedConfig)config.GetValue("Object", new NestedConfig(""))); // GetSection tests. Assert.False(config.GetSection("Boolean").Get()); Assert.Equal(0, config.GetSection("Integer").Get()); Assert.Equal(0, config.GetSection("Nested:Integer").Get()); Assert.Null(config.GetSection("Object").Get()); + + #pragma warning restore IDE0004 + #nullable restore } [Fact] @@ -1958,7 +1971,7 @@ public void TypeWithPrimitives_Pass() #endif Assert.Equal(CultureInfo.GetCultureInfo("yo-NG"), obj.Prop17); -#if NETCOREAPP +#if NET data = @"{ ""Prop7"": 9, ""Prop11"": 65500, @@ -2119,6 +2132,7 @@ public void ComplexObj_As_Enumerable_Element() #if !BUILDING_SOURCE_GENERATOR_TESTS [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/91923", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsAppleMobile))] public void TraceSwitchTest() { var dic = new Dictionary @@ -2132,10 +2146,10 @@ public void TraceSwitchTest() TraceSwitch ts = new(displayName: "TraceSwitch", description: "This switch is set via config."); ConfigurationBinder.Bind(config, "TraceSwitch", ts); Assert.Equal(TraceLevel.Info, ts.Level); -#if NETCOREAPP +#if NET // Value property is not publicly exposed in .NET Framework. Assert.Equal("Info", ts.Value); -#endif // NETCOREAPP +#endif // NET } #endif @@ -2148,6 +2162,7 @@ private void ValidateGeolocation(IGeolocation location) [Fact] #if !BUILDING_SOURCE_GENERATOR_TESTS [ActiveIssue("Investigate Build browser-wasm linux Release LibraryTests_EAT CI failure for reflection impl", TestPlatforms.Browser)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/91923", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsAppleMobile))] #endif public void TestGraphWithUnsupportedMember() { @@ -2469,5 +2484,67 @@ public MockConfigurationRoot(IList providers) : base(pro IConfigurationSection IConfiguration.GetSection(string key) => this[key] is null ? null : new ConfigurationSection(this, key); } + + [Fact] + public void CanBindToClassWithNewProperties() + { + /// the source generator will bind to the most derived property only. + /// the reflection binder will bind the same data to all properties (including hidden). + + var config = TestHelpers.GetConfigurationFromJsonString(""" + { + "A": "AVal", + "B": "5", + "C": "CVal", + "D": "DVal", + "E": "Option2", + "F": "FVal", + "X": "52" + } + """); + var obj = new DerivedClassWithHiddenMembers(); + + config.Bind(obj); + + BaseForHiddenMembers baseObj = obj; + IntermediateDerivedClass intermediateObj = obj; + + Assert.Equal("ADerived", obj.A); +#if BUILDING_SOURCE_GENERATOR_TESTS + // source generator will not set hidden property + Assert.Null(baseObj.A); +#else + // reflection binder will set hidden property + Assert.Equal("AVal", baseObj.A); +#endif + + Assert.Equal(5, obj.B); +#if BUILDING_SOURCE_GENERATOR_TESTS + // source generator will not set hidden property + Assert.Null(baseObj.B); +#else + // reflection binder will set hidden property + Assert.Equal("5", baseObj.B); +#endif + + Assert.Equal(TestSettingsEnum2.Option2, obj.E); + Assert.Equal(TestSettingsEnum.Option2, baseObj.E); + + Assert.Equal("DC", obj.C); + // The setter should still be called, even when only getter is overridden. + Assert.Equal("CVal", obj.CBase); + + // can hide a readonly property with r/w property + Assert.Null(baseObj.D); + Assert.Equal("DD", obj.D); + // The setter should still be called, even when only getter is overridden. + Assert.Equal("DVal", obj.DBase); + + Assert.Equal("DF", obj.F); + Assert.Equal("FVal", obj.FBase); + + Assert.Equal(53, obj.X); + Assert.Equal(53, obj.XBase); + } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Collections.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Collections.generated.txt index a03d4c855c39..54c0b42cc3f0 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Collections.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Collections.generated.txt @@ -73,7 +73,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance[section.Key] = ParseInt(value, () => section.Path); + instance[section.Key] = ParseInt(value, section.Path); } } } @@ -100,7 +100,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - temp.Add(ParseInt(value, () => section.Path)); + temp.Add(ParseInt(value, section.Path)); } } } @@ -116,7 +116,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - temp[section.Key] = ParseInt(value, () => section.Path); + temp[section.Key] = ParseInt(value, section.Path); } } } @@ -217,7 +217,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -225,7 +225,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind.generated.txt index 8cb6fa53a52e..1b64f116d250 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind.generated.txt @@ -98,7 +98,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -137,7 +137,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -219,7 +219,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -227,7 +227,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind_Instance.generated.txt index 392f067b9c36..c80e48e19e15 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind_Instance.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind_Instance.generated.txt @@ -62,7 +62,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -101,7 +101,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -165,7 +165,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return null; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -173,7 +173,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind_Instance_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind_Instance_BinderOptions.generated.txt index 35f4495fe0c1..efb7616cd1b9 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind_Instance_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind_Instance_BinderOptions.generated.txt @@ -62,7 +62,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -101,7 +101,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -183,7 +183,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -191,7 +191,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind_Key_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind_Key_Instance.generated.txt index 6373c432f524..c8f211fe59de 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind_Key_Instance.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Bind_Key_Instance.generated.txt @@ -62,7 +62,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -101,7 +101,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -165,7 +165,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return null; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -173,7 +173,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get.generated.txt index b51fefddba98..c9b1f23de26c 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get.generated.txt @@ -91,7 +91,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -104,7 +104,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - temp2.Add(ParseInt(value, () => section.Path)); + temp2.Add(ParseInt(value, section.Path)); } } @@ -135,7 +135,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value4) { - instance.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -173,7 +173,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value14) { - instance.MyInt = ParseInt(value14, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value14, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -240,7 +240,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -248,7 +248,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue.generated.txt index e6fb4b5166ed..7466c543a85e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue.generated.txt @@ -67,25 +67,25 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (type == typeof(int)) { - return ParseInt(value, () => section.Path); + return ParseInt(value, section.Path); } else if (type == typeof(bool?)) { - return ParseBool(value, () => section.Path); + return ParseBool(value, section.Path); } else if (type == typeof(byte[])) { - return ParseByteArray(value, () => section.Path); + return ParseByteArray(value, section.Path); } else if (type == typeof(global::System.Globalization.CultureInfo)) { - return ParseSystemGlobalizationCultureInfo(value, () => section.Path); + return ParseSystemGlobalizationCultureInfo(value, section.Path); } return null; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -93,11 +93,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } - public static bool ParseBool(string value, Func getPath) + public static bool ParseBool(string value, string? path) { try { @@ -105,11 +105,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(bool)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(bool)}'.", exception); } } - public static byte[] ParseByteArray(string value, Func getPath) + public static byte[] ParseByteArray(string value, string? path) { try { @@ -117,11 +117,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(byte[])}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(byte[])}'.", exception); } } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, Func getPath) + public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) { try { @@ -129,7 +129,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_T_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_T_Key.generated.txt index 273df87c8e80..4f822c0f75d6 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_T_Key.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_T_Key.generated.txt @@ -55,13 +55,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (type == typeof(int)) { - return ParseInt(value, () => section.Path); + return ParseInt(value, section.Path); } return null; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -69,7 +69,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt index b3d91eb6b49e..f7fe233d3569 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt @@ -55,13 +55,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (type == typeof(int)) { - return ParseInt(value, () => section.Path); + return ParseInt(value, section.Path); } return null; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -69,7 +69,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_TypeOf_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_TypeOf_Key.generated.txt index b8c1c5b13819..644f3ce18e82 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_TypeOf_Key.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_TypeOf_Key.generated.txt @@ -55,13 +55,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (type == typeof(bool?)) { - return ParseBool(value, () => section.Path); + return ParseBool(value, section.Path); } return null; } - public static bool ParseBool(string value, Func getPath) + public static bool ParseBool(string value, string? path) { try { @@ -69,7 +69,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(bool)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(bool)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt index f93fb114275f..ebf24068b77f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt @@ -55,13 +55,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (type == typeof(global::System.Globalization.CultureInfo)) { - return ParseSystemGlobalizationCultureInfo(value, () => section.Path); + return ParseSystemGlobalizationCultureInfo(value, section.Path); } return null; } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, Func getPath) + public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) { try { @@ -69,7 +69,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_PrimitivesOnly.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_PrimitivesOnly.generated.txt index 446bf43866a3..29d5a787ef3b 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_PrimitivesOnly.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_PrimitivesOnly.generated.txt @@ -73,7 +73,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (section.Value is string value) { - return ParseInt(value, () => section.Path); + return ParseInt(value, section.Path); } } else if (type == typeof(string)) @@ -92,7 +92,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (section.Value is string value) { - return ParseFloat(value, () => section.Path); + return ParseFloat(value, section.Path); } } else if (type == typeof(double)) @@ -103,7 +103,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (section.Value is string value) { - return ParseDouble(value, () => section.Path); + return ParseDouble(value, section.Path); } } @@ -146,7 +146,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -154,11 +154,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } - public static float ParseFloat(string value, Func getPath) + public static float ParseFloat(string value, string? path) { try { @@ -166,11 +166,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(float)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(float)}'.", exception); } } - public static double ParseDouble(string value, Func getPath) + public static double ParseDouble(string value, string? path) { try { @@ -178,7 +178,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(double)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(double)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_T.generated.txt index 8eecd3ba72a1..470d6857874f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_T.generated.txt @@ -72,7 +72,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -85,7 +85,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - temp1.Add(ParseInt(value, () => section.Path)); + temp1.Add(ParseInt(value, section.Path)); } } @@ -116,7 +116,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value3) { - instance.MyInt = ParseInt(value3, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value3, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -207,7 +207,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -215,7 +215,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_T_BinderOptions.generated.txt index ec88c39f20a2..3f0d165c40c1 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_T_BinderOptions.generated.txt @@ -72,7 +72,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -85,7 +85,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - temp1.Add(ParseInt(value, () => section.Path)); + temp1.Add(ParseInt(value, section.Path)); } } @@ -116,7 +116,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value3) { - instance.MyInt = ParseInt(value3, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value3, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -207,7 +207,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -215,7 +215,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_TypeOf.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_TypeOf.generated.txt index 46c24547478a..5b5050214620 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_TypeOf.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_TypeOf.generated.txt @@ -72,7 +72,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -139,7 +139,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -147,7 +147,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_TypeOf_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_TypeOf_BinderOptions.generated.txt index f37307065a78..039e2eecef84 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_TypeOf_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Get_TypeOf_BinderOptions.generated.txt @@ -72,7 +72,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -139,7 +139,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -147,7 +147,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/DefaultConstructorParameters.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/DefaultConstructorParameters.generated.txt index e76b1450e472..3780c1a56ce1 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/DefaultConstructorParameters.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/DefaultConstructorParameters.generated.txt @@ -78,73 +78,73 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration int age = (int)(42); if (configuration["Age"] is string value2) { - age = ParseInt(value2, () => configuration.GetSection("Age").Path); + age = ParseInt(value2, configuration.GetSection("Age").Path); } float f = 42F; if (configuration["F"] is string value3) { - f = ParseFloat(value3, () => configuration.GetSection("F").Path); + f = ParseFloat(value3, configuration.GetSection("F").Path); } double d = 3.1415899999999999D; if (configuration["D"] is string value4) { - d = ParseDouble(value4, () => configuration.GetSection("D").Path); + d = ParseDouble(value4, configuration.GetSection("D").Path); } decimal m = 3.1415926535897932384626433M; if (configuration["M"] is string value5) { - m = ParseDecimal(value5, () => configuration.GetSection("M").Path); + m = ParseDecimal(value5, configuration.GetSection("M").Path); } global::System.StringComparison sc = (global::System.StringComparison)(4); if (configuration["SC"] is string value6) { - sc = ParseEnum(value6, () => configuration.GetSection("SC").Path); + sc = ParseEnum(value6, configuration.GetSection("SC").Path); } char c = 'q'; if (configuration["C"] is string value7) { - c = ParseChar(value7, () => configuration.GetSection("C").Path); + c = ParseChar(value7, configuration.GetSection("C").Path); } int? nage = (int?)(42); if (configuration["NAge"] is string value8) { - nage = ParseInt(value8, () => configuration.GetSection("NAge").Path); + nage = ParseInt(value8, configuration.GetSection("NAge").Path); } float? nf = 42F; if (configuration["NF"] is string value9) { - nf = ParseFloat(value9, () => configuration.GetSection("NF").Path); + nf = ParseFloat(value9, configuration.GetSection("NF").Path); } double? nd = 3.1415899999999999D; if (configuration["ND"] is string value10) { - nd = ParseDouble(value10, () => configuration.GetSection("ND").Path); + nd = ParseDouble(value10, configuration.GetSection("ND").Path); } decimal? nm = 3.1415926535897932384626433M; if (configuration["NM"] is string value11) { - nm = ParseDecimal(value11, () => configuration.GetSection("NM").Path); + nm = ParseDecimal(value11, configuration.GetSection("NM").Path); } global::System.StringComparison? nsc = (global::System.StringComparison?)(4); if (configuration["NSC"] is string value12) { - nsc = ParseEnum(value12, () => configuration.GetSection("NSC").Path); + nsc = ParseEnum(value12, configuration.GetSection("NSC").Path); } char? nc = 'q'; if (configuration["NC"] is string value13) { - nc = ParseChar(value13, () => configuration.GetSection("NC").Path); + nc = ParseChar(value13, configuration.GetSection("NC").Path); } return new global::Program.ClassWhereParametersHaveDefaultValue(name, address, age, f, d, m, sc, c, nage, nf, nd, nm, nsc, nc); @@ -173,7 +173,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static T ParseEnum(string value, Func getPath) where T : struct + public static T ParseEnum(string value, string? path) where T : struct { try { @@ -181,11 +181,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(T)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(T)}'.", exception); } } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -193,11 +193,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } - public static float ParseFloat(string value, Func getPath) + public static float ParseFloat(string value, string? path) { try { @@ -205,11 +205,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(float)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(float)}'.", exception); } } - public static double ParseDouble(string value, Func getPath) + public static double ParseDouble(string value, string? path) { try { @@ -217,11 +217,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(double)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(double)}'.", exception); } } - public static decimal ParseDecimal(string value, Func getPath) + public static decimal ParseDecimal(string value, string? path) { try { @@ -229,11 +229,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(decimal)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(decimal)}'.", exception); } } - public static char ParseChar(string value, Func getPath) + public static char ParseChar(string value, string? path) { try { @@ -241,7 +241,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(char)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(char)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/BindConfiguration.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/BindConfiguration.generated.txt index e5b2254220fc..87515b8b4b32 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/BindConfiguration.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/BindConfiguration.generated.txt @@ -103,7 +103,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -119,7 +119,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value2) { - instance.MyInt = ParseInt(value2, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -194,7 +194,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -202,7 +202,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Bind_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Bind_T.generated.txt index 1907c5259932..8b31876d5bac 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Bind_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Bind_T.generated.txt @@ -109,7 +109,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -125,7 +125,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value2) { - instance.MyInt = ParseInt(value2, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -200,7 +200,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -208,7 +208,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Bind_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Bind_T_BinderOptions.generated.txt index b3eb6354b5db..e58ef0662ee2 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Bind_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Bind_T_BinderOptions.generated.txt @@ -103,7 +103,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -119,7 +119,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value2) { - instance.MyInt = ParseInt(value2, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -194,7 +194,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -202,7 +202,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Primitives.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Primitives.generated.txt index 90c6a72aa4e5..39cfc67e44f9 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Primitives.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Primitives.generated.txt @@ -62,7 +62,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop0"] is string value0) { - instance.Prop0 = ParseBool(value0, () => configuration.GetSection("Prop0").Path); + instance.Prop0 = ParseBool(value0, configuration.GetSection("Prop0").Path); } else if (defaultValueIfNotFound) { @@ -71,7 +71,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop1"] is string value1) { - instance.Prop1 = ParseByte(value1, () => configuration.GetSection("Prop1").Path); + instance.Prop1 = ParseByte(value1, configuration.GetSection("Prop1").Path); } else if (defaultValueIfNotFound) { @@ -80,7 +80,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop2"] is string value2) { - instance.Prop2 = ParseSbyte(value2, () => configuration.GetSection("Prop2").Path); + instance.Prop2 = ParseSbyte(value2, configuration.GetSection("Prop2").Path); } else if (defaultValueIfNotFound) { @@ -89,7 +89,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop3"] is string value3) { - instance.Prop3 = ParseChar(value3, () => configuration.GetSection("Prop3").Path); + instance.Prop3 = ParseChar(value3, configuration.GetSection("Prop3").Path); } else if (defaultValueIfNotFound) { @@ -98,7 +98,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop4"] is string value4) { - instance.Prop4 = ParseDouble(value4, () => configuration.GetSection("Prop4").Path); + instance.Prop4 = ParseDouble(value4, configuration.GetSection("Prop4").Path); } else if (defaultValueIfNotFound) { @@ -112,7 +112,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop6"] is string value6) { - instance.Prop6 = ParseInt(value6, () => configuration.GetSection("Prop6").Path); + instance.Prop6 = ParseInt(value6, configuration.GetSection("Prop6").Path); } else if (defaultValueIfNotFound) { @@ -121,7 +121,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop8"] is string value7) { - instance.Prop8 = ParseShort(value7, () => configuration.GetSection("Prop8").Path); + instance.Prop8 = ParseShort(value7, configuration.GetSection("Prop8").Path); } else if (defaultValueIfNotFound) { @@ -130,7 +130,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop9"] is string value8) { - instance.Prop9 = ParseLong(value8, () => configuration.GetSection("Prop9").Path); + instance.Prop9 = ParseLong(value8, configuration.GetSection("Prop9").Path); } else if (defaultValueIfNotFound) { @@ -139,7 +139,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop10"] is string value9) { - instance.Prop10 = ParseFloat(value9, () => configuration.GetSection("Prop10").Path); + instance.Prop10 = ParseFloat(value9, configuration.GetSection("Prop10").Path); } else if (defaultValueIfNotFound) { @@ -148,7 +148,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop13"] is string value10) { - instance.Prop13 = ParseUshort(value10, () => configuration.GetSection("Prop13").Path); + instance.Prop13 = ParseUshort(value10, configuration.GetSection("Prop13").Path); } else if (defaultValueIfNotFound) { @@ -157,7 +157,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop14"] is string value11) { - instance.Prop14 = ParseUint(value11, () => configuration.GetSection("Prop14").Path); + instance.Prop14 = ParseUint(value11, configuration.GetSection("Prop14").Path); } else if (defaultValueIfNotFound) { @@ -166,7 +166,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop15"] is string value12) { - instance.Prop15 = ParseUlong(value12, () => configuration.GetSection("Prop15").Path); + instance.Prop15 = ParseUlong(value12, configuration.GetSection("Prop15").Path); } else if (defaultValueIfNotFound) { @@ -180,12 +180,12 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop17"] is string value14) { - instance.Prop17 = ParseSystemGlobalizationCultureInfo(value14, () => configuration.GetSection("Prop17").Path); + instance.Prop17 = ParseSystemGlobalizationCultureInfo(value14, configuration.GetSection("Prop17").Path); } if (configuration["Prop19"] is string value15) { - instance.Prop19 = ParseSystemDateTime(value15, () => configuration.GetSection("Prop19").Path); + instance.Prop19 = ParseSystemDateTime(value15, configuration.GetSection("Prop19").Path); } else if (defaultValueIfNotFound) { @@ -194,7 +194,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop20"] is string value16) { - instance.Prop20 = ParseSystemDateTimeOffset(value16, () => configuration.GetSection("Prop20").Path); + instance.Prop20 = ParseSystemDateTimeOffset(value16, configuration.GetSection("Prop20").Path); } else if (defaultValueIfNotFound) { @@ -203,7 +203,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop21"] is string value17) { - instance.Prop21 = ParseDecimal(value17, () => configuration.GetSection("Prop21").Path); + instance.Prop21 = ParseDecimal(value17, configuration.GetSection("Prop21").Path); } else if (defaultValueIfNotFound) { @@ -212,7 +212,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop23"] is string value18) { - instance.Prop23 = ParseSystemTimeSpan(value18, () => configuration.GetSection("Prop23").Path); + instance.Prop23 = ParseSystemTimeSpan(value18, configuration.GetSection("Prop23").Path); } else if (defaultValueIfNotFound) { @@ -221,7 +221,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop24"] is string value19) { - instance.Prop24 = ParseSystemGuid(value19, () => configuration.GetSection("Prop24").Path); + instance.Prop24 = ParseSystemGuid(value19, configuration.GetSection("Prop24").Path); } else if (defaultValueIfNotFound) { @@ -230,17 +230,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop25"] is string value20) { - instance.Prop25 = ParseSystemUri(value20, () => configuration.GetSection("Prop25").Path); + instance.Prop25 = ParseSystemUri(value20, configuration.GetSection("Prop25").Path); } if (configuration["Prop26"] is string value21) { - instance.Prop26 = ParseSystemVersion(value21, () => configuration.GetSection("Prop26").Path); + instance.Prop26 = ParseSystemVersion(value21, configuration.GetSection("Prop26").Path); } if (configuration["Prop27"] is string value22) { - instance.Prop27 = ParseEnum(value22, () => configuration.GetSection("Prop27").Path); + instance.Prop27 = ParseEnum(value22, configuration.GetSection("Prop27").Path); } else if (defaultValueIfNotFound) { @@ -249,12 +249,12 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop28"] is string value23) { - instance.Prop28 = ParseByteArray(value23, () => configuration.GetSection("Prop28").Path); + instance.Prop28 = ParseByteArray(value23, configuration.GetSection("Prop28").Path); } if (configuration["Prop29"] is string value24) { - instance.Prop29 = ParseInt(value24, () => configuration.GetSection("Prop29").Path); + instance.Prop29 = ParseInt(value24, configuration.GetSection("Prop29").Path); } else if (defaultValueIfNotFound) { @@ -263,7 +263,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop30"] is string value25) { - instance.Prop30 = ParseSystemDateTime(value25, () => configuration.GetSection("Prop30").Path); + instance.Prop30 = ParseSystemDateTime(value25, configuration.GetSection("Prop30").Path); } else if (defaultValueIfNotFound) { @@ -294,7 +294,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static T ParseEnum(string value, Func getPath) where T : struct + public static T ParseEnum(string value, string? path) where T : struct { try { @@ -302,11 +302,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(T)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(T)}'.", exception); } } - public static bool ParseBool(string value, Func getPath) + public static bool ParseBool(string value, string? path) { try { @@ -314,11 +314,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(bool)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(bool)}'.", exception); } } - public static byte ParseByte(string value, Func getPath) + public static byte ParseByte(string value, string? path) { try { @@ -326,11 +326,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(byte)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(byte)}'.", exception); } } - public static sbyte ParseSbyte(string value, Func getPath) + public static sbyte ParseSbyte(string value, string? path) { try { @@ -338,11 +338,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(sbyte)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(sbyte)}'.", exception); } } - public static char ParseChar(string value, Func getPath) + public static char ParseChar(string value, string? path) { try { @@ -350,11 +350,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(char)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(char)}'.", exception); } } - public static double ParseDouble(string value, Func getPath) + public static double ParseDouble(string value, string? path) { try { @@ -362,11 +362,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(double)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(double)}'.", exception); } } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -374,11 +374,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } - public static short ParseShort(string value, Func getPath) + public static short ParseShort(string value, string? path) { try { @@ -386,11 +386,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(short)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(short)}'.", exception); } } - public static long ParseLong(string value, Func getPath) + public static long ParseLong(string value, string? path) { try { @@ -398,11 +398,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(long)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(long)}'.", exception); } } - public static float ParseFloat(string value, Func getPath) + public static float ParseFloat(string value, string? path) { try { @@ -410,11 +410,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(float)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(float)}'.", exception); } } - public static ushort ParseUshort(string value, Func getPath) + public static ushort ParseUshort(string value, string? path) { try { @@ -422,11 +422,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(ushort)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(ushort)}'.", exception); } } - public static uint ParseUint(string value, Func getPath) + public static uint ParseUint(string value, string? path) { try { @@ -434,11 +434,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(uint)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(uint)}'.", exception); } } - public static ulong ParseUlong(string value, Func getPath) + public static ulong ParseUlong(string value, string? path) { try { @@ -446,11 +446,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(ulong)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(ulong)}'.", exception); } } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, Func getPath) + public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) { try { @@ -458,11 +458,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); } } - public static global::System.DateTime ParseSystemDateTime(string value, Func getPath) + public static global::System.DateTime ParseSystemDateTime(string value, string? path) { try { @@ -470,11 +470,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.DateTime)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.DateTime)}'.", exception); } } - public static global::System.DateTimeOffset ParseSystemDateTimeOffset(string value, Func getPath) + public static global::System.DateTimeOffset ParseSystemDateTimeOffset(string value, string? path) { try { @@ -482,11 +482,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.DateTimeOffset)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.DateTimeOffset)}'.", exception); } } - public static decimal ParseDecimal(string value, Func getPath) + public static decimal ParseDecimal(string value, string? path) { try { @@ -494,11 +494,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(decimal)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(decimal)}'.", exception); } } - public static global::System.TimeSpan ParseSystemTimeSpan(string value, Func getPath) + public static global::System.TimeSpan ParseSystemTimeSpan(string value, string? path) { try { @@ -506,11 +506,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.TimeSpan)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.TimeSpan)}'.", exception); } } - public static global::System.Guid ParseSystemGuid(string value, Func getPath) + public static global::System.Guid ParseSystemGuid(string value, string? path) { try { @@ -518,11 +518,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.Guid)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Guid)}'.", exception); } } - public static global::System.Uri ParseSystemUri(string value, Func getPath) + public static global::System.Uri ParseSystemUri(string value, string? path) { try { @@ -530,11 +530,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.Uri)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Uri)}'.", exception); } } - public static global::System.Version ParseSystemVersion(string value, Func getPath) + public static global::System.Version ParseSystemVersion(string value, string? path) { try { @@ -542,11 +542,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.Version)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Version)}'.", exception); } } - public static byte[] ParseByteArray(string value, Func getPath) + public static byte[] ParseByteArray(string value, string? path) { try { @@ -554,7 +554,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(byte[])}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(byte[])}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T.generated.txt index a3f236c19104..9da38162f69c 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T.generated.txt @@ -97,7 +97,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -108,7 +108,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -152,7 +152,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value4) { - instance.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -243,7 +243,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -251,7 +251,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T_BinderOptions.generated.txt index b7207282c949..c61cb79650c6 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T_BinderOptions.generated.txt @@ -97,7 +97,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -108,7 +108,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -152,7 +152,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value4) { - instance.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -243,7 +243,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -251,7 +251,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T_name.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T_name.generated.txt index 3238545870fa..72e2503fd5b2 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T_name.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T_name.generated.txt @@ -97,7 +97,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -108,7 +108,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -152,7 +152,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value4) { - instance.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -243,7 +243,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -251,7 +251,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T_name_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T_name_BinderOptions.generated.txt index 634a091f2755..e09478cf4aed 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T_name_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Configure_T_name_BinderOptions.generated.txt @@ -91,7 +91,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -102,7 +102,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -146,7 +146,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value4) { - instance.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -237,7 +237,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -245,7 +245,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/UnsupportedTypes.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/UnsupportedTypes.generated.txt index e2a440440c54..d9d9ddc9e7fd 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/UnsupportedTypes.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/UnsupportedTypes.generated.txt @@ -137,7 +137,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Age"] is string value3) { - instance.Age = ParseInt(value3, () => configuration.GetSection("Age").Path); + instance.Age = ParseInt(value3, configuration.GetSection("Age").Path); } else if (defaultValueIfNotFound) { @@ -174,7 +174,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration int x = (int)(10); if (configuration["x"] is string value13) { - x = ParseInt(value13, () => configuration.GetSection("x").Path); + x = ParseInt(value13, configuration.GetSection("x").Path); } return new global::Record(x) @@ -242,7 +242,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -250,7 +250,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Collections.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Collections.generated.txt index b489907db900..b8d24de4a64e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Collections.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Collections.generated.txt @@ -70,7 +70,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance[section.Key] = ParseInt(value, () => section.Path); + instance[section.Key] = ParseInt(value, section.Path); } } } @@ -97,7 +97,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - temp.Add(ParseInt(value, () => section.Path)); + temp.Add(ParseInt(value, section.Path)); } } } @@ -113,7 +113,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - temp[section.Key] = ParseInt(value, () => section.Path); + temp[section.Key] = ParseInt(value, section.Path); } } } @@ -214,7 +214,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -222,7 +222,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind.generated.txt index da0c7375e13f..15bfede964ef 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind.generated.txt @@ -89,7 +89,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -128,7 +128,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -210,7 +210,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -218,7 +218,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind_Instance.generated.txt index 336d1b5a9f4c..e3baa0a47961 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind_Instance.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind_Instance.generated.txt @@ -59,7 +59,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -98,7 +98,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -162,7 +162,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return null; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -170,7 +170,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind_Instance_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind_Instance_BinderOptions.generated.txt index 80c908cedbee..975b2bf79000 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind_Instance_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind_Instance_BinderOptions.generated.txt @@ -59,7 +59,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -98,7 +98,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -180,7 +180,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -188,7 +188,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind_Key_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind_Key_Instance.generated.txt index 592e8f14ae41..f8a85a2c6ea1 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind_Key_Instance.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Bind_Key_Instance.generated.txt @@ -59,7 +59,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -98,7 +98,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -162,7 +162,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return null; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -170,7 +170,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get.generated.txt index 0c631bfc10e6..210cc441463f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get.generated.txt @@ -88,7 +88,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -101,7 +101,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - temp2.Add(ParseInt(value, () => section.Path)); + temp2.Add(ParseInt(value, section.Path)); } } @@ -132,7 +132,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value4) { - instance.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -170,7 +170,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value14) { - instance.MyInt = ParseInt(value14, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value14, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -237,7 +237,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -245,7 +245,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue.generated.txt index 67df05b508e8..1b4db77eaa31 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue.generated.txt @@ -39,6 +39,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// Extracts the value with the specified key and converts it to the specified type. [InterceptsLocation(@"src-0.cs", 16, 24)] + [return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))] public static T? GetValue(this IConfiguration configuration, string key, T defaultValue) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? defaultValue); /// Extracts the value with the specified key and converts it to the specified type. @@ -47,6 +48,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// Extracts the value with the specified key and converts it to the specified type. [InterceptsLocation(@"src-0.cs", 17, 24)] + [return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))] public static object? GetValue(this IConfiguration configuration, Type type, string key, object? defaultValue) => BindingExtensions.GetValueCore(configuration, type, key) ?? defaultValue; #endregion IConfiguration extensions. @@ -64,25 +66,25 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (type == typeof(int)) { - return ParseInt(value, () => section.Path); + return ParseInt(value, section.Path); } else if (type == typeof(bool?)) { - return ParseBool(value, () => section.Path); + return ParseBool(value, section.Path); } else if (type == typeof(byte[])) { - return ParseByteArray(value, () => section.Path); + return ParseByteArray(value, section.Path); } else if (type == typeof(global::System.Globalization.CultureInfo)) { - return ParseSystemGlobalizationCultureInfo(value, () => section.Path); + return ParseSystemGlobalizationCultureInfo(value, section.Path); } return null; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -90,11 +92,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } - public static bool ParseBool(string value, Func getPath) + public static bool ParseBool(string value, string? path) { try { @@ -102,11 +104,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(bool)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(bool)}'.", exception); } } - public static byte[] ParseByteArray(string value, Func getPath) + public static byte[] ParseByteArray(string value, string? path) { try { @@ -114,11 +116,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(byte[])}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(byte[])}'.", exception); } } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, Func getPath) + public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) { try { @@ -126,7 +128,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_T_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_T_Key.generated.txt index 678fa163a57c..f941602574bf 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_T_Key.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_T_Key.generated.txt @@ -52,13 +52,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (type == typeof(int)) { - return ParseInt(value, () => section.Path); + return ParseInt(value, section.Path); } return null; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -66,7 +66,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt index b546b86ea1b9..b4e732218e36 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt @@ -35,6 +35,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #region IConfiguration extensions. /// Extracts the value with the specified key and converts it to the specified type. [InterceptsLocation(@"src-0.cs", 12, 20)] + [return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))] public static T? GetValue(this IConfiguration configuration, string key, T defaultValue) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? defaultValue); #endregion IConfiguration extensions. @@ -52,13 +53,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (type == typeof(int)) { - return ParseInt(value, () => section.Path); + return ParseInt(value, section.Path); } return null; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -66,7 +67,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_TypeOf_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_TypeOf_Key.generated.txt index 706dec382c86..071e80f21f7a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_TypeOf_Key.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_TypeOf_Key.generated.txt @@ -52,13 +52,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (type == typeof(bool?)) { - return ParseBool(value, () => section.Path); + return ParseBool(value, section.Path); } return null; } - public static bool ParseBool(string value, Func getPath) + public static bool ParseBool(string value, string? path) { try { @@ -66,7 +66,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(bool)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(bool)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt index 772160a53bdd..a8a4333c82fc 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt @@ -35,6 +35,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #region IConfiguration extensions. /// Extracts the value with the specified key and converts it to the specified type. [InterceptsLocation(@"src-0.cs", 11, 20)] + [return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))] public static object? GetValue(this IConfiguration configuration, Type type, string key, object? defaultValue) => BindingExtensions.GetValueCore(configuration, type, key) ?? defaultValue; #endregion IConfiguration extensions. @@ -52,13 +53,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (type == typeof(global::System.Globalization.CultureInfo)) { - return ParseSystemGlobalizationCultureInfo(value, () => section.Path); + return ParseSystemGlobalizationCultureInfo(value, section.Path); } return null; } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, Func getPath) + public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) { try { @@ -66,7 +67,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_PrimitivesOnly.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_PrimitivesOnly.generated.txt index 4934212d5836..b47e3b04fe55 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_PrimitivesOnly.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_PrimitivesOnly.generated.txt @@ -70,7 +70,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (section.Value is string value) { - return ParseInt(value, () => section.Path); + return ParseInt(value, section.Path); } } else if (type == typeof(string)) @@ -89,7 +89,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (section.Value is string value) { - return ParseFloat(value, () => section.Path); + return ParseFloat(value, section.Path); } } else if (type == typeof(double)) @@ -100,7 +100,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (section.Value is string value) { - return ParseDouble(value, () => section.Path); + return ParseDouble(value, section.Path); } } @@ -143,7 +143,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -151,11 +151,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } - public static float ParseFloat(string value, Func getPath) + public static float ParseFloat(string value, string? path) { try { @@ -163,11 +163,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(float)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(float)}'.", exception); } } - public static double ParseDouble(string value, Func getPath) + public static double ParseDouble(string value, string? path) { try { @@ -175,7 +175,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(double)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(double)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_T.generated.txt index 93766ec1d405..7e8a129fb206 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_T.generated.txt @@ -69,7 +69,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -82,7 +82,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - temp1.Add(ParseInt(value, () => section.Path)); + temp1.Add(ParseInt(value, section.Path)); } } @@ -113,7 +113,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value3) { - instance.MyInt = ParseInt(value3, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value3, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -204,7 +204,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -212,7 +212,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_T_BinderOptions.generated.txt index caae5dfc5a83..7e265b892419 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_T_BinderOptions.generated.txt @@ -69,7 +69,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -82,7 +82,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - temp1.Add(ParseInt(value, () => section.Path)); + temp1.Add(ParseInt(value, section.Path)); } } @@ -113,7 +113,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value3) { - instance.MyInt = ParseInt(value3, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value3, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -204,7 +204,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -212,7 +212,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_TypeOf.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_TypeOf.generated.txt index 9c28e846781d..fbfde08c4632 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_TypeOf.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_TypeOf.generated.txt @@ -69,7 +69,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -136,7 +136,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -144,7 +144,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_TypeOf_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_TypeOf_BinderOptions.generated.txt index c2b86bd863e4..8e4a799bcdd0 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_TypeOf_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Get_TypeOf_BinderOptions.generated.txt @@ -69,7 +69,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -136,7 +136,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -144,7 +144,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/DefaultConstructorParameters.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/DefaultConstructorParameters.generated.txt index 052829b26415..8b1c55c52e85 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/DefaultConstructorParameters.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/DefaultConstructorParameters.generated.txt @@ -75,73 +75,73 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration int age = (int)(42); if (configuration["Age"] is string value2) { - age = ParseInt(value2, () => configuration.GetSection("Age").Path); + age = ParseInt(value2, configuration.GetSection("Age").Path); } float f = 42F; if (configuration["F"] is string value3) { - f = ParseFloat(value3, () => configuration.GetSection("F").Path); + f = ParseFloat(value3, configuration.GetSection("F").Path); } double d = 3.1415899999999999D; if (configuration["D"] is string value4) { - d = ParseDouble(value4, () => configuration.GetSection("D").Path); + d = ParseDouble(value4, configuration.GetSection("D").Path); } decimal m = 3.1415926535897932384626433M; if (configuration["M"] is string value5) { - m = ParseDecimal(value5, () => configuration.GetSection("M").Path); + m = ParseDecimal(value5, configuration.GetSection("M").Path); } global::System.StringComparison sc = (global::System.StringComparison)(4); if (configuration["SC"] is string value6) { - sc = ParseEnum(value6, () => configuration.GetSection("SC").Path); + sc = ParseEnum(value6, configuration.GetSection("SC").Path); } char c = 'q'; if (configuration["C"] is string value7) { - c = ParseChar(value7, () => configuration.GetSection("C").Path); + c = ParseChar(value7, configuration.GetSection("C").Path); } int? nage = (int?)(42); if (configuration["NAge"] is string value8) { - nage = ParseInt(value8, () => configuration.GetSection("NAge").Path); + nage = ParseInt(value8, configuration.GetSection("NAge").Path); } float? nf = 42F; if (configuration["NF"] is string value9) { - nf = ParseFloat(value9, () => configuration.GetSection("NF").Path); + nf = ParseFloat(value9, configuration.GetSection("NF").Path); } double? nd = 3.1415899999999999D; if (configuration["ND"] is string value10) { - nd = ParseDouble(value10, () => configuration.GetSection("ND").Path); + nd = ParseDouble(value10, configuration.GetSection("ND").Path); } decimal? nm = 3.1415926535897932384626433M; if (configuration["NM"] is string value11) { - nm = ParseDecimal(value11, () => configuration.GetSection("NM").Path); + nm = ParseDecimal(value11, configuration.GetSection("NM").Path); } global::System.StringComparison? nsc = (global::System.StringComparison?)(4); if (configuration["NSC"] is string value12) { - nsc = ParseEnum(value12, () => configuration.GetSection("NSC").Path); + nsc = ParseEnum(value12, configuration.GetSection("NSC").Path); } char? nc = 'q'; if (configuration["NC"] is string value13) { - nc = ParseChar(value13, () => configuration.GetSection("NC").Path); + nc = ParseChar(value13, configuration.GetSection("NC").Path); } return new global::Program.ClassWhereParametersHaveDefaultValue(name, address, age, f, d, m, sc, c, nage, nf, nd, nm, nsc, nc); @@ -170,7 +170,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static T ParseEnum(string value, Func getPath) where T : struct + public static T ParseEnum(string value, string? path) where T : struct { try { @@ -178,11 +178,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(T)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(T)}'.", exception); } } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -190,11 +190,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } - public static float ParseFloat(string value, Func getPath) + public static float ParseFloat(string value, string? path) { try { @@ -202,11 +202,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(float)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(float)}'.", exception); } } - public static double ParseDouble(string value, Func getPath) + public static double ParseDouble(string value, string? path) { try { @@ -214,11 +214,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(double)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(double)}'.", exception); } } - public static decimal ParseDecimal(string value, Func getPath) + public static decimal ParseDecimal(string value, string? path) { try { @@ -226,11 +226,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(decimal)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(decimal)}'.", exception); } } - public static char ParseChar(string value, Func getPath) + public static char ParseChar(string value, string? path) { try { @@ -238,7 +238,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(char)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(char)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/BindConfiguration.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/BindConfiguration.generated.txt index d09432aa2583..0ac91850d67a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/BindConfiguration.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/BindConfiguration.generated.txt @@ -94,7 +94,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -110,7 +110,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value2) { - instance.MyInt = ParseInt(value2, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -185,7 +185,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -193,7 +193,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Bind_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Bind_T.generated.txt index 1d116049774f..bd896297fec6 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Bind_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Bind_T.generated.txt @@ -100,7 +100,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -116,7 +116,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value2) { - instance.MyInt = ParseInt(value2, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -191,7 +191,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -199,7 +199,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Bind_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Bind_T_BinderOptions.generated.txt index 2a1abf7f17d3..56682ad884a6 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Bind_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Bind_T_BinderOptions.generated.txt @@ -94,7 +94,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -110,7 +110,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value2) { - instance.MyInt = ParseInt(value2, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -185,7 +185,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -193,7 +193,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Primitives.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Primitives.generated.txt index fdbe79002b2d..31cd91c8cfd0 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Primitives.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Primitives.generated.txt @@ -59,7 +59,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop0"] is string value0) { - instance.Prop0 = ParseBool(value0, () => configuration.GetSection("Prop0").Path); + instance.Prop0 = ParseBool(value0, configuration.GetSection("Prop0").Path); } else if (defaultValueIfNotFound) { @@ -68,7 +68,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop1"] is string value1) { - instance.Prop1 = ParseByte(value1, () => configuration.GetSection("Prop1").Path); + instance.Prop1 = ParseByte(value1, configuration.GetSection("Prop1").Path); } else if (defaultValueIfNotFound) { @@ -77,7 +77,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop2"] is string value2) { - instance.Prop2 = ParseSbyte(value2, () => configuration.GetSection("Prop2").Path); + instance.Prop2 = ParseSbyte(value2, configuration.GetSection("Prop2").Path); } else if (defaultValueIfNotFound) { @@ -86,7 +86,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop3"] is string value3) { - instance.Prop3 = ParseChar(value3, () => configuration.GetSection("Prop3").Path); + instance.Prop3 = ParseChar(value3, configuration.GetSection("Prop3").Path); } else if (defaultValueIfNotFound) { @@ -95,7 +95,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop4"] is string value4) { - instance.Prop4 = ParseDouble(value4, () => configuration.GetSection("Prop4").Path); + instance.Prop4 = ParseDouble(value4, configuration.GetSection("Prop4").Path); } else if (defaultValueIfNotFound) { @@ -109,7 +109,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop6"] is string value6) { - instance.Prop6 = ParseInt(value6, () => configuration.GetSection("Prop6").Path); + instance.Prop6 = ParseInt(value6, configuration.GetSection("Prop6").Path); } else if (defaultValueIfNotFound) { @@ -118,7 +118,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop8"] is string value7) { - instance.Prop8 = ParseShort(value7, () => configuration.GetSection("Prop8").Path); + instance.Prop8 = ParseShort(value7, configuration.GetSection("Prop8").Path); } else if (defaultValueIfNotFound) { @@ -127,7 +127,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop9"] is string value8) { - instance.Prop9 = ParseLong(value8, () => configuration.GetSection("Prop9").Path); + instance.Prop9 = ParseLong(value8, configuration.GetSection("Prop9").Path); } else if (defaultValueIfNotFound) { @@ -136,7 +136,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop10"] is string value9) { - instance.Prop10 = ParseFloat(value9, () => configuration.GetSection("Prop10").Path); + instance.Prop10 = ParseFloat(value9, configuration.GetSection("Prop10").Path); } else if (defaultValueIfNotFound) { @@ -145,7 +145,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop13"] is string value10) { - instance.Prop13 = ParseUshort(value10, () => configuration.GetSection("Prop13").Path); + instance.Prop13 = ParseUshort(value10, configuration.GetSection("Prop13").Path); } else if (defaultValueIfNotFound) { @@ -154,7 +154,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop14"] is string value11) { - instance.Prop14 = ParseUint(value11, () => configuration.GetSection("Prop14").Path); + instance.Prop14 = ParseUint(value11, configuration.GetSection("Prop14").Path); } else if (defaultValueIfNotFound) { @@ -163,7 +163,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop15"] is string value12) { - instance.Prop15 = ParseUlong(value12, () => configuration.GetSection("Prop15").Path); + instance.Prop15 = ParseUlong(value12, configuration.GetSection("Prop15").Path); } else if (defaultValueIfNotFound) { @@ -177,12 +177,12 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop17"] is string value14) { - instance.Prop17 = ParseSystemGlobalizationCultureInfo(value14, () => configuration.GetSection("Prop17").Path); + instance.Prop17 = ParseSystemGlobalizationCultureInfo(value14, configuration.GetSection("Prop17").Path); } if (configuration["Prop19"] is string value15) { - instance.Prop19 = ParseSystemDateTime(value15, () => configuration.GetSection("Prop19").Path); + instance.Prop19 = ParseSystemDateTime(value15, configuration.GetSection("Prop19").Path); } else if (defaultValueIfNotFound) { @@ -191,7 +191,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop20"] is string value16) { - instance.Prop20 = ParseSystemDateTimeOffset(value16, () => configuration.GetSection("Prop20").Path); + instance.Prop20 = ParseSystemDateTimeOffset(value16, configuration.GetSection("Prop20").Path); } else if (defaultValueIfNotFound) { @@ -200,7 +200,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop21"] is string value17) { - instance.Prop21 = ParseDecimal(value17, () => configuration.GetSection("Prop21").Path); + instance.Prop21 = ParseDecimal(value17, configuration.GetSection("Prop21").Path); } else if (defaultValueIfNotFound) { @@ -209,7 +209,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop23"] is string value18) { - instance.Prop23 = ParseSystemTimeSpan(value18, () => configuration.GetSection("Prop23").Path); + instance.Prop23 = ParseSystemTimeSpan(value18, configuration.GetSection("Prop23").Path); } else if (defaultValueIfNotFound) { @@ -218,7 +218,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop24"] is string value19) { - instance.Prop24 = ParseSystemGuid(value19, () => configuration.GetSection("Prop24").Path); + instance.Prop24 = ParseSystemGuid(value19, configuration.GetSection("Prop24").Path); } else if (defaultValueIfNotFound) { @@ -227,17 +227,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop25"] is string value20) { - instance.Prop25 = ParseSystemUri(value20, () => configuration.GetSection("Prop25").Path); + instance.Prop25 = ParseSystemUri(value20, configuration.GetSection("Prop25").Path); } if (configuration["Prop26"] is string value21) { - instance.Prop26 = ParseSystemVersion(value21, () => configuration.GetSection("Prop26").Path); + instance.Prop26 = ParseSystemVersion(value21, configuration.GetSection("Prop26").Path); } if (configuration["Prop27"] is string value22) { - instance.Prop27 = ParseEnum(value22, () => configuration.GetSection("Prop27").Path); + instance.Prop27 = ParseEnum(value22, configuration.GetSection("Prop27").Path); } else if (defaultValueIfNotFound) { @@ -246,7 +246,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop7"] is string value23) { - instance.Prop7 = ParseSystemInt128(value23, () => configuration.GetSection("Prop7").Path); + instance.Prop7 = ParseSystemInt128(value23, configuration.GetSection("Prop7").Path); } else if (defaultValueIfNotFound) { @@ -255,7 +255,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop11"] is string value24) { - instance.Prop11 = ParseSystemHalf(value24, () => configuration.GetSection("Prop11").Path); + instance.Prop11 = ParseSystemHalf(value24, configuration.GetSection("Prop11").Path); } else if (defaultValueIfNotFound) { @@ -264,7 +264,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop12"] is string value25) { - instance.Prop12 = ParseSystemUInt128(value25, () => configuration.GetSection("Prop12").Path); + instance.Prop12 = ParseSystemUInt128(value25, configuration.GetSection("Prop12").Path); } else if (defaultValueIfNotFound) { @@ -273,7 +273,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop18"] is string value26) { - instance.Prop18 = ParseSystemDateOnly(value26, () => configuration.GetSection("Prop18").Path); + instance.Prop18 = ParseSystemDateOnly(value26, configuration.GetSection("Prop18").Path); } else if (defaultValueIfNotFound) { @@ -282,7 +282,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop22"] is string value27) { - instance.Prop22 = ParseSystemTimeOnly(value27, () => configuration.GetSection("Prop22").Path); + instance.Prop22 = ParseSystemTimeOnly(value27, configuration.GetSection("Prop22").Path); } else if (defaultValueIfNotFound) { @@ -291,12 +291,12 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop28"] is string value28) { - instance.Prop28 = ParseByteArray(value28, () => configuration.GetSection("Prop28").Path); + instance.Prop28 = ParseByteArray(value28, configuration.GetSection("Prop28").Path); } if (configuration["Prop29"] is string value29) { - instance.Prop29 = ParseInt(value29, () => configuration.GetSection("Prop29").Path); + instance.Prop29 = ParseInt(value29, configuration.GetSection("Prop29").Path); } else if (defaultValueIfNotFound) { @@ -305,7 +305,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop30"] is string value30) { - instance.Prop30 = ParseSystemDateTime(value30, () => configuration.GetSection("Prop30").Path); + instance.Prop30 = ParseSystemDateTime(value30, configuration.GetSection("Prop30").Path); } else if (defaultValueIfNotFound) { @@ -336,7 +336,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static T ParseEnum(string value, Func getPath) where T : struct + public static T ParseEnum(string value, string? path) where T : struct { try { @@ -344,11 +344,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(T)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(T)}'.", exception); } } - public static bool ParseBool(string value, Func getPath) + public static bool ParseBool(string value, string? path) { try { @@ -356,11 +356,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(bool)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(bool)}'.", exception); } } - public static byte ParseByte(string value, Func getPath) + public static byte ParseByte(string value, string? path) { try { @@ -368,11 +368,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(byte)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(byte)}'.", exception); } } - public static sbyte ParseSbyte(string value, Func getPath) + public static sbyte ParseSbyte(string value, string? path) { try { @@ -380,11 +380,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(sbyte)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(sbyte)}'.", exception); } } - public static char ParseChar(string value, Func getPath) + public static char ParseChar(string value, string? path) { try { @@ -392,11 +392,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(char)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(char)}'.", exception); } } - public static double ParseDouble(string value, Func getPath) + public static double ParseDouble(string value, string? path) { try { @@ -404,11 +404,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(double)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(double)}'.", exception); } } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -416,11 +416,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } - public static short ParseShort(string value, Func getPath) + public static short ParseShort(string value, string? path) { try { @@ -428,11 +428,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(short)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(short)}'.", exception); } } - public static long ParseLong(string value, Func getPath) + public static long ParseLong(string value, string? path) { try { @@ -440,11 +440,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(long)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(long)}'.", exception); } } - public static float ParseFloat(string value, Func getPath) + public static float ParseFloat(string value, string? path) { try { @@ -452,11 +452,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(float)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(float)}'.", exception); } } - public static ushort ParseUshort(string value, Func getPath) + public static ushort ParseUshort(string value, string? path) { try { @@ -464,11 +464,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(ushort)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(ushort)}'.", exception); } } - public static uint ParseUint(string value, Func getPath) + public static uint ParseUint(string value, string? path) { try { @@ -476,11 +476,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(uint)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(uint)}'.", exception); } } - public static ulong ParseUlong(string value, Func getPath) + public static ulong ParseUlong(string value, string? path) { try { @@ -488,11 +488,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(ulong)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(ulong)}'.", exception); } } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, Func getPath) + public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) { try { @@ -500,11 +500,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); } } - public static global::System.DateTime ParseSystemDateTime(string value, Func getPath) + public static global::System.DateTime ParseSystemDateTime(string value, string? path) { try { @@ -512,11 +512,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.DateTime)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.DateTime)}'.", exception); } } - public static global::System.DateTimeOffset ParseSystemDateTimeOffset(string value, Func getPath) + public static global::System.DateTimeOffset ParseSystemDateTimeOffset(string value, string? path) { try { @@ -524,11 +524,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.DateTimeOffset)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.DateTimeOffset)}'.", exception); } } - public static decimal ParseDecimal(string value, Func getPath) + public static decimal ParseDecimal(string value, string? path) { try { @@ -536,11 +536,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(decimal)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(decimal)}'.", exception); } } - public static global::System.TimeSpan ParseSystemTimeSpan(string value, Func getPath) + public static global::System.TimeSpan ParseSystemTimeSpan(string value, string? path) { try { @@ -548,11 +548,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.TimeSpan)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.TimeSpan)}'.", exception); } } - public static global::System.Guid ParseSystemGuid(string value, Func getPath) + public static global::System.Guid ParseSystemGuid(string value, string? path) { try { @@ -560,11 +560,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.Guid)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Guid)}'.", exception); } } - public static global::System.Uri ParseSystemUri(string value, Func getPath) + public static global::System.Uri ParseSystemUri(string value, string? path) { try { @@ -572,11 +572,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.Uri)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Uri)}'.", exception); } } - public static global::System.Version ParseSystemVersion(string value, Func getPath) + public static global::System.Version ParseSystemVersion(string value, string? path) { try { @@ -584,11 +584,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.Version)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Version)}'.", exception); } } - public static global::System.Int128 ParseSystemInt128(string value, Func getPath) + public static global::System.Int128 ParseSystemInt128(string value, string? path) { try { @@ -596,11 +596,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.Int128)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Int128)}'.", exception); } } - public static global::System.Half ParseSystemHalf(string value, Func getPath) + public static global::System.Half ParseSystemHalf(string value, string? path) { try { @@ -608,11 +608,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.Half)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Half)}'.", exception); } } - public static global::System.UInt128 ParseSystemUInt128(string value, Func getPath) + public static global::System.UInt128 ParseSystemUInt128(string value, string? path) { try { @@ -620,11 +620,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.UInt128)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.UInt128)}'.", exception); } } - public static global::System.DateOnly ParseSystemDateOnly(string value, Func getPath) + public static global::System.DateOnly ParseSystemDateOnly(string value, string? path) { try { @@ -632,11 +632,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.DateOnly)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.DateOnly)}'.", exception); } } - public static global::System.TimeOnly ParseSystemTimeOnly(string value, Func getPath) + public static global::System.TimeOnly ParseSystemTimeOnly(string value, string? path) { try { @@ -644,11 +644,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(global::System.TimeOnly)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.TimeOnly)}'.", exception); } } - public static byte[] ParseByteArray(string value, Func getPath) + public static byte[] ParseByteArray(string value, string? path) { try { @@ -656,7 +656,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(byte[])}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(byte[])}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T.generated.txt index b26d7ebc0bc3..c7a8191aa6e9 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T.generated.txt @@ -91,7 +91,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -102,7 +102,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -146,7 +146,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value4) { - instance.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -237,7 +237,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -245,7 +245,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T_BinderOptions.generated.txt index 89d3a8714e2f..e7ebd66c7b8c 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T_BinderOptions.generated.txt @@ -91,7 +91,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -102,7 +102,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -146,7 +146,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value4) { - instance.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -237,7 +237,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -245,7 +245,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T_name.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T_name.generated.txt index eb23ee05417b..63fd389cb721 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T_name.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T_name.generated.txt @@ -91,7 +91,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -102,7 +102,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -146,7 +146,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value4) { - instance.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -237,7 +237,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -245,7 +245,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T_name_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T_name_BinderOptions.generated.txt index d2a398bbc904..b95cb9ae0e95 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T_name_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Configure_T_name_BinderOptions.generated.txt @@ -85,7 +85,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (section.Value is string value) { - instance.Add(ParseInt(value, () => section.Path)); + instance.Add(ParseInt(value, section.Path)); } } } @@ -96,7 +96,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value1) { - instance.MyInt = ParseInt(value1, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -140,7 +140,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["MyInt"] is string value4) { - instance.MyInt = ParseInt(value4, () => configuration.GetSection("MyInt").Path); + instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); } else if (defaultValueIfNotFound) { @@ -231,7 +231,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -239,7 +239,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/UnsupportedTypes.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/UnsupportedTypes.generated.txt index e4390c7ada0e..8becba5ac74c 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/UnsupportedTypes.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/UnsupportedTypes.generated.txt @@ -131,7 +131,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Age"] is string value3) { - instance.Age = ParseInt(value3, () => configuration.GetSection("Age").Path); + instance.Age = ParseInt(value3, configuration.GetSection("Age").Path); } else if (defaultValueIfNotFound) { @@ -168,7 +168,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration int x = (int)(10); if (configuration["x"] is string value13) { - x = ParseInt(value13, () => configuration.GetSection("x").Path); + x = ParseInt(value13, configuration.GetSection("x").Path); } return new global::Record(x) @@ -236,7 +236,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, Func getPath) + public static int ParseInt(string value, string? path) { try { @@ -244,7 +244,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/GeneratorTests.Helpers.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/GeneratorTests.Helpers.cs index 24285047fff9..e9dcad70de4f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/GeneratorTests.Helpers.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/GeneratorTests.Helpers.cs @@ -106,7 +106,7 @@ private static async Task VerifyAgainstBaselineUsingF ExpectedDiagnostics expectedDiags = ExpectedDiagnostics.None) { string environmentSubFolder = -#if NETCOREAPP +#if NET "netcoreapp" #else "net462" @@ -138,7 +138,7 @@ private static async Task VerifyAgainstBaselineUsingF string source = string.Join(Environment.NewLine, lines).TrimEnd(Environment.NewLine.ToCharArray()) + Environment.NewLine; path = Path.Combine($"{repoRootDir}\\src\\libraries\\Microsoft.Extensions.Configuration.Binder\\tests\\SourceGenerationTests\\", path); -#if NETCOREAPP +#if NET await File.WriteAllTextAsync(path, source); #else File.WriteAllText(path, source); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests.csproj index eccbe7d759b4..c19f91354cba 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests.csproj @@ -8,6 +8,9 @@ $(NoWarn);SYSLIB1103,SYSLIB1104 $(InterceptorsPreviewNamespaces);Microsoft.Extensions.Configuration.Binder.SourceGeneration true + + + true diff --git a/src/libraries/Microsoft.Extensions.Configuration.CommandLine/src/CommandLineConfigurationProvider.cs b/src/libraries/Microsoft.Extensions.Configuration.CommandLine/src/CommandLineConfigurationProvider.cs index e938472f476c..8877a3086b23 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.CommandLine/src/CommandLineConfigurationProvider.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.CommandLine/src/CommandLineConfigurationProvider.cs @@ -33,7 +33,7 @@ public CommandLineConfigurationProvider(IEnumerable args, IDictionary /// The command line arguments. /// - protected IEnumerable Args { get; private set; } + protected IEnumerable Args { get; } /// /// Loads the configuration data from the command line args. diff --git a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationExtensions.cs b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationExtensions.cs index 77ac387d0960..f84c5c10eea7 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationExtensions.cs @@ -29,9 +29,6 @@ public static IConfigurationBuilder SetFileProvider(this IConfigurationBuilder b return builder; } - internal static IFileProvider? GetUserDefinedFileProvider(this IConfigurationBuilder builder) - => builder.Properties.TryGetValue(FileProviderKey, out object? provider) ? (IFileProvider)provider : null; - /// /// Gets the default to be used for file-based providers. /// @@ -41,7 +38,12 @@ public static IFileProvider GetFileProvider(this IConfigurationBuilder builder) { ThrowHelper.ThrowIfNull(builder); - return GetUserDefinedFileProvider(builder) ?? new PhysicalFileProvider(AppContext.BaseDirectory ?? string.Empty); + if (builder.Properties.TryGetValue(FileProviderKey, out object? provider)) + { + return (IFileProvider)provider; + } + + return new PhysicalFileProvider(AppContext.BaseDirectory ?? string.Empty); } /// diff --git a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationProvider.cs b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationProvider.cs index c0d8c9f34127..d226051b1ab8 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationProvider.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationProvider.cs @@ -162,11 +162,6 @@ private void HandleException(ExceptionDispatchInfo info) protected virtual void Dispose(bool disposing) { _changeTokenRegistration?.Dispose(); - - if (Source.OwnsFileProvider) - { - (Source.FileProvider as IDisposable)?.Dispose(); - } } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationSource.cs b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationSource.cs index 60555b2c6725..d58c265f406a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationSource.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationSource.cs @@ -18,11 +18,6 @@ public abstract class FileConfigurationSource : IConfigurationSource /// public IFileProvider? FileProvider { get; set; } - /// - /// Set to true when was not provided by user and can be safely disposed. - /// - internal bool OwnsFileProvider { get; private set; } - /// /// The path to the file. /// @@ -63,11 +58,6 @@ public abstract class FileConfigurationSource : IConfigurationSource /// The . public void EnsureDefaults(IConfigurationBuilder builder) { - if (FileProvider is null && builder.GetUserDefinedFileProvider() is null) - { - OwnsFileProvider = true; - } - FileProvider ??= builder.GetFileProvider(); OnLoadException ??= builder.GetFileLoadExceptionHandler(); } @@ -91,7 +81,6 @@ public void ResolveFileProvider() } if (Directory.Exists(directory)) { - OwnsFileProvider = true; FileProvider = new PhysicalFileProvider(directory); Path = pathToFile; } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Json/tests/JsonConfigurationTest.cs b/src/libraries/Microsoft.Extensions.Configuration.Json/tests/JsonConfigurationTest.cs index 4b08c918fb89..08d59e30ea6e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Json/tests/JsonConfigurationTest.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Json/tests/JsonConfigurationTest.cs @@ -222,56 +222,26 @@ public void ThrowFormatExceptionWhenFileIsEmpty() Assert.Contains("Could not parse the JSON file.", exception.Message); } - [Theory] - [InlineData(true)] - [InlineData(false)] - public void AddJsonFile_FileProvider_Gets_Disposed_When_It_Was_Not_Created_By_The_User(bool disposeConfigRoot) + [Fact] + public void AddJsonFile_FileProvider_Is_Not_Disposed_When_SourcesGetReloaded() { - string filePath = Path.Combine(Path.GetTempPath(), $"{nameof(AddJsonFile_FileProvider_Gets_Disposed_When_It_Was_Not_Created_By_The_User)}.json"); + string filePath = Path.Combine(Path.GetTempPath(), $"{nameof(AddJsonFile_FileProvider_Is_Not_Disposed_When_SourcesGetReloaded)}.json"); File.WriteAllText(filePath, @"{ ""some"": ""value"" }"); - IConfigurationRoot config = new ConfigurationBuilder().AddJsonFile(filePath, optional: false).Build(); - JsonConfigurationProvider jsonConfigurationProvider = config.Providers.OfType().Single(); - - Assert.NotNull(jsonConfigurationProvider.Source.FileProvider); - PhysicalFileProvider fileProvider = (PhysicalFileProvider)jsonConfigurationProvider.Source.FileProvider; - Assert.False(GetIsDisposed(fileProvider)); - - if (disposeConfigRoot) - { - (config as IDisposable).Dispose(); // disposing ConfigurationRoot - } - else - { - jsonConfigurationProvider.Dispose(); // disposing JsonConfigurationProvider - } - - Assert.True(GetIsDisposed(fileProvider)); - } + IConfigurationBuilder builder = new ConfigurationManager(); - [Fact] - public void AddJsonFile_FileProvider_Is_Not_Disposed_When_It_Is_Owned_By_The_User() - { - string filePath = Path.Combine(Path.GetTempPath(), $"{nameof(AddJsonFile_FileProvider_Is_Not_Disposed_When_It_Is_Owned_By_The_User)}.json"); - File.WriteAllText(filePath, @"{ ""some"": ""value"" }"); + builder.AddJsonFile(filePath, optional: false); - PhysicalFileProvider fileProvider = new(Path.GetDirectoryName(filePath)); - JsonConfigurationProvider configurationProvider = new(new JsonConfigurationSource() - { - Path = filePath, - FileProvider = fileProvider - }); - IConfigurationRoot config = new ConfigurationBuilder().AddJsonFile(configurationProvider.Source.FileProvider, filePath, optional: true, reloadOnChange: false).Build(); + FileConfigurationSource fileConfigurationSource = (FileConfigurationSource)builder.Sources.Last(); + PhysicalFileProvider fileProvider = (PhysicalFileProvider)fileConfigurationSource.FileProvider; Assert.False(GetIsDisposed(fileProvider)); - (config as IDisposable).Dispose(); // disposing ConfigurationRoot that does not own the provider - Assert.False(GetIsDisposed(fileProvider)); + builder.Properties.Add("simplest", "repro"); - configurationProvider.Dispose(); // disposing JsonConfigurationProvider that does not own the provider Assert.False(GetIsDisposed(fileProvider)); - fileProvider.Dispose(); // disposing PhysicalFileProvider itself + fileProvider.Dispose(); Assert.True(GetIsDisposed(fileProvider)); } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/XmlConfigurationTest.cs b/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/XmlConfigurationTest.cs index d248d96d9d46..4012d775afa5 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/XmlConfigurationTest.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/XmlConfigurationTest.cs @@ -3,13 +3,11 @@ using System; using System.IO; -using System.Linq; using System.Security.Cryptography; using System.Security.Cryptography.Xml; using System.Tests; using System.Xml; using Microsoft.Extensions.Configuration.Test; -using Microsoft.Extensions.FileProviders; using Xunit; namespace Microsoft.Extensions.Configuration.Xml.Test @@ -781,64 +779,5 @@ public void LoadKeyValuePairsFromValidEncryptedXml() Assert.Equal("AnotherTestConnectionString", xmlConfigSrc.Get("data.setting:inventory:connectionstring")); Assert.Equal("MySql", xmlConfigSrc.Get("Data.setting:Inventory:Provider")); } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void AddXmlFile_FileProvider_Gets_Disposed_When_It_Was_Not_Created_By_The_User(bool disposeConfigRoot) - { - string filePath = Path.Combine(Path.GetTempPath(), $"{nameof(AddXmlFile_FileProvider_Gets_Disposed_When_It_Was_Not_Created_By_The_User)}.xml"); - File.WriteAllText(filePath, @"Settings"); - - IConfigurationRoot config = new ConfigurationBuilder().AddXmlFile(filePath, optional: false).Build(); - XmlConfigurationProvider xmlConfigurationProvider = config.Providers.OfType().Single(); - - Assert.NotNull(xmlConfigurationProvider.Source.FileProvider); - PhysicalFileProvider fileProvider = (PhysicalFileProvider)xmlConfigurationProvider.Source.FileProvider; - Assert.False(GetIsDisposed(fileProvider)); - - if (disposeConfigRoot) - { - (config as IDisposable).Dispose(); // disposing ConfigurationRoot - } - else - { - xmlConfigurationProvider.Dispose(); // disposing XmlConfigurationProvider - } - - Assert.True(GetIsDisposed(fileProvider)); - } - - [Fact] - public void AddXmlFile_FileProvider_Is_Not_Disposed_When_It_Is_Owned_By_The_User() - { - string filePath = Path.Combine(Path.GetTempPath(), $"{nameof(AddXmlFile_FileProvider_Is_Not_Disposed_When_It_Is_Owned_By_The_User)}.xml"); - File.WriteAllText(filePath, @"Settings"); - - PhysicalFileProvider fileProvider = new(Path.GetDirectoryName(filePath)); - XmlConfigurationProvider configurationProvider = new(new XmlConfigurationSource() - { - Path = filePath, - FileProvider = fileProvider - }); - IConfigurationRoot config = new ConfigurationBuilder().AddXmlFile(configurationProvider.Source.FileProvider, filePath, optional: true, reloadOnChange: false).Build(); - - Assert.False(GetIsDisposed(fileProvider)); - - (config as IDisposable).Dispose(); // disposing ConfigurationRoot that does not own the provider - Assert.False(GetIsDisposed(fileProvider)); - - configurationProvider.Dispose(); // disposing XmlConfigurationProvider - Assert.False(GetIsDisposed(fileProvider)); - - fileProvider.Dispose(); // disposing PhysicalFileProvider itself - Assert.True(GetIsDisposed(fileProvider)); - } - - private static bool GetIsDisposed(PhysicalFileProvider fileProvider) - { - System.Reflection.FieldInfo isDisposedField = typeof(PhysicalFileProvider).GetField("_disposed", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); - return (bool)isDisposedField.GetValue(fileProvider); - } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs index f00a9ab49f04..274f4696dd94 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs @@ -69,7 +69,7 @@ static ReadOnlySpan SkipAheadOnDelimiter(ReadOnlySpan a) static int Compare(ReadOnlySpan a, ReadOnlySpan b) { -#if NETCOREAPP +#if NET bool aIsInt = int.TryParse(a, out int value1); bool bIsInt = int.TryParse(b, out int value2); #else diff --git a/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/DisposableFileSystem.cs b/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/DisposableFileSystem.cs index fffca558b0c7..0c16295d5be5 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/DisposableFileSystem.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/DisposableFileSystem.cs @@ -14,7 +14,7 @@ public class DisposableFileSystem : IDisposable public DisposableFileSystem() { -#if NETCOREAPP +#if NET DirectoryInfo = Directory.CreateTempSubdirectory(); #else DirectoryInfo = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ActivatorUtilities.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ActivatorUtilities.cs index 6dbd4b3495ab..6d8a30b6dd5d 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ActivatorUtilities.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ActivatorUtilities.cs @@ -12,7 +12,7 @@ using System.Runtime.InteropServices; using Microsoft.Extensions.Internal; -#if NETCOREAPP +#if NET [assembly: System.Reflection.Metadata.MetadataUpdateHandler(typeof(Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ActivatorUtilitiesUpdateHandler))] #endif @@ -23,7 +23,7 @@ namespace Microsoft.Extensions.DependencyInjection /// public static class ActivatorUtilities { -#if NETCOREAPP +#if NET // Support caching of constructor metadata for the common case of types in non-collectible assemblies. private static readonly ConcurrentDictionary s_constructorInfos = new(); @@ -35,7 +35,7 @@ public static class ActivatorUtilities #endif private static readonly MethodInfo GetServiceInfo = - GetMethodInfo>((sp, t, r, c, k) => GetService(sp, t, r, c, k)); + new Func(GetService).Method; /// /// Instantiate a type with constructor arguments provided directly and/or from an . @@ -60,7 +60,7 @@ public static object CreateInstance( } ConstructorInfoEx[]? constructors; -#if NETCOREAPP +#if NET if (!s_constructorInfos.TryGetValue(instanceType, out constructors)) { constructors = GetOrAddConstructors(instanceType); @@ -135,7 +135,7 @@ public static object CreateInstance( if (bestLength < length) { bestLength = length; -#if NETCOREAPP +#if NET ctorArgs.CopyTo(bestCtorArgs); #else if (i == constructors.Length - 1) @@ -191,7 +191,7 @@ public static object CreateInstance( matcher.MapParameters(parameterMap, parameters); return matcher.CreateInstance(provider); -#if NETCOREAPP +#if NET int GetMaxArgCount() { int max = 0; @@ -222,7 +222,7 @@ static void InitializeCtorArgValues(ref object[] ctorArgs, int length) #endif } -#if NETCOREAPP +#if NET private static ConstructorInfoEx[] GetOrAddConstructors( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) { @@ -246,7 +246,7 @@ private static ConstructorInfoEx[] GetOrAddConstructors( s_collectibleConstructorInfos.Value.AddOrUpdate(type, value); return value; } -#endif // NETCOREAPP +#endif // NET private static ConstructorInfoEx[] CreateConstructorInfoExs( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) @@ -277,7 +277,7 @@ public static ObjectFactory CreateFactory( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType, Type[] argumentTypes) { -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP +#if NETSTANDARD2_1_OR_GREATER || NET if (!RuntimeFeature.IsDynamicCodeCompiled) { // Create a reflection-based factory when dynamic code is not compiled\jitted as would be the case with @@ -314,7 +314,7 @@ public static ObjectFactory CreateFactory<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>( Type[] argumentTypes) { -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP +#if NETSTANDARD2_1_OR_GREATER || NET if (!RuntimeFeature.IsDynamicCodeCompiled) { // See the comment above in the non-generic CreateFactory() for why we use 'IsDynamicCodeCompiled' here. @@ -376,12 +376,6 @@ public static object GetServiceOrCreateInstance( return provider.GetService(type) ?? CreateInstance(provider, type); } - private static MethodInfo GetMethodInfo(Expression expr) - { - var mc = (MethodCallExpression)expr.Body; - return mc.Method; - } - private static object? GetService(IServiceProvider sp, Type type, Type requiredBy, bool hasDefaultValue, object? key) { object? service = key == null ? sp.GetService(type) : GetKeyedService(sp, type, key); @@ -443,7 +437,7 @@ private static BlockExpression BuildFactoryExpression( Expression.New(constructor, constructorArguments)); } -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP +#if NETSTANDARD2_1_OR_GREATER || NET [DoesNotReturn] private static void ThrowHelperArgumentNullExceptionServiceProvider() { @@ -457,7 +451,7 @@ private static ObjectFactory CreateFactoryReflection( FindApplicableConstructor(instanceType, argumentTypes, constructors: null, out ConstructorInfo constructor, out int?[] parameterMap); Type declaringType = constructor.DeclaringType!; -#if NETCOREAPP +#if NET ConstructorInvoker invoker = ConstructorInvoker.Create(constructor); ParameterInfo[] constructorParameters = constructor.GetParameters(); @@ -526,7 +520,7 @@ ObjectFactory InvokeCanonical() FactoryParameterContext[] parameters = GetFactoryParameterContext(); return (serviceProvider, arguments) => ReflectionFactoryCanonical(constructor, parameters, declaringType, serviceProvider, arguments); -#endif // NETCOREAPP +#endif // NET FactoryParameterContext[] GetFactoryParameterContext() { @@ -548,7 +542,7 @@ FactoryParameterContext[] GetFactoryParameterContext() return parameters; } } -#endif // NETSTANDARD2_1_OR_GREATER || NETCOREAPP +#endif // NETSTANDARD2_1_OR_GREATER || NET private readonly struct FactoryParameterContext { @@ -650,7 +644,7 @@ private static bool TryFindPreferredConstructor( if (constructors is null) { -#if NETCOREAPP +#if NET if (!s_constructorInfos.TryGetValue(instanceType, out constructors)) { constructors = GetOrAddConstructors(instanceType); @@ -731,7 +725,7 @@ private sealed class ConstructorInfoEx public readonly ParameterInfo[] Parameters; public readonly bool IsPreferred; private readonly object?[]? _parameterKeys; -#if NETCOREAPP +#if NET public ConstructorInvoker? _invoker; public ConstructorInvoker Invoker { @@ -807,7 +801,7 @@ private readonly ref struct ConstructorMatcher { private readonly ConstructorInfoEx _constructor; -#if NETCOREAPP +#if NET private readonly Span _parameterValues; public ConstructorMatcher(ConstructorInfoEx constructor, Span parameterValues) #else @@ -890,7 +884,7 @@ public object CreateInstance(IServiceProvider provider) } } -#if NETCOREAPP +#if NET return _constructor.Invoker.Invoke(_parameterValues.Slice(0, _constructor.Parameters.Length)); #else try @@ -928,7 +922,7 @@ private static void ThrowMarkedCtorDoesNotTakeAllProvidedArguments() throw new InvalidOperationException(SR.Format(SR.MarkedCtorMissingArgumentTypes, nameof(ActivatorUtilitiesConstructorAttribute))); } -#if NETCOREAPP // Use the faster ConstructorInvoker which also has alloc-free APIs when <= 4 parameters. +#if NET // Use the faster ConstructorInvoker which also has alloc-free APIs when <= 4 parameters. private static object ReflectionFactoryServiceOnlyFixed( ConstructorInvoker invoker, FactoryParameterContext[] parameters, @@ -1173,7 +1167,7 @@ private static void ThrowHelperNullReferenceException() { throw new NullReferenceException(); } -#elif NETSTANDARD2_1_OR_GREATER || NETCOREAPP +#elif NETSTANDARD2_1_OR_GREATER || NET private static object ReflectionFactoryCanonical( ConstructorInfo constructor, FactoryParameterContext[] parameters, @@ -1203,7 +1197,7 @@ private static object ReflectionFactoryCanonical( } #endif -#if NETCOREAPP +#if NET internal static class ActivatorUtilitiesUpdateHandler { public static void ClearCache(Type[]? _) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/CallSiteJsonFormatter.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/CallSiteJsonFormatter.cs index 5702d1795f92..37520c3d1127 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/CallSiteJsonFormatter.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/CallSiteJsonFormatter.cs @@ -9,7 +9,7 @@ namespace Microsoft.Extensions.DependencyInjection { internal sealed class CallSiteJsonFormatter : CallSiteVisitor { - internal static CallSiteJsonFormatter Instance = new CallSiteJsonFormatter(); + internal static readonly CallSiteJsonFormatter Instance = new CallSiteJsonFormatter(); private CallSiteJsonFormatter() { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ActivatorUtilitiesTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ActivatorUtilitiesTests.cs index 1144ff33a1c7..8e0d07c0b0ac 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ActivatorUtilitiesTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ActivatorUtilitiesTests.cs @@ -8,7 +8,7 @@ using Xunit; using System.Runtime.CompilerServices; -#if NETCOREAPP +#if NET using System.Runtime.Loader; #endif @@ -332,7 +332,7 @@ public void CreateFactory_CreatesFactoryMethod_5Types_5Injected() [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_CreatesFactoryMethod_KeyedParams(bool useDynamicCode) @@ -363,7 +363,7 @@ public void CreateFactory_CreatesFactoryMethod_KeyedParams(bool useDynamicCode) [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_CreatesFactoryMethod_KeyedParams_5Types(bool useDynamicCode) @@ -396,7 +396,7 @@ public void CreateFactory_CreatesFactoryMethod_KeyedParams_5Types(bool useDynami [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_CreatesFactoryMethod_KeyedParams_1Injected(bool useDynamicCode) @@ -426,7 +426,7 @@ public void CreateFactory_CreatesFactoryMethod_KeyedParams_1Injected(bool useDyn [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_RemoteExecutor_CreatesFactoryMethod(bool useDynamicCode) @@ -460,7 +460,7 @@ public void CreateFactory_RemoteExecutor_CreatesFactoryMethod(bool useDynamicCod [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_RemoteExecutor_NullArguments_Throws(bool useDynamicCode) @@ -483,7 +483,7 @@ public void CreateFactory_RemoteExecutor_NullArguments_Throws(bool useDynamicCod [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_RemoteExecutor_NoArguments_UseNullDefaultValue(bool useDynamicCode) @@ -507,7 +507,7 @@ public void CreateFactory_RemoteExecutor_NoArguments_UseNullDefaultValue(bool us [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_RemoteExecutor_NoArguments_ThrowRequiredValue(bool useDynamicCode) @@ -531,7 +531,7 @@ public void CreateFactory_RemoteExecutor_NoArguments_ThrowRequiredValue(bool use [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_RemoteExecutor_NullArgument_UseDefaultValue(bool useDynamicCode) @@ -555,7 +555,7 @@ public void CreateFactory_RemoteExecutor_NullArgument_UseDefaultValue(bool useDy [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] -#if NETCOREAPP +#if NET [InlineData(false)] #endif public void CreateFactory_RemoteExecutor_NoParameters_Success(bool useDynamicCode) @@ -577,7 +577,7 @@ public void CreateFactory_RemoteExecutor_NoParameters_Success(bool useDynamicCod }, options); } -#if NETCOREAPP +#if NET [ActiveIssue("https://github.com/dotnet/runtime/issues/34072", TestRuntimes.Mono)] [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(true)] @@ -1008,7 +1008,7 @@ public ClassWithStringDefaultValue(string text = "DEFAULT") } } -#if NETCOREAPP +#if NET internal class MyLoadContext : AssemblyLoadContext { private MyLoadContext() : base(isCollectible: true) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs index 74f85296af95..919dee647590 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs @@ -792,7 +792,7 @@ public void CreateCallSite_EnumberableCachedAtLowestLevel(ServiceDescriptor[] de Assert.Equal(typeof(IEnumerable), callSite.Cache.Key.ServiceIdentifier.ServiceType); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] public void CallSitesAreUniquePerServiceTypeAndSlot() { // Connected graph @@ -828,7 +828,7 @@ public void CallSitesAreUniquePerServiceTypeAndSlot() } } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] public void CallSitesAreUniquePerServiceTypeAndSlotWithOpenGenericInGraph() { // Connected graph diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderContainerTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderContainerTests.cs index f668cee41efc..3e08a16db282 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderContainerTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderContainerTests.cs @@ -371,7 +371,7 @@ public void GetService_DisposeOnSameThread_Throws() }); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] public void GetAsyncService_DisposeAsyncOnSameThread_ThrowsAndDoesNotHangAndDisposeAsyncGetsCalled() { // Arrange @@ -398,7 +398,7 @@ public void GetAsyncService_DisposeAsyncOnSameThread_ThrowsAndDoesNotHangAndDisp Assert.True(asyncDisposableResource.DisposeAsyncCalled); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] public void GetService_DisposeOnSameThread_ThrowsAndDoesNotHangAndDisposeGetsCalled() { // Arrange diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextPaths.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextPaths.cs index b5c6730eef3e..298b704ac1c2 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextPaths.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextPaths.cs @@ -40,7 +40,7 @@ private static DependencyContextPaths GetCurrent() internal static DependencyContextPaths Create(string? depsFiles, string? sharedRuntime) { -#if NETCOREAPP +#if NET const char separator = ';'; #else // This method is only executed once at startup. No need to cache the char[]. diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/EnvironmentWrapper.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/EnvironmentWrapper.cs index d61aed3e622e..015103860277 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/EnvironmentWrapper.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/EnvironmentWrapper.cs @@ -10,7 +10,7 @@ namespace Microsoft.Extensions.DependencyModel { internal sealed class EnvironmentWrapper : IEnvironment { - public static IEnvironment Default = new EnvironmentWrapper(); + public static readonly IEnvironment Default = new EnvironmentWrapper(); public string? GetEnvironmentVariable(string name) => Environment.GetEnvironmentVariable(name); diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Composite/tests/MockFileProvider.cs b/src/libraries/Microsoft.Extensions.FileProviders.Composite/tests/MockFileProvider.cs index c9ce31d6e276..eed6a5044e6a 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Composite/tests/MockFileProvider.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Composite/tests/MockFileProvider.cs @@ -11,7 +11,7 @@ namespace Microsoft.Extensions.FileProviders.Composite { public class MockFileProvider : IFileProvider { -#if NETCOREAPP +#if NET static MockFileProvider() { // Castle DynamicProxy hasn't been updated to ignore .net5 infrastructure attributes diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/FileSystemInfoHelper.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/FileSystemInfoHelper.cs index 6559d5d46c9f..4796d4a8b0a3 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/FileSystemInfoHelper.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/FileSystemInfoHelper.cs @@ -31,7 +31,7 @@ public static bool IsExcluded(FileSystemInfo fileSystemInfo, ExclusionFilters fi public static DateTime? GetFileLinkTargetLastWriteTimeUtc(string filePath) { -#if NETCOREAPP +#if NET var fileInfo = new FileInfo(filePath); if (fileInfo.Exists) { @@ -47,7 +47,7 @@ public static bool IsExcluded(FileSystemInfo fileSystemInfo, ExclusionFilters fi // If file is not a link, return null to inform the caller that file is not a link. public static DateTime? GetFileLinkTargetLastWriteTimeUtc(FileInfo fileInfo) { -#if NETCOREAPP +#if NET Debug.Assert(fileInfo.Exists); if (fileInfo.LinkTarget != null) { diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFileProvider.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFileProvider.cs index fb2306d56e9f..925df9892752 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFileProvider.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFileProvider.cs @@ -162,7 +162,7 @@ internal PhysicalFilesWatcher CreateFileWatcher() string root = PathUtils.EnsureTrailingSlash(Path.GetFullPath(Root)); FileSystemWatcher? watcher; -#if NETCOREAPP +#if NET // For browser/iOS/tvOS we will proactively fallback to polling since FileSystemWatcher is not supported. if (OperatingSystem.IsBrowser() || (OperatingSystem.IsIOS() && !OperatingSystem.IsMacCatalyst()) || OperatingSystem.IsTvOS()) { diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs index db0a767573a1..712a83a3ef2c 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs @@ -88,7 +88,7 @@ public PhysicalFilesWatcher( if (fileSystemWatcher != null) { -#if NETCOREAPP +#if NET if (OperatingSystem.IsBrowser() || (OperatingSystem.IsIOS() && !OperatingSystem.IsMacCatalyst()) || OperatingSystem.IsTvOS()) { throw new PlatformNotSupportedException(SR.Format(SR.FileSystemWatcher_PlatformNotSupported, typeof(FileSystemWatcher))); @@ -160,7 +160,7 @@ private IChangeToken GetOrAddChangeToken(string pattern) } IChangeToken changeToken; -#if NET5_0_OR_GREATER +#if NET bool isWildCard = pattern.Contains('*'); #else bool isWildCard = pattern.IndexOf('*') != -1; diff --git a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/InMemoryDirectoryInfo.cs b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/InMemoryDirectoryInfo.cs index 4d41468a173e..8d6c9c3f33e4 100644 --- a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/InMemoryDirectoryInfo.cs +++ b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/InMemoryDirectoryInfo.cs @@ -51,13 +51,14 @@ private InMemoryDirectoryInfo(string rootDir, IEnumerable? files, bool n // normalize foreach (string file in files) { + string fileWithNormalSeparators = file.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); if (Path.IsPathRooted(file)) { - fileList.Add(Path.GetFullPath(file.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar))); + fileList.Add(Path.GetFullPath(fileWithNormalSeparators)); } else { - fileList.Add(Path.Combine(normalizedRoot, file.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar))); + fileList.Add(Path.GetFullPath(Path.Combine(normalizedRoot, fileWithNormalSeparators))); } } diff --git a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/Internal/MatcherContext.cs b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/Internal/MatcherContext.cs index b213474c2bb8..5080120689d2 100644 --- a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/Internal/MatcherContext.cs +++ b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/Internal/MatcherContext.cs @@ -17,8 +17,8 @@ namespace Microsoft.Extensions.FileSystemGlobbing.Internal public class MatcherContext { private readonly DirectoryInfoBase _root; - private readonly List _includePatternContexts; - private readonly List _excludePatternContexts; + private readonly IPatternContext[] _includePatternContexts; + private readonly IPatternContext[] _excludePatternContexts; private readonly List _files; private readonly HashSet _declaredLiteralFolderSegmentInString; @@ -39,8 +39,8 @@ public MatcherContext( _files = new List(); _comparisonType = comparison; - _includePatternContexts = includePatterns.Select(pattern => pattern.CreatePatternContextForInclude()).ToList(); - _excludePatternContexts = excludePatterns.Select(pattern => pattern.CreatePatternContextForExclude()).ToList(); + _includePatternContexts = includePatterns.Select(pattern => pattern.CreatePatternContextForInclude()).ToArray(); + _excludePatternContexts = excludePatterns.Select(pattern => pattern.CreatePatternContextForExclude()).ToArray(); _declaredLiteralFolderSegmentInString = new HashSet(StringComparisonHelper.GetStringComparer(comparison)); } @@ -67,10 +67,11 @@ private void Match(DirectoryInfoBase directory, string? parentRelativePath) } else { - IEnumerable candidates = directory.EnumerateFileSystemInfos().OfType(); - foreach (DirectoryInfoBase candidate in candidates) + IEnumerable candidates = directory.EnumerateFileSystemInfos(); + foreach (FileSystemInfoBase candidate in candidates) { - if (_declaredLiteralFolderSegmentInString.Contains(candidate.Name)) + if (candidate is DirectoryInfoBase && + _declaredLiteralFolderSegmentInString.Contains(candidate.Name)) { entities.Add(candidate); } diff --git a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/MatcherExtensions.cs b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/MatcherExtensions.cs index c400b6a665e9..c7db2fc67034 100644 --- a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/MatcherExtensions.cs +++ b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/MatcherExtensions.cs @@ -2,9 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections; using System.Collections.Generic; using System.IO; -using System.Linq; using Microsoft.Extensions.FileSystemGlobbing.Abstractions; namespace Microsoft.Extensions.FileSystemGlobbing @@ -51,9 +51,18 @@ public static void AddIncludePatterns(this Matcher matcher, params IEnumerableAbsolute file paths of all files matched. Empty enumerable if no files matched given patterns. public static IEnumerable GetResultsInFullPath(this Matcher matcher, string directoryPath) { - IEnumerable matches = matcher.Execute(new DirectoryInfoWrapper(new DirectoryInfo(directoryPath))).Files; - string[] result = matches.Select(match => Path.GetFullPath(Path.Combine(directoryPath, match.Path))).ToArray(); + PatternMatchingResult patternMatchingResult = matcher.Execute(new DirectoryInfoWrapper(new DirectoryInfo(directoryPath))); + if (!patternMatchingResult.HasMatches) + { + return Array.Empty(); + } + IEnumerable matches = patternMatchingResult.Files; + List result = matches is ICollection matchCollection ? new(matchCollection.Count) : new(); + foreach (FilePatternMatch match in matches) + { + result.Add(Path.GetFullPath(Path.Combine(directoryPath, match.Path))); + } return result; } diff --git a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/FunctionalTests.cs b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/FunctionalTests.cs index 0d9ca6ce1e20..e8bcdacdb955 100644 --- a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/FunctionalTests.cs +++ b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/FunctionalTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.DotNet.XUnitExtensions; using Microsoft.Extensions.FileSystemGlobbing.Abstractions; using Microsoft.Extensions.FileSystemGlobbing.Tests.TestUtility; using Xunit; @@ -851,5 +852,54 @@ public void VerifyInMemoryDirectoryInfo_IsNotEmpty() Assert.Equal(1, fileSystemInfos.Count()); } + + [Theory] + [InlineData("./sdk/9.0.100-preview.4.24207.1/.version")] + [InlineData("././sdk/9.0.100-preview.4.24207.1/.version")] + public void VerifyFiles_RedundantSegment_HasMatches(string file) + { + foreach (string pattern in new[] { "**/*", "./", file }) + { + var matcher = new Matcher(); + matcher.AddInclude(pattern); + Assert.True(matcher.Match(file).HasMatches); + Assert.True(matcher.Match([file]).HasMatches); + Assert.True(matcher.Match("X:/foo", file).HasMatches); + Assert.True(matcher.Match("X:/foo", [file]).HasMatches); + } + } + + [ConditionalFact] + public void VerifyFiles_ParentRedundantSegment_HasMatches() + { + string file = "sdk/9.0.100-preview.4.24207.1/.version"; + foreach (string pattern in new[] { "**/*", "./", file }) + { + var matcher = new Matcher(); + matcher.AddInclude(pattern); + Assert.True(matcher.Match("X:/foo", $"../foo/{file}").HasMatches); + Assert.True(matcher.Match("X:/foo", [$"../foo/{file}"]).HasMatches); + } + } + + [ConditionalFact] + public void VerifyFiles_ParentRedundantSegment_CurrentDirectory_HasMatches() + { + string cwd = Environment.CurrentDirectory; + string cwdFolderName = new DirectoryInfo(cwd).Name; + if (cwd == cwdFolderName) // cwd is root, we can't do ../C:/ + { + throw new SkipTestException($"CurrentDirectory {cwd} is the root directory."); + } + + string file = "sdk/9.0.100-preview.4.24207.1/.version"; + foreach (string pattern in new[] { "**/*", "./", file }) + { + var matcher = new Matcher(); + matcher.AddInclude(pattern); + Assert.True(matcher.Match($"../{cwdFolderName}/{file}").HasMatches); + Assert.True(matcher.Match([$"../{cwdFolderName}/{file}"]).HasMatches); + } + } } } diff --git a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/Microsoft.Extensions.FileSystemGlobbing.Tests.csproj b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/Microsoft.Extensions.FileSystemGlobbing.Tests.csproj index f96695c91c01..18043e2391cb 100644 --- a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/Microsoft.Extensions.FileSystemGlobbing.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/Microsoft.Extensions.FileSystemGlobbing.Tests.csproj @@ -5,10 +5,6 @@ true - - - - diff --git a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/TestUtility/DisposableFileSystem.cs b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/TestUtility/DisposableFileSystem.cs index 50abfa57af42..1571b88402ec 100644 --- a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/TestUtility/DisposableFileSystem.cs +++ b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/TestUtility/DisposableFileSystem.cs @@ -10,7 +10,7 @@ public class DisposableFileSystem : IDisposable { public DisposableFileSystem() { -#if NETCOREAPP +#if NET DirectoryInfo = Directory.CreateTempSubdirectory(); #else DirectoryInfo = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())); diff --git a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/default.rd.xml b/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/default.rd.xml deleted file mode 100644 index 2c14c77dbb3c..000000000000 --- a/src/libraries/Microsoft.Extensions.FileSystemGlobbing/tests/default.rd.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/HostFactoryResolverTests.cs b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/HostFactoryResolverTests.cs index f123b65bb58b..e95a745a5259 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/HostFactoryResolverTests.cs +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/HostFactoryResolverTests.cs @@ -37,7 +37,7 @@ public void BuildWebHostPattern_CanFindServiceProvider() Assert.IsAssignableFrom(factory(Array.Empty())); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(BuildWebHostInvalidSignature.Program))] public void BuildWebHostPattern__Invalid_CantFindWebHost() { @@ -46,7 +46,7 @@ public void BuildWebHostPattern__Invalid_CantFindWebHost() Assert.Null(factory); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(BuildWebHostInvalidSignature.Program))] public void BuildWebHostPattern__Invalid_CantFindServiceProvider() { @@ -55,7 +55,7 @@ public void BuildWebHostPattern__Invalid_CantFindServiceProvider() Assert.NotNull(factory); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CreateWebHostBuilderPatternTestSite.Program))] public void CreateWebHostBuilderPattern_CanFindWebHostBuilder() { @@ -65,7 +65,7 @@ public void CreateWebHostBuilderPattern_CanFindWebHostBuilder() Assert.IsAssignableFrom(factory(Array.Empty())); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CreateWebHostBuilderPatternTestSite.Program))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(IWebHost))] public void CreateWebHostBuilderPattern_CanFindServiceProvider() @@ -76,7 +76,7 @@ public void CreateWebHostBuilderPattern_CanFindServiceProvider() Assert.IsAssignableFrom(factory(Array.Empty())); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CreateWebHostBuilderInvalidSignature.Program))] public void CreateWebHostBuilderPattern__Invalid_CantFindWebHostBuilder() { @@ -85,7 +85,7 @@ public void CreateWebHostBuilderPattern__Invalid_CantFindWebHostBuilder() Assert.Null(factory); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CreateWebHostBuilderInvalidSignature.Program))] public void CreateWebHostBuilderPattern__InvalidReturnType_CanFindServiceProvider() { @@ -95,7 +95,7 @@ public void CreateWebHostBuilderPattern__InvalidReturnType_CanFindServiceProvide Assert.Null(factory(Array.Empty())); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CreateHostBuilderPatternTestSite.Program))] public void CreateHostBuilderPattern_CanFindHostBuilder() { @@ -105,7 +105,7 @@ public void CreateHostBuilderPattern_CanFindHostBuilder() Assert.IsAssignableFrom(factory(Array.Empty())); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CreateHostBuilderPatternTestSite.Program))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Host))] public void CreateHostBuilderPattern_CanFindServiceProvider() @@ -116,7 +116,7 @@ public void CreateHostBuilderPattern_CanFindServiceProvider() Assert.IsAssignableFrom(factory(Array.Empty())); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CreateHostBuilderInvalidSignature.Program))] public void CreateHostBuilderPattern__Invalid_CantFindHostBuilder() { @@ -125,7 +125,7 @@ public void CreateHostBuilderPattern__Invalid_CantFindHostBuilder() Assert.Null(factory); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(CreateHostBuilderInvalidSignature.Program))] public void CreateHostBuilderPattern__Invalid_CantFindServiceProvider() { @@ -135,7 +135,7 @@ public void CreateHostBuilderPattern__Invalid_CantFindServiceProvider() Assert.Throws(() => factory(Array.Empty())); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NoSpecialEntryPointPattern.Program))] public void NoSpecialEntryPointPattern() { @@ -145,7 +145,7 @@ public void NoSpecialEntryPointPattern() Assert.IsAssignableFrom(factory(Array.Empty())); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NoSpecialEntryPointPattern.Program))] public void NoSpecialEntryPointPatternHostBuilderConfigureHostBuilderCallbackIsCalled() { @@ -163,7 +163,7 @@ void ConfigureHostBuilder(object hostBuilder) Assert.True(called); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NoSpecialEntryPointPattern.Program))] public void NoSpecialEntryPointPatternBuildsThenThrowsCallsEntryPointCompletedCallback() { @@ -183,7 +183,7 @@ void EntryPointCompleted(Exception? exception) Assert.Null(entryPointException); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NoSpecialEntryPointPatternBuildsThenThrows.Program))] public void NoSpecialEntryPointPatternBuildsThenThrowsCallsEntryPointCompletedCallbackWithException() { @@ -203,7 +203,7 @@ void EntryPointCompleted(Exception? exception) Assert.NotNull(entryPointException); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NoSpecialEntryPointPatternThrows.Program))] public void NoSpecialEntryPointPatternThrows() { @@ -213,7 +213,7 @@ public void NoSpecialEntryPointPatternThrows() Assert.Throws(() => factory(Array.Empty())); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NoSpecialEntryPointPatternExits.Program))] public void NoSpecialEntryPointPatternExits() { @@ -223,7 +223,7 @@ public void NoSpecialEntryPointPatternExits() Assert.Throws(() => factory(Array.Empty())); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NoSpecialEntryPointPatternHangs.Program))] public void NoSpecialEntryPointPatternHangs() { @@ -233,7 +233,7 @@ public void NoSpecialEntryPointPatternHangs() Assert.Throws(() => factory(Array.Empty())); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NoSpecialEntryPointPatternMainNoArgs.Program))] public void NoSpecialEntryPointPatternMainNoArgs() { @@ -243,7 +243,7 @@ public void NoSpecialEntryPointPatternMainNoArgs() Assert.IsAssignableFrom(factory(Array.Empty())); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, "Program", "TopLevelStatements")] public void TopLevelStatements() { @@ -254,7 +254,7 @@ public void TopLevelStatements() Assert.IsAssignableFrom(factory(Array.Empty())); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, "Program", "TopLevelStatementsTestsTimeout")] public void TopLevelStatementsTestsTimeout() { @@ -265,7 +265,7 @@ public void TopLevelStatementsTestsTimeout() Assert.Throws(() => factory(Array.Empty())); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, "Program", "ApplicationNameSetFromArgument")] public void ApplicationNameSetFromArgument() { @@ -277,7 +277,7 @@ public void ApplicationNameSetFromArgument() Assert.Contains("ApplicationNameSetFromArgument", configuration["applicationName"]); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NoSpecialEntryPointPattern.Program))] public void NoSpecialEntryPointPatternCanRunInParallel() { diff --git a/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdHelpers.cs b/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdHelpers.cs index c7887bc29b23..53d382c5e7c9 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdHelpers.cs +++ b/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdHelpers.cs @@ -5,7 +5,7 @@ using System.Globalization; using System.IO; using System.Text; -#if !NETCOREAPP +#if !NET using System.Diagnostics; #endif @@ -37,7 +37,7 @@ private static bool GetIsSystemdService() // To support containerized systemd services, check if we're the main process (PID 1) // and if there are systemd environment variables defined for notifying the service // manager, or passing listen handles. -#if NETCOREAPP +#if NET int processId = Environment.ProcessId; #else int processId = Process.GetCurrentProcess().Id; diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceHelpers.cs b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceHelpers.cs index 9de601ddebe7..05eed40ff6df 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceHelpers.cs +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceHelpers.cs @@ -28,7 +28,7 @@ private static bool GetIsWindowsService() if ( #if NETFRAMEWORK Environment.OSVersion.Platform != PlatformID.Win32NT -#elif NET5_0_OR_GREATER +#elif NET !OperatingSystem.IsWindows() #else !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs b/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs index 7a965e0efc85..4a9806a2fcd7 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs @@ -190,11 +190,6 @@ internal static DiagnosticListener LogHostBuilding(HostApplicationBuilder hostAp return diagnosticListener; } -// Remove when https://github.com/dotnet/runtime/pull/78532 is merged and consumed by the used SDK. -#if NET7_0 - [UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", - Justification = "DiagnosticSource is used here to pass objects in-memory to code using HostFactoryResolver. This won't require creating new generic types.")] -#endif [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = "The values being passed into Write are being consumed by the application already.")] private static void Write<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>( diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs b/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs index a0407b8c2ec7..09274bad3a3c 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs @@ -275,7 +275,7 @@ internal static void AddDefaultServices(HostBuilderContext hostingContext, IServ services.AddLogging(logging => { bool isWindows = -#if NETCOREAPP +#if NET OperatingSystem.IsWindows(); #elif NETFRAMEWORK Environment.OSVersion.Platform == PlatformID.Win32NT; @@ -292,7 +292,7 @@ internal static void AddDefaultServices(HostBuilderContext hostingContext, IServ } logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); -#if NETCOREAPP +#if NET if (!OperatingSystem.IsBrowser()) #endif { diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs index d2167ae3697f..f923221fdb7b 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs @@ -255,7 +255,7 @@ public void DisableDefaultIHostEnvironmentValues(CreateBuilderFunc createBuilder HostApplicationBuilder builder = createBuilder(); Assert.Equal(Environments.Production, builder.Environment.EnvironmentName); -#if NETCOREAPP +#if NET Assert.NotNull(builder.Environment.ApplicationName); #elif NETFRAMEWORK // Note GetEntryAssembly returns null for the net4x console test runner. @@ -270,7 +270,7 @@ public void DisableDefaultIHostEnvironmentValues(CreateBuilderFunc createBuilder var env = host.Services.GetRequiredService(); Assert.Equal(Environments.Production, env.EnvironmentName); -#if NETCOREAPP +#if NET Assert.NotNull(env.ApplicationName); #elif NETFRAMEWORK // Note GetEntryAssembly returns null for the net4x console test runner. @@ -382,7 +382,7 @@ public void DirectSettingsOverrideConfigurationSetting(CreateBuilderSettingsFunc private static string CreateTempSubdirectory() { -#if NETCOREAPP +#if NET DirectoryInfo directoryInfo = Directory.CreateTempSubdirectory(); #else DirectoryInfo directoryInfo = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())); diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostBuilderTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostBuilderTests.cs index 5d37dbd15ec3..da863fec6535 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostBuilderTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostBuilderTests.cs @@ -174,7 +174,7 @@ public void DefaultIHostEnvironmentValues() { var env = hostContext.HostingEnvironment; Assert.Equal(Environments.Production, env.EnvironmentName); -#if NETCOREAPP +#if NET Assert.NotNull(env.ApplicationName); #elif NETFRAMEWORK // Note GetEntryAssembly returns null for the net4x console test runner. @@ -190,7 +190,7 @@ public void DefaultIHostEnvironmentValues() { var env = host.Services.GetRequiredService(); Assert.Equal(Environments.Production, env.EnvironmentName); -#if NETCOREAPP +#if NET Assert.NotNull(env.ApplicationName); #elif NETFRAMEWORK // Note GetEntryAssembly returns null for the net4x console test runner. diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/OptionsBuilderExtensionsTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/OptionsBuilderExtensionsTests.cs index 74c2a1c0bfe9..6a67cbcaa950 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/OptionsBuilderExtensionsTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/OptionsBuilderExtensionsTests.cs @@ -413,7 +413,7 @@ private static void ValidateFailure(Type type, OptionsValidationException e, int // Check for the error in any of the failures foreach (var error in errorsToMatch) { -#if NETCOREAPP +#if NET Assert.True(e.Failures.FirstOrDefault(predicate: f => f.Contains(error, StringComparison.CurrentCulture)) != null, "Did not find: " + error + " " + e.Failures.First()); #else Assert.True(e.Failures.FirstOrDefault(predicate: f => f.IndexOf(error, StringComparison.CurrentCulture) >= 0) != null, "Did not find: " + error + " " + e.Failures.First()); diff --git a/src/libraries/Microsoft.Extensions.Http/ref/Microsoft.Extensions.Http.cs b/src/libraries/Microsoft.Extensions.Http/ref/Microsoft.Extensions.Http.cs index 51891e8ebcf7..8c7911242088 100644 --- a/src/libraries/Microsoft.Extensions.Http/ref/Microsoft.Extensions.Http.cs +++ b/src/libraries/Microsoft.Extensions.Http/ref/Microsoft.Extensions.Http.cs @@ -28,7 +28,7 @@ public static partial class HttpClientBuilderExtensions public static Microsoft.Extensions.DependencyInjection.IHttpClientBuilder RedactLoggedHeaders(this Microsoft.Extensions.DependencyInjection.IHttpClientBuilder builder, System.Func shouldRedactHeaderValue) { throw null; } public static Microsoft.Extensions.DependencyInjection.IHttpClientBuilder RemoveAllLoggers(this Microsoft.Extensions.DependencyInjection.IHttpClientBuilder builder) { throw null; } public static Microsoft.Extensions.DependencyInjection.IHttpClientBuilder SetHandlerLifetime(this Microsoft.Extensions.DependencyInjection.IHttpClientBuilder builder, System.TimeSpan handlerLifetime) { throw null; } -#if NET5_0_OR_GREATER +#if NET [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public static Microsoft.Extensions.DependencyInjection.IHttpClientBuilder UseSocketsHttpHandler(this Microsoft.Extensions.DependencyInjection.IHttpClientBuilder builder, System.Action? configureHandler = null) { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] @@ -64,14 +64,14 @@ public partial interface IHttpClientBuilder string Name { get; } Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get; } } -#if NET5_0_OR_GREATER +#if NET public partial interface ISocketsHttpHandlerBuilder { string Name { get; } Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get; } } #endif -#if NET5_0_OR_GREATER +#if NET public static partial class SocketsHttpHandlerBuilderExtensions { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] diff --git a/src/libraries/Microsoft.Extensions.Http/src/ActiveHandlerTrackingEntry.cs b/src/libraries/Microsoft.Extensions.Http/src/ActiveHandlerTrackingEntry.cs index 54453271946e..c6e78a4d67d8 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/ActiveHandlerTrackingEntry.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/ActiveHandlerTrackingEntry.cs @@ -33,7 +33,7 @@ public ActiveHandlerTrackingEntry( _lock = new object(); } - public LifetimeTrackingHttpMessageHandler Handler { get; private set; } + public LifetimeTrackingHttpMessageHandler Handler { get; } public TimeSpan Lifetime { get; } diff --git a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/DefaultSocketsHttpHandlerBuilder.cs b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/DefaultSocketsHttpHandlerBuilder.cs index 57b905c0f3e6..61986cedfbe1 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/DefaultSocketsHttpHandlerBuilder.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/DefaultSocketsHttpHandlerBuilder.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NET5_0_OR_GREATER +#if NET namespace Microsoft.Extensions.DependencyInjection { internal sealed class DefaultSocketsHttpHandlerBuilder : ISocketsHttpHandlerBuilder diff --git a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/HttpClientBuilderExtensions.cs b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/HttpClientBuilderExtensions.cs index a9adb32fc5d8..758a989be3a8 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/HttpClientBuilderExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/HttpClientBuilderExtensions.cs @@ -265,7 +265,7 @@ public static IHttpClientBuilder ConfigureHttpMessageHandlerBuilder(this IHttpCl return builder; } -#if NET5_0_OR_GREATER +#if NET /// /// Adds or updates as a primary handler for a named . If provided, /// also adds a delegate that will be used to configure the primary . diff --git a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/ISocketsHttpHandlerBuilder.cs b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/ISocketsHttpHandlerBuilder.cs index d7509e009c9c..75333f8d747c 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/ISocketsHttpHandlerBuilder.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/ISocketsHttpHandlerBuilder.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NET5_0_OR_GREATER +#if NET namespace Microsoft.Extensions.DependencyInjection { /// diff --git a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/SocketsHttpHandlerBuilderExtensions.cs b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/SocketsHttpHandlerBuilderExtensions.cs index 0d56606b742b..d3bb98c8a116 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/SocketsHttpHandlerBuilderExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/SocketsHttpHandlerBuilderExtensions.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NET5_0_OR_GREATER +#if NET using System; using System.Net; using System.Net.Http; diff --git a/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpClientLoggerHandler.cs b/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpClientLoggerHandler.cs index 087ec81fbb6c..a7aeebe8578f 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpClientLoggerHandler.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpClientLoggerHandler.cs @@ -61,7 +61,7 @@ protected override async Task SendAsync(HttpRequestMessage } } -#if NET5_0_OR_GREATER +#if NET protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) { ThrowHelper.ThrowIfNull(request); diff --git a/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpHeadersLogValue.cs b/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpHeadersLogValue.cs index 802192c4a905..23b07adf7f50 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpHeadersLogValue.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/Logging/HttpHeadersLogValue.cs @@ -103,7 +103,7 @@ public override string ToString() } else { -#if NETCOREAPP +#if NET builder.AppendJoin(", ", (IEnumerable)kvp.Value); builder.AppendLine(); #else diff --git a/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingHttpMessageHandler.cs b/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingHttpMessageHandler.cs index 5056474e9ead..e592e7d236fb 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingHttpMessageHandler.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingHttpMessageHandler.cs @@ -62,7 +62,7 @@ async Task Core(HttpRequestMessage request, bool useAsync, var stopwatch = ValueStopwatch.StartNew(); HttpResponseMessage response = useAsync ? await base.SendAsync(request, cancellationToken).ConfigureAwait(false) -#if NET5_0_OR_GREATER +#if NET : base.Send(request, cancellationToken); #else : throw new NotImplementedException("Unreachable code"); @@ -78,7 +78,7 @@ async Task Core(HttpRequestMessage request, bool useAsync, protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => SendCoreAsync(request, useAsync: true, cancellationToken); -#if NET5_0_OR_GREATER +#if NET /// /// Logs the request to and response from the sent . protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) diff --git a/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingScopeHttpMessageHandler.cs b/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingScopeHttpMessageHandler.cs index e170acbfe83c..1894a005f84a 100644 --- a/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingScopeHttpMessageHandler.cs +++ b/src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingScopeHttpMessageHandler.cs @@ -63,7 +63,7 @@ async Task Core(HttpRequestMessage request, bool useAsync, Log.RequestPipelineStart(_logger, request, shouldRedactHeaderValue); HttpResponseMessage response = useAsync ? await base.SendAsync(request, cancellationToken).ConfigureAwait(false) -#if NET5_0_OR_GREATER +#if NET : base.Send(request, cancellationToken); #else : throw new NotImplementedException("Unreachable code"); @@ -80,7 +80,7 @@ async Task Core(HttpRequestMessage request, bool useAsync, protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => SendCoreAsync(request, useAsync: true, cancellationToken); -#if NET5_0_OR_GREATER +#if NET /// /// Logs the request to and response from the sent . protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) diff --git a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/DependencyInjection/HttpClientFactoryServiceCollectionExtensionsTest.cs b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/DependencyInjection/HttpClientFactoryServiceCollectionExtensionsTest.cs index 81bb589fcfb3..c72b17e72884 100644 --- a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/DependencyInjection/HttpClientFactoryServiceCollectionExtensionsTest.cs +++ b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/DependencyInjection/HttpClientFactoryServiceCollectionExtensionsTest.cs @@ -1203,7 +1203,7 @@ public async Task AddHttpClient_MessageHandler_Scope_TransientDependency() } } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec), nameof(PlatformDetection.IsReflectionEmitSupported))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported), nameof(PlatformDetection.IsReflectionEmitSupported))] public void AddHttpClient_GetAwaiterAndResult_InSingleThreadedSynchronizationContext_ShouldNotHangs() { // Arrange diff --git a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/HttpClientLoggerTest.cs b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/HttpClientLoggerTest.cs index 6fb8e2dd8f7a..039ba46b1862 100644 --- a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/HttpClientLoggerTest.cs +++ b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/HttpClientLoggerTest.cs @@ -156,7 +156,7 @@ private void AssertCounters(TestCountingLogger testLogger, int requestCount, boo } } -#if NET5_0_OR_GREATER +#if NET [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNetCore))] [InlineData(false, false)] [InlineData(false, true)] @@ -588,7 +588,7 @@ private async Task SendAsyncCore(HttpRequestMessage request } else { -#if NET5_0_OR_GREATER +#if NET return base.Send(request, cancellationToken); #else throw new NotImplementedException("unreachable"); @@ -609,7 +609,7 @@ private async Task SendAsyncCore(HttpRequestMessage request protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => SendAsyncCore(request, async: true, cancellationToken); -#if NET5_0_OR_GREATER +#if NET protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) => SendAsyncCore(request, async: false, cancellationToken).GetAwaiter().GetResult(); #endif diff --git a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/LoggingUriOutputTests.cs b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/LoggingUriOutputTests.cs index 8f6ca7a8c4e2..bdd204f709df 100644 --- a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/LoggingUriOutputTests.cs +++ b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/Logging/LoggingUriOutputTests.cs @@ -91,7 +91,7 @@ public async Task LoggingScopeHttpMessageHandler_LogsAbsoluteUri() Assert.Equal("HTTP GET http://api.example.com/search?term=Western%20Australia", message.Scope.ToString()); } -#if NET5_0_OR_GREATER +#if NET [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNetCore))] public void LoggingHttpMessageHandler_LogsAbsoluteUri_Sync() { diff --git a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/SocketsHttpHandlerConfigurationTest.cs b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/SocketsHttpHandlerConfigurationTest.cs index 4473917ff728..059557a0784a 100644 --- a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/SocketsHttpHandlerConfigurationTest.cs +++ b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/SocketsHttpHandlerConfigurationTest.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NET5_0_OR_GREATER +#if NET using System; using System.Collections.Generic; using System.Net; diff --git a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/TestMessageHandler.cs b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/TestMessageHandler.cs index 5cbb8eb168f3..6bf2050cbd15 100644 --- a/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/TestMessageHandler.cs +++ b/src/libraries/Microsoft.Extensions.Http/tests/Microsoft.Extensions.Http.Tests/TestMessageHandler.cs @@ -26,7 +26,7 @@ protected override Task SendAsync(HttpRequestMessage reques return Task.FromResult(response); } -#if NET5_0_OR_GREATER +#if NET protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) => _responseFactory(request); #endif } diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogValuesFormatter.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogValuesFormatter.cs index fb92b7bbd1e2..69707c14c3f2 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogValuesFormatter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogValuesFormatter.cs @@ -82,7 +82,7 @@ public LogValuesFormatter(string format) #endif } - public string OriginalFormat { get; private set; } + public string OriginalFormat { get; } public List ValueNames => _valueNames; private static int FindBraceIndex(string format, char brace, int startIndex, int endIndex) diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/AnsiParsingLogConsole.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/AnsiParsingLogConsole.cs index 8cab45f3ffc0..563fcacac6da 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/AnsiParsingLogConsole.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/AnsiParsingLogConsole.cs @@ -62,7 +62,7 @@ private void WriteToConsole(string message, int startIndex, int length, ConsoleC { ReadOnlySpan span = message.AsSpan(startIndex, length); var colorChanged = SetColor(background, foreground); -#if NETCOREAPP +#if NET _textWriter.Write(span); #else _textWriter.Write(span.ToString()); diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs index 122556bbbe46..945e6ebb2358 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Buffers; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; @@ -32,10 +33,16 @@ public override void Write(in LogEntry logEntry, IExternalScopeP { return; } - LogLevel logLevel = logEntry.LogLevel; - string category = logEntry.Category; - int eventId = logEntry.EventId.Id; - Exception? exception = logEntry.Exception; + + // We extract most of the work into a non-generic method to save code size. If this was left in the generic + // method, we'd get generic specialization for all TState parameters, but that's unnecessary. + WriteInternal(scopeProvider, textWriter, message, logEntry.LogLevel, logEntry.Category, logEntry.EventId.Id, logEntry.Exception, + logEntry.State != null, logEntry.State?.ToString(), logEntry.State as IReadOnlyCollection>); + } + + private void WriteInternal(IExternalScopeProvider? scopeProvider, TextWriter textWriter, string message, LogLevel logLevel, + string category, int eventId, Exception? exception, bool hasState, string? stateMessage, IReadOnlyCollection>? stateProperties) + { const int DefaultBufferSize = 1024; using (var output = new PooledByteBufferWriter(DefaultBufferSize)) { @@ -48,9 +55,9 @@ public override void Write(in LogEntry logEntry, IExternalScopeP DateTimeOffset dateTimeOffset = FormatterOptions.UseUtcTimestamp ? DateTimeOffset.UtcNow : DateTimeOffset.Now; writer.WriteString("Timestamp", dateTimeOffset.ToString(timestampFormat)); } - writer.WriteNumber(nameof(logEntry.EventId), eventId); - writer.WriteString(nameof(logEntry.LogLevel), GetLogLevelString(logLevel)); - writer.WriteString(nameof(logEntry.Category), category); + writer.WriteNumber(nameof(LogEntry.EventId), eventId); + writer.WriteString(nameof(LogEntry.LogLevel), GetLogLevelString(logLevel)); + writer.WriteString(nameof(LogEntry.Category), category); writer.WriteString("Message", message); if (exception != null) @@ -58,11 +65,11 @@ public override void Write(in LogEntry logEntry, IExternalScopeP writer.WriteString(nameof(Exception), exception.ToString()); } - if (logEntry.State != null) + if (hasState) { - writer.WriteStartObject(nameof(logEntry.State)); - writer.WriteString("Message", logEntry.State.ToString()); - if (logEntry.State is IReadOnlyCollection> stateProperties) + writer.WriteStartObject(nameof(LogEntry.State)); + writer.WriteString("Message", stateMessage); + if (stateProperties != null) { foreach (KeyValuePair item in stateProperties) { @@ -75,11 +82,30 @@ public override void Write(in LogEntry logEntry, IExternalScopeP writer.WriteEndObject(); writer.Flush(); } -#if NETCOREAPP - textWriter.Write(Encoding.UTF8.GetString(output.WrittenMemory.Span)); -#else - textWriter.Write(Encoding.UTF8.GetString(output.WrittenMemory.Span.ToArray())); -#endif + + var messageBytes = output.WrittenMemory.Span; + var logMessageBuffer = ArrayPool.Shared.Rent(Encoding.UTF8.GetMaxCharCount(messageBytes.Length)); + try + { + #if NET + var charsWritten = Encoding.UTF8.GetChars(messageBytes, logMessageBuffer); + #else + int charsWritten; + unsafe + { + fixed (byte* messageBytesPtr = messageBytes) + fixed (char* logMessageBufferPtr = logMessageBuffer) + { + charsWritten = Encoding.UTF8.GetChars(messageBytesPtr, messageBytes.Length, logMessageBufferPtr, logMessageBuffer.Length); + } + } + #endif + textWriter.Write(logMessageBuffer, 0, charsWritten); + } + finally + { + ArrayPool.Shared.Return(logMessageBuffer); + } } textWriter.Write(Environment.NewLine); } @@ -139,7 +165,7 @@ private static void WriteItem(Utf8JsonWriter writer, KeyValuePair OperatingSystem.IsAndroid() || OperatingSystem.IsTvOS() || OperatingSystem.IsIOS(); // returns true on MacCatalyst @@ -51,7 +51,15 @@ public override void Write(in LogEntry logEntry, IExternalScopeP { return; } - LogLevel logLevel = logEntry.LogLevel; + + // We extract most of the work into a non-generic method to save code size. If this was left in the generic + // method, we'd get generic specialization for all TState parameters, but that's unnecessary. + WriteInternal(scopeProvider, textWriter, message, logEntry.LogLevel, logEntry.EventId.Id, logEntry.Exception, logEntry.Category); + } + + private void WriteInternal(IExternalScopeProvider? scopeProvider, TextWriter textWriter, string message, LogLevel logLevel, + int eventId, Exception? exception, string category) + { ConsoleColors logLevelColors = GetLogLevelConsoleColors(logLevel); string logLevelString = GetLogLevelString(logLevel); @@ -70,14 +78,8 @@ public override void Write(in LogEntry logEntry, IExternalScopeP { textWriter.WriteColoredMessage(logLevelString, logLevelColors.Background, logLevelColors.Foreground); } - CreateDefaultLogMessage(textWriter, logEntry, message, scopeProvider); - } - private void CreateDefaultLogMessage(TextWriter textWriter, in LogEntry logEntry, string message, IExternalScopeProvider? scopeProvider) - { bool singleLine = FormatterOptions.SingleLine; - int eventId = logEntry.EventId.Id; - Exception? exception = logEntry.Exception; // Example: // info: ConsoleApp.Program[10] @@ -85,10 +87,10 @@ private void CreateDefaultLogMessage(TextWriter textWriter, in LogEntry< // category and event id textWriter.Write(LoglevelPadding); - textWriter.Write(logEntry.Category); + textWriter.Write(category); textWriter.Write('['); -#if NETCOREAPP +#if NET Span span = stackalloc char[10]; if (eventId.TryFormat(span, out int charsWritten)) textWriter.Write(span.Slice(0, charsWritten)); diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/SystemdConsoleFormatter.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/SystemdConsoleFormatter.cs index 5c0626307db1..2d306fee1d0a 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/SystemdConsoleFormatter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/SystemdConsoleFormatter.cs @@ -41,10 +41,15 @@ public override void Write(in LogEntry logEntry, IExternalScopeP { return; } - LogLevel logLevel = logEntry.LogLevel; - string category = logEntry.Category; - int eventId = logEntry.EventId.Id; - Exception? exception = logEntry.Exception; + + // We extract most of the work into a non-generic method to save code size. If this was left in the generic + // method, we'd get generic specialization for all TState parameters, but that's unnecessary. + WriteInternal(scopeProvider, textWriter, message, logEntry.LogLevel, logEntry.Category, logEntry.EventId.Id, logEntry.Exception); + } + + private void WriteInternal(IExternalScopeProvider? scopeProvider, TextWriter textWriter, string message, LogLevel logLevel, string category, + int eventId, Exception? exception) + { // systemd reads messages from standard out line-by-line in a 'message' format. // newline characters are treated as message delimiters, so we must replace them. // Messages longer than the journal LineMax setting (default: 48KB) are cropped. diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerConfigureOptions.cs b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerConfigureOptions.cs index 3b725f1cb59e..663b766ba4c9 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerConfigureOptions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerConfigureOptions.cs @@ -25,7 +25,7 @@ public void EnsureConsoleLoggerOptions_ConfigureOptions_SupportsAllProperties() Assert.Equal(3, typeof(ConsoleFormatterOptions).GetProperties(flags).Length); Assert.Equal(5, typeof(SimpleConsoleFormatterOptions).GetProperties(flags).Length); Assert.Equal(4, typeof(JsonConsoleFormatterOptions).GetProperties(flags).Length); - Assert.Equal(6, typeof(JsonWriterOptions).GetProperties(flags).Length); + Assert.Equal(7, typeof(JsonWriterOptions).GetProperties(flags).Length); } [Theory] diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerExtensionsTests.cs b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerExtensionsTests.cs index fec2d737c8d2..60188dc2ce4f 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerExtensionsTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerExtensionsTests.cs @@ -273,11 +273,13 @@ public void AddSystemdConsole_OutsideConfig_TakesProperty() [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] public void AddJsonConsole_ChangeProperties_IsReadFromLoggingConfiguration() { + var newLine = Environment.NewLine.Length is 2 ? "\n" : "\r\n"; var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair("Console:FormatterOptions:TimestampFormat", "HH:mm "), new KeyValuePair("Console:FormatterOptions:UseUtcTimestamp", "true"), new KeyValuePair("Console:FormatterOptions:IncludeScopes", "true"), new KeyValuePair("Console:FormatterOptions:JsonWriterOptions:Indented", "true"), + new KeyValuePair("Console:FormatterOptions:JsonWriterOptions:NewLine", newLine), }).Build(); var loggerProvider = new ServiceCollection() @@ -296,11 +298,13 @@ public void AddJsonConsole_ChangeProperties_IsReadFromLoggingConfiguration() Assert.True(formatter.FormatterOptions.UseUtcTimestamp); Assert.True(formatter.FormatterOptions.IncludeScopes); Assert.True(formatter.FormatterOptions.JsonWriterOptions.Indented); + Assert.Equal(newLine, formatter.FormatterOptions.JsonWriterOptions.NewLine); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] public void AddJsonConsole_OutsideConfig_TakesProperty() { + var newLine = Environment.NewLine.Length is 2 ? "\n" : "\r\n"; var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair("Console:FormatterOptions:TimestampFormat", "HH:mm "), new KeyValuePair("Console:FormatterOptions:UseUtcTimestamp", "true"), @@ -314,7 +318,8 @@ public void AddJsonConsole_OutsideConfig_TakesProperty() o.JsonWriterOptions = new JsonWriterOptions() { Indented = false, - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + NewLine = newLine }; }) ) @@ -329,6 +334,7 @@ public void AddJsonConsole_OutsideConfig_TakesProperty() Assert.True(formatter.FormatterOptions.UseUtcTimestamp); Assert.True(formatter.FormatterOptions.IncludeScopes); Assert.False(formatter.FormatterOptions.JsonWriterOptions.Indented); + Assert.Equal(newLine, formatter.FormatterOptions.JsonWriterOptions.NewLine); Assert.Equal(JavaScriptEncoder.UnsafeRelaxedJsonEscaping, formatter.FormatterOptions.JsonWriterOptions.Encoder); } diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/EventSourceLoggerTest.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/EventSourceLoggerTest.cs index 343036cca5b5..eb4f25eb34fc 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/EventSourceLoggerTest.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/tests/EventSourceLoggerTest.cs @@ -904,7 +904,7 @@ private static class EventTypes @"""FormattedMessage"":""Logger2 Event5 Critical bar 23 45") }, // Starting in netcoreapp3.0 Exception.ToString() puts a newline before inner exceptions -#if NETCOREAPP +#if NET { "E5JS", (e) => VerifySingleEvent(e, "Logger2", EventTypes.MessageJson, 5, null, LogLevel.Critical, @"""ArgumentsJson"":{""stringParam"":""bar"",""int1Param"":""23"",""int2Param"":""45""", @$"""ExceptionJson"":{{""TypeName"":""System.Exception"",""Message"":""oops"",""HResult"":""-2146233088"",""VerboseMessage"":""System.Exception: oops{EscapedNewline()} ---\u003E System.Exception: inner oops") }, diff --git a/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceLoggerProviderTest.cs b/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceLoggerProviderTest.cs index 80d9e7ab1909..83dd9e8b619b 100644 --- a/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceLoggerProviderTest.cs +++ b/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceLoggerProviderTest.cs @@ -66,7 +66,7 @@ public override void WriteLine(string message) } } } -#elif NETCOREAPP +#elif NET #else #error Target framework needs to be updated #endif diff --git a/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceScopeTest.cs b/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceScopeTest.cs index 25bd315a8679..42c16ecd30bb 100644 --- a/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceScopeTest.cs +++ b/src/libraries/Microsoft.Extensions.Logging/tests/Common/TraceSourceScopeTest.cs @@ -33,7 +33,7 @@ public static void DiagnosticsScope_PushesAndPops_LogicalOperationStack() Assert.Same(a, c); Assert.Same(state, b); } -#elif NETCOREAPP +#elif NET #else #error Target framework needs to be updated #endif diff --git a/src/libraries/Microsoft.Extensions.Options/src/IOptionsFactory.cs b/src/libraries/Microsoft.Extensions.Options/src/IOptionsFactory.cs index e59516138288..1504a6566a34 100644 --- a/src/libraries/Microsoft.Extensions.Options/src/IOptionsFactory.cs +++ b/src/libraries/Microsoft.Extensions.Options/src/IOptionsFactory.cs @@ -17,7 +17,7 @@ public interface IOptionsFactory<[DynamicallyAccessedMembers(Options.Dynamically /// Returns a configured instance with the given . /// /// The name of the instance to create. - /// The created instance with thw given . + /// The created instance with the given . TOptions Create(string name); } } diff --git a/src/libraries/Microsoft.Extensions.Options/src/OptionsBuilderExtensions.cs b/src/libraries/Microsoft.Extensions.Options/src/OptionsBuilderExtensions.cs index b8bcaa418cce..2eacc9038e30 100644 --- a/src/libraries/Microsoft.Extensions.Options/src/OptionsBuilderExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Options/src/OptionsBuilderExtensions.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics.CodeAnalysis; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; namespace Microsoft.Extensions.DependencyInjection @@ -25,7 +26,7 @@ public static class OptionsBuilderExtensions { ThrowHelper.ThrowIfNull(optionsBuilder); - optionsBuilder.Services.AddTransient(); + optionsBuilder.Services.TryAddTransient(); optionsBuilder.Services.AddOptions() .Configure>((vo, options) => { diff --git a/src/libraries/Microsoft.Extensions.Options/src/UnnamedOptionsManager.cs b/src/libraries/Microsoft.Extensions.Options/src/UnnamedOptionsManager.cs index 27f6d6e92ac2..e6ce20b94d18 100644 --- a/src/libraries/Microsoft.Extensions.Options/src/UnnamedOptionsManager.cs +++ b/src/libraries/Microsoft.Extensions.Options/src/UnnamedOptionsManager.cs @@ -11,7 +11,7 @@ internal sealed class UnnamedOptionsManager<[DynamicallyAccessedMembers(Options. where TOptions : class { private readonly IOptionsFactory _factory; - private volatile object? _syncObj; + private object? _syncObj; private volatile TOptions? _value; public UnnamedOptionsManager(IOptionsFactory factory) => _factory = factory; diff --git a/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/OptionsTest.cs b/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/OptionsTest.cs index bb76bb9d7fc2..52e4e1a69dce 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/OptionsTest.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/OptionsTest.cs @@ -167,6 +167,18 @@ public void PostConfiguresInRegistrationOrderAfterConfigures() Assert.Equal("_-ABC", option.Message); } + [Fact] + public void SingleValidateOnStartRegistrationTest() + { + ServiceCollection sc = new(); + sc.AddOptions("name1").Configure(o => o.Message += "1").Validate(o => o.Message.Length > 0).ValidateOnStart(); + sc.AddOptions("name2").Configure(o => o.Message += "2").Validate(o => o.Message.Length > 0).ValidateOnStart(); + sc.AddOptions("name3").Configure(o => o.Message += "3").Validate(o => o.Message.Length > 0).ValidateOnStart(); + sc.AddOptions("name4").Configure(o => o.Message += "4").Validate(o => o.Message.Length > 0).ValidateOnStart(); + + Assert.Equal(1, sc.Count(sd => sd.ServiceType == typeof(IStartupValidator))); + } + public static TheoryData Configure_GetsNullableOptionsFromConfiguration_Data { get diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs index 618c751d2810..5a3479b42c35 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs @@ -56,11 +56,11 @@ public partial struct MyOptionsValidator : IValidateOptions Assert.Empty(diagnostics); _ = Assert.Single(generatedSources); -#if NETCOREAPP +#if NET string generatedSource = File.ReadAllText(@"Baselines/EmitterWithCustomValidator.netcore.g.cs"); #else string generatedSource = File.ReadAllText(@"Baselines/EmitterWithCustomValidator.netfx.g.cs"); -#endif // NETCOREAPP +#endif // NET Assert.Equal(generatedSource.Replace("\r\n", "\n"), generatedSources[0].SourceText.ToString().Replace("\r\n", "\n")); } @@ -1715,7 +1715,7 @@ private static CSharpCompilation CreateCompilationForOptionsSource(string assemb public async Task GeneratedAttributesTest(LanguageVersion languageVersion) { -#if NETCOREAPP +#if NET string lengthAttribute = $$""" [LengthAttribute(1, 3)] public string? P0 { get; set; } @@ -1728,7 +1728,7 @@ public async Task GeneratedAttributesTest(LanguageVersion languageVersion) """; #else string lengthAttribute = ""; -#endif //NETCOREAPP +#endif //NET string source = $$""" using System; @@ -1807,7 +1807,7 @@ public sealed partial class OptionsUsingGeneratedAttributesValidator : IValidate var diags = syntaxTree.GetDiagnostics().ToArray(); Assert.Empty(diags); -#if NETCOREAPP +#if NET string generatedSource = File.ReadAllText(languageVersion == LanguageVersion.CSharp10 ? @"Baselines/GeneratedAttributesTest.netcore.lang10.g.cs" : @"Baselines/GeneratedAttributesTest.netcore.lang11.g.cs"); #else string generatedSource = File.ReadAllText(languageVersion == LanguageVersion.CSharp10 ? @"Baselines/GeneratedAttributesTest.netfx.lang10.g.cs" : @"Baselines/GeneratedAttributesTest.netfx.lang11.g.cs"); @@ -1857,11 +1857,11 @@ public partial class MyOptionsValidator : IValidateOptions Assert.Empty(diagnostics); Assert.Single(generatedSources); -#if NETCOREAPP +#if NET string generatedSource = File.ReadAllText(@"Baselines/UsingInterfaceAsPropertyTypeForLengthAttributesTests.netcore.g.cs"); #else string generatedSource = File.ReadAllText(@"Baselines/UsingInterfaceAsPropertyTypeForLengthAttributesTests.netfx.g.cs"); -#endif // NETCOREAPP +#endif // NET Assert.Equal(generatedSource.Replace("\r\n", "\n"), generatedSources[0].SourceText.ToString().Replace("\r\n", "\n")); } @@ -1907,11 +1907,11 @@ public sealed class EndPointsOptions var (diagnostics, src) = await RunGenerator(source); Assert.Empty(diagnostics); Assert.Single(src); -#if NETCOREAPP +#if NET string generatedSource = File.ReadAllText(@"Baselines/OptionsExtendingSystemClassTest.netcore.g.cs"); #else string generatedSource = File.ReadAllText(@"Baselines/OptionsExtendingSystemClassTest.netfx.g.cs"); -#endif // NETCOREAPP +#endif // NET Assert.Equal(generatedSource.Replace("\r\n", "\n"), src[0].SourceText.ToString().Replace("\r\n", "\n")); } } diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs index af91cab872c8..1f54faf77d7f 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs @@ -24,8 +24,8 @@ public async Task TestEmitter() #pragma warning disable RS1035 // To allow using the File IO APIs inside the analyzer test foreach (var file in Directory.GetFiles("TestClasses")) { -#if NETCOREAPP3_1_OR_GREATER - sources.Add("#define NETCOREAPP3_1_OR_GREATER\n" + File.ReadAllText(file)); +#if NET + sources.Add("#define NET\n" + File.ReadAllText(file)); #else sources.Add(File.ReadAllText(file)); #endif @@ -46,7 +46,7 @@ public async Task TestEmitter() Assert.Empty(d); _ = Assert.Single(r); -#if NETCOREAPP3_1_OR_GREATER +#if NET string baseline = File.ReadAllText(@"Baselines/NetCoreApp/Validators.g.cs"); #else string baseline = File.ReadAllText(@"Baselines/NetFX/Validators.g.cs"); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/OptionsValidationTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/OptionsValidationTests.cs index 4f9770ce7a17..01519b780eba 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/OptionsValidationTests.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/OptionsValidationTests.cs @@ -186,7 +186,7 @@ public void RangeAttributeModelDoubleInvalid() [Fact] public void RangeAttributeModelDateValid() { -#if NETCOREAPP3_1_OR_GREATER +#if NET // Setting non-invariant culture to check that // attribute's "ParseLimitsInInvariantCulture" property // was set up correctly in the validator: diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/Utils.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/Utils.cs index 7412374f18a5..eb6bf6614909 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/Utils.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/Utils.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETCOREAPP3_1_OR_GREATER +#if NET using System.Linq; #endif using Microsoft.Extensions.Options; @@ -15,7 +15,7 @@ public static void VerifyValidateOptionsResult(ValidateOptionsResult vr, int exp { Assert.NotNull(vr); -#if NETCOREAPP3_1_OR_GREATER +#if NET var failures = vr.Failures!.ToArray(); #else var failures = vr.FailureMessage!.Split(';'); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Models.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Models.cs index c245ebd783bd..bc76114ab629 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Models.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Models.cs @@ -76,7 +76,7 @@ public class RangeAttributeModelDouble public class RangeAttributeModelDate { -#if NETCOREAPP3_1_OR_GREATER +#if NET [Range(typeof(DateTime), "1/2/2004", "3/4/2004", ParseLimitsInInvariantCulture = true)] #else [Range(typeof(DateTime), "1/2/2004", "3/4/2004")] diff --git a/src/libraries/Microsoft.Extensions.Primitives/src/StringSegment.cs b/src/libraries/Microsoft.Extensions.Primitives/src/StringSegment.cs index c78527db921b..f91f2314439c 100644 --- a/src/libraries/Microsoft.Extensions.Primitives/src/StringSegment.cs +++ b/src/libraries/Microsoft.Extensions.Primitives/src/StringSegment.cs @@ -271,7 +271,7 @@ public bool Equals(string? text, StringComparison comparisonType) [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() { -#if NETCOREAPP +#if NET return string.GetHashCode(AsSpan()); #elif (NETSTANDARD2_0 || NETFRAMEWORK) // This GetHashCode is expensive since it allocates on every call. diff --git a/src/libraries/Microsoft.Extensions.Primitives/src/StringSegmentComparer.cs b/src/libraries/Microsoft.Extensions.Primitives/src/StringSegmentComparer.cs index 9942f7959f5b..f1c645483da8 100644 --- a/src/libraries/Microsoft.Extensions.Primitives/src/StringSegmentComparer.cs +++ b/src/libraries/Microsoft.Extensions.Primitives/src/StringSegmentComparer.cs @@ -61,7 +61,7 @@ public bool Equals(StringSegment x, StringSegment y) /// A hash code for a , suitable for use in hashing algorithms and data structures like a hash table. public int GetHashCode(StringSegment obj) { -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 return string.GetHashCode(obj.AsSpan(), Comparison); #else if (!obj.HasValue) diff --git a/src/libraries/Microsoft.Extensions.Primitives/src/StringValues.cs b/src/libraries/Microsoft.Extensions.Primitives/src/StringValues.cs index 45cfea152227..591830f3bec3 100644 --- a/src/libraries/Microsoft.Extensions.Primitives/src/StringValues.cs +++ b/src/libraries/Microsoft.Extensions.Primitives/src/StringValues.cs @@ -219,7 +219,7 @@ static string GetJoinedStringValueFromArray(string?[] values) length += value.Length; } } -#if NETCOREAPP +#if NET // Create the new string return string.Create(length, values, (span, strings) => { int offset = 0; diff --git a/src/libraries/Microsoft.VisualBasic.Core/tests/NewLateBindingTests.cs b/src/libraries/Microsoft.VisualBasic.Core/tests/NewLateBindingTests.cs index b247e1e8b6c2..956362d23830 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/tests/NewLateBindingTests.cs +++ b/src/libraries/Microsoft.VisualBasic.Core/tests/NewLateBindingTests.cs @@ -96,6 +96,7 @@ public static IEnumerable LateCall_OptionalValues_Data() [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] [ActiveIssue("https://github.com/dotnet/runtime/issues/51834", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/51834", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsAppleMobile))] [MemberData(nameof(LateCall_OptionalValues_Data))] public void LateCall_OptionalValues(string memberName, object[] arguments, Type[] typeArguments, string expectedValue) { diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs index 1fedc0ec5c6a..400d16af590b 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs @@ -66,8 +66,8 @@ public sealed partial class RegistryKey : MarshalByRefObject, IDisposable private const int MaxKeyLength = 255; private const int MaxValueLength = 16383; - private volatile SafeRegistryHandle _hkey; - private volatile string _keyName; + private SafeRegistryHandle _hkey; + private string _keyName; private readonly bool _remoteKey; private volatile StateFlags _state; private volatile RegistryKeyPermissionCheck _checkMode; diff --git a/src/libraries/NetCoreAppLibrary.props b/src/libraries/NetCoreAppLibrary.props index 49fc1048b2b1..2b0f1a0f2e51 100644 --- a/src/libraries/NetCoreAppLibrary.props +++ b/src/libraries/NetCoreAppLibrary.props @@ -77,6 +77,7 @@ System.IO.MemoryMappedFiles; System.IO.Pipes; System.IO.Pipes.AccessControl; + System.IO.Pipelines; System.IO.UnmanagedMemoryStream; System.Linq; System.Linq.Expressions; @@ -220,7 +221,6 @@ Microsoft.Extensions.Options.DataAnnotations; Microsoft.Extensions.Primitives; System.Diagnostics.EventLog; - System.IO.Pipelines; System.Security.Cryptography.Xml; System.Threading.RateLimiting; diff --git a/src/libraries/System.CodeDom/src/Microsoft/VisualBasic/VBCodeGenerator.cs b/src/libraries/System.CodeDom/src/Microsoft/VisualBasic/VBCodeGenerator.cs index e83798d5d6e2..58f468d7c8fa 100644 --- a/src/libraries/System.CodeDom/src/Microsoft/VisualBasic/VBCodeGenerator.cs +++ b/src/libraries/System.CodeDom/src/Microsoft/VisualBasic/VBCodeGenerator.cs @@ -865,7 +865,7 @@ protected override void GenerateArrayCreateExpression(CodeArrayCreateExpression string typeName = GetTypeOutput(e.CreateType); Output.Write(typeName); -#if NETCOREAPP +#if NET if (!typeName.Contains('(')) #else if (typeName.IndexOf('(') == -1) @@ -892,7 +892,7 @@ protected override void GenerateArrayCreateExpression(CodeArrayCreateExpression } else { -#if NETCOREAPP +#if NET Output.Write(typeName.AsSpan(0, index + 1)); #else Output.Write(typeName.Substring(0, index + 1)); @@ -917,7 +917,7 @@ protected override void GenerateArrayCreateExpression(CodeArrayCreateExpression } else { -#if NETCOREAPP +#if NET Output.Write(typeName.AsSpan(index + 1)); #else Output.Write(typeName.Substring(index + 1)); diff --git a/src/libraries/System.CodeDom/tests/System/CodeDom/TempFileCollectionTests.cs b/src/libraries/System.CodeDom/tests/System/CodeDom/TempFileCollectionTests.cs index 7162c9358fdd..0fce53d4f877 100644 --- a/src/libraries/System.CodeDom/tests/System/CodeDom/TempFileCollectionTests.cs +++ b/src/libraries/System.CodeDom/tests/System/CodeDom/TempFileCollectionTests.cs @@ -277,7 +277,7 @@ private static string TempDirectory() { if (s_tempDirectory == null) { -#if NETCOREAPP +#if NET string tempDirectory = Directory.CreateTempSubdirectory().FullName; #else string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); diff --git a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs index dc3c47eae3b8..2165c3344f5e 100644 --- a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs +++ b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs @@ -28,7 +28,7 @@ internal sealed class CDSCollectionETWBCLProvider : EventSource /// Defines the singleton instance for the collection ETW provider. /// The collection provider GUID is {35167F8E-49B2-4b96-AB86-435B59336B5E}. /// - public static CDSCollectionETWBCLProvider Log = new CDSCollectionETWBCLProvider(); + public static readonly CDSCollectionETWBCLProvider Log = new CDSCollectionETWBCLProvider(); /// Prevent external instantiation. All logging should go through the Log instance. private CDSCollectionETWBCLProvider() { } diff --git a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/OrderablePartitioner.cs b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/OrderablePartitioner.cs index 964cf4a9f374..675d54776ac1 100644 --- a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/OrderablePartitioner.cs +++ b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/OrderablePartitioner.cs @@ -131,7 +131,7 @@ public virtual IEnumerable> GetOrderableDynamicParti /// /// Gets whether elements in each partition are yielded in the order of increasing keys. /// - public bool KeysOrderedInEachPartition { get; private set; } + public bool KeysOrderedInEachPartition { get; } /// /// Gets whether elements in an earlier partition always come before elements in a later partition. @@ -141,7 +141,7 @@ public virtual IEnumerable> GetOrderableDynamicParti /// smaller order key than any element in partition 1, each element in partition 1 has a smaller /// order key than any element in partition 2, and so on. /// - public bool KeysOrderedAcrossPartitions { get; private set; } + public bool KeysOrderedAcrossPartitions { get; } /// /// Gets whether order keys are normalized. @@ -151,7 +151,7 @@ public virtual IEnumerable> GetOrderableDynamicParti /// [0 .. numberOfElements-1]. If the property returns false, order keys must still be distinct, but /// only their relative order is considered, not their absolute values. /// - public bool KeysNormalized { get; private set; } + public bool KeysNormalized { get; } /// /// Partitions the underlying collection into the given number of ordered partitions. diff --git a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/PartitionerStatic.cs b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/PartitionerStatic.cs index a3a52c86d1db..9c9fcc88424f 100644 --- a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/PartitionerStatic.cs +++ b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/PartitionerStatic.cs @@ -308,7 +308,7 @@ private abstract class DynamicPartitionEnumerator_Abstract(); + protected static readonly int s_defaultMaxChunkSize = GetDefaultChunkSize(); //deferred allocating in MoveNext() with initial value 0, to avoid false sharing //we also use the fact that: (_currentChunkSize==null) means MoveNext is never called on this enumerator diff --git a/src/libraries/System.Collections.Concurrent/tests/ConcurrentQueueTests.cs b/src/libraries/System.Collections.Concurrent/tests/ConcurrentQueueTests.cs index 49ab211a3059..eb0299a260eb 100644 --- a/src/libraries/System.Collections.Concurrent/tests/ConcurrentQueueTests.cs +++ b/src/libraries/System.Collections.Concurrent/tests/ConcurrentQueueTests.cs @@ -130,7 +130,7 @@ public void MultipleProducerConsumer_AllItemsTransferred(int producers, int cons }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default)); } - Task.WaitAll(tasks.ToArray()); + Task.WaitAll(tasks); Assert.Equal(producers * (itemsPerProducer * (itemsPerProducer + 1) / 2), sum); } diff --git a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs index 3c2f745f3c0c..bf180cfb33db 100644 --- a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs +++ b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs @@ -70,8 +70,11 @@ void System.IDisposable.Dispose() { } } public static partial class FrozenSet { + public static System.Collections.Frozen.FrozenSet Create(params System.ReadOnlySpan source) { throw null; } + public static System.Collections.Frozen.FrozenSet Create(System.Collections.Generic.IEqualityComparer? equalityComparer, params System.ReadOnlySpan source) { throw null; } public static System.Collections.Frozen.FrozenSet ToFrozenSet(this System.Collections.Generic.IEnumerable source, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } } + [System.Runtime.CompilerServices.CollectionBuilder(typeof(System.Collections.Frozen.FrozenSet), nameof(System.Collections.Frozen.FrozenSet.Create))] public abstract partial class FrozenSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.ISet, System.Collections.ICollection, System.Collections.IEnumerable { internal FrozenSet() { } @@ -207,7 +210,7 @@ public static partial class ImmutableArray public static System.Collections.Immutable.ImmutableArray Create(T item1, T item2, T item3, T item4) { throw null; } public static System.Collections.Immutable.ImmutableArray Create(params T[]? items) { throw null; } public static System.Collections.Immutable.ImmutableArray Create(T[] items, int start, int length) { throw null; } - public static System.Collections.Immutable.ImmutableArray Create(System.ReadOnlySpan items) { throw null; } + public static System.Collections.Immutable.ImmutableArray Create(params System.ReadOnlySpan items) { throw null; } public static System.Collections.Immutable.ImmutableArray Create(System.Span items) { throw null; } public static System.Collections.Immutable.ImmutableArray ToImmutableArray(this System.Collections.Generic.IEnumerable items) { throw null; } public static System.Collections.Immutable.ImmutableArray ToImmutableArray(this System.Collections.Immutable.ImmutableArray.Builder builder) { throw null; } @@ -244,7 +247,7 @@ public static partial class ImmutableArray public System.Collections.Immutable.ImmutableArray AddRange(TDerived[] items) where TDerived : T { throw null; } public System.Collections.Immutable.ImmutableArray AddRange(ImmutableArray items, int length) { throw null; } public System.Collections.Immutable.ImmutableArray AddRange(ImmutableArray items) where TDerived : T { throw null; } - public System.Collections.Immutable.ImmutableArray AddRange(System.ReadOnlySpan items) { throw null; } + public System.Collections.Immutable.ImmutableArray AddRange(params System.ReadOnlySpan items) { throw null; } public System.Collections.Immutable.ImmutableArray AddRange(params T[] items) { throw null; } public System.ReadOnlyMemory AsMemory() { throw null; } public System.ReadOnlySpan AsSpan() { throw null; } @@ -284,7 +287,7 @@ public void CopyTo(System.Span destination) { } public System.Collections.Immutable.ImmutableArray InsertRange(int index, System.Collections.Generic.IEnumerable items) { throw null; } public System.Collections.Immutable.ImmutableArray InsertRange(int index, System.Collections.Immutable.ImmutableArray items) { throw null; } public System.Collections.Immutable.ImmutableArray InsertRange(int index, T[] items) { throw null; } - public System.Collections.Immutable.ImmutableArray InsertRange(int index, System.ReadOnlySpan items) { throw null; } + public System.Collections.Immutable.ImmutableArray InsertRange(int index, params System.ReadOnlySpan items) { throw null; } public ref readonly T ItemRef(int index) { throw null; } public int LastIndexOf(T item) { throw null; } public int LastIndexOf(T item, int startIndex) { throw null; } @@ -362,8 +365,8 @@ public void AddRange(T[] items, int length) { } public void AddRange(System.Collections.Immutable.ImmutableArray items) where TDerived : T { } public void AddRange(System.Collections.Immutable.ImmutableArray.Builder items) where TDerived : T { } public void AddRange(TDerived[] items) where TDerived : T { } - public void AddRange(System.ReadOnlySpan items) { } - public void AddRange(System.ReadOnlySpan items) where TDerived : T { } + public void AddRange(params System.ReadOnlySpan items) { } + public void AddRange(params System.ReadOnlySpan items) where TDerived : T { } public void Clear() { } public bool Contains(T item) { throw null; } public void CopyTo(T[] array, int index) { } @@ -562,17 +565,17 @@ public static partial class ImmutableHashSet public static System.Collections.Immutable.ImmutableHashSet Create(System.Collections.Generic.IEqualityComparer? equalityComparer) { throw null; } public static System.Collections.Immutable.ImmutableHashSet Create(System.Collections.Generic.IEqualityComparer? equalityComparer, T item) { throw null; } public static System.Collections.Immutable.ImmutableHashSet Create(System.Collections.Generic.IEqualityComparer? equalityComparer, params T[] items) { throw null; } - public static System.Collections.Immutable.ImmutableHashSet Create(System.Collections.Generic.IEqualityComparer? equalityComparer, System.ReadOnlySpan items) { throw null; } + public static System.Collections.Immutable.ImmutableHashSet Create(System.Collections.Generic.IEqualityComparer? equalityComparer, params System.ReadOnlySpan items) { throw null; } public static System.Collections.Immutable.ImmutableHashSet Create(T item) { throw null; } public static System.Collections.Immutable.ImmutableHashSet Create(params T[] items) { throw null; } - public static System.Collections.Immutable.ImmutableHashSet Create(System.ReadOnlySpan items) { throw null; } + public static System.Collections.Immutable.ImmutableHashSet Create(params System.ReadOnlySpan items) { throw null; } public static System.Collections.Immutable.ImmutableHashSet ToImmutableHashSet(this System.Collections.Generic.IEnumerable source) { throw null; } public static System.Collections.Immutable.ImmutableHashSet ToImmutableHashSet(this System.Collections.Generic.IEnumerable source, System.Collections.Generic.IEqualityComparer? equalityComparer) { throw null; } public static System.Collections.Immutable.ImmutableHashSet ToImmutableHashSet(this System.Collections.Immutable.ImmutableHashSet.Builder builder) { throw null; } } [System.Runtime.CompilerServices.CollectionBuilderAttribute(typeof(System.Collections.Immutable.ImmutableHashSet), "Create")] -#if NETCOREAPP +#if NET public sealed partial class ImmutableHashSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.ISet, System.Collections.Generic.IReadOnlySet, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.Immutable.IImmutableSet #else public sealed partial class ImmutableHashSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.ISet, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.Immutable.IImmutableSet @@ -691,7 +694,7 @@ public static partial class ImmutableList public static System.Collections.Immutable.ImmutableList Create() { throw null; } public static System.Collections.Immutable.ImmutableList Create(T item) { throw null; } public static System.Collections.Immutable.ImmutableList Create(params T[] items) { throw null; } - public static System.Collections.Immutable.ImmutableList Create(System.ReadOnlySpan items) { throw null; } + public static System.Collections.Immutable.ImmutableList Create(params System.ReadOnlySpan items) { throw null; } public static int IndexOf(this System.Collections.Immutable.IImmutableList list, T item) { throw null; } public static int IndexOf(this System.Collections.Immutable.IImmutableList list, T item, System.Collections.Generic.IEqualityComparer? equalityComparer) { throw null; } public static int IndexOf(this System.Collections.Immutable.IImmutableList list, T item, int startIndex) { throw null; } @@ -887,7 +890,7 @@ public static partial class ImmutableQueue public static System.Collections.Immutable.ImmutableQueue Create() { throw null; } public static System.Collections.Immutable.ImmutableQueue Create(T item) { throw null; } public static System.Collections.Immutable.ImmutableQueue Create(params T[] items) { throw null; } - public static System.Collections.Immutable.ImmutableQueue Create(System.ReadOnlySpan items) { throw null; } + public static System.Collections.Immutable.ImmutableQueue Create(params System.ReadOnlySpan items) { throw null; } public static System.Collections.Immutable.IImmutableQueue Dequeue(this System.Collections.Immutable.IImmutableQueue queue, out T value) { throw null; } } [System.Runtime.CompilerServices.CollectionBuilderAttribute(typeof(System.Collections.Immutable.ImmutableQueue), "Create")] @@ -1063,17 +1066,17 @@ public static partial class ImmutableSortedSet public static System.Collections.Immutable.ImmutableSortedSet Create(System.Collections.Generic.IComparer? comparer) { throw null; } public static System.Collections.Immutable.ImmutableSortedSet Create(System.Collections.Generic.IComparer? comparer, T item) { throw null; } public static System.Collections.Immutable.ImmutableSortedSet Create(System.Collections.Generic.IComparer? comparer, params T[] items) { throw null; } - public static System.Collections.Immutable.ImmutableSortedSet Create(System.Collections.Generic.IComparer? comparer, System.ReadOnlySpan items) { throw null; } + public static System.Collections.Immutable.ImmutableSortedSet Create(System.Collections.Generic.IComparer? comparer, params System.ReadOnlySpan items) { throw null; } public static System.Collections.Immutable.ImmutableSortedSet Create(T item) { throw null; } public static System.Collections.Immutable.ImmutableSortedSet Create(params T[] items) { throw null; } - public static System.Collections.Immutable.ImmutableSortedSet Create(System.ReadOnlySpan items) { throw null; } + public static System.Collections.Immutable.ImmutableSortedSet Create(params System.ReadOnlySpan items) { throw null; } public static System.Collections.Immutable.ImmutableSortedSet ToImmutableSortedSet(this System.Collections.Generic.IEnumerable source) { throw null; } public static System.Collections.Immutable.ImmutableSortedSet ToImmutableSortedSet(this System.Collections.Generic.IEnumerable source, System.Collections.Generic.IComparer? comparer) { throw null; } public static System.Collections.Immutable.ImmutableSortedSet ToImmutableSortedSet(this System.Collections.Immutable.ImmutableSortedSet.Builder builder) { throw null; } } [System.Runtime.CompilerServices.CollectionBuilderAttribute(typeof(System.Collections.Immutable.ImmutableSortedSet), "Create")] -#if NETCOREAPP +#if NET public sealed partial class ImmutableSortedSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.ISet, System.Collections.Generic.IReadOnlySet, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.Immutable.IImmutableSet #else public sealed partial class ImmutableSortedSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.ISet, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.Immutable.IImmutableSet @@ -1198,7 +1201,7 @@ public static partial class ImmutableStack public static System.Collections.Immutable.ImmutableStack Create() { throw null; } public static System.Collections.Immutable.ImmutableStack Create(T item) { throw null; } public static System.Collections.Immutable.ImmutableStack Create(params T[] items) { throw null; } - public static System.Collections.Immutable.ImmutableStack Create(System.ReadOnlySpan items) { throw null; } + public static System.Collections.Immutable.ImmutableStack Create(params System.ReadOnlySpan items) { throw null; } public static System.Collections.Immutable.IImmutableStack Pop(this System.Collections.Immutable.IImmutableStack stack, out T value) { throw null; } } [System.Runtime.CompilerServices.CollectionBuilderAttribute(typeof(System.Collections.Immutable.ImmutableStack), "Create")] diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Constants.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Constants.cs index 5371a0354aea..ed797f8fae7b 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Constants.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Constants.cs @@ -61,19 +61,13 @@ public static bool IsKnownComparable() => typeof(T) == typeof(DateTime) || typeof(T) == typeof(DateTimeOffset) || typeof(T) == typeof(Guid) || -#if NETCOREAPP3_0_OR_GREATER +#if NET typeof(T) == typeof(Rune) || -#endif -#if NET5_0_OR_GREATER typeof(T) == typeof(Half) || typeof(T) == typeof(nint) || typeof(T) == typeof(nuint) || -#endif -#if NET6_0_OR_GREATER typeof(T) == typeof(DateOnly) || typeof(T) == typeof(TimeOnly) || -#endif -#if NET7_0_OR_GREATER typeof(T) == typeof(Int128) || typeof(T) == typeof(UInt128) || #endif diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs index afb478514739..2bda7b2c76e7 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs @@ -159,7 +159,7 @@ private static int CalcNumBuckets(ReadOnlySpan hashCodes, bool hashCodesAre if (!hashCodesAreUnique) { codes = -#if NETCOREAPP2_0_OR_GREATER +#if NET new HashSet(hashCodes.Length); #else new HashSet(); diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenSet.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenSet.cs index 50bbdeb18aad..2c48fc8d76e4 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenSet.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenSet.cs @@ -5,6 +5,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace System.Collections.Frozen @@ -14,6 +15,40 @@ namespace System.Collections.Frozen /// public static class FrozenSet { + /// Creates a with the specified values. + /// The values to use to populate the set. + /// The type of the values in the set. + /// A frozen set. + public static FrozenSet Create(params ReadOnlySpan source) => Create(null, source); + + /// Creates a with the specified values. + /// The values to use to populate the set. + /// The comparer implementation to use to compare values for equality. If null, is used. + /// The type of the values in the set. + /// A frozen set. + public static FrozenSet Create(IEqualityComparer? equalityComparer, params ReadOnlySpan source) + { + if (source.Length == 0) + { + return equalityComparer is null || ReferenceEquals(equalityComparer, FrozenSet.Empty.Comparer) ? + FrozenSet.Empty : + new EmptyFrozenSet(equalityComparer); + } + + HashSet set = +#if NET + new(source.Length, equalityComparer); // we assume there are few-to-no duplicates when using this API +#else + new(equalityComparer); +#endif + foreach (T item in source) + { + set.Add(item); + } + + return ToFrozenSet(set, equalityComparer); + } + /// Creates a with the specified values. /// The values to use to populate the set. /// The comparer implementation to use to compare values for equality. If null, is used. @@ -199,10 +234,11 @@ private static FrozenSet CreateFromSet(HashSet source) /// the remainder of the life of the application. should only be initialized /// with trusted elements, as the details of the elements impacts construction time. /// + [CollectionBuilder(typeof(FrozenSet), nameof(FrozenSet.Create))] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] [DebuggerDisplay("Count = {Count}")] public abstract class FrozenSet : ISet, -#if NET5_0_OR_GREATER +#if NET IReadOnlySet, #endif IReadOnlyCollection, ICollection diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/Hashing.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/Hashing.cs index 4db4d2f03d9e..8e9a7db1dd31 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/Hashing.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/Hashing.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; +using System.Diagnostics; using System.Numerics; using System.Runtime.InteropServices; @@ -76,6 +77,8 @@ public static unsafe int GetHashCodeOrdinal(ReadOnlySpan s) // useful if the string only contains ASCII characters public static unsafe int GetHashCodeOrdinalIgnoreCaseAscii(ReadOnlySpan s) { + Debug.Assert(KeyAnalyzer.IsAllAscii(s)); + // We "normalize to lowercase" every char by ORing with 0x20. This casts // a very wide net because it will change, e.g., '^' to '~'. But that should // be ok because we expect this to be very rare in practice. @@ -138,6 +141,9 @@ public static unsafe int GetHashCodeOrdinalIgnoreCaseAscii(ReadOnlySpan s) public static unsafe int GetHashCodeOrdinalIgnoreCase(ReadOnlySpan s) { +#if NET + return string.GetHashCode(s, StringComparison.OrdinalIgnoreCase); +#else int length = s.Length; char[]? rentedArray = null; @@ -145,7 +151,7 @@ public static unsafe int GetHashCodeOrdinalIgnoreCase(ReadOnlySpan s) stackalloc char[256] : (rentedArray = ArrayPool.Shared.Rent(length)); - length = s.ToUpperInvariant(scratch); // NOTE: this really should be the (non-existent) ToUpperOrdinal + length = s.ToUpperInvariant(scratch); // NOTE: this both allocates and really should be the (non-existent) ToUpperOrdinal int hash = GetHashCodeOrdinal(scratch.Slice(0, length)); if (rentedArray is not null) @@ -154,6 +160,7 @@ public static unsafe int GetHashCodeOrdinalIgnoreCase(ReadOnlySpan s) } return hash; +#endif } } } diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs index 9f6094edb977..0793b3d12f73 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs @@ -32,31 +32,40 @@ public static AnalysisResults Analyze( ReadOnlySpan uniqueStrings, bool ignoreCase, int minLength, int maxLength) { Debug.Assert(!uniqueStrings.IsEmpty); + bool allUniqueStringsAreConfirmedAscii = ignoreCase && AreAllAscii(uniqueStrings); // Try to pick a substring comparer. If we can't find a good substring comparer, fallback to a full string comparer. AnalysisResults results; - if (minLength == 0 || !TryUseSubstring(uniqueStrings, ignoreCase, minLength, maxLength, out results)) + if (minLength == 0 || !TryUseSubstring(uniqueStrings, allUniqueStringsAreConfirmedAscii, ignoreCase, minLength, maxLength, out results)) { - results = CreateAnalysisResults(uniqueStrings, ignoreCase, minLength, maxLength, 0, 0, static (s, _, _) => s.AsSpan()); + results = CreateAnalysisResults(uniqueStrings, allUniqueStringsAreConfirmedAscii, ignoreCase, minLength, maxLength, 0, 0, static (s, _, _) => s.AsSpan()); } return results; } /// Try to find the minimal unique substring index/length to use for comparisons. - private static bool TryUseSubstring(ReadOnlySpan uniqueStrings, bool ignoreCase, int minLength, int maxLength, out AnalysisResults results) + private static bool TryUseSubstring(ReadOnlySpan uniqueStrings, bool allUniqueStringsAreConfirmedAscii, bool ignoreCase, int minLength, int maxLength, out AnalysisResults results) { const int MaxSubstringLengthLimit = 8; // arbitrary small-ish limit... it's not worth the increase in algorithmic complexity to analyze longer substrings - int uniqueStringsLength = uniqueStrings.Length; // Sufficient uniqueness factor of 95% is good enough. // Instead of ensuring that 95% of data is good, we stop when we know that at least 5% is bad. - int acceptableNonUniqueCount = uniqueStringsLength / 20; + int acceptableNonUniqueCount = uniqueStrings.Length / 20; + + // If we're case-sensitive, we can just use a case-sensitive substring comparer, which is cheap. + // For case-insensitive / ignoreCase, we don't know which portion of the input strings we're going to care about. + // However, if all of the strings are entirely ASCII, we know that no portion of any will be non-ASCII and thus can + // use a comparer that only knows how to do ASCII-based ordinal casing, which is cheaper than full Unicode casing, + // in particular for GetHashCode. + SubstringComparer comparer = + !ignoreCase ? new JustifiedSubstringComparer() : + allUniqueStringsAreConfirmedAscii ? new JustifiedCaseInsensitiveAsciiSubstringComparer() : + new JustifiedCaseInsensitiveSubstringComparer(); - SubstringComparer comparer = ignoreCase ? new JustifiedCaseInsensitiveSubstringComparer() : new JustifiedSubstringComparer(); HashSet set = new HashSet( -#if NET6_0_OR_GREATER - uniqueStringsLength, +#if NET + uniqueStrings.Length, #endif comparer); @@ -77,7 +86,7 @@ private static bool TryUseSubstring(ReadOnlySpan uniqueStrings, bool ign if (HasSufficientUniquenessFactor(set, uniqueStrings, acceptableNonUniqueCount)) { results = CreateAnalysisResults( - uniqueStrings, ignoreCase, minLength, maxLength, index, count, + uniqueStrings, allUniqueStringsAreConfirmedAscii, ignoreCase, minLength, maxLength, index, count, static (string s, int index, int count) => s.AsSpan(index, count)); return true; } @@ -101,7 +110,7 @@ private static bool TryUseSubstring(ReadOnlySpan uniqueStrings, bool ign if (HasSufficientUniquenessFactor(set, uniqueStrings, acceptableNonUniqueCount)) { results = CreateAnalysisResults( - uniqueStrings, ignoreCase, minLength, maxLength, comparer.Index, count, + uniqueStrings, allUniqueStringsAreConfirmedAscii, ignoreCase, minLength, maxLength, comparer.Index, count, static (string s, int index, int count) => s.AsSpan(s.Length + index, count)); return true; } @@ -115,7 +124,7 @@ private static bool TryUseSubstring(ReadOnlySpan uniqueStrings, bool ign } private static AnalysisResults CreateAnalysisResults( - ReadOnlySpan uniqueStrings, bool ignoreCase, int minLength, int maxLength, int index, int count, GetSpan getHashString) + ReadOnlySpan uniqueStrings, bool allUniqueStringsAreConfirmedAscii, bool ignoreCase, int minLength, int maxLength, int index, int count, GetSpan getHashString) { // Start off by assuming all strings are ASCII bool allAsciiIfIgnoreCase = true; @@ -134,10 +143,9 @@ private static AnalysisResults CreateAnalysisResults( foreach (string uniqueString in uniqueStrings) { // Get a span representing the slice of the uniqueString which will be hashed. - ReadOnlySpan hashString = getHashString(uniqueString, index, count); - // If the slice isn't ASCII, bail out to return the results. - if (!IsAllAscii(hashString)) + if (!allUniqueStringsAreConfirmedAscii && + !IsAllAscii(getHashString(uniqueString, index, count))) { allAsciiIfIgnoreCase = false; canSwitchIgnoreCaseHashToCaseSensitive = false; @@ -153,13 +161,14 @@ private static AnalysisResults CreateAnalysisResults( // and as we have just checked that IsAllAscii(hashString) is true // then we know IsAllAscii(uniqueString) must be true, // so we can skip the check. - if (count > 0 && !IsAllAscii(uniqueString.AsSpan())) - { - canSwitchIgnoreCaseHashToCaseSensitive = false; - } - else if (ContainsAnyAsciiLetters(uniqueString.AsSpan())) + if ((count > 0 && !allUniqueStringsAreConfirmedAscii && !IsAllAscii(uniqueString.AsSpan())) || + ContainsAnyAsciiLetters(uniqueString.AsSpan())) { canSwitchIgnoreCaseHashToCaseSensitive = false; + if (allUniqueStringsAreConfirmedAscii) + { + break; + } } } } @@ -177,6 +186,19 @@ private static AnalysisResults CreateAnalysisResults( private delegate ReadOnlySpan GetSpan(string s, int index, int count); + private static bool AreAllAscii(ReadOnlySpan strings) + { + foreach (string s in strings) + { + if (!IsAllAscii(s.AsSpan())) + { + return false; + } + } + + return true; + } + internal static unsafe bool IsAllAscii(ReadOnlySpan s) { #if NET8_0_OR_GREATER @@ -296,5 +318,11 @@ private sealed class JustifiedCaseInsensitiveSubstringComparer : SubstringCompar public override bool Equals(string? x, string? y) => x.AsSpan(IsLeft ? Index : (x!.Length + Index), Count).Equals(y.AsSpan(IsLeft ? Index : (y!.Length + Index), Count), StringComparison.OrdinalIgnoreCase); public override int GetHashCode(string s) => Hashing.GetHashCodeOrdinalIgnoreCase(s.AsSpan(IsLeft ? Index : (s.Length + Index), Count)); } + + private sealed class JustifiedCaseInsensitiveAsciiSubstringComparer : SubstringComparer + { + public override bool Equals(string? x, string? y) => x.AsSpan(IsLeft ? Index : (x!.Length + Index), Count).Equals(y.AsSpan(IsLeft ? Index : (y!.Length + Index), Count), StringComparison.OrdinalIgnoreCase); + public override int GetHashCode(string s) => Hashing.GetHashCodeOrdinalIgnoreCaseAscii(s.AsSpan(IsLeft ? Index : (s.Length + Index), Count)); + } } } diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/LengthBuckets.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/LengthBuckets.cs index 97659c547936..626b21a8bf12 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/LengthBuckets.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/LengthBuckets.cs @@ -28,7 +28,7 @@ internal static class LengthBuckets } int arraySize = spread * MaxPerLength; -#if NET6_0_OR_GREATER +#if NET if (arraySize > Array.MaxLength) #else if (arraySize > 0X7FFFFFC7) @@ -87,7 +87,7 @@ internal static class LengthBuckets return null; } -#if NET6_0_OR_GREATER +#if NET // We don't need an array with every value initialized to zero if we are just about to overwrite every value anyway. int[] copy = GC.AllocateUninitializedArray(arraySize); Array.Copy(buckets, copy, arraySize); diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/AllocFreeConcurrentStack.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/AllocFreeConcurrentStack.cs index ad22b0bbab69..1f1b1be4c5bf 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/AllocFreeConcurrentStack.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/AllocFreeConcurrentStack.cs @@ -10,7 +10,7 @@ internal static class AllocFreeConcurrentStack { private const int MaxSize = 35; -#if NETCOREAPP +#if NET [ThreadStatic] private static Stack>? t_stack; #else @@ -20,7 +20,7 @@ internal static class AllocFreeConcurrentStack public static void TryAdd(T item) { Stack> localStack = -#if NETCOREAPP +#if NET t_stack ??= new Stack>(MaxSize); #else ThreadLocalStack; @@ -36,7 +36,7 @@ public static void TryAdd(T item) public static bool TryTake([MaybeNullWhen(false)] out T item) { -#if NETCOREAPP +#if NET Stack>? localStack = t_stack; // cache in a local to avoid unnecessary TLS hits on repeated accesses #else Stack> localStack = ThreadLocalStack; @@ -51,7 +51,7 @@ public static bool TryTake([MaybeNullWhen(false)] out T item) return false; } -#if !NETCOREAPP +#if !NET private static Stack> ThreadLocalStack { get @@ -73,7 +73,7 @@ private static Stack> ThreadLocalStack #endif } -#if !NETCOREAPP +#if !NET internal static class AllocFreeConcurrentStack { // Workaround for https://github.com/dotnet/runtime/issues/4731. diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray.cs index f2743d3f16f8..8f244bc8305b 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray.cs @@ -87,7 +87,7 @@ public static ImmutableArray Create(T item1, T item2, T item3, T item4) /// The type of element stored in the array. /// The elements to store in the array. /// An immutable array containing the specified items. - public static ImmutableArray Create(ReadOnlySpan items) + public static ImmutableArray Create(params ReadOnlySpan items) { if (items.IsEmpty) { diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs index 8af78d72a063..891c783b5d66 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs @@ -430,7 +430,7 @@ public void AddRange(ImmutableArray items, int length) /// Adds the specified items to the end of the array. /// /// The items to add at the end of the array. - public void AddRange(ReadOnlySpan items) + public void AddRange(params ReadOnlySpan items) { int offset = this.Count; this.Count += items.Length; @@ -443,7 +443,7 @@ public void AddRange(ReadOnlySpan items) /// /// The type that derives from the type of item already in the array. /// The items to add at the end of the array. - public void AddRange(ReadOnlySpan items) where TDerived : T + public void AddRange(params ReadOnlySpan items) where TDerived : T { int offset = this.Count; this.Count += items.Length; @@ -589,7 +589,7 @@ public void RemoveRange(int index, int length) if (index + length < this._count) { -#if NET6_0_OR_GREATER +#if NET if (RuntimeHelpers.IsReferenceOrContainsReferences()) { Array.Clear(_elements, index, length); // Clear the elements so that the gc can reclaim the references. @@ -919,7 +919,7 @@ public int LastIndexOf(T item, int startIndex, int count, IEqualityComparer? /// public void Reverse() { -#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER +#if NET || NETSTANDARD2_1_OR_GREATER Array.Reverse(_elements, 0, _count); #else // The non-generic Array.Reverse is not used because it does not perform @@ -963,7 +963,7 @@ public void Sort(Comparison comparison) if (Count > 1) { -#if NET6_0_OR_GREATER +#if NET // MemoryExtensions.Sort is not available in .NET Framework / Standard 2.0. // But the overload with a Comparison argument doesn't allocate. _elements.AsSpan(0, _count).Sort(comparison); diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.cs index 2d203d015b82..5d146329b185 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.cs @@ -880,7 +880,7 @@ public IEnumerable OfType() /// /// The values to add. /// A new list with the elements added. - public ImmutableArray AddRange(ReadOnlySpan items) + public ImmutableArray AddRange(params ReadOnlySpan items) { ImmutableArray self = this; return self.InsertRange(self.Length, items); @@ -949,7 +949,7 @@ public ImmutableArray InsertRange(int index, T[] items) /// The index at which to insert the value. /// The elements to insert. /// The new immutable collection. - public ImmutableArray InsertRange(int index, ReadOnlySpan items) + public ImmutableArray InsertRange(int index, params ReadOnlySpan items) { ImmutableArray self = this; self.ThrowNullRefIfNotInitialized(); diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableExtensions.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableExtensions.cs index 823c5e04cd27..8d941eb0bcec 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableExtensions.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableExtensions.cs @@ -16,7 +16,7 @@ internal static partial class ImmutableExtensions { internal static bool IsValueType() { -#if NETCOREAPP +#if NET return typeof(T).IsValueType; #else if (default(T) != null) diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet.cs index 9630bb33b5c0..8cb871e5e01d 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet.cs @@ -98,7 +98,7 @@ public static ImmutableHashSet Create(params T[] items) /// The type of items stored by the collection. /// The items to prepopulate. /// The new immutable collection. - public static ImmutableHashSet Create(ReadOnlySpan items) + public static ImmutableHashSet Create(params ReadOnlySpan items) { return ImmutableHashSet.Empty.Union(items); } @@ -124,7 +124,7 @@ public static ImmutableHashSet Create(IEqualityComparer? equalityCompar /// The equality comparer. /// The items to prepopulate. /// The new immutable collection. - public static ImmutableHashSet Create(IEqualityComparer? equalityComparer, ReadOnlySpan items) + public static ImmutableHashSet Create(IEqualityComparer? equalityComparer, params ReadOnlySpan items) { return ImmutableHashSet.Empty.WithComparer(equalityComparer).Union(items); } diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs index b2e073484bb4..2ff4b68d19af 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs @@ -15,7 +15,7 @@ namespace System.Collections.Immutable [CollectionBuilder(typeof(ImmutableHashSet), nameof(ImmutableHashSet.Create))] [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] -#if NETCOREAPP +#if NET public sealed partial class ImmutableHashSet : IImmutableSet, IHashKeyCollection, IReadOnlyCollection, ICollection, ISet, IReadOnlySet, ICollection, IStrongEnumerable.Enumerator> #else public sealed partial class ImmutableHashSet : IImmutableSet, IHashKeyCollection, IReadOnlyCollection, ICollection, ISet, ICollection, IStrongEnumerable.Enumerator> diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableList.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableList.cs index f3004e3fd019..43c0b23bc954 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableList.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableList.cs @@ -52,7 +52,7 @@ public static ImmutableList Create(params T[] items) /// The type of items stored by the collection. /// A span that contains the items to prepopulate the list with. /// A new immutable list that contains the specified items. - public static ImmutableList Create(ReadOnlySpan items) => ImmutableList.Empty.AddRange(items); + public static ImmutableList Create(params ReadOnlySpan items) => ImmutableList.Empty.AddRange(items); /// /// Creates a new immutable list builder. diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableQueue.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableQueue.cs index 122bae100534..051d79aa6e64 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableQueue.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableQueue.cs @@ -83,7 +83,7 @@ public static ImmutableQueue Create(params T[] items) /// The type of items in the immutable queue. /// A span that contains the items to prepopulate the queue with. /// A new immutable queue that contains the specified items. - public static ImmutableQueue Create(ReadOnlySpan items) + public static ImmutableQueue Create(params ReadOnlySpan items) { if (items.IsEmpty) { diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet.cs index 567997ed0472..c2eb36418070 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet.cs @@ -97,7 +97,7 @@ public static ImmutableSortedSet Create(params T[] items) /// The type of items in the immutable set. /// A span that contains the items to prepopulate the set with. /// A new immutable set that contains the specified items. - public static ImmutableSortedSet Create(ReadOnlySpan items) + public static ImmutableSortedSet Create(params ReadOnlySpan items) { return ImmutableSortedSet.Empty.Union(items); } @@ -123,7 +123,7 @@ public static ImmutableSortedSet Create(IComparer? comparer, params T[] /// The comparer. /// The items to prepopulate. /// The new immutable collection. - public static ImmutableSortedSet Create(IComparer? comparer, ReadOnlySpan items) + public static ImmutableSortedSet Create(IComparer? comparer, params ReadOnlySpan items) { return ImmutableSortedSet.Empty.WithComparer(comparer).Union(items); } diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet_1.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet_1.cs index 2befd4a7c130..ee1d369c6ea1 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet_1.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet_1.cs @@ -20,7 +20,7 @@ namespace System.Collections.Immutable [CollectionBuilder(typeof(ImmutableSortedSet), nameof(ImmutableSortedSet.Create))] [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] -#if NETCOREAPP +#if NET public sealed partial class ImmutableSortedSet : IImmutableSet, ISortKeyCollection, IReadOnlySet, IReadOnlyList, IList, ISet, IList, IStrongEnumerable.Enumerator> #else public sealed partial class ImmutableSortedSet : IImmutableSet, ISortKeyCollection, IReadOnlyList, IList, ISet, IList, IStrongEnumerable.Enumerator> diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableStack.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableStack.cs index 4e11bb768880..12480554339e 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableStack.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableStack.cs @@ -70,7 +70,7 @@ public static ImmutableStack Create(params T[] items) /// The type of items in the immutable stack. /// A span that contains the items to prepopulate the stack with. /// A new immutable stack that contains the specified items. - public static ImmutableStack Create(ReadOnlySpan items) + public static ImmutableStack Create(params ReadOnlySpan items) { ImmutableStack stack = ImmutableStack.Empty; foreach (T item in items) diff --git a/src/libraries/System.Collections.Immutable/src/System/Polyfills.cs b/src/libraries/System.Collections.Immutable/src/System/Polyfills.cs index 77f304f46fdc..eeb82f0960cc 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Polyfills.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Polyfills.cs @@ -6,7 +6,7 @@ namespace System.Collections.Generic { -#if !NETCOREAPP2_0_OR_GREATER +#if !NET internal static class KeyValuePairExtensions { [EditorBrowsable(EditorBrowsableState.Never)] @@ -18,7 +18,7 @@ public static void Deconstruct(this KeyValuePair sou } #endif -#if !NET5_0_OR_GREATER +#if !NET internal interface IReadOnlySet : IReadOnlyCollection { bool Contains(T item); @@ -34,7 +34,7 @@ internal interface IReadOnlySet : IReadOnlyCollection namespace System.Numerics { -#if !NETCOREAPP3_0_OR_GREATER +#if !NET internal static class BitOperations { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -45,7 +45,7 @@ internal static class BitOperations namespace System.Runtime.CompilerServices { -#if !NETCOREAPP3_0_OR_GREATER +#if !NET [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] internal sealed class CallerArgumentExpressionAttribute : Attribute { diff --git a/src/libraries/System.Collections.Immutable/tests/Frozen/FrozenDictionaryTests.cs b/src/libraries/System.Collections.Immutable/tests/Frozen/FrozenDictionaryTests.cs index 13e695ef0a79..86a6f3539278 100644 --- a/src/libraries/System.Collections.Immutable/tests/Frozen/FrozenDictionaryTests.cs +++ b/src/libraries/System.Collections.Immutable/tests/Frozen/FrozenDictionaryTests.cs @@ -361,6 +361,35 @@ protected override string CreateTKey(int seed) } protected override string CreateTValue(int seed) => CreateTKey(seed); + + [Theory] + [InlineData(0)] + [InlineData(25)] + [InlineData(50)] + [InlineData(75)] + [InlineData(100)] + public void ContainsKey_WithNonAscii(int percentageWithNonAscii) + { + Random rand = new(42); + + Dictionary expected = new(GetKeyIEqualityComparer()); + for (int i = 0; i < 100; i++) + { + int stringLength = rand.Next(4, 30); + byte[] bytes = new byte[stringLength]; + rand.NextBytes(bytes); + string value = Convert.ToBase64String(bytes); + if (rand.Next(100) < percentageWithNonAscii) + { + value = value.Replace(value[rand.Next(value.Length)], '\u05D0'); + } + expected.Add(value, value); + } + + FrozenDictionary actual = expected.ToFrozenDictionary(GetKeyIEqualityComparer()); + + Assert.All(expected, kvp => actual.ContainsKey(kvp.Key)); + } } public class FrozenDictionary_Generic_Tests_string_string_Default : FrozenDictionary_Generic_Tests_string_string diff --git a/src/libraries/System.Collections.Immutable/tests/Frozen/FrozenSetTests.cs b/src/libraries/System.Collections.Immutable/tests/Frozen/FrozenSetTests.cs index 8465f66c4c37..989292fe7b4f 100644 --- a/src/libraries/System.Collections.Immutable/tests/Frozen/FrozenSetTests.cs +++ b/src/libraries/System.Collections.Immutable/tests/Frozen/FrozenSetTests.cs @@ -6,7 +6,6 @@ using System.Globalization; using System.Linq; using Xunit; -using System.Numerics; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; @@ -81,6 +80,16 @@ public void EmptySource_ProducedFrozenSetEmpty() Assert.NotSame(FrozenSet.Empty, source.ToFrozenSet(NonDefaultEqualityComparer.Instance)); } + + Assert.Same(FrozenSet.Empty, FrozenSet.Create(ReadOnlySpan.Empty)); + Assert.Same(FrozenSet.Empty, FrozenSet.Create()); + + foreach (IEqualityComparer comparer in new IEqualityComparer[] { null, EqualityComparer.Default }) + { + Assert.Same(FrozenSet.Empty, FrozenSet.Create(comparer)); + } + + Assert.NotSame(FrozenSet.Empty, FrozenSet.Create(NonDefaultEqualityComparer.Instance)); } [Fact] @@ -298,7 +307,7 @@ private sealed class InvertingComparer : IEqualityComparer private sealed class EmptySet : ISet -#if NET5_0_OR_GREATER +#if NET , IReadOnlySet #endif { @@ -338,6 +347,35 @@ protected override string CreateT(int seed) rand.NextBytes(bytes1); return Convert.ToBase64String(bytes1); } + + [Theory] + [InlineData(0)] + [InlineData(25)] + [InlineData(50)] + [InlineData(75)] + [InlineData(100)] + public void Contains_WithNonAscii(int percentageWithNonAscii) + { + Random rand = new(42); + + HashSet expected = new(GetIEqualityComparer()); + for (int i = 0; i < 100; i++) + { + int stringLength = rand.Next(4, 30); + byte[] bytes = new byte[stringLength]; + rand.NextBytes(bytes); + string value = Convert.ToBase64String(bytes); + if (rand.Next(100) < percentageWithNonAscii) + { + value = value.Replace(value[rand.Next(value.Length)], '\u05D0'); + } + expected.Add(value); + } + + FrozenSet actual = expected.ToFrozenSet(GetIEqualityComparer()); + + Assert.All(expected, s => actual.Contains(s)); + } } public class FrozenSet_Generic_Tests_string_Default : FrozenSet_Generic_Tests_string @@ -359,7 +397,7 @@ public class FrozenSet_Generic_Tests_string_OrdinalIgnoreCase : FrozenSet_Generi [Fact] public void TryGetValue_FindsExpectedResult() { - FrozenSet frozen = new[] { "abc" }.ToFrozenSet(StringComparer.OrdinalIgnoreCase); + FrozenSet frozen = FrozenSet.Create(StringComparer.OrdinalIgnoreCase, "abc"); Assert.False(frozen.TryGetValue("ab", out string actualValue)); Assert.Null(actualValue); @@ -470,7 +508,7 @@ public void Sparse_LookupItems_AlltemsFoundAsExpected() foreach (int skip in new[] { 2, 3, 5 }) { var original = new HashSet(Enumerable.Range(-3, size).Where(i => i % skip == 0)); - FrozenSet frozen = original.ToFrozenSet(); + FrozenSet frozen = [.. original]; for (int i = -10; i <= size + 66; i++) { @@ -511,7 +549,7 @@ public void ClosedRange_Lookup_AllItemsFoundAsExpected() original.Add(i); } - FrozenSet frozen = original.ToFrozenSet(); + FrozenSet frozen = [.. original]; min = start > long.MinValue ? start - 10 : start; max = start + size - 1 < long.MaxValue ? start + size + 9 : start + size - 1; diff --git a/src/libraries/System.Collections.Immutable/tests/ImmutableHashSetTest.cs b/src/libraries/System.Collections.Immutable/tests/ImmutableHashSetTest.cs index 0aab9405d559..d6a01aee099a 100644 --- a/src/libraries/System.Collections.Immutable/tests/ImmutableHashSetTest.cs +++ b/src/libraries/System.Collections.Immutable/tests/ImmutableHashSetTest.cs @@ -118,7 +118,7 @@ public void Create() Assert.Equal(1, set.Count); Assert.Same(comparer, set.KeyComparer); - set = ImmutableHashSet.Create("a", "b"); + set = ImmutableHashSet.Create(new[] { "a", "b" }); Assert.Equal(2, set.Count); Assert.Same(EqualityComparer.Default, set.KeyComparer); @@ -126,7 +126,7 @@ public void Create() Assert.Equal(2, set.Count); Assert.Same(EqualityComparer.Default, set.KeyComparer); - set = ImmutableHashSet.Create(comparer, "a", "b"); + set = ImmutableHashSet.Create(comparer, new[] { "a", "b" }); Assert.Equal(2, set.Count); Assert.Same(comparer, set.KeyComparer); diff --git a/src/libraries/System.Collections.Immutable/tests/ImmutableListTest.cs b/src/libraries/System.Collections.Immutable/tests/ImmutableListTest.cs index ec569e776994..e522f4cff834 100644 --- a/src/libraries/System.Collections.Immutable/tests/ImmutableListTest.cs +++ b/src/libraries/System.Collections.Immutable/tests/ImmutableListTest.cs @@ -584,7 +584,7 @@ public void Create() list = ImmutableList.Create("a"); Assert.Equal(1, list.Count); - list = ImmutableList.Create("a", "b"); + list = ImmutableList.Create(new[] { "a", "b" }); Assert.Equal(2, list.Count); list = ImmutableList.Create((ReadOnlySpan)new[] { "a", "b" }); @@ -793,7 +793,7 @@ public static void TestDebuggerAttributes_Null() Assert.IsType(tie.InnerException); } -#if NETCOREAPP +#if NET [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] public void UsableWithCollectibleAssemblies() { diff --git a/src/libraries/System.Collections.Immutable/tests/ImmutableQueueTest.cs b/src/libraries/System.Collections.Immutable/tests/ImmutableQueueTest.cs index c03621929a59..4aef1b5577a3 100644 --- a/src/libraries/System.Collections.Immutable/tests/ImmutableQueueTest.cs +++ b/src/libraries/System.Collections.Immutable/tests/ImmutableQueueTest.cs @@ -213,7 +213,7 @@ public void Create() Assert.False(queue.IsEmpty); Assert.Equal(new[] { 1 }, queue); - queue = ImmutableQueue.Create(1, 2); + queue = ImmutableQueue.Create(new int[] { 1, 2 }); Assert.False(queue.IsEmpty); Assert.Equal(new[] { 1, 2 }, queue); diff --git a/src/libraries/System.Collections.Immutable/tests/ImmutableSortedSetTest.cs b/src/libraries/System.Collections.Immutable/tests/ImmutableSortedSetTest.cs index eecff21ffb34..f16d59dd63ae 100644 --- a/src/libraries/System.Collections.Immutable/tests/ImmutableSortedSetTest.cs +++ b/src/libraries/System.Collections.Immutable/tests/ImmutableSortedSetTest.cs @@ -289,7 +289,7 @@ public void Create() Assert.Equal(1, set.Count); Assert.Same(comparer, set.KeyComparer); - set = ImmutableSortedSet.Create("a", "b"); + set = ImmutableSortedSet.Create(new [] { "a", "b" }); Assert.Equal(2, set.Count); Assert.Same(Comparer.Default, set.KeyComparer); @@ -297,7 +297,7 @@ public void Create() Assert.Equal(2, set.Count); Assert.Same(Comparer.Default, set.KeyComparer); - set = ImmutableSortedSet.Create(comparer, "a", "b"); + set = ImmutableSortedSet.Create(comparer, new[] { "a", "b" }); Assert.Equal(2, set.Count); Assert.Same(comparer, set.KeyComparer); diff --git a/src/libraries/System.Collections.Immutable/tests/ImmutableStackTest.cs b/src/libraries/System.Collections.Immutable/tests/ImmutableStackTest.cs index 26336209e120..4abd031ed43b 100644 --- a/src/libraries/System.Collections.Immutable/tests/ImmutableStackTest.cs +++ b/src/libraries/System.Collections.Immutable/tests/ImmutableStackTest.cs @@ -241,7 +241,7 @@ public void Create() Assert.False(stack.IsEmpty); Assert.Equal(new[] { 1 }, stack); - stack = ImmutableStack.Create(1, 2); + stack = ImmutableStack.Create(new[] { 1, 2 }); Assert.False(stack.IsEmpty); Assert.Equal(new[] { 2, 1 }, stack); diff --git a/src/libraries/System.Collections.NonGeneric/src/System.Collections.NonGeneric.csproj b/src/libraries/System.Collections.NonGeneric/src/System.Collections.NonGeneric.csproj index 770e5fc0fc18..1bc456cd13ba 100644 --- a/src/libraries/System.Collections.NonGeneric/src/System.Collections.NonGeneric.csproj +++ b/src/libraries/System.Collections.NonGeneric/src/System.Collections.NonGeneric.csproj @@ -21,6 +21,7 @@ + diff --git a/src/libraries/System.Collections.NonGeneric/src/System/Collections/CaseInsensitiveComparer.cs b/src/libraries/System.Collections.NonGeneric/src/System/Collections/CaseInsensitiveComparer.cs index 0c84d460db36..82f587ec9616 100644 --- a/src/libraries/System.Collections.NonGeneric/src/System/Collections/CaseInsensitiveComparer.cs +++ b/src/libraries/System.Collections.NonGeneric/src/System/Collections/CaseInsensitiveComparer.cs @@ -17,7 +17,7 @@ namespace System.Collections public class CaseInsensitiveComparer : IComparer { private readonly CompareInfo _compareInfo; - private static volatile CaseInsensitiveComparer? s_InvariantCaseInsensitiveComparer; + private static CaseInsensitiveComparer? s_InvariantCaseInsensitiveComparer; public CaseInsensitiveComparer() { diff --git a/src/libraries/System.Collections.NonGeneric/src/System/Collections/CaseInsensitiveHashCodeProvider.cs b/src/libraries/System.Collections.NonGeneric/src/System/Collections/CaseInsensitiveHashCodeProvider.cs index 61777b6c93c5..22bb48f8a1c2 100644 --- a/src/libraries/System.Collections.NonGeneric/src/System/Collections/CaseInsensitiveHashCodeProvider.cs +++ b/src/libraries/System.Collections.NonGeneric/src/System/Collections/CaseInsensitiveHashCodeProvider.cs @@ -12,7 +12,7 @@ namespace System.Collections [Obsolete("CaseInsensitiveHashCodeProvider has been deprecated. Use StringComparer instead.")] public class CaseInsensitiveHashCodeProvider : IHashCodeProvider { - private static volatile CaseInsensitiveHashCodeProvider? s_invariantCaseInsensitiveHashCodeProvider; + private static CaseInsensitiveHashCodeProvider? s_invariantCaseInsensitiveHashCodeProvider; private readonly CompareInfo _compareInfo; public CaseInsensitiveHashCodeProvider() diff --git a/src/libraries/System.Collections.Specialized/src/System.Collections.Specialized.csproj b/src/libraries/System.Collections.Specialized/src/System.Collections.Specialized.csproj index 21e6fc760efa..4301d885411c 100644 --- a/src/libraries/System.Collections.Specialized/src/System.Collections.Specialized.csproj +++ b/src/libraries/System.Collections.Specialized/src/System.Collections.Specialized.csproj @@ -23,6 +23,7 @@ + diff --git a/src/libraries/System.Collections/ref/System.Collections.cs b/src/libraries/System.Collections/ref/System.Collections.cs index 2fa8f622b611..6d8c4f6f2738 100644 --- a/src/libraries/System.Collections/ref/System.Collections.cs +++ b/src/libraries/System.Collections/ref/System.Collections.cs @@ -416,11 +416,11 @@ namespace System.Collections.Generic { public static partial class CollectionExtensions { - public static void AddRange(this System.Collections.Generic.List list, System.ReadOnlySpan source) { } + public static void AddRange(this System.Collections.Generic.List list, params System.ReadOnlySpan source) { } public static void CopyTo(this System.Collections.Generic.List list, System.Span destination) { } public static TValue? GetValueOrDefault(this System.Collections.Generic.IReadOnlyDictionary dictionary, TKey key) { throw null; } public static TValue GetValueOrDefault(this System.Collections.Generic.IReadOnlyDictionary dictionary, TKey key, TValue defaultValue) { throw null; } - public static void InsertRange(this System.Collections.Generic.List list, int index, System.ReadOnlySpan source) { } + public static void InsertRange(this System.Collections.Generic.List list, int index, params System.ReadOnlySpan source) { } public static bool Remove(this System.Collections.Generic.IDictionary dictionary, TKey key, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TValue value) { throw null; } public static bool TryAdd(this System.Collections.Generic.IDictionary dictionary, TKey key, TValue value) { throw null; } public static System.Collections.ObjectModel.ReadOnlyCollection AsReadOnly(this IList list) { throw null; } diff --git a/src/libraries/System.Collections/src/CompatibilitySuppressions.xml b/src/libraries/System.Collections/src/CompatibilitySuppressions.xml index c313881d4317..f281317339d4 100644 --- a/src/libraries/System.Collections/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Collections/src/CompatibilitySuppressions.xml @@ -1,4 +1,5 @@  + CP0001 diff --git a/src/libraries/System.Collections/src/System/Collections/StructuralComparisons.cs b/src/libraries/System.Collections/src/System/Collections/StructuralComparisons.cs index 988cc218e9fd..d4eb6576b3ae 100644 --- a/src/libraries/System.Collections/src/System/Collections/StructuralComparisons.cs +++ b/src/libraries/System.Collections/src/System/Collections/StructuralComparisons.cs @@ -7,16 +7,15 @@ namespace System.Collections { public static class StructuralComparisons { - private static volatile IComparer? s_StructuralComparer; - private static volatile IEqualityComparer? s_StructuralEqualityComparer; + public static IComparer StructuralComparer => System.Collections.StructuralComparer.s_instance; - public static IComparer StructuralComparer => s_StructuralComparer ??= new StructuralComparer(); - - public static IEqualityComparer StructuralEqualityComparer => s_StructuralEqualityComparer ??= new StructuralEqualityComparer(); + public static IEqualityComparer StructuralEqualityComparer => System.Collections.StructuralEqualityComparer.s_instance; } internal sealed class StructuralEqualityComparer : IEqualityComparer { + internal static readonly StructuralEqualityComparer s_instance = new(); + public new bool Equals(object? x, object? y) { if (x != null) @@ -58,6 +57,8 @@ public int GetHashCode(object obj) internal sealed class StructuralComparer : IComparer { + internal static readonly StructuralComparer s_instance = new(); + public int Compare(object? x, object? y) { if (x == null) return y == null ? 0 : -1; diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/EmailAddressAttribute.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/EmailAddressAttribute.cs index 2e28b0cb6ac3..c7743f0144ba 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/EmailAddressAttribute.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/EmailAddressAttribute.cs @@ -27,6 +27,11 @@ public override bool IsValid(object? value) return false; } + if (valueAsString.AsSpan().ContainsAny('\r', '\n')) + { + return false; + } + // only return true if there is only 1 '@' character // and it is neither the first nor the last character int index = valueAsString.IndexOf('@'); diff --git a/src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/EmailAddressAttributeTests.cs b/src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/EmailAddressAttributeTests.cs index a0c67ed7d2b9..da80016608e4 100644 --- a/src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/EmailAddressAttributeTests.cs +++ b/src/libraries/System.ComponentModel.Annotations/tests/System/ComponentModel/DataAnnotations/EmailAddressAttributeTests.cs @@ -29,6 +29,7 @@ protected override IEnumerable InvalidValues() yield return new TestCase(new EmailAddressAttribute(), 0); yield return new TestCase(new EmailAddressAttribute(), ""); yield return new TestCase(new EmailAddressAttribute(), " \r \t \n" ); + yield return new TestCase(new EmailAddressAttribute(), "someName@[\r\n\tsomeDomain]"); yield return new TestCase(new EmailAddressAttribute(), "@someDomain.com"); yield return new TestCase(new EmailAddressAttribute(), "@someDomain@abc.com"); yield return new TestCase(new EmailAddressAttribute(), "someName"); diff --git a/src/libraries/System.ComponentModel.Composition.Registration/src/System/ComponentModel/Composition/Registration/PartBuilder.cs b/src/libraries/System.ComponentModel.Composition.Registration/src/System/ComponentModel/Composition/Registration/PartBuilder.cs index 2ad43f582629..e0f9cb29774d 100644 --- a/src/libraries/System.ComponentModel.Composition.Registration/src/System/ComponentModel/Composition/Registration/PartBuilder.cs +++ b/src/libraries/System.ComponentModel.Composition.Registration/src/System/ComponentModel/Composition/Registration/PartBuilder.cs @@ -29,7 +29,7 @@ public class PartBuilder private readonly List, Action, Type>> _propertyImports; private readonly List, Action>> _interfaceExports; - internal Predicate SelectType { get; private set; } + internal Predicate SelectType { get; } internal PartBuilder(Predicate selectType) { diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ExportAttribute.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ExportAttribute.cs index 9e9fc6424362..bdfdd0b3b6d9 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ExportAttribute.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ExportAttribute.cs @@ -126,7 +126,7 @@ public ExportAttribute(string? contractName, Type? contractType) /// A containing the contract name to export the type or member /// marked with this attribute, under. The default value is an empty string (""). /// - public string? ContractName { get; private set; } + public string? ContractName { get; } /// /// Get the contract type that is exported by the member that this attribute is attached to. @@ -136,6 +136,6 @@ public ExportAttribute(string? contractName, Type? contractType) /// which means that the type will be obtained by looking at the type on /// the member that this export is attached to. /// - public Type? ContractType { get; private set; } + public Type? ContractType { get; } } } diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/CatalogExportProvider.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/CatalogExportProvider.cs index 879e5a1dd289..8b465a5e0f0f 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/CatalogExportProvider.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/CatalogExportProvider.cs @@ -1025,7 +1025,7 @@ public CatalogPart(ComposablePart part) { Part = part; } - public ComposablePart Part { get; private set; } + public ComposablePart Part { get; } public bool ImportsSatisfied { diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ComposablePartCatalogChangeEventArgs.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ComposablePartCatalogChangeEventArgs.cs index b1b948fcdd31..660db0d74169 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ComposablePartCatalogChangeEventArgs.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ComposablePartCatalogChangeEventArgs.cs @@ -95,6 +95,6 @@ public IEnumerable RemovedDefinitions /// When the value is non-null it should be used to record temporary changed state /// and actions that will be executed when the atomicComposition is completeed. /// - public AtomicComposition? AtomicComposition { get; private set; } + public AtomicComposition? AtomicComposition { get; } } } diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/DirectoryCatalog.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/DirectoryCatalog.cs index 95ea38065458..75744ec2c1d3 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/DirectoryCatalog.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/DirectoryCatalog.cs @@ -22,7 +22,7 @@ namespace System.ComponentModel.Composition.Hosting public partial class DirectoryCatalog : ComposablePartCatalog, INotifyComposablePartCatalogChanged, ICompositionElement { private static bool IsWindows => -#if NETCOREAPP_5_0_OR_GREATER +#if NET OperatingSystem.IsWindows(); #else RuntimeInformation.IsOSPlatform(OSPlatform.Windows); diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ExportsChangeEventArgs.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ExportsChangeEventArgs.cs index 0e0cbedfd01d..3fed9029fdd0 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ExportsChangeEventArgs.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ExportsChangeEventArgs.cs @@ -113,6 +113,6 @@ public IEnumerable RemovedExports /// When the value is non-null it should be used to record temporary changed state /// and actions that will be executed when the atomicComposition is completeed. /// - public AtomicComposition? AtomicComposition { get; private set; } + public AtomicComposition? AtomicComposition { get; } } } diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ImportAttribute.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ImportAttribute.cs index 6357021ed54d..c9e3e11e071f 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ImportAttribute.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ImportAttribute.cs @@ -99,7 +99,7 @@ public ImportAttribute(string? contractName, Type? contractType) /// A containing the contract name of the export to import. The /// default value is an empty string (""). /// - public string? ContractName { get; private set; } + public string? ContractName { get; } /// /// Get the contract type of the export to import. @@ -110,7 +110,7 @@ public ImportAttribute(string? contractName, Type? contractType) /// the member that this import is attached to. If the type is then the /// importer is delaring they can accept any exported type. /// - public Type? ContractType { get; private set; } + public Type? ContractType { get; } /// /// Gets or sets a value indicating whether the property, field or parameter will be set diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ImportManyAttribute.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ImportManyAttribute.cs index 918cb09cedb5..687c794c7d1f 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ImportManyAttribute.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ImportManyAttribute.cs @@ -99,7 +99,7 @@ public ImportManyAttribute(string? contractName, Type? contractType) /// A containing the contract name of the exports to import. The /// default value is an empty string (""). /// - public string? ContractName { get; private set; } + public string? ContractName { get; } /// /// Get the contract type of the export to import. @@ -110,7 +110,7 @@ public ImportManyAttribute(string? contractName, Type? contractType) /// the member that this import is attached to. If the type is then the /// importer is delaring they can accept any exported type. /// - public Type? ContractType { get; private set; } + public Type? ContractType { get; } /// /// Gets or sets a value indicating whether the property or field will be recomposed diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/MetadataViewImplementationAttribute.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/MetadataViewImplementationAttribute.cs index 7f70310ff980..557ab0a65c66 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/MetadataViewImplementationAttribute.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/MetadataViewImplementationAttribute.cs @@ -36,6 +36,6 @@ public MetadataViewImplementationAttribute(Type? implementationType) /// which means that the type will be obtained by looking at the type on /// the member that this export is attached to. /// - public Type? ImplementationType { get; private set; } + public Type? ImplementationType { get; } } } diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/PartCreationPolicyAttribute.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/PartCreationPolicyAttribute.cs index a1b151c48358..fa06489b1b60 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/PartCreationPolicyAttribute.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/PartCreationPolicyAttribute.cs @@ -9,8 +9,8 @@ namespace System.ComponentModel.Composition [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public sealed class PartCreationPolicyAttribute : Attribute { - internal static PartCreationPolicyAttribute Default = new PartCreationPolicyAttribute(CreationPolicy.Any); - internal static PartCreationPolicyAttribute Shared = new PartCreationPolicyAttribute(CreationPolicy.Shared); + internal static readonly PartCreationPolicyAttribute Default = new PartCreationPolicyAttribute(CreationPolicy.Any); + internal static readonly PartCreationPolicyAttribute Shared = new PartCreationPolicyAttribute(CreationPolicy.Shared); /// /// Initializes a new instance of the class. @@ -28,6 +28,6 @@ public PartCreationPolicyAttribute(CreationPolicy creationPolicy) /// attributed part. The default is /// . /// - public CreationPolicy CreationPolicy { get; private set; } + public CreationPolicy CreationPolicy { get; } } } diff --git a/src/libraries/System.ComponentModel.EventBasedAsync/src/System.ComponentModel.EventBasedAsync.csproj b/src/libraries/System.ComponentModel.EventBasedAsync/src/System.ComponentModel.EventBasedAsync.csproj index 0d413f6fd370..a5d9913733b4 100644 --- a/src/libraries/System.ComponentModel.EventBasedAsync/src/System.ComponentModel.EventBasedAsync.csproj +++ b/src/libraries/System.ComponentModel.EventBasedAsync/src/System.ComponentModel.EventBasedAsync.csproj @@ -18,6 +18,7 @@ + diff --git a/src/libraries/System.ComponentModel.Primitives/src/System.ComponentModel.Primitives.csproj b/src/libraries/System.ComponentModel.Primitives/src/System.ComponentModel.Primitives.csproj index 5fcff9013095..2938d1e64126 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System.ComponentModel.Primitives.csproj +++ b/src/libraries/System.ComponentModel.Primitives/src/System.ComponentModel.Primitives.csproj @@ -47,6 +47,7 @@ + diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/CategoryAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/CategoryAttribute.cs index 2b9c0c08c88e..fc06665da5ec 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/CategoryAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/CategoryAttribute.cs @@ -12,22 +12,22 @@ namespace System.ComponentModel [AttributeUsage(AttributeTargets.All)] public class CategoryAttribute : Attribute { - private static volatile CategoryAttribute? s_action; - private static volatile CategoryAttribute? s_appearance; - private static volatile CategoryAttribute? s_asynchronous; - private static volatile CategoryAttribute? s_behavior; - private static volatile CategoryAttribute? s_data; - private static volatile CategoryAttribute? s_design; - private static volatile CategoryAttribute? s_dragDrop; - private static volatile CategoryAttribute? s_defAttr; - private static volatile CategoryAttribute? s_focus; - private static volatile CategoryAttribute? s_format; - private static volatile CategoryAttribute? s_key; - private static volatile CategoryAttribute? s_layout; - private static volatile CategoryAttribute? s_mouse; - private static volatile CategoryAttribute? s_windowStyle; - - private bool _localized; + private static CategoryAttribute? s_action; + private static CategoryAttribute? s_appearance; + private static CategoryAttribute? s_asynchronous; + private static CategoryAttribute? s_behavior; + private static CategoryAttribute? s_data; + private static CategoryAttribute? s_design; + private static CategoryAttribute? s_dragDrop; + private static CategoryAttribute? s_defAttr; + private static CategoryAttribute? s_focus; + private static CategoryAttribute? s_format; + private static CategoryAttribute? s_key; + private static CategoryAttribute? s_layout; + private static CategoryAttribute? s_mouse; + private static CategoryAttribute? s_windowStyle; + + private volatile bool _localized; private readonly object _locker = new object(); diff --git a/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs index 59c3284a7fab..5467a62036eb 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs @@ -10,7 +10,7 @@ public partial class UriTypeConverter : System.ComponentModel.TypeConverter { public UriTypeConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } public override bool IsValid(System.ComponentModel.ITypeDescriptorContext? context, object? value) { throw null; } @@ -38,7 +38,6 @@ public AmbientValueAttribute(long value) { } public AmbientValueAttribute(object? value) { } public AmbientValueAttribute(float value) { } public AmbientValueAttribute(string? value) { } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Generic TypeConverters may require the generic types to be annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All.")] public AmbientValueAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, string value) { } public object? Value { get { throw null; } } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } @@ -91,7 +90,7 @@ public abstract partial class BaseNumberConverter : System.ComponentModel.TypeCo { internal BaseNumberConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } } @@ -246,6 +245,7 @@ public ComponentResourceManager(System.Type t) { } public void ApplyResources(object value, string objectName) { } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of value cannot be statically discovered.")] public virtual void ApplyResources(object value, string objectName, System.Globalization.CultureInfo? culture) { } + public virtual void ApplyResourcesToRegisteredType(object value, string objectName, System.Globalization.CultureInfo? culture) { } } public partial class Container : System.ComponentModel.IContainer, System.IDisposable { @@ -273,7 +273,7 @@ public partial class CultureInfoConverter : System.ComponentModel.TypeConverter { public CultureInfoConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } protected virtual string GetCultureName(System.Globalization.CultureInfo culture) { throw null; } @@ -290,6 +290,7 @@ protected CustomTypeDescriptor(System.ComponentModel.ICustomTypeDescriptor? pare public virtual string? GetComponentName() { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Generic TypeConverters may require the generic types to be annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All.")] public virtual System.ComponentModel.TypeConverter? GetConverter() { throw null; } + public virtual System.ComponentModel.TypeConverter? GetConverterFromRegisteredType() { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The built-in EventDescriptor implementation uses Reflection which requires unreferenced code.")] public virtual System.ComponentModel.EventDescriptor? GetDefaultEvent() { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered.")] @@ -297,13 +298,16 @@ protected CustomTypeDescriptor(System.ComponentModel.ICustomTypeDescriptor? pare [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Design-time attributes are not preserved when trimming. Types referenced by attributes like EditorAttribute and DesignerAttribute may not be available after trimming.")] public virtual object? GetEditor(System.Type editorBaseType) { throw null; } public virtual System.ComponentModel.EventDescriptorCollection GetEvents() { throw null; } + public virtual System.ComponentModel.EventDescriptorCollection GetEventsFromRegisteredType() { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public virtual System.ComponentModel.EventDescriptorCollection GetEvents(System.Attribute[]? attributes) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered.")] public virtual System.ComponentModel.PropertyDescriptorCollection GetProperties() { throw null; } + public virtual System.ComponentModel.PropertyDescriptorCollection GetPropertiesFromRegisteredType() { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public virtual System.ComponentModel.PropertyDescriptorCollection GetProperties(System.Attribute[]? attributes) { throw null; } public virtual object? GetPropertyOwner(System.ComponentModel.PropertyDescriptor? pd) { throw null; } + public virtual bool? RequireRegisteredTypes { get { throw null; } } } [System.AttributeUsageAttribute(System.AttributeTargets.Class)] public sealed partial class DataObjectAttribute : System.Attribute @@ -355,7 +359,7 @@ public partial class DateOnlyConverter : System.ComponentModel.TypeConverter { public DateOnlyConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } } @@ -363,7 +367,7 @@ public partial class DateTimeConverter : System.ComponentModel.TypeConverter { public DateTimeConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } } @@ -371,14 +375,14 @@ public partial class DateTimeOffsetConverter : System.ComponentModel.TypeConvert { public DateTimeOffsetConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } } public partial class DecimalConverter : System.ComponentModel.BaseNumberConverter { public DecimalConverter() { } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } } [System.AttributeUsageAttribute(System.AttributeTargets.Class)] @@ -433,7 +437,7 @@ public EnumConverter(System.Type type) { } protected System.Type EnumType { get { throw null; } } protected System.ComponentModel.TypeConverter.StandardValuesCollection? Values { get { throw null; } set { } } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } public override System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(System.ComponentModel.ITypeDescriptorContext? context) { throw null; } @@ -513,7 +517,7 @@ public partial class GuidConverter : System.ComponentModel.TypeConverter { public GuidConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } } @@ -584,6 +588,7 @@ public partial interface ICustomTypeDescriptor string? GetComponentName(); [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Generic TypeConverters may require the generic types to be annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All.")] System.ComponentModel.TypeConverter? GetConverter(); + System.ComponentModel.TypeConverter? GetConverterFromRegisteredType() { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The built-in EventDescriptor implementation uses Reflection which requires unreferenced code.")] System.ComponentModel.EventDescriptor? GetDefaultEvent(); [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered.")] @@ -593,10 +598,13 @@ public partial interface ICustomTypeDescriptor System.ComponentModel.EventDescriptorCollection GetEvents(); [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] System.ComponentModel.EventDescriptorCollection GetEvents(System.Attribute[]? attributes); + System.ComponentModel.EventDescriptorCollection GetEventsFromRegisteredType() { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered.")] System.ComponentModel.PropertyDescriptorCollection GetProperties(); [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] System.ComponentModel.PropertyDescriptorCollection GetProperties(System.Attribute[]? attributes); + System.ComponentModel.PropertyDescriptorCollection GetPropertiesFromRegisteredType() { throw null; } + bool? RequireRegisteredTypes => throw null!; object? GetPropertyOwner(System.ComponentModel.PropertyDescriptor? pd); } public partial interface IDataErrorInfo @@ -720,16 +728,16 @@ public virtual void SetSavedLicenseKey(System.Type type, string key) { } } public partial class LicenseException : System.SystemException { - [System.ObsoleteAttribute("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId = "SYSLIB0051", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId="SYSLIB0051", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] protected LicenseException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public LicenseException(System.Type? type) { } public LicenseException(System.Type? type, object? instance) { } public LicenseException(System.Type? type, object? instance, string? message) { } public LicenseException(System.Type? type, object? instance, string? message, System.Exception? innerException) { } public System.Type? LicensedType { get { throw null; } } - [System.ObsoleteAttribute("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId = "SYSLIB0051", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId="SYSLIB0051", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } public sealed partial class LicenseManager @@ -1037,7 +1045,7 @@ public NullableConverter(System.Type type) { } public System.Type UnderlyingType { get { throw null; } } public System.ComponentModel.TypeConverter UnderlyingTypeConverter { get { throw null; } } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } public override object? CreateInstance(System.ComponentModel.ITypeDescriptorContext? context, System.Collections.IDictionary propertyValues) { throw null; } @@ -1070,6 +1078,7 @@ protected PropertyDescriptor(System.ComponentModel.MemberDescriptor descr, Syste protected PropertyDescriptor(string name, System.Attribute[]? attrs) : base (default(string)) { } public abstract System.Type ComponentType { get; } public virtual System.ComponentModel.TypeConverter Converter { [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered.")] get { throw null; } } + public virtual System.ComponentModel.TypeConverter ConverterFromRegisteredType { get { throw null; } } public virtual bool IsLocalizable { get { throw null; } } public abstract bool IsReadOnly { get; } public abstract System.Type PropertyType { get; } @@ -1267,7 +1276,7 @@ public partial class TimeOnlyConverter : System.ComponentModel.TypeConverter { public TimeOnlyConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } } @@ -1275,7 +1284,7 @@ public partial class TimeSpanConverter : System.ComponentModel.TypeConverter { public TimeSpanConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } } @@ -1320,8 +1329,8 @@ public partial class TypeConverter public TypeConverter() { } public virtual bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } public bool CanConvertFrom(System.Type sourceType) { throw null; } - public virtual bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } - public bool CanConvertTo([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public virtual bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } + public bool CanConvertTo([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public virtual object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public object? ConvertFrom(object value) { throw null; } public object? ConvertFromInvariantString(System.ComponentModel.ITypeDescriptorContext? context, string text) { throw null; } @@ -1385,10 +1394,13 @@ public abstract partial class TypeDescriptionProvider { protected TypeDescriptionProvider() { } protected TypeDescriptionProvider(System.ComponentModel.TypeDescriptionProvider parent) { } + public virtual void RegisterType<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.Interfaces | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicEvents)] T>() { } + public virtual bool? RequireRegisteredTypes { get { throw null; } } public virtual object? CreateInstance(System.IServiceProvider? provider, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type objectType, System.Type[]? argTypes, object?[]? args) { throw null; } public virtual System.Collections.IDictionary? GetCache(object instance) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of instance cannot be statically discovered.")] public virtual System.ComponentModel.ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) { throw null; } + public virtual System.ComponentModel.ICustomTypeDescriptor GetExtendedTypeDescriptorFromRegisteredType(object instance) { throw null; } protected internal virtual System.ComponentModel.IExtenderProvider[] GetExtenderProviders(object instance) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered.")] public virtual string? GetFullComponentName(object component) { throw null; } @@ -1403,6 +1415,10 @@ protected TypeDescriptionProvider(System.ComponentModel.TypeDescriptionProvider public System.ComponentModel.ICustomTypeDescriptor? GetTypeDescriptor(object instance) { throw null; } public System.ComponentModel.ICustomTypeDescriptor? GetTypeDescriptor([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type objectType) { throw null; } public virtual System.ComponentModel.ICustomTypeDescriptor? GetTypeDescriptor([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type objectType, object? instance) { throw null; } + public System.ComponentModel.ICustomTypeDescriptor? GetTypeDescriptorFromRegisteredType(object instance) { throw null; } + public System.ComponentModel.ICustomTypeDescriptor? GetTypeDescriptorFromRegisteredType(Type objectType) { throw null; } + public virtual System.ComponentModel.ICustomTypeDescriptor? GetTypeDescriptorFromRegisteredType(Type objectType, object? instance) { throw null; } + public virtual bool IsRegisteredType(System.Type type) { throw null; } public virtual bool IsSupportedType(System.Type type) { throw null; } } public sealed partial class TypeDescriptor @@ -1410,9 +1426,17 @@ public sealed partial class TypeDescriptor internal TypeDescriptor() { } [System.Diagnostics.CodeAnalysis.DisallowNullAttribute] [System.ObsoleteAttribute("TypeDescriptor.ComNativeDescriptorHandler has been deprecated. Use a type description provider to supply type information for COM types instead.")] - public static System.ComponentModel.IComNativeDescriptorHandler? ComNativeDescriptorHandler { get { throw null; } set { } } + public static System.ComponentModel.IComNativeDescriptorHandler? ComNativeDescriptorHandler { + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("COM type descriptors are not trim-compatible.")] + get { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("COM type descriptors are not trim-compatible.")] + set { } + } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] - public static System.Type ComObjectType { [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] get { throw null; } } + public static System.Type ComObjectType { + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("COM type descriptors are not trim-compatible.")] + [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] get { throw null; } + } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Type InterfaceType { [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] get { throw null; } } public static event System.ComponentModel.RefreshEventHandler? Refreshed { add { } remove { } } @@ -1420,9 +1444,10 @@ public static event System.ComponentModel.RefreshEventHandler? Refreshed { add { public static System.ComponentModel.TypeDescriptionProvider AddAttributes(object instance, params System.Attribute[] attributes) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.ComponentModel.TypeDescriptionProvider AddAttributes(System.Type type, params System.Attribute[] attributes) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Types specified in table may be trimmed, or have their static construtors trimmed.")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Types specified in table may be trimmed, or have their static constructors trimmed.")] public static void AddEditorTable(System.Type editorBaseType, System.Collections.Hashtable table) { } + public static void RegisterType<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.Interfaces | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicEvents)]T> () { } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static void AddProvider(System.ComponentModel.TypeDescriptionProvider provider, object instance) { } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] @@ -1433,7 +1458,7 @@ public static void AddProviderTransparent(System.ComponentModel.TypeDescriptionP public static void AddProviderTransparent(System.ComponentModel.TypeDescriptionProvider provider, System.Type type) { } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static void CreateAssociation(object primary, object secondary) { } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered.")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Design-time attributes are not preserved when trimming. Types referenced by attributes like EditorAttribute and DesignerAttribute may not be available after trimming.")] public static System.ComponentModel.Design.IDesigner? CreateDesigner(System.ComponentModel.IComponent component, System.Type designerBaseType) { throw null; } public static System.ComponentModel.EventDescriptor CreateEvent([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType, System.ComponentModel.EventDescriptor oldEventDescriptor, params System.Attribute[] attributes) { throw null; } public static System.ComponentModel.EventDescriptor CreateEvent([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType, string name, System.Type type, params System.Attribute[] attributes) { throw null; } @@ -1446,46 +1471,48 @@ public static void CreateAssociation(object primary, object secondary) { } public static object GetAssociation(System.Type type, object primary) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered.")] public static System.ComponentModel.AttributeCollection GetAttributes(object component) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered.")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered.")] public static System.ComponentModel.AttributeCollection GetAttributes(object component, bool noCustomTypeDesc) { throw null; } public static System.ComponentModel.AttributeCollection GetAttributes([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered.")] public static string? GetClassName(object component) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered.")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered.")] public static string? GetClassName(object component, bool noCustomTypeDesc) { throw null; } public static string? GetClassName([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered.")] public static string? GetComponentName(object component) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered.")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered.")] public static string? GetComponentName(object component, bool noCustomTypeDesc) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Generic TypeConverters may require the generic types to be annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All. The Type of component cannot be statically discovered.")] public static System.ComponentModel.TypeConverter GetConverter(object component) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Generic TypeConverters may require the generic types to be annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All. The Type of component cannot be statically discovered.")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Generic TypeConverters may require the generic types to be annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All. The Type of component cannot be statically discovered.")] public static System.ComponentModel.TypeConverter GetConverter(object component, bool noCustomTypeDesc) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Generic TypeConverters may require the generic types to be annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All.")] public static System.ComponentModel.TypeConverter GetConverter([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type) { throw null; } + public static System.ComponentModel.TypeConverter GetConverterFromRegisteredType(object component) { throw null; } + public static System.ComponentModel.TypeConverter GetConverterFromRegisteredType(System.Type type) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The built-in EventDescriptor implementation uses Reflection which requires unreferenced code. The Type of component cannot be statically discovered.")] public static System.ComponentModel.EventDescriptor? GetDefaultEvent(object component) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The built-in EventDescriptor implementation uses Reflection which requires unreferenced code. The Type of component cannot be statically discovered.")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The built-in EventDescriptor implementation uses Reflection which requires unreferenced code. The Type of component cannot be statically discovered.")] public static System.ComponentModel.EventDescriptor? GetDefaultEvent(object component, bool noCustomTypeDesc) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The built-in EventDescriptor implementation uses Reflection which requires unreferenced code.")] public static System.ComponentModel.EventDescriptor? GetDefaultEvent([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered. The Type of component cannot be statically discovered.")] public static System.ComponentModel.PropertyDescriptor? GetDefaultProperty(object component) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered. The Type of component cannot be statically discovered.")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered. The Type of component cannot be statically discovered.")] public static System.ComponentModel.PropertyDescriptor? GetDefaultProperty(object component, bool noCustomTypeDesc) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered.")] public static System.ComponentModel.PropertyDescriptor? GetDefaultProperty([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Design-time attributes are not preserved when trimming. Types referenced by attributes like EditorAttribute and DesignerAttribute may not be available after trimming. The Type of component cannot be statically discovered.")] public static object? GetEditor(object component, System.Type editorBaseType) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Design-time attributes are not preserved when trimming. Types referenced by attributes like EditorAttribute and DesignerAttribute may not be available after trimming. The Type of component cannot be statically discovered.")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Design-time attributes are not preserved when trimming. Types referenced by attributes like EditorAttribute and DesignerAttribute may not be available after trimming. The Type of component cannot be statically discovered.")] public static object? GetEditor(object component, System.Type editorBaseType, bool noCustomTypeDesc) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Design-time attributes are not preserved when trimming. Types referenced by attributes like EditorAttribute and DesignerAttribute may not be available after trimming.")] public static object? GetEditor([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, System.Type editorBaseType) { throw null; } @@ -1493,15 +1520,16 @@ public static void CreateAssociation(object primary, object secondary) { } public static System.ComponentModel.EventDescriptorCollection GetEvents(object component) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public static System.ComponentModel.EventDescriptorCollection GetEvents(object component, System.Attribute[] attributes) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public static System.ComponentModel.EventDescriptorCollection GetEvents(object component, System.Attribute[]? attributes, bool noCustomTypeDesc) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered.")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered.")] public static System.ComponentModel.EventDescriptorCollection GetEvents(object component, bool noCustomTypeDesc) { throw null; } public static System.ComponentModel.EventDescriptorCollection GetEvents([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public static System.ComponentModel.EventDescriptorCollection GetEvents([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType, System.Attribute[] attributes) { throw null; } + public static System.ComponentModel.EventDescriptorCollection GetEventsFromRegisteredType(System.Type componentType) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered.")] public static string? GetFullComponentName(object component) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered. The Type of component cannot be statically discovered.")] @@ -1510,19 +1538,21 @@ public static void CreateAssociation(object primary, object secondary) { } public static System.ComponentModel.PropertyDescriptorCollection GetProperties(object component, System.Attribute[]? attributes) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered. The Type of component cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public static System.ComponentModel.PropertyDescriptorCollection GetProperties(object component, System.Attribute[]? attributes, bool noCustomTypeDesc) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered. The Type of component cannot be statically discovered.")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered. The Type of component cannot be statically discovered.")] public static System.ComponentModel.PropertyDescriptorCollection GetProperties(object component, bool noCustomTypeDesc) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered.")] public static System.ComponentModel.PropertyDescriptorCollection GetProperties([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("PropertyDescriptor's PropertyType cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public static System.ComponentModel.PropertyDescriptorCollection GetProperties([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType, System.Attribute[]? attributes) { throw null; } + public static System.ComponentModel.PropertyDescriptorCollection GetPropertiesFromRegisteredType(System.Type componentType) { throw null; } + public static System.ComponentModel.PropertyDescriptorCollection GetPropertiesFromRegisteredType(object component) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.ComponentModel.TypeDescriptionProvider GetProvider(object instance) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.ComponentModel.TypeDescriptionProvider GetProvider(System.Type type) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("GetReflectionType is not trim compatible because the Type of object cannot be statically discovered.")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("GetReflectionType is not trim compatible because the Type of object cannot be statically discovered.")] public static System.Type GetReflectionType(object instance) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] @@ -1549,13 +1579,17 @@ public abstract partial class TypeListConverter : System.ComponentModel.TypeConv { protected TypeListConverter(System.Type[] types) { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } public override System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(System.ComponentModel.ITypeDescriptorContext? context) { throw null; } public override bool GetStandardValuesExclusive(System.ComponentModel.ITypeDescriptorContext? context) { throw null; } public override bool GetStandardValuesSupported(System.ComponentModel.ITypeDescriptorContext? context) { throw null; } } + public partial class UInt128Converter : System.ComponentModel.BaseNumberConverter + { + public UInt128Converter() { } + } public partial class UInt16Converter : System.ComponentModel.BaseNumberConverter { public UInt16Converter() { } @@ -1568,15 +1602,11 @@ public partial class UInt64Converter : System.ComponentModel.BaseNumberConverter { public UInt64Converter() { } } - public partial class UInt128Converter : System.ComponentModel.BaseNumberConverter - { - public UInt128Converter() { } - } public partial class VersionConverter : System.ComponentModel.TypeConverter { public VersionConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } public override bool IsValid(System.ComponentModel.ITypeDescriptorContext? context, object? value) { throw null; } @@ -1584,8 +1614,8 @@ public VersionConverter() { } public partial class WarningException : System.SystemException { public WarningException() { } - [System.ObsoleteAttribute("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId = "SYSLIB0051", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId="SYSLIB0051", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] protected WarningException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public WarningException(string? message) { } public WarningException(string? message, System.Exception? innerException) { } @@ -1593,8 +1623,8 @@ public WarningException(string? message, string? helpUrl) { } public WarningException(string? message, string? helpUrl, string? helpTopic) { } public string? HelpTopic { get { throw null; } } public string? HelpUrl { get { throw null; } } - [System.ObsoleteAttribute("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId = "SYSLIB0051", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId="SYSLIB0051", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } } @@ -1611,8 +1641,8 @@ public partial class CheckoutException : System.Runtime.InteropServices.External { public static readonly System.ComponentModel.Design.CheckoutException Canceled; public CheckoutException() { } - [System.ObsoleteAttribute("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId = "SYSLIB0051", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId="SYSLIB0051", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] protected CheckoutException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public CheckoutException(string? message) { } public CheckoutException(string? message, System.Exception? innerException) { } @@ -2294,7 +2324,7 @@ public partial class ColorConverter : System.ComponentModel.TypeConverter { public ColorConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } public override System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(System.ComponentModel.ITypeDescriptorContext? context) { throw null; } @@ -2304,7 +2334,7 @@ public partial class PointConverter : System.ComponentModel.TypeConverter { public PointConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } public override object CreateInstance(System.ComponentModel.ITypeDescriptorContext? context, System.Collections.IDictionary propertyValues) { throw null; } @@ -2317,7 +2347,7 @@ public partial class RectangleConverter : System.ComponentModel.TypeConverter { public RectangleConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } public override object CreateInstance(System.ComponentModel.ITypeDescriptorContext? context, System.Collections.IDictionary propertyValues) { throw null; } @@ -2330,7 +2360,7 @@ public partial class SizeConverter : System.ComponentModel.TypeConverter { public SizeConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } public override object CreateInstance(System.ComponentModel.ITypeDescriptorContext? context, System.Collections.IDictionary propertyValues) { throw null; } @@ -2343,7 +2373,7 @@ public partial class SizeFConverter : System.ComponentModel.TypeConverter { public SizeFConverter() { } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) { throw null; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { throw null; } public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } public override object CreateInstance(System.ComponentModel.ITypeDescriptorContext? context, System.Collections.IDictionary propertyValues) { throw null; } @@ -2358,7 +2388,7 @@ namespace System.Security.Authentication.ExtendedProtection public partial class ExtendedProtectionPolicyTypeConverter : System.ComponentModel.TypeConverter { public ExtendedProtectionPolicyTypeConverter() { } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] System.Type? destinationType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Type? destinationType) { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) { throw null; } } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/CompatibilitySuppressions.xml b/src/libraries/System.ComponentModel.TypeConverter/src/CompatibilitySuppressions.xml deleted file mode 100644 index d3c053f6e463..000000000000 --- a/src/libraries/System.ComponentModel.TypeConverter/src/CompatibilitySuppressions.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - CP0015 - M:System.ComponentModel.TypeDescriptor.CreateDesigner(System.ComponentModel.IComponent,System.Type):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - ref/net9.0/System.ComponentModel.TypeConverter.dll - lib/net9.0/System.ComponentModel.TypeConverter.dll - - \ No newline at end of file diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.LibraryBuild.xml b/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.LibraryBuild.xml index 00f9036918d6..e796cac8f444 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.LibraryBuild.xml +++ b/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.LibraryBuild.xml @@ -15,5 +15,19 @@ M:System.ComponentModel.Design.DesigntimeLicenseContextSerializer.DeserializeUsingBinaryFormatter(System.ComponentModel.Design.DesigntimeLicenseContextSerializer.StreamWrapper,System.String,System.ComponentModel.Design.RuntimeLicenseContext) This warning is left in the product so developers get an ILLink warning when trimming an app with System.ComponentModel.TypeConverter.EnableUnsafeBinaryFormatterInDesigntimeLicenseContextSerialization=true. + + ILLink + IL2026 + member + M:System.ComponentModel.TypeDescriptor.NodeFor(System.Object,System.Boolean) + This warning is left in the product so developers get an ILLink warning when trimming an app with System.ComponentModel.TypeDescriptor.IsComObjectDescriptorSupported=true. + + + ILLink + IL2026 + member + M:System.ComponentModel.AmbientValueAttribute.#ctor(System.Type,System.String) + This warning is left in the product so developers get an ILLink warning when trimming an app with System.ComponentModel.Design.IDesignerHost.IsSupported=true. + diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx b/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx index b8a10ffbcd5f..a5781823444f 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx +++ b/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx @@ -1,5 +1,64 @@  + @@ -172,6 +231,9 @@ An array of tab type names or tab types must be specified + + COM object type descriptor functionality has been disabled in the app configuration and is not supported. + (Default) @@ -259,4 +321,10 @@ BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information. - + + The type {0} is not registered. Call 'TypeDescriptor.RegisterType()' to register the type. + + + Custom type providers must implement member {0}. + + \ No newline at end of file diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System.ComponentModel.TypeConverter.csproj b/src/libraries/System.ComponentModel.TypeConverter/src/System.ComponentModel.TypeConverter.csproj index cc6429cd8f8d..588c6a970ae5 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System.ComponentModel.TypeConverter.csproj +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System.ComponentModel.TypeConverter.csproj @@ -92,17 +92,14 @@ - - + + - + @@ -184,6 +181,7 @@ + @@ -250,10 +248,7 @@ - + diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs index 53a432046683..ae52e7ebc938 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs @@ -24,12 +24,12 @@ public sealed class AmbientValueAttribute : Attribute /// specified value to the specified type, and using the U.S. English culture as the /// translation context. /// - [RequiresUnreferencedCode(TypeConverter.RequiresUnreferencedCodeMessage)] public AmbientValueAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, string value) { // The try/catch here is because attributes should never throw exceptions. We would fail to // load an otherwise normal class. + Debug.Assert(IDesignerHost.IsSupported, "Runtime instantiation of this attribute is not allowed with trimming."); if (!IDesignerHost.IsSupported) { return; @@ -37,7 +37,10 @@ public AmbientValueAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemb try { - _value = TypeDescriptor.GetConverter(type).ConvertFromInvariantString(value); + _value = TypeDescriptorGetConverter(type).ConvertFromInvariantString(value); + + [RequiresUnreferencedCode("AmbientValueAttribute usage of TypeConverter is not compatible with trimming.")] + static TypeConverter TypeDescriptorGetConverter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) => TypeDescriptor.GetConverter(type); } catch { diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentResourceManager.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentResourceManager.cs index b35e0a13e5f4..0633fe471ebf 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentResourceManager.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentResourceManager.cs @@ -64,10 +64,31 @@ private CultureInfo? NeutralResourcesCulture /// [RequiresUnreferencedCode("The Type of value cannot be statically discovered.")] public virtual void ApplyResources(object value, string objectName, CultureInfo? culture) + { + ArgumentNullException.ThrowIfNull(value); + ArgumentNullException.ThrowIfNull(objectName); + ApplyResources(value, value.GetType(), objectName, culture); + } + + /// + /// This method examines all the resources for the provided culture. + /// When it finds a resource with a key in the format of + /// "[objectName].[property name]" or "[objectName]-[property name]" it will apply that resource's value + /// to the corresponding property on the object. If there is no matching + /// property the resource will be ignored. + /// + public virtual void ApplyResourcesToRegisteredType(object value, string objectName, CultureInfo? culture) { ArgumentNullException.ThrowIfNull(value); ArgumentNullException.ThrowIfNull(objectName); + Type typeFromValue = value.GetType(); + TypeDescriptor.ValidateRegisteredType(typeFromValue); + ApplyResources(value, typeFromValue, objectName, culture); + } + + private void ApplyResources(object value, Type typeFromValue, string objectName, CultureInfo? culture) + { culture ??= CultureInfo.CurrentUICulture; // The general case here will be to always use the same culture, so optimize for @@ -148,7 +169,7 @@ public virtual void ApplyResources(object value, string objectName, CultureInfo? if (componentReflect) { - PropertyDescriptor? prop = TypeDescriptor.GetProperties(value).Find(propName, IgnoreCase); + PropertyDescriptor? prop = TypeDescriptorGetProperties(value).Find(propName, IgnoreCase); if (prop != null && !prop.IsReadOnly && (kvp.Value == null || prop.PropertyType.IsInstanceOfType(kvp.Value))) { @@ -161,16 +182,16 @@ public virtual void ApplyResources(object value, string objectName, CultureInfo? try { - prop = value.GetType().GetProperty(propName, flags); + prop = prop = TrimSafeReflectionHelper.GetProperty(typeFromValue, propName, flags); } catch (AmbiguousMatchException) { // Looks like we ran into a conflict between a declared property and an inherited one. // In such cases, we choose the most declared one. - Type? t = value.GetType(); + Type? t = typeFromValue; do { - prop = t.GetProperty(propName, flags | BindingFlags.DeclaredOnly); + prop = TrimSafeReflectionHelper.GetProperty(t, propName, flags | BindingFlags.DeclaredOnly); t = t.BaseType; } while (prop == null && t != null && t != typeof(object)); } @@ -181,6 +202,10 @@ public virtual void ApplyResources(object value, string objectName, CultureInfo? } } } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "Calling method either has RequiresUnreferencedCode or has registered types.")] + static PropertyDescriptorCollection TypeDescriptorGetProperties(object value) => TypeDescriptor.GetProperties(value); } /// diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/CustomTypeDescriptor.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/CustomTypeDescriptor.cs index 0516dae7767c..e6f78670f604 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/CustomTypeDescriptor.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/CustomTypeDescriptor.cs @@ -80,6 +80,36 @@ public virtual AttributeCollection GetAttributes() return new TypeConverter(); } + /// + /// The GetConverterFromRegisteredType method returns a type converter for the type this type + /// descriptor is representing. + /// + public virtual TypeConverter? GetConverterFromRegisteredType() + { + if (_parent != null) + { + return _parent.GetConverterFromRegisteredType(); + } + + if (RequireRegisteredTypes is null) + { + if (TypeDescriptor.RequireRegisteredTypes) + { + TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetConverterFromRegisteredType)); + } + } + else if (RequireRegisteredTypes == true) + { + TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetConverterFromRegisteredType)); + } + + return Forward(); + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = TypeDescriptionProvider.ForwardFromRegisteredMessage)] + TypeConverter? Forward() => GetConverter(); + } + /// /// The GetDefaultEvent method returns the event descriptor for the default /// event on the object this type descriptor is representing. @@ -103,10 +133,7 @@ public virtual AttributeCollection GetAttributes() /// /// The GetEvents method returns a collection of event descriptors - /// for the object this type descriptor is representing. An optional - /// attribute array may be provided to filter the collection that is - /// returned. If no parent is provided,this will return an empty - /// event collection. + /// for the object this type descriptor is representing. /// public virtual EventDescriptorCollection GetEvents() { @@ -136,12 +163,35 @@ public virtual EventDescriptorCollection GetEvents(Attribute[]? attributes) return EventDescriptorCollection.Empty; } + /// + /// Returns a collection of event descriptors + /// for the object this type descriptor is representing. + /// + public virtual EventDescriptorCollection GetEventsFromRegisteredType() + { + if (_parent != null) + { + return _parent.GetEventsFromRegisteredType(); + } + + if (RequireRegisteredTypes is null) + { + if (TypeDescriptor.RequireRegisteredTypes) + { + TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetEventsFromRegisteredType)); + } + } + else if (RequireRegisteredTypes == true) + { + TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetEventsFromRegisteredType)); + } + + return GetEvents(); + } + /// /// The GetProperties method returns a collection of property descriptors - /// for the object this type descriptor is representing. An optional - /// attribute array may be provided to filter the collection that is returned. - /// If no parent is provided,this will return an empty - /// property collection. + /// for the object this type descriptor is representing. /// [RequiresUnreferencedCode(PropertyDescriptor.PropertyDescriptorPropertyTypeMessage)] public virtual PropertyDescriptorCollection GetProperties() @@ -154,6 +204,36 @@ public virtual PropertyDescriptorCollection GetProperties() return PropertyDescriptorCollection.Empty; } + /// + /// The GetProperties method returns a collection of property descriptors + /// for the object this type descriptor is representing. + /// + public virtual PropertyDescriptorCollection GetPropertiesFromRegisteredType() + { + if (_parent != null) + { + return _parent.GetPropertiesFromRegisteredType(); + } + + if (RequireRegisteredTypes is null) + { + if (TypeDescriptor.RequireRegisteredTypes) + { + TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetPropertiesFromRegisteredType)); + } + } + else if (RequireRegisteredTypes == true) + { + TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetPropertiesFromRegisteredType)); + } + + return Forward(); + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = TypeDescriptionProvider.ForwardFromRegisteredMessage)] + PropertyDescriptorCollection Forward() => GetProperties(); + } + /// /// The GetProperties method returns a collection of property descriptors /// for the object this type descriptor is representing. An optional @@ -180,5 +260,30 @@ public virtual PropertyDescriptorCollection GetProperties(Attribute[]? attribute /// to use its default type description services. /// public virtual object? GetPropertyOwner(PropertyDescriptor? pd) => _parent?.GetPropertyOwner(pd); + + /// + /// Whether types are required to be registered through . + /// + /// + /// The default value is which means that the type descriptor has not declared whether or not it is compatible registered types. + /// A type descriptor needs to implement this to return or if the feature switch + /// 'System.ComponentModel.TypeDescriptor.RequireRegisteredTypes' is enabled. + /// If is returned, then the type descriptor must also implement + /// , + /// , and + /// . + /// + public virtual bool? RequireRegisteredTypes + { + get + { + if (_parent != null) + { + return _parent.RequireRegisteredTypes; + } + + return null; + } + } } } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/DelegatingTypeDescriptionProvider.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/DelegatingTypeDescriptionProvider.cs index 173eb6bfed74..f9526b6f6719 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/DelegatingTypeDescriptionProvider.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/DelegatingTypeDescriptionProvider.cs @@ -120,5 +120,13 @@ public override Type GetReflectionType( } public override bool IsSupportedType(Type type) => Provider.IsSupportedType(type); + + public override bool IsRegisteredType(Type type) => Provider.IsRegisteredType(type); + + public override bool? RequireRegisteredTypes => Provider.RequireRegisteredTypes; + + public override ICustomTypeDescriptor? GetTypeDescriptorFromRegisteredType(Type objectType, object? instance) => Provider.GetTypeDescriptorFromRegisteredType(objectType, instance); + + public override void RegisterType<[DynamicallyAccessedMembers(TypeDescriptor.RegisteredTypesDynamicallyAccessedMembers)] T>() => Provider.RegisterType(); } } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/IDesignerHost.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/IDesignerHost.cs index 8ab34614a7eb..46dbae0a74d4 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/IDesignerHost.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/IDesignerHost.cs @@ -12,7 +12,10 @@ namespace System.ComponentModel.Design public interface IDesignerHost : IServiceContainer { [FeatureSwitchDefinition("System.ComponentModel.Design.IDesignerHost.IsSupported")] + [FeatureGuard(typeof(RequiresUnreferencedCodeAttribute))] +#pragma warning disable IL4000 internal static bool IsSupported => AppContext.TryGetSwitch("System.ComponentModel.Design.IDesignerHost.IsSupported", out bool isSupported) ? isSupported : true; +#pragma warning restore IL4000 /// /// Gets or sets a value indicating whether the designer host diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ICustomTypeDescriptor.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ICustomTypeDescriptor.cs index aaec2986c1fa..58ae41a0a24a 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ICustomTypeDescriptor.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ICustomTypeDescriptor.cs @@ -78,5 +78,84 @@ public interface ICustomTypeDescriptor /// Gets the object that directly depends on this value being edited. /// object? GetPropertyOwner(PropertyDescriptor? pd); + + /// + /// Gets a type converter for this object that may be registered. + /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = TypeDescriptionProvider.ForwardFromRegisteredMessage)] + TypeConverter? GetConverterFromRegisteredType() + { + if (RequireRegisteredTypes is null) + { + if (TypeDescriptor.RequireRegisteredTypes) + { + TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetConverterFromRegisteredType)); + } + } + else if (RequireRegisteredTypes == true) + { + TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetConverterFromRegisteredType)); + } + + return GetConverter(); + } + + /// + /// Gets the events for this instance of a component that may be registered. + /// + EventDescriptorCollection GetEventsFromRegisteredType() + { + if (RequireRegisteredTypes is null) + { + if (TypeDescriptor.RequireRegisteredTypes) + { + TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetEventsFromRegisteredType)); + } + } + else if (RequireRegisteredTypes == true) + { + TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetEventsFromRegisteredType)); + } + + return GetEvents(); + } + + /// + /// Gets the properties for this instance of a component that may be registered. + /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = TypeDescriptionProvider.ForwardFromRegisteredMessage)] + PropertyDescriptorCollection GetPropertiesFromRegisteredType() + { + if (RequireRegisteredTypes is null) + { + if (TypeDescriptor.RequireRegisteredTypes) + { + TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetPropertiesFromRegisteredType)); + } + } + else if (RequireRegisteredTypes == true) + { + TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetPropertiesFromRegisteredType)); + } + + return GetProperties(); + } + + /// + /// Whether types are required to be registered through . + /// + /// + /// The default value is which means that the type descriptor has not declared whether or not it is compatible registered types. + /// A type descriptor needs to implement this to return either or if the feature switch + /// 'System.ComponentModel.TypeDescriptor.RequireRegisteredTypes' is enabled. + /// If is returned, then the type descriptor must also implement + /// , + /// , and + /// . + ///
    + ///
    + bool? RequireRegisteredTypes => null; } } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptor.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptor.cs index f21ddb67010e..23d05036265e 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptor.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptor.cs @@ -85,6 +85,47 @@ public virtual TypeConverter Converter } } + /// + /// Gets the type converter for this property. + /// + public virtual TypeConverter ConverterFromRegisteredType + { + get + { + // Always grab the attribute collection first here, because if the metadata version + // changes it will invalidate our type converter cache. + AttributeCollection attrs = Attributes; + + if (_converter == null) + { + TypeConverterAttribute attr = (TypeConverterAttribute)attrs[typeof(TypeConverterAttribute)]!; + if (attr.ConverterTypeName != null && attr.ConverterTypeName.Length > 0) + { + // We don't validate that the type is registered since the trimmer + // does not remove custom attributes that references the converter. + _converter = CreateConverterFromTypeName(attr); + } + + _converter ??= TypeDescriptor.GetConverterFromRegisteredType(PropertyType); + } + + return _converter; + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = "GetTypeFromName() can be called on a registered type.")] + TypeConverter? CreateConverterFromTypeName(TypeConverterAttribute attr) + { + Type? converterType = GetTypeFromName(attr.ConverterTypeName); + if (converterType != null && typeof(TypeConverter).IsAssignableFrom(converterType)) + { + return (TypeConverter?)CreateInstance(converterType)!; + } + + return null; + } + } + } + /// /// Gets a value /// indicating whether this property should be localized, as diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectEventDescriptor.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectEventDescriptor.cs index c1ccb9aabefe..0656f5fcd5b2 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectEventDescriptor.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectEventDescriptor.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; +using System.Runtime.InteropServices; namespace System.ComponentModel { @@ -101,6 +102,10 @@ public ReflectEventDescriptor( _realEvent = eventInfo; } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:UnrecognizedReflectionPattern", + Justification = "componentClass is annotated as preserve All members, so it can call ReflectEventDescriptor ctor.")] + internal static ReflectEventDescriptor CreateWithRegisteredType(Type componentClass, EventInfo eventInfo) => new ReflectEventDescriptor(componentClass, eventInfo); + /// /// This constructor takes an existing ReflectEventDescriptor and modifies it by merging in the /// passed-in attributes. diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectPropertyDescriptor.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectPropertyDescriptor.cs index 4aab33a85ab9..82b886c6d741 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectPropertyDescriptor.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectPropertyDescriptor.cs @@ -46,6 +46,8 @@ namespace System.ComponentModel /// internal sealed class ReflectPropertyDescriptor : PropertyDescriptor { + private const string ComponentClassIsProtected = "_componentClass is already a protected through [DynamicallyAccessedModifiers(All)] or is a registered type."; + private static readonly object s_noValue = new object(); private static readonly int s_bitDefaultValueQueried = InterlockedBitVector32.CreateMask(); @@ -60,7 +62,6 @@ internal sealed class ReflectPropertyDescriptor : PropertyDescriptor private static readonly int s_bitSetOnDemand = InterlockedBitVector32.CreateMask(s_bitAmbientValueQueried); private InterlockedBitVector32 _state; // Contains the state bits for this property descriptor. - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] private readonly Type _componentClass; // used to determine if we should all on us or on the designer private readonly Type _type; // the data type of the property private object? _defaultValue; // the default value of the property (or noValue) @@ -77,9 +78,8 @@ internal sealed class ReflectPropertyDescriptor : PropertyDescriptor /// /// The main constructor for ReflectPropertyDescriptors. /// - [RequiresUnreferencedCode(PropertyDescriptorPropertyTypeMessage)] public ReflectPropertyDescriptor( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentClass, + Type componentClass, string name, Type type, Attribute[]? attributes) @@ -111,11 +111,10 @@ public ReflectPropertyDescriptor( } /// - /// A constructor for ReflectPropertyDescriptors that have no attributes. + /// A constructor for ReflectPropertyDescriptors. /// - [RequiresUnreferencedCode(PropertyDescriptorPropertyTypeMessage)] public ReflectPropertyDescriptor( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentClass, + Type componentClass, string name, Type type, PropertyInfo propInfo, @@ -244,6 +243,8 @@ private object AmbientValue /// /// The EventDescriptor for the "{propertyname}Changed" event on the component, or null if there isn't one for this property. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2077:UnrecognizedReflectionPattern", + Justification = ComponentClassIsProtected)] private EventDescriptor ChangedEventValue { get @@ -316,6 +317,10 @@ private object DefaultValue /// /// The GetMethod for this property /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2077:UnrecognizedReflectionPattern", + Justification = ComponentClassIsProtected)] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2080:UnrecognizedReflectionPattern", + Justification = ComponentClassIsProtected)] private MethodInfo GetMethodValue { get @@ -370,6 +375,8 @@ private MethodInfo GetMethodValue /// /// Access to the reset method, if one exists for this property. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2077:UnrecognizedReflectionPattern", + Justification = ComponentClassIsProtected)] private MethodInfo? ResetMethodValue { get @@ -398,6 +405,12 @@ private MethodInfo? ResetMethodValue /// /// Accessor for the set method /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2077:UnrecognizedReflectionPattern", + Justification = ComponentClassIsProtected)] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", + Justification = ComponentClassIsProtected)] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2080:UnrecognizedReflectionPattern", + Justification = ComponentClassIsProtected)] private MethodInfo? SetMethodValue { get @@ -454,6 +467,8 @@ private MethodInfo? SetMethodValue /// /// Accessor for the ShouldSerialize method. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2077:UnrecognizedReflectionPattern", + Justification = ComponentClassIsProtected)] private MethodInfo? ShouldSerializeMethodValue { get @@ -727,6 +742,10 @@ public override bool CanResetValue(object component) [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072:UnrecognizedReflectionPattern", Justification = "ReflectPropertyDescriptor ctors are all marked as RequiresUnreferencedCode because PropertyType can't be annotated as 'All'.")] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", + Justification = ComponentClassIsProtected)] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2080:UnrecognizedReflectionPattern", + Justification = ComponentClassIsProtected)] protected override void FillAttributes(IList attributes) { Debug.Assert(_componentClass != null, "Must have a component class for FillAttributes"); @@ -895,7 +914,6 @@ protected override void FillAttributes(IList attributes) { component = GetInvocationTarget(_componentClass, component)!; - try { return GetMethodValue.Invoke(component, null); diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.ReflectedTypeData.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.ReflectedTypeData.cs index 6cd9c843a6f4..74820cc532c8 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.ReflectedTypeData.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.ReflectedTypeData.cs @@ -17,7 +17,6 @@ internal sealed partial class ReflectTypeDescriptionProvider : TypeDescriptionPr /// private sealed class ReflectedTypeData { - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] private readonly Type _type; private AttributeCollection? _attributes; private EventDescriptorCollection? _events; @@ -26,10 +25,12 @@ private sealed class ReflectedTypeData private object[]? _editors; private Type[]? _editorTypes; private int _editorCount; + private bool _isRegistered; - internal ReflectedTypeData([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) + internal ReflectedTypeData(Type type, bool isRegisteredType) { _type = type; + _isRegistered = isRegisteredType; } /// @@ -38,6 +39,8 @@ internal ReflectedTypeData([DynamicallyAccessedMembers(DynamicallyAccessedMember /// internal bool IsPopulated => (_attributes != null) | (_events != null) | (_properties != null); + internal bool IsRegistered => _isRegistered; + /// /// Retrieves custom attributes. /// @@ -95,7 +98,7 @@ internal AttributeCollection GetAttributes() // Next, walk the type's interfaces. We append these to // the attribute array as well. int ifaceStartIdx = attributes.Count; - Type[] interfaces = _type.GetInterfaces(); + Type[] interfaces = TrimSafeReflectionHelper.GetInterfaces(_type); for (int idx = 0; idx < interfaces.Length; idx++) { // Only do this for public interfaces. @@ -172,8 +175,13 @@ internal AttributeCollection GetAttributes() /// it will be used to retrieve attributes. Otherwise, _type /// will be used. ///
    - [RequiresUnreferencedCode("NullableConverter's UnderlyingType cannot be statically discovered. The Type of instance cannot be statically discovered.")] - internal TypeConverter GetConverter(object? instance) + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = "_type is annotated as preserve All members, so any Types returned from GetAttributes.")] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072:UnrecognizedReflectionPattern", + Justification = "_type is annotated as preserve All members, so any Types returned from CreateInstance.")] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2077:UnrecognizedReflectionPattern", + Justification = "_type is annotated as preserve All members, so any Types returned from GetAttributes.")] + internal TypeConverter GetConverter(object? instance, bool verifyIsRegisteredType) { TypeConverterAttribute? typeAttr = null; @@ -191,6 +199,11 @@ internal TypeConverter GetConverter(object? instance) Type? converterType = GetTypeFromName(instanceAttr.ConverterTypeName); if (converterType != null && typeof(TypeConverter).IsAssignableFrom(converterType)) { + if (verifyIsRegisteredType && !_isRegistered && !IsIntrinsicType(_type)) + { + TypeDescriptor.ThrowHelper.ThrowInvalidOperationException_RegisterTypeRequired(_type); + } + return (TypeConverter)ReflectTypeDescriptionProvider.CreateInstance(converterType, _type)!; } } @@ -215,10 +228,16 @@ internal TypeConverter GetConverter(object? instance) // We did not get a converter. Traverse up the base class chain until // we find one in the stock hashtable. _converter = GetIntrinsicTypeConverter(_type); + Debug.Assert(_converter != null, "There is no intrinsic setup in the hashtable for the Object type"); } } + if (verifyIsRegisteredType && !_isRegistered && !IsIntrinsicType(_type)) + { + TypeDescriptor.ThrowHelper.ThrowInvalidOperationException_RegisterTypeRequired(_type); + } + return _converter; } @@ -480,6 +499,10 @@ internal PropertyDescriptorCollection GetProperties() return _properties; } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "Before this method was called, the type was validated to be registered.")] + internal PropertyDescriptorCollection GetPropertiesFromRegisteredType() => GetProperties(); + /// /// Retrieves a type from a name. The Assembly of the type /// that this PropertyDescriptor came from is first checked, diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs index 5fc0d064f810..28beac41a7c2 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs @@ -22,31 +22,25 @@ namespace System.ComponentModel /// internal sealed partial class ReflectTypeDescriptionProvider : TypeDescriptionProvider { - // Hastable of Type -> ReflectedTypeData. ReflectedTypeData contains all - // of the type information we have gathered for a given type. - // - private Hashtable? _typeData; + // ReflectedTypeData contains all of the type information we have gathered for a given type. + private Dictionary? _typeData; // This is the signature we look for when creating types that are generic, but // want to know what type they are dealing with. Enums are a good example of this; // there is one enum converter that can work with all enums, but it needs to know // the type of enum it is dealing with. - // - private static readonly Type[] s_typeConstructor = new Type[] { typeof(Type) }; + private static readonly Type[] s_typeConstructor = { typeof(Type) }; // This is where we store the various converters, etc for the intrinsic types. - // private static Hashtable? s_editorTables; private static Dictionary? s_intrinsicTypeConverters; // For converters, etc that are bound to class attribute data, rather than a class // type, we have special key sentinel values that we put into the hash table. - // private static readonly object s_intrinsicReferenceKey = new object(); private static readonly object s_intrinsicNullableKey = new object(); // The key we put into IDictionaryService to store our cache dictionary. - // private static readonly object s_dictionaryKey = new object(); // This is a cache on top of core reflection. The cache @@ -54,7 +48,6 @@ internal sealed partial class ReflectTypeDescriptionProvider : TypeDescriptionPr // on Control, Component and object are also automatically filled // in. The keys to the property and event caches are types. // The keys to the attribute cache are either MemberInfos or types. - // private static Hashtable? s_propertyCache; private static Hashtable? s_eventCache; private static Hashtable? s_attributeCache; @@ -62,7 +55,6 @@ internal sealed partial class ReflectTypeDescriptionProvider : TypeDescriptionPr // These are keys we stuff into our object cache. We use this // cache data to store extender provider info for an object. - // private static readonly Guid s_extenderPropertiesKey = Guid.NewGuid(); private static readonly Guid s_extenderProviderPropertiesKey = Guid.NewGuid(); @@ -88,10 +80,8 @@ private static Type[] InitializeSkipInterfaceAttributeList() }; } - internal static Guid ExtenderProviderKey { get; } = Guid.NewGuid(); - private static readonly object s_internalSyncObject = new object(); /// /// Creates a new ReflectTypeDescriptionProvider. The type is the @@ -154,7 +144,6 @@ public TypeConverter GetOrCreateConverterInstance(Type innerType) /// private static Dictionary IntrinsicTypeConverters { - [RequiresUnreferencedCode("NullableConverter's UnderlyingType cannot be statically discovered.")] get { return LazyInitializer.EnsureInitialized(ref s_intrinsicTypeConverters, () => new Dictionary(32) @@ -228,7 +217,7 @@ internal static void ClearReflectionCaches() /// TypeDescriptor will search an editor /// table for the editor type, if one can be found. /// - [RequiresUnreferencedCode("The Types specified in table may be trimmed, or have their static construtors trimmed.")] + [RequiresUnreferencedCode("The Types specified in table may be trimmed, or have their static constructors trimmed.")] internal static void AddEditorTable(Type editorBaseType, Hashtable table) { ArgumentNullException.ThrowIfNull(editorBaseType); @@ -290,6 +279,18 @@ internal static void AddEditorTable(Type editorBaseType, Hashtable table) return obj ?? Activator.CreateInstance(objectType, args); } + public override bool? RequireRegisteredTypes => true; + public override bool IsRegisteredType(Type type) + { + if (_typeData != null && + _typeData.TryGetValue(type, out ReflectedTypeData? data) && + data.IsRegistered) + { + return true; + } + + return IsIntrinsicType(type); + } /// /// Helper method to create editors and type converters. This checks to see if the @@ -309,7 +310,7 @@ internal static void AddEditorTable(Type editorBaseType, Hashtable table) /// internal AttributeCollection GetAttributes([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) { - ReflectedTypeData td = GetTypeData(type, true)!; + ReflectedTypeData td = GetTypeData(type, createIfNeeded: true)!; return td.GetAttributes(); } @@ -346,6 +347,15 @@ internal AttributeCollection GetAttributes([DynamicallyAccessedMembers(Dynamical return td.GetClassName(); } + /// + /// Retrieves the class name for our type. + /// + internal string? GetClassNameFromRegisteredType(Type type) + { + ReflectedTypeData td = GetTypeDataFromRegisteredType(type); + return td.GetClassName(); + } + /// /// Retrieves the component name from the site. /// @@ -359,11 +369,16 @@ internal AttributeCollection GetAttributes([DynamicallyAccessedMembers(Dynamical /// it will be used to retrieve attributes. Otherwise, _type /// will be used. ///
    - [RequiresUnreferencedCode("NullableConverter's UnderlyingType cannot be statically discovered. The Type of instance cannot be statically discovered.")] internal TypeConverter GetConverter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, object? instance) { - ReflectedTypeData td = GetTypeData(type, true)!; - return td.GetConverter(instance); + ReflectedTypeData td = GetTypeData(type, createIfNeeded: true)!; + return td.GetConverter(instance, verifyIsRegisteredType: false); + } + + internal TypeConverter GetConverterFromRegisteredType(Type type, object? instance) + { + ReflectedTypeData td = GetTypeDataFromRegisteredType(type); + return td.GetConverter(instance, verifyIsRegisteredType: true); } /// @@ -383,7 +398,7 @@ internal TypeConverter GetConverter([DynamicallyAccessedMembers(DynamicallyAcces [RequiresUnreferencedCode(PropertyDescriptor.PropertyDescriptorPropertyTypeMessage + " The Type of instance cannot be statically discovered.")] internal PropertyDescriptor? GetDefaultProperty([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, object? instance) { - ReflectedTypeData td = GetTypeData(type, true)!; + ReflectedTypeData td = GetTypeData(type, createIfNeeded: true)!; return td.GetDefaultProperty(instance); } @@ -393,14 +408,14 @@ internal TypeConverter GetConverter([DynamicallyAccessedMembers(DynamicallyAcces [RequiresUnreferencedCode(TypeDescriptor.DesignTimeAttributeTrimmed + " The Type of instance cannot be statically discovered.")] internal object? GetEditor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, object? instance, Type editorBaseType) { - ReflectedTypeData td = GetTypeData(type, true)!; + ReflectedTypeData td = GetTypeData(type, createIfNeeded: true)!; return td.GetEditor(instance, editorBaseType); } /// /// Retrieves a default editor table for the given editor base type. /// - [RequiresUnreferencedCode("The Types specified in EditorTables may be trimmed, or have their static construtors trimmed.")] + [RequiresUnreferencedCode("The Types specified in EditorTables may be trimmed, or have their static constructors trimmed.")] private static Hashtable? GetEditorTable(Type editorBaseType) { Hashtable editorTables = EditorTables; @@ -453,6 +468,12 @@ internal EventDescriptorCollection GetEvents([DynamicallyAccessedMembers(Dynamic return td.GetEvents(); } + internal EventDescriptorCollection GetEventsFromRegisteredType(Type type) + { + ReflectedTypeData td = GetTypeDataFromRegisteredType(type); + return td.GetEvents(); + } + /// /// Retrieves custom extender attributes. We don't support /// extender attributes, so we always return an empty collection. @@ -510,7 +531,7 @@ internal TypeConverter GetExtendedConverter(object instance) /// /// Retrieves the editor for the given base type. /// - [RequiresUnreferencedCode(TypeDescriptor.DesignTimeAttributeTrimmed + " The Type of instance cannot be statically discovered.")] + [RequiresUnreferencedCode(TypeDescriptor.DesignTimeAttributeTrimmed + " The Type of instance cannot be statically discovered.")] internal object? GetExtendedEditor(object instance, Type editorBaseType) { return GetEditor(instance.GetType(), instance, editorBaseType); @@ -524,6 +545,13 @@ internal static EventDescriptorCollection GetExtendedEvents() return EventDescriptorCollection.Empty; } + /// + /// Retrieves the properties for this type. + /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "Instance is verified at run-time to be registered.")] + internal PropertyDescriptorCollection GetExtendedPropertiesFromRegisteredType(object instance) => GetExtendedProperties(instance); + /// /// Retrieves the properties for this type. /// @@ -799,6 +827,12 @@ public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) return null; } + public override ICustomTypeDescriptor? GetTypeDescriptorFromRegisteredType(Type objectType, object? instance) + { + Debug.Fail("This should never be invoked. TypeDescriptionNode should wrap for us."); + return null; + } + /// /// The name of the specified component, or null if the component has no name. /// In many cases this will return the same value as GetComponentName. If the @@ -831,18 +865,14 @@ internal Type[] GetPopulatedTypes(Module module) lock (s_internalSyncObject) { - Hashtable? typeData = _typeData; + Dictionary? typeData = _typeData; if (typeData != null) { - // Manual use of IDictionaryEnumerator instead of foreach to avoid DictionaryEntry box allocations. - IDictionaryEnumerator e = typeData.GetEnumerator(); - while (e.MoveNext()) + foreach (KeyValuePair kvp in typeData) { - DictionaryEntry de = e.Entry; - Type type = (Type)de.Key; - if (type.Module == module && ((ReflectedTypeData)de.Value!).IsPopulated) + if (kvp.Key.Module == module && kvp.Value!.IsPopulated) { - typeList.Add(type); + typeList.Add(kvp.Key); } } } @@ -857,10 +887,19 @@ internal Type[] GetPopulatedTypes(Module module) [RequiresUnreferencedCode(PropertyDescriptor.PropertyDescriptorPropertyTypeMessage)] internal PropertyDescriptorCollection GetProperties([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) { - ReflectedTypeData td = GetTypeData(type, true)!; + ReflectedTypeData td = GetTypeData(type, createIfNeeded: true)!; return td.GetProperties(); } + /// + /// Retrieves the properties for this type. + /// + internal PropertyDescriptorCollection GetPropertiesFromRegisteredType(Type type) + { + ReflectedTypeData td = GetTypeDataFromRegisteredType(type); + return td.GetPropertiesFromRegisteredType(); + } + /// /// Retrieves the owner for a property. /// @@ -891,26 +930,111 @@ public override Type GetReflectionType( { ReflectedTypeData? td = null; - if (_typeData != null) + if (_typeData != null && _typeData.TryGetValue(type, out td)) { - td = (ReflectedTypeData?)_typeData[type]; - if (td != null) + Debug.Assert(td != null); + return td; + } + + lock (s_internalSyncObject) + { + if (_typeData != null && _typeData.TryGetValue(type, out td)) { + Debug.Assert(td != null); + + if (TypeDescriptor.RequireRegisteredTypes && !td.IsRegistered && !IsIntrinsicType(type)) + { + TypeDescriptor.ThrowHelper.ThrowInvalidOperationException_RegisterTypeRequired(type); + } + return td; } + + if (TypeDescriptor.RequireRegisteredTypes && !IsIntrinsicType(type)) + { + // Since registering a type adds it to _typeData, this means the type was not registered. + TypeDescriptor.ThrowHelper.ThrowInvalidOperationException_RegisterTypeRequired(type); + } + + if (createIfNeeded) + { + td = new ReflectedTypeData(type, isRegisteredType: false); + _typeData ??= new Dictionary(); + _typeData[type] = td; + } + } + + return td; + } + + private ReflectedTypeData GetTypeDataFromRegisteredType(Type type) + { + if (_typeData == null || !_typeData.TryGetValue(type, out ReflectedTypeData? td)) + { + if (IsIntrinsicType(type)) + { + return GetOrRegisterType(type); + } + + // Since registering a type adds it to _typeData, this means the type was not registered. + TypeDescriptor.ThrowHelper.ThrowInvalidOperationException_RegisterTypeRequired(type); + td = null; + } + + if (!td.IsRegistered && !IsIntrinsicType(type)) + { + TypeDescriptor.ThrowHelper.ThrowInvalidOperationException_RegisterTypeRequired(type); + } + + return td; + } + + public override void RegisterType<[DynamicallyAccessedMembers(TypeDescriptor.RegisteredTypesDynamicallyAccessedMembers)] T>() + { + Type componentType = typeof(T); + ReflectedTypeData? td = null; + + if (_typeData != null && _typeData.ContainsKey(componentType)) + { + return; } lock (s_internalSyncObject) { - if (_typeData != null) + if (_typeData != null && _typeData.ContainsKey(componentType)) { - td = (ReflectedTypeData?)_typeData[type]; + return; } - if (td == null && createIfNeeded) + if (td == null) { - td = new ReflectedTypeData(type); - _typeData ??= new Hashtable(); + td = new ReflectedTypeData(componentType, isRegisteredType: true); + _typeData ??= new Dictionary(); + _typeData[componentType] = td; + } + } + } + + private ReflectedTypeData GetOrRegisterType(Type type) + { + ReflectedTypeData? td = null; + + if (_typeData != null && _typeData.TryGetValue(type, out td)) + { + return td; + } + + lock (s_internalSyncObject) + { + if (_typeData != null && _typeData.TryGetValue(type, out td)) + { + return td; + } + + if (td == null) + { + td = new ReflectedTypeData(type, isRegisteredType: true); + _typeData ??= new Dictionary(); _typeData[type] = td; } } @@ -1045,8 +1169,7 @@ internal static Attribute[] ReflectGetAttributes(MemberInfo member) /// Static helper API around reflection to get and cache /// events. This does not recurse to the base class. /// - private static EventDescriptor[] ReflectGetEvents( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) + private static EventDescriptor[] ReflectGetEvents(Type type) { Hashtable eventCache = EventCache; EventDescriptor[]? events = (EventDescriptor[]?)eventCache[type]; @@ -1069,7 +1192,7 @@ private static EventDescriptor[] ReflectGetEvents( // have both add and remove, we skip it here, because it // will be picked up in our base class scan. // - EventInfo[] eventInfos = type.GetEvents(bindingFlags); + EventInfo[] eventInfos = TrimSafeReflectionHelper.GetEvents(type, bindingFlags); events = new EventDescriptor[eventInfos.Length]; int eventCount = 0; @@ -1088,7 +1211,7 @@ private static EventDescriptor[] ReflectGetEvents( if (eventInfo.AddMethod != null && eventInfo.RemoveMethod != null) { - events[eventCount++] = new ReflectEventDescriptor(type, eventInfo); + events[eventCount++] = ReflectEventDescriptor.CreateWithRegisteredType(type, eventInfo); } } @@ -1223,7 +1346,15 @@ private static PropertyDescriptor[] ReflectGetExtendedProperties(IExtenderProvid /// [RequiresUnreferencedCode(PropertyDescriptor.PropertyDescriptorPropertyTypeMessage)] private static PropertyDescriptor[] ReflectGetProperties( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) => + ReflectGetPropertiesImpl(type); + + private static PropertyDescriptor[] ReflectGetPropertiesFromRegisteredType(Type type) + { + return ReflectGetPropertiesImpl(type); + } + + private static PropertyDescriptor[] ReflectGetPropertiesImpl(Type type) { Hashtable propertyCache = PropertyCache; PropertyDescriptor[]? properties = (PropertyDescriptor[]?)propertyCache[type]; @@ -1247,7 +1378,7 @@ private static PropertyDescriptor[] ReflectGetProperties( // "new" properties of the same name, so we must preserve // the member info for each method individually. // - PropertyInfo[] propertyInfos = type.GetProperties(bindingFlags); + PropertyInfo[] propertyInfos = TrimSafeReflectionHelper.GetProperties(type, bindingFlags); properties = new PropertyDescriptor[propertyInfos.Length]; int propertyCount = 0; @@ -1441,7 +1572,6 @@ internal void Refresh(Type type) /// The strongly-typed dictionary maps object types to converter data objects which lazily /// creates (and caches for re-use, where applicable) converter instances. /// - [RequiresUnreferencedCode("NullableConverter's UnderlyingType cannot be statically discovered.")] private static TypeConverter GetIntrinsicTypeConverter(Type callingType) { TypeConverter converter; @@ -1507,5 +1637,13 @@ private static TypeConverter GetIntrinsicTypeConverter(Type callingType) return converter; } + + private static bool IsIntrinsicType(Type callingType) + { + TypeConverter converter = GetIntrinsicTypeConverter(callingType); + + // If TypeConverter is returned, it fell back to the System.Object converter. + return (converter.GetType() != typeof(TypeConverter)); + } } } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TrimSafeReflectionHelper.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TrimSafeReflectionHelper.cs new file mode 100644 index 000000000000..ba2f4c42d9ae --- /dev/null +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TrimSafeReflectionHelper.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using System.Reflection; + +namespace System.ComponentModel +{ + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", + Justification = "Class is only called with types are are registered or protected with [DynamicallyAccessedMemberTypes].")] + internal static class TrimSafeReflectionHelper + { + public static PropertyInfo[] GetProperties(Type type, BindingFlags bindingAttr) => type.GetProperties(bindingAttr); + public static PropertyInfo? GetProperty(Type type, string name, BindingFlags bindingAttr) => type.GetProperty(name, bindingAttr); + public static EventInfo[] GetEvents(Type type, BindingFlags bindingAttr) => type.GetEvents(bindingAttr); + public static Type[] GetInterfaces(Type type) => type.GetInterfaces(); + } +} diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProvider.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProvider.cs index 83af65e55910..47b612f9a277 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProvider.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProvider.cs @@ -13,6 +13,8 @@ namespace System.ComponentModel ///
    public abstract class TypeDescriptionProvider { + internal const string ForwardFromRegisteredMessage = "Forwarding from a type provider that supports registered types to one that does not is supported."; + private readonly TypeDescriptionProvider? _parent; private EmptyCustomTypeDescriptor? _emptyDescriptor; @@ -41,6 +43,15 @@ protected TypeDescriptionProvider(TypeDescriptionProvider parent) _parent = parent; } + /// + /// Registers the type so it can be used by reflection-based providers in trimmed applications. + /// + /// The type to register. + public virtual void RegisterType<[DynamicallyAccessedMembers(TypeDescriptor.RegisteredTypesDynamicallyAccessedMembers)] T>() + { + // We allow this to be a no-op since the caller may not know if the provider supports known types. + } + /// /// This method is used to create an instance that can substitute for another /// data type. If the method is not interested in providing a substitute @@ -104,6 +115,30 @@ public virtual ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) return _emptyDescriptor ??= new EmptyCustomTypeDescriptor(); } + /// + /// This method returns an extended custom type descriptor for the given object. + /// An extended type descriptor is a custom type descriptor that offers properties + /// that other objects have added to this object, but are not actually defined on + /// the object. For example, in the .NET Framework Component Model, objects that + /// implement the interface IExtenderProvider can "attach" properties to other + /// objects that reside in the same logical container. The GetTypeDescriptor + /// method does not return a type descriptor that provides these extra extended + /// properties. GetExtendedTypeDescriptor returns the set of these extended + /// properties. TypeDescriptor will automatically merge the results of these + /// two property collections. Note that while the .NET Framework component + /// model only supports extended properties this API can be used for extended + /// attributes and events as well, if the type description provider supports it. + /// + public virtual ICustomTypeDescriptor GetExtendedTypeDescriptorFromRegisteredType(object instance) + { + if (_parent != null) + { + return _parent.GetExtendedTypeDescriptorFromRegisteredType(instance); + } + + return _emptyDescriptor ??= new EmptyCustomTypeDescriptor(); + } + protected internal virtual IExtenderProvider[] GetExtenderProviders(object instance) { if (_parent != null) @@ -259,6 +294,115 @@ public virtual Type GetRuntimeType(Type reflectionType) return _emptyDescriptor ??= new EmptyCustomTypeDescriptor(); } + /// + /// This method returns a custom type descriptor for the given type / object. + /// The objectType parameter is always valid, but the instance parameter may + /// be null if no instance was passed to TypeDescriptor. The method should + /// return a custom type descriptor for the object. If the method is not + /// interested in providing type information for the object it should + /// return base. + /// + public ICustomTypeDescriptor? GetTypeDescriptorFromRegisteredType(Type objectType) + { + ArgumentNullException.ThrowIfNull(objectType); + + if (_parent != null) + { + return _parent.GetTypeDescriptorFromRegisteredType(objectType); + } + + return GetTypeDescriptorFromRegisteredType(objectType, instance: null); + } + + /// + /// This method returns a custom type descriptor for the given type / object. + /// The objectType parameter is always valid, but the instance parameter may + /// be null if no instance was passed to TypeDescriptor. The method should + /// return a custom type descriptor for the object. If the method is not + /// interested in providing type information for the object it should + /// return base. + /// + public ICustomTypeDescriptor? GetTypeDescriptorFromRegisteredType(object instance) + { + ArgumentNullException.ThrowIfNull(instance); + + if (_parent != null) + { + return _parent.GetTypeDescriptorFromRegisteredType(instance); + } + + return GetTypeDescriptorFromRegisteredType(instance.GetType(), instance); + } + + /// + /// This method returns a custom type descriptor for the given type / object. + /// The objectType parameter is always valid, but the instance parameter may + /// be null if no instance was passed to TypeDescriptor. The method should + /// return a custom type descriptor for the object. If the method is not + /// interested in providing type information for the object it should + /// return base. + /// + /// This method is prototyped as virtual, and by default returns a + /// custom type descriptor that returns empty collections for all values + /// if no parent provider was passed. If a parent provider was passed, + /// this method will invoke the parent provider's GetTypeDescriptorFromRegisteredType + /// method. + /// + // This method doesn't contain [DynamicallyAccessedMembers(All)] unlike GetTypeDescriptor(type,object). It does this to + // prevent trim errors similar to other "FromRegisteredType" methods. However, unlike those other methods, + // it does not validate that the type is registered so it could be ubused by the caller. + // However, validation still occurs during subsequent calls to Get*FromRegisteredType() which validate that the type + // was registered and also for subsequent calls to Get*() for the reflection provider if the feature switch is on. + public virtual ICustomTypeDescriptor? GetTypeDescriptorFromRegisteredType(Type objectType, object? instance) + { + ArgumentNullException.ThrowIfNull(objectType); + + if (_parent != null) + { + return _parent.GetTypeDescriptorFromRegisteredType(objectType, instance); + } + + return Forward(); + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:UnrecognizedReflectionPattern", + Justification = TypeDescriptionProvider.ForwardFromRegisteredMessage)] + ICustomTypeDescriptor? Forward() => GetTypeDescriptor(objectType, instance); + } + + /// + /// Whether the provider uses reflection and requires types to be registered through + /// to support trimmed applications. For backwards compatibility, this is typically only enforced when calling members that have + /// a "FromRegisteredType" suffix. + /// + public virtual bool? RequireRegisteredTypes + { + get + { + if (_parent != null) + { + return _parent.RequireRegisteredTypes; + } + + return null; + } + } + + /// + /// Returns whether the type was registered with its provider through . + /// + /// If is null. + public virtual bool IsRegisteredType(Type type) + { + ArgumentNullException.ThrowIfNull(type); + + if (_parent != null) + { + return _parent.IsRegisteredType(type); + } + + return false; + } + /// /// This method returns true if the type is "supported" by the type descriptor /// and its chain of type description providers. diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs index 0e5bba3b7486..9cab702218a0 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; +using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel.Design; using System.Diagnostics; @@ -19,23 +20,48 @@ namespace System.ComponentModel /// public sealed class TypeDescriptor { - internal const DynamicallyAccessedMemberTypes ReflectTypesDynamicallyAccessedMembers = DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicFields; + internal const DynamicallyAccessedMemberTypes ReflectTypesDynamicallyAccessedMembers = + DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | + DynamicallyAccessedMemberTypes.PublicFields; + + internal const DynamicallyAccessedMemberTypes RegisteredTypesDynamicallyAccessedMembers = + DynamicallyAccessedMemberTypes.PublicConstructors | // For ReflectTypeDescriptionProvider.CreateInstance() + DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | + DynamicallyAccessedMemberTypes.PublicFields | // For enum field access + DynamicallyAccessedMemberTypes.Interfaces | // For ReflectedTypeData.GetAttributes() + DynamicallyAccessedMemberTypes.PublicProperties | // For GetProperties() + DynamicallyAccessedMemberTypes.PublicMethods | // For calling enum.ToObject() + DynamicallyAccessedMemberTypes.PublicEvents; // For GetEvents() + internal const string DesignTimeAttributeTrimmed = "Design-time attributes are not preserved when trimming. Types referenced by attributes like EditorAttribute and DesignerAttribute may not be available after trimming."; + [FeatureSwitchDefinition("System.ComponentModel.TypeDescriptor.IsComObjectDescriptorSupported")] + [FeatureGuard(typeof(RequiresUnreferencedCodeAttribute))] +#pragma warning disable IL4000 // MSBuild logic will ensure that the switch is disabled in trimmed scenarios. + internal static bool IsComObjectDescriptorSupported => AppContext.TryGetSwitch("System.ComponentModel.TypeDescriptor.IsComObjectDescriptorSupported", out bool isEnabled) ? isEnabled : true; +#pragma warning restore IL4000 + + // Mapping of type or object hash to a provider list. // Note: this is initialized at class load because we // lock on it for thread safety. It is used from nearly // every call to this class, so it will be created soon after // class load anyway. - private static readonly WeakHashtable s_providerTable = new WeakHashtable(); // mapping of type or object hash to a provider list - private static readonly Hashtable s_providerTypeTable = new Hashtable(); // A direct mapping from type to provider. + private static readonly WeakHashtable s_providerTable = new WeakHashtable(); + + // A direct mapping from type to provider. + private static readonly Dictionary s_providerTypeTable = new Dictionary(); + + // Tracks DefaultTypeDescriptionProviderAttributes. + // A value of `null` indicates initialization is in progress. + // A value of s_initializedDefaultProvider indicates the provider is initialized. + private static readonly Dictionary s_defaultProviderInitialized = new Dictionary(); - private static readonly Hashtable s_defaultProviderInitialized = new Hashtable(); // A table of type -> object to track DefaultTypeDescriptionProviderAttributes. - // A value of `null` indicates initialization is in progress. - // A value of s_initializedDefaultProvider indicates the provider is initialized. private static readonly object s_initializedDefaultProvider = new object(); private static WeakHashtable? s_associationTable; - private static int s_metadataVersion; // a version stamp for our metadata. Used by property descriptors to know when to rebuild attributes. + + // A version stamp for our metadata. Used by property descriptors to know when to rebuild attributes. + private static int s_metadataVersion; // This is an index that we use to create a unique name for a property in the // event of a name collision. The only time we should use this is when @@ -84,6 +110,16 @@ private TypeDescriptor() { } + /// + /// Registers the type so it can be used by reflection-based providers in trimmed applications. + /// + /// The type to register. + public static void RegisterType<[DynamicallyAccessedMembers(RegisteredTypesDynamicallyAccessedMembers)] T>() + { + TypeDescriptionNode node = NodeFor(typeof(T), createDelegator: false); + node.Provider.RegisterType(); + } + /// /// This property returns a Type object that can be passed to the various /// AddProvider methods to define a type description provider for interface types. @@ -107,6 +143,31 @@ public static Type InterfaceType /// public static event RefreshEventHandler? Refreshed; + private static readonly bool s_requireRegisteredTypes = + AppContext.TryGetSwitch( + switchName: "System.ComponentModel.TypeDescriptor.RequireRegisteredTypes", + isEnabled: out bool isEnabled) + ? isEnabled : false; + + /// + /// Indicates whether types require registration in order to be used with . + /// + /// + /// The value of the property is backed by the "System.ComponentModel.TypeDescriptor.RequireRegisteredTypes" + /// feature switch. + /// + [FeatureSwitchDefinition("System.ComponentModel.TypeDescriptor.RequireRegisteredTypes")] + internal static bool RequireRegisteredTypes => s_requireRegisteredTypes; + + internal static void ValidateRegisteredType(Type type) + { + TypeDescriptionProvider provider = GetProvider(type); + if (provider.RequireRegisteredTypes == true && !provider.IsRegisteredType(type)) + { + ThrowHelper.ThrowInvalidOperationException_RegisterTypeRequired(type); + } + } + /// /// The AddAttributes method allows you to add class-level attributes for a /// type or an instance. This method simply implements a type description provider @@ -158,7 +219,7 @@ public static TypeDescriptionProvider AddAttributes(object instance, params Attr /// an editor table for the editor type, if one can be found. /// [EditorBrowsable(EditorBrowsableState.Advanced)] - [RequiresUnreferencedCode("The Types specified in table may be trimmed, or have their static construtors trimmed.")] + [RequiresUnreferencedCode("The Types specified in table may be trimmed, or have their static constructors trimmed.")] public static void AddEditorTable(Type editorBaseType, Hashtable table) { ReflectTypeDescriptionProvider.AddEditorTable(editorBaseType, table); @@ -265,7 +326,7 @@ public static void AddProviderTransparent(TypeDescriptionProvider provider, obje /// private static void CheckDefaultProvider(Type type) { - if (s_defaultProviderInitialized[type] == s_initializedDefaultProvider) + if (s_defaultProviderInitialized.TryGetValue(type, out object? provider) && provider == s_initializedDefaultProvider) { return; } @@ -295,7 +356,7 @@ private static void AddDefaultProvider(Type type) // Immediately set this to null to indicate we are in progress setting the default provider for a type. // This prevents re-entrance to this method. - s_defaultProviderInitialized[type] = null; + s_defaultProviderInitialized.TryAdd(type, null); // Always use core reflection when checking for the default provider attribute. // If there is a provider, we probably don't want to build up our own cache state against the type. @@ -613,7 +674,7 @@ public static AttributeCollection GetAttributes([DynamicallyAccessedMembers(Dyna if (componentType == null) { Debug.Fail("COMPAT: Returning an empty collection, but you should not pass null here"); - return new AttributeCollection((Attribute[])null); + return new AttributeCollection(null); } AttributeCollection attributes = GetDescriptor(componentType, nameof(componentType)).GetAttributes(); @@ -781,6 +842,16 @@ public static TypeConverter GetConverter(object component, bool noCustomTypeDesc return converter; } + /// + /// Gets a type converter for the type of the specified component. + /// + public static TypeConverter GetConverterFromRegisteredType(object component) + { + TypeConverter? converter = GetDescriptorFromRegisteredType(component)!.GetConverterFromRegisteredType(); + Debug.Assert(converter != null, "Unexpected null TypeConverter."); + return converter; + } + /// /// Gets a type converter for the specified type. /// @@ -791,10 +862,18 @@ public static TypeConverter GetConverter([DynamicallyAccessedMembers(Dynamically } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "The callers of this method ensure getting the converter is trim compatible - i.e. the type is not Nullable.")] + Justification = "The callers of this method ensure getting the converter is trim compatible - i.e. the type is not Nullable.")] internal static TypeConverter GetConverterTrimUnsafe([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) => GetConverter(type); + /// + /// Gets a type converter for the specified registered type. + /// + public static TypeConverter GetConverterFromRegisteredType(Type type) + { + return GetDescriptorFromRegisteredType(type, nameof(type)).GetConverterFromRegisteredType(); + } + // This is called by System.ComponentModel.DefaultValueAttribute via reflection. [RequiresUnreferencedCode(TypeConverter.RequiresUnreferencedCodeMessage)] private static object? ConvertFromInvariantString([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, string stringValue) @@ -891,6 +970,20 @@ private static DefaultTypeDescriptor GetDescriptor( return NodeFor(type).GetDefaultTypeDescriptor(type); } + /// + /// Returns a custom type descriptor for the given type. + /// Performs arg checking so callers don't have to. + /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:UnrecognizedReflectionPattern", + Justification = "The type will be validated to see if it was registered.")] + private static DefaultTypeDescriptor GetDescriptorFromRegisteredType(Type type, + string typeName) + { + ArgumentNullException.ThrowIfNull(type, typeName); + + return NodeFor(type).GetDefaultTypeDescriptor(type); + } + /// /// Returns a custom type descriptor for the given instance. /// Performs arg checking so callers don't have to. This @@ -915,6 +1008,18 @@ private static DefaultTypeDescriptor GetDescriptor( return desc; } + internal static ICustomTypeDescriptor? GetDescriptorFromRegisteredType(object component) + { + ICustomTypeDescriptor? desc = NodeFor(component).GetTypeDescriptorFromRegisteredType(component); + ICustomTypeDescriptor? d = component as ICustomTypeDescriptor; + if (d != null) + { + desc = new MergedTypeDescriptor(d, desc!); + } + + return desc; + } + /// /// Returns an extended custom type descriptor for the given instance. /// @@ -929,6 +1034,16 @@ internal static ICustomTypeDescriptor GetExtendedDescriptor(object component) return NodeFor(component).GetExtendedTypeDescriptor(component); } + internal static ICustomTypeDescriptor GetExtendedDescriptorFromRegisteredType(object component) + { + if (component == null) + { + throw new ArgumentException(nameof(component)); + } + + return NodeFor(component).GetExtendedTypeDescriptorFromRegisteredType(component); + } + /// /// Gets an editor with the specified base type for the /// specified component. @@ -980,6 +1095,15 @@ public static EventDescriptorCollection GetEvents( return GetDescriptor(componentType, nameof(componentType))!.GetEvents(); } + /// + /// Gets a collection of events for a specified type of component. + /// + public static EventDescriptorCollection GetEventsFromRegisteredType(Type componentType) + { + ArgumentNullException.ThrowIfNull(componentType); + return GetDescriptorFromRegisteredType(componentType, nameof(componentType)).GetEventsFromRegisteredType(); + } + /// /// Gets a collection of events for a specified type of /// component using a specified array of attributes as a filter. @@ -1208,6 +1332,15 @@ public static PropertyDescriptorCollection GetProperties( return GetDescriptor(componentType, nameof(componentType)).GetProperties(); } + /// + /// Gets a collection of properties for a specified type. + /// + public static PropertyDescriptorCollection GetPropertiesFromRegisteredType(Type componentType) + { + ArgumentNullException.ThrowIfNull(componentType); + return GetDescriptorFromRegisteredType(componentType, nameof(componentType)).GetPropertiesFromRegisteredType(); + } + /// /// Gets a collection of properties for a specified type of /// component using a specified array of attributes as a filter. @@ -1248,6 +1381,14 @@ public static PropertyDescriptorCollection GetProperties(object component) return GetProperties(component, false); } + /// + /// Gets a collection of properties for a specified component. + /// + public static PropertyDescriptorCollection GetPropertiesFromRegisteredType(object component) + { + return GetPropertiesFromRegisteredTypeImpl(component); + } + /// /// Gets a collection of properties for a specified component. /// @@ -1380,7 +1521,6 @@ private static PropertyDescriptorCollection GetPropertiesImpl(object component, public static TypeDescriptionProvider GetProvider(Type type) { ArgumentNullException.ThrowIfNull(type); - return NodeFor(type, true); } @@ -1395,10 +1535,50 @@ public static TypeDescriptionProvider GetProvider(Type type) public static TypeDescriptionProvider GetProvider(object instance) { ArgumentNullException.ThrowIfNull(instance); - return NodeFor(instance, true); } + /// + /// This is a copy of the above GetPropertiesImpl but only for known types, + /// and without support for additional parameters. + /// + private static PropertyDescriptorCollection GetPropertiesFromRegisteredTypeImpl(object component) + { + ArgumentNullException.ThrowIfNull(component); + + ICustomTypeDescriptor typeDesc = GetDescriptorFromRegisteredType(component)!; + ICollection results; + + if (component is ICustomTypeDescriptor) + { + results = typeDesc.GetPropertiesFromRegisteredType(); + results = PipelineFilter(PIPELINE_PROPERTIES, results, component, null); + } + else + { + IDictionary? cache = GetCache(component); + results = typeDesc.GetPropertiesFromRegisteredType(); + results = PipelineInitialize(PIPELINE_PROPERTIES, results, cache); + ICustomTypeDescriptor extDesc = GetExtendedDescriptorFromRegisteredType(component); + if (extDesc != null) + { + ICollection extResults = extDesc.GetPropertiesFromRegisteredType(); + results = PipelineMerge(PIPELINE_PROPERTIES, results, extResults, cache); + } + + results = PipelineFilter(PIPELINE_PROPERTIES, results, component, cache); + } + + if (!(results is PropertyDescriptorCollection props)) + { + PropertyDescriptor[] propArray = new PropertyDescriptor[results.Count]; + results.CopyTo(propArray, 0); + props = new PropertyDescriptorCollection(propArray, true); + } + + return props; + } + /// /// This method returns a type description provider, but instead of creating /// a delegating provider for the type, this will walk all base types until @@ -1475,8 +1655,10 @@ private static TypeDescriptionNode NodeFor(Type type, bool createDelegator) while (node == null) { - node = (TypeDescriptionNode?)s_providerTypeTable[searchType] ?? - (TypeDescriptionNode?)s_providerTable[searchType]; + if (!s_providerTypeTable.TryGetValue(searchType, out node)) + { + node = (TypeDescriptionNode?)s_providerTable[searchType]; + } if (node == null) { @@ -1502,7 +1684,7 @@ private static TypeDescriptionNode NodeFor(Type type, bool createDelegator) node = new TypeDescriptionNode(new DelegatingTypeDescriptionProvider(baseType)); lock (s_providerTable) { - s_providerTypeTable[searchType] = node; + s_providerTypeTable.TryAdd(searchType, node); } } else @@ -1556,11 +1738,19 @@ private static TypeDescriptionNode NodeFor(object instance, bool createDelegator if (type.IsCOMObject) { + if (!IsComObjectDescriptorSupported) + { + throw new NotSupportedException(SR.ComObjectDescriptorsNotSupported); + } type = ComObjectType; } else if (OperatingSystem.IsWindows() && ComWrappers.TryGetComInstance(instance, out nint unknown)) { + if (!IsComObjectDescriptorSupported) + { + throw new NotSupportedException(SR.ComObjectDescriptorsNotSupported); + } // ComObjectType uses the Windows Forms provided ComNativeDescriptor. It currently has hard Win32 // API dependencies. Even though ComWrappers work with other platforms, restricting to Windows until // such time that the ComNativeDescriptor can handle basic COM types on other platforms. @@ -2338,6 +2528,7 @@ public static void Refresh(Assembly assembly) [EditorBrowsable(EditorBrowsableState.Advanced)] public static Type ComObjectType { + [RequiresUnreferencedCode("COM type descriptors are not trim-compatible.")] [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] get => typeof(TypeDescriptorComObject); } @@ -2385,6 +2576,7 @@ public static Type ComObjectType [DisallowNull] public static IComNativeDescriptorHandler? ComNativeDescriptorHandler { + [RequiresUnreferencedCode("COM type descriptors are not trim-compatible.")] get { TypeDescriptionNode? typeDescriptionNode = NodeFor(ComObjectType); @@ -2397,6 +2589,7 @@ public static IComNativeDescriptorHandler? ComNativeDescriptorHandler while (typeDescriptionNode != null && comNativeDescriptionProvider == null); return comNativeDescriptionProvider?.Handler; } + [RequiresUnreferencedCode("COM type descriptors are not trim-compatible.")] set { TypeDescriptionNode? typeDescriptionNode = NodeFor(ComObjectType); @@ -2850,6 +3043,11 @@ private sealed class ComNativeDescriptorProxy : TypeDescriptionProvider public ComNativeDescriptorProxy() { + if (!IsComObjectDescriptorSupported) + { + throw new NotSupportedException(SR.ComObjectDescriptorsNotSupported); + } + Type realComNativeDescriptor = Type.GetType("System.Windows.Forms.ComponentModel.Com2Interop.ComNativeDescriptor, System.Windows.Forms", throwOnError: true)!; _comNativeDescriptor = (TypeDescriptionProvider)Activator.CreateInstance(realComNativeDescriptor)!; } @@ -3082,6 +3280,24 @@ public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) return new DefaultExtendedTypeDescriptor(this, instance); } + /// + /// Implements GetExtendedTypeDescriptor. This creates a custom type + /// descriptor that walks the linked list for each of its calls. + /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The object is verified at run-time to be a registered type.")] + public override ICustomTypeDescriptor GetExtendedTypeDescriptorFromRegisteredType(object instance) + { + ArgumentNullException.ThrowIfNull(instance); + + Type type = instance.GetType(); + if (!Provider.IsRegisteredType(type)) + { + ThrowHelper.ThrowInvalidOperationException_RegisterTypeRequired(type); + } + + return new DefaultExtendedTypeDescriptor(this, instance); + } + protected internal override IExtenderProvider[] GetExtenderProviders(object instance) { ArgumentNullException.ThrowIfNull(instance); @@ -3143,6 +3359,31 @@ public override ICustomTypeDescriptor GetTypeDescriptor([DynamicallyAccessedMemb return new DefaultTypeDescriptor(this, objectType, instance); } + /// + /// Implements GetTypeDescriptor. This creates a custom type + /// descriptor that walks the linked list for each of its calls. + /// + public override ICustomTypeDescriptor GetTypeDescriptorFromRegisteredType(Type objectType, object? instance) + { + ArgumentNullException.ThrowIfNull(objectType); + + if (instance != null && !objectType.IsInstanceOfType(instance)) + { + throw new ArgumentException(nameof(instance)); + } + + if (!IsRegisteredType(objectType)) + { + ThrowHelper.ThrowInvalidOperationException_RegisterTypeRequired(objectType); + } + + return Forward(); + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:UnrecognizedReflectionPattern", + Justification = TypeDescriptionProvider.ForwardFromRegisteredMessage)] + ICustomTypeDescriptor Forward() => GetTypeDescriptor(objectType, instance); + } + internal DefaultTypeDescriptor GetDefaultTypeDescriptor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType) { return new DefaultTypeDescriptor(this, objectType, instance: null); @@ -3155,6 +3396,12 @@ public override bool IsSupportedType(Type type) return Provider.IsSupportedType(type); } + public override bool? RequireRegisteredTypes => Provider.RequireRegisteredTypes; + + public override bool IsRegisteredType(Type type) => Provider.IsRegisteredType(type); + + public override void RegisterType<[DynamicallyAccessedMembers(RegisteredTypesDynamicallyAccessedMembers)] T>() => Provider.RegisterType(); + /// /// A type descriptor for extended types. This type descriptor /// looks at the head node in the linked list. @@ -3263,6 +3510,28 @@ TypeConverter ICustomTypeDescriptor.GetConverter() return converter; } + /// + /// ICustomTypeDescriptor implementation. + /// + TypeConverter ICustomTypeDescriptor.GetConverterFromRegisteredType() + { + // Check to see if the provider we get is a ReflectTypeDescriptionProvider. + // If so, we can call on it directly rather than creating another + // custom type descriptor + + TypeDescriptionProvider p = _node.Provider; + if (p is ReflectTypeDescriptionProvider rp) + { + return rp.GetConverterFromRegisteredType(_instance.GetType(), _instance); + } + + ICustomTypeDescriptor? desc = p.GetTypeDescriptorFromRegisteredType(_instance); + if (desc == null) throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor")); + TypeConverter? converter = desc.GetConverterFromRegisteredType(); + if (converter == null) throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetConverter")); + return converter; + } + /// /// ICustomTypeDescriptor implementation. /// @@ -3348,6 +3617,27 @@ EventDescriptorCollection ICustomTypeDescriptor.GetEvents() return events; } + /// + /// ICustomTypeDescriptor implementation. + /// + EventDescriptorCollection ICustomTypeDescriptor.GetEventsFromRegisteredType() + { + // Check to see if the provider we get is a ReflectTypeDescriptionProvider. + // If so, we can call on it directly rather than creating another + // custom type descriptor + TypeDescriptionProvider p = _node.Provider; + if (p is ReflectTypeDescriptionProvider) + { + return ReflectTypeDescriptionProvider.GetExtendedEvents(); + } + + ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptorFromRegisteredType(_instance); + if (desc == null) throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptorFromRegisteredType")); + EventDescriptorCollection events = desc.GetEventsFromRegisteredType(); + if (events == null) throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetEventsFromRegisteredType")); + return events; + } + /// /// ICustomTypeDescriptor implementation. /// @@ -3397,6 +3687,27 @@ PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() return properties; } + /// + /// ICustomTypeDescriptor implementation. + /// + PropertyDescriptorCollection ICustomTypeDescriptor.GetPropertiesFromRegisteredType() + { + // Check to see if the provider we get is a ReflectTypeDescriptionProvider. + // If so, we can call on it directly rather than creating another + // custom type descriptor + TypeDescriptionProvider p = _node.Provider; + if (p is ReflectTypeDescriptionProvider rp) + { + return rp.GetExtendedPropertiesFromRegisteredType(_instance); + } + + ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptorFromRegisteredType(_instance); + if (desc == null) throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor")); + PropertyDescriptorCollection properties = desc.GetPropertiesFromRegisteredType(); + if (properties == null) throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetProperties")); + return properties; + } + /// /// ICustomTypeDescriptor implementation. /// @@ -3577,6 +3888,33 @@ public TypeConverter GetConverter() return converter; } + /// + /// ICustomTypeDescriptor implementation. + /// + public TypeConverter GetConverterFromRegisteredType() + { + // Check to see if the provider we get is a ReflectTypeDescriptionProvider. + // If so, we can call on it directly rather than creating another + // custom type descriptor + TypeDescriptionProvider p = _node.Provider; + TypeConverter? converter; + if (p is ReflectTypeDescriptionProvider rp) + { + converter = rp.GetConverterFromRegisteredType(_objectType, _instance); + } + else + { + ICustomTypeDescriptor? desc = p.GetTypeDescriptorFromRegisteredType(_objectType, _instance); + if (desc == null) + throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor")); + converter = desc.GetConverterFromRegisteredType(); + if (converter == null) + throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetConverterFromRegisteredType")); + } + + return converter; + } + /// /// ICustomTypeDescriptor implementation. /// @@ -3684,6 +4022,33 @@ public EventDescriptorCollection GetEvents() return events; } + /// + /// ICustomTypeDescriptor implementation. + /// + public EventDescriptorCollection GetEventsFromRegisteredType() + { + // Check to see if the provider we get is a ReflectTypeDescriptionProvider. + // If so, we can call on it directly rather than creating another + // custom type descriptor + TypeDescriptionProvider p = _node.Provider; + EventDescriptorCollection events; + if (p is ReflectTypeDescriptionProvider rp) + { + events = rp.GetEventsFromRegisteredType(_objectType); + } + else + { + ICustomTypeDescriptor? desc = p.GetTypeDescriptorFromRegisteredType(_objectType, _instance); + if (desc == null) + throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptorFromRegisteredType")); + events = desc.GetEventsFromRegisteredType(); + if (events == null) + throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetEventsFromRegisteredType")); + } + + return events; + } + /// /// ICustomTypeDescriptor implementation. /// @@ -3732,6 +4097,7 @@ public PropertyDescriptorCollection GetProperties() ICustomTypeDescriptor? desc = p.GetTypeDescriptor(_objectType, _instance); if (desc == null) throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor")); + properties = desc.GetProperties(); if (properties == null) throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetProperties")); @@ -3740,6 +4106,35 @@ public PropertyDescriptorCollection GetProperties() return properties; } + /// + /// ICustomTypeDescriptor implementation. + /// + public PropertyDescriptorCollection GetPropertiesFromRegisteredType() + { + // Check to see if the provider we get is a ReflectTypeDescriptionProvider. + // If so, we can call on it directly rather than creating another + // custom type descriptor + TypeDescriptionProvider p = _node.Provider; + PropertyDescriptorCollection properties; + if (p is ReflectTypeDescriptionProvider rp) + { + properties = rp.GetPropertiesFromRegisteredType(_objectType); + } + else + { + ICustomTypeDescriptor? desc = p.GetTypeDescriptorFromRegisteredType(_objectType, _instance); + if (desc == null) + throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor")); + + properties = desc.GetPropertiesFromRegisteredType(); + + if (properties == null) + throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetPropertiesFromRegisteredType")); + } + + return properties; + } + /// /// ICustomTypeDescriptor implementation. /// @@ -3771,7 +4166,7 @@ public PropertyDescriptorCollection GetProperties(Attribute[]? attributes) /// /// ICustomTypeDescriptor implementation. /// - object? ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor? pd) + public object? GetPropertyOwner(PropertyDescriptor? pd) { // Check to see if the provider we get is a ReflectTypeDescriptionProvider. // If so, we can call on it directly rather than creating another @@ -3801,5 +4196,16 @@ public PropertyDescriptorCollection GetProperties(Attribute[]? attributes) private sealed class TypeDescriptorInterface { } + + internal static class ThrowHelper + { + [DoesNotReturn] + internal static void ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(string memberName) => + throw new NotImplementedException(SR.Format(SR.CustomTypeProviderNotImplemented, memberName)); + + [DoesNotReturn] + internal static void ThrowInvalidOperationException_RegisterTypeRequired(Type type) => + throw new InvalidOperationException(SR.Format(SR.TypeIsNotRegistered, type.FullName)); + } } } diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/RegisteredTypesTests.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/RegisteredTypesTests.cs new file mode 100644 index 000000000000..371515eb0202 --- /dev/null +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/RegisteredTypesTests.cs @@ -0,0 +1,414 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.DotNet.RemoteExecutor; +using Xunit; +using static System.ComponentModel.Tests.TypeDescriptorTests; + +namespace System.ComponentModel.Tests +{ + public class RegisteredTypesTests + { + private const string TypeDescriptorRequireRegisteredTypesSwitchName = "System.ComponentModel.TypeDescriptor.RequireRegisteredTypes"; + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void ApplyResourcesToRegisteredType_NotRegistered() + { + RemoteExecutor.Invoke(() => + { + ComponentResourceManager resourceManager = new(typeof(global::Resources.TestResx)); + Assert.Throws(() => resourceManager.ApplyResourcesToRegisteredType(new C1(), "SomeName", null)); + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void ApplyResourcesToRegisteredType_Registered() + { + RemoteExecutor.Invoke(() => + { + TypeDescriptor.RegisterType(); + ComponentResourceManager resourceManager = new(typeof(global::Resources.TestResx)); + resourceManager.ApplyResourcesToRegisteredType(new C1(), "SomeName", null); + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void GetMembersWithRegisteredType_NotRegistered() + { + RemoteExecutor.Invoke(() => + { + // These throw even if we aren't trimming since we are calling RegisteredType APIs. + Assert.Throws(() => TypeDescriptor.GetPropertiesFromRegisteredType(typeof(C1))); + Assert.Throws(() => TypeDescriptor.GetEventsFromRegisteredType(typeof(C1))); + Assert.Throws(() => TypeDescriptor.GetConverterFromRegisteredType(typeof(C1))); + + // Intrinsic types do not need to be registered. + TypeDescriptor.GetPropertiesFromRegisteredType(typeof(string)); + TypeDescriptor.GetEventsFromRegisteredType(typeof(string)); + Assert.IsType(TypeDescriptor.GetConverterFromRegisteredType(typeof(string))); + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void GetMembers_NotRegistered_SwitchOn() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions[TypeDescriptorRequireRegisteredTypesSwitchName] = bool.TrueString; + + RemoteExecutor.Invoke(() => + { + TypeDescriptionProvider provider = TypeDescriptor.GetProvider(typeof(C1)); + Assert.Throws(() => TypeDescriptor.GetProperties(typeof(C1))); + Assert.Throws(() => TypeDescriptor.GetEvents(typeof(C1))); + Assert.Throws(() => TypeDescriptor.GetConverter(typeof(C1))); + }, options).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void GetMembers_NotRegistered() + { + RemoteExecutor.Invoke(() => + { + TypeDescriptionProvider provider = TypeDescriptor.GetProvider(typeof(C1)); + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(C1)); + Assert.Equal(2, properties.Count); + Assert.Equal("System.ComponentModel.Int32Converter", properties[0].Converter.ToString()); + Assert.Equal(2, TypeDescriptor.GetEvents(typeof(C1)).Count); + Assert.IsType(TypeDescriptor.GetConverter(typeof(C1))); + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void GetMembers_FromRegisteredType_Registered_FullCoverage() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions[TypeDescriptorRequireRegisteredTypesSwitchName] = bool.TrueString; + + RemoteExecutor.Invoke(() => + { + TypeDescriptor.RegisterType(); + TypeDescriptionProvider provider = TypeDescriptor.GetProvider(typeof(C1)); + + Test_PropertyDescriptorCollection(TypeDescriptor.GetPropertiesFromRegisteredType(typeof(C1))); + Test_PropertyDescriptorCollection(provider.GetTypeDescriptor(typeof(C1)).GetPropertiesFromRegisteredType()); + Test_PropertyDescriptorCollection(provider.GetTypeDescriptor(new C1()).GetPropertiesFromRegisteredType()); + Test_PropertyDescriptorCollection(provider.GetTypeDescriptor(typeof(C1), new C1()).GetPropertiesFromRegisteredType()); + + static void Test_PropertyDescriptorCollection(PropertyDescriptorCollection collection) + { + Assert.Equal(2, collection.Count); + Assert.Equal("System.ComponentModel.Int32Converter", collection[0].ConverterFromRegisteredType.ToString()); + } + + Test_EventDescriptorCollection(TypeDescriptor.GetEventsFromRegisteredType(typeof(C1))); + Test_EventDescriptorCollection(provider.GetTypeDescriptor(typeof(C1)).GetEventsFromRegisteredType()); + Test_EventDescriptorCollection(provider.GetTypeDescriptor(new C1()).GetEventsFromRegisteredType()); + Test_EventDescriptorCollection(provider.GetTypeDescriptor(typeof(C1), new C1()).GetEventsFromRegisteredType()); + + static void Test_EventDescriptorCollection(EventDescriptorCollection collection) + { + Assert.Equal(2, collection.Count); + } + + Test_GetConverter(TypeDescriptor.GetConverterFromRegisteredType(typeof(C1))); + Test_GetConverter(provider.GetTypeDescriptor(typeof(C1)).GetConverterFromRegisteredType()); + Test_GetConverter(provider.GetTypeDescriptor(new C1()).GetConverterFromRegisteredType()); + Test_GetConverter(provider.GetTypeDescriptor(typeof(C1), new C1()).GetConverterFromRegisteredType()); + static void Test_GetConverter(TypeConverter converter) + { + // The default type converter returns null. + Assert.Null(converter.GetProperties(null, new C1())); + } + + // C2 has a base class; base class properties are included. + TypeDescriptor.RegisterType(); + PropertyDescriptorCollection collection = TypeDescriptor.GetPropertiesFromRegisteredType(typeof(C2)); + Assert.Equal(2, collection.Count); + Assert.Equal("Bool", collection[0].Name); + Assert.Equal("String", collection[1].Name); + Assert.Equal("Base", collection[1].ComponentType.Name); + + // Since the base class is not explicitly registered, we throw on GetPropertiesFromRegisteredType(). + Assert.Throws(() => TypeDescriptor.GetPropertiesFromRegisteredType(typeof(Base))); + + }, options).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void TypeDescriptionProvider_RegisterType() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + + RemoteExecutor.Invoke(() => + { + TypeDescriptionProvider provider = TypeDescriptor.GetProvider(typeof(C1)); + + // Ensure RegisterType() forwards to the reflection provider (through TypeDescriptionNode and then DelegatingTypeDescriptionProvider) + provider.RegisterType(); + + PropertyDescriptorCollection properties = TypeDescriptor.GetPropertiesFromRegisteredType(typeof(C1)); + Assert.Equal(2, properties.Count); + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void GetMembersFromRegisteredType_ChildRegistered_SwitchOn() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions[TypeDescriptorRequireRegisteredTypesSwitchName] = bool.TrueString; + + RemoteExecutor.Invoke(() => + { + TypeDescriptor.RegisterType(); + TypeDescriptor.RegisterType(); + PropertyDescriptorCollection properties = TypeDescriptor.GetPropertiesFromRegisteredType(typeof(C1)); + Assert.Equal("Class", properties[1].Name); + Assert.Equal(2, properties[1].GetChildProperties().Count); + }, options).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void GetMembersFromRegisteredType_ChildUnregistered_SwitchOn() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions[TypeDescriptorRequireRegisteredTypesSwitchName] = bool.TrueString; + + RemoteExecutor.Invoke(() => + { + TypeDescriptor.RegisterType(); + PropertyDescriptorCollection properties = TypeDescriptor.GetPropertiesFromRegisteredType(typeof(C1)); + Assert.Equal("Class", properties[1].Name); + Assert.Throws(() => properties[1].GetChildProperties()); + }, options).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void GetMembersFromRegisteredType_BaseClassUnregistered_SwitchOn() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions[TypeDescriptorRequireRegisteredTypesSwitchName] = bool.TrueString; + + RemoteExecutor.Invoke(() => + { + TypeDescriptor.RegisterType(); + TypeDescriptor.RegisterType(); + + PropertyDescriptorCollection properties = TypeDescriptor.GetPropertiesFromRegisteredType(typeof(C1)); + Assert.Equal("Int32", properties[0].Name); + Assert.Equal("Class", properties[1].Name); + Assert.Equal(2, properties[1].GetChildProperties().Count); + Assert.Equal("Bool", properties[1].GetChildProperties()[0].Name); + + // Even though C1.Class.Base is not explictely registered, we should still be able to get the properties of Base. + Assert.Equal("String", properties[1].GetChildProperties()[1].Name); + }, options).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void GetPropertiesFromRegisteredTypeInstance() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + + RemoteExecutor.Invoke(() => + { + TypeDescriptor.RegisterType(); + TypeDescriptor.RegisterType(); + + PropertyDescriptorCollection properties = TypeDescriptor.GetPropertiesFromRegisteredType(new C1()); + Assert.Equal("Int32", properties[0].Name); + Assert.Equal("Class", properties[1].Name); + Assert.Equal(2, properties[1].GetChildProperties().Count); + Assert.Equal("Bool", properties[1].GetChildProperties()[0].Name); + + // Even though C1.Class.Base is not explictely registered, we should still be able to get the properties of Base. + Assert.Equal("String", properties[1].GetChildProperties()[1].Name); + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void GetPropertiesFromRegisteredTypeInstance_Trimmed() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions[TypeDescriptorRequireRegisteredTypesSwitchName] = bool.TrueString; + + RemoteExecutor.Invoke(() => + { + GetPropertiesFromRegisteredTypeInstance(); + }, options).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void GetPropertiesFromRegisteredTypeInstance_Unregistered_Trimmed() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions[TypeDescriptorRequireRegisteredTypesSwitchName] = bool.TrueString; + + RemoteExecutor.Invoke(() => + { + Assert.Throws(() => TypeDescriptor.GetPropertiesFromRegisteredType(new C1())); + }, options).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void LegacyProviders_ThrowOnFeatureSwitch_ICustomTypeDescriptor() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions[TypeDescriptorRequireRegisteredTypesSwitchName] = bool.TrueString; + + RemoteExecutor.Invoke(() => + { + EmptyPropertiesTypeProvider provider = new(); + + // This uses the ICustomTypeDescriptor DIM implementation. + Test(provider.GetTypeDescriptor(typeof(C1))); + + // This uses the CustomTypeDescriptor implementation. + Test(new EmptyCustomTypeDescriptor()); + + void Test(ICustomTypeDescriptor ictd) + { + Exception ex; + + ex = Assert.Throws(() => ictd.GetPropertiesFromRegisteredType()); + Assert.Contains("GetPropertiesFromRegisteredType", ex.Message); + + ex = Assert.Throws(() => ictd.GetEventsFromRegisteredType()); + Assert.Contains("GetEventsFromRegisteredType", ex.Message); + + ex = Assert.Throws(() => ictd.GetConverterFromRegisteredType()); + Assert.Contains("GetConverterFromRegisteredType", ex.Message); + } + }, options).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void LegacyProviders_DotNotThrowWhenNoFeatureSwitch() + { + RemoteExecutor.Invoke(() => + { + EmptyPropertiesTypeProvider provider = new(); + + // This uses the ICustomTypeDescriptor DIM implementation. + Test(provider.GetTypeDescriptor(typeof(C1))); + + // This uses the CustomTypeDescriptor implementation. + Test(new EmptyCustomTypeDescriptor()); + + void Test(ICustomTypeDescriptor ictd) + { + ictd.GetPropertiesFromRegisteredType(); + ictd.GetEventsFromRegisteredType(); + ictd.GetConverterFromRegisteredType(); + } + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void GetProviderWithInstance_Registered() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions[TypeDescriptorRequireRegisteredTypesSwitchName] = bool.TrueString; + + RemoteExecutor.Invoke(() => + { + TypeDescriptor.RegisterType(); + C1 obj = new C1(); + TypeDescriptionProvider provider = TypeDescriptor.GetProvider(obj); + Assert.NotNull(provider); + + ICustomTypeDescriptor instanceDescriptor = provider.GetExtendedTypeDescriptor(obj); + Assert.Equal(0, instanceDescriptor.GetProperties().Count); + Assert.Throws(() => instanceDescriptor.GetPropertiesFromRegisteredType().Count); + Assert.Equal(0, instanceDescriptor.GetEvents().Count); + Assert.Throws(() => instanceDescriptor.GetEventsFromRegisteredType().Count); + Assert.NotNull(instanceDescriptor.GetConverterFromRegisteredType()); + + instanceDescriptor = provider.GetTypeDescriptor(obj); + Assert.Equal(2, instanceDescriptor.GetProperties().Count); + Assert.Equal(2, instanceDescriptor.GetPropertiesFromRegisteredType().Count); + Assert.Equal(2, instanceDescriptor.GetEvents().Count); + Assert.Equal(2, instanceDescriptor.GetEventsFromRegisteredType().Count); + Assert.NotNull(instanceDescriptor.GetConverterFromRegisteredType()); + }, options).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void VerifyNullableUnderlying_Registered() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions[TypeDescriptorRequireRegisteredTypesSwitchName] = bool.TrueString; + + RemoteExecutor.Invoke(() => + { + TypeDescriptor.RegisterType(); + TypeDescriptor.RegisterType(); + + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(GetType_ClassWithGenericProperty()); + Assert.Equal(1, properties.Count); + Assert.Equal("NullableStruct", properties[0].Name); + Assert.NotNull(properties[0].Converter); + + static Type GetType_ClassWithGenericProperty() => typeof(ClassWithGenericProperty); + }, options).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void VerifyNullableUnderlying_NotRegistered() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions[TypeDescriptorRequireRegisteredTypesSwitchName] = bool.TrueString; + + RemoteExecutor.Invoke(() => + { + TypeDescriptor.RegisterType(); + + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(GetType_ClassWithGenericProperty()); + Assert.Equal(1, properties.Count); + Assert.Equal("NullableStruct", properties[0].Name); + + Assert.Throws(() => properties[0].Converter); + + static Type GetType_ClassWithGenericProperty() => typeof(ClassWithGenericProperty); + }, options).Dispose(); + } + + internal class MyStruct + { + } + + class ClassWithGenericProperty + { + public MyStruct? NullableStruct { get; set; } + } + + private sealed class EmptyCustomTypeDescriptor : CustomTypeDescriptor { } + + private class C1 + { + public int Int32 { get; set; } + public C2 Class { get; set; } + + public event EventHandler E1 + { + add => throw new NotImplementedException(); + remove => throw new NotImplementedException(); + } + + public event EventHandler E2 + { + add => throw new NotImplementedException(); + remove => throw new NotImplementedException(); + } + } + + private class C2 : Base + { + public bool Bool { get; set; } + } + + private class Base + { + public string String { get; set; } + } + } +} diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/System.ComponentModel.TypeConverter.Tests.csproj b/src/libraries/System.ComponentModel.TypeConverter/tests/System.ComponentModel.TypeConverter.Tests.csproj index b5e7125f3091..6abc8b4552ef 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/tests/System.ComponentModel.TypeConverter.Tests.csproj +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/System.ComponentModel.TypeConverter.Tests.csproj @@ -120,6 +120,7 @@ + @@ -159,8 +160,7 @@ - + diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/System.ComponentModel.TypeConverter.TrimmingTests.proj b/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/System.ComponentModel.TypeConverter.TrimmingTests.proj index b60e51f170cb..ecd2a44e3df3 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/System.ComponentModel.TypeConverter.TrimmingTests.proj +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/System.ComponentModel.TypeConverter.TrimmingTests.proj @@ -6,6 +6,14 @@ + + System.ComponentModel.TypeDescriptor.RequireRegisteredTypes + + + System.ComponentModel.TypeDescriptor.RequireRegisteredTypes + + + diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeDescriptorTest_FeatureSwitch_Registered.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeDescriptorTest_FeatureSwitch_Registered.cs new file mode 100644 index 000000000000..102a8a7f06e9 --- /dev/null +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeDescriptorTest_FeatureSwitch_Registered.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. + +using System; +using System.Collections; +using System.ComponentModel; + +/// +/// Tests that the properties are preserved in a trimmed application. +/// +class Program +{ + public static int s_usedProperty; + + static int Main(string[] args) + { + var c1 = new ClassWithUsedProperties(); + s_usedProperty = c1.P1; + s_usedProperty = c1.P2; + s_usedProperty = c1.P3; + + if (!RunTest(targetType: typeof(ClassWithUnusedProperties), expectedPropertyCount: 3)) + { + return -1; + } + + if (!RunTest(targetType: typeof(ClassWithUsedProperties), expectedPropertyCount: 3)) + { + return -2; + } + + return 100; + } + + private static bool RunTest(Type targetType, int expectedPropertyCount) + { + TypeDescriptor.RegisterType(); + TypeDescriptor.RegisterType(); + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(targetType); + return (properties.Count == expectedPropertyCount); + } + + private class ClassWithUnusedProperties : BaseClass + { + public int P1 { get; set; } + public int P2 { get; set; } + } + + private class ClassWithUsedProperties : BaseClass + { + public int P1 { get; set; } + public int P2 { get; set; } + } + + private class BaseClass + { + public int P3 { get; set; } + } +} diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeDescriptorTest_FeatureSwitch_Unregistered.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeDescriptorTest_FeatureSwitch_Unregistered.cs new file mode 100644 index 000000000000..d2ce27854c76 --- /dev/null +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeDescriptorTest_FeatureSwitch_Unregistered.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. + +using System; +using System.ComponentModel; + +/// +/// Tests that the properties are preserved in a trimmed application. +/// +class Program +{ + public static int s_usedProperty; + + static int Main(string[] args) + { + var c1 = new ClassWithUsedProperties(); + s_usedProperty = c1.P1; + s_usedProperty = c1.P2; + + if (!RunTest(targetType: typeof(ClassWithUnusedProperties))) + { + return -1; + } + + if (!RunTest(targetType: typeof(ClassWithUsedProperties))) + { + return -2; + } + + return 100; + } + + private static bool RunTest(Type targetType) + { + try + { + // The feature switch is on so InvalidOperationException should be thrown. + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(targetType); + } + catch (InvalidOperationException) + { + return true; + } + + return false; + } + + private class ClassWithUnusedProperties + { + public int P1 { get; set; } + public int P2 { get; set; } + } + + private class ClassWithUsedProperties + { + public int P1 { get; set; } + public int P2 { get; set; } + } +} diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeDescriptorTest_Registered.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeDescriptorTest_Registered.cs new file mode 100644 index 000000000000..235af8b341ac --- /dev/null +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeDescriptorTest_Registered.cs @@ -0,0 +1,90 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.ComponentModel; + +/// +/// Tests that the properties are preserved in a trimmed application. +/// +class Program +{ + public static int s_usedProperty; + + static int Main(string[] args) + { + var c1 = new ClassWithUsedProperties(); + s_usedProperty = c1.P1; + s_usedProperty = c1.P2; + + if (!RunTest(targetType: typeof(ClassWithUnusedProperties), expectedPropertyCount: 2, expectedAttributeCount: 0, expectedEventCount: 0)) + { + return -1; + } + + if (!RunTest(targetType: typeof(ClassWithUsedProperties), expectedPropertyCount: 2, expectedAttributeCount: 0, expectedEventCount: 0)) + { + return -2; + } + + if (!RunTest(targetType: typeof(ClassWithAttribute), expectedPropertyCount: 0, expectedAttributeCount: 1, expectedEventCount: 0)) + { + return -3; + } + + if (!RunTest(targetType: typeof(ClassWithEvent), expectedPropertyCount: 0, expectedAttributeCount: 0, expectedEventCount: 1)) + { + return -4; + } + + return 100; + } + + private static bool RunTest(Type targetType, int expectedPropertyCount, int expectedAttributeCount, int expectedEventCount) + { + TypeDescriptor.RegisterType(); + TypeDescriptor.RegisterType(); + TypeDescriptor.RegisterType(); + // ClassWithAttribute is not registered; trimmer does not remove attributes. + + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(targetType); + if (properties.Count != expectedPropertyCount) + { + return false; + } + + AttributeCollection attributes = TypeDescriptor.GetAttributes(targetType); + if (attributes.Count != expectedAttributeCount) + { + return false; + } + + EventDescriptorCollection events = TypeDescriptor.GetEvents(targetType); + return (events.Count == expectedEventCount); + } + + private class ClassWithUnusedProperties + { + public int P1 { get; set; } + public int P2 { get; set; } + } + + private class ClassWithUsedProperties + { + public int P1 { get; set; } + public int P2 { get; set; } + } + + [MyCustom] + private class ClassWithAttribute { } + + [AttributeUsage(AttributeTargets.All)] + private class MyCustomAttribute : Attribute { } + + private class ClassWithEvent + { +#pragma warning disable CS0067 // The event is never used + public event EventHandler MyEvent; +#pragma warning restore CS0067 + } +} diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeDescriptorTest_Unregistered.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeDescriptorTest_Unregistered.cs new file mode 100644 index 000000000000..a983ca7809b6 --- /dev/null +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeDescriptorTest_Unregistered.cs @@ -0,0 +1,71 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.ComponentModel; + +/// +/// Tests that the properties are preserved in a trimmed application. +/// +class Program +{ + static int Main(string[] args) + { + if (!RunTest(targetType: typeof(ClassWithUnusedProperties), expectedPropertyCount: 0, expectedAttributeCount: 0, expectedEventCount: 0)) + { + return -1; + } + + if (!RunTest(targetType: typeof(ClassWithAttribute), expectedPropertyCount: 0, expectedAttributeCount: 1, expectedEventCount: 0)) + { + return -2; + } + + if (!RunTest(targetType: typeof(ClassWithEvent), expectedPropertyCount: 0, expectedAttributeCount: 0, expectedEventCount: 0)) + { + return -3; + } + + return 100; + } + + private static bool RunTest(Type targetType, int expectedPropertyCount, int expectedAttributeCount, int expectedEventCount) + { + // Some properties may be missing, but since the feature switch is off there is no InvalidOperationException. + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(targetType); + if (properties.Count != expectedPropertyCount) + { + return false; + } + + // Attributes are preserved. + AttributeCollection attributes = TypeDescriptor.GetAttributes(targetType); + if (attributes.Count != expectedAttributeCount) + { + return false; + } + + // Events are not preserved. + EventDescriptorCollection events = TypeDescriptor.GetEvents(targetType); + return (events.Count == expectedEventCount); + } + + private class ClassWithUnusedProperties + { + public int P1 { get; set; } + public int P2 { get; set; } + } + + [MyCustom] + private class ClassWithAttribute { } + + [AttributeUsage(AttributeTargets.All)] + private class MyCustomAttribute : Attribute { } + + private class ClassWithEvent + { +#pragma warning disable CS0067 // The event is never used + public event EventHandler MyEvent; +#pragma warning restore CS0067 + } +} diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/TypeDescriptionProviderTests.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/TypeDescriptionProviderTests.cs index 2044bd44b47b..5e840c0a4476 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/tests/TypeDescriptionProviderTests.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/TypeDescriptionProviderTests.cs @@ -48,6 +48,9 @@ public void CreateInstance_InvokeWithParent_ReturnsExpected(IServiceProvider ser .Setup(p => p.CreateInstance(serviceProvider, objectType, argTypes, args)) .Returns(result) .Verifiable(); + mockParentProvider + .Setup(p => p.RequireRegisteredTypes) + .CallBase(); var provider = new SubTypeDescriptionProvider(mockParentProvider.Object); Assert.Same(result, provider.CreateInstance(serviceProvider, objectType, argTypes, args)); mockParentProvider.Verify(p => p.CreateInstance(serviceProvider, objectType, argTypes, args), Times.Once()); @@ -598,6 +601,9 @@ public void GetTypeDescriptor_InvokeTypeWithoutParent_CallsTypeObjectOverload_Ty mockProvider .Setup(p => p.GetTypeDescriptor(objectType, null)) .CallBase(); + mockProvider + .Setup(p => p.RequireRegisteredTypes) + .CallBase(); TypeDescriptionProvider provider = mockProvider.Object; CustomTypeDescriptor result1 = Assert.IsAssignableFrom(provider.GetTypeDescriptor(objectType)); Assert.Empty(result1.GetProperties()); @@ -660,6 +666,9 @@ public void GetTypeDescriptor_InvokeTypeWithoutParent_CallsTypeObjectOverload_Ob mockProvider .Setup(p => p.GetTypeDescriptor(instance.GetType(), instance)) .CallBase(); + mockProvider + .Setup(p => p.RequireRegisteredTypes) + .CallBase(); TypeDescriptionProvider provider = mockProvider.Object; CustomTypeDescriptor result1 = Assert.IsAssignableFrom(provider.GetTypeDescriptor(instance)); Assert.Empty(result1.GetProperties()); diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/TypeDescriptorTests.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/TypeDescriptorTests.cs index 193dcba83359..a9b6a2cd7091 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/tests/TypeDescriptorTests.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/TypeDescriptorTests.cs @@ -26,6 +26,10 @@ public void AddProvider_InvokeObject_GetProviderReturnsExpected() .Setup(p => p.IsSupportedType(typeof(int))) .Returns(true) .Verifiable(); + mockProvider1 + .Setup(p => p.RequireRegisteredTypes) + .Returns(false) + .Verifiable(); var mockProvider2 = new Mock(MockBehavior.Strict); mockProvider2 .Setup(p => p.IsSupportedType(typeof(int))) @@ -34,6 +38,10 @@ public void AddProvider_InvokeObject_GetProviderReturnsExpected() mockProvider2 .Setup(p => p.GetCache(instance)) .Returns(new Dictionary()); + mockProvider2 + .Setup(p => p.RequireRegisteredTypes) + .Returns(false) + .Verifiable(); TypeDescriptor.AddProvider(mockProvider1.Object, instance); TypeDescriptionProvider actualProvider1 = TypeDescriptor.GetProvider(instance); @@ -218,6 +226,10 @@ public void AddProviderTransparent_InvokeObject_GetProviderReturnsExpected() .Setup(p => p.IsSupportedType(typeof(int))) .Returns(true) .Verifiable(); + mockProvider1 + .Setup(p => p.RequireRegisteredTypes) + .Returns(false) + .Verifiable(); var mockProvider2 = new Mock(MockBehavior.Strict); mockProvider2 .Setup(p => p.IsSupportedType(typeof(int))) @@ -226,6 +238,10 @@ public void AddProviderTransparent_InvokeObject_GetProviderReturnsExpected() mockProvider2 .Setup(p => p.GetCache(instance)) .Returns(new Dictionary()); + mockProvider2 + .Setup(p => p.RequireRegisteredTypes) + .Returns(false) + .Verifiable(); TypeDescriptor.AddProviderTransparent(mockProvider1.Object, instance); TypeDescriptionProvider actualProvider1 = TypeDescriptor.GetProvider(instance); @@ -564,6 +580,10 @@ public void RemoveProvider_InvokeObject_RemovesProvider() .Setup(p => p.IsSupportedType(typeof(int))) .Returns(true) .Verifiable(); + mockProvider1 + .Setup(p => p.RequireRegisteredTypes) + .Returns(false) + .Verifiable(); var mockProvider2 = new Mock(MockBehavior.Strict); mockProvider2 .Setup(p => p.GetCache(instance)) @@ -572,6 +592,10 @@ public void RemoveProvider_InvokeObject_RemovesProvider() .Setup(p => p.IsSupportedType(typeof(int))) .Returns(true) .Verifiable(); + mockProvider2 + .Setup(p => p.RequireRegisteredTypes) + .Returns(false) + .Verifiable(); var mockProvider3 = new Mock(MockBehavior.Strict); mockProvider3 .Setup(p => p.GetCache(instance)) @@ -580,6 +604,10 @@ public void RemoveProvider_InvokeObject_RemovesProvider() .Setup(p => p.IsSupportedType(typeof(int))) .Returns(true) .Verifiable(); + mockProvider3 + .Setup(p => p.RequireRegisteredTypes) + .Returns(false) + .Verifiable(); TypeDescriptor.AddProvider(mockProvider1.Object, instance); TypeDescriptor.AddProvider(mockProvider2.Object, instance); @@ -826,6 +854,10 @@ public void RemoveProviderTransparent_InvokeObject_RemovesProvider() .Setup(p => p.IsSupportedType(typeof(int))) .Returns(true) .Verifiable(); + mockProvider1 + .Setup(p => p.RequireRegisteredTypes) + .Returns(false) + .Verifiable(); var mockProvider2 = new Mock(MockBehavior.Strict); mockProvider2 .Setup(p => p.GetCache(instance)) @@ -834,6 +866,10 @@ public void RemoveProviderTransparent_InvokeObject_RemovesProvider() .Setup(p => p.IsSupportedType(typeof(int))) .Returns(true) .Verifiable(); + mockProvider2 + .Setup(p => p.RequireRegisteredTypes) + .Returns(false) + .Verifiable(); var mockProvider3 = new Mock(MockBehavior.Strict); mockProvider3 .Setup(p => p.GetCache(instance)) @@ -842,6 +878,10 @@ public void RemoveProviderTransparent_InvokeObject_RemovesProvider() .Setup(p => p.IsSupportedType(typeof(int))) .Returns(true) .Verifiable(); + mockProvider3 + .Setup(p => p.RequireRegisteredTypes) + .Returns(false) + .Verifiable(); TypeDescriptor.AddProvider(mockProvider1.Object, instance); TypeDescriptor.AddProvider(mockProvider2.Object, instance); diff --git a/src/libraries/System.Composition.Convention/src/System/Composition/Convention/PartConventionBuilder.cs b/src/libraries/System.Composition.Convention/src/System/Composition/Convention/PartConventionBuilder.cs index fa7b93bc989b..76b0efd4898e 100644 --- a/src/libraries/System.Composition.Convention/src/System/Composition/Convention/PartConventionBuilder.cs +++ b/src/libraries/System.Composition.Convention/src/System/Composition/Convention/PartConventionBuilder.cs @@ -35,7 +35,7 @@ public class PartConventionBuilder private readonly List, Action>> _interfaceExports; private readonly List> _methodImportsSatisfiedNotifications; - internal Predicate SelectType { get; private set; } + internal Predicate SelectType { get; } internal PartConventionBuilder(Predicate selectType) { diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationLockCollection.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationLockCollection.cs index de0d3af555f8..8f5c8c9f37c3 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationLockCollection.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationLockCollection.cs @@ -220,7 +220,7 @@ internal bool DefinedInParent(string name) string parentListEnclosed = "," + _seedList + ","; if (name.Equals(_ignoreName) || -#if NETCOREAPP +#if NET parentListEnclosed.Contains("," + name + ",", StringComparison.Ordinal)) #else parentListEnclosed.IndexOf("," + name + ",", StringComparison.Ordinal) >= 0) diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationProperty.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationProperty.cs index f401066ddd8d..959ba9bd9ed5 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationProperty.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationProperty.cs @@ -133,7 +133,7 @@ internal ConfigurationProperty(PropertyInfo info) if (collectionAttribute != null) { -#if NETCOREAPP +#if NET if (!collectionAttribute.AddItemName.Contains(',')) #else if (collectionAttribute.AddItemName.IndexOf(',') == -1) diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionCollection.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionCollection.cs index b103a4a35a26..ef54b46ac031 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionCollection.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionCollection.cs @@ -88,7 +88,7 @@ public ConfigurationSection Get(string name) throw ExceptionUtil.ParameterNullOrEmpty(nameof(name)); // prevent GetConfig from returning config not in this collection -#if NETCOREAPP +#if NET if (name.Contains('/')) #else if (name.IndexOf('/') >= 0) diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionGroupCollection.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionGroupCollection.cs index 68157107c77a..81210e851119 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionGroupCollection.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSectionGroupCollection.cs @@ -92,7 +92,7 @@ public ConfigurationSectionGroup Get(string name) throw ExceptionUtil.ParameterNullOrEmpty(nameof(name)); // prevent GetConfig from returning config not in this collection -#if NETCOREAPP +#if NET if (name.Contains('/')) #else if (name.IndexOf('/') >= 0) diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ImplicitMachineConfigHost.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ImplicitMachineConfigHost.cs index 32403a8950c2..195b3ca5ff4a 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ImplicitMachineConfigHost.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ImplicitMachineConfigHost.cs @@ -81,7 +81,7 @@ public override Stream OpenStreamForRead(string streamName)
    " + -#if NET7_0_OR_GREATER +#if NET @"
    " + #endif @"
    diff --git a/src/libraries/System.Configuration.ConfigurationManager/tests/ILLink.Descriptors.xml b/src/libraries/System.Configuration.ConfigurationManager/tests/ILLink.Descriptors.xml new file mode 100644 index 000000000000..8eb200db1924 --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/tests/ILLink.Descriptors.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj b/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj index e7881df77eb9..6880adcbf6c2 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj +++ b/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj @@ -59,7 +59,7 @@ - + @@ -97,6 +97,8 @@ + + diff --git a/src/libraries/System.Configuration.ConfigurationManager/tests/System/Configuration/CustomHostTests.cs b/src/libraries/System.Configuration.ConfigurationManager/tests/System/Configuration/CustomHostTests.cs index e8f69c198cf8..3d32a020502a 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/tests/System/Configuration/CustomHostTests.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/tests/System/Configuration/CustomHostTests.cs @@ -19,7 +19,8 @@ public void FilePathIsPopulatedCorrectly() { RemoteExecutor.Invoke(() => { - MakeAssemblyGetEntryAssemblyReturnNull(); + Assembly.SetEntryAssembly(null); + Assert.Null(Assembly.GetEntryAssembly()); string expectedFilePathEnding = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "dotnet.exe.config" : @@ -29,17 +30,5 @@ public void FilePathIsPopulatedCorrectly() Assert.EndsWith(expectedFilePathEnding, config.FilePath); }).Dispose(); } - - /// - /// Makes Assembly.GetEntryAssembly() return null using private reflection. - /// - private static void MakeAssemblyGetEntryAssemblyReturnNull() - { - typeof(Assembly) - .GetField("s_forceNullEntryPoint", BindingFlags.NonPublic | BindingFlags.Static) - .SetValue(null, true); - - Assert.Null(Assembly.GetEntryAssembly()); - } } } diff --git a/src/libraries/System.Console/ref/System.Console.cs b/src/libraries/System.Console/ref/System.Console.cs index 273290de2a89..297f94aac0ec 100644 --- a/src/libraries/System.Console/ref/System.Console.cs +++ b/src/libraries/System.Console/ref/System.Console.cs @@ -175,6 +175,7 @@ public static void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute( public static void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public static void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { } public static void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[]? arg) { } + public static void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params System.ReadOnlySpan arg) { } [System.CLSCompliantAttribute(false)] public static void Write(uint value) { } [System.CLSCompliantAttribute(false)] @@ -195,6 +196,7 @@ public static void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttrib public static void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public static void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { } public static void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[]? arg) { } + public static void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params System.ReadOnlySpan arg) { } [System.CLSCompliantAttribute(false)] public static void WriteLine(uint value) { } [System.CLSCompliantAttribute(false)] diff --git a/src/libraries/System.Console/src/System/Console.cs b/src/libraries/System.Console/src/System/Console.cs index 63736b597417..d2db8f831d44 100644 --- a/src/libraries/System.Console/src/System/Console.cs +++ b/src/libraries/System.Console/src/System/Console.cs @@ -865,6 +865,17 @@ public static void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat Out.WriteLine(format, arg); } + /// + /// Writes the text representation of the specified span of objects, followed by the current line terminator, to the standard output stream using the specified format information. + /// + /// A composite format string. + /// A span of objects to write using format. + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan arg) + { + Out.WriteLine(format, arg); + } + [MethodImplAttribute(MethodImplOptions.NoInlining)] public static void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0) { @@ -892,6 +903,17 @@ public static void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] s Out.Write(format, arg); } + /// + /// Writes the text representation of the specified span of objects to the standard output stream using the specified format information. + /// + /// A composite format string. + /// A span of objects to write using format. + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan arg) + { + Out.Write(format, arg); + } + [MethodImplAttribute(MethodImplOptions.NoInlining)] public static void Write(bool value) { diff --git a/src/libraries/System.Console/src/System/ConsolePal.Windows.cs b/src/libraries/System.Console/src/System/ConsolePal.Windows.cs index ee25d844de86..f51fed48b026 100644 --- a/src/libraries/System.Console/src/System/ConsolePal.Windows.cs +++ b/src/libraries/System.Console/src/System/ConsolePal.Windows.cs @@ -347,7 +347,7 @@ public static ConsoleKeyInfo ReadKey(bool intercept) while (true) { r = Interop.Kernel32.ReadConsoleInput(InputHandle, out ir, 1, out int numEventsRead); - if (!r || numEventsRead == 0) + if (!r) { // This will fail when stdin is redirected from a file or pipe. // We could theoretically call Console.Read here, but I @@ -355,6 +355,28 @@ public static ConsoleKeyInfo ReadKey(bool intercept) throw new InvalidOperationException(SR.InvalidOperation_ConsoleReadKeyOnFile); } + if (numEventsRead == 0) + { + // This can happen when there are multiple console-attached + // processes waiting for input, and another one is terminated + // while we are waiting for input. + // + // (This is "almost certainly" a bug, but behavior has been + // this way for a long time, so we should handle it: + // https://github.com/microsoft/terminal/issues/15859) + // + // (It's a rare case to have multiple console-attached + // processes waiting for input, but it can happen sometimes, + // such as when ctrl+c'ing a build process that is spawning + // tons of child processes--sometimes, due to the order in + // which processes exit, a managed shell process (like pwsh) + // might get back to the prompt and start trying to read input + // while there are still child processes getting cleaned up.) + // + // In this case, we just need to retry the read. + continue; + } + ushort keyCode = ir.keyEvent.wVirtualKeyCode; // First check for non-keyboard events & discard them. Generally we tap into only KeyDown events and ignore the KeyUp events diff --git a/src/libraries/System.Console/tests/ManualTests/Readme.md b/src/libraries/System.Console/tests/ManualTests/Readme.md index 6c56bce87840..4cd91a362a94 100644 --- a/src/libraries/System.Console/tests/ManualTests/Readme.md +++ b/src/libraries/System.Console/tests/ManualTests/Readme.md @@ -6,7 +6,8 @@ To run the suite, follow these steps: 1. Build the CLR and libraries. 2. Using a terminal, navigate to the current folder. 3. Enable manual testing by defining the `MANUAL_TESTS` environment variable (e.g. on bash `export MANUAL_TESTS=true`). -4. Run `dotnet test` and follow the instructions in the command prompt. +4. Disable terminal logger output for dotnet test by setting `MSBUILDENSURESTDOUTFORTASKPROCESSES=1` environment variable. (e.g. on bash `export MSBUILDENSURESTDOUTFORTASKPROCESSES=1`). +5. Run `dotnet test` and follow the instructions in the command prompt. ## Instructions for Windows testers diff --git a/src/libraries/System.Console/tests/ReadAndWrite.cs b/src/libraries/System.Console/tests/ReadAndWrite.cs index 5fbf425fc848..d60fd6aa34cc 100644 --- a/src/libraries/System.Console/tests/ReadAndWrite.cs +++ b/src/libraries/System.Console/tests/ReadAndWrite.cs @@ -84,10 +84,14 @@ private static void WriteCore() Console.Write("{0}", null, null); Console.Write("{0} {1} {2}", 32, "Hello", (uint)50); Console.Write("{0}", null, null, null); - Console.Write("{0} {1} {2} {3}", 32, "Hello", (uint)50, (ulong)5); - Console.Write("{0}", null, null, null, null); - Console.Write("{0} {1} {2} {3} {4}", 32, "Hello", (uint)50, (ulong)5, 'a'); - Console.Write("{0}", null, null, null, null, null); + Console.Write("{0} {1} {2} {3}", new object[] { 32, "Hello", (uint)50, (ulong)5 }); + Console.Write("{0} {1} {2} {3}", new object[] { 32, "Hello", (uint)50, (ulong)5 }.AsSpan()); + Console.Write("{0}", new object[] { null, null, null, null }); + Console.Write("{0}", new object[] { null, null, null, null }.AsSpan()); + Console.Write("{0} {1} {2} {3} {4}", new object[] { 32, "Hello", (uint)50, (ulong)5, 'a' }); + Console.Write("{0} {1} {2} {3} {4}", new object[] { 32, "Hello", (uint)50, (ulong)5, 'a' }.AsSpan()); + Console.Write("{0}", new object[] { null, null, null, null, null }); + Console.Write("{0}", new object[] { null, null, null, null, null }.AsSpan()); Console.Write(true); Console.Write('a'); Console.Write(new char[] { 'a', 'b', 'c', 'd', }); @@ -120,10 +124,14 @@ private static void WriteLineCore() Console.WriteLine("{0}", null, null); Console.WriteLine("{0} {1} {2}", 32, "Hello", (uint)50); Console.WriteLine("{0}", null, null, null); - Console.WriteLine("{0} {1} {2} {3}", 32, "Hello", (uint)50, (ulong)5); - Console.WriteLine("{0}", null, null, null, null); - Console.WriteLine("{0} {1} {2} {3} {4}", 32, "Hello", (uint)50, (ulong)5, 'a'); - Console.WriteLine("{0}", null, null, null, null, null); + Console.WriteLine("{0} {1} {2} {3}", new object[] { 32, "Hello", (uint)50, (ulong)5 }); + Console.WriteLine("{0} {1} {2} {3}", new object[] { 32, "Hello", (uint)50, (ulong)5 }.AsSpan()); + Console.WriteLine("{0}", new object[] { null, null, null, null }); + Console.WriteLine("{0}", new object[] { null, null, null, null }.AsSpan()); + Console.WriteLine("{0} {1} {2} {3} {4}", new object[] { 32, "Hello", (uint)50, (ulong)5, 'a' }); + Console.WriteLine("{0} {1} {2} {3} {4}", new object[] { 32, "Hello", (uint)50, (ulong)5, 'a' }.AsSpan()); + Console.WriteLine("{0}", new object[] { null, null, null, null, null }); + Console.WriteLine("{0}", new object[] { null, null, null, null, null }.AsSpan()); Console.WriteLine(true); Console.WriteLine('a'); Console.WriteLine(new char[] { 'a', 'b', 'c', 'd', }); @@ -158,8 +166,10 @@ public static async Task OutWriteAndWriteLineOverloads() writer.Write("{0}", 32); writer.Write("{0} {1}", 32, "Hello"); writer.Write("{0} {1} {2}", 32, "Hello", (uint)50); - writer.Write("{0} {1} {2} {3}", 32, "Hello", (uint)50, (ulong)5); - writer.Write("{0} {1} {2} {3} {4}", 32, "Hello", (uint)50, (ulong)5, 'a'); + writer.Write("{0} {1} {2} {3}", new object[] { 32, "Hello", (uint)50, (ulong)5 }); + writer.Write("{0} {1} {2} {3}", new object[] { 32, "Hello", (uint)50, (ulong)5 }.AsSpan()); + writer.Write("{0} {1} {2} {3} {4}", new object[] { 32, "Hello", (uint)50, (ulong)5, 'a' }); + writer.Write("{0} {1} {2} {3} {4}", new object[] { 32, "Hello", (uint)50, (ulong)5, 'a' }.AsSpan()); writer.Write(true); writer.Write('a'); writer.Write(new char[] { 'a', 'b', 'c', 'd', }); diff --git a/src/libraries/System.Data.Common/src/System/Data/DataView.cs b/src/libraries/System.Data.Common/src/System/Data/DataView.cs index 8babfcf6c498..902280624262 100644 --- a/src/libraries/System.Data.Common/src/System/Data/DataView.cs +++ b/src/libraries/System.Data.Common/src/System/Data/DataView.cs @@ -53,7 +53,7 @@ public class DataView : MarshalByValueComponent, IBindingListView, System.Compon private ListChangedEventArgs? _addNewMoved; private System.ComponentModel.ListChangedEventHandler? _onListChanged; - internal static ListChangedEventArgs s_resetEventArgs = new ListChangedEventArgs(ListChangedType.Reset, -1); + internal static readonly ListChangedEventArgs s_resetEventArgs = new ListChangedEventArgs(ListChangedType.Reset, -1); private DataTable? _delayedTable; private string? _delayedRowFilter; diff --git a/src/libraries/System.Data.Common/src/System/Data/Filter/Operators.cs b/src/libraries/System.Data.Common/src/System/Data/Filter/Operators.cs index bf84ba65ec3e..ca33c626fa78 100644 --- a/src/libraries/System.Data.Common/src/System/Data/Filter/Operators.cs +++ b/src/libraries/System.Data.Common/src/System/Data/Filter/Operators.cs @@ -37,9 +37,9 @@ internal static class Operators internal const int Minus = 16; // - internal const int Multiply = 17; // * internal const int Divide = 18; // / - //internal final static int IntegerDiv = 19; // \ + //internal const int IntegerDiv = 19; // \ internal const int Modulo = 20; // % - //internal final static int Exponent = 21; // ** + //internal const int Exponent = 21; // ** /* End of arithmetic operators */ /* Beginning of bitwise operators */ diff --git a/src/libraries/System.Data.Common/tests/ILLink.Descriptors.xml b/src/libraries/System.Data.Common/tests/ILLink.Descriptors.xml new file mode 100644 index 000000000000..54b7989e54db --- /dev/null +++ b/src/libraries/System.Data.Common/tests/ILLink.Descriptors.xml @@ -0,0 +1,3 @@ + + + diff --git a/src/libraries/System.Data.Common/tests/System.Data.Common.Tests.csproj b/src/libraries/System.Data.Common/tests/System.Data.Common.Tests.csproj index 84d25bfe8e5c..ae85c66d7e8b 100644 --- a/src/libraries/System.Data.Common/tests/System.Data.Common.Tests.csproj +++ b/src/libraries/System.Data.Common/tests/System.Data.Common.Tests.csproj @@ -123,5 +123,7 @@ + + diff --git a/src/libraries/System.Data.Common/tests/System/Data/XmlDataReaderTest.cs b/src/libraries/System.Data.Common/tests/System/Data/XmlDataReaderTest.cs index 5e56718d833d..6de3301b4f01 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/XmlDataReaderTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/XmlDataReaderTest.cs @@ -36,6 +36,7 @@ public class XmlDataReaderTest { [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/51369", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/51369", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsAppleMobile))] public void XmlLoadTest() { var ds = new DataSet(); diff --git a/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbConnectionPool.cs b/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbConnectionPool.cs index bceb5f5c4a63..33d522bbe128 100644 --- a/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbConnectionPool.cs +++ b/src/libraries/System.Data.Odbc/src/Common/System/Data/ProviderBase/DbConnectionPool.cs @@ -28,9 +28,9 @@ public PendingGetConnection(long dueTime, DbConnection owner, TaskCompletionSour Owner = owner; Completion = completion; } - public long DueTime { get; private set; } - public DbConnection Owner { get; private set; } - public TaskCompletionSource Completion { get; private set; } + public long DueTime { get; } + public DbConnection Owner { get; } + public TaskCompletionSource Completion { get; } } diff --git a/src/libraries/System.Data.OleDb/src/DbConnectionOptions.cs b/src/libraries/System.Data.OleDb/src/DbConnectionOptions.cs index 0bb5bde47ea4..81b4ecdc5b71 100644 --- a/src/libraries/System.Data.OleDb/src/DbConnectionOptions.cs +++ b/src/libraries/System.Data.OleDb/src/DbConnectionOptions.cs @@ -59,7 +59,7 @@ internal partial class DbConnectionOptions private static readonly Regex ConnectionStringRegex = CreateConnectionStringRegex(); private static readonly Regex ConnectionStringRegexOdbc = CreateConnectionStringRegexOdbc(); -#if NET7_0_OR_GREATER +#if NET [GeneratedRegex(ConnectionStringPattern, RegexOptions.ExplicitCapture)] private static partial Regex CreateConnectionStringRegex(); @@ -76,7 +76,7 @@ internal partial class DbConnectionOptions private static readonly Regex ConnectionStringQuoteValueRegex = CreateConnectionStringQuoteValueRegex(); // generally do not quote the value if it matches the pattern private static readonly Regex ConnectionStringQuoteOdbcValueRegex = CreateConnectionStringQuoteOdbcValueRegex(); // do not quote odbc value if it matches this pattern -#if NET7_0_OR_GREATER +#if NET [GeneratedRegex("^(?![;\\s])[^\\p{Cc}]+(?? _Pool; - internal static object _PoolLock = new object(); + internal static readonly object _PoolLock = new object(); } private static class VALUES diff --git a/src/libraries/System.Data.OleDb/src/OleDbDataReader.cs b/src/libraries/System.Data.OleDb/src/OleDbDataReader.cs index a0eaeef4acb7..6f1e90f05be0 100644 --- a/src/libraries/System.Data.OleDb/src/OleDbDataReader.cs +++ b/src/libraries/System.Data.OleDb/src/OleDbDataReader.cs @@ -611,7 +611,7 @@ private void BuildSchemaTableRowset(object handle) using (DualCoTaskMem prgOptColumns = new DualCoTaskMem(icolumnsRowset, out cOptColumns, out hr)) { Debug.Assert((0 == hr) || prgOptColumns.IsInvalid, "GetAvailableCOlumns: unexpected return"); - hr = icolumnsRowset.GetColumnsRowset(IntPtr.Zero, cOptColumns, prgOptColumns, ref ODB.IID_IRowset, 0, IntPtr.Zero, out rowset); + hr = icolumnsRowset.GetColumnsRowset(IntPtr.Zero, cOptColumns, prgOptColumns, in ODB.IID_IRowset, 0, IntPtr.Zero, out rowset); } Debug.Assert((0 <= hr) || (null == rowset), "if GetColumnsRowset failed, rowset should be null"); @@ -952,7 +952,7 @@ private OleDbDataReader GetDataForReader(IntPtr ordinal, RowBinding rowbinding, UnsafeNativeMethods.IRowsetInfo rowsetInfo = IRowsetInfo(); UnsafeNativeMethods.IRowset? result; OleDbHResult hr; - hr = rowsetInfo.GetReferencedRowset((IntPtr)ordinal, ref ODB.IID_IRowset, out result); + hr = rowsetInfo.GetReferencedRowset((IntPtr)ordinal, in ODB.IID_IRowset, out result); ProcessResults(hr); // Per docs result can be null only when hr is DB_E_NOTAREFERENCECOLUMN which in most of the cases will cause the exception in ProcessResult @@ -1236,7 +1236,7 @@ internal void HasRowsRead() { break; } - hr = imultipleResults.GetResult(IntPtr.Zero, ODB.DBRESULTFLAG_DEFAULT, ref ODB.IID_NULL, out affected, out _); + hr = imultipleResults.GetResult(IntPtr.Zero, ODB.DBRESULTFLAG_DEFAULT, in ODB.IID_NULL, out affected, out _); // If a provider doesn't support IID_NULL and returns E_NOINTERFACE we want to break out // of the loop without throwing an exception. Our behavior will match ADODB in that scenario @@ -1327,7 +1327,7 @@ public override bool NextResult() Close(); break; } - hr = imultipleResults.GetResult(IntPtr.Zero, ODB.DBRESULTFLAG_DEFAULT, ref ODB.IID_IRowset, out affected, out result); + hr = imultipleResults.GetResult(IntPtr.Zero, ODB.DBRESULTFLAG_DEFAULT, in ODB.IID_IRowset, out affected, out result); if ((0 <= hr) && (null != result)) { diff --git a/src/libraries/System.Data.OleDb/src/OleDbError.cs b/src/libraries/System.Data.OleDb/src/OleDbError.cs index db1968fb844a..6497414fd496 100644 --- a/src/libraries/System.Data.OleDb/src/OleDbError.cs +++ b/src/libraries/System.Data.OleDb/src/OleDbError.cs @@ -61,7 +61,7 @@ internal OleDbError(UnsafeNativeMethods.IErrorRecords errorRecords, int index) } UnsafeNativeMethods.ISQLErrorInfo sqlErrorInfo; - errorRecords.GetCustomErrorObject(index, ref ODB.IID_ISQLErrorInfo, out sqlErrorInfo); + errorRecords.GetCustomErrorObject(index, in ODB.IID_ISQLErrorInfo, out sqlErrorInfo); if (null != sqlErrorInfo) { diff --git a/src/libraries/System.Data.OleDb/src/OleDb_Util.cs b/src/libraries/System.Data.OleDb/src/OleDb_Util.cs index d42b00151beb..b35087409aeb 100644 --- a/src/libraries/System.Data.OleDb/src/OleDb_Util.cs +++ b/src/libraries/System.Data.OleDb/src/OleDb_Util.cs @@ -580,24 +580,24 @@ internal static InvalidOperationException IDBInfoNotSupported() internal static readonly int OffsetOf_tagDBBINDING_obValue = Marshal.OffsetOf(typeof(tagDBBINDING), "obValue").ToInt32(); internal static readonly int OffsetOf_tagDBBINDING_wType = Marshal.OffsetOf(typeof(tagDBBINDING), "wType").ToInt32(); - internal static Guid IID_NULL = Guid.Empty; - internal static Guid IID_IUnknown = new Guid(0x00000000, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); - internal static Guid IID_IDBInitialize = new Guid(0x0C733A8B, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); - internal static Guid IID_IDBCreateSession = new Guid(0x0C733A5D, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); - internal static Guid IID_IDBCreateCommand = new Guid(0x0C733A1D, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); - internal static Guid IID_ICommandText = new Guid(0x0C733A27, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); - internal static Guid IID_IMultipleResults = new Guid(0x0C733A90, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); - internal static Guid IID_IRow = new Guid(0x0C733AB4, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); - internal static Guid IID_IRowset = new Guid(0x0C733A7C, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); - internal static Guid IID_ISQLErrorInfo = new Guid(0x0C733A74, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); - - internal static Guid CLSID_DataLinks = new Guid(0x2206CDB2, 0x19C1, 0x11D1, 0x89, 0xE0, 0x00, 0xC0, 0x4F, 0xD7, 0xA8, 0x29); - - internal static Guid DBGUID_DEFAULT = new Guid(0xc8b521fb, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d); - internal static Guid DBGUID_ROWSET = new Guid(0xc8b522f6, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d); - internal static Guid DBGUID_ROW = new Guid(0xc8b522f7, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d); - - internal static Guid DBGUID_ROWDEFAULTSTREAM = new Guid(0x0C733AB7, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); + internal static readonly Guid IID_NULL = Guid.Empty; + internal static readonly Guid IID_IUnknown = new Guid(0x00000000, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + internal static readonly Guid IID_IDBInitialize = new Guid(0x0C733A8B, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); + internal static readonly Guid IID_IDBCreateSession = new Guid(0x0C733A5D, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); + internal static readonly Guid IID_IDBCreateCommand = new Guid(0x0C733A1D, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); + internal static readonly Guid IID_ICommandText = new Guid(0x0C733A27, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); + internal static readonly Guid IID_IMultipleResults = new Guid(0x0C733A90, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); + internal static readonly Guid IID_IRow = new Guid(0x0C733AB4, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); + internal static readonly Guid IID_IRowset = new Guid(0x0C733A7C, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); + internal static readonly Guid IID_ISQLErrorInfo = new Guid(0x0C733A74, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); + + internal static readonly Guid CLSID_DataLinks = new Guid(0x2206CDB2, 0x19C1, 0x11D1, 0x89, 0xE0, 0x00, 0xC0, 0x4F, 0xD7, 0xA8, 0x29); + + internal static readonly Guid DBGUID_DEFAULT = new Guid(0xc8b521fb, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d); + internal static readonly Guid DBGUID_ROWSET = new Guid(0xc8b522f6, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d); + internal static readonly Guid DBGUID_ROW = new Guid(0xc8b522f7, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d); + + internal static readonly Guid DBGUID_ROWDEFAULTSTREAM = new Guid(0x0C733AB7, 0x2A1C, 0x11CE, 0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D); internal static readonly Guid CLSID_MSDASQL = new Guid(0xc8b522cb, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d); diff --git a/src/libraries/System.Data.OleDb/src/System/Data/ProviderBase/DbConnectionPool.cs b/src/libraries/System.Data.OleDb/src/System/Data/ProviderBase/DbConnectionPool.cs index 4e3b0e9f13e7..4bffaa74980f 100644 --- a/src/libraries/System.Data.OleDb/src/System/Data/ProviderBase/DbConnectionPool.cs +++ b/src/libraries/System.Data.OleDb/src/System/Data/ProviderBase/DbConnectionPool.cs @@ -50,10 +50,10 @@ public PendingGetConnection(long dueTime, DbConnection owner, TaskCompletionSour Owner = owner; Completion = completion; } - public long DueTime { get; private set; } - public DbConnection Owner { get; private set; } - public TaskCompletionSource Completion { get; private set; } - public DbConnectionOptions? UserOptions { get; private set; } + public long DueTime { get; } + public DbConnection Owner { get; } + public TaskCompletionSource Completion { get; } + public DbConnectionOptions? UserOptions { get; } } private sealed class TransactedConnectionPool diff --git a/src/libraries/System.Data.OleDb/src/UnsafeNativeMethods.cs b/src/libraries/System.Data.OleDb/src/UnsafeNativeMethods.cs index db5a7d27e542..474d677280e5 100644 --- a/src/libraries/System.Data.OleDb/src/UnsafeNativeMethods.cs +++ b/src/libraries/System.Data.OleDb/src/UnsafeNativeMethods.cs @@ -299,7 +299,7 @@ System.Data.OleDb.OleDbHResult GetColumnsRowset( [In] IntPtr pUnkOuter, [In] IntPtr cOptColumns, [In] SafeHandle rgOptColumns, - [In] ref Guid riid, + [In] in Guid riid, [In] int cPropertySets, [In] IntPtr rgPropertySets, [Out, MarshalAs(UnmanagedType.Interface)] out IRowset ppColRowset); @@ -367,7 +367,7 @@ HRESULT Execute( [PreserveSig] System.Data.OleDb.OleDbHResult Execute( [In] IntPtr pUnkOuter, - [In] ref Guid riid, + [In] in Guid riid, [In] System.Data.OleDb.tagDBPARAMS? pDBParams, [Out] out IntPtr pcRowsAffected, [Out, MarshalAs(UnmanagedType.Interface)] out object ppRowset); @@ -383,7 +383,7 @@ HRESULT SetCommandText( );*/ [PreserveSig] System.Data.OleDb.OleDbHResult SetCommandText( - [In] ref Guid rguidDialect, + [In] in Guid rguidDialect, [In, MarshalAs(UnmanagedType.LPWStr)] string pwszCommand); } @@ -486,10 +486,10 @@ HRESULT GetRowset( [PreserveSig] System.Data.OleDb.OleDbHResult GetRowset( [In] IntPtr pUnkOuter, - [In] ref Guid rguidSchema, + [In] in Guid rguidSchema, [In] int cRestrictions, [In, MarshalAs(UnmanagedType.LPArray)] object?[] rgRestrictions, - [In] ref Guid riid, + [In] in Guid riid, [In] int cPropertySets, [In] IntPtr rgPropertySets, [Out, MarshalAs(UnmanagedType.Interface)] out IRowset ppRowset); @@ -549,7 +549,7 @@ internal interface IErrorRecords [PreserveSig] System.Data.OleDb.OleDbHResult GetCustomErrorObject( // may return E_NOINTERFACE when asking for IID_ISQLErrorInfo [In] int ulRecordNum, - [In] ref Guid riid, + [In] in Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out ISQLErrorInfo ppObject); [return: MarshalAs(UnmanagedType.Interface)] @@ -603,7 +603,7 @@ HRESULT GetResult( System.Data.OleDb.OleDbHResult GetResult( [In] IntPtr pUnkOuter, [In] IntPtr lResultFlag, - [In] ref Guid riid, + [In] in Guid riid, [Out] out IntPtr pcRowsAffected, [Out, MarshalAs(UnmanagedType.Interface)] out object ppRowset); } @@ -631,7 +631,7 @@ System.Data.OleDb.OleDbHResult OpenRowset( [In] IntPtr pUnkOuter, [In] System.Data.OleDb.tagDBID pTableID, [In] IntPtr pIndexID, - [In] ref Guid riid, + [In] in Guid riid, [In] int cPropertySets, [In] IntPtr rgPropertySets, [Out, MarshalAs(UnmanagedType.Interface)] out object ppRowset); @@ -718,7 +718,7 @@ System.Data.OleDb.OleDbHResult GetProperties( [PreserveSig] System.Data.OleDb.OleDbHResult GetReferencedRowset( [In] IntPtr iOrdinal, - [In] ref Guid riid, + [In] in Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out IRowset? ppRowset); //[PreserveSig] diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs index 7cb90d245dcf..0e24044c733a 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs @@ -50,6 +50,7 @@ public string? Id public string? TraceStateString { get { throw null; } set { } } public System.Diagnostics.Activity AddBaggage(string key, string? value) { throw null; } public System.Diagnostics.Activity AddEvent(System.Diagnostics.ActivityEvent e) { throw null; } + public System.Diagnostics.Activity AddLink(System.Diagnostics.ActivityLink link) { throw null; } public System.Diagnostics.Activity AddTag(string key, string? value) { throw null; } public System.Diagnostics.Activity AddTag(string key, object? value) { throw null; } public System.Diagnostics.Activity SetTag(string key, object? value) { throw null; } @@ -297,7 +298,7 @@ public abstract class DistributedContextPropagator [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] public struct TagList : System.Collections.Generic.IList>, System.Collections.Generic.IReadOnlyList> { - public TagList(System.ReadOnlySpan> tagList) : this() { throw null; } + public TagList(params System.ReadOnlySpan> tagList) : this() { throw null; } public readonly int Count => throw null; public readonly bool IsReadOnly => throw null; public System.Collections.Generic.KeyValuePair this[int index] @@ -336,7 +337,7 @@ public sealed class Counter : Instrument where T : struct public void Add(T delta, System.Collections.Generic.KeyValuePair tag) { throw null; } public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2) { throw null; } public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2, System.Collections.Generic.KeyValuePair tag3) { throw null; } - public void Add(T delta, ReadOnlySpan> tags) { throw null; } + public void Add(T delta, params System.ReadOnlySpan> tags) { throw null; } public void Add(T delta, params System.Collections.Generic.KeyValuePair[] tags) { throw null; } public void Add(T delta, in TagList tagList) { throw null; } internal Counter(Meter meter, string name, string? unit, string? description) : @@ -348,7 +349,7 @@ public sealed class UpDownCounter : Instrument where T : struct public void Add(T delta, System.Collections.Generic.KeyValuePair tag) { throw null; } public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2) { throw null; } public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2, System.Collections.Generic.KeyValuePair tag3) { throw null; } - public void Add(T delta, ReadOnlySpan> tags) { throw null; } + public void Add(T delta, params System.ReadOnlySpan> tags) { throw null; } public void Add(T delta, params System.Collections.Generic.KeyValuePair[] tags) { throw null; } public void Add(T delta, in TagList tagList) { throw null; } internal UpDownCounter(Meter meter, string name, string? unit, string? description) : @@ -362,7 +363,7 @@ public sealed class Histogram : Instrument where T : struct public void Record(T value, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2) { throw null; } public void Record(T value, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2, System.Collections.Generic.KeyValuePair tag3) { throw null; } public void Record(T value, in TagList tagList) { throw null; } - public void Record(T value, ReadOnlySpan> tags) { throw null; } + public void Record(T value, params System.ReadOnlySpan> tags) { throw null; } public void Record(T value, params System.Collections.Generic.KeyValuePair[] tags) { throw null; } } public interface IMeterFactory : System.IDisposable @@ -398,11 +399,11 @@ public abstract class Instrument : Instrument where T : struct public Measurement(T value) { throw null; } public Measurement(T value, System.Collections.Generic.IEnumerable>? tags) { throw null; } public Measurement(T value, params System.Collections.Generic.KeyValuePair[]? tags) { throw null; } - public Measurement(T value, ReadOnlySpan> tags) { throw null; } + public Measurement(T value, params System.ReadOnlySpan> tags) { throw null; } public ReadOnlySpan> Tags { get { throw null; } } public T Value { get { throw null; } } } - public delegate void MeasurementCallback(Instrument instrument, T measurement, ReadOnlySpan> tags, object? state); + public delegate void MeasurementCallback(Instrument instrument, T measurement, ReadOnlySpan> tags, object? state) where T : struct; public class Meter : IDisposable { public Counter CreateCounter(string name, string? unit = null, string? description = null) where T : struct { throw null; } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/DiagnosticSourceUsersGuide.md b/src/libraries/System.Diagnostics.DiagnosticSource/src/DiagnosticSourceUsersGuide.md index bcd4e96cb8aa..15ee7fce3a66 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/DiagnosticSourceUsersGuide.md +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/DiagnosticSourceUsersGuide.md @@ -61,7 +61,7 @@ Thus the first step in instrumenting code with `DiagnosticSource` is to create a `DiagnosticListener`. For example: ```C# - private static DiagnosticSource httpLogger = new DiagnosticListener("System.Net.Http"); + private static readonly DiagnosticSource httpLogger = new DiagnosticListener("System.Net.Http"); ``` Notice that httpLogger is typed as a `DiagnosticSource`. This is because this code only cares about writing events and thus only cares about the `DiagnosticSource` methods that @@ -104,7 +104,7 @@ Already some of the architectural elements are being exposed, namely: Perhaps confusingly you make a `DiagnosticSource` by creating a `DiagnosticListener`: ```C# - static DiagnosticSource mySource = new DiagnosticListener("System.Net.Http"); + static readonly DiagnosticSource mySource = new DiagnosticListener("System.Net.Http"); ``` Basically a `DiagnosticListener` is a named place where a source sends its information (events). @@ -248,7 +248,7 @@ A typical use of the `AllListeners` static property looks like this: ```C# // We are using AllListeners to turn an Action into an IObserver - static IDisposable listenerSubscription = DiagnosticListener.AllListeners.Subscribe(delegate (DiagnosticListener listener) + static readonly IDisposable listenerSubscription = DiagnosticListener.AllListeners.Subscribe(delegate (DiagnosticListener listener) { // We get a callback of every Diagnostics Listener that is active in the system (past present or future) if (listener.Name == "System.Net.Http") @@ -290,7 +290,7 @@ call `Subscribe()` on it as well. Thus we can fill out the previous example a bi ```C# static IDisposable networkSubscription = null; - static IDisposable listenerSubscription = DiagnosticListener.AllListeners.Subscribe(delegate (DiagnosticListener listener) + static readonly IDisposable listenerSubscription = DiagnosticListener.AllListeners.Subscribe(delegate (DiagnosticListener listener) { if (listener.Name == "System.Net.Http") { diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs index 0605251a93b7..bf2fb0bb0430 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs @@ -226,7 +226,7 @@ public string? Id Span flagsChars = stackalloc char[2]; HexConverter.ToCharsBuffer((byte)((~ActivityTraceFlagsIsSet) & _w3CIdFlags), flagsChars, 0, HexConverter.Casing.Lower); string id = -#if NET6_0_OR_GREATER +#if NET string.Create(null, stackalloc char[128], $"00-{_traceId}-{_spanId}-{flagsChars}"); #else "00-" + _traceId + "-" + _spanId + "-" + flagsChars.ToString(); @@ -258,7 +258,7 @@ public string? ParentId Span flagsChars = stackalloc char[2]; HexConverter.ToCharsBuffer((byte)((~ActivityTraceFlagsIsSet) & _parentTraceFlags), flagsChars, 0, HexConverter.Casing.Lower); string parentId = -#if NET6_0_OR_GREATER +#if NET string.Create(null, stackalloc char[128], $"00-{_traceId}-{_parentSpanId}-{flagsChars}"); #else "00-" + _traceId + "-" + _parentSpanId + "-" + flagsChars.ToString(); @@ -517,6 +517,25 @@ public Activity AddEvent(ActivityEvent e) return this; } + /// + /// Add an to the list. + /// + /// The to add. + /// for convenient chaining. + /// + /// For contexts that are available during span creation, adding links at span creation is preferred to calling later, + /// because head sampling decisions can only consider information present during span creation. + /// + public Activity AddLink(ActivityLink link) + { + if (_links != null || Interlocked.CompareExchange(ref _links, new DiagLinkedList(link), null) != null) + { + _links.Add(link); + } + + return this; + } + /// /// Update the Activity to have baggage with an additional 'key' and value 'value'. /// This shows up in the enumeration as well as the diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs index 1a58f827851c..7e287c30123a 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs @@ -195,7 +195,7 @@ public virtual void Dispose() /// /// When a DiagnosticListener is created it is given a name. Return this. /// - public string Name { get; private set; } + public string Name { get; } /// /// Return the name for the ToString() to aid in debugging. diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs index fbb13c9c9b6d..4d4edfbf7b79 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -174,7 +174,7 @@ namespace System.Diagnostics "EnsureDescriptorsInitialized does not access these members and is safe to call.")] internal sealed class DiagnosticSourceEventSource : EventSource { - public static DiagnosticSourceEventSource Log = new DiagnosticSourceEventSource(); + public static readonly DiagnosticSourceEventSource Log = new DiagnosticSourceEventSource(); public static class Keywords { @@ -1240,7 +1240,7 @@ public PropertySpec(string propertyName, PropertySpec? next) } } - public bool IsStatic { get; private set; } + public bool IsStatic { get; } /// /// Given an object fetch the property that this PropertySpec represents. @@ -1362,7 +1362,7 @@ public static PropertyFetch FetcherForProperty(Type? type, string propertyName) private static PropertyFetch CreateEnumeratePropertyFetch(Type type, TypeInfo enumerableOfTType) { Type elemType = enumerableOfTType.GetGenericArguments()[0]; -#if NETCOREAPP +#if NET if (!RuntimeFeature.IsDynamicCodeSupported && elemType.IsValueType) { return new EnumeratePropertyFetch(type); @@ -1377,7 +1377,7 @@ private static PropertyFetch CreateEnumeratePropertyFetch(Type type, TypeInfo en Justification = "MakeGenericType is only called when IsDynamicCodeSupported is true or only with ref types.")] private static PropertyFetch CreatePropertyFetch(Type type, PropertyInfo propertyInfo) { -#if NETCOREAPP +#if NET if (!RuntimeFeature.IsDynamicCodeSupported && (propertyInfo.DeclaringType!.IsValueType || propertyInfo.PropertyType.IsValueType)) { return new ReflectionPropertyFetch(type, propertyInfo); @@ -1434,7 +1434,7 @@ public ValueTypedFetchProperty(Type type, PropertyInfo property) : base(type) private readonly StructFunc _propertyFetch; } -#if NETCOREAPP +#if NET /// /// A fetcher that can be used when MakeGenericType isn't available. /// diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/HttpHandlerDiagnosticListener.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/HttpHandlerDiagnosticListener.cs index 94d4192721ca..ef1b21f8cda1 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/HttpHandlerDiagnosticListener.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/HttpHandlerDiagnosticListener.cs @@ -792,7 +792,7 @@ private static Func CreateFieldGetter(Type classType, st #endregion - internal static HttpHandlerDiagnosticListener s_instance = new HttpHandlerDiagnosticListener(); + internal static readonly HttpHandlerDiagnosticListener s_instance = new HttpHandlerDiagnosticListener(); #region private fields private const string DiagnosticListenerName = "System.Net.Http.Desktop"; diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Counter.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Counter.cs index 1d311d621963..4c503a50ac72 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Counter.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Counter.cs @@ -59,7 +59,7 @@ internal Counter(Meter meter, string name, string? unit, string? description, IE /// /// The increment measurement. /// A span of key-value pair tags associated with the measurement. - public void Add(T delta, ReadOnlySpan> tags) => RecordMeasurement(delta, tags); + public void Add(T delta, params ReadOnlySpan> tags) => RecordMeasurement(delta, tags); /// /// Record the increment value of the measurement. diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/CounterAggregator.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/CounterAggregator.cs index b9e3c8d35bca..4577c16b9b98 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/CounterAggregator.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/CounterAggregator.cs @@ -33,7 +33,7 @@ public override void Update(double value) // Get the delta best associated with the current thread, preferring to use core ID rather than // thread ID to reduce contention. ref PaddedDouble delta = ref deltas[ -#if NETCOREAPP2_1_OR_GREATER +#if NET Thread.GetCurrentProcessorId() #else Environment.CurrentManagedThreadId diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Histogram.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Histogram.cs index ed3431edfce8..3863efe704c7 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Histogram.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Histogram.cs @@ -59,7 +59,7 @@ internal Histogram(Meter meter, string name, string? unit, string? description, /// /// The measurement value. /// A span of key-value pair tags associated with the measurement. - public void Record(T value, ReadOnlySpan> tags) => RecordMeasurement(value, tags); + public void Record(T value, params ReadOnlySpan> tags) => RecordMeasurement(value, tags); /// /// Record a measurement value. diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Measurement.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Measurement.cs index 49db3c86f8db..88f269855522 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Measurement.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Measurement.cs @@ -59,7 +59,7 @@ public Measurement(T value, params KeyValuePair[]? tags) /// /// The measurement value. /// The measurement associated tags list. - public Measurement(T value, ReadOnlySpan> tags) + public Measurement(T value, params ReadOnlySpan> tags) { _tags = tags.ToArray(); Value = value; diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs index 3fbe68f55454..ba789aa98b15 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs @@ -298,7 +298,7 @@ public CommandHandler(MetricsEventSource parent) Parent = parent; } - public MetricsEventSource Parent { get; private set; } + public MetricsEventSource Parent { get; } public bool IsSharedSession(string commandSessionId) { @@ -737,7 +737,7 @@ private static string FormatQuantiles(QuantileValue[] quantiles) StringBuilder sb = new StringBuilder(); for (int i = 0; i < quantiles.Length; i++) { -#if NETCOREAPP +#if NET sb.Append(CultureInfo.InvariantCulture, $"{quantiles[i].Quantile}={quantiles[i].Value}"); #else sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}", quantiles[i].Quantile, quantiles[i].Value); @@ -754,8 +754,8 @@ private static string FormatQuantiles(QuantileValue[] quantiles) private sealed class MetricSpec { private const char MeterInstrumentSeparator = '\\'; - public string MeterName { get; private set; } - public string? InstrumentName { get; private set; } + public string MeterName { get; } + public string? InstrumentName { get; } public MetricSpec(string meterName, string? instrumentName) { diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/TagList.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/TagList.cs index 7646bcc2d33a..f003241ceb40 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/TagList.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/TagList.cs @@ -43,7 +43,7 @@ public struct TagList : IList>, IReadOnlyList. /// /// A span of tags to initialize the list with. - public TagList(ReadOnlySpan> tagList) : this() + public TagList(params ReadOnlySpan> tagList) : this() { _tagsCount = tagList.Length; switch (_tagsCount) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs index 79d0ed29d8f4..dc9a65b91d37 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs @@ -58,7 +58,7 @@ internal UpDownCounter(Meter meter, string name, string? unit, string? descripti /// /// The amount to be added which can be positive, negative or zero. /// A span of key-value pair tags associated with the measurement. - public void Add(T delta, ReadOnlySpan> tags) => RecordMeasurement(delta, tags); + public void Add(T delta, params ReadOnlySpan> tags) => RecordMeasurement(delta, tags); /// /// Record the delta value of the measurement. The delta can be positive, negative or zero. diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs index ae3c138e3697..00cb26017a38 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs @@ -1597,6 +1597,35 @@ public void TestEvent() Assert.Equal(0, activity.Events.ElementAt(1).Tags.Count()); } + [Fact] + public void AddLinkTest() + { + ActivityContext c1 = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None); + ActivityContext c2 = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None); + + ActivityLink l1 = new ActivityLink(c1); + ActivityLink l2 = new ActivityLink(c2, new ActivityTagsCollection() + { + new KeyValuePair("foo", 99) + }); + + Activity activity = new Activity("LinkTest"); + Assert.True(ReferenceEquals(activity, activity.AddLink(l1))); + Assert.True(ReferenceEquals(activity, activity.AddLink(l2))); + + // Add a duplicate of l1. The implementation doesn't check for duplicates. + Assert.True(ReferenceEquals(activity, activity.AddLink(l1))); + + ActivityLink[] links = activity.Links.ToArray(); + Assert.Equal(3, links.Length); + Assert.Equal(c1, links[0].Context); + Assert.Equal(c2, links[1].Context); + Assert.Equal(c1, links[2].Context); + KeyValuePair tag = links[1].Tags.Single(); + Assert.Equal("foo", tag.Key); + Assert.Equal(99, tag.Value); + } + [Fact] public void TestIsAllDataRequested() { @@ -2163,12 +2192,14 @@ public void EnumerateLinksTest() var context1 = new ActivityContext(ActivityTraceId.CreateRandom(), default, ActivityTraceFlags.None); var context2 = new ActivityContext(ActivityTraceId.CreateRandom(), default, ActivityTraceFlags.None); + var context3 = new ActivityContext(ActivityTraceId.CreateRandom(), default, ActivityTraceFlags.None); a = source.CreateActivity( name: "Root", kind: ActivityKind.Internal, parentContext: default, links: new[] { new ActivityLink(context1), new ActivityLink(context2) }); + a.AddLink(new ActivityLink(context3)); Assert.NotNull(a); @@ -2182,6 +2213,9 @@ public void EnumerateLinksTest() Assert.True(enumerator.MoveNext()); Assert.Equal(context2.TraceId, enumerator.Current.Context.TraceId); values.Add(enumerator.Current); + Assert.True(enumerator.MoveNext()); + Assert.Equal(context3.TraceId, enumerator.Current.Context.TraceId); + values.Add(enumerator.Current); Assert.False(enumerator.MoveNext()); Assert.Equal(a.Links, values); diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs index 4a3cd242bb8b..b292e55f1bcf 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs @@ -4,6 +4,7 @@ using Microsoft.DotNet.RemoteExecutor; using System.Collections.Generic; using System.Diagnostics.Metrics; +using System.Diagnostics.Tests; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -13,6 +14,29 @@ namespace System.Diagnostics.Metrics.Tests { public class MetricsTests { + [Fact] + public void MeasurementConstructionTest() + { + for (int i = 0; i < 30; i++) + { + TagListTests.CreateTagList(i, out TagList tags); + TagListTests.ValidateTags(in tags, i); + KeyValuePair[] tagsArray = tags.ToArray(); + + var measurement = new Measurement(i, tags); + Assert.Equal(i, measurement.Value); + TagListTests.ValidateTags(new TagList(measurement.Tags), tagsArray); + + measurement = new Measurement(i, tagsArray); + Assert.Equal(i, measurement.Value); + TagListTests.ValidateTags(new TagList(measurement.Tags), tagsArray); + + measurement = new Measurement(i, tagsArray.AsSpan()); + Assert.Equal(i, measurement.Value); + TagListTests.ValidateTags(new TagList(measurement.Tags), tagsArray); + } + } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public void MeterConstructionTest() { @@ -238,76 +262,115 @@ public void ThrowingExceptionsFromObservableInstrumentCallbacks() }).Dispose(); } - [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] - public void InstrumentMeasurementTest() + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [InlineData(false)] + [InlineData(true)] + public void InstrumentMeasurementTest(bool useSpan) { - RemoteExecutor.Invoke(() => { + RemoteExecutor.Invoke((string useSpanStr) => { Meter meter = new Meter("InstrumentMeasurementTest"); + bool useSpan = bool.Parse(useSpanStr); Counter counter = meter.CreateCounter("byteCounter"); - InstrumentMeasurementAggregationValidation(counter, (value, tags) => { counter.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter, (value, tags) => { AddToCounter(counter, value, tags, useSpan); } ); UpDownCounter upDownCounter = meter.CreateUpDownCounter("byteUpDownCounter"); - InstrumentMeasurementAggregationValidation(upDownCounter, (value, tags) => { upDownCounter.Add(value, tags); }); + InstrumentMeasurementAggregationValidation(upDownCounter, (value, tags) => { AddToUpDownCounter(upDownCounter, value, tags, useSpan); }); Counter counter1 = meter.CreateCounter("shortCounter"); - InstrumentMeasurementAggregationValidation(counter1, (value, tags) => { counter1.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter1, (value, tags) => { AddToCounter(counter1, value, tags, useSpan); } ); UpDownCounter upDownCounter1 = meter.CreateUpDownCounter("shortUpDownCounter"); - InstrumentMeasurementAggregationValidation(upDownCounter1, (value, tags) => { upDownCounter1.Add(value, tags); }, true); + InstrumentMeasurementAggregationValidation(upDownCounter1, (value, tags) => { AddToUpDownCounter(upDownCounter1, value, tags, useSpan); }, true); Counter counter2 = meter.CreateCounter("intCounter"); - InstrumentMeasurementAggregationValidation(counter2, (value, tags) => { counter2.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter2, (value, tags) => { AddToCounter(counter2, value, tags, useSpan); } ); UpDownCounter upDownCounter2 = meter.CreateUpDownCounter("intUpDownCounter"); - InstrumentMeasurementAggregationValidation(upDownCounter2, (value, tags) => { upDownCounter2.Add(value, tags); }, true); + InstrumentMeasurementAggregationValidation(upDownCounter2, (value, tags) => { AddToUpDownCounter(upDownCounter2, value, tags, useSpan); }, true); Counter counter3 = meter.CreateCounter("longCounter"); - InstrumentMeasurementAggregationValidation(counter3, (value, tags) => { counter3.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter3, (value, tags) => { AddToCounter(counter3, value, tags, useSpan); } ); UpDownCounter upDownCounter3 = meter.CreateUpDownCounter("longUpDownCounter"); - InstrumentMeasurementAggregationValidation(upDownCounter3, (value, tags) => { upDownCounter3.Add(value, tags); }, true); + InstrumentMeasurementAggregationValidation(upDownCounter3, (value, tags) => { AddToUpDownCounter(upDownCounter3, value, tags, useSpan); }, true); Counter counter4 = meter.CreateCounter("floatCounter"); - InstrumentMeasurementAggregationValidation(counter4, (value, tags) => { counter4.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter4, (value, tags) => { AddToCounter(counter4, value, tags, useSpan); } ); UpDownCounter upDownCounter4 = meter.CreateUpDownCounter("floatUpDownCounter"); - InstrumentMeasurementAggregationValidation(upDownCounter4, (value, tags) => { upDownCounter4.Add(value, tags); }, true); + InstrumentMeasurementAggregationValidation(upDownCounter4, (value, tags) => { AddToUpDownCounter(upDownCounter4, value, tags, useSpan); }, true); Counter counter5 = meter.CreateCounter("doubleCounter"); - InstrumentMeasurementAggregationValidation(counter5, (value, tags) => { counter5.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter5, (value, tags) => { AddToCounter(counter5, value, tags, useSpan); } ); UpDownCounter upDownCounter5 = meter.CreateUpDownCounter("doubleUpDownCounter"); - InstrumentMeasurementAggregationValidation(upDownCounter5, (value, tags) => { upDownCounter5.Add(value, tags); }, true); + InstrumentMeasurementAggregationValidation(upDownCounter5, (value, tags) => { AddToUpDownCounter(upDownCounter5, value, tags, useSpan); }, true); Counter counter6 = meter.CreateCounter("decimalCounter"); - InstrumentMeasurementAggregationValidation(counter6, (value, tags) => { counter6.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter6, (value, tags) => { AddToCounter(counter6, value, tags, useSpan); } ); UpDownCounter upDownCounter6 = meter.CreateUpDownCounter("decimalUpDownCounter"); - InstrumentMeasurementAggregationValidation(upDownCounter6, (value, tags) => { upDownCounter6.Add(value, tags); }, true); + InstrumentMeasurementAggregationValidation(upDownCounter6, (value, tags) => { AddToUpDownCounter(upDownCounter6, value, tags, useSpan); }, true); Histogram histogram = meter.CreateHistogram("byteHistogram"); - InstrumentMeasurementAggregationValidation(histogram, (value, tags) => { histogram.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram, (value, tags) => { Record(histogram, value, tags, useSpan); } ); Histogram histogram1 = meter.CreateHistogram("shortHistogram"); - InstrumentMeasurementAggregationValidation(histogram1, (value, tags) => { histogram1.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram1, (value, tags) => { Record(histogram1, value, tags, useSpan); } ); Histogram histogram2 = meter.CreateHistogram("intHistogram"); - InstrumentMeasurementAggregationValidation(histogram2, (value, tags) => { histogram2.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram2, (value, tags) => { Record(histogram2, value, tags, useSpan); } ); Histogram histogram3 = meter.CreateHistogram("longHistogram"); - InstrumentMeasurementAggregationValidation(histogram3, (value, tags) => { histogram3.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram3, (value, tags) => { Record(histogram3, value, tags, useSpan); } ); Histogram histogram4 = meter.CreateHistogram("floatHistogram"); - InstrumentMeasurementAggregationValidation(histogram4, (value, tags) => { histogram4.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram4, (value, tags) => { Record(histogram4, value, tags, useSpan); } ); Histogram histogram5 = meter.CreateHistogram("doubleHistogram"); - InstrumentMeasurementAggregationValidation(histogram5, (value, tags) => { histogram5.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram5, (value, tags) => { Record(histogram5, value, tags, useSpan); } ); Histogram histogram6 = meter.CreateHistogram("decimalHistogram"); - InstrumentMeasurementAggregationValidation(histogram6, (value, tags) => { histogram6.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram6, (value, tags) => { Record(histogram6, value, tags, useSpan); } ); - }).Dispose(); + }, useSpan.ToString()).Dispose(); + + void AddToCounter(Counter counter, T delta, KeyValuePair[] tags, bool useSpan) where T : struct + { + if (useSpan) + { + counter.Add(delta, (ReadOnlySpan>)tags); + } + else + { + counter.Add(delta, tags); + } + } + + void AddToUpDownCounter(UpDownCounter upDownCounter, T delta, KeyValuePair[] tags, bool useSpan) where T : struct + { + if (useSpan) + { + upDownCounter.Add(delta, (ReadOnlySpan>)tags); + } + else + { + upDownCounter.Add(delta, tags); + } + } + + void Record(Histogram histogram, T value, KeyValuePair[] tags, bool useSpan) where T : struct + { + if (useSpan) + { + histogram.Record(value, (ReadOnlySpan>)tags); + } + else + { + histogram.Record(value, tags); + } + } } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/System.Diagnostics.DiagnosticSource.NativeAotTests.proj b/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/System.Diagnostics.DiagnosticSource.NativeAotTests.proj deleted file mode 100644 index 8001203352b5..000000000000 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/System.Diagnostics.DiagnosticSource.NativeAotTests.proj +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TagListTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TagListTests.cs index 9f35cb9d47c0..59edc168186a 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TagListTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TagListTests.cs @@ -3,7 +3,6 @@ using Xunit; using System.Collections.Generic; -using System.Diagnostics; namespace System.Diagnostics.Tests { @@ -21,7 +20,7 @@ public void TestConstruction() KeyValuePair[] array = new KeyValuePair[tagList.Count]; tagList.CopyTo(array); TagList list = new TagList(array.AsSpan()); - ValidateTags(in tagList, i); + ValidateTags(in list, i); } } @@ -303,7 +302,7 @@ public void TestNegativeCases() Assert.Throws(() => list.RemoveAt(2)); } - private void ValidateTags(in TagList tagList, KeyValuePair[] array) + internal static void ValidateTags(in TagList tagList, KeyValuePair[] array) { Assert.True(tagList.Count <= array.Length); for (int i = 0; i < tagList.Count; i++) @@ -313,7 +312,7 @@ private void ValidateTags(in TagList tagList, KeyValuePair[] ar } } - private void ValidateTags(in TagList tagList, int tagsCount) + internal static void ValidateTags(in TagList tagList, int tagsCount) { Assert.Equal(tagsCount, tagList.Count); for (int i = 0; i < tagList.Count; i++) @@ -323,7 +322,7 @@ private void ValidateTags(in TagList tagList, int tagsCount) } } - private void CreateTagList(int tagsCount, out TagList tagList) + internal static void CreateTagList(int tagsCount, out TagList tagList) { tagList = new TagList(); for (int i = 0; i < tagsCount; i++) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/DiagnosticSourceEventSourceTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TrimmingTests/DiagnosticSourceEventSourceTests.cs similarity index 100% rename from src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/DiagnosticSourceEventSourceTests.cs rename to src/libraries/System.Diagnostics.DiagnosticSource/tests/TrimmingTests/DiagnosticSourceEventSourceTests.cs diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TrimmingTests/System.Diagnostics.DiagnosticSource.proj b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TrimmingTests/System.Diagnostics.DiagnosticSource.proj index ca9483e224ff..919c0b7614b1 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TrimmingTests/System.Diagnostics.DiagnosticSource.proj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TrimmingTests/System.Diagnostics.DiagnosticSource.proj @@ -2,6 +2,8 @@ + diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/default.rd.xml b/src/libraries/System.Diagnostics.DiagnosticSource/tests/default.rd.xml index a235c3f0b8de..73387b8ef62a 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/default.rd.xml +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/default.rd.xml @@ -2,12 +2,6 @@ - - - - - - diff --git a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs index e5cdb63f7ba7..a8f8fd633696 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs +++ b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs @@ -5,7 +5,7 @@ using System; using System.Diagnostics.Eventing.Reader; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.InteropServices.Marshalling; #endif using System.Security; @@ -341,7 +341,7 @@ internal enum EvtLoginClass EvtRpcLogin = 1 } -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #endif [StructLayout(LayoutKind.Sequential)] @@ -355,7 +355,7 @@ internal struct EvtRpcLogin public string Domain; public CoTaskMemUnicodeSafeHandle Password; public int Flags; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(EvtRpcLogin), MarshalMode.ManagedToUnmanagedRef, typeof(ValueMarshaller))] public static class Marshaller { @@ -695,7 +695,7 @@ internal static partial bool EvtRender( out int buffUsed, out int propCount); -#if NET7_0_OR_GREATER +#if NET [NativeMarshalling(typeof(Marshaller))] #endif [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)] @@ -708,7 +708,7 @@ internal struct EvtStringVariant [FieldOffset(12)] public uint Type; -#if NET7_0_OR_GREATER +#if NET [CustomMarshaller(typeof(EvtStringVariant), MarshalMode.Default, typeof(Marshaller))] public static class Marshaller { diff --git a/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/ILLink.Descriptors.xml b/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/ILLink.Descriptors.xml new file mode 100644 index 000000000000..ed3c59f0b70f --- /dev/null +++ b/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/ILLink.Descriptors.xml @@ -0,0 +1,3 @@ + + + diff --git a/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/System.Diagnostics.FileVersionInfo.Tests.csproj b/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/System.Diagnostics.FileVersionInfo.Tests.csproj index 41cc56f94fdf..fa358a2a9089 100644 --- a/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/System.Diagnostics.FileVersionInfo.Tests.csproj +++ b/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/System.Diagnostics.FileVersionInfo.Tests.csproj @@ -52,5 +52,7 @@ + + diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs index f6b7737ef81a..2f7e0847782a 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterLib.cs @@ -13,7 +13,7 @@ using Microsoft.Win32; using static Interop.Advapi32; -#if !NETCOREAPP +#if !NET using MemoryMarshal = System.Diagnostics.PerformanceCounterLib; #endif @@ -120,7 +120,7 @@ internal static string ComputerName } } -#if !NETCOREAPP +#if !NET internal static T Read(ReadOnlySpan span) where T : struct => System.Runtime.InteropServices.MemoryMarshal.Read(span); diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessWaitingTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessWaitingTests.cs index 5cbd89d5a770..8ef602113be2 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessWaitingTests.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessWaitingTests.cs @@ -86,7 +86,7 @@ public void MultipleProcesses_ParallelStartKillWait() p.WaitForExit(WaitInMS); } }; - Task.WaitAll(Enumerable.Range(0, Tasks).Select(_ => Task.Run(work)).ToArray()); + Task.WaitAll(Enumerable.Range(0, Tasks).Select(_ => Task.Run(work))); } [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] @@ -108,7 +108,7 @@ public async Task MultipleProcesses_ParallelStartKillWaitAsync() } }; - await Task.WhenAll(Enumerable.Range(0, Tasks).Select(_ => Task.Run(work)).ToArray()); + await Task.WhenAll(Enumerable.Range(0, Tasks).Select(_ => Task.Run(work))); } [Theory] diff --git a/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/XmlWriterTraceListener.cs b/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/XmlWriterTraceListener.cs index a513b8aa8615..e5b72a51d411 100644 --- a/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/XmlWriterTraceListener.cs +++ b/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/XmlWriterTraceListener.cs @@ -16,7 +16,7 @@ public class XmlWriterTraceListener : TextWriterTraceListener { private const string FixedHeader = ""; - private static volatile string? s_processName; + private static string? s_processName; private readonly string _machineName = Environment.MachineName; private StringBuilder? _strBldr; private XmlTextWriter? _xmlBlobWriter; @@ -252,13 +252,15 @@ private void WriteEndHeader() { if (OperatingSystem.IsBrowser()) // Process isn't supported on Browser { - s_processName = processName = string.Empty; + processName = string.Empty; } else { using Process process = Process.GetCurrentProcess(); - s_processName = processName = process.ProcessName; + processName = process.ProcessName; } + + s_processName = processName; } InternalWrite("\" />"); diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/DefaultTraceListenerClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/DefaultTraceListenerClassTests.cs index efbb26a53a7a..ef84bec4fd21 100644 --- a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/DefaultTraceListenerClassTests.cs +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/DefaultTraceListenerClassTests.cs @@ -159,7 +159,8 @@ public void EntryAssemblyName_Null_NotIncludedInTrace() { RemoteExecutor.Invoke(() => { - MakeAssemblyGetEntryAssemblyReturnNull(); + Assembly.SetEntryAssembly(null); + Assert.Null(Assembly.GetEntryAssembly()); var listener = new TestDefaultTraceListener(); Trace.Listeners.Add(listener); @@ -167,17 +168,5 @@ public void EntryAssemblyName_Null_NotIncludedInTrace() Assert.Equal("Error: 0 : hello world", listener.Output.Trim()); }).Dispose(); } - - /// - /// Makes Assembly.GetEntryAssembly() return null using private reflection. - /// - private static void MakeAssemblyGetEntryAssemblyReturnNull() - { - typeof(Assembly) - .GetField("s_forceNullEntryPoint", BindingFlags.NonPublic | BindingFlags.Static) - .SetValue(null, true); - - Assert.Null(Assembly.GetEntryAssembly()); - } } } diff --git a/src/libraries/System.Diagnostics.Tracing/tests/TrimmingTests/EventSourcePropertyValueTest.cs b/src/libraries/System.Diagnostics.Tracing/tests/TrimmingTests/EventSourcePropertyValueTest.cs index 6682cb0fd45e..e98a84a45ae8 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/TrimmingTests/EventSourcePropertyValueTest.cs +++ b/src/libraries/System.Diagnostics.Tracing/tests/TrimmingTests/EventSourcePropertyValueTest.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; /// @@ -34,6 +35,7 @@ private class TestEventSource : EventSource public TestEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) { } [Event(1)] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(TestSubData))] public void LogData(TestData data) { Write("LogData", data); diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/constants.cs b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/constants.cs index 98be922fbe23..8fe028226b4b 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/constants.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/constants.cs @@ -20,15 +20,15 @@ internal enum LoadState // These are the default options used when a user does not specify a context option to connect to the store. internal static class DefaultContextOptions { - internal static ContextOptions MachineDefaultContextOption = ContextOptions.Negotiate; - internal static ContextOptions ADDefaultContextOption = ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing; + internal const ContextOptions MachineDefaultContextOption = ContextOptions.Negotiate; + internal const ContextOptions ADDefaultContextOption = ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing; } internal static class LdapConstants { - public static int LDAP_SSL_PORT = 636; - public static int LDAP_PORT = 389; - internal static DateTime defaultUtcTime = new DateTime(1601, 1, 1, 0, 0, 0); + public const int LDAP_SSL_PORT = 636; + public const int LDAP_PORT = 389; + internal static readonly DateTime defaultUtcTime = new DateTime(1601, 1, 1, 0, 0, 0); } // The string constants used internally to specify each property internal static class PropertyNames diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.cs index 3dc2a589a8d5..012f137b7df8 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.cs @@ -8,7 +8,7 @@ namespace System.DirectoryServices.Protocols { internal sealed class HGlobalMemHandle : SafeHandleZeroOrMinusOneIsInvalid { - internal static IntPtr _dummyPointer = new IntPtr(1); + internal const IntPtr _dummyPointer = 1; internal HGlobalMemHandle(IntPtr value) : base(true) { diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs index fb663740108b..422c37e70dbb 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs @@ -22,7 +22,7 @@ public static bool IsLibLdapInstalled { get { -#if NETCOREAPP +#if NET if (!_isLibLdapInstalled.HasValue) { if (PlatformDetection.IsApplePlatform) diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/PropertyManager.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/PropertyManager.cs index 278aa9cdad75..9d08baf2f767 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/PropertyManager.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/PropertyManager.cs @@ -8,121 +8,103 @@ namespace System.DirectoryServices.ActiveDirectory { internal static class PropertyManager { - public static string DefaultNamingContext = "defaultNamingContext"; - public static string SchemaNamingContext = "schemaNamingContext"; - public static string ConfigurationNamingContext = "configurationNamingContext"; - public static string RootDomainNamingContext = "rootDomainNamingContext"; - public static string MsDSBehaviorVersion = "msDS-Behavior-Version"; - public static string FsmoRoleOwner = "fsmoRoleOwner"; - public static string ForestFunctionality = "forestFunctionality"; - public static string NTMixedDomain = "ntMixedDomain"; - public static string DomainFunctionality = "domainFunctionality"; - public static string ObjectCategory = "objectCategory"; - public static string SystemFlags = "systemFlags"; - public static string DnsRoot = "dnsRoot"; - public static string DistinguishedName = "distinguishedName"; - public static string TrustParent = "trustParent"; + public const string DefaultNamingContext = "defaultNamingContext"; + public const string SchemaNamingContext = "schemaNamingContext"; + public const string ConfigurationNamingContext = "configurationNamingContext"; + public const string RootDomainNamingContext = "rootDomainNamingContext"; + public const string MsDSBehaviorVersion = "msDS-Behavior-Version"; + public const string FsmoRoleOwner = "fsmoRoleOwner"; + public const string ForestFunctionality = "forestFunctionality"; + public const string NTMixedDomain = "ntMixedDomain"; + public const string DomainFunctionality = "domainFunctionality"; + public const string ObjectCategory = "objectCategory"; + public const string SystemFlags = "systemFlags"; + public const string DnsRoot = "dnsRoot"; + public const string DistinguishedName = "distinguishedName"; + public const string TrustParent = "trustParent"; // disable csharp compiler warning #0414: field assigned unused value #pragma warning disable 0414 - public static string FlatName = "flatName"; - public static string Name = "name"; - public static string Flags = "flags"; - public static string TrustType = "trustType"; - public static string TrustAttributes = "trustAttributes"; + public const string FlatName = "flatName"; + public const string Name = "name"; + public const string Flags = "flags"; + public const string TrustType = "trustType"; + public const string TrustAttributes = "trustAttributes"; #pragma warning restore 0414 - public static string BecomeSchemaMaster = "becomeSchemaMaster"; - public static string BecomeDomainMaster = "becomeDomainMaster"; - public static string BecomePdc = "becomePdc"; - public static string BecomeRidMaster = "becomeRidMaster"; - public static string BecomeInfrastructureMaster = "becomeInfrastructureMaster"; - public static string DnsHostName = "dnsHostName"; - public static string Options = "options"; - public static string CurrentTime = "currentTime"; - public static string HighestCommittedUSN = "highestCommittedUSN"; - public static string OperatingSystem = "operatingSystem"; - public static string HasMasterNCs = "hasMasterNCs"; - public static string MsDSHasMasterNCs = "msDS-HasMasterNCs"; - public static string MsDSHasFullReplicaNCs = "msDS-hasFullReplicaNCs"; - public static string NCName = "nCName"; - public static string Cn = "cn"; - // disable csharp compiler warning #0414: field assigned unused value -#pragma warning disable 0414 - public static string NETBIOSName = "nETBIOSName"; -#pragma warning restore 0414 - public static string DomainDNS = "domainDNS"; - public static string InstanceType = "instanceType"; - public static string MsDSSDReferenceDomain = "msDS-SDReferenceDomain"; - public static string MsDSPortLDAP = "msDS-PortLDAP"; - public static string MsDSPortSSL = "msDS-PortSSL"; - public static string MsDSNCReplicaLocations = "msDS-NC-Replica-Locations"; - public static string MsDSNCROReplicaLocations = "msDS-NC-RO-Replica-Locations"; - public static string SupportedCapabilities = "supportedCapabilities"; - public static string ServerName = "serverName"; - public static string Enabled = "Enabled"; - public static string ObjectGuid = "objectGuid"; - public static string Keywords = "keywords"; - public static string ServiceBindingInformation = "serviceBindingInformation"; - public static string MsDSReplAuthenticationMode = "msDS-ReplAuthenticationMode"; - public static string HasPartialReplicaNCs = "hasPartialReplicaNCs"; - // disable csharp compiler warning #0414: field assigned unused value -#pragma warning disable 0414 - public static string Container = "container"; -#pragma warning restore 0414 - public static string LdapDisplayName = "ldapDisplayName"; - public static string AttributeID = "attributeID"; - public static string AttributeSyntax = "attributeSyntax"; - public static string Description = "description"; - public static string SearchFlags = "searchFlags"; - public static string OMSyntax = "oMSyntax"; - public static string OMObjectClass = "oMObjectClass"; - public static string IsSingleValued = "isSingleValued"; - public static string IsDefunct = "isDefunct"; - public static string RangeUpper = "rangeUpper"; - public static string RangeLower = "rangeLower"; - public static string IsMemberOfPartialAttributeSet = "isMemberOfPartialAttributeSet"; - // disable csharp compiler warning #0414: field assigned unused value -#pragma warning disable 0414 - public static string ObjectVersion = "objectVersion"; -#pragma warning restore 0414 - public static string LinkID = "linkID"; - public static string ObjectClassCategory = "objectClassCategory"; - public static string SchemaUpdateNow = "schemaUpdateNow"; - public static string SubClassOf = "subClassOf"; - public static string SchemaIDGuid = "schemaIDGUID"; - public static string PossibleSuperiors = "possSuperiors"; - public static string PossibleInferiors = "possibleInferiors"; - public static string MustContain = "mustContain"; - public static string MayContain = "mayContain"; - public static string SystemMustContain = "systemMustContain"; - public static string SystemMayContain = "systemMayContain"; - public static string GovernsID = "governsID"; - public static string IsGlobalCatalogReady = "isGlobalCatalogReady"; - // disable csharp compiler warning #0414: field assigned unused value -#pragma warning disable 0414 - public static string NTSecurityDescriptor = "ntSecurityDescriptor"; -#pragma warning restore 0414 - public static string DsServiceName = "dsServiceName"; - public static string ReplicateSingleObject = "replicateSingleObject"; - // disable csharp compiler warning #0414: field assigned unused value -#pragma warning disable 0414 - public static string MsDSMasteredBy = "msDS-masteredBy"; -#pragma warning restore 0414 - public static string DefaultSecurityDescriptor = "defaultSecurityDescriptor"; - public static string NamingContexts = "namingContexts"; - public static string MsDSDefaultNamingContext = "msDS-DefaultNamingContext"; - public static string OperatingSystemVersion = "operatingSystemVersion"; - public static string AuxiliaryClass = "auxiliaryClass"; - public static string SystemAuxiliaryClass = "systemAuxiliaryClass"; - public static string SystemPossibleSuperiors = "systemPossSuperiors"; - public static string InterSiteTopologyGenerator = "interSiteTopologyGenerator"; - public static string FromServer = "fromServer"; - public static string RIDAvailablePool = "rIDAvailablePool"; + public const string BecomeSchemaMaster = "becomeSchemaMaster"; + public const string BecomeDomainMaster = "becomeDomainMaster"; + public const string BecomePdc = "becomePdc"; + public const string BecomeRidMaster = "becomeRidMaster"; + public const string BecomeInfrastructureMaster = "becomeInfrastructureMaster"; + public const string DnsHostName = "dnsHostName"; + public const string Options = "options"; + public const string CurrentTime = "currentTime"; + public const string HighestCommittedUSN = "highestCommittedUSN"; + public const string OperatingSystem = "operatingSystem"; + public const string HasMasterNCs = "hasMasterNCs"; + public const string MsDSHasMasterNCs = "msDS-HasMasterNCs"; + public const string MsDSHasFullReplicaNCs = "msDS-hasFullReplicaNCs"; + public const string NCName = "nCName"; + public const string Cn = "cn"; + public const string NETBIOSName = "nETBIOSName"; + public const string DomainDNS = "domainDNS"; + public const string InstanceType = "instanceType"; + public const string MsDSSDReferenceDomain = "msDS-SDReferenceDomain"; + public const string MsDSPortLDAP = "msDS-PortLDAP"; + public const string MsDSPortSSL = "msDS-PortSSL"; + public const string MsDSNCReplicaLocations = "msDS-NC-Replica-Locations"; + public const string MsDSNCROReplicaLocations = "msDS-NC-RO-Replica-Locations"; + public const string SupportedCapabilities = "supportedCapabilities"; + public const string ServerName = "serverName"; + public const string Enabled = "Enabled"; + public const string ObjectGuid = "objectGuid"; + public const string Keywords = "keywords"; + public const string ServiceBindingInformation = "serviceBindingInformation"; + public const string MsDSReplAuthenticationMode = "msDS-ReplAuthenticationMode"; + public const string HasPartialReplicaNCs = "hasPartialReplicaNCs"; + public const string Container = "container"; + public const string LdapDisplayName = "ldapDisplayName"; + public const string AttributeID = "attributeID"; + public const string AttributeSyntax = "attributeSyntax"; + public const string Description = "description"; + public const string SearchFlags = "searchFlags"; + public const string OMSyntax = "oMSyntax"; + public const string OMObjectClass = "oMObjectClass"; + public const string IsSingleValued = "isSingleValued"; + public const string IsDefunct = "isDefunct"; + public const string RangeUpper = "rangeUpper"; + public const string RangeLower = "rangeLower"; + public const string IsMemberOfPartialAttributeSet = "isMemberOfPartialAttributeSet"; + public const string ObjectVersion = "objectVersion"; + public const string LinkID = "linkID"; + public const string ObjectClassCategory = "objectClassCategory"; + public const string SchemaUpdateNow = "schemaUpdateNow"; + public const string SubClassOf = "subClassOf"; + public const string SchemaIDGuid = "schemaIDGUID"; + public const string PossibleSuperiors = "possSuperiors"; + public const string PossibleInferiors = "possibleInferiors"; + public const string MustContain = "mustContain"; + public const string MayContain = "mayContain"; + public const string SystemMustContain = "systemMustContain"; + public const string SystemMayContain = "systemMayContain"; + public const string GovernsID = "governsID"; + public const string IsGlobalCatalogReady = "isGlobalCatalogReady"; + public const string NTSecurityDescriptor = "ntSecurityDescriptor"; + public const string DsServiceName = "dsServiceName"; + public const string ReplicateSingleObject = "replicateSingleObject"; + public const string MsDSMasteredBy = "msDS-masteredBy"; + public const string DefaultSecurityDescriptor = "defaultSecurityDescriptor"; + public const string NamingContexts = "namingContexts"; + public const string MsDSDefaultNamingContext = "msDS-DefaultNamingContext"; + public const string OperatingSystemVersion = "operatingSystemVersion"; + public const string AuxiliaryClass = "auxiliaryClass"; + public const string SystemAuxiliaryClass = "systemAuxiliaryClass"; + public const string SystemPossibleSuperiors = "systemPossSuperiors"; + public const string InterSiteTopologyGenerator = "interSiteTopologyGenerator"; + public const string FromServer = "fromServer"; + public const string RIDAvailablePool = "rIDAvailablePool"; - // disable csharp compiler warning #0414: field assigned unused value -#pragma warning disable 0414 - public static string SiteList = "siteList"; -#pragma warning restore 0414 - public static string MsDSHasInstantiatedNCs = "msDS-HasInstantiatedNCs"; + public const string SiteList = "siteList"; + public const string MsDSHasInstantiatedNCs = "msDS-HasInstantiatedNCs"; public static object? GetPropertyValue(DirectoryEntry directoryEntry, string propertyName) { diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Utils.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Utils.cs index 56412ca15b02..19a6879f635a 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Utils.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Utils.cs @@ -34,8 +34,8 @@ internal enum SidType internal struct SupportedCapability { - public static string ADOid = "1.2.840.113556.1.4.800"; - public static string ADAMOid = "1.2.840.113556.1.4.1851"; + public const string ADOid = "1.2.840.113556.1.4.800"; + public const string ADAMOid = "1.2.840.113556.1.4.1851"; } internal sealed class Utils diff --git a/src/libraries/System.Formats.Asn1/ref/System.Formats.Asn1.cs b/src/libraries/System.Formats.Asn1/ref/System.Formats.Asn1.cs index bec9d28b7b42..f27056100697 100644 --- a/src/libraries/System.Formats.Asn1/ref/System.Formats.Asn1.cs +++ b/src/libraries/System.Formats.Asn1/ref/System.Formats.Asn1.cs @@ -55,6 +55,7 @@ public AsnContentException(string? message, System.Exception? inner) { } } public static partial class AsnDecoder { + public static int? DecodeLength(System.ReadOnlySpan source, System.Formats.Asn1.AsnEncodingRules ruleSet, out int bytesConsumed) { throw null; } public static byte[] ReadBitString(System.ReadOnlySpan source, System.Formats.Asn1.AsnEncodingRules ruleSet, out int unusedBitCount, out int bytesConsumed, System.Formats.Asn1.Asn1Tag? expectedTag = default(System.Formats.Asn1.Asn1Tag?)) { throw null; } public static bool ReadBoolean(System.ReadOnlySpan source, System.Formats.Asn1.AsnEncodingRules ruleSet, out int bytesConsumed, System.Formats.Asn1.Asn1Tag? expectedTag = default(System.Formats.Asn1.Asn1Tag?)) { throw null; } public static string ReadCharacterString(System.ReadOnlySpan source, System.Formats.Asn1.AsnEncodingRules ruleSet, System.Formats.Asn1.UniversalTagNumber encodingType, out int bytesConsumed, System.Formats.Asn1.Asn1Tag? expectedTag = default(System.Formats.Asn1.Asn1Tag?)) { throw null; } @@ -74,6 +75,7 @@ public static partial class AsnDecoder public static void ReadSequence(System.ReadOnlySpan source, System.Formats.Asn1.AsnEncodingRules ruleSet, out int contentOffset, out int contentLength, out int bytesConsumed, System.Formats.Asn1.Asn1Tag? expectedTag = default(System.Formats.Asn1.Asn1Tag?)) { throw null; } public static void ReadSetOf(System.ReadOnlySpan source, System.Formats.Asn1.AsnEncodingRules ruleSet, out int contentOffset, out int contentLength, out int bytesConsumed, bool skipSortOrderValidation = false, System.Formats.Asn1.Asn1Tag? expectedTag = default(System.Formats.Asn1.Asn1Tag?)) { throw null; } public static System.DateTimeOffset ReadUtcTime(System.ReadOnlySpan source, System.Formats.Asn1.AsnEncodingRules ruleSet, out int bytesConsumed, int twoDigitYearMax = 2049, System.Formats.Asn1.Asn1Tag? expectedTag = default(System.Formats.Asn1.Asn1Tag?)) { throw null; } + public static bool TryDecodeLength(System.ReadOnlySpan source, System.Formats.Asn1.AsnEncodingRules ruleSet, out int? decodedLength, out int bytesConsumed) { throw null; } public static bool TryReadBitString(System.ReadOnlySpan source, System.Span destination, System.Formats.Asn1.AsnEncodingRules ruleSet, out int unusedBitCount, out int bytesConsumed, out int bytesWritten, System.Formats.Asn1.Asn1Tag? expectedTag = default(System.Formats.Asn1.Asn1Tag?)) { throw null; } public static bool TryReadCharacterString(System.ReadOnlySpan source, System.Span destination, System.Formats.Asn1.AsnEncodingRules ruleSet, System.Formats.Asn1.UniversalTagNumber encodingType, out int bytesConsumed, out int charsWritten, System.Formats.Asn1.Asn1Tag? expectedTag = default(System.Formats.Asn1.Asn1Tag?)) { throw null; } public static bool TryReadCharacterStringBytes(System.ReadOnlySpan source, System.Span destination, System.Formats.Asn1.AsnEncodingRules ruleSet, System.Formats.Asn1.Asn1Tag expectedTag, out int bytesConsumed, out int bytesWritten) { throw null; } diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnCharacterStringEncodings.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnCharacterStringEncodings.cs index 48ae19cce80c..e13d5ddfd6f7 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnCharacterStringEncodings.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnCharacterStringEncodings.cs @@ -100,7 +100,7 @@ public override int GetByteCount(string s) } public -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 override #endif int GetByteCount(ReadOnlySpan chars) @@ -135,7 +135,7 @@ public override unsafe int GetCharCount(byte* bytes, int count) } public -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 override #endif int GetCharCount(ReadOnlySpan bytes) @@ -435,7 +435,7 @@ public override int GetByteCount(string s) return s_utf8Encoding.GetByteCount(s); } -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 public override int GetByteCount(ReadOnlySpan chars) { return s_utf8Encoding.GetByteCount(chars); @@ -476,7 +476,7 @@ public override unsafe int GetCharCount(byte* bytes, int count) } } -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 public override int GetCharCount(ReadOnlySpan bytes) { try diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Integer.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Integer.cs index 102b05b82fb3..35372824d35e 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Integer.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Integer.cs @@ -104,7 +104,7 @@ public static BigInteger ReadInteger( { ReadOnlySpan contents = ReadIntegerBytes(source, ruleSet, out int consumed, expectedTag); -#if NETCOREAPP2_1_OR_GREATER +#if NET BigInteger value = new BigInteger(contents, isBigEndian: true); #else byte[] tmp = CryptoPool.Rent(contents.Length); diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Oid.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Oid.cs index fac90e12aec1..33e5a0adb1c9 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Oid.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Oid.cs @@ -61,7 +61,7 @@ public static string ReadObjectIdentifier( UniversalTagNumber.ObjectIdentifier, out int consumed); -#if NETCOREAPP +#if NET string? wellKnown = WellKnownOids.GetValue(contents); if (wellKnown is not null) diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.cs index 6a0bc94a9478..28e55b114bec 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.cs @@ -206,6 +206,86 @@ private static ReadOnlySpan GetPrimitiveContentSpan( return ret; } + /// + /// Decodes the data in as a length value under the specified + /// encoding rules. + /// + /// The buffer containing encoded data. + /// The encoding constraints to use when interpreting the data. + /// + /// When this method returns, the number of bytes from the beginning of + /// that contributed to the length. + /// This parameter is treated as uninitialized. + /// + /// + /// The decoded value of the length, or if the + /// encoded length represents the indefinite length. + /// + /// + /// is not a known value. + /// + /// + /// does not decode as a length under the specified encoding rules. + /// + /// + /// This method only processes the length portion of an ASN.1/BER Tag-Length-Value triplet, + /// so needs to have already sliced off the encoded tag. + /// + public static int? DecodeLength( + ReadOnlySpan source, + AsnEncodingRules ruleSet, + out int bytesConsumed) + { + CheckEncodingRules(ruleSet); + + // Use locals for the outs to hide the intermediate calculations from an out to a field. + int? ret = ReadLength(source, ruleSet, out int read); + bytesConsumed = read; + return ret; + } + + /// + /// Attempts to decode the data in as a length value under the specified + /// encoding rules. + /// + /// The buffer containing encoded data. + /// The encoding constraints to use when interpreting the data. + /// + /// When this method returns, the decoded value of the length, or if the + /// encoded length represents the indefinite length. + /// This parameter is treated as uninitialized. + /// + /// + /// When this method returns, the number of bytes from the beginning of + /// that contributed to the length. + /// This parameter is treated as uninitialized. + /// + /// + /// if the buffer represents a valid length under the specified encoding rules; + /// otherwise, + /// + /// + /// is not a known value. + /// + /// + /// This method only processes the length portion of an ASN.1/BER Tag-Length-Value triplet, + /// so needs to have already sliced off the encoded tag. + /// + public static bool TryDecodeLength( + ReadOnlySpan source, + AsnEncodingRules ruleSet, + out int? decodedLength, + out int bytesConsumed) + { + CheckEncodingRules(ruleSet); + + // Use locals for the outs to hide the intermediate calculations from an out to a field. + bool ret = TryReadLength(source, ruleSet, out int? decoded, out int read); + bytesConsumed = read; + decodedLength = decoded; + return ret; + } + private static bool TryReadLength( ReadOnlySpan source, AsnEncodingRules ruleSet, diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Integer.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Integer.cs index 389196c0acd2..b1720b5106b2 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Integer.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Integer.cs @@ -281,7 +281,7 @@ private void WriteIntegerCore(Asn1Tag tag, BigInteger value) Debug.Assert(!tag.IsConstructed); WriteTag(tag); -#if NETCOREAPP2_1_OR_GREATER +#if NET WriteLength(value.GetByteCount()); // WriteLength ensures the content-space value.TryWriteBytes(_buffer.AsSpan(_offset), out int bytesWritten, isBigEndian: true); diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Oid.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Oid.cs index 7c046016c531..04a063a11fdc 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Oid.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Oid.cs @@ -59,7 +59,7 @@ public void WriteObjectIdentifier(ReadOnlySpan oidValue, Asn1Tag? tag = nu { CheckUniversalTag(tag, UniversalTagNumber.ObjectIdentifier); -#if NETCOREAPP +#if NET ReadOnlySpan wellKnownContents = WellKnownOids.GetContents(oidValue); if (!wellKnownContents.IsEmpty) diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/SetOfValueComparer.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/SetOfValueComparer.cs index 44b6c3030957..d766b5008c32 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/SetOfValueComparer.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/SetOfValueComparer.cs @@ -17,7 +17,7 @@ internal static int Compare(ReadOnlySpan x, ReadOnlySpan y) int min = Math.Min(x.Length, y.Length); int diff; -#if NET7_0_OR_GREATER +#if NET int diffIndex = x.CommonPrefixLength(y); if (diffIndex != min) diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/WellKnownOids.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/WellKnownOids.cs index c308c5af7fd5..215dbe5eb846 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/WellKnownOids.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/WellKnownOids.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETCOREAPP +#if NET namespace System.Formats.Asn1 { internal static class WellKnownOids diff --git a/src/libraries/System.Formats.Asn1/tests/Reader/ReadIA5String.cs b/src/libraries/System.Formats.Asn1/tests/Reader/ReadIA5String.cs index b7a74a95c3ff..b11db277363c 100644 --- a/src/libraries/System.Formats.Asn1/tests/Reader/ReadIA5String.cs +++ b/src/libraries/System.Formats.Asn1/tests/Reader/ReadIA5String.cs @@ -678,7 +678,7 @@ public static void ExpectedTag_IgnoresConstructed( Assert.Equal(val1.ByteArrayToHex(), val2.ByteArrayToHex()); -#if NETCOREAPP +#if NET string expected = Encoding.ASCII.GetString(val1.Span); #else string expected = Encoding.ASCII.GetString(val1.ToArray()); diff --git a/src/libraries/System.Formats.Asn1/tests/Reader/ReadLength.cs b/src/libraries/System.Formats.Asn1/tests/Reader/ReadLength.cs index e2238ce7c687..50dd7f4f9570 100644 --- a/src/libraries/System.Formats.Asn1/tests/Reader/ReadLength.cs +++ b/src/libraries/System.Formats.Asn1/tests/Reader/ReadLength.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Reflection; using Test.Cryptography; using Xunit; @@ -9,15 +8,46 @@ namespace System.Formats.Asn1.Tests.Reader { public sealed class ReadLength { - private delegate Asn1Tag ReadTagAndLengthDelegate( + private static Asn1Tag ReadTagAndLength( ReadOnlySpan source, AsnEncodingRules ruleSet, out int? parsedLength, - out int bytesRead); + out int bytesRead) + { + Asn1Tag tag = Asn1Tag.Decode(source, out int tagLength); + parsedLength = AsnDecoder.DecodeLength(source.Slice(tagLength), ruleSet, out int lengthLength); + bytesRead = tagLength + lengthLength; + return tag; + } + + private static bool TryReadTagAndLength( + ReadOnlySpan source, + AsnEncodingRules ruleSet, + out Asn1Tag tag, + out int? parsedLength, + out int bytesRead) + { + Asn1Tag localTag = Asn1Tag.Decode(source, out int tagLength); + + bool read = AsnDecoder.TryDecodeLength( + source.Slice(tagLength), + ruleSet, + out parsedLength, + out int lengthLength); + + if (read) + { + tag = localTag; + bytesRead = tagLength + lengthLength; + } + else + { + tag = default; + bytesRead = default; + } - private static ReadTagAndLengthDelegate ReadTagAndLength = (ReadTagAndLengthDelegate) - typeof(AsnDecoder).GetMethod("ReadTagAndLength", BindingFlags.Static | BindingFlags.NonPublic) - .CreateDelegate(typeof(ReadTagAndLengthDelegate)); + return read; + } [Theory] [InlineData(4, 0, "0400")] @@ -39,6 +69,13 @@ public static void MinimalPrimitiveLength(int tagValue, int length, string input Assert.False(tag.IsConstructed, "tag.IsConstructed"); Assert.Equal(tagValue, tag.TagValue); Assert.Equal(length, parsedLength.Value); + + Assert.True(TryReadTagAndLength(inputBytes, rules, out tag, out parsedLength, out bytesRead)); + + Assert.Equal(inputBytes.Length, bytesRead); + Assert.False(tag.IsConstructed, "tag.IsConstructed"); + Assert.Equal(tagValue, tag.TagValue); + Assert.Equal(length, parsedLength.Value); } } @@ -51,10 +88,64 @@ public static void ReadWithUnknownRuleSet(int invalidRuleSetValue) Assert.Throws( () => new AsnReader(data, (AsnEncodingRules)invalidRuleSetValue)); + + Assert.Throws( + () => ReadTagAndLength(data, (AsnEncodingRules)invalidRuleSetValue, out _, out _)); + + Assert.Throws( + () => TryReadTagAndLength(data, (AsnEncodingRules)invalidRuleSetValue, out _, out _, out _)); + } + + private static void ReadValid( + ReadOnlySpan source, + AsnEncodingRules ruleSet, + int? expectedLength, + int expectedBytesRead = -1) + { + if (expectedBytesRead < 0) + { + expectedBytesRead = source.Length; + } + + ReadTagAndLength( + source, + ruleSet, + out int? length, + out int bytesRead); + + Assert.Equal(expectedBytesRead, bytesRead); + Assert.Equal(expectedLength, length); + + bool read = TryReadTagAndLength( + source, + ruleSet, + out _, + out length, + out bytesRead); + + Assert.True(read); + Assert.Equal(expectedBytesRead, bytesRead); + Assert.Equal(expectedLength, length); + } + + private static void ReadInvalid(byte[] source, AsnEncodingRules ruleSet) + { + Assert.Throws( + () => ReadTagAndLength(source, ruleSet, out _, out _)); + + Asn1Tag tag; + int? decodedLength; + int bytesConsumed; + + Assert.False( + TryReadTagAndLength(source, ruleSet, out tag, out decodedLength, out bytesConsumed)); + + Assert.True(tag == default); + Assert.Null(decodedLength); + Assert.Equal(0, bytesConsumed); } [Theory] - [InlineData("")] [InlineData("05")] [InlineData("0481")] [InlineData("048201")] @@ -64,8 +155,9 @@ public static void ReadWithInsufficientData(string inputHex) { byte[] inputData = inputHex.HexToByteArray(); - Assert.Throws( - () => ReadTagAndLength(inputData, AsnEncodingRules.DER, out _, out _)); + ReadInvalid(inputData, AsnEncodingRules.BER); + ReadInvalid(inputData, AsnEncodingRules.CER); + ReadInvalid(inputData, AsnEncodingRules.DER); } [Theory] @@ -73,9 +165,6 @@ public static void ReadWithInsufficientData(string inputHex) [InlineData("0xFF-BER", AsnEncodingRules.BER, "04FF")] [InlineData("0xFF-CER", AsnEncodingRules.CER, "04FF")] [InlineData("0xFF-DER", AsnEncodingRules.DER, "04FF")] - [InlineData("CER definite constructed", AsnEncodingRules.CER, "30820500")] - [InlineData("BER indefinite primitive", AsnEncodingRules.BER, "0480" + "0000")] - [InlineData("CER indefinite primitive", AsnEncodingRules.CER, "0480" + "0000")] [InlineData("DER indefinite primitive", AsnEncodingRules.DER, "0480" + "0000")] [InlineData("DER non-minimal 0", AsnEncodingRules.DER, "048100")] [InlineData("DER non-minimal 7F", AsnEncodingRules.DER, "04817F")] @@ -102,10 +191,28 @@ public static void InvalidLengths( { _ = description; byte[] inputData = inputHex.HexToByteArray(); - AsnReader reader = new AsnReader(inputData, rules); - Assert.Throws( - () => ReadTagAndLength(inputData, rules, out _, out _)); + ReadInvalid(inputData, rules); + } + + [Theory] + [InlineData("CER definite constructed", AsnEncodingRules.CER, 0x0500, 4, "30820500")] + [InlineData("BER indefinite primitive", AsnEncodingRules.BER, null, 2, "0480" + "0000")] + [InlineData("CER indefinite primitive", AsnEncodingRules.CER, null, 2, "0480" + "0000")] + public static void ContextuallyInvalidLengths( + string description, + AsnEncodingRules rules, + int? expectedLength, + int expectedBytesRead, + string inputHex) + { + // These inputs will all throw from AsnDecoder.ReadTagAndLength, but require + // the tag as context. + + _ = description; + byte[] inputData = inputHex.HexToByteArray(); + + ReadValid(inputData, rules, expectedLength, expectedBytesRead); } [Theory] @@ -117,18 +224,8 @@ public static void IndefiniteLength(AsnEncodingRules ruleSet) // NULL // End-of-Contents byte[] data = { 0x30, 0x80, 0x05, 0x00, 0x00, 0x00 }; - AsnReader reader = new AsnReader(data, ruleSet); - - Asn1Tag tag = ReadTagAndLength( - data, - ruleSet, - out int? length, - out int bytesRead); - Assert.Equal(2, bytesRead); - Assert.False(length.HasValue, "length.HasValue"); - Assert.Equal((int)UniversalTagNumber.Sequence, tag.TagValue); - Assert.True(tag.IsConstructed, "tag.IsConstructed"); + ReadValid(data, ruleSet, null, 2); } [Theory] @@ -138,42 +235,25 @@ public static void IndefiniteLength(AsnEncodingRules ruleSet) public static void BerNonMinimalLength(int expectedLength, string inputHex) { byte[] inputData = inputHex.HexToByteArray(); - AsnReader reader = new AsnReader(inputData, AsnEncodingRules.BER); - Asn1Tag tag = ReadTagAndLength( - inputData, - AsnEncodingRules.BER, - out int? length, - out int bytesRead); - - Assert.Equal(inputData.Length, bytesRead); - Assert.Equal(expectedLength, length.Value); - // ReadTagAndLength doesn't move the _data span forward. - Assert.True(reader.HasData, "reader.HasData"); + ReadValid(inputData, AsnEncodingRules.BER, expectedLength); + ReadInvalid(inputData, AsnEncodingRules.CER); + ReadInvalid(inputData, AsnEncodingRules.DER); } [Theory] - [InlineData(AsnEncodingRules.BER, 4, 0, 5, "0483000000" + "0500")] - [InlineData(AsnEncodingRules.DER, 1, 1, 2, "0101" + "FF")] - [InlineData(AsnEncodingRules.CER, 0x10, null, 2, "3080" + "0500" + "0000")] + [InlineData(AsnEncodingRules.BER, 0, 5, "0483000000" + "0500")] + [InlineData(AsnEncodingRules.DER, 1, 2, "0101" + "FF")] + [InlineData(AsnEncodingRules.CER, null, 2, "3080" + "0500" + "0000")] public static void ReadWithDataRemaining( AsnEncodingRules ruleSet, - int tagValue, int? expectedLength, int expectedBytesRead, string inputHex) { byte[] inputData = inputHex.HexToByteArray(); - Asn1Tag tag = ReadTagAndLength( - inputData, - ruleSet, - out int? length, - out int bytesRead); - - Assert.Equal(expectedBytesRead, bytesRead); - Assert.Equal(tagValue, tag.TagValue); - Assert.Equal(expectedLength, length); + ReadValid(inputData, ruleSet, expectedLength, expectedBytesRead); } } } diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborConformanceLevel.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborConformanceLevel.cs index b31bbbcd62a2..b46066f061a5 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborConformanceLevel.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborConformanceLevel.cs @@ -207,7 +207,7 @@ public static bool RequireCanonicalSimpleValueEncodings(CborConformanceMode conf public static int GetKeyEncodingHashCode(ReadOnlySpan encoding) { HashCode hash = default; -#if NETCOREAPP +#if NET hash.AddBytes(encoding); #else while (encoding.Length >= sizeof(int)) diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.cs index 988b79dae85f..9354a772f64f 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.cs @@ -241,7 +241,7 @@ private void EnsureWriteCapacity(int pendingCount) { int newCapacity = currentCapacity == 0 ? 1024 : currentCapacity * 2; const uint MaxArrayLength = 0x7FFFFFC7; // Array.MaxLength -#if NETCOREAPP +#if NET Debug.Assert(MaxArrayLength == Array.MaxLength); #endif if ((uint)newCapacity > MaxArrayLength || newCapacity < requiredCapacity) diff --git a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.TextString.cs b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.TextString.cs index 4f6acad8e528..314592bb6f00 100644 --- a/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.TextString.cs +++ b/src/libraries/System.Formats.Cbor/tests/Reader/CborReaderTests.TextString.cs @@ -106,7 +106,7 @@ public static void TryReadTextString_IndefiniteLengthConcatenated_SingleValue__H Assert.True(result); Assert.Equal(expectedValue.Length, charsWritten); Assert.Equal(expectedValue, new string(buffer.Slice(0, charsWritten) -#if !NETCOREAPP +#if !NET .ToArray() #endif )); @@ -136,7 +136,7 @@ public static void TryReadTextString_BufferTooSmall_ShouldReturnFalse(string act Assert.True(result); Assert.Equal(actualValue.Length, charsWritten); Assert.Equal(actualValue, new string(buffer.AsSpan(0, charsWritten) -#if !NETCOREAPP +#if !NET .ToArray() #endif )); @@ -162,7 +162,7 @@ public static void TryReadTextString_IndefiniteLengthConcatenated_BufferTooSmall Assert.True(result); Assert.Equal(expectedValue.Length, charsWritten); Assert.Equal(expectedValue, new string(buffer.AsSpan(0, charsWritten) -#if !NETCOREAPP +#if !NET .ToArray() #endif )); @@ -184,7 +184,7 @@ public static void ReadDefiniteLengthTextStringBytes_SingleValue_HappyPath(strin ReadOnlyMemory resultBytes = reader.ReadDefiniteLengthTextStringBytes(); string result = Encoding.UTF8.GetString(resultBytes.Span -#if !NETCOREAPP +#if !NET .ToArray() #endif ); diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs index df77341be9a0..a3e1bd82d259 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.cs @@ -81,7 +81,7 @@ public TarWriter(Stream archiveStream, TarEntryFormat format = TarEntryFormat.Pa /// /// The format of the entries when writing entries to the archive using the method. /// - public TarEntryFormat Format { get; private set; } + public TarEntryFormat Format { get; } /// /// Disposes the current instance, and closes the archive stream if the leaveOpen argument was set to in the constructor. diff --git a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs index 3d713a514e4a..d77de24adbb0 100644 --- a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs +++ b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs @@ -6,8 +6,8 @@ namespace System.IO.Compression public static partial class ZipFileExtensions { /// - /// Creates a file on the file system with the entry?s contents and the specified name. The last write time of the file is set to the - /// entry?s last write time. This method does not allow overwriting of an existing file with the same name. Attempting to extract explicit + /// Creates a file on the file system with the entry's contents and the specified name. The last write time of the file is set to the + /// entry's last write time. This method does not allow overwriting of an existing file with the same name. Attempting to extract explicit /// directories (entries with names that end in directory separator characters) will not result in the creation of a directory. /// /// @@ -34,8 +34,8 @@ public static void ExtractToFile(this ZipArchiveEntry source, string destination ExtractToFile(source, destinationFileName, false); /// - /// Creates a file on the file system with the entry?s contents and the specified name. - /// The last write time of the file is set to the entry?s last write time. + /// Creates a file on the file system with the entry's contents and the specified name. + /// The last write time of the file is set to the entry's last write time. /// This method does allows overwriting of an existing file with the same name. /// /// diff --git a/src/libraries/System.IO.Compression.ZipFile/tests/System.IO.Compression.ZipFile.Tests.csproj b/src/libraries/System.IO.Compression.ZipFile/tests/System.IO.Compression.ZipFile.Tests.csproj index e07ea71438a4..507e4d5a0fa3 100644 --- a/src/libraries/System.IO.Compression.ZipFile/tests/System.IO.Compression.ZipFile.Tests.csproj +++ b/src/libraries/System.IO.Compression.ZipFile/tests/System.IO.Compression.ZipFile.Tests.csproj @@ -7,7 +7,7 @@ - WasmTestOnBrowser + WasmTestOnChrome $(TestArchiveRoot)browserornodejs/ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ $(DefineConstants);TARGET_BROWSER diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs index 14988fcab728..d54cb5a95471 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs @@ -44,7 +44,7 @@ public partial class ZipArchiveEntry private List? _cdUnknownExtraFields; private List? _lhUnknownExtraFields; private byte[] _fileComment; - private readonly CompressionLevel? _compressionLevel; + private readonly CompressionLevel _compressionLevel; // Initializes a ZipArchiveEntry instance for an existing archive entry. internal ZipArchiveEntry(ZipArchive archive, ZipCentralDirectoryFileHeader cd) @@ -86,7 +86,7 @@ internal ZipArchiveEntry(ZipArchive archive, ZipCentralDirectoryFileHeader cd) _fileComment = cd.FileComment; - _compressionLevel = null; + _compressionLevel = MapCompressionLevel(_generalPurposeBitFlag, CompressionMethod); } // Initializes a ZipArchiveEntry instance for a new archive entry with a specified compression level. @@ -98,6 +98,7 @@ internal ZipArchiveEntry(ZipArchive archive, string entryName, CompressionLevel { CompressionMethod = CompressionMethodValues.Stored; } + _generalPurposeBitFlag = MapDeflateCompressionOption(_generalPurposeBitFlag, _compressionLevel, CompressionMethod); } // Initializes a ZipArchiveEntry instance for a new archive entry. @@ -111,8 +112,9 @@ internal ZipArchiveEntry(ZipArchive archive, string entryName) _versionMadeByPlatform = CurrentZipPlatform; _versionMadeBySpecification = ZipVersionNeededValues.Default; _versionToExtract = ZipVersionNeededValues.Default; // this must happen before following two assignment - _generalPurposeBitFlag = 0; + _compressionLevel = CompressionLevel.Optimal; CompressionMethod = CompressionMethodValues.Deflate; + _generalPurposeBitFlag = MapDeflateCompressionOption(0, _compressionLevel, CompressionMethod); _lastModified = DateTimeOffset.Now; _compressedSize = 0; // we don't know these yet @@ -138,8 +140,6 @@ internal ZipArchiveEntry(ZipArchive archive, string entryName) _fileComment = Array.Empty(); - _compressionLevel = null; - if (_storedEntryNameBytes.Length > ushort.MaxValue) throw new ArgumentException(SR.EntryNamesTooLong); @@ -632,7 +632,7 @@ private CheckSumAndSizeWriteStream GetDataCompressor(Stream backingStream, bool case CompressionMethodValues.Deflate: case CompressionMethodValues.Deflate64: default: - compressorStream = new DeflateStream(backingStream, _compressionLevel ?? CompressionLevel.Optimal, leaveBackingStreamOpen); + compressorStream = new DeflateStream(backingStream, _compressionLevel, leaveBackingStreamOpen); break; } @@ -799,6 +799,46 @@ private bool IsOpenable(bool needToUncompress, bool needToLoadIntoMemory, out st private bool SizesTooLarge() => _compressedSize > uint.MaxValue || _uncompressedSize > uint.MaxValue; + private static CompressionLevel MapCompressionLevel(BitFlagValues generalPurposeBitFlag, CompressionMethodValues compressionMethod) + { + // Information about the Deflate compression option is stored in bits 1 and 2 of the general purpose bit flags. + // If the compression method is not Deflate, the Deflate compression option is invalid - default to NoCompression. + if (compressionMethod == CompressionMethodValues.Deflate || compressionMethod == CompressionMethodValues.Deflate64) + { + return ((int)generalPurposeBitFlag & 0x6) switch + { + 0 => CompressionLevel.Optimal, + 2 => CompressionLevel.SmallestSize, + 4 => CompressionLevel.Fastest, + 6 => CompressionLevel.Fastest, + _ => CompressionLevel.Optimal + }; + } + else + { + return CompressionLevel.NoCompression; + } + } + + private static BitFlagValues MapDeflateCompressionOption(BitFlagValues generalPurposeBitFlag, CompressionLevel compressionLevel, CompressionMethodValues compressionMethod) + { + ushort deflateCompressionOptions = (ushort)( + // The Deflate compression level is only valid if the compression method is actually Deflate (or Deflate64). If it's not, the + // value of the two bits is undefined and they should be zeroed out. + compressionMethod == CompressionMethodValues.Deflate || compressionMethod == CompressionMethodValues.Deflate64 + ? compressionLevel switch + { + CompressionLevel.Optimal => 0, + CompressionLevel.SmallestSize => 2, + CompressionLevel.Fastest => 6, + CompressionLevel.NoCompression => 6, + _ => 0 + } + : 0); + + return (BitFlagValues)(((int)generalPurposeBitFlag & ~0x6) | deflateCompressionOptions); + } + // return value is true if we allocated an extra field for 64 bit headers, un/compressed size private bool WriteLocalFileHeader(bool isEmptyFile) { diff --git a/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj b/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj index 7715606fcfdd..eb974f44651a 100644 --- a/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj +++ b/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj @@ -7,7 +7,7 @@ - WasmTestOnBrowser + WasmTestOnChrome $(TestArchiveRoot)browserornodejs/ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ $(DefineConstants);TARGET_BROWSER diff --git a/src/libraries/System.IO.Compression/tests/ZipArchive/zip_CreateTests.cs b/src/libraries/System.IO.Compression/tests/ZipArchive/zip_CreateTests.cs index fe1daa839bfe..dae65db374f4 100644 --- a/src/libraries/System.IO.Compression/tests/ZipArchive/zip_CreateTests.cs +++ b/src/libraries/System.IO.Compression/tests/ZipArchive/zip_CreateTests.cs @@ -142,6 +142,78 @@ public static void CreateUncompressedArchive() } } + // This test checks to ensure that setting the compression level of an archive entry sets the general-purpose + // bit flags correctly. It verifies that these have been set by reading from the MemoryStream manually, and by + // reopening the generated file to confirm that the compression levels match. + [Theory] + // Special-case NoCompression: in this case, the CompressionMethod becomes Stored and the bits are unset. + [InlineData(CompressionLevel.NoCompression, 0)] + [InlineData(CompressionLevel.Optimal, 0)] + [InlineData(CompressionLevel.SmallestSize, 2)] + [InlineData(CompressionLevel.Fastest, 6)] + public static void CreateArchiveEntriesWithBitFlags(CompressionLevel compressionLevel, ushort expectedGeneralBitFlags) + { + var testfilename = "testfile"; + var testFileContent = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + var utf8WithoutBom = new Text.UTF8Encoding(encoderShouldEmitUTF8Identifier: false); + + byte[] zipFileContent; + + using (var testStream = new MemoryStream()) + { + + using (var zip = new ZipArchive(testStream, ZipArchiveMode.Create)) + { + ZipArchiveEntry newEntry = zip.CreateEntry(testfilename, compressionLevel); + using (var writer = new StreamWriter(newEntry.Open(), utf8WithoutBom)) + { + writer.Write(testFileContent); + writer.Flush(); + } + + ZipArchiveEntry secondNewEntry = zip.CreateEntry(testFileContent + "_post", CompressionLevel.NoCompression); + } + + zipFileContent = testStream.ToArray(); + } + + // expected bit flags are at position 6 in the file header + var generalBitFlags = System.Buffers.Binary.BinaryPrimitives.ReadUInt16LittleEndian(zipFileContent.AsSpan(6)); + + Assert.Equal(expectedGeneralBitFlags, generalBitFlags); + + using (var reReadStream = new MemoryStream(zipFileContent)) + { + using (var reReadZip = new ZipArchive(reReadStream, ZipArchiveMode.Read)) + { + var firstArchive = reReadZip.Entries[0]; + var secondArchive = reReadZip.Entries[1]; + var compressionLevelFieldInfo = typeof(ZipArchiveEntry).GetField("_compressionLevel", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + var generalBitFlagsFieldInfo = typeof(ZipArchiveEntry).GetField("_generalPurposeBitFlag", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + + var reReadCompressionLevel = (CompressionLevel)compressionLevelFieldInfo.GetValue(firstArchive); + var reReadGeneralBitFlags = (ushort)generalBitFlagsFieldInfo.GetValue(firstArchive); + + Assert.Equal(compressionLevel, reReadCompressionLevel); + Assert.Equal(expectedGeneralBitFlags, reReadGeneralBitFlags); + + reReadCompressionLevel = (CompressionLevel)compressionLevelFieldInfo.GetValue(secondArchive); + Assert.Equal(CompressionLevel.NoCompression, reReadCompressionLevel); + + using (var strm = firstArchive.Open()) + { + var readBuffer = new byte[firstArchive.Length]; + + strm.Read(readBuffer); + + var readText = Text.Encoding.UTF8.GetString(readBuffer); + + Assert.Equal(readText, testFileContent); + } + } + } + } + [Fact] public static void CreateNormal_VerifyDataDescriptor() { diff --git a/src/libraries/System.IO.FileSystem.AccessControl/src/System.IO.FileSystem.AccessControl.csproj b/src/libraries/System.IO.FileSystem.AccessControl/src/System.IO.FileSystem.AccessControl.csproj index e120f89518cc..03cbd816a2ff 100644 --- a/src/libraries/System.IO.FileSystem.AccessControl/src/System.IO.FileSystem.AccessControl.csproj +++ b/src/libraries/System.IO.FileSystem.AccessControl/src/System.IO.FileSystem.AccessControl.csproj @@ -95,7 +95,7 @@ - + diff --git a/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs b/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs index 8508ea648b35..e1b0be746f26 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs +++ b/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs @@ -105,8 +105,12 @@ private void StopRaisingEvents() // increased, such that the disposal operation won't take effect and close the handle // until that P/Invoke returns; if during that time the FSW is restarted, the IsHandleInvalid // check will see a valid handle, unless we also null it out. - _directoryHandle.Dispose(); - _directoryHandle = null; + SafeFileHandle? handle = _directoryHandle; + if (handle is not null) + { + _directoryHandle = null; + handle.Dispose(); + } } private void FinalizeDispose() diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.cs index 3a844a60637b..260bf0bdadb3 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.cs @@ -169,7 +169,7 @@ public static uint HashToUInt32(ReadOnlySpan source) => private static uint Update(uint crc, ReadOnlySpan source) { -#if NET7_0_OR_GREATER +#if NET if (CanBeVectorized(source)) { return UpdateVectorized(crc, source); @@ -181,7 +181,7 @@ private static uint Update(uint crc, ReadOnlySpan source) private static uint UpdateScalar(uint crc, ReadOnlySpan source) { -#if NET6_0_OR_GREATER +#if NET // Use ARM intrinsics for CRC if available. This is used for the trailing bytes on the vectorized path // and is the primary method if the vectorized path is unavailable. if (System.Runtime.Intrinsics.Arm.Crc32.Arm64.IsSupported) diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.cs index e9993a7503e7..89b81c657c51 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.cs @@ -167,7 +167,7 @@ public static ulong HashToUInt64(ReadOnlySpan source) => private static ulong Update(ulong crc, ReadOnlySpan source) { -#if NET7_0_OR_GREATER +#if NET if (CanBeVectorized(source)) { return UpdateVectorized(crc, source); diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/NonCryptographicHashAlgorithm.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/NonCryptographicHashAlgorithm.cs index c11622efbbd2..9b18216370a1 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/NonCryptographicHashAlgorithm.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/NonCryptographicHashAlgorithm.cs @@ -156,7 +156,7 @@ private async Task AppendAsyncCore(Stream stream, CancellationToken cancellation while (true) { -#if NETCOREAPP +#if NET int read = await stream.ReadAsync(buffer.AsMemory(), cancellationToken).ConfigureAwait(false); #else int read = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash128.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash128.cs index fdfd24a60ab1..e1181cb73f91 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash128.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash128.cs @@ -17,7 +17,7 @@ namespace System.IO.Hashing /// For methods that persist the computed numerical hash value as bytes, /// the value is written in the Big Endian byte order. /// -#if NET5_0_OR_GREATER +#if NET [SkipLocalsInit] #endif public sealed unsafe class XxHash128 : NonCryptographicHashAlgorithm @@ -51,7 +51,7 @@ public XxHash128(long seed) : base(HashLengthInBytes) /// is null. public static byte[] Hash(byte[] source, long seed) { -#if NET6_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(source); #else if (source is null) @@ -110,7 +110,7 @@ public static bool TryHash(ReadOnlySpan source, Span destination, ou return false; } -#if NET7_0_OR_GREATER +#if NET /// Computes the XXH128 hash of the provided data. /// The data to hash. /// The seed value for this hash computation. The default is zero. @@ -197,7 +197,7 @@ private Hash128 GetCurrentHashAsHash128() return current; } -#if NET7_0_OR_GREATER +#if NET /// Gets the current computed hash value without modifying accumulated state. /// The hash value for the data already provided. [CLSCompliant(false)] diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash3.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash3.cs index 702409b949d4..affdfe78d6a8 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash3.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash3.cs @@ -16,7 +16,7 @@ namespace System.IO.Hashing /// For methods that persist the computed numerical hash value as bytes, /// the value is written in the Big Endian byte order. /// -#if NET5_0_OR_GREATER +#if NET [SkipLocalsInit] #endif public sealed unsafe class XxHash3 : NonCryptographicHashAlgorithm @@ -50,7 +50,7 @@ public XxHash3(long seed) : base(HashLengthInBytes) /// is null. public static byte[] Hash(byte[] source, long seed) { -#if NET6_0_OR_GREATER +#if NET ArgumentNullException.ThrowIfNull(source); #else if (source is null) diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHashShared.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHashShared.cs index bfdf1963ac3b..cafa80dbbf11 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHashShared.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHashShared.cs @@ -6,7 +6,7 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if NET7_0_OR_GREATER +#if NET using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.X86; @@ -15,7 +15,7 @@ namespace System.IO.Hashing { /// Shared implementation of the XXH3 hash algorithm for 64-bit in and version. -#if NET5_0_OR_GREATER +#if NET [SkipLocalsInit] #endif internal static unsafe class XxHashShared @@ -333,7 +333,7 @@ public static void CopyAccumulators(ref State state, ulong* accumulators) { fixed (ulong* stateAccumulators = state.Accumulators) { -#if NET7_0_OR_GREATER +#if NET if (Vector256.IsHardwareAccelerated) { Vector256.Store(Vector256.Load(stateAccumulators), accumulators); @@ -390,7 +390,7 @@ public static void DigestLong(ref State state, ulong* accumulators, byte* secret [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void InitializeAccumulators(ulong* accumulators) { -#if NET7_0_OR_GREATER +#if NET if (Vector256.IsHardwareAccelerated) { Vector256.Store(Vector256.Create(Prime32_3, Prime64_1, Prime64_2, Prime64_3), accumulators); @@ -452,7 +452,7 @@ public static ulong Avalanche(ulong hash) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong Multiply64To128(ulong left, ulong right, out ulong lower) { -#if NET5_0_OR_GREATER +#if NET return Math.BigMul(left, right, out lower); #else ulong lowerLow = Multiply32To64((uint)left, (uint)right); @@ -479,7 +479,7 @@ public static void DeriveSecretFromSeed(byte* destinationSecret, ulong seed) { fixed (byte* defaultSecret = &MemoryMarshal.GetReference(DefaultSecret)) { -#if NET7_0_OR_GREATER +#if NET if (Vector256.IsHardwareAccelerated && BitConverter.IsLittleEndian) { Vector256 seedVec = Vector256.Create(seed, 0u - seed, seed, 0u - seed); @@ -515,7 +515,7 @@ private static void Accumulate(ulong* accumulators, byte* source, byte* secret, byte* secretForAccumulate = secret; byte* secretForScramble = secret + (SecretLengthBytes - StripeLengthBytes); -#if NET7_0_OR_GREATER +#if NET if (Vector256.IsHardwareAccelerated && BitConverter.IsLittleEndian) { Vector256 acc1 = Vector256.Load(accumulators); @@ -620,7 +620,7 @@ public static void Accumulate512(ulong* accumulators, byte* source, byte* secret [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void Accumulate512Inlined(ulong* accumulators, byte* source, byte* secret) { -#if NET7_0_OR_GREATER +#if NET if (Vector256.IsHardwareAccelerated && BitConverter.IsLittleEndian) { for (int i = 0; i < AccumulatorCount / Vector256.Count; i++) @@ -659,7 +659,7 @@ private static void Accumulate512Inlined(ulong* accumulators, byte* source, byte } } -#if NET7_0_OR_GREATER +#if NET [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector256 Accumulate256(Vector256 accVec, byte* source, Vector256 secret) { @@ -714,7 +714,7 @@ private static Vector128 MultiplyWideningLower(Vector128 source) private static void ScrambleAccumulators(ulong* accumulators, byte* secret) { -#if NET7_0_OR_GREATER +#if NET if (Vector256.IsHardwareAccelerated && BitConverter.IsLittleEndian) { for (int i = 0; i < AccumulatorCount / Vector256.Count; i++) @@ -752,7 +752,7 @@ private static void ScrambleAccumulators(ulong* accumulators, byte* secret) } } -#if NET7_0_OR_GREATER +#if NET [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector256 ScrambleAccumulator256(Vector256 accVec, Vector256 secret) { diff --git a/src/libraries/System.IO.Hashing/tests/NonCryptoHashTestDriver.cs b/src/libraries/System.IO.Hashing/tests/NonCryptoHashTestDriver.cs index f2d8e411533e..3204d93d4fb5 100644 --- a/src/libraries/System.IO.Hashing/tests/NonCryptoHashTestDriver.cs +++ b/src/libraries/System.IO.Hashing/tests/NonCryptoHashTestDriver.cs @@ -334,7 +334,7 @@ protected TestCaseBase(string name, byte[] output) internal static string ToHexString(ReadOnlySpan input) { -#if NETCOREAPP +#if NET return Convert.ToHexString(input); #else var builder = new global::System.Text.StringBuilder(input.Length * 2); @@ -350,7 +350,7 @@ internal static string ToHexString(ReadOnlySpan input) internal static byte[] FromHexString(string hexString) { -#if NETCOREAPP +#if NET return Convert.FromHexString(hexString); #else byte[] bytes = new byte[hexString.Length / 2]; @@ -420,7 +420,7 @@ public LargeTestCase(string name, byte data, long repeatCount, string outputHex) public IEnumerable> EnumerateDataChunks() { -#if NET5_0_OR_GREATER +#if NET byte[] chunk = GC.AllocateUninitializedArray(1024 * 1024); #else byte[] chunk = new byte[1024 * 1024]; diff --git a/src/libraries/System.IO.Hashing/tests/XxHash128Tests.cs b/src/libraries/System.IO.Hashing/tests/XxHash128Tests.cs index 8d32a6f06c1d..3ba2044d0695 100644 --- a/src/libraries/System.IO.Hashing/tests/XxHash128Tests.cs +++ b/src/libraries/System.IO.Hashing/tests/XxHash128Tests.cs @@ -41,7 +41,7 @@ public void Hash_OneShot_Expected() Assert.Equal(expectedHash128, ReadHashBigEndian(XxHash128.Hash(input, test.Seed))); Assert.Equal(expectedHash128, ReadHashBigEndian(XxHash128.Hash((ReadOnlySpan)input, test.Seed))); -#if NET7_0_OR_GREATER +#if NET // Validate `XxHash128.HashToUInt128` Assert.Equal(new UInt128(test.HashHigh, test.HashLow), XxHash128.HashToUInt128(input, test.Seed)); #endif @@ -110,7 +110,7 @@ public void Hash_Streaming_Expected() // Validate that the hash we get from doing a one-shot of all the data up to this point // matches the incremental hash for the data appended until now. -#if NET7_0_OR_GREATER +#if NET Assert.Equal(XxHash128.HashToUInt128(asciiBytes.AsSpan(0, processed), test.Seed), hash.GetCurrentHashAsUInt128()); #endif Assert.True(hash.TryGetCurrentHash(destination, out int bytesWritten)); @@ -120,7 +120,7 @@ public void Hash_Streaming_Expected() } // Validate the final hash code. -#if NET7_0_OR_GREATER +#if NET Assert.Equal(new UInt128(test.HashHigh, test.HashLow), hash.GetCurrentHashAsUInt128()); #endif Array.Clear(destination, 0, destination.Length); diff --git a/src/libraries/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj b/src/libraries/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj index 3b224099af76..a11a0d7077cc 100644 --- a/src/libraries/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj +++ b/src/libraries/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj @@ -46,6 +46,7 @@ + diff --git a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/InternalRelationshipCollection.cs b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/InternalRelationshipCollection.cs index b2ace96c8073..d76b0972d017 100644 --- a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/InternalRelationshipCollection.cs +++ b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/InternalRelationshipCollection.cs @@ -320,7 +320,7 @@ private void ProcessRelationshipAttributes(XmlCompatibilityReader reader) { try { -#if NET6_0_OR_GREATER +#if NET relationshipTargetMode = Enum.Parse(targetModeAttributeValue, ignoreCase: false); #else relationshipTargetMode = (TargetMode)(Enum.Parse(typeof(TargetMode), targetModeAttributeValue, ignoreCase: false)); diff --git a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.PackUriScheme.cs b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.PackUriScheme.cs index 2707afbf4b53..8bf3d1e5a0e8 100644 --- a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.PackUriScheme.cs +++ b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.PackUriScheme.cs @@ -285,7 +285,7 @@ private static string EscapeSpecialCharacters(string path) // This is currently enforced by the order of characters in the s_specialCharacterChars array foreach (char c in s_specialCharacterChars) { -#if NET5_0_OR_GREATER +#if NET if (path.Contains(c)) #else if (path.IndexOf(c) != -1) diff --git a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipPackage.cs b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipPackage.cs index c30915c5eacf..2d8f4273ad10 100644 --- a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipPackage.cs +++ b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipPackage.cs @@ -383,7 +383,11 @@ internal static void GetZipCompressionMethodFromOpcCompressionOption( break; case CompressionOption.Maximum: { +#if NET + compressionLevel = CompressionLevel.SmallestSize; +#else compressionLevel = CompressionLevel.Optimal; +#endif } break; case CompressionOption.Fast: diff --git a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipWrappingStream.cs b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipWrappingStream.cs index e3f3b42e7753..2a50857af0e3 100644 --- a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipWrappingStream.cs +++ b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipWrappingStream.cs @@ -67,7 +67,7 @@ int count return _baseStream.Read(buffer, offset, count); } -#if NETCOREAPP +#if NET public override void Write( ReadOnlySpan buffer ) diff --git a/src/libraries/System.IO.Packaging/tests/ReflectionTests.cs b/src/libraries/System.IO.Packaging/tests/ReflectionTests.cs index 78f080aa6ce7..91e31b356e85 100644 --- a/src/libraries/System.IO.Packaging/tests/ReflectionTests.cs +++ b/src/libraries/System.IO.Packaging/tests/ReflectionTests.cs @@ -34,7 +34,7 @@ public void Verify_GeneralPurposeBitFlag_NotSetTo_Unicode() FieldInfo fieldInfo = typeof(ZipArchiveEntry).GetField("_generalPurposeBitFlag", BindingFlags.Instance | BindingFlags.NonPublic); object fieldObject = fieldInfo.GetValue(entry); ushort shortField = (ushort)fieldObject; - Assert.Equal(0, shortField); // If it was UTF8, we would set the general purpose bit flag to 0x800 (UnicodeFileNameAndComment) + Assert.Equal(0, shortField & 0x800); // If it was UTF8, we would set the general purpose bit flag to 0x800 (UnicodeFileNameAndComment) CheckCharacters(entry.Name); CheckCharacters(entry.Comment); // Unavailable in .NET Framework } diff --git a/src/libraries/System.IO.Packaging/tests/Tests.cs b/src/libraries/System.IO.Packaging/tests/Tests.cs index 4d547db5e1c1..2d814bdde505 100644 --- a/src/libraries/System.IO.Packaging/tests/Tests.cs +++ b/src/libraries/System.IO.Packaging/tests/Tests.cs @@ -3988,6 +3988,47 @@ public void CreatePackUriWithFragment() } + [Theory] +#if NET + [InlineData(CompressionOption.NotCompressed, CompressionOption.Normal, 0)] + [InlineData(CompressionOption.Normal, CompressionOption.Normal, 0)] + [InlineData(CompressionOption.Maximum, CompressionOption.Normal, 2)] + [InlineData(CompressionOption.Fast, CompressionOption.Normal, 6)] + [InlineData(CompressionOption.SuperFast, CompressionOption.Normal, 6)] +#else + [InlineData(CompressionOption.NotCompressed, CompressionOption.NotCompressed, 0)] + [InlineData(CompressionOption.Normal, CompressionOption.Normal, 0)] + [InlineData(CompressionOption.Maximum, CompressionOption.Maximum, 2)] + [InlineData(CompressionOption.Fast, CompressionOption.Fast, 4)] + [InlineData(CompressionOption.SuperFast, CompressionOption.SuperFast, 6)] +#endif + public void Roundtrip_Compression_Option(CompressionOption createdCompressionOption, CompressionOption expectedCompressionOption, ushort expectedZipFileBitFlags) + { + var documentPath = "untitled.txt"; + Uri partUriDocument = PackUriHelper.CreatePartUri(new Uri(documentPath, UriKind.Relative)); + + using (MemoryStream ms = new MemoryStream()) + { + Package package = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite); + PackagePart part = package.CreatePart(partUriDocument, "application/text", createdCompressionOption); + + package.Flush(); + package.Close(); + (package as IDisposable).Dispose(); + + ms.Seek(0, SeekOrigin.Begin); + + var zipBytes = ms.ToArray(); + var generalBitFlags = System.Buffers.Binary.BinaryPrimitives.ReadUInt16LittleEndian(zipBytes.AsSpan(6)); + + package = Package.Open(ms, FileMode.Open, FileAccess.Read); + part = package.GetPart(partUriDocument); + + Assert.Equal(expectedZipFileBitFlags, generalBitFlags); + Assert.Equal(expectedCompressionOption, part.CompressionOption); + } + } + private const string DocumentRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; } diff --git a/src/libraries/System.IO.Pipelines/ref/System.IO.Pipelines.csproj b/src/libraries/System.IO.Pipelines/ref/System.IO.Pipelines.csproj index c87749fe9854..7148be9f761d 100644 --- a/src/libraries/System.IO.Pipelines/ref/System.IO.Pipelines.csproj +++ b/src/libraries/System.IO.Pipelines/ref/System.IO.Pipelines.csproj @@ -7,6 +7,11 @@ + + + + + diff --git a/src/libraries/System.IO.Pipelines/src/PACKAGE.md b/src/libraries/System.IO.Pipelines/src/PACKAGE.md index 2bf8184f1c3b..8f3ac7aaeb70 100644 --- a/src/libraries/System.IO.Pipelines/src/PACKAGE.md +++ b/src/libraries/System.IO.Pipelines/src/PACKAGE.md @@ -2,43 +2,48 @@ +A library designed to make it easier to do high-performance I/O. +Apps that parse streaming data are composed of boilerplate code having many specialized and unusual code flows. +The boilerplate and special case code is complex and difficult to maintain. + +`System.IO.Pipelines` was architected to: + +* Have high performance parsing streaming data. +* Reduce code complexity. ## Key Features -* -* -* +* Single producer/single consumer byte buffer management. +* Reduction in code complexity and boilerplate code associated with I/O operations. ## How to Use +Check the [System.IO.Pipelines in .NET article](https://learn.microsoft.com/dotnet/standard/io/pipelines) for a full example. + ## Main Types The main types provided by this library are: -* `` -* `` -* `` +* `System.IO.Pipelines.Pipe` +* `System.IO.Pipelines.PipeWriter` +* `System.IO.Pipelines.PipeReader` ## Additional Documentation -* [Conceptual documentation](https://learn.microsoft.com/dotnet/standard/serialization/**LIBRARYNAME**/overview) -* [API documentation](https://learn.microsoft.com/dotnet/api/**LIBRARYNAME**) - -## Related Packages - - +* [Conceptual documentation](https://learn.microsoft.com/dotnet/standard/io/pipelines) +* [API documentation](https://learn.microsoft.com/dotnet/api/system.io.pipelines) ## Feedback & Contributing -System.IO.Pipelines is released as open source under the [MIT license](https://licenses.nuget.org/MIT). Bug reports and contributions are welcome at [the GitHub repository](https://github.com/dotnet/runtime). \ No newline at end of file +System.IO.Pipelines is released as open source under the [MIT license](https://licenses.nuget.org/MIT). Bug reports and contributions are welcome at [the GitHub repository](https://github.com/dotnet/runtime). diff --git a/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj b/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj index c672633ad168..a4517443d183 100644 --- a/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj +++ b/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj @@ -65,4 +65,12 @@ System.IO.Pipelines.PipeReader + + + + + + + + diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs index 747d23e778f8..0b4d13593a03 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs +++ b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs @@ -171,7 +171,7 @@ public override void Complete(Exception? exception = null) } } -#if NETCOREAPP +#if NET public override ValueTask CompleteAsync(Exception? exception = null) => CompleteAndGetNeedsDispose() ? InnerStream.DisposeAsync() : default; #endif @@ -239,7 +239,7 @@ private ValueTask ReadInternalAsync(int? minimumSize, CancellationTo return Core(this, minimumSize, tokenSource, cancellationToken); -#if NETCOREAPP +#if NET [AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))] #endif static async ValueTask Core(StreamPipeReader reader, int? minimumSize, CancellationTokenSource tokenSource, CancellationToken cancellationToken) diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeWriter.cs b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeWriter.cs index c065df5cd1a1..6f5731a9fbb0 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeWriter.cs +++ b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeWriter.cs @@ -286,7 +286,7 @@ private void Cancel() InternalTokenSource.Cancel(); } -#if NETCOREAPP +#if NET [AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))] #endif private async ValueTask FlushAsyncInternal(bool writeToStream, ReadOnlyMemory data, CancellationToken cancellationToken = default) diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeWriterOptions.cs b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeWriterOptions.cs index 35c1da235f86..15dfc3b0292c 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeWriterOptions.cs +++ b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeWriterOptions.cs @@ -10,7 +10,7 @@ public class StreamPipeWriterOptions { private const int DefaultMinimumBufferSize = 4096; - internal static StreamPipeWriterOptions s_default = new StreamPipeWriterOptions(); + internal static readonly StreamPipeWriterOptions s_default = new StreamPipeWriterOptions(); /// Initializes a instance, optionally specifying a memory pool, a minimum buffer size, and whether the underlying stream should be left open after the completes. /// The memory pool to use when allocating memory. The default value is . diff --git a/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledReadsStream.cs b/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledReadsStream.cs index 0b925b337a74..dc6c6474f1fc 100644 --- a/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledReadsStream.cs +++ b/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledReadsStream.cs @@ -24,7 +24,7 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, return 0; } -#if NETCOREAPP +#if NET public override async ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) { await WaitForReadTask.Task; diff --git a/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledWritesStream.cs b/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledWritesStream.cs index a0e15629cee1..a3bde09cad0a 100644 --- a/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledWritesStream.cs +++ b/src/libraries/System.IO.Pipelines/tests/Infrastructure/CancelledWritesStream.cs @@ -23,7 +23,7 @@ public override async Task WriteAsync(byte[] buffer, int offset, int count, Canc cancellationToken.ThrowIfCancellationRequested(); } -#if NETCOREAPP +#if NET public override async ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) { await WaitForWriteTask.Task; diff --git a/src/libraries/System.IO.Pipelines/tests/Infrastructure/ThrowAfterNWritesStream.cs b/src/libraries/System.IO.Pipelines/tests/Infrastructure/ThrowAfterNWritesStream.cs index b46d0c233ea3..72640a70e4f7 100644 --- a/src/libraries/System.IO.Pipelines/tests/Infrastructure/ThrowAfterNWritesStream.cs +++ b/src/libraries/System.IO.Pipelines/tests/Infrastructure/ThrowAfterNWritesStream.cs @@ -32,7 +32,7 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati return Task.CompletedTask; } -#if NETCOREAPP +#if NET public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) { if (_writes >= _maxWrites) diff --git a/src/libraries/System.IO.Pipelines/tests/PipeReaderCopyToAsyncTests.cs b/src/libraries/System.IO.Pipelines/tests/PipeReaderCopyToAsyncTests.cs index 21228b2a1bf7..3c524de51223 100644 --- a/src/libraries/System.IO.Pipelines/tests/PipeReaderCopyToAsyncTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/PipeReaderCopyToAsyncTests.cs @@ -349,7 +349,7 @@ public override void Write(byte[] buffer, int offset, int count) Check(count); base.Write(buffer, offset, count); } -#if NETCOREAPP3_0_OR_GREATER +#if NET public override void Write(ReadOnlySpan buffer) { Check(buffer.Length); diff --git a/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs b/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs index 2913efbe3cdf..85070e1534a8 100644 --- a/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs @@ -294,7 +294,6 @@ public async Task WritesUsingGetMemoryWorks() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91547", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public async Task CompleteWithLargeWriteThrows() { var completeDelay = TimeSpan.FromMilliseconds(10); diff --git a/src/libraries/System.IO.Pipelines/tests/StreamPipeReaderTests.cs b/src/libraries/System.IO.Pipelines/tests/StreamPipeReaderTests.cs index f70373c58fef..f9fb1f87dbaf 100644 --- a/src/libraries/System.IO.Pipelines/tests/StreamPipeReaderTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/StreamPipeReaderTests.cs @@ -614,7 +614,7 @@ public async Task CompleteCallsAppropriateDisposeMethodOnUnderlyingStream() stream = new(); reader = PipeReader.Create(stream); await reader.CompleteAsync(); -#if NETCOREAPP +#if NET Assert.False(stream.DisposeCalled); Assert.True(stream.DisposeAsyncCalled); #else @@ -661,7 +661,7 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel { throw new OperationCanceledException(); } -#if NETCOREAPP +#if NET public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) { throw new OperationCanceledException(); @@ -696,7 +696,7 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, return bytes; } -#if NETCOREAPP +#if NET public override async ValueTask ReadAsync(Memory destination, CancellationToken cancellationToken = default) { if (_throwOnNextCallToRead) @@ -723,7 +723,7 @@ protected override void Dispose(bool disposing) DisposeCalled = true; } -#if NETCOREAPP +#if NET public override ValueTask DisposeAsync() { DisposeAsyncCalled = true; diff --git a/src/libraries/System.IO.Pipelines/tests/StreamPipeWriterTests.cs b/src/libraries/System.IO.Pipelines/tests/StreamPipeWriterTests.cs index 6b158f8fdb22..3a812857822d 100644 --- a/src/libraries/System.IO.Pipelines/tests/StreamPipeWriterTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/StreamPipeWriterTests.cs @@ -661,7 +661,7 @@ public override Task FlushAsync(CancellationToken cancellationToken) throw new OperationCanceledException(); } -#if NETCOREAPP +#if NET public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) { throw new OperationCanceledException(); diff --git a/src/libraries/System.IO.Pipes.AccessControl/src/System.IO.Pipes.AccessControl.csproj b/src/libraries/System.IO.Pipes.AccessControl/src/System.IO.Pipes.AccessControl.csproj index fcd66e7adf9a..6e48d964b274 100644 --- a/src/libraries/System.IO.Pipes.AccessControl/src/System.IO.Pipes.AccessControl.csproj +++ b/src/libraries/System.IO.Pipes.AccessControl/src/System.IO.Pipes.AccessControl.csproj @@ -19,6 +19,7 @@ Condition="'$(TargetPlatformIdentifier)' == 'windows'" /> + diff --git a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CurrentUserOnly.cs b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CurrentUserOnly.cs index b064ef28ee14..28bbf8c1326e 100644 --- a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CurrentUserOnly.cs +++ b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CurrentUserOnly.cs @@ -131,7 +131,7 @@ public static void CreateMultipleServers_ConnectMultipleClients_MultipleThreads( })); } - Task.WaitAll(tasks.ToArray()); + Task.WaitAll(tasks); } [Theory] diff --git a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialDataReceivedEventArgs.cs b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialDataReceivedEventArgs.cs index 5a8c2a1a6507..7027f0212d5e 100644 --- a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialDataReceivedEventArgs.cs +++ b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialDataReceivedEventArgs.cs @@ -10,6 +10,6 @@ internal SerialDataReceivedEventArgs(SerialData eventCode) EventType = eventCode; } - public SerialData EventType { get; private set; } + public SerialData EventType { get; } } } diff --git a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialErrorReceivedEventArgs.cs b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialErrorReceivedEventArgs.cs index 972783912ae4..d959a8530338 100644 --- a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialErrorReceivedEventArgs.cs +++ b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialErrorReceivedEventArgs.cs @@ -10,6 +10,6 @@ internal SerialErrorReceivedEventArgs(SerialError eventCode) EventType = eventCode; } - public SerialError EventType { get; private set; } + public SerialError EventType { get; } } } diff --git a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPinChangedEventArgs.cs b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPinChangedEventArgs.cs index 46bdf9ef8809..41f2e0e2556d 100644 --- a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPinChangedEventArgs.cs +++ b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPinChangedEventArgs.cs @@ -10,6 +10,6 @@ internal SerialPinChangedEventArgs(SerialPinChange eventCode) EventType = eventCode; } - public SerialPinChange EventType { get; private set; } + public SerialPinChange EventType { get; } } } diff --git a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.Unix.cs b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.Unix.cs index edcf919c2ea6..65bbba57685a 100644 --- a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.Unix.cs +++ b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.Unix.cs @@ -13,7 +13,7 @@ public partial class SerialPort : Component { public static string[] GetPortNames() { -#if NETCOREAPP +#if NET return OperatingSystem.IsLinux() ? GetPortNames_Linux() : OperatingSystem.IsAndroid() ? GetPortNames_Linux() : OperatingSystem.IsMacOS() ? GetPortNames_OSX() diff --git a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.cs b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.cs index 752163fd2bd3..426eb77d637d 100644 --- a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.cs +++ b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialPort.cs @@ -963,7 +963,7 @@ public string ReadExisting() Buffer.BlockCopy(_inBuffer, _readPos, bytesReceived, 0, CachedBytesToRead); } -#if NET7_0_OR_GREATER +#if NET _internalSerialStream.ReadExactly(bytesReceived, CachedBytesToRead, bytesReceived.Length - CachedBytesToRead); // get everything #else int readCount = bytesReceived.Length - CachedBytesToRead; diff --git a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Windows.cs b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Windows.cs index 398eb2817a1d..fa79f2a9c1e0 100644 --- a/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Windows.cs +++ b/src/libraries/System.IO.Ports/src/System/IO/Ports/SerialStream.Windows.cs @@ -562,7 +562,7 @@ internal SerialStream(string portName, int baudRate, Parity parity, int dataBits if (!portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase) || !uint.TryParse( -#if NETCOREAPP +#if NET portName.AsSpan(3), #else portName.Substring(3), diff --git a/src/libraries/System.Linq.Expressions/src/System.Linq.Expressions.csproj b/src/libraries/System.Linq.Expressions/src/System.Linq.Expressions.csproj index 9213e4c6c944..66a070211ddc 100644 --- a/src/libraries/System.Linq.Expressions/src/System.Linq.Expressions.csproj +++ b/src/libraries/System.Linq.Expressions/src/System.Linq.Expressions.csproj @@ -219,6 +219,7 @@ + diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/ExpandoObject.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/ExpandoObject.cs index 46905a8a0b1f..288d01c185db 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/ExpandoObject.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/ExpandoObject.cs @@ -1026,7 +1026,7 @@ private BindingRestrictions GetRestrictions() /// private sealed class ExpandoData { - internal static ExpandoData Empty = new ExpandoData(); + internal static readonly ExpandoData Empty = new ExpandoData(); /// /// the dynamically assigned class associated with the Expando object diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/CacheDict.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/CacheDict.cs index b1446848ce61..9a1c951c1b18 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/CacheDict.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/CacheDict.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Numerics; using System.Threading; namespace System.Dynamic.Utils @@ -40,27 +41,11 @@ internal Entry(int hash, TKey key, TValue value) /// The maximum number of elements to store will be this number aligned to next ^2. internal CacheDict(int size) { - int alignedSize = AlignSize(size); + int alignedSize = (int)BitOperations.RoundUpToPowerOf2((uint)size); _mask = alignedSize - 1; _entries = new Entry[alignedSize]; } - private static int AlignSize(int size) - { - Debug.Assert(size > 0); - - size--; - size |= size >> 1; - size |= size >> 2; - size |= size >> 4; - size |= size >> 8; - size |= size >> 16; - size++; - - Debug.Assert((size & (~size + 1)) == size, "aligned size should be a power of 2"); - return size; - } - /// /// Tries to get the value associated with 'key', returning true if it's found and /// false if it's not present. diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.Generated.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.Generated.cs index 1ebd36b06988..9c1a1fe7c6d2 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.Generated.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.Generated.cs @@ -55,7 +55,7 @@ internal static TypeInfo GetNextTypeInfo(Type initialArg, TypeInfo curTypeInfo) } } - private static TypeInfo _DelegateCache = new TypeInfo(); + private static readonly TypeInfo _DelegateCache = new TypeInfo(); private const int MaximumArity = 17; diff --git a/src/libraries/System.Linq.Expressions/tests/TrimmingTests/System.Linq.Expressions.TrimmingTests.proj b/src/libraries/System.Linq.Expressions/tests/TrimmingTests/System.Linq.Expressions.TrimmingTests.proj index a05afbc2b4c8..d58901c55e5e 100644 --- a/src/libraries/System.Linq.Expressions/tests/TrimmingTests/System.Linq.Expressions.TrimmingTests.proj +++ b/src/libraries/System.Linq.Expressions/tests/TrimmingTests/System.Linq.Expressions.TrimmingTests.proj @@ -2,9 +2,18 @@ - - - + + + true + + + + true + + + + true + diff --git a/src/libraries/System.Linq.Expressions/tests/default.rd.xml b/src/libraries/System.Linq.Expressions/tests/default.rd.xml index 8f9762a7fb73..b3f7ab6dd93c 100644 --- a/src/libraries/System.Linq.Expressions/tests/default.rd.xml +++ b/src/libraries/System.Linq.Expressions/tests/default.rd.xml @@ -17,10 +17,6 @@ - - - - @@ -73,12 +69,6 @@ - - - - - - diff --git a/src/libraries/System.Linq.Parallel/src/System.Linq.Parallel.csproj b/src/libraries/System.Linq.Parallel/src/System.Linq.Parallel.csproj index 3d7f38289ac0..15ff9887505a 100644 --- a/src/libraries/System.Linq.Parallel/src/System.Linq.Parallel.csproj +++ b/src/libraries/System.Linq.Parallel/src/System.Linq.Parallel.csproj @@ -157,6 +157,7 @@ + diff --git a/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Scheduling/Scheduling.cs b/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Scheduling/Scheduling.cs index acc5c8f17037..142ecda782b5 100644 --- a/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Scheduling/Scheduling.cs +++ b/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Scheduling/Scheduling.cs @@ -30,9 +30,8 @@ internal static class Scheduling // Whether to preserve order by default, when neither AsOrdered nor AsUnordered is used. internal const bool DefaultPreserveOrder = false; - // The default degree of parallelism, or -1 if unspecified. Dev unit tests set this value - // to change the default DOP. - internal static int DefaultDegreeOfParallelism = Math.Min(Environment.ProcessorCount, MAX_SUPPORTED_DOP); + // The default degree of parallelism. + internal static readonly int DefaultDegreeOfParallelism = Math.Min(Environment.ProcessorCount, MAX_SUPPORTED_DOP); // The size to use for bounded buffers. internal const int DEFAULT_BOUNDED_BUFFER_CAPACITY = 512; diff --git a/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/PLINQETWProvider.cs b/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/PLINQETWProvider.cs index 7cf1ba84e853..590dbce5a518 100644 --- a/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/PLINQETWProvider.cs +++ b/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/PLINQETWProvider.cs @@ -28,7 +28,7 @@ internal sealed class PlinqEtwProvider : EventSource /// Defines the singleton instance for the PLINQ ETW provider. /// The PLINQ Event provider GUID is {159eeeec-4a14-4418-a8fe-faabcd987887}. /// - internal static PlinqEtwProvider Log = new PlinqEtwProvider(); + internal static readonly PlinqEtwProvider Log = new PlinqEtwProvider(); /// Prevent external instantiation. All logging should go through the Log instance. private PlinqEtwProvider() { } diff --git a/src/libraries/System.Linq.Queryable/src/System.Linq.Queryable.csproj b/src/libraries/System.Linq.Queryable/src/System.Linq.Queryable.csproj index 8298f9380861..343028ced1ad 100644 --- a/src/libraries/System.Linq.Queryable/src/System.Linq.Queryable.csproj +++ b/src/libraries/System.Linq.Queryable/src/System.Linq.Queryable.csproj @@ -19,6 +19,7 @@ + diff --git a/src/libraries/System.Linq.Queryable/tests/TrimCompatibilityTests.cs b/src/libraries/System.Linq.Queryable/tests/TrimCompatibilityTests.cs index 86faa014ef1d..89021695eb35 100644 --- a/src/libraries/System.Linq.Queryable/tests/TrimCompatibilityTests.cs +++ b/src/libraries/System.Linq.Queryable/tests/TrimCompatibilityTests.cs @@ -17,6 +17,7 @@ public class TrimCompatibilityTests /// [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/50712", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/50712", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsAppleMobile))] public static void QueryableMethodsContainCorrectDynamicDependency() { IEnumerable dependentMethods = diff --git a/src/libraries/System.Linq.Queryable/tests/TrimmingTests/System.Linq.Queryable.TrimmingTests.proj b/src/libraries/System.Linq.Queryable/tests/TrimmingTests/System.Linq.Queryable.TrimmingTests.proj index ad8a68f39634..b82b486cc367 100644 --- a/src/libraries/System.Linq.Queryable/tests/TrimmingTests/System.Linq.Queryable.TrimmingTests.proj +++ b/src/libraries/System.Linq.Queryable/tests/TrimmingTests/System.Linq.Queryable.TrimmingTests.proj @@ -2,7 +2,10 @@ - + + + true + diff --git a/src/libraries/System.Linq/tests/ILLink.Descriptors.xml b/src/libraries/System.Linq/tests/ILLink.Descriptors.xml new file mode 100644 index 000000000000..1e87b73c07d1 --- /dev/null +++ b/src/libraries/System.Linq/tests/ILLink.Descriptors.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/libraries/System.Linq/tests/System.Linq.Tests.csproj b/src/libraries/System.Linq/tests/System.Linq.Tests.csproj index de5d8b642a3d..1e4692999a17 100644 --- a/src/libraries/System.Linq/tests/System.Linq.Tests.csproj +++ b/src/libraries/System.Linq/tests/System.Linq.Tests.csproj @@ -5,6 +5,8 @@ + + diff --git a/src/libraries/System.Linq/tests/default.rd.xml b/src/libraries/System.Linq/tests/default.rd.xml index 057eb1783e5d..f7f197214175 100644 --- a/src/libraries/System.Linq/tests/default.rd.xml +++ b/src/libraries/System.Linq/tests/default.rd.xml @@ -382,10 +382,5 @@ - - - - - diff --git a/src/libraries/System.Management/src/System/Management/InteropClasses/WMIInterop.cs b/src/libraries/System.Management/src/System/Management/InteropClasses/WMIInterop.cs index 8dd98bd0f568..8ef0deb6551d 100644 --- a/src/libraries/System.Management/src/System/Management/InteropClasses/WMIInterop.cs +++ b/src/libraries/System.Management/src/System/Management/InteropClasses/WMIInterop.cs @@ -366,7 +366,7 @@ private enum MSHLFLAGS internal sealed class IWbemQualifierSetFreeThreaded : IDisposable { private static readonly string name = typeof(IWbemQualifierSetFreeThreaded).FullName; - public static Guid IID_IWbemClassObject = new Guid("DC12A681-737F-11CF-884D-00AA004B2E24"); + public static readonly Guid IID_IWbemClassObject = new Guid("DC12A681-737F-11CF-884D-00AA004B2E24"); private IntPtr pWbemQualifierSet = IntPtr.Zero; public IWbemQualifierSetFreeThreaded(IntPtr pWbemQualifierSet) diff --git a/src/libraries/System.Memory/ref/System.Memory.cs b/src/libraries/System.Memory/ref/System.Memory.cs index 8aac4764a149..edacc807a04f 100644 --- a/src/libraries/System.Memory/ref/System.Memory.cs +++ b/src/libraries/System.Memory/ref/System.Memory.cs @@ -408,7 +408,7 @@ public static void Sort(this System.Span keys, Sy public static bool TryWrite(this System.Span destination, System.IFormatProvider? provider, System.Text.CompositeFormat format, out int charsWritten, TArg0 arg0, TArg1 arg1) { throw null; } public static bool TryWrite(this System.Span destination, System.IFormatProvider? provider, System.Text.CompositeFormat format, out int charsWritten, TArg0 arg0, TArg1 arg1, TArg2 arg2) { throw null; } public static bool TryWrite(this Span destination, System.IFormatProvider? provider, System.Text.CompositeFormat format, out int charsWritten, params object?[] args) { throw null; } - public static bool TryWrite(this Span destination, System.IFormatProvider? provider, System.Text.CompositeFormat format, out int charsWritten, System.ReadOnlySpan args) { throw null; } + public static bool TryWrite(this Span destination, System.IFormatProvider? provider, System.Text.CompositeFormat format, out int charsWritten, params System.ReadOnlySpan args) { throw null; } [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] [System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute] public ref struct TryWriteInterpolatedStringHandler diff --git a/src/libraries/System.Memory/tests/Span/SearchValues.cs b/src/libraries/System.Memory/tests/Span/SearchValues.cs index f2020279cdf4..f76584e15983 100644 --- a/src/libraries/System.Memory/tests/Span/SearchValues.cs +++ b/src/libraries/System.Memory/tests/Span/SearchValues.cs @@ -68,9 +68,31 @@ public static IEnumerable Values_MemberData() "\uFFFF\uFFFE\uFFFD\uFFFC\uFFFB\uFFFA", "\uFFFF\uFFFE\uFFFD\uFFFC\uFFFB\uFFFB", "\uFFFF\uFFFE\uFFFD\uFFFC\uFFFB\uFFF9", + new string('\u0080', 256) + '\u0082', + new string('\u0080', 100) + '\uF000', + new string('\u0080', 256) + '\uF000', + string.Concat(Enumerable.Range(128, 255).Select(i => (char)i)), + string.Concat(Enumerable.Range(128, 257).Select(i => (char)i)), + string.Concat(Enumerable.Range(128, 254).Select(i => (char)i)) + '\uF000', + string.Concat(Enumerable.Range(128, 256).Select(i => (char)i)) + '\uF000', + '\0' + string.Concat(Enumerable.Range(2, char.MaxValue - 1).Select(i => (char)i)), }; - return values.Select(v => new object[] { v, Encoding.Latin1.GetBytes(v) }); + foreach (string value in values) + { + yield return Pair(value); + yield return Pair('a' + value); + + // Test some more duplicates + if (value.Length > 0) + { + yield return Pair(value + value[0]); + yield return Pair(value[0] + value); + yield return Pair(value + value); + } + } + + static object[] Pair(string value) => new object[] { value, Encoding.Latin1.GetBytes(value) }; } [Theory] @@ -192,10 +214,12 @@ public static void SearchValues_Contains(string needle, byte[] byteNeedle) static void Test(ReadOnlySpan needle, SearchValues values) where T : struct, INumber, IMinMaxValue { + HashSet needleSet = needle.ToArray().ToHashSet(); + for (int i = int.CreateChecked(T.MaxValue); i >= 0; i--) { T t = T.CreateChecked(i); - Assert.Equal(needle.Contains(t), values.Contains(t)); + Assert.Equal(needleSet.Contains(t), values.Contains(t)); } } } diff --git a/src/libraries/System.Memory/tests/default.rd.xml b/src/libraries/System.Memory/tests/default.rd.xml index ab97e03a817e..f6baee8588c7 100644 --- a/src/libraries/System.Memory/tests/default.rd.xml +++ b/src/libraries/System.Memory/tests/default.rd.xml @@ -1,10 +1,5 @@ - - - - - diff --git a/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj b/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj index 4f8e58e36abf..ef01da51d137 100644 --- a/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj +++ b/src/libraries/System.Net.Http.Json/src/System.Net.Http.Json.csproj @@ -53,6 +53,7 @@ System.Net.Http.Json.JsonContent + @@ -65,6 +66,7 @@ System.Net.Http.Json.JsonContent + diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.cs index 2d033b206872..4223cf3e0641 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.cs @@ -95,7 +95,7 @@ public static partial class HttpClientJsonExtensions { // Matches how HttpClient throws a timeout exception. string message = SR.Format(SR.net_http_request_timedout, client.Timeout.TotalSeconds); -#if NETCOREAPP +#if NET throw new TaskCanceledException(message, new TimeoutException(oce.Message, oce), oce.CancellationToken); #else throw new TaskCanceledException(message, new TimeoutException(oce.Message, oce)); diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs index 539df6d3d43f..179cb829ef52 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs @@ -114,7 +114,7 @@ private Task SerializeToStreamAsyncCore(Stream targetStream, CancellationToken c private async Task SerializeToStreamAsyncTranscoding(Stream targetStream, bool async, Encoding targetEncoding, CancellationToken cancellationToken) { // Wrap provided stream into a transcoding stream that buffers the data transcoded from utf-8 to the targetEncoding. -#if NETCOREAPP +#if NET Stream transcodingStream = Encoding.CreateTranscodingStream(targetStream, targetEncoding, Encoding.UTF8, leaveOpen: true); try { diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/LengthLimitReadStream.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/LengthLimitReadStream.cs index 9837587958a9..b40d400f89fb 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/LengthLimitReadStream.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/LengthLimitReadStream.cs @@ -37,7 +37,7 @@ internal static void ThrowExceededBufferLimit(int limit) public override bool CanSeek => _innerStream.CanSeek; public override bool CanWrite => false; -#if NETCOREAPP +#if NET public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => ReadAsync(new Memory(buffer, offset, count), cancellationToken).AsTask(); diff --git a/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpClientJsonExtensionsTests.cs b/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpClientJsonExtensionsTests.cs index fee02cc88229..a57b1cf24f51 100644 --- a/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpClientJsonExtensionsTests.cs +++ b/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpClientJsonExtensionsTests.cs @@ -478,7 +478,7 @@ await LoopbackServer.CreateClientAndServerAsync(async uri => Exception ex = await Assert.ThrowsAsync(() => useDeleteAsync ? client.DeleteFromJsonAsync(uri) : client.GetFromJsonAsync(uri)); -#if NETCOREAPP +#if NET Assert.Contains("HttpClient.Timeout", ex.Message); Assert.IsType(ex.InnerException); #endif @@ -526,7 +526,7 @@ await LoopbackServer.CreateClientAndServerAsync(async uri => } }); -#if NETCOREAPP +#if NET Assert.Contains("HttpClient.Timeout", ex.Message); Assert.IsType(ex.InnerException); #endif diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/NoWriteNoSeekStreamContent.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/NoWriteNoSeekStreamContent.cs index 047ef52edbb5..67992f6b25c4 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/NoWriteNoSeekStreamContent.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/NoWriteNoSeekStreamContent.cs @@ -29,7 +29,7 @@ protected override Task SerializeToStreamAsync(Stream stream, TransportContext? SerializeToStreamAsync(stream, context, CancellationToken.None); #pragma warning disable IDE0060 -#if NETCOREAPP +#if NET protected override #else internal diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpRequestState.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpRequestState.cs index a0af9a557f58..f8b01f140b75 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpRequestState.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpRequestState.cs @@ -157,6 +157,7 @@ public WinHttpTransportContext TransportContext public long CurrentBytesRead { get; set; } private GCHandle _cachedReceivePinnedBuffer; + private GCHandle _cachedSendPinnedBuffer; public void PinReceiveBuffer(byte[] buffer) { @@ -171,6 +172,19 @@ public void PinReceiveBuffer(byte[] buffer) } } + public void PinSendBuffer(byte[] buffer) + { + if (!_cachedSendPinnedBuffer.IsAllocated || _cachedSendPinnedBuffer.Target != buffer) + { + if (_cachedSendPinnedBuffer.IsAllocated) + { + _cachedSendPinnedBuffer.Free(); + } + + _cachedSendPinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); + } + } + #region IDisposable Members private void Dispose(bool disposing) { @@ -193,12 +207,18 @@ private void Dispose(bool disposing) { // This method only gets called when the WinHTTP request handle is fully closed and thus all // async operations are done. So, it is safe at this point to unpin the buffers and release - // the strong GCHandle for this object. + // the strong GCHandle for the pinned buffers. if (_cachedReceivePinnedBuffer.IsAllocated) { _cachedReceivePinnedBuffer.Free(); _cachedReceivePinnedBuffer = default(GCHandle); } + + if (_cachedSendPinnedBuffer.IsAllocated) + { + _cachedSendPinnedBuffer.Free(); + _cachedSendPinnedBuffer = default(GCHandle); + } #if DEBUG Interlocked.Increment(ref s_dbg_operationHandleFree); #endif diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpRequestStream.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpRequestStream.cs index ebbb43eaeedb..64288c537fa6 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpRequestStream.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpRequestStream.cs @@ -24,8 +24,6 @@ internal sealed class WinHttpRequestStream : Stream private readonly SafeWinHttpHandle _requestHandle; private readonly WinHttpChunkMode _chunkedMode; - private GCHandle _cachedSendPinnedBuffer; - internal WinHttpRequestStream(WinHttpRequestState state, WinHttpChunkMode chunkedMode) { _state = state; @@ -182,15 +180,7 @@ internal async Task EndUploadAsync(CancellationToken token) protected override void Dispose(bool disposing) { - if (!_disposed) - { - _disposed = true; - if (_cachedSendPinnedBuffer.IsAllocated) - { - _cachedSendPinnedBuffer.Free(); - } - } - + _disposed = true; base.Dispose(disposing); } @@ -234,16 +224,7 @@ private Task InternalWriteDataAsync(byte[] buffer, int offset, int count, { Debug.Assert(count > 0); - if (!_cachedSendPinnedBuffer.IsAllocated || _cachedSendPinnedBuffer.Target != buffer) - { - if (_cachedSendPinnedBuffer.IsAllocated) - { - _cachedSendPinnedBuffer.Free(); - } - - _cachedSendPinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); - } - + _state.PinSendBuffer(buffer); _state.TcsInternalWriteDataToRequestStream = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseStream.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseStream.cs index dccbaea01da0..5482588aa2f5 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseStream.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseStream.cs @@ -154,7 +154,7 @@ private async Task CopyToAsyncCore(Stream destination, byte[] buffer, Cancellati Debug.Assert(bytesRead > 0); // Write that data out to the output stream -#if NETSTANDARD2_1 || NETCOREAPP +#if NETSTANDARD2_1 || NET await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false); #else await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false); diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpTrailersHelper.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpTrailersHelper.cs index 2bf4de4e34eb..e4f4257a366f 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpTrailersHelper.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpTrailersHelper.cs @@ -11,7 +11,7 @@ namespace System.Net.Http internal static class WinHttpTrailersHelper { // UNITTEST is true when building against WinHttpHandler.Unit.Tests, which includes the source file. -#if !NETSTANDARD2_1 && !NETCOREAPP && !UNITTEST +#if !NETSTANDARD2_1 && !NET && !UNITTEST // Trailer property name was chosen to be descriptive and be unlikely to collide with a user set property. // Apps and libraries will use this key so it shouldn't change. private const string RequestMessagePropertyName = "__ResponseTrailers"; @@ -24,7 +24,7 @@ private sealed class HttpResponseTrailers : HttpHeaders public static HttpHeaders GetResponseTrailers(HttpResponseMessage response) { -#if NETSTANDARD2_1 || NETCOREAPP || UNITTEST +#if NETSTANDARD2_1 || NET || UNITTEST return response.TrailingHeaders; #else HttpResponseTrailers responseTrailers = new HttpResponseTrailers(); diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs index b75571770fa9..0d2165eda36e 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs @@ -82,7 +82,7 @@ public sealed class PlatformHandler_HttpClientEKUTest : HttpClientEKUTest public PlatformHandler_HttpClientEKUTest(ITestOutputHelper output) : base(output) { } } -#if NETCOREAPP +#if NET public sealed class PlatformHandler_HttpClientHandler_Decompression_Tests : HttpClientHandler_Decompression_Test { public PlatformHandler_HttpClientHandler_Decompression_Tests(ITestOutputHelper output) : base(output) { } @@ -182,7 +182,7 @@ public sealed class PlatformHandler_HttpClientHandler_Authentication_Test : Http public PlatformHandler_HttpClientHandler_Authentication_Test(ITestOutputHelper output) : base(output) { } } -#if NETCOREAPP +#if NET #if !WINHTTPHANDLER_TEST // [ActiveIssue("https://github.com/dotnet/runtime/issues/33930")] [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsWindows10Version1607OrGreater))] public sealed class PlatformHandlerTest_Cookies_Http2 : HttpClientHandlerTest_Cookies diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj index 26e14365f292..e4ffec94743f 100644 --- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj @@ -164,6 +164,8 @@ Link="Common\System\Text\ValueStringBuilder.AppendSpanFormattable.cs" /> + @@ -173,6 +175,12 @@ + + + + + + @@ -199,7 +207,6 @@ - @@ -211,6 +218,7 @@ + diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaderParser.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaderParser.cs index 711e37cf1469..25449e6b5d36 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaderParser.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaderParser.cs @@ -13,11 +13,11 @@ internal abstract class HttpHeaderParser public const string DefaultSeparator = ", "; public static readonly byte[] DefaultSeparatorBytes = ", "u8.ToArray(); - public bool SupportsMultipleValues { get; private set; } + public bool SupportsMultipleValues { get; } - public string Separator { get; private set; } + public string Separator { get; } - public byte[] SeparatorBytes { get; private set; } + public byte[] SeparatorBytes { get; } // If ValueType implements Equals() as required, there is no need to provide a comparer. A comparer is needed // e.g. if we want to compare strings using case-insensitive comparison. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.cs index 4b04787d3acd..0d647385f996 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.cs @@ -776,15 +776,10 @@ protected internal override Task SendAsync(HttpRequestMessa // lazy-load the validator func so it can be trimmed by the ILLinker if it isn't used. private static Func? s_dangerousAcceptAnyServerCertificateValidator; [UnsupportedOSPlatform("browser")] - public static Func DangerousAcceptAnyServerCertificateValidator - { - get - { - return Volatile.Read(ref s_dangerousAcceptAnyServerCertificateValidator) ?? - Interlocked.CompareExchange(ref s_dangerousAcceptAnyServerCertificateValidator, delegate { return true; }, null) ?? - s_dangerousAcceptAnyServerCertificateValidator; - } - } + public static Func DangerousAcceptAnyServerCertificateValidator => + s_dangerousAcceptAnyServerCertificateValidator ?? + Interlocked.CompareExchange(ref s_dangerousAcceptAnyServerCertificateValidator, delegate { return true; }, null) ?? + s_dangerousAcceptAnyServerCertificateValidator; private void ThrowForModifiedManagedSslOptionsIfStarted() { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs index 9c3935701e82..7a6edd71053b 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs @@ -363,7 +363,7 @@ protected internal override Task SendAsync(HttpRequestMessa private static Func? s_dangerousAcceptAnyServerCertificateValidator; [UnsupportedOSPlatform("browser")] public static Func DangerousAcceptAnyServerCertificateValidator => - Volatile.Read(ref s_dangerousAcceptAnyServerCertificateValidator) ?? + s_dangerousAcceptAnyServerCertificateValidator ?? Interlocked.CompareExchange(ref s_dangerousAcceptAnyServerCertificateValidator, delegate { return true; }, null) ?? s_dangerousAcceptAnyServerCertificateValidator; diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.NtAuth.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.NtAuth.cs index ae572bbdcdf2..65c355595462 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.NtAuth.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.NtAuth.cs @@ -8,6 +8,7 @@ using System.Net.Http.Headers; using System.Net.Security; using System.Security.Authentication.ExtendedProtection; +using System.Security.Principal; using System.Threading; using System.Threading.Tasks; @@ -72,7 +73,7 @@ private static bool ProxySupportsConnectionAuth(HttpResponseMessage response) return false; } - private static async Task SendWithNtAuthAsync(HttpRequestMessage request, Uri authUri, bool async, ICredentials credentials, bool isProxyAuth, HttpConnection connection, HttpConnectionPool connectionPool, CancellationToken cancellationToken) + private static async Task SendWithNtAuthAsync(HttpRequestMessage request, Uri authUri, bool async, ICredentials credentials, TokenImpersonationLevel impersonationLevel, bool isProxyAuth, HttpConnection connection, HttpConnectionPool connectionPool, CancellationToken cancellationToken) { HttpResponseMessage response = await InnerSendAsync(request, async, isProxyAuth, connectionPool, connection, cancellationToken).ConfigureAwait(false); if (!isProxyAuth && connection.Kind == HttpConnectionKind.Proxy && !ProxySupportsConnectionAuth(response)) @@ -173,7 +174,8 @@ private static async Task SendWithNtAuthAsync(HttpRequestMe Credential = challenge.Credential, TargetName = spn, RequiredProtectionLevel = requiredProtectionLevel, - Binding = connection.TransportContext?.GetChannelBinding(ChannelBindingKind.Endpoint) + Binding = connection.TransportContext?.GetChannelBinding(ChannelBindingKind.Endpoint), + AllowedImpersonationLevel = impersonationLevel }; using NegotiateAuthentication authContext = new NegotiateAuthentication(authClientOptions); @@ -203,7 +205,7 @@ private static async Task SendWithNtAuthAsync(HttpRequestMe if (!IsAuthenticationChallenge(response, isProxyAuth)) { - // Tail response for Negoatiate on successful authentication. Validate it before we proceed. + // Tail response for Negotiate on successful authentication. Validate it before we proceed. authContext.GetOutgoingBlob(challengeData, out statusCode); if (statusCode > NegotiateAuthenticationStatusCode.ContinueNeeded) { @@ -230,15 +232,15 @@ private static async Task SendWithNtAuthAsync(HttpRequestMe return response!; } - public static Task SendWithNtProxyAuthAsync(HttpRequestMessage request, Uri proxyUri, bool async, ICredentials proxyCredentials, HttpConnection connection, HttpConnectionPool connectionPool, CancellationToken cancellationToken) + public static Task SendWithNtProxyAuthAsync(HttpRequestMessage request, Uri proxyUri, bool async, ICredentials proxyCredentials, TokenImpersonationLevel impersonationLevel, HttpConnection connection, HttpConnectionPool connectionPool, CancellationToken cancellationToken) { - return SendWithNtAuthAsync(request, proxyUri, async, proxyCredentials, isProxyAuth: true, connection, connectionPool, cancellationToken); + return SendWithNtAuthAsync(request, proxyUri, async, proxyCredentials, impersonationLevel, isProxyAuth: true, connection, connectionPool, cancellationToken); } - public static Task SendWithNtConnectionAuthAsync(HttpRequestMessage request, bool async, ICredentials credentials, HttpConnection connection, HttpConnectionPool connectionPool, CancellationToken cancellationToken) + public static Task SendWithNtConnectionAuthAsync(HttpRequestMessage request, bool async, ICredentials credentials, TokenImpersonationLevel impersonationLevel, HttpConnection connection, HttpConnectionPool connectionPool, CancellationToken cancellationToken) { Debug.Assert(request.RequestUri != null); - return SendWithNtAuthAsync(request, request.RequestUri, async, credentials, isProxyAuth: false, connection, connectionPool, cancellationToken); + return SendWithNtAuthAsync(request, request.RequestUri, async, credentials, impersonationLevel, isProxyAuth: false, connection, connectionPool, cancellationToken); } } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs index 639e0367ba5a..69f01907167c 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs @@ -215,11 +215,12 @@ private static async ValueTask SendWithAuthAsync(HttpReques // If preauth is enabled and this isn't proxy auth, try to get a basic credential from the // preauth credentials cache, and if successful, set an auth header for it onto the request. // Currently we only support preauth for Basic. - bool performedBasicPreauth = false; + NetworkCredential? preAuthCredential = null; + Uri? preAuthCredentialUri = null; if (preAuthenticate) { Debug.Assert(pool.PreAuthCredentials != null); - NetworkCredential? credential; + (Uri uriPrefix, NetworkCredential credential)? preAuthCredentialPair; lock (pool.PreAuthCredentials) { // Just look for basic credentials. If in the future we support preauth @@ -227,13 +228,13 @@ private static async ValueTask SendWithAuthAsync(HttpReques Debug.Assert(pool.PreAuthCredentials.GetCredential(authUri, NegotiateScheme) == null); Debug.Assert(pool.PreAuthCredentials.GetCredential(authUri, NtlmScheme) == null); Debug.Assert(pool.PreAuthCredentials.GetCredential(authUri, DigestScheme) == null); - credential = pool.PreAuthCredentials.GetCredential(authUri, BasicScheme); + preAuthCredentialPair = pool.PreAuthCredentials.GetCredential(authUri, BasicScheme); } - if (credential != null) + if (preAuthCredentialPair != null) { - SetBasicAuthToken(request, credential, isProxyAuth); - performedBasicPreauth = true; + (preAuthCredentialUri, preAuthCredential) = preAuthCredentialPair.Value; + SetBasicAuthToken(request, preAuthCredential, isProxyAuth); } } @@ -265,13 +266,21 @@ await TrySetDigestAuthToken(request, challenge.Credential, digestResponse, isPro break; case AuthenticationType.Basic: - if (performedBasicPreauth) + if (preAuthCredential != null) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.AuthenticationError(authUri, $"Pre-authentication with {(isProxyAuth ? "proxy" : "server")} failed."); } - break; + + if (challenge.Credential == preAuthCredential) + { + // Pre auth failed, and user supplied credentials are still same, we can stop there. + break; + } + + // Pre-auth credentials have changed, continue with the new ones. + // The old ones will be removed below. } response.Dispose(); @@ -293,6 +302,17 @@ await TrySetDigestAuthToken(request, challenge.Credential, digestResponse, isPro default: lock (pool.PreAuthCredentials!) { + // remove previously cached (failing) creds + if (preAuthCredentialUri != null) + { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(pool.PreAuthCredentials, $"Removing Basic credential from cache, uri={preAuthCredentialUri}, username={preAuthCredential!.UserName}"); + } + + pool.PreAuthCredentials.Remove(preAuthCredentialUri, BasicScheme); + } + try { if (NetEventSource.Log.IsEnabled()) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http1.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http1.cs new file mode 100644 index 000000000000..80d506b00d0a --- /dev/null +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http1.cs @@ -0,0 +1,432 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http +{ + internal sealed partial class HttpConnectionPool + { + /// Stack of currently available HTTP/1.1 connections stored in the pool. + private readonly ConcurrentStack _http11Connections = new(); + /// Controls whether we can use a fast path when returning connections to the pool and skip calling into . + private bool _http11RequestQueueIsEmptyAndNotDisposed; + /// The maximum number of HTTP/1.1 connections allowed to be associated with the pool. + private readonly int _maxHttp11Connections; + /// The number of HTTP/1.1 connections associated with the pool, including in use, available, and pending. + private int _associatedHttp11ConnectionCount; + /// The number of HTTP/1.1 connections that are in the process of being established. + private int _pendingHttp11ConnectionCount; + /// Queue of requests waiting for an HTTP/1.1 connection. + private RequestQueue _http11RequestQueue; + + /// For non-proxy connection pools, this is the host name in bytes; for proxies, null. + private readonly byte[]? _hostHeaderLineBytes; + + public byte[]? HostHeaderLineBytes => _hostHeaderLineBytes; + + private bool TryGetPooledHttp11Connection(HttpRequestMessage request, bool async, [NotNullWhen(true)] out HttpConnection? connection, [NotNullWhen(false)] out HttpConnectionWaiter? waiter) + { + while (_http11Connections.TryPop(out connection)) + { + if (CheckExpirationOnGet(connection)) + { + if (NetEventSource.Log.IsEnabled()) connection.Trace("Found expired HTTP/1.1 connection in pool."); + connection.Dispose(); + continue; + } + + if (!connection.PrepareForReuse(async)) + { + if (NetEventSource.Log.IsEnabled()) connection.Trace("Found invalid HTTP/1.1 connection in pool."); + connection.Dispose(); + continue; + } + + if (NetEventSource.Log.IsEnabled()) connection.Trace("Found usable HTTP/1.1 connection in pool."); + waiter = null; + return true; + } + + // Slow path - no available connection found. + // Push the request onto the request queue and check if we should inject a new connection. + + waiter = new HttpConnectionWaiter(); + + // Technically this block under the lock could be a part of ProcessHttp11RequestQueue to avoid taking the lock twice. + // It is kept separate to simplify that method (avoid extra arguments that are only relevant for this caller). + lock (SyncObj) + { + _http11RequestQueue.EnqueueRequest(request, waiter); + + // Disable the fast path and force connections returned to the pool to check the request queue first. + _http11RequestQueueIsEmptyAndNotDisposed = false; + } + + // Other threads may have added a connection to the pool before we were able to + // add the request to the queue, so we must check for an available connection again. + + ProcessHttp11RequestQueue(null); + return false; + } + + /// + /// This method is called: + ///
    - When returning a connection and observing that the request queue is not empty ( is ). + ///
    - After adding a request to the queue if we fail to obtain a connection from . + ///
    - After scavenging or disposing the pool to ensure that any pending requests are handled or connections disposed. + /// The method will attempt to match one request from the to an available connection. + /// The can either be provided as an argument (when returning a connection to the pool), or one will be rented from . + /// As we'll only process a single request, we are expecting the method to be called every time a request is enqueued, and every time a connection is returned while the request queue is not empty. + /// If the becomes empty, this method will reset the flag back to , + /// such that returning connections will use the fast path again and skip calling into this method. + /// Notably, this method will not be called on the fast path as long as we have enough connections to handle all new requests. + ///
    + /// The connection to use for a pending request, or return to the pool. + private void ProcessHttp11RequestQueue(HttpConnection? connection) + { + // Loop in case the request we try to signal was already cancelled or handled by a different connection. + while (true) + { + HttpConnectionWaiter? waiter = null; + + lock (SyncObj) + { +#if DEBUG + // Other threads may still interact with the connections stack. Read the count once to keep the assert message accurate. + int connectionCount = _http11Connections.Count; + Debug.Assert(_associatedHttp11ConnectionCount >= connectionCount + _pendingHttp11ConnectionCount, + $"Expected {_associatedHttp11ConnectionCount} >= {connectionCount} + {_pendingHttp11ConnectionCount}"); +#endif + Debug.Assert(_associatedHttp11ConnectionCount <= _maxHttp11Connections, + $"Expected {_associatedHttp11ConnectionCount} <= {_maxHttp11Connections}"); + Debug.Assert(_associatedHttp11ConnectionCount >= _pendingHttp11ConnectionCount, + $"Expected {_associatedHttp11ConnectionCount} >= {_pendingHttp11ConnectionCount}"); + + if (_http11RequestQueue.Count != 0) + { + if (connection is not null || _http11Connections.TryPop(out connection)) + { + // TryDequeueWaiter will prune completed requests from the head of the queue, + // so it's possible for it to return false even though we checked that Count != 0. + bool success = _http11RequestQueue.TryDequeueWaiter(this, out waiter); + Debug.Assert(success == waiter is not null); + } + } + + // Update the empty queue flag now. + // If the request queue is now empty, returning connections will use the fast path and skip calling into this method. + _http11RequestQueueIsEmptyAndNotDisposed = _http11RequestQueue.Count == 0 && !_disposed; + + if (waiter is null) + { + // We didn't find a waiter to signal, or there were no connections available. + + if (connection is not null) + { + // A connection was provided to this method, or we rented one from the pool. + // Return it back to the pool since we're not going to use it yet. + + // We're returning it while holding the lock to avoid a scenario where + // - thread A sees no requests are waiting in the queue (current thread) + // - thread B adds a request to the queue, and sees no connections are available + // - thread A returns the connection to the pool + // We'd have both a connection and a request waiting in the pool, but nothing to pair the two. + + // The main scenario where we'll reach this branch is when we enqueue a request to the queue + // and set the _http11RequestQueueIsEmptyAndNotDisposed flag to false, followed by multiple + // returning connections observing the flag and calling into this method before we clear the flag. + // This should be a relatively rare case, so the added contention should be minimal. + _http11Connections.Push(connection); + } + else + { + CheckForHttp11ConnectionInjection(); + } + + break; + } + } + + Debug.Assert(connection is not null); + + if (waiter.TrySignal(connection)) + { + // Success. Note that we did not call connection.PrepareForReuse + // before signaling the waiter. This is intentional, as the fact that + // this method was called indicates that the connection is either new, + // or was just returned to the pool and is still in a good state. + return; + } + + // The request was already cancelled or handled by a different connection. + // Loop again to try to find another request to signal, or return the connection. + } + + if (_disposed) + { + // The pool is being disposed and there are no more requests to handle. + // Clean up any idle connections still waiting in the pool. + while (_http11Connections.TryPop(out connection)) + { + connection.Dispose(); + } + } + } + + private void CheckForHttp11ConnectionInjection() + { + Debug.Assert(HasSyncObjLock); + + _http11RequestQueue.PruneCompletedRequestsFromHeadOfQueue(this); + + // Determine if we can and should add a new connection to the pool. + bool willInject = + _http11RequestQueue.Count > _pendingHttp11ConnectionCount && // More requests queued than pending connections + _associatedHttp11ConnectionCount < _maxHttp11Connections && // Under the connection limit + _http11RequestQueue.RequestsWithoutAConnectionAttempt > 0; // There are requests we haven't issued a connection attempt for + + if (NetEventSource.Log.IsEnabled()) + { + Trace($"Available HTTP/1.1 connections: {_http11Connections.Count}, Requests in the queue: {_http11RequestQueue.Count}, " + + $"Requests without a connection attempt: {_http11RequestQueue.RequestsWithoutAConnectionAttempt}, " + + $"Pending HTTP/1.1 connections: {_pendingHttp11ConnectionCount}, Total associated HTTP/1.1 connections: {_associatedHttp11ConnectionCount}, " + + $"Max HTTP/1.1 connection limit: {_maxHttp11Connections}, " + + $"Will inject connection: {willInject}."); + } + + if (willInject) + { + _associatedHttp11ConnectionCount++; + _pendingHttp11ConnectionCount++; + + RequestQueue.QueueItem queueItem = _http11RequestQueue.PeekNextRequestForConnectionAttempt(); + _ = InjectNewHttp11ConnectionAsync(queueItem); // ignore returned task + } + } + + private async Task InjectNewHttp11ConnectionAsync(RequestQueue.QueueItem queueItem) + { + if (NetEventSource.Log.IsEnabled()) Trace("Creating new HTTP/1.1 connection for pool."); + + // Queue the remainder of the work so that this method completes quickly + // and escapes locks held by the caller. + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); + + HttpConnectionWaiter waiter = queueItem.Waiter; + HttpConnection? connection = null; + Exception? connectionException = null; + + CancellationTokenSource cts = GetConnectTimeoutCancellationTokenSource(); + waiter.ConnectionCancellationTokenSource = cts; + try + { + connection = await CreateHttp11ConnectionAsync(queueItem.Request, true, cts.Token).ConfigureAwait(false); + } + catch (Exception e) + { + connectionException = e is OperationCanceledException oce && oce.CancellationToken == cts.Token && !waiter.CancelledByOriginatingRequestCompletion ? + CreateConnectTimeoutException(oce) : + e; + } + finally + { + lock (waiter) + { + waiter.ConnectionCancellationTokenSource = null; + cts.Dispose(); + } + } + + if (connection is not null) + { + // Add the established connection to the pool. + AddNewHttp11Connection(connection, queueItem.Waiter); + } + else + { + Debug.Assert(connectionException is not null); + HandleHttp11ConnectionFailure(waiter, connectionException); + } + } + + internal async ValueTask CreateHttp11ConnectionAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken) + { + (Stream stream, TransportContext? transportContext, IPEndPoint? remoteEndPoint) = await ConnectAsync(request, async, cancellationToken).ConfigureAwait(false); + return await ConstructHttp11ConnectionAsync(async, stream, transportContext, request, remoteEndPoint, cancellationToken).ConfigureAwait(false); + } + + private async ValueTask ConstructHttp11ConnectionAsync(bool async, Stream stream, TransportContext? transportContext, HttpRequestMessage request, IPEndPoint? remoteEndPoint, CancellationToken cancellationToken) + { + Stream newStream = await ApplyPlaintextFilterAsync(async, stream, HttpVersion.Version11, request, cancellationToken).ConfigureAwait(false); + return new HttpConnection(this, newStream, transportContext, remoteEndPoint); + } + + private void HandleHttp11ConnectionFailure(HttpConnectionWaiter? requestWaiter, Exception e) + { + if (NetEventSource.Log.IsEnabled()) Trace($"HTTP/1.1 connection failed: {e}"); + + // If this is happening as part of an HTTP/2 => HTTP/1.1 downgrade, we won't have an HTTP/1.1 waiter associated with this request + // We don't care if this fails; that means the request was previously canceled or handled by a different connection. + requestWaiter?.TrySetException(e); + + lock (SyncObj) + { + Debug.Assert(_associatedHttp11ConnectionCount > 0); + Debug.Assert(_pendingHttp11ConnectionCount > 0); + + _associatedHttp11ConnectionCount--; + _pendingHttp11ConnectionCount--; + + CheckForHttp11ConnectionInjection(); + } + } + + public void RecycleHttp11Connection(HttpConnection connection) + { + if (CheckExpirationOnReturn(connection)) + { + if (NetEventSource.Log.IsEnabled()) connection.Trace("Disposing HTTP/1.1 connection when returning to pool. Connection lifetime expired."); + connection.Dispose(); + return; + } + + ReturnHttp11Connection(connection); + } + + private void AddNewHttp11Connection(HttpConnection connection, HttpConnectionWaiter? initialRequestWaiter) + { + if (NetEventSource.Log.IsEnabled()) Trace(""); + + lock (SyncObj) + { + Debug.Assert(_pendingHttp11ConnectionCount > 0); + _pendingHttp11ConnectionCount--; + + if (initialRequestWaiter is not null) + { + // If we're about to signal the initial waiter, that request must be removed from the queue if it was at the head to avoid rooting it forever. + // Normally, TryDequeueWaiter would handle the removal. TryDequeueSpecificWaiter matches this behavior for the initial request case. + // We don't care if this fails; that means the request was previously canceled, handled by a different connection, or not at the head of the queue. + _http11RequestQueue.TryDequeueSpecificWaiter(initialRequestWaiter); + + // There's no need for us to hold the lock while signaling the waiter. + } + } + + if (initialRequestWaiter is not null && + initialRequestWaiter.TrySignal(connection)) + { + return; + } + + ReturnHttp11Connection(connection); + } + + private void ReturnHttp11Connection(HttpConnection connection) + { + connection.MarkConnectionAsIdle(); + + // The fast path when there are enough connections and no pending requests + // is that we'll see _http11RequestQueueIsEmptyAndNotDisposed being true both + // times, and all we'll have to do as part of returning the connection is + // a Push call on the concurrent stack. + + if (Volatile.Read(ref _http11RequestQueueIsEmptyAndNotDisposed)) + { + _http11Connections.Push(connection); + + // When we add a connection to the pool, we must ensure that there are + // either no pending requests waiting, or that _something_ will pair those + // requests with the connection we just added. + + // When adding a request to the queue, we'll first check if there's + // an available connection waiting in the pool that we could use. + // If there isn't, we'll set the _http11RequestQueueIsEmptyAndNotDisposed + // flag and check for available connections again. + + // To avoid a race where we add the connection after a request was enqueued, + // we'll check the flag again and try to process one request from the queue. + + if (!Volatile.Read(ref _http11RequestQueueIsEmptyAndNotDisposed)) + { + ProcessHttp11RequestQueue(null); + } + } + else + { + // ProcessHttp11RequestQueue is responsible for handing the connection to a pending request, + // or to return it back to the pool if there aren't any. + + // We hand over the connection directly instead of pushing it on the stack first to ensure + // that pending requests are processed in a fair (FIFO) order. + ProcessHttp11RequestQueue(connection); + } + } + + /// + /// Called when an HttpConnection from this pool is no longer usable. + /// Note, this is always called from HttpConnection.Dispose, which is a bit different than how HTTP2 works. + /// + public void InvalidateHttp11Connection(HttpConnection connection, bool disposing = true) + { + lock (SyncObj) + { + Debug.Assert(_associatedHttp11ConnectionCount > 0); + Debug.Assert(!disposing || Array.IndexOf(_http11Connections.ToArray(), connection) < 0); + + _associatedHttp11ConnectionCount--; + + CheckForHttp11ConnectionInjection(); + } + } + + private static void ScavengeHttp11ConnectionStack(HttpConnectionPool pool, ConcurrentStack connections, ref List? toDispose, long nowTicks, TimeSpan pooledConnectionLifetime, TimeSpan pooledConnectionIdleTimeout) + { + // We can't simply enumerate the connections stack as other threads may still be adding and removing entries. + // If we want to check the state of a connection, we must take it from the stack first to ensure we own it. + + // We're about to starve the connection pool of all available connections for a moment. + // We must be holding the lock while doing so to ensure that any new requests that + // come in during this time will be blocked waiting in ProcessHttp11RequestQueue. + // If this were not the case, requests would repeatedly call into CheckForHttp11ConnectionInjection + // and trigger new connection attempts, even if we have enough connections in our copy. + Debug.Assert(pool.HasSyncObjLock); + Debug.Assert(connections.Count <= pool._associatedHttp11ConnectionCount); + + HttpConnection[] stackCopy = ArrayPool.Shared.Rent(pool._associatedHttp11ConnectionCount); + int usableConnections = 0; + + while (connections.TryPop(out HttpConnection? connection)) + { + if (connection.IsUsable(nowTicks, pooledConnectionLifetime, pooledConnectionIdleTimeout)) + { + stackCopy[usableConnections++] = connection; + } + else + { + toDispose ??= new List(); + toDispose.Add(connection); + } + } + + if (usableConnections > 0) + { + // Add them back in reverse to maintain the LIFO order. + Span usable = stackCopy.AsSpan(0, usableConnections); + usable.Reverse(); + connections.PushRange(stackCopy, 0, usableConnections); + usable.Clear(); + } + + ArrayPool.Shared.Return(stackCopy); + } + } +} diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http2.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http2.cs new file mode 100644 index 000000000000..fb1054165cac --- /dev/null +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http2.cs @@ -0,0 +1,633 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.IO; +using System.Net.Security; +using System.Runtime.ExceptionServices; +using System.Security.Authentication; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http +{ + internal sealed partial class HttpConnectionPool + { + /// List of available HTTP/2 connections stored in the pool. + private List? _availableHttp2Connections; + /// The number of HTTP/2 connections associated with the pool, including in use, available, and pending. + private int _associatedHttp2ConnectionCount; + /// Indicates whether an HTTP/2 connection is in the process of being established. + private bool _pendingHttp2Connection; + /// Queue of requests waiting for an HTTP/2 connection. + private RequestQueue _http2RequestQueue; + + private bool _http2Enabled; + private byte[]? _http2AltSvcOriginUri; + internal readonly byte[]? _http2EncodedAuthorityHostHeader; + + /// + /// An ASCII origin string per RFC 6454 Section 6.2, in format <scheme>://<host>[:<port>] + /// + /// + /// Used by to test ALTSVC frames for our origin. + /// + public byte[] Http2AltSvcOriginUri + { + get + { + if (_http2AltSvcOriginUri == null) + { + var sb = new StringBuilder(); + + sb.Append(IsSecure ? "https://" : "http://") + .Append(_originAuthority.IdnHost); + + if (!IsDefaultPort) + { + sb.Append(CultureInfo.InvariantCulture, $":{_originAuthority.Port}"); + } + + _http2AltSvcOriginUri = Encoding.ASCII.GetBytes(sb.ToString()); + } + + return _http2AltSvcOriginUri; + } + } + + private bool EnableMultipleHttp2Connections => _poolManager.Settings.EnableMultipleHttp2Connections; + + private bool TryGetPooledHttp2Connection(HttpRequestMessage request, [NotNullWhen(true)] out Http2Connection? connection, out HttpConnectionWaiter? waiter) + { + Debug.Assert(_kind == HttpConnectionKind.Https || _kind == HttpConnectionKind.SslProxyTunnel || _kind == HttpConnectionKind.Http || _kind == HttpConnectionKind.SocksTunnel || _kind == HttpConnectionKind.SslSocksTunnel); + + // Look for a usable connection. + while (true) + { + lock (SyncObj) + { + if (!_http2Enabled) + { + waiter = null; + connection = null; + return false; + } + + int availableConnectionCount = _availableHttp2Connections?.Count ?? 0; + if (availableConnectionCount > 0) + { + // We have a connection that we can attempt to use. + // Validate it below outside the lock, to avoid doing expensive operations while holding the lock. + connection = _availableHttp2Connections![availableConnectionCount - 1]; + } + else + { + // No available connections. Add to the request queue. + waiter = _http2RequestQueue.EnqueueRequest(request); + + CheckForHttp2ConnectionInjection(); + + // There were no available connections. This request has been added to the request queue. + if (NetEventSource.Log.IsEnabled()) Trace($"No available HTTP/2 connections; request queued."); + connection = null; + return false; + } + } + + if (CheckExpirationOnGet(connection)) + { + if (NetEventSource.Log.IsEnabled()) connection.Trace("Found expired HTTP/2 connection in pool."); + + InvalidateHttp2Connection(connection); + continue; + } + + if (!connection.TryReserveStream()) + { + if (NetEventSource.Log.IsEnabled()) connection.Trace("Found HTTP/2 connection in pool without available streams."); + + bool found = false; + lock (SyncObj) + { + int index = _availableHttp2Connections.IndexOf(connection); + if (index != -1) + { + found = true; + _availableHttp2Connections.RemoveAt(index); + } + } + + // If we didn't find the connection, then someone beat us to removing it (or it shut down) + if (found) + { + DisableHttp2Connection(connection); + } + continue; + } + + if (NetEventSource.Log.IsEnabled()) connection.Trace("Found usable HTTP/2 connection in pool."); + waiter = null; + return true; + } + } + + private void CheckForHttp2ConnectionInjection() + { + Debug.Assert(HasSyncObjLock); + + _http2RequestQueue.PruneCompletedRequestsFromHeadOfQueue(this); + + // Determine if we can and should add a new connection to the pool. + int availableHttp2ConnectionCount = _availableHttp2Connections?.Count ?? 0; + bool willInject = availableHttp2ConnectionCount == 0 && // No available connections + !_pendingHttp2Connection && // Only allow one pending HTTP2 connection at a time + _http2RequestQueue.Count > 0 && // There are requests left on the queue + (_associatedHttp2ConnectionCount == 0 || EnableMultipleHttp2Connections) && // We allow multiple connections, or don't have a connection currently + _http2RequestQueue.RequestsWithoutAConnectionAttempt > 0; // There are requests we haven't issued a connection attempt for + + if (NetEventSource.Log.IsEnabled()) + { + Trace($"Available HTTP/2.0 connections: {availableHttp2ConnectionCount}, " + + $"Pending HTTP/2.0 connection: {_pendingHttp2Connection}, " + + $"Requests in the queue: {_http2RequestQueue.Count}, " + + $"Requests without a connection attempt: {_http2RequestQueue.RequestsWithoutAConnectionAttempt}, " + + $"Total associated HTTP/2.0 connections: {_associatedHttp2ConnectionCount}, " + + $"Will inject connection: {willInject}."); + } + + if (willInject) + { + _associatedHttp2ConnectionCount++; + _pendingHttp2Connection = true; + + RequestQueue.QueueItem queueItem = _http2RequestQueue.PeekNextRequestForConnectionAttempt(); + _ = InjectNewHttp2ConnectionAsync(queueItem); // ignore returned task + } + } + + private async Task InjectNewHttp2ConnectionAsync(RequestQueue.QueueItem queueItem) + { + if (NetEventSource.Log.IsEnabled()) Trace("Creating new HTTP/2 connection for pool."); + + // Queue the remainder of the work so that this method completes quickly + // and escapes locks held by the caller. + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); + + Http2Connection? connection = null; + Exception? connectionException = null; + HttpConnectionWaiter waiter = queueItem.Waiter; + + CancellationTokenSource cts = GetConnectTimeoutCancellationTokenSource(); + waiter.ConnectionCancellationTokenSource = cts; + try + { + (Stream stream, TransportContext? transportContext, IPEndPoint? remoteEndPoint) = await ConnectAsync(queueItem.Request, true, cts.Token).ConfigureAwait(false); + + if (IsSecure) + { + SslStream sslStream = (SslStream)stream; + + if (sslStream.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2) + { + // The server accepted our request for HTTP2. + + if (sslStream.SslProtocol < SslProtocols.Tls12) + { + stream.Dispose(); + connectionException = new HttpRequestException(SR.Format(SR.net_ssl_http2_requires_tls12, sslStream.SslProtocol)); + } + else + { + connection = await ConstructHttp2ConnectionAsync(stream, queueItem.Request, remoteEndPoint, cts.Token).ConfigureAwait(false); + } + } + else + { + // We established an SSL connection, but the server denied our request for HTTP2. + await HandleHttp11Downgrade(queueItem.Request, stream, transportContext, remoteEndPoint, cts.Token).ConfigureAwait(false); + return; + } + } + else + { + connection = await ConstructHttp2ConnectionAsync(stream, queueItem.Request, remoteEndPoint, cts.Token).ConfigureAwait(false); + } + } + catch (Exception e) + { + connectionException = e is OperationCanceledException oce && oce.CancellationToken == cts.Token && !waiter.CancelledByOriginatingRequestCompletion ? + CreateConnectTimeoutException(oce) : + e; + } + finally + { + lock (waiter) + { + waiter.ConnectionCancellationTokenSource = null; + cts.Dispose(); + } + } + + if (connection is not null) + { + // Add the new connection to the pool. + ReturnHttp2Connection(connection, isNewConnection: true, queueItem.Waiter); + } + else + { + Debug.Assert(connectionException is not null); + HandleHttp2ConnectionFailure(waiter, connectionException); + } + } + + private async ValueTask ConstructHttp2ConnectionAsync(Stream stream, HttpRequestMessage request, IPEndPoint? remoteEndPoint, CancellationToken cancellationToken) + { + stream = await ApplyPlaintextFilterAsync(async: true, stream, HttpVersion.Version20, request, cancellationToken).ConfigureAwait(false); + + Http2Connection http2Connection = new Http2Connection(this, stream, remoteEndPoint); + try + { + await http2Connection.SetupAsync(cancellationToken).ConfigureAwait(false); + } + catch (Exception e) + { + // Note, SetupAsync will dispose the connection if there is an exception. + if (e is OperationCanceledException oce && oce.CancellationToken == cancellationToken) + { + // Note, AddHttp2ConnectionAsync handles this OCE separately so don't wrap it. + throw; + } + + throw new HttpRequestException(SR.net_http_client_execution_error, e); + } + + return http2Connection; + } + + private void HandleHttp2ConnectionFailure(HttpConnectionWaiter requestWaiter, Exception e) + { + if (NetEventSource.Log.IsEnabled()) Trace($"HTTP2 connection failed: {e}"); + + // We don't care if this fails; that means the request was previously canceled or handled by a different connection. + requestWaiter.TrySetException(e); + + lock (SyncObj) + { + Debug.Assert(_associatedHttp2ConnectionCount > 0); + Debug.Assert(_pendingHttp2Connection); + + _associatedHttp2ConnectionCount--; + _pendingHttp2Connection = false; + + CheckForHttp2ConnectionInjection(); + } + } + + private async Task HandleHttp11Downgrade(HttpRequestMessage request, Stream stream, TransportContext? transportContext, IPEndPoint? remoteEndPoint, CancellationToken cancellationToken) + { + if (NetEventSource.Log.IsEnabled()) Trace("Server does not support HTTP2; disabling HTTP2 use and proceeding with HTTP/1.1 connection"); + + bool canUse = true; + HttpConnectionWaiter? waiter = null; + lock (SyncObj) + { + Debug.Assert(_pendingHttp2Connection); + Debug.Assert(_associatedHttp2ConnectionCount > 0); + + // Server does not support HTTP2. Disable further HTTP2 attempts. + _http2Enabled = false; + _associatedHttp2ConnectionCount--; + _pendingHttp2Connection = false; + + if (_associatedHttp11ConnectionCount < _maxHttp11Connections) + { + _associatedHttp11ConnectionCount++; + _pendingHttp11ConnectionCount++; + } + else + { + // We are already at the limit for HTTP/1.1 connections, so do not proceed with this connection. + canUse = false; + } + + _http2RequestQueue.TryDequeueWaiter(this, out waiter); + } + + // Signal to any queued HTTP2 requests that they must downgrade. + while (waiter is not null) + { + if (NetEventSource.Log.IsEnabled()) Trace("Downgrading queued HTTP2 request to HTTP/1.1"); + + // We are done with the HTTP2 connection attempt, no point to cancel it. + Volatile.Write(ref waiter.ConnectionCancellationTokenSource, null); + + // We don't care if this fails; that means the request was previously canceled or handled by a different connection. + waiter.TrySetResult(null); + + lock (SyncObj) + { + _http2RequestQueue.TryDequeueWaiter(this, out waiter); + } + } + + if (!canUse) + { + if (NetEventSource.Log.IsEnabled()) Trace("Discarding downgraded HTTP/1.1 connection because HTTP/1.1 connection limit is exceeded"); + stream.Dispose(); + return; + } + + HttpConnection http11Connection; + try + { + // Note, the same CancellationToken from the original HTTP2 connection establishment still applies here. + http11Connection = await ConstructHttp11ConnectionAsync(true, stream, transportContext, request, remoteEndPoint, cancellationToken).ConfigureAwait(false); + } + catch (OperationCanceledException oce) when (oce.CancellationToken == cancellationToken) + { + HandleHttp11ConnectionFailure(requestWaiter: null, CreateConnectTimeoutException(oce)); + return; + } + catch (Exception e) + { + HandleHttp11ConnectionFailure(requestWaiter: null, e); + return; + } + + AddNewHttp11Connection(http11Connection, initialRequestWaiter: null); + } + + private void ReturnHttp2Connection(Http2Connection connection, bool isNewConnection, HttpConnectionWaiter? initialRequestWaiter = null) + { + if (NetEventSource.Log.IsEnabled()) connection.Trace($"{nameof(isNewConnection)}={isNewConnection}"); + + Debug.Assert(!HasSyncObjLock); + Debug.Assert(isNewConnection || initialRequestWaiter is null, "Shouldn't have a request unless the connection is new"); + + if (!isNewConnection && CheckExpirationOnReturn(connection)) + { + lock (SyncObj) + { + Debug.Assert(_availableHttp2Connections is null || !_availableHttp2Connections.Contains(connection)); + Debug.Assert(_associatedHttp2ConnectionCount > (_availableHttp2Connections?.Count ?? 0)); + _associatedHttp2ConnectionCount--; + } + + if (NetEventSource.Log.IsEnabled()) connection.Trace("Disposing HTTP2 connection return to pool. Connection lifetime expired."); + connection.Dispose(); + return; + } + + while (connection.TryReserveStream()) + { + // Loop in case we get a request that has already been canceled or handled by a different connection. + while (true) + { + HttpConnectionWaiter? waiter = null; + bool added = false; + lock (SyncObj) + { + Debug.Assert(_availableHttp2Connections is null || !_availableHttp2Connections.Contains(connection), $"HTTP2 connection already in available list"); + Debug.Assert(_associatedHttp2ConnectionCount > (_availableHttp2Connections?.Count ?? 0), + $"Expected _associatedHttp2ConnectionCount={_associatedHttp2ConnectionCount} > _availableHttp2Connections.Count={(_availableHttp2Connections?.Count ?? 0)}"); + + if (isNewConnection) + { + Debug.Assert(_pendingHttp2Connection); + _pendingHttp2Connection = false; + isNewConnection = false; + } + + if (initialRequestWaiter is not null) + { + // Try to handle the request that we initiated the connection for first + waiter = initialRequestWaiter; + initialRequestWaiter = null; + + // If this method found a request to service, that request must be removed from the queue if it was at the head to avoid rooting it forever. + // Normally, TryDequeueWaiter would handle the removal. TryDequeueSpecificWaiter matches this behavior for the initial request case. + // We don't care if this fails; that means the request was previously canceled, handled by a different connection, or not at the head of the queue. + _http2RequestQueue.TryDequeueSpecificWaiter(waiter); + } + else if (_http2RequestQueue.TryDequeueWaiter(this, out waiter)) + { + Debug.Assert((_availableHttp2Connections?.Count ?? 0) == 0, $"With {(_availableHttp2Connections?.Count ?? 0)} available HTTP2 connections, we shouldn't have a waiter."); + } + else if (_disposed) + { + // The pool has been disposed. We will dispose this connection below outside the lock. + // We do this check after processing the request queue so that any queued requests will be handled by existing connections if possible. + _associatedHttp2ConnectionCount--; + } + else + { + // Add connection to the pool. + added = true; + _availableHttp2Connections ??= new List(); + _availableHttp2Connections.Add(connection); + } + } + + if (waiter is not null) + { + Debug.Assert(!added); + + if (waiter.TrySignal(connection)) + { + break; + } + + // Loop and process the queue again + } + else + { + connection.ReleaseStream(); + if (added) + { + if (NetEventSource.Log.IsEnabled()) connection.Trace("Put HTTP2 connection in pool."); + return; + } + else + { + Debug.Assert(_disposed); + if (NetEventSource.Log.IsEnabled()) connection.Trace("Disposing HTTP2 connection returned to pool. Pool was disposed."); + connection.Dispose(); + return; + } + } + } + } + + if (isNewConnection) + { + Debug.Assert(initialRequestWaiter is not null, "Expect request for a new connection"); + + // The new connection could not handle even one request, either because it shut down before we could use it for any requests, + // or because it immediately set the max concurrent streams limit to 0. + // We don't want to get stuck in a loop where we keep trying to create new connections for the same request. + // So, treat this as a connection failure. + + if (NetEventSource.Log.IsEnabled()) connection.Trace("New HTTP2 connection is unusable due to no available streams."); + connection.Dispose(); + + HttpRequestException hre = new HttpRequestException(SR.net_http_http2_connection_not_established); + ExceptionDispatchInfo.SetCurrentStackTrace(hre); + HandleHttp2ConnectionFailure(initialRequestWaiter, hre); + } + else + { + // Since we only inject one connection at a time, we may want to inject another now. + lock (SyncObj) + { + CheckForHttp2ConnectionInjection(); + } + + // We need to wait until the connection is usable again. + DisableHttp2Connection(connection); + } + } + + /// + /// Disable usage of the specified connection because it cannot handle any more streams at the moment. + /// We will register to be notified when it can handle more streams (or becomes permanently unusable). + /// + private void DisableHttp2Connection(Http2Connection connection) + { + if (NetEventSource.Log.IsEnabled()) connection.Trace(""); + + _ = DisableHttp2ConnectionAsync(connection); // ignore returned task + + async Task DisableHttp2ConnectionAsync(Http2Connection connection) + { + bool usable = await connection.WaitForAvailableStreamsAsync().ConfigureAwait(ConfigureAwaitOptions.ForceYielding); + + if (NetEventSource.Log.IsEnabled()) connection.Trace($"{nameof(connection.WaitForAvailableStreamsAsync)} completed, {nameof(usable)}={usable}"); + + if (usable) + { + ReturnHttp2Connection(connection, isNewConnection: false); + } + else + { + // Connection has shut down. + lock (SyncObj) + { + Debug.Assert(_availableHttp2Connections is null || !_availableHttp2Connections.Contains(connection)); + Debug.Assert(_associatedHttp2ConnectionCount > 0); + + _associatedHttp2ConnectionCount--; + + CheckForHttp2ConnectionInjection(); + } + + if (NetEventSource.Log.IsEnabled()) connection.Trace("HTTP2 connection no longer usable"); + connection.Dispose(); + } + }; + } + + /// + /// Called when an Http2Connection from this pool is no longer usable. + /// + public void InvalidateHttp2Connection(Http2Connection connection) + { + if (NetEventSource.Log.IsEnabled()) connection.Trace(""); + + bool found = false; + lock (SyncObj) + { + if (_availableHttp2Connections is not null) + { + Debug.Assert(_associatedHttp2ConnectionCount >= _availableHttp2Connections.Count); + + int index = _availableHttp2Connections.IndexOf(connection); + if (index != -1) + { + found = true; + _availableHttp2Connections.RemoveAt(index); + _associatedHttp2ConnectionCount--; + } + } + + CheckForHttp2ConnectionInjection(); + } + + // If we found the connection in the available list, then dispose it now. + // Otherwise, when we try to put it back in the pool, we will see it is shut down and dispose it (and adjust connection counts). + if (found) + { + connection.Dispose(); + } + } + + public void HeartBeat() + { + Http2Connection[]? localHttp2Connections; + lock (SyncObj) + { + localHttp2Connections = _availableHttp2Connections?.ToArray(); + } + + // Avoid calling HeartBeat under the lock, as it may call back into HttpConnectionPool.InvalidateHttp2Connection. + if (localHttp2Connections is not null) + { + foreach (Http2Connection http2Connection in localHttp2Connections) + { + http2Connection.HeartBeat(); + } + } + } + + private static int ScavengeHttp2ConnectionList(List list, ref List? toDispose, long nowTicks, TimeSpan pooledConnectionLifetime, TimeSpan pooledConnectionIdleTimeout) + { + int freeIndex = 0; + while (freeIndex < list.Count && list[freeIndex].IsUsable(nowTicks, pooledConnectionLifetime, pooledConnectionIdleTimeout)) + { + freeIndex++; + } + + // If freeIndex == list.Count, nothing needs to be removed. + // But if it's < list.Count, at least one connection needs to be purged. + int removed = 0; + if (freeIndex < list.Count) + { + // We know the connection at freeIndex is unusable, so dispose of it. + toDispose ??= new List(); + toDispose.Add(list[freeIndex]); + + // Find the first item after the one to be removed that should be kept. + int current = freeIndex + 1; + while (current < list.Count) + { + // Look for the first item to be kept. Along the way, any + // that shouldn't be kept are disposed of. + while (current < list.Count && !list[current].IsUsable(nowTicks, pooledConnectionLifetime, pooledConnectionIdleTimeout)) + { + toDispose.Add(list[current]); + current++; + } + + // If we found something to keep, copy it down to the known free slot. + if (current < list.Count) + { + // copy item to the free slot + list[freeIndex++] = list[current++]; + } + + // Keep going until there are no more good items. + } + + // At this point, good connections have been moved below freeIndex, and garbage connections have + // been added to the dispose list, so clear the end of the list past freeIndex. + removed = list.Count - freeIndex; + list.RemoveRange(freeIndex, removed); + } + + return removed; + } + } +} diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http3.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http3.cs new file mode 100644 index 000000000000..227aa11ef816 --- /dev/null +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http3.cs @@ -0,0 +1,463 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Net.Http.Headers; +using System.Net.Quic; +using System.Net.Security; +using System.Runtime.Versioning; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http +{ + internal sealed partial class HttpConnectionPool + { + /// + /// If exceeds this size, Alt-Svc will be disabled entirely for milliseconds. + /// This is to prevent a failing server from bloating the dictionary beyond a reasonable value. + /// + private const int MaxAltSvcIgnoreListSize = 8; + + /// The time, in milliseconds, that an authority should remain in . + private const int AltSvcBlocklistTimeoutInMilliseconds = 10 * 60 * 1000; + + [SupportedOSPlatformGuard("linux")] + [SupportedOSPlatformGuard("macOS")] + [SupportedOSPlatformGuard("Windows")] + internal static bool IsHttp3Supported() => (OperatingSystem.IsLinux() && !OperatingSystem.IsAndroid()) || OperatingSystem.IsWindows() || OperatingSystem.IsMacOS(); + + private bool _http3Enabled; + private Http3Connection? _http3Connection; + private SemaphoreSlim? _http3ConnectionCreateLock; + internal readonly byte[]? _http3EncodedAuthorityHostHeader; + + /// Initially set to null, this can be set to enable HTTP/3 based on Alt-Svc. + private volatile HttpAuthority? _http3Authority; + + /// A timer to expire and return the pool to . Initialized on first use. + private Timer? _authorityExpireTimer; + + /// If true, the will persist across a network change. If false, it will be reset to . + private bool _persistAuthority; + + /// + /// When an Alt-Svc authority fails due to 421 Misdirected Request, it is placed in the blocklist to be ignored + /// for milliseconds. Initialized on first use. + /// + private volatile Dictionary? _altSvcBlocklist; + private CancellationTokenSource? _altSvcBlocklistTimerCancellation; + private volatile bool _altSvcEnabled = true; + + // Returns null if HTTP3 cannot be used. + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("linux")] + [SupportedOSPlatform("macos")] + private async ValueTask TrySendUsingHttp3Async(HttpRequestMessage request, CancellationToken cancellationToken) + { + // Loop in case we get a 421 and need to send the request to a different authority. + while (true) + { + HttpAuthority? authority = _http3Authority; + + // If H3 is explicitly requested, assume prenegotiated H3. + if (request.Version.Major >= 3 && request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) + { + authority ??= _originAuthority; + } + + if (authority == null) + { + return null; + } + + Exception? reasonException; + if (IsAltSvcBlocked(authority, out reasonException)) + { + ThrowGetVersionException(request, 3, reasonException); + } + + long queueStartingTimestamp = HttpTelemetry.Log.IsEnabled() || Settings._metrics!.RequestsQueueDuration.Enabled ? Stopwatch.GetTimestamp() : 0; + + ValueTask connectionTask = GetHttp3ConnectionAsync(request, authority, cancellationToken); + + Http3Connection connection = await connectionTask.ConfigureAwait(false); + + HttpResponseMessage response = await connection.SendAsync(request, queueStartingTimestamp, cancellationToken).ConfigureAwait(false); + + // If an Alt-Svc authority returns 421, it means it can't actually handle the request. + // An authority is supposed to be able to handle ALL requests to the origin, so this is a server bug. + // In this case, we blocklist the authority and retry the request at the origin. + if (response.StatusCode == HttpStatusCode.MisdirectedRequest && connection.Authority != _originAuthority) + { + response.Dispose(); + BlocklistAuthority(connection.Authority); + continue; + } + + return response; + } + } + + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("linux")] + [SupportedOSPlatform("macos")] + private async ValueTask GetHttp3ConnectionAsync(HttpRequestMessage request, HttpAuthority authority, CancellationToken cancellationToken) + { + Debug.Assert(_kind == HttpConnectionKind.Https); + Debug.Assert(_http3Enabled); + + Http3Connection? http3Connection = Volatile.Read(ref _http3Connection); + + if (http3Connection != null) + { + if (CheckExpirationOnGet(http3Connection) || http3Connection.Authority != authority) + { + // Connection expired. + if (NetEventSource.Log.IsEnabled()) http3Connection.Trace("Found expired HTTP3 connection."); + http3Connection.Dispose(); + InvalidateHttp3Connection(http3Connection); + } + else + { + // Connection exists and it is still good to use. + if (NetEventSource.Log.IsEnabled()) Trace("Using existing HTTP3 connection."); + return http3Connection; + } + } + + // Ensure that the connection creation semaphore is created + if (_http3ConnectionCreateLock == null) + { + lock (SyncObj) + { + _http3ConnectionCreateLock ??= new SemaphoreSlim(1); + } + } + + await _http3ConnectionCreateLock.WaitAsync(cancellationToken).ConfigureAwait(false); + try + { + if (_http3Connection != null) + { + // Someone beat us to creating the connection. + + if (NetEventSource.Log.IsEnabled()) + { + Trace("Using existing HTTP3 connection."); + } + + return _http3Connection; + } + + if (NetEventSource.Log.IsEnabled()) + { + Trace("Attempting new HTTP3 connection."); + } + + QuicConnection quicConnection; + try + { + quicConnection = await ConnectHelper.ConnectQuicAsync(request, new DnsEndPoint(authority.IdnHost, authority.Port), _poolManager.Settings._pooledConnectionIdleTimeout, _sslOptionsHttp3!, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + if (NetEventSource.Log.IsEnabled()) Trace($"QUIC connection failed: {ex}"); + + // Block list authority only if the connection attempt was not cancelled. + if (ex is not OperationCanceledException oce || !cancellationToken.IsCancellationRequested || oce.CancellationToken != cancellationToken) + { + // Disables HTTP/3 until server announces it can handle it via Alt-Svc. + BlocklistAuthority(authority, ex); + } + throw; + } + + if (quicConnection.NegotiatedApplicationProtocol != SslApplicationProtocol.Http3) + { + BlocklistAuthority(authority); + throw new HttpRequestException(HttpRequestError.ConnectionError, "QUIC connected but no HTTP/3 indicated via ALPN.", null, RequestRetryType.RetryOnConnectionFailure); + } + + // if the authority was sent as an option through alt-svc then include alt-used header + http3Connection = new Http3Connection(this, authority, quicConnection, includeAltUsedHeader: _http3Authority == authority); + _http3Connection = http3Connection; + + if (NetEventSource.Log.IsEnabled()) + { + Trace("New HTTP3 connection established."); + } + + return http3Connection; + } + finally + { + _http3ConnectionCreateLock.Release(); + } + } + + /// Check for the Alt-Svc header, to upgrade to HTTP/3. + private void ProcessAltSvc(HttpResponseMessage response) + { + if (_altSvcEnabled && response.Headers.TryGetValues(KnownHeaders.AltSvc.Descriptor, out IEnumerable? altSvcHeaderValues)) + { + HandleAltSvc(altSvcHeaderValues, response.Headers.Age); + } + } + + /// + /// Inspects a collection of Alt-Svc headers to find the first eligible upgrade path. + /// + /// TODO: common case will likely be a single value. Optimize for that. + internal void HandleAltSvc(IEnumerable altSvcHeaderValues, TimeSpan? responseAge) + { + HttpAuthority? nextAuthority = null; + TimeSpan nextAuthorityMaxAge = default; + bool nextAuthorityPersist = false; + + foreach (string altSvcHeaderValue in altSvcHeaderValues) + { + int parseIdx = 0; + + if (AltSvcHeaderParser.Parser.TryParseValue(altSvcHeaderValue, null, ref parseIdx, out object? parsedValue)) + { + var value = (AltSvcHeaderValue?)parsedValue; + + // 'clear' should be the only value present. + if (value == AltSvcHeaderValue.Clear) + { + lock (SyncObj) + { + ExpireAltSvcAuthority(); + Debug.Assert(_authorityExpireTimer != null || _disposed); + _authorityExpireTimer?.Change(Timeout.Infinite, Timeout.Infinite); + break; + } + } + + if (nextAuthority == null && value != null && value.AlpnProtocolName == "h3") + { + var authority = new HttpAuthority(value.Host ?? _originAuthority.IdnHost, value.Port); + if (IsAltSvcBlocked(authority, out _)) + { + // Skip authorities in our blocklist. + continue; + } + + TimeSpan authorityMaxAge = value.MaxAge; + + if (responseAge != null) + { + authorityMaxAge -= responseAge.GetValueOrDefault(); + } + + if (authorityMaxAge > TimeSpan.Zero) + { + nextAuthority = authority; + nextAuthorityMaxAge = authorityMaxAge; + nextAuthorityPersist = value.Persist; + } + } + } + } + + // There's a race here in checking _http3Authority outside of the lock, + // but there's really no bad behavior if _http3Authority changes in the mean time. + if (nextAuthority != null && !nextAuthority.Equals(_http3Authority)) + { + // Clamp the max age to 30 days... this is arbitrary but prevents passing a too-large TimeSpan to the Timer. + if (nextAuthorityMaxAge.Ticks > (30 * TimeSpan.TicksPerDay)) + { + nextAuthorityMaxAge = TimeSpan.FromTicks(30 * TimeSpan.TicksPerDay); + } + + lock (SyncObj) + { + if (_disposed) + { + // avoid creating or touching _authorityExpireTimer after disposal + return; + } + + if (_authorityExpireTimer == null) + { + var thisRef = new WeakReference(this); + + using (ExecutionContext.SuppressFlow()) + { + _authorityExpireTimer = new Timer(static o => + { + var wr = (WeakReference)o!; + if (wr.TryGetTarget(out HttpConnectionPool? @this)) + { + @this.ExpireAltSvcAuthority(); + } + }, thisRef, nextAuthorityMaxAge, Timeout.InfiniteTimeSpan); + } + } + else + { + _authorityExpireTimer.Change(nextAuthorityMaxAge, Timeout.InfiniteTimeSpan); + } + + _http3Authority = nextAuthority; + _persistAuthority = nextAuthorityPersist; + } + + if (!nextAuthorityPersist) + { +#if !ILLUMOS && !SOLARIS + _poolManager.StartMonitoringNetworkChanges(); +#endif + } + } + } + + /// + /// Expires the current Alt-Svc authority, resetting the connection back to origin. + /// + private void ExpireAltSvcAuthority() + { + // If we ever support prenegotiated HTTP/3, this should be set to origin, not nulled out. + _http3Authority = null; + } + + /// + /// Checks whether the given is on the currext Alt-Svc blocklist. + /// If it is, then it places the cause in the + /// + /// + private bool IsAltSvcBlocked(HttpAuthority authority, out Exception? reasonException) + { + if (_altSvcBlocklist != null) + { + lock (_altSvcBlocklist) + { + return _altSvcBlocklist.TryGetValue(authority, out reasonException); + } + } + reasonException = null; + return false; + } + + /// + /// Blocklists an authority and resets the current authority back to origin. + /// If the number of blocklisted authorities exceeds , + /// Alt-Svc will be disabled entirely for a period of time. + /// + /// + /// This is called when we get a "421 Misdirected Request" from an alternate authority. + /// A future strategy would be to retry the individual request on an older protocol, we'd want to have + /// some logic to blocklist after some number of failures to avoid doubling our request latency. + /// + /// For now, the spec states alternate authorities should be able to handle ALL requests, so this + /// is treated as an exceptional error by immediately blocklisting the authority. + /// + internal void BlocklistAuthority(HttpAuthority badAuthority, Exception? exception = null) + { + Debug.Assert(badAuthority != null); + + Dictionary? altSvcBlocklist = _altSvcBlocklist; + + if (altSvcBlocklist == null) + { + lock (SyncObj) + { + if (_disposed) + { + // avoid creating _altSvcBlocklistTimerCancellation after disposal + return; + } + + altSvcBlocklist = _altSvcBlocklist; + if (altSvcBlocklist == null) + { + altSvcBlocklist = new Dictionary(); + _altSvcBlocklistTimerCancellation = new CancellationTokenSource(); + _altSvcBlocklist = altSvcBlocklist; + } + } + } + + bool added, disabled = false; + + lock (altSvcBlocklist) + { + added = altSvcBlocklist.TryAdd(badAuthority, exception); + + if (added && altSvcBlocklist.Count >= MaxAltSvcIgnoreListSize && _altSvcEnabled) + { + _altSvcEnabled = false; + disabled = true; + } + } + + CancellationToken altSvcBlocklistTimerCt; + + lock (SyncObj) + { + if (_disposed) + { + // avoid touching _authorityExpireTimer and _altSvcBlocklistTimerCancellation after disposal + return; + } + + if (_http3Authority == badAuthority) + { + ExpireAltSvcAuthority(); + Debug.Assert(_authorityExpireTimer != null); + _authorityExpireTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + + Debug.Assert(_altSvcBlocklistTimerCancellation != null); + altSvcBlocklistTimerCt = _altSvcBlocklistTimerCancellation.Token; + } + + if (added) + { + _ = Task.Delay(AltSvcBlocklistTimeoutInMilliseconds, altSvcBlocklistTimerCt) + .ContinueWith(t => + { + lock (altSvcBlocklist) + { + altSvcBlocklist.Remove(badAuthority); + } + }, altSvcBlocklistTimerCt, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); + } + + if (disabled) + { + _ = Task.Delay(AltSvcBlocklistTimeoutInMilliseconds, altSvcBlocklistTimerCt) + .ContinueWith(t => + { + _altSvcEnabled = true; + }, altSvcBlocklistTimerCt, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); + } + } + + public void InvalidateHttp3Connection(Http3Connection connection) + { + lock (SyncObj) + { + if (_http3Connection == connection) + { + _http3Connection = null; + } + } + } + + public void OnNetworkChanged() + { + lock (SyncObj) + { + if (_http3Authority != null && _persistAuthority == false) + { + ExpireAltSvcAuthority(); + Debug.Assert(_authorityExpireTimer != null || _disposed); + _authorityExpireTimer?.Change(Timeout.Infinite, Timeout.Infinite); + } + } + } + } +} diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.cs new file mode 100644 index 000000000000..3fc2f43b01a8 --- /dev/null +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.cs @@ -0,0 +1,1005 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Net.Http.Headers; +using System.Net.Http.HPack; +using System.Net.Http.QPack; +using System.Net.Quic; +using System.Net.Security; +using System.Net.Sockets; +using System.Runtime.CompilerServices; +using System.Runtime.ExceptionServices; +using System.Security.Authentication; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http +{ + /// Provides a pool of connections to the same endpoint. + internal sealed partial class HttpConnectionPool : IDisposable + { + /// The maximum number of times to retry a request after a failure on an established connection. + private const int MaxConnectionFailureRetries = 3; + public const int DefaultHttpPort = 80; + public const int DefaultHttpsPort = 443; + + private static readonly bool s_isWindows7Or2008R2 = GetIsWindows7Or2008R2(); + private static readonly List s_http3ApplicationProtocols = new List() { SslApplicationProtocol.Http3 }; + private static readonly List s_http2ApplicationProtocols = new List() { SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 }; + private static readonly List s_http2OnlyApplicationProtocols = new List() { SslApplicationProtocol.Http2 }; + + private readonly HttpConnectionPoolManager _poolManager; + private readonly HttpConnectionKind _kind; + private readonly Uri? _proxyUri; + + /// The origin authority used to construct the . + private readonly HttpAuthority _originAuthority; + + /// The User-Agent header to use when creating a CONNECT tunnel. + private string? _connectTunnelUserAgent; + + // These settings are advertised by the server via SETTINGS_MAX_HEADER_LIST_SIZE and SETTINGS_MAX_FIELD_SECTION_SIZE. + // If we had previous connections to the same host in this pool, memorize the last value seen. + // This value is used as an initial value for new connections before they have a chance to observe the SETTINGS frame. + // Doing so avoids immediately exceeding the server limit on the first request, potentially causing the connection to be torn down. + // 0 means there were no previous connections, or they hadn't advertised this limit. + // There is no need to lock when updating these values - we're only interested in saving _a_ value, not necessarily the min/max/last. + internal uint _lastSeenHttp2MaxHeaderListSize; + internal uint _lastSeenHttp3MaxHeaderListSize; + + /// Options specialized and cached for this pool and its key. + private readonly SslClientAuthenticationOptions? _sslOptionsHttp11; + private readonly SslClientAuthenticationOptions? _sslOptionsHttp2; + private readonly SslClientAuthenticationOptions? _sslOptionsHttp2Only; + private SslClientAuthenticationOptions? _sslOptionsHttp3; + private readonly SslClientAuthenticationOptions? _sslOptionsProxy; + + private readonly PreAuthCredentialCache? _preAuthCredentials; + + /// Whether the pool has been used since the last time a cleanup occurred. + private bool _usedSinceLastCleanup = true; + /// Whether the pool has been disposed. + private bool _disposed; + + /// Initializes the pool. + /// The manager associated with this pool. + /// The kind of HTTP connections stored in this pool. + /// The host with which this pool is associated. + /// The port with which this pool is associated. + /// The SSL host with which this pool is associated. + /// The proxy this pool targets (optional). + public HttpConnectionPool(HttpConnectionPoolManager poolManager, HttpConnectionKind kind, string? host, int port, string? sslHostName, Uri? proxyUri) + { + _poolManager = poolManager; + _kind = kind; + _proxyUri = proxyUri; + _maxHttp11Connections = Settings._maxConnectionsPerServer; + + // The only case where 'host' will not be set is if this is a Proxy connection pool. + Debug.Assert(host is not null || (kind == HttpConnectionKind.Proxy && proxyUri is not null)); + _originAuthority = new HttpAuthority(host ?? proxyUri!.IdnHost, port); + + _http2Enabled = _poolManager.Settings._maxHttpVersion >= HttpVersion.Version20; + + if (IsHttp3Supported()) + { + _http3Enabled = _poolManager.Settings._maxHttpVersion >= HttpVersion.Version30; + } + + switch (kind) + { + case HttpConnectionKind.Http: + Debug.Assert(host != null); + Debug.Assert(port != 0); + Debug.Assert(sslHostName == null); + Debug.Assert(proxyUri == null); + + _http3Enabled = false; + break; + + case HttpConnectionKind.Https: + Debug.Assert(host != null); + Debug.Assert(port != 0); + Debug.Assert(sslHostName != null); + Debug.Assert(proxyUri == null); + break; + + case HttpConnectionKind.Proxy: + Debug.Assert(host == null); + Debug.Assert(port == 0); + Debug.Assert(sslHostName == null); + Debug.Assert(proxyUri != null); + + _http2Enabled = false; + _http3Enabled = false; + break; + + case HttpConnectionKind.ProxyTunnel: + Debug.Assert(host != null); + Debug.Assert(port != 0); + Debug.Assert(sslHostName == null); + Debug.Assert(proxyUri != null); + + _http2Enabled = false; + _http3Enabled = false; + break; + + case HttpConnectionKind.SslProxyTunnel: + Debug.Assert(host != null); + Debug.Assert(port != 0); + Debug.Assert(sslHostName != null); + Debug.Assert(proxyUri != null); + + _http3Enabled = false; // TODO: how do we tunnel HTTP3? + break; + + case HttpConnectionKind.ProxyConnect: + Debug.Assert(host != null); + Debug.Assert(port != 0); + Debug.Assert(sslHostName == null); + Debug.Assert(proxyUri != null); + + // Don't enforce the max connections limit on proxy tunnels; this would mean that connections to different origin servers + // would compete for the same limited number of connections. + // We will still enforce this limit on the user of the tunnel (i.e. ProxyTunnel or SslProxyTunnel). + _maxHttp11Connections = int.MaxValue; + + _http2Enabled = false; + _http3Enabled = false; + break; + + case HttpConnectionKind.SocksTunnel: + case HttpConnectionKind.SslSocksTunnel: + Debug.Assert(host != null); + Debug.Assert(port != 0); + Debug.Assert(proxyUri != null); + + _http3Enabled = false; // TODO: SOCKS supports UDP and may be used for HTTP3 + break; + + default: + Debug.Fail("Unknown HttpConnectionKind in HttpConnectionPool.ctor"); + break; + } + + if (!_http3Enabled) + { + // Avoid parsing Alt-Svc headers if they won't be used. + _altSvcEnabled = false; + } + + string? hostHeader = null; + if (host is not null) + { + // Precalculate ASCII bytes for Host header + // Note that if _host is null, this is a (non-tunneled) proxy connection, and we can't cache the hostname. + hostHeader = IsDefaultPort + ? _originAuthority.HostValue + : $"{_originAuthority.HostValue}:{_originAuthority.Port}"; + + // Note the IDN hostname should always be ASCII, since it's already been IDNA encoded. + byte[] hostHeaderLine = new byte[6 + hostHeader.Length + 2]; // Host: foo\r\n + "Host: "u8.CopyTo(hostHeaderLine); + Encoding.ASCII.GetBytes(hostHeader, hostHeaderLine.AsSpan(6)); + hostHeaderLine[^2] = (byte)'\r'; + hostHeaderLine[^1] = (byte)'\n'; + _hostHeaderLineBytes = hostHeaderLine; + + Debug.Assert(Encoding.ASCII.GetString(_hostHeaderLineBytes) == $"Host: {hostHeader}\r\n"); + } + + if (sslHostName != null) + { + _sslOptionsHttp11 = ConstructSslOptions(poolManager, sslHostName); + _sslOptionsHttp11.ApplicationProtocols = null; + + if (_http2Enabled) + { + _sslOptionsHttp2 = ConstructSslOptions(poolManager, sslHostName); + _sslOptionsHttp2.ApplicationProtocols = s_http2ApplicationProtocols; + _sslOptionsHttp2Only = ConstructSslOptions(poolManager, sslHostName); + _sslOptionsHttp2Only.ApplicationProtocols = s_http2OnlyApplicationProtocols; + + // Note: + // The HTTP/2 specification states: + // "A deployment of HTTP/2 over TLS 1.2 MUST disable renegotiation. + // An endpoint MUST treat a TLS renegotiation as a connection error (Section 5.4.1) + // of type PROTOCOL_ERROR." + // which suggests we should do: + // _sslOptionsHttp2.AllowRenegotiation = false; + // However, if AllowRenegotiation is set to false, that will also prevent + // renegotation if the server denies the HTTP/2 request and causes a + // downgrade to HTTP/1.1, and the current APIs don't provide a mechanism + // by which AllowRenegotiation could be set back to true in that case. + // For now, if an HTTP/2 server erroneously issues a renegotiation, we'll + // allow it. + } + } + + if (hostHeader is not null) + { + if (_http2Enabled) + { + _http2EncodedAuthorityHostHeader = HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexingToAllocatedArray(H2StaticTable.Authority, hostHeader); + } + + if (IsHttp3Supported() && _http3Enabled) + { + _http3EncodedAuthorityHostHeader = QPackEncoder.EncodeLiteralHeaderFieldWithStaticNameReferenceToArray(H3StaticTable.Authority, hostHeader); + } + } + + // Set up for PreAuthenticate. Access to this cache is guarded by a lock on the cache itself. + if (_poolManager.Settings._preAuthenticate) + { + _preAuthCredentials = new PreAuthCredentialCache(); + } + + _http11RequestQueue = new RequestQueue(); + if (_http2Enabled) + { + _http2RequestQueue = new RequestQueue(); + } + + if (_proxyUri != null && HttpUtilities.IsSupportedSecureScheme(_proxyUri.Scheme)) + { + _sslOptionsProxy = ConstructSslOptions(poolManager, _proxyUri.IdnHost); + _sslOptionsProxy.ApplicationProtocols = null; + } + + if (NetEventSource.Log.IsEnabled()) Trace($"{this}"); + } + + private static SslClientAuthenticationOptions ConstructSslOptions(HttpConnectionPoolManager poolManager, string sslHostName) + { + Debug.Assert(sslHostName != null); + + SslClientAuthenticationOptions sslOptions = poolManager.Settings._sslOptions?.ShallowClone() ?? new SslClientAuthenticationOptions(); + + // This is only set if we are underlying handler for HttpClientHandler + if (poolManager.Settings._clientCertificateOptions == ClientCertificateOption.Manual && sslOptions.LocalCertificateSelectionCallback != null && + (sslOptions.ClientCertificates == null || sslOptions.ClientCertificates.Count == 0)) + { + // If we have no client certificates do not set callback when internal selection is used. + // It breaks TLS resume on Linux + sslOptions.LocalCertificateSelectionCallback = null; + } + + // Set TargetHost for SNI + sslOptions.TargetHost = sslHostName; + + // Windows 7 and Windows 2008 R2 support TLS 1.1 and 1.2, but for legacy reasons by default those protocols + // are not enabled when a developer elects to use the system default. However, in .NET Core 2.0 and earlier, + // HttpClientHandler would enable them, due to being a wrapper for WinHTTP, which enabled them. Both for + // compatibility and because we prefer those higher protocols whenever possible, SocketsHttpHandler also + // pretends they're part of the default when running on Win7/2008R2. + if (s_isWindows7Or2008R2 && sslOptions.EnabledSslProtocols == SslProtocols.None) + { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(poolManager, $"Win7OrWin2K8R2 platform, Changing default TLS protocols to {SecurityProtocol.DefaultSecurityProtocols}"); + } + sslOptions.EnabledSslProtocols = SecurityProtocol.DefaultSecurityProtocols; + } + + return sslOptions; + } + + public HttpAuthority OriginAuthority => _originAuthority; + public HttpConnectionSettings Settings => _poolManager.Settings; + public HttpConnectionKind Kind => _kind; + public bool IsSecure => _kind == HttpConnectionKind.Https || _kind == HttpConnectionKind.SslProxyTunnel || _kind == HttpConnectionKind.SslSocksTunnel; + public Uri? ProxyUri => _proxyUri; + public ICredentials? ProxyCredentials => _poolManager.ProxyCredentials; + public PreAuthCredentialCache? PreAuthCredentials => _preAuthCredentials; + public bool IsDefaultPort => OriginAuthority.Port == (IsSecure ? DefaultHttpsPort : DefaultHttpPort); + private bool DoProxyAuth => (_kind == HttpConnectionKind.Proxy || _kind == HttpConnectionKind.ProxyConnect); + + /// Object used to synchronize access to state in the pool. + private object SyncObj + { + get + { + Debug.Assert(!Monitor.IsEntered(_http11Connections)); + return _http11Connections; + } + } + + public bool HasSyncObjLock => Monitor.IsEntered(_http11Connections); + + // Overview of connection management (mostly HTTP version independent): + // + // Each version of HTTP (1.1, 2, 3) has its own connection pool, and each of these work in a similar manner, + // allowing for differences between the versions (most notably, HTTP/1.1 is not multiplexed.) + // + // When a request is submitted for a particular version (e.g. HTTP/1.1), we first look in the pool for available connections. + // An "available" connection is one that is (hopefully) usable for a new request. + // For HTTP/1.1, this is just an idle connection. + // For HTTP2/3, this is a connection that (hopefully) has available streams to use for new requests. + // If we find an available connection, we will attempt to validate it and then use it. + // We check the lifetime of the connection and discard it if the lifetime is exceeded. + // We check that the connection has not shut down; if so we discard it. + // For HTTP2/3, we reserve a stream on the connection. If this fails, we cannot use the connection right now. + // If validation fails, we will attempt to find a different available connection. + // + // Once we have found a usable connection, we use it to process the request. + // For HTTP/1.1, a connection can handle only a single request at a time, thus it is immediately removed from the list of available connections. + // For HTTP2/3, a connection is only removed from the available list when it has no more available streams. + // In either case, the connection still counts against the total associated connection count for the pool. + // + // If we cannot find a usable available connection, then the request is added the to the request queue for the appropriate version. + // + // Whenever a request is queued, or an existing connection shuts down, we will check to see if we should inject a new connection. + // Injection policy depends on both user settings and some simple heuristics. + // See comments on the relevant routines for details on connection injection policy. + // + // When a new connection is successfully created, or an existing unavailable connection becomes available again, + // we will attempt to use this connection to handle any queued requests (subject to lifetime restrictions on existing connections). + // This may result in the connection becoming unavailable again, because it cannot handle any more requests at the moment. + // If not, we will return the connection to the pool as an available connection for use by new requests. + // + // When a connection shuts down, either gracefully (e.g. GOAWAY) or abortively (e.g. IOException), + // we will remove it from the list of available connections, if it is present there. + // If not, then it must be unavailable at the moment; we will detect this and ensure it is not added back to the available pool. + + public ValueTask SendAsync(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) + { + // We need the User-Agent header when we send a CONNECT request to the proxy. + // We must read the header early, before we return the ownership of the request back to the user. + if ((Kind is HttpConnectionKind.ProxyTunnel or HttpConnectionKind.SslProxyTunnel) && + request.HasHeaders && + request.Headers.NonValidated.TryGetValues(HttpKnownHeaderNames.UserAgent, out HeaderStringValues userAgent)) + { + _connectTunnelUserAgent = userAgent.ToString(); + } + + if (doRequestAuth && Settings._credentials != null) + { + return AuthenticationHelper.SendWithRequestAuthAsync(request, async, Settings._credentials, Settings._preAuthenticate, this, cancellationToken); + } + + return SendWithProxyAuthAsync(request, async, doRequestAuth, cancellationToken); + } + + public ValueTask SendWithProxyAuthAsync(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) + { + if (DoProxyAuth && ProxyCredentials is not null) + { + return AuthenticationHelper.SendWithProxyAuthAsync(request, _proxyUri!, async, ProxyCredentials, doRequestAuth, this, cancellationToken); + } + + return SendWithVersionDetectionAndRetryAsync(request, async, doRequestAuth, cancellationToken); + } + + private Task SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) + { + if (doRequestAuth && Settings._credentials != null) + { + return AuthenticationHelper.SendWithNtConnectionAuthAsync(request, async, Settings._credentials, Settings._impersonationLevel, connection, this, cancellationToken); + } + + return SendWithNtProxyAuthAsync(connection, request, async, cancellationToken); + } + + public Task SendWithNtProxyAuthAsync(HttpConnection connection, HttpRequestMessage request, bool async, CancellationToken cancellationToken) + { + if (DoProxyAuth && ProxyCredentials is not null) + { + return AuthenticationHelper.SendWithNtProxyAuthAsync(request, ProxyUri!, async, ProxyCredentials, HttpHandlerDefaults.DefaultImpersonationLevel, connection, this, cancellationToken); + } + + return connection.SendAsync(request, async, cancellationToken); + } + + public async ValueTask SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) + { + _usedSinceLastCleanup = true; + + // Loop on connection failures (or other problems like version downgrade) and retry if possible. + int retryCount = 0; + while (true) + { + HttpConnectionWaiter? http11ConnectionWaiter = null; + HttpConnectionWaiter? http2ConnectionWaiter = null; + try + { + HttpResponseMessage? response = null; + + // Use HTTP/3 if possible. + if (IsHttp3Supported() && // guard to enable trimming HTTP/3 support + _http3Enabled && + (request.Version.Major >= 3 || (request.VersionPolicy == HttpVersionPolicy.RequestVersionOrHigher && IsSecure)) && + !request.IsExtendedConnectRequest) + { + Debug.Assert(async); + if (QuicConnection.IsSupported) + { + if (_sslOptionsHttp3 == null) + { + // deferred creation. We use atomic exchange to be sure all threads point to single object to mimic ctor behavior. + SslClientAuthenticationOptions sslOptionsHttp3 = ConstructSslOptions(_poolManager, _sslOptionsHttp11!.TargetHost!); + sslOptionsHttp3.ApplicationProtocols = s_http3ApplicationProtocols; + Interlocked.CompareExchange(ref _sslOptionsHttp3, sslOptionsHttp3, null); + } + + response = await TrySendUsingHttp3Async(request, cancellationToken).ConfigureAwait(false); + } + else + { + _altSvcEnabled = false; + _http3Enabled = false; + } + } + + if (response is null) + { + // We could not use HTTP/3. Do not continue if downgrade is not allowed. + if (request.Version.Major >= 3 && request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) + { + ThrowGetVersionException(request, 3); + } + + // Use HTTP/2 if possible. + if (_http2Enabled && + (request.Version.Major >= 2 || (request.VersionPolicy == HttpVersionPolicy.RequestVersionOrHigher && IsSecure)) && + (request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower || IsSecure)) // prefer HTTP/1.1 if connection is not secured and downgrade is possible + { + if (!TryGetPooledHttp2Connection(request, out Http2Connection? connection, out http2ConnectionWaiter) && + http2ConnectionWaiter != null) + { + connection = await http2ConnectionWaiter.WaitForConnectionAsync(request, this, async, cancellationToken).ConfigureAwait(false); + } + + Debug.Assert(connection is not null || !_http2Enabled); + if (connection is not null) + { + if (request.IsExtendedConnectRequest) + { + await connection.InitialSettingsReceived.WaitWithCancellationAsync(cancellationToken).ConfigureAwait(false); + if (!connection.IsConnectEnabled) + { + HttpRequestException exception = new(HttpRequestError.ExtendedConnectNotSupported, SR.net_unsupported_extended_connect); + exception.Data["SETTINGS_ENABLE_CONNECT_PROTOCOL"] = false; + throw exception; + } + } + + response = await connection.SendAsync(request, async, cancellationToken).ConfigureAwait(false); + } + } + + if (response is null) + { + // We could not use HTTP/2. Do not continue if downgrade is not allowed. + if (request.Version.Major >= 2 && request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) + { + ThrowGetVersionException(request, 2); + } + + // Use HTTP/1.x. + if (!TryGetPooledHttp11Connection(request, async, out HttpConnection? connection, out http11ConnectionWaiter)) + { + connection = await http11ConnectionWaiter.WaitForConnectionAsync(request, this, async, cancellationToken).ConfigureAwait(false); + } + + connection.Acquire(); // In case we are doing Windows (i.e. connection-based) auth, we need to ensure that we hold on to this specific connection while auth is underway. + try + { + response = await SendWithNtConnectionAuthAsync(connection, request, async, doRequestAuth, cancellationToken).ConfigureAwait(false); + } + finally + { + connection.Release(); + } + } + } + + ProcessAltSvc(response); + return response; + } + catch (HttpRequestException e) when (e.AllowRetry == RequestRetryType.RetryOnConnectionFailure) + { + Debug.Assert(retryCount >= 0 && retryCount <= MaxConnectionFailureRetries); + + if (retryCount == MaxConnectionFailureRetries) + { + if (NetEventSource.Log.IsEnabled()) + { + Trace($"MaxConnectionFailureRetries limit of {MaxConnectionFailureRetries} hit. Retryable request will not be retried. Exception: {e}"); + } + + throw; + } + + retryCount++; + + if (NetEventSource.Log.IsEnabled()) + { + Trace($"Retry attempt {retryCount} after connection failure. Connection exception: {e}"); + } + + // Eat exception and try again. + } + catch (HttpRequestException e) when (e.AllowRetry == RequestRetryType.RetryOnLowerHttpVersion) + { + // Throw if fallback is not allowed by the version policy. + if (request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) + { + throw new HttpRequestException(HttpRequestError.VersionNegotiationError, SR.Format(SR.net_http_requested_version_server_refused, request.Version, request.VersionPolicy), e); + } + + if (NetEventSource.Log.IsEnabled()) + { + Trace($"Retrying request because server requested version fallback: {e}"); + } + + // Eat exception and try again on a lower protocol version. + request.Version = HttpVersion.Version11; + } + catch (HttpRequestException e) when (e.AllowRetry == RequestRetryType.RetryOnStreamLimitReached) + { + if (NetEventSource.Log.IsEnabled()) + { + Trace($"Retrying request on another HTTP/2 connection after active streams limit is reached on existing one: {e}"); + } + + // Eat exception and try again. + } + finally + { + // We never cancel both attempts at the same time. When downgrade happens, it's possible that both waiters are non-null, + // but in that case http2ConnectionWaiter.ConnectionCancellationTokenSource shall be null. + Debug.Assert(http11ConnectionWaiter is null || http2ConnectionWaiter?.ConnectionCancellationTokenSource is null); + http11ConnectionWaiter?.CancelIfNecessary(this, cancellationToken.IsCancellationRequested); + http2ConnectionWaiter?.CancelIfNecessary(this, cancellationToken.IsCancellationRequested); + } + } + } + + private async ValueTask<(Stream, TransportContext?, IPEndPoint?)> ConnectAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken) + { + Stream? stream = null; + IPEndPoint? remoteEndPoint = null; + switch (_kind) + { + case HttpConnectionKind.Http: + case HttpConnectionKind.Https: + case HttpConnectionKind.ProxyConnect: + stream = await ConnectToTcpHostAsync(_originAuthority.IdnHost, _originAuthority.Port, request, async, cancellationToken).ConfigureAwait(false); + // remoteEndPoint is returned for diagnostic purposes. + remoteEndPoint = GetRemoteEndPoint(stream); + if (_kind == HttpConnectionKind.ProxyConnect && _sslOptionsProxy != null) + { + stream = await ConnectHelper.EstablishSslConnectionAsync(_sslOptionsProxy, request, async, stream, cancellationToken).ConfigureAwait(false); + } + break; + + case HttpConnectionKind.Proxy: + stream = await ConnectToTcpHostAsync(_proxyUri!.IdnHost, _proxyUri.Port, request, async, cancellationToken).ConfigureAwait(false); + // remoteEndPoint is returned for diagnostic purposes. + remoteEndPoint = GetRemoteEndPoint(stream); + if (_sslOptionsProxy != null) + { + stream = await ConnectHelper.EstablishSslConnectionAsync(_sslOptionsProxy, request, async, stream, cancellationToken).ConfigureAwait(false); + } + break; + + case HttpConnectionKind.ProxyTunnel: + case HttpConnectionKind.SslProxyTunnel: + stream = await EstablishProxyTunnelAsync(async, cancellationToken).ConfigureAwait(false); + + if (stream is HttpContentStream contentStream && contentStream._connection?._stream is Stream innerStream) + { + remoteEndPoint = GetRemoteEndPoint(innerStream); + } + + break; + + case HttpConnectionKind.SocksTunnel: + case HttpConnectionKind.SslSocksTunnel: + stream = await EstablishSocksTunnel(request, async, cancellationToken).ConfigureAwait(false); + // remoteEndPoint is returned for diagnostic purposes. + remoteEndPoint = GetRemoteEndPoint(stream); + break; + } + + Debug.Assert(stream != null); + + TransportContext? transportContext = null; + if (IsSecure) + { + SslStream? sslStream = stream as SslStream; + if (sslStream == null) + { + sslStream = await ConnectHelper.EstablishSslConnectionAsync(GetSslOptionsForRequest(request), request, async, stream, cancellationToken).ConfigureAwait(false); + } + else + { + if (NetEventSource.Log.IsEnabled()) + { + Trace($"Connected with custom SslStream: alpn='${sslStream.NegotiatedApplicationProtocol}'"); + } + } + transportContext = sslStream.TransportContext; + stream = sslStream; + } + + static IPEndPoint? GetRemoteEndPoint(Stream stream) => (stream as NetworkStream)?.Socket?.RemoteEndPoint as IPEndPoint; + + return (stream, transportContext, remoteEndPoint); + } + + private async ValueTask ConnectToTcpHostAsync(string host, int port, HttpRequestMessage initialRequest, bool async, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var endPoint = new DnsEndPoint(host, port); + Stream? stream = null; + try + { + // If a ConnectCallback was supplied, use that to establish the connection. + if (Settings._connectCallback != null) + { + ValueTask streamTask = Settings._connectCallback(new SocketsHttpConnectionContext(endPoint, initialRequest), cancellationToken); + + if (!async && !streamTask.IsCompleted) + { + // User-provided ConnectCallback is completing asynchronously but the user is making a synchronous request; if the user cares, they should + // set it up so that synchronous requests are made on a handler with a synchronously-completing ConnectCallback supplied. If in the future, + // we could add a Boolean to SocketsHttpConnectionContext (https://github.com/dotnet/runtime/issues/44876) to let the callback know whether + // this request is sync or async. + Trace($"{nameof(SocketsHttpHandler.ConnectCallback)} completing asynchronously for a synchronous request."); + } + + stream = await streamTask.ConfigureAwait(false) ?? throw new HttpRequestException(SR.net_http_null_from_connect_callback); + } + else + { + // Otherwise, create and connect a socket using default settings. + Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp) { NoDelay = true }; + try + { + if (async) + { + await socket.ConnectAsync(endPoint, cancellationToken).ConfigureAwait(false); + } + else + { + using (cancellationToken.UnsafeRegister(static s => ((Socket)s!).Dispose(), socket)) + { + socket.Connect(endPoint); + } + } + + stream = new NetworkStream(socket, ownsSocket: true); + } + catch + { + socket.Dispose(); + throw; + } + } + + return stream; + } + catch (Exception ex) + { + throw ex is OperationCanceledException oce && oce.CancellationToken == cancellationToken ? + CancellationHelper.CreateOperationCanceledException(innerException: null, cancellationToken) : + ConnectHelper.CreateWrappedException(ex, endPoint.Host, endPoint.Port, cancellationToken); + } + } + + private SslClientAuthenticationOptions GetSslOptionsForRequest(HttpRequestMessage request) + { + if (_http2Enabled) + { + if (request.Version.Major >= 2 && request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) + { + return _sslOptionsHttp2Only!; + } + + if (request.Version.Major >= 2 || request.VersionPolicy == HttpVersionPolicy.RequestVersionOrHigher) + { + return _sslOptionsHttp2!; + } + } + return _sslOptionsHttp11!; + } + + private async ValueTask ApplyPlaintextFilterAsync(bool async, Stream stream, Version httpVersion, HttpRequestMessage request, CancellationToken cancellationToken) + { + if (Settings._plaintextStreamFilter is null) + { + return stream; + } + + Stream newStream; + try + { + ValueTask streamTask = Settings._plaintextStreamFilter(new SocketsHttpPlaintextStreamFilterContext(stream, httpVersion, request), cancellationToken); + + if (!async && !streamTask.IsCompleted) + { + // User-provided PlaintextStreamFilter is completing asynchronously but the user is making a synchronous request; if the user cares, they should + // set it up so that synchronous requests are made on a handler with a synchronously-completing PlaintextStreamFilter supplied. If in the future, + // we could add a Boolean to SocketsHttpPlaintextStreamFilterContext (https://github.com/dotnet/runtime/issues/44876) to let the callback know whether + // this request is sync or async. + Trace($"{nameof(SocketsHttpHandler.PlaintextStreamFilter)} completing asynchronously for a synchronous request."); + } + + newStream = await streamTask.ConfigureAwait(false); + } + catch (OperationCanceledException oce) when (oce.CancellationToken == cancellationToken) + { + stream.Dispose(); + throw; + } + catch (Exception e) + { + stream.Dispose(); + throw new HttpRequestException(SR.net_http_exception_during_plaintext_filter, e); + } + + if (newStream == null) + { + stream.Dispose(); + throw new HttpRequestException(SR.net_http_null_from_plaintext_filter); + } + + return newStream; + } + + private async ValueTask EstablishProxyTunnelAsync(bool async, CancellationToken cancellationToken) + { + // Send a CONNECT request to the proxy server to establish a tunnel. + HttpRequestMessage tunnelRequest = new HttpRequestMessage(HttpMethod.Connect, _proxyUri); + tunnelRequest.Headers.Host = $"{_originAuthority.IdnHost}:{_originAuthority.Port}"; // This specifies destination host/port to connect to + + if (_connectTunnelUserAgent is not null) + { + tunnelRequest.Headers.TryAddWithoutValidation(KnownHeaders.UserAgent.Descriptor, _connectTunnelUserAgent); + } + + HttpResponseMessage tunnelResponse = await _poolManager.SendProxyConnectAsync(tunnelRequest, _proxyUri!, async, cancellationToken).ConfigureAwait(false); + + if (tunnelResponse.StatusCode != HttpStatusCode.OK) + { + tunnelResponse.Dispose(); + throw new HttpRequestException(HttpRequestError.ProxyTunnelError, SR.Format(SR.net_http_proxy_tunnel_returned_failure_status_code, _proxyUri, (int)tunnelResponse.StatusCode)); + } + + try + { + return tunnelResponse.Content.ReadAsStream(cancellationToken); + } + catch + { + tunnelResponse.Dispose(); + throw; + } + } + + private async ValueTask EstablishSocksTunnel(HttpRequestMessage request, bool async, CancellationToken cancellationToken) + { + Debug.Assert(_proxyUri != null); + + Stream stream = await ConnectToTcpHostAsync(_proxyUri.IdnHost, _proxyUri.Port, request, async, cancellationToken).ConfigureAwait(false); + + try + { + await SocksHelper.EstablishSocksTunnelAsync(stream, _originAuthority.IdnHost, _originAuthority.Port, _proxyUri, ProxyCredentials, async, cancellationToken).ConfigureAwait(false); + } + catch (Exception e) when (!(e is OperationCanceledException)) + { + Debug.Assert(!(e is HttpRequestException)); + throw new HttpRequestException(HttpRequestError.ProxyTunnelError, SR.net_http_proxy_tunnel_error, e); + } + + return stream; + } + + private CancellationTokenSource GetConnectTimeoutCancellationTokenSource() => new CancellationTokenSource(Settings._connectTimeout); + + private static Exception CreateConnectTimeoutException(OperationCanceledException oce) + { + // The pattern for request timeouts (on HttpClient) is to throw an OCE with an inner exception of TimeoutException. + // Do the same for ConnectTimeout-based timeouts. + TimeoutException te = new TimeoutException(SR.net_http_connect_timedout, oce.InnerException); + Exception newException = CancellationHelper.CreateOperationCanceledException(te, oce.CancellationToken); + ExceptionDispatchInfo.SetCurrentStackTrace(newException); + return newException; + } + + [DoesNotReturn] + private static void ThrowGetVersionException(HttpRequestMessage request, int desiredVersion, Exception? inner = null) + { + Debug.Assert(desiredVersion == 2 || desiredVersion == 3); + + HttpRequestException ex = new(HttpRequestError.VersionNegotiationError, SR.Format(SR.net_http_requested_version_cannot_establish, request.Version, request.VersionPolicy, desiredVersion), inner); + if (request.IsExtendedConnectRequest && desiredVersion == 2) + { + ex.Data["HTTP2_ENABLED"] = false; + } + + throw ex; + } + + private bool CheckExpirationOnGet(HttpConnectionBase connection) + { + Debug.Assert(!HasSyncObjLock); + + TimeSpan pooledConnectionLifetime = _poolManager.Settings._pooledConnectionLifetime; + if (pooledConnectionLifetime != Timeout.InfiniteTimeSpan) + { + return connection.GetLifetimeTicks(Environment.TickCount64) > pooledConnectionLifetime.TotalMilliseconds; + } + + return false; + } + + private bool CheckExpirationOnReturn(HttpConnectionBase connection) + { + TimeSpan lifetime = _poolManager.Settings._pooledConnectionLifetime; + if (lifetime != Timeout.InfiniteTimeSpan) + { + return lifetime == TimeSpan.Zero || connection.GetLifetimeTicks(Environment.TickCount64) > lifetime.TotalMilliseconds; + } + + return false; + } + + /// + /// Disposes the connection pool. This is only needed when the pool currently contains + /// or has associated connections. + /// + public void Dispose() + { + List? toDispose = null; + + lock (SyncObj) + { + if (_disposed) + { + return; + } + + _disposed = true; + _http11RequestQueueIsEmptyAndNotDisposed = false; + + if (NetEventSource.Log.IsEnabled()) Trace("Disposing the pool."); + + if (_availableHttp2Connections is not null) + { + toDispose = [.. _availableHttp2Connections]; + _associatedHttp2ConnectionCount -= _availableHttp2Connections.Count; + _availableHttp2Connections.Clear(); + } + + if (_http3Connection is not null) + { + toDispose ??= new(); + toDispose.Add(_http3Connection); + _http3Connection = null; + } + + if (_authorityExpireTimer != null) + { + _authorityExpireTimer.Dispose(); + _authorityExpireTimer = null; + } + + if (_altSvcBlocklistTimerCancellation != null) + { + _altSvcBlocklistTimerCancellation.Cancel(); + _altSvcBlocklistTimerCancellation.Dispose(); + _altSvcBlocklistTimerCancellation = null; + } + + Debug.Assert((_availableHttp2Connections?.Count ?? 0) == 0, $"Expected {nameof(_availableHttp2Connections)}.{nameof(_availableHttp2Connections.Count)} == 0"); + } + + // Dispose connections outside the lock to avoid lock re-entrancy issues. + + // This will trigger the disposal of Http11 connections. + // Note: Http11 connections will decrement the _associatedHttp11ConnectionCount when disposed. + // Http2 connections will not, hence the difference in handing _associatedHttp2ConnectionCount. + ProcessHttp11RequestQueue(null); + + toDispose?.ForEach(c => c.Dispose()); + } + + /// + /// Removes any unusable connections from the pool, and if the pool + /// is then empty and stale, disposes of it. + /// + /// + /// true if the pool disposes of itself; otherwise, false. + /// + public bool CleanCacheAndDisposeIfUnused() + { + TimeSpan pooledConnectionLifetime = _poolManager.Settings._pooledConnectionLifetime; + TimeSpan pooledConnectionIdleTimeout = _poolManager.Settings._pooledConnectionIdleTimeout; + long nowTicks = Environment.TickCount64; + + List? toDispose = null; + + lock (SyncObj) + { + // If there are now no connections associated with this pool, we can dispose of it. We + // avoid aggressively cleaning up pools that have recently been used but currently aren't; + // if a pool was used since the last time we cleaned up, give it another chance. New pools + // start out saying they've recently been used, to give them a bit of breathing room and time + // for the initial collection to be added to it. + if (!_usedSinceLastCleanup && _associatedHttp11ConnectionCount == 0 && _associatedHttp2ConnectionCount == 0) + { + _disposed = true; + return true; // Pool is disposed of. It should be removed. + } + + // Reset the cleanup flag. Any pools that are empty and not used since the last cleanup + // will be purged next time around. + _usedSinceLastCleanup = false; + + ScavengeHttp11ConnectionStack(this, _http11Connections, ref toDispose, nowTicks, pooledConnectionLifetime, pooledConnectionIdleTimeout); + + if (_availableHttp2Connections is not null) + { + int removed = ScavengeHttp2ConnectionList(_availableHttp2Connections, ref toDispose, nowTicks, pooledConnectionLifetime, pooledConnectionIdleTimeout); + _associatedHttp2ConnectionCount -= removed; + + // Note: Http11 connections will decrement the _associatedHttp11ConnectionCount when disposed. + // Http2 connections will not, hence the difference in handing _associatedHttp2ConnectionCount. + } + } + + // Dispose the stale connections outside the pool lock, to avoid holding the lock too long. + // Dispose them asynchronously to not to block the caller on closing the SslStream or NetworkStream. + if (toDispose is not null) + { + Task.Factory.StartNew(static s => ((List)s!).ForEach(c => c.Dispose()), toDispose, + CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + } + + // Pool is active. Should not be removed. + return false; + } + + /// Gets whether we're running on Windows 7 or Windows 2008 R2. + private static bool GetIsWindows7Or2008R2() + { + OperatingSystem os = Environment.OSVersion; + if (os.Platform == PlatformID.Win32NT) + { + // Both Windows 7 and Windows 2008 R2 report version 6.1. + Version v = os.Version; + return v.Major == 6 && v.Minor == 1; + } + return false; + } + + // For diagnostic purposes + public override string ToString() => + $"{nameof(HttpConnectionPool)} " + + (_proxyUri == null ? + (_sslOptionsHttp11 == null ? + $"http://{_originAuthority}" : + $"https://{_originAuthority}" + (_sslOptionsHttp11.TargetHost != _originAuthority.IdnHost ? $", SSL TargetHost={_sslOptionsHttp11.TargetHost}" : null)) : + (_sslOptionsHttp11 == null ? + $"Proxy {_proxyUri}" : + $"https://{_originAuthority}/ tunnelled via Proxy {_proxyUri}" + (_sslOptionsHttp11.TargetHost != _originAuthority.IdnHost ? $", SSL TargetHost={_sslOptionsHttp11.TargetHost}" : null))); + + public void Trace(string? message, [CallerMemberName] string? memberName = null) => + NetEventSource.Log.HandlerMessage( + GetHashCode(), // pool ID + 0, // connection ID + 0, // request ID + memberName, // method name + message); // message + } +} diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionWaiter.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionWaiter.cs new file mode 100644 index 000000000000..3ca1412ebe71 --- /dev/null +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionWaiter.cs @@ -0,0 +1,109 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http +{ + internal sealed class HttpConnectionWaiter : TaskCompletionSourceWithCancellation + where T : HttpConnectionBase? + { + // When a connection attempt is pending, reference the connection's CTS, so we can tear it down if the initiating request is cancelled + // or completes on a different connection. + public CancellationTokenSource? ConnectionCancellationTokenSource; + + // Distinguish connection cancellation that happens because the initiating request is cancelled or completed on a different connection. + public bool CancelledByOriginatingRequestCompletion { get; set; } + + public ValueTask WaitForConnectionAsync(HttpRequestMessage request, HttpConnectionPool pool, bool async, CancellationToken requestCancellationToken) + { + return HttpTelemetry.Log.IsEnabled() || pool.Settings._metrics!.RequestsQueueDuration.Enabled + ? WaitForConnectionWithTelemetryAsync(request, pool, async, requestCancellationToken) + : WaitWithCancellationAsync(async, requestCancellationToken); + } + + private async ValueTask WaitForConnectionWithTelemetryAsync(HttpRequestMessage request, HttpConnectionPool pool, bool async, CancellationToken requestCancellationToken) + { + Debug.Assert(typeof(T) == typeof(HttpConnection) || typeof(T) == typeof(Http2Connection)); + + long startingTimestamp = Stopwatch.GetTimestamp(); + try + { + return await WaitWithCancellationAsync(async, requestCancellationToken).ConfigureAwait(false); + } + finally + { + TimeSpan duration = Stopwatch.GetElapsedTime(startingTimestamp); + int versionMajor = typeof(T) == typeof(HttpConnection) ? 1 : 2; + + pool.Settings._metrics!.RequestLeftQueue(request, pool, duration, versionMajor); + + if (HttpTelemetry.Log.IsEnabled()) + { + HttpTelemetry.Log.RequestLeftQueue(versionMajor, duration); + } + } + } + + public bool TrySignal(T connection) + { + Debug.Assert(connection is not null); + + if (TrySetResult(connection)) + { + if (NetEventSource.Log.IsEnabled()) connection.Trace("Dequeued waiting request."); + return true; + } + else + { + if (NetEventSource.Log.IsEnabled()) + { + connection.Trace(Task.IsCanceled + ? "Discarding canceled request from queue." + : "Discarding signaled request waiter from queue."); + } + return false; + } + } + + public void CancelIfNecessary(HttpConnectionPool pool, bool requestCancelled) + { + int timeout = GlobalHttpSettings.SocketsHttpHandler.PendingConnectionTimeoutOnRequestCompletion; + if (ConnectionCancellationTokenSource is null || + timeout == Timeout.Infinite || + pool.Settings._connectTimeout != Timeout.InfiniteTimeSpan && timeout > (int)pool.Settings._connectTimeout.TotalMilliseconds) // Do not override shorter ConnectTimeout + { + return; + } + + lock (this) + { + if (ConnectionCancellationTokenSource is null) + { + return; + } + + if (NetEventSource.Log.IsEnabled()) + { + pool.Trace($"Initiating cancellation of a pending connection attempt with delay of {timeout} ms, " + + $"Reason: {(requestCancelled ? "Request cancelled" : "Request served by another connection")}."); + } + + CancelledByOriginatingRequestCompletion = true; + if (timeout > 0) + { + // Cancel after the specified timeout. This cancellation will not fire if the connection + // succeeds within the delay and the CTS becomes disposed. + ConnectionCancellationTokenSource.CancelAfter(timeout); + } + else + { + // Cancel immediately if no timeout specified. + ConnectionCancellationTokenSource.Cancel(); + } + } + } + } +} diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/RequestQueue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/RequestQueue.cs new file mode 100644 index 000000000000..9deff4da7516 --- /dev/null +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/RequestQueue.cs @@ -0,0 +1,184 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace System.Net.Http +{ + internal struct RequestQueue + where T : HttpConnectionBase? + { + public struct QueueItem + { + public HttpRequestMessage Request; + public HttpConnectionWaiter Waiter; + } + + // This implementation mimics that of Queue, but without version checks and with an extra head pointer + // https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs + private QueueItem[] _array; + private int _head; // The index from which to dequeue if the queue isn't empty. + private int _tail; // The index at which to enqueue if the queue isn't full. + private int _size; // Number of elements. + private int _attemptedConnectionsOffset; // The offset from head where we should next peek for a request without a connection attempt + + public RequestQueue() + { + _array = Array.Empty(); + _head = 0; + _tail = 0; + _size = 0; + _attemptedConnectionsOffset = 0; + } + + private void Enqueue(QueueItem queueItem) + { + if (_size == _array.Length) + { + Grow(); + } + + _array[_tail] = queueItem; + MoveNext(ref _tail); + + _size++; + } + + private QueueItem Dequeue() + { + Debug.Assert(_size > 0); + + int head = _head; + QueueItem[] array = _array; + + QueueItem queueItem = array[head]; + array[head] = default; + + MoveNext(ref _head); + + if (_attemptedConnectionsOffset > 0) + { + _attemptedConnectionsOffset--; + } + + _size--; + return queueItem; + } + + private bool TryPeek(out QueueItem queueItem) + { + if (_size == 0) + { + queueItem = default!; + return false; + } + + queueItem = _array[_head]; + return true; + } + + private void MoveNext(ref int index) + { + int tmp = index + 1; + if (tmp == _array.Length) + { + tmp = 0; + } + index = tmp; + } + + private void Grow() + { + var newArray = new QueueItem[Math.Max(4, _array.Length * 2)]; + + if (_size != 0) + { + if (_head < _tail) + { + Array.Copy(_array, _head, newArray, 0, _size); + } + else + { + Array.Copy(_array, _head, newArray, 0, _array.Length - _head); + Array.Copy(_array, 0, newArray, _array.Length - _head, _tail); + } + } + + _array = newArray; + _head = 0; + _tail = _size; + } + + + public HttpConnectionWaiter EnqueueRequest(HttpRequestMessage request) + { + var waiter = new HttpConnectionWaiter(); + EnqueueRequest(request, waiter); + return waiter; + } + + + public void EnqueueRequest(HttpRequestMessage request, HttpConnectionWaiter waiter) + { + Enqueue(new QueueItem { Request = request, Waiter = waiter }); + } + + public void PruneCompletedRequestsFromHeadOfQueue(HttpConnectionPool pool) + { + while (TryPeek(out QueueItem queueItem) && queueItem.Waiter.Task.IsCompleted) + { + if (NetEventSource.Log.IsEnabled()) + { + pool.Trace(queueItem.Waiter.Task.IsCanceled + ? "Discarding canceled request from queue." + : "Discarding signaled request waiter from queue."); + } + + Dequeue(); + } + } + + public bool TryDequeueWaiter(HttpConnectionPool pool, [MaybeNullWhen(false)] out HttpConnectionWaiter waiter) + { + PruneCompletedRequestsFromHeadOfQueue(pool); + + if (Count != 0) + { + waiter = Dequeue().Waiter; + return true; + } + + waiter = null; + return false; + } + + public void TryDequeueSpecificWaiter(HttpConnectionWaiter waiter) + { + if (TryPeek(out QueueItem queueItem) && queueItem.Waiter == waiter) + { + Dequeue(); + } + } + + public QueueItem PeekNextRequestForConnectionAttempt() + { + Debug.Assert(_attemptedConnectionsOffset >= 0); + Debug.Assert(_attemptedConnectionsOffset < _size, $"{_attemptedConnectionsOffset} < {_size}"); + + int index = _head + _attemptedConnectionsOffset; + _attemptedConnectionsOffset++; + + if (index >= _array.Length) + { + index -= _array.Length; + } + + return _array[index]; + } + + public int Count => _size; + + public int RequestsWithoutAConnectionAttempt => _size - _attemptedConnectionsOffset; + } +} diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DecompressionHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DecompressionHandler.cs index 1ea55ac07f61..dc02b3699572 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DecompressionHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DecompressionHandler.cs @@ -229,7 +229,7 @@ protected override Stream GetDecompressedStream(Stream originalStream) => private sealed class ZLibOrDeflateStream : HttpBaseStream { // As described in RFC 2616, the deflate content-coding is the "zlib" format (RFC 1950) in combination with - // the "deflate" compression algrithm (RFC 1951). Thus, the right stream to use here is ZLibStream. However, + // the "deflate" compression algorithm (RFC 1951). Thus, the right stream to use here is ZLibStream. However, // some servers incorrectly interpret "deflate" to mean the raw, unwrapped deflate protocol. To account for // that, this switches between using ZLibStream (correct) and DeflateStream (incorrect) in order to maximize // compatibility with servers. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs index a4e8efeca641..75b9d9b1f8a9 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs @@ -300,6 +300,11 @@ internal Exception Abort(Exception abortException) private void OnServerGoAway(long firstRejectedStreamId) { + if (NetEventSource.Log.IsEnabled()) + { + Trace($"GOAWAY received. First rejected stream ID = {firstRejectedStreamId}"); + } + // Stop sending requests to this connection. _pool.InvalidateHttp3Connection(this); @@ -649,6 +654,10 @@ private async Task ProcessServerControlStreamAsync(QuicStream stream, ArrayBuffe case Http3FrameType.ReservedHttp2Ping: case Http3FrameType.ReservedHttp2WindowUpdate: case Http3FrameType.ReservedHttp2Continuation: + if (NetEventSource.Log.IsEnabled()) + { + Trace($"Received reserved frame: {frameType}"); + } throw HttpProtocolException.CreateHttp3ConnectionException(Http3ErrorCode.UnexpectedFrame); case Http3FrameType.PushPromise: case Http3FrameType.CancelPush: @@ -663,6 +672,10 @@ private async Task ProcessServerControlStreamAsync(QuicStream stream, ArrayBuffe } if (!shuttingDown) { + if (NetEventSource.Log.IsEnabled()) + { + Trace($"Control stream closed by the server."); + } throw HttpProtocolException.CreateHttp3ConnectionException(Http3ErrorCode.ClosedCriticalStream); } return; diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs index 64ba4089d5db..ef2532b2b22d 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs @@ -277,8 +277,12 @@ await Task.WhenAny(sendRequestTask, readResponseTask).ConfigureAwait(false) == s } catch (QuicException ex) when (ex.QuicError == QuicError.OperationAborted && _connection.AbortException != null) { - // we close the connection, propagate the AbortException - throw new HttpRequestException(HttpRequestError.Unknown, SR.net_http_client_execution_error, _connection.AbortException); + // we closed the connection already, propagate the AbortException + HttpRequestError httpRequestError = _connection.AbortException is HttpProtocolException + ? HttpRequestError.HttpProtocolError + : HttpRequestError.Unknown; + + throw new HttpRequestException(httpRequestError, SR.net_http_client_execution_error, _connection.AbortException); } // It is possible for user's Content code to throw an unexpected OperationCanceledException. catch (OperationCanceledException ex) when (ex.CancellationToken == _requestBodyCancellationSource.Token || ex.CancellationToken == cancellationToken) @@ -300,6 +304,16 @@ await Task.WhenAny(sendRequestTask, readResponseTask).ConfigureAwait(false) == s _connection.Abort(ex); throw new HttpRequestException(ex.HttpRequestError, SR.net_http_client_execution_error, ex); } + catch (QPackDecodingException ex) + { + Exception abortException = _connection.Abort(HttpProtocolException.CreateHttp3ConnectionException(Http3ErrorCode.QPackDecompressionFailed)); + throw new HttpRequestException(HttpRequestError.InvalidResponse, SR.net_http_invalid_response, ex); + } + catch (QPackEncodingException ex) + { + _stream.Abort(QuicAbortDirection.Write, (long)Http3ErrorCode.InternalError); + throw new HttpRequestException(HttpRequestError.Unknown, SR.net_http_client_execution_error, ex); + } catch (Exception ex) { _stream.Abort(QuicAbortDirection.Write, (long)Http3ErrorCode.InternalError); @@ -307,6 +321,9 @@ await Task.WhenAny(sendRequestTask, readResponseTask).ConfigureAwait(false) == s { throw; } + + // all exceptions should be already handled above + Debug.Fail($"Unexpected exception type in Http3RequestStream.SendAsync: {ex}"); throw new HttpRequestException(HttpRequestError.Unknown, SR.net_http_client_execution_error, ex); } finally @@ -1253,6 +1270,13 @@ private void HandleReadResponseContentException(Exception ex, CancellationToken _connection.Abort(exception); throw exception; + case QuicException e when (e.QuicError == QuicError.OperationAborted && _connection.AbortException != null): + // we closed the connection already, propagate the AbortException + HttpRequestError httpRequestError = _connection.AbortException is HttpProtocolException + ? HttpRequestError.HttpProtocolError + : HttpRequestError.Unknown; + throw new HttpRequestException(httpRequestError, SR.net_http_client_execution_error, _connection.AbortException); + case HttpIOException: _connection.Abort(ex); ExceptionDispatchInfo.Throw(ex); // Rethrow. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionBase.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionBase.cs index f472762e6799..d1a48491674e 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionBase.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionBase.cs @@ -211,5 +211,41 @@ static void LogFaulted(HttpConnectionBase connection, Task task) } public abstract void Dispose(); + + /// + /// Called by while holding the lock. + /// + public bool IsUsable(long nowTicks, TimeSpan pooledConnectionLifetime, TimeSpan pooledConnectionIdleTimeout) + { + // Validate that the connection hasn't been idle in the pool for longer than is allowed. + if (pooledConnectionIdleTimeout != Timeout.InfiniteTimeSpan) + { + long idleTicks = GetIdleTicks(nowTicks); + if (idleTicks > pooledConnectionIdleTimeout.TotalMilliseconds) + { + if (NetEventSource.Log.IsEnabled()) Trace($"Scavenging connection. Idle {TimeSpan.FromMilliseconds(idleTicks)} > {pooledConnectionIdleTimeout}."); + return false; + } + } + + // Validate that the connection lifetime has not been exceeded. + if (pooledConnectionLifetime != Timeout.InfiniteTimeSpan) + { + long lifetimeTicks = GetLifetimeTicks(nowTicks); + if (lifetimeTicks > pooledConnectionLifetime.TotalMilliseconds) + { + if (NetEventSource.Log.IsEnabled()) Trace($"Scavenging connection. Lifetime {TimeSpan.FromMilliseconds(lifetimeTicks)} > {pooledConnectionLifetime}."); + return false; + } + } + + if (!CheckUsabilityOnScavenge()) + { + if (NetEventSource.Log.IsEnabled()) Trace($"Scavenging connection. Keep-Alive timeout exceeded, unexpected data or EOF received."); + return false; + } + + return true; + } } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs deleted file mode 100644 index e51669888352..000000000000 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs +++ /dev/null @@ -1,2798 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Buffers; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.IO; -using System.Net.Http.Headers; -using System.Net.Http.HPack; -using System.Net.Http.QPack; -using System.Net.Quic; -using System.Net.Security; -using System.Net.Sockets; -using System.Runtime.CompilerServices; -using System.Runtime.ExceptionServices; -using System.Runtime.Versioning; -using System.Security.Authentication; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace System.Net.Http -{ - /// Provides a pool of connections to the same endpoint. - internal sealed class HttpConnectionPool : IDisposable - { - private static readonly bool s_isWindows7Or2008R2 = GetIsWindows7Or2008R2(); - - private readonly HttpConnectionPoolManager _poolManager; - private readonly HttpConnectionKind _kind; - private readonly Uri? _proxyUri; - - /// The origin authority used to construct the . - private readonly HttpAuthority _originAuthority; - - /// Initially set to null, this can be set to enable HTTP/3 based on Alt-Svc. - private volatile HttpAuthority? _http3Authority; - - /// A timer to expire and return the pool to . Initialized on first use. - private Timer? _authorityExpireTimer; - - /// If true, the will persist across a network change. If false, it will be reset to . - private bool _persistAuthority; - - /// The User-Agent header to use when creating a CONNECT tunnel. - private string? _connectTunnelUserAgent; - - /// - /// When an Alt-Svc authority fails due to 421 Misdirected Request, it is placed in the blocklist to be ignored - /// for milliseconds. Initialized on first use. - /// - private volatile Dictionary? _altSvcBlocklist; - private CancellationTokenSource? _altSvcBlocklistTimerCancellation; - private volatile bool _altSvcEnabled = true; - - /// The maximum number of times to retry a request after a failure on an established connection. - private const int MaxConnectionFailureRetries = 3; - - /// - /// If exceeds this size, Alt-Svc will be disabled entirely for milliseconds. - /// This is to prevent a failing server from bloating the dictionary beyond a reasonable value. - /// - private const int MaxAltSvcIgnoreListSize = 8; - - /// The time, in milliseconds, that an authority should remain in . - private const int AltSvcBlocklistTimeoutInMilliseconds = 10 * 60 * 1000; - - // HTTP/1.1 connection pool - - /// Stack of currently available HTTP/1.1 connections stored in the pool. - private readonly ConcurrentStack _http11Connections = new(); - /// Controls whether we can use a fast path when returning connections to the pool and skip calling into . - private bool _http11RequestQueueIsEmptyAndNotDisposed; - /// The maximum number of HTTP/1.1 connections allowed to be associated with the pool. - private readonly int _maxHttp11Connections; - /// The number of HTTP/1.1 connections associated with the pool, including in use, available, and pending. - private int _associatedHttp11ConnectionCount; - /// The number of HTTP/1.1 connections that are in the process of being established. - private int _pendingHttp11ConnectionCount; - /// Queue of requests waiting for an HTTP/1.1 connection. - private RequestQueue _http11RequestQueue; - - // HTTP/2 connection pool - - /// List of available HTTP/2 connections stored in the pool. - private List? _availableHttp2Connections; - /// The number of HTTP/2 connections associated with the pool, including in use, available, and pending. - private int _associatedHttp2ConnectionCount; - /// Indicates whether an HTTP/2 connection is in the process of being established. - private bool _pendingHttp2Connection; - /// Queue of requests waiting for an HTTP/2 connection. - private RequestQueue _http2RequestQueue; - - private bool _http2Enabled; - private byte[]? _http2AltSvcOriginUri; - internal readonly byte[]? _http2EncodedAuthorityHostHeader; - private bool _http3Enabled; - private Http3Connection? _http3Connection; - private SemaphoreSlim? _http3ConnectionCreateLock; - internal readonly byte[]? _http3EncodedAuthorityHostHeader; - - // These settings are advertised by the server via SETTINGS_MAX_HEADER_LIST_SIZE and SETTINGS_MAX_FIELD_SECTION_SIZE. - // If we had previous connections to the same host in this pool, memorize the last value seen. - // This value is used as an initial value for new connections before they have a chance to observe the SETTINGS frame. - // Doing so avoids immediately exceeding the server limit on the first request, potentially causing the connection to be torn down. - // 0 means there were no previous connections, or they hadn't advertised this limit. - // There is no need to lock when updating these values - we're only interested in saving _a_ value, not necessarily the min/max/last. - internal uint _lastSeenHttp2MaxHeaderListSize; - internal uint _lastSeenHttp3MaxHeaderListSize; - - /// For non-proxy connection pools, this is the host name in bytes; for proxies, null. - private readonly byte[]? _hostHeaderLineBytes; - /// Options specialized and cached for this pool and its key. - private readonly SslClientAuthenticationOptions? _sslOptionsHttp11; - private readonly SslClientAuthenticationOptions? _sslOptionsHttp2; - private readonly SslClientAuthenticationOptions? _sslOptionsHttp2Only; - private SslClientAuthenticationOptions? _sslOptionsHttp3; - private SslClientAuthenticationOptions? _sslOptionsProxy; - - /// Whether the pool has been used since the last time a cleanup occurred. - private bool _usedSinceLastCleanup = true; - /// Whether the pool has been disposed. - private bool _disposed; - - public const int DefaultHttpPort = 80; - public const int DefaultHttpsPort = 443; - - /// Initializes the pool. - /// The manager associated with this pool. - /// The kind of HTTP connections stored in this pool. - /// The host with which this pool is associated. - /// The port with which this pool is associated. - /// The SSL host with which this pool is associated. - /// The proxy this pool targets (optional). - public HttpConnectionPool(HttpConnectionPoolManager poolManager, HttpConnectionKind kind, string? host, int port, string? sslHostName, Uri? proxyUri) - { - _poolManager = poolManager; - _kind = kind; - _proxyUri = proxyUri; - _maxHttp11Connections = Settings._maxConnectionsPerServer; - - // The only case where 'host' will not be set is if this is a Proxy connection pool. - Debug.Assert(host is not null || (kind == HttpConnectionKind.Proxy && proxyUri is not null)); - _originAuthority = new HttpAuthority(host ?? proxyUri!.IdnHost, port); - - _http2Enabled = _poolManager.Settings._maxHttpVersion >= HttpVersion.Version20; - - if (IsHttp3Supported()) - { - _http3Enabled = _poolManager.Settings._maxHttpVersion >= HttpVersion.Version30; - } - - switch (kind) - { - case HttpConnectionKind.Http: - Debug.Assert(host != null); - Debug.Assert(port != 0); - Debug.Assert(sslHostName == null); - Debug.Assert(proxyUri == null); - - _http3Enabled = false; - break; - - case HttpConnectionKind.Https: - Debug.Assert(host != null); - Debug.Assert(port != 0); - Debug.Assert(sslHostName != null); - Debug.Assert(proxyUri == null); - break; - - case HttpConnectionKind.Proxy: - Debug.Assert(host == null); - Debug.Assert(port == 0); - Debug.Assert(sslHostName == null); - Debug.Assert(proxyUri != null); - - _http2Enabled = false; - _http3Enabled = false; - break; - - case HttpConnectionKind.ProxyTunnel: - Debug.Assert(host != null); - Debug.Assert(port != 0); - Debug.Assert(sslHostName == null); - Debug.Assert(proxyUri != null); - - _http2Enabled = false; - _http3Enabled = false; - break; - - case HttpConnectionKind.SslProxyTunnel: - Debug.Assert(host != null); - Debug.Assert(port != 0); - Debug.Assert(sslHostName != null); - Debug.Assert(proxyUri != null); - - _http3Enabled = false; // TODO: how do we tunnel HTTP3? - break; - - case HttpConnectionKind.ProxyConnect: - Debug.Assert(host != null); - Debug.Assert(port != 0); - Debug.Assert(sslHostName == null); - Debug.Assert(proxyUri != null); - - // Don't enforce the max connections limit on proxy tunnels; this would mean that connections to different origin servers - // would compete for the same limited number of connections. - // We will still enforce this limit on the user of the tunnel (i.e. ProxyTunnel or SslProxyTunnel). - _maxHttp11Connections = int.MaxValue; - - _http2Enabled = false; - _http3Enabled = false; - break; - - case HttpConnectionKind.SocksTunnel: - case HttpConnectionKind.SslSocksTunnel: - Debug.Assert(host != null); - Debug.Assert(port != 0); - Debug.Assert(proxyUri != null); - - _http3Enabled = false; // TODO: SOCKS supports UDP and may be used for HTTP3 - break; - - default: - Debug.Fail("Unknown HttpConnectionKind in HttpConnectionPool.ctor"); - break; - } - - if (!_http3Enabled) - { - // Avoid parsing Alt-Svc headers if they won't be used. - _altSvcEnabled = false; - } - - string? hostHeader = null; - if (host is not null) - { - // Precalculate ASCII bytes for Host header - // Note that if _host is null, this is a (non-tunneled) proxy connection, and we can't cache the hostname. - hostHeader = IsDefaultPort - ? _originAuthority.HostValue - : $"{_originAuthority.HostValue}:{_originAuthority.Port}"; - - // Note the IDN hostname should always be ASCII, since it's already been IDNA encoded. - byte[] hostHeaderLine = new byte[6 + hostHeader.Length + 2]; // Host: foo\r\n - "Host: "u8.CopyTo(hostHeaderLine); - Encoding.ASCII.GetBytes(hostHeader, hostHeaderLine.AsSpan(6)); - hostHeaderLine[^2] = (byte)'\r'; - hostHeaderLine[^1] = (byte)'\n'; - _hostHeaderLineBytes = hostHeaderLine; - - Debug.Assert(Encoding.ASCII.GetString(_hostHeaderLineBytes) == $"Host: {hostHeader}\r\n"); - } - - if (sslHostName != null) - { - _sslOptionsHttp11 = ConstructSslOptions(poolManager, sslHostName); - _sslOptionsHttp11.ApplicationProtocols = null; - - if (_http2Enabled) - { - _sslOptionsHttp2 = ConstructSslOptions(poolManager, sslHostName); - _sslOptionsHttp2.ApplicationProtocols = s_http2ApplicationProtocols; - _sslOptionsHttp2Only = ConstructSslOptions(poolManager, sslHostName); - _sslOptionsHttp2Only.ApplicationProtocols = s_http2OnlyApplicationProtocols; - - // Note: - // The HTTP/2 specification states: - // "A deployment of HTTP/2 over TLS 1.2 MUST disable renegotiation. - // An endpoint MUST treat a TLS renegotiation as a connection error (Section 5.4.1) - // of type PROTOCOL_ERROR." - // which suggests we should do: - // _sslOptionsHttp2.AllowRenegotiation = false; - // However, if AllowRenegotiation is set to false, that will also prevent - // renegotation if the server denies the HTTP/2 request and causes a - // downgrade to HTTP/1.1, and the current APIs don't provide a mechanism - // by which AllowRenegotiation could be set back to true in that case. - // For now, if an HTTP/2 server erroneously issues a renegotiation, we'll - // allow it. - } - } - - if (hostHeader is not null) - { - if (_http2Enabled) - { - _http2EncodedAuthorityHostHeader = HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexingToAllocatedArray(H2StaticTable.Authority, hostHeader); - } - - if (IsHttp3Supported() && _http3Enabled) - { - _http3EncodedAuthorityHostHeader = QPackEncoder.EncodeLiteralHeaderFieldWithStaticNameReferenceToArray(H3StaticTable.Authority, hostHeader); - } - } - - // Set up for PreAuthenticate. Access to this cache is guarded by a lock on the cache itself. - if (_poolManager.Settings._preAuthenticate) - { - PreAuthCredentials = new CredentialCache(); - } - - _http11RequestQueue = new RequestQueue(); - if (_http2Enabled) - { - _http2RequestQueue = new RequestQueue(); - } - - if (_proxyUri != null && HttpUtilities.IsSupportedSecureScheme(_proxyUri.Scheme)) - { - _sslOptionsProxy = ConstructSslOptions(poolManager, _proxyUri.IdnHost); - _sslOptionsProxy.ApplicationProtocols = null; - } - - if (NetEventSource.Log.IsEnabled()) Trace($"{this}"); - } - - [SupportedOSPlatformGuard("linux")] - [SupportedOSPlatformGuard("macOS")] - [SupportedOSPlatformGuard("Windows")] - internal static bool IsHttp3Supported() => (OperatingSystem.IsLinux() && !OperatingSystem.IsAndroid()) || OperatingSystem.IsWindows() || OperatingSystem.IsMacOS(); - - private static readonly List s_http3ApplicationProtocols = new List() { SslApplicationProtocol.Http3 }; - private static readonly List s_http2ApplicationProtocols = new List() { SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 }; - private static readonly List s_http2OnlyApplicationProtocols = new List() { SslApplicationProtocol.Http2 }; - - private static SslClientAuthenticationOptions ConstructSslOptions(HttpConnectionPoolManager poolManager, string sslHostName) - { - Debug.Assert(sslHostName != null); - - SslClientAuthenticationOptions sslOptions = poolManager.Settings._sslOptions?.ShallowClone() ?? new SslClientAuthenticationOptions(); - - // This is only set if we are underlying handler for HttpClientHandler - if (poolManager.Settings._clientCertificateOptions == ClientCertificateOption.Manual && sslOptions.LocalCertificateSelectionCallback != null && - (sslOptions.ClientCertificates == null || sslOptions.ClientCertificates.Count == 0)) - { - // If we have no client certificates do not set callback when internal selection is used. - // It breaks TLS resume on Linux - sslOptions.LocalCertificateSelectionCallback = null; - } - - // Set TargetHost for SNI - sslOptions.TargetHost = sslHostName; - - // Windows 7 and Windows 2008 R2 support TLS 1.1 and 1.2, but for legacy reasons by default those protocols - // are not enabled when a developer elects to use the system default. However, in .NET Core 2.0 and earlier, - // HttpClientHandler would enable them, due to being a wrapper for WinHTTP, which enabled them. Both for - // compatibility and because we prefer those higher protocols whenever possible, SocketsHttpHandler also - // pretends they're part of the default when running on Win7/2008R2. - if (s_isWindows7Or2008R2 && sslOptions.EnabledSslProtocols == SslProtocols.None) - { - if (NetEventSource.Log.IsEnabled()) - { - NetEventSource.Info(poolManager, $"Win7OrWin2K8R2 platform, Changing default TLS protocols to {SecurityProtocol.DefaultSecurityProtocols}"); - } - sslOptions.EnabledSslProtocols = SecurityProtocol.DefaultSecurityProtocols; - } - - return sslOptions; - } - - public HttpAuthority OriginAuthority => _originAuthority; - public HttpConnectionSettings Settings => _poolManager.Settings; - public HttpConnectionKind Kind => _kind; - public bool IsSecure => _kind == HttpConnectionKind.Https || _kind == HttpConnectionKind.SslProxyTunnel || _kind == HttpConnectionKind.SslSocksTunnel; - public Uri? ProxyUri => _proxyUri; - public ICredentials? ProxyCredentials => _poolManager.ProxyCredentials; - public byte[]? HostHeaderLineBytes => _hostHeaderLineBytes; - public CredentialCache? PreAuthCredentials { get; } - public bool IsDefaultPort => OriginAuthority.Port == (IsSecure ? DefaultHttpsPort : DefaultHttpPort); - - /// - /// An ASCII origin string per RFC 6454 Section 6.2, in format <scheme>://<host>[:<port>] - /// - /// - /// Used by to test ALTSVC frames for our origin. - /// - public byte[] Http2AltSvcOriginUri - { - get - { - if (_http2AltSvcOriginUri == null) - { - var sb = new StringBuilder(); - - sb.Append(IsSecure ? "https://" : "http://") - .Append(_originAuthority.IdnHost); - - if (!IsDefaultPort) - { - sb.Append(CultureInfo.InvariantCulture, $":{_originAuthority.Port}"); - } - - _http2AltSvcOriginUri = Encoding.ASCII.GetBytes(sb.ToString()); - } - - return _http2AltSvcOriginUri; - } - } - - private bool EnableMultipleHttp2Connections => _poolManager.Settings.EnableMultipleHttp2Connections; - - /// Object used to synchronize access to state in the pool. - private object SyncObj - { - get - { - Debug.Assert(!Monitor.IsEntered(_http11Connections)); - return _http11Connections; - } - } - - public bool HasSyncObjLock => Monitor.IsEntered(_http11Connections); - - // Overview of connection management (mostly HTTP version independent): - // - // Each version of HTTP (1.1, 2, 3) has its own connection pool, and each of these work in a similar manner, - // allowing for differences between the versions (most notably, HTTP/1.1 is not multiplexed.) - // - // When a request is submitted for a particular version (e.g. HTTP/1.1), we first look in the pool for available connections. - // An "available" connection is one that is (hopefully) usable for a new request. - // For HTTP/1.1, this is just an idle connection. - // For HTTP2/3, this is a connection that (hopefully) has available streams to use for new requests. - // If we find an available connection, we will attempt to validate it and then use it. - // We check the lifetime of the connection and discard it if the lifetime is exceeded. - // We check that the connection has not shut down; if so we discard it. - // For HTTP2/3, we reserve a stream on the connection. If this fails, we cannot use the connection right now. - // If validation fails, we will attempt to find a different available connection. - // - // Once we have found a usable connection, we use it to process the request. - // For HTTP/1.1, a connection can handle only a single request at a time, thus it is immediately removed from the list of available connections. - // For HTTP2/3, a connection is only removed from the available list when it has no more available streams. - // In either case, the connection still counts against the total associated connection count for the pool. - // - // If we cannot find a usable available connection, then the request is added the to the request queue for the appropriate version. - // - // Whenever a request is queued, or an existing connection shuts down, we will check to see if we should inject a new connection. - // Injection policy depends on both user settings and some simple heuristics. - // See comments on the relevant routines for details on connection injection policy. - // - // When a new connection is successfully created, or an existing unavailable connection becomes available again, - // we will attempt to use this connection to handle any queued requests (subject to lifetime restrictions on existing connections). - // This may result in the connection becoming unavailable again, because it cannot handle any more requests at the moment. - // If not, we will return the connection to the pool as an available connection for use by new requests. - // - // When a connection shuts down, either gracefully (e.g. GOAWAY) or abortively (e.g. IOException), - // we will remove it from the list of available connections, if it is present there. - // If not, then it must be unavailable at the moment; we will detect this and ensure it is not added back to the available pool. - - [DoesNotReturn] - private static void ThrowGetVersionException(HttpRequestMessage request, int desiredVersion, Exception? inner = null) - { - Debug.Assert(desiredVersion == 2 || desiredVersion == 3); - - HttpRequestException ex = new(HttpRequestError.VersionNegotiationError, SR.Format(SR.net_http_requested_version_cannot_establish, request.Version, request.VersionPolicy, desiredVersion), inner); - if (request.IsExtendedConnectRequest && desiredVersion == 2) - { - ex.Data["HTTP2_ENABLED"] = false; - } - - throw ex; - } - - private bool CheckExpirationOnGet(HttpConnectionBase connection) - { - Debug.Assert(!HasSyncObjLock); - - TimeSpan pooledConnectionLifetime = _poolManager.Settings._pooledConnectionLifetime; - if (pooledConnectionLifetime != Timeout.InfiniteTimeSpan) - { - return connection.GetLifetimeTicks(Environment.TickCount64) > pooledConnectionLifetime.TotalMilliseconds; - } - - return false; - } - - private static Exception CreateConnectTimeoutException(OperationCanceledException oce) - { - // The pattern for request timeouts (on HttpClient) is to throw an OCE with an inner exception of TimeoutException. - // Do the same for ConnectTimeout-based timeouts. - TimeoutException te = new TimeoutException(SR.net_http_connect_timedout, oce.InnerException); - Exception newException = CancellationHelper.CreateOperationCanceledException(te, oce.CancellationToken); - ExceptionDispatchInfo.SetCurrentStackTrace(newException); - return newException; - } - - private async Task AddHttp11ConnectionAsync(RequestQueue.QueueItem queueItem) - { - if (NetEventSource.Log.IsEnabled()) Trace("Creating new HTTP/1.1 connection for pool."); - - // Queue the remainder of the work so that this method completes quickly - // and escapes locks held by the caller. - await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); - - HttpConnectionWaiter waiter = queueItem.Waiter; - HttpConnection? connection = null; - Exception? connectionException = null; - - CancellationTokenSource cts = GetConnectTimeoutCancellationTokenSource(); - waiter.ConnectionCancellationTokenSource = cts; - try - { - connection = await CreateHttp11ConnectionAsync(queueItem.Request, true, cts.Token).ConfigureAwait(false); - } - catch (Exception e) - { - connectionException = e is OperationCanceledException oce && oce.CancellationToken == cts.Token && !waiter.CancelledByOriginatingRequestCompletion ? - CreateConnectTimeoutException(oce) : - e; - } - finally - { - lock (waiter) - { - waiter.ConnectionCancellationTokenSource = null; - cts.Dispose(); - } - } - - if (connection is not null) - { - // Add the established connection to the pool. - AddNewHttp11Connection(connection, queueItem.Waiter); - } - else - { - Debug.Assert(connectionException is not null); - HandleHttp11ConnectionFailure(waiter, connectionException); - } - } - - private void CheckForHttp11ConnectionInjection() - { - Debug.Assert(HasSyncObjLock); - - _http11RequestQueue.PruneCompletedRequestsFromHeadOfQueue(this); - - // Determine if we can and should add a new connection to the pool. - bool willInject = - _http11RequestQueue.Count > _pendingHttp11ConnectionCount && // More requests queued than pending connections - _associatedHttp11ConnectionCount < _maxHttp11Connections && // Under the connection limit - _http11RequestQueue.RequestsWithoutAConnectionAttempt > 0; // There are requests we haven't issued a connection attempt for - - if (NetEventSource.Log.IsEnabled()) - { - Trace($"Available HTTP/1.1 connections: {_http11Connections.Count}, Requests in the queue: {_http11RequestQueue.Count}, " + - $"Requests without a connection attempt: {_http11RequestQueue.RequestsWithoutAConnectionAttempt}, " + - $"Pending HTTP/1.1 connections: {_pendingHttp11ConnectionCount}, Total associated HTTP/1.1 connections: {_associatedHttp11ConnectionCount}, " + - $"Max HTTP/1.1 connection limit: {_maxHttp11Connections}, " + - $"Will inject connection: {willInject}."); - } - - if (willInject) - { - _associatedHttp11ConnectionCount++; - _pendingHttp11ConnectionCount++; - - RequestQueue.QueueItem queueItem = _http11RequestQueue.PeekNextRequestForConnectionAttempt(); - _ = AddHttp11ConnectionAsync(queueItem); // ignore returned task - } - } - - /// - /// This method is called: - ///
    - When returning a connection and observing that the request queue is not empty ( is ). - ///
    - After adding a request to the queue if we fail to obtain a connection from . - ///
    - After scavenging or disposing the pool to ensure that any pending requests are handled or connections disposed. - /// The method will attempt to match one request from the to an available connection. - /// The can either be provided as an argument (when returning a connection to the pool), or one will be rented from . - /// As we'll only process a single request, we are expecting the method to be called every time a request is enqueued, and every time a connection is returned while the request queue is not empty. - /// If the becomes empty, this method will reset the flag back to , - /// such that returning connections will use the fast path again and skip calling into this method. - /// Notably, this method will not be called on the fast path as long as we have enough connections to handle all new requests. - ///
    - /// The connection to use for a pending request, or return to the pool. - private void ProcessHttp11RequestQueue(HttpConnection? connection) - { - // Loop in case the request we try to signal was already cancelled or handled by a different connection. - while (true) - { - HttpConnectionWaiter? waiter = null; - - lock (SyncObj) - { -#if DEBUG - // Other threads may still interact with the connections stack. Read the count once to keep the assert message accurate. - int connectionCount = _http11Connections.Count; - Debug.Assert(_associatedHttp11ConnectionCount >= connectionCount + _pendingHttp11ConnectionCount, - $"Expected {_associatedHttp11ConnectionCount} >= {connectionCount} + {_pendingHttp11ConnectionCount}"); -#endif - Debug.Assert(_associatedHttp11ConnectionCount <= _maxHttp11Connections, - $"Expected {_associatedHttp11ConnectionCount} <= {_maxHttp11Connections}"); - Debug.Assert(_associatedHttp11ConnectionCount >= _pendingHttp11ConnectionCount, - $"Expected {_associatedHttp11ConnectionCount} >= {_pendingHttp11ConnectionCount}"); - - if (_http11RequestQueue.Count != 0) - { - if (connection is not null || _http11Connections.TryPop(out connection)) - { - // TryDequeueWaiter will prune completed requests from the head of the queue, - // so it's possible for it to return false even though we checked that Count != 0. - bool success = _http11RequestQueue.TryDequeueWaiter(this, out waiter); - Debug.Assert(success == waiter is not null); - } - } - - // Update the empty queue flag now. - // If the request queue is now empty, returning connections will use the fast path and skip calling into this method. - _http11RequestQueueIsEmptyAndNotDisposed = _http11RequestQueue.Count == 0 && !_disposed; - - if (waiter is null) - { - // We didn't find a waiter to signal, or there were no connections available. - - if (connection is not null) - { - // A connection was provided to this method, or we rented one from the pool. - // Return it back to the pool since we're not going to use it yet. - - // We're returning it while holding the lock to avoid a scenario where - // - thread A sees no requests are waiting in the queue (current thread) - // - thread B adds a request to the queue, and sees no connections are available - // - thread A returns the connection to the pool - // We'd have both a connection and a request waiting in the pool, but nothing to pair the two. - - // The main scenario where we'll reach this branch is when we enqueue a request to the queue - // and set the _http11RequestQueueIsEmptyAndNotDisposed flag to false, followed by multiple - // returning connections observing the flag and calling into this method before we clear the flag. - // This should be a relatively rare case, so the added contention should be minimal. - _http11Connections.Push(connection); - } - else - { - CheckForHttp11ConnectionInjection(); - } - - break; - } - } - - Debug.Assert(connection is not null); - - if (TrySignalWaiter(waiter, connection)) - { - // Success. Note that we did not call connection.PrepareForReuse - // before signaling the waiter. This is intentional, as the fact that - // this method was called indicates that the connection is either new, - // or was just returned to the pool and is still in a good state. - return; - } - - // The request was already cancelled or handled by a different connection. - // Loop again to try to find another request to signal, or return the connection. - } - - if (_disposed) - { - // The pool is being disposed and there are no more requests to handle. - // Clean up any idle connections still waiting in the pool. - while (_http11Connections.TryPop(out connection)) - { - connection.Dispose(); - } - } - } - - private bool TryGetPooledHttp11Connection(HttpRequestMessage request, bool async, [NotNullWhen(true)] out HttpConnection? connection, [NotNullWhen(false)] out HttpConnectionWaiter? waiter) - { - while (_http11Connections.TryPop(out connection)) - { - if (CheckExpirationOnGet(connection)) - { - if (NetEventSource.Log.IsEnabled()) connection.Trace("Found expired HTTP/1.1 connection in pool."); - connection.Dispose(); - continue; - } - - if (!connection.PrepareForReuse(async)) - { - if (NetEventSource.Log.IsEnabled()) connection.Trace("Found invalid HTTP/1.1 connection in pool."); - connection.Dispose(); - continue; - } - - if (NetEventSource.Log.IsEnabled()) connection.Trace("Found usable HTTP/1.1 connection in pool."); - waiter = null; - return true; - } - - // Slow path - no available connection found. - // Push the request onto the request queue and check if we should inject a new connection. - - waiter = new HttpConnectionWaiter(); - - // Technically this block under the lock could be a part of ProcessHttp11RequestQueue to avoid taking the lock twice. - // It is kept separate to simplify that method (avoid extra arguments that are only relevant for this caller). - lock (SyncObj) - { - _http11RequestQueue.EnqueueRequest(request, waiter); - - // Disable the fast path and force connections returned to the pool to check the request queue first. - _http11RequestQueueIsEmptyAndNotDisposed = false; - } - - // Other threads may have added a connection to the pool before we were able to - // add the request to the queue, so we must check for an available connection again. - - ProcessHttp11RequestQueue(null); - return false; - } - - private async Task HandleHttp11Downgrade(HttpRequestMessage request, Stream stream, TransportContext? transportContext, IPEndPoint? remoteEndPoint, CancellationToken cancellationToken) - { - if (NetEventSource.Log.IsEnabled()) Trace("Server does not support HTTP2; disabling HTTP2 use and proceeding with HTTP/1.1 connection"); - - bool canUse = true; - HttpConnectionWaiter? waiter = null; - lock (SyncObj) - { - Debug.Assert(_pendingHttp2Connection); - Debug.Assert(_associatedHttp2ConnectionCount > 0); - - // Server does not support HTTP2. Disable further HTTP2 attempts. - _http2Enabled = false; - _associatedHttp2ConnectionCount--; - _pendingHttp2Connection = false; - - if (_associatedHttp11ConnectionCount < _maxHttp11Connections) - { - _associatedHttp11ConnectionCount++; - _pendingHttp11ConnectionCount++; - } - else - { - // We are already at the limit for HTTP/1.1 connections, so do not proceed with this connection. - canUse = false; - } - - _http2RequestQueue.TryDequeueWaiter(this, out waiter); - } - - // Signal to any queued HTTP2 requests that they must downgrade. - while (waiter is not null) - { - if (NetEventSource.Log.IsEnabled()) Trace("Downgrading queued HTTP2 request to HTTP/1.1"); - - // We are done with the HTTP2 connection attempt, no point to cancel it. - Volatile.Write(ref waiter.ConnectionCancellationTokenSource, null); - - // We don't care if this fails; that means the request was previously canceled or handled by a different connection. - waiter.TrySetResult(null); - - lock (SyncObj) - { - _http2RequestQueue.TryDequeueWaiter(this, out waiter); - } - } - - if (!canUse) - { - if (NetEventSource.Log.IsEnabled()) Trace("Discarding downgraded HTTP/1.1 connection because HTTP/1.1 connection limit is exceeded"); - stream.Dispose(); - return; - } - - HttpConnection http11Connection; - try - { - // Note, the same CancellationToken from the original HTTP2 connection establishment still applies here. - http11Connection = await ConstructHttp11ConnectionAsync(true, stream, transportContext, request, remoteEndPoint, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException oce) when (oce.CancellationToken == cancellationToken) - { - HandleHttp11ConnectionFailure(requestWaiter: null, CreateConnectTimeoutException(oce)); - return; - } - catch (Exception e) - { - HandleHttp11ConnectionFailure(requestWaiter: null, e); - return; - } - - AddNewHttp11Connection(http11Connection, initialRequestWaiter: null); - } - - private async Task AddHttp2ConnectionAsync(RequestQueue.QueueItem queueItem) - { - if (NetEventSource.Log.IsEnabled()) Trace("Creating new HTTP/2 connection for pool."); - - // Queue the remainder of the work so that this method completes quickly - // and escapes locks held by the caller. - await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); - - Http2Connection? connection = null; - Exception? connectionException = null; - HttpConnectionWaiter waiter = queueItem.Waiter; - - CancellationTokenSource cts = GetConnectTimeoutCancellationTokenSource(); - waiter.ConnectionCancellationTokenSource = cts; - try - { - (Stream stream, TransportContext? transportContext, IPEndPoint? remoteEndPoint) = await ConnectAsync(queueItem.Request, true, cts.Token).ConfigureAwait(false); - - if (IsSecure) - { - SslStream sslStream = (SslStream)stream; - - if (sslStream.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2) - { - // The server accepted our request for HTTP2. - - if (sslStream.SslProtocol < SslProtocols.Tls12) - { - stream.Dispose(); - connectionException = new HttpRequestException(SR.Format(SR.net_ssl_http2_requires_tls12, sslStream.SslProtocol)); - } - else - { - connection = await ConstructHttp2ConnectionAsync(stream, queueItem.Request, remoteEndPoint, cts.Token).ConfigureAwait(false); - } - } - else - { - // We established an SSL connection, but the server denied our request for HTTP2. - await HandleHttp11Downgrade(queueItem.Request, stream, transportContext, remoteEndPoint, cts.Token).ConfigureAwait(false); - return; - } - } - else - { - connection = await ConstructHttp2ConnectionAsync(stream, queueItem.Request, remoteEndPoint, cts.Token).ConfigureAwait(false); - } - } - catch (Exception e) - { - connectionException = e is OperationCanceledException oce && oce.CancellationToken == cts.Token && !waiter.CancelledByOriginatingRequestCompletion ? - CreateConnectTimeoutException(oce) : - e; - } - finally - { - lock (waiter) - { - waiter.ConnectionCancellationTokenSource = null; - cts.Dispose(); - } - } - - if (connection is not null) - { - // Add the new connection to the pool. - ReturnHttp2Connection(connection, isNewConnection: true, queueItem.Waiter); - } - else - { - Debug.Assert(connectionException is not null); - HandleHttp2ConnectionFailure(waiter, connectionException); - } - } - - private void CheckForHttp2ConnectionInjection() - { - Debug.Assert(HasSyncObjLock); - - _http2RequestQueue.PruneCompletedRequestsFromHeadOfQueue(this); - - // Determine if we can and should add a new connection to the pool. - int availableHttp2ConnectionCount = _availableHttp2Connections?.Count ?? 0; - bool willInject = availableHttp2ConnectionCount == 0 && // No available connections - !_pendingHttp2Connection && // Only allow one pending HTTP2 connection at a time - _http2RequestQueue.Count > 0 && // There are requests left on the queue - (_associatedHttp2ConnectionCount == 0 || EnableMultipleHttp2Connections) && // We allow multiple connections, or don't have a connection currently - _http2RequestQueue.RequestsWithoutAConnectionAttempt > 0; // There are requests we haven't issued a connection attempt for - - if (NetEventSource.Log.IsEnabled()) - { - Trace($"Available HTTP/2.0 connections: {availableHttp2ConnectionCount}, " + - $"Pending HTTP/2.0 connection: {_pendingHttp2Connection}, " + - $"Requests in the queue: {_http2RequestQueue.Count}, " + - $"Requests without a connection attempt: {_http2RequestQueue.RequestsWithoutAConnectionAttempt}, " + - $"Total associated HTTP/2.0 connections: {_associatedHttp2ConnectionCount}, " + - $"Will inject connection: {willInject}."); - } - - if (willInject) - { - _associatedHttp2ConnectionCount++; - _pendingHttp2Connection = true; - - RequestQueue.QueueItem queueItem = _http2RequestQueue.PeekNextRequestForConnectionAttempt(); - _ = AddHttp2ConnectionAsync(queueItem); // ignore returned task - } - } - - private bool TryGetPooledHttp2Connection(HttpRequestMessage request, [NotNullWhen(true)] out Http2Connection? connection, out HttpConnectionWaiter? waiter) - { - Debug.Assert(_kind == HttpConnectionKind.Https || _kind == HttpConnectionKind.SslProxyTunnel || _kind == HttpConnectionKind.Http || _kind == HttpConnectionKind.SocksTunnel || _kind == HttpConnectionKind.SslSocksTunnel); - - // Look for a usable connection. - while (true) - { - lock (SyncObj) - { - if (!_http2Enabled) - { - waiter = null; - connection = null; - return false; - } - - int availableConnectionCount = _availableHttp2Connections?.Count ?? 0; - if (availableConnectionCount > 0) - { - // We have a connection that we can attempt to use. - // Validate it below outside the lock, to avoid doing expensive operations while holding the lock. - connection = _availableHttp2Connections![availableConnectionCount - 1]; - } - else - { - // No available connections. Add to the request queue. - waiter = _http2RequestQueue.EnqueueRequest(request); - - CheckForHttp2ConnectionInjection(); - - // There were no available connections. This request has been added to the request queue. - if (NetEventSource.Log.IsEnabled()) Trace($"No available HTTP/2 connections; request queued."); - connection = null; - return false; - } - } - - if (CheckExpirationOnGet(connection)) - { - if (NetEventSource.Log.IsEnabled()) connection.Trace("Found expired HTTP/2 connection in pool."); - - InvalidateHttp2Connection(connection); - continue; - } - - if (!connection.TryReserveStream()) - { - if (NetEventSource.Log.IsEnabled()) connection.Trace("Found HTTP/2 connection in pool without available streams."); - - bool found = false; - lock (SyncObj) - { - int index = _availableHttp2Connections.IndexOf(connection); - if (index != -1) - { - found = true; - _availableHttp2Connections.RemoveAt(index); - } - } - - // If we didn't find the connection, then someone beat us to removing it (or it shut down) - if (found) - { - DisableHttp2Connection(connection); - } - continue; - } - - if (NetEventSource.Log.IsEnabled()) connection.Trace("Found usable HTTP/2 connection in pool."); - waiter = null; - return true; - } - } - - [SupportedOSPlatform("windows")] - [SupportedOSPlatform("linux")] - [SupportedOSPlatform("macos")] - private async ValueTask GetHttp3ConnectionAsync(HttpRequestMessage request, HttpAuthority authority, CancellationToken cancellationToken) - { - Debug.Assert(_kind == HttpConnectionKind.Https); - Debug.Assert(_http3Enabled); - - Http3Connection? http3Connection = Volatile.Read(ref _http3Connection); - - if (http3Connection != null) - { - if (CheckExpirationOnGet(http3Connection) || http3Connection.Authority != authority) - { - // Connection expired. - if (NetEventSource.Log.IsEnabled()) http3Connection.Trace("Found expired HTTP3 connection."); - http3Connection.Dispose(); - InvalidateHttp3Connection(http3Connection); - } - else - { - // Connection exists and it is still good to use. - if (NetEventSource.Log.IsEnabled()) Trace("Using existing HTTP3 connection."); - return http3Connection; - } - } - - // Ensure that the connection creation semaphore is created - if (_http3ConnectionCreateLock == null) - { - lock (SyncObj) - { - _http3ConnectionCreateLock ??= new SemaphoreSlim(1); - } - } - - await _http3ConnectionCreateLock.WaitAsync(cancellationToken).ConfigureAwait(false); - try - { - if (_http3Connection != null) - { - // Someone beat us to creating the connection. - - if (NetEventSource.Log.IsEnabled()) - { - Trace("Using existing HTTP3 connection."); - } - - return _http3Connection; - } - - if (NetEventSource.Log.IsEnabled()) - { - Trace("Attempting new HTTP3 connection."); - } - - QuicConnection quicConnection; - try - { - quicConnection = await ConnectHelper.ConnectQuicAsync(request, new DnsEndPoint(authority.IdnHost, authority.Port), _poolManager.Settings._pooledConnectionIdleTimeout, _sslOptionsHttp3!, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - if (NetEventSource.Log.IsEnabled()) Trace($"QUIC connection failed: {ex}"); - - // Block list authority only if the connection attempt was not cancelled. - if (ex is not OperationCanceledException oce || !cancellationToken.IsCancellationRequested || oce.CancellationToken != cancellationToken) - { - // Disables HTTP/3 until server announces it can handle it via Alt-Svc. - BlocklistAuthority(authority, ex); - } - throw; - } - - if (quicConnection.NegotiatedApplicationProtocol != SslApplicationProtocol.Http3) - { - BlocklistAuthority(authority); - throw new HttpRequestException(HttpRequestError.ConnectionError, "QUIC connected but no HTTP/3 indicated via ALPN.", null, RequestRetryType.RetryOnConnectionFailure); - } - - // if the authority was sent as an option through alt-svc then include alt-used header - http3Connection = new Http3Connection(this, authority, quicConnection, includeAltUsedHeader: _http3Authority == authority); - _http3Connection = http3Connection; - - if (NetEventSource.Log.IsEnabled()) - { - Trace("New HTTP3 connection established."); - } - - return http3Connection; - } - finally - { - _http3ConnectionCreateLock.Release(); - } - } - - // Returns null if HTTP3 cannot be used. - [SupportedOSPlatform("windows")] - [SupportedOSPlatform("linux")] - [SupportedOSPlatform("macos")] - private async ValueTask TrySendUsingHttp3Async(HttpRequestMessage request, CancellationToken cancellationToken) - { - // Loop in case we get a 421 and need to send the request to a different authority. - while (true) - { - HttpAuthority? authority = _http3Authority; - - // If H3 is explicitly requested, assume prenegotiated H3. - if (request.Version.Major >= 3 && request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) - { - authority ??= _originAuthority; - } - - if (authority == null) - { - return null; - } - - Exception? reasonException; - if (IsAltSvcBlocked(authority, out reasonException)) - { - ThrowGetVersionException(request, 3, reasonException); - } - - long queueStartingTimestamp = HttpTelemetry.Log.IsEnabled() || Settings._metrics!.RequestsQueueDuration.Enabled ? Stopwatch.GetTimestamp() : 0; - - ValueTask connectionTask = GetHttp3ConnectionAsync(request, authority, cancellationToken); - - Http3Connection connection = await connectionTask.ConfigureAwait(false); - - HttpResponseMessage response = await connection.SendAsync(request, queueStartingTimestamp, cancellationToken).ConfigureAwait(false); - - // If an Alt-Svc authority returns 421, it means it can't actually handle the request. - // An authority is supposed to be able to handle ALL requests to the origin, so this is a server bug. - // In this case, we blocklist the authority and retry the request at the origin. - if (response.StatusCode == HttpStatusCode.MisdirectedRequest && connection.Authority != _originAuthority) - { - response.Dispose(); - BlocklistAuthority(connection.Authority); - continue; - } - - return response; - } - } - - /// Check for the Alt-Svc header, to upgrade to HTTP/3. - private void ProcessAltSvc(HttpResponseMessage response) - { - if (_altSvcEnabled && response.Headers.TryGetValues(KnownHeaders.AltSvc.Descriptor, out IEnumerable? altSvcHeaderValues)) - { - HandleAltSvc(altSvcHeaderValues, response.Headers.Age); - } - } - - public async ValueTask SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) - { - _usedSinceLastCleanup = true; - - // Loop on connection failures (or other problems like version downgrade) and retry if possible. - int retryCount = 0; - while (true) - { - HttpConnectionWaiter? http11ConnectionWaiter = null; - HttpConnectionWaiter? http2ConnectionWaiter = null; - try - { - HttpResponseMessage? response = null; - - // Use HTTP/3 if possible. - if (IsHttp3Supported() && // guard to enable trimming HTTP/3 support - _http3Enabled && - (request.Version.Major >= 3 || (request.VersionPolicy == HttpVersionPolicy.RequestVersionOrHigher && IsSecure)) && - !request.IsExtendedConnectRequest) - { - Debug.Assert(async); - if (QuicConnection.IsSupported) - { - if (_sslOptionsHttp3 == null) - { - // deferred creation. We use atomic exchange to be sure all threads point to single object to mimic ctor behavior. - SslClientAuthenticationOptions sslOptionsHttp3 = ConstructSslOptions(_poolManager, _sslOptionsHttp11!.TargetHost!); - sslOptionsHttp3.ApplicationProtocols = s_http3ApplicationProtocols; - Interlocked.CompareExchange(ref _sslOptionsHttp3, sslOptionsHttp3, null); - } - - response = await TrySendUsingHttp3Async(request, cancellationToken).ConfigureAwait(false); - } - else - { - _altSvcEnabled = false; - _http3Enabled = false; - } - } - - if (response is null) - { - // We could not use HTTP/3. Do not continue if downgrade is not allowed. - if (request.Version.Major >= 3 && request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) - { - ThrowGetVersionException(request, 3); - } - - // Use HTTP/2 if possible. - if (_http2Enabled && - (request.Version.Major >= 2 || (request.VersionPolicy == HttpVersionPolicy.RequestVersionOrHigher && IsSecure)) && - (request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower || IsSecure)) // prefer HTTP/1.1 if connection is not secured and downgrade is possible - { - if (!TryGetPooledHttp2Connection(request, out Http2Connection? connection, out http2ConnectionWaiter) && - http2ConnectionWaiter != null) - { - connection = await http2ConnectionWaiter.WaitForConnectionAsync(request, this, async, cancellationToken).ConfigureAwait(false); - } - - Debug.Assert(connection is not null || !_http2Enabled); - if (connection is not null) - { - if (request.IsExtendedConnectRequest) - { - await connection.InitialSettingsReceived.WaitWithCancellationAsync(cancellationToken).ConfigureAwait(false); - if (!connection.IsConnectEnabled) - { - HttpRequestException exception = new(HttpRequestError.ExtendedConnectNotSupported, SR.net_unsupported_extended_connect); - exception.Data["SETTINGS_ENABLE_CONNECT_PROTOCOL"] = false; - throw exception; - } - } - - response = await connection.SendAsync(request, async, cancellationToken).ConfigureAwait(false); - } - } - - if (response is null) - { - // We could not use HTTP/2. Do not continue if downgrade is not allowed. - if (request.Version.Major >= 2 && request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) - { - ThrowGetVersionException(request, 2); - } - - // Use HTTP/1.x. - if (!TryGetPooledHttp11Connection(request, async, out HttpConnection? connection, out http11ConnectionWaiter)) - { - connection = await http11ConnectionWaiter.WaitForConnectionAsync(request, this, async, cancellationToken).ConfigureAwait(false); - } - - connection.Acquire(); // In case we are doing Windows (i.e. connection-based) auth, we need to ensure that we hold on to this specific connection while auth is underway. - try - { - response = await SendWithNtConnectionAuthAsync(connection, request, async, doRequestAuth, cancellationToken).ConfigureAwait(false); - } - finally - { - connection.Release(); - } - } - } - - ProcessAltSvc(response); - return response; - } - catch (HttpRequestException e) when (e.AllowRetry == RequestRetryType.RetryOnConnectionFailure) - { - Debug.Assert(retryCount >= 0 && retryCount <= MaxConnectionFailureRetries); - - if (retryCount == MaxConnectionFailureRetries) - { - if (NetEventSource.Log.IsEnabled()) - { - Trace($"MaxConnectionFailureRetries limit of {MaxConnectionFailureRetries} hit. Retryable request will not be retried. Exception: {e}"); - } - - throw; - } - - retryCount++; - - if (NetEventSource.Log.IsEnabled()) - { - Trace($"Retry attempt {retryCount} after connection failure. Connection exception: {e}"); - } - - // Eat exception and try again. - } - catch (HttpRequestException e) when (e.AllowRetry == RequestRetryType.RetryOnLowerHttpVersion) - { - // Throw if fallback is not allowed by the version policy. - if (request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) - { - throw new HttpRequestException(HttpRequestError.VersionNegotiationError, SR.Format(SR.net_http_requested_version_server_refused, request.Version, request.VersionPolicy), e); - } - - if (NetEventSource.Log.IsEnabled()) - { - Trace($"Retrying request because server requested version fallback: {e}"); - } - - // Eat exception and try again on a lower protocol version. - request.Version = HttpVersion.Version11; - } - catch (HttpRequestException e) when (e.AllowRetry == RequestRetryType.RetryOnStreamLimitReached) - { - if (NetEventSource.Log.IsEnabled()) - { - Trace($"Retrying request on another HTTP/2 connection after active streams limit is reached on existing one: {e}"); - } - - // Eat exception and try again. - } - finally - { - // We never cancel both attempts at the same time. When downgrade happens, it's possible that both waiters are non-null, - // but in that case http2ConnectionWaiter.ConnectionCancellationTokenSource shall be null. - Debug.Assert(http11ConnectionWaiter is null || http2ConnectionWaiter?.ConnectionCancellationTokenSource is null); - CancelIfNecessary(http11ConnectionWaiter, cancellationToken.IsCancellationRequested); - CancelIfNecessary(http2ConnectionWaiter, cancellationToken.IsCancellationRequested); - } - } - } - - private void CancelIfNecessary(HttpConnectionWaiter? waiter, bool requestCancelled) - where T : HttpConnectionBase? - { - int timeout = GlobalHttpSettings.SocketsHttpHandler.PendingConnectionTimeoutOnRequestCompletion; - if (waiter?.ConnectionCancellationTokenSource is null || - timeout == Timeout.Infinite || - Settings._connectTimeout != Timeout.InfiniteTimeSpan && timeout > (int)Settings._connectTimeout.TotalMilliseconds) // Do not override shorter ConnectTimeout - { - return; - } - - lock (waiter) - { - if (waiter.ConnectionCancellationTokenSource is null) - { - return; - } - - if (NetEventSource.Log.IsEnabled()) - { - Trace($"Initiating cancellation of a pending connection attempt with delay of {timeout} ms, " + - $"Reason: {(requestCancelled ? "Request cancelled" : "Request served by another connection")}."); - } - - waiter.CancelledByOriginatingRequestCompletion = true; - if (timeout > 0) - { - // Cancel after the specified timeout. This cancellation will not fire if the connection - // succeeds within the delay and the CTS becomes disposed. - waiter.ConnectionCancellationTokenSource.CancelAfter(timeout); - } - else - { - // Cancel immediately if no timeout specified. - waiter.ConnectionCancellationTokenSource.Cancel(); - } - } - } - - /// - /// Inspects a collection of Alt-Svc headers to find the first eligible upgrade path. - /// - /// TODO: common case will likely be a single value. Optimize for that. - internal void HandleAltSvc(IEnumerable altSvcHeaderValues, TimeSpan? responseAge) - { - HttpAuthority? nextAuthority = null; - TimeSpan nextAuthorityMaxAge = default; - bool nextAuthorityPersist = false; - - foreach (string altSvcHeaderValue in altSvcHeaderValues) - { - int parseIdx = 0; - - if (AltSvcHeaderParser.Parser.TryParseValue(altSvcHeaderValue, null, ref parseIdx, out object? parsedValue)) - { - var value = (AltSvcHeaderValue?)parsedValue; - - // 'clear' should be the only value present. - if (value == AltSvcHeaderValue.Clear) - { - lock (SyncObj) - { - ExpireAltSvcAuthority(); - Debug.Assert(_authorityExpireTimer != null || _disposed); - _authorityExpireTimer?.Change(Timeout.Infinite, Timeout.Infinite); - break; - } - } - - if (nextAuthority == null && value != null && value.AlpnProtocolName == "h3") - { - var authority = new HttpAuthority(value.Host ?? _originAuthority.IdnHost, value.Port); - if (IsAltSvcBlocked(authority, out _)) - { - // Skip authorities in our blocklist. - continue; - } - - TimeSpan authorityMaxAge = value.MaxAge; - - if (responseAge != null) - { - authorityMaxAge -= responseAge.GetValueOrDefault(); - } - - if (authorityMaxAge > TimeSpan.Zero) - { - nextAuthority = authority; - nextAuthorityMaxAge = authorityMaxAge; - nextAuthorityPersist = value.Persist; - } - } - } - } - - // There's a race here in checking _http3Authority outside of the lock, - // but there's really no bad behavior if _http3Authority changes in the mean time. - if (nextAuthority != null && !nextAuthority.Equals(_http3Authority)) - { - // Clamp the max age to 30 days... this is arbitrary but prevents passing a too-large TimeSpan to the Timer. - if (nextAuthorityMaxAge.Ticks > (30 * TimeSpan.TicksPerDay)) - { - nextAuthorityMaxAge = TimeSpan.FromTicks(30 * TimeSpan.TicksPerDay); - } - - lock (SyncObj) - { - if (_disposed) - { - // avoid creating or touching _authorityExpireTimer after disposal - return; - } - - if (_authorityExpireTimer == null) - { - var thisRef = new WeakReference(this); - - using (ExecutionContext.SuppressFlow()) - { - _authorityExpireTimer = new Timer(static o => - { - var wr = (WeakReference)o!; - if (wr.TryGetTarget(out HttpConnectionPool? @this)) - { - @this.ExpireAltSvcAuthority(); - } - }, thisRef, nextAuthorityMaxAge, Timeout.InfiniteTimeSpan); - } - } - else - { - _authorityExpireTimer.Change(nextAuthorityMaxAge, Timeout.InfiniteTimeSpan); - } - - _http3Authority = nextAuthority; - _persistAuthority = nextAuthorityPersist; - } - - if (!nextAuthorityPersist) - { -#if !ILLUMOS && !SOLARIS - _poolManager.StartMonitoringNetworkChanges(); -#endif - } - } - } - - /// - /// Expires the current Alt-Svc authority, resetting the connection back to origin. - /// - private void ExpireAltSvcAuthority() - { - // If we ever support prenegotiated HTTP/3, this should be set to origin, not nulled out. - _http3Authority = null; - } - - /// - /// Checks whether the given is on the currext Alt-Svc blocklist. - /// If it is, then it places the cause in the - /// - /// - private bool IsAltSvcBlocked(HttpAuthority authority, out Exception? reasonException) - { - if (_altSvcBlocklist != null) - { - lock (_altSvcBlocklist) - { - return _altSvcBlocklist.TryGetValue(authority, out reasonException); - } - } - reasonException = null; - return false; - } - - - /// - /// Blocklists an authority and resets the current authority back to origin. - /// If the number of blocklisted authorities exceeds , - /// Alt-Svc will be disabled entirely for a period of time. - /// - /// - /// This is called when we get a "421 Misdirected Request" from an alternate authority. - /// A future strategy would be to retry the individual request on an older protocol, we'd want to have - /// some logic to blocklist after some number of failures to avoid doubling our request latency. - /// - /// For now, the spec states alternate authorities should be able to handle ALL requests, so this - /// is treated as an exceptional error by immediately blocklisting the authority. - /// - internal void BlocklistAuthority(HttpAuthority badAuthority, Exception? exception = null) - { - Debug.Assert(badAuthority != null); - - Dictionary? altSvcBlocklist = _altSvcBlocklist; - - if (altSvcBlocklist == null) - { - lock (SyncObj) - { - if (_disposed) - { - // avoid creating _altSvcBlocklistTimerCancellation after disposal - return; - } - - altSvcBlocklist = _altSvcBlocklist; - if (altSvcBlocklist == null) - { - altSvcBlocklist = new Dictionary(); - _altSvcBlocklistTimerCancellation = new CancellationTokenSource(); - _altSvcBlocklist = altSvcBlocklist; - } - } - } - - bool added, disabled = false; - - lock (altSvcBlocklist) - { - added = altSvcBlocklist.TryAdd(badAuthority, exception); - - if (added && altSvcBlocklist.Count >= MaxAltSvcIgnoreListSize && _altSvcEnabled) - { - _altSvcEnabled = false; - disabled = true; - } - } - - CancellationToken altSvcBlocklistTimerCt; - - lock (SyncObj) - { - if (_disposed) - { - // avoid touching _authorityExpireTimer and _altSvcBlocklistTimerCancellation after disposal - return; - } - - if (_http3Authority == badAuthority) - { - ExpireAltSvcAuthority(); - Debug.Assert(_authorityExpireTimer != null); - _authorityExpireTimer.Change(Timeout.Infinite, Timeout.Infinite); - } - - Debug.Assert(_altSvcBlocklistTimerCancellation != null); - altSvcBlocklistTimerCt = _altSvcBlocklistTimerCancellation.Token; - } - - if (added) - { - _ = Task.Delay(AltSvcBlocklistTimeoutInMilliseconds, altSvcBlocklistTimerCt) - .ContinueWith(t => - { - lock (altSvcBlocklist) - { - altSvcBlocklist.Remove(badAuthority); - } - }, altSvcBlocklistTimerCt, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); - } - - if (disabled) - { - _ = Task.Delay(AltSvcBlocklistTimeoutInMilliseconds, altSvcBlocklistTimerCt) - .ContinueWith(t => - { - _altSvcEnabled = true; - }, altSvcBlocklistTimerCt, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); - } - } - - public void OnNetworkChanged() - { - lock (SyncObj) - { - if (_http3Authority != null && _persistAuthority == false) - { - ExpireAltSvcAuthority(); - Debug.Assert(_authorityExpireTimer != null || _disposed); - _authorityExpireTimer?.Change(Timeout.Infinite, Timeout.Infinite); - } - } - } - - public Task SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) - { - if (doRequestAuth && Settings._credentials != null) - { - return AuthenticationHelper.SendWithNtConnectionAuthAsync(request, async, Settings._credentials, connection, this, cancellationToken); - } - - return SendWithNtProxyAuthAsync(connection, request, async, cancellationToken); - } - - private bool DoProxyAuth => (_kind == HttpConnectionKind.Proxy || _kind == HttpConnectionKind.ProxyConnect); - - public Task SendWithNtProxyAuthAsync(HttpConnection connection, HttpRequestMessage request, bool async, CancellationToken cancellationToken) - { - if (DoProxyAuth && ProxyCredentials is not null) - { - return AuthenticationHelper.SendWithNtProxyAuthAsync(request, ProxyUri!, async, ProxyCredentials, connection, this, cancellationToken); - } - - return connection.SendAsync(request, async, cancellationToken); - } - - public ValueTask SendWithProxyAuthAsync(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) - { - if (DoProxyAuth && ProxyCredentials is not null) - { - return AuthenticationHelper.SendWithProxyAuthAsync(request, _proxyUri!, async, ProxyCredentials, doRequestAuth, this, cancellationToken); - } - - return SendWithVersionDetectionAndRetryAsync(request, async, doRequestAuth, cancellationToken); - } - - public ValueTask SendAsync(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) - { - // We need the User-Agent header when we send a CONNECT request to the proxy. - // We must read the header early, before we return the ownership of the request back to the user. - if ((Kind is HttpConnectionKind.ProxyTunnel or HttpConnectionKind.SslProxyTunnel) && - request.HasHeaders && - request.Headers.NonValidated.TryGetValues(HttpKnownHeaderNames.UserAgent, out HeaderStringValues userAgent)) - { - _connectTunnelUserAgent = userAgent.ToString(); - } - - if (doRequestAuth && Settings._credentials != null) - { - return AuthenticationHelper.SendWithRequestAuthAsync(request, async, Settings._credentials, Settings._preAuthenticate, this, cancellationToken); - } - - return SendWithProxyAuthAsync(request, async, doRequestAuth, cancellationToken); - } - - private CancellationTokenSource GetConnectTimeoutCancellationTokenSource() => new CancellationTokenSource(Settings._connectTimeout); - - private async ValueTask<(Stream, TransportContext?, IPEndPoint?)> ConnectAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken) - { - Stream? stream = null; - IPEndPoint? remoteEndPoint = null; - switch (_kind) - { - case HttpConnectionKind.Http: - case HttpConnectionKind.Https: - case HttpConnectionKind.ProxyConnect: - stream = await ConnectToTcpHostAsync(_originAuthority.IdnHost, _originAuthority.Port, request, async, cancellationToken).ConfigureAwait(false); - // remoteEndPoint is returned for diagnostic purposes. - remoteEndPoint = GetRemoteEndPoint(stream); - if (_kind == HttpConnectionKind.ProxyConnect && _sslOptionsProxy != null) - { - stream = await ConnectHelper.EstablishSslConnectionAsync(_sslOptionsProxy, request, async, stream, cancellationToken).ConfigureAwait(false); - } - break; - - case HttpConnectionKind.Proxy: - stream = await ConnectToTcpHostAsync(_proxyUri!.IdnHost, _proxyUri.Port, request, async, cancellationToken).ConfigureAwait(false); - // remoteEndPoint is returned for diagnostic purposes. - remoteEndPoint = GetRemoteEndPoint(stream); - if (_sslOptionsProxy != null) - { - stream = await ConnectHelper.EstablishSslConnectionAsync(_sslOptionsProxy, request, async, stream, cancellationToken).ConfigureAwait(false); - } - break; - - case HttpConnectionKind.ProxyTunnel: - case HttpConnectionKind.SslProxyTunnel: - stream = await EstablishProxyTunnelAsync(async, cancellationToken).ConfigureAwait(false); - - if (stream is HttpContentStream contentStream && contentStream._connection?._stream is Stream innerStream) - { - remoteEndPoint = GetRemoteEndPoint(innerStream); - } - - break; - - case HttpConnectionKind.SocksTunnel: - case HttpConnectionKind.SslSocksTunnel: - stream = await EstablishSocksTunnel(request, async, cancellationToken).ConfigureAwait(false); - // remoteEndPoint is returned for diagnostic purposes. - remoteEndPoint = GetRemoteEndPoint(stream); - break; - } - - Debug.Assert(stream != null); - - TransportContext? transportContext = null; - if (IsSecure) - { - SslStream? sslStream = stream as SslStream; - if (sslStream == null) - { - sslStream = await ConnectHelper.EstablishSslConnectionAsync(GetSslOptionsForRequest(request), request, async, stream, cancellationToken).ConfigureAwait(false); - } - else - { - if (NetEventSource.Log.IsEnabled()) - { - Trace($"Connected with custom SslStream: alpn='${sslStream.NegotiatedApplicationProtocol}'"); - } - } - transportContext = sslStream.TransportContext; - stream = sslStream; - } - - static IPEndPoint? GetRemoteEndPoint(Stream stream) => (stream as NetworkStream)?.Socket?.RemoteEndPoint as IPEndPoint; - - return (stream, transportContext, remoteEndPoint); - } - - private async ValueTask ConnectToTcpHostAsync(string host, int port, HttpRequestMessage initialRequest, bool async, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - var endPoint = new DnsEndPoint(host, port); - Stream? stream = null; - try - { - // If a ConnectCallback was supplied, use that to establish the connection. - if (Settings._connectCallback != null) - { - ValueTask streamTask = Settings._connectCallback(new SocketsHttpConnectionContext(endPoint, initialRequest), cancellationToken); - - if (!async && !streamTask.IsCompleted) - { - // User-provided ConnectCallback is completing asynchronously but the user is making a synchronous request; if the user cares, they should - // set it up so that synchronous requests are made on a handler with a synchronously-completing ConnectCallback supplied. If in the future, - // we could add a Boolean to SocketsHttpConnectionContext (https://github.com/dotnet/runtime/issues/44876) to let the callback know whether - // this request is sync or async. - Trace($"{nameof(SocketsHttpHandler.ConnectCallback)} completing asynchronously for a synchronous request."); - } - - stream = await streamTask.ConfigureAwait(false) ?? throw new HttpRequestException(SR.net_http_null_from_connect_callback); - } - else - { - // Otherwise, create and connect a socket using default settings. - Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp) { NoDelay = true }; - try - { - if (async) - { - await socket.ConnectAsync(endPoint, cancellationToken).ConfigureAwait(false); - } - else - { - using (cancellationToken.UnsafeRegister(static s => ((Socket)s!).Dispose(), socket)) - { - socket.Connect(endPoint); - } - } - - stream = new NetworkStream(socket, ownsSocket: true); - } - catch - { - socket.Dispose(); - throw; - } - } - - return stream; - } - catch (Exception ex) - { - throw ex is OperationCanceledException oce && oce.CancellationToken == cancellationToken ? - CancellationHelper.CreateOperationCanceledException(innerException: null, cancellationToken) : - ConnectHelper.CreateWrappedException(ex, endPoint.Host, endPoint.Port, cancellationToken); - } - } - - internal async ValueTask CreateHttp11ConnectionAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken) - { - (Stream stream, TransportContext? transportContext, IPEndPoint? remoteEndPoint) = await ConnectAsync(request, async, cancellationToken).ConfigureAwait(false); - return await ConstructHttp11ConnectionAsync(async, stream, transportContext, request, remoteEndPoint, cancellationToken).ConfigureAwait(false); - } - - private SslClientAuthenticationOptions GetSslOptionsForRequest(HttpRequestMessage request) - { - if (_http2Enabled) - { - if (request.Version.Major >= 2 && request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) - { - return _sslOptionsHttp2Only!; - } - - if (request.Version.Major >= 2 || request.VersionPolicy == HttpVersionPolicy.RequestVersionOrHigher) - { - return _sslOptionsHttp2!; - } - } - return _sslOptionsHttp11!; - } - - private async ValueTask ApplyPlaintextFilterAsync(bool async, Stream stream, Version httpVersion, HttpRequestMessage request, CancellationToken cancellationToken) - { - if (Settings._plaintextStreamFilter is null) - { - return stream; - } - - Stream newStream; - try - { - ValueTask streamTask = Settings._plaintextStreamFilter(new SocketsHttpPlaintextStreamFilterContext(stream, httpVersion, request), cancellationToken); - - if (!async && !streamTask.IsCompleted) - { - // User-provided PlaintextStreamFilter is completing asynchronously but the user is making a synchronous request; if the user cares, they should - // set it up so that synchronous requests are made on a handler with a synchronously-completing PlaintextStreamFilter supplied. If in the future, - // we could add a Boolean to SocketsHttpPlaintextStreamFilterContext (https://github.com/dotnet/runtime/issues/44876) to let the callback know whether - // this request is sync or async. - Trace($"{nameof(SocketsHttpHandler.PlaintextStreamFilter)} completing asynchronously for a synchronous request."); - } - - newStream = await streamTask.ConfigureAwait(false); - } - catch (OperationCanceledException oce) when (oce.CancellationToken == cancellationToken) - { - stream.Dispose(); - throw; - } - catch (Exception e) - { - stream.Dispose(); - throw new HttpRequestException(SR.net_http_exception_during_plaintext_filter, e); - } - - if (newStream == null) - { - stream.Dispose(); - throw new HttpRequestException(SR.net_http_null_from_plaintext_filter); - } - - return newStream; - } - - private async ValueTask ConstructHttp11ConnectionAsync(bool async, Stream stream, TransportContext? transportContext, HttpRequestMessage request, IPEndPoint? remoteEndPoint, CancellationToken cancellationToken) - { - Stream newStream = await ApplyPlaintextFilterAsync(async, stream, HttpVersion.Version11, request, cancellationToken).ConfigureAwait(false); - return new HttpConnection(this, newStream, transportContext, remoteEndPoint); - } - - private async ValueTask ConstructHttp2ConnectionAsync(Stream stream, HttpRequestMessage request, IPEndPoint? remoteEndPoint, CancellationToken cancellationToken) - { - stream = await ApplyPlaintextFilterAsync(async: true, stream, HttpVersion.Version20, request, cancellationToken).ConfigureAwait(false); - - Http2Connection http2Connection = new Http2Connection(this, stream, remoteEndPoint); - try - { - await http2Connection.SetupAsync(cancellationToken).ConfigureAwait(false); - } - catch (Exception e) - { - // Note, SetupAsync will dispose the connection if there is an exception. - if (e is OperationCanceledException oce && oce.CancellationToken == cancellationToken) - { - // Note, AddHttp2ConnectionAsync handles this OCE separately so don't wrap it. - throw; - } - - throw new HttpRequestException(SR.net_http_client_execution_error, e); - } - - return http2Connection; - } - - private async ValueTask EstablishProxyTunnelAsync(bool async, CancellationToken cancellationToken) - { - // Send a CONNECT request to the proxy server to establish a tunnel. - HttpRequestMessage tunnelRequest = new HttpRequestMessage(HttpMethod.Connect, _proxyUri); - tunnelRequest.Headers.Host = $"{_originAuthority.IdnHost}:{_originAuthority.Port}"; // This specifies destination host/port to connect to - - if (_connectTunnelUserAgent is not null) - { - tunnelRequest.Headers.TryAddWithoutValidation(KnownHeaders.UserAgent.Descriptor, _connectTunnelUserAgent); - } - - HttpResponseMessage tunnelResponse = await _poolManager.SendProxyConnectAsync(tunnelRequest, _proxyUri!, async, cancellationToken).ConfigureAwait(false); - - if (tunnelResponse.StatusCode != HttpStatusCode.OK) - { - tunnelResponse.Dispose(); - throw new HttpRequestException(HttpRequestError.ProxyTunnelError, SR.Format(SR.net_http_proxy_tunnel_returned_failure_status_code, _proxyUri, (int)tunnelResponse.StatusCode)); - } - - try - { - return tunnelResponse.Content.ReadAsStream(cancellationToken); - } - catch - { - tunnelResponse.Dispose(); - throw; - } - } - - private async ValueTask EstablishSocksTunnel(HttpRequestMessage request, bool async, CancellationToken cancellationToken) - { - Debug.Assert(_proxyUri != null); - - Stream stream = await ConnectToTcpHostAsync(_proxyUri.IdnHost, _proxyUri.Port, request, async, cancellationToken).ConfigureAwait(false); - - try - { - await SocksHelper.EstablishSocksTunnelAsync(stream, _originAuthority.IdnHost, _originAuthority.Port, _proxyUri, ProxyCredentials, async, cancellationToken).ConfigureAwait(false); - } - catch (Exception e) when (!(e is OperationCanceledException)) - { - Debug.Assert(!(e is HttpRequestException)); - throw new HttpRequestException(HttpRequestError.ProxyTunnelError, SR.net_http_proxy_tunnel_error, e); - } - - return stream; - } - - private void HandleHttp11ConnectionFailure(HttpConnectionWaiter? requestWaiter, Exception e) - { - if (NetEventSource.Log.IsEnabled()) Trace($"HTTP/1.1 connection failed: {e}"); - - // If this is happening as part of an HTTP/2 => HTTP/1.1 downgrade, we won't have an HTTP/1.1 waiter associated with this request - // We don't care if this fails; that means the request was previously canceled or handled by a different connection. - requestWaiter?.TrySetException(e); - - lock (SyncObj) - { - Debug.Assert(_associatedHttp11ConnectionCount > 0); - Debug.Assert(_pendingHttp11ConnectionCount > 0); - - _associatedHttp11ConnectionCount--; - _pendingHttp11ConnectionCount--; - - CheckForHttp11ConnectionInjection(); - } - } - - private void HandleHttp2ConnectionFailure(HttpConnectionWaiter requestWaiter, Exception e) - { - if (NetEventSource.Log.IsEnabled()) Trace($"HTTP2 connection failed: {e}"); - - // We don't care if this fails; that means the request was previously canceled or handled by a different connection. - requestWaiter.TrySetException(e); - - lock (SyncObj) - { - Debug.Assert(_associatedHttp2ConnectionCount > 0); - Debug.Assert(_pendingHttp2Connection); - - _associatedHttp2ConnectionCount--; - _pendingHttp2Connection = false; - - CheckForHttp2ConnectionInjection(); - } - } - - /// - /// Called when an HttpConnection from this pool is no longer usable. - /// Note, this is always called from HttpConnection.Dispose, which is a bit different than how HTTP2 works. - /// - public void InvalidateHttp11Connection(HttpConnection connection, bool disposing = true) - { - lock (SyncObj) - { - Debug.Assert(_associatedHttp11ConnectionCount > 0); - Debug.Assert(!disposing || Array.IndexOf(_http11Connections.ToArray(), connection) < 0); - - _associatedHttp11ConnectionCount--; - - CheckForHttp11ConnectionInjection(); - } - } - - /// - /// Called when an Http2Connection from this pool is no longer usable. - /// - public void InvalidateHttp2Connection(Http2Connection connection) - { - if (NetEventSource.Log.IsEnabled()) connection.Trace(""); - - bool found = false; - lock (SyncObj) - { - if (_availableHttp2Connections is not null) - { - Debug.Assert(_associatedHttp2ConnectionCount >= _availableHttp2Connections.Count); - - int index = _availableHttp2Connections.IndexOf(connection); - if (index != -1) - { - found = true; - _availableHttp2Connections.RemoveAt(index); - _associatedHttp2ConnectionCount--; - } - } - - CheckForHttp2ConnectionInjection(); - } - - // If we found the connection in the available list, then dispose it now. - // Otherwise, when we try to put it back in the pool, we will see it is shut down and dispose it (and adjust connection counts). - if (found) - { - connection.Dispose(); - } - } - - private bool CheckExpirationOnReturn(HttpConnectionBase connection) - { - TimeSpan lifetime = _poolManager.Settings._pooledConnectionLifetime; - if (lifetime != Timeout.InfiniteTimeSpan) - { - return lifetime == TimeSpan.Zero || connection.GetLifetimeTicks(Environment.TickCount64) > lifetime.TotalMilliseconds; - } - - return false; - } - - public void RecycleHttp11Connection(HttpConnection connection) - { - if (CheckExpirationOnReturn(connection)) - { - if (NetEventSource.Log.IsEnabled()) connection.Trace("Disposing HTTP/1.1 connection when returning to pool. Connection lifetime expired."); - connection.Dispose(); - return; - } - - ReturnHttp11Connection(connection); - } - - private void AddNewHttp11Connection(HttpConnection connection, HttpConnectionWaiter? initialRequestWaiter) - { - if (NetEventSource.Log.IsEnabled()) Trace(""); - - lock (SyncObj) - { - Debug.Assert(_pendingHttp11ConnectionCount > 0); - _pendingHttp11ConnectionCount--; - - if (initialRequestWaiter is not null) - { - // If we're about to signal the initial waiter, that request must be removed from the queue if it was at the head to avoid rooting it forever. - // Normally, TryDequeueWaiter would handle the removal. TryDequeueSpecificWaiter matches this behavior for the initial request case. - // We don't care if this fails; that means the request was previously canceled, handled by a different connection, or not at the head of the queue. - _http11RequestQueue.TryDequeueSpecificWaiter(initialRequestWaiter); - - // There's no need for us to hold the lock while signaling the waiter. - } - } - - if (initialRequestWaiter is not null && - TrySignalWaiter(initialRequestWaiter, connection)) - { - return; - } - - ReturnHttp11Connection(connection); - } - - private void ReturnHttp11Connection(HttpConnection connection) - { - connection.MarkConnectionAsIdle(); - - // The fast path when there are enough connections and no pending requests - // is that we'll see _http11RequestQueueIsEmptyAndNotDisposed being true both - // times, and all we'll have to do as part of returning the connection is - // a Push call on the concurrent stack. - - if (Volatile.Read(ref _http11RequestQueueIsEmptyAndNotDisposed)) - { - _http11Connections.Push(connection); - - // When we add a connection to the pool, we must ensure that there are - // either no pending requests waiting, or that _something_ will pair those - // requests with the connection we just added. - - // When adding a request to the queue, we'll first check if there's - // an available connection waiting in the pool that we could use. - // If there isn't, we'll set the _http11RequestQueueIsEmptyAndNotDisposed - // flag and check for available connections again. - - // To avoid a race where we add the connection after a request was enqueued, - // we'll check the flag again and try to process one request from the queue. - - if (!Volatile.Read(ref _http11RequestQueueIsEmptyAndNotDisposed)) - { - ProcessHttp11RequestQueue(null); - } - } - else - { - // ProcessHttp11RequestQueue is responsible for handing the connection to a pending request, - // or to return it back to the pool if there aren't any. - - // We hand over the connection directly instead of pushing it on the stack first to ensure - // that pending requests are processed in a fair (FIFO) order. - ProcessHttp11RequestQueue(connection); - } - } - - private bool TrySignalWaiter(HttpConnectionWaiter waiter, T connection) - where T : HttpConnectionBase? - { - Debug.Assert(connection is not null); - - if (waiter.TrySetResult(connection)) - { - if (NetEventSource.Log.IsEnabled()) connection.Trace("Dequeued waiting request."); - return true; - } - else - { - if (NetEventSource.Log.IsEnabled()) - { - Trace(waiter.Task.IsCanceled - ? "Discarding canceled request from queue." - : "Discarding signaled request waiter from queue."); - } - return false; - } - } - - private void ReturnHttp2Connection(Http2Connection connection, bool isNewConnection, HttpConnectionWaiter? initialRequestWaiter = null) - { - if (NetEventSource.Log.IsEnabled()) connection.Trace($"{nameof(isNewConnection)}={isNewConnection}"); - - Debug.Assert(!HasSyncObjLock); - Debug.Assert(isNewConnection || initialRequestWaiter is null, "Shouldn't have a request unless the connection is new"); - - if (!isNewConnection && CheckExpirationOnReturn(connection)) - { - lock (SyncObj) - { - Debug.Assert(_availableHttp2Connections is null || !_availableHttp2Connections.Contains(connection)); - Debug.Assert(_associatedHttp2ConnectionCount > (_availableHttp2Connections?.Count ?? 0)); - _associatedHttp2ConnectionCount--; - } - - if (NetEventSource.Log.IsEnabled()) connection.Trace("Disposing HTTP2 connection return to pool. Connection lifetime expired."); - connection.Dispose(); - return; - } - - while (connection.TryReserveStream()) - { - // Loop in case we get a request that has already been canceled or handled by a different connection. - while (true) - { - HttpConnectionWaiter? waiter = null; - bool added = false; - lock (SyncObj) - { - Debug.Assert(_availableHttp2Connections is null || !_availableHttp2Connections.Contains(connection), $"HTTP2 connection already in available list"); - Debug.Assert(_associatedHttp2ConnectionCount > (_availableHttp2Connections?.Count ?? 0), - $"Expected _associatedHttp2ConnectionCount={_associatedHttp2ConnectionCount} > _availableHttp2Connections.Count={(_availableHttp2Connections?.Count ?? 0)}"); - - if (isNewConnection) - { - Debug.Assert(_pendingHttp2Connection); - _pendingHttp2Connection = false; - isNewConnection = false; - } - - if (initialRequestWaiter is not null) - { - // Try to handle the request that we initiated the connection for first - waiter = initialRequestWaiter; - initialRequestWaiter = null; - - // If this method found a request to service, that request must be removed from the queue if it was at the head to avoid rooting it forever. - // Normally, TryDequeueWaiter would handle the removal. TryDequeueSpecificWaiter matches this behavior for the initial request case. - // We don't care if this fails; that means the request was previously canceled, handled by a different connection, or not at the head of the queue. - _http2RequestQueue.TryDequeueSpecificWaiter(waiter); - } - else if (_http2RequestQueue.TryDequeueWaiter(this, out waiter)) - { - Debug.Assert((_availableHttp2Connections?.Count ?? 0) == 0, $"With {(_availableHttp2Connections?.Count ?? 0)} available HTTP2 connections, we shouldn't have a waiter."); - } - else if (_disposed) - { - // The pool has been disposed. We will dispose this connection below outside the lock. - // We do this check after processing the request queue so that any queued requests will be handled by existing connections if possible. - _associatedHttp2ConnectionCount--; - } - else - { - // Add connection to the pool. - added = true; - _availableHttp2Connections ??= new List(); - _availableHttp2Connections.Add(connection); - } - } - - if (waiter is not null) - { - Debug.Assert(!added); - - if (TrySignalWaiter(waiter, connection)) - { - break; - } - - // Loop and process the queue again - } - else - { - connection.ReleaseStream(); - if (added) - { - if (NetEventSource.Log.IsEnabled()) connection.Trace("Put HTTP2 connection in pool."); - return; - } - else - { - Debug.Assert(_disposed); - if (NetEventSource.Log.IsEnabled()) connection.Trace("Disposing HTTP2 connection returned to pool. Pool was disposed."); - connection.Dispose(); - return; - } - } - } - } - - if (isNewConnection) - { - Debug.Assert(initialRequestWaiter is not null, "Expect request for a new connection"); - - // The new connection could not handle even one request, either because it shut down before we could use it for any requests, - // or because it immediately set the max concurrent streams limit to 0. - // We don't want to get stuck in a loop where we keep trying to create new connections for the same request. - // So, treat this as a connection failure. - - if (NetEventSource.Log.IsEnabled()) connection.Trace("New HTTP2 connection is unusable due to no available streams."); - connection.Dispose(); - - HttpRequestException hre = new HttpRequestException(SR.net_http_http2_connection_not_established); - ExceptionDispatchInfo.SetCurrentStackTrace(hre); - HandleHttp2ConnectionFailure(initialRequestWaiter, hre); - } - else - { - // Since we only inject one connection at a time, we may want to inject another now. - lock (SyncObj) - { - CheckForHttp2ConnectionInjection(); - } - - // We need to wait until the connection is usable again. - DisableHttp2Connection(connection); - } - } - - /// - /// Disable usage of the specified connection because it cannot handle any more streams at the moment. - /// We will register to be notified when it can handle more streams (or becomes permanently unusable). - /// - private void DisableHttp2Connection(Http2Connection connection) - { - if (NetEventSource.Log.IsEnabled()) connection.Trace(""); - - _ = DisableHttp2ConnectionAsync(connection); // ignore returned task - - async Task DisableHttp2ConnectionAsync(Http2Connection connection) - { - bool usable = await connection.WaitForAvailableStreamsAsync().ConfigureAwait(ConfigureAwaitOptions.ForceYielding); - - if (NetEventSource.Log.IsEnabled()) connection.Trace($"{nameof(connection.WaitForAvailableStreamsAsync)} completed, {nameof(usable)}={usable}"); - - if (usable) - { - ReturnHttp2Connection(connection, isNewConnection: false); - } - else - { - // Connection has shut down. - lock (SyncObj) - { - Debug.Assert(_availableHttp2Connections is null || !_availableHttp2Connections.Contains(connection)); - Debug.Assert(_associatedHttp2ConnectionCount > 0); - - _associatedHttp2ConnectionCount--; - - CheckForHttp2ConnectionInjection(); - } - - if (NetEventSource.Log.IsEnabled()) connection.Trace("HTTP2 connection no longer usable"); - connection.Dispose(); - } - }; - } - - public void InvalidateHttp3Connection(Http3Connection connection) - { - lock (SyncObj) - { - if (_http3Connection == connection) - { - _http3Connection = null; - } - } - } - - /// - /// Disposes the connection pool. This is only needed when the pool currently contains - /// or has associated connections. - /// - public void Dispose() - { - List? toDispose = null; - - lock (SyncObj) - { - if (_disposed) - { - return; - } - - _disposed = true; - _http11RequestQueueIsEmptyAndNotDisposed = false; - - if (NetEventSource.Log.IsEnabled()) Trace("Disposing the pool."); - - if (_availableHttp2Connections is not null) - { - toDispose = [.. _availableHttp2Connections]; - _associatedHttp2ConnectionCount -= _availableHttp2Connections.Count; - _availableHttp2Connections.Clear(); - } - - if (_http3Connection is not null) - { - toDispose ??= new(); - toDispose.Add(_http3Connection); - _http3Connection = null; - } - - if (_authorityExpireTimer != null) - { - _authorityExpireTimer.Dispose(); - _authorityExpireTimer = null; - } - - if (_altSvcBlocklistTimerCancellation != null) - { - _altSvcBlocklistTimerCancellation.Cancel(); - _altSvcBlocklistTimerCancellation.Dispose(); - _altSvcBlocklistTimerCancellation = null; - } - - Debug.Assert((_availableHttp2Connections?.Count ?? 0) == 0, $"Expected {nameof(_availableHttp2Connections)}.{nameof(_availableHttp2Connections.Count)} == 0"); - } - - // Dispose connections outside the lock to avoid lock re-entrancy issues. - - // This will trigger the disposal of Http11 connections. - // Note: Http11 connections will decrement the _associatedHttp11ConnectionCount when disposed. - // Http2 connections will not, hence the difference in handing _associatedHttp2ConnectionCount. - ProcessHttp11RequestQueue(null); - - toDispose?.ForEach(c => c.Dispose()); - } - - /// - /// Removes any unusable connections from the pool, and if the pool - /// is then empty and stale, disposes of it. - /// - /// - /// true if the pool disposes of itself; otherwise, false. - /// - public bool CleanCacheAndDisposeIfUnused() - { - TimeSpan pooledConnectionLifetime = _poolManager.Settings._pooledConnectionLifetime; - TimeSpan pooledConnectionIdleTimeout = _poolManager.Settings._pooledConnectionIdleTimeout; - long nowTicks = Environment.TickCount64; - - List? toDispose = null; - - lock (SyncObj) - { - // If there are now no connections associated with this pool, we can dispose of it. We - // avoid aggressively cleaning up pools that have recently been used but currently aren't; - // if a pool was used since the last time we cleaned up, give it another chance. New pools - // start out saying they've recently been used, to give them a bit of breathing room and time - // for the initial collection to be added to it. - if (!_usedSinceLastCleanup && _associatedHttp11ConnectionCount == 0 && _associatedHttp2ConnectionCount == 0) - { - _disposed = true; - return true; // Pool is disposed of. It should be removed. - } - - // Reset the cleanup flag. Any pools that are empty and not used since the last cleanup - // will be purged next time around. - _usedSinceLastCleanup = false; - - ScavengeConnectionStack(this, _http11Connections, ref toDispose, nowTicks, pooledConnectionLifetime, pooledConnectionIdleTimeout); - - if (_availableHttp2Connections is not null) - { - int removed = ScavengeConnectionList(_availableHttp2Connections, ref toDispose, nowTicks, pooledConnectionLifetime, pooledConnectionIdleTimeout); - _associatedHttp2ConnectionCount -= removed; - - // Note: Http11 connections will decrement the _associatedHttp11ConnectionCount when disposed. - // Http2 connections will not, hence the difference in handing _associatedHttp2ConnectionCount. - } - } - - // Dispose the stale connections outside the pool lock, to avoid holding the lock too long. - // Dispose them asynchronously to not to block the caller on closing the SslStream or NetworkStream. - if (toDispose is not null) - { - Task.Factory.StartNew(static s => ((List)s!).ForEach(c => c.Dispose()), toDispose, - CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); - } - - // Pool is active. Should not be removed. - return false; - - static void ScavengeConnectionStack(HttpConnectionPool pool, ConcurrentStack connections, ref List? toDispose, long nowTicks, TimeSpan pooledConnectionLifetime, TimeSpan pooledConnectionIdleTimeout) - { - // We can't simply enumerate the connections stack as other threads may still be adding and removing entries. - // If we want to check the state of a connection, we must take it from the stack first to ensure we own it. - - // We're about to starve the connection pool of all available connections for a moment. - // We must be holding the lock while doing so to ensure that any new requests that - // come in during this time will be blocked waiting in ProcessHttp11RequestQueue. - // If this were not the case, requests would repeatedly call into CheckForHttp11ConnectionInjection - // and trigger new connection attempts, even if we have enough connections in our copy. - Debug.Assert(pool.HasSyncObjLock); - Debug.Assert(connections.Count <= pool._associatedHttp11ConnectionCount); - - HttpConnection[] stackCopy = ArrayPool.Shared.Rent(pool._associatedHttp11ConnectionCount); - int usableConnections = 0; - - while (connections.TryPop(out HttpConnection? connection)) - { - if (IsUsableConnection(connection, nowTicks, pooledConnectionLifetime, pooledConnectionIdleTimeout)) - { - stackCopy[usableConnections++] = connection; - } - else - { - toDispose ??= new List(); - toDispose.Add(connection); - } - } - - if (usableConnections > 0) - { - // Add them back in reverse to maintain the LIFO order. - Span usable = stackCopy.AsSpan(0, usableConnections); - usable.Reverse(); - connections.PushRange(stackCopy, 0, usableConnections); - usable.Clear(); - } - - ArrayPool.Shared.Return(stackCopy); - } - - static int ScavengeConnectionList(List list, ref List? toDispose, long nowTicks, TimeSpan pooledConnectionLifetime, TimeSpan pooledConnectionIdleTimeout) - where T : HttpConnectionBase - { - int freeIndex = 0; - while (freeIndex < list.Count && IsUsableConnection(list[freeIndex], nowTicks, pooledConnectionLifetime, pooledConnectionIdleTimeout)) - { - freeIndex++; - } - - // If freeIndex == list.Count, nothing needs to be removed. - // But if it's < list.Count, at least one connection needs to be purged. - int removed = 0; - if (freeIndex < list.Count) - { - // We know the connection at freeIndex is unusable, so dispose of it. - toDispose ??= new List(); - toDispose.Add(list[freeIndex]); - - // Find the first item after the one to be removed that should be kept. - int current = freeIndex + 1; - while (current < list.Count) - { - // Look for the first item to be kept. Along the way, any - // that shouldn't be kept are disposed of. - while (current < list.Count && !IsUsableConnection(list[current], nowTicks, pooledConnectionLifetime, pooledConnectionIdleTimeout)) - { - toDispose.Add(list[current]); - current++; - } - - // If we found something to keep, copy it down to the known free slot. - if (current < list.Count) - { - // copy item to the free slot - list[freeIndex++] = list[current++]; - } - - // Keep going until there are no more good items. - } - - // At this point, good connections have been moved below freeIndex, and garbage connections have - // been added to the dispose list, so clear the end of the list past freeIndex. - removed = list.Count - freeIndex; - list.RemoveRange(freeIndex, removed); - } - - return removed; - } - - static bool IsUsableConnection(HttpConnectionBase connection, long nowTicks, TimeSpan pooledConnectionLifetime, TimeSpan pooledConnectionIdleTimeout) - { - // Validate that the connection hasn't been idle in the pool for longer than is allowed. - if (pooledConnectionIdleTimeout != Timeout.InfiniteTimeSpan) - { - long idleTicks = connection.GetIdleTicks(nowTicks); - if (idleTicks > pooledConnectionIdleTimeout.TotalMilliseconds) - { - if (NetEventSource.Log.IsEnabled()) connection.Trace($"Scavenging connection. Idle {TimeSpan.FromMilliseconds(idleTicks)} > {pooledConnectionIdleTimeout}."); - return false; - } - } - - // Validate that the connection lifetime has not been exceeded. - if (pooledConnectionLifetime != Timeout.InfiniteTimeSpan) - { - long lifetimeTicks = connection.GetLifetimeTicks(nowTicks); - if (lifetimeTicks > pooledConnectionLifetime.TotalMilliseconds) - { - if (NetEventSource.Log.IsEnabled()) connection.Trace($"Scavenging connection. Lifetime {TimeSpan.FromMilliseconds(lifetimeTicks)} > {pooledConnectionLifetime}."); - return false; - } - } - - if (!connection.CheckUsabilityOnScavenge()) - { - if (NetEventSource.Log.IsEnabled()) connection.Trace($"Scavenging connection. Keep-Alive timeout exceeded, unexpected data or EOF received."); - return false; - } - - return true; - } - } - - /// Gets whether we're running on Windows 7 or Windows 2008 R2. - private static bool GetIsWindows7Or2008R2() - { - OperatingSystem os = Environment.OSVersion; - if (os.Platform == PlatformID.Win32NT) - { - // Both Windows 7 and Windows 2008 R2 report version 6.1. - Version v = os.Version; - return v.Major == 6 && v.Minor == 1; - } - return false; - } - - internal void HeartBeat() - { - Http2Connection[]? localHttp2Connections; - lock (SyncObj) - { - localHttp2Connections = _availableHttp2Connections?.ToArray(); - } - - // Avoid calling HeartBeat under the lock, as it may call back into HttpConnectionPool.InvalidateHttp2Connection. - if (localHttp2Connections is not null) - { - foreach (Http2Connection http2Connection in localHttp2Connections) - { - http2Connection.HeartBeat(); - } - } - } - - // For diagnostic purposes - public override string ToString() => - $"{nameof(HttpConnectionPool)} " + - (_proxyUri == null ? - (_sslOptionsHttp11 == null ? - $"http://{_originAuthority}" : - $"https://{_originAuthority}" + (_sslOptionsHttp11.TargetHost != _originAuthority.IdnHost ? $", SSL TargetHost={_sslOptionsHttp11.TargetHost}" : null)) : - (_sslOptionsHttp11 == null ? - $"Proxy {_proxyUri}" : - $"https://{_originAuthority}/ tunnelled via Proxy {_proxyUri}" + (_sslOptionsHttp11.TargetHost != _originAuthority.IdnHost ? $", SSL TargetHost={_sslOptionsHttp11.TargetHost}" : null))); - - private void Trace(string? message, [CallerMemberName] string? memberName = null) => - NetEventSource.Log.HandlerMessage( - GetHashCode(), // pool ID - 0, // connection ID - 0, // request ID - memberName, // method name - message); // message - - private struct RequestQueue - where T : HttpConnectionBase? - { - public struct QueueItem - { - public HttpRequestMessage Request; - public HttpConnectionWaiter Waiter; - } - - // This implementation mimics that of Queue, but without version checks and with an extra head pointer - // https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs - private QueueItem[] _array; - private int _head; // The index from which to dequeue if the queue isn't empty. - private int _tail; // The index at which to enqueue if the queue isn't full. - private int _size; // Number of elements. - private int _attemptedConnectionsOffset; // The offset from head where we should next peek for a request without a connection attempt - - public RequestQueue() - { - _array = Array.Empty(); - _head = 0; - _tail = 0; - _size = 0; - _attemptedConnectionsOffset = 0; - } - - private void Enqueue(QueueItem queueItem) - { - if (_size == _array.Length) - { - Grow(); - } - - _array[_tail] = queueItem; - MoveNext(ref _tail); - - _size++; - } - - private QueueItem Dequeue() - { - Debug.Assert(_size > 0); - - int head = _head; - QueueItem[] array = _array; - - QueueItem queueItem = array[head]; - array[head] = default; - - MoveNext(ref _head); - - if (_attemptedConnectionsOffset > 0) - { - _attemptedConnectionsOffset--; - } - - _size--; - return queueItem; - } - - private bool TryPeek(out QueueItem queueItem) - { - if (_size == 0) - { - queueItem = default!; - return false; - } - - queueItem = _array[_head]; - return true; - } - - private void MoveNext(ref int index) - { - int tmp = index + 1; - if (tmp == _array.Length) - { - tmp = 0; - } - index = tmp; - } - - private void Grow() - { - var newArray = new QueueItem[Math.Max(4, _array.Length * 2)]; - - if (_size != 0) - { - if (_head < _tail) - { - Array.Copy(_array, _head, newArray, 0, _size); - } - else - { - Array.Copy(_array, _head, newArray, 0, _array.Length - _head); - Array.Copy(_array, 0, newArray, _array.Length - _head, _tail); - } - } - - _array = newArray; - _head = 0; - _tail = _size; - } - - - public HttpConnectionWaiter EnqueueRequest(HttpRequestMessage request) - { - var waiter = new HttpConnectionWaiter(); - EnqueueRequest(request, waiter); - return waiter; - } - - - public void EnqueueRequest(HttpRequestMessage request, HttpConnectionWaiter waiter) - { - Enqueue(new QueueItem { Request = request, Waiter = waiter }); - } - - public void PruneCompletedRequestsFromHeadOfQueue(HttpConnectionPool pool) - { - while (TryPeek(out QueueItem queueItem) && queueItem.Waiter.Task.IsCompleted) - { - if (NetEventSource.Log.IsEnabled()) - { - pool.Trace(queueItem.Waiter.Task.IsCanceled - ? "Discarding canceled request from queue." - : "Discarding signaled request waiter from queue."); - } - - Dequeue(); - } - } - - public bool TryDequeueWaiter(HttpConnectionPool pool, [MaybeNullWhen(false)] out HttpConnectionWaiter waiter) - { - PruneCompletedRequestsFromHeadOfQueue(pool); - - if (Count != 0) - { - waiter = Dequeue().Waiter; - return true; - } - - waiter = null; - return false; - } - - public void TryDequeueSpecificWaiter(HttpConnectionWaiter waiter) - { - if (TryPeek(out QueueItem queueItem) && queueItem.Waiter == waiter) - { - Dequeue(); - } - } - - public QueueItem PeekNextRequestForConnectionAttempt() - { - Debug.Assert(_attemptedConnectionsOffset >= 0); - Debug.Assert(_attemptedConnectionsOffset < _size, $"{_attemptedConnectionsOffset} < {_size}"); - - int index = _head + _attemptedConnectionsOffset; - _attemptedConnectionsOffset++; - - if (index >= _array.Length) - { - index -= _array.Length; - } - - return _array[index]; - } - - public int Count => _size; - - public int RequestsWithoutAConnectionAttempt => _size - _attemptedConnectionsOffset; - } - - private sealed class HttpConnectionWaiter : TaskCompletionSourceWithCancellation - where T : HttpConnectionBase? - { - // When a connection attempt is pending, reference the connection's CTS, so we can tear it down if the initiating request is cancelled - // or completes on a different connection. - public CancellationTokenSource? ConnectionCancellationTokenSource; - - // Distinguish connection cancellation that happens because the initiating request is cancelled or completed on a different connection. - public bool CancelledByOriginatingRequestCompletion { get; set; } - - public ValueTask WaitForConnectionAsync(HttpRequestMessage request, HttpConnectionPool pool, bool async, CancellationToken requestCancellationToken) - { - return HttpTelemetry.Log.IsEnabled() || pool.Settings._metrics!.RequestsQueueDuration.Enabled - ? WaitForConnectionWithTelemetryAsync(request, pool, async, requestCancellationToken) - : WaitWithCancellationAsync(async, requestCancellationToken); - } - - private async ValueTask WaitForConnectionWithTelemetryAsync(HttpRequestMessage request, HttpConnectionPool pool, bool async, CancellationToken requestCancellationToken) - { - Debug.Assert(typeof(T) == typeof(HttpConnection) || typeof(T) == typeof(Http2Connection)); - - long startingTimestamp = Stopwatch.GetTimestamp(); - try - { - return await WaitWithCancellationAsync(async, requestCancellationToken).ConfigureAwait(false); - } - finally - { - TimeSpan duration = Stopwatch.GetElapsedTime(startingTimestamp); - int versionMajor = typeof(T) == typeof(HttpConnection) ? 1 : 2; - - pool.Settings._metrics!.RequestLeftQueue(request, pool, duration, versionMajor); - - if (HttpTelemetry.Log.IsEnabled()) - { - HttpTelemetry.Log.RequestLeftQueue(versionMajor, duration); - } - } - } - } - } -} diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs index a76440e5fb16..5cd1ee218c32 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs @@ -8,6 +8,7 @@ using System.Net.Http.Metrics; using System.Net.Security; using System.Runtime.Versioning; +using System.Security.Principal; using System.Threading; using System.Threading.Tasks; @@ -29,6 +30,7 @@ internal sealed class HttpConnectionSettings internal bool _preAuthenticate = HttpHandlerDefaults.DefaultPreAuthenticate; internal ICredentials? _credentials; + internal TokenImpersonationLevel _impersonationLevel = HttpHandlerDefaults.DefaultImpersonationLevel; // this is here to support impersonation on HttpWebRequest internal bool _allowAutoRedirect = HttpHandlerDefaults.DefaultAutomaticRedirection; internal int _maxAutomaticRedirections = HttpHandlerDefaults.DefaultMaxAutomaticRedirections; @@ -128,6 +130,7 @@ public HttpConnectionSettings CloneAndNormalize() _defaultCredentialsUsedForProxy = _proxy != null && (_proxy.Credentials == CredentialCache.DefaultCredentials || _defaultProxyCredentials == CredentialCache.DefaultCredentials), _defaultCredentialsUsedForServer = _credentials == CredentialCache.DefaultCredentials, _clientCertificateOptions = _clientCertificateOptions, + _impersonationLevel = _impersonationLevel, }; return settings; diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/PreAuthCredentialCache.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/PreAuthCredentialCache.cs new file mode 100644 index 000000000000..1f4dcc54fb0c --- /dev/null +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/PreAuthCredentialCache.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; + +namespace System.Net.Http +{ + internal sealed class PreAuthCredentialCache + { + private Dictionary? _cache; + + public void Add(Uri uriPrefix, string authType, NetworkCredential cred) + { + Debug.Assert(uriPrefix != null); + Debug.Assert(authType != null); + + var key = new CredentialCacheKey(uriPrefix, authType); + + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Adding key:[{key}], cred:[{cred.Domain}],[{cred.UserName}]"); + + _cache ??= new Dictionary(); + _cache.Add(key, cred); + } + + public void Remove(Uri uriPrefix, string authType) + { + Debug.Assert(uriPrefix != null); + Debug.Assert(authType != null); + + if (_cache == null) + { + return; + } + + var key = new CredentialCacheKey(uriPrefix, authType); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Removing key:[{key}]"); + _cache.Remove(key); + } + + public (Uri uriPrefix, NetworkCredential credential)? GetCredential(Uri uriPrefix, string authType) + { + Debug.Assert(uriPrefix != null); + Debug.Assert(authType != null); + + if (_cache == null) + { + return null; + } + + CredentialCacheHelper.TryGetCredential(_cache, uriPrefix, authType, out Uri? mostSpecificMatchUri, out NetworkCredential? mostSpecificMatch); + + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Returning {(mostSpecificMatch == null ? "null" : "(" + mostSpecificMatch.UserName + ":" + mostSpecificMatch.Domain + ")")}"); + + return mostSpecificMatch == null ? null : (mostSpecificMatchUri!, mostSpecificMatch!); + } + } +} diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AltSvc.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AltSvc.cs index f71efde66310..d6a53a33e234 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AltSvc.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AltSvc.cs @@ -8,6 +8,8 @@ using System.Net.Test.Common; using System.Net.Quic; +using Microsoft.DotNet.XUnitExtensions; + namespace System.Net.Http.Functional.Tests { public abstract class HttpClientHandler_AltSvc_Test : HttpClientHandlerTestBase @@ -27,10 +29,15 @@ private HttpClient CreateHttpClient(Version version) return client; } - [Theory] + [ConditionalTheory] [MemberData(nameof(AltSvcHeaderUpgradeVersions))] public async Task AltSvc_Header_Upgrade_Success(Version fromVersion, bool overrideHost) { + if (UseVersion == HttpVersion30 && fromVersion == HttpVersion.Version11 && overrideHost) + { + throw new SkipTestException("https://github.com/dotnet/runtime/issues/91757"); + } + // The test makes a request to a HTTP/1 or HTTP/2 server first, which supplies an Alt-Svc header pointing to the second server. using GenericLoopbackServer firstServer = fromVersion.Major switch @@ -71,9 +78,14 @@ public async Task AltSvc_Header_Upgrade_Success(Version fromVersion, bool overri { HttpVersion.Version20, false } }; - [Fact] + [ConditionalFact] public async Task AltSvc_ConnectionFrame_UpgradeFrom20_Success() { + if (UseVersion == HttpVersion30) + { + throw new SkipTestException("https://github.com/dotnet/runtime/issues/101376"); + } + using Http2LoopbackServer firstServer = Http2LoopbackServer.CreateServer(); using Http3LoopbackServer secondServer = CreateHttp3LoopbackServer(); using HttpClient client = CreateHttpClient(HttpVersion.Version20); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.BasicAuth.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.BasicAuth.cs new file mode 100644 index 000000000000..a6ac590fb6ad --- /dev/null +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.BasicAuth.cs @@ -0,0 +1,114 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq; +using System.Net.Test.Common; +using System.Text; +using System.Threading.Tasks; + +using Microsoft.DotNet.XUnitExtensions; +using Xunit; +using Xunit.Abstractions; + +namespace System.Net.Http.Functional.Tests +{ + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public class HttpClientHandlerTest_BasicAuth : HttpClientHandlerTestBase + { + public HttpClientHandlerTest_BasicAuth(ITestOutputHelper output) : base(output) + { + } + + protected override Version UseVersion => HttpVersion.Version20; + + [Fact] + public async Task RefreshesPreAuthCredentialsOnChange() + { + CredentialPlugin credentialPlugin = new CredentialPlugin(); + + using Http2LoopbackServer server = Http2LoopbackServer.CreateServer(); + server.AllowMultipleConnections = true; + + HttpClientHandler handler = CreateHttpClientHandler(); + handler.PreAuthenticate = true; + handler.Credentials = credentialPlugin; + using HttpClient client = CreateHttpClient(handler); + + Task sendTask = client.GetAsync(server.Address); + + async Task GetAuth(GenericLoopbackConnection connection) + { + HttpRequestData data = await connection.ReadRequestDataAsync(); + HttpHeaderData? header = data.Headers.FirstOrDefault(h => string.Equals(h.Name, "Authorization", StringComparison.OrdinalIgnoreCase)); + + if (header == null) + { + return ""; + } + + return Encoding.UTF8.GetString(Convert.FromBase64String(header.Value.Value.Replace("Basic", "", StringComparison.OrdinalIgnoreCase))); + } + + await server.HandleRequestAsync(HttpStatusCode.Unauthorized, headers: new[] { new HttpHeaderData("WWW-Authenticate", "Basic realm=\"test\"") }); + await server.AcceptConnectionAsync(async conn => + { + Assert.Equal("username:password", await GetAuth(conn)); + await conn.SendResponseAsync(HttpStatusCode.OK); + }).WaitAsync(TimeSpan.FromSeconds(30)); + + HttpResponseMessage response = await sendTask; + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + // change password and try again + credentialPlugin.ChangePassword(); + sendTask = client.GetAsync(server.Address); + + // first one reuses the cached credentials -> 401 + await server.AcceptConnectionAsync(async conn => + { + Assert.Equal("username:password", await GetAuth(conn)); + await conn.SendResponseAsync(HttpStatusCode.Unauthorized, headers: new[] { new HttpHeaderData("WWW-Authenticate", "Basic realm=\"test\"") }); + }).WaitAsync(TimeSpan.FromSeconds(30)); + + // client should try again with correct credentials + await server.AcceptConnectionAsync(async conn => + { + Assert.Equal("username:password1", await GetAuth(conn)); + await conn.SendResponseAsync(HttpStatusCode.OK); + }).WaitAsync(TimeSpan.FromSeconds(30)); + + response = await sendTask; + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + } + + internal class CredentialPlugin : ICredentials + { + public CredentialPlugin() + { + UserName = "username"; + counter = 0; + Password = "password"; + } + + private int counter; + public string UserName { get; private set; } + public string Password { get; private set; } + + public void ChangePassword() + { + counter++; + Password = "password" + counter; + } + + NetworkCredential? ICredentials.GetCredential(Uri uri, string authType) + { + if (authType == "Basic") + { + return new NetworkCredential(UserName, Password); + } + + return null; + } + } +} diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs index 663e3e3a4e14..cbd74f8188a2 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs @@ -13,6 +13,8 @@ using Xunit; using Xunit.Abstractions; +using Microsoft.DotNet.XUnitExtensions; + namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; @@ -24,6 +26,7 @@ public HttpClientHandlerTest_Headers(ITestOutputHelper output) : base(output) { private sealed class DerivedHttpHeaders : HttpHeaders { } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task SendAsync_RequestWithSimpleHeader_ResponseReferencesUnmodifiedRequestHeaders() { const string HeaderKey = "some-header-123", HeaderValue = "this is the expected header value"; @@ -71,6 +74,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task SendAsync_LargeHeaders_CorrectlyWritten() { if (UseVersion == HttpVersion.Version30) @@ -106,6 +110,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task SendAsync_DefaultHeaders_CorrectlyWritten() { const string Version = "2017-04-17"; @@ -167,6 +172,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => [InlineData("Accept-CharSet", "text/plain, text/json", false)] // invalid format for header but added with TryAddWithoutValidation [InlineData("Content-Location", "", false)] // invalid format for header but added with TryAddWithoutValidation [InlineData("Max-Forwards", "NotAnInteger", false)] // invalid format for header but added with TryAddWithoutValidation + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task SendAsync_SpecialHeaderKeyOrValue_Success(string key, string value, bool parsable) { if (PlatformDetection.IsBrowser && (key == "Content-Location" || key == "Date" || key == "Accept-CharSet")) @@ -283,12 +289,17 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => }); } - [Theory] + [ConditionalTheory] [InlineData("Thu, 01 Dec 1994 16:00:00 GMT", true)] [InlineData("-1", false)] [InlineData("0", false)] public async Task SendAsync_Expires_Success(string value, bool isValid) { + if (UseVersion == HttpVersion30) + { + throw new SkipTestException("https://github.com/dotnet/runtime/issues/91757"); + } + await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { using (HttpClient client = CreateHttpClient()) @@ -349,6 +360,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => [Theory] [InlineData(false)] [InlineData(true)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task SendAsync_GetWithValidHostHeader_Success(bool withPort) { if (UseVersion == HttpVersion.Version30) diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http1.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http1.cs index b3949e548e7c..b57e38127845 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http1.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http1.cs @@ -17,6 +17,7 @@ public class HttpClientHandlerTest_Http1 : HttpClientHandlerTestBase public HttpClientHandlerTest_Http1(ITestOutputHelper output) : base(output) { } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotNodeJS))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task SendAsync_HostHeader_First() { // RFC 7230 3.2.2. Field Order diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs index 0af7c66ac8ff..5baccdd37855 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs @@ -35,7 +35,10 @@ private async Task AssertProtocolErrorAsync(long errorCode, Func task) { Exception outerEx = await Assert.ThrowsAnyAsync(task); _output.WriteLine(outerEx.ToString()); - Assert.IsType(outerEx); + + HttpRequestException httpReqException = Assert.IsType(outerEx); + Assert.Equal(HttpRequestError.HttpProtocolError, httpReqException.HttpRequestError); + HttpProtocolException protocolEx = Assert.IsType(outerEx.InnerException); Assert.Equal(errorCode, protocolEx.ErrorCode); } @@ -137,6 +140,7 @@ public async Task SendStreamLimitRequestsConcurrently_Succeeds(int streamLimit) { await using Http3LoopbackStream stream = await connection.AcceptRequestStreamAsync(); await stream.HandleRequestAsync(); + _output.WriteLine($"[{DateTime.Now:HH:mm:ss.fffffff}] Server: Finished request {i}"); } }); @@ -156,9 +160,11 @@ public async Task SendStreamLimitRequestsConcurrently_Succeeds(int streamLimit) }; tasks[i] = client.SendAsync(request); + _output.WriteLine($"[{DateTime.Now:HH:mm:ss.fffffff}] Client: Started request {i}"); }); var responses = await Task.WhenAll(tasks); + _output.WriteLine($"[{DateTime.Now:HH:mm:ss.fffffff}] Client: Got all responses"); foreach (var response in responses) { response.Dispose(); @@ -1756,7 +1762,14 @@ public async Task ServerClosesOutboundControlStream_ClientClosesConnection(Close return; } await connection.OutboundControlStream.DisposeAsync(); - await connection.EstablishControlStreamAsync(Array.Empty()); + try + { + await connection.EstablishControlStreamAsync(Array.Empty()); + } + catch (QuicException ex) when (ex.QuicError == QuicError.ConnectionAborted && ex.ApplicationErrorCode == Http3LoopbackConnection.H3_CLOSED_CRITICAL_STREAM) + { + // Data race, connection closed between WaitAsync and EstablishControlStreamAsync. Ignore this. + } await Task.Delay(100); } } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.RequestRetry.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.RequestRetry.cs index 4e2426b958e6..8198fb8818a0 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.RequestRetry.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.RequestRetry.cs @@ -170,7 +170,7 @@ public SynchronizedSendContent(TaskCompletionSource sendingContent, Task c _sendingContent = sendingContent; } -#if NETCOREAPP +#if NET protected override void SerializeToStream(Stream stream, TransportContext context, CancellationToken cancellationToken) => SerializeToStreamAsync(stream, context).GetAwaiter().GetResult(); #endif diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs index 888b38b81312..088e57294d54 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs @@ -96,7 +96,7 @@ protected static LoopbackServerFactory GetFactoryForVersion(Version useVersion) { return useVersion.Major switch { -#if NETCOREAPP +#if NET #if HTTP3 3 => Http3LoopbackServerFactory.Singleton, #endif diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpRequestMessageTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpRequestMessageTest.cs index 0dd1a485894d..d62566f1dd1b 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpRequestMessageTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpRequestMessageTest.cs @@ -239,6 +239,7 @@ public void ToString_DefaultAndNonDefaultInstance_DumpAllFields() [InlineData("OPTIONS")] [InlineData("HEAD")] [ActiveIssue("https://github.com/dotnet/runtime/issues/86317", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task HttpRequest_BodylessMethod_NoContentLength(string method) { using (HttpClient client = CreateHttpClient()) diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs index c44df51433c9..f91fc2dda1dd 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs @@ -1633,8 +1633,10 @@ public SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength_Http2(ITest protected override Version UseVersion => HttpVersion.Version20; } - [ActiveIssue("https://github.com/dotnet/runtime/issues/91757")] + [Collection(nameof(DisableParallelization))] [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/91757")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101015")] public sealed class SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength_Http3 : SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength { public SocketsHttpHandler_HttpClientHandler_MaxResponseHeadersLength_Http3(ITestOutputHelper output) : base(output) { } @@ -3993,6 +3995,7 @@ public SocketsHttpHandlerTest_HttpClientHandlerTest_Headers_Http11(ITestOutputHe [InlineData("foo", "\tbar\t")] [InlineData("foo", "\t bar \t")] [InlineData("foo ", " \t bar \r\n ")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task ResponseHeaders_ExtraWhitespace_Trimmed(string name, string value) { await LoopbackServer.CreateClientAndServerAsync(async uri => @@ -4039,6 +4042,10 @@ public sealed class SocketsHttpHandlerTest_Cookies_Http3 : HttpClientHandlerTest { public SocketsHttpHandlerTest_Cookies_Http3(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version30; + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/91757")] + public override Task GetAsync_DefaultCoookieContainer_NoCookieSent() { return null!; } } [Collection(nameof(DisableParallelization))] @@ -4230,6 +4237,7 @@ public SocketsHttpHandler_RequestContentLengthMismatchTest_Http2(ITestOutputHelp protected override Version UseVersion => HttpVersion.Version20; } + [Collection(nameof(DisableParallelization))] [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] public sealed class SocketsHttpHandler_RequestContentLengthMismatchTest_Http3 : SocketsHttpHandler_RequestContentLengthMismatchTest { @@ -4329,7 +4337,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync( }; policy.ExtraStore.AddRange(caCerts); - policy.CustomTrustStore.Add(caCerts[caCerts.Count -1]); + policy.CustomTrustStore.Add(caCerts[caCerts.Count - 1]); socketsHandler.SslOptions = new SslClientAuthenticationOptions() { CertificateChainPolicy = policy }; using HttpClient client = CreateHttpClient(handler); @@ -4406,6 +4414,7 @@ public SocketsHttpHandler_SocketsHttpHandler_SecurityTest_Http2(ITestOutputHelpe protected override Version UseVersion => HttpVersion.Version20; } + [Collection(nameof(DisableParallelization))] [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] public sealed class SocketsHttpHandler_SocketsHttpHandler_SecurityTest_Http3 : SocketsHttpHandler_SecurityTest { @@ -4491,7 +4500,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => options: new GenericLoopbackOptions() { UseSsl = true }); } - + } public sealed class SocketsHttpHandler_HttpRequestErrorTest_Http11 : SocketsHttpHandler_HttpRequestErrorTest diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj index 26cc22001465..0256d1d53a45 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj @@ -20,7 +20,7 @@ - WasmTestOnBrowser + WasmTestOnChrome $(TestArchiveRoot)browserornodejs/ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ $(DefineConstants);TARGET_BROWSER @@ -245,6 +245,7 @@ + diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Dockerfile b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Dockerfile index 545041cdce47..8368cc8f7e47 100644 --- a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Dockerfile +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Dockerfile @@ -7,7 +7,7 @@ RUN apt-get update -y && \ apt-get upgrade -y && \ apt-get install -y cmake clang ruby-dev gem lttng-tools libssl-dev && \ gem install fpm -RUN git clone --recursive https://github.com/microsoft/msquic --depth 1 +RUN git clone --depth 1 --single-branch --branch v2.3.5 --recursive https://github.com/microsoft/msquic RUN cd msquic/ && \ mkdir build && \ cmake -B build -DCMAKE_BUILD_TYPE=Debug -DQUIC_ENABLE_LOGGING=false -DQUIC_USE_SYSTEM_LIBCRYPTO=true -DQUIC_BUILD_TOOLS=off -DQUIC_BUILD_TEST=off -DQUIC_BUILD_PERF=off -DQUIC_TLS=openssl3 -DQUIC_ENABLE_SANITIZERS=on && \ diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Program.cs b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Program.cs index e97e4baaf820..d5962dfba4d0 100644 --- a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Program.cs +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Program.cs @@ -16,8 +16,8 @@ using System.Net.Quic; using Microsoft.Quic; -[assembly:SupportedOSPlatform("windows")] -[assembly:SupportedOSPlatform("linux")] +[assembly: SupportedOSPlatform("windows")] +[assembly: SupportedOSPlatform("linux")] namespace HttpStress { @@ -186,24 +186,6 @@ private static async Task Run(Configuration config) Console.WriteLine("Query Parameters: " + config.MaxParameters); Console.WriteLine(); - if (config.HttpVersion == HttpVersion.Version30 && IsQuicSupported) - { - unsafe - { - // If the system gets overloaded, MsQuic has a tendency to drop incoming connections, see https://github.com/dotnet/runtime/issues/55979. - // So in case we're running H/3 stress test, we're using the same hack as for System.Net.Quic tests, which increases the time limit for pending operations in MsQuic thread pool. - object msQuicApiInstance = msQuicApiType.GetProperty("Api", BindingFlags.NonPublic | BindingFlags.Static)!.GetGetMethod(true)!.Invoke(null, Array.Empty())!; - QUIC_API_TABLE* apiTable = (QUIC_API_TABLE*)(Pointer.Unbox(msQuicApiType.GetProperty("ApiTable")!.GetGetMethod()!.Invoke(msQuicApiInstance, Array.Empty())!)); - QUIC_SETTINGS settings = default(QUIC_SETTINGS); - settings.IsSet.MaxWorkerQueueDelayUs = 1; - settings.MaxWorkerQueueDelayUs = 2_500_000u; // 2.5s, 10x the default - if (MsQuic.StatusFailed(apiTable->SetParam(null, MsQuic.QUIC_PARAM_GLOBAL_SETTINGS, (uint)sizeof(QUIC_SETTINGS), (byte*)&settings))) - { - Console.WriteLine($"Unable to set MsQuic MaxWorkerQueueDelayUs."); - } - } - } - StressServer? server = null; if (config.RunMode.HasFlag(RunMode.server)) { diff --git a/src/libraries/System.Net.Http/tests/TrimmingTests/System.Net.Http.TrimmingTests.proj b/src/libraries/System.Net.Http/tests/TrimmingTests/System.Net.Http.TrimmingTests.proj index ca55774a5ac4..ea8bfeffaa4b 100644 --- a/src/libraries/System.Net.Http/tests/TrimmingTests/System.Net.Http.TrimmingTests.proj +++ b/src/libraries/System.Net.Http/tests/TrimmingTests/System.Net.Http.TrimmingTests.proj @@ -5,6 +5,8 @@ browser-wasm + + true diff --git a/src/libraries/System.Net.HttpListener/src/System/Net/Windows/HttpListenerContext.Windows.cs b/src/libraries/System.Net.HttpListener/src/System/Net/Windows/HttpListenerContext.Windows.cs index 010b702d6225..2c76626a75b5 100644 --- a/src/libraries/System.Net.HttpListener/src/System/Net/Windows/HttpListenerContext.Windows.cs +++ b/src/libraries/System.Net.HttpListener/src/System/Net/Windows/HttpListenerContext.Windows.cs @@ -15,7 +15,7 @@ namespace System.Net public sealed unsafe partial class HttpListenerContext { private string? _mutualAuthentication; - internal HttpListenerSession ListenerSession { get; private set; } + internal HttpListenerSession ListenerSession { get; } internal HttpListenerContext(HttpListenerSession session, RequestContextBase memoryBlob) { diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs index 47ac65dbf9b5..a4cc338453b8 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs @@ -216,6 +216,12 @@ private string GetHost(bool allowUnicode) throw new SmtpException(SR.Format(SR.SmtpInvalidHostName, Address), argEx); } } + + if (domain.AsSpan().ContainsAny('\r', '\n')) + { + throw new SmtpException(SR.Format(SR.SmtpInvalidHostName, Address)); + } + return domain; } diff --git a/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs b/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs index 306368df2021..c8c5734b04cf 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs @@ -9,11 +9,15 @@ // (C) 2006 John Luke // +using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Net.NetworkInformation; using System.Net.Sockets; +using System.Reflection; using System.Threading; using System.Threading.Tasks; +using Microsoft.DotNet.RemoteExecutor; using Systen.Net.Mail.Tests; using System.Net.Test.Common; using Xunit; @@ -573,5 +577,41 @@ public void TestGssapiAuthentication() Assert.Equal("GSSAPI", server.AuthMethodUsed, StringComparer.OrdinalIgnoreCase); } + + [Theory] + [MemberData(nameof(SendMail_MultiLineDomainLiterals_Data))] + public async Task SendMail_MultiLineDomainLiterals_Disabled_Throws(string from, string to, bool asyncSend) + { + using var server = new LoopbackSmtpServer(); + + using SmtpClient client = server.CreateClient(); + client.Credentials = new NetworkCredential("Foo", "Bar"); + + using var msg = new MailMessage(@from, @to, "subject", "body"); + + await Assert.ThrowsAsync(async () => + { + if (asyncSend) + { + await client.SendMailAsync(msg).WaitAsync(TimeSpan.FromSeconds(30)); + } + else + { + client.Send(msg); + } + }); + } + + public static IEnumerable SendMail_MultiLineDomainLiterals_Data() + { + foreach (bool async in new[] { true, false }) + { + foreach (string address in new[] { "foo@[\r\n bar]", "foo@[bar\r\n ]", "foo@[bar\r\n baz]" }) + { + yield return new object[] { address, "foo@example.com", async }; + yield return new object[] { "foo@example.com", address, async }; + } + } + } } } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.OSX.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.OSX.cs index 5d062e94fd80..2385e4d98008 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.OSX.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.OSX.cs @@ -17,7 +17,7 @@ namespace System.Net.NetworkInformation // the documentation for CFRunLoop for more information on the components involved. public partial class NetworkChange { - private static object s_lockObj = new object(); + private static readonly object s_lockObj = new object(); // The dynamic store. We listen to changes in the IPv4 and IPv6 address keys. // When those keys change, our callback below is called (OnAddressChanged). diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemNetworkInterface.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemNetworkInterface.cs index de2197321e53..8a99feaeec36 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemNetworkInterface.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemNetworkInterface.cs @@ -85,8 +85,7 @@ internal static unsafe NetworkInterface[] GetNetworkInterfaces() List interfaceList = new List(); Interop.IpHlpApi.GetAdaptersAddressesFlags flags = - Interop.IpHlpApi.GetAdaptersAddressesFlags.IncludeGateways - | Interop.IpHlpApi.GetAdaptersAddressesFlags.IncludeWins; + Interop.IpHlpApi.GetAdaptersAddressesFlags.IncludeAllInterfaces; // Figure out the right buffer size for the adapter information. uint result = Interop.IpHlpApi.GetAdaptersAddresses( diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs index dcb12e8b7f87..5d5167be739f 100644 --- a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs @@ -22,6 +22,7 @@ public NetworkInterfaceBasicTest(ITestOutputHelper output) [Fact] public void BasicTest_GetNetworkInterfaces_AtLeastOne() { + Assert.NotEqual(0, NetworkInterface.GetAllNetworkInterfaces().Length); } @@ -50,7 +51,8 @@ public void BasicTest_AccessInstanceProperties_NoExceptions() if (nic.NetworkInterfaceType == NetworkInterfaceType.Ethernet) { - Assert.Equal(6, nic.GetPhysicalAddress().GetAddressBytes().Length); + var physicalAddressLength = nic.GetPhysicalAddress().GetAddressBytes().Length; + Assert.True(physicalAddressLength == 0 || physicalAddressLength == 6); } } } diff --git a/src/libraries/System.Net.Ping/src/System.Net.Ping.csproj b/src/libraries/System.Net.Ping/src/System.Net.Ping.csproj index 99f83f5fa17b..0cfd246889fa 100644 --- a/src/libraries/System.Net.Ping/src/System.Net.Ping.csproj +++ b/src/libraries/System.Net.Ping/src/System.Net.Ping.csproj @@ -41,6 +41,14 @@ Link="Common\System\Net\SocketProtocolSupportPal.Unix.cs" /> + + + + @@ -48,8 +56,14 @@ Link="Common\Interop\Unix\Interop.Errors.cs" /> + + + + diff --git a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.RawSocket.cs b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.RawSocket.cs index d535734a2f77..cef4453630b6 100644 --- a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.RawSocket.cs +++ b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.RawSocket.cs @@ -102,6 +102,12 @@ private static Socket GetRawSocket(SocketConfig socketConfig) { // If it is not multicast, use Connect to scope responses only to the target address. socket.Connect(socketConfig.EndPoint); + unsafe + { + int opt = 1; + // setsockopt(fd, IPPROTO_IP, IP_RECVERR, &value, sizeof(int)) + socket.SetRawSocketOption(0, 11, new ReadOnlySpan(&opt, sizeof(int))); + } } #pragma warning restore 618 @@ -232,11 +238,12 @@ private static bool TryGetPingReply( return true; } - private static PingReply SendIcmpEchoRequestOverRawSocket(IPAddress address, byte[] buffer, int timeout, PingOptions? options) + private static unsafe PingReply SendIcmpEchoRequestOverRawSocket(IPAddress address, byte[] buffer, int timeout, PingOptions? options) { SocketConfig socketConfig = GetSocketConfig(address, buffer, timeout, options); using (Socket socket = GetRawSocket(socketConfig)) { + Span socketAddress = stackalloc byte[SocketAddress.GetMaximumAddressSize(address.AddressFamily)]; int ipHeaderLength = socketConfig.IsIpv4 ? MinIpHeaderLengthInBytes : 0; try { @@ -270,6 +277,29 @@ private static PingReply SendIcmpEchoRequestOverRawSocket(IPAddress address, byt { return CreatePingReply(IPStatus.PacketTooBig); } + catch (SocketException ex) when (ex.SocketErrorCode == SocketError.HostUnreachable) + { + // This happens on Linux where we explicitly subscribed to error messages + // We should be able to get more info by getting extended socket error from error queue. + + Interop.Sys.MessageHeader header = default; + + SocketError result; + fixed (byte* sockAddr = &MemoryMarshal.GetReference(socketAddress)) + { + header.SocketAddress = sockAddr; + header.SocketAddressLen = socketAddress.Length; + header.IOVectors = null; + header.IOVectorCount = 0; + + result = Interop.Sys.ReceiveSocketError(socket.SafeHandle, &header); + } + + if (result == SocketError.Success && header.SocketAddressLen > 0) + { + return CreatePingReply(IPStatus.TtlExpired, IPEndPointExtensions.GetIPAddress(socketAddress.Slice(0, header.SocketAddressLen))); + } + } // We have exceeded our timeout duration, and no reply has been received. return CreatePingReply(IPStatus.TimedOut); diff --git a/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj b/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj index a659207964a3..e71aaa8222e3 100644 --- a/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj +++ b/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj @@ -82,6 +82,8 @@ Link="Common\System\Text\StringBuilderCache.cs" /> + diff --git a/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs b/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs index 8e21138d1b58..b25a5df1db2d 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs @@ -63,7 +63,7 @@ public sealed class Cookie private bool m_secure; // Do not rename (binary serialization) [System.Runtime.Serialization.OptionalField] private bool m_httpOnly = false; // Do not rename (binary serialization) - private DateTime m_timeStamp = DateTime.Now; // Do not rename (binary serialization) + private DateTime m_timeStamp = DateTime.UtcNow; // Do not rename (binary serialization) private string m_value = string.Empty; // Do not rename (binary serialization) private int m_version; // Do not rename (binary serialization) @@ -199,13 +199,13 @@ public bool Expired { get { - return (m_expires != DateTime.MinValue) && (m_expires.ToLocalTime() <= DateTime.Now); + return (m_expires != DateTime.MinValue) && (m_expires.ToUniversalTime() <= DateTime.UtcNow); } set { if (value) { - m_expires = DateTime.Now; + m_expires = DateTime.UtcNow; } } } @@ -801,7 +801,7 @@ internal void ToString(StringBuilder sb) } if (Expires != DateTime.MinValue) { - int seconds = (int)(Expires.ToLocalTime() - DateTime.Now).TotalSeconds; + int seconds = (int)(Expires.ToUniversalTime() - DateTime.UtcNow).TotalSeconds; if (seconds < 0) { // This means that the cookie has already expired. Set Max-Age to 0 diff --git a/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs b/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs index 8cb883712279..8e46d4ab6c52 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs @@ -13,7 +13,7 @@ namespace System.Net // name-password pairs and associates these with host/realm. public class CredentialCache : ICredentials, ICredentialsByHost, IEnumerable { - private Dictionary? _cache; + private Dictionary? _cache; private Dictionary? _cacheForHosts; private int _version; @@ -37,11 +37,11 @@ public void Add(Uri uriPrefix, string authType, NetworkCredential cred) ++_version; - var key = new CredentialKey(uriPrefix, authType); + var key = new CredentialCacheKey(uriPrefix, authType); if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Adding key:[{key}], cred:[{cred.Domain}],[{cred.UserName}]"); - _cache ??= new Dictionary(); + _cache ??= new Dictionary(); _cache.Add(key, cred); } @@ -88,7 +88,7 @@ public void Remove(Uri? uriPrefix, string? authType) ++_version; - var key = new CredentialKey(uriPrefix, authType); + var key = new CredentialCacheKey(uriPrefix, authType); if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Removing key:[{key}]"); @@ -135,28 +135,7 @@ public void Remove(string? host, int port, string? authenticationType) return null; } - int longestMatchPrefix = -1; - NetworkCredential? mostSpecificMatch = null; - - // Enumerate through every credential in the cache - foreach (KeyValuePair pair in _cache) - { - CredentialKey key = pair.Key; - - // Determine if this credential is applicable to the current Uri/AuthType - if (key.Match(uriPrefix, authType)) - { - int prefixLen = key.UriPrefixLength; - - // Check if the match is better than the current-most-specific match - if (prefixLen > longestMatchPrefix) - { - // Yes: update the information about currently preferred match - longestMatchPrefix = prefixLen; - mostSpecificMatch = pair.Value; - } - } - } + CredentialCacheHelper.TryGetCredential(_cache, uriPrefix, authType, out _ /*uri*/, out NetworkCredential? mostSpecificMatch); if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Returning {(mostSpecificMatch == null ? "null" : "(" + mostSpecificMatch.UserName + ":" + mostSpecificMatch.Domain + ")")}"); @@ -201,7 +180,7 @@ internal static CredentialEnumerator Create(CredentialCache cache) { return cache._cacheForHosts != null ? new DoubleTableCredentialEnumerator(cache) : - new SingleTableCredentialEnumerator(cache, cache._cache); + new SingleTableCredentialEnumerator(cache, cache._cache); } else { @@ -286,7 +265,7 @@ public override void Reset() } } - private sealed class DoubleTableCredentialEnumerator : SingleTableCredentialEnumerator + private sealed class DoubleTableCredentialEnumerator : SingleTableCredentialEnumerator { private Dictionary.ValueCollection.Enumerator _enumerator; // mutable struct field deliberately not readonly. private bool _onThisEnumerator; @@ -406,95 +385,4 @@ public override bool Equals([NotNullWhen(true)] object? obj) => public override string ToString() => string.Create(CultureInfo.InvariantCulture, $"{Host}:{Port}:{AuthenticationType}"); } - - internal sealed class CredentialKey : IEquatable - { - public readonly Uri UriPrefix; - public readonly int UriPrefixLength = -1; - public readonly string AuthenticationType; - - internal CredentialKey(Uri uriPrefix, string authenticationType) - { - Debug.Assert(uriPrefix != null); - Debug.Assert(authenticationType != null); - - UriPrefix = uriPrefix; - UriPrefixLength = UriPrefix.ToString().Length; - AuthenticationType = authenticationType; - } - - internal bool Match(Uri uri, string authenticationType) - { - if (uri == null || authenticationType == null) - { - return false; - } - - // If the protocols don't match, this credential is not applicable for the given Uri. - if (!string.Equals(authenticationType, AuthenticationType, StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Match({UriPrefix} & {uri})"); - - return IsPrefix(uri, UriPrefix); - } - - // IsPrefix (Uri) - // - // Determines whether is a prefix of this URI. A prefix - // match is defined as: - // - // scheme match - // + host match - // + port match, if any - // + path is a prefix of path, if any - // - // Returns: - // True if is a prefix of this URI - private static bool IsPrefix(Uri uri, Uri prefixUri) - { - Debug.Assert(uri != null); - Debug.Assert(prefixUri != null); - - if (prefixUri.Scheme != uri.Scheme || prefixUri.Host != uri.Host || prefixUri.Port != uri.Port) - { - return false; - } - - int prefixLen = prefixUri.AbsolutePath.LastIndexOf('/'); - if (prefixLen > uri.AbsolutePath.LastIndexOf('/')) - { - return false; - } - - return string.Compare(uri.AbsolutePath, 0, prefixUri.AbsolutePath, 0, prefixLen, StringComparison.OrdinalIgnoreCase) == 0; - } - - public override int GetHashCode() => - StringComparer.OrdinalIgnoreCase.GetHashCode(AuthenticationType) ^ - UriPrefix.GetHashCode(); - - public bool Equals([NotNullWhen(true)] CredentialKey? other) - { - if (other == null) - { - return false; - } - - bool equals = - string.Equals(AuthenticationType, other.AuthenticationType, StringComparison.OrdinalIgnoreCase) && - UriPrefix.Equals(other.UriPrefix); - - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Equals({this},{other}) returns {equals}"); - - return equals; - } - - public override bool Equals([NotNullWhen(true)] object? obj) => Equals(obj as CredentialKey); - - public override string ToString() => - string.Create(CultureInfo.InvariantCulture, $"[{UriPrefixLength}]:{UriPrefix}:{AuthenticationType}"); - } } diff --git a/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest.cs b/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest.cs index 1ba710d4f46e..11fa3ba37026 100644 --- a/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest.cs +++ b/src/libraries/System.Net.Primitives/tests/FunctionalTests/CookieTest.cs @@ -116,10 +116,10 @@ public static void Expired_GetSet_Success() Cookie c = new Cookie(); Assert.False(c.Expired); - c.Expires = DateTime.Now.AddDays(-1); + c.Expires = DateTime.UtcNow.AddDays(-1); Assert.True(c.Expired); - c.Expires = DateTime.Now.AddDays(1); + c.Expires = DateTime.UtcNow.AddDays(1); Assert.False(c.Expired); c.Expired = true; @@ -135,7 +135,7 @@ public static void Expires_GetSet_Success() Cookie c = new Cookie(); Assert.Equal(c.Expires, DateTime.MinValue); - DateTime dt = DateTime.Now; + DateTime dt = DateTime.UtcNow; c.Expires = dt; Assert.Equal(dt, c.Expires); } @@ -226,7 +226,9 @@ public static void Secure_GetSet_Success() [Fact] public static void Timestamp_GetSet_Success() { - DateTime dt = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, 0); //DateTime.Now changes as the test runs + //DateTime.UtcNow changes as the test runs + DateTime dt = DateTime.UtcNow; + dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0); Cookie c = new Cookie(); Assert.True(c.TimeStamp >= dt); } diff --git a/src/libraries/System.Net.Primitives/tests/FunctionalTests/CredentialCacheTest.cs b/src/libraries/System.Net.Primitives/tests/FunctionalTests/CredentialCacheTest.cs index a67967b36811..6895fabba4f1 100644 --- a/src/libraries/System.Net.Primitives/tests/FunctionalTests/CredentialCacheTest.cs +++ b/src/libraries/System.Net.Primitives/tests/FunctionalTests/CredentialCacheTest.cs @@ -272,6 +272,17 @@ public static void GetCredential_SimilarUriAuthenticationType_GetLongestUriPrefi Assert.Equal(nc, credential2); } + [Fact] + public static void GetCredential_LongerUriButShorterMatch() + { + CredentialCache cc = new CredentialCache(); + cc.Add(new Uri("http://microsoft:80/common/unique/something"), authenticationType1, credential2); + cc.Add(new Uri("http://microsoft:80/common/veryloooooongprefix"), authenticationType1, credential1); + + NetworkCredential nc = cc.GetCredential(new Uri("http://microsoft:80/common/unique/a"), authenticationType1); + Assert.Equal(nc, credential2); + } + [Fact] public static void GetCredential_UriAuthenticationType_Invalid() { diff --git a/src/libraries/System.Net.Quic/src/ExcludeApiList.PNSE.txt b/src/libraries/System.Net.Quic/src/ExcludeApiList.PNSE.txt index 63d6cfde19fe..d6b3f48e2a73 100644 --- a/src/libraries/System.Net.Quic/src/ExcludeApiList.PNSE.txt +++ b/src/libraries/System.Net.Quic/src/ExcludeApiList.PNSE.txt @@ -1,7 +1,2 @@ P:System.Net.Quic.QuicConnection.IsSupported -P:System.Net.Quic.QuicListener.IsSupported -C:System.Net.Quic.QuicListenerOptions -C:System.Net.Quic.QuicConnectionOptions -C:System.Net.Quic.QuicReceiveWindowSizes -C:System.Net.Quic.QuicClientConnectionOptions -C:System.Net.Quic.QuicServerConnectionOptions \ No newline at end of file +P:System.Net.Quic.QuicListener.IsSupported \ No newline at end of file diff --git a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj index aafca7f3e93b..56f1d2837ac6 100644 --- a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj +++ b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj @@ -38,6 +38,7 @@ + @@ -46,10 +47,6 @@ - - - - diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs index 4b284284f526..28c326b7b65f 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs @@ -54,7 +54,7 @@ private MsQuicApi(QUIC_API_TABLE* apiTable) private static readonly Lazy _api = new Lazy(AllocateMsQuicApi); internal static MsQuicApi Api => _api.Value; - internal static Version? Version { get; private set; } + internal static Version? Version { get; } internal static bool IsQuicSupported { get; } @@ -62,7 +62,7 @@ private MsQuicApi(QUIC_API_TABLE* apiTable) internal static string? NotSupportedReason { get; } // workaround for https://github.com/microsoft/msquic/issues/4132 - internal static bool SupportsAsyncCertValidation => Version >= new Version(2, 4, 0); + internal static bool SupportsAsyncCertValidation => Version >= new Version(2, 3, 5); internal static bool UsesSChannelBackend { get; } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.Cache.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.Cache.cs index 4fc86adfbd15..38a02cad2328 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.Cache.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.Cache.cs @@ -21,6 +21,7 @@ internal static partial class MsQuicConfiguration private const string DisableCacheCtxSwitch = "System.Net.Quic.DisableConfigurationCache"; internal static bool ConfigurationCacheEnabled { get; } = GetConfigurationCacheEnabled(); + private static bool GetConfigurationCacheEnabled() { // AppContext switch takes precedence @@ -28,15 +29,15 @@ private static bool GetConfigurationCacheEnabled() { return !value; } - else + // check environment variable second + else if (Environment.GetEnvironmentVariable(DisableCacheEnvironmentVariable) is string envVar) { - // check environment variable - return - Environment.GetEnvironmentVariable(DisableCacheEnvironmentVariable) is string envVar && - !(envVar == "1" || envVar.Equals("true", StringComparison.OrdinalIgnoreCase)); + return !(envVar == "1" || envVar.Equals("true", StringComparison.OrdinalIgnoreCase)); } - } + // enabled by default + return true; + } private static readonly ConcurrentDictionary s_configurationCache = new(); private readonly struct CacheKey : IEquatable diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.cs index d45be601ae86..00fb1ee8c72b 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.cs @@ -157,16 +157,16 @@ private static MsQuicConfigurationSafeHandle Create(QuicConnectionOptions option } settings.IsSet.ConnFlowControlWindow = 1; - settings.ConnFlowControlWindow = (uint)(options._initialRecieveWindowSizes?.Connection ?? QuicDefaults.DefaultConnectionMaxData); + settings.ConnFlowControlWindow = (uint)(options._initialReceiveWindowSizes?.Connection ?? QuicDefaults.DefaultConnectionMaxData); settings.IsSet.StreamRecvWindowBidiLocalDefault = 1; - settings.StreamRecvWindowBidiLocalDefault = (uint)(options._initialRecieveWindowSizes?.LocallyInitiatedBidirectionalStream ?? QuicDefaults.DefaultStreamMaxData); + settings.StreamRecvWindowBidiLocalDefault = (uint)(options._initialReceiveWindowSizes?.LocallyInitiatedBidirectionalStream ?? QuicDefaults.DefaultStreamMaxData); settings.IsSet.StreamRecvWindowBidiRemoteDefault = 1; - settings.StreamRecvWindowBidiRemoteDefault = (uint)(options._initialRecieveWindowSizes?.RemotelyInitiatedBidirectionalStream ?? QuicDefaults.DefaultStreamMaxData); + settings.StreamRecvWindowBidiRemoteDefault = (uint)(options._initialReceiveWindowSizes?.RemotelyInitiatedBidirectionalStream ?? QuicDefaults.DefaultStreamMaxData); settings.IsSet.StreamRecvWindowUnidiDefault = 1; - settings.StreamRecvWindowUnidiDefault = (uint)(options._initialRecieveWindowSizes?.UnidirectionalStream ?? QuicDefaults.DefaultStreamMaxData); + settings.StreamRecvWindowUnidiDefault = (uint)(options._initialReceiveWindowSizes?.UnidirectionalStream ?? QuicDefaults.DefaultStreamMaxData); if (options.HandshakeTimeout != TimeSpan.Zero) { diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicExtensions.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicExtensions.cs index 5c079f652874..cfc5a09a3717 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicExtensions.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Net.Quic; namespace Microsoft.Quic; @@ -17,7 +18,7 @@ public override string ToString() => Type switch { QUIC_LISTENER_EVENT_TYPE.NEW_CONNECTION - => $"{{ {nameof(NEW_CONNECTION.Info)} = {{ {nameof(QUIC_NEW_CONNECTION_INFO.QuicVersion)} = {NEW_CONNECTION.Info->QuicVersion}, {nameof(QUIC_NEW_CONNECTION_INFO.LocalAddress)} = {MsQuicHelpers.QuicAddrToIPEndPoint(NEW_CONNECTION.Info->LocalAddress)}, {nameof(QUIC_NEW_CONNECTION_INFO.RemoteAddress)} = {MsQuicHelpers.QuicAddrToIPEndPoint(NEW_CONNECTION.Info->RemoteAddress)} }} }}", + => $"{{ {nameof(NEW_CONNECTION.Info)} = {{ {nameof(QUIC_NEW_CONNECTION_INFO.QuicVersion)} = {NEW_CONNECTION.Info->QuicVersion}, {nameof(QUIC_NEW_CONNECTION_INFO.LocalAddress)} = {MsQuicHelpers.QuicAddrToIPEndPoint(NEW_CONNECTION.Info->LocalAddress)}, {nameof(QUIC_NEW_CONNECTION_INFO.RemoteAddress)} = {MsQuicHelpers.QuicAddrToIPEndPoint(NEW_CONNECTION.Info->RemoteAddress)} }}, {nameof(NEW_CONNECTION.Connection)} = 0x{(IntPtr)NEW_CONNECTION.Connection:X11} }}", _ => string.Empty }; } @@ -40,9 +41,29 @@ public override string ToString() QUIC_CONNECTION_EVENT_TYPE.PEER_ADDRESS_CHANGED => $"{{ {nameof(PEER_ADDRESS_CHANGED.Address)} = {MsQuicHelpers.QuicAddrToIPEndPoint(PEER_ADDRESS_CHANGED.Address)} }}", QUIC_CONNECTION_EVENT_TYPE.PEER_STREAM_STARTED - => $"{{ {nameof(PEER_STREAM_STARTED.Flags)} = {PEER_STREAM_STARTED.Flags} }}", + => $"{{ {nameof(PEER_STREAM_STARTED.Stream)} = 0x{(IntPtr)PEER_STREAM_STARTED.Stream:X11} {nameof(PEER_STREAM_STARTED.Flags)} = {PEER_STREAM_STARTED.Flags} }}", + QUIC_CONNECTION_EVENT_TYPE.STREAMS_AVAILABLE + => $"{{ {nameof(STREAMS_AVAILABLE.BidirectionalCount)} = {STREAMS_AVAILABLE.BidirectionalCount}, {nameof(STREAMS_AVAILABLE.UnidirectionalCount)} = {STREAMS_AVAILABLE.UnidirectionalCount} }}", + QUIC_CONNECTION_EVENT_TYPE.PEER_NEEDS_STREAMS + => $"{{ {nameof(PEER_NEEDS_STREAMS.Bidirectional)} = {PEER_NEEDS_STREAMS.Bidirectional} }}", + QUIC_CONNECTION_EVENT_TYPE.IDEAL_PROCESSOR_CHANGED + => $"{{ {nameof(IDEAL_PROCESSOR_CHANGED.IdealProcessor)} = {IDEAL_PROCESSOR_CHANGED.IdealProcessor}, {nameof(IDEAL_PROCESSOR_CHANGED.PartitionIndex)} = {IDEAL_PROCESSOR_CHANGED.PartitionIndex} }}", + QUIC_CONNECTION_EVENT_TYPE.DATAGRAM_STATE_CHANGED + => $"{{ {nameof(DATAGRAM_STATE_CHANGED.SendEnabled)} = {DATAGRAM_STATE_CHANGED.SendEnabled}, {nameof(DATAGRAM_STATE_CHANGED.MaxSendLength)} = {DATAGRAM_STATE_CHANGED.MaxSendLength} }}", + QUIC_CONNECTION_EVENT_TYPE.DATAGRAM_RECEIVED + => $"{{ {nameof(DATAGRAM_RECEIVED.Flags)} = {DATAGRAM_RECEIVED.Flags} }}", + QUIC_CONNECTION_EVENT_TYPE.DATAGRAM_SEND_STATE_CHANGED + => $"{{ {nameof(DATAGRAM_SEND_STATE_CHANGED.ClientContext)} = 0x{(IntPtr)DATAGRAM_SEND_STATE_CHANGED.ClientContext:X11}, {nameof(DATAGRAM_SEND_STATE_CHANGED.State)} = {DATAGRAM_SEND_STATE_CHANGED.State} }}", + QUIC_CONNECTION_EVENT_TYPE.RESUMED + => $"{{ {nameof(RESUMED.ResumptionStateLength)} = {RESUMED.ResumptionStateLength} }}", + QUIC_CONNECTION_EVENT_TYPE.RESUMPTION_TICKET_RECEIVED + => $"{{ {nameof(RESUMPTION_TICKET_RECEIVED.ResumptionTicketLength)} = {RESUMPTION_TICKET_RECEIVED.ResumptionTicketLength} }}", QUIC_CONNECTION_EVENT_TYPE.PEER_CERTIFICATE_RECEIVED - => $"{{ {nameof(PEER_CERTIFICATE_RECEIVED.DeferredStatus)} = {PEER_CERTIFICATE_RECEIVED.DeferredStatus}, {nameof(PEER_CERTIFICATE_RECEIVED.DeferredErrorFlags)} = {PEER_CERTIFICATE_RECEIVED.DeferredErrorFlags} }}", + => $"{{ {nameof(PEER_CERTIFICATE_RECEIVED.DeferredStatus)} = {PEER_CERTIFICATE_RECEIVED.DeferredStatus}, {nameof(PEER_CERTIFICATE_RECEIVED.DeferredErrorFlags)} = {PEER_CERTIFICATE_RECEIVED.DeferredErrorFlags}, {nameof(PEER_CERTIFICATE_RECEIVED.Certificate)} = 0x{(IntPtr)PEER_CERTIFICATE_RECEIVED.Certificate:X11} }}", + QUIC_CONNECTION_EVENT_TYPE.RELIABLE_RESET_NEGOTIATED + => $"{{ {nameof(RELIABLE_RESET_NEGOTIATED.IsNegotiated)} = {RELIABLE_RESET_NEGOTIATED.IsNegotiated} }}", + QUIC_CONNECTION_EVENT_TYPE.ONE_WAY_DELAY_NEGOTIATED + => $"{{ {nameof(ONE_WAY_DELAY_NEGOTIATED.SendNegotiated)} = {ONE_WAY_DELAY_NEGOTIATED.SendNegotiated}, {nameof(ONE_WAY_DELAY_NEGOTIATED.ReceiveNegotiated)} = {ONE_WAY_DELAY_NEGOTIATED.ReceiveNegotiated} }}", _ => string.Empty }; } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicSafeHandle.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicSafeHandle.cs index cf7d70a18e08..8e70ec205724 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicSafeHandle.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicSafeHandle.cs @@ -88,7 +88,7 @@ internal sealed class MsQuicContextSafeHandle : MsQuicSafeHandle /// Holds a weak reference to the managed instance. /// It allows delegating MsQuic events to the managed object while it still can be collected and finalized. ///
    - private readonly GCHandle _context; + private GCHandle _context; /// /// Optional parent safe handle, used to increment/decrement reference count with the lifetime of this instance. diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicTlsSecret.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicTlsSecret.cs index 26f69c1653aa..44f57b8b86bc 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicTlsSecret.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicTlsSecret.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if DEBUG using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; @@ -13,14 +12,11 @@ namespace System.Net.Quic; internal sealed class MsQuicTlsSecret : IDisposable { - private static readonly string? s_keyLogFile = Environment.GetEnvironmentVariable("SSLKEYLOGFILE"); - private static readonly FileStream? s_fileStream = s_keyLogFile != null ? File.Open(s_keyLogFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite) : null; - private unsafe QUIC_TLS_SECRETS* _tlsSecrets; public static unsafe MsQuicTlsSecret? Create(MsQuicContextSafeHandle handle) { - if (s_fileStream is null) + if (!SslKeyLogger.IsEnabled) { return null; } @@ -55,40 +51,69 @@ private unsafe MsQuicTlsSecret(QUIC_TLS_SECRETS* tlsSecrets) public unsafe void WriteSecret() { - Debug.Assert(_tlsSecrets is not null); - Debug.Assert(s_fileStream is not null); + ReadOnlySpan clientRandom = _tlsSecrets->IsSet.ClientRandom != 0 + ? new ReadOnlySpan(_tlsSecrets->ClientRandom, 32) + : ReadOnlySpan.Empty; + + Span clientHandshakeTrafficSecret = _tlsSecrets->IsSet.ClientHandshakeTrafficSecret != 0 + ? new Span(_tlsSecrets->ClientHandshakeTrafficSecret, _tlsSecrets->SecretLength) + : Span.Empty; + + Span serverHandshakeTrafficSecret = _tlsSecrets->IsSet.ServerHandshakeTrafficSecret != 0 + ? new Span(_tlsSecrets->ServerHandshakeTrafficSecret, _tlsSecrets->SecretLength) + : Span.Empty; + + Span clientTrafficSecret0 = _tlsSecrets->IsSet.ClientTrafficSecret0 != 0 + ? new Span(_tlsSecrets->ClientTrafficSecret0, _tlsSecrets->SecretLength) + : Span.Empty; - lock (s_fileStream) + Span serverTrafficSecret0 = _tlsSecrets->IsSet.ServerTrafficSecret0 != 0 + ? new Span(_tlsSecrets->ServerTrafficSecret0, _tlsSecrets->SecretLength) + : Span.Empty; + + Span clientEarlyTrafficSecret = _tlsSecrets->IsSet.ClientEarlyTrafficSecret != 0 + ? new Span(_tlsSecrets->ClientEarlyTrafficSecret, _tlsSecrets->SecretLength) + : Span.Empty; + + SslKeyLogger.WriteSecrets( + clientRandom, + clientHandshakeTrafficSecret, + serverHandshakeTrafficSecret, + clientTrafficSecret0, + serverTrafficSecret0, + clientEarlyTrafficSecret); + + // clear secrets already logged, so they are not logged again on next call, + // keep ClientRandom as it is used for all secrets (and is not a secret itself) + if (!clientHandshakeTrafficSecret.IsEmpty) { - string clientRandom = string.Empty; - if (_tlsSecrets->IsSet.ClientRandom != 0) - { - clientRandom = Convert.ToHexString(new ReadOnlySpan(_tlsSecrets->ClientRandom, 32)); - } - if (_tlsSecrets->IsSet.ClientHandshakeTrafficSecret != 0) - { - s_fileStream.Write(Encoding.ASCII.GetBytes($"CLIENT_HANDSHAKE_TRAFFIC_SECRET {clientRandom} {Convert.ToHexString(new ReadOnlySpan(_tlsSecrets->ClientHandshakeTrafficSecret, _tlsSecrets->SecretLength))}\n")); - } - if (_tlsSecrets->IsSet.ServerHandshakeTrafficSecret != 0) - { - s_fileStream.Write(Encoding.ASCII.GetBytes($"SERVER_HANDSHAKE_TRAFFIC_SECRET {clientRandom} {Convert.ToHexString(new ReadOnlySpan(_tlsSecrets->ServerHandshakeTrafficSecret, _tlsSecrets->SecretLength))}\n")); - } - if (_tlsSecrets->IsSet.ClientTrafficSecret0 != 0) - { - s_fileStream.Write(Encoding.ASCII.GetBytes($"CLIENT_TRAFFIC_SECRET_0 {clientRandom} {Convert.ToHexString(new ReadOnlySpan(_tlsSecrets->ClientTrafficSecret0, _tlsSecrets->SecretLength))}\n")); - } - if (_tlsSecrets->IsSet.ServerTrafficSecret0 != 0) - { - s_fileStream.Write(Encoding.ASCII.GetBytes($"SERVER_TRAFFIC_SECRET_0 {clientRandom} {Convert.ToHexString(new ReadOnlySpan(_tlsSecrets->ServerTrafficSecret0, _tlsSecrets->SecretLength))}\n")); - } - if (_tlsSecrets->IsSet.ClientEarlyTrafficSecret != 0) - { - s_fileStream.Write(Encoding.ASCII.GetBytes($"CLIENT_EARLY_TRAFFIC_SECRET {clientRandom} {Convert.ToHexString(new ReadOnlySpan(_tlsSecrets->ClientEarlyTrafficSecret, _tlsSecrets->SecretLength))}\n")); - } - s_fileStream.Flush(); + clientHandshakeTrafficSecret.Clear(); + _tlsSecrets->IsSet.ClientHandshakeTrafficSecret = 0; } - NativeMemory.Clear(_tlsSecrets, (nuint)sizeof(QUIC_TLS_SECRETS)); + if (!serverHandshakeTrafficSecret.IsEmpty) + { + serverHandshakeTrafficSecret.Clear(); + _tlsSecrets->IsSet.ServerHandshakeTrafficSecret = 0; + } + + if (!clientTrafficSecret0.IsEmpty) + { + clientTrafficSecret0.Clear(); + _tlsSecrets->IsSet.ClientTrafficSecret0 = 0; + } + + if (!serverTrafficSecret0.IsEmpty) + { + serverTrafficSecret0.Clear(); + _tlsSecrets->IsSet.ServerTrafficSecret0 = 0; + } + + if (!clientEarlyTrafficSecret.IsEmpty) + { + clientEarlyTrafficSecret.Clear(); + _tlsSecrets->IsSet.ClientEarlyTrafficSecret = 0; + } } public unsafe void Dispose() @@ -110,4 +135,3 @@ public unsafe void Dispose() } } } -#endif diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/ThrowHelper.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/ThrowHelper.cs index 114c39c49c1e..85a06e12a0f9 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/ThrowHelper.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/ThrowHelper.cs @@ -6,6 +6,7 @@ using System.Net.Sockets; using System.Runtime.CompilerServices; using System.Security.Authentication; +using System.Threading; using static Microsoft.Quic.MsQuic; namespace System.Net.Quic; @@ -27,13 +28,27 @@ internal static QuicException GetOperationAbortedException(string? message = nul return new QuicException(QuicError.OperationAborted, null, message ?? SR.net_quic_operationaborted); } - internal static bool TryGetStreamExceptionForMsQuicStatus(int status, [NotNullWhen(true)] out Exception? exception) + internal static bool TryGetStreamExceptionForMsQuicStatus(int status, [NotNullWhen(true)] out Exception? exception, bool streamWasSuccessfullyStarted = true, string? message = null) { if (status == QUIC_STATUS_ABORTED) { - // If status == QUIC_STATUS_ABORTED, we will receive an event later, which will complete the task source. - exception = null; - return false; + // Connection has been closed by the peer (either at transport or application level), + if (streamWasSuccessfullyStarted) + { + // we will receive an event later, which will complete the stream with concrete + // information why the connection was aborted. + exception = null; + return false; + } + else + { + // we won't be receiving any event callback for shutdown on this stream, so we don't + // necessarily know which error to report. So we throw an exception which we can distinguish + // at the caller (ConnectionAborted normally has App error code) and throw the correct + // exception from there. + exception = new QuicException(QuicError.ConnectionAborted, null, ""); + return true; + } } else if (status == QUIC_STATUS_INVALID_STATE) { @@ -43,13 +58,16 @@ internal static bool TryGetStreamExceptionForMsQuicStatus(int status, [NotNullWh } else if (StatusFailed(status)) { - exception = GetExceptionForMsQuicStatus(status); + exception = GetExceptionForMsQuicStatus(status, message: message); return true; } exception = null; return false; } + // see TryGetStreamExceptionForMsQuicStatus for explanation + internal static bool IsConnectionAbortedWhenStartingStreamException(Exception ex) => ex is QuicException qe && qe.QuicError == QuicError.ConnectionAborted && qe.ApplicationErrorCode is null; + internal static Exception GetExceptionForMsQuicStatus(int status, long? errorCode = default, string? message = null) { Exception ex = GetExceptionInternal(status, errorCode, message); @@ -184,4 +202,31 @@ internal static string GetErrorMessageForStatus(int status) else if (status == QUIC_STATUS_CERT_NO_CERT) return "QUIC_STATUS_CERT_NO_CERT"; else return $"Unknown (0x{status:x})"; } + + public static void ValidateErrorCode(string argumentName, long value, [CallerArgumentExpression(nameof(value))] string? propertyName = null) + => ValidateInRange(argumentName, value, QuicDefaults.MaxErrorCodeValue, propertyName); + + public static void ValidateInRange(string argumentName, long value, long max, [CallerArgumentExpression(nameof(value))] string? propertyName = null) + { + if (value < 0 || value > max) + { + throw new ArgumentOutOfRangeException(argumentName, value, SR.Format(SR.net_quic_in_range, propertyName, max)); + } + } + + public static void ValidateTimeSpan(string argumentName, TimeSpan value, [CallerArgumentExpression(nameof(value))] string? propertyName = null) + { + if (value < TimeSpan.Zero && value != Timeout.InfiniteTimeSpan) + { + throw new ArgumentOutOfRangeException(argumentName, value, SR.Format(SR.net_quic_timeout_use_gt_zero, propertyName)); + } + } + + public static void ValidateNotNull(string argumentName, string resourceName, object value, [CallerArgumentExpression(nameof(value))] string? propertyName = null) + { + if (value is null) + { + throw new ArgumentNullException(argumentName, SR.Format(resourceName, propertyName)); + } + } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/QUIC_SETTINGS.IEquattable.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/QUIC_SETTINGS.IEquattable.cs new file mode 100644 index 000000000000..3f008c74136d --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/QUIC_SETTINGS.IEquattable.cs @@ -0,0 +1,94 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.Quic; + +internal partial struct QUIC_SETTINGS : System.IEquatable +{ + // Because QUIC_SETTINGS may contain gaps due to layout/alignment of individual + // fields, we implement IEquatable manually. If a new field is added, + // then there is a unit test which should fail. + + public readonly bool Equals(QUIC_SETTINGS other) + { + return Anonymous1.IsSetFlags == other.Anonymous1.IsSetFlags + && MaxBytesPerKey == other.MaxBytesPerKey + && HandshakeIdleTimeoutMs == other.HandshakeIdleTimeoutMs + && IdleTimeoutMs == other.IdleTimeoutMs + && MtuDiscoverySearchCompleteTimeoutUs == other.MtuDiscoverySearchCompleteTimeoutUs + && TlsClientMaxSendBuffer == other.TlsClientMaxSendBuffer + && TlsServerMaxSendBuffer == other.TlsServerMaxSendBuffer + && StreamRecvWindowDefault == other.StreamRecvWindowDefault + && StreamRecvBufferDefault == other.StreamRecvBufferDefault + && ConnFlowControlWindow == other.ConnFlowControlWindow + && MaxWorkerQueueDelayUs == other.MaxWorkerQueueDelayUs + && MaxStatelessOperations == other.MaxStatelessOperations + && InitialWindowPackets == other.InitialWindowPackets + && SendIdleTimeoutMs == other.SendIdleTimeoutMs + && InitialRttMs == other.InitialRttMs + && MaxAckDelayMs == other.MaxAckDelayMs + && DisconnectTimeoutMs == other.DisconnectTimeoutMs + && KeepAliveIntervalMs == other.KeepAliveIntervalMs + && CongestionControlAlgorithm == other.CongestionControlAlgorithm + && PeerBidiStreamCount == other.PeerBidiStreamCount + && PeerUnidiStreamCount == other.PeerUnidiStreamCount + && MaxBindingStatelessOperations == other.MaxBindingStatelessOperations + && StatelessOperationExpirationMs == other.StatelessOperationExpirationMs + && MinimumMtu == other.MinimumMtu + && MaximumMtu == other.MaximumMtu + && _bitfield == other._bitfield + && MaxOperationsPerDrain == other.MaxOperationsPerDrain + && MtuDiscoveryMissingProbeCount == other.MtuDiscoveryMissingProbeCount + && DestCidUpdateIdleTimeoutMs == other.DestCidUpdateIdleTimeoutMs + && Anonymous2.Flags == other.Anonymous2.Flags + && StreamRecvWindowBidiLocalDefault == other.StreamRecvWindowBidiLocalDefault + && StreamRecvWindowBidiRemoteDefault == other.StreamRecvWindowBidiRemoteDefault + && StreamRecvWindowUnidiDefault == other.StreamRecvWindowUnidiDefault; + } + + public override readonly int GetHashCode() + { + HashCode hash = default; + hash.Add(Anonymous1.IsSetFlags); + hash.Add(MaxBytesPerKey); + hash.Add(HandshakeIdleTimeoutMs); + hash.Add(IdleTimeoutMs); + hash.Add(MtuDiscoverySearchCompleteTimeoutUs); + hash.Add(TlsClientMaxSendBuffer); + hash.Add(TlsServerMaxSendBuffer); + hash.Add(StreamRecvWindowDefault); + hash.Add(StreamRecvBufferDefault); + hash.Add(ConnFlowControlWindow); + hash.Add(MaxWorkerQueueDelayUs); + hash.Add(MaxStatelessOperations); + hash.Add(InitialWindowPackets); + hash.Add(SendIdleTimeoutMs); + hash.Add(InitialRttMs); + hash.Add(MaxAckDelayMs); + hash.Add(DisconnectTimeoutMs); + hash.Add(KeepAliveIntervalMs); + hash.Add(CongestionControlAlgorithm); + hash.Add(PeerBidiStreamCount); + hash.Add(PeerUnidiStreamCount); + hash.Add(MaxBindingStatelessOperations); + hash.Add(StatelessOperationExpirationMs); + hash.Add(MinimumMtu); + hash.Add(MaximumMtu); + hash.Add(_bitfield); + hash.Add(MaxOperationsPerDrain); + hash.Add(MtuDiscoveryMissingProbeCount); + hash.Add(DestCidUpdateIdleTimeoutMs); + hash.Add(Anonymous2.Flags); + hash.Add(StreamRecvWindowBidiLocalDefault); + hash.Add(StreamRecvWindowBidiRemoteDefault); + hash.Add(StreamRecvWindowUnidiDefault); + return hash.ToHashCode(); + } + + public override readonly bool Equals(object? obj) + { + return obj is QUIC_SETTINGS other && Equals(other); + } +} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/msquic.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/msquic.cs index 26296b1f6a89..29b4c822d623 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/msquic.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/msquic.cs @@ -20,7 +20,7 @@ namespace Microsoft.Quic { internal unsafe partial struct QUIC_BUFFER { - public Span Span => new(Buffer, (int)Length); + public readonly Span Span => new(Buffer, (int)Length); } internal partial class MsQuic diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/NetEventSource.Quic.Counters.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/NetEventSource.Quic.Counters.cs index 93ec7e7532c7..a7a392858c89 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/NetEventSource.Quic.Counters.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/NetEventSource.Quic.Counters.cs @@ -14,7 +14,7 @@ namespace System.Net { internal sealed partial class NetEventSource { - private static Meter s_meter = new Meter("Private.InternalDiagnostics.System.Net.Quic.MsQuic"); + private static readonly Meter s_meter = new Meter("Private.InternalDiagnostics.System.Net.Quic.MsQuic"); private static long s_countersLastFetched; private static readonly long[] s_counters = new long[(int)QUIC_PERFORMANCE_COUNTERS.MAX]; public static readonly ObservableCounter s_CONN_CREATED = s_meter.CreateObservableCounter( diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs index 0846543a6aee..3316fc8050d3 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs @@ -108,6 +108,11 @@ static async ValueTask StartConnectAsync(QuicClientConnectionOpt /// private int _disposed; + /// + /// Completed when connection shutdown is initiated. + /// + private TaskCompletionSource _connectionCloseTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + private readonly ValueTaskSource _connectedTcs = new ValueTaskSource(); private readonly ResettableValueTaskSource _shutdownTcs = new ResettableValueTaskSource() { @@ -187,13 +192,11 @@ static async ValueTask StartConnectAsync(QuicClientConnectionOpt ///
    private SslApplicationProtocol _negotiatedApplicationProtocol; -#if DEBUG /// /// Will contain TLS secret after CONNECTED event is received and store it into SSLKEYLOGFILE. /// MsQuic holds the underlying pointer so this object can be disposed only after connection native handle gets closed. /// private readonly MsQuicTlsSecret? _tlsSecret; -#endif /// /// The remote endpoint used for this connection. @@ -254,9 +257,12 @@ private unsafe QuicConnection() throw; } -#if DEBUG + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} New outbound connection."); + } + _tlsSecret = MsQuicTlsSecret.Create(_handle); -#endif } /// @@ -284,9 +290,7 @@ internal unsafe QuicConnection(QUIC_HANDLE* handle, QUIC_NEW_CONNECTION_INFO* in _remoteEndPoint = MsQuicHelpers.QuicAddrToIPEndPoint(info->RemoteAddress); _localEndPoint = MsQuicHelpers.QuicAddrToIPEndPoint(info->LocalAddress); -#if DEBUG _tlsSecret = MsQuicTlsSecret.Create(_handle); -#endif } private async ValueTask FinishConnectAsync(QuicClientConnectionOptions options, CancellationToken cancellationToken = default) @@ -417,9 +421,15 @@ public async ValueTask OpenOutboundStreamAsync(QuicStreamType type, try { stream = new QuicStream(_handle, type, _defaultStreamErrorCode); + + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} New outbound {type} stream {stream}."); + } + await stream.StartAsync(cancellationToken).ConfigureAwait(false); } - catch + catch (Exception ex) { if (stream is not null) { @@ -428,10 +438,16 @@ public async ValueTask OpenOutboundStreamAsync(QuicStreamType type, // Propagate ODE if disposed in the meantime. ObjectDisposedException.ThrowIf(_disposed == 1, this); + + // In case of an incoming race when the connection is closed by the peer just before we open the stream, + // we receive QUIC_STATUS_ABORTED from MsQuic, but we don't know how the connection was closed. We throw + // special exception and handle it here where we can determine the shutdown reason. + bool connectionAbortedByPeer = ThrowHelper.IsConnectionAbortedWhenStartingStreamException(ex); + // Propagate connection error if present. - if (_acceptQueue.Reader.Completion.IsFaulted) + if (_connectionCloseTcs.Task.IsFaulted || connectionAbortedByPeer) { - await _acceptQueue.Reader.Completion.ConfigureAwait(false); + await _connectionCloseTcs.Task.ConfigureAwait(false); } throw; } @@ -485,9 +501,15 @@ public async ValueTask AcceptInboundStreamAsync(CancellationToken ca public ValueTask CloseAsync(long errorCode, CancellationToken cancellationToken = default) { ObjectDisposedException.ThrowIf(_disposed == 1, this); + ThrowHelper.ValidateErrorCode(nameof(errorCode), errorCode, $"{nameof(CloseAsync)}.{nameof(errorCode)}"); if (_shutdownTcs.TryGetValueTask(out ValueTask valueTask, this, cancellationToken)) { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} Closing connection, Error code = {errorCode}"); + } + unsafe { MsQuicApi.Api.ConnectionShutdown( @@ -510,9 +532,8 @@ private unsafe int HandleEventConnected(ref CONNECTED_DATA data) QuicAddr localAddress = MsQuicHelpers.GetMsQuicParameter(_handle, QUIC_PARAM_CONN_LOCAL_ADDRESS); _localEndPoint = MsQuicHelpers.QuicAddrToIPEndPoint(&localAddress); -#if DEBUG + // Final (1-RTT) secrets have been derived, log them if desired to allow decrypting application traffic. _tlsSecret?.WriteSecret(); -#endif if (NetEventSource.Log.IsEnabled()) { @@ -525,17 +546,24 @@ private unsafe int HandleEventShutdownInitiatedByTransport(ref SHUTDOWN_INITIATE { Exception exception = ExceptionDispatchInfo.SetCurrentStackTrace(ThrowHelper.GetExceptionForMsQuicStatus(data.Status, (long)data.ErrorCode)); _connectedTcs.TrySetException(exception); + _connectionCloseTcs.TrySetException(exception); _acceptQueue.Writer.TryComplete(exception); return QUIC_STATUS_SUCCESS; } private unsafe int HandleEventShutdownInitiatedByPeer(ref SHUTDOWN_INITIATED_BY_PEER_DATA data) { - _acceptQueue.Writer.TryComplete(ExceptionDispatchInfo.SetCurrentStackTrace(ThrowHelper.GetConnectionAbortedException((long)data.ErrorCode))); + Exception exception = ExceptionDispatchInfo.SetCurrentStackTrace(ThrowHelper.GetConnectionAbortedException((long)data.ErrorCode)); + _connectionCloseTcs.TrySetException(exception); + _acceptQueue.Writer.TryComplete(exception); return QUIC_STATUS_SUCCESS; } private unsafe int HandleEventShutdownComplete() { + // make sure we log at least some secrets in case of shutdown before handshake completes. + _tlsSecret?.WriteSecret(); + Exception exception = ExceptionDispatchInfo.SetCurrentStackTrace(_disposed == 1 ? new ObjectDisposedException(GetType().FullName) : ThrowHelper.GetOperationAbortedException()); + _connectionCloseTcs.TrySetException(exception); _acceptQueue.Writer.TryComplete(exception); _connectedTcs.TrySetException(exception); _shutdownTokenSource.Cancel(); @@ -555,6 +583,13 @@ private unsafe int HandleEventPeerAddressChanged(ref PEER_ADDRESS_CHANGED_DATA d private unsafe int HandleEventPeerStreamStarted(ref PEER_STREAM_STARTED_DATA data) { QuicStream stream = new QuicStream(_handle, data.Stream, data.Flags, _defaultStreamErrorCode); + + if (NetEventSource.Log.IsEnabled()) + { + QuicStreamType type = data.Flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? QuicStreamType.Unidirectional : QuicStreamType.Bidirectional; + NetEventSource.Info(this, $"{this} New inbound {type} stream {stream}, Id = {stream.Id}."); + } + if (!_acceptQueue.Writer.TryWrite(stream)) { if (NetEventSource.Log.IsEnabled()) @@ -578,6 +613,9 @@ private unsafe int HandleEventPeerCertificateReceived(ref PEER_CERTIFICATE_RECEI // worker threads. // + // Handshake keys should be available by now, log them now if desired. + _tlsSecret?.WriteSecret(); + var task = _sslConnectionOptions.StartAsyncCertificateValidation((IntPtr)data.Certificate, (IntPtr)data.Chain); if (task.IsCompletedSuccessfully) { @@ -649,6 +687,11 @@ public async ValueTask DisposeAsync() return; } + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} Disposing."); + } + // Check if the connection has been shut down and if not, shut it down. if (_shutdownTcs.TryGetValueTask(out ValueTask valueTask, this)) { diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnectionOptions.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnectionOptions.cs index 81a20eacad95..b2d3b0d811f8 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnectionOptions.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnectionOptions.cs @@ -4,6 +4,7 @@ using System.Net.Security; using System.Runtime.CompilerServices; using System.Threading; +using static System.Net.Quic.ThrowHelper; namespace System.Net.Quic; @@ -97,15 +98,15 @@ internal QuicConnectionOptions() // We can safely use this to distinguish if user provided value during validation. public long DefaultCloseErrorCode { get; set; } = -1; - internal QuicReceiveWindowSizes? _initialRecieveWindowSizes; + internal QuicReceiveWindowSizes? _initialReceiveWindowSizes; /// /// The initial receive window sizes for the connection and individual stream types. /// public QuicReceiveWindowSizes InitialReceiveWindowSizes { - get => _initialRecieveWindowSizes ??= new QuicReceiveWindowSizes(); - set => _initialRecieveWindowSizes = value; + get => _initialReceiveWindowSizes ??= new QuicReceiveWindowSizes(); + set => _initialReceiveWindowSizes = value; } /// @@ -131,29 +132,13 @@ internal virtual void Validate(string argumentName) { ValidateInRange(argumentName, MaxInboundBidirectionalStreams, ushort.MaxValue); ValidateInRange(argumentName, MaxInboundUnidirectionalStreams, ushort.MaxValue); - ValidateTimespan(argumentName, IdleTimeout); - ValidateTimespan(argumentName, KeepAliveInterval); - ValidateInRange(argumentName, DefaultCloseErrorCode, QuicDefaults.MaxErrorCodeValue); - ValidateInRange(argumentName, DefaultStreamErrorCode, QuicDefaults.MaxErrorCodeValue); - ValidateTimespan(argumentName, HandshakeTimeout); + ValidateTimeSpan(argumentName, IdleTimeout); + ValidateTimeSpan(argumentName, KeepAliveInterval); + ValidateErrorCode(argumentName, DefaultCloseErrorCode); + ValidateErrorCode(argumentName, DefaultStreamErrorCode); + ValidateTimeSpan(argumentName, HandshakeTimeout); - _initialRecieveWindowSizes?.Validate(argumentName); - - static void ValidateInRange(string argumentName, long value, long max, [CallerArgumentExpression(nameof(value))] string? propertyName = null) - { - if (value < 0 || value > max) - { - throw new ArgumentOutOfRangeException(argumentName, value, SR.Format(SR.net_quic_in_range, propertyName, max)); - } - } - - static void ValidateTimespan(string argumentName, TimeSpan value, [CallerArgumentExpression(nameof(value))] string? propertyName = null) - { - if (value < TimeSpan.Zero && value != Timeout.InfiniteTimeSpan) - { - throw new ArgumentOutOfRangeException(argumentName, value, SR.Format(SR.net_quic_timeout_use_gt_zero, propertyName)); - } - } + _initialReceiveWindowSizes?.Validate(argumentName); } } @@ -197,16 +182,8 @@ internal override void Validate(string argumentName) base.Validate(argumentName); // The content of ClientAuthenticationOptions gets validate in MsQuicConfiguration.Create. - ValidateNotNull(argumentName, ClientAuthenticationOptions); - ValidateNotNull(argumentName, RemoteEndPoint); - - static void ValidateNotNull(string argumentName, object value, [CallerArgumentExpression(nameof(value))] string? propertyName = null) - { - if (value is null) - { - throw new ArgumentNullException(argumentName, SR.Format(SR.net_quic_not_null_open_connection, propertyName)); - } - } + ValidateNotNull(argumentName, SR.net_quic_not_null_open_connection, ClientAuthenticationOptions); + ValidateNotNull(argumentName, SR.net_quic_not_null_open_connection, RemoteEndPoint); } } @@ -239,14 +216,6 @@ internal override void Validate(string argumentName) base.Validate(argumentName); // The content of ServerAuthenticationOptions gets validate in MsQuicConfiguration.Create. - ValidateNotNull(argumentName, ServerAuthenticationOptions); - - static void ValidateNotNull(string argumentName, object value, [CallerArgumentExpression(nameof(value))] string? propertyName = null) - { - if (value is null) - { - throw new ArgumentNullException(argumentName, SR.Format(SR.net_quic_not_null_accept_connection, propertyName)); - } - } + ValidateNotNull(argumentName, SR.net_quic_not_null_accept_connection, ServerAuthenticationOptions); } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicDefaults.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicDefaults.cs index e31bc1d21c20..f2248431d05d 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicDefaults.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicDefaults.cs @@ -41,10 +41,10 @@ internal static partial class QuicDefaults /// /// Default initial_max_data value. /// - public static int DefaultConnectionMaxData = 16 * 1024 * 1024; + public const int DefaultConnectionMaxData = 16 * 1024 * 1024; /// /// Default initial_max_stream_data_* value. /// - public static int DefaultStreamMaxData = 64 * 1024; + public const int DefaultStreamMaxData = 64 * 1024; } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs index 88ea309054a7..249f75715191 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs @@ -335,6 +335,12 @@ private unsafe int HandleEventNewConnection(ref NEW_CONNECTION_DATA data) } QuicConnection connection = new QuicConnection(data.Connection, data.Info); + + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} New inbound connection {connection}."); + } + SslClientHelloInfo clientHello = new SslClientHelloInfo(data.Info->ServerNameLength > 0 ? Marshal.PtrToStringUTF8((IntPtr)data.Info->ServerName, data.Info->ServerNameLength) : "", SslProtocols.Tls13); // Kicks off the rest of the handshake in the background, the process itself will enqueue the result in the accept queue. @@ -404,6 +410,11 @@ public async ValueTask DisposeAsync() return; } + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} Disposing."); + } + // Check if the listener has been shut down and if not, shut it down. if (_shutdownTcs.TryInitialize(out ValueTask valueTask, this)) { diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListenerOptions.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListenerOptions.cs index e65d0bfe4e1b..e5e0e160541c 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListenerOptions.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListenerOptions.cs @@ -5,6 +5,7 @@ using System.Net.Security; using System.Threading; using System.Threading.Tasks; +using static System.Net.Quic.ThrowHelper; namespace System.Net.Quic; @@ -41,21 +42,15 @@ public sealed class QuicListenerOptions /// Name of the from the caller. internal void Validate(string argumentName) { - if (ListenEndPoint is null) - { - throw new ArgumentNullException(SR.Format(SR.net_quic_not_null_listener, nameof(QuicListenerOptions.ListenEndPoint)), argumentName); - } + ValidateNotNull(argumentName, SR.net_quic_not_null_listener, ListenEndPoint); + ValidateNotNull(argumentName, SR.net_quic_not_null_listener, ConnectionOptionsCallback); if (ApplicationProtocols is null || ApplicationProtocols.Count <= 0) { - throw new ArgumentNullException(SR.Format(SR.net_quic_not_null_not_empty_listener, nameof(QuicListenerOptions.ApplicationProtocols)), argumentName); + throw new ArgumentNullException(argumentName, SR.Format(SR.net_quic_not_null_not_empty_listener, nameof(ApplicationProtocols))); } if (ListenBacklog == 0) { ListenBacklog = QuicDefaults.DefaultListenBacklog; } - if (ConnectionOptionsCallback is null) - { - throw new ArgumentNullException(SR.Format(SR.net_quic_not_null_listener, nameof(QuicListenerOptions.ConnectionOptionsCallback)), argumentName); - } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs index 06515f3310bf..55058958a214 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs @@ -162,13 +162,18 @@ internal unsafe QuicStream(MsQuicContextSafeHandle connectionHandle, QuicStreamT try { QUIC_HANDLE* handle; - ThrowHelper.ThrowIfMsQuicError(MsQuicApi.Api.StreamOpen( + int status = MsQuicApi.Api.StreamOpen( connectionHandle, type == QuicStreamType.Unidirectional ? QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL : QUIC_STREAM_OPEN_FLAGS.NONE, &NativeCallback, (void*)GCHandle.ToIntPtr(context), - &handle), - "StreamOpen failed"); + &handle); + + if (ThrowHelper.TryGetStreamExceptionForMsQuicStatus(status, out Exception? ex, streamWasSuccessfullyStarted: false, message: "StreamOpen failed")) + { + throw ex; + } + _handle = new MsQuicContextSafeHandle(handle, context, SafeHandleType.Stream, connectionHandle); _handle.Disposable = _sendBuffers; } @@ -225,6 +230,7 @@ internal unsafe QuicStream(MsQuicContextSafeHandle connectionHandle, QUIC_HANDLE } _id = (long)GetMsQuicParameter(_handle, QUIC_PARAM_STREAM_ID); _type = flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? QuicStreamType.Unidirectional : QuicStreamType.Bidirectional; + _startedTcs.TrySetResult(); } @@ -244,7 +250,8 @@ internal ValueTask StartAsync(CancellationToken cancellationToken = default) int status = MsQuicApi.Api.StreamStart( _handle, QUIC_STREAM_START_FLAGS.SHUTDOWN_ON_FAIL | QUIC_STREAM_START_FLAGS.INDICATE_PEER_ACCEPT); - if (ThrowHelper.TryGetStreamExceptionForMsQuicStatus(status, out Exception? exception)) + + if (ThrowHelper.TryGetStreamExceptionForMsQuicStatus(status, out Exception? exception, streamWasSuccessfullyStarted: false)) { _startedTcs.TrySetException(exception); } @@ -325,6 +332,11 @@ public override async ValueTask ReadAsync(Memory buffer, Cancellation } } + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} Stream read '{totalCopied}' bytes."); + } + return totalCopied; } @@ -434,6 +446,7 @@ public void Abort(QuicAbortDirection abortDirection, long errorCode) { return; } + ThrowHelper.ValidateErrorCode(nameof(errorCode), errorCode, $"{nameof(Abort)}.{nameof(errorCode)}"); QUIC_STREAM_SHUTDOWN_FLAGS flags = QUIC_STREAM_SHUTDOWN_FLAGS.NONE; if (abortDirection.HasFlag(QuicAbortDirection.Read) && !_receiveTcs.IsCompleted) @@ -690,6 +703,11 @@ public override async ValueTask DisposeAsync() return; } + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"{this} Disposing."); + } + // If the stream wasn't started successfully, gracelessly abort it. if (!_startedTcs.IsCompletedSuccessfully) { diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicInteropTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicInteropTests.cs new file mode 100644 index 000000000000..5ffd5b53510d --- /dev/null +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicInteropTests.cs @@ -0,0 +1,74 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Net.Security; +using System.Threading.Tasks; +using System.Runtime.InteropServices; +using System.Reflection; +using System.Linq; +using Xunit; +using Xunit.Abstractions; + +using Microsoft.Quic; + +namespace System.Net.Quic.Tests +{ + public class MsQuicInteropTests + { + private static MemberInfo[] GetMembers() + { + var members = typeof(T).FindMembers(MemberTypes.Field | MemberTypes.Property, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, (mi, _) => + { + if (mi is PropertyInfo property && property.GetSetMethod() == null) + { + return false; + } + + return true; + }, null); + + Assert.NotEmpty(members); + + return members; + } + + private static void ResetMember(MemberInfo member, object instance) + { + switch (member) + { + case FieldInfo field: + field.SetValue(instance, Activator.CreateInstance(field.FieldType)); + break; + case PropertyInfo property: + property.SetValue(instance, Activator.CreateInstance(property.PropertyType)); + break; + default: + throw new InvalidOperationException($"Unexpected member type: {member.MemberType}"); + } + } + + [Fact] + public void QuicSettings_Equals_RespectsAllMembers() + { + QUIC_SETTINGS settings = new QUIC_SETTINGS(); + + // make sure the extension definition is included in compilation + Assert.Contains(typeof(IEquatable), typeof(QUIC_SETTINGS).GetInterfaces()); + + var settingsSpan = MemoryMarshal.AsBytes(new Span(ref settings)); + + // Fill the memory with 1s,we will try to zero out each member and compare + settingsSpan.Fill(0xFF); + + foreach (MemberInfo member in GetMembers()) + { + // copy and box the instance because reflection methods take a reference type arg + object boxed = settings; + ResetMember(member, boxed); + Assert.False(settings.Equals((QUIC_SETTINGS)boxed), $"Member {member.Name} is not compared."); + } + } + } +} diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicRemoteExecutorTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicRemoteExecutorTests.cs index f57f4aef8ec6..d2a40a1f35af 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicRemoteExecutorTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicRemoteExecutorTests.cs @@ -20,27 +20,43 @@ public class MsQuicRemoteExecutorTests : QuicTestBase public MsQuicRemoteExecutorTests() : base(null!) { } - [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] - public void SslKeyLogFile_IsCreatedAndFilled() + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [InlineData(true)] + [InlineData(false)] + public void SslKeyLogFile_IsCreatedAndFilled(bool enabledBySwitch) { - if (PlatformDetection.IsReleaseLibrary(typeof(QuicConnection).Assembly)) + if (PlatformDetection.IsDebugLibrary(typeof(QuicConnection).Assembly) && !enabledBySwitch) { - throw new SkipTestException("Retrieving SSL secrets is not supported in Release mode."); + // AppCtxSwitch is not checked for SSLKEYLOGFILE in Debug builds, the same code path + // will be tested by the enabledBySwitch = true case. Skip it here. + return; } var psi = new ProcessStartInfo(); var tempFile = Path.GetTempFileName(); psi.Environment.Add("SSLKEYLOGFILE", tempFile); - RemoteExecutor.Invoke(async () => + RemoteExecutor.Invoke(async (enabledBySwitch) => { + if (bool.Parse(enabledBySwitch)) + { + AppContext.SetSwitch("System.Net.EnableSslKeyLogging", true); + } + (QuicConnection clientConnection, QuicConnection serverConnection) = await CreateConnectedQuicConnection(); await clientConnection.DisposeAsync(); await serverConnection.DisposeAsync(); - }, new RemoteInvokeOptions { StartInfo = psi }).Dispose(); + } + , enabledBySwitch.ToString(), new RemoteInvokeOptions { StartInfo = psi }).Dispose(); - Assert.True(File.Exists(tempFile)); - Assert.True(File.ReadAllText(tempFile).Length > 0); + if (enabledBySwitch) + { + Assert.True(File.ReadAllText(tempFile).Length > 0); + } + else + { + Assert.True(File.ReadAllText(tempFile).Length == 0); + } } } } diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs index b2042adffe33..41ac5e41da24 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs @@ -357,10 +357,8 @@ public async Task UntrustedClientCertificateFails() } } - static bool SupportsAsyncCertValidation => QuicTestCollection.MsQuicVersion >= new Version(2, 4); - [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/99074", typeof(MsQuicTests), nameof(SupportsAsyncCertValidation))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/99074")] public async Task CertificateCallbackThrowPropagates() { using CancellationTokenSource cts = new CancellationTokenSource(PassingTestTimeout); diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs index 5125b33bec95..3526ab513cd1 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs @@ -94,6 +94,27 @@ await RunClientServer( }); } + [Theory] + [InlineData(-1)] + [InlineData(long.MaxValue)] + [InlineData(long.MinValue)] + public async Task CloseAsync_InvalidCode_Throws(long errorCode) + { + using var sync = new SemaphoreSlim(0); + + await RunClientServer( + clientConnection => + { + Assert.Throws(() => clientConnection.CloseAsync(errorCode)); + sync.Release(); + return Task.CompletedTask; + }, + async serverConnection => + { + await sync.WaitAsync(); + }); + } + [Fact] public async Task Dispose_WithPendingAcceptAndConnect_PendingAndSubsequentThrowOperationAbortedException() { diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs index 5bf718df7308..8f455d61f6a7 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs @@ -52,6 +52,27 @@ await RunClientServer( ); } + [Theory] + [InlineData(-1)] + [InlineData(long.MaxValue)] + [InlineData(long.MinValue)] + public async Task Abort_InvalidCode_Throws(long errorCode) + { + using var sync = new SemaphoreSlim(0); + + await RunClientServer( + async clientConnection => + { + await using var stream = await clientConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); + Assert.Throws(() => stream.Abort(QuicAbortDirection.Both, errorCode)); + sync.Release(); + }, + async serverConnection => + { + await sync.WaitAsync(); + }); + } + [Fact] public async Task MultipleReadsAndWrites() { diff --git a/src/libraries/System.Net.Requests/src/System/Net/HttpWebRequest.cs b/src/libraries/System.Net.Requests/src/System/Net/HttpWebRequest.cs index 8f37002cf206..7510495533be 100644 --- a/src/libraries/System.Net.Requests/src/System/Net/HttpWebRequest.cs +++ b/src/libraries/System.Net.Requests/src/System/Net/HttpWebRequest.cs @@ -13,10 +13,12 @@ using System.Net.Http.Headers; using System.Net.Security; using System.Net.Sockets; +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; +using System.Security.Principal; using System.Threading; using System.Threading.Tasks; @@ -122,6 +124,7 @@ private sealed class HttpClientParameters public readonly CookieContainer? CookieContainer; public readonly ServicePoint? ServicePoint; public readonly TimeSpan ContinueTimeout; + public readonly TokenImpersonationLevel ImpersonationLevel; public HttpClientParameters(HttpWebRequest webRequest, bool async) { @@ -144,6 +147,7 @@ public HttpClientParameters(HttpWebRequest webRequest, bool async) CookieContainer = webRequest._cookieContainer; ServicePoint = webRequest._servicePoint; ContinueTimeout = TimeSpan.FromMilliseconds(webRequest.ContinueTimeout); + ImpersonationLevel = webRequest.ImpersonationLevel; } public bool Matches(HttpClientParameters requestParameters) @@ -164,7 +168,8 @@ public bool Matches(HttpClientParameters requestParameters) && ReferenceEquals(ServerCertificateValidationCallback, requestParameters.ServerCertificateValidationCallback) && ReferenceEquals(ClientCertificates, requestParameters.ClientCertificates) && ReferenceEquals(CookieContainer, requestParameters.CookieContainer) - && ReferenceEquals(ServicePoint, requestParameters.ServicePoint); + && ReferenceEquals(ServicePoint, requestParameters.ServicePoint) + && ImpersonationLevel == requestParameters.ImpersonationLevel; } public bool AreParametersAcceptableForCaching() @@ -1666,6 +1671,17 @@ private static HttpClient CreateHttpClient(HttpClientParameters parameters, Http handler.Expect100ContinueTimeout = parameters.ContinueTimeout; client.Timeout = parameters.Timeout; + if (request != null && request.ImpersonationLevel != TokenImpersonationLevel.None) + { + // This is legacy feature and we don't have public API at the moment. + // So we want to process it only if explicitly set. + var settings = typeof(SocketsHttpHandler).GetField("_settings", BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(handler); + Debug.Assert(settings != null); + FieldInfo? fi = Type.GetType("System.Net.Http.HttpConnectionSettings, System.Net.Http")?.GetField("_impersonationLevel", BindingFlags.NonPublic | BindingFlags.Instance); + Debug.Assert(fi != null); + fi.SetValue(settings, request.ImpersonationLevel); + } + if (parameters.CookieContainer != null) { handler.CookieContainer = parameters.CookieContainer; diff --git a/src/libraries/System.Net.Requests/src/System/Net/WebRequest.cs b/src/libraries/System.Net.Requests/src/System/Net/WebRequest.cs index e33ffea0fa14..5442fdeef0fa 100644 --- a/src/libraries/System.Net.Requests/src/System/Net/WebRequest.cs +++ b/src/libraries/System.Net.Requests/src/System/Net/WebRequest.cs @@ -376,7 +376,7 @@ internal static List PrefixList public AuthenticationLevel AuthenticationLevel { get; set; } = AuthenticationLevel.MutualAuthRequested; - public TokenImpersonationLevel ImpersonationLevel { get; set; } = TokenImpersonationLevel.Delegation; + public TokenImpersonationLevel ImpersonationLevel { get; set; } = TokenImpersonationLevel.None; public virtual string? ConnectionGroupName { diff --git a/src/libraries/System.Net.Requests/tests/HttpWebRequestTest.cs b/src/libraries/System.Net.Requests/tests/HttpWebRequestTest.cs index 54ad032277d8..c6d693cdf500 100644 --- a/src/libraries/System.Net.Requests/tests/HttpWebRequestTest.cs +++ b/src/libraries/System.Net.Requests/tests/HttpWebRequestTest.cs @@ -8,11 +8,11 @@ using System.Linq; using System.Net.Cache; using System.Net.Http; -using System.Net.Http.Functional.Tests; using System.Net.Sockets; using System.Net.Test.Common; using System.Runtime.Serialization.Formatters.Binary; using System.Security.Cryptography.X509Certificates; +using System.Security.Principal; using System.Text; using System.Text.Json; using System.Threading; @@ -1067,6 +1067,25 @@ public void ReadWriteTimeout_NegativeOrZeroValue_Fail() Assert.Throws(() => { request.ReadWriteTimeout = -10; }); } + [Theory] + [InlineData(TokenImpersonationLevel.Delegation)] + [InlineData(TokenImpersonationLevel.Impersonation)] + public async Task ImpersonationLevel_NonDefault_Ok(TokenImpersonationLevel impersonationLevel) + { + await LoopbackServer.CreateClientAndServerAsync(async uri => + { + HttpWebRequest request = WebRequest.CreateHttp(uri); + request.UseDefaultCredentials = true; + // We really don't test the functionality here. + // We need to trigger the Reflection part to make sure it works + // e.g. verify that it was not trimmed away or broken by refactoring. + request.ImpersonationLevel = impersonationLevel; + + using WebResponse response = await GetResponseAsync(request); + Assert.True(request.HaveResponse); + }, server => server.HandleRequestAsync()); + } + [OuterLoop("Uses timeout")] [Theory] [InlineData(false)] diff --git a/src/libraries/System.Net.Security/src/System.Net.Security.csproj b/src/libraries/System.Net.Security/src/System.Net.Security.csproj index 9a7fd09fd88b..e6650f80670e 100644 --- a/src/libraries/System.Net.Security/src/System.Net.Security.csproj +++ b/src/libraries/System.Net.Security/src/System.Net.Security.csproj @@ -387,6 +387,8 @@ Link="Common\Microsoft\Win32\SafeHandles\SafeHandleCache.cs" /> + diff --git a/src/libraries/System.Net.Security/src/System/Net/CertificateValidationPal.Windows.cs b/src/libraries/System.Net.Security/src/System/Net/CertificateValidationPal.Windows.cs index 27224b4e4be0..53437a623225 100644 --- a/src/libraries/System.Net.Security/src/System/Net/CertificateValidationPal.Windows.cs +++ b/src/libraries/System.Net.Security/src/System/Net/CertificateValidationPal.Windows.cs @@ -105,7 +105,7 @@ internal static bool IsLocalCertificateUsed(SafeFreeCredentials? _credentialsHan // This is TLS Resumed session. Windows can fail to query the local cert bellow. // Instead, we will determine the usage form used credentials. SafeFreeCredential_SECURITY creds = (SafeFreeCredential_SECURITY)_credentialsHandle!; - return creds.LocalCertificate != null; + return creds.HasLocalCertificate; } SafeFreeCertContext? localContext = null; diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicy.cs b/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicy.cs index 8b3d6a0aaf1f..2dd83bfe4d20 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicy.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicy.cs @@ -13,7 +13,7 @@ namespace System.Net.Security [UnsupportedOSPlatform("android")] public sealed partial class CipherSuitesPolicy { - internal CipherSuitesPolicyPal Pal { get; private set; } + internal CipherSuitesPolicyPal Pal { get; } [CLSCompliant(false)] public CipherSuitesPolicy(IEnumerable allowedCipherSuites) diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicyPal.Android.cs b/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicyPal.Android.cs index b96c301c7d51..064d5a76fce0 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicyPal.Android.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicyPal.Android.cs @@ -8,7 +8,7 @@ namespace System.Net.Security { internal sealed class CipherSuitesPolicyPal { - internal TlsCipherSuite[] TlsCipherSuites { get; private set; } + internal TlsCipherSuite[] TlsCipherSuites { get; } internal CipherSuitesPolicyPal(IEnumerable allowedCipherSuites) { diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicyPal.OSX.cs b/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicyPal.OSX.cs index 4838e4738a39..bd042c167571 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicyPal.OSX.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicyPal.OSX.cs @@ -8,7 +8,7 @@ namespace System.Net.Security { internal sealed class CipherSuitesPolicyPal { - internal uint[] TlsCipherSuites { get; private set; } + internal uint[] TlsCipherSuites { get; } internal CipherSuitesPolicyPal(IEnumerable allowedCipherSuites) { diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/NetSecurityTelemetry.cs b/src/libraries/System.Net.Security/src/System/Net/Security/NetSecurityTelemetry.cs index a2d4e411e75a..c751742175af 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/NetSecurityTelemetry.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/NetSecurityTelemetry.cs @@ -164,7 +164,6 @@ public void HandshakeFailed(bool isServer, long startingTimestamp, string except HandshakeStop(SslProtocols.None); } -#pragma warning disable IDE0060 // https://github.com/dotnet/roslyn-analyzers/issues/6228 [NonEvent] public void HandshakeCompleted(SslProtocols protocol, long startingTimestamp, bool connectionOpen) { @@ -213,7 +212,6 @@ public void HandshakeCompleted(SslProtocols protocol, long startingTimestamp, bo HandshakeStop(protocol); } -#pragma warning restore IDE0060 // https://github.com/dotnet/roslyn-analyzers/issues/6228 [NonEvent] public void ConnectionClosed(SslProtocols protocol) diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.IO.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.IO.cs index 43e9a42050d3..5a01ee065c2b 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.IO.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.IO.cs @@ -360,6 +360,9 @@ private async Task ForceAuthenticationAsync(bool receiveFirst, byte[ } token.ReleasePayload(); + + // reset the cached flag which has potentially outdated value. + _localClientCertificateUsed = -1; } if (NetEventSource.Log.IsEnabled()) diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Protocol.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Protocol.cs index a3b8b2914404..1fee2be053af 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Protocol.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Protocol.cs @@ -57,6 +57,9 @@ internal static bool DisableTlsResume private X509Certificate2? _remoteCertificate; private bool _remoteCertificateExposed; + // -1 for uninitialized, 0 for false, 1 for true, should be accessed via IsLocalClientCertificateUsed property + private int _localClientCertificateUsed = -1; + // These are the MAX encrypt buffer output sizes, not the actual sizes. private int _headerSize = 5; //ATTN must be set to at least 5 by default private int _trailerSize = 16; @@ -82,11 +85,28 @@ internal X509Certificate? LocalServerCertificate } } + // IsLocalCertificateUsed is expensive, but it does not change during the lifetime of the SslStream except for renegotiation, so we + // can cache the value. + private bool IsLocalClientCertificateUsed + { + get + { + if (_localClientCertificateUsed == -1) + { + _localClientCertificateUsed = CertificateValidationPal.IsLocalCertificateUsed(_credentialsHandle, _securityContext!) + ? 1 + : 0; + } + + return _localClientCertificateUsed == 1; + } + } + internal X509Certificate? LocalClientCertificate { get { - if (_selectedClientCertificate != null && CertificateValidationPal.IsLocalCertificateUsed(_credentialsHandle, _securityContext!)) + if (_selectedClientCertificate != null && IsLocalClientCertificateUsed) { return _selectedClientCertificate; } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamCertificateContext.Linux.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamCertificateContext.Linux.cs index 82ba564cc0a6..6b91066290b6 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamCertificateContext.Linux.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamCertificateContext.Linux.cs @@ -10,6 +10,7 @@ using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; +using System.Net; using System.Threading.Tasks; using Microsoft.Win32.SafeHandles; @@ -115,6 +116,10 @@ partial void AddRootCertificate(X509Certificate2? rootCertificate, ref bool tran if (task.IsCompletedSuccessfully) { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"Got OCSP response."); + } return task.Result; } } @@ -122,6 +127,10 @@ partial void AddRootCertificate(X509Certificate2? rootCertificate, ref bool tran { } + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, "No OCSP response available."); + } return null; } @@ -136,11 +145,19 @@ partial void AddRootCertificate(X509Certificate2? rootCertificate, ref bool tran if (now > _ocspExpiration) { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, "Cached OCSP response expired, fetching fresh staple."); + } return DownloadOcspAsync(); } if (now > _nextDownload) { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, "Starting async refresh of OCSP staple"); + } // Calling DownloadOcsp will activate a Task to initiate // in the background. Further calls will attach to the // same Task if it's still running. @@ -171,6 +188,10 @@ partial void AddRootCertificate(X509Certificate2? rootCertificate, ref bool tran if (pending is not null && !pending.IsFaulted) { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"Pending download task exists."); + } return new ValueTask(pending); } @@ -208,14 +229,18 @@ partial void AddRootCertificate(X509Certificate2? rootCertificate, ref bool tran if (pending is null || pending.IsFaulted) { - _pendingDownload = pending = FetchOcspAsync(); + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"Starting new OCSP download task."); + } + pending = FetchOcspAsync(); } } return new ValueTask(pending); } - private async Task FetchOcspAsync() + private Task FetchOcspAsync() { Debug.Assert(_rootCertificate != null); X509Certificate2? caCert = _privateIntermediateCertificates.Length > 0 ? _privateIntermediateCertificates[0] : _rootCertificate; @@ -235,7 +260,7 @@ partial void AddRootCertificate(X509Certificate2? rootCertificate, ref bool tran if (subject == 0 || issuer == 0) { _staplingForbidden = true; - return null; + return Task.FromResult(null); } IntPtr[] issuerHandles = ArrayPool.Shared.Rent(_privateIntermediateCertificates.Length + 1); @@ -245,64 +270,91 @@ partial void AddRootCertificate(X509Certificate2? rootCertificate, ref bool tran } issuerHandles[_privateIntermediateCertificates.Length] = _rootCertificate.Handle; - using (SafeOcspRequestHandle ocspRequest = Interop.Crypto.X509BuildOcspRequest(subject, issuer)) - { - byte[] rentedBytes = ArrayPool.Shared.Rent(Interop.Crypto.GetOcspRequestDerSize(ocspRequest)); - int encodingSize = Interop.Crypto.EncodeOcspRequest(ocspRequest, rentedBytes); - ArraySegment encoded = new ArraySegment(rentedBytes, 0, encodingSize); + TaskCompletionSource completionSource = new TaskCompletionSource(); - ArraySegment rentedChars = UrlBase64Encoding.RentEncode(encoded); - byte[]? ret = null; + _pendingDownload = completionSource.Task; + FetchOcspAsyncCore(completionSource); + return completionSource.Task; - for (int i = 0; i < _ocspUrls.Count; i++) + async void FetchOcspAsyncCore(TaskCompletionSource completionSource) + { + try { - string url = MakeUrl(_ocspUrls[i], rentedChars); - ret = await System.Net.Http.X509ResourceClient.DownloadAssetAsync(url, TimeSpan.MaxValue).ConfigureAwait(false); + using SafeOcspRequestHandle ocspRequest = Interop.Crypto.X509BuildOcspRequest(subject, issuer); + byte[] rentedBytes = ArrayPool.Shared.Rent(Interop.Crypto.GetOcspRequestDerSize(ocspRequest)); + int encodingSize = Interop.Crypto.EncodeOcspRequest(ocspRequest, rentedBytes); + ArraySegment encoded = new ArraySegment(rentedBytes, 0, encodingSize); - if (ret is not null) + ArraySegment rentedChars = UrlBase64Encoding.RentEncode(encoded); + byte[]? ret = null; + + for (int i = 0; i < _ocspUrls.Count; i++) { - if (!Interop.Crypto.X509DecodeOcspToExpiration(ret, ocspRequest, subject, issuerHandles.AsSpan(0, _privateIntermediateCertificates.Length + 1), out DateTimeOffset expiration)) - { - ret = null; - continue; - } + string url = MakeUrl(_ocspUrls[i], rentedChars); + ret = await System.Net.Http.X509ResourceClient.DownloadAssetAsync(url, TimeSpan.MaxValue).ConfigureAwait(false); - // Swap the working URL in as the first one we'll try next time. - if (i != 0) + if (ret is not null) { - string tmp = _ocspUrls[0]; - _ocspUrls[0] = _ocspUrls[i]; - _ocspUrls[i] = tmp; + if (!Interop.Crypto.X509DecodeOcspToExpiration(ret, ocspRequest, subject, issuerHandles.AsSpan(0, _privateIntermediateCertificates.Length + 1), out DateTimeOffset expiration)) + { + ret = null; + continue; + } + + // Swap the working URL in as the first one we'll try next time. + if (i != 0) + { + string tmp = _ocspUrls[0]; + _ocspUrls[0] = _ocspUrls[i]; + _ocspUrls[i] = tmp; + } + + DateTimeOffset nextCheckA = DateTimeOffset.UtcNow.Add(DefaultOcspRefreshInterval); + DateTimeOffset nextCheckB = expiration.Subtract(MinRefreshBeforeExpirationInterval); + + _ocspResponse = ret; + _ocspExpiration = expiration; + _nextDownload = nextCheckA < nextCheckB ? nextCheckA : nextCheckB; + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"Received {ret.Length} B OCSP response, Expiration: {_ocspExpiration}, Next refresh: {_nextDownload}"); + } + break; } + } - DateTimeOffset nextCheckA = DateTimeOffset.UtcNow.Add(DefaultOcspRefreshInterval); - DateTimeOffset nextCheckB = expiration.Subtract(MinRefreshBeforeExpirationInterval); + issuerHandles.AsSpan().Clear(); + ArrayPool.Shared.Return(issuerHandles); + ArrayPool.Shared.Return(rentedBytes); + ArrayPool.Shared.Return(rentedChars.Array!); + GC.KeepAlive(TargetCertificate); + GC.KeepAlive(_privateIntermediateCertificates); + GC.KeepAlive(_rootCertificate); + GC.KeepAlive(caCert); - _ocspResponse = ret; - _ocspExpiration = expiration; - _nextDownload = nextCheckA < nextCheckB ? nextCheckA : nextCheckB; - break; + if (ret == null) + { + // All download attempts failed, don't try again for 5 seconds. + // This backoff will be applied only if the OCSP staple is not expired. + // If it is expired, we will force-refresh it during next GetOcspResponseAsync call. + _nextDownload = DateTimeOffset.UtcNow.Add(RefreshAfterFailureBackOffInterval); + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, $"OCSP response fetch failed, backing off, Next refresh = {_nextDownload}"); + } } - } - issuerHandles.AsSpan().Clear(); - ArrayPool.Shared.Return(issuerHandles); - ArrayPool.Shared.Return(rentedBytes); - ArrayPool.Shared.Return(rentedChars.Array!); - GC.KeepAlive(TargetCertificate); - GC.KeepAlive(_privateIntermediateCertificates); - GC.KeepAlive(_rootCertificate); - GC.KeepAlive(caCert); - - _pendingDownload = null; - if (ret == null) + _pendingDownload = null; + completionSource.SetResult(ret); + } + catch (Exception ex) { - // All download attempts failed, don't try again for 5 seconds. - // This backoff will be applied only if the OCSP staple is not expired. - // If it is expired, we will force-refresh it during next GetOcspResponseAsync call. - _nextDownload = DateTimeOffset.UtcNow.Add(RefreshAfterFailureBackOffInterval); + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Error(this, $"OCSP refresh failed: {ex}"); + } + completionSource.SetException(ex); } - return ret; } } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs index 63b9aea0e4bd..615ccd01167e 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs @@ -233,8 +233,7 @@ public static SafeFreeCredentials AcquireCredentialsHandle(SslAuthenticationOpti if (newCredentialsRequested && sslAuthenticationOptions.CertificateContext != null) { SafeFreeCredential_SECURITY handle = (SafeFreeCredential_SECURITY)cred; - // We need to create copy to avoid Disposal issue. - handle.LocalCertificate = new X509Certificate2(sslAuthenticationOptions.CertificateContext.TargetCertificate); + handle.HasLocalCertificate = true; } return cred; @@ -362,11 +361,9 @@ public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchCredentials( if (isServer) { direction = Interop.SspiCli.CredentialUse.SECPKG_CRED_INBOUND; - flags = Interop.SspiCli.SCH_CREDENTIALS.Flags.SCH_SEND_AUX_RECORD; - if (authOptions.CertificateContext?.Trust?._sendTrustInHandshake == true) - { - flags |= Interop.SspiCli.SCH_CREDENTIALS.Flags.SCH_CRED_NO_SYSTEM_MAPPER; - } + flags = + Interop.SspiCli.SCH_CREDENTIALS.Flags.SCH_SEND_AUX_RECORD | + Interop.SspiCli.SCH_CREDENTIALS.Flags.SCH_CRED_NO_SYSTEM_MAPPER; if (!allowTlsResume) { // Works only on server diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamRemoteExecutorTests.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamRemoteExecutorTests.cs index d162a54bf921..82cd3114eb47 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamRemoteExecutorTests.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamRemoteExecutorTests.cs @@ -21,21 +21,30 @@ public class SslStreamRemoteExecutorTests public SslStreamRemoteExecutorTests() { } - [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/94843", ~TestPlatforms.Linux)] - public void SslKeyLogFile_IsCreatedAndFilled() + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [PlatformSpecific(TestPlatforms.Linux)] // SSLKEYLOGFILE is only supported on Linux for SslStream + [InlineData(true)] + [InlineData(false)] + public void SslKeyLogFile_IsCreatedAndFilled(bool enabledBySwitch) { - if (PlatformDetection.IsReleaseLibrary(typeof(SslStream).Assembly)) + if (PlatformDetection.IsDebugLibrary(typeof(SslStream).Assembly) && !enabledBySwitch) { - throw new SkipTestException("Retrieving SSL secrets is not supported in Release mode."); + // AppCtxSwitch is not checked for SSLKEYLOGFILE in Debug builds, the same code path + // will be tested by the enabledBySwitch = true case. Skip it here. + return; } var psi = new ProcessStartInfo(); var tempFile = Path.GetTempFileName(); psi.Environment.Add("SSLKEYLOGFILE", tempFile); - RemoteExecutor.Invoke(async () => + RemoteExecutor.Invoke(async (enabledBySwitch) => { + if (bool.Parse(enabledBySwitch)) + { + AppContext.SetSwitch("System.Net.EnableSslKeyLogging", true); + } + (Stream clientStream, Stream serverStream) = TestHelper.GetConnectedStreams(); using (clientStream) using (serverStream) @@ -55,10 +64,16 @@ await TestConfiguration.WhenAllOrAnyFailedWithTimeout( await TestHelper.PingPong(client, server); } - }, new RemoteInvokeOptions { StartInfo = psi }).Dispose(); + }, enabledBySwitch.ToString(), new RemoteInvokeOptions { StartInfo = psi }).Dispose(); - Assert.True(File.Exists(tempFile)); - Assert.True(File.ReadAllText(tempFile).Length > 0); + if (enabledBySwitch) + { + Assert.True(File.ReadAllText(tempFile).Length > 0); + } + else + { + Assert.True(File.ReadAllText(tempFile).Length == 0); + } } } -} \ No newline at end of file +} diff --git a/src/libraries/System.Net.Security/tests/UnitTests/SslStreamCertificateContextOcspLinuxTests.cs b/src/libraries/System.Net.Security/tests/UnitTests/SslStreamCertificateContextOcspLinuxTests.cs index 5e31aafc5cce..7d1f33a32b32 100644 --- a/src/libraries/System.Net.Security/tests/UnitTests/SslStreamCertificateContextOcspLinuxTests.cs +++ b/src/libraries/System.Net.Security/tests/UnitTests/SslStreamCertificateContextOcspLinuxTests.cs @@ -77,7 +77,6 @@ await SimpleTest(PkiOptions.OcspEverywhere, async (root, intermediate, endEntity } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/97836")] public async Task FetchOcspResponse_FirstInvalidThenValid() { await SimpleTest(PkiOptions.OcspEverywhere, async (root, intermediate, endEntity, ctxFactory, responder) => @@ -95,7 +94,6 @@ await SimpleTest(PkiOptions.OcspEverywhere, async (root, intermediate, endEntity } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/97779")] public async Task RefreshOcspResponse_BeforeExpiration() { await SimpleTest(PkiOptions.OcspEverywhere, async (root, intermediate, endEntity, ctxFactory, responder) => @@ -110,12 +108,12 @@ await SimpleTest(PkiOptions.OcspEverywhere, async (root, intermediate, endEntity intermediate.RevocationExpiration = DateTimeOffset.UtcNow.AddDays(1); - // first call will dispatch a download and return the cached response, the first call after - // the pending download finishes will return the updated response - byte[] ocsp2 = ctx.GetOcspResponseNoWaiting(); - Assert.Equal(ocsp, ocsp2); + // First call will dispatch a download. It most likely will return the + // previous cached response, but if the current thread gets delayed + // it may actually return the fresh OCSP staple so we won't check the result + ctx.GetOcspResponseNoWaiting(); - // The download should succeed + // The pending download should eventually succeed byte[] ocsp3 = await ctx.WaitForPendingOcspFetchAsync(); Assert.NotNull(ocsp3); Assert.NotEqual(ocsp, ocsp3); @@ -123,7 +121,6 @@ await SimpleTest(PkiOptions.OcspEverywhere, async (root, intermediate, endEntity } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/97779")] public async Task RefreshOcspResponse_AfterExpiration() { await SimpleTest(PkiOptions.OcspEverywhere, async (root, intermediate, endEntity, ctxFactory, responder) => @@ -139,13 +136,14 @@ await SimpleTest(PkiOptions.OcspEverywhere, async (root, intermediate, endEntity intermediate.RevocationExpiration = DateTimeOffset.UtcNow.AddDays(1); - // The cached OCSP is expired, so the first call will dispatch a download and return the cached response, - byte[] ocsp = ctx.GetOcspResponseNoWaiting(); - Assert.Null(ocsp); + // The cached OCSP is expired, so the first call will dispatch a download. + // It most likely will return null, but if the current thread gets delayed + // it may actually return the fresh OCSP staple so we won't check the result + ctx.GetOcspResponseNoWaiting(); - // The download should succeed - byte[] ocsp2 = await ctx.WaitForPendingOcspFetchAsync(); - Assert.NotNull(ocsp2); + // The pending download should eventually succeed + byte[] ocsp = await ctx.WaitForPendingOcspFetchAsync(); + Assert.NotNull(ocsp); }); } diff --git a/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj b/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj index e3e81ecb61a3..5602fc0cab35 100644 --- a/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj +++ b/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj @@ -121,6 +121,8 @@ Link="Common\Microsoft\Win32\SafeHandles\SafeHandleCache.cs" /> + diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.Unix.cs index 62417e62599b..35e9871bb88a 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.Unix.cs @@ -96,18 +96,10 @@ internal void TrackOption(SocketOptionLevel level, SocketOptionName name) ExposedHandleOrUntrackedConfiguration = true; } - internal SocketAsyncContext AsyncContext - { - get - { - if (Volatile.Read(ref _asyncContext) == null) - { - Interlocked.CompareExchange(ref _asyncContext, new SocketAsyncContext(this), null); - } - - return _asyncContext!; - } - } + internal SocketAsyncContext AsyncContext => + _asyncContext ?? + Interlocked.CompareExchange(ref _asyncContext, new SocketAsyncContext(this), null) ?? + _asyncContext!; /// /// This represents whether the Socket instance is blocking or non-blocking *from the user's point of view*, diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs index a8c95005154c..646c71d62994 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs @@ -1909,8 +1909,6 @@ public int ReceiveFrom(Span buffer, SocketFlags socketFlags, SocketAddress int bytesTransferred; SocketError errorCode = SocketPal.ReceiveFrom(_handle, buffer, socketFlags, receivedAddress.Buffer, out int socketAddressSize, out bytesTransferred); - receivedAddress.Size = socketAddressSize; - UpdateReceiveSocketErrorForDisposed(ref errorCode, bytesTransferred); // If the native call fails we'll throw a SocketException. if (errorCode != SocketError.Success) @@ -1927,6 +1925,7 @@ public int ReceiveFrom(Span buffer, SocketFlags socketFlags, SocketAddress if (SocketType == SocketType.Dgram) SocketsTelemetry.Log.DatagramReceived(); } + receivedAddress.Size = socketAddressSize; return bytesTransferred; } @@ -3754,7 +3753,7 @@ internal void UpdateStatusAfterSocketError(SocketError errorCode, bool disconnec if (disconnectOnFailure && _isConnected && (_handle.IsInvalid || (errorCode != SocketError.WouldBlock && errorCode != SocketError.IOPending && errorCode != SocketError.NoBufferSpaceAvailable && - errorCode != SocketError.TimedOut))) + errorCode != SocketError.TimedOut && errorCode != SocketError.OperationAborted))) { // The socket is no longer a valid socket. if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, "Invalidating socket."); diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UDPClient.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UDPClient.cs index 7646d0ae458d..8d628720d7e4 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UDPClient.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UDPClient.cs @@ -379,14 +379,7 @@ public byte[] EndReceive(IAsyncResult asyncResult, ref IPEndPoint? remoteEP) // Because we don't return the actual length, we need to ensure the returned buffer // has the appropriate length. - if (received < MaxUDPSize) - { - byte[] newBuffer = new byte[received]; - Buffer.BlockCopy(_buffer, 0, newBuffer, 0, received); - return newBuffer; - } - - return _buffer; + return _buffer.AsSpan(0, received).ToArray(); } // Joins a multicast address group. @@ -623,11 +616,7 @@ public Task ReceiveAsync() async Task WaitAndWrap(Task task) { SocketReceiveFromResult result = await task.ConfigureAwait(false); - - byte[] buffer = result.ReceivedBytes < MaxUDPSize ? - _buffer.AsSpan(0, result.ReceivedBytes).ToArray() : - _buffer; - + byte[] buffer = _buffer.AsSpan(0, result.ReceivedBytes).ToArray(); return new UdpReceiveResult(buffer, (IPEndPoint)result.RemoteEndPoint); } } @@ -653,11 +642,7 @@ public ValueTask ReceiveAsync(CancellationToken cancellationTo async ValueTask WaitAndWrap(ValueTask task) { SocketReceiveFromResult result = await task.ConfigureAwait(false); - - byte[] buffer = result.ReceivedBytes < MaxUDPSize ? - _buffer.AsSpan(0, result.ReceivedBytes).ToArray() : - _buffer; - + byte[] buffer = _buffer.AsSpan(0, result.ReceivedBytes).ToArray(); return new UdpReceiveResult(buffer, (IPEndPoint)result.RemoteEndPoint); } } @@ -845,14 +830,7 @@ public byte[] Receive([NotNull] ref IPEndPoint? remoteEP) // because we don't return the actual length, we need to ensure the returned buffer // has the appropriate length. - - if (received < MaxUDPSize) - { - byte[] newBuffer = new byte[received]; - Buffer.BlockCopy(_buffer, 0, newBuffer, 0, received); - return newBuffer; - } - return _buffer; + return _buffer.AsSpan(0, received).ToArray(); } diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs index 52022c5da821..a2df38adac5d 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs @@ -547,7 +547,7 @@ private static async Task RunWithConnectedNetworkStreamsAsync(Func(new byte[1]), new IPEndPoint(address, ((IPEndPoint)receiver.Client.LocalEndPoint).Port)); - AssertReceive(receiver); + sender.Send(new ReadOnlySpan(data), new IPEndPoint(address, ((IPEndPoint)receiver.Client.LocalEndPoint).Port)); + AssertReceive(receiver, data); } } @@ -536,11 +538,12 @@ public void Send_Receive_With_HostName_Success(bool ipv4) using (var receiver = new UdpClient(new IPEndPoint(address, 0))) using (var sender = new UdpClient(new IPEndPoint(address, 0))) { - sender.Send(new byte[1], 1, "localhost", ((IPEndPoint)receiver.Client.LocalEndPoint).Port); - AssertReceive(receiver); + byte[] data = [1, 2, 3]; + sender.Send(data, 2, "localhost", ((IPEndPoint)receiver.Client.LocalEndPoint).Port); + AssertReceive(receiver, [1, 2]); - sender.Send(new ReadOnlySpan(new byte[1]), "localhost", ((IPEndPoint)receiver.Client.LocalEndPoint).Port); - AssertReceive(receiver); + sender.Send(new ReadOnlySpan(data), "localhost", ((IPEndPoint)receiver.Client.LocalEndPoint).Port); + AssertReceive(receiver, data); } } @@ -551,20 +554,22 @@ public void Send_Receive_Connected_Success() using (var receiver = new UdpClient("localhost", 0)) using (var sender = new UdpClient("localhost", ((IPEndPoint)receiver.Client.LocalEndPoint).Port)) { - sender.Send(new byte[1], 1); - AssertReceive(receiver); + byte[] data = [1, 2, 3]; + + sender.Send(data, 2); + AssertReceive(receiver, [1, 2]); - sender.Send(new ReadOnlySpan(new byte[1])); - AssertReceive(receiver); + sender.Send(new ReadOnlySpan(data)); + AssertReceive(receiver, data); } } - private static void AssertReceive(UdpClient receiver) + private static void AssertReceive(UdpClient receiver, byte[] sentData) { IPEndPoint remoteEP = null; byte[] data = receiver.Receive(ref remoteEP); Assert.NotNull(remoteEP); - Assert.InRange(data.Length, 1, int.MaxValue); + Assert.True(Enumerable.SequenceEqual(sentData, data)); } [Theory] @@ -589,16 +594,17 @@ public void Send_Available_Success(bool ipv4) public void BeginEndSend_BeginEndReceive_Success(bool ipv4) { IPAddress address = ipv4 ? IPAddress.Loopback : IPAddress.IPv6Loopback; + byte[] data = [1, 2, 3]; using (var receiver = new UdpClient(new IPEndPoint(address, 0))) using (var sender = new UdpClient(new IPEndPoint(address, 0))) { - sender.EndSend(sender.BeginSend(new byte[1], 1, new IPEndPoint(address, ((IPEndPoint)receiver.Client.LocalEndPoint).Port), null, null)); + sender.EndSend(sender.BeginSend(data, 2, new IPEndPoint(address, ((IPEndPoint)receiver.Client.LocalEndPoint).Port), null, null)); IPEndPoint remoteEP = null; - byte[] data = receiver.EndReceive(receiver.BeginReceive(null, null), ref remoteEP); + byte[] receivedData = receiver.EndReceive(receiver.BeginReceive(null, null), ref remoteEP); Assert.NotNull(remoteEP); - Assert.InRange(data.Length, 1, int.MaxValue); + Assert.True(Enumerable.SequenceEqual(receivedData, new byte[] {1, 2})); } } @@ -606,15 +612,17 @@ public void BeginEndSend_BeginEndReceive_Success(bool ipv4) [PlatformSpecific(TestPlatforms.Windows)] // "localhost" resolves to IPv4 & IPV6 on Windows, but may resolve to only one of those on Unix public void BeginEndSend_BeginEndReceive_Connected_Success() { + byte[] data = [1, 2, 3]; + using (var receiver = new UdpClient("localhost", 0)) using (var sender = new UdpClient("localhost", ((IPEndPoint)receiver.Client.LocalEndPoint).Port)) { - sender.EndSend(sender.BeginSend(new byte[1], 1, null, null)); + sender.EndSend(sender.BeginSend(data, 2, null, null)); IPEndPoint remoteEP = null; - byte[] data = receiver.EndReceive(receiver.BeginReceive(null, null), ref remoteEP); + byte[] receivedData = receiver.EndReceive(receiver.BeginReceive(null, null), ref remoteEP); Assert.NotNull(remoteEP); - Assert.InRange(data.Length, 1, int.MaxValue); + Assert.True(Enumerable.SequenceEqual(receivedData, new byte[] {1, 2})); } } @@ -624,15 +632,16 @@ public void BeginEndSend_BeginEndReceive_Connected_Success() public async Task SendAsync_ReceiveAsync_Success(bool ipv4) { IPAddress address = ipv4 ? IPAddress.Loopback : IPAddress.IPv6Loopback; + byte[] data = [1, 2, 3]; using (var receiver = new UdpClient(new IPEndPoint(address, 0))) using (var sender = new UdpClient(new IPEndPoint(address, 0))) { - await sender.SendAsync(new byte[1], 1, new IPEndPoint(address, ((IPEndPoint)receiver.Client.LocalEndPoint).Port)); - await AssertReceiveAsync(receiver); + await sender.SendAsync(data, 2, new IPEndPoint(address, ((IPEndPoint)receiver.Client.LocalEndPoint).Port)); + await AssertReceiveAsync(receiver, [1, 2]); - await sender.SendAsync(new ReadOnlyMemory(new byte[1]), new IPEndPoint(address, ((IPEndPoint)receiver.Client.LocalEndPoint).Port)); - await AssertReceiveAsync(receiver); + await sender.SendAsync(new ReadOnlyMemory(data), new IPEndPoint(address, ((IPEndPoint)receiver.Client.LocalEndPoint).Port)); + await AssertReceiveAsync(receiver, data); } } @@ -643,15 +652,16 @@ public async Task SendAsync_ReceiveAsync_Success(bool ipv4) public async Task SendAsync_ReceiveAsync_With_HostName_Success(bool ipv4) { IPAddress address = ipv4 ? IPAddress.Loopback : IPAddress.IPv6Loopback; + byte[] data = [1, 2, 3]; using (var receiver = new UdpClient(new IPEndPoint(address, 0))) using (var sender = new UdpClient(new IPEndPoint(address, 0))) { - await sender.SendAsync(new byte[1], "localhost", ((IPEndPoint)receiver.Client.LocalEndPoint).Port); - await AssertReceiveAsync(receiver); + await sender.SendAsync(data, "localhost", ((IPEndPoint)receiver.Client.LocalEndPoint).Port); + await AssertReceiveAsync(receiver, data); - await sender.SendAsync(new ReadOnlyMemory(new byte[1]), "localhost", ((IPEndPoint)receiver.Client.LocalEndPoint).Port); - await AssertReceiveAsync(receiver); + await sender.SendAsync(new ReadOnlyMemory(data), "localhost", ((IPEndPoint)receiver.Client.LocalEndPoint).Port); + await AssertReceiveAsync(receiver, data); } } @@ -675,29 +685,30 @@ public async Task ReceiveAsync_Cancel_Throw(bool ipv4) [PlatformSpecific(TestPlatforms.Windows)] // "localhost" resolves to IPv4 & IPV6 on Windows, but may resolve to only one of those on Unix public async Task SendAsync_ReceiveAsync_Connected_Success() { + byte[] data = [1, 2, 3]; + using (var receiver = new UdpClient("localhost", 0)) using (var sender = new UdpClient("localhost", ((IPEndPoint)receiver.Client.LocalEndPoint).Port)) { - await sender.SendAsync(new byte[1], 1); - await AssertReceiveAsync(receiver); + await sender.SendAsync(data, 2); + await AssertReceiveAsync(receiver, [1, 2]); - await sender.SendAsync(new ReadOnlyMemory(new byte[1])); - await AssertReceiveAsync(receiver); + await sender.SendAsync(new ReadOnlyMemory(data)); + await AssertReceiveAsync(receiver, data); - await sender.SendAsync(new ReadOnlyMemory(new byte[1]), null); - await AssertReceiveAsync(receiver); + await sender.SendAsync(new ReadOnlyMemory(data), null); + await AssertReceiveAsync(receiver, data); - await sender.SendAsync(new ReadOnlyMemory(new byte[1]), null, 0); - await AssertReceiveAsync(receiver); + await sender.SendAsync(new ReadOnlyMemory(data), null, 0); + await AssertReceiveAsync(receiver, data); } } - private static async Task AssertReceiveAsync(UdpClient receiver) + private static async Task AssertReceiveAsync(UdpClient receiver, byte[] sentData) { UdpReceiveResult result = await receiver.ReceiveAsync(); Assert.NotNull(result.RemoteEndPoint); - Assert.NotNull(result.Buffer); - Assert.InRange(result.Buffer.Length, 1, int.MaxValue); + Assert.True(Enumerable.SequenceEqual(sentData, result.Buffer)); } [Fact] diff --git a/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs b/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs index 0c8b94778a58..0dc1775b5734 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs @@ -15,18 +15,13 @@ namespace System.Net.WebSockets.Client.Tests { public class ClientWebSocketTestBase { - public static readonly object[][] EchoServers = System.Net.Test.Common.Configuration.WebSockets.EchoServers; - public static readonly object[][] EchoHeadersServers = System.Net.Test.Common.Configuration.WebSockets.EchoHeadersServers; + public static readonly object[][] EchoServers = System.Net.Test.Common.Configuration.WebSockets.GetEchoServers(); + public static readonly object[][] EchoHeadersServers = System.Net.Test.Common.Configuration.WebSockets.GetEchoHeadersServers(); public static readonly object[][] EchoServersAndBoolean = EchoServers.SelectMany(o => new object[][] { new object[] { o[0], false }, new object[] { o[0], true } }).ToArray(); - public static readonly object[][] SecureEchoServersAndBoolean = new object[][] - { - new object[] { Test.Common.Configuration.WebSockets.SecureRemoteEchoServer, false }, - new object[] { Test.Common.Configuration.WebSockets.SecureRemoteEchoServer, true } - }; public const int TimeOutMilliseconds = 30000; public const int CloseDescriptionMaxLength = 123; diff --git a/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs index 7f44a7a69349..cb5f0f978f76 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.cs @@ -254,6 +254,7 @@ public async Task ConnectAsync_CookieHeaders_Success(Uri server) [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))] [ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoServers))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101115", typeof(PlatformDetection), nameof(PlatformDetection.IsFirefox))] public async Task ConnectAsync_PassNoSubProtocol_ServerRequires_ThrowsWebSocketException(Uri server) { const string AcceptedProtocol = "CustomProtocol"; diff --git a/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj b/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj index 2c7762cc6bc8..057726e2a8a8 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj +++ b/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj @@ -9,7 +9,7 @@ - WasmTestOnBrowser + WasmTestOnChrome $(TestArchiveRoot)browserornodejs/ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ $(DefineConstants);TARGET_BROWSER diff --git a/src/libraries/System.Net.WebSockets.Client/tests/wasm/System.Net.WebSockets.Client.Wasm.Tests.csproj b/src/libraries/System.Net.WebSockets.Client/tests/wasm/System.Net.WebSockets.Client.Wasm.Tests.csproj index 4024dc05baff..c4b8a5a4545e 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/wasm/System.Net.WebSockets.Client.Wasm.Tests.csproj +++ b/src/libraries/System.Net.WebSockets.Client/tests/wasm/System.Net.WebSockets.Client.Wasm.Tests.csproj @@ -9,7 +9,7 @@ --background-throttling - WasmTestOnBrowser + WasmTestOnChrome $(TestArchiveRoot)browseronly/ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ $(DefineConstants);TARGET_BROWSER diff --git a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/Compression/WebSocketInflater.cs b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/Compression/WebSocketInflater.cs index 8e95d5fa32f6..4a25fcb03d10 100644 --- a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/Compression/WebSocketInflater.cs +++ b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/Compression/WebSocketInflater.cs @@ -210,12 +210,12 @@ private void ReleaseBuffer() } } - private static unsafe bool IsFinished(ZLibStreamHandle stream, out byte? remainingByte) + private static bool IsFinished(ZLibStreamHandle stream, out byte? remainingByte) { // There is no other way to make sure that we've consumed all data // but to try to inflate again with at least one byte of output buffer. - byte b; - if (Inflate(stream, new Span(&b, 1), FlushCode.SyncFlush) == 0) + byte b = 0; + if (Inflate(stream, new Span(ref b), FlushCode.SyncFlush) == 0) { remainingByte = null; return true; diff --git a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs index 8de2521373f7..569bc856bca7 100644 --- a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs +++ b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; +using System.Buffers.Binary; using System.Diagnostics; using System.IO; using System.Net.WebSockets.Compression; @@ -288,7 +289,7 @@ public override ValueTask SendAsync(ReadOnlyMemory buffer, WebSocketMessag } catch (Exception exc) { - return new ValueTask(Task.FromException(exc)); + return ValueTask.FromException(exc); } bool endOfMessage = messageFlags.HasFlag(WebSocketMessageFlags.EndOfMessage); @@ -466,10 +467,10 @@ private ValueTask SendFrameLockAcquiredNonCancelableAsync(MessageOpcode opcode, } catch (Exception exc) { - return new ValueTask(Task.FromException( + return ValueTask.FromException( exc is OperationCanceledException ? exc : _state == WebSocketState.Aborted ? CreateOperationCanceledException(exc) : - new WebSocketException(WebSocketError.ConnectionClosedPrematurely, exc))); + new WebSocketException(WebSocketError.ConnectionClosedPrematurely, exc)); } finally { @@ -493,7 +494,7 @@ private async ValueTask WaitForWriteTaskAsync(ValueTask writeTask, bool shouldFl await _stream.FlushAsync().ConfigureAwait(false); } } - catch (Exception exc) when (!(exc is OperationCanceledException)) + catch (Exception exc) when (exc is not OperationCanceledException) { throw _state == WebSocketState.Aborted ? CreateOperationCanceledException(exc) : @@ -518,7 +519,7 @@ private async ValueTask SendFrameFallbackAsync(MessageOpcode opcode, bool endOfM await _stream.FlushAsync(cancellationToken).ConfigureAwait(false); } } - catch (Exception exc) when (!(exc is OperationCanceledException)) + catch (Exception exc) when (exc is not OperationCanceledException) { throw _state == WebSocketState.Aborted ? CreateOperationCanceledException(exc, cancellationToken) : @@ -649,19 +650,13 @@ private static int WriteHeader(MessageOpcode opcode, byte[] sendBuffer, ReadOnly else if (payload.Length <= ushort.MaxValue) { sendBuffer[1] = 126; - sendBuffer[2] = (byte)(payload.Length / 256); - sendBuffer[3] = unchecked((byte)payload.Length); + BinaryPrimitives.WriteUInt16BigEndian(sendBuffer.AsSpan(2), (ushort)payload.Length); maskOffset = 2 + sizeof(ushort); // additional 2 bytes for 16-bit length } else { sendBuffer[1] = 127; - int length = payload.Length; - for (int i = 9; i >= 2; i--) - { - sendBuffer[i] = unchecked((byte)length); - length /= 256; - } + BinaryPrimitives.WriteUInt64BigEndian(sendBuffer.AsSpan(2), (ulong)payload.Length); maskOffset = 2 + sizeof(ulong); // additional 8 bytes for 64-bit length } @@ -976,7 +971,7 @@ private async ValueTask HandleReceivedCloseAsync(MessageHeader header, Cancellat ApplyMask(_receiveBuffer.Span.Slice(_receiveBufferOffset, (int)header.PayloadLength), header.Mask, 0); } - closeStatus = (WebSocketCloseStatus)(_receiveBuffer.Span[_receiveBufferOffset] << 8 | _receiveBuffer.Span[_receiveBufferOffset + 1]); + closeStatus = (WebSocketCloseStatus)BinaryPrimitives.ReadUInt16BigEndian(_receiveBuffer.Span.Slice(_receiveBufferOffset)); if (!IsValidCloseStatus(closeStatus)) { await CloseWithReceiveErrorAndThrowAsync(WebSocketCloseStatus.ProtocolError, WebSocketError.Faulted).ConfigureAwait(false); @@ -1158,17 +1153,13 @@ private async ValueTask CloseWithReceiveErrorAndThrowAsync( if (header.PayloadLength == 126) { Debug.Assert(_receiveBufferCount >= 2, "Expected to have two bytes for the payload length."); - header.PayloadLength = (receiveBufferSpan[_receiveBufferOffset] << 8) | receiveBufferSpan[_receiveBufferOffset + 1]; + header.PayloadLength = BinaryPrimitives.ReadUInt16BigEndian(receiveBufferSpan.Slice(_receiveBufferOffset)); ConsumeFromBuffer(2); } else if (header.PayloadLength == 127) { Debug.Assert(_receiveBufferCount >= 8, "Expected to have eight bytes for the payload length."); - header.PayloadLength = 0; - for (int i = 0; i < 8; i++) - { - header.PayloadLength = (header.PayloadLength << 8) | receiveBufferSpan[_receiveBufferOffset + i]; - } + header.PayloadLength = BinaryPrimitives.ReadInt64BigEndian(receiveBufferSpan.Slice(_receiveBufferOffset)); ConsumeFromBuffer(8); } @@ -1363,9 +1354,7 @@ private async ValueTask SendCloseFrameAsync(WebSocketCloseStatus closeStatus, st Debug.Assert(count - 2 == encodedLength, $"{nameof(s_textEncoding.GetByteCount)} and {nameof(s_textEncoding.GetBytes)} encoded count didn't match"); } - ushort closeStatusValue = (ushort)closeStatus; - buffer[0] = (byte)(closeStatusValue >> 8); - buffer[1] = (byte)(closeStatusValue & 0xFF); + BinaryPrimitives.WriteUInt16BigEndian(buffer, (ushort)closeStatus); await SendFrameAsync(MessageOpcode.Close, endOfMessage: true, disableCompression: true, new Memory(buffer, 0, count), cancellationToken).ConfigureAwait(false); } diff --git a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ValueWebSocketReceiveResult.cs b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ValueWebSocketReceiveResult.cs index 1353af112d90..d5e904510d82 100644 --- a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ValueWebSocketReceiveResult.cs +++ b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ValueWebSocketReceiveResult.cs @@ -17,7 +17,7 @@ public readonly struct ValueWebSocketReceiveResult /// Whether this is the final message. public ValueWebSocketReceiveResult(int count, WebSocketMessageType messageType, bool endOfMessage) { - if (count < 0) ThrowCountOutOfRange(); + ArgumentOutOfRangeException.ThrowIfNegative(count); if ((uint)messageType > (uint)WebSocketMessageType.Close) ThrowMessageTypeOutOfRange(); _countAndEndOfMessage = (uint)count | (uint)(endOfMessage ? 1 << 31 : 0); @@ -32,7 +32,6 @@ public ValueWebSocketReceiveResult(int count, WebSocketMessageType messageType, public bool EndOfMessage => (_countAndEndOfMessage & 0x80000000) == 0x80000000; public WebSocketMessageType MessageType => _messageType; - private static void ThrowCountOutOfRange() => throw new ArgumentOutOfRangeException("count"); private static void ThrowMessageTypeOutOfRange() => throw new ArgumentOutOfRangeException("messageType"); } } diff --git a/src/libraries/System.Net.WebSockets/tests/WebSocketCreateTest.cs b/src/libraries/System.Net.WebSockets/tests/WebSocketCreateTest.cs index f8323a203320..988f8e4eaaa9 100644 --- a/src/libraries/System.Net.WebSockets/tests/WebSocketCreateTest.cs +++ b/src/libraries/System.Net.WebSockets/tests/WebSocketCreateTest.cs @@ -344,7 +344,7 @@ private static async Task CreateWebSocketStream(Uri echoUri, Socket clie return stream; } - public static readonly object[][] EchoServers = System.Net.Test.Common.Configuration.WebSockets.EchoServers; + public static readonly object[][] EchoServers = System.Net.Test.Common.Configuration.WebSockets.GetEchoServers(); public static readonly object[][] EchoServersAndBoolean = EchoServers.SelectMany(o => new object[][] { new object[] { o[0], false }, diff --git a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.csproj b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.csproj index 89bdef6ea38e..18030df31165 100644 --- a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.csproj +++ b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.csproj @@ -2,6 +2,7 @@ $(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) + true diff --git a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs index 40fcdafe6543..0b6241008f6f 100644 --- a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs +++ b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs @@ -4,8 +4,271 @@ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ +#pragma warning disable 8500 // address / sizeof of managed types + +namespace System.Buffers +{ + public readonly partial struct NIndex : System.IEquatable + { + private readonly int _dummyPrimitive; + public NIndex(System.Index index) { throw null; } + public NIndex(nint value, bool fromEnd = false) { throw null; } + public static System.Buffers.NIndex End { get { throw null; } } + public bool IsFromEnd { get { throw null; } } + public static System.Buffers.NIndex Start { get { throw null; } } + public nint Value { get { throw null; } } + public bool Equals(System.Buffers.NIndex other) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } + public static System.Buffers.NIndex FromEnd(nint value) { throw null; } + public static System.Buffers.NIndex FromStart(nint value) { throw null; } + public override int GetHashCode() { throw null; } + public nint GetOffset(nint length) { throw null; } + public static explicit operator checked System.Index (System.Buffers.NIndex value) { throw null; } + public static explicit operator System.Index (System.Buffers.NIndex value) { throw null; } + public static implicit operator System.Buffers.NIndex (System.Index value) { throw null; } + public static implicit operator System.Buffers.NIndex (nint value) { throw null; } + public System.Index ToIndex() { throw null; } + public System.Index ToIndexUnchecked() { throw null; } + public override string ToString() { throw null; } + } + public readonly partial struct NRange : System.IEquatable + { + private readonly int _dummyPrimitive; + public NRange(System.Buffers.NIndex start, System.Buffers.NIndex end) { throw null; } + public NRange(System.Range range) { throw null; } + public static System.Buffers.NRange All { get { throw null; } } + public System.Buffers.NIndex End { get { throw null; } } + public System.Buffers.NIndex Start { get { throw null; } } + public static System.Buffers.NRange EndAt(System.Buffers.NIndex end) { throw null; } + public bool Equals(System.Buffers.NRange other) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } + public override int GetHashCode() { throw null; } + public (nint Offset, nint Length) GetOffsetAndLength(nint length) { throw null; } + public static explicit operator checked System.Range (System.Buffers.NRange value) { throw null; } + public static explicit operator System.Range (System.Buffers.NRange value) { throw null; } + public static implicit operator System.Buffers.NRange (System.Range range) { throw null; } + public static System.Buffers.NRange StartAt(System.Buffers.NIndex start) { throw null; } + public System.Range ToRange() { throw null; } + public System.Range ToRangeUnchecked() { throw null; } + public override string ToString() { throw null; } + } +} namespace System.Numerics.Tensors { + public partial interface IReadOnlyTensor : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable where TSelf : System.Numerics.Tensors.IReadOnlyTensor + { + static abstract TSelf? Empty { get; } + nint FlattenedLength { get; } + bool IsEmpty { get; } + bool IsPinned { get; } + T this[scoped System.ReadOnlySpan indexes] { get; } + TSelf this[scoped System.ReadOnlySpan ranges] { get; } + T this[scoped System.ReadOnlySpan indexes] { get; } + int Rank { get; } + System.Numerics.Tensors.ReadOnlyTensorSpan AsReadOnlyTensorSpan(); + System.Numerics.Tensors.ReadOnlyTensorSpan AsReadOnlyTensorSpan(scoped System.ReadOnlySpan startIndex); + System.Numerics.Tensors.ReadOnlyTensorSpan AsReadOnlyTensorSpan(scoped System.ReadOnlySpan range); + System.Numerics.Tensors.ReadOnlyTensorSpan AsReadOnlyTensorSpan(scoped System.ReadOnlySpan start); + void CopyTo(scoped System.Numerics.Tensors.TensorSpan destination); + void FlattenTo(scoped System.Span destination); + void GetLengths(scoped System.Span destination); + ref readonly T GetPinnableReference(); + void GetStrides(scoped System.Span destination); + TSelf Slice(scoped System.ReadOnlySpan startIndex); + TSelf Slice(scoped System.ReadOnlySpan range); + TSelf Slice(scoped System.ReadOnlySpan start); + bool TryCopyTo(scoped System.Numerics.Tensors.TensorSpan destination); + bool TryFlattenTo(scoped System.Span destination); + } + public partial interface ITensor : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor where TSelf : System.Numerics.Tensors.ITensor + { + bool IsReadOnly { get; } + new T this[scoped System.ReadOnlySpan indexes] { get; set; } + new TSelf this[scoped System.ReadOnlySpan ranges] { get; set; } + new T this[scoped System.ReadOnlySpan indexes] { get; set; } + System.Numerics.Tensors.TensorSpan AsTensorSpan(); + System.Numerics.Tensors.TensorSpan AsTensorSpan(scoped System.ReadOnlySpan startIndex); + System.Numerics.Tensors.TensorSpan AsTensorSpan(scoped System.ReadOnlySpan range); + System.Numerics.Tensors.TensorSpan AsTensorSpan(scoped System.ReadOnlySpan start); + void Clear(); + static abstract TSelf Create(scoped System.ReadOnlySpan lengths, bool pinned = false); + static abstract TSelf Create(scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides, bool pinned = false); + static abstract TSelf CreateUninitialized(scoped System.ReadOnlySpan lengths, bool pinned = false); + static abstract TSelf CreateUninitialized(scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides, bool pinned = false); + void Fill(T value); + new ref T GetPinnableReference(); + } + public readonly ref partial struct ReadOnlyTensorSpan + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public ReadOnlyTensorSpan(System.Array? array) { throw null; } + public ReadOnlyTensorSpan(System.Array? array, scoped System.ReadOnlySpan startIndex, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides) { throw null; } + public ReadOnlyTensorSpan(System.Array? array, scoped System.ReadOnlySpan start, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides) { throw null; } + public ReadOnlyTensorSpan(System.ReadOnlySpan span) { throw null; } + public ReadOnlyTensorSpan(System.ReadOnlySpan span, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides) { throw null; } + [System.CLSCompliantAttribute(false)] + public unsafe ReadOnlyTensorSpan(T* data, nint dataLength) { throw null; } + [System.CLSCompliantAttribute(false)] + public unsafe ReadOnlyTensorSpan(T* data, nint dataLength, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides) { throw null; } + public ReadOnlyTensorSpan(T[]? array) { throw null; } + public ReadOnlyTensorSpan(T[]? array, System.Index startIndex, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides) { throw null; } + public ReadOnlyTensorSpan(T[]? array, int start, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides) { throw null; } + public static System.Numerics.Tensors.ReadOnlyTensorSpan Empty { get { throw null; } } + public nint FlattenedLength { get { throw null; } } + public bool IsEmpty { get { throw null; } } + public ref readonly T this[scoped System.ReadOnlySpan indexes] { get { throw null; } } + public System.Numerics.Tensors.ReadOnlyTensorSpan this[scoped System.ReadOnlySpan ranges] { get { throw null; } } + public ref readonly T this[scoped System.ReadOnlySpan indexes] { get { throw null; } } + [System.Diagnostics.CodeAnalysis.UnscopedRefAttribute] + public System.ReadOnlySpan Lengths { get { throw null; } } + public int Rank { get { throw null; } } + [System.Diagnostics.CodeAnalysis.UnscopedRefAttribute] + public System.ReadOnlySpan Strides { get { throw null; } } + public static System.Numerics.Tensors.ReadOnlyTensorSpan CastUp(System.Numerics.Tensors.ReadOnlyTensorSpan items) where TDerived : class?, T? { throw null; } + public void CopyTo(scoped System.Numerics.Tensors.TensorSpan destination) { } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("Equals() on ReadOnlyTensorSpan will always throw an exception. Use the equality operator instead.")] +#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member + public override bool Equals(object? obj) { throw null; } +#pragma warning restore CS0809 // Obsolete member overrides non-obsolete member + public System.Numerics.Tensors.ReadOnlyTensorSpan.Enumerator GetEnumerator() { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("GetHashCode() on ReadOnlyTensorSpan will always throw an exception.")] +#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member + public override int GetHashCode() { throw null; } +#pragma warning restore CS0809 // Obsolete member overrides non-obsolete member + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public ref readonly T GetPinnableReference() { throw null; } + public static bool operator ==(System.Numerics.Tensors.ReadOnlyTensorSpan left, System.Numerics.Tensors.ReadOnlyTensorSpan right) { throw null; } + public static implicit operator System.Numerics.Tensors.ReadOnlyTensorSpan (T[]? array) { throw null; } + public static bool operator !=(System.Numerics.Tensors.ReadOnlyTensorSpan left, System.Numerics.Tensors.ReadOnlyTensorSpan right) { throw null; } + public System.Numerics.Tensors.ReadOnlyTensorSpan Slice(scoped System.ReadOnlySpan indexes) { throw null; } + public System.Numerics.Tensors.ReadOnlyTensorSpan Slice(scoped System.ReadOnlySpan ranges) { throw null; } + public override string ToString() { throw null; } + public bool TryCopyTo(scoped System.Numerics.Tensors.TensorSpan destination) { throw null; } + public bool TryFlattenTo(scoped System.Span destination) { throw null; } + public void FlattenTo(scoped System.Span destination) { throw null; } + public ref partial struct Enumerator + { + private object _dummy; + private int _dummyPrimitive; + public ref readonly T Current { get { throw null; } } + public bool MoveNext() { throw null; } + } + } + public static partial class Tensor + { + public static System.Numerics.Tensors.TensorSpan AddInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static System.Numerics.Tensors.TensorSpan AddInPlace(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static System.Numerics.Tensors.Tensor AddInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static System.Numerics.Tensors.Tensor AddInPlace(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static System.Numerics.Tensors.TensorSpan Add(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static System.Numerics.Tensors.TensorSpan Add(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static System.Numerics.Tensors.Tensor Add(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static System.Numerics.Tensors.Tensor Add(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static System.Numerics.Tensors.Tensor Broadcast(System.Numerics.Tensors.Tensor input, scoped System.ReadOnlySpan shape) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.Tensor Concatenate(System.ReadOnlySpan> tensors, int axis = 0) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan CosInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor CosInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.TensorSpan Cos(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Cos(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor CreateAndFillGaussianNormalDistribution(scoped System.ReadOnlySpan lengths) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } + public static System.Numerics.Tensors.Tensor CreateAndFillUniformDistribution(scoped System.ReadOnlySpan lengths) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } + public static System.Numerics.Tensors.Tensor CreateFromEnumerable(System.Collections.Generic.IEnumerable data) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.Tensor CreateUninitialized(scoped System.ReadOnlySpan lengths, bool pinned = false) where T : System.IEquatable { throw null; } + public static System.Numerics.Tensors.Tensor CreateUninitialized(scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides, bool pinned = false) where T : System.IEquatable { throw null; } + public static System.Numerics.Tensors.Tensor Create(scoped System.ReadOnlySpan lengths, bool pinned = false) where T : System.IEquatable { throw null; } + public static System.Numerics.Tensors.Tensor Create(scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides, bool pinned = false) where T : System.IEquatable { throw null; } + public static System.Numerics.Tensors.Tensor Create(T[] values, scoped System.ReadOnlySpan lengths) where T : System.IEquatable { throw null; } + public static System.Numerics.Tensors.Tensor Create(T[] values, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides) where T : System.IEquatable { throw null; } + public static System.Numerics.Tensors.TensorSpan DivideInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan DivideInPlace(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.Tensor DivideInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.Tensor DivideInPlace(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan DivideInPlace(T val, System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.Tensor DivideInPlace(T val, System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan Divide(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan Divide(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.Tensor Divide(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.Tensor Divide(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan Divide(T val, System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.Tensor Divide(T val, System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.Tensor FilteredUpdate(System.Numerics.Tensors.Tensor tensor, System.Numerics.Tensors.Tensor filter, System.Numerics.Tensors.Tensor values) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.Tensor FilteredUpdate(System.Numerics.Tensors.Tensor tensor, System.Numerics.Tensors.Tensor filter, T value) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static bool GreaterThanAll(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } + public static bool GreaterThanAny(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } + public static System.Numerics.Tensors.Tensor GreaterThan(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } + public static System.Numerics.Tensors.Tensor GreaterThan(System.Numerics.Tensors.Tensor left, T right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } + public static bool LessThanAll(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } + public static bool LessThanAny(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } + public static System.Numerics.Tensors.Tensor LessThan(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } + public static System.Numerics.Tensors.Tensor LessThan(System.Numerics.Tensors.Tensor left, T right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan Log10InPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Log10InPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.TensorSpan Log10(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Log10(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.TensorSpan Log2InPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Log2InPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.TensorSpan Log2(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Log2(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.TensorSpan LogInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor LogInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.TensorSpan Log(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Log(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } + public static T Mean(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } + public static TResult Mean(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber where TResult : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } + public static System.Numerics.Tensors.TensorSpan MultiplyInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } + public static System.Numerics.Tensors.TensorSpan MultiplyInPlace(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } + public static System.Numerics.Tensors.Tensor MultiplyInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } + public static System.Numerics.Tensors.Tensor MultiplyInPlace(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } + public static System.Numerics.Tensors.TensorSpan Multiply(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } + public static System.Numerics.Tensors.TensorSpan Multiply(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } + public static System.Numerics.Tensors.Tensor Multiply(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } + public static System.Numerics.Tensors.Tensor Multiply(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } + public static T Norm(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } + public static T Norm(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Permute(System.Numerics.Tensors.Tensor input, scoped System.ReadOnlySpan axis) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan Reshape(this System.Numerics.Tensors.TensorSpan input, scoped System.ReadOnlySpan lengths) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.Tensor Reshape(this System.Numerics.Tensors.Tensor input, scoped System.ReadOnlySpan lengths) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan Resize(System.Numerics.Tensors.TensorSpan input, scoped System.ReadOnlySpan shape) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.Tensor Resize(System.Numerics.Tensors.Tensor input, scoped System.ReadOnlySpan shape) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan Reverse(System.Numerics.Tensors.TensorSpan input, nint axis = -1) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.Tensor Reverse(System.Numerics.Tensors.Tensor input, nint axis = -1) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.Tensor SequenceEqual(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.Tensor SetSlice(this System.Numerics.Tensors.Tensor tensor, System.Numerics.Tensors.Tensor values, scoped System.ReadOnlySpan ranges) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan SinInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor SinInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.TensorSpan Sin(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Sin(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor[] Split(System.Numerics.Tensors.Tensor input, nint numSplits, nint axis) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan SqrtInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } + public static System.Numerics.Tensors.Tensor SqrtInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } + public static System.Numerics.Tensors.TensorSpan Sqrt(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Sqrt(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Squeeze(System.Numerics.Tensors.Tensor input, int axis = -1) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.Tensor Stack(System.Numerics.Tensors.Tensor[] input, int axis = 0) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static T StdDev(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint, System.Numerics.IPowerFunctions, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static TResult StdDev(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber where TResult : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } + public static System.Numerics.Tensors.TensorSpan SubtractInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan SubtractInPlace(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } + public static System.Numerics.Tensors.Tensor SubtractInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } + public static System.Numerics.Tensors.Tensor SubtractInPlace(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan SubtractInPlace(T val, System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } + public static System.Numerics.Tensors.Tensor SubtractInPlace(T val, System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan Subtract(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan Subtract(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } + public static System.Numerics.Tensors.Tensor Subtract(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } + public static System.Numerics.Tensors.Tensor Subtract(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } + public static System.Numerics.Tensors.TensorSpan Subtract(T val, System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } + public static System.Numerics.Tensors.Tensor Subtract(T val, System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } + public static T Sum(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static T Sum(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static string ToString(this System.Numerics.Tensors.ReadOnlyTensorSpan span, scoped System.ReadOnlySpan maximumLengths) { throw null; } + public static string ToString(this System.Numerics.Tensors.TensorSpan span, scoped System.ReadOnlySpan maximumLengths) { throw null; } + public static System.Numerics.Tensors.Tensor Transpose(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.Tensor Unsqueeze(System.Numerics.Tensors.Tensor input, int axis) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + } public static partial class TensorPrimitives { public static void Abs(System.ReadOnlySpan x, System.Span destination) where T : System.Numerics.INumberBase { } @@ -89,12 +352,18 @@ public static void MaxMagnitude(System.ReadOnlySpan x, T y, System.Span public static T Max(System.ReadOnlySpan x) where T : System.Numerics.INumber { throw null; } public static void Max(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) where T : System.Numerics.INumber { } public static void Max(System.ReadOnlySpan x, T y, System.Span destination) where T : System.Numerics.INumber { } + public static T MaxNumber(System.ReadOnlySpan x) where T : System.Numerics.INumber { throw null; } + public static void MaxNumber(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) where T : System.Numerics.INumber { } + public static void MaxNumber(System.ReadOnlySpan x, T y, System.Span destination) where T : System.Numerics.INumber { } public static T MinMagnitude(System.ReadOnlySpan x) where T : System.Numerics.INumberBase { throw null; } public static void MinMagnitude(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) where T : System.Numerics.INumberBase { } public static void MinMagnitude(System.ReadOnlySpan x, T y, System.Span destination) where T : System.Numerics.INumberBase { } public static T Min(System.ReadOnlySpan x) where T : System.Numerics.INumber { throw null; } public static void Min(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) where T : System.Numerics.INumber { } public static void Min(System.ReadOnlySpan x, T y, System.Span destination) where T : System.Numerics.INumber { } + public static T MinNumber(System.ReadOnlySpan x) where T : System.Numerics.INumber { throw null; } + public static void MinNumber(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) where T : System.Numerics.INumber { } + public static void MinNumber(System.ReadOnlySpan x, T y, System.Span destination) where T : System.Numerics.INumber { } public static void MultiplyAdd(System.ReadOnlySpan x, System.ReadOnlySpan y, System.ReadOnlySpan addend, System.Span destination) where T : System.Numerics.IAdditionOperators, System.Numerics.IMultiplyOperators { } public static void MultiplyAdd(System.ReadOnlySpan x, System.ReadOnlySpan y, T addend, System.Span destination) where T : System.Numerics.IAdditionOperators, System.Numerics.IMultiplyOperators { } public static void MultiplyAdd(System.ReadOnlySpan x, T y, System.ReadOnlySpan addend, System.Span destination) where T : System.Numerics.IAdditionOperators, System.Numerics.IMultiplyOperators { } @@ -151,4 +420,125 @@ public static void Truncate(System.ReadOnlySpan x, System.Span destinat public static void Xor(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) where T : System.Numerics.IBitwiseOperators { } public static void Xor(System.ReadOnlySpan x, T y, System.Span destination) where T : System.Numerics.IBitwiseOperators { } } + public static partial class TensorSpan + { + public static System.Numerics.Tensors.TensorSpan AsTensorSpan(this T[]? array, scoped System.ReadOnlySpan shape) { throw null; } + public static bool SequenceEqual(this System.Numerics.Tensors.TensorSpan span, System.Numerics.Tensors.TensorSpan other) where T : System.IEquatable? { throw null; } + } + public readonly ref partial struct TensorSpan + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public TensorSpan(System.Array? array) { throw null; } + public TensorSpan(System.Array? array, scoped System.ReadOnlySpan startIndex, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides) { throw null; } + public TensorSpan(System.Array? array, scoped System.ReadOnlySpan start, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides) { throw null; } + public TensorSpan(System.Span span) { throw null; } + public TensorSpan(System.Span span, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides) { throw null; } + [System.CLSCompliantAttribute(false)] + public unsafe TensorSpan(T* data, nint dataLength) { throw null; } + [System.CLSCompliantAttribute(false)] + public unsafe TensorSpan(T* data, nint dataLength, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides) { throw null; } + public TensorSpan(T[]? array) { throw null; } + public TensorSpan(T[]? array, System.Index startIndex, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides) { throw null; } + public TensorSpan(T[]? array, int start, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides) { throw null; } + public static System.Numerics.Tensors.TensorSpan Empty { get { throw null; } } + public nint FlattenedLength { get { throw null; } } + public bool IsEmpty { get { throw null; } } + public ref T this[scoped System.ReadOnlySpan indexes] { get { throw null; } } + public System.Numerics.Tensors.TensorSpan this[scoped System.ReadOnlySpan ranges] { get { throw null; } set { } } + public ref T this[scoped System.ReadOnlySpan indexes] { get { throw null; } } + [System.Diagnostics.CodeAnalysis.UnscopedRefAttribute] + public System.ReadOnlySpan Lengths { get { throw null; } } + public int Rank { get { throw null; } } + [System.Diagnostics.CodeAnalysis.UnscopedRefAttribute] + public System.ReadOnlySpan Strides { get { throw null; } } + public void Clear() { } + public void CopyTo(scoped System.Numerics.Tensors.TensorSpan destination) { } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("Equals() on TensorSpan will always throw an exception. Use the equality operator instead.")] +#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member + public override bool Equals(object? obj) { throw null; } +#pragma warning restore CS0809 // Obsolete member overrides non-obsolete member + public void Fill(T value) { } + public void FlattenTo(scoped System.Span destination) { } + public System.Numerics.Tensors.TensorSpan.Enumerator GetEnumerator() { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("GetHashCode() on TensorSpan will always throw an exception.")] +#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member + public override int GetHashCode() { throw null; } +#pragma warning restore CS0809 // Obsolete member overrides non-obsolete member + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public ref T GetPinnableReference() { throw null; } + public static bool operator ==(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) { throw null; } + public static implicit operator System.Numerics.Tensors.ReadOnlyTensorSpan (System.Numerics.Tensors.TensorSpan span) { throw null; } + public static implicit operator System.Numerics.Tensors.TensorSpan (T[]? array) { throw null; } + public static bool operator !=(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) { throw null; } + public System.Numerics.Tensors.TensorSpan Slice(scoped System.ReadOnlySpan indexes) { throw null; } + public System.Numerics.Tensors.TensorSpan Slice(scoped System.ReadOnlySpan ranges) { throw null; } + public override string ToString() { throw null; } + public bool TryCopyTo(scoped System.Numerics.Tensors.TensorSpan destination) { throw null; } + public bool TryFlattenTo(scoped System.Span destination) { throw null; } + public ref partial struct Enumerator + { + private object _dummy; + private int _dummyPrimitive; + public ref T Current { get { throw null; } } + public bool MoveNext() { throw null; } + } + } + public sealed partial class Tensor : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor, T>, System.Numerics.Tensors.ITensor, T> + { + internal Tensor() { } + public static System.Numerics.Tensors.Tensor Empty { get { throw null; } } + public nint FlattenedLength { get { throw null; } } + public bool IsEmpty { get { throw null; } } + public bool IsPinned { get { throw null; } } + public System.Numerics.Tensors.Tensor this[System.Numerics.Tensors.Tensor filter] { get { throw null; } } + public ref T this[scoped System.ReadOnlySpan indexes] { get { throw null; } } + public System.Numerics.Tensors.Tensor this[scoped System.ReadOnlySpan ranges] { get { throw null; } set { } } + public ref T this[scoped System.ReadOnlySpan indexes] { get { throw null; } } + public System.ReadOnlySpan Lengths { get { throw null; } } + public int Rank { get { throw null; } } + public System.ReadOnlySpan Strides { get { throw null; } } + T System.Numerics.Tensors.IReadOnlyTensor, T>.this[scoped System.ReadOnlySpan indexes] { get { throw null; } } + System.Numerics.Tensors.Tensor System.Numerics.Tensors.IReadOnlyTensor, T>.this[scoped System.ReadOnlySpan ranges] { get { throw null; } } + T System.Numerics.Tensors.IReadOnlyTensor, T>.this[scoped System.ReadOnlySpan indexes] { get { throw null; } } + bool System.Numerics.Tensors.ITensor, T>.IsReadOnly { get { throw null; } } + T System.Numerics.Tensors.ITensor, T>.this[scoped System.ReadOnlySpan indexes] { get { throw null; } set { } } + T System.Numerics.Tensors.ITensor, T>.this[scoped System.ReadOnlySpan indexes] { get { throw null; } set { } } + public System.Numerics.Tensors.ReadOnlyTensorSpan AsReadOnlyTensorSpan() { throw null; } + public System.Numerics.Tensors.ReadOnlyTensorSpan AsReadOnlyTensorSpan(scoped System.ReadOnlySpan startIndex) { throw null; } + public System.Numerics.Tensors.ReadOnlyTensorSpan AsReadOnlyTensorSpan(scoped System.ReadOnlySpan start) { throw null; } + public System.Numerics.Tensors.ReadOnlyTensorSpan AsReadOnlyTensorSpan(scoped System.ReadOnlySpan start) { throw null; } + public System.Numerics.Tensors.TensorSpan AsTensorSpan() { throw null; } + public System.Numerics.Tensors.TensorSpan AsTensorSpan(scoped System.ReadOnlySpan startIndex) { throw null; } + public System.Numerics.Tensors.TensorSpan AsTensorSpan(scoped System.ReadOnlySpan start) { throw null; } + public System.Numerics.Tensors.TensorSpan AsTensorSpan(scoped System.ReadOnlySpan start) { throw null; } + public void Clear() { } + public void CopyTo(System.Numerics.Tensors.TensorSpan destination) { } + public void Fill(T value) { } + public void FlattenTo(System.Span destination) { } + public System.Collections.Generic.IEnumerator GetEnumerator() { throw null; } + public override int GetHashCode() { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public ref T GetPinnableReference() { throw null; } + public static implicit operator System.Numerics.Tensors.ReadOnlyTensorSpan (System.Numerics.Tensors.Tensor value) { throw null; } + public static implicit operator System.Numerics.Tensors.TensorSpan (System.Numerics.Tensors.Tensor value) { throw null; } + public System.Numerics.Tensors.Tensor Slice(scoped System.ReadOnlySpan startIndex) { throw null; } + public System.Numerics.Tensors.Tensor Slice(scoped System.ReadOnlySpan start) { throw null; } + public System.Numerics.Tensors.Tensor Slice(scoped System.ReadOnlySpan start) { throw null; } + System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } + void System.Numerics.Tensors.IReadOnlyTensor, T>.GetLengths(System.Span destination) { } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + ref readonly T System.Numerics.Tensors.IReadOnlyTensor, T>.GetPinnableReference() { throw null; } + void System.Numerics.Tensors.IReadOnlyTensor, T>.GetStrides(scoped System.Span destination) { } + static System.Numerics.Tensors.Tensor System.Numerics.Tensors.ITensor, T>.Create(scoped System.ReadOnlySpan lengths, bool pinned) { throw null; } + static System.Numerics.Tensors.Tensor System.Numerics.Tensors.ITensor, T>.Create(scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides, bool pinned) { throw null; } + static System.Numerics.Tensors.Tensor System.Numerics.Tensors.ITensor, T>.CreateUninitialized(scoped System.ReadOnlySpan lengths, bool pinned) { throw null; } + static System.Numerics.Tensors.Tensor System.Numerics.Tensors.ITensor, T>.CreateUninitialized(scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides, bool pinned) { throw null; } + public string ToString(scoped System.ReadOnlySpan maximumLengths) { throw null; } + public bool TryCopyTo(System.Numerics.Tensors.TensorSpan destination) { throw null; } + public bool TryFlattenTo(System.Span destination) { throw null; } + } } diff --git a/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx b/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx index 890bfd7ed850..a499e962b07b 100644 --- a/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx +++ b/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx @@ -135,4 +135,88 @@ The value '{0}' is not valid for this usage of the type {1}. - + + Cannot use type '{0}'. Only value types without pointers or references are supported. + + + Destination is too short. + + + Equals() on TensorSpan and ReadOnlyTensorSpan is not supported. Use operator== instead. + + + GetHashCode() on TensorSpan and ReadOnlyTensorSpan is not supported. + + + Number of Indices must equal the rank of the TensorSpan. + + + The total length specified by the lengths must equal the length of the array. + + + Must be a 1d tensor + + + Cannot select an axis greater than the current Rank + + + Must provide at least 2 tensors to Concatenate + + + Number of dimensions to slice does not equal the number of dimensions in the span + + + The total length of the filter tensor must equal the length of the tensor to be filtered. + + + Number of elements provided does not match the number of filters. + + + In place operations require the same shape for both tensors + + + Invalid axis provided. Must be greater then or equal to 0 and less than the tensor rank. + + + The tensors must have the same shape, except in the dimension corresponding to axis. + + + Provided dimensions are not valid for reshaping + + + Cannot select an axis to squeeze which has size not equal to one + + + Provided dimensions can only include 1 wildcard. + + + Must provide an axis order for each axis + + + Provided values must have the same shape as the input tensor. + + + When no ranges are specified the values tensor must be equal in size as the input tensor. + + + Shapes are not broadcast compatible. + + + The number of splits must perfectly divide the dimension. + + + Must provide at least 2 tensors to Stack. + + + Must provide a tensor with at least 2 dimensions to transpose it. + + + The provided value must be non-negative. + + + The provided lengths and strides would allow you to access elements outside the provided memory. + + + Strides cannot be less than 0. + + \ No newline at end of file diff --git a/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj b/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj index f5bb6c851dfb..485702c370ca 100644 --- a/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj +++ b/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) @@ -6,6 +6,7 @@ true Provides support for operating over tensors. ReferenceAssemblyExclusions.txt + true @@ -15,6 +16,20 @@ + + + + + + + + + + + + + + @@ -82,8 +97,10 @@ + + diff --git a/src/libraries/System.Numerics.Tensors/src/System/NIndex.cs b/src/libraries/System.Numerics.Tensors/src/System/NIndex.cs new file mode 100644 index 000000000000..512d1ecb7ac5 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/NIndex.cs @@ -0,0 +1,175 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace System.Buffers +{ + /// Represent a type can be used to index a collection either from the start or the end. + /// + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ; + /// int lastElement = someArray[^1]; // lastElement = 5 + /// + /// + public readonly struct NIndex : IEquatable + { + private readonly nint _value; + + /// Construct an NIndex using a value and indicating if the NIndex is from the start or from the end. + /// The index value. it has to be zero or positive number. + /// Indicating if the index is from the start or from the end. + /// + /// If the NIndex constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public NIndex(nint value, bool fromEnd = false) + { + if (value < 0) + { + ThrowHelper.ThrowValueArgumentOutOfRange_NeedNonNegNumException(); + } + + if (fromEnd) + _value = ~value; + else + _value = value; + } + + /// Construct a from a + /// The to create the from. + /// + /// If the NIndex constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public NIndex(Index index) + { + if (index.IsFromEnd) + _value = ~index.Value; + else + _value = index.Value; + } + + // The following private constructor exists to skip the checks in the public ctor + private NIndex(nint value) + { + _value = value; + } + + /// Create an NIndex pointing at first element. + public static NIndex Start => new NIndex((nint)0); + + /// Create an NIndex pointing at beyond last element. + public static NIndex End => new NIndex((nint)~0); + + /// Create an NIndex from the start at the position indicated by the value. + /// The index value from the start. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static NIndex FromStart(nint value) + { + if (value < 0) + { + ThrowHelper.ThrowValueArgumentOutOfRange_NeedNonNegNumException(); + } + + return new NIndex(value); + } + + /// Create an NIndex from the end at the position indicated by the value. + /// The index value from the end. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static NIndex FromEnd(nint value) + { + if (value < 0) + { + ThrowHelper.ThrowValueArgumentOutOfRange_NeedNonNegNumException(); + } + + return new NIndex(~value); + } + + public Index ToIndex() => checked((Index)this); + public Index ToIndexUnchecked() => (Index)this; + + /// Returns the NIndex value. + public nint Value + { + get + { + if (_value < 0) + return ~_value; + else + return _value; + } + } + + /// Indicates whether the NIndex is from the start or the end. + public bool IsFromEnd => _value < 0; + + /// Calculate the offset from the start using the giving collection length. + /// The length of the collection that the NIndex will be used with. length has to be a positive value + /// + /// For performance reason, we don't validate the input length parameter and the returned offset value against negative values. + /// we don't validate either the returned offset is greater than the input length. + /// It is expected NIndex will be used with collections which always have non negative length/count. If the returned offset is negative and + /// then used to NIndex a collection will get out of range exception which will be same affect as the validation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public nint GetOffset(nint length) + { + nint offset = _value; + if (IsFromEnd) + { + // offset = length - (~value) + // offset = length + (~(~value) + 1) + // offset = length + value + 1 + + offset += length + 1; + } + return offset; + } + + /// Indicates whether the current NIndex object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals([NotNullWhen(true)] object? value) => value is NIndex other && _value == other._value; + + /// Indicates whether the current NIndex object is equal to another NIndex object. + /// An object to compare with this object + public bool Equals(NIndex other) => _value == other._value; + + /// Returns the hash code for this instance. + public override int GetHashCode() => _value.GetHashCode(); + + /// Converts integer number to an NIndex. + public static implicit operator NIndex(nint value) => FromStart(value); + + /// Converts native integer number to an NIndex. + public static implicit operator NIndex(Index value) => new NIndex(value); + + /// Converts a to an ."/> + public static explicit operator Index(NIndex value) => new Index((int)value.Value, value.IsFromEnd); + + /// Converts a to an ."/> + public static explicit operator checked Index(NIndex value) => new Index(checked((int)value.Value), value.IsFromEnd); + + /// Converts the value of the current NIndex object to its equivalent string representation. + public override string ToString() + { + if (IsFromEnd) + return ToStringFromEnd(); + + return Value.ToString(); + } + + private string ToStringFromEnd() + { + Span span = stackalloc char[21]; // 1 for ^ and 20 for longest possible nuint value + bool formatted = ((uint)Value).TryFormat(span.Slice(1), out int charsWritten); + Debug.Assert(formatted); + span[0] = '^'; + return new string(span.Slice(0, charsWritten + 1)); + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/NRange.cs b/src/libraries/System.Numerics.Tensors/src/System/NRange.cs new file mode 100644 index 000000000000..974407fae167 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/NRange.cs @@ -0,0 +1,131 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace System.Buffers +{ + /// Represent a range that has start and end indices. + /// + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 }; + /// int[] subArray1 = someArray[0..2]; // { 1, 2 } + /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 } + /// + /// + public readonly struct NRange : IEquatable + { + /// Represent the inclusive start NIndex of the NRange. + public NIndex Start { get; } + + /// Represent the exclusive end NIndex of the NRange. + public NIndex End { get; } + + /// Construct an NRange object using the start and end NIndexes. + /// Represent the inclusive start NIndex of the NRange. + /// Represent the exclusive end NIndex of the NRange. + public NRange(NIndex start, NIndex end) + { + Start = start; + End = end; + } + + /// + /// Construct a object using a . + /// + /// The to use. + public NRange(Range range) + { + Start = range.Start; + End = range.End; + } + + /// Indicates whether the current NRange object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals([NotNullWhen(true)] object? value) => + value is NRange r && + r.Start.Equals(Start) && + r.End.Equals(End); + + /// Indicates whether the current NRange object is equal to another NRange object. + /// An object to compare with this object + public bool Equals(NRange other) => other.Start.Equals(Start) && other.End.Equals(End); + + /// Returns the hash code for this instance. + public override int GetHashCode() + { + return HashCode.Combine(Start.GetHashCode(), End.GetHashCode()); + } + + /// Converts the value of the current NRange object to its equivalent string representation. + public override string ToString() + { + Span span = stackalloc char[2 + 2 * 21]; // 2 for "..", then for each NIndex 1 for '^' and 20 for longest possible nuint + int pos = 0; + + if (Start.IsFromEnd) + { + span[0] = '^'; + pos = 1; + } + bool formatted = ((uint)Start.Value).TryFormat(span.Slice(pos), out int charsWritten); + Debug.Assert(formatted); + pos += charsWritten; + + span[pos++] = '.'; + span[pos++] = '.'; + + if (End.IsFromEnd) + { + span[pos++] = '^'; + } + formatted = ((uint)End.Value).TryFormat(span.Slice(pos), out charsWritten); + Debug.Assert(formatted); + pos += charsWritten; + + return new string(span.Slice(0, pos)); + } + + /// Create an NRange object starting from start NIndex to the end of the collection. + public static NRange StartAt(NIndex start) => new NRange(start, NIndex.End); + + /// Create an NRange object starting from first element in the collection to the end NIndex. + public static NRange EndAt(NIndex end) => new NRange(NIndex.Start, end); + + /// Create an NRange object starting from first element to the end. + public static NRange All => new NRange(NIndex.Start, NIndex.End); + + /// Calculate the start offset and length of NRange object using a collection length. + /// The length of the collection that the NRange will be used with. length has to be a positive value. + /// + /// For performance reason, we don't validate the input length parameter against negative values. + /// It is expected NRange will be used with collections which always have non negative length/count. + /// We validate the NRange is inside the length scope though. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public (nint Offset, nint Length) GetOffsetAndLength(nint length) + { + nint start = Start.GetOffset(length); + nint end = End.GetOffset(length); + + if ((uint)end > (uint)length || (uint)start > (uint)end) + { + ThrowArgumentOutOfRangeException(); + } + + return (start, end - start); + } + + private static void ThrowArgumentOutOfRangeException() => throw new ArgumentOutOfRangeException("length"); + + public static implicit operator NRange(Range range) => new NRange(range.Start, range.End); + + public static explicit operator Range(NRange value) => new Range((Index)value.Start, (Index)value.End); + public static explicit operator checked Range(NRange value) => new Range(checked((Index)value.Start), checked((Index)value.End)); + + public Range ToRange() => new Range(checked((Index)Start), checked((Index)End)); + public Range ToRangeUnchecked() => new Range((Index)Start, (Index)End); + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.Single.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.Single.cs index 7255f7a212bd..ae6df0ed43f5 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.Single.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.Single.cs @@ -597,7 +597,7 @@ public static void Multiply(ReadOnlySpan x, ReadOnlySpan y, Span x, float y, Span destination) => InvokeSpanScalarIntoSpan(x, y, destination); - /// Computes the element-wise result of ( * ) * for the specified tensors of single-precision floating-point numbers. + /// Computes the element-wise result of ( * ) + for the specified tensors of single-precision floating-point numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The third tensor, represented as a span. @@ -618,7 +618,7 @@ public static void Multiply(ReadOnlySpan x, float y, Span destinat public static void MultiplyAdd(ReadOnlySpan x, ReadOnlySpan y, ReadOnlySpan addend, Span destination) => InvokeSpanSpanSpanIntoSpan(x, y, addend, destination); - /// Computes the element-wise result of ( * ) * for the specified tensors of single-precision floating-point numbers. + /// Computes the element-wise result of ( * ) + for the specified tensors of single-precision floating-point numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The third tensor, represented as a scalar. @@ -639,7 +639,7 @@ public static void MultiplyAdd(ReadOnlySpan x, ReadOnlySpan y, Rea public static void MultiplyAdd(ReadOnlySpan x, ReadOnlySpan y, float addend, Span destination) => InvokeSpanSpanScalarIntoSpan(x, y, addend, destination); - /// Computes the element-wise result of ( * ) * for the specified tensors of single-precision floating-point numbers. + /// Computes the element-wise result of ( * ) + for the specified tensors of single-precision floating-point numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a scalar. /// The third tensor, represented as a span. diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Common/IReadOnlyTensor.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Common/IReadOnlyTensor.cs new file mode 100644 index 000000000000..75c3b95e8720 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Common/IReadOnlyTensor.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. + +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Numerics.Tensors +{ + public interface IReadOnlyTensor : IEnumerable + where TSelf : IReadOnlyTensor + { + static abstract TSelf? Empty { get; } + + bool IsEmpty { get; } + bool IsPinned { get; } + nint FlattenedLength { get; } + int Rank { get; } + + T this[params ReadOnlySpan indexes] { get; } + T this[params ReadOnlySpan indexes] { get; } + TSelf this[params scoped ReadOnlySpan ranges] { get; } + + ReadOnlyTensorSpan AsReadOnlyTensorSpan(); + ReadOnlyTensorSpan AsReadOnlyTensorSpan(params scoped ReadOnlySpan start); + ReadOnlyTensorSpan AsReadOnlyTensorSpan(params scoped ReadOnlySpan startIndex); + ReadOnlyTensorSpan AsReadOnlyTensorSpan(params scoped ReadOnlySpan range); + + void CopyTo(scoped TensorSpan destination); + void FlattenTo(scoped Span destination); + + // These are not properties so that structs can implement the interface without allocating: + void GetLengths(scoped Span destination); + void GetStrides(scoped Span destination); + + ref readonly T GetPinnableReference(); + TSelf Slice(params scoped ReadOnlySpan start); + TSelf Slice(params scoped ReadOnlySpan startIndex); + TSelf Slice(params scoped ReadOnlySpan range); + bool TryCopyTo(scoped TensorSpan destination); + bool TryFlattenTo(scoped Span destination); + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ITensor.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ITensor.cs new file mode 100644 index 000000000000..78fab614d181 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ITensor.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Numerics.Tensors +{ + public interface ITensor + : IReadOnlyTensor + where TSelf : ITensor + { + // TODO: Determine if we can implement `IEqualityOperators`. + // It looks like C#/.NET currently hits limitations here as it believes TSelf and T could be the same type + // Ideally we could annotate it such that they cannot be the same type and no conflicts would exist + + static abstract TSelf Create(scoped ReadOnlySpan lengths, bool pinned = false); + static abstract TSelf Create(scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool pinned = false); + + static abstract TSelf CreateUninitialized(scoped ReadOnlySpan lengths, bool pinned = false); + static abstract TSelf CreateUninitialized(scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool pinned = false); + + bool IsReadOnly { get; } + + new T this[params ReadOnlySpan indexes] { get; set; } + new T this[params ReadOnlySpan indexes] { get; set; } + new TSelf this[params scoped ReadOnlySpan ranges] { get; set; } + + TensorSpan AsTensorSpan(); + TensorSpan AsTensorSpan(params scoped ReadOnlySpan start); + TensorSpan AsTensorSpan(params scoped ReadOnlySpan startIndex); + TensorSpan AsTensorSpan(params scoped ReadOnlySpan range); + + void Clear(); + void Fill(T value); + new ref T GetPinnableReference(); + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs new file mode 100644 index 000000000000..530bf27993e0 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs @@ -0,0 +1,769 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using System.Runtime.Versioning; +using System.Text; +using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute; +using EditorBrowsableState = System.ComponentModel.EditorBrowsableState; + +#pragma warning disable 0809 //warning CS0809: Obsolete member 'ReadOnlyTensorSpan.Equals(object)' overrides non-obsolete member 'object.Equals(object)' +#pragma warning disable 8500 // address / sizeof of managed types + +namespace System.Numerics.Tensors +{ + /// + /// ReadOnlyTensorSpan represents a contiguous region of arbitrary memory. Unlike arrays, it can point to either managed + /// or native memory, or to memory allocated on the stack. It is type-safe and memory-safe. + /// + [DebuggerTypeProxy(typeof(TensorSpanDebugView<>))] + [DebuggerDisplay("{ToString(),raw}")] + public readonly ref struct ReadOnlyTensorSpan + { + /// A byref or a native ptr. + internal readonly ref T _reference; + /// The number of elements this ReadOnlyTensorSpan contains. + internal readonly nint _flattenedLength; + /// The length of the underlying memory. Can be different than the number of elements in the span. + internal readonly nint _memoryLength; + /// The lengths of each dimension. + internal readonly ReadOnlySpan _lengths; + /// The strides representing the memory offsets for each dimension. + private readonly ReadOnlySpan _strides; + + /// + /// Creates a new span over the entirety of the target array. + /// + /// The target array. + /// Returns default when is null. + /// Thrown when is covariant and array's type is not exactly T[]. + public ReadOnlyTensorSpan(T[]? array) : this(array, 0, [], []) + { + } + + /// + /// Creates a new span over the portion of the target array beginning + /// at 'start' index and ending at 'end' index (exclusive). + /// + /// The target array. + /// The index at which to begin the span. + /// The lengths of the dimensions. If default is provided its assumed to have 1 dimension with a length equal to the length of the data. + /// The strides of each dimension. If default or span of length 0 is provided then strides will be automatically calculated. + /// Returns default when is null. + /// Thrown when is covariant and array's type is not exactly T[]. + /// + /// Thrown when the specified or end index is not in the range (<0 or >FlattenedLength). + /// + public ReadOnlyTensorSpan(T[]? array, Index startIndex, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides) + : this(array, startIndex.GetOffset(array?.Length ?? 0), lengths, strides) + { + } + + /// + /// Creates a new span over the portion of the target array beginning + /// at 'start' index and ending at 'end' index (exclusive). + /// + /// The target array. + /// The index at which to begin the span. + /// The lengths of the dimensions. If default is provided its assumed to have 1 dimension with a length equal to the length of the data. + /// The strides of each dimension. If default or span of length 0 is provided then strides will be automatically calculated. + /// Returns default when is null. + /// Thrown when is covariant and array's type is not exactly T[]. + /// + /// Thrown when the specified or end index is not in the range (<0 or >FlattenedLength). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ReadOnlyTensorSpan(T[]? array, int start, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + if (array == null) + { + if (start != 0 || linearLength != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + this = default; + return; // returns default + } + if (!typeof(T).IsValueType && array.GetType() != typeof(T[])) + ThrowHelper.ThrowArrayTypeMismatchException(); + + strides = strides.IsEmpty ? (ReadOnlySpan)TensorSpanHelpers.CalculateStrides(lengths) : strides; + nint maxElements = TensorSpanHelpers.ComputeMaxElementCount(strides, lengths); + if (Environment.Is64BitProcess) + { + // See comment in Span.Slice for how this works. + if ((ulong)(uint)start + (ulong)(uint)maxElements > (ulong)(uint)array.Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + else + { + if ((uint)start > (uint)array.Length || (uint)maxElements > (uint)(array.Length - start)) + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + + _flattenedLength = linearLength; + _memoryLength = array.Length; + _reference = ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start /* force zero-extension */); + + _lengths = lengths.ToArray(); + _strides = strides.ToArray(); + } + + /// + /// Creates a new over the provided . The new will + /// have a rank of 1 and a length equal to the length of the provided . + /// + /// The target span. + public ReadOnlyTensorSpan(ReadOnlySpan span) : this(span, [span.Length], []) { } + + /// + /// Creates a new over the provided using the specified lengths and strides. + /// If the strides are not provided, they will be automatically calculated. + /// + /// The target span. + /// The lengths of each dimension. + /// The strides for each dimension. Will be automatically calculated if not provided. + public ReadOnlyTensorSpan(ReadOnlySpan span, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + if (span.IsEmpty) + { + if (linearLength != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + this = default; + return; // returns default + } + + strides = strides.IsEmpty ? (ReadOnlySpan)TensorSpanHelpers.CalculateStrides(lengths) : strides; + nint maxElements = TensorSpanHelpers.ComputeMaxElementCount(strides, lengths); + if (maxElements >= span.Length) + ThrowHelper.ThrowArgument_InvalidStridesAndLengths(); + + _flattenedLength = linearLength; + _memoryLength = span.Length; + _reference = ref MemoryMarshal.GetReference(span); + + _lengths = lengths.ToArray(); + _strides = strides.ToArray(); + } + + /// + /// Creates a new over the provided . The new will + /// have a rank of 1 and a length equal to the length of the provided . + /// + /// The target array. + public ReadOnlyTensorSpan(Array? array) : this(array, ReadOnlySpan.Empty, [], []) { } + + /// + /// Creates a new over the provided using the specified start offsets, lengths, and strides. + /// If the strides are not provided, they will be automatically calculated. + /// + /// The target array. + /// The starting offset for each dimension. + /// The lengths of each dimension. + /// The strides for each dimension. Will be automatically calculated if not provided. + public ReadOnlyTensorSpan(Array? array, scoped ReadOnlySpan start, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + strides = strides.IsEmpty ? (ReadOnlySpan)TensorSpanHelpers.CalculateStrides(lengths) : strides; + nint startOffset = TensorSpanHelpers.ComputeLinearIndex(start, strides, lengths); + if (array == null) + { + if (!start.IsEmpty || linearLength != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + this = default; + return; // returns default + } + if (!typeof(T).IsValueType && array.GetType() != typeof(T[])) + ThrowHelper.ThrowArrayTypeMismatchException(); + + nint maxElements = TensorSpanHelpers.ComputeMaxElementCount(strides, lengths); + if (Environment.Is64BitProcess) + { + // See comment in Span.Slice for how this works. + if ((ulong)(uint)startOffset + (ulong)(uint)maxElements > (ulong)(uint)array.Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + else + { + if ((uint)startOffset > (uint)array.Length || (uint)maxElements > (uint)(array.Length - startOffset)) + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + + _flattenedLength = linearLength; + _memoryLength = array.Length; + _reference = ref Unsafe.Add(ref Unsafe.As(ref MemoryMarshal.GetArrayDataReference(array)), (nint)(uint)startOffset /* force zero-extension */); + + _lengths = lengths.ToArray(); + _strides = strides.ToArray(); + } + + /// + /// Creates a new over the provided using the specified start offsets, lengths, and strides. + /// If the strides are not provided, they will be automatically calculated. + /// + /// The target array. + /// The starting offset for each dimension. + /// The lengths of each dimension. + /// The strides for each dimension. Will be automatically calculated if not provided. + public ReadOnlyTensorSpan(Array? array, scoped ReadOnlySpan startIndex, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + strides = strides.IsEmpty ? (ReadOnlySpan)TensorSpanHelpers.CalculateStrides(lengths) : strides; + nint start = TensorSpanHelpers.ComputeLinearIndex(startIndex, strides, lengths); + if (array == null) + { + if (!startIndex.IsEmpty || linearLength != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + this = default; + return; // returns default + } + if (!typeof(T).IsValueType && array.GetType() != typeof(T[])) + ThrowHelper.ThrowArrayTypeMismatchException(); + + nint maxElements = TensorSpanHelpers.ComputeMaxElementCount(strides, lengths); + if (Environment.Is64BitProcess) + { + // See comment in Span.Slice for how this works. + if ((ulong)(uint)start + (ulong)(uint)maxElements > (ulong)(uint)array.Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + else + { + if ((uint)start > (uint)array.Length || (uint)maxElements > (uint)(array.Length - start)) + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + + _flattenedLength = linearLength; + _memoryLength = array.Length; + _reference = ref Unsafe.Add(ref Unsafe.As(ref MemoryMarshal.GetArrayDataReference(array)), (nint)(uint)start /* force zero-extension */); + + _lengths = lengths.ToArray(); + _strides = strides.ToArray(); + } + + /// + /// Creates a new span over the target unmanaged buffer. Clearly this + /// is quite dangerous the length is not checked. + /// But if this creation is correct, then all subsequent uses are correct. + /// + /// An unmanaged data to memory. + /// The number of elements the unmanaged memory can hold. + [CLSCompliant(false)] + public unsafe ReadOnlyTensorSpan(T* data, nint dataLength) : this(data, dataLength, [dataLength], []) { } + + /// + /// Creates a new span over the target unmanaged buffer. Clearly this + /// is quite dangerous, because the length is not checked. + /// But if this creation is correct, then all subsequent uses are correct. + /// + /// An unmanaged data to memory. + /// The number of elements the unmanaged memory can hold. + /// The lengths of the dimensions. If default is provided its assumed to have 1 dimension with a length equal to the length of the data. + /// The lengths of the strides. If nothing is provided it figures out the default stride configuration. + /// + /// Thrown when is reference type or contains pointers and hence cannot be stored in unmanaged memory. + /// + /// + /// Thrown when the specified length is negative. + /// + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public unsafe ReadOnlyTensorSpan(T* data, nint dataLength, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + if (RuntimeHelpers.IsReferenceOrContainsReferences()) + ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T)); + + strides = strides.IsEmpty ? (ReadOnlySpan)TensorSpanHelpers.CalculateStrides(lengths) : strides; + nint maxElements = TensorSpanHelpers.ComputeMaxElementCount(strides, lengths); + if (maxElements >= dataLength) + ThrowHelper.ThrowArgument_InvalidStridesAndLengths(); + + _flattenedLength = linearLength; + _memoryLength = dataLength; + + _reference = ref *data; + + _lengths = lengths.ToArray(); + _strides = strides.ToArray(); + } + + // Constructor for internal use only. It is not safe to expose publicly. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal ReadOnlyTensorSpan(ref T reference, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, nint memoryLength) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + + _flattenedLength = linearLength; + _memoryLength = memoryLength; + _reference = ref reference; + + _lengths = lengths.ToArray(); + _strides = strides.ToArray(); + } + + /// + /// Returns a reference to specified element of the ReadOnlyTensorSpan. + /// + /// + /// + /// + /// Thrown when any index is less than 0 or any index is greater than or equal to FlattenedLength + /// + public ref readonly T this[params scoped ReadOnlySpan indexes] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + if (indexes.Length != Rank) + ThrowHelper.ThrowIndexOutOfRangeException(); + + nint index = TensorSpanHelpers.ComputeLinearIndex(indexes, Strides, Lengths); + if (index >= _memoryLength || index < 0) + ThrowHelper.ThrowIndexOutOfRangeException(); + + return ref Unsafe.Add(ref _reference, index /* force zero-extension */); + } + } + + /// + /// Returns a reference to specified element of the ReadOnlyTensorSpan. + /// + /// + /// + /// + /// Thrown when any index is less than 0 or any index is greater than or equal to FlattenedLength + /// + public ref readonly T this[params scoped ReadOnlySpan indexes] + { + get + { + if (indexes.Length != Rank) + ThrowHelper.ThrowIndexOutOfRangeException(); + + nint index = TensorSpanHelpers.ComputeLinearIndex(indexes, Strides, Lengths); + if (index >= _memoryLength || index < 0) + ThrowHelper.ThrowIndexOutOfRangeException(); + + return ref Unsafe.Add(ref _reference, index /* force zero-extension */); + } + } + + /// + /// Returns a slice of the ReadOnlyTensorSpan. + /// + /// + /// + /// + /// Thrown when any index is less than 0 or any index is greater than or equal to FlattenedLength + /// + public ReadOnlyTensorSpan this[params scoped ReadOnlySpan ranges] + { + get + { + if (ranges.Length != Rank) + ThrowHelper.ThrowIndexOutOfRangeException(); + + return Slice(ranges); + } + } + + /// + /// The number of items in the span. + /// + public nint FlattenedLength => _flattenedLength; + + /// + /// Gets a value indicating whether this is empty. + /// + /// if this span is empty; otherwise, . + public bool IsEmpty => _flattenedLength == 0; + + /// + /// Gets the length of each dimension in this . + /// + [UnscopedRef] + public ReadOnlySpan Lengths => _lengths; + + /// + /// Gets the rank, aka the number of dimensions, of this . + /// + public int Rank => Lengths.Length; + + /// + /// Gets the strides of this + /// + [UnscopedRef] + public ReadOnlySpan Strides => _strides; + + /// + /// Returns false if left and right point at the same memory and have the same length. Note that + /// this does *not* check to see if the *contents* are equal. + /// + public static bool operator !=(ReadOnlyTensorSpan left, ReadOnlyTensorSpan right) => !(left == right); + + /// + /// Returns true if left and right point at the same memory and have the same length. Note that + /// this does *not* check to see if the *contents* are equal. + /// + public static bool operator ==(ReadOnlyTensorSpan left, ReadOnlyTensorSpan right) => + left._flattenedLength == right._flattenedLength && + left.Rank == right.Rank && + left._lengths.SequenceEqual(right._lengths )&& + Unsafe.AreSame(ref left._reference, ref right._reference); + + /// + /// This method is not supported as spans cannot be boxed. To compare two spans, use operator==. + /// + /// + /// Always thrown by this method. + /// +#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member + [Obsolete("Equals() on ReadOnlyTensorSpan will always throw an exception. Use the equality operator instead.")] + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object? obj) => + throw new NotSupportedException(SR.NotSupported_CannotCallEqualsOnSpan); + + /// + /// This method is not supported as spans cannot be boxed. + /// + /// + /// Always thrown by this method. + /// + [Obsolete("GetHashCode() on ReadOnlyTensorSpan will always throw an exception.")] + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => + throw new NotSupportedException(SR.NotSupported_CannotCallGetHashCodeOnSpan); +#pragma warning restore CS0809 + + /// + /// Returns a 0-length read-only span whose base is the null pointer. + /// + public static ReadOnlyTensorSpan Empty => default; + + /// + /// Casts a read-only span of to a read-only span of . + /// + /// The element type of the source read-only span, which must be derived from . + /// The source read-only span. No copy is made. + /// A read-only span with elements cast to the new type. + /// This method uses a covariant cast, producing a read-only span that shares the same memory as the source. The relationships expressed in the type constraints ensure that the cast is a safe operation. + public static ReadOnlyTensorSpan CastUp(ReadOnlyTensorSpan items) where TDerived : class?, T + { + return new ReadOnlyTensorSpan(ref Unsafe.As(ref items._reference), items._lengths, items._strides, items._memoryLength); + } + + /// Gets an enumerator for this span. + public Enumerator GetEnumerator() => new Enumerator(this); + + /// Enumerates the elements of a . + public ref struct Enumerator + { + /// The span being enumerated. + private readonly ReadOnlyTensorSpan _span; + /// The current index that the enumerator is on. + private Span _curIndexes; + /// The total item count. + private nint _items; + + /// Initialize the enumerator. + /// The span to enumerate. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal Enumerator(ReadOnlyTensorSpan span) + { + _span = span; + _items = -1; + _curIndexes = new nint[_span.Rank]; + _curIndexes[_span.Rank - 1] = -1; + } + + /// Advances the enumerator to the next element of the span. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + { + TensorSpanHelpers.AdjustIndexes(_span.Rank - 1, 1, _curIndexes, _span.Lengths); + + if (_items < _span.FlattenedLength) + _items++; + + return _items < _span.FlattenedLength; + } + + /// Gets the element at the current position of the enumerator. + public ref readonly T Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => ref _span[_curIndexes]; + } + } + + /// + /// Returns a reference to the 0th element of the ReadOnlyTensorSpan. If the ReadOnlyTensorSpan is empty, returns null reference. + /// It can be used for pinning and is required to support the use of span within a fixed statement. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public ref readonly T GetPinnableReference() + { + // Ensure that the native code has just one forward branch that is predicted-not-taken. + ref T ret = ref Unsafe.NullRef(); + if (_flattenedLength != 0) ret = ref _reference; + return ref ret; + } + + /// + /// Copies the contents of this read-only span into destination span. If the source + /// and destinations overlap, this method behaves as if the original values in + /// a temporary location before the destination is overwritten. + /// + /// The span to copy items into. + /// + /// Thrown when the destination ReadOnlyTensorSpan is shorter than the source ReadOnlyTensorSpan. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyTo(scoped TensorSpan destination) + { + // Using "if (!TryCopyTo(...))" results in two branches: one for the length + // check, and one for the result of TryCopyTo. Since these checks are equivalent, + // we can optimize by performing the check once ourselves then calling Memmove directly. + if (_flattenedLength <= destination.FlattenedLength) + { + scoped Span curIndexes; + nint[]? curIndexesArray; + if (Rank > 6) + { + curIndexesArray = ArrayPool.Shared.Rent(Rank); + curIndexes = curIndexesArray; + } + else + { + curIndexesArray = null; + curIndexes = stackalloc nint[Rank]; + } + + nint copiedValues = 0; + TensorSpan slice = destination.Slice(_lengths); + while (copiedValues < _flattenedLength) + { + TensorSpanHelpers.Memmove(ref Unsafe.Add(ref slice._reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), Lengths[Rank - 1]); + TensorSpanHelpers.AdjustIndexes(Rank - 2, 1, curIndexes, _lengths); + copiedValues += Lengths[Rank - 1]; + } + Debug.Assert(copiedValues == _flattenedLength, "Didn't copy the right amount to the array."); + + if (curIndexesArray != null) + ArrayPool.Shared.Return(curIndexesArray); + } + else + { + ThrowHelper.ThrowArgumentException_DestinationTooShort(); + } + } + + /// + /// Copies the contents of this read-only span into destination span. If the source + /// and destinations overlap, this method behaves as if the original values in + /// a temporary location before the destination is overwritten. + /// + /// If the destination span is shorter than the source span, this method + /// return false and no data is written to the destination. + /// The span to copy items into. + public bool TryCopyTo(scoped TensorSpan destination) + { + bool retVal = false; + + if (_flattenedLength <= destination.FlattenedLength) + { + scoped Span curIndexes; + nint[]? curIndexesArray; + if (Rank > 6) + { + curIndexesArray = ArrayPool.Shared.Rent(Rank); + curIndexes = curIndexesArray; + } + else + { + curIndexesArray = null; + curIndexes = stackalloc nint[Rank]; + } + + nint copiedValues = 0; + TensorSpan slice = destination.Slice(_lengths); + while (copiedValues < _flattenedLength) + { + TensorSpanHelpers.Memmove(ref Unsafe.Add(ref slice._reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), Lengths[Rank - 1]); + TensorSpanHelpers.AdjustIndexes(Rank - 2, 1, curIndexes, _lengths); + copiedValues += Lengths[Rank - 1]; + } + retVal = true; + Debug.Assert(copiedValues == _flattenedLength, "Didn't copy the right amount to the array."); + + if (curIndexesArray != null) + ArrayPool.Shared.Return(curIndexesArray); + } + + return retVal; + } + + //public static explicit operator TensorSpan(Array? array); + public static implicit operator ReadOnlyTensorSpan(T[]? array) => new ReadOnlyTensorSpan(array); + + /// + /// Returns a with the name of the type and the number of elements. + /// + public override string ToString() => $"System.Numerics.Tensors.ReadOnlyTensorSpan<{typeof(T).Name}>[{_flattenedLength}]"; + + /// + /// Returns a reference to specified element of the TensorSpan. + /// + /// The indexes for the slice. + /// + /// + /// Thrown when any index is less than 0 or any index is greater than or equal to FlattenedLength + /// + public ReadOnlyTensorSpan Slice(params scoped ReadOnlySpan indexes) + { + NRange[] ranges = new NRange[indexes.Length]; + for (int i = 0; i < indexes.Length; i++) + { + ranges[i] = new NRange(checked((int)indexes[i].GetOffset(Lengths[i])), Lengths[i]); + } + return Slice(ranges); + } + + /// + /// Takes in the lengths of the dimensions and slices according to them. + /// + /// The dimension lengths + /// A based on the provided + internal ReadOnlyTensorSpan Slice(scoped ReadOnlySpan lengths) + { + NRange[] ranges = new NRange[lengths.Length]; + for (int i = 0; i < lengths.Length; i++) + { + ranges[i] = new NRange(0, lengths[i]); + } + return Slice(ranges); + } + + /// + /// Forms a slice out of the given span + /// + /// The ranges for the slice + /// A based on the provided + + public ReadOnlyTensorSpan Slice(params scoped ReadOnlySpan ranges) + { + if (ranges.Length != Lengths.Length) + throw new ArgumentOutOfRangeException(nameof(ranges), "Number of dimensions to slice does not equal the number of dimensions in the span"); + + scoped Span shape; + scoped Span offsets; + if (Rank > 6) + { + shape = stackalloc nint[Rank]; + offsets = stackalloc nint[Rank]; + } + else + { + shape = new nint[Rank]; + offsets = new nint[Rank]; + } + + for (int i = 0; i < ranges.Length; i++) + { + (offsets[i], shape[i]) = ranges[i].GetOffsetAndLength(Lengths[i]); + } + + nint index = 0; + for (int i = 0; i < offsets.Length; i++) + { + index += Strides[i] * (offsets[i]); + } + + if (index >= _memoryLength || index < 0) + ThrowHelper.ThrowIndexOutOfRangeException(); + + return new ReadOnlyTensorSpan(ref Unsafe.Add(ref _reference, index), shape, _strides, _memoryLength - index); + } + + /// + /// Flattens the contents of this span into the provided . + /// + /// The span to copy items into. + public bool TryFlattenTo(scoped Span destination) + { + bool retVal = false; + if (destination.Length < _flattenedLength) + { + scoped Span curIndexes; + nint[]? curIndexesArray; + if (Rank > 6) + { + curIndexesArray = ArrayPool.Shared.Rent(Rank); + curIndexes = curIndexesArray; + } + else + { + curIndexesArray = null; + curIndexes = stackalloc nint[Rank]; + } + + nint copiedValues = 0; + while (copiedValues < _flattenedLength) + { + TensorSpanHelpers.Memmove(destination.Slice(checked((int)copiedValues)), ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), Lengths[Rank - 1]); + TensorSpanHelpers.AdjustIndexes(Rank - 2, 1, curIndexes, _lengths); + copiedValues += Lengths[Rank - 1]; + } + + if (curIndexesArray != null) + ArrayPool.Shared.Return(curIndexesArray); + retVal = true; + } + return retVal; + } + + /// + /// Flattens the contents of this span into the provided . + /// + /// The span to copy items into. + public void FlattenTo(scoped Span destination) + { + if (destination.Length < _flattenedLength) + ThrowHelper.ThrowArgumentException_DestinationTooShort(); + + if (_flattenedLength == 0) + return; + + scoped Span curIndexes; + nint[]? curIndexesArray; + if (Rank > 6) + { + curIndexesArray = ArrayPool.Shared.Rent(Rank); + curIndexes = curIndexesArray; + } + else + { + curIndexesArray = null; + curIndexes = stackalloc nint[Rank]; + } + + nint copiedValues = 0; + while (copiedValues < _flattenedLength) + { + TensorSpanHelpers.Memmove(destination.Slice(checked((int)copiedValues)), ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), Lengths[Rank - 1]); + TensorSpanHelpers.AdjustIndexes(Rank - 2, 1, curIndexes, _lengths); + copiedValues += Lengths[Rank - 1]; + } + + if (curIndexesArray != null) + ArrayPool.Shared.Return(curIndexesArray); + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.Factory.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.Factory.cs new file mode 100644 index 000000000000..e833c1b8ff60 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.Factory.cs @@ -0,0 +1,158 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Linq; + +#pragma warning disable CS8601 // Possible null reference assignment. +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. +#pragma warning disable 8500 // address / sizeof of managed types + +namespace System.Numerics.Tensors +{ + public static partial class Tensor + { + /// + /// Creates a and initializes it with the default value of T. If is true, the memory will be pinned. + /// + /// A indicating the lengths of each dimension. + /// A whether the underlying data should be pinned or not. + public static Tensor Create(scoped ReadOnlySpan lengths, bool pinned = false) + where T : IEquatable + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + T[] values = pinned ? GC.AllocateArray((int)linearLength, pinned) : (new T[linearLength]); + return new Tensor(values, lengths, pinned); + } + + /// + /// Creates a and initializes it with the default value of T. If is true, the memory will be pinned. + /// + /// A indicating the lengths of each dimension. + /// A indicating the strides of each dimension. + /// A whether the underlying data should be pinned or not. + public static Tensor Create(scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool pinned = false) + where T : IEquatable + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + T[] values = pinned ? GC.AllocateArray((int)linearLength, pinned) : (new T[linearLength]); + return new Tensor(values, lengths, strides, pinned); + } + + /// + /// Creates a from the provided . If the product of the + /// does not equal the length of the array, an exception will be thrown. + /// + /// An array of the backing memory. + /// A indicating the lengths of each dimension. + /// + public static Tensor Create(T[] values, scoped ReadOnlySpan lengths) + where T : IEquatable + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + if (linearLength != values.Length) + ThrowHelper.ThrowArgument_LengthsMustEqualArrayLength(); + + return new Tensor(values, lengths, false); + } + + /// + /// Creates a from the provided . If the product of the + /// does not equal the length of the array, an exception will be thrown. + /// + /// An array of the backing memory. + /// A indicating the lengths of each dimension. + /// A indicating the strides of each dimension. + /// + public static Tensor Create(T[] values, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides) + where T : IEquatable + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + if (linearLength != values.Length) + ThrowHelper.ThrowArgument_LengthsMustEqualArrayLength(); + + return new Tensor(values, lengths, strides, false); + } + + /// + /// Creates a and does not initialize it. If is true, the memory will be pinned. + /// + /// A indicating the lengths of each dimension. + /// A whether the underlying data should be pinned or not. + public static Tensor CreateUninitialized(scoped ReadOnlySpan lengths, bool pinned = false) + where T : IEquatable + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + T[] values = GC.AllocateUninitializedArray((int)linearLength, pinned); + return new Tensor(values, lengths, pinned); + } + + /// + /// Creates a and does not initialize it. If is true, the memory will be pinned. + /// + /// A indicating the lengths of each dimension. + /// A indicating the strides of each dimension. + /// A whether the underlying data should be pinned or not. + public static Tensor CreateUninitialized(scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool pinned = false ) + where T : IEquatable + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + T[] values = GC.AllocateUninitializedArray((int)linearLength, pinned); + return new Tensor(values, lengths, strides, pinned); + } + + /// + /// Creates a and initializes it with the data from . + /// + /// A with the data to use for the initialization. + public static Tensor CreateFromEnumerable(IEnumerable data) + where T : IEquatable, IEqualityOperators + { + T[] values = data.ToArray(); + return new Tensor(values, [values.Length], false); + } + + /// + /// Creates a and initializes it with random data uniformly distributed. + /// + /// A indicating the lengths of each dimension. + public static Tensor CreateAndFillUniformDistribution(params scoped ReadOnlySpan lengths) + where T : IEquatable, IEqualityOperators, IFloatingPoint + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + T[] values = new T[linearLength]; + Random rand = Random.Shared; + for (int i = 0; i < values.Length; i++) + values[i] = T.CreateChecked(rand.NextDouble()); + + return new Tensor(values, lengths, false); + } + + #region Normal + /// + /// Creates a and initializes it with random data in a gaussian normal distribution. + /// + /// A indicating the lengths of each dimension. + public static Tensor CreateAndFillGaussianNormalDistribution(params scoped ReadOnlySpan lengths) + where T : IEquatable, IEqualityOperators, IFloatingPoint + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + T[] values = new T[linearLength]; + GaussianDistribution(ref values, linearLength); + return new Tensor(values, lengths, false); + } + + private static void GaussianDistribution(ref T[] values, nint linearLength) + where T : IEquatable, IEqualityOperators, IFloatingPoint + { + Random rand = Random.Shared; + for (int i = 0; i < linearLength; i++) + { + double u1 = 1.0 - rand.NextDouble(); + double u2 = 1.0 - rand.NextDouble(); + values[i] = T.CreateChecked(Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2)); + } + } + #endregion + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs new file mode 100644 index 000000000000..380e3298f2ac --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs @@ -0,0 +1,645 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; + +#pragma warning disable CS8601 // Possible null reference assignment. +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. +#pragma warning disable 8500 // address / sizeof of managed types + +namespace System.Numerics.Tensors +{ + public sealed class Tensor + : ITensor, T> + { + /// A byref or a native ptr. + internal readonly T[] _values; + /// The number of elements this Tensor contains. + internal readonly nint _flattenedLength; + /// The lengths of each dimension. + internal readonly nint[] _lengths; + /// The strides representing the memory offsets for each dimension. + internal readonly nint[] _strides; + /// If the backing memory is permanently pinned (so not just using a fixed statement). + internal readonly bool _isPinned; + + /// + /// Creates a new empty Tensor. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal Tensor() + { + _flattenedLength = 0; + _values = []; + _lengths = []; + _strides = []; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal Tensor(T[] values, scoped ReadOnlySpan lengths, bool isPinned = false) + { + _flattenedLength = TensorSpanHelpers.CalculateTotalLength(lengths); + + _values = values; + _lengths = lengths.ToArray(); + _strides = TensorSpanHelpers.CalculateStrides(_lengths); + _isPinned = isPinned; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal Tensor(T[] values, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool isPinned = false) + { + _flattenedLength = TensorSpanHelpers.CalculateTotalLength(lengths); + + _values = values; + _lengths = lengths.ToArray(); + _strides = strides.ToArray(); + if (strides == Array.Empty()) + _strides = TensorSpanHelpers.CalculateStrides(lengths); + _isPinned = isPinned; + + } + + /// + /// Creates a and initializes it with the default value of T. If is true, the memory will be pinned. + /// + /// A indicating the lengths of each dimension. + /// A whether the underlying data should be pinned or not. + static Tensor ITensor, T>.Create(scoped ReadOnlySpan lengths, bool pinned) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + T[] values = pinned ? GC.AllocateArray((int)linearLength, pinned) : (new T[linearLength]); + return new Tensor(values, lengths.ToArray(), pinned); + } + + /// + /// Creates a and initializes it with the default value of T. If is true, the memory will be pinned. + /// + /// A indicating the lengths of each dimension. + /// A indicating the strides of each dimension. + /// A whether the underlying data should be pinned or not. + static Tensor ITensor, T>.Create(scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool pinned) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + T[] values = pinned ? GC.AllocateArray((int)linearLength, pinned) : (new T[linearLength]); + return new Tensor(values, lengths.ToArray(), strides.ToArray(), pinned); + } + + /// + /// Creates a and does not initialize it. If is true, the memory will be pinned. + /// + /// A indicating the lengths of each dimension. + /// A whether the underlying data should be pinned or not. + static Tensor ITensor, T>.CreateUninitialized(scoped ReadOnlySpan lengths, bool pinned) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + T[] values = GC.AllocateUninitializedArray((int)linearLength, pinned); + return new Tensor(values, lengths.ToArray(), pinned); + } + + /// + /// Creates a and does not initialize it. If is true, the memory will be pinned. + /// + /// A indicating the lengths of each dimension. + /// A indicating the strides of each dimension. + /// A whether the underlying data should be pinned or not. + static Tensor ITensor, T>.CreateUninitialized(scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool pinned) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + T[] values = GC.AllocateUninitializedArray((int)linearLength, pinned); + return new Tensor(values, lengths.ToArray(), strides.ToArray(), pinned); + } + + // ITensor + /// + /// The Empty Tensor. + /// + public static Tensor Empty { get; } = new(); + + /// + /// Gets a value indicating whether this is empty. + /// + /// if this tensor is empty; otherwise, . + public bool IsEmpty => _lengths.Length == 0; + + /// + /// Gets a value indicating whether the backing memory of the is pinned."/> + /// + /// if the backing memory is pinned; otherwise, . + public bool IsPinned => _isPinned; + + /// + /// Gets a value indicating the rank, or number of dimensions, of this . + /// + /// with the number of dimensions. + public int Rank => _lengths.Length; + + /// + /// The number of items in the . + /// + /// with the number of items. + public nint FlattenedLength => _flattenedLength; + + /// + /// Gets the length of each dimension in this . + /// + /// with the lengths of each dimension. + public ReadOnlySpan Lengths => _lengths; + + /// + /// Gets the length of each dimension in this . + /// + /// with the lengths of each dimension. + void IReadOnlyTensor, T>.GetLengths(Span destination) => _lengths.CopyTo(destination); + + + /// + /// Gets the strides of each dimension in this . + /// + /// with the strides of each dimension. + public ReadOnlySpan Strides => _strides; + + /// + /// Gets the strides of each dimension in this . + /// + /// with the strides of each dimension. + void IReadOnlyTensor, T>.GetStrides(scoped Span destination) => _strides.CopyTo(destination); + + bool ITensor, T>.IsReadOnly => false; + + /// + /// Returns a reference to specified element of the Tensor. + /// + /// + /// + /// + /// Thrown when index less than 0 or index greater than or equal to FlattenedLength + /// + public ref T this[params scoped ReadOnlySpan indexes] => ref AsTensorSpan()[indexes]; + + /// + /// Returns a reference to specified element of the Tensor. + /// + /// + /// + /// + /// Thrown when index less than 0 or index greater than or equal to FlattenedLength + /// + public ref T this[params scoped ReadOnlySpan indexes] => ref AsTensorSpan()[indexes]; + + /// + /// Returns a slice of the Tensor. + /// + /// + /// + /// + /// Thrown when any index is less than 0 or any index is greater than or equal to FlattenedLength + /// + public Tensor this[params ReadOnlySpan ranges] + { + get + { + if (ranges.Length != Rank) + ThrowHelper.ThrowIndexOutOfRangeException(); + + return Slice(ranges); + } + set + { + TensorSpan srcSpan; + if (ranges == ReadOnlySpan.Empty) + { + if (!Lengths.SequenceEqual(value.Lengths)) + ThrowHelper.ThrowArgument_SetSliceNoRange(nameof(value)); + srcSpan = AsTensorSpan().Slice(Lengths); + } + else + srcSpan = AsTensorSpan().Slice(ranges); + + if (!srcSpan.Lengths.SequenceEqual(value.Lengths)) + ThrowHelper.ThrowArgument_SetSliceInvalidShapes(nameof(value)); + + value.AsTensorSpan().CopyTo(srcSpan); + } + } + + /// + /// Returns the specified element of the Tensor. + /// + /// + /// + /// + /// Thrown when index less than 0 or index greater than or equal to FlattenedLength + /// + T ITensor, T>.this[params ReadOnlySpan indexes] + { + get + { + return this[indexes]; + } + set + { + this[indexes] = value; + } + } + + /// + /// Returns the specified element of the Tensor. + /// + /// + /// + /// + /// Thrown when index less than 0 or index greater than or equal to FlattenedLength + /// + T ITensor, T>.this[params ReadOnlySpan indexes] + { + get + { + return this[indexes]; + } + set + { + this[indexes] = value; + } + } + + /// + /// Returns the specified element of the ReadOnlyTensor. + /// + /// + /// + /// + /// Thrown when index less than 0 or index greater than or equal to FlattenedLength + /// + T IReadOnlyTensor, T>.this[params ReadOnlySpan indexes] => AsReadOnlyTensorSpan()[indexes]; + + /// + /// Returns the specified element of the ReadOnlyTensor. + /// + /// + /// + /// + /// Thrown when index less than 0 or index greater than or equal to FlattenedLength + /// + T IReadOnlyTensor, T>.this[params ReadOnlySpan indexes] => AsReadOnlyTensorSpan()[indexes]; + + /// + /// Returns a slice of the ReadOnlyTensor. + /// + /// + /// + /// + /// Thrown when any index is less than 0 or any index is greater than or equal to FlattenedLength + /// + Tensor IReadOnlyTensor, T>.this[params ReadOnlySpan ranges] + { + get + { + if (ranges.Length != Rank) + ThrowHelper.ThrowIndexOutOfRangeException(); + + return Slice(ranges); + } + } + + // REVIEW: WE WILL WANT THIS CHANGED FROM A BOOL TO SOME FILTER EXPRESSION. + /// + /// + /// + /// + /// + /// + public Tensor this[Tensor filter] + { + get + { + if (filter.Lengths.Length != Lengths.Length) + throw new ArgumentOutOfRangeException(nameof(filter), "Number of dimensions does not equal the number of dimensions in the span"); + + for (int i = 0; i < filter.Lengths.Length; i++) + { + if (filter.Lengths[i] != Lengths[i]) + ThrowHelper.ThrowArgument_FilterTensorMustEqualTensorLength(); + } + + Span srcSpan = _values; + Span filterSpan = filter._values; + + nint linearLength = TensorHelpers.CountTrueElements(filter); + + T[] values = _isPinned ? GC.AllocateArray((int)linearLength, _isPinned) : (new T[linearLength]); + int index = 0; + for (int i = 0; i < filterSpan.Length; i++) + { + if (filterSpan[i]) + { + values[i] = srcSpan[index++]; + } + } + + return new Tensor(values, [linearLength], _isPinned); + } + } + + public static implicit operator TensorSpan(Tensor value) => new TensorSpan(ref MemoryMarshal.GetArrayDataReference(value._values), value._lengths, value._strides, value._flattenedLength); + + public static implicit operator ReadOnlyTensorSpan(Tensor value) => new ReadOnlyTensorSpan(ref MemoryMarshal.GetArrayDataReference(value._values), value._lengths, value._strides, value.FlattenedLength); + + /// + /// Converts this to a pointing to the same backing memory."/> + /// + /// + public TensorSpan AsTensorSpan() => new TensorSpan(ref MemoryMarshal.GetArrayDataReference(_values), _lengths, _strides, _flattenedLength); + + /// + /// Converts this to a pointing to the same backing memory based on the provided ranges."/> + /// + /// The ranges you want in the . + /// based on the provided ranges. + public TensorSpan AsTensorSpan(params scoped ReadOnlySpan start) => AsTensorSpan().Slice(start); + + /// + /// Converts this to a pointing to the same backing memory based on the provided start locations."/> + /// + /// The start location you want in the . + /// based on the provided ranges. + public TensorSpan AsTensorSpan(params scoped ReadOnlySpan start) => Slice(start); + + /// + /// Converts this to a pointing to the same backing memory based on the provided start indexes."/> + /// + /// The ranges you want in the . + /// based on the provided ranges. + public TensorSpan AsTensorSpan(params scoped ReadOnlySpan startIndex) => AsTensorSpan().Slice(startIndex); + + /// + /// Converts this to a pointing to the same backing memory."/> + /// + /// + public ReadOnlyTensorSpan AsReadOnlyTensorSpan() => new ReadOnlyTensorSpan(ref MemoryMarshal.GetArrayDataReference(_values), _lengths, _strides, _flattenedLength); + + /// + /// Converts this to a pointing to the same backing memory based on the provided ranges."/> + /// + /// The ranges you want in the + /// + public ReadOnlyTensorSpan AsReadOnlyTensorSpan(params scoped ReadOnlySpan start) => AsTensorSpan().Slice(start); + + /// + /// Converts this to a pointing to the same backing memory based on the provided start locations."/> + /// + /// The start locations you want in the + /// + public ReadOnlyTensorSpan AsReadOnlyTensorSpan(params scoped ReadOnlySpan start) => Slice(start); + + /// + /// Converts this to a pointing to the same backing memory based on the provided start indexes."/> + /// + /// The start indexes you want in the + /// + public ReadOnlyTensorSpan AsReadOnlyTensorSpan(params scoped ReadOnlySpan startIndex) => AsTensorSpan().Slice(startIndex); + + /// + /// Returns a reference to the 0th element of the Tensor. If the Tensor is empty, returns null reference. + /// It can be used for pinning and is required to support the use of Tensor within a fixed statement. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public ref T GetPinnableReference() => ref AsTensorSpan().GetPinnableReference(); + + /// + /// Returns a reference to the 0th element of the ReadOnlyTensor. If the ReadOnlyTensor is empty, returns null reference. + /// It can be used for pinning and is required to support the use of ReadOnlyTensor within a fixed statement. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + ref readonly T IReadOnlyTensor, T>.GetPinnableReference() => ref AsReadOnlyTensorSpan().GetPinnableReference(); + + /// + /// Forms a slice out of the given tensor + /// + /// The ranges for the slice + /// as a copy of the provided ranges. + // REVIEW: CURRENTLY DOES A COPY. + public Tensor Slice(params ReadOnlySpan start) + { + if (start.Length != Lengths.Length) + throw new ArgumentOutOfRangeException(nameof(start), "Number of dimensions to slice does not equal the number of dimensions in the span"); + + TensorSpan s = AsTensorSpan(start); + T[] values = _isPinned ? GC.AllocateArray(checked((int)s.FlattenedLength), _isPinned) : (new T[s.FlattenedLength]); + var outTensor = new Tensor(values, s.Lengths.ToArray(), _isPinned); + s.CopyTo(outTensor); + return outTensor; + } + + /// + /// Forms a slice out of the given tensor + /// + /// The start indexes for the slice + /// as a copy of the provided ranges. + // REVIEW: CURRENTLY DOES A COPY. + public Tensor Slice(params ReadOnlySpan start) + { + NRange[] ranges = new NRange[start.Length]; + for (int i = 0; i < start.Length; i++) + { + ranges[i] = new NRange(start[i], new NIndex(0, fromEnd: true)); + } + return Slice(ranges); + } + + /// + /// Forms a slice out of the given tensor + /// + /// The start indexes for the slice + /// as a copy of the provided ranges. + // REVIEW: CURRENTLY DOES A COPY. + public Tensor Slice(params ReadOnlySpan startIndex) + { + NRange[] ranges = new NRange[startIndex.Length]; + for (int i = 0; i < startIndex.Length; i++) + { + ranges[i] = new NRange(startIndex[i], new NIndex(0, fromEnd: true)); + } + return Slice(ranges); + } + + /// + /// Clears the contents of this tensor. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public unsafe void Clear() => AsTensorSpan().Clear(); + + /// + /// Copies the contents of this tensor into destination span. If the source + /// and destinations overlap, this method behaves as if the original values in + /// a temporary location before the destination is overwritten. + /// + /// The span to copy items into. + /// + /// Thrown when the destination TensorSpan is shorter than the source Tensor. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyTo(TensorSpan destination) => AsTensorSpan().CopyTo(destination); + + /// + /// Fills the contents of this span with the given value. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Fill(T value) => AsTensorSpan().Fill(value); + + /// + /// Copies the contents of this tensor into destination span. If the source + /// and destinations overlap, this method behaves as if the original values in + /// a temporary location before the destination is overwritten. + /// + /// The span to copy items into. + /// If the destination span is shorter than the source tensor, this method + /// return false and no data is written to the destination. + public bool TryCopyTo(TensorSpan destination) => AsTensorSpan().TryCopyTo(destination); + + /// + /// Flattens the contents of this Tensor into the provided . + /// + /// The span to copy items into. + public void FlattenTo(Span destination) => AsTensorSpan().FlattenTo(destination); + + /// + /// Flattens the contents of this Tensor into the provided . + /// + /// The span to copy items into. + public bool TryFlattenTo(Span destination) => AsTensorSpan().TryFlattenTo(destination); + + // IEnumerable + /// + /// Gets an for the . + /// + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + // IEnumerable + /// + /// Gets an for the . + /// + /// + public IEnumerator GetEnumerator() => new Enumerator(this); + + /// + /// Gets an for the ."/> + /// + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + private struct Enumerator : IEnumerator + { + /// The span being enumerated. + private readonly Tensor _tensor; + /// + /// + /// + private nint[] _curIndices; + /// The total item count. + private nint _items; + + /// Initialize the enumerator. + /// The tensor to enumerate. + internal Enumerator(Tensor tensor) + { + _tensor = tensor; + _items = -1; + _curIndices = new nint[_tensor.Rank]; + _curIndices[_tensor.Rank - 1] = -1; + } + + /// Advances the enumerator to the next element of the span. + public bool MoveNext() + { + TensorSpanHelpers.AdjustIndexes(_tensor.Rank - 1, 1, ref _curIndices, _tensor.Lengths); + + _items++; + return _items < _tensor.FlattenedLength; + } + + /// + /// Resets the enumerator to the beginning of the span. + /// + public void Reset() + { + Array.Clear(_curIndices); + _curIndices[_tensor.Rank - 1] = -1; + } + + /// + /// + /// + public void Dispose() + { + + } + + /// + /// Current T value of the + /// + T IEnumerator.Current => _tensor[_curIndices]; + + /// + /// Current of the + /// + object? IEnumerator.Current => _tensor[_curIndices]; + } + + // REVIEW: PENDING API REVIEW TO DETERMINE IMPLEMENTATION + public override int GetHashCode() + { + throw new NotImplementedException(); + } + + /// + /// Get a string representation of the tensor. + /// + private string ToMetadataString() + { + var sb = new StringBuilder("["); + + int n = Rank; + if (n == 0) + { + sb.Append(']'); + } + else + { + for (int i = 0; i < n; i++) + { + sb.Append(Lengths[i]); + if (i + 1 < n) + sb.Append('x'); + } + + sb.Append(']'); + } + sb.Append($", type = {typeof(T)}, isPinned = {IsPinned}"); + + return sb.ToString(); + } + + /// + /// Creates a representation of the ."/> + /// + /// Maximum Length of each dimension + /// A representation of the + public string ToString(params ReadOnlySpan maximumLengths) + { + var sb = new StringBuilder(); + sb.AppendLine(ToMetadataString()); + sb.AppendLine("{"); + sb.Append(AsTensorSpan().ToString(10, 10)); + sb.AppendLine("}"); + return sb.ToString(); + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs new file mode 100644 index 000000000000..4d1fdffceddc --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs @@ -0,0 +1,2527 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using Microsoft.VisualBasic; +using System.Text; +using System.Buffers; +using System.Xml.Linq; + +#pragma warning disable CS8601 // Possible null reference assignment. +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. +#pragma warning disable 8500 // address / sizeof of managed types + +namespace System.Numerics.Tensors +{ + public static partial class Tensor + { + #region ToString + // REVIEW: WHAT SHOULD WE NAME THIS? WHERE DO WE WANT IT TO LIVE? + /// + /// Creates a representation of the ."/> + /// + /// The you want to represent as a string. + /// Maximum Length of each dimension + /// A representation of the + public static string ToString(this TensorSpan span, params scoped ReadOnlySpan maximumLengths) => ((ReadOnlyTensorSpan)span).ToString(maximumLengths); + + /// + /// Creates a representation of the ."/> + /// + /// + /// The you want to represent as a string. + /// Maximum Length of each dimension + public static string ToString(this ReadOnlyTensorSpan span, params scoped ReadOnlySpan maximumLengths) + { + var sb = new StringBuilder(); + scoped Span curIndexes; + nint[]? curIndexesArray; + if (span.Rank > 6) + { + curIndexesArray = ArrayPool.Shared.Rent(span.Rank); + curIndexes = curIndexesArray; + } + else + { + curIndexesArray = null; + curIndexes = stackalloc nint[span.Rank]; + } + + nint copiedValues = 0; + + T[] values = new T[span.Lengths[span.Rank - 1]]; + while (copiedValues < span._flattenedLength) + { + var sp = new ReadOnlyTensorSpan(ref Unsafe.Add(ref span._reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, span.Strides, span.Lengths)), [span.Lengths[span.Rank - 1]], [1], span.Lengths[span.Rank - 1]); + sb.Append('{'); + sp.FlattenTo(values); + sb.Append(string.Join(",", values)); + sb.AppendLine("}"); + + TensorSpanHelpers.AdjustIndexes(span.Rank - 2, 1, curIndexes, span._lengths); + copiedValues += span.Lengths[span.Rank - 1]; + } + + if (curIndexesArray != null) + ArrayPool.Shared.Return(curIndexesArray); + + return sb.ToString(); + } + #endregion + + #region Resize + /// + /// Creates a new , allocates new memory, and copies the data from . If the final shape is smaller all data after + /// that point is ignored. + /// + /// Input . + /// of the desired new shape. + public static Tensor Resize(Tensor input, scoped ReadOnlySpan shape) + where T : IEquatable, IEqualityOperators + { + nint newSize = TensorSpanHelpers.CalculateTotalLength(shape); + T[] values = input.IsPinned ? GC.AllocateArray((int)newSize) : (new T[newSize]); + Tensor output = new Tensor(values, shape, false); + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input.AsTensorSpan()._reference, (int)input.FlattenedLength); + Span ospan = MemoryMarshal.CreateSpan(ref output.AsTensorSpan()._reference, (int)output.FlattenedLength); + if (newSize > input.FlattenedLength) + TensorSpanHelpers.Memmove(ospan, span, input.FlattenedLength); + else + TensorSpanHelpers.Memmove(ospan, span, newSize); + + return output; + } + + /// + /// Creates a new , allocates new managed memory, and copies the data from . If the final shape is smaller all data after + /// + /// Input . + /// of the desired new shape. + public static TensorSpan Resize(TensorSpan input, scoped ReadOnlySpan shape) + where T : IEquatable, IEqualityOperators + { + nint newSize = TensorSpanHelpers.CalculateTotalLength(shape); + T[] values = new T[newSize]; + TensorSpan output = new TensorSpan(values, 0, shape, default); + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + if (newSize > input.FlattenedLength) + TensorSpanHelpers.Memmove(ospan, span, input.FlattenedLength); + else + TensorSpanHelpers.Memmove(ospan, span, newSize); + + return output; + } + #endregion + + #region Broadcast + /// + /// Broadcast the data from to the new shape . Creates a new and allocates new memory. + /// If the shape of the is not compatible with the new shape, an exception is thrown. + /// + /// Input . + /// of the desired new shape. + /// Thrown when the shapes are not broadcast compatible. + public static Tensor Broadcast(Tensor input, scoped ReadOnlySpan shape) + where T : IEquatable, IEqualityOperators + { + Tensor intermediate = BroadcastTo(input, shape); + return Tensor.Create(intermediate.ToArray(), intermediate.Lengths); + } + + // Lazy/non-copy broadcasting, internal only for now. + /// + /// Broadcast the data from to the new shape . Creates a new + /// but no memory is allocated. It manipulates the strides to achieve this affect. + /// If the shape of the is not compatible with the new shape, an exception is thrown. + /// + /// Input . + /// of the desired new shape. + /// Thrown when the shapes are not broadcast compatible. + internal static Tensor BroadcastTo(Tensor input, ReadOnlySpan shape) + where T : IEquatable, IEqualityOperators + { + if (input.Lengths.SequenceEqual(shape)) + return new Tensor(input._values, shape, false); + + if (!TensorHelpers.AreShapesBroadcastCompatible(input.Lengths, shape)) + ThrowHelper.ThrowArgument_ShapesNotBroadcastCompatible(); + + nint newSize = TensorSpanHelpers.CalculateTotalLength(shape); + + if (newSize == input.FlattenedLength) + return Reshape(input, shape); + + nint[] intermediateShape = TensorHelpers.GetIntermediateShape(input.Lengths, shape.Length); + nint[] strides = new nint[shape.Length]; + + nint stride = 1; + + for (int i = strides.Length - 1; i >= 0; i--) + { + if ((intermediateShape[i] == 1 && shape[i] != 1) || (intermediateShape[i] == 1 && shape[i] == 1)) + strides[i] = 0; + else + { + strides[i] = stride; + stride *= intermediateShape[i]; + } + } + + Tensor output = new Tensor(input._values, shape, strides); + + return output; + } + + // Lazy/non-copy broadcasting, internal only for now. + /// + /// Broadcast the data from to the new shape . Creates a new + /// but no memory is allocated. It manipulates the strides to achieve this affect. + /// If the shape of the is not compatible with the new shape, an exception is thrown. + /// + /// Input . + /// of the desired new shape. + /// Thrown when the shapes are not broadcast compatible. + internal static TensorSpan BroadcastTo(TensorSpan input, scoped ReadOnlySpan shape) + where T : IEquatable, IEqualityOperators + { + if (input.Lengths.SequenceEqual(shape)) + return new TensorSpan(ref input._reference, shape, input.Strides, input._memoryLength); + + if (!TensorHelpers.AreShapesBroadcastCompatible(input.Lengths, shape)) + ThrowHelper.ThrowArgument_ShapesNotBroadcastCompatible(); + + nint newSize = TensorSpanHelpers.CalculateTotalLength(shape); + + if (newSize == input.FlattenedLength) + return Reshape(input, shape); + + nint[] intermediateShape = TensorHelpers.GetIntermediateShape(input.Lengths, shape.Length); + nint[] strides = new nint[shape.Length]; + + nint stride = 1; + + for (int i = strides.Length - 1; i >= 0; i--) + { + if ((intermediateShape[i] == 1 && shape[i] != 1) || (intermediateShape[i] == 1 && shape[i] == 1)) + strides[i] = 0; + else + { + strides[i] = stride; + stride *= intermediateShape[i]; + } + } + + TensorSpan output = new TensorSpan(ref input._reference, shape, strides, input._memoryLength); + + return output; + } + #endregion + + #region Reverse + /// + /// Reverse the order of elements in the along the given axis. The shape of the tensor is preserved, but the elements are reordered. + /// defaults to -1 when not provided, which reverses the entire tensor. + /// + /// Input . + /// Axis along which to reverse over. The default, -1, will reverse over all of the axes of the left tensor. + public static Tensor Reverse(Tensor input, nint axis = -1) + where T : IEquatable, IEqualityOperators + { + T[] values = input.IsPinned ? GC.AllocateArray((int)input._flattenedLength) : (new T[input._flattenedLength]); + Tensor output = new Tensor(values, input.Lengths.ToArray(), input.Strides.ToArray()); + if (axis == -1) + { + int index = 0; + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input.FlattenedLength); + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output.FlattenedLength); + for (int i = (int)input.FlattenedLength - 1; i >= 0; i--) + { + ospan[index++] = span[i]; + } + } + else + { + nint copyLength = 1; + for (nint i = axis; i < input.Lengths.Length; i++) + { + copyLength *= input.Lengths[(int)i]; + } + copyLength /= input.Lengths[(int)axis]; + + scoped Span oIndices; + nint[]? oIndicesArray; + scoped Span iIndices; + nint[]? iIndicesArray; + if (input.Rank > 6) + { + oIndicesArray = ArrayPool.Shared.Rent(input.Rank); + oIndices = oIndicesArray; + iIndicesArray = ArrayPool.Shared.Rent(input.Rank); + iIndices = iIndicesArray; + } + else + { + oIndicesArray = null; + oIndices = stackalloc nint[input.Rank]; + iIndicesArray = null; + iIndices = stackalloc nint[input.Rank]; + } + + iIndices[(int)axis] = input.Lengths[(int)axis] - 1; + nint copiedValues = 0; + TensorSpan islice = input.AsTensorSpan().Slice(input.Lengths); + TensorSpan oslice = output.AsTensorSpan().Slice(output._lengths); + while (copiedValues < input._flattenedLength) + { + TensorSpanHelpers.Memmove(ref Unsafe.Add(ref oslice._reference, TensorSpanHelpers.ComputeLinearIndex(oIndices, input.Strides, input.Lengths)), ref Unsafe.Add(ref islice._reference, TensorSpanHelpers.ComputeLinearIndex(iIndices, islice.Strides, islice.Lengths)), copyLength); + TensorSpanHelpers.AdjustIndexes((int)axis, 1, oIndices, input._lengths); + TensorSpanHelpers.AdjustIndexesDown((int)axis, 1, iIndices, input._lengths); + copiedValues += copyLength; + } + + if (oIndicesArray != null && iIndicesArray != null) + { + ArrayPool.Shared.Return(oIndicesArray); + ArrayPool.Shared.Return(iIndicesArray); + } + } + + return output; + } + + /// + /// Reverse the order of elements in the along the given axis. The shape of the tensor is preserved, but the elements are reordered. + /// defaults to -1 when not provided, which reverses the entire span. + /// + /// Input . + /// Axis along which to reverse over. The default, -1, will reverse over all of the axes of the left span. + public static TensorSpan Reverse(TensorSpan input, nint axis = -1) + where T : IEquatable, IEqualityOperators + { + if (axis == -1) + { + nint index = input.FlattenedLength - 1; + Span span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + T temp; + for (int i = 0; i <= input.FlattenedLength / 2; i++) + { + temp = span[(int)index]; + span[(int)index] = span[i]; + span[i] = temp; + } + } + else + { + T[] values = new T[input.FlattenedLength]; + + nint copyLength = 1; + for (nint i = axis; i < input.Lengths.Length; i++) + { + copyLength *= input.Lengths[(int)i]; + } + copyLength /= input.Lengths[(int)axis]; + + scoped Span oIndices; + nint[]? oIndicesArray; + scoped Span iIndices; + nint[]? iIndicesArray; + if (input.Rank > 6) + { + oIndicesArray = ArrayPool.Shared.Rent(input.Rank); + oIndices = oIndicesArray; + iIndicesArray = ArrayPool.Shared.Rent(input.Rank); + iIndices = iIndicesArray; + } + else + { + oIndicesArray = null; + oIndices = stackalloc nint[input.Rank]; + iIndicesArray = null; + iIndices = stackalloc nint[input.Rank]; + } + + iIndices[(int)axis] = input.Lengths[(int)axis] - 1; + nint copiedValues = 0; + TensorSpan islice = input.Slice(input.Lengths); + while (copiedValues < input.FlattenedLength) + { + TensorSpanHelpers.Memmove(ref Unsafe.Add(ref values, TensorSpanHelpers.ComputeLinearIndex(oIndices, input.Strides, input.Lengths)), ref Unsafe.Add(ref islice._reference, TensorSpanHelpers.ComputeLinearIndex(iIndices, islice.Strides, islice.Lengths)), copyLength); + TensorSpanHelpers.AdjustIndexes((int)axis, 1, oIndices, input.Lengths); + TensorSpanHelpers.AdjustIndexesDown((int)axis, 1, iIndices, input.Lengths); + copiedValues += copyLength; + } + TensorSpanHelpers.Memmove(ref input._reference, ref values[0], input.FlattenedLength); + + if (oIndicesArray != null && iIndicesArray != null) + { + ArrayPool.Shared.Return(oIndicesArray); + ArrayPool.Shared.Return(iIndicesArray); + } + } + + return input; + } + #endregion + + #region Split + /// + /// Split a into along the given . If the tensor cannot be split + /// evenly on the given an exception is thrown. + /// + /// Input . + /// How many times to split the + /// The axis to split on. + public static Tensor[] Split(Tensor input, nint numSplits, nint axis) + where T : IEquatable, IEqualityOperators + { + if (input.Lengths[(int)axis] % numSplits != 0) + ThrowHelper.ThrowArgument_SplitNotSplitEvenly(); + + Tensor[] outputs = new Tensor[numSplits]; + + nint totalToCopy = input.FlattenedLength / numSplits; + nint copyLength = 1; + for (nint i = axis; i < input.Lengths.Length; i++) + { + copyLength *= input.Lengths[(int)i]; + } + copyLength /= numSplits; + nint[] newShape = input.Lengths.ToArray(); + newShape[(int)axis] = newShape[(int)axis] / numSplits; + + scoped Span oIndices; + nint[]? oIndicesArray; + scoped Span iIndices; + nint[]? iIndicesArray; + if (input.Rank > 6) + { + oIndicesArray = ArrayPool.Shared.Rent(input.Rank); + oIndices = oIndicesArray; + iIndicesArray = ArrayPool.Shared.Rent(input.Rank); + iIndices = iIndicesArray; + } + else + { + oIndicesArray = null; + oIndices = stackalloc nint[input.Rank]; + iIndicesArray = null; + iIndices = stackalloc nint[input.Rank]; + } + + for (int i = 0; i < outputs.Length; i++) + { + T[] values = input.IsPinned ? GC.AllocateArray((int)totalToCopy) : (new T[(int)totalToCopy]); + outputs[i] = new Tensor(values, newShape); + oIndices.Clear(); + iIndices.Clear(); + + iIndices[(int)axis] = i; + TensorSpan islice = input.AsTensorSpan().Slice(input.Lengths); + TensorSpan oslice = outputs[i].AsTensorSpan().Slice(outputs[i]._lengths); + + nint copiedValues = 0; + while (copiedValues < totalToCopy) + { + TensorSpanHelpers.Memmove(ref Unsafe.Add(ref oslice._reference, TensorSpanHelpers.ComputeLinearIndex(oIndices, outputs[0].Strides, outputs[0].Lengths)), ref Unsafe.Add(ref islice._reference, TensorSpanHelpers.ComputeLinearIndex(iIndices, islice.Strides, islice.Lengths)), copyLength); + TensorSpanHelpers.AdjustIndexes((int)axis, 1, oIndices, outputs[i]._lengths); + TensorSpanHelpers.AdjustIndexes((int)axis - 1, 1, iIndices, input._lengths); + copiedValues += copyLength; + } + } + + if (oIndicesArray != null && iIndicesArray != null) + { + ArrayPool.Shared.Return(oIndicesArray); + ArrayPool.Shared.Return(iIndicesArray); + } + + return outputs; + } + #endregion + + #region SetSlice + // REVIEW: WHAT DO WE WANT TO CALL THIS? COPYTO? IT DOES FIT IN WITH THE EXISTING COPY TO CONVENTIONS FOR VECTOR (albeit backwards). + /// + /// Sets a slice of the given with the provided for the given + /// + /// Input . + /// The values you want to set in the . + /// The ranges you want to set. + public static Tensor SetSlice(this Tensor tensor, Tensor values, params scoped ReadOnlySpan ranges) + where T : IEquatable, IEqualityOperators + { + TensorSpan srcSpan; + if (ranges == ReadOnlySpan.Empty) + { + if (!tensor.Lengths.SequenceEqual(values.Lengths)) + ThrowHelper.ThrowArgument_SetSliceNoRange(nameof(values)); + srcSpan = tensor.AsTensorSpan().Slice(tensor.Lengths); + } + else + srcSpan = tensor.AsTensorSpan().Slice(ranges); + + if (!srcSpan.Lengths.SequenceEqual(values.Lengths)) + ThrowHelper.ThrowArgument_SetSliceInvalidShapes(nameof(values)); + + values.AsTensorSpan().CopyTo(srcSpan); + + return tensor; + } + #endregion + + #region FilteredUpdate + // REVIEW: PYTORCH/NUMPY DO THIS. + // t0[t0 < 2] = -1; + // OR SHOULD THIS BE AN OVERLOAD OF FILL THAT TAKES IN A FUNC TO KNOW WHICH ONE TO UPDATE? + /// + /// Updates the tensor with the where the is true. + /// + /// Input . + /// Input filter where if the index is true then it will update the . + /// Value to update in the . + public static Tensor FilteredUpdate(Tensor tensor, Tensor filter, T value) + where T : IEquatable, IEqualityOperators + { + if (filter.Lengths.Length != tensor.Lengths.Length) + ThrowHelper.ThrowArgument_DimensionsNotSame(nameof(filter)); + + Span srcSpan = MemoryMarshal.CreateSpan(ref tensor._values[0], (int)tensor._flattenedLength); + Span filterSpan = MemoryMarshal.CreateSpan(ref filter._values[0], (int)tensor._flattenedLength); + + for (int i = 0; i < filterSpan.Length; i++) + { + if (filterSpan[i]) + { + srcSpan[i] = value; + } + } + + return tensor; + } + + /// + /// Updates the tensor with the where the is true. + /// If dmesions are not the same an exception is thrown. + /// + /// Input . + /// Input filter where if the index is true then it will update the . + /// Values to update in the . + public static Tensor FilteredUpdate(Tensor tensor, Tensor filter, Tensor values) + where T : IEquatable, IEqualityOperators + { + if (filter.Lengths.Length != tensor.Lengths.Length) + ThrowHelper.ThrowArgument_DimensionsNotSame(nameof(filter)); + if (values.Rank != 1) + ThrowHelper.ThrowArgument_1DTensorRequired(nameof(values)); + + nint numTrueElements = TensorHelpers.CountTrueElements(filter); + if (numTrueElements != values._flattenedLength) + ThrowHelper.ThrowArgument_IncorrectNumberOfFilterItems(nameof(values)); + + Span dstSpan = MemoryMarshal.CreateSpan(ref tensor._values[0], (int)tensor._flattenedLength); + Span filterSpan = MemoryMarshal.CreateSpan(ref filter._values[0], (int)tensor._flattenedLength); + Span valuesSpan = MemoryMarshal.CreateSpan(ref values._values[0], (int)values._flattenedLength); + + int index = 0; + for (int i = 0; i < filterSpan.Length; i++) + { + if (filterSpan[i]) + { + dstSpan[i] = valuesSpan[index++]; + } + } + + return tensor; + } + #endregion + + #region SequenceEqual + /// + /// Compares the elements of two for equality. If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size + /// before they are compared. It returns a where the value is true if the elements are equal and false if they are not."/> + /// + /// First to compare. + /// Second to compare. + /// A where the value is true if the elements are equal and false if they are not. + public static Tensor SequenceEqual(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators + { + Tensor result; + if (TensorHelpers.AreShapesTheSame(left, right)) + { + result = Tensor.Create(left.Lengths, false); + + for (int i = 0; i < left.FlattenedLength; i++) + { + result._values[i] = left._values[i] == right._values[i]; + } + } + else + { + nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); + result = Tensor.Create(newSize, false); + Tensor broadcastedLeft = BroadcastTo(left, newSize); + Tensor broadcastedRight = BroadcastTo(right, newSize); + + scoped Span curIndex; + nint[]? curIndexArray; + + if (broadcastedRight.Lengths.Length > 6) + { + curIndexArray = ArrayPool.Shared.Rent(broadcastedRight.Lengths.Length); + curIndex = curIndexArray; + } + else + { + curIndexArray = null; + curIndex = stackalloc nint[broadcastedRight.Lengths.Length]; + } + + for (int i = 0; i < broadcastedLeft.FlattenedLength; i++) + { + result._values[i] = broadcastedLeft[curIndex] == broadcastedRight[curIndex]; + TensorSpanHelpers.AdjustIndexes(broadcastedRight.Rank - 1, 1, curIndex, broadcastedRight.Lengths); + } + + if (curIndexArray != null) + ArrayPool.Shared.Return(curIndexArray); + } + + return result; + } + #endregion + + #region LessThan + /// + /// Compares the elements of two to see which elements of are less than . + /// If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size before they are compared. + /// It returns a where the value is true if the elements in are less than + /// and false if they are not."/> + /// + /// First to compare. + /// Second to compare. + /// A where the value is true if the elements in are less than and + /// false if they are not. + public static Tensor LessThan(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators, IComparisonOperators + { + Tensor result; + if (TensorHelpers.AreShapesTheSame(left, right)) + { + result = Tensor.Create(left.Lengths, false); + + for (int i = 0; i < left.FlattenedLength; i++) + { + result._values[i] = left._values[i] < right._values[i]; + } + } + else + { + nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); + result = Tensor.Create(newSize, false); + Tensor broadcastedLeft = BroadcastTo(left, newSize); + Tensor broadcastedRight = BroadcastTo(right, newSize); + + scoped Span curIndex; + nint[]? curIndexArray; + + if (broadcastedRight.Lengths.Length > 6) + { + curIndexArray = ArrayPool.Shared.Rent(broadcastedRight.Lengths.Length); + curIndex = curIndexArray; + } + else + { + curIndexArray = null; + curIndex = stackalloc nint[broadcastedRight.Lengths.Length]; + } + + for (int i = 0; i < broadcastedLeft.FlattenedLength; i++) + { + result._values[i] = broadcastedLeft[curIndex] < broadcastedRight[curIndex]; + TensorSpanHelpers.AdjustIndexes(broadcastedRight.Rank - 1, 1, curIndex, broadcastedRight.Lengths); + } + + if (curIndexArray != null) + ArrayPool.Shared.Return(curIndexArray); + } + + return result; + } + + /// + /// Compares the elements of a to see which elements are less than . + /// It returns a where the value is true if the elements in are less than + /// and false if they are not."/> + /// + /// to compare. + /// to compare against . + /// where the value is true if the elements in are less than + /// and false if they are not. + public static Tensor LessThan(Tensor left, T right) + where T : IEquatable, IEqualityOperators, IComparisonOperators + { + Tensor result = Tensor.Create(left.Lengths, false); + + for (int i = 0; i < left.FlattenedLength; i++) + { + result._values[i] = left._values[i] < right; + } + return result; + } + + /// + /// Compares the elements of two to see if any elements of are less than . + /// If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size before they are compared. + /// It returns a where the value is true if any elements in are less than . + /// + /// First to compare. + /// Second to compare against. + /// where the value is true if any elements in are less than . + public static bool LessThanAny(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators, IComparisonOperators + { + if (TensorHelpers.AreShapesTheSame(left, right)) + { + for (int i = 0; i < left.FlattenedLength; i++) + { + if (left._values[i] < right._values[i]) + return true; + } + } + else + { + nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); + Tensor broadcastedLeft = BroadcastTo(left, newSize); + Tensor broadcastedRight = BroadcastTo(right, newSize); + + scoped Span curIndex; + nint[]? curIndexArray; + + if (broadcastedRight.Lengths.Length > 6) + { + curIndexArray = ArrayPool.Shared.Rent(broadcastedRight.Lengths.Length); + curIndex = curIndexArray; + } + else + { + curIndexArray = null; + curIndex = stackalloc nint[broadcastedRight.Lengths.Length]; + } + + for (int i = 0; i < broadcastedLeft.FlattenedLength; i++) + { + if (broadcastedLeft[curIndex] < broadcastedRight[curIndex]) + return true; + TensorSpanHelpers.AdjustIndexes(broadcastedRight.Rank - 1, 1, curIndex, broadcastedRight.Lengths); + } + + if (curIndexArray != null) + ArrayPool.Shared.Return(curIndexArray); + } + + return false; + } + + /// + /// Compares the elements of two to see if all elements of are less than . + /// If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size before they are compared. + /// It returns a where the value is true if all elements in are less than . + /// + /// First to compare. + /// Second to compare against. + /// where the value is true if all elements in are less than . + public static bool LessThanAll(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators, IComparisonOperators + { + if (TensorHelpers.AreShapesTheSame(left, right)) + { + for (int i = 0; i < left.FlattenedLength; i++) + { + if (left._values[i] > right._values[i]) + return false; + } + } + else + { + nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); + Tensor broadcastedLeft = BroadcastTo(left, newSize); + Tensor broadcastedRight = BroadcastTo(right, newSize); + + scoped Span curIndex; + nint[]? curIndexArray; + + if (broadcastedRight.Lengths.Length > 6) + { + curIndexArray = ArrayPool.Shared.Rent(broadcastedRight.Lengths.Length); + curIndex = curIndexArray; + } + else + { + curIndexArray = null; + curIndex = stackalloc nint[broadcastedRight.Lengths.Length]; + } + + for (int i = 0; i < broadcastedLeft.FlattenedLength; i++) + { + if (broadcastedLeft[curIndex] > broadcastedRight[curIndex]) + return false; + TensorSpanHelpers.AdjustIndexes(broadcastedRight.Rank - 1, 1, curIndex, broadcastedRight.Lengths); + } + + if (curIndexArray != null) + ArrayPool.Shared.Return(curIndexArray); + } + return true; + } + #endregion + + #region GreaterThan + /// + /// Compares the elements of two to see which elements of are greater than . + /// If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size before they are compared. + /// It returns a where the value is true if the elements in are greater than + /// and false if they are not."/> + /// + /// First to compare. + /// Second to compare. + /// A where the value is true if the elements in are greater than and + /// false if they are not. + public static Tensor GreaterThan(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators, IComparisonOperators + { + Tensor result; + if (TensorHelpers.AreShapesTheSame(left, right)) + { + result = Tensor.Create(left.Lengths, false); + + for (int i = 0; i < left.FlattenedLength; i++) + { + result._values[i] = left._values[i] > right._values[i]; + } + } + else + { + nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); + result = Tensor.Create(newSize, false); + Tensor broadcastedLeft = BroadcastTo(left, newSize); + Tensor broadcastedRight = BroadcastTo(right, newSize); + + scoped Span curIndex; + nint[]? curIndexArray; + + if (broadcastedRight.Lengths.Length > 6) + { + curIndexArray = ArrayPool.Shared.Rent(broadcastedRight.Lengths.Length); + curIndex = curIndexArray; + } + else + { + curIndexArray = null; + curIndex = stackalloc nint[broadcastedRight.Lengths.Length]; + } + + for (int i = 0; i < broadcastedLeft.FlattenedLength; i++) + { + result._values[i] = broadcastedLeft[curIndex] > broadcastedRight[curIndex]; + TensorSpanHelpers.AdjustIndexes(broadcastedRight.Rank - 1, 1, curIndex, broadcastedRight.Lengths); + } + + if (curIndexArray != null) + ArrayPool.Shared.Return(curIndexArray); + } + + return result; + } + + /// + /// Compares the elements of a to see which elements are greater than . + /// It returns a where the value is true if the elements in are greater than + /// and false if they are not."/> + /// + /// to compare. + /// to compare against . + /// where the value is true if the elements in are greater than + /// and false if they are not. + public static Tensor GreaterThan(Tensor left, T right) + where T : IEquatable, IEqualityOperators, IComparisonOperators + { + Tensor result = Tensor.Create(left.Lengths, false); + + for (int i = 0; i < left.FlattenedLength; i++) + { + result._values[i] = left._values[i] > right; + } + return result; + } + + /// + /// Compares the elements of two to see if any elements of are greater than . + /// If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size before they are compared. + /// It returns a where the value is true if any elements in are greater than . + /// + /// First to compare. + /// Second to compare against. + /// where the value is true if any elements in are greater than . + public static bool GreaterThanAny(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators, IComparisonOperators + { + if (TensorHelpers.AreShapesTheSame(left, right)) + { + + for (int i = 0; i < left.FlattenedLength; i++) + { + if (left._values[i] > right._values[i]) + return true; + } + } + else + { + nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); + Tensor broadcastedLeft = BroadcastTo(left, newSize); + Tensor broadcastedRight = BroadcastTo(right, newSize); + + scoped Span curIndex; + nint[]? curIndexArray; + + if (broadcastedRight.Lengths.Length > 6) + { + curIndexArray = ArrayPool.Shared.Rent(broadcastedRight.Lengths.Length); + curIndex = curIndexArray; + } + else + { + curIndexArray = null; + curIndex = stackalloc nint[broadcastedRight.Lengths.Length]; + } + + for (int i = 0; i < broadcastedLeft.FlattenedLength; i++) + { + if (broadcastedLeft[curIndex] > broadcastedRight[curIndex]) + return true; + TensorSpanHelpers.AdjustIndexes(broadcastedRight.Rank - 1, 1, curIndex, broadcastedRight.Lengths); + } + + if (curIndexArray != null) + ArrayPool.Shared.Return(curIndexArray); + } + return false; + } + + /// + /// Compares the elements of two to see if all elements of are greater than . + /// If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size before they are compared. + /// It returns a where the value is true if all elements in are greater than . + /// + /// First to compare. + /// Second to compare against. + /// where the value is true if all elements in are greater than . + public static bool GreaterThanAll(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators, IComparisonOperators + { + if (TensorHelpers.AreShapesTheSame(left, right)) + { + + for (int i = 0; i < left.FlattenedLength; i++) + { + if (left._values[i] < right._values[i]) + return false; + } + } + else + { + nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); + Tensor broadcastedLeft = BroadcastTo(left, newSize); + Tensor broadcastedRight = BroadcastTo(right, newSize); + + scoped Span curIndex; + nint[]? curIndexArray; + + if (broadcastedRight.Lengths.Length > 6) + { + curIndexArray = ArrayPool.Shared.Rent(broadcastedRight.Lengths.Length); + curIndex = curIndexArray; + } + else + { + curIndexArray = null; + curIndex = stackalloc nint[broadcastedRight.Lengths.Length]; + } + + for (int i = 0; i < broadcastedLeft.FlattenedLength; i++) + { + if (broadcastedLeft[curIndex] < broadcastedRight[curIndex]) + return false; + TensorSpanHelpers.AdjustIndexes(broadcastedRight.Rank - 1, 1, curIndex, broadcastedRight.Lengths); + } + + if (curIndexArray != null) + ArrayPool.Shared.Return(curIndexArray); + } + return true; + } + #endregion + + #region Stack + // REVIEW: NEEDS A DIFFERENT NAME? + // JUST AN OVERLOAD FOR CONCATENATE? + /// + /// Join an array of along a new axis. The axis parameter specifies the index of the new axis in the dimensions of the result and + /// defaults to 0. All tensors must have the same shape. + /// + /// Array of . + /// Index of where the new axis will be. Defaults to 0. + public static Tensor Stack(Tensor[] input, int axis = 0) + where T : IEquatable, IEqualityOperators + { + if (input.Length < 2) + ThrowHelper.ThrowArgument_StackTooFewTensors(); + if (axis < 0) + axis = input.Rank - axis; + + Tensor[] outputs = new Tensor[input.Length]; + for (int i = 0; i < input.Length; i++) + { + outputs[i] = Tensor.Unsqueeze(input[0], axis); + } + return Tensor.Concatenate(outputs, axis); + } + #endregion + + #region Reshape + // REVIEW: SENTINAL VALUE? CONSTANT VALUE FOR -1 WILDCARD? + /// + /// Reshapes the tensor to the specified . If one of the lengths is -1, it will be calculated automatically. + /// Does not change the length of the underlying memory nor does it allocate new memory. If the new shape is not compatible with the old shape, + /// an exception is thrown. + /// + /// you want to reshape. + /// with the new dimensions. + public static Tensor Reshape(this Tensor input, params scoped ReadOnlySpan lengths) + where T : IEquatable, IEqualityOperators + { + nint[] arrLengths = lengths.ToArray(); + // Calculate wildcard info. + if (lengths.Contains(-1)) + { + if (lengths.Count(-1) > 1) + ThrowHelper.ThrowArgument_OnlyOneWildcard(); + nint tempTotal = input._flattenedLength; + for (int i = 0; i < lengths.Length; i++) + { + if (lengths[i] != -1) + { + tempTotal /= lengths[i]; + } + } + arrLengths[lengths.IndexOf(-1)] = tempTotal; + + } + + nint tempLinear = TensorSpanHelpers.CalculateTotalLength(arrLengths); + if (tempLinear != input.FlattenedLength) + ThrowHelper.ThrowArgument_InvalidReshapeDimensions(); + nint[] strides = TensorSpanHelpers.CalculateStrides(arrLengths); + return new Tensor(input._values, arrLengths, strides); + } + + /// + /// Reshapes the tensor to the specified . If one of the lengths is -1, it will be calculated automatically. + /// Does not change the length of the underlying memory nor does it allocate new memory. If the new shape is not compatible with the old shape, + /// an exception is thrown. + /// + /// you want to reshape. + /// with the new dimensions. + public static TensorSpan Reshape(this TensorSpan input, params scoped ReadOnlySpan lengths) + where T : IEquatable, IEqualityOperators + { + nint[] arrLengths = lengths.ToArray(); + // Calculate wildcard info. + if (lengths.Contains(-1)) + { + if (lengths.Count(-1) > 1) + ThrowHelper.ThrowArgument_OnlyOneWildcard(); + nint tempTotal = input.FlattenedLength; + for (int i = 0; i < lengths.Length; i++) + { + if (lengths[i] != -1) + { + tempTotal /= lengths[i]; + } + } + arrLengths[lengths.IndexOf(-1)] = tempTotal; + + } + + nint tempLinear = TensorSpanHelpers.CalculateTotalLength(arrLengths); + if (tempLinear != input.FlattenedLength) + ThrowHelper.ThrowArgument_InvalidReshapeDimensions(); + nint[] strides = TensorSpanHelpers.CalculateStrides(arrLengths); + return new TensorSpan(ref input._reference, arrLengths, strides, input._memoryLength); + } + #endregion + + #region Squeeze + // REVIEW: NAME? + /// + /// Removes axis of length one from the . defaults to -1 and will remove all axis with length of 1. + /// If is specified, it will only remove that axis and if it is not of length one it will throw an exception. + /// + /// The to remove axis of length 1. + /// The axis to remove. Defaults to -1 which removes all axis of length 1. + public static Tensor Squeeze(Tensor input, int axis = -1) + where T : IEquatable, IEqualityOperators + { + if (axis >= input.Rank) + ThrowHelper.ThrowArgument_AxisLargerThanRank(); + + nint[] lengths; + nint[] strides; + + List tempLengths = new List(); + if (axis == -1) + { + for (int i = 0; i < input.Lengths.Length; i++) + { + if (input.Lengths[i] != 1) + { + tempLengths.Add(input.Lengths[i]); + } + } + lengths = tempLengths.ToArray(); + strides = TensorSpanHelpers.CalculateStrides(lengths); + } + else + { + if (input.Lengths[axis] != 1) + { + ThrowHelper.ThrowArgument_InvalidSqueezeAxis(); + } + for (int i = 0; i < input.Lengths.Length; i++) + { + if (i != axis) + { + tempLengths.Add(input.Lengths[i]); + } + } + lengths = tempLengths.ToArray(); + strides = TensorSpanHelpers.CalculateStrides(lengths); + } + + return new Tensor(input._values, lengths, strides); + } + #endregion + + #region Unsqueeze + // REVIEW: NAME? NUMPY CALLS THIS expand_dims. + /// + /// Insert a new axis of length 1 that will appear at the axis position. + /// + /// The to remove axis of length 1. + /// The axis to add. + public static Tensor Unsqueeze(Tensor input, int axis) + where T : IEquatable, IEqualityOperators + { + if (axis > input.Lengths.Length) + ThrowHelper.ThrowArgument_AxisLargerThanRank(); + if (axis < 0) + axis = input.Rank - axis; + + List tempLengths = input._lengths.ToList(); + tempLengths.Insert(axis, 1); + nint[] lengths = tempLengths.ToArray(); + nint[] strides = TensorSpanHelpers.CalculateStrides(lengths); + return new Tensor(input._values, lengths, strides); + } + #endregion + + #region Concatenate + /// + /// Join a sequence of tensors along an existing axis. + /// + /// The tensors must have the same shape, except in the dimension corresponding to axis (the first, by default). + /// The axis along which the tensors will be joined. If axis is -1, arrays are flattened before use. Default is 0. + public static Tensor Concatenate(ReadOnlySpan> tensors, int axis = 0) + where T : IEquatable, IEqualityOperators + { + if (tensors.Length < 2) + ThrowHelper.ThrowArgument_ConcatenateTooFewTensors(); + + if (axis < -1 || axis > tensors[0].Rank) + ThrowHelper.ThrowArgument_InvalidAxis(); + + // Calculate total space needed. + nint totalLength = 0; + for (int i = 0; i < tensors.Length; i++) + totalLength += TensorSpanHelpers.CalculateTotalLength(tensors[i].Lengths); + + nint sumOfAxis = 0; + // If axis != -1, make sure all dimensions except the one to concatenate on match. + if (axis != -1) + { + sumOfAxis = tensors[0].Lengths[axis]; + for (int i = 1; i < tensors.Length; i++) + { + if (tensors[0].Rank != tensors[i].Rank) + ThrowHelper.ThrowArgument_InvalidConcatenateShape(); + for (int j = 0; j < tensors[0].Rank; j++) + { + if (j != axis) + { + if (tensors[0].Lengths[j] != tensors[i].Lengths[j]) + ThrowHelper.ThrowArgument_InvalidConcatenateShape(); + } + } + sumOfAxis += tensors[i].Lengths[axis]; + } + } + + T[] values = tensors[0].IsPinned ? GC.AllocateArray((int)totalLength, tensors[0].IsPinned) : (new T[totalLength]); + Span dstSpan = MemoryMarshal.CreateSpan(ref values[0], (int)totalLength); + nint valuesCopied = 0; + + scoped Span curIndex; + nint[]? curIndexArray; + + if (tensors[0].Rank > 6) + { + curIndexArray = ArrayPool.Shared.Rent(tensors[0].Rank); + curIndex = curIndexArray; + } + else + { + curIndexArray = null; + curIndex = stackalloc nint[tensors[0].Rank]; + } + nint srcIndex; + nint copyLength; + + while (valuesCopied < totalLength) + { + for (int i = 0; i < tensors.Length; i++) + { + srcIndex = TensorSpanHelpers.ComputeLinearIndex(curIndex, tensors[i].Strides, tensors[i].Lengths); + copyLength = CalculateCopyLength(tensors[i].Lengths, axis); + Span srcSpan = MemoryMarshal.CreateSpan(ref tensors[i]._values[srcIndex], (int)copyLength); + TensorSpanHelpers.Memmove(dstSpan, srcSpan, copyLength, valuesCopied); + valuesCopied += copyLength; + } + TensorSpanHelpers.AdjustIndexes(axis - 1, 1, curIndex, tensors[0].Lengths); + } + + Tensor tensor; + if (axis == -1) + { + tensor = new Tensor(values, [valuesCopied], tensors[0].IsPinned); + } + else + { + nint[] lengths = new nint[tensors[0].Rank]; + tensors[0].Lengths.CopyTo(lengths); + lengths[axis] = sumOfAxis; + tensor = new Tensor(values, lengths, tensors[0].IsPinned); + } + + if (curIndexArray != null) + ArrayPool.Shared.Return(curIndexArray); + + return tensor; + } + + private static nint CalculateCopyLength(ReadOnlySpan lengths, int startingAxis) + { + // When starting axis is -1 we want all the data at once same as if starting axis is 0 + if (startingAxis == -1) + startingAxis = 0; + nint length = 1; + for (int i = startingAxis; i < lengths.Length; i++) + { + length *= lengths[i]; + } + return length; + } + #endregion + + #region StdDev + /// + /// Returns the standard deviation of the elements in the tensor. + /// + /// The to take the standard deviation of. + /// representing the standard deviation. + public static T StdDev(Tensor input) + where T : IEquatable, IEqualityOperators, IFloatingPoint, IPowerFunctions, IAdditionOperators, IAdditiveIdentity + + { + T mean = Mean(input); + Span span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Span output = new T[input._flattenedLength].AsSpan(); + TensorPrimitives.Subtract(span, mean, output); + TensorPrimitives.Abs(output, output); + TensorPrimitives.Pow((ReadOnlySpan)output, T.CreateChecked(2), output); + T sum = TensorPrimitives.Sum((ReadOnlySpan)output); + return T.CreateChecked(sum / T.CreateChecked(input.FlattenedLength)); + } + + /// + /// Return the standard deviation of the elements in the tensor. Casts the return value to . + /// + /// The to take the standard deviation of. + /// representing the standard deviation. + public static TResult StdDev(Tensor input) + where T : IEquatable, IEqualityOperators, INumber + where TResult : IEquatable, IEqualityOperators, IFloatingPoint + + { + T sum = Tensor.Sum(input); + return TResult.CreateChecked(TResult.CreateChecked(sum) / TResult.CreateChecked(input.FlattenedLength)); + } + + #endregion + + #region Mean + /// + /// Returns the mean of the elements in the tensor. + /// + /// The to take the mean of. + /// representing the mean. + public static T Mean(Tensor input) + where T : IEquatable, IEqualityOperators, IFloatingPoint + + { + T sum = Tensor.Sum(input); + return T.CreateChecked(sum / T.CreateChecked(input.FlattenedLength)); + } + + /// + /// Return the mean of the elements in the tensor. Casts the return value to . + /// + /// The to take the mean of. + /// representing the mean. + public static TResult Mean(Tensor input) + where T : IEquatable, IEqualityOperators, INumber + where TResult : IEquatable, IEqualityOperators, IFloatingPoint + + { + T sum = Tensor.Sum(input); + return TResult.CreateChecked(TResult.CreateChecked(sum) / TResult.CreateChecked(input.FlattenedLength)); + } + + #endregion + + #region Permute/Transpose + /// + /// Swaps the last two dimensions of the tensor. + /// + /// Input . + public static Tensor Transpose(Tensor input) + where T : IEquatable, IEqualityOperators + { + if (input.Lengths.Length < 2) + ThrowHelper.ThrowArgument_TransposeTooFewDimensions(); + int[] axis = Enumerable.Range(0, input.Rank).ToArray(); + int temp = axis[input.Rank - 1]; + axis[input.Rank - 1] = axis[input.Rank - 2]; + axis[input.Rank - 2] = temp; + return Permute(input, axis.AsSpan()); + } + + /// + /// Swaps the dimensions of the tensor according to the parameter. + /// If is a 1D tensor, it will return . Otherwise it creates a new + /// with the new axis ordering by allocating new memory. + /// + /// Input + /// with the new axis ordering. + public static Tensor Permute(Tensor input, params scoped ReadOnlySpan axis) + where T : IEquatable, IEqualityOperators + { + if (input.Rank == 1) + { + return input; + } + else + { + T[] values = input.IsPinned ? GC.AllocateArray((int)input._flattenedLength) : (new T[input._flattenedLength]); + nint[] lengths = new nint[input.Rank]; + Tensor tensor; + TensorSpan ospan; + TensorSpan ispan; + ReadOnlySpan permutation; + + if (axis.IsEmpty) + { + lengths = input._lengths.Reverse().ToArray(); + permutation = Enumerable.Range(0, input.Rank).Reverse().ToArray(); + } + else + { + if (axis.Length != input.Lengths.Length) + ThrowHelper.ThrowArgument_PermuteAxisOrder(); + for (int i = 0; i < lengths.Length; i++) + lengths[i] = input.Lengths[axis[i]]; + permutation = axis.ToArray(); + } + tensor = new Tensor(values, lengths, Array.Empty(), input._isPinned); + + ospan = tensor.AsTensorSpan(); + ispan = input.AsTensorSpan(); + + scoped Span indexes; + nint[]? indicesArray; + scoped Span permutedIndices; + nint[]? permutedIndicesArray; + if (tensor.Rank > 6) + { + indicesArray = ArrayPool.Shared.Rent(tensor.Rank); + indexes = indicesArray; + permutedIndicesArray = ArrayPool.Shared.Rent(tensor.Rank); + permutedIndices = permutedIndicesArray; + } + else + { + indicesArray = null; + indexes = stackalloc nint[tensor.Rank]; + permutedIndicesArray = null; + permutedIndices = stackalloc nint[tensor.Rank]; + } + + for (int i = 0; i < input._flattenedLength; i++) + { + TensorHelpers.PermuteIndices(indexes, permutedIndices, permutation); + ospan[permutedIndices] = ispan[indexes]; + TensorSpanHelpers.AdjustIndexes(tensor.Rank - 1, 1, indexes, input._lengths); + } + + if (indicesArray != null && permutedIndicesArray != null) + { + ArrayPool.Shared.Return(indicesArray); + ArrayPool.Shared.Return(permutedIndicesArray); + } + + return tensor; + } + } + #endregion + + #region TensorPrimitives + #region Multiply + /// + /// Multiplies each element of with and returns a new with the result. + /// + /// Input + /// value to multiply by. + public static Tensor Multiply(Tensor input, T val) + where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Tensor output = Create(input.Lengths, input.IsPinned); + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + TensorPrimitives.Multiply(span, val, ospan); + return output; + } + + /// + /// Multiplies each element of with in place. + /// + /// Input + /// value to multiply by. + public static Tensor MultiplyInPlace(Tensor input, T val) + where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Tensor output = input; + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + TensorPrimitives.Multiply(span, val, ospan); + return output; + } + + /// + /// Multiplies each element of with and returns a new with the result. + /// If the shapes are not the same they are broadcast to the smallest compatible shape. + /// + /// Left for multiplication. + /// Right for multiplication. + public static Tensor Multiply(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Multiply); + } + + /// + /// Multiplies each element of with in place. + /// If the shapes are not the same they are broadcast to the smallest compatible shape. + /// + /// Left for multiplication. + /// Right for multiplication. + public static Tensor MultiplyInPlace(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Multiply, true); + } + + /// + /// Multiplies each element of with and returns a new with the result. + /// + /// Input + /// value to multiply by. + public static TensorSpan Multiply(TensorSpan input, T val) + where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + T[] values = new T[input.FlattenedLength]; + TensorSpan output = new TensorSpan(values, 0, input.Lengths, default); + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + TensorPrimitives.Multiply(span, val, ospan); + return output; + } + + /// + /// Multiplies each element of with in place. + /// + /// Input + /// value to multiply by. + public static TensorSpan MultiplyInPlace(TensorSpan input, T val) + where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + TensorSpan output = input; + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + TensorPrimitives.Multiply(span, val, ospan); + return output; + } + + /// + /// Multiplies each element of with and returns a new with the result. + /// If the shapes are not the same they are broadcast to the smallest compatible shape. + /// + /// Left for multiplication. + /// Right for multiplication. + public static TensorSpan Multiply(TensorSpan left, TensorSpan right) + where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Multiply); + } + + /// + /// Multiplies each element of with in place. + /// If the shapes are not the same they are broadcast to the smallest compatible shape. + /// + /// Left for multiplication. + /// Right for multiplication. + public static TensorSpan MultiplyInPlace(TensorSpan left, TensorSpan right) + where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Multiply, true); + } + #endregion + + #region Divide + /// + /// Divides each element of by and returns a new with the result. + /// + /// Input . + /// The divisor + public static Tensor Divide(Tensor input, T val) + where T : IEquatable, IEqualityOperators, IDivisionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Tensor output = Create(input.Lengths, input.IsPinned); + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + TensorPrimitives.Divide(span, val, ospan); + return output; + } + + /// + /// Divides each element of by in place. + /// + /// Input . + /// The divisor. + public static Tensor DivideInPlace(Tensor input, T val) + where T : IEquatable, IEqualityOperators, IDivisionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Tensor output = input; + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + TensorPrimitives.Divide(span, val, ospan); + return output; + } + + /// + /// Divides by each element of and returns a new with the result."/> + /// + /// The value to be divided. + /// The divisor. + public static Tensor Divide(T val, Tensor input) + where T : IEquatable, IEqualityOperators, IDivisionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Tensor output = Create(input.Lengths, input.IsPinned); + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + TensorPrimitives.Divide(val, span, ospan); + return output; + } + + /// + /// Divides by each element of in place. + /// + /// The value to be divided. + /// The divisor. + public static Tensor DivideInPlace(T val, Tensor input) + where T : IEquatable, IEqualityOperators, IDivisionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Tensor output = input; + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + TensorPrimitives.Divide(val, span, ospan); + return output; + } + + /// + /// Divides each element of by its corresponding element in and returns + /// a new with the result. + /// + /// The to be divided. + /// The divisor. + public static Tensor Divide(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators, IDivisionOperators + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Divide); + } + + /// + /// Divides each element of by its corresponding element in in place. + /// + /// The to be divided. + /// The divisor. + public static Tensor DivideInPlace(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators, IDivisionOperators + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Divide, true); + } + + /// + /// Divides each element of by and returns a new with the result. + /// + /// Input . + /// The divisor + public static TensorSpan Divide(TensorSpan input, T val) + where T : IEquatable, IEqualityOperators, IDivisionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + T[] values = new T[input.FlattenedLength]; + TensorSpan output = new TensorSpan(values, 0, input.Lengths, default); + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + TensorPrimitives.Divide(span, val, ospan); + return output; + } + + /// + /// Divides each element of by in place. + /// + /// Input . + /// The divisor + public static TensorSpan DivideInPlace(TensorSpan input, T val) + where T : IEquatable, IEqualityOperators, IDivisionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + TensorSpan output = input; + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + TensorPrimitives.Divide(span, val, ospan); + return output; + } + + /// + /// Divides by each element of and returns a new with the result."/> + /// + /// The value to be divided. + /// The divisor. + public static TensorSpan Divide(T val, TensorSpan input) + where T : IEquatable, IEqualityOperators, IDivisionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + T[] values = new T[input.FlattenedLength]; + TensorSpan output = new TensorSpan(values, 0, input.Lengths, default); + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + TensorPrimitives.Divide(val, span, ospan); + return output; + } + + /// + /// Divides by each element of in place. + /// + /// The value to be divided. + /// The divisor. + public static TensorSpan DivideInPlace(T val, TensorSpan input) + where T : IEquatable, IEqualityOperators, IDivisionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + TensorSpan output = input; + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + TensorPrimitives.Divide(val, span, ospan); + return output; + } + + /// + /// Divides each element of by its corresponding element in and returns + /// a new with the result. + /// + /// The to be divided. + /// The divisor. + public static TensorSpan Divide(TensorSpan left, TensorSpan right) + where T : IEquatable, IEqualityOperators, IDivisionOperators + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Divide); + } + + /// + /// Divides each element of by its corresponding element in in place. + /// + /// The to be divided. + /// The divisor. + public static TensorSpan DivideInPlace(TensorSpan left, TensorSpan right) + where T : IEquatable, IEqualityOperators, IDivisionOperators + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Divide, true); + } + + #endregion + + #region Subtract + /// + /// Subtracts from each element of and returns a new with the result. + /// + /// The . + /// The to subtract. + public static Tensor Subtract(Tensor input, T val) + where T : IEquatable, IEqualityOperators, ISubtractionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Tensor output = Create(input.Lengths, input.IsPinned); + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + TensorPrimitives.Subtract(span, val, ospan); + return output; + } + + /// + /// Subtracts from each element of in place. + /// + /// The . + /// The to subtract. + public static Tensor SubtractInPlace(Tensor input, T val) + where T : IEquatable, IEqualityOperators, ISubtractionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Tensor output = input; + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + TensorPrimitives.Subtract(span, val, ospan); + return output; + } + + /// + /// Subtracts each element of from and returns a new with the result. + /// + /// The to be subtracted from. + /// The of values to subtract. + public static Tensor Subtract(T val, Tensor input) + where T : IEquatable, IEqualityOperators, ISubtractionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Tensor output = Create(input.Lengths, input.IsPinned); + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + TensorPrimitives.Subtract(val, span, ospan); + return output; + } + + /// + /// Subtracts each element of from in place. + /// + /// The to be subtracted from. + /// The of values to subtract. + public static Tensor SubtractInPlace(T val, Tensor input) + where T : IEquatable, IEqualityOperators, ISubtractionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Tensor output = input; + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + TensorPrimitives.Subtract(val, span, ospan); + return output; + } + + /// + /// Subtracts each element of from and returns a new with the result. + /// + /// The with values to be subtracted from. + /// The with values to subtract. + public static Tensor Subtract(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators, ISubtractionOperators + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Subtract); + } + + /// + /// Subtracts each element of from in place. + /// + /// The with values to be subtracted from. + /// The with values to subtract. + public static Tensor SubtractInPlace(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators, ISubtractionOperators + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Subtract, true); + } + + /// + /// Subtracts from each element of and returns a new with the result. + /// + /// The with values to be subtracted from. + /// The value to subtract. + public static TensorSpan Subtract(TensorSpan input, T val) + where T : IEquatable, IEqualityOperators, ISubtractionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + T[] values = new T[input.FlattenedLength]; + TensorSpan output = new TensorSpan(values, 0, input.Lengths, default); + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + TensorPrimitives.Subtract(span, val, ospan); + return output; + } + + /// + /// Subtracts from each element of in place. + /// + /// The with values to be subtracted from. + /// The value to subtract. + public static TensorSpan SubtractInPlace(TensorSpan input, T val) + where T : IEquatable, IEqualityOperators, ISubtractionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + TensorSpan output = input; + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + TensorPrimitives.Subtract(span, val, ospan); + return output; + } + + /// + /// Subtracts each element of from and returns a new with the result. + /// + /// The value to be subtracted from. + /// The values to subtract. + public static TensorSpan Subtract(T val, TensorSpan input) + where T : IEquatable, IEqualityOperators, ISubtractionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + T[] values = new T[input.FlattenedLength]; + TensorSpan output = new TensorSpan(values, 0, input.Lengths, default); + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + TensorPrimitives.Subtract(val, span, ospan); + return output; + } + + /// + /// Subtracts each element of from in place. + /// + /// The value to be subtracted from. + /// The values to subtract. + public static TensorSpan SubtractInPlace(T val, TensorSpan input) + where T : IEquatable, IEqualityOperators, ISubtractionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + TensorSpan output = input; + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + TensorPrimitives.Subtract(val, span, ospan); + return output; + } + + /// + /// Subtracts each element of from and returns a new with the result. + /// + /// The of values to be subtracted from. + /// The of values to subtract. + public static TensorSpan Subtract(TensorSpan left, TensorSpan right) + where T : IEquatable, IEqualityOperators, ISubtractionOperators + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Subtract); + } + + /// + /// Subtracts each element of from in place. + /// + /// The of values to be subtracted from. + /// The of values to subtract. + public static TensorSpan SubtractInPlace(TensorSpan left, TensorSpan right) + where T : IEquatable, IEqualityOperators, ISubtractionOperators + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Subtract, true); + } + + #endregion + + #region Sum + + /// + /// Sums all the elements of the and returns the result. + /// + /// The to sum. + public static T Sum(Tensor input) + where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + return TensorPrimitives.Sum(span); + } + + /// + /// Sums all the elements of the and returns the result. + /// + /// The to sum. + public static T Sum(TensorSpan input) + where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + return TensorPrimitives.Sum(span); + } + + #endregion + + #region Add + /// + /// Adds each element of to each element of and returns a new with the result. + /// + /// The of values to add. + /// The second of values to add. + public static Tensor Add(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Add); + } + + /// + /// Adds each element of to each element of in place. + /// + /// The of values to add. + /// The second of values to add. + public static Tensor AddInPlace(Tensor left, Tensor right) + where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Add, true); + } + + /// + /// Adds to each element of and returns a new with the result. + /// + /// The of values to add. + /// The to add to each element of . + public static Tensor Add(Tensor input, T val) + where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Tensor output = Create(input.Lengths, input.IsPinned); + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + TensorPrimitives.Add(span, val, ospan); + return output; + } + + /// + /// Adds to each element of in place. + /// + /// The of values to add. + /// The to add to each element of . + public static Tensor AddInPlace(Tensor input, T val) + where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Tensor output = input; + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + TensorPrimitives.Add(span, val, ospan); + return output; + } + + /// + /// Adds each element of to each element of and returns a new with the result. + /// + /// The first of elements to add. + /// The second of elements to add. + public static TensorSpan Add(TensorSpan left, TensorSpan right) + where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Add); + } + + /// + /// Adds each element of to each element of in place. + /// + /// The first of values to add. + /// The second of values to add. + public static TensorSpan AddInPlace(TensorSpan left, TensorSpan right) + where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity + { + return TensorPrimitivesHelperT1T2(left, right, TensorPrimitives.Add, true); + } + + /// + /// Adds to each element of and returns a new with the result. + /// + /// The of values to add. + /// The value to add to each element of . + public static TensorSpan Add(TensorSpan input, T val) + where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + T[] values = new T[input.FlattenedLength]; + TensorSpan output = new TensorSpan(values, 0, input.Lengths, default); + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + TensorPrimitives.Add(span, val, ospan); + return output; + } + + /// + /// Adds to each element of in place. + /// + /// The of values to add. + /// The value to add to each element of . + public static TensorSpan AddInPlace(TensorSpan input, T val) + where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + TensorSpan output = input; + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + TensorPrimitives.Add(span, val, ospan); + return output; + } + + #endregion + + #region Norm + /// + /// Takes the norm of the and returns the result. + /// + /// The to take the norm of. + public static T Norm(Tensor input) + where T : IEquatable, IEqualityOperators, IRootFunctions + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + return TensorPrimitives.Norm(span); + } + + /// + /// Takes the norm of the and returns the result. + /// + /// The to take the norm of. + public static T Norm(TensorSpan input) + where T : IEquatable, IEqualityOperators, IRootFunctions + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + return TensorPrimitives.Norm(span); + } + + #endregion + + #region Cos + /// + /// Takes the cosine of each element of the and returns a new with the result. + /// + /// The to take the cosine of. + public static Tensor Cos(Tensor input) + where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Cos); + } + + /// + /// Takes the cosine of each element of the and returns a new with the result. + /// + /// The to take the cosine of. + public static TensorSpan Cos(TensorSpan input) + where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Cos); + } + + /// + /// Takes the cosine of each element of the in place. + /// + /// The to take the cosine of. + public static Tensor CosInPlace(Tensor input) + where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Cos, true); + } + + /// + /// Takes the cosine of each element of the in place. + /// + /// The to take the cosine of. + public static TensorSpan CosInPlace(TensorSpan input) + where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Cos, true); + } + + #endregion + + #region Sin + /// + /// Takes the sin of each element of the and returns a new with the result. + /// + /// The to take the sin of. + public static Tensor Sin(Tensor input) + where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Sin); + } + + /// + /// Takes the sin of each element of the and returns a new with the result. + /// + /// The to take the sin of. + public static TensorSpan Sin(TensorSpan input) + where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Sin); + } + + /// + /// Takes the sin of each element of the in place. + /// + /// The to take the sin of. + public static Tensor SinInPlace(Tensor input) + where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Sin, true); + } + + /// + /// Takes the sin of each element of the in place. + /// + /// The to take the sin of. + public static TensorSpan SinInPlace(TensorSpan input) + where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Sin, true); + } + + #endregion + + #region Sqrt + /// + /// Takes the square root of each element of the and returns a new with the result. + /// + /// The to take the square root of. + public static Tensor Sqrt(Tensor input) + where T : IEquatable, IEqualityOperators, IRootFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Sqrt); + } + + /// + /// Takes the square root of each element of the and returns a new with the result. + /// + /// The to take the square root of. + public static TensorSpan Sqrt(TensorSpan input) + where T : IEquatable, IEqualityOperators, IRootFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Sqrt); + } + + /// + /// Takes the square root of each element of the in place. + /// + /// The to take the square root of. + public static Tensor SqrtInPlace(Tensor input) + where T : IEquatable, IEqualityOperators, IRootFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Sqrt, true); + } + + /// + /// Takes the square root of each element of the in place. + /// + /// The to take the square root of. + public static TensorSpan SqrtInPlace(TensorSpan input) + where T : IEquatable, IEqualityOperators, IRootFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Sqrt, true); + } + + #endregion + + #region Log + /// + /// Takes the natural logarithm of each element of the and returns a new with the result. + /// + /// The to take the natural logarithm of. + public static Tensor Log(Tensor input) + where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Log); + } + + /// + /// Takes the natural logarithm of each element of the and returns a new with the result. + /// + /// The to take the natural logarithm of. + public static TensorSpan Log(TensorSpan input) + where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Log); + } + + /// + /// Takes the natural logarithm of each element of the in place. + /// + /// The to take the natural logarithm of. + public static Tensor LogInPlace(Tensor input) + where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Log, true); + } + + /// + /// Takes the natural logarithm of each element of the in place. + /// + /// The to take the natural logarithm of. + public static TensorSpan LogInPlace(TensorSpan input) + where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Log, true); + } + + #endregion + + #region Log10 + /// + /// Takes the base 10 logarithm of each element of the and returns a new with the result. + /// + /// The to take the base 10 logarithm of. + public static Tensor Log10(Tensor input) + where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Log10); + } + + /// + /// Takes the base 10 logarithm of each element of the and returns a new with the result. + /// + /// The to take the base 10 logarithm of. + public static TensorSpan Log10(TensorSpan input) + where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Log10); + } + + /// + /// Takes the base 10 logarithm of each element of the in place. + /// + /// The to take the base 10 logarithm of. + public static Tensor Log10InPlace(Tensor input) + where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Log10, true); + } + + /// + /// Takes the base 10 logarithm of each element of the in place. + /// + /// The to take the base 10 logarithm of. + public static TensorSpan Log10InPlace(TensorSpan input) + where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Log10, true); + } + #endregion + + #region Log2 + /// + /// Takes the base 2 logarithm of each element of the and returns a new with the result. + /// + /// The to take the base 2 logarithm of. + public static Tensor Log2(Tensor input) + where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Log2); + } + + /// + /// Takes the base 2 logarithm of each element of the and returns a new with the result. + /// + /// The to take the base 2 logarithm of. + public static TensorSpan Log2(TensorSpan input) + where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Log2); + } + + /// + /// Takes the base 2 logarithm of each element of the in place. + /// + /// The to take the base 2 logarithm of. + public static Tensor Log2InPlace(Tensor input) + where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Log2, true); + } + + /// + /// Takes the base 2 logarithm of each element of the in place. + /// + /// The to take the base 2 logarithm of. + public static TensorSpan Log2InPlace(TensorSpan input) + where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + { + return TensorPrimitivesHelperT1(input, TensorPrimitives.Log2, true); + } + + #endregion + + #region TensorPrimitivesHelpers + private delegate void PerformCalculationT1(ReadOnlySpan input, Span output) + where T : IEquatable, IEqualityOperators; + + private delegate void PerformCalculationT1T2(ReadOnlySpan input, ReadOnlySpan inputTwo, Span output) + where T : IEquatable, IEqualityOperators; + + private static Tensor TensorPrimitivesHelperT1(Tensor input, PerformCalculationT1 performCalculation, bool inPlace = false) + where T : IEquatable, IEqualityOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Tensor output = inPlace ? input : Create(input.Lengths, input.IsPinned); + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + performCalculation(span, ospan); + return output; + } + + private static TensorSpan TensorPrimitivesHelperT1(TensorSpan input, PerformCalculationT1 performCalculation, bool inPlace = false) + where T : IEquatable, IEqualityOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + TensorSpan output = inPlace ? input : new TensorSpan(new T[input.FlattenedLength], 0, input.Lengths, input.Strides); + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + performCalculation(span, ospan); + return output; + } + + private static Tensor TensorPrimitivesHelperT1T2(Tensor left, Tensor right, PerformCalculationT1T2 performCalculation, bool inPlace = false) + where T : IEquatable, IEqualityOperators + { + if (inPlace && left.Lengths != right.Lengths) + ThrowHelper.ThrowArgument_InPlaceInvalidShape(); + + Tensor output; + if (inPlace) + { + + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref left._values[0], (int)left._flattenedLength); + ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref right._values[0], (int)right._flattenedLength); + output = left; + Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + performCalculation(span, rspan, ospan); + } + // If not in place but sizes are the same. + else if (left.Lengths.SequenceEqual(right.Lengths)) + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref left.AsTensorSpan()._reference, (int)left.FlattenedLength); + ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref right.AsTensorSpan()._reference, (int)right.FlattenedLength); + output = Create(left.Lengths, left.IsPinned); + Span ospan = MemoryMarshal.CreateSpan(ref output.AsTensorSpan()._reference, (int)output.FlattenedLength); + performCalculation(span, rspan, ospan); + return output; + } + // Not in place and broadcasting needs to happen. + else + { + // Have a couple different possible cases here. + // 1 - Both tensors have row contiguous memory (i.e. a 1x5 being broadcast to a 5x5) + // 2 - One tensor has row contiguous memory and the right has column contiguous memory (i.e. a 1x5 and a 5x1) + + nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); + + var broadcastedLeft = Tensor.BroadcastTo(left, newSize); + var broadcastedRight = Tensor.BroadcastTo(right, newSize); + + output = Create(newSize, left.IsPinned); + nint rowLength = newSize[^1]; + Span ospan; + Span ispan; + Span buffer = new T[rowLength]; + + scoped Span curIndexes; + nint[]? curIndexesArray; + if (newSize.Length> 6) + { + curIndexesArray = ArrayPool.Shared.Rent(newSize.Length); + curIndexes = curIndexesArray; + } + else + { + curIndexesArray = null; + curIndexes = stackalloc nint[newSize.Length]; + } + + int outputOffset = 0; + // tensor not row contiguous + if (broadcastedLeft.Strides[^1] == 0) + { + while (outputOffset < output.FlattenedLength) + { + ospan = MemoryMarshal.CreateSpan(ref output._values[outputOffset], (int)rowLength); + buffer.Fill(broadcastedLeft[curIndexes]); + ispan = MemoryMarshal.CreateSpan(ref broadcastedRight[curIndexes], (int)rowLength); + performCalculation(buffer, ispan, ospan); + outputOffset += (int)rowLength; + TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndexes, broadcastedLeft.Lengths); + } + } + // right now row contiguous + else if (broadcastedRight.Strides[^1] == 0) + { + while (outputOffset < output.FlattenedLength) + { + ospan = MemoryMarshal.CreateSpan(ref output._values[outputOffset], (int)rowLength); + buffer.Fill(broadcastedRight[curIndexes]); + ispan = MemoryMarshal.CreateSpan(ref broadcastedLeft[curIndexes], (int)rowLength); + performCalculation(ispan, buffer, ospan); + outputOffset += (int)rowLength; + TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndexes, broadcastedLeft.Lengths); + } + } + // both row contiguous + else + { + Span rspan; + while (outputOffset < output.FlattenedLength) + { + ospan = MemoryMarshal.CreateSpan(ref output._values[outputOffset], (int)rowLength); + ispan = MemoryMarshal.CreateSpan(ref broadcastedLeft[curIndexes], (int)rowLength); + rspan = MemoryMarshal.CreateSpan(ref broadcastedRight[curIndexes], (int)rowLength); + performCalculation(ispan, rspan, ospan); + outputOffset += (int)rowLength; + TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndexes, broadcastedLeft.Lengths); + } + } + + if (curIndexesArray != null) + ArrayPool.Shared.Return(curIndexesArray); + } + + return output; + } + + private static TensorSpan TensorPrimitivesHelperT1T2(TensorSpan left, TensorSpan right, PerformCalculationT1T2 performCalculation, bool inPlace = false) + where T : IEquatable, IEqualityOperators + { + if (inPlace && left.Lengths != right.Lengths) + ThrowHelper.ThrowArgument_InPlaceInvalidShape(); + + //ReadOnlySpan span = MemoryMarshal.CreateSpan(ref tensor._reference, (int)tensor.FlattenedLength); + //ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref right._reference, (int)right.FlattenedLength); + //TensorSpan output = inPlace ? tensor : Create(tensor.IsPinned, tensor.Lengths); + //Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + //performCalculation(span, rspan, ospan); + //return output; + + TensorSpan output; + if (inPlace) + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref left._reference, (int)left.FlattenedLength); + ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref right._reference, (int)right.FlattenedLength); + output = left; + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + performCalculation(span, rspan, ospan); + } + // If not in place but sizes are the same. + else if (left.Lengths.SequenceEqual(right.Lengths)) + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref left._reference, (int)left.FlattenedLength); + ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref right._reference, (int)right.FlattenedLength); + output = new TensorSpan(new T[left.FlattenedLength], 0, left.Lengths, left.Strides); + Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); + performCalculation(span, rspan, ospan); + return output; + } + // Not in place and broadcasting needs to happen. + else + { + // Have a couple different possible cases here. + // 1 - Both tensors have row contiguous memory (i.e. a 1x5 being broadcast to a 5x5) + // 2 - One tensor has row contiguous memory and the right has column contiguous memory (i.e. a 1x5 and a 5x1) + + nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); + + TensorSpan broadcastedLeft = Tensor.BroadcastTo(left, newSize); + TensorSpan broadcastedRight = Tensor.BroadcastTo(right, newSize); + + output = new TensorSpan(new T[TensorSpanHelpers.CalculateTotalLength(newSize)], newSize, default); + nint rowLength = newSize[^1]; + Span ospan; + Span ispan; + Span buffer = new T[rowLength]; + + scoped Span curIndex; + nint[]? curIndexArray; + if (newSize.Length > 6) + { + curIndexArray = ArrayPool.Shared.Rent(newSize.Length); + curIndex = curIndexArray; + } + else + { + curIndexArray = null; + curIndex = stackalloc nint[newSize.Length]; + } + + int outputOffset = 0; + // ADD IN CASE WHERE NEITHER ARE ROW CONTIGUOUS + // tensor not row contiguous + if (broadcastedLeft.Strides[^1] == 0) + { + while (outputOffset < output.FlattenedLength) + { + ospan = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref output._reference, outputOffset), (int)rowLength); + buffer.Fill(broadcastedLeft[curIndex]); + ispan = MemoryMarshal.CreateSpan(ref broadcastedRight[curIndex], (int)rowLength); + performCalculation(buffer, ispan, ospan); + outputOffset += (int)rowLength; + TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndex, broadcastedLeft.Lengths); + } + } + // right not row contiguous + else if (broadcastedRight.Strides[^1] == 0) + { + while (outputOffset < output.FlattenedLength) + { + ospan = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref output._reference, outputOffset), (int)rowLength); + buffer.Fill(broadcastedRight[curIndex]); + ispan = MemoryMarshal.CreateSpan(ref broadcastedLeft[curIndex], (int)rowLength); + performCalculation(ispan, buffer, ospan); + outputOffset += (int)rowLength; + TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndex, broadcastedLeft.Lengths); + } + } + // both row contiguous + else + { + Span rspan; + while (outputOffset < output.FlattenedLength) + { + ospan = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref output._reference, outputOffset), (int)rowLength); + ispan = MemoryMarshal.CreateSpan(ref broadcastedLeft[curIndex], (int)rowLength); + rspan = MemoryMarshal.CreateSpan(ref broadcastedRight[curIndex], (int)rowLength); + performCalculation(ispan, rspan, ospan); + outputOffset += (int)rowLength; + TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndex, broadcastedLeft.Lengths); + } + } + + if (curIndexArray != null) + ArrayPool.Shared.Return(curIndexArray); + } + return output; + } + #endregion + #endregion + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorHelpers.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorHelpers.cs new file mode 100644 index 000000000000..585bc4e34414 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorHelpers.cs @@ -0,0 +1,131 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Net.NetworkInformation; +using System.Reflection.Metadata.Ecma335; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CSharp.RuntimeBinder; +using Microsoft.VisualBasic; + +namespace System.Numerics.Tensors +{ + internal static class TensorHelpers + { + + /// + /// Counts the number of true elements in a boolean filter tensor so we know how much space we will need. + /// + /// + /// How many boolean values are true. + public static nint CountTrueElements(Tensor filter) + { + Span filterSpan = MemoryMarshal.CreateSpan(ref filter._values[0], (int)filter._flattenedLength); + nint count = 0; + for (int i = 0; i < filterSpan.Length; i++) + { + if (filterSpan[i]) + count++; + } + + return count; + } + + internal static bool AreShapesBroadcastCompatible(Tensor tensor1, Tensor tensor2) + where T : IEquatable, IEqualityOperators => AreShapesBroadcastCompatible(tensor1.Lengths, tensor2.Lengths); + + internal static bool AreShapesBroadcastCompatible(ReadOnlySpan shape1, ReadOnlySpan shape2) + { + int shape1Index = shape1.Length - 1; + int shape2Index = shape2.Length - 1; + + bool areCompatible = true; + + nint s1; + nint s2; + + while (shape1Index >= 0 || shape2Index >= 0) + { + // if a dimension is missing in one of the shapes, it is considered to be 1 + if (shape1Index < 0) + s1 = 1; + else + s1 = shape1[shape1Index--]; + + if (shape2Index < 0) + s2 = 1; + else + s2 = shape2[shape2Index--]; + + if (s1 == s2 || (s1 == 1 && s2 != 1) || (s2 == 1 && s1 != 1)) { } + else + { + areCompatible = false; + break; + } + } + + return areCompatible; + } + + internal static nint[] GetSmallestBroadcastableSize(ReadOnlySpan shape1, ReadOnlySpan shape2) + { + if (!AreShapesBroadcastCompatible(shape1, shape2)) + throw new Exception("Shapes are not broadcast compatible"); + + nint[] intermediateShape = GetIntermediateShape(shape1, shape2.Length); + for (int i = 1; i <= shape1.Length; i++) + { + intermediateShape[^i] = Math.Max(intermediateShape[^i], shape1[^i]); + } + for (int i = 1; i <= shape2.Length; i++) + { + intermediateShape[^i] = Math.Max(intermediateShape[^i], shape2[^i]); + } + + return intermediateShape; + } + + internal static nint[] GetIntermediateShape(ReadOnlySpan shape1, int shape2Length) + { + int shape1Index = shape1.Length - 1; + int newShapeIndex = Math.Max(shape1.Length, shape2Length) - 1; + nint[] newShape = new nint[Math.Max(shape1.Length, shape2Length)]; + + while (newShapeIndex >= 0) + { + // if a dimension is missing in one of the shapes, it is considered to be 1 + if (shape1Index < 0) + newShape[newShapeIndex--] = 1; + else + newShape[newShapeIndex--] = shape1[shape1Index--]; + } + + return newShape; + } + + internal static bool IsUnderlyingStorageSameSize(Tensor tensor1, Tensor tensor2) + where T : IEquatable, IEqualityOperators => tensor1.Lengths.Length == tensor2.Lengths.Length; + + internal static bool AreShapesTheSame(Tensor tensor1, Tensor tensor2) + where T : IEquatable, IEqualityOperators => tensor1._lengths.SequenceEqual(tensor2._lengths); + + + internal static void PermuteIndices(Span indices, Span permutedIndices, ReadOnlySpan permutation) + { + for (int i = 0; i < indices.Length; i++) + { + permutedIndices[i] = indices[permutation[i]]; + } + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Cbrt.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Cbrt.cs index 1bc8b85696c1..3336411a0989 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Cbrt.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Cbrt.cs @@ -26,7 +26,7 @@ public static void Cbrt(ReadOnlySpan x, Span destination) private readonly struct CbrtOperator : IUnaryOperator where T : IRootFunctions { - public static bool Vectorizable => typeof(T) == typeof(float) || typeof(T) == typeof(double); + public static bool Vectorizable => false; // typeof(T) == typeof(float) || typeof(T) == typeof(double); // TODO: https://github.com/dotnet/runtime/issues/100535 public static T Invoke(T x) => T.Cbrt(x); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.FusedMultiplyAdd.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.FusedMultiplyAdd.cs index 57cc8f3a373a..42f36ec494a9 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.FusedMultiplyAdd.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.FusedMultiplyAdd.cs @@ -10,7 +10,7 @@ namespace System.Numerics.Tensors { public static partial class TensorPrimitives { - /// Computes the element-wise result of ( * ) * for the specified tensors of numbers. + /// Computes the element-wise result of ( * ) + for the specified tensors of numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The third tensor, represented as a span. @@ -38,7 +38,7 @@ public static void FusedMultiplyAdd(ReadOnlySpan x, ReadOnlySpan y, Rea where T : IFloatingPointIeee754 => InvokeSpanSpanSpanIntoSpan>(x, y, addend, destination); - /// Computes the element-wise result of ( * ) * for the specified tensors of numbers. + /// Computes the element-wise result of ( * ) + for the specified tensors of numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The third tensor, represented as a scalar. @@ -66,7 +66,7 @@ public static void FusedMultiplyAdd(ReadOnlySpan x, ReadOnlySpan y, T a where T : IFloatingPointIeee754 => InvokeSpanSpanScalarIntoSpan>(x, y, addend, destination); - /// Computes the element-wise result of ( * ) * for the specified tensors of numbers. + /// Computes the element-wise result of ( * ) + for the specified tensors of numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a scalar. /// The third tensor, represented as a span. @@ -100,6 +100,17 @@ public static void FusedMultiplyAdd(ReadOnlySpan x, T y, ReadOnlySpan a public static Vector128 Invoke(Vector128 x, Vector128 y, Vector128 z) { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector128.FusedMultiplyAdd(x.AsDouble(), y.AsDouble(), z.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector128.FusedMultiplyAdd(x.AsSingle(), y.AsSingle(), z.AsSingle()).As(); + } +#else if (Fma.IsSupported) { if (typeof(T) == typeof(float)) return Fma.MultiplyAdd(x.AsSingle(), y.AsSingle(), z.AsSingle()).As(); @@ -137,10 +148,22 @@ public static Vector128 Invoke(Vector128 x, Vector128 y, Vector128 z double.FusedMultiplyAdd(xDoubles[0], yDoubles[0], zDoubles[0]), double.FusedMultiplyAdd(xDoubles[1], yDoubles[1], zDoubles[1])).As(); } +#endif } public static Vector256 Invoke(Vector256 x, Vector256 y, Vector256 z) { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector256.FusedMultiplyAdd(x.AsDouble(), y.AsDouble(), z.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector256.FusedMultiplyAdd(x.AsSingle(), y.AsSingle(), z.AsSingle()).As(); + } +#else if (Fma.IsSupported) { if (typeof(T) == typeof(float)) return Fma.MultiplyAdd(x.AsSingle(), y.AsSingle(), z.AsSingle()).As(); @@ -150,10 +173,22 @@ public static Vector256 Invoke(Vector256 x, Vector256 y, Vector256 z return Vector256.Create( Invoke(x.GetLower(), y.GetLower(), z.GetLower()), Invoke(x.GetUpper(), y.GetUpper(), z.GetUpper())); +#endif } public static Vector512 Invoke(Vector512 x, Vector512 y, Vector512 z) { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector512.FusedMultiplyAdd(x.AsDouble(), y.AsDouble(), z.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector512.FusedMultiplyAdd(x.AsSingle(), y.AsSingle(), z.AsSingle()).As(); + } +#else if (Avx512F.IsSupported) { if (typeof(T) == typeof(float)) return Avx512F.FusedMultiplyAdd(x.AsSingle(), y.AsSingle(), z.AsSingle()).As(); @@ -163,6 +198,7 @@ public static Vector512 Invoke(Vector512 x, Vector512 y, Vector512 z return Vector512.Create( Invoke(x.GetLower(), y.GetLower(), z.GetLower()), Invoke(x.GetUpper(), y.GetUpper(), z.GetUpper())); +#endif } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log.cs index 74d17f036d94..d3d2f3e9a705 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Log.cs @@ -161,7 +161,7 @@ public static Vector512 Invoke(Vector512 x) private readonly struct LogBaseOperator : IBinaryOperator where T : ILogarithmicFunctions { - public static bool Vectorizable => LogOperator.Vectorizable; + public static bool Vectorizable => false; //LogOperator.Vectorizable; // TODO: https://github.com/dotnet/runtime/issues/100535 public static T Invoke(T x, T y) => T.Log(x, y); public static Vector128 Invoke(Vector128 x, Vector128 y) => LogOperator.Invoke(x) / LogOperator.Invoke(y); public static Vector256 Invoke(Vector256 x, Vector256 y) => LogOperator.Invoke(x) / LogOperator.Invoke(y); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Max.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Max.cs index 0e0566f2d935..2e760e30fb7c 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Max.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Max.cs @@ -96,35 +96,21 @@ public static T Invoke(T x, T y) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Invoke(Vector128 x, Vector128 y) { - if (AdvSimd.IsSupported) - { - if (typeof(T) == typeof(byte)) return AdvSimd.Max(x.AsByte(), y.AsByte()).As(); - if (typeof(T) == typeof(sbyte)) return AdvSimd.Max(x.AsSByte(), y.AsSByte()).As(); - if (typeof(T) == typeof(short)) return AdvSimd.Max(x.AsInt16(), y.AsInt16()).As(); - if (typeof(T) == typeof(ushort)) return AdvSimd.Max(x.AsUInt16(), y.AsUInt16()).As(); - if (typeof(T) == typeof(int)) return AdvSimd.Max(x.AsInt32(), y.AsInt32()).As(); - if (typeof(T) == typeof(uint)) return AdvSimd.Max(x.AsUInt32(), y.AsUInt32()).As(); - if (typeof(T) == typeof(float)) return AdvSimd.Max(x.AsSingle(), y.AsSingle()).As(); - } - - if (AdvSimd.Arm64.IsSupported) + if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - if (typeof(T) == typeof(double)) return AdvSimd.Arm64.Max(x.AsDouble(), y.AsDouble()).As(); - } + if (AdvSimd.IsSupported && typeof(T) == typeof(float)) + { + return AdvSimd.Max(x.AsSingle(), y.AsSingle()).As(); + } - if (typeof(T) == typeof(float)) - { - return - Vector128.ConditionalSelect(Vector128.Equals(x, y), - Vector128.ConditionalSelect(IsNegative(x.AsSingle()).As(), y, x), - Vector128.Max(x, y)); - } + if (AdvSimd.Arm64.IsSupported && typeof(T) == typeof(double)) + { + return AdvSimd.Arm64.Max(x.AsDouble(), y.AsDouble()).As(); + } - if (typeof(T) == typeof(double)) - { return Vector128.ConditionalSelect(Vector128.Equals(x, y), - Vector128.ConditionalSelect(IsNegative(x.AsDouble()).As(), y, x), + Vector128.ConditionalSelect(IsNegative(x), y, x), Vector128.Max(x, y)); } @@ -134,19 +120,11 @@ public static Vector128 Invoke(Vector128 x, Vector128 y) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Invoke(Vector256 x, Vector256 y) { - if (typeof(T) == typeof(float)) - { - return - Vector256.ConditionalSelect(Vector256.Equals(x, y), - Vector256.ConditionalSelect(IsNegative(x.AsSingle()).As(), y, x), - Vector256.Max(x, y)); - } - - if (typeof(T) == typeof(double)) + if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { return Vector256.ConditionalSelect(Vector256.Equals(x, y), - Vector256.ConditionalSelect(IsNegative(x.AsDouble()).As(), y, x), + Vector256.ConditionalSelect(IsNegative(x), y, x), Vector256.Max(x, y)); } @@ -156,19 +134,11 @@ public static Vector256 Invoke(Vector256 x, Vector256 y) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Invoke(Vector512 x, Vector512 y) { - if (typeof(T) == typeof(float)) - { - return - Vector512.ConditionalSelect(Vector512.Equals(x, y), - Vector512.ConditionalSelect(IsNegative(x.AsSingle()).As(), y, x), - Vector512.Max(x, y)); - } - - if (typeof(T) == typeof(double)) + if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { return Vector512.ConditionalSelect(Vector512.Equals(x, y), - Vector512.ConditionalSelect(IsNegative(x.AsDouble()).As(), y, x), + Vector512.ConditionalSelect(IsNegative(x), y, x), Vector512.Max(x, y)); } @@ -192,24 +162,18 @@ public static Vector512 Invoke(Vector512 x, Vector512 y) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Invoke(Vector128 x, Vector128 y) { - if (AdvSimd.IsSupported) + if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - if (typeof(T) == typeof(byte)) return AdvSimd.Max(x.AsByte(), y.AsByte()).As(); - if (typeof(T) == typeof(sbyte)) return AdvSimd.Max(x.AsSByte(), y.AsSByte()).As(); - if (typeof(T) == typeof(ushort)) return AdvSimd.Max(x.AsUInt16(), y.AsUInt16()).As(); - if (typeof(T) == typeof(short)) return AdvSimd.Max(x.AsInt16(), y.AsInt16()).As(); - if (typeof(T) == typeof(uint)) return AdvSimd.Max(x.AsUInt32(), y.AsUInt32()).As(); - if (typeof(T) == typeof(int)) return AdvSimd.Max(x.AsInt32(), y.AsInt32()).As(); - if (typeof(T) == typeof(float)) return AdvSimd.Max(x.AsSingle(), y.AsSingle()).As(); - } + if (AdvSimd.IsSupported && typeof(T) == typeof(float)) + { + return AdvSimd.Max(x.AsSingle(), y.AsSingle()).As(); + } - if (AdvSimd.Arm64.IsSupported) - { - if (typeof(T) == typeof(double)) return AdvSimd.Arm64.Max(x.AsDouble(), y.AsDouble()).As(); - } + if (AdvSimd.Arm64.IsSupported && typeof(T) == typeof(double)) + { + return AdvSimd.Arm64.Max(x.AsDouble(), y.AsDouble()).As(); + } - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { return Vector128.ConditionalSelect(Vector128.Equals(x, x), Vector128.ConditionalSelect(Vector128.Equals(y, y), diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxNumber.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxNumber.cs new file mode 100644 index 000000000000..dc0019ce6601 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MaxNumber.cs @@ -0,0 +1,183 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using System.Runtime.Intrinsics.X86; + +namespace System.Numerics.Tensors +{ + public static partial class TensorPrimitives + { + /// Searches for the largest number in the specified tensor. + /// The tensor, represented as a span. + /// The maximum element in . + /// Length of must be greater than zero. + /// + /// + /// The determination of the maximum element matches the IEEE 754:2019 `maximumNumber` function. Positive 0 is considered greater than negative 0. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static T MaxNumber(ReadOnlySpan x) + where T : INumber => + MinMaxCore>(x); + + /// Computes the element-wise maximum of the numbers in the specified tensors. + /// The first tensor, represented as a span. + /// The second tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Length of must be same as length of . + /// Destination is too short. + /// and reference overlapping memory locations and do not begin at the same location. + /// and reference overlapping memory locations and do not begin at the same location. + /// + /// + /// This method effectively computes [i] = .MaxNumber([i], [i]). + /// + /// + /// The determination of the maximum element matches the IEEE 754:2019 `maximumNumber` function. If either value is + /// the other is returned. Positive 0 is considered greater than negative 0. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static void MaxNumber(ReadOnlySpan x, ReadOnlySpan y, Span destination) + where T : INumber => + InvokeSpanSpanIntoSpan>(x, y, destination); + + /// Computes the element-wise maximum of the numbers in the specified tensors. + /// The first tensor, represented as a span. + /// The second tensor, represented as a scalar. + /// The destination tensor, represented as a span. + /// Destination is too short. + /// and reference overlapping memory locations and do not begin at the same location. + /// + /// + /// This method effectively computes [i] = .MaxNumber([i], ). + /// + /// + /// The determination of the maximum element matches the IEEE 754:2019 `maximumNumber` function. If either value is + /// the other is returned. Positive 0 is considered greater than negative 0. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static void MaxNumber(ReadOnlySpan x, T y, Span destination) + where T : INumber => + InvokeSpanScalarIntoSpan>(x, y, destination); + + /// T.MaxNumber(x, y) + internal readonly struct MaxNumberOperator : IAggregationOperator where T : INumber + { + public static bool Vectorizable => true; + + public static T Invoke(T x, T y) => T.MaxNumber(x, y); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 Invoke(Vector128 x, Vector128 y) + { + if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) + { + // We can't use AdvSimd.MaxNumber here because it doesn't correctly + // handle sNaN (it converts it to qNaN as per the now deprecated + // maxNum function defined by IEEE 754:2008, but which is not inline + // with the maximumNumber function that replaces it in IEEE 754:2019) + + Vector128 max; + + if (Sse.IsSupported && typeof(T) == typeof(float)) + { + max = Sse.Max(x.AsSingle(), y.AsSingle()).As(); + } + else if (Sse2.IsSupported && typeof(T) == typeof(double)) + { + max = Sse2.Max(x.AsDouble(), y.AsDouble()).As(); + } + else + { + max = Vector128.ConditionalSelect(Vector128.LessThan(y, x), x, y); + } + + return + Vector128.ConditionalSelect(Vector128.Equals(x, y), + Vector128.ConditionalSelect(IsNegative(y), x, y), + Vector128.ConditionalSelect(Vector128.Equals(y, y), max, x)); + } + + return Vector128.Max(x, y); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 Invoke(Vector256 x, Vector256 y) + { + if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) + { + Vector256 max; + + if (Avx.IsSupported && typeof(T) == typeof(float)) + { + max = Avx.Max(x.AsSingle(), y.AsSingle()).As(); + } + else if (Avx.IsSupported && typeof(T) == typeof(double)) + { + max = Avx.Max(x.AsDouble(), y.AsDouble()).As(); + } + else + { + max = Vector256.ConditionalSelect(Vector256.LessThan(y, x), x, y); + } + + return + Vector256.ConditionalSelect(Vector256.Equals(x, y), + Vector256.ConditionalSelect(IsNegative(y), x, y), + Vector256.ConditionalSelect(Vector256.Equals(y, y), max, x)); + } + + return Vector256.Max(x, y); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 Invoke(Vector512 x, Vector512 y) + { + if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) + { + Vector512 max; + + if (Avx512F.IsSupported && typeof(T) == typeof(float)) + { + max = Avx512F.Max(x.AsSingle(), y.AsSingle()).As(); + } + else if (Avx512F.IsSupported && typeof(T) == typeof(double)) + { + max = Avx512F.Max(x.AsDouble(), y.AsDouble()).As(); + } + else + { + max = Vector512.ConditionalSelect(Vector512.LessThan(y, x), x, y); + } + + return + Vector512.ConditionalSelect(Vector512.Equals(x, y), + Vector512.ConditionalSelect(IsNegative(y), x, y), + Vector512.ConditionalSelect(Vector512.Equals(y, y), max, x)); + } + + return Vector512.Max(x, y); + } + + public static T Invoke(Vector128 x) => HorizontalAggregate>(x); + public static T Invoke(Vector256 x) => HorizontalAggregate>(x); + public static T Invoke(Vector512 x) => HorizontalAggregate>(x); + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Min.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Min.cs index faea47805798..fd3931fa3d19 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Min.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Min.cs @@ -79,24 +79,18 @@ public static T Invoke(T x, T y) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Invoke(Vector128 x, Vector128 y) { - if (AdvSimd.IsSupported) + if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - if (typeof(T) == typeof(byte)) return AdvSimd.Min(x.AsByte(), y.AsByte()).As(); - if (typeof(T) == typeof(sbyte)) return AdvSimd.Min(x.AsSByte(), y.AsSByte()).As(); - if (typeof(T) == typeof(short)) return AdvSimd.Min(x.AsInt16(), y.AsInt16()).As(); - if (typeof(T) == typeof(ushort)) return AdvSimd.Min(x.AsUInt16(), y.AsUInt16()).As(); - if (typeof(T) == typeof(int)) return AdvSimd.Min(x.AsInt32(), y.AsInt32()).As(); - if (typeof(T) == typeof(uint)) return AdvSimd.Min(x.AsUInt32(), y.AsUInt32()).As(); - if (typeof(T) == typeof(float)) return AdvSimd.Min(x.AsSingle(), y.AsSingle()).As(); - } + if (AdvSimd.IsSupported && typeof(T) == typeof(float)) + { + return AdvSimd.Min(x.AsSingle(), y.AsSingle()).As(); + } - if (AdvSimd.Arm64.IsSupported) - { - if (typeof(T) == typeof(double)) return AdvSimd.Arm64.Min(x.AsDouble(), y.AsDouble()).As(); - } + if (AdvSimd.Arm64.IsSupported && typeof(T) == typeof(double)) + { + return AdvSimd.Arm64.Min(x.AsDouble(), y.AsDouble()).As(); + } - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { return Vector128.ConditionalSelect(Vector128.Equals(x, y), Vector128.ConditionalSelect(IsNegative(y), y, x), @@ -149,24 +143,18 @@ public static Vector512 Invoke(Vector512 x, Vector512 y) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Invoke(Vector128 x, Vector128 y) { - if (AdvSimd.IsSupported) + if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { - if (typeof(T) == typeof(byte)) return AdvSimd.Min(x.AsByte(), y.AsByte()).As(); - if (typeof(T) == typeof(sbyte)) return AdvSimd.Min(x.AsSByte(), y.AsSByte()).As(); - if (typeof(T) == typeof(short)) return AdvSimd.Min(x.AsInt16(), y.AsInt16()).As(); - if (typeof(T) == typeof(ushort)) return AdvSimd.Min(x.AsUInt16(), y.AsUInt16()).As(); - if (typeof(T) == typeof(int)) return AdvSimd.Min(x.AsInt32(), y.AsInt32()).As(); - if (typeof(T) == typeof(uint)) return AdvSimd.Min(x.AsUInt32(), y.AsUInt32()).As(); - if (typeof(T) == typeof(float)) return AdvSimd.Min(x.AsSingle(), y.AsSingle()).As(); - } + if (AdvSimd.IsSupported && typeof(T) == typeof(float)) + { + return AdvSimd.Min(x.AsSingle(), y.AsSingle()).As(); + } - if (AdvSimd.Arm64.IsSupported) - { - if (typeof(T) == typeof(double)) return AdvSimd.Arm64.Min(x.AsDouble(), y.AsDouble()).As(); - } + if (AdvSimd.Arm64.IsSupported && typeof(T) == typeof(double)) + { + return AdvSimd.Arm64.Min(x.AsDouble(), y.AsDouble()).As(); + } - if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) - { return Vector128.ConditionalSelect(Vector128.Equals(x, x), Vector128.ConditionalSelect(Vector128.Equals(y, y), diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinNumber.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinNumber.cs new file mode 100644 index 000000000000..79e04bf6d747 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MinNumber.cs @@ -0,0 +1,183 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using System.Runtime.Intrinsics.X86; + +namespace System.Numerics.Tensors +{ + public static partial class TensorPrimitives + { + /// Searches for the largest number in the specified tensor. + /// The tensor, represented as a span. + /// The maximum element in . + /// Length of must be greater than zero. + /// + /// + /// The determination of the maximum element matches the IEEE 754:2019 `maximumNumber` function. Positive 0 is considered greater than negative 0. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static T MinNumber(ReadOnlySpan x) + where T : INumber => + MinMaxCore>(x); + + /// Computes the element-wise maximum of the numbers in the specified tensors. + /// The first tensor, represented as a span. + /// The second tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Length of must be same as length of . + /// Destination is too short. + /// and reference overlapping memory locations and do not begin at the same location. + /// and reference overlapping memory locations and do not begin at the same location. + /// + /// + /// This method effectively computes [i] = .MinNumber([i], [i]). + /// + /// + /// The determination of the maximum element matches the IEEE 754:2019 `maximumNumber` function. If either value is + /// the other is returned. Positive 0 is considered greater than negative 0. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static void MinNumber(ReadOnlySpan x, ReadOnlySpan y, Span destination) + where T : INumber => + InvokeSpanSpanIntoSpan>(x, y, destination); + + /// Computes the element-wise maximum of the numbers in the specified tensors. + /// The first tensor, represented as a span. + /// The second tensor, represented as a scalar. + /// The destination tensor, represented as a span. + /// Destination is too short. + /// and reference overlapping memory locations and do not begin at the same location. + /// + /// + /// This method effectively computes [i] = .MinNumber([i], ). + /// + /// + /// The determination of the maximum element matches the IEEE 754:2019 `maximumNumber` function. If either value is + /// the other is returned. Positive 0 is considered greater than negative 0. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static void MinNumber(ReadOnlySpan x, T y, Span destination) + where T : INumber => + InvokeSpanScalarIntoSpan>(x, y, destination); + + /// T.MinNumber(x, y) + internal readonly struct MinNumberOperator : IAggregationOperator where T : INumber + { + public static bool Vectorizable => true; + + public static T Invoke(T x, T y) => T.MinNumber(x, y); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 Invoke(Vector128 x, Vector128 y) + { + if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) + { + // We can't use AdvSimd.MinNumber here because it doesn't correctly + // handle sNaN (it converts it to qNaN as per the now deprecated + // minNum function defined by IEEE 754:2008, but which is not inline + // with the minimumNumber function that replaces it in IEEE 754:2019) + + Vector128 min; + + if (Sse.IsSupported && typeof(T) == typeof(float)) + { + min = Sse.Min(x.AsSingle(), y.AsSingle()).As(); + } + else if (Sse2.IsSupported && typeof(T) == typeof(double)) + { + min = Sse2.Min(x.AsDouble(), y.AsDouble()).As(); + } + else + { + min = Vector128.ConditionalSelect(Vector128.LessThan(x, y), x, y); + } + + return + Vector128.ConditionalSelect(Vector128.Equals(x, y), + Vector128.ConditionalSelect(IsNegative(x), x, y), + Vector128.ConditionalSelect(Vector128.Equals(y, y), min, x)); + } + + return Vector128.Min(x, y); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 Invoke(Vector256 x, Vector256 y) + { + if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) + { + Vector256 min; + + if (Avx.IsSupported && typeof(T) == typeof(float)) + { + min = Avx.Min(x.AsSingle(), y.AsSingle()).As(); + } + else if (Avx.IsSupported && typeof(T) == typeof(double)) + { + min = Avx.Min(x.AsDouble(), y.AsDouble()).As(); + } + else + { + min = Vector256.ConditionalSelect(Vector256.LessThan(x, y), x, y); + } + + return + Vector256.ConditionalSelect(Vector256.Equals(x, y), + Vector256.ConditionalSelect(IsNegative(x), x, y), + Vector256.ConditionalSelect(Vector256.Equals(y, y), min, x)); + } + + return Vector256.Min(x, y); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 Invoke(Vector512 x, Vector512 y) + { + if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) + { + Vector512 min; + + if (Avx512F.IsSupported && typeof(T) == typeof(float)) + { + min = Avx512F.Min(x.AsSingle(), y.AsSingle()).As(); + } + else if (Avx512F.IsSupported && typeof(T) == typeof(double)) + { + min = Avx512F.Min(x.AsDouble(), y.AsDouble()).As(); + } + else + { + min = Vector512.ConditionalSelect(Vector512.LessThan(x, y), x, y); + } + + return + Vector512.ConditionalSelect(Vector512.Equals(x, y), + Vector512.ConditionalSelect(IsNegative(x), x, y), + Vector512.ConditionalSelect(Vector512.Equals(y, y), min, x)); + } + + return Vector512.Min(x, y); + } + + public static T Invoke(Vector128 x) => HorizontalAggregate>(x); + public static T Invoke(Vector256 x) => HorizontalAggregate>(x); + public static T Invoke(Vector512 x) => HorizontalAggregate>(x); + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MultiplyAdd.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MultiplyAdd.cs index 07042b32c379..3c76af4592ae 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MultiplyAdd.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MultiplyAdd.cs @@ -7,7 +7,7 @@ namespace System.Numerics.Tensors { public static partial class TensorPrimitives { - /// Computes the element-wise result of ( * ) * for the specified tensors of numbers. + /// Computes the element-wise result of ( * ) + for the specified tensors of numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The third tensor, represented as a span. @@ -29,7 +29,7 @@ public static void MultiplyAdd(ReadOnlySpan x, ReadOnlySpan y, ReadOnly where T : IAdditionOperators, IMultiplyOperators => InvokeSpanSpanSpanIntoSpan>(x, y, addend, destination); - /// Computes the element-wise result of ( * ) * for the specified tensors of numbers. + /// Computes the element-wise result of ( * ) + for the specified tensors of numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The third tensor, represented as a scalar. @@ -51,7 +51,7 @@ public static void MultiplyAdd(ReadOnlySpan x, ReadOnlySpan y, T addend where T : IAdditionOperators, IMultiplyOperators => InvokeSpanSpanScalarIntoSpan>(x, y, addend, destination); - /// Computes the element-wise result of ( * ) * for the specified tensors of numbers. + /// Computes the element-wise result of ( * ) + for the specified tensors of numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a scalar. /// The third tensor, represented as a span. diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MultiplyAddEstimate.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MultiplyAddEstimate.cs index 3bd615e54701..d3e651c160e8 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MultiplyAddEstimate.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.MultiplyAddEstimate.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.Arm; @@ -10,7 +11,7 @@ namespace System.Numerics.Tensors { public static partial class TensorPrimitives { - /// Computes the element-wise result of ( * ) * for the specified tensors of numbers. + /// Computes the element-wise result of ( * ) + for the specified tensors of numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The third tensor, represented as a span. @@ -36,7 +37,7 @@ public static void MultiplyAddEstimate(ReadOnlySpan x, ReadOnlySpan y, where T : INumberBase => InvokeSpanSpanSpanIntoSpan>(x, y, addend, destination); - /// Computes the element-wise result of ( * ) * for the specified tensors of numbers. + /// Computes the element-wise result of ( * ) + for the specified tensors of numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The third tensor, represented as a scalar. @@ -62,7 +63,7 @@ public static void MultiplyAddEstimate(ReadOnlySpan x, ReadOnlySpan y, where T : INumberBase => InvokeSpanSpanScalarIntoSpan>(x, y, addend, destination); - /// Computes the element-wise result of ( * ) * for the specified tensors of numbers. + /// Computes the element-wise result of ( * ) + for the specified tensors of numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a scalar. /// The third tensor, represented as a span. @@ -88,40 +89,51 @@ public static void MultiplyAddEstimate(ReadOnlySpan x, T y, ReadOnlySpan>(x, y, addend, destination); /// (x * y) + z - private readonly struct MultiplyAddEstimateOperator : ITernaryOperator where T : INumberBase + private readonly struct MultiplyAddEstimateOperator : ITernaryOperator + where T : INumberBase { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T Invoke(T x, T y, T z) { - // TODO https://github.com/dotnet/runtime/issues/98053: Use T.MultiplyAddEstimate when it's available. - +#if NET9_0_OR_GREATER + return T.MultiplyAddEstimate(x, y, z); +#else if (Fma.IsSupported || AdvSimd.IsSupported) { if (typeof(T) == typeof(Half)) { - Half result = Half.FusedMultiplyAdd(Unsafe.As(ref x), Unsafe.As(ref y), Unsafe.As(ref z)); - return Unsafe.As(ref result); + return (T)(object)Half.FusedMultiplyAdd((Half)(object)x, (Half)(object)y, (Half)(object)z); } if (typeof(T) == typeof(float)) { - float result = float.FusedMultiplyAdd(Unsafe.As(ref x), Unsafe.As(ref y), Unsafe.As(ref z)); - return Unsafe.As(ref result); + return (T)(object)float.FusedMultiplyAdd((float)(object)x, (float)(object)y, (float)(object)z); } if (typeof(T) == typeof(double)) { - double result = double.FusedMultiplyAdd(Unsafe.As(ref x), Unsafe.As(ref y), Unsafe.As(ref z)); - return Unsafe.As(ref result); + return (T)(object)double.FusedMultiplyAdd((double)(object)x, (double)(object)y, (double)(object)z); } } return (x * y) + z; +#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Invoke(Vector128 x, Vector128 y, Vector128 z) { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector128.MultiplyAddEstimate(x.AsDouble(), y.AsDouble(), z.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector128.MultiplyAddEstimate(x.AsSingle(), y.AsSingle(), z.AsSingle()).As(); + } +#else if (Fma.IsSupported) { if (typeof(T) == typeof(float)) return Fma.MultiplyAdd(x.AsSingle(), y.AsSingle(), z.AsSingle()).As(); @@ -139,11 +151,23 @@ public static Vector128 Invoke(Vector128 x, Vector128 y, Vector128 z } return (x * y) + z; +#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Invoke(Vector256 x, Vector256 y, Vector256 z) { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector256.MultiplyAddEstimate(x.AsDouble(), y.AsDouble(), z.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector256.MultiplyAddEstimate(x.AsSingle(), y.AsSingle(), z.AsSingle()).As(); + } +#else if (Fma.IsSupported) { if (typeof(T) == typeof(float)) return Fma.MultiplyAdd(x.AsSingle(), y.AsSingle(), z.AsSingle()).As(); @@ -151,11 +175,23 @@ public static Vector256 Invoke(Vector256 x, Vector256 y, Vector256 z } return (x * y) + z; +#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Invoke(Vector512 x, Vector512 y, Vector512 z) { +#if NET9_0_OR_GREATER + if (typeof(T) == typeof(double)) + { + return Vector512.MultiplyAddEstimate(x.AsDouble(), y.AsDouble(), z.AsDouble()).As(); + } + else + { + Debug.Assert(typeof(T) == typeof(float)); + return Vector512.MultiplyAddEstimate(x.AsSingle(), y.AsSingle(), z.AsSingle()).As(); + } +#else if (Avx512F.IsSupported) { if (typeof(T) == typeof(float)) return Avx512F.FusedMultiplyAdd(x.AsSingle(), y.AsSingle(), z.AsSingle()).As(); @@ -163,6 +199,7 @@ public static Vector512 Invoke(Vector512 x, Vector512 y, Vector512 z } return (x * y) + z; +#endif } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Pow.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Pow.cs index 72d35ed5be77..263235e4a5c2 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Pow.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Pow.cs @@ -59,7 +59,7 @@ public static void Pow(T x, ReadOnlySpan y, Span destination) private readonly struct PowOperator : IBinaryOperator where T : IPowerFunctions { - public static bool Vectorizable => typeof(T) == typeof(float) || typeof(T) == typeof(double); + public static bool Vectorizable => false; // typeof(T) == typeof(float) || typeof(T) == typeof(double); // TODO: https://github.com/dotnet/runtime/issues/100535 public static T Invoke(T x, T y) => T.Pow(x, y); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Reciprocal.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Reciprocal.cs index 50ef635a21ad..16d0df26157c 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Reciprocal.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.Reciprocal.cs @@ -95,6 +95,14 @@ public static void ReciprocalSqrtEstimate(ReadOnlySpan x, Span destinat public static Vector128 Invoke(Vector128 x) { +#if NET9_0_OR_GREATER + if (Avx512F.VL.IsSupported) + { + if (typeof(T) == typeof(float)) return Avx512F.VL.Reciprocal14(x.AsSingle()).As(); + if (typeof(T) == typeof(double)) return Avx512F.VL.Reciprocal14(x.AsDouble()).As(); + } +#endif + if (Sse.IsSupported) { if (typeof(T) == typeof(float)) return Sse.Reciprocal(x.AsSingle()).As(); @@ -115,6 +123,14 @@ public static Vector128 Invoke(Vector128 x) public static Vector256 Invoke(Vector256 x) { +#if NET9_0_OR_GREATER + if (Avx512F.VL.IsSupported) + { + if (typeof(T) == typeof(float)) return Avx512F.VL.Reciprocal14(x.AsSingle()).As(); + if (typeof(T) == typeof(double)) return Avx512F.VL.Reciprocal14(x.AsDouble()).As(); + } +#endif + if (Avx.IsSupported) { if (typeof(T) == typeof(float)) return Avx.Reciprocal(x.AsSingle()).As(); @@ -125,11 +141,13 @@ public static Vector256 Invoke(Vector256 x) public static Vector512 Invoke(Vector512 x) { +#if NET9_0_OR_GREATER if (Avx512F.IsSupported) { if (typeof(T) == typeof(float)) return Avx512F.Reciprocal14(x.AsSingle()).As(); if (typeof(T) == typeof(double)) return Avx512F.Reciprocal14(x.AsDouble()).As(); } +#endif return Vector512.One / x; } @@ -143,6 +161,14 @@ public static Vector512 Invoke(Vector512 x) public static Vector128 Invoke(Vector128 x) { +#if NET9_0_OR_GREATER + if (Avx512F.VL.IsSupported) + { + if (typeof(T) == typeof(float)) return Avx512F.VL.ReciprocalSqrt14(x.AsSingle()).As(); + if (typeof(T) == typeof(double)) return Avx512F.VL.ReciprocalSqrt14(x.AsDouble()).As(); + } +#endif + if (Sse.IsSupported) { if (typeof(T) == typeof(float)) return Sse.ReciprocalSqrt(x.AsSingle()).As(); @@ -163,6 +189,14 @@ public static Vector128 Invoke(Vector128 x) public static Vector256 Invoke(Vector256 x) { +#if NET9_0_OR_GREATER + if (Avx512F.VL.IsSupported) + { + if (typeof(T) == typeof(float)) return Avx512F.VL.ReciprocalSqrt14(x.AsSingle()).As(); + if (typeof(T) == typeof(double)) return Avx512F.VL.ReciprocalSqrt14(x.AsDouble()).As(); + } +#endif + if (Avx.IsSupported) { if (typeof(T) == typeof(float)) return Avx.ReciprocalSqrt(x.AsSingle()).As(); @@ -173,11 +207,13 @@ public static Vector256 Invoke(Vector256 x) public static Vector512 Invoke(Vector512 x) { +#if NET9_0_OR_GREATER if (Avx512F.IsSupported) { if (typeof(T) == typeof(float)) return Avx512F.ReciprocalSqrt14(x.AsSingle()).As(); if (typeof(T) == typeof(double)) return Avx512F.ReciprocalSqrt14(x.AsDouble()).As(); } +#endif return Vector512.One / Vector512.Sqrt(x); } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.RootN.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.RootN.cs index e7c394892950..5a732f769360 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.RootN.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.RootN.cs @@ -28,7 +28,7 @@ private readonly struct RootNOperator(int n) : IStatefulUnaryOperator wher { private readonly int _n = n; - public static bool Vectorizable => typeof(T) == typeof(float) || typeof(T) == typeof(double); + public static bool Vectorizable => false; // typeof(T) == typeof(float) || typeof(T) == typeof(double); // TODO: https://github.com/dotnet/runtime/issues/100535 public T Invoke(T x) => T.RootN(x, _n); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpan.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpan.cs new file mode 100644 index 000000000000..77c795fb8c11 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpan.cs @@ -0,0 +1,810 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using System.Runtime.Versioning; +using System.Text; +using static System.Runtime.InteropServices.JavaScript.JSType; +using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute; +using EditorBrowsableState = System.ComponentModel.EditorBrowsableState; + +#pragma warning disable 0809 //warning CS0809: Obsolete member 'TensorSpan.Equals(object)' overrides non-obsolete member 'object.Equals(object)' +#pragma warning disable 8500 // address / sizeof of managed types + +namespace System.Numerics.Tensors +{ + /// + /// TensorSpan represents a contiguous region of arbitrary memory. Unlike arrays, it can point to either managed + /// or native memory, or to memory allocated on the stack. It is type-safe and memory-safe. + /// + [DebuggerTypeProxy(typeof(TensorSpanDebugView<>))] + [DebuggerDisplay("{ToString(),raw}")] + public readonly ref struct TensorSpan + { + /// A byref or a native ptr. + internal readonly ref T _reference; + /// The number of elements this TensorSpan contains. + internal readonly nint _flattenedLength; + /// The length of the underlying memory. Can be different than the number of elements in the span. + internal readonly nint _memoryLength; + /// The lengths of each dimension. + internal readonly ReadOnlySpan _lengths; + /// The strides representing the memory offsets for each dimension. + private readonly ReadOnlySpan _strides; + + + /// + /// Creates a new span over the entirety of the target array. + /// + /// The target array. + /// Returns default when is null. + /// Thrown when is covariant and array's type is not exactly T[]. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TensorSpan(T[]? array) : this(array, 0, [], []) + { + } + + /// + /// Creates a new span over the portion of the target array beginning + /// at 'start' index and ending at 'end' index (exclusive). + /// + /// The target array. + /// The index at which to begin the span. + /// The lengths of the dimensions. If default is provided its assumed to have 1 dimension with a length equal to the length of the data. + /// The strides of each dimension. If default or span of length 0 is provided then strides will be automatically calculated. + /// Returns default when is null. + /// Thrown when is covariant and array's type is not exactly T[]. + /// + /// Thrown when the specified or end index is not in the range (<0 or >FlattenedLength). + /// + public TensorSpan(T[]? array, Index startIndex, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides) + : this(array, startIndex.GetOffset(array?.Length ?? 0), lengths, strides) + { + } + + /// + /// Creates a new span over the portion of the target array beginning + /// at 'start' index and ending at 'end' index (exclusive). + /// + /// The target array. + /// The index at which to begin the span. + /// The lengths of the dimensions. If default is provided its assumed to have 1 dimension with a length equal to the length of the data. + /// The strides of each dimension. If default or span of length 0 is provided then strides will be automatically calculated. + /// Returns default when is null. + /// Thrown when is covariant and array's type is not exactly T[]. + /// + /// Thrown when the specified or end index is not in the range (<0 or >FlattenedLength). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TensorSpan(T[]? array, int start, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + if (array == null) + { + if (start != 0 || linearLength != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + this = default; + return; // returns default + } + if (!typeof(T).IsValueType && array.GetType() != typeof(T[])) + ThrowHelper.ThrowArrayTypeMismatchException(); + + strides = strides.IsEmpty ? (ReadOnlySpan)TensorSpanHelpers.CalculateStrides(lengths) : strides; + nint maxElements = TensorSpanHelpers.ComputeMaxElementCount(strides, lengths); + + if (Environment.Is64BitProcess) + { + // See comment in Span.Slice for how this works. + if ((ulong)(uint)start + (ulong)(uint)maxElements > (ulong)(uint)array.Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + else + { + if ((uint)start > (uint)array.Length || (uint)maxElements > (uint)(array.Length - start)) + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + + _flattenedLength = linearLength; + _memoryLength = array.Length - start; + _reference = ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start /* force zero-extension */); + + _lengths = lengths.ToArray(); + _strides = strides.ToArray(); + } + + /// + /// Creates a new over the provided . The new will + /// have a rank of 1 and a length equal to the length of the provided . + /// + /// The target span. + public TensorSpan(Span span) : this(span, [span.Length], []) { } + + /// + /// Creates a new over the provided using the specified lengths and strides. + /// If the strides are not provided, they will be automatically calculated. + /// + /// The target span. + /// The lengths of each dimension. + /// The strides for each dimension. Will be automatically calculated if not provided. + public TensorSpan(Span span, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + if (span.IsEmpty) + { + if (linearLength != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + this = default; + return; // returns default + } + + strides = strides.IsEmpty ? (ReadOnlySpan)TensorSpanHelpers.CalculateStrides(lengths) : strides; + nint maxElements = TensorSpanHelpers.ComputeMaxElementCount(strides, lengths); + if (maxElements > span.Length) + ThrowHelper.ThrowArgument_InvalidStridesAndLengths(); + + _flattenedLength = linearLength; + _memoryLength = span.Length; + _reference = ref MemoryMarshal.GetReference(span); + + _lengths = lengths.ToArray(); + _strides = strides.ToArray(); + } + + /// + /// Creates a new over the provided . The new will + /// have a rank of 1 and a length equal to the length of the provided . + /// + /// The target array. + public TensorSpan(Array? array) : this(array, ReadOnlySpan.Empty, [], []) { } + + /// + /// Creates a new over the provided using the specified start offsets, lengths, and strides. + /// If the strides are not provided, they will be automatically calculated. + /// + /// The target array. + /// The starting offset for each dimension. + /// The lengths of each dimension. + /// The strides for each dimension. Will be automatically calculated if not provided. + public TensorSpan(Array? array, scoped ReadOnlySpan start, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + strides = strides.IsEmpty ? (ReadOnlySpan)TensorSpanHelpers.CalculateStrides(lengths) : strides; + nint startOffset = TensorSpanHelpers.ComputeLinearIndex(start, strides, lengths); + if (array == null) + { + if (!start.IsEmpty || linearLength != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + this = default; + return; // returns default + } + if (!typeof(T).IsValueType && array.GetType() != typeof(T[])) + ThrowHelper.ThrowArrayTypeMismatchException(); + + nint maxElements = TensorSpanHelpers.ComputeMaxElementCount(strides, lengths); + if (Environment.Is64BitProcess) + { + // See comment in Span.Slice for how this works. + if ((ulong)(uint)startOffset + (ulong)(uint)maxElements > (ulong)(uint)array.Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + else + { + if ((uint)startOffset > (uint)array.Length || (uint)maxElements > (uint)(array.Length - startOffset)) + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + + _flattenedLength = linearLength; + _memoryLength = array.Length; + _reference = ref Unsafe.Add(ref Unsafe.As(ref MemoryMarshal.GetArrayDataReference(array)), (nint)(uint)startOffset /* force zero-extension */); + + _lengths = lengths.ToArray(); + _strides = strides.ToArray(); + } + + /// + /// Creates a new over the provided using the specified start offsets, lengths, and strides. + /// If the strides are not provided, they will be automatically calculated. + /// + /// The target array. + /// The starting offset for each dimension. + /// The lengths of each dimension. + /// The strides for each dimension. Will be automatically calculated if not provided. + public TensorSpan(Array? array, scoped ReadOnlySpan startIndex, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + strides = strides.IsEmpty ? (ReadOnlySpan)TensorSpanHelpers.CalculateStrides(lengths) : strides; + nint start = TensorSpanHelpers.ComputeLinearIndex(startIndex, strides, lengths); + if (array == null) + { + if (!startIndex.IsEmpty || linearLength != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + this = default; + return; // returns default + } + if (!typeof(T).IsValueType && array.GetType() != typeof(T[])) + ThrowHelper.ThrowArrayTypeMismatchException(); + + nint maxElements = TensorSpanHelpers.ComputeMaxElementCount(strides, lengths); + if (Environment.Is64BitProcess) + { + // See comment in Span.Slice for how this works. + if ((ulong)(uint)start + (ulong)(uint)maxElements > (ulong)(uint)array.Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + else + { + if ((uint)start > (uint)array.Length || (uint)maxElements > (uint)(array.Length - start)) + ThrowHelper.ThrowArgumentOutOfRangeException(); + } + + _flattenedLength = linearLength; + _memoryLength = array.Length; + _reference = ref Unsafe.Add(ref Unsafe.As(ref MemoryMarshal.GetArrayDataReference(array)), (nint)(uint)start /* force zero-extension */); + + _lengths = lengths.ToArray(); + _strides = strides.ToArray(); + } + + /// + /// Creates a new span over the target unmanaged buffer. Clearly this + /// is quite dangerous the length is not checked. + /// But if this creation is correct, then all subsequent uses are correct. + /// + /// An unmanaged data to memory. + /// The number of elements the unmanaged memory can hold. + [CLSCompliant(false)] + public unsafe TensorSpan(T* data, nint dataLength) : this(data, dataLength, [dataLength], []) { } + + /// + /// Creates a new span over the target unmanaged buffer. Clearly this + /// is quite dangerous, because the length is not checked. + /// But if this creation is correct, then all subsequent uses are correct. + /// + /// An unmanaged data to memory. + /// The number of elements the unmanaged memory can hold. + /// The lengths of the dimensions. If default is provided its assumed to have 1 dimension with a length equal to the length of the data. + /// The lengths of the strides. If nothing is provided it figures out the default stride configuration. + /// + /// Thrown when is reference type or contains pointers and hence cannot be stored in unmanaged memory. + /// + /// + /// Thrown when the specified length is negative. + /// + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public unsafe TensorSpan(T* data, nint dataLength, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + if (RuntimeHelpers.IsReferenceOrContainsReferences()) + ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T)); + + strides = strides.IsEmpty ? (ReadOnlySpan)TensorSpanHelpers.CalculateStrides(lengths) : strides; + nint maxElements = TensorSpanHelpers.ComputeMaxElementCount(strides, lengths); + if (maxElements > dataLength) + ThrowHelper.ThrowArgument_InvalidStridesAndLengths(); + _flattenedLength = linearLength; + _memoryLength = dataLength; + _reference = ref *data; + + _lengths = lengths.ToArray(); + _strides = strides.ToArray(); + } + + // Constructor for internal use only. It is not safe to expose publicly. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal TensorSpan(ref T reference, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, nint memoryLength) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + + _flattenedLength = linearLength; + _memoryLength = memoryLength; + _reference = ref reference; + + _lengths = lengths.ToArray(); + _strides = strides.ToArray(); + } + + /// + /// Returns a reference to specified element of the TensorSpan. + /// + /// + /// + /// + /// Thrown when any index is less than 0 or any index is greater than or equal to FlattenedLength + /// + public ref T this[params scoped ReadOnlySpan indexes] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + if (indexes.Length != Rank) + ThrowHelper.ThrowIndexOutOfRangeException(); + + nint index = TensorSpanHelpers.ComputeLinearIndex(indexes, Strides, Lengths); + if (index >= _memoryLength || index < 0) + ThrowHelper.ThrowIndexOutOfRangeException(); + + return ref Unsafe.Add(ref _reference, index /* force zero-extension */); + } + } + + /// + /// Returns a reference to specified element of the TensorSpan. + /// + /// + /// + /// + /// Thrown when any index is less than 0 or any index is greater than or equal to FlattenedLength + /// + public ref T this[params scoped ReadOnlySpan indexes] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + + if (indexes.Length != Rank) + ThrowHelper.ThrowIndexOutOfRangeException(); + + nint index = TensorSpanHelpers.ComputeLinearIndex(indexes, Strides, Lengths); + if (index >= _memoryLength || index < 0) + ThrowHelper.ThrowIndexOutOfRangeException(); + + return ref Unsafe.Add(ref _reference, index /* force zero-extension */); + } + } + + /// + /// Returns a slice of the TensorSpan. + /// + /// + /// + /// + /// Thrown when any index is less than 0 or any index is greater than or equal to FlattenedLength + /// + public TensorSpan this[params scoped ReadOnlySpan ranges] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return Slice(ranges); + } + set + { + value.CopyTo(this[ranges]); + } + } + + /// + /// The number of items in the span. + /// + public nint FlattenedLength => _flattenedLength; + + /// + /// Gets a value indicating whether this is empty. + /// + /// if this span is empty; otherwise, . + public bool IsEmpty => _flattenedLength == 0; + + /// + /// Gets the length of each dimension in this . + /// + [UnscopedRef] + public ReadOnlySpan Lengths => _lengths; + + /// + /// Gets the rank, aka the number of dimensions, of this . + /// + public int Rank => Lengths.Length; + + /// + /// Gets the strides of this + /// + [UnscopedRef] + public ReadOnlySpan Strides => _strides; + + /// + /// Returns false if left and right point at the same memory and have the same length. Note that + /// this does *not* check to see if the *contents* are equal. + /// + public static bool operator !=(TensorSpan left, TensorSpan right) => !(left == right); + + /// + /// Returns true if left and right point at the same memory and have the same length. Note that + /// this does *not* check to see if the *contents* are equal. + /// + public static bool operator ==(TensorSpan left, TensorSpan right) => + left._flattenedLength == right._flattenedLength && + left.Rank == right.Rank && + left._lengths.SequenceEqual(right._lengths) && + Unsafe.AreSame(ref left._reference, ref right._reference); + + /// + /// This method is not supported as spans cannot be boxed. To compare two spans, use operator==. + /// + /// + /// Always thrown by this method. + /// + [Obsolete("Equals() on TensorSpan will always throw an exception. Use the equality operator instead.")] + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object? obj) => + throw new NotSupportedException(SR.NotSupported_CannotCallEqualsOnSpan); + + /// + /// This method is not supported as spans cannot be boxed. + /// + /// + /// Always thrown by this method. + /// + [Obsolete("GetHashCode() on TensorSpan will always throw an exception.")] + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => + throw new NotSupportedException(SR.NotSupported_CannotCallGetHashCodeOnSpan); + + /// + /// Returns an empty + /// + public static TensorSpan Empty => default; + + /// Gets an enumerator for this span. + public Enumerator GetEnumerator() => new Enumerator(this); + + /// Enumerates the elements of a . + public ref struct Enumerator + { + /// The span being enumerated. + private readonly TensorSpan _span; + /// The current index that the enumerator is on. + private Span _curIndexes; + /// The total item count. + private nint _items; + + /// Initialize the enumerator. + /// The span to enumerate. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal Enumerator(TensorSpan span) + { + _span = span; + _items = -1; + _curIndexes = new nint[_span.Rank]; + + _curIndexes[_span.Rank - 1] = -1; + } + + /// Advances the enumerator to the next element of the span. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + { + TensorSpanHelpers.AdjustIndexes(_span.Rank - 1, 1, _curIndexes, _span.Lengths); + + if (_items < _span.FlattenedLength) + _items++; + + return _items < _span.FlattenedLength; + } + + /// Gets the element at the current position of the enumerator. + public ref T Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => ref _span[_curIndexes]; + } + } + + /// + /// Returns a reference to the 0th element of the TensorSpan. If the TensorSpan is empty, returns null reference. + /// It can be used for pinning and is required to support the use of span within a fixed statement. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public ref T GetPinnableReference() + { + // Ensure that the native code has just one forward branch that is predicted-not-taken. + ref T ret = ref Unsafe.NullRef(); + if (_flattenedLength != 0) ret = ref _reference; + return ref ret; + } + + /// + /// Clears the contents of this span. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Clear() + { + scoped Span curIndexes; + nint[]? curIndexesArray; + if (Rank > 6) + { + curIndexesArray = ArrayPool.Shared.Rent(Rank); + curIndexes = curIndexesArray; + } + else + { + curIndexesArray = null; + curIndexes = stackalloc nint[Rank]; + } + + nint clearedValues = 0; + while (clearedValues < _flattenedLength) + { + TensorSpanHelpers.Clear(ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), (nuint)Lengths[Rank - 1]); + TensorSpanHelpers.AdjustIndexes(Rank - 2, 1, curIndexes, _lengths); + clearedValues += Lengths[Rank - 1]; + } + Debug.Assert(clearedValues == _flattenedLength, "Didn't clear the right amount"); + + if (curIndexesArray != null) + ArrayPool.Shared.Return(curIndexesArray); + } + + /// + /// Fills the contents of this span with the given value. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Fill(T value) + { + Span curIndexes = stackalloc nint[Rank]; + nint filledValues = 0; + // REVIEW: If we track the actual length of the backing data, because FlattenedLength doesn't always equal the actual length, we could use that here to not need to loop. + while (filledValues < _flattenedLength) + { + TensorSpanHelpers.Fill(ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), (nuint)Lengths[Rank - 1], value); + TensorSpanHelpers.AdjustIndexes(Rank - 2, 1, curIndexes, _lengths); + filledValues += Lengths[Rank - 1]; + } + + Debug.Assert(filledValues == _flattenedLength, "Didn't copy the right amount to the array."); + + } + + /// + /// Copies the contents of this span into destination span. If the source + /// and destinations overlap, this method behaves as if the original values in + /// a temporary location before the destination is overwritten. + /// + /// The span to copy items into. + /// + /// Thrown when the destination TensorSpan is shorter than the source Span. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyTo(scoped TensorSpan destination) + { + // Using "if (!TryCopyTo(...))" results in two branches: one for the length + // check, and one for the result of TryCopyTo. Since these checks are equivalent, + // we can optimize by performing the check once ourselves then calling Memmove directly. + if (_flattenedLength > destination.FlattenedLength) + ThrowHelper.ThrowArgumentException_DestinationTooShort(); + + scoped Span curIndexes; + nint[]? curIndexesArray; + if (Rank > 6) + { + curIndexesArray = ArrayPool.Shared.Rent(Rank); + curIndexes = curIndexesArray; + } + else + { + curIndexesArray = null; + curIndexes = stackalloc nint[Rank]; + } + + nint copiedValues = 0; + TensorSpan slice = destination.Slice(_lengths); + while (copiedValues < _flattenedLength) + { + TensorSpanHelpers.Memmove(ref Unsafe.Add(ref slice._reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, destination.Strides, Lengths)), ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), Lengths[Rank - 1]); + TensorSpanHelpers.AdjustIndexes(Rank - 2, 1, curIndexes, _lengths); + copiedValues += Lengths[Rank - 1]; + } + Debug.Assert(copiedValues == _flattenedLength, "Didn't copy the right amount to the array."); + + if (curIndexesArray != null) + ArrayPool.Shared.Return(curIndexesArray); + + } + + /// + /// Copies the contents of this span into destination span. If the source + /// and destinations overlap, this method behaves as if the original values in + /// a temporary location before the destination is overwritten. + /// + /// The span to copy items into. + /// If the destination span is shorter than the source span, this method + /// return false and no data is written to the destination. + public bool TryCopyTo(scoped TensorSpan destination) + { + bool retVal = false; + + if (_flattenedLength <= destination.FlattenedLength) + { + scoped Span curIndexes; + nint[]? curIndexesArray; + if (Rank > 6) + { + curIndexesArray = ArrayPool.Shared.Rent(Rank); + curIndexes = curIndexesArray; + } + else + { + curIndexesArray = null; + curIndexes = stackalloc nint[Rank]; + } + + nint copiedValues = 0; + TensorSpan slice = destination.Slice(_lengths); + while (copiedValues < _flattenedLength) + { + TensorSpanHelpers.Memmove(ref Unsafe.Add(ref slice._reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), Lengths[Rank - 1]); + TensorSpanHelpers.AdjustIndexes(Rank - 2, 1, curIndexes, _lengths); + copiedValues += Lengths[Rank - 1]; + } + retVal = true; + Debug.Assert(copiedValues == _flattenedLength, "Didn't copy the right amount to the array."); + + if (curIndexesArray != null) + ArrayPool.Shared.Return(curIndexesArray); + } + return retVal; + } + + //public static explicit operator TensorSpan(Array? array); + public static implicit operator TensorSpan(T[]? array) => new TensorSpan(array); + + /// + /// Defines an implicit conversion of a to a + /// + public static implicit operator ReadOnlyTensorSpan(TensorSpan span) => + new ReadOnlyTensorSpan(ref span._reference, span._lengths, span._strides, span._memoryLength); + + /// + /// For , returns a new instance of string that represents the characters pointed to by the span. + /// Otherwise, returns a with the name of the type and the number of elements. + /// + public override string ToString() => $"System.Numerics.Tensors.TensorSpan<{typeof(T).Name}>[{_flattenedLength}]"; + + /// + /// Returns a reference to specified element of the TensorSpan. + /// + /// The indexes for the slice. + /// + /// + /// Thrown when any index is less than 0 or any index is greater than or equal to FlattenedLength + /// + public TensorSpan Slice(params scoped ReadOnlySpan indexes) + { + NRange[] ranges = new NRange[indexes.Length]; + for (int i = 0; i < indexes.Length; i++) + { + ranges[i] = new NRange(checked((int)indexes[i].GetOffset(Lengths[i])), Lengths[i]); + } + return Slice(ranges); + } + + /// + /// Takes in the lengths of the dimensions and slices according to them. + /// + /// The dimension lengths + /// A based on the provided + internal TensorSpan Slice(params scoped ReadOnlySpan lengths) + { + NRange[] ranges = new NRange[lengths.Length]; + for(int i = 0; i < lengths.Length; i++) + { + ranges[i] = new NRange(0, lengths[i]); + } + return Slice(ranges); + } + + /// + /// Forms a slice out of the given span + /// + /// The ranges for the slice + /// A based on the provided + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TensorSpan Slice(params scoped ReadOnlySpan ranges) + { + if (ranges.Length != Lengths.Length) + ThrowHelper.ThrowIndexOutOfRangeException(); + + nint[] lengths = new nint[ranges.Length]; + nint[] offsets = new nint[ranges.Length]; + + for (int i = 0; i < ranges.Length; i++) + { + (offsets[i], lengths[i]) = ranges[i].GetOffsetAndLength(Lengths[i]); + } + + nint index = 0; + for (int i = 0; i < offsets.Length; i++) + { + if (offsets[i] < 0 || offsets[i] >= Lengths[i]) + ThrowHelper.ThrowIndexOutOfRangeException(); + + index += Strides[i] * (offsets[i]); + } + + if (index >= _memoryLength || index < 0) + ThrowHelper.ThrowIndexOutOfRangeException(); + + return new TensorSpan(ref Unsafe.Add(ref _reference, index), lengths, _strides, _memoryLength - index); + } + + /// + /// Flattens the contents of this span into the provided . + /// + /// The span to copy items into. + public bool TryFlattenTo(scoped Span destination) + { + bool retVal = false; + if (destination.Length < _flattenedLength) + { + scoped Span curIndexes; + nint[]? curIndexesArray; + if (Rank > 6) + { + curIndexesArray = ArrayPool.Shared.Rent(Rank); + curIndexes = curIndexesArray; + } + else + { + curIndexesArray = null; + curIndexes = stackalloc nint[Rank]; + } + + nint copiedValues = 0; + while (copiedValues < _flattenedLength) + { + TensorSpanHelpers.Memmove(destination.Slice(checked((int)copiedValues)), ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), Lengths[Rank - 1]); + TensorSpanHelpers.AdjustIndexes(Rank - 2, 1, curIndexes, _lengths); + copiedValues += Lengths[Rank - 1]; + } + + if (curIndexesArray != null) + ArrayPool.Shared.Return(curIndexesArray); + retVal = true; + } + return retVal; + } + + /// + /// Flattens the contents of this span into the provided . + /// + /// The span to copy items into. + public void FlattenTo(scoped Span destination) + { + if (destination.Length < _flattenedLength) + ThrowHelper.ThrowArgumentException_DestinationTooShort(); + + if (_flattenedLength == 0) + return; + + scoped Span curIndexes; + nint[]? curIndexesArray; + if (Rank > 6) + { + curIndexesArray = ArrayPool.Shared.Rent(Rank); + curIndexes = curIndexesArray; + } + else + { + curIndexesArray = null; + curIndexes = stackalloc nint[Rank]; + } + + nint copiedValues = 0; + while (copiedValues < _flattenedLength) + { + TensorSpanHelpers.Memmove(destination.Slice(checked((int)copiedValues)), ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), Lengths[Rank - 1]); + TensorSpanHelpers.AdjustIndexes(Rank - 2, 1, curIndexes, _lengths); + copiedValues += Lengths[Rank - 1]; + } + + if (curIndexesArray != null) + ArrayPool.Shared.Return(curIndexesArray); + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanDebugView.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanDebugView.cs new file mode 100644 index 000000000000..151f04fd67dd --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanDebugView.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Numerics.Tensors +{ + internal sealed class TensorSpanDebugView + { + private readonly T[] _array; + + public TensorSpanDebugView(TensorSpan span) + { + _array = new T[span.FlattenedLength]; + span.FlattenTo(_array); + } + + public TensorSpanDebugView(ReadOnlyTensorSpan span) + { + _array = new T[span.FlattenedLength]; + span.FlattenTo(_array); + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public T[] Items => _array; + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanExtensions.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanExtensions.cs new file mode 100644 index 000000000000..629ffb27f64d --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanExtensions.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace System.Numerics.Tensors +{ + public static class TensorSpan + { + /// + /// Determines whether two sequences are equal by comparing the elements using IEquatable{T}.Equals(T). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe bool SequenceEqual(this TensorSpan span, TensorSpan other) where T : IEquatable? => span.FlattenedLength == other.FlattenedLength && span.Lengths.SequenceEqual(other.Lengths) && TensorSpanHelpers.SequenceEqual(ref span.GetPinnableReference(), ref other.GetPinnableReference(), (nuint)span.FlattenedLength); + + // Doing a copy here for shape because otherwise I get a CS8347 about potentially exposing it beyond its lifetime. In this case that would never happen + // because we were always doing a copy of the shape in the constructor anyways, but I couldn't figure out another way around it. + /// + /// Extension method to more easily create a TensorSpan from an array. + /// + /// The type of the elements in the array + /// The with the data + /// The shape for the + /// + public static TensorSpan AsTensorSpan(this T[]? array, params scoped ReadOnlySpan shape) => new(array, 0, shape, default); + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanHelpers.T.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanHelpers.T.cs new file mode 100644 index 000000000000..5a55bebba6b4 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanHelpers.T.cs @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Xml.Serialization; + + +#pragma warning disable 8500 // sizeof of managed types + +namespace System.Numerics.Tensors +{ + internal static partial class TensorSpanHelpers // .T + { + public static unsafe void Memmove(Span destination, ReadOnlySpan source, nint length, nint dstOffset = 0) + { + source.Slice(0, checked((int)length)).CopyTo(destination.Slice(checked((int)dstOffset))); + } + + public static unsafe void Memmove(ref T[] destination, ref T source, nint length) + { + MemoryMarshal.CreateSpan(ref source, checked((int)length)).CopyTo(destination); + } + + public static unsafe void Memmove(ref T destination, ref T source, nint length) + { + MemoryMarshal.CreateSpan(ref source, checked((int)length)).CopyTo(MemoryMarshal.CreateSpan(ref destination, checked((int)length))); + } + + public static unsafe void Memmove(Span destination, ref T source, nint length) + { + MemoryMarshal.CreateSpan(ref source, checked((int)length)).CopyTo(destination); + } + + public static void Clear(ref T dest, nuint len) + { + while (len > 0) + { + nuint toClear = Math.Min(len, int.MaxValue); + MemoryMarshal.CreateSpan(ref dest, (int)toClear).Clear(); + dest = ref Unsafe.Add(ref dest, toClear); + len -= toClear; + } + } + + public static unsafe void Fill(ref T dest, nuint numElements, T value) + { + while (numElements > 0) + { + nuint toFill = Math.Min(numElements, int.MaxValue); + MemoryMarshal.CreateSpan(ref dest, (int)toFill).Fill(value); + dest = ref Unsafe.Add(ref dest, toFill); + numElements -= toFill; + } + } + + public static bool SequenceEqual(ref T first, ref T second, nuint length) where T : IEquatable? + { + bool equal = true; + while (length > 0) + { + nuint toCompare = Math.Min(length, int.MaxValue); + equal &= MemoryMarshal.CreateSpan(ref first, (int)toCompare).SequenceEqual(MemoryMarshal.CreateSpan(ref second, (int)toCompare)); + first = ref Unsafe.Add(ref first, toCompare); + second = ref Unsafe.Add(ref second, toCompare); + length -= toCompare; + } + + return equal; + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanHelpers.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanHelpers.cs new file mode 100644 index 000000000000..d40726f4ab83 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanHelpers.cs @@ -0,0 +1,199 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using Microsoft.VisualBasic; + +#pragma warning disable 8500 // sizeof of managed types + +namespace System.Numerics.Tensors +{ + internal static partial class TensorSpanHelpers + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint CalculateTotalLength(ReadOnlySpan lengths) + { + if (lengths.IsEmpty) + return 0; + nint totalLength = 1; + for (int i = 0; i < lengths.Length; i++) + { + if (lengths[i] < 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + totalLength *= lengths[i]; + } + + if (totalLength < 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + return totalLength; + } + + /// + /// Gets the set of strides that can be used to calculate the offset of n-dimensions in a 1-dimensional layout + /// + /// + public static nint[] CalculateStrides(ReadOnlySpan lengths) + { + nint[] strides = new nint[lengths.Length]; + + nint stride = 1; + + for (int i = strides.Length - 1; i >= 0; i--) + { + strides[i] = stride; + stride *= lengths[i]; + } + + return strides; + } + + /// + /// Calculates the 1-d index for n-d indexes in layout specified by strides. + /// + /// + /// + /// + /// + public static nint ComputeLinearIndex(ReadOnlySpan indexes, ReadOnlySpan strides, ReadOnlySpan lengths) + { + Debug.Assert(strides.Length == indexes.Length); + + nint index = 0; + for (int i = 0; i < indexes.Length; i++) + { + if (indexes[i] >= lengths[i] || indexes[i] < 0) + ThrowHelper.ThrowIndexOutOfRangeException(); + index += strides[i] * indexes[i]; + } + + return index; + } + + /// + /// Calculates the 1-d index for n-d indexes in layout specified by strides. + /// + /// + /// + /// + /// + public static nint ComputeLinearIndex(ReadOnlySpan indexes, ReadOnlySpan strides, ReadOnlySpan lengths) + { + Debug.Assert(strides.Length == indexes.Length); + + nint index = 0; + for (int i = 0; i < indexes.Length; i++) + { + if (indexes[i] >= lengths[i] || indexes[i] < 0) + ThrowHelper.ThrowIndexOutOfRangeException(); + index += strides[i] * indexes[i]; + } + + return index; + } + + /// + /// Calculates the 1-d index for n-d indexes in layout specified by strides. + /// + /// + /// + /// + /// + public static nint ComputeLinearIndex(ReadOnlySpan indexes, ReadOnlySpan strides, ReadOnlySpan lengths) + { + Debug.Assert(strides.Length == indexes.Length); + + nint index = 0; + for (int i = 0; i < indexes.Length; i++) + { + nint offset = indexes[i].GetOffset(lengths[i]); + if (offset >= lengths[i] || offset < 0) + ThrowHelper.ThrowIndexOutOfRangeException(); + index += strides[i] * offset; + } + + return index; + } + + public static nint ComputeMaxElementCount(ReadOnlySpan strides, ReadOnlySpan lengths) + { + Debug.Assert(strides.Length == lengths.Length); + + nint index = 0; + for (int i = 0; i < lengths.Length; i++) + { + if (strides[i] < 0) + ThrowHelper.ThrowArgument_StrideLessThan0(); + index *= strides[i] * lengths[i]; + } + + return index; + } + + /// + /// Takes the span holding the current index and increments it by the addend. If the length of the current spot is greater than the + /// length of that dimension then it rolls that over to the next dimension. + /// + /// The current index from the indexes we are on. + /// How much we are adding to the + /// The current indexes + /// The length of the TensorSpan we are iterating over. + public static void AdjustIndexes(int curIndex, nint addend, Span curIndexes, scoped ReadOnlySpan length) + { + if (addend <= 0 || curIndex < 0) + return; + curIndexes[curIndex] += addend; + + (nint Quotient, nint Remainder) result = Math.DivRem(curIndexes[curIndex], length[curIndex]); + + AdjustIndexes(curIndex - 1, result.Quotient, curIndexes, length); + curIndexes[curIndex] = result.Remainder; + } + + /// + /// Takes the span holding the current index and increments it by the addend. If the length of the current spot is greater than the + /// length of that dimension then it rolls that over to the next dimension. + /// + /// The current index from the indexes we are on. + /// How much we are adding to the + /// The current indexes + /// The length of the TensorSpan we are iterating over. + public static void AdjustIndexes(int curIndex, nint addend, ref nint[] curIndexes, ReadOnlySpan shape) + { + if (addend <= 0 || curIndex < 0) + return; + curIndexes[curIndex] += addend; + + (nint Quotient, nint Remainder) result = Math.DivRem(curIndexes[curIndex], shape[curIndex]); + + AdjustIndexes(curIndex - 1, result.Quotient, ref curIndexes, shape); + curIndexes[curIndex] = result.Remainder; + } + + /// + /// Takes the span holding the current index and decrements it by the addend. If the length of the current spot is greater than the + /// length of that dimension then it rolls that over to the next dimension. + /// + /// The current index from the indexes we are on. + /// How much we are subtracting from the + /// The current indexes + /// The length of the TensorSpan we are iterating over. + public static void AdjustIndexesDown(int curIndex, nint addend, Span curIndexes, ReadOnlySpan shape) + { + if (addend <= 0 || curIndex < 0) + return; + curIndexes[curIndex] -= addend; + if (curIndexes[curIndex] < 0) + { + curIndexes[curIndex] = shape[curIndex] - 1; + AdjustIndexes(curIndex - 1, 1, curIndexes, shape); + } + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/ThrowHelper.cs b/src/libraries/System.Numerics.Tensors/src/System/ThrowHelper.cs index 380add4727e8..520de436ac5f 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/ThrowHelper.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/ThrowHelper.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; namespace System @@ -26,5 +27,182 @@ public static void ThrowArgument_SpansMustBeNonEmpty() => [DoesNotReturn] public static void ThrowArgument_InputAndDestinationSpanMustNotOverlap() => throw new ArgumentException(SR.Argument_InputAndDestinationSpanMustNotOverlap, "destination"); + + [DoesNotReturn] + internal static void ThrowArrayTypeMismatchException() + { + throw new ArrayTypeMismatchException(); + } + + [DoesNotReturn] + internal static void ThrowArgumentOutOfRangeException() + { + throw new ArgumentOutOfRangeException(); + } + + [DoesNotReturn] + internal static void ThrowInvalidTypeWithPointersNotSupported(Type targetType) + { + throw new ArgumentException(SR.Format(SR.Argument_InvalidTypeWithPointersNotSupported, targetType)); + } + + [DoesNotReturn] + internal static void ThrowIndexOutOfRangeException() + { + throw new IndexOutOfRangeException(); + } + + [DoesNotReturn] + public static void ThrowArgumentException_DestinationTooShort() + { + throw GetArgumentException(SR.DestinationTooShort); + } + + [DoesNotReturn] + public static void ThrowArgument_LengthsMustEqualArrayLength() + { + throw new ArgumentOutOfRangeException(); + } + + [DoesNotReturn] + public static void ThrowArgument_IndicesLengthMustEqualRank() => + throw new ArgumentException(SR.ThrowArgument_IndicesLengthMustEqualRank); + + private static ArgumentException GetArgumentException(string message) + { + return new ArgumentException(message); + } + + [DoesNotReturn] + public static void ThrowValueArgumentOutOfRange_NeedNonNegNumException() + { + throw new ArgumentOutOfRangeException("value", SR.ThrowArgument_ValueNonNegative); + } + + [DoesNotReturn] + public static void ThrowArgument_FilterTensorMustEqualTensorLength() + { + throw new ArgumentException(SR.ThrowArgument_FilterTensorMustEqualTensorLength); + } + + [DoesNotReturn] + public static void ThrowArgument_SetSliceNoRange(string? paramNames) + { + throw new ArgumentException(SR.ThrowArgument_SetSliceNoRange, paramNames); + } + + [DoesNotReturn] + public static void ThrowArgument_SetSliceInvalidShapes(string? paramNames) + { + throw new ArgumentException(SR.ThrowArgument_SetSliceInvalidShapes, paramNames); + } + + [DoesNotReturn] + public static void ThrowArgument_ShapesNotBroadcastCompatible() + { + throw new ArgumentException(SR.ThrowArgument_ShapesNotBroadcastCompatible); + } + + [DoesNotReturn] + public static void ThrowArgument_SplitNotSplitEvenly() + { + throw new ArgumentException(SR.ThrowArgument_SplitNotSplitEvenly); + } + + [DoesNotReturn] + public static void ThrowArgument_DimensionsNotSame(string? paramNames) + { + throw new ArgumentException(SR.ThrowArgument_DimensionsNotSame, paramNames); + } + + [DoesNotReturn] + public static void ThrowArgument_1DTensorRequired(string? paramNames) + { + throw new ArgumentException(SR.ThrowArgument_1DTensorRequired, paramNames); + } + + [DoesNotReturn] + public static void ThrowArgument_IncorrectNumberOfFilterItems(string? paramNames) + { + throw new ArgumentException(SR.ThrowArgument_IncorrectNumberOfFilterItems, paramNames); + } + + [DoesNotReturn] + public static void ThrowArgument_StackTooFewTensors() + { + throw new ArgumentException(SR.ThrowArgument_StackTooFewTensors); + } + + [DoesNotReturn] + public static void ThrowArgument_OnlyOneWildcard() + { + throw new ArgumentException(SR.ThrowArgument_OnlyOneWildcard); + } + + [DoesNotReturn] + public static void ThrowArgument_InvalidReshapeDimensions() + { + throw new ArgumentException(SR.ThrowArgument_InvalidReshapeDimensions); + } + + [DoesNotReturn] + public static void ThrowArgument_AxisLargerThanRank() + { + throw new ArgumentException(SR.ThrowArgument_AxisLargerThanRank); + } + + [DoesNotReturn] + public static void ThrowArgument_InvalidSqueezeAxis() + { + throw new ArgumentException(SR.ThrowArgument_InvalidSqueezeAxis); + } + + [DoesNotReturn] + public static void ThrowArgument_ConcatenateTooFewTensors() + { + throw new ArgumentException(SR.ThrowArgument_ConcatenateTooFewTensors); + } + + [DoesNotReturn] + public static void ThrowArgument_InvalidAxis() + { + throw new ArgumentException(SR.ThrowArgument_InvalidAxis); + } + + [DoesNotReturn] + public static void ThrowArgument_InvalidConcatenateShape() + { + throw new ArgumentException(SR.ThrowArgument_InvalidConcatenateShape); + } + + [DoesNotReturn] + public static void ThrowArgument_TransposeTooFewDimensions() + { + throw new ArgumentException(SR.ThrowArgument_TransposeTooFewDimensions); + } + + [DoesNotReturn] + public static void ThrowArgument_PermuteAxisOrder() + { + throw new ArgumentException(SR.ThrowArgument_PermuteAxisOrder); + } + + [DoesNotReturn] + public static void ThrowArgument_InPlaceInvalidShape() + { + throw new ArgumentException(SR.ThrowArgument_InPlaceInvalidShape); + } + + [DoesNotReturn] + public static void ThrowArgument_InvalidStridesAndLengths() + { + throw new ArgumentException(SR.ThrowArgument_InvalidStridesAndLengths); + } + + [DoesNotReturn] + public static void ThrowArgument_StrideLessThan0() + { + throw new ArgumentException(SR.ThrowArgument_StrideLessThan0); + } } } diff --git a/src/libraries/System.Numerics.Tensors/tests/Helpers.cs b/src/libraries/System.Numerics.Tensors/tests/Helpers.cs index 729cacda3516..052d22d0e183 100644 --- a/src/libraries/System.Numerics.Tensors/tests/Helpers.cs +++ b/src/libraries/System.Numerics.Tensors/tests/Helpers.cs @@ -3,10 +3,13 @@ using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; +using System.Numerics.Tensors; +using Xunit; namespace System.Numerics.Tensors.Tests { - internal static class Helpers + public static class Helpers { public static IEnumerable TensorLengthsIncluding0 => Enumerable.Range(0, 257); @@ -20,7 +23,7 @@ internal static class Helpers public const float DefaultHalfTolerance = 3.90625e-03f; public const double DefaultToleranceForEstimates = 1.171875e-02; -#if NETCOREAPP +#if NET private static class DefaultTolerance where T : unmanaged, INumber { public static readonly T Value = DetermineTolerance(DefaultDoubleTolerance, DefaultFloatTolerance, Half.CreateTruncating(DefaultHalfTolerance)) ?? T.CreateTruncating(0); @@ -28,6 +31,11 @@ private static class DefaultTolerance where T : unmanaged, INumber public static bool IsEqualWithTolerance(T expected, T actual, T? tolerance = null) where T : unmanaged, INumber { + if (T.IsNaN(expected) != T.IsNaN(actual)) + { + return false; + } + tolerance = tolerance ?? DefaultTolerance.Value; T diff = T.Abs(expected - actual); return !(diff > tolerance && diff > T.Max(T.Abs(expected), T.Abs(actual)) * tolerance); @@ -35,6 +43,11 @@ public static bool IsEqualWithTolerance(T expected, T actual, T? tolerance = #else public static bool IsEqualWithTolerance(float expected, float actual, float? tolerance = null) { + if (float.IsNaN(expected) != float.IsNaN(actual)) + { + return false; + } + tolerance ??= DefaultFloatTolerance; float diff = MathF.Abs(expected - actual); return !(diff > tolerance && diff > MathF.Max(MathF.Abs(expected), MathF.Abs(actual)) * tolerance); @@ -44,7 +57,7 @@ public static bool IsEqualWithTolerance(float expected, float actual, float? tol public static T? DetermineTolerance( double? doubleTolerance = null, float? floatTolerance = null -#if NETCOREAPP +#if NET , Half? halfTolerance = null #endif ) where T : struct @@ -57,14 +70,52 @@ public static bool IsEqualWithTolerance(float expected, float actual, float? tol { return (T?)(object)floatTolerance; } -#if NETCOREAPP +#if NET else if (typeof(T) == typeof(Half) && halfTolerance != null) { return (T?)(object)halfTolerance; } + else if (typeof(T) == typeof(NFloat)) + { + if (IntPtr.Size == 8 && doubleTolerance != null) + { + return (T?)(object)(NFloat)doubleTolerance; + } + else if (IntPtr.Size == 4 && floatTolerance != null) + { + return (T?)(object)(NFloat)doubleTolerance; + } + } #endif - return null; } + +#if NETCOREAPP + public delegate void AssertThrowsAction(TensorSpan span); + + // Cannot use standard Assert.Throws() when testing Span - Span and closures don't get along. + public static void AssertThrows(TensorSpan span, AssertThrowsAction action) where E : Exception + { + try + { + action(span); + Assert.Fail($"Expected exception: {typeof(E)}"); + } + catch (Exception ex) + { + Assert.True(ex is E, $"Wrong exception thrown. Expected: {typeof(E)} Actual: {ex.GetType()}"); + } + } + + public static void AdjustIndices(int curIndex, nint addend, ref nint[] curIndices, ReadOnlySpan lengths) + { + if (addend == 0 || curIndex < 0) + return; + curIndices[curIndex] += addend; + AdjustIndices(curIndex - 1, curIndices[curIndex] / lengths[curIndex], ref curIndices, lengths); + curIndices[curIndex] = curIndices[curIndex] % lengths[curIndex]; + } + +#endif } } diff --git a/src/libraries/System.Numerics.Tensors/tests/NIndexTests.cs b/src/libraries/System.Numerics.Tensors/tests/NIndexTests.cs new file mode 100644 index 000000000000..193e6b33a1d5 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/tests/NIndexTests.cs @@ -0,0 +1,137 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Xunit; + +namespace System.Buffers.Tests +{ + public static class NativeIndexTests + { + [Fact] + public static void CreationTest() + { + NIndex index = new NIndex(1, fromEnd: false); + Assert.Equal(1, index.Value); + Assert.False(index.IsFromEnd); + + index = new NIndex(11, fromEnd: true); + Assert.Equal(11, index.Value); + Assert.True(index.IsFromEnd); + + index = NIndex.Start; + Assert.Equal(0, index.Value); + Assert.False(index.IsFromEnd); + + index = NIndex.End; + Assert.Equal(0, index.Value); + Assert.True(index.IsFromEnd); + + index = NIndex.FromStart(3); + Assert.Equal(3, index.Value); + Assert.False(index.IsFromEnd); + + index = NIndex.FromEnd(10); + Assert.Equal(10, index.Value); + Assert.True(index.IsFromEnd); + + // Make sure can implicitly convert form Index + index = Index.FromEnd(10); + Assert.Equal(10, index.Value); + Assert.True(index.IsFromEnd); + + AssertExtensions.Throws("value", () => new NIndex(-1, fromEnd: false)); + AssertExtensions.Throws("value", () => NIndex.FromStart(-3)); + AssertExtensions.Throws("value", () => NIndex.FromEnd(-1)); + } + + [Fact] + public static void GetOffsetTest() + { + NIndex index = NIndex.FromStart(3); + Assert.Equal(3, index.GetOffset(3)); + Assert.Equal(3, index.GetOffset(10)); + Assert.Equal(3, index.GetOffset(20)); + + // we don't validate the length in the GetOffset so passing short length will just return the regular calculation according to the length value. + Assert.Equal(3, index.GetOffset(2)); + + index = NIndex.FromEnd(3); + Assert.Equal(0, index.GetOffset(3)); + Assert.Equal(7, index.GetOffset(10)); + Assert.Equal(17, index.GetOffset(20)); + + // we don't validate the length in the GetOffset so passing short length will just return the regular calculation according to the length value. + Assert.Equal(-1, index.GetOffset(2)); + } + + [Fact] + public static void ImplicitCastTest() + { + NIndex index = 10; + Assert.Equal(10, index.Value); + Assert.False(index.IsFromEnd); + + AssertExtensions.Throws("value", () => index = -10); + } + + [Fact] + public static void EqualityTest() + { + NIndex index1 = 10; + NIndex index2 = 10; + Assert.True(index1.Equals(index2)); + Assert.True(index1.Equals((object)index2)); + + index2 = new NIndex(10, fromEnd: true); + Assert.False(index1.Equals(index2)); + Assert.False(index1.Equals((object)index2)); + + index2 = new NIndex(9, fromEnd: false); + Assert.False(index1.Equals(index2)); + Assert.False(index1.Equals((object)index2)); + } + + [Fact] + public static void HashCodeTest() + { + NIndex index1 = 10; + NIndex index2 = 10; + Assert.Equal(index1.GetHashCode(), index2.GetHashCode()); + + index2 = new NIndex(101, fromEnd: true); + Assert.NotEqual(index1.GetHashCode(), index2.GetHashCode()); + + index2 = new NIndex(99999, fromEnd: false); + Assert.NotEqual(index1.GetHashCode(), index2.GetHashCode()); + } + + [Fact] + public static void ToStringTest() + { + NIndex index1 = 100; + Assert.Equal(100.ToString(), index1.ToString()); + + index1 = new NIndex(50, fromEnd: true); + Assert.Equal("^" + 50.ToString(), index1.ToString()); + } + + [Fact] + public static void CollectionTest() + { + int[] array = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + List list = new List(array); + + for (int i = 0; i < list.Count; i++) + { + Assert.Equal(i, list[(int)NIndex.FromStart(i).Value]); + Assert.Equal(list.Count - i - 1, list[^(i + 1)]); + + Assert.Equal(i, array[NIndex.FromStart(i).Value]); + Assert.Equal(list.Count - i - 1, array[^(i + 1)]); + + Assert.Equal(array.AsSpan(i, array.Length - i).ToArray(), array[i..]); + } + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/tests/NRangeTests.cs b/src/libraries/System.Numerics.Tensors/tests/NRangeTests.cs new file mode 100644 index 000000000000..eb5d7ba88ae4 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/tests/NRangeTests.cs @@ -0,0 +1,181 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace System.Buffers.Tests +{ + public static class NativeRangeTests + { + [Fact] + public static void CreationTest() + { + NRange NativeRange = new NRange(new NIndex(10, fromEnd: false), new NIndex(2, fromEnd: true)); + Assert.Equal(10, NativeRange.Start.Value); + Assert.False(NativeRange.Start.IsFromEnd); + Assert.Equal(2, NativeRange.End.Value); + Assert.True(NativeRange.End.IsFromEnd); + + NativeRange = NRange.StartAt(new NIndex(7, fromEnd: false)); + Assert.Equal(7, NativeRange.Start.Value); + Assert.False(NativeRange.Start.IsFromEnd); + Assert.Equal(0, NativeRange.End.Value); + Assert.True(NativeRange.End.IsFromEnd); + + NativeRange = NRange.EndAt(new NIndex(3, fromEnd: true)); + Assert.Equal(0, NativeRange.Start.Value); + Assert.False(NativeRange.Start.IsFromEnd); + Assert.Equal(3, NativeRange.End.Value); + Assert.True(NativeRange.End.IsFromEnd); + + NativeRange = NRange.All; + Assert.Equal(0, NativeRange.Start.Value); + Assert.False(NativeRange.Start.IsFromEnd); + Assert.Equal(0, NativeRange.End.Value); + Assert.True(NativeRange.End.IsFromEnd); + + // Make sure can implicitly convert from Range/Index + NativeRange = new Range(new Index(10, fromEnd: false), new Index(2, fromEnd: true)); + Assert.Equal(10, NativeRange.Start.Value); + Assert.False(NativeRange.Start.IsFromEnd); + Assert.Equal(2, NativeRange.End.Value); + Assert.True(NativeRange.End.IsFromEnd); + + NativeRange = new NRange(new Index(10, fromEnd: false), new Index(2, fromEnd: true)); + Assert.Equal(10, NativeRange.Start.Value); + Assert.False(NativeRange.Start.IsFromEnd); + Assert.Equal(2, NativeRange.End.Value); + Assert.True(NativeRange.End.IsFromEnd); + } + + [Fact] + public static void GetOffsetAndLengthTest() + { + NRange NativeRange = NRange.StartAt(new NIndex(5)); + (nint offset, nint length) = NativeRange.GetOffsetAndLength(20); + Assert.Equal(5, offset); + Assert.Equal(15, length); + + (offset, length) = NativeRange.GetOffsetAndLength(5); + Assert.Equal(5, offset); + Assert.Equal(0, length); + + // we don't validate the length in the GetOffsetAndLength so passing negative length will just return the regular calculation according to the length value. + (offset, length) = NativeRange.GetOffsetAndLength(-10); + Assert.Equal(5, offset); + Assert.Equal(-15, length); + + Assert.Throws(() => NativeRange.GetOffsetAndLength(4)); + + NativeRange = NRange.EndAt(new NIndex(4)); + (offset, length) = NativeRange.GetOffsetAndLength(20); + Assert.Equal(0, offset); + Assert.Equal(4, length); + Assert.Throws(() => NativeRange.GetOffsetAndLength(1)); + } + + [Fact] + public static void EqualityTest() + { + NRange NativeRange1 = new NRange(new NIndex(10, fromEnd: false), new NIndex(20, fromEnd: false)); + NRange NativeRange2 = new NRange(new NIndex(10, fromEnd: false), new NIndex(20, fromEnd: false)); + Assert.True(NativeRange1.Equals(NativeRange2)); + Assert.True(NativeRange1.Equals((object)NativeRange2)); + + NativeRange2 = new NRange(new NIndex(10, fromEnd: false), new NIndex(20, fromEnd: true)); + Assert.False(NativeRange1.Equals(NativeRange2)); + Assert.False(NativeRange1.Equals((object)NativeRange2)); + + NativeRange2 = new NRange(new NIndex(10, fromEnd: false), new NIndex(21, fromEnd: false)); + Assert.False(NativeRange1.Equals(NativeRange2)); + Assert.False(NativeRange1.Equals((object)NativeRange2)); + } + + [Fact] + public static void HashCodeTest() + { + NRange NativeRange1 = new NRange(new NIndex(10, fromEnd: false), new NIndex(20, fromEnd: false)); + NRange NativeRange2 = new NRange(new NIndex(10, fromEnd: false), new NIndex(20, fromEnd: false)); + Assert.Equal(NativeRange1.GetHashCode(), NativeRange2.GetHashCode()); + + NativeRange2 = new NRange(new NIndex(101, fromEnd: false), new NIndex(20, fromEnd: true)); + Assert.NotEqual(NativeRange1.GetHashCode(), NativeRange2.GetHashCode()); + + NativeRange2 = new NRange(new NIndex(10, fromEnd: false), new NIndex(21, fromEnd: false)); + Assert.NotEqual(NativeRange1.GetHashCode(), NativeRange2.GetHashCode()); + } + + [Fact] + public static void ToStringTest() + { + NRange NativeRange1 = new NRange(new NIndex(10, fromEnd: false), new NIndex(20, fromEnd: false)); + Assert.Equal(10.ToString() + ".." + 20.ToString(), NativeRange1.ToString()); + + NativeRange1 = new NRange(new NIndex(10, fromEnd: false), new NIndex(20, fromEnd: true)); + Assert.Equal(10.ToString() + "..^" + 20.ToString(), NativeRange1.ToString()); + } + + [Fact] + public static void CustomTypeTest() + { + CustomNativeRangeTester crt = new CustomNativeRangeTester(new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); + for (int i = 0; i < crt.Length; i++) + { + Assert.Equal(crt[i], crt[(int)NIndex.FromStart(i).Value]); + Assert.Equal(crt[crt.Length - i - 1], crt[^(i + 1)]); + + Assert.True(crt.Slice(i, crt.Length - i).Equals(crt[i..^0]), $"NIndex = {i} and {crt.Slice(i, crt.Length - i)} != {crt[i..^0]}"); + } + } + + // CustomNativeRangeTester is a custom class which containing the members FlattenedLength, Slice and int NativeIndexer. + // Having these members allow the C# compiler to support + // this[NIndex] + // this[NRange] + private class CustomNativeRangeTester : IEquatable + { + private int[] _data; + + public CustomNativeRangeTester(int[] data) => _data = data; + public int Length => _data.Length; + public int this[int NativeIndex] => _data[NativeIndex]; + public CustomNativeRangeTester Slice(int start, int length) => new CustomNativeRangeTester(_data.AsSpan(start, length).ToArray()); + + public int[] Data => _data; + + public bool Equals(CustomNativeRangeTester other) + { + if (_data.Length == other.Data.Length) + { + for (int i = 0; i < _data.Length; i++) + { + if (_data[i] != other.Data[i]) + { + return false; + } + } + return true; + } + + return false; + } + + public override string ToString() + { + if (Length == 0) + { + return "[]"; + } + + string s = "[" + _data[0]; + + for (int i = 1; i < Length; i++) + { + s = s + ", " + _data[i]; + } + + return s + "]"; + } + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/tests/Net8Tests/System.Numerics.Tensors.Net8.Tests.csproj b/src/libraries/System.Numerics.Tensors/tests/Net8Tests/System.Numerics.Tensors.Net8.Tests.csproj index eb08d0e5974a..3b8f867b355c 100644 --- a/src/libraries/System.Numerics.Tensors/tests/Net8Tests/System.Numerics.Tensors.Net8.Tests.csproj +++ b/src/libraries/System.Numerics.Tensors/tests/Net8Tests/System.Numerics.Tensors.Net8.Tests.csproj @@ -10,6 +10,7 @@ $(NetCoreAppCurrent) true + $(DefineConstants);SNT_NET8_TESTS diff --git a/src/libraries/System.Numerics.Tensors/tests/ReadOnlyTensorSpanTests.cs b/src/libraries/System.Numerics.Tensors/tests/ReadOnlyTensorSpanTests.cs new file mode 100644 index 000000000000..918f011c3c16 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/tests/ReadOnlyTensorSpanTests.cs @@ -0,0 +1,327 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace System.Numerics.Tensors.Tests +{ + public class ReadOnlyTensorSpanTests + { + [Fact] + public static void IntArrayAsReadOnlyTensorSpan() + { + int[] a = { 91, 92, -93, 94 }; + int[] results = new int[4]; + ReadOnlyTensorSpan spanInt = a.AsTensorSpan(4); + Assert.Equal(1, spanInt.Rank); + + Assert.Equal(1, spanInt.Lengths.Length); + Assert.Equal(4, spanInt.Lengths[0]); + Assert.Equal(1, spanInt.Strides.Length); + Assert.Equal(1, spanInt.Strides[0]); + Assert.Equal(91, spanInt[0]); + Assert.Equal(92, spanInt[1]); + Assert.Equal(-93, spanInt[2]); + Assert.Equal(94, spanInt[3]); + spanInt.FlattenTo(results); + Assert.Equal(a, results); + + a[0] = 91; + a[1] = 92; + a[2] = -93; + a[3] = 94; + spanInt = a.AsTensorSpan(2, 2); + spanInt.FlattenTo(results); + Assert.Equal(a, results); + Assert.Equal(2, spanInt.Rank); + Assert.Equal(2, spanInt.Lengths.Length); + Assert.Equal(2, spanInt.Lengths[0]); + Assert.Equal(2, spanInt.Lengths[1]); + Assert.Equal(2, spanInt.Strides.Length); + Assert.Equal(2, spanInt.Strides[0]); + Assert.Equal(1, spanInt.Strides[1]); + Assert.Equal(91, spanInt[0, 0]); + Assert.Equal(92, spanInt[0, 1]); + Assert.Equal(-93, spanInt[1, 0]); + Assert.Equal(94, spanInt[1, 1]); + } + + [Fact] + public static void ReadOnlyTensorSpanCopyTest() + { + int[] leftData = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + int[] rightData = new int[9]; + ReadOnlyTensorSpan leftSpan = leftData.AsTensorSpan(3, 3); + TensorSpan rightSpan = rightData.AsTensorSpan(3, 3); + leftSpan.CopyTo(rightSpan); + var leftEnum = leftSpan.GetEnumerator(); + var rightEnum = rightSpan.GetEnumerator(); + while (leftEnum.MoveNext() && rightEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, rightEnum.Current); + } + + //Make sure its a copy + rightSpan[0, 0] = 100; + Assert.NotEqual(leftSpan[0, 0], rightSpan[0, 0]); + + leftData = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + rightData = new int[15]; + leftSpan = leftData.AsTensorSpan(9); + rightSpan = rightData.AsTensorSpan(15); + leftSpan.CopyTo(rightSpan); + leftEnum = leftSpan.GetEnumerator(); + rightEnum = rightSpan.GetEnumerator(); + // Make sure the first 9 spots are equal after copy + while (leftEnum.MoveNext() && rightEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, rightEnum.Current); + } + // The rest of the slots shouldn't have been touched. + while (rightEnum.MoveNext()) + { + Assert.Equal(0, rightEnum.Current); + } + + //Make sure its a copy + rightSpan[0] = 100; + Assert.NotEqual(leftSpan[0], rightSpan[0]); + + leftData = [.. Enumerable.Range(0, 27)]; + rightData = [.. Enumerable.Range(0, 27)]; + leftSpan = leftData.AsTensorSpan(3, 3, 3); + rightSpan = rightData.AsTensorSpan(3, 3, 3); + leftSpan.CopyTo(rightSpan); + + while (leftEnum.MoveNext() && rightEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, rightEnum.Current); + } + + Assert.Throws(() => + { + var l = leftData.AsTensorSpan(3, 3, 3); + var r = new TensorSpan(); + l.CopyTo(r); + }); + } + + [Fact] + public static void ReadOnlyTensorSpanTryCopyTest() + { + int[] leftData = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + int[] rightData = new int[9]; + ReadOnlyTensorSpan leftSpan = leftData.AsTensorSpan(3, 3); + TensorSpan rightSpan = rightData.AsTensorSpan(3, 3); + var success = leftSpan.TryCopyTo(rightSpan); + Assert.True(success); + var leftEnum = leftSpan.GetEnumerator(); + var rightEnum = rightSpan.GetEnumerator(); + while (leftEnum.MoveNext() && rightEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, rightEnum.Current); + } + + //Make sure its a copy + rightSpan[0, 0] = 100; + Assert.NotEqual(leftSpan[0, 0], rightSpan[0, 0]); + + leftData = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + rightData = new int[15]; + leftSpan = leftData.AsTensorSpan(9); + rightSpan = rightData.AsTensorSpan(15); + success = leftSpan.TryCopyTo(rightSpan); + leftEnum = leftSpan.GetEnumerator(); + rightEnum = rightSpan.GetEnumerator(); + Assert.True(success); + // Make sure the first 9 spots are equal after copy + while (leftEnum.MoveNext() && rightEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, rightEnum.Current); + } + // The rest of the slots shouldn't have been touched. + while (rightEnum.MoveNext()) + { + Assert.Equal(0, rightEnum.Current); + } + + //Make sure its a copy + rightSpan[0] = 100; + Assert.NotEqual(leftSpan[0], rightSpan[0]); + + leftData = [.. Enumerable.Range(0, 27)]; + rightData = [.. Enumerable.Range(0, 27)]; + leftSpan = leftData.AsTensorSpan(3, 3, 3); + rightSpan = rightData.AsTensorSpan(3, 3, 3); + success = leftSpan.TryCopyTo(rightSpan); + Assert.True(success); + + while (leftEnum.MoveNext() && rightEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, rightEnum.Current); + } + + var l = leftData.AsTensorSpan(3, 3, 3); + var r = new TensorSpan(); + success = l.TryCopyTo(r); + Assert.False(success); + } + + [Fact] + public static void ReadOnlyTensorSpanSliceTest() + { + int[] a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + int[] results = new int[9]; + ReadOnlyTensorSpan spanInt = a.AsTensorSpan(3, 3); + + Assert.Throws(() => a.AsTensorSpan(2, 3).Slice(0..1)); + Assert.Throws(() => a.AsTensorSpan(2, 3).Slice(1..2)); + Assert.Throws(() => a.AsTensorSpan(2, 3).Slice(0..1, 5..6)); + + var sp = spanInt.Slice(1..3, 1..3); + Assert.Equal(5, sp[0, 0]); + Assert.Equal(6, sp[0, 1]); + Assert.Equal(8, sp[1, 0]); + Assert.Equal(9, sp[1, 1]); + int[] slice = [5, 6, 8, 9]; + results = new int[4]; + sp.FlattenTo(results); + Assert.Equal(slice, results); + var enumerator = sp.GetEnumerator(); + var index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + sp = spanInt.Slice(0..3, 0..3); + Assert.Equal(1, sp[0, 0]); + Assert.Equal(2, sp[0, 1]); + Assert.Equal(3, sp[0, 2]); + Assert.Equal(4, sp[1, 0]); + Assert.Equal(5, sp[1, 1]); + Assert.Equal(6, sp[1, 2]); + Assert.Equal(7, sp[2, 0]); + Assert.Equal(8, sp[2, 1]); + Assert.Equal(9, sp[2, 2]); + results = new int[9]; + sp.FlattenTo(results); + Assert.Equal(a, results); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(a[index++], enumerator.Current); + } + + sp = spanInt.Slice(0..1, 0..1); + Assert.Equal(1, sp[0, 0]); + Assert.Throws(() => a.AsTensorSpan(3, 3).Slice(0..1, 0..1)[0, 1]); + slice = [1]; + results = new int[1]; + sp.FlattenTo(results); + Assert.Equal(slice, results); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + sp = spanInt.Slice(0..2, 0..2); + Assert.Equal(1, sp[0, 0]); + Assert.Equal(2, sp[0, 1]); + Assert.Equal(4, sp[1, 0]); + Assert.Equal(5, sp[1, 1]); + slice = [1, 2, 4, 5]; + results = new int[4]; + sp.FlattenTo(results); + Assert.Equal(slice, results); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + int[] numbers = [.. Enumerable.Range(0, 27)]; + spanInt = numbers.AsTensorSpan(3, 3, 3); + sp = spanInt.Slice(1..2, 1..2, 1..2); + Assert.Equal(13, sp[0, 0, 0]); + slice = [13]; + results = new int[1]; + sp.FlattenTo(results); + Assert.Equal(slice, results); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + sp = spanInt.Slice(1..3, 1..3, 1..3); + Assert.Equal(13, sp[0, 0, 0]); + Assert.Equal(14, sp[0, 0, 1]); + Assert.Equal(16, sp[0, 1, 0]); + Assert.Equal(17, sp[0, 1, 1]); + Assert.Equal(22, sp[1, 0, 0]); + Assert.Equal(23, sp[1, 0, 1]); + Assert.Equal(25, sp[1, 1, 0]); + Assert.Equal(26, sp[1, 1, 1]); + slice = [13, 14, 16, 17, 22, 23, 25, 26]; + results = new int[8]; + sp.FlattenTo(results); + Assert.Equal(slice, results); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + numbers = [.. Enumerable.Range(0, 16)]; + spanInt = numbers.AsTensorSpan(2, 2, 2, 2); + sp = spanInt.Slice(1..2, 0..2, 1..2, 0..2); + Assert.Equal(10, sp[0, 0, 0, 0]); + Assert.Equal(11, sp[0, 0, 0, 1]); + Assert.Equal(14, sp[0, 1, 0, 0]); + Assert.Equal(15, sp[0, 1, 0, 1]); + slice = [10, 11, 14, 15]; + results = new int[4]; + sp.FlattenTo(results); + Assert.Equal(slice, results); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + } + + [Fact] + public static void LongArrayAsReadOnlyTensorSpan() + { + long[] b = { 91, -92, 93, 94, -95 }; + ReadOnlyTensorSpan spanLong = b.AsTensorSpan(5); + Assert.Equal(91, spanLong[0]); + Assert.Equal(-92, spanLong[1]); + Assert.Equal(93, spanLong[2]); + Assert.Equal(94, spanLong[3]); + Assert.Equal(-95, spanLong[4]); + } + + [Fact] + public static void NullArrayAsReadOnlyTensorSpan() + { + int[] a = null; + ReadOnlyTensorSpan span = a.AsTensorSpan(); + ReadOnlyTensorSpan d = default; + Assert.True(span == d); + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/tests/System.Numerics.Tensors.Tests.csproj b/src/libraries/System.Numerics.Tensors/tests/System.Numerics.Tensors.Tests.csproj index 4a508197cae5..4b31efa2aaef 100644 --- a/src/libraries/System.Numerics.Tensors/tests/System.Numerics.Tensors.Tests.csproj +++ b/src/libraries/System.Numerics.Tensors/tests/System.Numerics.Tensors.Tests.csproj @@ -17,6 +17,11 @@ + + + + + diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs b/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs index 0cd20f1d647a..2768a03a0704 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorPrimitives.Generic.cs @@ -386,7 +386,12 @@ public static IEnumerable SpanDestinationFunctionsToTest() yield return Create(TensorPrimitives.Reciprocal, f => T.One / f); yield return Create(TensorPrimitives.ReciprocalEstimate, T.ReciprocalEstimate, T.CreateTruncating(Helpers.DefaultToleranceForEstimates)); yield return Create(TensorPrimitives.ReciprocalSqrt, f => T.One / T.Sqrt(f)); + +#if !SNT_NET8_TESTS + // Avoid running with the net8 tests due to: https://github.com/dotnet/runtime/issues/101846 yield return Create(TensorPrimitives.ReciprocalSqrtEstimate, T.ReciprocalSqrtEstimate, T.CreateTruncating(Helpers.DefaultToleranceForEstimates)); +#endif + yield return Create(TensorPrimitives.Round, T.Round); yield return Create(TensorPrimitives.Sin, T.Sin, trigTolerance); yield return Create(TensorPrimitives.Sinh, T.Sinh, Helpers.DetermineTolerance(doubleTolerance: 1e-14)); @@ -480,8 +485,11 @@ public void SpanDestinationFunctions_ValueRange(SpanDestinationDelegate tensorPr #pragma warning disable xUnit1026 // Theory methods should use all of their parameters [Theory] [MemberData(nameof(SpanDestinationFunctionsToTest))] - public void SpanDestinationFunctions_ThrowsForTooShortDestination(SpanDestinationDelegate tensorPrimitivesMethod, Func _, T? __ = null) + public void SpanDestinationFunctions_ThrowsForTooShortDestination(SpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -493,8 +501,11 @@ public void SpanDestinationFunctions_ThrowsForTooShortDestination(SpanDestinatio [Theory] [MemberData(nameof(SpanDestinationFunctionsToTest))] - public void SpanDestinationFunctions_ThrowsForOverlapppingInputsWithOutputs(SpanDestinationDelegate tensorPrimitivesMethod, Func _, T? __ = null) + public void SpanDestinationFunctions_ThrowsForOverlapppingInputsWithOutputs(SpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + T[] array = new T[10]; AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(0, 2))); AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(2, 2))); @@ -511,6 +522,8 @@ public static IEnumerable SpanSpanDestinationFunctionsToTest() yield return Create(TensorPrimitives.Hypot, T.Hypot); yield return Create(TensorPrimitives.Ieee754Remainder, T.Ieee754Remainder); yield return Create(TensorPrimitives.Log, T.Log); + yield return Create(TensorPrimitives.MaxNumber, T.MaxNumber); + yield return Create(TensorPrimitives.MinNumber, T.MinNumber); yield return Create(TensorPrimitives.Pow, T.Pow, Helpers.DetermineTolerance(doubleTolerance: 1e-13, floatTolerance: 1e-5f)); static object[] Create(SpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) @@ -644,8 +657,10 @@ public static IEnumerable SpanScalarDestinationFunctionsToTest() yield return Create(TensorPrimitives.Log, T.Log); yield return Create(TensorPrimitives.Max, T.Max); yield return Create(TensorPrimitives.MaxMagnitude, T.MaxMagnitude); + yield return Create(TensorPrimitives.MaxNumber, T.MaxNumber); yield return Create(TensorPrimitives.Min, T.Min); yield return Create(TensorPrimitives.MinMagnitude, T.MinMagnitude); + yield return Create(TensorPrimitives.MinNumber, T.MinNumber); static object[] Create(SpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) => new object[] { tensorPrimitivesMethod, expectedMethod, tolerance }; @@ -942,15 +957,15 @@ public static IEnumerable SpanSpanSpanDestinationFunctionsToTest() { yield return Create(TensorPrimitives.FusedMultiplyAdd, T.FusedMultiplyAdd); yield return Create(TensorPrimitives.Lerp, T.Lerp); - yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available + yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd, T.CreateTruncating(Helpers.DefaultToleranceForEstimates)); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available - static object[] Create(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) - => new object[] { tensorPrimitivesMethod, expectedMethod }; + static object[] Create(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) + => new object[] { tensorPrimitivesMethod, expectedMethod, tolerance }; } [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_AllLengths(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanSpanDestination_AllLengths(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -962,14 +977,14 @@ public void SpanSpanSpanDestination_AllLengths(SpanSpanSpanDestinationDelegate t tensorPrimitivesMethod(x, y, z, destination); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_InPlace(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanSpanDestination_InPlace(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -980,14 +995,14 @@ public void SpanSpanSpanDestination_InPlace(SpanSpanSpanDestinationDelegate tens for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(xOrig[i], xOrig[i], xOrig[i]), x[i]); + AssertEqualTolerance(expectedMethod(xOrig[i], xOrig[i], xOrig[i]), x[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengths, tensorLength => { @@ -1001,7 +1016,7 @@ public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegat tensorPrimitivesMethod(x.Span, y.Span, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i], tolerance); } }, x); @@ -1010,7 +1025,7 @@ public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegat tensorPrimitivesMethod(x.Span, y.Span, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i], tolerance); } }, y); @@ -1019,7 +1034,7 @@ public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegat tensorPrimitivesMethod(x.Span, y.Span, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z[i]), destination[i], tolerance); } }, z); }); @@ -1027,8 +1042,11 @@ public void SpanSpanSpanDestination_SpecialValues(SpanSpanSpanDestinationDelegat [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_ThrowsForMismatchedLengths(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanSpanDestination_ThrowsForMismatchedLengths(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -1047,8 +1065,11 @@ public void SpanSpanSpanDestination_ThrowsForMismatchedLengths(SpanSpanSpanDesti [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_ThrowsForTooShortDestination(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanSpanDestination_ThrowsForTooShortDestination(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -1062,8 +1083,11 @@ public void SpanSpanSpanDestination_ThrowsForTooShortDestination(SpanSpanSpanDes [Theory] [MemberData(nameof(SpanSpanSpanDestinationFunctionsToTest))] - public void SpanSpanSpanDestination_ThrowsForOverlapppingInputsWithOutputs(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanSpanDestination_ThrowsForOverlapppingInputsWithOutputs(SpanSpanSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + T[] array = new T[10]; AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(5, 2), array.AsSpan(7, 2), array.AsSpan(0, 2))); AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(5, 2), array.AsSpan(7, 2), array.AsSpan(2, 2))); @@ -1078,15 +1102,15 @@ public static IEnumerable SpanSpanScalarDestinationFunctionsToTest() { yield return Create(TensorPrimitives.FusedMultiplyAdd, T.FusedMultiplyAdd); yield return Create(TensorPrimitives.Lerp, T.Lerp); - yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available + yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd, T.CreateTruncating(Helpers.DefaultToleranceForEstimates)); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available - static object[] Create(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) - => new object[] { tensorPrimitivesMethod, expectedMethod }; + static object[] Create(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) + => new object[] { tensorPrimitivesMethod, expectedMethod, tolerance }; } [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_AllLengths(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanScalarDestination_AllLengths(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -1099,14 +1123,14 @@ public void SpanSpanScalarDestination_AllLengths(SpanSpanScalarDestinationDelega for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_InPlace(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanScalarDestination_InPlace(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -1118,14 +1142,14 @@ public void SpanSpanScalarDestination_InPlace(SpanSpanScalarDestinationDelegate for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(xOrig[i], xOrig[i], z), x[i]); + AssertEqualTolerance(expectedMethod(xOrig[i], xOrig[i], z), x[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengths, tensorLength => { @@ -1139,7 +1163,7 @@ public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDel tensorPrimitivesMethod(x.Span, y.Span, z, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i], tolerance); } }, x); @@ -1148,7 +1172,7 @@ public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDel tensorPrimitivesMethod(x.Span, y.Span, z, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y[i], z), destination[i], tolerance); } }, y); }); @@ -1156,8 +1180,11 @@ public void SpanSpanScalarDestination_SpecialValues(SpanSpanScalarDestinationDel [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_ThrowsForTooShortDestination(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanScalarDestination_ThrowsForTooShortDestination(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -1171,8 +1198,11 @@ public void SpanSpanScalarDestination_ThrowsForTooShortDestination(SpanSpanScala [Theory] [MemberData(nameof(SpanSpanScalarDestinationFunctionsToTest))] - public void SpanSpanScalarDestination_ThrowsForOverlapppingInputsWithOutputs(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanSpanScalarDestination_ThrowsForOverlapppingInputsWithOutputs(SpanSpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + T[] array = new T[10]; AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(4, 2), default, array.AsSpan(0, 2))); AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), array.AsSpan(4, 2), default, array.AsSpan(2, 2))); @@ -1186,15 +1216,15 @@ public static IEnumerable SpanScalarSpanDestinationFunctionsToTest() { yield return Create(TensorPrimitives.FusedMultiplyAdd, T.FusedMultiplyAdd); yield return Create(TensorPrimitives.Lerp, T.Lerp); - yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available + yield return Create(TensorPrimitives.MultiplyAddEstimate, T.FusedMultiplyAdd, T.CreateTruncating(Helpers.DefaultToleranceForEstimates)); // TODO: Change T.FusedMultiplyAdd to T.MultiplyAddEstimate when available - static object[] Create(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + static object[] Create(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) => new object[] { tensorPrimitivesMethod, expectedMethod }; } [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_AllLengths(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanScalarSpanDestination_AllLengths(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -1207,14 +1237,14 @@ public void SpanScalarSpanDestination_AllLengths(SpanScalarSpanDestinationDelega for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_InPlace(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanScalarSpanDestination_InPlace(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengthsIncluding0, tensorLength => { @@ -1226,14 +1256,14 @@ public void SpanScalarSpanDestination_InPlace(SpanScalarSpanDestinationDelegate for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(xOrig[i], y, xOrig[i]), x[i]); + AssertEqualTolerance(expectedMethod(xOrig[i], y, xOrig[i]), x[i], tolerance); } }); } [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) + public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { Assert.All(Helpers.TensorLengths, tensorLength => { @@ -1247,7 +1277,7 @@ public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDel tensorPrimitivesMethod(x.Span, y, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i], tolerance); } }, x); @@ -1256,7 +1286,7 @@ public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDel tensorPrimitivesMethod(x.Span, y, z.Span, destination.Span); for (int i = 0; i < tensorLength; i++) { - AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i]); + AssertEqualTolerance(expectedMethod(x[i], y, z[i]), destination[i], tolerance); } }, z); }); @@ -1264,8 +1294,11 @@ public void SpanScalarSpanDestination_SpecialValues(SpanScalarSpanDestinationDel [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_ThrowsForTooShortDestination(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanScalarSpanDestination_ThrowsForTooShortDestination(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + Assert.All(Helpers.TensorLengths, tensorLength => { using BoundedMemory x = CreateAndFillTensor(tensorLength); @@ -1279,8 +1312,11 @@ public void SpanScalarSpanDestination_ThrowsForTooShortDestination(SpanScalarSpa [Theory] [MemberData(nameof(SpanScalarSpanDestinationFunctionsToTest))] - public void SpanScalarSpanDestination_ThrowsForOverlapppingInputsWithOutputs(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func _) + public void SpanScalarSpanDestination_ThrowsForOverlapppingInputsWithOutputs(SpanScalarSpanDestinationDelegate tensorPrimitivesMethod, Func expectedMethod, T? tolerance = null) { + _ = expectedMethod; + _ = tolerance; + T[] array = new T[10]; AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), default, array.AsSpan(4, 2), array.AsSpan(0, 2))); AssertExtensions.Throws("destination", () => tensorPrimitivesMethod(array.AsSpan(1, 2), default, array.AsSpan(4, 2), array.AsSpan(2, 2))); @@ -1806,8 +1842,10 @@ public static IEnumerable SpanScalarDestinationFunctionsToTest() yield return Create(TensorPrimitives.BitwiseOr, (x, y) => x | y); yield return Create(TensorPrimitives.Max, T.Max); yield return Create(TensorPrimitives.MaxMagnitude, T.MaxMagnitude); + yield return Create(TensorPrimitives.MaxNumber, T.MaxNumber); yield return Create(TensorPrimitives.Min, T.Min); yield return Create(TensorPrimitives.MinMagnitude, T.MinMagnitude); + yield return Create(TensorPrimitives.MinNumber, T.MinNumber); yield return Create(TensorPrimitives.Xor, (x, y) => x ^ y); static object[] Create(SpanScalarDestinationDelegate tensorPrimitivesMethod, Func expectedMethod) diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs b/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs new file mode 100644 index 000000000000..911dc6805588 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs @@ -0,0 +1,522 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace System.Numerics.Tensors.Tests +{ + public class TensorSpanTests + { + [Fact] + public static void ConstructorTests() + { + int[] a = [1, 2, 3]; + TensorSpan span = new TensorSpan(a, 0, [3, 3], [0, 1]); + + + + } + + [Fact] + public static void IntArrayAsTensorSpan() + { + int[] a = { 91, 92, -93, 94 }; + int[] results = new int[4]; + TensorSpan spanInt = a.AsTensorSpan(4); + Assert.Equal(1, spanInt.Rank); + + Assert.Equal(1, spanInt.Lengths.Length); + Assert.Equal(4, spanInt.Lengths[0]); + Assert.Equal(1, spanInt.Strides.Length); + Assert.Equal(1, spanInt.Strides[0]); + Assert.Equal(91, spanInt[0]); + Assert.Equal(92, spanInt[1]); + Assert.Equal(-93, spanInt[2]); + Assert.Equal(94, spanInt[3]); + spanInt.FlattenTo(results); + Assert.Equal(a, results); + spanInt[0] = 100; + spanInt[1] = 101; + spanInt[2] = -102; + spanInt[3] = 103; + + Assert.Equal(100, spanInt[0]); + Assert.Equal(101, spanInt[1]); + Assert.Equal(-102, spanInt[2]); + Assert.Equal(103, spanInt[3]); + + a[0] = 91; + a[1] = 92; + a[2] = -93; + a[3] = 94; + spanInt = a.AsTensorSpan(2, 2); + spanInt.FlattenTo(results); + Assert.Equal(a, results); + Assert.Equal(2, spanInt.Rank); + Assert.Equal(2, spanInt.Lengths.Length); + Assert.Equal(2, spanInt.Lengths[0]); + Assert.Equal(2, spanInt.Lengths[1]); + Assert.Equal(2, spanInt.Strides.Length); + Assert.Equal(2, spanInt.Strides[0]); + Assert.Equal(1, spanInt.Strides[1]); + Assert.Equal(91, spanInt[0, 0]); + Assert.Equal(92, spanInt[0, 1]); + Assert.Equal(-93, spanInt[1, 0]); + Assert.Equal(94, spanInt[1, 1]); + + spanInt[0, 0] = 100; + spanInt[0, 1] = 101; + spanInt[1, 0] = -102; + spanInt[1, 1] = 103; + + Assert.Equal(100, spanInt[0, 0]); + Assert.Equal(101, spanInt[0, 1]); + Assert.Equal(-102, spanInt[1, 0]); + Assert.Equal(103, spanInt[1, 1]); + } + + [Fact] + public static void TensorSpanFillTest() + { + int[] a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + TensorSpan spanInt = a.AsTensorSpan(3, 3); + spanInt.Fill(-1); + var enumerator = spanInt.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(-1, enumerator.Current); + } + + spanInt.Fill(int.MinValue); + enumerator = spanInt.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(int.MinValue, enumerator.Current); + } + + spanInt.Fill(int.MaxValue); + enumerator = spanInt.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(int.MaxValue, enumerator.Current); + } + + a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + spanInt = a.AsTensorSpan(9); + spanInt.Fill(-1); + enumerator = spanInt.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(-1, enumerator.Current); + } + + a = [.. Enumerable.Range(0, 27)]; + spanInt = a.AsTensorSpan(3,3,3); + spanInt.Fill(-1); + enumerator = spanInt.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(-1, enumerator.Current); + } + + a = [.. Enumerable.Range(0, 12)]; + spanInt = a.AsTensorSpan(3, 2, 2); + spanInt.Fill(-1); + enumerator = spanInt.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(-1, enumerator.Current); + } + + a = [.. Enumerable.Range(0, 16)]; + spanInt = a.AsTensorSpan(2,2,2,2); + spanInt.Fill(-1); + enumerator = spanInt.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(-1, enumerator.Current); + } + + a = [.. Enumerable.Range(0, 24)]; + spanInt = a.AsTensorSpan(3, 2, 2, 2); + spanInt.Fill(-1); + enumerator = spanInt.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(-1, enumerator.Current); + } + } + + [Fact] + public static void TensorSpanClearTest() + { + int[] a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + TensorSpan spanInt = a.AsTensorSpan(3, 3); + + var slice = spanInt.Slice(0..2, 0..2); + slice.Clear(); + Assert.Equal(0, slice[0, 0]); + Assert.Equal(0, slice[0, 1]); + Assert.Equal(0, slice[1, 0]); + Assert.Equal(0, slice[1, 1]); + //First values of original span should be cleared. + Assert.Equal(0, spanInt[0, 0]); + Assert.Equal(0, spanInt[0, 1]); + Assert.Equal(0, spanInt[1, 0]); + Assert.Equal(0, spanInt[1, 1]); + //Make sure the rest of the values from the original span didn't get cleared. + Assert.Equal(3, spanInt[0, 2]); + Assert.Equal(6, spanInt[1, 2]); + Assert.Equal(7, spanInt[2, 0]); + Assert.Equal(8, spanInt[2, 1]); + Assert.Equal(9, spanInt[2, 2]); + + + spanInt.Clear(); + var enumerator = spanInt.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(0, enumerator.Current); + } + + a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + spanInt = a.AsTensorSpan(9); + slice = spanInt.Slice(0..1); + slice.Clear(); + Assert.Equal(0, slice[0]); + //First value of original span should be cleared. + Assert.Equal(0, spanInt[0]); + //Make sure the rest of the values from the original span didn't get cleared. + Assert.Equal(2, spanInt[1]); + Assert.Equal(3, spanInt[2]); + Assert.Equal(4, spanInt[3]); + Assert.Equal(5, spanInt[4]); + Assert.Equal(6, spanInt[5]); + Assert.Equal(7, spanInt[6]); + Assert.Equal(8, spanInt[7]); + Assert.Equal(9, spanInt[8]); + + + spanInt.Clear(); + enumerator = spanInt.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(0, enumerator.Current); + } + + a = [.. Enumerable.Range(0, 27)]; + spanInt = a.AsTensorSpan(3, 3, 3); + spanInt.Clear(); + enumerator = spanInt.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(0, enumerator.Current); + } + + a = [.. Enumerable.Range(0, 12)]; + spanInt = a.AsTensorSpan(3, 2, 2); + spanInt.Clear(); + enumerator = spanInt.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(0, enumerator.Current); + } + + a = [.. Enumerable.Range(0, 16)]; + spanInt = a.AsTensorSpan(2, 2, 2, 2); + spanInt.Clear(); + enumerator = spanInt.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(0, enumerator.Current); + } + + a = [.. Enumerable.Range(0, 24)]; + spanInt = a.AsTensorSpan(3, 2, 2, 2); + spanInt.Clear(); + enumerator = spanInt.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(0, enumerator.Current); + } + } + + [Fact] + public static void TensorSpanCopyTest() + { + int[] leftData = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + int[] rightData = new int[9]; + TensorSpan leftSpan = leftData.AsTensorSpan(3, 3); + TensorSpan rightSpan = rightData.AsTensorSpan(3, 3); + leftSpan.CopyTo(rightSpan); + var leftEnum = leftSpan.GetEnumerator(); + var rightEnum = rightSpan.GetEnumerator(); + while(leftEnum.MoveNext() && rightEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, rightEnum.Current); + } + + //Make sure its a copy + leftSpan[0, 0] = 100; + Assert.NotEqual(leftSpan[0, 0], rightSpan[0, 0]); + + leftData = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + rightData = new int[15]; + leftSpan = leftData.AsTensorSpan(9); + rightSpan = rightData.AsTensorSpan(15); + leftSpan.CopyTo(rightSpan); + leftEnum = leftSpan.GetEnumerator(); + rightEnum = rightSpan.GetEnumerator(); + // Make sure the first 9 spots are equal after copy + while (leftEnum.MoveNext() && rightEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, rightEnum.Current); + } + // The rest of the slots shouldn't have been touched. + while(rightEnum.MoveNext()) + { + Assert.Equal(0, rightEnum.Current); + } + + //Make sure its a copy + leftSpan[0] = 100; + Assert.NotEqual(leftSpan[0], rightSpan[0]); + + leftData = [.. Enumerable.Range(0, 27)]; + rightData = [.. Enumerable.Range(0, 27)]; + leftSpan = leftData.AsTensorSpan(3, 3, 3); + rightSpan = rightData.AsTensorSpan(3, 3, 3); + leftSpan.CopyTo(rightSpan); + + while (leftEnum.MoveNext() && rightEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, rightEnum.Current); + } + + Assert.Throws(() => + { + var l = leftData.AsTensorSpan(3, 3, 3); + var r = new TensorSpan(); + l.CopyTo(r); + }); + } + + [Fact] + public static void TensorSpanTryCopyTest() + { + int[] leftData = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + int[] rightData = new int[9]; + TensorSpan leftSpan = leftData.AsTensorSpan(3, 3); + TensorSpan rightSpan = rightData.AsTensorSpan(3, 3); + var success = leftSpan.TryCopyTo(rightSpan); + Assert.True(success); + var leftEnum = leftSpan.GetEnumerator(); + var rightEnum = rightSpan.GetEnumerator(); + while (leftEnum.MoveNext() && rightEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, rightEnum.Current); + } + + //Make sure its a copy + leftSpan[0, 0] = 100; + Assert.NotEqual(leftSpan[0, 0], rightSpan[0, 0]); + + leftData = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + rightData = new int[15]; + leftSpan = leftData.AsTensorSpan(9); + rightSpan = rightData.AsTensorSpan(15); + success = leftSpan.TryCopyTo(rightSpan); + leftEnum = leftSpan.GetEnumerator(); + rightEnum = rightSpan.GetEnumerator(); + Assert.True(success); + // Make sure the first 9 spots are equal after copy + while (leftEnum.MoveNext() && rightEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, rightEnum.Current); + } + // The rest of the slots shouldn't have been touched. + while (rightEnum.MoveNext()) + { + Assert.Equal(0, rightEnum.Current); + } + + //Make sure its a copy + leftSpan[0] = 100; + Assert.NotEqual(leftSpan[0], rightSpan[0]); + + leftData = [.. Enumerable.Range(0, 27)]; + rightData = [.. Enumerable.Range(0, 27)]; + leftSpan = leftData.AsTensorSpan(3, 3, 3); + rightSpan = rightData.AsTensorSpan(3, 3, 3); + success = leftSpan.TryCopyTo(rightSpan); + Assert.True(success); + + while (leftEnum.MoveNext() && rightEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, rightEnum.Current); + } + + var l = leftData.AsTensorSpan(3, 3, 3); + var r = new TensorSpan(); + success = l.TryCopyTo(r); + Assert.False(success); + } + + [Fact] + public static void TensorSpanSliceTest() + { + int[] a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + int[] results = new int[9]; + TensorSpan spanInt = a.AsTensorSpan(3, 3); + + Assert.Throws(() => a.AsTensorSpan(2, 3).Slice(0..1)); + Assert.Throws(() => a.AsTensorSpan(2, 3).Slice(1..2)); + Assert.Throws(() => a.AsTensorSpan(2, 3).Slice(0..1, 5..6)); + + var sp = spanInt.Slice(1..3, 1..3); + Assert.Equal(5, sp[0, 0]); + Assert.Equal(6, sp[0, 1]); + Assert.Equal(8, sp[1, 0]); + Assert.Equal(9, sp[1, 1]); + int[] slice = [5, 6, 8, 9]; + results = new int[4]; + sp.FlattenTo(results); + Assert.Equal(slice, results); + var enumerator = sp.GetEnumerator(); + var index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + sp = spanInt.Slice(0..3, 0..3); + Assert.Equal(1, sp[0, 0]); + Assert.Equal(2, sp[0, 1]); + Assert.Equal(3, sp[0, 2]); + Assert.Equal(4, sp[1, 0]); + Assert.Equal(5, sp[1, 1]); + Assert.Equal(6, sp[1, 2]); + Assert.Equal(7, sp[2, 0]); + Assert.Equal(8, sp[2, 1]); + Assert.Equal(9, sp[2, 2]); + results = new int[9]; + sp.FlattenTo(results); + Assert.Equal(a, results); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(a[index++], enumerator.Current); + } + + sp = spanInt.Slice(0..1, 0..1); + Assert.Equal(1, sp[0, 0]); + Assert.Throws(() => a.AsTensorSpan(3, 3).Slice(0..1, 0..1)[0, 1]); + slice = [1]; + results = new int[1]; + sp.FlattenTo(results); + Assert.Equal(slice, results); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + sp = spanInt.Slice(0..2, 0..2); + Assert.Equal(1, sp[0, 0]); + Assert.Equal(2, sp[0, 1]); + Assert.Equal(4, sp[1, 0]); + Assert.Equal(5, sp[1, 1]); + slice = [1, 2, 4, 5]; + results = new int[4]; + sp.FlattenTo(results); + Assert.Equal(slice, results); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + int[] numbers = [.. Enumerable.Range(0, 27)]; + spanInt = numbers.AsTensorSpan(3, 3, 3); + sp = spanInt.Slice(1..2, 1..2, 1..2); + Assert.Equal(13, sp[0, 0, 0]); + slice = [13]; + results = new int[1]; + sp.FlattenTo(results); + Assert.Equal(slice, results); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + sp = spanInt.Slice(1..3, 1..3, 1..3); + Assert.Equal(13, sp[0, 0, 0]); + Assert.Equal(14, sp[0, 0, 1]); + Assert.Equal(16, sp[0, 1, 0]); + Assert.Equal(17, sp[0, 1, 1]); + Assert.Equal(22, sp[1, 0, 0]); + Assert.Equal(23, sp[1, 0, 1]); + Assert.Equal(25, sp[1, 1, 0]); + Assert.Equal(26, sp[1, 1, 1]); + slice = [13, 14, 16, 17, 22, 23, 25, 26]; + results = new int[8]; + sp.FlattenTo(results); + Assert.Equal(slice, results); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + numbers = [.. Enumerable.Range(0, 16)]; + spanInt = numbers.AsTensorSpan(2, 2, 2, 2); + sp = spanInt.Slice(1..2, 0..2, 1..2, 0..2); + Assert.Equal(10, sp[0,0,0,0]); + Assert.Equal(11, sp[0,0,0,1]); + Assert.Equal(14, sp[0,1,0,0]); + Assert.Equal(15, sp[0,1,0,1]); + slice = [10, 11, 14, 15]; + results = new int[4]; + sp.FlattenTo(results); + Assert.Equal(slice, results); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + } + + [Fact] + public static void LongArrayAsTensorSpan() + { + long[] b = { 91, -92, 93, 94, -95 }; + TensorSpan spanLong = b.AsTensorSpan(5); + Assert.Equal(91, spanLong[0]); + Assert.Equal(-92, spanLong[1]); + Assert.Equal(93, spanLong[2]); + Assert.Equal(94, spanLong[3]); + Assert.Equal(-95, spanLong[4]); + } + + [Fact] + public static void NullArrayAsTensorSpan() + { + int[] a = null; + TensorSpan span = a.AsTensorSpan(); + Assert.True(span == default); + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs b/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs new file mode 100644 index 000000000000..822469f3c4a4 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs @@ -0,0 +1,1568 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace System.Numerics.Tensors.Tests +{ + public class TensorTests + { + [Fact] + public static void TensorSequenceEqualTests() + { + Tensor t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); + Tensor t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); + Tensor equal = Tensor.SequenceEqual(t0, t1); + + Assert.Equal([3], equal.Lengths.ToArray()); + Assert.True(equal[0]); + Assert.True(equal[1]); + Assert.True(equal[2]); + + t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(1, 3); + t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); + equal = Tensor.SequenceEqual(t0, t1); + + Assert.Equal([1, 3], equal.Lengths.ToArray()); + Assert.True(equal[0, 0]); + Assert.True(equal[0, 1]); + Assert.True(equal[0, 2]); + + t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(1, 1, 3); + t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); + equal = Tensor.SequenceEqual(t0, t1); + + Assert.Equal([1, 1, 3], equal.Lengths.ToArray()); + Assert.True(equal[0, 0, 0]); + Assert.True(equal[0, 0, 1]); + Assert.True(equal[0, 0, 2]); + + t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); + t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(1, 3); + equal = Tensor.SequenceEqual(t0, t1); + + Assert.Equal([1, 3], equal.Lengths.ToArray()); + Assert.True(equal[0, 0]); + Assert.True(equal[0, 1]); + Assert.True(equal[0, 2]); + + t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); + t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(3, 1); + equal = Tensor.SequenceEqual(t0, t1); + + Assert.Equal([3, 3], equal.Lengths.ToArray()); + Assert.True(equal[0, 0]); + Assert.False(equal[0, 1]); + Assert.False(equal[0, 2]); + Assert.False(equal[1, 0]); + Assert.True(equal[1, 1]); + Assert.False(equal[1, 2]); + Assert.False(equal[2, 0]); + Assert.False(equal[2, 1]); + Assert.True(equal[2, 2]); + + t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(1, 3); + t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(3, 1); + equal = Tensor.SequenceEqual(t0, t1); + + Assert.Equal([3, 3], equal.Lengths.ToArray()); + Assert.True(equal[0, 0]); + Assert.False(equal[0, 1]); + Assert.False(equal[0, 2]); + Assert.False(equal[1, 0]); + Assert.True(equal[1, 1]); + Assert.False(equal[1, 2]); + Assert.False(equal[2, 0]); + Assert.False(equal[2, 1]); + Assert.True(equal[2, 2]); + + t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 4)); + t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); + Assert.Throws(() => Tensor.SequenceEqual(t0, t1)); + } + + [Fact] + public static void TensorMultiplyTests() + { + Tensor t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); + Tensor t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(3, 1); + Tensor t2 = Tensor.Multiply(t0, t1); + + Assert.Equal([3,3], t2.Lengths.ToArray()); + Assert.Equal(0, t2[0, 0]); + Assert.Equal(0, t2[0, 1]); + Assert.Equal(0, t2[0, 2]); + Assert.Equal(0, t2[1, 0]); + Assert.Equal(1, t2[1, 1]); + Assert.Equal(2, t2[1, 2]); + Assert.Equal(0, t2[2, 0]); + Assert.Equal(2, t2[2, 1]); + Assert.Equal(4, t2[2, 2]); + + t2 = Tensor.Multiply(t1, t0); + + Assert.Equal([3, 3], t2.Lengths.ToArray()); + Assert.Equal(0, t2[0, 0]); + Assert.Equal(0, t2[0, 1]); + Assert.Equal(0, t2[0, 2]); + Assert.Equal(0, t2[1, 0]); + Assert.Equal(1, t2[1, 1]); + Assert.Equal(2, t2[1, 2]); + Assert.Equal(0, t2[2, 0]); + Assert.Equal(2, t2[2, 1]); + Assert.Equal(4, t2[2, 2]); + + t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 9)).Reshape(3, 3); + t2 = Tensor.Multiply(t0, t1); + + Assert.Equal([3, 3], t2.Lengths.ToArray()); + Assert.Equal(0, t2[0, 0]); + Assert.Equal(1, t2[0, 1]); + Assert.Equal(4, t2[0, 2]); + Assert.Equal(0, t2[1, 0]); + Assert.Equal(4, t2[1, 1]); + Assert.Equal(10, t2[1, 2]); + Assert.Equal(0, t2[2, 0]); + Assert.Equal(7, t2[2, 1]); + Assert.Equal(16, t2[2, 2]); + + + + + } + + [Fact] + public static void TensorBroadcastTests() + { + Tensor t0 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)), 1, 3, 1, 1, 1); + Tensor t1 = Tensor.Broadcast(t0, [1, 3, 1, 2, 1]); + + Assert.Equal([1, 3, 1, 2, 1], t1.Lengths.ToArray()); + + Assert.Equal(0, t1[0, 0, 0, 0, 0]); + Assert.Equal(0, t1[0, 0, 0, 1, 0]); + Assert.Equal(1, t1[0, 1, 0, 0, 0]); + Assert.Equal(1, t1[0, 1, 0, 1, 0]); + Assert.Equal(2, t1[0, 2, 0, 0, 0]); + Assert.Equal(2, t1[0, 2, 0, 1, 0]); + + t1 = Tensor.Broadcast(t0, [1, 3, 2, 1, 1]); + Assert.Equal([1, 3, 2, 1, 1], t1.Lengths.ToArray()); + + Assert.Equal(0, t1[0, 0, 0, 0, 0]); + Assert.Equal(0, t1[0, 0, 1, 0, 0]); + Assert.Equal(1, t1[0, 1, 0, 0, 0]); + Assert.Equal(1, t1[0, 1, 1, 0, 0]); + Assert.Equal(2, t1[0, 2, 0, 0, 0]); + Assert.Equal(2, t1[0, 2, 1, 0, 0]); + + t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(1, 3); + t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(3, 1); + var t2 = Tensor.Broadcast(t0, [3, 3]); + Assert.Equal([3, 3], t2.Lengths.ToArray()); + + Assert.Equal(0, t2[0, 0]); + Assert.Equal(1, t2[0, 1]); + Assert.Equal(2, t2[0, 2]); + Assert.Equal(0, t2[1, 0]); + Assert.Equal(1, t2[1, 1]); + Assert.Equal(2, t2[1, 2]); + Assert.Equal(0, t2[2, 0]); + Assert.Equal(1, t2[2, 1]); + Assert.Equal(2, t2[2, 2]); + + t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(3, 1); + t2 = Tensor.Broadcast(t1, [3, 3]); + Assert.Equal([3, 3], t2.Lengths.ToArray()); + + Assert.Equal(0, t2[0, 0]); + Assert.Equal(0, t2[0, 1]); + Assert.Equal(0, t2[0, 2]); + Assert.Equal(1, t2[1, 0]); + Assert.Equal(1, t2[1, 1]); + Assert.Equal(1, t2[1, 2]); + Assert.Equal(2, t2[2, 0]); + Assert.Equal(2, t2[2, 1]); + Assert.Equal(2, t2[2, 2]); + + var s1 = t2.AsTensorSpan(); + Assert.Equal(0, s1[0, 0]); + Assert.Equal(0, s1[0, 1]); + Assert.Equal(0, s1[0, 2]); + Assert.Equal(1, s1[1, 0]); + Assert.Equal(1, s1[1, 1]); + Assert.Equal(1, s1[1, 2]); + Assert.Equal(2, s1[2, 0]); + Assert.Equal(2, s1[2, 1]); + Assert.Equal(2, s1[2, 2]); + + var t3 = t2.Slice(0..1, ..); + Assert.Equal([1, 3], t3.Lengths.ToArray()); + + t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); + t2 = Tensor.Broadcast(t1, [3, 3]); + Assert.Equal([3, 3], t2.Lengths.ToArray()); + + Assert.Equal(0, t2[0, 0]); + Assert.Equal(1, t2[0, 1]); + Assert.Equal(2, t2[0, 2]); + Assert.Equal(0, t2[1, 0]); + Assert.Equal(1, t2[1, 1]); + Assert.Equal(2, t2[1, 2]); + Assert.Equal(0, t2[2, 0]); + Assert.Equal(1, t2[2, 1]); + Assert.Equal(2, t2[2, 2]); + } + + //// Needs internals visible + //[Fact] + //public static void TensorBroadcastToShapeCompatibleTests() + //{ + // Tensor t0 = Tensor.Reshape(Tensor.FillRange(Enumerable.Range(0, 8)), 8); + // Tensor t1 = Tensor.Reshape(Tensor.FillRange(Enumerable.Range(0, 8)), 1, 8); + + // Assert.True(Tensor.AreShapesBroadcastToCompatible(t0.Lengths, t1.Lengths)); + // Assert.True(Tensor.AreShapesBroadcastToCompatible(t0, t1)); + + // t1 = Tensor.Reshape(Tensor.FillRange(Enumerable.Range(0, 8)), 2, 4); + // Assert.False(Tensor.AreShapesBroadcastToCompatible(t0, t1)); + + // t0 = Tensor.FillRange(Enumerable.Range(0, 3)); + + // Assert.False(Tensor.AreShapesBroadcastToCompatible(t0.Lengths, [1,3,1,1,1])); + + //} + + [Fact] + public static void TensorResizeTests() + { + Tensor t0 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(0, 8)), 2, 2, 2); + var t1 = Tensor.Resize(t0, [1]); + Assert.Equal([1], t1.Lengths.ToArray()); + Assert.Equal(0, t1[0]); + + t1 = Tensor.Resize(t0, [1, 1]); + Assert.Equal([1, 1], t1.Lengths.ToArray()); + Assert.Equal(0, t1[0, 0]); + + t1 = Tensor.Resize(t0, [6]); + Assert.Equal([6], t1.Lengths.ToArray()); + Assert.Equal(0, t1[0]); + Assert.Equal(1, t1[1]); + Assert.Equal(2, t1[2]); + Assert.Equal(3, t1[3]); + Assert.Equal(4, t1[4]); + Assert.Equal(5, t1[5]); + + t1 = Tensor.Resize(t0, [10]); + Assert.Equal([10], t1.Lengths.ToArray()); + Assert.Equal(0, t1[0]); + Assert.Equal(1, t1[1]); + Assert.Equal(2, t1[2]); + Assert.Equal(3, t1[3]); + Assert.Equal(4, t1[4]); + Assert.Equal(5, t1[5]); + Assert.Equal(6, t1[6]); + Assert.Equal(7, t1[7]); + Assert.Equal(0, t1[8]); + Assert.Equal(0, t1[9]); + + t1 = Tensor.Resize(t0, [2, 5]); + Assert.Equal([2, 5], t1.Lengths.ToArray()); + Assert.Equal(0, t1[0, 0]); + Assert.Equal(1, t1[0, 1]); + Assert.Equal(2, t1[0, 2]); + Assert.Equal(3, t1[0, 3]); + Assert.Equal(4, t1[0, 4]); + Assert.Equal(5, t1[1, 0]); + Assert.Equal(6, t1[1, 1]); + Assert.Equal(7, t1[1, 2]); + Assert.Equal(0, t1[1, 3]); + Assert.Equal(0, t1[1, 4]); + } + + [Fact] + public static void TensorSplitTests() + { + Tensor t0 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(0, 8)), 2, 2, 2); + var t1 = Tensor.Split(t0, 2, 0); + Assert.Equal([1, 2, 2], t1[0].Lengths.ToArray()); + Assert.Equal([1, 2, 2], t1[1].Lengths.ToArray()); + Assert.Equal(0, t1[0][0, 0, 0]); + Assert.Equal(1, t1[0][0, 0, 1]); + Assert.Equal(2, t1[0][0, 1, 0]); + Assert.Equal(3, t1[0][0, 1, 1]); + Assert.Equal(4, t1[1][0, 0, 0]); + Assert.Equal(5, t1[1][0, 0, 1]); + Assert.Equal(6, t1[1][0, 1, 0]); + Assert.Equal(7, t1[1][0, 1, 1]); + + t1 = Tensor.Split(t0, 2, 1); + Assert.Equal([2, 1, 2], t1[0].Lengths.ToArray()); + Assert.Equal([2, 1, 2], t1[1].Lengths.ToArray()); + Assert.Equal(0, t1[0][0, 0, 0]); + Assert.Equal(1, t1[0][0, 0, 1]); + Assert.Equal(4, t1[0][1, 0, 0]); + Assert.Equal(5, t1[0][1, 0, 1]); + Assert.Equal(2, t1[1][0, 0, 0]); + Assert.Equal(3, t1[1][0, 0, 1]); + Assert.Equal(6, t1[1][1, 0, 0]); + Assert.Equal(7, t1[1][1, 0, 1]); + + t1 = Tensor.Split(t0, 2, 2); + Assert.Equal([2, 2, 1], t1[0].Lengths.ToArray()); + Assert.Equal([2, 2, 1], t1[1].Lengths.ToArray()); + Assert.Equal(0, t1[0][0, 0, 0]); + Assert.Equal(2, t1[0][0, 1, 0]); + Assert.Equal(4, t1[0][1, 0, 0]); + Assert.Equal(6, t1[0][1, 1, 0]); + Assert.Equal(1, t1[1][0, 0, 0]); + Assert.Equal(3, t1[1][0, 1, 0]); + Assert.Equal(5, t1[1][1, 0, 0]); + Assert.Equal(7, t1[1][1, 1, 0]); + } + + [Fact] + public static void TensorReverseTests() + { + Tensor t0 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(0, 8)), 2, 2, 2); + var t1 = Tensor.Reverse(t0); + Assert.Equal(7, t1[0, 0, 0]); + Assert.Equal(6, t1[0, 0, 1]); + Assert.Equal(5, t1[0, 1, 0]); + Assert.Equal(4, t1[0, 1, 1]); + Assert.Equal(3, t1[1, 0, 0]); + Assert.Equal(2, t1[1, 0, 1]); + Assert.Equal(1, t1[1, 1, 0]); + Assert.Equal(0, t1[1, 1, 1]); + + t1 = Tensor.Reverse(t0, 0); + Assert.Equal(4, t1[0, 0, 0]); + Assert.Equal(5, t1[0, 0, 1]); + Assert.Equal(6, t1[0, 1, 0]); + Assert.Equal(7, t1[0, 1, 1]); + Assert.Equal(0, t1[1, 0, 0]); + Assert.Equal(1, t1[1, 0, 1]); + Assert.Equal(2, t1[1, 1, 0]); + Assert.Equal(3, t1[1, 1, 1]); + + t1 = Tensor.Reverse(t0, 1); + Assert.Equal(2, t1[0, 0, 0]); + Assert.Equal(3, t1[0, 0, 1]); + Assert.Equal(0, t1[0, 1, 0]); + Assert.Equal(1, t1[0, 1, 1]); + Assert.Equal(6, t1[1, 0, 0]); + Assert.Equal(7, t1[1, 0, 1]); + Assert.Equal(4, t1[1, 1, 0]); + Assert.Equal(5, t1[1, 1, 1]); + + t1 = Tensor.Reverse(t0, 2); + Assert.Equal(1, t1[0, 0, 0]); + Assert.Equal(0, t1[0, 0, 1]); + Assert.Equal(3, t1[0, 1, 0]); + Assert.Equal(2, t1[0, 1, 1]); + Assert.Equal(5, t1[1, 0, 0]); + Assert.Equal(4, t1[1, 0, 1]); + Assert.Equal(7, t1[1, 1, 0]); + Assert.Equal(6, t1[1, 1, 1]); + } + + [Fact] + public static void TensorSetSliceTests() + { + Tensor t0 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(0, 10)), 2, 5); + Tensor t1 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(10, 10)), 2, 5); + Tensor.SetSlice(t0, t1); + + Assert.Equal(10, t0[0, 0]); + Assert.Equal(11, t0[0, 1]); + Assert.Equal(12, t0[0, 2]); + Assert.Equal(13, t0[0, 3]); + Assert.Equal(14, t0[0, 4]); + Assert.Equal(15, t0[1, 0]); + Assert.Equal(16, t0[1, 1]); + Assert.Equal(17, t0[1, 2]); + Assert.Equal(18, t0[1, 3]); + Assert.Equal(19, t0[1, 4]); + + t0 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(0, 10)), 2, 5); + t1 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(10, 5)), 1, 5); + t0.SetSlice(t1, 0..1, ..); + + Assert.Equal(10, t0[0, 0]); + Assert.Equal(11, t0[0, 1]); + Assert.Equal(12, t0[0, 2]); + Assert.Equal(13, t0[0, 3]); + Assert.Equal(14, t0[0, 4]); + Assert.Equal(5, t0[1, 0]); + Assert.Equal(6, t0[1, 1]); + Assert.Equal(7, t0[1, 2]); + Assert.Equal(8, t0[1, 3]); + Assert.Equal(9, t0[1, 4]); + + t0 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(0, 10)), 2, 5); + t1 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(10, 5)), 1, 5); + Tensor.SetSlice(t0, t1, 1..2, ..); + + Assert.Equal(0, t0[0, 0]); + Assert.Equal(1, t0[0, 1]); + Assert.Equal(2, t0[0, 2]); + Assert.Equal(3, t0[0, 3]); + Assert.Equal(4, t0[0, 4]); + Assert.Equal(10, t0[1, 0]); + Assert.Equal(11, t0[1, 1]); + Assert.Equal(12, t0[1, 2]); + Assert.Equal(13, t0[1, 3]); + Assert.Equal(14, t0[1, 4]); + } + [Fact] + public static void TensorStackTests() + { + Tensor t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 10)).Reshape(2, 5); + Tensor t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 10)).Reshape(2, 5); + + var resultTensor = Tensor.Stack([t0, t1]); + Assert.Equal(3, resultTensor.Rank); + Assert.Equal(2, resultTensor.Lengths[0]); + Assert.Equal(2, resultTensor.Lengths[1]); + Assert.Equal(5, resultTensor.Lengths[2]); + + Assert.Equal(0, resultTensor[0, 0, 0]); + Assert.Equal(1, resultTensor[0, 0, 1]); + Assert.Equal(2, resultTensor[0, 0, 2]); + Assert.Equal(3, resultTensor[0, 0, 3]); + Assert.Equal(4, resultTensor[0, 0, 4]); + Assert.Equal(5, resultTensor[0, 1, 0]); + Assert.Equal(6, resultTensor[0, 1, 1]); + Assert.Equal(7, resultTensor[0, 1, 2]); + Assert.Equal(8, resultTensor[0, 1, 3]); + Assert.Equal(9, resultTensor[0, 1, 4]); + Assert.Equal(0, resultTensor[1, 0, 0]); + Assert.Equal(1, resultTensor[1, 0, 1]); + Assert.Equal(2, resultTensor[1, 0, 2]); + Assert.Equal(3, resultTensor[1, 0, 3]); + Assert.Equal(4, resultTensor[1, 0, 4]); + Assert.Equal(5, resultTensor[1, 1, 0]); + Assert.Equal(6, resultTensor[1, 1, 1]); + Assert.Equal(7, resultTensor[1, 1, 2]); + Assert.Equal(8, resultTensor[1, 1, 3]); + Assert.Equal(9, resultTensor[1, 1, 4]); + + resultTensor = Tensor.Stack([t0, t1], axis:1); + Assert.Equal(3, resultTensor.Rank); + Assert.Equal(2, resultTensor.Lengths[0]); + Assert.Equal(2, resultTensor.Lengths[1]); + Assert.Equal(5, resultTensor.Lengths[2]); + + Assert.Equal(0, resultTensor[0, 0, 0]); + Assert.Equal(1, resultTensor[0, 0, 1]); + Assert.Equal(2, resultTensor[0, 0, 2]); + Assert.Equal(3, resultTensor[0, 0, 3]); + Assert.Equal(4, resultTensor[0, 0, 4]); + Assert.Equal(0, resultTensor[0, 1, 0]); + Assert.Equal(1, resultTensor[0, 1, 1]); + Assert.Equal(2, resultTensor[0, 1, 2]); + Assert.Equal(3, resultTensor[0, 1, 3]); + Assert.Equal(4, resultTensor[0, 1, 4]); + Assert.Equal(5, resultTensor[1, 0, 0]); + Assert.Equal(6, resultTensor[1, 0, 1]); + Assert.Equal(7, resultTensor[1, 0, 2]); + Assert.Equal(8, resultTensor[1, 0, 3]); + Assert.Equal(9, resultTensor[1, 0, 4]); + Assert.Equal(5, resultTensor[1, 1, 0]); + Assert.Equal(6, resultTensor[1, 1, 1]); + Assert.Equal(7, resultTensor[1, 1, 2]); + Assert.Equal(8, resultTensor[1, 1, 3]); + Assert.Equal(9, resultTensor[1, 1, 4]); + + resultTensor = Tensor.Stack([t0, t1], axis: 2); + Assert.Equal(3, resultTensor.Rank); + Assert.Equal(2, resultTensor.Lengths[0]); + Assert.Equal(5, resultTensor.Lengths[1]); + Assert.Equal(2, resultTensor.Lengths[2]); + + Assert.Equal(0, resultTensor[0, 0, 0]); + Assert.Equal(0, resultTensor[0, 0, 1]); + Assert.Equal(1, resultTensor[0, 1, 0]); + Assert.Equal(1, resultTensor[0, 1, 1]); + Assert.Equal(2, resultTensor[0, 2, 0]); + Assert.Equal(2, resultTensor[0, 2, 1]); + Assert.Equal(3, resultTensor[0, 3, 0]); + Assert.Equal(3, resultTensor[0, 3, 1]); + Assert.Equal(4, resultTensor[0, 4, 0]); + Assert.Equal(4, resultTensor[0, 4, 1]); + Assert.Equal(5, resultTensor[1, 0, 0]); + Assert.Equal(5, resultTensor[1, 0, 1]); + Assert.Equal(6, resultTensor[1, 1, 0]); + Assert.Equal(6, resultTensor[1, 1, 1]); + Assert.Equal(7, resultTensor[1, 2, 0]); + Assert.Equal(7, resultTensor[1, 2, 1]); + Assert.Equal(8, resultTensor[1, 3, 0]); + Assert.Equal(8, resultTensor[1, 3, 1]); + Assert.Equal(9, resultTensor[1, 4, 0]); + Assert.Equal(9, resultTensor[1, 4, 1]); + } + + [Fact] + public static void TensorStdDevTests() + { + Tensor t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 4).Select(i => (float)i))).Reshape(2, 2); + //Tensor.Sum(t0) + + Assert.Equal(StdDev([0, 1, 2, 3]), Tensor.StdDev(t0), .1); + + + } + + public static float StdDev(float[] values) + { + float mean = Mean(values); + float sum = 0; + for(int i = 0; i < values.Length; i++) + { + sum += MathF.Pow(values[i] - mean, 2); + } + return sum / values.Length; + } + + [Fact] + public static void TensorMeanTests() + { + Tensor t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 4).Select(i => (float)i))).Reshape(2, 2); + + Assert.Equal(Mean([0, 1, 2, 3]), Tensor.Mean(t0), .1); + } + + public static float Mean(float[] values) + { + float sum = 0; + for (int i = 0; i < values.Length; i++) + { + sum += values[i]; + } + return sum/values.Length; + } + + [Fact] + public static void TensorConcatenateTests() + { + Tensor t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 4).Select(i => (float)i))).Reshape(2, 2); + Tensor t1 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 4).Select(i => (float)i))).Reshape(2, 2); + var resultTensor = Tensor.Concatenate([t0, t1]); + + Assert.Equal(2, resultTensor.Rank); + Assert.Equal(4, resultTensor.Lengths[0]); + Assert.Equal(2, resultTensor.Lengths[1]); + Assert.Equal(0, resultTensor[0, 0]); + Assert.Equal(1, resultTensor[0, 1]); + Assert.Equal(2, resultTensor[1, 0]); + Assert.Equal(3, resultTensor[1, 1]); + Assert.Equal(0, resultTensor[2, 0]); + Assert.Equal(1, resultTensor[2, 1]); + Assert.Equal(2, resultTensor[3, 0]); + Assert.Equal(3, resultTensor[3, 1]); + + resultTensor = Tensor.Concatenate([t0, t1], 1); + Assert.Equal(2, resultTensor.Rank); + Assert.Equal(2, resultTensor.Lengths[0]); + Assert.Equal(4, resultTensor.Lengths[1]); + Assert.Equal(0, resultTensor[0, 0]); + Assert.Equal(1, resultTensor[0, 1]); + Assert.Equal(0, resultTensor[0, 2]); + Assert.Equal(1, resultTensor[0, 3]); + Assert.Equal(2, resultTensor[1, 0]); + Assert.Equal(3, resultTensor[1, 1]); + Assert.Equal(2, resultTensor[1, 2]); + Assert.Equal(3, resultTensor[1, 3]); + + resultTensor = Tensor.Concatenate([t0, t1], -1); + Assert.Equal(1, resultTensor.Rank); + Assert.Equal(8, resultTensor.Lengths[0]); + Assert.Equal(0, resultTensor[0]); + Assert.Equal(1, resultTensor[1]); + Assert.Equal(2, resultTensor[2]); + Assert.Equal(3, resultTensor[3]); + Assert.Equal(0, resultTensor[4]); + Assert.Equal(1, resultTensor[5]); + Assert.Equal(2, resultTensor[6]); + Assert.Equal(3, resultTensor[7]); + + Tensor t2 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 4).Select(i => (float)i))).Reshape(2, 2); + resultTensor = Tensor.Concatenate([t0, t1, t2]); + + Assert.Equal(2, resultTensor.Rank); + Assert.Equal(6, resultTensor.Lengths[0]); + Assert.Equal(2, resultTensor.Lengths[1]); + Assert.Equal(0, resultTensor[0, 0]); + Assert.Equal(1, resultTensor[0, 1]); + Assert.Equal(2, resultTensor[1, 0]); + Assert.Equal(3, resultTensor[1, 1]); + Assert.Equal(0, resultTensor[2, 0]); + Assert.Equal(1, resultTensor[2, 1]); + Assert.Equal(2, resultTensor[3, 0]); + Assert.Equal(3, resultTensor[3, 1]); + Assert.Equal(0, resultTensor[4, 0]); + Assert.Equal(1, resultTensor[4, 1]); + Assert.Equal(2, resultTensor[5, 0]); + Assert.Equal(3, resultTensor[5, 1]); + + resultTensor = Tensor.Concatenate([t0, t1, t2], -1); + + Assert.Equal(1, resultTensor.Rank); + Assert.Equal(12, resultTensor.Lengths[0]); + Assert.Equal(0, resultTensor[0]); + Assert.Equal(1, resultTensor[1]); + Assert.Equal(2, resultTensor[2]); + Assert.Equal(3, resultTensor[3]); + Assert.Equal(0, resultTensor[4]); + Assert.Equal(1, resultTensor[5]); + Assert.Equal(2, resultTensor[6]); + Assert.Equal(3, resultTensor[7]); + Assert.Equal(0, resultTensor[8]); + Assert.Equal(1, resultTensor[9]); + Assert.Equal(2, resultTensor[10]); + Assert.Equal(3, resultTensor[11]); + + resultTensor = Tensor.Concatenate([t0, t1, t2], 1); + + Assert.Equal(2, resultTensor.Rank); + Assert.Equal(2, resultTensor.Lengths[0]); + Assert.Equal(6, resultTensor.Lengths[1]); + Assert.Equal(0, resultTensor[0, 0]); + Assert.Equal(1, resultTensor[0, 1]); + Assert.Equal(0, resultTensor[0, 2]); + Assert.Equal(1, resultTensor[0, 3]); + Assert.Equal(0, resultTensor[0, 4]); + Assert.Equal(1, resultTensor[0, 5]); + Assert.Equal(2, resultTensor[1, 0]); + Assert.Equal(3, resultTensor[1, 1]); + Assert.Equal(2, resultTensor[1, 2]); + Assert.Equal(3, resultTensor[1, 3]); + Assert.Equal(2, resultTensor[1, 4]); + Assert.Equal(3, resultTensor[1, 5]); + + t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(2, 3, 2); + t1 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(2, 3, 2); + t2 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 8).Select(i => (float)i))).Reshape(2, 2, 2); + Assert.Throws(() => Tensor.Concatenate([t0, t1, t2])); + Assert.Throws(() => Tensor.Concatenate([t0, t1, t2], 2)); + Assert.Throws(() => Tensor.Concatenate([t0, t1, t2], 5)); + Assert.Throws(() => Tensor.Concatenate([t0, t1, t2], -2)); + resultTensor = Tensor.Concatenate([t0, t1, t2], -1); + float[] result = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7]; + Assert.Equal(1, resultTensor.Rank); + Assert.Equal(32, resultTensor.Lengths[0]); + Assert.Equal(result, resultTensor.ToArray()); + + resultTensor = Tensor.Concatenate([t0, t1, t2], 1); + result = [0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 6, 7, 8, 9, 10, 11, 6, 7, 8, 9, 10, 11, 4, 5, 6, 7]; + Assert.Equal(3, resultTensor.Rank); + Assert.Equal(2, resultTensor.Lengths[0]); + Assert.Equal(8, resultTensor.Lengths[1]); + Assert.Equal(2, resultTensor.Lengths[2]); + Assert.Equal(result, resultTensor.ToArray()); + nint[] indices = new nint[resultTensor.Rank]; + for(int i = 0; i < result.Length; i++) + { + Assert.Equal(result[i], resultTensor[indices]); + Helpers.AdjustIndices(resultTensor.Rank - 1, 1, ref indices, resultTensor.Lengths); + } + + t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(2, 2, 3); + t1 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(2, 2, 3); + t2 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 8).Select(i => (float)i))).Reshape(2, 2, 2); + Assert.Throws(() => Tensor.Concatenate([t0, t1, t2], 0)); + Assert.Throws(() => Tensor.Concatenate([t0, t1, t2], 1)); + resultTensor = Tensor.Concatenate([t0, t1, t2], 2); + result = [0, 1, 2, 0, 1, 2, 0, 1, 3, 4, 5, 3, 4, 5, 2, 3, 6, 7, 8, 6, 7, 8, 4, 5, 9, 10, 11, 9, 10, 11, 6, 7]; + Assert.Equal(3, resultTensor.Rank); + Assert.Equal(2, resultTensor.Lengths[0]); + Assert.Equal(2, resultTensor.Lengths[1]); + Assert.Equal(8, resultTensor.Lengths[2]); + Assert.Equal(result, resultTensor.ToArray()); + indices = new nint[resultTensor.Rank]; + for (int i = 0; i < result.Length; i++) + { + Assert.Equal(result[i], resultTensor[indices]); + Helpers.AdjustIndices(resultTensor.Rank - 1, 1, ref indices, resultTensor.Lengths); + } + + t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(3, 2, 2); + t1 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(3, 2, 2); + t2 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 8).Select(i => (float)i))).Reshape(2, 2, 2); + Assert.Throws(() => Tensor.Concatenate([t0, t1, t2], 1)); + Assert.Throws(() => Tensor.Concatenate([t0, t1, t2], 2)); + resultTensor = Tensor.Concatenate([t0, t1, t2]); + result = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7]; + Assert.Equal(3, resultTensor.Rank); + Assert.Equal(8, resultTensor.Lengths[0]); + Assert.Equal(2, resultTensor.Lengths[1]); + Assert.Equal(2, resultTensor.Lengths[2]); + Assert.Equal(result, resultTensor.ToArray()); + indices = new nint[resultTensor.Rank]; + for (int i = 0; i < result.Length; i++) + { + Assert.Equal(result[i], resultTensor[indices]); + Helpers.AdjustIndices(resultTensor.Rank - 1, 1, ref indices, resultTensor.Lengths); + } + } + + [Fact] + public static void TensorTransposeTests() + { + Tensor t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 4).Select(i => (float)i))).Reshape(2, 2); + var t1 = Tensor.Permute(t0); + + Assert.Equal(0, t1[0, 0]); + Assert.Equal(2, t1[0, 1]); + Assert.Equal(1, t1[1, 0]); + Assert.Equal(3, t1[1, 1]); + + t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 6).Select(i => (float)i))).Reshape(2, 3); + t1 = Tensor.Permute(t0); + + Assert.Equal(3, t1.Lengths[0]); + Assert.Equal(2, t1.Lengths[1]); + Assert.Equal(0, t1[0, 0]); + Assert.Equal(3, t1[0, 1]); + Assert.Equal(1, t1[1, 0]); + Assert.Equal(4, t1[1, 1]); + Assert.Equal(2, t1[2, 0]); + Assert.Equal(5, t1[2, 1]); + + t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 6).Select(i => (float)i))).Reshape(1, 2, 3); + t1 = Tensor.Permute(t0); + + Assert.Equal(3, t1.Lengths[0]); + Assert.Equal(2, t1.Lengths[1]); + Assert.Equal(1, t1.Lengths[2]); + Assert.Equal(0, t1[0, 0, 0]); + Assert.Equal(3, t1[0, 1, 0]); + Assert.Equal(1, t1[1, 0, 0]); + Assert.Equal(4, t1[1, 1, 0]); + Assert.Equal(2, t1[2, 0, 0]); + Assert.Equal(5, t1[2, 1, 0]); + + t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(2, 2, 3); + t1 = Tensor.Permute(t0); + + Assert.Equal(3, t1.Lengths[0]); + Assert.Equal(2, t1.Lengths[1]); + Assert.Equal(2, t1.Lengths[2]); + Assert.Equal(0, t1[0, 0, 0]); + Assert.Equal(6, t1[0, 0, 1]); + Assert.Equal(3, t1[0, 1, 0]); + Assert.Equal(9, t1[0, 1, 1]); + Assert.Equal(1, t1[1, 0, 0]); + Assert.Equal(7, t1[1, 0, 1]); + Assert.Equal(4, t1[1, 1, 0]); + Assert.Equal(10, t1[1, 1, 1]); + Assert.Equal(2, t1[2, 0, 0]); + Assert.Equal(8, t1[2, 0, 1]); + Assert.Equal(5, t1[2, 1, 0]); + Assert.Equal(11, t1[2, 1, 1]); + + t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(2, 2, 3); + t1 = Tensor.Permute(t0, 1, 2, 0); + + Assert.Equal(2, t1.Lengths[0]); + Assert.Equal(3, t1.Lengths[1]); + Assert.Equal(2, t1.Lengths[2]); + Assert.Equal(0, t1[0, 0, 0]); + Assert.Equal(6, t1[0, 0, 1]); + Assert.Equal(1, t1[0, 1, 0]); + Assert.Equal(7, t1[0, 1, 1]); + Assert.Equal(2, t1[0, 2, 0]); + Assert.Equal(8, t1[0, 2, 1]); + Assert.Equal(3, t1[1, 0, 0]); + Assert.Equal(9, t1[1, 0, 1]); + Assert.Equal(4, t1[1, 1, 0]); + Assert.Equal(10, t1[1, 1, 1]); + Assert.Equal(5, t1[1, 2, 0]); + Assert.Equal(11, t1[1, 2, 1]); + } + + [Fact] + public static void TensorPermuteTests() + { + Tensor t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 4).Select(i => (float)i))).Reshape(2, 2); + var t1 = Tensor.Transpose(t0); + + Assert.Equal(0, t1[0, 0]); + Assert.Equal(2, t1[0, 1]); + Assert.Equal(1, t1[1, 0]); + Assert.Equal(3, t1[1, 1]); + + t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(2, 2, 3); + t1 = Tensor.Transpose(t0); + + Assert.Equal(2, t1.Lengths[0]); + Assert.Equal(3, t1.Lengths[1]); + Assert.Equal(2, t1.Lengths[2]); + Assert.Equal(0, t1[0, 0, 0]); + Assert.Equal(3, t1[0, 0, 1]); + Assert.Equal(1, t1[0, 1, 0]); + Assert.Equal(4, t1[0, 1, 1]); + Assert.Equal(2, t1[0, 2, 0]); + Assert.Equal(5, t1[0, 2, 1]); + Assert.Equal(6, t1[1, 0, 0]); + Assert.Equal(9, t1[1, 0, 1]); + Assert.Equal(7, t1[1, 1, 0]); + Assert.Equal(10, t1[1, 1, 1]); + Assert.Equal(8, t1[1, 2, 0]); + Assert.Equal(11, t1[1, 2, 1]); + } + + [Fact] + public static void IntArrayAsTensor() + { + int[] a = [91, 92, -93, 94]; + TensorSpan spanInt = a.AsTensorSpan(4); + nint[] dims = [4]; + var tensor = Tensor.CreateUninitialized(dims.AsSpan(), false); + spanInt.CopyTo(tensor); + Assert.Equal(1, tensor.Rank); + + Assert.Equal(1, tensor.Lengths.Length); + Assert.Equal(4, tensor.Lengths[0]); + Assert.Equal(1, tensor.Strides.Length); + Assert.Equal(1, tensor.Strides[0]); + Assert.Equal(91, tensor[0]); + Assert.Equal(92, tensor[1]); + Assert.Equal(-93, tensor[2]); + Assert.Equal(94, tensor[3]); + Assert.Equal(a, tensor.ToArray()); + tensor[0] = 100; + tensor[1] = 101; + tensor[2] = -102; + tensor[3] = 103; + + Assert.Equal(100, tensor[0]); + Assert.Equal(101, tensor[1]); + Assert.Equal(-102, tensor[2]); + Assert.Equal(103, tensor[3]); + + a[0] = 91; + a[1] = 92; + a[2] = -93; + a[3] = 94; + spanInt = a.AsTensorSpan(2, 2); + dims = [2, 2]; + tensor = Tensor.CreateUninitialized(dims.AsSpan(), false); + spanInt.CopyTo(tensor); + Assert.Equal(a, tensor.ToArray()); + Assert.Equal(2, tensor.Rank); + //Assert.Equal(4, spanInt.FlattenedLength); + Assert.Equal(2, tensor.Lengths.Length); + Assert.Equal(2, tensor.Lengths[0]); + Assert.Equal(2, tensor.Lengths[1]); + Assert.Equal(2, tensor.Strides.Length); + Assert.Equal(2, tensor.Strides[0]); + Assert.Equal(1, tensor.Strides[1]); + Assert.Equal(91, tensor[0, 0]); + Assert.Equal(92, tensor[0, 1]); + Assert.Equal(-93, tensor[1, 0]); + Assert.Equal(94, tensor[1, 1]); + + tensor[0, 0] = 100; + tensor[0, 1] = 101; + tensor[1, 0] = -102; + tensor[1, 1] = 103; + + Assert.Equal(100, tensor[0, 0]); + Assert.Equal(101, tensor[0, 1]); + Assert.Equal(-102, tensor[1, 0]); + Assert.Equal(103, tensor[1, 1]); + } + + [Fact] + public static void TensorFillTest() + { + nint[] dims = [3, 3]; + var tensor = Tensor.CreateUninitialized(dims.AsSpan(), false); + tensor.Fill(-1); + var enumerator = tensor.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(-1, enumerator.Current); + } + + tensor.Fill(int.MinValue); + enumerator = tensor.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(int.MinValue, enumerator.Current); + } + + tensor.Fill(int.MaxValue); + enumerator = tensor.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(int.MaxValue, enumerator.Current); + } + + dims = [9]; + tensor = Tensor.CreateUninitialized(dims.AsSpan(), false); + tensor.Fill(-1); + enumerator = tensor.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(-1, enumerator.Current); + } + + dims = [3, 3, 3]; + tensor = Tensor.CreateUninitialized(dims.AsSpan(), false); + tensor.Fill(-1); + enumerator = tensor.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(-1, enumerator.Current); + } + + dims = [3, 2, 2]; + tensor = Tensor.CreateUninitialized(dims.AsSpan(), false); + tensor.Fill(-1); + enumerator = tensor.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(-1, enumerator.Current); + } + + dims = [2, 2, 2, 2]; + tensor = Tensor.CreateUninitialized(dims.AsSpan(), false); + tensor.Fill(-1); + enumerator = tensor.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(-1, enumerator.Current); + } + + dims = [3, 2, 2, 2]; + tensor = Tensor.CreateUninitialized(dims.AsSpan(), false); + tensor.Fill(-1); + enumerator = tensor.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(-1, enumerator.Current); + } + } + + [Fact] + public static void TensorClearTest() + { + int[] a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + TensorSpan spanInt = a.AsTensorSpan(3, 3); + var tensor = Tensor.CreateUninitialized([3, 3], false); + spanInt.CopyTo(tensor); + var slice = tensor.Slice(0..2, 0..2); + slice.Clear(); + Assert.Equal(0, slice[0, 0]); + Assert.Equal(0, slice[0, 1]); + Assert.Equal(0, slice[1, 0]); + Assert.Equal(0, slice[1, 1]); + + // Since Tensor.Slice does a copy the original tensor shouldn't be modified + Assert.Equal(1, tensor[0, 0]); + Assert.Equal(2, tensor[0, 1]); + Assert.Equal(3, tensor[0, 2]); + Assert.Equal(4, tensor[1, 0]); + Assert.Equal(5, tensor[1, 1]); + Assert.Equal(6, tensor[1, 2]); + Assert.Equal(7, tensor[2, 0]); + Assert.Equal(8, tensor[2, 1]); + Assert.Equal(9, tensor[2, 2]); + + + tensor.Clear(); + var enumerator = tensor.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(0, enumerator.Current); + } + + a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + spanInt = a.AsTensorSpan(9); + tensor = Tensor.CreateUninitialized([9], false); + spanInt.CopyTo(tensor); + slice = tensor.Slice(0..1); + slice.Clear(); + Assert.Equal(0, slice[0]); + + // Since Tensor.Slice does a copy the original tensor shouldn't be modified + Assert.Equal(1, tensor[0]); + Assert.Equal(2, tensor[1]); + Assert.Equal(3, tensor[2]); + Assert.Equal(4, tensor[3]); + Assert.Equal(5, tensor[4]); + Assert.Equal(6, tensor[5]); + Assert.Equal(7, tensor[6]); + Assert.Equal(8, tensor[7]); + Assert.Equal(9, tensor[8]); + + + tensor.Clear(); + enumerator = tensor.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(0, enumerator.Current); + } + + a = [.. Enumerable.Range(0, 27)]; + spanInt = a.AsTensorSpan(3, 3, 3); + tensor = Tensor.CreateUninitialized([3, 3, 3], false); + spanInt.CopyTo(tensor); + tensor.Clear(); + enumerator = tensor.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(0, enumerator.Current); + } + + a = [.. Enumerable.Range(0, 12)]; + spanInt = a.AsTensorSpan(3, 2, 2); + tensor = Tensor.CreateUninitialized([3, 2, 2], false); + spanInt.CopyTo(tensor); + tensor.Clear(); + enumerator = tensor.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(0, enumerator.Current); + } + + a = [.. Enumerable.Range(0, 16)]; + spanInt = a.AsTensorSpan(2, 2, 2, 2); + tensor = Tensor.CreateUninitialized([2, 2, 2, 2], false); + spanInt.CopyTo(tensor); + tensor.Clear(); + enumerator = tensor.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(0, enumerator.Current); + } + + a = [.. Enumerable.Range(0, 24)]; + spanInt = a.AsTensorSpan(3, 2, 2, 2); + tensor = Tensor.CreateUninitialized([3, 2, 2, 2], false); + spanInt.CopyTo(tensor); + tensor.Clear(); + enumerator = tensor.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.Equal(0, enumerator.Current); + } + + // Make sure clearing a slice of a SPan doesn't clear the whole thing. + a = [.. Enumerable.Range(0, 9)]; + spanInt = a.AsTensorSpan(3, 3); + var spanSlice = spanInt.Slice(0..1, 0..3); + spanSlice.Clear(); + var spanEnumerator = spanSlice.GetEnumerator(); + while (spanEnumerator.MoveNext()) + { + Assert.Equal(0, spanEnumerator.Current); + } + + Assert.Equal(0, spanInt[0, 0]); + Assert.Equal(0, spanInt[0, 1]); + Assert.Equal(0, spanInt[0, 2]); + Assert.Equal(3, spanInt[1, 0]); + Assert.Equal(4, spanInt[1, 1]); + Assert.Equal(5, spanInt[1, 2]); + Assert.Equal(6, spanInt[2, 0]); + Assert.Equal(7, spanInt[2, 1]); + Assert.Equal(8, spanInt[2, 2]); + + // Make sure clearing a slice from the middle of a SPan doesn't clear the whole thing. + a = [.. Enumerable.Range(0, 9)]; + spanInt = a.AsTensorSpan(3, 3); + spanSlice = spanInt.Slice(1..2, 0..3); + spanSlice.Clear(); + spanEnumerator = spanSlice.GetEnumerator(); + while (spanEnumerator.MoveNext()) + { + Assert.Equal(0, spanEnumerator.Current); + } + + Assert.Equal(0, spanInt[0, 0]); + Assert.Equal(1, spanInt[0, 1]); + Assert.Equal(2, spanInt[0, 2]); + Assert.Equal(0, spanInt[1, 0]); + Assert.Equal(0, spanInt[1, 1]); + Assert.Equal(0, spanInt[1, 2]); + Assert.Equal(6, spanInt[2, 0]); + Assert.Equal(7, spanInt[2, 1]); + Assert.Equal(8, spanInt[2, 2]); + + // Make sure clearing a slice from the end of a SPan doesn't clear the whole thing. + a = [.. Enumerable.Range(0, 9)]; + spanInt = a.AsTensorSpan(3, 3); + spanSlice = spanInt.Slice(2..3, 0..3); + spanSlice.Clear(); + spanEnumerator = spanSlice.GetEnumerator(); + while (spanEnumerator.MoveNext()) + { + Assert.Equal(0, spanEnumerator.Current); + } + + Assert.Equal(0, spanInt[0, 0]); + Assert.Equal(1, spanInt[0, 1]); + Assert.Equal(2, spanInt[0, 2]); + Assert.Equal(3, spanInt[1, 0]); + Assert.Equal(4, spanInt[1, 1]); + Assert.Equal(5, spanInt[1, 2]); + Assert.Equal(0, spanInt[2, 0]); + Assert.Equal(0, spanInt[2, 1]); + Assert.Equal(0, spanInt[2, 2]); + + // Make sure it works with reference types. + object[] o = [new object(), new object(), new object(), new object(), new object(), new object(), new object(), new object(), new object()]; + TensorSpan spanObj = o.AsTensorSpan(3, 3); + spanObj.Clear(); + + var oSpanEnumerator = spanObj.GetEnumerator(); + while (oSpanEnumerator.MoveNext()) + { + Assert.Null(oSpanEnumerator.Current); + } + + // Make sure clearing a slice of a SPan with references it doesn't clear the whole thing. + o = [new object(), new object(), new object(), new object(), new object(), new object(), new object(), new object(), new object()]; + spanObj = o.AsTensorSpan(3, 3); + var oSpanSlice = spanObj.Slice(0..1, 0..3); + oSpanSlice.Clear(); + oSpanEnumerator = oSpanSlice.GetEnumerator(); + while (oSpanEnumerator.MoveNext()) + { + Assert.Null(oSpanEnumerator.Current); + } + + Assert.Null(spanObj[0, 0]); + Assert.Null(spanObj[0, 1]); + Assert.Null(spanObj[0, 2]); + Assert.NotNull(spanObj[1, 0]); + Assert.NotNull(spanObj[1, 1]); + Assert.NotNull(spanObj[1, 2]); + Assert.NotNull(spanObj[2, 0]); + Assert.NotNull(spanObj[2, 1]); + Assert.NotNull(spanObj[2, 2]); + + // Make sure clearing a slice of a SPan with references it doesn't clear the whole thing. + o = [new object(), new object(), new object(), new object(), new object(), new object(), new object(), new object(), new object()]; + spanObj = o.AsTensorSpan(3, 3); + oSpanSlice = spanObj.Slice(1..2, 0..3); + oSpanSlice.Clear(); + oSpanEnumerator = oSpanSlice.GetEnumerator(); + while (oSpanEnumerator.MoveNext()) + { + Assert.Null(oSpanEnumerator.Current); + } + + Assert.NotNull(spanObj[0, 0]); + Assert.NotNull(spanObj[0, 1]); + Assert.NotNull(spanObj[0, 2]); + Assert.Null(spanObj[1, 0]); + Assert.Null(spanObj[1, 1]); + Assert.Null(spanObj[1, 2]); + Assert.NotNull(spanObj[2, 0]); + Assert.NotNull(spanObj[2, 1]); + Assert.NotNull(spanObj[2, 2]); + + // Make sure clearing a slice of a SPan with references it doesn't clear the whole thing. + o = [new object(), new object(), new object(), new object(), new object(), new object(), new object(), new object(), new object()]; + spanObj = o.AsTensorSpan(3, 3); + oSpanSlice = spanObj.Slice(2..3, 0..3); + oSpanSlice.Clear(); + oSpanEnumerator = oSpanSlice.GetEnumerator(); + while (oSpanEnumerator.MoveNext()) + { + Assert.Null(oSpanEnumerator.Current); + } + + Assert.NotNull(spanObj[0, 0]); + Assert.NotNull(spanObj[0, 1]); + Assert.NotNull(spanObj[0, 2]); + Assert.NotNull(spanObj[1, 0]); + Assert.NotNull(spanObj[1, 1]); + Assert.NotNull(spanObj[1, 2]); + Assert.Null(spanObj[2, 0]); + Assert.Null(spanObj[2, 1]); + Assert.Null(spanObj[2, 2]); + } + + [Fact] + public static void TensorCopyTest() + { + int[] leftData = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + int[] rightData = new int[9]; + nint[] dims = [3, 3]; + TensorSpan leftSpan = leftData.AsTensorSpan(3, 3); + var tensor = Tensor.CreateUninitialized(dims.AsSpan(), false); + TensorSpan rightSpan = rightData.AsTensorSpan(3, 3); + leftSpan.CopyTo(tensor); + var leftEnum = leftSpan.GetEnumerator(); + var tensorEnum = tensor.GetEnumerator(); + while (leftEnum.MoveNext() && tensorEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, tensorEnum.Current); + } + tensor.CopyTo(rightSpan); + var rightEnum = rightSpan.GetEnumerator(); + tensorEnum = tensor.GetEnumerator(); + while (rightEnum.MoveNext() && tensorEnum.MoveNext()) + { + Assert.Equal(rightEnum.Current, tensorEnum.Current); + } + + //Make sure its a copy + leftSpan[0, 0] = 100; + Assert.NotEqual(leftSpan[0, 0], rightSpan[0, 0]); + Assert.NotEqual(leftSpan[0, 0], tensor[0, 0]); + + leftData = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + dims = [15]; + leftSpan = leftData.AsTensorSpan(9); + tensor = Tensor.Create(dims.AsSpan(), false); + leftSpan.CopyTo(tensor); + leftEnum = leftSpan.GetEnumerator(); + tensorEnum = tensor.GetEnumerator(); + // Make sure the first 9 spots are equal after copy + while (leftEnum.MoveNext() && tensorEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, tensorEnum.Current); + } + // The rest of the slots shouldn't have been touched. + while (tensorEnum.MoveNext()) + { + Assert.Equal(0, tensorEnum.Current); + } + + Assert.Throws(() => + { + var l = leftData.AsTensorSpan(3, 3, 3); + var r = new TensorSpan(); + l.CopyTo(r); + }); + } + + [Fact] + public static void TensorTryCopyTest() + { + int[] leftData = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + int[] rightData = new int[9]; + TensorSpan leftSpan = leftData.AsTensorSpan(3, 3); + nint[] dims = [3, 3]; + var tensor = Tensor.CreateUninitialized(dims.AsSpan(), false); + TensorSpan rightSpan = rightData.AsTensorSpan(3, 3); + var success = leftSpan.TryCopyTo(tensor); + Assert.True(success); + success = tensor.TryCopyTo(rightSpan); + Assert.True(success); + + var leftEnum = leftSpan.GetEnumerator(); + var tensorEnum = tensor.GetEnumerator(); + while (leftEnum.MoveNext() && tensorEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, tensorEnum.Current); + } + + //Make sure its a copy + leftSpan[0, 0] = 100; + Assert.NotEqual(leftSpan[0, 0], rightSpan[0, 0]); + Assert.NotEqual(leftSpan[0, 0], tensor[0, 0]); + + leftData = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + dims = [15]; + leftSpan = leftData.AsTensorSpan(9); + tensor = Tensor.Create(dims.AsSpan(), false); + success = leftSpan.TryCopyTo(tensor); + leftEnum = leftSpan.GetEnumerator(); + tensorEnum = tensor.GetEnumerator(); + Assert.True(success); + // Make sure the first 9 spots are equal after copy + while (leftEnum.MoveNext() && tensorEnum.MoveNext()) + { + Assert.Equal(leftEnum.Current, tensorEnum.Current); + } + // The rest of the slots shouldn't have been touched. + while (tensorEnum.MoveNext()) + { + Assert.Equal(0, tensorEnum.Current); + } + + leftData = [.. Enumerable.Range(0, 27)]; + var l = leftData.AsTensorSpan(3, 3, 3); + dims = [2, 2]; + tensor = Tensor.Create(dims.AsSpan(), false); + var r = new TensorSpan(); + success = l.TryCopyTo(tensor); + Assert.False(success); + success = tensor.TryCopyTo(r); + Assert.False(success); + } + + [Fact] + public static void TensorSliceTest() + { + int[] a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + var tensor = Tensor.CreateUninitialized([3, 3], false); + + //Assert.Throws(() => tensor.Slice(0..1)); + //Assert.Throws(() => tensor.Slice(1..2)); + //Assert.Throws(() => tensor.Slice(0..1, 5..6)); + var intSpan = a.AsTensorSpan(3, 3); + intSpan.CopyTo(tensor.AsTensorSpan()); + + var sp = tensor.Slice(1..3, 1..3); + Assert.Equal(5, sp[0, 0]); + Assert.Equal(6, sp[0, 1]); + Assert.Equal(8, sp[1, 0]); + Assert.Equal(9, sp[1, 1]); + int[] slice = [5, 6, 8, 9]; + Assert.Equal(slice, sp.ToArray()); + var enumerator = sp.GetEnumerator(); + var index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + sp = tensor.Slice(0..3, 0..3); + Assert.Equal(1, sp[0, 0]); + Assert.Equal(2, sp[0, 1]); + Assert.Equal(3, sp[0, 2]); + Assert.Equal(4, sp[1, 0]); + Assert.Equal(5, sp[1, 1]); + Assert.Equal(6, sp[1, 2]); + Assert.Equal(7, sp[2, 0]); + Assert.Equal(8, sp[2, 1]); + Assert.Equal(9, sp[2, 2]); + Assert.Equal(a, sp.ToArray()); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(a[index++], enumerator.Current); + } + + sp = tensor.Slice(0..1, 0..1); + Assert.Equal(1, sp[0, 0]); + Assert.Throws(() => a.AsTensorSpan(3, 3).Slice(0..1, 0..1)[0, 1]); + slice = [1]; + Assert.Equal(slice, sp.ToArray()); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + sp = tensor.Slice(0..2, 0..2); + Assert.Equal(1, sp[0, 0]); + Assert.Equal(2, sp[0, 1]); + Assert.Equal(4, sp[1, 0]); + Assert.Equal(5, sp[1, 1]); + slice = [1, 2, 4, 5]; + Assert.Equal(slice, sp.ToArray()); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + int[] numbers = [.. Enumerable.Range(0, 27)]; + intSpan = numbers.AsTensorSpan(3, 3, 3); + tensor = Tensor.CreateUninitialized([3, 3, 3], false); + intSpan.CopyTo(tensor.AsTensorSpan()); + sp = tensor.Slice(1..2, 1..2, 1..2); + Assert.Equal(13, sp[0, 0, 0]); + slice = [13]; + Assert.Equal(slice, sp.ToArray()); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + sp = tensor.Slice(1..3, 1..3, 1..3); + Assert.Equal(13, sp[0, 0, 0]); + Assert.Equal(14, sp[0, 0, 1]); + Assert.Equal(16, sp[0, 1, 0]); + Assert.Equal(17, sp[0, 1, 1]); + Assert.Equal(22, sp[1, 0, 0]); + Assert.Equal(23, sp[1, 0, 1]); + Assert.Equal(25, sp[1, 1, 0]); + Assert.Equal(26, sp[1, 1, 1]); + slice = [13, 14, 16, 17, 22, 23, 25, 26]; + Assert.Equal(slice, sp.ToArray()); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + + numbers = [.. Enumerable.Range(0, 16)]; + intSpan = numbers.AsTensorSpan(2, 2, 2, 2); + tensor = Tensor.CreateUninitialized([2, 2, 2, 2], false); + intSpan.CopyTo(tensor.AsTensorSpan()); + sp = tensor.Slice(1..2, 0..2, 1..2, 0..2); + Assert.Equal(10, sp[0, 0, 0, 0]); + Assert.Equal(11, sp[0, 0, 0, 1]); + Assert.Equal(14, sp[0, 1, 0, 0]); + Assert.Equal(15, sp[0, 1, 0, 1]); + slice = [10, 11, 14, 15]; + Assert.Equal(slice, sp.ToArray()); + enumerator = sp.GetEnumerator(); + index = 0; + while (enumerator.MoveNext()) + { + Assert.Equal(slice[index++], enumerator.Current); + } + } + + [Fact] + public static void TensorReshapeTest() + { + int[] a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + nint[] dims = [9]; + var tensor = Tensor.CreateUninitialized(dims.AsSpan(), false); + var span = a.AsTensorSpan(dims); + span.CopyTo(tensor); + + Assert.Equal(1, tensor.Rank); + Assert.Equal(9, tensor.Lengths[0]); + Assert.Equal(1, tensor.Strides.Length); + Assert.Equal(1, tensor.Strides[0]); + Assert.Equal(1, tensor[0]); + Assert.Equal(2, tensor[1]); + Assert.Equal(3, tensor[2]); + Assert.Equal(4, tensor[3]); + Assert.Equal(5, tensor[4]); + Assert.Equal(6, tensor[5]); + Assert.Equal(7, tensor[6]); + Assert.Equal(8, tensor[7]); + Assert.Equal(9, tensor[8]); + + dims = [3, 3]; + tensor = Tensor.Reshape(tensor, dims); + Assert.Equal(2, tensor.Rank); + Assert.Equal(3, tensor.Lengths[0]); + Assert.Equal(3, tensor.Lengths[1]); + Assert.Equal(2, tensor.Strides.Length); + Assert.Equal(3, tensor.Strides[0]); + Assert.Equal(1, tensor.Strides[1]); + Assert.Equal(1, tensor[0, 0]); + Assert.Equal(2, tensor[0, 1]); + Assert.Equal(3, tensor[0, 2]); + Assert.Equal(4, tensor[1, 0]); + Assert.Equal(5, tensor[1, 1]); + Assert.Equal(6, tensor[1, 2]); + Assert.Equal(7, tensor[2, 0]); + Assert.Equal(8, tensor[2, 1]); + Assert.Equal(9, tensor[2, 2]); + + Assert.Throws(() => Tensor.Reshape(tensor, [1, 2, 3, 4, 5])); + } + + [Fact] + public static void TensorSqueezeTest() + { + nint[] dims = [1, 2]; + var tensor = Tensor.Create(dims.AsSpan(), false); + Assert.Equal(2, tensor.Rank); + Assert.Equal(1, tensor.Lengths[0]); + Assert.Equal(2, tensor.Lengths[1]); + + tensor = Tensor.Squeeze(tensor); + Assert.Equal(1, tensor.Rank); + Assert.Equal(2, tensor.Lengths[0]); + + dims = [1, 2, 1]; + tensor = Tensor.Create(dims.AsSpan(), false); + Assert.Equal(3, tensor.Rank); + Assert.Equal(1, tensor.Lengths[0]); + Assert.Equal(2, tensor.Lengths[1]); + Assert.Equal(1, tensor.Lengths[2]); + + tensor = Tensor.Squeeze(tensor); + Assert.Equal(1, tensor.Rank); + Assert.Equal(2, tensor.Lengths[0]); + + dims = [1, 2, 1]; + tensor = Tensor.Create(dims.AsSpan(), false); + Assert.Equal(3, tensor.Rank); + Assert.Equal(1, tensor.Lengths[0]); + Assert.Equal(2, tensor.Lengths[1]); + Assert.Equal(1, tensor.Lengths[2]); + + tensor = Tensor.Squeeze(tensor, 0); + Assert.Equal(2, tensor.Rank); + Assert.Equal(2, tensor.Lengths[0]); + Assert.Equal(1, tensor.Lengths[1]); + + dims = [1, 2, 1]; + tensor = Tensor.Create(dims.AsSpan(), false); + Assert.Equal(3, tensor.Rank); + Assert.Equal(1, tensor.Lengths[0]); + Assert.Equal(2, tensor.Lengths[1]); + Assert.Equal(1, tensor.Lengths[2]); + + tensor = Tensor.Squeeze(tensor, 2); + Assert.Equal(2, tensor.Rank); + Assert.Equal(1, tensor.Lengths[0]); + Assert.Equal(2, tensor.Lengths[1]); + + dims = [1, 2, 1]; + tensor = Tensor.Create(dims.AsSpan(), false); + Assert.Equal(3, tensor.Rank); + Assert.Equal(1, tensor.Lengths[0]); + Assert.Equal(2, tensor.Lengths[1]); + Assert.Equal(1, tensor.Lengths[2]); + + Assert.Throws(() => tensor = Tensor.Squeeze(tensor, 1)); + Assert.Throws(() => tensor = Tensor.Squeeze(tensor, 3)); + } + + [Fact] + public static void TensorUnsqueezeTest() + { + var tensor = Tensor.Create([2], false); + Assert.Equal(1, tensor.Rank); + Assert.Equal(2, tensor.Lengths[0]); + + tensor = Tensor.Unsqueeze(tensor, 0); + Assert.Equal(2, tensor.Rank); + Assert.Equal(1, tensor.Lengths[0]); + Assert.Equal(2, tensor.Lengths[1]); + + tensor = Tensor.Create([2], false); + Assert.Equal(1, tensor.Rank); + Assert.Equal(2, tensor.Lengths[0]); + + tensor = Tensor.Unsqueeze(tensor, 1); + Assert.Equal(2, tensor.Rank); + Assert.Equal(2, tensor.Lengths[0]); + Assert.Equal(1, tensor.Lengths[1]); + + tensor = Tensor.Create([2], false); + Assert.Equal(1, tensor.Rank); + Assert.Equal(2, tensor.Lengths[0]); + + Assert.Throws(() => Tensor.Unsqueeze(tensor, -1)); + Assert.Throws(() => Tensor.Unsqueeze(tensor, 2)); + + Tensor t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 2)); + t0 = Tensor.Unsqueeze(t0, 1); + Assert.Equal(0, t0[0, 0]); + Assert.Equal(1, t0[1, 0]); + } + } +} diff --git a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs index 8bf4cb6c5348..98b2db5e1336 100644 --- a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs +++ b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs @@ -235,14 +235,20 @@ public static partial class Vector [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector ConvertToDouble(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector ConvertToInt32(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ConvertToInt32Native(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector ConvertToInt64(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ConvertToInt64Native(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector ConvertToSingle(System.Numerics.Vector value) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector ConvertToSingle(System.Numerics.Vector value) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector ConvertToUInt32(System.Numerics.Vector value) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Numerics.Vector ConvertToUInt32Native(System.Numerics.Vector value) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector ConvertToUInt64(System.Numerics.Vector value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Numerics.Vector ConvertToUInt64Native(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector CreateSequence(T start, T step) { throw null; } public static System.Numerics.Vector Divide(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Divide(System.Numerics.Vector left, T right) { throw null; } @@ -256,6 +262,8 @@ public static partial class Vector public static System.Numerics.Vector Equals(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Floor(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector Floor(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector FusedMultiplyAdd(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector addend) { throw null; } + public static System.Numerics.Vector FusedMultiplyAdd(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector addend) { throw null; } public static T GetElement(this System.Numerics.Vector vector, int index) { throw null; } public static System.Numerics.Vector GreaterThan(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector GreaterThan(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -301,6 +309,8 @@ public static partial class Vector public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Multiply(System.Numerics.Vector left, T right) { throw null; } public static System.Numerics.Vector Multiply(T left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplyAddEstimate(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector addend) { throw null; } + public static System.Numerics.Vector MultiplyAddEstimate(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector addend) { throw null; } public static System.Numerics.Vector Narrow(System.Numerics.Vector low, System.Numerics.Vector high) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector Narrow(System.Numerics.Vector low, System.Numerics.Vector high) { throw null; } @@ -427,6 +437,7 @@ public readonly void CopyTo(System.Span destination) { } public static float Dot(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } public readonly bool Equals(System.Numerics.Vector2 other) { throw null; } public override readonly bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public static System.Numerics.Vector2 FusedMultiplyAdd(System.Numerics.Vector2 left, System.Numerics.Vector2 right, System.Numerics.Vector2 addend) { throw null; } public override readonly int GetHashCode() { throw null; } public readonly float Length() { throw null; } public readonly float LengthSquared() { throw null; } @@ -436,6 +447,7 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector2 Multiply(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } public static System.Numerics.Vector2 Multiply(System.Numerics.Vector2 left, float right) { throw null; } public static System.Numerics.Vector2 Multiply(float left, System.Numerics.Vector2 right) { throw null; } + public static System.Numerics.Vector2 MultiplyAddEstimate(System.Numerics.Vector2 left, System.Numerics.Vector2 right, System.Numerics.Vector2 addend) { throw null; } public static System.Numerics.Vector2 Negate(System.Numerics.Vector2 value) { throw null; } public static System.Numerics.Vector2 Normalize(System.Numerics.Vector2 value) { throw null; } public static System.Numerics.Vector2 operator +(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } @@ -490,6 +502,7 @@ public readonly void CopyTo(System.Span destination) { } public static float Dot(System.Numerics.Vector3 vector1, System.Numerics.Vector3 vector2) { throw null; } public readonly bool Equals(System.Numerics.Vector3 other) { throw null; } public override readonly bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public static System.Numerics.Vector3 FusedMultiplyAdd(System.Numerics.Vector3 left, System.Numerics.Vector3 right, System.Numerics.Vector3 addend) { throw null; } public override readonly int GetHashCode() { throw null; } public readonly float Length() { throw null; } public readonly float LengthSquared() { throw null; } @@ -499,6 +512,7 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector3 Multiply(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } public static System.Numerics.Vector3 Multiply(System.Numerics.Vector3 left, float right) { throw null; } public static System.Numerics.Vector3 Multiply(float left, System.Numerics.Vector3 right) { throw null; } + public static System.Numerics.Vector3 MultiplyAddEstimate(System.Numerics.Vector3 left, System.Numerics.Vector3 right, System.Numerics.Vector3 addend) { throw null; } public static System.Numerics.Vector3 Negate(System.Numerics.Vector3 value) { throw null; } public static System.Numerics.Vector3 Normalize(System.Numerics.Vector3 value) { throw null; } public static System.Numerics.Vector3 operator +(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } @@ -553,6 +567,7 @@ public readonly void CopyTo(System.Span destination) { } public static float Dot(System.Numerics.Vector4 vector1, System.Numerics.Vector4 vector2) { throw null; } public readonly bool Equals(System.Numerics.Vector4 other) { throw null; } public override readonly bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public static System.Numerics.Vector4 FusedMultiplyAdd(System.Numerics.Vector4 left, System.Numerics.Vector4 right, System.Numerics.Vector4 addend) { throw null; } public override readonly int GetHashCode() { throw null; } public readonly float Length() { throw null; } public readonly float LengthSquared() { throw null; } @@ -562,6 +577,7 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector4 Multiply(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } public static System.Numerics.Vector4 Multiply(System.Numerics.Vector4 left, float right) { throw null; } public static System.Numerics.Vector4 Multiply(float left, System.Numerics.Vector4 right) { throw null; } + public static System.Numerics.Vector4 MultiplyAddEstimate(System.Numerics.Vector4 left, System.Numerics.Vector4 right, System.Numerics.Vector4 addend) { throw null; } public static System.Numerics.Vector4 Negate(System.Numerics.Vector4 value) { throw null; } public static System.Numerics.Vector4 Normalize(System.Numerics.Vector4 vector) { throw null; } public static System.Numerics.Vector4 operator +(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } diff --git a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs index 367d2f966996..02c7d3fa8a87 100644 --- a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs @@ -8,6 +8,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; +using System.Runtime.Intrinsics.Tests.Vectors; using Xunit; using Xunit.Sdk; @@ -19,6 +20,32 @@ namespace System.Numerics.Tests [RequiresPreviewFeatures] public unsafe class GenericVectorTests { + /// Verifies that two values are equal, within the . + /// The expected value + /// The value to be compared against + /// The total variance allowed between the expected and actual results. + /// Thrown when the values are not equal + internal static void AssertEqual(Vector expected, Vector actual, Vector variance) + { + for (int i = 0; i < Vector.Count; i++) + { + AssertExtensions.Equal(expected.GetElement(i), actual.GetElement(i), variance.GetElement(i)); + } + } + + /// Verifies that two values are equal, within the . + /// The expected value + /// The value to be compared against + /// The total variance allowed between the expected and actual results. + /// Thrown when the values are not equal + internal static void AssertEqual(Vector expected, Vector actual, Vector variance) + { + for (int i = 0; i < Vector.Count; i++) + { + AssertExtensions.Equal(expected.GetElement(i), actual.GetElement(i), variance.GetElement(i)); + } + } + // Static constructor in top-level class\ static System.Numerics.Vector dummy; static GenericVectorTests() @@ -3164,7 +3191,7 @@ public void ConvertSingleToInt32() Vector targetVec = Vector.ConvertToInt32(sourceVec); for (int i = 0; i < Vector.Count; i++) { - Assert.Equal(unchecked((int)source[i]), targetVec[i]); + Assert.Equal(float.ConvertToInteger(source[i]), targetVec[i]); } } @@ -3176,7 +3203,7 @@ public void ConvertSingleToUInt32() Vector targetVec = Vector.ConvertToUInt32(sourceVec); for (int i = 0; i < Vector.Count; i++) { - Assert.Equal(unchecked((uint)source[i]), targetVec[i]); + Assert.Equal(float.ConvertToInteger(source[i]), targetVec[i]); } } @@ -3188,7 +3215,7 @@ public void ConvertDoubleToInt64() Vector targetVec = Vector.ConvertToInt64(sourceVec); for (int i = 0; i < Vector.Count; i++) { - Assert.Equal(unchecked((long)source[i]), targetVec[i]); + Assert.Equal(double.ConvertToInteger(source[i]), targetVec[i]); } } @@ -3200,7 +3227,7 @@ public void ConvertDoubleToUInt64() Vector targetVec = Vector.ConvertToUInt64(sourceVec); for (int i = 0; i < Vector.Count; i++) { - Assert.Equal(unchecked((ulong)source[i]), targetVec[i]); + Assert.Equal(double.ConvertToInteger(source[i]), targetVec[i]); } } @@ -4508,5 +4535,37 @@ private static void TestCreateSequence(T start, T step) expected += step; } } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] + public void FusedMultiplyAddDoubleTest(double left, double right, double addend) + { + Vector actualResult = Vector.FusedMultiplyAdd(new Vector(left), new Vector(right), new Vector(addend)); + AssertEqual(new Vector(double.FusedMultiplyAdd(left, right, addend)), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend) + { + Vector actualResult = Vector.FusedMultiplyAdd(new Vector(left), new Vector(right), new Vector(addend)); + AssertEqual(new Vector(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] + public void MultiplyAddEstimateDoubleTest(double left, double right, double addend) + { + Vector actualResult = Vector.MultiplyAddEstimate(new Vector(left), new Vector(right), new Vector(addend)); + AssertEqual(new Vector(double.MultiplyAddEstimate(left, right, addend)), actualResult, Vector.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void MultiplyAddEstimateSingleTest(float left, float right, float addend) + { + Vector actualResult = Vector.MultiplyAddEstimate(new Vector(left), new Vector(right), new Vector(addend)); + AssertEqual(new Vector(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector.Zero); + } } } diff --git a/src/libraries/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj b/src/libraries/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj index 264fb0fe340d..243d1490ced0 100644 --- a/src/libraries/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj +++ b/src/libraries/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj @@ -18,5 +18,6 @@ + diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs index 6bb05504afb8..853ad86480b1 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs @@ -3,12 +3,24 @@ using System.Globalization; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.Tests.Vectors; using Xunit; namespace System.Numerics.Tests { public sealed class Vector2Tests { + /// Verifies that two values are equal, within the . + /// The expected value + /// The value to be compared against + /// The total variance allowed between the expected and actual results. + /// Thrown when the values are not equal + internal static void AssertEqual(Vector2 expected, Vector2 actual, Vector2 variance) + { + AssertExtensions.Equal(expected.X, actual.X, variance.X); + AssertExtensions.Equal(expected.Y, actual.Y, variance.Y); + } + [Fact] public void Vector2MarshalSizeTest() { @@ -1286,5 +1298,21 @@ private class EmbeddedVectorObject { public Vector2 FieldVector; } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend) + { + Vector2 actualResult = Vector2.FusedMultiplyAdd(new Vector2(left), new Vector2(right), new Vector2(addend)); + AssertEqual(new Vector2(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector2.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void MultiplyAddEstimateSingleTest(float left, float right, float addend) + { + Vector2 actualResult = Vector2.MultiplyAddEstimate(new Vector2(left), new Vector2(right), new Vector2(addend)); + AssertEqual(new Vector2(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector2.Zero); + } } } diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs index dc310461b616..235d8b08c431 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs @@ -3,12 +3,25 @@ using System.Globalization; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.Tests.Vectors; using Xunit; namespace System.Numerics.Tests { public sealed class Vector3Tests { + /// Verifies that two values are equal, within the . + /// The expected value + /// The value to be compared against + /// The total variance allowed between the expected and actual results. + /// Thrown when the values are not equal + internal static void AssertEqual(Vector3 expected, Vector3 actual, Vector3 variance) + { + AssertExtensions.Equal(expected.X, actual.X, variance.X); + AssertExtensions.Equal(expected.Y, actual.Y, variance.Y); + AssertExtensions.Equal(expected.Z, actual.Z, variance.Z); + } + [Fact] public void Vector3MarshalSizeTest() { @@ -1335,5 +1348,21 @@ private class EmbeddedVectorObject { public Vector3 FieldVector; } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend) + { + Vector3 actualResult = Vector3.FusedMultiplyAdd(new Vector3(left), new Vector3(right), new Vector3(addend)); + AssertEqual(new Vector3(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector3.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void MultiplyAddEstimateSingleTest(float left, float right, float addend) + { + Vector3 actualResult = Vector3.MultiplyAddEstimate(new Vector3(left), new Vector3(right), new Vector3(addend)); + AssertEqual(new Vector3(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector3.Zero); + } } } diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs index 68a0878476d8..041663f41443 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs @@ -3,12 +3,26 @@ using System.Globalization; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.Tests.Vectors; using Xunit; namespace System.Numerics.Tests { public sealed class Vector4Tests { + /// Verifies that two values are equal, within the . + /// The expected value + /// The value to be compared against + /// The total variance allowed between the expected and actual results. + /// Thrown when the values are not equal + internal static void AssertEqual(Vector4 expected, Vector4 actual, Vector4 variance) + { + AssertExtensions.Equal(expected.X, actual.X, variance.X); + AssertExtensions.Equal(expected.Y, actual.Y, variance.Y); + AssertExtensions.Equal(expected.Z, actual.Z, variance.Z); + AssertExtensions.Equal(expected.W, actual.W, variance.W); + } + [Fact] public void Vector4MarshalSizeTest() { @@ -1709,5 +1723,21 @@ public struct Level7 } } #pragma warning restore 0169 + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend) + { + Vector4 actualResult = Vector4.FusedMultiplyAdd(new Vector4(left), new Vector4(right), new Vector4(addend)); + AssertEqual(new Vector4(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector4.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void MultiplyAddEstimateSingleTest(float left, float right, float addend) + { + Vector4 actualResult = Vector4.MultiplyAddEstimate(new Vector4(left), new Vector4(right), new Vector4(addend)); + AssertEqual(new Vector4(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector4.Zero); + } } } diff --git a/src/libraries/System.ObjectModel/src/System.ObjectModel.csproj b/src/libraries/System.ObjectModel/src/System.ObjectModel.csproj index 1a8f23c29c49..0ef93fda9ecd 100644 --- a/src/libraries/System.ObjectModel/src/System.ObjectModel.csproj +++ b/src/libraries/System.ObjectModel/src/System.ObjectModel.csproj @@ -33,6 +33,7 @@ + diff --git a/src/libraries/System.ObjectModel/tests/ObservableCollection/ObservableCollection_Serialization.cs b/src/libraries/System.ObjectModel/tests/ObservableCollection/ObservableCollection_Serialization.cs index ad46a712462f..22179a67a512 100644 --- a/src/libraries/System.ObjectModel/tests/ObservableCollection/ObservableCollection_Serialization.cs +++ b/src/libraries/System.ObjectModel/tests/ObservableCollection/ObservableCollection_Serialization.cs @@ -28,6 +28,7 @@ public void SerializeDeserialize_Roundtrips(ObservableCollection c) [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/57588", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/57588", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsAppleMobile))] public void OnDeserialized_MonitorNotInitialized_ExpectSuccess() { var observableCollection = new ObservableCollection(); diff --git a/src/libraries/System.Private.CoreLib/Tools/GenUnicodeProp/Updating-Unicode-Versions.md b/src/libraries/System.Private.CoreLib/Tools/GenUnicodeProp/Updating-Unicode-Versions.md index 03e0dd016e8d..7a9087f4134e 100644 --- a/src/libraries/System.Private.CoreLib/Tools/GenUnicodeProp/Updating-Unicode-Versions.md +++ b/src/libraries/System.Private.CoreLib/Tools/GenUnicodeProp/Updating-Unicode-Versions.md @@ -41,7 +41,7 @@ This should be done automatically by dependency-flow, so in theory there shouldn - System.Globalization.Tests.csproj - System.Globalization.Nls.Tests.csproj - System.Text.Encodings.Web.Tests.csproj -4. If the new Unicode data contains casing changes/updates, then we will also need to update `src/coreclr/pal/src/locale/unicodedata.cpp` file. This file is used by most of the reflection stack whenever you specify the `BindingFlags.IgnoreCase`. In order to regenerate the contents of the `unicdedata.cpp` file, you need to run the Program located at `src/coreclr/pal/src/locale/unicodedata.cs` and give a full path to the new UnicodeData.txt as a parameter. +4. If the new Unicode data contains casing changes/updates, then we will also need to update `src/native/minipal/UnicodeDataGenerator/unicodedata.c` file. This file is used by most of the reflection stack whenever you specify the `BindingFlags.IgnoreCase`. In order to regenerate the contents of the `unicdedata.c` file, you need to run the Program located at `src/native/minipal/UnicodeDataGenerator/unicodedata.cs` and give a full path to the new UnicodeData.txt as a parameter. 5. Update the Regex casing equivalence table using the UnicodeData.txt file from the new Unicode version. You can find the instructions on how to do this [here](../../../System.Text.RegularExpressions/tools/Readme.md). 6. Finally, last step is to update the license for the Unicode data into our [Third party notices](../../../../../THIRD-PARTY-NOTICES.TXT) by copying the contents located in `https://www.unicode.org/license.html` to the section that has the Unicode license in our notices. 7. That's it, now commit all of the changed files, and send a PR into dotnet/runtime with the updates. If there were any special things you had to do that are not noted on this document, PLEASE UPDATE THESE INSTRUCTIONS to facilitate future updates. diff --git a/src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs b/src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs new file mode 100644 index 000000000000..fbf8cb48a3a9 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Reflection; +using Microsoft.CodeAnalysis; + +namespace Generators +{ + [Generator] + public partial class ProductVersionInfoGenerator : IIncrementalGenerator + { + public void Initialize(IncrementalGeneratorInitializationContext context) + { + context.RegisterPostInitializationOutput(ctx => + { + string? informationalVersion = typeof(ProductVersionInfoGenerator).Assembly.GetCustomAttribute()?.InformationalVersion; + + // strip semver metadata (git hash) followed by + sign + string? productVersion = informationalVersion?.Split('+')?[0]; + + if (string.IsNullOrEmpty(productVersion)) + throw new InvalidOperationException($"Unable to obtain product version at build-time."); + + // strip semver prerelease label followed by - sign for Environment.Version + Version versionObject = Version.Parse(productVersion.Split('-')[0]); + + ctx.AddSource("ProductVersionInfo.g.cs", $@"// + +namespace System +{{ + public static partial class Environment + {{ + /// + /// Gets a version consisting of the major, minor, build, and revision numbers of the common language runtime. + /// + public static Version Version => new Version({versionObject.ToString().Replace(".", ", ")}); + }} +}} + +namespace System.Runtime.InteropServices +{{ + public static partial class RuntimeInformation + {{ + /// + /// Gets the name of the .NET installation on which an app is running. + /// + public static string FrameworkDescription => "".NET {productVersion}""; + }} +}}"); + }); + } + } +} diff --git a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj index fa1603a00910..ff92d663d01c 100644 --- a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj +++ b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj @@ -5,6 +5,7 @@ + @@ -20,4 +21,5 @@ + diff --git a/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ManualShimTypeForwards.cs b/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ManualShimTypeForwards.cs index 0a93320ccff1..ab8473216cd8 100644 --- a/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ManualShimTypeForwards.cs +++ b/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ManualShimTypeForwards.cs @@ -65,7 +65,7 @@ public ByteEqualityComparer() { } public override int GetHashCode() { throw null; } public override int GetHashCode(byte b) { throw null; } } - public sealed partial class EnumEqualityComparer : System.Collections.Generic.EqualityComparer, System.Runtime.Serialization.ISerializable where T : struct + public sealed partial class EnumEqualityComparer : System.Collections.Generic.EqualityComparer, System.Runtime.Serialization.ISerializable where T : struct, System.Enum { public EnumEqualityComparer() { } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } diff --git a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.Shared.xml b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.Shared.xml index a152f063f51c..5561632ceaaa 100644 --- a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.Shared.xml +++ b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.Shared.xml @@ -2,6 +2,7 @@ + @@ -10,6 +11,7 @@ to be trimmed when Invariant=true, and allows for the Settings static cctor (on Unix) to be preserved when Invariant=false. --> + diff --git a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.LibraryBuild.xml b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.LibraryBuild.xml index 278ed933f070..c0523c4d646d 100644 --- a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.LibraryBuild.xml +++ b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.LibraryBuild.xml @@ -22,5 +22,12 @@ M:System.StartupHookProvider.ProcessStartupHooks(System.String) This warning is left in the product so developers get an ILLink warning when trimming an app with System.StartupHookProvider.IsSupported=true. + + ILLink + IL2026 + member + M:System.ComponentModel.DefaultValueAttribute.#ctor(System.Type,System.String) + This warning is left in the product so developers get an ILLink warning when trimming an app with System.ComponentModel.DefaultValueAttribute.IsSupported=true. + diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 2bc7699526df..c4504f140527 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -4316,4 +4316,7 @@ Blocking wait is not supported on the JS interop threads. + + Emitting debug info is not supported for this member. + diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 61e511427510..f17e5ee1f916 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -4,8 +4,6 @@ c5ed3c1d-b572-46f1-8f96-522a85ce1179 System.Private.CoreLib.Strings true - - true @@ -50,7 +48,6 @@ $(DefineConstants);TARGET_HAIKU - @@ -133,6 +130,7 @@ + @@ -434,6 +432,7 @@ + @@ -444,7 +443,7 @@ - + @@ -648,9 +647,7 @@ - - @@ -779,6 +776,7 @@ + @@ -877,6 +875,7 @@ + @@ -1266,6 +1265,7 @@ + @@ -1424,6 +1424,9 @@ Common\System\LocalAppContextSwitches.Common.cs + + Common\System\HexConverter.cs + Common\System\HResults.cs @@ -1472,8 +1475,26 @@ Common\System\IO\PathInternal.CaseSensitivity.cs - - Common\System\Reflection\TypeNameParser.cs + + Common\System\Reflection\AssemblyNameParser.cs + + + Common\System\Reflection\AssemblyNameFormatter.cs + + + Common\System\Reflection\Metadata\AssemblyNameInfo.cs + + + Common\System\Reflection\Metadata\TypeName.cs + + + Common\System\Reflection\Metadata\TypeNameHelpers.cs + + + Common\System\Reflection\Metadata\TypeNameParser.cs + + + Common\System\Reflection\Metadata\TypeNameParserHelpers.cs Common\System\Runtime\Versioning\NonVersionableAttribute.cs @@ -1578,11 +1599,6 @@ - - - Common\System\HexConverter.cs - - Common\Interop\Windows\Advapi32\Interop.EncryptDecrypt.cs @@ -2070,6 +2086,9 @@ Common\Interop\Windows\OleAut32\Interop.SysFreeString.cs + + Common\Interop\Windows\OleAut32\Interop.VariantChangeTypeEx.cs + Common\Interop\Windows\Ole32\Interop.CLSIDFromProgID.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs index b59a7bdcc372..d0ab3305bfd4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs @@ -141,7 +141,17 @@ public static void SetSwitch(string switchName, bool isEnabled) } } -#if !NATIVEAOT +#if MONO + internal static unsafe void Setup(char** pNames, uint* pNameLengths, char** pValues, uint* pValueLengths, int count) + { + Debug.Assert(s_dataStore == null, "s_dataStore is not expected to be inited before Setup is called"); + s_dataStore = new Dictionary(count); + for (int i = 0; i < count; i++) + { + s_dataStore.Add(new string(pNames[i], 0, (int)pNameLengths[i]), new string(pValues[i], 0, (int)pValueLengths[i])); + } + } +#elif !NATIVEAOT internal static unsafe void Setup(char** pNames, char** pValues, int count) { Debug.Assert(s_dataStore == null, "s_dataStore is not expected to be inited before Setup is called"); diff --git a/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs b/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs index b07429f409cb..2849756d131b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs @@ -414,8 +414,7 @@ public void SetThreadPrincipal(IPrincipal principal) Debug.Assert(mi != null); // Don't throw PNSE if null like for WindowsPrincipal as UnauthenticatedPrincipal should // be available on all platforms. - Volatile.Write(ref s_getUnauthenticatedPrincipal, - mi.CreateDelegate>()); + s_getUnauthenticatedPrincipal = mi.CreateDelegate>(); } principal = s_getUnauthenticatedPrincipal(); @@ -430,8 +429,7 @@ public void SetThreadPrincipal(IPrincipal principal) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_Principal); } - Volatile.Write(ref s_getWindowsPrincipal, - mi.CreateDelegate>()); + s_getWindowsPrincipal = mi.CreateDelegate>(); } principal = s_getWindowsPrincipal(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffer.cs b/src/libraries/System.Private.CoreLib/src/System/Buffer.cs index 24f8794d852a..25b6965ee2d1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffer.cs @@ -62,7 +62,7 @@ public static int ByteLength(Array array) nuint byteLength = array.NativeLength * (nuint)array.GetElementSize(); - // This API is explosed both as Buffer.ByteLength and also used indirectly in argument + // This API is exposed both as Buffer.ByteLength and also used indirectly in argument // checks for Buffer.GetByte/SetByte. // // If somebody called Get/SetByte on 2GB+ arrays, there is a decent chance that @@ -177,6 +177,9 @@ ref Unsafe.As(ref source), private const uint BulkMoveWithWriteBarrierChunk = 0x4000; #endif +#if NATIVEAOT + [System.Runtime.RuntimeExport("RhBuffer_BulkMoveWithWriteBarrier")] +#endif internal static void BulkMoveWithWriteBarrier(ref byte destination, ref byte source, nuint byteCount) { if (byteCount <= BulkMoveWithWriteBarrierChunk) diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/SharedArrayPool.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/SharedArrayPool.cs index 89bbd4504523..3fa044d074d6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/SharedArrayPool.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/SharedArrayPool.cs @@ -40,10 +40,7 @@ internal sealed partial class SharedArrayPool : ArrayPool /// Allocate a new and try to store it into the array. private unsafe SharedArrayPoolPartitions CreatePerCorePartitions(int bucketIndex) { -#pragma warning disable 8500 // sizeof of managed types - int elementSize = sizeof(T); -#pragma warning restore 8500 - var inst = new SharedArrayPoolPartitions(elementSize); + var inst = new SharedArrayPoolPartitions(); return Interlocked.CompareExchange(ref _buckets[bucketIndex], inst, null) ?? inst; } @@ -199,7 +196,7 @@ public bool Trim() SharedArrayPoolPartitions?[] perCoreBuckets = _buckets; for (int i = 0; i < perCoreBuckets.Length; i++) { - perCoreBuckets[i]?.Trim(currentMilliseconds, Id, pressure, Utilities.GetMaxSizeForBucket(i)); + perCoreBuckets[i]?.Trim(currentMilliseconds, Id, pressure); } // Trim each of the TLS buckets. Note that threads may be modifying their TLS slots concurrently with @@ -323,14 +320,13 @@ internal sealed class SharedArrayPoolPartitions private readonly Partition[] _partitions; /// Initializes the partitions. - /// The size of the elements stored in arrays. - public SharedArrayPoolPartitions(int elementSize) + public SharedArrayPoolPartitions() { // Create the partitions. We create as many as there are processors, limited by our max. var partitions = new Partition[SharedArrayPoolStatics.s_partitionCount]; for (int i = 0; i < partitions.Length; i++) { - partitions[i] = new Partition(elementSize); + partitions[i] = new Partition(); } _partitions = partitions; } @@ -374,23 +370,20 @@ public bool TryPush(Array array) return null; } - public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure pressure, int bucketSize) + public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure pressure) { Partition[] partitions = _partitions; for (int i = 0; i < partitions.Length; i++) { - partitions[i].Trim(currentMilliseconds, id, pressure, bucketSize); + partitions[i].Trim(currentMilliseconds, id, pressure); } } /// Provides a simple, bounded stack of arrays, protected by a lock. - /// The size of the elements stored in arrays. - private sealed class Partition(int elementSize) + private sealed class Partition { /// The arrays in the partition. private readonly Array?[] _arrays = new Array[SharedArrayPoolStatics.s_maxArraysPerPartition]; - /// The size of the elements stored in arrays. - private readonly int _elementSize = elementSize; /// Number of arrays stored in . private int _count; /// Timestamp set by Trim when it sees this as 0. @@ -437,20 +430,11 @@ public bool TryPush(Array array) return arr; } - public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure pressure, int bucketSize) + public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure pressure) { const int TrimAfterMS = 60 * 1000; // Trim after 60 seconds for low/moderate pressure const int HighTrimAfterMS = 10 * 1000; // Trim after 10 seconds for high pressure - const int LargeBucket = 16384; // If the bucket is larger than this we'll trim an extra when under high pressure - - const int ModerateTypeSize = 16; // If T is larger than this we'll trim an extra when under high pressure - const int LargeTypeSize = 32; // If T is larger than this we'll trim an extra (additional) when under high pressure - - const int LowTrimCount = 1; // Trim one item when pressure is low - const int MediumTrimCount = 2; // Trim two items when pressure is moderate - int HighTrimCount = SharedArrayPoolStatics.s_maxArraysPerPartition; // Trim all items when pressure is high - if (_count == 0) { return; @@ -477,38 +461,16 @@ public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure press } // We've elapsed enough time since the first item went into the partition. - // Drop the top item so it can be collected and make the partition look a little newer. + // Drop the top item(s) so they can be collected. - ArrayPoolEventSource log = ArrayPoolEventSource.Log; - int trimCount = LowTrimCount; - switch (pressure) + int trimCount = pressure switch { - case Utilities.MemoryPressure.High: - trimCount = HighTrimCount; - - // When pressure is high, aggressively trim larger arrays. - if (bucketSize > LargeBucket) - { - trimCount++; - } - - if (_elementSize > ModerateTypeSize) - { - trimCount++; - - if (_elementSize > LargeTypeSize) - { - trimCount++; - } - } - - break; - - case Utilities.MemoryPressure.Medium: - trimCount = MediumTrimCount; - break; - } + Utilities.MemoryPressure.High => SharedArrayPoolStatics.s_maxArraysPerPartition, + Utilities.MemoryPressure.Medium => 2, + _ => 1, + }; + ArrayPoolEventSource log = ArrayPoolEventSource.Log; while (_count > 0 && trimCount-- > 0) { Array? array = _arrays[--_count]; diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Decoder.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Decoder.cs index 1ad2cf9faa9f..777736e4a4de 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Decoder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Decoder.cs @@ -90,6 +90,17 @@ private static unsafe OperationStatus DecodeFromUtf8(ReadOnlySpan utf8, Sp } } + end = srcMax - 66; + if (AdvSimd.Arm64.IsSupported && (end >= src)) + { + AdvSimdDecode(ref src, ref dest, end, maxSrcLength, destLength, srcBytes, destBytes); + + if (src == srcEnd) + { + goto DoneExit; + } + } + end = srcMax - 24; if ((Ssse3.IsSupported || AdvSimd.Arm64.IsSupported) && BitConverter.IsLittleEndian && (end >= src)) { @@ -844,6 +855,141 @@ private static Vector128 SimdShuffle(Vector128 left, Vector128 return Vector128.ShuffleUnsafe(left, right); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] + private static unsafe void AdvSimdDecode(ref byte* srcBytes, ref byte* destBytes, byte* srcEnd, int sourceLength, int destLength, byte* srcStart, byte* destStart) + { + // C# implementation of https://github.com/aklomp/base64/blob/3a5add8652076612a8407627a42c768736a4263f/lib/arch/neon64/dec_loop.c + // If we have AdvSimd support, pick off 64 bytes at a time for as long as we can, + // but make sure that we quit before seeing any == markers at the end of the + // string. 64 + 2 = 66 bytes. + + // In the decoding process, we want to map each byte, representing a Base64 value, to its 6-bit (0-63) representation. + // It uses the following mapping. Values outside the following groups are invalid and, we abort decoding when encounter one. + // + // # From To Char + // 1 [43] [62] + + // 2 [47] [63] / + // 3 [48..57] [52..61] 0..9 + // 4 [65..90] [0..25] A..Z + // 5 [97..122] [26..51] a..z + // + // To map an input value to its Base64 representation, we use look-up tables 'decLutOne' and 'decLutTwo'. + // 'decLutOne' helps to map groups 1, 2 and 3 while 'decLutTwo' maps groups 4 and 5 in the above list. + // After mapping, each value falls between 0-63. Consequently, the last six bits of each byte now hold a valid value. + // We then compress four such bytes (with valid 4 * 6 = 24 bits) to three UTF8 bytes (3 * 8 = 24 bits). + // For faster decoding, we use SIMD operations that allow the processing of multiple bytes together. + // However, the compress operation on adjacent values of a vector could be slower. Thus, we de-interleave while reading + // the input bytes that store adjacent bytes in separate vectors. This later simplifies the compress step with the help + // of logical operations. This requires interleaving while storing the decoded result. + + // Values in 'decLutOne' maps input values from 0 to 63. + // 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 + // 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 + // 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63 + // 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255 + var decLutOne = (Vector128.AllBitsSet, + Vector128.AllBitsSet, + Vector128.Create(0xFFFFFFFF, 0xFFFFFFFF, 0x3EFFFFFF, 0x3FFFFFFF).AsByte(), + Vector128.Create(0x37363534, 0x3B3A3938, 0xFFFF3D3C, 0xFFFFFFFF).AsByte()); + + // Values in 'decLutTwo' maps input values from 63 to 127. + // 0, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 + // 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255 + // 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 + // 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255 + var decLutTwo = (Vector128.Create(0x0100FF00, 0x05040302, 0x09080706, 0x0D0C0B0A).AsByte(), + Vector128.Create(0x11100F0E, 0x15141312, 0x19181716, 0xFFFFFFFF).AsByte(), + Vector128.Create(0x1B1AFFFF, 0x1F1E1D1C, 0x23222120, 0x27262524).AsByte(), + Vector128.Create(0x2B2A2928, 0x2F2E2D2C, 0x33323130, 0xFFFFFFFF).AsByte()); + + byte* src = srcBytes; + byte* dest = destBytes; + Vector128 offset = Vector128.Create(63); + + do + { + // Step 1: Load 64 bytes and de-interleave. + AssertRead>(src, srcStart, sourceLength); + var (str1, str2, str3, str4) = AdvSimd.Arm64.LoadVector128x4AndUnzip(src); + + // Step 2: Map each valid input to its Base64 value. + // We use two look-ups to compute partial results and combine them later. + + // Step 2.1: Detect valid Base64 values from the first three groups. Maps input as, + // 0 to 63 (Invalid) => 255 + // 0 to 63 (Valid) => Their Base64 equivalent + // 64 to 255 => 0 + + // Each input value acts as an index in the look-up table 'decLutOne'. + // e.g., for group 1: index 43 maps to 62 (Base64 '+'). + // Group 4 and 5 values are out-of-range (>64), so they are mapped to zero. + // Other valid indices but invalid values are mapped to 255. + Vector128 decOne1 = AdvSimd.Arm64.VectorTableLookup(decLutOne, str1); + Vector128 decOne2 = AdvSimd.Arm64.VectorTableLookup(decLutOne, str2); + Vector128 decOne3 = AdvSimd.Arm64.VectorTableLookup(decLutOne, str3); + Vector128 decOne4 = AdvSimd.Arm64.VectorTableLookup(decLutOne, str4); + + // Step 2.2: Detect valid Base64 values from groups 4 and 5. Maps input as, + // 0 to 63 => 0 + // 64 to 122 (Valid) => Their Base64 equivalent + // 64 to 122 (Invalid) => 255 + // 123 to 255 => Remains unchanged + + // Subtract/offset each input value by 63 so that it can be used as a valid offset. + // Subtract saturate makes values from the first three groups set to zero that are + // then mapped to zero in the subsequent look-up. + Vector128 decTwo1 = AdvSimd.SubtractSaturate(str1, offset); + Vector128 decTwo2 = AdvSimd.SubtractSaturate(str2, offset); + Vector128 decTwo3 = AdvSimd.SubtractSaturate(str3, offset); + Vector128 decTwo4 = AdvSimd.SubtractSaturate(str4, offset); + + // We use VTBX to map values where out-of-range indices are unchanged. + decTwo1 = AdvSimd.Arm64.VectorTableLookupExtension(decTwo1, decLutTwo, decTwo1); + decTwo2 = AdvSimd.Arm64.VectorTableLookupExtension(decTwo2, decLutTwo, decTwo2); + decTwo3 = AdvSimd.Arm64.VectorTableLookupExtension(decTwo3, decLutTwo, decTwo3); + decTwo4 = AdvSimd.Arm64.VectorTableLookupExtension(decTwo4, decLutTwo, decTwo4); + + // Step 3: Combine the partial result. + // Each look-up above maps valid values to their Base64 equivalent or zero. + // Thus the intermediate results 'decOne' and 'decTwo' could be OR-ed to get final values. + str1 = (decOne1 | decTwo1); + str2 = (decOne2 | decTwo2); + str3 = (decOne3 | decTwo3); + str4 = (decOne4 | decTwo4); + + // Step 4: Detect an invalid input value. + // Invalid values < 122 are set to 255 while the ones above 122 are unchanged. + // Check for invalid input, any value larger than 63. + Vector128 classified = (Vector128.GreaterThan(str1, offset) + | Vector128.GreaterThan(str2, offset) + | Vector128.GreaterThan(str3, offset) + | Vector128.GreaterThan(str4, offset)); + + // Check that all bits are zero. + if (classified != Vector128.Zero) + { + break; + } + + // Step 5: Compress four bytes into three. + Vector128 res1 = ((str1 << 2) | (str2 >> 4)); + Vector128 res2 = ((str2 << 4) | (str3 >> 2)); + Vector128 res3 = ((str3 << 6) | str4); + + // Step 6: Interleave and store decoded results. + AssertWrite>(dest, destStart, destLength); + AdvSimd.Arm64.StoreVector128x3AndZip(dest, (res1, res2, res3)); + + src += 64; + dest += 48; + } + while (src <= srcEnd); + + srcBytes = src; + destBytes = dest; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] [CompExactlyDependsOn(typeof(Ssse3))] diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.Int128.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.Int128.cs new file mode 100644 index 000000000000..5264f100112e --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.Int128.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. + +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace System.Buffers.Text +{ + internal static partial class FormattingHelpers + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountDigits(UInt128 value) + { + ulong upper = value.Upper; + + // 1e19 is 8AC7_2304_89E8_0000 + // 1e20 is 5_6BC7_5E2D_6310_0000 + // 1e21 is 36_35C9_ADC5_DEA0_0000 + + if (upper == 0) + { + // We have less than 64-bits, so just return the lower count + return CountDigits(value.Lower); + } + + // We have more than 1e19, so we have at least 20 digits + int digits = 20; + + if (upper > 5) + { + // ((2^128) - 1) / 1e20 < 34_02_823_669_209_384_635 which + // is 18.5318 digits, meaning the result definitely fits + // into 64-bits and we only need to add the lower digit count + + value /= new UInt128(0x5, 0x6BC7_5E2D_6310_0000); // value /= 1e20 + Debug.Assert(value.Upper == 0); + + digits += CountDigits(value.Lower); + } + else if ((upper == 5) && (value.Lower >= 0x6BC75E2D63100000)) + { + // We're greater than 1e20, but definitely less than 1e21 + // so we have exactly 21 digits + + digits++; + Debug.Assert(digits == 21); + } + + return digits; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountHexDigits(UInt128 value) + { + // The number of hex digits is log16(value) + 1, or log2(value) / 4 + 1 + return ((int)UInt128.Log2(value) >> 2) + 1; + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs index 3da8684132f0..18eac2cf08eb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/FormattingHelpers.CountDigits.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Buffers.Binary; using System.Diagnostics; using System.Numerics; using System.Runtime.CompilerServices; @@ -11,47 +10,6 @@ namespace System.Buffers.Text { internal static partial class FormattingHelpers { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CountDigits(UInt128 value) - { - ulong upper = value.Upper; - - // 1e19 is 8AC7_2304_89E8_0000 - // 1e20 is 5_6BC7_5E2D_6310_0000 - // 1e21 is 36_35C9_ADC5_DEA0_0000 - - if (upper == 0) - { - // We have less than 64-bits, so just return the lower count - return CountDigits(value.Lower); - } - - // We have more than 1e19, so we have at least 20 digits - int digits = 20; - - if (upper > 5) - { - // ((2^128) - 1) / 1e20 < 34_02_823_669_209_384_635 which - // is 18.5318 digits, meaning the result definitely fits - // into 64-bits and we only need to add the lower digit count - - value /= new UInt128(0x5, 0x6BC7_5E2D_6310_0000); // value /= 1e20 - Debug.Assert(value.Upper == 0); - - digits += CountDigits(value.Lower); - } - else if ((upper == 5) && (value.Lower >= 0x6BC75E2D63100000)) - { - // We're greater than 1e20, but definitely less than 1e21 - // so we have exactly 21 digits - - digits++; - Debug.Assert(digits == 21); - } - - return digits; - } - // Based on do_count_digits from https://github.com/fmtlib/fmt/blob/662adf4f33346ba9aba8b072194e319869ede54a/include/fmt/format.h#L1124 [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int CountDigits(ulong value) @@ -149,13 +107,6 @@ public static int CountDigits(uint value) return (int)((value + tableValue) >> 32); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CountHexDigits(UInt128 value) - { - // The number of hex digits is log16(value) + 1, or log2(value) / 4 + 1 - return ((int)UInt128.Log2(value) >> 2) + 1; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int CountHexDigits(ulong value) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Byte.cs b/src/libraries/System.Private.CoreLib/src/System/Byte.cs index 31a2bccf21bf..0302bc2bc649 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Byte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Byte.cs @@ -678,6 +678,9 @@ public static byte CreateTruncating(TOther value) /// static byte INumberBase.MinMagnitudeNumber(byte x, byte y) => Min(x, y); + /// + static byte INumberBase.MultiplyAddEstimate(byte left, byte right, byte addend) => (byte)((left * right) + addend); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out byte result) => TryConvertFromChecked(value, out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/Char.cs b/src/libraries/System.Private.CoreLib/src/System/Char.cs index a44d61f61a2a..7df1b14afc03 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Char.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Char.cs @@ -1509,6 +1509,9 @@ bool IBinaryInteger.TryWriteLittleEndian(Span destination, out int b /// static char INumberBase.MinMagnitudeNumber(char x, char y) => (char)Math.Min(x, y); + /// + static char INumberBase.MultiplyAddEstimate(char left, char right, char addend) => (char)((left * right) + addend); + static char INumberBase.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s); static char INumberBase.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s); diff --git a/src/libraries/System.Private.CoreLib/src/System/CodeDom/Compiler/IndentedTextWriter.cs b/src/libraries/System.Private.CoreLib/src/System/CodeDom/Compiler/IndentedTextWriter.cs index 22ee77a8cc6e..dc7eca31f0d8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/CodeDom/Compiler/IndentedTextWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/CodeDom/Compiler/IndentedTextWriter.cs @@ -174,6 +174,17 @@ public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] _writer.Write(format, arg); } + /// + /// Writes out a formatted string, using the same semantics as specified. + /// + /// The formatting string to use. + /// The argument span to output. + public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan arg) + { + OutputTabs(); + _writer.Write(format, arg); + } + /// /// Asynchronously writes the specified to the underlying , inserting /// tabs at the start of every line. @@ -352,6 +363,18 @@ public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeForm _tabsPending = true; } + /// + /// Writes out a formatted string, followed by a line terminator, using the same semantics as specified. + /// + /// The formatting string to use. + /// The argument span to output. + public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan arg) + { + OutputTabs(); + _writer.WriteLine(format, arg); + _tabsPending = true; + } + [CLSCompliant(false)] public override void WriteLine(uint value) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/CollectionExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/CollectionExtensions.cs index 068536049a65..cf4256f546d5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/CollectionExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/CollectionExtensions.cs @@ -82,7 +82,7 @@ public static ReadOnlyDictionary AsReadOnly(this IDi /// The list to which the elements should be added. /// The span whose elements should be added to the end of the . /// The is null. - public static void AddRange(this List list, ReadOnlySpan source) + public static void AddRange(this List list, params ReadOnlySpan source) { if (list is null) { @@ -109,7 +109,7 @@ public static void AddRange(this List list, ReadOnlySpan source) /// The span whose elements should be added to the . /// The is null. /// is less than 0 or greater than 's . - public static void InsertRange(this List list, int index, ReadOnlySpan source) + public static void InsertRange(this List list, int index, params ReadOnlySpan source) { if (list is null) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs index 6007efe778ce..9b18d4a125ed 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs @@ -418,7 +418,6 @@ internal ref TValue FindValue(TKey key) i--; // Value in _buckets is 1-based; subtract 1 from i. We do it here so it fuses with the following conditional. do { - // Should be a while loop https://github.com/dotnet/runtime/issues/9422 // Test in if to drop range check for following array access if ((uint)i >= (uint)entries.Length) { @@ -450,7 +449,6 @@ internal ref TValue FindValue(TKey key) i--; // Value in _buckets is 1-based; subtract 1 from i. We do it here so it fuses with the following conditional. do { - // Should be a while loop https://github.com/dotnet/runtime/issues/9422 // Test in if to drop range check for following array access if ((uint)i >= (uint)entries.Length) { @@ -535,15 +533,8 @@ private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior) comparer == null) { // ValueType: Devirtualize with EqualityComparer.Default intrinsic - while (true) + while ((uint)i < (uint)entries.Length) { - // Should be a while loop https://github.com/dotnet/runtime/issues/9422 - // Test uint in if rather than loop condition to drop range check for following array access - if ((uint)i >= (uint)entries.Length) - { - break; - } - if (entries[i].hashCode == hashCode && EqualityComparer.Default.Equals(entries[i].key, key)) { if (behavior == InsertionBehavior.OverwriteExisting) @@ -574,15 +565,8 @@ private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior) else { Debug.Assert(comparer is not null); - while (true) + while ((uint)i < (uint)entries.Length) { - // Should be a while loop https://github.com/dotnet/runtime/issues/9422 - // Test uint in if rather than loop condition to drop range check for following array access - if ((uint)i >= (uint)entries.Length) - { - break; - } - if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) { if (behavior == InsertionBehavior.OverwriteExisting) @@ -690,15 +674,8 @@ internal static class CollectionsMarshalHelper comparer == null) { // ValueType: Devirtualize with EqualityComparer.Default intrinsic - while (true) + while ((uint)i < (uint)entries.Length) { - // Should be a while loop https://github.com/dotnet/runtime/issues/9422 - // Test uint in if rather than loop condition to drop range check for following array access - if ((uint)i >= (uint)entries.Length) - { - break; - } - if (entries[i].hashCode == hashCode && EqualityComparer.Default.Equals(entries[i].key, key)) { exists = true; @@ -720,15 +697,8 @@ internal static class CollectionsMarshalHelper else { Debug.Assert(comparer is not null); - while (true) + while ((uint)i < (uint)entries.Length) { - // Should be a while loop https://github.com/dotnet/runtime/issues/9422 - // Test uint in if rather than loop condition to drop range check for following array access - if ((uint)i >= (uint)entries.Length) - { - break; - } - if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) { exists = true; diff --git a/src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs index 322a6ae242b0..9fe1c77a1837 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs @@ -24,14 +24,16 @@ public class DefaultValueAttribute : Attribute private static object? s_convertFromInvariantString; [FeatureSwitchDefinition("System.ComponentModel.DefaultValueAttribute.IsSupported")] + [FeatureGuard(typeof(RequiresUnreferencedCodeAttribute))] +#pragma warning disable IL4000 internal static bool IsSupported => AppContext.TryGetSwitch("System.ComponentModel.DefaultValueAttribute.IsSupported", out bool isSupported) ? isSupported : true; +#pragma warning restore IL4000 /// /// Initializes a new instance of the /// class, converting the specified value to the specified type, and using the U.S. English /// culture as the translation context. /// - [RequiresUnreferencedCode("Generic TypeConverters may require the generic types to be annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All.")] public DefaultValueAttribute( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, string? value) @@ -39,9 +41,9 @@ public DefaultValueAttribute( // The null check and try/catch here are because attributes should never throw exceptions. // We would fail to load an otherwise normal class. + Debug.Assert(IsSupported, "Runtime instantiation of this attribute is not allowed with trimming."); if (!IsSupported) { - Debug.Assert(!IsSupported, "Runtime instantiation of this attribute is not allowed."); return; } @@ -69,7 +71,7 @@ public DefaultValueAttribute( _value = Convert.ChangeType(value, type, CultureInfo.InvariantCulture); } - [RequiresUnreferencedCode("Generic TypeConverters may require the generic types to be annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All.")] + [RequiresUnreferencedCode("DefaultValueAttribute usage of TypeConverter is not compatible with trimming.")] // Looking for ad hoc created TypeDescriptor.ConvertFromInvariantString(Type, string) static bool TryConvertFromInvariantString( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type typeToConvert, @@ -83,7 +85,7 @@ static bool TryConvertFromInvariantString( { Type? typeDescriptorType = Type.GetType("System.ComponentModel.TypeDescriptor, System.ComponentModel.TypeConverter", throwOnError: false); MethodInfo? mi = typeDescriptorType?.GetMethod("ConvertFromInvariantString", BindingFlags.NonPublic | BindingFlags.Static); - Volatile.Write(ref s_convertFromInvariantString, mi == null ? new object() : mi.CreateDelegate>()); + s_convertFromInvariantString = mi == null ? new object() : mi.CreateDelegate>(); } if (!(s_convertFromInvariantString is Func convertFromInvariantString)) diff --git a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs index f2d89445f834..fc05bc065d49 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs @@ -1117,6 +1117,14 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IFloatingPoint // + /// + public static TInteger ConvertToInteger(decimal value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + public static TInteger ConvertToIntegerNative(decimal value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + /// int IFloatingPoint.GetExponentByteCount() => sizeof(sbyte); @@ -1490,6 +1498,9 @@ public static decimal MinMagnitude(decimal x, decimal y) /// static decimal INumberBase.MinMagnitudeNumber(decimal x, decimal y) => MinMagnitude(x, y); + /// + static decimal INumberBase.MultiplyAddEstimate(decimal left, decimal right, decimal addend) => (left * right) + addend; + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out decimal result) => TryConvertFromChecked(value, out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/Delegate.cs b/src/libraries/System.Private.CoreLib/src/System/Delegate.cs index d24059770d5f..9e5a8170ac61 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Delegate.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Delegate.cs @@ -23,14 +23,30 @@ public abstract partial class Delegate : ICloneable, ISerializable return a.CombineImpl(b); } - public static Delegate? Combine(params Delegate?[]? delegates) + public static Delegate? Combine(params Delegate?[]? delegates) => + Combine((ReadOnlySpan)delegates); + + /// + /// Concatenates the invocation lists of an span of delegates. + /// + /// The span of delegates to combine. + /// + /// A new delegate with an invocation list that concatenates the invocation lists of the delegates in the span. + /// Returns if is , + /// if contains zero elements, or if every entry in is . + /// + public static Delegate? Combine(params ReadOnlySpan delegates) { - if (delegates == null || delegates.Length == 0) - return null; + Delegate? d = null; - Delegate? d = delegates[0]; - for (int i = 1; i < delegates.Length; i++) - d = Combine(d, delegates[i]); + if (!delegates.IsEmpty) + { + d = delegates[0]; + for (int i = 1; i < delegates.Length; i++) + { + d = Combine(d, delegates[i]); + } + } return d; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventDispatcher.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventDispatcher.cs index 548f792b5243..f54eae096980 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventDispatcher.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventDispatcher.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Microsoft.Win32.SafeHandles; namespace System.Diagnostics.Tracing { @@ -11,8 +10,8 @@ internal sealed class EventPipeEventDispatcher { internal sealed class EventListenerSubscription { - internal EventKeywords MatchAnyKeywords { get; private set; } - internal EventLevel Level { get; private set; } + internal EventKeywords MatchAnyKeywords { get; } + internal EventLevel Level { get; } internal EventListenerSubscription(EventKeywords matchAnyKeywords, EventLevel level) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeMetadataGenerator.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeMetadataGenerator.cs index ed19ea2178e3..efdb735b7b12 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeMetadataGenerator.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeMetadataGenerator.cs @@ -13,7 +13,7 @@ private enum MetadataTag ParameterPayload = 2 } - public static EventPipeMetadataGenerator Instance = new EventPipeMetadataGenerator(); + public static readonly EventPipeMetadataGenerator Instance = new EventPipeMetadataGenerator(); private EventPipeMetadataGenerator() { } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs index 61c7d5218bc6..48cab155a942 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs @@ -212,7 +212,7 @@ internal sealed class EventSourceAutoGenerateAttribute : Attribute /// [EventSource(Name="Samples.Demos.Minimal")] /// sealed class MinimalEventSource : EventSource /// { - /// public static MinimalEventSource Log = new MinimalEventSource(); + /// public static readonly MinimalEventSource Log = new MinimalEventSource(); /// public void Load(long ImageBase, string Name) { WriteEvent(1, ImageBase, Name); } /// public void Unload(long ImageBase) { WriteEvent(2, ImageBase); } /// private MinimalEventSource() {} @@ -1461,6 +1461,8 @@ public void Dispose() /// True if called from Dispose(), false if called from the finalizer. protected virtual void Dispose(bool disposing) { + // NOTE: If !IsSupported, we use ILLink.Substitutions to nop out the finalizer. + // Do not add any code before this line (or you'd need to delete the substitution). if (!IsSupported) { return; @@ -1504,6 +1506,7 @@ protected virtual void Dispose(bool disposing) /// ~EventSource() { + // NOTE: we nop out this method body if !IsSupported using ILLink.Substitutions. this.Dispose(false); } #endregion @@ -4851,12 +4854,12 @@ public sealed class EventAttribute : Attribute /// ID of the ETW event (an integer between 1 and 65535) public EventAttribute(int eventId) { - this.EventId = eventId; + EventId = eventId; Level = EventLevel.Informational; } /// Event's ID - public int EventId { get; private set; } + public int EventId { get; } /// Event's severity level: indicates the severity or verbosity of the event public EventLevel Level { get; set; } /// Event's keywords: allows classification of events by "categories" @@ -4867,8 +4870,8 @@ public EventOpcode Opcode get => m_opcode; set { - this.m_opcode = value; - this.m_opcodeSet = true; + m_opcode = value; + m_opcodeSet = true; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs index b978caaeaeba..20c6c8516d9f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs @@ -19,7 +19,7 @@ public partial class EventSource { private byte[]? m_providerMetadata; private protected virtual ReadOnlySpan ProviderMetadata => m_providerMetadata; - private const string EventSourceRequiresUnreferenceMessage = "EventSource will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed."; + private const string EventSourceRequiresUnreferenceMessage = "EventSource will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed. This can be suppressed if the object is a primitive type"; private const string EventSourceSuppressMessage = "Parameters to this method are primitive and are trimmer safe"; #if FEATURE_PERFTRACING diff --git a/src/libraries/System.Private.CoreLib/src/System/Double.cs b/src/libraries/System.Private.CoreLib/src/System/Double.cs index 71d73546bc13..26e65460ef24 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Double.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Double.cs @@ -655,6 +655,28 @@ public static bool IsPow2(double value) [Intrinsic] public static double Ceiling(double x) => Math.Ceiling(x); + /// + [Intrinsic] + public static TInteger ConvertToInteger(double value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + [Intrinsic] + public static TInteger ConvertToIntegerNative(double value) + where TInteger : IBinaryInteger + { +#if !MONO + if (typeof(TInteger).IsPrimitive) + { + // We need this to be recursive so indirect calls (delegates + // for example) produce the same result as direct invocation + return ConvertToIntegerNative(value); + } +#endif + + return TInteger.CreateSaturating(value); + } + /// [Intrinsic] public static double Floor(double x) => Math.Floor(x); @@ -855,9 +877,11 @@ bool IFloatingPoint.TryWriteSignificandLittleEndian(Span destinati public static double Lerp(double value1, double value2, double amount) => (value1 * (1.0 - amount)) + (value2 * amount); /// + [Intrinsic] public static double ReciprocalEstimate(double x) => Math.ReciprocalEstimate(x); /// + [Intrinsic] public static double ReciprocalSqrtEstimate(double x) => Math.ReciprocalSqrtEstimate(x); /// @@ -1192,6 +1216,17 @@ public static double MinMagnitudeNumber(double x, double y) return y; } + /// + [Intrinsic] + public static double MultiplyAddEstimate(double left, double right, double addend) + { +#if MONO + return (left * right) + addend; +#else + return MultiplyAddEstimate(left, right, addend); +#endif + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out double result) diff --git a/src/libraries/System.Private.CoreLib/src/System/Enum.cs b/src/libraries/System.Private.CoreLib/src/System/Enum.cs index 7e9a94a83ed9..d2b18ed344cc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Enum.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Enum.cs @@ -12,6 +12,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; #pragma warning disable 8500 // Allow taking address of managed types @@ -768,7 +769,7 @@ private static unsafe bool TryParse(Type enumType, ReadOnlySpan value, boo break; } - result = parsed ? InternalBoxEnum(rt, longScratch) : null; + result = parsed ? InternalBoxEnum(rt.TypeHandle, longScratch) : null; return parsed; [MethodImpl(MethodImplOptions.NoInlining)] @@ -1745,7 +1746,7 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, Re /// A span containing the character that represents the standard format string that defines the acceptable format of destination. This may be empty, or "g", "d", "f", or "x". /// if the formatting was successful; otherwise, if the destination span wasn't large enough to contain the formatted value. /// The format parameter contains an invalid value. - public static unsafe bool TryFormat(TEnum value, Span destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.EnumFormat)] ReadOnlySpan format = default) where TEnum : struct, Enum + public static unsafe bool TryFormat(TEnum value, Span destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.EnumFormat)] ReadOnlySpan format = default) where TEnum : struct { RuntimeType rt = (RuntimeType)typeof(TEnum); Type underlyingType = typeof(TEnum).GetEnumUnderlyingType(); @@ -2225,31 +2226,47 @@ public static object ToObject(Type enumType, object value) [CLSCompliant(false)] public static object ToObject(Type enumType, sbyte value) => - InternalBoxEnum(ValidateRuntimeType(enumType), value); + InternalBoxEnum(ValidateRuntimeType(enumType).TypeHandle, value); public static object ToObject(Type enumType, short value) => - InternalBoxEnum(ValidateRuntimeType(enumType), value); + InternalBoxEnum(ValidateRuntimeType(enumType).TypeHandle, value); public static object ToObject(Type enumType, int value) => - InternalBoxEnum(ValidateRuntimeType(enumType), value); + InternalBoxEnum(ValidateRuntimeType(enumType).TypeHandle, value); public static object ToObject(Type enumType, byte value) => - InternalBoxEnum(ValidateRuntimeType(enumType), value); + InternalBoxEnum(ValidateRuntimeType(enumType).TypeHandle, value); [CLSCompliant(false)] public static object ToObject(Type enumType, ushort value) => - InternalBoxEnum(ValidateRuntimeType(enumType), value); + InternalBoxEnum(ValidateRuntimeType(enumType).TypeHandle, value); [CLSCompliant(false)] public static object ToObject(Type enumType, uint value) => - InternalBoxEnum(ValidateRuntimeType(enumType), value); + InternalBoxEnum(ValidateRuntimeType(enumType).TypeHandle, value); public static object ToObject(Type enumType, long value) => - InternalBoxEnum(ValidateRuntimeType(enumType), value); + InternalBoxEnum(ValidateRuntimeType(enumType).TypeHandle, value); [CLSCompliant(false)] public static object ToObject(Type enumType, ulong value) => - InternalBoxEnum(ValidateRuntimeType(enumType), unchecked((long)value)); + InternalBoxEnum(ValidateRuntimeType(enumType).TypeHandle, unchecked((long)value)); + + private static object InternalBoxEnum(RuntimeTypeHandle type, long value) + { + ReadOnlySpan rawData = MemoryMarshal.AsBytes(new ReadOnlySpan(ref value)); + // On little-endian systems, we can always use the pointer to the start of the scratch space + // as memory layout since the least-significant bit is at the lowest address. + // For big-endian systems, the least-significant bit is at the highest address, so we need to adjust + // our starting ref to the correct offset from the end of the scratch space to get the value to box. + if (!BitConverter.IsLittleEndian) + { + int size = RuntimeHelpers.SizeOf(type); + rawData = rawData.Slice(sizeof(long) - size); + } + + return RuntimeHelpers.Box(ref MemoryMarshal.GetReference(rawData), type)!; + } internal static bool AreSequentialFromZero(TStorage[] values) where TStorage : struct, INumber { diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.cs index 53028ec74d02..ff58e43d54eb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.cs @@ -3,7 +3,6 @@ using System.Collections; using System.Diagnostics; -using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; @@ -201,24 +200,6 @@ public static OperatingSystem OSVersion } } - public static Version Version - { - get - { - string? versionString = typeof(object).Assembly.GetCustomAttribute()?.InformationalVersion; - - ReadOnlySpan versionSpan = versionString.AsSpan(); - - // Strip optional suffixes - int separatorIndex = versionSpan.IndexOfAny('-', '+', ' '); - if (separatorIndex >= 0) - versionSpan = versionSpan.Slice(0, separatorIndex); - - // Return zeros rather then failing if the version string fails to parse - return Version.TryParse(versionSpan, out Version? version) ? version : new Version(); - } - } - public static string StackTrace { [MethodImpl(MethodImplOptions.NoInlining)] // Prevent inlining from affecting where the stacktrace starts diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.Browser.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.Browser.cs index 87199ed3f1ee..582492c6c40f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.Browser.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.Browser.cs @@ -14,32 +14,33 @@ internal sealed partial class CalendarData private const int CALENDAR_INFO_BUFFER_LEN = 1000; private unsafe bool JSLoadCalendarDataFromBrowser(string localeName, CalendarId calendarId) { - char* buffer = stackalloc char[CALENDAR_INFO_BUFFER_LEN]; - int exception; - object exResult; - int resultLength = Interop.JsGlobalization.GetCalendarInfo(localeName, calendarId, buffer, CALENDAR_INFO_BUFFER_LEN, out exception, out exResult); - if (exception != 0) - throw new Exception((string)exResult); - string result = new string(buffer, 0, resultLength); - string[] subresults = result.Split("##"); - if (subresults.Length < 14) - throw new Exception("CalendarInfo recieved from the Browser is in icorrect format."); - // JS always has one result per locale, so even arrays are initialized with one element - this.sNativeName = string.IsNullOrEmpty(subresults[0]) ? ((CalendarId)calendarId).ToString() : subresults[0]; // this is EnglishName, not NativeName but it's the best we can do - this.saYearMonths = new string[] { subresults[1] }; - this.sMonthDay = subresults[2]; - this.saLongDates = new string[] { subresults[3] }; - this.saShortDates = new string[] { subresults[4] }; - this.saEraNames = new string[] { subresults[5] }; - this.saAbbrevEraNames = new string[] { subresults[6] }; - this.saDayNames = subresults[7].Split("||"); - this.saAbbrevDayNames = subresults[8].Split("||"); - this.saSuperShortDayNames = subresults[9].Split("||"); - this.saMonthNames = ResizeMonthsArray(subresults[10].Split("||")); - this.saAbbrevMonthNames = ResizeMonthsArray(subresults[11].Split("||")); - this.saMonthGenitiveNames = ResizeMonthsArray(subresults[12].Split("||")); - this.saAbbrevMonthGenitiveNames = ResizeMonthsArray(subresults[13].Split("||")); - return true; + ReadOnlySpan localeNameSpan = localeName.AsSpan(); + fixed (char* pLocaleName = &MemoryMarshal.GetReference(localeNameSpan)) + { + char* buffer = stackalloc char[CALENDAR_INFO_BUFFER_LEN]; + nint exceptionPtr = Interop.JsGlobalization.GetCalendarInfo(pLocaleName, localeNameSpan.Length, calendarId, buffer, CALENDAR_INFO_BUFFER_LEN, out int resultLength); + Helper.MarshalAndThrowIfException(exceptionPtr); + string result = new string(buffer, 0, resultLength); + string[] subresults = result.Split("##"); + if (subresults.Length < 14) + throw new Exception("CalendarInfo recieved from the Browser is in icorrect format."); + // JS always has one result per locale, so even arrays are initialized with one element + this.sNativeName = string.IsNullOrEmpty(subresults[0]) ? ((CalendarId)calendarId).ToString() : subresults[0]; // this is EnglishName, not NativeName but it's the best we can do + this.saYearMonths = new string[] { subresults[1] }; + this.sMonthDay = subresults[2]; + this.saLongDates = new string[] { subresults[3] }; + this.saShortDates = new string[] { subresults[4] }; + this.saEraNames = new string[] { subresults[5] }; + this.saAbbrevEraNames = new string[] { subresults[6] }; + this.saDayNames = subresults[7].Split("||"); + this.saAbbrevDayNames = subresults[8].Split("||"); + this.saSuperShortDayNames = subresults[9].Split("||"); + this.saMonthNames = ResizeMonthsArray(subresults[10].Split("||")); + this.saAbbrevMonthNames = ResizeMonthsArray(subresults[11].Split("||")); + this.saMonthGenitiveNames = ResizeMonthsArray(subresults[12].Split("||")); + this.saAbbrevMonthGenitiveNames = ResizeMonthsArray(subresults[13].Split("||")); + return true; + } static string[] ResizeMonthsArray(string[] months) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.iOS.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.iOS.cs index 6ebd6a2964d4..b0ccc60ac5e1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.iOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.iOS.cs @@ -18,6 +18,15 @@ private bool LoadCalendarDataFromNative(string localeName, CalendarId calendarId sNativeName = GetCalendarInfoNative(localeName, calendarId, CalendarDataType.NativeName); sMonthDay = GetCalendarInfoNative(localeName, calendarId, CalendarDataType.MonthDay); saShortDates = GetCalendarInfoNative(localeName, calendarId, CalendarDataType.ShortDates).Split("||"); + // Handle ShortDatePattern to have "yyyy" year format + List shortDatePatternList = new List(saShortDates); + for (int i = 0; i < shortDatePatternList.Count; i++) + { + shortDatePatternList[i] = NormalizeDatePattern(shortDatePatternList[i]); + } + FixDefaultShortDatePattern(shortDatePatternList); + saShortDates = shortDatePatternList.ToArray(); + saLongDates = GetCalendarInfoNative(localeName, calendarId, CalendarDataType.LongDates).Split("||"); saYearMonths = GetCalendarInfoNative(localeName, calendarId, CalendarDataType.YearMonths).Split("||"); saDayNames = GetCalendarInfoNative(localeName, calendarId, CalendarDataType.DayNames).Split("||"); diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.Icu.cs index 75440b2a23c4..bc532fcb26c0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.Icu.cs @@ -198,10 +198,13 @@ private unsafe int IndexOfOrdinalIgnoreCaseHelper(ReadOnlySpan source, Rea #if TARGET_BROWSER if (GlobalizationMode.Hybrid) { - int result = Interop.JsGlobalization.IndexOf(m_name, b, target.Length, a, source.Length, options, fromBeginning, out int exception, out object ex_result); - if (exception != 0) - throw new Exception((string)ex_result); - return result; + ReadOnlySpan cultureNameSpan = m_name.AsSpan(); + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureNameSpan)) + { + nint exceptionPtr = Interop.JsGlobalization.IndexOf(pCultureName, cultureNameSpan.Length, b, target.Length, a, source.Length, options, fromBeginning, out int result); + Helper.MarshalAndThrowIfException(exceptionPtr); + return result; + } } #elif TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS if (GlobalizationMode.Hybrid) @@ -300,10 +303,13 @@ private unsafe int IndexOfOrdinalHelper(ReadOnlySpan source, ReadOnlySpan< #if TARGET_BROWSER if (GlobalizationMode.Hybrid) { - int result = Interop.JsGlobalization.IndexOf(m_name, b, target.Length, a, source.Length, options, fromBeginning, out int exception, out object ex_result); - if (exception != 0) - throw new Exception((string)ex_result); - return result; + ReadOnlySpan cultureNameSpan = m_name.AsSpan(); + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureNameSpan)) + { + nint exceptionPtr = Interop.JsGlobalization.IndexOf(pCultureName, cultureNameSpan.Length, b, target.Length, a, source.Length, options, fromBeginning, out int result); + Helper.MarshalAndThrowIfException(exceptionPtr); + return result; + } } #elif TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS if (GlobalizationMode.Hybrid) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.WebAssembly.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.WebAssembly.cs index 1d265dc70450..e8935a6d2439 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.WebAssembly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.WebAssembly.cs @@ -47,86 +47,74 @@ private static void AssertIndexingSupported(CompareOptions options, string cultu private unsafe int JsCompareString(ReadOnlySpan string1, ReadOnlySpan string2, CompareOptions options) { AssertHybridOnWasm(options); - string cultureName = m_name; - AssertComparisonSupported(options, cultureName); + AssertComparisonSupported(options, m_name); - int cmpResult; + ReadOnlySpan cultureNameSpan = m_name.AsSpan(); fixed (char* pString1 = &MemoryMarshal.GetReference(string1)) fixed (char* pString2 = &MemoryMarshal.GetReference(string2)) + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureNameSpan)) { - cmpResult = Interop.JsGlobalization.CompareString(cultureName, pString1, string1.Length, pString2, string2.Length, options, out int exception, out object ex_result); - if (exception != 0) - throw new Exception((string)ex_result); + nint exceptionPtr = Interop.JsGlobalization.CompareString(pCultureName, cultureNameSpan.Length, pString1, string1.Length, pString2, string2.Length, options, out int cmpResult); + Helper.MarshalAndThrowIfException(exceptionPtr); + return cmpResult; } - - return cmpResult; } private unsafe bool JsStartsWith(ReadOnlySpan source, ReadOnlySpan prefix, CompareOptions options) { AssertHybridOnWasm(options); Debug.Assert(!prefix.IsEmpty); - string cultureName = m_name; - AssertIndexingSupported(options, cultureName); + AssertIndexingSupported(options, m_name); - bool result; + ReadOnlySpan cultureNameSpan = m_name.AsSpan(); fixed (char* pSource = &MemoryMarshal.GetReference(source)) fixed (char* pPrefix = &MemoryMarshal.GetReference(prefix)) + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureNameSpan)) { - result = Interop.JsGlobalization.StartsWith(cultureName, pSource, source.Length, pPrefix, prefix.Length, options, out int exception, out object ex_result); - if (exception != 0) - throw new Exception((string)ex_result); + nint exceptionPtr = Interop.JsGlobalization.StartsWith(pCultureName, cultureNameSpan.Length, pSource, source.Length, pPrefix, prefix.Length, options, out bool result); + Helper.MarshalAndThrowIfException(exceptionPtr); + return result; } - - - return result; } private unsafe bool JsEndsWith(ReadOnlySpan source, ReadOnlySpan prefix, CompareOptions options) { AssertHybridOnWasm(options); Debug.Assert(!prefix.IsEmpty); - string cultureName = m_name; - AssertIndexingSupported(options, cultureName); + AssertIndexingSupported(options, m_name); - bool result; + ReadOnlySpan cultureNameSpan = m_name.AsSpan(); fixed (char* pSource = &MemoryMarshal.GetReference(source)) fixed (char* pPrefix = &MemoryMarshal.GetReference(prefix)) + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureNameSpan)) { - result = Interop.JsGlobalization.EndsWith(cultureName, pSource, source.Length, pPrefix, prefix.Length, options, out int exception, out object ex_result); - if (exception != 0) - throw new Exception((string)ex_result); + nint exceptionPtr = Interop.JsGlobalization.EndsWith(pCultureName, cultureNameSpan.Length, pSource, source.Length, pPrefix, prefix.Length, options, out bool result); + Helper.MarshalAndThrowIfException(exceptionPtr); + return result; } - - return result; } private unsafe int JsIndexOfCore(ReadOnlySpan source, ReadOnlySpan target, CompareOptions options, int* matchLengthPtr, bool fromBeginning) { AssertHybridOnWasm(options); Debug.Assert(!target.IsEmpty); - string cultureName = m_name; - AssertIndexingSupported(options, cultureName); + AssertIndexingSupported(options, m_name); - int idx; if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options)) { - idx = (options & CompareOptions.IgnoreCase) != 0 ? + return (options & CompareOptions.IgnoreCase) != 0 ? IndexOfOrdinalIgnoreCaseHelper(source, target, options, matchLengthPtr, fromBeginning) : IndexOfOrdinalHelper(source, target, options, matchLengthPtr, fromBeginning); } - else + ReadOnlySpan cultureNameSpan = m_name.AsSpan(); + fixed (char* pSource = &MemoryMarshal.GetReference(source)) + fixed (char* pTarget = &MemoryMarshal.GetReference(target)) + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureNameSpan)) { - fixed (char* pSource = &MemoryMarshal.GetReference(source)) - fixed (char* pTarget = &MemoryMarshal.GetReference(target)) - { - idx = Interop.JsGlobalization.IndexOf(m_name, pTarget, target.Length, pSource, source.Length, options, fromBeginning, out int exception, out object ex_result); - if (exception != 0) - throw new Exception((string)ex_result); - } + nint exceptionPtr = Interop.JsGlobalization.IndexOf(pCultureName, cultureNameSpan.Length, pTarget, target.Length, pSource, source.Length, options, fromBeginning, out int idx); + Helper.MarshalAndThrowIfException(exceptionPtr); + return idx; } - - return idx; } // there are chars that are ignored by ICU hashing algorithm but not ignored by invariant hashing diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Browser.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Browser.cs index 8a8edadaf326..417bd563bf35 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Browser.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Browser.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; namespace System.Globalization { @@ -41,17 +42,22 @@ private void JSInitLocaleInfo() private unsafe (string, string) JSGetLocaleInfo(string cultureName, string localeName) { - char* buffer = stackalloc char[LOCALE_INFO_BUFFER_LEN]; - int resultLength = Interop.JsGlobalization.GetLocaleInfo(cultureName, localeName, buffer, LOCALE_INFO_BUFFER_LEN, out int exception, out object exResult); - if (exception != 0) - throw new Exception((string)exResult); - string result = new string(buffer, 0, resultLength); - string[] subresults = result.Split("##"); - if (subresults.Length == 0) - throw new Exception("LocaleInfo recieved from the Browser is in incorrect format."); - if (subresults.Length == 1) - return (subresults[0], ""); // Neutral culture - return (subresults[0], subresults[1]); + ReadOnlySpan cultureNameSpan = cultureName.AsSpan(); + ReadOnlySpan localeNameSpan = localeName.AsSpan(); + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureNameSpan)) + fixed (char* pLocaleName = &MemoryMarshal.GetReference(localeNameSpan)) + { + char* buffer = stackalloc char[LOCALE_INFO_BUFFER_LEN]; + nint exceptionPtr = Interop.JsGlobalization.GetLocaleInfo(pCultureName, cultureNameSpan.Length, pLocaleName, localeNameSpan.Length, buffer, LOCALE_INFO_BUFFER_LEN, out int resultLength); + Helper.MarshalAndThrowIfException(exceptionPtr); + string result = new string(buffer, 0, resultLength); + string[] subresults = result.Split("##"); + if (subresults.Length == 0) + throw new Exception("LocaleInfo recieved from the Browser is in incorrect format."); + if (subresults.Length == 1) + return (subresults[0], ""); // Neutral culture + return (subresults[0], subresults[1]); + } } private string JSGetNativeDisplayName(string localeName, string cultureName) @@ -64,43 +70,82 @@ private string JSGetNativeDisplayName(string localeName, string cultureName) private static unsafe CultureData JSLoadCultureInfoFromBrowser(string localeName, CultureData culture) { - char* buffer = stackalloc char[CULTURE_INFO_BUFFER_LEN]; - int resultLength = Interop.JsGlobalization.GetCultureInfo(localeName, buffer, CULTURE_INFO_BUFFER_LEN, out int exception, out object exResult); - if (exception != 0) - throw new Exception((string)exResult); - string result = new string(buffer, 0, resultLength); - string[] subresults = result.Split("##"); - if (subresults.Length < 4) - throw new Exception("CultureInfo recieved from the Browser is in incorrect format."); - culture._sAM1159 = subresults[0]; - culture._sPM2359 = subresults[1]; - culture._saLongTimes = new string[] { subresults[2] }; - culture._saShortTimes = new string[] { subresults[3] }; + ReadOnlySpan localeNameSpan = localeName.AsSpan(); + fixed (char* pLocaleName = &MemoryMarshal.GetReference(localeNameSpan)) + { + char* buffer = stackalloc char[CULTURE_INFO_BUFFER_LEN]; + nint exceptionPtr = Interop.JsGlobalization.GetCultureInfo(pLocaleName, localeNameSpan.Length, buffer, CULTURE_INFO_BUFFER_LEN, out int resultLength); + Helper.MarshalAndThrowIfException(exceptionPtr); + string result = new string(buffer, 0, resultLength); + string[] subresults = result.Split("##"); + if (subresults.Length < 4) + throw new Exception("CultureInfo recieved from the Browser is in incorrect format."); + culture._sAM1159 = subresults[0]; + culture._sPM2359 = subresults[1]; + culture._saLongTimes = new string[] { subresults[2] }; + culture._saShortTimes = new string[] { subresults[3] }; + } return culture; } private static unsafe int GetFirstDayOfWeek(string localeName) { - int result = Interop.JsGlobalization.GetFirstDayOfWeek(localeName, out int exception, out object ex_result); - if (exception != 0) + ReadOnlySpan localeNameSpan = localeName.AsSpan(); + fixed (char* pLocaleName = &MemoryMarshal.GetReference(localeNameSpan)) { - // Failed, just use 0 - Debug.Fail($"[CultureData.GetFirstDayOfWeek()] failed with {ex_result}"); - return 0; + nint exceptionPtr = Interop.JsGlobalization.GetFirstDayOfWeek(pLocaleName, localeNameSpan.Length, out int result); + if (exceptionPtr != IntPtr.Zero) + { + int success = Helper.MarshalAndThrowIfException( + exceptionPtr, + failOnlyDebug: true, + failureMessage: $"[CultureData.GetFirstDayOfWeek()] failed with"); + // Failed, just use 0 + if (success == -1) + return 0; + } + return result; } - return result; } private static unsafe int GetFirstWeekOfYear(string localeName) { - int result = Interop.JsGlobalization.GetFirstWeekOfYear(localeName, out int exception, out object ex_result); - if (exception != 0) + ReadOnlySpan localeNameSpan = localeName.AsSpan(); + fixed (char* pLocaleName = &MemoryMarshal.GetReference(localeNameSpan)) + { + nint exceptionPtr = Interop.JsGlobalization.GetFirstWeekOfYear(pLocaleName, localeNameSpan.Length, out int result); + if (exceptionPtr != IntPtr.Zero) + { + int success = Helper.MarshalAndThrowIfException( + exceptionPtr, + failOnlyDebug: true, + failureMessage: $"[CultureData.GetFirstWeekOfYear()] failed with"); + // Failed, just use 0 + if (success == -1) + return 0; + } + return result; + } + } + } + + internal static class Helper + { + internal static int MarshalAndThrowIfException(nint exceptionPtr, bool failOnlyDebug = false, string failureMessage = "") + { + if (exceptionPtr != IntPtr.Zero) { - // Failed, just use 0 - Debug.Fail($"[CultureData.GetFirstDayOfWeek()] failed with {ex_result}"); - return 0; + string message = Marshal.PtrToStringUni(exceptionPtr)!; + Marshal.FreeHGlobal(exceptionPtr); + if (failOnlyDebug) + { + Debug.Fail($"{failureMessage} {message}"); + return -1; + } + throw new Exception(message); } - return result; + return 0; } + } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs index 31cc5bdd6015..c6061ed1bd85 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs @@ -310,7 +310,7 @@ private unsafe string IcuGetTimeFormatString(bool shortFormat) private string IcuGetLanguageDisplayName(string cultureName) { -#if TARGET_BROWSER && !FEATURE_WASM_MANAGED_THREADS +#if TARGET_BROWSER return JSGetNativeDisplayName(CultureInfo.CurrentUICulture.Name, cultureName); #else return IcuGetLocaleInfo(cultureName, LocaleStringData.LocalizedDisplayName, CultureInfo.CurrentUICulture.Name); diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs index f049aef6c4c4..2421d862a276 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs @@ -111,14 +111,13 @@ internal sealed partial class CultureData private string? _sAM1159; // (user can override) AM designator private string? _sPM2359; // (user can override) PM designator private string? _sTimeSeparator; - private volatile string[]? _saLongTimes; // (user can override) time format - private volatile string[]? _saShortTimes; // (user can override) short time format - private volatile string[]? _saDurationFormats; // time duration format + private string[]? _saLongTimes; // (user can override) time format + private string[]? _saShortTimes; // (user can override) short time format // Calendar specific data private int _iFirstDayOfWeek = undef; // (user can override) first day of week (gregorian really) private int _iFirstWeekOfYear = undef; // (user can override) first week of year (gregorian really) - private volatile CalendarId[]? _waCalendars; // all available calendar type(s). The first one is the default calendar + private CalendarId[]? _waCalendars; // all available calendar type(s). The first one is the default calendar // Store for specific data about each calendar private CalendarData?[]? _calendars; // Store for specific calendar data @@ -150,7 +149,7 @@ internal sealed partial class CultureData /// private static Dictionary RegionNames => s_regionNames ??= - new Dictionary(257 /* prime */, StringComparer.OrdinalIgnoreCase) + new Dictionary(255, StringComparer.OrdinalIgnoreCase) { { "001", "en-001" }, { "029", "en-029" }, @@ -411,7 +410,7 @@ internal sealed partial class CultureData // Cache of regions we've already looked up private static volatile Dictionary? s_cachedRegions; - private static volatile Dictionary? s_regionNames; + private static Dictionary? s_regionNames; /// /// The culture name to use to interop with the underlying native globalization libraries like ICU or Windows NLS APIs. @@ -621,7 +620,6 @@ private static CultureData CreateCultureWithInvariantData() invariant._sPM2359 = "PM"; // PM designator invariant._saLongTimes = new string[] { "HH:mm:ss" }; // time format invariant._saShortTimes = new string[] { "HH:mm", "hh:mm tt", "H:mm", "h:mm tt" }; // short time format - invariant._saDurationFormats = new string[] { "HH:mm:ss" }; // time duration format // Calendar specific data invariant._iFirstDayOfWeek = 0; // first day of week @@ -630,7 +628,7 @@ private static CultureData CreateCultureWithInvariantData() // all available calendar type(s). The first one is the default calendar invariant._waCalendars = new CalendarId[] { CalendarId.GREGORIAN }; - if (!GlobalizationMode.Invariant) + if (!GlobalizationMode.InvariantNoLoad) { // Store for specific data about each calendar invariant._calendars = new CalendarData[CalendarData.MAX_CALENDARS]; @@ -648,7 +646,7 @@ private static CultureData CreateCultureWithInvariantData() invariant._iDefaultMacCodePage = 10000; // default macintosh code page invariant._iDefaultEbcdicCodePage = 037; // default EBCDIC code page - if (GlobalizationMode.Invariant) + if (GlobalizationMode.InvariantNoLoad) { invariant._sLocalizedCountry = invariant._sNativeCountry; } @@ -661,7 +659,7 @@ private static CultureData CreateCultureWithInvariantData() /// We need an invariant instance, which we build hard-coded /// internal static CultureData Invariant => s_Invariant ??= CreateCultureWithInvariantData(); - private static volatile CultureData? s_Invariant; + private static CultureData? s_Invariant; // Cache of cultures we've already looked up private static volatile Dictionary? s_cachedCultures; @@ -816,7 +814,7 @@ private static string NormalizeCultureName(string name, out bool isNeutralName) { return null; } -#if TARGET_BROWSER && !FEATURE_WASM_MANAGED_THREADS +#if TARGET_BROWSER // populate fields for which ICU does not provide data in Hybrid mode if (GlobalizationMode.Hybrid && !string.IsNullOrEmpty(culture._sName)) { @@ -1383,18 +1381,10 @@ internal string[] LongTimes { if (_saLongTimes == null && !GlobalizationMode.Invariant) { - Debug.Assert(!GlobalizationMode.Invariant); - string[]? longTimes = GetTimeFormatsCore(shortFormat: false); - if (longTimes == null || longTimes.Length == 0) - { - _saLongTimes = Invariant._saLongTimes!; - } - else - { - _saLongTimes = longTimes; - } + _saLongTimes = longTimes != null && longTimes.Length != 0 ? longTimes : Invariant._saLongTimes!; } + return _saLongTimes!; } } @@ -1409,23 +1399,13 @@ internal string[] ShortTimes { if (_saShortTimes == null && !GlobalizationMode.Invariant) { - Debug.Assert(!GlobalizationMode.Invariant); - // Try to get the short times from the OS/culture.dll + // If we couldn't find short times, then compute them from long times + // (eg: CORECLR on < Win7 OS & fallback for missing culture.dll) string[]? shortTimes = GetTimeFormatsCore(shortFormat: true); - - if (shortTimes == null || shortTimes.Length == 0) - { - // - // If we couldn't find short times, then compute them from long times - // (eg: CORECLR on < Win7 OS & fallback for missing culture.dll) - // - shortTimes = DeriveShortTimesFromLong(); - } - - // Found short times, use them - _saShortTimes = shortTimes; + _saShortTimes = shortTimes != null && shortTimes.Length != 0 ? shortTimes : DeriveShortTimesFromLong(); } + return _saShortTimes!; } } @@ -2250,7 +2230,7 @@ private string[] GetNativeDigits() internal void GetNFIValues(NumberFormatInfo nfi) { - if (GlobalizationMode.Invariant || IsInvariantCulture) + if (GlobalizationMode.InvariantNoLoad || IsInvariantCulture) { nfi._positiveSign = _sPositiveSign!; nfi._negativeSign = _sNegativeSign!; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs index a0789def2711..5c23a1732308 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs @@ -126,8 +126,8 @@ private static void AsyncLocalSetCurrentUICulture(AsyncLocalValueChangedArgs? s_cachedCulturesByName; - private static volatile Dictionary? s_cachedCulturesByLcid; + private static Dictionary? s_cachedCulturesByName; + private static Dictionary? s_cachedCulturesByLcid; // The parent culture. private CultureInfo? _parent; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs index 895a9e83b6a8..db12f89bf2dd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs @@ -484,11 +484,11 @@ private static void FormatCustomized( tokenLen = ParseRepeatPattern(format, i, ch); if (tokenLen <= MaxSecondsFractionDigits) { - long fraction = (dateTime.Ticks % Calendar.TicksPerSecond); - fraction /= (long)Math.Pow(10, 7 - tokenLen); + int fraction = (int)(dateTime.Ticks % Calendar.TicksPerSecond); + fraction /= TimeSpanParse.Pow10UpToMaxFractionDigits(MaxSecondsFractionDigits - tokenLen); if (ch == 'f') { - FormatFraction(ref result, (int)fraction, fixedNumberFormats[tokenLen - 1]); + FormatFraction(ref result, fraction, fixedNumberFormats[tokenLen - 1]); } else { @@ -507,7 +507,7 @@ private static void FormatCustomized( } if (effectiveDigits > 0) { - FormatFraction(ref result, (int)fraction, fixedNumberFormats[effectiveDigits - 1]); + FormatFraction(ref result, fraction, fixedNumberFormats[effectiveDigits - 1]); } else { diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs index e98c70711276..e87960b61792 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs @@ -1914,8 +1914,8 @@ internal bool YearMonthAdjustment(ref int year, ref int month, bool parsedMonthN internal const string JapaneseLangName = "ja"; internal const string EnglishLangName = "en"; - private static volatile DateTimeFormatInfo? s_jajpDTFI; - private static volatile DateTimeFormatInfo? s_zhtwDTFI; + private static DateTimeFormatInfo? s_jajpDTFI; + private static DateTimeFormatInfo? s_zhtwDTFI; /// /// Create a Japanese DTFI which uses JapaneseCalendar. This is used to parse diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs index 687cafbe9ca5..9613bddf4354 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs @@ -3179,6 +3179,7 @@ internal static bool ParseDigits(ref __DTString str, int minDigitLen, int maxDig private static bool ParseFractionExact(ref __DTString str, int maxDigitLen, scoped ref double result) { + Debug.Assert(maxDigitLen <= DateTimeFormat.MaxSecondsFractionDigits); if (!str.GetNextDigit()) { str.Index--; @@ -3197,7 +3198,7 @@ private static bool ParseFractionExact(ref __DTString str, int maxDigitLen, scop result = result * 10 + str.GetDigit(); } - result /= TimeSpanParse.Pow10(digitLen); + result /= TimeSpanParse.Pow10UpToMaxFractionDigits(digitLen); return digitLen == maxDigitLen; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs index 314bb33692dc..78cebb45b9a0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs @@ -25,6 +25,21 @@ private static partial class Settings // This allows for the whole Settings nested class to be trimmed when Invariant=true, and allows for the Settings // static cctor (on Unix) to be preserved when Invariant=false. internal static bool Invariant => Settings.Invariant; + + // same as GlobalizationMode.Invariant but doesn't trigger ICU load in GlobalizationMode.Settings.cctor + // during runtime startup on Browser platform + internal static bool InvariantNoLoad + { + get + { +#if TARGET_BROWSER + return AppContextConfigHelper.GetBooleanConfig("System.Globalization.Invariant", "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT"); +#else + return Settings.Invariant; +#endif + } + } + #if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS || TARGET_BROWSER internal static bool Hybrid => Settings.Hybrid; #endif diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendar.cs index edb65a805570..ee5919bae506 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendar.cs @@ -26,7 +26,7 @@ public class GregorianCalendar : Calendar internal static ReadOnlySpan DaysToMonth366 => [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]; - private static volatile Calendar? s_defaultInstance; + private static Calendar? s_defaultInstance; public override DateTime MinSupportedDateTime => DateTime.MinValue; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/JapaneseCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/JapaneseCalendar.cs index cd37d6ba6529..a6a5cc72de3a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/JapaneseCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/JapaneseCalendar.cs @@ -42,7 +42,7 @@ public partial class JapaneseCalendar : Calendar // Using a field initializer rather than a static constructor so that the whole class can be lazy // init. - private static volatile EraInfo[]? s_japaneseEraInfo; + private static EraInfo[]? s_japaneseEraInfo; // m_EraInfo must be listed in reverse chronological order. The most recent era // should be the first element. @@ -67,20 +67,19 @@ public partial class JapaneseCalendar : Calendar internal static EraInfo[] GetEraInfo() { // See if we need to build it - return s_japaneseEraInfo ?? - (s_japaneseEraInfo = GlobalizationMode.UseNls ? NlsGetJapaneseEras() : IcuGetJapaneseEras()) ?? + return s_japaneseEraInfo ??= + (GlobalizationMode.UseNls ? NlsGetJapaneseEras() : IcuGetJapaneseEras()) ?? // See if we have to use the built-in eras - (s_japaneseEraInfo = new EraInfo[] - { + [ new EraInfo(5, 2019, 5, 1, 2018, 1, GregorianCalendar.MaxYear - 2018, "\x4ee4\x548c", "\x4ee4", "R"), new EraInfo(4, 1989, 1, 8, 1988, 1, 2019 - 1988, "\x5e73\x6210", "\x5e73", "H"), new EraInfo(3, 1926, 12, 25, 1925, 1, 1989 - 1925, "\x662d\x548c", "\x662d", "S"), new EraInfo(2, 1912, 7, 30, 1911, 1, 1926 - 1911, "\x5927\x6b63", "\x5927", "T"), new EraInfo(1, 1868, 1, 1, 1867, 1, 1912 - 1867, "\x660e\x6cbb", "\x660e", "M") - }); + ]; } - internal static volatile Calendar? s_defaultInstance; + internal static Calendar? s_defaultInstance; internal GregorianCalendarHelper _helper; internal static Calendar GetDefaultInstance() => s_defaultInstance ??= new JapaneseCalendar(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs index a20ff0be7c6d..0424b678e4b1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs @@ -39,7 +39,7 @@ namespace System.Globalization /// public sealed class NumberFormatInfo : IFormatProvider, ICloneable { - private static volatile NumberFormatInfo? s_invariantInfo; + private static NumberFormatInfo? s_invariantInfo; internal static readonly string[] s_asciiDigits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; internal static readonly int[] s_intArrayWithElement3 = [3]; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/RegionInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/RegionInfo.cs index 091f3a8f6561..c8a736ffa4e6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/RegionInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/RegionInfo.cs @@ -21,7 +21,7 @@ public class RegionInfo private readonly CultureData _cultureData; // The RegionInfo for our current region - internal static volatile RegionInfo? s_currentRegionInfo; + internal static RegionInfo? s_currentRegionInfo; public RegionInfo(string name) { @@ -84,7 +84,6 @@ internal RegionInfo(CultureData cultureData) /// /// This instance provides methods based on the current user settings. - /// These settings are volatile and may change over the lifetime of the /// public static RegionInfo CurrentRegion { diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/TaiwanCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/TaiwanCalendar.cs index 8a282b12457d..ae935e6011a9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/TaiwanCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/TaiwanCalendar.cs @@ -27,7 +27,7 @@ public class TaiwanCalendar : Calendar new EraInfo(1, 1912, 1, 1, 1911, 1, GregorianCalendar.MaxYear - 1911) // era #, start year/month/day, yearOffset, minEraYear }; - private static volatile Calendar? s_defaultInstance; + private static Calendar? s_defaultInstance; private readonly GregorianCalendarHelper _helper; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.WebAssembly.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.WebAssembly.cs index a2dd2a02c05f..05e8cc3e1d04 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.WebAssembly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.WebAssembly.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Runtime.InteropServices; namespace System.Globalization { @@ -13,18 +14,14 @@ internal unsafe void JsChangeCase(char* src, int srcLen, char* dstBuffer, int ds Debug.Assert(!GlobalizationMode.UseNls); Debug.Assert(GlobalizationMode.Hybrid); - int exception; - object ex_result; - if (HasEmptyCultureName) + ReadOnlySpan cultureName = _cultureName.AsSpan(); + fixed (char* pCultureName = &MemoryMarshal.GetReference(cultureName)) { - Interop.JsGlobalization.ChangeCaseInvariant(src, srcLen, dstBuffer, dstBufferCapacity, toUpper, out exception, out ex_result); + nint exceptionPtr = HasEmptyCultureName ? + Interop.JsGlobalization.ChangeCaseInvariant(src, srcLen, dstBuffer, dstBufferCapacity, toUpper) : + Interop.JsGlobalization.ChangeCase(pCultureName, cultureName.Length, src, srcLen, dstBuffer, dstBufferCapacity, toUpper); + Helper.MarshalAndThrowIfException(exceptionPtr); } - else - { - Interop.JsGlobalization.ChangeCase(_cultureName, src, srcLen, dstBuffer, dstBufferCapacity, toUpper, out exception, out ex_result); - } - if (exception != 0) - throw new Exception((string)ex_result); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanFormat.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanFormat.cs index 8c8bea12bbf6..48faa5b1a983 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanFormat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanFormat.cs @@ -311,7 +311,7 @@ private static void FormatCustomized(TimeSpan value, scoped ReadOnlySpan< int seconds = (int)(time / TimeSpan.TicksPerSecond % 60); int fraction = (int)(time % TimeSpan.TicksPerSecond); - long tmp; + int tmp; int i = 0; int tokenLen; @@ -356,8 +356,8 @@ private static void FormatCustomized(TimeSpan value, scoped ReadOnlySpan< } tmp = fraction; - tmp /= TimeSpanParse.Pow10(DateTimeFormat.MaxSecondsFractionDigits - tokenLen); - DateTimeFormat.FormatFraction(ref result, (int)tmp, DateTimeFormat.fixedNumberFormats[tokenLen - 1]); + tmp /= TimeSpanParse.Pow10UpToMaxFractionDigits(DateTimeFormat.MaxSecondsFractionDigits - tokenLen); + DateTimeFormat.FormatFraction(ref result, tmp, DateTimeFormat.fixedNumberFormats[tokenLen - 1]); break; case 'F': // @@ -370,7 +370,7 @@ private static void FormatCustomized(TimeSpan value, scoped ReadOnlySpan< } tmp = fraction; - tmp /= TimeSpanParse.Pow10(DateTimeFormat.MaxSecondsFractionDigits - tokenLen); + tmp /= TimeSpanParse.Pow10UpToMaxFractionDigits(DateTimeFormat.MaxSecondsFractionDigits - tokenLen); int effectiveDigits = tokenLen; while (effectiveDigits > 0) { @@ -386,7 +386,7 @@ private static void FormatCustomized(TimeSpan value, scoped ReadOnlySpan< } if (effectiveDigits > 0) { - DateTimeFormat.FormatFraction(ref result, (int)tmp, DateTimeFormat.fixedNumberFormats[effectiveDigits - 1]); + DateTimeFormat.FormatFraction(ref result, tmp, DateTimeFormat.fixedNumberFormats[effectiveDigits - 1]); } break; case 'd': diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanParse.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanParse.cs index c900e64dcb96..033d0abe4e90 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanParse.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanParse.cs @@ -47,6 +47,7 @@ // //////////////////////////////////////////////////////////////////////////// +using System.Buffers.Text; using System.Diagnostics; using System.Text; @@ -114,7 +115,7 @@ public bool NormalizeAndValidateFraction() if (_zeroes == 0 && _num > MaxFraction) return false; - int totalDigitsCount = ((int)Math.Floor(Math.Log10(_num))) + 1 + _zeroes; + int totalDigitsCount = FormattingHelpers.CountDigits((uint)_num) + _zeroes; if (totalDigitsCount == MaxFractionDigits) { @@ -132,7 +133,7 @@ public bool NormalizeAndValidateFraction() // .000001 normalize to 10 ticks // .1 normalize to 1,000,000 ticks - _num *= (int)Pow10(MaxFractionDigits - totalDigitsCount); + _num *= Pow10UpToMaxFractionDigits(MaxFractionDigits - totalDigitsCount); return true; } @@ -143,7 +144,18 @@ public bool NormalizeAndValidateFraction() // .099999999 normalize to 1,000,000 ticks Debug.Assert(_zeroes > 0); // Already validated that in the condition _zeroes == 0 && _num > MaxFraction - _num = (int)Math.Round((double)_num / Pow10(totalDigitsCount - MaxFractionDigits), MidpointRounding.AwayFromZero); + + if (_zeroes > MaxFractionDigits) + { + // If there are 8 leading zeroes, it rounds to zero + _num = 0; + return true; + } + + Debug.Assert(totalDigitsCount - MaxFractionDigits <= MaxFractionDigits); + uint power = (uint)Pow10UpToMaxFractionDigits(totalDigitsCount - MaxFractionDigits); + // Unsigned integer division, rounding away from zero + _num = (int)(((uint)_num + power / 2) / power); Debug.Assert(_num < MaxFraction); return true; @@ -563,20 +575,21 @@ internal bool SetBadFormatSpecifierFailure(char? formatSpecifierCharacter = null } } - internal static long Pow10(int pow) + internal static int Pow10UpToMaxFractionDigits(int pow) { - return pow switch - { - 0 => 1, - 1 => 10, - 2 => 100, - 3 => 1000, - 4 => 10000, - 5 => 100000, - 6 => 1000000, - 7 => 10000000, - _ => (long)Math.Pow(10, pow), - }; + ReadOnlySpan powersOfTen = + [ + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + ]; + Debug.Assert(powersOfTen.Length == MaxFractionDigits + 1); + return powersOfTen[pow]; } private static bool TryTimeToTicks(bool positive, TimeSpanToken days, TimeSpanToken hours, TimeSpanToken minutes, TimeSpanToken seconds, TimeSpanToken fraction, out long result) diff --git a/src/libraries/System.Private.CoreLib/src/System/Half.cs b/src/libraries/System.Private.CoreLib/src/System/Half.cs index adc7df07932f..533521970c7e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Half.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Half.cs @@ -1314,6 +1314,14 @@ public static bool IsPow2(Half value) /// public static Half Ceiling(Half x) => (Half)MathF.Ceiling((float)x); + /// + public static TInteger ConvertToInteger(Half value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + public static TInteger ConvertToIntegerNative(Half value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + /// public static Half Floor(Half x) => (Half)MathF.Floor((float)x); @@ -1912,6 +1920,9 @@ public static Half MinMagnitudeNumber(Half x, Half y) return y; } + /// + public static Half MultiplyAddEstimate(Half left, Half right, Half addend) => (Half)float.MultiplyAddEstimate((float)left, (float)right, (float)addend); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out Half result) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs index 9d1dced98c8c..7b828df7720d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs @@ -371,7 +371,16 @@ public static string Combine(string path1, string path2, string path3, string pa public static string Combine(params string[] paths) { ArgumentNullException.ThrowIfNull(paths); + return Combine((ReadOnlySpan)paths); + } + /// + /// Combines a span of strings into a path. + /// + /// A span of parts of the path. + /// The combined paths. + public static string Combine(params ReadOnlySpan paths) + { int maxSize = 0; int firstComponent = 0; @@ -520,8 +529,17 @@ public static string Join(string? path1, string? path2, string? path3, string? p public static string Join(params string?[] paths) { ArgumentNullException.ThrowIfNull(paths); + return Join((ReadOnlySpan)paths); + } - if (paths.Length == 0) + /// + /// Concatenates a span of paths into a single path. + /// + /// A span of paths. + /// The concatenated path. + public static string Join(params ReadOnlySpan paths) + { + if (paths.IsEmpty) { return string.Empty; } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs index 86d01528643b..47d847f351d2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs @@ -22,9 +22,7 @@ public abstract class Stream : MarshalByRefObject, IDisposable, IAsyncDisposable private protected SemaphoreSlim EnsureAsyncActiveSemaphoreInitialized() => // Lazily-initialize _asyncActiveSemaphore. As we're never accessing the SemaphoreSlim's // WaitHandle, we don't need to worry about Disposing it in the case of a race condition. -#pragma warning disable CS8774 // We lack a NullIffNull annotation for Volatile.Read - Volatile.Read(ref _asyncActiveSemaphore) ?? -#pragma warning restore CS8774 + _asyncActiveSemaphore ?? Interlocked.CompareExchange(ref _asyncActiveSemaphore, new SemaphoreSlim(1, 1), null) ?? _asyncActiveSemaphore; diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs index d11c1313ba84..58efa18407c7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs @@ -568,6 +568,23 @@ public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] } } + /// + /// Writes a formatted string to the stream, using the same semantics as . + /// + /// A composite format string. + /// An object span that contains zero or more objects to format and write. + public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan arg) + { + if (GetType() == typeof(StreamWriter)) + { + WriteFormatHelper(format, arg, appendNewLine: false); + } + else + { + base.Write(format, arg); + } + } + public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0) { if (GetType() == typeof(StreamWriter)) @@ -619,6 +636,23 @@ public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeForm } } + /// + /// Writes out a formatted string and a new line to the stream, using the same semantics as . + /// + /// A composite format string. + /// An object span that contains zero or more objects to format and write. + public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan arg) + { + if (GetType() == typeof(StreamWriter)) + { + WriteFormatHelper(format, arg, appendNewLine: true); + } + else + { + base.WriteLine(format, arg); + } + } + public override Task WriteAsync(char value) { // If we have been inherited into a subclass, the following implementation could be incorrect diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StringWriter.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StringWriter.cs index 9b5eee9d8c04..8fc4bb83cd08 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StringWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StringWriter.cs @@ -12,7 +12,7 @@ namespace System.IO // the resulting sequence of characters to be presented as a string. public class StringWriter : TextWriter { - private static volatile UnicodeEncoding? s_encoding; + private static UnicodeEncoding? s_encoding; private readonly StringBuilder _sb; private bool _isOpen; diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.CreateBroadcasting.cs b/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.CreateBroadcasting.cs index 41fdf7eb56f9..0637cafb27e9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.CreateBroadcasting.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.CreateBroadcasting.cs @@ -268,6 +268,14 @@ public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] } } + public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan arg) + { + foreach (TextWriter writer in _writers) + { + writer.Write(format, arg); + } + } + public override void WriteLine() { foreach (TextWriter writer in _writers) @@ -428,6 +436,14 @@ public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeForm } } + public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan arg) + { + foreach (TextWriter writer in _writers) + { + writer.WriteLine(format, arg); + } + } + public override async Task WriteAsync(char value) { foreach (TextWriter writer in _writers) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs b/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs index 289ec5fac7a5..a6070683047a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs @@ -317,6 +317,16 @@ public virtual void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] Write(string.Format(FormatProvider, format, arg)); } + /// + /// Writes a formatted string to the text stream, using the same semantics as . + /// + /// A composite format string. + /// An object span that contains zero or more objects to format and write. + public virtual void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan arg) + { + Write(string.Format(FormatProvider, format, arg)); + } + // Writes a line terminator to the text stream. The default line terminator // is Environment.NewLine, but this value can be changed by setting the NewLine property. // @@ -514,6 +524,16 @@ public virtual void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeForma WriteLine(string.Format(FormatProvider, format, arg)); } + /// + /// Writes out a formatted string and a new line to the text stream, using the same semantics as . + /// + /// A composite format string. + /// An object span that contains zero or more objects to format and write. + public virtual void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan arg) + { + WriteLine(string.Format(FormatProvider, format, arg)); + } + #region Task based Async APIs public virtual Task WriteAsync(char value) => Task.Factory.StartNew(static state => @@ -700,6 +720,7 @@ public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1) { } public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1, object? arg2) { } public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params object?[] arg) { } + public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan arg) { } public override Task WriteAsync(char value) => Task.CompletedTask; public override Task WriteAsync(string? value) => Task.CompletedTask; public override Task WriteAsync(StringBuilder? value, CancellationToken cancellationToken = default) => Task.CompletedTask; @@ -725,6 +746,7 @@ public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeForm public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1) { } public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1, object? arg2) { } public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params object?[] arg) { } + public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan arg) { } public override Task WriteLineAsync(char value) => Task.CompletedTask; public override Task WriteLineAsync(string? value) => Task.CompletedTask; public override Task WriteLineAsync(StringBuilder? value, CancellationToken cancellationToken = default) => Task.CompletedTask; @@ -833,6 +855,9 @@ protected override void Dispose(bool disposing) [MethodImpl(MethodImplOptions.Synchronized)] public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object?[] arg) => _out.Write(format, arg); + [MethodImpl(MethodImplOptions.Synchronized)] + public override void Write([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, ReadOnlySpan arg) => _out.Write(format, arg); + [MethodImpl(MethodImplOptions.Synchronized)] public override void WriteLine() => _out.WriteLine(); @@ -893,6 +918,9 @@ protected override void Dispose(bool disposing) [MethodImpl(MethodImplOptions.Synchronized)] public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object?[] arg) => _out.WriteLine(format, arg); + [MethodImpl(MethodImplOptions.Synchronized)] + public override void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, ReadOnlySpan arg) => _out.WriteLine(format, arg); + // // On SyncTextWriter all APIs should run synchronously, even the async ones. // diff --git a/src/libraries/System.Private.CoreLib/src/System/Int128.cs b/src/libraries/System.Private.CoreLib/src/System/Int128.cs index c1e6c459f7b5..241c1c39e71d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int128.cs @@ -1043,57 +1043,39 @@ public static Int128 Log2(Int128 value) /// public static bool operator <(Int128 left, Int128 right) { - if (IsNegative(left) == IsNegative(right)) - { - return (left._upper < right._upper) - || ((left._upper == right._upper) && (left._lower < right._lower)); - } - else - { - return IsNegative(left); - } + // If left and right have different signs: Signed comparison of _upper gives result since it is stored as two's complement + // If signs are equal and left._upper < right._upper: left < right for negative and positive values, + // since _upper is upper 64 bits in two's complement. + // If signs are equal and left._upper > right._upper: left > right for negative and positive values, + // since _upper is upper 64 bits in two's complement. + // If left._upper == right._upper: unsigned comparison of _lower gives the result for both negative and positive values since + // lower values are lower 64 bits in two's complement. + return ((long)left._upper < (long)right._upper) + || ((left._upper == right._upper) && (left._lower < right._lower)); } /// public static bool operator <=(Int128 left, Int128 right) { - if (IsNegative(left) == IsNegative(right)) - { - return (left._upper < right._upper) - || ((left._upper == right._upper) && (left._lower <= right._lower)); - } - else - { - return IsNegative(left); - } + // See comment in < operator for how this works. + return ((long)left._upper < (long)right._upper) + || ((left._upper == right._upper) && (left._lower <= right._lower)); } /// public static bool operator >(Int128 left, Int128 right) { - if (IsNegative(left) == IsNegative(right)) - { - return (left._upper > right._upper) - || ((left._upper == right._upper) && (left._lower > right._lower)); - } - else - { - return IsNegative(right); - } + // See comment in < operator for how this works. + return ((long)left._upper > (long)right._upper) + || ((left._upper == right._upper) && (left._lower > right._lower)); } /// public static bool operator >=(Int128 left, Int128 right) { - if (IsNegative(left) == IsNegative(right)) - { - return (left._upper > right._upper) - || ((left._upper == right._upper) && (left._lower >= right._lower)); - } - else - { - return IsNegative(right); - } + // See comment in < operator for how this works. + return ((long)left._upper > (long)right._upper) + || ((left._upper == right._upper) && (left._lower >= right._lower)); } // @@ -1539,6 +1521,9 @@ public static Int128 MinMagnitude(Int128 x, Int128 y) /// static Int128 INumberBase.MinMagnitudeNumber(Int128 x, Int128 y) => MinMagnitude(x, y); + /// + static Int128 INumberBase.MultiplyAddEstimate(Int128 left, Int128 right, Int128 addend) => (left * right) + addend; + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out Int128 result) => TryConvertFromChecked(value, out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/Int16.cs b/src/libraries/System.Private.CoreLib/src/System/Int16.cs index af144fb860c9..e963c0df0132 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int16.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int16.cs @@ -876,6 +876,9 @@ public static short MinMagnitude(short x, short y) /// static short INumberBase.MinMagnitudeNumber(short x, short y) => MinMagnitude(x, y); + /// + static short INumberBase.MultiplyAddEstimate(short left, short right, short addend) => (short)((left * right) + addend); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out short result) => TryConvertFromChecked(value, out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/Int32.cs b/src/libraries/System.Private.CoreLib/src/System/Int32.cs index 2f91c2c2a597..e0406ecbd5c0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int32.cs @@ -911,6 +911,9 @@ public static int MinMagnitude(int x, int y) /// static int INumberBase.MinMagnitudeNumber(int x, int y) => MinMagnitude(x, y); + /// + static int INumberBase.MultiplyAddEstimate(int left, int right, int addend) => (left * right) + addend; + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out int result) => TryConvertFromChecked(value, out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/Int64.cs b/src/libraries/System.Private.CoreLib/src/System/Int64.cs index ca170d8c903e..54d69da8b227 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int64.cs @@ -908,6 +908,9 @@ public static long MinMagnitude(long x, long y) /// static long INumberBase.MinMagnitudeNumber(long x, long y) => MinMagnitude(x, y); + /// + static long INumberBase.MultiplyAddEstimate(long left, long right, long addend) => (long)((left * right) + addend); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out long result) => TryConvertFromChecked(value, out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs index 3dd33c2c66b8..fb2dec11f306 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs @@ -919,6 +919,9 @@ public static nint MinMagnitude(nint x, nint y) /// static nint INumberBase.MinMagnitudeNumber(nint x, nint y) => MinMagnitude(x, y); + /// + static nint INumberBase.MultiplyAddEstimate(nint left, nint right, nint addend) => (left * right) + addend; + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out nint result) => TryConvertFromChecked(value, out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/LocalDataStoreSlot.cs b/src/libraries/System.Private.CoreLib/src/System/LocalDataStoreSlot.cs index 257fe85bfeab..23adf4a566eb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/LocalDataStoreSlot.cs +++ b/src/libraries/System.Private.CoreLib/src/System/LocalDataStoreSlot.cs @@ -14,7 +14,7 @@ internal LocalDataStoreSlot(ThreadLocal data) GC.SuppressFinalize(this); } - internal ThreadLocal Data { get; private set; } + internal ThreadLocal Data { get; } [SuppressMessage("Microsoft.Security", "CA1821", Justification = "Finalizer preserved for compat, it is suppressed by the constructor.")] ~LocalDataStoreSlot() diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs index e2fe2051ce5c..380b63e5416c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Math.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs @@ -154,7 +154,9 @@ internal static void ThrowNegateTwosCompOverflow() [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static unsafe ulong BigMul(uint a, uint b) { -#if TARGET_32BIT +#if false // TARGET_32BIT + // This generates slower code currently than the simple multiplication + // https://github.com/dotnet/runtime/issues/11782 if (Bmi2.IsSupported) { uint low; @@ -1195,19 +1197,14 @@ public static double MinMagnitude(double x, double y) /// On ARM64 hardware this may use the FRECPE instruction which performs a single Newton-Raphson iteration. /// On hardware without specialized support, this may just return 1.0 / d. /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static double ReciprocalEstimate(double d) { - // x86 doesn't provide an estimate instruction for double-precision reciprocal - - if (AdvSimd.Arm64.IsSupported) - { - return AdvSimd.Arm64.ReciprocalEstimateScalar(Vector64.CreateScalar(d)).ToScalar(); - } - else - { - return 1.0 / d; - } +#if MONO + return 1.0 / d; +#else + return ReciprocalEstimate(d); +#endif } /// Returns an estimate of the reciprocal square root of a specified number. @@ -1217,19 +1214,14 @@ public static double ReciprocalEstimate(double d) /// On ARM64 hardware this may use the FRSQRTE instruction which performs a single Newton-Raphson iteration. /// On hardware without specialized support, this may just return 1.0 / Sqrt(d). /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static double ReciprocalSqrtEstimate(double d) { - // x86 doesn't provide an estimate instruction for double-precision reciprocal square root - - if (AdvSimd.Arm64.IsSupported) - { - return AdvSimd.Arm64.ReciprocalSquareRootEstimateScalar(Vector64.CreateScalar(d)).ToScalar(); - } - else - { - return 1.0 / Sqrt(d); - } +#if MONO || TARGET_RISCV64 || TARGET_LOONGARCH64 + return 1.0 / Sqrt(d); +#else + return ReciprocalSqrtEstimate(d); +#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1492,5 +1484,182 @@ public static double ScaleB(double x, int n) double u = BitConverter.Int64BitsToDouble(((long)(0x3ff + n) << 52)); return y * u; } + + // + // Helpers, those methods are referenced from the JIT + // + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint High32Bits(ulong a) => (uint)(a >> 32); + + [StackTraceHidden] + internal static long MultiplyChecked(long left, long right) + { +#if DEBUG + long result = left * right; +#endif + + // Remember the sign of the result + int sign = (int)(High32Bits((ulong)left) ^ High32Bits((ulong)right)); + + // Convert to unsigned multiplication + if (left < 0) + left = -left; + if (right < 0) + right = -right; + + // Get the upper 32 bits of the numbers + uint val1High = High32Bits((ulong)left); + uint val2High = High32Bits((ulong)right); + + ulong valMid; + + if (val1High == 0) + { + // Compute the 'middle' bits of the long multiplication + valMid = BigMul(val2High, (uint)left); + } + else + { + if (val2High != 0) + goto Overflow; + // Compute the 'middle' bits of the long multiplication + valMid = BigMul(val1High, (uint)right); + } + + // See if any bits after bit 32 are set + if (High32Bits(valMid) != 0) + goto Overflow; + + long ret = (long)(BigMul((uint)left, (uint)right) + (valMid << 32)); + + // check for overflow + if (High32Bits((ulong)ret) < (uint)valMid) + goto Overflow; + + if (sign >= 0) + { + // have we spilled into the sign bit? + if (ret < 0) + goto Overflow; + } + else + { + ret = -ret; + // have we spilled into the sign bit? + if (ret > 0) + goto Overflow; + } + +#if DEBUG + Debug.Assert(ret == result, $"Multiply overflow got: {ret}, expected: {result}"); +#endif + return ret; + + Overflow: + ThrowHelper.ThrowOverflowException(); + return 0; + } + + [StackTraceHidden] + internal static ulong MultiplyChecked(ulong left, ulong right) + { + // Get the upper 32 bits of the numbers + uint val1High = High32Bits(left); + uint val2High = High32Bits(right); + + ulong valMid; + + if (val1High == 0) + { + if (val2High == 0) + return (ulong)(uint)left * (uint)right; + // Compute the 'middle' bits of the long multiplication + valMid = BigMul(val2High, (uint)left); + } + else + { + if (val2High != 0) + goto Overflow; + // Compute the 'middle' bits of the long multiplication + valMid = BigMul(val1High, (uint)right); + } + + // See if any bits after bit 32 are set + if (High32Bits(valMid) != 0) + goto Overflow; + + ulong ret = BigMul((uint)left, (uint)right) + (valMid << 32); + + // check for overflow + if (High32Bits(ret) < (uint)valMid) + goto Overflow; + + Debug.Assert(ret == left * right, $"Multiply overflow got: {ret}, expected: {left * right}"); + return ret; + + Overflow: + ThrowHelper.ThrowOverflowException(); + return 0; + } + + private const double Int32MaxValueOffset = (double)int.MaxValue + 1; + private const double UInt32MaxValueOffset = (double)uint.MaxValue + 1; + + [StackTraceHidden] + internal static int ConvertToInt32Checked(double value) + { + // Note that this expression also works properly for val = NaN case + if (value is > -Int32MaxValueOffset - 1 and < Int32MaxValueOffset) + { + return double.ConvertToIntegerNative(value); + } + + ThrowHelper.ThrowOverflowException(); + return 0; + } + + [StackTraceHidden] + internal static uint ConvertToUInt32Checked(double value) + { + // Note that this expression also works properly for val = NaN case + if (value is > -1.0 and < UInt32MaxValueOffset) + { + return double.ConvertToIntegerNative(value); + } + + ThrowHelper.ThrowOverflowException(); + return 0; + } + + [StackTraceHidden] + internal static long ConvertToInt64Checked(double value) + { + const double two63 = Int32MaxValueOffset * UInt32MaxValueOffset; + + // Note that this expression also works properly for val = NaN case + // We need to compare with the very next double to two63. 0x402 is epsilon to get us there. + if (value is > -two63 - 0x402 and < two63) + { + return double.ConvertToIntegerNative(value); + } + + ThrowHelper.ThrowOverflowException(); + return 0; + } + + [StackTraceHidden] + internal static ulong ConvertToUInt64Checked(double value) + { + const double two64 = UInt32MaxValueOffset * UInt32MaxValueOffset; + // Note that this expression also works properly for val = NaN case + if (value is > -1.0 and < two64) + { + return double.ConvertToIntegerNative(value); + } + + ThrowHelper.ThrowOverflowException(); + return 0; + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/MathF.cs b/src/libraries/System.Private.CoreLib/src/System/MathF.cs index cc0795255d0c..31e749060226 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MathF.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MathF.cs @@ -313,21 +313,14 @@ public static float MinMagnitude(float x, float y) /// On ARM64 hardware this may use the FRECPE instruction which performs a single Newton-Raphson iteration. /// On hardware without specialized support, this may just return 1.0 / x. /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static float ReciprocalEstimate(float x) { - if (Sse.IsSupported) - { - return Sse.ReciprocalScalar(Vector128.CreateScalarUnsafe(x)).ToScalar(); - } - else if (AdvSimd.Arm64.IsSupported) - { - return AdvSimd.Arm64.ReciprocalEstimateScalar(Vector64.CreateScalarUnsafe(x)).ToScalar(); - } - else - { - return 1.0f / x; - } +#if MONO + return 1.0f / x; +#else + return ReciprocalEstimate(x); +#endif } /// Returns an estimate of the reciprocal square root of a specified number. @@ -338,21 +331,14 @@ public static float ReciprocalEstimate(float x) /// On ARM64 hardware this may use the FRSQRTE instruction which performs a single Newton-Raphson iteration. /// On hardware without specialized support, this may just return 1.0 / Sqrt(x). /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Intrinsic] public static float ReciprocalSqrtEstimate(float x) { - if (Sse.IsSupported) - { - return Sse.ReciprocalSqrtScalar(Vector128.CreateScalarUnsafe(x)).ToScalar(); - } - else if (AdvSimd.Arm64.IsSupported) - { - return AdvSimd.Arm64.ReciprocalSquareRootEstimateScalar(Vector64.CreateScalarUnsafe(x)).ToScalar(); - } - else - { - return 1.0f / Sqrt(x); - } +#if MONO || TARGET_RISCV64 || TARGET_LOONGARCH64 + return 1.0f / Sqrt(x); +#else + return ReciprocalSqrtEstimate(x); +#endif } [Intrinsic] diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index 83ea307fc857..f088e3ced535 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -323,28 +323,28 @@ public static unsafe bool Contains(this Span span, T value) where T : IEqu { return SpanHelpers.ContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.ContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(int)) { return SpanHelpers.ContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(long)) { return SpanHelpers.ContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } } @@ -367,28 +367,28 @@ public static unsafe bool Contains(this ReadOnlySpan span, T value) where { return SpanHelpers.ContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.ContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(int)) { return SpanHelpers.ContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(long)) { return SpanHelpers.ContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } } @@ -623,25 +623,25 @@ public static unsafe int IndexOf(this Span span, T value) where T : IEquat if (sizeof(T) == sizeof(byte)) return SpanHelpers.IndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); if (sizeof(T) == sizeof(short)) return SpanHelpers.IndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); if (sizeof(T) == sizeof(int)) return SpanHelpers.IndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); if (sizeof(T) == sizeof(long)) return SpanHelpers.IndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } @@ -690,28 +690,28 @@ public static unsafe int LastIndexOf(this Span span, T value) where T : IE { return SpanHelpers.LastIndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.LastIndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(int)) { return SpanHelpers.LastIndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(long)) { return SpanHelpers.LastIndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } } @@ -826,28 +826,28 @@ public static unsafe int IndexOfAnyExcept(this ReadOnlySpan span, T value) { return SpanHelpers.IndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.IndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(int)) { return SpanHelpers.IndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(long)) { return SpanHelpers.IndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } } @@ -873,16 +873,16 @@ public static unsafe int IndexOfAnyExcept(this ReadOnlySpan span, T value0 { return SpanHelpers.IndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.IndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), span.Length); } } @@ -909,18 +909,18 @@ public static unsafe int IndexOfAnyExcept(this ReadOnlySpan span, T value0 { return SpanHelpers.IndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.IndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), span.Length); } } @@ -937,20 +937,20 @@ private static unsafe int IndexOfAnyExcept(this ReadOnlySpan span, T value { return SpanHelpers.IndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), - Unsafe.As(ref value3), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), + Unsafe.BitCast(value3), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.IndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), - Unsafe.As(ref value3), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), + Unsafe.BitCast(value3), span.Length); } } @@ -1135,28 +1135,28 @@ public static unsafe int LastIndexOfAnyExcept(this ReadOnlySpan span, T va { return SpanHelpers.LastIndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.LastIndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(int)) { return SpanHelpers.LastIndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(long)) { return SpanHelpers.LastIndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } } @@ -1182,16 +1182,16 @@ public static unsafe int LastIndexOfAnyExcept(this ReadOnlySpan span, T va { return SpanHelpers.LastIndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.LastIndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), span.Length); } } @@ -1218,18 +1218,18 @@ public static unsafe int LastIndexOfAnyExcept(this ReadOnlySpan span, T va { return SpanHelpers.LastIndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.LastIndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), span.Length); } } @@ -1246,20 +1246,20 @@ private static unsafe int LastIndexOfAnyExcept(this ReadOnlySpan span, T v { return SpanHelpers.LastIndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), - Unsafe.As(ref value3), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), + Unsafe.BitCast(value3), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.LastIndexOfAnyExceptValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), - Unsafe.As(ref value3), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), + Unsafe.BitCast(value3), span.Length); } } @@ -1399,8 +1399,8 @@ public static int IndexOfAnyInRange(this ReadOnlySpan span, T lowInclusive { return SpanHelpers.IndexOfAnyInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } @@ -1408,8 +1408,8 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), { return SpanHelpers.IndexOfAnyInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } @@ -1417,8 +1417,8 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), { return SpanHelpers.IndexOfAnyInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } @@ -1426,8 +1426,8 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), { return SpanHelpers.IndexOfAnyInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } } @@ -1465,8 +1465,8 @@ public static int IndexOfAnyExceptInRange(this ReadOnlySpan span, T lowInc { return SpanHelpers.IndexOfAnyExceptInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } @@ -1474,8 +1474,8 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), { return SpanHelpers.IndexOfAnyExceptInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } @@ -1483,8 +1483,8 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), { return SpanHelpers.IndexOfAnyExceptInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } @@ -1492,8 +1492,8 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), { return SpanHelpers.IndexOfAnyExceptInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } } @@ -1531,8 +1531,8 @@ public static int LastIndexOfAnyInRange(this ReadOnlySpan span, T lowInclu { return SpanHelpers.LastIndexOfAnyInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } @@ -1540,8 +1540,8 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), { return SpanHelpers.LastIndexOfAnyInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } @@ -1549,8 +1549,8 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), { return SpanHelpers.LastIndexOfAnyInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } @@ -1558,8 +1558,8 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), { return SpanHelpers.LastIndexOfAnyInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } } @@ -1597,8 +1597,8 @@ public static int LastIndexOfAnyExceptInRange(this ReadOnlySpan span, T lo { return SpanHelpers.LastIndexOfAnyExceptInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } @@ -1606,8 +1606,8 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), { return SpanHelpers.LastIndexOfAnyExceptInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } @@ -1615,8 +1615,8 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), { return SpanHelpers.LastIndexOfAnyExceptInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } @@ -1624,8 +1624,8 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), { return SpanHelpers.LastIndexOfAnyExceptInRangeUnsignedNumber( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref lowInclusive), - Unsafe.As(ref highInclusive), + Unsafe.BitCast(lowInclusive), + Unsafe.BitCast(highInclusive), span.Length); } } @@ -1702,25 +1702,25 @@ public static unsafe int IndexOf(this ReadOnlySpan span, T value) where T if (sizeof(T) == sizeof(byte)) return SpanHelpers.IndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); if (sizeof(T) == sizeof(short)) return SpanHelpers.IndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); if (sizeof(T) == sizeof(int)) return SpanHelpers.IndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); if (sizeof(T) == sizeof(long)) return SpanHelpers.IndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } @@ -1769,28 +1769,28 @@ public static unsafe int LastIndexOf(this ReadOnlySpan span, T value) wher { return SpanHelpers.LastIndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.LastIndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(int)) { return SpanHelpers.LastIndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (sizeof(T) == sizeof(long)) { return SpanHelpers.LastIndexOfValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } } @@ -1844,16 +1844,16 @@ public static unsafe int IndexOfAny(this Span span, T value0, T value1) wh { return SpanHelpers.IndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.IndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), span.Length); } } @@ -1877,18 +1877,18 @@ public static unsafe int IndexOfAny(this Span span, T value0, T value1, T { return SpanHelpers.IndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.IndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), span.Length); } } @@ -1938,16 +1938,16 @@ public static unsafe int IndexOfAny(this ReadOnlySpan span, T value0, T va { return SpanHelpers.IndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.IndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), span.Length); } } @@ -1971,18 +1971,18 @@ public static unsafe int IndexOfAny(this ReadOnlySpan span, T value0, T va { return SpanHelpers.IndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.IndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), span.Length); } } @@ -2150,16 +2150,16 @@ public static unsafe int LastIndexOfAny(this Span span, T value0, T value1 { return SpanHelpers.LastIndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.LastIndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), span.Length); } } @@ -2183,18 +2183,18 @@ public static unsafe int LastIndexOfAny(this Span span, T value0, T value1 { return SpanHelpers.LastIndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.LastIndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), span.Length); } } @@ -2235,16 +2235,16 @@ public static unsafe int LastIndexOfAny(this ReadOnlySpan span, T value0, { return SpanHelpers.LastIndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.LastIndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), span.Length); } } @@ -2268,18 +2268,18 @@ public static unsafe int LastIndexOfAny(this ReadOnlySpan span, T value0, { return SpanHelpers.LastIndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), span.Length); } else if (sizeof(T) == sizeof(short)) { return SpanHelpers.LastIndexOfAnyValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value0), - Unsafe.As(ref value1), - Unsafe.As(ref value2), + Unsafe.BitCast(value0), + Unsafe.BitCast(value1), + Unsafe.BitCast(value2), span.Length); } } @@ -3382,8 +3382,8 @@ public static unsafe void Replace(this Span span, T oldValue, T newValue) SpanHelpers.ReplaceValueType( ref src, ref src, - Unsafe.As(ref oldValue), - Unsafe.As(ref newValue), + Unsafe.BitCast(oldValue), + Unsafe.BitCast(newValue), length); return; } @@ -3394,8 +3394,8 @@ public static unsafe void Replace(this Span span, T oldValue, T newValue) SpanHelpers.ReplaceValueType( ref src, ref src, - Unsafe.As(ref oldValue), - Unsafe.As(ref newValue), + Unsafe.BitCast(oldValue), + Unsafe.BitCast(newValue), length); return; } @@ -3405,8 +3405,8 @@ public static unsafe void Replace(this Span span, T oldValue, T newValue) SpanHelpers.ReplaceValueType( ref src, ref src, - Unsafe.As(ref oldValue), - Unsafe.As(ref newValue), + Unsafe.BitCast(oldValue), + Unsafe.BitCast(newValue), length); return; } @@ -3416,8 +3416,8 @@ public static unsafe void Replace(this Span span, T oldValue, T newValue) SpanHelpers.ReplaceValueType( ref src, ref src, - Unsafe.As(ref oldValue), - Unsafe.As(ref newValue), + Unsafe.BitCast(oldValue), + Unsafe.BitCast(newValue), length); return; } @@ -3469,8 +3469,8 @@ public static unsafe void Replace(this ReadOnlySpan source, Span destin SpanHelpers.ReplaceValueType( ref Unsafe.As(ref src), ref Unsafe.As(ref dst), - Unsafe.As(ref oldValue), - Unsafe.As(ref newValue), + Unsafe.BitCast(oldValue), + Unsafe.BitCast(newValue), length); return; } @@ -3480,8 +3480,8 @@ ref Unsafe.As(ref dst), SpanHelpers.ReplaceValueType( ref Unsafe.As(ref src), ref Unsafe.As(ref dst), - Unsafe.As(ref oldValue), - Unsafe.As(ref newValue), + Unsafe.BitCast(oldValue), + Unsafe.BitCast(newValue), length); return; } @@ -3490,8 +3490,8 @@ ref Unsafe.As(ref dst), SpanHelpers.ReplaceValueType( ref Unsafe.As(ref src), ref Unsafe.As(ref dst), - Unsafe.As(ref oldValue), - Unsafe.As(ref newValue), + Unsafe.BitCast(oldValue), + Unsafe.BitCast(newValue), length); return; } @@ -3500,8 +3500,8 @@ ref Unsafe.As(ref dst), SpanHelpers.ReplaceValueType( ref Unsafe.As(ref src), ref Unsafe.As(ref dst), - Unsafe.As(ref oldValue), - Unsafe.As(ref newValue), + Unsafe.BitCast(oldValue), + Unsafe.BitCast(newValue), length); return; } @@ -3976,28 +3976,28 @@ public static int Count(this ReadOnlySpan span, T value) where T : IEquata { return SpanHelpers.CountValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (Unsafe.SizeOf() == sizeof(short)) { return SpanHelpers.CountValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (Unsafe.SizeOf() == sizeof(int)) { return SpanHelpers.CountValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } else if (Unsafe.SizeOf() == sizeof(long)) { return SpanHelpers.CountValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - Unsafe.As(ref value), + Unsafe.BitCast(value), span.Length); } } @@ -4173,7 +4173,7 @@ public static bool TryWrite(this Span destination, IFormatProvider? provid /// if the entire interpolated string could be formatted successfully; otherwise, . /// is null. /// The index of a format item is greater than or equal to the number of supplied arguments. - public static bool TryWrite(this Span destination, IFormatProvider? provider, CompositeFormat format, out int charsWritten, ReadOnlySpan args) + public static bool TryWrite(this Span destination, IFormatProvider? provider, CompositeFormat format, out int charsWritten, params ReadOnlySpan args) { ArgumentNullException.ThrowIfNull(format); format.ValidateNumberOfArgs(args.Length); diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs b/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs index 8af96fc72569..733faa5320aa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs @@ -31,7 +31,9 @@ internal unsafe ref struct BigInteger private const int MaxBits = BitsForLongestBinaryMantissa + BitsForLongestDigitSequence + BitsPerBlock; private const int BitsPerBlock = sizeof(int) * 8; - private const int MaxBlockCount = (MaxBits + (BitsPerBlock - 1)) / BitsPerBlock; + + // We need one extra block to make our shift left algorithm significantly simpler + private const int MaxBlockCount = ((MaxBits + (BitsPerBlock - 1)) / BitsPerBlock) + 1; private static ReadOnlySpan Pow10UInt32Table => [ @@ -302,7 +304,8 @@ internal unsafe ref struct BigInteger 0xD9D61A05, 0x00000325, - // 9 Trailing blocks to ensure MaxBlockCount + // 10 Trailing blocks to ensure MaxBlockCount + 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -358,11 +361,24 @@ public static void Add(scoped ref BigInteger lhs, scoped ref BigInteger rhs, out resultIndex++; } + int resultLength = largeLength; + // If there's still a carry, append a new block if (carry != 0) { Debug.Assert(carry == 1); - Debug.Assert((resultIndex == largeLength) && (largeLength < MaxBlockCount)); + Debug.Assert(resultIndex == resultLength); + Debug.Assert(unchecked((uint)(resultLength)) < MaxBlockCount); + + if (unchecked((uint)(resultLength)) >= MaxBlockCount) + { + // We shouldn't reach here, and the above assert will help flag this + // during testing, but we'll ensure that we return a safe value of + // zero in the case we end up overflowing in any way. + + SetZero(out result); + return; + } result._blocks[resultIndex] = 1; result._length++; @@ -733,16 +749,27 @@ public static void Multiply(scoped ref BigInteger lhs, uint value, out BigIntege index++; } + int resultLength = lhsLength; + if (carry != 0) { - Debug.Assert(unchecked((uint)(lhsLength)) + 1 <= MaxBlockCount); + Debug.Assert(unchecked((uint)(resultLength)) < MaxBlockCount); + + if (unchecked((uint)(resultLength)) >= MaxBlockCount) + { + // We shouldn't reach here, and the above assert will help flag this + // during testing, but we'll ensure that we return a safe value of + // zero in the case we end up overflowing in any way. + + SetZero(out result); + return; + } + result._blocks[index] = carry; - result._length = (lhsLength + 1); - } - else - { - result._length = lhsLength; + resultLength += 1; } + + result._length = resultLength; } public static void Multiply(scoped ref BigInteger lhs, scoped ref BigInteger rhs, out BigInteger result) @@ -777,6 +804,16 @@ public static void Multiply(scoped ref BigInteger lhs, scoped ref BigInteger rhs int maxResultLength = smallLength + largeLength; Debug.Assert(unchecked((uint)(maxResultLength)) <= MaxBlockCount); + if (unchecked((uint)(maxResultLength)) > MaxBlockCount) + { + // We shouldn't reach here, and the above assert will help flag this + // during testing, but we'll ensure that we return a safe value of + // zero in the case we end up overflowing in any way. + + SetZero(out result); + return; + } + // Zero out result internal blocks. result._length = maxResultLength; result.Clear((uint)maxResultLength); @@ -822,7 +859,19 @@ public static void Pow2(uint exponent, out BigInteger result) { uint blocksToShift = DivRem32(exponent, out uint remainingBitsToShift); result._length = (int)blocksToShift + 1; + Debug.Assert(unchecked((uint)result._length) <= MaxBlockCount); + + if (unchecked((uint)result._length) > MaxBlockCount) + { + // We shouldn't reach here, and the above assert will help flag this + // during testing, but we'll ensure that we return a safe value of + // zero in the case we end up overflowing in any way. + + SetZero(out result); + return; + } + if (blocksToShift > 0) { result.Clear(blocksToShift); @@ -1012,7 +1061,18 @@ public void Add(uint value) } } - Debug.Assert(unchecked((uint)(length)) + 1 <= MaxBlockCount); + Debug.Assert(unchecked((uint)(length)) < MaxBlockCount); + + if (unchecked((uint)(length)) >= MaxBlockCount) + { + // We shouldn't reach here, and the above assert will help flag this + // during testing, but we'll ensure that we return a safe value of + // zero in the case we end up overflowing in any way. + + SetZero(out this); + return; + } + _blocks[length] = 1; _length = length + 1; } @@ -1074,9 +1134,20 @@ public void Multiply10() if (carry != 0) { - Debug.Assert(unchecked((uint)(_length)) + 1 <= MaxBlockCount); + Debug.Assert(unchecked((uint)(length)) < MaxBlockCount); + + if (unchecked((uint)(length)) >= MaxBlockCount) + { + // We shouldn't reach here, and the above assert will help flag this + // during testing, but we'll ensure that we return a safe value of + // zero in the case we end up overflowing in any way. + + SetZero(out this); + return; + } + _blocks[index] = (uint)carry; - _length++; + _length = length + 1; } } @@ -1152,7 +1223,17 @@ public void ShiftLeft(uint shift) // Check if the shift is block aligned if (remainingBitsToShift == 0) { - Debug.Assert(writeIndex < MaxBlockCount); + Debug.Assert(unchecked((uint)(length)) < MaxBlockCount); + + if (unchecked((uint)(length)) >= MaxBlockCount) + { + // We shouldn't reach here, and the above assert will help flag this + // during testing, but we'll ensure that we return a safe value of + // zero in the case we end up overflowing in any way. + + SetZero(out this); + return; + } while (readIndex >= 0) { @@ -1169,8 +1250,19 @@ public void ShiftLeft(uint shift) else { // We need an extra block for the partial shift + writeIndex++; - Debug.Assert(writeIndex < MaxBlockCount); + Debug.Assert(unchecked((uint)(length)) < MaxBlockCount); + + if (unchecked((uint)(length)) >= MaxBlockCount) + { + // We shouldn't reach here, and the above assert will help flag this + // during testing, but we'll ensure that we return a safe value of + // zero in the case we end up overflowing in any way. + + SetZero(out this); + return; + } // Set the length to hold the shifted blocks _length = writeIndex + 1; diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs index ad75d88cbda7..2a89bf963852 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs @@ -269,8 +269,6 @@ internal static partial class Number private const int SinglePrecisionCustomFormat = 7; private const int DoublePrecisionCustomFormat = 15; - private const int CharStackBufferSize = 32; - /// The non-inclusive upper bound of . /// /// This is a semi-arbitrary bound. For mono, which is often used for more size-constrained workloads, diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs index e36c76007bbd..9c92a14f0e75 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs @@ -16,6 +16,26 @@ public interface IFloatingPoint /// The ceiling of . static virtual TSelf Ceiling(TSelf x) => TSelf.Round(x, digits: 0, MidpointRounding.ToPositiveInfinity); + /// Converts a value to a specified integer type using saturation on overflow + /// The integer type to which is converted. + /// The value to be converted. + /// An instance of created from . + static virtual TInteger ConvertToInteger(TSelf value) + where TInteger : IBinaryInteger + { + return TInteger.CreateSaturating(value); + } + + /// Converts a value to a specified integer type using platform specific behavior on overflow. + /// The integer type to which is converted. + /// The value to be converted. + /// An instance of created from . + static virtual TInteger ConvertToIntegerNative(TSelf value) + where TInteger : IBinaryInteger + { + return TSelf.ConvertToInteger(value); + } + /// Computes the floor of a value. /// The value whose floor is to be computed. /// The floor of . diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs index 7e5acfafe75a..eca30a3c3ea1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs @@ -258,6 +258,17 @@ static virtual TSelf CreateTruncating(TOther value) /// For this method matches the IEEE 754:2019 minimumMagnitudeNumber function. This requires NaN inputs to not be propagated back to the caller and for -0.0 to be treated as less than +0.0. static abstract TSelf MinMagnitudeNumber(TSelf x, TSelf y); + /// Computes an estimate of ( * ) + . + /// The value to be multiplied with . + /// The value to be multiplied with . + /// The value to be added to the result of multiplied by . + /// An estimate of ( * ) + . + /// + /// On hardware that natively supports , this may return a result that was rounded as one ternary operation. + /// On hardware without specialized support, this may just return ( * ) + . + /// + static virtual TSelf MultiplyAddEstimate(TSelf left, TSelf right, TSelf addend) => (left * right) + addend; + /// Parses a string into a value. /// The string to parse. /// A bitwise combination of number styles that can be present in . diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs index 5d8bc58bbe26..6bbdf2f74230 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -325,7 +325,7 @@ public static Vector ConvertToDouble(Vector value) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -335,14 +335,31 @@ public static Vector ConvertToInt32(Vector value) for (int i = 0; i < Vector.Count; i++) { - int element = (int)value.GetElementUnsafe(i); + int element = float.ConvertToInteger(value.GetElementUnsafe(i)); result.SetElementUnsafe(i, element); } return result; } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + public static Vector ConvertToInt32Native(Vector value) + { + Unsafe.SkipInit(out Vector result); + + for (int i = 0; i < Vector.Count; i++) + { + int element = float.ConvertToIntegerNative(value.GetElementUnsafe(i)); + result.SetElementUnsafe(i, element); + } + + return result; + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -352,7 +369,24 @@ public static Vector ConvertToInt64(Vector value) for (int i = 0; i < Vector.Count; i++) { - long element = (long)value.GetElementUnsafe(i); + long element = double.ConvertToInteger(value.GetElementUnsafe(i)); + result.SetElementUnsafe(i, element); + } + + return result; + } + + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + public static Vector ConvertToInt64Native(Vector value) + { + Unsafe.SkipInit(out Vector result); + + for (int i = 0; i < Vector.Count; i++) + { + long element = double.ConvertToIntegerNative(value.GetElementUnsafe(i)); result.SetElementUnsafe(i, element); } @@ -396,7 +430,7 @@ public static Vector ConvertToSingle(Vector value) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -407,14 +441,32 @@ public static Vector ConvertToUInt32(Vector value) for (int i = 0; i < Vector.Count; i++) { - uint element = (uint)value.GetElementUnsafe(i); + uint element = float.ConvertToInteger(value.GetElementUnsafe(i)); result.SetElementUnsafe(i, element); } return result; } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + public static Vector ConvertToUInt32Native(Vector value) + { + Unsafe.SkipInit(out Vector result); + + for (int i = 0; i < Vector.Count; i++) + { + uint element = float.ConvertToIntegerNative(value.GetElementUnsafe(i)); + result.SetElementUnsafe(i, element); + } + + return result; + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -425,7 +477,25 @@ public static Vector ConvertToUInt64(Vector value) for (int i = 0; i < Vector.Count; i++) { - ulong element = (ulong)value.GetElementUnsafe(i); + ulong element = double.ConvertToInteger(value.GetElementUnsafe(i)); + result.SetElementUnsafe(i, element); + } + + return result; + } + + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + public static Vector ConvertToUInt64Native(Vector value) + { + Unsafe.SkipInit(out Vector result); + + for (int i = 0; i < Vector.Count; i++) + { + ulong element = double.ConvertToIntegerNative(value.GetElementUnsafe(i)); result.SetElementUnsafe(i, element); } @@ -598,6 +668,54 @@ public static Vector Floor(Vector value) return result; } + /// Computes ( * ) + , rounded as one ternary operation. + /// The vector to be multiplied with . + /// The vector to be multiplied with . + /// The vector to be added to the result of multiplied by . + /// ( * ) + , rounded as one ternary operation. + /// + /// This computes ( * ) as if to infinite precision, adds to that result as if to infinite precision, and finally rounds to the nearest representable value. + /// This differs from the non-fused sequence which would compute ( * ) as if to infinite precision, round the result to the nearest representable value, add to the rounded result as if to infinite precision, and finally round to the nearest representable value. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector FusedMultiplyAdd(Vector left, Vector right, Vector addend) + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + double value = double.FusedMultiplyAdd(left.GetElementUnsafe(index), right.GetElementUnsafe(index), addend.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + + /// Computes ( * ) + , rounded as one ternary operation. + /// The vector to be multiplied with . + /// The vector to be multiplied with . + /// The vector to be added to the result of multiplied by . + /// ( * ) + , rounded as one ternary operation. + /// + /// This computes ( * ) as if to infinite precision, adds to that result as if to infinite precision, and finally rounds to the nearest representable value. + /// This differs from the non-fused sequence which would compute ( * ) as if to infinite precision, round the result to the nearest representable value, add to the rounded result as if to infinite precision, and finally round to the nearest representable value. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector FusedMultiplyAdd(Vector left, Vector right, Vector addend) + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + float value = float.FusedMultiplyAdd(left.GetElementUnsafe(index), right.GetElementUnsafe(index), addend.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + /// Gets the element at the specified index. /// The type of the elements in the vector. /// The vector to get the element from. @@ -1124,6 +1242,38 @@ public static Vector Min(Vector left, Vector right) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector Multiply(T left, Vector right) => left * right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector MultiplyAddEstimate(Vector left, Vector right, Vector addend) + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + double element = double.MultiplyAddEstimate(left.GetElementUnsafe(index), right.GetElementUnsafe(index), addend.GetElementUnsafe(index)); + result.SetElementUnsafe(index, element); + } + + return result; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector MultiplyAddEstimate(Vector left, Vector right, Vector addend) + { + Unsafe.SkipInit(out Vector result); + + for (int index = 0; index < Vector.Count; index++) + { + float element = float.MultiplyAddEstimate(left.GetElementUnsafe(index), right.GetElementUnsafe(index), addend.GetElementUnsafe(index)); + result.SetElementUnsafe(index, element); + } + + return result; + } + /// Narrows two instances into one . /// The vector that will be narrowed to the lower half of the result vector. /// The vector that will be narrowed to the upper half of the result vector. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index e57dee217803..2b27fe4f961e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -326,6 +326,17 @@ public static float Dot(Vector2 value1, Vector2 value2) + (value1.Y * value2.Y); } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 FusedMultiplyAdd(Vector2 left, Vector2 right, Vector2 addend) + { + return new Vector2( + float.FusedMultiplyAdd(left.X, right.X, addend.X), + float.FusedMultiplyAdd(left.Y, right.Y, addend.Y) + ); + } + /// Performs a linear interpolation between two vectors based on the given weighting. /// The first vector. /// The second vector. @@ -402,6 +413,17 @@ public static Vector2 Multiply(float left, Vector2 right) return left * right; } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 MultiplyAddEstimate(Vector2 left, Vector2 right, Vector2 addend) + { + return new Vector2( + float.MultiplyAddEstimate(left.X, right.X, addend.X), + float.MultiplyAddEstimate(left.Y, right.Y, addend.Y) + ); + } + /// Negates a specified vector. /// The vector to negate. /// The negated vector. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index c4739ce80502..382b6838193b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -368,6 +368,18 @@ public static float Dot(Vector3 vector1, Vector3 vector2) + (vector1.Z * vector2.Z); } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 FusedMultiplyAdd(Vector3 left, Vector3 right, Vector3 addend) + { + return new Vector3( + float.FusedMultiplyAdd(left.X, right.X, addend.X), + float.FusedMultiplyAdd(left.Y, right.Y, addend.Y), + float.FusedMultiplyAdd(left.Z, right.Z, addend.Z) + ); + } + /// Performs a linear interpolation between two vectors based on the given weighting. /// The first vector. /// The second vector. @@ -443,6 +455,18 @@ public static Vector3 Multiply(float left, Vector3 right) return left * right; } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 MultiplyAddEstimate(Vector3 left, Vector3 right, Vector3 addend) + { + return new Vector3( + float.MultiplyAddEstimate(left.X, right.X, addend.X), + float.MultiplyAddEstimate(left.Y, right.Y, addend.Y), + float.MultiplyAddEstimate(left.Z, right.Z, addend.Z) + ); + } + /// Negates a specified vector. /// The vector to negate. /// The negated vector. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index 831b4f50d255..6a1a1c39c869 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -384,6 +384,19 @@ public static float Dot(Vector4 vector1, Vector4 vector2) + (vector1.W * vector2.W); } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 FusedMultiplyAdd(Vector4 left, Vector4 right, Vector4 addend) + { + return new Vector4( + float.FusedMultiplyAdd(left.X, right.X, addend.X), + float.FusedMultiplyAdd(left.Y, right.Y, addend.Y), + float.FusedMultiplyAdd(left.Z, right.Z, addend.Z), + float.FusedMultiplyAdd(left.W, right.W, addend.W) + ); + } + /// Performs a linear interpolation between two vectors based on the given weighting. /// The first vector. /// The second vector. @@ -464,6 +477,19 @@ public static Vector4 Multiply(float left, Vector4 right) return left * right; } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 MultiplyAddEstimate(Vector4 left, Vector4 right, Vector4 addend) + { + return new Vector4( + float.MultiplyAddEstimate(left.X, right.X, addend.X), + float.MultiplyAddEstimate(left.Y, right.Y, addend.Y), + float.MultiplyAddEstimate(left.Z, right.Z, addend.Z), + float.MultiplyAddEstimate(left.W, right.W, addend.W) + ); + } + /// Negates a specified vector. /// The vector to negate. /// The negated vector. diff --git a/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs b/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs index b182d42b66ec..e2c49c820d77 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs @@ -10,7 +10,8 @@ using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute; using EditorBrowsableState = System.ComponentModel.EditorBrowsableState; -#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span.Equals(object)' overrides non-obsolete member 'object.Equals(object)' +#pragma warning disable 0809 // Obsolete member 'Span.Equals(object)' overrides non-obsolete member 'object.Equals(object)' +#pragma warning disable 8500 // address / sizeof of managed types namespace System { @@ -107,7 +108,7 @@ public unsafe ReadOnlySpan(void* pointer, int length) if (length < 0) ThrowHelper.ThrowArgumentOutOfRangeException(); - _reference = ref Unsafe.As(ref *(byte*)pointer); + _reference = ref *(T*)pointer; _length = length; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs index d467fd6fb082..12123eb9116b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs @@ -217,13 +217,36 @@ public override string ToString() return type.Module?.Assembly; } - // internal test hook - private static bool s_forceNullEntryPoint; + private static object? s_overriddenEntryAssembly; + + /// + /// Sets the application's entry assembly to the provided assembly object. + /// + /// + /// Assembly object that represents the application's new entry assembly. + /// + /// + /// The assembly passed to this function has to be a runtime defined Assembly + /// type object. Otherwise, an exception will be thrown. + /// + public static void SetEntryAssembly(Assembly? assembly) + { + if (assembly is null) + { + s_overriddenEntryAssembly = string.Empty; + return; + } + + if (assembly is not RuntimeAssembly) + throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly); + + s_overriddenEntryAssembly = assembly; + } public static Assembly? GetEntryAssembly() { - if (s_forceNullEntryPoint) - return null; + if (s_overriddenEntryAssembly is not null) + return s_overriddenEntryAssembly as Assembly; return GetEntryAssemblyInternal(); } @@ -385,6 +408,7 @@ public static Assembly LoadFrom(string assemblyFile) } [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] + [Obsolete(Obsoletions.LoadFromHashAlgorithmMessage, DiagnosticId = Obsoletions.LoadFromHashAlgorithmDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Assembly LoadFrom(string assemblyFile, byte[]? hashValue, AssemblyHashAlgorithm hashAlgorithm) { throw new NotSupportedException(SR.NotSupported_AssemblyLoadFromHash); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs deleted file mode 100644 index dbaaefd4d8c9..000000000000 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs +++ /dev/null @@ -1,438 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.IO; -using System.Runtime.CompilerServices; -using System.Text; - -namespace System.Reflection -{ - // - // Parses an assembly name. - // - internal ref struct AssemblyNameParser - { - public readonly struct AssemblyNameParts - { - public AssemblyNameParts(string name, Version? version, string? cultureName, AssemblyNameFlags flags, byte[]? publicKeyOrToken) - { - _name = name; - _version = version; - _cultureName = cultureName; - _flags = flags; - _publicKeyOrToken = publicKeyOrToken; - } - - public readonly string _name; - public readonly Version? _version; - public readonly string? _cultureName; - public readonly AssemblyNameFlags _flags; - public readonly byte[]? _publicKeyOrToken; - } - - // Token categories for the lexer. - private enum Token - { - Equals = 1, - Comma = 2, - String = 3, - End = 4, - } - - private enum AttributeKind - { - Version = 1, - Culture = 2, - PublicKeyOrToken = 4, - ProcessorArchitecture = 8, - Retargetable = 16, - ContentType = 32 - } - - private readonly ReadOnlySpan _input; - private int _index; - - private AssemblyNameParser(ReadOnlySpan input) - { - if (input.Length == 0) - throw new ArgumentException(SR.Format_StringZeroLength); - - _input = input; - _index = 0; - } - - public static AssemblyNameParts Parse(string name) - { - return new AssemblyNameParser(name).Parse(); - } - - public static AssemblyNameParts Parse(ReadOnlySpan name) - { - return new AssemblyNameParser(name).Parse(); - } - - private void RecordNewSeenOrThrow(scoped ref AttributeKind seenAttributes, AttributeKind newAttribute) - { - if ((seenAttributes & newAttribute) != 0) - { - ThrowInvalidAssemblyName(); - } - seenAttributes |= newAttribute; - } - - private AssemblyNameParts Parse() - { - // Name must come first. - Token token = GetNextToken(out string name); - if (token != Token.String) - ThrowInvalidAssemblyName(); - - if (string.IsNullOrEmpty(name)) - ThrowInvalidAssemblyName(); - - Version? version = null; - string? cultureName = null; - byte[]? pkt = null; - AssemblyNameFlags flags = 0; - - AttributeKind alreadySeen = default; - token = GetNextToken(); - while (token != Token.End) - { - if (token != Token.Comma) - ThrowInvalidAssemblyName(); - - token = GetNextToken(out string attributeName); - if (token != Token.String) - ThrowInvalidAssemblyName(); - - token = GetNextToken(); - if (token != Token.Equals) - ThrowInvalidAssemblyName(); - - token = GetNextToken(out string attributeValue); - if (token != Token.String) - ThrowInvalidAssemblyName(); - - if (attributeName == string.Empty) - ThrowInvalidAssemblyName(); - - if (attributeName.Equals("Version", StringComparison.OrdinalIgnoreCase)) - { - RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.Version); - version = ParseVersion(attributeValue); - } - - if (attributeName.Equals("Culture", StringComparison.OrdinalIgnoreCase)) - { - RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.Culture); - cultureName = ParseCulture(attributeValue); - } - - if (attributeName.Equals("PublicKey", StringComparison.OrdinalIgnoreCase)) - { - RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.PublicKeyOrToken); - pkt = ParsePKT(attributeValue, isToken: false); - flags |= AssemblyNameFlags.PublicKey; - } - - if (attributeName.Equals("PublicKeyToken", StringComparison.OrdinalIgnoreCase)) - { - RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.PublicKeyOrToken); - pkt = ParsePKT(attributeValue, isToken: true); - } - - if (attributeName.Equals("ProcessorArchitecture", StringComparison.OrdinalIgnoreCase)) - { - RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.ProcessorArchitecture); - flags |= (AssemblyNameFlags)(((int)ParseProcessorArchitecture(attributeValue)) << 4); - } - - if (attributeName.Equals("Retargetable", StringComparison.OrdinalIgnoreCase)) - { - RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.Retargetable); - if (attributeValue.Equals("Yes", StringComparison.OrdinalIgnoreCase)) - { - flags |= AssemblyNameFlags.Retargetable; - } - else if (attributeValue.Equals("No", StringComparison.OrdinalIgnoreCase)) - { - // nothing to do - } - else - { - ThrowInvalidAssemblyName(); - } - } - - if (attributeName.Equals("ContentType", StringComparison.OrdinalIgnoreCase)) - { - RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.ContentType); - if (attributeValue.Equals("WindowsRuntime", StringComparison.OrdinalIgnoreCase)) - { - flags |= (AssemblyNameFlags)(((int)AssemblyContentType.WindowsRuntime) << 9); - } - else - { - ThrowInvalidAssemblyName(); - } - } - - // Desktop compat: If we got here, the attribute name is unknown to us. Ignore it. - token = GetNextToken(); - } - - return new AssemblyNameParts(name, version, cultureName, flags, pkt); - } - - private Version ParseVersion(string attributeValue) - { - ReadOnlySpan attributeValueSpan = attributeValue; - Span parts = stackalloc Range[5]; - parts = parts.Slice(0, attributeValueSpan.Split(parts, '.')); - if (parts.Length is < 2 or > 4) - { - ThrowInvalidAssemblyName(); - } - - Span versionNumbers = stackalloc ushort[4]; - for (int i = 0; i < versionNumbers.Length; i++) - { - if ((uint)i >= (uint)parts.Length) - { - versionNumbers[i] = ushort.MaxValue; - break; - } - - if (!ushort.TryParse(attributeValueSpan[parts[i]], NumberStyles.None, NumberFormatInfo.InvariantInfo, out versionNumbers[i])) - { - ThrowInvalidAssemblyName(); - } - } - - if (versionNumbers[0] == ushort.MaxValue || - versionNumbers[1] == ushort.MaxValue) - { - ThrowInvalidAssemblyName(); - } - - return - versionNumbers[2] == ushort.MaxValue ? new Version(versionNumbers[0], versionNumbers[1]) : - versionNumbers[3] == ushort.MaxValue ? new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2]) : - new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2], versionNumbers[3]); - } - - private static string ParseCulture(string attributeValue) - { - if (attributeValue.Equals("Neutral", StringComparison.OrdinalIgnoreCase)) - { - return ""; - } - - return attributeValue; - } - - private byte[] ParsePKT(string attributeValue, bool isToken) - { - if (attributeValue.Equals("null", StringComparison.OrdinalIgnoreCase) || attributeValue == string.Empty) - return Array.Empty(); - - if (isToken && attributeValue.Length != 8 * 2) - ThrowInvalidAssemblyName(); - - byte[] pkt = new byte[attributeValue.Length / 2]; - int srcIndex = 0; - for (int i = 0; i < pkt.Length; i++) - { - char hi = attributeValue[srcIndex++]; - char lo = attributeValue[srcIndex++]; - pkt[i] = (byte)((ParseHexNybble(hi) << 4) | ParseHexNybble(lo)); - } - return pkt; - } - - private ProcessorArchitecture ParseProcessorArchitecture(string attributeValue) - { - if (attributeValue.Equals("msil", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.MSIL; - if (attributeValue.Equals("x86", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.X86; - if (attributeValue.Equals("ia64", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.IA64; - if (attributeValue.Equals("amd64", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.Amd64; - if (attributeValue.Equals("arm", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.Arm; - ThrowInvalidAssemblyName(); - return default; // unreachable - } - - private byte ParseHexNybble(char c) - { - int value = HexConverter.FromChar(c); - if (value == 0xFF) - { - ThrowInvalidAssemblyName(); - } - return (byte)value; - } - - // - // Return the next token in assembly name. If you expect the result to be Token.String, - // use GetNext(out String) instead. - // - private Token GetNextToken() - { - return GetNextToken(out _); - } - - private static bool IsWhiteSpace(char ch) - { - switch (ch) - { - case '\n': - case '\r': - case ' ': - case '\t': - return true; - default: - return false; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private char GetNextChar() - { - char ch; - if (_index < _input.Length) - { - ch = _input[_index++]; - if (ch == '\0') - { - ThrowInvalidAssemblyName(); - } - } - else - { - ch = '\0'; - } - - return ch; - } - - // - // Return the next token in assembly name. If the result is Token.String, - // sets "tokenString" to the tokenized string. - // - private Token GetNextToken(out string tokenString) - { - tokenString = string.Empty; - char c; - - while (true) - { - c = GetNextChar(); - switch (c) - { - case ',': - return Token.Comma; - case '=': - return Token.Equals; - case '\0': - return Token.End; - } - - if (!IsWhiteSpace(c)) - { - break; - } - } - - ValueStringBuilder sb = new ValueStringBuilder(stackalloc char[64]); - - char quoteChar = '\0'; - if (c == '\'' || c == '\"') - { - quoteChar = c; - c = GetNextChar(); - } - - for (; ; ) - { - if (c == 0) - { - if (quoteChar != 0) - { - // EOS and unclosed quotes is an error - ThrowInvalidAssemblyName(); - } - // Reached end of input and therefore of string - break; - } - - if (quoteChar != 0 && c == quoteChar) - break; // Terminate: Found closing quote of quoted string. - - if (quoteChar == 0 && (c == ',' || c == '=')) - { - _index--; - break; // Terminate: Found start of a new ',' or '=' token. - } - - if (quoteChar == 0 && (c == '\'' || c == '\"')) - ThrowInvalidAssemblyName(); - - if (c == '\\') - { - c = GetNextChar(); - - switch (c) - { - case '\\': - case ',': - case '=': - case '\'': - case '"': - sb.Append(c); - break; - case 't': - sb.Append('\t'); - break; - case 'r': - sb.Append('\r'); - break; - case 'n': - sb.Append('\n'); - break; - default: - ThrowInvalidAssemblyName(); - break; //unreachable - } - } - else - { - sb.Append(c); - } - - c = GetNextChar(); - } - - - if (quoteChar == 0) - { - while (sb.Length > 0 && IsWhiteSpace(sb[sb.Length - 1])) - sb.Length--; - } - - tokenString = sb.ToString(); - return Token.String; - } - - [DoesNotReturn] - private void ThrowInvalidAssemblyName() - => throw new FileLoadException(SR.InvalidAssemblyName, _input.ToString()); - } -} diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs index b56f69381450..826fda1e2c5a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs @@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; +using System.Diagnostics.SymbolStore; namespace System.Reflection.Emit { @@ -200,6 +201,66 @@ public virtual LocalBuilder DeclareLocal(Type localType) [CLSCompliant(false)] public void Emit(OpCode opcode, sbyte arg) => Emit(opcode, (byte)arg); + /// + /// Marks a sequence point in the Microsoft intermediate language (MSIL) stream. + /// + /// The document for which the sequence point is being defined. + /// The line where the sequence point begins. + /// The column in the line where the sequence point begins. + /// The line where the sequence point ends. + /// The column in the line where the sequence point ends. + /// is . + /// is not valid. + /// + /// is not within range [0, 0x20000000) or + /// is not within range [0, 0x20000000) or lower than or + /// is not within range [0, 0x10000) or + /// is not within range [0, 0x10000) or + /// equal to and it is not hidden sequence point and lower than or equal to . + /// + /// Emitting debug info is not supported." + public void MarkSequencePoint(ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn) + { + ArgumentNullException.ThrowIfNull(document); + + if (startLine < 0 || startLine >= 0x20000000) + { + throw new ArgumentOutOfRangeException(nameof(startLine)); + } + + if (endLine < 0 || endLine >= 0x20000000 || startLine > endLine) + { + throw new ArgumentOutOfRangeException(nameof(endLine)); + } + + if (startColumn < 0 || startColumn >= 0x10000) + { + throw new ArgumentOutOfRangeException(nameof(startColumn)); + } + + if (endColumn < 0 || endColumn >= 0x10000 || + (startLine == endLine && startLine != 0xfeefee && startColumn >= endColumn)) + { + throw new ArgumentOutOfRangeException(nameof(endColumn)); + } + + MarkSequencePointCore(document, startLine, startColumn, endLine, endColumn); + } + + /// + /// When overridden in a derived class, marks a sequence point in the Microsoft intermediate language (MSIL) stream. + /// + /// The document for which the sequence point is being defined. + /// The line where the sequence point begins. + /// The column in the line where the sequence point begins. + /// The line where the sequence point ends. + /// The column in the line where the sequence point ends. + /// is not valid. + /// Emitting debug info is not supported." + /// The parameters validated in the caller: . + protected virtual void MarkSequencePointCore(ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn) => + throw new NotSupportedException(SR.NotSupported_EmitDebugInfo); + #endregion #endregion diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/LocalBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/LocalBuilder.cs index 7c38c287bf22..e5e86ab883f6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/LocalBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/LocalBuilder.cs @@ -12,5 +12,27 @@ public abstract class LocalBuilder : LocalVariableInfo /// This constructor is invoked by derived classes. /// protected LocalBuilder() { } + + /// + /// Sets the name of this local variable. + /// + /// The name of the local variable + /// The is null. + /// The containing type has been created with CreateType() or + /// containing type doesn't support symbol writing." + public void SetLocalSymInfo(string name) + { + ArgumentNullException.ThrowIfNull(name); + + SetLocalSymInfoCore(name); + } + + /// + /// When overridden in a derived class, sets the name of this local variable. + /// + /// The name of the local variable. + /// Emitting debug info is not supported." + /// The containing type has been created with CreateType()." + protected virtual void SetLocalSymInfoCore(string name) => throw new NotSupportedException(SR.NotSupported_EmitDebugInfo); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs index 21f68439ee39..f97935b24d7b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs @@ -1,7 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.ComponentModel; using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.SymbolStore; using System.Runtime.InteropServices; namespace System.Reflection.Emit @@ -24,6 +26,45 @@ public EnumBuilder DefineEnum(string name, TypeAttributes visibility, Type under return DefineEnumCore(name, visibility, underlyingType); } + /// + /// Defines a document for source. + /// + /// The URL for the document. + /// The GUID that identifies the document language. This can be Empty + /// The GUID that identifies the document language vendor. This is not used. + /// The GUID that identifies the document language vendor. This is not used. + /// The defined document. + /// is . + /// This method is called on a dynamic module that is not a persisted module. + [EditorBrowsable(EditorBrowsableState.Never)] + public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType) => + DefineDocument(url, language); + + /// + /// Defines a document for source. + /// + /// The URL for the document. + /// The GUID that identifies the document language. This is optional + /// The defined document. + /// is . + /// This method is called on a dynamic module that is not a persisted module. + public ISymbolDocumentWriter DefineDocument(string url, Guid language = default) + { + ArgumentException.ThrowIfNullOrEmpty(url); + + return DefineDocumentCore(url, language); + } + + /// + /// When override in a derived class, defines a document for source. + /// + /// The URL for the document. + /// The GUID that identifies the document language. This is optional + /// The defined document. + /// This method is called on a dynamic module that is not a debug module. + protected virtual ISymbolDocumentWriter DefineDocumentCore(string url, Guid language = default) => + throw new InvalidOperationException(SR.InvalidOperation_NotADebugModule); + protected abstract EnumBuilder DefineEnumCore(string name, TypeAttributes visibility, Type underlyingType); public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, Type? returnType, Type[]? parameterTypes) diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs index 531a8ed9f816..6a1b94d50859 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs @@ -402,6 +402,7 @@ private static bool TryByRefFastPath(RuntimeType type, ref object arg) { if (sigElementType.IsValueType) { + Debug.Assert(!sigElementType.IsNullableOfT, "A true boxed Nullable should never be here."); // Make a copy to prevent the boxed instance from being directly modified by the method. arg = RuntimeType.AllocateValueType(sigElementType, arg); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.cs new file mode 100644 index 000000000000..9e36505b390e --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.cs @@ -0,0 +1,122 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Reflection.Metadata; +using System.Text; + +namespace System.Reflection.Metadata +{ + internal struct TypeNameParseOptions + { + public TypeNameParseOptions() { } +#pragma warning disable CA1822 // Mark members as static + // CoreLib does not enforce any limits + public bool IsMaxDepthExceeded(int _) => false; + public int MaxNodes + { + get + { + Debug.Fail("Expected to be unreachable"); + return 0; + } + } +#pragma warning restore CA1822 + } +} + +namespace System.Reflection +{ + internal partial struct TypeNameResolver + { + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:RequiresDynamicCode", + Justification = "Used to implement resolving types from strings.")] + private Type? Resolve(TypeName typeName) + { + if (typeName.IsSimple) + { + return GetSimpleType(typeName); + } + else if (typeName.IsConstructedGenericType) + { + return GetGenericType(typeName); + } + else if (typeName.IsArray || typeName.IsPointer || typeName.IsByRef) + { + Type? type = Resolve(typeName.GetElementType()); + if (type is null) + return null; + + if (typeName.IsArray) + { + return typeName.IsSZArray ? type.MakeArrayType() : type.MakeArrayType(rank: typeName.GetArrayRank()); + } + if (typeName.IsByRef) + { + return type.MakeByRefType(); + } + else if (typeName.IsPointer) + { + return type.MakePointerType(); + } + } + + Debug.Fail("Expected to be unreachable"); + return null; + } + + private Type? GetSimpleType(TypeName typeName) + { + if (typeName.IsNested) + { + TypeName current = typeName; + int nestingDepth = 0; + do + { + nestingDepth++; + current = current.DeclaringType!; + } + while (current.IsNested); + + string[] nestedTypeNames = new string[nestingDepth]; + current = typeName; + while (current.IsNested) + { + nestedTypeNames[--nestingDepth] = TypeNameHelpers.Unescape(current.Name); + current = current.DeclaringType!; + } + + return GetType(current.FullName, nestedTypeNames, typeName); + } + else + { + return GetType(typeName.FullName, default, typeName); + } + + } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern", + Justification = "Used to implement resolving types from strings.")] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:RequiresDynamicCode", + Justification = "Used to implement resolving types from strings.")] + private Type? GetGenericType(TypeName typeName) + { + Type? type = Resolve(typeName.GetGenericTypeDefinition()); + if (type is null) + return null; + + ReadOnlySpan genericArgs = typeName.GetGenericArguments(); + Type[] genericTypes = new Type[genericArgs.Length]; + for (int i = 0; i < genericArgs.Length; i++) + { + Type? genericArg = Resolve(genericArgs[i]); + if (genericArg is null) + return null; + genericTypes[i] = genericArg; + } + + return type.MakeGenericType(genericTypes); + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs index 459fd26e6abb..7cb85c290c75 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs @@ -102,6 +102,12 @@ internal static string GetAsyncStateMachineDescription(IAsyncStateMachine stateM return sb.ToString(); } + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void LogTraceOperationBegin(Task t, Type stateMachineType) + { + TplEventSource.Log.TraceOperationBegin(t.Id, "Async: " + stateMachineType.Name, 0); + } + internal static Action CreateContinuationWrapper(Action continuation, Action invokeAction, Task innerTask) => new ContinuationWrapper(continuation, invokeAction, innerTask).Invoke; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilderT.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilderT.cs index c3064ad22114..5a2ccb1d6354 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilderT.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilderT.cs @@ -157,6 +157,8 @@ private static IAsyncStateMachineBox GetStateMachineBox( { ExecutionContext? currentContext = ExecutionContext.Capture(); + IAsyncStateMachineBox result; + // Check first for the most common case: not the first yield in an async method. // In this case, the first yield will have already "boxed" the state machine in // a strongly-typed manner into an AsyncStateMachineBox. It will already contain @@ -168,9 +170,8 @@ private static IAsyncStateMachineBox GetStateMachineBox( { stronglyTypedBox.Context = currentContext; } - return stronglyTypedBox; + result = stronglyTypedBox; } - // The least common case: we have a weakly-typed boxed. This results if the debugger // or some other use of reflection accesses a property like ObjectIdForDebugger or a // method like SetNotificationForWaitCompletion prior to the first await happening. In @@ -180,7 +181,7 @@ private static IAsyncStateMachineBox GetStateMachineBox( // result in a boxing allocation when storing the TStateMachine if it's a struct, but // this only happens in active debugging scenarios where such performance impact doesn't // matter. - if (taskField is AsyncStateMachineBox weaklyTypedBox) + else if (taskField is AsyncStateMachineBox weaklyTypedBox) { // If this is the first await, we won't yet have a state machine, so store it. if (weaklyTypedBox.StateMachine == null) @@ -192,52 +193,55 @@ private static IAsyncStateMachineBox GetStateMachineBox( // Update the context. This only happens with a debugger, so no need to spend // extra IL checking for equality before doing the assignment. weaklyTypedBox.Context = currentContext; - return weaklyTypedBox; + result = weaklyTypedBox; } - - // Alert a listening debugger that we can't make forward progress unless it slips threads. - // If we don't do this, and a method that uses "await foo;" is invoked through funceval, - // we could end up hooking up a callback to push forward the async method's state machine, - // the debugger would then abort the funceval after it takes too long, and then continuing - // execution could result in another callback being hooked up. At that point we have - // multiple callbacks registered to push the state machine, which could result in bad behavior. - Debugger.NotifyOfCrossThreadDependency(); - - // At this point, taskField should really be null, in which case we want to create the box. - // However, in a variety of debugger-related (erroneous) situations, it might be non-null, - // e.g. if the Task property is examined in a Watch window, forcing it to be lazily-initialized - // as a Task rather than as an AsyncStateMachineBox. The worst that happens in such - // cases is we lose the ability to properly step in the debugger, as the debugger uses that - // object's identity to track this specific builder/state machine. As such, we proceed to - // overwrite whatever's there anyway, even if it's non-null. + else + { + // Alert a listening debugger that we can't make forward progress unless it slips threads. + // If we don't do this, and a method that uses "await foo;" is invoked through funceval, + // we could end up hooking up a callback to push forward the async method's state machine, + // the debugger would then abort the funceval after it takes too long, and then continuing + // execution could result in another callback being hooked up. At that point we have + // multiple callbacks registered to push the state machine, which could result in bad behavior. + Debugger.NotifyOfCrossThreadDependency(); + + // At this point, taskField should really be null, in which case we want to create the box. + // However, in a variety of debugger-related (erroneous) situations, it might be non-null, + // e.g. if the Task property is examined in a Watch window, forcing it to be lazily-initialized + // as a Task rather than as an AsyncStateMachineBox. The worst that happens in such + // cases is we lose the ability to properly step in the debugger, as the debugger uses that + // object's identity to track this specific builder/state machine. As such, we proceed to + // overwrite whatever's there anyway, even if it's non-null. #if NATIVEAOT - // DebugFinalizableAsyncStateMachineBox looks like a small type, but it actually is not because - // it will have a copy of all the slots from its parent. It will add another hundred(s) bytes - // per each async method in NativeAOT binaries without adding much value. Avoid - // generating this extra code until a better solution is implemented. - var box = new AsyncStateMachineBox(); + // DebugFinalizableAsyncStateMachineBox looks like a small type, but it actually is not because + // it will have a copy of all the slots from its parent. It will add another hundred(s) bytes + // per each async method in NativeAOT binaries without adding much value. Avoid + // generating this extra code until a better solution is implemented. + var box = new AsyncStateMachineBox(); #else - AsyncStateMachineBox box = AsyncMethodBuilderCore.TrackAsyncMethodCompletion ? - CreateDebugFinalizableAsyncStateMachineBox() : - new AsyncStateMachineBox(); + AsyncStateMachineBox box = AsyncMethodBuilderCore.TrackAsyncMethodCompletion ? + CreateDebugFinalizableAsyncStateMachineBox() : + new AsyncStateMachineBox(); #endif - taskField = box; // important: this must be done before storing stateMachine into box.StateMachine! - box.StateMachine = stateMachine; - box.Context = currentContext; + taskField = box; // important: this must be done before storing stateMachine into box.StateMachine! + box.StateMachine = stateMachine; + box.Context = currentContext; - // Log the creation of the state machine box object / task for this async method. - if (TplEventSource.Log.IsEnabled()) - { - TplEventSource.Log.TraceOperationBegin(box.Id, "Async: " + stateMachine.GetType().Name, 0); - } + // Log the creation of the state machine box object / task for this async method. + if (TplEventSource.Log.IsEnabled()) + { + AsyncMethodBuilderCore.LogTraceOperationBegin(box, stateMachine.GetType()); + } - // And if async debugging is enabled, track the task. - if (Threading.Tasks.Task.s_asyncDebuggingEnabled) - { - Threading.Tasks.Task.AddToActiveTasks(box); + // And if async debugging is enabled, track the task. + if (Threading.Tasks.Task.s_asyncDebuggingEnabled) + { + Threading.Tasks.Task.AddToActiveTasks(box); + } + result = box; } - return box; + return result; } #if !NATIVEAOT diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/OverloadResolutionPriorityAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/OverloadResolutionPriorityAttribute.cs new file mode 100644 index 000000000000..f38d3195815b --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/OverloadResolutionPriorityAttribute.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Runtime.CompilerServices +{ + /// + /// Specifies the priority of a member in overload resolution. When unspecified, the default priority is 0. + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + public sealed class OverloadResolutionPriorityAttribute : Attribute + { + /// + /// Initializes a new instance of the class. + /// + /// The priority of the attributed member. Higher numbers are prioritized, lower numbers are deprioritized. 0 is the default if no attribute is present. + public OverloadResolutionPriorityAttribute(int priority) + { + Priority = priority; + } + + /// + /// The priority of the member. + /// + public int Priority { get; } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs index d33471813491..63471d9f9196 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -129,6 +129,9 @@ internal static bool IsPrimitiveType(this CorElementType et) [Intrinsic] internal static bool IsKnownConstant(char t) => false; + + [Intrinsic] + internal static bool IsKnownConstant(T t) where T : struct => false; #pragma warning restore IDE0060 } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs index 901d354cfc7c..e59b30fd7633 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs @@ -242,15 +242,14 @@ public static bool AreSame([AllowNull] ref readonly T left, [AllowNull] ref r /// /// Reinterprets the given value of type as a value of type . /// - /// The size of and are not the same. + /// The sizes of and are not the same + /// or the type parameters are not s. [Intrinsic] [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TTo BitCast(TFrom source) - where TFrom : struct - where TTo : struct { - if (sizeof(TFrom) != sizeof(TTo)) + if (sizeof(TFrom) != sizeof(TTo) || default(TFrom) is null || default(TTo) is null) { ThrowHelper.ThrowNotSupportedException(); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs index 74ef8257749a..25bc1f195fa4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs @@ -818,7 +818,6 @@ public static IntPtr GetHINSTANCE(Module m) }; } case HResults.FUSION_E_INVALID_NAME: - case HResults.FUSION_E_PRIVATE_ASM_DISALLOWED: case HResults.FUSION_E_REF_DEF_MISMATCH: case HResults.ERROR_TOO_MANY_OPEN_FILES: case HResults.ERROR_SHARING_VIOLATION: diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs index 37c39bbc029a..344f528a45c5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs @@ -992,6 +992,14 @@ static NFloat IBinaryNumber.AllBitsSet /// public static NFloat Ceiling(NFloat x) => new NFloat(NativeType.Ceiling(x._value)); + /// + public static TInteger ConvertToInteger(NFloat value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + public static TInteger ConvertToIntegerNative(NFloat value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + /// public static NFloat Floor(NFloat x) => new NFloat(NativeType.Floor(x._value)); @@ -1381,6 +1389,9 @@ public static NFloat CreateTruncating(TOther value) /// public static NFloat MinMagnitudeNumber(NFloat x, NFloat y) => new NFloat(NativeType.MinMagnitudeNumber(x._value, y._value)); + /// + public static NFloat MultiplyAddEstimate(NFloat left, NFloat right, NFloat addend) => new NFloat(NativeType.MultiplyAddEstimate(left._value, right._value, addend._value)); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out NFloat result) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs index 1bb3db3da194..e750d1011584 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs @@ -1,38 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Reflection; - namespace System.Runtime.InteropServices { public static partial class RuntimeInformation { - private const string FrameworkName = ".NET"; - private static string? s_frameworkDescription; private static string? s_runtimeIdentifier; - public static string FrameworkDescription - { - get - { - if (s_frameworkDescription == null) - { - ReadOnlySpan versionString = typeof(object).Assembly.GetCustomAttribute()?.InformationalVersion; - - // Strip the git hash if there is one - int plusIndex = versionString.IndexOf('+'); - if (plusIndex >= 0) - { - versionString = versionString.Slice(0, plusIndex); - } - - s_frameworkDescription = !versionString.Trim().IsEmpty ? $"{FrameworkName} {versionString}" : FrameworkName; - } - - return s_frameworkDescription; - } - } - /// /// Returns an opaque string that identifies the platform on which an app is running. /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs index 3202d6dc94a6..e358c5663db2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.PlatformNotSupported.cs @@ -3502,18 +3502,21 @@ internal Arm64() { } /// uint16_t vqrshrns_n_u32 (uint32_t a, const int n) /// A64: UQRSHRN Hd, Sn, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, [ConstantExpected(Min = 1, Max = (byte)(16))] byte count) { throw new PlatformNotSupportedException(); } /// /// uint32_t vqrshrnd_n_u64 (uint64_t a, const int n) /// A64: UQRSHRN Sd, Dn, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, [ConstantExpected(Min = 1, Max = (byte)(8))] byte count) { throw new PlatformNotSupportedException(); } /// /// uint8_t vqrshrnh_n_u16 (uint16_t a, const int n) /// A64: UQRSHRN Bd, Hn, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, [ConstantExpected(Min = 1, Max = (byte)(32))] byte count) { throw new PlatformNotSupportedException(); } /// @@ -15470,6 +15473,7 @@ internal Arm64() { } /// A32: VQRSHRN.U32 Dd, Qm, #n /// A64: UQRSHRN Vd.4H, Vn.4S, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, [ConstantExpected(Min = 1, Max = (byte)(32))] byte count) { throw new PlatformNotSupportedException(); } /// @@ -15477,6 +15481,7 @@ internal Arm64() { } /// A32: VQRSHRN.U64 Dd, Qm, #n /// A64: UQRSHRN Vd.2S, Vn.2D, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, [ConstantExpected(Min = 1, Max = (byte)(16))] byte count) { throw new PlatformNotSupportedException(); } /// @@ -15484,6 +15489,7 @@ internal Arm64() { } /// A32: VQRSHRN.U16 Dd, Qm, #n /// A64: UQRSHRN Vd.8B, Vn.8H, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, [ConstantExpected(Min = 1, Max = (byte)(64))] byte count) { throw new PlatformNotSupportedException(); } /// @@ -15512,6 +15518,7 @@ internal Arm64() { } /// A32: VQRSHRN.U32 Dd+1, Dn, #n /// A64: UQRSHRN2 Vd.8H, Vn.4S, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, [ConstantExpected(Min = 1, Max = (byte)(32))] byte count) { throw new PlatformNotSupportedException(); } /// @@ -15519,6 +15526,7 @@ internal Arm64() { } /// A32: VQRSHRN.U64 Dd+1, Dn, #n /// A64: UQRSHRN2 Vd.4S, Vn.2D, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, [ConstantExpected(Min = 1, Max = (byte)(16))] byte count) { throw new PlatformNotSupportedException(); } /// @@ -15526,6 +15534,7 @@ internal Arm64() { } /// A32: VQRSHRN.U16 Dd+1, Dn, #n /// A64: UQRSHRN2 Vd.16B, Vn.8H, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, [ConstantExpected(Min = 1, Max = (byte)(64))] byte count) { throw new PlatformNotSupportedException(); } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.cs index d343750838cd..d4354ca639a4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/AdvSimd.cs @@ -3500,18 +3500,21 @@ internal Arm64() { } /// uint16_t vqrshrns_n_u32 (uint32_t a, const int n) /// A64: UQRSHRN Hd, Sn, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, [ConstantExpected(Min = 1, Max = (byte)(16))] byte count) => ShiftRightLogicalRoundedNarrowingSaturateScalar(value, count); /// /// uint32_t vqrshrnd_n_u64 (uint64_t a, const int n) /// A64: UQRSHRN Sd, Dn, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, [ConstantExpected(Min = 1, Max = (byte)(8))] byte count) => ShiftRightLogicalRoundedNarrowingSaturateScalar(value, count); /// /// uint8_t vqrshrnh_n_u16 (uint16_t a, const int n) /// A64: UQRSHRN Bd, Hn, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(Vector64 value, [ConstantExpected(Min = 1, Max = (byte)(32))] byte count) => ShiftRightLogicalRoundedNarrowingSaturateScalar(value, count); /// @@ -15467,6 +15470,7 @@ internal Arm64() { } /// A32: VQRSHRN.U32 Dd, Qm, #n /// A64: UQRSHRN Vd.4H, Vn.4S, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, [ConstantExpected(Min = 1, Max = (byte)(32))] byte count) => ShiftRightLogicalRoundedNarrowingSaturateLower(value, count); /// @@ -15474,6 +15478,7 @@ internal Arm64() { } /// A32: VQRSHRN.U64 Dd, Qm, #n /// A64: UQRSHRN Vd.2S, Vn.2D, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, [ConstantExpected(Min = 1, Max = (byte)(16))] byte count) => ShiftRightLogicalRoundedNarrowingSaturateLower(value, count); /// @@ -15481,6 +15486,7 @@ internal Arm64() { } /// A32: VQRSHRN.U16 Dd, Qm, #n /// A64: UQRSHRN Vd.8B, Vn.8H, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(Vector128 value, [ConstantExpected(Min = 1, Max = (byte)(64))] byte count) => ShiftRightLogicalRoundedNarrowingSaturateLower(value, count); /// @@ -15509,6 +15515,7 @@ internal Arm64() { } /// A32: VQRSHRN.U32 Dd+1, Dn, #n /// A64: UQRSHRN2 Vd.8H, Vn.4S, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, [ConstantExpected(Min = 1, Max = (byte)(32))] byte count) => ShiftRightLogicalRoundedNarrowingSaturateUpper(lower, value, count); /// @@ -15516,6 +15523,7 @@ internal Arm64() { } /// A32: VQRSHRN.U64 Dd+1, Dn, #n /// A64: UQRSHRN2 Vd.4S, Vn.2D, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, [ConstantExpected(Min = 1, Max = (byte)(16))] byte count) => ShiftRightLogicalRoundedNarrowingSaturateUpper(lower, value, count); /// @@ -15523,6 +15531,7 @@ internal Arm64() { } /// A32: VQRSHRN.U16 Dd+1, Dn, #n /// A64: UQRSHRN2 Vd.16B, Vn.8H, #n /// + [Obsolete(Obsoletions.ArmIntrinsicPerformsUnsignedOperationMessage, DiagnosticId = Obsoletions.ArmIntrinsicPerformsUnsignedOperationDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(Vector64 lower, Vector128 value, [ConstantExpected(Min = 1, Max = (byte)(64))] byte count) => ShiftRightLogicalRoundedNarrowingSaturateUpper(lower, value, count); /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs index fbd5ee65ca74..346b2c1de1f0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs @@ -31,169 +31,3276 @@ internal Arm64() { } public static new bool IsSupported { [Intrinsic] get { return false; } } } + /// Abs : Absolute value + + /// + /// svint8_t svabs[_s8]_m(svint8_t inactive, svbool_t pg, svint8_t op) + /// svint8_t svabs[_s8]_x(svbool_t pg, svint8_t op) + /// svint8_t svabs[_s8]_z(svbool_t pg, svint8_t op) + /// + public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svabs[_s16]_m(svint16_t inactive, svbool_t pg, svint16_t op) + /// svint16_t svabs[_s16]_x(svbool_t pg, svint16_t op) + /// svint16_t svabs[_s16]_z(svbool_t pg, svint16_t op) + /// + public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svabs[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// svint32_t svabs[_s32]_x(svbool_t pg, svint32_t op) + /// svint32_t svabs[_s32]_z(svbool_t pg, svint32_t op) + /// + public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svabs[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// svint64_t svabs[_s64]_x(svbool_t pg, svint64_t op) + /// svint64_t svabs[_s64]_z(svbool_t pg, svint64_t op) + /// + public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svabs[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op) + /// svfloat32_t svabs[_f32]_x(svbool_t pg, svfloat32_t op) + /// svfloat32_t svabs[_f32]_z(svbool_t pg, svfloat32_t op) + /// + public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svabs[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op) + /// svfloat64_t svabs[_f64]_x(svbool_t pg, svfloat64_t op) + /// svfloat64_t svabs[_f64]_z(svbool_t pg, svfloat64_t op) + /// + public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); } + + /// AbsoluteDifference : Absolute difference + + /// + /// svuint8_t svabd[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svabd[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; UABD Zresult.B, Pg/M, Zresult.B, Zop2.B + /// UABD Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svabd[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svabd[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svabd[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FABD Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svabd[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svabd[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svabd[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// SABD Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svabd[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svabd[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svabd[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// SABD Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svabd[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svabd[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svabd[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// SABD Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svabd[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svabd[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svabd[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// SABD Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svabd[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svabd[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svabd[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FABD Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svabd[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svabd[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svabd[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// UABD Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svabd[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svabd[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svabd[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// UABD Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svabd[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svabd[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svabd[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// UABD Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// Add : Add + + /// + /// svint8_t svadd[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svadd[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svadd[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svadd[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svadd[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svadd[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svadd[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svadd[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svadd[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svadd[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svadd[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svadd[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint8_t svadd[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svadd[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svadd[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svadd[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svadd[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svadd[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svadd[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svadd[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svadd[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svadd[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svadd[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svadd[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svadd[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svadd[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svadd[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svadd[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svadd[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svadd[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// AddAcross : Add reduction + + /// + /// float64_t svaddv[_f64](svbool_t pg, svfloat64_t op) + /// FADDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svaddv[_s16](svbool_t pg, svint16_t op) + /// SADDV Dresult, Pg, Zop.H + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svaddv[_s32](svbool_t pg, svint32_t op) + /// SADDV Dresult, Pg, Zop.S + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svaddv[_s8](svbool_t pg, svint8_t op) + /// SADDV Dresult, Pg, Zop.B + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svaddv[_s64](svbool_t pg, svint64_t op) + /// UADDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// float32_t svaddv[_f32](svbool_t pg, svfloat32_t op) + /// FADDV Sresult, Pg, Zop.S + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svaddv[_u8](svbool_t pg, svuint8_t op) + /// UADDV Dresult, Pg, Zop.B + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svaddv[_u16](svbool_t pg, svuint16_t op) + /// UADDV Dresult, Pg, Zop.H + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svaddv[_u32](svbool_t pg, svuint32_t op) + /// UADDV Dresult, Pg, Zop.S + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svaddv[_u64](svbool_t pg, svuint64_t op) + /// UADDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AddAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// AddSaturate : Saturating add + + /// + /// svuint8_t svqadd[_u8](svuint8_t op1, svuint8_t op2) + /// UQADD Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svqadd[_s16](svint16_t op1, svint16_t op2) + /// SQADD Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svqadd[_s32](svint32_t op1, svint32_t op2) + /// SQADD Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svqadd[_s64](svint64_t op1, svint64_t op2) + /// SQADD Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svqadd[_s8](svint8_t op1, svint8_t op2) + /// SQADD Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svqadd[_u16](svuint16_t op1, svuint16_t op2) + /// UQADD Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svqadd[_u32](svuint32_t op1, svuint32_t op2) + /// UQADD Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svqadd[_u64](svuint64_t op1, svuint64_t op2) + /// UQADD Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// And : Bitwise AND + + /// + /// svuint8_t svand[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svand[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svand[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// AND Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svand[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svand[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svand[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// AND Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svand[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svand[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svand[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// AND Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svand[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svand[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svand[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// AND Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svand[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svand[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svand[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// AND Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svand[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svand[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svand[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// AND Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svand[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svand[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svand[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// AND Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svand[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svand[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svand[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// AND Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// AndAcross : Bitwise AND reduction to scalar + + /// + /// uint8_t svandv[_u8](svbool_t pg, svuint8_t op) + /// ANDV Bresult, Pg, Zop.B + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int16_t svandv[_s16](svbool_t pg, svint16_t op) + /// ANDV Hresult, Pg, Zop.H + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t svandv[_s32](svbool_t pg, svint32_t op) + /// ANDV Sresult, Pg, Zop.S + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svandv[_s64](svbool_t pg, svint64_t op) + /// ANDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t svandv[_s8](svbool_t pg, svint8_t op) + /// ANDV Bresult, Pg, Zop.B + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t svandv[_u16](svbool_t pg, svuint16_t op) + /// ANDV Hresult, Pg, Zop.H + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t svandv[_u32](svbool_t pg, svuint32_t op) + /// ANDV Sresult, Pg, Zop.S + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svandv[_u64](svbool_t pg, svuint64_t op) + /// ANDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AndAcross(Vector value) { throw new PlatformNotSupportedException(); } + + + /// BitwiseClear : Bitwise clear + + /// + /// svuint8_t svbic[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svbic[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svbic[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// BIC Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svbic[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svbic[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svbic[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// BIC Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svbic[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svbic[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svbic[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// BIC Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svbic[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svbic[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svbic[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// BIC Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svbic[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svbic[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svbic[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// BIC Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svbic[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svbic[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svbic[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// BIC Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svbic[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svbic[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svbic[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// BIC Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svbic[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svbic[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svbic[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// BIC Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// BooleanNot : Logically invert boolean condition + + /// + /// svuint8_t svcnot[_u8]_m(svuint8_t inactive, svbool_t pg, svuint8_t op) + /// svuint8_t svcnot[_u8]_x(svbool_t pg, svuint8_t op) + /// svuint8_t svcnot[_u8]_z(svbool_t pg, svuint8_t op) + /// CNOT Ztied.B, Pg/M, Zop.B + /// + public static unsafe Vector BooleanNot(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svcnot[_s16]_m(svint16_t inactive, svbool_t pg, svint16_t op) + /// svint16_t svcnot[_s16]_x(svbool_t pg, svint16_t op) + /// svint16_t svcnot[_s16]_z(svbool_t pg, svint16_t op) + /// CNOT Ztied.H, Pg/M, Zop.H + /// + public static unsafe Vector BooleanNot(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svcnot[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// svint32_t svcnot[_s32]_x(svbool_t pg, svint32_t op) + /// svint32_t svcnot[_s32]_z(svbool_t pg, svint32_t op) + /// CNOT Ztied.S, Pg/M, Zop.S + /// + public static unsafe Vector BooleanNot(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svcnot[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// svint64_t svcnot[_s64]_x(svbool_t pg, svint64_t op) + /// svint64_t svcnot[_s64]_z(svbool_t pg, svint64_t op) + /// CNOT Ztied.D, Pg/M, Zop.D + /// + public static unsafe Vector BooleanNot(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svcnot[_s8]_m(svint8_t inactive, svbool_t pg, svint8_t op) + /// svint8_t svcnot[_s8]_x(svbool_t pg, svint8_t op) + /// svint8_t svcnot[_s8]_z(svbool_t pg, svint8_t op) + /// CNOT Ztied.B, Pg/M, Zop.B + /// + public static unsafe Vector BooleanNot(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svcnot[_u16]_m(svuint16_t inactive, svbool_t pg, svuint16_t op) + /// svuint16_t svcnot[_u16]_x(svbool_t pg, svuint16_t op) + /// svuint16_t svcnot[_u16]_z(svbool_t pg, svuint16_t op) + /// CNOT Ztied.H, Pg/M, Zop.H + /// + public static unsafe Vector BooleanNot(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svcnot[_u32]_m(svuint32_t inactive, svbool_t pg, svuint32_t op) + /// svuint32_t svcnot[_u32]_x(svbool_t pg, svuint32_t op) + /// svuint32_t svcnot[_u32]_z(svbool_t pg, svuint32_t op) + /// CNOT Ztied.S, Pg/M, Zop.S + /// + public static unsafe Vector BooleanNot(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svcnot[_u64]_m(svuint64_t inactive, svbool_t pg, svuint64_t op) + /// svuint64_t svcnot[_u64]_x(svbool_t pg, svuint64_t op) + /// svuint64_t svcnot[_u64]_z(svbool_t pg, svuint64_t op) + /// CNOT Ztied.D, Pg/M, Zop.D + /// + public static unsafe Vector BooleanNot(Vector value) { throw new PlatformNotSupportedException(); } + + + /// ConditionalSelect : Conditionally select elements + + /// + /// svint8_t svsel[_s8](svbool_t pg, svint8_t op1, svint8_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svsel[_s16](svbool_t pg, svint16_t op1, svint16_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svsel[_s32](svbool_t pg, svint32_t op1, svint32_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svsel[_s64](svbool_t pg, svint64_t op1, svint64_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint8_t svsel[_u8](svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svsel[_u16](svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svsel[_u32](svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svsel[_u64](svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svsel[_f32](svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svsel[_f64](svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// Count16BitElements : Count the number of 16-bit elements in a vector + + /// + /// uint64_t svcnth_pat(enum svpattern pattern) + /// CNTH Xresult, pattern + /// + public static unsafe ulong Count16BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// Count32BitElements : Count the number of 32-bit elements in a vector + + /// + /// uint64_t svcntw_pat(enum svpattern pattern) + /// CNTW Xresult, pattern + /// + public static unsafe ulong Count32BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// Count64BitElements : Count the number of 64-bit elements in a vector + + /// + /// uint64_t svcntd_pat(enum svpattern pattern) + /// CNTD Xresult, pattern + /// + public static unsafe ulong Count64BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// Count8BitElements : Count the number of 8-bit elements in a vector + + /// + /// uint64_t svcntb_pat(enum svpattern pattern) + /// CNTB Xresult, pattern + /// + public static unsafe ulong Count8BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskByte() { throw new PlatformNotSupportedException(); } + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskDouble() { throw new PlatformNotSupportedException(); } + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskInt16() { throw new PlatformNotSupportedException(); } + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskInt32() { throw new PlatformNotSupportedException(); } + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskInt64() { throw new PlatformNotSupportedException(); } + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskSByte() { throw new PlatformNotSupportedException(); } + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskSingle() { throw new PlatformNotSupportedException(); } + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskUInt16() { throw new PlatformNotSupportedException(); } + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskUInt32() { throw new PlatformNotSupportedException(); } + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskUInt64() { throw new PlatformNotSupportedException(); } + + /// CreateTrueMaskByte : Set predicate elements to true /// - /// svbool_t svptrue_pat_b8(enum svpattern pattern) - /// PTRUE Presult.B, pattern + /// svbool_t svptrue_pat_b8(enum svpattern pattern) + /// PTRUE Presult.B, pattern + /// + public static unsafe Vector CreateTrueMaskByte([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// CreateTrueMaskDouble : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b8(enum svpattern pattern) + /// PTRUE Presult.B, pattern + /// + public static unsafe Vector CreateTrueMaskDouble([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// CreateTrueMaskInt16 : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b8(enum svpattern pattern) + /// PTRUE Presult.B, pattern + /// + public static unsafe Vector CreateTrueMaskInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// CreateTrueMaskInt32 : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b8(enum svpattern pattern) + /// PTRUE Presult.B, pattern + /// + public static unsafe Vector CreateTrueMaskInt32([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// CreateTrueMaskInt64 : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b8(enum svpattern pattern) + /// PTRUE Presult.B, pattern + /// + public static unsafe Vector CreateTrueMaskInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// CreateTrueMaskSByte : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b8(enum svpattern pattern) + /// PTRUE Presult.B, pattern + /// + public static unsafe Vector CreateTrueMaskSByte([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// CreateTrueMaskSingle : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b8(enum svpattern pattern) + /// PTRUE Presult.B, pattern + /// + public static unsafe Vector CreateTrueMaskSingle([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// CreateTrueMaskUInt16 : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b16(enum svpattern pattern) + /// PTRUE Presult.H, pattern + /// + public static unsafe Vector CreateTrueMaskUInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// CreateTrueMaskUInt32 : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b32(enum svpattern pattern) + /// PTRUE Presult.S, pattern + /// + public static unsafe Vector CreateTrueMaskUInt32([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// CreateTrueMaskUInt64 : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b64(enum svpattern pattern) + /// PTRUE Presult.D, pattern + /// + public static unsafe Vector CreateTrueMaskUInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + + + /// CreateWhileLessThanMask16Bit : While incrementing scalar is less than + + /// + /// svbool_t svwhilelt_b16[_s32](int32_t op1, int32_t op2) + /// WHILELT Presult.H, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask16Bit(int left, int right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilelt_b16[_s64](int64_t op1, int64_t op2) + /// WHILELT Presult.H, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask16Bit(long left, long right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilelt_b16[_u32](uint32_t op1, uint32_t op2) + /// WHILELO Presult.H, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask16Bit(uint left, uint right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilelt_b16[_u64](uint64_t op1, uint64_t op2) + /// WHILELO Presult.H, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask16Bit(ulong left, ulong right) { throw new PlatformNotSupportedException(); } + + + /// CreateWhileLessThanMask32Bit : While incrementing scalar is less than + + /// + /// svbool_t svwhilelt_b32[_s32](int32_t op1, int32_t op2) + /// WHILELT Presult.S, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask32Bit(int left, int right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilelt_b32[_s64](int64_t op1, int64_t op2) + /// WHILELT Presult.S, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask32Bit(long left, long right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilelt_b32[_u32](uint32_t op1, uint32_t op2) + /// WHILELO Presult.S, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask32Bit(uint left, uint right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilelt_b32[_u64](uint64_t op1, uint64_t op2) + /// WHILELO Presult.S, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask32Bit(ulong left, ulong right) { throw new PlatformNotSupportedException(); } + + + /// CreateWhileLessThanMask64Bit : While incrementing scalar is less than + + /// + /// svbool_t svwhilelt_b64[_s32](int32_t op1, int32_t op2) + /// WHILELT Presult.D, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask64Bit(int left, int right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilelt_b64[_s64](int64_t op1, int64_t op2) + /// WHILELT Presult.D, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask64Bit(long left, long right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilelt_b64[_u32](uint32_t op1, uint32_t op2) + /// WHILELO Presult.D, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask64Bit(uint left, uint right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilelt_b64[_u64](uint64_t op1, uint64_t op2) + /// WHILELO Presult.D, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask64Bit(ulong left, ulong right) { throw new PlatformNotSupportedException(); } + + + /// CreateWhileLessThanMask8Bit : While incrementing scalar is less than + + /// + /// svbool_t svwhilelt_b8[_s32](int32_t op1, int32_t op2) + /// WHILELT Presult.B, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask8Bit(int left, int right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilelt_b8[_s64](int64_t op1, int64_t op2) + /// WHILELT Presult.B, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask8Bit(long left, long right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilelt_b8[_u32](uint32_t op1, uint32_t op2) + /// WHILELO Presult.B, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask8Bit(uint left, uint right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilelt_b8[_u64](uint64_t op1, uint64_t op2) + /// WHILELO Presult.B, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask8Bit(ulong left, ulong right) { throw new PlatformNotSupportedException(); } + + + /// CreateWhileLessThanOrEqualMask16Bit : While incrementing scalar is less than or equal to + + /// + /// svbool_t svwhilele_b16[_s32](int32_t op1, int32_t op2) + /// WHILELE Presult.H, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask16Bit(int left, int right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilele_b16[_s64](int64_t op1, int64_t op2) + /// WHILELE Presult.H, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask16Bit(long left, long right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilele_b16[_u32](uint32_t op1, uint32_t op2) + /// WHILELS Presult.H, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask16Bit(uint left, uint right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilele_b16[_u64](uint64_t op1, uint64_t op2) + /// WHILELS Presult.H, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask16Bit(ulong left, ulong right) { throw new PlatformNotSupportedException(); } + + + /// CreateWhileLessThanOrEqualMask32Bit : While incrementing scalar is less than or equal to + + /// + /// svbool_t svwhilele_b32[_s32](int32_t op1, int32_t op2) + /// WHILELE Presult.S, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask32Bit(int left, int right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilele_b32[_s64](int64_t op1, int64_t op2) + /// WHILELE Presult.S, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask32Bit(long left, long right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilele_b32[_u32](uint32_t op1, uint32_t op2) + /// WHILELS Presult.S, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask32Bit(uint left, uint right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilele_b32[_u64](uint64_t op1, uint64_t op2) + /// WHILELS Presult.S, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask32Bit(ulong left, ulong right) { throw new PlatformNotSupportedException(); } + + + /// CreateWhileLessThanOrEqualMask64Bit : While incrementing scalar is less than or equal to + + /// + /// svbool_t svwhilele_b64[_s32](int32_t op1, int32_t op2) + /// WHILELE Presult.D, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask64Bit(int left, int right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilele_b64[_s64](int64_t op1, int64_t op2) + /// WHILELE Presult.D, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask64Bit(long left, long right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilele_b64[_u32](uint32_t op1, uint32_t op2) + /// WHILELS Presult.D, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask64Bit(uint left, uint right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilele_b64[_u64](uint64_t op1, uint64_t op2) + /// WHILELS Presult.D, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask64Bit(ulong left, ulong right) { throw new PlatformNotSupportedException(); } + + + /// CreateWhileLessThanOrEqualMask8Bit : While incrementing scalar is less than or equal to + + /// + /// svbool_t svwhilele_b8[_s32](int32_t op1, int32_t op2) + /// WHILELE Presult.B, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask8Bit(int left, int right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilele_b8[_s64](int64_t op1, int64_t op2) + /// WHILELE Presult.B, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask8Bit(long left, long right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilele_b8[_u32](uint32_t op1, uint32_t op2) + /// WHILELS Presult.B, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask8Bit(uint left, uint right) { throw new PlatformNotSupportedException(); } + + /// + /// svbool_t svwhilele_b8[_u64](uint64_t op1, uint64_t op2) + /// WHILELS Presult.B, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask8Bit(ulong left, ulong right) { throw new PlatformNotSupportedException(); } + + + /// Divide : Divide + + /// + /// svfloat32_t svdiv[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FDIV Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FDIV Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svdiv[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FDIV Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FDIV Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svdiv[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; FDIV Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Divide(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svdiv[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FDIV Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FDIV Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svdiv[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FDIV Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FDIV Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svdiv[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; FDIV Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Divide(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// DotProduct : Dot product + + /// + /// svint32_t svdot[_s32](svint32_t op1, svint8_t op2, svint8_t op3) + /// SDOT Ztied1.S, Zop2.B, Zop3.B + /// + public static unsafe Vector DotProduct(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svdot[_s64](svint64_t op1, svint16_t op2, svint16_t op3) + /// SDOT Ztied1.D, Zop2.H, Zop3.H + /// + public static unsafe Vector DotProduct(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svdot[_u32](svuint32_t op1, svuint8_t op2, svuint8_t op3) + /// UDOT Ztied1.S, Zop2.B, Zop3.B + /// + public static unsafe Vector DotProduct(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svdot[_u64](svuint64_t op1, svuint16_t op2, svuint16_t op3) + /// UDOT Ztied1.D, Zop2.H, Zop3.H + /// + public static unsafe Vector DotProduct(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// DotProductBySelectedScalar : Dot product + + /// + /// svint32_t svdot_lane[_s32](svint32_t op1, svint8_t op2, svint8_t op3, uint64_t imm_index) + /// SDOT Ztied1.S, Zop2.B, Zop3.B[imm_index] + /// + public static unsafe Vector DotProductBySelectedScalar(Vector addend, Vector left, Vector right, [ConstantExpected] byte rightIndex) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svdot_lane[_s64](svint64_t op1, svint16_t op2, svint16_t op3, uint64_t imm_index) + /// SDOT Ztied1.D, Zop2.H, Zop3.H[imm_index] + /// + public static unsafe Vector DotProductBySelectedScalar(Vector addend, Vector left, Vector right, [ConstantExpected] byte rightIndex) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svdot_lane[_u32](svuint32_t op1, svuint8_t op2, svuint8_t op3, uint64_t imm_index) + /// UDOT Ztied1.S, Zop2.B, Zop3.B[imm_index] + /// + public static unsafe Vector DotProductBySelectedScalar(Vector addend, Vector left, Vector right, [ConstantExpected] byte rightIndex) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svdot_lane[_u64](svuint64_t op1, svuint16_t op2, svuint16_t op3, uint64_t imm_index) + /// UDOT Ztied1.D, Zop2.H, Zop3.H[imm_index] + /// + public static unsafe Vector DotProductBySelectedScalar(Vector addend, Vector left, Vector right, [ConstantExpected] byte rightIndex) { throw new PlatformNotSupportedException(); } + + /// FusedMultiplyAdd : Multiply-add, addend first + + /// + /// svfloat64_t svmla[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svmla[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svmla[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// FMLA Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector FusedMultiplyAdd(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svmla[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svmla[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svmla[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// FMLA Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector FusedMultiplyAdd(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// FusedMultiplyAddBySelectedScalar : Multiply-add, addend first + + /// + /// svfloat64_t svmla_lane[_f64](svfloat64_t op1, svfloat64_t op2, svfloat64_t op3, uint64_t imm_index) + /// FMLA Ztied1.D, Zop2.D, Zop3.D[imm_index] + /// + public static unsafe Vector FusedMultiplyAddBySelectedScalar(Vector addend, Vector left, Vector right, [ConstantExpected] byte rightIndex) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svmla_lane[_f32](svfloat32_t op1, svfloat32_t op2, svfloat32_t op3, uint64_t imm_index) + /// FMLA Ztied1.S, Zop2.S, Zop3.S[imm_index] + /// + public static unsafe Vector FusedMultiplyAddBySelectedScalar(Vector addend, Vector left, Vector right, [ConstantExpected] byte rightIndex) { throw new PlatformNotSupportedException(); } + + + /// FusedMultiplyAddNegated : Negated multiply-add, addend first + + /// + /// svfloat64_t svnmla[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svnmla[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svnmla[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// FNMLA Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector FusedMultiplyAddNegated(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svnmla[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svnmla[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svnmla[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// FNMLA Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector FusedMultiplyAddNegated(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// FusedMultiplySubtract : Multiply-subtract, minuend first + + /// + /// svfloat64_t svmls[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svmls[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svmls[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// FMLS Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector FusedMultiplySubtract(Vector minuend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svmls[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svmls[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svmls[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// FMLS Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector FusedMultiplySubtract(Vector minuend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// FusedMultiplySubtractBySelectedScalar : Multiply-subtract, minuend first + + /// + /// svfloat64_t svmls_lane[_f64](svfloat64_t op1, svfloat64_t op2, svfloat64_t op3, uint64_t imm_index) + /// FMLS Ztied1.D, Zop2.D, Zop3.D[imm_index] + /// + public static unsafe Vector FusedMultiplySubtractBySelectedScalar(Vector minuend, Vector left, Vector right, [ConstantExpected] byte rightIndex) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svmls_lane[_f32](svfloat32_t op1, svfloat32_t op2, svfloat32_t op3, uint64_t imm_index) + /// FMLS Ztied1.S, Zop2.S, Zop3.S[imm_index] + /// + public static unsafe Vector FusedMultiplySubtractBySelectedScalar(Vector minuend, Vector left, Vector right, [ConstantExpected] byte rightIndex) { throw new PlatformNotSupportedException(); } + + + /// FusedMultiplySubtractNegated : Negated multiply-subtract, minuend first + + /// + /// svfloat64_t svnmls[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svnmls[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svnmls[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// FNMLS Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector FusedMultiplySubtractNegated(Vector minuend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svnmls[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svnmls[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svnmls[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// FNMLS Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector FusedMultiplySubtractNegated(Vector minuend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// LoadVector : Unextended load + + /// + /// svint8_t svld1[_s8](svbool_t pg, const int8_t *base) + /// LD1B Zresult.B, Pg/Z, [Xarray, Xindex] + /// LD1B Zresult.B, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svld1[_s16](svbool_t pg, const int16_t *base) + /// LD1H Zresult.H, Pg/Z, [Xarray, Xindex, LSL #1] + /// LD1H Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, short* address) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svld1[_s32](svbool_t pg, const int32_t *base) + /// LD1W Zresult.S, Pg/Z, [Xarray, Xindex, LSL #2] + /// LD1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, int* address) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svld1[_s64](svbool_t pg, const int64_t *base) + /// LD1D Zresult.D, Pg/Z, [Xarray, Xindex, LSL #3] + /// LD1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, long* address) { throw new PlatformNotSupportedException(); } + + /// + /// svuint8_t svld1[_u8](svbool_t pg, const uint8_t *base) + /// LD1B Zresult.B, Pg/Z, [Xarray, Xindex] + /// LD1B Zresult.B, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svld1[_u16](svbool_t pg, const uint16_t *base) + /// LD1H Zresult.H, Pg/Z, [Xarray, Xindex, LSL #1] + /// LD1H Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svld1[_u32](svbool_t pg, const uint32_t *base) + /// LD1W Zresult.S, Pg/Z, [Xarray, Xindex, LSL #2] + /// LD1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, uint* address) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svld1[_u64](svbool_t pg, const uint64_t *base) + /// LD1D Zresult.D, Pg/Z, [Xarray, Xindex, LSL #3] + /// LD1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, ulong* address) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svld1[_f32](svbool_t pg, const float32_t *base) + /// LD1W Zresult.S, Pg/Z, [Xarray, Xindex, LSL #2] + /// LD1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, float* address) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svld1[_f64](svbool_t pg, const float64_t *base) + /// LD1D Zresult.D, Pg/Z, [Xarray, Xindex, LSL #3] + /// LD1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, double* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorByteZeroExtendToInt16 : Load 8-bit data and zero-extend + + /// + /// svint16_t svld1ub_s16(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToInt16(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorByteZeroExtendToInt32 : Load 8-bit data and zero-extend + + /// + /// svint32_t svld1ub_s32(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToInt32(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorByteZeroExtendToInt64 : Load 8-bit data and zero-extend + + /// + /// svint64_t svld1ub_s64(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToInt64(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorByteZeroExtendToUInt16 : Load 8-bit data and zero-extend + + /// + /// svuint16_t svld1ub_u16(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToUInt16(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorByteZeroExtendToUInt32 : Load 8-bit data and zero-extend + + /// + /// svuint32_t svld1ub_u32(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToUInt32(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorByteZeroExtendToUInt64 : Load 8-bit data and zero-extend + + /// + /// svuint64_t svld1ub_u64(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToUInt64(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorInt16SignExtendToInt32 : Load 16-bit data and sign-extend + + /// + /// svint32_t svld1sh_s32(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToInt32(Vector mask, short* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorInt16SignExtendToInt64 : Load 16-bit data and sign-extend + + /// + /// svint64_t svld1sh_s64(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToInt64(Vector mask, short* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorInt16SignExtendToUInt32 : Load 16-bit data and sign-extend + + /// + /// svuint32_t svld1sh_u32(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToUInt32(Vector mask, short* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorInt16SignExtendToUInt64 : Load 16-bit data and sign-extend + + /// + /// svuint64_t svld1sh_u64(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToUInt64(Vector mask, short* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorInt32SignExtendToInt64 : Load 32-bit data and sign-extend + + /// + /// svint64_t svld1sw_s64(svbool_t pg, const int32_t *base) + /// LD1SW Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt32SignExtendToInt64(Vector mask, int* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorInt32SignExtendToUInt64 : Load 32-bit data and sign-extend + + /// + /// svuint64_t svld1sw_u64(svbool_t pg, const int32_t *base) + /// LD1SW Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt32SignExtendToUInt64(Vector mask, int* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorSByteSignExtendToInt16 : Load 8-bit data and sign-extend + + /// + /// svint16_t svld1sb_s16(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToInt16(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorSByteSignExtendToInt32 : Load 8-bit data and sign-extend + + /// + /// svint32_t svld1sb_s32(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToInt32(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorSByteSignExtendToInt64 : Load 8-bit data and sign-extend + + /// + /// svint64_t svld1sb_s64(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToInt64(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorSByteSignExtendToUInt16 : Load 8-bit data and sign-extend + + /// + /// svuint16_t svld1sb_u16(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToUInt16(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorSByteSignExtendToUInt32 : Load 8-bit data and sign-extend + + /// + /// svuint32_t svld1sb_u32(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToUInt32(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorSByteSignExtendToUInt64 : Load 8-bit data and sign-extend + + /// + /// svuint64_t svld1sb_u64(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToUInt64(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorUInt16ZeroExtendToInt32 : Load 16-bit data and zero-extend + + /// + /// svint32_t svld1uh_s32(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToInt32(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorUInt16ZeroExtendToInt64 : Load 16-bit data and zero-extend + + /// + /// svint64_t svld1uh_s64(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToInt64(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorUInt16ZeroExtendToUInt32 : Load 16-bit data and zero-extend + + /// + /// svuint32_t svld1uh_u32(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToUInt32(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorUInt16ZeroExtendToUInt64 : Load 16-bit data and zero-extend + + /// + /// svuint64_t svld1uh_u64(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToUInt64(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorUInt32ZeroExtendToInt64 : Load 32-bit data and zero-extend + + /// + /// svint64_t svld1uw_s64(svbool_t pg, const uint32_t *base) + /// LD1W Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt32ZeroExtendToInt64(Vector mask, uint* address) { throw new PlatformNotSupportedException(); } + + + /// LoadVectorUInt32ZeroExtendToUInt64 : Load 32-bit data and zero-extend + + /// + /// svuint64_t svld1uw_u64(svbool_t pg, const uint32_t *base) + /// LD1W Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt32ZeroExtendToUInt64(Vector mask, uint* address) { throw new PlatformNotSupportedException(); } + + /// Max : Maximum + + /// + /// svuint8_t svmax[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmax[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmax[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// UMAX Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UMAX Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svmax[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmax[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmax[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMAX Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMAX Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svmax[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmax[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmax[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// SMAX Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SMAX Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svmax[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmax[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmax[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// SMAX Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SMAX Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svmax[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmax[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmax[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// SMAX Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SMAX Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svmax[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmax[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmax[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// SMAX Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SMAX Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svmax[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmax[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmax[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMAX Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMAX Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svmax[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmax[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmax[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// UMAX Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UMAX Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svmax[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmax[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmax[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// UMAX Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UMAX Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svmax[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmax[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmax[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// UMAX Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UMAX Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Max(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// MaxAcross : Maximum reduction to scalar + + /// + /// uint8_t svmaxv[_u8](svbool_t pg, svuint8_t op) + /// UMAXV Bresult, Pg, Zop.B + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// float64_t svmaxv[_f64](svbool_t pg, svfloat64_t op) + /// FMAXV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int16_t svmaxv[_s16](svbool_t pg, svint16_t op) + /// SMAXV Hresult, Pg, Zop.H + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t svmaxv[_s32](svbool_t pg, svint32_t op) + /// SMAXV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svmaxv[_s64](svbool_t pg, svint64_t op) + /// SMAXV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t svmaxv[_s8](svbool_t pg, svint8_t op) + /// SMAXV Bresult, Pg, Zop.B + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// float32_t svmaxv[_f32](svbool_t pg, svfloat32_t op) + /// FMAXV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t svmaxv[_u16](svbool_t pg, svuint16_t op) + /// UMAXV Hresult, Pg, Zop.H + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t svmaxv[_u32](svbool_t pg, svuint32_t op) + /// UMAXV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svmaxv[_u64](svbool_t pg, svuint64_t op) + /// UMAXV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxAcross(Vector value) { throw new PlatformNotSupportedException(); } + + + /// MaxNumber : Maximum number + + /// + /// svfloat64_t svmaxnm[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmaxnm[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmaxnm[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMAXNM Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMAXNM Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector MaxNumber(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svmaxnm[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmaxnm[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmaxnm[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMAXNM Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMAXNM Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector MaxNumber(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// MaxNumberAcross : Maximum number reduction to scalar + + /// + /// float64_t svmaxnmv[_f64](svbool_t pg, svfloat64_t op) + /// FMAXNMV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxNumberAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// float32_t svmaxnmv[_f32](svbool_t pg, svfloat32_t op) + /// FMAXNMV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxNumberAcross(Vector value) { throw new PlatformNotSupportedException(); } + + + /// Min : Minimum + + /// + /// svuint8_t svmin[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmin[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmin[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// UMIN Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UMIN Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svmin[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmin[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmin[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMIN Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMIN Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svmin[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmin[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmin[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// SMIN Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SMIN Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svmin[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmin[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmin[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// SMIN Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SMIN Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svmin[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmin[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmin[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// SMIN Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SMIN Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svmin[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmin[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmin[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// SMIN Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SMIN Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svmin[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmin[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmin[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMIN Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMIN Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svmin[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmin[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmin[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// UMIN Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UMIN Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svmin[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmin[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmin[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// UMIN Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UMIN Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svmin[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmin[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmin[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// UMIN Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UMIN Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Min(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// MinAcross : Minimum reduction to scalar + + /// + /// uint8_t svminv[_u8](svbool_t pg, svuint8_t op) + /// UMINV Bresult, Pg, Zop.B + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// float64_t svminv[_f64](svbool_t pg, svfloat64_t op) + /// FMINV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int16_t svminv[_s16](svbool_t pg, svint16_t op) + /// SMINV Hresult, Pg, Zop.H + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t svminv[_s32](svbool_t pg, svint32_t op) + /// SMINV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svminv[_s64](svbool_t pg, svint64_t op) + /// SMINV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t svminv[_s8](svbool_t pg, svint8_t op) + /// SMINV Bresult, Pg, Zop.B + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// float32_t svminv[_f32](svbool_t pg, svfloat32_t op) + /// FMINV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t svminv[_u16](svbool_t pg, svuint16_t op) + /// UMINV Hresult, Pg, Zop.H + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t svminv[_u32](svbool_t pg, svuint32_t op) + /// UMINV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svminv[_u64](svbool_t pg, svuint64_t op) + /// UMINV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinAcross(Vector value) { throw new PlatformNotSupportedException(); } + + + /// MinNumber : Minimum number + + /// + /// svfloat64_t svminnm[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svminnm[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svminnm[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMINNM Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMINNM Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector MinNumber(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svminnm[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svminnm[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svminnm[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMINNM Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMINNM Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector MinNumber(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// MinNumberAcross : Minimum number reduction to scalar + + /// + /// float64_t svminnmv[_f64](svbool_t pg, svfloat64_t op) + /// FMINNMV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinNumberAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// float32_t svminnmv[_f32](svbool_t pg, svfloat32_t op) + /// FMINNMV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinNumberAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// Multiply : Multiply + + /// + /// svint8_t svmul[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svint8_t svmul[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MUL Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svint8_t svmul[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// MOVPRFX Zresult.B, Pg/Z, Zop2.B; MUL Zresult.B, Pg/M, Zresult.B, Zop1.B + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svmul[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svint16_t svmul[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MUL Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svint16_t svmul[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// MOVPRFX Zresult.H, Pg/Z, Zop2.H; MUL Zresult.H, Pg/M, Zresult.H, Zop1.H + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svmul[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svint32_t svmul[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MUL Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svint32_t svmul[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// MOVPRFX Zresult.S, Pg/Z, Zop2.S; MUL Zresult.S, Pg/M, Zresult.S, Zop1.S + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svmul[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svint64_t svmul[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MUL Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svint64_t svmul[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// MOVPRFX Zresult.D, Pg/Z, Zop2.D; MUL Zresult.D, Pg/M, Zresult.D, Zop1.D + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint8_t svmul[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svuint8_t svmul[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MUL Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svuint8_t svmul[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// MOVPRFX Zresult.B, Pg/Z, Zop2.B; MUL Zresult.B, Pg/M, Zresult.B, Zop1.B + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svmul[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svuint16_t svmul[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MUL Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svuint16_t svmul[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// MOVPRFX Zresult.H, Pg/Z, Zop2.H; MUL Zresult.H, Pg/M, Zresult.H, Zop1.H + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svmul[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svuint32_t svmul[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MUL Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svuint32_t svmul[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// MOVPRFX Zresult.S, Pg/Z, Zop2.S; MUL Zresult.S, Pg/M, Zresult.S, Zop1.S + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svmul[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svuint64_t svmul[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MUL Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svuint64_t svmul[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// MOVPRFX Zresult.D, Pg/Z, Zop2.D; MUL Zresult.D, Pg/M, Zresult.D, Zop1.D + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svmul[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FMUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svmul[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMUL Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// FMUL Zresult.S, Zop1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FMUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svmul[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; FMUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// MOVPRFX Zresult.S, Pg/Z, Zop2.S; FMUL Zresult.S, Pg/M, Zresult.S, Zop1.S + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svmul[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FMUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svmul[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMUL Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// FMUL Zresult.D, Zop1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FMUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svmul[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; FMUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// MOVPRFX Zresult.D, Pg/Z, Zop2.D; FMUL Zresult.D, Pg/M, Zresult.D, Zop1.D + /// + public static unsafe Vector Multiply(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// MultiplyAdd : Multiply-add, addend first + + /// + /// svuint8_t svmla[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2, svuint8_t op3) + /// svuint8_t svmla[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2, svuint8_t op3) + /// svuint8_t svmla[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2, svuint8_t op3) + /// MLA Ztied1.B, Pg/M, Zop2.B, Zop3.B + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svmla[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2, svint16_t op3) + /// svint16_t svmla[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2, svint16_t op3) + /// svint16_t svmla[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2, svint16_t op3) + /// MLA Ztied1.H, Pg/M, Zop2.H, Zop3.H + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svmla[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2, svint32_t op3) + /// svint32_t svmla[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2, svint32_t op3) + /// svint32_t svmla[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2, svint32_t op3) + /// MLA Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svmla[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2, svint64_t op3) + /// svint64_t svmla[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2, svint64_t op3) + /// svint64_t svmla[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2, svint64_t op3) + /// MLA Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svmla[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2, svint8_t op3) + /// svint8_t svmla[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2, svint8_t op3) + /// svint8_t svmla[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2, svint8_t op3) + /// MLA Ztied1.B, Pg/M, Zop2.B, Zop3.B + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svmla[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2, svuint16_t op3) + /// svuint16_t svmla[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2, svuint16_t op3) + /// svuint16_t svmla[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2, svuint16_t op3) + /// MLA Ztied1.H, Pg/M, Zop2.H, Zop3.H + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svmla[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2, svuint32_t op3) + /// svuint32_t svmla[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2, svuint32_t op3) + /// svuint32_t svmla[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2, svuint32_t op3) + /// MLA Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svmla[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2, svuint64_t op3) + /// svuint64_t svmla[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2, svuint64_t op3) + /// svuint64_t svmla[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2, svuint64_t op3) + /// MLA Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// MultiplyBySelectedScalar : Multiply + + /// + /// svfloat64_t svmul_lane[_f64](svfloat64_t op1, svfloat64_t op2, uint64_t imm_index) + /// FMUL Zresult.D, Zop1.D, Zop2.D[imm_index] + /// + public static unsafe Vector MultiplyBySelectedScalar(Vector left, Vector right, [ConstantExpected] byte rightIndex) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svmul_lane[_f32](svfloat32_t op1, svfloat32_t op2, uint64_t imm_index) + /// FMUL Zresult.S, Zop1.S, Zop2.S[imm_index] + /// + public static unsafe Vector MultiplyBySelectedScalar(Vector left, Vector right, [ConstantExpected] byte rightIndex) { throw new PlatformNotSupportedException(); } + + /// MultiplyExtended : Multiply extended (∞×0=2) + + /// + /// svfloat64_t svmulx[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmulx[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmulx[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMULX Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// + public static unsafe Vector MultiplyExtended(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svmulx[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmulx[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmulx[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMULX Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// + public static unsafe Vector MultiplyExtended(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// MultiplySubtract : Multiply-subtract, minuend first + + /// + /// svuint8_t svmls[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2, svuint8_t op3) + /// svuint8_t svmls[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2, svuint8_t op3) + /// svuint8_t svmls[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2, svuint8_t op3) + /// MLS Ztied1.B, Pg/M, Zop2.B, Zop3.B + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svmls[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2, svint16_t op3) + /// svint16_t svmls[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2, svint16_t op3) + /// svint16_t svmls[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2, svint16_t op3) + /// MLS Ztied1.H, Pg/M, Zop2.H, Zop3.H + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svmls[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2, svint32_t op3) + /// svint32_t svmls[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2, svint32_t op3) + /// svint32_t svmls[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2, svint32_t op3) + /// MLS Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svmls[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2, svint64_t op3) + /// svint64_t svmls[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2, svint64_t op3) + /// svint64_t svmls[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2, svint64_t op3) + /// MLS Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svmls[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2, svint8_t op3) + /// svint8_t svmls[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2, svint8_t op3) + /// svint8_t svmls[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2, svint8_t op3) + /// MLS Ztied1.B, Pg/M, Zop2.B, Zop3.B + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svmls[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2, svuint16_t op3) + /// svuint16_t svmls[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2, svuint16_t op3) + /// svuint16_t svmls[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2, svuint16_t op3) + /// MLS Ztied1.H, Pg/M, Zop2.H, Zop3.H + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svmls[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2, svuint32_t op3) + /// svuint32_t svmls[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2, svuint32_t op3) + /// svuint32_t svmls[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2, svuint32_t op3) + /// MLS Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svmls[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2, svuint64_t op3) + /// svuint64_t svmls[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2, svuint64_t op3) + /// svuint64_t svmls[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2, svuint64_t op3) + /// MLS Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// Negate : Negate + + /// + /// svfloat64_t svneg[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op) + /// svfloat64_t svneg[_f64]_x(svbool_t pg, svfloat64_t op) + /// svfloat64_t svneg[_f64]_z(svbool_t pg, svfloat64_t op) + /// FNEG Ztied.D, Pg/M, Zop.D + /// + public static unsafe Vector Negate(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svneg[_s16]_m(svint16_t inactive, svbool_t pg, svint16_t op) + /// svint16_t svneg[_s16]_x(svbool_t pg, svint16_t op) + /// svint16_t svneg[_s16]_z(svbool_t pg, svint16_t op) + /// NEG Ztied.H, Pg/M, Zop.H + /// + public static unsafe Vector Negate(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svneg[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// svint32_t svneg[_s32]_x(svbool_t pg, svint32_t op) + /// svint32_t svneg[_s32]_z(svbool_t pg, svint32_t op) + /// NEG Ztied.S, Pg/M, Zop.S + /// + public static unsafe Vector Negate(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svneg[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// svint64_t svneg[_s64]_x(svbool_t pg, svint64_t op) + /// svint64_t svneg[_s64]_z(svbool_t pg, svint64_t op) + /// NEG Ztied.D, Pg/M, Zop.D + /// + public static unsafe Vector Negate(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svneg[_s8]_x(svbool_t pg, svint8_t op) + /// svint8_t svneg[_s8]_m(svint8_t inactive, svbool_t pg, svint8_t op) + /// svint8_t svneg[_s8]_z(svbool_t pg, svint8_t op) + /// NEG Ztied.B, Pg/M, Zop.B + /// + public static unsafe Vector Negate(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svneg[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op) + /// svfloat32_t svneg[_f32]_x(svbool_t pg, svfloat32_t op) + /// svfloat32_t svneg[_f32]_z(svbool_t pg, svfloat32_t op) + /// FNEG Ztied.S, Pg/M, Zop.S + /// + public static unsafe Vector Negate(Vector value) { throw new PlatformNotSupportedException(); } + + /// Or : Bitwise inclusive OR + + /// + /// svuint8_t svorr[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svorr[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svorr[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// ORR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svorr[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svorr[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svorr[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// ORR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svorr[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svorr[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svorr[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// ORR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svorr[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svorr[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svorr[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// ORR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svorr[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svorr[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svorr[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// ORR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svorr[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svorr[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svorr[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// ORR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svorr[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svorr[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svorr[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// ORR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svorr[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svorr[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svorr[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// ORR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// OrAcross : Bitwise inclusive OR reduction to scalar + + /// + /// uint8_t svorv[_u8](svbool_t pg, svuint8_t op) + /// ORV Bresult, Pg, Zop.B + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int16_t svorv[_s16](svbool_t pg, svint16_t op) + /// ORV Hresult, Pg, Zop.H + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t svorv[_s32](svbool_t pg, svint32_t op) + /// ORV Sresult, Pg, Zop.S + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t svorv[_s64](svbool_t pg, svint64_t op) + /// ORV Dresult, Pg, Zop.D + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t svorv[_s8](svbool_t pg, svint8_t op) + /// ORV Bresult, Pg, Zop.B + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t svorv[_u16](svbool_t pg, svuint16_t op) + /// ORV Hresult, Pg, Zop.H + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t svorv[_u32](svbool_t pg, svuint32_t op) + /// ORV Sresult, Pg, Zop.S + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t svorv[_u64](svbool_t pg, svuint64_t op) + /// ORV Dresult, Pg, Zop.D + /// + public static unsafe Vector OrAcross(Vector value) { throw new PlatformNotSupportedException(); } + + + /// SignExtend16 : Sign-extend the low 16 bits + + /// + /// svint32_t svexth[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// SXTH Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; SXTH Zresult.S, Pg/M, Zop.S + /// svint32_t svexth[_s32]_x(svbool_t pg, svint32_t op) + /// SXTH Ztied.S, Pg/M, Ztied.S + /// MOVPRFX Zresult, Zop; SXTH Zresult.S, Pg/M, Zop.S + /// svint32_t svexth[_s32]_z(svbool_t pg, svint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; SXTH Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector SignExtend16(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svexth[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// SXTH Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; SXTH Zresult.D, Pg/M, Zop.D + /// svint64_t svexth[_s64]_x(svbool_t pg, svint64_t op) + /// SXTH Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; SXTH Zresult.D, Pg/M, Zop.D + /// svint64_t svexth[_s64]_z(svbool_t pg, svint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; SXTH Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector SignExtend16(Vector value) { throw new PlatformNotSupportedException(); } + + + /// SignExtend32 : Sign-extend the low 32 bits + + /// + /// svint64_t svextw[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// SXTW Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; SXTW Zresult.D, Pg/M, Zop.D + /// svint64_t svextw[_s64]_x(svbool_t pg, svint64_t op) + /// SXTW Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; SXTW Zresult.D, Pg/M, Zop.D + /// svint64_t svextw[_s64]_z(svbool_t pg, svint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; SXTW Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector SignExtend32(Vector value) { throw new PlatformNotSupportedException(); } + + + /// SignExtend8 : Sign-extend the low 8 bits + + /// + /// svint16_t svextb[_s16]_m(svint16_t inactive, svbool_t pg, svint16_t op) + /// SXTB Ztied.H, Pg/M, Zop.H + /// MOVPRFX Zresult, Zinactive; SXTB Zresult.H, Pg/M, Zop.H + /// svint16_t svextb[_s16]_x(svbool_t pg, svint16_t op) + /// SXTB Ztied.H, Pg/M, Ztied.H + /// MOVPRFX Zresult, Zop; SXTB Zresult.H, Pg/M, Zop.H + /// svint16_t svextb[_s16]_z(svbool_t pg, svint16_t op) + /// MOVPRFX Zresult.H, Pg/Z, Zop.H; SXTB Zresult.H, Pg/M, Zop.H + /// + public static unsafe Vector SignExtend8(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svextb[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// SXTB Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; SXTB Zresult.S, Pg/M, Zop.S + /// svint32_t svextb[_s32]_x(svbool_t pg, svint32_t op) + /// SXTB Ztied.S, Pg/M, Ztied.S + /// MOVPRFX Zresult, Zop; SXTB Zresult.S, Pg/M, Zop.S + /// svint32_t svextb[_s32]_z(svbool_t pg, svint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; SXTB Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector SignExtend8(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svextb[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// SXTB Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; SXTB Zresult.D, Pg/M, Zop.D + /// svint64_t svextb[_s64]_x(svbool_t pg, svint64_t op) + /// SXTB Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; SXTB Zresult.D, Pg/M, Zop.D + /// svint64_t svextb[_s64]_z(svbool_t pg, svint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; SXTB Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector SignExtend8(Vector value) { throw new PlatformNotSupportedException(); } + + /// Subtract : Subtract + + /// + /// svint8_t svsub[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svint8_t svsub[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SUB Zresult.B, Zop1.B, Zop2.B + /// svint8_t svsub[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svsub[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svint16_t svsub[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SUB Zresult.H, Zop1.H, Zop2.H + /// svint16_t svsub[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svsub[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svint32_t svsub[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SUB Zresult.S, Zop1.S, Zop2.S + /// svint32_t svsub[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svsub[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svint64_t svsub[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SUB Zresult.D, Zop1.D, Zop2.D + /// svint64_t svsub[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint8_t svsub[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svuint8_t svsub[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SUB Zresult.B, Zop1.B, Zop2.B + /// svuint8_t svsub[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svsub[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svuint16_t svsub[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SUB Zresult.H, Zop1.H, Zop2.H + /// svuint16_t svsub[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svsub[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svuint32_t svsub[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SUB Zresult.S, Zop1.S, Zop2.S + /// svuint32_t svsub[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svsub[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svuint64_t svsub[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SUB Zresult.D, Zop1.D, Zop2.D + /// svuint64_t svsub[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svsub[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FSUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svsub[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FSUB Zresult.S, Zop1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FSUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svsub[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; FSUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svsub[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FSUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svsub[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FSUB Zresult.D, Zop1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FSUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svsub[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; FSUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Subtract(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// SubtractSaturate : Saturating subtract + + /// + /// svuint8_t svqsub[_u8](svuint8_t op1, svuint8_t op2) + /// UQSUB Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector SubtractSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svqsub[_s16](svint16_t op1, svint16_t op2) + /// SQSUB Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector SubtractSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svqsub[_s32](svint32_t op1, svint32_t op2) + /// SQSUB Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector SubtractSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svqsub[_s64](svint64_t op1, svint64_t op2) + /// SQSUB Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector SubtractSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svqsub[_s8](svint8_t op1, svint8_t op2) + /// SQSUB Zresult.B, Zop1.B, Zop2.B /// - public static unsafe Vector CreateTrueMaskByte([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + public static unsafe Vector SubtractSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// + /// svuint16_t svqsub[_u16](svuint16_t op1, svuint16_t op2) + /// UQSUB Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector SubtractSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - /// CreateTrueMaskDouble : Set predicate elements to true + /// + /// svuint32_t svqsub[_u32](svuint32_t op1, svuint32_t op2) + /// UQSUB Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector SubtractSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// - /// svbool_t svptrue_pat_b8(enum svpattern pattern) - /// PTRUE Presult.B, pattern + /// svuint64_t svqsub[_u64](svuint64_t op1, svuint64_t op2) + /// UQSUB Zresult.D, Zop1.D, Zop2.D /// - public static unsafe Vector CreateTrueMaskDouble([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + public static unsafe Vector SubtractSaturate(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - /// CreateTrueMaskInt16 : Set predicate elements to true + /// SignExtendWideningLower : Unpack and extend low half /// - /// svbool_t svptrue_pat_b8(enum svpattern pattern) - /// PTRUE Presult.B, pattern + /// svint16_t svunpklo[_s16](svint8_t op) + /// SUNPKLO Zresult.H, Zop.B /// - public static unsafe Vector CreateTrueMaskInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + public static unsafe Vector SignExtendWideningLower(Vector value) { throw new PlatformNotSupportedException(); } + /// + /// svint32_t svunpklo[_s32](svint16_t op) + /// SUNPKLO Zresult.S, Zop.H + /// + public static unsafe Vector SignExtendWideningLower(Vector value) { throw new PlatformNotSupportedException(); } - /// CreateTrueMaskInt32 : Set predicate elements to true + /// + /// svint64_t svunpklo[_s64](svint32_t op) + /// SUNPKLO Zresult.D, Zop.S + /// + public static unsafe Vector SignExtendWideningLower(Vector value) { throw new PlatformNotSupportedException(); } + + + /// SignExtendWideningUpper : Unpack and extend high half /// - /// svbool_t svptrue_pat_b8(enum svpattern pattern) - /// PTRUE Presult.B, pattern + /// svint16_t svunpkhi[_s16](svint8_t op) + /// SUNPKHI Zresult.H, Zop.B /// - public static unsafe Vector CreateTrueMaskInt32([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + public static unsafe Vector SignExtendWideningUpper(Vector value) { throw new PlatformNotSupportedException(); } + /// + /// svint32_t svunpkhi[_s32](svint16_t op) + /// SUNPKHI Zresult.S, Zop.H + /// + public static unsafe Vector SignExtendWideningUpper(Vector value) { throw new PlatformNotSupportedException(); } - /// CreateTrueMaskInt64 : Set predicate elements to true + /// + /// svint64_t svunpkhi[_s64](svint32_t op) + /// SUNPKHI Zresult.D, Zop.S + /// + public static unsafe Vector SignExtendWideningUpper(Vector value) { throw new PlatformNotSupportedException(); } + + + /// UnzipEven : Concatenate even elements from two inputs /// - /// svbool_t svptrue_pat_b8(enum svpattern pattern) - /// PTRUE Presult.B, pattern + /// svint8_t svuzp1[_s8](svint8_t op1, svint8_t op2) /// - public static unsafe Vector CreateTrueMaskInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// + /// svint16_t svuzp1[_s16](svint16_t op1, svint16_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - /// CreateTrueMaskSByte : Set predicate elements to true + /// + /// svint32_t svuzp1[_s32](svint32_t op1, svint32_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// - /// svbool_t svptrue_pat_b8(enum svpattern pattern) - /// PTRUE Presult.B, pattern + /// svint64_t svuzp1[_s64](svint64_t op1, svint64_t op2) /// - public static unsafe Vector CreateTrueMaskSByte([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// + /// svuint8_t svuzp1[_u8](svuint8_t op1, svuint8_t op2) + /// svbool_t svuzp1_b8(svbool_t op1, svbool_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - /// CreateTrueMaskSingle : Set predicate elements to true + /// + /// svuint16_t svuzp1[_u16](svuint16_t op1, svuint16_t op2) + /// svbool_t svuzp1_b16(svbool_t op1, svbool_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// - /// svbool_t svptrue_pat_b8(enum svpattern pattern) - /// PTRUE Presult.B, pattern + /// svuint32_t svuzp1[_u32](svuint32_t op1, svuint32_t op2) + /// svbool_t svuzp1_b32(svbool_t op1, svbool_t op2) /// - public static unsafe Vector CreateTrueMaskSingle([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// + /// svuint64_t svuzp1[_u64](svuint64_t op1, svuint64_t op2) + /// svbool_t svuzp1_b64(svbool_t op1, svbool_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - /// CreateTrueMaskUInt16 : Set predicate elements to true + /// + /// svfloat32_t svuzp1[_f32](svfloat32_t op1, svfloat32_t op2) + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// - /// svbool_t svptrue_pat_b16(enum svpattern pattern) - /// PTRUE Presult.H, pattern + /// svfloat64_t svuzp1[_f64](svfloat64_t op1, svfloat64_t op2) /// - public static unsafe Vector CreateTrueMaskUInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + public static unsafe Vector UnzipEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - /// CreateTrueMaskUInt32 : Set predicate elements to true + /// UnzipOdd : Concatenate odd elements from two inputs /// - /// svbool_t svptrue_pat_b32(enum svpattern pattern) - /// PTRUE Presult.S, pattern + /// svuint8_t svuzp2[_u8](svuint8_t op1, svuint8_t op2) + /// svbool_t svuzp2_b8(svbool_t op1, svbool_t op2) /// - public static unsafe Vector CreateTrueMaskUInt32([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// + /// svfloat64_t svuzp2[_f64](svfloat64_t op1, svfloat64_t op2) + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - /// CreateTrueMaskUInt64 : Set predicate elements to true + /// + /// svint16_t svuzp2[_s16](svint16_t op1, svint16_t op2) + /// UZP2 Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// - /// svbool_t svptrue_pat_b64(enum svpattern pattern) - /// PTRUE Presult.D, pattern + /// svint32_t svuzp2[_s32](svint32_t op1, svint32_t op2) /// - public static unsafe Vector CreateTrueMaskUInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); } + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// + /// svint64_t svuzp2[_s64](svint64_t op1, svint64_t op2) + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// + /// svint8_t svuzp2[_s8](svint8_t op1, svint8_t op2) + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } - /// LoadVector : Unextended load + /// + /// svfloat32_t svuzp2[_f32](svfloat32_t op1, svfloat32_t op2) + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// - /// svint8_t svld1[_s8](svbool_t pg, const int8_t *base) - /// LD1B Zresult.B, Pg/Z, [Xarray, Xindex] - /// LD1B Zresult.B, Pg/Z, [Xbase, #0, MUL VL] + /// svuint16_t svuzp2[_u16](svuint16_t op1, svuint16_t op2) + /// svbool_t svuzp2_b16(svbool_t op1, svbool_t op2) /// - public static unsafe Vector LoadVector(Vector mask, sbyte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// - /// svint16_t svld1[_s16](svbool_t pg, const int16_t *base) - /// LD1H Zresult.H, Pg/Z, [Xarray, Xindex, LSL #1] - /// LD1H Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// svuint32_t svuzp2[_u32](svuint32_t op1, svuint32_t op2) + /// svbool_t svuzp2_b32(svbool_t op1, svbool_t op2) /// - public static unsafe Vector LoadVector(Vector mask, short* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// - /// svint32_t svld1[_s32](svbool_t pg, const int32_t *base) - /// LD1W Zresult.S, Pg/Z, [Xarray, Xindex, LSL #2] - /// LD1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// svuint64_t svuzp2[_u64](svuint64_t op1, svuint64_t op2) + /// svbool_t svuzp2_b64(svbool_t op1, svbool_t op2) /// - public static unsafe Vector LoadVector(Vector mask, int* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector UnzipOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// Xor : Bitwise exclusive OR /// - /// svint64_t svld1[_s64](svbool_t pg, const int64_t *base) - /// LD1D Zresult.D, Pg/Z, [Xarray, Xindex, LSL #3] - /// LD1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// svuint8_t sveor[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t sveor[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t sveor[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// EOR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, long* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// - /// svuint8_t svld1[_u8](svbool_t pg, const uint8_t *base) - /// LD1B Zresult.B, Pg/Z, [Xarray, Xindex] - /// LD1B Zresult.B, Pg/Z, [Xbase, #0, MUL VL] + /// svint16_t sveor[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t sveor[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t sveor[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// EOR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, byte* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// - /// svuint16_t svld1[_u16](svbool_t pg, const uint16_t *base) - /// LD1H Zresult.H, Pg/Z, [Xarray, Xindex, LSL #1] - /// LD1H Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// svint32_t sveor[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t sveor[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t sveor[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// EOR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, ushort* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// - /// svuint32_t svld1[_u32](svbool_t pg, const uint32_t *base) - /// LD1W Zresult.S, Pg/Z, [Xarray, Xindex, LSL #2] - /// LD1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// svint64_t sveor[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t sveor[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t sveor[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// EOR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, uint* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// - /// svuint64_t svld1[_u64](svbool_t pg, const uint64_t *base) - /// LD1D Zresult.D, Pg/Z, [Xarray, Xindex, LSL #3] - /// LD1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// svint8_t sveor[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t sveor[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t sveor[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// EOR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, ulong* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// - /// svfloat32_t svld1[_f32](svbool_t pg, const float32_t *base) - /// LD1W Zresult.S, Pg/Z, [Xarray, Xindex, LSL #2] - /// LD1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// svuint16_t sveor[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t sveor[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t sveor[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// EOR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, float* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } /// - /// svfloat64_t svld1[_f64](svbool_t pg, const float64_t *base) - /// LD1D Zresult.D, Pg/Z, [Xarray, Xindex, LSL #3] - /// LD1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// svuint32_t sveor[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t sveor[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t sveor[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// EOR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, double* address) { throw new PlatformNotSupportedException(); } + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t sveor[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t sveor[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t sveor[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// EOR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Xor(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// XorAcross : Bitwise exclusive OR reduction to scalar + + /// + /// uint8_t sveorv[_u8](svbool_t pg, svuint8_t op) + /// EORV Bresult, Pg, Zop.B + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int16_t sveorv[_s16](svbool_t pg, svint16_t op) + /// EORV Hresult, Pg, Zop.H + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int32_t sveorv[_s32](svbool_t pg, svint32_t op) + /// EORV Sresult, Pg, Zop.S + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int64_t sveorv[_s64](svbool_t pg, svint64_t op) + /// EORV Dresult, Pg, Zop.D + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// int8_t sveorv[_s8](svbool_t pg, svint8_t op) + /// EORV Bresult, Pg, Zop.B + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint16_t sveorv[_u16](svbool_t pg, svuint16_t op) + /// EORV Hresult, Pg, Zop.H + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint32_t sveorv[_u32](svbool_t pg, svuint32_t op) + /// EORV Sresult, Pg, Zop.S + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// uint64_t sveorv[_u64](svbool_t pg, svuint64_t op) + /// EORV Dresult, Pg, Zop.D + /// + public static unsafe Vector XorAcross(Vector value) { throw new PlatformNotSupportedException(); } + + + /// ZeroExtend16 : Zero-extend the low 16 bits + + /// + /// svuint32_t svexth[_u32]_m(svuint32_t inactive, svbool_t pg, svuint32_t op) + /// UXTH Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; UXTH Zresult.S, Pg/M, Zop.S + /// svuint32_t svexth[_u32]_x(svbool_t pg, svuint32_t op) + /// UXTH Ztied.S, Pg/M, Ztied.S + /// AND Ztied.S, Ztied.S, #65535 + /// svuint32_t svexth[_u32]_z(svbool_t pg, svuint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; UXTH Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector ZeroExtend16(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svexth[_u64]_m(svuint64_t inactive, svbool_t pg, svuint64_t op) + /// UXTH Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; UXTH Zresult.D, Pg/M, Zop.D + /// svuint64_t svexth[_u64]_x(svbool_t pg, svuint64_t op) + /// UXTH Ztied.D, Pg/M, Ztied.D + /// AND Ztied.D, Ztied.D, #65535 + /// svuint64_t svexth[_u64]_z(svbool_t pg, svuint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; UXTH Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector ZeroExtend16(Vector value) { throw new PlatformNotSupportedException(); } + + + /// ZeroExtend32 : Zero-extend the low 32 bits + + /// + /// svuint64_t svextw[_u64]_m(svuint64_t inactive, svbool_t pg, svuint64_t op) + /// UXTW Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; UXTW Zresult.D, Pg/M, Zop.D + /// svuint64_t svextw[_u64]_x(svbool_t pg, svuint64_t op) + /// UXTW Ztied.D, Pg/M, Ztied.D + /// AND Ztied.D, Ztied.D, #4294967295 + /// svuint64_t svextw[_u64]_z(svbool_t pg, svuint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; UXTW Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector ZeroExtend32(Vector value) { throw new PlatformNotSupportedException(); } + + /// ZeroExtend8 : Zero-extend the low 8 bits + + /// + /// svuint16_t svextb[_u16]_m(svuint16_t inactive, svbool_t pg, svuint16_t op) + /// UXTB Ztied.H, Pg/M, Zop.H + /// MOVPRFX Zresult, Zinactive; UXTB Zresult.H, Pg/M, Zop.H + /// svuint16_t svextb[_u16]_x(svbool_t pg, svuint16_t op) + /// UXTB Ztied.H, Pg/M, Ztied.H + /// AND Ztied.H, Ztied.H, #255 + /// svuint16_t svextb[_u16]_z(svbool_t pg, svuint16_t op) + /// MOVPRFX Zresult.H, Pg/Z, Zop.H; UXTB Zresult.H, Pg/M, Zop.H + /// + public static unsafe Vector ZeroExtend8(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svextb[_u32]_m(svuint32_t inactive, svbool_t pg, svuint32_t op) + /// UXTB Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; UXTB Zresult.S, Pg/M, Zop.S + /// svuint32_t svextb[_u32]_x(svbool_t pg, svuint32_t op) + /// UXTB Ztied.S, Pg/M, Ztied.S + /// AND Ztied.S, Ztied.S, #255 + /// svuint32_t svextb[_u32]_z(svbool_t pg, svuint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; UXTB Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector ZeroExtend8(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svextb[_u64]_m(svuint64_t inactive, svbool_t pg, svuint64_t op) + /// UXTB Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; UXTB Zresult.D, Pg/M, Zop.D + /// svuint64_t svextb[_u64]_x(svbool_t pg, svuint64_t op) + /// UXTB Ztied.D, Pg/M, Ztied.D + /// AND Ztied.D, Ztied.D, #255 + /// svuint64_t svextb[_u64]_z(svbool_t pg, svuint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; UXTB Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector ZeroExtend8(Vector value) { throw new PlatformNotSupportedException(); } + + /// ZeroExtendWideningLower : Unpack and extend low half + + /// + /// svuint16_t svunpklo[_u16](svuint8_t op) + /// UUNPKLO Zresult.H, Zop.B + /// + public static unsafe Vector ZeroExtendWideningLower(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svunpklo[_u32](svuint16_t op) + /// UUNPKLO Zresult.S, Zop.H + /// + public static unsafe Vector ZeroExtendWideningLower(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svunpklo[_u64](svuint32_t op) + /// UUNPKLO Zresult.D, Zop.S + /// + public static unsafe Vector ZeroExtendWideningLower(Vector value) { throw new PlatformNotSupportedException(); } + + + /// ZeroExtendWideningUpper : Unpack and extend high half + + /// + /// svuint16_t svunpkhi[_u16](svuint8_t op) + /// UUNPKHI Zresult.H, Zop.B + /// + public static unsafe Vector ZeroExtendWideningUpper(Vector value) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svunpkhi[_u32](svuint16_t op) + /// UUNPKHI Zresult.S, Zop.H + /// + public static unsafe Vector ZeroExtendWideningUpper(Vector value) { throw new PlatformNotSupportedException(); } + /// + /// svuint64_t svunpkhi[_u64](svuint32_t op) + /// UUNPKHI Zresult.D, Zop.S + /// + public static unsafe Vector ZeroExtendWideningUpper(Vector value) { throw new PlatformNotSupportedException(); } + + /// ZipHigh : Interleave elements from high halves of two inputs + + /// + /// svuint8_t svzip2[_u8](svuint8_t op1, svuint8_t op2) + /// ZIP2 Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svzip2[_f64](svfloat64_t op1, svfloat64_t op2) + /// ZIP2 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svzip2[_s16](svint16_t op1, svint16_t op2) + /// ZIP2 Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svzip2[_s32](svint32_t op1, svint32_t op2) + /// ZIP2 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svzip2[_s64](svint64_t op1, svint64_t op2) + /// ZIP2 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svzip2[_s8](svint8_t op1, svint8_t op2) + /// ZIP2 Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svzip2[_f32](svfloat32_t op1, svfloat32_t op2) + /// ZIP2 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint16_t svzip2[_u16](svuint16_t op1, svuint16_t op2) + /// ZIP2 Zresult.H, Zop1.H, Zop2.H + /// svbool_t svzip2_b16(svbool_t op1, svbool_t op2) + /// ZIP2 Presult.H, Pop1.H, Pop2.H + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svzip2[_u32](svuint32_t op1, svuint32_t op2) + /// ZIP2 Zresult.S, Zop1.S, Zop2.S + /// svbool_t svzip2_b32(svbool_t op1, svbool_t op2) + /// ZIP2 Presult.S, Pop1.S, Pop2.S + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svzip2[_u64](svuint64_t op1, svuint64_t op2) + /// ZIP2 Zresult.D, Zop1.D, Zop2.D + /// svbool_t svzip2_b64(svbool_t op1, svbool_t op2) + /// ZIP2 Presult.D, Pop1.D, Pop2.D + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + + /// ZipLow : Interleave elements from low halves of two inputs + + /// + /// svuint8_t svzip1[_u8](svuint8_t op1, svuint8_t op2) + /// ZIP1 Zresult.B, Zop1.B, Zop2.B + /// svbool_t svzip1_b8(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.B, Pop1.B, Pop2.B + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat64_t svzip1[_f64](svfloat64_t op1, svfloat64_t op2) + /// ZIP1 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint16_t svzip1[_s16](svint16_t op1, svint16_t op2) + /// ZIP1 Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint32_t svzip1[_s32](svint32_t op1, svint32_t op2) + /// ZIP1 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint64_t svzip1[_s64](svint64_t op1, svint64_t op2) + /// ZIP1 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svint8_t svzip1[_s8](svint8_t op1, svint8_t op2) + /// ZIP1 Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svfloat32_t svzip1[_f32](svfloat32_t op1, svfloat32_t op2) + /// ZIP1 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + /// + /// svuint16_t svzip1[_u16](svuint16_t op1, svuint16_t op2) + /// ZIP1 Zresult.H, Zop1.H, Zop2.H + /// svbool_t svzip1_b16(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.H, Pop1.H, Pop2.H + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint32_t svzip1[_u32](svuint32_t op1, svuint32_t op2) + /// ZIP1 Zresult.S, Zop1.S, Zop2.S + /// svbool_t svzip1_b32(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.S, Pop1.S, Pop2.S + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + + /// + /// svuint64_t svzip1[_u64](svuint64_t op1, svuint64_t op2) + /// ZIP1 Zresult.D, Zop1.D, Zop2.D + /// svbool_t svzip1_b64(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.D, Pop1.D, Pop2.D + /// + public static unsafe Vector ZipLow(Vector left, Vector right) { throw new PlatformNotSupportedException(); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs index 6ba2a2c67bc8..b6c4be424c05 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs @@ -29,168 +29,3362 @@ internal Arm64() { } } + /// Abs : Absolute value + + /// + /// svint8_t svabs[_s8]_m(svint8_t inactive, svbool_t pg, svint8_t op) + /// ABS Ztied.B, Pg/M, Zop.B + /// MOVPRFX Zresult, Zinactive; ABS Zresult.B, Pg/M, Zop.B + /// svint8_t svabs[_s8]_x(svbool_t pg, svint8_t op) + /// ABS Ztied.B, Pg/M, Ztied.B + /// MOVPRFX Zresult, Zop; ABS Zresult.B, Pg/M, Zop.B + /// svint8_t svabs[_s8]_z(svbool_t pg, svint8_t op) + /// MOVPRFX Zresult.B, Pg/Z, Zop.B; ABS Zresult.B, Pg/M, Zop.B + /// + public static unsafe Vector Abs(Vector value) => Abs(value); + + /// + /// svint16_t svabs[_s16]_m(svint16_t inactive, svbool_t pg, svint16_t op) + /// ABS Ztied.H, Pg/M, Zop.H + /// MOVPRFX Zresult, Zinactive; ABS Zresult.H, Pg/M, Zop.H + /// svint16_t svabs[_s16]_x(svbool_t pg, svint16_t op) + /// ABS Ztied.H, Pg/M, Ztied.H + /// MOVPRFX Zresult, Zop; ABS Zresult.H, Pg/M, Zop.H + /// svint16_t svabs[_s16]_z(svbool_t pg, svint16_t op) + /// MOVPRFX Zresult.H, Pg/Z, Zop.H; ABS Zresult.H, Pg/M, Zop.H + /// + public static unsafe Vector Abs(Vector value) => Abs(value); + + /// + /// svint32_t svabs[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// ABS Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; ABS Zresult.S, Pg/M, Zop.S + /// svint32_t svabs[_s32]_x(svbool_t pg, svint32_t op) + /// ABS Ztied.S, Pg/M, Ztied.S + /// MOVPRFX Zresult, Zop; ABS Zresult.S, Pg/M, Zop.S + /// svint32_t svabs[_s32]_z(svbool_t pg, svint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; ABS Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector Abs(Vector value) => Abs(value); + + /// + /// svint64_t svabs[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// ABS Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; ABS Zresult.D, Pg/M, Zop.D + /// svint64_t svabs[_s64]_x(svbool_t pg, svint64_t op) + /// ABS Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; ABS Zresult.D, Pg/M, Zop.D + /// svint64_t svabs[_s64]_z(svbool_t pg, svint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; ABS Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector Abs(Vector value) => Abs(value); + + /// + /// svfloat32_t svabs[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op) + /// FABS Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; FABS Zresult.S, Pg/M, Zop.S + /// svfloat32_t svabs[_f32]_x(svbool_t pg, svfloat32_t op) + /// FABS Ztied.S, Pg/M, Ztied.S + /// MOVPRFX Zresult, Zop; FABS Zresult.S, Pg/M, Zop.S + /// svfloat32_t svabs[_f32]_z(svbool_t pg, svfloat32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; FABS Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector Abs(Vector value) => Abs(value); + + /// + /// svfloat64_t svabs[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op) + /// FABS Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; FABS Zresult.D, Pg/M, Zop.D + /// svfloat64_t svabs[_f64]_x(svbool_t pg, svfloat64_t op) + /// FABS Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; FABS Zresult.D, Pg/M, Zop.D + /// svfloat64_t svabs[_f64]_z(svbool_t pg, svfloat64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; FABS Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector Abs(Vector value) => Abs(value); + + /// AbsoluteDifference : Absolute difference + + /// + /// svuint8_t svabd[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svabd[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; UABD Zresult.B, Pg/M, Zresult.B, Zop2.B + /// UABD Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) => AbsoluteDifference(left, right); + + /// + /// svfloat64_t svabd[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svabd[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svabd[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FABD Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) => AbsoluteDifference(left, right); + + /// + /// svint16_t svabd[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svabd[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svabd[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// SABD Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) => AbsoluteDifference(left, right); + + /// + /// svint32_t svabd[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svabd[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svabd[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// SABD Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) => AbsoluteDifference(left, right); + + /// + /// svint64_t svabd[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svabd[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svabd[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// SABD Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) => AbsoluteDifference(left, right); + + /// + /// svint8_t svabd[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svabd[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svabd[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// SABD Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) => AbsoluteDifference(left, right); + + /// + /// svfloat32_t svabd[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svabd[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svabd[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FABD Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) => AbsoluteDifference(left, right); + + /// + /// svuint16_t svabd[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svabd[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svabd[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// UABD Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) => AbsoluteDifference(left, right); + + /// + /// svuint32_t svabd[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svabd[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svabd[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// UABD Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) => AbsoluteDifference(left, right); + + /// + /// svuint64_t svabd[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svabd[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svabd[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// UABD Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// + public static unsafe Vector AbsoluteDifference(Vector left, Vector right) => AbsoluteDifference(left, right); + + /// Add : Add + + /// + /// svint8_t svadd[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svadd[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svadd[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svint16_t svadd[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svadd[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svadd[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svint32_t svadd[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svadd[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svadd[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svint64_t svadd[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svadd[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svadd[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svuint8_t svadd[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svadd[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svadd[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svuint16_t svadd[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svadd[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svadd[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svuint32_t svadd[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svadd[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svadd[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svuint64_t svadd[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svadd[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svadd[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svfloat32_t svadd[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svadd[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svadd[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + /// + /// svfloat64_t svadd[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svadd[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svadd[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// + public static unsafe Vector Add(Vector left, Vector right) => Add(left, right); + + + /// AddAcross : Add reduction + + /// + /// float64_t svaddv[_f64](svbool_t pg, svfloat64_t op) + /// FADDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// int64_t svaddv[_s16](svbool_t pg, svint16_t op) + /// SADDV Dresult, Pg, Zop.H + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// int64_t svaddv[_s32](svbool_t pg, svint32_t op) + /// SADDV Dresult, Pg, Zop.S + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// int64_t svaddv[_s8](svbool_t pg, svint8_t op) + /// SADDV Dresult, Pg, Zop.B + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// int64_t svaddv[_s64](svbool_t pg, svint64_t op) + /// UADDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// float32_t svaddv[_f32](svbool_t pg, svfloat32_t op) + /// FADDV Sresult, Pg, Zop.S + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// uint64_t svaddv[_u8](svbool_t pg, svuint8_t op) + /// UADDV Dresult, Pg, Zop.B + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// uint64_t svaddv[_u16](svbool_t pg, svuint16_t op) + /// UADDV Dresult, Pg, Zop.H + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// uint64_t svaddv[_u32](svbool_t pg, svuint32_t op) + /// UADDV Dresult, Pg, Zop.S + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// + /// uint64_t svaddv[_u64](svbool_t pg, svuint64_t op) + /// UADDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AddAcross(Vector value) => AddAcross(value); + + /// AddSaturate : Saturating add + + /// + /// svuint8_t svqadd[_u8](svuint8_t op1, svuint8_t op2) + /// UQADD Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) => AddSaturate(left, right); + + /// + /// svint16_t svqadd[_s16](svint16_t op1, svint16_t op2) + /// SQADD Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) => AddSaturate(left, right); + + /// + /// svint32_t svqadd[_s32](svint32_t op1, svint32_t op2) + /// SQADD Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) => AddSaturate(left, right); + + /// + /// svint64_t svqadd[_s64](svint64_t op1, svint64_t op2) + /// SQADD Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) => AddSaturate(left, right); + + /// + /// svint8_t svqadd[_s8](svint8_t op1, svint8_t op2) + /// SQADD Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) => AddSaturate(left, right); + + /// + /// svuint16_t svqadd[_u16](svuint16_t op1, svuint16_t op2) + /// UQADD Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) => AddSaturate(left, right); + + /// + /// svuint32_t svqadd[_u32](svuint32_t op1, svuint32_t op2) + /// UQADD Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) => AddSaturate(left, right); + + /// + /// svuint64_t svqadd[_u64](svuint64_t op1, svuint64_t op2) + /// UQADD Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector AddSaturate(Vector left, Vector right) => AddSaturate(left, right); + + /// And : Bitwise AND + + /// + /// svuint8_t svand[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svand[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svand[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// AND Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + /// + /// svint16_t svand[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svand[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svand[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// AND Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + /// + /// svint32_t svand[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svand[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svand[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// AND Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + /// + /// svint64_t svand[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svand[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svand[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// AND Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + /// + /// svint8_t svand[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svand[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svand[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// AND Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + /// + /// svuint16_t svand[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svand[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svand[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// AND Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + /// + /// svuint32_t svand[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svand[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svand[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// AND Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + /// + /// svuint64_t svand[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svand[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svand[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// AND Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// AND Zresult.D, Zop1.D, Zop2.D + /// svbool_t svand[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// AND Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector And(Vector left, Vector right) => And(left, right); + + + /// AndAcross : Bitwise AND reduction to scalar + + /// + /// uint8_t svandv[_u8](svbool_t pg, svuint8_t op) + /// ANDV Bresult, Pg, Zop.B + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// + /// int16_t svandv[_s16](svbool_t pg, svint16_t op) + /// ANDV Hresult, Pg, Zop.H + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// + /// int32_t svandv[_s32](svbool_t pg, svint32_t op) + /// ANDV Sresult, Pg, Zop.S + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// + /// int64_t svandv[_s64](svbool_t pg, svint64_t op) + /// ANDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// + /// int8_t svandv[_s8](svbool_t pg, svint8_t op) + /// ANDV Bresult, Pg, Zop.B + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// + /// uint16_t svandv[_u16](svbool_t pg, svuint16_t op) + /// ANDV Hresult, Pg, Zop.H + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// + /// uint32_t svandv[_u32](svbool_t pg, svuint32_t op) + /// ANDV Sresult, Pg, Zop.S + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + /// + /// uint64_t svandv[_u64](svbool_t pg, svuint64_t op) + /// ANDV Dresult, Pg, Zop.D + /// + public static unsafe Vector AndAcross(Vector value) => AndAcross(value); + + + /// BitwiseClear : Bitwise clear + + /// + /// svuint8_t svbic[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svbic[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svbic[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// BIC Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) => BitwiseClear(left, right); + + /// + /// svint16_t svbic[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svbic[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svbic[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// BIC Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) => BitwiseClear(left, right); + + /// + /// svint32_t svbic[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svbic[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svbic[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// BIC Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) => BitwiseClear(left, right); + + /// + /// svint64_t svbic[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svbic[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svbic[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// BIC Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) => BitwiseClear(left, right); + + /// + /// svint8_t svbic[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svbic[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svbic[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// BIC Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) => BitwiseClear(left, right); + + /// + /// svuint16_t svbic[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svbic[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svbic[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// BIC Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) => BitwiseClear(left, right); + + /// + /// svuint32_t svbic[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svbic[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svbic[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// BIC Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) => BitwiseClear(left, right); + + /// + /// svuint64_t svbic[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svbic[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svbic[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// BIC Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// BIC Zresult.D, Zop1.D, Zop2.D + /// svbool_t svbic[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// BIC Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector BitwiseClear(Vector left, Vector right) => BitwiseClear(left, right); + + + /// BooleanNot : Logically invert boolean condition + + /// + /// svuint8_t svcnot[_u8]_m(svuint8_t inactive, svbool_t pg, svuint8_t op) + /// svuint8_t svcnot[_u8]_x(svbool_t pg, svuint8_t op) + /// svuint8_t svcnot[_u8]_z(svbool_t pg, svuint8_t op) + /// CNOT Ztied.B, Pg/M, Zop.B + /// + public static unsafe Vector BooleanNot(Vector value) => BooleanNot(value); + + /// + /// svint16_t svcnot[_s16]_m(svint16_t inactive, svbool_t pg, svint16_t op) + /// svint16_t svcnot[_s16]_x(svbool_t pg, svint16_t op) + /// svint16_t svcnot[_s16]_z(svbool_t pg, svint16_t op) + /// CNOT Ztied.H, Pg/M, Zop.H + /// + public static unsafe Vector BooleanNot(Vector value) => BooleanNot(value); + + /// + /// svint32_t svcnot[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// svint32_t svcnot[_s32]_x(svbool_t pg, svint32_t op) + /// svint32_t svcnot[_s32]_z(svbool_t pg, svint32_t op) + /// CNOT Ztied.S, Pg/M, Zop.S + /// + public static unsafe Vector BooleanNot(Vector value) => BooleanNot(value); + + /// + /// svint64_t svcnot[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// svint64_t svcnot[_s64]_x(svbool_t pg, svint64_t op) + /// svint64_t svcnot[_s64]_z(svbool_t pg, svint64_t op) + /// CNOT Ztied.D, Pg/M, Zop.D + /// + public static unsafe Vector BooleanNot(Vector value) => BooleanNot(value); + + /// + /// svint8_t svcnot[_s8]_m(svint8_t inactive, svbool_t pg, svint8_t op) + /// svint8_t svcnot[_s8]_x(svbool_t pg, svint8_t op) + /// svint8_t svcnot[_s8]_z(svbool_t pg, svint8_t op) + /// CNOT Ztied.B, Pg/M, Zop.B + /// + public static unsafe Vector BooleanNot(Vector value) => BooleanNot(value); + + /// + /// svuint16_t svcnot[_u16]_m(svuint16_t inactive, svbool_t pg, svuint16_t op) + /// svuint16_t svcnot[_u16]_x(svbool_t pg, svuint16_t op) + /// svuint16_t svcnot[_u16]_z(svbool_t pg, svuint16_t op) + /// CNOT Ztied.H, Pg/M, Zop.H + /// + public static unsafe Vector BooleanNot(Vector value) => BooleanNot(value); + + /// + /// svuint32_t svcnot[_u32]_m(svuint32_t inactive, svbool_t pg, svuint32_t op) + /// svuint32_t svcnot[_u32]_x(svbool_t pg, svuint32_t op) + /// svuint32_t svcnot[_u32]_z(svbool_t pg, svuint32_t op) + /// CNOT Ztied.S, Pg/M, Zop.S + /// + public static unsafe Vector BooleanNot(Vector value) => BooleanNot(value); + + /// + /// svuint64_t svcnot[_u64]_m(svuint64_t inactive, svbool_t pg, svuint64_t op) + /// svuint64_t svcnot[_u64]_x(svbool_t pg, svuint64_t op) + /// svuint64_t svcnot[_u64]_z(svbool_t pg, svuint64_t op) + /// CNOT Ztied.D, Pg/M, Zop.D + /// + public static unsafe Vector BooleanNot(Vector value) => BooleanNot(value); + + + /// ConditionalSelect : Conditionally select elements + + /// + /// svint8_t svsel[_s8](svbool_t pg, svint8_t op1, svint8_t op2) + /// SEL Zresult.B, Pg, Zop1.B, Zop2.B + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svint16_t svsel[_s16](svbool_t pg, svint16_t op1, svint16_t op2) + /// SEL Zresult.H, Pg, Zop1.H, Zop2.H + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svint32_t svsel[_s32](svbool_t pg, svint32_t op1, svint32_t op2) + /// SEL Zresult.S, Pg, Zop1.S, Zop2.S + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svint64_t svsel[_s64](svbool_t pg, svint64_t op1, svint64_t op2) + /// SEL Zresult.D, Pg, Zop1.D, Zop2.D + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svuint8_t svsel[_u8](svbool_t pg, svuint8_t op1, svuint8_t op2) + /// SEL Zresult.B, Pg, Zop1.B, Zop2.B + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svuint16_t svsel[_u16](svbool_t pg, svuint16_t op1, svuint16_t op2) + /// SEL Zresult.H, Pg, Zop1.H, Zop2.H + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svuint32_t svsel[_u32](svbool_t pg, svuint32_t op1, svuint32_t op2) + /// SEL Zresult.S, Pg, Zop1.S, Zop2.S + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svuint64_t svsel[_u64](svbool_t pg, svuint64_t op1, svuint64_t op2) + /// SEL Zresult.D, Pg, Zop1.D, Zop2.D + /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2) + /// SEL Presult.B, Pg, Pop1.B, Pop2.B + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svfloat32_t svsel[_f32](svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// SEL Zresult.S, Pg, Zop1.S, Zop2.S + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + /// + /// svfloat64_t svsel[_f64](svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// SEL Zresult.D, Pg, Zop1.D, Zop2.D + /// + /// + public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right); + + + /// Count16BitElements : Count the number of 16-bit elements in a vector + + /// + /// uint64_t svcnth_pat(enum svpattern pattern) + /// CNTH Xresult, pattern + /// + public static unsafe ulong Count16BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => Count16BitElements(pattern); + + + /// Count32BitElements : Count the number of 32-bit elements in a vector + + /// + /// uint64_t svcntw_pat(enum svpattern pattern) + /// CNTW Xresult, pattern + /// + public static unsafe ulong Count32BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => Count32BitElements(pattern); + + + /// Count64BitElements : Count the number of 64-bit elements in a vector + + /// + /// uint64_t svcntd_pat(enum svpattern pattern) + /// CNTD Xresult, pattern + /// + public static unsafe ulong Count64BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => Count64BitElements(pattern); + + + /// Count8BitElements : Count the number of 8-bit elements in a vector + + /// + /// uint64_t svcntb_pat(enum svpattern pattern) + /// CNTB Xresult, pattern + /// + public static unsafe ulong Count8BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => Count8BitElements(pattern); + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskByte() => CreateFalseMaskByte(); + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskDouble() => CreateFalseMaskDouble(); + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskInt16() => CreateFalseMaskInt16(); + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskInt32() => CreateFalseMaskInt32(); + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskInt64() => CreateFalseMaskInt64(); + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskSByte() => CreateFalseMaskSByte(); + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskSingle() => CreateFalseMaskSingle(); + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskUInt16() => CreateFalseMaskUInt16(); + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskUInt32() => CreateFalseMaskUInt32(); + + + /// Set all predicate elements to false + + /// + /// svbool_t svpfalse[_b]() + /// PFALSE Presult.B + /// + public static unsafe Vector CreateFalseMaskUInt64() => CreateFalseMaskUInt64(); + + /// CreateTrueMaskByte : Set predicate elements to true /// - /// svbool_t svptrue_pat_b8(enum svpattern pattern) - /// PTRUE Presult.B, pattern + /// svbool_t svptrue_pat_b8(enum svpattern pattern) + /// PTRUE Presult.B, pattern + /// + public static unsafe Vector CreateTrueMaskByte([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskByte(pattern); + + + /// CreateTrueMaskDouble : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b8(enum svpattern pattern) + /// PTRUE Presult.B, pattern + /// + public static unsafe Vector CreateTrueMaskDouble([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskDouble(pattern); + + + /// CreateTrueMaskInt16 : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b8(enum svpattern pattern) + /// PTRUE Presult.B, pattern + /// + public static unsafe Vector CreateTrueMaskInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskInt16(pattern); + + + /// CreateTrueMaskInt32 : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b8(enum svpattern pattern) + /// PTRUE Presult.B, pattern + /// + public static unsafe Vector CreateTrueMaskInt32([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskInt32(pattern); + + + /// CreateTrueMaskInt64 : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b8(enum svpattern pattern) + /// PTRUE Presult.B, pattern + /// + public static unsafe Vector CreateTrueMaskInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskInt64(pattern); + + + /// CreateTrueMaskSByte : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b8(enum svpattern pattern) + /// PTRUE Presult.B, pattern + /// + public static unsafe Vector CreateTrueMaskSByte([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskSByte(pattern); + + + /// CreateTrueMaskSingle : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b8(enum svpattern pattern) + /// PTRUE Presult.B, pattern + /// + public static unsafe Vector CreateTrueMaskSingle([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskSingle(pattern); + + + /// CreateTrueMaskUInt16 : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b16(enum svpattern pattern) + /// PTRUE Presult.H, pattern + /// + public static unsafe Vector CreateTrueMaskUInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskUInt16(pattern); + + + /// CreateTrueMaskUInt32 : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b32(enum svpattern pattern) + /// PTRUE Presult.S, pattern + /// + public static unsafe Vector CreateTrueMaskUInt32([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskUInt32(pattern); + + + /// CreateTrueMaskUInt64 : Set predicate elements to true + + /// + /// svbool_t svptrue_pat_b64(enum svpattern pattern) + /// PTRUE Presult.D, pattern + /// + public static unsafe Vector CreateTrueMaskUInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskUInt64(pattern); + + + /// CreateWhileLessThanMask16Bit : While incrementing scalar is less than + + /// + /// svbool_t svwhilelt_b16[_s32](int32_t op1, int32_t op2) + /// WHILELT Presult.H, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask16Bit(int left, int right) => CreateWhileLessThanMask16Bit(left, right); + + /// + /// svbool_t svwhilelt_b16[_s64](int64_t op1, int64_t op2) + /// WHILELT Presult.H, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask16Bit(long left, long right) => CreateWhileLessThanMask16Bit(left, right); + + /// + /// svbool_t svwhilelt_b16[_u32](uint32_t op1, uint32_t op2) + /// WHILELO Presult.H, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask16Bit(uint left, uint right) => CreateWhileLessThanMask16Bit(left, right); + + /// + /// svbool_t svwhilelt_b16[_u64](uint64_t op1, uint64_t op2) + /// WHILELO Presult.H, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask16Bit(ulong left, ulong right) => CreateWhileLessThanMask16Bit(left, right); + + + /// CreateWhileLessThanMask32Bit : While incrementing scalar is less than + + /// + /// svbool_t svwhilelt_b32[_s32](int32_t op1, int32_t op2) + /// WHILELT Presult.S, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask32Bit(int left, int right) => CreateWhileLessThanMask32Bit(left, right); + + /// + /// svbool_t svwhilelt_b32[_s64](int64_t op1, int64_t op2) + /// WHILELT Presult.S, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask32Bit(long left, long right) => CreateWhileLessThanMask32Bit(left, right); + + /// + /// svbool_t svwhilelt_b32[_u32](uint32_t op1, uint32_t op2) + /// WHILELO Presult.S, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask32Bit(uint left, uint right) => CreateWhileLessThanMask32Bit(left, right); + + /// + /// svbool_t svwhilelt_b32[_u64](uint64_t op1, uint64_t op2) + /// WHILELO Presult.S, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask32Bit(ulong left, ulong right) => CreateWhileLessThanMask32Bit(left, right); + + + /// CreateWhileLessThanMask64Bit : While incrementing scalar is less than + + /// + /// svbool_t svwhilelt_b64[_s32](int32_t op1, int32_t op2) + /// WHILELT Presult.D, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask64Bit(int left, int right) => CreateWhileLessThanMask64Bit(left, right); + + /// + /// svbool_t svwhilelt_b64[_s64](int64_t op1, int64_t op2) + /// WHILELT Presult.D, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask64Bit(long left, long right) => CreateWhileLessThanMask64Bit(left, right); + + /// + /// svbool_t svwhilelt_b64[_u32](uint32_t op1, uint32_t op2) + /// WHILELO Presult.D, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask64Bit(uint left, uint right) => CreateWhileLessThanMask64Bit(left, right); + + /// + /// svbool_t svwhilelt_b64[_u64](uint64_t op1, uint64_t op2) + /// WHILELO Presult.D, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask64Bit(ulong left, ulong right) => CreateWhileLessThanMask64Bit(left, right); + + + /// CreateWhileLessThanMask8Bit : While incrementing scalar is less than + + /// + /// svbool_t svwhilelt_b8[_s32](int32_t op1, int32_t op2) + /// WHILELT Presult.B, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask8Bit(int left, int right) => CreateWhileLessThanMask8Bit(left, right); + + /// + /// svbool_t svwhilelt_b8[_s64](int64_t op1, int64_t op2) + /// WHILELT Presult.B, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask8Bit(long left, long right) => CreateWhileLessThanMask8Bit(left, right); + + /// + /// svbool_t svwhilelt_b8[_u32](uint32_t op1, uint32_t op2) + /// WHILELO Presult.B, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanMask8Bit(uint left, uint right) => CreateWhileLessThanMask8Bit(left, right); + + /// + /// svbool_t svwhilelt_b8[_u64](uint64_t op1, uint64_t op2) + /// WHILELO Presult.B, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanMask8Bit(ulong left, ulong right) => CreateWhileLessThanMask8Bit(left, right); + + + /// CreateWhileLessThanOrEqualMask16Bit : While incrementing scalar is less than or equal to + + /// + /// svbool_t svwhilele_b16[_s32](int32_t op1, int32_t op2) + /// WHILELE Presult.H, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask16Bit(int left, int right) => CreateWhileLessThanOrEqualMask16Bit(left, right); + + /// + /// svbool_t svwhilele_b16[_s64](int64_t op1, int64_t op2) + /// WHILELE Presult.H, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask16Bit(long left, long right) => CreateWhileLessThanOrEqualMask16Bit(left, right); + + /// + /// svbool_t svwhilele_b16[_u32](uint32_t op1, uint32_t op2) + /// WHILELS Presult.H, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask16Bit(uint left, uint right) => CreateWhileLessThanOrEqualMask16Bit(left, right); + + /// + /// svbool_t svwhilele_b16[_u64](uint64_t op1, uint64_t op2) + /// WHILELS Presult.H, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask16Bit(ulong left, ulong right) => CreateWhileLessThanOrEqualMask16Bit(left, right); + + + /// CreateWhileLessThanOrEqualMask32Bit : While incrementing scalar is less than or equal to + + /// + /// svbool_t svwhilele_b32[_s32](int32_t op1, int32_t op2) + /// WHILELE Presult.S, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask32Bit(int left, int right) => CreateWhileLessThanOrEqualMask32Bit(left, right); + + /// + /// svbool_t svwhilele_b32[_s64](int64_t op1, int64_t op2) + /// WHILELE Presult.S, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask32Bit(long left, long right) => CreateWhileLessThanOrEqualMask32Bit(left, right); + + /// + /// svbool_t svwhilele_b32[_u32](uint32_t op1, uint32_t op2) + /// WHILELS Presult.S, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask32Bit(uint left, uint right) => CreateWhileLessThanOrEqualMask32Bit(left, right); + + /// + /// svbool_t svwhilele_b32[_u64](uint64_t op1, uint64_t op2) + /// WHILELS Presult.S, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask32Bit(ulong left, ulong right) => CreateWhileLessThanOrEqualMask32Bit(left, right); + + + /// CreateWhileLessThanOrEqualMask64Bit : While incrementing scalar is less than or equal to + + /// + /// svbool_t svwhilele_b64[_s32](int32_t op1, int32_t op2) + /// WHILELE Presult.D, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask64Bit(int left, int right) => CreateWhileLessThanOrEqualMask64Bit(left, right); + + /// + /// svbool_t svwhilele_b64[_s64](int64_t op1, int64_t op2) + /// WHILELE Presult.D, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask64Bit(long left, long right) => CreateWhileLessThanOrEqualMask64Bit(left, right); + + /// + /// svbool_t svwhilele_b64[_u32](uint32_t op1, uint32_t op2) + /// WHILELS Presult.D, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask64Bit(uint left, uint right) => CreateWhileLessThanOrEqualMask64Bit(left, right); + + /// + /// svbool_t svwhilele_b64[_u64](uint64_t op1, uint64_t op2) + /// WHILELS Presult.D, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask64Bit(ulong left, ulong right) => CreateWhileLessThanOrEqualMask64Bit(left, right); + + + /// CreateWhileLessThanOrEqualMask8Bit : While incrementing scalar is less than or equal to + + /// + /// svbool_t svwhilele_b8[_s32](int32_t op1, int32_t op2) + /// WHILELE Presult.B, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask8Bit(int left, int right) => CreateWhileLessThanOrEqualMask8Bit(left, right); + + /// + /// svbool_t svwhilele_b8[_s64](int64_t op1, int64_t op2) + /// WHILELE Presult.B, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask8Bit(long left, long right) => CreateWhileLessThanOrEqualMask8Bit(left, right); + + /// + /// svbool_t svwhilele_b8[_u32](uint32_t op1, uint32_t op2) + /// WHILELS Presult.B, Wop1, Wop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask8Bit(uint left, uint right) => CreateWhileLessThanOrEqualMask8Bit(left, right); + + /// + /// svbool_t svwhilele_b8[_u64](uint64_t op1, uint64_t op2) + /// WHILELS Presult.B, Xop1, Xop2 + /// + public static unsafe Vector CreateWhileLessThanOrEqualMask8Bit(ulong left, ulong right) => CreateWhileLessThanOrEqualMask8Bit(left, right); + + + /// Divide : Divide + + /// + /// svfloat32_t svdiv[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FDIV Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FDIV Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svdiv[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FDIV Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FDIV Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svdiv[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; FDIV Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Divide(Vector left, Vector right) => Divide(left, right); + + /// + /// svfloat64_t svdiv[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FDIV Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FDIV Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svdiv[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FDIV Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FDIV Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svdiv[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; FDIV Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Divide(Vector left, Vector right) => Divide(left, right); + + /// DotProduct : Dot product + + /// + /// svint32_t svdot[_s32](svint32_t op1, svint8_t op2, svint8_t op3) + /// SDOT Ztied1.S, Zop2.B, Zop3.B + /// + public static unsafe Vector DotProduct(Vector addend, Vector left, Vector right) => DotProduct(addend, left, right); + + /// + /// svint64_t svdot[_s64](svint64_t op1, svint16_t op2, svint16_t op3) + /// SDOT Ztied1.D, Zop2.H, Zop3.H + /// + public static unsafe Vector DotProduct(Vector addend, Vector left, Vector right) => DotProduct(addend, left, right); + + /// + /// svuint32_t svdot[_u32](svuint32_t op1, svuint8_t op2, svuint8_t op3) + /// UDOT Ztied1.S, Zop2.B, Zop3.B + /// + public static unsafe Vector DotProduct(Vector addend, Vector left, Vector right) => DotProduct(addend, left, right); + + /// + /// svuint64_t svdot[_u64](svuint64_t op1, svuint16_t op2, svuint16_t op3) + /// UDOT Ztied1.D, Zop2.H, Zop3.H + /// + public static unsafe Vector DotProduct(Vector addend, Vector left, Vector right) => DotProduct(addend, left, right); + + + /// DotProductBySelectedScalar : Dot product + + /// + /// svint32_t svdot_lane[_s32](svint32_t op1, svint8_t op2, svint8_t op3, uint64_t imm_index) + /// SDOT Ztied1.S, Zop2.B, Zop3.B[imm_index] + /// + public static unsafe Vector DotProductBySelectedScalar(Vector addend, Vector left, Vector right, [ConstantExpected] byte rightIndex) => DotProductBySelectedScalar(addend, left, right, rightIndex); + + /// + /// svint64_t svdot_lane[_s64](svint64_t op1, svint16_t op2, svint16_t op3, uint64_t imm_index) + /// SDOT Ztied1.D, Zop2.H, Zop3.H[imm_index] + /// + public static unsafe Vector DotProductBySelectedScalar(Vector addend, Vector left, Vector right, [ConstantExpected] byte rightIndex) => DotProductBySelectedScalar(addend, left, right, rightIndex); + + /// + /// svuint32_t svdot_lane[_u32](svuint32_t op1, svuint8_t op2, svuint8_t op3, uint64_t imm_index) + /// UDOT Ztied1.S, Zop2.B, Zop3.B[imm_index] + /// + public static unsafe Vector DotProductBySelectedScalar(Vector addend, Vector left, Vector right, [ConstantExpected] byte rightIndex) => DotProductBySelectedScalar(addend, left, right, rightIndex); + + /// + /// svuint64_t svdot_lane[_u64](svuint64_t op1, svuint16_t op2, svuint16_t op3, uint64_t imm_index) + /// UDOT Ztied1.D, Zop2.H, Zop3.H[imm_index] + /// + public static unsafe Vector DotProductBySelectedScalar(Vector addend, Vector left, Vector right, [ConstantExpected] byte rightIndex) => DotProductBySelectedScalar(addend, left, right, rightIndex); + + /// FusedMultiplyAdd : Multiply-add, addend first + + /// + /// svfloat64_t svmla[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svmla[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svmla[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// FMLA Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector FusedMultiplyAdd(Vector addend, Vector left, Vector right) => FusedMultiplyAdd(addend, left, right); + + /// + /// svfloat32_t svmla[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svmla[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svmla[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// FMLA Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector FusedMultiplyAdd(Vector addend, Vector left, Vector right) => FusedMultiplyAdd(addend, left, right); + + + /// FusedMultiplyAddBySelectedScalar : Multiply-add, addend first + + /// + /// svfloat64_t svmla_lane[_f64](svfloat64_t op1, svfloat64_t op2, svfloat64_t op3, uint64_t imm_index) + /// FMLA Ztied1.D, Zop2.D, Zop3.D[imm_index] + /// + public static unsafe Vector FusedMultiplyAddBySelectedScalar(Vector addend, Vector left, Vector right, [ConstantExpected] byte rightIndex) => FusedMultiplyAddBySelectedScalar(addend, left, right, rightIndex); + + /// + /// svfloat32_t svmla_lane[_f32](svfloat32_t op1, svfloat32_t op2, svfloat32_t op3, uint64_t imm_index) + /// FMLA Ztied1.S, Zop2.S, Zop3.S[imm_index] + /// + public static unsafe Vector FusedMultiplyAddBySelectedScalar(Vector addend, Vector left, Vector right, [ConstantExpected] byte rightIndex) => FusedMultiplyAddBySelectedScalar(addend, left, right, rightIndex); + + + /// FusedMultiplyAddNegated : Negated multiply-add, addend first + + /// + /// svfloat64_t svnmla[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svnmla[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svnmla[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// FNMLA Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector FusedMultiplyAddNegated(Vector addend, Vector left, Vector right) => FusedMultiplyAddNegated(addend, left, right); + + /// + /// svfloat32_t svnmla[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svnmla[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svnmla[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// FNMLA Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector FusedMultiplyAddNegated(Vector addend, Vector left, Vector right) => FusedMultiplyAddNegated(addend, left, right); + + + /// FusedMultiplySubtract : Multiply-subtract, minuend first + + /// + /// svfloat64_t svmls[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svmls[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svmls[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// FMLS Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector FusedMultiplySubtract(Vector minuend, Vector left, Vector right) => FusedMultiplySubtract(minuend, left, right); + + /// + /// svfloat32_t svmls[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svmls[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svmls[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// FMLS Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector FusedMultiplySubtract(Vector minuend, Vector left, Vector right) => FusedMultiplySubtract(minuend, left, right); + + + /// FusedMultiplySubtractBySelectedScalar : Multiply-subtract, minuend first + + /// + /// svfloat64_t svmls_lane[_f64](svfloat64_t op1, svfloat64_t op2, svfloat64_t op3, uint64_t imm_index) + /// FMLS Ztied1.D, Zop2.D, Zop3.D[imm_index] + /// + public static unsafe Vector FusedMultiplySubtractBySelectedScalar(Vector minuend, Vector left, Vector right, [ConstantExpected] byte rightIndex) => FusedMultiplySubtractBySelectedScalar(minuend, left, right, rightIndex); + + /// + /// svfloat32_t svmls_lane[_f32](svfloat32_t op1, svfloat32_t op2, svfloat32_t op3, uint64_t imm_index) + /// FMLS Ztied1.S, Zop2.S, Zop3.S[imm_index] + /// + public static unsafe Vector FusedMultiplySubtractBySelectedScalar(Vector minuend, Vector left, Vector right, [ConstantExpected] byte rightIndex) => FusedMultiplySubtractBySelectedScalar(minuend, left, right, rightIndex); + + + /// FusedMultiplySubtractNegated : Negated multiply-subtract, minuend first + + /// + /// svfloat64_t svnmls[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svnmls[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// svfloat64_t svnmls[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3) + /// FNMLS Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector FusedMultiplySubtractNegated(Vector minuend, Vector left, Vector right) => FusedMultiplySubtractNegated(minuend, left, right); + + /// + /// svfloat32_t svnmls[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svnmls[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// svfloat32_t svnmls[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3) + /// FNMLS Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector FusedMultiplySubtractNegated(Vector minuend, Vector left, Vector right) => FusedMultiplySubtractNegated(minuend, left, right); + + /// LoadVector : Unextended load + + /// + /// svint8_t svld1[_s8](svbool_t pg, const int8_t *base) + /// LD1B Zresult.B, Pg/Z, [Xarray, Xindex] + /// LD1B Zresult.B, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, sbyte* address) => LoadVector(mask, address); + + /// + /// svint16_t svld1[_s16](svbool_t pg, const int16_t *base) + /// LD1H Zresult.H, Pg/Z, [Xarray, Xindex, LSL #1] + /// LD1H Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, short* address) => LoadVector(mask, address); + + /// + /// svint32_t svld1[_s32](svbool_t pg, const int32_t *base) + /// LD1W Zresult.S, Pg/Z, [Xarray, Xindex, LSL #2] + /// LD1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, int* address) => LoadVector(mask, address); + + /// + /// svint64_t svld1[_s64](svbool_t pg, const int64_t *base) + /// LD1D Zresult.D, Pg/Z, [Xarray, Xindex, LSL #3] + /// LD1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, long* address) => LoadVector(mask, address); + + /// + /// svuint8_t svld1[_u8](svbool_t pg, const uint8_t *base) + /// LD1B Zresult.B, Pg/Z, [Xarray, Xindex] + /// LD1B Zresult.B, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, byte* address) => LoadVector(mask, address); + + /// + /// svuint16_t svld1[_u16](svbool_t pg, const uint16_t *base) + /// LD1H Zresult.H, Pg/Z, [Xarray, Xindex, LSL #1] + /// LD1H Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, ushort* address) => LoadVector(mask, address); + + /// + /// svuint32_t svld1[_u32](svbool_t pg, const uint32_t *base) + /// LD1W Zresult.S, Pg/Z, [Xarray, Xindex, LSL #2] + /// LD1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, uint* address) => LoadVector(mask, address); + + /// + /// svuint64_t svld1[_u64](svbool_t pg, const uint64_t *base) + /// LD1D Zresult.D, Pg/Z, [Xarray, Xindex, LSL #3] + /// LD1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, ulong* address) => LoadVector(mask, address); + + /// + /// svfloat32_t svld1[_f32](svbool_t pg, const float32_t *base) + /// LD1W Zresult.S, Pg/Z, [Xarray, Xindex, LSL #2] + /// LD1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, float* address) => LoadVector(mask, address); + + /// + /// svfloat64_t svld1[_f64](svbool_t pg, const float64_t *base) + /// LD1D Zresult.D, Pg/Z, [Xarray, Xindex, LSL #3] + /// LD1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVector(Vector mask, double* address) => LoadVector(mask, address); + + + /// LoadVectorByteZeroExtendToInt16 : Load 8-bit data and zero-extend + + /// + /// svint16_t svld1ub_s16(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToInt16(Vector mask, byte* address) => LoadVectorByteZeroExtendToInt16(mask, address); + + + /// LoadVectorByteZeroExtendToInt32 : Load 8-bit data and zero-extend + + /// + /// svint32_t svld1ub_s32(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToInt32(Vector mask, byte* address) => LoadVectorByteZeroExtendToInt32(mask, address); + + + /// LoadVectorByteZeroExtendToInt64 : Load 8-bit data and zero-extend + + /// + /// svint64_t svld1ub_s64(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToInt64(Vector mask, byte* address) => LoadVectorByteZeroExtendToInt64(mask, address); + + + /// LoadVectorByteZeroExtendToUInt16 : Load 8-bit data and zero-extend + + /// + /// svuint16_t svld1ub_u16(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToUInt16(Vector mask, byte* address) => LoadVectorByteZeroExtendToUInt16(mask, address); + + + /// LoadVectorByteZeroExtendToUInt32 : Load 8-bit data and zero-extend + + /// + /// svuint32_t svld1ub_u32(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToUInt32(Vector mask, byte* address) => LoadVectorByteZeroExtendToUInt32(mask, address); + + + /// LoadVectorByteZeroExtendToUInt64 : Load 8-bit data and zero-extend + + /// + /// svuint64_t svld1ub_u64(svbool_t pg, const uint8_t *base) + /// LD1B Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorByteZeroExtendToUInt64(Vector mask, byte* address) => LoadVectorByteZeroExtendToUInt64(mask, address); + + + /// LoadVectorInt16SignExtendToInt32 : Load 16-bit data and sign-extend + + /// + /// svint32_t svld1sh_s32(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToInt32(Vector mask, short* address) => LoadVectorInt16SignExtendToInt32(mask, address); + + + /// LoadVectorInt16SignExtendToInt64 : Load 16-bit data and sign-extend + + /// + /// svint64_t svld1sh_s64(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToInt64(Vector mask, short* address) => LoadVectorInt16SignExtendToInt64(mask, address); + + + /// LoadVectorInt16SignExtendToUInt32 : Load 16-bit data and sign-extend + + /// + /// svuint32_t svld1sh_u32(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToUInt32(Vector mask, short* address) => LoadVectorInt16SignExtendToUInt32(mask, address); + + + /// LoadVectorInt16SignExtendToUInt64 : Load 16-bit data and sign-extend + + /// + /// svuint64_t svld1sh_u64(svbool_t pg, const int16_t *base) + /// LD1SH Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt16SignExtendToUInt64(Vector mask, short* address) => LoadVectorInt16SignExtendToUInt64(mask, address); + + + /// LoadVectorInt32SignExtendToInt64 : Load 32-bit data and sign-extend + + /// + /// svint64_t svld1sw_s64(svbool_t pg, const int32_t *base) + /// LD1SW Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt32SignExtendToInt64(Vector mask, int* address) => LoadVectorInt32SignExtendToInt64(mask, address); + + + /// LoadVectorInt32SignExtendToUInt64 : Load 32-bit data and sign-extend + + /// + /// svuint64_t svld1sw_u64(svbool_t pg, const int32_t *base) + /// LD1SW Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorInt32SignExtendToUInt64(Vector mask, int* address) => LoadVectorInt32SignExtendToUInt64(mask, address); + + + /// LoadVectorSByteSignExtendToInt16 : Load 8-bit data and sign-extend + + /// + /// svint16_t svld1sb_s16(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToInt16(Vector mask, sbyte* address) => LoadVectorSByteSignExtendToInt16(mask, address); + + + /// LoadVectorSByteSignExtendToInt32 : Load 8-bit data and sign-extend + + /// + /// svint32_t svld1sb_s32(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToInt32(Vector mask, sbyte* address) => LoadVectorSByteSignExtendToInt32(mask, address); + + + /// LoadVectorSByteSignExtendToInt64 : Load 8-bit data and sign-extend + + /// + /// svint64_t svld1sb_s64(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToInt64(Vector mask, sbyte* address) => LoadVectorSByteSignExtendToInt64(mask, address); + + + /// LoadVectorSByteSignExtendToUInt16 : Load 8-bit data and sign-extend + + /// + /// svuint16_t svld1sb_u16(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToUInt16(Vector mask, sbyte* address) => LoadVectorSByteSignExtendToUInt16(mask, address); + + + /// LoadVectorSByteSignExtendToUInt32 : Load 8-bit data and sign-extend + + /// + /// svuint32_t svld1sb_u32(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToUInt32(Vector mask, sbyte* address) => LoadVectorSByteSignExtendToUInt32(mask, address); + + + /// LoadVectorSByteSignExtendToUInt64 : Load 8-bit data and sign-extend + + /// + /// svuint64_t svld1sb_u64(svbool_t pg, const int8_t *base) + /// LD1SB Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorSByteSignExtendToUInt64(Vector mask, sbyte* address) => LoadVectorSByteSignExtendToUInt64(mask, address); + + + /// LoadVectorUInt16ZeroExtendToInt32 : Load 16-bit data and zero-extend + + /// + /// svint32_t svld1uh_s32(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToInt32(Vector mask, ushort* address) => LoadVectorUInt16ZeroExtendToInt32(mask, address); + + + /// LoadVectorUInt16ZeroExtendToInt64 : Load 16-bit data and zero-extend + + /// + /// svint64_t svld1uh_s64(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToInt64(Vector mask, ushort* address) => LoadVectorUInt16ZeroExtendToInt64(mask, address); + + + /// LoadVectorUInt16ZeroExtendToUInt32 : Load 16-bit data and zero-extend + + /// + /// svuint32_t svld1uh_u32(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToUInt32(Vector mask, ushort* address) => LoadVectorUInt16ZeroExtendToUInt32(mask, address); + + + /// LoadVectorUInt16ZeroExtendToUInt64 : Load 16-bit data and zero-extend + + /// + /// svuint64_t svld1uh_u64(svbool_t pg, const uint16_t *base) + /// LD1H Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt16ZeroExtendToUInt64(Vector mask, ushort* address) => LoadVectorUInt16ZeroExtendToUInt64(mask, address); + + + /// LoadVectorUInt32ZeroExtendToInt64 : Load 32-bit data and zero-extend + + /// + /// svint64_t svld1uw_s64(svbool_t pg, const uint32_t *base) + /// LD1W Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt32ZeroExtendToInt64(Vector mask, uint* address) => LoadVectorUInt32ZeroExtendToInt64(mask, address); + + + /// LoadVectorUInt32ZeroExtendToUInt64 : Load 32-bit data and zero-extend + + /// + /// svuint64_t svld1uw_u64(svbool_t pg, const uint32_t *base) + /// LD1W Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// + public static unsafe Vector LoadVectorUInt32ZeroExtendToUInt64(Vector mask, uint* address) => LoadVectorUInt32ZeroExtendToUInt64(mask, address); + + /// Max : Maximum + + /// + /// svuint8_t svmax[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmax[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmax[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// UMAX Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UMAX Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svfloat64_t svmax[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmax[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmax[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMAX Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMAX Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svint16_t svmax[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmax[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmax[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// SMAX Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SMAX Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svint32_t svmax[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmax[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmax[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// SMAX Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SMAX Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svint64_t svmax[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmax[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmax[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// SMAX Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SMAX Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svint8_t svmax[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmax[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmax[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// SMAX Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SMAX Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svfloat32_t svmax[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmax[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmax[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMAX Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMAX Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svuint16_t svmax[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmax[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmax[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// UMAX Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UMAX Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svuint32_t svmax[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmax[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmax[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// UMAX Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UMAX Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + /// + /// svuint64_t svmax[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmax[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmax[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// UMAX Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UMAX Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Max(Vector left, Vector right) => Max(left, right); + + + /// MaxAcross : Maximum reduction to scalar + + /// + /// uint8_t svmaxv[_u8](svbool_t pg, svuint8_t op) + /// UMAXV Bresult, Pg, Zop.B + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// float64_t svmaxv[_f64](svbool_t pg, svfloat64_t op) + /// FMAXV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// int16_t svmaxv[_s16](svbool_t pg, svint16_t op) + /// SMAXV Hresult, Pg, Zop.H + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// int32_t svmaxv[_s32](svbool_t pg, svint32_t op) + /// SMAXV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// int64_t svmaxv[_s64](svbool_t pg, svint64_t op) + /// SMAXV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// int8_t svmaxv[_s8](svbool_t pg, svint8_t op) + /// SMAXV Bresult, Pg, Zop.B + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// float32_t svmaxv[_f32](svbool_t pg, svfloat32_t op) + /// FMAXV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// uint16_t svmaxv[_u16](svbool_t pg, svuint16_t op) + /// UMAXV Hresult, Pg, Zop.H + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// uint32_t svmaxv[_u32](svbool_t pg, svuint32_t op) + /// UMAXV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + /// + /// uint64_t svmaxv[_u64](svbool_t pg, svuint64_t op) + /// UMAXV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxAcross(Vector value) => MaxAcross(value); + + + /// MaxNumber : Maximum number + + /// + /// svfloat64_t svmaxnm[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmaxnm[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmaxnm[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMAXNM Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMAXNM Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector MaxNumber(Vector left, Vector right) => MaxNumber(left, right); + + /// + /// svfloat32_t svmaxnm[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmaxnm[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmaxnm[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMAXNM Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMAXNM Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector MaxNumber(Vector left, Vector right) => MaxNumber(left, right); + + + /// MaxNumberAcross : Maximum number reduction to scalar + + /// + /// float64_t svmaxnmv[_f64](svbool_t pg, svfloat64_t op) + /// FMAXNMV Dresult, Pg, Zop.D + /// + public static unsafe Vector MaxNumberAcross(Vector value) => MaxNumberAcross(value); + + /// + /// float32_t svmaxnmv[_f32](svbool_t pg, svfloat32_t op) + /// FMAXNMV Sresult, Pg, Zop.S + /// + public static unsafe Vector MaxNumberAcross(Vector value) => MaxNumberAcross(value); + + + /// Min : Minimum + + /// + /// svuint8_t svmin[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmin[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svmin[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// UMIN Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// UMIN Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svfloat64_t svmin[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmin[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmin[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMIN Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMIN Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svint16_t svmin[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmin[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svmin[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// SMIN Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SMIN Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svint32_t svmin[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmin[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svmin[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// SMIN Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SMIN Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svint64_t svmin[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmin[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svmin[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// SMIN Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SMIN Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svint8_t svmin[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmin[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svmin[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// SMIN Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SMIN Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svfloat32_t svmin[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmin[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmin[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMIN Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMIN Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svuint16_t svmin[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmin[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svmin[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// UMIN Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// UMIN Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svuint32_t svmin[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmin[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svmin[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// UMIN Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// UMIN Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + /// + /// svuint64_t svmin[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmin[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svmin[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// UMIN Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// UMIN Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector Min(Vector left, Vector right) => Min(left, right); + + + /// MinAcross : Minimum reduction to scalar + + /// + /// uint8_t svminv[_u8](svbool_t pg, svuint8_t op) + /// UMINV Bresult, Pg, Zop.B + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// float64_t svminv[_f64](svbool_t pg, svfloat64_t op) + /// FMINV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// int16_t svminv[_s16](svbool_t pg, svint16_t op) + /// SMINV Hresult, Pg, Zop.H + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// int32_t svminv[_s32](svbool_t pg, svint32_t op) + /// SMINV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// int64_t svminv[_s64](svbool_t pg, svint64_t op) + /// SMINV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// int8_t svminv[_s8](svbool_t pg, svint8_t op) + /// SMINV Bresult, Pg, Zop.B + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// float32_t svminv[_f32](svbool_t pg, svfloat32_t op) + /// FMINV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// uint16_t svminv[_u16](svbool_t pg, svuint16_t op) + /// UMINV Hresult, Pg, Zop.H + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// uint32_t svminv[_u32](svbool_t pg, svuint32_t op) + /// UMINV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + /// + /// uint64_t svminv[_u64](svbool_t pg, svuint64_t op) + /// UMINV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinAcross(Vector value) => MinAcross(value); + + + /// MinNumber : Minimum number + + /// + /// svfloat64_t svminnm[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svminnm[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svminnm[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMINNM Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMINNM Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// + public static unsafe Vector MinNumber(Vector left, Vector right) => MinNumber(left, right); + + /// + /// svfloat32_t svminnm[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svminnm[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svminnm[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMINNM Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMINNM Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// + public static unsafe Vector MinNumber(Vector left, Vector right) => MinNumber(left, right); + + + /// MinNumberAcross : Minimum number reduction to scalar + + /// + /// float64_t svminnmv[_f64](svbool_t pg, svfloat64_t op) + /// FMINNMV Dresult, Pg, Zop.D + /// + public static unsafe Vector MinNumberAcross(Vector value) => MinNumberAcross(value); + + /// + /// float32_t svminnmv[_f32](svbool_t pg, svfloat32_t op) + /// FMINNMV Sresult, Pg, Zop.S + /// + public static unsafe Vector MinNumberAcross(Vector value) => MinNumberAcross(value); + + + /// + /// svint8_t svmul[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svint8_t svmul[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MUL Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svint8_t svmul[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// MOVPRFX Zresult.B, Pg/Z, Zop2.B; MUL Zresult.B, Pg/M, Zresult.B, Zop1.B + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svint16_t svmul[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svint16_t svmul[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MUL Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svint16_t svmul[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// MOVPRFX Zresult.H, Pg/Z, Zop2.H; MUL Zresult.H, Pg/M, Zresult.H, Zop1.H + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svint32_t svmul[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svint32_t svmul[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MUL Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svint32_t svmul[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// MOVPRFX Zresult.S, Pg/Z, Zop2.S; MUL Zresult.S, Pg/M, Zresult.S, Zop1.S + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svint64_t svmul[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svint64_t svmul[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MUL Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svint64_t svmul[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// MOVPRFX Zresult.D, Pg/Z, Zop2.D; MUL Zresult.D, Pg/M, Zresult.D, Zop1.D + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svuint8_t svmul[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svuint8_t svmul[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MUL Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MUL Ztied2.B, Pg/M, Ztied2.B, Zop1.B + /// MOVPRFX Zresult, Zop1; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svuint8_t svmul[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; MUL Zresult.B, Pg/M, Zresult.B, Zop2.B + /// MOVPRFX Zresult.B, Pg/Z, Zop2.B; MUL Zresult.B, Pg/M, Zresult.B, Zop1.B + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svuint16_t svmul[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svuint16_t svmul[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MUL Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MUL Ztied2.H, Pg/M, Ztied2.H, Zop1.H + /// MOVPRFX Zresult, Zop1; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svuint16_t svmul[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; MUL Zresult.H, Pg/M, Zresult.H, Zop2.H + /// MOVPRFX Zresult.H, Pg/Z, Zop2.H; MUL Zresult.H, Pg/M, Zresult.H, Zop1.H + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svuint32_t svmul[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svuint32_t svmul[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MUL Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// MOVPRFX Zresult, Zop1; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svuint32_t svmul[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; MUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// MOVPRFX Zresult.S, Pg/Z, Zop2.S; MUL Zresult.S, Pg/M, Zresult.S, Zop1.S + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svuint64_t svmul[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svuint64_t svmul[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MUL Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// MOVPRFX Zresult, Zop1; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svuint64_t svmul[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; MUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// MOVPRFX Zresult.D, Pg/Z, Zop2.D; MUL Zresult.D, Pg/M, Zresult.D, Zop1.D + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svfloat32_t svmul[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FMUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svmul[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMUL Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FMUL Ztied2.S, Pg/M, Ztied2.S, Zop1.S + /// FMUL Zresult.S, Zop1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FMUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svmul[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; FMUL Zresult.S, Pg/M, Zresult.S, Zop2.S + /// MOVPRFX Zresult.S, Pg/Z, Zop2.S; FMUL Zresult.S, Pg/M, Zresult.S, Zop1.S + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// + /// svfloat64_t svmul[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FMUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svmul[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMUL Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FMUL Ztied2.D, Pg/M, Ztied2.D, Zop1.D + /// FMUL Zresult.D, Zop1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FMUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svmul[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; FMUL Zresult.D, Pg/M, Zresult.D, Zop2.D + /// MOVPRFX Zresult.D, Pg/Z, Zop2.D; FMUL Zresult.D, Pg/M, Zresult.D, Zop1.D + /// + public static unsafe Vector Multiply(Vector left, Vector right) => Multiply(left, right); + + /// MultiplyAdd : Multiply-add, addend first + + /// + /// svuint8_t svmla[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2, svuint8_t op3) + /// svuint8_t svmla[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2, svuint8_t op3) + /// svuint8_t svmla[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2, svuint8_t op3) + /// MLA Ztied1.B, Pg/M, Zop2.B, Zop3.B + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) => MultiplyAdd(addend, left, right); + + /// + /// svint16_t svmla[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2, svint16_t op3) + /// svint16_t svmla[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2, svint16_t op3) + /// svint16_t svmla[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2, svint16_t op3) + /// MLA Ztied1.H, Pg/M, Zop2.H, Zop3.H + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) => MultiplyAdd(addend, left, right); + + /// + /// svint32_t svmla[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2, svint32_t op3) + /// svint32_t svmla[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2, svint32_t op3) + /// svint32_t svmla[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2, svint32_t op3) + /// MLA Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) => MultiplyAdd(addend, left, right); + + /// + /// svint64_t svmla[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2, svint64_t op3) + /// svint64_t svmla[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2, svint64_t op3) + /// svint64_t svmla[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2, svint64_t op3) + /// MLA Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) => MultiplyAdd(addend, left, right); + + /// + /// svint8_t svmla[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2, svint8_t op3) + /// svint8_t svmla[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2, svint8_t op3) + /// svint8_t svmla[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2, svint8_t op3) + /// MLA Ztied1.B, Pg/M, Zop2.B, Zop3.B + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) => MultiplyAdd(addend, left, right); + + /// + /// svuint16_t svmla[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2, svuint16_t op3) + /// svuint16_t svmla[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2, svuint16_t op3) + /// svuint16_t svmla[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2, svuint16_t op3) + /// MLA Ztied1.H, Pg/M, Zop2.H, Zop3.H + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) => MultiplyAdd(addend, left, right); + + /// + /// svuint32_t svmla[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2, svuint32_t op3) + /// svuint32_t svmla[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2, svuint32_t op3) + /// svuint32_t svmla[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2, svuint32_t op3) + /// MLA Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) => MultiplyAdd(addend, left, right); + + /// + /// svuint64_t svmla[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2, svuint64_t op3) + /// svuint64_t svmla[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2, svuint64_t op3) + /// svuint64_t svmla[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2, svuint64_t op3) + /// MLA Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector MultiplyAdd(Vector addend, Vector left, Vector right) => MultiplyAdd(addend, left, right); + + /// MultiplyBySelectedScalar : Multiply + + /// + /// svfloat64_t svmul_lane[_f64](svfloat64_t op1, svfloat64_t op2, uint64_t imm_index) + /// FMUL Zresult.D, Zop1.D, Zop2.D[imm_index] + /// + public static unsafe Vector MultiplyBySelectedScalar(Vector left, Vector right, [ConstantExpected] byte rightIndex) => MultiplyBySelectedScalar(left, right, rightIndex); + + /// + /// svfloat32_t svmul_lane[_f32](svfloat32_t op1, svfloat32_t op2, uint64_t imm_index) + /// FMUL Zresult.S, Zop1.S, Zop2.S[imm_index] + /// + public static unsafe Vector MultiplyBySelectedScalar(Vector left, Vector right, [ConstantExpected] byte rightIndex) => MultiplyBySelectedScalar(left, right, rightIndex); + + /// MultiplyExtended : Multiply extended (∞×0=2) + + /// + /// svfloat64_t svmulx[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmulx[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// svfloat64_t svmulx[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FMULX Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// + public static unsafe Vector MultiplyExtended(Vector left, Vector right) => MultiplyExtended(left, right); + + /// + /// svfloat32_t svmulx[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmulx[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// svfloat32_t svmulx[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FMULX Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// + public static unsafe Vector MultiplyExtended(Vector left, Vector right) => MultiplyExtended(left, right); + + /// MultiplySubtract : Multiply-subtract, minuend first + + /// + /// svuint8_t svmls[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2, svuint8_t op3) + /// svuint8_t svmls[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2, svuint8_t op3) + /// svuint8_t svmls[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2, svuint8_t op3) + /// MLS Ztied1.B, Pg/M, Zop2.B, Zop3.B + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) => MultiplySubtract(minuend, left, right); + + /// + /// svint16_t svmls[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2, svint16_t op3) + /// svint16_t svmls[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2, svint16_t op3) + /// svint16_t svmls[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2, svint16_t op3) + /// MLS Ztied1.H, Pg/M, Zop2.H, Zop3.H + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) => MultiplySubtract(minuend, left, right); + + /// + /// svint32_t svmls[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2, svint32_t op3) + /// svint32_t svmls[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2, svint32_t op3) + /// svint32_t svmls[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2, svint32_t op3) + /// MLS Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) => MultiplySubtract(minuend, left, right); + + /// + /// svint64_t svmls[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2, svint64_t op3) + /// svint64_t svmls[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2, svint64_t op3) + /// svint64_t svmls[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2, svint64_t op3) + /// MLS Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) => MultiplySubtract(minuend, left, right); + + /// + /// svint8_t svmls[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2, svint8_t op3) + /// svint8_t svmls[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2, svint8_t op3) + /// svint8_t svmls[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2, svint8_t op3) + /// MLS Ztied1.B, Pg/M, Zop2.B, Zop3.B + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) => MultiplySubtract(minuend, left, right); + + /// + /// svuint16_t svmls[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2, svuint16_t op3) + /// svuint16_t svmls[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2, svuint16_t op3) + /// svuint16_t svmls[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2, svuint16_t op3) + /// MLS Ztied1.H, Pg/M, Zop2.H, Zop3.H + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) => MultiplySubtract(minuend, left, right); + + /// + /// svuint32_t svmls[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2, svuint32_t op3) + /// svuint32_t svmls[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2, svuint32_t op3) + /// svuint32_t svmls[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2, svuint32_t op3) + /// MLS Ztied1.S, Pg/M, Zop2.S, Zop3.S + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) => MultiplySubtract(minuend, left, right); + + /// + /// svuint64_t svmls[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2, svuint64_t op3) + /// svuint64_t svmls[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2, svuint64_t op3) + /// svuint64_t svmls[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2, svuint64_t op3) + /// MLS Ztied1.D, Pg/M, Zop2.D, Zop3.D + /// + public static unsafe Vector MultiplySubtract(Vector minuend, Vector left, Vector right) => MultiplySubtract(minuend, left, right); + + /// Negate : Negate + + /// + /// svfloat64_t svneg[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op) + /// svfloat64_t svneg[_f64]_x(svbool_t pg, svfloat64_t op) + /// svfloat64_t svneg[_f64]_z(svbool_t pg, svfloat64_t op) + /// FNEG Ztied.D, Pg/M, Zop.D + /// + public static unsafe Vector Negate(Vector value) => Negate(value); + + /// + /// svint16_t svneg[_s16]_m(svint16_t inactive, svbool_t pg, svint16_t op) + /// svint16_t svneg[_s16]_x(svbool_t pg, svint16_t op) + /// svint16_t svneg[_s16]_z(svbool_t pg, svint16_t op) + /// NEG Ztied.H, Pg/M, Zop.H + /// + public static unsafe Vector Negate(Vector value) => Negate(value); + + /// + /// svint32_t svneg[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// svint32_t svneg[_s32]_x(svbool_t pg, svint32_t op) + /// svint32_t svneg[_s32]_z(svbool_t pg, svint32_t op) + /// NEG Ztied.S, Pg/M, Zop.S + /// + public static unsafe Vector Negate(Vector value) => Negate(value); + + /// + /// svint64_t svneg[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// svint64_t svneg[_s64]_x(svbool_t pg, svint64_t op) + /// svint64_t svneg[_s64]_z(svbool_t pg, svint64_t op) + /// NEG Ztied.D, Pg/M, Zop.D + /// + public static unsafe Vector Negate(Vector value) => Negate(value); + + /// + /// svint8_t svneg[_s8]_x(svbool_t pg, svint8_t op) + /// svint8_t svneg[_s8]_m(svint8_t inactive, svbool_t pg, svint8_t op) + /// svint8_t svneg[_s8]_z(svbool_t pg, svint8_t op) + /// NEG Ztied.B, Pg/M, Zop.B + /// + public static unsafe Vector Negate(Vector value) => Negate(value); + + /// + /// svfloat32_t svneg[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op) + /// svfloat32_t svneg[_f32]_x(svbool_t pg, svfloat32_t op) + /// svfloat32_t svneg[_f32]_z(svbool_t pg, svfloat32_t op) + /// FNEG Ztied.S, Pg/M, Zop.S + /// + public static unsafe Vector Negate(Vector value) => Negate(value); + + /// Or : Bitwise inclusive OR + + /// + /// svuint8_t svorr[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svorr[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t svorr[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// ORR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + /// + /// svint16_t svorr[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svorr[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t svorr[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// ORR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + /// + /// svint32_t svorr[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svorr[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t svorr[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// ORR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + /// + /// svint64_t svorr[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svorr[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t svorr[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// ORR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + /// + /// svint8_t svorr[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svorr[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t svorr[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// ORR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + /// + /// svuint16_t svorr[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svorr[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t svorr[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// ORR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + /// + /// svuint32_t svorr[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svorr[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t svorr[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// ORR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + /// + /// svuint64_t svorr[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svorr[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t svorr[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// ORR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// ORR Zresult.D, Zop1.D, Zop2.D + /// svbool_t svorr[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// ORR Presult.B, Pg/Z, Pop1.B, Pop2.B + /// + public static unsafe Vector Or(Vector left, Vector right) => Or(left, right); + + + /// OrAcross : Bitwise inclusive OR reduction to scalar + + /// + /// uint8_t svorv[_u8](svbool_t pg, svuint8_t op) + /// ORV Bresult, Pg, Zop.B + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// + /// int16_t svorv[_s16](svbool_t pg, svint16_t op) + /// ORV Hresult, Pg, Zop.H + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// + /// int32_t svorv[_s32](svbool_t pg, svint32_t op) + /// ORV Sresult, Pg, Zop.S + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// + /// int64_t svorv[_s64](svbool_t pg, svint64_t op) + /// ORV Dresult, Pg, Zop.D + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// + /// int8_t svorv[_s8](svbool_t pg, svint8_t op) + /// ORV Bresult, Pg, Zop.B + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// + /// uint16_t svorv[_u16](svbool_t pg, svuint16_t op) + /// ORV Hresult, Pg, Zop.H + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// + /// uint32_t svorv[_u32](svbool_t pg, svuint32_t op) + /// ORV Sresult, Pg, Zop.S + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + /// + /// uint64_t svorv[_u64](svbool_t pg, svuint64_t op) + /// ORV Dresult, Pg, Zop.D + /// + public static unsafe Vector OrAcross(Vector value) => OrAcross(value); + + + /// SignExtend16 : Sign-extend the low 16 bits + + /// + /// svint32_t svexth[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// SXTH Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; SXTH Zresult.S, Pg/M, Zop.S + /// svint32_t svexth[_s32]_x(svbool_t pg, svint32_t op) + /// SXTH Ztied.S, Pg/M, Ztied.S + /// MOVPRFX Zresult, Zop; SXTH Zresult.S, Pg/M, Zop.S + /// svint32_t svexth[_s32]_z(svbool_t pg, svint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; SXTH Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector SignExtend16(Vector value) => SignExtend16(value); + + /// + /// svint64_t svexth[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// SXTH Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; SXTH Zresult.D, Pg/M, Zop.D + /// svint64_t svexth[_s64]_x(svbool_t pg, svint64_t op) + /// SXTH Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; SXTH Zresult.D, Pg/M, Zop.D + /// svint64_t svexth[_s64]_z(svbool_t pg, svint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; SXTH Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector SignExtend16(Vector value) => SignExtend16(value); + + /// SignExtend32 : Sign-extend the low 32 bits + + /// + /// svint64_t svextw[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// SXTW Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; SXTW Zresult.D, Pg/M, Zop.D + /// svint64_t svextw[_s64]_x(svbool_t pg, svint64_t op) + /// SXTW Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; SXTW Zresult.D, Pg/M, Zop.D + /// svint64_t svextw[_s64]_z(svbool_t pg, svint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; SXTW Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector SignExtend32(Vector value) => SignExtend32(value); + + + /// SignExtend8 : Sign-extend the low 8 bits + + /// + /// svint16_t svextb[_s16]_m(svint16_t inactive, svbool_t pg, svint16_t op) + /// SXTB Ztied.H, Pg/M, Zop.H + /// MOVPRFX Zresult, Zinactive; SXTB Zresult.H, Pg/M, Zop.H + /// svint16_t svextb[_s16]_x(svbool_t pg, svint16_t op) + /// SXTB Ztied.H, Pg/M, Ztied.H + /// MOVPRFX Zresult, Zop; SXTB Zresult.H, Pg/M, Zop.H + /// svint16_t svextb[_s16]_z(svbool_t pg, svint16_t op) + /// MOVPRFX Zresult.H, Pg/Z, Zop.H; SXTB Zresult.H, Pg/M, Zop.H + /// + public static unsafe Vector SignExtend8(Vector value) => SignExtend8(value); + + /// + /// svint32_t svextb[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op) + /// SXTB Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; SXTB Zresult.S, Pg/M, Zop.S + /// svint32_t svextb[_s32]_x(svbool_t pg, svint32_t op) + /// SXTB Ztied.S, Pg/M, Ztied.S + /// MOVPRFX Zresult, Zop; SXTB Zresult.S, Pg/M, Zop.S + /// svint32_t svextb[_s32]_z(svbool_t pg, svint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; SXTB Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector SignExtend8(Vector value) => SignExtend8(value); + + /// + /// svint64_t svextb[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op) + /// SXTB Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; SXTB Zresult.D, Pg/M, Zop.D + /// svint64_t svextb[_s64]_x(svbool_t pg, svint64_t op) + /// SXTB Ztied.D, Pg/M, Ztied.D + /// MOVPRFX Zresult, Zop; SXTB Zresult.D, Pg/M, Zop.D + /// svint64_t svextb[_s64]_z(svbool_t pg, svint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; SXTB Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector SignExtend8(Vector value) => SignExtend8(value); + + + /// SignExtendWideningLower : Unpack and extend low half + + /// + /// svint16_t svunpklo[_s16](svint8_t op) + /// SUNPKLO Zresult.H, Zop.B + /// + public static unsafe Vector SignExtendWideningLower(Vector value) => SignExtendWideningLower(value); + + /// + /// svint32_t svunpklo[_s32](svint16_t op) + /// SUNPKLO Zresult.S, Zop.H + /// + public static unsafe Vector SignExtendWideningLower(Vector value) => SignExtendWideningLower(value); + + /// + /// svint64_t svunpklo[_s64](svint32_t op) + /// SUNPKLO Zresult.D, Zop.S + /// + public static unsafe Vector SignExtendWideningLower(Vector value) => SignExtendWideningLower(value); + + + /// SignExtendWideningUpper : Unpack and extend high half + + /// + /// svint16_t svunpkhi[_s16](svint8_t op) + /// SUNPKHI Zresult.H, Zop.B + /// + public static unsafe Vector SignExtendWideningUpper(Vector value) => SignExtendWideningUpper(value); + + /// + /// svint32_t svunpkhi[_s32](svint16_t op) + /// SUNPKHI Zresult.S, Zop.H + /// + public static unsafe Vector SignExtendWideningUpper(Vector value) => SignExtendWideningUpper(value); + + /// + /// svint64_t svunpkhi[_s64](svint32_t op) + /// SUNPKHI Zresult.D, Zop.S + /// + public static unsafe Vector SignExtendWideningUpper(Vector value) => SignExtendWideningUpper(value); + + /// Subtract : Subtract + + /// + /// svint8_t svsub[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svint8_t svsub[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SUB Zresult.B, Zop1.B, Zop2.B + /// svint8_t svsub[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svint16_t svsub[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svint16_t svsub[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SUB Zresult.H, Zop1.H, Zop2.H + /// svint16_t svsub[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svint32_t svsub[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svint32_t svsub[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SUB Zresult.S, Zop1.S, Zop2.S + /// svint32_t svsub[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svint64_t svsub[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svint64_t svsub[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SUB Zresult.D, Zop1.D, Zop2.D + /// svint64_t svsub[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svuint8_t svsub[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// MOVPRFX Zresult, Zop1; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// svuint8_t svsub[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// SUB Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// SUB Zresult.B, Zop1.B, Zop2.B + /// svuint8_t svsub[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// MOVPRFX Zresult.B, Pg/Z, Zop1.B; SUB Zresult.B, Pg/M, Zresult.B, Zop2.B + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svuint16_t svsub[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// MOVPRFX Zresult, Zop1; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// svuint16_t svsub[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// SUB Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// SUB Zresult.H, Zop1.H, Zop2.H + /// svuint16_t svsub[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// MOVPRFX Zresult.H, Pg/Z, Zop1.H; SUB Zresult.H, Pg/M, Zresult.H, Zop2.H + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svuint32_t svsub[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svuint32_t svsub[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// SUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// SUB Zresult.S, Zop1.S, Zop2.S + /// svuint32_t svsub[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; SUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// + /// svuint64_t svsub[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svuint64_t svsub[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// SUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// SUB Zresult.D, Zop1.D, Zop2.D + /// svuint64_t svsub[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; SUB Zresult.D, Pg/M, Zresult.D, Zop2.D /// - public static unsafe Vector CreateTrueMaskByte([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskByte(pattern); + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + /// + /// svfloat32_t svsub[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FSUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svsub[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// FSUB Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// FSUB Zresult.S, Zop1.S, Zop2.S + /// MOVPRFX Zresult, Zop1; FSUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// svfloat32_t svsub[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2) + /// MOVPRFX Zresult.S, Pg/Z, Zop1.S; FSUB Zresult.S, Pg/M, Zresult.S, Zop2.S + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); - /// CreateTrueMaskDouble : Set predicate elements to true + /// + /// svfloat64_t svsub[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FSUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svsub[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// FSUB Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// FSUB Zresult.D, Zop1.D, Zop2.D + /// MOVPRFX Zresult, Zop1; FSUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// svfloat64_t svsub[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2) + /// MOVPRFX Zresult.D, Pg/Z, Zop1.D; FSUB Zresult.D, Pg/M, Zresult.D, Zop2.D + /// + public static unsafe Vector Subtract(Vector left, Vector right) => Subtract(left, right); + + /// SubtractSaturate : Saturating subtract /// - /// svbool_t svptrue_pat_b8(enum svpattern pattern) - /// PTRUE Presult.B, pattern + /// svuint8_t svqsub[_u8](svuint8_t op1, svuint8_t op2) + /// UQSUB Zresult.B, Zop1.B, Zop2.B /// - public static unsafe Vector CreateTrueMaskDouble([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskDouble(pattern); + public static unsafe Vector SubtractSaturate(Vector left, Vector right) => SubtractSaturate(left, right); + /// + /// svint16_t svqsub[_s16](svint16_t op1, svint16_t op2) + /// SQSUB Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector SubtractSaturate(Vector left, Vector right) => SubtractSaturate(left, right); - /// CreateTrueMaskInt16 : Set predicate elements to true + /// + /// svint32_t svqsub[_s32](svint32_t op1, svint32_t op2) + /// SQSUB Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector SubtractSaturate(Vector left, Vector right) => SubtractSaturate(left, right); /// - /// svbool_t svptrue_pat_b8(enum svpattern pattern) - /// PTRUE Presult.B, pattern + /// svint64_t svqsub[_s64](svint64_t op1, svint64_t op2) + /// SQSUB Zresult.D, Zop1.D, Zop2.D /// - public static unsafe Vector CreateTrueMaskInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskInt16(pattern); + public static unsafe Vector SubtractSaturate(Vector left, Vector right) => SubtractSaturate(left, right); + /// + /// svint8_t svqsub[_s8](svint8_t op1, svint8_t op2) + /// SQSUB Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector SubtractSaturate(Vector left, Vector right) => SubtractSaturate(left, right); - /// CreateTrueMaskInt32 : Set predicate elements to true + /// + /// svuint16_t svqsub[_u16](svuint16_t op1, svuint16_t op2) + /// UQSUB Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector SubtractSaturate(Vector left, Vector right) => SubtractSaturate(left, right); /// - /// svbool_t svptrue_pat_b8(enum svpattern pattern) - /// PTRUE Presult.B, pattern + /// svuint32_t svqsub[_u32](svuint32_t op1, svuint32_t op2) + /// UQSUB Zresult.S, Zop1.S, Zop2.S /// - public static unsafe Vector CreateTrueMaskInt32([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskInt32(pattern); + public static unsafe Vector SubtractSaturate(Vector left, Vector right) => SubtractSaturate(left, right); + /// + /// svuint64_t svqsub[_u64](svuint64_t op1, svuint64_t op2) + /// UQSUB Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector SubtractSaturate(Vector left, Vector right) => SubtractSaturate(left, right); - /// CreateTrueMaskInt64 : Set predicate elements to true + + /// UnzipEven : Concatenate even elements from two inputs /// - /// svbool_t svptrue_pat_b8(enum svpattern pattern) - /// PTRUE Presult.B, pattern + /// svuint8_t svuzp1[_u8](svuint8_t op1, svuint8_t op2) + /// UZP1 Zresult.B, Zop1.B, Zop2.B + /// svbool_t svuzp1_b8(svbool_t op1, svbool_t op2) + /// UZP1 Presult.B, Pop1.B, Pop2.B /// - public static unsafe Vector CreateTrueMaskInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskInt64(pattern); + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); + /// + /// svfloat64_t svuzp1[_f64](svfloat64_t op1, svfloat64_t op2) + /// UZP1 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); - /// CreateTrueMaskSByte : Set predicate elements to true + /// + /// svint16_t svuzp1[_s16](svint16_t op1, svint16_t op2) + /// UZP1 Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); /// - /// svbool_t svptrue_pat_b8(enum svpattern pattern) - /// PTRUE Presult.B, pattern + /// svint32_t svuzp1[_s32](svint32_t op1, svint32_t op2) + /// UZP1 Zresult.S, Zop1.S, Zop2.S /// - public static unsafe Vector CreateTrueMaskSByte([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskSByte(pattern); + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); + /// + /// svint64_t svuzp1[_s64](svint64_t op1, svint64_t op2) + /// UZP1 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); - /// CreateTrueMaskSingle : Set predicate elements to true + /// + /// svint8_t svuzp1[_s8](svint8_t op1, svint8_t op2) + /// UZP1 Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); /// - /// svbool_t svptrue_pat_b8(enum svpattern pattern) - /// PTRUE Presult.B, pattern + /// svfloat32_t svuzp1[_f32](svfloat32_t op1, svfloat32_t op2) + /// UZP1 Zresult.S, Zop1.S, Zop2.S /// - public static unsafe Vector CreateTrueMaskSingle([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskSingle(pattern); + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); + /// + /// svuint16_t svuzp1[_u16](svuint16_t op1, svuint16_t op2) + /// UZP1 Zresult.H, Zop1.H, Zop2.H + /// svbool_t svuzp1_b16(svbool_t op1, svbool_t op2) + /// UZP1 Presult.H, Pop1.H, Pop2.H + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); - /// CreateTrueMaskUInt16 : Set predicate elements to true + /// + /// svuint32_t svuzp1[_u32](svuint32_t op1, svuint32_t op2) + /// UZP1 Zresult.S, Zop1.S, Zop2.S + /// svbool_t svuzp1_b32(svbool_t op1, svbool_t op2) + /// UZP1 Presult.S, Pop1.S, Pop2.S + /// + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); /// - /// svbool_t svptrue_pat_b16(enum svpattern pattern) - /// PTRUE Presult.H, pattern + /// svuint64_t svuzp1[_u64](svuint64_t op1, svuint64_t op2) + /// UZP1 Zresult.D, Zop1.D, Zop2.D + /// svbool_t svuzp1_b64(svbool_t op1, svbool_t op2) + /// UZP1 Presult.D, Pop1.D, Pop2.D /// - public static unsafe Vector CreateTrueMaskUInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskUInt16(pattern); + public static unsafe Vector UnzipEven(Vector left, Vector right) => UnzipEven(left, right); - /// CreateTrueMaskUInt32 : Set predicate elements to true + /// UnzipOdd : Concatenate odd elements from two inputs /// - /// svbool_t svptrue_pat_b32(enum svpattern pattern) - /// PTRUE Presult.S, pattern + /// svuint8_t svuzp2[_u8](svuint8_t op1, svuint8_t op2) + /// UZP2 Zresult.B, Zop1.B, Zop2.B + /// svbool_t svuzp2_b8(svbool_t op1, svbool_t op2) + /// UZP2 Presult.B, Pop1.B, Pop2.B /// - public static unsafe Vector CreateTrueMaskUInt32([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskUInt32(pattern); + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + + /// + /// svfloat64_t svuzp2[_f64](svfloat64_t op1, svfloat64_t op2) + /// UZP2 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + /// + /// svint16_t svuzp2[_s16](svint16_t op1, svint16_t op2) + /// UZP2 Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); - /// CreateTrueMaskUInt64 : Set predicate elements to true + /// + /// svint32_t svuzp2[_s32](svint32_t op1, svint32_t op2) + /// UZP2 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); /// - /// svbool_t svptrue_pat_b64(enum svpattern pattern) - /// PTRUE Presult.D, pattern + /// svint64_t svuzp2[_s64](svint64_t op1, svint64_t op2) + /// UZP2 Zresult.D, Zop1.D, Zop2.D /// - public static unsafe Vector CreateTrueMaskUInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskUInt64(pattern); + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + /// + /// svint8_t svuzp2[_s8](svint8_t op1, svint8_t op2) + /// UZP2 Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + /// + /// svfloat32_t svuzp2[_f32](svfloat32_t op1, svfloat32_t op2) + /// UZP2 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); - /// LoadVector : Unextended load + /// + /// svuint16_t svuzp2[_u16](svuint16_t op1, svuint16_t op2) + /// UZP2 Zresult.H, Zop1.H, Zop2.H + /// svbool_t svuzp2_b16(svbool_t op1, svbool_t op2) + /// UZP2 Presult.H, Pop1.H, Pop2.H + /// + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); /// - /// svint8_t svld1[_s8](svbool_t pg, const int8_t *base) - /// LD1B Zresult.B, Pg/Z, [Xarray, Xindex] - /// LD1B Zresult.B, Pg/Z, [Xbase, #0, MUL VL] + /// svuint32_t svuzp2[_u32](svuint32_t op1, svuint32_t op2) + /// UZP2 Zresult.S, Zop1.S, Zop2.S + /// svbool_t svuzp2_b32(svbool_t op1, svbool_t op2) + /// UZP2 Presult.S, Pop1.S, Pop2.S /// - public static unsafe Vector LoadVector(Vector mask, sbyte* address) => LoadVector(mask, address); + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); /// - /// svint16_t svld1[_s16](svbool_t pg, const int16_t *base) - /// LD1H Zresult.H, Pg/Z, [Xarray, Xindex, LSL #1] - /// LD1H Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// svuint64_t svuzp2[_u64](svuint64_t op1, svuint64_t op2) + /// UZP2 Zresult.D, Zop1.D, Zop2.D + /// svbool_t svuzp2_b64(svbool_t op1, svbool_t op2) + /// UZP2 Presult.D, Pop1.D, Pop2.D /// - public static unsafe Vector LoadVector(Vector mask, short* address) => LoadVector(mask, address); + public static unsafe Vector UnzipOdd(Vector left, Vector right) => UnzipOdd(left, right); + + + /// Xor : Bitwise exclusive OR /// - /// svint32_t svld1[_s32](svbool_t pg, const int32_t *base) - /// LD1W Zresult.S, Pg/Z, [Xarray, Xindex, LSL #2] - /// LD1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// svuint8_t sveor[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t sveor[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// svuint8_t sveor[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2) + /// EOR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, int* address) => LoadVector(mask, address); + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); /// - /// svint64_t svld1[_s64](svbool_t pg, const int64_t *base) - /// LD1D Zresult.D, Pg/Z, [Xarray, Xindex, LSL #3] - /// LD1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// svint16_t sveor[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t sveor[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2) + /// svint16_t sveor[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2) + /// EOR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, long* address) => LoadVector(mask, address); + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); /// - /// svuint8_t svld1[_u8](svbool_t pg, const uint8_t *base) - /// LD1B Zresult.B, Pg/Z, [Xarray, Xindex] - /// LD1B Zresult.B, Pg/Z, [Xbase, #0, MUL VL] + /// svint32_t sveor[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t sveor[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2) + /// svint32_t sveor[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2) + /// EOR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, byte* address) => LoadVector(mask, address); + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); /// - /// svuint16_t svld1[_u16](svbool_t pg, const uint16_t *base) - /// LD1H Zresult.H, Pg/Z, [Xarray, Xindex, LSL #1] - /// LD1H Zresult.H, Pg/Z, [Xbase, #0, MUL VL] + /// svint64_t sveor[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t sveor[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2) + /// svint64_t sveor[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2) + /// EOR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, ushort* address) => LoadVector(mask, address); + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); /// - /// svuint32_t svld1[_u32](svbool_t pg, const uint32_t *base) - /// LD1W Zresult.S, Pg/Z, [Xarray, Xindex, LSL #2] - /// LD1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// svint8_t sveor[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t sveor[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2) + /// svint8_t sveor[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2) + /// EOR Ztied1.B, Pg/M, Ztied1.B, Zop2.B + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, uint* address) => LoadVector(mask, address); + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); /// - /// svuint64_t svld1[_u64](svbool_t pg, const uint64_t *base) - /// LD1D Zresult.D, Pg/Z, [Xarray, Xindex, LSL #3] - /// LD1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// svuint16_t sveor[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t sveor[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// svuint16_t sveor[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2) + /// EOR Ztied1.H, Pg/M, Ztied1.H, Zop2.H + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, ulong* address) => LoadVector(mask, address); + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); /// - /// svfloat32_t svld1[_f32](svbool_t pg, const float32_t *base) - /// LD1W Zresult.S, Pg/Z, [Xarray, Xindex, LSL #2] - /// LD1W Zresult.S, Pg/Z, [Xbase, #0, MUL VL] + /// svuint32_t sveor[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t sveor[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// svuint32_t sveor[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2) + /// EOR Ztied1.S, Pg/M, Ztied1.S, Zop2.S + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, float* address) => LoadVector(mask, address); + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); /// - /// svfloat64_t svld1[_f64](svbool_t pg, const float64_t *base) - /// LD1D Zresult.D, Pg/Z, [Xarray, Xindex, LSL #3] - /// LD1D Zresult.D, Pg/Z, [Xbase, #0, MUL VL] + /// svuint64_t sveor[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t sveor[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// svuint64_t sveor[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2) + /// EOR Ztied1.D, Pg/M, Ztied1.D, Zop2.D + /// EOR Zresult.D, Zop1.D, Zop2.D + /// svbool_t sveor[_b]_z(svbool_t pg, svbool_t op1, svbool_t op2) + /// EOR Presult.B, Pg/Z, Pop1.B, Pop2.B /// - public static unsafe Vector LoadVector(Vector mask, double* address) => LoadVector(mask, address); + public static unsafe Vector Xor(Vector left, Vector right) => Xor(left, right); + + + /// XorAcross : Bitwise exclusive OR reduction to scalar + + /// + /// uint8_t sveorv[_u8](svbool_t pg, svuint8_t op) + /// EORV Bresult, Pg, Zop.B + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + /// + /// int16_t sveorv[_s16](svbool_t pg, svint16_t op) + /// EORV Hresult, Pg, Zop.H + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + /// + /// int32_t sveorv[_s32](svbool_t pg, svint32_t op) + /// EORV Sresult, Pg, Zop.S + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + /// + /// int64_t sveorv[_s64](svbool_t pg, svint64_t op) + /// EORV Dresult, Pg, Zop.D + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + /// + /// int8_t sveorv[_s8](svbool_t pg, svint8_t op) + /// EORV Bresult, Pg, Zop.B + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + /// + /// uint16_t sveorv[_u16](svbool_t pg, svuint16_t op) + /// EORV Hresult, Pg, Zop.H + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + /// + /// uint32_t sveorv[_u32](svbool_t pg, svuint32_t op) + /// EORV Sresult, Pg, Zop.S + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + /// + /// uint64_t sveorv[_u64](svbool_t pg, svuint64_t op) + /// EORV Dresult, Pg, Zop.D + /// + public static unsafe Vector XorAcross(Vector value) => XorAcross(value); + + + /// ZeroExtend16 : Zero-extend the low 16 bits + + /// + /// svuint32_t svexth[_u32]_m(svuint32_t inactive, svbool_t pg, svuint32_t op) + /// UXTH Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; UXTH Zresult.S, Pg/M, Zop.S + /// svuint32_t svexth[_u32]_x(svbool_t pg, svuint32_t op) + /// UXTH Ztied.S, Pg/M, Ztied.S + /// AND Ztied.S, Ztied.S, #65535 + /// svuint32_t svexth[_u32]_z(svbool_t pg, svuint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; UXTH Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector ZeroExtend16(Vector value) => ZeroExtend16(value); + + /// + /// svuint64_t svexth[_u64]_m(svuint64_t inactive, svbool_t pg, svuint64_t op) + /// UXTH Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; UXTH Zresult.D, Pg/M, Zop.D + /// svuint64_t svexth[_u64]_x(svbool_t pg, svuint64_t op) + /// UXTH Ztied.D, Pg/M, Ztied.D + /// AND Ztied.D, Ztied.D, #65535 + /// svuint64_t svexth[_u64]_z(svbool_t pg, svuint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; UXTH Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector ZeroExtend16(Vector value) => ZeroExtend16(value); + + + /// ZeroExtend32 : Zero-extend the low 32 bits + + /// + /// svuint64_t svextw[_u64]_m(svuint64_t inactive, svbool_t pg, svuint64_t op) + /// UXTW Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; UXTW Zresult.D, Pg/M, Zop.D + /// svuint64_t svextw[_u64]_x(svbool_t pg, svuint64_t op) + /// UXTW Ztied.D, Pg/M, Ztied.D + /// AND Ztied.D, Ztied.D, #4294967295 + /// svuint64_t svextw[_u64]_z(svbool_t pg, svuint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; UXTW Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector ZeroExtend32(Vector value) => ZeroExtend32(value); + + + /// ZeroExtend8 : Zero-extend the low 8 bits + + /// + /// svuint16_t svextb[_u16]_m(svuint16_t inactive, svbool_t pg, svuint16_t op) + /// UXTB Ztied.H, Pg/M, Zop.H + /// MOVPRFX Zresult, Zinactive; UXTB Zresult.H, Pg/M, Zop.H + /// svuint16_t svextb[_u16]_x(svbool_t pg, svuint16_t op) + /// UXTB Ztied.H, Pg/M, Ztied.H + /// AND Ztied.H, Ztied.H, #255 + /// svuint16_t svextb[_u16]_z(svbool_t pg, svuint16_t op) + /// MOVPRFX Zresult.H, Pg/Z, Zop.H; UXTB Zresult.H, Pg/M, Zop.H + /// + public static unsafe Vector ZeroExtend8(Vector value) => ZeroExtend8(value); + + /// + /// svuint32_t svextb[_u32]_m(svuint32_t inactive, svbool_t pg, svuint32_t op) + /// UXTB Ztied.S, Pg/M, Zop.S + /// MOVPRFX Zresult, Zinactive; UXTB Zresult.S, Pg/M, Zop.S + /// svuint32_t svextb[_u32]_x(svbool_t pg, svuint32_t op) + /// UXTB Ztied.S, Pg/M, Ztied.S + /// AND Ztied.S, Ztied.S, #255 + /// svuint32_t svextb[_u32]_z(svbool_t pg, svuint32_t op) + /// MOVPRFX Zresult.S, Pg/Z, Zop.S; UXTB Zresult.S, Pg/M, Zop.S + /// + public static unsafe Vector ZeroExtend8(Vector value) => ZeroExtend8(value); + + /// + /// svuint64_t svextb[_u64]_m(svuint64_t inactive, svbool_t pg, svuint64_t op) + /// UXTB Ztied.D, Pg/M, Zop.D + /// MOVPRFX Zresult, Zinactive; UXTB Zresult.D, Pg/M, Zop.D + /// svuint64_t svextb[_u64]_x(svbool_t pg, svuint64_t op) + /// UXTB Ztied.D, Pg/M, Ztied.D + /// AND Ztied.D, Ztied.D, #255 + /// svuint64_t svextb[_u64]_z(svbool_t pg, svuint64_t op) + /// MOVPRFX Zresult.D, Pg/Z, Zop.D; UXTB Zresult.D, Pg/M, Zop.D + /// + public static unsafe Vector ZeroExtend8(Vector value) => ZeroExtend8(value); + + /// ZeroExtendWideningLower : Unpack and extend low half + + /// + /// svuint16_t svunpklo[_u16](svuint8_t op) + /// UUNPKLO Zresult.H, Zop.B + /// + public static unsafe Vector ZeroExtendWideningLower(Vector value) => ZeroExtendWideningLower(value); + + /// + /// svuint32_t svunpklo[_u32](svuint16_t op) + /// UUNPKLO Zresult.S, Zop.H + /// + public static unsafe Vector ZeroExtendWideningLower(Vector value) => ZeroExtendWideningLower(value); + + /// + /// svuint64_t svunpklo[_u64](svuint32_t op) + /// UUNPKLO Zresult.D, Zop.S + /// + public static unsafe Vector ZeroExtendWideningLower(Vector value) => ZeroExtendWideningLower(value); + + + /// ZeroExtendWideningUpper : Unpack and extend high half + + /// + /// svuint16_t svunpkhi[_u16](svuint8_t op) + /// UUNPKHI Zresult.H, Zop.B + /// + public static unsafe Vector ZeroExtendWideningUpper(Vector value) => ZeroExtendWideningUpper(value); + + /// + /// svuint32_t svunpkhi[_u32](svuint16_t op) + /// UUNPKHI Zresult.S, Zop.H + /// svbool_t svunpkhi[_b](svbool_t op) + /// PUNPKHI Presult.H, Pop.B + /// + public static unsafe Vector ZeroExtendWideningUpper(Vector value) => ZeroExtendWideningUpper(value); + + /// + /// svuint64_t svunpkhi[_u64](svuint32_t op) + /// UUNPKHI Zresult.D, Zop.S + /// + public static unsafe Vector ZeroExtendWideningUpper(Vector value) => ZeroExtendWideningUpper(value); + + /// ZipHigh : Interleave elements from high halves of two inputs + + /// + /// svuint8_t svzip2[_u8](svuint8_t op1, svuint8_t op2) + /// ZIP2 Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svfloat64_t svzip2[_f64](svfloat64_t op1, svfloat64_t op2) + /// ZIP2 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svint16_t svzip2[_s16](svint16_t op1, svint16_t op2) + /// ZIP2 Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svint32_t svzip2[_s32](svint32_t op1, svint32_t op2) + /// ZIP2 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svint64_t svzip2[_s64](svint64_t op1, svint64_t op2) + /// ZIP2 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svint8_t svzip2[_s8](svint8_t op1, svint8_t op2) + /// ZIP2 Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svfloat32_t svzip2[_f32](svfloat32_t op1, svfloat32_t op2) + /// ZIP2 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svuint16_t svzip2[_u16](svuint16_t op1, svuint16_t op2) + /// ZIP2 Zresult.H, Zop1.H, Zop2.H + /// svbool_t svzip2_b16(svbool_t op1, svbool_t op2) + /// ZIP2 Presult.H, Pop1.H, Pop2.H + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svuint32_t svzip2[_u32](svuint32_t op1, svuint32_t op2) + /// ZIP2 Zresult.S, Zop1.S, Zop2.S + /// svbool_t svzip2_b32(svbool_t op1, svbool_t op2) + /// ZIP2 Presult.S, Pop1.S, Pop2.S + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + /// + /// svuint64_t svzip2[_u64](svuint64_t op1, svuint64_t op2) + /// ZIP2 Zresult.D, Zop1.D, Zop2.D + /// svbool_t svzip2_b64(svbool_t op1, svbool_t op2) + /// ZIP2 Presult.D, Pop1.D, Pop2.D + /// + public static unsafe Vector ZipHigh(Vector left, Vector right) => ZipHigh(left, right); + + + /// ZipLow : Interleave elements from low halves of two inputs + + /// + /// svuint8_t svzip1[_u8](svuint8_t op1, svuint8_t op2) + /// ZIP1 Zresult.B, Zop1.B, Zop2.B + /// svbool_t svzip1_b8(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.B, Pop1.B, Pop2.B + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svfloat64_t svzip1[_f64](svfloat64_t op1, svfloat64_t op2) + /// ZIP1 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svint16_t svzip1[_s16](svint16_t op1, svint16_t op2) + /// ZIP1 Zresult.H, Zop1.H, Zop2.H + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svint32_t svzip1[_s32](svint32_t op1, svint32_t op2) + /// ZIP1 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svint64_t svzip1[_s64](svint64_t op1, svint64_t op2) + /// ZIP1 Zresult.D, Zop1.D, Zop2.D + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svint8_t svzip1[_s8](svint8_t op1, svint8_t op2) + /// ZIP1 Zresult.B, Zop1.B, Zop2.B + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svfloat32_t svzip1[_f32](svfloat32_t op1, svfloat32_t op2) + /// ZIP1 Zresult.S, Zop1.S, Zop2.S + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svuint16_t svzip1[_u16](svuint16_t op1, svuint16_t op2) + /// ZIP1 Zresult.H, Zop1.H, Zop2.H + /// svbool_t svzip1_b16(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.H, Pop1.H, Pop2.H + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svuint32_t svzip1[_u32](svuint32_t op1, svuint32_t op2) + /// ZIP1 Zresult.S, Zop1.S, Zop2.S + /// svbool_t svzip1_b32(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.S, Pop1.S, Pop2.S + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); + + /// + /// svuint64_t svzip1[_u64](svuint64_t op1, svuint64_t op2) + /// ZIP1 Zresult.D, Zop1.D, Zop2.D + /// svbool_t svzip1_b64(svbool_t op1, svbool_t op2) + /// ZIP1 Presult.D, Pop1.D, Pop2.D + /// + public static unsafe Vector ZipLow(Vector left, Vector right) => ZipLow(left, right); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs index a1d49045bb2a..a88b5f0dec6a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs @@ -553,6 +553,19 @@ static virtual bool TryCopyTo(TSelf vector, Span destination) // New Surface Area // + /// Checks if any of the vector lanes are equivalent to value. + /// The Vector. + /// The Value to check. + /// true if has any lanes equivalent to otherwise, false if none of the lanes are equivalent to />. + /// The type of the elements in the vector () is not supported. + static abstract bool Any(TSelf vector, T value); + + /// Checks if any of the vector lanes have All Bits set. + /// The Vector to check. + /// true if has any lanes with All Bits set otherwise, false if none of the lanes have All Bits set />. + /// The type of the elements in the vector () is not supported. + static abstract bool AnyWhereAllBitsSet(TSelf vector); + static abstract int IndexOfLastMatch(TSelf vector); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs index 66c0a4773442..1cb989eedba4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs @@ -468,7 +468,7 @@ public static unsafe Vector128 ConvertToDouble(Vector128 vector) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -481,7 +481,20 @@ public static unsafe Vector128 ConvertToInt32(Vector128 vector) ); } - /// Converts a to a . + /// Converts a to a platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector128 ConvertToInt32Native(Vector128 vector) + { + return Create( + Vector64.ConvertToInt32Native(vector._lower), + Vector64.ConvertToInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -494,6 +507,19 @@ public static unsafe Vector128 ConvertToInt64(Vector128 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector128 ConvertToInt64Native(Vector128 vector) + { + return Create( + Vector64.ConvertToInt64Native(vector._lower), + Vector64.ConvertToInt64Native(vector._upper) + ); + } + /// Converts a to a . /// The vector to convert. /// The converted vector. @@ -564,7 +590,7 @@ static Vector128 SoftwareFallback(Vector128 vector) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -578,7 +604,21 @@ public static unsafe Vector128 ConvertToUInt32(Vector128 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector128 ConvertToUInt32Native(Vector128 vector) + { + return Create( + Vector64.ConvertToUInt32Native(vector._lower), + Vector64.ConvertToUInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -592,6 +632,20 @@ public static unsafe Vector128 ConvertToUInt64(Vector128 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector128 ConvertToUInt64Native(Vector128 vector) + { + return Create( + Vector64.ConvertToUInt64Native(vector._lower), + Vector64.ConvertToUInt64Native(vector._upper) + ); + } + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. @@ -1041,7 +1095,7 @@ public static Vector128 Create(Vector64 lower, Vector64 upper) } else { - ThrowHelper.ThrowForUnsupportedIntrinsicsVector256BaseType(); + ThrowHelper.ThrowForUnsupportedIntrinsicsVector128BaseType(); Unsafe.SkipInit(out Vector128 result); result.SetLowerUnsafe(lower); @@ -1513,6 +1567,28 @@ internal static Vector128 Floor(Vector128 vector) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Floor(Vector128 vector) => Floor(vector); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 FusedMultiplyAdd(Vector128 left, Vector128 right, Vector128 addend) + { + return Create( + Vector64.FusedMultiplyAdd(left._lower, right._lower, addend._lower), + Vector64.FusedMultiplyAdd(left._upper, right._upper, addend._upper) + ); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 FusedMultiplyAdd(Vector128 left, Vector128 right, Vector128 addend) + { + return Create( + Vector64.FusedMultiplyAdd(left._lower, right._lower, addend._lower), + Vector64.FusedMultiplyAdd(left._upper, right._upper, addend._upper) + ); + } + /// Gets the element at the specified index. /// The type of the elements in the vector. /// The vector to get the element from. @@ -1954,6 +2030,28 @@ public static Vector128 Min(Vector128 left, Vector128 right) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Multiply(T left, Vector128 right) => left * right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 MultiplyAddEstimate(Vector128 left, Vector128 right, Vector128 addend) + { + return Create( + Vector64.MultiplyAddEstimate(left._lower, right._lower, addend._lower), + Vector64.MultiplyAddEstimate(left._upper, right._upper, addend._upper) + ); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 MultiplyAddEstimate(Vector128 left, Vector128 right, Vector128 addend) + { + return Create( + Vector64.MultiplyAddEstimate(left._lower, right._lower, addend._lower), + Vector64.MultiplyAddEstimate(left._upper, right._upper, addend._upper) + ); + } + /// Narrows two instances into one . /// The vector that will be narrowed to the lower half of the result vector. /// The vector that will be narrowed to the upper half of the result vector. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs index 42bef9fe0ed9..23f027f12f71 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs @@ -692,6 +692,16 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri // New Surface Area // + static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector128 vector) + { + return Vector128.EqualsAny(vector, Vector128.AllBitsSet); + } + + static bool ISimdVector, T>.Any(Vector128 vector, T value) + { + return Vector128.EqualsAny(vector, Vector128.Create((T)value)); + } + static int ISimdVector, T>.IndexOfLastMatch(Vector128 vector) { uint mask = vector.ExtractMostSignificantBits(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs index 1347a082afab..01591e0aa20c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs @@ -5,6 +5,7 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.X86; namespace System.Runtime.Intrinsics @@ -386,7 +387,7 @@ public static Vector256 ConvertToDouble(Vector256 vector) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -399,7 +400,20 @@ public static Vector256 ConvertToInt32(Vector256 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 ConvertToInt32Native(Vector256 vector) + { + return Create( + Vector128.ConvertToInt32Native(vector._lower), + Vector128.ConvertToInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -412,6 +426,19 @@ public static Vector256 ConvertToInt64(Vector256 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 ConvertToInt64Native(Vector256 vector) + { + return Create( + Vector128.ConvertToInt64Native(vector._lower), + Vector128.ConvertToInt64Native(vector._upper) + ); + } + /// Converts a to a . /// The vector to convert. /// The converted vector. @@ -472,7 +499,7 @@ public static Vector256 ConvertToSingle(Vector256 vector) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -486,7 +513,21 @@ public static Vector256 ConvertToUInt32(Vector256 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 ConvertToUInt32Native(Vector256 vector) + { + return Create( + Vector128.ConvertToUInt32Native(vector._lower), + Vector128.ConvertToUInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -500,6 +541,20 @@ public static Vector256 ConvertToUInt64(Vector256 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 ConvertToUInt64Native(Vector256 vector) + { + return Create( + Vector128.ConvertToUInt64Native(vector._lower), + Vector128.ConvertToUInt64Native(vector._upper) + ); + } + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. @@ -1492,6 +1547,28 @@ internal static Vector256 Floor(Vector256 vector) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Floor(Vector256 vector) => Floor(vector); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 FusedMultiplyAdd(Vector256 left, Vector256 right, Vector256 addend) + { + return Create( + Vector128.FusedMultiplyAdd(left._lower, right._lower, addend._lower), + Vector128.FusedMultiplyAdd(left._upper, right._upper, addend._upper) + ); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 FusedMultiplyAdd(Vector256 left, Vector256 right, Vector256 addend) + { + return Create( + Vector128.FusedMultiplyAdd(left._lower, right._lower, addend._lower), + Vector128.FusedMultiplyAdd(left._upper, right._upper, addend._upper) + ); + } + /// Gets the element at the specified index. /// The type of the input vector. /// The vector to get the element from. @@ -1931,6 +2008,28 @@ public static Vector256 Min(Vector256 left, Vector256 right) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Multiply(T left, Vector256 right) => left * right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 MultiplyAddEstimate(Vector256 left, Vector256 right, Vector256 addend) + { + return Create( + Vector128.MultiplyAddEstimate(left._lower, right._lower, addend._lower), + Vector128.MultiplyAddEstimate(left._upper, right._upper, addend._upper) + ); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 MultiplyAddEstimate(Vector256 left, Vector256 right, Vector256 addend) + { + return Create( + Vector128.MultiplyAddEstimate(left._lower, right._lower, addend._lower), + Vector128.MultiplyAddEstimate(left._upper, right._upper, addend._upper) + ); + } + /// Narrows two instances into one . /// The vector that will be narrowed to the lower half of the result vector. /// The vector that will be narrowed to the upper half of the result vector. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs index fd1e889e44f2..d506b0da0277 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs @@ -682,6 +682,16 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri // New Surface Area // + static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector256 vector) + { + return Vector256.EqualsAny(vector, Vector256.AllBitsSet); + } + + static bool ISimdVector, T>.Any(Vector256 vector, T value) + { + return Vector256.EqualsAny(vector, Vector256.Create((T)value)); + } + static int ISimdVector, T>.IndexOfLastMatch(Vector256 vector) { uint mask = vector.ExtractMostSignificantBits(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs index edb84585a987..bf24a68ffc81 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs @@ -5,6 +5,7 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.X86; namespace System.Runtime.Intrinsics @@ -348,7 +349,7 @@ public static Vector512 ConvertToDouble(Vector512 vector) ); } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -361,7 +362,20 @@ public static Vector512 ConvertToInt32(Vector512 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 ConvertToInt32Native(Vector512 vector) + { + return Create( + Vector256.ConvertToInt32Native(vector._lower), + Vector256.ConvertToInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -374,6 +388,19 @@ public static Vector512 ConvertToInt64(Vector512 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 ConvertToInt64Native(Vector512 vector) + { + return Create( + Vector256.ConvertToInt64Native(vector._lower), + Vector256.ConvertToInt64Native(vector._upper) + ); + } + /// Converts a to a . /// The vector to convert. /// The converted vector. @@ -401,7 +428,7 @@ public static Vector512 ConvertToSingle(Vector512 vector) ); } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -415,7 +442,21 @@ public static Vector512 ConvertToUInt32(Vector512 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 ConvertToUInt32Native(Vector512 vector) + { + return Create( + Vector256.ConvertToUInt32Native(vector._lower), + Vector256.ConvertToUInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -429,6 +470,20 @@ public static Vector512 ConvertToUInt64(Vector512 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 ConvertToUInt64Native(Vector512 vector) + { + return Create( + Vector256.ConvertToUInt64Native(vector._lower), + Vector256.ConvertToUInt64Native(vector._upper) + ); + } + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. @@ -1539,6 +1594,28 @@ internal static Vector512 Floor(Vector512 vector) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Floor(Vector512 vector) => Floor(vector); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 FusedMultiplyAdd(Vector512 left, Vector512 right, Vector512 addend) + { + return Create( + Vector256.FusedMultiplyAdd(left._lower, right._lower, addend._lower), + Vector256.FusedMultiplyAdd(left._upper, right._upper, addend._upper) + ); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 FusedMultiplyAdd(Vector512 left, Vector512 right, Vector512 addend) + { + return Create( + Vector256.FusedMultiplyAdd(left._lower, right._lower, addend._lower), + Vector256.FusedMultiplyAdd(left._upper, right._upper, addend._upper) + ); + } + /// Gets the element at the specified index. /// The type of the input vector. /// The vector to get the element from. @@ -1978,6 +2055,27 @@ public static Vector512 Min(Vector512 left, Vector512 right) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Multiply(T left, Vector512 right) => left * right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 MultiplyAddEstimate(Vector512 left, Vector512 right, Vector512 addend) + { + return Create( + Vector256.MultiplyAddEstimate(left._lower, right._lower, addend._lower), + Vector256.MultiplyAddEstimate(left._upper, right._upper, addend._upper) + ); + } + + /// + [Intrinsic] + public static Vector512 MultiplyAddEstimate(Vector512 left, Vector512 right, Vector512 addend) + { + return Create( + Vector256.MultiplyAddEstimate(left._lower, right._lower, addend._lower), + Vector256.MultiplyAddEstimate(left._upper, right._upper, addend._upper) + ); + } + /// Narrows two instances into one . /// The vector that will be narrowed to the lower half of the result vector. /// The vector that will be narrowed to the upper half of the result vector. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs index 5c3f6a593ebf..b070fc6e54dc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs @@ -682,6 +682,16 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri // New Surface Area // + static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector512 vector) + { + return Vector512.EqualsAny(vector, Vector512.AllBitsSet); + } + + static bool ISimdVector, T>.Any(Vector512 vector, T value) + { + return Vector512.EqualsAny(vector, Vector512.Create((T)value)); + } + static int ISimdVector, T>.IndexOfLastMatch(Vector512 vector) { ulong mask = vector.ExtractMostSignificantBits(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs index 50e9f697c94f..78b15f643ac2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs @@ -6,6 +6,8 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics.Arm; +using System.Runtime.Intrinsics.X86; +using System.Text; namespace System.Runtime.Intrinsics { @@ -339,7 +341,7 @@ public static unsafe Vector64 ConvertToDouble(Vector64 vector) return result; } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -350,14 +352,32 @@ public static unsafe Vector64 ConvertToInt32(Vector64 vector) for (int i = 0; i < Vector64.Count; i++) { - int value = (int)vector.GetElementUnsafe(i); + int value = float.ConvertToInteger(vector.GetElementUnsafe(i)); result.SetElementUnsafe(i, value); } return result; } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector64 ConvertToInt32Native(Vector64 vector) + { + Unsafe.SkipInit(out Vector64 result); + + for (int i = 0; i < Vector64.Count; i++) + { + int value = float.ConvertToIntegerNative(vector.GetElementUnsafe(i)); + result.SetElementUnsafe(i, value); + } + + return result; + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -368,7 +388,25 @@ public static unsafe Vector64 ConvertToInt64(Vector64 vector) for (int i = 0; i < Vector64.Count; i++) { - long value = (long)vector.GetElementUnsafe(i); + long value = double.ConvertToInteger(vector.GetElementUnsafe(i)); + result.SetElementUnsafe(i, value); + } + + return result; + } + + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector64 ConvertToInt64Native(Vector64 vector) + { + Unsafe.SkipInit(out Vector64 result); + + for (int i = 0; i < Vector64.Count; i++) + { + long value = double.ConvertToIntegerNative(vector.GetElementUnsafe(i)); result.SetElementUnsafe(i, value); } @@ -412,7 +450,7 @@ public static unsafe Vector64 ConvertToSingle(Vector64 vector) return result; } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -424,14 +462,33 @@ public static unsafe Vector64 ConvertToUInt32(Vector64 vector) for (int i = 0; i < Vector64.Count; i++) { - uint value = (uint)vector.GetElementUnsafe(i); + uint value = float.ConvertToInteger(vector.GetElementUnsafe(i)); result.SetElementUnsafe(i, value); } return result; } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector64 ConvertToUInt32Native(Vector64 vector) + { + Unsafe.SkipInit(out Vector64 result); + + for (int i = 0; i < Vector64.Count; i++) + { + uint value = float.ConvertToIntegerNative(vector.GetElementUnsafe(i)); + result.SetElementUnsafe(i, value); + } + + return result; + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -443,7 +500,26 @@ public static unsafe Vector64 ConvertToUInt64(Vector64 vector) for (int i = 0; i < Vector64.Count; i++) { - ulong value = (ulong)vector.GetElementUnsafe(i); + ulong value = double.ConvertToInteger(vector.GetElementUnsafe(i)); + result.SetElementUnsafe(i, value); + } + + return result; + } + + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector64 ConvertToUInt64Native(Vector64 vector) + { + Unsafe.SkipInit(out Vector64 result); + + for (int i = 0; i < Vector64.Count; i++) + { + ulong value = double.ConvertToIntegerNative(vector.GetElementUnsafe(i)); result.SetElementUnsafe(i, value); } @@ -1158,7 +1234,7 @@ internal static Vector64 Exp(Vector64 vector) for (int index = 0; index < Vector64.Count; index++) { - T value = T.Exp(vector.GetElement(index)); + T value = T.Exp(vector.GetElementUnsafe(index)); result.SetElementUnsafe(index, value); } @@ -1268,6 +1344,54 @@ internal static Vector64 Floor(Vector64 vector) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector64 Floor(Vector64 vector) => Floor(vector); + /// Computes ( * ) + , rounded as one ternary operation. + /// The vector to be multiplied with . + /// The vector to be multiplied with . + /// The vector to be added to the result of multiplied by . + /// ( * ) + , rounded as one ternary operation. + /// + /// This computes ( * ) as if to infinite precision, adds to that result as if to infinite precision, and finally rounds to the nearest representable value. + /// This differs from the non-fused sequence which would compute ( * ) as if to infinite precision, round the result to the nearest representable value, add to the rounded result as if to infinite precision, and finally round to the nearest representable value. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 FusedMultiplyAdd(Vector64 left, Vector64 right, Vector64 addend) + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + double value = double.FusedMultiplyAdd(left.GetElementUnsafe(index), right.GetElementUnsafe(index), addend.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + + /// Computes ( * ) + , rounded as one ternary operation. + /// The vector to be multiplied with . + /// The vector to be multiplied with . + /// The vector to be added to the result of multiplied by . + /// ( * ) + , rounded as one ternary operation. + /// + /// This computes ( * ) as if to infinite precision, adds to that result as if to infinite precision, and finally rounds to the nearest representable value. + /// This differs from the non-fused sequence which would compute ( * ) as if to infinite precision, round the result to the nearest representable value, add to the rounded result as if to infinite precision, and finally round to the nearest representable value. + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 FusedMultiplyAdd(Vector64 left, Vector64 right, Vector64 addend) + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + float value = float.FusedMultiplyAdd(left.GetElementUnsafe(index), right.GetElementUnsafe(index), addend.GetElementUnsafe(index)); + result.SetElementUnsafe(index, value); + } + + return result; + } + /// Gets the element at the specified index. /// The type of the elements in the vector. /// The vector to get the element from. @@ -1619,7 +1743,7 @@ internal static Vector64 Log(Vector64 vector) for (int index = 0; index < Vector64.Count; index++) { - T value = T.Log(vector.GetElement(index)); + T value = T.Log(vector.GetElementUnsafe(index)); result.SetElementUnsafe(index, value); } @@ -1665,7 +1789,7 @@ internal static Vector64 Log2(Vector64 vector) for (int index = 0; index < Vector64.Count; index++) { - T value = T.Log2(vector.GetElement(index)); + T value = T.Log2(vector.GetElementUnsafe(index)); result.SetElementUnsafe(index, value); } @@ -1776,6 +1900,54 @@ public static Vector64 Min(Vector64 left, Vector64 right) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector64 Multiply(T left, Vector64 right) => left * right; + /// Computes an estimate of ( * ) + . + /// The vector to be multiplied with . + /// The vector to be multiplied with . + /// The vector to be added to the result of multiplied by . + /// An estimate of ( * ) + . + /// + /// On hardware that natively supports , this may return a result that was rounded as one ternary operation. + /// On hardware without specialized support, this may just return ( * ) + . + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 MultiplyAddEstimate(Vector64 left, Vector64 right, Vector64 addend) + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + double element = double.MultiplyAddEstimate(left.GetElementUnsafe(index), right.GetElementUnsafe(index), addend.GetElementUnsafe(index)); + result.SetElementUnsafe(index, element); + } + + return result; + } + + /// Computes an estimate of ( * ) + . + /// The vector to be multiplied with . + /// The vector to be multiplied with . + /// The vector to be added to the result of multiplied by . + /// An estimate of ( * ) + . + /// + /// On hardware that natively supports , this may return a result that was rounded as one ternary operation. + /// On hardware without specialized support, this may just return ( * ) + . + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 MultiplyAddEstimate(Vector64 left, Vector64 right, Vector64 addend) + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + float element = float.MultiplyAddEstimate(left.GetElementUnsafe(index), right.GetElementUnsafe(index), addend.GetElementUnsafe(index)); + result.SetElementUnsafe(index, element); + } + + return result; + } + /// Narrows two instances into one . /// The vector that will be narrowed to the lower half of the result vector. /// The vector that will be narrowed to the upper half of the result vector. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs index 3ec5a675e61b..362977a3b227 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs @@ -757,6 +757,16 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri // New Surface Area // + static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector64 vector) + { + return Vector64.EqualsAny(vector, Vector64.AllBitsSet); + } + + static bool ISimdVector, T>.Any(Vector64 vector, T value) + { + return Vector64.EqualsAny(vector, Vector64.Create((T)value)); + } + static int ISimdVector, T>.IndexOfLastMatch(Vector64 vector) { uint mask = vector.ExtractMostSignificantBits(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index 1bacef78f325..498aa1e4d4a9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -30,7 +30,7 @@ private enum InternalState Unloading } - private static volatile Dictionary>? s_allContexts; + private static Dictionary>? s_allContexts; private static long s_nextId; [MemberNotNull(nameof(s_allContexts))] diff --git a/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs b/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs index 17fbb2950c6c..a4cfbaee8f29 100644 --- a/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs @@ -881,6 +881,31 @@ internal bool CheckValue( return false; } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:UnrecognizedReflectionPattern", + Justification = "AllocateValueType is only called on a ValueType. You can always create an instance of a ValueType.")] + [return: NotNullIfNotNull(nameof(value))] + internal static object? AllocateValueType(RuntimeType type, object? value) + { + Debug.Assert(type.IsValueType); + Debug.Assert(!type.IsByRefLike); + + if (value is not null) + { + // Make a copy of the provided value by re-boxing the existing value's underlying data. + Debug.Assert(type.IsEquivalentTo(value.GetType())); + return RuntimeHelpers.Box(ref RuntimeHelpers.GetRawData(value), type.TypeHandle)!; + } + + if (type.IsNullableOfT) + { + // If the type is Nullable, then create a true boxed Nullable of the default Nullable value. + return RuntimeMethodHandle.ReboxToNullable(null, type); + } + + // Otherwise, just create a default instance of the type. + return RuntimeHelpers.GetUninitializedObject(type); + } + private CheckValueStatus TryChangeType(ref object? value, ref bool copyBack) { RuntimeType? sigElementType; diff --git a/src/libraries/System.Private.CoreLib/src/System/SByte.cs b/src/libraries/System.Private.CoreLib/src/System/SByte.cs index fb4734d41b69..00bce51b3a2b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SByte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SByte.cs @@ -837,6 +837,9 @@ public static sbyte MinMagnitude(sbyte x, sbyte y) /// static sbyte INumberBase.MinMagnitudeNumber(sbyte x, sbyte y) => MinMagnitude(x, y); + /// + static sbyte INumberBase.MultiplyAddEstimate(sbyte left, sbyte right, sbyte addend) => (sbyte)((left * right) + addend); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out sbyte result) => TryConvertFromChecked(value, out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/SearchValues/BitmapCharSearchValues.cs b/src/libraries/System.Private.CoreLib/src/System/SearchValues/BitmapCharSearchValues.cs new file mode 100644 index 000000000000..71e364cc618d --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/BitmapCharSearchValues.cs @@ -0,0 +1,108 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace System.Buffers +{ + internal sealed class BitmapCharSearchValues : SearchValues + { + private readonly uint[] _bitmap; + + public BitmapCharSearchValues(ReadOnlySpan values, int maxInclusive) + { + Debug.Assert(maxInclusive <= char.MaxValue); + + _bitmap = new uint[maxInclusive / 32 + 1]; + + foreach (char c in values) + { + _bitmap[c >> 5] |= 1u << c; + } + } + + internal override char[] GetValues() + { + var chars = new List(); + uint[] bitmap = _bitmap; + + for (int i = 0; i < _bitmap.Length * 32; i++) + { + if (Contains(bitmap, i)) + { + chars.Add((char)i); + } + } + + return chars.ToArray(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal override bool ContainsCore(char value) => + Contains(_bitmap, value); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool Contains(uint[] bitmap, int value) + { + uint offset = (uint)(value >> 5); + return offset < (uint)bitmap.Length && (bitmap[offset] & (1u << value)) != 0; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal override int IndexOfAny(ReadOnlySpan span) => + IndexOfAny(ref MemoryMarshal.GetReference(span), span.Length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal override int IndexOfAnyExcept(ReadOnlySpan span) => + IndexOfAny(ref MemoryMarshal.GetReference(span), span.Length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal override int LastIndexOfAny(ReadOnlySpan span) => + LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal override int LastIndexOfAnyExcept(ReadOnlySpan span) => + LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length); + + private int IndexOfAny(ref char searchSpace, int searchSpaceLength) + where TNegator : struct, IndexOfAnyAsciiSearcher.INegator + { + ref char searchSpaceEnd = ref Unsafe.Add(ref searchSpace, searchSpaceLength); + ref char cur = ref searchSpace; + uint[] bitmap = _bitmap; + + while (!Unsafe.AreSame(ref cur, ref searchSpaceEnd)) + { + char c = cur; + if (TNegator.NegateIfNeeded(Contains(bitmap, c))) + { + return (int)((nuint)Unsafe.ByteOffset(ref searchSpace, ref cur) / sizeof(char)); + } + + cur = ref Unsafe.Add(ref cur, 1); + } + + return -1; + } + + private int LastIndexOfAny(ref char searchSpace, int searchSpaceLength) + where TNegator : struct, IndexOfAnyAsciiSearcher.INegator + { + uint[] bitmap = _bitmap; + + while (--searchSpaceLength >= 0) + { + char c = Unsafe.Add(ref searchSpace, searchSpaceLength); + if (TNegator.NegateIfNeeded(Contains(bitmap, c))) + { + break; + } + } + + return searchSpaceLength; + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/SearchValues/Latin1CharSearchValues.cs b/src/libraries/System.Private.CoreLib/src/System/SearchValues/Latin1CharSearchValues.cs deleted file mode 100644 index 3968825ccd4c..000000000000 --- a/src/libraries/System.Private.CoreLib/src/System/SearchValues/Latin1CharSearchValues.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace System.Buffers -{ - internal sealed class Latin1CharSearchValues : SearchValues - { - private readonly BitVector256 _lookup; - - public Latin1CharSearchValues(ReadOnlySpan values) - { - foreach (char c in values) - { - if (c > 255) - { - // The values were modified concurrent with the call to SearchValues.Create - ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); - } - - _lookup.Set(c); - } - } - - internal override char[] GetValues() => _lookup.GetCharValues(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal override bool ContainsCore(char value) => - _lookup.Contains256(value); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal override int IndexOfAny(ReadOnlySpan span) => - IndexOfAny(ref MemoryMarshal.GetReference(span), span.Length); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal override int IndexOfAnyExcept(ReadOnlySpan span) => - IndexOfAny(ref MemoryMarshal.GetReference(span), span.Length); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal override int LastIndexOfAny(ReadOnlySpan span) => - LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal override int LastIndexOfAnyExcept(ReadOnlySpan span) => - LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length); - - private int IndexOfAny(ref char searchSpace, int searchSpaceLength) - where TNegator : struct, IndexOfAnyAsciiSearcher.INegator - { - ref char searchSpaceEnd = ref Unsafe.Add(ref searchSpace, searchSpaceLength); - ref char cur = ref searchSpace; - - while (!Unsafe.AreSame(ref cur, ref searchSpaceEnd)) - { - char c = cur; - if (TNegator.NegateIfNeeded(_lookup.Contains256(c))) - { - return (int)((nuint)Unsafe.ByteOffset(ref searchSpace, ref cur) / sizeof(char)); - } - - cur = ref Unsafe.Add(ref cur, 1); - } - - return -1; - } - - private int LastIndexOfAny(ref char searchSpace, int searchSpaceLength) - where TNegator : struct, IndexOfAnyAsciiSearcher.INegator - { - for (int i = searchSpaceLength - 1; i >= 0; i--) - { - char c = Unsafe.Add(ref searchSpace, i); - if (TNegator.NegateIfNeeded(_lookup.Contains256(c))) - { - return i; - } - } - - return -1; - } - } -} diff --git a/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticCharSearchValues.cs b/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticCharSearchValues.cs index 5ec79a3b8911..2914407b0cc1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticCharSearchValues.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticCharSearchValues.cs @@ -8,31 +8,30 @@ namespace System.Buffers { internal sealed class ProbabilisticCharSearchValues : SearchValues { - private ProbabilisticMap _map; - private readonly string _values; + private ProbabilisticMapState _map; - public ProbabilisticCharSearchValues(scoped ReadOnlySpan values) + public ProbabilisticCharSearchValues(ReadOnlySpan values, int maxInclusive) { - _values = new string(values); - _map = new ProbabilisticMap(_values); + _map = new ProbabilisticMapState(values, maxInclusive); } - internal override char[] GetValues() => _values.ToCharArray(); + internal override char[] GetValues() => + _map.GetValues(); [MethodImpl(MethodImplOptions.AggressiveInlining)] internal override bool ContainsCore(char value) => - ProbabilisticMap.Contains(ref Unsafe.As(ref _map), _values, value); + _map.FastContains(value); internal override int IndexOfAny(ReadOnlySpan span) => - ProbabilisticMap.IndexOfAny(ref Unsafe.As(ref _map), ref MemoryMarshal.GetReference(span), span.Length, _values); + ProbabilisticMap.IndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref _map); internal override int IndexOfAnyExcept(ReadOnlySpan span) => - ProbabilisticMap.IndexOfAnySimpleLoop(ref MemoryMarshal.GetReference(span), span.Length, _values); + ProbabilisticMapState.IndexOfAnySimpleLoop(ref MemoryMarshal.GetReference(span), span.Length, ref _map); internal override int LastIndexOfAny(ReadOnlySpan span) => - ProbabilisticMap.LastIndexOfAny(ref Unsafe.As(ref _map), ref MemoryMarshal.GetReference(span), span.Length, _values); + ProbabilisticMap.LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref _map); internal override int LastIndexOfAnyExcept(ReadOnlySpan span) => - ProbabilisticMap.LastIndexOfAnySimpleLoop(ref MemoryMarshal.GetReference(span), span.Length, _values); + ProbabilisticMapState.LastIndexOfAnySimpleLoop(ref MemoryMarshal.GetReference(span), span.Length, ref _map); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMap.cs b/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMap.cs index 076340bebeba..3c93ad6cd46d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMap.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMap.cs @@ -10,6 +10,7 @@ using System.Runtime.Intrinsics.Wasm; using System.Runtime.Intrinsics.X86; +#pragma warning disable CS8500 // Takes the address of a managed type namespace System.Buffers { @@ -98,7 +99,7 @@ internal static bool Contains(ref uint charMap, ReadOnlySpan values, int c Contains(values, (char)ch); [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool Contains(ReadOnlySpan values, char ch) => + internal static bool Contains(ReadOnlySpan values, char ch) => SpanHelpers.NonPackedContainsValueType( ref Unsafe.As(ref MemoryMarshal.GetReference(values)), (short)ch, @@ -344,78 +345,69 @@ public static int LastIndexOfAnyExcept(ref char searchSpace, int searchSpaceLeng } [MethodImpl(MethodImplOptions.NoInlining)] - private static int ProbabilisticIndexOfAny(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) + private static unsafe int ProbabilisticIndexOfAny(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) { var valuesSpan = new ReadOnlySpan(ref values, valuesLength); - var map = new ProbabilisticMap(valuesSpan); - ref uint charMap = ref Unsafe.As(ref map); + // ProbabilisticMapState can hold either a precomputed hash table or a pointer to the values. + // Precomputing the table is relatively expensive, so we only do it when using SearchValues where instances can be reused. + var state = new ProbabilisticMapState(&valuesSpan); - return IndexOfAny(ref charMap, ref searchSpace, searchSpaceLength, valuesSpan); + // The FalseConst here indicates that we can't use the fast character checks and must instead check the values span. + return IndexOfAny(ref searchSpace, searchSpaceLength, ref state); } [MethodImpl(MethodImplOptions.NoInlining)] - private static int ProbabilisticLastIndexOfAny(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) + private static unsafe int ProbabilisticLastIndexOfAny(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) { var valuesSpan = new ReadOnlySpan(ref values, valuesLength); - var map = new ProbabilisticMap(valuesSpan); - ref uint charMap = ref Unsafe.As(ref map); + // ProbabilisticMapState can hold either a precomputed hash table or a pointer to the values. + // Precomputing the table is relatively expensive, so we only do it when using SearchValues where instances can be reused. + var state = new ProbabilisticMapState(&valuesSpan); - return LastIndexOfAny(ref charMap, ref searchSpace, searchSpaceLength, valuesSpan); + // The FalseConst here indicates that we can't use the fast character checks and must instead check the values span. + return LastIndexOfAny(ref searchSpace, searchSpaceLength, ref state); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static int IndexOfAny(ref uint charMap, ref char searchSpace, int searchSpaceLength, ReadOnlySpan values) + internal static int IndexOfAny(ref char searchSpace, int searchSpaceLength, ref ProbabilisticMapState state) + where TUseFastContains : struct, SearchValues.IRuntimeConst { if ((Sse41.IsSupported || AdvSimd.Arm64.IsSupported) && searchSpaceLength >= 16) { return Vector512.IsHardwareAccelerated && Avx512Vbmi.VL.IsSupported - ? IndexOfAnyVectorizedAvx512(ref charMap, ref searchSpace, searchSpaceLength, values) - : IndexOfAnyVectorized(ref charMap, ref searchSpace, searchSpaceLength, values); + ? IndexOfAnyVectorizedAvx512(ref searchSpace, searchSpaceLength, ref state) + : IndexOfAnyVectorized(ref searchSpace, searchSpaceLength, ref state); } - ref char searchSpaceEnd = ref Unsafe.Add(ref searchSpace, searchSpaceLength); - ref char cur = ref searchSpace; - - while (!Unsafe.AreSame(ref cur, ref searchSpaceEnd)) - { - int ch = cur; - if (Contains(ref charMap, values, ch)) - { - return MatchOffset(ref searchSpace, ref cur); - } - - cur = ref Unsafe.Add(ref cur, 1); - } - - return -1; + return ProbabilisticMapState.IndexOfAnySimpleLoop(ref searchSpace, searchSpaceLength, ref state); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static int LastIndexOfAny(ref uint charMap, ref char searchSpace, int searchSpaceLength, ReadOnlySpan values) + internal static int LastIndexOfAny(ref char searchSpace, int searchSpaceLength, ref ProbabilisticMapState state) + where TUseFastContains : struct, SearchValues.IRuntimeConst { - for (int i = searchSpaceLength - 1; i >= 0; i--) + if ((Sse41.IsSupported || AdvSimd.Arm64.IsSupported) && searchSpaceLength >= 16) { - int ch = Unsafe.Add(ref searchSpace, i); - if (Contains(ref charMap, values, ch)) - { - return i; - } + return Vector512.IsHardwareAccelerated && Avx512Vbmi.VL.IsSupported + ? LastIndexOfAnyVectorizedAvx512(ref searchSpace, searchSpaceLength, ref state) + : LastIndexOfAnyVectorized(ref searchSpace, searchSpaceLength, ref state); } - return -1; + return ProbabilisticMapState.LastIndexOfAnySimpleLoop(ref searchSpace, searchSpaceLength, ref state); } [CompExactlyDependsOn(typeof(Avx512Vbmi.VL))] - private static int IndexOfAnyVectorizedAvx512(ref uint charMap, ref char searchSpace, int searchSpaceLength, ReadOnlySpan values) + private static int IndexOfAnyVectorizedAvx512(ref char searchSpace, int searchSpaceLength, ref ProbabilisticMapState state) + where TUseFastContains : struct, SearchValues.IRuntimeConst { Debug.Assert(Avx512Vbmi.VL.IsSupported); Debug.Assert(searchSpaceLength >= 16); ref char searchSpaceEnd = ref Unsafe.Add(ref searchSpace, searchSpaceLength); - Vector256 charMap256 = Vector256.LoadUnsafe(ref Unsafe.As(ref charMap)); + Vector256 charMap256 = Vector256.LoadUnsafe(ref Unsafe.As(ref state.Map)); if (searchSpaceLength > 32) { @@ -432,7 +424,7 @@ private static int IndexOfAnyVectorizedAvx512(ref uint charMap, ref char searchS if (result != Vector512.Zero) { - if (TryFindMatch(ref cur, PackedSpanHelpers.FixUpPackedVector512Result(result).ExtractMostSignificantBits(), values, out int index)) + if (TryFindMatchAvx512(ref cur, PackedSpanHelpers.FixUpPackedVector512Result(result).ExtractMostSignificantBits(), ref state, out int index)) { return MatchOffset(ref searchSpace, ref cur) + index; } @@ -462,7 +454,7 @@ private static int IndexOfAnyVectorizedAvx512(ref uint charMap, ref char searchS if (result != Vector512.Zero) { - if (TryFindMatchOverlapped(ref searchSpace, searchSpaceLength, PackedSpanHelpers.FixUpPackedVector512Result(result).ExtractMostSignificantBits(), values, out int index)) + if (TryFindMatchOverlappedAvx512(ref searchSpace, searchSpaceLength, PackedSpanHelpers.FixUpPackedVector512Result(result).ExtractMostSignificantBits(), ref state, out int index)) { return index; } @@ -479,7 +471,7 @@ private static int IndexOfAnyVectorizedAvx512(ref uint charMap, ref char searchS if (result != Vector256.Zero) { - if (TryFindMatchOverlapped(ref searchSpace, searchSpaceLength, PackedSpanHelpers.FixUpPackedVector256Result(result).ExtractMostSignificantBits(), values, out int index)) + if (TryFindMatchOverlappedAvx512(ref searchSpace, searchSpaceLength, PackedSpanHelpers.FixUpPackedVector256Result(result).ExtractMostSignificantBits(), ref state, out int index)) { return index; } @@ -491,7 +483,8 @@ private static int IndexOfAnyVectorizedAvx512(ref uint charMap, ref char searchS [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] [CompExactlyDependsOn(typeof(Sse41))] - private static int IndexOfAnyVectorized(ref uint charMap, ref char searchSpace, int searchSpaceLength, ReadOnlySpan values) + private static int IndexOfAnyVectorized(ref char searchSpace, int searchSpaceLength, ref ProbabilisticMapState state) + where TUseFastContains : struct, SearchValues.IRuntimeConst { Debug.Assert(Sse41.IsSupported || AdvSimd.Arm64.IsSupported); Debug.Assert(searchSpaceLength >= 16); @@ -499,8 +492,8 @@ private static int IndexOfAnyVectorized(ref uint charMap, ref char searchSpace, ref char searchSpaceEnd = ref Unsafe.Add(ref searchSpace, searchSpaceLength); ref char cur = ref searchSpace; - Vector128 charMapLower = Vector128.LoadUnsafe(ref Unsafe.As(ref charMap)); - Vector128 charMapUpper = Vector128.LoadUnsafe(ref Unsafe.As(ref charMap), (nuint)Vector128.Count); + Vector128 charMapLower = Vector128.LoadUnsafe(ref Unsafe.As(ref state.Map)); + Vector128 charMapUpper = Vector128.LoadUnsafe(ref Unsafe.As(ref state.Map), (nuint)Vector128.Count); #pragma warning disable IntrinsicsInSystemPrivateCoreLibAttributeNotSpecificEnough // In this case, we have an else clause which has the same semantic meaning whether or not Avx2 is considered supported or unsupported if (Avx2.IsSupported && searchSpaceLength >= 32) @@ -517,7 +510,7 @@ private static int IndexOfAnyVectorized(ref uint charMap, ref char searchSpace, if (result != Vector256.Zero) { - if (TryFindMatch(ref cur, PackedSpanHelpers.FixUpPackedVector256Result(result).ExtractMostSignificantBits(), values, out int index)) + if (TryFindMatch(ref cur, PackedSpanHelpers.FixUpPackedVector256Result(result).ExtractMostSignificantBits(), ref state, out int index)) { return MatchOffset(ref searchSpace, ref cur) + index; } @@ -557,7 +550,7 @@ private static int IndexOfAnyVectorized(ref uint charMap, ref char searchSpace, if (result != Vector128.Zero) { - if (TryFindMatch(ref cur, result.ExtractMostSignificantBits(), values, out int index)) + if (TryFindMatch(ref cur, result.ExtractMostSignificantBits(), ref state, out int index)) { return MatchOffset(ref searchSpace, ref cur) + index; } @@ -580,18 +573,200 @@ private static int IndexOfAnyVectorized(ref uint charMap, ref char searchSpace, return -1; } + [CompExactlyDependsOn(typeof(Avx512Vbmi.VL))] + private static int LastIndexOfAnyVectorizedAvx512(ref char searchSpace, int searchSpaceLength, ref ProbabilisticMapState state) + where TUseFastContains : struct, SearchValues.IRuntimeConst + { + Debug.Assert(Avx512Vbmi.VL.IsSupported); + Debug.Assert(searchSpaceLength >= 16); + + ref char cur = ref Unsafe.Add(ref searchSpace, searchSpaceLength); + + Vector256 charMap256 = Vector256.LoadUnsafe(ref Unsafe.As(ref state.Map)); + + if (searchSpaceLength > 32) + { + Vector512 charMap512 = Vector512.Create(charMap256, charMap256); + + if (searchSpaceLength > 64) + { + ref char lastStartVector = ref Unsafe.Add(ref searchSpace, 64); + + while (true) + { + Debug.Assert(Unsafe.ByteOffset(ref searchSpace, ref cur) >= 64 * sizeof(char)); + + cur = ref Unsafe.Subtract(ref cur, 64); + + Vector512 result = ContainsMask64CharsAvx512(charMap512, ref cur, ref Unsafe.Add(ref cur, Vector512.Count)); + + if (result != Vector512.Zero) + { + if (TryFindLastMatchAvx512(ref cur, PackedSpanHelpers.FixUpPackedVector512Result(result).ExtractMostSignificantBits(), ref state, out int index)) + { + return MatchOffset(ref searchSpace, ref cur) + index; + } + } + + if (!Unsafe.IsAddressGreaterThan(ref cur, ref lastStartVector)) + { + if (Unsafe.AreSame(ref cur, ref searchSpace)) + { + break; + } + + // Adjust the current vector and do one last iteration. + cur = ref lastStartVector; + } + } + } + else + { + Debug.Assert(searchSpaceLength is > 32 and <= 64); + Debug.Assert(Unsafe.ByteOffset(ref searchSpace, ref cur) >= 32 * sizeof(char)); + + // Process the first and last vector in the search space. + // They may overlap, but we'll handle that in the index calculation if we do get a match. + Vector512 result = ContainsMask64CharsAvx512(charMap512, ref searchSpace, ref Unsafe.Subtract(ref cur, Vector512.Count)); + + if (result != Vector512.Zero) + { + if (TryFindLastMatchOverlappedAvx512(ref searchSpace, searchSpaceLength, PackedSpanHelpers.FixUpPackedVector512Result(result).ExtractMostSignificantBits(), ref state, out int index)) + { + return index; + } + } + } + } + else + { + Debug.Assert(searchSpaceLength is >= 16 and <= 32); + Debug.Assert(Unsafe.ByteOffset(ref searchSpace, ref cur) >= 16 * sizeof(char)); + + // Process the first and last vector in the search space. + // They may overlap, but we'll handle that in the index calculation if we do get a match. + Vector256 result = ContainsMask32CharsAvx512(charMap256, ref searchSpace, ref Unsafe.Subtract(ref cur, Vector256.Count)); + + if (result != Vector256.Zero) + { + if (TryFindLastMatchOverlappedAvx512(ref searchSpace, searchSpaceLength, PackedSpanHelpers.FixUpPackedVector256Result(result).ExtractMostSignificantBits(), ref state, out int index)) + { + return index; + } + } + } + + return -1; + } + + [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] + [CompExactlyDependsOn(typeof(Sse41))] + private static int LastIndexOfAnyVectorized(ref char searchSpace, int searchSpaceLength, ref ProbabilisticMapState state) + where TUseFastContains : struct, SearchValues.IRuntimeConst + { + Debug.Assert(Sse41.IsSupported || AdvSimd.Arm64.IsSupported); + Debug.Assert(searchSpaceLength >= 16); + + ref char cur = ref Unsafe.Add(ref searchSpace, searchSpaceLength); + + Vector128 charMapLower = Vector128.LoadUnsafe(ref Unsafe.As(ref state.Map)); + Vector128 charMapUpper = Vector128.LoadUnsafe(ref Unsafe.As(ref state.Map), (nuint)Vector128.Count); + +#pragma warning disable IntrinsicsInSystemPrivateCoreLibAttributeNotSpecificEnough // In this case, we have an else clause which has the same semantic meaning whether or not Avx2 is considered supported or unsupported + if (Avx2.IsSupported && searchSpaceLength >= 32) +#pragma warning restore IntrinsicsInSystemPrivateCoreLibAttributeNotSpecificEnough + { + Vector256 charMapLower256 = Vector256.Create(charMapLower, charMapLower); + Vector256 charMapUpper256 = Vector256.Create(charMapUpper, charMapUpper); + + ref char lastStartVectorAvx2 = ref Unsafe.Add(ref searchSpace, 32); + + while (true) + { + Debug.Assert(Unsafe.ByteOffset(ref searchSpace, ref cur) >= 32 * sizeof(char)); + + cur = ref Unsafe.Subtract(ref cur, 32); + + Vector256 result = ContainsMask32CharsAvx2(charMapLower256, charMapUpper256, ref cur); + + if (result != Vector256.Zero) + { + if (TryFindLastMatch(ref cur, PackedSpanHelpers.FixUpPackedVector256Result(result).ExtractMostSignificantBits(), ref state, out int index)) + { + return MatchOffset(ref searchSpace, ref cur) + index; + } + } + + if (!Unsafe.IsAddressGreaterThan(ref cur, ref lastStartVectorAvx2)) + { + if (Unsafe.AreSame(ref cur, ref searchSpace)) + { + return -1; + } + + if (Unsafe.ByteOffset(ref searchSpace, ref cur) > 16 * sizeof(char)) + { + // If we have more than 16 characters left to process, we can + // adjust the current vector and do one last iteration of Avx2. + cur = ref lastStartVectorAvx2; + } + else + { + // Otherwise adjust the vector such that we'll only need to do a single + // iteration of ContainsMask16Chars below. + cur = ref Unsafe.Add(ref searchSpace, 16); + break; + } + } + } + } + + ref char lastStartVector = ref Unsafe.Add(ref searchSpace, 16); + + while (true) + { + Debug.Assert(Unsafe.ByteOffset(ref searchSpace, ref cur) >= 16 * sizeof(char)); + + cur = ref Unsafe.Subtract(ref cur, 16); + + Vector128 result = ContainsMask16Chars(charMapLower, charMapUpper, ref cur); + + if (result != Vector128.Zero) + { + if (TryFindLastMatch(ref cur, result.ExtractMostSignificantBits(), ref state, out int index)) + { + return MatchOffset(ref searchSpace, ref cur) + index; + } + } + + if (!Unsafe.IsAddressGreaterThan(ref cur, ref lastStartVector)) + { + if (Unsafe.AreSame(ref cur, ref searchSpace)) + { + break; + } + + // Adjust the current vector and do one last iteration. + cur = ref lastStartVector; + } + } + + return -1; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int MatchOffset(ref char searchSpace, ref char cur) => (int)((nuint)Unsafe.ByteOffset(ref searchSpace, ref cur) / sizeof(char)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool TryFindMatch(ref char cur, uint mask, ReadOnlySpan values, out int index) + private static bool TryFindMatch(ref char cur, uint mask, ref ProbabilisticMapState state, out int index) + where TUseFastContains : struct, SearchValues.IRuntimeConst { do { index = BitOperations.TrailingZeroCount(mask); - if (Contains(values, Unsafe.Add(ref cur, index))) + if (state.ConfirmProbabilisticMatch(Unsafe.Add(ref cur, index))) { return true; } @@ -605,7 +780,8 @@ private static bool TryFindMatch(ref char cur, uint mask, ReadOnlySpan val } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool TryFindMatchOverlapped(ref char cur, int searchSpaceLength, uint mask, ReadOnlySpan values, out int index) + private static bool TryFindMatchOverlappedAvx512(ref char cur, int searchSpaceLength, uint mask, ref ProbabilisticMapState state, out int index) + where TUseFastContains : struct, SearchValues.IRuntimeConst { do { @@ -618,7 +794,7 @@ private static bool TryFindMatchOverlapped(ref char cur, int searchSpaceLength, index += searchSpaceLength - (2 * Vector256.Count); } - if (Contains(values, Unsafe.Add(ref cur, index))) + if (state.ConfirmProbabilisticMatch(Unsafe.Add(ref cur, index))) { return true; } @@ -632,13 +808,14 @@ private static bool TryFindMatchOverlapped(ref char cur, int searchSpaceLength, } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool TryFindMatch(ref char cur, ulong mask, ReadOnlySpan values, out int index) + private static bool TryFindMatchAvx512(ref char cur, ulong mask, ref ProbabilisticMapState state, out int index) + where TUseFastContains : struct, SearchValues.IRuntimeConst { do { index = BitOperations.TrailingZeroCount(mask); - if (Contains(values, Unsafe.Add(ref cur, index))) + if (state.ConfirmProbabilisticMatch(Unsafe.Add(ref cur, index))) { return true; } @@ -652,7 +829,8 @@ private static bool TryFindMatch(ref char cur, ulong mask, ReadOnlySpan va } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool TryFindMatchOverlapped(ref char cur, int searchSpaceLength, ulong mask, ReadOnlySpan values, out int index) + private static bool TryFindMatchOverlappedAvx512(ref char cur, int searchSpaceLength, ulong mask, ref ProbabilisticMapState state, out int index) + where TUseFastContains : struct, SearchValues.IRuntimeConst { do { @@ -665,7 +843,7 @@ private static bool TryFindMatchOverlapped(ref char cur, int searchSpaceLength, index += searchSpaceLength - (2 * Vector512.Count); } - if (Contains(values, Unsafe.Add(ref cur, index))) + if (state.ConfirmProbabilisticMatch(Unsafe.Add(ref cur, index))) { return true; } @@ -678,6 +856,108 @@ private static bool TryFindMatchOverlapped(ref char cur, int searchSpaceLength, return false; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool TryFindLastMatch(ref char cur, uint mask, ref ProbabilisticMapState state, out int index) + where TUseFastContains : struct, SearchValues.IRuntimeConst + { + do + { + index = 31 - BitOperations.LeadingZeroCount(mask); + + if (state.ConfirmProbabilisticMatch(Unsafe.Add(ref cur, index))) + { + return true; + } + + // Clear the highest set bit + mask = BitOperations.FlipBit(mask, index); + } + while (mask != 0); + + index = 0; + return false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool TryFindLastMatchOverlappedAvx512(ref char cur, int searchSpaceLength, uint mask, ref ProbabilisticMapState state, out int index) + where TUseFastContains : struct, SearchValues.IRuntimeConst + { + do + { + index = 31 - BitOperations.LeadingZeroCount(mask); + + // Clear the highest set bit + mask = BitOperations.FlipBit(mask, index); + + if (index >= Vector256.Count) + { + // The potential match is in the second vector. + // Fixup the index to account for how we loaded the second overlapped vector. + index += searchSpaceLength - (2 * Vector256.Count); + } + + if (state.ConfirmProbabilisticMatch(Unsafe.Add(ref cur, index))) + { + return true; + } + } + while (mask != 0); + + index = 0; + return false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool TryFindLastMatchAvx512(ref char cur, ulong mask, ref ProbabilisticMapState state, out int index) + where TUseFastContains : struct, SearchValues.IRuntimeConst + { + do + { + index = 63 - BitOperations.LeadingZeroCount(mask); + + if (state.ConfirmProbabilisticMatch(Unsafe.Add(ref cur, index))) + { + return true; + } + + // Clear the highest set bit + mask = BitOperations.FlipBit(mask, index); + } + while (mask != 0); + + index = 0; + return false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool TryFindLastMatchOverlappedAvx512(ref char cur, int searchSpaceLength, ulong mask, ref ProbabilisticMapState state, out int index) + where TUseFastContains : struct, SearchValues.IRuntimeConst + { + do + { + index = 63 - BitOperations.LeadingZeroCount(mask); + + // Clear the highest set bit + mask = BitOperations.FlipBit(mask, index); + + if (index >= Vector512.Count) + { + // The potential match is in the second vector. + // Fixup the index to account for how we loaded the second overlapped vector. + index += searchSpaceLength - (2 * Vector512.Count); + } + + if (state.ConfirmProbabilisticMatch(Unsafe.Add(ref cur, index))) + { + return true; + } + } + while (mask != 0); + + index = 0; + return false; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int IndexOfAnySimpleLoop(ref char searchSpace, int searchSpaceLength, ReadOnlySpan values) where TNegator : struct, IndexOfAnyAsciiSearcher.INegator diff --git a/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMapState.cs b/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMapState.cs new file mode 100644 index 000000000000..c1631feabf80 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMapState.cs @@ -0,0 +1,310 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +#pragma warning disable CS8500 // Takes the address of a managed type + +namespace System.Buffers +{ + /// + /// Stores the state necessary to call vectorized members on , + /// as well as (optionally) a precomputed perfect hash table for faster single-character lookups/match confirmations. + /// When the hash table isn't available, the structure stores a pointer to the span of values in the set instead. + /// + internal unsafe struct ProbabilisticMapState + { + private const int MaxModulus = char.MaxValue + 1; + + public ProbabilisticMap Map; + + // Hash entries store each value from the set at the index determined by the remainder modulo the table size. + // As every value has a unique remainder, we can check if a value is contained in the set by checking + // _hashEntries[value % _hashEntries.Length] == value (see FastContains below). + // The multiplier is used for faster modulo operations when determining the hash table index. + // Exactly one of _hashEntries and _slowContainsValuesPtr may be initialized at the same time. + private readonly uint _multiplier; + private readonly char[]? _hashEntries; + private readonly ReadOnlySpan* _slowContainsValuesPtr; + + public ProbabilisticMapState(ReadOnlySpan values, int maxInclusive) + { + Debug.Assert(!values.IsEmpty); + + Map = new ProbabilisticMap(values); + + uint modulus = FindModulus(values, maxInclusive); + _multiplier = GetFastModMultiplier(modulus); + _hashEntries = new char[modulus]; + + // Some hash entries will remain unused. + // We can't leave them uninitialized as we would otherwise erroneously match (char)0. + // The exact value doesn't matter, as long as it's in the set of our values. + _hashEntries.AsSpan().Fill(values[0]); + + foreach (char c in values) + { + _hashEntries[FastMod(c, modulus, _multiplier)] = c; + } + } + + // valuesPtr must remain valid for as long as this ProbabilisticMapState is used. + public unsafe ProbabilisticMapState(ReadOnlySpan* valuesPtr) + { + Debug.Assert((IntPtr)valuesPtr != IntPtr.Zero); + + Map = new ProbabilisticMap(*valuesPtr); + _slowContainsValuesPtr = valuesPtr; + } + + public char[] GetValues() + { + Debug.Assert(_hashEntries is not null); + + var unique = new HashSet(_hashEntries); + char[] values = new char[unique.Count]; + unique.CopyTo(values); + return values; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool FastContains(char value) + { + Debug.Assert(_hashEntries is not null); + Debug.Assert((IntPtr)_slowContainsValuesPtr == IntPtr.Zero); + + return FastContains(_hashEntries, _multiplier, value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool FastContains(char[] hashEntries, uint multiplier, char value) + { + ulong offset = FastMod(value, (uint)hashEntries.Length, multiplier); + Debug.Assert(offset < (ulong)hashEntries.Length); + + return Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(hashEntries), (nuint)offset) == value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private bool SlowProbabilisticContains(char value) + { + Debug.Assert(_hashEntries is null); + Debug.Assert((IntPtr)_slowContainsValuesPtr != IntPtr.Zero); + + return ProbabilisticMap.Contains( + ref Unsafe.As(ref Map), + *_slowContainsValuesPtr, + value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private bool SlowContains(char value) + { + Debug.Assert(_hashEntries is null); + Debug.Assert((IntPtr)_slowContainsValuesPtr != IntPtr.Zero); + + return ProbabilisticMap.Contains(*_slowContainsValuesPtr, value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool ConfirmProbabilisticMatch(char value) + where TUseFastContains : struct, SearchValues.IRuntimeConst + { + if (TUseFastContains.Value) + { + return FastContains(value); + } + else + { + // We use SlowContains instead of SlowProbabilisticContains here as we've already checked + // the value against the probabilistic filter and are now confirming the potential match. + return SlowContains(value); + } + } + + /// Finds a modulus where remainders for all values in the set are unique. + private static uint FindModulus(ReadOnlySpan values, int maxInclusive) + { + Debug.Assert(maxInclusive <= char.MaxValue); + + int modulus = HashHelpers.GetPrime(values.Length); + bool removedDuplicates = false; + + if (modulus >= maxInclusive) + { + return (uint)(maxInclusive + 1); + } + + while (true) + { + if (modulus >= maxInclusive) + { + // Try to remove duplicates and try again. + if (!removedDuplicates && TryRemoveDuplicates(values, out char[]? deduplicated)) + { + removedDuplicates = true; + values = deduplicated; + modulus = HashHelpers.GetPrime(values.Length); + continue; + } + + return (uint)(maxInclusive + 1); + } + + if (TestModulus(values, modulus)) + { + return (uint)modulus; + } + + modulus = HashHelpers.GetPrime(modulus + 1); + } + + static bool TestModulus(ReadOnlySpan values, int modulus) + { + Debug.Assert(modulus < MaxModulus); + + bool[] seen = ArrayPool.Shared.Rent(modulus); + seen.AsSpan(0, modulus).Clear(); + + uint multiplier = GetFastModMultiplier((uint)modulus); + + foreach (char c in values) + { + ulong index = FastMod(c, (uint)modulus, multiplier); + + if (seen[index]) + { + ArrayPool.Shared.Return(seen); + return false; + } + + seen[index] = true; + } + + // Saw no duplicates. + ArrayPool.Shared.Return(seen); + return true; + } + + static bool TryRemoveDuplicates(ReadOnlySpan values, [NotNullWhen(true)] out char[]? deduplicated) + { + HashSet unique = [.. values]; + + if (unique.Count == values.Length) + { + deduplicated = null; + return false; + } + + deduplicated = new char[unique.Count]; + unique.CopyTo(deduplicated); + return true; + } + } + + // This is a variant of HashHelpers.GetFastModMultiplier, specialized for smaller divisors (<= 65536). + private static uint GetFastModMultiplier(uint divisor) + { + Debug.Assert(divisor > 0); + Debug.Assert(divisor <= MaxModulus); + + return uint.MaxValue / divisor + 1; + } + + // This is a faster variant of HashHelpers.FastMod, specialized for smaller divisors (<= 65536). + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static ulong FastMod(char value, uint divisor, uint multiplier) + { + Debug.Assert(multiplier == GetFastModMultiplier(divisor)); + + ulong result = ((ulong)(multiplier * value) * divisor) >> 32; + + Debug.Assert(result == (value % divisor)); + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOfAnySimpleLoop(ref char searchSpace, int searchSpaceLength, ref ProbabilisticMapState state) + where TUseFastContains : struct, SearchValues.IRuntimeConst + where TNegator : struct, IndexOfAnyAsciiSearcher.INegator + { + ref char searchSpaceEnd = ref Unsafe.Add(ref searchSpace, searchSpaceLength); + ref char cur = ref searchSpace; + + if (TUseFastContains.Value) + { + Debug.Assert(state._hashEntries is not null); + + char[] hashEntries = state._hashEntries; + uint multiplier = state._multiplier; + + while (!Unsafe.AreSame(ref cur, ref searchSpaceEnd)) + { + char c = cur; + if (TNegator.NegateIfNeeded(FastContains(hashEntries, multiplier, c))) + { + return (int)((nuint)Unsafe.ByteOffset(ref searchSpace, ref cur) / sizeof(char)); + } + + cur = ref Unsafe.Add(ref cur, 1); + } + } + else + { + while (!Unsafe.AreSame(ref cur, ref searchSpaceEnd)) + { + char c = cur; + if (TNegator.NegateIfNeeded(state.SlowProbabilisticContains(c))) + { + return (int)((nuint)Unsafe.ByteOffset(ref searchSpace, ref cur) / sizeof(char)); + } + + cur = ref Unsafe.Add(ref cur, 1); + } + } + + return -1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOfAnySimpleLoop(ref char searchSpace, int searchSpaceLength, ref ProbabilisticMapState state) + where TUseFastContains : struct, SearchValues.IRuntimeConst + where TNegator : struct, IndexOfAnyAsciiSearcher.INegator + { + if (TUseFastContains.Value) + { + Debug.Assert(state._hashEntries is not null); + + char[] hashEntries = state._hashEntries; + uint multiplier = state._multiplier; + + while (--searchSpaceLength >= 0) + { + char c = Unsafe.Add(ref searchSpace, searchSpaceLength); + if (TNegator.NegateIfNeeded(FastContains(hashEntries, multiplier, c))) + { + break; + } + } + } + else + { + while (--searchSpaceLength >= 0) + { + char c = Unsafe.Add(ref searchSpace, searchSpaceLength); + if (TNegator.NegateIfNeeded(state.SlowProbabilisticContains(c))) + { + break; + } + } + } + + return searchSpaceLength; + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticWithAsciiCharSearchValues.cs b/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticWithAsciiCharSearchValues.cs index b9b9227aa3ff..7b05c3f8a3b7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticWithAsciiCharSearchValues.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticWithAsciiCharSearchValues.cs @@ -15,10 +15,9 @@ internal sealed class ProbabilisticWithAsciiCharSearchValues : S { private IndexOfAnyAsciiSearcher.AsciiState _asciiState; private IndexOfAnyAsciiSearcher.AsciiState _inverseAsciiState; - private ProbabilisticMap _map; - private readonly string _values; + private ProbabilisticMapState _map; - public ProbabilisticWithAsciiCharSearchValues(scoped ReadOnlySpan values) + public ProbabilisticWithAsciiCharSearchValues(ReadOnlySpan values, int maxInclusive) { Debug.Assert(IndexOfAnyAsciiSearcher.IsVectorizationSupported); Debug.Assert(values.ContainsAnyInRange((char)0, (char)127)); @@ -26,15 +25,15 @@ public ProbabilisticWithAsciiCharSearchValues(scoped ReadOnlySpan values) IndexOfAnyAsciiSearcher.ComputeAsciiState(values, out _asciiState); _inverseAsciiState = _asciiState.CreateInverse(); - _values = new string(values); - _map = new ProbabilisticMap(_values); + _map = new ProbabilisticMapState(values, maxInclusive); } - internal override char[] GetValues() => _values.ToCharArray(); + internal override char[] GetValues() => + _map.GetValues(); [MethodImpl(MethodImplOptions.AggressiveInlining)] internal override bool ContainsCore(char value) => - ProbabilisticMap.Contains(ref Unsafe.As(ref _map), _values, value); + _map.FastContains(value); internal override int IndexOfAny(ReadOnlySpan span) { @@ -83,11 +82,10 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span = span.Slice(offset); } - int index = ProbabilisticMap.IndexOfAny( - ref Unsafe.As(ref _map), + int index = ProbabilisticMap.IndexOfAny( ref MemoryMarshal.GetReference(span), span.Length, - _values); + ref _map); if (index >= 0) { @@ -122,10 +120,10 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span = span.Slice(offset); } - int index = ProbabilisticMap.IndexOfAnySimpleLoop( + int index = ProbabilisticMapState.IndexOfAnySimpleLoop( ref MemoryMarshal.GetReference(span), span.Length, - _values); + ref _map); if (index >= 0) { @@ -183,11 +181,10 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span = span.Slice(0, offset + 1); } - return ProbabilisticMap.LastIndexOfAny( - ref Unsafe.As(ref _map), + return ProbabilisticMap.LastIndexOfAny( ref MemoryMarshal.GetReference(span), span.Length, - _values); + ref _map); } internal override int LastIndexOfAnyExcept(ReadOnlySpan span) @@ -212,10 +209,10 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span = span.Slice(0, offset + 1); } - return ProbabilisticMap.LastIndexOfAnySimpleLoop( + return ProbabilisticMapState.LastIndexOfAnySimpleLoop( ref MemoryMarshal.GetReference(span), span.Length, - _values); + ref _map); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/SearchValues/SearchValues.cs b/src/libraries/System.Private.CoreLib/src/System/SearchValues/SearchValues.cs index 3c1805afdf61..6e08d95d2e40 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SearchValues/SearchValues.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/SearchValues.cs @@ -3,9 +3,7 @@ using System.Diagnostics; using System.Numerics; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.Wasm; using System.Runtime.Intrinsics.X86; @@ -159,36 +157,52 @@ public static SearchValues Create(ReadOnlySpan values) return new Any5SearchValues(shortValues); } - scoped ReadOnlySpan probabilisticValues = values; - - if (Vector128.IsHardwareAccelerated && values.Length < 8) - { - // ProbabilisticMap does a Span.Contains check to confirm potential matches. - // If we have fewer than 8 values, pad them with existing ones to make the verification faster. - Span newValues = stackalloc char[8]; - newValues.Fill(values[0]); - values.CopyTo(newValues); - probabilisticValues = newValues; - } - if (IndexOfAnyAsciiSearcher.IsVectorizationSupported && minInclusive < 128) { // If we have both ASCII and non-ASCII characters, use an implementation that // does an optimistic ASCII fast-path and then falls back to the ProbabilisticMap. - return (Ssse3.IsSupported || PackedSimd.IsSupported) && probabilisticValues.Contains('\0') - ? new ProbabilisticWithAsciiCharSearchValues(probabilisticValues) - : new ProbabilisticWithAsciiCharSearchValues(probabilisticValues); + return (Ssse3.IsSupported || PackedSimd.IsSupported) && values.Contains('\0') + ? new ProbabilisticWithAsciiCharSearchValues(values, maxInclusive) + : new ProbabilisticWithAsciiCharSearchValues(values, maxInclusive); } - // We prefer using the ProbabilisticMap over Latin1CharSearchValues if the former is vectorized. - if (!(Sse41.IsSupported || AdvSimd.Arm64.IsSupported) && maxInclusive < 256) + if (ShouldUseProbabilisticMap(values.Length, maxInclusive)) { - // This will also match ASCII values when IndexOfAnyAsciiSearcher is not supported. - return new Latin1CharSearchValues(values); + return new ProbabilisticCharSearchValues(values, maxInclusive); } - return new ProbabilisticCharSearchValues(probabilisticValues); + // This will also match ASCII values when IndexOfAnyAsciiSearcher is not supported. + return new BitmapCharSearchValues(values, maxInclusive); + + static bool ShouldUseProbabilisticMap(int valuesLength, int maxInclusive) + { + // *Rough estimates*. The current implementation uses 256 bits for the bloom filter. + // If the implementation is vectorized we can get away with a decent false positive rate. + const int MaxValuesForProbabilisticMap = 256; + + if (valuesLength > MaxValuesForProbabilisticMap) + { + // If the number of values is too high, we won't see any benefits from the 'probabilistic' part. + return false; + } + + if (Sse41.IsSupported || AdvSimd.Arm64.IsSupported) + { + // If the probabilistic map is vectorized, we prefer it. + return true; + } + + // The probabilistic map is more memory efficient for spare sets, while the bitmap is more efficient for dense sets. + int bitmapFootprintBytesEstimate = 64 + (maxInclusive / 8); + int probabilisticFootprintBytesEstimate = 128 + (valuesLength * 4); + + // The bitmap is a bit faster than the perfect hash checks employed by the probabilistic map. + // Sacrifice some memory usage for faster lookups. + const int AcceptableSizeMultiplier = 2; + + return AcceptableSizeMultiplier * probabilisticFootprintBytesEstimate < bitmapFootprintBytesEstimate; + } } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Single.cs b/src/libraries/System.Private.CoreLib/src/System/Single.cs index 9cc7c6b56c0a..88c923892309 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Single.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Single.cs @@ -650,6 +650,28 @@ public static bool IsPow2(float value) [Intrinsic] public static float Ceiling(float x) => MathF.Ceiling(x); + /// + [Intrinsic] + public static TInteger ConvertToInteger(float value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + [Intrinsic] + public static TInteger ConvertToIntegerNative(float value) + where TInteger : IBinaryInteger + { +#if !MONO + if (typeof(TInteger).IsPrimitive) + { + // We need this to be recursive so indirect calls (delegates + // for example) produce the same result as direct invocation + return ConvertToIntegerNative(value); + } +#endif + + return TInteger.CreateSaturating(value); + } + /// [Intrinsic] public static float Floor(float x) => MathF.Floor(x); @@ -838,9 +860,11 @@ bool IFloatingPoint.TryWriteSignificandLittleEndian(Span destinatio public static float Lerp(float value1, float value2, float amount) => (value1 * (1.0f - amount)) + (value2 * amount); /// + [Intrinsic] public static float ReciprocalEstimate(float x) => MathF.ReciprocalEstimate(x); /// + [Intrinsic] public static float ReciprocalSqrtEstimate(float x) => MathF.ReciprocalSqrtEstimate(x); /// @@ -1175,6 +1199,19 @@ public static float MinMagnitudeNumber(float x, float y) return y; } + + + /// + [Intrinsic] + public static float MultiplyAddEstimate(float left, float right, float addend) + { +#if MONO + return (left * right) + addend; +#else + return MultiplyAddEstimate(left, right, addend); +#endif + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out float result) diff --git a/src/libraries/System.Private.CoreLib/src/System/Span.cs b/src/libraries/System.Private.CoreLib/src/System/Span.cs index 38b94e872b0c..691b2eb558f3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Span.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Span.cs @@ -9,7 +9,7 @@ using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute; using EditorBrowsableState = System.ComponentModel.EditorBrowsableState; -#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span.Equals(object)' overrides non-obsolete member 'object.Equals(object)' +#pragma warning disable 0809 // Obsolete member 'Span.Equals(object)' overrides non-obsolete member 'object.Equals(object)' #pragma warning disable 8500 // address / sizeof of managed types namespace System diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs index b4aa563b2774..c4831969ccb0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs @@ -58,56 +58,56 @@ internal static unsafe void Memmove(ref byte dest, ref byte src, nuint len) // Copy bytes which are multiples of 16 and leave the remainder for MCPY01 to handle. Debug.Assert(len > 16 && len <= 64); #if HAS_CUSTOM_BLOCKS - Unsafe.As(ref dest) = Unsafe.As(ref src); // [0,16] + Unsafe.WriteUnaligned(ref dest, Unsafe.ReadUnaligned(ref src)); #elif TARGET_64BIT - Unsafe.As(ref dest) = Unsafe.As(ref src); - Unsafe.As(ref Unsafe.Add(ref dest, 8)) = Unsafe.As(ref Unsafe.Add(ref src, 8)); // [0,16] + Unsafe.WriteUnaligned(ref dest, Unsafe.ReadUnaligned(ref src)); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 8), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 8))); #else - Unsafe.As(ref dest) = Unsafe.As(ref src); - Unsafe.As(ref Unsafe.Add(ref dest, 4)) = Unsafe.As(ref Unsafe.Add(ref src, 4)); - Unsafe.As(ref Unsafe.Add(ref dest, 8)) = Unsafe.As(ref Unsafe.Add(ref src, 8)); - Unsafe.As(ref Unsafe.Add(ref dest, 12)) = Unsafe.As(ref Unsafe.Add(ref src, 12)); // [0,16] + Unsafe.WriteUnaligned(ref dest, Unsafe.ReadUnaligned(ref src)); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 4), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 4))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 8), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 8))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 12), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 12))); #endif if (len <= 32) goto MCPY01; #if HAS_CUSTOM_BLOCKS - Unsafe.As(ref Unsafe.Add(ref dest, 16)) = Unsafe.As(ref Unsafe.Add(ref src, 16)); // [0,32] + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 16), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 16))); #elif TARGET_64BIT - Unsafe.As(ref Unsafe.Add(ref dest, 16)) = Unsafe.As(ref Unsafe.Add(ref src, 16)); - Unsafe.As(ref Unsafe.Add(ref dest, 24)) = Unsafe.As(ref Unsafe.Add(ref src, 24)); // [0,32] + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 16), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 16))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 24), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 24))); #else - Unsafe.As(ref Unsafe.Add(ref dest, 16)) = Unsafe.As(ref Unsafe.Add(ref src, 16)); - Unsafe.As(ref Unsafe.Add(ref dest, 20)) = Unsafe.As(ref Unsafe.Add(ref src, 20)); - Unsafe.As(ref Unsafe.Add(ref dest, 24)) = Unsafe.As(ref Unsafe.Add(ref src, 24)); - Unsafe.As(ref Unsafe.Add(ref dest, 28)) = Unsafe.As(ref Unsafe.Add(ref src, 28)); // [0,32] + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 16), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 16))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 20), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 20))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 24), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 24))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 28), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 28))); #endif if (len <= 48) goto MCPY01; #if HAS_CUSTOM_BLOCKS - Unsafe.As(ref Unsafe.Add(ref dest, 32)) = Unsafe.As(ref Unsafe.Add(ref src, 32)); // [0,48] + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 32), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 32))); #elif TARGET_64BIT - Unsafe.As(ref Unsafe.Add(ref dest, 32)) = Unsafe.As(ref Unsafe.Add(ref src, 32)); - Unsafe.As(ref Unsafe.Add(ref dest, 40)) = Unsafe.As(ref Unsafe.Add(ref src, 40)); // [0,48] + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 32), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 32))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 40), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 40))); #else - Unsafe.As(ref Unsafe.Add(ref dest, 32)) = Unsafe.As(ref Unsafe.Add(ref src, 32)); - Unsafe.As(ref Unsafe.Add(ref dest, 36)) = Unsafe.As(ref Unsafe.Add(ref src, 36)); - Unsafe.As(ref Unsafe.Add(ref dest, 40)) = Unsafe.As(ref Unsafe.Add(ref src, 40)); - Unsafe.As(ref Unsafe.Add(ref dest, 44)) = Unsafe.As(ref Unsafe.Add(ref src, 44)); // [0,48] + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 32), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 32))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 36), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 36))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 40), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 40))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 44), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 44))); #endif MCPY01: // Unconditionally copy the last 16 bytes using destEnd and srcEnd and return. Debug.Assert(len > 16 && len <= 64); #if HAS_CUSTOM_BLOCKS - Unsafe.As(ref Unsafe.Add(ref destEnd, -16)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -16)); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -16), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -16))); #elif TARGET_64BIT - Unsafe.As(ref Unsafe.Add(ref destEnd, -16)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -16)); - Unsafe.As(ref Unsafe.Add(ref destEnd, -8)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -8)); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -16), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -16))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -8), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -8))); #else - Unsafe.As(ref Unsafe.Add(ref destEnd, -16)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -16)); - Unsafe.As(ref Unsafe.Add(ref destEnd, -12)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -12)); - Unsafe.As(ref Unsafe.Add(ref destEnd, -8)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -8)); - Unsafe.As(ref Unsafe.Add(ref destEnd, -4)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -4)); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -16), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -16))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -12), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -12))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -8), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -8))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -4), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -4))); #endif return; @@ -117,13 +117,13 @@ internal static unsafe void Memmove(ref byte dest, ref byte src, nuint len) goto MCPY03; Debug.Assert(len >= 8 && len <= 16); #if TARGET_64BIT - Unsafe.As(ref dest) = Unsafe.As(ref src); - Unsafe.As(ref Unsafe.Add(ref destEnd, -8)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -8)); + Unsafe.WriteUnaligned(ref dest, Unsafe.ReadUnaligned(ref src)); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -8), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -8))); #else - Unsafe.As(ref dest) = Unsafe.As(ref src); - Unsafe.As(ref Unsafe.Add(ref dest, 4)) = Unsafe.As(ref Unsafe.Add(ref src, 4)); - Unsafe.As(ref Unsafe.Add(ref destEnd, -8)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -8)); - Unsafe.As(ref Unsafe.Add(ref destEnd, -4)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -4)); + Unsafe.WriteUnaligned(ref dest, Unsafe.ReadUnaligned(ref src)); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 4), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 4))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -8), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -8))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -4), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -4))); #endif return; @@ -132,8 +132,8 @@ internal static unsafe void Memmove(ref byte dest, ref byte src, nuint len) if ((len & 4) == 0) goto MCPY04; Debug.Assert(len >= 4 && len < 8); - Unsafe.As(ref dest) = Unsafe.As(ref src); - Unsafe.As(ref Unsafe.Add(ref destEnd, -4)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -4)); + Unsafe.WriteUnaligned(ref dest, Unsafe.ReadUnaligned(ref src)); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -4), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -4))); return; MCPY04: @@ -144,7 +144,7 @@ internal static unsafe void Memmove(ref byte dest, ref byte src, nuint len) dest = src; if ((len & 2) == 0) return; - Unsafe.As(ref Unsafe.Add(ref destEnd, -2)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -2)); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -2), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -2))); return; MCPY05: @@ -163,7 +163,7 @@ internal static unsafe void Memmove(ref byte dest, ref byte src, nuint len) // dest is more important to align than src because an unaligned store is more expensive // than an unaligned load. nuint misalignedElements = 64 - Unsafe.OpportunisticMisalignment(ref dest, 64); - Unsafe.As(ref dest) = Unsafe.As(ref src); + Unsafe.WriteUnaligned(ref dest, Unsafe.ReadUnaligned(ref src)); src = ref Unsafe.Add(ref src, misalignedElements); dest = ref Unsafe.Add(ref dest, misalignedElements); len -= misalignedElements; @@ -177,33 +177,33 @@ internal static unsafe void Memmove(ref byte dest, ref byte src, nuint len) MCPY06: #if HAS_CUSTOM_BLOCKS - Unsafe.As(ref dest) = Unsafe.As(ref src); + Unsafe.WriteUnaligned(ref dest, Unsafe.ReadUnaligned(ref src)); #elif TARGET_64BIT - Unsafe.As(ref dest) = Unsafe.As(ref src); - Unsafe.As(ref Unsafe.Add(ref dest, 8)) = Unsafe.As(ref Unsafe.Add(ref src, 8)); - Unsafe.As(ref Unsafe.Add(ref dest, 16)) = Unsafe.As(ref Unsafe.Add(ref src, 16)); - Unsafe.As(ref Unsafe.Add(ref dest, 24)) = Unsafe.As(ref Unsafe.Add(ref src, 24)); - Unsafe.As(ref Unsafe.Add(ref dest, 32)) = Unsafe.As(ref Unsafe.Add(ref src, 32)); - Unsafe.As(ref Unsafe.Add(ref dest, 40)) = Unsafe.As(ref Unsafe.Add(ref src, 40)); - Unsafe.As(ref Unsafe.Add(ref dest, 48)) = Unsafe.As(ref Unsafe.Add(ref src, 48)); - Unsafe.As(ref Unsafe.Add(ref dest, 56)) = Unsafe.As(ref Unsafe.Add(ref src, 56)); + Unsafe.WriteUnaligned(ref dest, Unsafe.ReadUnaligned(ref src)); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 8), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 8))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 16), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 16))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 24), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 24))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 32), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 32))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 40), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 40))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 48), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 48))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 56), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 56))); #else - Unsafe.As(ref dest) = Unsafe.As(ref src); - Unsafe.As(ref Unsafe.Add(ref dest, 4)) = Unsafe.As(ref Unsafe.Add(ref src, 4)); - Unsafe.As(ref Unsafe.Add(ref dest, 8)) = Unsafe.As(ref Unsafe.Add(ref src, 8)); - Unsafe.As(ref Unsafe.Add(ref dest, 12)) = Unsafe.As(ref Unsafe.Add(ref src, 12)); - Unsafe.As(ref Unsafe.Add(ref dest, 16)) = Unsafe.As(ref Unsafe.Add(ref src, 16)); - Unsafe.As(ref Unsafe.Add(ref dest, 20)) = Unsafe.As(ref Unsafe.Add(ref src, 20)); - Unsafe.As(ref Unsafe.Add(ref dest, 24)) = Unsafe.As(ref Unsafe.Add(ref src, 24)); - Unsafe.As(ref Unsafe.Add(ref dest, 28)) = Unsafe.As(ref Unsafe.Add(ref src, 28)); - Unsafe.As(ref Unsafe.Add(ref dest, 32)) = Unsafe.As(ref Unsafe.Add(ref src, 32)); - Unsafe.As(ref Unsafe.Add(ref dest, 36)) = Unsafe.As(ref Unsafe.Add(ref src, 36)); - Unsafe.As(ref Unsafe.Add(ref dest, 40)) = Unsafe.As(ref Unsafe.Add(ref src, 40)); - Unsafe.As(ref Unsafe.Add(ref dest, 44)) = Unsafe.As(ref Unsafe.Add(ref src, 44)); - Unsafe.As(ref Unsafe.Add(ref dest, 48)) = Unsafe.As(ref Unsafe.Add(ref src, 48)); - Unsafe.As(ref Unsafe.Add(ref dest, 52)) = Unsafe.As(ref Unsafe.Add(ref src, 52)); - Unsafe.As(ref Unsafe.Add(ref dest, 56)) = Unsafe.As(ref Unsafe.Add(ref src, 56)); - Unsafe.As(ref Unsafe.Add(ref dest, 60)) = Unsafe.As(ref Unsafe.Add(ref src, 60)); + Unsafe.WriteUnaligned(ref dest, Unsafe.ReadUnaligned(ref src)); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 4), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 4))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 8), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 8))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 12), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 12))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 16), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 16))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 20), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 20))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 24), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 24))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 28), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 28))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 32), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 32))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 36), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 36))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 40), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 40))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 44), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 44))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 48), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 48))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 52), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 52))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 56), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 56))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, 60), Unsafe.ReadUnaligned(ref Unsafe.Add(ref src, 60))); #endif dest = ref Unsafe.Add(ref dest, 64); src = ref Unsafe.Add(ref src, 64); @@ -215,15 +215,15 @@ internal static unsafe void Memmove(ref byte dest, ref byte src, nuint len) if (len > 16) goto MCPY00; #if HAS_CUSTOM_BLOCKS - Unsafe.As(ref Unsafe.Add(ref destEnd, -16)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -16)); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -16), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -16))); #elif TARGET_64BIT - Unsafe.As(ref Unsafe.Add(ref destEnd, -16)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -16)); - Unsafe.As(ref Unsafe.Add(ref destEnd, -8)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -8)); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -16), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -16))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -8), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -8))); #else - Unsafe.As(ref Unsafe.Add(ref destEnd, -16)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -16)); - Unsafe.As(ref Unsafe.Add(ref destEnd, -12)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -12)); - Unsafe.As(ref Unsafe.Add(ref destEnd, -8)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -8)); - Unsafe.As(ref Unsafe.Add(ref destEnd, -4)) = Unsafe.As(ref Unsafe.Add(ref srcEnd, -4)); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -16), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -16))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -12), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -12))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -8), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -8))); + Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -4), Unsafe.ReadUnaligned(ref Unsafe.Add(ref srcEnd, -4))); #endif return; diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Packed.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Packed.cs index 37f90c695090..70d4e22acb5c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Packed.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Packed.cs @@ -7,7 +7,6 @@ using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; - #pragma warning disable 8500 // sizeof of managed types namespace System @@ -28,7 +27,7 @@ public static unsafe bool CanUsePackedIndexOf(T value) Debug.Assert(RuntimeHelpers.IsBitwiseEquatable()); Debug.Assert(sizeof(T) == sizeof(ushort)); - return *(ushort*)&value - 1u < 254u; + return Unsafe.BitCast(value) - 1u < 254u; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs index ee378b7646b5..9ef07d114da6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs @@ -5,10 +5,8 @@ using System.Diagnostics; using System.Numerics; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using System.Runtime.Intrinsics; - #pragma warning disable 8500 // sizeof of managed types namespace System @@ -226,7 +224,7 @@ public static int IndexOf(ref T searchSpace, int searchSpaceLength, ref T val } // Adapted from IndexOf(...) - public static unsafe bool Contains(ref T searchSpace, T value, int length) where T : IEquatable? + public static bool Contains(ref T searchSpace, T value, int length) where T : IEquatable? { Debug.Assert(length >= 0); @@ -298,7 +296,7 @@ public static unsafe bool Contains(ref T searchSpace, T value, int length) wh return true; } - public static unsafe int IndexOf(ref T searchSpace, T value, int length) where T : IEquatable? + public static int IndexOf(ref T searchSpace, T value, int length) where T : IEquatable? { Debug.Assert(length >= 0); @@ -1305,11 +1303,11 @@ public static int SequenceCompareTo(ref T first, int firstLength, ref T secon } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static unsafe bool ContainsValueType(ref T searchSpace, T value, int length) where T : struct, INumber + internal static bool ContainsValueType(ref T searchSpace, T value, int length) where T : struct, INumber { if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(T) == typeof(short) && PackedSpanHelpers.CanUsePackedIndexOf(value)) { - return PackedSpanHelpers.Contains(ref Unsafe.As(ref searchSpace), *(short*)&value, length); + return PackedSpanHelpers.Contains(ref Unsafe.As(ref searchSpace), Unsafe.BitCast(value), length); } return NonPackedContainsValueType(ref searchSpace, value, length); @@ -1479,15 +1477,15 @@ internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value, int => IndexOfValueType>(ref searchSpace, value, length); [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static unsafe int IndexOfValueType(ref TValue searchSpace, TValue value, int length) + private static int IndexOfValueType(ref TValue searchSpace, TValue value, int length) where TValue : struct, INumber where TNegator : struct, INegator { if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(TValue) == typeof(short) && PackedSpanHelpers.CanUsePackedIndexOf(value)) { return typeof(TNegator) == typeof(DontNegate) - ? PackedSpanHelpers.IndexOf(ref Unsafe.As(ref searchSpace), *(char*)&value, length) - : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As(ref searchSpace), *(char*)&value, length); + ? PackedSpanHelpers.IndexOf(ref Unsafe.As(ref searchSpace), Unsafe.BitCast(value), length) + : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As(ref searchSpace), Unsafe.BitCast(value), length); } return NonPackedIndexOfValueType(ref searchSpace, value, length); @@ -1666,24 +1664,33 @@ internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value0, T => IndexOfAnyValueType>(ref searchSpace, value0, value1, length); [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static unsafe int IndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, int length) + private static int IndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, int length) where TValue : struct, INumber where TNegator : struct, INegator { if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(TValue) == typeof(short) && PackedSpanHelpers.CanUsePackedIndexOf(value0) && PackedSpanHelpers.CanUsePackedIndexOf(value1)) { - if ((*(char*)&value0 ^ *(char*)&value1) == 0x20) + char char0 = Unsafe.BitCast(value0); + char char1 = Unsafe.BitCast(value1); + + if (RuntimeHelpers.IsKnownConstant(value0) && RuntimeHelpers.IsKnownConstant(value1)) { - char lowerCase = (char)Math.Max(*(char*)&value0, *(char*)&value1); + // If the values differ only in the 0x20 bit, we can optimize the search by reducing the number of comparisons. + // This optimization only applies to a small subset of values and the throughput difference is not too significant. + // We avoid introducing per-call overhead for non-constant values by guarding this optimization behind RuntimeHelpers.IsKnownConstant. + if ((char0 ^ char1) == 0x20) + { + char lowerCase = (char)Math.Max(char0, char1); - return typeof(TNegator) == typeof(DontNegate) - ? PackedSpanHelpers.IndexOfAnyIgnoreCase(ref Unsafe.As(ref searchSpace), lowerCase, length) - : PackedSpanHelpers.IndexOfAnyExceptIgnoreCase(ref Unsafe.As(ref searchSpace), lowerCase, length); + return typeof(TNegator) == typeof(DontNegate) + ? PackedSpanHelpers.IndexOfAnyIgnoreCase(ref Unsafe.As(ref searchSpace), lowerCase, length) + : PackedSpanHelpers.IndexOfAnyExceptIgnoreCase(ref Unsafe.As(ref searchSpace), lowerCase, length); + } } return typeof(TNegator) == typeof(DontNegate) - ? PackedSpanHelpers.IndexOfAny(ref Unsafe.As(ref searchSpace), *(char*)&value0, *(char*)&value1, length) - : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As(ref searchSpace), *(char*)&value0, *(char*)&value1, length); + ? PackedSpanHelpers.IndexOfAny(ref Unsafe.As(ref searchSpace), char0, char1, length) + : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As(ref searchSpace), char0, char1, length); } return NonPackedIndexOfAnyValueType(ref searchSpace, value0, value1, length); @@ -1883,15 +1890,15 @@ internal static int IndexOfAnyExceptValueType(ref T searchSpace, T value0, T => IndexOfAnyValueType>(ref searchSpace, value0, value1, value2, length); [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static unsafe int IndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, TValue value2, int length) + private static int IndexOfAnyValueType(ref TValue searchSpace, TValue value0, TValue value1, TValue value2, int length) where TValue : struct, INumber where TNegator : struct, INegator { if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(TValue) == typeof(short) && PackedSpanHelpers.CanUsePackedIndexOf(value0) && PackedSpanHelpers.CanUsePackedIndexOf(value1) && PackedSpanHelpers.CanUsePackedIndexOf(value2)) { return typeof(TNegator) == typeof(DontNegate) - ? PackedSpanHelpers.IndexOfAny(ref Unsafe.As(ref searchSpace), *(char*)&value0, *(char*)&value1, *(char*)&value2, length) - : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As(ref searchSpace), *(char*)&value0, *(char*)&value1, *(char*)&value2, length); + ? PackedSpanHelpers.IndexOfAny(ref Unsafe.As(ref searchSpace), Unsafe.BitCast(value0), Unsafe.BitCast(value1), Unsafe.BitCast(value2), length) + : PackedSpanHelpers.IndexOfAnyExcept(ref Unsafe.As(ref searchSpace), Unsafe.BitCast(value0), Unsafe.BitCast(value1), Unsafe.BitCast(value2), length); } return NonPackedIndexOfAnyValueType(ref searchSpace, value0, value1, value2, length); @@ -3467,15 +3474,15 @@ internal static int IndexOfAnyExceptInRangeUnsignedNumber(ref T searchSpace, IndexOfAnyInRangeUnsignedNumber>(ref searchSpace, lowInclusive, highInclusive, length); [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static unsafe int IndexOfAnyInRangeUnsignedNumber(ref T searchSpace, T lowInclusive, T highInclusive, int length) + private static int IndexOfAnyInRangeUnsignedNumber(ref T searchSpace, T lowInclusive, T highInclusive, int length) where T : struct, IUnsignedNumber, IComparisonOperators where TNegator : struct, INegator { if (PackedSpanHelpers.PackedIndexOfIsSupported && typeof(T) == typeof(ushort) && PackedSpanHelpers.CanUsePackedIndexOf(lowInclusive) && PackedSpanHelpers.CanUsePackedIndexOf(highInclusive) && highInclusive >= lowInclusive) { ref char charSearchSpace = ref Unsafe.As(ref searchSpace); - char charLowInclusive = *(char*)&lowInclusive; - char charRange = (char)(*(char*)&highInclusive - charLowInclusive); + char charLowInclusive = Unsafe.BitCast(lowInclusive); + char charRange = (char)(Unsafe.BitCast(highInclusive) - charLowInclusive); return typeof(TNegator) == typeof(DontNegate) ? PackedSpanHelpers.IndexOfAnyInRange(ref charSearchSpace, charLowInclusive, charRange, length) diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs index 7f4f642526d4..3d421f35d99a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs @@ -62,10 +62,19 @@ public static string Concat(object? arg0, object? arg1, object? arg2) => public static string Concat(params object?[] args) { ArgumentNullException.ThrowIfNull(args); + return Concat((ReadOnlySpan)args); + } + /// + /// Concatenates the string representations of the elements in a specified span of objects. + /// + /// A span of objects that contains the elements to concatenate. + /// The concatenated string representations of the values of the elements in . + public static string Concat(params ReadOnlySpan args) + { if (args.Length <= 1) { - return args.Length == 0 ? + return args.IsEmpty ? Empty : args[0]?.ToString() ?? Empty; } @@ -355,10 +364,19 @@ internal static string Concat(ReadOnlySpan str0, ReadOnlySpan str1, public static string Concat(params string?[] values) { ArgumentNullException.ThrowIfNull(values); + return Concat((ReadOnlySpan)values); + } + /// + /// Concatenates the elements of a specified span of . + /// + /// A span of instances. + /// The concatenated elements of . + public static string Concat(params ReadOnlySpan values) + { if (values.Length <= 1) { - return values.Length == 0 ? + return values.IsEmpty ? Empty : values[0] ?? Empty; } @@ -416,7 +434,7 @@ public static string Concat(params string?[] values) // something changed concurrently to mutate the input array: fall back to // doing the concatenation again, but this time with a defensive copy. This // fall back should be extremely rare. - return copiedLength == totalLength ? result : Concat((string?[])values.Clone()); + return copiedLength == totalLength ? result : Concat((ReadOnlySpan)values.ToArray()); } public static string Format([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0) @@ -445,6 +463,17 @@ public static string Format([StringSyntax(StringSyntaxAttribute.CompositeFormat) ArgumentNullException.Throw(format is null ? nameof(format) : nameof(args)); } + return FormatHelper(null, format, (ReadOnlySpan)args); + } + + /// + /// Replaces the format item in a specified string with the string representation of a corresponding object in a specified span. + /// + /// A composite format string. + /// An object span that contains zero or more objects to format. + /// A copy of in which the format items have been replaced by the string representation of the corresponding objects in . + public static string Format([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan args) + { return FormatHelper(null, format, args); } @@ -474,6 +503,19 @@ public static string Format(IFormatProvider? provider, [StringSyntax(StringSynta ArgumentNullException.Throw(format is null ? nameof(format) : nameof(args)); } + return FormatHelper(provider, format, (ReadOnlySpan)args); + } + + /// + /// Replaces the format items in a string with the string representations of corresponding objects in a specified span. + /// A parameter supplies culture-specific formatting information. + /// + /// An object that supplies culture-specific formatting information. + /// A composite format string. + /// An object span that contains zero or more objects to format. + /// A copy of in which the format items have been replaced by the string representation of the corresponding objects in . + public static string Format(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan args) + { return FormatHelper(provider, format, args); } @@ -575,7 +617,7 @@ public static string Format(IFormatProvider? provider, CompositeFormat format, p /// The formatted string. /// is null. /// The index of a format item is greater than or equal to the number of supplied arguments. - public static string Format(IFormatProvider? provider, CompositeFormat format, ReadOnlySpan args) + public static string Format(IFormatProvider? provider, CompositeFormat format, params ReadOnlySpan args) { ArgumentNullException.ThrowIfNull(format); format.ValidateNumberOfArgs(args.Length); @@ -669,6 +711,21 @@ public static string Join(char separator, params string?[] value) return JoinCore(new ReadOnlySpan(in separator), new ReadOnlySpan(value)); } + /// + /// Concatenates a span of strings, using the specified separator between each member. + /// + /// The character to use as a separator. is included in the returned string only if has more than one element. + /// A span that contains the elements to concatenate. + /// + /// A string that consists of the elements of delimited by the string. + /// -or- + /// if has zero elements. + /// + public static string Join(char separator, params ReadOnlySpan value) + { + return JoinCore(new ReadOnlySpan(in separator), value); + } + public static string Join(string? separator, params string?[] value) { if (value == null) @@ -679,6 +736,21 @@ public static string Join(string? separator, params string?[] value) return JoinCore(separator.AsSpan(), new ReadOnlySpan(value)); } + /// + /// Concatenates a span of strings, using the specified separator between each member. + /// + /// The string to use as a separator. is included in the returned string only if has more than one element. + /// A span that contains the elements to concatenate. + /// + /// A string that consists of the elements of delimited by the string. + /// -or- + /// if has zero elements. + /// + public static string Join(string? separator, params ReadOnlySpan value) + { + return JoinCore(separator.AsSpan(), value); + } + public static string Join(char separator, string?[] value, int startIndex, int count) => JoinCore(new ReadOnlySpan(in separator), value, startIndex, count); @@ -743,20 +815,55 @@ public static string Join(string? separator, IEnumerable values) } } - public static string Join(char separator, params object?[] values) => - JoinCore(new ReadOnlySpan(in separator), values); + public static string Join(char separator, params object?[] values) + { + if (values == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } - public static string Join(string? separator, params object?[] values) => - JoinCore(separator.AsSpan(), values); + return JoinCore(new ReadOnlySpan(in separator), (ReadOnlySpan)values); + } - private static string JoinCore(ReadOnlySpan separator, object?[] values) + /// + /// Concatenates the string representations of a span of objects, using the specified separator between each member. + /// + /// The character to use as a separator. is included in the returned string only if value has more than one element. + /// A span of objects whose string representations will be concatenated. + /// + /// A string that consists of the elements of delimited by the character. + /// -or- + /// if has zero elements. + /// + public static string Join(char separator, params ReadOnlySpan values) => + JoinCore(new ReadOnlySpan(in separator), values); + + public static string Join(string? separator, params object?[] values) { if (values == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); } - if (values.Length == 0) + return JoinCore(separator.AsSpan(), (ReadOnlySpan)values); + } + + /// + /// Concatenates the string representations of a span of objects, using the specified separator between each member. + /// + /// The string to use as a separator. is included in the returned string only if has more than one element. + /// A span of objects whose string representations will be concatenated. + /// + /// A string that consists of the elements of delimited by the string. + /// -or- + /// if has zero elements. + /// + public static string Join(string? separator, params ReadOnlySpan values) => + JoinCore(separator.AsSpan(), values); + + private static string JoinCore(ReadOnlySpan separator, ReadOnlySpan values) + { + if (values.IsEmpty) { return Empty; } @@ -793,11 +900,16 @@ public static string Join(string? separator, IEnumerable values) => private static string JoinCore(ReadOnlySpan separator, IEnumerable values) { + if (values is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } + if (typeof(T) == typeof(string)) { - if (values is List valuesList) + if (values.GetType() == typeof(List)) // avoid accidentally bypassing a derived type's reimplementation of IEnumerable { - return JoinCore(separator, CollectionsMarshal.AsSpan(valuesList)); + return JoinCore(separator, CollectionsMarshal.AsSpan(Unsafe.As>(values))); } if (values is string?[] valuesArray) @@ -806,11 +918,6 @@ private static string JoinCore(ReadOnlySpan separator, IEnumerable v } } - if (values == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); - } - using (IEnumerator e = values.GetEnumerator()) { if (!e.MoveNext()) @@ -1548,6 +1655,16 @@ public string[] Split(params char[]? separator) return SplitInternal(separator, int.MaxValue, StringSplitOptions.None); } + /// + /// Splits a string into substrings based on specified delimiting characters. + /// + /// A span of delimiting characters, or an empty span that contains no delimiters. + /// An array whose elements contain the substrings from this instance that are delimited by one or more characters in . + public string[] Split(params ReadOnlySpan separator) + { + return SplitInternal(separator, int.MaxValue, StringSplitOptions.None); + } + // Creates an array of strings by splitting this string at each // occurrence of a separator. The separator is searched for, and if found, // the substring preceding the occurrence is stored as the first element in @@ -2241,6 +2358,28 @@ public unsafe string Trim(params char[]? trimChars) } } + /// + /// Removes all leading and trailing occurrences of a set of characters specified in a span from the current string. + /// + /// A span of Unicode characters to remove. + /// + /// The string that remains after all occurrences of the characters in the parameter are removed from the start and end of the current string. + /// If is empty, white-space characters are removed instead. + /// If no characters can be trimmed from the current instance, the method returns the current instance unchanged. + /// + public unsafe string Trim(params ReadOnlySpan trimChars) + { + if (trimChars.IsEmpty) + { + return TrimWhiteSpaceHelper(TrimType.Both); + } + + fixed (char* pTrimChars = &MemoryMarshal.GetReference(trimChars)) + { + return TrimHelper(pTrimChars, trimChars.Length, TrimType.Both); + } + } + // Removes a set of characters from the beginning of this string. public string TrimStart() => TrimWhiteSpaceHelper(TrimType.Head); @@ -2260,6 +2399,28 @@ public unsafe string TrimStart(params char[]? trimChars) } } + /// + /// Removes all the leading occurrences of a set of characters specified in a span from the current string. + /// + /// A span of Unicode characters to remove. + /// + /// The string that remains after all occurrences of characters in the parameter are removed from the start of the current string. + /// If is empty, white-space characters are removed instead. + /// If no characters can be trimmed from the current instance, the method returns the current instance unchanged. + /// + public unsafe string TrimStart(params ReadOnlySpan trimChars) + { + if (trimChars.IsEmpty) + { + return TrimWhiteSpaceHelper(TrimType.Head); + } + + fixed (char* pTrimChars = &MemoryMarshal.GetReference(trimChars)) + { + return TrimHelper(pTrimChars, trimChars.Length, TrimType.Head); + } + } + // Removes a set of characters from the end of this string. public string TrimEnd() => TrimWhiteSpaceHelper(TrimType.Tail); @@ -2279,6 +2440,28 @@ public unsafe string TrimEnd(params char[]? trimChars) } } + /// + /// Removes all the trailing occurrences of a set of characters specified in a span from the current string. + /// + /// A span of Unicode characters to remove. + /// + /// The string that remains after all occurrences of characters in the parameter are removed from the end of the current string. + /// If is empty, white-space characters are removed instead. + /// If no characters can be trimmed from the current instance, the method returns the current instance unchanged. + /// + public unsafe string TrimEnd(params ReadOnlySpan trimChars) + { + if (trimChars.IsEmpty) + { + return TrimWhiteSpaceHelper(TrimType.Tail); + } + + fixed (char* pTrimChars = &trimChars[0]) + { + return TrimHelper(pTrimChars, trimChars.Length, TrimType.Tail); + } + } + private string TrimWhiteSpaceHelper(TrimType trimType) { // end will point to the first non-trimmed character on the right. diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs index ba07b985b670..76d2701b0eaa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs @@ -2038,79 +2038,17 @@ internal static unsafe nuint WidenAsciiToUtf16(byte* pAsciiBuffer, char* pUtf16B if (BitConverter.IsLittleEndian && Vector128.IsHardwareAccelerated && elementCount >= (uint)Vector128.Count) { - ushort* pCurrentWriteAddress = (ushort*)pUtf16Buffer; - - if (Vector512.IsHardwareAccelerated && elementCount >= (uint)Vector512.Count) + if (Vector512.IsHardwareAccelerated && (elementCount - currentOffset) >= (uint)Vector512.Count) { - // Calculating the destination address outside the loop results in significant - // perf wins vs. relying on the JIT to fold memory addressing logic into the - // write instructions. See: https://github.com/dotnet/runtime/issues/33002 - nuint finalOffsetWhereCanRunLoop = elementCount - (uint)Vector512.Count; - - do - { - Vector512 asciiVector = Vector512.Load(pAsciiBuffer + currentOffset); - - if (asciiVector.ExtractMostSignificantBits() != 0) - { - break; - } - - (Vector512 utf16LowVector, Vector512 utf16HighVector) = Vector512.Widen(asciiVector); - utf16LowVector.Store(pCurrentWriteAddress); - utf16HighVector.Store(pCurrentWriteAddress + Vector512.Count); - - currentOffset += (nuint)Vector512.Count; - pCurrentWriteAddress += (nuint)Vector512.Count; - } while (currentOffset <= finalOffsetWhereCanRunLoop); + WidenAsciiToUtf1_Vector, Vector512>(pAsciiBuffer, pUtf16Buffer, ref currentOffset, elementCount); } - else if (Vector256.IsHardwareAccelerated && elementCount >= (uint)Vector256.Count) + else if (Vector256.IsHardwareAccelerated && (elementCount - currentOffset) >= (uint)Vector256.Count) { - // Calculating the destination address outside the loop results in significant - // perf wins vs. relying on the JIT to fold memory addressing logic into the - // write instructions. See: https://github.com/dotnet/runtime/issues/33002 - nuint finalOffsetWhereCanRunLoop = elementCount - (uint)Vector256.Count; - - do - { - Vector256 asciiVector = Vector256.Load(pAsciiBuffer + currentOffset); - - if (asciiVector.ExtractMostSignificantBits() != 0) - { - break; - } - - (Vector256 utf16LowVector, Vector256 utf16HighVector) = Vector256.Widen(asciiVector); - utf16LowVector.Store(pCurrentWriteAddress); - utf16HighVector.Store(pCurrentWriteAddress + Vector256.Count); - - currentOffset += (nuint)Vector256.Count; - pCurrentWriteAddress += (nuint)Vector256.Count; - } while (currentOffset <= finalOffsetWhereCanRunLoop); + WidenAsciiToUtf1_Vector, Vector256>(pAsciiBuffer, pUtf16Buffer, ref currentOffset, elementCount); } - else + else if (Vector128.IsHardwareAccelerated && (elementCount - currentOffset) >= (uint)Vector128.Count) { - // Calculating the destination address outside the loop results in significant - // perf wins vs. relying on the JIT to fold memory addressing logic into the - // write instructions. See: https://github.com/dotnet/runtime/issues/33002 - nuint finalOffsetWhereCanRunLoop = elementCount - (uint)Vector128.Count; - - do - { - Vector128 asciiVector = Vector128.Load(pAsciiBuffer + currentOffset); - - if (VectorContainsNonAsciiChar(asciiVector)) - { - break; - } - - (Vector128 utf16LowVector, Vector128 utf16HighVector) = Vector128.Widen(asciiVector); - utf16LowVector.Store(pCurrentWriteAddress); - utf16HighVector.Store(pCurrentWriteAddress + Vector128.Count); - - currentOffset += (nuint)Vector128.Count; - pCurrentWriteAddress += (nuint)Vector128.Count; - } while (currentOffset <= finalOffsetWhereCanRunLoop); + WidenAsciiToUtf1_Vector, Vector128>(pAsciiBuffer, pUtf16Buffer, ref currentOffset, elementCount); } } @@ -2212,6 +2150,85 @@ internal static unsafe nuint WidenAsciiToUtf16(byte* pAsciiBuffer, char* pUtf16B goto Finish; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static unsafe void WidenAsciiToUtf1_Vector(byte* pAsciiBuffer, char* pUtf16Buffer, ref nuint currentOffset, nuint elementCount) + where TVectorByte : unmanaged, ISimdVector + where TVectorUInt16 : unmanaged, ISimdVector + { + ushort* pCurrentWriteAddress = (ushort*)pUtf16Buffer; + // Calculating the destination address outside the loop results in significant + // perf wins vs. relying on the JIT to fold memory addressing logic into the + // write instructions. See: https://github.com/dotnet/runtime/issues/33002 + nuint finalOffsetWhereCanRunLoop = elementCount - (nuint)TVectorByte.Count; + TVectorByte asciiVector = TVectorByte.Load(pAsciiBuffer + currentOffset); + if (!HasMatch(asciiVector)) + { + (TVectorUInt16 utf16LowVector, TVectorUInt16 utf16HighVector) = Widen(asciiVector); + utf16LowVector.Store(pCurrentWriteAddress); + utf16HighVector.Store(pCurrentWriteAddress + TVectorUInt16.Count); + pCurrentWriteAddress += (nuint)(TVectorUInt16.Count * 2); + if (((nuint)pCurrentWriteAddress % sizeof(char)) == 0) + { + // Bump write buffer up to the next aligned boundary + pCurrentWriteAddress = (ushort*)((nuint)pCurrentWriteAddress & ~(nuint)(TVectorUInt16.Alignment - 1)); + nuint numBytesWritten = (nuint)pCurrentWriteAddress - (nuint)pUtf16Buffer; + currentOffset += (nuint)numBytesWritten / 2; + } + else + { + // If input isn't char aligned, we won't be able to align it to a Vector + currentOffset += (nuint)TVectorByte.Count; + } + while (currentOffset <= finalOffsetWhereCanRunLoop) + { + asciiVector = TVectorByte.Load(pAsciiBuffer + currentOffset); + if (HasMatch(asciiVector)) + { + break; + } + (utf16LowVector, utf16HighVector) = Widen(asciiVector); + utf16LowVector.Store(pCurrentWriteAddress); + utf16HighVector.Store(pCurrentWriteAddress + TVectorUInt16.Count); + + currentOffset += (nuint)TVectorByte.Count; + pCurrentWriteAddress += (nuint)(TVectorUInt16.Count * 2); + } + } + return; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static unsafe bool HasMatch(TVectorByte vector) + where TVectorByte : unmanaged, ISimdVector + { + return !(vector & TVectorByte.Create((byte)0x80)).Equals(TVectorByte.Zero); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static unsafe (TVectorUInt16 Lower, TVectorUInt16 Upper) Widen(TVectorByte vector) + where TVectorByte : unmanaged, ISimdVector + where TVectorUInt16 : unmanaged, ISimdVector + { + if (typeof(TVectorByte) == typeof(Vector256)) + { + (Vector256 Lower256, Vector256 Upper256) = Vector256.Widen((Vector256)(object)vector); + return ((TVectorUInt16)(object)Lower256, (TVectorUInt16)(object)Upper256); + } + else if (typeof(TVectorByte) == typeof(Vector512)) + { + (Vector512 Lower512, Vector512 Upper512) = Vector512.Widen((Vector512)(object)vector); + return ((TVectorUInt16)(object)Lower512, (TVectorUInt16)(object)Upper512); + } + else + { + Debug.Assert(typeof(TVectorByte) == typeof(Vector128)); + (Vector128 Lower128, Vector128 Upper128) = Vector128.Widen((Vector128)(object)vector); + return ((TVectorUInt16)(object)Lower128, (TVectorUInt16)(object)Upper128); + } + } + + /// /// Given a DWORD which represents a buffer of 4 bytes, widens the buffer into 4 WORDs and /// writes them to the output buffer with machine endianness. diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/EncodingProvider.cs b/src/libraries/System.Private.CoreLib/src/System/Text/EncodingProvider.cs index 11b284f8e04d..b939492ed975 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/EncodingProvider.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/EncodingProvider.cs @@ -118,10 +118,10 @@ internal static void AddProvider(EncodingProvider provider) internal static Encoding? GetEncodingFromProvider(string encodingName) { - if (s_providers == null) + EncodingProvider[]? providers = s_providers; + if (providers == null) return null; - EncodingProvider[] providers = s_providers; foreach (EncodingProvider provider in providers) { Encoding? enc = provider.GetEncoding(encodingName); @@ -134,10 +134,10 @@ internal static void AddProvider(EncodingProvider provider) internal static Encoding? GetEncodingFromProvider(int codepage, EncoderFallback enc, DecoderFallback dec) { - if (s_providers == null) + EncodingProvider[]? providers = s_providers; + if (providers == null) return null; - EncodingProvider[] providers = s_providers; foreach (EncodingProvider provider in providers) { Encoding? encoding = provider.GetEncoding(codepage, enc, dec); @@ -150,10 +150,10 @@ internal static void AddProvider(EncodingProvider provider) internal static Encoding? GetEncodingFromProvider(string encodingName, EncoderFallback enc, DecoderFallback dec) { - if (s_providers == null) + EncodingProvider[]? providers = s_providers; + if (providers == null) return null; - EncodingProvider[] providers = s_providers; foreach (EncodingProvider provider in providers) { Encoding? encoding = provider.GetEncoding(encodingName, enc, dec); diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs index 6f7b0abfa9b9..7a33d7d0ed3a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs @@ -1123,6 +1123,24 @@ public StringBuilder Append(ReadOnlySpan value) #region AppendJoin public StringBuilder AppendJoin(string? separator, params object?[] values) + { + if (values is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } + + separator ??= string.Empty; + return AppendJoinCore(ref separator.GetRawStringData(), separator.Length, values); + } + + /// + /// Concatenates the string representations of the elements in the provided span of objects, using the specified separator between each member, + /// then appends the result to the current instance of the string builder. + /// + /// The string to use as a separator. is included in the joined strings only if has more than one element. + /// A span that contains the strings to concatenate and append to the current instance of the string builder. + /// A reference to this instance after the append operation has completed. + public StringBuilder AppendJoin(string? separator, params ReadOnlySpan values) { separator ??= string.Empty; return AppendJoinCore(ref separator.GetRawStringData(), separator.Length, values); @@ -1130,11 +1148,34 @@ public StringBuilder AppendJoin(string? separator, params object?[] values) public StringBuilder AppendJoin(string? separator, IEnumerable values) { + if (values is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } + separator ??= string.Empty; return AppendJoinCore(ref separator.GetRawStringData(), separator.Length, values); } public StringBuilder AppendJoin(string? separator, params string?[] values) + { + if (values is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } + + separator ??= string.Empty; + return AppendJoinCore(ref separator.GetRawStringData(), separator.Length, values); + } + + /// + /// Concatenates the strings of the provided span, using the specified separator between each string, + /// then appends the result to the current instance of the string builder. + /// + /// The string to use as a separator. is included in the joined strings only if has more than one element. + /// A span that contains the strings to concatenate and append to the current instance of the string builder. + /// A reference to this instance after the append operation has completed. + public StringBuilder AppendJoin(string? separator, params ReadOnlySpan values) { separator ??= string.Empty; return AppendJoinCore(ref separator.GetRawStringData(), separator.Length, values); @@ -1142,30 +1183,60 @@ public StringBuilder AppendJoin(string? separator, params string?[] values) public StringBuilder AppendJoin(char separator, params object?[] values) { - return AppendJoinCore(ref separator, 1, values); + if (values is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } + + return AppendJoinCore(ref separator, 1, (ReadOnlySpan)values); } + /// + /// Concatenates the string representations of the elements in the provided span of objects, using the specified char separator between each member, + /// then appends the result to the current instance of the string builder. + /// + /// The character to use as a separator. is included in the joined strings only if has more than one element. + /// A span that contains the strings to concatenate and append to the current instance of the string builder. + /// A reference to this instance after the append operation has completed. + public StringBuilder AppendJoin(char separator, params ReadOnlySpan values) => + AppendJoinCore(ref separator, 1, values); + public StringBuilder AppendJoin(char separator, IEnumerable values) { + if (values is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } + return AppendJoinCore(ref separator, 1, values); } public StringBuilder AppendJoin(char separator, params string?[] values) { - return AppendJoinCore(ref separator, 1, values); + if (values is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); + } + + return AppendJoinCore(ref separator, 1, (ReadOnlySpan)values); } + /// + /// Concatenates the strings of the provided span, using the specified char separator between each string, + /// then appends the result to the current instance of the string builder. + /// + /// The character to use as a separator. is included in the joined strings only if has more than one element. + /// A span that contains the strings to concatenate and append to the current instance of the string builder. + /// A reference to this instance after the append operation has completed. + public StringBuilder AppendJoin(char separator, params ReadOnlySpan values) => + AppendJoinCore(ref separator, 1, values); + private StringBuilder AppendJoinCore(ref char separator, int separatorLength, IEnumerable values) { + Debug.Assert(values != null); Debug.Assert(!Unsafe.IsNullRef(ref separator)); Debug.Assert(separatorLength >= 0); - if (values == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); - } - - Debug.Assert(values != null); using (IEnumerator en = values.GetEnumerator()) { if (!en.MoveNext()) @@ -1192,15 +1263,9 @@ private StringBuilder AppendJoinCore(ref char separator, int separatorLength, return this; } - private StringBuilder AppendJoinCore(ref char separator, int separatorLength, T[] values) + private StringBuilder AppendJoinCore(ref char separator, int separatorLength, ReadOnlySpan values) { - if (values == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); - } - - Debug.Assert(values != null); - if (values.Length == 0) + if (values.IsEmpty) { return this; } @@ -1360,19 +1425,19 @@ private StringBuilder InsertSpanFormattable(int index, T value) where T : ISp public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0) { - return AppendFormatHelper(null, format, new ReadOnlySpan(in arg0)); + return AppendFormat(null, format, new ReadOnlySpan(in arg0)); } public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1) { TwoObjects two = new TwoObjects(arg0, arg1); - return AppendFormatHelper(null, format, two); + return AppendFormat(null, format, (ReadOnlySpan)two); } public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1, object? arg2) { ThreeObjects three = new ThreeObjects(arg0, arg1, arg2); - return AppendFormatHelper(null, format, three); + return AppendFormat(null, format, (ReadOnlySpan)three); } public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params object?[] args) @@ -1380,28 +1445,47 @@ public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeF if (args is null) { // To preserve the original exception behavior, throw an exception about format if both - // args and format are null. The actual null check for format is in AppendFormatHelper. + // args and format are null. The actual null check for format is in AppendFormat(..., span). ArgumentNullException.Throw(format is null ? nameof(format) : nameof(args)); } - return AppendFormatHelper(null, format, args); + return AppendFormat(null, format, args); + } + + /// + /// Appends the string returned by processing a composite format string, which contains zero or more format items, to this instance. + /// Each format item is replaced by the string representation of a corresponding argument in a parameter span. + /// + /// A composite format string. + /// A span of objects to format. + /// A reference to this instance after the append operation has completed. + /// is null. + /// The length of the expanded string would exceed . + /// + /// is invalid. + /// -or- + /// The index of a format item is less than 0 (zero), or greater than or equal to the length of the span. + /// + public StringBuilder AppendFormat([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan args) + { + return AppendFormat(null, format, args); } public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0) { - return AppendFormatHelper(provider, format, new ReadOnlySpan(in arg0)); + return AppendFormat(provider, format, new ReadOnlySpan(in arg0)); } public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1) { TwoObjects two = new TwoObjects(arg0, arg1); - return AppendFormatHelper(provider, format, two); + return AppendFormat(provider, format, (ReadOnlySpan)two); } public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0, object? arg1, object? arg2) { ThreeObjects three = new ThreeObjects(arg0, arg1, arg2); - return AppendFormatHelper(provider, format, three); + return AppendFormat(provider, format, (ReadOnlySpan)three); } public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params object?[] args) @@ -1409,14 +1493,29 @@ public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(Strin if (args is null) { // To preserve the original exception behavior, throw an exception about format if both - // args and format are null. The actual null check for format is in AppendFormatHelper. + // args and format are null. The actual null check for format is in AppendFormat(..., span). ArgumentNullException.Throw(format is null ? nameof(format) : nameof(args)); } - return AppendFormatHelper(provider, format, args); + return AppendFormat(provider, format, (ReadOnlySpan)args); } - internal StringBuilder AppendFormatHelper(IFormatProvider? provider, string format, ReadOnlySpan args) + /// + /// Appends the string returned by processing a composite format string, which contains zero or more format items, to this instance. + /// Each format item is replaced by the string representation of a corresponding argument in a parameter span using a specified format provider. + /// + /// An object that supplies culture-specific formatting information. + /// A composite format string. + /// A span of objects to format. + /// A reference to this instance after the append operation has completed. + /// is null. + /// The length of the expanded string would exceed . + /// + /// is invalid. + /// -or- + /// The index of a format item is less than 0 (zero), or greater than or equal to the length of the span. + /// + public StringBuilder AppendFormat(IFormatProvider? provider, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, params ReadOnlySpan args) { ArgumentNullException.ThrowIfNull(format); @@ -1776,7 +1875,7 @@ public StringBuilder AppendFormat(IFormatProvider? provider, CompositeFormat for /// A reference to this instance after the append operation has completed. /// is null. /// The index of a format item is greater than or equal to the number of supplied arguments. - public StringBuilder AppendFormat(IFormatProvider? provider, CompositeFormat format, ReadOnlySpan args) + public StringBuilder AppendFormat(IFormatProvider? provider, CompositeFormat format, params ReadOnlySpan args) { ArgumentNullException.ThrowIfNull(format); format.ValidateNumberOfArgs(args.Length); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs index ace2ed4b943d..f1358083a220 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs @@ -868,7 +868,17 @@ public static CancellationTokenSource CreateLinkedTokenSource(CancellationToken public static CancellationTokenSource CreateLinkedTokenSource(params CancellationToken[] tokens) { ArgumentNullException.ThrowIfNull(tokens); + return CreateLinkedTokenSource((ReadOnlySpan)tokens); + } + /// + /// Creates a that will be in the canceled state + /// when any of the source tokens are in the canceled state. + /// + /// The CancellationToken instances to observe. + /// A that is linked to the source tokens. + public static CancellationTokenSource CreateLinkedTokenSource(params ReadOnlySpan tokens) + { return tokens.Length switch { 0 => throw new ArgumentException(SR.CancellationToken_CreateLinkedToken_TokensIsEmpty), @@ -935,7 +945,7 @@ private sealed class LinkedNCancellationTokenSource : CancellationTokenSource }; private CancellationTokenRegistration[]? _linkingRegistrations; - internal LinkedNCancellationTokenSource(CancellationToken[] tokens) + internal LinkedNCancellationTokenSource(ReadOnlySpan tokens) { _linkingRegistrations = new CancellationTokenRegistration[tokens.Length]; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs index 986ea1bd62ce..c455235faf95 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs @@ -20,7 +20,7 @@ namespace System.Threading public sealed class ExecutionContext : IDisposable, ISerializable { internal static readonly ExecutionContext Default = new ExecutionContext(); - private static volatile ExecutionContext? s_defaultFlowSuppressed; + private static ExecutionContext? s_defaultFlowSuppressed; private readonly IAsyncLocalValueMap? m_localValues; private readonly IAsyncLocal[]? m_localChangeNotifications; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs index a5fb311877a3..93c8ee5416e7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs @@ -126,7 +126,7 @@ public static unsafe ushort Exchange(ref ushort location1, ushort value) nuint offset = Unsafe.OpportunisticMisalignment(ref location1, sizeof(uint)); ref uint alignedRef = ref Unsafe.As(ref Unsafe.SubtractByteOffset(ref location1, offset)); int bitOffset = - (int)((BitConverter.IsLittleEndian ? offset : sizeof(uint) - offset - sizeof(byte)) * 8); // to bit offset + (int)((BitConverter.IsLittleEndian ? offset : sizeof(uint) - offset - sizeof(ushort)) * 8); // to bit offset Debug.Assert(bitOffset is 0 or 16); uint mask = ~((uint)ushort.MaxValue << bitOffset); uint shiftedValue = (uint)value << bitOffset; @@ -308,7 +308,7 @@ public static unsafe ushort CompareExchange(ref ushort location1, ushort value, nuint offset = Unsafe.OpportunisticMisalignment(ref location1, sizeof(uint)); ref uint alignedRef = ref Unsafe.As(ref Unsafe.SubtractByteOffset(ref location1, offset)); int bitOffset = - (int)((BitConverter.IsLittleEndian ? offset : sizeof(uint) - offset - sizeof(byte)) * 8); // to bit offset + (int)((BitConverter.IsLittleEndian ? offset : sizeof(uint) - offset - sizeof(ushort)) * 8); // to bit offset Debug.Assert(bitOffset is 0 or 16); uint mask = ~((uint)ushort.MaxValue << bitOffset); uint shiftedValue = (uint)value << bitOffset; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.NonNativeAot.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.NonNativeAot.cs index 9386b7ed1746..bd3a0be6902a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.NonNativeAot.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.NonNativeAot.cs @@ -9,13 +9,19 @@ namespace System.Threading public sealed partial class Lock { private static readonly short s_maxSpinCount = DetermineMaxSpinCount(); - private static readonly short s_minSpinCount = DetermineMinSpinCount(); + private static readonly short s_minSpinCountForAdaptiveSpin = DetermineMinSpinCountForAdaptiveSpin(); /// /// Initializes a new instance of the class. /// public Lock() => _spinCount = s_maxSpinCount; + internal ulong OwningOSThreadId => _owningThreadId; + +#pragma warning disable CA1822 // can be marked as static - varies between runtimes + internal int OwningManagedThreadId => 0; +#pragma warning restore CA1822 + private static TryLockResult LazyInitializeOrEnter() => TryLockResult.Spin; private static bool IsSingleProcessor => Environment.IsSingleProcessor; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs index b7961869eac5..00b879b04c48 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs @@ -16,7 +16,6 @@ namespace System.Threading /// that holds a lock may enter the lock repeatedly without exiting it, such as recursively, in which case the thread should /// eventually exit the lock the same number of times to fully exit the lock and allow other threads to enter the lock. /// - [Runtime.Versioning.RequiresPreviewFeatures] public sealed partial class Lock { private const short DefaultMaxSpinCount = 22; @@ -37,7 +36,15 @@ public sealed partial class Lock private uint _state; // see State for layout private uint _recursionCount; + + // This field serves a few purposes currently: + // - When positive, it indicates the number of spin-wait iterations that most threads would do upon contention + // - When zero, it indicates that spin-waiting is to be attempted by a thread to test if it is successful + // - When negative, it serves as a rough counter for contentions that would increment it towards zero + // + // See references to this field and "AdaptiveSpin" in TryEnterSlow for more information. private short _spinCount; + private ushort _waiterStartTimeMs; private AutoResetEvent? _waitEvent; @@ -297,7 +304,7 @@ private void ExitImpl() } } - private static bool IsAdaptiveSpinEnabled(short minSpinCount) => minSpinCount <= 0; + private static bool IsAdaptiveSpinEnabled(short minSpinCountForAdaptiveSpin) => minSpinCountForAdaptiveSpin <= 0; [MethodImpl(MethodImplOptions.NoInlining)] private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) @@ -334,25 +341,35 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) return new ThreadId(0); } + // + // At this point, a full lock attempt has been made, and it's time to retry or wait for the lock. + // + + // Notify the debugger that this thread is about to wait for a lock that is likely held by another thread. The + // debugger may choose to enable other threads to run to help resolve the dependency, or it may choose to abort the + // FuncEval here. The lock state is consistent here for an abort, whereas letting a FuncEval continue to run could + // lead to the FuncEval timing out and potentially aborting at an arbitrary place where the lock state may not be + // consistent. + Debugger.NotifyOfCrossThreadDependency(); + if (LazyInitializeOrEnter() == TryLockResult.Locked) { goto Locked; } - bool isSingleProcessor = IsSingleProcessor; short maxSpinCount = s_maxSpinCount; if (maxSpinCount == 0) { goto Wait; } - short minSpinCount = s_minSpinCount; + short minSpinCountForAdaptiveSpin = s_minSpinCountForAdaptiveSpin; short spinCount = _spinCount; if (spinCount < 0) { // When negative, the spin count serves as a counter for contentions such that a spin-wait can be attempted // periodically to see if it would be beneficial. Increment the spin count and skip spin-waiting. - Debug.Assert(IsAdaptiveSpinEnabled(minSpinCount)); + Debug.Assert(IsAdaptiveSpinEnabled(minSpinCountForAdaptiveSpin)); _spinCount = (short)(spinCount + 1); goto Wait; } @@ -377,7 +394,7 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) for (short spinIndex = 0; ;) { - LowLevelSpinWaiter.Wait(spinIndex, SpinSleep0Threshold, isSingleProcessor); + LowLevelSpinWaiter.Wait(spinIndex, SpinSleep0Threshold, isSingleProcessor: false); if (++spinIndex >= spinCount) { @@ -394,7 +411,7 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) if (tryLockResult == TryLockResult.Locked) { - if (isFirstSpinner && IsAdaptiveSpinEnabled(minSpinCount)) + if (isFirstSpinner && IsAdaptiveSpinEnabled(minSpinCountForAdaptiveSpin)) { // Since the first spinner does a full-length spin-wait, and to keep upward and downward changes to the // spin count more balanced, only the first spinner adjusts the spin count @@ -415,7 +432,7 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) // Unregister the spinner and try to acquire the lock tryLockResult = State.TryLockAfterSpinLoop(this); - if (isFirstSpinner && IsAdaptiveSpinEnabled(minSpinCount)) + if (isFirstSpinner && IsAdaptiveSpinEnabled(minSpinCountForAdaptiveSpin)) { // Since the first spinner does a full-length spin-wait, and to keep upward and downward changes to the // spin count more balanced, only the first spinner adjusts the spin count @@ -433,7 +450,7 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) // number of contentions, the first spinner will attempt a spin-wait again to see if it is effective. Debug.Assert(tryLockResult == TryLockResult.Wait); spinCount = _spinCount; - _spinCount = spinCount > 0 ? (short)(spinCount - 1) : minSpinCount; + _spinCount = spinCount > 0 ? (short)(spinCount - 1) : minSpinCountForAdaptiveSpin; } } @@ -477,6 +494,8 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) waitStartTimeTicks = Stopwatch.GetTimestamp(); } + using ThreadBlockingInfo.Scope threadBlockingScope = new(this, timeoutMs); + bool acquiredLock = false; int waitStartTimeMs = timeoutMs < 0 ? 0 : Environment.TickCount; int remainingTimeoutMs = timeoutMs; @@ -504,7 +523,7 @@ private ThreadId TryEnterSlow(int timeoutMs, ThreadId currentThreadId) break; } - LowLevelSpinWaiter.Wait(spinIndex, SpinSleep0Threshold, isSingleProcessor); + LowLevelSpinWaiter.Wait(spinIndex, SpinSleep0Threshold, isSingleProcessor: false); } if (acquiredLock) @@ -648,14 +667,25 @@ internal nint LockIdForEvents internal ulong OwningThreadId => _owningThreadId; - private static short DetermineMaxSpinCount() => - AppContextConfigHelper.GetInt16Config( - "System.Threading.Lock.SpinCount", - "DOTNET_Lock_SpinCount", - DefaultMaxSpinCount, - allowNegative: false); + private static short DetermineMaxSpinCount() + { + if (IsSingleProcessor) + { + return 0; + } + + return + AppContextConfigHelper.GetInt16Config( + "System.Threading.Lock.SpinCount", + "DOTNET_Lock_SpinCount", + DefaultMaxSpinCount, + allowNegative: false); + } - private static short DetermineMinSpinCount() + // When the returned value is zero or negative, indicates the lowest value that the _spinCount field will have when + // adaptive spin chooses to pause spin-waiting, see the comment on the _spinCount field for more information. When the + // returned value is positive, adaptive spin is disabled. + private static short DetermineMinSpinCountForAdaptiveSpin() { // The config var can be set to -1 to disable adaptive spin short adaptiveSpinPeriod = diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs index 516fb42bf0a5..37f8c06af045 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.Versioning; namespace System.Threading @@ -35,7 +36,7 @@ public class ManualResetEventSlim : IDisposable // These are the default spin counts we use on single-proc and MP machines. private const int DEFAULT_SPIN_SP = 1; - private volatile object? m_lock; + private object? m_lock; // A lock used for waiting and pulsing. Lazily initialized via EnsureLockObjectCreated() private volatile ManualResetEvent? m_eventObj; // A true Win32 event used for waiting. @@ -199,13 +200,13 @@ private void Initialize(bool initialState, int spinCount) /// /// Helper to ensure the lock object is created before first use. /// + [MemberNotNull(nameof(m_lock))] private void EnsureLockObjectCreated() { - if (m_lock != null) - return; - - object newObj = new object(); - Interlocked.CompareExchange(ref m_lock, newObj, null); // failure is benign. Someone else set the value. + if (m_lock is null) + { + Interlocked.CompareExchange(ref m_lock, new object(), null); // failure is benign. Someone else set the value. + } } /// @@ -538,7 +539,7 @@ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken) // We must register and unregister the token outside of the lock, to avoid deadlocks. using (cancellationToken.UnsafeRegister(s_cancellationTokenCallback, this)) { - lock (m_lock!) + lock (m_lock) { // Loop to cope with spurious wakeups from other waits being canceled while (!IsSet) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs index b8a2196ec69b..4bf84b92a64d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs @@ -4681,14 +4681,33 @@ internal void RemoveContinuation(object continuationObject) // could be TaskCont [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger public static void WaitAll(params Task[] tasks) { -#if DEBUG - bool waitResult = -#endif - WaitAllCore(tasks, Timeout.Infinite, default); + if (tasks is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); + } -#if DEBUG + bool waitResult = WaitAllCore(tasks, Timeout.Infinite, default); + Debug.Assert(waitResult, "expected wait to succeed"); + } + + /// + /// Waits for all of the provided objects to complete execution. + /// + /// + /// An array of instances on which to wait. + /// + /// + /// The argument contains a null element. + /// + /// + /// At least one of the instances was canceled -or- an exception was thrown during + /// the execution of at least one of the instances. + /// + [UnsupportedOSPlatform("browser")] + public static void WaitAll(params ReadOnlySpan tasks) + { + bool waitResult = WaitAllCore(tasks, Timeout.Infinite, default); Debug.Assert(waitResult, "expected wait to succeed"); -#endif } /// @@ -4725,11 +4744,16 @@ public static void WaitAll(params Task[] tasks) public static bool WaitAll(Task[] tasks, TimeSpan timeout) { long totalMilliseconds = (long)timeout.TotalMilliseconds; - if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) + if (totalMilliseconds is < -1 or > int.MaxValue) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.timeout); } + if (tasks is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); + } + return WaitAllCore(tasks, (int)totalMilliseconds, default); } @@ -4763,6 +4787,11 @@ public static bool WaitAll(Task[] tasks, TimeSpan timeout) [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger public static bool WaitAll(Task[] tasks, int millisecondsTimeout) { + if (tasks is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); + } + return WaitAllCore(tasks, millisecondsTimeout, default); } @@ -4792,6 +4821,11 @@ public static bool WaitAll(Task[] tasks, int millisecondsTimeout) [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger public static void WaitAll(Task[] tasks, CancellationToken cancellationToken) { + if (tasks is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); + } + WaitAllCore(tasks, Timeout.Infinite, cancellationToken); } @@ -4831,18 +4865,48 @@ public static void WaitAll(Task[] tasks, CancellationToken cancellationToken) /// [UnsupportedOSPlatform("browser")] [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger - public static bool WaitAll(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken) => - WaitAllCore(tasks, millisecondsTimeout, cancellationToken); + public static bool WaitAll(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken) + { + if (tasks is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); + } - // Separated out to allow it to be optimized (caller is marked NoOptimization for VS parallel debugger - // to be able to see the method on the stack and inspect arguments). + return WaitAllCore(tasks, millisecondsTimeout, cancellationToken); + } + + /// Waits for all of the provided objects to complete execution unless the wait is cancelled. + /// An of Task instances on which to wait. + /// A to observe while waiting for the tasks to complete. + /// The argument is null. + /// The argument contains a null element. + /// One or more of the objects in tasks has been disposed. + /// The was canceled. + /// + /// At least one of the instances was canceled. If a task was canceled, the + /// contains an in its collection. + /// [UnsupportedOSPlatform("browser")] - private static bool WaitAllCore(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken) + public static void WaitAll(IEnumerable tasks, CancellationToken cancellationToken = default) { - if (tasks == null) + if (tasks is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); } + + ReadOnlySpan span = + tasks is List list ? CollectionsMarshal.AsSpan(list) : + tasks is Task[] array ? array : + CollectionsMarshal.AsSpan(new List(tasks)); + + WaitAllCore(span, Timeout.Infinite, cancellationToken); + } + + // Separated out to allow it to be optimized (caller is marked NoOptimization for VS parallel debugger + // to be able to see the method on the stack and inspect arguments). + [UnsupportedOSPlatform("browser")] + private static bool WaitAllCore(ReadOnlySpan tasks, int millisecondsTimeout, CancellationToken cancellationToken) + { if (millisecondsTimeout < -1) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.millisecondsTimeout); @@ -4919,11 +4983,6 @@ private static bool WaitAllCore(Task[] tasks, int millisecondsTimeout, Cancellat if (task.IsWaitNotificationEnabled) AddToList(task, ref notificationTasks, initSize: 1); } } - - // We need to prevent the tasks array from being GC'ed until we come out of the wait. - // This is necessary so that the Parallel Debugger can traverse it during the long wait and - // deduce waiter/waitee relationships - GC.KeepAlive(tasks); } // Now that we're done and about to exit, if the wait completed and if we have @@ -5914,7 +5973,7 @@ public static Task WhenAll(params Task[] tasks) /// /// /// The array contained a null task. - internal static Task WhenAll(ReadOnlySpan tasks) => // TODO https://github.com/dotnet/runtime/issues/77873: Make this public. + public static Task WhenAll(params ReadOnlySpan tasks) => tasks.Length != 0 ? new WhenAllPromise(tasks) : CompletedTask; /// A Task that gets completed when all of its constituent tasks complete. @@ -6133,7 +6192,13 @@ public static Task WhenAll(IEnumerable> tasks) // Skip a List allocation/copy if tasks is a collection if (tasks is ICollection> taskCollection) { - taskArray = new Task[taskCollection.Count]; + int count = taskCollection.Count; + if (count == 0) + { + return new Task(false, Array.Empty(), TaskCreationOptions.None, default); + } + + taskArray = new Task[count]; taskCollection.CopyTo(taskArray, 0); foreach (Task task in taskArray) { @@ -6142,20 +6207,30 @@ public static Task WhenAll(IEnumerable> tasks) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); } } - return InternalWhenAll(taskArray); + + return new WhenAllPromise(taskArray); } // Do some argument checking and convert tasks into a List (later an array) - if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); + if (tasks is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); + } + List> taskList = new List>(); foreach (Task task in tasks) { - if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); + if (task is null) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); + } + taskList.Add(task); } - // Delegate the rest to InternalWhenAll(). - return InternalWhenAll(taskList.ToArray()); + return taskList.Count == 0 ? + new Task(false, Array.Empty(), TaskCreationOptions.None, default) : + new WhenAllPromise(taskList.ToArray()); } /// @@ -6190,13 +6265,49 @@ public static Task WhenAll(IEnumerable> tasks) /// public static Task WhenAll(params Task[] tasks) { - // Do some argument checking and make a defensive copy of the tasks array - if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); + if (tasks is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks); + } - int taskCount = tasks.Length; - if (taskCount == 0) return InternalWhenAll(tasks); // small optimization in the case of an empty task array + return WhenAll((ReadOnlySpan>)tasks); + } - Task[] tasksCopy = (Task[])tasks.Clone(); + /// + /// Creates a task that will complete when all of the supplied tasks have completed. + /// + /// The tasks to wait on for completion. + /// A task that represents the completion of all of the supplied tasks. + /// + /// + /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state, + /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks. + /// + /// + /// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state. + /// + /// + /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state. + /// The Result of the returned task will be set to an array containing all of the results of the + /// supplied tasks in the same order as they were provided (e.g. if the input tasks array contained t1, t2, t3, the output + /// task's Result will return an TResult[] where arr[0] == t1.Result, arr[1] == t2.Result, and arr[2] == t3.Result). + /// + /// + /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion + /// state before it's returned to the caller. The returned TResult[] will be an array of 0 elements. + /// + /// + /// + /// The array contained a null task. + /// + public static Task WhenAll(params ReadOnlySpan> tasks) + { + if (tasks.IsEmpty) + { + return new Task(false, Array.Empty(), TaskCreationOptions.None, default); + } + + Task[] tasksCopy = tasks.ToArray(); foreach (Task task in tasksCopy) { if (task is null) @@ -6205,17 +6316,7 @@ public static Task WhenAll(params Task[] tasks) } } - // Delegate the rest to InternalWhenAll() - return InternalWhenAll(tasksCopy); - } - - // Some common logic to support WhenAll methods - private static Task InternalWhenAll(Task[] tasks) - { - Debug.Assert(tasks != null, "Expected a non-null tasks array"); - return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait - new Task(false, Array.Empty(), TaskCreationOptions.None, default) : - new WhenAllPromise(tasks); + return new WhenAllPromise(tasksCopy); } // A Task that gets completed when all of its constituent tasks complete. @@ -6355,7 +6456,7 @@ public static Task WhenAny(params Task[] tasks) { ArgumentNullException.ThrowIfNull(tasks); - return WhenAny((ReadOnlySpan)tasks); + return WhenAnyCore((ReadOnlySpan)tasks); } /// @@ -6370,7 +6471,22 @@ public static Task WhenAny(params Task[] tasks) /// /// The array contained a null task, or was empty. /// - private static Task WhenAny(ReadOnlySpan tasks) where TTask : Task + public static Task WhenAny(params ReadOnlySpan tasks) => + WhenAnyCore(tasks); + + /// + /// Creates a task that will complete when any of the supplied tasks have completed. + /// + /// The tasks to wait on for completion. + /// A task that represents the completion of one of the supplied tasks. The return Task's Result is the task that completed. + /// + /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state + /// with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state. + /// + /// + /// The array contained a null task, or was empty. + /// + private static Task WhenAnyCore(ReadOnlySpan tasks) where TTask : Task { if (tasks.Length == 2) { @@ -6550,13 +6666,13 @@ private static Task WhenAny(IEnumerable tasks) where TTask { // Take a more efficient path if tasks is actually a list or an array. Arrays are a bit less common, // since if argument was strongly-typed as an array, it would have bound to the array-based overload. - if (tasks is List tasksAsList) + if (tasks.GetType() == typeof(List)) { - return WhenAny((ReadOnlySpan)CollectionsMarshal.AsSpan(tasksAsList)); + return WhenAnyCore((ReadOnlySpan)CollectionsMarshal.AsSpan(Unsafe.As>(tasks))); } if (tasks is TTask[] tasksAsArray) { - return WhenAny((ReadOnlySpan)tasksAsArray); + return WhenAnyCore((ReadOnlySpan)tasksAsArray); } int count = tasksAsCollection.Count; @@ -6624,9 +6740,24 @@ public static Task> WhenAny(params Task[] tasks) { ArgumentNullException.ThrowIfNull(tasks); - return WhenAny((ReadOnlySpan>)tasks); + return WhenAnyCore((ReadOnlySpan>)tasks); } + /// + /// Creates a task that will complete when any of the supplied tasks have completed. + /// + /// The tasks to wait on for completion. + /// A task that represents the completion of one of the supplied tasks. The return Task's Result is the task that completed. + /// + /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state + /// with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state. + /// + /// + /// The array contained a null task, or was empty. + /// + public static Task> WhenAny(params ReadOnlySpan> tasks) => + WhenAnyCore(tasks); + /// Creates a task that will complete when either of the supplied tasks have completed. /// The first task to wait on for completion. /// The second task to wait on for completion. diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadBlockingInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadBlockingInfo.cs new file mode 100644 index 000000000000..6deed17e8f5d --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadBlockingInfo.cs @@ -0,0 +1,194 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace System.Threading +{ + // Tracks some kinds of blocking on the thread, like waiting on locks where it may be useful to know when debugging which + // thread owns the lock. + // + // Notes: + // - The type, some fields, and some other members may be used by debuggers (noted specifically below), so take care when + // renaming them + // - There is a native version of this struct in CoreCLR, used by Monitor to fold in its blocking info here. The struct is + // blittable with sequential layout to support that. + // + // Debuggers may use this info by evaluating expressions to enumerate the blocking infos for a thread. For example: + // - Evaluate "System.Threading.ThreadBlockingInfo.t_first" to obtain the first pointer to a blocking info for the current + // thread + // - While there is a non-null pointer to a blocking info: + // - Evaluate "(*(System.Threading.ThreadBlockingInfo*)ptr).fieldOrProperty", where "ptr" is the blocking info pointer + // value, to get the field and relevant property getter values below + // - Use the _objectKind field value to determine what kind of blocking is occurring + // - Get the LockOwnerOSThreadId and LockOwnerManagedThreadId property getter values. If the blocking is waiting for a + // lock and the lock is currently owned by a thread, one of these properties will return a nonzero value that can be + // used to identify the lock owner thread. + // - Use the _next field value to obtain the next pointer to a blocking info for the thread + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct ThreadBlockingInfo + { +#if CORECLR + // In CoreCLR, for the Monitor object kinds, the object ptr will be a pointer to a native AwareLock object. This + // relative offset indicates the location of the field holding the lock owner OS thread ID (the field is of type + // size_t), and is used to get that info by the LockOwnerOSThreadId property. The offset is not zero currently, so zero + // is used to determine if the static field has been initialized. + // + // This mechanism is used instead of using an FCall in the property getter such that the property can be more easily + // evaluated by a debugger. + private static int s_monitorObjectOffsetOfLockOwnerOSThreadId; +#endif + + // Points to the first (most recent) blocking info for the thread. The _next field points to the next-most-recent + // blocking info for the thread, or null if there are no more. Blocking can be reentrant in some cases, such as on UI + // threads where reentrant waits are used, or if a SynchronizationContext wait override is set. + [ThreadStatic] + private static ThreadBlockingInfo* t_first; // may be used by debuggers + + // This pointer can be used to obtain the object relevant to the blocking. For native object kinds, it points to the + // native object (for Monitor object kinds in CoreCLR, it points to a native AwareLock object). For managed object + // kinds, it points to a stack location containing the managed object reference. + private void* _objectPtr; // may be used by debuggers + + // Indicates the type of object relevant to the blocking + private ObjectKind _objectKind; // may be used by debuggers + + // The timeout in milliseconds for the wait, -1 for infinite timeout + private int _timeoutMs; // may be used by debuggers + + // Points to the next-most-recent blocking info for the thread + private ThreadBlockingInfo* _next; // may be used by debuggers + + private void Push(void* objectPtr, ObjectKind objectKind, int timeoutMs) + { + Debug.Assert(objectPtr != null); + + _objectPtr = objectPtr; + _objectKind = objectKind; + _timeoutMs = timeoutMs; + _next = t_first; + t_first = (ThreadBlockingInfo*)Unsafe.AsPointer(ref this); + } + + private void Pop() + { + Debug.Assert(_objectPtr != null); + Debug.Assert(t_first != null); + Debug.Assert(t_first->_next == _next); + + t_first = _next; + _objectPtr = null; + } + + // If the blocking is associated with a lock of some kind that has thread affinity and tracks the owner's OS thread ID, + // returns the OS thread ID of the thread that currently owns the lock. Otherwise, returns 0. A return value of 0 may + // indicate that the associated lock is currently not owned by a thread, or that the information could not be + // determined. + // + // Calls to native helpers are avoided in the property getter such that it can be more easily evaluated by a debugger. + public ulong LockOwnerOSThreadId // the getter may be used by debuggers + { + get + { + Debug.Assert(_objectPtr != null); + + switch (_objectKind) + { + case ObjectKind.MonitorLock: + case ObjectKind.MonitorWait: + // The Monitor object kinds are only used by CoreCLR, and only the OS thread ID is reported +#if CORECLR + if (s_monitorObjectOffsetOfLockOwnerOSThreadId != 0) + { + return *(nuint*)((nint)_objectPtr + s_monitorObjectOffsetOfLockOwnerOSThreadId); + } +#endif + return 0; + + case ObjectKind.Lock: + return ((Lock)Unsafe.AsRef(_objectPtr)).OwningOSThreadId; + + default: + Debug.Assert(_objectKind == ObjectKind.Condition); +#if NATIVEAOT + return ((Condition)Unsafe.AsRef(_objectPtr)).AssociatedLock.OwningOSThreadId; +#else + return 0; +#endif + } + } + } + + // If the blocking is associated with a lock of some kind that has thread affinity and tracks the owner's managed thread + // ID, returns the managed thread ID of the thread that currently owns the lock. Otherwise, returns 0. A return value of + // 0 may indicate that the associated lock is currently not owned by a thread, or that the information could not be + // determined. + // + // Calls to native helpers are avoided in the property getter such that it can be more easily evaluated by a debugger. + public int LockOwnerManagedThreadId // the getter may be used by debuggers + { + get + { + Debug.Assert(_objectPtr != null); + + switch (_objectKind) + { + case ObjectKind.MonitorLock: + case ObjectKind.MonitorWait: + // The Monitor object kinds are only used by CoreCLR, and only the OS thread ID is reported + return 0; + + case ObjectKind.Lock: + return ((Lock)Unsafe.AsRef(_objectPtr)).OwningManagedThreadId; + + default: + Debug.Assert(_objectKind == ObjectKind.Condition); +#if NATIVEAOT + return ((Condition)Unsafe.AsRef(_objectPtr)).AssociatedLock.OwningManagedThreadId; +#else + return 0; +#endif + } + } + } + + public unsafe ref struct Scope + { + private object? _object; + private ThreadBlockingInfo _blockingInfo; + +#pragma warning disable CS9216 // casting Lock to object + public Scope(Lock lockObj, int timeoutMs) : this(lockObj, ObjectKind.Lock, timeoutMs) { } +#pragma warning restore CS9216 + +#if NATIVEAOT + public Scope(Condition condition, int timeoutMs) : this(condition, ObjectKind.Condition, timeoutMs) { } +#endif + + private Scope(object obj, ObjectKind objectKind, int timeoutMs) + { + _object = obj; + _blockingInfo.Push(Unsafe.AsPointer(ref _object), objectKind, timeoutMs); + } + + public void Dispose() + { + if (_object is not null) + { + _blockingInfo.Pop(); + _object = null; + } + } + } + + public enum ObjectKind // may be used by debuggers + { + MonitorLock, // maps to DebugBlockingItemType::DebugBlock_MonitorCriticalSection in coreclr + MonitorWait, // maps to DebugBlockingItemType::DebugBlock_MonitorEvent in coreclr + Lock, + Condition + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadLocal.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadLocal.cs index 8890cde64f70..aa0c2e4478ca 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadLocal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadLocal.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Numerics; // A class that provides a simple, lightweight implementation of thread-local lazy-initialization, where a value is initialized once per accessing // thread; this provides an alternative to using a ThreadStatic static variable and having @@ -552,40 +553,15 @@ private static int GetNewTableSize(int minSize) } Debug.Assert(minSize > 0); - // - // Round up the size to the next power of 2 - // - // The algorithm takes three steps: - // input -> subtract one -> propagate 1-bits to the right -> add one - // - // Let's take a look at the 3 steps in both interesting cases: where the input - // is (Example 1) and isn't (Example 2) a power of 2. - // - // Example 1: 100000 -> 011111 -> 011111 -> 100000 - // Example 2: 011010 -> 011001 -> 011111 -> 100000 - // - int newSize = minSize; - - // Step 1: Decrement - newSize--; - - // Step 2: Propagate 1-bits to the right. - newSize |= newSize >> 1; - newSize |= newSize >> 2; - newSize |= newSize >> 4; - newSize |= newSize >> 8; - newSize |= newSize >> 16; - - // Step 3: Increment - newSize++; + uint newSize = BitOperations.RoundUpToPowerOf2((uint)minSize); // Don't set newSize to more than Array.MaxArrayLength - if ((uint)newSize > Array.MaxLength) + if (newSize > Array.MaxLength) { - newSize = Array.MaxLength; + newSize = (uint)Array.MaxLength; } - return newSize; + return (int)newSize; } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs index cc7c76922d99..7eef607ef106 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs @@ -21,23 +21,23 @@ internal sealed partial class ThreadPoolWorkQueue internal static class WorkStealingQueueList { #pragma warning disable CA1825 // avoid the extra generic instantiation for Array.Empty(); this is the only place we'll ever create this array - private static volatile WorkStealingQueue[] _queues = new WorkStealingQueue[0]; + private static WorkStealingQueue[] s_queues = new WorkStealingQueue[0]; #pragma warning restore CA1825 - public static WorkStealingQueue[] Queues => _queues; + public static WorkStealingQueue[] Queues => s_queues; public static void Add(WorkStealingQueue queue) { Debug.Assert(queue != null); while (true) { - WorkStealingQueue[] oldQueues = _queues; + WorkStealingQueue[] oldQueues = s_queues; Debug.Assert(Array.IndexOf(oldQueues, queue) < 0); var newQueues = new WorkStealingQueue[oldQueues.Length + 1]; Array.Copy(oldQueues, newQueues, oldQueues.Length); newQueues[^1] = queue; - if (Interlocked.CompareExchange(ref _queues, newQueues, oldQueues) == oldQueues) + if (Interlocked.CompareExchange(ref s_queues, newQueues, oldQueues) == oldQueues) { break; } @@ -49,7 +49,7 @@ public static void Remove(WorkStealingQueue queue) Debug.Assert(queue != null); while (true) { - WorkStealingQueue[] oldQueues = _queues; + WorkStealingQueue[] oldQueues = s_queues; if (oldQueues.Length == 0) { return; @@ -77,7 +77,7 @@ public static void Remove(WorkStealingQueue queue) Array.Copy(oldQueues, pos + 1, newQueues, pos, newQueues.Length - pos); } - if (Interlocked.CompareExchange(ref _queues, newQueues, oldQueues) == oldQueues) + if (Interlocked.CompareExchange(ref s_queues, newQueues, oldQueues) == oldQueues) { break; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Type.cs b/src/libraries/System.Private.CoreLib/src/System/Type.cs index 24be352778c8..7281867487a0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Type.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Type.cs @@ -705,20 +705,12 @@ public override int GetHashCode() [Obsolete(Obsoletions.ReflectionOnlyLoadingMessage, DiagnosticId = Obsoletions.ReflectionOnlyLoadingDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static Type? ReflectionOnlyGetType(string typeName, bool throwIfNotFound, bool ignoreCase) => throw new PlatformNotSupportedException(SR.PlatformNotSupported_ReflectionOnly); - public static Binder DefaultBinder - { - get - { - if (s_defaultBinder == null) - { - DefaultBinder binder = new DefaultBinder(); - Interlocked.CompareExchange(ref s_defaultBinder, binder, null); - } - return s_defaultBinder!; - } - } + public static Binder DefaultBinder => + s_defaultBinder ?? + Interlocked.CompareExchange(ref s_defaultBinder, new DefaultBinder(), null) ?? + s_defaultBinder; - private static volatile Binder? s_defaultBinder; + private static Binder? s_defaultBinder; public static readonly char Delimiter = '.'; public static readonly Type[] EmptyTypes = Array.Empty(); diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt128.cs b/src/libraries/System.Private.CoreLib/src/System/UInt128.cs index ec195239ca98..f988ab886ec8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt128.cs @@ -1588,6 +1588,9 @@ public static UInt128 CreateTruncating(TOther value) /// static UInt128 INumberBase.MinMagnitudeNumber(UInt128 x, UInt128 y) => Min(x, y); + /// + static UInt128 INumberBase.MultiplyAddEstimate(UInt128 left, UInt128 right, UInt128 addend) => (left * right) + addend; + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out UInt128 result) => TryConvertFromChecked(value, out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt16.cs b/src/libraries/System.Private.CoreLib/src/System/UInt16.cs index fcc863a6310a..999ad1bedd9c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt16.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt16.cs @@ -707,6 +707,9 @@ public static ushort CreateTruncating(TOther value) /// static ushort INumberBase.MinMagnitudeNumber(ushort x, ushort y) => Min(x, y); + /// + static ushort INumberBase.MultiplyAddEstimate(ushort left, ushort right, ushort addend) => (ushort)((left * right) + addend); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out ushort result) => TryConvertFromChecked(value, out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt32.cs b/src/libraries/System.Private.CoreLib/src/System/UInt32.cs index 8487630193ec..07603a068449 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt32.cs @@ -740,6 +740,9 @@ public static uint CreateTruncating(TOther value) /// static uint INumberBase.MinMagnitudeNumber(uint x, uint y) => Min(x, y); + /// + static uint INumberBase.MultiplyAddEstimate(uint left, uint right, uint addend) => (left * right) + addend; + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out uint result) => TryConvertFromChecked(value, out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt64.cs b/src/libraries/System.Private.CoreLib/src/System/UInt64.cs index dc12c5c006a8..3d95d606ee19 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt64.cs @@ -739,6 +739,9 @@ public static ulong CreateTruncating(TOther value) /// static ulong INumberBase.MinMagnitudeNumber(ulong x, ulong y) => Min(x, y); + /// + static ulong INumberBase.MultiplyAddEstimate(ulong left, ulong right, ulong addend) => (left * right) + addend; + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out ulong result) => TryConvertFromChecked(value, out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs index 42c58a5d0baa..2659d5d6c14f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs @@ -758,6 +758,9 @@ public static nuint CreateTruncating(TOther value) /// static nuint INumberBase.MinMagnitudeNumber(nuint x, nuint y) => Min(x, y); + /// + static nuint INumberBase.MultiplyAddEstimate(nuint left, nuint right, nuint addend) => (nuint)((left * right) + addend); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out nuint result) => TryConvertFromChecked(value, out result); diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs index f3b28edf1112..f76e4f0eebd1 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs @@ -1305,7 +1305,7 @@ public int Compare(Member x, Member y) return x._baseTypeIndex - y._baseTypeIndex; } - internal static DataMemberConflictComparer Singleton = new DataMemberConflictComparer(); + internal static readonly DataMemberConflictComparer Singleton = new DataMemberConflictComparer(); } } @@ -1491,7 +1491,7 @@ public int Compare(DataMember? x, DataMember? y) return string.CompareOrdinal(x.Name, y.Name); } - internal static DataMemberComparer Singleton = new DataMemberComparer(); + internal static readonly DataMemberComparer Singleton = new DataMemberComparer(); } /// diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlSerializableServices.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlSerializableServices.cs index ffa24e873bd9..2740e34ca3c3 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlSerializableServices.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlSerializableServices.cs @@ -62,7 +62,7 @@ public static void WriteNodes(XmlWriter xmlWriter, XmlNode?[]? nodes) nodes[i]!.WriteTo(xmlWriter); } - internal static string AddDefaultSchemaMethodName = "AddDefaultSchema"; + internal const string AddDefaultSchemaMethodName = "AddDefaultSchema"; public static void AddDefaultSchema(XmlSchemaSet schemas, XmlQualifiedName typeQName) { ArgumentNullException.ThrowIfNull(schemas); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlDocument.cs b/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlDocument.cs index 42f275027562..a7f9c855edfa 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlDocument.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlDocument.cs @@ -125,10 +125,10 @@ private static readonly (string key, int hash)[] s_nameTableSeeds = new[] private XmlAttribute? _namespaceXml; - internal static EmptyEnumerator EmptyEnumerator = new EmptyEnumerator(); - internal static IXmlSchemaInfo NotKnownSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.NotKnown); - internal static IXmlSchemaInfo ValidSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.Valid); - internal static IXmlSchemaInfo InvalidSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.Invalid); + internal static readonly EmptyEnumerator EmptyEnumerator = new EmptyEnumerator(); + internal static readonly IXmlSchemaInfo NotKnownSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.NotKnown); + internal static readonly IXmlSchemaInfo ValidSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.Valid); + internal static readonly IXmlSchemaInfo InvalidSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.Invalid); // Initializes a new instance of the XmlDocument class. public XmlDocument() : this(new XmlImplementation()) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs index 05f8bdc0bcbb..072991c236d7 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs @@ -114,19 +114,19 @@ internal abstract class DatatypeImplementation : XmlSchemaDatatype private const int anySimpleTypeIndex = 11; - internal static XmlQualifiedName QnAnySimpleType = new XmlQualifiedName("anySimpleType", XmlReservedNs.NsXs); - internal static XmlQualifiedName QnAnyType = new XmlQualifiedName("anyType", XmlReservedNs.NsXs); + internal static readonly XmlQualifiedName QnAnySimpleType = new XmlQualifiedName("anySimpleType", XmlReservedNs.NsXs); + internal static readonly XmlQualifiedName QnAnyType = new XmlQualifiedName("anyType", XmlReservedNs.NsXs); //Create facet checkers - internal static FacetsChecker stringFacetsChecker = new StringFacetsChecker(); - internal static FacetsChecker miscFacetsChecker = new MiscFacetsChecker(); - internal static FacetsChecker numeric2FacetsChecker = new Numeric2FacetsChecker(); - internal static FacetsChecker binaryFacetsChecker = new BinaryFacetsChecker(); - internal static FacetsChecker dateTimeFacetsChecker = new DateTimeFacetsChecker(); - internal static FacetsChecker durationFacetsChecker = new DurationFacetsChecker(); - internal static FacetsChecker listFacetsChecker = new ListFacetsChecker(); - internal static FacetsChecker qnameFacetsChecker = new QNameFacetsChecker(); - internal static FacetsChecker unionFacetsChecker = new UnionFacetsChecker(); + internal static readonly FacetsChecker stringFacetsChecker = new StringFacetsChecker(); + internal static readonly FacetsChecker miscFacetsChecker = new MiscFacetsChecker(); + internal static readonly FacetsChecker numeric2FacetsChecker = new Numeric2FacetsChecker(); + internal static readonly FacetsChecker binaryFacetsChecker = new BinaryFacetsChecker(); + internal static readonly FacetsChecker dateTimeFacetsChecker = new DateTimeFacetsChecker(); + internal static readonly FacetsChecker durationFacetsChecker = new DurationFacetsChecker(); + internal static readonly FacetsChecker listFacetsChecker = new ListFacetsChecker(); + internal static readonly FacetsChecker qnameFacetsChecker = new QNameFacetsChecker(); + internal static readonly FacetsChecker unionFacetsChecker = new UnionFacetsChecker(); static DatatypeImplementation() { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/Inference/Infer.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/Inference/Infer.cs index 9c7e3c6e4f87..dfc8b6fe880d 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/Inference/Infer.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/Inference/Infer.cs @@ -15,26 +15,26 @@ namespace System.Xml.Schema /// public sealed class XmlSchemaInference { - internal static XmlQualifiedName ST_boolean = new XmlQualifiedName("boolean", XmlSchema.Namespace); - internal static XmlQualifiedName ST_byte = new XmlQualifiedName("byte", XmlSchema.Namespace); - internal static XmlQualifiedName ST_unsignedByte = new XmlQualifiedName("unsignedByte", XmlSchema.Namespace); - internal static XmlQualifiedName ST_short = new XmlQualifiedName("short", XmlSchema.Namespace); - internal static XmlQualifiedName ST_unsignedShort = new XmlQualifiedName("unsignedShort", XmlSchema.Namespace); - internal static XmlQualifiedName ST_int = new XmlQualifiedName("int", XmlSchema.Namespace); - internal static XmlQualifiedName ST_unsignedInt = new XmlQualifiedName("unsignedInt", XmlSchema.Namespace); - internal static XmlQualifiedName ST_long = new XmlQualifiedName("long", XmlSchema.Namespace); - internal static XmlQualifiedName ST_unsignedLong = new XmlQualifiedName("unsignedLong", XmlSchema.Namespace); - internal static XmlQualifiedName ST_integer = new XmlQualifiedName("integer", XmlSchema.Namespace); - internal static XmlQualifiedName ST_decimal = new XmlQualifiedName("decimal", XmlSchema.Namespace); - internal static XmlQualifiedName ST_float = new XmlQualifiedName("float", XmlSchema.Namespace); - internal static XmlQualifiedName ST_double = new XmlQualifiedName("double", XmlSchema.Namespace); - internal static XmlQualifiedName ST_duration = new XmlQualifiedName("duration", XmlSchema.Namespace); - internal static XmlQualifiedName ST_dateTime = new XmlQualifiedName("dateTime", XmlSchema.Namespace); - internal static XmlQualifiedName ST_time = new XmlQualifiedName("time", XmlSchema.Namespace); - internal static XmlQualifiedName ST_date = new XmlQualifiedName("date", XmlSchema.Namespace); - internal static XmlQualifiedName ST_gYearMonth = new XmlQualifiedName("gYearMonth", XmlSchema.Namespace); - internal static XmlQualifiedName ST_string = new XmlQualifiedName("string", XmlSchema.Namespace); - internal static XmlQualifiedName ST_anySimpleType = new XmlQualifiedName("anySimpleType", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_boolean = new XmlQualifiedName("boolean", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_byte = new XmlQualifiedName("byte", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_unsignedByte = new XmlQualifiedName("unsignedByte", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_short = new XmlQualifiedName("short", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_unsignedShort = new XmlQualifiedName("unsignedShort", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_int = new XmlQualifiedName("int", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_unsignedInt = new XmlQualifiedName("unsignedInt", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_long = new XmlQualifiedName("long", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_unsignedLong = new XmlQualifiedName("unsignedLong", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_integer = new XmlQualifiedName("integer", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_decimal = new XmlQualifiedName("decimal", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_float = new XmlQualifiedName("float", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_double = new XmlQualifiedName("double", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_duration = new XmlQualifiedName("duration", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_dateTime = new XmlQualifiedName("dateTime", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_time = new XmlQualifiedName("time", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_date = new XmlQualifiedName("date", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_gYearMonth = new XmlQualifiedName("gYearMonth", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_string = new XmlQualifiedName("string", XmlSchema.Namespace); + internal static readonly XmlQualifiedName ST_anySimpleType = new XmlQualifiedName("anySimpleType", XmlSchema.Namespace); internal static XmlQualifiedName[] SimpleTypes = { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationEventSource.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationEventSource.cs index 8747cc9a39d8..7b6846b1d5d1 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationEventSource.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationEventSource.cs @@ -9,7 +9,7 @@ namespace System.Xml.Serialization Name = "System.Xml.Serialzation.XmlSerialization")] internal sealed class XmlSerializationEventSource : EventSource { - internal static XmlSerializationEventSource Log = new XmlSerializationEventSource(); + internal static readonly XmlSerializationEventSource Log = new XmlSerializationEventSource(); [Event(EventIds.XmlSerializerExpired, Level = EventLevel.Informational)] internal void XmlSerializerExpired(string serializerName, string type) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/XPath/Internal/XPathEmptyIterator.cs b/src/libraries/System.Private.Xml/src/System/Xml/XPath/Internal/XPathEmptyIterator.cs index 6c9f61662249..e2fd6bb1de81 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/XPath/Internal/XPathEmptyIterator.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/XPath/Internal/XPathEmptyIterator.cs @@ -33,6 +33,6 @@ public override bool MoveNext() public override void Reset() { } // -- Instance - public static XPathEmptyIterator Instance = new XPathEmptyIterator(); + public static readonly XPathEmptyIterator Instance = new XPathEmptyIterator(); } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/SourceLineInfo.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/SourceLineInfo.cs index 793f75f324d4..e6a7b8e5487c 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/SourceLineInfo.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/SourceLineInfo.cs @@ -55,7 +55,7 @@ public SourceLineInfo(string? uriString, Location start, Location end) /// private const int NoSourceMagicNumber = 0xfeefee; - public static SourceLineInfo NoSource = new SourceLineInfo(string.Empty, NoSourceMagicNumber, 0, NoSourceMagicNumber, 0); + public static readonly SourceLineInfo NoSource = new SourceLineInfo(string.Empty, NoSourceMagicNumber, 0, NoSourceMagicNumber, 0); public bool IsNoSource { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/Compiler.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/Compiler.cs index d5f44fe82342..918dfa58a2cd 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/Compiler.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/Compiler.cs @@ -445,7 +445,7 @@ internal sealed class DecimalFormatDecl public readonly string NanSymbol; public readonly char[] Characters; - public static DecimalFormatDecl Default = new DecimalFormatDecl(new XmlQualifiedName(), "Infinity", "NaN", ".,%\u20300#;-"); + public static readonly DecimalFormatDecl Default = new DecimalFormatDecl(new XmlQualifiedName(), "Infinity", "NaN", ".,%\u20300#;-"); public DecimalFormatDecl(XmlQualifiedName name, string infinitySymbol, string nanSymbol, string characters) { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/XsltLoader.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/XsltLoader.cs index 49c19730c53f..7148aacf2294 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/XsltLoader.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/XsltLoader.cs @@ -30,13 +30,13 @@ internal sealed class XsltLoader : IErrorHelper private Stylesheet? _curStylesheet; // Current stylesheet private Template? _curTemplate; // Current template - internal static QilName nullMode = F.QName(string.Empty); + internal static readonly QilName nullMode = F.QName(string.Empty); // Flags which control attribute versioning - public static int V1Opt = 1; - public static int V1Req = 2; - public static int V2Opt = 4; - public static int V2Req = 8; + public const int V1Opt = 1; + public const int V1Req = 2; + public const int V2Opt = 4; + public const int V2Req = 8; public void Load(Compiler compiler, object stylesheet, XmlResolver? xmlResolver, XmlResolver? origResolver) { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/Compiler.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/Compiler.cs index d77aef50b0eb..20e82a4a9374 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/Compiler.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/Compiler.cs @@ -91,7 +91,7 @@ internal sealed class Compiler private int _rtfCount; // Used to load Built In templates - public static XmlQualifiedName BuiltInMode = new XmlQualifiedName("*", string.Empty); + public static readonly XmlQualifiedName BuiltInMode = new XmlQualifiedName("*", string.Empty); internal KeywordsTable Atoms { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/VariableAction.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/VariableAction.cs index e23f7c449850..7b40f06718a3 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/VariableAction.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/VariableAction.cs @@ -17,7 +17,7 @@ internal enum VariableType internal class VariableAction : ContainerAction, IXsltContextVariable { - public static object BeingComputedMark = new object(); + public static readonly object BeingComputedMark = new object(); private const int ValueCalculated = 2; protected XmlQualifiedName? name; diff --git a/src/libraries/System.Private.Xml/tests/System.Private.Xml.Tests.csproj b/src/libraries/System.Private.Xml/tests/System.Private.Xml.Tests.csproj index 30fe5d7a261a..24a6ecf7559f 100644 --- a/src/libraries/System.Private.Xml/tests/System.Private.Xml.Tests.csproj +++ b/src/libraries/System.Private.Xml/tests/System.Private.Xml.Tests.csproj @@ -10,7 +10,7 @@ - WasmTestOnBrowser + WasmTestOnChrome $(TestArchiveRoot)browserornodejs/ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ $(DefineConstants);TARGET_BROWSER diff --git a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs index dd48ebd0d9e0..c2588f7fde33 100644 --- a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs +++ b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingAssembly.cs @@ -72,7 +72,7 @@ public override SecurityRuleSet SecurityRuleSet get { return UnderlyingAssembly.SecurityRuleSet; } } -#if NETCOREAPP +#if NET [Obsolete] [RequiresAssemblyFiles] #endif @@ -91,7 +91,7 @@ public override MethodInfo? EntryPoint get { return UnderlyingAssembly.EntryPoint; } } -#if NETCOREAPP +#if NET [Obsolete] [RequiresAssemblyFiles] #endif @@ -200,7 +200,7 @@ public override Type[] GetTypes() return UnderlyingAssembly.GetTypes(); } -#if NETCOREAPP +#if NET [Obsolete] #endif public override bool GlobalAssemblyCache diff --git a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs index d69e26494a77..21e19635db40 100644 --- a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs +++ b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs @@ -25,7 +25,7 @@ public override Assembly Assembly internal const string UnknownStringMessageInRAF = "Returns for modules with no file path"; -#if NETCOREAPP +#if NET [RequiresAssemblyFiles(UnknownStringMessageInRAF)] #endif public override string FullyQualifiedName @@ -48,7 +48,7 @@ public override Guid ModuleVersionId get { return UnderlyingModule.ModuleVersionId; } } -#if NETCOREAPP +#if NET [RequiresAssemblyFiles(UnknownStringMessageInRAF)] #endif public override string Name diff --git a/src/libraries/System.Reflection.DispatchProxy/src/System.Reflection.DispatchProxy.csproj b/src/libraries/System.Reflection.DispatchProxy/src/System.Reflection.DispatchProxy.csproj index 2d021999f586..17c279ab5213 100644 --- a/src/libraries/System.Reflection.DispatchProxy/src/System.Reflection.DispatchProxy.csproj +++ b/src/libraries/System.Reflection.DispatchProxy/src/System.Reflection.DispatchProxy.csproj @@ -16,6 +16,7 @@ + diff --git a/src/libraries/System.Reflection.DispatchProxy/tests/DispatchProxyTests.cs b/src/libraries/System.Reflection.DispatchProxy/tests/DispatchProxyTests.cs index 960917631875..df16833b724e 100644 --- a/src/libraries/System.Reflection.DispatchProxy/tests/DispatchProxyTests.cs +++ b/src/libraries/System.Reflection.DispatchProxy/tests/DispatchProxyTests.cs @@ -557,7 +557,7 @@ public static void Proxy_Declares_Interface_Properties(bool useGenericCreate) Assert.NotNull(propertyInfo); } -#if NETCOREAPP +#if NET [Fact] public static void Invoke_Event_Add_And_Remove_And_Raise_Invokes_Correct_Methods_Generic_And_Non_Generic_Tests() { diff --git a/src/libraries/System.Reflection.DispatchProxy/tests/TrimmingTests/System.Reflection.DispatchProxy.TrimmingTests.proj b/src/libraries/System.Reflection.DispatchProxy/tests/TrimmingTests/System.Reflection.DispatchProxy.TrimmingTests.proj index da4a46f2ae14..adb54eab7335 100644 --- a/src/libraries/System.Reflection.DispatchProxy/tests/TrimmingTests/System.Reflection.DispatchProxy.TrimmingTests.proj +++ b/src/libraries/System.Reflection.DispatchProxy/tests/TrimmingTests/System.Reflection.DispatchProxy.TrimmingTests.proj @@ -1,5 +1,12 @@ + + + + true + + + diff --git a/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.cs b/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.cs index f79ee4288df6..c5dcbd65fb18 100644 --- a/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.cs +++ b/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.cs @@ -54,6 +54,8 @@ public virtual void EmitWriteLine(string value) { } public abstract void EndExceptionBlock(); public abstract void EndScope(); public abstract void MarkLabel(System.Reflection.Emit.Label loc); + public void MarkSequencePoint(System.Diagnostics.SymbolStore.ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn) { throw null; } + protected virtual void MarkSequencePointCore(System.Diagnostics.SymbolStore.ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn) { throw null; } public virtual void ThrowException([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] System.Type excType) { } public abstract void UsingNamespace(string usingNamespace); } @@ -73,6 +75,8 @@ protected LocalBuilder() { } public override bool IsPinned { get { throw null; } } public override int LocalIndex { get { throw null; } } public override System.Type LocalType { get { throw null; } } + public void SetLocalSymInfo(string name) { throw null; } + protected virtual void SetLocalSymInfoCore(string name) { throw null; } } public abstract partial class ParameterBuilder { diff --git a/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.csproj b/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.csproj index 6894be6dab8f..4364c5c0b56d 100644 --- a/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.csproj +++ b/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.csproj @@ -9,5 +9,6 @@ + diff --git a/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs b/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs index 3690bf72a4c8..995ab5679fc7 100644 --- a/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs +++ b/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs @@ -398,6 +398,10 @@ protected ModuleBuilder() { } public override string ScopeName { get { throw null; } } public void CreateGlobalFunctions() { } protected abstract void CreateGlobalFunctionsCore(); + [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] + public System.Diagnostics.SymbolStore.ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType) { throw null; } + public System.Diagnostics.SymbolStore.ISymbolDocumentWriter DefineDocument(string url, System.Guid language = default) { throw null; } + protected virtual System.Diagnostics.SymbolStore.ISymbolDocumentWriter DefineDocumentCore(string url, System.Guid language = default) { throw null; } public System.Reflection.Emit.EnumBuilder DefineEnum(string name, System.Reflection.TypeAttributes visibility, System.Type underlyingType) { throw null; } protected abstract System.Reflection.Emit.EnumBuilder DefineEnumCore(string name, System.Reflection.TypeAttributes visibility, System.Type underlyingType); public System.Reflection.Emit.MethodBuilder DefineGlobalMethod(string name, System.Reflection.MethodAttributes attributes, System.Reflection.CallingConventions callingConvention, System.Type? returnType, System.Type[]? parameterTypes) { throw null; } @@ -479,9 +483,11 @@ public PersistedAssemblyBuilder(System.Reflection.AssemblyName name, System.Refl public override System.Reflection.Module ManifestModule { get { throw null; } } [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Defining a dynamic assembly requires dynamic code.")] protected override System.Reflection.Emit.ModuleBuilder DefineDynamicModuleCore(string name) { throw null; } - protected override System.Reflection.Emit.ModuleBuilder? GetDynamicModuleCore(string name) { throw null; } [System.CLSCompliantAttribute(false)] public System.Reflection.Metadata.Ecma335.MetadataBuilder GenerateMetadata(out System.Reflection.Metadata.BlobBuilder ilStream, out System.Reflection.Metadata.BlobBuilder mappedFieldData) { throw null; } + [System.CLSCompliantAttribute(false)] + public System.Reflection.Metadata.Ecma335.MetadataBuilder GenerateMetadata(out System.Reflection.Metadata.BlobBuilder ilStream, out System.Reflection.Metadata.BlobBuilder mappedFieldData, out System.Reflection.Metadata.Ecma335.MetadataBuilder pdbBuilder) { throw null; } + protected override System.Reflection.Emit.ModuleBuilder? GetDynamicModuleCore(string name) { throw null; } public override System.Reflection.AssemblyName GetName(bool copiedName) { throw null; } public void Save(string assemblyFileName) { throw null; } public void Save(System.IO.Stream stream) { throw null; } diff --git a/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.csproj b/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.csproj index 44f0feefe67d..89a1505b49ce 100644 --- a/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.csproj +++ b/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.csproj @@ -11,5 +11,6 @@ + \ No newline at end of file diff --git a/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx b/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx index 4ab50a83684c..6103dbef1f15 100644 --- a/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx +++ b/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx @@ -297,4 +297,10 @@ Not supported in an array method of a type definition that is not complete. + + Invalid source document. + + + Unmatching symbol scope. + \ No newline at end of file diff --git a/src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj b/src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj index 0c34ef45f448..57b328a0bbde 100644 --- a/src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj +++ b/src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj @@ -23,6 +23,8 @@ + + diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ILGeneratorImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ILGeneratorImpl.cs index dcb92654e124..d4b40387e30e 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ILGeneratorImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ILGeneratorImpl.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.SymbolStore; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Runtime.InteropServices; @@ -17,6 +18,8 @@ internal sealed class ILGeneratorImpl : ILGenerator private readonly BlobBuilder _builder; private readonly InstructionEncoder _il; private readonly ControlFlowBuilder _cfBuilder; + private readonly Scope _scope; // scope of the entire method body + private Scope _currentScope; private bool _hasDynamicStackAllocation; private int _maxStackDepth; private int _currentStackDepth; // Current stack labelStartDepth @@ -24,10 +27,11 @@ internal sealed class ILGeneratorImpl : ILGenerator // Adjustment to add to _maxStackDepth for incorrect/invalid IL. For example, when branch // instructions branches backward with non zero stack depths targeting the same label. private int _depthAdjustment; - private List _locals = new(); + private int _localCount; private Dictionary _labelTable = new(2); private List> _memberReferences = new(); private List _exceptionStack = new(); + private Dictionary> _documentToSequencePoints = new(); internal ILGeneratorImpl(MethodBuilderImpl methodBuilder, int size) { @@ -37,13 +41,18 @@ internal ILGeneratorImpl(MethodBuilderImpl methodBuilder, int size) _builder = new BlobBuilder(Math.Max(size, DefaultSize)); _cfBuilder = new ControlFlowBuilder(); _il = new InstructionEncoder(_builder, _cfBuilder); + _scope = new Scope(_il.Offset, parent: null); + _currentScope = _scope; } internal int GetMaxStack() => Math.Min(ushort.MaxValue, _maxStackDepth + _depthAdjustment); internal List> GetMemberReferences() => _memberReferences; internal InstructionEncoder Instructions => _il; internal bool HasDynamicStackAllocation => _hasDynamicStackAllocation; - internal List Locals => _locals; + internal List Locals => _scope.GetAllLocals(); + internal int LocalCount => _localCount; + internal Scope Scope => _scope; + internal Dictionary> DocumentToSequencePoints => _documentToSequencePoints; public override int ILOffset => _il.Offset; @@ -198,16 +207,19 @@ public override void BeginFinallyBlock() public override void BeginScope() { - // TODO: No-op, will be implemented wit PDB support + _currentScope._children ??= new List(); + Scope newScope = new Scope(_il.Offset, _currentScope); + _currentScope._children.Add(newScope); + _currentScope = newScope; } public override LocalBuilder DeclareLocal(Type localType, bool pinned) { ArgumentNullException.ThrowIfNull(localType); - LocalBuilder local = new LocalBuilderImpl(_locals.Count, localType, _methodBuilder, pinned); - _locals.Add(local); - + _currentScope._locals ??= new List(); + LocalBuilder local = new LocalBuilderImpl(_localCount++, localType, _methodBuilder, pinned); + _currentScope._locals.Add(local); return local; } @@ -731,7 +743,13 @@ public override void EndExceptionBlock() public override void EndScope() { - // TODO: No-op, will be implemented wit PDB support + if (_currentScope._parent == null) + { + throw new InvalidOperationException(SR.InvalidOperation_UnmatchingSymScope); + } + + _currentScope._endOffset = _il.Offset; + _currentScope = _currentScope._parent; } public override void MarkLabel(Label loc) @@ -777,9 +795,32 @@ public override void MarkLabel(Label loc) } } + protected override void MarkSequencePointCore(ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn) + { + if (document is SymbolDocumentWriter symbolDoc) + { + if (_documentToSequencePoints.TryGetValue(symbolDoc, out List? sequencePoints)) + { + sequencePoints.Add(new SequencePoint(_il.Offset, startLine, startColumn, endLine, endColumn)); + } + else + { + sequencePoints = new List { new SequencePoint(_il.Offset, startLine, startColumn, endLine, endColumn) }; + _documentToSequencePoints.Add(symbolDoc, sequencePoints); + } + } + else + { + throw new ArgumentException(SR.InvalidOperation_InvalidDocument, nameof(document)); + } + } + public override void UsingNamespace(string usingNamespace) { - // TODO: No-op, will be implemented wit PDB support + ArgumentException.ThrowIfNullOrEmpty(usingNamespace); + + _currentScope._importNamespaces ??= new List(); + _currentScope._importNamespaces.Add(usingNamespace); } } @@ -817,4 +858,40 @@ internal LabelInfo(LabelHandle metaLabel) internal int _startDepth; // Stack labelStartDepth, with -1 meaning unknown. internal LabelHandle _metaLabel; } + + internal sealed class Scope + { + internal Scope(int offset, Scope? parent) + { + _startOffset = offset; + _parent = parent; + } + + internal Scope? _parent; + internal List? _children; + internal List? _locals; + internal List? _importNamespaces; + internal int _startOffset; + internal int _endOffset; + + internal List GetAllLocals() + { + List locals = new List(); + + if (_locals != null) + { + locals.AddRange(_locals); + } + + if (_children != null) + { + foreach (Scope child in _children) + { + locals.AddRange(child.GetAllLocals()); + } + } + + return locals; + } + } } diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/LocalBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/LocalBuilderImpl.cs index fa9bffbec434..406d08120476 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/LocalBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/LocalBuilderImpl.cs @@ -10,6 +10,7 @@ internal sealed class LocalBuilderImpl : LocalBuilder private readonly Type _localType; private readonly MethodInfo _method; private readonly bool _isPinned; + private string? _name; #endregion #region Constructor @@ -24,6 +25,19 @@ internal LocalBuilderImpl(int index, Type type, MethodInfo method, bool isPinned #region Internal Members internal MethodInfo GetMethodBuilder() => _method; + internal string? Name => _name; + #endregion + + #region LocalBuilder Override + protected override void SetLocalSymInfoCore(string name) + { + if (_method.DeclaringType is TypeBuilder typeBuilder && typeBuilder.IsCreated()) + { + throw new InvalidOperationException(SR.InvalidOperation_TypeHasBeenCreated); + } + + _name = name; + } #endregion #region LocalVariableInfo Override diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs index 0349186b717f..b78526adda13 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.SymbolStore; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; @@ -25,6 +26,7 @@ internal sealed class ModuleBuilderImpl : ModuleBuilder private readonly Guid _moduleVersionId; private Dictionary? _moduleReferences; private List? _customAttributes; + private Dictionary _docHandles = new(); private int _nextTypeDefRowId = 1; private int _nextMethodDefRowId = 1; private int _nextFieldDefRowId = 1; @@ -34,6 +36,7 @@ internal sealed class ModuleBuilderImpl : ModuleBuilder private bool _coreTypesFullyPopulated; private bool _hasGlobalBeenCreated; private Type?[]? _coreTypes; + private MetadataBuilder _pdbBuilder = new(); private static readonly Type[] s_coreTypes = { typeof(void), typeof(object), typeof(bool), typeof(char), typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(string), typeof(nint), typeof(nuint), typeof(TypedReference) }; @@ -108,7 +111,7 @@ internal Type GetTypeFromCoreAssembly(CoreTypeId typeId) return null; } - internal void AppendMetadata(MethodBodyStreamEncoder methodBodyEncoder, BlobBuilder fieldDataBuilder) + internal void AppendMetadata(MethodBodyStreamEncoder methodBodyEncoder, BlobBuilder fieldDataBuilder, out MetadataBuilder pdbBuilder) { // Add module metadata ModuleDefinitionHandle moduleHandle = _metadataBuilder.AddModule( @@ -190,6 +193,8 @@ internal void AppendMetadata(MethodBodyStreamEncoder methodBodyEncoder, BlobBuil { AddGenericTypeParametersAndConstraintsCustomAttributes(param._parentHandle, param); } + + pdbBuilder = _pdbBuilder; } private void WriteInterfaceImplementations(TypeBuilderImpl typeBuilder, TypeDefinitionHandle typeHandle) @@ -339,7 +344,8 @@ private void PopulateTokensForTypesAndItsMembers() } } - private void WriteMethods(List methods, List genericParams, MethodBodyStreamEncoder methodBodyEncoder) + private void WriteMethods(List methods, List genericParams, + MethodBodyStreamEncoder methodBodyEncoder) { foreach (MethodBuilderImpl method in methods) { @@ -348,9 +354,10 @@ private void WriteMethods(List methods, List methods, List>.Enumerator enumerator = il.DocumentToSequencePoints.GetEnumerator(); + if (il.DocumentToSequencePoints.Count > 1) + { + // sequence points spans multiple docs + _pdbBuilder.AddMethodDebugInformation(default, PopulateMultiDocSequencePointsBlob(enumerator, localSignatureHandle)); + } + else // single document sequence point + { + int previousNonHiddenStartLine = -1; + int previousNonHiddenStartColumn = -1; + enumerator.MoveNext(); + BlobBuilder spBlobBuilder = new BlobBuilder(); + spBlobBuilder.WriteCompressedInteger(MetadataTokens.GetRowNumber(localSignatureHandle)); + PopulateSequencePointsBlob(spBlobBuilder, enumerator.Current.Value, ref previousNonHiddenStartLine, ref previousNonHiddenStartColumn); + _pdbBuilder.AddMethodDebugInformation(GetDocument(enumerator.Current.Key), _pdbBuilder.GetOrAddBlob(spBlobBuilder)); + } + } + + Scope scope = il.Scope; + scope._endOffset = il.ILOffset; // Outer most scope covers the entire method body, so haven't closed by the user. + + AddLocalScope(methodHandle, parentImport: default, MetadataTokens.LocalVariableHandle(_pdbBuilder.GetRowCount(TableIndex.LocalVariable) + 1), scope); + } + + private BlobHandle PopulateMultiDocSequencePointsBlob(Dictionary>.Enumerator enumerator, StandaloneSignatureHandle localSignature) + { + BlobBuilder spBlobBuilder = new BlobBuilder(); + int previousNonHiddenStartLine = -1; + int previousNonHiddenStartColumn = -1; + enumerator.MoveNext(); + KeyValuePair> pair = enumerator.Current; + + // header: + spBlobBuilder.WriteCompressedInteger(MetadataTokens.GetRowNumber(localSignature)); + spBlobBuilder.WriteCompressedInteger(MetadataTokens.GetRowNumber(GetDocument(pair.Key))); + + // First sequence point record + PopulateSequencePointsBlob(spBlobBuilder, pair.Value, ref previousNonHiddenStartLine, ref previousNonHiddenStartColumn); + + while (enumerator.MoveNext()) + { + pair = enumerator.Current; + spBlobBuilder.WriteCompressedInteger(0); + spBlobBuilder.WriteCompressedInteger(MetadataTokens.GetRowNumber(GetDocument(pair.Key))); + PopulateSequencePointsBlob(spBlobBuilder, pair.Value, ref previousNonHiddenStartLine, ref previousNonHiddenStartColumn); + } + + return _pdbBuilder.GetOrAddBlob(spBlobBuilder); + } + + private static void PopulateSequencePointsBlob(BlobBuilder spBlobBuilder, List sequencePoints, ref int previousNonHiddenStartLine, ref int previousNonHiddenStartColumn) + { + for (int i = 0; i < sequencePoints.Count; i++) + { + // IL offset delta: + if (i > 0) + { + spBlobBuilder.WriteCompressedInteger(sequencePoints[i].Offset - sequencePoints[i - 1].Offset); + } + else + { + spBlobBuilder.WriteCompressedInteger(sequencePoints[i].Offset); + } + + if (sequencePoints[i].IsHidden) + { + spBlobBuilder.WriteUInt16(0); + continue; + } + + // Delta Lines & Columns: + SerializeDeltaLinesAndColumns(spBlobBuilder, sequencePoints[i]); + + // delta Start Lines & Columns: + if (previousNonHiddenStartLine < 0) + { + Debug.Assert(previousNonHiddenStartColumn < 0); + spBlobBuilder.WriteCompressedInteger(sequencePoints[i].StartLine); + spBlobBuilder.WriteCompressedInteger(sequencePoints[i].StartColumn); + } + else + { + spBlobBuilder.WriteCompressedSignedInteger(sequencePoints[i].StartLine - previousNonHiddenStartLine); + spBlobBuilder.WriteCompressedSignedInteger(sequencePoints[i].StartColumn - previousNonHiddenStartColumn); + } + + previousNonHiddenStartLine = sequencePoints[i].StartLine; + previousNonHiddenStartColumn = sequencePoints[i].StartColumn; + } + } + + private void AddLocalScope(MethodDefinitionHandle methodHandle, ImportScopeHandle parentImport, LocalVariableHandle firstLocalVariableHandle, Scope scope) + { + parentImport = GetImportScopeHandle(scope._importNamespaces, parentImport); + firstLocalVariableHandle = GetLocalVariableHandle(scope._locals, firstLocalVariableHandle); + _pdbBuilder.AddLocalScope(methodHandle, parentImport, firstLocalVariableHandle, + constantList: MetadataTokens.LocalConstantHandle(1), scope._startOffset, scope._endOffset - scope._startOffset); + + if (scope._children != null) + { + foreach (Scope childScope in scope._children) + { + AddLocalScope(methodHandle, parentImport, MetadataTokens.LocalVariableHandle(_pdbBuilder.GetRowCount(TableIndex.LocalVariable) + 1), childScope); + } + } + } + + private LocalVariableHandle GetLocalVariableHandle(List? locals, LocalVariableHandle firstLocalHandleOfLastScope) + { + if (locals != null) + { + bool firstLocalSet = false; + foreach (LocalBuilderImpl local in locals) + { + if (!string.IsNullOrEmpty(local.Name)) + { + LocalVariableHandle localHandle = _pdbBuilder.AddLocalVariable(LocalVariableAttributes.None, local.LocalIndex, + local.Name == null ? _pdbBuilder.GetOrAddString(string.Empty) : _pdbBuilder.GetOrAddString(local.Name)); + if (!firstLocalSet) + { + firstLocalHandleOfLastScope = localHandle; + firstLocalSet = true; + } + } + } + } + + return firstLocalHandleOfLastScope; + } + + private ImportScopeHandle GetImportScopeHandle(List? importNamespaces, ImportScopeHandle parent) + { + if (importNamespaces == null) + { + return default; + } + + BlobBuilder importBlob = new BlobBuilder(); + + foreach (string importNs in importNamespaces) + { + importBlob.WriteByte((byte)ImportDefinitionKind.ImportNamespace); + importBlob.WriteCompressedInteger(MetadataTokens.GetHeapOffset(_pdbBuilder.GetOrAddBlobUTF8(importNs))); + } + + return _pdbBuilder.AddImportScope(parent, _pdbBuilder.GetOrAddBlob(importBlob)); + } + + private static void SerializeDeltaLinesAndColumns(BlobBuilder spBuilder, SequencePoint sequencePoint) + { + int deltaLines = sequencePoint.EndLine - sequencePoint.StartLine; + int deltaColumns = sequencePoint.EndColumn - sequencePoint.StartColumn; + + // only hidden sequence points have zero width + Debug.Assert(deltaLines != 0 || deltaColumns != 0 || sequencePoint.IsHidden); + + spBuilder.WriteCompressedInteger(deltaLines); + + if (deltaLines == 0) + { + spBuilder.WriteCompressedInteger(deltaColumns); + } + else + { + Debug.Assert(deltaLines > 0); + spBuilder.WriteCompressedSignedInteger(deltaColumns); + } + } + + private DocumentHandle GetDocument(SymbolDocumentWriter docWriter) + { + if (!_docHandles.TryGetValue(docWriter, out DocumentHandle handle)) + { + handle = AddDocument(docWriter.URL, docWriter.Language, docWriter.HashAlgorithm, docWriter.Hash); + _docHandles.Add(docWriter, handle); + } + + return handle; + } + + private DocumentHandle AddDocument(string url, Guid language, Guid hashAlgorithm, byte[]? hash) => + _pdbBuilder.AddDocument( + name: _pdbBuilder.GetOrAddDocumentName(url), + hashAlgorithm: hashAlgorithm == default ? default : _pdbBuilder.GetOrAddGuid(hashAlgorithm), + hash: hash == null ? default : _metadataBuilder.GetOrAddBlob(hash), + language: language == default ? default : _pdbBuilder.GetOrAddGuid(language)); + private void FillMemberReferences(ILGeneratorImpl il) { foreach (KeyValuePair pair in il.GetMemberReferences()) @@ -892,8 +1095,7 @@ private EntityHandle GetHandleForMember(MemberInfo member) } private static bool IsConstructedFromTypeBuilder(Type type) => type.IsConstructedGenericType && - (type.GetGenericTypeDefinition() is TypeBuilderImpl || - ContainsTypeBuilder(type.GetGenericArguments())); + (type.GetGenericTypeDefinition() is TypeBuilderImpl || ContainsTypeBuilder(type.GetGenericArguments())); internal static bool ContainsTypeBuilder(Type[] genericArguments) { @@ -1158,5 +1360,10 @@ private static SignatureCallingConvention GetSignatureConvention(CallingConventi CallingConvention.FastCall => SignatureCallingConvention.FastCall, _ => SignatureCallingConvention.Default, }; + + protected override ISymbolDocumentWriter DefineDocumentCore(string url, Guid language = default) + { + return new SymbolDocumentWriter(url, language); + } } } diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/Pdb/SequencePoint.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/Pdb/SequencePoint.cs new file mode 100644 index 000000000000..f82fea8986ff --- /dev/null +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/Pdb/SequencePoint.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Reflection.Emit +{ + internal sealed class SequencePoint + { + public const int HiddenLine = 0xfeefee; + + public int Offset { get; } + public int StartLine { get; } + public int EndLine { get; } + public int StartColumn { get; } + public int EndColumn { get; } + + public SequencePoint(int offset, int startLine, int startColumn, int endLine, int endColumn) + { + Offset = offset; + StartLine = startLine; + EndLine = endLine; + StartColumn = startColumn; + EndColumn = endColumn; + } + + public bool IsHidden => StartLine == HiddenLine; + } +} diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/Pdb/SymbolDocumentWriter.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/Pdb/SymbolDocumentWriter.cs new file mode 100644 index 000000000000..a07b44620fa8 --- /dev/null +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/Pdb/SymbolDocumentWriter.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.SymbolStore; + +namespace System.Reflection.Emit +{ + internal sealed class SymbolDocumentWriter : ISymbolDocumentWriter + { + internal readonly Guid _language; + internal readonly string _url; + private Guid _hashAlgorithm; + private byte[]? _hash; + private byte[]? _source; + + internal string URL => _url; + internal Guid Language => _language; + internal Guid HashAlgorithm => _hashAlgorithm; + internal byte[]? Hash => _hash; + internal byte[]? Source => _source; + + public SymbolDocumentWriter(string url, Guid language) + { + _language = language; + _url = url; + } + + public void SetCheckSum(Guid algorithmId, byte[] checkSum) + { + _hashAlgorithm = algorithmId; + _hash = checkSum; + } + + public void SetSource(byte[] source) + { + _source = source; + } + } +} diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/PersistedAssemblyBuilder.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/PersistedAssemblyBuilder.cs index 12fbf4704b7b..ad127094936e 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/PersistedAssemblyBuilder.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/PersistedAssemblyBuilder.cs @@ -98,11 +98,10 @@ private void SaveInternal(Stream stream) { ArgumentNullException.ThrowIfNull(stream); - PopulateAssemblyMetadata(out BlobBuilder ilStream, out BlobBuilder fieldData); + PopulateAssemblyMetadata(out BlobBuilder ilStream, out BlobBuilder fieldData, out _); WritePEImage(stream, ilStream, fieldData); } - /// /// Generates the metadata for the . /// @@ -110,16 +109,33 @@ private void SaveInternal(Stream stream) /// Outputs bytes that includes all field RVA data defined in the assembly. /// A that includes all members defined in the Assembly. /// A module not defined for the assembly. - /// The metadata already populated for the assembly before. + /// The metadata already populated for the assembly previously. [CLSCompliant(false)] public MetadataBuilder GenerateMetadata(out BlobBuilder ilStream, out BlobBuilder mappedFieldData) { - PopulateAssemblyMetadata(out ilStream, out mappedFieldData); + PopulateAssemblyMetadata(out ilStream, out mappedFieldData, out _); + + return _metadataBuilder; + } + + /// + /// Generates the metadata for the . + /// + /// Outputs bytes that includes all method's IL (body) emitted. + /// Outputs bytes that includes all field RVA data defined in the assembly. + /// Outputs that includes PDB metadata. + /// A that includes all members defined in the Assembly. + /// A module not defined for the assembly. + /// The metadata already populated for the assembly previously. + [CLSCompliant(false)] + public MetadataBuilder GenerateMetadata(out BlobBuilder ilStream, out BlobBuilder mappedFieldData, out MetadataBuilder pdbBuilder) + { + PopulateAssemblyMetadata(out ilStream, out mappedFieldData, out pdbBuilder); return _metadataBuilder; } - private void PopulateAssemblyMetadata(out BlobBuilder ilStream, out BlobBuilder fieldData) + private void PopulateAssemblyMetadata(out BlobBuilder ilStream, out BlobBuilder fieldData, out MetadataBuilder pdbBuilder) { if (_module == null) { @@ -147,7 +163,7 @@ private void PopulateAssemblyMetadata(out BlobBuilder ilStream, out BlobBuilder ); _module.WriteCustomAttributes(_customAttributes, assemblyHandle); - _module.AppendMetadata(new MethodBodyStreamEncoder(ilStream), fieldData); + _module.AppendMetadata(new MethodBodyStreamEncoder(ilStream), fieldData, out pdbBuilder); _isMetadataPopulated = true; } diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs index a698d744212a..733c79ad86d5 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs @@ -321,8 +321,6 @@ protected override void DefineMethodOverrideCore(MethodInfo methodInfoBody, Meth throw new ArgumentException(SR.ArgumentException_BadMethodImplBody); } Type baseType = methodInfoDeclaration.DeclaringType!; - ValidateBaseType(baseType, methodInfoDeclaration.Name); - ValidateImplementedMethod(methodInfoBody, methodInfoDeclaration); _methodOverrides ??= new(); if (_methodOverrides.TryGetValue(baseType, out List<(MethodInfo ifaceMethod, MethodInfo targetMethod)>? im)) @@ -342,24 +340,6 @@ protected override void DefineMethodOverrideCore(MethodInfo methodInfoBody, Meth } } - private void ValidateBaseType(Type baseType, string methodName) - { - if (baseType.IsInterface) - { - if (!IsInterfaceImplemented(baseType)) - { - throw ArgumentExceptionInvalidMethodOverride(methodName); - } - - return; - } - - if (!baseType.IsAssignableFrom(_typeParent)) - { - throw ArgumentExceptionInvalidMethodOverride(methodName); - } - } - private bool IsInterfaceImplemented(Type interfaceType) { if (_interfaces != null) @@ -390,47 +370,6 @@ private bool IsInterfaceImplemented(Type interfaceType) private ArgumentException ArgumentExceptionInvalidMethodOverride(string methodName) => new ArgumentException(SR.Format(SR.Argument_InvalidMethodOverride, FullName, methodName), "methodInfoBody"); - private void ValidateImplementedMethod(MethodInfo methodInfoBody, MethodInfo methodInfoDeclaration) - { - if ((methodInfoBody.IsVirtual || methodInfoBody.IsStatic) && - (methodInfoDeclaration.IsAbstract || methodInfoDeclaration.IsVirtual) && - methodInfoDeclaration.ReturnType.IsAssignableFrom(methodInfoBody.ReturnType)) - { - ParameterInfo[] bodyParameters = methodInfoBody.GetParameters(); - ParameterInfo[] declarationParameters = methodInfoDeclaration.GetParameters(); - if (bodyParameters.Length == declarationParameters.Length) - { - for (int i = 0; i < bodyParameters.Length; i++) - { - Type? bodyType = bodyParameters[i].ParameterType; - Type? declType = declarationParameters[i].ParameterType; - - if (bodyType.IsArray != declType.IsArray || - bodyType.IsByRef != declType.IsByRef || - bodyType.IsPointer != declType.IsPointer) - { - throw ArgumentExceptionInvalidMethodOverride(methodInfoDeclaration.Name); - } - - if (bodyType.HasElementType || declType.HasElementType) - { - bodyType = bodyType.GetElementType(); - declType = declType.GetElementType(); - } - - if (bodyType == null || !bodyType.Equals(declType)) - { - throw ArgumentExceptionInvalidMethodOverride(methodInfoDeclaration.Name); - } - } - - return; - } - } - - throw ArgumentExceptionInvalidMethodOverride(methodInfoDeclaration.Name); - } - protected override TypeBuilder DefineNestedTypeCore(string name, TypeAttributes attr, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, Type[]? interfaces, PackingSize packSize, int typeSize) { diff --git a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs index e533a2344662..54199f67e1f9 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs @@ -134,38 +134,6 @@ public void DefineMethodOverride_TypeCreated_ThrowsInvalidOperationException() Assert.Throws(() => type.DefineMethodOverride(method, declaration)); } - [Fact] - public void DefineMethodOverride_MethodNotVirtual_ThrowsArgumentException() - { - AssemblySaveTools.PopulateAssemblyBuilderAndTypeBuilder(out TypeBuilder type); - MethodBuilder method = type.DefineMethod("M", MethodAttributes.Public, typeof(int), null); - ILGenerator ilGenerator = method.GetILGenerator(); - ilGenerator.Emit(OpCodes.Ldc_I4, 2); - ilGenerator.Emit(OpCodes.Ret); - - type.AddInterfaceImplementation(typeof(DefineMethodOverrideInterface)); - MethodInfo declaration = typeof(DefineMethodOverrideInterface).GetMethod(method.Name); - - Assert.Throws("methodInfoBody", () => type.DefineMethodOverride(method, declaration)); - } - - [Fact] - public void DefineMethodOverride_TypeDoesNotImplementOrInheritMethod_ThrowsArgumentException() - { - AssemblySaveTools.PopulateAssemblyBuilderAndTypeBuilder(out TypeBuilder type); - MethodBuilder method = type.DefineMethod("M", MethodAttributes.Public | MethodAttributes.Virtual, typeof(int), null); - method.GetILGenerator().Emit(OpCodes.Ret); - MethodInfo interfaceMethod = typeof(DefineMethodOverrideInterface).GetMethod("M"); - MethodInfo baseTypeMethod = typeof(DefineMethodOverrideClass).GetMethod("M"); - - Assert.Throws("methodInfoBody", () => type.DefineMethodOverride(method, interfaceMethod)); - Assert.Throws("methodInfoBody", () => type.DefineMethodOverride(method, baseTypeMethod)); - - type.AddInterfaceImplementation(typeof(GenericInterface)); - MethodInfo implementingMethod = typeof(GenericInterface).GetMethod(nameof(GenericInterface.Method)); - Assert.Throws("methodInfoBody", () => type.DefineMethodOverride(method, implementingMethod)); - } - [Fact] public void DefineMethodOverride_CalledAgainWithSameDeclaration_ThrowsArgumentException() { @@ -188,24 +156,6 @@ public void DefineMethodOverride_CalledAgainWithSameDeclaration_ThrowsArgumentEx Assert.Throws(() => type.DefineMethodOverride(method2, declaration)); } - [Theory] - [InlineData(typeof(int), new Type[0])] - [InlineData(typeof(int), new Type[] { typeof(int), typeof(int) })] - [InlineData(typeof(int), new Type[] { typeof(string), typeof(string) })] - [InlineData(typeof(int), new Type[] { typeof(int), typeof(string), typeof(bool) })] - [InlineData(typeof(string), new Type[] { typeof(string), typeof(int) })] - public void DefineMethodOverride_BodyAndDeclarationHaveDifferentSignatures_ThrowsArgumentException(Type returnType, Type[] parameterTypes) - { - AssemblySaveTools.PopulateAssemblyBuilderAndTypeBuilder(out TypeBuilder type); - MethodBuilder method = type.DefineMethod("M", MethodAttributes.Public | MethodAttributes.Virtual, returnType, parameterTypes); - method.GetILGenerator().Emit(OpCodes.Ret); - type.AddInterfaceImplementation(typeof(InterfaceWithMethod)); - - MethodInfo declaration = typeof(InterfaceWithMethod).GetMethod(nameof(InterfaceWithMethod.Method)); - - Assert.Throws(() => type.DefineMethodOverride(method, declaration)); - } - public interface GenericInterface { T Method(); @@ -429,22 +379,6 @@ public interface InterfaceDerivedFromOtherInterface : DefineMethodOverrideInterf public string M2(int a); } - public abstract class PartialImplementation : InterfaceDerivedFromOtherInterface - { - public int M() => 1; - public abstract string M2(int a); - } - - public interface IDefaultImplementation - { - void Method() => Console.WriteLine("Hello"); - } - - public interface IStaticAbstract - { - static abstract void Method(); - } - [Fact] public void CreateType_ValidateMethods() { diff --git a/src/libraries/System.Reflection.Emit/tests/PortablePdb/ILGeneratorScopesAndSequencePointsTests.cs b/src/libraries/System.Reflection.Emit/tests/PortablePdb/ILGeneratorScopesAndSequencePointsTests.cs new file mode 100644 index 000000000000..abdbf5e4047b --- /dev/null +++ b/src/libraries/System.Reflection.Emit/tests/PortablePdb/ILGeneratorScopesAndSequencePointsTests.cs @@ -0,0 +1,372 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.SymbolStore; +using System.IO; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; +using Xunit; + +namespace System.Reflection.Emit.Tests +{ + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public class ILGeneratorScopesAndSequencePointsTests + { + [Fact] + public void SetLocalSymInfo_UsingNamespace_Validations() + { + ModuleBuilder mb = new PersistedAssemblyBuilder(new AssemblyName("MyAssembly2"), typeof(object).Assembly).DefineDynamicModule("MyModule2"); + TypeBuilder tb = mb.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class); + ILGenerator il = tb.DefineMethod("SumMethod", MethodAttributes.Public | MethodAttributes.Static).GetILGenerator(); + LocalBuilder local = il.DeclareLocal(typeof(int)); + Assert.Throws("usingNamespace", () => il.UsingNamespace(null)); + Assert.Throws("usingNamespace", () => il.UsingNamespace(string.Empty)); + Assert.Throws("name", () => local.SetLocalSymInfo(null)); + il.Emit(OpCodes.Ret); + tb.CreateType(); + Assert.Throws(() => local.SetLocalSymInfo("myInt1")); // type created + } + + [Fact] + public void LocalWithoutSymInfoWillNotAddedToLocalVariablesTable() + { + PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(new AssemblyName("MyAssembly"), typeof(object).Assembly); + ModuleBuilder mb = ab.DefineDynamicModule("MyModule"); + TypeBuilder tb = mb.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class); + ISymbolDocumentWriter srcDoc = mb.DefineDocument("MySourceFile.cs", SymLanguageType.CSharp); + MethodBuilder method = tb.DefineMethod("SumMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(int), [typeof(int), typeof(int)]); + ILGenerator il = method.GetILGenerator(); + LocalBuilder local = il.DeclareLocal(typeof(int)); + local.SetLocalSymInfo("myInt1"); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Add); + il.Emit(OpCodes.Stloc_0); + LocalBuilder local2 = il.DeclareLocal(typeof(string)); + il.Emit(OpCodes.Ldstr, "MyAssembly"); + il.Emit(OpCodes.Stloc, local2); + LocalBuilder local3 = il.DeclareLocal(typeof(int)); + local3.SetLocalSymInfo("myInt2"); + il.Emit(OpCodes.Ldc_I4_2); + il.Emit(OpCodes.Stloc_2); + il.Emit(OpCodes.Ldloc_2); + il.Emit(OpCodes.Ldloc_0); + il.Emit(OpCodes.Add); + il.Emit(OpCodes.Ret); + tb.CreateType(); + + MetadataBuilder mdb = ab.GenerateMetadata(out BlobBuilder _, out BlobBuilder _, out MetadataBuilder pdbMetadata); + + BlobBuilder portablePdbBlob = new BlobBuilder(); + PortablePdbBuilder pdbBuilder = new PortablePdbBuilder(pdbMetadata, mdb.GetRowCounts(), default); + pdbBuilder.Serialize(portablePdbBlob); + using TempFile pdbFile = TempFile.Create(); + using var pdbFileStream = new FileStream(pdbFile.Path, FileMode.Create, FileAccess.Write); + portablePdbBlob.WriteContentTo(pdbFileStream); + pdbFileStream.Close(); + + using var fs = new FileStream(pdbFile.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + using MetadataReaderProvider provider = MetadataReaderProvider.FromPortablePdbStream(fs); + MetadataReader reader = provider.GetMetadataReader(); + MethodDebugInformation mdi = reader.GetMethodDebugInformation(MetadataTokens.MethodDebugInformationHandle(method.MetadataToken)); + SequencePointCollection.Enumerator spcEnumerator = mdi.GetSequencePoints().GetEnumerator(); + Assert.False(spcEnumerator.MoveNext()); + + LocalScopeHandleCollection.Enumerator localScopes = reader.GetLocalScopes(MetadataTokens.MethodDefinitionHandle(method.MetadataToken)).GetEnumerator(); + Assert.True(localScopes.MoveNext()); + LocalScope localScope = reader.GetLocalScope(localScopes.Current); + LocalVariableHandleCollection.Enumerator localEnumerator = localScope.GetLocalVariables().GetEnumerator(); + Assert.True(localEnumerator.MoveNext()); + Assert.Equal("myInt1", reader.GetString(reader.GetLocalVariable(localEnumerator.Current).Name)); + Assert.True(localEnumerator.MoveNext()); + Assert.Equal("myInt2", reader.GetString(reader.GetLocalVariable(localEnumerator.Current).Name)); + Assert.False(localEnumerator.MoveNext()); + Assert.False(localScopes.MoveNext()); + } + + [Fact] + public void LocalsNamespacesWithinNestedScopes() + { + PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(new AssemblyName("MyAssembly"), typeof(object).Assembly); + ModuleBuilder mb = ab.DefineDynamicModule("MyModule"); + TypeBuilder tb = mb.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class); + ISymbolDocumentWriter srcDoc = mb.DefineDocument("MySourceFile.cs", SymLanguageType.CSharp); + MethodBuilder method = tb.DefineMethod("SumMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(int), [typeof(int), typeof(int)]); + ILGenerator il = method.GetILGenerator(); + LocalBuilder local = il.DeclareLocal(typeof(int)); + il.UsingNamespace("System"); + local.SetLocalSymInfo("myInt1"); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Add); + il.Emit(OpCodes.Stloc_0); + LocalBuilder local2 = il.DeclareLocal(typeof(string)); + local2.SetLocalSymInfo("myString"); + il.Emit(OpCodes.Ldstr, "MyAssembly"); + il.Emit(OpCodes.Stloc, local2); + il.BeginScope(); + il.UsingNamespace("System.Reflection"); + LocalBuilder local3 = il.DeclareLocal(typeof(AssemblyName)); + local3.SetLocalSymInfo("myAssembly"); + il.Emit(OpCodes.Ldloc_1); + il.Emit(OpCodes.Newobj, typeof(AssemblyName).GetConstructor([typeof(string)])); + il.Emit(OpCodes.Stloc_2); + il.BeginScope(); + LocalBuilder local4 = il.DeclareLocal(typeof(int)); + local4.SetLocalSymInfo("myInt2"); + LocalBuilder local5 = il.DeclareLocal(typeof(int)); + local5.SetLocalSymInfo("myInt3"); + il.Emit(OpCodes.Ldc_I4_2); + il.Emit(OpCodes.Stloc_3); + il.Emit(OpCodes.Ldc_I4_5); + il.Emit(OpCodes.Stloc_S, 4); + il.Emit(OpCodes.Ldloc_S, 4); + il.Emit(OpCodes.Ldloc_3); + il.Emit(OpCodes.Add); + il.Emit(OpCodes.Stloc_0); + il.EndScope(); + il.UsingNamespace("System.Reflection.Emit"); + il.EndScope(); + il.Emit(OpCodes.Ldloc_0); + il.Emit(OpCodes.Ret); + tb.CreateType(); + + MetadataBuilder mdb = ab.GenerateMetadata(out BlobBuilder _, out BlobBuilder _, out MetadataBuilder pdbMetadata); + + BlobBuilder portablePdbBlob = new BlobBuilder(); + PortablePdbBuilder pdbBuilder = new PortablePdbBuilder(pdbMetadata, mdb.GetRowCounts(), default); + pdbBuilder.Serialize(portablePdbBlob); + using TempFile pdbFile = TempFile.Create(); + using var pdbFileStream = new FileStream(pdbFile.Path, FileMode.Create, FileAccess.Write); + portablePdbBlob.WriteContentTo(pdbFileStream); + pdbFileStream.Close(); + + using var fs = new FileStream(pdbFile.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + using MetadataReaderProvider provider = MetadataReaderProvider.FromPortablePdbStream(fs); + MetadataReader reader = provider.GetMetadataReader(); + MethodDebugInformation mdi = reader.GetMethodDebugInformation(MetadataTokens.MethodDebugInformationHandle(method.MetadataToken)); + SequencePointCollection.Enumerator spcEnumerator = mdi.GetSequencePoints().GetEnumerator(); + Assert.False(spcEnumerator.MoveNext()); + + LocalScopeHandleCollection.Enumerator localScopes = reader.GetLocalScopes(MetadataTokens.MethodDefinitionHandle(method.MetadataToken)).GetEnumerator(); + Assert.True(localScopes.MoveNext()); + LocalScope localScope = reader.GetLocalScope(localScopes.Current); + Assert.Equal(0, localScope.StartOffset); + Assert.Equal(35, localScope.EndOffset); + LocalVariableHandleCollection.Enumerator localEnumerator = localScope.GetLocalVariables().GetEnumerator(); + Assert.True(localEnumerator.MoveNext()); + Assert.Equal("myInt1", reader.GetString(reader.GetLocalVariable(localEnumerator.Current).Name)); + Assert.True(localEnumerator.MoveNext()); + Assert.Equal("myString", reader.GetString(reader.GetLocalVariable(localEnumerator.Current).Name)); + Assert.False(localEnumerator.MoveNext()); + + ImportScope importScope = reader.GetImportScope(localScope.ImportScope); + Assert.True(importScope.Parent.IsNil); + ImportDefinitionCollection.Enumerator importEnumerator = importScope.GetImports().GetEnumerator(); + Assert.True(importEnumerator.MoveNext()); + ImportDefinition importDef = importEnumerator.Current; + Assert.Equal(ImportDefinitionKind.ImportNamespace, importDef.Kind); + BlobReader blobReader = reader.GetBlobReader(importDef.TargetNamespace); + Assert.Equal("System", blobReader.ReadUTF8(blobReader.Length)); + Assert.False(importEnumerator.MoveNext()); + + Assert.True(localScopes.MoveNext()); + LocalScope innerScope = reader.GetLocalScope(localScopes.Current); + Assert.Equal(10, innerScope.StartOffset); + Assert.Equal(33, innerScope.EndOffset); + localEnumerator = innerScope.GetLocalVariables().GetEnumerator(); + Assert.True(localEnumerator.MoveNext()); + Assert.Equal("myAssembly", reader.GetString(reader.GetLocalVariable(localEnumerator.Current).Name)); + Assert.False(localEnumerator.MoveNext()); + + ImportScope innerImport = reader.GetImportScope(innerScope.ImportScope); + Assert.Equal(importScope, reader.GetImportScope(innerImport.Parent)); + importEnumerator = innerImport.GetImports().GetEnumerator(); + Assert.True(importEnumerator.MoveNext()); + importDef = importEnumerator.Current; + Assert.Equal(ImportDefinitionKind.ImportNamespace, importDef.Kind); + blobReader = reader.GetBlobReader(importDef.TargetNamespace); + Assert.Equal("System.Reflection", blobReader.ReadUTF8(blobReader.Length)); + Assert.True(importEnumerator.MoveNext()); + importDef = importEnumerator.Current; + Assert.Equal(ImportDefinitionKind.ImportNamespace, importDef.Kind); + blobReader = reader.GetBlobReader(importDef.TargetNamespace); + Assert.Equal("System.Reflection.Emit", blobReader.ReadUTF8(blobReader.Length)); + Assert.False(importEnumerator.MoveNext()); + + Assert.True(localScopes.MoveNext()); + LocalScope innerMost = reader.GetLocalScope(localScopes.Current); + Assert.Equal(17, innerMost.StartOffset); + Assert.Equal(33, innerMost.EndOffset); + localEnumerator = innerMost.GetLocalVariables().GetEnumerator(); + Assert.True(localEnumerator.MoveNext()); + Assert.Equal("myInt2", reader.GetString(reader.GetLocalVariable(localEnumerator.Current).Name)); + Assert.True(localEnumerator.MoveNext()); + Assert.Equal("myInt3", reader.GetString(reader.GetLocalVariable(localEnumerator.Current).Name)); + Assert.False(localEnumerator.MoveNext()); + Assert.False(localScopes.MoveNext()); + + Assert.True(innerMost.ImportScope.IsNil); + } + + [Fact] + public void DefineDocument_MarkSequencePoint_Validations() + { + ModuleBuilder runtimeModule = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("T"), AssemblyBuilderAccess.Run).DefineDynamicModule("T"); + Assert.Throws(() => runtimeModule.DefineDocument("MySourceFile.cs", SymLanguageType.CSharp)); + + ModuleBuilder mb = new PersistedAssemblyBuilder(new AssemblyName("Assembly"), typeof(object).Assembly).DefineDynamicModule("MyModule"); + TypeBuilder tb = mb.DefineType("Type", TypeAttributes.Public | TypeAttributes.Class); + Assert.Throws("url", () => mb.DefineDocument(null)); + Assert.Throws("url", () => mb.DefineDocument(string.Empty)); + + ILGenerator il = tb.DefineMethod("Method", MethodAttributes.Public | MethodAttributes.Static).GetILGenerator(); + Assert.Throws("document", () => il.MarkSequencePoint(null, 0, 0, 0, 1)); + Assert.Throws("document", () => il.MarkSequencePoint(new TestDocument(), 0, 0, 0, 1)); + Assert.Throws("startLine", () => il.MarkSequencePoint(mb.DefineDocument("MySourceFile.cs"), -1, 1, 1, 1)); + Assert.Throws("startColumn", () => il.MarkSequencePoint(mb.DefineDocument("MySourceFile.cs"), 1, -1, 1, 1)); + Assert.Throws("endLine", () => il.MarkSequencePoint(mb.DefineDocument("MySourceFile.cs"), 1, 1, -1, 1)); + Assert.Throws("endColumn", () => il.MarkSequencePoint(mb.DefineDocument("MySourceFile.cs"), 1, 1, 1, -1)); + Assert.Throws("startLine", () => il.MarkSequencePoint(mb.DefineDocument("MySourceFile.cs"), 0x20000000, 1, 1, 1)); + Assert.Throws("startColumn", () => il.MarkSequencePoint(mb.DefineDocument("MySourceFile.cs"), 1, 0x10000, 1, 1)); + Assert.Throws("endLine", () => il.MarkSequencePoint(mb.DefineDocument("MySourceFile.cs"), 1, 1, 0x20000000, 1)); + Assert.Throws("endColumn", () => il.MarkSequencePoint(mb.DefineDocument("MySourceFile.cs"), 1, 1, 1, 0x10000)); + Assert.Throws("endColumn", () => il.MarkSequencePoint(mb.DefineDocument("MySourceFile.cs"), 1, 1, 1, 1)); + Assert.Throws("endLine", () => il.MarkSequencePoint(mb.DefineDocument("MySourceFile.cs"), 1, 1, 0, 1)); + } + + [Fact] + public void MultipleDocumentsAndSequencePoints() + { + PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(new AssemblyName("MyAssembly"), typeof(object).Assembly); + ModuleBuilder mb = ab.DefineDynamicModule("MyModule"); + TypeBuilder tb = mb.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class); + ISymbolDocumentWriter srcDoc1 = mb.DefineDocument("MySource1.cs", SymLanguageType.CSharp); + ISymbolDocumentWriter srcDoc2 = mb.DefineDocument("MySource2.cs", SymLanguageType.CSharp); + ISymbolDocumentWriter srcDoc3 = mb.DefineDocument("MySource3.cs", SymLanguageType.CSharp); + MethodBuilder method = tb.DefineMethod("SumMethod", MethodAttributes.Public | MethodAttributes.Static); + ILGenerator il1 = method.GetILGenerator(); + LocalBuilder local = il1.DeclareLocal(typeof(int)); + local.SetLocalSymInfo("MyInt"); + il1.MarkSequencePoint(srcDoc2, 7, 0, 7, 20); + il1.Emit(OpCodes.Ldarg_0); + il1.Emit(OpCodes.Ldarg_1); + il1.Emit(OpCodes.Add); + il1.Emit(OpCodes.Stloc_0); + il1.MarkSequencePoint(srcDoc1, 8, 0, 9, 18); + il1.Emit(OpCodes.Ldc_I4_2); + il1.Emit(OpCodes.Stloc_1); + il1.MarkSequencePoint(srcDoc1, 0xfeefee, 0, 0xfeefee, 0); // hidden sequence point + il1.Emit(OpCodes.Ldloc_0); + il1.Emit(OpCodes.Ldloc_1); + il1.Emit(OpCodes.Add); + il1.Emit(OpCodes.Stloc_0); + il1.MarkSequencePoint(srcDoc1, 11, 1, 11, 20); + il1.Emit(OpCodes.Ldloc_0); + il1.Emit(OpCodes.Ldloc_1); + il1.Emit(OpCodes.Add); + il1.Emit(OpCodes.Stloc_0); + il1.MarkSequencePoint(srcDoc3, 5, 0, 5, 20); + il1.Emit(OpCodes.Ldloc_0); + il1.Emit(OpCodes.Ret); + + MethodBuilder entryPoint = tb.DefineMethod("Main", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static); + ILGenerator il2 = entryPoint.GetILGenerator(); + il2.Emit(OpCodes.Ldc_I4_S, 10); + il2.Emit(OpCodes.Ldc_I4_1); + il2.Emit(OpCodes.Call, method); + il2.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", [typeof(int)])); + il2.Emit(OpCodes.Ret); + tb.CreateType(); + + MetadataBuilder mdb = ab.GenerateMetadata(out BlobBuilder _, out BlobBuilder _, out MetadataBuilder pdbMetadata); + + BlobBuilder portablePdbBlob = new BlobBuilder(); + PortablePdbBuilder pdbBuilder = new PortablePdbBuilder(pdbMetadata, mdb.GetRowCounts(), default); + pdbBuilder.Serialize(portablePdbBlob); + using TempFile pdbFile = TempFile.Create(); + using var pdbFileStream = new FileStream(pdbFile.Path, FileMode.Create, FileAccess.Write); + portablePdbBlob.WriteContentTo(pdbFileStream); + pdbFileStream.Close(); + + using var fs = new FileStream(pdbFile.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + using MetadataReaderProvider provider = MetadataReaderProvider.FromPortablePdbStream(fs); + MetadataReader reader = provider.GetMetadataReader(); + DocumentHandleCollection.Enumerator docEnumerator = reader.Documents.GetEnumerator(); + Assert.Equal(3, reader.Documents.Count); + Assert.True(docEnumerator.MoveNext()); + Document doc1 = reader.GetDocument(docEnumerator.Current); + Assert.Equal("MySource2.cs", reader.GetString(doc1.Name)); + Assert.Equal(SymLanguageType.CSharp, reader.GetGuid(doc1.Language)); + Assert.True(docEnumerator.MoveNext()); + Document doc2 = reader.GetDocument(docEnumerator.Current); + Assert.Equal("MySource1.cs", reader.GetString(doc2.Name)); + Assert.Equal(SymLanguageType.CSharp, reader.GetGuid(doc2.Language)); + Assert.True(docEnumerator.MoveNext()); + Document doc3 = reader.GetDocument(docEnumerator.Current); + Assert.Equal("MySource3.cs", reader.GetString(doc3.Name)); + Assert.Equal(SymLanguageType.CSharp, reader.GetGuid(doc3.Language)); + Assert.False(docEnumerator.MoveNext()); + + MethodDebugInformation mdi1 = reader.GetMethodDebugInformation(MetadataTokens.MethodDebugInformationHandle(method.MetadataToken)); + Assert.True(mdi1.Document.IsNil); + SequencePointCollection.Enumerator spcEnumerator = mdi1.GetSequencePoints().GetEnumerator(); + Assert.True(spcEnumerator.MoveNext()); + SequencePoint sp = spcEnumerator.Current; + Assert.Equal(doc1, reader.GetDocument(sp.Document)); + Assert.Equal(7, sp.StartLine); + Assert.False(sp.IsHidden); + Assert.Equal(0, sp.Offset); + Assert.Equal(0, sp.StartColumn); + Assert.Equal(7, sp.EndLine); + Assert.Equal(20, sp.EndColumn); + Assert.True(spcEnumerator.MoveNext()); + sp = spcEnumerator.Current; + Assert.Equal(doc2, reader.GetDocument(sp.Document)); + Assert.Equal(4, sp.Offset); + Assert.Equal(8, sp.StartLine); + Assert.Equal(0, sp.StartColumn); + Assert.Equal(9, sp.EndLine); + Assert.Equal(18, sp.EndColumn); + Assert.True(spcEnumerator.MoveNext()); + sp = spcEnumerator.Current; + Assert.Equal(doc2, reader.GetDocument(sp.Document)); + Assert.True(sp.IsHidden); + Assert.Equal(6, sp.Offset); + Assert.True(spcEnumerator.MoveNext()); + sp = spcEnumerator.Current; + Assert.Equal(doc2, reader.GetDocument(sp.Document)); + Assert.Equal(10, sp.Offset); + Assert.Equal(11, sp.StartLine); + Assert.Equal(1, sp.StartColumn); + Assert.Equal(11, sp.EndLine); + Assert.Equal(20, sp.EndColumn); + Assert.True(spcEnumerator.MoveNext()); + sp = spcEnumerator.Current; + Assert.Equal(doc3, reader.GetDocument(sp.Document)); + Assert.Equal(24, sp.Offset); + Assert.Equal(5, sp.StartLine); + Assert.Equal(0, sp.StartColumn); + Assert.Equal(5, sp.EndLine); + Assert.Equal(20, sp.EndColumn); + Assert.False(spcEnumerator.MoveNext()); + + LocalScopeHandleCollection.Enumerator localScopes = reader.GetLocalScopes(MetadataTokens.MethodDefinitionHandle(method.MetadataToken)).GetEnumerator(); + Assert.True(localScopes.MoveNext()); + LocalScope locals = reader.GetLocalScope(localScopes.Current); + Assert.Equal(0, locals.StartOffset); + Assert.Equal(16, locals.EndOffset); + LocalVariableHandleCollection.Enumerator localEnumerator = locals.GetLocalVariables().GetEnumerator(); + Assert.True(localEnumerator.MoveNext()); + Assert.Equal("MyInt", reader.GetString(reader.GetLocalVariable(localEnumerator.Current).Name)); + Assert.False(localEnumerator.MoveNext()); + Assert.False(localScopes.MoveNext()); + } + + private class TestDocument : ISymbolDocumentWriter + { + public void SetCheckSum(Guid algorithmId, byte[] checkSum) => throw new NotImplementedException(); + public void SetSource(byte[] source) => throw new NotImplementedException(); + } + } +} diff --git a/src/libraries/System.Reflection.Emit/tests/PortablePdb/PortablePdbStandalonePdbTest.cs b/src/libraries/System.Reflection.Emit/tests/PortablePdb/PortablePdbStandalonePdbTest.cs new file mode 100644 index 000000000000..e1ce56f151d8 --- /dev/null +++ b/src/libraries/System.Reflection.Emit/tests/PortablePdb/PortablePdbStandalonePdbTest.cs @@ -0,0 +1,234 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Immutable; +using System.Diagnostics.SymbolStore; +using System.IO; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; +using System.Reflection.PortableExecutable; +using Xunit; + +namespace System.Reflection.Emit.Tests +{ + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public class PortablePdbStandalonePdbTest + { + [Fact] + public void CreateStandalonePDBAndVerifyTest() + { + using (TempFile pdbFile = TempFile.Create()) + using (TempFile file = TempFile.Create()) + { + MethodBuilder method1, entryPoint; + MetadataBuilder metadataBuilder = GenerateAssemblyAndMetadata(out method1, out entryPoint, out BlobBuilder ilStream, out MetadataBuilder pdbMetadata); + MethodDefinitionHandle entryPointHandle = MetadataTokens.MethodDefinitionHandle(entryPoint.MetadataToken); + + BlobBuilder portablePdbBlob = new BlobBuilder(); + PortablePdbBuilder pdbBuilder = new PortablePdbBuilder(pdbMetadata, metadataBuilder.GetRowCounts(), entryPointHandle); + BlobContentId pdbContentId = pdbBuilder.Serialize(portablePdbBlob); + using var pdbFileStream = new FileStream(pdbFile.Path, FileMode.Create, FileAccess.Write); + portablePdbBlob.WriteContentTo(pdbFileStream); + pdbFileStream.Close(); + + DebugDirectoryBuilder debugDirectoryBuilder = new DebugDirectoryBuilder(); + debugDirectoryBuilder.AddCodeViewEntry(pdbFile.Path, pdbContentId, pdbBuilder.FormatVersion); + + ManagedPEBuilder peBuilder = new ManagedPEBuilder( + header: new PEHeaderBuilder(imageCharacteristics: Characteristics.ExecutableImage), + metadataRootBuilder: new MetadataRootBuilder(metadataBuilder), + ilStream: ilStream, + debugDirectoryBuilder: debugDirectoryBuilder, + entryPoint: entryPointHandle); + + BlobBuilder peBlob = new BlobBuilder(); + peBuilder.Serialize(peBlob); + using var assemblyFileStream = new FileStream(file.Path, FileMode.Create, FileAccess.Write); + peBlob.WriteContentTo(assemblyFileStream); + assemblyFileStream.Close(); + + using var fs = new FileStream(pdbFile.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + using MetadataReaderProvider provider = MetadataReaderProvider.FromPortablePdbStream(fs); + ValidatePDB(method1, entryPoint, provider.GetMetadataReader()); + } + } + + private static void ValidatePDB(MethodBuilder method, MethodBuilder entryPoint, MetadataReader reader) + { + DocumentHandleCollection.Enumerator docEnumerator = reader.Documents.GetEnumerator(); + Assert.Equal(1, reader.Documents.Count); + Assert.True(docEnumerator.MoveNext()); + Document doc = reader.GetDocument(docEnumerator.Current); + Assert.Equal("MySourceFile.cs", reader.GetString(doc.Name)); + Assert.Equal(SymLanguageType.CSharp, reader.GetGuid(doc.Language)); + Assert.Equal(default, reader.GetGuid(doc.HashAlgorithm)); + Assert.False(docEnumerator.MoveNext()); + + MethodDebugInformation mdi1 = reader.GetMethodDebugInformation(MetadataTokens.MethodDebugInformationHandle(method.MetadataToken)); + Assert.Equal(doc, reader.GetDocument(mdi1.Document)); + SequencePointCollection.Enumerator spce = mdi1.GetSequencePoints().GetEnumerator(); + Assert.True(spce.MoveNext()); + SequencePoint sp = spce.Current; + Assert.False(sp.IsHidden); + Assert.Equal(7, sp.StartLine); + Assert.Equal(0, sp.StartColumn); + Assert.Equal(7, sp.EndLine); + Assert.Equal(20, sp.EndColumn); + Assert.True(spce.MoveNext()); + sp = spce.Current; + Assert.False(sp.IsHidden); + Assert.Equal(8, sp.StartLine); + Assert.Equal(0, sp.StartColumn); + Assert.Equal(9, sp.EndLine); + Assert.Equal(18, sp.EndColumn); + Assert.False(spce.MoveNext()); + + LocalScopeHandleCollection.Enumerator localScopes = reader.GetLocalScopes(MetadataTokens.MethodDefinitionHandle(method.MetadataToken)).GetEnumerator(); + Assert.True(localScopes.MoveNext()); + LocalScope localScope = reader.GetLocalScope(localScopes.Current); + Assert.Equal(0, localScope.StartOffset); + Assert.Equal(12, localScope.EndOffset); + LocalVariableHandleCollection.Enumerator localEnumerator = localScope.GetLocalVariables().GetEnumerator(); + Assert.True(localEnumerator.MoveNext()); + Assert.Equal("MyInt", reader.GetString(reader.GetLocalVariable(localEnumerator.Current).Name)); + Assert.False(localEnumerator.MoveNext()); + + Assert.True(localScope.ImportScope.IsNil); + + Assert.True(localScopes.MoveNext()); + localScope = reader.GetLocalScope(localScopes.Current); + Assert.Equal(4, localScope.StartOffset); + Assert.Equal(10, localScope.EndOffset); + localEnumerator = localScope.GetLocalVariables().GetEnumerator(); + Assert.True(localEnumerator.MoveNext()); + Assert.Equal("MyInt2", reader.GetString(reader.GetLocalVariable(localEnumerator.Current).Name)); + Assert.False(localEnumerator.MoveNext()); + Assert.False(localScopes.MoveNext()); + + ImportScope importScope = reader.GetImportScope(localScope.ImportScope); + Assert.True(importScope.Parent.IsNil); + ImportDefinitionCollection.Enumerator importEnumerator = importScope.GetImports().GetEnumerator(); + Assert.True(importEnumerator.MoveNext()); + ImportDefinition importDef = importEnumerator.Current; + Assert.Equal(ImportDefinitionKind.ImportNamespace, importDef.Kind); + BlobReader blobReader = reader.GetBlobReader(importDef.TargetNamespace); + Assert.Equal("System.Reflection", blobReader.ReadUTF8(blobReader.Length)); + + mdi1 = reader.GetMethodDebugInformation(MetadataTokens.MethodDebugInformationHandle(entryPoint.MetadataToken)); + Assert.Equal(doc, reader.GetDocument(mdi1.Document)); + spce = mdi1.GetSequencePoints().GetEnumerator(); + Assert.True(spce.MoveNext()); + sp = spce.Current; + Assert.False(sp.IsHidden); + Assert.Equal(12, sp.StartLine); + Assert.Equal(0, sp.StartColumn); + Assert.Equal(12, sp.EndLine); + Assert.Equal(37, sp.EndColumn); + Assert.False(spce.MoveNext()); + + localScopes = reader.GetLocalScopes(MetadataTokens.MethodDefinitionHandle(entryPoint.MetadataToken)).GetEnumerator(); + Assert.True(localScopes.MoveNext()); + localScope = reader.GetLocalScope(localScopes.Current); + Assert.Equal(0, localScope.StartOffset); + Assert.Equal(21, localScope.EndOffset); + localEnumerator = localScope.GetLocalVariables().GetEnumerator(); + Assert.True(localEnumerator.MoveNext()); + Assert.Equal("MyLoc1", reader.GetString(reader.GetLocalVariable(localEnumerator.Current).Name)); + Assert.True(localEnumerator.MoveNext()); + Assert.Equal("MyLoc2", reader.GetString(reader.GetLocalVariable(localEnumerator.Current).Name)); + Assert.False(localEnumerator.MoveNext()); + Assert.False(localScopes.MoveNext()); + } + + private static MetadataBuilder GenerateAssemblyAndMetadata(out MethodBuilder method, + out MethodBuilder entryPoint, out BlobBuilder ilStream, out MetadataBuilder pdbMetadata) + { + PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(new AssemblyName("MyAssembly2"), typeof(object).Assembly); + ModuleBuilder mb = ab.DefineDynamicModule("MyModule2"); + TypeBuilder tb = mb.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class); + ISymbolDocumentWriter srcdoc = mb.DefineDocument("MySourceFile.cs", SymLanguageType.CSharp); + method = tb.DefineMethod("SumMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(int), [typeof(int), typeof(int)]); + ILGenerator il1 = method.GetILGenerator(); + LocalBuilder local = il1.DeclareLocal(typeof(int)); + local.SetLocalSymInfo("MyInt"); + il1.MarkSequencePoint(srcdoc, 7, 0, 7, 20); + il1.Emit(OpCodes.Ldarg_0); + il1.Emit(OpCodes.Ldarg_1); + il1.Emit(OpCodes.Add); + il1.Emit(OpCodes.Stloc_0); + il1.MarkSequencePoint(srcdoc, 8, 0, 9, 18); + il1.BeginScope(); + il1.UsingNamespace("System.Reflection"); + LocalBuilder local2 = il1.DeclareLocal(typeof(int)); + local2.SetLocalSymInfo("MyInt2"); + il1.Emit(OpCodes.Ldc_I4_2); + il1.Emit(OpCodes.Stloc_1); + il1.Emit(OpCodes.Ldloc_0); + il1.Emit(OpCodes.Ldloc_1); + il1.Emit(OpCodes.Add); + il1.Emit(OpCodes.Stloc_0); + il1.EndScope(); + il1.Emit(OpCodes.Ldloc_0); + il1.Emit(OpCodes.Ret); + + entryPoint = tb.DefineMethod("Mm", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static); + ILGenerator il2 = entryPoint.GetILGenerator(); + local = il2.DeclareLocal(typeof(int)); + local.SetLocalSymInfo("MyLoc1"); + il2.MarkSequencePoint(srcdoc, 12, 0, 12, 37); + local2 = il2.DeclareLocal(typeof(int)); + local2.SetLocalSymInfo("MyLoc2"); + il2.Emit(OpCodes.Ldc_I4_S, 10); + il2.Emit(OpCodes.Stloc_0); + il2.Emit(OpCodes.Ldc_I4_1); + il2.Emit(OpCodes.Stloc_1); + il2.Emit(OpCodes.Ldloc_0); + il2.Emit(OpCodes.Ldloc_1); + il2.Emit(OpCodes.Call, method); + il2.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", [typeof(int)])); + il2.Emit(OpCodes.Ret); + tb.CreateType(); + return ab.GenerateMetadata(out ilStream, out BlobBuilder _, out pdbMetadata); + } + + [Fact] + public void CreateEmbeddedPDBAndVerifyTest() + { + using (TempFile file = TempFile.Create()) + { + MethodBuilder method1, entryPoint; + MetadataBuilder metadataBuilder = GenerateAssemblyAndMetadata(out method1, out entryPoint, out BlobBuilder ilStream, out MetadataBuilder pdbMetadata); + MethodDefinitionHandle entryPointHandle = MetadataTokens.MethodDefinitionHandle(entryPoint.MetadataToken); + + BlobBuilder portablePdbBlob = new BlobBuilder(); + PortablePdbBuilder pdbBuilder = new PortablePdbBuilder(pdbMetadata, metadataBuilder.GetRowCounts(), entryPointHandle); + + BlobContentId pdbContentId = pdbBuilder.Serialize(portablePdbBlob); + DebugDirectoryBuilder debugDirectoryBuilder = new DebugDirectoryBuilder(); + debugDirectoryBuilder.AddEmbeddedPortablePdbEntry(portablePdbBlob, pdbBuilder.FormatVersion); + + ManagedPEBuilder peBuilder = new ManagedPEBuilder( + header: new PEHeaderBuilder(imageCharacteristics: Characteristics.ExecutableImage), + metadataRootBuilder: new MetadataRootBuilder(metadataBuilder), + ilStream: ilStream, + debugDirectoryBuilder: debugDirectoryBuilder, + entryPoint: entryPointHandle); + + BlobBuilder peBlob = new BlobBuilder(); + peBuilder.Serialize(peBlob); + using var fileStream = new FileStream(file.Path, FileMode.Create, FileAccess.Write); + peBlob.WriteContentTo(fileStream); + fileStream.Close(); + + using var fs = new FileStream(file.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + using var peReader = new PEReader(fs); + ImmutableArray entries = peReader.ReadDebugDirectory(); + Assert.Equal(1, entries.Length); + Assert.Equal(DebugDirectoryEntryType.EmbeddedPortablePdb, entries[0].Type); + + using MetadataReaderProvider provider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(entries[0]); + ValidatePDB(method1, entryPoint, provider.GetMetadataReader()); + } + } + } +} diff --git a/src/libraries/System.Reflection.Emit/tests/System.Reflection.Emit.Tests.csproj b/src/libraries/System.Reflection.Emit/tests/System.Reflection.Emit.Tests.csproj index 5317b25145a5..56d7b3869a16 100644 --- a/src/libraries/System.Reflection.Emit/tests/System.Reflection.Emit.Tests.csproj +++ b/src/libraries/System.Reflection.Emit/tests/System.Reflection.Emit.Tests.csproj @@ -73,6 +73,8 @@ + + diff --git a/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs b/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs index d65673856528..6eaf4ea70e61 100644 --- a/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs +++ b/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs @@ -2408,6 +2408,49 @@ public readonly partial struct TypeLayout public int PackingSize { get { throw null; } } public int Size { get { throw null; } } } + public sealed partial class AssemblyNameInfo + { + public AssemblyNameInfo(string name, System.Version? version = null, string? cultureName = null, System.Reflection.AssemblyNameFlags flags = AssemblyNameFlags.None, + Collections.Immutable.ImmutableArray publicKeyOrToken = default) { } + public string Name { get { throw null; } } + public string? CultureName { get { throw null; } } + public string FullName { get { throw null; } } + public System.Version? Version { get { throw null; } } + public System.Reflection.AssemblyNameFlags Flags { get { throw null; } } + public System.Collections.Immutable.ImmutableArray PublicKeyOrToken { get { throw null; } } + public static System.Reflection.Metadata.AssemblyNameInfo Parse(System.ReadOnlySpan assemblyName) { throw null; } + public static bool TryParse(System.ReadOnlySpan assemblyName, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Reflection.Metadata.AssemblyNameInfo? result) { throw null; } + public System.Reflection.AssemblyName ToAssemblyName() { throw null; } + } + public sealed partial class TypeName + { + internal TypeName() { } + public string AssemblyQualifiedName { get { throw null; } } + public AssemblyNameInfo? AssemblyName { get { throw null; } } + public System.Reflection.Metadata.TypeName? DeclaringType { get { throw null; } } + public string FullName { get { throw null; } } + public bool IsArray { get { throw null; } } + public bool IsByRef { get { throw null; } } + public bool IsConstructedGenericType { get { throw null; } } + public bool IsNested { get { throw null; } } + public bool IsPointer { get { throw null; } } + public bool IsSimple { get { throw null; } } + public bool IsSZArray { get { throw null; } } + public bool IsVariableBoundArrayType { get { throw null; } } + public string Name { get { throw null; } } + public static System.Reflection.Metadata.TypeName Parse(System.ReadOnlySpan typeName, System.Reflection.Metadata.TypeNameParseOptions? options = null) { throw null; } + public static bool TryParse(System.ReadOnlySpan typeName, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Reflection.Metadata.TypeName? result, System.Reflection.Metadata.TypeNameParseOptions? options = null) { throw null; } + public int GetArrayRank() { throw null; } + public System.Collections.Immutable.ImmutableArray GetGenericArguments() { throw null; } + public System.Reflection.Metadata.TypeName GetGenericTypeDefinition() { throw null; } + public System.Reflection.Metadata.TypeName GetElementType() { throw null; } + public int GetNodeCount() { throw null; } + } + public sealed partial class TypeNameParseOptions + { + public TypeNameParseOptions() { } + public int MaxNodes { get { throw null; } set { } } + } public readonly partial struct TypeReference { private readonly object _dummy; diff --git a/src/libraries/System.Reflection.Metadata/src/Resources/Strings.resx b/src/libraries/System.Reflection.Metadata/src/Resources/Strings.resx index c035a3efee09..963e4d0af9f8 100644 --- a/src/libraries/System.Reflection.Metadata/src/Resources/Strings.resx +++ b/src/libraries/System.Reflection.Metadata/src/Resources/Strings.resx @@ -411,4 +411,25 @@ The SwitchInstructionEncoder.Branch method was invoked too many times. + + The name of the type is invalid. + + + Maximum node count of {0} exceeded. + + + Must be an array type. + + + This operation is only valid on generic types. + + + This operation is only valid on nested types. + + + This operation is only valid on arrays, pointers and references. + + + The given assembly name was invalid. + \ No newline at end of file diff --git a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj index e713d6210651..6c74a3229021 100644 --- a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj +++ b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj @@ -16,6 +16,7 @@ The System.Reflection.Metadata library is built-in as part of the shared framewo $(DefineConstants);FEATURE_CER + $(DefineConstants);SYSTEM_REFLECTION_METADATA @@ -121,6 +122,11 @@ The System.Reflection.Metadata library is built-in as part of the shared framewo + + + + + @@ -250,7 +256,12 @@ The System.Reflection.Metadata library is built-in as part of the shared framewo + + + + + diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BitArithmetic.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BitArithmetic.cs index 7ad3c4aba6e6..43e7f2aad0f6 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BitArithmetic.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BitArithmetic.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -#if NETCOREAPP +#if NET using System.Numerics; #endif @@ -17,7 +17,7 @@ internal static int CountBits(int v) internal static int CountBits(uint v) { -#if NETCOREAPP +#if NET return BitOperations.PopCount(v); #else unchecked @@ -31,7 +31,7 @@ internal static int CountBits(uint v) internal static int CountBits(ulong v) { -#if NETCOREAPP +#if NET return BitOperations.PopCount(v); #else const ulong Mask01010101 = 0x5555555555555555UL; diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs index 843e95e616d3..462d2408b1d3 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs @@ -20,7 +20,7 @@ public static void WriteBytes(this byte[] buffer, int start, byte value, int byt public static void WriteDouble(this byte[] buffer, int start, double value) { -#if NETCOREAPP +#if NET WriteUInt64(buffer, start, BitConverter.DoubleToUInt64Bits(value)); #else WriteUInt64(buffer, start, *(ulong*)&value); @@ -29,7 +29,7 @@ public static void WriteDouble(this byte[] buffer, int start, double value) public static void WriteSingle(this byte[] buffer, int start, float value) { -#if NETCOREAPP +#if NET WriteUInt32(buffer, start, BitConverter.SingleToUInt32Bits(value)); #else WriteUInt32(buffer, start, *(uint*)&value); @@ -76,7 +76,7 @@ public static void WriteDecimal(this byte[] buffer, int start, decimal value) public static void WriteGuid(this byte[] buffer, int start, Guid value) { -#if NETCOREAPP +#if NET bool written = value.TryWriteBytes(buffer.AsSpan(start)); // This function is not public, callers have to ensure that enough space is available. Debug.Assert(written); diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/DecimalUtilities.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/DecimalUtilities.cs index 3733a4b45a5a..be69480203e9 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/DecimalUtilities.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/DecimalUtilities.cs @@ -7,7 +7,7 @@ internal static class DecimalUtilities { public static int GetScale(this decimal value) { -#if NETCOREAPP +#if NET Span bits = stackalloc int[4]; decimal.GetBits(value, bits); return unchecked((byte)(bits[3] >> 16)); @@ -18,7 +18,7 @@ public static int GetScale(this decimal value) public static void GetBits(this decimal value, out bool isNegative, out byte scale, out uint low, out uint mid, out uint high) { -#if NETCOREAPP +#if NET Span bits = stackalloc int[4]; decimal.GetBits(value, bits); #else diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableMemoryStream.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableMemoryStream.cs index 26dc9290ab4e..fe94886ac859 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableMemoryStream.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableMemoryStream.cs @@ -72,7 +72,7 @@ public override int Read(byte[] buffer, int offset, int count) return result; } -#if NETCOREAPP +#if NET // Duplicate the Read(byte[]) logic here instead of refactoring both to use Spans // so we don't affect perf on .NET Framework. public override int Read(Span buffer) diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ReadOnlyUnmanagedMemoryStream.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ReadOnlyUnmanagedMemoryStream.cs index 2a31a96a1540..b3fe0044c43c 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ReadOnlyUnmanagedMemoryStream.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ReadOnlyUnmanagedMemoryStream.cs @@ -36,7 +36,7 @@ public override int Read(byte[] buffer, int offset, int count) return bytesRead; } -#if NETCOREAPP +#if NET // Duplicate the Read(byte[]) logic here instead of refactoring both to use Spans // so we don't affect perf on .NET Framework. public override int Read(Span buffer) diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs index bb52925254c2..484f138762fe 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs @@ -76,9 +76,9 @@ internal static int TryReadAll(this Stream stream, byte[] buffer, int offset, in return totalBytesRead; } -#if NETCOREAPP +#if NET internal static int TryReadAll(this Stream stream, Span buffer) -#if NET7_0_OR_GREATER +#if NET => stream.ReadAtLeast(buffer, buffer.Length, throwOnEndOfStream: false); #else { diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/AssemblyNameInfo.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/AssemblyNameInfo.cs new file mode 100644 index 000000000000..14c796ac5217 --- /dev/null +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/AssemblyNameInfo.cs @@ -0,0 +1,211 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Text; + +#if !SYSTEM_PRIVATE_CORELIB +using System.Collections.Immutable; +using System.Linq; +#endif + +namespace System.Reflection.Metadata +{ + /// + /// Describes an assembly. + /// + /// + /// It's a more lightweight, immutable version of that does not pre-allocate instances. + /// + [DebuggerDisplay("{FullName}")] +#if SYSTEM_REFLECTION_METADATA + public +#else + internal +#endif + sealed class AssemblyNameInfo + { + internal readonly AssemblyNameFlags _flags; + private string? _fullName; + +#if !SYSTEM_PRIVATE_CORELIB + /// + /// Initializes a new instance of the AssemblyNameInfo class. + /// + /// The simple name of the assembly. + /// The version of the assembly. + /// The name of the culture associated with the assembly. + /// The attributes of the assembly. + /// The public key or its token. Set to when it's public key. + /// is null. + public AssemblyNameInfo(string name, Version? version = null, string? cultureName = null, AssemblyNameFlags flags = AssemblyNameFlags.None, ImmutableArray publicKeyOrToken = default) + { + Name = name ?? throw new ArgumentNullException(nameof(name)); + Version = version; + CultureName = cultureName; + _flags = flags; + PublicKeyOrToken = publicKeyOrToken; + } +#endif + + internal AssemblyNameInfo(AssemblyNameParser.AssemblyNameParts parts) + { + Name = parts._name; + Version = parts._version; + CultureName = parts._cultureName; + _flags = parts._flags; +#if SYSTEM_PRIVATE_CORELIB + PublicKeyOrToken = parts._publicKeyOrToken; +#else + PublicKeyOrToken = parts._publicKeyOrToken is null ? default : parts._publicKeyOrToken.Length == 0 + ? ImmutableArray.Empty + #if NET8_0_OR_GREATER + : Runtime.InteropServices.ImmutableCollectionsMarshal.AsImmutableArray(parts._publicKeyOrToken); + #else + : ImmutableArray.Create(parts._publicKeyOrToken); + #endif +#endif + } + + /// + /// Gets the simple name of the assembly. + /// + public string Name { get; } + + /// + /// Gets the version of the assembly. + /// + public Version? Version { get; } + + /// + /// Gets the name of the culture associated with the assembly. + /// + public string? CultureName { get; } + + /// + /// Gets the attributes of the assembly. + /// + public AssemblyNameFlags Flags => _flags; + + /// + /// Gets the public key or the public key token of the assembly. + /// + /// Check for flag to see whether it's public key or its token. +#if SYSTEM_PRIVATE_CORELIB + public byte[]? PublicKeyOrToken { get; } +#else + public ImmutableArray PublicKeyOrToken { get; } +#endif + + /// + /// Gets the full name of the assembly, also known as the display name. + /// + /// In contrary to it does not validate public key token neither computes it based on the provided public key. + public string FullName + { + get + { + if (_fullName is null) + { + byte[]? publicKeyToken = ((Flags & AssemblyNameFlags.PublicKey) != 0) ? null : +#if SYSTEM_PRIVATE_CORELIB + PublicKeyOrToken; +#elif NET8_0_OR_GREATER + !PublicKeyOrToken.IsDefault ? Runtime.InteropServices.ImmutableCollectionsMarshal.AsArray(PublicKeyOrToken) : null; +#else + !PublicKeyOrToken.IsDefault ? PublicKeyOrToken.ToArray() : null; +#endif + _fullName = AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, publicKeyToken, + ExtractAssemblyNameFlags(_flags), ExtractAssemblyContentType(_flags)); + } + + return _fullName; + } + } + + /// + /// Initializes a new instance of the class based on the stored information. + /// + public AssemblyName ToAssemblyName() + { + AssemblyName assemblyName = new(); + assemblyName.Name = Name; + assemblyName.CultureName = CultureName; + assemblyName.Version = Version; + assemblyName.Flags = Flags; + assemblyName.ContentType = ExtractAssemblyContentType(_flags); +#pragma warning disable SYSLIB0037 // Type or member is obsolete + assemblyName.ProcessorArchitecture = ExtractProcessorArchitecture(_flags); +#pragma warning restore SYSLIB0037 // Type or member is obsolete + +#if SYSTEM_PRIVATE_CORELIB + if (PublicKeyOrToken is not null) + { + if ((Flags & AssemblyNameFlags.PublicKey) != 0) + { + assemblyName.SetPublicKey(PublicKeyOrToken); + } + else + { + assemblyName.SetPublicKeyToken(PublicKeyOrToken); + } + } +#else + if (!PublicKeyOrToken.IsDefault) + { + // A copy of the array needs to be created, as AssemblyName allows for the mutation of provided array. + if ((Flags & AssemblyNameFlags.PublicKey) != 0) + { + assemblyName.SetPublicKey(PublicKeyOrToken.ToArray()); + } + else + { + assemblyName.SetPublicKeyToken(PublicKeyOrToken.ToArray()); + } + } +#endif + + return assemblyName; + } + + /// + /// Parses a span of characters into a assembly name. + /// + /// A span containing the characters representing the assembly name to parse. + /// Parsed type name. + /// Provided assembly name was invalid. + public static AssemblyNameInfo Parse(ReadOnlySpan assemblyName) + => TryParse(assemblyName, out AssemblyNameInfo? result) + ? result! + : throw new ArgumentException(SR.InvalidAssemblyName, nameof(assemblyName)); + + /// + /// Tries to parse a span of characters into an assembly name. + /// + /// A span containing the characters representing the assembly name to parse. + /// Contains the result when parsing succeeds. + /// true if assembly name was converted successfully, otherwise, false. + public static bool TryParse(ReadOnlySpan assemblyName, [NotNullWhen(true)] out AssemblyNameInfo? result) + { + AssemblyNameParser.AssemblyNameParts parts = default; + if (AssemblyNameParser.TryParse(assemblyName, ref parts)) + { + result = new(parts); + return true; + } + + result = null; + return false; + } + + internal static AssemblyNameFlags ExtractAssemblyNameFlags(AssemblyNameFlags combinedFlags) + => combinedFlags & unchecked((AssemblyNameFlags)0xFFFFF10F); + + internal static AssemblyContentType ExtractAssemblyContentType(AssemblyNameFlags flags) + => (AssemblyContentType)((((int)flags) >> 9) & 0x7); + + internal static ProcessorArchitecture ExtractProcessorArchitecture(AssemblyNameFlags flags) + => (ProcessorArchitecture)((((int)flags) >> 4) & 0x7); + } +} diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.Heaps.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.Heaps.cs index 21e47c8b22c1..fe8b6af07ee1 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.Heaps.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.Heaps.cs @@ -579,7 +579,7 @@ private static ImmutableArray SerializeStringHeap( /// private sealed class SuffixSort : IComparer> { - internal static SuffixSort Instance = new SuffixSort(); + internal static readonly SuffixSort Instance = new SuffixSort(); public int Compare(KeyValuePair xPair, KeyValuePair yPair) { diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeName.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeName.cs new file mode 100644 index 000000000000..3f1ea8394393 --- /dev/null +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeName.cs @@ -0,0 +1,396 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Text; + +#if !SYSTEM_PRIVATE_CORELIB +using System.Collections.Immutable; +#endif + +namespace System.Reflection.Metadata +{ + [DebuggerDisplay("{AssemblyQualifiedName}")] +#if SYSTEM_REFLECTION_METADATA + public +#else + internal +#endif + sealed class TypeName + { + /// + /// Positive value is array rank. + /// Negative value is modifier encoded using constants defined in . + /// + private readonly sbyte _rankOrModifier; + /// + /// To avoid the need of allocating a string for all declaring types (example: A+B+C+D+E+F+G), + /// length of the name is stored and the fullName passed in ctor represents the full name of the nested type. + /// So when the name is needed, a substring is being performed. + /// + private readonly int _nestedNameLength; + private readonly TypeName? _elementOrGenericType; + private readonly TypeName? _declaringType; +#if SYSTEM_PRIVATE_CORELIB + private readonly List? _genericArguments; +#else + private readonly ImmutableArray _genericArguments; +#endif + private string? _name, _fullName, _assemblyQualifiedName; + + internal TypeName(string? fullName, + AssemblyNameInfo? assemblyName, + TypeName? elementOrGenericType = default, + TypeName? declaringType = default, +#if SYSTEM_PRIVATE_CORELIB + List? genericTypeArguments = default, +#else + ImmutableArray.Builder? genericTypeArguments = default, +#endif + sbyte rankOrModifier = default, + int nestedNameLength = -1) + { + _fullName = fullName; + AssemblyName = assemblyName; + _rankOrModifier = rankOrModifier; + _elementOrGenericType = elementOrGenericType; + _declaringType = declaringType; + _nestedNameLength = nestedNameLength; + +#if SYSTEM_PRIVATE_CORELIB + _genericArguments = genericTypeArguments; +#else + _genericArguments = genericTypeArguments is null + ? ImmutableArray.Empty + : genericTypeArguments.Count == genericTypeArguments.Capacity ? genericTypeArguments.MoveToImmutable() : genericTypeArguments.ToImmutableArray(); +#endif + } + + /// + /// The assembly-qualified name of the type; e.g., "System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089". + /// + /// + /// If returns null, simply returns . + /// + public string AssemblyQualifiedName + => _assemblyQualifiedName ??= AssemblyName is null ? FullName : $"{FullName}, {AssemblyName.FullName}"; + + /// + /// Returns assembly name which contains this type, or null if this was not + /// created from a fully-qualified name. + /// + public AssemblyNameInfo? AssemblyName { get; } + + /// + /// If this type is a nested type (see ), gets + /// the declaring type. If this type is not a nested type, throws. + /// + /// + /// For example, given "Namespace.Declaring+Nested", unwraps the outermost type and returns "Namespace.Declaring". + /// + /// The current type is not a nested type. + public TypeName DeclaringType + { + get + { + if (_declaringType is null) + { + TypeNameParserHelpers.ThrowInvalidOperation_NotNestedType(); + } + + return _declaringType; + } + } + + /// + /// The full name of this type, including namespace, but without the assembly name; e.g., "System.Int32". + /// Nested types are represented with a '+'; e.g., "MyNamespace.MyType+NestedType". + /// + /// + /// For constructed generic types, the type arguments will be listed using their fully qualified + /// names. For example, given "List<int>", the property will return + /// "System.Collections.Generic.List`1[[System.Int32, mscorlib, ...]]". + /// For open generic types, the convention is to use a backtick ("`") followed by + /// the arity of the generic type. For example, given "Dictionary<,>", the + /// property will return "System.Collections.Generic.Dictionary`2". Given "Dictionary<,>.Enumerator", + /// the property will return "System.Collections.Generic.Dictionary`2+Enumerator". + /// See ECMA-335, Sec. I.10.7.2 (Type names and arity encoding) for more information. + /// + public string FullName + { + get + { + if (_fullName is null) + { + if (IsConstructedGenericType) + { + _fullName = TypeNameParserHelpers.GetGenericTypeFullName(GetGenericTypeDefinition().FullName.AsSpan(), +#if SYSTEM_PRIVATE_CORELIB + CollectionsMarshal.AsSpan(_genericArguments)); +#else + _genericArguments.AsSpan()); +#endif + } + else if (IsArray || IsPointer || IsByRef) + { + ValueStringBuilder builder = new(stackalloc char[128]); + builder.Append(GetElementType().FullName); + _fullName = TypeNameParserHelpers.GetRankOrModifierStringRepresentation(_rankOrModifier, ref builder); + } + else + { + Debug.Fail("Pre-allocated full name should have been provided in the ctor"); + } + } + else if (_nestedNameLength > 0 && _fullName.Length > _nestedNameLength) // Declaring types + { + // Stored fullName represents the full name of the nested type. + // Example: Namespace.Declaring+Nested + _fullName = _fullName.Substring(0, _nestedNameLength); + } + + return _fullName!; + } + } + + /// + /// Returns true if this type represents any kind of array, regardless of the array's + /// rank or its bounds. + /// + public bool IsArray => _rankOrModifier == TypeNameParserHelpers.SZArray || _rankOrModifier > 0; + + /// + /// Returns true if this type represents a constructed generic type (e.g., "List<int>"). + /// + /// + /// Returns false for open generic types (e.g., "Dictionary<,>"). + /// + public bool IsConstructedGenericType => +#if SYSTEM_PRIVATE_CORELIB + _genericArguments is not null; +#else + _genericArguments.Length > 0; +#endif + + /// + /// Returns true if this is a "plain" type; that is, not an array, not a pointer, not a reference, and + /// not a constructed generic type. Examples of elemental types are "System.Int32", + /// "System.Uri", and "YourNamespace.YourClass". + /// + /// + /// This property returning true doesn't mean that the type is a primitive like string + /// or int; it just means that there's no underlying type. + /// This property will return true for generic type definitions (e.g., "Dictionary<,>"). + /// This is because determining whether a type truly is a generic type requires loading the type + /// and performing a runtime check. + /// + public bool IsSimple => _elementOrGenericType is null; + + /// + /// Returns true if this is a managed pointer type (e.g., "ref int"). + /// Managed pointer types are sometimes called byref types () + /// + public bool IsByRef => _rankOrModifier == TypeNameParserHelpers.ByRef; + + /// + /// Returns true if this is a nested type (e.g., "Namespace.Declaring+Nested"). + /// For nested types returns their declaring type. + /// + public bool IsNested => _declaringType is not null; + + /// + /// Returns true if this type represents a single-dimensional, zero-indexed array (e.g., "int[]"). + /// + public bool IsSZArray => _rankOrModifier == TypeNameParserHelpers.SZArray; + + /// + /// Returns true if this type represents an unmanaged pointer (e.g., "int*" or "void*"). + /// Unmanaged pointer types are often just called pointers () + /// + public bool IsPointer => _rankOrModifier == TypeNameParserHelpers.Pointer; + + /// + /// Returns true if this type represents a variable-bound array; that is, an array of rank greater + /// than 1 (e.g., "int[,]") or a single-dimensional array which isn't necessarily zero-indexed. + /// + public bool IsVariableBoundArrayType => _rankOrModifier >= 1; + + /// + /// The name of this type, without the namespace and the assembly name; e.g., "Int32". + /// Nested types are represented without a '+'; e.g., "MyNamespace.MyType+NestedType" is just "NestedType". + /// + public string Name + { + get + { + if (_name is null) + { + if (IsConstructedGenericType) + { + _name = TypeNameParserHelpers.GetName(GetGenericTypeDefinition().FullName.AsSpan()).ToString(); + } + else if (IsPointer || IsByRef || IsArray) + { + ValueStringBuilder builder = new(stackalloc char[64]); + builder.Append(GetElementType().Name); + _name = TypeNameParserHelpers.GetRankOrModifierStringRepresentation(_rankOrModifier, ref builder); + } + else if (_nestedNameLength > 0 && _fullName is not null) + { + _name = TypeNameParserHelpers.GetName(_fullName.AsSpan(0, _nestedNameLength)).ToString(); + } + else + { + _name = TypeNameParserHelpers.GetName(FullName.AsSpan()).ToString(); + } + } + + return _name; + } + } + + /// + /// Represents the total number of instances that are used to describe + /// this instance, including any generic arguments or underlying types. + /// + /// + /// This value is computed every time this method gets called, it's not cached. + /// There's not really a parallel concept to this in reflection. Think of it + /// as the total number of instances that would be created if + /// you were to totally deconstruct this instance and visit each intermediate + /// that occurs as part of deconstruction. + /// "int" and "Person" each have complexities of 1 because they're standalone types. + /// "int[]" has a node count of 2 because to fully inspect it involves inspecting the + /// array type itself, plus unwrapping the underlying type ("int") and inspecting that. + /// + /// "Dictionary<string, List<int[][]>>" has node count 8 because fully visiting it + /// involves inspecting 8 instances total: + /// + /// Dictionary<string, List<int[][]>> (the original type) + /// Dictionary`2 (the generic type definition) + /// string (a type argument of Dictionary) + /// List<int[][]> (a type argument of Dictionary) + /// List`1 (the generic type definition) + /// int[][] (a type argument of List) + /// int[] (the underlying type of int[][]) + /// int (the underlying type of int[]) + /// + /// + /// + public int GetNodeCount() + { + int result = 1; + + if (IsNested) + { + result += DeclaringType.GetNodeCount(); + } + else if (IsConstructedGenericType) + { + result++; + } + else if (IsArray || IsPointer || IsByRef) + { + result += GetElementType().GetNodeCount(); + } + + foreach (TypeName genericArgument in GetGenericArguments()) + { + result += genericArgument.GetNodeCount(); + } + + return result; + } + + /// + /// The TypeName of the object encompassed or referred to by the current array, pointer, or reference type. + /// + /// + /// For example, given "int[][]", unwraps the outermost array and returns "int[]". + /// + /// The current type is not an array, pointer or reference. + public TypeName GetElementType() + { + if (!(IsArray || IsPointer || IsByRef)) + { + TypeNameParserHelpers.ThrowInvalidOperation_NoElement(); + } + + return _elementOrGenericType!; + } + + /// + /// Returns a TypeName object that represents a generic type name definition from which the current generic type name can be constructed. + /// + /// + /// Given "Dictionary<string, int>", returns the generic type definition "Dictionary<,>". + /// + /// The current type is not a generic type. + public TypeName GetGenericTypeDefinition() + { + if (!IsConstructedGenericType) + { + TypeNameParserHelpers.ThrowInvalidOperation_NotGenericType(); + } + + return _elementOrGenericType!; + } + + /// + /// Parses a span of characters into a type name. + /// + /// A span containing the characters representing the type name to parse. + /// An object that describes optional parameters to use. + /// Parsed type name. + /// Provided type name was invalid. + /// Parsing has exceeded the limit set by . + public static TypeName Parse(ReadOnlySpan typeName, TypeNameParseOptions? options = default) + => TypeNameParser.Parse(typeName, throwOnError: true, options)!; + + /// + /// Tries to parse a span of characters into a type name. + /// + /// A span containing the characters representing the type name to parse. + /// An object that describes optional parameters to use. + /// Contains the result when parsing succeeds. + /// true if type name was converted successfully, otherwise, false. + public static bool TryParse(ReadOnlySpan typeName, [NotNullWhen(true)] out TypeName? result, TypeNameParseOptions? options = default) + { + result = TypeNameParser.Parse(typeName, throwOnError: false, options); + return result is not null; + } + + /// + /// Gets the number of dimensions in an array. + /// + /// An integer that contains the number of dimensions in the current type. + /// The current type is not an array. + public int GetArrayRank() + { + if (!(_rankOrModifier == TypeNameParserHelpers.SZArray || _rankOrModifier > 0)) + { + TypeNameParserHelpers.ThrowInvalidOperation_HasToBeArrayClass(); + } + + return _rankOrModifier == TypeNameParserHelpers.SZArray ? 1 : _rankOrModifier; + } + + /// + /// If this represents a constructed generic type, returns an array + /// of all the generic arguments. Otherwise it returns an empty array. + /// + /// + /// For example, given "Dictionary<string, int>", returns a 2-element array containing + /// string and int. + /// + public +#if SYSTEM_PRIVATE_CORELIB + ReadOnlySpan GetGenericArguments() => CollectionsMarshal.AsSpan(_genericArguments); +#else + ImmutableArray GetGenericArguments() => _genericArguments; +#endif + } +} diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeNameParser.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeNameParser.cs new file mode 100644 index 000000000000..5a5bbe04a0c1 --- /dev/null +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeNameParser.cs @@ -0,0 +1,259 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics; + +#if !SYSTEM_PRIVATE_CORELIB +using System.Collections.Immutable; +#endif + +using static System.Reflection.Metadata.TypeNameParserHelpers; + +namespace System.Reflection.Metadata +{ + [DebuggerDisplay("{_inputString}")] + internal ref struct TypeNameParser + { + private static readonly TypeNameParseOptions s_defaults = new(); + + private readonly bool _throwOnError; + private readonly TypeNameParseOptions _parseOptions; + private ReadOnlySpan _inputString; + + private TypeNameParser(ReadOnlySpan name, bool throwOnError, TypeNameParseOptions? options) : this() + { + _inputString = name; + _throwOnError = throwOnError; + _parseOptions = options ?? s_defaults; + } + + internal static TypeName? Parse(ReadOnlySpan typeName, bool throwOnError, TypeNameParseOptions? options = default) + { + ReadOnlySpan trimmedName = typeName.TrimStart(); // whitespaces at beginning are always OK + if (trimmedName.IsEmpty) + { + if (throwOnError) + { + ThrowArgumentException_InvalidTypeName(errorIndex: 0); // whitespace input needs to report the error index as 0 + } + + return null; + } + + int recursiveDepth = 0; + TypeNameParser parser = new(trimmedName, throwOnError, options); + TypeName? parsedName = parser.ParseNextTypeName(allowFullyQualifiedName: true, ref recursiveDepth); + + if (parsedName is null || !parser._inputString.IsEmpty) // unconsumed input == error + { + if (throwOnError) + { + if (parser._parseOptions.IsMaxDepthExceeded(recursiveDepth)) + { + ThrowInvalidOperation_MaxNodesExceeded(parser._parseOptions.MaxNodes); + } + + int errorIndex = typeName.Length - parser._inputString.Length; + ThrowArgumentException_InvalidTypeName(errorIndex); + } + + return null; + } + + return parsedName; + } + + // this method should return null instead of throwing, so the caller can get errorIndex and include it in error msg + private TypeName? ParseNextTypeName(bool allowFullyQualifiedName, ref int recursiveDepth) + { + if (!TryDive(ref recursiveDepth)) + { + return null; + } + + List? nestedNameLengths = null; + if (!TryGetTypeNameInfo(ref _inputString, ref nestedNameLengths, out int fullTypeNameLength)) + { + return null; + } + + ReadOnlySpan fullTypeName = _inputString.Slice(0, fullTypeNameLength); + _inputString = _inputString.Slice(fullTypeNameLength); + + // Don't allocate now, as it may be an open generic type like "Name`1" +#if SYSTEM_PRIVATE_CORELIB + List? genericArgs = null; +#else + ImmutableArray.Builder? genericArgs = null; +#endif + + // Are there any captured generic args? We'll look for "[[" and "[". + // There are no spaces allowed before the first '[', but spaces are allowed + // after that. The check slices _inputString, so we'll capture it into + // a local so we can restore it later if needed. + ReadOnlySpan capturedBeforeProcessing = _inputString; + if (IsBeginningOfGenericArgs(ref _inputString, out bool doubleBrackets)) + { + ParseAnotherGenericArg: + + // Namespace.Type`2[[GenericArgument1, AssemblyName1],[GenericArgument2, AssemblyName2]] - double square bracket syntax allows for fully qualified type names + // Namespace.Type`2[GenericArgument1,GenericArgument2] - single square bracket syntax is legal only for non-fully qualified type names + // Namespace.Type`2[[GenericArgument1, AssemblyName1], GenericArgument2] - mixed mode + // Namespace.Type`2[GenericArgument1, [GenericArgument2, AssemblyName2]] - mixed mode + TypeName? genericArg = ParseNextTypeName(allowFullyQualifiedName: doubleBrackets, ref recursiveDepth); + if (genericArg is null) // parsing failed + { + return null; + } + + // For [[, there had better be a ']' after the type name. + if (doubleBrackets && !TryStripFirstCharAndTrailingSpaces(ref _inputString, ']')) + { + return null; + } + + if (genericArgs is null) + { +#if SYSTEM_PRIVATE_CORELIB + genericArgs = new List(2); +#else + genericArgs = ImmutableArray.CreateBuilder(2); +#endif + } + genericArgs.Add(genericArg); + + // Is there a ',[' indicating fully qualified generic type arg? + // Is there a ',' indicating non-fully qualified generic type arg? + if (TryStripFirstCharAndTrailingSpaces(ref _inputString, ',')) + { + doubleBrackets = TryStripFirstCharAndTrailingSpaces(ref _inputString, '['); + + goto ParseAnotherGenericArg; + } + + // The only other allowable character is ']', indicating the end of + // the generic type arg list. + if (!TryStripFirstCharAndTrailingSpaces(ref _inputString, ']')) + { + return null; + } + } + + // If there was an error stripping the generic args, back up to + // before we started processing them, and let the decorator + // parser try handling it. + if (genericArgs is null) + { + _inputString = capturedBeforeProcessing; + } + + int previousDecorator = default; + // capture the current state so we can reprocess it again once we know the AssemblyName + capturedBeforeProcessing = _inputString; + // iterate over the decorators to ensure there are no illegal combinations + while (TryParseNextDecorator(ref _inputString, out int parsedDecorator)) + { + if (!TryDive(ref recursiveDepth)) + { + return null; + } + + // Currently it's illegal for managed reference to be followed by any other decorator, + // but this is a runtime-specific behavior and the parser is not enforcing that rule. + previousDecorator = parsedDecorator; + } + + AssemblyNameInfo? assemblyName = null; + if (allowFullyQualifiedName && !TryParseAssemblyName(ref assemblyName)) + { +#if SYSTEM_PRIVATE_CORELIB + // backward compat: throw FileLoadException for non-empty invalid strings + if (_throwOnError || !_inputString.TrimStart().StartsWith(",")) + { + throw new IO.FileLoadException(SR.InvalidAssemblyName, _inputString.ToString()); + } +#else + return null; +#endif + } + + // No matter what was parsed, the full name string is allocated only once. + // In case of generic, nested, array, pointer and byref types the full name is allocated + // when needed for the first time . + string fullName = fullTypeName.ToString(); + + TypeName? declaringType = GetDeclaringType(fullName, nestedNameLengths, assemblyName); + TypeName result = new(fullName, assemblyName, declaringType: declaringType); + if (genericArgs is not null) + { + result = new(fullName: null, assemblyName, elementOrGenericType: result, declaringType, genericArgs); + } + + if (previousDecorator != default) // some decorators were recognized + { + while (TryParseNextDecorator(ref capturedBeforeProcessing, out int parsedModifier)) + { + result = new(fullName: null, assemblyName, elementOrGenericType: result, rankOrModifier: (sbyte)parsedModifier); + } + } + + return result; + } + + /// false means the input was invalid and parsing has failed. Empty input is valid and returns true. + private bool TryParseAssemblyName(ref AssemblyNameInfo? assemblyName) + { + ReadOnlySpan capturedBeforeProcessing = _inputString; + if (TryStripFirstCharAndTrailingSpaces(ref _inputString, ',')) + { + if (_inputString.IsEmpty) + { + _inputString = capturedBeforeProcessing; // restore the state + return false; + } + + ReadOnlySpan candidate = GetAssemblyNameCandidate(_inputString); + if (!AssemblyNameInfo.TryParse(candidate, out assemblyName)) + { + return false; + } + + _inputString = _inputString.Slice(candidate.Length); + return true; + } + + return true; + } + + private static TypeName? GetDeclaringType(string fullTypeName, List? nestedNameLengths, AssemblyNameInfo? assemblyName) + { + if (nestedNameLengths is null) + { + return null; + } + + TypeName? declaringType = null; + int nameOffset = 0; + foreach (int nestedNameLength in nestedNameLengths) + { + Debug.Assert(nestedNameLength > 0, "TryGetTypeNameInfo should return error on zero lengths"); + int fullNameLength = nameOffset + nestedNameLength; + declaringType = new(fullTypeName, assemblyName, declaringType: declaringType, nestedNameLength: fullNameLength); + nameOffset += nestedNameLength + 1; // include the '+' that was skipped in name + } + + return declaringType; + } + + private bool TryDive(ref int depth) + { + if (_parseOptions.IsMaxDepthExceeded(depth)) + { + return false; + } + depth++; + return true; + } + } +} diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeNameParserHelpers.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeNameParserHelpers.cs new file mode 100644 index 000000000000..2fa33ea1dfe3 --- /dev/null +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeNameParserHelpers.cs @@ -0,0 +1,392 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace System.Reflection.Metadata +{ + internal static class TypeNameParserHelpers + { + internal const sbyte SZArray = -1; + internal const sbyte Pointer = -2; + internal const sbyte ByRef = -3; + private const char EscapeCharacter = '\\'; +#if NET8_0_OR_GREATER + private static readonly SearchValues s_endOfFullTypeNameDelimitersSearchValues = SearchValues.Create("[]&*,+\\"); +#endif + + internal static string GetGenericTypeFullName(ReadOnlySpan fullTypeName, ReadOnlySpan genericArgs) + { + Debug.Assert(genericArgs.Length > 0); + + ValueStringBuilder result = new(stackalloc char[128]); + result.Append(fullTypeName); + + result.Append('['); + foreach (TypeName genericArg in genericArgs) + { + result.Append('['); + result.Append(genericArg.AssemblyQualifiedName); + result.Append(']'); + result.Append(','); + } + result[result.Length - 1] = ']'; // replace ',' with ']' + + return result.ToString(); + } + + /// Positive length or negative value for invalid name + internal static int GetFullTypeNameLength(ReadOnlySpan input, out bool isNestedType) + { + isNestedType = false; + + // NET 6+ guarantees that MemoryExtensions.IndexOfAny has worst-case complexity + // O(m * i) if a match is found, or O(m * n) if a match is not found, where: + // i := index of match position + // m := number of needles + // n := length of search space (haystack) + // + // Downlevel versions of .NET do not make this guarantee, instead having a + // worst-case complexity of O(m * n) even if a match occurs at the beginning of + // the search space. Since we're running this in a loop over untrusted user + // input, that makes the total loop complexity potentially O(m * n^2), where + // 'n' is adversary-controlled. To avoid DoS issues here, we'll loop manually. + +#if NET8_0_OR_GREATER + int offset = input.IndexOfAny(s_endOfFullTypeNameDelimitersSearchValues); + if (offset < 0) + { + return input.Length; // no type name end chars were found, the whole input is the type name + } + + if (input[offset] == EscapeCharacter) // this is very rare (IL Emit or pure IL) + { + offset = GetUnescapedOffset(input, startOffset: offset); // this is slower, but very rare so acceptable + } +#else + int offset = GetUnescapedOffset(input, startOffset: 0); +#endif + isNestedType = offset > 0 && offset < input.Length && input[offset] == '+'; + return offset; + + static int GetUnescapedOffset(ReadOnlySpan input, int startOffset) + { + int offset = startOffset; + for (; offset < input.Length; offset++) + { + char c = input[offset]; + if (c == EscapeCharacter) + { + offset++; // skip the escaped char + + if (offset == input.Length || // invalid name that ends with escape character + !NeedsEscaping(input[offset])) // invalid name, escapes a char that does not need escaping + { + return -1; + } + } + else if (NeedsEscaping(c)) + { + break; + } + } + return offset; + } + + static bool NeedsEscaping(char c) => c is '[' or ']' or '&' or '*' or ',' or '+' or EscapeCharacter; + } + + internal static ReadOnlySpan GetName(ReadOnlySpan fullName) + { + int offset = fullName.LastIndexOfAny('.', '+'); + + if (offset > 0 && fullName[offset - 1] == EscapeCharacter) // this should be very rare (IL Emit & pure IL) + { + offset = GetUnescapedOffset(fullName, startIndex: offset); + } + + return offset < 0 ? fullName : fullName.Slice(offset + 1); + + static int GetUnescapedOffset(ReadOnlySpan fullName, int startIndex) + { + int offset = startIndex; + for (; offset >= 0; offset--) + { + if (fullName[offset] is '.' or '+') + { + if (offset == 0 || fullName[offset - 1] != EscapeCharacter) + { + break; + } + offset--; // skip the escaping character + } + } + return offset; + } + } + + // this method handles escaping of the ] just to let the AssemblyNameParser fail for the right input + internal static ReadOnlySpan GetAssemblyNameCandidate(ReadOnlySpan input) + { + // The only delimiter which can terminate an assembly name is ']'. + // Otherwise EOL serves as the terminator. + int offset = input.IndexOf(']'); + + if (offset > 0 && input[offset - 1] == EscapeCharacter) // this should be very rare (IL Emit & pure IL) + { + offset = GetUnescapedOffset(input, startIndex: offset); + } + + return offset < 0 ? input : input.Slice(0, offset); + + static int GetUnescapedOffset(ReadOnlySpan input, int startIndex) + { + int offset = startIndex; + for (; offset < input.Length; offset++) + { + if (input[offset] is ']') + { + if (input[offset - 1] != EscapeCharacter) + { + break; + } + } + } + return offset; + } + } + + internal static string GetRankOrModifierStringRepresentation(int rankOrModifier, ref ValueStringBuilder builder) + { + if (rankOrModifier == ByRef) + { + builder.Append('&'); + } + else if (rankOrModifier == Pointer) + { + builder.Append('*'); + } + else if (rankOrModifier == SZArray) + { + builder.Append("[]"); + } + else if (rankOrModifier == 1) + { + builder.Append("[*]"); + } + else + { + Debug.Assert(rankOrModifier >= 2); + + builder.Append('['); + builder.Append(',', rankOrModifier - 1); + builder.Append(']'); + } + + return builder.ToString(); + } + + /// + /// Are there any captured generic args? We'll look for "[[" and "[" that is not followed by "]", "*" and ",". + /// + internal static bool IsBeginningOfGenericArgs(ref ReadOnlySpan span, out bool doubleBrackets) + { + doubleBrackets = false; + + if (!span.IsEmpty && span[0] == '[') + { + // There are no spaces allowed before the first '[', but spaces are allowed after that. + ReadOnlySpan trimmed = span.Slice(1).TrimStart(); + if (!trimmed.IsEmpty) + { + if (trimmed[0] == '[') + { + doubleBrackets = true; + span = trimmed.Slice(1).TrimStart(); + return true; + } + if (!(trimmed[0] is ',' or '*' or ']')) // [] or [*] or [,] or [,,,, ...] + { + span = trimmed; + return true; + } + } + } + + return false; + } + + internal static bool TryGetTypeNameInfo(ref ReadOnlySpan input, ref List? nestedNameLengths, out int totalLength) + { + bool isNestedType; + totalLength = 0; + do + { + int length = GetFullTypeNameLength(input.Slice(totalLength), out isNestedType); + if (length <= 0) + { + // invalid type names: + // -1: invalid escaping + // 0: pair of unescaped "++" characters + return false; + } + +#if SYSTEM_PRIVATE_CORELIB + // Compat: Ignore leading '.' for type names without namespace. .NET Framework historically ignored leading '.' here. It is likely + // that code out there depends on this behavior. For example, type names formed by concatenating namespace and name, without checking for + // empty namespace (bug), are going to have superfluous leading '.'. + // This behavior means that types that start with '.' are not round-trippable via type name. + if (length > 1 && input[0] == '.' && input.Slice(0, length).LastIndexOf('.') == 0) + { + input = input.Slice(1); + length--; + } +#endif + if (isNestedType) + { + (nestedNameLengths ??= new()).Add(length); + totalLength += 1; // skip the '+' sign in next search + } + totalLength += length; + } while (isNestedType); + + return true; + } + + internal static bool TryParseNextDecorator(ref ReadOnlySpan input, out int rankOrModifier) + { + // Then try pulling a single decorator. + // Whitespace cannot precede the decorator, but it can follow the decorator. + + ReadOnlySpan originalInput = input; // so we can restore on 'false' return + + if (TryStripFirstCharAndTrailingSpaces(ref input, '*')) + { + rankOrModifier = Pointer; + return true; + } + + if (TryStripFirstCharAndTrailingSpaces(ref input, '&')) + { + rankOrModifier = ByRef; + return true; + } + + if (TryStripFirstCharAndTrailingSpaces(ref input, '[')) + { + // SZArray := [] + // MDArray := [*] or [,] or [,,,, ...] + + int rank = 1; + bool hasSeenAsterisk = false; + + ReadNextArrayToken: + + if (TryStripFirstCharAndTrailingSpaces(ref input, ']')) + { + // End of array marker + rankOrModifier = rank == 1 && !hasSeenAsterisk ? SZArray : rank; + return true; + } + + if (!hasSeenAsterisk) + { + if (rank == 1 && TryStripFirstCharAndTrailingSpaces(ref input, '*')) + { + // [*] + hasSeenAsterisk = true; + goto ReadNextArrayToken; + } + else if (TryStripFirstCharAndTrailingSpaces(ref input, ',')) + { + // [,,, ...] + checked { rank++; } + goto ReadNextArrayToken; + } + } + + // Don't know what this token is. + // Fall through to 'return false' statement. + } + + input = originalInput; // ensure 'ref input' not mutated + rankOrModifier = 0; + return false; + } + + internal static bool TryStripFirstCharAndTrailingSpaces(ref ReadOnlySpan span, char value) + { + if (!span.IsEmpty && span[0] == value) + { + span = span.Slice(1).TrimStart(); + return true; + } + return false; + } + + [DoesNotReturn] + internal static void ThrowArgumentException_InvalidTypeName(int errorIndex) + { + throw new ArgumentException(SR.Argument_InvalidTypeName, $"typeName@{errorIndex}"); + } + + [DoesNotReturn] + internal static void ThrowInvalidOperation_MaxNodesExceeded(int limit) + { +#if SYSTEM_REFLECTION_METADATA + throw new InvalidOperationException(SR.Format(SR.InvalidOperation_MaxNodesExceeded, limit)); +#else + Debug.Fail("Expected to be unreachable"); + throw new InvalidOperationException(); +#endif + } + + [DoesNotReturn] + internal static void ThrowInvalidOperation_NotGenericType() + { +#if SYSTEM_REFLECTION_METADATA + throw new InvalidOperationException(SR.InvalidOperation_NotGenericType); +#else + Debug.Fail("Expected to be unreachable"); + throw new InvalidOperationException(); +#endif + } + + [DoesNotReturn] + internal static void ThrowInvalidOperation_NotNestedType() + { +#if SYSTEM_REFLECTION_METADATA + throw new InvalidOperationException(SR.InvalidOperation_NotNestedType); +#else + Debug.Fail("Expected to be unreachable"); + throw new InvalidOperationException(); +#endif + } + + [DoesNotReturn] + internal static void ThrowInvalidOperation_NoElement() + { +#if SYSTEM_REFLECTION_METADATA + throw new InvalidOperationException(SR.InvalidOperation_NoElement); +#else + Debug.Fail("Expected to be unreachable"); + throw new InvalidOperationException(); +#endif + } + + [DoesNotReturn] + internal static void ThrowInvalidOperation_HasToBeArrayClass() + { +#if SYSTEM_REFLECTION_METADATA + throw new InvalidOperationException(SR.Argument_HasToBeArrayClass); +#else + Debug.Fail("Expected to be unreachable"); + throw new InvalidOperationException(); +#endif + } + } +} diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeNameParserOptions.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeNameParserOptions.cs new file mode 100644 index 000000000000..551876e73147 --- /dev/null +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeNameParserOptions.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Reflection.Metadata +{ + public sealed class TypeNameParseOptions + { + private int _maxNodes = 20; + + /// + /// Limits the maximum value of node count that parser can handle. + /// + public int MaxNodes + { + get => _maxNodes; + set + { +#if NET8_0_OR_GREATER + ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(value, 0, nameof(value)); +#else + if (value <= 0) + { + throw new ArgumentOutOfRangeException(paramName: nameof(value)); + } +#endif + + _maxNodes = value; + } + } + + internal bool IsMaxDepthExceeded(int depth) => depth >= _maxNodes; + } +} diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaderBuilder.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaderBuilder.cs index f93b8bc0716d..9ddb82d35aa4 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaderBuilder.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaderBuilder.cs @@ -105,7 +105,7 @@ public static PEHeaderBuilder CreateLibraryHeader() return new PEHeaderBuilder(imageCharacteristics: Characteristics.ExecutableImage | Characteristics.Dll); } - internal bool Is32Bit => Machine != Machine.Amd64 && Machine != Machine.IA64 && Machine != Machine.Arm64 && Machine != Machine.RiscV64; + internal bool Is32Bit => Machine != Machine.Amd64 && Machine != Machine.IA64 && Machine != Machine.Arm64 && Machine != Machine.LoongArch64 && Machine != Machine.RiscV64; internal int ComputeSizeOfPEHeaders(int sectionCount) => PEBuilder.DosHeaderSize + diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEReader.EmbeddedPortablePdb.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEReader.EmbeddedPortablePdb.cs index 51eff57e43c0..e9d3b25e95af 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEReader.EmbeddedPortablePdb.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEReader.EmbeddedPortablePdb.cs @@ -99,7 +99,7 @@ internal static unsafe NativeHeapMemoryBlock DecodeEmbeddedPortablePdbDebugDirec try { -#if NETCOREAPP +#if NET actualLength = deflate.TryReadAll(new Span(decompressed.Pointer, decompressed.Size)); #else using var decompressedStream = new UnmanagedMemoryStream(decompressed.Pointer, decompressed.Size, decompressed.Size, FileAccess.Write); diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/AssemblyNameInfoTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/AssemblyNameInfoTests.cs new file mode 100644 index 000000000000..230e051ab045 --- /dev/null +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/AssemblyNameInfoTests.cs @@ -0,0 +1,105 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace System.Reflection.Metadata.Tests.Metadata +{ + public class AssemblyNameInfoTests + { + [Theory] + [InlineData("MyAssemblyName, Version=1.0.0.0, PublicKeyToken=b77a5c561934e089")] + public void WithPublicTokenKey(string fullName) + { + AssemblyName assemblyName = new AssemblyName(fullName); + + AssemblyNameInfo assemblyNameInfo = AssemblyNameInfo.Parse(fullName.AsSpan()); + + Assert.Equal(fullName, assemblyName.FullName); + Assert.Equal(fullName, assemblyNameInfo.FullName); + + Roundtrip(assemblyName); + } + + [Fact] + public void NoPublicKeyOrToken() + { + AssemblyName source = new AssemblyName(); + source.Name = "test"; + source.Version = new Version(1, 2, 3, 4); + source.CultureName = "en-US"; + + Roundtrip(source); + } + + [Theory] + [InlineData(ProcessorArchitecture.MSIL)] + [InlineData(ProcessorArchitecture.X86)] + [InlineData(ProcessorArchitecture.IA64)] + [InlineData(ProcessorArchitecture.Amd64)] + [InlineData(ProcessorArchitecture.Arm)] + public void ProcessorArchitectureIsPropagated(ProcessorArchitecture architecture) + { + string input = $"Abc, ProcessorArchitecture={architecture}"; + AssemblyNameInfo assemblyNameInfo = AssemblyNameInfo.Parse(input.AsSpan()); + + AssemblyName assemblyName = assemblyNameInfo.ToAssemblyName(); + + Assert.Equal(architecture, assemblyName.ProcessorArchitecture); + Assert.Equal(AssemblyContentType.Default, assemblyName.ContentType); + // By design (desktop compat) AssemblyName.FullName and ToString() do not include ProcessorArchitecture. + Assert.Equal(assemblyName.FullName, assemblyNameInfo.FullName); + Assert.DoesNotContain("ProcessorArchitecture", assemblyNameInfo.FullName); + } + + [Fact] + public void AssemblyContentTypeIsPropagated() + { + const string input = "Abc, ContentType=WindowsRuntime"; + AssemblyNameInfo assemblyNameInfo = AssemblyNameInfo.Parse(input.AsSpan()); + + AssemblyName assemblyName = assemblyNameInfo.ToAssemblyName(); + + Assert.Equal(AssemblyContentType.WindowsRuntime, assemblyName.ContentType); + Assert.Equal(ProcessorArchitecture.None, assemblyName.ProcessorArchitecture); + Assert.Equal(input, assemblyNameInfo.FullName); + Assert.Equal(assemblyName.FullName, assemblyNameInfo.FullName); + } + + [Fact] + public void RetargetableIsPropagated() + { + const string input = "Abc, Retargetable=Yes"; + AssemblyNameInfo assemblyNameInfo = AssemblyNameInfo.Parse(input.AsSpan()); + Assert.True((assemblyNameInfo.Flags & AssemblyNameFlags.Retargetable) != 0); + + AssemblyName assemblyName = assemblyNameInfo.ToAssemblyName(); + + Assert.True((assemblyName.Flags & AssemblyNameFlags.Retargetable) != 0); + Assert.Equal(AssemblyContentType.Default, assemblyName.ContentType); + Assert.Equal(ProcessorArchitecture.None, assemblyName.ProcessorArchitecture); + Assert.Equal(input, assemblyNameInfo.FullName); + Assert.Equal(assemblyName.FullName, assemblyNameInfo.FullName); + } + + [Fact] + public void EscapedSquareBracketIsNotAllowedInTheName() + => Assert.False(AssemblyNameInfo.TryParse("Esc\\[aped".AsSpan(), out _)); + + static void Roundtrip(AssemblyName source) + { + AssemblyNameInfo parsed = AssemblyNameInfo.Parse(source.FullName.AsSpan()); + Assert.Equal(source.Name, parsed.Name); + Assert.Equal(source.Version, parsed.Version); + Assert.Equal(source.CultureName, parsed.CultureName); + Assert.Equal(source.FullName, parsed.FullName); + + AssemblyName fromParsed = parsed.ToAssemblyName(); + Assert.Equal(source.Name, fromParsed.Name); + Assert.Equal(source.Version, fromParsed.Version); + Assert.Equal(source.CultureName, fromParsed.CultureName); + Assert.Equal(source.FullName, fromParsed.FullName); + Assert.Equal(source.GetPublicKeyToken(), fromParsed.GetPublicKeyToken()); + } + } +} diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/Decoding/CustomAttributeDecoderTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/Decoding/CustomAttributeDecoderTests.cs index 62944bef46d2..b697f7fadab3 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/Decoding/CustomAttributeDecoderTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/Decoding/CustomAttributeDecoderTests.cs @@ -197,7 +197,7 @@ public void TestCustomAttributeDecoderUsingReflection() } } -#if NETCOREAPP && !TARGET_BROWSER // Generic attribute is not supported on .NET Framework. +#if NET && !TARGET_BROWSER // Generic attribute is not supported on .NET Framework. [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.HasAssemblyFiles))] [ActiveIssue("https://github.com/dotnet/runtime/issues/60579", TestPlatforms.iOS | TestPlatforms.tvOS)] public void TestCustomAttributeDecoderGenericUsingReflection() diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/Decoding/SignatureDecoderTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/Decoding/SignatureDecoderTests.cs index e11c3e32445a..bcb6661e6ef2 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/Decoding/SignatureDecoderTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/Decoding/SignatureDecoderTests.cs @@ -130,6 +130,7 @@ public static void VarArgsCaller() // Test as much as we can with simple C# examples inline below. [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.HasAssemblyFiles))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/91923", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsAppleMobile))] public void SimpleSignatureProviderCoverage() { using (FileStream stream = File.OpenRead(AssemblyPathHelper.GetAssemblyLocation(typeof(SignaturesToDecode<>).GetTypeInfo().Assembly))) @@ -277,10 +278,14 @@ public static class PinnedAndUnpinnedLocalsToDecode public static unsafe int DoSomething() { byte[] bytes = new byte[] { 1, 2, 3 }; + Keep(ref bytes); fixed (byte* bytePtr = bytes) { return *bytePtr; } + + // Reference local variables to prevent them from being optimized out by Roslyn + static void Keep(ref T value) { }; } } diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameParserHelpersTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameParserHelpersTests.cs new file mode 100644 index 000000000000..b9d23a2be152 --- /dev/null +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameParserHelpersTests.cs @@ -0,0 +1,173 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using Xunit; + +namespace System.Reflection.Metadata.Tests +{ + public class TypeNameParserHelpersTests + { + [Theory] + [InlineData("A[]", 1, false)] + [InlineData("AB[a,b]", 2, false)] + [InlineData("AB[[a, b],[c,d]]", 2, false)] + [InlineData("12]]", 2, false)] + [InlineData("ABC&", 3, false)] + [InlineData("ABCD*", 4, false)] + [InlineData("ABCDE,otherType]]", 5, false)] + [InlineData("Containing+Nested", 10, true)] + [InlineData("NoSpecial.Characters", 20, false)] + [InlineData("Requires\\+Escaping", 18, false)] + [InlineData("Requires\\[Escaping+Nested", 18, true)] + [InlineData("Worst\\[\\]\\&\\*\\,\\+Case", 21, false)] + [InlineData("EscapingSthThatShouldNotBeEscaped\\A", -1 , false)] + [InlineData("EndsWithEscaping\\", -1, false)] + public void GetFullTypeNameLengthReturnsExpectedValue(string input, int expected, bool expectedIsNested) + { + Assert.Equal(expected, TypeNameParserHelpers.GetFullTypeNameLength(input.AsSpan(), out bool isNested)); + Assert.Equal(expectedIsNested, isNested); + + string withNamespace = $"Namespace1.Namespace2.Namespace3.{input}"; + int expectedWithNamespace = expected < 0 ? expected : expected + withNamespace.Length - input.Length; + Assert.Equal(expectedWithNamespace, TypeNameParserHelpers.GetFullTypeNameLength(withNamespace.AsSpan(), out isNested)); + Assert.Equal(expectedIsNested, isNested); + } + + [Theory] + [InlineData("JustTypeName", "JustTypeName")] + [InlineData("Namespace.TypeName", "TypeName")] + [InlineData("Namespace1.Namespace2.TypeName", "TypeName")] + [InlineData("Namespace.NotNamespace\\.TypeName", "NotNamespace\\.TypeName")] + [InlineData("Namespace1.Namespace2.Containing+Nested", "Nested")] + [InlineData("Namespace1.Namespace2.Not\\+Nested", "Not\\+Nested")] + [InlineData("NotNamespace1\\.NotNamespace2\\.TypeName", "NotNamespace1\\.NotNamespace2\\.TypeName")] + [InlineData("NotNamespace1\\.NotNamespace2\\.Not\\+Nested", "NotNamespace1\\.NotNamespace2\\.Not\\+Nested")] + public void GetNameReturnsJustName(string fullName, string expected) + => Assert.Equal(expected, TypeNameParserHelpers.GetName(fullName.AsSpan()).ToString()); + + [Theory] + [InlineData("simple", "simple")] + [InlineData("simple]", "simple")] + [InlineData("esc\\]aped", "esc\\]aped")] + [InlineData("esc\\]aped]", "esc\\]aped")] + public void GetAssemblyNameCandidateReturnsExpectedValue(string input, string expected) + => Assert.Equal(expected, TypeNameParserHelpers.GetAssemblyNameCandidate(input.AsSpan()).ToString()); + + [Theory] + [InlineData(TypeNameParserHelpers.SZArray, "[]")] + [InlineData(TypeNameParserHelpers.Pointer, "*")] + [InlineData(TypeNameParserHelpers.ByRef, "&")] + [InlineData(1, "[*]")] + [InlineData(2, "[,]")] + [InlineData(3, "[,,]")] + [InlineData(4, "[,,,]")] + public void AppendRankOrModifierStringRepresentationAppendsExpectedString(int input, string expected) + { + ValueStringBuilder builder = new ValueStringBuilder(initialCapacity: 10); + Assert.Equal(expected, TypeNameParserHelpers.GetRankOrModifierStringRepresentation(input, ref builder)); + } + + [Theory] + [InlineData(typeof(List))] + [InlineData(typeof(int?))] + [InlineData(typeof(List))] + [InlineData(typeof(Dictionary))] + [InlineData(typeof(ValueTuple))] + [InlineData(typeof(ValueTuple))] + public void GetGenericTypeFullNameReturnsSameStringAsTypeAPI(Type genericType) + { + TypeName openGenericTypeName = TypeName.Parse(genericType.GetGenericTypeDefinition().FullName.AsSpan()); + ReadOnlySpan genericArgNames = genericType.GetGenericArguments().Select(arg => TypeName.Parse(arg.AssemblyQualifiedName.AsSpan())).ToArray(); + + Assert.Equal(genericType.FullName, TypeNameParserHelpers.GetGenericTypeFullName(openGenericTypeName.FullName.AsSpan(), genericArgNames)); + } + + [Theory] + [InlineData("", false, false, "")] + [InlineData("[", false, false, "[")] // too little to be able to tell + [InlineData("[[", true, true, "")] + [InlineData("[[A],[B]]", true, true, "A],[B]]")] + [InlineData("[ [ A],[B]]", true, true, "A],[B]]")] + [InlineData("[\t[\t \r\nA],[B]]", true, true, "A],[B]]")] // whitespaces other than ' ' + [InlineData("[A,B]", true, false, "A,B]")] + [InlineData("[ A,B]", true, false, "A,B]")] + [InlineData("[]", false, false, "[]")] + [InlineData("[*]", false, false, "[*]")] + [InlineData("[,]", false, false, "[,]")] + [InlineData("[,,]", false, false, "[,,]")] + public void IsBeginningOfGenericAgsHandlesAllCasesProperly(string input, bool expectedResult, bool expectedDoubleBrackets, string expectedConsumedInput) + { + ReadOnlySpan inputSpan = input.AsSpan(); + + Assert.Equal(expectedResult, TypeNameParserHelpers.IsBeginningOfGenericArgs(ref inputSpan, out bool doubleBrackets)); + Assert.Equal(expectedDoubleBrackets, doubleBrackets); + Assert.Equal(expectedConsumedInput, inputSpan.ToString()); + } + + [Theory] + [InlineData("A.B.C", true, null, 5)] + [InlineData("A.B.C\\", false, null, 0)] // invalid type name: ends with escape character + [InlineData("A.B.C\\DoeNotNeedEscaping", false, null, 0)] // invalid type name: escapes non-special character + [InlineData("A.B+C", true, new int[] { 3 }, 5)] + [InlineData("A.B++C", false, null, 0)] // invalid type name: two following, unescaped + + [InlineData("A.B`1", true, null, 5)] + [InlineData("A+B`1+C1`2+DD2`3+E", true, new int[] { 1, 3, 4, 5 }, 18)] + [InlineData("Integer`2147483646+NoOverflow`1", true, new int[] { 18 }, 31)] + [InlineData("Integer`2147483647+Overflow`1", true, new int[] { 18 }, 29)] + public void TryGetTypeNameInfoGetsAllTheInfo(string input, bool expectedResult, int[] expectedNestedNameLengths, int expectedTotalLength) + { + List? nestedNameLengths = null; + ReadOnlySpan span = input.AsSpan(); + bool result = TypeNameParserHelpers.TryGetTypeNameInfo(ref span, ref nestedNameLengths, out int totalLength); + + Assert.Equal(expectedResult, result); + + if (expectedResult) + { + Assert.Equal(expectedNestedNameLengths, nestedNameLengths?.ToArray()); + Assert.Equal(expectedTotalLength, totalLength); + } + } + + [Theory] + [InlineData("*", true, TypeNameParserHelpers.Pointer, "")] + [InlineData(" *", false, default(int), " *")] // Whitespace cannot precede the decorator + [InlineData("* *", true, TypeNameParserHelpers.Pointer, "*")] // but it can follow the decorator. + [InlineData("&", true, TypeNameParserHelpers.ByRef, "")] + [InlineData("\t&", false, default(int), "\t&")] + [InlineData("&\t\r\n[]", true, TypeNameParserHelpers.ByRef, "[]")] + [InlineData("[]", true, TypeNameParserHelpers.SZArray, "")] + [InlineData("\r\n[]", false, default(int), "\r\n[]")] + [InlineData("[] []", true, TypeNameParserHelpers.SZArray, "[]")] + [InlineData("[,]", true, 2, "")] + [InlineData(" [,,,]", false, default(int), " [,,,]")] + [InlineData("[,,,,] *[]", true, 5, "*[]")] + public void TryParseNextDecoratorParsesTheDecoratorAndConsumesFollowingWhitespaces( + string input, bool expectedResult, int expectedModifier, string expectedConsumedInput) + { + ReadOnlySpan inputSpan = input.AsSpan(); + + Assert.Equal(expectedResult, TypeNameParserHelpers.TryParseNextDecorator(ref inputSpan, out int parsedModifier)); + Assert.Equal(expectedModifier, parsedModifier); + Assert.Equal(expectedConsumedInput, inputSpan.ToString()); + } + + [Theory] + [InlineData(" , ", ',', false, " , ")] // it can not start with a whitespace + [InlineData("AB", ',', false, "AB")] // does not start with given character + [InlineData(", ", ',', true, "")] // trimming + [InlineData(",[AB]", ',', true, "[AB]")] // nothing to trim + public void TryStripFirstCharAndTrailingSpacesWorksAsExpected( + string input, char argument, bool expectedResult, string expectedConsumedInput) + { + ReadOnlySpan inputSpan = input.AsSpan(); + + Assert.Equal(expectedResult, TypeNameParserHelpers.TryStripFirstCharAndTrailingSpaces(ref inputSpan, argument)); + Assert.Equal(expectedConsumedInput, inputSpan.ToString()); + } + } +} diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameParserSamples.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameParserSamples.cs new file mode 100644 index 000000000000..0c48cdc2641d --- /dev/null +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameParserSamples.cs @@ -0,0 +1,255 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using Xunit; + +namespace System.Reflection.Metadata.Tests +{ + public class TypeNameParserSamples + { + internal sealed class SampleSerializationBinder : SerializationBinder + { + private static TypeNameParseOptions _options; + + // we could use Frozen collections here ;) + private readonly static Dictionary _alwaysAllowed = new() + { + { typeof(string).FullName, typeof(string) }, + { typeof(int).FullName, typeof(int) }, + { typeof(uint).FullName, typeof(uint) }, + { typeof(long).FullName, typeof(long) }, + { typeof(ulong).FullName, typeof(ulong) }, + { typeof(double).FullName, typeof(double) }, + { typeof(float).FullName, typeof(float) }, + { typeof(bool).FullName, typeof(bool) }, + { typeof(short).FullName, typeof(short) }, + { typeof(ushort).FullName, typeof(ushort) }, + { typeof(byte).FullName, typeof(byte) }, + { typeof(char).FullName, typeof(char) }, + { typeof(DateTime).FullName, typeof(DateTime) }, + { typeof(TimeSpan).FullName, typeof(TimeSpan) }, + { typeof(Guid).FullName, typeof(Guid) }, + { typeof(Uri).FullName, typeof(Uri) }, + { typeof(DateTimeOffset).FullName, typeof(DateTimeOffset) }, + { typeof(Version).FullName, typeof(Version) }, + { typeof(Nullable).FullName, typeof(Nullable) }, // Nullable is generic! + }; + + private readonly Dictionary? _userDefined; + + public SampleSerializationBinder(Type[]? allowedTypes = null) + => _userDefined = allowedTypes?.ToDictionary(type => type.FullName); + + public override Type? BindToType(string assemblyName, string typeName) + { + // Fast path for common primitive type names and user-defined type names + // that use the same syntax and casing as System.Type.FullName API. + if (TryGetTypeFromFullName(typeName, out Type type)) + { + return type; + } + + _options ??= new TypeNameParseOptions() // there is no need for lazy initialization, I just wanted to have everything important in one method + { + // To prevent from unbounded recursion, we set the max depth for parser options. + // By ensuring that the max depth limit is enforced, we can safely use recursion in + // GetTypeFromParsedTypeName to get arrays of arrays and generics of generics. + MaxNodes = 10 + }; + + if (!TypeName.TryParse(typeName.AsSpan(), out TypeName parsed, _options)) + { + // we can throw any exception, log the information etc + throw new InvalidOperationException($"Invalid type name: '{typeName}'"); + } + + if (parsed.AssemblyName is not null) + { + // The attackers may create such a payload, + // where "typeName" passed to BindToType contains the assembly name + // and "assemblyName" passed to this method contains something else + // (some garbage or a different assembly name). Example: + // typeName: System.Int32, MyHackyDll.dll + // assemblyName: mscorlib.dll + throw new InvalidOperationException($"Type name '{typeName}' contained assembly name."); + } + + return GetTypeFromParsedTypeName(parsed); + } + + private Type? GetTypeFromParsedTypeName(TypeName parsed) + { + if (TryGetTypeFromFullName(parsed.FullName, out Type type)) + { + return type; + } + else if (parsed.IsArray) + { + TypeName arrayElementTypeName = parsed.GetElementType(); + Type arrayElementType = GetTypeFromParsedTypeName(arrayElementTypeName); // recursive call allows for creating arrays of arrays etc + + return parsed.IsSZArray + ? arrayElementType.MakeArrayType() + : arrayElementType.MakeArrayType(parsed.GetArrayRank()); + } + else if (parsed.IsConstructedGenericType) + { + TypeName genericTypeDefinitionName = parsed.GetGenericTypeDefinition(); + Type genericTypeDefinition = GetTypeFromParsedTypeName(genericTypeDefinitionName); + Debug.Assert(genericTypeDefinition.IsGenericTypeDefinition); + + ImmutableArray genericArgs = parsed.GetGenericArguments(); + Type[] typeArguments = new Type[genericArgs.Length]; + for (int i = 0; i < genericArgs.Length; i++) + { + typeArguments[i] = GetTypeFromParsedTypeName(genericArgs[i]); // recursive call allows for generics of generics like "List" + } + return genericTypeDefinition.MakeGenericType(typeArguments); + } + + throw new ArgumentException($"{parsed.FullName} is not on the allow list."); + } + + private bool TryGetTypeFromFullName(string fullName, out Type? type) + => _alwaysAllowed.TryGetValue(fullName, out type) + || (_userDefined is not null && _userDefined.TryGetValue(fullName, out type)); + } + + [Serializable] + public class CustomUserDefinedType + { + public int Integer { get; set; } + public string Text { get; set; } + public List ListOfDates { get; set; } + public CustomUserDefinedType[] ArrayOfCustomUserDefinedTypes { get; set; } + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] + public void CanDeserializeCustomUserDefinedType() + { + CustomUserDefinedType parent = new() + { + Integer = 1, + Text = "parent", + ListOfDates = new List() + { + DateTime.Parse("02/06/2024") + }, + ArrayOfCustomUserDefinedTypes = new [] + { + new CustomUserDefinedType() + { + Integer = 2, + Text = "child" + } + } + }; + SampleSerializationBinder binder = new( + allowedTypes: + [ + typeof(CustomUserDefinedType), + typeof(List<>) // using List would require using type forwarding info in dictionary + ]); + + CustomUserDefinedType deserialized = SerializeDeserialize(parent, binder); + + Assert.Equal(parent.Integer, deserialized.Integer); + Assert.Equal(parent.Text, deserialized.Text); + Assert.Equal(parent.ListOfDates.Count, deserialized.ListOfDates.Count); + for (int i = 0; i < deserialized.ListOfDates.Count; i++) + { + Assert.Equal(parent.ListOfDates[i], deserialized.ListOfDates[i]); + } + Assert.Equal(parent.ArrayOfCustomUserDefinedTypes.Length, deserialized.ArrayOfCustomUserDefinedTypes.Length); + for (int i = 0; i < deserialized.ArrayOfCustomUserDefinedTypes.Length; i++) + { + Assert.Equal(parent.ArrayOfCustomUserDefinedTypes[i].Integer, deserialized.ArrayOfCustomUserDefinedTypes[i].Integer); + Assert.Equal(parent.ArrayOfCustomUserDefinedTypes[i].Text, deserialized.ArrayOfCustomUserDefinedTypes[i].Text); + } + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] + public void CanDeserializeDictionaryUsingNonPublicComparerType() + { + Dictionary dictionary = new(StringComparer.CurrentCulture) + { + { "test", 1 } + }; + SampleSerializationBinder binder = new( + allowedTypes: + [ + typeof(Dictionary<,>), // this could be Dictionary to be more strict + StringComparer.CurrentCulture.GetType(), // this type is not public, this is all this test is about + typeof(Globalization.CompareOptions), + typeof(Globalization.CompareInfo), + typeof(KeyValuePair<,>), // this could be KeyValuePair to be more strict + ]); + + Dictionary deserialized = SerializeDeserialize(dictionary, binder); + + Assert.Equal(dictionary, deserialized); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] + public void CanDeserializeArraysOfArrays() + { + int[][] arrayOfArrays = new int[10][]; + for (int i = 0; i < arrayOfArrays.Length; i++) + { + arrayOfArrays[i] = Enumerable.Repeat(i, 10).ToArray(); + } + + SampleSerializationBinder binder = new(); + int[][] deserialized = SerializeDeserialize(arrayOfArrays, binder); + + Assert.Equal(arrayOfArrays.Length, deserialized.Length); + for (int i = 0; i < arrayOfArrays.Length; i++) + { + Assert.Equal(arrayOfArrays[i], deserialized[i]); + } + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] + public void CanDeserializeListOfListOfInt() + { + List> listOfListOfInts = new(10); + for (int i = 0; i < listOfListOfInts.Count; i++) + { + listOfListOfInts[i] = Enumerable.Repeat(i, 10).ToList(); + } + + SampleSerializationBinder binder = new(allowedTypes: + [ + typeof(List<>) + ]); + List> deserialized = SerializeDeserialize(listOfListOfInts, binder); + + Assert.Equal(listOfListOfInts.Count, deserialized.Count); + for (int i = 0; i < listOfListOfInts.Count; i++) + { + Assert.Equal(listOfListOfInts[i], deserialized[i]); + } + } + + static T SerializeDeserialize(T instance, SerializationBinder binder) + { + using MemoryStream bfStream = new(); + BinaryFormatter bf = new() + { + Binder = binder + }; + + bf.Serialize(bfStream, instance); + bfStream.Position = 0; + + return (T)bf.Deserialize(bfStream); + } + } +} diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameTests.cs new file mode 100644 index 000000000000..a5e22b5d6c50 --- /dev/null +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/TypeNameTests.cs @@ -0,0 +1,748 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Reflection.Emit; +using Xunit; + +namespace System.Reflection.Metadata.Tests +{ + public class TypeNameTests + { + [Theory] + [InlineData(" System.Int32", "System.Int32", "Int32")] + [InlineData(" MyNamespace.MyType+NestedType", "MyNamespace.MyType+NestedType", "NestedType")] + public void SpacesAtTheBeginningAreOK(string input, string expectedFullName, string expectedName) + { + TypeName parsed = TypeName.Parse(input.AsSpan()); + + Assert.Equal(expectedName, parsed.Name); + Assert.Equal(expectedFullName, parsed.FullName); + Assert.Equal(expectedFullName, parsed.AssemblyQualifiedName); + } + + [Fact] + public void LeadingDotIsNotConsumedForFullTypeNamesWithoutNamespace() + { + // This is true only for the public API. + // The internal CoreLib implementation consumes the leading dot for backward compat. + TypeName parsed = TypeName.Parse(".NoNamespace".AsSpan()); + + Assert.Equal("NoNamespace", parsed.Name); + Assert.Equal(".NoNamespace", parsed.FullName); + Assert.Equal(".NoNamespace", parsed.AssemblyQualifiedName); + } + + [Theory] + [InlineData("")] + [InlineData(" ")] + [InlineData(" ")] + public void EmptyStringsAreNotAllowed(string input) + { + Assert.Throws(() => TypeName.Parse(input.AsSpan())); + + Assert.False(TypeName.TryParse(input.AsSpan(), out _)); + } + + [Theory] + [InlineData("Namespace.Containing++Nested")] // a pair of '++' + [InlineData("TypeNameFollowedBySome[] unconsumedCharacters")] + [InlineData("MissingAssemblyName, ")] + [InlineData("ExtraComma, ,")] + [InlineData("ExtraComma, , System.Runtime")] + [InlineData("UsingGenericSyntaxButNotProvidingGenericArgs[[]]")] + [InlineData("ExtraCommaAfterFirstGenericArg`1[[type1, assembly1],]")] + [InlineData("MissingClosingSquareBrackets`1[[type1, assembly1")] // missing ]] + [InlineData("MissingClosingSquareBracket`1[[type1, assembly1]")] // missing ] + [InlineData("MissingClosingSquareBracketsMixedMode`2[[type1, assembly1], type2")] // missing ] + [InlineData("MissingClosingSquareBrackets`2[[type1, assembly1], [type2, assembly2")] // missing ] + [InlineData("MissingClosingSquareBracketsMixedMode`2[type1, [type2, assembly2")] // missing ]] + [InlineData("MissingClosingSquareBracketsMixedMode`2[type1, [type2, assembly2]")] // missing ] + [InlineData("EscapeCharacterAtTheEnd\\")] + [InlineData("EscapeNonSpecialChar\\a")] + [InlineData("EscapeNonSpecialChar\\0")] + [InlineData("DoubleNestingChar++Bla")] + public void InvalidTypeNamesAreNotAllowed(string input) + { + Assert.Throws(() => TypeName.Parse(input.AsSpan())); + + Assert.False(TypeName.TryParse(input.AsSpan(), out _)); + } + + [Theory] + [InlineData("System.Int32&&")] // by-ref to by-ref is currently not supported by CLR + [InlineData("System.Int32[,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,]")] // more than max array rank (32) + public void ParserIsNotEnforcingRuntimeSpecificRules(string input) + { + Assert.True(TypeName.TryParse(input.AsSpan(), out _)); + + if (PlatformDetection.IsNotMonoRuntime) // https://github.com/dotnet/runtime/issues/45033 + { +#if NET + Assert.Throws(() => Type.GetType(input)); +#endif + } + } + + [Theory] + [InlineData("Namespace.Kość", "Namespace.Kość")] + public void UnicodeCharactersAreAllowedByDefault(string input, string expectedFullName) + => Assert.Equal(expectedFullName, TypeName.Parse(input.AsSpan()).FullName); + + [Theory] + [InlineData(typeof(int))] + [InlineData(typeof(Dictionary))] + [InlineData(typeof(int[][]))] + [InlineData(typeof(Assert))] // xUnit assembly + [InlineData(typeof(TypeNameTests))] // test assembly + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1.NestedGeneric_2.NestedNonGeneric_3))] + public void TypeNameCanContainAssemblyName(Type type) + { + AssemblyName expectedAssemblyName = new(type.Assembly.FullName); + + Verify(type, expectedAssemblyName, TypeName.Parse(type.AssemblyQualifiedName.AsSpan())); + + static void Verify(Type type, AssemblyName expectedAssemblyName, TypeName parsed) + { + Assert.Equal(type.AssemblyQualifiedName, parsed.AssemblyQualifiedName); + Assert.Equal(type.FullName, parsed.FullName); + Assert.Equal(type.Name, parsed.Name); + + AssemblyNameInfo parsedAssemblyName = parsed.AssemblyName; + Assert.NotNull(parsedAssemblyName); + + Assert.Equal(expectedAssemblyName.Name, parsedAssemblyName.Name); + Assert.Equal(expectedAssemblyName.Version, parsedAssemblyName.Version); + Assert.Equal(expectedAssemblyName.CultureName, parsedAssemblyName.CultureName); + Assert.Equal(expectedAssemblyName.FullName, parsedAssemblyName.FullName); + + Assert.Equal(default, parsedAssemblyName.Flags); + } + } + + [Theory] + [InlineData(10, "*")] // pointer to pointer + [InlineData(10, "[]")] // array of arrays + [InlineData(100, "*")] + [InlineData(100, "[]")] + public void MaxNodesIsRespected_TooManyDecorators(int maxDepth, string decorator) + { + TypeNameParseOptions options = new() + { + MaxNodes = maxDepth + }; + + string notTooMany = $"System.Int32{string.Join("", Enumerable.Repeat(decorator, maxDepth - 1))}"; + string tooMany = $"System.Int32{string.Join("", Enumerable.Repeat(decorator, maxDepth))}"; + + Assert.Throws(() => TypeName.Parse(tooMany.AsSpan(), options)); + Assert.False(TypeName.TryParse(tooMany.AsSpan(), out _, options)); + + TypeName parsed = TypeName.Parse(notTooMany.AsSpan(), options); + ValidateElementType(maxDepth, parsed, decorator); + + Assert.True(TypeName.TryParse(notTooMany.AsSpan(), out parsed, options)); + ValidateElementType(maxDepth, parsed, decorator); + + static void ValidateElementType(int maxDepth, TypeName parsed, string decorator) + { + for (int i = 0; i < maxDepth - 1; i++) + { + Assert.Equal(decorator == "*", parsed.IsPointer); + Assert.Equal(decorator == "[]", parsed.IsSZArray); + Assert.False(parsed.IsConstructedGenericType); + + parsed = parsed.GetElementType(); + } + } + } + + [Theory] + [InlineData(10)] + [InlineData(100)] + public void MaxNodesIsRespected_TooDeepGenerics(int maxDepth) + { + TypeNameParseOptions options = new() + { + MaxNodes = maxDepth + }; + + string tooDeep = GetName(maxDepth); + string notTooDeep = GetName(maxDepth - 1); + + Assert.Throws(() => TypeName.Parse(tooDeep.AsSpan(), options)); + Assert.False(TypeName.TryParse(tooDeep.AsSpan(), out _, options)); + + TypeName parsed = TypeName.Parse(notTooDeep.AsSpan(), options); + Validate(maxDepth, parsed); + + Assert.True(TypeName.TryParse(notTooDeep.AsSpan(), out parsed, options)); + Validate(maxDepth, parsed); + + static string GetName(int depth) + { + // MakeGenericType is not used here, as it crashes for larger depths + string coreLibName = typeof(object).Assembly.FullName; + string fullName = typeof(int).AssemblyQualifiedName!; + for (int i = 0; i < depth; i++) + { + fullName = $"System.Collections.Generic.List`1[[{fullName}]], {coreLibName}"; + } + return fullName; + } + + static void Validate(int maxDepth, TypeName parsed) + { + for (int i = 0; i < maxDepth - 1; i++) + { + Assert.True(parsed.IsConstructedGenericType); + parsed = parsed.GetGenericArguments()[0]; + } + } + } + + [Theory] + [InlineData(10)] + [InlineData(100)] + public void MaxNodesIsRespected_TooManyGenericArguments(int maxDepth) + { + TypeNameParseOptions options = new() + { + MaxNodes = maxDepth + }; + + string tooMany = GetName(maxDepth); + string notTooMany = GetName(maxDepth - 1); + + Assert.Throws(() => TypeName.Parse(tooMany.AsSpan(), options)); + Assert.False(TypeName.TryParse(tooMany.AsSpan(), out _, options)); + + TypeName parsed = TypeName.Parse(notTooMany.AsSpan(), options); + Validate(parsed, maxDepth); + + Assert.True(TypeName.TryParse(notTooMany.AsSpan(), out parsed, options)); + Validate(parsed, maxDepth); + + static string GetName(int depth) + => $"Some.GenericType`{depth}[{string.Join(",", Enumerable.Repeat("System.Int32", depth))}]"; + + static void Validate(TypeName parsed, int maxDepth) + { + Assert.True(parsed.IsConstructedGenericType); + ImmutableArray genericArgs = parsed.GetGenericArguments(); + Assert.Equal(maxDepth - 1, genericArgs.Length); + Assert.All(genericArgs, arg => Assert.False(arg.IsConstructedGenericType)); + } + } + + public static IEnumerable GenericArgumentsAreSupported_Arguments() + { + yield return new object[] + { + "Generic`1[[A]]", + "Generic`1", + "Generic`1[[A]]", + new string[] { "A" }, + null + }; + yield return new object[] + { + "Generic`1[A]", + "Generic`1", + "Generic`1[[A]]", + new string[] { "A" }, + null + }; + yield return new object[] + { + "Generic`3[[A],[B],[C]]", + "Generic`3", + "Generic`3[[A],[B],[C]]", + new string[] { "A", "B", "C" }, + null + }; + yield return new object[] + { + "Generic`3[A,B,C]", + "Generic`3", + "Generic`3[[A],[B],[C]]", + new string[] { "A", "B", "C" }, + null + }; + yield return new object[] + { + "Generic`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + "Generic`1", + "Generic`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + new string[] { "System.Int32" }, + new AssemblyName[] { new AssemblyName("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") } + }; + yield return new object[] + { + "Generic`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Boolean, mscorlib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + "Generic`2", + "Generic`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Boolean, mscorlib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + new string[] { "System.Int32", "System.Boolean" }, + new AssemblyName[] + { + new AssemblyName("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"), + new AssemblyName("mscorlib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") + } + }; + yield return new object[] + { + "Generic`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089], System.Boolean]", + "Generic`2", + "Generic`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Boolean]]", + new string[] { "System.Int32", "System.Boolean" }, + new AssemblyName[] + { + new AssemblyName("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"), + null + } + }; + yield return new object[] + { + "Generic`2[System.Boolean, [System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + "Generic`2", + "Generic`2[[System.Boolean],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + new string[] { "System.Boolean", "System.Int32" }, + new AssemblyName[] + { + null, + new AssemblyName("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") + } + }; + yield return new object[] + { + "Generic`3[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089], System.Boolean, [System.Byte, other, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + "Generic`3", + "Generic`3[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Boolean],[System.Byte, other, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", + new string[] { "System.Int32", "System.Boolean", "System.Byte" }, + new AssemblyName[] + { + new AssemblyName("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"), + null, + new AssemblyName("other, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") + } + }; + yield return new object[] + { + "Generic`3[System.Boolean, [System.Byte, other, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089], System.Int32]", + "Generic`3", + "Generic`3[[System.Boolean],[System.Byte, other, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32]]", + new string[] { "System.Boolean", "System.Byte", "System.Int32" }, + new AssemblyName[] + { + null, + new AssemblyName("other, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"), + null + } + }; + } + + [Theory] + [MemberData(nameof(GenericArgumentsAreSupported_Arguments))] + public void GenericArgumentsAreSupported(string input, string name, string fullName, string[] genericTypesFullNames, AssemblyName[]? assemblyNames) + { + TypeName parsed = TypeName.Parse(input.AsSpan()); + + Assert.Equal(name, parsed.Name); + Assert.Equal(fullName, parsed.FullName); + Assert.True(parsed.IsConstructedGenericType); + Assert.NotNull(parsed.GetGenericTypeDefinition()); + Assert.False(parsed.IsSimple); + + ImmutableArray typeNames = parsed.GetGenericArguments(); + for (int i = 0; i < genericTypesFullNames.Length; i++) + { + TypeName genericArg = typeNames[i]; + Assert.Equal(genericTypesFullNames[i], genericArg.FullName); + Assert.True(genericArg.IsSimple); + Assert.False(genericArg.IsConstructedGenericType); + Assert.Throws(genericArg.GetGenericTypeDefinition); + + if (assemblyNames is not null) + { + if (assemblyNames[i] is null) + { + Assert.Null(genericArg.AssemblyName); + } + else + { + Assert.Equal(assemblyNames[i].FullName, genericArg.AssemblyName.FullName); + Assert.Equal(assemblyNames[i].Name, genericArg.AssemblyName.Name); + } + } + } + } + + public static IEnumerable DecoratorsAreSupported_Arguments() + { + yield return new object[] + { + "TypeName*", "TypeName", false, false, -1, false, true + }; + yield return new object[] + { + "TypeName&", "TypeName", false, false, -1, true, false + }; + yield return new object[] + { + "TypeName[]", "TypeName", true, true, 1, false, false + }; + yield return new object[] + { + "TypeName[*]", "TypeName", true, false, 1, false, false + }; + yield return new object[] + { + "TypeName[,,,]", "TypeName", true, false, 4, false, false + }; + } + + [Theory] + [MemberData(nameof(DecoratorsAreSupported_Arguments))] + public void DecoratorsAreSupported(string input, string typeNameWithoutDecorators, bool isArray, bool isSzArray, int arrayRank, bool isByRef, bool isPointer) + { + TypeName parsed = TypeName.Parse(input.AsSpan()); + + Assert.Equal(input, parsed.FullName); + Assert.Equal(isArray, parsed.IsArray); + Assert.Equal(isSzArray, parsed.IsSZArray); + if (isArray) + { + Assert.Equal(arrayRank, parsed.GetArrayRank()); + } + else + { + Assert.Throws(() => parsed.GetArrayRank()); + } + Assert.Equal(isByRef, parsed.IsByRef); + Assert.Equal(isPointer, parsed.IsPointer); + Assert.False(parsed.IsSimple); + + TypeName elementType = parsed.GetElementType(); + Assert.NotNull(elementType); + Assert.Equal(typeNameWithoutDecorators, elementType.FullName); + Assert.True(elementType.IsSimple); + Assert.False(elementType.IsArray); + Assert.False(elementType.IsSZArray); + Assert.False(elementType.IsByRef); + Assert.False(elementType.IsPointer); + Assert.Throws(elementType.GetElementType); + } + + public static IEnumerable GetAdditionalConstructedTypeData() + { + yield return new object[] { typeof(Dictionary[,], List>[]), 16 }; + + // "Dictionary[,], List>[]" breaks down to complexity 16 like so: + // + // 01: Dictionary[,], List>[] + // 02: `- Dictionary[,], List> + // 03: +- Dictionary`2 + // 04: +- List[,] + // 05: | `- List + // 06: | +- List`1 + // 07: | `- int[] + // 08: | `- int + // 09: `- List + // 10: +- List`1 + // 11: `- int?[][][,] + // 12: `- int?[][] + // 13: `- int?[] + // 14: `- int? + // 15: +- Nullable`1 + // 16: `- int + + yield return new object[] { typeof(int[]).MakePointerType().MakeByRefType(), 4 }; // int[]*& + yield return new object[] { typeof(long).MakeArrayType(31), 2 }; // long[,,,,,,,...] + yield return new object[] { typeof(long).Assembly.GetType("System.Int64[*]"), 2 }; // long[*] + } + + [Theory] + [InlineData(typeof(TypeName), 1)] + [InlineData(typeof(TypeNameTests), 1)] + [InlineData(typeof(object), 1)] + [InlineData(typeof(Assert), 1)] // xunit + [InlineData(typeof(int[]), 2)] + [InlineData(typeof(int[,][]), 3)] + [InlineData(typeof(Nullable<>), 1)] // open generic type treated as elemental + [InlineData(typeof(NestedNonGeneric_0), 2)] // declaring and nested + [InlineData(typeof(NestedGeneric_0), 3)] // declaring, nested and generic arg + [InlineData(typeof(NestedNonGeneric_0.NestedNonGeneric_1), 3)] // declaring, nested 0 and nested 1 + // TypeNameTests+NestedGeneric_0`1+NestedGeneric_1`2[[Int32],[String],[Boolean]] (simplified for brevity) + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1), 6)] // declaring, nested 0 and nested 1 and 3 generic args + [MemberData(nameof(GetAdditionalConstructedTypeData))] + public void GetNodeCountReturnsExpectedValue(Type type, int expected) + { + TypeName parsed = TypeName.Parse(type.AssemblyQualifiedName.AsSpan()); + + Assert.Equal(expected, parsed.GetNodeCount()); + + Assert.Equal(type.Name, parsed.Name); + Assert.Equal(type.FullName, parsed.FullName); + Assert.Equal(type.AssemblyQualifiedName, parsed.AssemblyQualifiedName); + } + + [Fact] + public void IsSimpleReturnsTrueForNestedNonGenericTypes() + { + Assert.True(TypeName.Parse("Containing+Nested".AsSpan()).IsSimple); + Assert.False(TypeName.Parse(typeof(NestedGeneric_0).FullName.AsSpan()).IsSimple); + } + + [Fact] + public void DeclaringTypeThrowsForNonNestedTypes() + { + TypeName nested = TypeName.Parse("Containing+Nested".AsSpan()); + Assert.True(nested.IsNested); + Assert.Equal("Containing", nested.DeclaringType.Name); + + TypeName notNested = TypeName.Parse("NotNested".AsSpan()); + Assert.False(notNested.IsNested); + Assert.Throws(() => notNested.DeclaringType); + } + + [Theory] + [InlineData("SingleDimensionNonZeroIndexed[*]", true)] + [InlineData("SingleDimensionZeroIndexed[]", false)] + [InlineData("MultiDimensional[,,,,,,]", true)] + public void IsVariableBoundArrayTypeReturnsTrueForNonSZArrays(string typeName, bool expected) + { + TypeName parsed = TypeName.Parse(typeName.AsSpan()); + + Assert.True(parsed.IsArray); + Assert.Equal(expected, parsed.IsVariableBoundArrayType); + Assert.NotEqual(expected, parsed.IsSZArray); + Assert.InRange(parsed.GetArrayRank(), 1, 32); + } + + public static IEnumerable GetTypesThatRequireEscaping() + { + if (PlatformDetection.IsReflectionEmitSupported + && !PlatformDetection.IsMonoRuntime) // Mono does not escape Type.Name + { + AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("TypesThatRequireEscaping"), AssemblyBuilderAccess.Run); + ModuleBuilder module = assembly.DefineDynamicModule("TypesThatRequireEscapingModule"); + + yield return new object[] { module.DefineType("TypeNameWith+ThatIsNotNestedType").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith\\TheEscapingCharacter").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith&Ampersand").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith*Asterisk").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith[OpeningSquareBracket").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith]ClosingSquareBracket").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith[]BothSquareBrackets").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith[[]]NestedSquareBrackets").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith,Comma").CreateType() }; + yield return new object[] { module.DefineType("TypeNameWith\\[]+*&,AllSpecialCharacters").CreateType() }; + + TypeBuilder containingType = module.DefineType("ContainingTypeWithA+Plus"); + _ = containingType.CreateType(); // containing type must exist! + yield return new object[] { containingType.DefineNestedType("NoSpecialCharacters").CreateType() }; + yield return new object[] { containingType.DefineNestedType("Contains+Plus").CreateType() }; + } + } + + [Theory] + [InlineData(typeof(List))] + [InlineData(typeof(List>))] + [InlineData(typeof(Dictionary))] + [InlineData(typeof(Dictionary>))] + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1))] + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1.NestedGeneric_2))] + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1.NestedGeneric_2.NestedNonGeneric_3))] + [MemberData(nameof(GetTypesThatRequireEscaping))] + public void ParsedNamesMatchSystemTypeNames(Type type) + { + TypeName parsed = TypeName.Parse(type.AssemblyQualifiedName.AsSpan()); + + Assert.Equal(type.Name, parsed.Name); + Assert.Equal(type.FullName, parsed.FullName); + Assert.Equal(type.AssemblyQualifiedName, parsed.AssemblyQualifiedName); + + if (type.IsGenericType) + { + Type genericType = type.GetGenericTypeDefinition(); + TypeName genericTypeName = parsed.GetGenericTypeDefinition(); + Assert.Equal(genericType.Name, genericTypeName.Name); + Assert.Equal(genericType.FullName, genericTypeName.FullName); + Assert.Equal(genericType.AssemblyQualifiedName, genericTypeName.AssemblyQualifiedName); + } + } + + [Theory] + [InlineData("Name`2[[int], [bool]]", "Name`2")] // match + [InlineData("Name`1[[int], [bool]]", "Name`1")] // less than expected + [InlineData("Name`3[[int], [bool]]", "Name`3")] // more than expected + [InlineData("Name[[int], [bool]]", "Name")] // no backtick at all! + public void TheNumberAfterBacktickDoesNotEnforceGenericArgCount(string input, string expectedName) + { + TypeName parsed = TypeName.Parse(input.AsSpan()); + + Assert.True(parsed.IsConstructedGenericType); + Assert.Equal(expectedName, parsed.Name); + Assert.Equal($"{expectedName}[[int],[bool]]", parsed.FullName); + Assert.Equal("int", parsed.GetGenericArguments()[0].Name); + Assert.Equal("bool", parsed.GetGenericArguments()[1].Name); + } + + [Theory] + [InlineData(typeof(int))] + [InlineData(typeof(int?))] + [InlineData(typeof(int[]))] + [InlineData(typeof(int[,]))] + [InlineData(typeof(int[,,,]))] + [InlineData(typeof(List))] + [InlineData(typeof(List>))] + [InlineData(typeof(Dictionary))] + [InlineData(typeof(Dictionary>))] + [InlineData(typeof(NestedNonGeneric_0))] + [InlineData(typeof(NestedNonGeneric_0.NestedNonGeneric_1))] + [InlineData(typeof(NestedGeneric_0))] + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1))] + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1.NestedGeneric_2))] + [InlineData(typeof(NestedGeneric_0.NestedGeneric_1.NestedGeneric_2.NestedNonGeneric_3))] + public void CanImplementGetTypeUsingPublicAPIs_Roundtrip(Type type) + { + Test(type); + Test(type.MakePointerType()); + Test(type.MakePointerType().MakePointerType()); + Test(type.MakeByRefType()); + + if (!type.IsArray) + { + Test(type.MakeArrayType()); // [] + Test(type.MakeArrayType(1)); // [*] + Test(type.MakeArrayType(2)); // [,] + } + + static void Test(Type type) + { + TypeName parsed = TypeName.Parse(type.AssemblyQualifiedName.AsSpan()); + + // ensure that Name, FullName and AssemblyQualifiedName match reflection APIs!! + Assert.Equal(type.Name, parsed.Name); + Assert.Equal(type.FullName, parsed.FullName); + Assert.Equal(type.AssemblyQualifiedName, parsed.AssemblyQualifiedName); + // now load load the type from name + Verify(type, parsed, ignoreCase: false); +#if NET // something weird is going on here + // load using lowercase name + Verify(type, TypeName.Parse(type.AssemblyQualifiedName.ToLower().AsSpan()), ignoreCase: true); + // load using uppercase name + Verify(type, TypeName.Parse(type.AssemblyQualifiedName.ToUpper().AsSpan()), ignoreCase: true); +#endif + + static void Verify(Type type, TypeName typeName, bool ignoreCase) + { + Type afterRoundtrip = GetType(typeName, throwOnError: true, ignoreCase: ignoreCase); + + Assert.NotNull(afterRoundtrip); + Assert.Equal(type, afterRoundtrip); + } + } + +#if NET8_0_OR_GREATER + [RequiresUnreferencedCode("The type might be removed")] + [RequiresDynamicCode("Required by MakeArrayType")] +#else +#pragma warning disable IL2055, IL2057, IL2075, IL2096 +#endif + static Type? GetType(TypeName typeName, bool throwOnError = true, bool ignoreCase = false) + { + if (typeName.IsNested) + { + BindingFlags flagsCopiedFromClr = BindingFlags.NonPublic | BindingFlags.Public; + if (ignoreCase) + { + flagsCopiedFromClr |= BindingFlags.IgnoreCase; + } + return Make(GetType(typeName.DeclaringType, throwOnError, ignoreCase)?.GetNestedType(typeName.Name, flagsCopiedFromClr)); + } + else if (typeName.IsConstructedGenericType) + { + return Make(GetType(typeName.GetGenericTypeDefinition(), throwOnError, ignoreCase)); + } + else if(typeName.IsArray || typeName.IsPointer || typeName.IsByRef) + { + return Make(GetType(typeName.GetElementType(), throwOnError, ignoreCase)); + } + else + { + Assert.True(typeName.IsSimple); + + AssemblyName? assemblyName = typeName.AssemblyName.ToAssemblyName(); + Type? type = assemblyName is null + ? Type.GetType(typeName.FullName, throwOnError, ignoreCase) + : Assembly.Load(assemblyName).GetType(typeName.FullName, throwOnError, ignoreCase); + + return Make(type); + } + + Type? Make(Type? type) + { + if (type is null || typeName.IsSimple) + { + return type; + } + else if (typeName.IsConstructedGenericType) + { + ImmutableArray genericArgs = typeName.GetGenericArguments(); + Type[] genericTypes = new Type[genericArgs.Length]; + for (int i = 0; i < genericArgs.Length; i++) + { + Type? genericArg = GetType(genericArgs[i], throwOnError, ignoreCase); + if (genericArg is null) + { + return null; + } + genericTypes[i] = genericArg; + } + + return type.MakeGenericType(genericTypes); + } + else if (typeName.IsByRef) + { + return type.MakeByRefType(); + } + else if (typeName.IsPointer) + { + return type.MakePointerType(); + } + else if (typeName.IsSZArray) + { + return type.MakeArrayType(); + } + else + { + Assert.True(typeName.IsVariableBoundArrayType); + + return type.MakeArrayType(rank: typeName.GetArrayRank()); + } + } + } +#pragma warning restore IL2055, IL2057, IL2075, IL2096 + } + + public class NestedNonGeneric_0 + { + public class NestedNonGeneric_1 { } + } + + public class NestedGeneric_0 + { + public class NestedGeneric_1 + { + public class NestedGeneric_2 + { + public class NestedNonGeneric_3 { } + } + } + } + } +} diff --git a/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj b/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj index fa48b37d26ab..a985caddfff1 100644 --- a/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj +++ b/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj @@ -25,6 +25,7 @@ Link="Common\Microsoft\Win32\SafeHandles\SafeLibraryHandle.cs" /> + @@ -36,6 +37,9 @@ + + + diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs index b6ad1c372e0f..e5caf0e3a79f 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs @@ -17,7 +17,7 @@ internal abstract partial class RoAssembly public sealed override Module? GetModule(string name) => GetRoModule(name); public sealed override Module[] GetModules(bool getResourceModules) => ComputeRoModules(getResourceModules).CloneArray(); -#if NETCOREAPP +#if NET [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif public sealed override FileStream? GetFile(string name) @@ -28,7 +28,7 @@ internal abstract partial class RoAssembly return new FileStream(m.FullyQualifiedName, FileMode.Open, FileAccess.Read, FileShare.Read); } -#if NETCOREAPP +#if NET [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif public sealed override FileStream[] GetFiles(bool getResourceModules) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs index 9e0e4320a021..8ba5c1656008 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs @@ -45,12 +45,12 @@ protected RoAssembly(MetadataLoadContext loader, int assemblyFileCount) // Location and codebase public abstract override string Location { get; } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeBaseMessage, DiagnosticId = Obsoletions.CodeBaseDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif public sealed override string CodeBase => throw new NotSupportedException(SR.NotSupported_AssemblyCodeBase); -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeBaseMessage, DiagnosticId = Obsoletions.CodeBaseDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif @@ -159,7 +159,7 @@ public sealed override AssemblyName[] GetReferencedAssemblies() // Miscellaneous properties public sealed override bool ReflectionOnly => true; -#if NETCOREAPP +#if NET [Obsolete("The Global Assembly Cache is not supported.", DiagnosticId = "SYSLIB0005", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed override bool GlobalAssemblyCache => false; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs index d172f20f1cb0..c303886f9e70 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs @@ -134,7 +134,7 @@ public static bool NeedsEscapingInTypeName(this char c) public static string UnescapeTypeNameIdentifier(this string identifier) { -#if NET5_0_OR_GREATER +#if NET if (identifier.Contains('\\')) #else if (identifier.IndexOf('\\') != -1) @@ -367,7 +367,7 @@ public static RoAssemblyName ToRoAssemblyName(this AssemblyName assemblyName) public static byte[] ToUtf8(this string s) => Encoding.UTF8.GetBytes(s); -#if NETCOREAPP +#if NET public static string ToUtf16(this ReadOnlySpan utf8) => Encoding.UTF8.GetString(utf8); #else public static unsafe string ToUtf16(this ReadOnlySpan utf8) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs index bd19faaac625..f236b209b3d2 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs @@ -34,7 +34,7 @@ internal RoModule(string fullyQualifiedName) internal const string UnknownStringMessageInRAF = "Returns for modules with no file path"; -#if NETCOREAPP +#if NET [RequiresAssemblyFiles(UnknownStringMessageInRAF)] #endif public sealed override string FullyQualifiedName => _fullyQualifiedName; @@ -42,7 +42,7 @@ internal RoModule(string fullyQualifiedName) public abstract override int MetadataToken { get; } public abstract override Guid ModuleVersionId { get; } -#if NETCOREAPP +#if NET [RequiresAssemblyFiles(UnknownStringMessageInRAF)] #endif public sealed override string Name diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoModifiedType.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoModifiedType.cs index afb9c79952cc..0e5928d26bbc 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoModifiedType.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoModifiedType.cs @@ -152,7 +152,7 @@ public override Type[] GetOptionalCustomModifiers() public override IEnumerable DeclaredNestedTypes { -#if NETCOREAPP +#if NET [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicNestedTypes | DynamicallyAccessedMemberTypes.PublicNestedTypes)] #endif get { throw new NotSupportedException(SR.NotSupported_ModifiedType); } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.cs index 50ab6b7f307a..1a5369f2f638 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.cs @@ -331,7 +331,7 @@ public sealed override Type MakeArrayType(int rank) private volatile RoType? _lazyUnderlyingEnumType; public sealed override Array GetEnumValues() => throw new InvalidOperationException(SR.Arg_InvalidOperation_Reflection); -#if NET7_0_OR_GREATER +#if NET [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2085:UnrecognizedReflectionPattern", Justification = "Enum Types are not trimmed.")] public override Array GetEnumValuesAsUnderlyingType() diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/ILLink.Descriptors.xml b/src/libraries/System.Reflection.MetadataLoadContext/tests/ILLink.Descriptors.xml index fdb5d5f8422c..c5be88bbbae1 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/ILLink.Descriptors.xml +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/ILLink.Descriptors.xml @@ -6,4 +6,5 @@ --> + diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/System.Reflection.MetadataLoadContext.Tests.csproj b/src/libraries/System.Reflection.MetadataLoadContext/tests/System.Reflection.MetadataLoadContext.Tests.csproj index cba407973381..4feacf3ede60 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/System.Reflection.MetadataLoadContext.Tests.csproj +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/System.Reflection.MetadataLoadContext.Tests.csproj @@ -90,7 +90,9 @@ + + diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/TestUtils/NetStandardBridge.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/TestUtils/NetStandardBridge.cs index 95ae7cea3e3e..e4fb5fbc1f5a 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/TestUtils/NetStandardBridge.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/TestUtils/NetStandardBridge.cs @@ -8,7 +8,7 @@ namespace System.Reflection.Tests { internal static class NetCoreApiEmulators { -#if NETCOREAPP +#if NET public static bool IsSZArray(this Type t) => t.IsSZArray; public static bool IsVariableBoundArray(this Type t) => t.IsVariableBoundArray; public static bool IsTypeDefinition(this Type t) => t.IsTypeDefinition; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs index 03611db20825..c47621396354 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs @@ -365,7 +365,7 @@ public static IEnumerable GetEnumUnderlyingTypeData } } -#if NET7_0_OR_GREATER +#if NET [Fact] public static void GetEnumValuesAsUnderlyingType() { diff --git a/src/libraries/System.Reflection.TypeExtensions/tests/ILLink.Descriptors.xml b/src/libraries/System.Reflection.TypeExtensions/tests/ILLink.Descriptors.xml new file mode 100644 index 000000000000..573b67e7172d --- /dev/null +++ b/src/libraries/System.Reflection.TypeExtensions/tests/ILLink.Descriptors.xml @@ -0,0 +1,3 @@ + + + diff --git a/src/libraries/System.Reflection.TypeExtensions/tests/ModuleTests.cs b/src/libraries/System.Reflection.TypeExtensions/tests/ModuleTests.cs index 9017b400f280..4e9233de36a7 100644 --- a/src/libraries/System.Reflection.TypeExtensions/tests/ModuleTests.cs +++ b/src/libraries/System.Reflection.TypeExtensions/tests/ModuleTests.cs @@ -28,7 +28,10 @@ public void GetModuleVersionId_KnownAssembly_ReturnsExpected() { Module module = Assembly.Load(new AssemblyName("TinyAssembly")).ManifestModule; Assert.True(module.HasModuleVersionId()); - Assert.Equal(Guid.Parse("{06BB2468-908C-48CF-ADE9-DB6DE4614004}"), module.GetModuleVersionId()); + if (!(PlatformDetection.IsMonoRuntime && PlatformDetection.IsAppleMobile && PlatformDetection.IsBuiltWithAggressiveTrimming)) + { + Assert.Equal(Guid.Parse("{06BB2468-908C-48CF-ADE9-DB6DE4614004}"), module.GetModuleVersionId()); + } } } } diff --git a/src/libraries/System.Reflection.TypeExtensions/tests/System.Reflection.TypeExtensions.Tests.csproj b/src/libraries/System.Reflection.TypeExtensions/tests/System.Reflection.TypeExtensions.Tests.csproj index 233e848ac80e..4cec27f2eab3 100644 --- a/src/libraries/System.Reflection.TypeExtensions/tests/System.Reflection.TypeExtensions.Tests.csproj +++ b/src/libraries/System.Reflection.TypeExtensions/tests/System.Reflection.TypeExtensions.Tests.csproj @@ -22,5 +22,6 @@ TinyAssembly.dll PreserveNewest + - \ No newline at end of file + diff --git a/src/libraries/System.Resources.Extensions/tests/ILLink.Descriptors.xml b/src/libraries/System.Resources.Extensions/tests/ILLink.Descriptors.xml new file mode 100644 index 000000000000..cec64e4a9de6 --- /dev/null +++ b/src/libraries/System.Resources.Extensions/tests/ILLink.Descriptors.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/libraries/System.Resources.Extensions/tests/System.Resources.Extensions.Tests.csproj b/src/libraries/System.Resources.Extensions/tests/System.Resources.Extensions.Tests.csproj index c1b004ee9110..8a197d093686 100644 --- a/src/libraries/System.Resources.Extensions/tests/System.Resources.Extensions.Tests.csproj +++ b/src/libraries/System.Resources.Extensions/tests/System.Resources.Extensions.Tests.csproj @@ -2,6 +2,7 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-unix;$(NetFrameworkMinimum) true + true @@ -15,7 +16,7 @@ - + @@ -25,7 +26,10 @@ - + + + + CP0001 diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/RcwAroundCcwTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/RcwAroundCcwTests.cs index 765c26ffac59..8ba4511fe93d 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/RcwAroundCcwTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/RcwAroundCcwTests.cs @@ -386,5 +386,39 @@ public void IStringArrayMarshallingFails_Failing() obj.ByValueOutParam(strings); }); } + + [Fact] + public unsafe void IHideWorksAsExpected() + { + IHide obj = CreateWrapper(); + + // IHide.SameMethod should be index 3 + Assert.Equal(3, obj.SameMethod()); + Assert.Equal(4, obj.DifferentMethod()); + + IHide2 obj2 = (IHide2)obj; + + // IHide2.SameMethod should be index 5 + Assert.Equal(5, obj2.SameMethod()); + Assert.Equal(4, obj2.DifferentMethod()); + Assert.Equal(6, obj2.DifferentMethod2()); + + IHide3 obj3 = (IHide3)obj; + // IHide3.SameMethod should be index 7 + Assert.Equal(7, obj3.SameMethod()); + Assert.Equal(4, obj3.DifferentMethod()); + Assert.Equal(6, obj3.DifferentMethod2()); + Assert.Equal(8, obj3.DifferentMethod3()); + + // Ensure each VTable method points to the correct method on HideBaseMethods + for (int i = 3; i < 9; i++) + { + var (__this, __vtable_native) = ((global::System.Runtime.InteropServices.Marshalling.IUnmanagedVirtualMethodTableProvider)obj3).GetVirtualMethodTableInfoForKey(typeof(global::SharedTypes.ComInterfaces.IHide3)); + int __retVal; + int __invokeRetVal; + __invokeRetVal = ((delegate* unmanaged[MemberFunction])__vtable_native[i])(__this, &__retVal); + Assert.Equal(i, __retVal); + } + } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs index 8defdfd8c4e3..af89c22e25fd 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; using System.Threading; +using Microsoft.Diagnostics.Runtime; using SharedTypes; using Xunit; using static ComInterfaceGenerator.Tests.UnmanagedToManagedCustomMarshallingTests; @@ -156,11 +157,11 @@ public unsafe void ValidateArrayElementsAndOutParameterNotFreed_Stateless() try { var values = new int[] { 1, 32, 63, 124, 255 }; - int freeCalls = IntWrapperMarshallerToIntWithFreeCounts.NumCallsToFree; - - NativeExportsNE.UnmanagedToManagedCustomMarshalling.SumAndSetNativeObjectData(wrapper, values, values.Length, out int _); - + int oldValue = startingValue + 100; + NativeExportsNE.UnmanagedToManagedCustomMarshalling.SumAndSetNativeObjectData(wrapper, values, values.Length, out oldValue); + Assert.Equal(values.Sum(), impl.GetData().i); + Assert.Equal(startingValue, oldValue); Assert.Equal(freeCalls, IntWrapperMarshallerToIntWithFreeCounts.NumCallsToFree); } finally @@ -181,11 +182,11 @@ public unsafe void ValidateArrayElementsByRefFreed_Stateless() try { var values = new int[] { 1, 32, 63, 124, 255 }; - int freeCalls = IntWrapperMarshallerToIntWithFreeCounts.NumCallsToFree; - - NativeExportsNE.UnmanagedToManagedCustomMarshalling.SumAndSetNativeObjectData(wrapper, ref values, values.Length, out int _); - + int oldValue = startingValue + 100; + NativeExportsNE.UnmanagedToManagedCustomMarshalling.SumAndSetNativeObjectData(wrapper, ref values, values.Length, out oldValue); + Assert.Equal(values.Sum(), impl.GetData().i); + Assert.Equal(startingValue, oldValue); Assert.Equal(freeCalls + values.Length, IntWrapperMarshallerToIntWithFreeCounts.NumCallsToFree); } finally diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs index 12b59f274425..c3115b7f1dba 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -109,8 +110,6 @@ public static StatelessCollectionAllShapes AllocateContainerFor } """; - public static readonly string DisableRuntimeMarshalling = "[assembly:System.Runtime.CompilerServices.DisableRuntimeMarshalling]"; - public static readonly string UsingSystemRuntimeInteropServicesMarshalling = "using System.Runtime.InteropServices.Marshalling;"; public const string IntMarshaller = """ [CustomMarshaller(typeof(int), MarshalMode.Default, typeof(IntMarshaller))] internal static class IntMarshaller @@ -433,6 +432,87 @@ partial interface INativeAPI {{_attributeProvider.AdditionalUserRequiredInterfaces("INativeAPI")}} """; + public string DerivedComInterfaceTypeWithShadowingMethod => $$""" + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + {{GeneratedComInterface()}} + partial interface IComInterface + { + void Method(); + } + {{GeneratedComInterface()}} + partial interface IComInterface2 : IComInterface + { + new void Method(); + } + """; + + public string DerivedComInterfaceTypeShadowsNonComMethod => $$""" + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + {{GeneratedComInterface()}} + partial interface IComInterface + { + void Method(); + } + interface IOtherInterface + { + void Method2(); + } + {{GeneratedComInterface()}} + partial interface IComInterface2 : IComInterface + { + new void Method2(); + } + """; + + public string DerivedComInterfaceTypeShadowsComAndNonComMethod => $$""" + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + {{GeneratedComInterface()}} + partial interface IComInterface + { + void Method(); + } + interface IOtherInterface + { + void Method(); + } + {{GeneratedComInterface()}} + partial interface IComInterface2 : IComInterface + { + new void Method(); + } + """; + + public string DerivedComInterfaceTypeTwoLevelShadows => $$""" + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + {{GeneratedComInterface()}} + partial interface IComInterface + { + void Method(); + } + {{GeneratedComInterface()}} + partial interface IComInterface1: IComInterface + { + new void Method1(); + } + {{GeneratedComInterface()}} + partial interface IComInterface2 : IComInterface1 + { + new void Method(); + } + """; + public string DerivedComInterfaceType => $$""" using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs index feb69cc01da9..1522ab3478ac 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Threading.Tasks; -using Microsoft.DotNet.XUnitExtensions.Attributes; using Microsoft.Interop.UnitTests; using Xunit; using VerifyComInterfaceGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; @@ -336,6 +335,10 @@ public static IEnumerable ComInterfaceSnippetsToCompile() { CodeSnippets codeSnippets = new(new GeneratedComInterfaceAttributeProvider()); yield return new object[] { ID(), codeSnippets.DerivedComInterfaceType }; + yield return new object[] { ID(), codeSnippets.DerivedComInterfaceTypeWithShadowingMethod }; + yield return new object[] { ID(), codeSnippets.DerivedComInterfaceTypeShadowsNonComMethod }; + yield return new object[] { ID(), codeSnippets.DerivedComInterfaceTypeShadowsComAndNonComMethod }; + yield return new object[] { ID(), codeSnippets.DerivedComInterfaceTypeTwoLevelShadows}; yield return new object[] { ID(), codeSnippets.DerivedWithParametersDeclaredInOtherNamespace }; yield return new object[] { ID(), codeSnippets.ComInterfaceParameters }; } diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/RefParameters.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/RefParameters.cs new file mode 100644 index 000000000000..3e845103eb2b --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/RefParameters.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Runtime.InteropServices; +using SharedTypes; +using Xunit; + +namespace LibraryImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + public partial class RefParameters + { + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "out_params")] + public static partial int OutParameters(out int values, out IntFields numValues); + } + } + public class RefParameters + { + [Fact] + public void OutParametersAreDefaultInitialized() + { + int myInt = 12; + IntFields myIntFields = new IntFields() { a = 12, b = 12, c = 12 }; + NativeExportsNE.RefParameters.OutParameters(out myInt, out myIntFields); + Debug.Assert(myInt == default); + Debug.Assert(myIntFields.a == default && myIntFields.b == default && myIntFields.c == default); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs index 413809f30f60..6181069f6bf4 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs @@ -147,7 +147,7 @@ public void StringToHGlobalUniToString() } -#if NETCOREAPP +#if NET [Fact] public void TestUTF8String() { diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj index 3daf1f99fe8b..ad5bd11ee41c 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj @@ -91,12 +91,12 @@ - arm64-apple-ios14.2-macabi - x86_64-apple-ios13.5-macabi + arm64-apple-ios$(MacCatalystVersionMin)-macabi + x86_64-apple-ios$(MacCatalystVersionMin)-macabi - arm64-apple-macos11 - x86_64-apple-macos10.15 + arm64-apple-macos$(macOSVersionMin) + x86_64-apple-macos$(macOSVersionMin) macosx diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/RefParameters.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/RefParameters.cs new file mode 100644 index 000000000000..5868826a359e --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/RefParameters.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using SharedTypes; + +namespace NativeExports +{ + public static unsafe class RefParameters + { + [UnmanagedCallersOnly(EntryPoint = "out_params")] + public static void EnsureOutParamIsDefault(int* ri, [DNNE.C99Type("struct int_fields*")]IntFields* rif) + { + int i = *ri; + Debug.Assert(i == default); + IntFields _if = *rif; + Debug.Assert(_if.a == default && _if.b == default && _if.c == default); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs index a8e6458fb0ab..bc3cac9d0a3c 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs @@ -198,6 +198,7 @@ public static void ExchangeNativeObjectData([DNNE.C99Type("struct INativeObject* [DNNE.C99DeclCode("struct INativeObject;")] public static void SumAndSetData([DNNE.C99Type("struct INativeObject*")] NativeObjectInterface* obj, int* values, int numValues, int* oldValue) { + Debug.Assert(*oldValue == default); obj->VTable->sumAndSetData(obj, values, numValues, oldValue); } @@ -205,6 +206,7 @@ public static void SumAndSetData([DNNE.C99Type("struct INativeObject*")] NativeO [DNNE.C99DeclCode("struct INativeObject;")] public static void SumAndSetDataWithRef([DNNE.C99Type("struct INativeObject*")] NativeObjectInterface* obj, int** values, int numValues, int* oldValue) { + Debug.Assert(*oldValue == default); obj->VTable->sumAndSetDataWithRef(obj, values, numValues, oldValue); } diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IHide.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IHide.cs new file mode 100644 index 000000000000..9d2fc102ba5d --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IHide.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +namespace SharedTypes.ComInterfaces +{ + [GeneratedComInterface] + [Guid("023EA72A-ECAA-4B65-9D96-2122CFADE16C")] + internal partial interface IHide + { + int SameMethod(); + int DifferentMethod(); + } + + [GeneratedComInterface] + [Guid("5293B3B1-4994-425C-803E-A21A5011E077")] + internal partial interface IHide2 : IHide + { + new int SameMethod(); + int DifferentMethod2(); + } + + internal interface UnrelatedInterfaceWithSameMethod + { + int SameMethod(); + int DifferentMethod3(); + } + + [GeneratedComInterface] + [Guid("5DD35432-4987-488D-94F1-7682D7E4405C")] + internal partial interface IHide3 : IHide2, UnrelatedInterfaceWithSameMethod + { + new int SameMethod(); + new int DifferentMethod3(); + } + + [GeneratedComClass] + [Guid("2D36BD6D-C80E-4F00-86E9-8D1B4A0CB59A")] + /// + /// Implements IHides3 and returns the expected VTable index for each method. + /// + internal partial class HideBaseMethods : IHide3 + { + int IHide.SameMethod() => 3; + int IHide.DifferentMethod() => 4; + int IHide2.SameMethod() => 5; + int IHide2.DifferentMethod2() => 6; + int IHide3.SameMethod() => 7; + int IHide3.DifferentMethod3() => 8; + int UnrelatedInterfaceWithSameMethod.SameMethod() => -1; + int UnrelatedInterfaceWithSameMethod.DifferentMethod3() => -1; + } +} diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 77fe06ddc5c0..665f5d41ee98 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -49,14 +49,20 @@ public static partial class Vector128 [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 ConvertToDouble(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 ConvertToInt32(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ConvertToInt32Native(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 ConvertToInt64(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ConvertToInt64Native(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 ConvertToSingle(System.Runtime.Intrinsics.Vector128 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 ConvertToSingle(System.Runtime.Intrinsics.Vector128 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 ConvertToUInt32(System.Runtime.Intrinsics.Vector128 vector) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector128 ConvertToUInt32Native(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 ConvertToUInt64(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector128 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, T[] destination, int startIndex) { } @@ -162,6 +168,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, public static uint ExtractMostSignificantBits(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 Floor(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 Floor(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 FusedMultiplyAdd(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 addend) { throw null; } + public static System.Runtime.Intrinsics.Vector128 FusedMultiplyAdd(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 addend) { throw null; } public static T GetElement(this System.Runtime.Intrinsics.Vector128 vector, int index) { throw null; } public static System.Runtime.Intrinsics.Vector64 GetLower(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 GetUpper(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } @@ -197,6 +205,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, public static System.Runtime.Intrinsics.Vector128 Multiply(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 Multiply(System.Runtime.Intrinsics.Vector128 left, T right) { throw null; } public static System.Runtime.Intrinsics.Vector128 Multiply(T left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MultiplyAddEstimate(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 addend) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MultiplyAddEstimate(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 addend) { throw null; } public static System.Runtime.Intrinsics.Vector128 Narrow(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 Narrow(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) { throw null; } @@ -384,14 +394,20 @@ public static partial class Vector256 [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 ConvertToDouble(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 ConvertToInt32(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 ConvertToInt32Native(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 ConvertToInt64(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 ConvertToInt64Native(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 ConvertToSingle(System.Runtime.Intrinsics.Vector256 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 ConvertToSingle(System.Runtime.Intrinsics.Vector256 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 ConvertToUInt32(System.Runtime.Intrinsics.Vector256 vector) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector256 ConvertToUInt32Native(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 ConvertToUInt64(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector256 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, T[] destination, int startIndex) { } @@ -497,6 +513,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, public static uint ExtractMostSignificantBits(this System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 Floor(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 Floor(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 FusedMultiplyAdd(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right, System.Runtime.Intrinsics.Vector256 addend) { throw null; } + public static System.Runtime.Intrinsics.Vector256 FusedMultiplyAdd(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right, System.Runtime.Intrinsics.Vector256 addend) { throw null; } public static T GetElement(this System.Runtime.Intrinsics.Vector256 vector, int index) { throw null; } public static System.Runtime.Intrinsics.Vector128 GetLower(this System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 GetUpper(this System.Runtime.Intrinsics.Vector256 vector) { throw null; } @@ -532,6 +550,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, public static System.Runtime.Intrinsics.Vector256 Multiply(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } public static System.Runtime.Intrinsics.Vector256 Multiply(System.Runtime.Intrinsics.Vector256 left, T right) { throw null; } public static System.Runtime.Intrinsics.Vector256 Multiply(T left, System.Runtime.Intrinsics.Vector256 right) { throw null; } + public static System.Runtime.Intrinsics.Vector256 MultiplyAddEstimate(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right, System.Runtime.Intrinsics.Vector256 addend) { throw null; } + public static System.Runtime.Intrinsics.Vector256 MultiplyAddEstimate(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right, System.Runtime.Intrinsics.Vector256 addend) { throw null; } public static System.Runtime.Intrinsics.Vector256 Narrow(System.Runtime.Intrinsics.Vector256 lower, System.Runtime.Intrinsics.Vector256 upper) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 Narrow(System.Runtime.Intrinsics.Vector256 lower, System.Runtime.Intrinsics.Vector256 upper) { throw null; } @@ -719,14 +739,20 @@ public static partial class Vector512 [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 ConvertToDouble(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 ConvertToInt32(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 ConvertToInt32Native(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 ConvertToInt64(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 ConvertToInt64Native(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 ConvertToSingle(System.Runtime.Intrinsics.Vector512 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 ConvertToSingle(System.Runtime.Intrinsics.Vector512 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 ConvertToUInt32(System.Runtime.Intrinsics.Vector512 vector) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector512 ConvertToUInt32Native(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 ConvertToUInt64(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector512 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, T[] destination, int startIndex) { } @@ -832,6 +858,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, public static ulong ExtractMostSignificantBits(this System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 Floor(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 Floor(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 FusedMultiplyAdd(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right, System.Runtime.Intrinsics.Vector512 addend) { throw null; } + public static System.Runtime.Intrinsics.Vector512 FusedMultiplyAdd(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right, System.Runtime.Intrinsics.Vector512 addend) { throw null; } public static T GetElement(this System.Runtime.Intrinsics.Vector512 vector, int index) { throw null; } public static System.Runtime.Intrinsics.Vector256 GetLower(this System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 GetUpper(this System.Runtime.Intrinsics.Vector512 vector) { throw null; } @@ -867,6 +895,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, public static System.Runtime.Intrinsics.Vector512 Multiply(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } public static System.Runtime.Intrinsics.Vector512 Multiply(System.Runtime.Intrinsics.Vector512 left, T right) { throw null; } public static System.Runtime.Intrinsics.Vector512 Multiply(T left, System.Runtime.Intrinsics.Vector512 right) { throw null; } + public static System.Runtime.Intrinsics.Vector512 MultiplyAddEstimate(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right, System.Runtime.Intrinsics.Vector512 addend) { throw null; } + public static System.Runtime.Intrinsics.Vector512 MultiplyAddEstimate(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right, System.Runtime.Intrinsics.Vector512 addend) { throw null; } public static System.Runtime.Intrinsics.Vector512 Narrow(System.Runtime.Intrinsics.Vector512 lower, System.Runtime.Intrinsics.Vector512 upper) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 Narrow(System.Runtime.Intrinsics.Vector512 lower, System.Runtime.Intrinsics.Vector512 upper) { throw null; } @@ -1050,14 +1080,20 @@ public static partial class Vector64 [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 ConvertToDouble(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 ConvertToInt32(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ConvertToInt32Native(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 ConvertToInt64(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ConvertToInt64Native(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 ConvertToSingle(System.Runtime.Intrinsics.Vector64 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 ConvertToSingle(System.Runtime.Intrinsics.Vector64 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 ConvertToUInt32(System.Runtime.Intrinsics.Vector64 vector) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector64 ConvertToUInt32Native(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 ConvertToUInt64(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector64 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, T[] destination, int startIndex) { } @@ -1141,6 +1177,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, public static uint ExtractMostSignificantBits(this System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 Floor(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 Floor(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 FusedMultiplyAdd(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, System.Runtime.Intrinsics.Vector64 addend) { throw null; } + public static System.Runtime.Intrinsics.Vector64 FusedMultiplyAdd(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, System.Runtime.Intrinsics.Vector64 addend) { throw null; } public static T GetElement(this System.Runtime.Intrinsics.Vector64 vector, int index) { throw null; } public static bool GreaterThanAll(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static bool GreaterThanAny(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } @@ -1174,6 +1212,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, public static System.Runtime.Intrinsics.Vector64 Multiply(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Multiply(System.Runtime.Intrinsics.Vector64 left, T right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Multiply(T left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static System.Runtime.Intrinsics.Vector64 MultiplyAddEstimate(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, System.Runtime.Intrinsics.Vector64 addend) { throw null; } + public static System.Runtime.Intrinsics.Vector64 MultiplyAddEstimate(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, System.Runtime.Intrinsics.Vector64 addend) { throw null; } public static System.Runtime.Intrinsics.Vector64 Narrow(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 Narrow(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) { throw null; } @@ -2837,15 +2877,21 @@ internal AdvSimd() { } public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingLower(System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(64))] byte count) { throw null; } public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingLower(System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(32))] byte count) { throw null; } public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingLower(System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(16))] byte count) { throw null; } + [System.Obsolete("The underlying hardware instruction does not perform a signed saturate narrowing operation, and it always returns an unsigned result. Use the unsigned overload instead.", DiagnosticId = "SYSLIB0055", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(64))] byte count) { throw null; } + [System.Obsolete("The underlying hardware instruction does not perform a signed saturate narrowing operation, and it always returns an unsigned result. Use the unsigned overload instead.", DiagnosticId = "SYSLIB0055", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(32))] byte count) { throw null; } + [System.Obsolete("The underlying hardware instruction does not perform a signed saturate narrowing operation, and it always returns an unsigned result. Use the unsigned overload instead.", DiagnosticId = "SYSLIB0055", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(16))] byte count) { throw null; } public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(64))] byte count) { throw null; } public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(32))] byte count) { throw null; } public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateLower(System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(16))] byte count) { throw null; } public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(64))] byte count) { throw null; } + [System.Obsolete("The underlying hardware instruction does not perform a signed saturate narrowing operation, and it always returns an unsigned result. Use the unsigned overload instead.", DiagnosticId = "SYSLIB0055", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(32))] byte count) { throw null; } + [System.Obsolete("The underlying hardware instruction does not perform a signed saturate narrowing operation, and it always returns an unsigned result. Use the unsigned overload instead.", DiagnosticId = "SYSLIB0055", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(16))] byte count) { throw null; } + [System.Obsolete("The underlying hardware instruction does not perform a signed saturate narrowing operation, and it always returns an unsigned result. Use the unsigned overload instead.", DiagnosticId = "SYSLIB0055", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(64))] byte count) { throw null; } public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(32))] byte count) { throw null; } public static System.Runtime.Intrinsics.Vector128 ShiftRightLogicalRoundedNarrowingSaturateUpper(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector128 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(16))] byte count) { throw null; } @@ -3690,8 +3736,11 @@ internal Arm64() { } public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(32))] byte count) { throw null; } public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(16))] byte count) { throw null; } public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(8))] byte count) { throw null; } + [System.Obsolete("The underlying hardware instruction does not perform a signed saturate narrowing operation, and it always returns an unsigned result. Use the unsigned overload instead.", DiagnosticId = "SYSLIB0055", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(32))] byte count) { throw null; } + [System.Obsolete("The underlying hardware instruction does not perform a signed saturate narrowing operation, and it always returns an unsigned result. Use the unsigned overload instead.", DiagnosticId = "SYSLIB0055", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(16))] byte count) { throw null; } + [System.Obsolete("The underlying hardware instruction does not perform a signed saturate narrowing operation, and it always returns an unsigned result. Use the unsigned overload instead.", DiagnosticId = "SYSLIB0055", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(8))] byte count) { throw null; } public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(32))] byte count) { throw null; } public static System.Runtime.Intrinsics.Vector64 ShiftRightLogicalRoundedNarrowingSaturateScalar(System.Runtime.Intrinsics.Vector64 value, [System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute(Min = 1, Max = (byte)(16))] byte count) { throw null; } @@ -4138,7 +4187,115 @@ internal Sve() { } internal Arm64() { } public static new bool IsSupported { get { throw null; } } } + public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; } + + public static System.Numerics.Vector AbsoluteDifference(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AbsoluteDifference(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AbsoluteDifference(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AbsoluteDifference(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AbsoluteDifference(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AbsoluteDifference(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AbsoluteDifference(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AbsoluteDifference(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AbsoluteDifference(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AbsoluteDifference(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AddAcross(System.Numerics.Vector value) { throw null; } + + public static System.Numerics.Vector AddSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector And(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector AndAcross(System.Numerics.Vector value) { throw null; } + + public static System.Numerics.Vector BitwiseClear(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector BitwiseClear(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector BitwiseClear(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector BitwiseClear(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector BitwiseClear(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector BitwiseClear(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector BitwiseClear(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector BitwiseClear(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector BooleanNot(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector BooleanNot(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector BooleanNot(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector BooleanNot(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector BooleanNot(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector BooleanNot(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector BooleanNot(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector BooleanNot(System.Numerics.Vector value) { throw null; } + + public static ulong Count16BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } + public static ulong Count32BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } + public static ulong Count64BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } + public static ulong Count8BitElements([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector CreateFalseMaskByte() { throw null; } + public static System.Numerics.Vector CreateFalseMaskDouble() { throw null; } + public static System.Numerics.Vector CreateFalseMaskInt16() { throw null; } + public static System.Numerics.Vector CreateFalseMaskInt32() { throw null; } + public static System.Numerics.Vector CreateFalseMaskInt64() { throw null; } + public static System.Numerics.Vector CreateFalseMaskSByte() { throw null; } + public static System.Numerics.Vector CreateFalseMaskSingle() { throw null; } + public static System.Numerics.Vector CreateFalseMaskUInt16() { throw null; } + public static System.Numerics.Vector CreateFalseMaskUInt32() { throw null; } + public static System.Numerics.Vector CreateFalseMaskUInt64() { throw null; } public static System.Numerics.Vector CreateTrueMaskByte([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } public static System.Numerics.Vector CreateTrueMaskDouble([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } public static System.Numerics.Vector CreateTrueMaskInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } @@ -4149,6 +4306,64 @@ internal Arm64() { } public static System.Numerics.Vector CreateTrueMaskUInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } public static System.Numerics.Vector CreateTrueMaskUInt32([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } public static System.Numerics.Vector CreateTrueMaskUInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask16Bit(int left, int right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask16Bit(long left, long right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask16Bit(uint left, uint right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask16Bit(ulong left, ulong right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask32Bit(int left, int right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask32Bit(long left, long right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask32Bit(uint left, uint right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask32Bit(ulong left, ulong right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask64Bit(int left, int right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask64Bit(long left, long right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask64Bit(uint left, uint right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask64Bit(ulong left, ulong right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask8Bit(int left, int right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask8Bit(long left, long right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask8Bit(uint left, uint right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanMask8Bit(ulong left, ulong right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask16Bit(int left, int right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask16Bit(long left, long right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask16Bit(uint left, uint right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask16Bit(ulong left, ulong right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask32Bit(int left, int right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask32Bit(long left, long right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask32Bit(uint left, uint right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask32Bit(ulong left, ulong right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask64Bit(int left, int right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask64Bit(long left, long right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask64Bit(uint left, uint right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask64Bit(ulong left, ulong right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask8Bit(int left, int right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask8Bit(long left, long right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask8Bit(uint left, uint right) { throw null; } + public static System.Numerics.Vector CreateWhileLessThanOrEqualMask8Bit(ulong left, ulong right) { throw null; } + + public static System.Numerics.Vector Divide(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Divide(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector DotProduct(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector DotProduct(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector DotProduct(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector DotProduct(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector DotProductBySelectedScalar(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right, [ConstantExpected] byte rightIndex) { throw null; } + public static System.Numerics.Vector DotProductBySelectedScalar(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right, [ConstantExpected] byte rightIndex) { throw null; } + public static System.Numerics.Vector DotProductBySelectedScalar(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right, [ConstantExpected] byte rightIndex) { throw null; } + public static System.Numerics.Vector DotProductBySelectedScalar(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right, [ConstantExpected] byte rightIndex) { throw null; } + + public static System.Numerics.Vector FusedMultiplyAdd(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedMultiplyAdd(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedMultiplyAddBySelectedScalar(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right, [ConstantExpected] byte rightIndex) { throw null; } + public static System.Numerics.Vector FusedMultiplyAddBySelectedScalar(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right, [ConstantExpected] byte rightIndex) { throw null; } + public static System.Numerics.Vector FusedMultiplyAddNegated(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedMultiplyAddNegated(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedMultiplySubtract(System.Numerics.Vector minuend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedMultiplySubtract(System.Numerics.Vector minuend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedMultiplySubtractBySelectedScalar(System.Numerics.Vector minuend, System.Numerics.Vector left, System.Numerics.Vector right, [ConstantExpected] byte rightIndex) { throw null; } + public static System.Numerics.Vector FusedMultiplySubtractBySelectedScalar(System.Numerics.Vector minuend, System.Numerics.Vector left, System.Numerics.Vector right, [ConstantExpected] byte rightIndex) { throw null; } + public static System.Numerics.Vector FusedMultiplySubtractNegated(System.Numerics.Vector minuend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector FusedMultiplySubtractNegated(System.Numerics.Vector minuend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, sbyte* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, short* address) { throw null; } @@ -4160,7 +4375,249 @@ internal Arm64() { } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, ulong* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, float* address) { throw null; } public static unsafe System.Numerics.Vector LoadVector(System.Numerics.Vector mask, double* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToInt16(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToInt32(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToInt64(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToUInt16(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToUInt32(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorByteZeroExtendToUInt64(System.Numerics.Vector mask, byte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt16SignExtendToInt32(System.Numerics.Vector mask, short* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt16SignExtendToInt64(System.Numerics.Vector mask, short* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt16SignExtendToUInt32(System.Numerics.Vector mask, short* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt16SignExtendToUInt64(System.Numerics.Vector mask, short* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt32SignExtendToInt64(System.Numerics.Vector mask, int* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorInt32SignExtendToUInt64(System.Numerics.Vector mask, int* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToInt16(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToInt32(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToInt64(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToUInt16(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToUInt32(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorSByteSignExtendToUInt64(System.Numerics.Vector mask, sbyte* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendToInt32(System.Numerics.Vector mask, ushort* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendToInt64(System.Numerics.Vector mask, ushort* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendToUInt32(System.Numerics.Vector mask, ushort* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt16ZeroExtendToUInt64(System.Numerics.Vector mask, ushort* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToInt64(System.Numerics.Vector mask, uint* address) { throw null; } + public static unsafe System.Numerics.Vector LoadVectorUInt32ZeroExtendToUInt64(System.Numerics.Vector mask, uint* address) { throw null; } + + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Max(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxNumber(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MaxNumber(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MaxNumberAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MaxNumberAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Min(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinNumber(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MinNumber(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MinNumberAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector MinNumberAcross(System.Numerics.Vector value) { throw null; } + + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Multiply(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector MultiplyAdd(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplyAdd(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplyAdd(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplyAdd(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplyAdd(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplyAdd(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplyAdd(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplyAdd(System.Numerics.Vector addend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector MultiplyBySelectedScalar(System.Numerics.Vector left, System.Numerics.Vector right, [ConstantExpected] byte rightIndex) { throw null; } + public static System.Numerics.Vector MultiplyBySelectedScalar(System.Numerics.Vector left, System.Numerics.Vector right, [ConstantExpected] byte rightIndex) { throw null; } + + public static System.Numerics.Vector MultiplyExtended(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplyExtended(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector MultiplySubtract(System.Numerics.Vector minuend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplySubtract(System.Numerics.Vector minuend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplySubtract(System.Numerics.Vector minuend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplySubtract(System.Numerics.Vector minuend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplySubtract(System.Numerics.Vector minuend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplySubtract(System.Numerics.Vector minuend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplySubtract(System.Numerics.Vector minuend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector MultiplySubtract(System.Numerics.Vector minuend, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector Negate(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Negate(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Negate(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Negate(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Negate(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector Negate(System.Numerics.Vector value) { throw null; } + + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Or(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector OrAcross(System.Numerics.Vector value) { throw null; } + + public static System.Numerics.Vector SignExtend16(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtend16(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtend32(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtend8(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtend8(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtend8(System.Numerics.Vector value) { throw null; } + + public static System.Numerics.Vector SignExtendWideningLower(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtendWideningLower(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtendWideningLower(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtendWideningUpper(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtendWideningUpper(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector SignExtendWideningUpper(System.Numerics.Vector value) { throw null; } + + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector SubtractSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector SubtractSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector SubtractSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector SubtractSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector SubtractSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector SubtractSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector SubtractSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector SubtractSaturate(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector UnzipOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector XorAcross(System.Numerics.Vector value) { throw null; } + + public static System.Numerics.Vector ZeroExtend16(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtend16(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtend32(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtend8(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtend8(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtend8(System.Numerics.Vector value) { throw null; } + + public static System.Numerics.Vector ZeroExtendWideningLower(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtendWideningLower(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtendWideningLower(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtendWideningUpper(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtendWideningUpper(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ZeroExtendWideningUpper(System.Numerics.Vector value) { throw null; } + + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipHigh(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector ZipLow(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } } public enum SveMaskPattern : byte diff --git a/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj b/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj index f4dee9ab306c..b8fc0641259d 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj +++ b/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs index 0ebed660f336..ce4f1d8fcf3e 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs @@ -5,6 +5,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -4872,5 +4873,119 @@ public void Log2SingleTest(float value, float expectedResult, float variance) Vector128 actualResult = Vector128.Log2(Vector128.Create(value)); AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Create(variance)); } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] + public void FusedMultiplyAddDoubleTest(double left, double right, double addend) + { + Vector128 actualResult = Vector128.FusedMultiplyAdd(Vector128.Create(left), Vector128.Create(right), Vector128.Create(addend)); + AssertEqual(Vector128.Create(double.FusedMultiplyAdd(left, right, addend)), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend) + { + Vector128 actualResult = Vector128.FusedMultiplyAdd(Vector128.Create(left), Vector128.Create(right), Vector128.Create(addend)); + AssertEqual(Vector128.Create(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] + public void MultiplyAddEstimateDoubleTest(double left, double right, double addend) + { + Vector128 actualResult = Vector128.MultiplyAddEstimate(Vector128.Create(left), Vector128.Create(right), Vector128.Create(addend)); + AssertEqual(Vector128.Create(double.MultiplyAddEstimate(left, right, addend)), actualResult, Vector128.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void MultiplyAddEstimateSingleTest(float left, float right, float addend) + { + Vector128 actualResult = Vector128.MultiplyAddEstimate(Vector128.Create(left), Vector128.Create(right), Vector128.Create(addend)); + AssertEqual(Vector128.Create(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector128.Zero); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32Test() + { + Assert.Equal(Vector128.Create(float.ConvertToInteger(float.MinValue)), Vector128.ConvertToInt32(Vector128.Create(float.MinValue))); + Assert.Equal(Vector128.Create(float.ConvertToInteger(2.6f)), Vector128.ConvertToInt32(Vector128.Create(2.6f))); + Assert.Equal(Vector128.Create(float.ConvertToInteger(float.MaxValue)), Vector128.ConvertToInt32(Vector128.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32NativeTest() + { + Assert.Equal(Vector128.Create(float.ConvertToIntegerNative(float.MinValue)), Vector128.ConvertToInt32Native(Vector128.Create(float.MinValue))); + Assert.Equal(Vector128.Create(float.ConvertToIntegerNative(2.6f)), Vector128.ConvertToInt32Native(Vector128.Create(2.6f))); + Assert.Equal(Vector128.Create(float.ConvertToIntegerNative(float.MaxValue)), Vector128.ConvertToInt32Native(Vector128.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64Test() + { + Assert.Equal(Vector128.Create(double.ConvertToInteger(double.MinValue)), Vector128.ConvertToInt64(Vector128.Create(double.MinValue))); + Assert.Equal(Vector128.Create(double.ConvertToInteger(2.6)), Vector128.ConvertToInt64(Vector128.Create(2.6))); + Assert.Equal(Vector128.Create(double.ConvertToInteger(double.MaxValue)), Vector128.ConvertToInt64(Vector128.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64NativeTest() + { + Assert.Equal(Vector128.Create(double.ConvertToIntegerNative(double.MinValue)), Vector128.ConvertToInt64Native(Vector128.Create(double.MinValue))); + Assert.Equal(Vector128.Create(double.ConvertToIntegerNative(2.6)), Vector128.ConvertToInt64Native(Vector128.Create(2.6))); + + if (Environment.Is64BitProcess) + { + // This isn't accelerated on all 32-bit systems today and may fallback to ConvertToInteger behavior + Assert.Equal(Vector128.Create(double.ConvertToIntegerNative(double.MaxValue)), Vector128.ConvertToInt64Native(Vector128.Create(double.MaxValue))); + } + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32Test() + { + Assert.Equal(Vector128.Create(float.ConvertToInteger(float.MinValue)), Vector128.ConvertToUInt32(Vector128.Create(float.MinValue))); + Assert.Equal(Vector128.Create(float.ConvertToInteger(2.6f)), Vector128.ConvertToUInt32(Vector128.Create(2.6f))); + Assert.Equal(Vector128.Create(float.ConvertToInteger(float.MaxValue)), Vector128.ConvertToUInt32(Vector128.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32NativeTest() + { + Assert.Equal(Vector128.Create(float.ConvertToIntegerNative(float.MinValue)), Vector128.ConvertToUInt32Native(Vector128.Create(float.MinValue))); + Assert.Equal(Vector128.Create(float.ConvertToIntegerNative(2.6f)), Vector128.ConvertToUInt32Native(Vector128.Create(2.6f))); + Assert.Equal(Vector128.Create(float.ConvertToIntegerNative(float.MaxValue)), Vector128.ConvertToUInt32Native(Vector128.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64Test() + { + Assert.Equal(Vector128.Create(double.ConvertToInteger(double.MinValue)), Vector128.ConvertToUInt64(Vector128.Create(double.MinValue))); + Assert.Equal(Vector128.Create(double.ConvertToInteger(2.6)), Vector128.ConvertToUInt64(Vector128.Create(2.6))); + Assert.Equal(Vector128.Create(double.ConvertToInteger(double.MaxValue)), Vector128.ConvertToUInt64(Vector128.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64NativeTest() + { + if (Environment.Is64BitProcess) + { + // This isn't accelerated on all 32-bit systems today and may fallback to ConvertToInteger behavior + Assert.Equal(Vector128.Create(double.ConvertToIntegerNative(double.MinValue)), Vector128.ConvertToUInt64Native(Vector128.Create(double.MinValue))); + } + + Assert.Equal(Vector128.Create(double.ConvertToIntegerNative(2.6)), Vector128.ConvertToUInt64Native(Vector128.Create(2.6))); + Assert.Equal(Vector128.Create(double.ConvertToIntegerNative(double.MaxValue)), Vector128.ConvertToUInt64Native(Vector128.Create(double.MaxValue))); + } } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs index d658ca08b17b..d264cd477712 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs @@ -4,6 +4,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -5887,5 +5888,119 @@ public void Log2SingleTest(float value, float expectedResult, float variance) Vector256 actualResult = Vector256.Log2(Vector256.Create(value)); AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Create(variance)); } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] + public void FusedMultiplyAddDoubleTest(double left, double right, double addend) + { + Vector256 actualResult = Vector256.FusedMultiplyAdd(Vector256.Create(left), Vector256.Create(right), Vector256.Create(addend)); + AssertEqual(Vector256.Create(double.FusedMultiplyAdd(left, right, addend)), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend) + { + Vector256 actualResult = Vector256.FusedMultiplyAdd(Vector256.Create(left), Vector256.Create(right), Vector256.Create(addend)); + AssertEqual(Vector256.Create(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] + public void MultiplyAddEstimateDoubleTest(double left, double right, double addend) + { + Vector256 actualResult = Vector256.MultiplyAddEstimate(Vector256.Create(left), Vector256.Create(right), Vector256.Create(addend)); + AssertEqual(Vector256.Create(double.MultiplyAddEstimate(left, right, addend)), actualResult, Vector256.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void MultiplyAddEstimateSingleTest(float left, float right, float addend) + { + Vector256 actualResult = Vector256.MultiplyAddEstimate(Vector256.Create(left), Vector256.Create(right), Vector256.Create(addend)); + AssertEqual(Vector256.Create(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector256.Zero); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32Test() + { + Assert.Equal(Vector256.Create(float.ConvertToInteger(float.MinValue)), Vector256.ConvertToInt32(Vector256.Create(float.MinValue))); + Assert.Equal(Vector256.Create(float.ConvertToInteger(2.6f)), Vector256.ConvertToInt32(Vector256.Create(2.6f))); + Assert.Equal(Vector256.Create(float.ConvertToInteger(float.MaxValue)), Vector256.ConvertToInt32(Vector256.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32NativeTest() + { + Assert.Equal(Vector256.Create(float.ConvertToIntegerNative(float.MinValue)), Vector256.ConvertToInt32Native(Vector256.Create(float.MinValue))); + Assert.Equal(Vector256.Create(float.ConvertToIntegerNative(2.6f)), Vector256.ConvertToInt32Native(Vector256.Create(2.6f))); + Assert.Equal(Vector256.Create(float.ConvertToIntegerNative(float.MaxValue)), Vector256.ConvertToInt32Native(Vector256.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64Test() + { + Assert.Equal(Vector256.Create(double.ConvertToInteger(double.MinValue)), Vector256.ConvertToInt64(Vector256.Create(double.MinValue))); + Assert.Equal(Vector256.Create(double.ConvertToInteger(2.6)), Vector256.ConvertToInt64(Vector256.Create(2.6))); + Assert.Equal(Vector256.Create(double.ConvertToInteger(double.MaxValue)), Vector256.ConvertToInt64(Vector256.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64NativeTest() + { + Assert.Equal(Vector256.Create(double.ConvertToIntegerNative(double.MinValue)), Vector256.ConvertToInt64Native(Vector256.Create(double.MinValue))); + Assert.Equal(Vector256.Create(double.ConvertToIntegerNative(2.6)), Vector256.ConvertToInt64Native(Vector256.Create(2.6))); + + if (Environment.Is64BitProcess) + { + // This isn't accelerated on all 32-bit systems today and may fallback to ConvertToInteger behavior + Assert.Equal(Vector256.Create(double.ConvertToIntegerNative(double.MaxValue)), Vector256.ConvertToInt64Native(Vector256.Create(double.MaxValue))); + } + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32Test() + { + Assert.Equal(Vector256.Create(float.ConvertToInteger(float.MinValue)), Vector256.ConvertToUInt32(Vector256.Create(float.MinValue))); + Assert.Equal(Vector256.Create(float.ConvertToInteger(2.6f)), Vector256.ConvertToUInt32(Vector256.Create(2.6f))); + Assert.Equal(Vector256.Create(float.ConvertToInteger(float.MaxValue)), Vector256.ConvertToUInt32(Vector256.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32NativeTest() + { + Assert.Equal(Vector256.Create(float.ConvertToIntegerNative(float.MinValue)), Vector256.ConvertToUInt32Native(Vector256.Create(float.MinValue))); + Assert.Equal(Vector256.Create(float.ConvertToIntegerNative(2.6f)), Vector256.ConvertToUInt32Native(Vector256.Create(2.6f))); + Assert.Equal(Vector256.Create(float.ConvertToIntegerNative(float.MaxValue)), Vector256.ConvertToUInt32Native(Vector256.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64Test() + { + Assert.Equal(Vector256.Create(double.ConvertToInteger(double.MinValue)), Vector256.ConvertToUInt64(Vector256.Create(double.MinValue))); + Assert.Equal(Vector256.Create(double.ConvertToInteger(2.6)), Vector256.ConvertToUInt64(Vector256.Create(2.6))); + Assert.Equal(Vector256.Create(double.ConvertToInteger(double.MaxValue)), Vector256.ConvertToUInt64(Vector256.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64NativeTest() + { + if (Environment.Is64BitProcess) + { + // This isn't accelerated on all 32-bit systems today and may fallback to ConvertToInteger behavior + Assert.Equal(Vector256.Create(double.ConvertToIntegerNative(double.MinValue)), Vector256.ConvertToUInt64Native(Vector256.Create(double.MinValue))); + } + + Assert.Equal(Vector256.Create(double.ConvertToIntegerNative(2.6)), Vector256.ConvertToUInt64Native(Vector256.Create(2.6))); + Assert.Equal(Vector256.Create(double.ConvertToIntegerNative(double.MaxValue)), Vector256.ConvertToUInt64Native(Vector256.Create(double.MaxValue))); + } } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs index 4b4f9e2d4692..93ecf183070e 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs @@ -4,6 +4,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -5320,5 +5321,119 @@ public void Log2SingleTest(float value, float expectedResult, float variance) Vector512 actualResult = Vector512.Log2(Vector512.Create(value)); AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Create(variance)); } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] + public void FusedMultiplyAddDoubleTest(double left, double right, double addend) + { + Vector512 actualResult = Vector512.FusedMultiplyAdd(Vector512.Create(left), Vector512.Create(right), Vector512.Create(addend)); + AssertEqual(Vector512.Create(double.FusedMultiplyAdd(left, right, addend)), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend) + { + Vector512 actualResult = Vector512.FusedMultiplyAdd(Vector512.Create(left), Vector512.Create(right), Vector512.Create(addend)); + AssertEqual(Vector512.Create(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] + public void MultiplyAddEstimateDoubleTest(double left, double right, double addend) + { + Vector512 actualResult = Vector512.MultiplyAddEstimate(Vector512.Create(left), Vector512.Create(right), Vector512.Create(addend)); + AssertEqual(Vector512.Create(double.MultiplyAddEstimate(left, right, addend)), actualResult, Vector512.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void MultiplyAddEstimateSingleTest(float left, float right, float addend) + { + Vector512 actualResult = Vector512.MultiplyAddEstimate(Vector512.Create(left), Vector512.Create(right), Vector512.Create(addend)); + AssertEqual(Vector512.Create(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector512.Zero); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32Test() + { + Assert.Equal(Vector512.Create(float.ConvertToInteger(float.MinValue)), Vector512.ConvertToInt32(Vector512.Create(float.MinValue))); + Assert.Equal(Vector512.Create(float.ConvertToInteger(2.6f)), Vector512.ConvertToInt32(Vector512.Create(2.6f))); + Assert.Equal(Vector512.Create(float.ConvertToInteger(float.MaxValue)), Vector512.ConvertToInt32(Vector512.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32NativeTest() + { + Assert.Equal(Vector512.Create(float.ConvertToIntegerNative(float.MinValue)), Vector512.ConvertToInt32Native(Vector512.Create(float.MinValue))); + Assert.Equal(Vector512.Create(float.ConvertToIntegerNative(2.6f)), Vector512.ConvertToInt32Native(Vector512.Create(2.6f))); + Assert.Equal(Vector512.Create(float.ConvertToIntegerNative(float.MaxValue)), Vector512.ConvertToInt32Native(Vector512.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64Test() + { + Assert.Equal(Vector512.Create(double.ConvertToInteger(double.MinValue)), Vector512.ConvertToInt64(Vector512.Create(double.MinValue))); + Assert.Equal(Vector512.Create(double.ConvertToInteger(2.6)), Vector512.ConvertToInt64(Vector512.Create(2.6))); + Assert.Equal(Vector512.Create(double.ConvertToInteger(double.MaxValue)), Vector512.ConvertToInt64(Vector512.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64NativeTest() + { + Assert.Equal(Vector512.Create(double.ConvertToIntegerNative(double.MinValue)), Vector512.ConvertToInt64Native(Vector512.Create(double.MinValue))); + Assert.Equal(Vector512.Create(double.ConvertToIntegerNative(2.6)), Vector512.ConvertToInt64Native(Vector512.Create(2.6))); + + if (Environment.Is64BitProcess) + { + // This isn't accelerated on all 32-bit systems today and may fallback to ConvertToInteger behavior + Assert.Equal(Vector512.Create(double.ConvertToIntegerNative(double.MaxValue)), Vector512.ConvertToInt64Native(Vector512.Create(double.MaxValue))); + } + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32Test() + { + Assert.Equal(Vector512.Create(float.ConvertToInteger(float.MinValue)), Vector512.ConvertToUInt32(Vector512.Create(float.MinValue))); + Assert.Equal(Vector512.Create(float.ConvertToInteger(2.6f)), Vector512.ConvertToUInt32(Vector512.Create(2.6f))); + Assert.Equal(Vector512.Create(float.ConvertToInteger(float.MaxValue)), Vector512.ConvertToUInt32(Vector512.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32NativeTest() + { + Assert.Equal(Vector512.Create(float.ConvertToIntegerNative(float.MinValue)), Vector512.ConvertToUInt32Native(Vector512.Create(float.MinValue))); + Assert.Equal(Vector512.Create(float.ConvertToIntegerNative(2.6f)), Vector512.ConvertToUInt32Native(Vector512.Create(2.6f))); + Assert.Equal(Vector512.Create(float.ConvertToIntegerNative(float.MaxValue)), Vector512.ConvertToUInt32Native(Vector512.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64Test() + { + Assert.Equal(Vector512.Create(double.ConvertToInteger(double.MinValue)), Vector512.ConvertToUInt64(Vector512.Create(double.MinValue))); + Assert.Equal(Vector512.Create(double.ConvertToInteger(2.6)), Vector512.ConvertToUInt64(Vector512.Create(2.6))); + Assert.Equal(Vector512.Create(double.ConvertToInteger(double.MaxValue)), Vector512.ConvertToUInt64(Vector512.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64NativeTest() + { + if (Environment.Is64BitProcess) + { + // This isn't accelerated on all 32-bit systems today and may fallback to ConvertToInteger behavior + Assert.Equal(Vector512.Create(double.ConvertToIntegerNative(double.MinValue)), Vector512.ConvertToUInt64Native(Vector512.Create(double.MinValue))); + } + + Assert.Equal(Vector512.Create(double.ConvertToIntegerNative(2.6)), Vector512.ConvertToUInt64Native(Vector512.Create(2.6))); + Assert.Equal(Vector512.Create(double.ConvertToIntegerNative(double.MaxValue)), Vector512.ConvertToUInt64Native(Vector512.Create(double.MaxValue))); + } } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs index 69f37520ad73..c42580263a03 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs @@ -4,6 +4,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -4287,5 +4288,109 @@ public void Log2SingleTest(float value, float expectedResult, float variance) Vector64 actualResult = Vector64.Log2(Vector64.Create(value)); AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Create(variance)); } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] + public void FusedMultiplyAddDoubleTest(double left, double right, double addend) + { + Vector64 actualResult = Vector64.FusedMultiplyAdd(Vector64.Create(left), Vector64.Create(right), Vector64.Create(addend)); + AssertEqual(Vector64.Create(double.FusedMultiplyAdd(left, right, addend)), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void FusedMultiplyAddSingleTest(float left, float right, float addend) + { + Vector64 actualResult = Vector64.FusedMultiplyAdd(Vector64.Create(left), Vector64.Create(right), Vector64.Create(addend)); + AssertEqual(Vector64.Create(float.FusedMultiplyAdd(left, right, addend)), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddDouble), MemberType = typeof(VectorTestMemberData))] + public void MultiplyAddEstimateDoubleTest(double left, double right, double addend) + { + Vector64 actualResult = Vector64.MultiplyAddEstimate(Vector64.Create(left), Vector64.Create(right), Vector64.Create(addend)); + AssertEqual(Vector64.Create(double.MultiplyAddEstimate(left, right, addend)), actualResult, Vector64.Zero); + } + + [Theory] + [MemberData(nameof(VectorTestMemberData.MultiplyAddSingle), MemberType = typeof(VectorTestMemberData))] + public void MultiplyAddEstimateSingleTest(float left, float right, float addend) + { + Vector64 actualResult = Vector64.MultiplyAddEstimate(Vector64.Create(left), Vector64.Create(right), Vector64.Create(addend)); + AssertEqual(Vector64.Create(float.MultiplyAddEstimate(left, right, addend)), actualResult, Vector64.Zero); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32Test() + { + Assert.Equal(Vector64.Create(float.ConvertToInteger(float.MinValue)), Vector64.ConvertToInt32(Vector64.Create(float.MinValue))); + Assert.Equal(Vector64.Create(float.ConvertToInteger(2.6f)), Vector64.ConvertToInt32(Vector64.Create(2.6f))); + Assert.Equal(Vector64.Create(float.ConvertToInteger(float.MaxValue)), Vector64.ConvertToInt32(Vector64.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32NativeTest() + { + Assert.Equal(Vector64.Create(float.ConvertToIntegerNative(float.MinValue)), Vector64.ConvertToInt32Native(Vector64.Create(float.MinValue))); + Assert.Equal(Vector64.Create(float.ConvertToIntegerNative(2.6f)), Vector64.ConvertToInt32Native(Vector64.Create(2.6f))); + Assert.Equal(Vector64.Create(float.ConvertToIntegerNative(float.MaxValue)), Vector64.ConvertToInt32Native(Vector64.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64Test() + { + Assert.Equal(Vector64.Create(double.ConvertToInteger(double.MinValue)), Vector64.ConvertToInt64(Vector64.Create(double.MinValue))); + Assert.Equal(Vector64.Create(double.ConvertToInteger(2.6)), Vector64.ConvertToInt64(Vector64.Create(2.6))); + Assert.Equal(Vector64.Create(double.ConvertToInteger(double.MaxValue)), Vector64.ConvertToInt64(Vector64.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64NativeTest() + { + Assert.Equal(Vector64.Create(double.ConvertToIntegerNative(double.MinValue)), Vector64.ConvertToInt64Native(Vector64.Create(double.MinValue))); + Assert.Equal(Vector64.Create(double.ConvertToIntegerNative(2.6)), Vector64.ConvertToInt64Native(Vector64.Create(2.6))); + Assert.Equal(Vector64.Create(double.ConvertToIntegerNative(double.MaxValue)), Vector64.ConvertToInt64Native(Vector64.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32Test() + { + Assert.Equal(Vector64.Create(float.ConvertToInteger(float.MinValue)), Vector64.ConvertToUInt32(Vector64.Create(float.MinValue))); + Assert.Equal(Vector64.Create(float.ConvertToInteger(2.6f)), Vector64.ConvertToUInt32(Vector64.Create(2.6f))); + Assert.Equal(Vector64.Create(float.ConvertToInteger(float.MaxValue)), Vector64.ConvertToUInt32(Vector64.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32NativeTest() + { + Assert.Equal(Vector64.Create(float.ConvertToIntegerNative(float.MinValue)), Vector64.ConvertToUInt32Native(Vector64.Create(float.MinValue))); + Assert.Equal(Vector64.Create(float.ConvertToIntegerNative(2.6f)), Vector64.ConvertToUInt32Native(Vector64.Create(2.6f))); + Assert.Equal(Vector64.Create(float.ConvertToIntegerNative(float.MaxValue)), Vector64.ConvertToUInt32Native(Vector64.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64Test() + { + Assert.Equal(Vector64.Create(double.ConvertToInteger(double.MinValue)), Vector64.ConvertToUInt64(Vector64.Create(double.MinValue))); + Assert.Equal(Vector64.Create(double.ConvertToInteger(2.6)), Vector64.ConvertToUInt64(Vector64.Create(2.6))); + Assert.Equal(Vector64.Create(double.ConvertToInteger(double.MaxValue)), Vector64.ConvertToUInt64(Vector64.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64NativeTest() + { + Assert.Equal(Vector64.Create(double.ConvertToIntegerNative(double.MinValue)), Vector64.ConvertToUInt64Native(Vector64.Create(double.MinValue))); + Assert.Equal(Vector64.Create(double.ConvertToIntegerNative(2.6)), Vector64.ConvertToUInt64Native(Vector64.Create(2.6))); + Assert.Equal(Vector64.Create(double.ConvertToIntegerNative(double.MaxValue)), Vector64.ConvertToUInt64Native(Vector64.Create(double.MaxValue))); + } } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/VectorTestMemberData.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/VectorTestMemberData.cs deleted file mode 100644 index 1579fa54e6af..000000000000 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/VectorTestMemberData.cs +++ /dev/null @@ -1,296 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Generic; - -namespace System.Runtime.Intrinsics.Tests.Vectors -{ - internal static class VectorTestMemberData - { - // binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this - // is slightly too accurate when writing tests meant to run against libm implementations - // for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. - // - // The tests themselves will take CrossPlatformMachineEpsilon and adjust it according to the expected result - // so that the delta used for comparison will compare the most significant digits and ignore - // any digits that are outside the double precision range (15-17 digits). - // - // For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use - // CrossPlatformMachineEpsilon for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx - // will use CrossPlatformMachineEpsilon / 10 and expected result in the format of x.xxxxxxxxxxxxxxxx will - // use CrossPlatformMachineEpsilon * 10. - internal const double DoubleCrossPlatformMachineEpsilon = 8.8817841970012523e-16; - - // binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this - // is slightly too accurate when writing tests meant to run against libm implementations - // for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. - // - // The tests themselves will take CrossPlatformMachineEpsilon and adjust it according to the expected result - // so that the delta used for comparison will compare the most significant digits and ignore - // any digits that are outside the single precision range (6-9 digits). - // - // For example, a test with an expect result in the format of 0.xxxxxxxxx will use - // CrossPlatformMachineEpsilon for the variance, while an expected result in the format of 0.0xxxxxxxxx - // will use CrossPlatformMachineEpsilon / 10 and expected result in the format of x.xxxxxx will - // use CrossPlatformMachineEpsilon * 10. - private const float SingleCrossPlatformMachineEpsilon = 4.76837158e-07f; - - public static IEnumerable ExpDouble - { - get - { - yield return new object[] { double.NegativeInfinity, 0.0, 0.0 }; - yield return new object[] { -3.1415926535897932, 0.043213918263772250, DoubleCrossPlatformMachineEpsilon / 10 }; // value: -(pi) - yield return new object[] { -2.7182818284590452, 0.065988035845312537, DoubleCrossPlatformMachineEpsilon / 10 }; // value: -(e) - yield return new object[] { -2.3025850929940457, 0.1, DoubleCrossPlatformMachineEpsilon }; // value: -(ln(10)) - yield return new object[] { -1.5707963267948966, 0.20787957635076191, DoubleCrossPlatformMachineEpsilon }; // value: -(pi / 2) - yield return new object[] { -1.4426950408889634, 0.23629008834452270, DoubleCrossPlatformMachineEpsilon }; // value: -(log2(e)) - yield return new object[] { -1.4142135623730950, 0.24311673443421421, DoubleCrossPlatformMachineEpsilon }; // value: -(sqrt(2)) - yield return new object[] { -1.1283791670955126, 0.32355726390307110, DoubleCrossPlatformMachineEpsilon }; // value: -(2 / sqrt(pi)) - yield return new object[] { -1.0, 0.36787944117144232, DoubleCrossPlatformMachineEpsilon }; - yield return new object[] { -0.78539816339744831, 0.45593812776599624, DoubleCrossPlatformMachineEpsilon }; // value: -(pi / 4) - yield return new object[] { -0.70710678118654752, 0.49306869139523979, DoubleCrossPlatformMachineEpsilon }; // value: -(1 / sqrt(2)) - yield return new object[] { -0.69314718055994531, 0.5, 0.0 }; // value: -(ln(2)) - yield return new object[] { -0.63661977236758134, 0.52907780826773535, DoubleCrossPlatformMachineEpsilon }; // value: -(2 / pi) - yield return new object[] { -0.43429448190325183, 0.64772148514180065, DoubleCrossPlatformMachineEpsilon }; // value: -(log10(e)) - yield return new object[] { -0.31830988618379067, 0.72737734929521647, DoubleCrossPlatformMachineEpsilon }; // value: -(1 / pi) - yield return new object[] { -0.0, 1.0, 0.0 }; - yield return new object[] { double.NaN, double.NaN, 0.0 }; - yield return new object[] { 0.0, 1.0, 0.0 }; - yield return new object[] { 0.31830988618379067, 1.3748022274393586, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (1 / pi) - yield return new object[] { 0.43429448190325183, 1.5438734439711811, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (log10(e)) - yield return new object[] { 0.63661977236758134, 1.8900811645722220, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (2 / pi) - yield return new object[] { 0.69314718055994531, 2.0, 0.0 }; // value: (ln(2)) - yield return new object[] { 0.70710678118654752, 2.0281149816474725, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (1 / sqrt(2)) - yield return new object[] { 0.78539816339744831, 2.1932800507380155, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 4) - yield return new object[] { 1.0, 2.7182818284590452, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (e) - yield return new object[] { 1.1283791670955126, 3.0906430223107976, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (2 / sqrt(pi)) - yield return new object[] { 1.4142135623730950, 4.1132503787829275, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (sqrt(2)) - yield return new object[] { 1.4426950408889634, 4.2320861065570819, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (log2(e)) - yield return new object[] { 1.5707963267948966, 4.8104773809653517, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 2) - yield return new object[] { 2.3025850929940457, 10.0, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (ln(10)) - yield return new object[] { 2.7182818284590452, 15.154262241479264, DoubleCrossPlatformMachineEpsilon * 100 }; // value: (e) - yield return new object[] { 3.1415926535897932, 23.140692632779269, DoubleCrossPlatformMachineEpsilon * 100 }; // value: (pi) - yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.0 }; - } - } - - public static IEnumerable ExpSingle - { - get - { - yield return new object[] { float.NegativeInfinity, 0.0f, 0.0f }; - yield return new object[] { -3.14159265f, 0.0432139183f, SingleCrossPlatformMachineEpsilon / 10 }; // value: -(pi) - yield return new object[] { -2.71828183f, 0.0659880358f, SingleCrossPlatformMachineEpsilon / 10 }; // value: -(e) - yield return new object[] { -2.30258509f, 0.1f, SingleCrossPlatformMachineEpsilon }; // value: -(ln(10)) - yield return new object[] { -1.57079633f, 0.207879576f, SingleCrossPlatformMachineEpsilon }; // value: -(pi / 2) - yield return new object[] { -1.44269504f, 0.236290088f, SingleCrossPlatformMachineEpsilon }; // value: -(log2(e)) - yield return new object[] { -1.41421356f, 0.243116734f, SingleCrossPlatformMachineEpsilon }; // value: -(sqrt(2)) - yield return new object[] { -1.12837917f, 0.323557264f, SingleCrossPlatformMachineEpsilon }; // value: -(2 / sqrt(pi)) - yield return new object[] { -1.0f, 0.367879441f, SingleCrossPlatformMachineEpsilon }; - yield return new object[] { -0.785398163f, 0.455938128f, SingleCrossPlatformMachineEpsilon }; // value: -(pi / 4) - yield return new object[] { -0.707106781f, 0.493068691f, SingleCrossPlatformMachineEpsilon }; // value: -(1 / sqrt(2)) - yield return new object[] { -0.693147181f, 0.5f, SingleCrossPlatformMachineEpsilon }; // value: -(ln(2)) - yield return new object[] { -0.636619772f, 0.529077808f, SingleCrossPlatformMachineEpsilon }; // value: -(2 / pi) - yield return new object[] { -0.434294482f, 0.647721485f, SingleCrossPlatformMachineEpsilon }; // value: -(log10(e)) - yield return new object[] { -0.318309886f, 0.727377349f, SingleCrossPlatformMachineEpsilon }; // value: -(1 / pi) - yield return new object[] { -0.0f, 1.0f, SingleCrossPlatformMachineEpsilon * 10 }; - yield return new object[] { float.NaN, float.NaN, 0.0f }; - yield return new object[] { 0.0f, 1.0f, SingleCrossPlatformMachineEpsilon * 10 }; - yield return new object[] { 0.318309886f, 1.37480223f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (1 / pi) - yield return new object[] { 0.434294482f, 1.54387344f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (log10(e)) - yield return new object[] { 0.636619772f, 1.89008116f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (2 / pi) - yield return new object[] { 0.693147181f, 2.0f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (ln(2)) - yield return new object[] { 0.707106781f, 2.02811498f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (1 / sqrt(2)) - yield return new object[] { 0.785398163f, 2.19328005f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 4) - yield return new object[] { 1.0f, 2.71828183f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (e) - yield return new object[] { 1.12837917f, 3.09064302f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (2 / sqrt(pi)) - yield return new object[] { 1.41421356f, 4.11325038f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (sqrt(2)) - yield return new object[] { 1.44269504f, 4.23208611f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (log2(e)) - yield return new object[] { 1.57079633f, 4.81047738f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (pi / 2) - yield return new object[] { 2.30258509f, 10.0f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (ln(10)) - yield return new object[] { 2.71828183f, 15.1542622f, SingleCrossPlatformMachineEpsilon * 100 }; // value: (e) - yield return new object[] { 3.14159265f, 23.1406926f, SingleCrossPlatformMachineEpsilon * 100 }; // value: (pi) - yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.0f }; - } - } - - public static IEnumerable LogDouble - { - get - { - yield return new object[] { double.NegativeInfinity, double.NaN, 0.0 }; - yield return new object[] { -3.1415926535897932, double.NaN, 0.0 }; // value: -(pi) - yield return new object[] { -2.7182818284590452, double.NaN, 0.0 }; // value: -(e) - yield return new object[] { -1.4142135623730950, double.NaN, 0.0 }; // value: -(sqrt(2)) - yield return new object[] { -1.0, double.NaN, 0.0 }; - yield return new object[] { -0.69314718055994531, double.NaN, 0.0 }; // value: -(ln(2)) - yield return new object[] { -0.43429448190325183, double.NaN, 0.0 }; // value: -(log10(e)) - yield return new object[] { -0.0, double.NegativeInfinity, 0.0 }; - yield return new object[] { double.NaN, double.NaN, 0.0 }; - yield return new object[] { 0.0, double.NegativeInfinity, 0.0 }; - yield return new object[] { 0.043213918263772250, -3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) - yield return new object[] { 0.065988035845312537, -2.7182818284590452, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) - yield return new object[] { 0.1, -2.3025850929940457, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) - yield return new object[] { 0.20787957635076191, -1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) - yield return new object[] { 0.23629008834452270, -1.4426950408889634, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) - yield return new object[] { 0.24311673443421421, -1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) - yield return new object[] { 0.32355726390307110, -1.1283791670955126, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) - yield return new object[] { 0.36787944117144232, -1.0, 0.0f }; - yield return new object[] { 0.45593812776599624, -0.78539816339744831, DoubleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) - yield return new object[] { 0.49306869139523979, -0.70710678118654752, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) - yield return new object[] { 0.5, -0.69314718055994531, DoubleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) - yield return new object[] { 0.52907780826773535, -0.63661977236758134, DoubleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) - yield return new object[] { 0.64772148514180065, -0.43429448190325183, DoubleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) - yield return new object[] { 0.72737734929521647, -0.31830988618379067, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) - yield return new object[] { 1.0, 0.0, 0.0 }; - yield return new object[] { 1.3748022274393586, 0.31830988618379067, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / pi) - yield return new object[] { 1.5438734439711811, 0.43429448190325183, DoubleCrossPlatformMachineEpsilon }; // expected: (log10(e)) - yield return new object[] { 1.8900811645722220, 0.63661977236758134, DoubleCrossPlatformMachineEpsilon }; // expected: (2 / pi) - yield return new object[] { 2.0, 0.69314718055994531, DoubleCrossPlatformMachineEpsilon }; // expected: (ln(2)) - yield return new object[] { 2.0281149816474725, 0.70710678118654752, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) - yield return new object[] { 2.1932800507380155, 0.78539816339744831, DoubleCrossPlatformMachineEpsilon }; // expected: (pi / 4) - yield return new object[] { 2.7182818284590452, 1.0, DoubleCrossPlatformMachineEpsilon * 10 }; // value: (e) - yield return new object[] { 3.0906430223107976, 1.1283791670955126, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) - yield return new object[] { 4.1132503787829275, 1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) - yield return new object[] { 4.2320861065570819, 1.4426950408889634, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) - yield return new object[] { 4.8104773809653517, 1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) - yield return new object[] { 10.0, 2.3025850929940457, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) - yield return new object[] { 15.154262241479264, 2.7182818284590452, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (e) - yield return new object[] { 23.140692632779269, 3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) - yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.0 }; - } - } - - public static IEnumerable LogSingle - { - get - { - yield return new object[] { float.NegativeInfinity, float.NaN, 0.0f }; - yield return new object[] { -3.14159265f, float.NaN, 0.0f }; // value: -(pi) - yield return new object[] { -2.71828183f, float.NaN, 0.0f }; // value: -(e) - yield return new object[] { -1.41421356f, float.NaN, 0.0f }; // value: -(sqrt(2)) - yield return new object[] { -1.0f, float.NaN, 0.0f }; - yield return new object[] { -0.693147181f, float.NaN, 0.0f }; // value: -(ln(2)) - yield return new object[] { -0.434294482f, float.NaN, 0.0f }; // value: -(log10(e)) - yield return new object[] { -0.0f, float.NegativeInfinity, 0.0f }; - yield return new object[] { float.NaN, float.NaN, 0.0f }; - yield return new object[] { 0.0f, float.NegativeInfinity, 0.0f }; - yield return new object[] { 0.0432139183f, -3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) - yield return new object[] { 0.0659880358f, -2.71828183f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) - yield return new object[] { 0.1f, -2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) - yield return new object[] { 0.207879576f, -1.57079633f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) - yield return new object[] { 0.236290088f, -1.44269504f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) - yield return new object[] { 0.243116734f, -1.41421356f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) - yield return new object[] { 0.323557264f, -1.12837917f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) - yield return new object[] { 0.367879441f, -1.0f, 0.0f }; - yield return new object[] { 0.455938128f, -0.785398163f, SingleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) - yield return new object[] { 0.493068691f, -0.707106781f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) - yield return new object[] { 0.5f, -0.693147181f, SingleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) - yield return new object[] { 0.529077808f, -0.636619772f, SingleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) - yield return new object[] { 0.647721485f, -0.434294482f, SingleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) - yield return new object[] { 0.727377349f, -0.318309886f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) - yield return new object[] { 1.0f, 0.0f, 0.0f }; - yield return new object[] { 1.37480223f, 0.318309886f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / pi) - yield return new object[] { 1.54387344f, 0.434294482f, SingleCrossPlatformMachineEpsilon }; // expected: (log10(e)) - yield return new object[] { 1.89008116f, 0.636619772f, SingleCrossPlatformMachineEpsilon }; // expected: (2 / pi) - yield return new object[] { 2.0f, 0.693147181f, SingleCrossPlatformMachineEpsilon }; // expected: (ln(2)) - yield return new object[] { 2.02811498f, 0.707106781f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) - yield return new object[] { 2.19328005f, 0.785398163f, SingleCrossPlatformMachineEpsilon }; // expected: (pi / 4) - yield return new object[] { 2.71828183f, 1.0f, SingleCrossPlatformMachineEpsilon * 10 }; // value: (e) - yield return new object[] { 3.09064302f, 1.12837917f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) - yield return new object[] { 4.11325038f, 1.41421356f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) - yield return new object[] { 4.23208611f, 1.44269504f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) - yield return new object[] { 4.81047738f, 1.57079633f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) - yield return new object[] { 10.0f, 2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) - yield return new object[] { 15.1542622f, 2.71828183f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (e) - yield return new object[] { 23.1406926f, 3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) - yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.0f }; - } - } - - public static IEnumerable Log2Double - { - get - { - yield return new object[] { double.NegativeInfinity, double.NaN, 0.0 }; - yield return new object[] {-0.11331473229676087, double.NaN, 0.0 }; - yield return new object[] {-0.0, double.NegativeInfinity, 0.0 }; - yield return new object[] { double.NaN, double.NaN, 0.0 }; - yield return new object[] { 0.0, double.NegativeInfinity, 0.0 }; - yield return new object[] { 0.11331473229676087, -3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) - yield return new object[] { 0.15195522325791297, -2.7182818284590453, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) - yield return new object[] { 0.20269956628651730, -2.3025850929940460, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) - yield return new object[] { 0.33662253682241906, -1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) - yield return new object[] { 0.36787944117144232, -1.4426950408889634, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) - yield return new object[] { 0.37521422724648177, -1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) - yield return new object[] { 0.45742934732229695, -1.1283791670955126, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) - yield return new object[] { 0.5, -1.0, 0.0f }; - yield return new object[] { 0.58019181037172444, -0.78539816339744840, DoubleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) - yield return new object[] { 0.61254732653606592, -0.70710678118654750, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) - yield return new object[] { 0.61850313780157598, -0.69314718055994537, DoubleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) - yield return new object[] { 0.64321824193300488, -0.63661977236758126, DoubleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) - yield return new object[] { 0.74005557395545179, -0.43429448190325190, DoubleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) - yield return new object[] { 0.80200887896145195, -0.31830988618379073, DoubleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) - yield return new object[] { 1, 0.0, 0.0 }; - yield return new object[] { 1.2468689889006383, 0.31830988618379073, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / pi) - yield return new object[] { 1.3512498725672678, 0.43429448190325226, DoubleCrossPlatformMachineEpsilon }; // expected: (log10(e)) - yield return new object[] { 1.5546822754821001, 0.63661977236758126, DoubleCrossPlatformMachineEpsilon }; // expected: (2 / pi) - yield return new object[] { 1.6168066722416747, 0.69314718055994537, DoubleCrossPlatformMachineEpsilon }; // expected: (ln(2)) - yield return new object[] { 1.6325269194381528, 0.70710678118654750, DoubleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) - yield return new object[] { 1.7235679341273495, 0.78539816339744830, DoubleCrossPlatformMachineEpsilon }; // expected: (pi / 4) - yield return new object[] { 2, 1.0, 0.0 }; // value: (e) - yield return new object[] { 2.1861299583286618, 1.1283791670955128, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) - yield return new object[] { 2.6651441426902252, 1.4142135623730950, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) - yield return new object[] { 2.7182818284590452, 1.4426950408889632, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) - yield return new object[] { 2.9706864235520193, 1.5707963267948966, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) - yield return new object[] { 4.9334096679145963, 2.3025850929940460, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) - yield return new object[] { 6.5808859910179210, 2.7182818284590455, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (e) - yield return new object[] { 8.8249778270762876, 3.1415926535897932, DoubleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) - yield return new object[] { double.PositiveInfinity, double.PositiveInfinity, 0.0 }; - } - } - - public static IEnumerable Log2Single - { - get - { - yield return new object[] { float.NegativeInfinity, float.NaN, 0.0f }; - yield return new object[] { -0.113314732f, float.NaN, 0.0f }; - yield return new object[] { -0.0f, float.NegativeInfinity, 0.0f }; - yield return new object[] { float.NaN, float.NaN, 0.0f }; - yield return new object[] { 0.0f, float.NegativeInfinity, 0.0f }; - yield return new object[] { 0.113314732f, -3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi) - yield return new object[] { 0.151955223f, -2.71828200f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(e) - yield return new object[] { 0.202699566f, -2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(ln(10)) - yield return new object[] { 0.336622537f, -1.57079630f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(pi / 2) - yield return new object[] { 0.367879441f, -1.44269500f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(log2(e)) - yield return new object[] { 0.375214227f, -1.41421360f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(sqrt(2)) - yield return new object[] { 0.457429347f, -1.12837910f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: -(2 / sqrt(pi)) - yield return new object[] { 0.5f, -1.0f, 0.0f }; - yield return new object[] { 0.580191810f, -0.785398211f, SingleCrossPlatformMachineEpsilon }; // expected: -(pi / 4) - yield return new object[] { 0.612547327f, -0.707106700f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / sqrt(2)) - yield return new object[] { 0.618503138f, -0.693147144f, SingleCrossPlatformMachineEpsilon }; // expected: -(ln(2)) - yield return new object[] { 0.643218242f, -0.636619823f, SingleCrossPlatformMachineEpsilon }; // expected: -(2 / pi) - yield return new object[] { 0.740055574f, -0.434294550f, SingleCrossPlatformMachineEpsilon }; // expected: -(log10(e)) - yield return new object[] { 0.802008879f, -0.318309900f, SingleCrossPlatformMachineEpsilon }; // expected: -(1 / pi) - yield return new object[] { 1, 0.0f, 0.0f }; - yield return new object[] { 1.24686899f, 0.318309870f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / pi) - yield return new object[] { 1.35124987f, 0.434294340f, SingleCrossPlatformMachineEpsilon }; // expected: (log10(e)) - yield return new object[] { 1.55468228f, 0.636619823f, SingleCrossPlatformMachineEpsilon }; // expected: (2 / pi) - yield return new object[] { 1.61680667f, 0.693147144f, SingleCrossPlatformMachineEpsilon }; // expected: (ln(2)) - yield return new object[] { 1.63252692f, 0.707106700f, SingleCrossPlatformMachineEpsilon }; // expected: (1 / sqrt(2)) - yield return new object[] { 1.72356793f, 0.785398211f, SingleCrossPlatformMachineEpsilon }; // expected: (pi / 4) - yield return new object[] { 2, 1.0f, 0.0f }; // value: (e) - yield return new object[] { 2.18612996f, 1.12837920f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (2 / sqrt(pi)) - yield return new object[] { 2.66514414f, 1.41421360f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (sqrt(2)) - yield return new object[] { 2.71828183f, 1.44269490f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (log2(e)) - yield return new object[] { 2.97068642f, 1.57079630f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi / 2) - yield return new object[] { 4.93340967f, 2.30258509f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (ln(10)) - yield return new object[] { 6.58088599f, 2.71828170f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (e) - yield return new object[] { 8.82497783f, 3.14159265f, SingleCrossPlatformMachineEpsilon * 10 }; // expected: (pi) - yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 0.0f }; - } - } - } -} diff --git a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj index 1874724006ee..504be89a6d4a 100644 --- a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj +++ b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj @@ -70,7 +70,8 @@ - + + @@ -87,7 +88,7 @@ copy - + diff --git a/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs b/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs index eb870ed17e3d..5ac9e6237bea 100644 --- a/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs +++ b/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs @@ -215,6 +215,7 @@ namespace System.Numerics static bool System.Numerics.INumberBase.IsZero(System.Numerics.BigInteger value) { throw null; } static System.Numerics.BigInteger System.Numerics.INumberBase.MaxMagnitudeNumber(System.Numerics.BigInteger x, System.Numerics.BigInteger y) { throw null; } static System.Numerics.BigInteger System.Numerics.INumberBase.MinMagnitudeNumber(System.Numerics.BigInteger x, System.Numerics.BigInteger y) { throw null; } + static System.Numerics.BigInteger System.Numerics.INumberBase.MultiplyAddEstimate(System.Numerics.BigInteger left, System.Numerics.BigInteger right, System.Numerics.BigInteger addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Numerics.BigInteger result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Numerics.BigInteger result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Numerics.BigInteger result) { throw null; } @@ -364,6 +365,7 @@ namespace System.Numerics static bool System.Numerics.INumberBase.IsZero(System.Numerics.Complex value) { throw null; } static System.Numerics.Complex System.Numerics.INumberBase.MaxMagnitudeNumber(System.Numerics.Complex x, System.Numerics.Complex y) { throw null; } static System.Numerics.Complex System.Numerics.INumberBase.MinMagnitudeNumber(System.Numerics.Complex x, System.Numerics.Complex y) { throw null; } + static System.Numerics.Complex System.Numerics.INumberBase.MultiplyAddEstimate(System.Numerics.Complex left, System.Numerics.Complex right, System.Numerics.Complex addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Numerics.Complex result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Numerics.Complex result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Numerics.Complex result) { throw null; } diff --git a/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj b/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj index d2003757c60f..6526656921c3 100644 --- a/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj +++ b/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj @@ -25,6 +25,8 @@ + fo return spanSuccess; } + private const uint kuBase = 1_000_000_000; // 10^9 + private const int kcchBase = 9; + private static unsafe string? FormatBigInteger( bool targetSpan, BigInteger value, string? formatString, ReadOnlySpan formatSpan, @@ -882,6 +886,7 @@ internal static bool TryFormatBigInteger(BigInteger value, ReadOnlySpan fo } else { + Debug.Assert(formatString != null); charsWritten = 0; spanSuccess = false; return value._sign.ToString(formatString, info); @@ -889,17 +894,17 @@ internal static bool TryFormatBigInteger(BigInteger value, ReadOnlySpan fo } // First convert to base 10^9. - const uint kuBase = 1000000000; // 10^9 - const int kcchBase = 9; - int cuSrc = value._bits.Length; - int cuMax; - try - { - cuMax = checked(cuSrc * 10 / 9 + 2); - } - catch (OverflowException e) { throw new FormatException(SR.Format_TooLarge, e); } - uint[] rguDst = new uint[cuMax]; + // A quick conservative max length of base 10^9 representation + // A uint contributes to no more than 10/9 of 10^9 block, +1 for ceiling of division + int cuMax = cuSrc * (kcchBase + 1) / kcchBase + 1; + Debug.Assert((long)BigInteger.MaxLength * (kcchBase + 1) / kcchBase + 1 < (long)int.MaxValue); // won't overflow + + uint[]? bufferToReturn = null; + Span base1E9Buffer = cuMax < BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[cuMax] : + (bufferToReturn = ArrayPool.Shared.Rent(cuMax)); + int cuDst = 0; for (int iuSrc = cuSrc; --iuSrc >= 0;) @@ -907,93 +912,86 @@ internal static bool TryFormatBigInteger(BigInteger value, ReadOnlySpan fo uint uCarry = value._bits[iuSrc]; for (int iuDst = 0; iuDst < cuDst; iuDst++) { - Debug.Assert(rguDst[iuDst] < kuBase); - ulong uuRes = NumericsHelpers.MakeUInt64(rguDst[iuDst], uCarry); - rguDst[iuDst] = (uint)(uuRes % kuBase); - uCarry = (uint)(uuRes / kuBase); + Debug.Assert(base1E9Buffer[iuDst] < kuBase); + + // Use X86Base.DivRem when stable + ulong uuRes = NumericsHelpers.MakeUInt64(base1E9Buffer[iuDst], uCarry); + (ulong quo, ulong rem) = Math.DivRem(uuRes, kuBase); + uCarry = (uint)quo; + base1E9Buffer[iuDst] = (uint)rem; } if (uCarry != 0) { - rguDst[cuDst++] = uCarry % kuBase; - uCarry /= kuBase; + (uCarry, base1E9Buffer[cuDst++]) = Math.DivRem(uCarry, kuBase); if (uCarry != 0) - rguDst[cuDst++] = uCarry; + base1E9Buffer[cuDst++] = uCarry; } } - int cchMax; - try - { - // Each uint contributes at most 9 digits to the decimal representation. - cchMax = checked(cuDst * kcchBase); - } - catch (OverflowException e) { throw new FormatException(SR.Format_TooLarge, e); } + ReadOnlySpan base1E9Value = base1E9Buffer[..cuDst]; + + int valueDigits = (base1E9Value.Length - 1) * kcchBase + FormattingHelpers.CountDigits(base1E9Value[^1]); + + string? strResult; - bool decimalFmt = (fmt == 'g' || fmt == 'G' || fmt == 'd' || fmt == 'D' || fmt == 'r' || fmt == 'R'); - if (decimalFmt) + if (fmt == 'g' || fmt == 'G' || fmt == 'd' || fmt == 'D' || fmt == 'r' || fmt == 'R') { - if (digits > 0 && digits > cchMax) - cchMax = digits; - if (value._sign < 0) + int strDigits = Math.Max(digits, valueDigits); + string? sNegative = value.Sign < 0 ? info.NegativeSign : null; + int strLength = strDigits + (sNegative?.Length ?? 0); + + if (targetSpan) { - try + if (destination.Length < strLength) + { + spanSuccess = false; + charsWritten = 0; + } + else { - // Leave an extra slot for a minus sign. - cchMax = checked(cchMax + info.NegativeSign.Length); + sNegative?.CopyTo(destination); + fixed (char* ptr = &MemoryMarshal.GetReference(destination)) + { + BigIntegerToDecChars((Utf16Char*)ptr + strLength, base1E9Value, digits); + } + charsWritten = strLength; + spanSuccess = true; } - catch (OverflowException e) { throw new FormatException(SR.Format_TooLarge, e); } + strResult = null; } - } - - int rgchBufSize; - - try - { - // We'll pass the rgch buffer to native code, which is going to treat it like a string of digits, so it needs - // to be null terminated. Let's ensure that we can allocate a buffer of that size. - rgchBufSize = checked(cchMax + 1); - } - catch (OverflowException e) { throw new FormatException(SR.Format_TooLarge, e); } - - char[] rgch = new char[rgchBufSize]; - - int ichDst = cchMax; - - for (int iuDst = 0; iuDst < cuDst - 1; iuDst++) - { - uint uDig = rguDst[iuDst]; - Debug.Assert(uDig < kuBase); - for (int cch = kcchBase; --cch >= 0;) + else { - rgch[--ichDst] = (char)('0' + uDig % 10); - uDig /= 10; + spanSuccess = false; + charsWritten = 0; + fixed (uint* ptr = base1E9Value) + { + strResult = string.Create(strLength, (digits, ptr: (IntPtr)ptr, base1E9Value.Length, sNegative), static (span, state) => + { + state.sNegative?.CopyTo(span); + fixed (char* ptr = &MemoryMarshal.GetReference(span)) + { + BigIntegerToDecChars((Utf16Char*)ptr + span.Length, new ReadOnlySpan((void*)state.ptr, state.Length), state.digits); + } + }); + } } } - for (uint uDig = rguDst[cuDst - 1]; uDig != 0;) - { - rgch[--ichDst] = (char)('0' + uDig % 10); - uDig /= 10; - } - - if (!decimalFmt) + else { - // sign = true for negative and false for 0 and positive values - bool sign = (value._sign < 0); - int scale = cchMax - ichDst; - - byte[]? buffer = ArrayPool.Shared.Rent(rgchBufSize + 1); - fixed (byte* ptr = buffer) // NumberBuffer expects pinned Digits + byte[]? numberBufferToReturn = null; + Span numberBuffer = valueDigits + 1 <= CharStackBufferSize ? + stackalloc byte[valueDigits + 1] : + (numberBufferToReturn = ArrayPool.Shared.Rent(valueDigits + 1)); + fixed (byte* ptr = numberBuffer) // NumberBuffer expects pinned Digits { - scoped NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, buffer); + scoped NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, ptr, valueDigits + 1); + BigIntegerToDecChars((Utf8Char*)ptr + valueDigits, base1E9Value, valueDigits); + number.Digits[^1] = 0; + number.DigitsCount = valueDigits; + number.Scale = valueDigits; + number.IsNegative = value.Sign < 0; - for (int i = 0; i < rgch.Length - ichDst; i++) - number.Digits[i] = (byte)rgch[ichDst + i]; - number.Digits[rgch.Length - ichDst] = 0; - number.DigitsCount = rgch.Length - ichDst - 1; // The cut-off point to switch (G)eneral from (F)ixed-point to (E)xponential form - number.Scale = scale; - number.IsNegative = sign; - - scoped var vlb = new ValueListBuilder(stackalloc Utf16Char[128]); // arbitrary stack cut-off + scoped var vlb = new ValueListBuilder(stackalloc Utf16Char[CharStackBufferSize]); // arbitrary stack cut-off if (fmt != 0) { @@ -1007,59 +1005,44 @@ internal static bool TryFormatBigInteger(BigInteger value, ReadOnlySpan fo if (targetSpan) { spanSuccess = vlb.TryCopyTo(MemoryMarshal.Cast(destination), out charsWritten); - vlb.Dispose(); - return null; + strResult = null; } else { charsWritten = 0; spanSuccess = false; - string result = MemoryMarshal.Cast(vlb.AsSpan()).ToString(); - vlb.Dispose(); - return result; + strResult = MemoryMarshal.Cast(vlb.AsSpan()).ToString(); + } + + vlb.Dispose(); + if (numberBufferToReturn != null) + { + ArrayPool.Shared.Return(numberBufferToReturn); } } } - // Format Round-trip decimal - // This format is supported for integral types only. The number is converted to a string of - // decimal digits (0-9), prefixed by a minus sign if the number is negative. The precision - // specifier indicates the minimum number of digits desired in the resulting string. If required, - // the number is padded with zeros to its left to produce the number of digits given by the - // precision specifier. - int numDigitsPrinted = cchMax - ichDst; - while (digits > 0 && digits > numDigitsPrinted) - { - // pad leading zeros - rgch[--ichDst] = '0'; - digits--; - } - if (value._sign < 0) + if (bufferToReturn != null) { - string negativeSign = info.NegativeSign; - for (int i = negativeSign.Length - 1; i > -1; i--) - rgch[--ichDst] = negativeSign[i]; + ArrayPool.Shared.Return(bufferToReturn); } - int resultLength = cchMax - ichDst; - if (!targetSpan) - { - charsWritten = 0; - spanSuccess = false; - return new string(rgch, ichDst, cchMax - ichDst); - } - else if (new ReadOnlySpan(rgch, ichDst, cchMax - ichDst).TryCopyTo(destination)) - { - charsWritten = resultLength; - spanSuccess = true; - return null; - } - else + return strResult; + } + + private static unsafe TChar* BigIntegerToDecChars(TChar* bufferEnd, ReadOnlySpan base1E9Value, int digits) + where TChar : unmanaged, IUtfChar + { + Debug.Assert(base1E9Value[^1] != 0, "Leading zeros should be trimmed by caller."); + + // The base 10^9 value is in reverse order + for (int i = 0; i < base1E9Value.Length - 1; i++) { - charsWritten = 0; - spanSuccess = false; - return null; + bufferEnd = UInt32ToDecChars(bufferEnd, base1E9Value[i], kcchBase); + digits -= kcchBase; } + + return UInt32ToDecChars(bufferEnd, base1E9Value[^1], digits); } } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Number.Polyfill.cs b/src/libraries/System.Runtime.Numerics/src/System/Number.Polyfill.cs index d5de46b5842e..9c1c2a89daf5 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Number.Polyfill.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Number.Polyfill.cs @@ -43,6 +43,21 @@ internal readonly struct Utf16Char(char ch) : IUtfChar public bool Equals(Utf16Char other) => value == other.value; } +#pragma warning disable CA1067 // Polyfill only type + internal readonly struct Utf8Char(byte ch) : IUtfChar +#pragma warning restore CA1067 + { + private readonly byte value = ch; + + public static Utf8Char CastFrom(byte value) => new(value); + public static Utf8Char CastFrom(char value) => new((byte)value); + public static Utf8Char CastFrom(int value) => new((byte)value); + public static Utf8Char CastFrom(uint value) => new((byte)value); + public static Utf8Char CastFrom(ulong value) => new((byte)value); + public static uint CastToUInt32(Utf8Char value) => value.value; + public bool Equals(Utf8Char other) => value == other.value; + } + internal static partial class Number { internal static bool AllowHyphenDuringParsing(this NumberFormatInfo info) diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs index 62fc443b8d4b..2ca6c7a1bf5a 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs @@ -4138,6 +4138,9 @@ public static BigInteger MinMagnitude(BigInteger x, BigInteger y) /// static BigInteger INumberBase.MinMagnitudeNumber(BigInteger x, BigInteger y) => MinMagnitude(x, y); + /// + static BigInteger INumberBase.MultiplyAddEstimate(BigInteger left, BigInteger right, BigInteger addend) => (left * right) + addend; + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out BigInteger result) => TryConvertFromChecked(value, out result); diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.SquMul.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.SquMul.cs index a31153ceec83..54d0bc9f69f6 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.SquMul.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.SquMul.cs @@ -155,29 +155,13 @@ internal static #else internal const #endif - int MultiplyThreshold = 32; - + int MultiplyKaratsubaThreshold = 32; public static void Multiply(ReadOnlySpan left, ReadOnlySpan right, Span bits) { Debug.Assert(left.Length >= right.Length); Debug.Assert(bits.Length >= left.Length + right.Length); - Debug.Assert(!bits.ContainsAnyExcept(0u)); - - if (left.Length - right.Length < 3) - { - MultiplyNearLength(left, right, bits); - } - else - { - MultiplyFarLength(left, right, bits); - } - } - - private static void MultiplyFarLength(ReadOnlySpan left, ReadOnlySpan right, Span bits) - { - Debug.Assert(left.Length - right.Length >= 3); - Debug.Assert(bits.Length >= left.Length + right.Length); - Debug.Assert(!bits.ContainsAnyExcept(0u)); + Debug.Assert(bits.Trim(0u).IsEmpty); + Debug.Assert(MultiplyKaratsubaThreshold >= 2); // Executes different algorithms for computing z = a * b // based on the actual length of b. If b is "small" enough @@ -188,120 +172,91 @@ private static void MultiplyFarLength(ReadOnlySpan left, ReadOnlySpan> 32; - } - Unsafe.Add(ref resultPtr, i + left.Length) = (uint)carry; - } - } - else - { - // Based on the Toom-Cook multiplication we split left/right - // into two smaller values, doing recursive multiplication. - // The special form of this multiplication, where we - // split both operands into two operands, is also known - // as the Karatsuba algorithm... + // Result + // z0= | | | a0 * b0 | + // z1= | | a1 * b0 + a0 * b1 | | + // z2= | a1 * b1 | | | - // https://en.wikipedia.org/wiki/Toom-Cook_multiplication - // https://en.wikipedia.org/wiki/Karatsuba_algorithm + // z1 = a1 * b0 + a0 * b1 + // = (a0 + a1) * (b0 + b1) - a0 * b0 - a1 * b1 + // = (a0 + a1) * (b0 + b1) - z0 - z2 - // Say we want to compute z = a * b ... - // ... we need to determine our new length (just the half) - int n = left.Length >> 1; - if (right.Length <= n + 1) - { - // ... split left like a = (a_1 << n) + a_0 - ReadOnlySpan leftLow = left.Slice(0, n); - ReadOnlySpan leftHigh = left.Slice(n); + // Based on the Toom-Cook multiplication we split left/right + // into two smaller values, doing recursive multiplication. + // The special form of this multiplication, where we + // split both operands into two operands, is also known + // as the Karatsuba algorithm... - // ... split right like b = (b_1 << n) + b_0 - ReadOnlySpan rightLow; - uint rightHigh; - if (n < right.Length) - { - Debug.Assert(right.Length == n + 1); - rightLow = right.Slice(0, n); - rightHigh = right[n]; - } - else - { - rightLow = right; - rightHigh = 0; - } + // https://en.wikipedia.org/wiki/Toom-Cook_multiplication + // https://en.wikipedia.org/wiki/Karatsuba_algorithm - // ... prepare our result array (to reuse its memory) - Span bitsLow = bits.Slice(0, n + rightLow.Length); - Span bitsHigh = bits.Slice(n); + // Say we want to compute z = a * b ... - int carryLength = rightLow.Length; - uint[]? carryFromPool = null; - Span carry = ((uint)carryLength <= StackAllocThreshold ? - stackalloc uint[StackAllocThreshold] - : carryFromPool = ArrayPool.Shared.Rent(carryLength)).Slice(0, carryLength); + // ... we need to determine our new length (just the half) + int n = (left.Length + 1) >> 1; - // ... compute low - Multiply(leftLow, rightLow, bitsLow); - Span carryOrig = bits.Slice(n, rightLow.Length); - carryOrig.CopyTo(carry); - carryOrig.Clear(); + if (right.Length <= n) + { + // ... split left like a = (a_1 << n) + a_0 + ReadOnlySpan leftLow = left.Slice(0, n); + ReadOnlySpan leftHigh = left.Slice(n); + Debug.Assert(leftLow.Length >= leftHigh.Length); - if (rightHigh != 0) - { - // ... compute high - MultiplyNearLength(leftHigh, rightLow, bitsHigh.Slice(0, leftHigh.Length + n)); + // ... prepare our result array (to reuse its memory) + Span bitsLow = bits.Slice(0, n + right.Length); + Span bitsHigh = bits.Slice(n); - int upperRightLength = left.Length + 1; - uint[]? upperRightFromPool = null; - Span upperRight = ((uint)upperRightLength <= StackAllocThreshold ? - stackalloc uint[StackAllocThreshold] - : upperRightFromPool = ArrayPool.Shared.Rent(upperRightLength)).Slice(0, upperRightLength); - upperRight.Clear(); + // ... compute low + Multiply(leftLow, right, bitsLow); - Multiply(left, rightHigh, upperRight); + int carryLength = right.Length; + uint[]? carryFromPool = null; + Span carry = ((uint)carryLength <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : carryFromPool = ArrayPool.Shared.Rent(carryLength)).Slice(0, carryLength); - AddSelf(bitsHigh, upperRight); + Span carryOrig = bits.Slice(n, right.Length); + carryOrig.CopyTo(carry); + carryOrig.Clear(); - if (upperRightFromPool != null) - ArrayPool.Shared.Return(upperRightFromPool); - } - else - { - // ... compute high - Multiply(leftHigh, rightLow, bitsHigh); - } + // ... compute high + if (leftHigh.Length < right.Length) + MultiplyKaratsuba(right, leftHigh, bitsHigh.Slice(0, leftHigh.Length + right.Length), (right.Length + 1) >> 1); + else + Multiply(leftHigh, right, bitsHigh.Slice(0, leftHigh.Length + right.Length)); + + AddSelf(bitsHigh, carry); - AddSelf(bitsHigh, carry); + if (carryFromPool != null) + ArrayPool.Shared.Return(carryFromPool); + } + else + MultiplyKaratsuba(left, right, bits, n); - if (carryFromPool != null) - ArrayPool.Shared.Return(carryFromPool); + static void MultiplyKaratsuba(ReadOnlySpan left, ReadOnlySpan right, Span bits, int n) + { + Debug.Assert(left.Length >= right.Length); + Debug.Assert(2 * n - left.Length is 0 or 1); + Debug.Assert(right.Length > n); + Debug.Assert(bits.Length >= left.Length + right.Length); + + if (right.Length < MultiplyKaratsubaThreshold) + { + Naive(left, right, bits); } else { - int n2 = n << 1; - - Debug.Assert(left.Length > right.Length); - // ... split left like a = (a_1 << n) + a_0 ReadOnlySpan leftLow = left.Slice(0, n); ReadOnlySpan leftHigh = left.Slice(n); @@ -311,47 +266,47 @@ stackalloc uint[StackAllocThreshold] ReadOnlySpan rightHigh = right.Slice(n); // ... prepare our result array (to reuse its memory) - Span bitsLow = bits.Slice(0, n2); - Span bitsHigh = bits.Slice(n2); + Span bitsLow = bits.Slice(0, n + n); + Span bitsHigh = bits.Slice(n + n); + + Debug.Assert(leftLow.Length >= leftHigh.Length); + Debug.Assert(rightLow.Length >= rightHigh.Length); + Debug.Assert(bitsLow.Length >= bitsHigh.Length); // ... compute z_0 = a_0 * b_0 (multiply again) - MultiplyNearLength(rightLow, leftLow, bitsLow); + MultiplyKaratsuba(leftLow, rightLow, bitsLow, (leftLow.Length + 1) >> 1); // ... compute z_2 = a_1 * b_1 (multiply again) - MultiplyFarLength(leftHigh, rightHigh, bitsHigh); + Multiply(leftHigh, rightHigh, bitsHigh); - int leftFoldLength = leftHigh.Length + 1; + int foldLength = n + 1; uint[]? leftFoldFromPool = null; - Span leftFold = ((uint)leftFoldLength <= StackAllocThreshold ? + Span leftFold = ((uint)foldLength <= StackAllocThreshold ? stackalloc uint[StackAllocThreshold] - : leftFoldFromPool = ArrayPool.Shared.Rent(leftFoldLength)).Slice(0, leftFoldLength); + : leftFoldFromPool = ArrayPool.Shared.Rent(foldLength)).Slice(0, foldLength); leftFold.Clear(); - int rightFoldLength = n + 1; uint[]? rightFoldFromPool = null; - Span rightFold = ((uint)rightFoldLength <= StackAllocThreshold ? + Span rightFold = ((uint)foldLength <= StackAllocThreshold ? stackalloc uint[StackAllocThreshold] - : rightFoldFromPool = ArrayPool.Shared.Rent(rightFoldLength)).Slice(0, rightFoldLength); + : rightFoldFromPool = ArrayPool.Shared.Rent(foldLength)).Slice(0, foldLength); rightFold.Clear(); - int coreLength = leftFoldLength + rightFoldLength; + // ... compute z_a = a_1 + a_0 (call it fold...) + Add(leftLow, leftHigh, leftFold); + + // ... compute z_b = b_1 + b_0 (call it fold...) + Add(rightLow, rightHigh, rightFold); + + int coreLength = foldLength + foldLength; uint[]? coreFromPool = null; Span core = ((uint)coreLength <= StackAllocThreshold ? stackalloc uint[StackAllocThreshold] : coreFromPool = ArrayPool.Shared.Rent(coreLength)).Slice(0, coreLength); core.Clear(); - Debug.Assert(bits.Length - n >= core.Length); - Debug.Assert(rightLow.Length >= rightHigh.Length); - - // ... compute z_a = a_1 + a_0 (call it fold...) - Add(leftHigh, leftLow, leftFold); - - // ... compute z_b = b_1 + b_0 (call it fold...) - Add(rightLow, rightHigh, rightFold); - - // ... compute z_1 = z_a * z_b - z_0 - z_2 - MultiplyNearLength(leftFold, rightFold, core); + // ... compute z_ab = z_a * z_b + MultiplyKaratsuba(leftFold, rightFold, core, (leftFold.Length + 1) >> 1); if (leftFoldFromPool != null) ArrayPool.Shared.Return(leftFoldFromPool); @@ -359,33 +314,24 @@ stackalloc uint[StackAllocThreshold] if (rightFoldFromPool != null) ArrayPool.Shared.Return(rightFoldFromPool); + // ... compute z_1 = z_a * z_b - z_0 - z_2 = a_0 * b_1 + a_1 * b_0 SubtractCore(bitsLow, bitsHigh, core); + Debug.Assert(ActualLength(core) <= left.Length + 1); + // ... and finally merge the result! :-) - AddSelf(bits.Slice(n), core); + AddSelf(bits.Slice(n), core.Slice(0, ActualLength(core))); if (coreFromPool != null) ArrayPool.Shared.Return(coreFromPool); } } - } - private static void MultiplyNearLength(ReadOnlySpan left, ReadOnlySpan right, Span bits) - { - Debug.Assert(left.Length - right.Length < 3); - Debug.Assert(bits.Length >= left.Length + right.Length); - Debug.Assert(!bits.ContainsAnyExcept(0u)); - // Executes different algorithms for computing z = a * b - // based on the actual length of b. If b is "small" enough - // we stick to the classic "grammar-school" method; for the - // rest we switch to implementations with less complexity - // albeit more overhead (which needs to pay off!). - - // NOTE: useful thresholds needs some "empirical" testing, - // which are smaller in DEBUG mode for testing purpose. - - if (right.Length < MultiplyThreshold) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static void Naive(ReadOnlySpan left, ReadOnlySpan right, Span bits) { + Debug.Assert(right.Length < MultiplyKaratsubaThreshold); + // Switching to managed references helps eliminating // index bounds check... ref uint resultPtr = ref MemoryMarshal.GetReference(bits); @@ -399,96 +345,18 @@ private static void MultiplyNearLength(ReadOnlySpan left, ReadOnlySpan> 32; } Unsafe.Add(ref resultPtr, i + left.Length) = (uint)carry; } } - else - { - // Based on the Toom-Cook multiplication we split left/right - // into two smaller values, doing recursive multiplication. - // The special form of this multiplication, where we - // split both operands into two operands, is also known - // as the Karatsuba algorithm... - - // https://en.wikipedia.org/wiki/Toom-Cook_multiplication - // https://en.wikipedia.org/wiki/Karatsuba_algorithm - - // Say we want to compute z = a * b ... - - // ... we need to determine our new length (just the half) - int n = right.Length >> 1; - int n2 = n << 1; - - // ... split left like a = (a_1 << n) + a_0 - ReadOnlySpan leftLow = left.Slice(0, n); - ReadOnlySpan leftHigh = left.Slice(n); - - // ... split right like b = (b_1 << n) + b_0 - ReadOnlySpan rightLow = right.Slice(0, n); - ReadOnlySpan rightHigh = right.Slice(n); - - // ... prepare our result array (to reuse its memory) - Span bitsLow = bits.Slice(0, n2); - Span bitsHigh = bits.Slice(n2); - - // ... compute z_0 = a_0 * b_0 (multiply again) - MultiplyNearLength(leftLow, rightLow, bitsLow); - - // ... compute z_2 = a_1 * b_1 (multiply again) - MultiplyNearLength(leftHigh, rightHigh, bitsHigh); - - int leftFoldLength = leftHigh.Length + 1; - uint[]? leftFoldFromPool = null; - Span leftFold = ((uint)leftFoldLength <= StackAllocThreshold ? - stackalloc uint[StackAllocThreshold] - : leftFoldFromPool = ArrayPool.Shared.Rent(leftFoldLength)).Slice(0, leftFoldLength); - leftFold.Clear(); - - int rightFoldLength = rightHigh.Length + 1; - uint[]? rightFoldFromPool = null; - Span rightFold = ((uint)rightFoldLength <= StackAllocThreshold ? - stackalloc uint[StackAllocThreshold] - : rightFoldFromPool = ArrayPool.Shared.Rent(rightFoldLength)).Slice(0, rightFoldLength); - rightFold.Clear(); - - int coreLength = leftFoldLength + rightFoldLength; - uint[]? coreFromPool = null; - Span core = ((uint)coreLength <= StackAllocThreshold ? - stackalloc uint[StackAllocThreshold] - : coreFromPool = ArrayPool.Shared.Rent(coreLength)).Slice(0, coreLength); - core.Clear(); - - // ... compute z_a = a_1 + a_0 (call it fold...) - Add(leftHigh, leftLow, leftFold); - - // ... compute z_b = b_1 + b_0 (call it fold...) - Add(rightHigh, rightLow, rightFold); - - // ... compute z_1 = z_a * z_b - z_0 - z_2 - MultiplyNearLength(leftFold, rightFold, core); - - if (leftFoldFromPool != null) - ArrayPool.Shared.Return(leftFoldFromPool); - - if (rightFoldFromPool != null) - ArrayPool.Shared.Return(rightFoldFromPool); - - SubtractCore(bitsHigh, bitsLow, core); - - // ... and finally merge the result! :-) - AddSelf(bits.Slice(n), core); - - if (coreFromPool != null) - ArrayPool.Shared.Return(coreFromPool); - } } private static void SubtractCore(ReadOnlySpan left, ReadOnlySpan right, Span core) diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs index 88f8ef25fe20..8d6b7abbfdbd 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs @@ -1466,6 +1466,23 @@ static Complex INumberBase.MinMagnitudeNumber(Complex x, Complex y) return y; } + /// + static Complex INumberBase.MultiplyAddEstimate(Complex left, Complex right, Complex addend) + { + // Multiplication: (a + bi)(c + di) = (ac - bd) + (bc + ad)i + // Addition: (a + bi) + (c + di) = (a + c) + (b + d)i + + double result_realpart = addend.m_real; + result_realpart = double.MultiplyAddEstimate(-left.m_imaginary, right.m_imaginary, result_realpart); + result_realpart = double.MultiplyAddEstimate(left.m_real, right.m_real, result_realpart); + + double result_imaginarypart = addend.m_imaginary; + result_imaginarypart = double.MultiplyAddEstimate(left.m_real, right.m_imaginary, result_imaginarypart); + result_imaginarypart = double.MultiplyAddEstimate(left.m_imaginary, right.m_real, result_imaginarypart); + + return new Complex(result_realpart, result_imaginarypart); + } + /// public static Complex Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) { diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/multiply.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/multiply.cs index d1abae863ea1..d94c235c65b6 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/multiply.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/multiply.cs @@ -38,12 +38,12 @@ public static void RunMultiply_TwoLargeBigIntegers_Threshold() { // Again, with lower threshold BigIntTools.Utils.RunWithFakeThreshold(BigIntegerCalculator.SquareThreshold, 8, () => - BigIntTools.Utils.RunWithFakeThreshold(BigIntegerCalculator.MultiplyThreshold, 8, RunMultiply_TwoLargeBigIntegers) + BigIntTools.Utils.RunWithFakeThreshold(BigIntegerCalculator.MultiplyKaratsubaThreshold, 8, RunMultiply_TwoLargeBigIntegers) ); // Again, with lower threshold BigIntTools.Utils.RunWithFakeThreshold(BigIntegerCalculator.SquareThreshold, 8, () => - BigIntTools.Utils.RunWithFakeThreshold(BigIntegerCalculator.MultiplyThreshold, 8, () => + BigIntTools.Utils.RunWithFakeThreshold(BigIntegerCalculator.MultiplyKaratsubaThreshold, 8, () => BigIntTools.Utils.RunWithFakeThreshold(BigIntegerCalculator.StackAllocThreshold, 8, RunMultiply_TwoLargeBigIntegers) ) ); @@ -216,10 +216,10 @@ public static void RunMultiplyKaratsubaBoundary() { for (int d1 = -2; d1 <= 2; d1++) { - tempByteArray1 = GetRandomByteArray(random, BigIntegerCalculator.MultiplyThreshold + d1); + tempByteArray1 = GetRandomByteArray(random, BigIntegerCalculator.MultiplyKaratsubaThreshold + d1); for (int d2 = -4; d2 <= 4; d2++) { - tempByteArray2 = GetRandomByteArray(random, (BigIntegerCalculator.MultiplyThreshold + 1) * 2 + d2); + tempByteArray2 = GetRandomByteArray(random, (BigIntegerCalculator.MultiplyKaratsubaThreshold + 1) * 2 + d2); VerifyMultiplyString(Print(tempByteArray1) + Print(tempByteArray2) + "bMultiply"); } } diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_multiply.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_multiply.cs index 08f73afe1819..9b09a402df59 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_multiply.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_multiply.cs @@ -169,10 +169,10 @@ public static void RunMultiplyKaratsubaBoundary() { for (int d1 = -2; d1 <= 2; d1++) { - tempByteArray1 = GetRandomByteArray(s_random, BigIntegerCalculator.MultiplyThreshold + d1); + tempByteArray1 = GetRandomByteArray(s_random, BigIntegerCalculator.MultiplyKaratsubaThreshold + d1); for (int d2 = -4; d2 <= 4; d2++) { - tempByteArray2 = GetRandomByteArray(s_random, (BigIntegerCalculator.MultiplyThreshold + 1) * 2 + d2); + tempByteArray2 = GetRandomByteArray(s_random, (BigIntegerCalculator.MultiplyKaratsubaThreshold + 1) * 2 + d2); VerifyMultiplyString(Print(tempByteArray1) + Print(tempByteArray2) + "b*"); } } diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTestData.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTestData.cs index f599a02df8df..d3e06e69b439 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTestData.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTestData.cs @@ -60,7 +60,7 @@ using System.Diagnostics.Eventing.Reader; // System.Text.Json is a .NET Core 3.0 specific library -#if NETCOREAPP +#if NET using System.Text.Json; #endif @@ -494,7 +494,7 @@ public static IEnumerable SerializableObjects() yield return new object[] { PopulateException(isolatedStorageException), new TypeSerializableValue[] { new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAEAQAAADJTeXN0ZW0uSU8uSXNvbGF0ZWRTdG9yYWdlLklzb2xhdGVkU3RvcmFnZUV4Y2VwdGlvbgwAAAAJQ2xhc3NOYW1lB01lc3NhZ2UERGF0YQ5Jbm5lckV4Y2VwdGlvbgdIZWxwVVJMEFN0YWNrVHJhY2VTdHJpbmcWUmVtb3RlU3RhY2tUcmFjZVN0cmluZxBSZW1vdGVTdGFja0luZGV4D0V4Y2VwdGlvbk1ldGhvZAdIUmVzdWx0BlNvdXJjZQ1XYXRzb25CdWNrZXRzAQEDAwEBAQABAAEHKVN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsEFN5c3RlbS5FeGNlcHRpb24ICAIGAgAAADJTeXN0ZW0uSU8uSXNvbGF0ZWRTdG9yYWdlLklzb2xhdGVkU3RvcmFnZUV4Y2VwdGlvbgYDAAAAB21lc3NhZ2UJBAAAAAkFAAAABgYAAAAZaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbQYHAAAAFFN0YWNrVHJhY2Ugc3RyaW5nLi4uBggAAAAbUmVtb3RlIFN0YWNrVHJhY2Ugc3RyaW5nLi4uAAAAAAroAwAABgkAAAAXRXhjZXB0aW9uX0NsYXNzX1NhbXBsZXMKBAQAAAApU3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwDAAAABGhlYWQHdmVyc2lvbgVjb3VudAMAADhTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbCtEaWN0aW9uYXJ5Tm9kZQgICQoAAAACAAAAAgAAAAQFAAAAEFN5c3RlbS5FeGNlcHRpb24MAAAACUNsYXNzTmFtZQdNZXNzYWdlBERhdGEOSW5uZXJFeGNlcHRpb24HSGVscFVSTBBTdGFja1RyYWNlU3RyaW5nFlJlbW90ZVN0YWNrVHJhY2VTdHJpbmcQUmVtb3RlU3RhY2tJbmRleA9FeGNlcHRpb25NZXRob2QHSFJlc3VsdAZTb3VyY2UNV2F0c29uQnVja2V0cwEBAwMBAQEAAQABBylTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbBBTeXN0ZW0uRXhjZXB0aW9uCAgCBgsAAAAQU3lzdGVtLkV4Y2VwdGlvbgkDAAAACQ0AAAAJDgAAAAkGAAAACQcAAAAJCAAAAAAAAAAK6AMAAAkJAAAACgQKAAAAOFN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsK0RpY3Rpb25hcnlOb2RlAwAAAANrZXkFdmFsdWUEbmV4dAICAzhTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbCtEaWN0aW9uYXJ5Tm9kZQYTAAAABnNlY3JldAgBAQkUAAAAAQ0AAAAEAAAACRUAAAACAAAAAgAAAAEOAAAABQAAAAkLAAAABhcAAAAXSW5uZXIgZXhjZXB0aW9uIG1lc3NhZ2UKCgoKCgAAAAAKABUTgAoKARQAAAAKAAAACAgBAAAABhgAAAADb25lCgEVAAAACgAAAAkTAAAACAEBCRoAAAABGgAAAAoAAAAICAEAAAAJGAAAAAoL", TargetFrameworkMoniker.netcoreapp20), new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAEAQAAADJTeXN0ZW0uSU8uSXNvbGF0ZWRTdG9yYWdlLklzb2xhdGVkU3RvcmFnZUV4Y2VwdGlvbgwAAAAJQ2xhc3NOYW1lB01lc3NhZ2UERGF0YQ5Jbm5lckV4Y2VwdGlvbgdIZWxwVVJMEFN0YWNrVHJhY2VTdHJpbmcWUmVtb3RlU3RhY2tUcmFjZVN0cmluZxBSZW1vdGVTdGFja0luZGV4D0V4Y2VwdGlvbk1ldGhvZAdIUmVzdWx0BlNvdXJjZQ1XYXRzb25CdWNrZXRzAQEDAwEBAQABAAEHKVN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsEFN5c3RlbS5FeGNlcHRpb24ICAIGAgAAADJTeXN0ZW0uSU8uSXNvbGF0ZWRTdG9yYWdlLklzb2xhdGVkU3RvcmFnZUV4Y2VwdGlvbgYDAAAAB21lc3NhZ2UJBAAAAAkFAAAABgYAAAAZaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbQYHAAAAFFN0YWNrVHJhY2Ugc3RyaW5nLi4uBggAAAAbUmVtb3RlIFN0YWNrVHJhY2Ugc3RyaW5nLi4uAAAAAAroAwAABgkAAAAXRXhjZXB0aW9uX0NsYXNzX1NhbXBsZXMKBAQAAAApU3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwDAAAABGhlYWQHdmVyc2lvbgVjb3VudAMAADhTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbCtEaWN0aW9uYXJ5Tm9kZQgICQoAAAACAAAAAgAAAAQFAAAAEFN5c3RlbS5FeGNlcHRpb24MAAAACUNsYXNzTmFtZQdNZXNzYWdlBERhdGEOSW5uZXJFeGNlcHRpb24HSGVscFVSTBBTdGFja1RyYWNlU3RyaW5nFlJlbW90ZVN0YWNrVHJhY2VTdHJpbmcQUmVtb3RlU3RhY2tJbmRleA9FeGNlcHRpb25NZXRob2QHSFJlc3VsdAZTb3VyY2UNV2F0c29uQnVja2V0cwEBAwMBAQEAAQABBylTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbBBTeXN0ZW0uRXhjZXB0aW9uCAgCBgsAAAAQU3lzdGVtLkV4Y2VwdGlvbgkDAAAACQ0AAAAJDgAAAAkGAAAACQcAAAAJCAAAAAAAAAAK6AMAAAkJAAAACgQKAAAAOFN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsK0RpY3Rpb25hcnlOb2RlAwAAAANrZXkFdmFsdWUEbmV4dAICAzhTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbCtEaWN0aW9uYXJ5Tm9kZQYTAAAABnNlY3JldAgBAQkUAAAAAQ0AAAAEAAAACRUAAAACAAAAAgAAAAEOAAAABQAAAAkLAAAABhcAAAAXSW5uZXIgZXhjZXB0aW9uIG1lc3NhZ2UKCgoKCgAAAAAKABUTgAoKARQAAAAKAAAACAgBAAAABhgAAAADb25lCgEVAAAACgAAAAkTAAAACAEBCRoAAAABGgAAAAoAAAAICAEAAAAJGAAAAAoL", TargetFrameworkMoniker.netfx461) } }; } -#if NETCOREAPP +#if NET var jsonException = new JsonException("message", path: "path", lineNumber: 1, bytePositionInLine: 2, innerException: exception); yield return new object[] { PopulateException(jsonException), new TypeSerializableValue[] { new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAFNTeXN0ZW0uVGV4dC5Kc29uLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Y2M3YjEzZmZjZDJkZGQ1MQUBAAAAHlN5c3RlbS5UZXh0Lkpzb24uSnNvbkV4Y2VwdGlvbhAAAAAJQ2xhc3NOYW1lB01lc3NhZ2UERGF0YQ5Jbm5lckV4Y2VwdGlvbgdIZWxwVVJMEFN0YWNrVHJhY2VTdHJpbmcWUmVtb3RlU3RhY2tUcmFjZVN0cmluZxBSZW1vdGVTdGFja0luZGV4D0V4Y2VwdGlvbk1ldGhvZAdIUmVzdWx0BlNvdXJjZQ1XYXRzb25CdWNrZXRzCkxpbmVOdW1iZXISQnl0ZVBvc2l0aW9uSW5MaW5lBFBhdGgNQWN0dWFsTWVzc2FnZQEBAwMBAQEAAQABBwMDAQEpU3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwQU3lzdGVtLkV4Y2VwdGlvbggIAgxTeXN0ZW0uSW50NjQMU3lzdGVtLkludDY0AgAAAAYDAAAAHlN5c3RlbS5UZXh0Lkpzb24uSnNvbkV4Y2VwdGlvbgYEAAAAB21lc3NhZ2UJBQAAAAkGAAAABgcAAAAZaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbQYIAAAAFFN0YWNrVHJhY2Ugc3RyaW5nLi4uBgkAAAAbUmVtb3RlIFN0YWNrVHJhY2Ugc3RyaW5nLi4uAAAAAAroAwAABgoAAAAXRXhjZXB0aW9uX0NsYXNzX1NhbXBsZXMKCAkBAAAAAAAAAAgJAgAAAAAAAAAGCwAAAARwYXRoCQQAAAAEBQAAAClTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbAMAAAAEaGVhZAd2ZXJzaW9uBWNvdW50AwAAOFN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsK0RpY3Rpb25hcnlOb2RlCAgJDQAAAAIAAAACAAAABAYAAAAQU3lzdGVtLkV4Y2VwdGlvbgwAAAAJQ2xhc3NOYW1lB01lc3NhZ2UERGF0YQ5Jbm5lckV4Y2VwdGlvbgdIZWxwVVJMEFN0YWNrVHJhY2VTdHJpbmcWUmVtb3RlU3RhY2tUcmFjZVN0cmluZxBSZW1vdGVTdGFja0luZGV4D0V4Y2VwdGlvbk1ldGhvZAdIUmVzdWx0BlNvdXJjZQ1XYXRzb25CdWNrZXRzAQEDAwEBAQABAAEHKVN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsEFN5c3RlbS5FeGNlcHRpb24ICAIGDgAAABBTeXN0ZW0uRXhjZXB0aW9uCQQAAAAJEAAAAAkRAAAACQcAAAAJCAAAAAkJAAAAAAAAAAroAwAACQoAAAAKBA0AAAA4U3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwrRGljdGlvbmFyeU5vZGUDAAAAA2tleQV2YWx1ZQRuZXh0AgIDOFN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsK0RpY3Rpb25hcnlOb2RlBhYAAAAGc2VjcmV0CAEBCRcAAAABEAAAAAUAAAAJGAAAAAIAAAACAAAAAREAAAAGAAAACQ4AAAAGGgAAABdJbm5lciBleGNlcHRpb24gbWVzc2FnZQoKCgoKAAAAAAoAFROACgoBFwAAAA0AAAAICAEAAAAGGwAAAANvbmUKARgAAAANAAAACRYAAAAIAQEJHQAAAAEdAAAADQAAAAgIAQAAAAkbAAAACgs=", TargetFrameworkMoniker.netcoreapp30) } }; @@ -677,7 +677,7 @@ public static IEnumerable SerializableObjects() yield return new object[] { PopulateException(smtpFailedRecipientsException), new TypeSerializableValue[] { new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAElTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAtU3lzdGVtLk5ldC5NYWlsLlNtdHBGYWlsZWRSZWNpcGllbnRzRXhjZXB0aW9uDwAAAAlDbGFzc05hbWUHTWVzc2FnZQREYXRhDklubmVyRXhjZXB0aW9uB0hlbHBVUkwQU3RhY2tUcmFjZVN0cmluZxZSZW1vdGVTdGFja1RyYWNlU3RyaW5nEFJlbW90ZVN0YWNrSW5kZXgPRXhjZXB0aW9uTWV0aG9kB0hSZXN1bHQGU291cmNlDVdhdHNvbkJ1Y2tldHMGU3RhdHVzD2ZhaWxlZFJlY2lwaWVudA9pbm5lckV4Y2VwdGlvbnMBAQMEAQEBAAEAAQcAAQQpU3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwsU3lzdGVtLk5ldC5NYWlsLlNtdHBGYWlsZWRSZWNpcGllbnRFeGNlcHRpb24CAAAACAgCCC5TeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudEV4Y2VwdGlvbltdAgAAAAIAAAAGAwAAAC1TeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudHNFeGNlcHRpb24GBAAAAAdtZXNzYWdlCQUAAAAJBgAAAAYHAAAAGWh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20GCAAAABRTdGFja1RyYWNlIHN0cmluZy4uLgYJAAAAG1JlbW90ZSBTdGFja1RyYWNlIHN0cmluZy4uLgAAAAAK6AMAAAYKAAAAF0V4Y2VwdGlvbl9DbGFzc19TYW1wbGVzCv////8GCwAAAA9mYWlsZWRSZWNpcGllbnQJDAAAAAQFAAAAKVN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsAwAAAARoZWFkB3ZlcnNpb24FY291bnQDAAA4U3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwrRGljdGlvbmFyeU5vZGUICAkNAAAAAgAAAAIAAAAFBgAAACxTeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudEV4Y2VwdGlvbg4AAAAJQ2xhc3NOYW1lB01lc3NhZ2UERGF0YQ5Jbm5lckV4Y2VwdGlvbgdIZWxwVVJMEFN0YWNrVHJhY2VTdHJpbmcWUmVtb3RlU3RhY2tUcmFjZVN0cmluZxBSZW1vdGVTdGFja0luZGV4D0V4Y2VwdGlvbk1ldGhvZAdIUmVzdWx0BlNvdXJjZQ1XYXRzb25CdWNrZXRzBlN0YXR1cw9mYWlsZWRSZWNpcGllbnQBAQMDAQEBAAEAAQcAASlTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbBBTeXN0ZW0uRXhjZXB0aW9uCAgCCAIAAAAGDgAAACxTeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudEV4Y2VwdGlvbgYPAAAAMkNvbXBsZXRlZC4gVGhlIHNlcnZlciByZXNwb25zZSB3YXM6IHNlcnZlclJlc3BvbnNlCRAAAAAKCQcAAAAJCAAAAAkJAAAAAAAAAAroAwAACQoAAAAK+gAAAAkLAAAABwwAAAAAAQAAAAEAAAAELFN5c3RlbS5OZXQuTWFpbC5TbXRwRmFpbGVkUmVjaXBpZW50RXhjZXB0aW9uAgAAAAkGAAAABA0AAAA4U3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwrRGljdGlvbmFyeU5vZGUDAAAAA2tleQV2YWx1ZQRuZXh0AgIDOFN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsK0RpY3Rpb25hcnlOb2RlBhcAAAAGc2VjcmV0CAEBCRgAAAABEAAAAAUAAAAJGQAAAAIAAAACAAAAARgAAAANAAAACAgBAAAABhoAAAADb25lCgEZAAAADQAAAAkXAAAACAEBCRwAAAABHAAAAA0AAAAICAEAAAAJGgAAAAoL", TargetFrameworkMoniker.netcoreapp20), new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAElTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAtU3lzdGVtLk5ldC5NYWlsLlNtdHBGYWlsZWRSZWNpcGllbnRzRXhjZXB0aW9uDwAAAAlDbGFzc05hbWUHTWVzc2FnZQREYXRhDklubmVyRXhjZXB0aW9uB0hlbHBVUkwQU3RhY2tUcmFjZVN0cmluZxZSZW1vdGVTdGFja1RyYWNlU3RyaW5nEFJlbW90ZVN0YWNrSW5kZXgPRXhjZXB0aW9uTWV0aG9kB0hSZXN1bHQGU291cmNlDVdhdHNvbkJ1Y2tldHMGU3RhdHVzD2ZhaWxlZFJlY2lwaWVudA9pbm5lckV4Y2VwdGlvbnMBAQMEAQEBAAEAAQcAAQQpU3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwsU3lzdGVtLk5ldC5NYWlsLlNtdHBGYWlsZWRSZWNpcGllbnRFeGNlcHRpb24CAAAACAgCCC5TeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudEV4Y2VwdGlvbltdAgAAAAIAAAAGAwAAAC1TeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudHNFeGNlcHRpb24GBAAAAAdtZXNzYWdlCQUAAAAJBgAAAAYHAAAAGWh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20GCAAAABRTdGFja1RyYWNlIHN0cmluZy4uLgYJAAAAG1JlbW90ZSBTdGFja1RyYWNlIHN0cmluZy4uLgAAAAAK6AMAAAYKAAAAF0V4Y2VwdGlvbl9DbGFzc19TYW1wbGVzCv////8GCwAAAA9mYWlsZWRSZWNpcGllbnQJDAAAAAQFAAAAKVN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsAwAAAARoZWFkB3ZlcnNpb24FY291bnQDAAA4U3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwrRGljdGlvbmFyeU5vZGUICAkNAAAAAgAAAAIAAAAFBgAAACxTeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudEV4Y2VwdGlvbg4AAAAJQ2xhc3NOYW1lB01lc3NhZ2UERGF0YQ5Jbm5lckV4Y2VwdGlvbgdIZWxwVVJMEFN0YWNrVHJhY2VTdHJpbmcWUmVtb3RlU3RhY2tUcmFjZVN0cmluZxBSZW1vdGVTdGFja0luZGV4D0V4Y2VwdGlvbk1ldGhvZAdIUmVzdWx0BlNvdXJjZQ1XYXRzb25CdWNrZXRzBlN0YXR1cw9mYWlsZWRSZWNpcGllbnQBAQMDAQEBAAEAAQcAASlTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbBBTeXN0ZW0uRXhjZXB0aW9uCAgCCAIAAAAGDgAAACxTeXN0ZW0uTmV0Lk1haWwuU210cEZhaWxlZFJlY2lwaWVudEV4Y2VwdGlvbgYPAAAAMkNvbXBsZXRlZC4gVGhlIHNlcnZlciByZXNwb25zZSB3YXM6IHNlcnZlclJlc3BvbnNlCRAAAAAKCQcAAAAJCAAAAAkJAAAAAAAAAAroAwAACQoAAAAK+gAAAAkLAAAABwwAAAAAAQAAAAEAAAAELFN5c3RlbS5OZXQuTWFpbC5TbXRwRmFpbGVkUmVjaXBpZW50RXhjZXB0aW9uAgAAAAkGAAAABA0AAAA4U3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwrRGljdGlvbmFyeU5vZGUDAAAAA2tleQV2YWx1ZQRuZXh0AgIDOFN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsK0RpY3Rpb25hcnlOb2RlBhcAAAAGc2VjcmV0CAEBCRgAAAABEAAAAAUAAAAJGQAAAAIAAAACAAAAARgAAAANAAAACAgBAAAABhoAAAADb25lCgEZAAAADQAAAAkXAAAACAEBCRwAAAABHAAAAA0AAAAICAEAAAAJGgAAAAoL", TargetFrameworkMoniker.netfx461) } }; } -#if NETCOREAPP +#if NET var ambiguousImplementationException = new AmbiguousImplementationException(); yield return new object[] { PopulateException(ambiguousImplementationException, false), new TypeSerializableValue[] { new TypeSerializableValue("AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uUnVudGltZSwgVmVyc2lvbj00LjIuMS4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAAC9TeXN0ZW0uUnVudGltZS5BbWJpZ3VvdXNJbXBsZW1lbnRhdGlvbkV4Y2VwdGlvbgwAAAAJQ2xhc3NOYW1lB01lc3NhZ2UERGF0YQ5Jbm5lckV4Y2VwdGlvbgdIZWxwVVJMEFN0YWNrVHJhY2VTdHJpbmcWUmVtb3RlU3RhY2tUcmFjZVN0cmluZxBSZW1vdGVTdGFja0luZGV4D0V4Y2VwdGlvbk1ldGhvZAdIUmVzdWx0BlNvdXJjZQ1XYXRzb25CdWNrZXRzAQEDAwEBAQABAAEHKVN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsEFN5c3RlbS5FeGNlcHRpb24ICAICAAAABgMAAAAvU3lzdGVtLlJ1bnRpbWUuQW1iaWd1b3VzSW1wbGVtZW50YXRpb25FeGNlcHRpb24GBAAAAB9BbWJpZ3VvdXMgaW1wbGVtZW50YXRpb24gZm91bmQuCQUAAAAKBgYAAAAZaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbQYHAAAAFFN0YWNrVHJhY2Ugc3RyaW5nLi4uBggAAAAbUmVtb3RlIFN0YWNrVHJhY2Ugc3RyaW5nLi4uAAAAAApqEBOABgkAAAAXRXhjZXB0aW9uX0NsYXNzX1NhbXBsZXMKBAUAAAApU3lzdGVtLkNvbGxlY3Rpb25zLkxpc3REaWN0aW9uYXJ5SW50ZXJuYWwDAAAABGhlYWQHdmVyc2lvbgVjb3VudAMAADhTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbCtEaWN0aW9uYXJ5Tm9kZQgICQoAAAACAAAAAgAAAAQKAAAAOFN5c3RlbS5Db2xsZWN0aW9ucy5MaXN0RGljdGlvbmFyeUludGVybmFsK0RpY3Rpb25hcnlOb2RlAwAAAANrZXkFdmFsdWUEbmV4dAICAzhTeXN0ZW0uQ29sbGVjdGlvbnMuTGlzdERpY3Rpb25hcnlJbnRlcm5hbCtEaWN0aW9uYXJ5Tm9kZQYLAAAABnNlY3JldAgBAQkMAAAAAQwAAAAKAAAACAgBAAAABg0AAAADb25lCgs=", TargetFrameworkMoniker.netcoreapp30) } }; var switchExpressionException = new SwitchExpressionException(34); diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/EqualityExtensions.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/EqualityExtensions.cs index e6d9652007e3..cbb1b2bba6b2 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/tests/EqualityExtensions.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/EqualityExtensions.cs @@ -23,7 +23,7 @@ using Xunit; // System.Text.Json is a .NET Core 3.0 specific library -#if NETCOREAPP +#if NET using System.Text.Json; #endif @@ -1195,7 +1195,7 @@ public static void IsEqual(this AggregateException @this, AggregateException oth @this.InnerExceptions.CheckSequenceEquals(other.InnerExceptions, isSamePlatform); } -#if NETCOREAPP +#if NET public static void IsEqual(this JsonException @this, JsonException other, bool isSamePlatform) { if (@this == null && other == null) diff --git a/src/libraries/System.Runtime.Serialization.Primitives/src/System.Runtime.Serialization.Primitives.csproj b/src/libraries/System.Runtime.Serialization.Primitives/src/System.Runtime.Serialization.Primitives.csproj index 08ff96e95af3..ca2ed33befc5 100644 --- a/src/libraries/System.Runtime.Serialization.Primitives/src/System.Runtime.Serialization.Primitives.csproj +++ b/src/libraries/System.Runtime.Serialization.Primitives/src/System.Runtime.Serialization.Primitives.csproj @@ -22,6 +22,7 @@ + diff --git a/src/libraries/System.Runtime.Serialization.Schema/tests/System/Runtime/Serialization/Schema/RoundTripTest.cs b/src/libraries/System.Runtime.Serialization.Schema/tests/System/Runtime/Serialization/Schema/RoundTripTest.cs index b8fe734b1a55..9b23c73d43e6 100644 --- a/src/libraries/System.Runtime.Serialization.Schema/tests/System/Runtime/Serialization/Schema/RoundTripTest.cs +++ b/src/libraries/System.Runtime.Serialization.Schema/tests/System/Runtime/Serialization/Schema/RoundTripTest.cs @@ -21,6 +21,7 @@ public RoundTripTest(ITestOutputHelper output) [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/73961", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/73961", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsAppleMobile))] public void RountTripTest() { // AppContext SetSwitch seems to be unreliable in the unit test case. So let's not rely on it diff --git a/src/libraries/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs b/src/libraries/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs index bbf437b40207..bba5dc9c04a4 100644 --- a/src/libraries/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs +++ b/src/libraries/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs @@ -4193,6 +4193,7 @@ public static void DCS_SampleICollectionTExplicitWithoutDC() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/73961", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [ActiveIssue("https://github.com/dotnet/runtime/issues/73961", typeof(PlatformDetection), nameof(PlatformDetection.IsWasi))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/73961", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsAppleMobile))] public static void DCS_MemoryStream_Serialize_UsesBuiltInAdapter() { ValidateObject( @@ -4253,6 +4254,7 @@ static void ValidateObject(MemoryStream original, string expectedXml, byte[] exp [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/73961", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [ActiveIssue("https://github.com/dotnet/runtime/issues/73961", typeof(PlatformDetection), nameof(PlatformDetection.IsWasi))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/73961", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsAppleMobile))] public static void DCS_MemoryStream_Deserialize_CompatibleWithFullFramework() { // The payloads in this test were generated by a Full Framework application. diff --git a/src/libraries/System.Runtime.Serialization.Xml/tests/XsdDataContractExporterTests/ExporterApiTests.cs b/src/libraries/System.Runtime.Serialization.Xml/tests/XsdDataContractExporterTests/ExporterApiTests.cs index 982cc7dc0888..32d4a70533b5 100644 --- a/src/libraries/System.Runtime.Serialization.Xml/tests/XsdDataContractExporterTests/ExporterApiTests.cs +++ b/src/libraries/System.Runtime.Serialization.Xml/tests/XsdDataContractExporterTests/ExporterApiTests.cs @@ -89,6 +89,7 @@ public static IEnumerable CanExport_MemberData() [Theory] [ActiveIssue("https://github.com/dotnet/runtime/issues/73961", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [ActiveIssue("https://github.com/dotnet/runtime/issues/73961", typeof(PlatformDetection), nameof(PlatformDetection.IsWasi))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/73961", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsAppleMobile))] [MemberData(nameof(Export_MemberData))] public void Export(string testname, Action export, Action schemaCheck = null) { diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 0371e3037e26..37bd783042bd 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -4,6 +4,8 @@ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ +using System.Numerics; + namespace Microsoft.Win32.SafeHandles { public abstract partial class CriticalHandleMinusOneIsInvalid : System.Runtime.InteropServices.CriticalHandle @@ -874,6 +876,7 @@ public static void SetByte(System.Array array, int index, byte value) { } static byte System.Numerics.INumberBase.MaxMagnitudeNumber(byte x, byte y) { throw null; } static byte System.Numerics.INumberBase.MinMagnitude(byte x, byte y) { throw null; } static byte System.Numerics.INumberBase.MinMagnitudeNumber(byte x, byte y) { throw null; } + static byte System.Numerics.INumberBase.MultiplyAddEstimate(byte left, byte right, byte addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out byte result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out byte result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out byte result) { throw null; } @@ -1061,6 +1064,7 @@ public CannotUnloadAppDomainException(string? message, System.Exception? innerEx static char System.Numerics.INumberBase.MaxMagnitudeNumber(char x, char y) { throw null; } static char System.Numerics.INumberBase.MinMagnitude(char x, char y) { throw null; } static char System.Numerics.INumberBase.MinMagnitudeNumber(char x, char y) { throw null; } + static char System.Numerics.INumberBase.MultiplyAddEstimate(char left, char right, char addend) { throw null; } static char System.Numerics.INumberBase.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } static char System.Numerics.INumberBase.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out char result) { throw null; } @@ -1985,6 +1989,8 @@ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, S public static int Compare(decimal d1, decimal d2) { throw null; } public int CompareTo(decimal value) { throw null; } public int CompareTo(object? value) { throw null; } + public static TInteger ConvertToInteger(decimal value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + public static TInteger ConvertToIntegerNative(decimal value) where TInteger : System.Numerics.IBinaryInteger { throw null; } public static decimal CopySign(decimal value, decimal sign) { throw null; } public static decimal CreateChecked(TOther value) where TOther : System.Numerics.INumberBase { throw null; } public static decimal CreateSaturating(TOther value) where TOther : System.Numerics.INumberBase { throw null; } @@ -2107,6 +2113,7 @@ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, S static bool System.Numerics.INumberBase.IsZero(decimal value) { throw null; } static decimal System.Numerics.INumberBase.MaxMagnitudeNumber(decimal x, decimal y) { throw null; } static decimal System.Numerics.INumberBase.MinMagnitudeNumber(decimal x, decimal y) { throw null; } + static decimal System.Numerics.INumberBase.MultiplyAddEstimate(decimal left, decimal right, decimal addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out decimal result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out decimal result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out decimal result) { throw null; } @@ -2163,6 +2170,7 @@ protected Delegate([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAt [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute("b")] public static System.Delegate? Combine(System.Delegate? a, System.Delegate? b) { throw null; } public static System.Delegate? Combine(params System.Delegate?[]? delegates) { throw null; } + public static System.Delegate? Combine(params System.ReadOnlySpan delegates) { throw null; } protected virtual System.Delegate CombineImpl(System.Delegate? d) { throw null; } public static System.Delegate CreateDelegate(System.Type type, object? firstArgument, System.Reflection.MethodInfo method) { throw null; } public static System.Delegate? CreateDelegate(System.Type type, object? firstArgument, System.Reflection.MethodInfo method, bool throwOnBindFailure) { throw null; } @@ -2258,6 +2266,8 @@ public DivideByZeroException(string? message, System.Exception? innerException) public static double Clamp(double value, double min, double max) { throw null; } public int CompareTo(double value) { throw null; } public int CompareTo(object? value) { throw null; } + public static TInteger ConvertToInteger(double value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + public static TInteger ConvertToIntegerNative(double value) where TInteger : System.Numerics.IBinaryInteger { throw null; } public static double CopySign(double value, double sign) { throw null; } public static double Cos(double x) { throw null; } public static double Cosh(double x) { throw null; } @@ -2311,6 +2321,7 @@ public DivideByZeroException(string? message, System.Exception? innerException) public static double MinMagnitude(double x, double y) { throw null; } public static double MinMagnitudeNumber(double x, double y) { throw null; } public static double MinNumber(double x, double y) { throw null; } + public static double MultiplyAddEstimate(double left, double right, double addend) { throw null; } public static bool operator ==(double left, double right) { throw null; } public static bool operator >(double left, double right) { throw null; } public static bool operator >=(double left, double right) { throw null; } @@ -2436,7 +2447,7 @@ protected Enum() { } public override int GetHashCode() { throw null; } public static string? GetName(System.Type enumType, object value) { throw null; } public static string[] GetNames(System.Type enumType) { throw null; } - public static string[] GetNames() where TEnum : struct { throw null; } + public static string[] GetNames() where TEnum : struct, System.Enum { throw null; } public static string? GetName(TEnum value) where TEnum : struct, System.Enum { throw null; } public System.TypeCode GetTypeCode() { throw null; } public static System.Type GetUnderlyingType(System.Type enumType) { throw null; } @@ -2880,6 +2891,8 @@ public enum GCNotificationStatus public static System.Half Clamp(System.Half value, System.Half min, System.Half max) { throw null; } public int CompareTo(System.Half other) { throw null; } public int CompareTo(object? obj) { throw null; } + public static TInteger ConvertToInteger(System.Half value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + public static TInteger ConvertToIntegerNative(System.Half value) where TInteger : System.Numerics.IBinaryInteger { throw null; } public static System.Half CopySign(System.Half value, System.Half sign) { throw null; } public static System.Half Cos(System.Half x) { throw null; } public static System.Half Cosh(System.Half x) { throw null; } @@ -2932,6 +2945,7 @@ public enum GCNotificationStatus public static System.Half MinMagnitude(System.Half x, System.Half y) { throw null; } public static System.Half MinMagnitudeNumber(System.Half x, System.Half y) { throw null; } public static System.Half MinNumber(System.Half x, System.Half y) { throw null; } + public static System.Half MultiplyAddEstimate(System.Half left, System.Half right, System.Half addend) { throw null; } public static System.Half operator +(System.Half left, System.Half right) { throw null; } public static explicit operator checked byte (System.Half value) { throw null; } public static explicit operator checked char (System.Half value) { throw null; } @@ -3355,6 +3369,7 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep static bool System.Numerics.INumberBase.IsZero(System.Int128 value) { throw null; } static System.Int128 System.Numerics.INumberBase.MaxMagnitudeNumber(System.Int128 x, System.Int128 y) { throw null; } static System.Int128 System.Numerics.INumberBase.MinMagnitudeNumber(System.Int128 x, System.Int128 y) { throw null; } + static System.Int128 System.Numerics.INumberBase.MultiplyAddEstimate(System.Int128 left, System.Int128 right, System.Int128 addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Int128 result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Int128 result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Int128 result) { throw null; } @@ -3486,6 +3501,7 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep static bool System.Numerics.INumberBase.IsZero(short value) { throw null; } static short System.Numerics.INumberBase.MaxMagnitudeNumber(short x, short y) { throw null; } static short System.Numerics.INumberBase.MinMagnitudeNumber(short x, short y) { throw null; } + static short System.Numerics.INumberBase.MultiplyAddEstimate(short left, short right, short addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out short result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out short result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out short result) { throw null; } @@ -3625,6 +3641,7 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep static bool System.Numerics.INumberBase.IsZero(int value) { throw null; } static int System.Numerics.INumberBase.MaxMagnitudeNumber(int x, int y) { throw null; } static int System.Numerics.INumberBase.MinMagnitudeNumber(int x, int y) { throw null; } + static int System.Numerics.INumberBase.MultiplyAddEstimate(int left, int right, int addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out int result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out int result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out int result) { throw null; } @@ -3764,6 +3781,7 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep static bool System.Numerics.INumberBase.IsZero(long value) { throw null; } static long System.Numerics.INumberBase.MaxMagnitudeNumber(long x, long y) { throw null; } static long System.Numerics.INumberBase.MinMagnitudeNumber(long x, long y) { throw null; } + static long System.Numerics.INumberBase.MultiplyAddEstimate(long left, long right, long addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out long result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out long result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out long result) { throw null; } @@ -3905,6 +3923,7 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep static bool System.Numerics.INumberBase.IsZero(nint value) { throw null; } static nint System.Numerics.INumberBase.MaxMagnitudeNumber(nint x, nint y) { throw null; } static nint System.Numerics.INumberBase.MinMagnitudeNumber(nint x, nint y) { throw null; } + static nint System.Numerics.INumberBase.MultiplyAddEstimate(nint left, nint right, nint addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out nint result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out nint result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out nint result) { throw null; } @@ -4909,6 +4928,7 @@ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, S static bool System.Numerics.INumberBase.IsZero(sbyte value) { throw null; } static sbyte System.Numerics.INumberBase.MaxMagnitudeNumber(sbyte x, sbyte y) { throw null; } static sbyte System.Numerics.INumberBase.MinMagnitudeNumber(sbyte x, sbyte y) { throw null; } + static sbyte System.Numerics.INumberBase.MultiplyAddEstimate(sbyte left, sbyte right, sbyte addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out sbyte result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out sbyte result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out sbyte result) { throw null; } @@ -4997,6 +5017,8 @@ public SerializableAttribute() { } public static float Clamp(float value, float min, float max) { throw null; } public int CompareTo(object? value) { throw null; } public int CompareTo(float value) { throw null; } + public static TInteger ConvertToInteger(float value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + public static TInteger ConvertToIntegerNative(float value) where TInteger : System.Numerics.IBinaryInteger { throw null; } public static float CopySign(float value, float sign) { throw null; } public static float Cos(float x) { throw null; } public static float Cosh(float x) { throw null; } @@ -5050,6 +5072,7 @@ public SerializableAttribute() { } public static float MinMagnitude(float x, float y) { throw null; } public static float MinMagnitudeNumber(float x, float y) { throw null; } public static float MinNumber(float x, float y) { throw null; } + public static float MultiplyAddEstimate(float left, float right, float addend) { throw null; } public static bool operator ==(float left, float right) { throw null; } public static bool operator >(float left, float right) { throw null; } public static bool operator >=(float left, float right) { throw null; } @@ -5242,6 +5265,7 @@ public unsafe String(sbyte* value, int startIndex, int length, System.Text.Encod public static string Concat(object? arg0, object? arg1) { throw null; } public static string Concat(object? arg0, object? arg1, object? arg2) { throw null; } public static string Concat(params object?[] args) { throw null; } + public static string Concat(params System.ReadOnlySpan args) { throw null; } public static string Concat(System.ReadOnlySpan str0, System.ReadOnlySpan str1) { throw null; } public static string Concat(System.ReadOnlySpan str0, System.ReadOnlySpan str1, System.ReadOnlySpan str2) { throw null; } public static string Concat(System.ReadOnlySpan str0, System.ReadOnlySpan str1, System.ReadOnlySpan str2, System.ReadOnlySpan str3) { throw null; } @@ -5249,6 +5273,7 @@ public unsafe String(sbyte* value, int startIndex, int length, System.Text.Encod public static string Concat(string? str0, string? str1, string? str2) { throw null; } public static string Concat(string? str0, string? str1, string? str2, string? str3) { throw null; } public static string Concat(params string?[] values) { throw null; } + public static string Concat(params System.ReadOnlySpan values) { throw null; } public static string Concat(System.Collections.Generic.IEnumerable values) { throw null; } public bool Contains(char value) { throw null; } public bool Contains(char value, System.StringComparison comparisonType) { throw null; } @@ -5276,12 +5301,14 @@ public void CopyTo(System.Span destination) { } public static string Format(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { throw null; } public static string Format(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { throw null; } public static string Format(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] args) { throw null; } + public static string Format(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params System.ReadOnlySpan args) { throw null; } public static string Format(System.IFormatProvider? provider, System.Text.CompositeFormat format, params object?[] args) { throw null; } - public static string Format(System.IFormatProvider? provider, System.Text.CompositeFormat format, System.ReadOnlySpan args) { throw null; } + public static string Format(System.IFormatProvider? provider, System.Text.CompositeFormat format, params System.ReadOnlySpan args) { throw null; } public static string Format([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0) { throw null; } public static string Format([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { throw null; } public static string Format([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { throw null; } public static string Format([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] args) { throw null; } + public static string Format([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params System.ReadOnlySpan args) { throw null; } public static string Format(System.IFormatProvider? provider, System.Text.CompositeFormat format, TArg0 arg0) { throw null; } public static string Format(System.IFormatProvider? provider, System.Text.CompositeFormat format, TArg0 arg0, TArg1 arg1) { throw null; } public static string Format(System.IFormatProvider? provider, System.Text.CompositeFormat format, TArg0 arg0, TArg1 arg1, TArg2 arg2) { throw null; } @@ -5314,11 +5341,15 @@ public void CopyTo(System.Span destination) { } public static bool IsNullOrEmpty([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] string? value) { throw null; } public static bool IsNullOrWhiteSpace([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] string? value) { throw null; } public static string Join(char separator, params object?[] values) { throw null; } + public static string Join(char separator, params System.ReadOnlySpan values) { throw null; } public static string Join(char separator, params string?[] value) { throw null; } + public static string Join(char separator, params System.ReadOnlySpan value) { throw null; } public static string Join(char separator, string?[] value, int startIndex, int count) { throw null; } public static string Join(string? separator, System.Collections.Generic.IEnumerable values) { throw null; } public static string Join(string? separator, params object?[] values) { throw null; } + public static string Join(string? separator, params System.ReadOnlySpan values) { throw null; } public static string Join(string? separator, params string?[] value) { throw null; } + public static string Join(string? separator, params System.ReadOnlySpan value) { throw null; } public static string Join(string? separator, string?[] value, int startIndex, int count) { throw null; } public static string Join(char separator, System.Collections.Generic.IEnumerable values) { throw null; } public static string Join(string? separator, System.Collections.Generic.IEnumerable values) { throw null; } @@ -5354,6 +5385,7 @@ public void CopyTo(System.Span destination) { } public string[] Split(char separator, int count, System.StringSplitOptions options = System.StringSplitOptions.None) { throw null; } public string[] Split(char separator, System.StringSplitOptions options = System.StringSplitOptions.None) { throw null; } public string[] Split(params char[]? separator) { throw null; } + public string[] Split(params System.ReadOnlySpan separator) { throw null; } public string[] Split(char[]? separator, int count) { throw null; } public string[] Split(char[]? separator, int count, System.StringSplitOptions options) { throw null; } public string[] Split(char[]? separator, System.StringSplitOptions options) { throw null; } @@ -5401,12 +5433,15 @@ public void CopyTo(System.Span destination) { } public string Trim() { throw null; } public string Trim(char trimChar) { throw null; } public string Trim(params char[]? trimChars) { throw null; } + public string Trim(params System.ReadOnlySpan trimChars) { throw null; } public string TrimEnd() { throw null; } public string TrimEnd(char trimChar) { throw null; } public string TrimEnd(params char[]? trimChars) { throw null; } + public string TrimEnd(params System.ReadOnlySpan trimChars) { throw null; } public string TrimStart() { throw null; } public string TrimStart(char trimChar) { throw null; } public string TrimStart(params char[]? trimChars) { throw null; } + public string TrimStart(params System.ReadOnlySpan trimChars) { throw null; } public bool TryCopyTo(System.Span destination) { throw null; } } public abstract partial class StringComparer : System.Collections.Generic.IComparer, System.Collections.Generic.IEqualityComparer, System.Collections.IComparer, System.Collections.IEqualityComparer @@ -6552,6 +6587,7 @@ public TypeUnloadedException(string? message, System.Exception? innerException) static System.UInt128 System.Numerics.INumberBase.MaxMagnitudeNumber(System.UInt128 x, System.UInt128 y) { throw null; } static System.UInt128 System.Numerics.INumberBase.MinMagnitude(System.UInt128 x, System.UInt128 y) { throw null; } static System.UInt128 System.Numerics.INumberBase.MinMagnitudeNumber(System.UInt128 x, System.UInt128 y) { throw null; } + static System.UInt128 System.Numerics.INumberBase.MultiplyAddEstimate(System.UInt128 left, System.UInt128 right, System.UInt128 addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.UInt128 result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.UInt128 result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.UInt128 result) { throw null; } @@ -6683,6 +6719,7 @@ public TypeUnloadedException(string? message, System.Exception? innerException) static ushort System.Numerics.INumberBase.MaxMagnitudeNumber(ushort x, ushort y) { throw null; } static ushort System.Numerics.INumberBase.MinMagnitude(ushort x, ushort y) { throw null; } static ushort System.Numerics.INumberBase.MinMagnitudeNumber(ushort x, ushort y) { throw null; } + static ushort System.Numerics.INumberBase.MultiplyAddEstimate(ushort left, ushort right, ushort addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out ushort result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out ushort result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out ushort result) { throw null; } @@ -6822,6 +6859,7 @@ public TypeUnloadedException(string? message, System.Exception? innerException) static uint System.Numerics.INumberBase.MaxMagnitudeNumber(uint x, uint y) { throw null; } static uint System.Numerics.INumberBase.MinMagnitude(uint x, uint y) { throw null; } static uint System.Numerics.INumberBase.MinMagnitudeNumber(uint x, uint y) { throw null; } + static uint System.Numerics.INumberBase.MultiplyAddEstimate(uint left, uint right, uint addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out uint result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out uint result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out uint result) { throw null; } @@ -6961,6 +6999,7 @@ public TypeUnloadedException(string? message, System.Exception? innerException) static ulong System.Numerics.INumberBase.MaxMagnitudeNumber(ulong x, ulong y) { throw null; } static ulong System.Numerics.INumberBase.MinMagnitude(ulong x, ulong y) { throw null; } static ulong System.Numerics.INumberBase.MinMagnitudeNumber(ulong x, ulong y) { throw null; } + static ulong System.Numerics.INumberBase.MultiplyAddEstimate(ulong left, ulong right, ulong addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out ulong result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out ulong result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out ulong result) { throw null; } @@ -7099,6 +7138,7 @@ public TypeUnloadedException(string? message, System.Exception? innerException) static nuint System.Numerics.INumberBase.MaxMagnitudeNumber(nuint x, nuint y) { throw null; } static nuint System.Numerics.INumberBase.MinMagnitude(nuint x, nuint y) { throw null; } static nuint System.Numerics.INumberBase.MinMagnitudeNumber(nuint x, nuint y) { throw null; } + static nuint System.Numerics.INumberBase.MultiplyAddEstimate(nuint left, nuint right, nuint addend) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out nuint result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out nuint result) { throw null; } static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out nuint result) { throw null; } @@ -7527,6 +7567,7 @@ public override void Write(string? s) { } public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0) { } public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] arg) { } + public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params System.ReadOnlySpan arg) { } public override System.Threading.Tasks.Task WriteAsync(char value) { throw null; } public override System.Threading.Tasks.Task WriteAsync(char[] buffer, int index, int count) { throw null; } public override System.Threading.Tasks.Task WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } @@ -7546,6 +7587,7 @@ public override void WriteLine(string? s) { } public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0) { } public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] arg) { } + public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params System.ReadOnlySpan arg) { } [System.CLSCompliantAttribute(false)] public override void WriteLine(uint value) { } public override System.Threading.Tasks.Task WriteLineAsync() { throw null; } @@ -8047,7 +8089,6 @@ public DefaultValueAttribute(object? value) { } public DefaultValueAttribute(sbyte value) { } public DefaultValueAttribute(float value) { } public DefaultValueAttribute(string? value) { } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Generic TypeConverters may require the generic types to be annotated. For example, NullableConverter requires the underlying type to be DynamicallyAccessedMembers All.")] public DefaultValueAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, string? value) { } [System.CLSCompliantAttribute(false)] public DefaultValueAttribute(ushort value) { } @@ -10113,6 +10154,7 @@ public static partial class Path public static string Combine(string path1, string path2, string path3) { throw null; } public static string Combine(string path1, string path2, string path3, string path4) { throw null; } public static string Combine(params string[] paths) { throw null; } + public static string Combine(params System.ReadOnlySpan paths) { throw null; } public static bool EndsInDirectorySeparator(System.ReadOnlySpan path) { throw null; } public static bool EndsInDirectorySeparator([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? path) { throw null; } public static bool Exists([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? path) { throw null; } @@ -10150,6 +10192,7 @@ public static partial class Path public static string Join(string? path1, string? path2, string? path3) { throw null; } public static string Join(string? path1, string? path2, string? path3, string? path4) { throw null; } public static string Join(params string?[] paths) { throw null; } + public static string Join(params System.ReadOnlySpan paths) { throw null; } public static System.ReadOnlySpan TrimEndingDirectorySeparator(System.ReadOnlySpan path) { throw null; } public static string TrimEndingDirectorySeparator(string path) { throw null; } public static bool TryJoin(System.ReadOnlySpan path1, System.ReadOnlySpan path2, System.ReadOnlySpan path3, System.Span destination, out int charsWritten) { throw null; } @@ -10316,6 +10359,7 @@ public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribut public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { } public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] arg) { } + public override void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params System.ReadOnlySpan arg) { } public override System.Threading.Tasks.Task WriteAsync(char value) { throw null; } public override System.Threading.Tasks.Task WriteAsync(char[] buffer, int index, int count) { throw null; } public override System.Threading.Tasks.Task WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } @@ -10326,6 +10370,7 @@ public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttr public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { } public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] arg) { } + public override void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params System.ReadOnlySpan arg) { } public override System.Threading.Tasks.Task WriteLineAsync() { throw null; } public override System.Threading.Tasks.Task WriteLineAsync(char value) { throw null; } public override System.Threading.Tasks.Task WriteLineAsync(char[] buffer, int index, int count) { throw null; } @@ -10443,6 +10488,7 @@ public virtual void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute public virtual void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public virtual void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { } public virtual void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] arg) { } + public virtual void Write([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params System.ReadOnlySpan arg) { } public virtual void Write(System.Text.StringBuilder? value) { } [System.CLSCompliantAttribute(false)] public virtual void Write(uint value) { } @@ -10471,6 +10517,7 @@ public virtual void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttri public virtual void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { } public virtual void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { } public virtual void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] arg) { } + public virtual void WriteLine([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params System.ReadOnlySpan arg) { } public virtual void WriteLine(System.Text.StringBuilder? value) { } [System.CLSCompliantAttribute(false)] public virtual void WriteLine(uint value) { } @@ -10789,6 +10836,8 @@ public partial interface IFloatingPointIeee754 : System.IComparable, Syst public partial interface IFloatingPoint : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointConstants, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IFloatingPoint? { static virtual TSelf Ceiling(TSelf x) { throw null; } + static virtual TInteger ConvertToInteger(TSelf value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + static virtual TInteger ConvertToIntegerNative(TSelf value) where TInteger : System.Numerics.IBinaryInteger { throw null; } static virtual TSelf Floor(TSelf x) { throw null; } int GetExponentByteCount(); int GetExponentShortestBitLength(); @@ -10897,6 +10946,7 @@ static virtual TSelf CreateTruncating(TOther value) static abstract TSelf MaxMagnitudeNumber(TSelf x, TSelf y); static abstract TSelf MinMagnitude(TSelf x, TSelf y); static abstract TSelf MinMagnitudeNumber(TSelf x, TSelf y); + static virtual TSelf MultiplyAddEstimate(TSelf left, TSelf right, TSelf addend) { throw null; } static virtual TSelf Parse(System.ReadOnlySpan utf8Text, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } static abstract TSelf Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider); static abstract TSelf Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider); @@ -11107,6 +11157,7 @@ public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types and members the loaded assembly depends on might be removed")] public static System.Reflection.Assembly LoadFrom(string assemblyFile) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types and members the loaded assembly depends on might be removed")] + [System.ObsoleteAttribute("LoadFrom with a custom AssemblyHashAlgorithm is obsolete. Use overloads without an AssemblyHashAlgorithm.", DiagnosticId = "SYSLIB0056", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public static System.Reflection.Assembly LoadFrom(string assemblyFile, byte[]? hashValue, System.Configuration.Assemblies.AssemblyHashAlgorithm hashAlgorithm) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types and members the loaded module depends on might be removed")] public System.Reflection.Module LoadModule(string moduleName, byte[]? rawModule) { throw null; } @@ -11125,6 +11176,7 @@ public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types and members the loaded assembly depends on might be removed")] [System.ObsoleteAttribute("ReflectionOnly loading is not supported and throws PlatformNotSupportedException.", DiagnosticId="SYSLIB0018", UrlFormat="https://aka.ms/dotnet-warnings/{0}")] public static System.Reflection.Assembly ReflectionOnlyLoadFrom(string assemblyFile) { throw null; } + public static void SetEntryAssembly(System.Reflection.Assembly? assembly) { throw null; } public override string ToString() { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types and members the loaded assembly depends on might be removed")] public static System.Reflection.Assembly UnsafeLoadFrom(string assemblyFile) { throw null; } @@ -13059,6 +13111,12 @@ public sealed partial class NullablePublicOnlyAttribute : System.Attribute public readonly bool IncludesInternals; public NullablePublicOnlyAttribute(bool value) { } } + [System.AttributeUsageAttribute(System.AttributeTargets.Method | System.AttributeTargets.Constructor | System.AttributeTargets.Property, AllowMultiple=false, Inherited=false)] + public sealed partial class OverloadResolutionPriorityAttribute : System.Attribute + { + public OverloadResolutionPriorityAttribute(int priority) { } + public int Priority { get { throw null; } } + } [System.AttributeUsageAttribute(System.AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)] public sealed partial class ParamCollectionAttribute : System.Attribute { @@ -13176,6 +13234,7 @@ public static void ProbeForSufficientStack() { } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Trimmer can't guarantee existence of class constructor")] public static void RunClassConstructor(System.RuntimeTypeHandle type) { } public static void RunModuleConstructor(System.ModuleHandle module) { } + public static int SizeOf(System.RuntimeTypeHandle type) { throw null; } public static bool TryEnsureSufficientExecutionStack() { throw null; } public delegate void CleanupCode(object? userData, bool exceptionThrown); public delegate void TryCode(object? userData); @@ -13299,7 +13358,7 @@ public static partial class Unsafe [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute("o")] public static T? As(object? o) where T : class? { throw null; } public static ref TTo As(ref TFrom source) { throw null; } - public static TTo BitCast(TFrom source) where TFrom : struct where TTo : struct { throw null; } + public static TTo BitCast(TFrom source) { throw null; } public static System.IntPtr ByteOffset([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T origin, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T target) { throw null; } [System.CLSCompliantAttribute(false)] public static void CopyBlock(ref byte destination, ref readonly byte source, uint byteCount) { } @@ -14915,19 +14974,25 @@ public StringBuilder(string? value, int startIndex, int length, int capacity) { public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { throw null; } public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { throw null; } public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] args) { throw null; } + public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params System.ReadOnlySpan args) { throw null; } public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, System.Text.CompositeFormat format, params object?[] args) { throw null; } - public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, System.Text.CompositeFormat format, System.ReadOnlySpan args) { throw null; } + public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, System.Text.CompositeFormat format, params System.ReadOnlySpan args) { throw null; } public System.Text.StringBuilder AppendFormat([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0) { throw null; } public System.Text.StringBuilder AppendFormat([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1) { throw null; } public System.Text.StringBuilder AppendFormat([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) { throw null; } public System.Text.StringBuilder AppendFormat([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params object?[] args) { throw null; } + public System.Text.StringBuilder AppendFormat([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("CompositeFormat")] string format, params System.ReadOnlySpan args) { throw null; } public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, System.Text.CompositeFormat format, TArg0 arg0) { throw null; } public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, System.Text.CompositeFormat format, TArg0 arg0, TArg1 arg1) { throw null; } public System.Text.StringBuilder AppendFormat(System.IFormatProvider? provider, System.Text.CompositeFormat format, TArg0 arg0, TArg1 arg1, TArg2 arg2) { throw null; } public System.Text.StringBuilder AppendJoin(char separator, params object?[] values) { throw null; } public System.Text.StringBuilder AppendJoin(char separator, params string?[] values) { throw null; } + public System.Text.StringBuilder AppendJoin(char separator, params System.ReadOnlySpan values) { throw null; } + public System.Text.StringBuilder AppendJoin(char separator, params System.ReadOnlySpan values) { throw null; } public System.Text.StringBuilder AppendJoin(string? separator, params object?[] values) { throw null; } public System.Text.StringBuilder AppendJoin(string? separator, params string?[] values) { throw null; } + public System.Text.StringBuilder AppendJoin(string? separator, params System.ReadOnlySpan values) { throw null; } + public System.Text.StringBuilder AppendJoin(string? separator, params System.ReadOnlySpan values) { throw null; } public System.Text.StringBuilder AppendJoin(char separator, System.Collections.Generic.IEnumerable values) { throw null; } public System.Text.StringBuilder AppendJoin(string? separator, System.Collections.Generic.IEnumerable values) { throw null; } public System.Text.StringBuilder AppendLine() { throw null; } @@ -15103,6 +15168,7 @@ public void CancelAfter(System.TimeSpan delay) { } public System.Threading.Tasks.Task CancelAsync() { throw null; } public static System.Threading.CancellationTokenSource CreateLinkedTokenSource(System.Threading.CancellationToken token) { throw null; } public static System.Threading.CancellationTokenSource CreateLinkedTokenSource(System.Threading.CancellationToken token1, System.Threading.CancellationToken token2) { throw null; } + public static System.Threading.CancellationTokenSource CreateLinkedTokenSource(params System.ReadOnlySpan tokens) { throw null; } public static System.Threading.CancellationTokenSource CreateLinkedTokenSource(params System.Threading.CancellationToken[] tokens) { throw null; } public void Dispose() { } protected virtual void Dispose(bool disposing) { } @@ -15118,7 +15184,6 @@ public enum LazyThreadSafetyMode PublicationOnly = 1, ExecutionAndPublication = 2, } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] public sealed partial class Lock { public Lock() { } @@ -15307,6 +15372,10 @@ public void Wait(System.Threading.CancellationToken cancellationToken) { } public bool Wait(System.TimeSpan timeout) { throw null; } public bool Wait(System.TimeSpan timeout, System.Threading.CancellationToken cancellationToken) { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public static void WaitAll(System.Collections.Generic.IEnumerable tasks, System.Threading.CancellationToken cancellationToken = default) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + public static void WaitAll(params System.ReadOnlySpan tasks) { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public static void WaitAll(params System.Threading.Tasks.Task[] tasks) { } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public static bool WaitAll(System.Threading.Tasks.Task[] tasks, int millisecondsTimeout) { throw null; } @@ -15327,14 +15396,18 @@ public static void WaitAll(System.Threading.Tasks.Task[] tasks, System.Threading public System.Threading.Tasks.Task WaitAsync(System.TimeSpan timeout, System.TimeProvider timeProvider) { throw null; } public System.Threading.Tasks.Task WaitAsync(System.TimeSpan timeout, System.TimeProvider timeProvider, System.Threading.CancellationToken cancellationToken) { throw null; } public static System.Threading.Tasks.Task WhenAll(System.Collections.Generic.IEnumerable tasks) { throw null; } + public static System.Threading.Tasks.Task WhenAll(params System.ReadOnlySpan tasks) { throw null; } public static System.Threading.Tasks.Task WhenAll(params System.Threading.Tasks.Task[] tasks) { throw null; } public static System.Threading.Tasks.Task WhenAll(System.Collections.Generic.IEnumerable> tasks) { throw null; } + public static System.Threading.Tasks.Task WhenAll(params System.ReadOnlySpan> tasks) { throw null; } public static System.Threading.Tasks.Task WhenAll(params System.Threading.Tasks.Task[] tasks) { throw null; } public static System.Threading.Tasks.Task WhenAny(System.Collections.Generic.IEnumerable tasks) { throw null; } public static System.Threading.Tasks.Task WhenAny(System.Threading.Tasks.Task task1, System.Threading.Tasks.Task task2) { throw null; } + public static System.Threading.Tasks.Task WhenAny(params System.ReadOnlySpan tasks) { throw null; } public static System.Threading.Tasks.Task WhenAny(params System.Threading.Tasks.Task[] tasks) { throw null; } public static System.Threading.Tasks.Task> WhenAny(System.Collections.Generic.IEnumerable> tasks) { throw null; } public static System.Threading.Tasks.Task> WhenAny(System.Threading.Tasks.Task task1, System.Threading.Tasks.Task task2) { throw null; } + public static System.Threading.Tasks.Task> WhenAny(params System.ReadOnlySpan> tasks) { throw null; } public static System.Threading.Tasks.Task> WhenAny(params System.Threading.Tasks.Task[] tasks) { throw null; } public static System.Collections.Generic.IAsyncEnumerable WhenEach(System.Collections.Generic.IEnumerable tasks) { throw null; } public static System.Collections.Generic.IAsyncEnumerable WhenEach(params System.Threading.Tasks.Task[] tasks) { throw null; } diff --git a/src/libraries/System.Runtime/tests/System.Buffers.Tests/ArrayPool/UnitTests.cs b/src/libraries/System.Runtime/tests/System.Buffers.Tests/ArrayPool/UnitTests.cs index d58a8838d90a..70f38687102d 100644 --- a/src/libraries/System.Runtime/tests/System.Buffers.Tests/ArrayPool/UnitTests.cs +++ b/src/libraries/System.Runtime/tests/System.Buffers.Tests/ArrayPool/UnitTests.cs @@ -272,7 +272,7 @@ public static void RentingReturningThenRentingABufferShouldNotAllocate() Assert.Equal(id, bt.GetHashCode()); } - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupportedOrBrowserBackgroundExec))] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [MemberData(nameof(BytePoolInstances))] public static void CanRentManySizedBuffers(ArrayPool pool) { diff --git a/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.regclass.cs b/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.regclass.cs index 4ab409341052..6cf350356975 100644 --- a/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.regclass.cs +++ b/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.regclass.cs @@ -714,7 +714,9 @@ public static void CalledFrom_UsingExpression() { using (StreamWriter sw = new StreamWriter(sm)) { +#pragma warning disable CS9220 // One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. sw.WriteLine(mc.Method_ReturnString('a')); +#pragma warning restore CS9220 sw.Flush(); sm.Position = 0; using (StreamReader sr = new StreamReader(sm, (bool)mc.Method_ReturnBool())) diff --git a/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Operators.basic.cs b/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Operators.basic.cs index 1230648a1f44..5d5933aaf4ee 100644 --- a/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Operators.basic.cs +++ b/src/libraries/System.Runtime/tests/System.Dynamic.Runtime.Tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Operators.basic.cs @@ -1169,7 +1169,9 @@ public static void ExecPositiveTest(dynamic dobj, Type exp_type, T exp_underv } else { +#pragma warning disable CS9220 // One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. System.Console.WriteLine("Got invalid result when testing {0}: {1}[{2}]", tip, dr, dr.GetType()); +#pragma warning restore CS9220 } } catch (Exception ex) @@ -1186,7 +1188,9 @@ public static void ExecNegativeTestWithBadOps(dynamic dobj, string[] exp_msg, st try { dynamic dr = test(dobj); +#pragma warning disable CS9220 // One or more overloads of method having non-array params collection parameter might be applicable only in expanded form which is not supported during dynamic dispatch. System.Console.WriteLine("Got invalid result when testing {0}: {1}[{2}]", tip, dr, dr.GetType()); +#pragma warning restore CS9220 } catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex) { diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Calendars.Tests/Hybrid/System.Globalization.Calendars.Hybrid.WASM.Tests.csproj b/src/libraries/System.Runtime/tests/System.Globalization.Calendars.Tests/Hybrid/System.Globalization.Calendars.Hybrid.WASM.Tests.csproj index 5b8983637640..7e10ef4ac1dd 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Calendars.Tests/Hybrid/System.Globalization.Calendars.Hybrid.WASM.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Globalization.Calendars.Tests/Hybrid/System.Globalization.Calendars.Hybrid.WASM.Tests.csproj @@ -4,6 +4,14 @@ true true true + + + + WasmTestOnChrome + $(TestArchiveRoot)browserornodejs/ + $(TestArchiveTestsRoot)$(OSPlatformConfig)/ + $(DefineConstants);TARGET_BROWSER + true diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/CultureInfo/CultureInfoEnglishName.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/CultureInfo/CultureInfoEnglishName.cs index 0868869622a6..8407726cc1e7 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/CultureInfo/CultureInfoEnglishName.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/CultureInfo/CultureInfoEnglishName.cs @@ -9,9 +9,8 @@ namespace System.Globalization.Tests public class CultureInfoEnglishName { // Android has its own ICU, which doesn't 100% map to UsingLimitedCultures - // Browser uses JS to get the NativeName that is missing in ICU (in the singlethreaded runtime only) - public static bool SupportFullGlobalizationData => - (!PlatformDetection.IsWasi || PlatformDetection.IsHybridGlobalizationOnApplePlatform) && !PlatformDetection.IsWasmThreadingSupported; + // Browser uses JS to get the NativeName that is missing in ICU + public static bool SupportFullGlobalizationData => !PlatformDetection.IsWasi || PlatformDetection.IsHybridGlobalizationOnApplePlatform; public static IEnumerable EnglishName_TestData() { diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/CultureInfo/CultureInfoNativeName.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/CultureInfo/CultureInfoNativeName.cs index c61f8364e20c..ac2195cec5db 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/CultureInfo/CultureInfoNativeName.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/CultureInfo/CultureInfoNativeName.cs @@ -9,9 +9,8 @@ namespace System.Globalization.Tests public class CultureInfoNativeName { // Android has its own ICU, which doesn't 100% map to UsingLimitedCultures - // Browser uses JS to get the NativeName that is missing in ICU (in the singlethreaded runtime only) - private static bool SupportFullIcuResources => - (!PlatformDetection.IsWasi || PlatformDetection.IsHybridGlobalizationOnApplePlatform) && !PlatformDetection.IsWasmThreadingSupported; + // Browser uses JS to get the NativeName that is missing in ICU + private static bool SupportFullIcuResources => !PlatformDetection.IsWasi || PlatformDetection.IsHybridGlobalizationOnApplePlatform; public static IEnumerable NativeName_TestData() { diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoAMDesignator.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoAMDesignator.cs index 0eeb6d9c4a73..3bc6ad88fb34 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoAMDesignator.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoAMDesignator.cs @@ -17,199 +17,202 @@ public void AMDesignator_GetInvariantInfo_ReturnsExpected() public static IEnumerable AMDesignator_Get_TestData_HybridGlobalization() { // see the comments on the right to check the non-Hybrid result, if it differs - yield return new object[] { new CultureInfo("ar-SA").DateTimeFormat, "ص" }; - yield return new object[] { new CultureInfo("am-ET").DateTimeFormat, "ጥዋት" }; - yield return new object[] { new CultureInfo("bg-BG").DateTimeFormat, "пр.об." }; - yield return new object[] { new CultureInfo("bn-BD").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("bn-IN").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("ca-AD").DateTimeFormat, "a.\u00A0m." }; - yield return new object[] { new CultureInfo("ca-ES").DateTimeFormat, "a.\u00A0m." }; - yield return new object[] { new CultureInfo("cs-CZ").DateTimeFormat, "dop." }; - yield return new object[] { new CultureInfo("da-DK").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("de-AT").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("de-BE").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("de-CH").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("de-DE").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("de-IT").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("de-LI").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("de-LU").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("el-CY").DateTimeFormat, "π.μ." }; - yield return new object[] { new CultureInfo("el-GR").DateTimeFormat, "π.μ." }; - yield return new object[] { new CultureInfo("en-AE").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("en-AG").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-AI").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-AS").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("en-AT").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-AU").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-BB").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-BE").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-BI").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("en-BM").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-BS").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-BW").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-BZ").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-CA").DateTimeFormat, "a.m." }; - yield return new object[] { new CultureInfo("en-CC").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-CH").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-CK").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-CM").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-CX").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-CY").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-DE").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-DK").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-DM").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-ER").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-FI").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-FJ").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-FK").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-FM").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-GB").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-GD").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-GG").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-GH").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-GI").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-GM").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-GU").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("en-GY").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-HK").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-IE").DateTimeFormat, "a.m." }; - yield return new object[] { new CultureInfo("en-IL").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-IM").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-IN").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-IO").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-JE").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-JM").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-KE").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-KI").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-KN").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-KY").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-LC").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-LR").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-LS").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-MG").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-MH").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("en-MO").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-MP").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("en-MS").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-MT").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-MU").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-MW").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-MY").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-NA").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-NF").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-NG").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-NL").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-NR").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-NU").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-NZ").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-PG").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-PH").DateTimeFormat, "AM" }; // am - yield return new object[] { new CultureInfo("en-PK").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-PN").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-PR").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("en-PW").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-RW").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-SB").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-SC").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-SD").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-SE").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-SG").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-SH").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-SI").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-SL").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-SS").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-SX").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-SZ").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-TC").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-TK").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-TO").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-TT").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-TV").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-TZ").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-UG").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-UM").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("en-US").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("en-VC").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-VG").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-VI").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("en-VU").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-WS").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-ZA").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-ZM").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("en-ZW").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("es-419").DateTimeFormat, "a.\u00A0m." }; - yield return new object[] { new CultureInfo("es-ES").DateTimeFormat, "a.\u00A0m." }; - yield return new object[] { new CultureInfo("es-MX").DateTimeFormat, "a.\u00A0m." }; - yield return new object[] { new CultureInfo("et-EE").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("fa-IR").DateTimeFormat, "قبل‌ازظهر" }; - yield return new object[] { new CultureInfo("fi-FI").DateTimeFormat, "ap." }; - yield return new object[] { new CultureInfo("fil-PH").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("fr-BE").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("fr-CA").DateTimeFormat, "a.m." }; - yield return new object[] { new CultureInfo("fr-CH").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("fr-FR").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("gu-IN").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("he-IL").DateTimeFormat, "לפנה״צ" }; - yield return new object[] { new CultureInfo("hi-IN").DateTimeFormat, "am" }; - yield return new object[] { new CultureInfo("hr-BA").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("hr-HR").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("hu-HU").DateTimeFormat, "de." }; - yield return new object[] { new CultureInfo("id-ID").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("it-CH").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("it-IT").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("ja-JP").DateTimeFormat, "午前" }; - yield return new object[] { new CultureInfo("kn-IN").DateTimeFormat, "ಪೂರ್ವಾಹ್ನ" }; - yield return new object[] { new CultureInfo("ko-KR").DateTimeFormat, "오전" }; - yield return new object[] { new CultureInfo("lt-LT").DateTimeFormat, "priešpiet" }; - yield return new object[] { new CultureInfo("lv-LV").DateTimeFormat, "priekšpusdienā" }; - yield return new object[] { new CultureInfo("ml-IN").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("mr-IN").DateTimeFormat, "AM" }; // म.पू. - yield return new object[] { new CultureInfo("ms-BN").DateTimeFormat, "PG" }; - yield return new object[] { new CultureInfo("ms-MY").DateTimeFormat, "PG" }; - yield return new object[] { new CultureInfo("ms-SG").DateTimeFormat, "PG" }; - yield return new object[] { new CultureInfo("nb-NO").DateTimeFormat, "a.m." }; - yield return new object[] { new CultureInfo("no").DateTimeFormat, "a.m." }; - yield return new object[] { new CultureInfo("no-NO").DateTimeFormat, "a.m." }; - yield return new object[] { new CultureInfo("nl-AW").DateTimeFormat, "a.m." }; - yield return new object[] { new CultureInfo("nl-BE").DateTimeFormat, "a.m." }; - yield return new object[] { new CultureInfo("nl-NL").DateTimeFormat, "a.m." }; - yield return new object[] { new CultureInfo("pl-PL").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("pt-BR").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("pt-PT").DateTimeFormat, "da manhã" }; - yield return new object[] { new CultureInfo("ro-RO").DateTimeFormat, "a.m." }; - yield return new object[] { new CultureInfo("ru-RU").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("sk-SK").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("sl-SI").DateTimeFormat, "dop." }; - yield return new object[] { new CultureInfo("sr-Cyrl-RS").DateTimeFormat, "AM" }; // пре подне - yield return new object[] { new CultureInfo("sr-Latn-RS").DateTimeFormat, "AM" }; // pre podne - yield return new object[] { new CultureInfo("sv-AX").DateTimeFormat, "fm" }; - yield return new object[] { new CultureInfo("sv-SE").DateTimeFormat, "fm" }; - yield return new object[] { new CultureInfo("sw-CD").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("sw-KE").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("sw-TZ").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("sw-UG").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("ta-IN").DateTimeFormat, "முற்பகல்" }; - yield return new object[] { new CultureInfo("ta-LK").DateTimeFormat, "முற்பகல்" }; - yield return new object[] { new CultureInfo("ta-MY").DateTimeFormat, "முற்பகல்" }; - yield return new object[] { new CultureInfo("ta-SG").DateTimeFormat, "முற்பகல்" }; - yield return new object[] { new CultureInfo("te-IN").DateTimeFormat, "AM" }; - yield return new object[] { new CultureInfo("th-TH").DateTimeFormat, "ก่อนเที่ยง" }; - yield return new object[] { new CultureInfo("tr-CY").DateTimeFormat, "ÖÖ" }; - yield return new object[] { new CultureInfo("tr-TR").DateTimeFormat, "ÖÖ" }; - yield return new object[] { new CultureInfo("uk-UA").DateTimeFormat, "дп" }; - yield return new object[] { new CultureInfo("vi-VN").DateTimeFormat, "SA" }; - yield return new object[] { new CultureInfo("zh-CN").DateTimeFormat, "上午" }; - yield return new object[] { new CultureInfo("zh-Hans-HK").DateTimeFormat, "上午" }; - yield return new object[] { new CultureInfo("zh-SG").DateTimeFormat, "上午" }; - yield return new object[] { new CultureInfo("zh-HK").DateTimeFormat, "上午" }; - yield return new object[] { new CultureInfo("zh-TW").DateTimeFormat, "上午" }; + yield return new object[] { "ar-SA", "ص" }; + yield return new object[] { "am-ET", "ጥዋት" }; + yield return new object[] { "bg-BG", "пр.об." }; + yield return new object[] { "bn-BD", "AM" }; + yield return new object[] { "bn-IN", "AM" }; + yield return new object[] { "ca-AD", "a.\u00A0m." }; + yield return new object[] { "ca-ES", "a.\u00A0m." }; + yield return new object[] { "cs-CZ", "dop." }; + yield return new object[] { "da-DK", "AM" }; + yield return new object[] { "de-AT", "AM" }; + yield return new object[] { "de-BE", "AM" }; + yield return new object[] { "de-CH", "AM" }; + yield return new object[] { "de-DE", "AM" }; + yield return new object[] { "de-IT", "AM" }; + yield return new object[] { "de-LI", "AM" }; + yield return new object[] { "de-LU", "AM" }; + yield return new object[] { "el-CY", "π.μ." }; + yield return new object[] { "el-GR", "π.μ." }; + yield return new object[] { "en-AE", "AM" }; + yield return new object[] { "en-AG", "am" }; + yield return new object[] { "en-AI", "am" }; + yield return new object[] { "en-AS", "AM" }; + yield return new object[] { "en-AT", "am" }; + yield return new object[] { "en-AU", "am" }; + yield return new object[] { "en-BB", "am" }; + yield return new object[] { "en-BE", "am" }; + yield return new object[] { "en-BI", "AM" }; + yield return new object[] { "en-BM", "am" }; + yield return new object[] { "en-BS", "am" }; + yield return new object[] { "en-BW", "am" }; + yield return new object[] { "en-BZ", "am" }; + yield return new object[] { "en-CA", "a.m." }; + yield return new object[] { "en-CC", "am" }; + yield return new object[] { "en-CH", "am" }; + yield return new object[] { "en-CK", "am" }; + yield return new object[] { "en-CM", "am" }; + yield return new object[] { "en-CX", "am" }; + yield return new object[] { "en-CY", "am" }; + yield return new object[] { "en-DE", "am" }; + yield return new object[] { "en-DK", "am" }; + yield return new object[] { "en-DM", "am" }; + yield return new object[] { "en-ER", "am" }; + yield return new object[] { "en-FI", "am" }; + yield return new object[] { "en-FJ", "am" }; + yield return new object[] { "en-FK", "am" }; + yield return new object[] { "en-FM", "am" }; + yield return new object[] { "en-GB", "am" }; + yield return new object[] { "en-GD", "am" }; + yield return new object[] { "en-GG", "am" }; + yield return new object[] { "en-GH", "am" }; + yield return new object[] { "en-GI", "am" }; + yield return new object[] { "en-GM", "am" }; + yield return new object[] { "en-GU", "AM" }; + yield return new object[] { "en-GY", "am" }; + yield return new object[] { "en-HK", "am" }; + yield return new object[] { "en-IE", "a.m." }; + yield return new object[] { "en-IL", "am" }; + yield return new object[] { "en-IM", "am" }; + yield return new object[] { "en-IN", "am" }; + yield return new object[] { "en-IO", "am" }; + yield return new object[] { "en-JE", "am" }; + yield return new object[] { "en-JM", "am" }; + yield return new object[] { "en-KE", "am" }; + yield return new object[] { "en-KI", "am" }; + yield return new object[] { "en-KN", "am" }; + yield return new object[] { "en-KY", "am" }; + yield return new object[] { "en-LC", "am" }; + yield return new object[] { "en-LR", "am" }; + yield return new object[] { "en-LS", "am" }; + yield return new object[] { "en-MG", "am" }; + yield return new object[] { "en-MH", "AM" }; + yield return new object[] { "en-MO", "am" }; + yield return new object[] { "en-MP", "AM" }; + yield return new object[] { "en-MS", "am" }; + yield return new object[] { "en-MT", "am" }; + yield return new object[] { "en-MU", "am" }; + yield return new object[] { "en-MW", "am" }; + yield return new object[] { "en-MY", "am" }; + yield return new object[] { "en-NA", "am" }; + yield return new object[] { "en-NF", "am" }; + yield return new object[] { "en-NG", "am" }; + yield return new object[] { "en-NL", "am" }; + yield return new object[] { "en-NR", "am" }; + yield return new object[] { "en-NU", "am" }; + yield return new object[] { "en-NZ", "am" }; + yield return new object[] { "en-PG", "am" }; + yield return new object[] { "en-PH", "AM" }; // am + yield return new object[] { "en-PK", "am" }; + yield return new object[] { "en-PN", "am" }; + yield return new object[] { "en-PR", "AM" }; + yield return new object[] { "en-PW", "am" }; + yield return new object[] { "en-RW", "am" }; + yield return new object[] { "en-SB", "am" }; + yield return new object[] { "en-SC", "am" }; + yield return new object[] { "en-SD", "am" }; + yield return new object[] { "en-SE", "am" }; + yield return new object[] { "en-SG", "am" }; + yield return new object[] { "en-SH", "am" }; + yield return new object[] { "en-SI", "am" }; + yield return new object[] { "en-SL", "am" }; + yield return new object[] { "en-SS", "am" }; + yield return new object[] { "en-SX", "am" }; + yield return new object[] { "en-SZ", "am" }; + yield return new object[] { "en-TC", "am" }; + yield return new object[] { "en-TK", "am" }; + yield return new object[] { "en-TO", "am" }; + yield return new object[] { "en-TT", "am" }; + yield return new object[] { "en-TV", "am" }; + yield return new object[] { "en-TZ", "am" }; + yield return new object[] { "en-UG", "am" }; + yield return new object[] { "en-UM", "AM" }; + yield return new object[] { "en-US", "AM" }; + yield return new object[] { "en-VC", "am" }; + yield return new object[] { "en-VG", "am" }; + yield return new object[] { "en-VI", "AM" }; + yield return new object[] { "en-VU", "am" }; + yield return new object[] { "en-WS", "am" }; + yield return new object[] { "en-ZA", "am" }; + yield return new object[] { "en-ZM", "am" }; + yield return new object[] { "en-ZW", "am" }; + string latinAmericaSpanishAMDesignator = PlatformDetection.IsFirefox ? "a.\u00A0m." : "a.m."; + yield return new object[] { "es-419", latinAmericaSpanishAMDesignator }; + yield return new object[] { "es-ES", "a.\u00A0m." }; + yield return new object[] { "es-MX", latinAmericaSpanishAMDesignator }; + yield return new object[] { "et-EE", "AM" }; + yield return new object[] { "fa-IR", "قبل‌ازظهر" }; + yield return new object[] { "fi-FI", "ap." }; + yield return new object[] { "fil-PH", "AM" }; + yield return new object[] { "fr-BE", "AM" }; + yield return new object[] { "fr-CA", "a.m." }; + yield return new object[] { "fr-CH", "AM" }; + yield return new object[] { "fr-FR", "AM" }; + yield return new object[] { "gu-IN", "AM" }; + yield return new object[] { "he-IL", "לפנה״צ" }; + yield return new object[] { "hi-IN", "am" }; + yield return new object[] { "hr-BA", "AM" }; + yield return new object[] { "hr-HR", "AM" }; + yield return new object[] { "hu-HU", "de." }; + yield return new object[] { "id-ID", "AM" }; + yield return new object[] { "it-CH", "AM" }; + yield return new object[] { "it-IT", "AM" }; + yield return new object[] { "ja-JP", "午前" }; + yield return new object[] { "kn-IN", "ಪೂರ್ವಾಹ್ನ" }; + yield return new object[] { "ko-KR", "오전" }; + yield return new object[] { "lt-LT", "priešpiet" }; + yield return new object[] { "lv-LV", "priekšpusdienā" }; + yield return new object[] { "ml-IN", "AM" }; + yield return new object[] { "mr-IN", "AM" }; // म.पू. + yield return new object[] { "ms-BN", "PG" }; + yield return new object[] { "ms-MY", "PG" }; + yield return new object[] { "ms-SG", "PG" }; + yield return new object[] { "nb-NO", "a.m." }; + yield return new object[] { "no", "a.m." }; + yield return new object[] { "no-NO", "a.m." }; + yield return new object[] { "nl-AW", "a.m." }; + yield return new object[] { "nl-BE", "a.m." }; + yield return new object[] { "nl-NL", "a.m." }; + yield return new object[] { "pl-PL", "AM" }; + yield return new object[] { "pt-BR", "AM" }; + yield return new object[] { "pt-PT", "da manhã" }; + yield return new object[] { "ro-RO", "a.m." }; + yield return new object[] { "ru-RU", "AM" }; + yield return new object[] { "sk-SK", "AM" }; + yield return new object[] { "sl-SI", "dop." }; + yield return new object[] { "sr-Cyrl-RS", "AM" }; // пре подне + yield return new object[] { "sr-Latn-RS", "AM" }; // pre podne + yield return new object[] { "sv-AX", "fm" }; + yield return new object[] { "sv-SE", "fm" }; + yield return new object[] { "sw-CD", "AM" }; + yield return new object[] { "sw-KE", "AM" }; + yield return new object[] { "sw-TZ", "AM" }; + yield return new object[] { "sw-UG", "AM" }; + string tamilAMDesignator = PlatformDetection.IsFirefox ? "முற்பகல்" : "AM"; // முற்பகல் + yield return new object[] { "ta-IN", tamilAMDesignator }; + yield return new object[] { "ta-LK", tamilAMDesignator }; + yield return new object[] { "ta-MY", tamilAMDesignator }; + yield return new object[] { "ta-SG", tamilAMDesignator }; + yield return new object[] { "te-IN", "AM" }; + yield return new object[] { "th-TH", "ก่อนเที่ยง" }; + yield return new object[] { "tr-CY", "ÖÖ" }; + yield return new object[] { "tr-TR", "ÖÖ" }; + yield return new object[] { "uk-UA", "дп" }; + yield return new object[] { "vi-VN", "SA" }; + yield return new object[] { "zh-CN", "上午" }; + yield return new object[] { "zh-Hans-HK", "上午" }; + yield return new object[] { "zh-SG", "上午" }; + yield return new object[] { "zh-HK", "上午" }; + yield return new object[] { "zh-TW", "上午" }; } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsHybridGlobalizationOnBrowser))] [MemberData(nameof(AMDesignator_Get_TestData_HybridGlobalization))] - public void AMDesignator_Get_ReturnsExpected_HybridGlobalization(DateTimeFormatInfo format, string value) + public void AMDesignator_Get_ReturnsExpected_HybridGlobalization(string cultureName, string expected) { - Assert.Equal(value, format.AMDesignator); + var format = new CultureInfo(cultureName).DateTimeFormat; + Assert.True(expected == format.AMDesignator, $"Failed for culture: {cultureName}. Expected: {expected}, Actual: {format.AMDesignator}"); } [Theory] diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoAbbreviatedMonthGenitiveNames.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoAbbreviatedMonthGenitiveNames.cs index 0330708cdc97..e7a66fa2f83a 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoAbbreviatedMonthGenitiveNames.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoAbbreviatedMonthGenitiveNames.cs @@ -12,7 +12,16 @@ public static IEnumerable AbbreviatedMonthGenitiveNames_Get_TestData_H { // see the comments on the right to check the non-Hybrid result, if it differs yield return new object[] { "ar-SA", new string[] { "محرم", "صفر", "ربيع الأول", "ربيع الآخر", "جمادى الأولى", "جمادى الآخرة", "رجب", "شعبان", "رمضان", "شوال", "ذو القعدة", "ذو الحجة", "" } }; - yield return new object[] { "am-ET", new string[] { "ጃንዩ", "ፌብሩ", "ማርች", "ኤፕሪ", "ሜይ", "ጁን", "ጁላይ", "ኦገስ", "ሴፕቴ", "ኦክቶ", "ኖቬም", "ዲሴም", "" } }; + if (PlatformDetection.IsFirefox) + { + yield return new object[] { "am-ET", new string[] { "ጃንዩ", "ፌብሩ", "ማርች", "ኤፕሪ", "ሜይ", "ጁን", "ጁላይ", "ኦገስ", "ሴፕቴ", "ኦክቶ", "ኖቬም", "ዲሴም", "" } }; + yield return new object[] { "es-MX", new string[] { "ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sept", "oct", "nov", "dic", "" } }; // "ene.", "feb.", "mar.", "abr.", "may.", "jun.", "jul.", "ago.", "sep.", "oct.", "nov.", "dic.", "" + } + else + { + yield return new object[] { "am-ET", new string[] { "ጃን", "ፌብ", "ማርች", "ኤፕሪ", "ሜይ", "ጁን", "ጁላይ", "ኦገስ", "ሴፕቴ", "ኦክቶ", "ኖቬም", "ዲሴም", "" } }; // "ጃንዩ", "ፌብሩ", "ማርች", "ኤፕሪ", "ሜይ", "ጁን", "ጁላይ", "ኦገስ", "ሴፕቴ", "ኦክቶ", "ኖቬም", "ዲሴም", "" + yield return new object[] { "es-MX", new string[] { "ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic", "" } }; // "ene.", "feb.", "mar.", "abr.", "may.", "jun.", "jul.", "ago.", "sep.", "oct.", "nov.", "dic.", "" + } yield return new object[] { "bg-BG", new string[] { "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "" } }; //"яну", "фев", "март", "апр", "май", "юни", "юли", "авг", "сеп", "окт", "ное", "дек", "" yield return new object[] { "bn-BD", new string[] { "জানু", "ফেব", "মার্চ", "এপ্রি", "মে", "জুন", "জুল", "আগ", "সেপ", "অক্টো", "নভে", "ডিসে", "" } }; // "জানু", "ফেব", "মার্চ", "এপ্রিল", "মে", "জুন", "জুলাই", "আগস্ট", "সেপ্টেম্বর", "অক্টোবর", "নভেম্বর", "ডিসেম্বর", "" yield return new object[] { "bn-IN", new string[] { "জানু", "ফেব", "মার্চ", "এপ্রি", "মে", "জুন", "জুল", "আগ", "সেপ্টেঃ", "অক্টোঃ", "নভেঃ", "ডিসেঃ", "" } }; // "জানু", "ফেব", "মার্চ", "এপ্রিল", "মে", "জুন", "জুলাই", "আগস্ট", "সেপ্টেম্বর", "অক্টোবর", "নভেম্বর", "ডিসেম্বর", "" @@ -133,7 +142,6 @@ public static IEnumerable AbbreviatedMonthGenitiveNames_Get_TestData_H yield return new object[] { "en-ZW", new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "" } }; // "Sep" yield return new object[] { "es-419", new string[] { "ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sept", "oct", "nov", "dic", "" } }; // "ene.", "feb.", "mar.", "abr.", "may.", "jun.", "jul.", "ago.", "sep.", "oct.", "nov.", "dic.", "" yield return new object[] { "es-ES", new string[] { "ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sept", "oct", "nov", "dic", "" } }; // "ene.", "feb.", "mar.", "abr.", "may.", "jun.", "jul.", "ago.", "sep.", "oct.", "nov.", "dic.", "" - yield return new object[] { "es-MX", new string[] { "ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sept", "oct", "nov", "dic", "" } }; // "ene.", "feb.", "mar.", "abr.", "may.", "jun.", "jul.", "ago.", "sep.", "oct.", "nov.", "dic.", "" yield return new object[] { "et-EE", new string[] { "jaan", "veebr", "märts", "apr", "mai", "juuni", "juuli", "aug", "sept", "okt", "nov", "dets", "" } }; yield return new object[] { "fa-IR", new string[] { "فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند", "" } }; yield return new object[] { "fi-FI", new string[] { "tammik.", "helmik.", "maalisk.", "huhtik.", "toukok.", "kesäk.", "heinäk.", "elok.", "syysk.", "lokak.", "marrask.", "jouluk.", "" } }; @@ -192,7 +200,8 @@ public static IEnumerable AbbreviatedMonthGenitiveNames_Get_TestData_H yield return new object[] { "tr-CY", new string[] { "Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara", "" } }; yield return new object[] { "tr-TR", new string[] { "Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara", "" } }; yield return new object[] { "uk-UA", new string[] { "січ.", "лют.", "бер.", "квіт.", "трав.", "черв.", "лип.", "серп.", "вер.", "жовт.", "лист.", "груд.", "" } }; - yield return new object[] { "vi-VN", new string[] { "Thg 1", "Thg 2", "Thg 3", "Thg 4", "Thg 5", "Thg 6", "Thg 7", "Thg 8", "Thg 9", "Thg 10", "Thg 11", "Thg 12", "" } }; // thg + string vietnameseAbbrMonth = PlatformDetection.IsFirefox ? "Thg" : "Tháng"; // thg + yield return new object[] { "vi-VN", new string[] { $"{vietnameseAbbrMonth} 1", $"{vietnameseAbbrMonth} 2", $"{vietnameseAbbrMonth} 3", $"{vietnameseAbbrMonth} 4", $"{vietnameseAbbrMonth} 5", $"{vietnameseAbbrMonth} 6", $"{vietnameseAbbrMonth} 7", $"{vietnameseAbbrMonth} 8", $"{vietnameseAbbrMonth} 9", $"{vietnameseAbbrMonth} 10", $"{vietnameseAbbrMonth} 11", $"{vietnameseAbbrMonth} 12", "" } }; yield return new object[] { "zh-CN", new string[] { "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月", "" } }; yield return new object[] { "zh-Hans-HK", new string[] { "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月", "" } }; yield return new object[] { "zh-SG", new string[] { "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月", "" } }; diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoAbbreviatedMonthNames.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoAbbreviatedMonthNames.cs index 4687babcb259..186977451db4 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoAbbreviatedMonthNames.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoAbbreviatedMonthNames.cs @@ -32,7 +32,22 @@ public static IEnumerable AbbreviatedMonthNames_Get_TestData_HybridGlo { // see the comments on the right to check the non-Hybrid result, if it differs yield return new object[] { "ar-SA", new string[] { "محرم", "صفر", "ربيع الأول", "ربيع الآخر", "جمادى الأولى", "جمادى الآخرة", "رجب", "شعبان", "رمضان", "شوال", "ذو القعدة", "ذو الحجة", "" } }; - yield return new object[] { "am-ET", new string[] { "ጃንዩ", "ፌብሩ", "ማርች", "ኤፕሪ", "ሜይ", "ጁን", "ጁላይ", "ኦገስ", "ሴፕቴ", "ኦክቶ", "ኖቬም", "ዲሴም", "" } }; + if (PlatformDetection.IsFirefox) + { + yield return new object[] { "am-ET", new string[] { "ጃንዩ", "ፌብሩ", "ማርች", "ኤፕሪ", "ሜይ", "ጁን", "ጁላይ", "ኦገስ", "ሴፕቴ", "ኦክቶ", "ኖቬም", "ዲሴም", "" } }; + yield return new object[] { "en-AU", new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "" } }; + yield return new object[] { "es-MX", new string[] { "ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sept", "oct", "nov", "dic", "" } }; // "ene.", "feb.", "mar.", "abr.", "may.", "jun.", "jul.", "ago.", "sep.", "oct.", "nov.", "dic.", "" + yield return new object[] { "uk-UA", new string[] { "січ", "лют", "бер", "кві", "тра", "чер", "лип", "сер", "вер", "жов", "лис", "гру", "" } }; + yield return new object[] { "vi-VN", new string[] { "Thg 1", "Thg 2", "Thg 3", "Thg 4", "Thg 5", "Thg 6", "Thg 7", "Thg 8", "Thg 9", "Thg 10", "Thg 11", "Thg 12", "" } }; + } + else + { + yield return new object[] { "am-ET", new string[] { "ጃን", "ፌብ", "ማርች", "ኤፕሪ", "ሜይ", "ጁን", "ጁላይ", "ኦገስ", "ሴፕቴ", "ኦክቶ", "ኖቬም", "ዲሴም", "" } }; // "ጃንዩ", "ፌብሩ", "ማርች", "ኤፕሪ", "ሜይ", "ጁን", "ጁላይ", "ኦገስ", "ሴፕቴ", "ኦክቶ", "ኖቬም", "ዲሴም", "" + yield return new object[] { "en-AU", new string[] { "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec", "" } }; // "Jun", "Jul" + yield return new object[] { "es-MX", new string[] { "ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic", "" } }; // "ene.", "feb.", "mar.", "abr.", "may.", "jun.", "jul.", "ago.", "sep.", "oct.", "nov.", "dic.", "" + yield return new object[] { "uk-UA", new string[] { "січ.", "лют.", "бер.", "квіт.", "трав.", "черв.", "лип.", "серп.", "вер.", "жовт.", "лист.", "груд.", "" } }; // "січ", "лют", "бер", "кві", "тра", "чер", "лип", "сер", "вер", "жов", "лис", "гру", "" + yield return new object[] { "vi-VN", new string[] { "Tháng 1", "Tháng 2", "Tháng 3", "Tháng 4", "Tháng 5", "Tháng 6", "Tháng 7", "Tháng 8", "Tháng 9", "Tháng 10", "Tháng 11", "Tháng 12", "" } }; + } yield return new object[] { "bg-BG", new string[] { "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "" } }; // "яну", "фев", "март", "апр", "май", "юни", "юли", "авг", "сеп", "окт", "ное", "дек", "" yield return new object[] { "bn-BD", new string[] { "জানু", "ফেব", "মার্চ", "এপ্রিল", "মে", "জুন", "জুলাই", "আগস্ট", "সেপ্টেম্বর", "অক্টোবর", "নভেম্বর", "ডিসেম্বর", "" } }; // "জানুয়ারী", "ফেব্রুয়ারী", "মার্চ", "এপ্রিল", "মে", "জুন", "জুলাই", "আগস্ট", "সেপ্টেম্বর", "অক্টোবর", "নভেম্বর", "ডিসেম্বর", "" yield return new object[] { "bn-IN", new string[] { "জানু", "ফেব", "মার্চ", "এপ্রিল", "মে", "জুন", "জুলাই", "আগস্ট", "সেপ্টেঃ", "অক্টোঃ", "নভেঃ", "ডিসেঃ", "" } }; // BUG. JS returns Genitive even though we expect Nominative; "জানু", "ফেব", "মার্চ", "এপ্রিল", "মে", "জুন", "জুলাই", "আগস্ট", "সেপ্টেম্বর", "অক্টোবর", "নভেম্বর", "ডিসেম্বর", "" @@ -54,7 +69,6 @@ public static IEnumerable AbbreviatedMonthNames_Get_TestData_HybridGlo yield return new object[] { "en-AI", new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "" } }; // "Sep" yield return new object[] { "en-AS", new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "" } }; yield return new object[] { "en-AT", new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "" } }; // "Sep" - yield return new object[] { "en-AU", new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "" } }; yield return new object[] { "en-BB", new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "" } }; // "Sep" yield return new object[] { "en-BE", new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "" } }; // "Sep" yield return new object[] { "en-BI", new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "" } }; @@ -153,7 +167,6 @@ public static IEnumerable AbbreviatedMonthNames_Get_TestData_HybridGlo yield return new object[] { "en-ZW", new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "" } }; // "Sep" yield return new object[] { "es-419", new string[] { "ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sept", "oct", "nov", "dic", "" } }; // "ene.", "feb.", "mar.", "abr.", "may.", "jun.", "jul.", "ago.", "sep.", "oct.", "nov.", "dic.", "" yield return new object[] { "es-ES", new string[] { "ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sept", "oct", "nov", "dic", "" } }; // "ene.", "feb.", "mar.", "abr.", "may.", "jun.", "jul.", "ago.", "sep.", "oct.", "nov.", "dic.", "" - yield return new object[] { "es-MX", new string[] { "ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sept", "oct", "nov", "dic", "" } }; // "ene.", "feb.", "mar.", "abr.", "may.", "jun.", "jul.", "ago.", "sep.", "oct.", "nov.", "dic.", "" yield return new object[] { "et-EE", new string[] { "jaanuar", "veebruar", "märts", "aprill", "mai", "juuni", "juuli", "august", "september", "oktoober", "november", "detsember", "" } }; // "jaan", "veebr", "märts", "apr", "mai", "juuni", "juuli", "aug", "sept", "okt", "nov", "dets", "" yield return new object[] { "fa-IR", new string[] { "فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند", "" } }; yield return new object[] { "fi-FI", new string[] { "tammi", "helmi", "maalis", "huhti", "touko", "kesä", "heinä", "elo", "syys", "loka", "marras", "joulu", "" } }; @@ -211,8 +224,7 @@ public static IEnumerable AbbreviatedMonthNames_Get_TestData_HybridGlo yield return new object[] { "th-TH", new string[] { "ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค.", "" } }; yield return new object[] { "tr-CY", new string[] { "Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara", "" } }; yield return new object[] { "tr-TR", new string[] { "Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara", "" } }; - yield return new object[] { "uk-UA", new string[] { "січ", "лют", "бер", "кві", "тра", "чер", "лип", "сер", "вер", "жов", "лис", "гру", "" } }; - yield return new object[] { "vi-VN", new string[] { "Thg 1", "Thg 2", "Thg 3", "Thg 4", "Thg 5", "Thg 6", "Thg 7", "Thg 8", "Thg 9", "Thg 10", "Thg 11", "Thg 12", "" } }; + yield return new object[] { "zh-CN", new string[] { "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月", "" } }; yield return new object[] { "zh-Hans-HK", new string[] { "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月", "" } }; yield return new object[] { "zh-SG", new string[] { "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月", "" } }; diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoFullDateTimePattern.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoFullDateTimePattern.cs index 97759781e2c5..a0b998ac31b3 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoFullDateTimePattern.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoFullDateTimePattern.cs @@ -28,11 +28,12 @@ public static IEnumerable FullDateTimePattern_Get_TestData_HybridGloba { yield return new object[] { new CultureInfo("ar-SA").DateTimeFormat, "dddd، d MMMM yyyy h:mm:ss tt" }; // dddd، d MMMM yyyy g h:mm:ss tt yield return new object[] { new CultureInfo("am-ET").DateTimeFormat, "yyyy MMMM d, dddd h:mm:ss tt" }; - yield return new object[] { new CultureInfo("bg-BG").DateTimeFormat, "dddd, d MMMM yyyy г. H:mm:ss ч." }; // dddd, d MMMM yyyy 'г'. H:mm:ss + yield return new object[] { new CultureInfo("bg-BG").DateTimeFormat, PlatformDetection.IsFirefox ? "dddd, d MMMM yyyy г. H:mm:ss ч." : "dddd, d MMMM yyyy г. H:mm:ss" }; // dddd, d MMMM yyyy 'г'. H:mm:ss yield return new object[] { new CultureInfo("bn-BD").DateTimeFormat, "dddd, d MMMM, yyyy h:mm:ss tt" }; yield return new object[] { new CultureInfo("bn-IN").DateTimeFormat, "dddd, d MMMM, yyyy h:mm:ss tt" }; - yield return new object[] { new CultureInfo("ca-AD").DateTimeFormat, "dddd, d de MMMM de yyyy H:mm:ss" }; // dddd, d MMMM 'de' yyyy H:mm:ss - yield return new object[] { new CultureInfo("ca-ES").DateTimeFormat, "dddd, d de MMMM de yyyy H:mm:ss" }; // dddd, d MMMM 'de' yyyy H:mm:ss + string catalanPattern = PlatformDetection.IsFirefox ? "dddd, d de MMMM de yyyy H:mm:ss" : "dddd, d de MMMM del yyyy H:mm:ss"; + yield return new object[] { new CultureInfo("ca-AD").DateTimeFormat, catalanPattern }; // dddd, d MMMM 'de' yyyy H:mm:ss + yield return new object[] { new CultureInfo("ca-ES").DateTimeFormat, catalanPattern }; // dddd, d MMMM 'de' yyyy H:mm:ss yield return new object[] { new CultureInfo("cs-CZ").DateTimeFormat, "dddd d. MMMM yyyy H:mm:ss" }; yield return new object[] { new CultureInfo("da-DK").DateTimeFormat, "dddd den d. MMMM yyyy HH.mm.ss" }; // dddd 'den' d. MMMM yyyy HH.mm.ss yield return new object[] { new CultureInfo("de-AT").DateTimeFormat, "dddd, d. MMMM yyyy HH:mm:ss" }; @@ -49,7 +50,7 @@ public static IEnumerable FullDateTimePattern_Get_TestData_HybridGloba yield return new object[] { new CultureInfo("en-AI").DateTimeFormat, "dddd, d MMMM yyyy HH:mm:ss" }; yield return new object[] { new CultureInfo("en-AS").DateTimeFormat, "dddd, MMMM d, yyyy h:mm:ss tt" }; yield return new object[] { new CultureInfo("en-AT").DateTimeFormat, "dddd, d MMMM yyyy HH:mm:ss" }; - yield return new object[] { new CultureInfo("en-AU").DateTimeFormat, "dddd, d MMMM yyyy h:mm:ss tt" }; + yield return new object[] { new CultureInfo("en-AU").DateTimeFormat, PlatformDetection.IsFirefox ? "dddd, d MMMM yyyy h:mm:ss tt" : "dddd d MMMM yyyy h:mm:ss tt" }; yield return new object[] { new CultureInfo("en-BB").DateTimeFormat, "dddd, d MMMM yyyy h:mm:ss tt" }; yield return new object[] { new CultureInfo("en-BE").DateTimeFormat, "dddd, d MMMM yyyy HH:mm:ss" }; yield return new object[] { new CultureInfo("en-BI").DateTimeFormat, "dddd, MMMM d, yyyy HH:mm:ss" }; @@ -72,7 +73,7 @@ public static IEnumerable FullDateTimePattern_Get_TestData_HybridGloba yield return new object[] { new CultureInfo("en-FJ").DateTimeFormat, "dddd, d MMMM yyyy h:mm:ss tt" }; yield return new object[] { new CultureInfo("en-FK").DateTimeFormat, "dddd, d MMMM yyyy HH:mm:ss" }; yield return new object[] { new CultureInfo("en-FM").DateTimeFormat, "dddd, d MMMM yyyy h:mm:ss tt" }; - yield return new object[] { new CultureInfo("en-GB").DateTimeFormat, "dddd, d MMMM yyyy HH:mm:ss" }; + yield return new object[] { new CultureInfo("en-GB").DateTimeFormat, PlatformDetection.IsFirefox ? "dddd, d MMMM yyyy HH:mm:ss" : "dddd d MMMM yyyy HH:mm:ss" }; yield return new object[] { new CultureInfo("en-GD").DateTimeFormat, "dddd, d MMMM yyyy h:mm:ss tt" }; yield return new object[] { new CultureInfo("en-GG").DateTimeFormat, "dddd, d MMMM yyyy HH:mm:ss" }; yield return new object[] { new CultureInfo("en-GH").DateTimeFormat, "dddd, d MMMM yyyy h:mm:ss tt" }; @@ -84,7 +85,7 @@ public static IEnumerable FullDateTimePattern_Get_TestData_HybridGloba yield return new object[] { new CultureInfo("en-IE").DateTimeFormat, "dddd d MMMM yyyy HH:mm:ss" }; yield return new object[] { new CultureInfo("en-IL").DateTimeFormat, "dddd, d MMMM yyyy H:mm:ss" }; yield return new object[] { new CultureInfo("en-IM").DateTimeFormat, "dddd, d MMMM yyyy HH:mm:ss" }; - yield return new object[] { new CultureInfo("en-IN").DateTimeFormat, "dddd, d MMMM, yyyy h:mm:ss tt" }; + yield return new object[] { new CultureInfo("en-IN").DateTimeFormat, PlatformDetection.IsFirefox ? "dddd, d MMMM, yyyy h:mm:ss tt" : "dddd d MMMM, yyyy h:mm:ss tt" }; yield return new object[] { new CultureInfo("en-IO").DateTimeFormat, "dddd, d MMMM yyyy HH:mm:ss" }; yield return new object[] { new CultureInfo("en-JE").DateTimeFormat, "dddd, d MMMM yyyy HH:mm:ss" }; yield return new object[] { new CultureInfo("en-JM").DateTimeFormat, "dddd, d MMMM yyyy h:mm:ss tt" }; @@ -146,9 +147,10 @@ public static IEnumerable FullDateTimePattern_Get_TestData_HybridGloba yield return new object[] { new CultureInfo("en-ZA").DateTimeFormat, "dddd, d MMMM yyyy HH:mm:ss" }; // dddd, dd MMMM yyyy HH:mm:ss yield return new object[] { new CultureInfo("en-ZM").DateTimeFormat, "dddd, d MMMM yyyy h:mm:ss tt" }; yield return new object[] { new CultureInfo("en-ZW").DateTimeFormat, "dddd, d MMMM yyyy HH:mm:ss" }; // dddd, dd MMMM yyyy HH:mm:ss - yield return new object[] { new CultureInfo("es-419").DateTimeFormat, "dddd, d de MMMM de yyyy HH:mm:ss" }; // dddd, d 'de' MMMM 'de' yyyy HH:mm:ss + string latinAmericaSpanishFormat = PlatformDetection.IsFirefox ? "dddd, d de MMMM de yyyy HH:mm:ss" : "dddd, d de MMMM de yyyy h:mm:ss tt"; // dddd, d 'de' MMMM 'de' yyyy HH:mm:ss + yield return new object[] { new CultureInfo("es-419").DateTimeFormat, latinAmericaSpanishFormat }; yield return new object[] { new CultureInfo("es-ES").DateTimeFormat, "dddd, d de MMMM de yyyy H:mm:ss" }; // dddd, d 'de' MMMM 'de' yyyy H:mm:ss - yield return new object[] { new CultureInfo("es-MX").DateTimeFormat, "dddd, d de MMMM de yyyy HH:mm:ss" }; // dddd, d 'de' MMMM 'de' yyyy H:mm:ss + yield return new object[] { new CultureInfo("es-MX").DateTimeFormat, latinAmericaSpanishFormat }; yield return new object[] { new CultureInfo("et-EE").DateTimeFormat, "dddd, d. MMMM yyyy HH:mm:ss" }; yield return new object[] { new CultureInfo("fa-IR").DateTimeFormat, "yyyy MMMM d, dddd H:mm:ss" }; yield return new object[] { new CultureInfo("fi-FI").DateTimeFormat, "dddd d. MMMM yyyy H.mm.ss" }; diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoGetAbbreviatedEraName.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoGetAbbreviatedEraName.cs index d0b2af309ea0..9b41129d472d 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoGetAbbreviatedEraName.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoGetAbbreviatedEraName.cs @@ -199,7 +199,7 @@ public static IEnumerable GetAbbreviatedEraName_TestData() yield return new object[] { "tr-CY", 1, "MS" }; yield return new object[] { "tr-TR", 1, "MS" }; yield return new object[] { "uk-UA", 1, "н.е." }; - yield return new object[] { "vi-VN", 1, "sau CN" }; + yield return new object[] { "vi-VN", 1, PlatformDetection.IsFirefox ? "sau CN" : "CN" }; // sau CN yield return new object[] { "zh-CN", 1, "公元" }; yield return new object[] { "zh-Hans-HK", 1, "公元" }; yield return new object[] { "zh-SG", 1, "公元" }; diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoGetEraName.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoGetEraName.cs index a2c69d95081a..9b97330ef0f4 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoGetEraName.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoGetEraName.cs @@ -387,8 +387,8 @@ public static IEnumerable GetEraName_TestData() yield return new object[] { "tr-TR", 1, "MS" }; yield return new object[] { "uk-UA", 0, "н. е." }; yield return new object[] { "uk-UA", 1, "н. е." }; - yield return new object[] { "vi-VN", 0, "CN" }; // sau CN - yield return new object[] { "vi-VN", 1, "CN" }; // sau CN + yield return new object[] { "vi-VN", 0, PlatformDetection.IsFirefox ? "CN" : "SCN" }; // sau CN + yield return new object[] { "vi-VN", 1, PlatformDetection.IsFirefox ? "CN" : "SCN" }; // sau CN yield return new object[] { "zh-CN", 0, "公元" }; yield return new object[] { "zh-CN", 1, "公元" }; yield return new object[] { "zh-Hans-HK", 0, "公元" }; diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoLongDatePattern.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoLongDatePattern.cs index dd8eebdefce3..1e2a7ca09b71 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoLongDatePattern.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoLongDatePattern.cs @@ -28,199 +28,201 @@ public static IEnumerable LongDatePattern_Set_TestData() public static IEnumerable LongDatePattern_Get_TestData_HybridGlobalization() { // see the comments on the right to check the non-Hybrid result, if it differs - yield return new object[] { new CultureInfo("ar-SA").DateTimeFormat, "dddd، d MMMM yyyy" }; // dddd، d MMMM yyyy g - yield return new object[] { new CultureInfo("am-ET").DateTimeFormat, "yyyy MMMM d, dddd" }; - yield return new object[] { new CultureInfo("bg-BG").DateTimeFormat, "dddd, d MMMM yyyy г." }; // "dddd, d MMMM yyyy 'г'." - yield return new object[] { new CultureInfo("bn-BD").DateTimeFormat, "dddd, d MMMM, yyyy" }; - yield return new object[] { new CultureInfo("bn-IN").DateTimeFormat, "dddd, d MMMM, yyyy" }; - yield return new object[] { new CultureInfo("ca-AD").DateTimeFormat, "dddd, d de MMMM de yyyy" }; // "dddd, d MMMM 'de' yyyy" - yield return new object[] { new CultureInfo("ca-ES").DateTimeFormat, "dddd, d de MMMM de yyyy" }; // "dddd, d MMMM 'de' yyyy" - yield return new object[] { new CultureInfo("cs-CZ").DateTimeFormat, "dddd d. MMMM yyyy" }; - yield return new object[] { new CultureInfo("da-DK").DateTimeFormat, "dddd den d. MMMM yyyy" }; // dddd 'den' d. MMMM yyyy - yield return new object[] { new CultureInfo("de-AT").DateTimeFormat, "dddd, d. MMMM yyyy" }; - yield return new object[] { new CultureInfo("de-BE").DateTimeFormat, "dddd, d. MMMM yyyy" }; - yield return new object[] { new CultureInfo("de-CH").DateTimeFormat, "dddd, d. MMMM yyyy" }; - yield return new object[] { new CultureInfo("de-DE").DateTimeFormat, "dddd, d. MMMM yyyy" }; - yield return new object[] { new CultureInfo("de-IT").DateTimeFormat, "dddd, d. MMMM yyyy" }; - yield return new object[] { new CultureInfo("de-LI").DateTimeFormat, "dddd, d. MMMM yyyy" }; - yield return new object[] { new CultureInfo("de-LU").DateTimeFormat, "dddd, d. MMMM yyyy" }; - yield return new object[] { new CultureInfo("el-CY").DateTimeFormat, "dddd d MMMM yyyy" }; // "dddd, d MMMM yyyy" - yield return new object[] { new CultureInfo("el-GR").DateTimeFormat, "dddd d MMMM yyyy" }; // "dddd, d MMMM yyyy" - yield return new object[] { new CultureInfo("en-AE").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-AG").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-AI").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-AS").DateTimeFormat, "dddd, MMMM d, yyyy" }; - yield return new object[] { new CultureInfo("en-AT").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-AU").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-BB").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-BE").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-BI").DateTimeFormat, "dddd, MMMM d, yyyy" }; - yield return new object[] { new CultureInfo("en-BM").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-BS").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-BW").DateTimeFormat, "dddd, d MMMM yyyy" }; // "dddd, dd MMMM yyyy" - yield return new object[] { new CultureInfo("en-BZ").DateTimeFormat, "dddd, d MMMM yyyy" }; // "dddd, dd MMMM yyyy" - yield return new object[] { new CultureInfo("en-CA").DateTimeFormat, "dddd, MMMM d, yyyy" }; - yield return new object[] { new CultureInfo("en-CC").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-CH").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-CK").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-CM").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-CX").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-CY").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-DE").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-DK").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-DM").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-ER").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-FI").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-FJ").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-FK").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-FM").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-GB").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-GD").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-GG").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-GH").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-GI").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-GM").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-GU").DateTimeFormat, "dddd, MMMM d, yyyy" }; - yield return new object[] { new CultureInfo("en-GY").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-HK").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-IE").DateTimeFormat, "dddd d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-IL").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-IM").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-IN").DateTimeFormat, "dddd, d MMMM, yyyy" }; - yield return new object[] { new CultureInfo("en-IO").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-JE").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-JM").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-KE").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-KI").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-KN").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-KY").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-LC").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-LR").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-LS").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-MG").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-MH").DateTimeFormat, "dddd, MMMM d, yyyy" }; - yield return new object[] { new CultureInfo("en-MO").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-MP").DateTimeFormat, "dddd, MMMM d, yyyy" }; - yield return new object[] { new CultureInfo("en-MS").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-MT").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-MU").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-MW").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-MY").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-NA").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-NF").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-NG").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-NL").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-NR").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-NU").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-NZ").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-PG").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-PH").DateTimeFormat, "dddd, MMMM d, yyyy" }; // "dddd, d MMMM yyyy" - yield return new object[] { new CultureInfo("en-PK").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-PN").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-PR").DateTimeFormat, "dddd, MMMM d, yyyy" }; - yield return new object[] { new CultureInfo("en-PW").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-RW").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-SB").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-SC").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-SD").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-SE").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-SG").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-SH").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-SI").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-SL").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-SS").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-SX").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-SZ").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-TC").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-TK").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-TO").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-TT").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-TV").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-TZ").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-UG").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-UM").DateTimeFormat, "dddd, MMMM d, yyyy" }; - yield return new object[] { new CultureInfo("en-US").DateTimeFormat, "dddd, MMMM d, yyyy" }; - yield return new object[] { new CultureInfo("en-VC").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-VG").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-VI").DateTimeFormat, "dddd, MMMM d, yyyy" }; - yield return new object[] { new CultureInfo("en-VU").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-WS").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-ZA").DateTimeFormat, "dddd, d MMMM yyyy" }; // "dddd, dd MMMM yyyy" - yield return new object[] { new CultureInfo("en-ZM").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("en-ZW").DateTimeFormat, "dddd, d MMMM yyyy" }; // "dddd, dd MMMM yyyy" - yield return new object[] { new CultureInfo("en-US").DateTimeFormat, "dddd, MMMM d, yyyy" }; - yield return new object[] { new CultureInfo("es-419").DateTimeFormat, "dddd, d de MMMM de yyyy" }; // dddd, d 'de' MMMM 'de' yyyy - yield return new object[] { new CultureInfo("es-ES").DateTimeFormat, "dddd, d de MMMM de yyyy" }; // dddd, d 'de' MMMM 'de' yyyy - yield return new object[] { new CultureInfo("es-MX").DateTimeFormat, "dddd, d de MMMM de yyyy" }; // dddd, d 'de' MMMM 'de' yyyy - yield return new object[] { new CultureInfo("et-EE").DateTimeFormat, "dddd, d. MMMM yyyy" }; - yield return new object[] { new CultureInfo("fa-IR").DateTimeFormat, "yyyy MMMM d, dddd" }; - yield return new object[] { new CultureInfo("fi-FI").DateTimeFormat, "dddd d. MMMM yyyy" }; - yield return new object[] { new CultureInfo("fil-PH").DateTimeFormat, "dddd, MMMM d, yyyy" }; - yield return new object[] { new CultureInfo("fr-BE").DateTimeFormat, "dddd d MMMM yyyy" }; - yield return new object[] { new CultureInfo("fr-CA").DateTimeFormat, "dddd d MMMM yyyy" }; - yield return new object[] { new CultureInfo("fr-CH").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("fr-FR").DateTimeFormat, "dddd d MMMM yyyy" }; - yield return new object[] { new CultureInfo("gu-IN").DateTimeFormat, "dddd, d MMMM, yyyy" }; - yield return new object[] { new CultureInfo("he-IL").DateTimeFormat, "dddd, d בMMMM yyyy" }; - yield return new object[] { new CultureInfo("hi-IN").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("hr-BA").DateTimeFormat, "dddd, d. MMMM yyyy." }; - yield return new object[] { new CultureInfo("hr-HR").DateTimeFormat, "dddd, d. MMMM yyyy." }; - yield return new object[] { new CultureInfo("hu-HU").DateTimeFormat, "yyyy. MMMM d., dddd" }; - yield return new object[] { new CultureInfo("id-ID").DateTimeFormat, "dddd, d MMMM yyyy" }; // "dddd, dd MMMM yyyy" - yield return new object[] { new CultureInfo("it-CH").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("it-IT").DateTimeFormat, "dddd d MMMM yyyy" }; - yield return new object[] { new CultureInfo("ja-JP").DateTimeFormat, "yyyy年M月d日dddd" }; - yield return new object[] { new CultureInfo("kn-IN").DateTimeFormat, "dddd, MMMM d, yyyy" }; - yield return new object[] { new CultureInfo("ko-KR").DateTimeFormat, "yyyy년 M월 d일 dddd" }; - yield return new object[] { new CultureInfo("lt-LT").DateTimeFormat, "yyyy m. MMMM d d., dddd" }; // "yyyy 'm'. MMMM d 'd'., dddd" - yield return new object[] { new CultureInfo("lv-LV").DateTimeFormat, "dddd, yyyy. gada d. MMMM" }; // "dddd, yyyy. 'gada' d. MMMM" - yield return new object[] { new CultureInfo("ml-IN").DateTimeFormat, "yyyy, MMMM d, dddd" }; - yield return new object[] { new CultureInfo("mr-IN").DateTimeFormat, "dddd, d MMMM, yyyy" }; - yield return new object[] { new CultureInfo("ms-BN").DateTimeFormat, "dddd, d MMMM yyyy" }; // "dd MMMM yyyy" - yield return new object[] { new CultureInfo("ms-MY").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("ms-SG").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("nb-NO").DateTimeFormat, "dddd d. MMMM yyyy" }; - yield return new object[] { new CultureInfo("no-NO").DateTimeFormat, "dddd d. MMMM yyyy" }; - yield return new object[] { new CultureInfo("nl-AW").DateTimeFormat, "dddd d MMMM yyyy" }; - yield return new object[] { new CultureInfo("nl-BE").DateTimeFormat, "dddd d MMMM yyyy" }; - yield return new object[] { new CultureInfo("nl-NL").DateTimeFormat, "dddd d MMMM yyyy" }; - yield return new object[] { new CultureInfo("pl-PL").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("pt-BR").DateTimeFormat, "dddd, d de MMMM de yyyy" }; // dddd, d 'de' MMMM 'de' yyyy - yield return new object[] { new CultureInfo("pt-PT").DateTimeFormat, "dddd, d de MMMM de yyyy" }; // dddd, d 'de' MMMM 'de' yyyy - yield return new object[] { new CultureInfo("ro-RO").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("ru-RU").DateTimeFormat, "dddd, d MMMM yyyy г." }; // "dddd, d MMMM yyyy 'г'." - yield return new object[] { new CultureInfo("sk-SK").DateTimeFormat, "dddd d. MMMM yyyy" }; - yield return new object[] { new CultureInfo("sl-SI").DateTimeFormat, "dddd, d. MMMM yyyy" }; // "dddd, dd. MMMM yyyy" - yield return new object[] { new CultureInfo("sr-Cyrl-RS").DateTimeFormat, "dddd, d. MMMM yyyy." }; // "dddd, dd. MMMM yyyy" - yield return new object[] { new CultureInfo("sr-Latn-RS").DateTimeFormat, "dddd, d. MMMM yyyy." }; // "dddd, dd. MMMM yyyy" - yield return new object[] { new CultureInfo("sv-AX").DateTimeFormat, "dddd d MMMM yyyy" }; - yield return new object[] { new CultureInfo("sv-SE").DateTimeFormat, "dddd d MMMM yyyy" }; - yield return new object[] { new CultureInfo("sw-CD").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("sw-KE").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("sw-TZ").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("sw-UG").DateTimeFormat, "dddd, d MMMM yyyy" }; - yield return new object[] { new CultureInfo("ta-IN").DateTimeFormat, "dddd, d MMMM, yyyy" }; - yield return new object[] { new CultureInfo("ta-LK").DateTimeFormat, "dddd, d MMMM, yyyy" }; - yield return new object[] { new CultureInfo("ta-MY").DateTimeFormat, "dddd, d MMMM, yyyy" }; - yield return new object[] { new CultureInfo("ta-SG").DateTimeFormat, "dddd, d MMMM, yyyy" }; - yield return new object[] { new CultureInfo("te-IN").DateTimeFormat, "d, MMMM yyyy, dddd" }; - yield return new object[] { new CultureInfo("th-TH").DateTimeFormat, "ddddที่ d MMMM g yyyy" }; - yield return new object[] { new CultureInfo("tr-CY").DateTimeFormat, "d MMMM yyyy dddd" }; - yield return new object[] { new CultureInfo("tr-TR").DateTimeFormat, "d MMMM yyyy dddd" }; - yield return new object[] { new CultureInfo("uk-UA").DateTimeFormat, "dddd, d MMMM yyyy р." }; // "dddd, d MMMM yyyy 'р'." - yield return new object[] { new CultureInfo("vi-VN").DateTimeFormat, "dddd, d MMMM, yyyy" }; - yield return new object[] { new CultureInfo("zh-CN").DateTimeFormat, "yyyy年M月d日dddd" }; - yield return new object[] { new CultureInfo("zh-Hans-HK").DateTimeFormat, "yyyy年M月d日dddd" }; - yield return new object[] { new CultureInfo("zh-SG").DateTimeFormat, "yyyy年M月d日dddd" }; - yield return new object[] { new CultureInfo("zh-HK").DateTimeFormat, "yyyy年M月d日dddd" }; - yield return new object[] { new CultureInfo("zh-TW").DateTimeFormat, "yyyy年M月d日 dddd" }; + yield return new object[] {"ar-SA", "dddd، d MMMM yyyy" }; // dddd، d MMMM yyyy g + yield return new object[] {"am-ET", "yyyy MMMM d, dddd" }; + yield return new object[] {"bg-BG", "dddd, d MMMM yyyy г." }; // "dddd, d MMMM yyyy 'г'." + yield return new object[] {"bn-BD", "dddd, d MMMM, yyyy" }; + yield return new object[] {"bn-IN", "dddd, d MMMM, yyyy" }; + string catalanianPattern = PlatformDetection.IsFirefox ? "dddd, d de MMMM de yyyy" : "dddd, d de MMMM del yyyy"; // "dddd, d MMMM 'de' yyyy" + yield return new object[] {"ca-AD", catalanianPattern }; + yield return new object[] {"ca-ES", catalanianPattern }; + yield return new object[] {"cs-CZ", "dddd d. MMMM yyyy" }; + yield return new object[] {"da-DK", "dddd den d. MMMM yyyy" }; // dddd 'den' d. MMMM yyyy + yield return new object[] {"de-AT", "dddd, d. MMMM yyyy" }; + yield return new object[] {"de-BE", "dddd, d. MMMM yyyy" }; + yield return new object[] {"de-CH", "dddd, d. MMMM yyyy" }; + yield return new object[] {"de-DE", "dddd, d. MMMM yyyy" }; + yield return new object[] {"de-IT", "dddd, d. MMMM yyyy" }; + yield return new object[] {"de-LI", "dddd, d. MMMM yyyy" }; + yield return new object[] {"de-LU", "dddd, d. MMMM yyyy" }; + yield return new object[] {"el-CY", "dddd d MMMM yyyy" }; // "dddd, d MMMM yyyy" + yield return new object[] {"el-GR", "dddd d MMMM yyyy" }; // "dddd, d MMMM yyyy" + yield return new object[] {"en-AE", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-AG", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-AI", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-AS", "dddd, MMMM d, yyyy" }; + yield return new object[] {"en-AT", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-AU", PlatformDetection.IsFirefox ? "dddd, d MMMM yyyy" : "dddd d MMMM yyyy" }; + yield return new object[] {"en-BB", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-BE", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-BI", "dddd, MMMM d, yyyy" }; + yield return new object[] {"en-BM", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-BS", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-BW", "dddd, d MMMM yyyy" }; // "dddd, dd MMMM yyyy" + yield return new object[] {"en-BZ", "dddd, d MMMM yyyy" }; // "dddd, dd MMMM yyyy" + yield return new object[] {"en-CA", "dddd, MMMM d, yyyy" }; + yield return new object[] {"en-CC", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-CH", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-CK", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-CM", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-CX", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-CY", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-DE", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-DK", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-DM", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-ER", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-FI", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-FJ", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-FK", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-FM", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-GB", PlatformDetection.IsFirefox ? "dddd, d MMMM yyyy" :"dddd d MMMM yyyy" }; + yield return new object[] {"en-GD", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-GG", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-GH", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-GI", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-GM", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-GU", "dddd, MMMM d, yyyy" }; + yield return new object[] {"en-GY", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-HK", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-IE", "dddd d MMMM yyyy" }; + yield return new object[] {"en-IL", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-IM", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-IN", PlatformDetection.IsFirefox ? "dddd, d MMMM, yyyy" : "dddd d MMMM, yyyy" }; // dddd, d MMMM, yyyy + yield return new object[] {"en-IO", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-JE", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-JM", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-KE", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-KI", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-KN", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-KY", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-LC", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-LR", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-LS", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-MG", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-MH", "dddd, MMMM d, yyyy" }; + yield return new object[] {"en-MO", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-MP", "dddd, MMMM d, yyyy" }; + yield return new object[] {"en-MS", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-MT", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-MU", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-MW", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-MY", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-NA", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-NF", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-NG", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-NL", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-NR", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-NU", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-NZ", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-PG", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-PH", "dddd, MMMM d, yyyy" }; // "dddd, d MMMM yyyy" + yield return new object[] {"en-PK", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-PN", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-PR", "dddd, MMMM d, yyyy" }; + yield return new object[] {"en-PW", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-RW", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-SB", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-SC", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-SD", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-SE", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-SG", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-SH", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-SI", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-SL", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-SS", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-SX", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-SZ", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-TC", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-TK", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-TO", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-TT", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-TV", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-TZ", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-UG", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-UM", "dddd, MMMM d, yyyy" }; + yield return new object[] {"en-US", "dddd, MMMM d, yyyy" }; + yield return new object[] {"en-VC", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-VG", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-VI", "dddd, MMMM d, yyyy" }; + yield return new object[] {"en-VU", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-WS", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-ZA", "dddd, d MMMM yyyy" }; // "dddd, dd MMMM yyyy" + yield return new object[] {"en-ZM", "dddd, d MMMM yyyy" }; + yield return new object[] {"en-ZW", "dddd, d MMMM yyyy" }; // "dddd, dd MMMM yyyy" + yield return new object[] {"en-US", "dddd, MMMM d, yyyy" }; + yield return new object[] {"es-419", "dddd, d de MMMM de yyyy" }; // dddd, d 'de' MMMM 'de' yyyy + yield return new object[] {"es-ES", "dddd, d de MMMM de yyyy" }; // dddd, d 'de' MMMM 'de' yyyy + yield return new object[] {"es-MX", "dddd, d de MMMM de yyyy" }; // dddd, d 'de' MMMM 'de' yyyy + yield return new object[] {"et-EE", "dddd, d. MMMM yyyy" }; + yield return new object[] {"fa-IR", "yyyy MMMM d, dddd" }; + yield return new object[] {"fi-FI", "dddd d. MMMM yyyy" }; + yield return new object[] {"fil-PH", "dddd, MMMM d, yyyy" }; + yield return new object[] {"fr-BE", "dddd d MMMM yyyy" }; + yield return new object[] {"fr-CA", "dddd d MMMM yyyy" }; + yield return new object[] {"fr-CH", "dddd, d MMMM yyyy" }; + yield return new object[] {"fr-FR", "dddd d MMMM yyyy" }; + yield return new object[] {"gu-IN", "dddd, d MMMM, yyyy" }; + yield return new object[] {"he-IL", "dddd, d בMMMM yyyy" }; + yield return new object[] {"hi-IN", "dddd, d MMMM yyyy" }; + yield return new object[] {"hr-BA", "dddd, d. MMMM yyyy." }; + yield return new object[] {"hr-HR", "dddd, d. MMMM yyyy." }; + yield return new object[] {"hu-HU", "yyyy. MMMM d., dddd" }; + yield return new object[] {"id-ID", "dddd, d MMMM yyyy" }; // "dddd, dd MMMM yyyy" + yield return new object[] {"it-CH", "dddd, d MMMM yyyy" }; + yield return new object[] {"it-IT", "dddd d MMMM yyyy" }; + yield return new object[] {"ja-JP", "yyyy年M月d日dddd" }; + yield return new object[] {"kn-IN", "dddd, MMMM d, yyyy" }; + yield return new object[] {"ko-KR", "yyyy년 M월 d일 dddd" }; + yield return new object[] {"lt-LT", "yyyy m. MMMM d d., dddd" }; // "yyyy 'm'. MMMM d 'd'., dddd" + yield return new object[] {"lv-LV", "dddd, yyyy. gada d. MMMM" }; // "dddd, yyyy. 'gada' d. MMMM" + yield return new object[] {"ml-IN", "yyyy, MMMM d, dddd" }; + yield return new object[] {"mr-IN", "dddd, d MMMM, yyyy" }; + yield return new object[] {"ms-BN", "dddd, d MMMM yyyy" }; // "dd MMMM yyyy" + yield return new object[] {"ms-MY", "dddd, d MMMM yyyy" }; + yield return new object[] {"ms-SG", "dddd, d MMMM yyyy" }; + yield return new object[] {"nb-NO", "dddd d. MMMM yyyy" }; + yield return new object[] {"no-NO", "dddd d. MMMM yyyy" }; + yield return new object[] {"nl-AW", "dddd d MMMM yyyy" }; + yield return new object[] {"nl-BE", "dddd d MMMM yyyy" }; + yield return new object[] {"nl-NL", "dddd d MMMM yyyy" }; + yield return new object[] {"pl-PL", "dddd, d MMMM yyyy" }; + yield return new object[] {"pt-BR", "dddd, d de MMMM de yyyy" }; // dddd, d 'de' MMMM 'de' yyyy + yield return new object[] {"pt-PT", "dddd, d de MMMM de yyyy" }; // dddd, d 'de' MMMM 'de' yyyy + yield return new object[] {"ro-RO", "dddd, d MMMM yyyy" }; + yield return new object[] {"ru-RU", "dddd, d MMMM yyyy г." }; // "dddd, d MMMM yyyy 'г'." + yield return new object[] {"sk-SK", "dddd d. MMMM yyyy" }; + yield return new object[] {"sl-SI", "dddd, d. MMMM yyyy" }; // "dddd, dd. MMMM yyyy" + yield return new object[] {"sr-Cyrl-RS", "dddd, d. MMMM yyyy." }; // "dddd, dd. MMMM yyyy" + yield return new object[] {"sr-Latn-RS", "dddd, d. MMMM yyyy." }; // "dddd, dd. MMMM yyyy" + yield return new object[] {"sv-AX", "dddd d MMMM yyyy" }; + yield return new object[] {"sv-SE", "dddd d MMMM yyyy" }; + yield return new object[] {"sw-CD", "dddd, d MMMM yyyy" }; + yield return new object[] {"sw-KE", "dddd, d MMMM yyyy" }; + yield return new object[] {"sw-TZ", "dddd, d MMMM yyyy" }; + yield return new object[] {"sw-UG", "dddd, d MMMM yyyy" }; + yield return new object[] {"ta-IN", "dddd, d MMMM, yyyy" }; + yield return new object[] {"ta-LK", "dddd, d MMMM, yyyy" }; + yield return new object[] {"ta-MY", "dddd, d MMMM, yyyy" }; + yield return new object[] {"ta-SG", "dddd, d MMMM, yyyy" }; + yield return new object[] {"te-IN", "d, MMMM yyyy, dddd" }; + yield return new object[] {"th-TH", "ddddที่ d MMMM g yyyy" }; + yield return new object[] {"tr-CY", "d MMMM yyyy dddd" }; + yield return new object[] {"tr-TR", "d MMMM yyyy dddd" }; + yield return new object[] {"uk-UA", "dddd, d MMMM yyyy р." }; // "dddd, d MMMM yyyy 'р'." + yield return new object[] {"vi-VN", "dddd, d MMMM, yyyy" }; + yield return new object[] {"zh-CN", "yyyy年M月d日dddd" }; + yield return new object[] {"zh-Hans-HK", "yyyy年M月d日dddd" }; + yield return new object[] {"zh-SG", "yyyy年M月d日dddd" }; + yield return new object[] {"zh-HK", "yyyy年M月d日dddd" }; + yield return new object[] {"zh-TW", "yyyy年M月d日 dddd" }; } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsHybridGlobalizationOnBrowser))] [MemberData(nameof(LongDatePattern_Get_TestData_HybridGlobalization))] - public void LongDatePattern_Get_ReturnsExpected_HybridGlobalization(DateTimeFormatInfo format, string expected) + public void LongDatePattern_Get_ReturnsExpected_HybridGlobalization(string cultureName, string expected) { - Assert.Equal(expected, format.LongDatePattern); + var format = new CultureInfo(cultureName).DateTimeFormat; + Assert.True(expected == format.LongDatePattern, $"Failed for culture: {cultureName}. Expected: {expected}, Actual: {format.LongDatePattern}"); } [Theory] diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoLongTimePattern.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoLongTimePattern.cs index 5992624b1e10..122eff9b4a77 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoLongTimePattern.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoLongTimePattern.cs @@ -19,7 +19,7 @@ public static IEnumerable LongTimePattern_Get_TestData_HybridGlobaliza // see the comments on the right to check the non-Hybrid result, if it differs yield return new object[] { new CultureInfo("ar-SA").DateTimeFormat, "h:mm:ss tt" }; yield return new object[] { new CultureInfo("am-ET").DateTimeFormat, "h:mm:ss tt" }; - yield return new object[] { new CultureInfo("bg-BG").DateTimeFormat, "H:mm:ss ч." }; + yield return new object[] { new CultureInfo("bg-BG").DateTimeFormat, PlatformDetection.IsFirefox ? "H:mm:ss ч." : "H:mm:ss" }; // H:mm:ss ч. yield return new object[] { new CultureInfo("bn-BD").DateTimeFormat, "h:mm:ss tt" }; yield return new object[] { new CultureInfo("bn-IN").DateTimeFormat, "h:mm:ss tt" }; yield return new object[] { new CultureInfo("ca-AD").DateTimeFormat, "H:mm:ss" }; @@ -137,9 +137,10 @@ public static IEnumerable LongTimePattern_Get_TestData_HybridGlobaliza yield return new object[] { new CultureInfo("en-ZA").DateTimeFormat, "HH:mm:ss" }; yield return new object[] { new CultureInfo("en-ZM").DateTimeFormat, "h:mm:ss tt" }; yield return new object[] { new CultureInfo("en-ZW").DateTimeFormat, "HH:mm:ss" }; - yield return new object[] { new CultureInfo("es-419").DateTimeFormat, "HH:mm:ss" }; + string latinAmericaSpanishPattern = PlatformDetection.IsFirefox ? "HH:mm:ss" : "h:mm:ss tt"; // H:mm:ss + yield return new object[] { new CultureInfo("es-419").DateTimeFormat, latinAmericaSpanishPattern }; yield return new object[] { new CultureInfo("es-ES").DateTimeFormat, "H:mm:ss" }; - yield return new object[] { new CultureInfo("es-MX").DateTimeFormat, "HH:mm:ss" }; // H:mm:ss + yield return new object[] { new CultureInfo("es-MX").DateTimeFormat, latinAmericaSpanishPattern }; yield return new object[] { new CultureInfo("et-EE").DateTimeFormat, "HH:mm:ss" }; yield return new object[] { new CultureInfo("fa-IR").DateTimeFormat, "H:mm:ss" }; yield return new object[] { new CultureInfo("fi-FI").DateTimeFormat, "H.mm.ss" }; diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoMonthGenitiveNames.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoMonthGenitiveNames.cs index 1587c514e827..1c6784cfdfe4 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoMonthGenitiveNames.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoMonthGenitiveNames.cs @@ -35,7 +35,14 @@ public static IEnumerable MonthGenitiveNames_Get_TestData() { // see the comments on the right to check the non-Hybrid result, if it differs yield return new object[] { new CultureInfo("ar-SA").DateTimeFormat, new string[] { "محرم", "صفر", "ربيع الأول", "ربيع الآخر", "جمادى الأولى", "جمادى الآخرة", "رجب", "شعبان", "رمضان", "شوال", "ذو القعدة", "ذو الحجة", "" } }; - yield return new object[] { new CultureInfo("am-ET").DateTimeFormat, new string[] { "ጃንዩወሪ", "ፌብሩወሪ", "ማርች", "ኤፕሪል", "ሜይ", "ጁን", "ጁላይ", "ኦገስት", "ሴፕቴምበር", "ኦክቶበር", "ኖቬምበር", "ዲሴምበር", "" } }; + if (PlatformDetection.IsFirefox) + { + yield return new object[] { new CultureInfo("am-ET").DateTimeFormat, new string[] { "ጃንዩወሪ", "ፌብሩወሪ", "ማርች", "ኤፕሪል", "ሜይ", "ጁን", "ጁላይ", "ኦገስት", "ሴፕቴምበር", "ኦክቶበር", "ኖቬምበር", "ዲሴምበር", "" } }; + } + else + { + yield return new object[] { new CultureInfo("am-ET").DateTimeFormat, new string[] { "ጃንዋሪ", "ፌብሩዋሪ", "ማርች", "ኤፕሪል", "ሜይ", "ጁን", "ጁላይ", "ኦገስት", "ሴፕቴምበር", "ኦክቶበር", "ኖቬምበር", "ዲሴምበር", "" } }; // "ጃንዩወሪ", "ፌብሩወሪ", "ማርች", "ኤፕሪል", "ሜይ", "ጁን", "ጁላይ", "ኦገስት", "ሴፕቴምበር", "ኦክቶበር", "ኖቬምበር", "ዲሴምበር", "" + } yield return new object[] { new CultureInfo("bg-BG").DateTimeFormat, new string[] { "януари", "февруари", "март", "април", "май", "юни", "юли", "август", "септември", "октомври", "ноември", "декември", "" } }; yield return new object[] { new CultureInfo("bn-BD").DateTimeFormat, new string[] { "জানুয়ারী", "ফেব্রুয়ারী", "মার্চ", "এপ্রিল", "মে", "জুন", "জুলাই", "আগস্ট", "সেপ্টেম্বর", "অক্টোবর", "নভেম্বর", "ডিসেম্বর", "" } }; yield return new object[] { new CultureInfo("bn-IN").DateTimeFormat, new string[] { "জানুয়ারী", "ফেব্রুয়ারী", "মার্চ", "এপ্রিল", "মে", "জুন", "জুলাই", "আগস্ট", "সেপ্টেম্বর", "অক্টোবর", "নভেম্বর", "ডিসেম্বর", "" } }; diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoMonthNames.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoMonthNames.cs index f7c18161dd6d..d6644f92303b 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoMonthNames.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoMonthNames.cs @@ -32,7 +32,14 @@ public static IEnumerable MonthNames_Get_TestData_HybridGlobalization( { // see the comments on the right to check the non-Hybrid result, if it differs yield return new object[] { new CultureInfo("ar-SA").DateTimeFormat, new string[] { "محرم", "صفر", "ربيع الأول", "ربيع الآخر", "جمادى الأولى", "جمادى الآخرة", "رجب", "شعبان", "رمضان", "شوال", "ذو القعدة", "ذو الحجة", "" } }; - yield return new object[] { new CultureInfo("am-ET").DateTimeFormat, new string[] { "ጃንዩወሪ", "ፌብሩወሪ", "ማርች", "ኤፕሪል", "ሜይ", "ጁን", "ጁላይ", "ኦገስት", "ሴፕቴምበር", "ኦክቶበር", "ኖቬምበር", "ዲሴምበር", "" } }; + if (PlatformDetection.IsFirefox) + { + yield return new object[] { new CultureInfo("am-ET").DateTimeFormat, new string[] { "ጃንዩወሪ", "ፌብሩወሪ", "ማርች", "ኤፕሪል", "ሜይ", "ጁን", "ጁላይ", "ኦገስት", "ሴፕቴምበር", "ኦክቶበር", "ኖቬምበር", "ዲሴምበር", "" } }; + } + else + { + yield return new object[] { new CultureInfo("am-ET").DateTimeFormat, new string[] { "ጃንዋሪ", "ፌብሩዋሪ", "ማርች", "ኤፕሪል", "ሜይ", "ጁን", "ጁላይ", "ኦገስት", "ሴፕቴምበር", "ኦክቶበር", "ኖቬምበር", "ዲሴምበር", "" } }; // "ጃንዩወሪ", "ፌብሩወሪ", "ማርች", "ኤፕሪል", "ሜይ", "ጁን", "ጁላይ", "ኦገስት", "ሴፕቴምበር", "ኦክቶበር", "ኖቬምበር", "ዲሴምበር", "" + } yield return new object[] { new CultureInfo("bg-BG").DateTimeFormat, new string[] { "януари", "февруари", "март", "април", "май", "юни", "юли", "август", "септември", "октомври", "ноември", "декември", "" } }; yield return new object[] { new CultureInfo("bn-BD").DateTimeFormat, new string[] { "জানুয়ারী", "ফেব্রুয়ারী", "মার্চ", "এপ্রিল", "মে", "জুন", "জুলাই", "আগস্ট", "সেপ্টেম্বর", "অক্টোবর", "নভেম্বর", "ডিসেম্বর", "" } }; yield return new object[] { new CultureInfo("bn-IN").DateTimeFormat, new string[] { "জানুয়ারী", "ফেব্রুয়ারী", "মার্চ", "এপ্রিল", "মে", "জুন", "জুলাই", "আগস্ট", "সেপ্টেম্বর", "অক্টোবর", "নভেম্বর", "ডিসেম্বর", "" } }; diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoNativeCalendarName.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoNativeCalendarName.cs index 86507dc1308f..377e6d30d597 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoNativeCalendarName.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoNativeCalendarName.cs @@ -11,10 +11,10 @@ public class DateTimeFormatInfoNativeCalendarName public static IEnumerable NativeCalendarName_Get_TestData_HybridGlobalization() { // see the comments on the right to check the non-Hybrid result, in this collection it always differs - string islamicName = "islamic-umalqura"; - string gregorianName = "gregory"; - string persianName = "persian"; - string bhuddistName = "buddhist"; + string islamicName = PlatformDetection.IsFirefox ? "UMALQURA" : "islamic-umalqura"; + string gregorianName = PlatformDetection.IsFirefox ? "GREGORIAN" : "gregory"; + string persianName = PlatformDetection.IsFirefox ? "PERSIAN" : "persian"; + string bhuddistName = PlatformDetection.IsFirefox ? "THAI" : "buddhist"; yield return new object[] { new CultureInfo("ar-SA").DateTimeFormat, islamicName }; // التقويم الإسلامي (أم القرى) yield return new object[] { new CultureInfo("am-ET").DateTimeFormat, gregorianName }; // የግሪጎሪያን የቀን አቆጣጠር yield return new object[] { new CultureInfo("bg-BG").DateTimeFormat, gregorianName }; // григориански календар diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoPMDesignator.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoPMDesignator.cs index 5eeea693a400..937dae6b7b24 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoPMDesignator.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoPMDesignator.cs @@ -137,9 +137,10 @@ public static IEnumerable PMDesignator_Get_TestData_HybridGlobalizatio yield return new object[] { new CultureInfo("en-ZA").DateTimeFormat, "pm" }; yield return new object[] { new CultureInfo("en-ZM").DateTimeFormat, "pm" }; yield return new object[] { new CultureInfo("en-ZW").DateTimeFormat, "pm" }; - yield return new object[] { new CultureInfo("es-419").DateTimeFormat, "p.\u00A0m." }; // p.m. + string latinAmericaSpanishDesignator = PlatformDetection.IsFirefox ? "p.\u00A0m." : "p.m."; // p.m. + yield return new object[] { new CultureInfo("es-419").DateTimeFormat, latinAmericaSpanishDesignator }; yield return new object[] { new CultureInfo("es-ES").DateTimeFormat, "p.\u00A0m." }; // p.m. - yield return new object[] { new CultureInfo("es-MX").DateTimeFormat, "p.\u00A0m." }; // p.m. + yield return new object[] { new CultureInfo("es-MX").DateTimeFormat, latinAmericaSpanishDesignator }; yield return new object[] { new CultureInfo("et-EE").DateTimeFormat, "PM" }; yield return new object[] { new CultureInfo("fa-IR").DateTimeFormat, "بعدازظهر" }; yield return new object[] { new CultureInfo("fi-FI").DateTimeFormat, "ip." }; @@ -188,10 +189,11 @@ public static IEnumerable PMDesignator_Get_TestData_HybridGlobalizatio yield return new object[] { new CultureInfo("sw-KE").DateTimeFormat, "PM" }; yield return new object[] { new CultureInfo("sw-TZ").DateTimeFormat, "PM" }; yield return new object[] { new CultureInfo("sw-UG").DateTimeFormat, "PM" }; - yield return new object[] { new CultureInfo("ta-IN").DateTimeFormat, "பிற்பகல்" }; - yield return new object[] { new CultureInfo("ta-LK").DateTimeFormat, "பிற்பகல்" }; - yield return new object[] { new CultureInfo("ta-MY").DateTimeFormat, "பிற்பகல்" }; - yield return new object[] { new CultureInfo("ta-SG").DateTimeFormat, "பிற்பகல்" }; + string tamilDesignator = PlatformDetection.IsFirefox ? "பிற்பகல்" : "PM"; // பிற்பகல் + yield return new object[] { new CultureInfo("ta-IN").DateTimeFormat, tamilDesignator }; + yield return new object[] { new CultureInfo("ta-LK").DateTimeFormat, tamilDesignator }; + yield return new object[] { new CultureInfo("ta-MY").DateTimeFormat, tamilDesignator }; + yield return new object[] { new CultureInfo("ta-SG").DateTimeFormat, tamilDesignator }; yield return new object[] { new CultureInfo("te-IN").DateTimeFormat, "PM" }; yield return new object[] { new CultureInfo("th-TH").DateTimeFormat, "หลังเที่ยง" }; yield return new object[] { new CultureInfo("tr-CY").DateTimeFormat, "ÖS" }; diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoShortDatePattern.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoShortDatePattern.cs index dd601d0f9ffb..c4e3dbcbdc3b 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoShortDatePattern.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoShortDatePattern.cs @@ -8,6 +8,12 @@ namespace System.Globalization.Tests { public class DateTimeFormatInfoShortDatePattern { + public static IEnumerable ShortDatePattern_Get_TestData() + { + yield return new object[] { DateTimeFormatInfo.InvariantInfo, "MM/dd/yyyy", "invariant" }; + yield return new object[] { new CultureInfo("en-US").DateTimeFormat, "M/d/yyyy", "en-US" }; + yield return new object[] { new CultureInfo("fr-FR").DateTimeFormat, "dd/MM/yyyy", "fr-FR" }; + } public static IEnumerable ShortDatePattern_Get_TestData_HybridGlobalization() { // see the comments on the right to check the non-Hybrid result, if it differs @@ -95,7 +101,7 @@ public static IEnumerable ShortDatePattern_Get_TestData_HybridGlobaliz yield return new object[] { "en-NL", "dd/MM/yyyy" }; yield return new object[] { "en-NR", "dd/MM/yyyy" }; yield return new object[] { "en-NU", "dd/MM/yyyy" }; - yield return new object[] { "en-NZ", "d/MM/yyyy" }; + yield return new object[] { "en-NZ", PlatformDetection.IsFirefox ? "d/MM/yyyy" : "dd/MM/yyyy" }; // "d/MM/yyyy" yield return new object[] { "en-PG", "dd/MM/yyyy" }; yield return new object[] { "en-PH", "M/d/yyyy" }; // "dd/MM/yyyy" yield return new object[] { "en-PK", "dd/MM/yyyy" }; @@ -131,7 +137,6 @@ public static IEnumerable ShortDatePattern_Get_TestData_HybridGlobaliz yield return new object[] { "en-ZA", "yyyy/MM/dd" }; yield return new object[] { "en-ZM", "dd/MM/yyyy" }; yield return new object[] { "en-ZW", "d/M/yyyy" }; - yield return new object[] { "en-US", "M/d/yyyy" }; yield return new object[] { "es-419", "d/M/yyyy" }; yield return new object[] { "es-ES", "d/M/yyyy" }; yield return new object[] { "es-MX", "dd/MM/yyyy" }; @@ -174,7 +179,7 @@ public static IEnumerable ShortDatePattern_Get_TestData_HybridGlobaliz yield return new object[] { "ro-RO", "dd.MM.yyyy" }; yield return new object[] { "ru-RU", "dd.MM.yyyy" }; yield return new object[] { "sk-SK", "d. M. yyyy" }; - yield return new object[] { "sl-SI", "d. MM. yyyy" }; + yield return new object[] { "sl-SI", PlatformDetection.IsFirefox ? "d. MM. yyyy" : "d. M. yyyy" }; // "d. MM. yyyy" yield return new object[] { "sr-Cyrl-RS", "d.M.yyyy." }; yield return new object[] { "sr-Latn-RS", "d.M.yyyy." }; yield return new object[] { "sv-AX", "yyyy-MM-dd" }; @@ -192,7 +197,7 @@ public static IEnumerable ShortDatePattern_Get_TestData_HybridGlobaliz yield return new object[] { "tr-CY", "d.MM.yyyy" }; yield return new object[] { "tr-TR", "d.MM.yyyy" }; yield return new object[] { "uk-UA", "dd.MM.yyyy" }; - yield return new object[] { "vi-VN", "dd/MM/yyyy" }; + yield return new object[] { "vi-VN", PlatformDetection.IsFirefox ? "dd/MM/yyyy" : "d/M/yyyy" }; // "dd/MM/yyyy" yield return new object[] { "zh-CN", "yyyy/M/d" }; yield return new object[] { "zh-Hans-HK", "d/M/yyyy" }; yield return new object[] { "zh-SG", "dd/MM/yyyy" }; @@ -200,6 +205,13 @@ public static IEnumerable ShortDatePattern_Get_TestData_HybridGlobaliz yield return new object[] { "zh-TW", "yyyy/M/d" }; } + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsHybridGlobalizationOnApplePlatform))] + [MemberData(nameof(ShortDatePattern_Get_TestData))] + public void ShortDatePattern_Get_ReturnsExpected(DateTimeFormatInfo format, string expected, string cultureName) + { + Assert.True(expected == format.ShortDatePattern, $"Failed for culture: {cultureName}. Expected: {expected}, Actual: {format.ShortDatePattern}"); + } + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsHybridGlobalizationOnBrowser))] [MemberData(nameof(ShortDatePattern_Get_TestData_HybridGlobalization))] public void ShortDatePattern_Get_ReturnsExpected_HybridGlobalization(string cultureName, string expected) diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoShortTimePattern.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoShortTimePattern.cs index 6afd8293248e..e9a891fb7ade 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoShortTimePattern.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoShortTimePattern.cs @@ -138,9 +138,10 @@ public static IEnumerable ShortTimePattern_Get_TestData_HybridGlobaliz yield return new object[] { new CultureInfo("en-ZM").DateTimeFormat, "h:mm tt" }; yield return new object[] { new CultureInfo("en-ZW").DateTimeFormat, "HH:mm" }; yield return new object[] { new CultureInfo("en-US").DateTimeFormat, "h:mm tt" }; - yield return new object[] { new CultureInfo("es-419").DateTimeFormat, "HH:mm" }; + string latinAmericanSpanishPattern = PlatformDetection.IsFirefox ? "HH:mm" : "h:mm tt"; // "HH:mm" + yield return new object[] { new CultureInfo("es-419").DateTimeFormat, latinAmericanSpanishPattern }; yield return new object[] { new CultureInfo("es-ES").DateTimeFormat, "H:mm" }; - yield return new object[] { new CultureInfo("es-MX").DateTimeFormat, "HH:mm" }; // H:mm + yield return new object[] { new CultureInfo("es-MX").DateTimeFormat, latinAmericanSpanishPattern }; yield return new object[] { new CultureInfo("et-EE").DateTimeFormat, "HH:mm" }; yield return new object[] { new CultureInfo("fa-IR").DateTimeFormat, "H:mm" }; yield return new object[] { new CultureInfo("fi-FI").DateTimeFormat, "H.mm" }; diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoShortestDayNames.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoShortestDayNames.cs index 0640ea3e2547..357762222de8 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoShortestDayNames.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoShortestDayNames.cs @@ -34,12 +34,21 @@ public static IEnumerable ShortestDayNames_Get_TestData_HybridGlobaliz yield return new object[] { new CultureInfo("am-ET").DateTimeFormat, new string[] { "እ", "ሰ", "ማ", "ረ", "ሐ", "ዓ", "ቅ" } }; yield return new object[] { new CultureInfo("bg-BG").DateTimeFormat, new string[] { "н", "п", "в", "с", "ч", "п", "с" } }; yield return new object[] { new CultureInfo("bn-IN").DateTimeFormat, new string[] { "র", "সো", "ম", "বু", "বৃ", "শু", "শ" } }; - yield return new object[] { new CultureInfo("ca-ES").DateTimeFormat, new string[] { "dg", "dl", "dt", "dc", "dj", "dv", "ds" } }; + if (PlatformDetection.IsFirefox) + { + yield return new object[] { new CultureInfo("ca-ES").DateTimeFormat, new string[] { "dg", "dl", "dt", "dc", "dj", "dv", "ds" } }; + yield return new object[] { new CultureInfo("en-AU").DateTimeFormat, new string[] { "Su.", "M.", "Tu.", "W.", "Th.", "F.", "Sa." } }; + } + else + { + yield return new object[] { new CultureInfo("ca-ES").DateTimeFormat, new string[] { "dg.", "dl.", "dt.", "dc.", "dj.", "dv.", "ds." } }; + yield return new object[] { new CultureInfo("en-AU").DateTimeFormat, new string[] { "S", "M", "T", "W", "T", "F", "S" } }; // "Su.", "M.", "Tu.", "W.", "Th.", "F.", "Sa." + } + yield return new object[] { new CultureInfo("cs-CZ").DateTimeFormat, new string[] { "N", "P", "Ú", "S", "Č", "P", "S" } }; yield return new object[] { new CultureInfo("da-DK").DateTimeFormat, new string[] { "S", "M", "T", "O", "T", "F", "L" } }; yield return new object[] { new CultureInfo("de-LU").DateTimeFormat, new string[] { "S", "M", "D", "M", "D", "F", "S" } }; yield return new object[] { new CultureInfo("el-CY").DateTimeFormat, new string[] { "Κ", "Δ", "Τ", "Τ", "Π", "Π", "Σ" } }; - yield return new object[] { new CultureInfo("en-AU").DateTimeFormat, new string[] { "Su.", "M.", "Tu.", "W.", "Th.", "F.", "Sa." } }; yield return new object[] { new CultureInfo("en-GB").DateTimeFormat, new string[] { "S", "M", "T", "W", "T", "F", "S" } }; yield return new object[] { new CultureInfo("es-419").DateTimeFormat, new string[] { "D", "L", "M", "M", "J", "V", "S" } }; yield return new object[] { new CultureInfo("es-ES").DateTimeFormat, new string[] { "D", "L", "M", "X", "J", "V", "S" } }; diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoYearMonthPattern.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoYearMonthPattern.cs index a80c65a7bbf6..f445f291754d 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoYearMonthPattern.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/DateTimeFormatInfo/DateTimeFormatInfoYearMonthPattern.cs @@ -17,7 +17,7 @@ public static IEnumerable YearMonthPattern_Get_TestData() // see the comments on the right to check the non-Hybrid result, if it differs yield return new object[] { new CultureInfo("ar-SA").DateTimeFormat, "MMMM yyyy" }; // "MMMM yyyy g" yield return new object[] { new CultureInfo("bg-BG").DateTimeFormat, "MMMM yyyy \u0433." }; // ICU: "MMMM yyyy '\u0433'." - yield return new object[] { new CultureInfo("ca-AD").DateTimeFormat, "MMMM de yyyy" }; // ICU: "MMMM 'de' yyyy" + yield return new object[] { new CultureInfo("ca-AD").DateTimeFormat, PlatformDetection.IsFirefox ? "MMMM de yyyy" : "MMMM del yyyy" }; // ICU: "MMMM 'de' yyyy" yield return new object[] { new CultureInfo("es-419").DateTimeFormat, "MMMM de yyyy" }; // ICU: "MMMM 'de' yyyy" yield return new object[] { new CultureInfo("es-ES").DateTimeFormat, "MMMM de yyyy" }; // ICU: "MMMM 'de' yyyy" yield return new object[] { new CultureInfo("es-MX").DateTimeFormat, "MMMM de yyyy" }; // ICU: "MMMM 'de' yyyy" diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/Hybrid/System.Globalization.Hybrid.WASM.Tests.csproj b/src/libraries/System.Runtime/tests/System.Globalization.Tests/Hybrid/System.Globalization.Hybrid.WASM.Tests.csproj index a39604c1cfac..fdc037e65555 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/Hybrid/System.Globalization.Hybrid.WASM.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/Hybrid/System.Globalization.Hybrid.WASM.Tests.csproj @@ -6,6 +6,14 @@ true true + + + WasmTestOnChrome + $(TestArchiveRoot)browserornodejs/ + $(TestArchiveTestsRoot)$(OSPlatformConfig)/ + $(DefineConstants);TARGET_BROWSER + true + diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/ILLink.Descriptors.xml b/src/libraries/System.Runtime/tests/System.Globalization.Tests/ILLink.Descriptors.xml new file mode 100644 index 000000000000..d7172e7a9b57 --- /dev/null +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/ILLink.Descriptors.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/System.Globalization.Tests.csproj b/src/libraries/System.Runtime/tests/System.Globalization.Tests/System.Globalization.Tests.csproj index e83591144f8b..6c0b2eab95b4 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/System.Globalization.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/System.Globalization.Tests.csproj @@ -11,6 +11,8 @@ + + diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/System/Globalization/RegionInfoTests.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/System/Globalization/RegionInfoTests.cs index ee39b219adb3..81a5e74b722d 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/System/Globalization/RegionInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/System/Globalization/RegionInfoTests.cs @@ -13,9 +13,8 @@ namespace System.Globalization.Tests public class RegionInfoPropertyTests { // Android has its own ICU, which doesn't 100% map to UsingLimitedCultures - // Browser uses JS to get the NativeName that is missing in ICU (in the singlethreaded runtime only) - public static bool SupportFullGlobalizationData => - (!PlatformDetection.IsWasi || PlatformDetection.IsHybridGlobalizationOnApplePlatform) && !PlatformDetection.IsWasmThreadingSupported; + // Browser uses JS to get the NativeName that is missing in ICU + public static bool SupportFullGlobalizationData => !PlatformDetection.IsWasi || PlatformDetection.IsHybridGlobalizationOnApplePlatform; [Theory] [InlineData("US", "US", "US")] diff --git a/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DisabledFileLockingTests/ILLink.Descriptors.xml b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DisabledFileLockingTests/ILLink.Descriptors.xml new file mode 100644 index 000000000000..a463351bf872 --- /dev/null +++ b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DisabledFileLockingTests/ILLink.Descriptors.xml @@ -0,0 +1,3 @@ + + + diff --git a/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DisabledFileLockingTests/System.IO.FileSystem.DisabledFileLocking.Tests.csproj b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DisabledFileLockingTests/System.IO.FileSystem.DisabledFileLocking.Tests.csproj index 62425e583e91..614de3d1ce97 100644 --- a/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DisabledFileLockingTests/System.IO.FileSystem.DisabledFileLocking.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/DisabledFileLockingTests/System.IO.FileSystem.DisabledFileLocking.Tests.csproj @@ -34,6 +34,8 @@ + + diff --git a/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/ILLink.Descriptors.xml b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/ILLink.Descriptors.xml new file mode 100644 index 000000000000..a463351bf872 --- /dev/null +++ b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/ILLink.Descriptors.xml @@ -0,0 +1,3 @@ + + + diff --git a/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csproj b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csproj index c2d3f67d0d55..b4f627b831f2 100644 --- a/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csproj @@ -245,5 +245,7 @@ + + diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/IndentedTextWriter.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/IndentedTextWriter.cs index 0de5d90f77bb..11b9ad7b82a1 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/IndentedTextWriter.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/IndentedTextWriter.cs @@ -104,6 +104,12 @@ public override void Write(string format, params object[] arg) LastCalledMethod = nameof(Write); } + public override void Write(string format, params ReadOnlySpan arg) + { + base.Write(format, arg); + LastCalledMethod = nameof(Write); + } + public override void Write(string value) { base.Write(value); @@ -212,6 +218,12 @@ public override void WriteLine(string format, params object[] arg) LastCalledMethod = nameof(WriteLine); } + public override void WriteLine(string format, params ReadOnlySpan arg) + { + base.WriteLine(format, arg); + LastCalledMethod = nameof(WriteLine); + } + public override void WriteLine(string value) { base.WriteLine(value); @@ -416,7 +428,8 @@ public static async Task Writes_ProducesExpectedOutput(string newline) itw.Write("{0}", 14); itw.Write("{0} {1}", 15, 16); itw.Write("{0} {1} {2}", 15, 16, 17); - itw.Write("{0} {1} {2} {3}", 15, 16, 17, 18); + itw.Write("{0} {1} {2} {3}", new object[] { 15, 16, 17, 18 }); + itw.Write("{0} {1} {2} {3}", (ReadOnlySpan)new object[] { 15, 16, 17, 18 }); itw.WriteLine(true); itw.WriteLine('a'); @@ -434,7 +447,8 @@ public static async Task Writes_ProducesExpectedOutput(string newline) itw.WriteLine("{0}", 14); itw.WriteLine("{0} {1}", 15, 16); itw.WriteLine("{0} {1} {2}", 15, 16, 17); - itw.WriteLine("{0} {1} {2} {3}", 15, 16, 17, 18); + itw.WriteLine("{0} {1} {2} {3}", new object[] { 15, 16, 17, 18 }); + itw.WriteLine("{0} {1} {2} {3}", (ReadOnlySpan)new object[] { 15, 16, 17, 18 }); await itw.WriteAsync('a'); await itw.WriteAsync(new char[] { 'b', 'c' }); @@ -450,7 +464,7 @@ public static async Task Writes_ProducesExpectedOutput(string newline) Assert.Equal( "t" + newline + - "tTrueabcde45.66.789101112131415 1615 16 1715 16 17 18True" + newline + + "tTrueabcde45.66.789101112131415 1615 16 1715 16 17 1815 16 17 18True" + newline + "ta" + newline + "tbc" + newline + "tde" + newline + @@ -467,6 +481,7 @@ public static async Task Writes_ProducesExpectedOutput(string newline) "t15 16" + newline + "t15 16 17" + newline + "t15 16 17 18" + newline + + "t15 16 17 18" + newline + "tabcde1a" + newline + "tbc" + newline + "tde" + newline + @@ -499,7 +514,8 @@ object[] CreateParameters(Action callWrite, string expected) yield return CreateParameters(x => x.Write("Hello {0} World", "Digital"), "Hello Digital World"); yield return CreateParameters(x => x.Write("Hello {0} World{1}", "Digital", "!!"), "Hello Digital World!!"); yield return CreateParameters(x => x.Write("Hello {0} {1} World{2}", "Dot", "NET", "!!"), "Hello Dot NET World!!"); - yield return CreateParameters(x => x.Write("Hello {0} {1} {2} World{3}", "Digital", "Dot", "NET", "!!"), "Hello Digital Dot NET World!!"); + yield return CreateParameters(x => x.Write("Hello {0} {1} {2} World{3}", new object[] { "Digital", "Dot", "NET", "!!" }), "Hello Digital Dot NET World!!"); + yield return CreateParameters(x => x.Write("Hello {0} {1} {2} World{3}", (ReadOnlySpan)new object[] { "Digital", "Dot", "NET", "!!" }), "Hello Digital Dot NET World!!"); yield return CreateParameters(x => x.Write("Hello World".ToCharArray(), 6, 5), "World"); } } @@ -530,7 +546,8 @@ object[] CreateParameters(Action callWriteLine, string expec yield return CreateParameters(x => x.WriteLine("Hello {0} {1} World", "Dot", "NET"), $"Hello Dot NET World{NewLine}"); yield return CreateParameters(x => x.WriteLine("Hello {0} {1} World{2}", "Dot", "NET", "!!"), $"Hello Dot NET World!!{NewLine}"); yield return CreateParameters(x => x.WriteLine("Hello World".ToCharArray(), 6, 5), $"World{NewLine}"); - yield return CreateParameters(x => x.WriteLine("Hello {0} {1} {2} World{3}", "Digital", "Dot", "NET", "!!"), $"Hello Digital Dot NET World!!{NewLine}"); + yield return CreateParameters(x => x.WriteLine("Hello {0} {1} {2} World{3}", new object[] { "Digital", "Dot", "NET", "!!" }), $"Hello Digital Dot NET World!!{NewLine}"); + yield return CreateParameters(x => x.WriteLine("Hello {0} {1} {2} World{3}", (ReadOnlySpan)new object[] { "Digital", "Dot", "NET", "!!" }), $"Hello Digital Dot NET World!!{NewLine}"); } } diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/Stream/Stream.NullTests.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/Stream/Stream.NullTests.cs index 86ebfba5efbe..3714ff3b2020 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/Stream/Stream.NullTests.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/Stream/Stream.NullTests.cs @@ -234,7 +234,8 @@ public static void TextNullTextWriter(TextWriter output) output.Write(" {0} ", "Friday"); output.Write(" {0}{1} ", "Saturday", "Sunday"); output.Write(" {0} {1} {2}", TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(2), TimeSpan.FromDays(3)); - output.Write(" {0} {1} {2} {3}", (Int128)4, (UInt128)5, (nint)6, (nuint)7); + output.Write(" {0} {1} {2} {3}", new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7 }); + output.Write(" {0} {1} {2} {3} {4}", (ReadOnlySpan)new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7, "8" }); output.WriteLine(); output.WriteLine(true); output.WriteLine('a'); @@ -256,7 +257,8 @@ public static void TextNullTextWriter(TextWriter output) output.WriteLine(" {0} ", "Friday"); output.WriteLine(" {0}{1} ", "Saturday", "Sunday"); output.WriteLine(" {0} {1} {2}", TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(2), TimeSpan.FromDays(3)); - output.WriteLine(" {0} {1} {2} {3}", (Int128)4, (UInt128)5, (nint)6, (nuint)7); + output.WriteLine(" {0} {1} {2} {3}", new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7 }); + output.WriteLine(" {0} {1} {2} {3} {4}", (ReadOnlySpan)new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7, "8" }); Assert.True(output.WriteAsync('a').IsCompletedSuccessfully); Assert.True(output.WriteAsync((char[])null).IsCompletedSuccessfully); Assert.True(output.WriteAsync(new char[] { 'b', 'c' }).IsCompletedSuccessfully); diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.cs index 0d34fe6730f0..69edb13a8a1f 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.cs @@ -58,20 +58,28 @@ public void FormatOverloadsCallWrite() Assert.Equal(2, writer.WriteCalls); writer.Write("{0}{1}{2}", "Zero", "One", "Two"); Assert.Equal(3, writer.WriteCalls); - writer.Write("{0}{1}{2}{3}", "Zero", "One", "Two", "Three"); + writer.Write("{0}{1}{2}{3}", new object[] { "Zero", "One", "Two", "Three" }); Assert.Equal(4, writer.WriteCalls); - writer.Write("{0}{1}{2}{3}{4}", "Zero", "One", "Two", "Three", "Four"); + writer.Write("{0}{1}{2}{3}", (ReadOnlySpan)new object[] { "Zero", "One", "Two", "Three" }); Assert.Equal(5, writer.WriteCalls); + writer.Write("{0}{1}{2}{3}{4}", new object[] { "Zero", "One", "Two", "Three", "Four" }); + Assert.Equal(6, writer.WriteCalls); + writer.Write("{0}{1}{2}{3}{4}", (ReadOnlySpan)new object[] { "Zero", "One", "Two", "Three", "Four" }); + Assert.Equal(7, writer.WriteCalls); writer.WriteLine("{0}", "Zero"); Assert.Equal(1, writer.WriteLineCalls); writer.WriteLine("{0}{1}", "Zero", "One"); Assert.Equal(2, writer.WriteLineCalls); writer.WriteLine("{0}{1}{2}", "Zero", "One", "Two"); Assert.Equal(3, writer.WriteLineCalls); - writer.WriteLine("{0}{1}{2}{3}", "Zero", "One", "Two", "Three"); + writer.WriteLine("{0}{1}{2}{3}", new object[] { "Zero", "One", "Two", "Three" }); Assert.Equal(4, writer.WriteLineCalls); - writer.WriteLine("{0}{1}{2}{3}{4}", "Zero", "One", "Two", "Three", "Four"); + writer.WriteLine("{0}{1}{2}{3}", (ReadOnlySpan)new object[] { "Zero", "One", "Two", "Three" }); Assert.Equal(5, writer.WriteLineCalls); + writer.WriteLine("{0}{1}{2}{3}{4}", new object[] { "Zero", "One", "Two", "Three", "Four" }); + Assert.Equal(6, writer.WriteLineCalls); + writer.WriteLine("{0}{1}{2}{3}{4}", (ReadOnlySpan)new object[] { "Zero", "One", "Two", "Three", "Four" }); + Assert.Equal(7, writer.WriteLineCalls); } } } diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/TextWriter/TextWriterTests.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/TextWriter/TextWriterTests.cs index de3ed9530a1e..2299dc86f567 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/TextWriter/TextWriterTests.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/TextWriter/TextWriterTests.cs @@ -226,15 +226,24 @@ public void WriteStringThreeObjectsTest() } [Fact] - public void WriteStringMultipleObjectsTest() + public void WriteStringMultipleObjectsArrayTest() { using (CharArrayTextWriter tw = NewTextWriter) { - tw.Write(TestDataProvider.FormatStringMultipleObjects, TestDataProvider.MultipleObjects); + tw.Write(TestDataProvider.FormatStringMultipleObjects, (object[])TestDataProvider.MultipleObjects); Assert.Equal(string.Format(TestDataProvider.FormatStringMultipleObjects, TestDataProvider.MultipleObjects), tw.Text); } } + [Fact] + public void WriteStringMultipleObjectsSpanTest() + { + using (CharArrayTextWriter tw = NewTextWriter) + { + tw.Write(TestDataProvider.FormatStringMultipleObjects, (ReadOnlySpan)TestDataProvider.MultipleObjects); + Assert.Equal(string.Format(TestDataProvider.FormatStringMultipleObjects, TestDataProvider.MultipleObjects), tw.Text); + } + } #endregion #region WriteLine Overloads @@ -454,11 +463,21 @@ public void WriteLineStringThreeObjectsTest() } [Fact] - public void WriteLineStringMultipleObjectsTest() + public void WriteLineStringMultipleObjectsArrayTest() { using (CharArrayTextWriter tw = NewTextWriter) { - tw.WriteLine(TestDataProvider.FormatStringMultipleObjects, TestDataProvider.MultipleObjects); + tw.WriteLine(TestDataProvider.FormatStringMultipleObjects, (object[])TestDataProvider.MultipleObjects); + Assert.Equal(string.Format(TestDataProvider.FormatStringMultipleObjects + tw.NewLine, TestDataProvider.MultipleObjects), tw.Text); + } + } + + [Fact] + public void WriteLineStringMultipleObjectsSpanTest() + { + using (CharArrayTextWriter tw = NewTextWriter) + { + tw.WriteLine(TestDataProvider.FormatStringMultipleObjects, (ReadOnlySpan)TestDataProvider.MultipleObjects); Assert.Equal(string.Format(TestDataProvider.FormatStringMultipleObjects + tw.NewLine, TestDataProvider.MultipleObjects), tw.Text); } } @@ -772,8 +791,11 @@ public async Task CreateBroadcasting_DelegatesToAllWriters() oracle.Write(" {0} {1} {2}", TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(2), TimeSpan.FromDays(3)); broadcasting.Write(" {0} {1} {2}", TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(2), TimeSpan.FromDays(3)); - oracle.Write(" {0} {1} {2} {3}", (Int128)4, (UInt128)5, (nint)6, (nuint)7); - broadcasting.Write(" {0} {1} {2} {3}", (Int128)4, (UInt128)5, (nint)6, (nuint)7); + oracle.Write(" {0} {1} {2} {3}", new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7 }); + broadcasting.Write(" {0} {1} {2} {3}", new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7 }); + + oracle.Write(" {0} {1} {2} {3} {4}", (ReadOnlySpan)new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7, "8" }); + broadcasting.Write(" {0} {1} {2} {3} {4}", (ReadOnlySpan)new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7, "8" }); oracle.WriteLine(); broadcasting.WriteLine(); @@ -835,8 +857,11 @@ public async Task CreateBroadcasting_DelegatesToAllWriters() oracle.WriteLine(" {0} {1} {2}", TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(2), TimeSpan.FromDays(3)); broadcasting.WriteLine(" {0} {1} {2}", TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(2), TimeSpan.FromDays(3)); - oracle.WriteLine(" {0} {1} {2} {3}", (Int128)4, (UInt128)5, (nint)6, (nuint)7); - broadcasting.WriteLine(" {0} {1} {2} {3}", (Int128)4, (UInt128)5, (nint)6, (nuint)7); + oracle.WriteLine(" {0} {1} {2} {3}", new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7 }); + broadcasting.WriteLine(" {0} {1} {2} {3}", new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7 }); + + oracle.WriteLine(" {0} {1} {2} {3} {4}", (ReadOnlySpan)new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7, "8" }); + broadcasting.WriteLine(" {0} {1} {2} {3} {4}", (ReadOnlySpan)new object[] { (Int128)4, (UInt128)5, (nint)6, (nuint)7, "8" }); await oracle.WriteAsync('a'); await broadcasting.WriteAsync('a'); diff --git a/src/libraries/System.Runtime/tests/System.Reflection.Tests/AssemblyTests.cs b/src/libraries/System.Runtime/tests/System.Reflection.Tests/AssemblyTests.cs index 600a4733b40c..65752a40ab81 100644 --- a/src/libraries/System.Runtime/tests/System.Reflection.Tests/AssemblyTests.cs +++ b/src/libraries/System.Runtime/tests/System.Reflection.Tests/AssemblyTests.cs @@ -7,10 +7,12 @@ using System.Globalization; using System.IO; using System.Linq; +using System.Reflection.Emit; using System.Reflection.Tests; using System.Runtime.CompilerServices; using System.Security; using System.Text; +using Microsoft.DotNet.RemoteExecutor; using Xunit; [assembly: @@ -181,6 +183,32 @@ public void GetEntryAssembly() Assert.True(correct, $"Unexpected assembly name {assembly}"); } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void SetEntryAssembly() + { + Assert.NotNull(Assembly.GetEntryAssembly()); + + RemoteExecutor.Invoke(() => + { + Assembly.SetEntryAssembly(null); + Assert.Null(Assembly.GetEntryAssembly()); + + Assembly testAssembly = typeof(AssemblyTests).Assembly; + + Assembly.SetEntryAssembly(testAssembly); + Assert.Equal(Assembly.GetEntryAssembly(), testAssembly); + + var invalidAssembly = new PersistedAssemblyBuilder( + new AssemblyName("NotaRuntimeAssemblyTest"), + typeof(object).Assembly + ); + + Assert.Throws( + () => Assembly.SetEntryAssembly(invalidAssembly) + ); + }).Dispose(); + } + [Fact] public void GetFile() { @@ -442,12 +470,20 @@ public void LoadFile_ValidPEBadIL_ThrowsBadImageFormatExceptionWithPath_ByInitia AssertExtensions.ThrowsContains(() => Assembly.LoadFile(path), path); } +#pragma warning disable SYSLIB0056 // AssemblyHashAlgorithm overload is not supported and throws NotSupportedException. [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsAssemblyLoadingSupported))] public void LoadFromUsingHashValue() { Assert.Throws(() => Assembly.LoadFrom("abc", null, System.Configuration.Assemblies.AssemblyHashAlgorithm.SHA1)); } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsAssemblyLoadingSupported))] + public void LoadFrom_WithHashValue_ThrowsNotSupportedException() + { + Assert.Throws(() => Assembly.LoadFrom(DestTestAssemblyPath, new byte[0], Configuration.Assemblies.AssemblyHashAlgorithm.None)); + } +#pragma warning restore SYSLIB0056 // AssemblyHashAlgorithm overload is not supported and throws NotSupportedException. + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsAssemblyLoadingSupported))] public void LoadFrom_SamePath_ReturnsEqualAssemblies() { @@ -496,12 +532,6 @@ public void UnsafeLoadFrom_SamePath_ReturnsEqualAssemblies() Assert.Equal(assembly1, assembly2); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsAssemblyLoadingSupported))] - public void LoadFrom_WithHashValue_ThrowsNotSupportedException() - { - Assert.Throws(() => Assembly.LoadFrom(DestTestAssemblyPath, new byte[0], Configuration.Assemblies.AssemblyHashAlgorithm.None)); - } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsAssemblyLoadingSupported))] public void LoadModule() { diff --git a/src/libraries/System.Runtime/tests/System.Reflection.Tests/CustomAttributeTests.cs b/src/libraries/System.Runtime/tests/System.Reflection.Tests/CustomAttributeTests.cs index ce6e5ecddf56..c3c7f3c465e4 100644 --- a/src/libraries/System.Runtime/tests/System.Reflection.Tests/CustomAttributeTests.cs +++ b/src/libraries/System.Runtime/tests/System.Reflection.Tests/CustomAttributeTests.cs @@ -237,5 +237,43 @@ public void CustomAttributeProvider () Assert.Equal(typeof(MyParameterAttribute), customAttributesData[0].AttributeType); Assert.Equal(typeof(MyPropertyAttribute), customAttributesData[1].AttributeType); } + + internal enum EnumForArrays { Zero, One, Two } + + [CustomAttributeWithObjects(EnumForArrays.One, new object[] { EnumForArrays.One }, new EnumForArrays[] { EnumForArrays.Two }, + B1 = EnumForArrays.One, B2 = new object[] { EnumForArrays.One }, B3 = new EnumForArrays[] { EnumForArrays.Two })] + internal class ClassWithObjectEnums { } + + internal class CustomAttributeWithObjectsAttribute(object a1, object a2, object a3) : Attribute + { + public object A1 => a1; + public object A2 => a2; + public object A3 => a3; + + public object B1 { get; set; } + public object B2 { get; set; } + public object B3 { get; set; } + } + + [Fact] + public void BoxedEnumAttributes() + { + CustomAttributeWithObjectsAttribute att = typeof(ClassWithObjectEnums) + .GetCustomAttribute()!; + + Assert.Equal(typeof(EnumForArrays), att.A1.GetType()); + Assert.Equal(typeof(object[]), att.A2.GetType()); + Assert.Equal(typeof(EnumForArrays), ((object[])att.A2)[0].GetType()); + Assert.Equal(EnumForArrays.One, ((object[])att.A2)[0]); + Assert.Equal(typeof(EnumForArrays[]), att.A3.GetType()); + Assert.Equal(EnumForArrays.Two, ((EnumForArrays[])att.A3)[0]); + + Assert.Equal(typeof(EnumForArrays), att.B1.GetType()); + Assert.Equal(typeof(object[]), att.B2.GetType()); + Assert.Equal(typeof(EnumForArrays), ((object[])att.B2)[0].GetType()); + Assert.Equal(EnumForArrays.One, ((object[])att.B2)[0]); + Assert.Equal(typeof(EnumForArrays[]), att.B3.GetType()); + Assert.Equal(EnumForArrays.Two, ((EnumForArrays[])att.B3)[0]); + } } } diff --git a/src/libraries/System.Runtime/tests/System.Reflection.Tests/System.Reflection.Tests.csproj b/src/libraries/System.Runtime/tests/System.Reflection.Tests/System.Reflection.Tests.csproj index 9553a7dacc48..9c380a90bfbd 100644 --- a/src/libraries/System.Runtime/tests/System.Reflection.Tests/System.Reflection.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Reflection.Tests/System.Reflection.Tests.csproj @@ -2,6 +2,7 @@ $(NetCoreAppCurrent) true + true true diff --git a/src/libraries/System.Runtime/tests/System.Resources.ResourceManager.Tests/ResourceManagerTests.cs b/src/libraries/System.Runtime/tests/System.Resources.ResourceManager.Tests/ResourceManagerTests.cs index 6bb68cb65b14..b80b709fd171 100644 --- a/src/libraries/System.Runtime/tests/System.Resources.ResourceManager.Tests/ResourceManagerTests.cs +++ b/src/libraries/System.Runtime/tests/System.Resources.ResourceManager.Tests/ResourceManagerTests.cs @@ -112,7 +112,7 @@ public static void GetString_FromTestClassWithoutNeutralResources() static int ResourcesAfAZEvents = 0; -#if NETCOREAPP +#if NET static System.Reflection.Assembly AssemblyResolvingEventHandler(System.Runtime.Loader.AssemblyLoadContext alc, System.Reflection.AssemblyName name) { if (name.FullName.StartsWith("System.Resources.ResourceManager.Tests.resources")) @@ -138,7 +138,7 @@ static System.Reflection.Assembly AssemblyResolveEventHandler(object sender, Res { if (name.Contains("Culture=af-ZA")) { -#if NETCOREAPP +#if NET Assert.Equal(1, ResourcesAfAZEvents); #else Assert.Equal(0, ResourcesAfAZEvents); @@ -162,7 +162,7 @@ public static void GetString_ExpectEvents() private static void Remote_ExpectEvents() { -#if NETCOREAPP +#if NET System.Runtime.Loader.AssemblyLoadContext.Default.Resolving += AssemblyResolvingEventHandler; #endif AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(AssemblyResolveEventHandler); @@ -176,7 +176,7 @@ private static void Remote_ExpectEvents() string actual = resourceManager.GetString("One", culture); Assert.Equal("Value-One", actual); -#if NETCOREAPP +#if NET Assert.Equal(2, ResourcesAfAZEvents); #else Assert.Equal(1, ResourcesAfAZEvents); diff --git a/src/libraries/System.Runtime/tests/System.Runtime.CompilerServices.Unsafe.Tests/UnsafeTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.CompilerServices.Unsafe.Tests/UnsafeTests.cs index 955bc189b433..70d55cd6f698 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.CompilerServices.Unsafe.Tests/UnsafeTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.CompilerServices.Unsafe.Tests/UnsafeTests.cs @@ -1166,6 +1166,18 @@ public static unsafe void BitCast() Assert.Throws(() => Unsafe.BitCast(5)); Assert.Throws(() => Unsafe.BitCast(5)); + // Conversion to/from a class should fail + + Assert.Throws(() => Unsafe.BitCast(string.Empty)); + Assert.Throws(() => Unsafe.BitCast(42)); + Assert.Throws(() => Unsafe.BitCast(string.Empty)); + + // Conversion to/from nullable value types should fail + + Assert.Throws(() => Unsafe.BitCast(42)); + Assert.Throws(() => Unsafe.BitCast(42)); + Assert.Throws(() => Unsafe.BitCast(42)); + // Conversion between floating-point and same sized integral should succeed Assert.Equal(0x8000_0000u, Unsafe.BitCast(-0.0f)); diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/AppDomainTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/AppDomainTests.cs index 1ef1c6557a74..cb89e2343a4c 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/AppDomainTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/AppDomainTests.cs @@ -7,6 +7,7 @@ using System.IO; using System.Net.Http; using System.Reflection; +using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; @@ -654,6 +655,24 @@ public void AssemblyResolve_IsNotCalledForCoreLibResources() }).Dispose(); } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void AssemblyResolve_IgnoresStrongNameMismatches() + { + RemoteExecutor.Invoke(() => + { + AppDomain.CurrentDomain.AssemblyResolve += + (sender, e) => + { + if (!e.Name.StartsWith("MyAssembly")) + return null; + + return AssemblyBuilder.DefineDynamicAssembly( + new AssemblyName("MyAssembly"), AssemblyBuilderAccess.Run); + }; + Assembly.Load("MyAssembly, PublicKeyToken=1234567890ABCDEF"); + }).Dispose(); + } + class CorrectlyPropagatesException : Exception { public CorrectlyPropagatesException(string message) : base(message) diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/EnvironmentTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/EnvironmentTests.cs index 4f30dfd0a09b..fd47fb81eb74 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/EnvironmentTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/EnvironmentTests.cs @@ -63,13 +63,13 @@ public void CurrentManagedThreadId_DifferentForActiveThreads() { var ids = new HashSet(); Barrier b = new Barrier(10); - Task.WaitAll((from i in Enumerable.Range(0, b.ParticipantCount) - select Task.Factory.StartNew(() => - { - b.SignalAndWait(); - lock (ids) ids.Add(Environment.CurrentManagedThreadId); - b.SignalAndWait(); - }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default)).ToArray()); + Task.WaitAll(from i in Enumerable.Range(0, b.ParticipantCount) + select Task.Factory.StartNew(() => + { + b.SignalAndWait(); + lock (ids) ids.Add(Environment.CurrentManagedThreadId); + b.SignalAndWait(); + }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default)); Assert.Equal(b.ParticipantCount, ids.Count); } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Combine.cs b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Combine.cs index 033168ce649a..9493d5aed543 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Combine.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Combine.cs @@ -98,6 +98,7 @@ public static void Combine(string[] paths) // Combine(string[]) Assert.Equal(expected, Path.Combine(paths)); + Assert.Equal(expected, Path.Combine((ReadOnlySpan)paths)); // Verify special cases switch (paths.Length) @@ -166,6 +167,10 @@ public static void ContainsInvalidCharWithRooted_Windows_core() private static void VerifyException(string[] paths) where T : Exception { Assert.Throws(() => Path.Combine(paths)); + if (paths != null) + { + Assert.Throws(() => Path.Combine((ReadOnlySpan)paths)); + } //verify passed as elements case if (paths != null) diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Join.cs b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Join.cs index 0984a9145385..f8b61049251f 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Join.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/IO/PathTests_Join.cs @@ -200,36 +200,42 @@ public void JoinStringArray_ThrowsArgumentNullException() public void JoinStringArray_ZeroLengthArray() { Assert.Equal(string.Empty, Path.Join(new string[0])); + Assert.Equal(string.Empty, Path.Join((ReadOnlySpan)new string[0])); } [Theory, MemberData(nameof(TestData_JoinOnePath))] public void JoinStringArray_1(string path1, string expected) { Assert.Equal(expected, Path.Join(new string[] { path1 })); + Assert.Equal(expected, Path.Join((ReadOnlySpan)new string[] { path1 })); } [Theory, MemberData(nameof(TestData_JoinTwoPaths))] public void JoinStringArray_2(string path1, string path2, string expected) { Assert.Equal(expected, Path.Join(new string[] { path1, path2 })); + Assert.Equal(expected, Path.Join((ReadOnlySpan)new string[] { path1, path2 })); } [Theory, MemberData(nameof(TestData_JoinThreePaths))] public void JoinStringArray_3(string path1, string path2, string path3, string expected) { Assert.Equal(expected, Path.Join(new string[] { path1, path2, path3 })); + Assert.Equal(expected, Path.Join((ReadOnlySpan)new string[] { path1, path2, path3 })); } [Theory, MemberData(nameof(TestData_JoinFourPaths))] public void JoinStringArray_4(string path1, string path2, string path3, string path4, string expected) { Assert.Equal(expected, Path.Join(new string[] { path1, path2, path3, path4 })); + Assert.Equal(expected, Path.Join((ReadOnlySpan)new string[] { path1, path2, path3, path4 })); } [Theory, MemberData(nameof(TestData_JoinFourPaths))] public void JoinStringArray_8(string path1, string path2, string path3, string path4, string fourJoined) { Assert.Equal(Path.Join(fourJoined, fourJoined), Path.Join(new string[] { path1, path2, path3, path4, path1, path2, path3, path4 })); + Assert.Equal(Path.Join(fourJoined, fourJoined), Path.Join((ReadOnlySpan)new string[] { path1, path2, path3, path4, path1, path2, path3, path4 })); } } } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/ILLink.Descriptors.iOS.xml b/src/libraries/System.Runtime/tests/System.Runtime.Tests/ILLink.Descriptors.iOS.xml new file mode 100644 index 000000000000..b327a37c7a60 --- /dev/null +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/ILLink.Descriptors.iOS.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj index 066a9994e31e..4356616834ee 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj @@ -13,9 +13,7 @@ true - - true - + true false @@ -345,7 +343,9 @@ - + + + diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ActivatorTests.Generic.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ActivatorTests.Generic.cs index 616cfd6b6d5d..e6ac3da7f459 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ActivatorTests.Generic.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ActivatorTests.Generic.cs @@ -61,6 +61,22 @@ public void CreateInstanceT_StructWithoutDefaultConstructor_InvokesConstructor() public void CreateInstanceT_StructWithDefaultConstructorThatThrows_ThrowsTargetInvocationException() => Assert.Throws(() => Activator.CreateInstance()); + [Fact] + public void CreateInstanceT_GenericTypes() + { + TestGenericClassWithDefaultConstructor(); + TestGenericClassWithDefaultConstructor(); + + TestGenericStructWithDefaultConstructor(); + TestGenericStructWithDefaultConstructor(); + + void TestGenericClassWithDefaultConstructor() + => Assert.Equal(typeof(T), Activator.CreateInstance>().TypeOfT); + + void TestGenericStructWithDefaultConstructor() + => Assert.Equal(typeof(T), Activator.CreateInstance>().TypeOfT); + } + private interface IInterface { } @@ -96,5 +112,27 @@ private class ClassWithDefaultConstructorThatThrows public ClassWithDefaultConstructorThatThrows() => throw new Exception(); } + + public class GenericClassWithDefaultConstructor + { + public GenericClassWithDefaultConstructor() => + TypeOfT = typeof(T); + + public Type TypeOfT { get; } + } + + public struct StructWithDefaultConstructorThatThrows + { + public StructWithDefaultConstructorThatThrows() => + throw new Exception(); + } + + public struct GenericStructWithDefaultConstructor + { + public GenericStructWithDefaultConstructor() => + TypeOfT = typeof(T); + + public Type TypeOfT { get; } + } } } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs index 05e71be7b325..d829eb1199d4 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Tests @@ -356,6 +357,172 @@ public static void op_InequalityTest() // IFloatingPoint // + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public static void ConvertToIntegerTest() + { + // Signed Values + + Assert.Equal(0, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(Int128.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToInteger(double.MinValue)); + + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + + Assert.Equal(-1, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(int.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(Int128.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(nint.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(-1, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + + // Unsigned Values + + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(UInt128.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + + Assert.Equal(byte.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(ushort.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(UInt128.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public static void ConvertToIntegerNativeTest() + { + // Signed Values + + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(Int128.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to int is natively supported and returns 0x8000_0000 + // * Conversion to long is natively supported on 64-bit and returns 0x8000_0000_0000_0000 + + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + + if (Environment.Is64BitProcess) + { + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + else + { + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + } + else + { + Assert.Equal(-1, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(int.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(nint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(-1, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + Assert.Equal(Int128.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + + // Unsigned Values + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to uint is natively supported w/ Avx512 and returns 0xFFFF_FFFF + // * Conversion to ulong is natively supported on 64-bit w/ Avx512 and returns 0xFFFF_FFFF_FFFF_FFFF + + if (Avx512F.IsSupported) + { + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + else + { + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + + if (Environment.Is64BitProcess && Avx512F.IsSupported) + { + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + else + { + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + } + else + { + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(UInt128.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to uint is natively supported w/ Avx512 and returns 0xFFFF_FFFF + // * Conversion to ulong is natively supported on 64-bit w/ Avx512 and returns 0xFFFF_FFFF_FFFF_FFFF + + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + else + { + Assert.Equal(byte.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(ushort.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(UInt128.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + [Fact] public static void GetExponentByteCountTest() { @@ -1055,7 +1222,7 @@ public static void CreateCheckedFromDecimalTest() AssertBitwiseEqual(-0.0, NumberBaseHelper.CreateChecked(-0.0m)); AssertBitwiseEqual(+0.0, NumberBaseHelper.CreateChecked(+0.0m)); AssertBitwiseEqual(+1.0, NumberBaseHelper.CreateChecked(+1.0m)); - AssertBitwiseEqual(+79228162514264337593543950335.0, NumberBaseHelper.CreateChecked(decimal.MaxValue)); + AssertBitwiseEqual(+79228162514264337593543950335.0, NumberBaseHelper.CreateChecked(decimal.MaxValue)); } [Fact] diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IO/Exceptions.HResults.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IO/Exceptions.HResults.cs index 777ffaebe963..0bf947e802e7 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IO/Exceptions.HResults.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IO/Exceptions.HResults.cs @@ -18,7 +18,6 @@ public static class HResults public const int COR_E_FILELOAD = unchecked((int)0x80131621); public const int FUSION_E_INVALID_NAME = unchecked((int)0x80131047); - public const int FUSION_E_PRIVATE_ASM_DISALLOWED = unchecked((int)0x80131044); public const int FUSION_E_REF_DEF_MISMATCH = unchecked((int)0x80131040); public const int ERROR_TOO_MANY_OPEN_FILES = unchecked((int)0x80070004); public const int ERROR_SHARING_VIOLATION = unchecked((int)0x80070020); diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IO/FileLoadException.InteropTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IO/FileLoadException.InteropTests.cs index 9d449775aa69..53b2f704547f 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IO/FileLoadException.InteropTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IO/FileLoadException.InteropTests.cs @@ -13,7 +13,6 @@ public static class FileLoadExceptionInteropTests [Theory] [InlineData(HResults.COR_E_FILELOAD)] [InlineData(HResults.FUSION_E_INVALID_NAME)] - [InlineData(HResults.FUSION_E_PRIVATE_ASM_DISALLOWED)] [InlineData(HResults.FUSION_E_REF_DEF_MISMATCH)] [InlineData(HResults.ERROR_TOO_MANY_OPEN_FILES)] [InlineData(HResults.ERROR_SHARING_VIOLATION)] diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int128Tests.GenericMath.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int128Tests.GenericMath.cs index 10c49230717d..66de69ce2eec 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int128Tests.GenericMath.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int128Tests.GenericMath.cs @@ -1012,6 +1012,12 @@ public static void op_GreaterThanTest() Assert.True(ComparisonOperatorsHelper.op_GreaterThan(MaxValue, 1)); Assert.False(ComparisonOperatorsHelper.op_GreaterThan(MinValue, 1)); Assert.False(ComparisonOperatorsHelper.op_GreaterThan(NegativeOne, 1)); + + Assert.True(ComparisonOperatorsHelper.op_GreaterThan(Zero, NegativeOne)); + Assert.True(ComparisonOperatorsHelper.op_GreaterThan(One, NegativeOne)); + Assert.True(ComparisonOperatorsHelper.op_GreaterThan(MaxValue, NegativeOne)); + Assert.False(ComparisonOperatorsHelper.op_GreaterThan(MinValue, NegativeOne)); + Assert.False(ComparisonOperatorsHelper.op_GreaterThan(NegativeOne, NegativeOne)); } [Fact] @@ -1022,6 +1028,12 @@ public static void op_GreaterThanOrEqualTest() Assert.True(ComparisonOperatorsHelper.op_GreaterThanOrEqual(MaxValue, 1)); Assert.False(ComparisonOperatorsHelper.op_GreaterThanOrEqual(MinValue, 1)); Assert.False(ComparisonOperatorsHelper.op_GreaterThanOrEqual(NegativeOne, 1)); + + Assert.True(ComparisonOperatorsHelper.op_GreaterThanOrEqual(Zero, NegativeOne)); + Assert.True(ComparisonOperatorsHelper.op_GreaterThanOrEqual(One, NegativeOne)); + Assert.True(ComparisonOperatorsHelper.op_GreaterThanOrEqual(MaxValue, NegativeOne)); + Assert.False(ComparisonOperatorsHelper.op_GreaterThanOrEqual(MinValue, NegativeOne)); + Assert.True(ComparisonOperatorsHelper.op_GreaterThanOrEqual(NegativeOne, NegativeOne)); } [Fact] @@ -1032,6 +1044,12 @@ public static void op_LessThanTest() Assert.False(ComparisonOperatorsHelper.op_LessThan(MaxValue, 1)); Assert.True(ComparisonOperatorsHelper.op_LessThan(MinValue, 1)); Assert.True(ComparisonOperatorsHelper.op_LessThan(NegativeOne, 1)); + + Assert.False(ComparisonOperatorsHelper.op_LessThan(Zero, NegativeOne)); + Assert.False(ComparisonOperatorsHelper.op_LessThan(One, NegativeOne)); + Assert.False(ComparisonOperatorsHelper.op_LessThan(MaxValue, NegativeOne)); + Assert.True(ComparisonOperatorsHelper.op_LessThan(MinValue, NegativeOne)); + Assert.False(ComparisonOperatorsHelper.op_LessThan(NegativeOne, NegativeOne)); } [Fact] @@ -1042,6 +1060,12 @@ public static void op_LessThanOrEqualTest() Assert.False(ComparisonOperatorsHelper.op_LessThanOrEqual(MaxValue, 1)); Assert.True(ComparisonOperatorsHelper.op_LessThanOrEqual(MinValue, 1)); Assert.True(ComparisonOperatorsHelper.op_LessThanOrEqual(NegativeOne, 1)); + + Assert.False(ComparisonOperatorsHelper.op_LessThanOrEqual(Zero, NegativeOne)); + Assert.False(ComparisonOperatorsHelper.op_LessThanOrEqual(One, NegativeOne)); + Assert.False(ComparisonOperatorsHelper.op_LessThanOrEqual(MaxValue, NegativeOne)); + Assert.True(ComparisonOperatorsHelper.op_LessThanOrEqual(MinValue, NegativeOne)); + Assert.True(ComparisonOperatorsHelper.op_LessThanOrEqual(NegativeOne, NegativeOne)); } // diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/MulticastDelegateTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/MulticastDelegateTests.cs index 9994fa02f10f..ab798d6442be 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/MulticastDelegateTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/MulticastDelegateTests.cs @@ -105,7 +105,19 @@ public static void Combine() D nothing = (D)(Delegate.Combine()); Assert.Null(nothing); - D one = (D)(Delegate.Combine(a)); + nothing = (D)(Delegate.Combine(null)); + Assert.Null(nothing); + + nothing = (D)(Delegate.Combine(ReadOnlySpan.Empty)); + Assert.Null(nothing); + + D one = (D)(Delegate.Combine(new[] { a })); + t1.Clear(); + one(5); + Assert.Equal("A5", t1.S); + CheckInvokeList(new D[] { a }, one, t1); + + one = (D)(Delegate.Combine((ReadOnlySpan)new[] { a })); t1.Clear(); one(5); Assert.Equal("A5", t1.S); @@ -117,13 +129,25 @@ public static void Combine() Assert.Equal("A5B5", t1.S); CheckInvokeList(new D[] { a, b }, ab, t1); - D abc = (D)(Delegate.Combine(a, b, c)); + D abc = (D)(Delegate.Combine(new[] { a, b, c })); t1.Clear(); abc(5); Assert.Equal("A5B5C5", t1.S); CheckInvokeList(new D[] { a, b, c }, abc, t1); - D abcdabc = (D)(Delegate.Combine(abc, d, abc)); + abc = (D)(Delegate.Combine((ReadOnlySpan)new[] { a, b, c })); + t1.Clear(); + abc(5); + Assert.Equal("A5B5C5", t1.S); + CheckInvokeList(new D[] { a, b, c }, abc, t1); + + D abcdabc = (D)(Delegate.Combine(new[] { abc, d, abc })); + t1.Clear(); + abcdabc(9); + Assert.Equal("A9B9C9D9A9B9C9", t1.S); + CheckInvokeList(new D[] { a, b, c, d, a, b, c }, abcdabc, t1); + + abcdabc = (D)(Delegate.Combine((ReadOnlySpan)new[] { abc, d, abc })); t1.Clear(); abcdabc(9); Assert.Equal("A9B9C9D9A9B9C9", t1.S); diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/NullableMetadataTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/NullableMetadataTests.cs index cb18c5e0222b..24a1de935ad2 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/NullableMetadataTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/NullableMetadataTests.cs @@ -132,6 +132,7 @@ public static void NullableAttributesOnPublicApiOnly(Type type) [Theory] [InlineData("mscorlib")] [InlineData("System.Threading.Overlapped")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/99592", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsAppleMobile))] public static void ShimsHaveOnlyTypeForwards(string assemblyName) { Assembly assembly = Assembly.Load(assemblyName); diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Reflection/MethodBaseTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Reflection/MethodBaseTests.cs index eeda2341e251..9d69ce855c6a 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Reflection/MethodBaseTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Reflection/MethodBaseTests.cs @@ -113,12 +113,18 @@ private static int MyOtherMethod(int x) public static void MyOtherMethod(object arg) { int var1 = 2; + Keep(ref var1); + string var2 = "I am a string"; + Keep(ref var2); if (arg == null) { throw new ArgumentNullException("Input arg cannot be null."); } + + // Reference local variables to prevent them from being optimized out by Roslyn + static void Keep(ref T value) { }; } #pragma warning restore xUnit1013 // Public method should be marked as test diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Reflection/MethodBodyTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Reflection/MethodBodyTests.cs index 146baf023bbf..eb6f4b36fab9 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Reflection/MethodBodyTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Reflection/MethodBodyTests.cs @@ -41,10 +41,10 @@ public static void Test_MethodBody_ExceptionHandlingClause() if (ehc.Flags != ExceptionHandlingClauseOptions.Finally && ehc.Flags != ExceptionHandlingClauseOptions.Filter) { Assert.Equal(typeof(Exception), ehc.CatchType); - Assert.Equal(19, ehc.HandlerLength); - Assert.Equal(70, ehc.HandlerOffset); + Assert.Equal(27, ehc.HandlerLength); + Assert.Equal(86, ehc.HandlerOffset); Assert.Equal(61, ehc.TryLength); - Assert.Equal(9, ehc.TryOffset); + Assert.Equal(25, ehc.TryOffset); return; } } @@ -64,10 +64,10 @@ public static void Test_MethodBody_ExceptionHandlingClause() if (ehc.Flags != ExceptionHandlingClauseOptions.Finally && ehc.Flags != ExceptionHandlingClauseOptions.Filter) { Assert.Equal(typeof(Exception), ehc.CatchType); - Assert.Equal(14, ehc.HandlerLength); - Assert.Equal(58, ehc.HandlerOffset); + Assert.Equal(21, ehc.HandlerLength); + Assert.Equal(72, ehc.HandlerOffset); Assert.Equal(50, ehc.TryLength); - Assert.Equal(8, ehc.TryOffset); + Assert.Equal(22, ehc.TryOffset); return; } } @@ -79,7 +79,10 @@ public static void Test_MethodBody_ExceptionHandlingClause() private static void MethodBodyExample(object arg) { int var1 = 2; + Keep(ref var1); + string var2 = "I am a string"; + Keep(ref var2); try { @@ -94,6 +97,7 @@ private static void MethodBodyExample(object arg) } catch (Exception ex) { + Keep(ref ex); Console.WriteLine(ex.Message); } finally @@ -101,6 +105,9 @@ private static void MethodBodyExample(object arg) var1 = 3; var2 = "I am a new string!"; } + + // Reference local variables to prevent them from being optimized out by Roslyn + static void Keep(ref T value) { }; } } } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/AttributesTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/AttributesTests.cs index 6f58cc48e5bf..bb7539a4e357 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/AttributesTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/AttributesTests.cs @@ -399,5 +399,12 @@ public static void RequiresLocationAttributeTests() { new RequiresLocationAttribute(); } + + [Fact] + public static void OverloadResolutionPriorityAttributeTests() + { + var attr = new OverloadResolutionPriorityAttribute(42); + Assert.Equal(42, attr.Priority); + } } } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/RuntimeHelpersTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/RuntimeHelpersTests.cs index afb72bbe0949..9e2dc8059fa8 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/RuntimeHelpersTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/RuntimeHelpersTests.cs @@ -438,6 +438,52 @@ public static void FixedAddressValueTypeTest() Assert.Equal(fixedPtr1, fixedPtr2); } + [InlineArray(3)] + private struct Byte3 + { + public byte b1; + } + + [Fact] + public static unsafe void SizeOf() + { + Assert.Equal(1, RuntimeHelpers.SizeOf(typeof(sbyte).TypeHandle)); + Assert.Equal(1, RuntimeHelpers.SizeOf(typeof(byte).TypeHandle)); + Assert.Equal(2, RuntimeHelpers.SizeOf(typeof(short).TypeHandle)); + Assert.Equal(2, RuntimeHelpers.SizeOf(typeof(ushort).TypeHandle)); + Assert.Equal(4, RuntimeHelpers.SizeOf(typeof(int).TypeHandle)); + Assert.Equal(4, RuntimeHelpers.SizeOf(typeof(uint).TypeHandle)); + Assert.Equal(8, RuntimeHelpers.SizeOf(typeof(long).TypeHandle)); + Assert.Equal(8, RuntimeHelpers.SizeOf(typeof(ulong).TypeHandle)); + Assert.Equal(4, RuntimeHelpers.SizeOf(typeof(float).TypeHandle)); + Assert.Equal(8, RuntimeHelpers.SizeOf(typeof(double).TypeHandle)); + Assert.Equal(3, RuntimeHelpers.SizeOf(typeof(Byte3).TypeHandle)); + Assert.Equal(nint.Size, RuntimeHelpers.SizeOf(typeof(void*).TypeHandle)); + Assert.Equal(nint.Size, RuntimeHelpers.SizeOf(typeof(delegate* ).TypeHandle)); + Assert.Equal(nint.Size, RuntimeHelpers.SizeOf(typeof(int).MakeByRefType().TypeHandle)); + Assert.Throws(() => RuntimeHelpers.SizeOf(default)); + Assert.ThrowsAny(() => RuntimeHelpers.SizeOf(typeof(List<>).TypeHandle)); + Assert.ThrowsAny(() => RuntimeHelpers.SizeOf(typeof(void).TypeHandle)); + } + + // We can't even get a RuntimeTypeHandle for a generic parameter type on NativeAOT, + // so we don't even get to the method we're testing. + // So, let's not even waste time running this test on NativeAOT + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotNativeAot))] + public static void SizeOfGenericParameter() + { + Assert.ThrowsAny(() => RuntimeHelpers.SizeOf(typeof(List<>).GetGenericArguments()[0].TypeHandle)); + } + + // We can't even get a RuntimeTypeHandle for a partially-open-generic type on NativeAOT, + // so we don't even get to the method we're testing. + // So, let's not even waste time running this test on NativeAOT + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotNativeAot))] + public static void SizeOfPartiallyOpenGeneric() + { + Assert.ThrowsAny(() => RuntimeHelpers.SizeOf(typeof(Dictionary<,>).MakeGenericType(typeof(object), typeof(Dictionary<,>).GetGenericArguments()[1]).TypeHandle)); + } + [Fact] public static void BoxPrimitive() { @@ -498,7 +544,7 @@ public static void BoxUnmanagedGenericStruct() { int value = 3; object result = RuntimeHelpers.Box(ref Unsafe.As(ref value), typeof(GenericStruct).TypeHandle); - + Assert.Equal(value, Assert.IsType>(result).data); } @@ -507,7 +553,7 @@ public static void BoxManagedGenericStruct() { object value = new(); object result = RuntimeHelpers.Box(ref Unsafe.As(ref value), typeof(GenericStruct).TypeHandle); - + Assert.Same(value, Assert.IsType>(result).data); } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs index a6637de7f7e2..21a4ba2cd77a 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Tests @@ -356,6 +357,172 @@ public static void op_InequalityTest() // IFloatingPoint // + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public static void ConvertToIntegerTest() + { + // Signed Values + + Assert.Equal(0, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(Int128.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToInteger(float.MinValue)); + + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + + Assert.Equal(-1, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(int.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(Int128.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(nint.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(-1, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + + // Unsigned Values + + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(UInt128.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + + Assert.Equal(byte.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(ushort.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(new UInt128(0xFFFF_FF00_0000_0000, 0x0000_0000_0000_0000), FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public static void ConvertToIntegerNativeTest() + { + // Signed Values + + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(Int128.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to int is natively supported and returns 0x8000_0000 + // * Conversion to long is natively supported on 64-bit and returns 0x8000_0000_0000_0000 + + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + + if (Environment.Is64BitProcess) + { + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + else + { + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + } + else + { + Assert.Equal(-1, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(int.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(nint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(-1, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + Assert.Equal(Int128.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + + // Unsigned Values + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to uint is natively supported w/ Avx512 and returns 0xFFFF_FFFF + // * Conversion to ulong is natively supported on 64-bit w/ Avx512 and returns 0xFFFF_FFFF_FFFF_FFFF + + if (Avx512F.IsSupported) + { + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + else + { + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + + if (Environment.Is64BitProcess && Avx512F.IsSupported) + { + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + else + { + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + } + else + { + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(UInt128.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to uint is natively supported w/ Avx512 and returns 0xFFFF_FFFF + // * Conversion to ulong is natively supported on 64-bit w/ Avx512 and returns 0xFFFF_FFFF_FFFF_FFFF + + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + else + { + Assert.Equal(byte.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(ushort.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(new UInt128(0xFFFF_FF00_0000_0000, 0x0000_0000_0000_0000), FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + [Fact] public static void GetExponentByteCountTest() { diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs index b12bd2cb74fc..037e7a98a958 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs @@ -141,6 +141,7 @@ public static void SplitNoMatchSingleResult() Assert.Equal(expected, Value.Split(',', Options)); Assert.Equal(expected, Value.Split(',', Count, Options)); Assert.Equal(expected, Value.Split(new[] { ',' })); + Assert.Equal(expected, Value.Split((ReadOnlySpan)new[] { ',' })); Assert.Equal(expected, Value.Split(new[] { ',' }, Options)); Assert.Equal(expected, Value.Split(new[] { ',' }, Count)); Assert.Equal(expected, Value.Split(new[] { ',' }, Count, Options)); @@ -516,6 +517,7 @@ public static void SplitCharSeparator(string value, char separator, int count, S { Assert.Equal(expected, value.Split(separator)); Assert.Equal(expected, value.Split(new[] { separator })); + Assert.Equal(expected, value.Split((ReadOnlySpan)new[] { separator })); Assert.Equal(expected, value.Split(separator.ToString())); } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/CompositeFormatTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/CompositeFormatTests.cs index bdfde206c850..64c0caf8f8c3 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/CompositeFormatTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/CompositeFormatTests.cs @@ -68,12 +68,15 @@ public static void MinimumArgumentCount_MatchesExpectedValue(string format, int Assert.Equal(expected, cf.MinimumArgumentCount); - string s = string.Format(null, cf, Enumerable.Repeat((object)"arg", expected).ToArray()); - Assert.NotNull(s); + object[] args = Enumerable.Repeat((object)"arg", expected).ToArray(); + Assert.NotNull(string.Format(null, cf, args)); + Assert.NotNull(string.Format(null, cf, (ReadOnlySpan)args)); if (expected != 0) { - Assert.Throws(() => string.Format(null, cf, Enumerable.Repeat((object)"arg", expected - 1).ToArray())); + args = Enumerable.Repeat((object)"arg", expected - 1).ToArray(); + Assert.Throws(() => string.Format(null, cf, args)); + Assert.Throws(() => string.Format(null, cf, (ReadOnlySpan)args)); } } @@ -86,21 +89,20 @@ public static void StringFormat_Valid(IFormatProvider provider, string format, o Assert.Same(format, cf.Format); Assert.Equal(expected, string.Format(provider, cf, values)); - - Assert.Equal(expected, string.Format(provider, cf, (ReadOnlySpan)values)); + Assert.Equal(expected, string.Format(provider, cf, (ReadOnlySpan)values)); switch (values.Length) { case 1: - Assert.Equal(expected, string.Format(provider, cf, values[0])); + Assert.Equal(expected, string.Format(provider, cf, arg0: values[0])); break; case 2: - Assert.Equal(expected, string.Format(provider, cf, values[0], values[1])); + Assert.Equal(expected, string.Format(provider, cf, arg0: values[0], arg1: values[1])); break; case 3: - Assert.Equal(expected, string.Format(provider, cf, values[0], values[1], values[2])); + Assert.Equal(expected, string.Format(provider, cf, arg0: values[0], arg1: values[1], arg2: values[2])); break; } } @@ -188,6 +190,8 @@ public static void MemoryExtensionsTryWrite_Valid(IFormatProvider provider, stri dest = new char[expected.Length - 1]; Assert.False(dest.AsSpan().TryWrite(provider, cf, out charsWritten, values)); Assert.Equal(0, charsWritten); + Assert.False(dest.AsSpan().TryWrite(provider, cf, out charsWritten, (ReadOnlySpan)values)); + Assert.Equal(0, charsWritten); } } @@ -209,16 +213,17 @@ public static void StringFormat_Invalid_FormatExceptionFromArgs(IFormatProvider Assert.NotNull(cf); Assert.Throws(() => string.Format(provider, cf, args)); + Assert.Throws(() => string.Format(provider, cf, (ReadOnlySpan)args)); switch (args.Length) { case 1: - Assert.Throws(() => string.Format(provider, cf, args[0])); + Assert.Throws(() => string.Format(provider, cf, arg0: args[0])); break; case 2: - Assert.Throws(() => string.Format(provider, cf, args[0], args[1])); + Assert.Throws(() => string.Format(provider, cf, arg0: args[0], arg1: args[1])); break; case 3: - Assert.Throws(() => string.Format(provider, cf, args[0], args[1], args[2])); + Assert.Throws(() => string.Format(provider, cf, arg0: args[0], arg1: args[1], arg2: args[2])); break; } } @@ -233,16 +238,17 @@ public static void StringBuilderAppendFormat_Invalid_FormatExceptionFromArgs(IFo var sb = new StringBuilder(); Assert.Throws(() => sb.AppendFormat(provider, cf, args)); + Assert.Throws(() => sb.AppendFormat(provider, cf, (ReadOnlySpan)args)); switch (args.Length) { case 1: - Assert.Throws(() => sb.AppendFormat(provider, cf, args[0])); + Assert.Throws(() => sb.AppendFormat(provider, cf, arg0: args[0])); break; case 2: - Assert.Throws(() => sb.AppendFormat(provider, cf, args[0], args[1])); + Assert.Throws(() => sb.AppendFormat(provider, cf, arg0: args[0], arg1: args[1])); break; case 3: - Assert.Throws(() => sb.AppendFormat(provider, cf, args[0], args[1], args[2])); + Assert.Throws(() => sb.AppendFormat(provider, cf, arg0: args[0], arg1: args[1], arg2: args[2])); break; } } @@ -257,16 +263,17 @@ public static void MemoryExtensionsTryWrite_Invalid_FormatExceptionFromArgs(IFor char[] dest = new char[1024]; Assert.Throws(() => new Span(dest).TryWrite(provider, cf, out _, args)); + Assert.Throws(() => new Span(dest).TryWrite(provider, cf, out _, (ReadOnlySpan)args)); switch (args.Length) { case 1: Assert.Throws(() => new Span(dest).TryWrite(provider, cf, out _, args[0])); break; case 2: - Assert.Throws(() => new Span(dest).TryWrite(provider, cf, out _, args[0], args[1])); + Assert.Throws(() => new Span(dest).TryWrite(provider, cf, out _, arg0: args[0], arg1: args[1])); break; case 3: - Assert.Throws(() => new Span(dest).TryWrite(provider, cf, out _, args[0], args[1], args[2])); + Assert.Throws(() => new Span(dest).TryWrite(provider, cf, out _, arg0: args[0], arg1: args[1], arg2: args[2])); break; } } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/StringBuilderTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/StringBuilderTests.cs index 2d1f569dd103..5671c6d3614e 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/StringBuilderTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/StringBuilderTests.cs @@ -842,6 +842,19 @@ public static void AppendFormat(string original, IFormatProvider provider, strin builder = new StringBuilder(original); builder.AppendFormat(provider, format, values); Assert.Equal(expected, builder.ToString()); + + // Use AppendFormat(string, ReadOnlySpan) or AppendFormat(IFormatProvider, string, ReadOnlySpan) + if (provider == null) + { + // Use AppendFormat(string, ReadOnlySpan) + builder = new StringBuilder(original); + builder.AppendFormat(format, (ReadOnlySpan)values); + Assert.Equal(expected, builder.ToString()); + } + // Use AppendFormat(IFormatProvider, string, ReadOnlySpan) + builder = new StringBuilder(original); + builder.AppendFormat(provider, format, (ReadOnlySpan)values); + Assert.Equal(expected, builder.ToString()); } [Fact] @@ -855,17 +868,21 @@ public static void AppendFormat_Invalid() var obj2 = new object(); var obj3 = new object(); var obj4 = new object(); + var objArray = new object[] { obj1, obj2, obj3, obj4 }; AssertExtensions.Throws("format", () => builder.AppendFormat(null, obj1)); // Format is null AssertExtensions.Throws("format", () => builder.AppendFormat(null, obj1, obj2, obj3)); // Format is null - AssertExtensions.Throws("format", () => builder.AppendFormat(null, obj1, obj2, obj3)); // Format is null AssertExtensions.Throws("format", () => builder.AppendFormat(null, obj1, obj2, obj3, obj4)); // Format is null + AssertExtensions.Throws("format", () => builder.AppendFormat(null, objArray)); // Format is null + AssertExtensions.Throws("format", () => builder.AppendFormat(null, (ReadOnlySpan)objArray)); // Format is null AssertExtensions.Throws("args", () => builder.AppendFormat("", null)); // Args is null AssertExtensions.Throws("format", () => builder.AppendFormat(null, (object[])null)); // Both format and args are null AssertExtensions.Throws("format", () => builder.AppendFormat(formatter, (string)null, obj1)); // Format is null AssertExtensions.Throws("format", () => builder.AppendFormat(formatter, (string)null, obj1, obj2)); // Format is null AssertExtensions.Throws("format", () => builder.AppendFormat(formatter, (string)null, obj1, obj2, obj3)); // Format is null AssertExtensions.Throws("format", () => builder.AppendFormat(formatter, (string)null, obj1, obj2, obj3, obj4)); // Format is null + AssertExtensions.Throws("format", () => builder.AppendFormat(formatter, (string)null, objArray)); // Format is null + AssertExtensions.Throws("format", () => builder.AppendFormat(formatter, (string)null, (ReadOnlySpan)objArray)); // Format is null AssertExtensions.Throws("args", () => builder.AppendFormat(formatter, "", null)); // Args is null AssertExtensions.Throws("format", () => builder.AppendFormat(formatter, (string)null, null)); // Both format and args are null @@ -873,19 +890,27 @@ public static void AppendFormat_Invalid() Assert.Throws(() => builder.AppendFormat("{-1}", obj1, obj2)); // Format has value < 0 Assert.Throws(() => builder.AppendFormat("{-1}", obj1, obj2, obj3)); // Format has value < 0 Assert.Throws(() => builder.AppendFormat("{-1}", obj1, obj2, obj3, obj4)); // Format has value < 0 + Assert.Throws(() => builder.AppendFormat("{-1}", objArray)); // Format has value < 0 + Assert.Throws(() => builder.AppendFormat("{-1}", (ReadOnlySpan)objArray)); // Format has value < 0 Assert.Throws(() => builder.AppendFormat(formatter, "{-1}", obj1)); // Format has value < 0 Assert.Throws(() => builder.AppendFormat(formatter, "{-1}", obj1, obj2)); // Format has value < 0 Assert.Throws(() => builder.AppendFormat(formatter, "{-1}", obj1, obj2, obj3)); // Format has value < 0 Assert.Throws(() => builder.AppendFormat(formatter, "{-1}", obj1, obj2, obj3, obj4)); // Format has value < 0 + Assert.Throws(() => builder.AppendFormat(formatter, "{-1}", objArray)); // Format has value < 0 + Assert.Throws(() => builder.AppendFormat(formatter, "{-1}", (ReadOnlySpan)objArray)); // Format has value < 0 Assert.Throws(() => builder.AppendFormat("{1}", obj1)); // Format has value >= 1 Assert.Throws(() => builder.AppendFormat("{2}", obj1, obj2)); // Format has value >= 2 Assert.Throws(() => builder.AppendFormat("{3}", obj1, obj2, obj3)); // Format has value >= 3 Assert.Throws(() => builder.AppendFormat("{4}", obj1, obj2, obj3, obj4)); // Format has value >= 4 + Assert.Throws(() => builder.AppendFormat("{4}", objArray)); // Format has value >= 4 + Assert.Throws(() => builder.AppendFormat("{4}", (ReadOnlySpan)objArray)); // Format has value >= 4 Assert.Throws(() => builder.AppendFormat(formatter, "{1}", obj1)); // Format has value >= 1 Assert.Throws(() => builder.AppendFormat(formatter, "{2}", obj1, obj2)); // Format has value >= 2 Assert.Throws(() => builder.AppendFormat(formatter, "{3}", obj1, obj2, obj3)); // Format has value >= 3 Assert.Throws(() => builder.AppendFormat(formatter, "{4}", obj1, obj2, obj3, obj4)); // Format has value >= 4 + Assert.Throws(() => builder.AppendFormat(formatter, "{4}", objArray)); // Format has value >= 4 + Assert.Throws(() => builder.AppendFormat(formatter, "{4}", (ReadOnlySpan)objArray)); // Format has value >= 4 Assert.Throws(() => builder.AppendFormat("{", "")); // Format has unescaped { Assert.Throws(() => builder.AppendFormat("{a", "")); // Format has unescaped { @@ -900,7 +925,9 @@ public static void AppendFormat_Invalid() Assert.Throws(() => builder.AppendFormat("{0 ", "")); // Format with index and spaces is not closed Assert.Throws(() => builder.AppendFormat("{1000000", new string[10])); // Format index is too long + Assert.Throws(() => builder.AppendFormat("{1000000", (ReadOnlySpan)new string[10])); // Format index is too long Assert.Throws(() => builder.AppendFormat("{10000000}", new string[10])); // Format index is too long + Assert.Throws(() => builder.AppendFormat("{10000000}", (ReadOnlySpan)new string[10])); // Format index is too long Assert.Throws(() => builder.AppendFormat("{0,", "")); // Format with comma is not closed Assert.Throws(() => builder.AppendFormat("{0, ", "")); // Format with comma and spaces is not closed @@ -910,13 +937,19 @@ public static void AppendFormat_Invalid() Assert.Throws(() => builder.AppendFormat("{0,-a", "")); // Format has invalid character after minus sign Assert.Throws(() => builder.AppendFormat("{0,1000000", new string[10])); // Format length is too long + Assert.Throws(() => builder.AppendFormat("{0,1000000", (ReadOnlySpan)new string[10])); // Format length is too long Assert.Throws(() => builder.AppendFormat("{0,10000000}", new string[10])); // Format length is too long + Assert.Throws(() => builder.AppendFormat("{0,10000000}", (ReadOnlySpan)new string[10])); // Format length is too long Assert.Throws(() => builder.AppendFormat("{0:", new string[10])); // Format with colon is not closed + Assert.Throws(() => builder.AppendFormat("{0:", (ReadOnlySpan)new string[10])); // Format with colon is not closed Assert.Throws(() => builder.AppendFormat("{0: ", new string[10])); // Format with colon and spaces is not closed + Assert.Throws(() => builder.AppendFormat("{0: ", (ReadOnlySpan)new string[10])); // Format with colon and spaces is not closed Assert.Throws(() => builder.AppendFormat("{0:{", new string[10])); // Format with custom format contains unescaped { + Assert.Throws(() => builder.AppendFormat("{0:{", (ReadOnlySpan)new string[10])); // Format with custom format contains unescaped { Assert.Throws(() => builder.AppendFormat("{0:{}", new string[10])); // Format with custom format contains unescaped { + Assert.Throws(() => builder.AppendFormat("{0:{}", (ReadOnlySpan)new string[10])); // Format with custom format contains unescaped { Assert.Throws(() => builder.AppendFormat("{0}", new TooManyCharsWrittenSpanFormattable())); // ISpanFormattable that returns more characters than it actually wrote } @@ -1775,11 +1808,15 @@ public static void AppendJoin_TestValues(object[] values, string expected) var enumerable = values.Select(_ => _); Assert.Equal(expected, new StringBuilder().AppendJoin('|', values).ToString()); + Assert.Equal(expected, new StringBuilder().AppendJoin('|', (ReadOnlySpan)values).ToString()); Assert.Equal(expected, new StringBuilder().AppendJoin('|', enumerable).ToString()); Assert.Equal(expected, new StringBuilder().AppendJoin('|', stringValues).ToString()); + Assert.Equal(expected, new StringBuilder().AppendJoin('|', (ReadOnlySpan)stringValues).ToString()); Assert.Equal(expected, new StringBuilder().AppendJoin("|", values).ToString()); + Assert.Equal(expected, new StringBuilder().AppendJoin("|", (ReadOnlySpan)values).ToString()); Assert.Equal(expected, new StringBuilder().AppendJoin("|", enumerable).ToString()); Assert.Equal(expected, new StringBuilder().AppendJoin("|", stringValues).ToString()); + Assert.Equal(expected, new StringBuilder().AppendJoin("|", (ReadOnlySpan)stringValues).ToString()); } [Fact] @@ -1801,9 +1838,14 @@ private sealed class NullToStringObject [InlineData(", ", "1, 2, 3")] public static void AppendJoin_TestStringSeparators(string separator, string expected) { - Assert.Equal(expected, new StringBuilder().AppendJoin(separator, new object[] { 1, 2, 3 }).ToString()); + var values = new object[] { 1, 2, 3 }; + var stringValues = new string[] { "1", "2", "3" }; + + Assert.Equal(expected, new StringBuilder().AppendJoin(separator, values).ToString()); + Assert.Equal(expected, new StringBuilder().AppendJoin(separator, (ReadOnlySpan)values).ToString()); Assert.Equal(expected, new StringBuilder().AppendJoin(separator, Enumerable.Range(1, 3)).ToString()); - Assert.Equal(expected, new StringBuilder().AppendJoin(separator, new string[] { "1", "2", "3" }).ToString()); + Assert.Equal(expected, new StringBuilder().AppendJoin(separator, stringValues).ToString()); + Assert.Equal(expected, new StringBuilder().AppendJoin(separator, (ReadOnlySpan)stringValues).ToString()); } @@ -1825,12 +1867,16 @@ public static void AppendJoin_NoValues_NoSpareCapacity_DoesNotThrow(string separ if (separator?.Length == 1) { CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], values); + CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], (ReadOnlySpan)values); CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], enumerable); CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], stringValues); + CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], (ReadOnlySpan)stringValues); } CreateBuilderWithNoSpareCapacity().AppendJoin(separator, values); + CreateBuilderWithNoSpareCapacity().AppendJoin(separator, (ReadOnlySpan)values); CreateBuilderWithNoSpareCapacity().AppendJoin(separator, enumerable); CreateBuilderWithNoSpareCapacity().AppendJoin(separator, stringValues); + CreateBuilderWithNoSpareCapacity().AppendJoin(separator, (ReadOnlySpan)stringValues); } [Theory] @@ -1849,12 +1895,16 @@ public static void AppendJoin_NoSpareCapacity_ThrowsArgumentOutOfRangeException( if (separator?.Length == 1) { AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], values)); + AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], (ReadOnlySpan)values)); AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], enumerable)); AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], stringValues)); + AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], (ReadOnlySpan)stringValues)); } AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, values)); + AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, (ReadOnlySpan)values)); AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, enumerable)); AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, stringValues)); + AssertExtensions.Throws(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, (ReadOnlySpan)stringValues)); } [Theory] diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/TimeZoneInfoTests.cs index a927e0a12990..16818b51ab89 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/TimeZoneInfoTests.cs @@ -3060,7 +3060,7 @@ public static void TestTimeZoneIdBackwardCompatibility(string oldId, string curr // Note we cannot test the DisplayName, as it will contain the ID. } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWasmThreadingSupported))] [PlatformSpecific(TestPlatforms.Browser)] [InlineData("America/Buenos_Aires")] [InlineData("America/Catamarca")] diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/TestStructs/System.TestStructs.il b/src/libraries/System.Runtime/tests/System.Runtime.Tests/TestStructs/System.TestStructs.il index a7573c0116d6..2be57ece0cc3 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/TestStructs/System.TestStructs.il +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/TestStructs/System.TestStructs.il @@ -57,18 +57,6 @@ ret } } - - .class public sequential sealed StructWithDefaultConstructorThatThrows - extends [System.Runtime]System.ValueType - { - .size 1 - - .method public hidebysig specialname rtspecialname instance void .ctor () cil managed - { - newobj instance void [System.Runtime]System.Exception::.ctor() - throw - } - } } .class public sequential sealed '.GlobalStructStartingWithDot' diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/InvariantGlobalizationTrue.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/InvariantGlobalizationTrue.cs index fe878e3a7459..27ab1b136b5a 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/InvariantGlobalizationTrue.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/InvariantGlobalizationTrue.cs @@ -4,6 +4,7 @@ using System; using System.Globalization; using System.Reflection; +using System.Runtime.CompilerServices; /// /// Ensures setting InvariantGlobalization = true still works in a trimmed app. @@ -27,6 +28,18 @@ static int Main(string[] args) { return -3; } + + // The rest of this code depends on a property of IL level trimming that keeps reflection + // metadata for anything that is statically reachable. It's not applicable if we're not doing that + // kind of trimming. Approximate what kind of trimming are we doing. + if (GetMethodSecretly(typeof(Program), nameof(GetCoreLibType)) == null) + { + // Sanity check: we only expect this for native AOT; IsDynamicCodeSupported approximates that. + if (RuntimeFeature.IsDynamicCodeSupported) + throw new Exception(); + + return 100; + } // Ensure the internal GlobalizationMode class is trimmed correctly. Type globalizationMode = GetCoreLibType("System.Globalization.GlobalizationMode"); @@ -65,4 +78,8 @@ static int Main(string[] args) // The intention of this method is to ensure the trimmer doesn't preserve the Type. private static Type GetCoreLibType(string name) => typeof(object).Assembly.GetType(name, throwOnError: false); + + // The intention is to look for a method on a type in a way that trimming cannot detect. + private static MethodBase GetMethodSecretly(Type type, string name) => + type.GetMethod(name, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/System.Runtime.TrimmingTests.proj b/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/System.Runtime.TrimmingTests.proj index c9c42b2c2023..6cfdea28f5e0 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/System.Runtime.TrimmingTests.proj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/System.Runtime.TrimmingTests.proj @@ -43,6 +43,8 @@ and tested with this test. Issue https://github.com/dotnet/runtime/issues/48849 is tracking investigation on why this test is failing if not skipped. --> browser-wasm + + true + true NullabilityInfoContextSupport @@ -62,6 +66,8 @@ System.Threading.ThreadPool.UseWindowsThreadPool + + true System.Threading.ThreadPool.UseWindowsThreadPool diff --git a/src/libraries/System.Runtime/tests/System.Security.SecureString.Tests/SecureStringTests.cs b/src/libraries/System.Runtime/tests/System.Security.SecureString.Tests/SecureStringTests.cs index ed094b312326..6fabfc8cfe3c 100644 --- a/src/libraries/System.Runtime/tests/System.Security.SecureString.Tests/SecureStringTests.cs +++ b/src/libraries/System.Runtime/tests/System.Security.SecureString.Tests/SecureStringTests.cs @@ -499,7 +499,7 @@ public static void Grow_Large() break; } } - })).ToArray()); + }))); } } diff --git a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/CESchedulerPairTests.cs b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/CESchedulerPairTests.cs index 7bc44998523a..0dd20961e6e6 100644 --- a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/CESchedulerPairTests.cs +++ b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/CESchedulerPairTests.cs @@ -244,7 +244,7 @@ public static void TestMaxItemsPerTask(int maxConcurrency, int maxItemsPerTask, } //finally wait for all of the tasks, to ensure they all executed properly - Task.WaitAll(taskList.ToArray()); + Task.WaitAll(taskList); if (!completeBeforeTaskWait) { @@ -292,7 +292,7 @@ public static void TestLowerConcurrencyLevel() //finally unblock the blocjedTask and wait for all of the tasks, to ensure they all executed properly blockReaderTaskEvent.Set(); - Task.WaitAll(taskList.ToArray()); + Task.WaitAll(taskList); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] @@ -325,7 +325,7 @@ public static void TestConcurrentBlockage() } blockExclusiveTaskEvent.Set(); - Task.WaitAll(taskList.ToArray()); + Task.WaitAll(taskList); } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] @@ -482,7 +482,7 @@ public static void TestSchedulerNesting() } // Wait for all tasks to complete, then complete the schedulers - Task.WaitAll(tasks.ToArray()); + Task.WaitAll(tasks); foreach (var cesp in cesps) { cesp.Complete(); diff --git a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/CancellationTokenTests.cs b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/CancellationTokenTests.cs index ba75f617bf0b..0d48e3840d96 100644 --- a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/CancellationTokenTests.cs +++ b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/CancellationTokenTests.cs @@ -207,6 +207,7 @@ public static void TokenSourceDispose_Negative() //shouldn't throw CancellationTokenSource.CreateLinkedTokenSource(new[] { token, token }); + CancellationTokenSource.CreateLinkedTokenSource((ReadOnlySpan)new[] { token, token }); } /// @@ -431,15 +432,20 @@ public static void CreateLinkedTokenSource_Simple_TwoToken() "CreateLinkedToken_Simple_TwoToken: The combined token should now be signalled"); } - [Fact] - public static void CreateLinkedTokenSource_Simple_MultiToken() + [Theory] + [InlineData(false)] + [InlineData(true)] + public static void CreateLinkedTokenSource_Simple_MultiToken(bool useSpan) { CancellationTokenSource signal1 = new CancellationTokenSource(); CancellationTokenSource signal2 = new CancellationTokenSource(); CancellationTokenSource signal3 = new CancellationTokenSource(); //Neither token is signalled. - CancellationTokenSource combined = CancellationTokenSource.CreateLinkedTokenSource(new[] { signal1.Token, signal2.Token, signal3.Token }); + CancellationTokenSource combined = useSpan ? + CancellationTokenSource.CreateLinkedTokenSource((ReadOnlySpan)new[] { signal1.Token, signal2.Token, signal3.Token }) : + CancellationTokenSource.CreateLinkedTokenSource(new[] { signal1.Token, signal2.Token, signal3.Token }); + Assert.False(combined.IsCancellationRequested, "CreateLinkedToken_Simple_MultiToken: The combined token should start unsignalled"); @@ -874,7 +880,6 @@ static void FinalizeHelper(DisposeTracker disposeTracker) // Several tests for deriving custom user types from CancellationTokenSource [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/99519", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public static void DerivedCancellationTokenSource() { // Verify that a derived CTS is functional diff --git a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/MethodCoverage.cs b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/MethodCoverage.cs index 2634e8340ef9..695cd6abb171 100644 --- a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/MethodCoverage.cs +++ b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/MethodCoverage.cs @@ -188,14 +188,30 @@ public static void Task_WhenAny_TwoTasks_InvalidArgs_Throws() AssertExtensions.Throws("task2", () => Task.WhenAny(Task.FromResult(2), null)); } + [Fact] + public static void Task_WhenAny_NullTaskElement_Throws() + { + AssertExtensions.Throws("tasks", () => { Task.WhenAny(new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAny((ReadOnlySpan)new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAny(NullElementIterator()); }); + + AssertExtensions.Throws("tasks", () => { Task.WhenAny(new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAny((ReadOnlySpan>)new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAny(NullElementIterator>()); }); + + static IEnumerable NullElementIterator() where T : Task { yield return null; } + } + [Fact] public static void Task_WhenAny_NoTasks_Throws() { AssertExtensions.Throws("tasks", () => { Task.WhenAny(new Task[0]); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAny(ReadOnlySpan.Empty); }); AssertExtensions.Throws("tasks", () => { Task.WhenAny(new List()); }); AssertExtensions.Throws("tasks", () => { Task.WhenAny(EmptyIterator()); }); AssertExtensions.Throws("tasks", () => { Task.WhenAny(new Task[0]); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAny(ReadOnlySpan>.Empty); }); AssertExtensions.Throws("tasks", () => { Task.WhenAny(new List>()); }); AssertExtensions.Throws("tasks", () => { Task.WhenAny(EmptyIterator>()); }); @@ -279,7 +295,6 @@ public static async Task Task_WhenAny_TwoTasks_WakesOnFirstCompletion() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/99500", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public static void CancellationTokenRegitration() { ManualResetEvent mre = new ManualResetEvent(false); @@ -297,7 +312,6 @@ public static void CancellationTokenRegitration() /// verify that the taskawaiter.UnsafeOnCompleted is invoked /// [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/99519", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public static void TaskAwaiter() { ManualResetEvent mre = new ManualResetEvent(false); @@ -353,6 +367,36 @@ public static void FromAsync() mre2.WaitOne(); } + [Fact] + public static void Task_WaitAll_NullArgument_Throws() + { + AssertExtensions.Throws("tasks", () => { Task.WaitAll((Task[])null); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll((Task[])null, CancellationToken.None); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll((Task[])null, 30_000); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll((Task[])null, TimeSpan.FromSeconds(30)); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll((Task[])null, 30_000, CancellationToken.None); }); + } + + [Fact] + public static void Task_WaitAll_NullTaskElement_Throws() + { + Task[] nullElement = [null]; + AssertExtensions.Throws("tasks", () => { Task.WaitAll(nullElement); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll((ReadOnlySpan)nullElement); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll(nullElement, CancellationToken.None); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll(nullElement, 30_000); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll(nullElement, TimeSpan.FromSeconds(30)); }); + AssertExtensions.Throws("tasks", () => { Task.WaitAll(nullElement, 30_000, CancellationToken.None); }); + } + + [Fact] + public static void Task_WaitAll_InvalidArgument_Throws() + { + Assert.Throws(() => Task.WaitAll([Task.Factory.StartNew(() => { })], -2)); + Assert.Throws(() => Task.WaitAll([Task.Factory.StartNew(() => { })], -2, CancellationToken.None)); + Assert.Throws(() => Task.WaitAll([Task.Factory.StartNew(() => { })], TimeSpan.FromMilliseconds(-2))); + } + [Fact] public static void Task_WhenAll_NullArgument_Throws() { @@ -363,14 +407,30 @@ public static void Task_WhenAll_NullArgument_Throws() AssertExtensions.Throws("tasks", () => { Task.WhenAll((IEnumerable>)null); }); } + [Fact] + public static void Task_WhenAll_NullTaskElement_Throws() + { + AssertExtensions.Throws("tasks", () => { Task.WhenAll(new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAll((ReadOnlySpan)new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAll(NullElementIterator()); }); + + AssertExtensions.Throws("tasks", () => { Task.WhenAll(new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAll((ReadOnlySpan>)new Task[] { null }); }); + AssertExtensions.Throws("tasks", () => { Task.WhenAll(NullElementIterator>()); }); + + static IEnumerable NullElementIterator() where T : Task { yield return null; } + } + [Fact] public static void Task_WhenAll_NoTasks_IsCompletedSuccessfully() { Assert.True(Task.WhenAll(new Task[0]).IsCompletedSuccessfully); + Assert.True(Task.WhenAll(ReadOnlySpan.Empty).IsCompletedSuccessfully); Assert.True(Task.WhenAll(new List()).IsCompletedSuccessfully); Assert.True(Task.WhenAll(EmptyIterator()).IsCompletedSuccessfully); AssertIsCompletedWithEmptyResult(Task.WhenAll(new Task[0])); + AssertIsCompletedWithEmptyResult(Task.WhenAll(ReadOnlySpan>.Empty)); AssertIsCompletedWithEmptyResult(Task.WhenAll(new List>())); AssertIsCompletedWithEmptyResult(Task.WhenAll(EmptyIterator>())); diff --git a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/AsyncEnumerableToBlockingEnumerableTests.cs b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/AsyncEnumerableToBlockingEnumerableTests.cs index 786734ad8391..0692aedb514f 100644 --- a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/AsyncEnumerableToBlockingEnumerableTests.cs +++ b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/AsyncEnumerableToBlockingEnumerableTests.cs @@ -70,7 +70,6 @@ static async IAsyncEnumerable CreateSourceEnumerable() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/99519", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public static void AsyncEnumerableWithDelays() { var source = new InstrumentedAsyncEnumerable(CreateSourceEnumerable()); @@ -105,7 +104,6 @@ static async IAsyncEnumerable CreateSourceEnumerable() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/99519", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public static void AsyncEnumerableWithException() { var source = new InstrumentedAsyncEnumerable(CreateSourceEnumerable()); @@ -134,7 +132,6 @@ static async IAsyncEnumerable CreateSourceEnumerable() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/99519", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public static void AsyncEnumerableWithCancellation() { var source = new InstrumentedAsyncEnumerable(CreateSourceEnumerable()); diff --git a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskContinueWithTests.cs b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskContinueWithTests.cs index 76803afb0195..2800a5e9e24c 100644 --- a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskContinueWithTests.cs +++ b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskContinueWithTests.cs @@ -1076,7 +1076,6 @@ public static void RunContinuationCancelTest_State() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/99519", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public static void TestNoDeadlockOnContinueWith() { Debug.WriteLine("TestNoDeadlockOnContinueWith: shouldn't deadlock if it passes."); @@ -1256,7 +1255,6 @@ public static void LongContinuationChain_Unwrap_DoesNotStackOverflow() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/99519", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public static void LongContinuationChain_Await_DoesNotStackOverflow() { const int DiveDepth = 12_000; diff --git a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskRtTests_Core.cs b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskRtTests_Core.cs index 088c45ddc116..1225ca6433a2 100644 --- a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskRtTests_Core.cs +++ b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskRtTests_Core.cs @@ -1338,11 +1338,6 @@ public static void RunTaskWaitAnyTests_WithCancellationTokenTests() [OuterLoop] public static void RunTaskWaitAllTests() { - Assert.Throws(() => Task.WaitAll((Task[])null)); - AssertExtensions.Throws("tasks", () => Task.WaitAll(new Task[] { null })); - Assert.Throws(() => Task.WaitAll(new Task[] { Task.Factory.StartNew(() => { }) }, -2)); - Assert.Throws(() => Task.WaitAll(new Task[] { Task.Factory.StartNew(() => { }) }, TimeSpan.FromMilliseconds(-2))); - ThreadPoolHelpers.EnsureMinThreadsAtLeast(10); RunTaskWaitAllTest(false, 1); RunTaskWaitAllTest(false, 10); diff --git a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskWaitAllAnyTest.cs b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskWaitAllAnyTest.cs index cb8adbc17925..61d5e4fc0179 100644 --- a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskWaitAllAnyTest.cs +++ b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/Task/TaskWaitAllAnyTest.cs @@ -220,7 +220,6 @@ public TaskWaitAllAnyTest(TestParameters_WaitAllAny parameters) /// /// The method that will run the scenario /// - /// internal void RealRun() { //create the tasks @@ -325,7 +324,6 @@ private void CreateTask() /// - the returned index form WaitAny should correspond to a completed task /// - in case of Cancelled and Exception tests the right exceptions should be got for WaitAll /// - /// private void Verify() { // verification for WaitAll @@ -1255,5 +1253,43 @@ public static void TaskWaitAllAny58() TaskWaitAllAnyTest test = new TaskWaitAllAnyTest(parameters); test.RealRun(); } + + [Fact] + public static void TaskWaitAll_Enumerable_InvalidArguments() + { + AssertExtensions.Throws("tasks", () => Task.WaitAll((IEnumerable)null)); + AssertExtensions.Throws("tasks", () => Task.WaitAll((IEnumerable)[null])); + AssertExtensions.Throws("tasks", () => Task.WaitAll((IEnumerable)[Task.CompletedTask, null])); + AssertExtensions.Throws("tasks", () => Task.WaitAll((IEnumerable)[null, Task.CompletedTask])); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + public static void TaskWaitAll_Enumerable_Canceled() + { + var tcs = new TaskCompletionSource(); + + Assert.Throws(() => Task.WaitAll((IEnumerable)[tcs.Task], new CancellationToken(true))); + + using var cts = new CancellationTokenSource(1); + Assert.Throws(() => Task.WaitAll((IEnumerable)[Task.CompletedTask, tcs.Task], cts.Token)); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + public static void TaskWaitAll_Enumerable_AllComplete() + { + Task.WaitAll((IEnumerable)[]); + Task.WaitAll((IEnumerable)[Task.CompletedTask]); + Task.WaitAll((IEnumerable)[Task.CompletedTask, Task.CompletedTask]); + + Task.WaitAll((IEnumerable)(Task[])[Task.CompletedTask, Task.CompletedTask]); + + Task.WaitAll((List)[]); + Task.WaitAll((List)[Task.CompletedTask]); + Task.WaitAll((List)[Task.CompletedTask, Task.CompletedTask]); + + Task.WaitAll((IEnumerable)[Task.Delay(1)]); + Task.WaitAll((List)[Task.Delay(1)]); + Task.WaitAll((IEnumerable)[Task.Delay(1), Task.CompletedTask, Task.Delay(1), Task.CompletedTask, Task.Delay(1)]); + } } } diff --git a/src/libraries/System.Runtime/tests/System.ValueTuple.Tests/ValueTupleTests.cs b/src/libraries/System.Runtime/tests/System.ValueTuple.Tests/ValueTupleTests.cs index 147b4ea9647c..0e85e1565149 100644 --- a/src/libraries/System.Runtime/tests/System.ValueTuple.Tests/ValueTupleTests.cs +++ b/src/libraries/System.Runtime/tests/System.ValueTuple.Tests/ValueTupleTests.cs @@ -3,7 +3,7 @@ using System.Collections; using Xunit; -#if NETCOREAPP +#if NET using System.Runtime.CompilerServices; #endif @@ -775,7 +775,7 @@ public static void ZeroTuples() AssertExtensions.Throws("other", () => ((IStructuralComparable)a).CompareTo("string", DummyTestComparer.Instance)); Assert.Equal("(1, 2, 3, 4, 5, 6, 7, )", CreateLong(1, 2, 3, 4, 5, 6, 7, new ValueTuple()).ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(); Assert.Throws(() => it[-1].ToString()); Assert.Throws(() => it[0].ToString()); @@ -812,7 +812,7 @@ public static void OneTuples() Assert.Equal("()", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(1); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -852,7 +852,7 @@ public static void TwoTuples() Assert.Equal("(, )", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(1, 2); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -897,7 +897,7 @@ public static void ThreeTuples() Assert.Equal("(, , )", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(1, 2, 3); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -948,7 +948,7 @@ public static void FourTuples() Assert.Equal("(, , , )", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(1, 2, 3, 4); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -1004,7 +1004,7 @@ public static void FiveTuples() Assert.Equal("(, , , , )", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(1, 2, 3, 4, 5); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -1065,7 +1065,7 @@ public static void SixTuples() Assert.Equal("(, , , , , )", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(1, 2, 3, 4, 5, 6); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -1131,7 +1131,7 @@ public static void SevenTuples() Assert.Equal("(, , , , , , )", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = ValueTuple.Create(1, 2, 3, 4, 5, 6, 7); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -1223,7 +1223,7 @@ public static void EightTuples() Assert.Equal("(, , , , , , , )", vtWithNull.ToString()); Assert.Equal(tupleWithNull.ToString(), vtWithNull.ToString()); -#if NETCOREAPP +#if NET ITuple it = CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8)); Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); @@ -1312,7 +1312,7 @@ public static void EightTuplesWithBadRest() Assert.Equal("(1, 2, 3, 4, 5, 6, 7, 1, 0, 0, 0, 0, 0, 0, 42)", CreateLong(1, 2, 3, 4, 5, 6, 7, d).ToString()); -#if NETCOREAPP +#if NET ITuple it = d; Assert.Throws(() => it[-1].ToString()); Assert.Equal(1, it[0]); diff --git a/src/libraries/System.Security.Claims/src/System.Security.Claims.csproj b/src/libraries/System.Security.Claims/src/System.Security.Claims.csproj index e1e3b9838c4c..4376906dbbc4 100644 --- a/src/libraries/System.Security.Claims/src/System.Security.Claims.csproj +++ b/src/libraries/System.Security.Claims/src/System.Security.Claims.csproj @@ -18,6 +18,7 @@ + diff --git a/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj b/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj index c4215a5c774a..18e8462a5c6e 100644 --- a/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj @@ -3,9 +3,6 @@ $(DefineConstants);TESTING_CNG_IMPLEMENTATION $(NetCoreAppCurrent)-windows - - - diff --git a/src/libraries/System.Security.Cryptography.Cng/tests/default.rd.xml b/src/libraries/System.Security.Cryptography.Cng/tests/default.rd.xml deleted file mode 100644 index 932f3c37ec64..000000000000 --- a/src/libraries/System.Security.Cryptography.Cng/tests/default.rd.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/src/libraries/System.Security.Cryptography.Cose/src/System/Security/Cryptography/Cose/CoseSignature.cs b/src/libraries/System.Security.Cryptography.Cose/src/System/Security/Cryptography/Cose/CoseSignature.cs index 831c5c8f676b..da0962a48b3b 100644 --- a/src/libraries/System.Security.Cryptography.Cose/src/System/Security/Cryptography/Cose/CoseSignature.cs +++ b/src/libraries/System.Security.Cryptography.Cose/src/System/Security/Cryptography/Cose/CoseSignature.cs @@ -450,7 +450,7 @@ private bool VerifyCore(AsymmetricAlgorithm key, ReadOnlySpan contentBytes private bool VerifyHash(AsymmetricAlgorithm key, IncrementalHash hasher, HashAlgorithmName hashAlgorithm, KeyType keyType, RSASignaturePadding? padding) { -#if NETCOREAPP +#if NET Debug.Assert(hasher.HashLengthInBytes <= 512 / 8); // largest hash we can get (SHA512). Span hash = stackalloc byte[hasher.HashLengthInBytes]; hasher.GetHashAndReset(hash); diff --git a/src/libraries/System.Security.Cryptography.Cose/tests/CoseTestHelpers.cs b/src/libraries/System.Security.Cryptography.Cose/tests/CoseTestHelpers.cs index 4eb5d7dba72d..2e73ce54ffef 100644 --- a/src/libraries/System.Security.Cryptography.Cose/tests/CoseTestHelpers.cs +++ b/src/libraries/System.Security.Cryptography.Cose/tests/CoseTestHelpers.cs @@ -588,7 +588,7 @@ public static IEnumerable AllCborTypes() w.WriteDouble(default); yield return ReturnDataAndReset(w); -#if NETCOREAPP +#if NET w.WriteHalf(default); yield return ReturnDataAndReset(w); #endif diff --git a/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.cs b/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.cs index 6c17e4ac0840..f687149f8022 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.cs @@ -83,7 +83,7 @@ public void Reset() { } public sealed partial class CmsSigner { public CmsSigner() { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("CmsSigner(CspParameters) is obsolete and is not supported. Use an alternative constructor instead.", DiagnosticId = "SYSLIB0034", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] @@ -270,7 +270,7 @@ internal SignerInfo() { } public void CheckHash() { } public void CheckSignature(bool verifySignatureOnly) { } public void CheckSignature(System.Security.Cryptography.X509Certificates.X509Certificate2Collection extraStore, bool verifySignatureOnly) { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("ComputeCounterSignature without specifying a CmsSigner is obsolete and is not supported. Use the overload that accepts a CmsSigner.", DiagnosticId = "SYSLIB0035", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.KeyTrans.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.KeyTrans.cs index e95be29e9990..fd9cc62ac0ec 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.KeyTrans.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.KeyTrans.cs @@ -189,7 +189,7 @@ private KeyTransRecipientInfoAsn MakeKtri( return null; } -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 byte[]? cek = null; int cekLength = 0; diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.cs index c0831046595a..69525a16b001 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.cs @@ -80,7 +80,7 @@ public override byte[] GetSubjectKeyIdentifier(X509Certificate2 certificate) return (T?)(object?)certificate.GetRSAPrivateKey(); if (typeof(T) == typeof(ECDsa)) return (T?)(object?)certificate.GetECDsaPrivateKey(); -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 if (typeof(T) == typeof(DSA) && Internal.Cryptography.Helpers.IsDSASupported) return (T?)(object?)certificate.GetDSAPrivateKey(); #endif diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/PkcsPalWindows.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/PkcsPalWindows.cs index ab05ccc6f9f6..db93dff50c67 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/PkcsPalWindows.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/PkcsPalWindows.cs @@ -127,7 +127,7 @@ public sealed override byte[] GetSubjectKeyIdentifier(X509Certificate2 certifica if (keySpec == CryptKeySpec.CERT_NCRYPT_KEY_SPEC) { -#if NETSTANDARD || NETCOREAPP +#if NETSTANDARD || NET Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); #endif diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/PkcsHelpers.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/PkcsHelpers.cs index 6351a376c0bc..1cf3bc1f4a5a 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/PkcsHelpers.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/PkcsHelpers.cs @@ -36,7 +36,7 @@ private static bool DetectInitOnlyOid() } } -#if !NETCOREAPP && !NETSTANDARD2_1 +#if !NET && !NETSTANDARD2_1 // Compatibility API. internal static void AppendData(this IncrementalHash hasher, ReadOnlySpan data) { @@ -364,12 +364,12 @@ public static string ToSerialString(this byte[] serialBytes) return ToUpperHexString(serialBytes); } -#if NET5_0_OR_GREATER +#if NET private static string ToUpperHexString(ReadOnlySpan ba) { return Convert.ToHexString(ba); } -#elif NETCOREAPP || NETSTANDARD2_1 +#elif NETSTANDARD2_1 private static string ToUpperHexString(ReadOnlySpan ba) { return HexConverter.ToString(ba, HexConverter.Casing.Upper); @@ -433,7 +433,7 @@ public static Pkcs9AttributeObject CreateBestPkcs9AttributeObjectAvailable(Oid o Oids.SigningTime => new Pkcs9SigningTime(encodedAttribute), Oids.ContentType => new Pkcs9ContentType(encodedAttribute), Oids.MessageDigest => new Pkcs9MessageDigest(encodedAttribute), -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 Oids.LocalKeyId => new Pkcs9LocalKeyId() { RawData = encodedAttribute.ToArray() }, #endif _ => new Pkcs9AttributeObject(oid, encodedAttribute), diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs index 97192c83b916..183520aa9c3f 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs @@ -43,7 +43,7 @@ protected override bool VerifyKeyType(AsymmetricAlgorithm key) } internal override bool VerifySignature( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan valueHash, ReadOnlyMemory signature, #else @@ -76,7 +76,7 @@ internal override bool VerifySignature( DSAParameters dsaParameters = dsa.ExportParameters(false); int bufSize = 2 * dsaParameters.Q!.Length; -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 byte[] rented = CryptoPool.Rent(bufSize); Span ieee = new Span(rented, 0, bufSize); @@ -91,7 +91,7 @@ internal override bool VerifySignature( } return dsa.VerifySignature(valueHash, ieee); -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 } finally { @@ -101,7 +101,7 @@ internal override bool VerifySignature( } protected override bool Sign( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan dataHash, #else byte[] dataHash, @@ -145,7 +145,7 @@ protected override bool Sign( signatureAlgorithm = oidValue; -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 // The Q size cannot be bigger than the KeySize. byte[] rented = CryptoPool.Rent(dsa.KeySize / 8); int bytesWritten = 0; diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs index dd098e46362e..e89e6e5232d5 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs @@ -44,7 +44,7 @@ protected override bool VerifyKeyType(AsymmetricAlgorithm key) } internal override bool VerifySignature( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan valueHash, ReadOnlyMemory signature, #else @@ -80,7 +80,7 @@ internal override bool VerifySignature( bufSize = 2 * fieldSize; } -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 byte[] rented = CryptoPool.Rent(bufSize); Span ieee = new Span(rented, 0, bufSize); @@ -95,7 +95,7 @@ internal override bool VerifySignature( } return key.VerifyHash(valueHash, ieee); -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 } finally { @@ -105,7 +105,7 @@ internal override bool VerifySignature( } protected override bool Sign( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan dataHash, #else byte[] dataHash, @@ -152,7 +152,7 @@ protected override bool Sign( signatureAlgorithm = oidValue; -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 int bufSize; checked { @@ -188,7 +188,7 @@ protected override bool Sign( #endif signatureValue = DsaIeeeToDer(key.SignHash( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 dataHash.ToArray() #else dataHash diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs index 51677662dd52..80aa6abb9085 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs @@ -45,7 +45,7 @@ protected override bool VerifyKeyType(AsymmetricAlgorithm key) } internal override bool VerifySignature( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan valueHash, ReadOnlyMemory signature, #else @@ -81,7 +81,7 @@ internal override bool VerifySignature( return publicKey.VerifyHash( valueHash, -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 signature.Span, #else signature, @@ -97,7 +97,7 @@ protected abstract RSASignaturePadding GetSignaturePadding( int digestValueLength); private protected static bool SignCore( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan dataHash, #else byte[] dataHash, @@ -122,7 +122,7 @@ private protected static bool SignCore( return false; } -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 byte[] signature = new byte[privateKey.KeySize / 8]; bool signed = privateKey.TrySignHash( @@ -147,7 +147,7 @@ private protected static bool SignCore( } #endif signatureValue = privateKey.SignHash( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 dataHash.ToArray(), #else dataHash, @@ -199,7 +199,7 @@ protected override RSASignaturePadding GetSignaturePadding( } protected override bool Sign( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan dataHash, #else byte[] dataHash, @@ -319,7 +319,7 @@ protected override RSASignaturePadding GetSignaturePadding( } protected override bool Sign( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan dataHash, #else byte[] dataHash, diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs index 7cf3436b54aa..a0595c61dc3c 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs @@ -30,7 +30,7 @@ static CmsSignature() protected abstract bool VerifyKeyType(AsymmetricAlgorithm key); internal abstract bool VerifySignature( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan valueHash, ReadOnlyMemory signature, #else @@ -43,7 +43,7 @@ internal abstract bool VerifySignature( X509Certificate2 certificate); protected abstract bool Sign( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan dataHash, #else byte[] dataHash, @@ -112,7 +112,7 @@ protected abstract bool Sign( } internal static bool Sign( -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 ReadOnlySpan dataHash, #else byte[] dataHash, @@ -224,7 +224,7 @@ private static byte[] DsaIeeeToDer(ReadOnlySpan ieeeSignature) { writer.PushSequence(); -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 // r BigInteger val = new BigInteger( ieeeSignature.Slice(0, fieldSize), diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs index a78cf3a4ee56..04c2fd59e78a 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs @@ -22,11 +22,11 @@ public sealed class CmsSigner public X509Certificate2? Certificate { get; set; } public AsymmetricAlgorithm? PrivateKey { get; set; } - public X509Certificate2Collection Certificates { get; private set; } = new X509Certificate2Collection(); + public X509Certificate2Collection Certificates { get; } = new X509Certificate2Collection(); public Oid DigestAlgorithm { get; set; } public X509IncludeOption IncludeOption { get; set; } - public CryptographicAttributeObjectCollection SignedAttributes { get; private set; } = new CryptographicAttributeObjectCollection(); - public CryptographicAttributeObjectCollection UnsignedAttributes { get; private set; } = new CryptographicAttributeObjectCollection(); + public CryptographicAttributeObjectCollection SignedAttributes { get; } = new CryptographicAttributeObjectCollection(); + public CryptographicAttributeObjectCollection UnsignedAttributes { get; } = new CryptographicAttributeObjectCollection(); /// /// Gets or sets the RSA signature padding to use. @@ -73,7 +73,7 @@ public CmsSigner(X509Certificate2? certificate) { } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CmsSignerCspParamsCtorMessage, DiagnosticId = Obsoletions.CmsSignerCspParamsCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [EditorBrowsable(EditorBrowsableState.Never)] diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs index 0b0700d26584..51dccc6458d6 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignedCms.cs @@ -96,7 +96,7 @@ public X509Certificate2Collection Certificates if (choice.Certificate.HasValue) { coll.Add(new X509Certificate2(choice.Certificate.Value -#if NETCOREAPP +#if NET .Span #else .ToArray() diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs index 021e1f8e9be2..46b6fc056e4c 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs @@ -262,7 +262,7 @@ private SignerInfoCollection GetCounterSigners(AttributeAsn[] unsignedAttrs) return new SignerInfoCollection(signerInfos.ToArray()); } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.SignerInfoCounterSigMessage, DiagnosticId = Obsoletions.SignerInfoCounterSigDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [EditorBrowsable(EditorBrowsableState.Never)] @@ -746,7 +746,7 @@ private bool VerifySignature( return false; } -#if NETCOREAPP || NETSTANDARD2_1 +#if NET || NETSTANDARD2_1 // SHA-2-512 is the biggest digest type we know about. Span digestValue = stackalloc byte[512 / 8]; ReadOnlySpan digest = digestValue; diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/CertLoader.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/CertLoader.cs index be71f91529a1..e310abc86cd4 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/CertLoader.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/CertLoader.cs @@ -14,7 +14,7 @@ internal abstract partial class CertLoader // Prefer ephemeral when available private static X509KeyStorageFlags GetBestKeyStorageFlags() { -#if NETCOREAPP +#if NET if (OperatingSystem.IsWindows()) { // On Windows 7 ephemeral keys with a key usage embedded in the PFX @@ -176,7 +176,7 @@ public CertLoaderFromRawData(byte[] cerData, byte[] pfxData = null, string passw internal override CertLoader CloneAsEphemeralLoader() { -#if NETCOREAPP +#if NET return new CertLoaderFromRawData(CerData, PfxData, Password) { KeyStorageFlags = X509KeyStorageFlags.EphemeralKeySet, diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/DecryptTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/DecryptTests.cs index bca63841dfde..58ff32fd6328 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/DecryptTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/DecryptTests.cs @@ -835,7 +835,7 @@ internal void VerifySimpleDecrypt(byte[] encodedMessage, CertLoader certLoader, if (cert == null) return; // Sorry - CertLoader is not configured to load certs with private keys - we've tested as much as we can. -#if NETCOREAPP // API not present on netfx +#if NET // API not present on netfx if (_useExplicitPrivateKey) { using (X509Certificate2 pubCert = certLoader.GetCertificate()) diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/StateTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/StateTests.cs index 02b83db21688..288aa11e4ad9 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/StateTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/EnvelopedCms/StateTests.cs @@ -274,7 +274,7 @@ public static void PostDecode_ContentInfo_netcore() [Theory] [OuterLoop(/* Leaks key on disk if interrupted */)] [InlineData(false)] -#if NETCOREAPP // API not supported on netfx +#if NET // API not supported on netfx [InlineData(true)] #endif public static void PostDecrypt_Encode(bool useExplicitPrivateKey) @@ -300,7 +300,7 @@ public static void PostDecrypt_Encode(bool useExplicitPrivateKey) if (useExplicitPrivateKey) { -#if NETCOREAPP +#if NET ecms.Decrypt(r[0], cer.GetRSAPrivateKey()); #else Assert.Fail("Should not run on this platform"); @@ -362,7 +362,7 @@ public static void PostDecrypt_RecipientInfos() [Theory] [OuterLoop(/* Leaks key on disk if interrupted */)] [InlineData(false)] -#if NETCOREAPP // API not supported on netfx +#if NET // API not supported on netfx [InlineData(true)] #endif public static void PostDecrypt_Decrypt(bool useExplicitPrivateKey) @@ -404,7 +404,7 @@ public static void PostDecrypt_Decrypt(bool useExplicitPrivateKey) { if (useExplicitPrivateKey) { -#if NETCOREAPP +#if NET ecms.Decrypt(r[0], cert1.GetRSAPrivateKey()); #else Assert.Fail("Should not run on this platform"); diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/CertBagTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/CertBagTests.cs index 68f364b9d858..45ffae839acd 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/CertBagTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/CertBagTests.cs @@ -47,7 +47,7 @@ public static void OidCtorPreservesFriendlyName() Oid firstCall = certBag.GetCertificateType(); Oid secondCall = certBag.GetCertificateType(); -#if !NETCOREAPP +#if !NET Assert.NotSame(oid, firstCall); Assert.NotSame(oid, secondCall); Assert.NotSame(firstCall, secondCall); diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/Pkcs12SafeBagTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/Pkcs12SafeBagTests.cs index d5ace8984490..9c7f5e360df6 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/Pkcs12SafeBagTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs12/Pkcs12SafeBagTests.cs @@ -66,7 +66,7 @@ public static void GetBagIdIsFactory() Assert.Equal(Oids.Aes192, firstCall.Value); Assert.Equal(firstCall.Value, secondCall.Value); -#if !NETCOREAPP +#if !NET Assert.NotSame(firstCall, secondCall); #endif } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/CmsSignerTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/CmsSignerTests.cs index a99d2f8d4dde..27be5cf21152 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/CmsSignerTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/CmsSignerTests.cs @@ -21,7 +21,7 @@ public static void SignerIdentifierType_InvalidValues(SubjectIdentifierType inva () => signer.SignerIdentifierType = invalidType); } -#if NETCOREAPP +#if NET [Fact] public static void SignaturePadding_InvalidValue() { diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs index 7eee42aa5db7..c0c1421daac4 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs @@ -562,7 +562,7 @@ public static void AddFirstSigner_DSA(SubjectIdentifierType identifierType, bool Assert.NotSame(cms.Certificates[0], firstSigner.Certificate); Assert.Equal(cms.Certificates[0], firstSigner.Certificate); -#if NETCOREAPP +#if NET byte[] signature = firstSigner.GetSignature(); Assert.NotEmpty(signature); // DSA PKIX signature format is a DER SEQUENCE. @@ -581,7 +581,7 @@ public static void AddFirstSigner_DSA(SubjectIdentifierType identifierType, bool Assert.Equal(identifierType, cms.SignerInfos[0].SignerIdentifier.Type); Assert.Equal(firstSigner.Certificate, cms.SignerInfos[0].Certificate); -#if NETCOREAPP +#if NET byte[] sig2 = cms.SignerInfos[0].GetSignature(); Assert.Equal(signature, sig2); #endif @@ -633,7 +633,7 @@ public static void AddFirstSigner_ECDSA(SubjectIdentifierType identifierType, bo Assert.NotSame(cms.Certificates[0], firstSigner.Certificate); Assert.Equal(cms.Certificates[0], firstSigner.Certificate); -#if NETCOREAPP +#if NET byte[] signature = firstSigner.GetSignature(); Assert.NotEmpty(signature); // ECDSA PKIX signature format is a DER SEQUENCE. @@ -655,7 +655,7 @@ public static void AddFirstSigner_ECDSA(SubjectIdentifierType identifierType, bo Assert.Equal(identifierType, cms.SignerInfos[0].SignerIdentifier.Type); Assert.Equal(firstSigner.Certificate, cms.SignerInfos[0].Certificate); -#if NETCOREAPP +#if NET byte[] sig2 = cms.SignerInfos[0].GetSignature(); Assert.Equal(signature, sig2); #endif @@ -1165,7 +1165,7 @@ public static void EnsureDataIsolation_NewDocument(bool detached) // CheckSignature doesn't read the public mutable data contentInfo.Content[0] ^= 0xFF; -#if !NETCOREAPP +#if !NET contentInfo.ContentType.Value = Oids.Pkcs7Hashed; #endif cms.CheckSignature(true); diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsWholeDocumentTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsWholeDocumentTests.cs index 8918d7adbb66..c5b7c000e2b7 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsWholeDocumentTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsWholeDocumentTests.cs @@ -60,7 +60,7 @@ public static void ReadRsaPssDocument(bool fromSpan) Assert.Equal(SubjectIdentifierType.SubjectKeyIdentifier, signer.SignerIdentifier.Type); Assert.Equal("1063CAB14FB14C47DC211C0E0285F3EE5946BF2D", signer.SignerIdentifier.Value); Assert.Equal("2.16.840.1.101.3.4.2.1", signer.DigestAlgorithm.Value); -#if NETCOREAPP +#if NET Assert.Equal("1.2.840.113549.1.1.10", signer.SignatureAlgorithm.Value); #endif @@ -91,7 +91,7 @@ public static void ReadRsaPssDocument(bool fromSpan) messageDigestAttr.MessageDigest.ByteArrayToHex()); Assert.IsType(signedAttrs[3].Values[0]); -#if !NETCOREAPP +#if !NET Assert.NotSame(signedAttrs[3].Oid, signedAttrs[3].Values[0].Oid); #endif Assert.Equal( @@ -101,7 +101,7 @@ public static void ReadRsaPssDocument(bool fromSpan) "082A864886F70D0302020128", signedAttrs[3].Values[0].RawData.ByteArrayToHex()); -#if NETCOREAPP +#if NET Assert.Equal( "B93E81D141B3C9F159AB0021910635DC72E8E860BE43C28E5D53243D6DC247B7" + "D4F18C20195E80DEDCC75B29C43CE5047AD775B65BFC93589BD748B950C68BAD" + @@ -170,7 +170,7 @@ public static void ReadRsaPkcs1SimpleDocument() Assert.Equal(SubjectIdentifierType.IssuerAndSerialNumber, signer.SignerIdentifier.Type); Assert.Equal(Oids.Sha1, signer.DigestAlgorithm.Value); -#if NETCOREAPP +#if NET Assert.Equal(Oids.Rsa, signer.SignatureAlgorithm.Value); Assert.Equal( @@ -237,7 +237,7 @@ public static void ReadRsaPkcs1CounterSigned() Assert.Equal(SubjectIdentifierType.IssuerAndSerialNumber, signer.SignerIdentifier.Type); Assert.Equal(Oids.Sha1, signer.DigestAlgorithm.Value); -#if NETCOREAPP +#if NET Assert.Equal(Oids.Rsa, signer.SignatureAlgorithm.Value); Assert.Equal( @@ -311,7 +311,7 @@ public static void CheckNoSignatureDocument() Assert.Null(signer.Certificate); Assert.Equal(Oids.Sha1, signer.DigestAlgorithm.Value); -#if NETCOREAPP +#if NET Assert.Equal("1.3.6.1.5.5.7.6.2", signer.SignatureAlgorithm.Value); Assert.Equal( @@ -370,7 +370,7 @@ public static void CheckNoSignatureDocument() "833378066BDCCBA7047EF6919843D181A57D6479", csMessageDigest.MessageDigest.ByteArrayToHex()); -#if NETCOREAPP +#if NET Assert.Equal(Oids.Rsa, counterSigner.SignatureAlgorithm.Value); Assert.Equal( @@ -447,7 +447,7 @@ public static void NonEmbeddedCertificate() Assert.Empty(signer.CounterSignerInfos); Assert.Null(signer.Certificate); -#if NETCOREAPP +#if NET Assert.Equal(Oids.Rsa, signer.SignatureAlgorithm.Value); Assert.Equal( @@ -551,7 +551,7 @@ public static void ReadRsaPkcs1DoubleCounterSigned() Assert.Equal(SubjectIdentifierType.IssuerAndSerialNumber, signer.SignerIdentifier.Type); Assert.Equal(Oids.Sha1, signer.DigestAlgorithm.Value); -#if NETCOREAPP +#if NET Assert.Equal(Oids.Rsa, signer.SignatureAlgorithm.Value); Assert.Equal( @@ -597,7 +597,7 @@ public static void ReadRsaPkcs1DoubleCounterSigned() // Assert.NotThrows cms.CheckSignature(true); -#if NETCOREAPP +#if NET Assert.Equal( "1AA282DBED4D862D7CEA30F803E790BDB0C97EE852778CEEDDCD94BB9304A155" + "2E60A8D36052AC8C2D28755F3B2F473824100AB3A6ABD4C15ABD77E0FFE13D0D" + diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs index 10a51fc81954..37d8b29ddc5d 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs @@ -100,7 +100,7 @@ public static void SignerInfo_CounterSignerInfos_UniquePerCall_WhenNonEmpty() Assert.NotSame(counterSigner.Certificate, counterSigner2.Certificate); Assert.Equal(counterSigner.Certificate, counterSigner2.Certificate); -#if NETCOREAPP +#if NET byte[] signature = counterSigner.GetSignature(); byte[] signature2 = counterSigner2.GetSignature(); @@ -110,7 +110,7 @@ public static void SignerInfo_CounterSignerInfos_UniquePerCall_WhenNonEmpty() } } -#if NETCOREAPP +#if NET [Fact] public static void SignerInfo_GetSignature_UniquePerCall() { @@ -139,7 +139,7 @@ public static void SignerInfo_DigestAlgorithm_NotSame() Assert.NotSame(oid, oid2); } -#if NETCOREAPP +#if NET [Fact] public static void SignerInfo_SignatureAlgorithm_NotSame() { @@ -745,7 +745,7 @@ public static void AddCounterSigner_DSA() Assert.NotEqual(firstSigner2.Certificate, counterSigner.Certificate); Assert.Equal(2, cms.Certificates.Count); -#if NETCOREAPP +#if NET byte[] signature = counterSigner.GetSignature(); Assert.NotEmpty(signature); // DSA PKIX signature format is a DER SEQUENCE. @@ -813,7 +813,7 @@ public static void AddCounterSigner_ECDSA(SubjectIdentifierType identifierType, Assert.NotEqual(firstSigner2.Certificate, counterSigner.Certificate); Assert.Equal(2, cms.Certificates.Count); -#if NETCOREAPP +#if NET byte[] signature = counterSigner.GetSignature(); Assert.NotEmpty(signature); // DSA PKIX signature format is a DER SEQUENCE. diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXml.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXml.cs index adc6af7f077e..98a5c73ea6e4 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXml.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXml.cs @@ -12,11 +12,6 @@ internal sealed class CanonicalXml private readonly CanonicalXmlDocument _c14nDoc; private readonly C14NAncestralNamespaceContextManager _ancMgr; - // private static string defaultXPathWithoutComments = "(//. | //@* | //namespace::*)[not(self::comment())]"; - // private static string defaultXPathWithoutComments = "(//. | //@* | //namespace::*)"; - // private static string defaultXPathWithComments = "(//. | //@* | //namespace::*)"; - // private static string defaultXPathWithComments = "(//. | //@* | //namespace::*)"; - internal CanonicalXml(Stream inputStream, bool includeComments, XmlResolver? resolver, string strBaseUri) { if (inputStream is null) diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoHelpers.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoHelpers.cs index 17fedbe3daa9..5a6ece8b2d6c 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoHelpers.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoHelpers.cs @@ -50,7 +50,7 @@ internal static class CryptoHelpers [RequiresDynamicCode(XsltRequiresDynamicCodeMessage)] private static XmlDsigXsltTransform CreateXmlDsigXsltTransform() { -#if NETCOREAPP +#if NET if (!RuntimeFeature.IsDynamicCodeSupported) { // XSLTs are only supported when dynamic code is supported. See https://github.com/dotnet/runtime/issues/84389 @@ -73,7 +73,7 @@ private static XmlDsigXsltTransform CreateXmlDsigXsltTransform() { return (CryptoConfig.CreateFromName(name) ?? CreateFromKnownName(name)) as T; } -#if NETCOREAPP +#if NET catch (NotSupportedException) { if (name == "http://www.w3.org/TR/1999/REC-xslt-19991116") diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSASignatureDescription.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSASignatureDescription.cs index 22b1c4c355a7..46e214ab54fa 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSASignatureDescription.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSASignatureDescription.cs @@ -17,7 +17,7 @@ public DSASignatureDescription() DigestAlgorithm = "SHA1"; } -#if NETCOREAPP +#if NET [RequiresUnreferencedCode("CreateDeformatter is not trim compatible because the algorithm implementation referenced by DeformatterAlgorithm might be removed.")] #endif public sealed override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key) @@ -28,7 +28,7 @@ public sealed override AsymmetricSignatureDeformatter CreateDeformatter(Asymmetr return item; } -#if NETCOREAPP +#if NET [RequiresUnreferencedCode("CreateFormatter is not trim compatible because the algorithm implementation referenced by FormatterAlgorithm might be removed.")] #endif public sealed override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key) diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoX509Data.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoX509Data.cs index 87bb9ac53ef7..dd5fcd2af56a 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoX509Data.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoX509Data.cs @@ -160,6 +160,15 @@ public void AddIssuerSerial(string issuerName, string serialNumber) if (!BigInteger.TryParse(serialNumber, NumberStyles.AllowHexSpecifier, NumberFormatInfo.CurrentInfo, out h)) throw new ArgumentException(SR.Cryptography_Xml_InvalidX509IssuerSerialNumber, nameof(serialNumber)); + // NetFx compat: .NET Framework treats the input as unsigned and we need to write down the X509SerialNumber + // as a positive number. + if (h < BigInteger.Zero) + { + byte[] bytes = h.ToByteArray(); + Array.Resize(ref bytes, bytes.Length + 1); + h = new BigInteger(bytes); + } + _issuerSerials ??= new ArrayList(); _issuerSerials.Add(Utils.CreateX509IssuerSerial(issuerName, h.ToString())); } diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SignatureDescription.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SignatureDescription.cs index 6d5a8fd733e0..28e0850891d8 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SignatureDescription.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SignatureDescription.cs @@ -15,7 +15,7 @@ public RSAPKCS1SignatureDescription(string hashAlgorithmName) DigestAlgorithm = hashAlgorithmName; } -#if NETCOREAPP +#if NET [RequiresUnreferencedCode("CreateDeformatter is not trim compatible because the algorithm implementation referenced by DeformatterAlgorithm might be removed.")] #endif public sealed override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key) @@ -26,7 +26,7 @@ public sealed override AsymmetricSignatureDeformatter CreateDeformatter(Asymmetr return item; } -#if NETCOREAPP +#if NET [RequiresUnreferencedCode("CreateFormatter is not trim compatible because the algorithm implementation referenced by FormatterAlgorithm might be removed.")] #endif public sealed override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key) @@ -37,7 +37,7 @@ public sealed override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAl return item; } -#if NETCOREAPP +#if NET [RequiresUnreferencedCode("CreateDigest is not trim compatible because the algorithm implementation referenced by DigestAlgorithm might be removed.")] #endif public abstract override HashAlgorithm CreateDigest(); diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs index ffffeefa5bac..5505994fd829 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs @@ -720,7 +720,7 @@ internal static X509Certificate2Collection BuildBagOfCerts(KeyInfoX509Data keyIn return collection; } -#if NET5_0_OR_GREATER +#if NET internal static string EncodeHexString(byte[] sArray) { return Convert.ToHexString(sArray); @@ -761,7 +761,7 @@ internal static bool IsSelfSigned(X509Chain chain) { AsymmetricAlgorithm? algorithm = (AsymmetricAlgorithm?)certificate.GetRSAPublicKey() ?? certificate.GetECDsaPublicKey(); -#if NETCOREAPP +#if NET if (algorithm is null && !OperatingSystem.IsTvOS() && !OperatingSystem.IsIOS()) { algorithm = certificate.GetDSAPublicKey(); diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlResolverHelper.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlResolverHelper.cs index 3070ffa8e1d2..948f883b80a2 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlResolverHelper.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlResolverHelper.cs @@ -11,14 +11,14 @@ internal static class XmlResolverHelper { internal static XmlResolver GetThrowingResolver() { -#if NET7_0_OR_GREATER +#if NET return XmlResolver.ThrowingResolver; #else return XmlThrowingResolver.s_singleton; #endif } -#if !NET7_0_OR_GREATER +#if !NET // An XmlResolver that forbids all external entity resolution. // (Copied from XmlResolver.ThrowingResolver.cs.) private sealed class XmlThrowingResolver : XmlResolver diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/ILLink.Descriptors.xml b/src/libraries/System.Security.Cryptography.Xml/tests/ILLink.Descriptors.xml new file mode 100644 index 000000000000..3e8cdae693f7 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Xml/tests/ILLink.Descriptors.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoX509DataTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoX509DataTest.cs index cf3092e87ccb..cb09746fa0ee 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoX509DataTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoX509DataTest.cs @@ -335,5 +335,14 @@ public void InvalidKeyNode3() KeyInfoX509Data data1 = new KeyInfoX509Data(); Assert.Throws(() => data1.LoadXml(doc.DocumentElement)); } + + [Fact] + public void AddIssuerSerial_NegativeSerial() + { + KeyInfoX509Data data = new KeyInfoX509Data(); + data.AddIssuerSerial("CN=Vince", "FF"); + X509IssuerSerial serial = (X509IssuerSerial)Assert.Single(data.IssuerSerials); + Assert.Equal("255", serial.SerialNumber); + } } } diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceTest.cs index a28065dac5a3..db65e8de5381 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceTest.cs @@ -131,7 +131,7 @@ public void LoadXPathTransforms() [ConditionalFact] public void LoadXsltTransforms() { -#if NETCOREAPP +#if NET if (!RuntimeFeature.IsDynamicCodeSupported) { throw new SkipTestException("XSLTs are only supported when dynamic code is supported. See https://github.com/dotnet/runtime/issues/84389"); @@ -167,7 +167,7 @@ public void LoadAllTransforms() xsltTransform += ""; xsltTransform += ""; int expectedTransformsCount = 6; -#if NETCOREAPP +#if NET if (!RuntimeFeature.IsDynamicCodeSupported) { // XSLTs are only supported when dynamic code is supported. See https://github.com/dotnet/runtime/issues/84389 diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/Samples/SigningVerifyingX509Cert.cs b/src/libraries/System.Security.Cryptography.Xml/tests/Samples/SigningVerifyingX509Cert.cs index 37431c1e53c1..69af96accd8d 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/Samples/SigningVerifyingX509Cert.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/Samples/SigningVerifyingX509Cert.cs @@ -87,7 +87,7 @@ public void SignedXmlHasDSACertificateVerifiableSignature() xmlDoc.PreserveWhitespace = true; xmlDoc.LoadXml(ExampleXml); -#if NETCOREAPP +#if NET using (DSA key = x509cert.GetDSAPrivateKey()) { SignXml(xmlDoc, key); diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs index bd22c5b835ee..54c153694f7b 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs @@ -1673,7 +1673,7 @@ static byte[] GetResponse() => try { -#if NETCOREAPP +#if NET socket = await listener.AcceptSocketAsync(cancellationToken); #else socket = await listener.AcceptSocketAsync(); diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj b/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj index b4704975b821..56458c07a5a0 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj @@ -74,4 +74,8 @@ + + + + diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/TestHelpers.cs b/src/libraries/System.Security.Cryptography.Xml/tests/TestHelpers.cs index 16364a4315c3..17e498325abb 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/TestHelpers.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/TestHelpers.cs @@ -229,7 +229,7 @@ internal static DSA GetWorkingDSA() { DSA dsa = DSA.Create(); -#if NETCOREAPP +#if NET if (OperatingSystem.IsMacOS()) { // macOS cannot generate DSA keys, so for this platform we will use a fixed key. diff --git a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs index a6ee388c8cec..4bd007d9030c 100644 --- a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs +++ b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs @@ -2587,6 +2587,7 @@ public Shake128() { } public static bool IsSupported { get { throw null; } } public void AppendData(byte[] data) { } public void AppendData(System.ReadOnlySpan data) { } + public System.Security.Cryptography.Shake128 Clone() { throw null; } public void Dispose() { } public byte[] GetCurrentHash(int outputLength) { throw null; } public void GetCurrentHash(System.Span destination) { } @@ -2599,6 +2600,9 @@ public static void HashData(System.IO.Stream source, System.Span destinati public static void HashData(System.ReadOnlySpan source, System.Span destination) { } public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, int outputLength, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public byte[] Read(int outputLength) { throw null; } + public void Read(System.Span destination) { } + public void Reset() { } } public sealed partial class Shake256 : System.IDisposable { @@ -2606,6 +2610,7 @@ public Shake256() { } public static bool IsSupported { get { throw null; } } public void AppendData(byte[] data) { } public void AppendData(System.ReadOnlySpan data) { } + public System.Security.Cryptography.Shake256 Clone() { throw null; } public void Dispose() { } public byte[] GetCurrentHash(int outputLength) { throw null; } public void GetCurrentHash(System.Span destination) { } @@ -2618,6 +2623,9 @@ public static void HashData(System.IO.Stream source, System.Span destinati public static void HashData(System.ReadOnlySpan source, System.Span destination) { } public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, int outputLength, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public byte[] Read(int outputLength) { throw null; } + public void Read(System.Span destination) { } + public void Reset() { } } public partial class SignatureDescription { diff --git a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx index a0a9e1e4afcf..05c91987126a 100644 --- a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx @@ -273,6 +273,9 @@ The specified CipherMode '{0}' is not supported. + + Concurrent operations from multiple threads on this type are not supported. + This key is for algorithm '{0}'. Expected '{1}'. @@ -777,6 +780,9 @@ The algorithm's block size is not supported. + + This operation is not supported once the algorithm has started reading. + CryptoApi ECDsa keys are not supported. diff --git a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj index 7e24c20a7fc4..ae5affcbb971 100644 --- a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj +++ b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj @@ -371,6 +371,8 @@ + + diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesGcm.macOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesGcm.macOS.cs index 3b528f496f4d..d9f036f61ca5 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesGcm.macOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesGcm.macOS.cs @@ -11,7 +11,7 @@ public sealed partial class AesGcm { private FixedMemoryKeyBox _keyBox; - // CryptoKit added AES.GCM in macOS 10.15, which is our minimum target for macOS. + // CryptoKit added AES.GCM in macOS 10.15, which is lower than our minimum target for macOS. public static bool IsSupported => true; // CryptoKit only supports 16 byte tags. diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/BasicSymmetricCipher.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/BasicSymmetricCipher.cs index 1fbcd1620c67..6f1c1e1b6317 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/BasicSymmetricCipher.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/BasicSymmetricCipher.cs @@ -31,8 +31,8 @@ protected BasicSymmetricCipher(byte[]? iv, int blockSizeInBytes, int paddingSize public abstract int TransformFinal(ReadOnlySpan input, Span output); - public int BlockSizeInBytes { get; private set; } - public int PaddingSizeInBytes { get; private set; } + public int BlockSizeInBytes { get; } + public int PaddingSizeInBytes { get; } public void Dispose() { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ChaCha20Poly1305.macOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ChaCha20Poly1305.macOS.cs index aa2cba5f234b..7e45061f971a 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ChaCha20Poly1305.macOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ChaCha20Poly1305.macOS.cs @@ -8,7 +8,7 @@ namespace System.Security.Cryptography { public sealed partial class ChaCha20Poly1305 { - // CryptoKit added ChaCha20Poly1305 in macOS 10.15, which is our minimum target for macOS. + // CryptoKit added ChaCha20Poly1305 in macOS 10.15, which is lower than our minimum target for macOS. public static bool IsSupported => true; private FixedMemoryKeyBox _keyBox; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyCreationParameters.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyCreationParameters.cs index ad742335f7ae..b8b8b3d198df 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyCreationParameters.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKeyCreationParameters.cs @@ -36,7 +36,7 @@ public CngKeyCreationParameters() /// /// Extra parameter values to set before the key is finalized /// - public CngPropertyCollection Parameters { get; private set; } + public CngPropertyCollection Parameters { get; } /// /// Window handle to use as the parent for the dialog shown when the key is created diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngProperty.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngProperty.cs index 45fe97ab41e5..179054ad9796 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngProperty.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngProperty.cs @@ -52,7 +52,7 @@ internal CngProperty(string name, ReadOnlySpan value, CngPropertyOptions o /// /// Options used to set / get the property /// - public CngPropertyOptions Options { get; private set; } + public CngPropertyOptions Options { get; } public override bool Equals([NotNullWhen(true)] object? obj) { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngUIPolicy.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngUIPolicy.cs index b784e4217dd8..c32b049a257f 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngUIPolicy.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngUIPolicy.cs @@ -43,27 +43,27 @@ public CngUIPolicy(CngUIProtectionLevels protectionLevel, string? friendlyName, /// /// Level of UI protection to apply to the key /// - public CngUIProtectionLevels ProtectionLevel { get; private set; } + public CngUIProtectionLevels ProtectionLevel { get; } /// /// Friendly name to describe the key with in the dialog box that appears when the key is accessed, /// null for default name /// - public string? FriendlyName { get; private set; } + public string? FriendlyName { get; } /// /// Description text displayed in the dialog box when the key is accessed, null for the default text /// - public string? Description { get; private set; } + public string? Description { get; } /// /// Description of how the key will be used /// - public string? UseContext { get; private set; } + public string? UseContext { get; } /// /// Title of the dialog box displayed when a newly created key is finalized, null for the default title /// - public string? CreationTitle { get; private set; } + public string? CreationTitle { get; } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ConcurrencyBlock.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ConcurrencyBlock.cs new file mode 100644 index 000000000000..c0eafe849da9 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ConcurrencyBlock.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Threading; + +namespace System.Security.Cryptography +{ + internal struct ConcurrencyBlock + { + private int _count; + + internal static Scope Enter(ref ConcurrencyBlock block) + { + int count = Interlocked.Increment(ref block._count); + + if (count != 1) + { + Interlocked.Decrement(ref block._count); + throw new CryptographicException(SR.Cryptography_ConcurrentUseNotSupported); + } + + return new Scope(ref block._count); + } + + internal ref struct Scope + { + private ref int _parentCount; + + internal Scope(ref int parentCount) + { + _parentCount = ref parentCount; + } + + internal void Dispose() + { + Interlocked.Decrement(ref _parentCount); + } + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ConcurrentSafeKmac.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ConcurrentSafeKmac.cs new file mode 100644 index 000000000000..ca41668473fa --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/ConcurrentSafeKmac.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography +{ + internal struct ConcurrentSafeKmac + { + private readonly LiteKmac _liteKmac; + private ConcurrencyBlock _block; + + public int HashSizeInBytes => _liteKmac.HashSizeInBytes; + + internal ConcurrentSafeKmac(string algorithmId, ReadOnlySpan key, ReadOnlySpan customizationString, bool xof) + { + _liteKmac = LiteHashProvider.CreateKmac(algorithmId, key, customizationString, xof); + } + + public void Append(ReadOnlySpan data) + { + using (ConcurrencyBlock.Enter(ref _block)) + { + _liteKmac.Append(data); + } + } + + public int Current(Span destination) + { + using (ConcurrencyBlock.Enter(ref _block)) + { + return _liteKmac.Current(destination); + } + } + + public int Finalize(Span destination) + { + using (ConcurrencyBlock.Enter(ref _block)) + { + return _liteKmac.Finalize(destination); + } + } + + public void Reset() + { + using (ConcurrencyBlock.Enter(ref _block)) + { + _liteKmac.Reset(); + } + } + + public void Dispose() => _liteKmac.Dispose(); + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderCng.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderCng.cs index 36f4767e9939..b698299e3c6c 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderCng.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderCng.cs @@ -3,6 +3,8 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Threading; using Microsoft.Win32.SafeHandles; using BCryptCreateHashFlags = Interop.BCrypt.BCryptCreateHashFlags; using BCryptOpenAlgorithmProviderFlags = Interop.BCrypt.BCryptOpenAlgorithmProviderFlags; @@ -63,47 +65,57 @@ internal HashProviderCng(string hashAlgId, ReadOnlySpan key, bool isHmac) public sealed override unsafe void AppendHashData(ReadOnlySpan source) { Debug.Assert(_hHash != null); - NTSTATUS ntStatus = Interop.BCrypt.BCryptHashData(_hHash, source, source.Length, 0); - if (ntStatus != NTSTATUS.STATUS_SUCCESS) + + using (ConcurrencyBlock.Enter(ref _block)) { - throw Interop.BCrypt.CreateCryptographicException(ntStatus); - } + NTSTATUS ntStatus = Interop.BCrypt.BCryptHashData(_hHash, source, source.Length, 0); + if (ntStatus != NTSTATUS.STATUS_SUCCESS) + { + throw Interop.BCrypt.CreateCryptographicException(ntStatus); + } - _running = true; + _running = true; + } } public override int FinalizeHashAndReset(Span destination) { Debug.Assert(destination.Length >= _hashSize); - Debug.Assert(_hHash != null); - NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(_hHash, destination, _hashSize, 0); - if (ntStatus != NTSTATUS.STATUS_SUCCESS) + + using (ConcurrencyBlock.Enter(ref _block)) { - throw Interop.BCrypt.CreateCryptographicException(ntStatus); - } + NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(_hHash, destination, _hashSize, 0); + + if (ntStatus != NTSTATUS.STATUS_SUCCESS) + { + throw Interop.BCrypt.CreateCryptographicException(ntStatus); + } - _running = false; - Reset(); - return _hashSize; + _running = false; + Reset(); + return _hashSize; + } } public override int GetCurrentHash(Span destination) { Debug.Assert(destination.Length >= _hashSize); - Debug.Assert(_hHash != null); - using (SafeBCryptHashHandle tmpHash = Interop.BCrypt.BCryptDuplicateHash(_hHash)) + using (ConcurrencyBlock.Enter(ref _block)) { - NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(tmpHash, destination, _hashSize, 0); - - if (ntStatus != NTSTATUS.STATUS_SUCCESS) + using (SafeBCryptHashHandle tmpHash = Interop.BCrypt.BCryptDuplicateHash(_hHash)) { - throw Interop.BCrypt.CreateCryptographicException(ntStatus); - } + NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(tmpHash, destination, _hashSize, 0); - return _hashSize; + if (ntStatus != NTSTATUS.STATUS_SUCCESS) + { + throw Interop.BCrypt.CreateCryptographicException(ntStatus); + } + + return _hashSize; + } } } @@ -111,7 +123,9 @@ public sealed override void Dispose(bool disposing) { if (disposing) { - DestroyHash(); + // Not disposing of _hAlgorithm as we got this from a cache. So it's not ours to Dispose(). + _hHash.Dispose(); + if (_key != null) { byte[] key = _key; @@ -123,12 +137,17 @@ public sealed override void Dispose(bool disposing) public sealed override int HashSizeInBytes => _hashSize; + [MemberNotNull(nameof(_hHash))] public override void Reset() { + // Reset does not need to use ConcurrencyBlock. It either no-ops, or creates an entirely new handle, exchanges + // them, and disposes of the old handle. We don't need to block concurrency on the Dispose because SafeHandle + // does that. if (_reusable && !_running) + { + Debug.Assert(_hHash is not null); return; - - DestroyHash(); + } BCryptCreateHashFlags flags = _reusable ? BCryptCreateHashFlags.BCRYPT_HASH_REUSABLE_FLAG : @@ -136,30 +155,24 @@ public override void Reset() SafeBCryptHashHandle hHash; NTSTATUS ntStatus = Interop.BCrypt.BCryptCreateHash(_hAlgorithm, out hHash, IntPtr.Zero, 0, _key, _key == null ? 0 : _key.Length, flags); - if (ntStatus != NTSTATUS.STATUS_SUCCESS) - throw Interop.BCrypt.CreateCryptographicException(ntStatus); - _hHash = hHash; - } - - private void DestroyHash() - { - SafeBCryptHashHandle? hHash = _hHash; - if (hHash != null) + if (ntStatus != NTSTATUS.STATUS_SUCCESS) { - _hHash = null; hHash.Dispose(); + throw Interop.BCrypt.CreateCryptographicException(ntStatus); } - // Not disposing of _hAlgorithm as we got this from a cache. So it's not ours to Dispose(). + SafeBCryptHashHandle? previousHash = Interlocked.Exchange(ref _hHash, hHash); + previousHash?.Dispose(); } private readonly SafeBCryptAlgorithmHandle _hAlgorithm; - private SafeBCryptHashHandle? _hHash; + private SafeBCryptHashHandle _hHash; private byte[]? _key; private readonly bool _reusable; private readonly int _hashSize; private bool _running; + private ConcurrencyBlock _block; } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Apple.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Apple.cs index 58e63629300a..fdd414d59ff2 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Apple.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Apple.cs @@ -141,6 +141,7 @@ private sealed class AppleDigestProvider : HashProvider { private readonly LiteHash _liteHash; private bool _running; + private ConcurrencyBlock _block; public AppleDigestProvider(string hashAlgorithmId) { @@ -149,21 +150,30 @@ public AppleDigestProvider(string hashAlgorithmId) public override void AppendHashData(ReadOnlySpan data) { - _liteHash.Append(data); - _running = true; + using (ConcurrencyBlock.Enter(ref _block)) + { + _liteHash.Append(data); + _running = true; + } } public override int FinalizeHashAndReset(Span destination) { - int written = _liteHash.Finalize(destination); - // Apple's DigestFinal self-resets, so don't bother calling reset. - _running = false; - return written; + using (ConcurrencyBlock.Enter(ref _block)) + { + int written = _liteHash.Finalize(destination); + // Apple's DigestFinal self-resets, so don't bother calling reset. + _running = false; + return written; + } } public override int GetCurrentHash(Span destination) { - return _liteHash.Current(destination); + using (ConcurrencyBlock.Enter(ref _block)) + { + return _liteHash.Current(destination); + } } public override int HashSizeInBytes => _liteHash.HashSizeInBytes; @@ -178,10 +188,13 @@ public override void Dispose(bool disposing) public override void Reset() { - if (_running) + using (ConcurrencyBlock.Enter(ref _block)) { - _liteHash.Reset(); - _running = false; + if (_running) + { + _liteHash.Reset(); + _running = false; + } } } } @@ -191,6 +204,7 @@ private sealed class AppleHmacProvider : HashProvider private readonly LiteHmac _liteHmac; private readonly byte[] _key; private bool _running; + private ConcurrencyBlock _block; public AppleHmacProvider(string hashAlgorithmId, ReadOnlySpan key) { @@ -201,36 +215,45 @@ public AppleHmacProvider(string hashAlgorithmId, ReadOnlySpan key) public override void AppendHashData(ReadOnlySpan data) { - if (!_running) + using (ConcurrencyBlock.Enter(ref _block)) { - _liteHmac.Reset(_key); - } + if (!_running) + { + _liteHmac.Reset(_key); + } - _liteHmac.Append(data); - _running = true; + _liteHmac.Append(data); + _running = true; + } } public override int FinalizeHashAndReset(Span destination) { - if (!_running) + using (ConcurrencyBlock.Enter(ref _block)) { + if (!_running) + { + _liteHmac.Reset(_key); + } + + int written = _liteHmac.Finalize(destination); _liteHmac.Reset(_key); + _running = false; + return written; } - - int written = _liteHmac.Finalize(destination); - _liteHmac.Reset(_key); - _running = false; - return written; } public override int GetCurrentHash(Span destination) { - if (!_running) + using (ConcurrencyBlock.Enter(ref _block)) { - _liteHmac.Reset(_key); - } + if (!_running) + { + _liteHmac.Reset(_key); + } - return _liteHmac.Current(destination); + return _liteHmac.Current(destination); + } } public override int HashSizeInBytes => _liteHmac.HashSizeInBytes; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Unix.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Unix.cs index d62505e88873..18e8659d0cbf 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Unix.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Unix.cs @@ -87,6 +87,7 @@ private sealed class EvpHashProvider : HashProvider { private readonly LiteHash _liteHash; private bool _running; + private ConcurrencyBlock _block; public EvpHashProvider(string hashAlgorithmId) { @@ -95,21 +96,30 @@ public EvpHashProvider(string hashAlgorithmId) public override void AppendHashData(ReadOnlySpan data) { - _liteHash.Append(data); - _running = true; + using (ConcurrencyBlock.Enter(ref _block)) + { + _liteHash.Append(data); + _running = true; + } } public override int FinalizeHashAndReset(Span destination) { - int written = _liteHash.Finalize(destination); - _liteHash.Reset(); - _running = false; - return written; + using (ConcurrencyBlock.Enter(ref _block)) + { + int written = _liteHash.Finalize(destination); + _liteHash.Reset(); + _running = false; + return written; + } } public override int GetCurrentHash(Span destination) { - return _liteHash.Current(destination); + using (ConcurrencyBlock.Enter(ref _block)) + { + return _liteHash.Current(destination); + } } public override int HashSizeInBytes => _liteHash.HashSizeInBytes; @@ -124,10 +134,13 @@ public override void Dispose(bool disposing) public override void Reset() { - if (_running) + using (ConcurrencyBlock.Enter(ref _block)) { - _liteHash.Reset(); - _running = false; + if (_running) + { + _liteHash.Reset(); + _running = false; + } } } } @@ -136,6 +149,7 @@ private sealed class HmacHashProvider : HashProvider { private readonly LiteHmac _liteHmac; private bool _running; + private ConcurrencyBlock _block; public HmacHashProvider(string hashAlgorithmId, ReadOnlySpan key) { @@ -144,21 +158,30 @@ public HmacHashProvider(string hashAlgorithmId, ReadOnlySpan key) public override void AppendHashData(ReadOnlySpan data) { - _liteHmac.Append(data); - _running = true; + using (ConcurrencyBlock.Enter(ref _block)) + { + _liteHmac.Append(data); + _running = true; + } } public override int FinalizeHashAndReset(Span destination) { - int written = _liteHmac.Finalize(destination); - _liteHmac.Reset(); - _running = false; - return written; + using (ConcurrencyBlock.Enter(ref _block)) + { + int written = _liteHmac.Finalize(destination); + _liteHmac.Reset(); + _running = false; + return written; + } } public override int GetCurrentHash(Span destination) { - return _liteHmac.Current(destination); + using (ConcurrencyBlock.Enter(ref _block)) + { + return _liteHmac.Current(destination); + } } public override int HashSizeInBytes => _liteHmac.HashSizeInBytes; @@ -173,10 +196,13 @@ public override void Dispose(bool disposing) public override void Reset() { - if (_running) + using (ConcurrencyBlock.Enter(ref _block)) { - _liteHmac.Reset(); - _running = false; + if (_running) + { + _liteHmac.Reset(); + _running = false; + } } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KeySizes.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KeySizes.cs index 167fbbc1853e..9189c896e2ab 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KeySizes.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KeySizes.cs @@ -17,8 +17,8 @@ public KeySizes(int minSize, int maxSize, int skipSize) SkipSize = skipSize; } - public int MinSize { get; private set; } - public int MaxSize { get; private set; } - public int SkipSize { get; private set; } + public int MinSize { get; } + public int MaxSize { get; } + public int SkipSize { get; } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Kmac128.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Kmac128.cs index c850977ef9b8..a90c987a8278 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Kmac128.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Kmac128.cs @@ -19,7 +19,7 @@ namespace System.Security.Cryptography /// public sealed class Kmac128 : IDisposable { - private readonly LiteKmac _kmacProvider; + private ConcurrentSafeKmac _kmacProvider; private bool _disposed; /// @@ -53,7 +53,7 @@ public Kmac128(byte[] key, byte[]? customizationString = null) public Kmac128(ReadOnlySpan key, ReadOnlySpan customizationString = default) { CheckPlatformSupport(); - _kmacProvider = LiteHashProvider.CreateKmac(HashAlgorithmNames.KMAC128, key, customizationString, xof: false); + _kmacProvider = new ConcurrentSafeKmac(HashAlgorithmNames.KMAC128, key, customizationString, xof: false); } /// diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Kmac256.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Kmac256.cs index 3ee2ff818191..d5c3d013e31e 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Kmac256.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Kmac256.cs @@ -19,7 +19,7 @@ namespace System.Security.Cryptography /// public sealed class Kmac256 : IDisposable { - private readonly LiteKmac _kmacProvider; + private ConcurrentSafeKmac _kmacProvider; private bool _disposed; /// @@ -53,7 +53,7 @@ public Kmac256(byte[] key, byte[]? customizationString = null) public Kmac256(ReadOnlySpan key, ReadOnlySpan customizationString = default) { CheckPlatformSupport(); - _kmacProvider = LiteHashProvider.CreateKmac(HashAlgorithmNames.KMAC256, key, customizationString, xof: false); + _kmacProvider = new ConcurrentSafeKmac(HashAlgorithmNames.KMAC256, key, customizationString, xof: false); } /// diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KmacXof128.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KmacXof128.cs index 3514fbaaa0c9..7275d822b136 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KmacXof128.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KmacXof128.cs @@ -19,7 +19,7 @@ namespace System.Security.Cryptography /// public sealed class KmacXof128 : IDisposable { - private readonly LiteKmac _kmacProvider; + private ConcurrentSafeKmac _kmacProvider; private bool _disposed; /// @@ -53,7 +53,7 @@ public KmacXof128(byte[] key, byte[]? customizationString = null) public KmacXof128(ReadOnlySpan key, ReadOnlySpan customizationString = default) { CheckPlatformSupport(); - _kmacProvider = LiteHashProvider.CreateKmac(HashAlgorithmNames.KMAC128, key, customizationString, xof: true); + _kmacProvider = new ConcurrentSafeKmac(HashAlgorithmNames.KMAC128, key, customizationString, xof: true); } /// diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KmacXof256.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KmacXof256.cs index 040fe7a37ec0..fe08a87d494f 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KmacXof256.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KmacXof256.cs @@ -19,7 +19,7 @@ namespace System.Security.Cryptography /// public sealed class KmacXof256 : IDisposable { - private readonly LiteKmac _kmacProvider; + private ConcurrentSafeKmac _kmacProvider; private bool _disposed; /// @@ -53,7 +53,7 @@ public KmacXof256(byte[] key, byte[]? customizationString = null) public KmacXof256(ReadOnlySpan key, ReadOnlySpan customizationString = default) { CheckPlatformSupport(); - _kmacProvider = LiteHashProvider.CreateKmac(HashAlgorithmNames.KMAC256, key, customizationString, xof: true); + _kmacProvider = new ConcurrentSafeKmac(HashAlgorithmNames.KMAC256, key, customizationString, xof: true); } /// diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Apple.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Apple.cs index 0b2fde720a20..1dbfd5567f02 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Apple.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Apple.cs @@ -39,6 +39,8 @@ internal static LiteXof CreateXof(string hashAlgorithmId) public int Finalize(Span destination) => throw new UnreachableException(); public void Current(Span destination) => throw new UnreachableException(); public int Reset() => throw new UnreachableException(); + public LiteXof Clone() => throw new UnreachableException(); + public void Read(Span destination) => throw new UnreachableException(); public void Dispose() => throw new UnreachableException(); #pragma warning restore IDE0060 #pragma warning restore CA1822 diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Browser.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Browser.cs index 92de5db403f3..5591479f0c79 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Browser.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Browser.cs @@ -34,6 +34,8 @@ internal static LiteXof CreateXof(string hashAlgorithmId) public int Finalize(Span destination) => throw new UnreachableException(); public void Current(Span destination) => throw new UnreachableException(); public int Reset() => throw new UnreachableException(); + public LiteXof Clone() => throw new UnreachableException(); + public void Read(Span destination) => throw new UnreachableException(); public void Dispose() => throw new UnreachableException(); #pragma warning restore IDE0060 #pragma warning restore CA1822 diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Unix.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Unix.cs index ab09b7217f89..32ebdb5ce092 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Unix.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Unix.cs @@ -44,6 +44,12 @@ internal LiteXof(IntPtr algorithm) Interop.Crypto.CheckValidOpenSslHandle(_ctx); } + private LiteXof(SafeEvpMdCtxHandle ctx, IntPtr algorithm) + { + _ctx = ctx; + _algorithm = algorithm; + } + public void Append(ReadOnlySpan data) { if (data.IsEmpty) @@ -70,6 +76,18 @@ public void Current(Span destination) Check(Interop.Crypto.EvpDigestCurrentXOF(_ctx, destination)); } + public LiteXof Clone() + { + SafeEvpMdCtxHandle clone = Interop.Crypto.EvpMdCtxCopyEx(_ctx); + Interop.Crypto.CheckValidOpenSslHandle(clone); + return new LiteXof(clone, _algorithm); + } + + public void Read(Span destination) + { + Check(Interop.Crypto.EvpDigestSqueeze(_ctx, destination)); + } + public void Dispose() { _ctx.Dispose(); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Windows.cs index bb3df4bb2f4c..324001daee99 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/LiteHash.Windows.cs @@ -159,10 +159,11 @@ private static void CheckStatus(NTSTATUS status) } } - internal struct LiteXof : ILiteHash + internal readonly struct LiteXof : ILiteHash { + private const int BCRYPT_HASH_DONT_RESET_FLAG = 0x00000001; private readonly nuint _algorithm; - private SafeBCryptHashHandle _hashHandle; + private readonly SafeBCryptHashHandle _hashHandle; internal LiteXof(string algorithm) { @@ -173,7 +174,24 @@ internal LiteXof(string algorithm) _ => throw FailThrow(algorithm), }; - Reset(); + SafeBCryptHashHandle hashHandle; + + NTSTATUS ntStatus = Interop.BCrypt.BCryptCreateHash( + _algorithm, + out hashHandle, + pbHashObject: IntPtr.Zero, + cbHashObject: 0, + secret: ReadOnlySpan.Empty, + cbSecret: 0, + BCryptCreateHashFlags.None); + + if (ntStatus != NTSTATUS.STATUS_SUCCESS) + { + hashHandle.Dispose(); + throw Interop.BCrypt.CreateCryptographicException(ntStatus); + } + + _hashHandle = hashHandle; static Exception FailThrow(string algorithm) { @@ -182,7 +200,13 @@ static Exception FailThrow(string algorithm) } } - public readonly int HashSizeInBytes + private LiteXof(SafeBCryptHashHandle hashHandle, nuint algorithm) + { + _algorithm = algorithm; + _hashHandle = hashHandle; + } + + public int HashSizeInBytes { get { @@ -191,7 +215,7 @@ public readonly int HashSizeInBytes } } - public readonly void Append(ReadOnlySpan data) + public void Append(ReadOnlySpan data) { if (data.IsEmpty) { @@ -206,7 +230,7 @@ public readonly void Append(ReadOnlySpan data) } } - public readonly unsafe int Finalize(Span destination) + public unsafe int Finalize(Span destination) { fixed (byte* pDestination = &Helpers.GetNonNullPinnableReference(destination)) { @@ -221,36 +245,33 @@ public readonly unsafe int Finalize(Span destination) } } - [MemberNotNull(nameof(_hashHandle))] - public void Reset() - { - _hashHandle?.Dispose(); - SafeBCryptHashHandle hashHandle; - - NTSTATUS ntStatus = Interop.BCrypt.BCryptCreateHash( - _algorithm, - out hashHandle, - pbHashObject: IntPtr.Zero, - cbHashObject: 0, - secret: ReadOnlySpan.Empty, - cbSecret: 0, - BCryptCreateHashFlags.None); + public void Reset() => Finalize(Span.Empty); - if (ntStatus != NTSTATUS.STATUS_SUCCESS) + public unsafe void Current(Span destination) + { + using (SafeBCryptHashHandle tmpHash = Interop.BCrypt.BCryptDuplicateHash(_hashHandle)) + fixed (byte* pDestination = &Helpers.GetNonNullPinnableReference(destination)) { - hashHandle.Dispose(); - throw Interop.BCrypt.CreateCryptographicException(ntStatus); + NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(tmpHash, pDestination, destination.Length, dwFlags: 0); + + if (ntStatus != NTSTATUS.STATUS_SUCCESS) + { + throw Interop.BCrypt.CreateCryptographicException(ntStatus); + } } + } - _hashHandle = hashHandle; + public LiteXof Clone() + { + SafeBCryptHashHandle clone = Interop.BCrypt.BCryptDuplicateHash(_hashHandle); + return new LiteXof(clone, _algorithm); } - public readonly unsafe void Current(Span destination) + public unsafe void Read(Span destination) { - using (SafeBCryptHashHandle tmpHash = Interop.BCrypt.BCryptDuplicateHash(_hashHandle)) fixed (byte* pDestination = &Helpers.GetNonNullPinnableReference(destination)) { - NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(tmpHash, pDestination, destination.Length, dwFlags: 0); + NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(_hashHandle, pDestination, destination.Length, dwFlags: BCRYPT_HASH_DONT_RESET_FLAG); if (ntStatus != NTSTATUS.STATUS_SUCCESS) { @@ -259,7 +280,7 @@ public readonly unsafe void Current(Span destination) } } - public readonly void Dispose() + public void Dispose() { _hashHandle.Dispose(); } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake128.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake128.cs index a8b5e5f3257f..80740c59a657 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake128.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake128.cs @@ -19,9 +19,10 @@ namespace System.Security.Cryptography /// public sealed partial class Shake128 : IDisposable { - // Some platforms have a mutable struct for LiteXof, do not mark this field as readonly. - private LiteXof _hashProvider; + private readonly LiteXof _hashProvider; private bool _disposed; + private ConcurrencyBlock _block; + private bool _reading; /// /// Initializes a new instance of the class. @@ -36,6 +37,11 @@ public Shake128() _hashProvider = LiteHashProvider.CreateXof(HashAlgorithmId); } + internal Shake128(LiteXof hashProvider) + { + _hashProvider = hashProvider; + } + /// /// Gets a value that indicates whether the algorithm is supported on the current platform. /// @@ -68,7 +74,11 @@ public void AppendData(ReadOnlySpan data) { CheckDisposed(); - _hashProvider.Append(data); + using (ConcurrencyBlock.Enter(ref _block)) + { + CheckReading(); + _hashProvider.Append(data); + } } /// @@ -87,10 +97,14 @@ public byte[] GetHashAndReset(int outputLength) ArgumentOutOfRangeException.ThrowIfNegative(outputLength); CheckDisposed(); - byte[] output = new byte[outputLength]; - _hashProvider.Finalize(output); - _hashProvider.Reset(); - return output; + using (ConcurrencyBlock.Enter(ref _block)) + { + CheckReading(); + byte[] output = new byte[outputLength]; + _hashProvider.Finalize(output); + _hashProvider.Reset(); + return output; + } } /// @@ -104,8 +118,12 @@ public void GetHashAndReset(Span destination) { CheckDisposed(); - _hashProvider.Finalize(destination); - _hashProvider.Reset(); + using (ConcurrencyBlock.Enter(ref _block)) + { + CheckReading(); + _hashProvider.Finalize(destination); + _hashProvider.Reset(); + } } /// @@ -124,9 +142,13 @@ public byte[] GetCurrentHash(int outputLength) ArgumentOutOfRangeException.ThrowIfNegative(outputLength); CheckDisposed(); - byte[] output = new byte[outputLength]; - _hashProvider.Current(output); - return output; + using (ConcurrencyBlock.Enter(ref _block)) + { + CheckReading(); + byte[] output = new byte[outputLength]; + _hashProvider.Current(output); + return output; + } } /// @@ -139,7 +161,100 @@ public byte[] GetCurrentHash(int outputLength) public void GetCurrentHash(Span destination) { CheckDisposed(); - _hashProvider.Current(destination); + + using (ConcurrencyBlock.Enter(ref _block)) + { + CheckReading(); + _hashProvider.Current(destination); + } + } + + /// + /// Retrieves the hash for the data accumulated from prior calls to the AppendData methods without + /// resetting the object to its initial state and allowing additional calls to continue retrieving the hash. + /// + /// The size of the hash to produce. + /// The computed hash. + /// + /// is negative. + /// + /// An error has occurred during the operation. + /// The object has already been disposed. + /// + /// The platform does not support multiple reads of the hash. can be used + /// to perform a single operation. + /// + public byte[] Read(int outputLength) + { + ArgumentOutOfRangeException.ThrowIfNegative(outputLength); + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + byte[] output = new byte[outputLength]; + _hashProvider.Read(output); + _reading = true; + return output; + } + } + + /// + /// Fills the buffer with the hash for the data accumulated from prior calls to the AppendData methods without + /// resetting the object to its initial state and allowing additional calls to continue retrieving the hash. + /// + /// The buffer to fill with the hash. + /// An error has occurred during the operation. + /// The object has already been disposed. + /// + /// The platform does not support multiple reads of the hash. can be used + /// to perform a single operation. + /// + public void Read(Span destination) + { + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + _hashProvider.Read(destination); + _reading = true; + } + } + + /// + /// Resets the instance back to its initial state. + /// + /// An error has occurred during the operation. + /// The object has already been disposed. + public void Reset() + { + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + _hashProvider.Reset(); + _reading = false; + } + } + + /// + /// Creates a new instance of with the existing appended data preserved. + /// + /// A clone of the current instance. + /// An error has occurred during the operation. + /// + /// The current instance is being read from and cannot be cloned. + /// + /// The object has already been disposed. + public Shake128 Clone() + { + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + CheckReading(); + LiteXof clone = _hashProvider.Clone(); + return new Shake128(clone); + } } /// @@ -368,5 +483,13 @@ private static void CheckPlatformSupport() } private void CheckDisposed() => ObjectDisposedException.ThrowIf(_disposed, this); + + private void CheckReading() + { + if (_reading) + { + throw new InvalidOperationException(SR.InvalidOperation_AlreadyReading); + } + } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake256.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake256.cs index cafe8d303633..d861257cf1e4 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake256.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Shake256.cs @@ -19,9 +19,10 @@ namespace System.Security.Cryptography /// public sealed partial class Shake256 : IDisposable { - // Some platforms have a mutable struct for LiteXof, do not mark this field as readonly. - private LiteXof _hashProvider; + private readonly LiteXof _hashProvider; private bool _disposed; + private ConcurrencyBlock _block; + private bool _reading; /// /// Initializes a new instance of the class. @@ -36,6 +37,11 @@ public Shake256() _hashProvider = LiteHashProvider.CreateXof(HashAlgorithmId); } + internal Shake256(LiteXof hashProvider) + { + _hashProvider = hashProvider; + } + /// /// Gets a value that indicates whether the algorithm is supported on the current platform. /// @@ -68,7 +74,11 @@ public void AppendData(ReadOnlySpan data) { CheckDisposed(); - _hashProvider.Append(data); + using (ConcurrencyBlock.Enter(ref _block)) + { + CheckReading(); + _hashProvider.Append(data); + } } /// @@ -87,10 +97,14 @@ public byte[] GetHashAndReset(int outputLength) ArgumentOutOfRangeException.ThrowIfNegative(outputLength); CheckDisposed(); - byte[] output = new byte[outputLength]; - _hashProvider.Finalize(output); - _hashProvider.Reset(); - return output; + using (ConcurrencyBlock.Enter(ref _block)) + { + CheckReading(); + byte[] output = new byte[outputLength]; + _hashProvider.Finalize(output); + _hashProvider.Reset(); + return output; + } } /// @@ -104,8 +118,12 @@ public void GetHashAndReset(Span destination) { CheckDisposed(); - _hashProvider.Finalize(destination); - _hashProvider.Reset(); + using (ConcurrencyBlock.Enter(ref _block)) + { + CheckReading(); + _hashProvider.Finalize(destination); + _hashProvider.Reset(); + } } /// @@ -124,9 +142,13 @@ public byte[] GetCurrentHash(int outputLength) ArgumentOutOfRangeException.ThrowIfNegative(outputLength); CheckDisposed(); - byte[] output = new byte[outputLength]; - _hashProvider.Current(output); - return output; + using (ConcurrencyBlock.Enter(ref _block)) + { + CheckReading(); + byte[] output = new byte[outputLength]; + _hashProvider.Current(output); + return output; + } } /// @@ -139,7 +161,100 @@ public byte[] GetCurrentHash(int outputLength) public void GetCurrentHash(Span destination) { CheckDisposed(); - _hashProvider.Current(destination); + + using (ConcurrencyBlock.Enter(ref _block)) + { + CheckReading(); + _hashProvider.Current(destination); + } + } + + /// + /// Retrieves the hash for the data accumulated from prior calls to the AppendData methods without + /// resetting the object to its initial state and allowing additional calls to continue retrieving the hash. + /// + /// The size of the hash to produce. + /// The computed hash. + /// + /// is negative. + /// + /// An error has occurred during the operation. + /// The object has already been disposed. + /// + /// The platform does not support multiple reads of the hash. can be used + /// to perform a single operation. + /// + public byte[] Read(int outputLength) + { + ArgumentOutOfRangeException.ThrowIfNegative(outputLength); + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + byte[] output = new byte[outputLength]; + _hashProvider.Read(output); + _reading = true; + return output; + } + } + + /// + /// Fills the buffer with the hash for the data accumulated from prior calls to the AppendData methods without + /// resetting the object to its initial state and allowing additional calls to continue retrieving the hash. + /// + /// The buffer to fill with the hash. + /// An error has occurred during the operation. + /// The object has already been disposed. + /// + /// The platform does not support multiple reads of the hash. can be used + /// to perform a single operation. + /// + public void Read(Span destination) + { + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + _hashProvider.Read(destination); + _reading = true; + } + } + + /// + /// Resets the instance back to its initial state. + /// + /// An error has occurred during the operation. + /// The object has already been disposed. + public void Reset() + { + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + _hashProvider.Reset(); + _reading = false; + } + } + + /// + /// Creates a new instance of with the existing appended data preserved. + /// + /// A clone of the current instance. + /// An error has occurred during the operation. + /// + /// The current instance is being read from and cannot be cloned. + /// + /// The object has already been disposed. + public Shake256 Clone() + { + CheckDisposed(); + + using (ConcurrencyBlock.Enter(ref _block)) + { + CheckReading(); + LiteXof clone = _hashProvider.Clone(); + return new Shake256(clone); + } } /// @@ -368,5 +483,13 @@ private static void CheckPlatformSupport() } private void CheckDisposed() => ObjectDisposedException.ThrowIf(_disposed, this); + + private void CheckReading() + { + if (_reading) + { + throw new InvalidOperationException(SR.InvalidOperation_AlreadyReading); + } + } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/UniversalCryptoTransform.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/UniversalCryptoTransform.cs index 865b6a54e861..824636e4e9f6 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/UniversalCryptoTransform.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/UniversalCryptoTransform.cs @@ -121,7 +121,7 @@ protected int UncheckedTransformBlock(byte[] inputBuffer, int inputOffset, int i protected abstract byte[] UncheckedTransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount); protected abstract int UncheckedTransformFinalBlock(ReadOnlySpan inputBuffer, Span outputBuffer); - protected PaddingMode PaddingMode { get; private set; } - protected BasicSymmetricCipher BasicSymmetricCipher { get; private set; } + protected PaddingMode PaddingMode { get; } + protected BasicSymmetricCipher BasicSymmetricCipher { get; } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs index baa791d59f34..1de7e8ce9bee 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs @@ -7,7 +7,7 @@ namespace System.Security.Cryptography.X509Certificates { internal sealed partial class AppleCertificatePal : ICertificatePal { - private static SafePasswordHandle s_passwordExportHandle = new SafePasswordHandle("DotnetExportPassphrase", passwordProvided: true); + private static readonly SafePasswordHandle s_passwordExportHandle = new SafePasswordHandle("DotnetExportPassphrase", passwordProvided: true); private static AppleCertificatePal ImportPkcs12( ReadOnlySpan rawData, diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/PublicKey.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/PublicKey.cs index d70378ef97b2..589e548fc85e 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/PublicKey.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/PublicKey.cs @@ -68,9 +68,9 @@ public PublicKey(AsymmetricAlgorithm key) // will start returning non Rsa / Dsa types. } - public AsnEncodedData EncodedKeyValue { get; private set; } + public AsnEncodedData EncodedKeyValue { get; } - public AsnEncodedData EncodedParameters { get; private set; } + public AsnEncodedData EncodedParameters { get; } [Obsolete(Obsoletions.PublicKeyPropertyMessage, DiagnosticId = Obsoletions.PublicKeyPropertyDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public AsymmetricAlgorithm Key diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainElement.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainElement.cs index ec247c9d98c5..9f926d75f2b0 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainElement.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509ChainElement.cs @@ -20,11 +20,11 @@ internal X509ChainElement(X509Certificate2 certificate, X509ChainStatus[] chainE Information = information; } - public X509Certificate2 Certificate { get; private set; } + public X509Certificate2 Certificate { get; } // For compat purposes, ChainElementStatus does *not* give each caller a private copy of the array. - public X509ChainStatus[] ChainElementStatus { get; private set; } + public X509ChainStatus[] ChainElementStatus { get; } - public string Information { get; private set; } + public string Information { get; } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Store.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Store.cs index 07e68341d2c2..b68ea52a80ea 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Store.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Store.cs @@ -97,9 +97,9 @@ public IntPtr StoreHandle } } - public StoreLocation Location { get; private set; } + public StoreLocation Location { get; } - public string? Name { get; private set; } + public string? Name { get; } public void Open(OpenFlags flags) diff --git a/src/libraries/System.Security.Cryptography/tests/AsymmetricAlgorithm/Trivial.cs b/src/libraries/System.Security.Cryptography/tests/AsymmetricAlgorithm/Trivial.cs index 1fb2f0306aa8..97a6ba6d3548 100644 --- a/src/libraries/System.Security.Cryptography/tests/AsymmetricAlgorithm/Trivial.cs +++ b/src/libraries/System.Security.Cryptography/tests/AsymmetricAlgorithm/Trivial.cs @@ -51,7 +51,7 @@ public static void ValidKeySizeUsesProperty() } } -#if NETCOREAPP +#if NET [Fact] public static void ClearCallsDispose() { diff --git a/src/libraries/System.Security.Cryptography/tests/ChaCha20Poly1305Tests.cs b/src/libraries/System.Security.Cryptography/tests/ChaCha20Poly1305Tests.cs index ced6edcf3509..00ae5286b25a 100644 --- a/src/libraries/System.Security.Cryptography/tests/ChaCha20Poly1305Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/ChaCha20Poly1305Tests.cs @@ -475,7 +475,7 @@ public static void CheckIsSupported() } else if (PlatformDetection.IsOSX) { - // CryptoKit is supported on macOS 10.15+, which is our minimum target. + // CryptoKit is supported on macOS 10.15+, which is lower than our minimum target. expectedIsSupported = true; } else if (PlatformDetection.OpenSslPresentOnSystem && PlatformDetection.IsOpenSslSupported) diff --git a/src/libraries/System.Security.Cryptography/tests/DefaultDSAProvider.cs b/src/libraries/System.Security.Cryptography/tests/DefaultDSAProvider.cs index e04a1ce81f26..03c3bf5d02a3 100644 --- a/src/libraries/System.Security.Cryptography/tests/DefaultDSAProvider.cs +++ b/src/libraries/System.Security.Cryptography/tests/DefaultDSAProvider.cs @@ -12,7 +12,7 @@ public DSA Create() public DSA Create(int keySize) { -#if NETCOREAPP +#if NET return DSA.Create(keySize); #else DSA dsa = Create(); diff --git a/src/libraries/System.Security.Cryptography/tests/DefaultECDsaProvider.cs b/src/libraries/System.Security.Cryptography/tests/DefaultECDsaProvider.cs index 001869125e0c..91015c49a39f 100644 --- a/src/libraries/System.Security.Cryptography/tests/DefaultECDsaProvider.cs +++ b/src/libraries/System.Security.Cryptography/tests/DefaultECDsaProvider.cs @@ -19,7 +19,7 @@ public ECDsa Create(int keySize) return ec; } -#if NETCOREAPP +#if NET public ECDsa Create(ECCurve curve) { return ECDsa.Create(curve); diff --git a/src/libraries/System.Security.Cryptography/tests/DefaultRSAProvider.cs b/src/libraries/System.Security.Cryptography/tests/DefaultRSAProvider.cs index c65b78ace128..ab19c2aa0334 100644 --- a/src/libraries/System.Security.Cryptography/tests/DefaultRSAProvider.cs +++ b/src/libraries/System.Security.Cryptography/tests/DefaultRSAProvider.cs @@ -15,7 +15,7 @@ public class DefaultRSAProvider : IRSAProvider public RSA Create(int keySize) { -#if NETCOREAPP +#if NET return RSA.Create(keySize); #else RSA rsa = Create(); diff --git a/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTestDriver.cs b/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTestDriver.cs index 2fa0779a257e..bbcf23ec0e59 100644 --- a/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTestDriver.cs +++ b/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTestDriver.cs @@ -5,6 +5,8 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.DotNet.RemoteExecutor; +using Microsoft.DotNet.XUnitExtensions; using Test.Cryptography; using Xunit; @@ -14,7 +16,7 @@ public abstract class HashAlgorithmTestDriver where THashTrait : IHa { public static bool IsSupported => THashTrait.IsSupported; public static bool IsNotSupported => !IsSupported; - protected abstract HashAlgorithm Create(); + protected HashAlgorithm Create() => THashTrait.Create(); protected abstract bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten); protected abstract byte[] HashData(byte[] source); protected abstract byte[] HashData(ReadOnlySpan source); @@ -930,11 +932,235 @@ public void CryptographicOperations_HashData_ArgValidation_UnreadableStream() Assert.Throws("source", () => CryptographicOperations.HashDataAsync(HashAlgorithm, UntouchableStream.Instance, Memory.Empty)); } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void HashAlgorithm_ComputeHash_ConcurrentUseDoesNotCrashProcess() + { + if (!IsSupported) + { + throw new SkipTestException("Algorithm is not supported on this platform."); + } + + static void Update(object obj) + { + byte[] data = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + + for (int i = 0; i < 10_000; i++) + { + try + { + ((HashAlgorithm)obj).ComputeHash(data); + } + catch + { + // Ignore all managed exceptions. HashAlgorithm is not thread safe, but we don't want process + // crashes. + } + } + } + + RemoteExecutor.Invoke(static () => + { + using (HashAlgorithm hash = THashTrait.Create()) + { + Thread thread1 = new(Update); + Thread thread2 = new(Update); + thread1.Start(hash); + thread2.Start(hash); + thread1.Join(); + thread2.Join(); + } + + return RemoteExecutor.SuccessExitCode; + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void HashAlgorithm_TransformBlock_ConcurrentUseDoesNotCrashProcess() + { + if (!IsSupported) + { + throw new SkipTestException("Algorithm is not supported on this platform."); + } + + static void Update(object obj) + { + byte[] data = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + + for (int i = 0; i < 10_000; i++) + { + try + { + ((HashAlgorithm)obj).TransformBlock(data, 0, data.Length, null, 0); + } + catch + { + // Ignore all managed exceptions. HashAlgorithm is not thread safe, but we don't want process + // crashes. + } + } + } + + RemoteExecutor.Invoke(static () => + { + using (HashAlgorithm hash = THashTrait.Create()) + { + Thread thread1 = new(Update); + Thread thread2 = new(Update); + thread1.Start(hash); + thread2.Start(hash); + thread1.Join(); + thread2.Join(); + } + + return RemoteExecutor.SuccessExitCode; + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void HashAlgorithm_TransformFinalBlock_ConcurrentUseDoesNotCrashProcess() + { + if (!IsSupported) + { + throw new SkipTestException("Algorithm is not supported on this platform."); + } + + static void Update(object obj) + { + byte[] data = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + + for (int i = 0; i < 10_000; i++) + { + try + { + ((HashAlgorithm)obj).TransformFinalBlock(data, 0, data.Length); + } + catch + { + // Ignore all managed exceptions. HashAlgorithm is not thread safe, but we don't want process + // crashes. + } + } + } + + RemoteExecutor.Invoke(static () => + { + using (HashAlgorithm hash = THashTrait.Create()) + { + Thread thread1 = new(Update); + Thread thread2 = new(Update); + thread1.Start(hash); + thread2.Start(hash); + thread1.Join(); + thread2.Join(); + } + + return RemoteExecutor.SuccessExitCode; + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void HashAlgorithm_TransformBlockAndInitialize_ConcurrentUseDoesNotCrashProcess() + { + if (!IsSupported) + { + throw new SkipTestException("Algorithm is not supported on this platform."); + } + + static void Update(object obj) + { + byte[] data = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + + for (int i = 0; i < 10_000; i++) + { + try + { + HashAlgorithm hash = ((HashAlgorithm)obj); + hash.TransformBlock(data, 0, data.Length, null, 0); + hash.Initialize(); + } + catch + { + // Ignore all managed exceptions. HashAlgorithm is not thread safe, but we don't want process + // crashes. + } + } + } + + RemoteExecutor.Invoke(static () => + { + using (HashAlgorithm hash = THashTrait.Create()) + { + Thread thread1 = new(Update); + Thread thread2 = new(Update); + thread1.Start(hash); + thread2.Start(hash); + thread1.Join(); + thread2.Join(); + } + + return RemoteExecutor.SuccessExitCode; + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void HashAlgorithm_TransformBlockAndDispose_ConcurrentUseDoesNotCrashProcess() + { + if (!IsSupported) + { + throw new SkipTestException("Algorithm is not supported on this platform."); + } + + static void Update(object obj) + { + byte[] data = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + + for (int i = 0; i < 10_000; i++) + { + try + { + HashAlgorithm hash = ((HashAlgorithm)obj); + hash.TransformBlock(data, 0, data.Length, null, 0); + } + catch + { + // Ignore all managed exceptions. HashAlgorithm is not thread safe, but we don't want process + // crashes. + } + } + } + + RemoteExecutor.Invoke(static () => + { + using (HashAlgorithm hash = THashTrait.Create()) + { + Thread thread1 = new(Update); + Thread thread2 = new(obj => + { + Thread.Sleep(10); + try + { + ((HashAlgorithm)obj).Dispose(); + } + catch + { + } + }); + thread1.Start(hash); + thread2.Start(hash); + thread1.Join(); + thread2.Join(); + } + + return RemoteExecutor.SuccessExitCode; + }).Dispose(); + } } public interface IHashTrait { static abstract bool IsSupported { get; } static abstract int HashSizeInBytes { get; } + static abstract HashAlgorithm Create(); } } diff --git a/src/libraries/System.Security.Cryptography/tests/IncrementalHashTests.cs b/src/libraries/System.Security.Cryptography/tests/IncrementalHashTests.cs index dc7c33debfa8..69788b240232 100644 --- a/src/libraries/System.Security.Cryptography/tests/IncrementalHashTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/IncrementalHashTests.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Threading; +using Microsoft.DotNet.RemoteExecutor; using Test.Cryptography; using Xunit; @@ -622,6 +624,106 @@ public static void VerifyBounds_GetHashAndReset_Hash(HashAlgorithm referenceAlgo } } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void Hash_GetHashAndReset_ConcurrentUseDoesNotCrashProcess() + { + static void ThreadWork(object obj) + { + try + { + IncrementalHash hash = (IncrementalHash)obj; + + for (int i = 0; i < 10_000; i++) + { + hash.AppendData("potatos and carrots make for a fine stew."u8); + hash.GetHashAndReset(); + } + } + catch + { + // Ignore all managed exceptions. IncrementalHash is not thread safe, but we don't want process + // crashes. + } + } + + RemoteExecutor.Invoke(static () => + { + foreach(object[] items in GetHashAlgorithms()) + { + if (items is [HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm]) + { + referenceAlgorithm.Dispose(); + + using (IncrementalHash hash = IncrementalHash.CreateHash(hashAlgorithm)) + { + Thread thread1 = new(ThreadWork); + Thread thread2 = new(ThreadWork); + thread1.Start(hash); + thread2.Start(hash); + thread1.Join(); + thread2.Join(); + } + } + else + { + Assert.Fail("Test is not set up correctly."); + } + } + + return RemoteExecutor.SuccessExitCode; + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void HMAC_GetHashAndReset_ConcurrentUseDoesNotCrashProcess() + { + static void ThreadWork(object obj) + { + try + { + IncrementalHash hash = (IncrementalHash)obj; + + for (int i = 0; i < 10_000; i++) + { + hash.AppendData("potatos and carrots make for a fine stew."u8); + hash.GetHashAndReset(); + } + } + catch + { + // Ignore all managed exceptions. IncrementalHash is not thread safe, but we don't want process + // crashes. + } + } + + RemoteExecutor.Invoke(static () => + { + foreach(object[] items in GetHMACs()) + { + if (items is [HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm]) + { + referenceAlgorithm.Dispose(); + + using (IncrementalHash hash = IncrementalHash.CreateHMAC(hashAlgorithm, [1, 2, 3, 4])) + { + Thread thread1 = new(ThreadWork); + Thread thread2 = new(ThreadWork); + thread1.Start(hash); + thread2.Start(hash); + thread1.Join(); + thread2.Join(); + } + } + else + { + Assert.Fail("Test is not set up correctly."); + } + } + + return RemoteExecutor.SuccessExitCode; + }).Dispose(); + } + private static void VerifyGetCurrentHash(IncrementalHash single, IncrementalHash accumulated) { Span buf = stackalloc byte[2048]; diff --git a/src/libraries/System.Security.Cryptography/tests/MD5Tests.cs b/src/libraries/System.Security.Cryptography/tests/MD5Tests.cs index 8fe91caf0d1b..6e9f4a724fff 100644 --- a/src/libraries/System.Security.Cryptography/tests/MD5Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/MD5Tests.cs @@ -15,9 +15,9 @@ public sealed class Traits : IHashTrait { public static bool IsSupported => true; public static int HashSizeInBytes => MD5.HashSizeInBytes; + public static HashAlgorithm Create() => MD5.Create(); } - protected override HashAlgorithm Create() => MD5.Create(); protected override HashAlgorithmName HashAlgorithm => HashAlgorithmName.MD5; protected override bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten) diff --git a/src/libraries/System.Security.Cryptography/tests/Sha1ManagedTests.cs b/src/libraries/System.Security.Cryptography/tests/Sha1ManagedTests.cs index 54e7476f5447..7d9fee4ee137 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha1ManagedTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha1ManagedTests.cs @@ -6,11 +6,13 @@ namespace System.Security.Cryptography.Tests /// /// Sha1Managed has a copy of the same implementation as SHA1 /// - public class Sha1ManagedTests : Sha1Tests + public class Sha1ManagedTests : Sha1Tests { - protected override HashAlgorithm Create() + public sealed class Traits : IHashTrait { - return new SHA1Managed(); + public static bool IsSupported => true; + public static int HashSizeInBytes => SHA1.HashSizeInBytes; + public static HashAlgorithm Create() => new SHA1Managed(); } } } diff --git a/src/libraries/System.Security.Cryptography/tests/Sha1Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha1Tests.cs index 691dd9ea45e1..ede541452f59 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha1Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha1Tests.cs @@ -8,15 +8,18 @@ namespace System.Security.Cryptography.Tests { - public class Sha1Tests : HashAlgorithmTestDriver + public sealed class FactorySha1Tests : Sha1Tests { public sealed class Traits : IHashTrait { public static bool IsSupported => true; public static int HashSizeInBytes => SHA1.HashSizeInBytes; + public static HashAlgorithm Create() => SHA1.Create(); } + } - protected override HashAlgorithm Create() => SHA1.Create(); + public abstract class Sha1Tests : HashAlgorithmTestDriver where THashTrait : IHashTrait + { protected override HashAlgorithmName HashAlgorithm => HashAlgorithmName.SHA1; protected override bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten) diff --git a/src/libraries/System.Security.Cryptography/tests/Sha256ManagedTests.cs b/src/libraries/System.Security.Cryptography/tests/Sha256ManagedTests.cs index 2f153da87a60..3241fe97d5bd 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha256ManagedTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha256ManagedTests.cs @@ -6,11 +6,13 @@ namespace System.Security.Cryptography.Tests /// /// Sha256Managed has a copy of the same implementation as SHA256 /// - public class Sha256ManagedTests : Sha256Tests + public class Sha256ManagedTests : Sha256Tests { - protected override HashAlgorithm Create() + public sealed class Traits : IHashTrait { - return new SHA256Managed(); + public static bool IsSupported => true; + public static int HashSizeInBytes => SHA256.HashSizeInBytes; + public static HashAlgorithm Create() => new SHA256Managed(); } } } diff --git a/src/libraries/System.Security.Cryptography/tests/Sha256Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha256Tests.cs index b10cc017a313..c19008e5580c 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha256Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha256Tests.cs @@ -8,15 +8,18 @@ namespace System.Security.Cryptography.Tests { - public class Sha256Tests : HashAlgorithmTestDriver + public sealed class FactorySha256Tests : Sha256Tests { public sealed class Traits : IHashTrait { public static bool IsSupported => true; public static int HashSizeInBytes => SHA256.HashSizeInBytes; + public static HashAlgorithm Create() => SHA256.Create(); } + } - protected override HashAlgorithm Create() => SHA256.Create(); + public abstract class Sha256Tests : HashAlgorithmTestDriver where THashTrait : IHashTrait + { protected override HashAlgorithmName HashAlgorithm => HashAlgorithmName.SHA256; protected override bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten) diff --git a/src/libraries/System.Security.Cryptography/tests/Sha384ManagedTests.cs b/src/libraries/System.Security.Cryptography/tests/Sha384ManagedTests.cs index 88166dbf0496..4cf7baa1fa39 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha384ManagedTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha384ManagedTests.cs @@ -6,11 +6,13 @@ namespace System.Security.Cryptography.Tests /// /// Sha384Managed has a copy of the same implementation as SHA384 /// - public class Sha384ManagedTests : Sha384Tests + public class Sha384ManagedTests : Sha384Tests { - protected override HashAlgorithm Create() + public sealed class Traits : IHashTrait { - return new SHA384Managed(); + public static bool IsSupported => true; + public static int HashSizeInBytes => SHA384.HashSizeInBytes; + public static HashAlgorithm Create() => new SHA384Managed(); } } } diff --git a/src/libraries/System.Security.Cryptography/tests/Sha384Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha384Tests.cs index ae1a720c51ee..53b557b42190 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha384Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha384Tests.cs @@ -8,15 +8,18 @@ namespace System.Security.Cryptography.Tests { - public class Sha384Tests : HashAlgorithmTestDriver + public sealed class FactorySha384Tests : Sha384Tests { public sealed class Traits : IHashTrait { public static bool IsSupported => true; public static int HashSizeInBytes => SHA384.HashSizeInBytes; + public static HashAlgorithm Create() => SHA384.Create(); } + } - protected override HashAlgorithm Create() => SHA384.Create(); + public abstract class Sha384Tests : HashAlgorithmTestDriver where THashTrait : IHashTrait + { protected override HashAlgorithmName HashAlgorithm => HashAlgorithmName.SHA384; protected override bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten) diff --git a/src/libraries/System.Security.Cryptography/tests/Sha3_256Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha3_256Tests.cs index 96fe91e4f302..f5c002d64e4a 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha3_256Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha3_256Tests.cs @@ -15,9 +15,9 @@ public sealed class Traits : IHashTrait { public static bool IsSupported => SHA3_256.IsSupported; public static int HashSizeInBytes => SHA3_256.HashSizeInBytes; + public static HashAlgorithm Create() => SHA3_256.Create(); } - protected override HashAlgorithm Create() => SHA3_256.Create(); protected override HashAlgorithmName HashAlgorithm => HashAlgorithmName.SHA3_256; protected override bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten) diff --git a/src/libraries/System.Security.Cryptography/tests/Sha3_384Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha3_384Tests.cs index 9e67fb32b7ab..416e6ae1b6cb 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha3_384Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha3_384Tests.cs @@ -15,9 +15,9 @@ public sealed class Traits : IHashTrait { public static bool IsSupported => SHA3_384.IsSupported; public static int HashSizeInBytes => SHA3_384.HashSizeInBytes; + public static HashAlgorithm Create() => SHA3_384.Create(); } - protected override HashAlgorithm Create() => SHA3_384.Create(); protected override HashAlgorithmName HashAlgorithm => HashAlgorithmName.SHA3_384; protected override bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten) diff --git a/src/libraries/System.Security.Cryptography/tests/Sha3_512Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha3_512Tests.cs index a715cd40c559..843d87110fc6 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha3_512Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha3_512Tests.cs @@ -15,9 +15,9 @@ public sealed class Traits : IHashTrait { public static bool IsSupported => SHA3_512.IsSupported; public static int HashSizeInBytes => SHA3_512.HashSizeInBytes; + public static HashAlgorithm Create() => SHA3_512.Create(); } - protected override HashAlgorithm Create() => SHA3_512.Create(); protected override HashAlgorithmName HashAlgorithm => HashAlgorithmName.SHA3_512; protected override bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten) diff --git a/src/libraries/System.Security.Cryptography/tests/Sha512ManagedTests.cs b/src/libraries/System.Security.Cryptography/tests/Sha512ManagedTests.cs index e616e4fea13e..d6299ec4c84f 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha512ManagedTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha512ManagedTests.cs @@ -6,11 +6,13 @@ namespace System.Security.Cryptography.Tests /// /// Sha512Managed has a copy of the same implementation as SHA512 /// - public class Sha512ManagedTests : Sha512Tests + public class Sha512ManagedTests : Sha512Tests { - protected override HashAlgorithm Create() + public sealed class Traits : IHashTrait { - return new SHA512Managed(); + public static bool IsSupported => true; + public static int HashSizeInBytes => SHA512.HashSizeInBytes; + public static HashAlgorithm Create() => new SHA512Managed(); } } } diff --git a/src/libraries/System.Security.Cryptography/tests/Sha512Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha512Tests.cs index dde06d364696..7abfdb8a5460 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha512Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha512Tests.cs @@ -8,15 +8,18 @@ namespace System.Security.Cryptography.Tests { - public class Sha512Tests : HashAlgorithmTestDriver + public sealed class FactorySha512Tests : Sha512Tests { public sealed class Traits : IHashTrait { public static bool IsSupported => true; public static int HashSizeInBytes => SHA512.HashSizeInBytes; + public static HashAlgorithm Create() => SHA512.Create(); } + } - protected override HashAlgorithm Create() => SHA512.Create(); + public abstract class Sha512Tests : HashAlgorithmTestDriver where THashTrait : IHashTrait + { protected override HashAlgorithmName HashAlgorithm => HashAlgorithmName.SHA512; protected override bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten) diff --git a/src/libraries/System.Security.Cryptography/tests/Shake128Tests.cs b/src/libraries/System.Security.Cryptography/tests/Shake128Tests.cs index e203d77f46b6..8cfa95b57621 100644 --- a/src/libraries/System.Security.Cryptography/tests/Shake128Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Shake128Tests.cs @@ -21,6 +21,10 @@ public class Traits : IShakeTrait public static void GetHashAndReset(Shake128 shake, Span destination) => shake.GetHashAndReset(destination); public static byte[] GetCurrentHash(Shake128 shake, int outputLength) => shake.GetCurrentHash(outputLength); public static void GetCurrentHash(Shake128 shake, Span destination) => shake.GetCurrentHash(destination); + public static void Read(Shake128 shake, Span destination) => shake.Read(destination); + public static byte[] Read(Shake128 shake, int outputLength) => shake.Read(outputLength); + public static void Reset(Shake128 shake) => shake.Reset(); + public static Shake128 Clone(Shake128 shake) => shake.Clone(); public static byte[] HashData(byte[] source, int outputLength) => Shake128.HashData(source, outputLength); public static byte[] HashData(ReadOnlySpan source, int outputLength) => Shake128.HashData(source, outputLength); diff --git a/src/libraries/System.Security.Cryptography/tests/Shake256Tests.cs b/src/libraries/System.Security.Cryptography/tests/Shake256Tests.cs index 9631752e6944..23886ccb2b2d 100644 --- a/src/libraries/System.Security.Cryptography/tests/Shake256Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Shake256Tests.cs @@ -21,6 +21,10 @@ public class Traits : IShakeTrait public static void GetHashAndReset(Shake256 shake, Span destination) => shake.GetHashAndReset(destination); public static byte[] GetCurrentHash(Shake256 shake, int outputLength) => shake.GetCurrentHash(outputLength); public static void GetCurrentHash(Shake256 shake, Span destination) => shake.GetCurrentHash(destination); + public static void Read(Shake256 shake, Span destination) => shake.Read(destination); + public static byte[] Read(Shake256 shake, int outputLength) => shake.Read(outputLength); + public static void Reset(Shake256 shake) => shake.Reset(); + public static Shake256 Clone(Shake256 shake) => shake.Clone(); public static byte[] HashData(byte[] source, int outputLength) => Shake256.HashData(source, outputLength); public static byte[] HashData(ReadOnlySpan source, int outputLength) => Shake256.HashData(source, outputLength); diff --git a/src/libraries/System.Security.Cryptography/tests/ShakeTestDriver.cs b/src/libraries/System.Security.Cryptography/tests/ShakeTestDriver.cs index f7d1ee2de070..658d1b83a80d 100644 --- a/src/libraries/System.Security.Cryptography/tests/ShakeTestDriver.cs +++ b/src/libraries/System.Security.Cryptography/tests/ShakeTestDriver.cs @@ -6,11 +6,13 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.DotNet.RemoteExecutor; +using Microsoft.DotNet.XUnitExtensions; using Xunit; namespace System.Security.Cryptography.Tests { - public interface IShakeTrait where TShake : IDisposable, new() + public interface IShakeTrait where TShake : class, IDisposable, new() { static abstract TShake Create(); static abstract bool IsSupported { get; } @@ -20,6 +22,10 @@ namespace System.Security.Cryptography.Tests static abstract void GetHashAndReset(TShake shake, Span destination); static abstract byte[] GetCurrentHash(TShake shake, int outputLength); static abstract void GetCurrentHash(TShake shake, Span destination); + static abstract void Read(TShake shake, Span destination); + static abstract byte[] Read(TShake shake, int outputLength); + static abstract void Reset(TShake shake); + static abstract TShake Clone(TShake shake); static abstract byte[] HashData(byte[] source, int outputLength); static abstract byte[] HashData(ReadOnlySpan source, int outputLength); @@ -35,12 +41,21 @@ namespace System.Security.Cryptography.Tests public abstract class ShakeTestDriver where TShakeTrait : IShakeTrait - where TShake : IDisposable, new() + where TShake : class, IDisposable, new() { protected abstract IEnumerable<(string Msg, string Output)> Fips202Kats { get; } public static bool IsSupported => TShakeTrait.IsSupported; public static bool IsNotSupported => !IsSupported; + public static bool IsReadSupported + { + get + { + const long OpenSsl_3_2_0 = 0x30200000L; + return IsSupported && (PlatformDetection.IsWindows || SafeEvpPKeyHandle.OpenSslVersion >= OpenSsl_3_2_0); + } + } + [ConditionalFact(nameof(IsSupported))] public void KnownAnswerTests_Allocated_AllAtOnce() { @@ -149,6 +164,113 @@ public void KnownAnswerTests_Allocated_Hash_Destination() } } + [ConditionalFact(nameof(IsReadSupported))] + public void KnownAnswerTests_Allocated_Read_Twice() + { + foreach ((string Msg, string Output) kat in Fips202Kats) + { + byte[] message = Convert.FromHexString(kat.Msg); + + using (TShake shake = new TShake()) + { + TShakeTrait.AppendData(shake, message); + Span hash = new byte[kat.Output.Length / 2]; + ReadChunked(shake, hash); + Assert.Equal(kat.Output, Convert.ToHexString(hash), ignoreCase: true); + + TShakeTrait.Reset(shake); + hash.Clear(); + + TShakeTrait.AppendData(shake, message); + ReadChunked(shake, hash); + Assert.Equal(kat.Output, Convert.ToHexString(hash), ignoreCase: true); + } + } + } + + [ConditionalFact(nameof(IsReadSupported))] + public void KnownAnswerTests_Allocated_Read_GetHashAndReset() + { + foreach ((string Msg, string Output) kat in Fips202Kats) + { + byte[] message = Convert.FromHexString(kat.Msg); + + using (TShake shake = new TShake()) + { + TShakeTrait.AppendData(shake, message); + Span hash = new byte[kat.Output.Length / 2]; + ReadChunked(shake, hash); + Assert.Equal(kat.Output, Convert.ToHexString(hash), ignoreCase: true); + + TShakeTrait.Reset(shake); + hash.Clear(); + + TShakeTrait.AppendData(shake, message); + TShakeTrait.GetHashAndReset(shake, hash); + Assert.Equal(kat.Output, Convert.ToHexString(hash), ignoreCase: true); + } + } + } + + [ConditionalFact(nameof(IsSupported))] + public void KnownAnswerTests_Clone_Independent_Unobserved() + { + foreach ((string Msg, string Output) kat in Fips202Kats) + { + byte[] message = Convert.FromHexString(kat.Msg); + byte[] hash = new byte[kat.Output.Length / 2]; + + using (TShake shake = new TShake()) + using (TShake clone = TShakeTrait.Clone(shake)) + { + TShakeTrait.AppendData(shake, "badbadbad"u8); + + TShakeTrait.AppendData(clone, message); + TShakeTrait.GetCurrentHash(clone, hash); + Assert.Equal(kat.Output, Convert.ToHexString(hash), ignoreCase: true); + } + } + } + + [ConditionalFact(nameof(IsSupported))] + public void KnownAnswerTests_Clone_Independent_Disposed() + { + foreach ((string Msg, string Output) kat in Fips202Kats) + { + byte[] message = Convert.FromHexString(kat.Msg); + byte[] hash = new byte[kat.Output.Length / 2]; + + TShake shake = new TShake(); + using (TShake clone = TShakeTrait.Clone(shake)) + { + shake.Dispose(); + + TShakeTrait.AppendData(clone, message); + TShakeTrait.GetCurrentHash(clone, hash); + Assert.Equal(kat.Output, Convert.ToHexString(hash), ignoreCase: true); + } + } + } + + [ConditionalFact(nameof(IsSupported))] + public void KnownAnswerTests_Reset() + { + foreach ((string Msg, string Output) kat in Fips202Kats) + { + byte[] message = Convert.FromHexString(kat.Msg); + byte[] hash = new byte[kat.Output.Length / 2]; + + using (TShake shake = new TShake()) + { + TShakeTrait.AppendData(shake, "badbadbad"u8); + TShakeTrait.Reset(shake); + TShakeTrait.AppendData(shake, message); + TShakeTrait.GetCurrentHash(shake, hash); + Assert.Equal(kat.Output, Convert.ToHexString(hash), ignoreCase: true); + } + } + } + [ConditionalFact(nameof(IsSupported))] public void KnownAnswerTests_OneShot_HashData_ByteArray() { @@ -513,6 +635,10 @@ public void ArgValidation_Allocated_UseAfterDispose() Assert.Throws(() => TShakeTrait.GetHashAndReset(shake, buffer.AsSpan())); Assert.Throws(() => TShakeTrait.GetCurrentHash(shake, outputLength: 1)); Assert.Throws(() => TShakeTrait.GetCurrentHash(shake, buffer.AsSpan())); + Assert.Throws(() => TShakeTrait.Clone(shake)); + Assert.Throws(() => TShakeTrait.Reset(shake)); + Assert.Throws(() => TShakeTrait.Read(shake, buffer.AsSpan())); + Assert.Throws(() => TShakeTrait.Read(shake, outputLength: 1)); } [ConditionalFact(nameof(IsNotSupported))] @@ -536,5 +662,157 @@ public void IsSupported_AgreesWithPlatform() { Assert.Equal(TShakeTrait.IsSupported, PlatformDetection.SupportsSha3); } + + [ConditionalFact(nameof(IsSupported))] + public void Clone_DifferentInstance() + { + using (TShake shake = new TShake()) + using (TShake clone = TShakeTrait.Clone(shake)) + { + Assert.NotSame(shake, clone); + } + } + + [ConditionalFact(nameof(IsReadSupported))] + public void Read_MixedAppendAfterRead() + { + using (TShake shake = new TShake()) + { + TShakeTrait.Read(shake, Span.Empty); + + Assert.Throws(() => TShakeTrait.AppendData(shake, ReadOnlySpan.Empty)); + Assert.Throws(() => TShakeTrait.AppendData(shake, Array.Empty())); + + TShakeTrait.Reset(shake); + + // Assert.NoThrow + TShakeTrait.AppendData(shake, ReadOnlySpan.Empty); + TShakeTrait.AppendData(shake, Array.Empty()); + } + } + + [ConditionalFact(nameof(IsReadSupported))] + public void Read_MixedCloneAfterRead() + { + using (TShake shake = new TShake()) + { + TShakeTrait.Read(shake, Span.Empty); + Assert.Throws(() => TShakeTrait.Clone(shake)); + + TShakeTrait.Reset(shake); + + using (TShake clone = TShakeTrait.Clone(shake)) + { + Assert.NotNull(clone); + } + } + } + + [ConditionalFact(nameof(IsReadSupported))] + public void Read_MixedGetHashAndReset() + { + using (TShake shake = new TShake()) + { + TShakeTrait.Read(shake, Span.Empty); + Assert.Throws(() => TShakeTrait.GetHashAndReset(shake, Span.Empty)); + Assert.Throws(() => TShakeTrait.GetHashAndReset(shake, outputLength: 0)); + + TShakeTrait.Reset(shake); + + // Assert.NoThrow + TShakeTrait.GetHashAndReset(shake, Span.Empty); + TShakeTrait.GetHashAndReset(shake, outputLength: 0); + } + } + + [ConditionalFact(nameof(IsReadSupported))] + public void Read_MixedGetCurrentHash() + { + using (TShake shake = new TShake()) + { + TShakeTrait.Read(shake, Span.Empty); + + // Cannot GetCurrentHash while reading. + Assert.Throws(() => TShakeTrait.GetCurrentHash(shake, Span.Empty)); + Assert.Throws(() => TShakeTrait.GetCurrentHash(shake, outputLength: 0)); + + TShakeTrait.Reset(shake); + + // Assert.NoThrow + TShakeTrait.GetCurrentHash(shake, Span.Empty); + TShakeTrait.GetCurrentHash(shake, outputLength: 0); + } + } + + [ConditionalFact(nameof(IsSupported))] + public void Read_NotSupported() + { + // This is testing when a TShake can be created, but the platform does not have Read. + if (IsReadSupported) + { + return; + } + + using (TShake shake = new TShake()) + { + Assert.Throws(() => TShakeTrait.Read(shake, Span.Empty)); + Assert.Throws(() => TShakeTrait.Read(shake, outputLength: 0)); + } + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void GetHashAndReset_ConcurrentUseDoesNotCrashProcess() + { + if (!IsSupported) + { + throw new SkipTestException("Algorithm is not supported on this platform."); + } + + RemoteExecutor.Invoke(static () => + { + using (TShake shake = TShakeTrait.Create()) + { + Thread thread1 = new(ThreadWork); + Thread thread2 = new(ThreadWork); + thread1.Start(shake); + thread2.Start(shake); + thread1.Join(); + thread2.Join(); + } + }).Dispose(); + + static void ThreadWork(object obj) + { + TShake shake = (TShake)obj; + + try + { + byte[] input = new byte[128]; + + for (int i = 0; i < 10_000; i++) + { + TShakeTrait.AppendData(shake, input); + TShakeTrait.GetHashAndReset(shake, 128); + } + } + catch + { + // Ignore all managed exceptions. HashAlgorithm is not thread safe, but we don't want process crashes. + } + } + } + + private static void ReadChunked(TShake shake, Span destination) + { + int read = 0; + int outputLength = destination.Length; + + while (read < outputLength) + { + int size = Math.Min(Math.Max(outputLength / 4, 1), outputLength - read); + TShakeTrait.Read(shake, destination.Slice(read, size)); + read += size; + } + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj b/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj index ae804e50f551..09ffc37aca35 100644 --- a/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj +++ b/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj @@ -6,9 +6,6 @@ $(NoWarn);SYSLIB0021;SYSLIB0026;SYSLIB0027;SYSLIB0028 true - - - $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs index e65a0445b09b..8c434619d72e 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs @@ -551,7 +551,7 @@ public static void InvalidSignatureAlgorithmEncoding(string caseName, string sig Exception exception = Assert.Throws( () => request.Create(request.SubjectName, generator, now, now.AddDays(1), new byte[1])); -#if NETCOREAPP +#if NET if (CultureInfo.CurrentCulture.Name == "en-US") { Assert.Contains("ASN1", exception.Message, StringComparison.OrdinalIgnoreCase); diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.cs index 0c8e37401856..fb286e393c98 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETCOREAPP +#if NET #define HAVE_STORE_ISOPEN #endif diff --git a/src/libraries/System.Security.Cryptography/tests/default.rd.xml b/src/libraries/System.Security.Cryptography/tests/default.rd.xml deleted file mode 100644 index 932f3c37ec64..000000000000 --- a/src/libraries/System.Security.Cryptography/tests/default.rd.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.Forwards.cs b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.Forwards.cs index 4d9a824761f5..c4f0228c0541 100644 --- a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.Forwards.cs +++ b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.Forwards.cs @@ -15,7 +15,7 @@ [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Permissions.SecurityPermissionFlag))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Policy.Evidence))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Policy.EvidenceBase))] -#if NETCOREAPP +#if NET [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.IStackWalk))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.PermissionSet))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Permissions.PermissionState))] diff --git a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.cs b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.cs index 512d130416ea..5d2fc5fabc8b 100644 --- a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.cs +++ b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.cs @@ -17,7 +17,7 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser } namespace System.Configuration { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class ConfigurationPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -31,7 +31,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.All, AllowMultiple=true, Inherited=false)] @@ -43,7 +43,7 @@ public ConfigurationPermissionAttribute(System.Security.Permissions.SecurityActi } namespace System.Data.Common { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public abstract partial class DBDataPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -65,7 +65,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -84,7 +84,7 @@ protected DBDataPermissionAttribute(System.Security.Permissions.SecurityAction a } namespace System.Data.Odbc { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class OdbcPermission : System.Data.Common.DBDataPermission @@ -95,7 +95,7 @@ public OdbcPermission(System.Security.Permissions.PermissionState state, bool al public override void Add(string connectionString, string restrictions, System.Data.KeyRestrictionBehavior behavior) { } public override System.Security.IPermission Copy() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -107,7 +107,7 @@ public OdbcPermissionAttribute(System.Security.Permissions.SecurityAction action } namespace System.Data.OleDb { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class OleDbPermission : System.Data.Common.DBDataPermission @@ -120,7 +120,7 @@ public OleDbPermission(System.Security.Permissions.PermissionState state, bool a public string Provider { get { throw null; } set { } } public override System.Security.IPermission Copy() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -135,7 +135,7 @@ public OleDbPermissionAttribute(System.Security.Permissions.SecurityAction actio } namespace System.Data.OracleClient { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class OraclePermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -151,7 +151,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -171,7 +171,7 @@ public OraclePermissionAttribute(System.Security.Permissions.SecurityAction acti } namespace System.Data.SqlClient { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class SqlClientPermission : System.Data.Common.DBDataPermission @@ -182,7 +182,7 @@ public SqlClientPermission(System.Security.Permissions.PermissionState state, bo public override void Add(string connectionString, string restrictions, System.Data.KeyRestrictionBehavior behavior) { } public override System.Security.IPermission Copy() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -194,7 +194,7 @@ public SqlClientPermissionAttribute(System.Security.Permissions.SecurityAction a } namespace System.Diagnostics { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class EventLogPermission : System.Security.Permissions.ResourcePermissionBase @@ -215,7 +215,7 @@ public enum EventLogPermissionAccess Write = 16, Administer = 48, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Event | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -249,7 +249,7 @@ protected override void OnRemove(int index, object value) { } protected override void OnSet(int index, object oldValue, object newValue) { } public void Remove(System.Diagnostics.EventLogPermissionEntry value) { } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class PerformanceCounterPermission : System.Security.Permissions.ResourcePermissionBase @@ -270,7 +270,7 @@ public enum PerformanceCounterPermissionAccess Instrument = 3, Administer = 7, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Event | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -360,7 +360,7 @@ public void Remove(System.DirectoryServices.DirectoryServicesPermissionEntry val } namespace System.Drawing.Printing { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class PrintingPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -376,7 +376,7 @@ public override void FromXml(System.Security.SecurityElement element) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.All, AllowMultiple=true)] @@ -396,7 +396,7 @@ public enum PrintingPermissionLevel } namespace System.Net { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class DnsPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -410,7 +410,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -434,7 +434,7 @@ public enum NetworkAccess Connect = 64, Accept = 128, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class SocketPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -453,7 +453,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -474,7 +474,7 @@ public enum TransportType Tcp = 2, All = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class WebPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -495,7 +495,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -517,7 +517,7 @@ public enum SmtpAccess Connect = 1, ConnectToUnrestrictedPort = 2, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class SmtpPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -535,7 +535,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -555,7 +555,7 @@ public enum NetworkInformationAccess Read = 1, Ping = 4, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class NetworkInformationPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -572,7 +572,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -585,7 +585,7 @@ public NetworkInformationPermissionAttribute(System.Security.Permissions.Securit } namespace System.Net.PeerToPeer { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class PnrpPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -599,7 +599,7 @@ public override void FromXml(System.Security.SecurityElement e) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -618,7 +618,7 @@ public enum PnrpScope } namespace System.Net.PeerToPeer.Collaboration { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class PeerCollaborationPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -632,7 +632,7 @@ public override void FromXml(System.Security.SecurityElement e) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -644,7 +644,7 @@ public PeerCollaborationPermissionAttribute(System.Security.Permissions.Security } namespace System.Security { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public abstract partial class CodeAccessPermission : System.Security.IPermission, System.Security.ISecurityEncodable, System.Security.IStackWalk @@ -670,7 +670,7 @@ public static void RevertPermitOnly() { } public abstract System.Security.SecurityElement ToXml(); public virtual System.Security.IPermission Union(System.Security.IPermission other) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public partial class HostProtectionException : System.SystemException @@ -723,7 +723,7 @@ public partial interface ISecurityPolicyEncodable void FromXml(System.Security.SecurityElement e, System.Security.Policy.PolicyLevel level); System.Security.SecurityElement ToXml(System.Security.Policy.PolicyLevel level); } -#if !NETCOREAPP +#if !NET public partial interface IStackWalk { void Assert(); @@ -732,7 +732,7 @@ public partial interface IStackWalk void PermitOnly(); } #endif -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class NamedPermissionSet : System.Security.PermissionSet @@ -750,7 +750,7 @@ public override void FromXml(System.Security.SecurityElement et) { } public override int GetHashCode() { throw null; } public override System.Security.SecurityElement ToXml() { throw null; } } -#if !NETCOREAPP +#if !NET public partial class PermissionSet : System.Collections.ICollection, System.Collections.IEnumerable, System.Runtime.Serialization.IDeserializationCallback, System.Security.ISecurityEncodable, System.Security.IStackWalk { public PermissionSet(System.Security.Permissions.PermissionState state) { } @@ -800,7 +800,7 @@ public enum PolicyLevelType Enterprise = 2, AppDomain = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class SecurityContext : System.IDisposable @@ -821,7 +821,7 @@ public enum SecurityContextSource CurrentAppDomain = 0, CurrentAssembly = 1, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public static partial class SecurityManager @@ -882,7 +882,7 @@ public XmlSyntaxException(string message, System.Exception inner) { } } namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class DataProtectionPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -898,7 +898,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -912,7 +912,7 @@ public DataProtectionPermissionAttribute(System.Security.Permissions.SecurityAct public bool UnprotectMemory { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -925,7 +925,7 @@ public enum DataProtectionPermissionFlags UnprotectMemory = 8, AllFlags = 15, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class EnvironmentPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -943,7 +943,7 @@ public void SetPathList(System.Security.Permissions.EnvironmentPermissionAccess public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission other) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -954,7 +954,7 @@ public enum EnvironmentPermissionAccess Write = 2, AllAccess = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -966,7 +966,7 @@ public EnvironmentPermissionAttribute(System.Security.Permissions.SecurityAction public string Write { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class FileDialogPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -982,7 +982,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -993,7 +993,7 @@ public enum FileDialogPermissionAccess Save = 2, OpenSave = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1004,7 +1004,7 @@ public FileDialogPermissionAttribute(System.Security.Permissions.SecurityAction public bool Save { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class FileIOPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1031,7 +1031,7 @@ public void SetPathList(System.Security.Permissions.FileIOPermissionAccess acces public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission other) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -1044,7 +1044,7 @@ public enum FileIOPermissionAccess PathDiscovery = 8, AllAccess = 15, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1064,7 +1064,7 @@ public FileIOPermissionAttribute(System.Security.Permissions.SecurityAction acti public string Write { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class GacIdentityPermission : System.Security.CodeAccessPermission @@ -1078,7 +1078,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1087,7 +1087,7 @@ public sealed partial class GacIdentityPermissionAttribute : System.Security.Per public GacIdentityPermissionAttribute(System.Security.Permissions.SecurityAction action) : base (default(System.Security.Permissions.SecurityAction)) { } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Delegate | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1107,7 +1107,7 @@ public HostProtectionAttribute(System.Security.Permissions.SecurityAction action public bool UI { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -1125,7 +1125,7 @@ public enum HostProtectionResource MayLeakOnAbort = 256, All = 511, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum IsolatedStorageContainment @@ -1143,7 +1143,7 @@ public enum IsolatedStorageContainment AdministerIsolatedStorageByUser = 112, UnrestrictedIsolatedStorage = 240, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class IsolatedStorageFilePermission : System.Security.Permissions.IsolatedStoragePermission @@ -1155,7 +1155,7 @@ public IsolatedStorageFilePermission(System.Security.Permissions.PermissionState public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1164,7 +1164,7 @@ public sealed partial class IsolatedStorageFilePermissionAttribute : System.Secu public IsolatedStorageFilePermissionAttribute(System.Security.Permissions.SecurityAction action) : base (default(System.Security.Permissions.SecurityAction)) { } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public abstract partial class IsolatedStoragePermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1176,7 +1176,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public bool IsUnrestricted() { throw null; } public override System.Security.SecurityElement ToXml() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public abstract partial class IsolatedStoragePermissionAttribute : System.Security.Permissions.CodeAccessSecurityAttribute @@ -1185,14 +1185,14 @@ protected IsolatedStoragePermissionAttribute(System.Security.Permissions.Securit public System.Security.Permissions.IsolatedStorageContainment UsageAllowed { get { throw null; } set { } } public long UserQuota { get { throw null; } set { } } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public partial interface IUnrestrictedPermission { bool IsUnrestricted(); } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class KeyContainerPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1210,7 +1210,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class KeyContainerPermissionAccessEntry @@ -1227,7 +1227,7 @@ public KeyContainerPermissionAccessEntry(string keyStore, string providerName, i public override bool Equals(object o) { throw null; } public override int GetHashCode() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class KeyContainerPermissionAccessEntryCollection : System.Collections.ICollection, System.Collections.IEnumerable @@ -1246,7 +1246,7 @@ public void CopyTo(System.Security.Permissions.KeyContainerPermissionAccessEntry public void Remove(System.Security.Permissions.KeyContainerPermissionAccessEntry accessEntry) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class KeyContainerPermissionAccessEntryEnumerator : System.Collections.IEnumerator @@ -1257,7 +1257,7 @@ public KeyContainerPermissionAccessEntryEnumerator() { } public bool MoveNext() { throw null; } public void Reset() { } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1272,7 +1272,7 @@ public KeyContainerPermissionAttribute(System.Security.Permissions.SecurityActio public int ProviderType { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum KeyContainerPermissionFlags @@ -1289,7 +1289,7 @@ public enum KeyContainerPermissionFlags ChangeAcl = 8192, AllFlags = 13111, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class MediaPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1311,7 +1311,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1323,7 +1323,7 @@ public MediaPermissionAttribute(System.Security.Permissions.SecurityAction actio public System.Security.Permissions.MediaPermissionVideo Video { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum MediaPermissionAudio @@ -1333,7 +1333,7 @@ public enum MediaPermissionAudio SafeAudio = 2, AllAudio = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum MediaPermissionImage @@ -1343,7 +1343,7 @@ public enum MediaPermissionImage SafeImage = 2, AllImage = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum MediaPermissionVideo @@ -1353,7 +1353,7 @@ public enum MediaPermissionVideo SafeVideo = 2, AllVideo = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1368,14 +1368,14 @@ public PermissionSetAttribute(System.Security.Permissions.SecurityAction action) public override System.Security.IPermission CreatePermission() { throw null; } public System.Security.PermissionSet CreatePermissionSet() { throw null; } } -#if !NETCOREAPP +#if !NET public enum PermissionState { None = 0, Unrestricted = 1, } #endif -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class PrincipalPermission : System.Security.IPermission, System.Security.ISecurityEncodable, System.Security.Permissions.IUnrestrictedPermission @@ -1395,13 +1395,13 @@ public void FromXml(System.Security.SecurityElement elem) { } public System.Security.SecurityElement ToXml() { throw null; } public System.Security.IPermission Union(System.Security.IPermission other) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Method, AllowMultiple=true, Inherited=false)] public sealed partial class PrincipalPermissionAttribute : System.Security.Permissions.CodeAccessSecurityAttribute { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("PrincipalPermissionAttribute is not honored by the runtime and must not be used.", true, DiagnosticId = "SYSLIB0002", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public PrincipalPermissionAttribute(System.Security.Permissions.SecurityAction action) : base (default(System.Security.Permissions.SecurityAction)) { } @@ -1410,7 +1410,7 @@ public PrincipalPermissionAttribute(System.Security.Permissions.SecurityAction a public string Role { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class PublisherIdentityPermission : System.Security.CodeAccessPermission @@ -1425,7 +1425,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1437,7 +1437,7 @@ public PublisherIdentityPermissionAttribute(System.Security.Permissions.Security public string X509Certificate { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class ReflectionPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1453,7 +1453,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission other) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1469,7 +1469,7 @@ public ReflectionPermissionAttribute(System.Security.Permissions.SecurityAction public bool TypeInformation { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -1485,7 +1485,7 @@ public enum ReflectionPermissionFlag AllFlags = 7, RestrictedMemberAccess = 8, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class RegistryPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1505,7 +1505,7 @@ public void SetPathList(System.Security.Permissions.RegistryPermissionAccess acc public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission other) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -1517,7 +1517,7 @@ public enum RegistryPermissionAccess Create = 4, AllAccess = 7, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1534,7 +1534,7 @@ public RegistryPermissionAttribute(System.Security.Permissions.SecurityAction ac public string Write { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public abstract partial class ResourcePermissionBase : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1557,7 +1557,7 @@ protected void RemovePermissionAccess(System.Security.Permissions.ResourcePermis public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public partial class ResourcePermissionBaseEntry @@ -1567,7 +1567,7 @@ public ResourcePermissionBaseEntry(int permissionAccess, string[] permissionAcce public int PermissionAccess { get { throw null; } } public string[] PermissionAccessPath { get { throw null; } } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class SecurityPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1583,7 +1583,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class SiteIdentityPermission : System.Security.CodeAccessPermission @@ -1598,7 +1598,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1608,7 +1608,7 @@ public SiteIdentityPermissionAttribute(System.Security.Permissions.SecurityActio public string Site { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class StorePermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1624,7 +1624,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1641,7 +1641,7 @@ public StorePermissionAttribute(System.Security.Permissions.SecurityAction actio public bool RemoveFromStore { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -1657,7 +1657,7 @@ public enum StorePermissionFlags EnumerateCertificates = 128, AllFlags = 247, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class StrongNameIdentityPermission : System.Security.CodeAccessPermission @@ -1674,7 +1674,7 @@ public override void FromXml(System.Security.SecurityElement e) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1686,7 +1686,7 @@ public StrongNameIdentityPermissionAttribute(System.Security.Permissions.Securit public string Version { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class StrongNamePublicKeyBlob @@ -1696,7 +1696,7 @@ public StrongNamePublicKeyBlob(byte[] publicKey) { } public override int GetHashCode() { throw null; } public override string ToString() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class TypeDescriptorPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1712,7 +1712,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1723,7 +1723,7 @@ public TypeDescriptorPermissionAttribute(System.Security.Permissions.SecurityAct public bool RestrictedRegistrationAccess { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.FlagsAttribute] @@ -1732,7 +1732,7 @@ public enum TypeDescriptorPermissionFlags NoFlags = 0, RestrictedRegistrationAccess = 1, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class UIPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1751,7 +1751,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1762,7 +1762,7 @@ public UIPermissionAttribute(System.Security.Permissions.SecurityAction action) public System.Security.Permissions.UIPermissionWindow Window { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum UIPermissionClipboard @@ -1771,7 +1771,7 @@ public enum UIPermissionClipboard OwnClipboard = 1, AllClipboard = 2, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum UIPermissionWindow @@ -1781,7 +1781,7 @@ public enum UIPermissionWindow SafeTopLevelWindows = 2, AllWindows = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class UrlIdentityPermission : System.Security.CodeAccessPermission @@ -1796,7 +1796,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1806,7 +1806,7 @@ public UrlIdentityPermissionAttribute(System.Security.Permissions.SecurityAction public string Url { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class WebBrowserPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -1823,7 +1823,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1833,7 +1833,7 @@ public WebBrowserPermissionAttribute(System.Security.Permissions.SecurityAction public System.Security.Permissions.WebBrowserPermissionLevel Level { get { throw null; } set { } } public override System.Security.IPermission CreatePermission() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public enum WebBrowserPermissionLevel @@ -1842,7 +1842,7 @@ public enum WebBrowserPermissionLevel Safe = 1, Unrestricted = 2, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class ZoneIdentityPermission : System.Security.CodeAccessPermission @@ -1857,7 +1857,7 @@ public override void FromXml(System.Security.SecurityElement esd) { } public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple=true, Inherited=false)] @@ -1909,14 +1909,14 @@ public sealed partial class ApplicationTrust : System.Security.Policy.EvidenceBa { public ApplicationTrust() { } public ApplicationTrust(System.ApplicationIdentity identity) { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public ApplicationTrust(System.Security.PermissionSet defaultGrantSet, System.Collections.Generic.IEnumerable fullTrustAssemblies) { } public System.ApplicationIdentity ApplicationIdentity { get { throw null; } set { } } public System.Security.Policy.PolicyStatement DefaultGrantSet { get { throw null; } set { } } public object ExtraInfo { get { throw null; } set { } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public System.Collections.Generic.IList FullTrustAssemblies { get { throw null; } } @@ -2000,7 +2000,7 @@ public void RemoveChild(System.Security.Policy.CodeGroup group) { } public System.Security.SecurityElement ToXml() { throw null; } public System.Security.SecurityElement ToXml(System.Security.Policy.PolicyLevel level) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class FileCodeGroup : System.Security.Policy.CodeGroup @@ -2026,7 +2026,7 @@ public sealed partial class FirstMatchCodeGroup : System.Security.Policy.CodeGro public override System.Security.Policy.PolicyStatement Resolve(System.Security.Policy.Evidence evidence) { throw null; } public override System.Security.Policy.CodeGroup ResolveMatchingCodeGroups(System.Security.Policy.Evidence evidence) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class GacInstalled : System.Security.Policy.EvidenceBase, System.Security.Policy.IIdentityPermissionFactory @@ -2085,7 +2085,7 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser public System.Security.SecurityElement ToXml() { throw null; } public System.Security.SecurityElement ToXml(System.Security.Policy.PolicyLevel level) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public partial interface IIdentityPermissionFactory @@ -2153,18 +2153,18 @@ internal PolicyLevel() { } public void AddFullTrustAssembly(System.Security.Policy.StrongName sn) { } [Obsolete("Because all GAC assemblies always get full trust, the full trust list is no longer meaningful. You should install any assemblies that are used in security policy in the GAC to ensure they are trusted.")] public void AddFullTrustAssembly(System.Security.Policy.StrongNameMembershipCondition snMC) { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public void AddNamedPermissionSet(System.Security.NamedPermissionSet permSet) { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public System.Security.NamedPermissionSet ChangeNamedPermissionSet(string name, System.Security.PermissionSet pSet) { throw null; } [System.ObsoleteAttribute("AppDomain policy levels are obsolete. See https://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public static System.Security.Policy.PolicyLevel CreateAppDomainLevel() { throw null; } public void FromXml(System.Security.SecurityElement e) { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public System.Security.NamedPermissionSet GetNamedPermissionSet(string name) { throw null; } @@ -2173,11 +2173,11 @@ public void Recover() { } public void RemoveFullTrustAssembly(System.Security.Policy.StrongName sn) { } [Obsolete("Because all GAC assemblies always get full trust, the full trust list is no longer meaningful. You should install any assemblies that are used in security policy in the GAC to ensure they are trusted.")] public void RemoveFullTrustAssembly(System.Security.Policy.StrongNameMembershipCondition snMC) { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public System.Security.NamedPermissionSet RemoveNamedPermissionSet(System.Security.NamedPermissionSet permSet) { throw null; } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public System.Security.NamedPermissionSet RemoveNamedPermissionSet(string name) { throw null; } @@ -2188,17 +2188,17 @@ public void Reset() { } } public sealed partial class PolicyStatement : System.Security.ISecurityEncodable, System.Security.ISecurityPolicyEncodable { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public PolicyStatement(System.Security.PermissionSet permSet) { } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public PolicyStatement(System.Security.PermissionSet permSet, System.Security.Policy.PolicyStatementAttribute attributes) { } public System.Security.Policy.PolicyStatementAttribute Attributes { get { throw null; } set { } } public string AttributeString { get { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public System.Security.PermissionSet PermissionSet { get { throw null; } set { } } @@ -2218,7 +2218,7 @@ public enum PolicyStatementAttribute LevelFinal = 2, All = 3, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class Publisher : System.Security.Policy.EvidenceBase, System.Security.Policy.IIdentityPermissionFactory @@ -2245,7 +2245,7 @@ public void FromXml(System.Security.SecurityElement e, System.Security.Policy.Po public System.Security.SecurityElement ToXml() { throw null; } public System.Security.SecurityElement ToXml(System.Security.Policy.PolicyLevel level) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class Site : System.Security.Policy.EvidenceBase, System.Security.Policy.IIdentityPermissionFactory @@ -2273,7 +2273,7 @@ public void FromXml(System.Security.SecurityElement e, System.Security.Policy.Po public System.Security.SecurityElement ToXml() { throw null; } public System.Security.SecurityElement ToXml(System.Security.Policy.PolicyLevel level) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class StrongName : System.Security.Policy.EvidenceBase, System.Security.Policy.IIdentityPermissionFactory @@ -2288,7 +2288,7 @@ public StrongName(System.Security.Permissions.StrongNamePublicKeyBlob blob, stri public override int GetHashCode() { throw null; } public override string ToString() { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class StrongNameMembershipCondition : System.Security.ISecurityEncodable, System.Security.ISecurityPolicyEncodable, System.Security.Policy.IMembershipCondition @@ -2333,7 +2333,7 @@ public sealed partial class UnionCodeGroup : System.Security.Policy.CodeGroup public override System.Security.Policy.PolicyStatement Resolve(System.Security.Policy.Evidence evidence) { throw null; } public override System.Security.Policy.CodeGroup ResolveMatchingCodeGroups(System.Security.Policy.Evidence evidence) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class Url : System.Security.Policy.EvidenceBase, System.Security.Policy.IIdentityPermissionFactory @@ -2360,7 +2360,7 @@ public void FromXml(System.Security.SecurityElement e, System.Security.Policy.Po public System.Security.SecurityElement ToXml() { throw null; } public System.Security.SecurityElement ToXml(System.Security.Policy.PolicyLevel level) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class Zone : System.Security.Policy.EvidenceBase, System.Security.Policy.IIdentityPermissionFactory @@ -2391,7 +2391,7 @@ public void FromXml(System.Security.SecurityElement e, System.Security.Policy.Po } namespace System.ServiceProcess { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class ServiceControllerPermission : System.Security.Permissions.ResourcePermissionBase @@ -2409,7 +2409,7 @@ public enum ServiceControllerPermissionAccess Browse = 2, Control = 6, } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Event | System.AttributeTargets.Method | System.AttributeTargets.Struct, AllowMultiple = true, Inherited = false)] @@ -2449,7 +2449,7 @@ public void Remove(System.ServiceProcess.ServiceControllerPermissionEntry value) } namespace System.Transactions { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class DistributedTransactionPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -2463,7 +2463,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.All, AllowMultiple=true)] @@ -2476,7 +2476,7 @@ public DistributedTransactionPermissionAttribute(System.Security.Permissions.Sec } namespace System.Web { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class AspNetHostingPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission @@ -2492,7 +2492,7 @@ public override void FromXml(System.Security.SecurityElement securityElement) { public override System.Security.SecurityElement ToXml() { throw null; } public override System.Security.IPermission Union(System.Security.IPermission target) { throw null; } } -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif [System.AttributeUsageAttribute(System.AttributeTargets.All, AllowMultiple=true, Inherited=false)] diff --git a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.netcoreapp.cs b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.netcoreapp.cs index bd7e4dd59a6c..f3e0de569038 100644 --- a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.netcoreapp.cs +++ b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.netcoreapp.cs @@ -6,7 +6,7 @@ namespace System.Xaml.Permissions { -#if NETCOREAPP +#if NET [System.ObsoleteAttribute("Code Access Security is not supported or honored by the runtime.", DiagnosticId = "SYSLIB0003", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public sealed partial class XamlLoadPermission : System.Security.CodeAccessPermission, System.Security.Permissions.IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermission.cs b/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermission.cs index 3adc471ddc89..47967148e4b6 100644 --- a/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermission.cs @@ -6,7 +6,7 @@ namespace System.Configuration { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class ConfigurationPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermissionAttribute.cs index 8366e422d917..43a98812096e 100644 --- a/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Configuration/ConfigurationPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Configuration { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermission.cs b/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermission.cs index 93b727f99073..3982f48df334 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermission.cs @@ -6,7 +6,7 @@ namespace System.Data.Common { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public abstract class DBDataPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermissionAttribute.cs index 9968cb6d565a..ac1e409a951d 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/Common/DBDataPermissionAttribute.cs @@ -5,7 +5,7 @@ namespace System.Data.Common { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method, diff --git a/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermission.cs b/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermission.cs index 6504d49d8881..2dca7ee412de 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermission.cs @@ -7,7 +7,7 @@ namespace System.Data.Odbc { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class OdbcPermission : DBDataPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermissionAttribute.cs index c6286aa49ba7..e0bd5ec1abf8 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/Odbc/OdbcPermissionAttribute.cs @@ -7,7 +7,7 @@ namespace System.Data.Odbc { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | diff --git a/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermission.cs b/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermission.cs index d71f863adcf3..7b162ca30c26 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermission.cs @@ -7,7 +7,7 @@ namespace System.Data.OleDb { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class OleDbPermission : DBDataPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermissionAttribute.cs index c4e0aca2d7a2..c5e90d994417 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/OleDb/OleDbPermissionAttribute.cs @@ -7,7 +7,7 @@ namespace System.Data.OleDb { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | diff --git a/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermission.cs b/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermission.cs index a0389c9a0be1..3517fd1cb4ee 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermission.cs @@ -6,7 +6,7 @@ namespace System.Data.OracleClient { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class OraclePermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermissionAttribute.cs index 639d38aa48e9..bc7175def787 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/OracleClient/OraclePermissionAttribute.cs @@ -5,7 +5,7 @@ namespace System.Data.OracleClient { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | diff --git a/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermission.cs b/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermission.cs index e3cc4ced62e7..1cd20d3ead17 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermission.cs @@ -6,7 +6,7 @@ namespace System.Data.SqlClient { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class SqlClientPermission : DBDataPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermissionAttribute.cs index 0979d37e899f..fffc013004f7 100644 --- a/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Data/SqlClient/SqlClientPermissionAttribute.cs @@ -7,7 +7,7 @@ namespace System.Data.SqlClient { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method, diff --git a/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermission.cs b/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermission.cs index e1e64c3c12be..206e729cbb09 100644 --- a/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermission.cs @@ -5,7 +5,7 @@ namespace System.Diagnostics { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class EventLogPermission : ResourcePermissionBase diff --git a/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermissionAttribute.cs index e296e032d6ba..a0406ccde6a2 100644 --- a/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Diagnostics/EventLogPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Diagnostics { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct diff --git a/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermission.cs b/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermission.cs index 49cee1607c33..d3b0c2b6e155 100644 --- a/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermission.cs @@ -5,7 +5,7 @@ namespace System.Diagnostics { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class PerformanceCounterPermission : ResourcePermissionBase diff --git a/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermissionAttribute.cs index 804e21d7d809..0f7322763e10 100644 --- a/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Diagnostics/PerformanceCounterPermissionAttribute.cs @@ -5,7 +5,7 @@ using System.Security.Permissions; namespace System.Diagnostics { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Event, diff --git a/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermission.cs b/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermission.cs index e429ac0b3259..9981ec0a12d5 100644 --- a/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermission.cs @@ -6,7 +6,7 @@ namespace System.Drawing.Printing { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class PrintingPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermissionAttribute.cs index 654f04f6ede1..71c3d6e46d65 100644 --- a/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Drawing/Printing/PrintingPermissionAttribute.cs @@ -5,7 +5,7 @@ namespace System.Drawing.Printing { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] diff --git a/src/libraries/System.Security.Permissions/src/System/Net/DnsPermission.cs b/src/libraries/System.Security.Permissions/src/System/Net/DnsPermission.cs index 86817bf064ea..4bc042aa3c42 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/DnsPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/DnsPermission.cs @@ -6,7 +6,7 @@ namespace System.Net { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class DnsPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Net/DnsPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Net/DnsPermissionAttribute.cs index ab40a425fcaa..61f45a9f646d 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/DnsPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/DnsPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Net { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | diff --git a/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermission.cs b/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermission.cs index d9c5c6edba6a..4284d30ea6b8 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermission.cs @@ -6,7 +6,7 @@ namespace System.Net.Mail { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class SmtpPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermissionAttribute.cs index 8d8a3379277e..3a91cbdffafb 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/Mail/SmtpPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Net.Mail { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | diff --git a/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermission.cs b/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermission.cs index 40a7e39426ac..1acf38c0fd91 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermission.cs @@ -6,7 +6,7 @@ namespace System.Net.NetworkInformation { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class NetworkInformationPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermissionAttribute.cs index d25b0cf35e4e..befe4af33830 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/NetworkInformation/NetworkInformationPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Net.NetworkInformation { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermission.cs b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermission.cs index 25627f89a6bd..c09cceea2a47 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermission.cs @@ -6,7 +6,7 @@ namespace System.Net.PeerToPeer.Collaboration { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class PeerCollaborationPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermissionAttribute.cs index 8e171c3cd5c7..5fb68c79dcf6 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/Collaboration/PeerCollaborationPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Net.PeerToPeer.Collaboration { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | diff --git a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermission.cs b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermission.cs index c7b3ccbdf778..bac836ed20b7 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermission.cs @@ -6,7 +6,7 @@ namespace System.Net.PeerToPeer { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class PnrpPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermissionAttribute.cs index b9df6e845e49..88b06a69b287 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/PeerToPeer/PnrpPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Net.PeerToPeer { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | diff --git a/src/libraries/System.Security.Permissions/src/System/Net/SocketPermission.cs b/src/libraries/System.Security.Permissions/src/System/Net/SocketPermission.cs index 88e835058e78..1e51df16e960 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/SocketPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/SocketPermission.cs @@ -6,7 +6,7 @@ namespace System.Net { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class SocketPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Net/SocketPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Net/SocketPermissionAttribute.cs index 88147043b921..cf4611a39e6e 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/SocketPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/SocketPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Net { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | diff --git a/src/libraries/System.Security.Permissions/src/System/Net/WebPermission.cs b/src/libraries/System.Security.Permissions/src/System/Net/WebPermission.cs index e61b27b590f2..e7fe49c24dd7 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/WebPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/WebPermission.cs @@ -8,7 +8,7 @@ namespace System.Net { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class WebPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Net/WebPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Net/WebPermissionAttribute.cs index 7113110a896b..82f30ea9df72 100644 --- a/src/libraries/System.Security.Permissions/src/System/Net/WebPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Net/WebPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Net { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | diff --git a/src/libraries/System.Security.Permissions/src/System/Security/CodeAccessPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/CodeAccessPermission.cs index 4ecc14aca2bf..9ca3f51ce606 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/CodeAccessPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/CodeAccessPermission.cs @@ -3,7 +3,7 @@ namespace System.Security { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public abstract partial class CodeAccessPermission : IPermission, ISecurityEncodable, IStackWalk diff --git a/src/libraries/System.Security.Permissions/src/System/Security/HostProtectionException.cs b/src/libraries/System.Security.Permissions/src/System/Security/HostProtectionException.cs index b93a00a2a8e5..455e045198c4 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/HostProtectionException.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/HostProtectionException.cs @@ -8,7 +8,7 @@ namespace System.Security { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Serializable] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/NamedPermissionSet.cs b/src/libraries/System.Security.Permissions/src/System/Security/NamedPermissionSet.cs index 26bfa5dae85d..b437033366e0 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/NamedPermissionSet.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/NamedPermissionSet.cs @@ -5,7 +5,7 @@ namespace System.Security { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class NamedPermissionSet : PermissionSet diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermission.cs index 2af3cafe200e..f7c18edfea5e 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class DataProtectionPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionAttribute.cs index 5c6d99af3565..b3cf765ca13e 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionFlags.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionFlags.cs index 44a442408e8f..80c1dd19d180 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionFlags.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/DataProtectionPermissionFlags.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermission.cs index 5c26c1494754..76f0c82c8029 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class EnvironmentPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAccess.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAccess.cs index b5dee502e691..0a7f56c80fff 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAccess.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAccess.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAttribute.cs index d68a1e4842fb..b69d26db2be9 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/EnvironmentPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermission.cs index 6774ece3a080..952148edcb99 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class FileDialogPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAccess.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAccess.cs index 80dfc8f43e16..8d2eb8a87bd0 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAccess.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAccess.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAttribute.cs index a6dc55eb78b6..9f4c8b6fc8eb 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileDialogPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermission.cs index 7df64c4145df..99e507ecd7c5 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class FileIOPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAccess.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAccess.cs index e3fb61c97b23..029e63b1a093 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAccess.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAccess.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAttribute.cs index 1780e55dde85..702cc1fae179 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/FileIOPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermission.cs index a0d0abc573fd..39604e13f555 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class GacIdentityPermission : CodeAccessPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermissionAttribute.cs index bdeee8607fd1..928f72a5b51f 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/GacIdentityPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionAttribute.cs index 56f6d8a24bbe..ecf10307271e 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(4205), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionResource.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionResource.cs index d1db88246d00..81e284a65647 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionResource.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/HostProtectionResource.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IUnrestrictedPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IUnrestrictedPermission.cs index a4c95a4a13fd..04e5fa166a59 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IUnrestrictedPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IUnrestrictedPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public partial interface IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageContainment.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageContainment.cs index 1563eba6e790..4292c351f4f5 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageContainment.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageContainment.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum IsolatedStorageContainment diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermission.cs index fafbdca772d7..4e3535109fbc 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class IsolatedStorageFilePermission : IsolatedStoragePermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermissionAttribute.cs index e7d95b864091..8789e27a496d 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStorageFilePermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermission.cs index d0d08571e6a8..c33e6fcae177 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public abstract class IsolatedStoragePermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermissionAttribute.cs index 30189ad07816..77bdd246411b 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/IsolatedStoragePermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public abstract class IsolatedStoragePermissionAttribute : CodeAccessSecurityAttribute diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermission.cs index 0f6a49016005..5567368fc678 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class KeyContainerPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntry.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntry.cs index 771c23abb4db..038ab40f6d93 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntry.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntry.cs @@ -5,7 +5,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class KeyContainerPermissionAccessEntry diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryCollection.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryCollection.cs index 4dd5f15a0d09..f4312632fb71 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryCollection.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryCollection.cs @@ -5,7 +5,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class KeyContainerPermissionAccessEntryCollection : ICollection diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryEnumerator.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryEnumerator.cs index 86ed27dd250c..e8af76d42405 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryEnumerator.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAccessEntryEnumerator.cs @@ -5,7 +5,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class KeyContainerPermissionAccessEntryEnumerator : IEnumerator diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAttribute.cs index 7211ff86ccba..239772f6912b 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionFlags.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionFlags.cs index 50004c265344..0a4ece5eb35d 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionFlags.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/KeyContainerPermissionFlags.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum KeyContainerPermissionFlags diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/MediaPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/MediaPermission.cs index 26d3b914f868..543f37aa1167 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/MediaPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/MediaPermission.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum MediaPermissionAudio @@ -13,7 +13,7 @@ public enum MediaPermissionAudio AllAudio } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum MediaPermissionVideo @@ -24,7 +24,7 @@ public enum MediaPermissionVideo AllVideo, } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum MediaPermissionImage @@ -35,7 +35,7 @@ public enum MediaPermissionImage AllImage, } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class MediaPermission : CodeAccessPermission, IUnrestrictedPermission @@ -61,7 +61,7 @@ public override void FromXml(SecurityElement securityElement) { } public MediaPermissionImage Image { get { return MediaPermissionImage.AllImage; } } } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PermissionSetAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PermissionSetAttribute.cs index c36c4cbc73bd..6bfe07a081b8 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PermissionSetAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PermissionSetAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermission.cs index 060fd7b4f067..aebdfcfbe661 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermission.cs @@ -8,7 +8,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class PrincipalPermission : IPermission, ISecurityEncodable, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermissionAttribute.cs index b8a3ff91e7b4..14a620670ec8 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PrincipalPermissionAttribute.cs @@ -3,13 +3,13 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(68), AllowMultiple = true, Inherited = false)] public sealed partial class PrincipalPermissionAttribute : CodeAccessSecurityAttribute { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.PrincipalPermissionAttributeMessage, error: true, DiagnosticId = Obsoletions.PrincipalPermissionAttributeDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public PrincipalPermissionAttribute(SecurityAction action) : base(default(SecurityAction)) { } diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermission.cs index b0faace69f7e..1c326f704581 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermission.cs @@ -5,7 +5,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class PublisherIdentityPermission : CodeAccessPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermissionAttribute.cs index d8ce7f50636b..567d880bfdc8 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/PublisherIdentityPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermission.cs index d6577df82424..153550aa2a74 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class ReflectionPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionAttribute.cs index aeec90580dcc..f6762fe4944b 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionFlag.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionFlag.cs index 1c9e39eb6b3d..14d809eee162 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionFlag.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ReflectionPermissionFlag.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermission.cs index 04fa83df8084..03cefc8f6ae0 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermission.cs @@ -5,7 +5,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class RegistryPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAccess.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAccess.cs index b2f0384acdc1..2f50d5d5fecd 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAccess.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAccess.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAttribute.cs index da29af354dc3..9c4495a8ea3b 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/RegistryPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBase.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBase.cs index 597647caf26d..4297b80a4955 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBase.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBase.cs @@ -5,7 +5,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public abstract class ResourcePermissionBase : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBaseEntry.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBaseEntry.cs index 77c012439029..ade10e2674c7 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBaseEntry.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ResourcePermissionBaseEntry.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public class ResourcePermissionBaseEntry diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SecurityPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SecurityPermission.cs index a1aa39a9764f..5df48d3d440f 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SecurityPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SecurityPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class SecurityPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermission.cs index 160a9301aed3..d1296b7bd7e4 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class SiteIdentityPermission : CodeAccessPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermissionAttribute.cs index 9110f6b74f74..da1eacf54f76 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/SiteIdentityPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermission.cs index 691439b51dd5..07a2ea11dbe4 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class StorePermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionAttribute.cs index c3c50ebf60af..8614491c3d21 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionFlags.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionFlags.cs index 283e66a697f7..13b271e49dc8 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionFlags.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StorePermissionFlags.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermission.cs index 1d66fa2f7e48..2fd19c8447fd 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class StrongNameIdentityPermission : CodeAccessPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermissionAttribute.cs index 07b3014ec9a7..7863adc97853 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNameIdentityPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs index 44b39f9c8ad9..513e5e04b21c 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class StrongNamePublicKeyBlob diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermission.cs index d1e18e0a8106..8ba9f50cdb8a 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class TypeDescriptorPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionAttribute.cs index 767a40af5103..708244fba8b5 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionFlags.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionFlags.cs index b8c76becc953..ad40546c57ce 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionFlags.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/TypeDescriptorPermissionFlags.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [Flags] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermission.cs index a325753b6113..95e3fadeea8b 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class UIPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionAttribute.cs index f5569f8af056..8de208042740 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionClipboard.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionClipboard.cs index cbe563a8ecff..7739ac11bd19 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionClipboard.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionClipboard.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum UIPermissionClipboard diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionWindow.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionWindow.cs index c87c0b8dfdf6..766027238938 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionWindow.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UIPermissionWindow.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum UIPermissionWindow diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermission.cs index 1ddc1172e273..7a74ef52fcd1 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class UrlIdentityPermission : CodeAccessPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermissionAttribute.cs index 49ce74de84e4..cda8134abe7f 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/UrlIdentityPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/WebBrowserPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/WebBrowserPermission.cs index 3f0670d9fa27..c4ac4a3fb126 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/WebBrowserPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/WebBrowserPermission.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public enum WebBrowserPermissionLevel @@ -12,7 +12,7 @@ public enum WebBrowserPermissionLevel Unrestricted } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class WebBrowserPermission : CodeAccessPermission, IUnrestrictedPermission @@ -30,7 +30,7 @@ public override void FromXml(SecurityElement securityElement) { } public WebBrowserPermissionLevel Level { get { return WebBrowserPermissionLevel.Unrestricted; } set { } } } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermission.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermission.cs index 61e1945c22ef..0caf076e6e58 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermission.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class ZoneIdentityPermission : CodeAccessPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermissionAttribute.cs index 0f66c4bd4317..2833529125c5 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Permissions/ZoneIdentityPermissionAttribute.cs @@ -3,7 +3,7 @@ namespace System.Security.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage((AttributeTargets)(109), AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/ApplicationTrust.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/ApplicationTrust.cs index b17afed7b99d..6646fe297938 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/ApplicationTrust.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/ApplicationTrust.cs @@ -9,14 +9,14 @@ public sealed partial class ApplicationTrust : EvidenceBase, ISecurityEncodable { public ApplicationTrust() { } public ApplicationTrust(ApplicationIdentity identity) { } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public ApplicationTrust(PermissionSet defaultGrantSet, IEnumerable fullTrustAssemblies) { } public ApplicationIdentity ApplicationIdentity { get; set; } public PolicyStatement DefaultGrantSet { get; set; } public object ExtraInfo { get; set; } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public IList FullTrustAssemblies { get { return default(IList); } } diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/FileCodeGroup.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/FileCodeGroup.cs index 599d70f03c43..4e73e5d26f9b 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/FileCodeGroup.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/FileCodeGroup.cs @@ -3,7 +3,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class FileCodeGroup : CodeGroup diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/GacInstalled.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/GacInstalled.cs index f6565fbf7916..ddee079fb88d 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/GacInstalled.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/GacInstalled.cs @@ -3,7 +3,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class GacInstalled : EvidenceBase, IIdentityPermissionFactory diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/IIdentityPermissionFactory.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/IIdentityPermissionFactory.cs index f519bf2c06c2..b310bdb61d5a 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/IIdentityPermissionFactory.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/IIdentityPermissionFactory.cs @@ -3,7 +3,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public partial interface IIdentityPermissionFactory diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyLevel.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyLevel.cs index 74afa9599191..06c65039eee7 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyLevel.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyLevel.cs @@ -18,18 +18,18 @@ internal PolicyLevel() { } public void AddFullTrustAssembly(StrongName sn) { } [Obsolete("Because all GAC assemblies always get full trust, the full trust list is no longer meaningful. You should install any assemblies that are used in security policy in the GAC to ensure they are trusted.")] public void AddFullTrustAssembly(StrongNameMembershipCondition snMC) { } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public void AddNamedPermissionSet(NamedPermissionSet permSet) { } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public NamedPermissionSet ChangeNamedPermissionSet(string name, PermissionSet pSet) { return default(NamedPermissionSet); } [Obsolete("AppDomain policy levels are obsolete. See https://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public static PolicyLevel CreateAppDomainLevel() { return default(PolicyLevel); } public void FromXml(SecurityElement e) { } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public NamedPermissionSet GetNamedPermissionSet(string name) { return default(NamedPermissionSet); } @@ -38,11 +38,11 @@ public void Recover() { } public void RemoveFullTrustAssembly(StrongName sn) { } [Obsolete("Because all GAC assemblies always get full trust, the full trust list is no longer meaningful. You should install any assemblies that are used in security policy in the GAC to ensure they are trusted.")] public void RemoveFullTrustAssembly(StrongNameMembershipCondition snMC) { } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public NamedPermissionSet RemoveNamedPermissionSet(NamedPermissionSet permSet) { return default(NamedPermissionSet); } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public NamedPermissionSet RemoveNamedPermissionSet(string name) { return default(NamedPermissionSet); } diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyStatement.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyStatement.cs index d94b4ebaec30..7ded9666afeb 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyStatement.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/PolicyStatement.cs @@ -5,17 +5,17 @@ namespace System.Security.Policy { public sealed partial class PolicyStatement : ISecurityEncodable, ISecurityPolicyEncodable { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public PolicyStatement(PermissionSet permSet) { } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public PolicyStatement(PermissionSet permSet, PolicyStatementAttribute attributes) { } public PolicyStatementAttribute Attributes { get; set; } public string AttributeString { get { return null; } } -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public PermissionSet PermissionSet { get; set; } diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Publisher.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Publisher.cs index 82d4a4c014ac..ada8aecc2c14 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Publisher.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Publisher.cs @@ -5,7 +5,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class Publisher : EvidenceBase, IIdentityPermissionFactory diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Site.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Site.cs index e257cb4d44f1..885d0cdf5a37 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Site.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Site.cs @@ -3,7 +3,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class Site : EvidenceBase, IIdentityPermissionFactory diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongName.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongName.cs index 7f9521026ed3..6ef2b7de49a8 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongName.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongName.cs @@ -5,7 +5,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class StrongName : EvidenceBase, IIdentityPermissionFactory diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongNameMembershipCondition.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongNameMembershipCondition.cs index e7fa15937002..a4fcaaa3ac2a 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongNameMembershipCondition.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/StrongNameMembershipCondition.cs @@ -5,7 +5,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class StrongNameMembershipCondition : ISecurityEncodable, ISecurityPolicyEncodable, IMembershipCondition diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Url.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Url.cs index a108d3691fb5..c83c904c5056 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Url.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Url.cs @@ -3,7 +3,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class Url : EvidenceBase, IIdentityPermissionFactory diff --git a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Zone.cs b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Zone.cs index 2e08fd3e3a0f..e494f429238c 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/Policy/Zone.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/Policy/Zone.cs @@ -3,7 +3,7 @@ namespace System.Security.Policy { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class Zone : EvidenceBase, IIdentityPermissionFactory diff --git a/src/libraries/System.Security.Permissions/src/System/Security/SecurityContext.cs b/src/libraries/System.Security.Permissions/src/System/Security/SecurityContext.cs index 1ee1b1d5e60a..8d8756a54fb1 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/SecurityContext.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/SecurityContext.cs @@ -5,7 +5,7 @@ namespace System.Security { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed partial class SecurityContext : System.IDisposable diff --git a/src/libraries/System.Security.Permissions/src/System/Security/SecurityManager.cs b/src/libraries/System.Security.Permissions/src/System/Security/SecurityManager.cs index 0ff033c383be..9f02c6f39514 100644 --- a/src/libraries/System.Security.Permissions/src/System/Security/SecurityManager.cs +++ b/src/libraries/System.Security.Permissions/src/System/Security/SecurityManager.cs @@ -6,7 +6,7 @@ namespace System.Security { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public static partial class SecurityManager diff --git a/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermission.cs b/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermission.cs index c049d1e67046..af27008cee09 100644 --- a/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermission.cs @@ -5,7 +5,7 @@ namespace System.ServiceProcess { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class ServiceControllerPermission : ResourcePermissionBase diff --git a/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermissionAttribute.cs index bf7d8cbd98da..fea924e61bd5 100644 --- a/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/ServiceProcess/ServiceControllerPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.ServiceProcess { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly | AttributeTargets.Event, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermission.cs b/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermission.cs index 0905e0f5b7bd..7107e3fd7a23 100644 --- a/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermission.cs @@ -6,7 +6,7 @@ namespace System.Transactions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class DistributedTransactionPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermissionAttribute.cs index cf17caabf319..4c794df14bee 100644 --- a/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Transactions/DistributedTransactionPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Transactions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] diff --git a/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermission.cs b/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermission.cs index 74b2a712674c..9735b517fe4f 100644 --- a/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermission.cs @@ -6,7 +6,7 @@ namespace System.Web { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class AspNetHostingPermission : CodeAccessPermission, IUnrestrictedPermission diff --git a/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermissionAttribute.cs b/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermissionAttribute.cs index d5c8631f2162..9b91e5a31dc7 100644 --- a/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermissionAttribute.cs +++ b/src/libraries/System.Security.Permissions/src/System/Web/AspNetHostingPermissionAttribute.cs @@ -6,7 +6,7 @@ namespace System.Web { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] diff --git a/src/libraries/System.Security.Permissions/src/System/Xaml/Permissions/XamlLoadPermission.cs b/src/libraries/System.Security.Permissions/src/System/Xaml/Permissions/XamlLoadPermission.cs index 84e13bd45dc9..5ce3a929edeb 100644 --- a/src/libraries/System.Security.Permissions/src/System/Xaml/Permissions/XamlLoadPermission.cs +++ b/src/libraries/System.Security.Permissions/src/System/Xaml/Permissions/XamlLoadPermission.cs @@ -10,7 +10,7 @@ namespace System.Xaml.Permissions { -#if NETCOREAPP +#if NET [Obsolete(Obsoletions.CodeAccessSecurityMessage, DiagnosticId = Obsoletions.CodeAccessSecurityDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] #endif public sealed class XamlLoadPermission : CodeAccessPermission, IUnrestrictedPermission @@ -23,7 +23,7 @@ public XamlLoadPermission(IEnumerable allowedAccess) { } [ComVisible(false)] public override int GetHashCode() { return base.GetHashCode(); } [SupportedOSPlatform("windows")] - public IList AllowedAccess { get; private set; } = new ReadOnlyCollection(Array.Empty()); + public IList AllowedAccess { get; } = new ReadOnlyCollection(Array.Empty()); public override IPermission Copy() { return new XamlLoadPermission(PermissionState.Unrestricted); } public override void FromXml(SecurityElement elem) { } public bool Includes(XamlAccessLevel requestedAccess) { return true; } diff --git a/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/SID.cs b/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/SID.cs index 8cfdb97aa077..e21a610b3a9a 100644 --- a/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/SID.cs +++ b/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/SID.cs @@ -861,7 +861,10 @@ public override IdentityReference Translate(Type targetType) public int CompareTo(SecurityIdentifier? sid) { - ArgumentNullException.ThrowIfNull(sid); + if (sid is null) + { + return 1; + } if (this.IdentifierAuthority < sid.IdentifierAuthority) { diff --git a/src/libraries/System.Security.Principal.Windows/tests/WellKnownSidTypeTests.cs b/src/libraries/System.Security.Principal.Windows/tests/WellKnownSidTypeTests.cs index 07d9404e65e1..962b0c16c666 100644 --- a/src/libraries/System.Security.Principal.Windows/tests/WellKnownSidTypeTests.cs +++ b/src/libraries/System.Security.Principal.Windows/tests/WellKnownSidTypeTests.cs @@ -152,4 +152,15 @@ public void MaxDefinedHasLegacyValue() Assert.Equal(WellKnownSidType.WinBuiltinTerminalServerLicenseServersSid, WellKnownSidType.MaxDefined); #pragma warning restore 0618 } + + [ConditionalTheory(nameof(AccountIsDomainJoined))] + [InlineData(WellKnownSidType.WorldSid)] + public void CompareTo_Null(WellKnownSidType sidType) + { + using (var identity = WindowsIdentity.GetCurrent()) + { + var si = new SecurityIdentifier(sidType, identity.Owner.AccountDomainSid); + Assert.Equal(1, si.CompareTo(null)); + } + } } diff --git a/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/Syndication/DateTimeHelper.cs b/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/Syndication/DateTimeHelper.cs index ee0bb46bdfb1..b9b6cada89d5 100644 --- a/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/Syndication/DateTimeHelper.cs +++ b/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/Syndication/DateTimeHelper.cs @@ -58,7 +58,7 @@ private static bool Rfc3339DateTimeParser(string dateTimeString, out DateTimeOff ++i; } -#if NETCOREAPP +#if NET dateTimeString = string.Concat(dateTimeString.AsSpan(0, 19), dateTimeString.AsSpan(i)); #else dateTimeString = dateTimeString.Substring(0, 19) + dateTimeString.Substring(i); diff --git a/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/XmlBuffer.cs b/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/XmlBuffer.cs index 17f3cfa2e1e7..4c31f32bf505 100644 --- a/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/XmlBuffer.cs +++ b/src/libraries/System.ServiceModel.Syndication/src/System/ServiceModel/XmlBuffer.cs @@ -87,7 +87,7 @@ public void Close() _buffer = new byte[_stream.Length]; _stream.Position = 0; -#if NET7_0_OR_GREATER +#if NET _stream.ReadExactly(_buffer); #else int totalRead = 0; diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs index dc3a9d931f13..fa6be7f42e74 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs @@ -73,7 +73,7 @@ public unsafe void RequestAdditionalTime(int milliseconds) } } -#if NETCOREAPP +#if NET /// /// When this method is called from OnStart, OnStop, OnPause or OnContinue, /// the specified wait hint is passed to the diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceController.cs b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceController.cs index 2892e1abebe4..3041721ecaa6 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceController.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceController.cs @@ -934,7 +934,7 @@ public void Stop() /// /// true to stop all running dependent services together with the service; false to stop only the service. /// -#if NETCOREAPP +#if NET public #else private diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/SessionChangeDescription.cs b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/SessionChangeDescription.cs index e4924e93c414..0503b80316e8 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/SessionChangeDescription.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/SessionChangeDescription.cs @@ -6,7 +6,7 @@ namespace System.ServiceProcess { public readonly struct SessionChangeDescription -#if NETCOREAPP +#if NET : IEquatable #endif { diff --git a/src/libraries/System.ServiceProcess.ServiceController/tests/ServiceBaseTests.cs b/src/libraries/System.ServiceProcess.ServiceController/tests/ServiceBaseTests.cs index 2d097c766c33..f0b49f902fa8 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/tests/ServiceBaseTests.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/tests/ServiceBaseTests.cs @@ -70,7 +70,7 @@ private void Cleanup() } } -#if NETCOREAPP +#if NET [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsPrivilegedProcess))] [InlineData(-2)] [InlineData((long)int.MaxValue + 1)] diff --git a/src/libraries/System.Speech/src/Internal/AlphabetConverter.cs b/src/libraries/System.Speech/src/Internal/AlphabetConverter.cs index 754b0f2e1e41..ccba4dd0df96 100644 --- a/src/libraries/System.Speech/src/Internal/AlphabetConverter.cs +++ b/src/libraries/System.Speech/src/Internal/AlphabetConverter.cs @@ -216,13 +216,13 @@ private PhoneMapData CreateMap(string resourceName) private int _currentLangId; private PhoneMapData _phoneMap; - private static int[] s_langIds = new int[] { 0x804, 0x404, 0x407, 0x409, 0x40A, 0x40C, 0x411 }; - private static string[] s_resourceNames = + private static readonly int[] s_langIds = new int[] { 0x804, 0x404, 0x407, 0x409, 0x40A, 0x40C, 0x411 }; + private static readonly string[] s_resourceNames = new string[] { "upstable_chs.upsmap", "upstable_cht.upsmap", "upstable_deu.upsmap", "upstable_enu.upsmap", "upstable_esp.upsmap", "upstable_fra.upsmap", "upstable_jpn.upsmap", }; - private static PhoneMapData[] s_phoneMaps = new PhoneMapData[7]; - private static object s_staticLock = new(); + private static readonly PhoneMapData[] s_phoneMaps = new PhoneMapData[7]; + private static readonly object s_staticLock = new(); #endregion diff --git a/src/libraries/System.Speech/src/Internal/SrgsCompiler/CFGGrammar.cs b/src/libraries/System.Speech/src/Internal/SrgsCompiler/CFGGrammar.cs index 1430c1595270..6fece55f676b 100644 --- a/src/libraries/System.Speech/src/Internal/SrgsCompiler/CFGGrammar.cs +++ b/src/libraries/System.Speech/src/Internal/SrgsCompiler/CFGGrammar.cs @@ -530,7 +530,7 @@ internal static uint NextHandle #region Internal Fields - internal static Guid _SPGDF_ContextFree = new(0x4ddc926d, 0x6ce7, 0x4dc0, 0x99, 0xa7, 0xaf, 0x9e, 0x6b, 0x6a, 0x4e, 0x91); + internal static readonly Guid _SPGDF_ContextFree = new(0x4ddc926d, 0x6ce7, 0x4dc0, 0x99, 0xa7, 0xaf, 0x9e, 0x6b, 0x6a, 0x4e, 0x91); // internal const int INFINITE = unchecked((int)0xffffffff); diff --git a/src/libraries/System.Speech/src/Internal/Synthesis/AudioBase.cs b/src/libraries/System.Speech/src/Internal/Synthesis/AudioBase.cs index 782cd59fb6c3..c8ecfa784835 100644 --- a/src/libraries/System.Speech/src/Internal/Synthesis/AudioBase.cs +++ b/src/libraries/System.Speech/src/Internal/Synthesis/AudioBase.cs @@ -122,7 +122,7 @@ internal void PlayWaveFile(AudioData audio) { byte[] data = new byte[(int)audio._stream.Length]; -#if NET7_0_OR_GREATER +#if NET audio._stream.ReadExactly(data); #else int totalRead = 0; diff --git a/src/libraries/System.Speech/src/Internal/Synthesis/EngineSite.cs b/src/libraries/System.Speech/src/Internal/Synthesis/EngineSite.cs index a658f37ca618..c6caca4d9c25 100644 --- a/src/libraries/System.Speech/src/Internal/Synthesis/EngineSite.cs +++ b/src/libraries/System.Speech/src/Internal/Synthesis/EngineSite.cs @@ -175,7 +175,7 @@ public Stream LoadResource(Uri uri, string mediaType) MemoryStream memStream = new(cLen); byte[] ab = new byte[cLen]; -#if NET7_0_OR_GREATER +#if NET stream.ReadExactly(ab); #else int totalRead = 0; diff --git a/src/libraries/System.Speech/src/Recognition/DictationGrammar.cs b/src/libraries/System.Speech/src/Recognition/DictationGrammar.cs index 758da033e353..e14510e5bc1d 100644 --- a/src/libraries/System.Speech/src/Recognition/DictationGrammar.cs +++ b/src/libraries/System.Speech/src/Recognition/DictationGrammar.cs @@ -50,7 +50,7 @@ public void SetDictationContext(string precedingText, string subsequentText) #region Private Fields - private static Uri s_defaultDictationUri = new("grammar:dictation"); + private static readonly Uri s_defaultDictationUri = new("grammar:dictation"); #endregion } diff --git a/src/libraries/System.Speech/src/Recognition/Grammar.cs b/src/libraries/System.Speech/src/Recognition/Grammar.cs index 95d8a33be3ff..b4737ed283a4 100644 --- a/src/libraries/System.Speech/src/Recognition/Grammar.cs +++ b/src/libraries/System.Speech/src/Recognition/Grammar.cs @@ -1121,7 +1121,7 @@ private static string CheckRuleName(Stream stream, string rulename, bool isImpor private InternalGrammarData _internalData; private string _grammarName = string.Empty; private Collection _ruleRefs; - private static ResourceLoader s_resourceLoader = new(); + private static readonly ResourceLoader s_resourceLoader = new(); #if DEBUG private bool _loaded; diff --git a/src/libraries/System.Speech/src/SR.cs b/src/libraries/System.Speech/src/SR.cs index 540a8d57c292..b41f29dbe670 100644 --- a/src/libraries/System.Speech/src/SR.cs +++ b/src/libraries/System.Speech/src/SR.cs @@ -8,7 +8,7 @@ namespace System.Speech { internal static class SR { - private static ResourceManager s_resourceManager = new("ExceptionStringTable", typeof(SR).Assembly); + private static readonly ResourceManager s_resourceManager = new("ExceptionStringTable", typeof(SR).Assembly); internal static string Get(SRID id, params object[] args) { diff --git a/src/libraries/System.Speech/src/Synthesis/Prompt.cs b/src/libraries/System.Speech/src/Synthesis/Prompt.cs index e771fca8d9b7..4c281cb8dbbe 100644 --- a/src/libraries/System.Speech/src/Synthesis/Prompt.cs +++ b/src/libraries/System.Speech/src/Synthesis/Prompt.cs @@ -148,7 +148,7 @@ internal object Synthesizer /// private object _synthesizer; - private static ResourceLoader s_resourceLoader = new(); + private static readonly ResourceLoader s_resourceLoader = new(); #endregion } diff --git a/src/libraries/System.Speech/src/Synthesis/PromptBuilder.cs b/src/libraries/System.Speech/src/Synthesis/PromptBuilder.cs index 2b4c43414055..5cabd2f19490 100644 --- a/src/libraries/System.Speech/src/Synthesis/PromptBuilder.cs +++ b/src/libraries/System.Speech/src/Synthesis/PromptBuilder.cs @@ -991,7 +991,7 @@ private void AppendSsmlInternal(XmlReader ssmlFile) private List _elements = new(); // Resource loader for the prompt builder - private static ResourceLoader s_resourceLoader = new(); + private static readonly ResourceLoader s_resourceLoader = new(); private const string _xmlnsDefault = @"http://www.w3.org/2001/10/synthesis"; diff --git a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/CodePagesEncodingProvider.cs b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/CodePagesEncodingProvider.cs index c984dbf460d8..58bb679c7712 100644 --- a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/CodePagesEncodingProvider.cs +++ b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/CodePagesEncodingProvider.cs @@ -197,7 +197,7 @@ public static EncodingProvider Instance internal static unsafe ref T GetNonNullPinnableReference(T[] array) where T : struct { return ref -#if NET5_0_OR_GREATER +#if NET MemoryMarshal.GetArrayDataReference(array); #else array.Length != 0 ? ref array[0] : ref Unsafe.AsRef((void*)1); diff --git a/src/libraries/System.Text.Encodings.Web/src/System/IO/TextWriterExtensions.cs b/src/libraries/System.Text.Encodings.Web/src/System/IO/TextWriterExtensions.cs index bcb3cb0bd778..11bff860545b 100644 --- a/src/libraries/System.Text.Encodings.Web/src/System/IO/TextWriterExtensions.cs +++ b/src/libraries/System.Text.Encodings.Web/src/System/IO/TextWriterExtensions.cs @@ -3,7 +3,7 @@ using System.Diagnostics; -#if !NETCOREAPP +#if !NET using System.Buffers; #endif @@ -29,7 +29,7 @@ public static void WritePartialString(this TextWriter writer, string value, int // if slicing is required, call TextWriter.Write(ROS) if available; // otherwise rent an array and implement the Write routine ourselves ReadOnlySpan sliced = value.AsSpan(offset, count); -#if NETCOREAPP +#if NET writer.Write(sliced); #else char[] rented = ArrayPool.Shared.Rent(sliced.Length); diff --git a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/AllowedBmpCodePointsBitmap.cs b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/AllowedBmpCodePointsBitmap.cs index 377d1d0c071d..d989b7c267e7 100644 --- a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/AllowedBmpCodePointsBitmap.cs +++ b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/AllowedBmpCodePointsBitmap.cs @@ -6,7 +6,7 @@ using System.Runtime.CompilerServices; using System.Text.Unicode; -#if NETCOREAPP +#if NET using System.Numerics; #endif @@ -69,7 +69,7 @@ public void ForbidUndefinedCharacters() Span thisAllowedCharactersBitmap = new Span(pBitmap, BitmapLengthInDWords); Debug.Assert(definedCharsBitmapAsLittleEndian.Length == thisAllowedCharactersBitmap.Length * sizeof(uint)); -#if NETCOREAPP +#if NET if (Vector.IsHardwareAccelerated && BitConverter.IsLittleEndian) { while (!definedCharsBitmapAsLittleEndian.IsEmpty) diff --git a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.Ascii.cs b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.Ascii.cs index 03c0e7fc324b..d2aac7f94f4c 100644 --- a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.Ascii.cs +++ b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.Ascii.cs @@ -5,7 +5,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if NETCOREAPP +#if NET using System.Runtime.Intrinsics; #endif @@ -22,7 +22,7 @@ private unsafe partial struct AllowedAsciiCodePoints [FieldOffset(0)] // ensure same offset with AsVector field private fixed byte AsBytes[16]; -#if NETCOREAPP +#if NET #if !TARGET_BROWSER [FieldOffset(0)] // ensure same offset with AsBytes field internal Vector128 AsVector; diff --git a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.cs b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.cs index 56fc2b77a938..e3f12a3b2a84 100644 --- a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.cs +++ b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/OptimizedInboxTextEncoder.cs @@ -5,11 +5,11 @@ using System.Diagnostics; using System.Runtime.CompilerServices; -#if NETCOREAPP +#if NET using System.Runtime.Intrinsics.X86; #endif -#if NETCOREAPP +#if NET using System.Runtime.Intrinsics.Arm; #endif @@ -347,7 +347,7 @@ public int GetIndexOfFirstByteToEncode(ReadOnlySpan data) int dataOriginalLength = data.Length; -#if NETCOREAPP +#if NET if (Ssse3.IsSupported || (AdvSimd.Arm64.IsSupported && BitConverter.IsLittleEndian)) { int asciiBytesSkipped; @@ -416,7 +416,7 @@ public unsafe int GetIndexOfFirstCharToEncode(ReadOnlySpan data) // The SIMD-enabled version handles only ASCII characters. nuint idx = 0; -#if NETCOREAPP +#if NET if (Ssse3.IsSupported) { idx = GetIndexOfFirstCharToEncodeSsse3(pData, lengthInChars); diff --git a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/TextEncoder.cs b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/TextEncoder.cs index 41b620e1beec..4c9aee529294 100644 --- a/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/TextEncoder.cs +++ b/src/libraries/System.Text.Encodings.Web/src/System/Text/Encodings/Web/TextEncoder.cs @@ -150,7 +150,7 @@ private string EncodeToNewString(ReadOnlySpan value, int indexOfFirstCharT ReadOnlySpan remainingInput = value.Slice(indexOfFirstCharToEncode); ValueStringBuilder stringBuilder = new ValueStringBuilder(stackalloc char[EncodeStartingOutputBufferSize]); -#if !NETCOREAPP +#if !NET // Can't call string.Concat later in the method, so memcpy now. stringBuilder.Append(value.Slice(0, indexOfFirstCharToEncode)); #endif @@ -175,7 +175,7 @@ private string EncodeToNewString(ReadOnlySpan value, int indexOfFirstCharT stringBuilder.Length -= destBuffer.Length - charsWrittenJustNow; } while (!remainingInput.IsEmpty); -#if NETCOREAPP +#if NET string retVal = string.Concat(value.Slice(0, indexOfFirstCharToEncode), stringBuilder.AsSpan()); stringBuilder.Dispose(); return retVal; diff --git a/src/libraries/System.Text.Encodings.Web/src/System/Text/Unicode/UnicodeRange.cs b/src/libraries/System.Text.Encodings.Web/src/System/Text/Unicode/UnicodeRange.cs index 2c199790d2b9..71bc46690bf8 100644 --- a/src/libraries/System.Text.Encodings.Web/src/System/Text/Unicode/UnicodeRange.cs +++ b/src/libraries/System.Text.Encodings.Web/src/System/Text/Unicode/UnicodeRange.cs @@ -38,12 +38,12 @@ public UnicodeRange(int firstCodePoint, int length) /// /// The first code point in this range. /// - public int FirstCodePoint { get; private set; } + public int FirstCodePoint { get; } /// /// The number of code points in this range. /// - public int Length { get; private set; } + public int Length { get; } /// /// Creates a new from a span of characters. diff --git a/src/libraries/System.Text.Json/Common/JsonCamelCaseNamingPolicy.cs b/src/libraries/System.Text.Json/Common/JsonCamelCaseNamingPolicy.cs index 436489906a62..43fa642a3c6d 100644 --- a/src/libraries/System.Text.Json/Common/JsonCamelCaseNamingPolicy.cs +++ b/src/libraries/System.Text.Json/Common/JsonCamelCaseNamingPolicy.cs @@ -12,7 +12,7 @@ public override string ConvertName(string name) return name; } -#if NETCOREAPP +#if NET return string.Create(name.Length, name, (chars, name) => { name.CopyTo(chars); diff --git a/src/libraries/System.Text.Json/Common/JsonHelpers.cs b/src/libraries/System.Text.Json/Common/JsonHelpers.cs index 5711afa83706..ad718eba4a41 100644 --- a/src/libraries/System.Text.Json/Common/JsonHelpers.cs +++ b/src/libraries/System.Text.Json/Common/JsonHelpers.cs @@ -11,7 +11,7 @@ namespace System.Text.Json { internal static partial class JsonHelpers { -#if !NETCOREAPP +#if !NET /// /// netstandard/netfx polyfill for Dictionary.TryAdd /// @@ -55,7 +55,7 @@ internal static bool RequiresSpecialNumberHandlingOnWrite(JsonNumberHandling? ha internal static void StableSortByKey(this List items, Func keySelector) where TKey : unmanaged, IComparable { -#if NET6_0_OR_GREATER +#if NET Span span = CollectionsMarshal.AsSpan(items); // Tuples implement lexical ordering OOTB which can be used to encode stable sorting diff --git a/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs b/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs index d3c7d0dfc1e6..f1c76e7674f0 100644 --- a/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs +++ b/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs @@ -150,5 +150,10 @@ public JsonSourceGenerationOptionsAttribute(JsonSerializerDefaults defaults) /// instead of numeric serialization for all enum types encountered in its type graph. /// public bool UseStringEnumConverter { get; set; } + + /// + /// Specifies the default value of when set. + /// + public string? NewLine { get; set; } } } diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs index 7dbc4de3a57f..12173a0e917d 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs @@ -1147,6 +1147,9 @@ private static void GetLogicForDefaultSerializerOptionsInit(SourceGenerationOpti if (optionsSpec.MaxDepth is int maxDepth) writer.WriteLine($"MaxDepth = {maxDepth},"); + if (optionsSpec.NewLine is string newLine) + writer.WriteLine($"NewLine = {FormatStringLiteral(newLine)},"); + if (optionsSpec.NumberHandling is JsonNumberHandling numberHandling) writer.WriteLine($"NumberHandling = {FormatNumberHandling(numberHandling)},"); diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs index 9ae7ea968178..5d94f860cd78 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs @@ -272,6 +272,7 @@ private SourceGenerationOptionsSpec ParseJsonSourceGenerationOptionsAttribute(IN bool? ignoreReadOnlyProperties = null; bool? includeFields = null; int? maxDepth = null; + string? newLine = null; JsonNumberHandling? numberHandling = null; JsonObjectCreationHandling? preferredObjectCreationHandling = null; bool? propertyNameCaseInsensitive = null; @@ -344,6 +345,10 @@ private SourceGenerationOptionsSpec ParseJsonSourceGenerationOptionsAttribute(IN maxDepth = (int)namedArg.Value.Value!; break; + case nameof(JsonSourceGenerationOptionsAttribute.NewLine): + newLine = (string)namedArg.Value.Value!; + break; + case nameof(JsonSourceGenerationOptionsAttribute.NumberHandling): numberHandling = (JsonNumberHandling)namedArg.Value.Value!; break; @@ -411,6 +416,7 @@ private SourceGenerationOptionsSpec ParseJsonSourceGenerationOptionsAttribute(IN IgnoreReadOnlyProperties = ignoreReadOnlyProperties, IncludeFields = includeFields, MaxDepth = maxDepth, + NewLine = newLine, NumberHandling = numberHandling, PreferredObjectCreationHandling = preferredObjectCreationHandling, PropertyNameCaseInsensitive = propertyNameCaseInsensitive, diff --git a/src/libraries/System.Text.Json/gen/Model/SourceGenerationOptionsSpec.cs b/src/libraries/System.Text.Json/gen/Model/SourceGenerationOptionsSpec.cs index 82ad9ff711af..e16bebb6ceb4 100644 --- a/src/libraries/System.Text.Json/gen/Model/SourceGenerationOptionsSpec.cs +++ b/src/libraries/System.Text.Json/gen/Model/SourceGenerationOptionsSpec.cs @@ -36,6 +36,8 @@ public sealed record SourceGenerationOptionsSpec public required int? MaxDepth { get; init; } + public required string? NewLine { get; init; } + public required JsonNumberHandling? NumberHandling { get; init; } public required JsonObjectCreationHandling? PreferredObjectCreationHandling { get; init; } diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs index c0f23522b137..3fd6af13262b 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -307,8 +307,17 @@ public static void Serialize(System.Text.Json.Utf8JsonWriter writer, object? val public static System.Threading.Tasks.Task SerializeAsync(System.IO.Stream utf8Json, object? value, System.Type inputType, System.Text.Json.Serialization.JsonSerializerContext context, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.")] [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] + public static System.Threading.Tasks.Task SerializeAsync(System.IO.Pipelines.PipeWriter utf8Json, TValue value, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] public static System.Threading.Tasks.Task SerializeAsync(System.IO.Stream utf8Json, TValue value, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.Task SerializeAsync(System.IO.Stream utf8Json, TValue value, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SerializeAsync(System.IO.Pipelines.PipeWriter utf8Json, TValue value, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SerializeAsync(System.IO.Pipelines.PipeWriter utf8Json, object? value, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] + public static System.Threading.Tasks.Task SerializeAsync(System.IO.Pipelines.PipeWriter utf8Json, object? value, System.Type inputType, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SerializeAsync(System.IO.Pipelines.PipeWriter utf8Json, object? value, System.Type inputType, System.Text.Json.Serialization.JsonSerializerContext context, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Text.Json.JsonDocument SerializeToDocument(object? value, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.")] [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] @@ -385,6 +394,7 @@ public JsonSerializerOptions(System.Text.Json.JsonSerializerOptions options) { } public bool IncludeFields { get { throw null; } set { } } public bool IsReadOnly { get { throw null; } } public int MaxDepth { get { throw null; } set { } } + public string NewLine { get { throw null; } set { } } public System.Text.Json.Serialization.JsonNumberHandling NumberHandling { get { throw null; } set { } } public System.Text.Json.Serialization.JsonObjectCreationHandling PreferredObjectCreationHandling { get { throw null; } set { } } public bool PropertyNameCaseInsensitive { get { throw null; } set { } } @@ -445,6 +455,7 @@ public partial struct JsonWriterOptions public bool Indented { get { throw null; } set { } } public char IndentCharacter { get { throw null; } set { } } public int IndentSize { get { throw null; } set { } } + public string NewLine { get { throw null; } set { } } public int MaxDepth { readonly get { throw null; } set { } } public bool SkipValidation { get { throw null; } set { } } } @@ -657,7 +668,9 @@ namespace System.Text.Json.Nodes public sealed partial class JsonArray : System.Text.Json.Nodes.JsonNode, System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.IEnumerable { public JsonArray(System.Text.Json.Nodes.JsonNodeOptions? options = default(System.Text.Json.Nodes.JsonNodeOptions?)) { } + public JsonArray(System.Text.Json.Nodes.JsonNodeOptions options, params System.ReadOnlySpan items) { } public JsonArray(System.Text.Json.Nodes.JsonNodeOptions options, params System.Text.Json.Nodes.JsonNode?[] items) { } + public JsonArray(params System.ReadOnlySpan items) { } public JsonArray(params System.Text.Json.Nodes.JsonNode?[] items) { } public int Count { get { throw null; } } bool System.Collections.Generic.ICollection.IsReadOnly { get { throw null; } } @@ -1072,6 +1085,7 @@ public JsonSourceGenerationOptionsAttribute(System.Text.Json.JsonSerializerDefau public bool IgnoreReadOnlyProperties { get { throw null; } set { } } public bool IncludeFields { get { throw null; } set { } } public int MaxDepth { get { throw null; } set { } } + public string? NewLine { get { throw null; } set { } } public System.Text.Json.Serialization.JsonNumberHandling NumberHandling { get { throw null; } set { } } public System.Text.Json.Serialization.JsonObjectCreationHandling PreferredObjectCreationHandling { get { throw null; } set { } } public bool PropertyNameCaseInsensitive { get { throw null; } set { } } @@ -1349,6 +1363,7 @@ public enum JsonTypeInfoKind } public static partial class JsonTypeInfoResolver { + public static System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver Combine(params System.ReadOnlySpan resolvers) { throw null; } public static System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver Combine(params System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver?[] resolvers) { throw null; } public static System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver WithAddedModifier(this System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver resolver, System.Action modifier) { throw null; } } diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.csproj b/src/libraries/System.Text.Json/ref/System.Text.Json.csproj index 48187a11e58e..9e41bc3097af 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.csproj @@ -26,6 +26,7 @@ + diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.netcoreapp.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.netcoreapp.cs index 847da900ad35..bbf2e3846a6b 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.netcoreapp.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.netcoreapp.cs @@ -12,7 +12,7 @@ public static partial class JsonMetadataServices public static System.Text.Json.Serialization.JsonConverter HalfConverter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter TimeOnlyConverter { get { throw null; } } -#if NET7_0_OR_GREATER +#if NET public static System.Text.Json.Serialization.JsonConverter Int128Converter { get { throw null; } } [System.CLSCompliantAttribute(false)] public static System.Text.Json.Serialization.JsonConverter UInt128Converter { get { throw null; } } diff --git a/src/libraries/System.Text.Json/src/Resources/Strings.resx b/src/libraries/System.Text.Json/src/Resources/Strings.resx index 54d82b5f0578..e343daa47cf5 100644 --- a/src/libraries/System.Text.Json/src/Resources/Strings.resx +++ b/src/libraries/System.Text.Json/src/Resources/Strings.resx @@ -1,13 +1,17 @@ - @@ -717,4 +728,13 @@ Indentation size must be between {0} and {1}. + + PipeWriter.FlushAsync was canceled. + + + PipeWriter has been completed, nothing more can be written to it. + + + New line can be only "\n" or "\r\n". + diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 34fb2d13a6f3..7b49b89792cd 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -102,6 +102,7 @@ The System.Text.Json library is built-in as part of the shared framework in .NET + @@ -252,6 +253,7 @@ The System.Text.Json library is built-in as part of the shared framework in .NET + @@ -372,6 +374,7 @@ The System.Text.Json library is built-in as part of the shared framework in .NET + diff --git a/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs b/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs index 9dab389dd045..ec6b46db24e8 100644 --- a/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs +++ b/src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs @@ -97,7 +97,7 @@ private static bool HasCustomAttributeWithName(this MemberInfo memberInfo, strin object?[] parameters) { ConstructorInfo ctorInfo = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, parameterTypes, null)!; -#if NETCOREAPP +#if NET return ctorInfo.Invoke(BindingFlags.DoNotWrapExceptions, null, parameters, null); #else object? result = null; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.MetadataDb.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.MetadataDb.cs index afdbf4bd0b9b..a53df982c12e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.MetadataDb.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.MetadataDb.cs @@ -240,7 +240,7 @@ private void Enlarge() // Note: Array.MaxLength exists only on .NET 6 or greater, // so for the other versions value is hardcoded const int MaxArrayLength = 0x7FFFFFC7; -#if NET6_0_OR_GREATER +#if NET Debug.Assert(MaxArrayLength == Array.MaxLength); #endif diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs index f9b1fffd4243..6bd5a2814b64 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs @@ -833,7 +833,7 @@ private static ArraySegment ReadToEnd(Stream stream) } private static async -#if NETCOREAPP +#if NET ValueTask> #else Task> @@ -871,7 +871,7 @@ private static async Debug.Assert(rented.Length >= JsonConstants.Utf8Bom.Length); lastRead = await stream.ReadAsync( -#if NETCOREAPP +#if NET rented.AsMemory(written, utf8BomLength - written), #else rented, @@ -902,7 +902,7 @@ private static async } lastRead = await stream.ReadAsync( -#if NETCOREAPP +#if NET rented.AsMemory(written), #else rented, diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonConstants.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonConstants.cs index 078a6a4b8377..c2dbc58e131a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonConstants.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonConstants.cs @@ -28,6 +28,9 @@ internal static partial class JsonConstants public const byte UtcOffsetToken = (byte)'Z'; public const byte TimePrefix = (byte)'T'; + public const string NewLineLineFeed = "\n"; + public const string NewLineCarriageReturnLineFeed = "\r\n"; + // \u2028 and \u2029 are considered respectively line and paragraph separators // UTF-8 representation for them is E2, 80, A8/A9 public const byte StartingByteOfNonStandardSeparator = 0xE2; @@ -62,7 +65,7 @@ internal static partial class JsonConstants // When transcoding from UTF8 -> UTF16, the byte count threshold where we rent from the array pool before performing a normal alloc. public const long ArrayPoolMaxSizeBeforeUsingNormalAlloc = -#if NET6_0_OR_GREATER +#if NET 1024 * 1024 * 1024; // ArrayPool limit increased in .NET 6 #else 1024 * 1024; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs index f6c6e9255d9c..751f262acf3a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs @@ -95,7 +95,7 @@ public static bool TryParseAsISO(ReadOnlySpan source, out DateTimeOffset v return TryCreateDateTimeOffsetInterpretingDataAsLocalTime(parseData, out value); } -#if NETCOREAPP +#if NET public static bool TryParseAsIso(ReadOnlySpan source, out DateOnly value) { if (TryParseDateTimeOffset(source, out DateTimeParseData parseData) && diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs index 322b1d315c09..63e2e177f49e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs @@ -76,7 +76,7 @@ static bool TryAdvanceWithReadAhead(scoped ref Utf8JsonReader reader) } } -#if !NETCOREAPP +#if !NET /// /// Returns if is a valid Unicode scalar /// value, i.e., is in [ U+0000..U+D7FF ], inclusive; or [ U+E000..U+10FFFF ], inclusive. @@ -165,7 +165,7 @@ public static bool TrySkipPartial(this ref Utf8JsonReader reader) /// public static string Utf8GetString(ReadOnlySpan bytes) { -#if NETCOREAPP +#if NET return Encoding.UTF8.GetString(bytes); #else if (bytes.Length == 0) @@ -191,7 +191,7 @@ public static Dictionary CreateDictionaryFromCollection comparer) where TKey : notnull { -#if !NETCOREAPP +#if !NET var dictionary = new Dictionary(comparer); foreach (KeyValuePair item in collection) @@ -207,7 +207,7 @@ public static Dictionary CreateDictionaryFromCollection + /// Initializes a new instance of the class that contains items from the specified params span. + /// + /// Options to control the behavior. + /// The items to add to the new . + public JsonArray(JsonNodeOptions options, params ReadOnlySpan items) : base(options) + { + InitializeFromSpan(items); + } + /// /// Initializes a new instance of the class that contains items from the specified array. /// @@ -48,6 +58,15 @@ public JsonArray(params JsonNode?[] items) : base() InitializeFromArray(items); } + /// + /// Initializes a new instance of the class that contains items from the specified span. + /// + /// The items to add to the new . + public JsonArray(params ReadOnlySpan items) : base() + { + InitializeFromSpan(items); + } + internal override JsonValueKind GetValueKindCore() => JsonValueKind.Array; internal override JsonNode DeepCloneCore() @@ -129,9 +148,30 @@ private void InitializeFromArray(JsonNode?[] items) { var list = new List(items); - for (int i = 0; i < items.Length; i++) + for (int i = 0; i < list.Count; i++) + { + list[i]?.AssignParent(this); + } + + _list = list; + } + + private void InitializeFromSpan(ReadOnlySpan items) + { + List list = new(items.Length); + +#if NET8_0_OR_GREATER + list.AddRange(items); +#else + foreach (JsonNode? item in items) + { + list.Add(item); + } +#endif + + for (int i = 0; i < list.Count; i++) { - items[i]?.AssignParent(this); + list[i]?.AssignParent(this); } _list = list; @@ -206,7 +246,7 @@ internal override void GetPath(ref ValueStringBuilder path, JsonNode? child) Debug.Assert(index >= 0); path.Append('['); -#if NETCOREAPP +#if NET Span chars = stackalloc char[JsonConstants.MaximumFormatUInt32Length]; bool formatted = ((uint)index).TryFormat(chars, out int charsWritten); Debug.Assert(formatted); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs index 7408aaecc53c..298a59a64717 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs @@ -210,7 +210,7 @@ public static string TranscodeHelper(ReadOnlySpan utf8Unescaped) { try { -#if NETCOREAPP +#if NET return s_utf8Encoding.GetString(utf8Unescaped); #else if (utf8Unescaped.IsEmpty) @@ -241,7 +241,7 @@ public static int TranscodeHelper(ReadOnlySpan utf8Unescaped, Span d { try { -#if NETCOREAPP +#if NET return s_utf8Encoding.GetChars(utf8Unescaped, destination); #else if (utf8Unescaped.IsEmpty) @@ -285,7 +285,7 @@ public static void ValidateUtf8(ReadOnlySpan utf8Buffer) #else try { -#if NETCOREAPP +#if NET s_utf8Encoding.GetCharCount(utf8Buffer); #else if (utf8Buffer.IsEmpty) @@ -317,7 +317,7 @@ internal static int GetUtf8ByteCount(ReadOnlySpan text) { try { -#if NETCOREAPP +#if NET return s_utf8Encoding.GetByteCount(text); #else if (text.IsEmpty) @@ -348,7 +348,7 @@ internal static int GetUtf8FromText(ReadOnlySpan text, Span dest) { try { -#if NETCOREAPP +#if NET return s_utf8Encoding.GetBytes(text, dest); #else if (text.IsEmpty) @@ -379,7 +379,7 @@ internal static int GetUtf8FromText(ReadOnlySpan text, Span dest) internal static string GetTextFromUtf8(ReadOnlySpan utf8Text) { -#if NETCOREAPP +#if NET return s_utf8Encoding.GetString(utf8Text); #else if (utf8Text.IsEmpty) @@ -528,7 +528,7 @@ private static bool TryUnescape(ReadOnlySpan source, Span destinatio + JsonConstants.UnicodePlane01StartValue; } -#if NETCOREAPP +#if NET var rune = new Rune(scalar); bool success = rune.TryEncodeToUtf8(destination.Slice(written), out int bytesWritten); #else @@ -601,7 +601,7 @@ private static bool TryUnescape(ReadOnlySpan source, Span destinatio return false; } -#if !NETCOREAPP +#if !NET /// /// Copies the UTF-8 code unit representation of this scalar to an output buffer. /// The buffer must be large enough to hold the required number of s. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs index 9cdcc0ddfad7..b426f61cbb31 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs @@ -145,7 +145,7 @@ public static bool TryGetEscapedGuid(ReadOnlySpan source, out Guid value) return false; } -#if NETCOREAPP +#if NET public static bool TryGetFloatingPointConstant(ReadOnlySpan span, out Half value) { if (span.Length == 3) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.MultiSegment.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.MultiSegment.cs index 8635031292e3..22d3cc1c497d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.MultiSegment.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.MultiSegment.cs @@ -633,7 +633,7 @@ private static int FindMismatch(ReadOnlySpan span, ReadOnlySpan lite int indexOfFirstMismatch; -#if NET7_0_OR_GREATER +#if NET indexOfFirstMismatch = span.CommonPrefixLength(literal); #else int minLength = Math.Min(span.Length, literal.Length); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/AsyncSerializationBufferWriterContext.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/AsyncSerializationBufferWriterContext.cs new file mode 100644 index 000000000000..f34bcaf61289 --- /dev/null +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/AsyncSerializationBufferWriterContext.cs @@ -0,0 +1,85 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.IO; +using System.IO.Pipelines; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Text.Json.Serialization +{ + // Common interface to help de-dupe code for different types that can do async serialization (Stream and PipeWriter) + internal interface IAsyncSerializationBufferWriterContext : IDisposable + { + int FlushThreshold { get; } + + ValueTask FlushAsync(CancellationToken cancellationToken); + + public IBufferWriter BufferWriter { get; } + } + + internal readonly struct AsyncSerializationStreamContext : IAsyncSerializationBufferWriterContext + { + private readonly Stream _stream; + private readonly JsonSerializerOptions _options; + private readonly PooledByteBufferWriter _bufferWriter; + + public AsyncSerializationStreamContext(Stream stream, JsonSerializerOptions options) + { + _stream = stream; + _options = options; + _bufferWriter = new PooledByteBufferWriter(_options.DefaultBufferSize); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public async ValueTask FlushAsync(CancellationToken cancellationToken) + { + await _bufferWriter.WriteToStreamAsync(_stream, cancellationToken).ConfigureAwait(false); + _bufferWriter.Clear(); + } + + public int FlushThreshold => (int)(_options.DefaultBufferSize * JsonSerializer.FlushThreshold); + + public IBufferWriter BufferWriter => _bufferWriter; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + _bufferWriter.Dispose(); + } + } + + internal readonly struct AsyncSerializationPipeContext : IAsyncSerializationBufferWriterContext + { + private readonly PipeWriter _pipe; + + public AsyncSerializationPipeContext(PipeWriter pipe) + { + _pipe = pipe; + } + + public int FlushThreshold => (int)((4 * PipeOptions.Default.MinimumSegmentSize) * JsonSerializer.FlushThreshold); + + public IBufferWriter BufferWriter => _pipe; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public async ValueTask FlushAsync(CancellationToken cancellationToken) + { + FlushResult result = await _pipe.FlushAsync(cancellationToken).ConfigureAwait(false); + if (result.IsCanceled || result.IsCompleted) + { + if (result.IsCanceled) + { + ThrowHelper.ThrowOperationCanceledException_PipeWriteCanceled(); + } + + ThrowHelper.ThrowOperationCanceledException_PipeWriteCompleted(); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() { } + } +} diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Attributes/JsonConverterAttribute.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Attributes/JsonConverterAttribute.cs index e456a009178d..6a3ead5847d5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Attributes/JsonConverterAttribute.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Attributes/JsonConverterAttribute.cs @@ -36,7 +36,7 @@ protected JsonConverterAttribute() { } /// The type of the converter to create, or null if should be used to obtain the converter. /// [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] - public Type? ConverterType { get; private set; } + public Type? ConverterType { get; } /// /// If overridden and is null, allows a custom attribute to create the converter in order to pass additional state. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactoryHelpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactoryHelpers.cs index 622ba2cf21d1..3d1c4ce8fce5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactoryHelpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactoryHelpers.cs @@ -93,7 +93,7 @@ public static MethodInfo GetImmutableDictionaryCreateRangeMethod(this Type type, public static bool IsNonGenericStackOrQueue(this Type type) { -#if NETCOREAPP +#if NET // Optimize for linking scenarios where mscorlib is trimmed out. const string stackTypeName = "System.Collections.Stack, System.Collections.NonGeneric"; const string queueTypeName = "System.Collections.Queue, System.Collections.NonGeneric"; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/CharConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/CharConverter.cs index 82e7e2699a95..c102a0879e1a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/CharConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/CharConverter.cs @@ -36,7 +36,7 @@ public override char Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSer public override void Write(Utf8JsonWriter writer, char value, JsonSerializerOptions options) { writer.WriteStringValue( -#if NETCOREAPP +#if NET new ReadOnlySpan(in value) #else value.ToString() @@ -53,7 +53,7 @@ internal override char ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type ty internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, char value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) { writer.WritePropertyName( -#if NETCOREAPP +#if NET new ReadOnlySpan(in value) #else value.ToString() diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs index 99b576030243..5f9ddf1eee1b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs @@ -61,7 +61,7 @@ public EnumConverter(EnumConverterOptions converterOptions, JsonNamingPolicy? na _nameCacheForReading = new ConcurrentDictionary(); } -#if NETCOREAPP +#if NET string[] names = Enum.GetNames(); T[] values = Enum.GetValues(); #else @@ -74,7 +74,7 @@ public EnumConverter(EnumConverterOptions converterOptions, JsonNamingPolicy? na for (int i = 0; i < names.Length; i++) { -#if NETCOREAPP +#if NET T value = values[i]; #else T value = (T)values.GetValue(i)!; @@ -106,7 +106,7 @@ public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerial return default; } -#if NETCOREAPP +#if NET if (TryParseEnumCore(ref reader, out T value)) #else string? enumString = reader.GetString(); @@ -116,7 +116,7 @@ public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerial return value; } -#if NETCOREAPP +#if NET return ReadEnumUsingNamingPolicy(reader.GetString()); #else return ReadEnumUsingNamingPolicy(enumString); @@ -270,7 +270,7 @@ public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions internal override T ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { -#if NETCOREAPP +#if NET if (TryParseEnumCore(ref reader, out T value)) #else string? enumString = reader.GetString(); @@ -280,7 +280,7 @@ internal override T ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeT return value; } -#if NETCOREAPP +#if NET return ReadEnumUsingNamingPolicy(reader.GetString()); #else return ReadEnumUsingNamingPolicy(enumString); @@ -362,14 +362,14 @@ internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, T value, J } private bool TryParseEnumCore( -#if NETCOREAPP +#if NET ref Utf8JsonReader reader, #else string? source, #endif out T value) { -#if NETCOREAPP +#if NET char[]? rentedBuffer = null; int bufferLength = reader.ValueLength; @@ -393,7 +393,7 @@ private bool TryParseEnumCore( value = default; } -#if NETCOREAPP +#if NET if (rentedBuffer != null) { charBuffer.Slice(0, charsWritten).Clear(); @@ -525,7 +525,7 @@ private static string[] SplitFlagsEnum(string value) { // todo: optimize implementation here by leveraging https://github.com/dotnet/runtime/issues/934. return value.Split( -#if NETCOREAPP +#if NET ValueSeparator #else new string[] { ValueSeparator }, StringSplitOptions.None diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/TimeSpanConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/TimeSpanConverter.cs index 245f5ea4afc1..08ef78d3f697 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/TimeSpanConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/TimeSpanConverter.cs @@ -8,7 +8,7 @@ namespace System.Text.Json.Serialization.Converters { internal sealed class TimeSpanConverter : JsonPrimitiveConverter { - private const int MinimumTimeSpanFormatLength = 8; // hh:mm:ss + private const int MinimumTimeSpanFormatLength = 1; // d private const int MaximumTimeSpanFormatLength = 26; // -dddddddd.hh:mm:ss.fffffff private const int MaximumEscapedTimeSpanFormatLength = JsonConstants.MaxExpansionFactorWhileEscaping * MaximumTimeSpanFormatLength; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/VersionConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/VersionConverter.cs index c3e60ab0448d..85e0d8f67398 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/VersionConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/VersionConverter.cs @@ -7,7 +7,7 @@ namespace System.Text.Json.Serialization.Converters { internal sealed class VersionConverter : JsonPrimitiveConverter { -#if NETCOREAPP +#if NET private const int MinimumVersionLength = 3; // 0.0 private const int MaximumVersionLength = 43; // 2147483647.2147483647.2147483647.2147483647 @@ -34,7 +34,7 @@ private static Version ReadCore(ref Utf8JsonReader reader) { Debug.Assert(reader.TokenType is JsonTokenType.PropertyName or JsonTokenType.String); -#if NETCOREAPP +#if NET if (!JsonHelpers.IsInRangeInclusive(reader.ValueLength, MinimumVersionLength, MaximumEscapedVersionLength)) { ThrowHelper.ThrowFormatException(DataType.Version); @@ -84,7 +84,7 @@ public override void Write(Utf8JsonWriter writer, Version? value, JsonSerializer return; } -#if NETCOREAPP +#if NET #if NET8_0_OR_GREATER Span span = stackalloc byte[MaximumVersionLength]; #else @@ -110,7 +110,7 @@ internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, Version va ThrowHelper.ThrowArgumentNullException(nameof(value)); } -#if NETCOREAPP +#if NET #if NET8_0_OR_GREATER Span span = stackalloc byte[MaximumVersionLength]; #else diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs index 469abaae498d..cf8b87696ea7 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs @@ -214,7 +214,7 @@ internal bool TryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSeriali bool success; if ( -#if NETCOREAPP +#if NET !typeof(T).IsValueType && #endif CanBePolymorphic) @@ -367,7 +367,7 @@ internal bool TryWrite(Utf8JsonWriter writer, in T? value, JsonSerializerOptions bool success; if ( -#if NETCOREAPP +#if NET // Short-circuit the check against "is not null"; treated as a constant by recent versions of the JIT. !typeof(T).IsValueType && #else diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Pipe.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Pipe.cs new file mode 100644 index 000000000000..dbd8debe55f0 --- /dev/null +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Pipe.cs @@ -0,0 +1,194 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using System.IO.Pipelines; +using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Text.Json +{ + public static partial class JsonSerializer + { + /// + /// Converts the provided value to UTF-8 encoded JSON text and write it to the . + /// + /// The type of the value to serialize. + /// The UTF-8 to write to. + /// The value to convert. + /// Metadata about the type to convert. + /// The that can be used to cancel the write operation. + /// A task that represents the asynchronous write operation. + /// + /// is . + /// + public static Task SerializeAsync( + PipeWriter utf8Json, + TValue value, + JsonTypeInfo jsonTypeInfo, + CancellationToken cancellationToken = default) + { + if (utf8Json is null) + { + ThrowHelper.ThrowArgumentNullException(nameof(utf8Json)); + } + if (jsonTypeInfo is null) + { + ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); + } + + jsonTypeInfo.EnsureConfigured(); + return jsonTypeInfo.SerializeAsync(utf8Json, value, cancellationToken); + } + + /// + /// Converts the provided value to UTF-8 encoded JSON text and write it to the . + /// + /// The type of the value to serialize. + /// The UTF-8 to write to. + /// The value to convert. + /// Options to control the conversion behavior. + /// The that can be used to cancel the write operation. + /// A task that represents the asynchronous write operation. + /// + /// is . + /// + /// + /// There is no compatible + /// for or its serializable members. + /// + [RequiresUnreferencedCode(SerializationUnreferencedCodeMessage)] + [RequiresDynamicCode(SerializationRequiresDynamicCodeMessage)] + public static Task SerializeAsync( + PipeWriter utf8Json, + TValue value, + JsonSerializerOptions? options = null, + CancellationToken cancellationToken = default) + { + if (utf8Json is null) + { + ThrowHelper.ThrowArgumentNullException(nameof(utf8Json)); + } + + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options); + return jsonTypeInfo.SerializeAsync(utf8Json, value, cancellationToken); + } + + /// + /// Converts the provided value to UTF-8 encoded JSON text and write it to the . + /// + /// The UTF-8 to write to. + /// The value to convert. + /// Metadata about the type to convert. + /// The that can be used to cancel the write operation. + /// A task that represents the asynchronous write operation. + /// + /// is . + /// + /// + /// does not match the type of . + /// + public static Task SerializeAsync( + PipeWriter utf8Json, + object? value, + JsonTypeInfo jsonTypeInfo, + CancellationToken cancellationToken = default) + { + if (utf8Json is null) + { + ThrowHelper.ThrowArgumentNullException(nameof(utf8Json)); + } + + if (jsonTypeInfo is null) + { + ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); + } + + jsonTypeInfo.EnsureConfigured(); + return jsonTypeInfo.SerializeAsObjectAsync(utf8Json, value, cancellationToken); + } + + /// + /// Converts the provided value to UTF-8 encoded JSON text and write it to the . + /// + /// The UTF-8 to write to. + /// The value to convert. + /// The type of the to convert. + /// A metadata provider for serializable types. + /// The that can be used to cancel the write operation. + /// A task that represents the asynchronous write operation. + /// + /// is not compatible with . + /// + /// + /// , , or is . + /// + /// + /// There is no compatible + /// for or its serializable members. + /// + public static Task SerializeAsync( + PipeWriter utf8Json, + object? value, + Type inputType, + JsonSerializerContext context, + CancellationToken cancellationToken = default) + { + if (utf8Json is null) + { + ThrowHelper.ThrowArgumentNullException(nameof(utf8Json)); + } + + if (context is null) + { + ThrowHelper.ThrowArgumentNullException(nameof(context)); + } + + ValidateInputType(value, inputType); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(context, inputType); + + return jsonTypeInfo.SerializeAsObjectAsync(utf8Json, value, cancellationToken); + } + + /// + /// Converts the provided value to UTF-8 encoded JSON text and write it to the . + /// + /// The UTF-8 to write to. + /// The value to convert. + /// The type of the to convert. + /// Options to control the conversion behavior. + /// The that can be used to cancel the write operation. + /// A task that represents the asynchronous write operation. + /// + /// is not compatible with . + /// + /// + /// or is . + /// + /// + /// There is no compatible + /// for or its serializable members. + /// + [RequiresUnreferencedCode(SerializationUnreferencedCodeMessage)] + [RequiresDynamicCode(SerializationRequiresDynamicCodeMessage)] + public static Task SerializeAsync( + PipeWriter utf8Json, + object? value, + Type inputType, + JsonSerializerOptions? options = null, + CancellationToken cancellationToken = default) + { + if (utf8Json is null) + { + ThrowHelper.ThrowArgumentNullException(nameof(utf8Json)); + } + + ValidateInputType(value, inputType); + JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, inputType); + + return jsonTypeInfo.SerializeAsObjectAsync(utf8Json, value, cancellationToken); + } + } +} diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs index ad529fa034fb..e171d8cdebe4 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs @@ -213,7 +213,7 @@ internal void ClearCaches() internal sealed class CachingContext { private readonly ConcurrentDictionary _cache = new(); -#if !NETCOREAPP +#if !NET private readonly Func _cacheEntryFactory; #endif @@ -221,7 +221,7 @@ public CachingContext(JsonSerializerOptions options, int hashCode) { Options = options; HashCode = hashCode; -#if !NETCOREAPP +#if !NET _cacheEntryFactory = type => CreateCacheEntry(type, this); #endif } @@ -254,7 +254,7 @@ public void Clear() private CacheEntry GetOrAddCacheEntry(Type type) { -#if NETCOREAPP +#if NET return _cache.GetOrAdd(type, CreateCacheEntry, this); #else return _cache.GetOrAdd(type, _cacheEntryFactory); @@ -504,6 +504,7 @@ public bool Equals(JsonSerializerOptions? left, JsonSerializerOptions? right) left._unmappedMemberHandling == right._unmappedMemberHandling && left._defaultBufferSize == right._defaultBufferSize && left._maxDepth == right._maxDepth && + left.NewLine == right.NewLine && // Read through property due to lazy initialization of the backing field left._allowOutOfOrderMetadataProperties == right._allowOutOfOrderMetadataProperties && left._allowTrailingCommas == right._allowTrailingCommas && left._ignoreNullValues == right._ignoreNullValues && @@ -561,6 +562,7 @@ public int GetHashCode(JsonSerializerOptions options) AddHashCode(ref hc, options._unmappedMemberHandling); AddHashCode(ref hc, options._defaultBufferSize); AddHashCode(ref hc, options._maxDepth); + AddHashCode(ref hc, options.NewLine); // Read through property due to lazy initialization of the backing field AddHashCode(ref hc, options._allowOutOfOrderMetadataProperties); AddHashCode(ref hc, options._allowTrailingCommas); AddHashCode(ref hc, options._ignoreNullValues); @@ -591,19 +593,19 @@ static void AddListHashCode(ref HashCode hc, ConfigurationList? static void AddHashCode(ref HashCode hc, TValue? value) { - if (typeof(TValue).IsValueType) + if (typeof(TValue).IsSealed) { hc.Add(value); } else { - Debug.Assert(!typeof(TValue).IsSealed, "Sealed reference types like string should not use this method."); + // Use the built-in hashcode for types that could be overriding GetHashCode(). hc.Add(RuntimeHelpers.GetHashCode(value)); } } } -#if !NETCOREAPP +#if !NET /// /// Polyfill for System.HashCode. /// diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs index 246d3ab303fc..e7123e3a4431 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs @@ -89,6 +89,7 @@ public static JsonSerializerOptions Web private bool _ignoreReadOnlyProperties; private bool _ignoreReadonlyFields; private bool _includeFields; + private string? _newLine; private bool _propertyNameCaseInsensitive; private bool _writeIndented; private char _indentCharacter = JsonConstants.DefaultIndentCharacter; @@ -141,6 +142,7 @@ public JsonSerializerOptions(JsonSerializerOptions options) _ignoreReadOnlyProperties = options._ignoreReadOnlyProperties; _ignoreReadonlyFields = options._ignoreReadonlyFields; _includeFields = options._includeFields; + _newLine = options._newLine; _propertyNameCaseInsensitive = options._propertyNameCaseInsensitive; _writeIndented = options._writeIndented; _indentCharacter = options._indentCharacter; @@ -750,6 +752,33 @@ public ReferenceHandler? ReferenceHandler } } + /// + /// Gets or sets the new line string to use when is . + /// The default is the value of . + /// + /// + /// Thrown when the new line string is . + /// + /// + /// Thrown when the new line string is not \n or \r\n. + /// + /// + /// Thrown if this property is set after serialization or deserialization has occurred. + /// + public string NewLine + { + get + { + return _newLine ??= Environment.NewLine; + } + set + { + JsonWriterHelper.ValidateNewLine(value); + VerifyMutable(); + _newLine = value; + } + } + /// /// Returns true if options uses compatible built-in resolvers or a combination of compatible built-in resolvers. /// @@ -970,6 +999,7 @@ internal JsonWriterOptions GetWriterOptions() IndentCharacter = IndentCharacter, IndentSize = IndentSize, MaxDepth = EffectiveMaxDepth, + NewLine = NewLine, #if !DEBUG SkipValidation = true #endif diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Converters.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Converters.cs index 117e3ba3d63a..c96e2a1c8f5d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Converters.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Converters.cs @@ -51,7 +51,7 @@ private static Dictionary GetDefaultSimpleConverters() Add(JsonMetadataServices.CharConverter); Add(JsonMetadataServices.DateTimeConverter); Add(JsonMetadataServices.DateTimeOffsetConverter); -#if NETCOREAPP +#if NET Add(JsonMetadataServices.DateOnlyConverter); Add(JsonMetadataServices.TimeOnlyConverter); Add(JsonMetadataServices.HalfConverter); @@ -74,7 +74,7 @@ private static Dictionary GetDefaultSimpleConverters() Add(JsonMetadataServices.UInt16Converter); Add(JsonMetadataServices.UInt32Converter); Add(JsonMetadataServices.UInt64Converter); -#if NET7_0_OR_GREATER +#if NET Add(JsonMetadataServices.Int128Converter); Add(JsonMetadataServices.UInt128Converter); #endif diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Helpers.cs index 3a39315eba51..3ce9c1570981 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Helpers.cs @@ -23,7 +23,7 @@ internal static MemberAccessor MemberAccessor static MemberAccessor Initialize() { MemberAccessor value = -#if NETCOREAPP +#if NET // if dynamic code isn't supported, fallback to reflection RuntimeFeature.IsDynamicCodeSupported ? new ReflectionEmitCachingMemberAccessor() : diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs index 83a24191b8fe..9c6cb4b9e3ce 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs @@ -50,7 +50,7 @@ public static partial class JsonMetadataServices public static JsonConverter DateTimeOffsetConverter => s_dateTimeOffsetConverter ??= new DateTimeOffsetConverter(); private static JsonConverter? s_dateTimeOffsetConverter; -#if NETCOREAPP +#if NET /// /// Returns a instance that converts values. /// @@ -108,7 +108,7 @@ public static partial class JsonMetadataServices public static JsonConverter Int64Converter => s_int64Converter ??= new Int64Converter(); private static JsonConverter? s_int64Converter; -#if NET7_0_OR_GREATER +#if NET /// /// Returns a instance that converts values. /// @@ -188,7 +188,7 @@ public static partial class JsonMetadataServices public static JsonConverter ObjectConverter => s_objectConverter ??= new DefaultObjectConverter(); private static JsonConverter? s_objectConverter; -#if NETCOREAPP +#if NET /// /// Returns a instance that converts values. /// diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs index 959490b53f19..4a6f10aa4406 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs @@ -623,10 +623,10 @@ private bool NumberHandingIsApplicable() potentialNumberType == typeof(ushort) || potentialNumberType == typeof(uint) || potentialNumberType == typeof(ulong) || -#if NETCOREAPP +#if NET potentialNumberType == typeof(Half) || #endif -#if NET7_0_OR_GREATER +#if NET potentialNumberType == typeof(Int128) || potentialNumberType == typeof(UInt128) || #endif diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs index 379a3754cf57..01369330feb6 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs @@ -160,7 +160,7 @@ internal override bool GetMemberAndWriteJson(object obj, ref WriteStack state, U T value = Get!(obj); if ( -#if NETCOREAPP +#if NET !typeof(T).IsValueType && // treated as a constant by recent versions of the JIT. #else !EffectiveConverter.IsValueType && diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs index e915c5bf4879..b46a44f10f31 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.IO.Pipelines; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Text.Json.Reflection; @@ -989,7 +990,10 @@ public JsonPropertyInfo CreateJsonPropertyInfo(Type propertyType, string name) // Untyped, root-level serialization methods internal abstract void SerializeAsObject(Utf8JsonWriter writer, object? rootValue); + internal abstract Task SerializeAsObjectAsync(TSerializationContext serializationContext, object? rootValue, CancellationToken cancellationToken) + where TSerializationContext : struct, IAsyncSerializationBufferWriterContext; internal abstract Task SerializeAsObjectAsync(Stream utf8Json, object? rootValue, CancellationToken cancellationToken); + internal abstract Task SerializeAsObjectAsync(PipeWriter utf8Json, object? rootValue, CancellationToken cancellationToken); internal abstract void SerializeAsObject(Stream utf8Json, object? rootValue); // Untyped, root-level deserialization methods @@ -1249,7 +1253,7 @@ internal void SetCreateObjectIfCompatible(Delegate? createObject) private static bool IsByRefLike(Type type) { -#if NETCOREAPP +#if NET return type.IsByRefLike; #else if (!type.IsValueType) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.WriteHelpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.WriteHelpers.cs index d916334c1925..a5c2bf874559 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.WriteHelpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.WriteHelpers.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.IO; +using System.IO.Pipelines; using System.Text.Json.Serialization.Converters; using System.Threading; using System.Threading.Tasks; @@ -36,7 +37,7 @@ internal void Serialize( writer.Flush(); } else if ( -#if NETCOREAPP +#if NET !typeof(T).IsValueType && #endif Converter.CanBePolymorphic && @@ -58,12 +59,28 @@ rootValue is not null && } } - // Root serialization method for async streaming serialization. - internal async Task SerializeAsync( - Stream utf8Json, + internal Task SerializeAsync(Stream utf8Json, T? rootValue, CancellationToken cancellationToken, object? rootValueBoxed = null) + { + return SerializeAsync(new AsyncSerializationStreamContext(utf8Json, Options), rootValue, cancellationToken, rootValueBoxed); + } + + internal Task SerializeAsync(PipeWriter utf8Json, + T? rootValue, + CancellationToken cancellationToken, + object? rootValueBoxed = null) + { + return SerializeAsync(new AsyncSerializationPipeContext(utf8Json), rootValue, cancellationToken, rootValueBoxed); + } + + // Root serialization method for async streaming serialization. + private async Task SerializeAsync( + TSerializationContext serializationContext, + T? rootValue, + CancellationToken cancellationToken, + object? rootValueBoxed = null) where TSerializationContext : struct, IAsyncSerializationBufferWriterContext { Debug.Assert(IsConfigured); Debug.Assert(rootValueBoxed is null || rootValueBoxed is T); @@ -76,27 +93,33 @@ internal async Task SerializeAsync( Debug.Assert(CanUseSerializeHandler); Debug.Assert(Converter is JsonMetadataServicesConverter); - using var bufferWriter = new PooledByteBufferWriter(Options.DefaultBufferSize); - Utf8JsonWriter writer = Utf8JsonWriterCache.RentWriter(Options, bufferWriter); + Utf8JsonWriter writer = Utf8JsonWriterCache.RentWriter(Options, serializationContext.BufferWriter); try { - SerializeHandler(writer, rootValue!); - writer.Flush(); + try + { + SerializeHandler(writer, rootValue!); + writer.Flush(); + } + finally + { + // Record the serialization size in both successful and failed operations, + // since we want to immediately opt out of the fast path if it exceeds the threshold. + OnRootLevelAsyncSerializationCompleted(writer.BytesCommitted + writer.BytesPending); + + Utf8JsonWriterCache.ReturnWriter(writer); + } + + await serializationContext.FlushAsync(cancellationToken).ConfigureAwait(false); } finally { - // Record the serialization size in both successful and failed operations, - // since we want to immediately opt out of the fast path if it exceeds the threshold. - OnRootLevelAsyncSerializationCompleted(writer.BytesCommitted + writer.BytesPending); - - Utf8JsonWriterCache.ReturnWriter(writer); + serializationContext.Dispose(); } - - await bufferWriter.WriteToStreamAsync(utf8Json, cancellationToken).ConfigureAwait(false); } else if ( -#if NETCOREAPP +#if NET !typeof(T).IsValueType && #endif Converter.CanBePolymorphic && @@ -104,7 +127,7 @@ rootValue is not null && Options.TryGetPolymorphicTypeInfoForRootType(rootValue, out JsonTypeInfo? derivedTypeInfo)) { Debug.Assert(typeof(T) == typeof(object)); - await derivedTypeInfo.SerializeAsObjectAsync(utf8Json, rootValue, cancellationToken).ConfigureAwait(false); + await derivedTypeInfo.SerializeAsObjectAsync(serializationContext, rootValue, cancellationToken).ConfigureAwait(false); } else { @@ -117,14 +140,13 @@ rootValue is not null && state.CancellationToken = cancellationToken; - using var bufferWriter = new PooledByteBufferWriter(Options.DefaultBufferSize); - using var writer = new Utf8JsonWriter(bufferWriter, Options.GetWriterOptions()); + var writer = new Utf8JsonWriter(serializationContext.BufferWriter, Options.GetWriterOptions()); try { do { - state.FlushThreshold = (int)(bufferWriter.Capacity * JsonSerializer.FlushThreshold); + state.FlushThreshold = serializationContext.FlushThreshold; try { @@ -139,8 +161,7 @@ rootValue is not null && } else { - await bufferWriter.WriteToStreamAsync(utf8Json, cancellationToken).ConfigureAwait(false); - bufferWriter.Clear(); + await serializationContext.FlushAsync(cancellationToken).ConfigureAwait(false); } } finally @@ -169,6 +190,15 @@ rootValue is not null && } } while (!isFinalBlock); + + if (CanUseSerializeHandler) + { + // On successful serialization, record the serialization size + // to determine potential suitability of the type for + // fast-path serialization in streaming methods. + Debug.Assert(writer.BytesPending == 0); + OnRootLevelAsyncSerializationCompleted(writer.BytesCommitted); + } } catch { @@ -176,14 +206,10 @@ rootValue is not null && await state.DisposePendingDisposablesOnExceptionAsync().ConfigureAwait(false); throw; } - - if (CanUseSerializeHandler) + finally { - // On successful serialization, record the serialization size - // to determine potential suitability of the type for - // fast-path serialization in streaming methods. - Debug.Assert(writer.BytesPending == 0); - OnRootLevelAsyncSerializationCompleted(writer.BytesCommitted); + writer.Dispose(); + serializationContext.Dispose(); } } } @@ -222,7 +248,7 @@ internal void Serialize( } } else if ( -#if NETCOREAPP +#if NET !typeof(T).IsValueType && #endif Converter.CanBePolymorphic && @@ -271,9 +297,15 @@ rootValue is not null && internal sealed override void SerializeAsObject(Utf8JsonWriter writer, object? rootValue) => Serialize(writer, JsonSerializer.UnboxOnWrite(rootValue), rootValue); + internal sealed override Task SerializeAsObjectAsync(TSerializationContext serializationContext, object? rootValue, CancellationToken cancellationToken) + => SerializeAsync(serializationContext, JsonSerializer.UnboxOnWrite(rootValue), cancellationToken, rootValue); + internal sealed override Task SerializeAsObjectAsync(Stream utf8Json, object? rootValue, CancellationToken cancellationToken) => SerializeAsync(utf8Json, JsonSerializer.UnboxOnWrite(rootValue), cancellationToken, rootValue); + internal sealed override Task SerializeAsObjectAsync(PipeWriter utf8Json, object? rootValue, CancellationToken cancellationToken) + => SerializeAsync(utf8Json, JsonSerializer.UnboxOnWrite(rootValue), cancellationToken, rootValue); + internal sealed override void SerializeAsObject(Stream utf8Json, object? rootValue) => Serialize(utf8Json, JsonSerializer.UnboxOnWrite(rootValue), rootValue); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoResolver.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoResolver.cs index 216329609f3b..58cc32c795e4 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoResolver.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoResolver.cs @@ -30,6 +30,25 @@ public static IJsonTypeInfoResolver Combine(params IJsonTypeInfoResolver?[] reso ThrowHelper.ThrowArgumentNullException(nameof(resolvers)); } + return Combine((ReadOnlySpan)resolvers); + } + + /// + /// Combines multiple sources into one. + /// + /// Sequence of contract resolvers to be queried for metadata. + /// A combining results from . + /// + /// The combined resolver will query each of in the specified order, + /// returning the first result that is non-null. If all return null, + /// then the combined resolver will also return . + /// + /// Can be used to combine multiple sources, + /// which typically define contract metadata for small subsets of types. + /// It can also be used to fall back to wherever necessary. + /// + public static IJsonTypeInfoResolver Combine(params ReadOnlySpan resolvers) + { var resolverChain = new JsonTypeInfoResolverChain(); foreach (IJsonTypeInfoResolver? resolver in resolvers) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.Cache.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.Cache.cs index 8e966a122a4f..dc203854c3d8 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.Cache.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.Cache.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETFRAMEWORK || NETCOREAPP +#if NETFRAMEWORK || NET using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; @@ -30,7 +30,7 @@ public TValue GetOrAdd(TKey key, Func valueFactory) where { CacheEntry entry = _cache.GetOrAdd( key, -#if NETCOREAPP +#if NET static (TKey key, Func valueFactory) => new(valueFactory(key)), valueFactory); #else diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.cs index 4efe2a3af47f..dc18286f7e12 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETFRAMEWORK || NETCOREAPP +#if NETFRAMEWORK || NET using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Reflection; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitMemberAccessor.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitMemberAccessor.cs index 5e6f6986539e..7bda4bda73f5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitMemberAccessor.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitMemberAccessor.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NETFRAMEWORK || NETCOREAPP +#if NETFRAMEWORK || NET using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs index 593bb6a20dff..dc624235377a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs @@ -49,7 +49,7 @@ public readonly async ValueTask ReadFromStreamAsync( do { int bytesRead = await utf8Json.ReadAsync( -#if NETCOREAPP +#if NET bufferState._buffer.AsMemory(bufferState._count), #else bufferState._buffer, bufferState._count, bufferState._buffer.Length - bufferState._count, @@ -80,7 +80,7 @@ public void ReadFromStream(Stream utf8Json) do { int bytesRead = utf8Json.Read( -#if NETCOREAPP +#if NET _buffer.AsSpan(_count)); #else _buffer, _count, _buffer.Length - _count); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs index d183423c1323..d50f3f261fe0 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs @@ -412,7 +412,7 @@ public static void ReThrowWithPath(scoped ref ReadStack state, JsonReaderExcepti string message = ex.Message; // Insert the "Path" portion before "LineNumber" and "BytePositionInLine". -#if NETCOREAPP +#if NET int iPos = message.AsSpan().LastIndexOf(" LineNumber: "); #else int iPos = message.LastIndexOf(" LineNumber: ", StringComparison.Ordinal); @@ -897,5 +897,17 @@ public static void ThrowArgumentException_JsonPolymorphismOptionsAssociatedWithD { throw new ArgumentException(SR.JsonPolymorphismOptionsAssociatedWithDifferentJsonTypeInfo, paramName: parameterName); } + + [DoesNotReturn] + public static void ThrowOperationCanceledException_PipeWriteCanceled() + { + throw new OperationCanceledException(SR.PipeWriterCanceled); + } + + [DoesNotReturn] + public static void ThrowOperationCanceledException_PipeWriteCompleted() + { + throw new OperationCanceledException(SR.PipeWriterCompleted); + } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs index 58bd0a717249..6976d42b967b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs @@ -12,6 +12,12 @@ internal static partial class ThrowHelper // If the exception source is this value, the serializer will re-throw as JsonException. public const string ExceptionSourceValueToRethrowAsJsonException = "System.Text.Json.Rethrowable"; + [DoesNotReturn] + public static void ThrowArgumentOutOfRangeException_NewLine(string parameterName) + { + throw GetArgumentOutOfRangeException(parameterName, SR.InvalidNewLine); + } + [DoesNotReturn] public static void ThrowArgumentOutOfRangeException_IndentCharacter(string parameterName) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.Escaping.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.Escaping.cs index 62705446f8f5..140ecfb91123 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.Escaping.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.Escaping.cs @@ -6,7 +6,7 @@ using System.Diagnostics; using System.Text.Encodings.Web; -#if !NETCOREAPP +#if !NET using System.Runtime.CompilerServices; #endif @@ -42,7 +42,7 @@ internal static partial class JsonWriterHelper 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // U+00F0..U+00FF ]; -#if NETCOREAPP +#if NET private const string HexFormatString = "X4"; #endif @@ -290,7 +290,7 @@ private static void EscapeNextChars(char value, Span destination, ref int break; default: destination[written++] = 'u'; -#if NETCOREAPP +#if NET int intChar = value; intChar.TryFormat(destination.Slice(written), out int charsWritten, HexFormatString); Debug.Assert(charsWritten == 4); @@ -302,7 +302,7 @@ private static void EscapeNextChars(char value, Span destination, ref int } } -#if !NETCOREAPP +#if !NET private static int WriteHex(int value, Span destination, int written) { destination[written++] = HexConverter.ToCharUpper(value >> 12); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs index c34c8cd3d672..b2e05f589fc1 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs @@ -36,6 +36,16 @@ public static void WriteIndentation(Span buffer, int indent, byte indentBy } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ValidateNewLine(string value) + { + if (value is null) + ThrowHelper.ThrowArgumentNullException(nameof(value)); + + if (value is not JsonConstants.NewLineLineFeed and not JsonConstants.NewLineCarriageReturnLineFeed) + ThrowHelper.ThrowArgumentOutOfRangeException_NewLine(nameof(value)); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ValidateIndentCharacter(char value) { @@ -254,7 +264,7 @@ public static unsafe bool IsValidUtf8String(ReadOnlySpan bytes) #else try { -#if NETCOREAPP +#if NET s_utf8Encoding.GetCharCount(bytes); #else if (!bytes.IsEmpty) @@ -276,7 +286,7 @@ public static unsafe bool IsValidUtf8String(ReadOnlySpan bytes) internal static unsafe OperationStatus ToUtf8(ReadOnlySpan source, Span destination, out int written) { -#if NETCOREAPP +#if NET OperationStatus status = Utf8.FromUtf16(source, destination, out int charsRead, out written, replaceInvalidSequences: false, isFinalBlock: true); Debug.Assert(status is OperationStatus.Done or OperationStatus.DestinationTooSmall or OperationStatus.InvalidData); Debug.Assert(charsRead == source.Length || status is not OperationStatus.Done); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterOptions.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterOptions.cs index 1d89e5d6aa14..2a96d748ad54 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterOptions.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterOptions.cs @@ -13,6 +13,8 @@ namespace System.Text.Json /// public struct JsonWriterOptions { + private static readonly string s_alternateNewLine = Environment.NewLine.Length == 2 ? JsonConstants.NewLineLineFeed : JsonConstants.NewLineCarriageReturnLineFeed; + internal const int DefaultMaxDepth = 1000; private int _maxDepth; @@ -68,11 +70,11 @@ public char IndentCharacter /// is out of the allowed range. public int IndentSize { - readonly get => EncodeIndentSize((_optionsMask & IndentSizeMask) >> 3); + readonly get => EncodeIndentSize((_optionsMask & IndentSizeMask) >> OptionsBitCount); set { JsonWriterHelper.ValidateIndentSize(value); - _optionsMask = (_optionsMask & ~IndentSizeMask) | (EncodeIndentSize(value) << 3); + _optionsMask = (_optionsMask & ~IndentSizeMask) | (EncodeIndentSize(value) << OptionsBitCount); } } @@ -135,11 +137,36 @@ public bool SkipValidation } } + /// + /// Gets or sets the new line string to use when is . + /// The default is the value of . + /// + /// + /// Thrown when the new line string is . + /// + /// + /// Thrown when the new line string is not \n or \r\n. + /// + public string NewLine + { + get => (_optionsMask & NewLineBit) != 0 ? s_alternateNewLine : Environment.NewLine; + set + { + JsonWriterHelper.ValidateNewLine(value); + if (value != Environment.NewLine) + _optionsMask |= NewLineBit; + else + _optionsMask &= ~NewLineBit; + } + } + internal bool IndentedOrNotSkipValidation => (_optionsMask & (IndentBit | SkipValidationBit)) != SkipValidationBit; // Equivalent to: Indented || !SkipValidation; + private const int OptionsBitCount = 4; private const int IndentBit = 1; private const int SkipValidationBit = 2; - private const int IndentCharacterBit = 4; - private const int IndentSizeMask = JsonConstants.MaximumIndentSize << 3; + private const int NewLineBit = 4; + private const int IndentCharacterBit = 8; + private const int IndentSizeMask = JsonConstants.MaximumIndentSize << OptionsBitCount; } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs index 1a1b3edb2ca8..c97d1cb15462 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs @@ -284,11 +284,11 @@ private void WriteBase64Indented(ReadOnlySpan escapedPropertyName, ReadOnl int encodedLength = Base64.GetMaxEncodedToUtf8Length(bytes.Length); - Debug.Assert(escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding < int.MaxValue - indent - encodedLength - 7 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding < int.MaxValue - indent - encodedLength - 7 - _newLineLength); // All ASCII, 2 quotes for property name, 2 quotes to surround the base-64 encoded string value, 1 colon, and 1 space => indent + escapedPropertyName.Length + encodedLength + 6 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding. - int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + encodedLength + 7 + s_newLineLength; + int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + encodedLength + 7 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -334,11 +334,11 @@ private void WriteBase64Indented(ReadOnlySpan escapedPropertyName, ReadOnl int encodedLength = Base64.GetMaxEncodedToUtf8Length(bytes.Length); - Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - encodedLength - 7 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - encodedLength - 7 - _newLineLength); // 2 quotes for property name, 2 quotes to surround the base-64 encoded string value, 1 colon, and 1 space => indent + escapedPropertyName.Length + encodedLength + 6 // Optionally, 1 list separator, and 1-2 bytes for new line. - int maxRequired = indent + escapedPropertyName.Length + encodedLength + 7 + s_newLineLength; + int maxRequired = indent + escapedPropertyName.Length + encodedLength + 7 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTime.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTime.cs index 392facd7d85e..9e1f07e25e01 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTime.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTime.cs @@ -286,11 +286,11 @@ private void WriteStringIndented(ReadOnlySpan escapedPropertyName, DateTim int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatDateTimeOffsetLength - 7 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatDateTimeOffsetLength - 7 - _newLineLength); // All ASCII, 2 quotes for property name, 2 quotes for date, 1 colon, and 1 space => escapedPropertyName.Length + JsonConstants.MaximumFormatDateTimeOffsetLength + 6 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatDateTimeOffsetLength + 7 + s_newLineLength; + int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatDateTimeOffsetLength + 7 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -335,10 +335,10 @@ private void WriteStringIndented(ReadOnlySpan escapedPropertyName, DateTim int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatDateTimeOffsetLength - 7 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatDateTimeOffsetLength - 7 - _newLineLength); int minRequired = indent + escapedPropertyName.Length + JsonConstants.MaximumFormatDateTimeOffsetLength + 6; // 2 quotes for property name, 2 quotes for date, 1 colon, and 1 space - int maxRequired = minRequired + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = minRequired + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTimeOffset.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTimeOffset.cs index 313693b3b766..38809447b91b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTimeOffset.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTimeOffset.cs @@ -285,11 +285,11 @@ private void WriteStringIndented(ReadOnlySpan escapedPropertyName, DateTim int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatDateTimeOffsetLength - 7 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatDateTimeOffsetLength - 7 - _newLineLength); // All ASCII, 2 quotes for property name, 2 quotes for date, 1 colon, and 1 space => escapedPropertyName.Length + JsonConstants.MaximumFormatDateTimeOffsetLength + 6 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatDateTimeOffsetLength + 7 + s_newLineLength; + int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatDateTimeOffsetLength + 7 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -334,10 +334,10 @@ private void WriteStringIndented(ReadOnlySpan escapedPropertyName, DateTim int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatDateTimeOffsetLength - 7 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatDateTimeOffsetLength - 7 - _newLineLength); int minRequired = indent + escapedPropertyName.Length + JsonConstants.MaximumFormatDateTimeOffsetLength + 6; // 2 quotes for property name, 2 quotes for date, 1 colon, and 1 space - int maxRequired = minRequired + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = minRequired + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Decimal.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Decimal.cs index 3f1af56067cd..aadc70a39b5f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Decimal.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Decimal.cs @@ -279,11 +279,11 @@ private void WriteNumberIndented(ReadOnlySpan escapedPropertyName, decimal int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatDecimalLength - 5 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatDecimalLength - 5 - _newLineLength); // All ASCII, 2 quotes for property name, 1 colon, and 1 space => escapedPropertyName.Length + JsonConstants.MaximumFormatDecimalLength + 4 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatDecimalLength + 5 + s_newLineLength; + int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatDecimalLength + 5 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -325,10 +325,10 @@ private void WriteNumberIndented(ReadOnlySpan escapedPropertyName, decimal int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatDecimalLength - 5 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatDecimalLength - 5 - _newLineLength); int minRequired = indent + escapedPropertyName.Length + JsonConstants.MaximumFormatDecimalLength + 4; // 2 quotes for property name, 1 colon, and 1 space - int maxRequired = minRequired + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = minRequired + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Double.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Double.cs index eee0535903cf..4a58e3057ac6 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Double.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Double.cs @@ -283,11 +283,11 @@ private void WriteNumberIndented(ReadOnlySpan escapedPropertyName, double int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatDoubleLength - 5 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatDoubleLength - 5 - _newLineLength); // All ASCII, 2 quotes for property name, 1 colon, and 1 space => escapedPropertyName.Length + JsonConstants.MaximumFormatDoubleLength + 4 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatDoubleLength + 5 + s_newLineLength; + int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatDoubleLength + 5 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -329,10 +329,10 @@ private void WriteNumberIndented(ReadOnlySpan escapedPropertyName, double int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatDoubleLength - 5 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatDoubleLength - 5 - _newLineLength); int minRequired = indent + escapedPropertyName.Length + JsonConstants.MaximumFormatDoubleLength + 4; // 2 quotes for property name, 1 colon, and 1 space - int maxRequired = minRequired + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = minRequired + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Float.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Float.cs index 133c95ece5d8..f3b6b4847f2d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Float.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Float.cs @@ -283,11 +283,11 @@ private void WriteNumberIndented(ReadOnlySpan escapedPropertyName, float v int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatSingleLength - 5 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatSingleLength - 5 - _newLineLength); // All ASCII, 2 quotes for property name, 1 colon, and 1 space => escapedPropertyName.Length + JsonConstants.MaximumFormatSingleLength + 4 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatSingleLength + 5 + s_newLineLength; + int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatSingleLength + 5 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -329,10 +329,10 @@ private void WriteNumberIndented(ReadOnlySpan escapedPropertyName, float v int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatSingleLength - 5 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatSingleLength - 5 - _newLineLength); int minRequired = indent + escapedPropertyName.Length + JsonConstants.MaximumFormatSingleLength + 4; // 2 quotes for property name, 1 colon, and 1 space - int maxRequired = minRequired + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = minRequired + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Guid.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Guid.cs index 1ded7b8f3f6a..004a0d228eea 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Guid.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Guid.cs @@ -287,11 +287,11 @@ private void WriteStringIndented(ReadOnlySpan escapedPropertyName, Guid va int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatGuidLength - 7 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatGuidLength - 7 - _newLineLength); // All ASCII, 2 quotes for property name, 2 quotes for date, 1 colon, and 1 space => escapedPropertyName.Length + JsonConstants.MaximumFormatGuidLength + 6 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatGuidLength + 7 + s_newLineLength; + int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatGuidLength + 7 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -337,10 +337,10 @@ private void WriteStringIndented(ReadOnlySpan escapedPropertyName, Guid va int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatGuidLength - 7 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatGuidLength - 7 - _newLineLength); int minRequired = indent + escapedPropertyName.Length + JsonConstants.MaximumFormatGuidLength + 6; // 2 quotes for property name, 2 quotes for date, 1 colon, and 1 space - int maxRequired = minRequired + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = minRequired + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Helpers.cs index c09aaa40c8a2..95a0a6745164 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Helpers.cs @@ -91,10 +91,10 @@ private void WritePropertyNameIndented(ReadOnlySpan escapedPropertyName, b int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - 6 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - 6 - _newLineLength); int minRequired = indent + escapedPropertyName.Length + 5; // 2 quotes, 1 colon, 1 space, and 1 start token - int maxRequired = minRequired + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = minRequired + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { @@ -163,11 +163,11 @@ private void WritePropertyNameIndented(ReadOnlySpan escapedPropertyName, b int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - 6 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - 6 - _newLineLength); // All ASCII, 2 quotes, 1 colon, 1 space, and 1 start token => indent + escapedPropertyName.Length + 5 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + 6 + s_newLineLength; + int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + 6 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Literal.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Literal.cs index aff0da471b1a..bf41ed2e5264 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Literal.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Literal.cs @@ -430,11 +430,11 @@ private void WriteLiteralIndented(ReadOnlySpan escapedPropertyName, ReadOn Debug.Assert(indent <= _indentLength * _options.MaxDepth); Debug.Assert(value.Length <= JsonConstants.MaxUnescapedTokenSize); - Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - value.Length - 5 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - value.Length - 5 - _newLineLength); // All ASCII, 2 quotes for property name, 1 colon, and 1 space => escapedPropertyName.Length + value.Length + 4 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + value.Length + 5 + s_newLineLength; + int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + value.Length + 5 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -476,10 +476,10 @@ private void WriteLiteralIndented(ReadOnlySpan escapedPropertyName, ReadOn Debug.Assert(indent <= _indentLength * _options.MaxDepth); Debug.Assert(value.Length <= JsonConstants.MaxUnescapedTokenSize); - Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - value.Length - 5 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - value.Length - 5 - _newLineLength); int minRequired = indent + escapedPropertyName.Length + value.Length + 4; // 2 quotes for property name, 1 colon, and 1 space - int maxRequired = minRequired + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = minRequired + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.SignedNumber.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.SignedNumber.cs index 82694f738cc7..633d0e1c86aa 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.SignedNumber.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.SignedNumber.cs @@ -355,11 +355,11 @@ private void WriteNumberIndented(ReadOnlySpan escapedPropertyName, long va int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatInt64Length - 5 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatInt64Length - 5 - _newLineLength); // All ASCII, 2 quotes for property name, 1 colon, and 1 space => escapedPropertyName.Length + JsonConstants.MaximumFormatInt64Length + 4 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatInt64Length + 5 + s_newLineLength; + int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatInt64Length + 5 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -401,10 +401,10 @@ private void WriteNumberIndented(ReadOnlySpan escapedPropertyName, long va int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatInt64Length - 5 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatInt64Length - 5 - _newLineLength); int minRequired = indent + escapedPropertyName.Length + JsonConstants.MaximumFormatInt64Length + 4; // 2 quotes for property name, 1 colon, and 1 space - int maxRequired = minRequired + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = minRequired + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs index 16629ea424f4..3c4179d5906e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs @@ -190,11 +190,11 @@ private void WriteStringIndentedPropertyName(ReadOnlySpan escapedPropertyN Debug.Assert(indent <= _indentLength * _options.MaxDepth); Debug.Assert(escapedPropertyName.Length <= JsonConstants.MaxEscapedTokenSize); - Debug.Assert(escapedPropertyName.Length < (int.MaxValue - 5 - indent - s_newLineLength) / JsonConstants.MaxExpansionFactorWhileTranscoding); + Debug.Assert(escapedPropertyName.Length < (int.MaxValue - 5 - indent - _newLineLength) / JsonConstants.MaxExpansionFactorWhileTranscoding); // All ASCII, 2 quotes for property name, 1 colon, and 1 space => escapedPropertyName.Length + 4 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + 5 + s_newLineLength; + int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + 5 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -378,10 +378,10 @@ private void WriteStringIndentedPropertyName(ReadOnlySpan escapedPropertyN Debug.Assert(indent <= _indentLength * _options.MaxDepth); Debug.Assert(escapedPropertyName.Length <= JsonConstants.MaxEscapedTokenSize); - Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - 5 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - 5 - _newLineLength); int minRequired = indent + escapedPropertyName.Length + 4; // 2 quotes for property name, 1 colon, and 1 space - int maxRequired = minRequired + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = minRequired + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { @@ -1516,11 +1516,11 @@ private void WriteStringIndented(ReadOnlySpan escapedPropertyName, ReadOnl Debug.Assert(indent <= _indentLength * _options.MaxDepth); Debug.Assert(escapedValue.Length <= JsonConstants.MaxEscapedTokenSize); - Debug.Assert(escapedPropertyName.Length < ((int.MaxValue - 7 - indent - s_newLineLength) / JsonConstants.MaxExpansionFactorWhileTranscoding) - escapedValue.Length); + Debug.Assert(escapedPropertyName.Length < ((int.MaxValue - 7 - indent - _newLineLength) / JsonConstants.MaxExpansionFactorWhileTranscoding) - escapedValue.Length); // All ASCII, 2 quotes for property name, 2 quotes for value, 1 colon, and 1 space => escapedPropertyName.Length + escapedValue.Length + 6 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + ((escapedPropertyName.Length + escapedValue.Length) * JsonConstants.MaxExpansionFactorWhileTranscoding) + 7 + s_newLineLength; + int maxRequired = indent + ((escapedPropertyName.Length + escapedValue.Length) * JsonConstants.MaxExpansionFactorWhileTranscoding) + 7 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -1566,10 +1566,10 @@ private void WriteStringIndented(ReadOnlySpan escapedPropertyName, ReadOnl Debug.Assert(indent <= _indentLength * _options.MaxDepth); Debug.Assert(escapedValue.Length <= JsonConstants.MaxEscapedTokenSize); - Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - escapedValue.Length - 7 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - escapedValue.Length - 7 - _newLineLength); int minRequired = indent + escapedPropertyName.Length + escapedValue.Length + 6; // 2 quotes for property name, 2 quotes for value, 1 colon, and 1 space - int maxRequired = minRequired + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = minRequired + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { @@ -1617,11 +1617,11 @@ private void WriteStringIndented(ReadOnlySpan escapedPropertyName, ReadOnl Debug.Assert(indent <= _indentLength * _options.MaxDepth); Debug.Assert(escapedValue.Length <= JsonConstants.MaxEscapedTokenSize); - Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - escapedValue.Length - 7 - indent - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - escapedValue.Length - 7 - indent - _newLineLength); // All ASCII, 2 quotes for property name, 2 quotes for value, 1 colon, and 1 space => escapedPropertyName.Length + escapedValue.Length + 6 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + escapedValue.Length + 7 + s_newLineLength; + int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + escapedValue.Length + 7 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -1668,11 +1668,11 @@ private void WriteStringIndented(ReadOnlySpan escapedPropertyName, ReadOnl Debug.Assert(indent <= _indentLength * _options.MaxDepth); Debug.Assert(escapedValue.Length <= JsonConstants.MaxEscapedTokenSize); - Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - escapedValue.Length - 7 - indent - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - escapedValue.Length - 7 - indent - _newLineLength); // All ASCII, 2 quotes for property name, 2 quotes for value, 1 colon, and 1 space => escapedPropertyName.Length + escapedValue.Length + 6 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (escapedValue.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + escapedPropertyName.Length + 7 + s_newLineLength; + int maxRequired = indent + (escapedValue.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + escapedPropertyName.Length + 7 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.UnsignedNumber.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.UnsignedNumber.cs index 37aad4626659..68536e35cc5d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.UnsignedNumber.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.UnsignedNumber.cs @@ -364,11 +364,11 @@ private void WriteNumberIndented(ReadOnlySpan escapedPropertyName, ulong v int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatUInt64Length - 5 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - JsonConstants.MaximumFormatUInt64Length - 5 - _newLineLength); // All ASCII, 2 quotes for property name, 1 colon, and 1 space => escapedPropertyName.Length + JsonConstants.MaximumFormatUInt64Length + 4 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatUInt64Length + 5 + s_newLineLength; + int maxRequired = indent + (escapedPropertyName.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + JsonConstants.MaximumFormatUInt64Length + 5 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -410,10 +410,10 @@ private void WriteNumberIndented(ReadOnlySpan escapedPropertyName, ulong v int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatUInt64Length - 5 - s_newLineLength); + Debug.Assert(escapedPropertyName.Length < int.MaxValue - indent - JsonConstants.MaximumFormatUInt64Length - 5 - _newLineLength); int minRequired = indent + escapedPropertyName.Length + JsonConstants.MaximumFormatUInt64Length + 4; // 2 quotes for property name, 1 colon, and 1 space - int maxRequired = minRequired + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = minRequired + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Bytes.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Bytes.cs index e4b4a877bbd5..a425049e9c28 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Bytes.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Bytes.cs @@ -94,7 +94,7 @@ private void WriteBase64Indented(ReadOnlySpan bytes) // as a length longer than that would overflow int.MaxValue when Base64 encoded. However, we // also need the indentation + 2 quotes, and optionally a list separate and 1-2 bytes for a new line. // Validate the encoded bytes length won't overflow with all of the length. - int extraSpaceRequired = indent + 3 + s_newLineLength; + int extraSpaceRequired = indent + 3 + _newLineLength; int maxLengthAllowed = int.MaxValue / 4 * 3 - extraSpaceRequired; if (bytes.Length > maxLengthAllowed) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Comment.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Comment.cs index 93f11451f454..aa62396df6c8 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Comment.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Comment.cs @@ -107,11 +107,11 @@ private void WriteCommentIndented(ReadOnlySpan value) int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(value.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - 4 - s_newLineLength); + Debug.Assert(value.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - 4 - _newLineLength); // All ASCII, /*...*/ => escapedValue.Length + 4 // Optionally, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (value.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + 4 + s_newLineLength; + int maxRequired = indent + (value.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + 4 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -214,10 +214,10 @@ private void WriteCommentIndented(ReadOnlySpan utf8Value) int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(utf8Value.Length < int.MaxValue - indent - 4 - s_newLineLength); + Debug.Assert(utf8Value.Length < int.MaxValue - indent - 4 - _newLineLength); int minRequired = indent + utf8Value.Length + 4; // /*...*/ - int maxRequired = minRequired + s_newLineLength; // Optionally, 1-2 bytes for new line + int maxRequired = minRequired + _newLineLength; // Optionally, 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.DateTime.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.DateTime.cs index ad8a887cdf55..5366496ca74e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.DateTime.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.DateTime.cs @@ -69,7 +69,7 @@ private void WriteStringValueIndented(DateTime value) Debug.Assert(indent <= _indentLength * _options.MaxDepth); // 2 quotes, and optionally, 1 list separator and 1-2 bytes for new line - int maxRequired = indent + JsonConstants.MaximumFormatDateTimeOffsetLength + 3 + s_newLineLength; + int maxRequired = indent + JsonConstants.MaximumFormatDateTimeOffsetLength + 3 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.DateTimeOffset.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.DateTimeOffset.cs index 1ee48004f21f..0fa10649ac24 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.DateTimeOffset.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.DateTimeOffset.cs @@ -70,7 +70,7 @@ private void WriteStringValueIndented(DateTimeOffset value) Debug.Assert(indent <= _indentLength * _options.MaxDepth); // 2 quotes, and optionally, 1 list separator and 1-2 bytes for new line - int maxRequired = indent + JsonConstants.MaximumFormatDateTimeOffsetLength + 3 + s_newLineLength; + int maxRequired = indent + JsonConstants.MaximumFormatDateTimeOffsetLength + 3 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Decimal.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Decimal.cs index 35089030c2d4..65bfff3b6c6e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Decimal.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Decimal.cs @@ -65,7 +65,7 @@ private void WriteNumberValueIndented(decimal value) int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - int maxRequired = indent + JsonConstants.MaximumFormatDecimalLength + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = indent + JsonConstants.MaximumFormatDecimalLength + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Double.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Double.cs index b638931ce122..abaa20358cf6 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Double.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Double.cs @@ -69,7 +69,7 @@ private void WriteNumberValueIndented(double value) int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - int maxRequired = indent + JsonConstants.MaximumFormatDoubleLength + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = indent + JsonConstants.MaximumFormatDoubleLength + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { @@ -106,7 +106,7 @@ private static bool TryFormatDouble(double value, Span destination, out in // the .NET Core 3.0 logic of forwarding to the UTF16 formatter and transcoding it back to UTF8, // with some additional changes to remove dependencies on Span APIs which don't exist downlevel. -#if NETCOREAPP +#if NET return Utf8Formatter.TryFormat(value, destination, out bytesWritten); #else string utf16Text = value.ToString(JsonConstants.DoubleFormatString, CultureInfo.InvariantCulture); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Float.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Float.cs index c1755c7c4dc5..c65c92a89c03 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Float.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Float.cs @@ -69,7 +69,7 @@ private void WriteNumberValueIndented(float value) int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - int maxRequired = indent + JsonConstants.MaximumFormatSingleLength + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = indent + JsonConstants.MaximumFormatSingleLength + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { @@ -106,7 +106,7 @@ private static bool TryFormatSingle(float value, Span destination, out int // the .NET Core 3.0 logic of forwarding to the UTF16 formatter and transcoding it back to UTF8, // with some additional changes to remove dependencies on Span APIs which don't exist downlevel. -#if NETCOREAPP +#if NET return Utf8Formatter.TryFormat(value, destination, out bytesWritten); #else string utf16Text = value.ToString(JsonConstants.SingleFormatString, CultureInfo.InvariantCulture); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.FormattedNumber.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.FormattedNumber.cs index f4c902e184af..c2f8bb8ff82a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.FormattedNumber.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.FormattedNumber.cs @@ -69,9 +69,9 @@ private void WriteNumberValueIndented(ReadOnlySpan utf8Value) int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(utf8Value.Length < int.MaxValue - indent - 1 - s_newLineLength); + Debug.Assert(utf8Value.Length < int.MaxValue - indent - 1 - _newLineLength); - int maxRequired = indent + utf8Value.Length + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = indent + utf8Value.Length + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Guid.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Guid.cs index 695cc83e0368..fedbc0959f34 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Guid.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Guid.cs @@ -70,7 +70,7 @@ private void WriteStringValueIndented(Guid value) Debug.Assert(indent <= _indentLength * _options.MaxDepth); // 2 quotes, and optionally, 1 list separator and 1-2 bytes for new line - int maxRequired = indent + JsonConstants.MaximumFormatGuidLength + 3 + s_newLineLength; + int maxRequired = indent + JsonConstants.MaximumFormatGuidLength + 3 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Literal.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Literal.cs index 8c0dee44e785..fdda2ce6837e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Literal.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Literal.cs @@ -89,7 +89,7 @@ private void WriteLiteralIndented(ReadOnlySpan utf8Value) Debug.Assert(indent <= _indentLength * _options.MaxDepth); Debug.Assert(utf8Value.Length <= 5); - int maxRequired = indent + utf8Value.Length + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = indent + utf8Value.Length + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.SignedNumber.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.SignedNumber.cs index b2126de77fb2..85d37a858b9c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.SignedNumber.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.SignedNumber.cs @@ -78,7 +78,7 @@ private void WriteNumberValueIndented(long value) int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - int maxRequired = indent + JsonConstants.MaximumFormatInt64Length + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = indent + JsonConstants.MaximumFormatInt64Length + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.String.cs index 4ede0fc9bce9..5ff4064d2b59 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.String.cs @@ -145,11 +145,11 @@ private void WriteStringIndented(ReadOnlySpan escapedValue) int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedValue.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - 3 - s_newLineLength); + Debug.Assert(escapedValue.Length < (int.MaxValue / JsonConstants.MaxExpansionFactorWhileTranscoding) - indent - 3 - _newLineLength); // All ASCII, 2 quotes => indent + escapedValue.Length + 2 // Optionally, 1 list separator, 1-2 bytes for new line, and up to 3x growth when transcoding - int maxRequired = indent + (escapedValue.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + 3 + s_newLineLength; + int maxRequired = indent + (escapedValue.Length * JsonConstants.MaxExpansionFactorWhileTranscoding) + 3 + _newLineLength; if (_memory.Length - BytesPending < maxRequired) { @@ -292,10 +292,10 @@ private void WriteStringIndented(ReadOnlySpan escapedValue) int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - Debug.Assert(escapedValue.Length < int.MaxValue - indent - 3 - s_newLineLength); + Debug.Assert(escapedValue.Length < int.MaxValue - indent - 3 - _newLineLength); int minRequired = indent + escapedValue.Length + 2; // 2 quotes - int maxRequired = minRequired + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = minRequired + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.UnsignedNumber.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.UnsignedNumber.cs index 82ec4677b222..eaabba59a7a2 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.UnsignedNumber.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.UnsignedNumber.cs @@ -80,7 +80,7 @@ private void WriteNumberValueIndented(ulong value) int indent = Indentation; Debug.Assert(indent <= _indentLength * _options.MaxDepth); - int maxRequired = indent + JsonConstants.MaximumFormatUInt64Length + 1 + s_newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line + int maxRequired = indent + JsonConstants.MaximumFormatUInt64Length + 1 + _newLineLength; // Optionally, 1 list separator and 1-2 bytes for new line if (_memory.Length - BytesPending < maxRequired) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs index 315b7a30b8e2..f357a89d5d2d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs @@ -8,7 +8,7 @@ using System.Threading; using System.Threading.Tasks; -#if !NETCOREAPP +#if !NET using System.Runtime.InteropServices; #endif @@ -34,9 +34,6 @@ namespace System.Text.Json [DebuggerDisplay("{DebuggerDisplay,nq}")] public sealed partial class Utf8JsonWriter : IDisposable, IAsyncDisposable { - // Depending on OS, either '\r\n' OR '\n' - private static readonly int s_newLineLength = Environment.NewLine.Length; - private const int DefaultGrowthSize = 4096; private const int InitialGrowthSize = 256; @@ -62,6 +59,9 @@ public sealed partial class Utf8JsonWriter : IDisposable, IAsyncDisposable private byte _indentByte; private int _indentLength; + // A length of 1 will emit LF for indented writes, a length of 2 will emit CRLF. Other values are invalid. + private int _newLineLength; + /// /// Returns the amount of bytes written by the so far /// that have not yet been flushed to the output and committed. @@ -151,6 +151,9 @@ private void SetOptions(JsonWriterOptions options) _indentByte = (byte)_options.IndentCharacter; _indentLength = options.IndentSize; + Debug.Assert(options.NewLine is "\n" or "\r\n", "Invalid NewLine string."); + _newLineLength = options.NewLine.Length; + if (_options.MaxDepth == 0) { _options.MaxDepth = JsonWriterOptions.DefaultMaxDepth; // If max depth is not set, revert to the default depth. @@ -306,7 +309,7 @@ public void Flush() _arrayBufferWriter.Advance(BytesPending); BytesPending = 0; -#if NETCOREAPP +#if NET _stream.Write(_arrayBufferWriter.WrittenSpan); #else Debug.Assert(_arrayBufferWriter.WrittenMemory.Length == _arrayBufferWriter.WrittenCount); @@ -420,7 +423,7 @@ public async Task FlushAsync(CancellationToken cancellationToken = default) _arrayBufferWriter.Advance(BytesPending); BytesPending = 0; -#if NETCOREAPP +#if NET await _stream.WriteAsync(_arrayBufferWriter.WrittenMemory, cancellationToken).ConfigureAwait(false); #else Debug.Assert(_arrayBufferWriter.WrittenMemory.Length == _arrayBufferWriter.WrittenCount); @@ -1023,8 +1026,9 @@ private void WriteEndIndented(byte token) [MethodImpl(MethodImplOptions.AggressiveInlining)] private void WriteNewLine(Span output) { - // Write '\r\n' OR '\n', depending on OS - if (s_newLineLength == 2) + // Write '\r\n' OR '\n', depending on the configured new line string + Debug.Assert(_newLineLength is 1 or 2, "Invalid new line length."); + if (_newLineLength == 2) { output[BytesPending++] = JsonConstants.CarriageReturn; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriterCache.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriterCache.cs index b0d952803128..bfe92487f01c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriterCache.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriterCache.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers; using System.Diagnostics; namespace System.Text.Json @@ -40,7 +41,7 @@ public static Utf8JsonWriter RentWriterAndBuffer(JsonWriterOptions options, int return writer; } - public static Utf8JsonWriter RentWriter(JsonSerializerOptions options, PooledByteBufferWriter bufferWriter) + public static Utf8JsonWriter RentWriter(JsonSerializerOptions options, IBufferWriter bufferWriter) { ThreadLocalState state = t_threadLocalState ??= new(); Utf8JsonWriter writer; diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs index dfaff9130fa7..4d61a6f8b309 100644 --- a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs +++ b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs @@ -46,7 +46,7 @@ public static IEnumerable GetTestDictionaries() yield return WrapArgs(DateTime.MaxValue, 1, expectedJson: $@"{{""{DateTime.MaxValue:O}"":1}}"); yield return WrapArgs(DateTimeOffset.MaxValue, 1, expectedJson: $@"{{""{DateTimeOffset.MaxValue:O}"":1}}"); yield return WrapArgs(TimeSpan.MaxValue, 1, expectedJson: $@"{{""{TimeSpan.MaxValue}"":1}}"); -#if NET6_0_OR_GREATER +#if NET yield return WrapArgs(DateOnly.MaxValue, 1, expectedJson: $@"{{""{DateOnly.MaxValue:O}"":1}}"); yield return WrapArgs(TimeOnly.MaxValue, 1, expectedJson: $@"{{""{TimeOnly.MaxValue:O}"":1}}"); #endif @@ -66,7 +66,7 @@ public static IEnumerable GetTestDictionaries() yield return WrapArgs(ushort.MaxValue, 1); yield return WrapArgs(uint.MaxValue, 1); yield return WrapArgs(ulong.MaxValue, 1); -#if NETCOREAPP +#if NET yield return WrapArgs(Half.MinValue, 1); yield return WrapArgs(Int128.MinValue, 1); yield return WrapArgs(UInt128.MaxValue, 1); @@ -340,7 +340,7 @@ public async Task TestEscapedValuesOnDeserialize(string escapedPropertyName, obj new object[] { @"\u0042\u0061\u0072\u002c\u0042\u0061\u007a", MyEnumFlags.Bar | MyEnumFlags.Baz, typeof(Dictionary) }, new object[] { @"\u002b", '+', typeof(Dictionary) }, -#if NETCOREAPP +#if NET new object[] { @"\u0033\u002e\u0031\u0032\u0035\u0065\u0034", (Half)3.125e4, typeof(Dictionary) }, new object[] { @"\u002D\u0031\u0037\u0030\u0031\u0034\u0031\u0031\u0038\u0033\u0034\u0036\u0030\u0034\u0036\u0039\u0032\u0033\u0031\u0037\u0033\u0031\u0036\u0038\u0037\u0033\u0030\u0033\u0037\u0031\u0035\u0038\u0038\u0034\u0031\u0030\u0035\u0037\u0032\u0038", diff --git a/src/libraries/System.Text.Json/tests/Common/JsonNumberTestData.cs b/src/libraries/System.Text.Json/tests/Common/JsonNumberTestData.cs index d2d2591ade5f..83cf29458dd0 100644 --- a/src/libraries/System.Text.Json/tests/Common/JsonNumberTestData.cs +++ b/src/libraries/System.Text.Json/tests/Common/JsonNumberTestData.cs @@ -20,7 +20,7 @@ internal class JsonNumberTestData public static List Floats { get; set; } public static List Doubles { get; set; } public static List Decimals { get; set; } -#if NETCOREAPP +#if NET public static List Int128s { get; set; } public static List UInt128s { get; set; } public static List Halfs { get; set; } @@ -37,7 +37,7 @@ internal class JsonNumberTestData public static List NullableFloats { get; set; } public static List NullableDoubles { get; set; } public static List NullableDecimals { get; set; } -#if NETCOREAPP +#if NET public static List NullableInt128s { get; set; } public static List NullableUInt128s { get; set; } public static List NullableHalfs { get; set; } @@ -247,7 +247,7 @@ static JsonNumberTestData() } #endregion -#if NETCOREAPP +#if NET #region generate Int128s Int128s = new List { @@ -381,7 +381,7 @@ static JsonNumberTestData() NullableFloats = new List(Floats.Select(num => (float?)num)); NullableDoubles = new List(Doubles.Select(num => (double?)num)); NullableDecimals = new List(Decimals.Select(num => (decimal?)num)); -#if NETCOREAPP +#if NET NullableInt128s = new List(Int128s.Select(num => (Int128?)num)); NullableUInt128s = new List(UInt128s.Select(num => (UInt128?)num)); NullableHalfs = new List(Halfs.Select(num => (Half?)num)); diff --git a/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs b/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs index f641a4a31290..8d96c4e79c43 100644 --- a/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs +++ b/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs @@ -15,7 +15,7 @@ namespace System.Text.Json { internal static partial class JsonTestHelper { -#if NETCOREAPP +#if NET public const string DoubleFormatString = null; public const string SingleFormatString = null; #else @@ -23,7 +23,7 @@ internal static partial class JsonTestHelper public const string SingleFormatString = "G9"; #endif -#if NETCOREAPP +#if NET public static Half NextHalf(Random random) { double mantissa = (random.NextDouble() * 2.0) - 1.0; diff --git a/src/libraries/System.Text.Json/tests/Common/NumberHandlingTests.cs b/src/libraries/System.Text.Json/tests/Common/NumberHandlingTests.cs index 6b16a631576f..833b01114dc6 100644 --- a/src/libraries/System.Text.Json/tests/Common/NumberHandlingTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/NumberHandlingTests.cs @@ -63,7 +63,7 @@ public async Task Number_AsRootType_RoundTrip() await RunAsRootTypeTest(JsonNumberTestData.Floats); await RunAsRootTypeTest(JsonNumberTestData.Doubles); await RunAsRootTypeTest(JsonNumberTestData.Decimals); -#if NETCOREAPP +#if NET await RunAsRootTypeTest(JsonNumberTestData.Int128s); await RunAsRootTypeTest(JsonNumberTestData.UInt128s); await RunAsRootTypeTest(JsonNumberTestData.Halfs); @@ -79,7 +79,7 @@ public async Task Number_AsRootType_RoundTrip() await RunAsRootTypeTest(JsonNumberTestData.NullableFloats); await RunAsRootTypeTest(JsonNumberTestData.NullableDoubles); await RunAsRootTypeTest(JsonNumberTestData.NullableDecimals); -#if NETCOREAPP +#if NET await RunAsRootTypeTest(JsonNumberTestData.NullableInt128s); await RunAsRootTypeTest(JsonNumberTestData.NullableUInt128s); await RunAsRootTypeTest(JsonNumberTestData.NullableHalfs); @@ -383,7 +383,7 @@ public async Task Number_AsCollectionElement_RoundTrip() await RunAsCollectionElementTest(JsonNumberTestData.Floats); await RunAsCollectionElementTest(JsonNumberTestData.Doubles); await RunAsCollectionElementTest(JsonNumberTestData.Decimals); -#if NETCOREAPP +#if NET await RunAsCollectionElementTest(JsonNumberTestData.Int128s); await RunAsCollectionElementTest(JsonNumberTestData.UInt128s); await RunAsCollectionElementTest(JsonNumberTestData.Halfs); @@ -403,7 +403,7 @@ public async Task Number_AsCollectionElement_RoundTrip() await RunAsCollectionElementTest(JsonNumberTestData.NullableFloats); await RunAsCollectionElementTest(JsonNumberTestData.NullableDoubles); await RunAsCollectionElementTest(JsonNumberTestData.NullableDecimals); -#if NETCOREAPP +#if NET await RunAsCollectionElementTest(JsonNumberTestData.NullableInt128s); await RunAsCollectionElementTest(JsonNumberTestData.NullableUInt128s); await RunAsCollectionElementTest(JsonNumberTestData.NullableHalfs); @@ -781,7 +781,7 @@ public async Task FloatingPointConstants_Pass() async Task PerformFloatingPointSerialization(string testString) { string testStringAsJson = $@"""{testString}"""; -#if NETCOREAPP +#if NET string testJson = @$"{{""HalfNumber"":{testStringAsJson},""FloatNumber"":{testStringAsJson},""DoubleNumber"":{testStringAsJson}}}"; #else string testJson = @$"{{""FloatNumber"":{testStringAsJson},""DoubleNumber"":{testStringAsJson}}}"; @@ -792,14 +792,14 @@ async Task PerformFloatingPointSerialization(string testString) { case "NaN": obj = await Serializer.DeserializeWrapper(testJson, s_optionsAllowFloatConstants); -#if NETCOREAPP +#if NET Assert.Equal(Half.NaN, obj.HalfNumber); #endif Assert.Equal(float.NaN, obj.FloatNumber); Assert.Equal(double.NaN, obj.DoubleNumber); obj = await Serializer.DeserializeWrapper(testJson, s_optionReadFromStr); -#if NETCOREAPP +#if NET Assert.Equal(Half.NaN, obj.HalfNumber); #endif Assert.Equal(float.NaN, obj.FloatNumber); @@ -807,14 +807,14 @@ async Task PerformFloatingPointSerialization(string testString) break; case "Infinity": obj = await Serializer.DeserializeWrapper(testJson, s_optionsAllowFloatConstants); -#if NETCOREAPP +#if NET Assert.Equal(Half.PositiveInfinity, obj.HalfNumber); #endif Assert.Equal(float.PositiveInfinity, obj.FloatNumber); Assert.Equal(double.PositiveInfinity, obj.DoubleNumber); obj = await Serializer.DeserializeWrapper(testJson, s_optionReadFromStr); -#if NETCOREAPP +#if NET Assert.Equal(Half.PositiveInfinity, obj.HalfNumber); #endif Assert.Equal(float.PositiveInfinity, obj.FloatNumber); @@ -822,14 +822,14 @@ async Task PerformFloatingPointSerialization(string testString) break; case "-Infinity": obj = await Serializer.DeserializeWrapper(testJson, s_optionsAllowFloatConstants); -#if NETCOREAPP +#if NET Assert.Equal(Half.NegativeInfinity, obj.HalfNumber); #endif Assert.Equal(float.NegativeInfinity, obj.FloatNumber); Assert.Equal(double.NegativeInfinity, obj.DoubleNumber); obj = await Serializer.DeserializeWrapper(testJson, s_optionReadFromStr); -#if NETCOREAPP +#if NET Assert.Equal(Half.NegativeInfinity, obj.HalfNumber); #endif Assert.Equal(float.NegativeInfinity, obj.FloatNumber); @@ -877,7 +877,7 @@ public async Task FloatingPointConstants_Fail(string testString) { string testStringAsJson = $@"""{testString}"""; string testJson; -#if NETCOREAPP +#if NET testJson = @$"{{""HalfNumber"":{testStringAsJson}}}"; await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(testJson, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(testJson, s_optionReadFromStr)); @@ -894,7 +894,7 @@ public async Task FloatingPointConstants_Fail(string testString) [Fact] public async Task AllowFloatingPointConstants_WriteAsNumber_IfNotConstant() { -#if NETCOREAPP +#if NET Half half = (Half)1; // Not written as "1" Assert.Equal("1", await Serializer.SerializeWrapper(half, s_optionsAllowFloatConstants)); @@ -914,7 +914,7 @@ public async Task AllowFloatingPointConstants_WriteAsNumber_IfNotConstant() [InlineData("-Infinity")] public async Task Unquoted_FloatingPointConstants_Read_Fail(string testString) { -#if NETCOREAPP +#if NET await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(testString, s_optionsAllowFloatConstants)); #endif await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(testString, s_optionsAllowFloatConstants)); @@ -924,7 +924,7 @@ public async Task Unquoted_FloatingPointConstants_Read_Fail(string testString) public struct StructWithNumbers { -#if NETCOREAPP +#if NET public Half HalfNumber { get; set; } #endif public float FloatNumber { get; set; } @@ -985,7 +985,7 @@ public async Task FloatingPointConstants_IncompatibleNumber() await AssertFloatingPointIncompatible_Fails(); await AssertFloatingPointIncompatible_Fails(); await AssertFloatingPointIncompatible_Fails(); -#if NETCOREAPP +#if NET await AssertFloatingPointIncompatible_Fails(); await AssertFloatingPointIncompatible_Fails(); await AssertFloatingPointIncompatible_Fails(); @@ -1031,7 +1031,7 @@ public async Task UnsupportedFormats() await AssertUnsupportedFormatThrows(); await AssertUnsupportedFormatThrows(); await AssertUnsupportedFormatThrows(); -#if NETCOREAPP +#if NET await AssertUnsupportedFormatThrows(); await AssertUnsupportedFormatThrows(); await AssertUnsupportedFormatThrows(); @@ -1058,7 +1058,7 @@ private async Task AssertUnsupportedFormatThrows() } } -#if NETCOREAPP +#if NET [Fact] public async Task InvalidNumberFormatThrows() { @@ -1103,7 +1103,7 @@ public async Task EscapingTest() await PerformEscapingTest(JsonNumberTestData.Floats, options); await PerformEscapingTest(JsonNumberTestData.Doubles, options); await PerformEscapingTest(JsonNumberTestData.Decimals, options); -#if NETCOREAPP +#if NET await PerformEscapingTest(JsonNumberTestData.Int128s, options); await PerformEscapingTest(JsonNumberTestData.UInt128s, options); await PerformEscapingTest(JsonNumberTestData.Halfs, options); @@ -1180,7 +1180,7 @@ public async Task Number_RoundtripNull() await Perform_Number_RoundTripNull_Test(); await Perform_Number_RoundTripNull_Test(); await Perform_Number_RoundTripNull_Test(); -#if NETCOREAPP +#if NET await Perform_Number_RoundTripNull_Test(); await Perform_Number_RoundTripNull_Test(); await Perform_Number_RoundTripNull_Test(); @@ -1210,7 +1210,7 @@ public async Task NullableNumber_RoundtripNull() await Perform_NullableNumber_RoundTripNull_Test(); await Perform_NullableNumber_RoundTripNull_Test(); await Perform_NullableNumber_RoundTripNull_Test(); -#if NETCOREAPP +#if NET await Perform_NullableNumber_RoundTripNull_Test(); await Perform_NullableNumber_RoundTripNull_Test(); await Perform_NullableNumber_RoundTripNull_Test(); @@ -1243,7 +1243,7 @@ public async Task Disallow_ArbritaryStrings_On_AllowFloatingPointConstants() await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); -#if NETCOREAPP +#if NET await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); @@ -1259,7 +1259,7 @@ public async Task Disallow_ArbritaryStrings_On_AllowFloatingPointConstants() await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); -#if NETCOREAPP +#if NET await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json, s_optionsAllowFloatConstants)); diff --git a/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.cs b/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.cs index 9f8af715fdb8..92c12b1dfc44 100644 --- a/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.cs +++ b/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.cs @@ -1907,7 +1907,7 @@ public override void WriteAsPropertyName(Utf8JsonWriter writer, int value, JsonS public static class ReflectionExtensions { -#if NET6_0_OR_GREATER +#if NET [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] public static Type WithConstructors( [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] diff --git a/src/libraries/System.Text.Json/tests/Common/Utf8MemoryStream.cs b/src/libraries/System.Text.Json/tests/Common/Utf8MemoryStream.cs index 2904d744aa94..c28b5bb6c112 100644 --- a/src/libraries/System.Text.Json/tests/Common/Utf8MemoryStream.cs +++ b/src/libraries/System.Text.Json/tests/Common/Utf8MemoryStream.cs @@ -20,7 +20,7 @@ public Utf8MemoryStream(string text) : base(Encoding.UTF8.GetBytes(text)) { } -#if NETCOREAPP +#if NET public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) => base.WriteAsync(buffer, _ignoreCancellationTokenOnWriteAsync ? default : cancellationToken); #endif diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs index 182981002b74..a26c22e1dde2 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs @@ -38,7 +38,7 @@ public interface ITestContext public JsonTypeInfo JsonElement { get; } public JsonTypeInfo ClassWithEnumAndNullable { get; } public JsonTypeInfo ClassWithNullableProperties { get; } -#if NETCOREAPP +#if NET public JsonTypeInfo ClassWithDateOnlyAndTimeOnlyValues { get; } #endif public JsonTypeInfo ClassWithCustomConverter { get; } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSourceGenerationOptionsTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSourceGenerationOptionsTests.cs index 0b24bf6ef676..74aee9393a2f 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSourceGenerationOptionsTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSourceGenerationOptionsTests.cs @@ -71,6 +71,7 @@ public static void ContextWithAllOptionsSet_GeneratesExpectedOptions() IgnoreReadOnlyProperties = true, IncludeFields = true, MaxDepth = 1024, + NewLine = "\n", NumberHandling = JsonNumberHandling.WriteAsString, PreferredObjectCreationHandling = JsonObjectCreationHandling.Replace, PropertyNameCaseInsensitive = true, @@ -101,6 +102,7 @@ public static void ContextWithAllOptionsSet_GeneratesExpectedOptions() IgnoreReadOnlyProperties = true, IncludeFields = true, MaxDepth = 1024, + NewLine = "\n", NumberHandling = JsonNumberHandling.WriteAsString, PreferredObjectCreationHandling = JsonObjectCreationHandling.Replace, PropertyNameCaseInsensitive = true, diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs index 308a6b8a1046..2db01d53c6eb 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs @@ -34,7 +34,7 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(JsonElement))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties))] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(RealWorldContextTests.ClassWithDateOnlyAndTimeOnlyValues))] #endif [JsonSerializable(typeof(ClassWithCustomConverter))] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs index 10e394518cdf..7c99a9f7ec4b 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs @@ -33,7 +33,7 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(JsonElement), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties), GenerationMode = JsonSourceGenerationMode.Metadata)] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(RealWorldContextTests.ClassWithDateOnlyAndTimeOnlyValues), GenerationMode = JsonSourceGenerationMode.Metadata)] #endif [JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata)] @@ -137,7 +137,7 @@ public override void EnsureFastPathGeneratedAsExpected() [JsonSerializable(typeof(JsonElement))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties))] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(RealWorldContextTests.ClassWithDateOnlyAndTimeOnlyValues))] #endif [JsonSerializable(typeof(ClassWithCustomConverter))] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs index 529bd598b6ea..d2ef2350092b 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs @@ -34,7 +34,7 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(JsonElement), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(RealWorldContextTests.ClassWithDateOnlyAndTimeOnlyValues), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] #endif [JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs index 00ce5d49d451..152b716d2aaf 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs @@ -893,7 +893,7 @@ void RunTest(ClassWithNullableProperties expected) } } -#if NETCOREAPP +#if NET [Fact] public virtual void ClassWithDateOnlyAndTimeOnlyValues_Roundtrip() { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NumberHandlingTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NumberHandlingTests.cs index 0fdcf44a0e88..9b5ae831bc43 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NumberHandlingTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NumberHandlingTests.cs @@ -244,7 +244,7 @@ public NumberHandlingTests_Metadata() [JsonSerializable(typeof(List))] [JsonSerializable(typeof(Queue))] [JsonSerializable(typeof(ImmutableList))] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(Int128))] [JsonSerializable(typeof(Int128[]))] [JsonSerializable(typeof(ConcurrentQueue))] @@ -694,7 +694,7 @@ public NumberHandlingTests_Default() [JsonSerializable(typeof(List))] [JsonSerializable(typeof(List))] [JsonSerializable(typeof(List))] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(Int128))] [JsonSerializable(typeof(Int128[]))] [JsonSerializable(typeof(ConcurrentQueue))] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs index 162a8b12bd7e..937117a84b7d 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs @@ -35,7 +35,7 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(JsonElement))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties))] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(RealWorldContextTests.ClassWithDateOnlyAndTimeOnlyValues))] #endif [JsonSerializable(typeof(ClassWithCustomConverter))] @@ -88,7 +88,7 @@ internal partial class SerializationContext : JsonSerializerContext, ITestContex [JsonSerializable(typeof(JsonElement), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties), GenerationMode = JsonSourceGenerationMode.Serialization)] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(RealWorldContextTests.ClassWithDateOnlyAndTimeOnlyValues), GenerationMode = JsonSourceGenerationMode.Serialization)] #endif [JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] @@ -144,7 +144,7 @@ internal partial class SerializationWithPerTypeAttributeContext : JsonSerializer [JsonSerializable(typeof(JsonElement), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties), GenerationMode = JsonSourceGenerationMode.Serialization)] -#if NETCOREAPP +#if NET [JsonSerializable(typeof(RealWorldContextTests.ClassWithDateOnlyAndTimeOnlyValues), GenerationMode = JsonSourceGenerationMode.Serialization)] #endif [JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] @@ -482,7 +482,7 @@ void RunTest(ClassWithNullableProperties expected) } } -#if NETCOREAPP +#if NET [Fact] public override void ClassWithDateOnlyAndTimeOnlyValues_Roundtrip() { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/CompilationHelper.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/CompilationHelper.cs index 09daf5795dab..7f56065297f1 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/CompilationHelper.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/CompilationHelper.cs @@ -46,7 +46,7 @@ public static CSharpParseOptions CreateParseOptions( documentationMode: documentationMode ?? DocumentationMode.Parse); } -#if NETCOREAPP +#if NET private static readonly Assembly systemRuntimeAssembly = Assembly.Load(new AssemblyName("System.Runtime")); #endif @@ -68,7 +68,7 @@ public static Compilation CreateCompilation( MetadataReference.CreateFromFile(typeof(GeneratedCodeAttribute).Assembly.Location), MetadataReference.CreateFromFile(typeof(ReadOnlySpan<>).Assembly.Location), MetadataReference.CreateFromFile(typeof(Console).Assembly.Location), -#if NETCOREAPP +#if NET MetadataReference.CreateFromFile(typeof(LinkedList<>).Assembly.Location), MetadataReference.CreateFromFile(systemRuntimeAssembly.Location), #else @@ -94,7 +94,7 @@ public static Compilation CreateCompilation( SyntaxTree[] syntaxTrees = new[] { CSharpSyntaxTree.ParseText(source, parseOptions), -#if !NETCOREAPP +#if !NET CSharpSyntaxTree.ParseText(NetfxPolyfillAttributes, parseOptions), #endif }; @@ -169,7 +169,7 @@ public static byte[] CreateAssemblyImage(Compilation compilation) return ms.ToArray(); } -#if !NETCOREAPP +#if !NET private const string NetfxPolyfillAttributes = """ namespace System.Runtime.CompilerServices { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs index e2f08b988441..0143e7dd1c41 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs @@ -711,7 +711,7 @@ public class NestedGenericClass [InlineData("public ref partial struct MyGenericRefStruct")] [InlineData("public readonly partial struct MyReadOnlyStruct")] [InlineData("public readonly ref partial struct MyReadOnlyRefStruct")] -#if ROSLYN4_0_OR_GREATER && NETCOREAPP +#if ROSLYN4_0_OR_GREATER && NET [InlineData("public partial record MyRecord(int x)", LanguageVersion.CSharp10)] [InlineData("public partial record struct MyRecordStruct(int x)", LanguageVersion.CSharp10)] #endif @@ -771,7 +771,7 @@ internal partial class JsonContext : JsonSerializerContext CompilationHelper.RunJsonSourceGenerator(compilation); } -#if ROSLYN4_4_OR_GREATER && NETCOREAPP +#if ROSLYN4_4_OR_GREATER && NET [Fact] public void ShadowedMemberInitializers() { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/AssemblyInfo.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/AssemblyInfo.cs new file mode 100644 index 000000000000..68af8051230a --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/AssemblyInfo.cs @@ -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. + +using System; +using Xunit; + +[assembly: ActiveIssue("Interpreter with debug runtime can be very slow", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoInterpreter), nameof(PlatformDetection.IsDebugRuntime))] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/ILLink.Descriptors.xml b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/ILLink.Descriptors.xml new file mode 100644 index 000000000000..2c692431c3ac --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/ILLink.Descriptors.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonArrayTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonArrayTests.cs index ef5170395815..3b8a7b8c4b6b 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonArrayTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonArrayTests.cs @@ -12,6 +12,25 @@ namespace System.Text.Json.Nodes.Tests { public static class JsonArrayTests { + [Fact] + public static void ParamsContructors() + { + JsonArray expectedArray = [41, 42, 43]; + JsonNodeOptions options = new JsonNodeOptions { PropertyNameCaseInsensitive = true }; + + Verify(new JsonArray(new JsonNode[] { 41, 42, 43 }), null); + Verify(new JsonArray((ReadOnlySpan)new JsonNode[] { 41, 42, 43 }), null); + Verify(new JsonArray(options, new JsonNode[] { 41, 42, 43 }), options); + Verify(new JsonArray(options, (ReadOnlySpan)new JsonNode[] { 41, 42, 43 }), options); + + void Verify(JsonArray jsonArray, JsonNodeOptions? expectedOptions) + { + Assert.Equal(expectedArray.Count, jsonArray.Count); + JsonNodeTests.AssertDeepEqual(expectedArray, jsonArray); + Assert.Equal(expectedOptions, jsonArray.Options); + } + } + [Fact] public static void FromElement() { @@ -34,7 +53,7 @@ public static void FromElement() public static void FromElement_WrongNodeTypeThrows(string json) { using (JsonDocument document = JsonDocument.Parse(json)) - Assert.Throws(() => JsonArray.Create(document.RootElement)); + Assert.Throws(() => JsonArray.Create(document.RootElement)); } [Fact] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonTestHelper.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonTestHelper.cs index 3083d0bed99a..adaff17da693 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonTestHelper.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonTestHelper.cs @@ -754,7 +754,7 @@ public static TException AssertThrows(ref Utf8JsonReader json, Asser throw ex is null ? ThrowsException.ForNoException(typeof(TException)) : ThrowsException.ForIncorrectExceptionType(typeof(TException), ex); } -#if NETCOREAPP +#if NET // This is needed due to the fact that git might normalize line endings when checking-out files public static string NormalizeLineEndings(this string value) => value.ReplaceLineEndings(); #else diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonWriterOptionsTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonWriterOptionsTests.cs index 127ca9601150..5c742d6294b6 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonWriterOptionsTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonWriterOptionsTests.cs @@ -19,6 +19,7 @@ public static void JsonWriterOptionsDefaultCtor() IndentSize = 2, SkipValidation = false, MaxDepth = 0, + NewLine = Environment.NewLine, }; Assert.Equal(expectedOption, options); } @@ -35,16 +36,17 @@ public static void JsonWriterOptionsCtor() IndentSize = 2, SkipValidation = false, MaxDepth = 0, + NewLine = Environment.NewLine, }; Assert.Equal(expectedOption, options); } [Theory] - [InlineData(true, '\t', 1, true, 0)] - [InlineData(true, ' ', 127, false, 1)] - [InlineData(false, ' ', 0, true, 1024)] - [InlineData(false, ' ', 4, false, 1024 * 1024)] - public static void JsonWriterOptions(bool indented, char indentCharacter, int indentSize, bool skipValidation, int maxDepth) + [InlineData(true, '\t', 1, true, 0, "\n")] + [InlineData(true, ' ', 127, false, 1, "\r\n")] + [InlineData(false, ' ', 0, true, 1024, "\n")] + [InlineData(false, ' ', 4, false, 1024 * 1024, "\r\n")] + public static void JsonWriterOptions(bool indented, char indentCharacter, int indentSize, bool skipValidation, int maxDepth, string newLine) { var options = new JsonWriterOptions(); options.Indented = indented; @@ -52,6 +54,7 @@ public static void JsonWriterOptions(bool indented, char indentCharacter, int in options.IndentSize = indentSize; options.SkipValidation = skipValidation; options.MaxDepth = maxDepth; + options.NewLine = newLine; var expectedOption = new JsonWriterOptions { @@ -60,16 +63,17 @@ public static void JsonWriterOptions(bool indented, char indentCharacter, int in IndentSize = indentSize, SkipValidation = skipValidation, MaxDepth = maxDepth, + NewLine = newLine, }; Assert.Equal(expectedOption, options); } [Theory] - [InlineData(true, '\t', 1, true, 0)] - [InlineData(true, ' ', 127, false, 1)] - [InlineData(false, ' ', 0, true, 1024)] - [InlineData(false, ' ', 4, false, 1024 * 1024)] - public static void JsonWriterOptions_Properties(bool indented, char indentCharacter, int indentSize, bool skipValidation, int maxDepth) + [InlineData(true, '\t', 1, true, 0, "\n")] + [InlineData(true, ' ', 127, false, 1, "\r\n")] + [InlineData(false, ' ', 0, true, 1024, "\n")] + [InlineData(false, ' ', 4, false, 1024 * 1024, "\r\n")] + public static void JsonWriterOptions_Properties(bool indented, char indentCharacter, int indentSize, bool skipValidation, int maxDepth, string newLine) { var options = new JsonWriterOptions(); options.Indented = indented; @@ -77,12 +81,14 @@ public static void JsonWriterOptions_Properties(bool indented, char indentCharac options.IndentSize = indentSize; options.SkipValidation = skipValidation; options.MaxDepth = maxDepth; + options.NewLine = newLine; Assert.Equal(indented, options.Indented); Assert.Equal(indentCharacter, options.IndentCharacter); Assert.Equal(indentSize, options.IndentSize); Assert.Equal(skipValidation, options.SkipValidation); Assert.Equal(maxDepth, options.MaxDepth); + Assert.Equal(newLine, options.NewLine); } [Fact] @@ -95,6 +101,7 @@ public static void JsonWriterOptions_DefaultValues() Assert.Equal(2, options.IndentSize); Assert.False(options.SkipValidation); Assert.Equal(0, options.MaxDepth); + Assert.Equal(Environment.NewLine, options.NewLine); } [Fact] @@ -123,6 +130,10 @@ public static void JsonWriterOptions_MultipleValues() options.MaxDepth = defaultOptions.MaxDepth; Assert.Equal(defaultOptions.MaxDepth, options.MaxDepth); + options.NewLine = Environment.NewLine.Length == 1 ? "\r\n" : "\n"; + options.NewLine = defaultOptions.NewLine; + Assert.Equal(defaultOptions.NewLine, options.NewLine); + Assert.Equal(defaultOptions, options); } @@ -157,5 +168,30 @@ public static void JsonWriterOptions_IndentSize_OutOfRange(int size) var options = new JsonWriterOptions(); Assert.Throws(() => options.IndentSize = size); } + + [Theory] + [InlineData("")] + [InlineData(" ")] + [InlineData("\r")] + [InlineData("\n\n")] + [InlineData("\r\n\r\n")] + [InlineData("0")] + [InlineData("a")] + [InlineData("foo")] + [InlineData("$")] + [InlineData(".")] + [InlineData("\u03b1")] + public static void JsonWriterOptions_NewLine_InvalidNewLine(string value) + { + var options = new JsonWriterOptions(); + Assert.Throws(() => options.NewLine = value); + } + + [Fact] + public static void JsonWriterOptions_NewLine_Null_Throws() + { + var options = new JsonWriterOptions(); + Assert.Throws(() => options.NewLine = null); + } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CacheTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CacheTests.cs index 877c44d183a1..64d96934ed78 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CacheTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CacheTests.cs @@ -367,6 +367,7 @@ public static void JsonSerializerOptions_EqualityComparer_ChangingAnySettingShou yield return (GetProp(nameof(JsonSerializerOptions.IgnoreReadOnlyFields)), true); yield return (GetProp(nameof(JsonSerializerOptions.IncludeFields)), true); yield return (GetProp(nameof(JsonSerializerOptions.MaxDepth)), 11); + yield return (GetProp(nameof(JsonSerializerOptions.NewLine)), Environment.NewLine.Length is 1 ? "\r\n" : "\n"); yield return (GetProp(nameof(JsonSerializerOptions.PropertyNamingPolicy)), JsonNamingPolicy.CamelCase); yield return (GetProp(nameof(JsonSerializerOptions.PropertyNameCaseInsensitive)), true); yield return (GetProp(nameof(JsonSerializerOptions.ReadCommentHandling)), JsonCommentHandling.Skip); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests.cs index 3b3d3ac1942d..73c4ed6f661c 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests.cs @@ -24,4 +24,9 @@ public sealed partial class CollectionTestsDynamic_SyncStream : CollectionTests { public CollectionTestsDynamic_SyncStream() : base(JsonSerializerWrapper.SyncStreamSerializer) { } } + + public sealed partial class CollectionTestsDynamic_Pipe : CollectionTests + { + public CollectionTestsDynamic_Pipe() : base(JsonSerializerWrapper.AsyncPipeSerializer) { } + } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ConstructorTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ConstructorTests.cs index 7808e5b109b4..ca5c31afc1b8 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ConstructorTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ConstructorTests.cs @@ -27,4 +27,10 @@ public class ConstructorTests_Span : ConstructorTests public ConstructorTests_Span() : base(JsonSerializerWrapper.SpanSerializer) { } } + + public class ConstructorTests_Pipe : ConstructorTests + { + public ConstructorTests_Pipe() + : base(JsonSerializerWrapper.AsyncPipeSerializer) { } + } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.Tests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.Tests.cs index 69c53e91e37d..3eef5a856aee 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.Tests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.Dynamic.Sample.Tests.cs @@ -59,7 +59,7 @@ public static void VerifyPrimitives() Assert.IsType(obj); double dbl = (double)obj; -#if !NETCOREAPP +#if !NET string temp = dbl.ToString(System.Globalization.CultureInfo.InvariantCulture); // The reader uses "G17" format which causes temp to be 4.2000000000000002 in this case. dbl = double.Parse(temp, System.Globalization.CultureInfo.InvariantCulture); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/InvalidTypeTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/InvalidTypeTests.cs index 91ca5c015a64..d4ea4d2f594c 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/InvalidTypeTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/InvalidTypeTests.cs @@ -37,6 +37,11 @@ public class InvalidTypeTests_Writer : InvalidTypeTests public InvalidTypeTests_Writer() : base(JsonSerializerWrapper.ReaderWriterSerializer) { } } + public class InvalidTypeTests_Pipe : InvalidTypeTests + { + public InvalidTypeTests_Pipe() : base(JsonSerializerWrapper.AsyncPipeSerializer) { } + } + public abstract class InvalidTypeTests { private JsonSerializerWrapper Serializer { get; } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonCreationHandlingTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonCreationHandlingTests.cs index 5a669bb5b2f9..573638913ae3 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonCreationHandlingTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonCreationHandlingTests.cs @@ -22,4 +22,9 @@ public sealed class JsonCreationHandlingTests_SyncStream : JsonCreationHandlingT { public JsonCreationHandlingTests_SyncStream() : base(JsonSerializerWrapper.SyncStreamSerializer) { } } + + public sealed class JsonCreationHandlingTests_Pipe : JsonCreationHandlingTests + { + public JsonCreationHandlingTests_Pipe() : base(JsonSerializerWrapper.AsyncPipeSerializer) { } + } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerApiValidation.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerApiValidation.cs index 1057e6a89006..1ed08df56d62 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerApiValidation.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerApiValidation.cs @@ -50,6 +50,11 @@ public class JsonSerializerApiValidation_Node : JsonSerializerApiValidation { public JsonSerializerApiValidation_Node() : base(JsonSerializerWrapper.NodeSerializer) { } } + + public class JsonSerializerApiValidation_Pipe : JsonSerializerApiValidation + { + public JsonSerializerApiValidation_Pipe() : base(JsonSerializerWrapper.AsyncPipeSerializer) { } + } } /// diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapper.Reflection.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapper.Reflection.cs index d3531970a8e7..a0a8167ec328 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapper.Reflection.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapper.Reflection.cs @@ -1,10 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.IO.Pipelines; using System.Runtime.CompilerServices; using System.Text.Json.Nodes; using System.Text.Json.Serialization.Metadata; @@ -32,6 +34,7 @@ protected JsonSerializerWrapper() public static JsonSerializerWrapper DocumentSerializer { get; } = new DocumentSerializerWrapper(); public static JsonSerializerWrapper ElementSerializer { get; } = new ElementSerializerWrapper(); public static JsonSerializerWrapper NodeSerializer { get; } = new NodeSerializerWrapper(); + public static JsonSerializerWrapper AsyncPipeSerializer { get; } = new AsyncPipelinesSerializerWrapper(); private class SpanSerializerWrapper : JsonSerializerWrapper { @@ -881,5 +884,91 @@ private int ReadExactlyFromSource(byte[] buffer, int offset, int count) public override void SetLength(long value) => throw new NotSupportedException(); public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); } + + // TODO: Deserialize to use PipeReader overloads once implemented + private class AsyncPipelinesSerializerWrapper : JsonSerializerWrapper + { + public override JsonSerializerOptions DefaultOptions => JsonSerializerOptions.Default; + public override bool SupportsNullValueOnDeserialize => true; + + public override async Task DeserializeWrapper(string json, JsonSerializerOptions options = null) + { + return await JsonSerializer.DeserializeAsync(new MemoryStream(Encoding.UTF8.GetBytes(json)), options); + } + public override async Task DeserializeWrapper(string json, Type type, JsonSerializerOptions options = null) + { + return await JsonSerializer.DeserializeAsync(new MemoryStream(Encoding.UTF8.GetBytes(json)), type, options); + } + + public override async Task DeserializeWrapper(string json, JsonTypeInfo jsonTypeInfo) + { + return await JsonSerializer.DeserializeAsync(new MemoryStream(Encoding.UTF8.GetBytes(json)), jsonTypeInfo); + } + + public override async Task DeserializeWrapper(string value, JsonTypeInfo jsonTypeInfo) + { + return await JsonSerializer.DeserializeAsync(new MemoryStream(Encoding.UTF8.GetBytes(value)), jsonTypeInfo); + } + + public override async Task DeserializeWrapper(string json, Type type, JsonSerializerContext context) + { + return await JsonSerializer.DeserializeAsync(new MemoryStream(Encoding.UTF8.GetBytes(json)), type, context); + } + + public override async Task SerializeWrapper(object value, Type inputType, JsonSerializerOptions options = null) + { + Pipe pipe = new Pipe(); + await JsonSerializer.SerializeAsync(pipe.Writer, value, inputType, options); + ReadResult result = await pipe.Reader.ReadAsync(); + + string stringResult = Encoding.UTF8.GetString(result.Buffer.ToArray()); + pipe.Reader.AdvanceTo(result.Buffer.End); + return stringResult; + } + + public override async Task SerializeWrapper(T value, JsonSerializerOptions options = null) + { + Pipe pipe = new Pipe(); + await JsonSerializer.SerializeAsync(pipe.Writer, value, options); + ReadResult result = await pipe.Reader.ReadAsync(); + + string stringResult = Encoding.UTF8.GetString(result.Buffer.ToArray()); + pipe.Reader.AdvanceTo(result.Buffer.End); + return stringResult; + } + + public override async Task SerializeWrapper(object value, Type inputType, JsonSerializerContext context) + { + Pipe pipe = new Pipe(); + await JsonSerializer.SerializeAsync(pipe.Writer, value, inputType, context); + ReadResult result = await pipe.Reader.ReadAsync(); + + string stringResult = Encoding.UTF8.GetString(result.Buffer.ToArray()); + pipe.Reader.AdvanceTo(result.Buffer.End); + return stringResult; + } + + public override async Task SerializeWrapper(T value, JsonTypeInfo jsonTypeInfo) + { + Pipe pipe = new Pipe(); + await JsonSerializer.SerializeAsync(pipe.Writer, value, jsonTypeInfo); + ReadResult result = await pipe.Reader.ReadAsync(); + + string stringResult = Encoding.UTF8.GetString(result.Buffer.ToArray()); + pipe.Reader.AdvanceTo(result.Buffer.End); + return stringResult; + } + + public override async Task SerializeWrapper(object value, JsonTypeInfo jsonTypeInfo) + { + Pipe pipe = new Pipe(); + await JsonSerializer.SerializeAsync(pipe.Writer, value, jsonTypeInfo); + ReadResult result = await pipe.Reader.ReadAsync(); + + string stringResult = Encoding.UTF8.GetString(result.Buffer.ToArray()); + pipe.Reader.AdvanceTo(result.Buffer.End); + return stringResult; + } + } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/JsonTypeInfoResolverTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/JsonTypeInfoResolverTests.cs index 9136555b0fd9..17e1a73c970a 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/JsonTypeInfoResolverTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/JsonTypeInfoResolverTests.cs @@ -7,32 +7,46 @@ namespace System.Text.Json.Serialization.Tests { - public static partial class JsonTypeInfoResolverTests + public class JsonTypeInfoResolverCombineArrayTests : JsonTypeInfoResolverCombineTests { + public override IJsonTypeInfoResolver Combine(params IJsonTypeInfoResolver?[] resolvers) => + JsonTypeInfoResolver.Combine(resolvers); + [Fact] - public static void CombineNullArgument() + public void CombineNullArgument() { IJsonTypeInfoResolver[] resolvers = null; - Assert.Throws(() => JsonTypeInfoResolver.Combine(resolvers)); + Assert.Throws(() => Combine(resolvers)); } + } + + public class JsonTypeInfoResolverCombineSpanTests : JsonTypeInfoResolverCombineTests + { + public override IJsonTypeInfoResolver Combine(params IJsonTypeInfoResolver?[] resolvers) => + JsonTypeInfoResolver.Combine((ReadOnlySpan)resolvers); + } + + public abstract class JsonTypeInfoResolverCombineTests + { + public abstract IJsonTypeInfoResolver Combine(params IJsonTypeInfoResolver?[] resolvers); [Fact] - public static void Combine_ShouldFlattenResolvers() + public void Combine_ShouldFlattenResolvers() { DefaultJsonTypeInfoResolver nonNullResolver1 = new(); DefaultJsonTypeInfoResolver nonNullResolver2 = new(); DefaultJsonTypeInfoResolver nonNullResolver3 = new(); - ValidateCombinations(Array.Empty(), JsonTypeInfoResolver.Combine()); - ValidateCombinations(Array.Empty(), JsonTypeInfoResolver.Combine(new IJsonTypeInfoResolver[] { null })); - ValidateCombinations(Array.Empty(), JsonTypeInfoResolver.Combine(null, null)); - ValidateCombinations(new[] { nonNullResolver1 }, JsonTypeInfoResolver.Combine(nonNullResolver1, null)); - ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2 }, JsonTypeInfoResolver.Combine(nonNullResolver1, nonNullResolver2, null)); - ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2 }, JsonTypeInfoResolver.Combine(nonNullResolver1, null, nonNullResolver2)); - ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2, nonNullResolver3 }, JsonTypeInfoResolver.Combine(JsonTypeInfoResolver.Combine(JsonTypeInfoResolver.Combine(nonNullResolver1), nonNullResolver2), nonNullResolver3)); - ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2, nonNullResolver3 }, JsonTypeInfoResolver.Combine(JsonTypeInfoResolver.Combine(nonNullResolver1, null, nonNullResolver2), nonNullResolver3)); + ValidateCombinations(Array.Empty(), Combine()); + ValidateCombinations(Array.Empty(), Combine(new IJsonTypeInfoResolver[] { null })); + ValidateCombinations(Array.Empty(), Combine(null, null)); + ValidateCombinations(new[] { nonNullResolver1 }, Combine(nonNullResolver1, null)); + ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2 }, Combine(nonNullResolver1, nonNullResolver2, null)); + ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2 }, Combine(nonNullResolver1, null, nonNullResolver2)); + ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2, nonNullResolver3 }, Combine(Combine(Combine(nonNullResolver1), nonNullResolver2), nonNullResolver3)); + ValidateCombinations(new[] { nonNullResolver1, nonNullResolver2, nonNullResolver3 }, Combine(Combine(nonNullResolver1, null, nonNullResolver2), nonNullResolver3)); - static void ValidateCombinations(IJsonTypeInfoResolver[] expectedResolvers, IJsonTypeInfoResolver combinedResolver) + void ValidateCombinations(IJsonTypeInfoResolver[] expectedResolvers, IJsonTypeInfoResolver combinedResolver) { if (expectedResolvers.Length == 1) { @@ -46,9 +60,9 @@ static void ValidateCombinations(IJsonTypeInfoResolver[] expectedResolvers, IJso } [Fact] - public static void CombiningZeroResolversProducesValidResolver() + public void CombiningZeroResolversProducesValidResolver() { - IJsonTypeInfoResolver resolver = JsonTypeInfoResolver.Combine(); + IJsonTypeInfoResolver resolver = Combine(); Assert.NotNull(resolver); // calling twice to make sure we get the same answer @@ -57,7 +71,7 @@ public static void CombiningZeroResolversProducesValidResolver() } [Fact] - public static void CombiningSingleResolverProducesSameAnswersAsInputResolver() + public void CombiningSingleResolverProducesSameAnswersAsInputResolver() { JsonSerializerOptions options = new(); JsonTypeInfo t1 = JsonTypeInfo.CreateJsonTypeInfo(typeof(int), options); @@ -74,7 +88,7 @@ public static void CombiningSingleResolverProducesSameAnswersAsInputResolver() return null; }); - IJsonTypeInfoResolver combined = JsonTypeInfoResolver.Combine(resolver); + IJsonTypeInfoResolver combined = Combine(resolver); Assert.Same(t1, combined.GetTypeInfo(typeof(int), options)); Assert.Same(t2, combined.GetTypeInfo(typeof(uint), options)); @@ -84,7 +98,7 @@ public static void CombiningSingleResolverProducesSameAnswersAsInputResolver() } [Fact] - public static void CombiningUsesAndRespectsAllResolversInOrder() + public void CombiningUsesAndRespectsAllResolversInOrder() { JsonSerializerOptions options = new(); JsonTypeInfo t1 = JsonTypeInfo.CreateJsonTypeInfo(typeof(int), options); @@ -121,7 +135,7 @@ public static void CombiningUsesAndRespectsAllResolversInOrder() return null; }); - IJsonTypeInfoResolver combined = JsonTypeInfoResolver.Combine(r1, r2, r3); + IJsonTypeInfoResolver combined = Combine(r1, r2, r3); resolverId = 1; Assert.Same(t1, combined.GetTypeInfo(typeof(int), options)); @@ -144,7 +158,7 @@ public static void CombiningUsesAndRespectsAllResolversInOrder() Assert.Equal(4, resolverId); } - private static IList GetAndValidateCombinedResolvers(IJsonTypeInfoResolver resolver) + private IList GetAndValidateCombinedResolvers(IJsonTypeInfoResolver resolver) { var list = (IList)resolver; @@ -155,8 +169,12 @@ private static IList GetAndValidateCombinedResolvers(IJso return list; } + } + + public class JsonTypeInfoResolverTests + { [Fact] - public static void WithAddedModifier_CallsModifierOnResolvedMetadata() + public void WithAddedModifier_CallsModifierOnResolvedMetadata() { int modifierInvocationCount = 0; JsonSerializerOptions options = new(); @@ -175,11 +193,11 @@ public static void WithAddedModifier_CallsModifierOnResolvedMetadata() } [Fact] - public static void WithAddedModifier_DoesNotCallModifierOnUnResolvedMetadata() + public void WithAddedModifier_DoesNotCallModifierOnUnResolvedMetadata() { int modifierInvocationCount = 0; JsonSerializerOptions options = new(); - TestResolver resolver = new((_,_) => null); + TestResolver resolver = new((_, _) => null); IJsonTypeInfoResolver resolverWithModifier = resolver.WithAddedModifier(_ => modifierInvocationCount++); @@ -191,7 +209,7 @@ public static void WithAddedModifier_DoesNotCallModifierOnUnResolvedMetadata() } [Fact] - public static void WithAddedModifier_CanChainMultipleModifiers() + public void WithAddedModifier_CanChainMultipleModifiers() { int modifier1InvocationCount = 0; int modifier2InvocationCount = 0; @@ -208,7 +226,7 @@ public static void WithAddedModifier_CanChainMultipleModifiers() } [Fact] - public static void WithAddedModifier_ChainingDoesNotMutateIntermediateResolvers() + public void WithAddedModifier_ChainingDoesNotMutateIntermediateResolvers() { int modifier1InvocationCount = 0; int modifier2InvocationCount = 0; @@ -233,7 +251,7 @@ public static void WithAddedModifier_ChainingDoesNotMutateIntermediateResolvers( } [Fact] - public static void WithAddedModifier_ThrowsOnNullArguments() + public void WithAddedModifier_ThrowsOnNullArguments() { TestResolver resolver = new(JsonTypeInfo.CreateJsonTypeInfo); @@ -242,7 +260,7 @@ public static void WithAddedModifier_ThrowsOnNullArguments() } [Fact] - public static void NullResolver_ReturnsObjectMetadata() + public void NullResolver_ReturnsObjectMetadata() { var options = new JsonSerializerOptions(); var resolver = new NullResolver(); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/MetadataTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/MetadataTests.cs index 0e40f66a685d..7d8c2238a085 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/MetadataTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/MetadataTests.cs @@ -47,6 +47,11 @@ public class MetadataTests_Node : MetadataTests public MetadataTests_Node() : base(JsonSerializerWrapper.NodeSerializer) { } } + public class MetadataTests_Pipe : MetadataTests + { + public MetadataTests_Pipe() : base(JsonSerializerWrapper.AsyncPipeSerializer) { } + } + public abstract partial class MetadataTests { protected JsonSerializerWrapper Serializer { get; } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/NumberHandlingTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/NumberHandlingTests.cs index 1dfa1e16b0b8..5613dda77933 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/NumberHandlingTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/NumberHandlingTests.cs @@ -42,6 +42,11 @@ public class NumberHandlingTests_Node : NumberHandlingTests_OverloadSpecific public NumberHandlingTests_Node() : base(JsonSerializerWrapper.NodeSerializer) { } } + public class NumberHandlingTests_Pipe : NumberHandlingTests_OverloadSpecific + { + public NumberHandlingTests_Pipe() : base(JsonSerializerWrapper.AsyncPipeSerializer) { } + } + public abstract class NumberHandlingTests_OverloadSpecific { private JsonSerializerWrapper Serializer { get; } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs index 0cca85c6cc03..b0c8e41f7179 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs @@ -516,6 +516,57 @@ public static void MaxDepthRead() Assert.Throws(() => JsonSerializer.Deserialize(BasicCompany.s_data, options)); } + [Theory] + [InlineData(new char[] { '\n' }, '\r')] + [InlineData(new char[] { '\r', '\n' }, null)] + public static void NewLine(char[] newLineChars, char? notExpectedNewLineChars) + { + var obj = new BasicCompany(); + obj.Initialize(); + + var newLine = new string(newLineChars); + var options = new JsonSerializerOptions(); + var json = JsonSerializer.Serialize(obj, options); + Assert.DoesNotContain(newLine, json); + + // Set custom newLine with indentation enabled + options = new JsonSerializerOptions(); + options.WriteIndented = true; + options.NewLine = newLine; + json = JsonSerializer.Serialize(obj, options); + Assert.Contains(newLine, json); + + if (notExpectedNewLineChars is { } notExpected) + { + Assert.DoesNotContain(notExpected, json); + } + } + + [Theory] + [InlineData("")] + [InlineData(" ")] + [InlineData("\r")] + [InlineData("\n\n")] + [InlineData("\r\n\r\n")] + [InlineData("0")] + [InlineData("a")] + [InlineData("foo")] + [InlineData("$")] + [InlineData(".")] + [InlineData("\u03b1")] + public static void TestNewLineInvalid(string value) + { + var options = new JsonSerializerOptions(); + Assert.Throws("value", () => options.NewLine = value); + } + + [Fact] + public static void TestNewLineNullThrows() + { + var options = new JsonSerializerOptions(); + Assert.Throws("value", () => options.NewLine = null); + } + private class TestClassForEncoding { public string MyString { get; set; } @@ -1416,7 +1467,14 @@ and not nameof(JsonSerializerOptions.IsReadOnly)) // Property is not structural } else if (propertyType == typeof(string)) { - property.SetValue(options, "\t"); + if (property.Name is nameof(JsonSerializerOptions.NewLine)) + { + property.SetValue(options, "\n"); + } + else + { + property.SetValue(options, "\t"); + } } else if (propertyType == typeof(IList)) { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Pipe.WriteTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Pipe.WriteTests.cs new file mode 100644 index 000000000000..7e2a9502df97 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Pipe.WriteTests.cs @@ -0,0 +1,426 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Collections.Generic; +using System.IO.Pipelines; +using System.Text.Json.Serialization.Metadata; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace System.Text.Json.Serialization.Tests +{ + public partial class PipeTests + { + [Fact] + public async Task WriteNullArgumentFail() + { + await Assert.ThrowsAsync(async () => await JsonSerializer.SerializeAsync((PipeWriter)null, 1)); + await Assert.ThrowsAsync(async () => await JsonSerializer.SerializeAsync((PipeWriter)null, 1, typeof(int))); + } + + [Fact] + public async Task VerifyValueFail() + { + Pipe pipe = new Pipe(); + await Assert.ThrowsAsync(async () => await JsonSerializer.SerializeAsync(pipe.Writer, "", (Type)null)); + } + + [Fact] + public async Task VerifyTypeFail() + { + Pipe pipe = new Pipe(); + await Assert.ThrowsAsync(async () => await JsonSerializer.SerializeAsync(pipe.Writer, 1, typeof(string))); + } + + [Fact] + public async Task CompletedPipeWithExceptionThrowsFromSerialize() + { + Pipe pipe = new Pipe(); + pipe.Reader.Complete(new FormatException()); + + await Assert.ThrowsAsync(() => JsonSerializer.SerializeAsync(pipe.Writer, 1)); + } + + [Fact] + public async Task CompletedPipeThrowsFromSerialize() + { + Pipe pipe = new Pipe(); + pipe.Reader.Complete(); + + await Assert.ThrowsAsync(() => JsonSerializer.SerializeAsync(pipe.Writer, 1)); + } + + [Fact] + public async Task CancelPendingFlushDuringBackpressureThrows() + { + int i = 0; + Pipe pipe = new Pipe(new PipeOptions(pauseWriterThreshold: 10, resumeWriterThreshold: 5)); + await pipe.Writer.WriteAsync("123456789"u8.ToArray()); + Task serializeTask = JsonSerializer.SerializeAsync(pipe.Writer, GetNumbersAsync()); + Assert.False(serializeTask.IsCompleted); + + pipe.Writer.CancelPendingFlush(); + + await Assert.ThrowsAsync(() => serializeTask); + + ReadResult result = await pipe.Reader.ReadAsync(); + + // Technically this check is not needed, but helps confirm behavior, that Pipe had written but was waiting for flush to continue. + // result.Buffer: 123456789[0... + Assert.Equal(10 + i - 1, result.Buffer.Length); + pipe.Reader.AdvanceTo(result.Buffer.End); + + async IAsyncEnumerable GetNumbersAsync() + { + while (true) + { + await Task.Delay(10); + yield return i++; + } + } + } + + [Fact] + public async Task BackpressureIsObservedWhenWritingJson() + { + Pipe pipe = new Pipe(new PipeOptions(pauseWriterThreshold: 10, resumeWriterThreshold: 5)); + await pipe.Writer.WriteAsync("123456789"u8.ToArray()); + Task serializeTask = JsonSerializer.SerializeAsync(pipe.Writer, 1); + Assert.False(serializeTask.IsCompleted); + + ReadResult result = await pipe.Reader.ReadAsync(); + pipe.Reader.AdvanceTo(result.Buffer.GetPosition(5)); + + // Still need to read 1 more byte to unblock flush + Assert.False(serializeTask.IsCompleted); + + result = await pipe.Reader.ReadAsync(); + pipe.Reader.AdvanceTo(result.Buffer.GetPosition(1)); + + await serializeTask; + } + + [Fact] + public async Task CanCancelBackpressuredJsonWrite() + { + Pipe pipe = new Pipe(new PipeOptions(pauseWriterThreshold: 10, resumeWriterThreshold: 5)); + await pipe.Writer.WriteAsync("123456789"u8.ToArray()); + + CancellationTokenSource cts = new(); + Task serializeTask = JsonSerializer.SerializeAsync(pipe.Writer, 1, cancellationToken: cts.Token); + Assert.False(serializeTask.IsCompleted); + + cts.Cancel(); + + await Assert.ThrowsAsync(() => serializeTask); + + ReadResult result = await pipe.Reader.ReadAsync(); + // Even though flush was canceled, the bytes are still written to the Pipe + Assert.Equal(10, result.Buffer.Length); + pipe.Reader.AdvanceTo(result.Buffer.End); + } + + [Theory] + [InlineData(32)] + [InlineData(128)] + [InlineData(1024)] + [InlineData(1024 * 16)] // the default JsonSerializerOptions.DefaultBufferSize value + [InlineData(1024 * 1024)] + public async Task ShouldUseFastPathOnSmallPayloads(int defaultBufferSize) + { + var instrumentedResolver = new PocoWithInstrumentedFastPath.Context( + new JsonSerializerOptions + { + DefaultBufferSize = defaultBufferSize, + }); + + // The current implementation uses a heuristic + int smallValueThreshold = defaultBufferSize / 2; + PocoWithInstrumentedFastPath smallValue = PocoWithInstrumentedFastPath.CreateValueWithSerializationSize(smallValueThreshold); + + // We don't care about backpressure in this test + Pipe pipe = new Pipe(new PipeOptions(pauseWriterThreshold: defaultBufferSize, resumeWriterThreshold: defaultBufferSize / 2)); + ReadResult result; + + // The first 10 serializations should not call into the fast path + for (int i = 0; i < 10; i++) + { + await JsonSerializer.SerializeAsync(pipe.Writer, smallValue, instrumentedResolver.Options); + result = await pipe.Reader.ReadAsync(); + pipe.Reader.AdvanceTo(result.Buffer.End); + Assert.Equal(0, instrumentedResolver.FastPathInvocationCount); + } + + // Subsequent iterations do call into the fast path + for (int i = 0; i < 10; i++) + { + await JsonSerializer.SerializeAsync(pipe.Writer, smallValue, instrumentedResolver.Options); + result = await pipe.Reader.ReadAsync(); + pipe.Reader.AdvanceTo(result.Buffer.End); + Assert.Equal(i + 1, instrumentedResolver.FastPathInvocationCount); + } + + // Polymorphic serialization should use the fast path + await JsonSerializer.SerializeAsync(pipe.Writer, (object)smallValue, instrumentedResolver.Options); + result = await pipe.Reader.ReadAsync(); + pipe.Reader.AdvanceTo(result.Buffer.End); + Assert.Equal(11, instrumentedResolver.FastPathInvocationCount); + + // Attempt to serialize a value that is deemed large + var largeValue = PocoWithInstrumentedFastPath.CreateValueWithSerializationSize(smallValueThreshold + 1); + await JsonSerializer.SerializeAsync(pipe.Writer, largeValue, instrumentedResolver.Options); + result = await pipe.Reader.ReadAsync(); + pipe.Reader.AdvanceTo(result.Buffer.End); + Assert.Equal(12, instrumentedResolver.FastPathInvocationCount); + + // Any subsequent attempts no longer call into the fast path + for (int i = 0; i < 10; i++) + { + await JsonSerializer.SerializeAsync(pipe.Writer, smallValue, instrumentedResolver.Options); + result = await pipe.Reader.ReadAsync(); + pipe.Reader.AdvanceTo(result.Buffer.End); + Assert.Equal(12, instrumentedResolver.FastPathInvocationCount); + } + } + + [Fact] + public async Task FastPathObservesBackpressure() + { + int defaultBufferSize = 4096; + var instrumentedResolver = new PocoWithInstrumentedFastPath.Context( + new JsonSerializerOptions + { + DefaultBufferSize = defaultBufferSize, + }); + + // The current implementation uses a heuristic + int smallValueThreshold = defaultBufferSize / 2; + PocoWithInstrumentedFastPath smallValue = PocoWithInstrumentedFastPath.CreateValueWithSerializationSize(smallValueThreshold); + + Pipe pipe = new Pipe(new PipeOptions(pauseWriterThreshold: defaultBufferSize / 2, resumeWriterThreshold: defaultBufferSize / 4)); + ReadResult result; + + // The first 10 serializations should not call into the fast path + for (int i = 0; i < 10; i++) + { + await JsonSerializer.SerializeAsync(pipe.Writer, smallValue, instrumentedResolver.Options); + result = await pipe.Reader.ReadAsync(); + pipe.Reader.AdvanceTo(result.Buffer.End); + Assert.Equal(0, instrumentedResolver.FastPathInvocationCount); + } + + Task serializeTask = JsonSerializer.SerializeAsync(pipe.Writer, smallValue, instrumentedResolver.Options); + Assert.False(serializeTask.IsCompleted); + Assert.Equal(1, instrumentedResolver.FastPathInvocationCount); + + result = await pipe.Reader.ReadAsync(); + pipe.Reader.AdvanceTo(result.Buffer.End); + await serializeTask; + } + + [Fact] + public async Task CanCancelBackpressuredFastPath() + { + int defaultBufferSize = 4096; + var instrumentedResolver = new PocoWithInstrumentedFastPath.Context( + new JsonSerializerOptions + { + DefaultBufferSize = defaultBufferSize, + }); + + // The current implementation uses a heuristic + int smallValueThreshold = defaultBufferSize / 2; + PocoWithInstrumentedFastPath smallValue = PocoWithInstrumentedFastPath.CreateValueWithSerializationSize(smallValueThreshold); + + Pipe pipe = new Pipe(new PipeOptions(pauseWriterThreshold: defaultBufferSize / 2, resumeWriterThreshold: defaultBufferSize / 4)); + ReadResult result; + + // The first 10 serializations should not call into the fast path + for (int i = 0; i < 10; i++) + { + await JsonSerializer.SerializeAsync(pipe.Writer, smallValue, instrumentedResolver.Options); + result = await pipe.Reader.ReadAsync(); + pipe.Reader.AdvanceTo(result.Buffer.End); + Assert.Equal(0, instrumentedResolver.FastPathInvocationCount); + } + + CancellationTokenSource cts = new(); + + Task serializeTask = JsonSerializer.SerializeAsync(pipe.Writer, smallValue, instrumentedResolver.Options, cts.Token); + Assert.False(serializeTask.IsCompleted); + + cts.Cancel(); + await Assert.ThrowsAsync(() => serializeTask); + } + + [Fact] + public async Task BuffersBehaveAsExpected() + { + TestPool pool = new TestPool(2000); + Pipe pipe = new Pipe(new PipeOptions(pool)); + + // Many small writes + for (int i = 0; i < 100; ++i) + { + await JsonSerializer.SerializeAsync(pipe.Writer, "a"); + } + // Should fit into a single 2000 byte buffer + Assert.Equal(1, pool.BufferCount); + ReadResult result = await pipe.Reader.ReadAsync(); + pipe.Reader.AdvanceTo(result.Buffer.End); + Assert.Equal(0, pool.BufferCount); + + // Partially fill Pipe so next write needs a new buffer + await JsonSerializer.SerializeAsync(pipe.Writer, new string('a', 600)); + Assert.Equal(1, pool.BufferCount); + + // Writing strings incurs a 3x buffer size due to max potential transcoding + // 600 + 600*3 > 2000 means a second buffer will be grabbed + await JsonSerializer.SerializeAsync(pipe.Writer, new string('a', 600)); + Assert.Equal(2, pool.BufferCount); + result = await pipe.Reader.ReadAsync(); + Assert.Equal(1204, result.Buffer.Length); + SequencePosition pos = result.Buffer.Start; + int segments = 0; + while (result.Buffer.TryGet(ref pos, out ReadOnlyMemory memory)) + { + segments++; + Assert.Equal(602, memory.Length); + } + Assert.Equal(2, segments); + pipe.Reader.AdvanceTo(result.Buffer.End); + + // Large write + await JsonSerializer.SerializeAsync(pipe.Writer, new string('a', 2000)); + // Write is larger than pools max buffer size so Pipes will provide a buffer from elsewhere. + Assert.Equal(0, pool.BufferCount); + result = await pipe.Reader.ReadAsync(); + Assert.Equal(2002, result.Buffer.Length); + + } + + internal class TestPool : MemoryPool + { + private readonly int _bufferSize; + private int _bufferCount; + + public int BufferCount => _bufferCount; + + public TestPool(int bufferSize) + { + _bufferSize = bufferSize; + } + + public override int MaxBufferSize => _bufferSize; + + public override IMemoryOwner Rent(int minBufferSize = -1) + { + _bufferCount++; + return new MemoryPoolBuffer(_bufferSize, this); + } + + protected override void Dispose(bool disposing) + { } + + private sealed class MemoryPoolBuffer : IMemoryOwner + { + private readonly TestPool _pool; + private byte[]? _array; + private int _length; + + public MemoryPoolBuffer(int size, TestPool pool) + { + _array = ArrayPool.Shared.Rent(size); + _length = size; + _pool = pool; + } + + public Memory Memory + { + get + { + byte[]? array = _array; + + return new Memory(array, 0, _length); + } + } + + public void Dispose() + { + byte[]? array = _array; + if (array != null) + { + _array = null; + ArrayPool.Shared.Return(array); + _pool._bufferCount--; + } + } + } + } + + internal class PocoWithInstrumentedFastPath + { + public static PocoWithInstrumentedFastPath CreateValueWithSerializationSize(int targetSerializationSize) + { + int objectSerializationPaddingSize = """{"Value":""}""".Length; // 12 + return new PocoWithInstrumentedFastPath { Value = new string('a', targetSerializationSize - objectSerializationPaddingSize) }; + } + + public string? Value { get; set; } + + public class Context : JsonSerializerContext, IJsonTypeInfoResolver + { + public int FastPathInvocationCount { get; private set; } + + public Context(JsonSerializerOptions options) : base(options) + { } + + protected override JsonSerializerOptions? GeneratedSerializerOptions => Options; + public override JsonTypeInfo? GetTypeInfo(Type type) => GetTypeInfo(type, Options); + + public JsonTypeInfo? GetTypeInfo(Type type, JsonSerializerOptions options) + { + if (type == typeof(string)) + { + return JsonMetadataServices.CreateValueInfo(options, JsonMetadataServices.StringConverter); + } + + if (type == typeof(object)) + { + return JsonMetadataServices.CreateValueInfo(options, JsonMetadataServices.ObjectConverter); + } + + if (type == typeof(PocoWithInstrumentedFastPath)) + { + return JsonMetadataServices.CreateObjectInfo(options, + new JsonObjectInfoValues + { + PropertyMetadataInitializer = _ => new JsonPropertyInfo[1] + { + JsonMetadataServices.CreatePropertyInfo(options, + new JsonPropertyInfoValues + { + DeclaringType = typeof(PocoWithInstrumentedFastPath), + PropertyName = "Value", + Getter = obj => ((PocoWithInstrumentedFastPath)obj).Value, + }) + }, + + SerializeHandler = (writer, value) => + { + writer.WriteStartObject(); + writer.WriteString("Value", value.Value); + writer.WriteEndObject(); + FastPathInvocationCount++; + } + }); + } + + return null; + } + } + } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PolymorphicTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PolymorphicTests.cs index 46f2202b1420..9e14737051a2 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PolymorphicTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PolymorphicTests.cs @@ -55,6 +55,11 @@ public class PolymorphicTests_Node : PolymorphicTests public PolymorphicTests_Node() : base(JsonSerializerWrapper.NodeSerializer) { } } + public class PolymorphicTests_Pipe : PolymorphicTests + { + public PolymorphicTests_Pipe() : base(JsonSerializerWrapper.AsyncPipeSerializer) { } + } + public abstract partial class PolymorphicTests : SerializerTests { public PolymorphicTests(JsonSerializerWrapper serializer) : base(serializer) diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ReferenceHandlerTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ReferenceHandlerTests.cs index 3cfcdbeff8df..d793d4cbd47e 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ReferenceHandlerTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ReferenceHandlerTests.cs @@ -29,4 +29,9 @@ public sealed class ReferenceHandlerTestsDynamic_IgnoreCycles_AsyncStream : Refe { public ReferenceHandlerTestsDynamic_IgnoreCycles_AsyncStream() : base(JsonSerializerWrapper.AsyncStreamSerializer) { } } + + public sealed class ReferenceHandlerTestsDynamic_IgnoreCycles_Pipe : ReferenceHandlerTests_IgnoreCycles + { + public ReferenceHandlerTestsDynamic_IgnoreCycles_Pipe() : base(JsonSerializerWrapper.AsyncPipeSerializer) { } + } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/RequiredKeywordTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/RequiredKeywordTests.cs index 41dd4f61688f..969f5d17c606 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/RequiredKeywordTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/RequiredKeywordTests.cs @@ -52,4 +52,9 @@ public class RequiredKeywordTests_Node : RequiredKeywordTests { public RequiredKeywordTests_Node() : base(JsonSerializerWrapper.NodeSerializer) { } } + + public class RequiredKeywordTests_Pipe : RequiredKeywordTests + { + public RequiredKeywordTests_Pipe() : base(JsonSerializerWrapper.AsyncPipeSerializer) { } + } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/UnmappedMemberHandlingTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/UnmappedMemberHandlingTests.cs index 2b532b6e6f44..5c59342f3c77 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/UnmappedMemberHandlingTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/UnmappedMemberHandlingTests.cs @@ -12,4 +12,9 @@ public sealed partial class UnmappedMemberHandlingTests_AsyncStream : UnmappedMe { public UnmappedMemberHandlingTests_AsyncStream() : base(JsonSerializerWrapper.AsyncStreamSerializer) { } } + + public sealed partial class UnmappedMemberHandlingTests_Pipe : UnmappedMemberHandlingTests + { + public UnmappedMemberHandlingTests_Pipe() : base(JsonSerializerWrapper.AsyncPipeSerializer) { } + } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.ReadTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.ReadTests.cs index 437acca92b09..95a2cde389cf 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.ReadTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.ReadTests.cs @@ -391,7 +391,7 @@ public static void ReadPrimitiveUri() private static int SingleToInt32Bits(float value) { -#if NETCOREAPP +#if NET return BitConverter.SingleToInt32Bits(value); #else return Unsafe.As(ref value); @@ -470,7 +470,7 @@ private static void DeserializeLongJsonString(int stringLength) string json; char fillChar = 'x'; -#if NETCOREAPP +#if NET json = string.Create(stringLength, fillChar, (chars, fillChar) => { chars.Fill(fillChar); @@ -488,6 +488,18 @@ private static void DeserializeLongJsonString(int stringLength) } [Theory] + [InlineData("1:00:00")] + [InlineData("1")] + [InlineData("10")] + [InlineData("00:01")] + [InlineData("0:00:02")] + [InlineData("0:00:00.0000001")] + [InlineData("0:00:00.0000010")] + [InlineData("0:00:00.0000100")] + [InlineData("0:00:00.0001000")] + [InlineData("0:00:00.0010000")] + [InlineData("0:00:00.0100000")] + [InlineData("0:00:00.1000000")] [InlineData("23:59:59")] [InlineData("\\u002D23:59:59", "-23:59:59")] [InlineData("\\u0032\\u0033\\u003A\\u0035\\u0039\\u003A\\u0035\\u0039", "23:59:59")] @@ -546,13 +558,13 @@ public static void TimeSpan_Read_KnownDifferences() [InlineData("00:00:60")] [InlineData("00:00:00.00000009")] [InlineData("900000000.00:00:00")] - [InlineData("1:00:00")] // 'g' Format [InlineData("1:2:00:00")] // 'g' Format [InlineData("+00:00:00")] [InlineData("2021-06-18")] [InlineData("1$")] [InlineData("10675199.02:48:05.4775808")] // TimeSpan.MaxValue + 1 [InlineData("-10675199.02:48:05.4775809")] // TimeSpan.MinValue - 1 + [InlineData("")] [InlineData("1234", false)] [InlineData("{}", false)] [InlineData("[]", false)] @@ -566,7 +578,7 @@ public static void TimeSpan_Read_Failure(string json, bool addQuotes = true) Assert.Throws(() => JsonSerializer.Deserialize(json)); } -#if NETCOREAPP +#if NET [Theory] [InlineData("1970-01-01")] [InlineData("2002-02-13")] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.WriteTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.WriteTests.cs index af83df3f9696..a59e7dc91703 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.WriteTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Value.WriteTests.cs @@ -148,7 +148,7 @@ public static void TimeSpan_Write_Success(string value, string? expectedValue = Assert.Equal(json, JsonConvert.SerializeObject(ts)); } -#if NETCOREAPP +#if NET [Theory] [InlineData("1970-01-01")] [InlineData("2002-02-13")] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj index 61bea23cac82..3dc7cc9e50d4 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj @@ -16,6 +16,9 @@ true true + + true true @@ -28,6 +31,7 @@ + @@ -166,6 +170,7 @@ + @@ -302,5 +307,8 @@ - + + + + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/TrimmingTests/System.Text.Json.TrimmingTests.proj b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/TrimmingTests/System.Text.Json.TrimmingTests.proj index 6d9885fed2a9..37188a8dce70 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/TrimmingTests/System.Text.Json.TrimmingTests.proj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/TrimmingTests/System.Text.Json.TrimmingTests.proj @@ -1,7 +1,9 @@ - + + Helper.cs diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs index 643762183c71..4515e69412d3 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs @@ -1442,7 +1442,7 @@ private static string GetExpectedLargeString(JsonWriterOptions options) json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } [Theory] @@ -2683,12 +2683,12 @@ public void InvalidJsonContinueShouldSucceed(bool formatted) for (int i = 0; i < 100; i++) { if (options.Indented) - sb.Append(Environment.NewLine); + sb.Append(options.NewLine); sb.Append("]"); } sb.Append(","); if (options.Indented) - sb.Append(Environment.NewLine); + sb.Append(options.NewLine); sb.Append("[]"); JsonTestHelper.AssertContents(sb.ToString(), output); @@ -2722,7 +2722,7 @@ public void WriteSeparateProperties(JsonWriterOptions options) json.Flush(); - string expectedStr = HandleIndent(stringWriter.ToString(), options); + string expectedStr = HandleFormatting(stringWriter.ToString(), options); using var jsonUtf8 = new Utf8JsonWriter(output, options); jsonUtf8.WriteStartObject(); @@ -3069,7 +3069,7 @@ public void WritingHugeBase64Bytes(JsonWriterOptions options) } // https://github.com/dotnet/runtime/issues/30746 - [Theory] + [Theory, OuterLoop("Very long running test")] [MemberData(nameof(JsonOptions_TestData))] [SkipOnCoreClr("https://github.com/dotnet/runtime/issues/45464", ~RuntimeConfiguration.Release)] public void Writing3MBBase64Bytes(JsonWriterOptions options) @@ -3082,7 +3082,7 @@ public void Writing3MBBase64Bytes(JsonWriterOptions options) Base64.EncodeToUtf8(value, base64StringUtf8, out _, out int bytesWritten); string expectedValue = Encoding.UTF8.GetString(base64StringUtf8.AsSpan(0, bytesWritten).ToArray()); - string expectedJson = options.Indented ? $"{{{Environment.NewLine}{GetIndentText(options)}\"foo\": \"{expectedValue}\"{Environment.NewLine}}}" : $"{{\"foo\":\"{expectedValue}\"}}"; + string expectedJson = options.Indented ? $"{{{options.NewLine}{GetIndentText(options)}\"foo\": \"{expectedValue}\"{options.NewLine}}}" : $"{{\"foo\":\"{expectedValue}\"}}"; var output = new ArrayBufferWriter(1024); @@ -3558,14 +3558,14 @@ public void WritePartialHelloWorld(JsonWriterOptions options) Assert.Equal(0, jsonUtf8.BytesCommitted); if (options.Indented) - Assert.Equal(26 + options.IndentSize + Environment.NewLine.Length + 1, jsonUtf8.BytesPending); // new lines, indentation, white space + Assert.Equal(26 + options.IndentSize + options.NewLine.Length + 1, jsonUtf8.BytesPending); // new lines, indentation, white space else Assert.Equal(26, jsonUtf8.BytesPending); jsonUtf8.Flush(); if (options.Indented) - Assert.Equal(26 + options.IndentSize + Environment.NewLine.Length + 1, jsonUtf8.BytesCommitted); // new lines, indentation, white space + Assert.Equal(26 + options.IndentSize + options.NewLine.Length + 1, jsonUtf8.BytesCommitted); // new lines, indentation, white space else Assert.Equal(26, jsonUtf8.BytesCommitted); @@ -3575,19 +3575,19 @@ public void WritePartialHelloWorld(JsonWriterOptions options) jsonUtf8.WriteEndObject(); if (options.Indented) - Assert.Equal(26 + options.IndentSize + Environment.NewLine.Length + 1, jsonUtf8.BytesCommitted); + Assert.Equal(26 + options.IndentSize + options.NewLine.Length + 1, jsonUtf8.BytesCommitted); else Assert.Equal(26, jsonUtf8.BytesCommitted); if (options.Indented) - Assert.Equal(27 + options.IndentSize + (2 * Environment.NewLine.Length) + 1, jsonUtf8.BytesPending); // new lines, indentation, white space + Assert.Equal(27 + options.IndentSize + (2 * options.NewLine.Length) + 1, jsonUtf8.BytesPending); // new lines, indentation, white space else Assert.Equal(27, jsonUtf8.BytesPending); jsonUtf8.Flush(); if (options.Indented) - Assert.Equal(53 + (2 * options.IndentSize) + (3 * Environment.NewLine.Length) + (1 * 2), jsonUtf8.BytesCommitted); // new lines, indentation, white space + Assert.Equal(53 + (2 * options.IndentSize) + (3 * options.NewLine.Length) + (1 * 2), jsonUtf8.BytesCommitted); // new lines, indentation, white space else Assert.Equal(53, jsonUtf8.BytesCommitted); @@ -3675,14 +3675,14 @@ public void WritePartialBase64String(JsonWriterOptions options) Assert.Equal(0, jsonUtf8.BytesCommitted); if (options.Indented) - Assert.Equal(17 + options.IndentSize + Environment.NewLine.Length + 1, jsonUtf8.BytesPending); // new lines, indentation, white space + Assert.Equal(17 + options.IndentSize + options.NewLine.Length + 1, jsonUtf8.BytesPending); // new lines, indentation, white space else Assert.Equal(17, jsonUtf8.BytesPending); jsonUtf8.Flush(); if (options.Indented) - Assert.Equal(17 + options.IndentSize + Environment.NewLine.Length + 1, jsonUtf8.BytesCommitted); // new lines, indentation, white space + Assert.Equal(17 + options.IndentSize + options.NewLine.Length + 1, jsonUtf8.BytesCommitted); // new lines, indentation, white space else Assert.Equal(17, jsonUtf8.BytesCommitted); @@ -3692,19 +3692,19 @@ public void WritePartialBase64String(JsonWriterOptions options) jsonUtf8.WriteEndObject(); if (options.Indented) - Assert.Equal(17 + options.IndentSize + Environment.NewLine.Length + 1, jsonUtf8.BytesCommitted); + Assert.Equal(17 + options.IndentSize + options.NewLine.Length + 1, jsonUtf8.BytesCommitted); else Assert.Equal(17, jsonUtf8.BytesCommitted); if (options.Indented) - Assert.Equal(18 + options.IndentSize + (2 * Environment.NewLine.Length) + 1, jsonUtf8.BytesPending); // new lines, indentation, white space + Assert.Equal(18 + options.IndentSize + (2 * options.NewLine.Length) + 1, jsonUtf8.BytesPending); // new lines, indentation, white space else Assert.Equal(18, jsonUtf8.BytesPending); jsonUtf8.Flush(); if (options.Indented) - Assert.Equal(35 + (2 * options.IndentSize) + (3 * Environment.NewLine.Length) + (1 * 2), jsonUtf8.BytesCommitted); // new lines, indentation, white space + Assert.Equal(35 + (2 * options.IndentSize) + (3 * options.NewLine.Length) + (1 * 2), jsonUtf8.BytesCommitted); // new lines, indentation, white space else Assert.Equal(35, jsonUtf8.BytesCommitted); @@ -4078,7 +4078,7 @@ private static string GetCommentExpectedString(JsonWriterOptions options) json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } [Theory] @@ -4421,6 +4421,7 @@ public void EscapeAsciiCharacters(JsonWriterOptions options) [Theory] [MemberData(nameof(JsonOptions_TestData))] + [OuterLoop("Too slow", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime))] public void EscapeCharacters(JsonWriterOptions options) { // Do not include surrogate pairs. @@ -5303,6 +5304,7 @@ public void WriteDoubleValue(JsonWriterOptions options, double value) [Theory] [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] [MemberData(nameof(WriteValue_TestData))] + [OuterLoop("Too slow", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime))] public void WriteNumbers(JsonWriterOptions options, string keyString) { var random = new Random(42); @@ -6970,7 +6972,7 @@ private static string GetHelloWorldExpectedString(JsonWriterOptions options, str json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetBase64ExpectedString(JsonWriterOptions options, string propertyName, byte[] value) @@ -6998,7 +7000,7 @@ private static string GetBase64ExpectedString(JsonWriterOptions options, string json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetCommentInArrayExpectedString(JsonWriterOptions options, string comment) @@ -7032,7 +7034,7 @@ private static string GetCommentInArrayExpectedString(JsonWriterOptions options, json.WriteComment(comment); json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetCommentInObjectExpectedString(JsonWriterOptions options, string comment) @@ -7098,7 +7100,7 @@ private static string GetCommentInObjectExpectedString(JsonWriterOptions options json.WriteComment(comment); json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetStringsExpectedString(JsonWriterOptions options, string value) @@ -7118,7 +7120,7 @@ private static string GetStringsExpectedString(JsonWriterOptions options, string json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetEscapedExpectedString(JsonWriterOptions options, string propertyName, string value, StringEscapeHandling escaping, bool escape = true) @@ -7136,7 +7138,7 @@ private static string GetEscapedExpectedString(JsonWriterOptions options, string json.WriteEnd(); json.Flush(); - return HandleIndent(stringWriter.ToString(), options); + return HandleFormatting(stringWriter.ToString(), options); } } @@ -7160,7 +7162,7 @@ private static string GetCustomExpectedString(JsonWriterOptions options) json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetStartEndExpectedString(JsonWriterOptions options) @@ -7180,7 +7182,7 @@ private static string GetStartEndExpectedString(JsonWriterOptions options) json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetStartEndWithPropertyArrayExpectedString(JsonWriterOptions options) @@ -7201,7 +7203,7 @@ private static string GetStartEndWithPropertyArrayExpectedString(JsonWriterOptio json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetStartEndWithPropertyArrayExpectedString(string key, JsonWriterOptions options, bool escape = false) @@ -7223,7 +7225,7 @@ private static string GetStartEndWithPropertyArrayExpectedString(string key, Jso json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetStartEndWithPropertyObjectExpectedString(JsonWriterOptions options) @@ -7244,7 +7246,7 @@ private static string GetStartEndWithPropertyObjectExpectedString(JsonWriterOpti json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetStartEndWithPropertyObjectExpectedString(string key, JsonWriterOptions options, bool escape = false) @@ -7266,7 +7268,7 @@ private static string GetStartEndWithPropertyObjectExpectedString(string key, Js json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetArrayWithPropertyExpectedString(JsonWriterOptions options) @@ -7286,7 +7288,7 @@ private static string GetArrayWithPropertyExpectedString(JsonWriterOptions optio json.WriteEndObject(); json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetBooleanExpectedString(JsonWriterOptions options, string keyString, bool value, bool escape = false) @@ -7316,7 +7318,7 @@ private static string GetBooleanExpectedString(JsonWriterOptions options, string json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetNullExpectedString(JsonWriterOptions options, string keyString, bool escape = false) @@ -7346,7 +7348,7 @@ private static string GetNullExpectedString(JsonWriterOptions options, string ke json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetPropertyExpectedString(JsonWriterOptions options, T value) @@ -7366,7 +7368,7 @@ private static string GetPropertyExpectedString(JsonWriterOptions options, T json.Flush(); - return HandleIndent(sb.ToString(), options); + return HandleFormatting(sb.ToString(), options); } private static string GetNumbersExpectedString(JsonWriterOptions options, string keyString, int[] ints, uint[] uints, long[] longs, ulong[] ulongs, float[] floats, double[] doubles, decimal[] decimals, bool escape = false) @@ -7432,7 +7434,7 @@ private static string GetNumbersExpectedString(JsonWriterOptions options, string json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetExpectedString_RelaxedEscaping(bool prettyPrint, string keyString) @@ -7492,7 +7494,7 @@ private static string GetGuidsExpectedString(JsonWriterOptions options, string k json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetNumbersExpectedString(JsonWriterOptions options, int numberOfElements, T value) @@ -7514,7 +7516,7 @@ private static string GetNumbersExpectedString(JsonWriterOptions options, int json.Flush(); - return HandleIndent(sb.ToString(), options); + return HandleFormatting(sb.ToString(), options); } private static string GetDatesExpectedString(JsonWriterOptions options, string keyString, DateTime[] dates, bool escape = false) @@ -7546,7 +7548,7 @@ private static string GetDatesExpectedString(JsonWriterOptions options, string k json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static string GetDatesExpectedString(JsonWriterOptions options, string keyString, DateTimeOffset[] dates, bool escape = false) @@ -7578,7 +7580,7 @@ private static string GetDatesExpectedString(JsonWriterOptions options, string k json.Flush(); - return HandleIndent(Encoding.UTF8.GetString(ms.ToArray()), options); + return HandleFormatting(Encoding.UTF8.GetString(ms.ToArray()), options); } private static void CompensateWhitespaces(bool prettyPrint, JsonTextWriter json, TextWriter streamWriter, int whitespaceCount = 1) @@ -7599,9 +7601,16 @@ private static void CompensateNewLine(bool prettyPrint, JsonTextWriter json, Tex } } - private static string HandleIndent(string text, JsonWriterOptions options) + private static string HandleFormatting(string text, JsonWriterOptions options) { - return text.Replace(" ", GetIndentText(options)); + var normalized = text.Replace(" ", GetIndentText(options)); + + if (options.NewLine != Environment.NewLine) + { + normalized = normalized.Replace(Environment.NewLine, options.NewLine); + } + + return normalized; } private static string GetIndentText(JsonWriterOptions options) => new(options.IndentCharacter, options.IndentSize); @@ -7627,14 +7636,16 @@ private static IEnumerable JsonOptions() return from indented in new[] { true, false } from skipValidation in new[] { true, false } from indentCharacter in indented ? new char?[] { null, ' ', '\t' } : [] - from indentSize in indented ? new int?[] { null, 0, 1, 2, 127 } : [] - select CreateOptions(indented, indentCharacter, indentSize, skipValidation); + from indentSize in indented ? new int?[] { null, 0, 1, 2, 3 } : [] + from newLine in indented ? new string?[] { null, "\n", "\r\n" } : [] + select CreateOptions(indented, indentCharacter, indentSize, skipValidation, newLine); - static JsonWriterOptions CreateOptions(bool indented, char? indentCharacter, int? indentSize, bool skipValidation) + static JsonWriterOptions CreateOptions(bool indented, char? indentCharacter, int? indentSize, bool skipValidation, string? newLine) { var options = new JsonWriterOptions { Indented = indented, SkipValidation = skipValidation }; if (indentCharacter is not null) options.IndentCharacter = (char)indentCharacter; if (indentSize is not null) options.IndentSize = (int)indentSize; + if (newLine is not null) options.NewLine = newLine; return options; } } diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs index b2ab52c4c71f..b9a4b80a70ba 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs @@ -4136,22 +4136,31 @@ void EmitSingleCharAtomicLoop(RegexNode node, bool emitLengthChecksIfRequired = TransferSliceStaticPosToPos(); writer.WriteLine($"int {iterationLocal} = inputSpan.Length - pos;"); } - else if (maxIterations == int.MaxValue && TryEmitIndexOf(requiredHelpers, node, useLast: false, negate: true, out _, out string? indexOfExpr)) + else if (TryEmitIndexOf(requiredHelpers, node, useLast: false, negate: true, out _, out string? indexOfExpr)) { - // We're unbounded and we can use an IndexOf method to perform the search. The unbounded restriction is - // purely for simplicity; it could be removed in the future with additional code to handle that case. + // We can use an IndexOf method to perform the search. If the number of iterations is unbounded, we can just search the whole span. + // If, however, it's bounded, we need to slice the span to the min(remainingSpan.Length, maxIterations) so that we don't + // search more than is necessary. + + // If maxIterations is 0, the node should have been optimized away. If it's 1 and min is 0, it should + // have been handled as an optional loop above, and if it's 1 and min is 1, it should have been transformed + // into a single char match. So, we should only be here if maxIterations is greater than 1. And that's relevant, + // because we wouldn't want to invest in an IndexOf call if we're only going to iterate once. + Debug.Assert(maxIterations > 1); + + TransferSliceStaticPosToPos(); writer.Write($"int {iterationLocal} = {sliceSpan}"); - if (sliceStaticPos != 0) + if (maxIterations != int.MaxValue) { - writer.Write($".Slice({sliceStaticPos})"); + writer.Write($".Slice(0, Math.Min({sliceSpan}.Length, {maxIterations}))"); } writer.WriteLine($".{indexOfExpr};"); using (EmitBlock(writer, $"if ({iterationLocal} < 0)")) { - writer.WriteLine(sliceStaticPos > 0 ? - $"{iterationLocal} = {sliceSpan}.Length - {sliceStaticPos};" : + writer.WriteLine(maxIterations != int.MaxValue ? + $"{iterationLocal} = Math.Min({sliceSpan}.Length, {maxIterations});" : $"{iterationLocal} = {sliceSpan}.Length;"); } writer.WriteLine(); @@ -5405,7 +5414,7 @@ private static string GetSHA256FieldName(string prefix, string toEncode) { #pragma warning disable CA1850 // SHA256.HashData isn't available on netstandard2.0 using SHA256 sha = SHA256.Create(); - return $"{prefix}{ToHexStringNoDashes(Encoding.UTF8.GetBytes(toEncode))}"; + return $"{prefix}{ToHexStringNoDashes(sha.ComputeHash(Encoding.UTF8.GetBytes(toEncode)))}"; #pragma warning restore CA1850 } @@ -5602,7 +5611,7 @@ private static string DescribeLoop(RegexNode node, RegexMethod rm) } private static string ToHexStringNoDashes(byte[] bytes) => -#if NETCOREAPP +#if NET Convert.ToHexString(bytes); #else BitConverter.ToString(bytes).Replace("-", ""); diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs index 5666498347e4..3c24bdc78ad0 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs @@ -563,7 +563,7 @@ public static string ConvertOldStringsToClass(string set, string category) } return -#if NETCOREAPP2_1_OR_GREATER +#if NET string #else StringExtensions @@ -1304,7 +1304,7 @@ static bool InitializeValue(char ch, string set, ref uint[]? asciiLazyCache) } uint[]? cache = asciiLazyCache ?? Interlocked.CompareExchange(ref asciiLazyCache, new uint[CacheArrayLength], null) ?? asciiLazyCache; -#if NET5_0_OR_GREATER +#if NET Interlocked #else InterlockedExtensions @@ -1594,7 +1594,7 @@ internal static unsafe string CharsToStringClass(ReadOnlySpan chars) #pragma warning disable CS8500 // takes address of managed type ReadOnlySpan tmpChars = chars; // avoid address exposing the span and impacting the other code in the method that uses it return -#if NETCOREAPP2_1_OR_GREATER +#if NET string #else StringExtensions diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs index 082087939bcd..a020b8bd858c 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs @@ -4457,17 +4457,25 @@ void EmitSingleCharAtomicLoop(RegexNode node) Sub(); Stloc(iterationLocal); } - else if (maxIterations == int.MaxValue && CanEmitIndexOf(node, out _)) + else if (maxIterations > 1 && CanEmitIndexOf(node, out _)) { - // We're unbounded and we can use an IndexOf method to perform the search. The unbounded restriction is - // purely for simplicity; it could be removed in the future with additional code to handle that case. + // We can use an IndexOf method to perform the search. If the number of iterations is unbounded, we can just search the whole span. + // If, however, it's bounded, we need to slice the span to the min(remainingSpan.Length, maxIterations) so that we don't + // search more than is necessary. (There's little point in using IndexOf for an optional / something with at most one iteration, + // so we also skip using IndexOf in that case.) - // int i = slice.Slice(sliceStaticPos).IndexOf(...); - if (sliceStaticPos > 0) + TransferSliceStaticPosToPos(); + + // int i = slice.Slice(0, Math.Min(maxIterations, slice.Length)).IndexOf(...); + if (maxIterations != int.MaxValue) { Ldloca(slice); - Ldc(sliceStaticPos); - Call(s_spanSliceIntMethod); + Ldc(0); + Ldc(maxIterations); + Ldloca(slice); + Call(s_spanGetLengthMethod); + Call(s_mathMinIntInt); + Call(s_spanSliceIntIntMethod); } else { @@ -4482,13 +4490,13 @@ void EmitSingleCharAtomicLoop(RegexNode node) Ldc(0); BgeFar(atomicLoopDoneLabel); - // i = slice.Length - sliceStaticPos; + // i = Math.Min(slice.Length, maxIterations); Ldloca(slice); Call(s_spanGetLengthMethod); - if (sliceStaticPos > 0) + if (maxIterations != int.MaxValue) { - Ldc(sliceStaticPos); - Sub(); + Ldc(maxIterations); + Call(s_mathMinIntInt); } Stloc(iterationLocal); } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreter.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreter.cs index 11cf75298230..8d49e71e3b90 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreter.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreter.cs @@ -53,10 +53,7 @@ private void Advance(int i) private void Goto(int newpos) { // When branching backward, ensure storage. - if (newpos < _codepos) - { - EnsureStorage(); - } + EnsureStorage(); _codepos = newpos; SetOperator((RegexOpcode)_code.Codes[newpos]); @@ -144,10 +141,7 @@ private void Backtrack() SetOperator((RegexOpcode)(_code.Codes[newpos] | back)); // When branching backward, ensure storage. - if (newpos < _codepos) - { - EnsureStorage(); - } + EnsureStorage(); _codepos = newpos; } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs index 926a28339162..556a187203f0 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs @@ -59,9 +59,11 @@ static bool FindPrefixesCore(RegexNode node, List results, bool i // If we're too deep to analyze further, we can't trust what we've already computed, so stop iterating. // Also bail if any of our results is already hitting the threshold, or if this node is RTL, which is // not worth the complexity of handling. + // Or if we've already discovered more than the allowed number of prefixes. if (!StackHelper.TryEnsureSufficientExecutionStack() || !results.TrueForAll(sb => sb.Length < MaxPrefixLength) || - (node.Options & RegexOptions.RightToLeft) != 0) + (node.Options & RegexOptions.RightToLeft) != 0 || + results.Count > MaxPrefixes) { return false; } @@ -162,23 +164,30 @@ static bool FindPrefixesCore(RegexNode node, List results, bool i int reps = node.Kind is RegexNodeKind.Set ? 1 : Math.Min(node.M, MaxPrefixLength); if (!ignoreCase) { - int existingCount = results.Count; - - // Duplicate all of the existing strings for all of the new suffixes, other than the first. - foreach (char suffix in setChars.Slice(1, charCount - 1)) + for (int rep = 0; rep < reps; rep++) { - for (int existing = 0; existing < existingCount; existing++) + int existingCount = results.Count; + if (existingCount * charCount > MaxPrefixes) { - StringBuilder newSb = new StringBuilder().Append(results[existing]); - newSb.Append(suffix, reps); - results.Add(newSb); + return false; } - } - // Then append the first suffix to all of the existing strings. - for (int existing = 0; existing < existingCount; existing++) - { - results[existing].Append(setChars[0], reps); + // Duplicate all of the existing strings for all of the new suffixes, other than the first. + foreach (char suffix in setChars.Slice(1, charCount - 1)) + { + for (int existing = 0; existing < existingCount; existing++) + { + StringBuilder newSb = new StringBuilder().Append(results[existing]); + newSb.Append(suffix); + results.Add(newSb); + } + } + + // Then append the first suffix to all of the existing strings. + for (int existing = 0; existing < existingCount; existing++) + { + results[existing].Append(setChars[0]); + } } } else @@ -248,6 +257,12 @@ static bool FindPrefixesCore(RegexNode node, List results, bool i { _ = FindPrefixesCore(node.Child(i), alternateBranchResults, ignoreCase); + // If we now have too many results, bail. + if ((allBranchResults?.Count ?? 0) + alternateBranchResults.Count > MaxPrefixes) + { + return false; + } + Debug.Assert(alternateBranchResults.Count > 0); foreach (StringBuilder sb in alternateBranchResults) { @@ -359,7 +374,7 @@ static bool Process(RegexNode node, ref ValueStringBuilder vsb) } // Alternation: find a string that's a shared prefix of all branches - case RegexNodeKind.Alternate: + case RegexNodeKind.Alternate when !rtl: // for RTL we'd need to be matching the suffixes of the alternation cases { int childCount = node.ChildCount(); diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs index 5284c09339bd..4d779d4f48f1 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs @@ -177,7 +177,7 @@ private void Emit(RegexOpcode op, int opd1, int opd2) /// private int StringCode(string str) { -#if NET6_0_OR_GREATER +#if NET ref int i = ref CollectionsMarshal.GetValueRefOrAddDefault(_stringTable, str, out bool exists); if (!exists) { diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexNode.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexNode.cs index b20564cee32a..a138c819be00 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexNode.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexNode.cs @@ -243,7 +243,7 @@ bool WithCache(uint context) Debug.Assert(context < CharKind.ContextLimit); - // If nullablity has been computed for the given context then return it + // If nullability has been computed for the given context then return it byte b = Volatile.Read(ref _nullabilityCache[context]); if (b != UndefinedByte) { diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/UnicodeCategoryConditions.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/UnicodeCategoryConditions.cs index 27d8f18298a0..6ad4f5a526c4 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/UnicodeCategoryConditions.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/UnicodeCategoryConditions.cs @@ -33,7 +33,7 @@ static UnicodeCategoryConditions() /// Gets a that represents the specified . public static BDD GetCategory(UnicodeCategory category) => - Volatile.Read(ref s_categories[(int)category]) ?? + s_categories[(int)category] ?? Interlocked.CompareExchange(ref s_categories[(int)category], BDD.Deserialize(UnicodeCategoryRanges.GetSerializedCategory(category)), null) ?? s_categories[(int)category]!; diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Threading/StackHelper.cs b/src/libraries/System.Text.RegularExpressions/src/System/Threading/StackHelper.cs index c338c2bb73e9..ded50c662ea4 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Threading/StackHelper.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Threading/StackHelper.cs @@ -12,7 +12,7 @@ internal static class StackHelper /// Tries to ensure there is sufficient stack to execute the average .NET function. public static bool TryEnsureSufficientExecutionStack() { -#if NETCOREAPP2_0_OR_GREATER +#if NET return RuntimeHelpers.TryEnsureSufficientExecutionStack(); #else try diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.CompileToAssembly.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.CompileToAssembly.Tests.cs index a669f65bd023..c1d17ffa6a3a 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.CompileToAssembly.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.CompileToAssembly.Tests.cs @@ -14,63 +14,62 @@ namespace System.Text.RegularExpressions.Tests [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] public class RegexCompileToAssemblyTests : FileCleanupTestBase { - public static bool IsDebug => typeof(Regex).Assembly.GetCustomAttributes(false).OfType().Any(da => da.IsJITTrackingEnabled); - public static bool IsRelease => !IsDebug; - public static bool IsDebugAndRemoteExecutorSupported => IsDebug && RemoteExecutor.IsSupported; - - [ConditionalFact(nameof(IsRelease))] - public void CompileToAssembly_PNSE() + [Fact] + public void CompileToAssembly_SimpleTest() { - Assert.Throws(() => Regex.CompileToAssembly(null, null)); - Assert.Throws(() => Regex.CompileToAssembly(null, null, null)); - Assert.Throws(() => Regex.CompileToAssembly(null, null, null, null)); + bool isDebug = typeof(Regex).Assembly.GetCustomAttributes(false).OfType().Any(da => da.IsJITTrackingEnabled); - Assert.Throws(() => Regex.CompileToAssembly( - [new RegexCompilationInfo("abcd", RegexOptions.None, "abcd", "SomeNamespace", true)], - new AssemblyName("abcd"))); + if (!isDebug) + { + Assert.Throws(() => Regex.CompileToAssembly(null, null)); + Assert.Throws(() => Regex.CompileToAssembly(null, null, null)); + Assert.Throws(() => Regex.CompileToAssembly(null, null, null, null)); - Assert.Throws(() => Regex.CompileToAssembly( - [new RegexCompilationInfo("abcd", RegexOptions.None, "abcd", "SomeNamespace", true)], - new AssemblyName("abcd"), - [new CustomAttributeBuilder(typeof(AssemblyCompanyAttribute).GetConstructor([typeof(string)]), new[] { "TestCompany" })])); + Assert.Throws(() => Regex.CompileToAssembly( + [new RegexCompilationInfo("abcd", RegexOptions.None, "abcd", "SomeNamespace", true)], + new AssemblyName("abcd"))); - Assert.Throws(() => Regex.CompileToAssembly( - [new RegexCompilationInfo("abcd", RegexOptions.None, "abcd", "SomeNamespace", true)], - new AssemblyName("abcd"), - [new CustomAttributeBuilder(typeof(AssemblyCompanyAttribute).GetConstructor([typeof(string)]), new[] { "TestCompany" })], - "resourceFile")); - } + Assert.Throws(() => Regex.CompileToAssembly( + [new RegexCompilationInfo("abcd", RegexOptions.None, "abcd", "SomeNamespace", true)], + new AssemblyName("abcd"), + [new CustomAttributeBuilder(typeof(AssemblyCompanyAttribute).GetConstructor([typeof(string)]), new[] { "TestCompany" })])); - [ConditionalFact(nameof(IsDebugAndRemoteExecutorSupported))] - public void CompileToAssembly_SimpleUseInDebug() - { - RemoteExecutor.Invoke(() => + Assert.Throws(() => Regex.CompileToAssembly( + [new RegexCompilationInfo("abcd", RegexOptions.None, "abcd", "SomeNamespace", true)], + new AssemblyName("abcd"), + [new CustomAttributeBuilder(typeof(AssemblyCompanyAttribute).GetConstructor([typeof(string)]), new[] { "TestCompany" })], + "resourceFile")); + } + else if (RemoteExecutor.IsSupported) { - (RegexCompilationInfo rci, string validInput, string invalidInput)[] regexes = - [ - (new RegexCompilationInfo("abcd", RegexOptions.None, "Type1", "Namespace1", ispublic: true), "123abcd123", "123abed123"), - (new RegexCompilationInfo("(a|b|cde)+", RegexOptions.None, "Type2", "Namespace2.Sub", ispublic: true), "abcde", "cd"), - ]; + RemoteExecutor.Invoke(() => + { + (RegexCompilationInfo rci, string validInput, string invalidInput)[] regexes = + [ + (new RegexCompilationInfo("abcd", RegexOptions.None, "Type1", "Namespace1", ispublic: true), "123abcd123", "123abed123"), + (new RegexCompilationInfo("(a|b|cde)+", RegexOptions.None, "Type2", "Namespace2.Sub", ispublic: true), "abcde", "cd"), + ]; - string assemblyName = Path.GetRandomFileName(); + string assemblyName = Path.GetRandomFileName(); - string cwd = Environment.CurrentDirectory; - Environment.CurrentDirectory = TestDirectory; - try - { - Regex.CompileToAssembly(regexes.Select(r => r.rci).ToArray(), new AssemblyName(assemblyName)); - } - finally - { - Environment.CurrentDirectory = cwd; - } + string cwd = Environment.CurrentDirectory; + Environment.CurrentDirectory = TestDirectory; + try + { + Regex.CompileToAssembly(regexes.Select(r => r.rci).ToArray(), new AssemblyName(assemblyName)); + } + finally + { + Environment.CurrentDirectory = cwd; + } - string assemblyPath = Path.Combine(TestDirectory, assemblyName + ".dll"); - Assert.True(File.Exists(assemblyPath)); + string assemblyPath = Path.Combine(TestDirectory, assemblyName + ".dll"); + Assert.True(File.Exists(assemblyPath)); - // Uncomment to save the assembly to the desktop for inspection: - // File.Copy(assemblyPath, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), Path.GetFileName(assemblyPath))); - }).Dispose(); + // Uncomment to save the assembly to the desktop for inspection: + // File.Copy(assemblyPath, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), Path.GetFileName(assemblyPath))); + }).Dispose(); + } } } } diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.EnumerateMatches.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.EnumerateMatches.Tests.cs index c79f4de0c7cd..cac2753615e1 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.EnumerateMatches.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.EnumerateMatches.Tests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Threading.Tasks; using Xunit; namespace System.Text.RegularExpressions.Tests @@ -41,7 +42,7 @@ public void EnumerateMatches_Ctor_Invalid() [Theory] [MemberData(nameof(RegexHelpers.AvailableEngines_MemberData), MemberType = typeof(RegexHelpers))] - public void EnumerateMatches_Lookahead(RegexEngine engine) + public async Task EnumerateMatches_Lookahead(RegexEngine engine) { if (RegexHelpers.IsNonBacktracking(engine)) { @@ -49,23 +50,27 @@ public void EnumerateMatches_Lookahead(RegexEngine engine) return; } - const string Pattern = @"\b(?!un)\w+\b"; - const string Input = "unite one unethical ethics use untie ultimate"; + Test("unite one unethical ethics use untie ultimate", + await RegexHelpers.GetRegexAsync(engine, @"\b(?!un)\w+\b", RegexOptions.IgnoreCase), + ["one", "ethics", "use", "ultimate"]); - Regex r = RegexHelpers.GetRegexAsync(engine, Pattern, RegexOptions.IgnoreCase).GetAwaiter().GetResult(); - int count = 0; - string[] expectedMatches = ["one", "ethics", "use", "ultimate"]; - ReadOnlySpan span = Input.AsSpan(); - foreach (ValueMatch match in r.EnumerateMatches(span)) + static void Test(string input, Regex r, string[] expectedMatches) { - Assert.Equal(expectedMatches[count++], span.Slice(match.Index, match.Length).ToString()); + ReadOnlySpan span = input.AsSpan(); + + int count = 0; + foreach (ValueMatch match in r.EnumerateMatches(span)) + { + Assert.Equal(expectedMatches[count++], span.Slice(match.Index, match.Length).ToString()); + } + + Assert.Equal(expectedMatches.Length, count); } - Assert.Equal(4, count); } [Theory] [MemberData(nameof(RegexHelpers.AvailableEngines_MemberData), MemberType = typeof(RegexHelpers))] - public void EnumerateMatches_Lookbehind(RegexEngine engine) + public async Task EnumerateMatches_Lookbehind(RegexEngine engine) { if (RegexHelpers.IsNonBacktracking(engine)) { @@ -73,36 +78,45 @@ public void EnumerateMatches_Lookbehind(RegexEngine engine) return; } - const string Pattern = @"(?<=\b20)\d{2}\b"; - const string Input = "2010 1999 1861 2140 2009"; + Test("2010 1999 1861 2140 2009", + await RegexHelpers.GetRegexAsync(engine, @"(?<=\b20)\d{2}\b", RegexOptions.IgnoreCase), + ["10", "09"]); - Regex r = RegexHelpers.GetRegexAsync(engine, Pattern, RegexOptions.IgnoreCase).GetAwaiter().GetResult(); - int count = 0; - string[] expectedMatches = ["10", "09"]; - ReadOnlySpan span = Input.AsSpan(); - foreach (ValueMatch match in r.EnumerateMatches(span)) + static void Test(string input, Regex r, string[] expectedMatches) { - Assert.Equal(expectedMatches[count++], span.Slice(match.Index, match.Length).ToString()); + ReadOnlySpan span = input.AsSpan(); + + int count = 0; + foreach (ValueMatch match in r.EnumerateMatches(span)) + { + Assert.Equal(expectedMatches[count++], span.Slice(match.Index, match.Length).ToString()); + } + + Assert.Equal(expectedMatches.Length, count); } - Assert.Equal(2, count); } [Theory] [MemberData(nameof(RegexHelpers.AvailableEngines_MemberData), MemberType = typeof(RegexHelpers))] - public void EnumerateMatches_CheckIndex(RegexEngine engine) + public async Task EnumerateMatches_CheckIndex(RegexEngine engine) { - const string Pattern = @"e{2}\w\b"; - const string Input = "needing a reed"; - - Regex r = RegexHelpers.GetRegexAsync(engine, Pattern).GetAwaiter().GetResult(); - int count = 0; - string[] expectedMatches = ["eed"]; - int[] expectedIndex = [11]; - ReadOnlySpan span = Input.AsSpan(); - foreach (ValueMatch match in r.EnumerateMatches(span)) + Test("needing a reed", + await RegexHelpers.GetRegexAsync(engine, @"e{2}\w\b"), + ["eed"], + [11]); + + static void Test(string input, Regex r, string[] expectedMatches, int[] expectedIndex) { - Assert.Equal(expectedMatches[count], span.Slice(match.Index, match.Length).ToString()); - Assert.Equal(expectedIndex[count++], match.Index); + ReadOnlySpan span = input.AsSpan(); + + int count = 0; + foreach (ValueMatch match in r.EnumerateMatches(span)) + { + Assert.Equal(expectedMatches[count], span.Slice(match.Index, match.Length).ToString()); + Assert.Equal(expectedIndex[count], match.Index); + + count++; + } } } } @@ -111,19 +125,24 @@ public partial class RegexMultipleMatchTests { [Theory] [MemberData(nameof(Matches_TestData))] - public void EnumerateMatches(RegexEngine engine, string pattern, string input, RegexOptions options, CaptureData[] expected) + public async Task EnumerateMatches(RegexEngine engine, string pattern, string input, RegexOptions options, CaptureData[] expected) { - Regex regexAdvanced = RegexHelpers.GetRegexAsync(engine, pattern, options).GetAwaiter().GetResult(); - int count = 0; - ReadOnlySpan span = input.AsSpan(); - foreach (ValueMatch match in regexAdvanced.EnumerateMatches(span)) + Test(input, expected, await RegexHelpers.GetRegexAsync(engine, pattern, options)); + + static void Test(string input, CaptureData[] expected, Regex regexAdvanced) { - Assert.Equal(expected[count].Index, match.Index); - Assert.Equal(expected[count].Length, match.Length); - Assert.Equal(expected[count].Value, span.Slice(match.Index, match.Length).ToString()); - count++; + int count = 0; + ReadOnlySpan span = input.AsSpan(); + foreach (ValueMatch match in regexAdvanced.EnumerateMatches(span)) + { + Assert.Equal(expected[count].Index, match.Index); + Assert.Equal(expected[count].Length, match.Length); + Assert.Equal(expected[count].Value, span.Slice(match.Index, match.Length).ToString()); + count++; + } + + Assert.Equal(expected.Length, count); } - Assert.Equal(expected.Length, count); } } @@ -131,15 +150,20 @@ public partial class RegexMatchTests { [Theory] [MemberData(nameof(Match_Count_TestData))] - public void EnumerateMatches_Count(RegexEngine engine, string pattern, string input, int expectedCount) + public async Task EnumerateMatches_Count(RegexEngine engine, string pattern, string input, int expectedCount) { - Regex r = RegexHelpers.GetRegexAsync(engine, pattern).GetAwaiter().GetResult(); - int count = 0; - foreach (ValueMatch _ in r.EnumerateMatches(input)) + Test(input, expectedCount, await RegexHelpers.GetRegexAsync(engine, pattern)); + + static void Test(string input, int expectedCount, Regex r) { - count++; + int count = 0; + foreach (ValueMatch _ in r.EnumerateMatches(input)) + { + count++; + } + + Assert.Equal(expectedCount, count); } - Assert.Equal(expectedCount, count); } } @@ -147,55 +171,56 @@ public partial class RegexCountTests { [Theory] [MemberData(nameof(Count_ReturnsExpectedCount_TestData))] - public void EnumerateMatches_ReturnsExpectedCount(RegexEngine engine, string pattern, string input, int startat, RegexOptions options, int expectedCount) + public async Task EnumerateMatches_ReturnsExpectedCount(RegexEngine engine, string pattern, string input, int startat, RegexOptions options, int expectedCount) { - Regex r = RegexHelpers.GetRegexAsync(engine, pattern, options).GetAwaiter().GetResult(); - - int count; - - count = 0; - foreach (ValueMatch _ in r.EnumerateMatches(input, startat)) - { - count++; - } - Assert.Equal(expectedCount, count); - - bool isDefaultStartAt = startat == ((options & RegexOptions.RightToLeft) != 0 ? input.Length : 0); - if (!isDefaultStartAt) - { - return; - } + Test(engine, pattern, input, startat, options, expectedCount, await RegexHelpers.GetRegexAsync(engine, pattern, options)); - if (options == RegexOptions.None && engine == RegexEngine.Interpreter) + static void Test(RegexEngine engine, string pattern, string input, int startat, RegexOptions options, int expectedCount, Regex r) { - count = 0; - foreach (ValueMatch _ in Regex.EnumerateMatches(input, pattern)) + int count = 0; + foreach (ValueMatch _ in r.EnumerateMatches(input, startat)) { count++; } Assert.Equal(expectedCount, count); - } - switch (engine) - { - case RegexEngine.Interpreter: - case RegexEngine.Compiled: - case RegexEngine.NonBacktracking: - RegexOptions engineOptions = RegexHelpers.OptionsFromEngine(engine); - count = 0; - foreach (ValueMatch _ in Regex.EnumerateMatches(input, pattern, options | engineOptions)) - { - count++; - } - Assert.Equal(expectedCount, count); + bool isDefaultStartAt = startat == ((options & RegexOptions.RightToLeft) != 0 ? input.Length : 0); + if (!isDefaultStartAt) + { + return; + } + if (options == RegexOptions.None && engine == RegexEngine.Interpreter) + { count = 0; - foreach (ValueMatch _ in Regex.EnumerateMatches(input, pattern, options | engineOptions, Regex.InfiniteMatchTimeout)) + foreach (ValueMatch _ in Regex.EnumerateMatches(input, pattern)) { count++; } Assert.Equal(expectedCount, count); - break; + } + + switch (engine) + { + case RegexEngine.Interpreter: + case RegexEngine.Compiled: + case RegexEngine.NonBacktracking: + RegexOptions engineOptions = RegexHelpers.OptionsFromEngine(engine); + count = 0; + foreach (ValueMatch _ in Regex.EnumerateMatches(input, pattern, options | engineOptions)) + { + count++; + } + Assert.Equal(expectedCount, count); + + count = 0; + foreach (ValueMatch _ in Regex.EnumerateMatches(input, pattern, options | engineOptions, Regex.InfiniteMatchTimeout)) + { + count++; + } + Assert.Equal(expectedCount, count); + break; + } } } } diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.KnownPattern.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.KnownPattern.Tests.cs index 5748fd8df3c2..e7fe42f1cb16 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.KnownPattern.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.KnownPattern.Tests.cs @@ -1526,7 +1526,7 @@ other is not null && (Options & ~RegexOptions.Compiled) == (other.Options & ~RegexOptions.Compiled); // Compiled doesn't affect semantics, so remove it from equality for our purposes } -#if NETCOREAPP +#if NET [OuterLoop("Takes many seconds")] [Fact] public async Task PatternsDataSet_ConstructRegexForAll_NonBacktracking() diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs index 1b06272fba64..234b416a9b46 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs @@ -698,6 +698,11 @@ public static IEnumerable Match_MemberData() yield return (@"(...)(?(1)\w*|\s*)[a1 ]", "zabcaaaaaaa", RegexOptions.RightToLeft, 0, 11, true, "aaaa"); yield return (@"(...)(?(1)\w*|\s*)[a1 ]", "---- ", RegexOptions.RightToLeft, 0, 11, true, "--- "); yield return (@"(aaa)(?(1)aaa|b?)*", "aaaaaa", RegexOptions.None, 0, 6, true, "aaaaaa"); + + yield return (@"AAB|AAC", "AABAACD", RegexOptions.RightToLeft, 0, 6, true, "AAC"); + yield return (@"AAB|AA\d", "AABAACD", RegexOptions.RightToLeft, 0, 6, true, "AAB"); + yield return (@"(AB){3,}", "1234ABABABAB5678", RegexOptions.RightToLeft, 0, 16, true, "ABABABAB"); + yield return (@"(AB){1,3}", "1234ABABABAB5678", RegexOptions.RightToLeft, 0, 16, true, "ABABAB"); } // Character Class Subtraction @@ -1167,6 +1172,7 @@ public async Task Match_VaryingLengthStrings_Huge(RegexEngine engine) public static IEnumerable Match_DeepNesting_MemberData() { + foreach (RegexOptions options in new[] { RegexOptions.None, RegexOptions.IgnoreCase }) foreach (RegexEngine engine in RegexHelpers.AvailableEngines) { if (RegexHelpers.IsNonBacktracking(engine)) @@ -1175,15 +1181,15 @@ public static IEnumerable Match_DeepNesting_MemberData() continue; } - yield return new object[] { engine, 1 }; - yield return new object[] { engine, 10 }; - yield return new object[] { engine, 100 }; + yield return new object[] { engine, options, 1 }; + yield return new object[] { engine, options, 10 }; + yield return new object[] { engine, options, 100 }; } } [Theory] [MemberData(nameof(Match_DeepNesting_MemberData))] - public async Task Match_DeepNesting(RegexEngine engine, int count) + public async Task Match_DeepNesting(RegexEngine engine, RegexOptions options, int count) { const string Start = @"((?>abc|(?:def[ghi]", End = @")))"; const string Match = "defg"; @@ -1191,7 +1197,7 @@ public async Task Match_DeepNesting(RegexEngine engine, int count) string pattern = string.Concat(Enumerable.Repeat(Start, count)) + string.Concat(Enumerable.Repeat(End, count)); string input = string.Concat(Enumerable.Repeat(Match, count)); - Regex r = await RegexHelpers.GetRegexAsync(engine, pattern); + Regex r = await RegexHelpers.GetRegexAsync(engine, pattern, options); Match m = r.Match(input); Assert.True(m.Success); @@ -1321,7 +1327,7 @@ public void Match_InstanceMethods_DefaultTimeout_Throws(RegexEngine engine) }, ((int)engine).ToString(CultureInfo.InvariantCulture)).Dispose(); } -#if NET7_0_OR_GREATER +#if NET [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public void Match_InstanceMethods_DefaultTimeout_SourceGenerated_Throws() { @@ -1879,7 +1885,7 @@ public async Task Match_StartatDiffersFromBeginning(RegexEngine engine, string p Regex r = await RegexHelpers.GetRegexAsync(engine, pattern, options); Assert.Equal(expectedSuccessStartAt, r.IsMatch(input, startat)); -#if NET7_0_OR_GREATER +#if NET Assert.Equal(expectedSuccessStartAt, r.IsMatch(input.AsSpan(), startat)); #endif @@ -2063,7 +2069,7 @@ public async Task TestCharIsLowerCultureEdgeCasesAroundTurkishCharacters(RegexEn Regex r1 = await RegexHelpers.GetRegexAsync(engine, "[\u012F-\u0130]", RegexOptions.IgnoreCase); Regex r2 = await RegexHelpers.GetRegexAsync(engine, "[\u012F\u0130]", RegexOptions.IgnoreCase); Assert.Equal(r1.IsMatch("\u0130"), r2.IsMatch("\u0130")); -#if NET7_0_OR_GREATER +#if NET Assert.Equal(r1.IsMatch("\u0130".AsSpan()), r2.IsMatch("\u0130".AsSpan())); #endif @@ -2485,14 +2491,14 @@ private static void VerifyIsMatchThrows(Regex? r, string input, TimeSpan time if (r == null) { Assert.Throws(() => timeout == Regex.InfiniteMatchTimeout ? Regex.IsMatch(input, pattern, options) : Regex.IsMatch(input, pattern, options, timeout)); -#if NET7_0_OR_GREATER +#if NET Assert.Throws(() => timeout == Regex.InfiniteMatchTimeout ? Regex.IsMatch(input.AsSpan(), pattern, options) : Regex.IsMatch(input.AsSpan(), pattern, options, timeout)); #endif } else { Assert.Throws(() => r.IsMatch(input)); -#if NET7_0_OR_GREATER +#if NET Assert.Throws(() => r.IsMatch(input.AsSpan())); #endif } @@ -2507,7 +2513,7 @@ private static void VerifyIsMatch(Regex? r, string input, bool expected, TimeSpa { Assert.Equal(expected, Regex.IsMatch(input, pattern)); } -#if NET7_0_OR_GREATER +#if NET Assert.Equal(expected, timeout == Regex.InfiniteMatchTimeout ? Regex.IsMatch(input.AsSpan(), pattern, options) : Regex.IsMatch(input.AsSpan(), pattern, options, timeout)); if (options == RegexOptions.None) { @@ -2518,7 +2524,7 @@ private static void VerifyIsMatch(Regex? r, string input, bool expected, TimeSpa else { Assert.Equal(expected, r.IsMatch(input)); -#if NET7_0_OR_GREATER +#if NET Assert.Equal(expected, r.IsMatch(input.AsSpan())); #endif } diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.MultipleMatches.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.MultipleMatches.Tests.cs index 461387d71eee..ab5f20f41310 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.MultipleMatches.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.MultipleMatches.Tests.cs @@ -454,19 +454,15 @@ public static IEnumerable Matches_TestData() }; } - if (engine != RegexEngine.Interpreter && // these tests currently fail with RegexInterpreter - RuntimeFeature.IsDynamicCodeCompiled) // if dynamic code isn't compiled, RegexOptions.Compiled falls back to the interpreter, for which these tests currently fail + // Fails on .NET Framework: [ActiveIssue("https://github.com/dotnet/runtime/issues/62094")] + yield return new object[] { - // Fails on interpreter and .NET Framework: [ActiveIssue("https://github.com/dotnet/runtime/issues/62094")] - yield return new object[] + engine, @"(?:){93}", "x", RegexOptions.None, new[] { - engine, @"(?:){93}", "x", RegexOptions.None, new[] - { - new CaptureData("", 0, 0), - new CaptureData("", 1, 0) - } - }; - } + new CaptureData("", 0, 0), + new CaptureData("", 1, 0) + } + }; #endif } } diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Tests.Common.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Tests.Common.cs index 4d4f2252839a..b0a9b6549492 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Tests.Common.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Tests.Common.cs @@ -187,7 +187,7 @@ public static async Task GetRegexesAsync(RegexEngine engine, params (st /// Set the AppContext variable REGEX_NONBACKTRACKING_MAX_AUTOMATA_SIZE to the given max value. Only used with Nonbacktracking engine. public static void SetSafeSizeThreshold(int maxSize) { -#if NET7_0_OR_GREATER +#if NET AppContext.SetData("REGEX_NONBACKTRACKING_MAX_AUTOMATA_SIZE", maxSize); #endif } @@ -195,7 +195,7 @@ public static void SetSafeSizeThreshold(int maxSize) /// Remove the AppContext variable REGEX_NONBACKTRACKING_MAX_AUTOMATA_SIZE value. Only used with Nonbacktracking engine. public static void RestoreSafeSizeThresholdToDefault() { -#if NET7_0_OR_GREATER +#if NET AppContext.SetData("REGEX_NONBACKTRACKING_MAX_AUTOMATA_SIZE", null); #endif } diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexRunnerTests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexRunnerTests.cs index d4cd665e5b1a..0f5799687011 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexRunnerTests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexRunnerTests.cs @@ -50,7 +50,7 @@ public async Task EnsureRunmatchValueIsNulledAfterIsMatch(RegexEngine engine) MethodInfo getTextMethod = typeof(Match).GetMethod("get_Text", BindingFlags.Instance | BindingFlags.NonPublic); Assert.Null(getTextMethod.Invoke(runmatch, [])); Assert.Equal(string.Empty, runmatch.Value); -#if NET7_0_OR_GREATER +#if NET Assert.True(runmatch.ValueSpan == ReadOnlySpan.Empty); #endif } diff --git a/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexFindOptimizationsTests.cs b/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexFindOptimizationsTests.cs index c962bc072b6f..4c0b02b26614 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexFindOptimizationsTests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexFindOptimizationsTests.cs @@ -88,7 +88,6 @@ public void TrailingAnchor(string pattern, int options, int expectedMode, int ex [InlineData(@"(ab){2,4}(de){4,}", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "abab")] [InlineData(@"(ab){2,4}(de){4,}", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "de")] [InlineData(@"ab|(abc)|(abcd)", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "ab")] - [InlineData(@"ab|(abc)|(abcd)", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "ab")] [InlineData(@"ab(?=cd)", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "ab")] [InlineData(@"ab(?=cd)", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "ab")] [InlineData(@"\bab(?=\w)(?!=\d)c\b", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "abc")] @@ -110,6 +109,7 @@ public void LeadingPrefix(string pattern, int options, int expectedMode, string [InlineData(@"a", (int)RegexOptions.IgnoreCase | (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "Aa")] [InlineData(@"ab|cd|ef|gh", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "bdfh")] [InlineData(@"\bab(?=\w)(?!=\d)c\b", (int)(RegexOptions.IgnoreCase | RegexOptions.RightToLeft), (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "Cc")] + [InlineData(@"ab|(abc)|(abcd)", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "bcd")] public void LeadingSet(string pattern, int options, int expectedMode, string expectedChars) { RegexFindOptimizations opts = ComputeOptimizations(pattern, (RegexOptions)options); diff --git a/src/libraries/System.Threading.Channels/ref/System.Threading.Channels.csproj b/src/libraries/System.Threading.Channels/ref/System.Threading.Channels.csproj index fae9b5740497..eb088734e55a 100644 --- a/src/libraries/System.Threading.Channels/ref/System.Threading.Channels.csproj +++ b/src/libraries/System.Threading.Channels/ref/System.Threading.Channels.csproj @@ -5,13 +5,17 @@ - + + + + + diff --git a/src/libraries/System.Threading.Channels/ref/System.Threading.Channels.netcoreapp.cs b/src/libraries/System.Threading.Channels/ref/System.Threading.Channels.netcoreapp.cs index c591bf988813..37492efd644b 100644 --- a/src/libraries/System.Threading.Channels/ref/System.Threading.Channels.netcoreapp.cs +++ b/src/libraries/System.Threading.Channels/ref/System.Threading.Channels.netcoreapp.cs @@ -4,14 +4,17 @@ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ +using System.Collections.Generic; + namespace System.Threading.Channels { - public partial class ChannelClosedException : System.InvalidOperationException + public partial class Channel + { + public static System.Threading.Channels.Channel CreateUnboundedPrioritized() { throw null; } + public static System.Threading.Channels.Channel CreateUnboundedPrioritized(System.Threading.Channels.UnboundedPrioritizedChannelOptions options) { throw null; } + } + public sealed partial class UnboundedPrioritizedChannelOptions : System.Threading.Channels.ChannelOptions { -#if NET8_0_OR_GREATER - [System.ObsoleteAttribute("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId = "SYSLIB0051", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] -#endif - protected ChannelClosedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } + public System.Collections.Generic.IComparer? Comparer { get; set; } } } diff --git a/src/libraries/System.Threading.Channels/ref/System.Threading.Channels.netstandard21.cs b/src/libraries/System.Threading.Channels/ref/System.Threading.Channels.netstandard21.cs new file mode 100644 index 000000000000..c591bf988813 --- /dev/null +++ b/src/libraries/System.Threading.Channels/ref/System.Threading.Channels.netstandard21.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the https://aka.ms/api-review process. +// ------------------------------------------------------------------------------ + +namespace System.Threading.Channels +{ + public partial class ChannelClosedException : System.InvalidOperationException + { +#if NET8_0_OR_GREATER + [System.ObsoleteAttribute("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId = "SYSLIB0051", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] +#endif + protected ChannelClosedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } + } +} diff --git a/src/libraries/System.Threading.Channels/src/System.Threading.Channels.csproj b/src/libraries/System.Threading.Channels/src/System.Threading.Channels.csproj index ac68cda0be66..a5030bcee656 100644 --- a/src/libraries/System.Threading.Channels/src/System.Threading.Channels.csproj +++ b/src/libraries/System.Threading.Channels/src/System.Threading.Channels.csproj @@ -14,16 +14,10 @@ System.Threading.Channel<T> - - - @@ -31,32 +25,41 @@ System.Threading.Channel<T> + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.cs index 1e260f4c871a..834d8ad88ed1 100644 --- a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.cs +++ b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.cs @@ -1,15 +1,19 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + namespace System.Threading.Channels { /// Provides static methods for creating channels. - public static class Channel + public static partial class Channel { /// Creates an unbounded channel usable by any number of readers and writers concurrently. /// The created channel. public static Channel CreateUnbounded() => - new UnboundedChannel(runContinuationsAsynchronously: true); + new UnboundedChannel>(new(new()), runContinuationsAsynchronously: true); /// Creates an unbounded channel subject to the provided options. /// Specifies the type of data in the channel. @@ -27,7 +31,7 @@ public static Channel CreateUnbounded(UnboundedChannelOptions options) return new SingleConsumerUnboundedChannel(!options.AllowSynchronousContinuations); } - return new UnboundedChannel(!options.AllowSynchronousContinuations); + return new UnboundedChannel>(new(new()), !options.AllowSynchronousContinuations); } /// Creates a channel with the specified maximum capacity. @@ -71,5 +75,32 @@ public static Channel CreateBounded(BoundedChannelOptions options, Action< return new BoundedChannel(options.Capacity, options.FullMode, !options.AllowSynchronousContinuations, itemDropped); } + + /// Provides an for a . + private readonly struct UnboundedChannelConcurrentQueue(ConcurrentQueue queue) : IUnboundedChannelQueue + { + private readonly ConcurrentQueue _queue = queue; + + /// + public bool IsThreadSafe => true; + + /// + public void Enqueue(T item) => _queue.Enqueue(item); + + /// + public bool TryDequeue([MaybeNullWhen(false)] out T item) => _queue.TryDequeue(out item); + + /// + public bool TryPeek([MaybeNullWhen(false)] out T item) => _queue.TryPeek(out item); + + /// + public int Count => _queue.Count; + + /// + public bool IsEmpty => _queue.IsEmpty; + + /// + public IEnumerator GetEnumerator() => _queue.GetEnumerator(); + } } } diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.netcoreapp.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.netcoreapp.cs new file mode 100644 index 000000000000..c8fc9baebae7 --- /dev/null +++ b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/Channel.netcoreapp.cs @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace System.Threading.Channels +{ + /// Provides static methods for creating channels. + public static partial class Channel + { + /// Creates an unbounded prioritized channel usable by any number of readers and writers concurrently. + /// Specifies the type of data in the channel. + /// The created channel. + /// + /// is used to determine priority of elements. + /// The next item read from the channel will be the element available in the channel with the lowest priority value. + /// + public static Channel CreateUnboundedPrioritized() => + new UnboundedChannel>(new(new()), runContinuationsAsynchronously: true); + + /// Creates an unbounded prioritized channel subject to the provided options. + /// Specifies the type of data in the channel. + /// Options that guide the behavior of the channel. + /// The created channel. + /// + /// The supplied ' is used to determine priority of elements, + /// or if the provided comparer is null. + /// The next item read from the channel will be the element available in the channel with the lowest priority value. + /// + public static Channel CreateUnboundedPrioritized(UnboundedPrioritizedChannelOptions options) + { + ArgumentNullException.ThrowIfNull(options); + + return new UnboundedChannel>(new(new(options.Comparer)), !options.AllowSynchronousContinuations); + } + + /// Provides an for a . + private readonly struct UnboundedChannelPriorityQueue(PriorityQueue queue) : IUnboundedChannelQueue + { + private readonly PriorityQueue _queue = queue; + + /// + public bool IsThreadSafe => false; + + /// + public void Enqueue(T item) => _queue.Enqueue(true, item); + + /// + public bool TryDequeue([MaybeNullWhen(false)] out T item) => _queue.TryDequeue(out _, out item); + + /// + public bool TryPeek([MaybeNullWhen(false)] out T item) => _queue.TryPeek(out _, out item); + + /// + public int Count => _queue.Count; + + /// + public bool IsEmpty => _queue.Count == 0; + + /// + public IEnumerator GetEnumerator() + { + List list = []; + foreach ((bool _, T Priority) item in _queue.UnorderedItems) + { + list.Add(item.Priority); + } + + list.Sort(_queue.Comparer); + + return list.GetEnumerator(); + } + } + } +} diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/ChannelOptions.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/ChannelOptions.cs index bbde42638c84..ab3a722bb909 100644 --- a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/ChannelOptions.cs +++ b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/ChannelOptions.cs @@ -39,7 +39,7 @@ public abstract class ChannelOptions public bool AllowSynchronousContinuations { get; set; } } - /// Provides options that control the behavior of instances. + /// Provides options that control the behavior of instances created by . public sealed class BoundedChannelOptions : ChannelOptions { /// The maximum number of items the bounded channel may store. @@ -94,7 +94,7 @@ public BoundedChannelFullMode FullMode } } - /// Provides options that control the behavior of instances. + /// Provides options that control the behavior of instances created by . public sealed class UnboundedChannelOptions : ChannelOptions { } diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/ChannelOptions.netcoreapp.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/ChannelOptions.netcoreapp.cs new file mode 100644 index 000000000000..bfa672fa8a93 --- /dev/null +++ b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/ChannelOptions.netcoreapp.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; + +namespace System.Threading.Channels +{ + /// Provides options that control the behavior of instances created by . + public sealed class UnboundedPrioritizedChannelOptions : ChannelOptions + { + /// Gets or sets the comparer used by the channel to prioritize elements. + public IComparer? Comparer { get; set; } + } +} diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/IDebugEnumerator.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/IDebugEnumerator.cs index a3d072ee9f7c..af2a77bb1bf7 100644 --- a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/IDebugEnumerator.cs +++ b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/IDebugEnumerator.cs @@ -11,7 +11,7 @@ internal interface IDebugEnumerable IEnumerator GetEnumerator(); } - internal sealed class DebugEnumeratorDebugView + internal class DebugEnumeratorDebugView { public DebugEnumeratorDebugView(IDebugEnumerable enumerable) { @@ -26,4 +26,6 @@ public DebugEnumeratorDebugView(IDebugEnumerable enumerable) [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public T[] Items { get; } } + + internal sealed class DebugEnumeratorDebugView(IDebugEnumerable enumerable) : DebugEnumeratorDebugView(enumerable); } diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/IUnboundedChannelQueue.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/IUnboundedChannelQueue.cs new file mode 100644 index 000000000000..b1b65a1dffeb --- /dev/null +++ b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/IUnboundedChannelQueue.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace System.Threading.Channels +{ + /// Representation of the queue data structure used by . + internal interface IUnboundedChannelQueue : IDebugEnumerable + { + /// Gets whether the other members are safe to use concurrently with each other and themselves. + bool IsThreadSafe { get; } + + /// Enqueues an item into the queue. + /// The item to enqueue. + void Enqueue(T item); + + /// Dequeues an item from the queue, if possible. + /// The dequeued item, or default if the queue was empty. + /// Whether an item was dequeued. + bool TryDequeue([MaybeNullWhen(false)] out T item); + + /// Peeks at the next item from the queue that would be dequeued, if possible. + /// The peeked item, or default if the queue was empty. + /// Whether an item was peeked. + bool TryPeek([MaybeNullWhen(false)] out T item); + + /// Gets the number of elements in the queue. + int Count { get; } + + /// Gets whether the queue is empty. + bool IsEmpty { get; } + } +} diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/UnboundedChannel.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/UnboundedChannel.cs index fb3facf83dc4..ad7ee0e3608d 100644 --- a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/UnboundedChannel.cs +++ b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/UnboundedChannel.cs @@ -5,19 +5,20 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Threading.Tasks; namespace System.Threading.Channels { /// Provides a buffered channel of unbounded capacity. [DebuggerDisplay("Items = {ItemsCountForDebugger}, Closed = {ChannelIsClosedForDebugger}")] - [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<>))] - internal sealed class UnboundedChannel : Channel, IDebugEnumerable + [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<,>))] + internal sealed class UnboundedChannel : Channel, IDebugEnumerable where TQueue : struct, IUnboundedChannelQueue { /// Task that indicates the channel has completed. private readonly TaskCompletionSource _completion; /// The items in the channel. - private readonly ConcurrentQueue _items = new ConcurrentQueue(); + private readonly TQueue _items; /// Readers blocked reading from the channel. private readonly Deque> _blockedReaders = new Deque>(); /// Whether to force continuations to be executed asynchronously from producer writes. @@ -29,8 +30,9 @@ internal sealed class UnboundedChannel : Channel, IDebugEnumerable private Exception? _doneWriting; /// Initialize the channel. - internal UnboundedChannel(bool runContinuationsAsynchronously) + internal UnboundedChannel(TQueue items, bool runContinuationsAsynchronously) { + _items = items; _runContinuationsAsynchronously = runContinuationsAsynchronously; _completion = new TaskCompletionSource(runContinuationsAsynchronously ? TaskCreationOptions.RunContinuationsAsynchronously : TaskCreationOptions.None); Reader = new UnboundedChannelReader(this); @@ -38,14 +40,14 @@ internal UnboundedChannel(bool runContinuationsAsynchronously) } [DebuggerDisplay("Items = {Count}")] - [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<>))] + [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<,>))] private sealed class UnboundedChannelReader : ChannelReader, IDebugEnumerable { - internal readonly UnboundedChannel _parent; + internal readonly UnboundedChannel _parent; private readonly AsyncOperation _readerSingleton; private readonly AsyncOperation _waiterSingleton; - internal UnboundedChannelReader(UnboundedChannel parent) + internal UnboundedChannelReader(UnboundedChannel parent) { _parent = parent; _readerSingleton = new AsyncOperation(parent._runContinuationsAsynchronously, pooled: true); @@ -68,8 +70,8 @@ public override ValueTask ReadAsync(CancellationToken cancellationToken) } // Dequeue an item if we can. - UnboundedChannel parent = _parent; - if (parent._items.TryDequeue(out T? item)) + UnboundedChannel parent = _parent; + if (parent._items.IsThreadSafe && parent._items.TryDequeue(out T? item)) { CompleteIfDone(parent); return new ValueTask(item); @@ -112,24 +114,60 @@ public override ValueTask ReadAsync(CancellationToken cancellationToken) public override bool TryRead([MaybeNullWhen(false)] out T item) { - UnboundedChannel parent = _parent; + UnboundedChannel parent = _parent; + return parent._items.IsThreadSafe ? + LockFree(parent, out item) : + Locked(parent, out item); - // Dequeue an item if we can - if (parent._items.TryDequeue(out item)) + static bool LockFree(UnboundedChannel parent, [MaybeNullWhen(false)] out T item) { - CompleteIfDone(parent); - return true; + if (parent._items.TryDequeue(out item)) + { + CompleteIfDone(parent); + return true; + } + + item = default; + return false; } - item = default; - return false; + static bool Locked(UnboundedChannel parent, [MaybeNullWhen(false)] out T item) + { + lock (parent.SyncObj) + { + if (parent._items.TryDequeue(out item)) + { + CompleteIfDone(parent); + return true; + } + } + + item = default; + return false; + } } - public override bool TryPeek([MaybeNullWhen(false)] out T item) => - _parent._items.TryPeek(out item); + public override bool TryPeek([MaybeNullWhen(false)] out T item) + { + UnboundedChannel parent = _parent; + return parent._items.IsThreadSafe ? + parent._items.TryPeek(out item) : + Locked(parent, out item); + + // Separated out to keep the try/finally from preventing TryPeek from being inlined + static bool Locked(UnboundedChannel parent, [MaybeNullWhen(false)] out T item) + { + lock (parent.SyncObj) + { + return parent._items.TryPeek(out item); + } + } + } - private static void CompleteIfDone(UnboundedChannel parent) + private static void CompleteIfDone(UnboundedChannel parent) { + Debug.Assert(parent._items.IsThreadSafe || Monitor.IsEntered(parent.SyncObj)); + if (parent._doneWriting != null && parent._items.IsEmpty) { // If we've now emptied the items queue and we're not getting any more, complete. @@ -144,12 +182,12 @@ public override ValueTask WaitToReadAsync(CancellationToken cancellationTo return new ValueTask(Task.FromCanceled(cancellationToken)); } - if (!_parent._items.IsEmpty) + if (_parent._items.IsThreadSafe && !_parent._items.IsEmpty) { return new ValueTask(true); } - UnboundedChannel parent = _parent; + UnboundedChannel parent = _parent; lock (parent.SyncObj) { @@ -192,15 +230,15 @@ public override ValueTask WaitToReadAsync(CancellationToken cancellationTo } [DebuggerDisplay("Items = {ItemsCountForDebugger}")] - [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<>))] + [DebuggerTypeProxy(typeof(DebugEnumeratorDebugView<,>))] private sealed class UnboundedChannelWriter : ChannelWriter, IDebugEnumerable { - internal readonly UnboundedChannel _parent; - internal UnboundedChannelWriter(UnboundedChannel parent) => _parent = parent; + internal readonly UnboundedChannel _parent; + internal UnboundedChannelWriter(UnboundedChannel parent) => _parent = parent; public override bool TryComplete(Exception? error) { - UnboundedChannel parent = _parent; + UnboundedChannel parent = _parent; bool completeTask; lock (parent.SyncObj) @@ -240,7 +278,7 @@ public override bool TryComplete(Exception? error) public override bool TryWrite(T item) { - UnboundedChannel parent = _parent; + UnboundedChannel parent = _parent; while (true) { AsyncOperation? blockedReader = null; @@ -321,7 +359,7 @@ public override ValueTask WriteAsync(T item, CancellationToken cancellationToken } /// Gets the object used to synchronize access to all state on this instance. - private object SyncObj => _items; + private object SyncObj => _blockedReaders; [Conditional("DEBUG")] private void AssertInvariants() diff --git a/src/libraries/System.Threading.Channels/tests/PriorityUnboundedChannelTests.cs b/src/libraries/System.Threading.Channels/tests/PriorityUnboundedChannelTests.cs new file mode 100644 index 000000000000..1280db17b3fb --- /dev/null +++ b/src/libraries/System.Threading.Channels/tests/PriorityUnboundedChannelTests.cs @@ -0,0 +1,108 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Xunit; + +namespace System.Threading.Channels.Tests +{ + public class UnboundedPrioritizedChannelTests : UnboundedChannelTests + { + protected override Channel CreateChannel() => Channel.CreateUnboundedPrioritized(new() { AllowSynchronousContinuations = AllowSynchronousContinuations }); + + [Fact] + public void ItemsReadInExpectedOrder_NoComparer() + { + Channel c = CreateChannel(); + + for (int trial = 0; trial < 2; trial++) + { + Assert.True(c.Writer.WriteAsync(new Person { Age = 20 }).IsCompletedSuccessfully); + Assert.Equal(1, c.Reader.Count); + + Assert.True(c.Writer.WriteAsync(new Person { Age = 21 }).IsCompletedSuccessfully); + Assert.Equal(2, c.Reader.Count); + + Assert.True(c.Writer.WriteAsync(new Person { Age = 19 }).IsCompletedSuccessfully); + Assert.Equal(3, c.Reader.Count); + + Assert.True(c.Reader.TryRead(out Person p)); + Assert.Equal(19, p.Age); + Assert.Equal(2, c.Reader.Count); + + Assert.True(c.Writer.WriteAsync(new Person { Age = 18 }).IsCompletedSuccessfully); + Assert.Equal(3, c.Reader.Count); + + Assert.True(c.Writer.WriteAsync(new Person { Age = 22 }).IsCompletedSuccessfully); + Assert.Equal(4, c.Reader.Count); + + Assert.True(c.Reader.TryRead(out p)); + Assert.Equal(18, p.Age); + Assert.Equal(3, c.Reader.Count); + + Assert.True(c.Reader.TryRead(out p)); + Assert.Equal(20, p.Age); + Assert.Equal(2, c.Reader.Count); + + Assert.True(c.Reader.TryRead(out p)); + Assert.Equal(21, p.Age); + Assert.Equal(1, c.Reader.Count); + + Assert.True(c.Reader.TryRead(out p)); + Assert.Equal(22, p.Age); + Assert.Equal(0, c.Reader.Count); + } + } + + [Fact] + public void ItemsReadInExpectedOrder_Comparer() + { + Channel c = Channel.CreateUnboundedPrioritized(new UnboundedPrioritizedChannelOptions { Comparer = Comparer.Create((p1, p2) => p2.Age.CompareTo(p1.Age)) }); + + for (int trial = 0; trial < 2; trial++) + { + Assert.True(c.Writer.WriteAsync(new Person { Age = 20 }).IsCompletedSuccessfully); + Assert.Equal(1, c.Reader.Count); + + Assert.True(c.Writer.WriteAsync(new Person { Age = 21 }).IsCompletedSuccessfully); + Assert.Equal(2, c.Reader.Count); + + Assert.True(c.Writer.WriteAsync(new Person { Age = 19 }).IsCompletedSuccessfully); + Assert.Equal(3, c.Reader.Count); + + Assert.True(c.Reader.TryRead(out Person p)); + Assert.Equal(21, p.Age); + Assert.Equal(2, c.Reader.Count); + + Assert.True(c.Writer.WriteAsync(new Person { Age = 18 }).IsCompletedSuccessfully); + Assert.Equal(3, c.Reader.Count); + + Assert.True(c.Writer.WriteAsync(new Person { Age = 22 }).IsCompletedSuccessfully); + Assert.Equal(4, c.Reader.Count); + + Assert.True(c.Reader.TryRead(out p)); + Assert.Equal(22, p.Age); + Assert.Equal(3, c.Reader.Count); + + Assert.True(c.Reader.TryRead(out p)); + Assert.Equal(20, p.Age); + Assert.Equal(2, c.Reader.Count); + + Assert.True(c.Reader.TryRead(out p)); + Assert.Equal(19, p.Age); + Assert.Equal(1, c.Reader.Count); + + Assert.True(c.Reader.TryRead(out p)); + Assert.Equal(18, p.Age); + Assert.Equal(0, c.Reader.Count); + } + } + + private struct Person : IComparable + { + public int Age { get; set; } + + public int CompareTo(Person other) => Age.CompareTo(other.Age); + } + } +} diff --git a/src/libraries/System.Threading.Channels/tests/System.Threading.Channels.Tests.csproj b/src/libraries/System.Threading.Channels/tests/System.Threading.Channels.Tests.csproj index 7d929a96eade..7d22b2afdee0 100644 --- a/src/libraries/System.Threading.Channels/tests/System.Threading.Channels.Tests.csproj +++ b/src/libraries/System.Threading.Channels/tests/System.Threading.Channels.Tests.csproj @@ -6,7 +6,6 @@ - @@ -15,6 +14,10 @@ + + + + diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs index 6b5a4014990e..bab7263c2b1c 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs @@ -156,8 +156,17 @@ protected override ValueTask AcquireAsyncCore(int permitCount, C Debug.Assert(_queueCount >= 0); if (!oldestRequest.TrySetResult(FailedLease)) { - // Updating queue count is handled by the cancellation code - _queueCount += oldestRequest.Count; + if (!oldestRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + oldestRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += oldestRequest.Count; + } } else { @@ -277,10 +286,19 @@ private void Release(int releaseCount) // Check if request was canceled if (!nextPendingRequest.TrySetResult(lease)) { - // Queued item was canceled so add count back + // Queued item was canceled so add count back, permits weren't acquired _permitCount += nextPendingRequest.Count; - // Updating queue count is handled by the cancellation code - _queueCount += nextPendingRequest.Count; + if (!nextPendingRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + nextPendingRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += nextPendingRequest.Count; + } } else { @@ -399,6 +417,9 @@ private sealed class RequestRegistration : TaskCompletionSource private readonly CancellationToken _cancellationToken; private CancellationTokenRegistration _cancellationTokenRegistration; + // Update under the limiter lock and only if the queue count was updated by the calling code + public bool QueueCountModified { get; set; } + // this field is used only by the disposal mechanics and never shared between threads private RequestRegistration? _next; @@ -413,7 +434,7 @@ public RequestRegistration(int permitCount, ConcurrencyLimiter limiter, Cancella // is going to invoke the callback synchronously, but this does not create // a deadlock because lock are reentrant if (cancellationToken.CanBeCanceled) -#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER +#if NET || NETSTANDARD2_1_OR_GREATER _cancellationTokenRegistration = cancellationToken.UnsafeRegister(Cancel, this); #else _cancellationTokenRegistration = cancellationToken.Register(Cancel, this); @@ -429,7 +450,14 @@ private static void Cancel(object? state) var limiter = (ConcurrencyLimiter)registration.Task.AsyncState!; lock (limiter.Lock) { - limiter._queueCount -= registration.Count; + // Queuing and replenishing code might modify the _queueCount, since there is no guarantee of when the cancellation + // code runs and we only want to update the _queueCount once, we set a bool (under a lock) so either method + // can update the count and not double count. + if (!registration.QueueCountModified) + { + limiter._queueCount -= registration.Count; + registration.QueueCountModified = true; + } } } } diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs index d09c7973b18a..7ed567f174a5 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs @@ -173,7 +173,17 @@ protected override ValueTask AcquireAsyncCore(int permitCount, C Debug.Assert(_queueCount >= 0); if (!oldestRequest.TrySetResult(FailedLease)) { - _queueCount += oldestRequest.Count; + if (!oldestRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + oldestRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += oldestRequest.Count; + } } else { @@ -330,10 +340,19 @@ private void ReplenishInternal(long nowTicks) if (!nextPendingRequest.TrySetResult(SuccessfulLease)) { - // Queued item was canceled so add count back + // Queued item was canceled so add count back, permits weren't acquired _permitCount += nextPendingRequest.Count; - // Updating queue count is handled by the cancellation code - _queueCount += nextPendingRequest.Count; + if (!nextPendingRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + nextPendingRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += nextPendingRequest.Count; + } } else { @@ -435,6 +454,9 @@ private sealed class RequestRegistration : TaskCompletionSource private readonly CancellationToken _cancellationToken; private CancellationTokenRegistration _cancellationTokenRegistration; + // Update under the limiter lock and only if the queue count was updated by the calling code + public bool QueueCountModified { get; set; } + // this field is used only by the disposal mechanics and never shared between threads private RequestRegistration? _next; @@ -449,7 +471,7 @@ public RequestRegistration(int permitCount, FixedWindowRateLimiter limiter, Canc // is going to invoke the callback synchronously, but this does not create // a deadlock because lock are reentrant if (cancellationToken.CanBeCanceled) -#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER +#if NET || NETSTANDARD2_1_OR_GREATER _cancellationTokenRegistration = cancellationToken.UnsafeRegister(Cancel, this); #else _cancellationTokenRegistration = cancellationToken.Register(Cancel, this); @@ -465,7 +487,14 @@ private static void Cancel(object? state) var limiter = (FixedWindowRateLimiter)registration.Task.AsyncState!; lock (limiter.Lock) { - limiter._queueCount -= registration.Count; + // Queuing and replenishing code might modify the _queueCount, since there is no guarantee of when the cancellation + // code runs and we only want to update the _queueCount once, we set a bool (under a lock) so either method + // can update the count and not double count. + if (!registration.QueueCountModified) + { + limiter._queueCount -= registration.Count; + registration.QueueCountModified = true; + } } } } diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs index a179720ede33..16398459a4d8 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs @@ -185,7 +185,17 @@ protected override ValueTask AcquireAsyncCore(int permitCount, C Debug.Assert(_queueCount >= 0); if (!oldestRequest.TrySetResult(FailedLease)) { - _queueCount += oldestRequest.Count; + if (!oldestRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + oldestRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += oldestRequest.Count; + } } else { @@ -342,11 +352,20 @@ private void ReplenishInternal(long nowTicks) if (!nextPendingRequest.TrySetResult(SuccessfulLease)) { - // Queued item was canceled so add count back + // Queued item was canceled so add count back, permits weren't acquired _permitCount += nextPendingRequest.Count; _requestsPerSegment[_currentSegmentIndex] -= nextPendingRequest.Count; - // Updating queue count is handled by the cancellation code - _queueCount += nextPendingRequest.Count; + if (!nextPendingRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + nextPendingRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += nextPendingRequest.Count; + } } else { @@ -448,6 +467,9 @@ private sealed class RequestRegistration : TaskCompletionSource private readonly CancellationToken _cancellationToken; private CancellationTokenRegistration _cancellationTokenRegistration; + // Update under the limiter lock and only if the queue count was updated by the calling code + public bool QueueCountModified { get; set; } + // this field is used only by the disposal mechanics and never shared between threads private RequestRegistration? _next; @@ -462,7 +484,7 @@ public RequestRegistration(int permitCount, SlidingWindowRateLimiter limiter, Ca // is going to invoke the callback synchronously, but this does not create // a deadlock because lock are reentrant if (cancellationToken.CanBeCanceled) -#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER +#if NET || NETSTANDARD2_1_OR_GREATER _cancellationTokenRegistration = cancellationToken.UnsafeRegister(Cancel, this); #else _cancellationTokenRegistration = cancellationToken.Register(Cancel, this); @@ -478,7 +500,14 @@ private static void Cancel(object? state) var limiter = (SlidingWindowRateLimiter)registration.Task.AsyncState!; lock (limiter.Lock) { - limiter._queueCount -= registration.Count; + // Queuing and replenishing code might modify the _queueCount, since there is no guarantee of when the cancellation + // code runs and we only want to update the _queueCount once, we set a bool (under a lock) so either method + // can update the count and not double count. + if (!registration.QueueCountModified) + { + limiter._queueCount -= registration.Count; + registration.QueueCountModified = true; + } } } } diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs index 5ad7859792ff..73d78efdc680 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs @@ -178,8 +178,17 @@ protected override ValueTask AcquireAsyncCore(int tokenCount, Ca Debug.Assert(_queueCount >= 0); if (!oldestRequest.TrySetResult(FailedLease)) { - // Updating queue count is handled by the cancellation code - _queueCount += oldestRequest.Count; + if (!oldestRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + oldestRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += oldestRequest.Count; + } } else { @@ -345,10 +354,19 @@ private void ReplenishInternal(long nowTicks) if (!nextPendingRequest.TrySetResult(SuccessfulLease)) { - // Queued item was canceled so add count back + // Queued item was canceled so add count back, permits weren't acquired _tokenCount += nextPendingRequest.Count; - // Updating queue count is handled by the cancellation code - _queueCount += nextPendingRequest.Count; + if (!nextPendingRequest.QueueCountModified) + { + // We already updated the queue count, the Cancel code is about to run or running and waiting on our lock, + // tell Cancel not to do anything + nextPendingRequest.QueueCountModified = true; + } + else + { + // Updating queue count was handled by the cancellation code, don't double count + _queueCount += nextPendingRequest.Count; + } } else { @@ -450,6 +468,9 @@ private sealed class RequestRegistration : TaskCompletionSource private readonly CancellationToken _cancellationToken; private CancellationTokenRegistration _cancellationTokenRegistration; + // Update under the limiter lock and only if the queue count was updated by the calling code + public bool QueueCountModified { get; set; } + // this field is used only by the disposal mechanics and never shared between threads private RequestRegistration? _next; @@ -464,7 +485,7 @@ public RequestRegistration(int permitCount, TokenBucketRateLimiter limiter, Canc // is going to invoke the callback synchronously, but this does not create // a deadlock because lock are reentrant if (cancellationToken.CanBeCanceled) -#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER +#if NET || NETSTANDARD2_1_OR_GREATER _cancellationTokenRegistration = cancellationToken.UnsafeRegister(Cancel, this); #else _cancellationTokenRegistration = cancellationToken.Register(Cancel, this); @@ -480,7 +501,14 @@ private static void Cancel(object? state) var limiter = (TokenBucketRateLimiter)registration.Task.AsyncState!; lock (limiter.Lock) { - limiter._queueCount -= registration.Count; + // Queuing and replenishing code might modify the _queueCount, since there is no guarantee of when the cancellation + // code runs and we only want to update the _queueCount once, we set a bool (under a lock) so either method + // can update the count and not double count. + if (!registration.QueueCountModified) + { + limiter._queueCount -= registration.Count; + registration.QueueCountModified = true; + } } } } diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs b/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs index 63cdedf4b466..7b7064f948f1 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs @@ -1434,63 +1434,48 @@ public static Task OutputAvailableAsync(this ISourceBlock OutputAvailableAsync( this ISourceBlock source, CancellationToken cancellationToken) { - if (source is null) - { - throw new ArgumentNullException(nameof(source)); - } - - // Fast path for cancellation - if (cancellationToken.IsCancellationRequested) - return Common.CreateTaskFromCancellation(cancellationToken); - - // In a method like this, normally we would want to check source.Completion.IsCompleted - // and avoid linking completely by simply returning a completed task. However, - // some blocks that are completed still have data available, like WriteOnceBlock, - // which completes as soon as it gets a value and stores that value forever. - // As such, OutputAvailableAsync must link from the source so that the source - // can push data to us if it has it, at which point we can immediately unlink. + return + source is null ? throw new ArgumentNullException(nameof(source)) : + cancellationToken.IsCancellationRequested ? Common.CreateTaskFromCancellation(cancellationToken) : + Impl(source, cancellationToken); - // Create a target task that will complete when it's offered a message (but it won't accept the message) - var target = new OutputAvailableAsyncTarget(); - try + static async Task Impl(ISourceBlock source, CancellationToken cancellationToken) { - // Link from the source. If the source propagates a message during or immediately after linking - // such that our target is already completed, just return its task. - target._unlinker = source.LinkTo(target, DataflowLinkOptions.UnlinkAfterOneAndPropagateCompletion); + // In a method like this, normally we would want to check source.Completion.IsCompleted + // and avoid linking completely by simply returning a completed task. However, + // some blocks that are completed still have data available, like WriteOnceBlock, + // which completes as soon as it gets a value and stores that value forever. + // As such, OutputAvailableAsync must link from the source so that the source + // can push data to us if it has it, at which point we can immediately unlink. - // If the task is already completed (an exception may have occurred, or the source may have propagated - // a message to the target during LinkTo or soon thereafter), just return the task directly. - if (target.Task.IsCompleted) - { - return target.Task; - } + // Create a target task that will complete when it's offered a message (but it won't accept the message) + var target = new OutputAvailableAsyncTarget(); - // If cancellation could be requested, hook everything up to be notified of cancellation requests. - if (cancellationToken.CanBeCanceled) + // Link from the source. + using (source.LinkTo(target, DataflowLinkOptions.UnlinkAfterOneAndPropagateCompletion)) { - // When cancellation is requested, unlink the target from the source and cancel the target. - target._ctr = cancellationToken.Register( -#if NET6_0_OR_GREATER - OutputAvailableAsyncTarget.CancelAndUnlink, + CancellationTokenRegistration registration = default; + try + { + // Register for cancellation if the target isn't already completed (the source may have propagated + // a message to the target during LinkTo or soon thereafter). + if (!target.Task.IsCompleted) + { + registration = +#if NET + cancellationToken.UnsafeRegister(static (state, cancellationToken) => ((OutputAvailableAsyncTarget)state!).TrySetCanceled(cancellationToken), target); #else - static state => OutputAvailableAsyncTarget.CancelAndUnlink(state, default), + cancellationToken.Register(static state => ((OutputAvailableAsyncTarget)state!).TrySetCanceled(), target); #endif - target); - } - - return target.Task; - } - catch (Exception exc) - { - // Source.LinkTo could throw, as could cancellationToken.Register if cancellation was already requested - // such that it synchronously invokes the source's unlinker IDisposable, which could throw. - target.TrySetException(exc); - - // Undo the link from the source to the target - target.AttemptThreadSafeUnlink(); + } - // Return the now faulted task - return target.Task; + return await target.Task.ConfigureAwait(false); + } + finally + { + registration.Dispose(); + } + } } } @@ -1504,46 +1489,6 @@ public OutputAvailableAsyncTarget() : { } - /// - /// Cached continuation delegate that unregisters from cancellation and - /// marshals the antecedent's result to the return value. - /// - internal static readonly Func, object?, bool> s_handleCompletion = (antecedent, state) => - { - var target = state as OutputAvailableAsyncTarget; - Debug.Assert(target != null, "Expected non-null target"); - target._ctr.Dispose(); - return antecedent.GetAwaiter().GetResult(); - }; - - /// Cancels the target and unlinks the target from the source. - /// An OutputAvailableAsyncTarget. - /// The token that triggered cancellation - internal static void CancelAndUnlink(object? state, CancellationToken cancellationToken) - { - var target = state as OutputAvailableAsyncTarget; - Debug.Assert(target != null, "Expected a non-null target"); - - target.TrySetCanceled(cancellationToken); - target.AttemptThreadSafeUnlink(); - } - - /// Disposes of _unlinker if the target has been linked. - internal void AttemptThreadSafeUnlink() - { - // A race is possible. Therefore use an interlocked operation. - IDisposable? cachedUnlinker = _unlinker; - if (cachedUnlinker != null && Interlocked.CompareExchange(ref _unlinker, null, cachedUnlinker) == cachedUnlinker) - { - cachedUnlinker.Dispose(); - } - } - - /// The IDisposable used to unlink this target from its source. - internal IDisposable? _unlinker; - /// The registration used to unregister this target from the cancellation token. - internal CancellationTokenRegistration _ctr; - /// Completes the task when offered a message (but doesn't consume the message). DataflowMessageStatus ITargetBlock.OfferMessage(DataflowMessageHeader messageHeader, T messageValue, ISourceBlock? source, bool consumeToAccept) { @@ -1551,14 +1496,12 @@ DataflowMessageStatus ITargetBlock.OfferMessage(DataflowMessageHeader message if (source == null) throw new ArgumentNullException(nameof(source)); TrySetResult(true); + return DataflowMessageStatus.DecliningPermanently; } /// - void IDataflowBlock.Complete() - { - TrySetResult(false); - } + void IDataflowBlock.Complete() => TrySetResult(false); /// void IDataflowBlock.Fault(Exception exception) @@ -1572,13 +1515,13 @@ void IDataflowBlock.Fault(Exception exception) } /// - Task IDataflowBlock.Completion { get { throw new NotSupportedException(SR.NotSupported_MemberNotNeeded); } } + Task IDataflowBlock.Completion => throw new NotSupportedException(SR.NotSupported_MemberNotNeeded); /// The data to display in the debugger display attribute. private object DebuggerDisplayContent => $"{Common.GetNameForDebugger(this)} IsCompleted = {base.Task.IsCompleted}"; /// Gets the data to display in the debugger display attribute for this instance. - object IDebuggerDisplay.Content { get { return DebuggerDisplayContent; } } + object IDebuggerDisplay.Content => DebuggerDisplayContent; } #endregion diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/Common.cs b/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/Common.cs index 7bfd3ecf35d9..c04ee9556003 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/Common.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/Common.cs @@ -190,7 +190,7 @@ internal static void WireCancellationToComplete( // data, and we also want to dispose of that registration when we complete so that we don't // leak into a long-living cancellation token. CancellationTokenRegistration reg = cancellationToken.Register( -#if NET6_0_OR_GREATER +#if NET completeAction, completeState #else state => diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj b/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj index 2a1eaf2804e3..21e1af107050 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj @@ -80,6 +80,7 @@ System.Threading.Tasks.Dataflow.WriteOnceBlock<T> + diff --git a/src/libraries/System.Threading.Tasks.Parallel/src/System.Threading.Tasks.Parallel.csproj b/src/libraries/System.Threading.Tasks.Parallel/src/System.Threading.Tasks.Parallel.csproj index 3278b9f2c5e1..32d0f7c8cf6a 100644 --- a/src/libraries/System.Threading.Tasks.Parallel/src/System.Threading.Tasks.Parallel.csproj +++ b/src/libraries/System.Threading.Tasks.Parallel/src/System.Threading.Tasks.Parallel.csproj @@ -24,6 +24,7 @@ + diff --git a/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForTests.cs b/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForTests.cs index 8093dc661b87..399ba8c63f5e 100644 --- a/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForTests.cs +++ b/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForTests.cs @@ -1211,7 +1211,6 @@ public static void RunParallelLoopCancellationTests() /// Test to ensure that the task ID can be accessed from inside the task /// [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91583", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public static void TaskIDFromExternalContextTest() { int? withinTaskId = int.MinValue; diff --git a/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs b/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs index 408fe376752c..64f46a74635b 100644 --- a/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs +++ b/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs @@ -31,7 +31,7 @@ internal sealed class CdsSyncEtwBCLProvider : EventSource /// Defines the singleton instance for the CDS Sync ETW provider. /// The CDS Sync Event provider GUID is {EC631D38-466B-4290-9306-834971BA0217}. /// - public static CdsSyncEtwBCLProvider Log = new CdsSyncEtwBCLProvider(); + public static readonly CdsSyncEtwBCLProvider Log = new CdsSyncEtwBCLProvider(); /// Prevent external instantiation. All logging should go through the Log instance. private CdsSyncEtwBCLProvider() { } diff --git a/src/libraries/System.Threading/tests/InterlockedTests.cs b/src/libraries/System.Threading/tests/InterlockedTests.cs index b9f61749c80b..ae9cd493f4df 100644 --- a/src/libraries/System.Threading/tests/InterlockedTests.cs +++ b/src/libraries/System.Threading/tests/InterlockedTests.cs @@ -810,7 +810,7 @@ public void MemoryBarrierProcessWide() } })); } - Task.WaitAll(threads.ToArray()); + Task.WaitAll(threads); Assert.Equal(1000*1000, count); } diff --git a/src/libraries/System.Threading/tests/LockTests.cs b/src/libraries/System.Threading/tests/LockTests.cs index b4eab8787c8c..e18013188378 100644 --- a/src/libraries/System.Threading/tests/LockTests.cs +++ b/src/libraries/System.Threading/tests/LockTests.cs @@ -11,6 +11,37 @@ public static class LockTests { private const int FailTimeoutMilliseconds = 30000; +#pragma warning disable CS9216 // casting Lock to object + [Fact] + public static void LockStatementWithLockVsMonitor() + { + Lock lockObj = new(); + lock (lockObj) + { + Assert.True(lockObj.IsHeldByCurrentThread); + Assert.False(Monitor.IsEntered(lockObj)); + } + + lock ((object)lockObj) + { + Assert.False(lockObj.IsHeldByCurrentThread); + Assert.True(Monitor.IsEntered(lockObj)); + } + + LockOnTWhereTIsLock(lockObj); + + static void LockOnTWhereTIsLock(T lockObj) where T : class + { + Assert.IsType(lockObj); + lock (lockObj) + { + Assert.False(((Lock)(object)lockObj).IsHeldByCurrentThread); + Assert.True(Monitor.IsEntered(lockObj)); + } + } + } +#pragma warning restore CS9216 + // Attempts a single recursive acquisition/release cycle of a newly-created lock. [Fact] public static void BasicRecursion() @@ -27,6 +58,10 @@ public static void BasicRecursion() { Assert.True(lockObj.IsHeldByCurrentThread); } + lock (lockObj) + { + Assert.True(lockObj.IsHeldByCurrentThread); + } Assert.True(lockObj.IsHeldByCurrentThread); lockObj.Exit(); Assert.False(lockObj.IsHeldByCurrentThread); @@ -64,6 +99,10 @@ public static void IsHeldByCurrentThread() { Assert.True(lockObj.IsHeldByCurrentThread); } + lock (lockObj) + { + Assert.True(lockObj.IsHeldByCurrentThread); + } Assert.False(lockObj.IsHeldByCurrentThread); } diff --git a/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs b/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs index dfc75fc2a89e..7aabd01c39f1 100644 --- a/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs +++ b/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs @@ -90,7 +90,6 @@ public static void RunSemaphoreSlimTest1_WaitAsync() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/99501", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public static void RunSemaphoreSlimTest1_WaitAsync_NegativeCases() { // Invalid timeout diff --git a/src/libraries/System.Threading/tests/System.Threading.Tests.csproj b/src/libraries/System.Threading/tests/System.Threading.Tests.csproj index 768bb7b665d9..c552756fd17e 100644 --- a/src/libraries/System.Threading/tests/System.Threading.Tests.csproj +++ b/src/libraries/System.Threading/tests/System.Threading.Tests.csproj @@ -4,8 +4,6 @@ true $(NetCoreAppCurrent) true - - true true diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/OletxHelper.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/OletxHelper.cs index ce0bb80e0599..d62e67922898 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/OletxHelper.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/OletxHelper.cs @@ -11,24 +11,24 @@ internal static class OletxHelper private const int RetryInterval = 50; // in milliseconds private const int MaxRetryCount = 100; - internal static int S_OK = 0; - internal static int E_FAIL = -2147467259; // 0x80004005, -2147467259 - internal static int XACT_S_READONLY = 315394; // 0x0004D002, 315394 - internal static int XACT_S_SINGLEPHASE = 315401; // 0x0004D009, 315401 - internal static int XACT_E_ABORTED = -2147168231; // 0x8004D019, -2147168231 - internal static int XACT_E_NOTRANSACTION = -2147168242; // 0x8004D00E, -2147168242 - internal static int XACT_E_CONNECTION_DOWN = -2147168228; // 0x8004D01C, -2147168228 - internal static int XACT_E_REENLISTTIMEOUT = -2147168226; // 0x8004D01E, -2147168226 - internal static int XACT_E_RECOVERYALREADYDONE = -2147167996; // 0x8004D104, -2147167996 - internal static int XACT_E_TMNOTAVAILABLE = -2147168229; // 0x8004d01b, -2147168229 - internal static int XACT_E_INDOUBT = -2147168234; // 0x8004d016, - internal static int XACT_E_ALREADYINPROGRESS = -2147168232; // x08004d018, - internal static int XACT_E_TOOMANY_ENLISTMENTS = -2147167999; // 0x8004d101 - internal static int XACT_E_PROTOCOL = -2147167995; // 8004d105 - internal static int XACT_E_FIRST = -2147168256; // 0x8004D000 - internal static int XACT_E_LAST = -2147168215; // 0x8004D029 - internal static int XACT_E_NOTSUPPORTED = -2147168241; // 0x8004D00F - internal static int XACT_E_NETWORK_TX_DISABLED = -2147168220; // 0x8004D024 + internal const int S_OK = 0; + internal const int E_FAIL = -2147467259; // 0x80004005, -2147467259 + internal const int XACT_S_READONLY = 315394; // 0x0004D002, 315394 + internal const int XACT_S_SINGLEPHASE = 315401; // 0x0004D009, 315401 + internal const int XACT_E_ABORTED = -2147168231; // 0x8004D019, -2147168231 + internal const int XACT_E_NOTRANSACTION = -2147168242; // 0x8004D00E, -2147168242 + internal const int XACT_E_CONNECTION_DOWN = -2147168228; // 0x8004D01C, -2147168228 + internal const int XACT_E_REENLISTTIMEOUT = -2147168226; // 0x8004D01E, -2147168226 + internal const int XACT_E_RECOVERYALREADYDONE = -2147167996; // 0x8004D104, -2147167996 + internal const int XACT_E_TMNOTAVAILABLE = -2147168229; // 0x8004d01b, -2147168229 + internal const int XACT_E_INDOUBT = -2147168234; // 0x8004d016, + internal const int XACT_E_ALREADYINPROGRESS = -2147168232; // x08004d018, + internal const int XACT_E_TOOMANY_ENLISTMENTS = -2147167999; // 0x8004d101 + internal const int XACT_E_PROTOCOL = -2147167995; // 8004d105 + internal const int XACT_E_FIRST = -2147168256; // 0x8004D000 + internal const int XACT_E_LAST = -2147168215; // 0x8004D029 + internal const int XACT_E_NOTSUPPORTED = -2147168241; // 0x8004D00F + internal const int XACT_E_NETWORK_TX_DISABLED = -2147168220; // 0x8004D024 internal static void Retry(Action action) { diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/Oletx/OletxEnlistment.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/Oletx/OletxEnlistment.cs index 23e72382d2dc..75cc0607be9e 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/Oletx/OletxEnlistment.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/Oletx/OletxEnlistment.cs @@ -846,7 +846,6 @@ public EnlistmentTraceIdentifier EnlistmentTraceId public void Prepared() { - int hrResult = OletxHelper.S_OK; EnlistmentShim? localEnlistmentShim = null; Phase0EnlistmentShim? localPhase0Shim = null; bool localFabricateRollback = false; diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/Oletx/OletxResourceManager.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/Oletx/OletxResourceManager.cs index c2cb9bf50498..c38d9751a222 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/Oletx/OletxResourceManager.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/Oletx/OletxResourceManager.cs @@ -15,7 +15,7 @@ internal sealed class OletxResourceManager internal ResourceManagerShim? resourceManagerShim; internal Hashtable EnlistmentHashtable; - internal static Hashtable VolatileEnlistmentHashtable = new Hashtable(); + internal static readonly Hashtable VolatileEnlistmentHashtable = new Hashtable(); internal OletxTransactionManager OletxTransactionManager; // reenlistList is a simple ArrayList of OletxEnlistment objects that are either in the diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/Oletx/OletxTransactionManager.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/Oletx/OletxTransactionManager.cs index e32c991e4e13..a68c0608e0c9 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/Oletx/OletxTransactionManager.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/Oletx/OletxTransactionManager.cs @@ -30,7 +30,7 @@ internal sealed class OletxTransactionManager private readonly DtcTransactionManager _dtcTransactionManager; internal OletxInternalResourceManager InternalResourceManager; - internal static DtcProxyShimFactory ProxyShimFactory = null!; // Late initialization + internal static DtcProxyShimFactory ProxyShimFactory = null!; // Lazy initialization // Double-checked locking pattern requires volatile for read/write synchronization internal static volatile EventWaitHandle? _shimWaitHandle; diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionManager.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionManager.cs index 8fed4d70cb8f..e88772583be0 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionManager.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionManager.cs @@ -432,7 +432,7 @@ public static bool ImplicitDistributedTransactions } internal static bool? s_implicitDistributedTransactions; - internal static object s_implicitDistributedTransactionsLock = new(); + internal static readonly object s_implicitDistributedTransactionsLock = new(); #else public static bool ImplicitDistributedTransactions { diff --git a/src/libraries/System.Windows.Extensions/src/PACKAGE.md b/src/libraries/System.Windows.Extensions/src/PACKAGE.md index edf526dfe909..8ccfc244f6f6 100644 --- a/src/libraries/System.Windows.Extensions/src/PACKAGE.md +++ b/src/libraries/System.Windows.Extensions/src/PACKAGE.md @@ -2,43 +2,96 @@ +Provides miscellaneous Windows-specific types. +This collection of types facilitates interactions with unique features provided by the Windows operating system, including playing sounds, selecting X509 certificates in a user-friendly manner, among other features. ## Key Features -* -* -* +* Controls playback of a sound from a .wav file. +* Retrieves sounds associated with a set of Windows operating system sound-event types. +* User-friendly handling of X509 certificates. ## How to Use +Below are examples demonstrating the usage of the key types provided by this package. + +### Playing a .wav File + +```csharp +using System.Media; + +SoundPlayer player = new SoundPlayer("sound.wav"); +player.Play(); + +// Wait while the sound plays. +Console.ReadKey(); +``` + +### Playing a System Sound + +```csharp +using System.Media; + +SystemSounds.Asterisk.Play(); +SystemSounds.Beep.Play(); +SystemSounds.Exclamation.Play(); +SystemSounds.Hand.Play(); +SystemSounds.Question.Play(); +``` + +### Displaying a Certificate Selection Dialog + +```csharp +using System.Security.Cryptography.X509Certificates; + +X509Store store = new X509Store(StoreName.My); +store.Open(OpenFlags.ReadOnly); + +X509Certificate2Collection selectedCerts = X509Certificate2UI.SelectFromCollection( + store.Certificates, + "Select Certificate", + "Select a certificate from the following list:", + X509SelectionFlag.SingleSelection +); +store.Close(); + +if (selectedCerts.Count == 0) +{ + Console.WriteLine("No certificate selected."); +} +else +{ + Console.WriteLine($"Certificate selected: {selectedCerts[0].Subject}"); +} +``` + ## Main Types The main types provided by this library are: -* `` -* `` -* `` +* `System.Media.SoundPlayer` +* `System.Media.SystemSounds` +* `System.Security.Cryptography.X509Certificates.X509Certificate2UI` +* `System.Xaml.Permissions.XamlAccessLevel` ## Additional Documentation -* [Conceptual documentation](https://learn.microsoft.com/dotnet/standard/serialization/**LIBRARYNAME**/overview) -* [API documentation](https://learn.microsoft.com/dotnet/api/**LIBRARYNAME**) - -## Related Packages - - +* API documentation + * [System.Media Namespace](https://learn.microsoft.com/dotnet/api/system.media) + * [System.Security.Cryptography.X509Certificates Namespace](https://learn.microsoft.com/dotnet/api/system.security.cryptography.x509certificates) + * [XamlAccessLevel Class](https://learn.microsoft.com/dotnet/api/system.xaml.permissions.xamlaccesslevel) ## Feedback & Contributing -System.Windows.Extensions is released as open source under the [MIT license](https://licenses.nuget.org/MIT). Bug reports and contributions are welcome at [the GitHub repository](https://github.com/dotnet/runtime). \ No newline at end of file +System.Windows.Extensions is released as open source under the [MIT license](https://licenses.nuget.org/MIT). Bug reports and contributions are welcome at [the GitHub repository](https://github.com/dotnet/runtime). diff --git a/src/libraries/System.Windows.Extensions/src/System/Media/SoundPlayer.cs b/src/libraries/System.Windows.Extensions/src/System/Media/SoundPlayer.cs index d77919070c24..e57dff3e55ce 100644 --- a/src/libraries/System.Windows.Extensions/src/System/Media/SoundPlayer.cs +++ b/src/libraries/System.Windows.Extensions/src/System/Media/SoundPlayer.cs @@ -314,7 +314,7 @@ private void LoadStream(bool loadSync) int streamLen = (int)_stream.Length; _currentPos = 0; _streamData = new byte[streamLen]; -#if NET7_0_OR_GREATER +#if NET _stream.ReadExactly(_streamData); #else int totalRead = 0; diff --git a/src/libraries/System.Windows.Extensions/src/System/Media/SystemSounds.cs b/src/libraries/System.Windows.Extensions/src/System/Media/SystemSounds.cs index da1c5de5f35d..a5042fc02420 100644 --- a/src/libraries/System.Windows.Extensions/src/System/Media/SystemSounds.cs +++ b/src/libraries/System.Windows.Extensions/src/System/Media/SystemSounds.cs @@ -5,11 +5,11 @@ namespace System.Media { public static class SystemSounds { - private static volatile SystemSound? s_asterisk; - private static volatile SystemSound? s_beep; - private static volatile SystemSound? s_exclamation; - private static volatile SystemSound? s_hand; - private static volatile SystemSound? s_question; + private static SystemSound? s_asterisk; + private static SystemSound? s_beep; + private static SystemSound? s_exclamation; + private static SystemSound? s_hand; + private static SystemSound? s_question; public static SystemSound Asterisk { diff --git a/src/libraries/System.Windows.Extensions/src/System/Security/Cryptography/X509Certificates/X509Certificate2UI.cs b/src/libraries/System.Windows.Extensions/src/System/Security/Cryptography/X509Certificates/X509Certificate2UI.cs index b19e217322f0..dfdb4660ea49 100644 --- a/src/libraries/System.Windows.Extensions/src/System/Security/Cryptography/X509Certificates/X509Certificate2UI.cs +++ b/src/libraries/System.Windows.Extensions/src/System/Security/Cryptography/X509Certificates/X509Certificate2UI.cs @@ -53,7 +53,7 @@ private static unsafe void DisplayX509Certificate(X509Certificate2 certificate, // Initialize view structure. Interop.CryptUI.CRYPTUI_VIEWCERTIFICATE_STRUCTW ViewInfo = default; -#if NET7_0_OR_GREATER +#if NET ViewInfo.dwSize = (uint)sizeof(Interop.CryptUI.CRYPTUI_VIEWCERTIFICATE_STRUCTW.Marshaller.Native); #else ViewInfo.dwSize = (uint)Marshal.SizeOf(); @@ -122,7 +122,7 @@ private static unsafe SafeCertStoreHandle SelectFromStore(SafeCertStoreHandle sa Interop.CryptUI.CRYPTUI_SELECTCERTIFICATE_STRUCTW csc = default; // Older versions of CRYPTUI do not check the size correctly, // so always force it to the oldest version of the structure. -#if NET7_0_OR_GREATER +#if NET // Declare a local for Native to enable us to get the managed byte offset // without having a null check cause a failure. Interop.CryptUI.CRYPTUI_SELECTCERTIFICATE_STRUCTW.Marshaller.Native native; diff --git a/src/libraries/System.Windows.Extensions/src/System/Xaml/Permissions/XamlAccessLevel.cs b/src/libraries/System.Windows.Extensions/src/System/Xaml/Permissions/XamlAccessLevel.cs index 3c4d510fd3a1..8d4e171f68f2 100644 --- a/src/libraries/System.Windows.Extensions/src/System/Xaml/Permissions/XamlAccessLevel.cs +++ b/src/libraries/System.Windows.Extensions/src/System/Xaml/Permissions/XamlAccessLevel.cs @@ -43,8 +43,8 @@ public AssemblyName AssemblyAccessToAssemblyName get { return new AssemblyName(AssemblyNameString); } } - public string? PrivateAccessToTypeName { get; private set; } + public string? PrivateAccessToTypeName { get; } - internal string AssemblyNameString { get; private set; } + internal string AssemblyNameString { get; } } } diff --git a/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml b/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml index 09cfe417e381..935f4a69d115 100644 --- a/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml +++ b/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml @@ -469,4 +469,64 @@ net8.0/System.dll net9.0/System.dll + + CP0021 + T:System.Diagnostics.Metrics.MeasurementCallback`1``0:struct + net8.0/System.Diagnostics.DiagnosticSource.dll + net9.0/System.Diagnostics.DiagnosticSource.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsDefaultMarshaller`1``0:struct + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsDefaultMarshaller`1``0:unmanaged + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsHResultMarshaller`1``0:struct + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsHResultMarshaller`1``0:T:System.Numerics.INumber{`0} + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsHResultMarshaller`1``0:unmanaged + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsNaNMarshaller`1``0:struct + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsNaNMarshaller`1``0:T:System.Numerics.IFloatingPointIeee754{`0} + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Runtime.InteropServices.Marshalling.ExceptionAsNaNMarshaller`1``0:unmanaged + net8.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + T:System.Text.Json.Serialization.JsonNumberEnumConverter`1``0:T:System.Enum + net8.0/System.Text.Json.dll + net9.0/System.Text.Json.dll + \ No newline at end of file diff --git a/src/libraries/apicompat/ApiCompatBaseline.netstandard2.0.xml b/src/libraries/apicompat/ApiCompatBaseline.netstandard2.0.xml index e03170246c0a..939342fce86a 100644 --- a/src/libraries/apicompat/ApiCompatBaseline.netstandard2.0.xml +++ b/src/libraries/apicompat/ApiCompatBaseline.netstandard2.0.xml @@ -2791,4 +2791,382 @@ netstandard2.0/System.dll net9.0/System.dll + + CP0021 + M:System.Runtime.InteropServices.Marshal.CreateAggregatedObject``1(System.IntPtr,``0)``0:notnull + netstandard2.0/mscorlib.dll + net9.0/mscorlib.dll + + + CP0021 + M:System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate``1(``0)``0:notnull + netstandard2.0/mscorlib.dll + net9.0/mscorlib.dll + + + CP0021 + T:System.Collections.Concurrent.ConcurrentDictionary`2``0:notnull + netstandard2.0/mscorlib.dll + net9.0/mscorlib.dll + + + CP0021 + T:System.Collections.Generic.Dictionary`2``0:notnull + netstandard2.0/mscorlib.dll + net9.0/mscorlib.dll + + + CP0021 + T:System.Collections.ObjectModel.KeyedCollection`2``0:notnull + netstandard2.0/mscorlib.dll + net9.0/mscorlib.dll + + + CP0021 + T:System.Collections.ObjectModel.ReadOnlyDictionary`2``0:notnull + netstandard2.0/mscorlib.dll + net9.0/mscorlib.dll + + + CP0021 + T:System.Tuple`8``7:notnull + netstandard2.0/mscorlib.dll + net9.0/mscorlib.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Runtime.InteropServices.Marshal.CreateAggregatedObject``1(System.IntPtr,``0)``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate``1(``0)``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Concurrent.ConcurrentDictionary`2``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Generic.Dictionary`2``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Generic.SortedDictionary`2``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Generic.SortedList`2``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.ObjectModel.KeyedCollection`2``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.ObjectModel.ReadOnlyDictionary`2``0:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Tuple`8``7:notnull + netstandard2.0/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Concurrent.ConcurrentDictionary`2``0:notnull + netstandard2.0/System.Collections.Concurrent.dll + net9.0/System.Collections.Concurrent.dll + + + CP0021 + T:System.Collections.Generic.Dictionary`2``0:notnull + netstandard2.0/System.Collections.dll + net9.0/System.Collections.dll + + + CP0021 + T:System.Collections.Generic.SortedDictionary`2``0:notnull + netstandard2.0/System.Collections.dll + net9.0/System.Collections.dll + + + CP0021 + T:System.Collections.Generic.SortedList`2``0:notnull + netstandard2.0/System.Collections.dll + net9.0/System.Collections.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/System.Core.dll + net9.0/System.Core.dll + + + CP0021 + T:System.Collections.Generic.SortedDictionary`2``0:notnull + netstandard2.0/System.dll + net9.0/System.dll + + + CP0021 + T:System.Collections.Generic.SortedList`2``0:notnull + netstandard2.0/System.dll + net9.0/System.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Linq.dll + net9.0/System.Linq.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/System.Linq.dll + net9.0/System.Linq.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Linq.dll + net9.0/System.Linq.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/System.Linq.dll + net9.0/System.Linq.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.0/System.Linq.Parallel.dll + net9.0/System.Linq.Parallel.dll + + + CP0021 + T:System.Collections.ObjectModel.KeyedCollection`2``0:notnull + netstandard2.0/System.ObjectModel.dll + net9.0/System.ObjectModel.dll + + + CP0021 + T:System.Collections.ObjectModel.ReadOnlyDictionary`2``0:notnull + netstandard2.0/System.ObjectModel.dll + net9.0/System.ObjectModel.dll + + + CP0021 + T:System.Tuple`8``7:notnull + netstandard2.0/System.Runtime.dll + net9.0/System.Runtime.dll + + + CP0021 + M:System.Runtime.InteropServices.Marshal.CreateAggregatedObject``1(System.IntPtr,``0)``0:notnull + netstandard2.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + + + CP0021 + M:System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate``1(``0)``0:notnull + netstandard2.0/System.Runtime.InteropServices.dll + net9.0/System.Runtime.InteropServices.dll + \ No newline at end of file diff --git a/src/libraries/apicompat/ApiCompatBaseline.netstandard2.1.xml b/src/libraries/apicompat/ApiCompatBaseline.netstandard2.1.xml index f7c8eb8430ef..f0ef02d93c1a 100644 --- a/src/libraries/apicompat/ApiCompatBaseline.netstandard2.1.xml +++ b/src/libraries/apicompat/ApiCompatBaseline.netstandard2.1.xml @@ -877,4 +877,130 @@ netstandard2.1/netstandard.dll net9.0/netstandard.dll + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.Enumerable.ToDictionary``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToDictionary``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``2(System.Linq.ParallelQuery{``0},System.Func{``0,``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Linq.ParallelEnumerable.ToLookup``3(System.Linq.ParallelQuery{``0},System.Func{``0,``1},System.Func{``0,``2})``1:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Runtime.InteropServices.Marshal.CreateAggregatedObject``1(System.IntPtr,``0)``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + M:System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate``1(``0)``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Concurrent.ConcurrentDictionary`2``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Generic.Dictionary`2``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Generic.SortedDictionary`2``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.Generic.SortedList`2``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.ObjectModel.KeyedCollection`2``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Collections.ObjectModel.ReadOnlyDictionary`2``0:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + + + CP0021 + T:System.Tuple`8``7:notnull + netstandard2.1/netstandard.dll + net9.0/netstandard.dll + \ No newline at end of file diff --git a/src/libraries/externals.csproj b/src/libraries/externals.csproj index 7f85d5d67e31..6aa753ec79b2 100644 --- a/src/libraries/externals.csproj +++ b/src/libraries/externals.csproj @@ -85,6 +85,10 @@ + + + diff --git a/src/libraries/sendtohelix-browser.targets b/src/libraries/sendtohelix-browser.targets index f710cb8893df..80cbacd109a9 100644 --- a/src/libraries/sendtohelix-browser.targets +++ b/src/libraries/sendtohelix-browser.targets @@ -10,7 +10,7 @@ - In this `wasm.helix.targets` file, add to $(HelixExtensionTargets) to run your custom target - + $(HelixExtensionTargets);_AddHelixCrypoItems - Useful properties to condition on: $(Scenario), $(IsRunningLibraryTests) @@ -32,10 +32,14 @@ <_ShippingPackagesPath>$([MSBuild]::NormalizeDirectory($(ArtifactsDir), 'packages', $(Configuration), 'Shipping')) - $(Scenario)- + $(Scenario)-ST- + $(Scenario)-MT- true - true + true @@ -48,15 +52,15 @@ false false - - $(RepoRoot)src\mono\browser\emsdk\ + $([MSBuild]::NormalizeDirectory($(RepoRoot), 'src', 'mono', 'browser', 'emsdk')) $(HelixDependenciesStagingPath)\emsdk chrome true true false - true + true + true true true @@ -91,31 +95,27 @@ - - - - - - + + + + - - - - - - + + + + @@ -174,26 +174,34 @@ + - - - - - - - - + + + - - - + + + + + + @@ -222,8 +230,11 @@ - <_WasmWorkItem Include="$(TestArchiveRoot)browseronly/**/*.zip" Condition="'$(Scenario)' == 'WasmTestOnBrowser'" /> - <_WasmWorkItem Include="$(TestArchiveRoot)browserornodejs/**/*.zip" Condition="'$(Scenario)' == 'WasmTestOnBrowser'" /> + <_WasmWorkItem Include="$(TestArchiveRoot)browseronly/**/*.zip" Condition="'$(Scenario)' == 'WasmTestOnChrome'" /> + <_WasmWorkItem Include="$(TestArchiveRoot)chromeonly/**/*.zip" Condition="'$(Scenario)' == 'WasmTestOnChrome'" /> + <_WasmWorkItem Include="$(TestArchiveRoot)browserornodejs/**/*.zip" Condition="'$(Scenario)' == 'WasmTestOnChrome'" /> + <_WasmWorkItem Include="$(TestArchiveRoot)browseronly/**/*.zip" Condition="'$(Scenario)' == 'WasmTestOnFirefox'" /> + <_WasmWorkItem Include="$(TestArchiveRoot)browserornodejs/**/*.zip" Condition="'$(Scenario)' == 'WasmTestOnFirefox'" /> <_WasmWorkItem Include="$(TestArchiveRoot)browserornodejs/**/*.zip" Condition="'$(Scenario)' == 'WasmTestOnNodeJS'" /> <_WasmWorkItem Include="$(TestArchiveRoot)nodejsonly/**/*.zip" Condition="'$(Scenario)' == 'WasmTestOnNodeJS'" /> @@ -244,11 +255,14 @@ - <_WasmSampleZipFile Condition="'$(Scenario)' == 'normal' or '$(Scenario)' == ''" Include="$(TestArchiveRoot)runonly/**/*.Console.V8.*.Sample.zip" /> - <_WasmSampleZipFile Condition="'$(Scenario)' == 'WasmTestOnNodeJS'" Include="$(TestArchiveRoot)runonly/**/*.Console.Node.*.Sample.zip" /> - <_WasmSampleZipFile Condition="'$(Scenario)' == 'WasmTestOnBrowser'" Include="$(TestArchiveRoot)runonly/**/*.Browser.*.Sample.zip" /> - - + <_WasmSampleZipFile Condition="'$(Scenario)' == 'WasmTestOnV8'" Include="$(TestArchiveRoot)runonly/**/*.Console.V8.*.Sample.zip" /> + <_WasmSampleZipFile Condition="'$(Scenario)' == 'WasmTestOnNodeJS'" Include="$(TestArchiveRoot)runonly/**/*.Console.Node.*.Sample.zip" /> + <_WasmSampleZipFile Condition="'$(Scenario)' == 'WasmTestOnChrome'" Include="$(TestArchiveRoot)runonly/**/*.Browser.*.Sample.zip" /> + + + %(Identity) $(HelixCommand) $(_workItemTimeout) diff --git a/src/libraries/sendtohelix-mobile.targets b/src/libraries/sendtohelix-mobile.targets index b003014bdcd2..0a3a091fdf4f 100644 --- a/src/libraries/sendtohelix-mobile.targets +++ b/src/libraries/sendtohelix-mobile.targets @@ -81,7 +81,7 @@ Destination="build/BuildIntegration" /> - + @@ -94,7 +94,7 @@ - $(AppleTestTarget) @@ -116,8 +116,8 @@ - false diff --git a/src/libraries/sendtohelix-wasi.targets b/src/libraries/sendtohelix-wasi.targets index bedb1d4192a8..8a1902eb378f 100644 --- a/src/libraries/sendtohelix-wasi.targets +++ b/src/libraries/sendtohelix-wasi.targets @@ -10,7 +10,7 @@ - In this `wasm.helix.targets` file, add to $(HelixExtensionTargets) to run your custom target - + $(HelixExtensionTargets);_AddHelixCrypoItems - Useful properties to condition on: $(Scenario), $(IsRunningLibraryTests) @@ -31,8 +31,8 @@ - true - wasmtime + true + wasmtime true <_ShippingPackagesPath>$([MSBuild]::NormalizeDirectory($(ArtifactsDir), 'packages', $(Configuration), 'Shipping')) @@ -48,8 +48,8 @@ $(RepoRoot)src\mono\wasi\wasi-sdk\ $([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'src', 'mono', 'wasi', 'build')) - $(HelixDependenciesStagingPath)\wasi-sdk - $(HelixDependenciesStagingPath)\wasmtime + $(HelixDependenciesStagingPath)$(WorkItemPrefix)wasi-sdk + $(HelixDependenciesStagingPath)$(WorkItemPrefix)wasmtime true true @@ -104,6 +104,11 @@ + + + @@ -127,7 +132,7 @@ - <_WasiWorkItem Include="$(TestArchiveRoot)browseronly/**/*.zip" Condition="'$(Scenario)' == 'WasmTestOnBrowser'" /> + <_WasiWorkItem Include="$(TestArchiveRoot)wasmtimeonly/**/*.zip" Condition="'$(Scenario)' == 'WasmTestOnWasmtime'" /> %(Identity) $(HelixCommand) @@ -137,7 +142,7 @@ - <_WasiSampleZipFile Condition="'$(Scenario)' == 'normal' or '$(Scenario)' == ''" Include="$(TestArchiveRoot)runonly/**/*.Console.V8.*.Sample.zip" /> + <_WasiSampleZipFile Condition="'$(Scenario)' == 'WasmTestOnWasmtime'" Include="$(TestArchiveRoot)runonly/**/Wasi.*.Sample.zip" /> %(Identity) diff --git a/src/libraries/sendtohelix-wasm.targets b/src/libraries/sendtohelix-wasm.targets index d9c2e3aead08..3fce57cf9c4e 100644 --- a/src/libraries/sendtohelix-wasm.targets +++ b/src/libraries/sendtohelix-wasm.targets @@ -9,6 +9,14 @@ $([MSBuild]::NormalizeDirectory($(WasmProjectRoot), 'build')) + + Workloads- + NoWorkload- + $(WorkItemPrefix)NoWebcil- + $(WorkItemPrefix)ST- + $(WorkItemPrefix)MT- + + @@ -27,12 +35,6 @@ - - Workloads- - NoWorkload- - $(WorkItemPrefix)NoWebcil- - - <_WasmWorkItem Include="$(WorkItemArchiveWildCard)" Exclude="$(HelixCorrelationPayload)" /> diff --git a/src/libraries/sendtohelixhelp.proj b/src/libraries/sendtohelixhelp.proj index 7c668b034712..e3efcd584ce4 100644 --- a/src/libraries/sendtohelixhelp.proj +++ b/src/libraries/sendtohelixhelp.proj @@ -115,11 +115,11 @@ setting up the per-scenario environment. --> - + - + diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 0e11b1da8933..748f9d9d6226 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -74,9 +74,6 @@ - - - @@ -655,16 +652,16 @@ BuildInParallel="$(BuildTestInParallel)" /> + + + + + - - :Debug>") # statically link VC runtime library - add_compile_options($<$:/W4>) # set warning level 4 - add_compile_options($<$:/WX>) # treat warnings as errors - add_compile_options($<$:/wd4324>) # 'struct_name' : structure was padded due to __declspec(align()) - add_compile_options($<$:/EHsc>) # set exception handling behavior - add_compile_options($<$:/FC>) # use full pathnames in diagnostics + add_compile_options($<$:/W4>) # set warning level 4 + add_compile_options($<$:/WX>) # treat warnings as errors + add_compile_options($<$:/wd4324>) # 'struct_name' : structure was padded due to __declspec(align()) + add_compile_options($<$:/EHsc>) # set exception handling behavior + add_compile_options($<$:/FC>) # use full pathnames in diagnostics + add_compile_options($<$:/guard:cf>) # Enable control flow guard add_link_options(/STACK:0x800000) # set stack size to 8MB (default is 1MB) + add_link_options(/guard:cf) if(CMAKE_BUILD_TYPE STREQUAL "Release") add_compile_options($<$:/Oi>) # enable intrinsics add_compile_options($<$:/GF>) # enable string pooling @@ -330,13 +332,6 @@ elseif(TARGET_SYSTEM_NAME STREQUAL "ios" OR TARGET_SYSTEM_NAME STREQUAL "tvos") elseif(TARGET_SYSTEM_NAME STREQUAL "tvos") set(TARGET_TVOS 1) endif() -elseif(TARGET_SYSTEM_NAME STREQUAL "linux") - set(TARGET_UNIX 1) - set(TARGET_LINUX 1) -elseif(TARGET_SYSTEM_NAME STREQUAL "alpine") - set(TARGET_UNIX 1) - set(TARGET_LINUX 1) - set(TARGET_LINUX_MUSL 1) elseif(TARGET_SYSTEM_NAME STREQUAL "android") set(TARGET_UNIX 1) set(TARGET_LINUX_BIONIC 1) @@ -344,6 +339,13 @@ elseif(TARGET_SYSTEM_NAME STREQUAL "android") if (CMAKE_BUILD_TYPE STREQUAL "Release") add_compile_options(-O2) endif() +elseif(CLR_CMAKE_TARGET_LINUX_MUSL) + set(TARGET_UNIX 1) + set(TARGET_LINUX 1) + set(TARGET_LINUX_MUSL 1) +elseif(TARGET_SYSTEM_NAME STREQUAL "linux") + set(TARGET_UNIX 1) + set(TARGET_LINUX 1) elseif(TARGET_SYSTEM_NAME STREQUAL "emscripten") set(TARGET_BROWSER 1) if (CMAKE_BUILD_TYPE STREQUAL "Release") @@ -633,9 +635,9 @@ if(LLVM_PREFIX) endif() if(HOST_LINUX AND NOT HOST_WASM AND NOT HOST_WASI AND ${llvm_api_version} GREATER_EQUAL 1600) - set(MONO_stdlib "-stdlib=libc++") - set(MONO_cxx_lib "-L${LLVM_PREFIX}/lib -lc++") - set(MONO_cxx_include "-I${LLVM_PREFIX}/include/c++/v1") + set(MONO_stdlib "-nostdinc++ -nostdlib++") + set(MONO_cxx_lib "-L${LLVM_PREFIX}/lib -lc++ -lc++abi") + set(MONO_cxx_include "-isystem ${LLVM_PREFIX}/include/c++/v1") endif() if(${llvm_api_version} GREATER_EQUAL 1600) diff --git a/src/mono/Directory.Build.props b/src/mono/Directory.Build.props index 12d6fdb34cfc..d97bf84a1da6 100644 --- a/src/mono/Directory.Build.props +++ b/src/mono/Directory.Build.props @@ -34,10 +34,12 @@ - <_ProvisionWasiSdkDir>$([MSBuild]::NormalizeDirectory($(MSBuildThisFileDirectory), 'wasi', 'wasi-sdk')) - true - $(_ProvisionWasiSdkDir) + + $([MSBuild]::NormalizeDirectory($(MSBuildThisFileDirectory), 'wasi', 'wasi-sdk')) $([MSBuild]::EnsureTrailingSlash('$(WASI_SDK_PATH)').Replace('\', '/')) + true diff --git a/src/mono/System.Private.CoreLib/CompatibilitySuppressions.xml b/src/mono/System.Private.CoreLib/CompatibilitySuppressions.xml deleted file mode 100644 index 8e96fb8cbaa7..000000000000 --- a/src/mono/System.Private.CoreLib/CompatibilitySuppressions.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - CP0014 - M:System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(System.Object)->object?:[T:System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.Write``1(System.String,``0):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.Write``1(System.String,System.Diagnostics.Tracing.EventSourceOptions@,``0@):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.Write``1(System.String,System.Diagnostics.Tracing.EventSourceOptions@,System.Guid@,System.Guid@,``0@):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.WriteEvent(System.Int32,System.Object[]):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.WriteEventCore(System.Int32,System.Int32,System.Diagnostics.Tracing.EventSource.EventData*):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.WriteEventWithRelatedActivityId(System.Int32,System.Guid,System.Object[]):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - - CP0015 - M:System.Diagnostics.Tracing.EventSource.WriteEventWithRelatedActivityIdCore(System.Int32,System.Guid*,System.Int32,System.Diagnostics.Tracing.EventSource.EventData*):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - - diff --git a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj index 95f7f110cda5..9137c694aa4a 100644 --- a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -26,6 +26,7 @@ + AnyCPU true false @@ -35,8 +36,7 @@ $(ProductVersion) $(ProductVersion) - - $(NoWarn),0419,0649,AD0001 + $(NoWarn),0419,0649 enable @@ -48,40 +48,30 @@ - x64 - false $(DefineConstants);TARGET_AMD64 - x86 $(DefineConstants);TARGET_X86 - arm $(DefineConstants);TARGET_ARMV6 - arm $(DefineConstants);TARGET_ARM - AnyCPU $(DefineConstants);TARGET_ARM64 - AnyCPU $(DefineConstants);TARGET_RISCV64 - AnyCPU $(DefineConstants);TARGET_S390X - AnyCPU $(DefineConstants);TARGET_WASM - AnyCPU $(DefineConstants);TARGET_POWERPC64 @@ -245,7 +235,7 @@ - + diff --git a/src/mono/System.Private.CoreLib/src/System/Enum.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Enum.Mono.cs index c057acd9da07..5a4fe01cfc5d 100644 --- a/src/mono/System.Private.CoreLib/src/System/Enum.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Enum.Mono.cs @@ -15,22 +15,12 @@ public partial class Enum [MethodImpl(MethodImplOptions.InternalCall)] private static extern void GetEnumValuesAndNames(QCallTypeHandle enumType, out ulong[] values, out string[] names); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void InternalBoxEnum(QCallTypeHandle enumType, ObjectHandleOnStack res, long value); - [MethodImpl(MethodImplOptions.InternalCall)] private static extern CorElementType InternalGetCorElementType(QCallTypeHandle enumType); [MethodImpl(MethodImplOptions.InternalCall)] private static extern void InternalGetUnderlyingType(QCallTypeHandle enumType, ObjectHandleOnStack res); - private static object InternalBoxEnum(RuntimeType enumType, long value) - { - object? res = null; - InternalBoxEnum(new QCallTypeHandle(ref enumType), ObjectHandleOnStack.Create(ref res), value); - return res!; - } - private static unsafe CorElementType InternalGetCorElementType(RuntimeType rt) { Debug.Assert(rt.IsActualEnum); diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameParser.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameParser.Mono.cs deleted file mode 100644 index 3622b4e27626..000000000000 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameParser.Mono.cs +++ /dev/null @@ -1,165 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.Loader; -using System.Text; -using System.Threading; - -namespace System.Reflection -{ - internal unsafe ref partial struct TypeNameParser - { - private Func? _assemblyResolver; - private Func? _typeResolver; - private bool _throwOnError; - private bool _ignoreCase; - private void* _stackMark; - - [RequiresUnreferencedCode("The type might be removed")] - internal static Type? GetType( - string typeName, - Func? assemblyResolver, - Func? typeResolver, - bool throwOnError, - bool ignoreCase, - ref StackCrawlMark stackMark) - { - ArgumentNullException.ThrowIfNull(typeName); - - // Compat: Empty name throws TypeLoadException instead of - // the natural ArgumentException - if (typeName.Length == 0) - { - if (throwOnError) - throw new TypeLoadException(SR.Arg_TypeLoadNullStr); - return null; - } - - return new TypeNameParser(typeName) - { - _assemblyResolver = assemblyResolver, - _typeResolver = typeResolver, - _throwOnError = throwOnError, - _ignoreCase = ignoreCase, - _stackMark = Unsafe.AsPointer(ref stackMark) - }.Parse(); - } - - private static bool CheckTopLevelAssemblyQualifiedName() - { - return true; - } - - private Assembly? ResolveAssembly(string assemblyName) - { - var name = new AssemblyName(assemblyName); - - Assembly? assembly; - if (_assemblyResolver is not null) - { - assembly = _assemblyResolver(name); - if (assembly is null && _throwOnError) - { - throw new FileNotFoundException(SR.Format(SR.FileNotFound_ResolveAssembly, assemblyName)); - } - } - else - { - ref StackCrawlMark stackMark = ref Unsafe.AsRef(_stackMark); - - if (_throwOnError) - { - assembly = Assembly.Load(name, ref stackMark, null); - } - else - { - // When throwOnError is false we should only catch FileNotFoundException. - // Other exceptions like BadImangeFormatException should still fly. - try - { - assembly = Assembly.Load(name, ref stackMark, null); - } - catch (FileNotFoundException) - { - return null; - } - } - } - return assembly; - } - - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", - Justification = "TypeNameParser.GetType is marked as RequiresUnreferencedCode.")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", - Justification = "TypeNameParser.GetType is marked as RequiresUnreferencedCode.")] - private Type? GetType(string typeName, ReadOnlySpan nestedTypeNames, string? assemblyNameIfAny) - { - Assembly? assembly = (assemblyNameIfAny is not null) ? ResolveAssembly(assemblyNameIfAny) : null; - - // Both the external type resolver and the default type resolvers expect escaped type names - string escapedTypeName = EscapeTypeName(typeName); - - Type? type; - - // Resolve the top level type. - if (_typeResolver is not null) - { - type = _typeResolver(assembly, escapedTypeName, _ignoreCase); - - if (type is null) - { - if (_throwOnError) - { - throw new TypeLoadException(assembly is null ? - SR.Format(SR.TypeLoad_ResolveType, escapedTypeName) : - SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, escapedTypeName, assembly.FullName)); - } - return null; - } - } - else - { - if (assembly is null) - { - ref StackCrawlMark stackMark = ref Unsafe.AsRef(_stackMark); - - type = RuntimeType.GetType(escapedTypeName, _throwOnError, _ignoreCase, ref stackMark); - } - else - { - type = assembly.GetType(escapedTypeName, _throwOnError, _ignoreCase); - } - - if (type is null) - { - return null; - } - } - - for (int i = 0; i < nestedTypeNames.Length; i++) - { - BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public; - if (_ignoreCase) - bindingFlags |= BindingFlags.IgnoreCase; - - type = type.GetNestedType(nestedTypeNames[i], bindingFlags); - - if (type is null) - { - if (_throwOnError) - { - throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveNestedType, - nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : typeName)); - } - return null; - } - } - - return type; - } - } -} diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.Mono.cs new file mode 100644 index 000000000000..ef5d63ec2807 --- /dev/null +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.Mono.cs @@ -0,0 +1,163 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Reflection; +using System.Reflection.Metadata; +using System.Runtime.CompilerServices; +using System.Runtime.Loader; +using System.Text; +using System.Threading; + +namespace System.Reflection +{ + internal unsafe ref partial struct TypeNameResolver + { + private Func? _assemblyResolver; + private Func? _typeResolver; + private bool _throwOnError; + private bool _ignoreCase; + private void* _stackMark; + + [RequiresUnreferencedCode("The type might be removed")] + internal static Type? GetType( + string typeName, + Func? assemblyResolver, + Func? typeResolver, + bool throwOnError, + bool ignoreCase, + ref StackCrawlMark stackMark) + { + ArgumentNullException.ThrowIfNull(typeName); + + // Compat: Empty name throws TypeLoadException instead of + // the natural ArgumentException + if (typeName.Length == 0) + { + if (throwOnError) + throw new TypeLoadException(SR.Arg_TypeLoadNullStr); + return null; + } + + TypeName? parsed = TypeNameParser.Parse(typeName, throwOnError); + if (parsed is null) + { + return null; + } + + return new TypeNameResolver() + { + _assemblyResolver = assemblyResolver, + _typeResolver = typeResolver, + _throwOnError = throwOnError, + _ignoreCase = ignoreCase, + _stackMark = Unsafe.AsPointer(ref stackMark) + }.Resolve(parsed); + } + + private Assembly? ResolveAssembly(AssemblyName name) + { + Assembly? assembly; + if (_assemblyResolver is not null) + { + assembly = _assemblyResolver(name); + if (assembly is null && _throwOnError) + { + throw new FileNotFoundException(SR.Format(SR.FileNotFound_ResolveAssembly, name.FullName)); + } + } + else + { + ref StackCrawlMark stackMark = ref Unsafe.AsRef(_stackMark); + + if (_throwOnError) + { + assembly = Assembly.Load(name, ref stackMark, null); + } + else + { + // When throwOnError is false we should only catch FileNotFoundException. + // Other exceptions like BadImangeFormatException should still fly. + try + { + assembly = Assembly.Load(name, ref stackMark, null); + } + catch (FileNotFoundException) + { + return null; + } + } + } + return assembly; + } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", + Justification = "TypeNameResolver.GetType is marked as RequiresUnreferencedCode.")] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "TypeNameResolver.GetType is marked as RequiresUnreferencedCode.")] + private Type? GetType(string escapedTypeName, ReadOnlySpan nestedTypeNames, TypeName parsedName) + { + Assembly? assembly = (parsedName.AssemblyName is not null) ? ResolveAssembly(parsedName.AssemblyName.ToAssemblyName()) : null; + + // Both the external type resolver and the default type resolvers expect escaped type names + Type? type; + + // Resolve the top level type. + if (_typeResolver is not null) + { + type = _typeResolver(assembly, escapedTypeName, _ignoreCase); + + if (type is null) + { + if (_throwOnError) + { + throw new TypeLoadException(assembly is null ? + SR.Format(SR.TypeLoad_ResolveType, escapedTypeName) : + SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, escapedTypeName, assembly.FullName)); + } + return null; + } + } + else + { + if (assembly is null) + { + ref StackCrawlMark stackMark = ref Unsafe.AsRef(_stackMark); + + type = RuntimeType.GetType(escapedTypeName, _throwOnError, _ignoreCase, ref stackMark); + } + else + { + type = assembly.GetType(escapedTypeName, _throwOnError, _ignoreCase); + } + + if (type is null) + { + return null; + } + } + + for (int i = 0; i < nestedTypeNames.Length; i++) + { + BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public; + if (_ignoreCase) + bindingFlags |= BindingFlags.IgnoreCase; + + type = type.GetNestedType(nestedTypeNames[i], bindingFlags); + + if (type is null) + { + if (_throwOnError) + { + throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveNestedType, + nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : TypeNameHelpers.Unescape(escapedTypeName))); + } + return null; + } + } + + return type; + } + } +} diff --git a/src/mono/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs index 1e2241de12b3..9be5b3d817dc 100644 --- a/src/mono/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs @@ -77,6 +77,7 @@ internal static int TryGetHashCode(object? o) } [MethodImplAttribute(MethodImplOptions.InternalCall)] + [return: NotNullIfNotNull(nameof(obj))] public static extern object? GetObjectValue(object? obj); [RequiresUnreferencedCode("Trimmer can't guarantee existence of class constructor")] @@ -258,5 +259,29 @@ private static extern unsafe IntPtr GetSpanDataFrom( InternalBox(new QCallTypeHandle(ref rtType), ref target, ObjectHandleOnStack.Create(ref result)); return result; } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern int SizeOf(QCallTypeHandle handle); + + /// + /// Get the size of an object of the given type. + /// + /// The type to get the size of. + /// The size of instances of the type. + /// The passed-in type is not a valid type to get the size of. + /// + /// This API returns the same value as for the type that represents. + /// + public static int SizeOf(RuntimeTypeHandle type) + { + if (type.Value == IntPtr.Zero) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.type); + + Type typeObj = Type.GetTypeFromHandle(type)!; + if (typeObj.ContainsGenericParameters || typeObj.IsGenericParameter || typeObj == typeof(void)) + throw new ArgumentException(SR.Arg_TypeNotSupported); + + return SizeOf(new QCallTypeHandle(ref type)); + } } } diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs index 62fb94c5a741..f289911d790f 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs @@ -2218,16 +2218,6 @@ public override string ToString() [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern object CreateInstanceInternal(QCallTypeHandle type); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void AllocateValueType(QCallTypeHandle type, object? value, ObjectHandleOnStack res); - - internal static object AllocateValueType(RuntimeType type, object? value) - { - object? res = null; - AllocateValueType(new QCallTypeHandle(ref type), value, ObjectHandleOnStack.Create(ref res)); - return res!; - } - [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void GetDeclaringMethod(QCallTypeHandle type, ObjectHandleOnStack res); diff --git a/src/mono/System.Private.CoreLib/src/System/Type.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Type.Mono.cs index 851cc8f92c55..3fc4f6082c9b 100644 --- a/src/mono/System.Private.CoreLib/src/System/Type.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Type.Mono.cs @@ -76,7 +76,7 @@ internal IntPtr GetUnderlyingNativeHandle() [RequiresUnreferencedCode("The type might be removed")] private static Type? GetType(string typeName, Func? assemblyResolver, Func? typeResolver, bool throwOnError, bool ignoreCase, ref StackCrawlMark stackMark) { - return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark); + return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark); } public static Type? GetTypeFromHandle(RuntimeTypeHandle handle) diff --git a/src/mono/browser/Makefile b/src/mono/browser/Makefile index 6b756c64e33e..1401a1b36a43 100644 --- a/src/mono/browser/Makefile +++ b/src/mono/browser/Makefile @@ -167,4 +167,4 @@ build-app-host: $(DOTNET) build $(TOP)/src/mono/wasm/host $(_MSBUILD_WASM_BUILD_ARGS) $(MSBUILD_ARGS) patch-deterministic: - cd emsdk/upstream/emscripten/ && patch -p1 < ../../../runtime/deterministic.diff + cd emsdk/emscripten/ && patch -p1 < ../../../runtime/deterministic.diff diff --git a/src/mono/browser/README.md b/src/mono/browser/README.md index 4fb494a86b19..ced0882ae831 100644 --- a/src/mono/browser/README.md +++ b/src/mono/browser/README.md @@ -362,18 +362,18 @@ npm update --lockfile-version=1 Tests are run with V8, Chrome, node, and wasmtime for the various jobs. -- V8: the version used is from `eng/testing/ChromeVersions.props`. This is used for all the library tests, and WBT, but *not* runtime tests. +- V8: the version used is from `eng/testing/BrowserVersions.props`. This is used for all the library tests, and WBT, but *not* runtime tests. - Chrome: Same as V8. - Node: fixed version from emsdk - wasmtime - fixed version in `src/mono/wasi/wasi-sdk-version.txt`. -### `eng/testing/ChromeVersions.props` +### `eng/testing/BrowserVersions.props` This file is updated once a week by a github action `.github/workflows/bump-chrome-version.yml`, and the version is obtained by `src/tasks/WasmBuildTasks/GetChromeVersions.cs` task. # Perf pipeline -- V8 version used to run the microbenchmarks is from `eng/testing/ChromeVersions.props` +- V8 version used to run the microbenchmarks is from `eng/testing/BrowserVersions.props` TBD diff --git a/src/mono/browser/browser.proj b/src/mono/browser/browser.proj index 201e214592c7..519e5c3b407d 100644 --- a/src/mono/browser/browser.proj +++ b/src/mono/browser/browser.proj @@ -36,7 +36,9 @@ <_EmccDefaultsRspPath>$(NativeBinDir)src\emcc-default.rsp <_EmccCompileRspPath>$(NativeBinDir)src\emcc-compile.rsp <_EmccLinkRspPath>$(NativeBinDir)src\emcc-link.rsp - $(EMSDK_PATH)\upstream\bin\llvm-ar + $(EMSDK_PATH)\bin\llvm-ar + + $(EMSDK_PATH)\upstream\bin\llvm-ar $(EmSdkLLVMAr).exe @@ -191,6 +193,7 @@ + @@ -206,12 +209,14 @@ + + @@ -400,12 +405,12 @@ $(CMakeBuildRuntimeConfigureCmd) -DENABLE_JS_INTEROP_BY_VALUE=1 $(CMakeBuildRuntimeConfigureCmd) $(CMakeConfigurationEmsdkPath) - call "$(RepositoryEngineeringDir)native\init-vs-env.cmd" && call "$([MSBuild]::NormalizePath('$(EMSDK_PATH)', 'emsdk_env.bat'))" && $(CMakeBuildRuntimeConfigureCmd) + call "$(RepositoryEngineeringDir)native\init-vs-env.cmd" && call "$([MSBuild]::NormalizePath('$(EMSDK_PATH)', 'emsdk_env.cmd'))" && $(CMakeBuildRuntimeConfigureCmd) bash -c 'source $(EMSDK_PATH)/emsdk_env.sh 2>&1 && $(CMakeBuildRuntimeConfigureCmd)' -v cmake --build . --config $(Configuration) $(CmakeOptions) - call "$(RepositoryEngineeringDir)native\init-vs-env.cmd" && call "$([MSBuild]::NormalizePath('$(EMSDK_PATH)', 'emsdk_env.bat'))" && $(CMakeBuildRuntimeCmd) + call "$(RepositoryEngineeringDir)native\init-vs-env.cmd" && call "$([MSBuild]::NormalizePath('$(EMSDK_PATH)', 'emsdk_env.cmd'))" && $(CMakeBuildRuntimeCmd) bash -c 'source $(EMSDK_PATH)/emsdk_env.sh 2>&1 && $(CMakeBuildRuntimeCmd)' @@ -493,14 +498,15 @@ true <_HasDotnetJsSymbols Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.js.symbols'">true <_HasDotnetNativeJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.js'">true + <_HasDotnetGlobalizationJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.globalization.js'">true false <_WasmIcuDataFileName Condition="'$(HybridGlobalization)' != 'true' and '$(WasmIcuDataFileName)' != '' and Exists('$(WasmIcuDataFileName)')">$(WasmIcuDataFileName) <_WasmIcuDataFileName Condition="'$(HybridGlobalization)' != 'true' and '$(WasmIcuDataFileName)' != '' and !Exists('$(WasmIcuDataFileName)')">$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(WasmIcuDataFileName) @@ -88,6 +89,10 @@ + @@ -260,6 +267,8 @@ $(_EmccOptimizationFlagDefault) $(EmccCompileOptimizationFlag) + -O2 + $(WasmCompileOptimizationFlag) -O2 $(WasmCompileOptimizationFlag) $(EmccLinkOptimizationFlag) @@ -406,8 +415,9 @@ - <_BitcodeLDFlags Include="@(_EmccLDFlags)" /> - <_BitcodeLDFlags Include="$(EmccExtraBitcodeLDFlags)" /> + <_BitcodeCompileFlags Include="$(WasmBitcodeCompileOptimizationFlag)" /> + <_BitcodeCompileFlags Include="@(_EmccCommonFlags)" /> + <_BitcodeCompileFlags Include="$(EmccExtraBitcodeCompilationFlags)" /> @@ -486,6 +496,7 @@ + @@ -541,6 +552,7 @@ + <_WasmAssembliesInternal Remove="$(_WasmDedupAssembly)"/> diff --git a/src/mono/browser/build/EmSdkRepo.Defaults.props b/src/mono/browser/build/EmSdkRepo.Defaults.props index 23bfe4551a5c..4e56389ea631 100644 --- a/src/mono/browser/build/EmSdkRepo.Defaults.props +++ b/src/mono/browser/build/EmSdkRepo.Defaults.props @@ -4,25 +4,18 @@ $([MSBuild]::EnsureTrailingSlash($(EMSDK_PATH))) - $([MSBuild]::NormalizeDirectory($(EmscriptenSdkToolsPath), 'upstream', 'bin')) - $([MSBuild]::NormalizeDirectory($(EmscriptenSdkToolsPath), 'upstream', 'emscripten')) - - <_NodeToolsBasePath>$(EmscriptenSdkToolsPath)node + $([MSBuild]::NormalizeDirectory($(EmscriptenSdkToolsPath), 'bin')) + $([MSBuild]::NormalizeDirectory($(EmscriptenSdkToolsPath), 'emscripten')) - <_NodeToolsVersionedPath Condition="Exists($(_NodeToolsBasePath))">$([System.IO.Directory]::GetDirectories($(_NodeToolsBasePath))) - $(_NodeToolsVersionedPath) - $([MSBuild]::NormalizeDirectory($(EmscriptenNodeToolsPath))) + $([MSBuild]::NormalizeDirectory($(EmscriptenSdkToolsPath), 'node', 'bin')) <_UsingEMSDK_PATH>true - <_PythonToolsBasePath>$(EmscriptenSdkToolsPath)python - <_PythonToolsVersionedPath Condition="Exists($(_PythonToolsBasePath))">$([System.IO.Directory]::GetDirectories($(_PythonToolsBasePath))) - $(_PythonToolsVersionedPath) - $([MSBuild]::NormalizeDirectory($(EmscriptenPythonToolsPath))) + $([MSBuild]::NormalizeDirectory($(EmscriptenSdkToolsPath)python)) <_EMSDKMissingPaths Condition="'$(_EMSDKMissingPaths)' == '' and ('$(EmscriptenPythonToolsPath)' == '' or !Exists('$(EmscriptenPythonToolsPath)'))">%24(EmscriptenPythonToolsPath)=$(EmscriptenPythonToolsPath) @@ -31,9 +24,9 @@ - + - + diff --git a/src/mono/browser/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/browser/debugger/BrowserDebugProxy/DebugStore.cs index a6c80c89ac8d..dfd0f368561b 100644 --- a/src/mono/browser/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/browser/debugger/BrowserDebugProxy/DebugStore.cs @@ -358,7 +358,7 @@ internal sealed class MethodInfo public int KickOffMethod { get; } internal bool IsCompilerGenerated { get; } private AsyncScopeDebugInformation[] _asyncScopes { get; set; } - private static SignatureTypeProvider _signatureTypeProvider = new(); + private static readonly SignatureTypeProvider _signatureTypeProvider = new(); public MethodInfo(AssemblyInfo assembly, string methodName, int methodToken, TypeInfo type, MethodAttributes attrs) { diff --git a/src/mono/browser/debugger/DebuggerTestSuite/ChromeProvider.cs b/src/mono/browser/debugger/DebuggerTestSuite/ChromeProvider.cs index 17eedf748ed7..1da9fbca9807 100644 --- a/src/mono/browser/debugger/DebuggerTestSuite/ChromeProvider.cs +++ b/src/mono/browser/debugger/DebuggerTestSuite/ChromeProvider.cs @@ -28,8 +28,8 @@ internal class ChromeProvider : WasmHostProvider private DebuggerProxy? _debuggerProxy; private static readonly Lazy s_browserPath = new(() => { - string artifactsBinDir = Path.Combine(Path.GetDirectoryName(typeof(ChromeProvider).Assembly.Location)!, "..", "..", ".."); - return BrowserLocator.FindChrome(artifactsBinDir, "BROWSER_PATH_FOR_TESTS"); + string artifactsBinDir = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(typeof(ChromeProvider).Assembly.Location)!, "..", "..", "..")); + return BrowserLocator.FindChrome(artifactsBinDir, "CHROME_PATH_FOR_TESTS"); }); private static readonly string[] s_messagesToFilterOut = new[] { diff --git a/src/mono/browser/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs b/src/mono/browser/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs index 82ea36992d34..5e099a787bc4 100644 --- a/src/mono/browser/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs +++ b/src/mono/browser/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs @@ -216,7 +216,7 @@ await EvaluateOnCallFrameAndCheck(id, ($"local_dt.Date.Year * 10", TNumber(10))); }); - [Theory] + [ConditionalTheory(nameof(RunningOnChrome))] [InlineData("")] [InlineData("this.")] public async Task InheritedAndPrivateMembersInAClass(string prefix) diff --git a/src/mono/browser/debugger/DebuggerTestSuite/FirefoxProvider.cs b/src/mono/browser/debugger/DebuggerTestSuite/FirefoxProvider.cs index b64fe84ca3d9..e854b63b0ef7 100644 --- a/src/mono/browser/debugger/DebuggerTestSuite/FirefoxProvider.cs +++ b/src/mono/browser/debugger/DebuggerTestSuite/FirefoxProvider.cs @@ -23,8 +23,8 @@ internal class FirefoxProvider : WasmHostProvider private FirefoxDebuggerProxy? _firefoxDebuggerProxy; private static readonly Lazy s_browserPath = new(() => { - string artifactsBinDir = Path.Combine(Path.GetDirectoryName(typeof(ChromeProvider).Assembly.Location)!, "..", "..", ".."); - return BrowserLocator.FindFirefox(artifactsBinDir, "BROWSER_PATH_FOR_TESTS"); + string artifactsBinDir = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(typeof(ChromeProvider).Assembly.Location)!, "..", "..", "..")); + return BrowserLocator.FindFirefox(artifactsBinDir, "FIREFOX_PATH_FOR_TESTS"); }); public FirefoxProvider(string id, ILogger logger) : base(id, logger) diff --git a/src/mono/browser/debugger/DebuggerTestSuite/SteppingTests.cs b/src/mono/browser/debugger/DebuggerTestSuite/SteppingTests.cs index 0074c536db81..2d7f86b950ee 100644 --- a/src/mono/browser/debugger/DebuggerTestSuite/SteppingTests.cs +++ b/src/mono/browser/debugger/DebuggerTestSuite/SteppingTests.cs @@ -1166,60 +1166,6 @@ await StepAndCheck(StepKind.Into, "dotnet://Newtonsoft.Json.dll/JArray.cs", 350, ); } - [ConditionalTheory(nameof(RunningOnChrome))] - [InlineData("https://symbols.nuget.org/download/symbols", "")] - // Symbols are already loaded, so setting urls = [] won't affect it - [InlineData] - [InlineData("", "https://microsoft.com/non-existant/symbols")] - public async Task SteppingIntoLibrarySymbolsLoadedFromSymbolServerRemoveSymbolServerAndStepAgain(params string[] secondServers) - { - string cachePath = _env.CreateTempDirectory("symbols-cache"); - _testOutput.WriteLine($"Using cachePath: {cachePath}"); - var searchPaths = new JArray - { - "https://symbols.nuget.org/download/symbols", - "https://msdl.microsoft.com/download/bad-non-existant", - "https://msdl.microsoft.com/download/symbols" - }; - var waitForScript = WaitForScriptParsedEventsAsync(new string [] { "JArray.cs" }); - var symbolOptions = JObject.FromObject(new { symbolOptions = JObject.FromObject(new { cachePath, searchPaths })}); - await SetJustMyCode(false); - await SetSymbolOptions(symbolOptions); - - await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method ('[debugger-test] TestLoadSymbols:Run'); invoke_static_method ('[debugger-test] TestLoadSymbols:Run'); }, 1);", - "dotnet://debugger-test.dll/debugger-test.cs", 1572, 8, - "TestLoadSymbols.Run" - ); - - await waitForScript; - - await StepAndCheck(StepKind.Into, "dotnet://Newtonsoft.Json.dll/JArray.cs", 350, 12, "Newtonsoft.Json.Linq.JArray.Add", - locals_fn: async (locals) => - { - await CheckObject(locals, "this", "Newtonsoft.Json.Linq.JArray", description: "[]"); - }, times: 2 - ); - searchPaths.Clear(); - foreach (string secondServer in secondServers) - searchPaths.Add(secondServer); - - symbolOptions = JObject.FromObject(new { symbolOptions = JObject.FromObject(new { cachePath, searchPaths })}); - await SetSymbolOptions(symbolOptions); - - await SendCommandAndCheck(null, "Debugger.resume", - "dotnet://debugger-test.dll/debugger-test.cs", 1572, 8, - "TestLoadSymbols.Run" - ); - - await StepAndCheck(StepKind.Into, "dotnet://Newtonsoft.Json.dll/JArray.cs", 350, 12, "Newtonsoft.Json.Linq.JArray.Add", - locals_fn: async (locals) => - { - await CheckObject(locals, "this", "Newtonsoft.Json.Linq.JArray", description: "[]"); - }, times: 2 - ); - } - [ConditionalTheory(nameof(RunningOnChrome))] [InlineData(true)] [InlineData(false)] diff --git a/src/mono/browser/debugger/Wasm.Debugger.Tests/Wasm.Debugger.Tests.csproj b/src/mono/browser/debugger/Wasm.Debugger.Tests/Wasm.Debugger.Tests.csproj index f305f84eb753..008a633de762 100644 --- a/src/mono/browser/debugger/Wasm.Debugger.Tests/Wasm.Debugger.Tests.csproj +++ b/src/mono/browser/debugger/Wasm.Debugger.Tests/Wasm.Debugger.Tests.csproj @@ -52,12 +52,12 @@ - - + + - + diff --git a/src/mono/browser/debugger/Wasm.Debugger.Tests/wasm.helix.targets b/src/mono/browser/debugger/Wasm.Debugger.Tests/wasm.helix.targets index e645a2c42c4d..4c36a8937fc1 100644 --- a/src/mono/browser/debugger/Wasm.Debugger.Tests/wasm.helix.targets +++ b/src/mono/browser/debugger/Wasm.Debugger.Tests/wasm.helix.targets @@ -1,6 +1,7 @@ - true + true + true $(DebuggerHost)- true <_DebuggerTestsWorkItemTimeout Condition="'$(Scenario)' == 'WasmDebuggerTests'">00:50:00 diff --git a/src/mono/browser/debugger/tests/debugger-test/debugger-driver.html b/src/mono/browser/debugger/tests/debugger-test/debugger-driver.html index 9d04b58b665c..e140e64e6ad4 100644 --- a/src/mono/browser/debugger/tests/debugger-test/debugger-driver.html +++ b/src/mono/browser/debugger/tests/debugger-test/debugger-driver.html @@ -1,4 +1,4 @@ - + diff --git a/src/mono/browser/debugger/tests/debugger-test/non-wasm-page.html b/src/mono/browser/debugger/tests/debugger-test/non-wasm-page.html index 2894375a79c8..1442fc9b6af9 100644 --- a/src/mono/browser/debugger/tests/debugger-test/non-wasm-page.html +++ b/src/mono/browser/debugger/tests/debugger-test/non-wasm-page.html @@ -1,4 +1,4 @@ - + diff --git a/src/mono/browser/debugger/tests/debugger-test/wasm-page-without-assets.html b/src/mono/browser/debugger/tests/debugger-test/wasm-page-without-assets.html index 49a836c8e885..9fcdbf4570c1 100644 --- a/src/mono/browser/debugger/tests/debugger-test/wasm-page-without-assets.html +++ b/src/mono/browser/debugger/tests/debugger-test/wasm-page-without-assets.html @@ -1,4 +1,4 @@ - + diff --git a/src/mono/browser/runtime/CMakeLists.txt b/src/mono/browser/runtime/CMakeLists.txt index 60570d6deafd..8b7939330f8c 100644 --- a/src/mono/browser/runtime/CMakeLists.txt +++ b/src/mono/browser/runtime/CMakeLists.txt @@ -44,7 +44,7 @@ set(ignoreMeEmsdkPath "${EMSDK_PATH}") if(CMAKE_BUILD_TYPE STREQUAL "Release") add_custom_command(TARGET dotnet.native - POST_BUILD COMMAND ${EMSDK_PATH}/upstream/bin/wasm-opt --enable-exception-handling ${CONFIGURATION_WASM_OPT_FLAGS} --strip-dwarf ${NATIVE_BIN_DIR}/dotnet.native.wasm -o ${NATIVE_BIN_DIR}/dotnet.native.wasm + POST_BUILD COMMAND ${EMSDK_PATH}/bin/wasm-opt --enable-exception-handling ${CONFIGURATION_WASM_OPT_FLAGS} --strip-dwarf ${NATIVE_BIN_DIR}/dotnet.native.wasm -o ${NATIVE_BIN_DIR}/dotnet.native.wasm COMMENT "Stripping debug symbols from dotnet.native.wasm using wasm-opt") endif() diff --git a/src/mono/browser/runtime/assets.ts b/src/mono/browser/runtime/assets.ts index 7cdff19d8a84..930f5bb20d18 100644 --- a/src/mono/browser/runtime/assets.ts +++ b/src/mono/browser/runtime/assets.ts @@ -5,17 +5,16 @@ import type { AssetEntryInternal } from "./types/internal"; import cwraps from "./cwraps"; import { mono_wasm_load_icu_data } from "./icu"; -import { Module, loaderHelpers, mono_assert, runtimeHelpers } from "./globals"; +import { Module, globalizationHelpers, loaderHelpers, mono_assert, runtimeHelpers } from "./globals"; import { mono_log_info, mono_log_debug, parseSymbolMapFile } from "./logging"; -import { mono_wasm_load_bytes_into_heap } from "./memory"; +import { mono_wasm_load_bytes_into_heap_persistent } from "./memory"; import { endMeasure, MeasuredBlock, startMeasure } from "./profiler"; import { AssetEntry } from "./types"; import { VoidPtr } from "./types/emscripten"; -import { setSegmentationRulesFromJson } from "./hybrid-globalization/grapheme-segmenter"; // this need to be run only after onRuntimeInitialized event, when the memory is ready export function instantiate_asset (asset: AssetEntry, url: string, bytes: Uint8Array): void { - mono_log_debug(`Loaded:${asset.name} as ${asset.behavior} size ${bytes.length} from ${url}`); + mono_log_debug(() => `Loaded:${asset.name} as ${asset.behavior} size ${bytes.length} from ${url}`); const mark = startMeasure(); const virtualName: string = typeof (asset.virtualPath) === "string" @@ -26,6 +25,7 @@ export function instantiate_asset (asset: AssetEntry, url: string, bytes: Uint8A switch (asset.behavior) { case "dotnetwasm": case "js-module-threads": + case "js-module-globalization": case "symbols": case "segmentation-rules": // do nothing @@ -37,21 +37,24 @@ export function instantiate_asset (asset: AssetEntry, url: string, bytes: Uint8A // falls through case "heap": case "icu": - offset = mono_wasm_load_bytes_into_heap(bytes); + offset = mono_wasm_load_bytes_into_heap_persistent(bytes); break; case "vfs": { // FIXME const lastSlash = virtualName.lastIndexOf("/"); let parentDirectory = (lastSlash > 0) - ? virtualName.substr(0, lastSlash) + ? virtualName.substring(0, lastSlash) : null; let fileName = (lastSlash > 0) - ? virtualName.substr(lastSlash + 1) + ? virtualName.substring(lastSlash + 1) : virtualName; if (fileName.startsWith("/")) - fileName = fileName.substr(1); + fileName = fileName.substring(1); if (parentDirectory) { + if (!parentDirectory.startsWith("/")) + parentDirectory = "/" + parentDirectory; + mono_log_debug(`Creating directory '${parentDirectory}'`); Module.FS_createPath( @@ -61,7 +64,7 @@ export function instantiate_asset (asset: AssetEntry, url: string, bytes: Uint8A parentDirectory = "/"; } - mono_log_debug(`Creating file '${fileName}' in directory '${parentDirectory}'`); + mono_log_debug(() => `Creating file '${fileName}' in directory '${parentDirectory}'`); Module.FS_createDataFile( parentDirectory, fileName, @@ -85,8 +88,7 @@ export function instantiate_asset (asset: AssetEntry, url: string, bytes: Uint8A } else if (asset.behavior === "pdb") { cwraps.mono_wasm_add_assembly(virtualName, offset!, bytes.length); } else if (asset.behavior === "icu") { - if (!mono_wasm_load_icu_data(offset!)) - Module.err(`Error loading ICU asset ${asset.name}`); + mono_wasm_load_icu_data(offset!); } else if (asset.behavior === "resource") { cwraps.mono_wasm_add_satellite_assembly(virtualName, asset.culture || "", offset!, bytes.length); } @@ -108,7 +110,7 @@ export async function instantiate_segmentation_rules_asset (pendingAsset: AssetE try { const response = await pendingAsset.pendingDownloadInternal!.response; const json = await response.json(); - setSegmentationRulesFromJson(json); + globalizationHelpers.setSegmentationRulesFromJson(json); } catch (error: any) { mono_log_info(`Error loading static json asset ${pendingAsset.name}: ${JSON.stringify(error)}`); } diff --git a/src/mono/browser/runtime/cancelable-promise.ts b/src/mono/browser/runtime/cancelable-promise.ts index c82cbdacb196..fa4e11fe07ee 100644 --- a/src/mono/browser/runtime/cancelable-promise.ts +++ b/src/mono/browser/runtime/cancelable-promise.ts @@ -111,9 +111,12 @@ export class PromiseHolder extends ManagedObject { mono_log_debug("This promise rejection can't be propagated to managed code, mono runtime already exited."); return; } + if (!reason) { + reason = new Error() as any; + } mono_assert(!this.isResolved, "reject could be called only once"); mono_assert(!this.isDisposed, "resolve is already disposed."); - const isCancelation = reason && reason[promise_holder_symbol] === this; + const isCancelation = reason[promise_holder_symbol] === this; if (WasmEnableThreads && !isCancelation && !this.setIsResolving()) { // we know that cancelation is in flight // because we need to keep the GCHandle alive until until the cancelation arrives @@ -166,9 +169,7 @@ export class PromiseHolder extends ManagedObject { try { mono_assert(!this.isPosted, "Promise is already posted to managed."); this.isPosted = true; - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } + forceThreadMemoryViewRefresh(); // we can unregister the GC handle just on JS side teardown_managed_proxy(this, this.gc_handle, /*skipManaged: */ true); diff --git a/src/mono/browser/runtime/corebindings.c b/src/mono/browser/runtime/corebindings.c index 485ba3189af6..1937eb114dd6 100644 --- a/src/mono/browser/runtime/corebindings.c +++ b/src/mono/browser/runtime/corebindings.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -34,7 +35,7 @@ typedef void (*background_job_cb)(void); void mono_wasm_bind_assembly_exports (char *assembly_name); void mono_wasm_assembly_get_entry_point (char *assembly_name, int auto_insert_breakpoint, MonoMethod **method_out); -void mono_wasm_get_assembly_export (char *assembly_name, char *namespace, char *classname, char *methodname, MonoMethod **method_out); +void mono_wasm_get_assembly_export (char *assembly_name, char *namespace, char *classname, char *methodname, int signature_hash, MonoMethod **method_out); #ifndef DISABLE_THREADS void mono_wasm_release_cs_owned_object_post (pthread_t target_tid, int js_handle); @@ -58,17 +59,17 @@ extern void mono_wasm_invoke_jsimport_ST (int function_handle, void *args); #endif /* DISABLE_THREADS */ // HybridGlobalization -extern void mono_wasm_change_case_invariant (const uint16_t* src, int32_t srcLength, uint16_t* dst, int32_t dstLength, mono_bool bToUpper, int *is_exception, MonoObject** ex_result); -extern void mono_wasm_change_case (MonoString **culture, const uint16_t* src, int32_t srcLength, uint16_t* dst, int32_t dstLength, mono_bool bToUpper, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_compare_string (MonoString **culture, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, int *is_exception, MonoObject** ex_result); -extern mono_bool mono_wasm_starts_with (MonoString **culture, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, int *is_exception, MonoObject** ex_result); -extern mono_bool mono_wasm_ends_with (MonoString **culture, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_index_of (MonoString **culture, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, mono_bool fromBeginning, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_get_calendar_info (MonoString **culture, int32_t calendarId, const uint16_t* result, int32_t resultLength, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_get_locale_info (MonoString **locale, MonoString **culture, const uint16_t* result, int32_t resultLength, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_get_culture_info (MonoString **culture, const uint16_t* result, int32_t resultLength, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_get_first_day_of_week (MonoString **culture, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_get_first_week_of_year (MonoString **culture, int *is_exception, MonoObject** ex_result); +extern char16_t* mono_wasm_change_case_invariant (const uint16_t* src, int32_t srcLength, uint16_t* dst, int32_t dstLength, mono_bool bToUpper); +extern char16_t* mono_wasm_change_case (const uint16_t* culture, int32_t cultureLength, const uint16_t* src, int32_t srcLength, uint16_t* dst, int32_t dstLength, mono_bool bToUpper); +extern char16_t* mono_wasm_compare_string (const uint16_t* culture, int32_t cultureLength, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, int *resultPtr); +extern char16_t* mono_wasm_starts_with (const uint16_t* culture, int32_t cultureLength, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, mono_bool *resultPtr); +extern char16_t* mono_wasm_ends_with (const uint16_t* culture, int32_t cultureLength, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, mono_bool *resultPtr); +extern char16_t* mono_wasm_index_of (const uint16_t* culture, int32_t cultureLength, const uint16_t* str1, int32_t str1Length, const uint16_t* str2, int32_t str2Length, int32_t options, mono_bool fromBeginning, int *resultPtr); +extern char16_t* mono_wasm_get_calendar_info (const uint16_t* culture, int32_t cultureLength, int32_t calendarId, const uint16_t* result, int32_t resultMaxLength, int *resultLength); +extern char16_t* mono_wasm_get_culture_info (const uint16_t* culture, int32_t cultureLength, const uint16_t* result, int32_t resultMaxLength, int *resultLength); +extern char16_t* mono_wasm_get_locale_info (const uint16_t* locale, int32_t localeLength, const uint16_t* culture, int32_t cultureLength, const uint16_t* result, int32_t resultMaxLength, int *resultLength); +extern char16_t* mono_wasm_get_first_day_of_week (const uint16_t* culture, int32_t cultureLength, int *resultPtr); +extern char16_t* mono_wasm_get_first_week_of_year (const uint16_t* culture, int32_t cultureLength, int *resultPtr); void bindings_initialize_internals (void) { @@ -100,7 +101,9 @@ void bindings_initialize_internals (void) mono_add_internal_call ("Interop/Runtime::AssemblyGetEntryPoint", mono_wasm_assembly_get_entry_point); mono_add_internal_call ("Interop/Runtime::BindAssemblyExports", mono_wasm_bind_assembly_exports); mono_add_internal_call ("Interop/Runtime::GetAssemblyExport", mono_wasm_get_assembly_export); + mono_add_internal_call ("System.ConsolePal::Clear", mono_wasm_console_clear); + // HybridGlobalization mono_add_internal_call ("Interop/JsGlobalization::ChangeCaseInvariant", mono_wasm_change_case_invariant); mono_add_internal_call ("Interop/JsGlobalization::ChangeCase", mono_wasm_change_case); mono_add_internal_call ("Interop/JsGlobalization::CompareString", mono_wasm_compare_string); @@ -112,7 +115,6 @@ void bindings_initialize_internals (void) mono_add_internal_call ("Interop/JsGlobalization::GetCultureInfo", mono_wasm_get_culture_info); mono_add_internal_call ("Interop/JsGlobalization::GetFirstDayOfWeek", mono_wasm_get_first_day_of_week); mono_add_internal_call ("Interop/JsGlobalization::GetFirstWeekOfYear", mono_wasm_get_first_week_of_year); - mono_add_internal_call ("System.ConsolePal::Clear", mono_wasm_console_clear); } static MonoAssembly* _mono_wasm_assembly_load (char *assembly_name) @@ -230,13 +232,14 @@ void mono_wasm_bind_assembly_exports (char *assembly_name) } } -void mono_wasm_get_assembly_export (char *assembly_name, char *namespace, char *classname, char *methodname, MonoMethod **method_out) +void mono_wasm_get_assembly_export (char *assembly_name, char *namespace, char *classname, char *methodname, int signature_hash, MonoMethod **method_out) { MonoError error; MonoAssembly* assembly; MonoImage *image; MonoClass *klass; MonoMethod *method=NULL; + char real_method_name_buffer[4096]; *method_out = NULL; assert (assembly_name); @@ -247,10 +250,15 @@ void mono_wasm_get_assembly_export (char *assembly_name, char *namespace, char * klass = mono_class_from_name (image, namespace, classname); assert (klass); - method = mono_class_get_method_from_name (klass, methodname, -1); + + snprintf(real_method_name_buffer, 4096, "__Wrapper_%s_%d", methodname, signature_hash); + + method = mono_class_get_method_from_name (klass, real_method_name_buffer, -1); assert (method); *method_out = method; + // This is freed by _mono_wasm_assembly_load for some reason + // free (assembly_name); free (namespace); free (classname); free (methodname); diff --git a/src/mono/browser/runtime/cwraps.ts b/src/mono/browser/runtime/cwraps.ts index ac616ec112d5..e4fbbea87056 100644 --- a/src/mono/browser/runtime/cwraps.ts +++ b/src/mono/browser/runtime/cwraps.ts @@ -65,7 +65,6 @@ const fn_signatures: SigLine[] = [ [true, "mono_wasm_intern_string_ref", "void", ["number"]], [false, "mono_wasm_exit", "void", ["number"]], - [false, "mono_wasm_abort", "void", []], [true, "mono_wasm_getenv", "number", ["string"]], [true, "mono_wasm_set_main_args", "void", ["number", "number"]], // These two need to be lazy because they may be missing @@ -102,6 +101,7 @@ const fn_signatures: SigLine[] = [ [true, "mono_jiterp_get_size_of_stackval", "number", []], [true, "mono_jiterp_parse_option", "number", ["string"]], [true, "mono_jiterp_get_options_as_json", "number", []], + [true, "mono_jiterp_get_option_as_int", "number", ["string"]], [true, "mono_jiterp_get_options_version", "number", []], [true, "mono_jiterp_adjust_abort_count", "number", ["number", "number"]], [true, "mono_jiterp_register_jit_call_thunk", "void", ["number", "number"]], @@ -194,7 +194,6 @@ export interface t_Cwraps { mono_wasm_intern_string_ref(strRef: MonoStringRef): void; mono_wasm_exit(exit_code: number): void; - mono_wasm_abort(): void; mono_wasm_getenv(name: string): CharPtr; mono_wasm_set_main_args(argc: number, argv: VoidPtr): void; mono_wasm_exec_regression(verbose_level: number, image: string): number; @@ -232,6 +231,7 @@ export interface t_Cwraps { mono_jiterp_type_get_raw_value_size(type: MonoType): number; mono_jiterp_parse_option(name: string): number; mono_jiterp_get_options_as_json(): number; + mono_jiterp_get_option_as_int(name: string): number; mono_jiterp_get_options_version(): number; mono_jiterp_adjust_abort_count(opcode: number, delta: number): number; mono_jiterp_register_jit_call_thunk(cinfo: number, func: number): void; diff --git a/src/mono/browser/runtime/diagnostics/mock/index.ts b/src/mono/browser/runtime/diagnostics/mock/index.ts index d320980e454d..3d1014d02c12 100644 --- a/src/mono/browser/runtime/diagnostics/mock/index.ts +++ b/src/mono/browser/runtime/diagnostics/mock/index.ts @@ -31,7 +31,7 @@ export function mock (script: MockScript): Mock { class MockScriptEngineSocketImpl implements MockRemoteSocket { constructor (private readonly engine: MockScriptEngineImpl) { } send (data: string | ArrayBuffer): void { - mono_log_debug(`mock ${this.engine.ident} client sent: `, data); + mono_log_debug(() => `mock ${this.engine.ident} client sent: ${data}`); let event: MessageEvent | null = null; if (typeof data === "string") { event = new MessageEvent("message", { data }); @@ -46,15 +46,15 @@ export function mock (script: MockScript): Mock { } addEventListener(event: T, listener: (event: WebSocketEventMap[T]) => any, options?: boolean | AddEventListenerOptions): void; addEventListener (event: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void { - mono_log_debug(`mock ${this.engine.ident} client added listener for ${event}`); + mono_log_debug(() => `mock ${this.engine.ident} client added listener for ${event}`); this.engine.eventTarget.addEventListener(event, listener, options); } removeEventListener (event: string, listener: EventListenerOrEventListenerObject): void { - mono_log_debug(`mock ${this.engine.ident} client removed listener for ${event}`); + mono_log_debug(() => `mock ${this.engine.ident} client removed listener for ${event}`); this.engine.eventTarget.removeEventListener(event, listener); } close (): void { - mono_log_debug(`mock ${this.engine.ident} client closed`); + mono_log_debug(() => `mock ${this.engine.ident} client closed`); this.engine.mockReplyEventTarget.dispatchEvent(new CloseEvent("close")); } dispatchEvent (ev: Event): boolean { @@ -73,7 +73,7 @@ export function mock (script: MockScript): Mock { } reply (data: ArrayBuffer | Uint8Array) { - mono_log_debug(`mock ${this.ident} reply:`, data); + mono_log_debug(() => `mock ${this.ident} reply:${data}`); let sendData: ArrayBuffer; if (typeof data === "object" && data instanceof ArrayBuffer) { sendData = new ArrayBuffer(data.byteLength); @@ -92,7 +92,7 @@ export function mock (script: MockScript): Mock { } processSend (onMessage: (data: ArrayBuffer) => any): Promise { - mono_log_debug(`mock ${this.ident} processSend`); + mono_log_debug(() => `mock ${this.ident} processSend`); return new Promise((resolve, reject) => { this.mockReplyEventTarget.addEventListener("close", () => { @@ -105,7 +105,7 @@ export function mock (script: MockScript): Mock { reject(new Error("mock script connection received string data")); } - mono_log_debug(`mock ${this.ident} processSend got:`, data.byteLength); + mono_log_debug(() => `mock ${this.ident} processSend got: ${data.byteLength}`); onMessage(data); }); @@ -113,7 +113,7 @@ export function mock (script: MockScript): Mock { } async waitForSend (filter: (data: ArrayBuffer) => boolean, extract?: (data: ArrayBuffer) => T): Promise { - mono_log_debug(`mock ${this.ident} waitForSend`); + mono_log_debug(() => `mock ${this.ident} waitForSend`); const data = await new Promise((resolve) => { this.mockReplyEventTarget.addEventListener("message", (event: any) => { @@ -122,7 +122,7 @@ export function mock (script: MockScript): Mock { mono_log_warn(`mock ${this.ident} waitForSend got string:`, data); throw new Error("mock script connection received string data"); } - mono_log_debug(`mock ${this.ident} waitForSend got:`, data.byteLength); + mono_log_debug(() => `mock ${this.ident} waitForSend got:${data.byteLength}`); resolve(data); }, { once: true }); @@ -153,7 +153,7 @@ export function mock (script: MockScript): Mock { } open (): MockRemoteSocket { const i = this.openCount++; - mono_log_debug(`mock ${i} open`); + mono_log_debug(() => `mock ${i} open`); return this.engines[i].socket; } diff --git a/src/mono/browser/runtime/diagnostics/server_pthread/index.ts b/src/mono/browser/runtime/diagnostics/server_pthread/index.ts index cbc94347a7d2..1175aeb2d8c5 100644 --- a/src/mono/browser/runtime/diagnostics/server_pthread/index.ts +++ b/src/mono/browser/runtime/diagnostics/server_pthread/index.ts @@ -139,12 +139,12 @@ class DiagnosticServerImpl implements DiagnosticServer { async advertiseAndWaitForClient (): Promise { try { const connNum = this.openCount++; - mono_log_debug("opening websocket and sending ADVR_V1", connNum); + mono_log_debug(() => `opening websocket and sending ADVR_V1 ${connNum}`); const ws = await this.openSocket(); const p = addOneShotProtocolCommandEventListener(createProtocolSocket(ws)); this.sendAdvertise(ws); const message = await p; - mono_log_debug("received advertising response: ", message, connNum); + mono_log_debug(() => `received advertising response: ${message},${connNum}`); queueMicrotask(() => this.parseAndDispatchMessage(ws, connNum, message)); } finally { // if there were errors, resume the runtime anyway @@ -183,9 +183,9 @@ class DiagnosticServerImpl implements DiagnosticServer { } parseCommand (message: ProtocolCommandEvent, connNum: number): ProtocolClientCommandBase | null { - mono_log_debug("parsing byte command: ", message.data, connNum); + mono_log_debug(() => `parsing byte command: ${message.data}, ${connNum}`); const result = parseProtocolCommand(message.data); - mono_log_debug("parsed byte command: ", result, connNum); + mono_log_debug(() => `parsed byte command: ${result} ${connNum}`); if (result.success) { return result.result; } else { @@ -236,7 +236,7 @@ class DiagnosticServerImpl implements DiagnosticServer { } async stopEventPipe (ws: WebSocket | MockRemoteSocket, sessionID: EventPipeSessionIDImpl): Promise { - mono_log_debug("stopEventPipe", sessionID); + mono_log_debug(() => `stopEventPipe ${sessionID}`); cwraps.mono_wasm_event_pipe_session_disable(sessionID); // we might send OK before the session is actually stopped since the websocket is async // but the client end should be robust to that. @@ -252,7 +252,7 @@ class DiagnosticServerImpl implements DiagnosticServer { sessionIDbuf[3] = (session.sessionID >> 24) & 0xFF; // sessionIDbuf[4..7] is 0 because all our session IDs are 32-bit this.postClientReplyOK(ws, sessionIDbuf); - mono_log_debug("created session, now streaming: ", session); + mono_log_debug(() => `created session, now streaming: ${session}`); cwraps.mono_wasm_event_pipe_session_start_streaming(session.sessionID); } @@ -291,7 +291,7 @@ function parseProtocolCommand (data: ArrayBuffer | BinaryProtocolCommand): Parse export function mono_wasm_diagnostic_server_on_server_thread_created (websocketUrlPtr: CharPtr): void { mono_assert(WasmEnableThreads, "The diagnostic server requires threads to be enabled during build time."); const websocketUrl = utf8ToString(websocketUrlPtr); - mono_log_debug(`mono_wasm_diagnostic_server_on_server_thread_created, url ${websocketUrl}`); + mono_log_debug(() => `mono_wasm_diagnostic_server_on_server_thread_created, url ${websocketUrl}`); let mock: PromiseAndController | undefined = undefined; if (monoDiagnosticsMock && websocketUrl.startsWith("mock:")) { mock = createPromiseController(); diff --git a/src/mono/browser/runtime/diagnostics/server_pthread/protocol-socket.ts b/src/mono/browser/runtime/diagnostics/server_pthread/protocol-socket.ts index 049d1525cd32..9b6cea2bc060 100644 --- a/src/mono/browser/runtime/diagnostics/server_pthread/protocol-socket.ts +++ b/src/mono/browser/runtime/diagnostics/server_pthread/protocol-socket.ts @@ -74,7 +74,7 @@ class StatefulParser { result = this.tryAppendBuffer(new Uint8Array(buf)); } if (result.success) { - mono_log_debug("protocol-socket: got result", result); + mono_log_debug(() => `protocol-socket: got result ${result}`); this.setState(result.newState); if (result.command) { const command = result.command; @@ -177,14 +177,14 @@ class ProtocolSocketImpl implements ProtocolSocket { onMessage (this: ProtocolSocketImpl, ev: MessageEvent): void { const data = ev.data; - mono_log_debug("protocol socket received message", ev.data); + mono_log_debug(() => `protocol socket received message ${ev.data}`); if (typeof data === "object" && data instanceof ArrayBuffer) { this.onArrayBuffer(data); } else if (typeof data === "object" && data instanceof Blob) { data.arrayBuffer().then(this.onArrayBuffer.bind(this)); } else if (typeof data === "string") { // otherwise it's string, ignore it. - mono_log_debug("protocol socket received string message; ignoring it", ev.data); + mono_log_debug(() => `protocol socket received string message; ignoring it ${ev.data}`); } else { assertNever(data); } @@ -195,15 +195,15 @@ class ProtocolSocketImpl implements ProtocolSocket { } onArrayBuffer (this: ProtocolSocketImpl, buf: ArrayBuffer) { - mono_log_debug("protocol-socket: parsing array buffer", buf); + mono_log_debug(() => `protocol-socket: parsing array buffer ${buf}`); this.statefulParser.receiveBuffer(buf); } // called by the stateful parser when it has a complete command emitCommandCallback (this: this, command: BinaryProtocolCommand): void { - mono_log_debug("protocol-socket: queueing command", command); + mono_log_debug(() => `protocol-socket: queueing command ${command}`); queueMicrotask(() => { - mono_log_debug("dispatching protocol event with command", command); + mono_log_debug(() => `dispatching protocol event with command ${command}`); this.dispatchProtocolCommandEvent(command); }); } diff --git a/src/mono/browser/runtime/diagnostics/server_pthread/socket-connection.ts b/src/mono/browser/runtime/diagnostics/server_pthread/socket-connection.ts index fec4a1fc32aa..bdecd140999c 100644 --- a/src/mono/browser/runtime/diagnostics/server_pthread/socket-connection.ts +++ b/src/mono/browser/runtime/diagnostics/server_pthread/socket-connection.ts @@ -100,7 +100,7 @@ export class EventPipeSocketConnection { } private _onError (event: Event) { - mono_log_debug("EventPipe session stream websocket error", event); + mono_log_debug(() => `EventPipe session stream websocket error ${event}`); this._state = ListenerState.Error; this.stream.close(); // TODO: notify runtime that connection had an error diff --git a/src/mono/browser/runtime/dotnet.d.ts b/src/mono/browser/runtime/dotnet.d.ts index e0d644558b46..484d5dad3b76 100644 --- a/src/mono/browser/runtime/dotnet.d.ts +++ b/src/mono/browser/runtime/dotnet.d.ts @@ -20,6 +20,7 @@ declare interface Int32Ptr extends NativePointer { declare interface EmscriptenModule { _malloc(size: number): VoidPtr; _free(ptr: VoidPtr): void; + _sbrk(size: number): VoidPtr; out(message: string): void; err(message: string): void; ccall(ident: string, returnType?: string | null, argTypes?: string[], args?: any[], opts?: any): T; @@ -31,6 +32,7 @@ declare interface EmscriptenModule { UTF8ToString(ptr: CharPtr, maxBytesToRead?: number): string; UTF8ArrayToString(u8Array: Uint8Array, idx?: number, maxBytesToRead?: number): string; stringToUTF8Array(str: string, heap: Uint8Array, outIdx: number, maxBytesToWrite: number): void; + lengthBytesUTF8(str: string): number; FS_createPath(parent: string, path: string, canRead?: boolean, canWrite?: boolean): string; FS_createDataFile(parent: string, name: string, data: TypedArray, canRead: boolean, canWrite: boolean, canOwn?: boolean): string; addFunction(fn: Function, signature: string): number; @@ -194,10 +196,6 @@ type MonoConfig = { * number of unused workers kept in the emscripten pthread pool after startup */ pthreadPoolUnusedSize?: number; - /** - * Delay in milliseconds before starting the finalizer thread - */ - finalizerThreadStartDelayMs?: number; /** * If true, a list of the methods optimized by the interpreter will be saved and used for faster startup * on future runs of the application @@ -245,10 +243,13 @@ type ResourceExtensions = { }; interface ResourceGroups { hash?: string; + coreAssembly?: ResourceList; assembly?: ResourceList; lazyAssembly?: ResourceList; + corePdb?: ResourceList; pdb?: ResourceList; jsModuleWorker?: ResourceList; + jsModuleGlobalization?: ResourceList; jsModuleNative: ResourceList; jsModuleRuntime: ResourceList; wasmSymbols?: ResourceList; @@ -260,6 +261,9 @@ interface ResourceGroups { modulesAfterConfigLoaded?: ResourceList; modulesAfterRuntimeReady?: ResourceList; extensions?: ResourceExtensions; + coreVfs?: { + [virtualPath: string]: ResourceList; + }; vfs?: { [virtualPath: string]: ResourceList; }; @@ -357,6 +361,10 @@ type SingleAssetBehaviors = * The javascript module for emscripten. */ | "js-module-native" +/** + * The javascript module for hybrid globalization. + */ + | "js-module-globalization" /** * Typically blazor.boot.json */ diff --git a/src/mono/browser/runtime/driver.c b/src/mono/browser/runtime/driver.c index f231a86119e7..1b3663e4f3f3 100644 --- a/src/mono/browser/runtime/driver.c +++ b/src/mono/browser/runtime/driver.c @@ -347,12 +347,6 @@ mono_wasm_exit (int exit_code) emscripten_force_exit (exit_code); } -EMSCRIPTEN_KEEPALIVE int -mono_wasm_abort () -{ - abort (); -} - EMSCRIPTEN_KEEPALIVE void mono_wasm_set_main_args (int argc, char* argv[]) { @@ -441,9 +435,7 @@ mono_wasm_init_finalizer_thread (void) { // in the single threaded build, finalizers periodically run on the main thread instead. #ifndef DISABLE_THREADS - MONO_ENTER_GC_UNSAFE; mono_gc_init_finalizer_thread (); - MONO_EXIT_GC_UNSAFE; #endif } diff --git a/src/mono/browser/runtime/es6/dotnet.es6.lib.js b/src/mono/browser/runtime/es6/dotnet.es6.lib.js index cc1944eeed98..69b6c31376f9 100644 --- a/src/mono/browser/runtime/es6/dotnet.es6.lib.js +++ b/src/mono/browser/runtime/es6/dotnet.es6.lib.js @@ -76,6 +76,8 @@ function createWasmImportStubsFrom(collection) { // we will replace them with the real implementation in replace_linker_placeholders function injectDependencies() { createWasmImportStubsFrom(methodIndexByName.mono_wasm_imports); + // mono_wasm_hybrid_globalization_imports is empty in non-hybrid globalization mode + createWasmImportStubsFrom(methodIndexByName.mono_wasm_hybrid_globalization_imports); #if USE_PTHREADS createWasmImportStubsFrom(methodIndexByName.mono_wasm_threads_imports); diff --git a/src/mono/browser/runtime/exports-binding.ts b/src/mono/browser/runtime/exports-binding.ts index f5420a3a729e..6ae7a08b95b0 100644 --- a/src/mono/browser/runtime/exports-binding.ts +++ b/src/mono/browser/runtime/exports-binding.ts @@ -17,12 +17,6 @@ import { mono_wasm_diagnostic_server_on_runtime_server_init, mono_wasm_event_pip import { mono_wasm_diagnostic_server_stream_signal_work_available } from "./diagnostics/server_pthread/stream-queue"; import { mono_log_warn, mono_wasm_console_clear, mono_wasm_trace_logger } from "./logging"; import { mono_wasm_profiler_leave, mono_wasm_profiler_enter } from "./profiler"; -import { mono_wasm_change_case, mono_wasm_change_case_invariant } from "./hybrid-globalization/change-case"; -import { mono_wasm_compare_string, mono_wasm_ends_with, mono_wasm_starts_with, mono_wasm_index_of } from "./hybrid-globalization/collations"; -import { mono_wasm_get_calendar_info } from "./hybrid-globalization/calendar"; - -import { mono_wasm_get_culture_info } from "./hybrid-globalization/culture-info"; -import { mono_wasm_get_locale_info, mono_wasm_get_first_day_of_week, mono_wasm_get_first_week_of_year } from "./hybrid-globalization/locales"; import { mono_wasm_browser_entropy } from "./crypto"; import { mono_wasm_cancel_promise } from "./cancelable-promise"; @@ -33,6 +27,7 @@ import { } from "./pthreads"; import { mono_wasm_dump_threads } from "./pthreads/ui-thread"; import { mono_wasm_schedule_synchronization_context } from "./pthreads/shared"; +import { mono_wasm_hybrid_globalization_imports } from "./globalization"; // the JS methods would be visible to EMCC linker and become imports of the WASM module @@ -101,23 +96,15 @@ export const mono_wasm_imports = [ mono_wasm_invoke_jsimport_ST, mono_wasm_resolve_or_reject_promise, mono_wasm_cancel_promise, - mono_wasm_change_case_invariant, - mono_wasm_change_case, - mono_wasm_compare_string, - mono_wasm_starts_with, - mono_wasm_ends_with, - mono_wasm_index_of, - mono_wasm_get_calendar_info, - mono_wasm_get_culture_info, - mono_wasm_get_locale_info, - mono_wasm_get_first_day_of_week, - mono_wasm_get_first_week_of_year, ]; + const wasmImports: Function[] = [ ...mono_wasm_imports, // threading exports, if threading is enabled ...mono_wasm_threads_imports, + // hybrid globalization exports + ...mono_wasm_hybrid_globalization_imports, ]; export function replace_linker_placeholders (imports: WebAssembly.Imports) { diff --git a/src/mono/browser/runtime/exports-linker.ts b/src/mono/browser/runtime/exports-linker.ts index b1d5c0234f56..3e1f8c4bd99c 100644 --- a/src/mono/browser/runtime/exports-linker.ts +++ b/src/mono/browser/runtime/exports-linker.ts @@ -3,11 +3,13 @@ import { mono_wasm_imports, mono_wasm_threads_imports } from "./exports-binding"; import gitHash from "consts:gitHash"; +import { mono_wasm_hybrid_globalization_imports } from "./globalization"; export function export_linker_indexes_as_code (): string { const indexByName: any = { mono_wasm_imports: {}, mono_wasm_threads_imports: {}, + mono_wasm_hybrid_globalization_imports: {}, }; let idx = 0; for (const wi of mono_wasm_imports) { @@ -18,6 +20,10 @@ export function export_linker_indexes_as_code (): string { indexByName.mono_wasm_threads_imports[wi.name] = idx; idx++; } + for (const wi of mono_wasm_hybrid_globalization_imports) { + indexByName.mono_wasm_hybrid_globalization_imports[wi.name] = idx; + idx++; + } return ` var gitHash = "${gitHash}"; var methodIndexByName = ${JSON.stringify(indexByName, null, 2)}; diff --git a/src/mono/browser/runtime/exports.ts b/src/mono/browser/runtime/exports.ts index d26e3c8b57ce..6c2b1fd10659 100644 --- a/src/mono/browser/runtime/exports.ts +++ b/src/mono/browser/runtime/exports.ts @@ -7,7 +7,7 @@ import WasmEnableThreads from "consts:wasmEnableThreads"; import WasmEnableSIMD from "consts:wasmEnableSIMD"; import WasmEnableExceptionHandling from "consts:wasmEnableExceptionHandling"; -import type { RuntimeAPI } from "./types"; +import { GlobalizationMode, type RuntimeAPI } from "./types"; import { Module, exportedRuntimeAPI, loaderHelpers, passEmscriptenInternals, runtimeHelpers, setRuntimeGlobals, } from "./globals"; import { GlobalObjects, RuntimeHelpers } from "./types/internal"; @@ -24,6 +24,10 @@ import { jiterpreter_dump_stats } from "./jiterpreter"; import { forceDisposeProxies } from "./gc-handles"; import { mono_wasm_dump_threads } from "./pthreads"; +import { threads_c_functions as tcwraps } from "./cwraps"; +import { stringToUTF16, stringToUTF16Ptr, utf16ToString, utf16ToStringLoop } from "./strings"; +import { localHeapViewU16, setI32, setU16_local } from "./memory"; + export let runtimeList: RuntimeList; function initializeExports (globalObjects: GlobalObjects): RuntimeAPI { @@ -43,7 +47,18 @@ function initializeExports (globalObjects: GlobalObjects): RuntimeAPI { }; if (WasmEnableThreads) { rh.dumpThreads = mono_wasm_dump_threads; + rh.mono_wasm_print_thread_dump = () => tcwraps.mono_wasm_print_thread_dump(); + } + if (loaderHelpers.config.globalizationMode === GlobalizationMode.Hybrid) { + rh.stringToUTF16 = stringToUTF16; + rh.stringToUTF16Ptr = stringToUTF16Ptr; + rh.utf16ToString = utf16ToString; + rh.utf16ToStringLoop = utf16ToStringLoop; + rh.localHeapViewU16 = localHeapViewU16; + rh.setU16_local = setU16_local; + rh.setI32 = setI32; } + Object.assign(runtimeHelpers, rh); const API = export_api(); diff --git a/src/mono/browser/runtime/globalization-stubs.ts b/src/mono/browser/runtime/globalization-stubs.ts new file mode 100644 index 000000000000..5544c3123d2b --- /dev/null +++ b/src/mono/browser/runtime/globalization-stubs.ts @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +import { globalizationHelpers } from "./globals"; +import { Int32Ptr, VoidPtr } from "./types/emscripten"; +import { VoidPtrNull } from "./types/internal"; + + +export function mono_wasm_change_case_invariant (src: number, srcLength: number, dst: number, dstLength: number, toUpper: number) : VoidPtr { + if (typeof globalizationHelpers.mono_wasm_change_case_invariant === "function") { + return globalizationHelpers.mono_wasm_change_case_invariant(src, srcLength, dst, dstLength, toUpper); + } + return VoidPtrNull; +} + +export function mono_wasm_change_case (culture: number, cultureLength: number, src: number, srcLength: number, dst: number, dstLength: number, toUpper: number) : VoidPtr { + if (typeof globalizationHelpers.mono_wasm_change_case === "function") { + return globalizationHelpers.mono_wasm_change_case(culture, cultureLength, src, srcLength, dst, dstLength, toUpper); + } + return VoidPtrNull; +} + +export function mono_wasm_compare_string (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr) : VoidPtr { + if (typeof globalizationHelpers.mono_wasm_compare_string === "function") { + return globalizationHelpers.mono_wasm_compare_string(culture, cultureLength, str1, str1Length, str2, str2Length, options, resultPtr); + } + return VoidPtrNull; +} + +export function mono_wasm_starts_with (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr): VoidPtr { + if (typeof globalizationHelpers.mono_wasm_starts_with === "function") { + return globalizationHelpers.mono_wasm_starts_with(culture, cultureLength, str1, str1Length, str2, str2Length, options, resultPtr); + } + return VoidPtrNull; +} + +export function mono_wasm_ends_with (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr): VoidPtr { + if (typeof globalizationHelpers.mono_wasm_ends_with === "function") { + return globalizationHelpers.mono_wasm_ends_with(culture, cultureLength, str1, str1Length, str2, str2Length, options, resultPtr); + } + return VoidPtrNull; +} + +export function mono_wasm_index_of (culture: number, cultureLength: number, needlePtr: number, needleLength: number, srcPtr: number, srcLength: number, options: number, fromBeginning: number, resultPtr: Int32Ptr): VoidPtr { + if (typeof globalizationHelpers.mono_wasm_index_of === "function") { + return globalizationHelpers.mono_wasm_index_of(culture, cultureLength, needlePtr, needleLength, srcPtr, srcLength, options, fromBeginning, resultPtr); + } + return VoidPtrNull; +} + +export function mono_wasm_get_calendar_info (culture: number, cultureLength: number, calendarId: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr): VoidPtr { + if (typeof globalizationHelpers.mono_wasm_get_calendar_info === "function") { + return globalizationHelpers.mono_wasm_get_calendar_info(culture, cultureLength, calendarId, dst, dstMaxLength, dstLength); + } + return VoidPtrNull; +} + +export function mono_wasm_get_culture_info (culture: number, cultureLength: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr): VoidPtr { + if (typeof globalizationHelpers.mono_wasm_get_culture_info === "function") { + return globalizationHelpers.mono_wasm_get_culture_info(culture, cultureLength, dst, dstMaxLength, dstLength); + } + return VoidPtrNull; +} + +export function mono_wasm_get_first_day_of_week (culture: number, cultureLength: number, resultPtr: Int32Ptr): VoidPtr { + if (typeof globalizationHelpers.mono_wasm_get_first_day_of_week === "function") { + return globalizationHelpers.mono_wasm_get_first_day_of_week(culture, cultureLength, resultPtr); + } + return VoidPtrNull; +} + +export function mono_wasm_get_first_week_of_year (culture: number, cultureLength: number, resultPtr: Int32Ptr): VoidPtr { + if (typeof globalizationHelpers.mono_wasm_get_first_week_of_year === "function") { + return globalizationHelpers.mono_wasm_get_first_week_of_year(culture, cultureLength, resultPtr); + } + return VoidPtrNull; +} diff --git a/src/mono/browser/runtime/globalization.ts b/src/mono/browser/runtime/globalization.ts new file mode 100644 index 000000000000..95fac1192733 --- /dev/null +++ b/src/mono/browser/runtime/globalization.ts @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +import { mono_wasm_change_case, mono_wasm_change_case_invariant, mono_wasm_compare_string, mono_wasm_ends_with, mono_wasm_get_calendar_info, mono_wasm_get_culture_info, mono_wasm_get_first_day_of_week, mono_wasm_get_first_week_of_year, mono_wasm_index_of, mono_wasm_starts_with } from "./globalization-stubs"; +import { mono_wasm_get_locale_info } from "./locales-common"; + +export const mono_wasm_hybrid_globalization_imports = [ + mono_wasm_change_case_invariant, + mono_wasm_change_case, + mono_wasm_compare_string, + mono_wasm_starts_with, + mono_wasm_ends_with, + mono_wasm_index_of, + mono_wasm_get_calendar_info, + mono_wasm_get_culture_info, + mono_wasm_get_first_day_of_week, + mono_wasm_get_first_week_of_year, + // used by both: non-HG and HG: + mono_wasm_get_locale_info, +]; diff --git a/src/mono/browser/runtime/globals.ts b/src/mono/browser/runtime/globals.ts index 047fcb60c950..f6b8aa1f548f 100644 --- a/src/mono/browser/runtime/globals.ts +++ b/src/mono/browser/runtime/globals.ts @@ -9,7 +9,7 @@ import gitHash from "consts:gitHash"; import { RuntimeAPI } from "./types/index"; -import type { GlobalObjects, EmscriptenInternals, RuntimeHelpers, LoaderHelpers, DotnetModuleInternal, PromiseAndController, EmscriptenBuildOptions, GCHandle } from "./types/internal"; +import type { GlobalObjects, EmscriptenInternals, RuntimeHelpers, LoaderHelpers, DotnetModuleInternal, PromiseAndController, EmscriptenBuildOptions, GCHandle, GlobalizationHelpers } from "./types/internal"; import { mono_log_error } from "./logging"; // these are our public API (except internal) @@ -29,6 +29,7 @@ export let ENVIRONMENT_IS_PTHREAD: boolean; export let exportedRuntimeAPI: RuntimeAPI = null as any; export let runtimeHelpers: RuntimeHelpers = null as any; export let loaderHelpers: LoaderHelpers = null as any; +export let globalizationHelpers: GlobalizationHelpers = null as any; export let _runtimeModuleLoaded = false; // please keep it in place also as rollup guard @@ -53,10 +54,12 @@ export function setRuntimeGlobals (globalObjects: GlobalObjects) { INTERNAL = globalObjects.internal; runtimeHelpers = globalObjects.runtimeHelpers; loaderHelpers = globalObjects.loaderHelpers; + globalizationHelpers = globalObjects.globalizationHelpers; exportedRuntimeAPI = globalObjects.api; const rh: Partial = { gitHash, + coreAssetsInMemory: createPromiseController(), allAssetsInMemory: createPromiseController(), dotnetReady: createPromiseController(), afterInstantiateWasm: createPromiseController(), @@ -64,7 +67,8 @@ export function setRuntimeGlobals (globalObjects: GlobalObjects) { afterPreInit: createPromiseController(), afterPreRun: createPromiseController(), beforeOnRuntimeInitialized: createPromiseController(), - afterMonoStarted: createPromiseController(), + afterMonoStarted: createPromiseController(), + afterDeputyReady: createPromiseController(), afterIOStarted: createPromiseController(), afterOnRuntimeInitialized: createPromiseController(), afterPostRun: createPromiseController(), diff --git a/src/mono/browser/runtime/hybrid-globalization/calendar.ts b/src/mono/browser/runtime/hybrid-globalization/calendar.ts index d3944f514ce8..dccb97820f1f 100644 --- a/src/mono/browser/runtime/hybrid-globalization/calendar.ts +++ b/src/mono/browser/runtime/hybrid-globalization/calendar.ts @@ -2,11 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. /* eslint-disable no-inner-declarations */ -import { mono_wasm_new_external_root } from "../roots"; -import { monoStringToString, stringToUTF16 } from "../strings"; -import { MonoObject, MonoObjectRef, MonoString, MonoStringRef } from "../types/internal"; -import { Int32Ptr } from "../types/emscripten"; -import { wrap_error_root, wrap_no_error_root } from "./helpers"; +import { VoidPtrNull } from "../types/internal"; +import { runtimeHelpers } from "./module-exports"; +import { Int32Ptr, VoidPtr } from "../types/emscripten"; import { INNER_SEPARATOR, OUTER_SEPARATOR, normalizeSpaces } from "./helpers"; const MONTH_CODE = "MMMM"; @@ -14,11 +12,9 @@ const YEAR_CODE = "yyyy"; const DAY_CODE = "d"; // this function joins all calendar info with OUTER_SEPARATOR into one string and returns it back to managed code -export function mono_wasm_get_calendar_info (culture: MonoStringRef, calendarId: number, dst: number, dstLength: number, isException: Int32Ptr, exAddress: MonoObjectRef): number { - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(exAddress); +export function mono_wasm_get_calendar_info (culture: number, cultureLength: number, calendarId: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = runtimeHelpers.utf16ToString(culture, (culture + 2 * cultureLength)); const locale = cultureName ? cultureName : undefined; const calendarInfo = { EnglishName: "", @@ -56,18 +52,14 @@ export function mono_wasm_get_calendar_info (culture: MonoStringRef, calendarId: calendarInfo.AbbreviatedEraNames = eraNames.abbreviatedEraNames; const result = Object.values(calendarInfo).join(OUTER_SEPARATOR); - if (result.length > dstLength) { - throw new Error(`Calendar info exceeds length of ${dstLength}.`); + if (result.length > dstMaxLength) { + throw new Error(`Calendar info exceeds length of ${dstMaxLength}.`); } - stringToUTF16(dst, dst + 2 * result.length, result); - wrap_no_error_root(isException, exceptionRoot); - return result.length; + runtimeHelpers.stringToUTF16(dst, dst + 2 * result.length, result); + runtimeHelpers.setI32(dstLength, result.length); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(isException, ex, exceptionRoot); - return -1; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + return runtimeHelpers.stringToUTF16Ptr(ex.toString()); } } diff --git a/src/mono/browser/runtime/hybrid-globalization/change-case.ts b/src/mono/browser/runtime/hybrid-globalization/change-case.ts index 762eacc94c26..c5b1a425ac0f 100644 --- a/src/mono/browser/runtime/hybrid-globalization/change-case.ts +++ b/src/mono/browser/runtime/hybrid-globalization/change-case.ts @@ -1,29 +1,24 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { mono_wasm_new_external_root } from "../roots"; -import { monoStringToString, utf16ToStringLoop, stringToUTF16 } from "../strings"; -import { MonoObject, MonoObjectRef, MonoString, MonoStringRef } from "../types/internal"; -import { Int32Ptr } from "../types/emscripten"; -import { wrap_error_root, wrap_no_error_root } from "./helpers"; -import { localHeapViewU16, setU16_local } from "../memory"; +import { VoidPtrNull } from "../types/internal"; +import { runtimeHelpers } from "./module-exports"; +import { VoidPtr } from "../types/emscripten"; import { isSurrogate } from "./helpers"; -export function mono_wasm_change_case_invariant (src: number, srcLength: number, dst: number, dstLength: number, toUpper: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): void { - const exceptionRoot = mono_wasm_new_external_root(ex_address); +export function mono_wasm_change_case_invariant (src: number, srcLength: number, dst: number, dstLength: number, toUpper: number): VoidPtr { try { - const input = utf16ToStringLoop(src, src + 2 * srcLength); + const input = runtimeHelpers.utf16ToStringLoop(src, src + 2 * srcLength); const result = toUpper ? input.toUpperCase() : input.toLowerCase(); // Unicode defines some codepoints which expand into multiple codepoints, // originally we do not support this expansion if (result.length <= dstLength) { - stringToUTF16(dst, dst + 2 * dstLength, result); - wrap_no_error_root(is_exception, exceptionRoot); - return; + runtimeHelpers.stringToUTF16(dst, dst + 2 * dstLength, result); + return VoidPtrNull; } // workaround to maintain the ICU-like behavior - const heapI16 = localHeapViewU16(); + const heapI16 = runtimeHelpers.localHeapViewU16(); let jump = 1; if (toUpper) { for (let i = 0; i < input.length; i += jump) { @@ -39,7 +34,7 @@ export function mono_wasm_change_case_invariant (src: number, srcLength: number, jump = 1; const upperChar = input[i].toUpperCase(); const appendedChar = upperChar.length > 1 ? input[i] : upperChar; - setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0)); + runtimeHelpers.setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0)); } } } else { @@ -55,35 +50,30 @@ export function mono_wasm_change_case_invariant (src: number, srcLength: number, jump = 1; const upperChar = input[i].toLowerCase(); const appendedChar = upperChar.length > 1 ? input[i] : upperChar; - setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0)); + runtimeHelpers.setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0)); } } } - wrap_no_error_root(is_exception, exceptionRoot); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(is_exception, ex, exceptionRoot); - } finally { - exceptionRoot.release(); + return runtimeHelpers.stringToUTF16Ptr(ex.toString()); } } -export function mono_wasm_change_case (culture: MonoStringRef, src: number, srcLength: number, dst: number, dstLength: number, toUpper: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): void { - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(ex_address); +export function mono_wasm_change_case (culture: number, cultureLength: number, src: number, srcLength: number, dst: number, dstLength: number, toUpper: number): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = runtimeHelpers.utf16ToString(culture, (culture + 2 * cultureLength)); if (!cultureName) throw new Error("Cannot change case, the culture name is null."); - const input = utf16ToStringLoop(src, src + 2 * srcLength); + const input = runtimeHelpers.utf16ToStringLoop(src, src + 2 * srcLength); const result = toUpper ? input.toLocaleUpperCase(cultureName) : input.toLocaleLowerCase(cultureName); if (result.length <= input.length) { - stringToUTF16(dst, dst + 2 * dstLength, result); - wrap_no_error_root(is_exception, exceptionRoot); - return; + runtimeHelpers.stringToUTF16(dst, dst + 2 * dstLength, result); + return VoidPtrNull; } // workaround to maintain the ICU-like behavior - const heapI16 = localHeapViewU16(); + const heapI16 = runtimeHelpers.localHeapViewU16(); let jump = 1; if (toUpper) { for (let i = 0; i < input.length; i += jump) { @@ -99,7 +89,7 @@ export function mono_wasm_change_case (culture: MonoStringRef, src: number, srcL jump = 1; const upperChar = input[i].toLocaleUpperCase(cultureName); const appendedChar = upperChar.length > 1 ? input[i] : upperChar; - setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0)); + runtimeHelpers.setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0)); } } } else { @@ -115,20 +105,17 @@ export function mono_wasm_change_case (culture: MonoStringRef, src: number, srcL jump = 1; const lowerChar = input[i].toLocaleLowerCase(cultureName); const appendedChar = lowerChar.length > 1 ? input[i] : lowerChar; - setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0)); + runtimeHelpers.setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0)); } } } - wrap_no_error_root(is_exception, exceptionRoot); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(is_exception, ex, exceptionRoot); - } finally { - cultureRoot.release(); - exceptionRoot.release(); + return runtimeHelpers.stringToUTF16Ptr(ex.toString()); } } function appendSurrogateToMemory (heapI16: Uint16Array, dst: number, surrogate: string, idx: number) { - setU16_local(heapI16, dst + idx * 2, surrogate.charCodeAt(0)); - setU16_local(heapI16, dst + (idx + 1) * 2, surrogate.charCodeAt(1)); + runtimeHelpers.setU16_local(heapI16, dst + idx * 2, surrogate.charCodeAt(0)); + runtimeHelpers.setU16_local(heapI16, dst + (idx + 1) * 2, surrogate.charCodeAt(1)); } diff --git a/src/mono/browser/runtime/hybrid-globalization/collations.ts b/src/mono/browser/runtime/hybrid-globalization/collations.ts index 523f63307e27..6b30ded537df 100644 --- a/src/mono/browser/runtime/hybrid-globalization/collations.ts +++ b/src/mono/browser/runtime/hybrid-globalization/collations.ts @@ -1,113 +1,105 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { mono_wasm_new_external_root } from "../roots"; -import { monoStringToString, utf16ToString } from "../strings"; -import { MonoObject, MonoObjectRef, MonoString, MonoStringRef } from "../types/internal"; -import { Int32Ptr } from "../types/emscripten"; -import { wrap_error_root, wrap_no_error_root } from "./helpers"; +import { VoidPtrNull } from "../types/internal"; +import { runtimeHelpers } from "./module-exports"; +import { Int32Ptr, VoidPtr } from "../types/emscripten"; import { GraphemeSegmenter } from "./grapheme-segmenter"; const COMPARISON_ERROR = -2; const INDEXING_ERROR = -1; let graphemeSegmenterCached: GraphemeSegmenter | null; -export function mono_wasm_compare_string (culture: MonoStringRef, str1: number, str1Length: number, str2: number, str2Length: number, options: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): number { - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(ex_address); +export function mono_wasm_compare_string (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); - const string1 = utf16ToString(str1, (str1 + 2 * str1Length)); - const string2 = utf16ToString(str2, (str2 + 2 * str2Length)); + const cultureName = runtimeHelpers.utf16ToString(culture, (culture + 2 * cultureLength)); + const string1 = runtimeHelpers.utf16ToString(str1, (str1 + 2 * str1Length)); + const string2 = runtimeHelpers.utf16ToString(str2, (str2 + 2 * str2Length)); const casePicker = (options & 0x1f); const locale = cultureName ? cultureName : undefined; - wrap_no_error_root(is_exception, exceptionRoot); - return compareStrings(string1, string2, locale, casePicker); + const result = compareStrings(string1, string2, locale, casePicker); + runtimeHelpers.setI32(resultPtr, result); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(is_exception, ex, exceptionRoot); - return COMPARISON_ERROR; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + runtimeHelpers.setI32(resultPtr, COMPARISON_ERROR); + return runtimeHelpers.stringToUTF16Ptr(ex.toString()); } } -export function mono_wasm_starts_with (culture: MonoStringRef, str1: number, str1Length: number, str2: number, str2Length: number, options: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): number { - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(ex_address); +export function mono_wasm_starts_with (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = runtimeHelpers.utf16ToString(culture, (culture + 2 * cultureLength)); const prefix = decodeToCleanString(str2, str2Length); // no need to look for an empty string - if (prefix.length == 0) - return 1; // true + if (prefix.length == 0) { + runtimeHelpers.setI32(resultPtr, 1); // true + return VoidPtrNull; + } const source = decodeToCleanString(str1, str1Length); - if (source.length < prefix.length) - return 0; //false + if (source.length < prefix.length) { + runtimeHelpers.setI32(resultPtr, 0); // false + return VoidPtrNull; + } const sourceOfPrefixLength = source.slice(0, prefix.length); const casePicker = (options & 0x1f); const locale = cultureName ? cultureName : undefined; - const result = compareStrings(sourceOfPrefixLength, prefix, locale, casePicker); - wrap_no_error_root(is_exception, exceptionRoot); - return result === 0 ? 1 : 0; // equals ? true : false + const cmpResult = compareStrings(sourceOfPrefixLength, prefix, locale, casePicker); + const result = cmpResult === 0 ? 1 : 0; // equals ? true : false + runtimeHelpers.setI32(resultPtr, result); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(is_exception, ex, exceptionRoot); - return INDEXING_ERROR; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + runtimeHelpers.setI32(resultPtr, INDEXING_ERROR); + return runtimeHelpers.stringToUTF16Ptr(ex.toString()); } } -export function mono_wasm_ends_with (culture: MonoStringRef, str1: number, str1Length: number, str2: number, str2Length: number, options: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): number { - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(ex_address); +export function mono_wasm_ends_with (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = runtimeHelpers.utf16ToString(culture, (culture + 2 * cultureLength)); const suffix = decodeToCleanString(str2, str2Length); - if (suffix.length == 0) - return 1; // true + if (suffix.length == 0) { + runtimeHelpers.setI32(resultPtr, 1); // true + return VoidPtrNull; + } const source = decodeToCleanString(str1, str1Length); const diff = source.length - suffix.length; - if (diff < 0) - return 0; //false + if (diff < 0) { + runtimeHelpers.setI32(resultPtr, 0); // false + return VoidPtrNull; + } const sourceOfSuffixLength = source.slice(diff, source.length); const casePicker = (options & 0x1f); const locale = cultureName ? cultureName : undefined; - const result = compareStrings(sourceOfSuffixLength, suffix, locale, casePicker); - wrap_no_error_root(is_exception, exceptionRoot); - return result === 0 ? 1 : 0; // equals ? true : false + const cmpResult = compareStrings(sourceOfSuffixLength, suffix, locale, casePicker); + const result = cmpResult === 0 ? 1 : 0; // equals ? true : false + runtimeHelpers.setI32(resultPtr, result); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(is_exception, ex, exceptionRoot); - return INDEXING_ERROR; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + runtimeHelpers.setI32(resultPtr, INDEXING_ERROR); + return runtimeHelpers.stringToUTF16Ptr(ex.toString()); } } -export function mono_wasm_index_of (culture: MonoStringRef, needlePtr: number, needleLength: number, srcPtr: number, srcLength: number, options: number, fromBeginning: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): number { - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(ex_address); +export function mono_wasm_index_of (culture: number, cultureLength: number, needlePtr: number, needleLength: number, srcPtr: number, srcLength: number, options: number, fromBeginning: number, resultPtr: Int32Ptr): VoidPtr { try { - const needle = utf16ToString(needlePtr, (needlePtr + 2 * needleLength)); + const needle = runtimeHelpers.utf16ToString(needlePtr, (needlePtr + 2 * needleLength)); // no need to look for an empty string if (cleanString(needle).length == 0) { - wrap_no_error_root(is_exception, exceptionRoot); - return fromBeginning ? 0 : srcLength; + runtimeHelpers.setI32(resultPtr, fromBeginning ? 0 : srcLength); + return VoidPtrNull; } - const source = utf16ToString(srcPtr, (srcPtr + 2 * srcLength)); + const source = runtimeHelpers.utf16ToString(srcPtr, (srcPtr + 2 * srcLength)); // no need to look in an empty string if (cleanString(source).length == 0) { - wrap_no_error_root(is_exception, exceptionRoot); - return fromBeginning ? 0 : srcLength; + runtimeHelpers.setI32(resultPtr, fromBeginning ? 0 : srcLength); + return VoidPtrNull; } - const cultureName = monoStringToString(cultureRoot); + const cultureName = runtimeHelpers.utf16ToString(culture, (culture + 2 * cultureLength)); const locale = cultureName ? cultureName : undefined; const casePicker = (options & 0x1f); let result = -1; @@ -148,14 +140,11 @@ export function mono_wasm_index_of (culture: MonoStringRef, needlePtr: number, n break; } } - wrap_no_error_root(is_exception, exceptionRoot); - return result; + runtimeHelpers.setI32(resultPtr, result); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(is_exception, ex, exceptionRoot); - return INDEXING_ERROR; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + runtimeHelpers.setI32(resultPtr, INDEXING_ERROR); + return runtimeHelpers.stringToUTF16Ptr(ex.toString()); } function checkMatchFound (str1: string, str2: string, locale: string | undefined, casePicker: number): boolean { @@ -256,7 +245,7 @@ function compareStrings (string1: string, string2: string, locale: string | unde } function decodeToCleanString (strPtr: number, strLen: number) { - const str = utf16ToString(strPtr, (strPtr + 2 * strLen)); + const str = runtimeHelpers.utf16ToString(strPtr, (strPtr + 2 * strLen)); return cleanString(str); } diff --git a/src/mono/browser/runtime/hybrid-globalization/culture-info.ts b/src/mono/browser/runtime/hybrid-globalization/culture-info.ts index 03bebd9ec65e..aa4e3f152d0d 100644 --- a/src/mono/browser/runtime/hybrid-globalization/culture-info.ts +++ b/src/mono/browser/runtime/hybrid-globalization/culture-info.ts @@ -1,18 +1,14 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { wrap_error_root, wrap_no_error_root } from "./helpers"; -import { mono_wasm_new_external_root } from "../roots"; -import { monoStringToString, stringToUTF16 } from "../strings"; -import { Int32Ptr } from "../types/emscripten"; -import { MonoObject, MonoObjectRef, MonoString, MonoStringRef } from "../types/internal"; +import { VoidPtrNull } from "../types/internal"; +import { runtimeHelpers } from "./module-exports"; +import { Int32Ptr, VoidPtr } from "../types/emscripten"; import { OUTER_SEPARATOR, normalizeLocale, normalizeSpaces } from "./helpers"; -export function mono_wasm_get_culture_info (culture: MonoStringRef, dst: number, dstLength: number, isException: Int32Ptr, exAddress: MonoObjectRef): number { - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(exAddress); +export function mono_wasm_get_culture_info (culture: number, cultureLength: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = runtimeHelpers.utf16ToString(culture, (culture + 2 * cultureLength)); const cultureInfo = { AmDesignator: "", PmDesignator: "", @@ -26,18 +22,15 @@ export function mono_wasm_get_culture_info (culture: MonoStringRef, dst: number, cultureInfo.LongTimePattern = getLongTimePattern(canonicalLocale, designators); cultureInfo.ShortTimePattern = getShortTimePattern(cultureInfo.LongTimePattern); const result = Object.values(cultureInfo).join(OUTER_SEPARATOR); - if (result.length > dstLength) { - throw new Error(`Culture info exceeds length of ${dstLength}.`); + if (result.length > dstMaxLength) { + throw new Error(`Culture info exceeds length of ${dstMaxLength}.`); } - stringToUTF16(dst, dst + 2 * result.length, result); - wrap_no_error_root(isException, exceptionRoot); - return result.length; + runtimeHelpers.stringToUTF16(dst, dst + 2 * result.length, result); + runtimeHelpers.setI32(dstLength, result.length); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(isException, ex, exceptionRoot); - return -1; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + runtimeHelpers.setI32(dstLength, -1); + return runtimeHelpers.stringToUTF16Ptr(ex.toString()); } } diff --git a/src/mono/browser/runtime/hybrid-globalization/grapheme-segmenter.ts b/src/mono/browser/runtime/hybrid-globalization/grapheme-segmenter.ts index 83bf8619affe..251304dcc902 100644 --- a/src/mono/browser/runtime/hybrid-globalization/grapheme-segmenter.ts +++ b/src/mono/browser/runtime/hybrid-globalization/grapheme-segmenter.ts @@ -7,7 +7,6 @@ * https://github.com/formatjs/formatjs/blob/58d6a7b398d776ca3d2726d72ae1573b65cc3bef/packages/intl-segmenter/src/segmentation-utils.ts */ -import { mono_assert } from "../globals"; import { isSurrogate } from "./helpers"; type SegmentationRule = { @@ -48,7 +47,8 @@ function isSegmentationTypeRaw (obj: any): obj is SegmentationTypeRaw { } export function setSegmentationRulesFromJson (json: string) { - mono_assert(isSegmentationTypeRaw(json), "Provided grapheme segmentation rules are not valid"); + if (!isSegmentationTypeRaw(json)) + throw new Error("Provided grapheme segmentation rules are not valid"); segmentationRules = GraphemeSegmenter.prepareSegmentationRules(json); } diff --git a/src/mono/browser/runtime/hybrid-globalization/helpers.ts b/src/mono/browser/runtime/hybrid-globalization/helpers.ts index b58fc6779b25..0cd229444722 100644 --- a/src/mono/browser/runtime/hybrid-globalization/helpers.ts +++ b/src/mono/browser/runtime/hybrid-globalization/helpers.ts @@ -1,14 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import NativeAOT from "consts:nativeAOT"; - -import { normalize_exception } from "../invoke-js"; -import { receiveWorkerHeapViews, setI32_unchecked } from "../memory"; -import { stringToMonoStringRoot } from "../strings"; -import { Int32Ptr } from "../types/emscripten"; -import { MonoObject, WasmRoot } from "../types/internal"; - const SURROGATE_HIGHER_START = "\uD800"; const SURROGATE_HIGHER_END = "\uDBFF"; const SURROGATE_LOWER_START = "\uDC00"; @@ -50,32 +42,3 @@ export function isSurrogate (str: string, startIdx: number): boolean { SURROGATE_LOWER_START <= str[startIdx + 1] && str[startIdx + 1] <= SURROGATE_LOWER_END; } - -function _wrap_error_flag (is_exception: Int32Ptr | null, ex: any): string { - const res = normalize_exception(ex); - if (is_exception) { - receiveWorkerHeapViews(); - setI32_unchecked(is_exception, 1); - } - return res; -} - -export function wrap_error_root (is_exception: Int32Ptr | null, ex: any, result: WasmRoot): void { - const res = _wrap_error_flag(is_exception, ex); - if (NativeAOT) { - return; - } - stringToMonoStringRoot(res, result); -} - -// TODO replace it with replace it with UTF16 char*, no GC root needed -// https://github.com/dotnet/runtime/issues/98365 -export function wrap_no_error_root (is_exception: Int32Ptr | null, result?: WasmRoot): void { - if (is_exception) { - receiveWorkerHeapViews(); - setI32_unchecked(is_exception, 0); - } - if (result) { - result.clear(); - } -} diff --git a/src/mono/browser/runtime/hybrid-globalization/locales.ts b/src/mono/browser/runtime/hybrid-globalization/locales.ts index 252dfe1badf9..0dc4c8bcc67f 100644 --- a/src/mono/browser/runtime/hybrid-globalization/locales.ts +++ b/src/mono/browser/runtime/hybrid-globalization/locales.ts @@ -1,120 +1,34 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { wrap_error_root, wrap_no_error_root } from "./helpers"; -import { mono_wasm_new_external_root } from "../roots"; -import { monoStringToString, stringToUTF16 } from "../strings"; -import { Int32Ptr } from "../types/emscripten"; -import { MonoObject, MonoObjectRef, MonoString, MonoStringRef } from "../types/internal"; -import { OUTER_SEPARATOR, normalizeLocale } from "./helpers"; +import { VoidPtrNull } from "../types/internal"; +import { runtimeHelpers } from "./module-exports"; +import { Int32Ptr, VoidPtr } from "../types/emscripten"; +import { normalizeLocale } from "./helpers"; -export function mono_wasm_get_locale_info (culture: MonoStringRef, locale: MonoStringRef, dst: number, dstLength: number, isException: Int32Ptr, exAddress: MonoObjectRef): number { - const localeRoot = mono_wasm_new_external_root(locale), - cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(exAddress); +export function mono_wasm_get_first_day_of_week (culture: number, cultureLength: number, resultPtr: Int32Ptr): VoidPtr { try { - const localeNameOriginal = monoStringToString(localeRoot); - const localeName = normalizeLocale(localeNameOriginal); - if (!localeName && localeNameOriginal) { - // handle non-standard or malformed locales by forwarding the locale code - stringToUTF16(dst, dst + 2 * localeNameOriginal.length, localeNameOriginal); - wrap_no_error_root(isException, exceptionRoot); - return localeNameOriginal.length; - } - const cultureNameOriginal = monoStringToString(cultureRoot); - const cultureName = normalizeLocale(cultureNameOriginal); - - if (!localeName || !cultureName) - throw new Error(`Locale or culture name is null or empty. localeName=${localeName}, cultureName=${cultureName}`); - - const localeParts = localeName.split("-"); - // cultureName can be in a form of: - // 1) "language", e.g. "zh" - // 2) "language-region", e.g. "zn-CN" - // 3) "language-script-region", e.g. "zh-Hans-CN" - // 4) "language-script", e.g. "zh-Hans" (served in the catch block below) - let languageName, regionName; - try { - const region = localeParts.length > 1 ? localeParts.pop() : undefined; - // this line might fail if form 4 from the comment above is used: - regionName = region ? new Intl.DisplayNames([cultureName], { type: "region" }).of(region) : undefined; - const language = localeParts.join("-"); - languageName = new Intl.DisplayNames([cultureName], { type: "language" }).of(language); - } catch (error) { - if (error instanceof RangeError && error.message === "invalid_argument") { - // if it failed from this reason then cultureName is in a form "language-script", without region - try { - languageName = new Intl.DisplayNames([cultureName], { type: "language" }).of(localeName); - } catch (error) { - if (error instanceof RangeError && error.message === "invalid_argument" && localeNameOriginal) { - // handle non-standard or malformed locales by forwarding the locale code, e.g. "xx-u-xx" - stringToUTF16(dst, dst + 2 * localeNameOriginal.length, localeNameOriginal); - wrap_no_error_root(isException, exceptionRoot); - return localeNameOriginal.length; - } - throw error; - } - } else { - throw error; - } - } - const localeInfo = { - LanguageName: languageName, - RegionName: regionName, - }; - const result = Object.values(localeInfo).join(OUTER_SEPARATOR); - - if (!result) - throw new Error(`Locale info for locale=${localeName} is null or empty.`); - - if (result.length > dstLength) - throw new Error(`Locale info for locale=${localeName} exceeds length of ${dstLength}.`); - - stringToUTF16(dst, dst + 2 * result.length, result); - wrap_no_error_root(isException, exceptionRoot); - return result.length; - } catch (ex: any) { - wrap_error_root(isException, ex, exceptionRoot); - return -1; - } finally { - cultureRoot.release(); - exceptionRoot.release(); - } -} - -export function mono_wasm_get_first_day_of_week (culture: MonoStringRef, isException: Int32Ptr, exAddress: MonoObjectRef): number { - - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(exAddress); - try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = runtimeHelpers.utf16ToString(culture, (culture + 2 * cultureLength)); const canonicalLocale = normalizeLocale(cultureName); - wrap_no_error_root(isException, exceptionRoot); - return getFirstDayOfWeek(canonicalLocale); + const result = getFirstDayOfWeek(canonicalLocale); + runtimeHelpers.setI32(resultPtr, result); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(isException, ex, exceptionRoot); - return -1; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + runtimeHelpers.setI32(resultPtr, -1); + return runtimeHelpers.stringToUTF16Ptr(ex.toString()); } } -export function mono_wasm_get_first_week_of_year (culture: MonoStringRef, isException: Int32Ptr, exAddress: MonoObjectRef): number { - - const cultureRoot = mono_wasm_new_external_root(culture), - exceptionRoot = mono_wasm_new_external_root(exAddress); +export function mono_wasm_get_first_week_of_year (culture: number, cultureLength: number, resultPtr: Int32Ptr): VoidPtr { try { - const cultureName = monoStringToString(cultureRoot); + const cultureName = runtimeHelpers.utf16ToString(culture, (culture + 2 * cultureLength)); const canonicalLocale = normalizeLocale(cultureName); - wrap_no_error_root(isException, exceptionRoot); - return getFirstWeekOfYear(canonicalLocale); + const result = getFirstWeekOfYear(canonicalLocale); + runtimeHelpers.setI32(resultPtr, result); + return VoidPtrNull; } catch (ex: any) { - wrap_error_root(isException, ex, exceptionRoot); - return -1; - } finally { - cultureRoot.release(); - exceptionRoot.release(); + runtimeHelpers.setI32(resultPtr, -1); + return runtimeHelpers.stringToUTF16Ptr(ex.toString()); } } @@ -130,8 +44,8 @@ function getFirstDayOfWeek (locale: string) { if (saturdayLocales.includes(locale)) { return 6; } - const sundayLanguages = ["zh", "th", "pt", "mr", "ml", "ko", "kn", "ja", "id", "hi", "he", "gu", "fil", "bn", "am", "ar"]; - const sundayLocales = ["ta-SG", "ta-IN", "sw-KE", "ms-SG", "fr-CA", "es-MX", "en-US", "en-ZW", "en-ZA", "en-WS", "en-VI", "en-UM", "en-TT", "en-SG", "en-PR", "en-PK", "en-PH", "en-MT", "en-MO", "en-MH", "en-KE", "en-JM", "en-IN", "en-IL", "en-HK", "en-GU", "en-DM", "en-CA", "en-BZ", "en-BW", "en-BS", "en-AU", "en-AS", "en-AG"]; + const sundayLanguages = ["th", "pt", "mr", "ml", "ko", "kn", "ja", "id", "hi", "he", "gu", "fil", "bn", "am", "ar", "te"]; + const sundayLocales = ["ta-SG", "ta-IN", "sw-KE", "ms-SG", "fr-CA", "es-MX", "en-US", "en-ZW", "en-ZA", "en-WS", "en-VI", "en-UM", "en-TT", "en-SG", "en-PR", "en-PK", "en-PH", "en-MT", "en-MO", "en-MH", "en-KE", "en-JM", "en-IN", "en-IL", "en-HK", "en-GU", "en-DM", "en-CA", "en-BZ", "en-BW", "en-BS", "en-AS", "en-AG", "zh-Hans-HK", "zh-SG", "zh-HK", "zh-TW"]; // "en-AU" is Monday in chrome, so firefox should be in line const localeLang = locale.split("-")[0]; if (sundayLanguages.includes(localeLang) || sundayLocales.includes(locale)) { return 0; @@ -151,8 +65,8 @@ function getFirstWeekOfYear (locale: string) { } // Firefox does not support it rn but we can make a temporary workaround for it, // that should be removed when it starts being supported: - const firstFourDayWeekLocales = ["pt-PT", "fr-CH", "fr-FR", "fr-BE", "es-ES", "en-SE", "en-NL", "en-JE", "en-IM", "en-IE", "en-GI", "en-GG", "en-GB", "en-FJ", "en-FI", "en-DK", "en-DE", "en-CH", "en-BE", "en-AT", "el-GR"]; - const firstFourDayWeekLanguages = ["sv", "sk", "ru", "pl", "nl", "no", "lt", "it", "hu", "fi", "et", "de", "da", "cs", "ca", "bg"]; + const firstFourDayWeekLocales = ["pt-PT", "fr-CH", "fr-FR", "fr-BE", "es-ES", "en-SE", "en-NL", "en-JE", "en-IM", "en-IE", "en-GI", "en-GG", "en-GB", "en-FJ", "en-FI", "en-DK", "en-DE", "en-CH", "en-BE", "en-AT", "el-GR", "nl-BE", "nl-NL"]; + const firstFourDayWeekLanguages = ["sv", "sk", "ru", "pl", "no", "nb", "lt", "it", "hu", "fi", "et", "de", "da", "cs", "ca", "bg"]; const localeLang = locale.split("-")[0]; if (firstFourDayWeekLocales.includes(locale) || firstFourDayWeekLanguages.includes(localeLang)) { return 2; diff --git a/src/mono/browser/runtime/hybrid-globalization/module-exports.ts b/src/mono/browser/runtime/hybrid-globalization/module-exports.ts new file mode 100644 index 000000000000..dc5b3aebf8fd --- /dev/null +++ b/src/mono/browser/runtime/hybrid-globalization/module-exports.ts @@ -0,0 +1,27 @@ +import { GlobalizationHelpers, RuntimeHelpers } from "../types/internal"; +import { mono_wasm_get_calendar_info } from "./calendar"; +import { mono_wasm_change_case, mono_wasm_change_case_invariant } from "./change-case"; +import { mono_wasm_compare_string, mono_wasm_starts_with, mono_wasm_ends_with, mono_wasm_index_of } from "./collations"; +import { mono_wasm_get_culture_info } from "./culture-info"; +import { setSegmentationRulesFromJson } from "./grapheme-segmenter"; +import { mono_wasm_get_first_day_of_week, mono_wasm_get_first_week_of_year } from "./locales"; + +export let globalizationHelpers: GlobalizationHelpers; +export let runtimeHelpers: RuntimeHelpers; + +export function initHybrid (gh: GlobalizationHelpers, rh: RuntimeHelpers) { + gh.mono_wasm_change_case_invariant = mono_wasm_change_case_invariant; + gh.mono_wasm_change_case = mono_wasm_change_case; + gh.mono_wasm_compare_string = mono_wasm_compare_string; + gh.mono_wasm_starts_with = mono_wasm_starts_with; + gh.mono_wasm_ends_with = mono_wasm_ends_with; + gh.mono_wasm_index_of = mono_wasm_index_of; + gh.mono_wasm_get_calendar_info = mono_wasm_get_calendar_info; + gh.mono_wasm_get_culture_info = mono_wasm_get_culture_info; + gh.mono_wasm_get_first_day_of_week = mono_wasm_get_first_day_of_week; + gh.mono_wasm_get_first_week_of_year = mono_wasm_get_first_week_of_year; + gh.setSegmentationRulesFromJson = setSegmentationRulesFromJson; + globalizationHelpers = gh; + runtimeHelpers = rh; +} + diff --git a/src/mono/browser/runtime/icu.ts b/src/mono/browser/runtime/icu.ts index 16b23871f987..b6c789f1138f 100644 --- a/src/mono/browser/runtime/icu.ts +++ b/src/mono/browser/runtime/icu.ts @@ -4,8 +4,8 @@ import cwraps from "./cwraps"; import { VoidPtr } from "./types/emscripten"; -// @offset must be the address of an ICU data archive in the native heap. -// returns true on success. -export function mono_wasm_load_icu_data (offset: VoidPtr): boolean { - return (cwraps.mono_wasm_load_icu_data(offset)) === 1; +export function mono_wasm_load_icu_data (offset: VoidPtr) { + if (!cwraps.mono_wasm_load_icu_data(offset)) { + throw new Error("Failed to load ICU data"); + } } diff --git a/src/mono/browser/runtime/interp-pgo.ts b/src/mono/browser/runtime/interp-pgo.ts index 14697385800b..90557b5f9e81 100644 --- a/src/mono/browser/runtime/interp-pgo.ts +++ b/src/mono/browser/runtime/interp-pgo.ts @@ -198,7 +198,6 @@ export async function getCacheKey (prefix: string): Promise { delete inputs.logExitCode; delete inputs.pthreadPoolInitialSize; delete inputs.pthreadPoolUnusedSize; - delete inputs.finalizerThreadStartDelayMs; delete inputs.asyncFlushOnExit; delete inputs.remoteSources; delete inputs.ignorePdbLoadErrors; diff --git a/src/mono/browser/runtime/invoke-cs.ts b/src/mono/browser/runtime/invoke-cs.ts index ebe1cf60c07a..fafc2d52f253 100644 --- a/src/mono/browser/runtime/invoke-cs.ts +++ b/src/mono/browser/runtime/invoke-cs.ts @@ -45,7 +45,7 @@ function fixupSymbolName (name: string) { export function mono_wasm_bind_cs_function (method: MonoMethod, assemblyName: string, namespaceName: string, shortClassName: string, methodName: string, signatureHash: number, signature: JSFunctionSignature): void { const fullyQualifiedName = `[${assemblyName}] ${namespaceName}.${shortClassName}:${methodName}`; const mark = startMeasure(); - mono_log_debug(`Binding [JSExport] ${namespaceName}.${shortClassName}:${methodName} from ${assemblyName} assembly`); + mono_log_debug(() => `Binding [JSExport] ${namespaceName}.${shortClassName}:${methodName} from ${assemblyName} assembly`); if (NativeAOT) { const namespaceNameWithDot = namespaceName ? `${namespaceName}.` : ""; const js_fqn = `[${assemblyName}]${namespaceNameWithDot}${shortClassName}:${methodName}`; diff --git a/src/mono/browser/runtime/invoke-js.ts b/src/mono/browser/runtime/invoke-js.ts index 2dc7584ab2b6..884a0d6d8a40 100644 --- a/src/mono/browser/runtime/invoke-js.ts +++ b/src/mono/browser/runtime/invoke-js.ts @@ -60,8 +60,8 @@ export function mono_wasm_invoke_jsimport_MT (signature: JSFunctionSignature, ar } } return; - } catch (ex2: any) { - runtimeHelpers.nativeExit(ex2); + } catch (ex: any) { + loaderHelpers.mono_exit(1, ex); return; } } @@ -90,7 +90,7 @@ function bind_js_import (signature: JSFunctionSignature): Function { const js_module_name = get_signature_module_name(signature)!; const function_handle = get_signature_handle(signature); - mono_log_debug(`Binding [JSImport] ${js_function_name} from ${js_module_name} module`); + mono_log_debug(() => `Binding [JSImport] ${js_function_name} from ${js_module_name} module`); const fn = mono_wasm_lookup_js_import(js_function_name, js_module_name); const args_count = get_signature_argument_count(signature); @@ -370,7 +370,7 @@ export function mono_wasm_invoke_js_function_impl (bound_function_js_handle: JSH export function mono_wasm_set_module_imports (module_name: string, moduleImports: any) { importedModules.set(module_name, moduleImports); - mono_log_debug(`added module imports '${module_name}'`); + mono_log_debug(() => `added module imports '${module_name}'`); } function mono_wasm_lookup_js_import (function_name: string, js_module_name: string | null): Function { @@ -447,7 +447,7 @@ export function dynamic_import (module_name: string, module_url: string): Promis let promise = importedModulesPromises.get(module_name); const newPromise = !promise; if (newPromise) { - mono_log_debug(`importing ES6 module '${module_name}' from '${module_url}'`); + mono_log_debug(() => `importing ES6 module '${module_name}' from '${module_url}'`); promise = import(/*! webpackIgnore: true */module_url); importedModulesPromises.set(module_name, promise); } @@ -456,7 +456,7 @@ export function dynamic_import (module_name: string, module_url: string): Promis const module = await promise; if (newPromise) { importedModules.set(module_name, module); - mono_log_debug(`imported ES6 module '${module_name}' from '${module_url}'`); + mono_log_debug(() => `imported ES6 module '${module_name}' from '${module_url}'`); } return module; }); diff --git a/src/mono/browser/runtime/jiterpreter-interp-entry.ts b/src/mono/browser/runtime/jiterpreter-interp-entry.ts index b99917dd2bb0..3863afb601e6 100644 --- a/src/mono/browser/runtime/jiterpreter-interp-entry.ts +++ b/src/mono/browser/runtime/jiterpreter-interp-entry.ts @@ -91,8 +91,8 @@ class TrampolineInfo { hasThisReference: boolean; unbox: boolean; hasReturnValue: boolean; - name: string; - traceName: string; + private name?: string; + private traceName?: string; defaultImplementation: number; result: number; @@ -100,8 +100,7 @@ class TrampolineInfo { constructor ( imethod: number, method: MonoMethod, argumentCount: number, pParamTypes: NativePointer, - unbox: boolean, hasThisReference: boolean, hasReturnValue: boolean, name: string, - defaultImplementation: number + unbox: boolean, hasThisReference: boolean, hasReturnValue: boolean, defaultImplementation: number ) { this.imethod = imethod; this.method = method; @@ -109,27 +108,49 @@ class TrampolineInfo { this.unbox = unbox; this.hasThisReference = hasThisReference; this.hasReturnValue = hasReturnValue; - this.name = name; this.paramTypes = new Array(argumentCount); for (let i = 0; i < argumentCount; i++) this.paramTypes[i] = getU32_unaligned(pParamTypes + (i * 4)); this.defaultImplementation = defaultImplementation; this.result = 0; - let subName = name; - if (!subName) { - subName = `${this.imethod.toString(16)}_${this.hasThisReference ? "i" : "s"}${this.hasReturnValue ? "_r" : ""}_${this.argumentCount}`; - } else { - // truncate the real method name so that it doesn't make the module too big. this isn't a big deal for module-per-function, - // but since we jit in groups now we need to keep the sizes reasonable. we keep the tail end of the name - // since it is likely to contain the method name and/or signature instead of type and noise - const maxLength = 24; - if (subName.length > maxLength) - subName = subName.substring(subName.length - maxLength, subName.length); - subName = `${this.imethod.toString(16)}_${subName}`; - } - this.traceName = subName; this.hitCount = 0; } + + generateName () { + const namePtr = cwraps.mono_wasm_method_get_full_name(this.method); + try { + const name = utf8ToString(namePtr); + this.name = name; + let subName = name; + if (!subName) { + subName = `${this.imethod.toString(16)}_${this.hasThisReference ? "i" : "s"}${this.hasReturnValue ? "_r" : ""}_${this.argumentCount}`; + } else { + // truncate the real method name so that it doesn't make the module too big. this isn't a big deal for module-per-function, + // but since we jit in groups now we need to keep the sizes reasonable. we keep the tail end of the name + // since it is likely to contain the method name and/or signature instead of type and noise + const maxLength = 24; + if (subName.length > maxLength) + subName = subName.substring(subName.length - maxLength, subName.length); + subName = `${this.imethod.toString(16)}_${subName}`; + } + this.traceName = subName; + } finally { + if (namePtr) + Module._free(namePtr); + } + } + + getTraceName () { + if (!this.traceName) + this.generateName(); + return this.traceName || "unknown"; + } + + getName () { + if (!this.name) + this.generateName(); + return this.name || "unknown"; + } } let mostRecentOptions: JiterpreterOptions | undefined = undefined; @@ -170,8 +191,7 @@ export function mono_interp_record_interp_entry (imethod: number) { // returns function pointer export function mono_interp_jit_wasm_entry_trampoline ( imethod: number, method: MonoMethod, argumentCount: number, pParamTypes: NativePointer, - unbox: boolean, hasThisReference: boolean, hasReturnValue: boolean, name: NativePointer, - defaultImplementation: number + unbox: boolean, hasThisReference: boolean, hasReturnValue: boolean, defaultImplementation: number ): number { // HACK if (argumentCount > maxInlineArgs) @@ -179,8 +199,7 @@ export function mono_interp_jit_wasm_entry_trampoline ( const info = new TrampolineInfo( imethod, method, argumentCount, pParamTypes, - unbox, hasThisReference, hasReturnValue, utf8ToString(name), - defaultImplementation + unbox, hasThisReference, hasReturnValue, defaultImplementation ); if (!fnTable) fnTable = getWasmFunctionTable(); @@ -311,7 +330,7 @@ function flush_wasm_entry_trampoline_jit_queue () { // Function type for compiled traces builder.defineType( - info.traceName, sig, WasmValtype.void, false + info.getTraceName(), sig, WasmValtype.void, false ); } @@ -338,9 +357,10 @@ function flush_wasm_entry_trampoline_jit_queue () { builder.appendULeb(jitQueue.length); for (let i = 0; i < jitQueue.length; i++) { const info = jitQueue[i]; + const traceName = info.getTraceName(); // Function type for our compiled trace - mono_assert(builder.functionTypes[info.traceName], "func type missing"); - builder.appendULeb(builder.functionTypes[info.traceName][0]); + mono_assert(builder.functionTypes[traceName], "func type missing"); + builder.appendULeb(builder.functionTypes[traceName][0]); } // Export section @@ -348,7 +368,8 @@ function flush_wasm_entry_trampoline_jit_queue () { builder.appendULeb(jitQueue.length); for (let i = 0; i < jitQueue.length; i++) { const info = jitQueue[i]; - builder.appendName(info.traceName); + const traceName = info.getTraceName(); + builder.appendName(traceName); builder.appendU8(0); // Imports get added to the function index space, so we need to add // the count of imported functions to get the index of our compiled trace @@ -360,7 +381,8 @@ function flush_wasm_entry_trampoline_jit_queue () { builder.appendULeb(jitQueue.length); for (let i = 0; i < jitQueue.length; i++) { const info = jitQueue[i]; - builder.beginFunction(info.traceName, { + const traceName = info.getTraceName(); + builder.beginFunction(traceName, { "sp_args": WasmValtype.i32, "need_unbox": WasmValtype.i32, "scratchBuffer": WasmValtype.i32, @@ -368,7 +390,7 @@ function flush_wasm_entry_trampoline_jit_queue () { const ok = generate_wasm_body(builder, info); if (!ok) - throw new Error(`Failed to generate ${info.traceName}`); + throw new Error(`Failed to generate ${traceName}`); builder.appendU8(WasmOpcode.end); builder.endFunction(true); @@ -390,9 +412,10 @@ function flush_wasm_entry_trampoline_jit_queue () { // to point to the new jitted trampolines instead of the default implementations for (let i = 0; i < jitQueue.length; i++) { const info = jitQueue[i]; + const traceName = info.getTraceName(); // Get the exported trampoline - const fn = traceInstance.exports[info.traceName]; + const fn = traceInstance.exports[traceName]; // Patch the function pointer for this function to use the trampoline now fnTable.set(info.result, fn); diff --git a/src/mono/browser/runtime/jiterpreter-support.ts b/src/mono/browser/runtime/jiterpreter-support.ts index c375b4f91e70..81fd9ebab726 100644 --- a/src/mono/browser/runtime/jiterpreter-support.ts +++ b/src/mono/browser/runtime/jiterpreter-support.ts @@ -11,7 +11,6 @@ import { MintOpcode } from "./mintops"; import cwraps from "./cwraps"; import { mono_log_error, mono_log_info } from "./logging"; import { localHeapViewU8, localHeapViewU32 } from "./memory"; -import { utf8ToString } from "./strings"; import { JiterpNumberMode, BailoutReason, JiterpreterTable, JiterpCounter, JiterpMember, OpcodeInfoType @@ -2017,15 +2016,13 @@ export function getOptions () { } function updateOptions () { - const pJson = cwraps.mono_jiterp_get_options_as_json(); - const json = utf8ToString(pJson); - Module._free(pJson); - const blob = JSON.parse(json); - optionTable = {}; for (const k in optionNames) { - const info = optionNames[k]; - (optionTable)[k] = blob[info]; + const value = cwraps.mono_jiterp_get_option_as_int(optionNames[k]); + if (value > -2147483647) + (optionTable)[k] = value; + else + mono_log_info(`Failed to retrieve value of option ${optionNames[k]}`); } } diff --git a/src/mono/browser/runtime/loader/assets.ts b/src/mono/browser/runtime/loader/assets.ts index 3ef34458dd83..5a4e3e708c1a 100644 --- a/src/mono/browser/runtime/loader/assets.ts +++ b/src/mono/browser/runtime/loader/assets.ts @@ -4,19 +4,21 @@ import WasmEnableThreads from "consts:wasmEnableThreads"; import { PThreadPtrNull, type AssetEntryInternal, type PThreadWorker, type PromiseAndController } from "../types/internal"; -import type { AssetBehaviors, AssetEntry, LoadingResource, ResourceList, SingleAssetBehaviors as SingleAssetBehaviors, WebAssemblyBootResourceType } from "../types"; -import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, ENVIRONMENT_IS_WEB, loaderHelpers, mono_assert, runtimeHelpers } from "./globals"; +import { GlobalizationMode, type AssetBehaviors, type AssetEntry, type LoadingResource, type ResourceList, type SingleAssetBehaviors as SingleAssetBehaviors, type WebAssemblyBootResourceType } from "../types"; +import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, ENVIRONMENT_IS_WEB, ENVIRONMENT_IS_WORKER, loaderHelpers, mono_assert, runtimeHelpers } from "./globals"; import { createPromiseController } from "./promise-controller"; import { mono_log_debug, mono_log_warn } from "./logging"; import { mono_exit } from "./exit"; import { addCachedReponse, findCachedResponse } from "./assetsCache"; import { getIcuResourceName } from "./icu"; import { makeURLAbsoluteWithApplicationBase } from "./polyfills"; +import { mono_log_info } from "./logging"; let throttlingPromise: PromiseAndController | undefined; // in order to prevent net::ERR_INSUFFICIENT_RESOURCES if we start downloading too many files at same time let parallel_count = 0; +const coreAssetsToLoad: AssetEntryInternal[] = []; const assetsToLoad: AssetEntryInternal[] = []; const singleAssets: Map = new Map(); @@ -27,6 +29,7 @@ const jsRuntimeModulesAssetTypes: { [k: string]: boolean } = { "js-module-threads": true, + "js-module-globalization": true, "js-module-runtime": true, "js-module-dotnet": true, "js-module-native": true, @@ -151,21 +154,25 @@ export function resolve_single_asset_path (behavior: SingleAssetBehaviors): Asse export async function mono_download_assets (): Promise { mono_log_debug("mono_download_assets"); try { - const promises_of_assets: Promise[] = []; + const promises_of_assets_core: Promise[] = []; + const promises_of_assets_remaining: Promise[] = []; - const countAndStartDownload = (asset: AssetEntryInternal) => { + const countAndStartDownload = (asset: AssetEntryInternal, promises_list: Promise[]) => { if (!skipInstantiateByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) { loaderHelpers.expected_instantiated_assets_count++; } if (!skipDownloadsByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) { loaderHelpers.expected_downloaded_assets_count++; - promises_of_assets.push(start_asset_download(asset)); + promises_list.push(start_asset_download(asset)); } }; // start fetching assets in parallel + for (const asset of coreAssetsToLoad) { + countAndStartDownload(asset, promises_of_assets_core); + } for (const asset of assetsToLoad) { - countAndStartDownload(asset); + countAndStartDownload(asset, promises_of_assets_remaining); } loaderHelpers.allDownloadsQueued.promise_control.resolve(); @@ -173,55 +180,73 @@ export async function mono_download_assets (): Promise { // continue after the dotnet.runtime.js was loaded await loaderHelpers.runtimeModuleLoaded.promise; - const promises_of_asset_instantiation: Promise[] = []; - for (const downloadPromise of promises_of_assets) { - promises_of_asset_instantiation.push((async () => { - const asset = await downloadPromise; - if (asset.buffer) { - if (!skipInstantiateByAssetTypes[asset.behavior]) { - mono_assert(asset.buffer && typeof asset.buffer === "object", "asset buffer must be array-like or buffer-like or promise of these"); - mono_assert(typeof asset.resolvedUrl === "string", "resolvedUrl must be string"); - const url = asset.resolvedUrl!; - const buffer = await asset.buffer; - const data = new Uint8Array(buffer); - cleanupAsset(asset); - - // wait till after onRuntimeInitialized - - await runtimeHelpers.beforeOnRuntimeInitialized.promise; - runtimeHelpers.instantiate_asset(asset, url, data); + const instantiate = async (downloadPromise: Promise) => { + const asset = await downloadPromise; + if (asset.buffer) { + if (!skipInstantiateByAssetTypes[asset.behavior]) { + mono_assert(asset.buffer && typeof asset.buffer === "object", "asset buffer must be array-like or buffer-like or promise of these"); + mono_assert(typeof asset.resolvedUrl === "string", "resolvedUrl must be string"); + const url = asset.resolvedUrl!; + const buffer = await asset.buffer; + const data = new Uint8Array(buffer); + cleanupAsset(asset); + + // wait till after onRuntimeInitialized + + await runtimeHelpers.beforeOnRuntimeInitialized.promise; + runtimeHelpers.instantiate_asset(asset, url, data); + } + } else { + const headersOnly = skipBufferByAssetTypes[asset.behavior]; + if (!headersOnly) { + mono_assert(asset.isOptional, "Expected asset to have the downloaded buffer"); + if (!skipDownloadsByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) { + loaderHelpers.expected_downloaded_assets_count--; + } + if (!skipInstantiateByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) { + loaderHelpers.expected_instantiated_assets_count--; } } else { - const headersOnly = skipBufferByAssetTypes[asset.behavior]; - if (!headersOnly) { - mono_assert(asset.isOptional, "Expected asset to have the downloaded buffer"); - if (!skipDownloadsByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) { - loaderHelpers.expected_downloaded_assets_count--; - } - if (!skipInstantiateByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) { - loaderHelpers.expected_instantiated_assets_count--; - } - } else { - if (asset.behavior === "symbols") { - await runtimeHelpers.instantiate_symbols_asset(asset); - cleanupAsset(asset); - } else if (asset.behavior === "segmentation-rules") { - await runtimeHelpers.instantiate_segmentation_rules_asset(asset); - cleanupAsset(asset); - } - - if (skipBufferByAssetTypes[asset.behavior]) { - ++loaderHelpers.actual_downloaded_assets_count; - } + if (asset.behavior === "symbols") { + await runtimeHelpers.instantiate_symbols_asset(asset); + cleanupAsset(asset); + } else if (asset.behavior === "segmentation-rules") { + await runtimeHelpers.instantiate_segmentation_rules_asset(asset); + cleanupAsset(asset); + } + + if (skipBufferByAssetTypes[asset.behavior]) { + ++loaderHelpers.actual_downloaded_assets_count; } } - })()); + } + }; + + const promises_of_asset_instantiation_core: Promise[] = []; + const promises_of_asset_instantiation_remaining: Promise[] = []; + for (const downloadPromise of promises_of_assets_core) { + promises_of_asset_instantiation_core.push(instantiate(downloadPromise)); + } + for (const downloadPromise of promises_of_assets_remaining) { + promises_of_asset_instantiation_remaining.push(instantiate(downloadPromise)); } // this await will get past the onRuntimeInitialized because we are not blocking via addRunDependency - // and we are not awating it here - Promise.all(promises_of_asset_instantiation).then(() => { - runtimeHelpers.allAssetsInMemory.promise_control.resolve(); + // and we are not awaiting it here + Promise.all(promises_of_asset_instantiation_core).then(() => { + if (!ENVIRONMENT_IS_WORKER) { + runtimeHelpers.coreAssetsInMemory.promise_control.resolve(); + } + }).catch(err => { + loaderHelpers.err("Error in mono_download_assets: " + err); + mono_exit(1, err); + throw err; + }); + Promise.all(promises_of_asset_instantiation_remaining).then(async () => { + if (!ENVIRONMENT_IS_WORKER) { + await runtimeHelpers.coreAssetsInMemory.promise; + runtimeHelpers.allAssetsInMemory.promise_control.resolve(); + } }).catch(err => { loaderHelpers.err("Error in mono_download_assets: " + err); mono_exit(1, err); @@ -250,7 +275,11 @@ export function prepareAssets () { mono_assert(!asset.resolvedUrl || typeof asset.resolvedUrl === "string", "asset resolvedUrl could be string"); mono_assert(!asset.hash || typeof asset.hash === "string", "asset resolvedUrl could be string"); mono_assert(!asset.pendingDownload || typeof asset.pendingDownload === "object", "asset pendingDownload could be object"); - assetsToLoad.push(asset); + if (asset.isCore) { + coreAssetsToLoad.push(asset); + } else { + assetsToLoad.push(asset); + } set_single_asset(asset); } } else if (config.resources) { @@ -266,24 +295,59 @@ export function prepareAssets () { if (WasmEnableThreads) { convert_single_asset(modulesAssets, resources.jsModuleWorker, "js-module-threads"); } + if (config.globalizationMode == GlobalizationMode.Hybrid) { + convert_single_asset(modulesAssets, resources.jsModuleGlobalization, "js-module-globalization"); + } + + const addAsset = (asset: AssetEntryInternal, isCore: boolean) => { + if (isCore) { + asset.isCore = true; + coreAssetsToLoad.push(asset); + } else { + assetsToLoad.push(asset); + } + }; + + if (resources.coreAssembly) { + for (const name in resources.coreAssembly) { + addAsset({ + name, + hash: resources.coreAssembly[name], + behavior: "assembly" + }, true); + } + } if (resources.assembly) { for (const name in resources.assembly) { - assetsToLoad.push({ + addAsset({ name, hash: resources.assembly[name], behavior: "assembly" - }); + }, !resources.coreAssembly); // if there are no core assemblies, then all assemblies are core } } - if (config.debugLevel != 0 && loaderHelpers.isDebuggingSupported() && resources.pdb) { - for (const name in resources.pdb) { - assetsToLoad.push({ - name, - hash: resources.pdb[name], - behavior: "pdb" - }); + + if (config.debugLevel != 0 && loaderHelpers.isDebuggingSupported()) { + if (resources.corePdb) { + for (const name in resources.corePdb) { + addAsset({ + name, + hash: resources.corePdb[name], + behavior: "pdb" + }, true); + } + } + + if (resources.pdb) { + for (const name in resources.pdb) { + addAsset({ + name, + hash: resources.pdb[name], + behavior: "pdb" + }, !resources.corePdb); // if there are no core pdbs, then all pdbs are core + } } } @@ -300,15 +364,28 @@ export function prepareAssets () { } } + if (resources.coreVfs) { + for (const virtualPath in resources.coreVfs) { + for (const name in resources.coreVfs[virtualPath]) { + addAsset({ + name, + hash: resources.coreVfs[virtualPath][name], + behavior: "vfs", + virtualPath + }, true); + } + } + } + if (resources.vfs) { for (const virtualPath in resources.vfs) { for (const name in resources.vfs[virtualPath]) { - assetsToLoad.push({ + addAsset({ name, hash: resources.vfs[virtualPath][name], behavior: "vfs", virtualPath - }); + }, !resources.coreVfs); } } } @@ -335,7 +412,7 @@ export function prepareAssets () { if (resources.wasmSymbols) { for (const name in resources.wasmSymbols) { - assetsToLoad.push({ + coreAssetsToLoad.push({ name, hash: resources.wasmSymbols[name], behavior: "symbols" @@ -362,7 +439,7 @@ export function prepareAssets () { } } - config.assets = [...assetsToLoad, ...modulesAssets]; + config.assets = [...coreAssetsToLoad, ...assetsToLoad, ...modulesAssets]; } export function prepareAssetsWorker () { @@ -416,14 +493,14 @@ export async function start_asset_download (asset: AssetEntryInternal): Promise< // second attempt only after all first attempts are queued await loaderHelpers.allDownloadsQueued.promise; try { - mono_log_debug(`Retrying download '${asset.name}'`); + mono_log_debug(() => `Retrying download '${asset.name}'`); return await start_asset_download_with_throttle(asset); } catch (err) { asset.pendingDownloadInternal = undefined; // third attempt after small delay await delay(100); - mono_log_debug(`Retrying download (2) '${asset.name}' after delay`); + mono_log_debug(() => `Retrying download (2) '${asset.name}' after delay`); return await start_asset_download_with_throttle(asset); } } @@ -504,9 +581,9 @@ async function start_asset_download_sources (asset: AssetEntryInternal): Promise const attemptUrl = resolve_path(asset, sourcePrefix); if (asset.name === attemptUrl) { - mono_log_debug(`Attempting to download '${attemptUrl}'`); + mono_log_debug(() => `Attempting to download '${attemptUrl}'`); } else { - mono_log_debug(`Attempting to download '${attemptUrl}' for ${asset.name}`); + mono_log_debug(() => `Attempting to download '${attemptUrl}' for ${asset.name}`); } try { asset.resolvedUrl = attemptUrl; @@ -536,7 +613,7 @@ async function start_asset_download_sources (asset: AssetEntryInternal): Promise err.status = response.status; throw err; } else { - loaderHelpers.out(`optional download '${response.url}' for ${asset.name} failed ${response.status} ${response.statusText}`); + mono_log_info(`optional download '${response.url}' for ${asset.name} failed ${response.status} ${response.statusText}`); return undefined; } } @@ -740,6 +817,7 @@ export async function streamingCompileWasm () { export function preloadWorkers () { if (!WasmEnableThreads) return; const jsModuleWorker = resolve_single_asset_path("js-module-threads"); + const loadingWorkers = []; for (let i = 0; i < loaderHelpers.config.pthreadPoolInitialSize!; i++) { const workerNumber = loaderHelpers.workerNextNumber++; const worker: Partial = new Worker(jsModuleWorker.resolvedUrl!, { @@ -753,6 +831,7 @@ export function preloadWorkers () { threadPrefix: worker_empty_prefix, threadName: "emscripten-pool", } as any; - loaderHelpers.loadingWorkers.push(worker as any); + loadingWorkers.push(worker as any); } + loaderHelpers.loadingWorkers.promise_control.resolve(loadingWorkers); } diff --git a/src/mono/browser/runtime/loader/config.ts b/src/mono/browser/runtime/loader/config.ts index 5ff185827c10..6b80f7326fb8 100644 --- a/src/mono/browser/runtime/loader/config.ts +++ b/src/mono/browser/runtime/loader/config.ts @@ -71,6 +71,9 @@ function deep_merge_resources (target: ResourceGroups, source: ResourceGroups): if (providedResources.jsModuleNative !== undefined) { providedResources.jsModuleNative = { ...(target.jsModuleNative || {}), ...(providedResources.jsModuleNative || {}) }; } + if (providedResources.jsModuleGlobalization !== undefined) { + providedResources.jsModuleGlobalization = { ...(target.jsModuleGlobalization || {}), ...(providedResources.jsModuleGlobalization || {}) }; + } if (providedResources.jsModuleRuntime !== undefined) { providedResources.jsModuleRuntime = { ...(target.jsModuleRuntime || {}), ...(providedResources.jsModuleRuntime || {}) }; } @@ -121,6 +124,7 @@ export function normalizeConfig () { config.resources = config.resources || { assembly: {}, jsModuleNative: {}, + jsModuleGlobalization: {}, jsModuleWorker: {}, jsModuleRuntime: {}, wasmNative: {}, @@ -161,6 +165,9 @@ export function normalizeConfig () { case "js-module-threads": toMerge.jsModuleWorker = resource; break; + case "js-module-globalization": + toMerge.jsModuleGlobalization = resource; + break; case "js-module-runtime": toMerge.jsModuleRuntime = resource; break; @@ -194,9 +201,6 @@ export function normalizeConfig () { if (!Number.isInteger(config.pthreadPoolUnusedSize)) { config.pthreadPoolUnusedSize = 1; } - if (!Number.isInteger(config.finalizerThreadStartDelayMs)) { - config.finalizerThreadStartDelayMs = 200; - } if (config.jsThreadBlockingMode == undefined) { config.jsThreadBlockingMode = JSThreadBlockingMode.PreventSynchronousJSExport; } diff --git a/src/mono/browser/runtime/loader/exit.ts b/src/mono/browser/runtime/loader/exit.ts index 2264cd086fbd..363296948786 100644 --- a/src/mono/browser/runtime/loader/exit.ts +++ b/src/mono/browser/runtime/loader/exit.ts @@ -39,36 +39,47 @@ export function uninstallUnhandledErrorHandler () { } } +let originalOnAbort: ((reason: any, extraJson?:string)=>void)|undefined; +let originalOnExit: ((code: number)=>void)|undefined; + export function registerEmscriptenExitHandlers () { - if (!emscriptenModule.onAbort) { - emscriptenModule.onAbort = onAbort; - } - if (!emscriptenModule.onExit) { - emscriptenModule.onExit = onExit; - } + originalOnAbort = emscriptenModule.onAbort; + originalOnExit = emscriptenModule.onExit; + emscriptenModule.onAbort = onAbort; + emscriptenModule.onExit = onExit; } function unregisterEmscriptenExitHandlers () { if (emscriptenModule.onAbort == onAbort) { - emscriptenModule.onAbort = undefined; + emscriptenModule.onAbort = originalOnAbort; } if (emscriptenModule.onExit == onExit) { - emscriptenModule.onExit = undefined; + emscriptenModule.onExit = originalOnExit; } } function onExit (code: number) { + if (originalOnExit) { + originalOnExit(code); + } mono_exit(code, loaderHelpers.exitReason); } function onAbort (reason: any) { - mono_exit(1, loaderHelpers.exitReason || reason); + if (originalOnAbort) { + originalOnAbort(reason || loaderHelpers.exitReason); + } + if (WasmEnableThreads && loaderHelpers.config?.dumpThreadsOnNonZeroExit && runtimeHelpers.mono_wasm_print_thread_dump && loaderHelpers.exitCode === undefined) { + try { + runtimeHelpers.mono_wasm_print_thread_dump(); + } catch (e) { + // ignore + } + } + mono_exit(1, reason || loaderHelpers.exitReason); } // this will also call mono_wasm_exit if available, which will call exitJS -> _proc_exit -> terminateAllThreads export function mono_exit (exit_code: number, reason?: any): void { - unregisterEmscriptenExitHandlers(); - uninstallUnhandledErrorHandler(); - // unify shape of the reason object const is_object = reason && typeof reason === "object"; exit_code = (is_object && typeof reason.status === "number") @@ -82,7 +93,7 @@ export function mono_exit (exit_code: number, reason?: any): void { reason = is_object ? reason : (runtimeHelpers.ExitStatus - ? new runtimeHelpers.ExitStatus(exit_code) + ? createExitStatus(exit_code, message) : new Error("Exit with code " + exit_code + " " + message)); reason.status = exit_code; if (!reason.message) { @@ -90,17 +101,25 @@ export function mono_exit (exit_code: number, reason?: any): void { } // force stack property to be generated before we shut down managed code, or create current stack if it doesn't exist - if (!reason.stack) { - reason.stack = new Error().stack || ""; + const stack = "" + (reason.stack || (new Error().stack)); + try { + Object.defineProperty(reason, "stack", { + get: () => stack + }); + } catch (e) { + // ignore } // don't report this error twice + const alreadySilent = !!reason.silent; reason.silent = true; if (!is_exited()) { try { + unregisterEmscriptenExitHandlers(); + uninstallUnhandledErrorHandler(); if (!runtimeHelpers.runtimeReady) { - mono_log_debug("abort_startup, reason: " + reason); + mono_log_debug(() => `abort_startup, reason: ${reason}`); abort_promises(reason); } else { if (runtimeHelpers.jiterpreter_dump_stats) { @@ -114,24 +133,30 @@ export function mono_exit (exit_code: number, reason?: any): void { } } } catch (err) { - mono_log_warn("mono_exit failed", err); + mono_log_warn("mono_exit A failed", err); // don't propagate any failures } try { - logOnExit(exit_code, reason); - appendElementOnExit(exit_code); + if (!alreadySilent) { + logOnExit(exit_code, reason); + appendElementOnExit(exit_code); + } } catch (err) { - mono_log_warn("mono_exit failed", err); + mono_log_warn("mono_exit B failed", err); // don't propagate any failures } loaderHelpers.exitCode = exit_code; - loaderHelpers.exitReason = reason.message; + if (!loaderHelpers.exitReason) { + loaderHelpers.exitReason = reason; + } if (!ENVIRONMENT_IS_WORKER && runtimeHelpers.runtimeReady) { emscriptenModule.runtimeKeepalivePop(); } + } else { + mono_log_debug("mono_exit called after exit"); } if (loaderHelpers.config && loaderHelpers.config.asyncFlushOnExit && exit_code === 0) { @@ -154,18 +179,16 @@ export function mono_exit (exit_code: number, reason?: any): void { function set_exit_code_and_quit_now (exit_code: number, reason?: any): void { if (WasmEnableThreads && ENVIRONMENT_IS_WORKER && runtimeHelpers.runtimeReady && runtimeHelpers.nativeAbort) { // note that the reason is not passed to UI thread - runtimeHelpers.runtimeReady = false; runtimeHelpers.nativeAbort(reason); throw reason; } if (runtimeHelpers.runtimeReady && runtimeHelpers.nativeExit) { - runtimeHelpers.runtimeReady = false; try { runtimeHelpers.nativeExit(exit_code); } catch (error: any) { if (runtimeHelpers.ExitStatus && !(error instanceof runtimeHelpers.ExitStatus)) { - mono_log_warn("mono_wasm_exit failed: " + error.toString()); + mono_log_warn("set_exit_code_and_quit_now failed: " + error.toString()); } } } @@ -205,7 +228,6 @@ async function flush_node_streams () { } function abort_promises (reason: any) { - loaderHelpers.exitReason = reason; loaderHelpers.allDownloadsQueued.promise_control.reject(reason); loaderHelpers.afterConfigLoaded.promise_control.reject(reason); loaderHelpers.wasmCompilePromise.promise_control.reject(reason); @@ -256,7 +278,7 @@ function logOnExit (exit_code: number, reason: any) { } } } - if (loaderHelpers.config) { + if (!ENVIRONMENT_IS_WORKER && loaderHelpers.config) { if (loaderHelpers.config.logExitCode) { if (loaderHelpers.config.forwardConsoleLogsToWS) { teardown_proxy_console("WASM EXIT " + exit_code); @@ -294,3 +316,10 @@ function fatal_handler (event: any, reason: any, type: string) { // no not re-throw from the fatal handler } } + +function createExitStatus (status:number, message:string) { + const ex = new runtimeHelpers.ExitStatus(status); + ex.message = message; + ex.toString = () => message; + return ex; +} diff --git a/src/mono/browser/runtime/loader/globals.ts b/src/mono/browser/runtime/loader/globals.ts index 5e76904d5525..d9d3ec018382 100644 --- a/src/mono/browser/runtime/loader/globals.ts +++ b/src/mono/browser/runtime/loader/globals.ts @@ -8,7 +8,7 @@ import { exceptions, simd } from "wasm-feature-detect"; import gitHash from "consts:gitHash"; -import type { DotnetModuleInternal, GlobalObjects, LoaderHelpers, MonoConfigInternal, RuntimeHelpers } from "../types/internal"; +import type { DotnetModuleInternal, GlobalObjects, GlobalizationHelpers, LoaderHelpers, MonoConfigInternal, PThreadWorker, RuntimeHelpers } from "../types/internal"; import type { MonoConfig, RuntimeAPI } from "../types"; import { assert_runtime_running, installUnhandledErrorHandler, is_exited, is_runtime_running, mono_exit } from "./exit"; import { assertIsControllablePromise, createPromiseController, getPromiseController } from "./promise-controller"; @@ -32,6 +32,7 @@ export const ENVIRONMENT_IS_WEB = typeof window == "object" || (ENVIRONMENT_IS_W export const ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE; export let runtimeHelpers: RuntimeHelpers = {} as any; +export let globalizationHelpers: GlobalizationHelpers = {} as any; export let loaderHelpers: LoaderHelpers = {} as any; export let exportedRuntimeAPI: RuntimeAPI = {} as any; export let INTERNAL: any = {}; @@ -48,6 +49,7 @@ export const globalObjectsRoot: GlobalObjects = { module: emscriptenModule, loaderHelpers, runtimeHelpers, + globalizationHelpers, api: exportedRuntimeAPI, } as any; @@ -61,6 +63,7 @@ export function setLoaderGlobals ( } _loaderModuleLoaded = true; runtimeHelpers = globalObjects.runtimeHelpers; + globalizationHelpers = globalObjects.globalizationHelpers; loaderHelpers = globalObjects.loaderHelpers; exportedRuntimeAPI = globalObjects.api; INTERNAL = globalObjects.internal; @@ -95,7 +98,6 @@ export function setLoaderGlobals ( loadedFiles: [], loadedAssemblies: [], libraryInitializers: [], - loadingWorkers: [], workerNextNumber: 1, actual_downloaded_assets_count: 0, actual_instantiated_assets_count: 0, @@ -106,6 +108,7 @@ export function setLoaderGlobals ( allDownloadsQueued: createPromiseController(), wasmCompilePromise: createPromiseController(), runtimeModuleLoaded: createPromiseController(), + loadingWorkers: createPromiseController(), is_exited, is_runtime_running, diff --git a/src/mono/browser/runtime/loader/icu.ts b/src/mono/browser/runtime/loader/icu.ts index 0a7823497aa8..b9bf54eb31f1 100644 --- a/src/mono/browser/runtime/loader/icu.ts +++ b/src/mono/browser/runtime/loader/icu.ts @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +import { mono_log_error } from "./logging"; import { GlobalizationMode, MonoConfig } from "../types"; import { ENVIRONMENT_IS_WEB, loaderHelpers } from "./globals"; import { mono_log_info, mono_log_debug } from "./logging"; @@ -18,7 +19,7 @@ export function init_globalization () { loaderHelpers.preferredIcuAsset = null; } else { const msg = "invariant globalization mode is inactive and no ICU data archives are available"; - loaderHelpers.err(`ERROR: ${msg}`); + mono_log_error(`ERROR: ${msg}`); throw new Error(msg); } } diff --git a/src/mono/browser/runtime/loader/libraryInitializers.ts b/src/mono/browser/runtime/loader/libraryInitializers.ts index a8a16c543dbc..4dd0ccfed9ff 100644 --- a/src/mono/browser/runtime/loader/libraryInitializers.ts +++ b/src/mono/browser/runtime/loader/libraryInitializers.ts @@ -18,7 +18,7 @@ export async function importLibraryInitializers (libraryInitializers: ResourceLi async function importInitializer (path: string): Promise { try { const adjustedPath = appendUniqueQuery(loaderHelpers.locateFile(path), "js-module-library-initializer"); - mono_log_debug(`Attempting to import '${adjustedPath}' for ${path}`); + mono_log_debug(() => `Attempting to import '${adjustedPath}' for ${path}`); const initializer = await import(/*! webpackIgnore: true */ adjustedPath); loaderHelpers.libraryInitializers!.push({ scriptName: path, exports: initializer }); diff --git a/src/mono/browser/runtime/loader/logging.ts b/src/mono/browser/runtime/loader/logging.ts index 668d7e667b6d..e11e844c56b4 100644 --- a/src/mono/browser/runtime/loader/logging.ts +++ b/src/mono/browser/runtime/loader/logging.ts @@ -18,9 +18,12 @@ export function set_thread_prefix (threadPrefix: string) { threadNamePrefix = threadPrefix; } -export function mono_log_debug (msg: string, ...data: any[]) { +export function mono_log_debug (messageFactory: string | (() => string)) { if (loaderHelpers.diagnosticTracing) { - console.debug(prefix + msg, ...data); + const message = (typeof messageFactory === "function" + ? messageFactory() + : messageFactory); + console.debug(prefix + message); } } @@ -42,9 +45,6 @@ export function mono_log_error (msg: string, ...data: any) { if (data[0].silent) { return; } - if (data[0].toString) { - console.error(prefix + msg, data[0].toString()); - } if (data[0].toString) { console.error(prefix + msg, data[0].toString()); return; @@ -118,12 +118,13 @@ export function setup_proxy_console (id: string, console: Console, origin: strin } export function teardown_proxy_console (message?: string) { + let counter = 30; const stop_when_ws_buffer_empty = () => { if (!consoleWebSocket) { if (message && originalConsoleMethods) { originalConsoleMethods.log(message); } - } else if (consoleWebSocket.bufferedAmount == 0) { + } else if (consoleWebSocket.bufferedAmount == 0 || counter == 0) { if (message) { // tell xharness WasmTestMessagesProcessor we are done. // note this sends last few bytes into the same WS @@ -136,6 +137,7 @@ export function teardown_proxy_console (message?: string) { consoleWebSocket.close(1000, message); (consoleWebSocket as any) = undefined; } else { + counter--; globalThis.setTimeout(stop_when_ws_buffer_empty, 100); } }; diff --git a/src/mono/browser/runtime/loader/run.ts b/src/mono/browser/runtime/loader/run.ts index 7aeb75d260cb..e3dba786c78a 100644 --- a/src/mono/browser/runtime/loader/run.ts +++ b/src/mono/browser/runtime/loader/run.ts @@ -4,8 +4,8 @@ import NativeAOT from "consts:nativeAOT"; import BuildConfiguration from "consts:configuration"; -import type { MonoConfig, DotnetHostBuilder, DotnetModuleConfig, RuntimeAPI, LoadBootResourceCallback } from "../types"; -import type { EmscriptenModuleInternal, RuntimeModuleExportsInternal, NativeModuleExportsInternal, } from "../types/internal"; +import { type MonoConfig, type DotnetHostBuilder, type DotnetModuleConfig, type RuntimeAPI, type LoadBootResourceCallback, GlobalizationMode } from "../types"; +import type { EmscriptenModuleInternal, RuntimeModuleExportsInternal, NativeModuleExportsInternal, HybridGlobalizationModuleExportsInternal, } from "../types/internal"; import { ENVIRONMENT_IS_WEB, ENVIRONMENT_IS_WORKER, emscriptenModule, exportedRuntimeAPI, globalObjectsRoot, monoConfig, mono_assert } from "./globals"; import { deep_merge_config, deep_merge_module, mono_wasm_load_config } from "./config"; @@ -13,7 +13,7 @@ import { installUnhandledErrorHandler, mono_exit, registerEmscriptenExitHandlers import { setup_proxy_console, mono_log_info, mono_log_debug } from "./logging"; import { mono_download_assets, preloadWorkers, prepareAssets, prepareAssetsWorker, resolve_single_asset_path, streamingCompileWasm } from "./assets"; import { detect_features_and_polyfill } from "./polyfills"; -import { runtimeHelpers, loaderHelpers } from "./globals"; +import { runtimeHelpers, loaderHelpers, globalizationHelpers } from "./globals"; import { init_globalization } from "./icu"; import { setupPreloadChannelToMainThread } from "./worker"; import { importLibraryInitializers, invokeLibraryInitializers } from "./libraryInitializers"; @@ -159,6 +159,10 @@ export class HostBuilder implements DotnetHostBuilder { interpreterPgo: value, interpreterPgoSaveDelay: autoSaveDelay }); + if (monoConfig.runtimeOptions) + monoConfig.runtimeOptions.push("--interp-pgo-recording"); + else + monoConfig.runtimeOptions = ["--interp-pgo-recording"]; return this; } catch (err) { mono_exit(1, err); @@ -269,9 +273,10 @@ export class HostBuilder implements DotnetHostBuilder { withRuntimeOptions (runtimeOptions: string[]): DotnetHostBuilder { try { mono_assert(runtimeOptions && Array.isArray(runtimeOptions), "must be array of strings"); - deep_merge_config(monoConfig, { - runtimeOptions - }); + if (monoConfig.runtimeOptions) + monoConfig.runtimeOptions.push(...runtimeOptions); + else + monoConfig.runtimeOptions = runtimeOptions; return this; } catch (err) { mono_exit(1, err); @@ -419,26 +424,44 @@ function importModules () { if (typeof jsModuleRuntimeAsset.moduleExports === "object") { jsModuleRuntimePromise = jsModuleRuntimeAsset.moduleExports; } else { - mono_log_debug(`Attempting to import '${jsModuleRuntimeAsset.resolvedUrl}' for ${jsModuleRuntimeAsset.name}`); + mono_log_debug(() => `Attempting to import '${jsModuleRuntimeAsset.resolvedUrl}' for ${jsModuleRuntimeAsset.name}`); jsModuleRuntimePromise = import(/*! webpackIgnore: true */jsModuleRuntimeAsset.resolvedUrl!); } if (typeof jsModuleNativeAsset.moduleExports === "object") { jsModuleNativePromise = jsModuleNativeAsset.moduleExports; } else { - mono_log_debug(`Attempting to import '${jsModuleNativeAsset.resolvedUrl}' for ${jsModuleNativeAsset.name}`); + mono_log_debug(() => `Attempting to import '${jsModuleNativeAsset.resolvedUrl}' for ${jsModuleNativeAsset.name}`); jsModuleNativePromise = import(/*! webpackIgnore: true */jsModuleNativeAsset.resolvedUrl!); } - return [jsModuleRuntimePromise, jsModuleNativePromise]; } +async function getHybridModuleExports () : Promise { + let jsModuleHybridGlobalizationPromise: Promise | undefined = undefined; + // todo: move it for after runtime startup + const jsModuleHybridGlobalization = resolve_single_asset_path("js-module-globalization"); + if (typeof jsModuleHybridGlobalization.moduleExports === "object") { + jsModuleHybridGlobalizationPromise = jsModuleHybridGlobalization.moduleExports; + } else { + mono_log_debug(`Attempting to import '${jsModuleHybridGlobalization.resolvedUrl}' for ${jsModuleHybridGlobalization.name}`); + jsModuleHybridGlobalizationPromise = import(/*! webpackIgnore: true */jsModuleHybridGlobalization.resolvedUrl!); + } + const hybridModule = await jsModuleHybridGlobalizationPromise; + return hybridModule as any; +} + async function initializeModules (es6Modules: [RuntimeModuleExportsInternal, NativeModuleExportsInternal]) { const { initializeExports, initializeReplacements, configureRuntimeStartup, configureEmscriptenStartup, configureWorkerStartup, setRuntimeGlobals, passEmscriptenInternals } = es6Modules[0]; const { default: emscriptenFactory } = es6Modules[1]; setRuntimeGlobals(globalObjectsRoot); initializeExports(globalObjectsRoot); - await configureRuntimeStartup(); + if (loaderHelpers.config.globalizationMode === GlobalizationMode.Hybrid) { + const hybridModule = await getHybridModuleExports(); + const { initHybrid } = hybridModule; + initHybrid(globalizationHelpers, runtimeHelpers); + } + await configureRuntimeStartup(emscriptenModule); loaderHelpers.runtimeModuleLoaded.promise_control.resolve(); emscriptenFactory((originalModule: EmscriptenModuleInternal) => { diff --git a/src/mono/browser/runtime/locales-common.ts b/src/mono/browser/runtime/locales-common.ts new file mode 100644 index 000000000000..aa3a8ce6c919 --- /dev/null +++ b/src/mono/browser/runtime/locales-common.ts @@ -0,0 +1,78 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +import { VoidPtrNull } from "./types/internal"; +import { Int32Ptr, VoidPtr } from "./types/emscripten"; +import { OUTER_SEPARATOR, normalizeLocale } from "./hybrid-globalization/helpers"; +import { stringToUTF16, stringToUTF16Ptr, utf16ToString } from "./strings"; +import { setI32 } from "./memory"; + +// functions common for Hybrid Globalization -> true | false : + +export function mono_wasm_get_locale_info (culture: number, cultureLength: number, locale: number, localeLength: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr): VoidPtr { + try { + const localeNameOriginal = utf16ToString(locale, (locale + 2 * localeLength)); + const localeName = normalizeLocale(localeNameOriginal); + if (!localeName && localeNameOriginal) { + // handle non-standard or malformed locales by forwarding the locale code + stringToUTF16(dst, dst + 2 * localeNameOriginal.length, localeNameOriginal); + setI32(dstLength, localeNameOriginal.length); + return VoidPtrNull; + } + const cultureNameOriginal = utf16ToString(culture, (culture + 2 * cultureLength)); + const cultureName = normalizeLocale(cultureNameOriginal); + + if (!localeName || !cultureName) + throw new Error(`Locale or culture name is null or empty. localeName=${localeName}, cultureName=${cultureName}`); + + const localeParts = localeName.split("-"); + // cultureName can be in a form of: + // 1) "language", e.g. "zh" + // 2) "language-region", e.g. "zn-CN" + // 3) "language-script-region", e.g. "zh-Hans-CN" + // 4) "language-script", e.g. "zh-Hans" (served in the catch block below) + let languageName, regionName; + try { + const region = localeParts.length > 1 ? localeParts.pop() : undefined; + // this line might fail if form 4 from the comment above is used: + regionName = region ? new Intl.DisplayNames([cultureName], { type: "region" }).of(region) : undefined; + const language = localeParts.join("-"); + languageName = new Intl.DisplayNames([cultureName], { type: "language" }).of(language); + } catch (error) { + if (error instanceof RangeError) { + // if it failed from this reason then cultureName is in a form "language-script", without region + try { + languageName = new Intl.DisplayNames([cultureName], { type: "language" }).of(localeName); + } catch (error) { + if (error instanceof RangeError && localeNameOriginal) { + // handle non-standard or malformed locales by forwarding the locale code, e.g. "xx-u-xx" + stringToUTF16(dst, dst + 2 * localeNameOriginal.length, localeNameOriginal); + setI32(dstLength, localeNameOriginal.length); + return VoidPtrNull; + } + throw error; + } + } else { + throw error; + } + } + const localeInfo = { + LanguageName: languageName, + RegionName: regionName, + }; + const result = Object.values(localeInfo).join(OUTER_SEPARATOR); + + if (!result) + throw new Error(`Locale info for locale=${localeName} is null or empty.`); + + if (result.length > dstMaxLength) + throw new Error(`Locale info for locale=${localeName} exceeds length of ${dstMaxLength}.`); + + stringToUTF16(dst, dst + 2 * result.length, result); + setI32(dstLength, result.length); + return VoidPtrNull; + } catch (ex: any) { + setI32(dstLength, -1); + return stringToUTF16Ptr(ex.toString()); + } +} diff --git a/src/mono/browser/runtime/logging.ts b/src/mono/browser/runtime/logging.ts index 1d91a870d52f..7cd4af973fb8 100644 --- a/src/mono/browser/runtime/logging.ts +++ b/src/mono/browser/runtime/logging.ts @@ -1,8 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -/* eslint-disable no-console */ -import { INTERNAL, runtimeHelpers, mono_assert } from "./globals"; +import WasmEnableThreads from "consts:wasmEnableThreads"; + +import { threads_c_functions as tcwraps } from "./cwraps"; +import { INTERNAL, runtimeHelpers, mono_assert, loaderHelpers, ENVIRONMENT_IS_WORKER, Module } from "./globals"; import { utf8ToString } from "./strings"; import { CharPtr, VoidPtr } from "./types/emscripten"; @@ -12,9 +14,14 @@ export function set_thread_prefix (threadPrefix: string) { prefix = `[${threadPrefix}] MONO_WASM: `; } -export function mono_log_debug (msg: string, ...data: any) { +/* eslint-disable no-console */ + +export function mono_log_debug (messageFactory: string | (() => string)) { if (runtimeHelpers.diagnosticTracing) { - console.debug(prefix + msg, ...data); + const message = (typeof messageFactory === "function" + ? messageFactory() + : messageFactory); + console.debug(prefix + message); } } @@ -27,9 +34,15 @@ export function mono_log_warn (msg: string, ...data: any) { } export function mono_log_error (msg: string, ...data: any) { - if (data && data.length > 0 && data[0] && typeof data[0] === "object" && data[0].silent) { + if (data && data.length > 0 && data[0] && typeof data[0] === "object") { // don't log silent errors - return; + if (data[0].silent) { + return; + } + if (data[0].toString) { + console.error(prefix + msg, data[0].toString()); + return; + } } console.error(prefix + msg, ...data); } @@ -38,21 +51,6 @@ export const wasm_func_map = new Map(); let wasm_pending_symbol_table: string | undefined; const regexes: any[] = []; -// V8 -// at :wasm-function[1900]:0x83f63 -// at dlfree (:wasm-function[18739]:0x2328ef) -regexes.push(/at (?[^:()]+:wasm-function\[(?\d+)\]:0x[a-fA-F\d]+)((?![^)a-fA-F\d])|$)/); - -//# 5: WASM [009712b2], function #111 (''), pc=0x7c16595c973 (+0x53), pos=38740 (+11) -regexes.push(/(?:WASM \[[\da-zA-Z]+\], (?function #(?[\d]+) \(''\)))/); - -//# chrome -//# at http://127.0.0.1:63817/dotnet.wasm:wasm-function[8963]:0x1e23f4 -regexes.push(/(?[a-z]+:\/\/[^ )]*:wasm-function\[(?\d+)\]:0x[a-fA-F\d]+)/); - -//# .wasm-function[8962] -regexes.push(/(?<[^ >]+>[.:]wasm-function\[(?[0-9]+)\])/); - export function mono_wasm_symbolicate_string (message: string): string { try { performDeferredSymbolMapParsing(); @@ -123,7 +121,27 @@ export function mono_wasm_trace_logger (log_domain_ptr: CharPtr, log_level_ptr: switch (log_level) { case "critical": case "error": - console.error(mono_wasm_stringify_as_error_with_stack(message)); + { + const messageWithStack = message + "\n" + (new Error().stack); + if (!loaderHelpers.exitReason) { + loaderHelpers.exitReason = messageWithStack; + } + console.error(mono_wasm_stringify_as_error_with_stack(messageWithStack)); + if (WasmEnableThreads) { + try { + tcwraps.mono_wasm_print_thread_dump(); + } catch (e) { + console.error("Failed to print thread dump", e); + } + } + if (WasmEnableThreads && ENVIRONMENT_IS_WORKER) { + setTimeout(() => { + mono_log_error("forcing abort 3000ms after last error log message", messageWithStack); + // _emscripten_force_exit is proxied to UI thread and should also arrive in spin wait loop + Module._emscripten_force_exit(1); + }, 3000); + } + } break; case "warning": console.warn(message); @@ -150,13 +168,28 @@ export function parseSymbolMapFile (text: string) { // may be never mono_assert(!wasm_pending_symbol_table, "Another symbol map was already loaded"); wasm_pending_symbol_table = text; - mono_log_debug(`Deferred loading of ${text.length}ch symbol map`); + mono_log_debug(() => `Deferred loading of ${text.length}ch symbol map`); } function performDeferredSymbolMapParsing () { if (!wasm_pending_symbol_table) return; + // V8 + // at :wasm-function[1900]:0x83f63 + // at dlfree (:wasm-function[18739]:0x2328ef) + regexes.push(/at (?[^:()]+:wasm-function\[(?\d+)\]:0x[a-fA-F\d]+)((?![^)a-fA-F\d])|$)/); + + //# 5: WASM [009712b2], function #111 (''), pc=0x7c16595c973 (+0x53), pos=38740 (+11) + regexes.push(/(?:WASM \[[\da-zA-Z]+\], (?function #(?[\d]+) \(''\)))/); + + //# chrome + //# at http://127.0.0.1:63817/dotnet.wasm:wasm-function[8963]:0x1e23f4 + regexes.push(/(?[a-z]+:\/\/[^ )]*:wasm-function\[(?\d+)\]:0x[a-fA-F\d]+)/); + + //# .wasm-function[8962] + regexes.push(/(?<[^ >]+>[.:]wasm-function\[(?[0-9]+)\])/); + const text = wasm_pending_symbol_table!; wasm_pending_symbol_table = undefined; try { @@ -168,7 +201,7 @@ function performDeferredSymbolMapParsing () { parts[1] = parts.splice(1).join(":"); wasm_func_map.set(Number(parts[0]), parts[1]); }); - mono_log_debug(`Loaded ${wasm_func_map.size} symbols`); + mono_log_debug(() => `Loaded ${wasm_func_map.size} symbols`); } catch (exc) { mono_log_warn(`Failed to load symbol map: ${exc}`); } diff --git a/src/mono/browser/runtime/managed-exports.ts b/src/mono/browser/runtime/managed-exports.ts index 2a062aa3f134..1a34436dd166 100644 --- a/src/mono/browser/runtime/managed-exports.ts +++ b/src/mono/browser/runtime/managed-exports.ts @@ -16,7 +16,7 @@ import { assert_c_interop, assert_js_interop } from "./invoke-js"; import { monoThreadInfo, mono_wasm_main_thread_ptr } from "./pthreads"; import { _zero_region, copyBytes } from "./memory"; import { stringToUTF8Ptr } from "./strings"; -import { mono_log_debug } from "./logging"; +import { mono_log_error } from "./logging"; const managedExports: ManagedExports = {} as any; @@ -271,7 +271,7 @@ export function install_main_synchronization_context (jsThreadBlockingMode: JSTh } return get_arg_gc_handle(res) as any; } catch (e) { - mono_log_debug("install_main_synchronization_context failed", e); + mono_log_error("install_main_synchronization_context failed", e); throw e; } } diff --git a/src/mono/browser/runtime/marshal-to-cs.ts b/src/mono/browser/runtime/marshal-to-cs.ts index 360cefec509c..58db72d21dd0 100644 --- a/src/mono/browser/runtime/marshal-to-cs.ts +++ b/src/mono/browser/runtime/marshal-to-cs.ts @@ -455,7 +455,7 @@ export function marshal_array_to_cs_impl (arg: JSMarshalerArgument, value: Array set_arg_type(arg, MarshalerType.None); } else { const element_size = array_element_size(element_type); - mono_assert(element_size != -1, () => `Element type ${MarshalerType[element_type]} not supported`); + mono_assert(element_size != -1, () => `Element type ${element_type} not supported`); const length = value.length; const buffer_length = element_size * length; const buffer_ptr = Module._malloc(buffer_length); @@ -540,7 +540,7 @@ function checkViewType (element_type: MarshalerType, viewType: MemoryViewType) { } else if (element_type == MarshalerType.Double) { mono_check(MemoryViewType.Double == viewType, "Expected MemoryViewType.Double"); } else { - throw new Error(`NotImplementedException ${MarshalerType[element_type]} `); + throw new Error(`NotImplementedException ${element_type} `); } } diff --git a/src/mono/browser/runtime/marshal-to-js.ts b/src/mono/browser/runtime/marshal-to-js.ts index eb12f9b542d5..27b8f4a73f4f 100644 --- a/src/mono/browser/runtime/marshal-to-js.ts +++ b/src/mono/browser/runtime/marshal-to-js.ts @@ -302,7 +302,7 @@ function try_marshal_sync_task_to_js (arg: JSMarshalerArgument, type: MarshalerT // when we arrived here from _marshal_cs_object_to_js res_converter = cs_to_js_marshalers.get(element_type); } - mono_assert(res_converter, () => `Unknown sub_converter for type ${MarshalerType[element_type]}. ${jsinteropDoc}`); + mono_assert(res_converter, () => `Unknown sub_converter for type ${element_type}. ${jsinteropDoc}`); const val = res_converter(arg); return Promise.resolve(val); @@ -325,13 +325,13 @@ function create_task_holder (res_converter?: MarshalerToJs) { // when we arrived here from _marshal_cs_object_to_js res_converter = cs_to_js_marshalers.get(type); } - mono_assert(res_converter, () => `Unknown sub_converter for type ${MarshalerType[type]}. ${jsinteropDoc}`); + mono_assert(res_converter, () => `Unknown sub_converter for type ${type}. ${jsinteropDoc}`); const js_value = res_converter!(argInner); promise_control.resolve(js_value); } } else { - mono_assert(false, () => `Unexpected type ${MarshalerType[type]}`); + mono_assert(false, () => `Unexpected type ${type}`); } mono_wasm_release_cs_owned_object(js_handle); }); @@ -483,7 +483,7 @@ function _marshal_cs_object_to_js (arg: JSMarshalerArgument): any { // other types const converter = cs_to_js_marshalers.get(marshaler_type); - mono_assert(converter, () => `Unknown converter for type ${MarshalerType[marshaler_type]}. ${jsinteropDoc}`); + mono_assert(converter, () => `Unknown converter for type ${marshaler_type}. ${jsinteropDoc}`); return converter(arg); } @@ -498,7 +498,7 @@ function _marshal_array_to_js_impl (arg: JSMarshalerArgument, element_type: Mars return null; } const elementSize = array_element_size(element_type); - mono_assert(elementSize != -1, () => `Element type ${MarshalerType[element_type]} not supported`); + mono_assert(elementSize != -1, () => `Element type ${element_type} not supported`); const buffer_ptr = get_arg_intptr(arg); const length = get_arg_length(arg); let result: Array | TypedArray | null = null; @@ -538,7 +538,7 @@ function _marshal_array_to_js_impl (arg: JSMarshalerArgument, element_type: Mars const sourceView = localHeapViewF64().subarray(buffer_ptr >> 3, (buffer_ptr >> 3) + length); result = sourceView.slice();//copy } else { - throw new Error(`NotImplementedException ${MarshalerType[element_type]}. ${jsinteropDoc}`); + throw new Error(`NotImplementedException ${element_type}. ${jsinteropDoc}`); } Module._free(buffer_ptr); return result; @@ -557,7 +557,7 @@ function _marshal_span_to_js (arg: JSMarshalerArgument, element_type?: Marshaler } else if (element_type == MarshalerType.Double) { result = new Span(buffer_ptr, length, MemoryViewType.Double); } else { - throw new Error(`NotImplementedException ${MarshalerType[element_type]}. ${jsinteropDoc}`); + throw new Error(`NotImplementedException ${element_type}. ${jsinteropDoc}`); } return result; } @@ -575,7 +575,7 @@ function _marshal_array_segment_to_js (arg: JSMarshalerArgument, element_type?: } else if (element_type == MarshalerType.Double) { result = new ArraySegment(buffer_ptr, length, MemoryViewType.Double); } else { - throw new Error(`NotImplementedException ${MarshalerType[element_type]}. ${jsinteropDoc}`); + throw new Error(`NotImplementedException ${element_type}. ${jsinteropDoc}`); } const gc_handle = get_arg_gc_handle(arg); if (BuildConfiguration === "Debug") { diff --git a/src/mono/browser/runtime/marshal.ts b/src/mono/browser/runtime/marshal.ts index c0ece106f53b..b26a94926f88 100644 --- a/src/mono/browser/runtime/marshal.ts +++ b/src/mono/browser/runtime/marshal.ts @@ -65,9 +65,7 @@ const enum JSBindingHeaderOffsets { } export function alloc_stack_frame (size: number): JSMarshalerArguments { - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } + forceThreadMemoryViewRefresh(); const bytes = JavaScriptMarshalerArgSize * size; const args = Module.stackAlloc(bytes) as any; _zero_region(args, bytes); @@ -145,7 +143,7 @@ export function get_signature_arg2_type (sig: JSMarshalerType): MarshalerType { export function get_signature_arg3_type (sig: JSMarshalerType): MarshalerType { mono_assert(sig, "Null sig"); - return getU8(sig + JSBindingTypeOffsets.Arg2MarshalerType); + return getU8(sig + JSBindingTypeOffsets.Arg3MarshalerType); } export function get_signature_argument_count (signature: JSFunctionSignature): number { diff --git a/src/mono/browser/runtime/memory.ts b/src/mono/browser/runtime/memory.ts index 8205e6fd8098..1834bcf3b888 100644 --- a/src/mono/browser/runtime/memory.ts +++ b/src/mono/browser/runtime/memory.ts @@ -8,7 +8,7 @@ import { VoidPtr, CharPtr } from "./types/emscripten"; import cwraps, { I52Error } from "./cwraps"; import { Module, mono_assert, runtimeHelpers } from "./globals"; import { utf8ToString } from "./strings"; -import { mono_log_warn } from "./logging"; +import { mono_log_warn, mono_log_error } from "./logging"; const alloca_stack: Array = []; const alloca_buffer_size = 32 * 1024; @@ -325,7 +325,37 @@ export function withStackAlloc (bytesWanted: number, f: (pt // @bytes must be a typed array. space is allocated for it in the native heap // and it is copied to that location. returns the address of the allocation. export function mono_wasm_load_bytes_into_heap (bytes: Uint8Array): VoidPtr { - const memoryOffset = Module._malloc(bytes.length); + // pad sizes by 16 bytes for simd + const memoryOffset = Module._malloc(bytes.length + 16); + if (memoryOffset <= 0) { + mono_log_error(`malloc failed to allocate ${(bytes.length + 16)} bytes.`); + throw new Error("Out of memory"); + } + const heapBytes = new Uint8Array(localHeapViewU8().buffer, memoryOffset, bytes.length); + heapBytes.set(bytes); + return memoryOffset; +} + +// @bytes must be a typed array. space is allocated for it in memory +// and it is copied to that location. returns the address of the data. +// the result pointer *cannot* be freed because malloc is bypassed for speed. +export function mono_wasm_load_bytes_into_heap_persistent (bytes: Uint8Array): VoidPtr { + // pad sizes by 16 bytes for simd + const desiredSize = bytes.length + 16; + // sbrk doesn't allocate whole pages so we can ask it for as many bytes as we want. + let memoryOffset = Module._sbrk(desiredSize); + if (memoryOffset <= 0) { + // sbrk failed. Due to identical bugs in v8 and spidermonkey, this isn't guaranteed to be OOM. + // We use this function early during startup, when OOM shouldn't be possible anyway! + // Log a warning, then retry. + memoryOffset = Module._sbrk(desiredSize); + if (memoryOffset <= 0) { + mono_log_error(`sbrk failed to allocate ${desiredSize} bytes, and failed upon retry.`); + throw new Error("Out of memory"); + } else { + mono_log_warn(`sbrk failed to allocate ${desiredSize} bytes, but succeeded upon retry!`); + } + } const heapBytes = new Uint8Array(localHeapViewU8().buffer, memoryOffset, bytes.length); heapBytes.set(bytes); return memoryOffset; @@ -430,8 +460,8 @@ export function copyBytes (srcPtr: VoidPtr, dstPtr: VoidPtr, bytes: number): voi // on non-MT build, this will be a no-op trimmed by rollup export function receiveWorkerHeapViews () { if (!WasmEnableThreads) return; - const memory = runtimeHelpers.getMemory(); - if (memory.buffer !== Module.HEAPU8.buffer) { + const wasmMemory = runtimeHelpers.getMemory(); + if (wasmMemory.buffer !== Module.HEAPU8.buffer) { runtimeHelpers.updateMemoryViews(); } } @@ -467,5 +497,7 @@ export function forceThreadMemoryViewRefresh () { This only works because their implementation does not skip doing work even when you ask to grow by 0 pages. */ wasmMemory.grow(0); - runtimeHelpers.updateMemoryViews(); + if (wasmMemory.buffer !== Module.HEAPU8.buffer) { + runtimeHelpers.updateMemoryViews(); + } } diff --git a/src/mono/browser/runtime/pthreads/deputy-thread.ts b/src/mono/browser/runtime/pthreads/deputy-thread.ts index 4b514b28a4ae..1e2041fa44da 100644 --- a/src/mono/browser/runtime/pthreads/deputy-thread.ts +++ b/src/mono/browser/runtime/pthreads/deputy-thread.ts @@ -8,8 +8,10 @@ import { mono_log_error, mono_log_info } from "../logging"; import { monoThreadInfo, postMessageToMain, update_thread_info } from "./shared"; import { Module, loaderHelpers, runtimeHelpers } from "../globals"; import { start_runtime } from "../startup"; -import { WorkerToMainMessageType } from "../types/internal"; +import { MainToWorkerMessageType, WorkerToMainMessageType } from "../types/internal"; import { forceThreadMemoryViewRefresh } from "../memory"; +import { install_main_synchronization_context } from "../managed-exports"; +import { pthread_self } from "./worker-thread"; export function mono_wasm_start_deputy_thread_async () { if (!WasmEnableThreads) return; @@ -31,11 +33,26 @@ export function mono_wasm_start_deputy_thread_async () { try { forceThreadMemoryViewRefresh(); + pthread_self.addEventListenerFromBrowser((message) => { + if (message.data.cmd == MainToWorkerMessageType.allAssetsLoaded) { + runtimeHelpers.allAssetsInMemory.promise_control.resolve(); + } + }); + await start_runtime(); postMessageToMain({ monoCmd: WorkerToMainMessageType.deputyStarted, info: monoThreadInfo, + }); + + await runtimeHelpers.allAssetsInMemory.promise; + + runtimeHelpers.proxyGCHandle = install_main_synchronization_context(runtimeHelpers.config.jsThreadBlockingMode!); + + postMessageToMain({ + monoCmd: WorkerToMainMessageType.deputyReady, + info: monoThreadInfo, deputyProxyGCHandle: runtimeHelpers.proxyGCHandle, }); } catch (err) { diff --git a/src/mono/browser/runtime/pthreads/index.ts b/src/mono/browser/runtime/pthreads/index.ts index 3678d709d105..87ed1b006184 100644 --- a/src/mono/browser/runtime/pthreads/index.ts +++ b/src/mono/browser/runtime/pthreads/index.ts @@ -5,13 +5,14 @@ import { mono_log_warn } from "../logging"; import { utf16ToString } from "../strings"; export { - mono_wasm_main_thread_ptr, mono_wasm_install_js_worker_interop, mono_wasm_uninstall_js_worker_interop, + mono_wasm_main_thread_ptr, mono_wasm_pthread_ptr, update_thread_info, isMonoThreadMessage, monoThreadInfo, } from "./shared"; +export { mono_wasm_install_js_worker_interop, mono_wasm_uninstall_js_worker_interop } from "./worker-interop"; export { - mono_wasm_dump_threads, cancelThreads, is_thread_available, - populateEmscriptenPool, mono_wasm_init_threads, init_finalizer_thread, - waitForThread, replaceEmscriptenPThreadUI + mono_wasm_dump_threads, postCancelThreads, + populateEmscriptenPool, mono_wasm_init_threads, + waitForThread, replaceEmscriptenPThreadUI, terminateAllThreads, } from "./ui-thread"; export { mono_wasm_pthread_on_pthread_attached, mono_wasm_pthread_on_pthread_unregistered, diff --git a/src/mono/browser/runtime/pthreads/shared.ts b/src/mono/browser/runtime/pthreads/shared.ts index f72804fbcf87..69137957eeee 100644 --- a/src/mono/browser/runtime/pthreads/shared.ts +++ b/src/mono/browser/runtime/pthreads/shared.ts @@ -6,11 +6,9 @@ import BuildConfiguration from "consts:configuration"; import type { GCHandle, MonoThreadMessage, PThreadInfo, PThreadPtr } from "../types/internal"; -import { ENVIRONMENT_IS_PTHREAD, Module, loaderHelpers, mono_assert, runtimeHelpers } from "../globals"; +import { Module, loaderHelpers, runtimeHelpers } from "../globals"; import { set_thread_prefix } from "../logging"; -import { bindings_init } from "../startup"; -import { forceDisposeProxies } from "../gc-handles"; -import { monoMessageSymbol, GCHandleNull, PThreadPtrNull, WorkerToMainMessageType } from "../types/internal"; +import { monoMessageSymbol, PThreadPtrNull, WorkerToMainMessageType } from "../types/internal"; import { threads_c_functions as tcwraps } from "../cwraps"; import { forceThreadMemoryViewRefresh } from "../memory"; @@ -34,39 +32,6 @@ export function isMonoThreadMessage (x: unknown): x is MonoThreadMessage { return typeof (xmsg.type) === "string" && typeof (xmsg.cmd) === "string"; } -export function mono_wasm_install_js_worker_interop (context_gc_handle: GCHandle): void { - if (!WasmEnableThreads) return; - bindings_init(); - mono_assert(!runtimeHelpers.proxyGCHandle, "JS interop should not be already installed on this worker."); - runtimeHelpers.proxyGCHandle = context_gc_handle; - if (ENVIRONMENT_IS_PTHREAD) { - runtimeHelpers.managedThreadTID = runtimeHelpers.currentThreadTID; - runtimeHelpers.isManagedRunningOnCurrentThread = true; - } - Module.runtimeKeepalivePush(); - monoThreadInfo.isDirtyBecauseOfInterop = true; - update_thread_info(); - if (ENVIRONMENT_IS_PTHREAD) { - postMessageToMain({ - monoCmd: WorkerToMainMessageType.enabledInterop, - info: monoThreadInfo, - }); - } -} - -export function mono_wasm_uninstall_js_worker_interop (): void { - if (!WasmEnableThreads) return; - mono_assert(runtimeHelpers.mono_wasm_bindings_is_ready, "JS interop is not installed on this worker."); - mono_assert(runtimeHelpers.proxyGCHandle, "JSSynchronizationContext is not installed on this worker."); - - forceDisposeProxies(true, runtimeHelpers.diagnosticTracing); - Module.runtimeKeepalivePop(); - - runtimeHelpers.proxyGCHandle = GCHandleNull; - runtimeHelpers.mono_wasm_bindings_is_ready = false; - update_thread_info(); -} - // this is just for Debug build of the runtime, making it easier to debug worker threads export function update_thread_info (): void { if (!WasmEnableThreads) return; @@ -112,7 +77,11 @@ export function exec_synchronization_context_pump (): void { return; } forceThreadMemoryViewRefresh(); - tcwraps.mono_wasm_synchronization_context_pump(); + try { + tcwraps.mono_wasm_synchronization_context_pump(); + } catch (ex) { + loaderHelpers.mono_exit(1, ex); + } } export function mono_wasm_schedule_synchronization_context (): void { diff --git a/src/mono/browser/runtime/pthreads/ui-thread.ts b/src/mono/browser/runtime/pthreads/ui-thread.ts index 14a7c9353b2f..505f1d813907 100644 --- a/src/mono/browser/runtime/pthreads/ui-thread.ts +++ b/src/mono/browser/runtime/pthreads/ui-thread.ts @@ -8,8 +8,7 @@ import { } from "../globals"; import { MonoWorkerToMainMessage, monoThreadInfo, mono_wasm_pthread_ptr, update_thread_info, worker_empty_prefix } from "./shared"; import { Module, ENVIRONMENT_IS_WORKER, createPromiseController, loaderHelpers, mono_assert, runtimeHelpers } from "../globals"; import { PThreadLibrary, MainToWorkerMessageType, MonoThreadMessage, PThreadInfo, PThreadPtr, PThreadPtrNull, PThreadWorker, PromiseController, Thread, WorkerToMainMessageType, monoMessageSymbol } from "../types/internal"; -import { mono_log_error, mono_log_info, mono_log_debug } from "../logging"; -import { threads_c_functions as cwraps } from "../cwraps"; +import { mono_log_info, mono_log_debug, mono_log_warn } from "../logging"; const threadPromises: Map[]> = new Map(); @@ -97,7 +96,11 @@ function monoWorkerMessageHandler (worker: PThreadWorker, ev: MessageEvent) worker.info = Object.assign(worker.info!, message.info, {}); break; case WorkerToMainMessageType.deputyStarted: - runtimeHelpers.afterMonoStarted.promise_control.resolve(message.deputyProxyGCHandle); + runtimeHelpers.deputyWorker = worker; + runtimeHelpers.afterMonoStarted.promise_control.resolve(); + break; + case WorkerToMainMessageType.deputyReady: + runtimeHelpers.afterDeputyReady.promise_control.resolve(message.deputyProxyGCHandle); break; case WorkerToMainMessageType.ioStarted: runtimeHelpers.afterIOStarted.promise_control.resolve(); @@ -129,13 +132,14 @@ export function onWorkerLoadInitiated (worker: PThreadWorker, loaded: Promise { if (!WasmEnableThreads) return; const unused = getUnusedWorkerPool(); - for (const worker of loaderHelpers.loadingWorkers) { + const loadingWorkers = await loaderHelpers.loadingWorkers.promise; + for (const worker of loadingWorkers) { unused.push(worker); } - loaderHelpers.loadingWorkers = []; + loadingWorkers.length = 0; } export async function mono_wasm_init_threads () { @@ -154,11 +158,13 @@ export async function mono_wasm_init_threads () { if (workers.length > 0) { const promises = workers.map(loadWasmModuleToWorker); await Promise.all(promises); + } else { + mono_log_warn("No workers in the pthread pool, please validate the pthreadPoolInitialSize"); } } // when we create threads with browser event loop, it's not able to be joined by mono's thread join during shutdown and blocks process exit -export function cancelThreads () { +export function postCancelThreads () { if (!WasmEnableThreads) return; const workers: PThreadWorker[] = getRunningWorkers(); for (const worker of workers) { @@ -202,22 +208,6 @@ export function mono_wasm_dump_threads (): void { }); } -export function init_finalizer_thread () { - // we don't need it immediately, so we can wait a bit, to keep CPU working on normal startup - setTimeout(() => { - try { - if (loaderHelpers.is_runtime_running()) { - cwraps.mono_wasm_init_finalizer_thread(); - } else { - mono_log_debug("init_finalizer_thread skipped"); - } - } catch (err) { - mono_log_error("init_finalizer_thread() failed", err); - loaderHelpers.mono_exit(1, err); - } - }, loaderHelpers.config.finalizerThreadStartDelayMs); -} - export function replaceEmscriptenPThreadUI (modulePThread: PThreadLibrary): void { if (!WasmEnableThreads) return; @@ -226,9 +216,6 @@ export function replaceEmscriptenPThreadUI (modulePThread: PThreadLibrary): void modulePThread.loadWasmModuleToWorker = (worker: PThreadWorker): Promise => { const afterLoaded = originalLoadWasmModuleToWorker(worker); - afterLoaded.then(() => { - availableThreadCount++; - }); onWorkerLoadInitiated(worker, afterLoaded); if (loaderHelpers.config.exitOnUnhandledError) { worker.onerror = (e) => { @@ -258,7 +245,6 @@ export function replaceEmscriptenPThreadUI (modulePThread: PThreadLibrary): void } })); } else { - availableThreadCount++; originalReturnWorkerToPool(worker); } }; @@ -268,20 +254,13 @@ export function replaceEmscriptenPThreadUI (modulePThread: PThreadLibrary): void } } -let availableThreadCount = 0; -export function is_thread_available () { - if (!WasmEnableThreads) return true; - return availableThreadCount > 0; -} - function getNewWorker (modulePThread: PThreadLibrary): PThreadWorker { if (!WasmEnableThreads) return null as any; if (modulePThread.unusedWorkers.length == 0) { - mono_log_debug(`Failed to find unused WebWorker, this may deadlock. Please increase the pthreadPoolReady. Running threads ${modulePThread.runningWorkers.length}. Loading workers: ${modulePThread.unusedWorkers.length}`); + mono_log_debug(() => `Failed to find unused WebWorker, this may deadlock. Please increase the pthreadPoolInitialSize. Running threads ${modulePThread.runningWorkers.length}. Loading workers: ${modulePThread.unusedWorkers.length}`); const worker = allocateUnusedWorker(); modulePThread.loadWasmModuleToWorker(worker); - availableThreadCount--; return worker; } @@ -295,12 +274,10 @@ function getNewWorker (modulePThread: PThreadLibrary): PThreadWorker { const worker = modulePThread.unusedWorkers[i]; if (worker.loaded) { modulePThread.unusedWorkers.splice(i, 1); - availableThreadCount--; return worker; } } - mono_log_debug(`Failed to find loaded WebWorker, this may deadlock. Please increase the pthreadPoolReady. Running threads ${modulePThread.runningWorkers.length}. Loading workers: ${modulePThread.unusedWorkers.length}`); - availableThreadCount--; // negative value + mono_log_debug(() => `Failed to find loaded WebWorker, this may deadlock. Please increase the pthreadPoolInitialSize. Running threads ${modulePThread.runningWorkers.length}. Loading workers: ${modulePThread.unusedWorkers.length}`); return modulePThread.unusedWorkers.pop()!; } @@ -340,6 +317,10 @@ export function getRunningWorkers (): PThreadWorker[] { return getModulePThread().runningWorkers; } +export function terminateAllThreads (): void { + getModulePThread().terminateAllThreads(); +} + export function loadWasmModuleToWorker (worker: PThreadWorker): Promise { return getModulePThread().loadWasmModuleToWorker(worker); } diff --git a/src/mono/browser/runtime/pthreads/worker-interop.ts b/src/mono/browser/runtime/pthreads/worker-interop.ts new file mode 100644 index 000000000000..35a8ff61a8a1 --- /dev/null +++ b/src/mono/browser/runtime/pthreads/worker-interop.ts @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +import WasmEnableThreads from "consts:wasmEnableThreads"; + +import type { GCHandle } from "../types/internal"; + +import { ENVIRONMENT_IS_PTHREAD, Module, mono_assert, runtimeHelpers } from "../globals"; +import { bindings_init } from "../startup"; +import { forceDisposeProxies } from "../gc-handles"; +import { GCHandleNull, WorkerToMainMessageType } from "../types/internal"; +import { monoThreadInfo, postMessageToMain, update_thread_info } from "./shared"; + +export function mono_wasm_install_js_worker_interop (context_gc_handle: GCHandle): void { + if (!WasmEnableThreads) return; + bindings_init(); + mono_assert(!runtimeHelpers.proxyGCHandle, "JS interop should not be already installed on this worker."); + runtimeHelpers.proxyGCHandle = context_gc_handle; + if (ENVIRONMENT_IS_PTHREAD) { + runtimeHelpers.managedThreadTID = runtimeHelpers.currentThreadTID; + runtimeHelpers.isManagedRunningOnCurrentThread = true; + } + Module.runtimeKeepalivePush(); + monoThreadInfo.isDirtyBecauseOfInterop = true; + update_thread_info(); + if (ENVIRONMENT_IS_PTHREAD) { + postMessageToMain({ + monoCmd: WorkerToMainMessageType.enabledInterop, + info: monoThreadInfo, + }); + } +} + +export function mono_wasm_uninstall_js_worker_interop (): void { + if (!WasmEnableThreads) return; + mono_assert(runtimeHelpers.mono_wasm_bindings_is_ready, "JS interop is not installed on this worker."); + mono_assert(runtimeHelpers.proxyGCHandle, "JSSynchronizationContext is not installed on this worker."); + + forceDisposeProxies(true, runtimeHelpers.diagnosticTracing); + Module.runtimeKeepalivePop(); + + runtimeHelpers.proxyGCHandle = GCHandleNull; + runtimeHelpers.mono_wasm_bindings_is_ready = false; + update_thread_info(); +} diff --git a/src/mono/browser/runtime/pthreads/worker-thread.ts b/src/mono/browser/runtime/pthreads/worker-thread.ts index fa1269c300cb..75b249812d33 100644 --- a/src/mono/browser/runtime/pthreads/worker-thread.ts +++ b/src/mono/browser/runtime/pthreads/worker-thread.ts @@ -65,7 +65,7 @@ export function initWorkerThreadEvents () { // this is the message handler for the worker that receives messages from the main thread // extend this with new cases as needed function monoDedicatedChannelMessageFromMainToWorker (event: MessageEvent): void { - mono_log_debug("got message from main on the dedicated channel", event.data); + mono_log_debug(() => `got message from main on the dedicated channel ${event.data}`); } export function on_emscripten_thread_init (pthread_ptr: PThreadPtr) { diff --git a/src/mono/browser/runtime/rollup.config.js b/src/mono/browser/runtime/rollup.config.js index cf7b9dfcbea1..5b7c10266bf9 100644 --- a/src/mono/browser/runtime/rollup.config.js +++ b/src/mono/browser/runtime/rollup.config.js @@ -14,7 +14,7 @@ import gitCommitInfo from "git-commit-info"; import MagicString from "magic-string"; const configuration = process.env.Configuration; -const isDebug = configuration !== "Release"; +const isDebug = false; const isContinuousIntegrationBuild = process.env.ContinuousIntegrationBuild === "true" ? true : false; const productVersion = process.env.ProductVersion || "8.0.0-dev"; const nativeBinDir = process.env.NativeBinDir ? process.env.NativeBinDir.replace(/"/g, "") : "bin"; @@ -69,7 +69,18 @@ const inlineAssert = [ // eslint-disable-next-line quotes pattern: 'mono_assert\\(([^,]*), \\(\\) => *`([^`]*)`\\);', replacement: (match) => `if (!(${match[1]})) mono_assert(false, \`${match[2]}\`); // inlined mono_assert condition` - } + }, + { + // eslint-disable-next-line quotes + pattern: 'mono_log_debug\\(*"([^"]*)"\\);', + // eslint-disable-next-line quotes + replacement: (match) => `if (loaderHelpers.diagnosticTracing) mono_log_debug("${match[1]}"); // inlined mono_log_debug condition` + }, + { + // eslint-disable-next-line quotes + pattern: 'mono_log_debug\\(\\(\\) => *`([^`]*)`\\);', + replacement: (match) => `if (loaderHelpers.diagnosticTracing) mono_log_debug(\`${match[1]}\`); // inlined mono_log_debug condition` + }, ]; const checkAssert = { @@ -216,6 +227,20 @@ const typesConfig = { plugins: [dts()], onwarn: onwarn }; +const hybridGlobalizationConfig = { + input: "./hybrid-globalization/module-exports.ts", + output: [ + { + format: "es", + file: nativeBinDir + "/dotnet.globalization.js", + banner, + sourcemap: true, + sourcemapPathTransform, + } + ], + plugins: [...outputCodePlugins], + onwarn: onwarn +}; let diagnosticMockTypesConfig = undefined; @@ -271,7 +296,9 @@ const allConfigs = [ runtimeConfig, wasmImportsConfig, typesConfig, -].concat(workerConfigs) + hybridGlobalizationConfig, +] + .concat(workerConfigs) .concat(diagnosticMockTypesConfig ? [diagnosticMockTypesConfig] : []); export default defineConfig(allConfigs); diff --git a/src/mono/browser/runtime/run.ts b/src/mono/browser/runtime/run.ts index 0a16ce45d533..b3f784124b7b 100644 --- a/src/mono/browser/runtime/run.ts +++ b/src/mono/browser/runtime/run.ts @@ -5,12 +5,12 @@ import NativeAOT from "consts:nativeAOT"; import WasmEnableThreads from "consts:wasmEnableThreads"; -import { ENVIRONMENT_IS_NODE, Module, loaderHelpers, mono_assert, runtimeHelpers } from "./globals"; +import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_WORKER, Module, loaderHelpers, mono_assert, runtimeHelpers } from "./globals"; import { mono_wasm_wait_for_debugger } from "./debug"; import { mono_wasm_set_main_args } from "./startup"; import cwraps from "./cwraps"; -import { mono_log_info } from "./logging"; -import { cancelThreads } from "./pthreads"; +import { mono_log_error, mono_log_info, mono_wasm_stringify_as_error_with_stack } from "./logging"; +import { postCancelThreads, terminateAllThreads } from "./pthreads"; import { call_entry_point } from "./managed-exports"; /** @@ -83,16 +83,35 @@ export async function mono_run_main (main_assembly_name?: string, args?: string[ export function nativeExit (code: number) { - if (WasmEnableThreads) { - cancelThreads(); + if (runtimeHelpers.runtimeReady) { + runtimeHelpers.runtimeReady = false; + if (WasmEnableThreads) { + postCancelThreads(); + } + cwraps.mono_wasm_exit(code); } - cwraps.mono_wasm_exit(code); } export function nativeAbort (reason: any) { loaderHelpers.exitReason = reason; - if (!loaderHelpers.is_exited()) { - cwraps.mono_wasm_abort(); + if (runtimeHelpers.runtimeReady) { + runtimeHelpers.runtimeReady = false; + if (WasmEnableThreads) { + if (!ENVIRONMENT_IS_WORKER) { + terminateAllThreads(); + } else { + // just in case if the UI thread is blocked, we need to force exit + // if UI thread receives message from Module.abort below, this thread will be terminated earlier + setTimeout(() => { + mono_log_error("forcing abort 3000ms after nativeAbort attempt", reason); + // _emscripten_force_exit is proxied to UI thread and should also arrive in spin wait loop + Module._emscripten_force_exit(1); + }, 3000); + } + } + + const reasonString = mono_wasm_stringify_as_error_with_stack(reason); + Module.abort(reasonString); } throw reason; } diff --git a/src/mono/browser/runtime/runtime.c b/src/mono/browser/runtime/runtime.c index 7dbdc02c2599..436c3a295863 100644 --- a/src/mono/browser/runtime/runtime.c +++ b/src/mono/browser/runtime/runtime.c @@ -65,6 +65,7 @@ int mono_wasm_enable_gc = 1; /* Missing from public headers */ +char *mono_fixup_symbol_name (const char *prefix, const char *key, const char *suffix); void mono_icall_table_init (void); void mono_wasm_enable_debugging (int); void mono_ee_interp_init (const char *opts); @@ -213,13 +214,9 @@ get_native_to_interp (MonoMethod *method, void *extra_arg) assert (strlen (name) < 100); snprintf (key, sizeof(key), "%s_%s_%s", name, class_name, method_name); - len = strlen (key); - for (int i = 0; i < len; ++i) { - if (key [i] == '.') - key [i] = '_'; - } - - addr = wasm_dl_get_native_to_interp (key, extra_arg); + char *fixedName = mono_fixup_symbol_name ("", key, ""); + addr = wasm_dl_get_native_to_interp (fixedName, extra_arg); + free (fixedName); MONO_EXIT_GC_UNSAFE; return addr; } @@ -229,6 +226,14 @@ static void *sysglobal_native_handle; static void* wasm_dl_load (const char *name, int flags, char **err, void *user_data) { +#if WASM_SUPPORTS_DLOPEN + if (!name) + return dlopen(NULL, flags); +#else + if (!name) + return NULL; +#endif + void* handle = wasm_dl_lookup_pinvoke_table (name); if (handle) return handle; diff --git a/src/mono/browser/runtime/scheduling.ts b/src/mono/browser/runtime/scheduling.ts index 35552123845a..62c02961c5ce 100644 --- a/src/mono/browser/runtime/scheduling.ts +++ b/src/mono/browser/runtime/scheduling.ts @@ -35,20 +35,28 @@ function prevent_timer_throttling_tick () { if (!loaderHelpers.is_runtime_running()) { return; } - cwraps.mono_wasm_execute_timer(); - pump_count++; + try { + cwraps.mono_wasm_execute_timer(); + pump_count++; + } catch (ex) { + loaderHelpers.mono_exit(1, ex); + } mono_background_exec_until_done(); } function mono_background_exec_until_done () { if (WasmEnableThreads) return; Module.maybeExit(); - if (!loaderHelpers.is_runtime_running()) { - return; - } - while (pump_count > 0) { - --pump_count; - cwraps.mono_background_exec(); + try { + while (pump_count > 0) { + --pump_count; + if (!loaderHelpers.is_runtime_running()) { + return; + } + cwraps.mono_background_exec(); + } + } catch (ex) { + loaderHelpers.mono_exit(1, ex); } } @@ -71,12 +79,15 @@ export function mono_wasm_schedule_timer (shortestDueTimeMs: number): void { function mono_wasm_schedule_timer_tick () { if (WasmEnableThreads) return; Module.maybeExit(); - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } + forceThreadMemoryViewRefresh(); if (!loaderHelpers.is_runtime_running()) { return; } lastScheduledTimeoutId = undefined; - cwraps.mono_wasm_execute_timer(); + try { + cwraps.mono_wasm_execute_timer(); + pump_count++; + } catch (ex) { + loaderHelpers.mono_exit(1, ex); + } } diff --git a/src/mono/browser/runtime/startup.ts b/src/mono/browser/runtime/startup.ts index 086a4b33d4b6..0662ac26f1b0 100644 --- a/src/mono/browser/runtime/startup.ts +++ b/src/mono/browser/runtime/startup.ts @@ -6,7 +6,7 @@ import NativeAOT from "consts:nativeAOT"; import WasmEnableThreads from "consts:wasmEnableThreads"; import BuildConfiguration from "consts:configuration"; -import { DotnetModuleInternal, CharPtrNull } from "./types/internal"; +import { DotnetModuleInternal, CharPtrNull, MainToWorkerMessageType } from "./types/internal"; import { exportedRuntimeAPI, INTERNAL, loaderHelpers, Module, runtimeHelpers, createPromiseController, mono_assert } from "./globals"; import cwraps, { init_c_exports, threads_c_functions as tcwraps } from "./cwraps"; import { mono_wasm_raise_debug_event, mono_wasm_runtime_ready } from "./debug"; @@ -16,7 +16,7 @@ import { initialize_marshalers_to_cs } from "./marshal-to-cs"; import { initialize_marshalers_to_js } from "./marshal-to-js"; import { init_polyfills_async } from "./polyfills"; import { strings_init, utf8ToString } from "./strings"; -import { init_managed_exports, install_main_synchronization_context } from "./managed-exports"; +import { init_managed_exports } from "./managed-exports"; import { cwraps_internal } from "./exports-internal"; import { CharPtr, InstantiateWasmCallBack, InstantiateWasmSuccessCallback } from "./types/emscripten"; import { wait_for_all_assets } from "./assets"; @@ -26,7 +26,7 @@ import { interp_pgo_load_data, interp_pgo_save_data } from "./interp-pgo"; import { mono_log_debug, mono_log_error, mono_log_info, mono_log_warn } from "./logging"; // threads -import { populateEmscriptenPool, mono_wasm_init_threads, init_finalizer_thread } from "./pthreads"; +import { populateEmscriptenPool, mono_wasm_init_threads } from "./pthreads"; import { currentWorkerThreadEvents, dotnetPthreadCreated, initWorkerThreadEvents, monoThreadInfo } from "./pthreads"; import { mono_wasm_pthread_ptr, update_thread_info } from "./pthreads"; import { jiterpreter_allocate_tables } from "./jiterpreter-support"; @@ -37,7 +37,23 @@ import { nativeAbort, nativeExit } from "./run"; import { mono_wasm_init_diagnostics } from "./diagnostics"; import { replaceEmscriptenPThreadInit } from "./pthreads/worker-thread"; -export async function configureRuntimeStartup (): Promise { +export async function configureRuntimeStartup (module: DotnetModuleInternal): Promise { + if (!module.out) { + // eslint-disable-next-line no-console + module.out = console.log.bind(console); + } + if (!module.err) { + // eslint-disable-next-line no-console + module.err = console.error.bind(console); + } + if (!module.print) { + module.print = module.out; + } + if (!module.printErr) { + module.printErr = module.err; + } + loaderHelpers.out = module.print; + loaderHelpers.err = module.printErr; await init_polyfills_async(); } @@ -51,17 +67,6 @@ export function configureEmscriptenStartup (module: DotnetModuleInternal): void module.locateFile = module.__locateFile = (path) => loaderHelpers.scriptDirectory + path; } - if (!module.out) { - // eslint-disable-next-line no-console - module.out = console.log.bind(console); - } - - if (!module.err) { - // eslint-disable-next-line no-console - module.err = console.error.bind(console); - } - loaderHelpers.out = module.out; - loaderHelpers.err = module.err; module.mainScriptUrlOrBlob = loaderHelpers.scriptUrl;// this is needed by worker threads // these all could be overridden on DotnetModuleConfig, we are chaing them to async below, as opposed to emscripten @@ -200,6 +205,8 @@ export function preRunWorker () { const mark = startMeasure(); try { jiterpreter_allocate_tables(); // this will return quickly if already allocated + runtimeHelpers.nativeExit = nativeExit; + runtimeHelpers.nativeAbort = nativeAbort; runtimeHelpers.runtimeReady = true; // signal next stage runtimeHelpers.afterPreRun.promise_control.resolve(); @@ -250,23 +257,24 @@ async function onRuntimeInitializedAsync (userOnRuntimeInitialized: () => void) threadsReady = mono_wasm_init_threads(); } - await wait_for_all_assets(); + await runtimeHelpers.coreAssetsInMemory.promise; if (runtimeHelpers.config.virtualWorkingDirectory) { const FS = Module.FS; const cwd = runtimeHelpers.config.virtualWorkingDirectory; - const wds = FS.stat(cwd); - if (!wds) { + try { + const wds = FS.stat(cwd); + if (!wds) { + Module.FS_createPath("/", cwd, true, true); + } else { + mono_assert(wds && FS.isDir(wds.mode), () => `FS.chdir: ${cwd} is not a directory`); + } + } catch (e) { Module.FS_createPath("/", cwd, true, true); } - mono_assert(wds && FS.isDir(wds.mode), () => `FS.chdir: ${cwd} is not a directory`); FS.chdir(cwd); } - if (WasmEnableThreads && threadsReady) { - await threadsReady; - } - if (runtimeHelpers.config.interpreterPgo) setTimeout(maybeSaveInterpPgoTable, (runtimeHelpers.config.interpreterPgoSaveDelay || 15) * 1000); @@ -277,12 +285,16 @@ async function onRuntimeInitializedAsync (userOnRuntimeInitialized: () => void) }, 3000); if (WasmEnableThreads) { + await threadsReady; + // this will create thread and call start_runtime() on it runtimeHelpers.monoThreadInfo = monoThreadInfo; runtimeHelpers.isManagedRunningOnCurrentThread = false; update_thread_info(); runtimeHelpers.managedThreadTID = tcwraps.mono_wasm_create_deputy_thread(); - runtimeHelpers.proxyGCHandle = await runtimeHelpers.afterMonoStarted.promise; + + // await mono started on deputy thread + await runtimeHelpers.afterMonoStarted.promise; runtimeHelpers.ioThreadTID = tcwraps.mono_wasm_create_io_thread(); // TODO make UI thread not managed/attached https://github.com/dotnet/runtime/issues/100411 @@ -294,6 +306,8 @@ async function onRuntimeInitializedAsync (userOnRuntimeInitialized: () => void) update_thread_info(); bindings_init(); + tcwraps.mono_wasm_init_finalizer_thread(); + runtimeHelpers.disableManagedTransition = true; } else { // load mono runtime and apply environment settings (if necessary) @@ -304,6 +318,16 @@ async function onRuntimeInitializedAsync (userOnRuntimeInitialized: () => void) await runtimeHelpers.afterIOStarted.promise; } + await wait_for_all_assets(); + + if (WasmEnableThreads) { + runtimeHelpers.deputyWorker.thread!.postMessageToWorker({ + type:"deputyThread", + cmd: MainToWorkerMessageType.allAssetsLoaded, + }); + runtimeHelpers.proxyGCHandle = await runtimeHelpers.afterDeputyReady.promise; + } + runtimeList.registerRuntime(exportedRuntimeAPI); if (!runtimeHelpers.mono_wasm_runtime_is_ready) mono_wasm_runtime_ready(); @@ -413,7 +437,7 @@ async function mono_wasm_pre_init_essential_async (): Promise { Module.addRunDependency("mono_wasm_pre_init_essential_async"); if (WasmEnableThreads) { - populateEmscriptenPool(); + await populateEmscriptenPool(); } Module.removeRunDependency("mono_wasm_pre_init_essential_async"); @@ -545,15 +569,11 @@ export async function start_runtime () { monoThreadInfo.isRegistered = true; runtimeHelpers.currentThreadTID = monoThreadInfo.pthreadId = runtimeHelpers.managedThreadTID = mono_wasm_pthread_ptr(); update_thread_info(); - runtimeHelpers.proxyGCHandle = install_main_synchronization_context(runtimeHelpers.config.jsThreadBlockingMode!); runtimeHelpers.isManagedRunningOnCurrentThread = true; - - // start finalizer thread, lazy - init_finalizer_thread(); } // get GCHandle of the ctx - runtimeHelpers.afterMonoStarted.promise_control.resolve(runtimeHelpers.proxyGCHandle); + runtimeHelpers.afterMonoStarted.promise_control.resolve(); if (runtimeHelpers.config.interpreterPgo) { await interp_pgo_load_data(); diff --git a/src/mono/browser/runtime/strings.ts b/src/mono/browser/runtime/strings.ts index a596b4e35ef5..0eda60ba850a 100644 --- a/src/mono/browser/runtime/strings.ts +++ b/src/mono/browser/runtime/strings.ts @@ -39,19 +39,20 @@ export function strings_init (): void { export function stringToUTF8 (str: string): Uint8Array { if (_text_encoder_utf8 === undefined) { - const buffer = new Uint8Array(str.length * 2); - Module.stringToUTF8Array(str, buffer, 0, str.length * 2); + const len = Module.lengthBytesUTF8(str); + const buffer = new Uint8Array(len); + Module.stringToUTF8Array(str, buffer, 0, len); return buffer; } return _text_encoder_utf8.encode(str); } export function stringToUTF8Ptr (str: string): CharPtr { - const bytes = (str.length + 1) * 2; - const ptr = Module._malloc(bytes) as any; - _zero_region(ptr, str.length * 2); - const buffer = localHeapViewU8().subarray(ptr, ptr + bytes); - buffer.set(stringToUTF8(str)); + const size = Module.lengthBytesUTF8(str) + 1; + const ptr = Module._malloc(size) as any; + const buffer = localHeapViewU8().subarray(ptr, ptr + size); + Module.stringToUTF8Array(str, buffer, 0, size); + buffer[size - 1] = 0; return ptr; } diff --git a/src/mono/browser/runtime/types/emscripten.ts b/src/mono/browser/runtime/types/emscripten.ts index a9691cde4906..bb630df0b32e 100644 --- a/src/mono/browser/runtime/types/emscripten.ts +++ b/src/mono/browser/runtime/types/emscripten.ts @@ -26,6 +26,7 @@ export declare interface EmscriptenModule { // this should match emcc -s EXPORTED_FUNCTIONS _malloc(size: number): VoidPtr; _free(ptr: VoidPtr): void; + _sbrk(size: number): VoidPtr; // this should match emcc -s EXPORTED_RUNTIME_METHODS out(message: string): void; @@ -39,6 +40,7 @@ export declare interface EmscriptenModule { UTF8ToString(ptr: CharPtr, maxBytesToRead?: number): string; UTF8ArrayToString(u8Array: Uint8Array, idx?: number, maxBytesToRead?: number): string; stringToUTF8Array(str: string, heap: Uint8Array, outIdx: number, maxBytesToWrite: number): void; + lengthBytesUTF8(str: string): number; FS_createPath(parent: string, path: string, canRead?: boolean, canWrite?: boolean): string; FS_createDataFile(parent: string, name: string, data: TypedArray, canRead: boolean, canWrite: boolean, canOwn?: boolean): string; addFunction(fn: Function, signature: string): number; diff --git a/src/mono/browser/runtime/types/index.ts b/src/mono/browser/runtime/types/index.ts index 73b9f9a2dee6..d4417065b833 100644 --- a/src/mono/browser/runtime/types/index.ts +++ b/src/mono/browser/runtime/types/index.ts @@ -148,10 +148,6 @@ export type MonoConfig = { * number of unused workers kept in the emscripten pthread pool after startup */ pthreadPoolUnusedSize?: number, - /** - * Delay in milliseconds before starting the finalizer thread - */ - finalizerThreadStartDelayMs?: number, /** * If true, a list of the methods optimized by the interpreter will be saved and used for faster startup * on future runs of the application @@ -203,11 +199,14 @@ export type ResourceExtensions = { [extensionName: string]: ResourceList }; export interface ResourceGroups { hash?: string; + coreAssembly?: ResourceList; // nullable only temporarily assembly?: ResourceList; // nullable only temporarily lazyAssembly?: ResourceList; // nullable only temporarily + corePdb?: ResourceList; pdb?: ResourceList; jsModuleWorker?: ResourceList; + jsModuleGlobalization?: ResourceList; jsModuleNative: ResourceList; jsModuleRuntime: ResourceList; wasmSymbols?: ResourceList; @@ -220,6 +219,7 @@ export interface ResourceGroups { modulesAfterRuntimeReady?: ResourceList extensions?: ResourceExtensions + coreVfs?: { [virtualPath: string]: ResourceList }; vfs?: { [virtualPath: string]: ResourceList }; } @@ -321,6 +321,10 @@ export type SingleAssetBehaviors = * The javascript module for emscripten. */ | "js-module-native" + /** + * The javascript module for hybrid globalization. + */ + | "js-module-globalization" /** * Typically blazor.boot.json */ diff --git a/src/mono/browser/runtime/types/internal.ts b/src/mono/browser/runtime/types/internal.ts index 0e564f8c8728..827c9787af27 100644 --- a/src/mono/browser/runtime/types/internal.ts +++ b/src/mono/browser/runtime/types/internal.ts @@ -111,6 +111,7 @@ export interface AssetEntryInternal extends AssetEntry { pendingDownloadInternal?: LoadingResource noCache?: boolean useCredentials?: boolean + isCore?: boolean } export type LoaderHelpers = { @@ -131,7 +132,6 @@ export type LoaderHelpers = { scriptUrl: string modulesUniqueQuery?: string preferredIcuAsset?: string | null, - loadingWorkers: PThreadWorker[], workerNextNumber: number, actual_downloaded_assets_count: number, @@ -143,6 +143,7 @@ export type LoaderHelpers = { allDownloadsQueued: PromiseAndController, wasmCompilePromise: PromiseAndController, runtimeModuleLoaded: PromiseAndController, + loadingWorkers: PromiseAndController, is_exited: () => boolean, is_runtime_running: () => boolean, @@ -209,11 +210,13 @@ export type RuntimeHelpers = { proxyGCHandle: GCHandle | undefined, managedThreadTID: PThreadPtr, ioThreadTID: PThreadPtr, + deputyWorker: PThreadWorker, currentThreadTID: PThreadPtr, isManagedRunningOnCurrentThread: boolean, isPendingSynchronousCall: boolean, // true when we are in the middle of a synchronous call from managed code from same thread cspPolicy: boolean, + coreAssetsInMemory: PromiseAndController, allAssetsInMemory: PromiseAndController, dotnetReady: PromiseAndController, afterInstantiateWasm: PromiseAndController, @@ -221,7 +224,8 @@ export type RuntimeHelpers = { afterPreInit: PromiseAndController, afterPreRun: PromiseAndController, beforeOnRuntimeInitialized: PromiseAndController, - afterMonoStarted: PromiseAndController, + afterMonoStarted: PromiseAndController, + afterDeputyReady: PromiseAndController, afterIOStarted: PromiseAndController, afterOnRuntimeInitialized: PromiseAndController, afterPostRun: PromiseAndController, @@ -237,6 +241,29 @@ export type RuntimeHelpers = { jiterpreter_dump_stats?: (concise?: boolean) => void, forceDisposeProxies: (disposeMethods: boolean, verbose: boolean) => void, dumpThreads: () => void, + mono_wasm_print_thread_dump: () => void, + + stringToUTF16: (dstPtr: number, endPtr: number, text: string) => void, + stringToUTF16Ptr: (str: string) => VoidPtr, + utf16ToString: (startPtr: number, endPtr: number) => string, + utf16ToStringLoop: (startPtr: number, endPtr: number) => string, + localHeapViewU16: () => Uint16Array, + setU16_local: (heap: Uint16Array, ptr: number, value: number) => void, + setI32: (offset: MemOffset, value: number) => void, +} +export type GlobalizationHelpers = { + + mono_wasm_change_case_invariant: (src: number, srcLength: number, dst: number, dstLength: number, toUpper: number) => VoidPtr; + mono_wasm_change_case: (culture: number, cultureLength: number, src: number, srcLength: number, dst: number, dstLength: number, toUpper: number) => VoidPtr; + mono_wasm_compare_string: (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr) => VoidPtr; + mono_wasm_starts_with: (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr) => VoidPtr; + mono_wasm_ends_with: (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr) => VoidPtr; + mono_wasm_index_of: (culture: number, cultureLength: number, needlePtr: number, needleLength: number, srcPtr: number, srcLength: number, options: number, fromBeginning: number, resultPtr: Int32Ptr) => VoidPtr; + mono_wasm_get_calendar_info: (culture: number, cultureLength: number, calendarId: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr) => VoidPtr; + mono_wasm_get_culture_info: (culture: number, cultureLength: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr) => VoidPtr; + mono_wasm_get_first_day_of_week: (culture: number, cultureLength: number, resultPtr: Int32Ptr) => VoidPtr; + mono_wasm_get_first_week_of_year: (culture: number, cultureLength: number, resultPtr: Int32Ptr) => VoidPtr; + setSegmentationRulesFromJson: (json: string) => void; } export type AOTProfilerOptions = { @@ -283,6 +310,7 @@ export type GlobalObjects = { module: DotnetModuleInternal, loaderHelpers: LoaderHelpers, runtimeHelpers: RuntimeHelpers, + globalizationHelpers: GlobalizationHelpers, api: RuntimeAPI, }; export type EmscriptenReplacements = { @@ -318,7 +346,7 @@ export type MarshalerToCs = (arg: JSMarshalerArgument, value: any, element_type? export type BoundMarshalerToJs = (args: JSMarshalerArguments) => any; export type BoundMarshalerToCs = (args: JSMarshalerArguments, value: any) => void; // please keep in sync with src\libraries\System.Runtime.InteropServices.JavaScript\src\System\Runtime\InteropServices\JavaScript\MarshalerType.cs -export enum MarshalerType { +export const enum MarshalerType { None = 0, Void = 1, Discard, @@ -431,6 +459,10 @@ export declare interface EmscriptenModuleInternal { runtimeKeepalivePop(): void; maybeExit(): void; __emscripten_thread_init(pthread_ptr: PThreadPtr, isMainBrowserThread: number, isMainRuntimeThread: number, canBlock: number): void; + print(message: string): void; + printErr(message: string): void; + abort(reason: any): void; + _emscripten_force_exit(exit_code: number): void; } /// A PromiseController encapsulates a Promise together with easy access to its resolve and reject functions. @@ -460,7 +492,7 @@ export type initializeExportsType = (globalObjects: GlobalObjects) => RuntimeAPI export type initializeReplacementsType = (replacements: EmscriptenReplacements) => void; export type afterInitializeType = (module: EmscriptenModuleInternal) => void; export type configureEmscriptenStartupType = (module: DotnetModuleInternal) => void; -export type configureRuntimeStartupType = () => Promise; +export type configureRuntimeStartupType = (module: DotnetModuleInternal) => Promise; export type configureWorkerStartupType = (module: DotnetModuleInternal) => Promise @@ -478,6 +510,10 @@ export type NativeModuleExportsInternal = { default: (unificator: Function) => EmscriptenModuleInternal } +export type HybridGlobalizationModuleExportsInternal = { + initHybrid: (gh: GlobalizationHelpers, rh: RuntimeHelpers) => void; +} + export type WeakRefInternal = WeakRef & { dispose?: () => void } @@ -496,12 +532,14 @@ export const enum WorkerToMainMessageType { deputyCreated = "createdDeputy", deputyFailed = "deputyFailed", deputyStarted = "monoStarted", + deputyReady = "deputyReady", ioStarted = "ioStarted", preload = "preload", } export const enum MainToWorkerMessageType { - applyConfig = "apply_mono_config", + applyConfig = "applyConfig", + allAssetsLoaded = "allAssetsLoaded", } export interface PThreadWorker extends Worker { @@ -549,6 +587,7 @@ export interface PThreadLibrary { threadInitTLS: () => void, getNewWorker: () => PThreadWorker, returnWorkerToPool: (worker: PThreadWorker) => void, + terminateAllThreads: () => void, } export interface PThreadInfoMap { diff --git a/src/mono/browser/runtime/web-socket.ts b/src/mono/browser/runtime/web-socket.ts index d97cc76cefe4..b328943ceaa6 100644 --- a/src/mono/browser/runtime/web-socket.ts +++ b/src/mono/browser/runtime/web-socket.ts @@ -78,9 +78,7 @@ export function ws_wasm_create (uri: string, sub_protocols: string[] | null, rec try { if (ws[wasm_ws_is_aborted]) return; if (!loaderHelpers.is_runtime_running()) return; - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } + forceThreadMemoryViewRefresh(); open_promise_control.resolve(ws); prevent_timer_throttling(); } catch (error: any) { @@ -91,9 +89,7 @@ export function ws_wasm_create (uri: string, sub_protocols: string[] | null, rec try { if (ws[wasm_ws_is_aborted]) return; if (!loaderHelpers.is_runtime_running()) return; - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } + forceThreadMemoryViewRefresh(); web_socket_on_message(ws, ev); prevent_timer_throttling(); } catch (error: any) { @@ -105,9 +101,7 @@ export function ws_wasm_create (uri: string, sub_protocols: string[] | null, rec ws.removeEventListener("message", local_on_message); if (ws[wasm_ws_is_aborted]) return; if (!loaderHelpers.is_runtime_running()) return; - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } + forceThreadMemoryViewRefresh(); ws[wasm_ws_close_received] = true; ws["close_status"] = ev.code; @@ -137,9 +131,7 @@ export function ws_wasm_create (uri: string, sub_protocols: string[] | null, rec try { if (ws[wasm_ws_is_aborted]) return; if (!loaderHelpers.is_runtime_running()) return; - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } + forceThreadMemoryViewRefresh(); ws.removeEventListener("message", local_on_message); const message = ev.message ? "WebSocket error: " + ev.message diff --git a/src/mono/browser/sanitize.py b/src/mono/browser/sanitize.py index c3a63434aa39..55737f8e4be5 100644 --- a/src/mono/browser/sanitize.py +++ b/src/mono/browser/sanitize.py @@ -32,7 +32,7 @@ def rewrite_package_json(path): emsdk_path = sys.argv[1] -emscripten_path = os.path.join(emsdk_path, "upstream", "emscripten") +emscripten_path = os.path.join(emsdk_path, "emscripten") node_root = os.path.join(emsdk_path, "node") node_paths = glob(node_root) upgrade = True diff --git a/src/mono/browser/test-main.js b/src/mono/browser/test-main.js index 1feb21ef2f79..1ada6f3cdde1 100644 --- a/src/mono/browser/test-main.js +++ b/src/mono/browser/test-main.js @@ -24,6 +24,8 @@ export const ENVIRONMENT_IS_SIDECAR = ENVIRONMENT_IS_WEB_WORKER && typeof dotnet export const ENVIRONMENT_IS_WORKER = ENVIRONMENT_IS_WEB_WORKER && !ENVIRONMENT_IS_SIDECAR; // we redefine what ENVIRONMENT_IS_WORKER, we replace it in emscripten internals, so that sidecar works export const ENVIRONMENT_IS_WEB = typeof window == "object" || (ENVIRONMENT_IS_WEB_WORKER && !ENVIRONMENT_IS_NODE); export const ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE; +export const isFirefox = !!(ENVIRONMENT_IS_WEB && navigator.userAgent.includes("Firefox")); +export const isChromium = !!(ENVIRONMENT_IS_WEB && navigator.userAgentData && navigator.userAgentData.brands.some(b => b.brand === "Google Chrome" || b.brand === "Microsoft Edge" || b.brand === "Chromium")); if (ENVIRONMENT_IS_NODE && process.versions.node.split(".")[0] < 14) { throw new Error(`NodeJS at '${process.execPath}' has too low version '${process.versions.node}'`); @@ -51,7 +53,13 @@ if (!ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WEB && typeof globalThis.crypto === } } -if (ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER) { +if (ENVIRONMENT_IS_WEB && isFirefox) { + Error.stackTraceLimit = 1000; +} + +// as soon as possible, see https://github.com/dotnet/runtime/issues/101169 +if (ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER && !isFirefox) { + console.log("Running in: " + globalThis.navigator.userAgent); console.log("Running at: " + globalThis.location.href); } @@ -179,6 +187,8 @@ function processArguments(incomingArguments, runArgs) { // cheap way to let the testing infrastructure know we're running in a browser context (or not) runArgs.environmentVariables["IsBrowserDomSupported"] = ENVIRONMENT_IS_WEB.toString().toLowerCase(); runArgs.environmentVariables["IsNodeJS"] = ENVIRONMENT_IS_NODE.toString().toLowerCase(); + runArgs.environmentVariables["IsFirefox"] = isFirefox.toString().toLowerCase(); + runArgs.environmentVariables["IsChromium"] = isChromium.toString().toLowerCase(); return runArgs; } @@ -312,6 +322,13 @@ async function run() { App.runtime = await dotnet.create(); App.runArgs = runArgs + // after console proxy was setup, see https://github.com/dotnet/runtime/issues/101169 + if (ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER && isFirefox) { + console.log("Application arguments: " + runArgs.applicationArguments.join(' ')); + console.log("Running in: " + globalThis.navigator.userAgent); + console.log("Running at: " + globalThis.location.href); + } + console.info("Initializing dotnet version " + App.runtime.runtimeBuildInfo.productVersion + " commit hash " + App.runtime.runtimeBuildInfo.gitHash); for (let i = 0; i < runArgs.profilers.length; ++i) { diff --git a/src/mono/mono.proj b/src/mono/mono.proj index 8b57badb1a2e..8f02901b6d77 100644 --- a/src/mono/mono.proj +++ b/src/mono/mono.proj @@ -77,6 +77,8 @@ true + true + false @@ -87,6 +89,20 @@ GeneratePathProperty="true" /> + + + + + + + Condition="'$(ShouldProvisionEmscripten)' == 'true'"> @@ -157,25 +173,133 @@ $([MSBuild]::NormalizeDirectory('$(MSBuildThisFileDirectory)', 'browser')) emsdk %(_VersionLines.Identity) - - $(EMSDK_PATH)/emsdk$(EmsdkExt) install $(EmscriptenVersion) - $(EMSDK_PATH)/emsdk$(EmsdkExt) activate $(EmscriptenVersion) - powershell -NonInteractive -command "& $(InstallCmd); Exit $LastExitCode " - powershell -NonInteractive -command "& $(ActivateCmd); Exit $LastExitCode " - setlocal EnableDelayedExpansion && call "$([MSBuild]::NormalizePath('$(EMSDK_PATH)', 'emsdk_env.bat'))" && !EMSDK_PYTHON! + <_EmsdkPaths Condition="'$(HostOS)' != 'windows'"> +CURRENT_SCRIPT= +DIR="." + +# use shell specific method to get the path +# to the current file being source'd. +# +# To add a shell, add another conditional below, +# then add tests to scripts/test_source_env.sh + +if [ -n "%24{BASH_SOURCE-}" ]%3B then + CURRENT_SCRIPT="%24BASH_SOURCE" +elif [ -n "%24{ZSH_VERSION-}" ]%3B then + CURRENT_SCRIPT="%24{(%):-%x}" +elif [ -n "%24{KSH_VERSION-}" ]%3B then + CURRENT_SCRIPT=%24{.sh.file} +fi + +if [ -n "%24{CURRENT_SCRIPT-}" ]%3B then + DIR=%24(dirname "%24CURRENT_SCRIPT") + if [ -h "%24CURRENT_SCRIPT" ]%3B then + # Now work out actual DIR since this is part of a symlink. + # Since we can't be sure that readlink or realpath + # are available, use tools more likely to be installed. + # (This will still fail if sed is not available.) + SYMDIR=%24(dirname "%24(ls -l "%24CURRENT_SCRIPT" | sed -n "s/.*-> //p")") + if [ -z "%24SYMDIR" ]%3B then + SYMDIR="." + fi + FULLDIR="%24DIR/%24SYMDIR" + DIR=%24(cd "%24FULLDIR" > /dev/null 2>&1%3B /bin/pwd) + unset SYMDIR + unset FULLDIR + fi +fi +unset CURRENT_SCRIPT + +if [ ! -f "%24DIR/emscripten/emcmake.py" ]%3B then + echo "Error: unable to determine 'emsdk' directory. Perhaps you are using a shell or" 1>&2 + echo " environment that this script does not support." 1>&2 + echo 1>&2 + echo "A possible solution is to source this script while in the 'emsdk' directory." 1>&2 + echo 1>&2 + unset DIR + return +fi + +export EMSDK_PATH=%24{DIR}/ +unset DIR + +export DOTNET_EMSCRIPTEN_LLVM_ROOT=%24{EMSDK_PATH}bin/ +export DOTNET_EMSCRIPTEN_NODE_JS=%24{EMSDK_PATH}node/bin/node +export DOTNET_EMSCRIPTEN_BINARYEN_ROOT=%24{EMSDK_PATH} + + + <_EmsdkPaths Condition="'$(HostOS)' == 'windows'"> +@echo off + +set CURRENT_SCRIPT=%~dp0 +set EMSDK_PATH=%CURRENT_SCRIPT:~0,-1%\ + +set EMSDK_PYTHON=%EMSDK_PATH%python\python.exe +set DOTNET_EMSCRIPTEN_LLVM_ROOT=%EMSDK_PATH%bin\ +set DOTNET_EMSCRIPTEN_NODE_JS=%EMSDK_PATH%node\bin\node +set DOTNET_EMSCRIPTEN_NODE_PATH=%EMSDK_PATH%node\bin\ +set DOTNET_EMSCRIPTEN_BINARYEN_ROOT=%EMSDK_PATH% + + + <_EmscriptenPaths> +import os + +emsdk_path = os.path.dirname(os.path.dirname(os.path.realpath(os.getenv('EM_CONFIG')).replace('\\', '/'))) + +LLVM_ROOT = emsdk_path + '/bin' +NODE_JS = emsdk_path + '/node/bin/node' +BINARYEN_ROOT = emsdk_path + +FROZEN_CACHE = bool(os.getenv('FROZEN_CACHE', 'True')) + +COMPILER_ENGINE = NODE_JS +JS_ENGINES = [NODE_JS] + + setlocal EnableDelayedExpansion && call "$([MSBuild]::NormalizePath('$(EMSDK_PATH)', 'emsdk_env$(ScriptExt)'))" && !EMSDK_PYTHON! - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + @@ -283,9 +407,9 @@ - <_MonoCXXFLAGS Include="-I$(MonoLLVMDir)\$(_MonoLLVMTargetArchitecture)\include\c++\v1" /> + <_MonoCXXFLAGS Include="-isystem $(MonoLLVMDir)\$(_MonoLLVMTargetArchitecture)\include\c++\v1" /> <_MonoCXXFLAGS Include="-L$(MonoLLVMDir)\$(_MonoLLVMTargetArchitecture)\lib" /> - <_MonoCXXFLAGS Include="-stdlib=libc++" /> + <_MonoCXXFLAGS Include="-lc++;-lc++abi" /> <_MonoCMakeArgs Include="-DMONO_SET_RPATH_ORIGIN=true" /> @@ -401,11 +525,11 @@ <_MonoCMakeArgs Include="-DCMAKE_SYSTEM_VARIANT=maccatalyst" /> <_MonoCPPFLAGS Include="-Wno-overriding-t-option" /> - <_MonoCFlags Condition="'$(TargetArchitecture)' == 'arm64'" Include="-target arm64-apple-ios14.2-macabi" /> - <_MonoCFlags Condition="'$(TargetArchitecture)' == 'x64'" Include="-target x86_64-apple-ios13.5-macabi" /> + <_MonoCFlags Condition="'$(TargetArchitecture)' == 'arm64'" Include="-target arm64-apple-ios$(MacCatalystVersionMin)-macabi" /> + <_MonoCFlags Condition="'$(TargetArchitecture)' == 'x64'" Include="-target x86_64-apple-ios$(MacCatalystVersionMin)-macabi" /> <_MonoCFLAGS Condition="'$(TargetArchitecture)' == 'arm64'" Include="-arch arm64" /> - <_MonoCXXFlags Condition="'$(TargetArchitecture)' == 'arm64'" Include="-target arm64-apple-ios14.2-macabi" /> - <_MonoCXXFlags Condition="'$(TargetArchitecture)' == 'x64'" Include="-target x86_64-apple-ios13.5-macabi" /> + <_MonoCXXFlags Condition="'$(TargetArchitecture)' == 'arm64'" Include="-target arm64-apple-ios$(MacCatalystVersionMin)-macabi" /> + <_MonoCXXFlags Condition="'$(TargetArchitecture)' == 'x64'" Include="-target x86_64-apple-ios$(MacCatalystVersionMin)-macabi" /> <_MonoCXXFLAGS Condition="'$(TargetArchitecture)' == 'arm64'" Include="-arch arm64" /> <_MonoBuildEnv Condition="'$(BuildArchitecture)' == 'arm64'" Include="arch -arch arm64" /> @@ -599,14 +723,16 @@ $([MSBuild]::EnsureTrailingSlash('$(EMSDK_PATH)').Replace('\', '/')) $([MSBuild]::EnsureTrailingSlash('$(WASI_SDK_PATH)').Replace('\', '/')) + <_EmsdkEnvScriptPath>$([MSBuild]::NormalizePath('$(EMSDK_PATH)', 'emsdk_env$(ScriptExt)')) + <_MonoCMakeConfigureCommand>cmake @(_MonoCMakeArgs, ' ') $(MonoCMakeExtraArgs) "$(MonoProjectRoot.TrimEnd('\/'))" <_MonoCMakeConfigureCommand Condition="'$(TargetsBrowser)' != 'true' and '$(TargetsWasi)' != 'true' and '$(_MonoSkipInitCompiler)' != 'true' and '$(HostOS)' != 'windows'">sh -c 'build_arch="$(_CompilerTargetArch)" compiler="$(MonoCCompiler)" . "$(RepositoryEngineeringCommonDir)native/init-compiler.sh" && @(_MonoBuildEnv, ' ') $(_MonoCMakeConfigureCommand)' <_MonoCMakeConfigureCommand Condition="'$(TargetsBrowser)' != 'true' and '$(TargetsWasi)' != 'true' and '$(_MonoSkipInitCompiler)' == 'true' and '$(HostOS)' != 'windows'">$(_MonoCCOption) $(_MonoCXXOption) @(_MonoBuildEnv, ' ') $(_MonoCMakeConfigureCommand) <_MonoCMakeConfigureCommand Condition="'$(TargetsWasi)' == 'true'">$(_MonoCMakeConfigureCommand) -DWASI_SDK_PREFIX=$(WASI_SDK_PATH) -DCMAKE_SYSROOT=$(WASI_SDK_PATH)share/wasi-sysroot -DCMAKE_TOOLCHAIN_FILE=$(WASI_SDK_PATH)share/cmake/wasi-sdk.cmake -DCMAKE_CXX_FLAGS="--sysroot=$(WASI_SDK_PATH)share/wasi-sysroot" <_MonoCMakeConfigureCommand Condition="'$(TargetsBrowser)' != 'true' and '$(TargetsWasi)' != 'true' and '$(HostOS)' == 'windows'">call "$(RepositoryEngineeringDir)native\init-vs-env.cmd" $(_CompilerTargetArch) && cd /D "$(MonoObjDir)" && @(_MonoBuildEnv, ' ') $(_MonoCMakeConfigureCommand) - <_MonoCMakeConfigureCommand Condition="'$(TargetsBrowser)' == 'true' and '$(HostOS)' != 'windows'">bash -c 'source $(EMSDK_PATH)/emsdk_env.sh 2>&1 && emcmake $(_MonoCMakeConfigureCommand)' - <_MonoCMakeConfigureCommand Condition="'$(TargetsBrowser)' == 'true' and '$(HostOS)' == 'windows'">call "$(RepositoryEngineeringDir)native\init-vs-env.cmd" && call "$([MSBuild]::NormalizePath('$(EMSDK_PATH)', 'emsdk_env.bat'))" && emcmake $(_MonoCMakeConfigureCommand) + <_MonoCMakeConfigureCommand Condition="'$(TargetsBrowser)' == 'true' and '$(HostOS)' != 'windows'">bash -c 'source $(_EmsdkEnvScriptPath) 2>&1 && emcmake $(_MonoCMakeConfigureCommand)' + <_MonoCMakeConfigureCommand Condition="'$(TargetsBrowser)' == 'true' and '$(HostOS)' == 'windows'">call "$(RepositoryEngineeringDir)native\init-vs-env.cmd" && call "$(_EmsdkEnvScriptPath)" && emcmake $(_MonoCMakeConfigureCommand) <_MonoCMakeConfigureCommand Condition="'$(TargetsWasi)' == 'true' and '$(HostOS)' == 'windows'">call "$(RepositoryEngineeringDir)native\init-vs-env.cmd" && cmake $(_MonoCMakeConfigureCommand) <_MonoCMakeBuildCommand>cmake --build . --target install --config $(Configuration) @@ -796,8 +922,8 @@ - - + + ", arg_pos)); - if (sig->pinvoke && !sig->marshalling_disabled) - arg_pos += mono_type_native_stack_size (sig->params [i], &align); - else - arg_pos += mono_type_stack_size (sig->params [i], &align); - - DEBUG (printf ("%d\n", stackval_arg_pos)); - } - - /*----------------------------------------------------------*/ - /* Set return area pointer. */ - /*----------------------------------------------------------*/ - s390_la (p, s390_r10, 0, STK_BASE, stackval_arg_pos); - s390_stg(p, s390_r10, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval))); - if (sig->ret->type == MONO_TYPE_VALUETYPE && !m_type_is_byref (sig->ret)) { - MonoClass *klass = sig->ret->data.klass; - if (!klass->enumtype) { - s390_la (p, s390_r9, 0, s390_r10, sizeof(stackval)); - s390_st (p, s390_r9, 0,STK_BASE, stackval_arg_pos); - stackval_arg_pos += sizeof(stackval); - } - } - - /*----------------------------------------------------------*/ - /* call ves_exec_method */ - /*----------------------------------------------------------*/ - s390_bras (p, s390_r13, 4); - s390_llong(p, ves_exec_method); - s390_lg (p, s390_r1, 0, s390_r13, 0); - s390_la (p, s390_r2, 0, STK_BASE, MINV_POS); - s390_basr (p, s390_r14, s390_r1); - - /*----------------------------------------------------------*/ - /* move retval from stackval to proper place (r3/r4/...) */ - /*----------------------------------------------------------*/ - DEBUG(printf("retType: %d byRef: %d\n",sig->ret->type,m_type_is_byref (sig->ret))); - if (m_type_is_byref (sig->ret)) { - DEBUG (printf ("ret by ref\n")); - s390_stg(p, s390_r2, 0, s390_r10, 0); - } else { - enum_retvalue: - switch (sig->ret->type) { - case MONO_TYPE_VOID: - break; - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_U1: - s390_lghi(p, s390_r2, 0); - s390_ic (p, s390_r2, 0, s390_r10, 0); - break; - case MONO_TYPE_I2: - case MONO_TYPE_U2: - s390_lh (p, s390_r2, 0,s390_r10, 0); - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - s390_lgf(p, s390_r2, 0, s390_r10, 0); - break; - case MONO_TYPE_OBJECT: - case MONO_TYPE_STRING: - case MONO_TYPE_CLASS: - case MONO_TYPE_I8: - s390_lg (p, s390_r2, 0, s390_r10, 0); - break; - case MONO_TYPE_R4: - s390_le (p, s390_f0, 0, s390_r10, 0); - break; - case MONO_TYPE_R8: - s390_ld (p, s390_f0, 0, s390_r10, 0); - break; - case MONO_TYPE_VALUETYPE: - if (sig->ret->data.klass->enumtype) { - simpletype = sig->ret->data.klass->enum_basetype->type; - goto enum_retvalue; - } - /*---------------------------------*/ - /* Call stackval_to_data to return */ - /* the structure */ - /*---------------------------------*/ - s390_bras (p, s390_r13, 8); - s390_llong(p, sig->ret); - s390_llong(p, sig->pinvoke); - s390_llong(p, stackval_to_data); - s390_lg (p, s390_r2, 0, s390_r13, 0); - s390_lg (p, s390_r3, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval))); - if (sz.retStruct) { - /*------------------------------------------*/ - /* Get stackval_to_data to set result area */ - /*------------------------------------------*/ - s390_lgr (p, s390_r4, s390_r8); - } else { - /*------------------------------------------*/ - /* Give stackval_to_data a temp result area */ - /*------------------------------------------*/ - s390_la (p, s390_r4, 0, STK_BASE, stackval_arg_pos); - } - s390_lg (p, s390_r5, 0,s390_r13, 4); - s390_lg (p, s390_r1, 0, s390_r13, 8); - s390_basr (p, s390_r14, s390_r1); - switch (retSize) { - case 0: - break; - case 1: - s390_lghi(p, s390_r2, 0); - s390_ic (p, s390_r2, 0, s390_r10, 0); - break; - case 2: - s390_lh (p, s390_r2, 0, s390_r10, 0); - break; - case 4: - s390_lgf(p, s390_r2, 0, s390_r10, 0); - break; - case 8: - s390_lg (p, s390_r2, 0, s390_r10, 0); - break; - default: ; - /*-------------------------------------------------*/ - /* stackval_to_data has placed data in result area */ - /*-------------------------------------------------*/ - } - break; - default: - g_error ("Type 0x%x not handled yet in thunk creation", - sig->ret->type); - break; - } - } - - /*----------------------------------------------------------*/ - /* epilog */ - /*----------------------------------------------------------*/ - s390_lg (p, STK_BASE, 0, STK_BASE, 0); - s390_lg (p, s390_r4, 0, STK_BASE, S390_RET_ADDR_OFFSET); - s390_lmg (p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET); - s390_br (p, s390_r4); - - DEBUG (printf ("emitted code size: %d\n", p - code_buffer)); - - DEBUG (printf ("Delegate [end emitting]\n")); - - ji = g_new0 (MonoJitInfo, 1); - ji->method = method; - ji->code_size = p - code_buffer; - ji->code_start = code_buffer; - - mono_jit_info_table_add (mono_get_root_domain (), ji); - - return ji->code_start; -} - -/*========================= End of Function ========================*/ diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c index 7c0a93093e34..ce43d282177f 100644 --- a/src/mono/mono/component/debugger-agent.c +++ b/src/mono/mono/component/debugger-agent.c @@ -470,8 +470,6 @@ static void emit_thread_start (gpointer key, gpointer value, gpointer user_data) static void invalidate_each_thread (gpointer key, gpointer value, gpointer user_data); -static void assembly_load (MonoProfiler *prof, MonoAssembly *assembly); - static void assembly_unload (MonoProfiler *prof, MonoAssembly *assembly); static void gc_finalizing (MonoProfiler *prof); @@ -804,7 +802,7 @@ mono_debugger_agent_init_internal (void) mono_profiler_set_domain_loaded_callback (prof, appdomain_load); mono_profiler_set_domain_unloading_callback (prof, appdomain_start_unload); mono_profiler_set_domain_unloaded_callback (prof, appdomain_unload); - mono_profiler_set_assembly_loaded_callback (prof, assembly_load); + mono_profiler_set_assembly_loaded_callback (prof, mono_dbg_assembly_load); mono_profiler_set_assembly_unloading_callback (prof, assembly_unload); mono_profiler_set_jit_failed_callback (prof, jit_failed); mono_profiler_set_gc_finalizing_callback (prof, gc_finalizing); @@ -4005,8 +4003,8 @@ invalidate_each_thread (gpointer key, gpointer value, gpointer user_data) invalidate_frames ((DebuggerTlsData *)value); } -static void -assembly_load (MonoProfiler *prof, MonoAssembly *assembly) +void +mono_dbg_assembly_load (MonoProfiler *prof, MonoAssembly *assembly) { /* Sent later in jit_end () */ dbg_lock (); @@ -4127,7 +4125,7 @@ jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo) if (!CHECK_ICORDBG (TRUE) || tls->invoke == NULL) { process_profiler_event (EVENT_KIND_ASSEMBLY_LOAD, assembly); } else { - assembly_load(prof, assembly); //send later + mono_dbg_assembly_load (prof, assembly); //send later break; } } else { diff --git a/src/mono/mono/component/debugger-agent.h b/src/mono/mono/component/debugger-agent.h index 35145597c99f..6d97cd9ab919 100644 --- a/src/mono/mono/component/debugger-agent.h +++ b/src/mono/mono/component/debugger-agent.h @@ -75,4 +75,7 @@ mono_debugger_agent_receive_and_process_command (void); bool mono_begin_breakpoint_processing (void *the_tls, MonoContext *ctx, MonoJitInfo *ji, gboolean from_signal); + +void +mono_dbg_assembly_load (MonoProfiler *prof, MonoAssembly *assembly); #endif diff --git a/src/mono/mono/component/debugger-engine.c b/src/mono/mono/component/debugger-engine.c index 378218a112ed..031404a2b8a8 100644 --- a/src/mono/mono/component/debugger-engine.c +++ b/src/mono/mono/component/debugger-engine.c @@ -449,6 +449,16 @@ mono_de_set_breakpoint (MonoMethod *method, long il_offset, EventRequest *req, M set_bp_in_method (domain, m, seq_points, bp, error); } + // trying to get the seqpoints directly from the jit info of the method + // the seqpoints in get_default_jit_mm may not be found for AOTed methods in arm64 + if (methods->len == 0) + { + MonoJitInfo *ji; + (void)mono_jit_search_all_backends_for_jit_info (method, &ji); + if (ji && ji->seq_points) + set_bp_in_method (mono_get_root_domain (), method, ji->seq_points, bp, error); + } + g_ptr_array_add (breakpoints, bp); mono_debugger_log_add_bp (bp, bp->method, bp->il_offset); mono_loader_unlock (); diff --git a/src/mono/mono/component/hot_reload.c b/src/mono/mono/component/hot_reload.c index 85d1029e490d..300a46a245f9 100644 --- a/src/mono/mono/component/hot_reload.c +++ b/src/mono/mono/component/hot_reload.c @@ -2776,14 +2776,6 @@ add_param_info_for_method (BaselineInfo *base_info, uint32_t param_token, uint32 } } -/* HACK - keep in sync with locator_t in metadata/metadata.c */ -typedef struct { - guint32 idx; /* The index that we are trying to locate */ - guint32 col_idx; /* The index in the row where idx may be stored */ - MonoTableInfo *t; /* pointer to the table */ - guint32 result; -} upd_locator_t; - void* hot_reload_metadata_linear_search (MonoImage *base_image, MonoTableInfo *base_table, const void *key, BinarySearchComparer comparer) { @@ -2804,11 +2796,10 @@ hot_reload_metadata_linear_search (MonoImage *base_image, MonoTableInfo *base_ta g_assert (success); uint32_t rows = table_info_get_rows (latest_mod_table); - upd_locator_t *loc = (upd_locator_t*)key; + mono_locator_t *loc = (mono_locator_t*)key; g_assert (loc); - loc->result = 0; /* HACK: this is so that the locator can compute the row index of the given row. but passing the mutant table to other metadata functions could backfire. */ - loc->t = (MonoTableInfo*)latest_mod_table; + *loc = mono_locator_init ((MonoTableInfo*)latest_mod_table, loc->idx, loc->col_idx); for (uint32_t idx = 0; idx < rows; ++idx) { const char *row = latest_mod_table->base + idx * latest_mod_table->row_size; if (!comparer (loc, row)) diff --git a/src/mono/mono/component/mini-wasm-debugger.c b/src/mono/mono/component/mini-wasm-debugger.c index 61020ecb5735..071a887c33c5 100644 --- a/src/mono/mono/component/mini-wasm-debugger.c +++ b/src/mono/mono/component/mini-wasm-debugger.c @@ -191,6 +191,7 @@ static void assembly_loaded (MonoProfiler *prof, MonoAssembly *assembly) { PRINT_DEBUG_MSG (2, "assembly_loaded callback called for %s\n", assembly->aname.name); + mono_dbg_assembly_load (prof, assembly); MonoImage *assembly_image = assembly->image; MonoImage *pdb_image = NULL; diff --git a/src/mono/mono/eglib/eglib-remap.h b/src/mono/mono/eglib/eglib-remap.h index 5fc770dfa973..3f42bd8308af 100644 --- a/src/mono/mono/eglib/eglib-remap.h +++ b/src/mono/mono/eglib/eglib-remap.h @@ -98,6 +98,7 @@ #define g_log_set_fatal_mask monoeg_g_log_set_fatal_mask #define g_logv monoeg_g_logv #define g_memdup monoeg_g_memdup +#define g_memrchr monoeg_g_memrchr #define g_mem_set_vtable monoeg_g_mem_set_vtable #define g_mem_get_vtable monoeg_g_mem_get_vtable #define g_mkdtemp monoeg_g_mkdtemp diff --git a/src/mono/mono/eglib/glib.h b/src/mono/mono/eglib/glib.h index d6c1e2e59a9a..ae0dd994db23 100644 --- a/src/mono/mono/eglib/glib.h +++ b/src/mono/mono/eglib/glib.h @@ -375,6 +375,7 @@ gchar *g_strchug (gchar *str); gchar *g_strchomp (gchar *str); gchar *g_strnfill (gsize length, gchar fill_char); gsize g_strnlen (const char*, gsize); +const gchar *g_memrchr (const char *s, char c, size_t n); void g_strdelimit (char *string, char delimiter, char new_delimiter); @@ -759,6 +760,7 @@ const char * g_get_assertion_message (void); #define g_message(...) g_log_disabled (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, __FILE__, __LINE__) #define g_debug(...) g_log_disabled (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, __FILE__, __LINE__) #endif +#define g_warning_dont_trim(...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, __VA_ARGS__) typedef void (*GLogFunc) (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data); typedef void (*GPrintFunc) (const gchar *string); diff --git a/src/mono/mono/eglib/gslist.c b/src/mono/mono/eglib/gslist.c index 71cd6dfd972e..aa03c4be8d15 100644 --- a/src/mono/mono/eglib/gslist.c +++ b/src/mono/mono/eglib/gslist.c @@ -52,7 +52,8 @@ g_slist_append (GSList *list, gpointer data) GSList* g_slist_prepend (GSList *list, gpointer data) { - GSList *head = g_slist_alloc (); + // We don't need to zero the allocation using g_slist_alloc since we fully initialize the node + GSList *head = g_new (GSList, 1); head->data = data; head->next = list; diff --git a/src/mono/mono/eglib/gstr.c b/src/mono/mono/eglib/gstr.c index 6ae0eb6b668b..557977cab0d6 100644 --- a/src/mono/mono/eglib/gstr.c +++ b/src/mono/mono/eglib/gstr.c @@ -783,3 +783,12 @@ g_strnlen (const char* s, gsize n) for (i = 0; i < n && s [i]; ++i) ; return i; } + +const gchar * +g_memrchr (const char *s, char c, size_t n) +{ + while (n--) + if (s[n] == c) + return (void *)(s + n); + return NULL; +} diff --git a/src/mono/mono/eventpipe/ep-rt-mono-profiler-provider.c b/src/mono/mono/eventpipe/ep-rt-mono-profiler-provider.c index 2076a2748b6f..12d730b84552 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono-profiler-provider.c +++ b/src/mono/mono/eventpipe/ep-rt-mono-profiler-provider.c @@ -3030,9 +3030,6 @@ void ep_rt_mono_profiler_provider_fini (void) { if (_mono_profiler_provider_enabled) { - if (_mono_profiler_provider_callspec.enabled) - mono_callspec_cleanup (&_mono_profiler_provider_callspec); - if (_mono_profiler_provider) { mono_profiler_set_gc_root_register_callback (_mono_profiler_provider, NULL); mono_profiler_set_gc_root_unregister_callback (_mono_profiler_provider, NULL); @@ -3100,7 +3097,6 @@ ep_rt_mono_profiler_provider_fini (void) mono_profiler_set_call_instrumentation_filter_callback (_mono_profiler_provider, NULL); } - _mono_profiler_provider = NULL; if (_mono_heap_dump_profiler_provider) { mono_profiler_set_gc_root_register_callback (_mono_heap_dump_profiler_provider, NULL); @@ -3110,21 +3106,16 @@ ep_rt_mono_profiler_provider_fini (void) mono_profiler_set_gc_resize_callback (_mono_heap_dump_profiler_provider, NULL); mono_profiler_set_gc_finalized_callback (_mono_heap_dump_profiler_provider, NULL); } - _mono_heap_dump_profiler_provider = NULL; _gc_heap_dump_requests = 0; _gc_heap_dump_in_progress = 0; _gc_heap_dump_trigger_count = 0; _gc_state = 0; - - _mono_profiler_provider_enabled = DEFAULT_MONO_PROFILER_PROVIDER_ENABLED; - - gc_heap_dump_mem_block_free_all (); - - gc_heap_dump_request_params_free (); - provider_params_free (); - - ep_rt_spin_lock_free (&_gc_lock); + + // We were cleaning up resources (mutexes, tls data, etc) here but it races with + // other threads on shutdown. Skipping cleanup to prevent failures. If unloading + // and not leaking these threads becomes a priority we will have to reimplement + // cleanup here. } } diff --git a/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c b/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c index a62ddf3aec9b..ed00c37e1a1f 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c +++ b/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c @@ -4630,26 +4630,10 @@ ep_rt_mono_runtime_provider_init (void) void ep_rt_mono_runtime_provider_fini (void) { - if (_sampled_thread_callstacks) - g_array_free (_sampled_thread_callstacks, TRUE); - _sampled_thread_callstacks = NULL; - - _max_sampled_thread_count = 32; - - g_free (_runtime_helper_compile_method_jitinfo); - _runtime_helper_compile_method_jitinfo = NULL; - - if (_runtime_helper_compile_method) - mono_free_method (_runtime_helper_compile_method); - _runtime_helper_compile_method = NULL; - - g_free (_monitor_enter_method_jitinfo); - _monitor_enter_method_jitinfo = NULL; - _monitor_enter_method = NULL; - - g_free (_monitor_enter_v4_method_jitinfo); - _monitor_enter_v4_method_jitinfo = NULL; - _monitor_enter_v4_method = NULL; + // We were cleaning up resources (mutexes, tls data, etc) here but it races with + // other threads on shutdown. Skipping cleanup to prevent failures. If unloading + // and not leaking these threads becomes a priority we will have to reimplement + // cleanup here. if (_ep_rt_mono_default_profiler_provider) { mono_profiler_set_jit_begin_callback (_ep_rt_mono_default_profiler_provider, NULL); @@ -4680,14 +4664,6 @@ ep_rt_mono_runtime_provider_fini (void) _gc_heap_dump_requests = 0; _gc_heap_dump_count = 0; _gc_heap_dump_trigger_count = 0; - - dn_vector_dispose (&_gc_heap_dump_requests_data); - memset (&_gc_heap_dump_requests_data, 0, sizeof (_gc_heap_dump_requests_data)); - - dn_umap_dispose (&_gc_roots_table); - memset (&_gc_roots_table, 0, sizeof (_gc_roots_table)); - - ep_rt_spin_lock_free (&_gc_lock); } void diff --git a/src/mono/mono/eventpipe/ep-rt-mono.c b/src/mono/mono/eventpipe/ep-rt-mono.c index 0aa3518df7af..a8890ca4bf66 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono.c +++ b/src/mono/mono/eventpipe/ep-rt-mono.c @@ -852,44 +852,19 @@ ep_rt_mono_init_finish (void) void ep_rt_mono_fini (void) { - // Avoid cleaning up resources to prevent cleaning up out from under running - // threads. - if (!mono_runtime_is_shutting_down ()) - return; - ep_rt_mono_runtime_provider_fini (); ep_rt_mono_profiler_provider_fini (); - if (_eventpipe_initialized) - mono_rand_close (_rand_provider); - - _rand_provider = NULL; - _eventpipe_initialized = FALSE; - - _ep_rt_mono_runtime_initialized = FALSE; - if (_ep_rt_mono_default_profiler_provider) { mono_profiler_set_runtime_initialized_callback (_ep_rt_mono_default_profiler_provider, NULL); mono_profiler_set_thread_started_callback (_ep_rt_mono_default_profiler_provider, NULL); mono_profiler_set_thread_stopped_callback (_ep_rt_mono_default_profiler_provider, NULL); } - _ep_rt_mono_default_profiler_provider = NULL; - - if (_ep_rt_mono_thread_holder_tls_id) - mono_native_tls_free (_ep_rt_mono_thread_holder_tls_id); - _ep_rt_mono_thread_holder_tls_id = 0; - - if (_thread_data_tls_id) - mono_native_tls_free (_thread_data_tls_id); - _thread_data_tls_id = 0; - - _ep_rt_mono_os_cmd_line_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED; - _ep_rt_mono_os_cmd_line = NULL; - - _ep_rt_mono_managed_cmd_line_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED; - _ep_rt_mono_managed_cmd_line = NULL; - - ep_rt_spin_lock_free (&_ep_rt_mono_config_lock); + + // We were cleaning up resources (mutexes, tls data, etc) here but it races with + // other threads on shutdown. Skipping cleanup to prevent failures. If unloading + // and not leaking these threads becomes a priority we will have to reimplement + // cleanup here. } void diff --git a/src/mono/mono/metadata/appdomain.c b/src/mono/mono/metadata/appdomain.c index e41b4fb1ca8b..f0a7789108d5 100644 --- a/src/mono/mono/metadata/appdomain.c +++ b/src/mono/mono/metadata/appdomain.c @@ -99,7 +99,11 @@ static const char * runtimeconfig_json_get_buffer (MonovmRuntimeConfigArguments *arg, MonoFileMap **file_map, gpointer *buf_handle); static void -runtimeconfig_json_read_props (const char *ptr, const char **endp, int nprops, gunichar2 **dest_keys, gunichar2 **dest_values); +runtimeconfig_json_read_props ( + const char *ptr, const char **endp, int nprops, + gunichar2 **dest_keys, guint32 *dest_key_lengths, + gunichar2 **dest_values, guint32 *dest_value_lengths +); static MonoLoadFunc load_function = NULL; @@ -846,17 +850,19 @@ void mono_runtime_install_appctx_properties (void) { ERROR_DECL (error); - gpointer args [3]; + gpointer args [5]; int n_runtimeconfig_json_props = 0; int n_combined_props; gunichar2 **combined_keys; gunichar2 **combined_values; + guint32 *combined_key_lengths; + guint32 *combined_value_lengths; MonoFileMap *runtimeconfig_json_map = NULL; gpointer runtimeconfig_json_map_handle = NULL; const char *buffer_start = runtimeconfig_json_get_buffer (runtime_config_arg, &runtimeconfig_json_map, &runtimeconfig_json_map_handle); const char *buffer = buffer_start; - MonoMethod *setup = mono_class_get_method_from_name_checked (mono_class_get_appctx_class (), "Setup", 3, 0, error); + MonoMethod *setup = mono_class_get_method_from_name_checked (mono_class_get_appctx_class (), "Setup", 5, 0, error); g_assert (setup); // FIXME: TRUSTED_PLATFORM_ASSEMBLIES is very large @@ -867,19 +873,31 @@ mono_runtime_install_appctx_properties (void) n_combined_props = n_appctx_props + n_runtimeconfig_json_props; combined_keys = g_new0 (gunichar2 *, n_combined_props); + combined_key_lengths = g_new0 (guint32, n_combined_props); combined_values = g_new0 (gunichar2 *, n_combined_props); + combined_value_lengths = g_new0 (guint32, n_combined_props); for (int i = 0; i < n_appctx_props; ++i) { - combined_keys [i] = g_utf8_to_utf16 (appctx_keys [i], -1, NULL, NULL, NULL); - combined_values [i] = g_utf8_to_utf16 (appctx_values [i], -1, NULL, NULL, NULL); + glong num_chars; + combined_keys [i] = g_utf8_to_utf16 (appctx_keys [i], -1, NULL, &num_chars, NULL); + // HACK: items_written from g_utf8_to_utf16 includes the null terminator unless you pass an explicit length. + combined_key_lengths [i] = GLONG_TO_UINT32 (num_chars ? num_chars - 1 : 0); + combined_values [i] = g_utf8_to_utf16 (appctx_values [i], -1, NULL, &num_chars, NULL); + combined_value_lengths [i] = GLONG_TO_UINT32 (num_chars ? num_chars - 1 : 0); } - runtimeconfig_json_read_props (buffer, &buffer, n_runtimeconfig_json_props, combined_keys + n_appctx_props, combined_values + n_appctx_props); + runtimeconfig_json_read_props ( + buffer, &buffer, n_runtimeconfig_json_props, + combined_keys + n_appctx_props, combined_key_lengths + n_appctx_props, + combined_values + n_appctx_props, combined_value_lengths + n_appctx_props + ); - /* internal static unsafe void Setup(char** pNames, char** pValues, int count) */ + /* internal static unsafe void Setup(char** pNames, uint* pNameLengths, char** pValues, uint* pValueLengths, int count) */ args [0] = combined_keys; - args [1] = combined_values; - args [2] = &n_combined_props; + args [1] = combined_key_lengths; + args [2] = combined_values; + args [3] = combined_value_lengths; + args [4] = &n_combined_props; mono_runtime_invoke_checked (setup, NULL, args, error); mono_error_assert_ok (error); @@ -900,6 +918,8 @@ mono_runtime_install_appctx_properties (void) } g_free (combined_keys); g_free (combined_values); + g_free (combined_key_lengths); + g_free (combined_value_lengths); for (int i = 0; i < n_appctx_props; ++i) { g_free (appctx_keys [i]); g_free (appctx_values [i]); @@ -949,17 +969,24 @@ runtimeconfig_json_get_buffer (MonovmRuntimeConfigArguments *arg, MonoFileMap ** } static void -runtimeconfig_json_read_props (const char *ptr, const char **endp, int nprops, gunichar2 **dest_keys, gunichar2 **dest_values) +runtimeconfig_json_read_props ( + const char *ptr, const char **endp, int nprops, + gunichar2 **dest_keys, guint32 *dest_key_lengths, + gunichar2 **dest_values, guint32 *dest_value_lengths +) { for (int i = 0; i < nprops; ++i) { int str_len; + glong chars_written; str_len = mono_metadata_decode_value (ptr, &ptr); - dest_keys [i] = g_utf8_to_utf16 (ptr, str_len, NULL, NULL, NULL); + dest_keys [i] = g_utf8_to_utf16 (ptr, str_len, NULL, &chars_written, NULL); + dest_key_lengths [i] = GLONG_TO_UINT32 (chars_written); ptr += str_len; str_len = mono_metadata_decode_value (ptr, &ptr); - dest_values [i] = g_utf8_to_utf16 (ptr, str_len, NULL, NULL, NULL); + dest_values [i] = g_utf8_to_utf16 (ptr, str_len, NULL, &chars_written, NULL); + dest_value_lengths [i] = GLONG_TO_UINT32 (chars_written); ptr += str_len; } diff --git a/src/mono/mono/metadata/bundled-resources-internals.h b/src/mono/mono/metadata/bundled-resources-internals.h index 1a8c03f4fb4e..34e911ba7a1e 100644 --- a/src/mono/mono/metadata/bundled-resources-internals.h +++ b/src/mono/mono/metadata/bundled-resources-internals.h @@ -17,6 +17,7 @@ typedef enum { typedef void (*free_bundled_resource_func)(void *, void*); +// WARNING: The layout of these structs cannot change because EmitBundleBase.cs depends on it! typedef struct _MonoBundledResource { MonoBundledResourceType type; const char *id; diff --git a/src/mono/mono/metadata/bundled-resources.c b/src/mono/mono/metadata/bundled-resources.c index 9eae4f5db8fa..17ddedb19c01 100644 --- a/src/mono/mono/metadata/bundled-resources.c +++ b/src/mono/mono/metadata/bundled-resources.c @@ -8,8 +8,11 @@ #include #include #include +#include "../native/containers/dn-simdhash-specializations.h" +#include "../native/containers/dn-simdhash-utils.h" -static GHashTable *bundled_resources = NULL; +static dn_simdhash_ght_t *bundled_resources = NULL; +static dn_simdhash_ptr_ptr_t *bundled_resource_key_lookup_table = NULL; static bool bundled_resources_contains_assemblies = false; static bool bundled_resources_contains_satellite_assemblies = false; @@ -31,8 +34,10 @@ mono_bundled_resources_free (void) { g_assert (mono_runtime_is_shutting_down ()); - g_hash_table_destroy (bundled_resources); + dn_simdhash_free (bundled_resources); + dn_simdhash_free (bundled_resource_key_lookup_table); bundled_resources = NULL; + bundled_resource_key_lookup_table = NULL; bundled_resources_contains_assemblies = false; bundled_resources_contains_satellite_assemblies = false; @@ -50,6 +55,12 @@ bundled_resources_value_destroy_func (void *resource) MonoBundledResource *value = (MonoBundledResource *)resource; if (value->free_func) value->free_func (resource, value->free_data); + + char *key; + if (dn_simdhash_ptr_ptr_try_get_value (bundled_resource_key_lookup_table, (void *)value->id, (void **)&key)) { + dn_simdhash_ptr_ptr_try_remove (bundled_resource_key_lookup_table, (void *)value->id); + g_free (key); + } } static bool @@ -62,48 +73,51 @@ bundled_resources_is_known_assembly_extension (const char *ext) #endif } -static gboolean -bundled_resources_resource_id_equal (const char *id_one, const char *id_two) +// If a bundled resource has a known assembly extension, we strip the extension from its name +// This ensures that lookups for foo.dll will work even if the assembly is in a webcil container +static char * +key_from_id (const char *id, char *buffer, guint buffer_len) { - const char *extension_one = strrchr (id_one, '.'); - const char *extension_two = strrchr (id_two, '.'); - if (extension_one && extension_two && bundled_resources_is_known_assembly_extension (extension_one) && bundled_resources_is_known_assembly_extension (extension_two)) { - size_t len_one = extension_one - id_one; - size_t len_two = extension_two - id_two; - return (len_one == len_two) && !strncmp (id_one, id_two, len_one); + size_t id_length = strlen (id), + extension_offset = -1; + const char *extension = g_memrchr (id, '.', id_length); + if (extension) + extension_offset = extension - id; + if (!buffer) { + // Add space for .dll and null terminator + buffer_len = (guint)(id_length + 6); + buffer = g_malloc (buffer_len); } + buffer[0] = 0; - return !strcmp (id_one, id_two); + if (extension_offset && bundled_resources_is_known_assembly_extension (extension)) { + // Subtract from buffer_len to make sure we have space for .dll + g_strlcpy (buffer, id, MIN(buffer_len - 4, extension_offset + 2)); + strcat (buffer, "dll"); + } else { + g_strlcpy (buffer, id, MIN(buffer_len, id_length + 1)); + } + + return buffer; } -static guint -bundled_resources_resource_id_hash (const char *id) +static gboolean +bundled_resources_resource_id_equal (const char *key_one, const char *key_two) { - const char *current = id; - const char *extension = NULL; - guint previous_hash = 0; - guint hash = 0; - - while (*current) { - hash = (hash << 5) - (hash + *current); - if (*current == '.') { - extension = current; - previous_hash = hash; - } - current++; - } - - // alias all extensions to .dll - if (extension && bundled_resources_is_known_assembly_extension (extension)) { - hash = previous_hash; - hash = (hash << 5) - (hash + 'd'); - hash = (hash << 5) - (hash + 'l'); - hash = (hash << 5) - (hash + 'l'); - } + return strcmp (key_one, key_two) == 0; +} - return hash; +static guint32 +bundled_resources_resource_id_hash (const char *key) +{ + // FIXME: Seed + // FIXME: We should cache the hash code so rehashes are cheaper + return MurmurHash3_32_streaming ((const uint8_t *)key, 0); } +static MonoBundledResource * +bundled_resources_get (const char *id); + //--------------------------------------------------------------------------------------- // // mono_bundled_resources_add handles bundling of many types of resources to circumvent @@ -126,11 +140,12 @@ bundled_resources_resource_id_hash (const char *id) void mono_bundled_resources_add (MonoBundledResource **resources_to_bundle, uint32_t len) { - MonoDomain *domain = mono_get_root_domain (); - g_assert (!domain); - if (!bundled_resources) - bundled_resources = g_hash_table_new_full ((GHashFunc)bundled_resources_resource_id_hash, (GEqualFunc)bundled_resources_resource_id_equal, NULL, bundled_resources_value_destroy_func); + // FIXME: Choose a good initial capacity to avoid rehashes during startup. I picked one at random + bundled_resources = dn_simdhash_ght_new_full ((GHashFunc)bundled_resources_resource_id_hash, (GEqualFunc)bundled_resources_resource_id_equal, NULL, bundled_resources_value_destroy_func, 2048, NULL); + + if (!bundled_resource_key_lookup_table) + bundled_resource_key_lookup_table = dn_simdhash_ptr_ptr_new (2048, NULL); bool assemblyAdded = false; bool satelliteAssemblyAdded = false; @@ -143,7 +158,13 @@ mono_bundled_resources_add (MonoBundledResource **resources_to_bundle, uint32_t if (resource_to_bundle->type == MONO_BUNDLED_SATELLITE_ASSEMBLY) satelliteAssemblyAdded = true; - g_hash_table_insert (bundled_resources, (gpointer) resource_to_bundle->id, resource_to_bundle); + // Generate the hash key for the id (strip certain extensions) and store it + // so that we can free it later when freeing the bundled data + char *key = key_from_id (resource_to_bundle->id, NULL, 0); + dn_simdhash_ptr_ptr_try_add (bundled_resource_key_lookup_table, (void *)resource_to_bundle->id, key); + + g_assert (dn_simdhash_ght_try_add (bundled_resources, (gpointer) key, resource_to_bundle)); + // g_assert (bundled_resources_get (resource_to_bundle->id) == resource_to_bundle); } if (assemblyAdded) @@ -172,7 +193,12 @@ bundled_resources_get (const char *id) if (!bundled_resources) return NULL; - return g_hash_table_lookup (bundled_resources, id); + char key_buffer[1024]; + key_from_id(id, key_buffer, sizeof(key_buffer)); + + MonoBundledResource *result = NULL; + dn_simdhash_ght_try_get_value (bundled_resources, key_buffer, (void **)&result); + return result; } //--------------------------------------------------------------------------------------- @@ -364,9 +390,7 @@ bool mono_bundled_resources_get_data_resource_values (const char *id, const uint8_t **data_out, uint32_t *size_out) { MonoBundledDataResource *bundled_data_resource = bundled_resources_get_data_resource (id); - if (!bundled_data_resource || - !bundled_data_resource->data.data || - bundled_data_resource->data.size == 0) + if (!bundled_data_resource || !bundled_data_resource->data.data) return false; if (data_out) diff --git a/src/mono/mono/metadata/class-getters.h b/src/mono/mono/metadata/class-getters.h index 57ff9afefceb..30cc66fcf7c1 100644 --- a/src/mono/mono/metadata/class-getters.h +++ b/src/mono/mono/metadata/class-getters.h @@ -48,6 +48,7 @@ MONO_CLASS_GETTER(m_class_is_interfaces_inited, gboolean, , MonoClass, interface MONO_CLASS_GETTER(m_class_is_simd_type, gboolean, , MonoClass, simd_type) MONO_CLASS_GETTER(m_class_is_has_finalize_inited, gboolean, , MonoClass, has_finalize_inited) MONO_CLASS_GETTER(m_class_is_fields_inited, gboolean, , MonoClass, fields_inited) +MONO_CLASS_GETTER(m_class_is_exception_class, gboolean, , MonoClass, is_exception_class) MONO_CLASS_GETTER(m_class_has_failure, gboolean, , MonoClass, has_failure) MONO_CLASS_GETTER(m_class_has_deferred_failure, gboolean, , MonoClass, has_deferred_failure) MONO_CLASS_GETTER(m_class_has_weak_fields, gboolean, , MonoClass, has_weak_fields) @@ -56,6 +57,7 @@ MONO_CLASS_GETTER(m_class_get_parent, MonoClass *, , MonoClass, parent) MONO_CLASS_GETTER(m_class_get_nested_in, MonoClass *, , MonoClass, nested_in) MONO_CLASS_GETTER(m_class_get_image, MonoImage *, , MonoClass, image) MONO_CLASS_GETTER(m_class_get_name, const char *, , MonoClass, name) +MONO_CLASS_GETTER(m_class_get_name_hash, guint, , MonoClass, name_hash) MONO_CLASS_GETTER(m_class_get_name_space, const char *, , MonoClass, name_space) MONO_CLASS_GETTER(m_class_get_type_token, guint32, , MonoClass, type_token) MONO_CLASS_GETTER(m_class_get_vtable_size, int, , MonoClass, vtable_size) diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index d9cfd751c819..8608dc30bfc6 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -500,6 +500,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError } klass->name = name; + klass->name_hash = mono_metadata_str_hash (name); klass->name_space = nspace; MONO_PROFILER_RAISE (class_loading, (klass)); @@ -734,6 +735,17 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError } } + // compute is_exception_class, used by interp to avoid inlining exception handling code + if ( + klass->parent && !m_class_is_valuetype (klass) && + !m_class_is_interface (klass) + ) { + if (m_class_is_exception_class (klass->parent)) + klass->is_exception_class = 1; + else if (!strcmp (klass->name, "Exception") && !strcmp(klass->name_space, "System")) + klass->is_exception_class = 1; + } + mono_loader_unlock (); MONO_PROFILER_RAISE (class_loaded, (klass)); @@ -909,6 +921,7 @@ mono_class_create_generic_inst (MonoGenericClass *gclass) } klass->name = gklass->name; + klass->name_hash = gklass->name_hash; klass->name_space = gklass->name_space; klass->image = gklass->image; @@ -924,6 +937,7 @@ mono_class_create_generic_inst (MonoGenericClass *gclass) klass->this_arg.byref__ = TRUE; klass->is_inlinearray = gklass->is_inlinearray; klass->inlinearray_value = gklass->inlinearray_value; + klass->is_exception_class = gklass->is_exception_class; klass->enumtype = gklass->enumtype; klass->valuetype = gklass->valuetype; @@ -1154,6 +1168,7 @@ mono_class_create_bounded_array (MonoClass *eclass, guint32 rank, gboolean bound name [nsize + maxrank + bounded] = ']'; name [nsize + maxrank + bounded + 1] = 0; klass->name = mm ? mono_mem_manager_strdup (mm, name) : mono_image_strdup (image, name); + klass->name_hash = mono_metadata_str_hash (klass->name); g_free (name); klass->type_token = 0; @@ -1508,6 +1523,7 @@ mono_class_create_ptr (MonoType *type) result->name_space = el_class->name_space; name = g_strdup_printf ("%s*", el_class->name); result->name = mm ? mono_mem_manager_strdup (mm, name) : mono_image_strdup (image, name); + result->name_hash = mono_metadata_str_hash (result->name); result->class_kind = MONO_CLASS_POINTER; g_free (name); @@ -1585,6 +1601,7 @@ mono_class_create_fnptr (MonoMethodSignature *sig) result->parent = NULL; /* no parent for PTR types */ result->name_space = "System"; result->name = "MonoFNPtrFakeClass"; + result->name_hash = mono_metadata_str_hash (result->name); result->class_kind = MONO_CLASS_POINTER; result->image = mono_defaults.corlib; /* need to fix... */ @@ -2314,7 +2331,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ instance_size = MAX (real_size, instance_size); - if (instance_size & (min_align - 1)) { + if (instance_size & (min_align - 1) && !explicit_size) { instance_size += min_align - 1; instance_size &= ~(min_align - 1); } diff --git a/src/mono/mono/metadata/class-internals.h b/src/mono/mono/metadata/class-internals.h index e7b56c72a38e..b423350d2981 100644 --- a/src/mono/mono/metadata/class-internals.h +++ b/src/mono/mono/metadata/class-internals.h @@ -96,6 +96,7 @@ struct _MonoMethodWrapper { MonoMethodHeader *header; MonoMemoryManager *mem_manager; void *method_data; + unsigned int inflate_wrapper_data : 1; /* method_data[MONO_MB_ILGEN_INFLATE_WRAPPER_INFO_IDX] is an MonoMethodBuilderInflateWrapperData array */ }; struct _MonoDynamicMethod { diff --git a/src/mono/mono/metadata/class-private-definition.h b/src/mono/mono/metadata/class-private-definition.h index 9beb3d40bad0..1e0c01ab336b 100644 --- a/src/mono/mono/metadata/class-private-definition.h +++ b/src/mono/mono/metadata/class-private-definition.h @@ -68,9 +68,8 @@ struct _MonoClass { guint no_special_static_fields : 1; /* has no thread/context static fields */ guint nested_classes_inited : 1; /* Whenever nested_class is initialized */ - - /* next byte*/ guint interfaces_inited : 1; /* interfaces is initialized */ + /* next byte*/ guint simd_type : 1; /* class is a simd intrinsic type */ guint has_finalize_inited : 1; /* has_finalize is initialized */ guint fields_inited : 1; /* setup_fields () has finished */ @@ -79,6 +78,8 @@ struct _MonoClass { guint has_dim_conflicts : 1; /* Class has conflicting default interface methods */ guint any_field_has_auto_layout : 1; /* a field in this type's layout uses auto-layout */ guint has_deferred_failure : 1; + /* next byte*/ + guint is_exception_class : 1; /* is System.Exception or derived from it */ MonoClass *parent; MonoClass *nested_in; @@ -99,7 +100,8 @@ struct _MonoClass { guint16 *interface_offsets_packed; guint8 *interface_bitmap; - gint32 inlinearray_value; /* System.Runtime.CompilerServices.InlineArrayAttribute length value */ + gint32 inlinearray_value; /* System.Runtime.CompilerServices.InlineArrayAttribute length value */ + guint name_hash; MonoClass **interfaces; diff --git a/src/mono/mono/metadata/class-setup-vtable.c b/src/mono/mono/metadata/class-setup-vtable.c index 9a235c1ec0cc..b2f13d72dfc4 100644 --- a/src/mono/mono/metadata/class-setup-vtable.c +++ b/src/mono/mono/metadata/class-setup-vtable.c @@ -773,6 +773,11 @@ mono_method_get_method_definition (MonoMethod *method) static gboolean verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum) { +#ifndef ENABLE_CHECKED_BUILD + if (klass->image == mono_defaults.corlib) + return TRUE; +#endif + int i; for (i = 0; i < onum; ++i) { @@ -1760,7 +1765,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o MonoMethod *override = iface_overrides [i*2 + 1]; if (mono_class_is_gtd (override->klass)) { override = mono_class_inflate_generic_method_full_checked (override, ic, mono_class_get_context (ic), error); - } + } // there used to be code here to inflate decl if decl->is_inflated, but in https://github.com/dotnet/runtime/pull/64102#discussion_r790019545 we // think that this does not correspond to any real code. if (!apply_override (klass, ic, vtable, decl, override, &override_map, &override_class_map, &conflict_map)) diff --git a/src/mono/mono/metadata/class.c b/src/mono/mono/metadata/class.c index 05da1332e301..ec0ddbe2f85a 100644 --- a/src/mono/mono/metadata/class.c +++ b/src/mono/mono/metadata/class.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -1168,7 +1169,7 @@ MonoMethod* mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error) { MonoMethod *result; - MonoMethodInflated *iresult, *cached; + MonoMethodInflated *iresult, *cached = NULL; MonoMethodSignature *sig; MonoGenericContext tmp_context; @@ -1223,8 +1224,8 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k // check cache mono_mem_manager_lock (mm); if (!mm->gmethod_cache) - mm->gmethod_cache = g_hash_table_new_full (inflated_method_hash, inflated_method_equal, NULL, (GDestroyNotify)free_inflated_method); - cached = (MonoMethodInflated *)g_hash_table_lookup (mm->gmethod_cache, iresult); + mm->gmethod_cache = dn_simdhash_ght_new_full (inflated_method_hash, inflated_method_equal, NULL, (GDestroyNotify)free_inflated_method, 0, NULL); + dn_simdhash_ght_try_get_value (mm->gmethod_cache, iresult, (void **)&cached); mono_mem_manager_unlock (mm); if (cached) { @@ -1263,6 +1264,17 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1)); memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1)); + if (mw->inflate_wrapper_data) { + mono_mb_inflate_generic_wrapper_data (context, (gpointer*)resw->method_data, error); + if (!is_ok (error)) { + g_free (resw->method_data); + goto fail; + } + // we can't set inflate_wrapper_data to 0 on the result, it's possible it + // will need to be inflated again (for example in the method_inst == + // generic_container->context.method_inst case, below) + resw->inflate_wrapper_data = 1; + } } if (iresult->context.method_inst) { @@ -1319,9 +1331,10 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k // check cache mono_mem_manager_lock (mm); - cached = (MonoMethodInflated *)g_hash_table_lookup (mm->gmethod_cache, iresult); + cached = NULL; + dn_simdhash_ght_try_get_value (mm->gmethod_cache, iresult, (void **)&cached); if (!cached) { - g_hash_table_insert (mm->gmethod_cache, iresult, iresult); + dn_simdhash_ght_insert (mm->gmethod_cache, iresult, iresult); iresult->owner = mm; cached = iresult; } @@ -3037,18 +3050,22 @@ mono_image_init_name_cache (MonoImage *image) const char *name; const char *nspace; guint32 visib, nspace_index; - GHashTable *name_cache2, *nspace_table, *the_name_cache; + dn_simdhash_u32_ptr_t *name_cache2; + dn_simdhash_string_ptr_t *nspace_table, *the_name_cache; if (image->name_cache) return; - the_name_cache = g_hash_table_new (g_str_hash, g_str_equal); + // TODO: Figure out a good initial capacity for this table by doing a scan, + // or just pre-reserve a reasonable amount of space based on how many nspaces + // an image typically has + the_name_cache = dn_simdhash_string_ptr_new (0, NULL); if (image_is_dynamic (image)) { mono_image_lock (image); if (image->name_cache) { /* Somebody initialized it before us */ - g_hash_table_destroy (the_name_cache); + dn_simdhash_free (the_name_cache); } else { mono_atomic_store_release (&image->name_cache, the_name_cache); } @@ -3057,7 +3074,7 @@ mono_image_init_name_cache (MonoImage *image) } /* Temporary hash table to avoid lookups in the nspace_table */ - name_cache2 = g_hash_table_new (NULL, NULL); + name_cache2 = dn_simdhash_u32_ptr_new (0, NULL); /* FIXME: metadata-update */ int rows = table_info_get_rows (t); @@ -3074,14 +3091,13 @@ mono_image_init_name_cache (MonoImage *image) nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]); nspace_index = cols [MONO_TYPEDEF_NAMESPACE]; - nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index)); - if (!nspace_table) { - nspace_table = g_hash_table_new (g_str_hash, g_str_equal); - g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table); - g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index), - nspace_table); + if (!dn_simdhash_u32_ptr_try_get_value (name_cache2, nspace_index, (void **)&nspace_table)) { + // FIXME: Compute an appropriate capacity for this table to avoid growing it + nspace_table = dn_simdhash_string_ptr_new (0, NULL); + dn_simdhash_string_ptr_try_add (the_name_cache, nspace, nspace_table); + dn_simdhash_u32_ptr_try_add (name_cache2, nspace_index, nspace_table); } - g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i)); + dn_simdhash_string_ptr_try_add (nspace_table, name, GUINT_TO_POINTER (i)); } /* Load type names from EXPORTEDTYPES table */ @@ -3102,23 +3118,22 @@ mono_image_init_name_cache (MonoImage *image) nspace = mono_metadata_string_heap (image, exptype_cols [MONO_EXP_TYPE_NAMESPACE]); nspace_index = exptype_cols [MONO_EXP_TYPE_NAMESPACE]; - nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index)); - if (!nspace_table) { - nspace_table = g_hash_table_new (g_str_hash, g_str_equal); - g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table); - g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index), - nspace_table); + if (!dn_simdhash_u32_ptr_try_get_value (name_cache2, nspace_index, (void **)&nspace_table)) { + // FIXME: Compute an appropriate capacity for this table to avoid growing it + nspace_table = dn_simdhash_string_ptr_new (0, NULL); + dn_simdhash_string_ptr_try_add (the_name_cache, nspace, nspace_table); + dn_simdhash_u32_ptr_try_add (name_cache2, nspace_index, nspace_table); } - g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1))); + dn_simdhash_string_ptr_try_add (nspace_table, name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1))); } } - g_hash_table_destroy (name_cache2); + dn_simdhash_free (name_cache2); mono_image_lock (image); if (image->name_cache) { /* Somebody initialized it before us */ - g_hash_table_destroy (the_name_cache); + dn_simdhash_free (the_name_cache); } else { mono_atomic_store_release (&image->name_cache, the_name_cache); } @@ -3133,23 +3148,19 @@ void mono_image_add_to_name_cache (MonoImage *image, const char *nspace, const char *name, guint32 index) { - GHashTable *nspace_table; - GHashTable *name_cache; - guint32 old_index; + dn_simdhash_string_ptr_t *nspace_table, *name_cache; mono_image_init_name_cache (image); mono_image_lock (image); name_cache = image->name_cache; - if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) { - nspace_table = g_hash_table_new (g_str_hash, g_str_equal); - g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table); + if (!dn_simdhash_string_ptr_try_get_value (name_cache, nspace, (void **)&nspace_table)) { + nspace_table = dn_simdhash_string_ptr_new (0, NULL); + dn_simdhash_string_ptr_try_add (name_cache, nspace, nspace_table); } - if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name)))) - g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name); - - g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index)); + if (!dn_simdhash_string_ptr_try_add (nspace_table, name, GUINT_TO_POINTER (index))) + g_error ("overrwritting old token ? on image %s for type %s::%s", image->name, nspace, name); mono_image_unlock (image); } @@ -3160,9 +3171,8 @@ typedef struct { } FindAllUserData; static void -find_all_nocase (gpointer key, gpointer value, gpointer user_data) +find_all_nocase (const char *name, gpointer value, gpointer user_data) { - char *name = (char*)key; FindAllUserData *data = (FindAllUserData*)user_data; if (mono_utf8_strcasecmp (name, (char*)data->key) == 0) data->values = g_slist_prepend (data->values, value); @@ -3174,9 +3184,8 @@ typedef struct { } FindUserData; static void -find_nocase (gpointer key, gpointer value, gpointer user_data) +find_nocase (const char *name, gpointer value, gpointer user_data) { - char *name = (char*)key; FindUserData *data = (FindUserData*)user_data; if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0)) @@ -3303,7 +3312,7 @@ search_modules (MonoImage *image, const char *name_space, const char *name, gboo static MonoClass * mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, gboolean case_sensitive, MonoError *error) { - GHashTable *nspace_table = NULL; + dn_simdhash_string_ptr_t *nspace_table = NULL; MonoImage *loaded_image = NULL; guint32 token = 0; MonoClass *klass; @@ -3350,10 +3359,11 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons mono_image_lock (image); if (case_sensitive) { - nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space); - - if (nspace_table) - token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name)); + if (dn_simdhash_string_ptr_try_get_value (image->name_cache, name_space, (void **)&nspace_table)) { + void * temp; + if (dn_simdhash_string_ptr_try_get_value (nspace_table, name, &temp)) + token = GPOINTER_TO_UINT(temp); + } } else { FindAllUserData all_user_data = { name_space, NULL }; FindUserData user_data = { name, NULL }; @@ -3361,12 +3371,12 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons // We're forced to check all matching namespaces, not just the first one found, // because our desired type could be in any of the ones that match case-insensitively. - g_hash_table_foreach (image->name_cache, find_all_nocase, &all_user_data); + dn_simdhash_string_ptr_foreach (image->name_cache, find_all_nocase, &all_user_data); values = all_user_data.values; while (values && !user_data.value) { - nspace_table = (GHashTable*)values->data; - g_hash_table_foreach (nspace_table, find_nocase, &user_data); + nspace_table = (dn_simdhash_string_ptr_t *)values->data; + dn_simdhash_string_ptr_foreach (nspace_table, find_nocase, &user_data); values = values->next; } @@ -4334,12 +4344,16 @@ mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass) } return TRUE; } -/*Check if @candidate implements the interface @target*/ + static gboolean -mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate) +mono_class_implement_interface_slow_cached (MonoClass *target, MonoClass *candidate, dn_simdhash_ptrpair_ptr_t *cache); + +static gboolean +mono_class_implement_interface_slow_uncached (MonoClass *target, MonoClass *candidate, dn_simdhash_ptrpair_ptr_t *cache) { ERROR_DECL (error); int i; + gboolean is_variant = mono_class_has_variant_generic_params (target); if (is_variant && MONO_CLASS_IS_INTERFACE_INTERNAL (candidate)) { @@ -4368,7 +4382,7 @@ mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate) return TRUE; if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class)) return TRUE; - if (mono_class_implement_interface_slow (target, iface_class)) + if (mono_class_implement_interface_slow_cached (target, iface_class, cache)) return TRUE; } } @@ -4393,7 +4407,7 @@ mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate) if (is_variant && mono_class_is_variant_compatible_slow (target, candidate_interfaces [i])) return TRUE; - if (mono_class_implement_interface_slow (target, candidate_interfaces [i])) + if (mono_class_implement_interface_slow_cached (target, candidate_interfaces [i], cache)) return TRUE; } } @@ -4403,6 +4417,107 @@ mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate) return FALSE; } +// #define LOG_INTERFACE_CACHE_HITS 1 + +#if LOG_INTERFACE_CACHE_HITS +static gint64 implement_interface_hits = 0, implement_interface_misses = 0; + +static void +log_hit_rate (dn_simdhash_ptrpair_ptr_t *cache) +{ + gint64 total_calls = implement_interface_hits + implement_interface_misses; + if ((total_calls % 500) != 0) + return; + double hit_rate = implement_interface_hits * 100.0 / total_calls; + g_printf ("implement_interface cache hit rate: %f (%lld total calls). Overflow count: %u\n", hit_rate, total_calls, dn_simdhash_overflow_count (cache)); +} +#endif + +static gboolean +mono_class_implement_interface_slow_cached (MonoClass *target, MonoClass *candidate, dn_simdhash_ptrpair_ptr_t *cache) +{ + gpointer cached_result = NULL; + dn_ptrpair_t key = { target, candidate }; + gboolean result = 0, cache_hit = 0; + + // Skip the caching logic for exact matches + if (candidate == target) + return TRUE; + + cache_hit = dn_simdhash_ptrpair_ptr_try_get_value (cache, key, &cached_result); + if (cache_hit) { + // Testing shows a cache hit rate of 60% on S.R.Tests and S.T.J.Tests, + // and 40-50% for small app startup. Near-zero overflow count. +#if LOG_INTERFACE_CACHE_HITS + implement_interface_hits++; + log_hit_rate (cache); +#endif + result = (cached_result != NULL); +#ifndef ENABLE_CHECKED_BUILD + return result; +#endif + } + + gboolean uncached_result = mono_class_implement_interface_slow_uncached (target, candidate, cache); + + if (!cache_hit) { +#if LOG_INTERFACE_CACHE_HITS + implement_interface_misses++; + log_hit_rate (cache); +#endif + dn_simdhash_ptrpair_ptr_try_add (cache, key, uncached_result ? GUINT_TO_POINTER(1) : NULL); + } + +#ifdef ENABLE_CHECKED_BUILD + if (cache_hit) { + if (result != uncached_result) + g_print ( + "Cache mismatch for %s.%s and %s.%s: cached=%d, uncached=%d\n", + m_class_get_name_space (target), m_class_get_name (target), + m_class_get_name_space (candidate), m_class_get_name (candidate), + result, uncached_result + ); + g_assert (result == uncached_result); + } +#endif + return uncached_result; +} + +static dn_simdhash_ptrpair_ptr_t *implement_interface_scratch_cache = NULL; + +/*Check if @candidate implements the interface @target*/ +static gboolean +mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate) +{ + gpointer cas_result; + gboolean result; + dn_simdhash_ptrpair_ptr_t *cache = (dn_simdhash_ptrpair_ptr_t *)mono_atomic_xchg_ptr ((volatile gpointer *)&implement_interface_scratch_cache, NULL); + if (!cache) + // Roughly 64KB of memory usage and big enough to have fast lookups + // Smaller is viable but makes the hit rate worse + cache = dn_simdhash_ptrpair_ptr_new (2048, NULL); + else if (dn_simdhash_count (cache) >= 2250) { + // FIXME: 2250 is arbitrary (roughly 256 11-item buckets w/load factor) + // One step down reduces hit rate by approximately 2-4% + // HACK: Only clear the scratch cache once it gets too big. + // The pattern is that (especially during startup), we have lots + // of mono_class_implement_interface_slow calls back to back that + // perform similar checks, so keeping the cache data around between + // sequential calls will potentially optimize them a lot. + dn_simdhash_clear (cache); + } + + result = mono_class_implement_interface_slow_cached (target, candidate, cache); + + // Under most circumstances we won't have multiple threads competing to run implement_interface_slow, + // so it's not worth making this thread-local and potentially keeping a cache instance around per-thread. + cas_result = mono_atomic_cas_ptr ((volatile gpointer *)&implement_interface_scratch_cache, cache, NULL); + if (cas_result != NULL) + dn_simdhash_free (cache); + + return result; +} + /* * Check if @oklass can be assigned to @klass. * This function does the same as mono_class_is_assignable_from_internal but is safe to be used from mono_class_init_internal context. @@ -4419,8 +4534,9 @@ mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate) return TRUE; /*If target is not an interface there is no need to check them.*/ - if (MONO_CLASS_IS_INTERFACE_INTERNAL (target)) + if (MONO_CLASS_IS_INTERFACE_INTERNAL (target)) { return mono_class_implement_interface_slow (target, candidate); + } if (m_class_is_delegate (target) && mono_class_has_variant_generic_params (target)) return mono_class_is_variant_compatible (target, candidate, FALSE); @@ -5161,7 +5277,7 @@ mono_class_get_fields_internal (MonoClass *klass, gpointer *iter) * mono_class_get_methods: * \param klass the \c MonoClass to act on * - * This routine is an iterator routine for retrieving the fields in a class. + * This routine is an iterator routine for retrieving the methods in a class. * * You must pass a \c gpointer that points to zero and is treated as an opaque handle to * iterate over all of the elements. When no more values are diff --git a/src/mono/mono/metadata/debug-helpers.c b/src/mono/mono/metadata/debug-helpers.c index ff2463300767..7ef728eadd5f 100644 --- a/src/mono/mono/metadata/debug-helpers.c +++ b/src/mono/mono/metadata/debug-helpers.c @@ -39,6 +39,7 @@ struct MonoMethodDesc { char *args; guint num_args; gboolean include_namespace, klass_glob, name_glob; + gboolean match_wrappers; }; // This, instead of an array of pointers, to optimize away a pointer and a relocation per string. @@ -341,7 +342,7 @@ mono_context_get_desc (MonoGenericContext *context) * Creates a method description for \p name, which conforms to the following * specification: * - * [namespace.]classname:methodname[(args...)] + * [w:][namespace.]classname:methodname[(args...)] * * in all the loaded assemblies. * @@ -356,7 +357,13 @@ mono_method_desc_new (const char *name, gboolean include_namespace) char *class_name, *class_nspace, *method_name, *use_args, *end; int use_namespace; int generic_delim_stack; + int match_wrappers = 0; + /* if the name starts with w: or W: allow matching wrappers */ + if (strstr(name, "W:") == name || strstr(name, "w:") == name) { + name += 2; + match_wrappers = 1; + } class_nspace = g_strdup (name); use_args = strchr (class_nspace, '('); if (use_args) { @@ -414,6 +421,8 @@ mono_method_desc_new (const char *name, gboolean include_namespace) ++end; } } + if (match_wrappers) + result->match_wrappers = TRUE; return result; } @@ -431,6 +440,8 @@ mono_method_desc_from_method (MonoMethod *method) result->name = g_strdup (method->name); result->klass = g_strdup (method->klass->name); result->name_space = g_strdup (method->klass->name_space); + if (method->wrapper_type) + result->match_wrappers = TRUE; return result; } @@ -466,6 +477,9 @@ mono_method_desc_match (MonoMethodDesc *desc, MonoMethod *method) char *sig; gboolean name_match; + if (desc->match_wrappers && method->wrapper_type == MONO_WRAPPER_NONE) { + return FALSE; + } if (desc->name_glob && !strcmp (desc->name, "*")) return TRUE; #if 0 diff --git a/src/mono/mono/metadata/debug-mono-ppdb.c b/src/mono/mono/metadata/debug-mono-ppdb.c index 545e5713f45d..bcbbb4c7f2be 100644 --- a/src/mono/mono/metadata/debug-mono-ppdb.c +++ b/src/mono/mono/metadata/debug-mono-ppdb.c @@ -60,7 +60,7 @@ enum { MONO_HAS_CUSTOM_DEBUG_MASK = 0x1f }; -gboolean +gboolean mono_get_pe_debug_info_full (MonoImage *image, guint8 *out_guid, gint32 *out_age, gint32 *out_timestamp, guint8 **ppdb_data, int *ppdb_uncompressed_size, int *ppdb_compressed_size, char **pdb_path, GArray *pdb_checksum_hash_type, GArray *pdb_checksum) { @@ -761,20 +761,11 @@ mono_ppdb_lookup_locals (MonoDebugMethodInfo *minfo) return mono_ppdb_lookup_locals_internal (image, method_idx); } -/* -* We use this to pass context information to the row locator -*/ -typedef struct { - guint32 idx; /* The index that we are trying to locate */ - guint32 col_idx; /* The index in the row where idx may be stored */ - MonoTableInfo *t; /* pointer to the table */ - guint32 result; -} locator_t; - +// FIXME: This duplicates table_locator from metadata.c static int table_locator (const void *a, const void *b) { - locator_t *loc = (locator_t *)a; + mono_locator_t *loc = (mono_locator_t *)a; const char *bb = (const char *)b; guint32 table_index = GPTRDIFF_TO_UINT32 ((bb - loc->t->base) / loc->t->row_size); guint32 col; @@ -808,14 +799,16 @@ lookup_custom_debug_information (MonoImage* image, guint32 token, uint8_t parent { MonoTableInfo *tables = image->tables; MonoTableInfo *table = &tables[MONO_TABLE_CUSTOMDEBUGINFORMATION]; - locator_t loc; + mono_locator_t loc; if (!table->base) return 0; - loc.idx = (mono_metadata_token_index (token) << MONO_HAS_CUSTOM_DEBUG_BITS) | parent_type; - loc.col_idx = MONO_CUSTOMDEBUGINFORMATION_PARENT; - loc.t = table; + loc = mono_locator_init ( + table, + (mono_metadata_token_index (token) << MONO_HAS_CUSTOM_DEBUG_BITS) | parent_type, + MONO_CUSTOMDEBUGINFORMATION_PARENT + ); if (!mono_binary_search (&loc, table->base, table_info_get_rows (table), table->row_size, table_locator)) return NULL; diff --git a/src/mono/mono/metadata/icall-def.h b/src/mono/mono/metadata/icall-def.h index 766754d52008..53c95c8245fa 100644 --- a/src/mono/mono/metadata/icall-def.h +++ b/src/mono/mono/metadata/icall-def.h @@ -194,9 +194,8 @@ NOHANDLES(ICALL(NATIVE_RUNTIME_EVENT_SOURCE_16, "LogWaitHandleWaitStop", ves_ica ICALL_TYPE(ENUM, "System.Enum", ENUM_1) HANDLES(ENUM_1, "GetEnumValuesAndNames", ves_icall_System_Enum_GetEnumValuesAndNames, void, 3, (MonoQCallTypeHandle, MonoArrayOut, MonoArrayOut)) -HANDLES(ENUM_2, "InternalBoxEnum", ves_icall_System_Enum_InternalBoxEnum, void, 3, (MonoQCallTypeHandle, MonoObjectHandleOnStack, guint64)) -NOHANDLES(ICALL(ENUM_3, "InternalGetCorElementType", ves_icall_System_Enum_InternalGetCorElementType)) -HANDLES(ENUM_4, "InternalGetUnderlyingType", ves_icall_System_Enum_InternalGetUnderlyingType, void, 2, (MonoQCallTypeHandle, MonoObjectHandleOnStack)) +NOHANDLES(ICALL(ENUM_2, "InternalGetCorElementType", ves_icall_System_Enum_InternalGetCorElementType)) +HANDLES(ENUM_3, "InternalGetUnderlyingType", ves_icall_System_Enum_InternalGetUnderlyingType, void, 2, (MonoQCallTypeHandle, MonoObjectHandleOnStack)) ICALL_TYPE(ENV, "System.Environment", ENV_1) NOHANDLES(ICALL(ENV_1, "Exit", ves_icall_System_Environment_Exit)) @@ -440,6 +439,7 @@ HANDLES(RUNH_7, "InternalGetHashCode", ves_icall_System_Runtime_CompilerServices HANDLES(RUNH_3a, "PrepareMethod", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_PrepareMethod, void, 3, (MonoMethod_ptr, gpointer, int)) HANDLES(RUNH_4, "RunClassConstructor", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor, void, 1, (MonoType_ptr)) HANDLES(RUNH_5, "RunModuleConstructor", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor, void, 1, (MonoImage_ptr)) +HANDLES(RUNH_9, "SizeOf", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SizeOf, gint32, 1, (MonoQCallTypeHandle)) NOHANDLES(ICALL(RUNH_5h, "SufficientExecutionStack", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack)) ICALL_TYPE(GCH, "System.Runtime.InteropServices.GCHandle", GCH_1) @@ -489,8 +489,7 @@ HANDLES(MHAN_1, "GetFunctionPointer", ves_icall_RuntimeMethodHandle_GetFunctionP HANDLES(MAHN_3, "ReboxFromNullable", ves_icall_RuntimeMethodHandle_ReboxFromNullable, void, 2, (MonoObject, MonoObjectHandleOnStack)) HANDLES(MAHN_2, "ReboxToNullable", ves_icall_RuntimeMethodHandle_ReboxToNullable, void, 3, (MonoObject, MonoQCallTypeHandle, MonoObjectHandleOnStack)) -ICALL_TYPE(RT, "System.RuntimeType", RT_31) -HANDLES(RT_31, "AllocateValueType", ves_icall_System_RuntimeType_AllocateValueType, void, 3, (MonoQCallTypeHandle, MonoObject, MonoObjectHandleOnStack)) +ICALL_TYPE(RT, "System.RuntimeType", RT_1) HANDLES(RT_1, "CreateInstanceInternal", ves_icall_System_RuntimeType_CreateInstanceInternal, MonoObject, 1, (MonoQCallTypeHandle)) HANDLES(RT_28, "FunctionPointerReturnAndParameterTypes", ves_icall_RuntimeType_FunctionPointerReturnAndParameterTypes, GPtrArray_ptr, 1, (MonoQCallTypeHandle)) NOHANDLES(ICALL(RT_33, "GetCallingConventionFromFunctionPointerInternal", ves_icall_RuntimeType_GetCallingConventionFromFunctionPointerInternal)) diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 54cae6cef38d..a1ab947afd36 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -957,6 +957,9 @@ ves_icall_System_Runtime_RuntimeImports_Memmove (guint8 *destination, guint8 *so void ves_icall_System_Buffer_BulkMoveWithWriteBarrier (guint8 *destination, guint8 *source, size_t len, MonoType *type) { + if (len == 0 || destination == source) + return; + if (MONO_TYPE_IS_REFERENCE (type)) mono_gc_wbarrier_arrayref_copy_internal (destination, source, (guint)len); else @@ -1230,6 +1233,13 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InternalBox (MonoQCallT HANDLE_ON_STACK_SET (obj, NULL); } +gint32 +ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SizeOf (MonoQCallTypeHandle type, MonoError* error) +{ + int align; + return mono_type_size (type.type, &align); +} + MonoObjectHandle ves_icall_System_Object_MemberwiseClone (MonoObjectHandle this_obj, MonoError *error) { @@ -3713,28 +3723,6 @@ write_enum_value (void *mem, int type, guint64 value) return; } -void -ves_icall_System_Enum_InternalBoxEnum (MonoQCallTypeHandle enum_handle, MonoObjectHandleOnStack res, guint64 value, MonoError *error) -{ - MonoClass *enumc; - MonoObjectHandle resultHandle; - MonoType *etype; - - enumc = mono_class_from_mono_type_internal (enum_handle.type); - - mono_class_init_checked (enumc, error); - return_if_nok (error); - - etype = mono_class_enum_basetype_internal (enumc); - - resultHandle = mono_object_new_handle (enumc, error); - return_if_nok (error); - - write_enum_value (mono_handle_unbox_unsafe (resultHandle), etype->type, value); - - HANDLE_ON_STACK_SET (res, MONO_HANDLE_RAW (resultHandle)); -} - void ves_icall_System_Enum_InternalGetUnderlyingType (MonoQCallTypeHandle type_handle, MonoObjectHandleOnStack res, MonoError *error) { @@ -6179,16 +6167,16 @@ void ves_icall_System_Environment_FailFast (MonoStringHandle message, MonoExceptionHandle exception, MonoStringHandle errorSource, MonoError *error) { if (MONO_HANDLE_IS_NULL (errorSource)) { - g_warning ("Process terminated."); + g_warning_dont_trim ("Process terminated."); } else { char *errorSourceMsg = mono_string_handle_to_utf8 (errorSource, error); - g_warning ("Process terminated. %s", errorSourceMsg); + g_warning_dont_trim ("Process terminated. %s", errorSourceMsg); g_free (errorSourceMsg); } if (!MONO_HANDLE_IS_NULL (message)) { char *msg = mono_string_handle_to_utf8 (message, error); - g_warning (msg); + g_warning_dont_trim (msg); g_free (msg); } @@ -6274,29 +6262,6 @@ ves_icall_System_RuntimeType_CreateInstanceInternal (MonoQCallTypeHandle type_ha return mono_object_new_handle (klass, error); } -/* Only used for value types */ -void -ves_icall_System_RuntimeType_AllocateValueType (MonoQCallTypeHandle type_handle, MonoObjectHandle value_h, MonoObjectHandleOnStack res, MonoError *error) -{ - MonoType *type = type_handle.type; - MonoClass *klass = mono_class_from_mono_type_internal (type); - - mono_class_init_checked (klass, error); - goto_if_nok (error, error_ret); - - MonoObject *obj_res = mono_object_new_checked (klass, error); - goto_if_nok (error, error_ret); - - MonoObject *value = MONO_HANDLE_RAW (value_h); - if (value) - mono_value_copy_internal (mono_object_unbox_internal (obj_res), mono_object_unbox_internal (value), klass); - - HANDLE_ON_STACK_SET (res, obj_res); - return; -error_ret: - HANDLE_ON_STACK_SET (res, NULL); -} - MonoReflectionMethodHandle ves_icall_RuntimeMethodInfo_get_base_method (MonoReflectionMethodHandle m, MonoBoolean definition, MonoError *error) { diff --git a/src/mono/mono/metadata/image.c b/src/mono/mono/metadata/image.c index 23333b1b2a97..37dec87fe5e8 100644 --- a/src/mono/mono/metadata/image.c +++ b/src/mono/mono/metadata/image.c @@ -1730,60 +1730,6 @@ mono_image_open_from_data (char *data, guint32 data_len, gboolean need_copy, Mon return result; } -#ifdef HOST_WIN32 -static MonoImageStorage * -mono_image_storage_open_from_module_handle (HMODULE module_handle, const char *fname, gboolean has_entry_point) -{ - char *key = g_strdup (fname); - MonoImageStorage *published_storage = NULL; - if (mono_image_storage_tryaddref (key, &published_storage)) { - g_free (key); - return published_storage; - } - - MonoImageStorage *storage = g_new0 (MonoImageStorage, 1); - mono_refcount_init (storage, mono_image_storage_dtor); - storage->raw_data = (char*) module_handle; - storage->is_module_handle = TRUE; - storage->has_entry_point = !!has_entry_point; - - storage->key = key; - - MonoImageStorage *other_storage = NULL; - if (!mono_image_storage_trypublish (storage, &other_storage)) { - mono_image_storage_close (storage); - storage = other_storage; - } - return storage; -} - -/* fname is not duplicated. */ -MonoImage* -mono_image_open_from_module_handle (MonoAssemblyLoadContext *alc, HMODULE module_handle, char* fname, gboolean has_entry_point, MonoImageOpenStatus* status) -{ - MonoImage* image; - MonoCLIImageInfo* iinfo; - - MonoImageStorage *storage = mono_image_storage_open_from_module_handle (module_handle, fname, has_entry_point); - image = g_new0 (MonoImage, 1); - image->storage = storage; - mono_image_init_raw_data (image, storage); - iinfo = g_new0 (MonoCLIImageInfo, 1); - image->image_info = iinfo; - image->name = fname; - image->filename = g_strdup (image->name); - image->ref_count = has_entry_point ? 0 : 1; - image->alc = alc; - - MonoImageLoadOptions options = {0, }; - image = do_mono_image_load (image, status, &options); - if (image == NULL) - return NULL; - - return register_image (mono_alc_get_loaded_images (alc), image); -} -#endif - /** * mono_image_open_full: */ @@ -1969,6 +1915,12 @@ free_hash_table (gpointer key, gpointer val, gpointer user_data) g_hash_table_destroy ((GHashTable*)val); } +static void +free_simdhash_table (const char *key, gpointer val, gpointer user_data) +{ + dn_simdhash_free ((dn_simdhash_t*)val); +} + /* static void free_mr_signatures (gpointer key, gpointer val, gpointer user_data) @@ -2114,9 +2066,9 @@ mono_image_close_except_pools (MonoImage *image) } if (image->method_cache) - g_hash_table_destroy (image->method_cache); + dn_simdhash_free (image->method_cache); if (image->methodref_cache) - g_hash_table_destroy (image->methodref_cache); + dn_simdhash_free (image->methodref_cache); mono_internal_hash_table_destroy (&image->class_cache); mono_conc_hashtable_destroy (image->field_cache); if (image->array_cache) { @@ -2128,8 +2080,8 @@ mono_image_close_except_pools (MonoImage *image) if (image->ptr_cache) g_hash_table_destroy (image->ptr_cache); if (image->name_cache) { - g_hash_table_foreach (image->name_cache, free_hash_table, NULL); - g_hash_table_destroy (image->name_cache); + dn_simdhash_string_ptr_foreach (image->name_cache, free_simdhash_table, NULL); + dn_simdhash_free (image->name_cache); } free_hash (image->icall_wrapper_cache); diff --git a/src/mono/mono/metadata/loader-internals.h b/src/mono/mono/metadata/loader-internals.h index 17a7a1968621..6fa39c096d10 100644 --- a/src/mono/mono/metadata/loader-internals.h +++ b/src/mono/mono/metadata/loader-internals.h @@ -18,6 +18,7 @@ #include #include #include +#include "../native/containers/dn-simdhash-specializations.h" #if defined(TARGET_OSX) #define MONO_LOADER_LIBRARY_NAME "libcoreclr.dylib" @@ -174,7 +175,8 @@ struct _MonoMemoryManager { MonoAssemblyLoadContext **alcs; // Generic-specific caches - GHashTable *ginst_cache, *gmethod_cache, *gsignature_cache; + GHashTable *gsignature_cache; + dn_simdhash_ght_t *ginst_cache, *gmethod_cache; MonoConcurrentHashTable *gclass_cache; /* mirror caches of ones already on MonoImage. These ones contain generics */ diff --git a/src/mono/mono/metadata/loader.c b/src/mono/mono/metadata/loader.c index 5f9e5c0e7d1f..467fe0e668c0 100644 --- a/src/mono/mono/metadata/loader.c +++ b/src/mono/mono/metadata/loader.c @@ -1182,12 +1182,12 @@ mono_get_method_checked (MonoImage *image, guint32 token, MonoClass *klass, Mono if (mono_metadata_token_table (token) == MONO_TABLE_METHOD) { if (!image->method_cache) - image->method_cache = g_hash_table_new (NULL, NULL); - result = (MonoMethod *)g_hash_table_lookup (image->method_cache, GINT_TO_POINTER (mono_metadata_token_index (token))); + image->method_cache = dn_simdhash_u32_ptr_new (0, NULL); + dn_simdhash_u32_ptr_try_get_value (image->method_cache, mono_metadata_token_index (token), (void **)&result); } else if (!image_is_dynamic (image)) { if (!image->methodref_cache) - image->methodref_cache = g_hash_table_new (NULL, NULL); - result = (MonoMethod *)g_hash_table_lookup (image->methodref_cache, GINT_TO_POINTER (token)); + image->methodref_cache = dn_simdhash_u32_ptr_new (0, NULL); + dn_simdhash_u32_ptr_try_get_value (image->methodref_cache, token, (void **)&result); } mono_image_unlock (image); @@ -1204,9 +1204,9 @@ mono_get_method_checked (MonoImage *image, guint32 token, MonoClass *klass, Mono MonoMethod *result2 = NULL; if (mono_metadata_token_table (token) == MONO_TABLE_METHOD) - result2 = (MonoMethod *)g_hash_table_lookup (image->method_cache, GINT_TO_POINTER (mono_metadata_token_index (token))); + dn_simdhash_u32_ptr_try_get_value (image->method_cache, mono_metadata_token_index (token), (void **)&result2); else if (!image_is_dynamic (image)) - result2 = (MonoMethod *)g_hash_table_lookup (image->methodref_cache, GINT_TO_POINTER (token)); + dn_simdhash_u32_ptr_try_get_value (image->methodref_cache, token, (void **)&result2); if (result2) { mono_image_unlock (image); @@ -1214,9 +1214,9 @@ mono_get_method_checked (MonoImage *image, guint32 token, MonoClass *klass, Mono } if (mono_metadata_token_table (token) == MONO_TABLE_METHOD) - g_hash_table_insert (image->method_cache, GINT_TO_POINTER (mono_metadata_token_index (token)), result); + dn_simdhash_u32_ptr_try_add (image->method_cache, mono_metadata_token_index (token), result); else if (!image_is_dynamic (image)) - g_hash_table_insert (image->methodref_cache, GINT_TO_POINTER (token), result); + dn_simdhash_u32_ptr_try_add (image->methodref_cache, token, result); } mono_image_unlock (image); @@ -1514,7 +1514,7 @@ mono_method_get_param_token (MonoMethod *method, int index) idx = mono_method_get_index (method); if (idx > 0) { guint param_index = mono_metadata_get_method_params (klass_image, idx, NULL); - + if (index == -1) /* Return value */ return mono_metadata_make_token (MONO_TABLE_PARAM, 0); diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 86f64eeb40bb..24aaeebc33ba 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -2136,6 +2136,16 @@ mb_skip_visibility_ilgen (MonoMethodBuilder *mb) mb->skip_visibility = 1; } +static void +mb_inflate_wrapper_data_ilgen (MonoMethodBuilder *mb) +{ + g_assert (!mb->dynamic); // dynamic methods with inflated data not implemented yet - needs at least mono_free_method changes, probably more + mb->inflate_wrapper_data = TRUE; + int idx = mono_mb_add_data (mb, NULL); + // note: match index used in create_method_ilgen + g_assertf (idx == MONO_MB_ILGEN_INFLATE_WRAPPER_INFO_IDX, "mb_inflate_wrapper_data called after data already added"); +} + static void emit_synchronized_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *method, MonoGenericContext *ctx, MonoGenericContainer *container, MonoMethod *enter_method, MonoMethod *exit_method, MonoMethod *gettypefromhandle_method) { @@ -2265,20 +2275,26 @@ emit_array_accessor_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *method, Mo mono_mb_emit_byte (mb, CEE_RET); } +static gboolean +unsafe_accessor_target_type_forbidden (MonoType *target_type); + static void -emit_unsafe_accessor_field_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_method, MonoMethodSignature *sig, MonoGenericContext *ctx, MonoUnsafeAccessorKind kind, const char *member_name) +emit_unsafe_accessor_field_wrapper (MonoMethodBuilder *mb, gboolean inflate_generic_data, MonoMethod *accessor_method, MonoMethodSignature *sig, MonoUnsafeAccessorKind kind, const char *member_name) { // Field access requires a single argument for target type and a return type. g_assert (kind == MONO_UNSAFE_ACCESSOR_FIELD || kind == MONO_UNSAFE_ACCESSOR_STATIC_FIELD); g_assert (member_name != NULL); - MonoType *target_type = sig->params[0]; // params[0] is the field's parent - MonoType *ret_type = sig->ret; - if (sig->param_count != 1 || target_type == NULL || sig->ret->type == MONO_TYPE_VOID) { + + MonoType *target_type = sig->param_count == 1 ? sig->params[0] : NULL; // params[0] is the field's parent + + if (sig->param_count != 1 || target_type == NULL || sig->ret->type == MONO_TYPE_VOID || unsafe_accessor_target_type_forbidden (target_type)) { mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "Invalid usage of UnsafeAccessorAttribute."); return; } + MonoType *ret_type = sig->ret; + MonoClass *target_class = mono_class_from_mono_type_internal (target_type); gboolean target_byref = m_type_is_byref (target_type); gboolean target_valuetype = m_class_is_valuetype (target_class); @@ -2307,6 +2323,8 @@ emit_unsafe_accessor_field_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_ if (kind == MONO_UNSAFE_ACCESSOR_FIELD) mono_mb_emit_ldarg (mb, 0); mono_mb_emit_op (mb, kind == MONO_UNSAFE_ACCESSOR_FIELD ? CEE_LDFLDA : CEE_LDSFLDA, target_field); + if (inflate_generic_data) + mono_mb_set_wrapper_data_kind (mb, MONO_MB_ILGEN_WRAPPER_DATA_FIELD); mono_mb_emit_byte (mb, CEE_RET); } @@ -2315,14 +2333,14 @@ emit_unsafe_accessor_field_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_ * of the expected member method (ie, with the first arg removed) */ static MonoMethodSignature * -method_sig_from_accessor_sig (MonoMethodBuilder *mb, gboolean hasthis, MonoMethodSignature *accessor_sig, MonoGenericContext *ctx) +method_sig_from_accessor_sig (MonoMethodBuilder *mb, gboolean hasthis, MonoMethodSignature *accessor_sig) { MonoMethodSignature *ret = mono_metadata_signature_dup_full (get_method_image (mb->method), accessor_sig); g_assert (ret->param_count > 0); ret->hasthis = hasthis; for (int i = 1; i < ret->param_count; i++) ret->params [i - 1] = ret->params [i]; - memset (&ret->params[ret->param_count - 1], 0, sizeof (MonoType)); // just in case + memset (&ret->params[ret->param_count - 1], 0, sizeof (MonoType*)); // just in case ret->param_count--; return ret; } @@ -2332,7 +2350,7 @@ method_sig_from_accessor_sig (MonoMethodBuilder *mb, gboolean hasthis, MonoMetho * of the expected constructor method (same args, but return type is void). */ static MonoMethodSignature * -ctor_sig_from_accessor_sig (MonoMethodBuilder *mb, MonoMethodSignature *accessor_sig, MonoGenericContext *ctx) +ctor_sig_from_accessor_sig (MonoMethodBuilder *mb, MonoMethodSignature *accessor_sig) { MonoMethodSignature *ret = mono_metadata_signature_dup_full (get_method_image (mb->method), accessor_sig); ret->hasthis = TRUE; /* ctors are considered instance methods */ @@ -2355,6 +2373,8 @@ unsafe_accessor_target_type_forbidden (MonoType *target_type) case MONO_TYPE_VOID: case MONO_TYPE_PTR: case MONO_TYPE_FNPTR: + case MONO_TYPE_VAR: + case MONO_TYPE_MVAR: return TRUE; default: return FALSE; @@ -2371,8 +2391,24 @@ emit_missing_method_error (MonoMethodBuilder *mb, MonoError *failure, const char } } +static MonoMethod * +inflate_method (MonoClass *klass, MonoMethod *method, MonoMethod *accessor_method, MonoError *error) +{ + MonoMethod *result = method; + MonoGenericContext context = { NULL, NULL }; + if (mono_class_is_ginst (klass)) + context.class_inst = mono_class_get_generic_class (klass)->context.class_inst; + if (accessor_method->is_inflated) + context.method_inst = mono_method_get_context (accessor_method)->method_inst; + if ((context.class_inst != NULL) || (context.method_inst != NULL)) + result = mono_class_inflate_generic_method_checked (method, &context, error); + mono_error_assert_ok (error); + + return result; +} + static void -emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_method, MonoMethodSignature *sig, MonoGenericContext *ctx, MonoUnsafeAccessorKind kind, const char *member_name) +emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, gboolean inflate_generic_data, MonoMethod *accessor_method, MonoMethodSignature *sig, MonoUnsafeAccessorKind kind, const char *member_name) { g_assert (kind == MONO_UNSAFE_ACCESSOR_CTOR); // null or empty string member name is ok for a constructor @@ -2384,17 +2420,20 @@ emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_m } MonoType *target_type = sig->ret; // for constructors the return type is the target type + if (target_type == NULL || m_type_is_byref (target_type) || unsafe_accessor_target_type_forbidden (target_type)) { mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "Invalid usage of UnsafeAccessorAttribute."); return; } - - MonoMethodSignature *member_sig = ctor_sig_from_accessor_sig (mb, sig, ctx); - + MonoClass *target_class = mono_class_from_mono_type_internal (target_type); ERROR_DECL(find_method_error); - MonoClass *in_class = mono_class_is_ginst (target_class) ? mono_class_get_generic_class (target_class)->container_class : target_class; + + MonoMethodSignature *member_sig = ctor_sig_from_accessor_sig (mb, sig); + + MonoClass *in_class = target_class; + MonoMethod *target_method = mono_unsafe_accessor_find_ctor (in_class, member_sig, target_class, find_method_error); if (!is_ok (find_method_error) || target_method == NULL) { if (mono_error_get_error_code (find_method_error) == MONO_ERROR_GENERIC) @@ -2404,16 +2443,21 @@ emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_m mono_error_cleanup (find_method_error); return; } + + target_method = inflate_method (target_class, target_method, accessor_method, find_method_error); + g_assert (target_method->klass == target_class); emit_unsafe_accessor_ldargs (mb, sig, 0); mono_mb_emit_op (mb, CEE_NEWOBJ, target_method); + if (inflate_generic_data) + mono_mb_set_wrapper_data_kind (mb, MONO_MB_ILGEN_WRAPPER_DATA_METHOD); mono_mb_emit_byte (mb, CEE_RET); } static void -emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_method, MonoMethodSignature *sig, MonoGenericContext *ctx, MonoUnsafeAccessorKind kind, const char *member_name) +emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, gboolean inflate_generic_data, MonoMethod *accessor_method, MonoMethodSignature *sig, MonoUnsafeAccessorKind kind, const char *member_name) { g_assert (kind == MONO_UNSAFE_ACCESSOR_METHOD || kind == MONO_UNSAFE_ACCESSOR_STATIC_METHOD); g_assert (member_name != NULL); @@ -2421,15 +2465,14 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor // We explicitly allow calling a constructor as if it was an instance method, but we need some hacks in a couple of places gboolean ctor_as_method = !strcmp (member_name, ".ctor"); - if (sig->param_count < 1 || sig->params[0] == NULL || unsafe_accessor_target_type_forbidden (sig->params[0])) { + MonoType *target_type = sig->param_count >= 1 ? sig->params[0] : NULL; + + if (sig->param_count < 1 || target_type == NULL || unsafe_accessor_target_type_forbidden (target_type)) { mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "Invalid usage of UnsafeAccessorAttribute."); return; } - gboolean hasthis = kind == MONO_UNSAFE_ACCESSOR_METHOD; - MonoType *target_type = sig->params[0]; - - MonoMethodSignature *member_sig = method_sig_from_accessor_sig (mb, hasthis, sig, ctx); + gboolean hasthis = kind == MONO_UNSAFE_ACCESSOR_METHOD; MonoClass *target_class = mono_class_from_mono_type_internal (target_type); if (hasthis && m_class_is_valuetype (target_class) && !m_type_is_byref (target_type)) { @@ -2438,7 +2481,11 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor } ERROR_DECL(find_method_error); - MonoClass *in_class = mono_class_is_ginst (target_class) ? mono_class_get_generic_class (target_class)->container_class : target_class; + + MonoMethodSignature *member_sig = method_sig_from_accessor_sig (mb, hasthis, sig); + + MonoClass *in_class = target_class; + MonoMethod *target_method = NULL; if (!ctor_as_method) target_method = mono_unsafe_accessor_find_method (in_class, member_name, member_sig, target_class, find_method_error); @@ -2452,26 +2499,27 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor mono_error_cleanup (find_method_error); return; } + + target_method = inflate_method (target_class, target_method, accessor_method, find_method_error); + if (!hasthis && target_method->klass != target_class) { emit_missing_method_error (mb, find_method_error, member_name); return; } - g_assert (target_method->klass == target_class); // are instance methods allowed to be looked up using inheritance? + + g_assert (target_method->klass == target_class); emit_unsafe_accessor_ldargs (mb, sig, !hasthis ? 1 : 0); mono_mb_emit_op (mb, hasthis ? CEE_CALLVIRT : CEE_CALL, target_method); + if (inflate_generic_data) + mono_mb_set_wrapper_data_kind (mb, MONO_MB_ILGEN_WRAPPER_DATA_METHOD); mono_mb_emit_byte (mb, CEE_RET); } static void -emit_unsafe_accessor_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *accessor_method, MonoMethodSignature *sig, MonoGenericContext *ctx, MonoUnsafeAccessorKind kind, const char *member_name) +emit_unsafe_accessor_wrapper_ilgen (MonoMethodBuilder *mb, gboolean inflate_generic_data, MonoMethod *accessor_method, MonoMethodSignature *sig, MonoUnsafeAccessorKind kind, const char *member_name) { - if (accessor_method->is_inflated || accessor_method->is_generic || mono_class_is_ginst (accessor_method->klass) || ctx != NULL) { - mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "UnsafeAccessor_Generics"); - return; - } - if (!m_method_is_static (accessor_method)) { mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "UnsafeAccessor_NonStatic"); return; @@ -2480,14 +2528,14 @@ emit_unsafe_accessor_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *accessor_ switch (kind) { case MONO_UNSAFE_ACCESSOR_FIELD: case MONO_UNSAFE_ACCESSOR_STATIC_FIELD: - emit_unsafe_accessor_field_wrapper (mb, accessor_method, sig, ctx, kind, member_name); + emit_unsafe_accessor_field_wrapper (mb, inflate_generic_data, accessor_method, sig, kind, member_name); return; case MONO_UNSAFE_ACCESSOR_CTOR: - emit_unsafe_accessor_ctor_wrapper (mb, accessor_method, sig, ctx, kind, member_name); + emit_unsafe_accessor_ctor_wrapper (mb, inflate_generic_data, accessor_method, sig, kind, member_name); return; case MONO_UNSAFE_ACCESSOR_METHOD: case MONO_UNSAFE_ACCESSOR_STATIC_METHOD: - emit_unsafe_accessor_method_wrapper (mb, accessor_method, sig, ctx, kind, member_name); + emit_unsafe_accessor_method_wrapper (mb, inflate_generic_data, accessor_method, sig, kind, member_name); return; default: mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "UnsafeAccessor_InvalidKindValue"); @@ -3343,6 +3391,7 @@ mono_marshal_lightweight_init (void) cb.emit_return = emit_return_ilgen; cb.emit_vtfixup_ftnptr = emit_vtfixup_ftnptr_ilgen; cb.mb_skip_visibility = mb_skip_visibility_ilgen; + cb.mb_inflate_wrapper_data = mb_inflate_wrapper_data_ilgen; cb.mb_emit_exception = mb_emit_exception_ilgen; cb.mb_emit_exception_for_error = mb_emit_exception_for_error_ilgen; cb.mb_emit_byte = mb_emit_byte_ilgen; diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 09fddd573c0f..90076ba1994e 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -3711,7 +3711,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, swift_error_args++; } else if (param_klass == swift_self) { swift_self_args++; - } else if (!m_class_is_blittable (param_klass) || m_class_is_simd_type (param_klass)) { + } else if (!type_is_blittable (method->signature->params [i]) || m_class_is_simd_type (param_klass)) { swift_error_args = swift_self_args = 0; mono_error_set_generic_error (emitted_error, "System", "InvalidProgramException", "Passing non-blittable types to a P/Invoke with the Swift calling convention is unsupported."); break; @@ -5226,39 +5226,129 @@ mono_marshal_get_unsafe_accessor_wrapper (MonoMethod *accessor_method, MonoUnsaf MonoMethod *res; GHashTable *cache; MonoGenericContext *ctx = NULL; + MonoGenericContainer *container = NULL; MonoMethod *orig_method = NULL; WrapperInfo *info; + /* generic_wrapper == TRUE means we will create a generic wrapper method. */ + gboolean generic_wrapper = FALSE; + /* is_inflated == TRUE means we will inflate a wrapper method before returning. */ + gboolean is_inflated = FALSE; + /* one or both of generic_wrapper or is_inflated might be set, depending on how we're called. */ if (member_name == NULL && kind != MONO_UNSAFE_ACCESSOR_CTOR) member_name = accessor_method->name; + // printf("CAME IN: %s (generic = %d, inflated = %d)\n", mono_method_full_name(accessor_method, TRUE), accessor_method->is_generic?1:0, accessor_method->is_inflated?1:0); + + /* + * the method is either a generic method definition, or it might be inflated, not both at + * the same time. + */ + g_assert (!(accessor_method->is_generic && accessor_method->is_inflated)); + + + if (accessor_method->is_inflated) { + MonoMethod *declaring = ((MonoMethodInflated*)accessor_method)->declaring; + if (declaring->is_generic) { + // JIT gets here sometimes. + generic_wrapper = TRUE; + } + is_inflated = TRUE; + } + + if (accessor_method->is_generic) { + generic_wrapper = TRUE; + } + + if (is_inflated) { + // TODO: this always tries to compile a generic version of the accessor method and + // then inflate it. But maybe we dont' want to do that (particularly for field + // accessors). In particular if there is no method_inst, we're looking at an + // accessor method inside a generic class (alwayst a ginst? or sometimes a gtd?) + // In that case we might just want to compile the instance. + + orig_method = accessor_method; + ctx = &((MonoMethodInflated*)accessor_method)->context; + accessor_method = ((MonoMethodInflated*)accessor_method)->declaring; + container = mono_method_get_generic_container (accessor_method); + if (!container) + container = mono_class_try_get_generic_container (accessor_method->klass); + g_assert (container); + // TODO: + // in the example below, do we need to mess with the context and container? + // + // class C { + // public static extern void AccessorMethod(List t, List u); + // } + // + // when we make a wrapper + // + // public static extern void wrapper_AccessorMethod(List, List u); + // + // do we need to substitute the new gparams of the wrapper, but leave the + // gparams of C unchanged? + // + } + + // printf("work on: %s (generic = %d, inflated = %d)\n", mono_method_full_name(accessor_method, TRUE), accessor_method->is_generic?1:0, accessor_method->is_inflated?1:0); + /* * Check cache */ - if (ctx) { - cache = NULL; - g_assert_not_reached (); + if (is_inflated) { + cache = get_cache (&((MonoMethodInflated*)orig_method)->owner->wrapper_caches.unsafe_accessor_cache , mono_aligned_addr_hash, NULL); + res = check_generic_wrapper_cache (cache, orig_method, orig_method, accessor_method); + if (res) + return res; } else { cache = get_cache (&mono_method_get_wrapper_cache (accessor_method)->unsafe_accessor_cache, mono_aligned_addr_hash, NULL); if ((res = mono_marshal_find_in_cache (cache, accessor_method))) return res; } + // printf ("Cache miss\n"); + + mb = mono_mb_new (accessor_method->klass, accessor_method->name, MONO_WRAPPER_OTHER); + if (generic_wrapper) { + // If the accessor method was generic, make the wrapper generic, too. - sig = mono_metadata_signature_dup_full (get_method_image (accessor_method), mono_method_signature_internal (accessor_method)); - sig->pinvoke = 0; + // Load a copy of the generic params of the accessor method + mb->method->is_generic = generic_wrapper; + container = mono_class_try_get_generic_container (accessor_method->klass); + container = mono_metadata_load_generic_params (m_class_get_image (accessor_method->klass), accessor_method->token, container, /*owner:*/mb->method); + mono_method_set_generic_container (mb->method, container); - mb = mono_mb_new (accessor_method->klass, accessor_method->name, MONO_WRAPPER_OTHER); + MonoGenericContext inst_ctx = {0,}; + // FIXME: if is_inflated, do we need to mess with ctx? + inst_ctx.method_inst = container->context.method_inst; + + ERROR_DECL (error); + // make a copy of the accessor signature, but replace the params of the accessor + // method, by the params we just loaded + sig = mono_inflate_generic_signature (mono_method_signature_internal (accessor_method), &inst_ctx, error); + mono_error_assert_ok (error); // FIXME + } else { + sig = mono_metadata_signature_dup_full (get_method_image (accessor_method), mono_method_signature_internal (accessor_method)); + } + sig->pinvoke = 0; get_marshal_cb ()->mb_skip_visibility (mb); - get_marshal_cb ()->emit_unsafe_accessor_wrapper (mb, accessor_method, sig, ctx, kind, member_name); + if (generic_wrapper || is_inflated) { + // wrapper data will mention MonoClassField* and MonoMethod* that need to be inflated + get_marshal_cb ()->mb_inflate_wrapper_data (mb); + } + + // if the wrapper will be inflated (either now by us, or when it's called, because it is + // generic), mark the wrapper data to be inflated, too + gboolean inflate_generic_data = accessor_method->is_generic || is_inflated; + get_marshal_cb ()->emit_unsafe_accessor_wrapper (mb, inflate_generic_data, accessor_method, sig, kind, member_name); info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_UNSAFE_ACCESSOR); info->d.unsafe_accessor.method = accessor_method; info->d.unsafe_accessor.kind = kind; info->d.unsafe_accessor.member_name = member_name; - if (ctx) { + if (is_inflated) { MonoMethod *def; def = mono_mb_create_and_cache_full (cache, accessor_method, mb, sig, sig->param_count + 16, info, NULL); res = cache_generic_wrapper (cache, orig_method, def, ctx, orig_method); @@ -5749,7 +5839,7 @@ MonoMarshalType * mono_marshal_load_type_info (MonoClass* klass) { int j, count = 0; - guint32 native_size = 0, min_align = 1, packing; + guint32 native_size = 0, min_align = 1, packing, explicit_size = 0; MonoMarshalType *info; MonoClassField* field; gpointer iter; @@ -5793,7 +5883,7 @@ mono_marshal_load_type_info (MonoClass* klass) info->num_fields = count; /* Try to find a size for this type in metadata */ - mono_metadata_packing_from_typedef (m_class_get_image (klass), m_class_get_type_token (klass), NULL, &native_size); + explicit_size = mono_metadata_packing_from_typedef (m_class_get_image (klass), m_class_get_type_token (klass), NULL, &native_size); if (m_class_get_parent (klass)) { int parent_size = mono_class_native_size (m_class_get_parent (klass), NULL); @@ -5879,6 +5969,9 @@ mono_marshal_load_type_info (MonoClass* klass) align_size = FALSE; else min_align = MIN (min_align, packing); + } else if (layout == TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT) { + if (explicit_size && native_size == info->native_size) + align_size = FALSE; } } @@ -6600,7 +6693,8 @@ typedef enum { SWIFT_DOUBLE, } SwiftPhysicalLoweringKind; -static int get_swift_lowering_alignment (SwiftPhysicalLoweringKind kind) { +static int get_swift_lowering_alignment (SwiftPhysicalLoweringKind kind) +{ switch (kind) { case SWIFT_INT64: case SWIFT_DOUBLE: @@ -6612,7 +6706,8 @@ static int get_swift_lowering_alignment (SwiftPhysicalLoweringKind kind) { } } -static void set_lowering_range(guint8* lowered_bytes, guint32 offset, guint32 size, SwiftPhysicalLoweringKind kind) { +static void set_lowering_range(guint8* lowered_bytes, guint32 offset, guint32 size, SwiftPhysicalLoweringKind kind) +{ bool force_opaque = false; if (offset != ALIGN_TO(offset, get_swift_lowering_alignment(kind))) { @@ -6643,7 +6738,8 @@ static void set_lowering_range(guint8* lowered_bytes, guint32 offset, guint32 si static void record_struct_field_physical_lowering (guint8* lowered_bytes, MonoType* type, guint32 offset); -static void record_inlinearray_struct_physical_lowering (guint8* lowered_bytes, MonoClass* klass, guint32 offset) { +static void record_inlinearray_struct_physical_lowering (guint8* lowered_bytes, MonoClass* klass, guint32 offset) +{ // Get the first field and record its physical lowering N times MonoClassField* field = mono_class_get_fields_internal (klass, NULL); MonoType* fieldType = field->type; @@ -6662,17 +6758,21 @@ static void record_struct_physical_lowering (guint8* lowered_bytes, MonoClass* k // For each field, we need to record the physical lowering of it. gpointer iter = NULL; MonoClassField* field; + int type_offset = MONO_ABI_SIZEOF (MonoObject); while ((field = mono_class_get_fields_internal (klass, &iter))) { if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; if (mono_field_is_deleted (field)) continue; - record_struct_field_physical_lowering(lowered_bytes, field->type, offset + m_field_get_offset(field)); + record_struct_field_physical_lowering(lowered_bytes, field->type, (offset + m_field_get_offset(field)) - type_offset); } } -static void record_struct_field_physical_lowering (guint8* lowered_bytes, MonoType* type, guint32 offset) { +static void record_struct_field_physical_lowering (guint8* lowered_bytes, MonoType* type, guint32 offset) +{ + int align; + // Normalize pointer types to IntPtr and resolve generic classes. // We don't need to care about specific pointer types at this ABI level. if (type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR) { @@ -6700,7 +6800,7 @@ static void record_struct_field_physical_lowering (guint8* lowered_bytes, MonoTy kind = SWIFT_DOUBLE; } - set_lowering_range(lowered_bytes, offset, mono_type_size(type, NULL), kind); + set_lowering_range(lowered_bytes, offset, mono_type_size(type, &align), kind); } } @@ -6727,13 +6827,13 @@ mono_marshal_get_swift_physical_lowering (MonoType *type, gboolean native_layout } MonoClass *klass = mono_class_from_mono_type_internal (type); - + int vtype_size = mono_class_value_size (klass, NULL); // TODO: We currently don't support vector types, so we can say that the maximum size of a non-by_reference struct // is 4 * PointerSize. // Strictly, this is inaccurate in the case where a struct has a fully-empty 8 bytes of padding using explicit layout, // but that's not possible in the Swift layout algorithm. - if (m_class_get_instance_size(klass) > 4 * TARGET_SIZEOF_VOID_P) { + if (vtype_size > 4 * TARGET_SIZEOF_VOID_P) { lowering.by_reference = TRUE; return lowering; } @@ -6752,8 +6852,7 @@ mono_marshal_get_swift_physical_lowering (MonoType *type, gboolean native_layout GArray* intervals = g_array_new(FALSE, TRUE, sizeof(struct _SwiftInterval)); // Now we'll build the intervals from the lowered_bytes array - int instance_size = m_class_get_instance_size(klass); - for (int i = 0; i < instance_size; ++i) { + for (int i = 0; i < vtype_size; ++i) { // Don't create an interval for empty bytes if (lowered_bytes[i] == SWIFT_EMPTY) { continue; @@ -6781,19 +6880,23 @@ mono_marshal_get_swift_physical_lowering (MonoType *type, gboolean native_layout } // Merge opaque intervals that are in the same pointer-sized block - for (int i = 0; i < intervals->len - 1; ++i) { - struct _SwiftInterval current = g_array_index(intervals, struct _SwiftInterval, i); - struct _SwiftInterval next = g_array_index(intervals, struct _SwiftInterval, i + 1); - - if (current.kind == SWIFT_OPAQUE && next.kind == SWIFT_OPAQUE && current.start / TARGET_SIZEOF_VOID_P == next.start / TARGET_SIZEOF_VOID_P) { - current.size = next.start + next.size - current.start; - g_array_remove_index(intervals, i + 1); - i--; + for (int i = 0; i < intervals->len; ++i) { + struct _SwiftInterval interval = g_array_index(intervals, struct _SwiftInterval, i); + + if (i != 0 && interval.kind == SWIFT_OPAQUE) { + // Merge two opaque intervals when the previous interval ends in the same pointer-sized block + struct _SwiftInterval prevInterval = g_array_index(intervals, struct _SwiftInterval, i - 1); + if (prevInterval.kind == SWIFT_OPAQUE && (prevInterval.start + prevInterval.size) / TARGET_SIZEOF_VOID_P == interval.start / TARGET_SIZEOF_VOID_P) { + (g_array_index(intervals, struct _SwiftInterval, i - 1)).size = interval.start + interval.size - prevInterval.start; + g_array_remove_index(intervals, i); + --i; + continue; + } } } // Now that we have the intervals, we can calculate the lowering - MonoTypeEnum lowered_types[4]; + MonoType *lowered_types[4]; guint32 offsets[4]; guint32 num_lowered_types = 0; @@ -6811,13 +6914,13 @@ mono_marshal_get_swift_physical_lowering (MonoType *type, gboolean native_layout switch (interval.kind) { case SWIFT_INT64: - lowered_types[num_lowered_types++] = MONO_TYPE_I8; + lowered_types[num_lowered_types++] = m_class_get_byval_arg (mono_defaults.int64_class); break; case SWIFT_FLOAT: - lowered_types[num_lowered_types++] = MONO_TYPE_R4; + lowered_types[num_lowered_types++] = m_class_get_byval_arg (mono_defaults.single_class); break; case SWIFT_DOUBLE: - lowered_types[num_lowered_types++] = MONO_TYPE_R8; + lowered_types[num_lowered_types++] = m_class_get_byval_arg (mono_defaults.double_class); break; case SWIFT_OPAQUE: { @@ -6850,20 +6953,20 @@ mono_marshal_get_swift_physical_lowering (MonoType *type, gboolean native_layout offsets[num_lowered_types] = opaque_interval_start; - if (remaining_interval_size > 8 && (opaque_interval_start % 8 == 0)) { - lowered_types[num_lowered_types] = MONO_TYPE_I8; + if (remaining_interval_size > 4 && (opaque_interval_start % 8 == 0)) { + lowered_types[num_lowered_types] = m_class_get_byval_arg (mono_defaults.int64_class); remaining_interval_size -= 8; opaque_interval_start += 8; - } else if (remaining_interval_size > 4 && (opaque_interval_start % 4 == 0)) { - lowered_types[num_lowered_types] = MONO_TYPE_I4; + } else if (remaining_interval_size > 2 && (opaque_interval_start % 4 == 0)) { + lowered_types[num_lowered_types] = m_class_get_byval_arg (mono_defaults.int32_class); remaining_interval_size -= 4; opaque_interval_start += 4; - } else if (remaining_interval_size > 2 && (opaque_interval_start % 2 == 0)) { - lowered_types[num_lowered_types] = MONO_TYPE_I2; + } else if (remaining_interval_size > 1 && (opaque_interval_start % 2 == 0)) { + lowered_types[num_lowered_types] = m_class_get_byval_arg (mono_defaults.int16_class); remaining_interval_size -= 2; opaque_interval_start += 2; } else { - lowered_types[num_lowered_types] = MONO_TYPE_U1; + lowered_types[num_lowered_types] = m_class_get_byval_arg (mono_defaults.byte_class); remaining_interval_size -= 1; opaque_interval_start += 1; } @@ -6874,7 +6977,7 @@ mono_marshal_get_swift_physical_lowering (MonoType *type, gboolean native_layout } } - memcpy(lowering.lowered_elements, lowered_types, num_lowered_types * sizeof(MonoTypeEnum)); + memcpy(lowering.lowered_elements, lowered_types, num_lowered_types * sizeof(MonoType*)); memcpy(lowering.offsets, offsets, num_lowered_types * sizeof(guint32)); lowering.num_lowered_elements = num_lowered_types; lowering.by_reference = FALSE; diff --git a/src/mono/mono/metadata/marshal.h b/src/mono/mono/metadata/marshal.h index 8d545fcc25de..47d47a15db44 100644 --- a/src/mono/mono/metadata/marshal.h +++ b/src/mono/mono/metadata/marshal.h @@ -342,7 +342,7 @@ typedef struct { void (*emit_synchronized_wrapper) (MonoMethodBuilder *mb, MonoMethod *method, MonoGenericContext *ctx, MonoGenericContainer *container, MonoMethod *enter_method, MonoMethod *exit_method, MonoMethod *gettypefromhandle_method); void (*emit_unbox_wrapper) (MonoMethodBuilder *mb, MonoMethod *method); void (*emit_array_accessor_wrapper) (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *sig, MonoGenericContext *ctx); - void (*emit_unsafe_accessor_wrapper) (MonoMethodBuilder *mb, MonoMethod *accessor_method, MonoMethodSignature *sig, MonoGenericContext *ctx, MonoUnsafeAccessorKind kind, const char *member_name); + void (*emit_unsafe_accessor_wrapper) (MonoMethodBuilder *mb, gboolean inflate_generic_data, MonoMethod *accessor_method, MonoMethodSignature *sig, MonoUnsafeAccessorKind kind, const char *member_name); void (*emit_generic_array_helper) (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *csig); void (*emit_thunk_invoke_wrapper) (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *csig); void (*emit_create_string_hack) (MonoMethodBuilder *mb, MonoMethodSignature *csig, MonoMethod *res); @@ -351,6 +351,7 @@ typedef struct { void (*emit_return) (MonoMethodBuilder *mb); void (*emit_vtfixup_ftnptr) (MonoMethodBuilder *mb, MonoMethod *method, int param_count, guint16 type); void (*mb_skip_visibility) (MonoMethodBuilder *mb); + void (*mb_inflate_wrapper_data) (MonoMethodBuilder *mb); void (*mb_emit_exception) (MonoMethodBuilder *mb, const char *exc_nspace, const char *exc_name, const char *msg); void (*mb_emit_exception_for_error) (MonoMethodBuilder *mb, const MonoError *emitted_error); void (*mb_emit_byte) (MonoMethodBuilder *mb, guint8 op); @@ -744,8 +745,8 @@ GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL (swift_error) typedef struct { gboolean by_reference; - int num_lowered_elements; - MonoTypeEnum lowered_elements[4]; + uint32_t num_lowered_elements; + MonoType *lowered_elements[4]; uint32_t offsets[4]; } SwiftPhysicalLowering; diff --git a/src/mono/mono/metadata/memory-manager.c b/src/mono/mono/metadata/memory-manager.c index a4de69eaa468..aeb7373f6b8f 100644 --- a/src/mono/mono/metadata/memory-manager.c +++ b/src/mono/mono/metadata/memory-manager.c @@ -204,6 +204,14 @@ free_hash (GHashTable **hash) *hash = NULL; } +static void +free_simdhash (dn_simdhash_t **hash) +{ + if (*hash) + dn_simdhash_free (*hash); + *hash = NULL; +} + // Full deletion static void memory_manager_delete (MonoMemoryManager *memory_manager, gboolean debug_unload) @@ -230,8 +238,8 @@ memory_manager_delete (MonoMemoryManager *memory_manager, gboolean debug_unload) MonoMemoryManager *mm = memory_manager; if (mm->gclass_cache) mono_conc_hashtable_destroy (mm->gclass_cache); - free_hash (&mm->ginst_cache); - free_hash (&mm->gmethod_cache); + free_simdhash (&mm->ginst_cache); + free_simdhash (&mm->gmethod_cache); free_hash (&mm->gsignature_cache); free_hash (&mm->szarray_cache); free_hash (&mm->array_cache); diff --git a/src/mono/mono/metadata/metadata-internals.h b/src/mono/mono/metadata/metadata-internals.h index 67c6d1350473..b35d96457fd9 100644 --- a/src/mono/mono/metadata/metadata-internals.h +++ b/src/mono/mono/metadata/metadata-internals.h @@ -19,6 +19,8 @@ #include #include "mono/utils/mono-conc-hashtable.h" #include "mono/utils/refcount.h" +// for dn_simdhash_string_ptr_t and dn_simdhash_u32_ptr_t +#include "../native/containers/dn-simdhash-specializations.h" struct _MonoType { union { @@ -416,11 +418,11 @@ struct _MonoImage { /* * Indexed by method tokens and typedef tokens. */ - GHashTable *method_cache; /*protected by the image lock*/ + dn_simdhash_u32_ptr_t *method_cache; /*protected by the image lock*/ MonoInternalHashTable class_cache; /* Indexed by memberref + methodspec tokens */ - GHashTable *methodref_cache; /*protected by the image lock*/ + dn_simdhash_u32_ptr_t *methodref_cache; /*protected by the image lock*/ /* * Indexed by fielddef and memberref tokens @@ -438,7 +440,7 @@ struct _MonoImage { /* * Indexes namespaces to hash tables that map class name to typedef token. */ - GHashTable *name_cache; /*protected by the image lock*/ + dn_simdhash_string_ptr_t *name_cache; /*protected by the image lock*/ /* * Indexed by MonoClass @@ -1008,6 +1010,7 @@ MonoMethodSignature *mono_metadata_signature_dup_mempool (MonoMemPool *mp, Mono MonoMethodSignature *mono_metadata_signature_dup_mem_manager (MonoMemoryManager *mem_manager, MonoMethodSignature *sig); MonoMethodSignature *mono_metadata_signature_dup_add_this (MonoImage *image, MonoMethodSignature *sig, MonoClass *klass); MonoMethodSignature *mono_metadata_signature_dup_delegate_invoke_to_target (MonoMethodSignature *sig); +MonoMethodSignature *mono_metadata_signature_dup_new_params (MonoMemPool *mp, MonoMethodSignature *sig, uint32_t num_params, MonoType **new_params); MonoGenericInst * mono_get_shared_generic_inst (MonoGenericContainer *container); @@ -1134,6 +1137,56 @@ mono_metadata_get_class_guid (MonoClass* klass, uint8_t* guid, MonoError *error) #define MONO_CLASS_IS_INTERFACE_INTERNAL(c) ((mono_class_get_flags (c) & TYPE_ATTRIBUTE_INTERFACE) || mono_type_is_generic_parameter (m_class_get_byval_arg (c))) +/* + * We use this to pass context information to the row locator + */ +typedef struct { + // caller inputs + // note: we can't optimize around locator_t.idx yet because a few call sites mutate it + guint32 idx; /* The index that we are trying to locate */ + // no call sites mutate this so we can optimize around it + guint32 col_idx; /* The index in the row where idx may be stored */ + // no call sites mutate this so we can optimize around it + MonoTableInfo *t; /* pointer to the table */ + + // optimization data + gint32 metadata_has_updates; // -1: uninitialized. 0/1: value + const char * t_base; + guint t_row_size; + guint32 t_rows; + guint32 column_size; + const char * first_column_data; + + // result + guint32 result; +} mono_locator_t; + +MONO_ALWAYS_INLINE static mono_locator_t +mono_locator_init (MonoTableInfo *t, guint32 idx, guint32 col_idx) +{ + mono_locator_t result = { 0, }; + + result.idx = idx; + result.col_idx = col_idx; + result.t = t; + + g_assert (t); + // FIXME: Callers shouldn't rely on this + if (!t->base) + return result; + + // optimization data for decode_locator_row + result.metadata_has_updates = -1; + result.t_base = t->base; + result.t_row_size = t->row_size; + result.t_rows = table_info_get_rows (t); + g_assert (col_idx < mono_metadata_table_count (t->size_bitfield)); + result.column_size = mono_metadata_table_size (t->size_bitfield, col_idx); + result.first_column_data = result.t_base + t->column_offsets [col_idx]; + + return result; +} + static inline gboolean m_image_is_raw_data_allocated (MonoImage *image) { diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index d005bfdb6b6b..0bb9ded0b66e 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -997,10 +997,10 @@ mono_metadata_table_bounds_check_slow (MonoImage *image, int table_index, int to if (G_LIKELY (GINT_TO_UINT32(token_index) <= table_info_get_rows (&image->tables [table_index]))) return FALSE; - if (G_LIKELY (!image->has_updates)) - return TRUE; + if (G_LIKELY (!image->has_updates)) + return TRUE; - return mono_metadata_update_table_bounds_check (image, table_index, token_index); + return mono_metadata_update_table_bounds_check (image, table_index, token_index); } void @@ -1094,7 +1094,7 @@ get_blob_heap (MonoImage *image) static gboolean mono_delta_heap_lookup (MonoImage *base_image, MetadataHeapGetterFunc get_heap, guint32 orig_index, MonoImage **image_out, guint32 *index_out) { - return mono_metadata_update_delta_heap_lookup (base_image, get_heap, orig_index, image_out, index_out); + return mono_metadata_update_delta_heap_lookup (base_image, get_heap, orig_index, image_out, index_out); } /** @@ -1931,7 +1931,7 @@ static guint mono_generic_class_hash (gconstpointer data) { const MonoGenericClass *gclass = (const MonoGenericClass *) data; - guint hash = mono_metadata_str_hash (m_class_get_name (gclass->container_class)); + guint hash = m_class_get_name_hash (gclass->container_class); hash *= 13; hash += gclass->is_tb_open; @@ -2546,6 +2546,37 @@ mono_metadata_signature_dup_delegate_invoke_to_target (MonoMethodSignature *sig) return res; } +/** + * mono_metadata_signature_dup_new_params: + * @param mp The memory pool to allocate the duplicated signature from. + * @param sig The original method signature. + * @param num_params The number parameters in the new signature. + * @param new_params An array of MonoType pointers representing the new parameters. + * + * Duplicate an existing \c MonoMethodSignature but with a new set of parameters. + * This is a Mono runtime internal function. + * + * @return the new \c MonoMethodSignature structure. + */ +MonoMethodSignature* +mono_metadata_signature_dup_new_params (MonoMemPool *mp, MonoMethodSignature *sig, uint32_t num_params, MonoType **new_params) +{ + size_t new_sig_size = MONO_SIZEOF_METHOD_SIGNATURE + num_params * sizeof (MonoType*); + if (sig->ret) + new_sig_size += mono_sizeof_type (sig->ret); + + MonoMethodSignature *res = (MonoMethodSignature *)mono_mempool_alloc0 (mp, (unsigned int)new_sig_size); + memcpy (res, sig, MONO_SIZEOF_METHOD_SIGNATURE); + res->param_count = GUINT32_TO_UINT16 (num_params); + + for (uint16_t i = 0; i < res->param_count; i++) { + res->params [i] = new_params [i]; + } + res->ret = sig->ret; + + return res; +} + /* * mono_metadata_signature_size: * @@ -3449,9 +3480,10 @@ mono_metadata_get_canonical_generic_inst (MonoGenericInst *candidate) mono_loader_lock (); if (!mm->ginst_cache) - mm->ginst_cache = g_hash_table_new_full (mono_metadata_generic_inst_hash, mono_metadata_generic_inst_equal, NULL, (GDestroyNotify)free_generic_inst); + mm->ginst_cache = dn_simdhash_ght_new_full (mono_metadata_generic_inst_hash, mono_metadata_generic_inst_equal, NULL, (GDestroyNotify)free_generic_inst, 0, NULL); - MonoGenericInst *ginst = (MonoGenericInst *)g_hash_table_lookup (mm->ginst_cache, candidate); + MonoGenericInst *ginst = NULL; + dn_simdhash_ght_try_get_value (mm->ginst_cache, candidate, (void **)&ginst); if (!ginst) { int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *); ginst = (MonoGenericInst *)mono_mem_manager_alloc0 (mm, size); @@ -3465,7 +3497,7 @@ mono_metadata_get_canonical_generic_inst (MonoGenericInst *candidate) for (int i = 0; i < type_argc; ++i) ginst->type_argv [i] = mono_metadata_type_dup (NULL, candidate->type_argv [i]); - g_hash_table_insert (mm->ginst_cache, ginst, ginst); + dn_simdhash_ght_insert (mm->ginst_cache, ginst, ginst); } mono_loader_unlock (); @@ -4679,15 +4711,34 @@ mono_metadata_token_from_dor (guint32 dor_index) return 0; } -/* - * We use this to pass context information to the row locator - */ -typedef struct { - guint32 idx; /* The index that we are trying to locate */ - guint32 col_idx; /* The index in the row where idx may be stored */ - MonoTableInfo *t; /* pointer to the table */ - guint32 result; -} locator_t; +static guint32 +decode_locator_row (mono_locator_t *loc, int row_index) +{ + const char *data; + + if (G_UNLIKELY (loc->metadata_has_updates < 0)) + loc->metadata_has_updates = mono_metadata_has_updates (); + if (G_UNLIKELY (loc->metadata_has_updates > 0)) + return mono_metadata_decode_row_col_slow (loc->t, row_index, loc->col_idx); + + // g_assert (col < mono_metadata_table_count (bitfield)); + // data = t->base + idx * t->row_size + t->column_offsets [col]; + // n = mono_metadata_table_size (bitfield, col); + + g_assert (GINT_TO_UINT32(row_index) < loc->t_rows); + data = loc->first_column_data + (row_index * loc->t_row_size); + switch (loc->column_size) { + case 1: + return *data; + case 2: + return read16 (data); + case 4: + return read32 (data); + default: + g_assert_not_reached (); + return 0; + } +} /* * How the row locator works. @@ -4724,23 +4775,23 @@ typedef struct { static int typedef_locator (const void *a, const void *b) { - locator_t *loc = (locator_t *) a; + mono_locator_t *loc = (mono_locator_t *) a; const char *bb = (const char *) b; - int typedef_index = GPTRDIFF_TO_INT ((bb - loc->t->base) / loc->t->row_size); - guint32 col, col_next; + int typedef_index = GPTRDIFF_TO_INT ((bb - loc->t_base) / loc->t_row_size); + guint32 col, col_next, target_idx = loc->idx; - col = mono_metadata_decode_row_col (loc->t, typedef_index, loc->col_idx); + col = decode_locator_row (loc, typedef_index); - if (loc->idx < col) + if (target_idx < col) return -1; /* * Need to check that the next row is valid. */ g_assert (typedef_index >= 0); - if (GINT_TO_UINT32(typedef_index) + 1 < table_info_get_rows (loc->t)) { - col_next = mono_metadata_decode_row_col (loc->t, typedef_index + 1, loc->col_idx); - if (loc->idx >= col_next) + if (GINT_TO_UINT32(typedef_index) + 1 < loc->t_rows) { + col_next = decode_locator_row (loc, typedef_index + 1); + if (target_idx >= col_next) return 1; if (col == col_next) @@ -4755,18 +4806,18 @@ typedef_locator (const void *a, const void *b) static int table_locator (const void *a, const void *b) { - locator_t *loc = (locator_t *) a; + mono_locator_t *loc = (mono_locator_t *) a; const char *bb = (const char *) b; - guint32 table_index = GPTRDIFF_TO_INT ((bb - loc->t->base) / loc->t->row_size); - guint32 col; + guint32 table_index = GPTRDIFF_TO_INT ((bb - loc->t_base) / loc->t_row_size); + guint32 col, target_idx = loc->idx; - col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx); + col = decode_locator_row (loc, table_index); - if (loc->idx == col) { + if (target_idx == col) { loc->result = table_index; return 0; } - if (loc->idx < col) + if (target_idx < col) return -1; else return 1; @@ -4775,18 +4826,18 @@ table_locator (const void *a, const void *b) static int declsec_locator (const void *a, const void *b) { - locator_t *loc = (locator_t *) a; + mono_locator_t *loc = (mono_locator_t *) a; const char *bb = (const char *) b; - guint32 table_index = GPTRDIFF_TO_UINT32 ((bb - loc->t->base) / loc->t->row_size); - guint32 col; + guint32 table_index = GPTRDIFF_TO_UINT32 ((bb - loc->t_base) / loc->t_row_size); + guint32 col, target_index = loc->idx; - col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx); + col = decode_locator_row (loc, table_index); - if (loc->idx == col) { + if (target_index == col) { loc->result = table_index; return 0; } - if (loc->idx < col) + if (target_index < col) return -1; else return 1; @@ -4829,15 +4880,12 @@ guint32 mono_metadata_typedef_from_field (MonoImage *meta, guint32 index) { MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF]; - locator_t loc; + mono_locator_t loc = mono_locator_init (tdef, mono_metadata_token_index (index), MONO_TYPEDEF_FIELD_LIST); if (!tdef->base) return 0; - loc.idx = mono_metadata_token_index (index); - loc.col_idx = MONO_TYPEDEF_FIELD_LIST; - loc.t = tdef; - + // FIXME: Modifies locator_t.idx if (meta->uncompressed_metadata) loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx); @@ -4866,15 +4914,12 @@ guint32 mono_metadata_typedef_from_method (MonoImage *meta, guint32 index) { MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF]; - locator_t loc; + mono_locator_t loc = mono_locator_init (tdef, mono_metadata_token_index (index), MONO_TYPEDEF_METHOD_LIST); if (!tdef->base) return 0; - loc.idx = mono_metadata_token_index (index); - loc.col_idx = MONO_TYPEDEF_METHOD_LIST; - loc.t = tdef; - + // FIXME: Modifies locator_t.idx if (meta->uncompressed_metadata) loc.idx = search_ptr_table (meta, MONO_TABLE_METHOD_POINTER, loc.idx); @@ -4911,7 +4956,7 @@ gboolean mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, gboolean heap_alloc_result, MonoGenericContext *context, MonoError *error) { MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL]; - locator_t loc; + mono_locator_t loc; guint32 start, pos; guint32 cols [MONO_INTERFACEIMPL_SIZE]; MonoClass **result; @@ -4924,10 +4969,7 @@ mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, Mono if (!tdef->base && !meta->has_updates) return TRUE; - loc.idx = mono_metadata_token_index (index); - loc.col_idx = MONO_INTERFACEIMPL_CLASS; - loc.t = tdef; - loc.result = 0; + loc = mono_locator_init (tdef, mono_metadata_token_index (index), MONO_INTERFACEIMPL_CLASS); gboolean found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator) != NULL; @@ -5026,16 +5068,11 @@ guint32 mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index) { MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS]; - locator_t loc; + mono_locator_t loc = mono_locator_init (tdef, mono_metadata_token_index (index), MONO_NESTED_CLASS_NESTED); if (!tdef->base && !meta->has_updates) return 0; - loc.idx = mono_metadata_token_index (index); - loc.col_idx = MONO_NESTED_CLASS_NESTED; - loc.t = tdef; - loc.result = 0; - gboolean found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator) != NULL; if (!found && !meta->has_updates) return 0; @@ -5095,16 +5132,12 @@ guint32 mono_metadata_packing_from_typedef (MonoImage *meta, guint32 index, guint32 *packing, guint32 *size) { MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CLASSLAYOUT]; - locator_t loc; + mono_locator_t loc = mono_locator_init (tdef, mono_metadata_token_index (index), MONO_CLASS_LAYOUT_PARENT); guint32 cols [MONO_CLASS_LAYOUT_SIZE]; if (!tdef->base) return 0; - loc.idx = mono_metadata_token_index (index); - loc.col_idx = MONO_CLASS_LAYOUT_PARENT; - loc.t = tdef; - /* FIXME: metadata-update */ if (!mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator)) @@ -5132,16 +5165,11 @@ guint32 mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index) { MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CUSTOMATTRIBUTE]; - locator_t loc; + mono_locator_t loc = mono_locator_init (tdef, index, MONO_CUSTOM_ATTR_PARENT); if (!tdef->base && !meta->has_updates) return 0; - loc.idx = index; - loc.col_idx = MONO_CUSTOM_ATTR_PARENT; - loc.t = tdef; - loc.result = 0; - /* FIXME: Index translation */ gboolean found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator) != NULL; @@ -5178,15 +5206,11 @@ guint32 mono_metadata_declsec_from_index (MonoImage *meta, guint32 index) { MonoTableInfo *tdef = &meta->tables [MONO_TABLE_DECLSECURITY]; - locator_t loc; + mono_locator_t loc = mono_locator_init (tdef, index, MONO_DECL_SECURITY_PARENT); if (!tdef->base) return -1; - loc.idx = index; - loc.col_idx = MONO_DECL_SECURITY_PARENT; - loc.t = tdef; - /* FIXME: metadata-update */ if (!mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, declsec_locator)) @@ -5212,15 +5236,11 @@ guint32 mono_metadata_localscope_from_methoddef (MonoImage *meta, guint32 index) { MonoTableInfo *tdef = &meta->tables [MONO_TABLE_LOCALSCOPE]; - locator_t loc; + mono_locator_t loc = mono_locator_init (tdef, index, MONO_LOCALSCOPE_METHOD); if (!tdef->base) return 0; - loc.idx = index; - loc.col_idx = MONO_LOCALSCOPE_METHOD; - loc.t = tdef; - /* FIXME: metadata-update */ if (!mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator)) @@ -5611,8 +5631,8 @@ mono_metadata_type_hash (MonoType *t1) * inserted in a bunch of hash tables before been finished. */ if (image_is_dynamic (m_class_get_image (klass))) - return ((m_type_is_byref (t1) ? 1 : 0) << 6) | mono_metadata_str_hash (m_class_get_name (klass)); - return ((hash << 5) - hash) ^ mono_metadata_str_hash (m_class_get_name (klass)); + return ((m_type_is_byref (t1) ? 1 : 0) << 6) | m_class_get_name_hash (klass); + return ((hash << 5) - hash) ^ m_class_get_name_hash (klass); } case MONO_TYPE_PTR: return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type); @@ -6201,17 +6221,26 @@ mono_metadata_type_dup_with_cmods (MonoImage *image, const MonoType *o, const Mo uint8_t num_mods = MAX (mono_type_custom_modifier_count (o), mono_type_custom_modifier_count (cmods_source)); gboolean aggregate = mono_type_is_aggregate_mods (o) || mono_type_is_aggregate_mods (cmods_source); - size_t sizeof_r = mono_sizeof_type_with_mods (num_mods, aggregate); + size_t sizeof_r = mono_sizeof_type_with_mods (num_mods, aggregate), + sizeof_o = mono_sizeof_type (o), + sizeof_cmods_source = cmods_source->has_cmods ? mono_sizeof_type (cmods_source) : 0, + sizeof_header = MAX(sizeof_o, sizeof_cmods_source); + uint8_t *r_bytes = NULL; - r = image ? (MonoType *)mono_image_alloc0 (image, (guint)sizeof_r) : (MonoType *)g_malloc0 (sizeof_r); + r = image ? (MonoType *)mono_image_alloc (image, (guint)sizeof_r) : (MonoType *)g_malloc (sizeof_r); + r_bytes = (uint8_t *)r; if (cmods_source->has_cmods) { /* FIXME: if it's aggregate what do we assert here? */ g_assert (!image || (!aggregate && image == mono_type_get_cmods (cmods_source)->image)); - memcpy (r, cmods_source, mono_sizeof_type (cmods_source)); + // Copy the portion of the source type that won't be overwritten by o below + memcpy (r_bytes + sizeof_o, ((uint8_t *)cmods_source) + sizeof_o, sizeof_cmods_source - sizeof_o); } - memcpy (r, o, mono_sizeof_type (o)); + memcpy (r, o, sizeof_o); + // Zero the remaining uninitialized bytes + if (sizeof_r > sizeof_header) + memset (r_bytes + sizeof_header, 0, sizeof_r - sizeof_header); /* reset custom mod count and aggregateness to be correct. */ mono_type_with_mods_init (r, num_mods, aggregate); @@ -6313,17 +6342,16 @@ mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, MonoMarshalSpec **marshal_spec, gboolean alloc_from_image) { MonoTableInfo *tdef; - locator_t loc = {0,}; + mono_locator_t loc; - loc.idx = index + 1; + guint32 idx = index + 1; if (meta->uncompressed_metadata) - loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx); + idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, idx); if (offset) { tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT]; - loc.col_idx = MONO_FIELD_LAYOUT_FIELD; - loc.t = tdef; + loc = mono_locator_init (tdef, idx, MONO_FIELD_LAYOUT_FIELD); /* metadata-update: explicit layout not supported, just return -1 */ @@ -6336,15 +6364,14 @@ mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, if (rva) { tdef = &meta->tables [MONO_TABLE_FIELDRVA]; - loc.col_idx = MONO_FIELD_RVA_FIELD; - loc.t = tdef; + loc = mono_locator_init (tdef, idx, MONO_FIELD_RVA_FIELD); - gboolean found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator); + gboolean found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator); - if (G_UNLIKELY (meta->has_updates)) { - if (!found) - found = (mono_metadata_update_metadata_linear_search (meta, tdef, &loc, table_locator) != NULL); - } + if (G_UNLIKELY (meta->has_updates)) { + if (!found) + found = (mono_metadata_update_metadata_linear_search (meta, tdef, &loc, table_locator) != NULL); + } if (found) { /* @@ -6379,7 +6406,7 @@ guint32 mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint) { MonoTableInfo *tdef; - locator_t loc; + mono_locator_t loc; guint32 index = mono_metadata_token_index (token); tdef = &meta->tables [MONO_TABLE_CONSTANT]; @@ -6398,9 +6425,8 @@ mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint) g_warning ("Not a valid token for the constant table: 0x%08x", token); return 0; } - loc.idx = index; - loc.col_idx = MONO_CONSTANT_PARENT; - loc.t = tdef; + + loc = mono_locator_init (tdef, index, MONO_CONSTANT_PARENT); /* FIXME: Index translation */ @@ -6429,7 +6455,7 @@ mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint) guint32 mono_metadata_events_from_typedef (MonoImage *meta, guint32 index, guint *end_idx) { - locator_t loc; + mono_locator_t loc; guint32 start, end; MonoTableInfo *tdef = &meta->tables [MONO_TABLE_EVENTMAP]; @@ -6438,10 +6464,7 @@ mono_metadata_events_from_typedef (MonoImage *meta, guint32 index, guint *end_id if (!tdef->base && !meta->has_updates) return 0; - loc.t = tdef; - loc.col_idx = MONO_EVENT_MAP_PARENT; - loc.idx = index + 1; - loc.result = 0; + loc = mono_locator_init (tdef, index + 1, MONO_EVENT_MAP_PARENT); gboolean found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator) != NULL; if (!found && !meta->has_updates) @@ -6460,12 +6483,12 @@ mono_metadata_events_from_typedef (MonoImage *meta, guint32 index, guint *end_id } start = mono_metadata_decode_row_col (tdef, loc.result, MONO_EVENT_MAP_EVENTLIST); - /* - * metadata-update: note this next line needs block needs to look at the number of rows in - * EventMap and Event of the base image. Updates will add rows for new properties, - * but they won't be contiguous. if we set end to the number of rows in the updated - * Property table, the range will include properties from some other class - */ + /* + * metadata-update: note this next line needs block needs to look at the number of rows in + * EventMap and Event of the base image. Updates will add rows for new properties, + * but they won't be contiguous. if we set end to the number of rows in the updated + * Property table, the range will include properties from some other class + */ if (loc.result + 1 < table_info_get_rows (tdef)) { end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_EVENT_MAP_EVENTLIST) - 1; } else { @@ -6487,7 +6510,7 @@ mono_metadata_events_from_typedef (MonoImage *meta, guint32 index, guint *end_id guint32 mono_metadata_methods_from_event (MonoImage *meta, guint32 index, guint *end_idx) { - locator_t loc; + mono_locator_t loc; guint32 start, end; guint32 cols [MONO_METHOD_SEMA_SIZE]; MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS]; @@ -6499,10 +6522,12 @@ mono_metadata_methods_from_event (MonoImage *meta, guint32 index, guint *end_i if (meta->uncompressed_metadata) index = search_ptr_table (meta, MONO_TABLE_EVENT_POINTER, index + 1) - 1; - loc.t = msemt; - loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION; - loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */ - loc.result = 0; + loc = mono_locator_init ( + msemt, + /* Method association coded index */ + ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT, + MONO_METHOD_SEMA_ASSOCIATION + ); gboolean found = msemt->base && mono_binary_search (&loc, msemt->base, table_info_get_rows (msemt), msemt->row_size, table_locator) != NULL; @@ -6547,7 +6572,7 @@ mono_metadata_methods_from_event (MonoImage *meta, guint32 index, guint *end_i guint32 mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *end_idx) { - locator_t loc; + mono_locator_t loc; guint32 start, end; MonoTableInfo *tdef = &meta->tables [MONO_TABLE_PROPERTYMAP]; @@ -6556,10 +6581,7 @@ mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *en if (!tdef->base && !meta->has_updates) return 0; - loc.t = tdef; - loc.col_idx = MONO_PROPERTY_MAP_PARENT; - loc.idx = index + 1; - loc.result = 0; + loc = mono_locator_init (tdef, index + 1, MONO_PROPERTY_MAP_PARENT); gboolean found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator) != NULL; @@ -6579,12 +6601,12 @@ mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *en } start = mono_metadata_decode_row_col (tdef, loc.result, MONO_PROPERTY_MAP_PROPERTY_LIST); - /* - * metadata-update: note this next line needs block needs to look at the number of rows in - * PropertyMap and Property of the base image. Updates will add rows for new properties, - * but they won't be contiguous. if we set end to the number of rows in the updated - * Property table, the range will include properties from some other class - */ + /* + * metadata-update: note this next line needs block needs to look at the number of rows in + * PropertyMap and Property of the base image. Updates will add rows for new properties, + * but they won't be contiguous. if we set end to the number of rows in the updated + * Property table, the range will include properties from some other class + */ if (loc.result + 1 < table_info_get_rows (&meta->tables [MONO_TABLE_PROPERTYMAP])) { end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_PROPERTY_MAP_PROPERTY_LIST) - 1; } else { @@ -6606,7 +6628,7 @@ mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *en guint32 mono_metadata_methods_from_property (MonoImage *meta, guint32 index, guint *end_idx) { - locator_t loc; + mono_locator_t loc; guint32 start, end; guint32 cols [MONO_METHOD_SEMA_SIZE]; MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS]; @@ -6618,10 +6640,12 @@ mono_metadata_methods_from_property (MonoImage *meta, guint32 index, guint *en if (meta->uncompressed_metadata) index = search_ptr_table (meta, MONO_TABLE_PROPERTY_POINTER, index + 1) - 1; - loc.t = msemt; - loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION; - loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */ - loc.result = 0; + loc = mono_locator_init ( + msemt, + /* Method association coded index */ + ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY, + MONO_METHOD_SEMA_ASSOCIATION + ); gboolean found = msemt->base && mono_binary_search (&loc, msemt->base, table_info_get_rows (msemt), msemt->row_size, table_locator) != NULL; @@ -6661,7 +6685,7 @@ mono_metadata_methods_from_property (MonoImage *meta, guint32 index, guint *en guint32 mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx) { - locator_t loc; + mono_locator_t loc; MonoTableInfo *tdef = &meta->tables [MONO_TABLE_IMPLMAP]; if (!tdef->base) @@ -6669,9 +6693,7 @@ mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx) /* No index translation seems to be needed */ - loc.t = tdef; - loc.col_idx = MONO_IMPLMAP_MEMBER; - loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF; + loc = mono_locator_init (tdef, ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF, MONO_IMPLMAP_MEMBER); /* FIXME: metadata-update */ @@ -7085,21 +7107,23 @@ mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_fiel const char* mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field) { - locator_t loc = {0,}; + mono_locator_t loc; MonoTableInfo *tdef = &meta->tables [MONO_TABLE_FIELDMARSHAL]; - loc.t = tdef; - loc.col_idx = MONO_FIELD_MARSHAL_PARENT; - loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF); + loc = mono_locator_init ( + tdef, + ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF), + MONO_FIELD_MARSHAL_PARENT + ); /* FIXME: Index translation */ gboolean found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator); - if (G_UNLIKELY (meta->has_updates)) { - if (!found && !mono_metadata_update_metadata_linear_search (meta, tdef, &loc, table_locator)) - return NULL; - } + if (G_UNLIKELY (meta->has_updates)) { + if (!found && !mono_metadata_update_metadata_linear_search (meta, tdef, &loc, table_locator)) + return NULL; + } return mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE)); } @@ -7135,7 +7159,7 @@ mono_method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContex void mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod ***overrides, gint32 *num_overrides, MonoGenericContext *generic_context, MonoError *error) { - locator_t loc; + mono_locator_t loc; MonoTableInfo *tdef = &image->tables [MONO_TABLE_METHODIMPL]; guint32 start, end; gint32 i, num; @@ -7151,10 +7175,7 @@ mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod if (!tdef->base && !image->has_updates) return; - loc.t = tdef; - loc.col_idx = MONO_METHODIMPL_CLASS; - loc.idx = mono_metadata_token_index (type_token); - loc.result = 0; + loc = mono_locator_init (tdef, mono_metadata_token_index (type_token), MONO_METHODIMPL_CLASS); gboolean found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator) != NULL; @@ -7253,7 +7274,7 @@ get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGene { MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT]; guint32 cols [MONO_GENPARCONSTRAINT_SIZE]; - locator_t loc; + mono_locator_t loc; guint32 i, token, found, start; MonoClass *klass, **res; GSList *cons = NULL, *tmp; @@ -7266,10 +7287,7 @@ get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGene /* FIXME: metadata-update */ guint32 rows = table_info_get_rows (tdef); - loc.idx = owner; - loc.col_idx = MONO_GENPARCONSTRAINT_GENERICPAR; - loc.t = tdef; - loc.result = 0; + loc = mono_locator_init (tdef, owner, MONO_GENPARCONSTRAINT_GENERICPAR); gboolean is_found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator) != NULL; if (!is_found && !image->has_updates) @@ -7326,7 +7344,7 @@ guint32 mono_metadata_get_generic_param_row (MonoImage *image, guint32 token, guint32 *owner) { MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM]; - locator_t loc; + mono_locator_t loc; g_assert (owner); if (!tdef->base && !image->has_updates) @@ -7342,10 +7360,7 @@ mono_metadata_get_generic_param_row (MonoImage *image, guint32 token, guint32 *o } *owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS; - loc.idx = *owner; - loc.col_idx = MONO_GENERICPARAM_OWNER; - loc.t = tdef; - loc.result = 0; + loc = mono_locator_init (tdef, *owner, MONO_GENERICPARAM_OWNER); gboolean found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator) != NULL; if (!found && !image->has_updates) @@ -8072,3 +8087,12 @@ mono_metadata_get_method_params (MonoImage *image, uint32_t method_idx, uint32_t return param_index; } + +// Required by dn_simdhash +void +dn_simdhash_assert_fail (const char *file, int line, const char *condition); + +void +dn_simdhash_assert_fail (const char *file, int line, const char *condition) { + mono_assertion_message (file, line, condition); +} diff --git a/src/mono/mono/metadata/method-builder-ilgen-internals.h b/src/mono/mono/metadata/method-builder-ilgen-internals.h index 1aa410beb34a..74538a7d5a1f 100644 --- a/src/mono/mono/metadata/method-builder-ilgen-internals.h +++ b/src/mono/mono/metadata/method-builder-ilgen-internals.h @@ -33,6 +33,25 @@ struct _MonoMethodBuilder { const gchar **param_names; MonoBitSet *volatile_args; MonoBitSet *volatile_locals; + gboolean inflate_wrapper_data; + GList *wrapper_data_inflate_info; }; +typedef struct MonoMethodBuilderInflateWrapperData +{ + uint16_t idx; + uint16_t kind; // MonoILGenWrapperDataKind +} MonoMethodBuilderInflateWrapperData; + +enum MonoILGenWrapperDataKind +{ + MONO_MB_ILGEN_WRAPPER_DATA_NONE = 0, + MONO_MB_ILGEN_WRAPPER_DATA_FIELD, + MONO_MB_ILGEN_WRAPPER_DATA_METHOD, +}; + +// index in MonoMethodWrapper:wrapper_data where the inflate info will be stored. +// note: idx 1 is the wrapper info (see mono_marshal_get_wrapper_info) +#define MONO_MB_ILGEN_INFLATE_WRAPPER_INFO_IDX 2 + #endif diff --git a/src/mono/mono/metadata/method-builder-ilgen.c b/src/mono/mono/metadata/method-builder-ilgen.c index 41bfc8fa6804..47f8a6d6cb54 100644 --- a/src/mono/mono/metadata/method-builder-ilgen.c +++ b/src/mono/mono/metadata/method-builder-ilgen.c @@ -52,7 +52,7 @@ new_base_ilgen (MonoClass *klass, MonoWrapperType type, gboolean dynamic) mb->init_locals = TRUE; mb->dynamic = dynamic; - /* placeholder for the wrapper always at index 1 */ + /* placeholder for the wrapper always at index 1, see mono_marshal_set_wrapper_info */ mono_mb_add_data (mb, NULL); return mb; @@ -61,9 +61,15 @@ new_base_ilgen (MonoClass *klass, MonoWrapperType type, gboolean dynamic) static void free_ilgen (MonoMethodBuilder *mb) { - GList *l; + if (mb->wrapper_data_inflate_info) { + for (GList *p = mb->wrapper_data_inflate_info; p && p->data; p = p->next) { + g_free (p->data); + } + g_list_free (mb->wrapper_data_inflate_info); + mb->wrapper_data_inflate_info = NULL; + } - for (l = mb->locals_list; l; l = l->next) { + for (GList *l = mb->locals_list; l; l = l->next) { /* Allocated in mono_mb_add_local () */ g_free (l->data); } @@ -172,14 +178,44 @@ create_method_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *signature, int i = g_list_length ((GList *)mw->method_data); if (i) { + MonoMethodBuilderInflateWrapperData *inflate_data = NULL; + if (mb->inflate_wrapper_data) { + int count = g_list_length (mb->wrapper_data_inflate_info); + inflate_data = (MonoMethodBuilderInflateWrapperData *) mb_alloc0 (mb, sizeof(MonoMethodBuilderInflateWrapperData) * (count + 1)); + int j = 0; + for (GList *p = mb->wrapper_data_inflate_info; p && p->data; p = p->next) { + inflate_data[j++] = *(MonoMethodBuilderInflateWrapperData*)p->data; + } + // trailing idx 0 element to mark the end + inflate_data[j].idx = 0; + inflate_data[j].kind = MONO_MB_ILGEN_WRAPPER_DATA_NONE; + mw->inflate_wrapper_data = 1; + } GList *tmp; void **data; l = g_list_reverse ((GList *)mw->method_data); - data = (void **)mb_alloc0 (mb, sizeof (gpointer) * (i + 1)); + int data_count = i + (inflate_data ? 2 : 1); + data = (void **)mb_alloc0 (mb, sizeof (gpointer) * data_count); /* store the size in the first element */ data [0] = GUINT_TO_POINTER (i); i = 1; - for (tmp = l; tmp; tmp = tmp->next) { + + // manually peel off the first 1 or 2 iterations of the loop since they're special + tmp = l; + g_assert (tmp); + // wrapper info is in slot 1 + g_assert (tmp->data == NULL); + data [i++] = NULL; + tmp = tmp->next; + // inflate data is in slot 2 + if (inflate_data) { + g_assert (tmp); + g_assert (MONO_MB_ILGEN_INFLATE_WRAPPER_INFO_IDX == i); + g_assert (tmp->data == NULL); + data[i++] = inflate_data; + tmp = tmp->next; + } + for (;tmp; tmp = tmp->next) { data [i++] = tmp->data; } g_list_free (l); @@ -214,6 +250,20 @@ create_method_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *signature, int mono_image_unlock (image); } + if (mb->method->is_generic) { + method->is_generic = TRUE; + MonoGenericContainer *container = mono_method_get_generic_container (mb->method); + mono_method_set_generic_container (method, container); + g_assert (!container->is_anonymous); + g_assert (container->is_method); + g_assert (container->owner.method == mb->method); + // NOTE: reassigning container owner from the method builder placeholder to the + // final created method. The "proper" way to do this would be a deep copy or + // calling mono_metadata_load_generic_params again and inflating everything. But + // method builder is already one-shot, so this is ok, too. + container->owner.method = method; + } + return method; } @@ -652,3 +702,77 @@ mono_mb_set_param_names (MonoMethodBuilder *mb, const char **param_names) { mb->param_names = param_names; } + +void +mono_mb_set_wrapper_data_kind (MonoMethodBuilder *mb, uint16_t wrapper_data_kind) +{ + g_assert (mb->inflate_wrapper_data); + MonoMethodWrapper *mw = (MonoMethodWrapper*)mb->method; + // index of the data added by most recent mono_mb_add_data + int idx = g_list_length((GList *)mw->method_data); + g_assert (idx > 0 && idx <= UINT16_MAX); + + MonoMethodBuilderInflateWrapperData *info = g_new (MonoMethodBuilderInflateWrapperData, 1); + info->idx = (uint16_t)idx; + info->kind = wrapper_data_kind; + mb->wrapper_data_inflate_info = g_list_prepend (mb->wrapper_data_inflate_info, info); +} + +gboolean +mono_mb_inflate_generic_wrapper_data (MonoGenericContext *context, gpointer *method_data, MonoError *error) +{ + MonoMethodBuilderInflateWrapperData* inflate_info = (MonoMethodBuilderInflateWrapperData*)method_data[MONO_MB_ILGEN_INFLATE_WRAPPER_INFO_IDX]; + MonoMethodBuilderInflateWrapperData* p = inflate_info; + + while (p && p->idx != 0) { + int idx = p->idx; + uint16_t kind = p->kind; + gpointer *pdata = &method_data[idx]; + switch (kind) { + case MONO_MB_ILGEN_WRAPPER_DATA_NONE: + continue; + case MONO_MB_ILGEN_WRAPPER_DATA_FIELD: { + MonoClassField *field = (MonoClassField*)*pdata; + MonoType *inflated_type = mono_class_inflate_generic_type_checked (m_class_get_byval_arg (m_field_get_parent (field)), context, error); + if (!is_ok (error)) + return FALSE; + + MonoClass *inflated_class = mono_class_from_mono_type_internal (inflated_type); + // TODO: EnC metadata-update. But note: + // error ENC0025: Adding an extern method requires restarting the application. + // + // So for UnsafeAccessor methods we don't need to handle this + // until https://github.com/dotnet/runtime/issues/102080 + // + // But if we have other kinds of generic wrappers, we may need to do it sooner. + g_assert (!m_field_is_from_update (field)); + int i = GPTRDIFF_TO_INT (field - m_class_get_fields (m_field_get_parent (field))); + gpointer dummy = NULL; + + mono_metadata_free_type (inflated_type); + + // note: inflated class might not have been used for much yet. Ensure + // fields are initialized. + mono_class_get_fields_internal (inflated_class, &dummy); + g_assert (m_class_get_fields (inflated_class)); + + MonoClassField *inflated_field = &m_class_get_fields (inflated_class) [i]; + + *pdata = inflated_field; + break; + } + case MONO_MB_ILGEN_WRAPPER_DATA_METHOD: { + MonoMethod *method = (MonoMethod*)*pdata; + MonoMethod *inflated_method = mono_class_inflate_generic_method_checked (method, context, error); + if (!is_ok (error)) + return FALSE; + *pdata = inflated_method; + break; + } + default: + g_assert_not_reached(); + } + p++; + } + return TRUE; +} diff --git a/src/mono/mono/metadata/method-builder-ilgen.h b/src/mono/mono/metadata/method-builder-ilgen.h index 2a5e40dc7025..209565d30282 100644 --- a/src/mono/mono/metadata/method-builder-ilgen.h +++ b/src/mono/mono/metadata/method-builder-ilgen.h @@ -139,4 +139,11 @@ mono_mb_set_param_names (MonoMethodBuilder *mb, const char **param_names); char* mono_mb_strdup (MonoMethodBuilder *mb, const char *s); +void +mono_mb_set_wrapper_data_kind (MonoMethodBuilder *mb, uint16_t wrapper_data_kind); + +gboolean +mono_mb_inflate_generic_wrapper_data (MonoGenericContext *context, gpointer *method_data, MonoError *error); + + #endif diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c index f26ab2e9152a..6adb70bfda4d 100644 --- a/src/mono/mono/metadata/native-library.c +++ b/src/mono/mono/metadata/native-library.c @@ -1222,3 +1222,63 @@ mono_loader_install_pinvoke_override (PInvokeOverrideFn override_fn) { pinvoke_override = override_fn; } + +static gboolean +is_symbol_char_verbatim (unsigned char b) +{ + return ((b >= '0' && b <= '9') || (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z')); +} + +static gboolean +is_symbol_char_underscore (unsigned char c) +{ + switch (c) { + case '_': + case '.': + case '-': + case '+': + case '<': + case '>': + return TRUE; + default: + return FALSE; + } +} + +static size_t mono_precompute_size (const char *key) +{ + size_t size = 1; // Null terminator + size_t len = (int)strlen (key); + for (size_t i = 0; i < len; ++i) { + unsigned char b = key[i]; + if (is_symbol_char_verbatim (b) || is_symbol_char_underscore (b)) { + size++; + } + else { + size += 4; + } + } + return size; +} + +// Keep synced with FixupSymbolName from src/tasks/Common/Utils.cs +char* mono_fixup_symbol_name (const char *prefix, const char *key, const char *suffix) { + size_t size = mono_precompute_size (key) + strlen (prefix) + strlen (suffix); + GString *str = g_string_sized_new (size); + size_t len = (int)strlen (key); + g_string_append_printf (str, "%s", prefix); + + for (size_t i = 0; i < len; ++i) { + unsigned char b = key[i]; + if (is_symbol_char_verbatim (b)) { + g_string_append_c (str, b); + } else if (is_symbol_char_underscore (b)) { + g_string_append_c (str, '_'); + } else { + // Append the hex representation of b between underscores + g_string_append_printf (str, "_%X_", b); + } + } + g_string_append_printf (str, "%s", suffix); + return g_string_free (str, FALSE); +} diff --git a/src/mono/mono/metadata/native-library.h b/src/mono/mono/metadata/native-library.h index 9108a86ae754..9a794a5bb8af 100644 --- a/src/mono/mono/metadata/native-library.h +++ b/src/mono/mono/metadata/native-library.h @@ -35,4 +35,7 @@ mono_lookup_pinvoke_qcall_internal (const char *name); void mono_loader_install_pinvoke_override (PInvokeOverrideFn override_fn); +char * +mono_fixup_symbol_name (const char *prefix, const char *key, const char *suffix); + #endif diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index 4b14d889b9df..2a0e9e9834e0 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -1343,7 +1343,7 @@ mono_method_get_imt_slot (MonoMethod *method) } /* Initialize hashes */ - hashes [0] = mono_metadata_str_hash (m_class_get_name (method->klass)); + hashes [0] = m_class_get_name_hash (method->klass); hashes [1] = mono_metadata_str_hash (m_class_get_name_space (method->klass)); hashes [2] = mono_metadata_str_hash (method->name); hashes [3] = mono_metadata_type_hash (sig->ret); diff --git a/src/mono/mono/metadata/reflection.c b/src/mono/mono/metadata/reflection.c index 4e450e027ac8..1539b020a1b6 100644 --- a/src/mono/mono/metadata/reflection.c +++ b/src/mono/mono/metadata/reflection.c @@ -440,6 +440,48 @@ mono_type_get_object (MonoDomain *domain, MonoType *type) return ret; } +/* LOCKING: assumes the loader lock is taken */ +static MonoReflectionType* +mono_type_get_object_checked_alloc_helper (MonoType *type, MonoMemoryManager *memory_manager, MonoDomain *domain, MonoError *error) +{ + HANDLE_FUNCTION_ENTER (); + + MonoReflectionType *res, *cached; + /* This is stored in vtables/JITted code so it has to be pinned */ + MonoReflectionTypeHandle res_handle = MONO_HANDLE_CAST (MonoReflectionType, mono_object_new_pinned_handle (mono_defaults.runtimetype_class, error)); + goto_if_nok (error, exit); + + res = MONO_HANDLE_RAW (res_handle); + + res->type = type; + if (memory_manager->collectible) { + MonoObject *loader_alloc = mono_gchandle_get_target_internal (mono_mem_manager_get_loader_alloc (memory_manager)); + g_assert (loader_alloc); + MONO_OBJECT_SETREF_INTERNAL (res, m_keepalive, loader_alloc); + } + + mono_mem_manager_lock (memory_manager); + if (memory_manager->collectible) + cached = (MonoReflectionType *)mono_weak_hash_table_lookup (memory_manager->weak_type_hash, type); + else + cached = (MonoReflectionType *)mono_g_hash_table_lookup (memory_manager->type_hash, type); + if (cached) { + res = cached; + MONO_HANDLE_ASSIGN_RAW (res_handle, res); + } else { + if (memory_manager->collectible) + mono_weak_hash_table_insert (memory_manager->weak_type_hash, type, res); + else + mono_g_hash_table_insert_internal (memory_manager->type_hash, type, res); + if (type->type == MONO_TYPE_VOID && !m_type_is_byref (type)) + domain->typeof_void = (MonoObject*)res; + } + mono_mem_manager_unlock (memory_manager); + +exit: + HANDLE_FUNCTION_RETURN_OBJ (res_handle); +} + MonoReflectionType* mono_type_get_object_checked (MonoType *type, MonoError *error) { @@ -554,33 +596,9 @@ mono_type_get_object_checked (MonoType *type, MonoError *error) res = &mono_class_get_ref_info_raw (klass)->type; /* FIXME use handles */ goto leave; } - /* This is stored in vtables/JITted code so it has to be pinned */ - res = (MonoReflectionType *)mono_object_new_pinned (mono_defaults.runtimetype_class, error); - goto_if_nok (error, leave); - res->type = type; - if (memory_manager->collectible) { - MonoObject *loader_alloc = mono_gchandle_get_target_internal (mono_mem_manager_get_loader_alloc (memory_manager)); - g_assert (loader_alloc); - MONO_OBJECT_SETREF_INTERNAL (res, m_keepalive, loader_alloc); - } - mono_mem_manager_lock (memory_manager); - if (memory_manager->collectible) - cached = (MonoReflectionType *)mono_weak_hash_table_lookup (memory_manager->weak_type_hash, type); - else - cached = (MonoReflectionType *)mono_g_hash_table_lookup (memory_manager->type_hash, type); - if (cached) { - res = cached; - } else { - if (memory_manager->collectible) - mono_weak_hash_table_insert (memory_manager->weak_type_hash, type, res); - else - mono_g_hash_table_insert_internal (memory_manager->type_hash, type, res); - if (type->type == MONO_TYPE_VOID && !m_type_is_byref (type)) - domain->typeof_void = (MonoObject*)res; - } - mono_mem_manager_unlock (memory_manager); + res = mono_type_get_object_checked_alloc_helper (type, memory_manager, domain, error); leave: mono_loader_unlock (); diff --git a/src/mono/mono/metadata/sre.c b/src/mono/mono/metadata/sre.c index 47c086595af0..7def0d08abd6 100644 --- a/src/mono/mono/metadata/sre.c +++ b/src/mono/mono/metadata/sre.c @@ -2555,6 +2555,7 @@ reflection_setup_internal_class_internal (MonoReflectionTypeBuilderHandle ref_tb klass->inited = 1; /* we lie to the runtime */ klass->name = mono_string_to_utf8_image (klass->image, ref_name, error); goto_if_nok (error, leave); + klass->name_hash = mono_metadata_str_hash (klass->name); klass->name_space = mono_string_to_utf8_image (klass->image, ref_nspace, error); goto_if_nok (error, leave); klass->type_token = MONO_TOKEN_TYPE_DEF | table_idx; diff --git a/src/mono/mono/metadata/unsafe-accessor.c b/src/mono/mono/metadata/unsafe-accessor.c index e7287a00c461..584b29146586 100644 --- a/src/mono/mono/metadata/unsafe-accessor.c +++ b/src/mono/mono/metadata/unsafe-accessor.c @@ -14,7 +14,7 @@ #include "mono/metadata/class-internals.h" #include "mono/utils/mono-error-internals.h" #include "mono/metadata/unsafe-accessor.h" - +#include static MonoMethod * @@ -134,7 +134,10 @@ find_method_slow (MonoClass *klass, const char *name, const char *qname, const c return precise_match; } mono_error_set_generic_error (error, "System.Reflection", "AmbiguousMatchException", "Ambiguity in binding of UnsafeAccessorAttribute."); - return NULL; + result->i = -1; + result->m = NULL; + result->matched = FALSE; + return result; } matched = TRUE; result->i = i; @@ -176,23 +179,10 @@ find_method_in_class_unsafe_accessor (MonoClass *klass, const char *name, const if (!is_ok(error) && mono_error_get_error_code (error) == MONO_ERROR_GENERIC) return NULL; - int mcount = mono_class_get_method_count (klass); g_assert (result != NULL); if (result->matched) { - if (result->i < mcount) - return mono_class_get_method_by_index (from_class, result->i); - else if (result->m != NULL) { - // FIXME: metadata-update: hack - // it's from a metadata-update, probably - MonoMethod * m = mono_class_inflate_generic_method_full_checked ( - result->m, from_class, mono_class_get_context (from_class), error); - mono_error_assert_ok (error); - g_assert (m != NULL); - g_assert (m->klass == from_class); - g_assert (m->is_inflated); - return m; - } + return result->m; } g_free (result); diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt index e81afefecfc2..b9bd9d426bc6 100644 --- a/src/mono/mono/mini/CMakeLists.txt +++ b/src/mono/mono/mini/CMakeLists.txt @@ -49,6 +49,14 @@ endif() # MINI # +set(imported_native_sources + ../../../native/containers/dn-simdhash.c + ../../../native/containers/dn-simdhash-ptr-ptr.c + ../../../native/containers/dn-simdhash-string-ptr.c + ../../../native/containers/dn-simdhash-u32-ptr.c + ../../../native/containers/dn-simdhash-ght-compatible.c + ../../../native/containers/dn-simdhash-ptrpair-ptr.c) + set(mini_common_sources mini.c mini-runtime.c @@ -302,7 +310,7 @@ else() set(profiler_sources "") endif() -set(mini_sources "main-core.c;${mini_common_sources};${arch_sources};${os_sources};${mini_interp_sources};${llvm_sources};${debugger_sources};${profiler_sources};${llvm_runtime_sources}") +set(mini_sources "main-core.c;${imported_native_sources};${mini_common_sources};${arch_sources};${os_sources};${mini_interp_sources};${llvm_sources};${debugger_sources};${profiler_sources};${llvm_runtime_sources}") if(LLVM_INCLUDEDIR) include_directories(BEFORE SYSTEM "${LLVM_INCLUDEDIR}") diff --git a/src/mono/mono/mini/alias-analysis.c b/src/mono/mono/mini/alias-analysis.c index 2e0d4507b9ef..abbdedb43074 100644 --- a/src/mono/mono/mini/alias-analysis.c +++ b/src/mono/mono/mini/alias-analysis.c @@ -53,10 +53,11 @@ lower_load (MonoCompile *cfg, MonoInst *load, MonoInst *ldaddr) } if (replaced_op != load->opcode) { - if (cfg->verbose_level > 2) - printf ("Incompatible load type: expected %s but got %s\n", + if (cfg->verbose_level > 2) { + printf ("Incompatible load type: expected " M_PRI_INST " but got " M_PRI_INST "\n", mono_inst_name (replaced_op), mono_inst_name (load->opcode)); + } return FALSE; } else { if (cfg->verbose_level > 2) { printf ("mem2reg replacing: "); mono_print_ins (load); } @@ -84,10 +85,11 @@ lower_store (MonoCompile *cfg, MonoInst *store, MonoInst *ldaddr) if (replaced_op != store->opcode) { - if (cfg->verbose_level > 2) - printf ("Incompatible store_reg type: expected %s but got %s\n", + if (cfg->verbose_level > 2) { + printf ("Incompatible store_reg type: expected " M_PRI_INST " but got " M_PRI_INST "\n", mono_inst_name (replaced_op), mono_inst_name (store->opcode)); + } return FALSE; } else { if (cfg->verbose_level > 2) { printf ("mem2reg replacing: "); mono_print_ins (store); } diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index bda04415e2d6..57edfe8b0873 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -3872,7 +3873,18 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 uint32_t len = (uint32_t) strlen (info->d.unsafe_accessor.member_name); encode_value (len, p, &p); encode_string (info->d.unsafe_accessor.member_name, p, &p); + } else { + encode_value (0, p, &p); + } + if (method->is_inflated) { + encode_value(1, p, &p); + MonoMethodInflated *inflated = (MonoMethodInflated*)method; + MonoGenericContext *ctx = &inflated->context; + encode_generic_context (acfg, ctx, p, &p); + } else { + encode_value(0, p, &p); } + } else if (info->subtype == WRAPPER_SUBTYPE_INTERP_IN) encode_signature (acfg, info->d.interp_in.sig, p, &p); @@ -4820,6 +4832,19 @@ mono_aot_can_enter_interp (MonoMethod *method) return FALSE; } +static MonoMethod* +replace_generated_method (MonoAotCompile *acfg, MonoMethod *method, MonoError *error) +{ + MonoMethod *wrapper = mini_replace_generated_method (method, error); + if (!is_ok (error)) { + char *method_name = mono_method_get_full_name (method); + aot_printerrf (acfg, "Could not get generated wrapper for %s due to %s", method_name, mono_error_get_message (error)); + g_free (method_name); + } + + return wrapper; +} + static void add_full_aot_wrappers (MonoAotCompile *acfg) { @@ -5310,25 +5335,6 @@ add_full_aot_wrappers (MonoAotCompile *acfg) add_method (acfg, mono_marshal_get_ptr_to_struct (klass)); } } - - /* unsafe accessor wrappers */ - rows = table_info_get_rows (&acfg->image->tables [MONO_TABLE_METHOD]); - for (int i = 0; i < rows; ++i) { - ERROR_DECL (error); - token = MONO_TOKEN_METHOD_DEF | (i + 1); - method = mono_get_method_checked (acfg->image, token, NULL, NULL, error); - report_loader_error (acfg, error, TRUE, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (error)); - - if (G_LIKELY (mono_method_metadata_has_header (method))) - continue; - - char *member_name = NULL; - int accessor_kind = -1; - if (mono_method_get_unsafe_accessor_attr_data (method, &accessor_kind, &member_name, error)) { - add_extra_method (acfg, mono_marshal_get_unsafe_accessor_wrapper (method, (MonoUnsafeAccessorKind)accessor_kind, member_name)); - } - } - } static void @@ -6023,6 +6029,16 @@ add_generic_instances (MonoAotCompile *acfg) continue; } + if (mono_aot_mode_is_full (&acfg->aot_opts)) { + MonoMethod *gen = replace_generated_method (acfg, method, error); + if (!is_ok (error)) { + mono_error_cleanup (error); + continue; + } else if (gen != NULL) { + method = gen; + } + } + if (m_class_get_image (method->klass) != acfg->image) continue; @@ -6118,6 +6134,8 @@ add_generic_instances (MonoAotCompile *acfg) add_extra_method (acfg, method); } + // TODO: [UnsafeAccessor] if there's a typespec from another assembly that has an + // unsafe accessor, we need to add it here. rows = table_info_get_rows (&acfg->image->tables [MONO_TABLE_TYPESPEC]); for (int i = 0; i < rows; ++i) { ERROR_DECL (error); @@ -9354,6 +9372,17 @@ add_referenced_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, int depth) if (mono_aot_mode_is_full (&acfg->aot_opts) && !method_has_type_vars (m)) add_extra_method_with_depth (acfg, mono_marshal_get_native_wrapper (m, TRUE, TRUE), depth + 1); } else { + if (mono_aot_mode_is_full (&acfg->aot_opts)) { + ERROR_DECL(error); + MonoMethod *gen = replace_generated_method (acfg, m, error); + if (!is_ok (error)) { + mono_error_cleanup (error); + return; + } else if (gen != NULL) { + m = gen; + } + } + add_extra_method_with_depth (acfg, m, depth + 1); add_types_from_method_header (acfg, m); } @@ -11181,7 +11210,7 @@ mono_aot_type_hash (MonoType *t1) case MONO_TYPE_CLASS: case MONO_TYPE_SZARRAY: /* check if the distribution is good enough */ - return ((hash << 5) - hash) ^ mono_metadata_str_hash (m_class_get_name (t1->data.klass)); + return ((hash << 5) - hash) ^ m_class_get_name_hash (t1->data.klass); case MONO_TYPE_PTR: return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type); case MONO_TYPE_ARRAY: @@ -11251,7 +11280,7 @@ mono_aot_method_hash (MonoMethod *method) hashes [1] = 0; g_free (full_name); } else { - hashes [0] = mono_metadata_str_hash (m_class_get_name (klass)); + hashes [0] = m_class_get_name_hash (klass); hashes [1] = mono_metadata_str_hash (m_class_get_name_space (klass)); } if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE && mono_marshal_get_wrapper_info (method)->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) @@ -12407,22 +12436,14 @@ emit_file_info (MonoAotCompile *acfg) if (acfg->aot_opts.static_link) { char symbol [MAX_SYMBOL_SIZE]; - char *p; /* * Emit a global symbol which can be passed by an embedding app to * mono_aot_register_module (). The symbol points to a pointer to the file info * structure. */ - sprintf (symbol, "%smono_aot_module_%s_info", acfg->user_symbol_prefix, acfg->image->assembly->aname.name); - - /* Get rid of characters which cannot occur in symbols */ - p = symbol; - for (p = symbol; *p; ++p) { - if (!(isalnum (*p) || *p == '_')) - *p = '_'; - } - acfg->static_linking_symbol = g_strdup (symbol); + snprintf (symbol, MAX_SYMBOL_SIZE, "%smono_aot_module_%s", acfg->user_symbol_prefix, acfg->image->assembly->aname.name); + acfg->static_linking_symbol = mono_fixup_symbol_name ("", symbol, "_info"); } if (acfg->llvm) @@ -13000,6 +13021,17 @@ collect_methods (MonoAotCompile *acfg) method = wrapper; } + if (mono_aot_mode_is_full (&acfg->aot_opts)) { + // if the method has no body, see if it's an [UnsafeAccessor] method and replace it by the wrapper. + MonoMethod *gen = replace_generated_method (acfg, method, error); + if (!is_ok (error)) { + mono_error_cleanup (error); + return FALSE; + } else if (gen != NULL) { + method = gen; + } + } + /* FIXME: Some mscorlib methods don't have debug info */ /* if (acfg->aot_opts.soft_debug && !method->wrapper_type) { @@ -13044,6 +13076,20 @@ collect_methods (MonoAotCompile *acfg) method = mono_get_method_checked (acfg->image, token, NULL, NULL, error); report_loader_error (acfg, error, TRUE, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (error)); + if (mono_aot_mode_is_full (&acfg->aot_opts) && !mono_method_metadata_has_header (method)) { + // if the method has no body, see if it's an [UnsafeAccessor] method and replace it by the wrapper. + char *member_name = NULL; + int accessor_kind = -1; + if (mono_method_get_unsafe_accessor_attr_data (method, &accessor_kind, &member_name, error)) { + MonoMethod *wrapper = mono_marshal_get_unsafe_accessor_wrapper (method, (MonoUnsafeAccessorKind)accessor_kind, member_name); + method = wrapper; + } else if (!is_ok (error)) { + aot_printerrf (acfg, "Could not get unsafe accessor wrapper due to %s ", mono_error_get_message (error)); + mono_error_cleanup (error); + return FALSE; + } + } + if ((method->is_generic || mono_class_is_gtd (method->klass)) && should_emit_gsharedvt_method (acfg, method)) { MonoMethod *gshared; @@ -13789,7 +13835,7 @@ is_local_inst (MonoGenericInst *inst, MonoImage *image) { for (guint i = 0; i < inst->type_argc; ++i) { MonoClass *k = mono_class_from_mono_type_internal (inst->type_argv [i]); - if (!MONO_TYPE_IS_PRIMITIVE (inst->type_argv [i]) && m_class_get_image (k) != image) + if ((m_class_get_image (k) != mono_defaults.corlib) && (m_class_get_image (k) != image)) return FALSE; } return TRUE; @@ -14291,6 +14337,8 @@ acfg_free (MonoAotCompile *acfg) g_free (acfg->static_linking_symbol); g_free (acfg->got_symbol); g_free (acfg->plt_symbol); + g_free (acfg->global_prefix); + g_free (acfg->assembly_name_sym); g_ptr_array_free (acfg->methods, TRUE); g_ptr_array_free (acfg->image_table, TRUE); g_ptr_array_free (acfg->globals, TRUE); @@ -14860,7 +14908,6 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) { MonoImage *image = ass->image; MonoAotCompile *acfg; - char *p; int res; TV_DECLARE (atv); TV_DECLARE (btv); @@ -15119,13 +15166,7 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) if (acfg->aot_opts.llvm_only) acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_LLVM_ONLY); - acfg->assembly_name_sym = g_strdup (get_assembly_prefix (acfg->image)); - /* Get rid of characters which cannot occur in symbols */ - for (p = acfg->assembly_name_sym; *p; ++p) { - if (!(isalnum (*p) || *p == '_')) - *p = '_'; - } - + acfg->assembly_name_sym = mono_fixup_symbol_name ("", get_assembly_prefix (acfg->image), ""); acfg->global_prefix = g_strdup_printf ("mono_aot_%s", acfg->assembly_name_sym); acfg->plt_symbol = g_strdup_printf ("%s_plt", acfg->global_prefix); acfg->got_symbol = g_strdup_printf ("%s_got", acfg->global_prefix); diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index bdd39e400edc..902c049c50f2 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -106,9 +107,9 @@ struct MonoAotModule { GHashTable *name_cache; GHashTable *extra_methods; /* Maps methods to their code */ - GHashTable *method_to_code; + dn_simdhash_ptr_ptr_t *method_to_code; /* Maps pointers into the method info to the methods themselves */ - GHashTable *method_ref_to_method; + dn_simdhash_ptr_ptr_t *method_ref_to_method; MonoAssemblyName *image_names; char **image_guids; MonoAssembly *assembly; @@ -1077,9 +1078,22 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod return FALSE; MonoUnsafeAccessorKind kind = (MonoUnsafeAccessorKind) decode_value (p, &p); uint32_t name_len = decode_value (p, &p); - const char *member_name = (const char*)p; - p += name_len + 1; - ref->method = mono_marshal_get_unsafe_accessor_wrapper (m, kind, member_name); + const char *member_name = NULL; + if (name_len > 0) { + member_name = (const char*)p; + p += name_len + 1; + } + int32_t inflated = decode_value (p, &p); + if (inflated) { + MonoGenericContext ctx = {0,}; + decode_generic_context (module, &ctx, p, &p, error); + mono_error_assert_ok (error); + ref->method = mini_inflate_unsafe_accessor_wrapper (m, &ctx, kind, member_name, error); + if (!is_ok (error)) + return FALSE; + } else { + ref->method = mono_marshal_get_unsafe_accessor_wrapper (m, kind, member_name); + } } else if (subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN) { ref->method = mono_marshal_get_gsharedvt_in_wrapper (); } else if (subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT) { @@ -1971,6 +1985,12 @@ load_aot_module (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer if (mono_aot_mode == MONO_AOT_MODE_NONE) return; +#ifdef HOST_BROWSER + // This indicates that we were not built for AOT, so there's no need to probe for AOT modules. + if (mono_aot_mode == MONO_AOT_MODE_INTERP_ONLY) + return; +#endif + if (assembly->image->aot_module) /* * Already loaded. This can happen because the assembly loading code might invoke @@ -2153,7 +2173,8 @@ load_aot_module (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer amodule->llvm_got = g_malloc0 (sizeof (gpointer) * amodule->info.llvm_got_size); amodule->globals = globals; amodule->sofile = sofile; - amodule->method_to_code = g_hash_table_new (mono_aligned_addr_hash, NULL); + // FIXME: Select a better default size + amodule->method_to_code = dn_simdhash_ptr_ptr_new (4096, NULL); amodule->extra_methods = g_hash_table_new (NULL, NULL); amodule->shared_got = g_new0 (gpointer, info->nshared_got_entries); @@ -2480,7 +2501,7 @@ load_container_amodule (MonoAssemblyLoadContext *alc) mono_loader_lock (); // There might be several threads that passed the first check - // Adding another check to ensure single load of a container assembly due to race condition + // Adding another check to ensure single load of a container assembly due to race condition if (!container_amodule) { ERROR_DECL (error); @@ -4438,7 +4459,7 @@ load_method (MonoAotModule *amodule, MonoImage *image, MonoMethod *method, guint mono_atomic_inc_i32 (&mono_jit_stats.methods_aot); if (method && method->wrapper_type) - g_hash_table_insert (amodule->method_to_code, method, code); + dn_simdhash_ptr_ptr_try_add (amodule->method_to_code, method, code); /* Commit changes since methods_loaded is accessed outside the lock */ mono_memory_barrier (); @@ -4507,7 +4528,7 @@ find_aot_method_in_amodule (MonoAotModule *code_amodule, MonoMethod *method, gui index = 0xffffff; while (TRUE) { - MonoMethod *m; + MonoMethod *m = NULL; guint8 *p, *orig_p; key = decode_uint_with_len (key_len, entry); @@ -4522,8 +4543,9 @@ find_aot_method_in_amodule (MonoAotModule *code_amodule, MonoMethod *method, gui amodule_lock (metadata_amodule); if (!metadata_amodule->method_ref_to_method) - metadata_amodule->method_ref_to_method = g_hash_table_new (NULL, NULL); - m = (MonoMethod *)g_hash_table_lookup (metadata_amodule->method_ref_to_method, p); + // FIXME: Select a better initial capacity. + metadata_amodule->method_ref_to_method = dn_simdhash_ptr_ptr_new (4096, NULL); + dn_simdhash_ptr_ptr_try_get_value (metadata_amodule->method_ref_to_method, p, (void **)&m); amodule_unlock (metadata_amodule); if (!m) { m = decode_resolve_method_ref_with_target (code_amodule, method, p, &p, error); @@ -4534,7 +4556,7 @@ find_aot_method_in_amodule (MonoAotModule *code_amodule, MonoMethod *method, gui */ if (m && m->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE) { amodule_lock (metadata_amodule); - g_hash_table_insert (metadata_amodule->method_ref_to_method, orig_p, m); + dn_simdhash_ptr_ptr_try_add (metadata_amodule->method_ref_to_method, orig_p, m); amodule_unlock (metadata_amodule); } } @@ -4601,6 +4623,10 @@ mono_aot_can_dedup (MonoMethod *method) info->subtype == WRAPPER_SUBTYPE_INTERP_LMF || info->subtype == WRAPPER_SUBTYPE_AOT_INIT) return FALSE; + + // TODO: see if we can share these + if (info->subtype == WRAPPER_SUBTYPE_UNSAFE_ACCESSOR) + return FALSE; #if 0 // See is_linkonce_method () in mini-llvm.c if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG || info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG) @@ -4895,7 +4921,7 @@ mono_aot_get_method (MonoMethod *method, MonoError *error) MonoMethod *orig_method = method; guint32 method_index; MonoAotModule *amodule = m_class_get_image (klass)->aot_module; - guint8 *code; + guint8 *code = NULL; gboolean cache_result = FALSE; ERROR_DECL (inner_error); @@ -4923,6 +4949,7 @@ mono_aot_get_method (MonoMethod *method, MonoError *error) gboolean dedupable = mono_aot_can_dedup (method); + // TODO: unsafe accessor methods should come here too? if (method->is_inflated && !method->wrapper_type && mono_method_is_generic_sharable_full (method, TRUE, FALSE, FALSE) && !dedupable) { MonoMethod *generic_orig_method = method; /* @@ -4944,7 +4971,7 @@ mono_aot_get_method (MonoMethod *method, MonoError *error) if (method_index == 0xffffff && (method->is_inflated || !method->token)) { /* This hash table is used to avoid the slower search in the extra_method_table in the AOT image */ amodule_lock (amodule); - code = (guint8 *)g_hash_table_lookup (amodule->method_to_code, method); + dn_simdhash_ptr_ptr_try_get_value (amodule->method_to_code, method, (void **)&code); amodule_unlock (amodule); if (code) return code; @@ -5043,6 +5070,19 @@ mono_aot_get_method (MonoMethod *method, MonoError *error) method_index = find_aot_method (shared, &amodule); if (method_index != 0xffffff) method = shared; + if (method_index == 0xffffff && !mono_method_metadata_has_header (method)) { + // replace lookups for unsafe accessor instances by lookups of the wrapper + MonoMethod *wrapper = mini_replace_generated_method (method, error); + mono_error_assert_ok (error); + if (wrapper != NULL) { + shared = mini_get_shared_method_full (wrapper, SHARE_MODE_NONE, error); + return_val_if_nok (error, NULL); + + method_index = find_aot_method (shared, &amodule); + if (method_index != 0xffffff) + method = shared; + } + } } if (method_index == 0xffffff && method->is_inflated && mono_method_is_generic_sharable_full (method, FALSE, FALSE, TRUE)) { @@ -5050,17 +5090,43 @@ mono_aot_get_method (MonoMethod *method, MonoError *error) /* gsharedvt */ /* Use the all-vt shared method since this is what was AOTed */ shared = mini_get_shared_method_full (method, SHARE_MODE_GSHAREDVT, error); + if (shared && !mono_method_metadata_has_header (shared)) { + MonoMethod *wrapper = mini_replace_generated_method (shared, error); + mono_error_assert_ok (error); + if (wrapper != NULL) { + shared = mini_get_shared_method_full (wrapper, SHARE_MODE_GSHAREDVT, error); + return_val_if_nok (error, NULL); + + if (shared) { + method = wrapper; + } + } + } + if (!shared) return NULL; method_index = find_aot_method (shared, &amodule); if (method_index != 0xffffff) { + // XXX AK: I don't understand why we call mini_get_shared_method_full twice + // in the gshared case, above, we just say method = shared, which seems right. method = mini_get_shared_method_full (method, SHARE_MODE_GSHAREDVT, error); if (!method) return NULL; } } + if (method_index == 0xffffff && !mono_method_metadata_has_header (method)) { + // replace lookups for unsafe accessor instances by lookups of the wrapper + MonoMethod *wrapper = mini_replace_generated_method (method, error); + mono_error_assert_ok (error); + if (wrapper != NULL) { + method_index = find_aot_method (wrapper, &amodule); + if (method_index != 0xffffff) + method = wrapper; + } + } + if (method_index == 0xffffff) { if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) { char *full_name; @@ -5096,7 +5162,7 @@ mono_aot_get_method (MonoMethod *method, MonoError *error) return NULL; if (code && cache_result) { amodule_lock (amodule); - g_hash_table_insert (amodule->method_to_code, orig_method, code); + dn_simdhash_ptr_ptr_try_add (amodule->method_to_code, orig_method, code); amodule_unlock (amodule); } return code; diff --git a/src/mono/mono/mini/aot-runtime.h b/src/mono/mono/mini/aot-runtime.h index bd6665935362..e4f84523c45e 100644 --- a/src/mono/mono/mini/aot-runtime.h +++ b/src/mono/mono/mini/aot-runtime.h @@ -11,7 +11,7 @@ #include "mini.h" /* Version number of the AOT file format */ -#define MONO_AOT_FILE_VERSION 185 +#define MONO_AOT_FILE_VERSION 186 #define MONO_AOT_TRAMP_PAGE_SIZE 16384 diff --git a/src/mono/mono/mini/driver.c b/src/mono/mono/mini/driver.c index 56e20eeb5eb0..fb57efb48976 100644 --- a/src/mono/mono/mini/driver.c +++ b/src/mono/mono/mini/driver.c @@ -1597,21 +1597,15 @@ mini_usage (void) " --help-devel Shows more options available to developers\n" "\n" "Runtime:\n" - " --config FILE Loads FILE as the Mono config\n" " --verbose, -v Increases the verbosity level\n" " --help, -h Show usage information\n" " --version, -V Show version information\n" " --version=number Show version number\n" - " --runtime=VERSION Use the VERSION runtime, instead of autodetecting\n" " --optimize=OPT Turns on or off a specific optimization\n" " Use --list-opt to get a list of optimizations\n" " --attach=OPTIONS Pass OPTIONS to the attach agent in the runtime.\n" " Currently the only supported option is 'disable'.\n" " --llvm, --nollvm Controls whenever the runtime uses LLVM to compile code.\n" - " --gc=[sgen,boehm] Select SGen or Boehm GC (runs mono or mono-sgen)\n" -#ifdef TARGET_OSX - " --arch=[32,64] Select architecture (runs mono32 or mono64)\n" -#endif " --handlers Install custom handlers, use --help-handlers for details.\n" " --aot-path=PATH List of additional directories to search for AOT images.\n" " --path=DIR Add DIR to the list of directories to search for assemblies.\n" @@ -1878,34 +1872,6 @@ mono_set_use_smp (int use_smp) #endif } -static void -switch_gc (char* argv[], const char* target_gc) -{ - GString *path; - - if (!strcmp (mono_gc_get_gc_name (), target_gc)) { - return; - } - - path = g_string_new (argv [0]); - - /*Running mono without any argument*/ - if (strstr (argv [0], "-sgen")) - g_string_truncate (path, path->len - 5); - else if (strstr (argv [0], "-boehm")) - g_string_truncate (path, path->len - 6); - - g_string_append_c (path, '-'); - g_string_append (path, target_gc); - -#ifdef HAVE_EXECVP - execvp (path->str, argv); - fprintf (stderr, "Error: Failed to switch to %s gc. mono-%s is not installed.\n", target_gc, target_gc); -#else - fprintf (stderr, "Error: --gc= option not supported on this platform.\n"); -#endif -} - static void increase_descriptor_limit (void) { @@ -1927,37 +1893,6 @@ increase_descriptor_limit (void) #endif } -#ifdef TARGET_OSX - -static void -switch_arch (char* argv[], const char* target_arch) -{ - GString *path; - gsize arch_offset; - - if ((strcmp (target_arch, "32") == 0 && strcmp (MONO_ARCHITECTURE, "x86") == 0) || - (strcmp (target_arch, "64") == 0 && strcmp (MONO_ARCHITECTURE, "amd64") == 0)) { - return; /* matching arch loaded */ - } - - path = g_string_new (argv [0]); - arch_offset = path->len -2; /* last two characters */ - - /* Remove arch suffix if present */ - if (strstr (&path->str[arch_offset], "32") || strstr (&path->str[arch_offset], "64")) { - g_string_truncate (path, arch_offset); - } - - g_string_append (path, target_arch); - - if (execvp (path->str, argv) < 0) { - fprintf (stderr, "Error: --arch=%s Failed to switch to '%s'.\n", target_arch, path->str); - exit (1); - } -} - -#endif - #define MONO_HANDLERS_ARGUMENT "--handlers=" #define MONO_HANDLERS_ARGUMENT_LEN STRING_LENGTH(MONO_HANDLERS_ARGUMENT) @@ -2174,28 +2109,19 @@ mono_main (int argc, char* argv[]) guint32 bisect_opt = parse_optimizations (0, bisect_opt_string, FALSE); g_free (bisect_opt_string); mono_set_bisect_methods (bisect_opt, sep + 1); - } else if (strcmp (argv [i], "--gc=sgen") == 0) { - switch_gc (argv, "sgen"); - } else if (strcmp (argv [i], "--gc=boehm") == 0) { - switch_gc (argv, "boehm"); + } else if (strncmp (argv [i], "--gc=", 5) == 0) { + // ignore } else if (strncmp (argv[i], "--gc-params=", 12) == 0) { mono_gc_params_set (argv[i] + 12); } else if (strncmp (argv[i], "--gc-debug=", 11) == 0) { mono_gc_debug_set (argv[i] + 11); } -#ifdef TARGET_OSX - else if (strcmp (argv [i], "--arch=32") == 0) { - switch_arch (argv, "32"); - } else if (strcmp (argv [i], "--arch=64") == 0) { - switch_arch (argv, "64"); + else if (strncmp (argv [i], "--arch=", 7) == 0) { + // ignore } -#endif else if (strcmp (argv [i], "--config") == 0) { - if (i +1 >= argc){ - fprintf (stderr, "error: --config requires a filename argument\n"); - return 1; - } ++i; + // ignore #ifndef DISABLE_JIT } else if (strcmp (argv [i], "--ncompile") == 0) { if (i + 1 >= argc){ diff --git a/src/mono/mono/mini/helpers.c b/src/mono/mono/mini/helpers.c index 9d903fdbc24a..e3860045d244 100644 --- a/src/mono/mono/mini/helpers.c +++ b/src/mono/mono/mini/helpers.c @@ -76,20 +76,17 @@ static const gint16 opidx [] = { #endif //#define ARCH_PREFIX "powerpc64-linux-gnu-" +#ifndef DISABLE_LOGGING const char* mono_inst_name (int op) { -#ifndef DISABLE_LOGGING if (op >= OP_LOAD && op <= OP_LAST) return (const char*)&opstr + opidx [op - OP_LOAD]; if (op < OP_LOAD) return mono_opcode_name (op); g_error ("unknown opcode name for %d", op); return NULL; -#else - g_error ("unknown opcode name for %d", op); - g_assert_not_reached (); -#endif } +#endif void mono_blockset_print (MonoCompile *cfg, MonoBitSet *set, const char *name, guint idom) diff --git a/src/mono/mono/mini/interp/interp-internals.h b/src/mono/mono/mini/interp/interp-internals.h index a815f39f9c8e..5fe04bf314c8 100644 --- a/src/mono/mono/mini/interp/interp-internals.h +++ b/src/mono/mono/mini/interp/interp-internals.h @@ -154,6 +154,8 @@ struct InterpMethod { unsigned int hasthis; // boolean MonoProfilerCallInstrumentationFlags prof_flags; InterpMethodCodeType code_type; + int ref_slot_offset; // GC visible pointer slot + int swift_error_offset; // swift error struct MonoBitSet *ref_slots; #ifdef ENABLE_EXPERIMENT_TIERED MiniTieredCounter tiered_counter; diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index f8e2ad02ad95..08023c81a489 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -266,8 +266,6 @@ static gboolean debugger_enabled = FALSE; static MonoException* do_transform_method (InterpMethod *imethod, InterpFrame *method, ThreadContext *context); -static InterpMethod* lookup_method_pointer (gpointer addr); - typedef void (*ICallMethod) (InterpFrame *frame); static MonoNativeTlsKey thread_context_id; @@ -2826,10 +2824,13 @@ do_jit_call (ThreadContext *context, stackval *ret_sp, stackval *sp, InterpFrame } JitCallCbData cb_data; - memset (&cb_data, 0, sizeof (cb_data)); cb_data.pindex = pindex; cb_data.args = args; + cb_data.ftndesc.interp_method = NULL; + cb_data.ftndesc.method = NULL; if (cinfo->no_wrapper) { + cb_data.ftndesc.addr = NULL; + cb_data.ftndesc.arg = NULL; cb_data.jit_wrapper = cinfo->addr; cb_data.extra_arg = cinfo->extra_arg; } else { @@ -3175,6 +3176,21 @@ interp_entry_from_trampoline (gpointer ccontext_untyped, gpointer rmethod_untype /* Copy the args saved in the trampoline to the frame stack */ gpointer retp = mono_arch_get_native_call_context_args (ccontext, &frame, sig, call_info); +#ifdef MONO_ARCH_HAVE_SWIFTCALL + int swift_error_arg_index = -1; + gpointer swift_error_data; + gpointer* swift_error_pointer; + if (mono_method_signature_has_ext_callconv (sig, MONO_EXT_CALLCONV_SWIFTCALL)) { + swift_error_data = mono_arch_get_swift_error (ccontext, sig, &swift_error_arg_index); + + int swift_error_offset = frame.imethod->swift_error_offset; + if (swift_error_offset >= 0) { + swift_error_pointer = (gpointer*)((guchar*)frame.stack + swift_error_offset); + *swift_error_pointer = *(gpointer*)swift_error_data; + } + } +#endif + /* Allocate storage for value types */ stackval *newsp = sp; /* FIXME we should reuse computation on imethod for this */ @@ -3194,6 +3210,10 @@ interp_entry_from_trampoline (gpointer ccontext_untyped, gpointer rmethod_untype } else { size = MINT_STACK_SLOT_SIZE; } +#ifdef MONO_ARCH_HAVE_SWIFTCALL + if (swift_error_arg_index >= 0 && swift_error_arg_index == i) + newsp->data.p = swift_error_pointer; +#endif newsp = STACK_ADD_BYTES (newsp, size); } newsp = (stackval*)ALIGN_TO (newsp, MINT_STACK_ALIGNMENT); @@ -3204,6 +3224,11 @@ interp_entry_from_trampoline (gpointer ccontext_untyped, gpointer rmethod_untype mono_interp_exec_method (&frame, context, NULL); MONO_EXIT_GC_UNSAFE; +#ifdef MONO_ARCH_HAVE_SWIFTCALL + if (swift_error_arg_index >= 0) + *(gpointer*)swift_error_data = *(gpointer*)swift_error_pointer; +#endif + context->stack_pointer = (guchar*)sp; g_assert (!context->has_resume_state); @@ -3262,20 +3287,6 @@ interp_compile_interp_method (MonoMethod *method, MonoError *error) return imethod->jinfo; } -static InterpMethod* -lookup_method_pointer (gpointer addr) -{ - InterpMethod *res = NULL; - MonoJitMemoryManager *jit_mm = get_default_jit_mm (); - - jit_mm_lock (jit_mm); - if (jit_mm->interp_method_pointer_hash) - res = (InterpMethod*)g_hash_table_lookup (jit_mm->interp_method_pointer_hash, addr); - jit_mm_unlock (jit_mm); - - return res; -} - #ifndef MONO_ARCH_HAVE_INTERP_NATIVE_TO_MANAGED static void interp_no_native_to_managed (void) @@ -3357,13 +3368,11 @@ interp_create_method_pointer_llvmonly (MonoMethod *method, gboolean unbox, MonoE ) { jiterp_preserve_module(); - const char *name = mono_method_full_name (method, FALSE); gpointer wasm_entry_func = mono_interp_jit_wasm_entry_trampoline ( imethod, method, sig->param_count, (MonoType *)sig->params, unbox, sig->hasthis, sig->ret->type != MONO_TYPE_VOID, - name, entry_func + entry_func ); - g_free((void *)name); // Compiling a trampoline can fail for various reasons, so in that case we will fall back to the pre-existing ones below if (wasm_entry_func) @@ -3380,13 +3389,6 @@ interp_create_method_pointer_llvmonly (MonoMethod *method, gboolean unbox, MonoE addr = mini_llvmonly_create_ftndesc (method, entry_wrapper, entry_ftndesc); - MonoJitMemoryManager *jit_mm = jit_mm_for_method (method); - jit_mm_lock (jit_mm); - if (!jit_mm->interp_method_pointer_hash) - jit_mm->interp_method_pointer_hash = g_hash_table_new (NULL, NULL); - g_hash_table_insert (jit_mm->interp_method_pointer_hash, addr, imethod); - jit_mm_unlock (jit_mm); - mono_memory_barrier (); if (unbox) imethod->llvmonly_unbox_entry = addr; @@ -3489,9 +3491,16 @@ interp_create_method_pointer (MonoMethod *method, gboolean compile, MonoError *e * separate temp register. We should update the wrappers for this * if we really care about those architectures (arm). */ - MonoMethod *wrapper = mini_get_interp_in_wrapper (sig); - entry_wrapper = mono_jit_compile_method_jit_only (wrapper, error); + MonoMethod *wrapper = NULL; +#ifdef MONO_ARCH_HAVE_SWIFTCALL + /* Methods with Swift cconv should go to trampoline */ + if (!mono_method_signature_has_ext_callconv (sig, MONO_EXT_CALLCONV_SWIFTCALL)) +#endif + { + wrapper = mini_get_interp_in_wrapper (sig); + entry_wrapper = mono_jit_compile_method_jit_only (wrapper, error); + } #endif if (!entry_wrapper) { #ifndef MONO_ARCH_HAVE_INTERP_ENTRY_TRAMPOLINE @@ -3538,13 +3547,6 @@ interp_create_method_pointer (MonoMethod *method, gboolean compile, MonoError *e addr = mono_create_ftnptr_arg_trampoline (ftndesc, entry_wrapper); - MonoJitMemoryManager *jit_mm = get_default_jit_mm (); - jit_mm_lock (jit_mm); - if (!jit_mm->interp_method_pointer_hash) - jit_mm->interp_method_pointer_hash = g_hash_table_new (NULL, NULL); - g_hash_table_insert (jit_mm->interp_method_pointer_hash, addr, imethod); - jit_mm_unlock (jit_mm); - mono_memory_barrier (); imethod->jit_entry = addr; @@ -3555,23 +3557,16 @@ static void interp_free_method (MonoMethod *method) { MonoJitMemoryManager *jit_mm = jit_mm_for_method (method); - InterpMethod *imethod; MonoDynamicMethod *dmethod = (MonoDynamicMethod*)method; jit_mm_lock (jit_mm); - imethod = (InterpMethod*)mono_internal_hash_table_lookup (&jit_mm->interp_code_hash, method); #if HOST_BROWSER + InterpMethod *imethod = (InterpMethod*)mono_internal_hash_table_lookup (&jit_mm->interp_code_hash, method); mono_jiterp_free_method_data (method, imethod); #endif mono_internal_hash_table_remove (&jit_mm->interp_code_hash, method); - if (imethod && jit_mm->interp_method_pointer_hash) { - if (imethod->jit_entry) - g_hash_table_remove (jit_mm->interp_method_pointer_hash, imethod->jit_entry); - if (imethod->llvmonly_unbox_entry) - g_hash_table_remove (jit_mm->interp_method_pointer_hash, imethod->llvmonly_unbox_entry); - } jit_mm_unlock (jit_mm); if (dmethod->mp) { @@ -4135,6 +4130,8 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause // Not created from interpreted code g_assert (del->method); del_imethod = mono_interp_get_imethod (del->method); + if (del->target && m_method_is_virtual (del->method)) + del_imethod = get_virtual_method (del_imethod, del->target->vtable); del->interp_method = del_imethod; del->interp_invoke_impl = del_imethod; } else { @@ -4164,6 +4161,9 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause } cmethod = del_imethod; if (!is_multicast) { + int ref_slot_offset = frame->imethod->ref_slot_offset; + if (ref_slot_offset >= 0) + LOCAL_VAR (ref_slot_offset, gpointer) = del; int param_count = ip [4]; if (cmethod->param_count == param_count + 1) { // Target method is static but the delegate has a target object. We handle diff --git a/src/mono/mono/mini/interp/jiterpreter.c b/src/mono/mono/mini/interp/jiterpreter.c index 12678e10e828..43b71e70cd3d 100644 --- a/src/mono/mono/mini/interp/jiterpreter.c +++ b/src/mono/mono/mini/interp/jiterpreter.c @@ -1021,8 +1021,28 @@ mono_jiterp_get_options_as_json () return mono_options_get_as_json (); } +EMSCRIPTEN_KEEPALIVE gint32 +mono_jiterp_get_option_as_int (const char *name) +{ + MonoOptionType type; + void *value_address; + + if (!mono_options_get (name, &type, &value_address)) + return INT32_MIN; + + switch (type) { + case MONO_OPTION_BOOL: + case MONO_OPTION_BOOL_READONLY: + return (*(guint8 *)value_address) != 0; + case MONO_OPTION_INT: + return *(gint32 *)value_address; + default: + return INT32_MIN; + } +} + EMSCRIPTEN_KEEPALIVE int -mono_jiterp_object_has_component_size (MonoObject ** ppObj) +mono_jiterp_object_has_component_size (MonoObject **ppObj) { MonoObject *obj = *ppObj; if (!obj) diff --git a/src/mono/mono/mini/interp/jiterpreter.h b/src/mono/mono/mini/interp/jiterpreter.h index ed57b0a0e17b..e9b3c67cb293 100644 --- a/src/mono/mono/mini/interp/jiterpreter.h +++ b/src/mono/mono/mini/interp/jiterpreter.h @@ -120,7 +120,7 @@ mono_interp_record_interp_entry (void *fn_ptr); extern gpointer mono_interp_jit_wasm_entry_trampoline ( void *imethod, MonoMethod *method, int argument_count, MonoType *param_types, - int unbox, int has_this, int has_return, const char *name, void *default_implementation + int unbox, int has_this, int has_return, void *default_implementation ); // Fast-path implemented in C diff --git a/src/mono/mono/mini/interp/tiering.c b/src/mono/mono/mini/interp/tiering.c index f22f8b7ea1f5..f35c83bc17d0 100644 --- a/src/mono/mono/mini/interp/tiering.c +++ b/src/mono/mono/mini/interp/tiering.c @@ -64,7 +64,7 @@ patch_interp_data_items (InterpMethod *old_imethod, InterpMethod *new_imethod) GSList *sites = g_hash_table_lookup (patch_sites_table, old_imethod); g_slist_foreach (sites, patch_imethod_site, new_imethod); - g_hash_table_remove (patch_sites_table, sites); + g_hash_table_remove (patch_sites_table, old_imethod); g_slist_free (sites); } diff --git a/src/mono/mono/mini/interp/transform-opt.c b/src/mono/mono/mini/interp/transform-opt.c index 4ee96b7a541d..7b606d60c262 100644 --- a/src/mono/mono/mini/interp/transform-opt.c +++ b/src/mono/mono/mini/interp/transform-opt.c @@ -2241,6 +2241,7 @@ interp_fold_unop (TransformData *td, InterpInst *ins) td->var_values [sreg].ref_count--; result.def = ins; result.ref_count = td->var_values [dreg].ref_count; // preserve ref count + result.liveness = td->var_values [dreg].liveness; td->var_values [dreg] = result; return ins; @@ -2478,6 +2479,7 @@ interp_fold_binop (TransformData *td, InterpInst *ins, gboolean *folded) td->var_values [sreg2].ref_count--; result.def = ins; result.ref_count = td->var_values [dreg].ref_count; // preserve ref count + result.liveness = td->var_values [dreg].liveness; td->var_values [dreg] = result; return ins; diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 70773797a47f..88f386802cc2 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -419,11 +419,12 @@ interp_create_var_explicit (TransformData *td, MonoType *type, int size) if (td->vars_size == td->vars_capacity) { td->vars_capacity *= 2; if (td->vars_capacity == 0) - td->vars_capacity = 2; + td->vars_capacity = 16; td->vars = (InterpVar*) g_realloc (td->vars, td->vars_capacity * sizeof (InterpVar)); } int mt = mono_mint_type (type); InterpVar *local = &td->vars [td->vars_size]; + // FIXME: We don't need to do this memset unless we realloc'd, since we malloc0 vars initially memset (local, 0, sizeof (InterpVar)); local->type = type; @@ -451,6 +452,15 @@ interp_create_dummy_var (TransformData *td) td->vars [td->dummy_var].global = TRUE; } +static void +interp_create_ref_handle_var (TransformData *td) +{ + int var = interp_create_var_explicit (td, m_class_get_byval_arg (mono_defaults.int_class), sizeof (gpointer)); + td->vars [var].global = TRUE; + interp_alloc_global_var_offset (td, var); + td->ref_handle_var = var; +} + static int get_tos_offset (TransformData *td) { @@ -2897,6 +2907,9 @@ interp_method_check_inlining (TransformData *td, MonoMethod *method, MonoMethodS if (g_list_find (td->dont_inline, method)) return FALSE; + if (m_class_is_exception_class (method->klass) && !strcmp (method->name, ".ctor")) + return FALSE; + return TRUE; } @@ -3307,6 +3320,95 @@ interp_try_devirt (MonoClass *this_klass, MonoMethod *target_method) return NULL; } +static MonoMethodSignature* +interp_emit_swiftcall_struct_lowering (TransformData *td, MonoMethodSignature *csignature) +{ + // P/Invoke calls shouldn't contain 'this' + g_assert (!csignature->hasthis); + + /* + * Argument reordering here doesn't handle on the fly offset allocation + * and requires the full var offset allocator pass that is only ran for optimized code + */ + g_assert (td->optimized); + + MonoMethodSignature *new_csignature; + // Save the function pointer + StackInfo sp_fp = td->sp [-1]; + --td->sp; + + // Save the old arguments + td->sp -= csignature->param_count; + StackInfo *sp_old_params = (StackInfo*) mono_mempool_alloc (td->mempool, sizeof (StackInfo) * csignature->param_count); + for (int i = 0; i < csignature->param_count; ++i) + sp_old_params [i] = td->sp [i]; + + GArray *new_params = g_array_sized_new (FALSE, FALSE, sizeof (MonoType*), csignature->param_count); + uint32_t new_param_count = 0; + int align; + MonoClass *swift_self = mono_class_try_get_swift_self_class (); + MonoClass *swift_error = mono_class_try_get_swift_error_class (); + /* + * Go through the lowered arguments, if the argument is a struct, + * we need to replace it with a sequence of lowered arguments. + * Also record the updated parameters for the new signature. + */ + for (int idx_param = 0; idx_param < csignature->param_count; ++idx_param) { + MonoType *ptype = csignature->params [idx_param]; + MonoClass *klass = mono_class_from_mono_type_internal (ptype); + // SwiftSelf and SwiftError are special cases where we need to preserve the class information for the codegen to handle them correctly. + if (mono_type_is_struct (ptype) && !(klass == swift_self || klass == swift_error)) { + SwiftPhysicalLowering lowered_swift_struct = mono_marshal_get_swift_physical_lowering (ptype, FALSE); + if (!lowered_swift_struct.by_reference) { + for (uint32_t idx_lowered = 0; idx_lowered < lowered_swift_struct.num_lowered_elements; ++idx_lowered) { + int mt_lowered = mono_mint_type (lowered_swift_struct.lowered_elements [idx_lowered]); + int lowered_elem_size = mono_type_size (lowered_swift_struct.lowered_elements [idx_lowered], &align); + // Load the lowered elements of the struct + interp_add_ins (td, MINT_MOV_SRC_OFF); + interp_ins_set_sreg (td->last_ins, sp_old_params [idx_param].var); + td->last_ins->data [0] = (guint16) lowered_swift_struct.offsets [idx_lowered]; + td->last_ins->data [1] = GINT_TO_UINT16 (mt_lowered); + td->last_ins->data [2] = GINT_TO_UINT16 (lowered_elem_size); + push_mono_type (td, lowered_swift_struct.lowered_elements [idx_lowered], mt_lowered, mono_class_from_mono_type_internal (lowered_swift_struct.lowered_elements [idx_lowered])); + interp_ins_set_dreg (td->last_ins, td->sp [-1].var); + + ++new_param_count; + g_array_append_val (new_params, lowered_swift_struct.lowered_elements [idx_lowered]); + } + } else { + // For structs that cannot be lowered, we change the argument to byref type + ptype = mono_class_get_byref_type (mono_defaults.typed_reference_class); + // Load the address of the struct + interp_add_ins (td, MINT_LDLOCA_S); + interp_ins_set_sreg (td->last_ins, sp_old_params [idx_param].var); + push_simple_type (td, STACK_TYPE_I); + interp_ins_set_dreg (td->last_ins, td->sp [-1].var); + + ++new_param_count; + g_array_append_val (new_params, ptype); + } + } else { + // Copy over non-struct arguments + memcpy (td->sp, &sp_old_params [idx_param], sizeof (StackInfo)); + ++td->sp; + + ++new_param_count; + g_array_append_val (new_params, ptype); + } + } + // Restore the function pointer + memcpy (td->sp, &sp_fp, sizeof (StackInfo)); + ++td->sp; + + // Create a new dummy signature with the lowered arguments + new_csignature = mono_metadata_signature_dup_new_params (td->mempool, csignature, new_param_count, (MonoType**)new_params->data); + + // Deallocate temp array + g_array_free (new_params, TRUE); + + return new_csignature; +} + /* Return FALSE if error, including inline failure */ static gboolean interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target_method, MonoGenericContext *generic_context, MonoClass *constrained_class, gboolean readonly, MonoError *error, gboolean check_visibility, gboolean save_last_error, gboolean tailcall) @@ -3391,6 +3493,16 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target return FALSE; } +#ifdef MONO_ARCH_HAVE_SWIFTCALL + /* + * We need to modify the signature of the swiftcall calli to account for the lowering of Swift structs. + * This is done by replacing struct arguments on stack with a lowered sequence and updating the signature. + */ + if (csignature->pinvoke && mono_method_signature_has_ext_callconv (csignature, MONO_EXT_CALLCONV_SWIFTCALL)) { + csignature = interp_emit_swiftcall_struct_lowering (td, csignature); + } +#endif + if (check_visibility && target_method && !mono_method_can_access_method (method, target_method)) interp_generate_mae_throw (td, method, target_method); @@ -3756,6 +3868,10 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target td->last_ins->data [0] = get_data_item_index_imethod (td, mono_interp_get_imethod (target_method)); } else { if (is_delegate_invoke) { + // MINT_CALL_DELEGATE will store the delegate object into this slot so it is kept alive + // while the method is invoked + if (td->ref_handle_var == -1) + interp_create_ref_handle_var (td); interp_add_ins (td, MINT_CALL_DELEGATE); interp_ins_set_dreg (td->last_ins, dreg); interp_ins_set_sreg (td->last_ins, MINT_CALL_ARGS_SREG); @@ -4329,17 +4445,27 @@ interp_method_compute_offsets (TransformData *td, InterpMethod *imethod, MonoMet int num_args = sig->hasthis + sig->param_count; int num_il_locals = header->num_locals; int num_locals = num_args + num_il_locals; + // HACK: Pre-reserve extra space to reduce the number of times we realloc during codegen, since it's expensive + // 64 vars * 72 bytes = 4608 bytes. Many methods need less than this + int target_vars_capacity = num_locals + 64; imethod->local_offsets = (guint32*)g_malloc (num_il_locals * sizeof(guint32)); - td->vars = (InterpVar*)g_malloc0 (num_locals * sizeof (InterpVar)); + td->vars = (InterpVar*)g_malloc0 (target_vars_capacity * sizeof (InterpVar)); td->vars_size = num_locals; - td->vars_capacity = td->vars_size; + td->vars_capacity = target_vars_capacity; - td->renamable_vars = (InterpRenamableVar*)g_malloc (num_locals * sizeof (InterpRenamableVar)); + td->renamable_vars = (InterpRenamableVar*)g_malloc (target_vars_capacity * sizeof (InterpRenamableVar)); td->renamable_vars_size = 0; - td->renamable_vars_capacity = num_locals; + td->renamable_vars_capacity = target_vars_capacity; offset = 0; +#ifdef MONO_ARCH_HAVE_SWIFTCALL + int swift_error_index = -1; + imethod->swift_error_offset = -1; + MonoClass *swift_error = mono_class_try_get_swift_error_class (); + MonoClass *swift_error_ptr = mono_class_create_ptr (m_class_get_this_arg (swift_error)); +#endif + /* * We will load arguments as if they are locals. Unlike normal locals, every argument * is stored in a stackval sized slot and valuetypes have special semantics since we @@ -4364,6 +4490,15 @@ interp_method_compute_offsets (TransformData *td, InterpMethod *imethod, MonoMet td->vars [i].offset = offset; interp_mark_ref_slots_for_var (td, i); offset += size; + +#ifdef MONO_ARCH_HAVE_SWIFTCALL + if (swift_error_index < 0 && mono_method_signature_has_ext_callconv (sig, MONO_EXT_CALLCONV_SWIFTCALL)) { + MonoClass *klass = mono_class_from_mono_type_internal (type); + if (klass == swift_error_ptr) + swift_error_index = i; + } +#endif + } offset = ALIGN_TO (offset, MINT_STACK_ALIGNMENT); @@ -4397,6 +4532,16 @@ interp_method_compute_offsets (TransformData *td, InterpMethod *imethod, MonoMet td->il_locals_size = offset - td->il_locals_offset; td->total_locals_size = offset; +#ifdef MONO_ARCH_HAVE_SWIFTCALL + if (mono_method_signature_has_ext_callconv (sig, MONO_EXT_CALLCONV_SWIFTCALL) && swift_error_index >= 0) { + MonoType* type = mono_method_signature_internal (td->method)->params [swift_error_index - sig->hasthis]; + int var = interp_create_var_explicit (td, type, sizeof(gpointer)); + td->vars [var].global = TRUE; + interp_alloc_global_var_offset (td, var); + imethod->swift_error_offset = td->vars [var].offset; + } +#endif + imethod->clause_data_offsets = (guint32*)g_malloc (header->num_clauses * sizeof (guint32)); td->clause_vars = (int*)mono_mempool_alloc (td->mempool, sizeof (int) * header->num_clauses); for (guint i = 0; i < header->num_clauses; i++) { @@ -4624,6 +4769,18 @@ interp_emit_sfld_access (TransformData *td, MonoClassField *field, MonoClass *fi } interp_ins_set_dreg (td->last_ins, td->sp [-1].var); } else { + // Fields from hotreload update and fields from collectible assemblies are not + // stored inside fixed gc roots but rather in other objects. This means that + // storing into these fields requires write barriers. + if ((mt == MINT_TYPE_VT || mt == MINT_TYPE_O) && + (m_field_is_from_update (field) || + mono_image_get_alc (m_class_get_image (m_field_get_parent (field)))->collectible)) { + interp_emit_ldsflda (td, field, error); + return_if_nok (error); + interp_emit_stobj (td, field_class, TRUE); + return; + } + if (G_LIKELY (!wide_data)) interp_add_ins (td, (mt == MINT_TYPE_VT) ? MINT_STSFLD_VT : (MINT_STSFLD_I1 + mt - MINT_TYPE_I1)); else @@ -8540,7 +8697,7 @@ interp_mark_ref_slots_for_vt (TransformData *td, int base_offset, MonoClass *kla retry: if (mini_type_is_reference (ftype) || ftype->type == MONO_TYPE_I || ftype->type == MONO_TYPE_U || m_type_is_byref (ftype)) { int index = offset / sizeof (gpointer); - mono_bitset_set_fast (td->ref_slots, index); + mono_bitset_set (td->ref_slots, index); if (td->verbose_level) g_print ("Stack ref slot vt field at off %d\n", offset); } else if (ftype->type == MONO_TYPE_VALUETYPE || ftype->type == MONO_TYPE_GENERICINST) { @@ -8572,6 +8729,8 @@ interp_mark_ref_slots_for_var (TransformData *td, int var) if (!td->ref_slots || max_index >= td->ref_slots->size) { guint32 old_size = td->ref_slots ? (guint32)td->ref_slots->size : 0; guint32 new_size = old_size ? old_size * 2 : 32; + while (new_size <= max_index) + new_size *= 2; gpointer mem = mono_mempool_alloc0 (td->mempool, mono_bitset_alloc_size (new_size, 0)); MonoBitSet *new_ref_slots = mono_bitset_mem_new (mem, new_size, 0); @@ -8589,7 +8748,7 @@ interp_mark_ref_slots_for_var (TransformData *td, int var) // Managed pointers in interp are normally MONO_TYPE_I if (mini_type_is_reference (type) || type->type == MONO_TYPE_I || type->type == MONO_TYPE_U || m_type_is_byref (type)) { int index = td->vars [var].offset / sizeof (gpointer); - mono_bitset_set_fast (td->ref_slots, index); + mono_bitset_set (td->ref_slots, index); if (td->verbose_level) g_print ("Stack ref slot at off %d for var %d\n", index * sizeof (gpointer), var); } @@ -9085,6 +9244,7 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, MonoG td->n_data_items = 0; td->max_data_items = 0; td->dummy_var = -1; + td->ref_handle_var = -1; td->data_items = NULL; td->data_hash = g_hash_table_new (NULL, NULL); #ifdef ENABLE_EXPERIMENT_TIERED @@ -9260,6 +9420,11 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, MonoG } } + if (td->ref_handle_var != -1) + rtm->ref_slot_offset = td->vars [td->ref_handle_var].offset; + else + rtm->ref_slot_offset = -1; + /* Save debug info */ interp_save_debug_info (rtm, header, td, td->line_numbers); @@ -9301,6 +9466,8 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, MonoG g_free (td->data_items); g_free (td->stack); g_free (td->vars); + g_free (td->renamable_vars); + g_free (td->renamed_fixed_vars); g_free (td->local_ref_count); g_hash_table_destroy (td->data_hash); #ifdef ENABLE_EXPERIMENT_TIERED diff --git a/src/mono/mono/mini/interp/transform.h b/src/mono/mono/mini/interp/transform.h index 1e6185f8089c..119ffe9db4b3 100644 --- a/src/mono/mono/mini/interp/transform.h +++ b/src/mono/mono/mini/interp/transform.h @@ -285,6 +285,7 @@ typedef struct gint32 total_locals_size; gint32 max_stack_size; int dummy_var; + int ref_handle_var; int *local_ref_count; unsigned int il_locals_offset; unsigned int il_locals_size; diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index 4835a84e2c91..2c629adf5966 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -283,7 +283,7 @@ llvm_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } } - if (in_corlib && !strcmp (m_class_get_name (cmethod->klass), "Buffer")) { + if (in_corlib && !strcmp (m_class_get_name (cmethod->klass), "SpanHelpers")) { if (!strcmp (cmethod->name, "Memmove") && fsig->param_count == 3 && m_type_is_byref (fsig->params [0]) && m_type_is_byref (fsig->params [1]) && !cmethod->is_inflated) { MonoBasicBlock *end_bb; NEW_BBLOCK (cfg, end_bb); @@ -304,6 +304,41 @@ llvm_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign ins->sreg3 = args [2]->dreg; // i32/i64 len MONO_ADD_INS (cfg->cbb, ins); MONO_START_BB (cfg, end_bb); + } else if (!strcmp (cmethod->name, "ClearWithoutReferences") && fsig->param_count == 2 && m_type_is_byref (fsig->params [0]) && !cmethod->is_inflated) { + MonoBasicBlock *end_bb; + NEW_BBLOCK (cfg, end_bb); + + // do nothing if len == 0 (even if src is null) + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, 0); + MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, end_bb); + + // throw NRE if src is null + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [0]->dreg, 0); + MONO_EMIT_NEW_COND_EXC (cfg, EQ, "NullReferenceException"); + + MONO_INST_NEW (cfg, ins, OP_MEMSET_ZERO); + ins->sreg1 = args [0]->dreg; // i1* dst + ins->sreg2 = args [1]->dreg; // i32/i64 len + MONO_ADD_INS (cfg->cbb, ins); + MONO_START_BB (cfg, end_bb); + } else if (!strcmp (cmethod->name, "Fill") && fsig->param_count == 3 && m_type_is_byref (fsig->params [0]) && !cmethod->is_inflated) { + MonoBasicBlock *end_bb; + NEW_BBLOCK (cfg, end_bb); + + // do nothing if len == 0 (even if src is null) + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, 0); + MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, end_bb); + + // throw NRE if src is null + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [0]->dreg, 0); + MONO_EMIT_NEW_COND_EXC (cfg, EQ, "NullReferenceException"); + + MONO_INST_NEW (cfg, ins, OP_MEMSET); + ins->sreg1 = args [0]->dreg; // i1* dst + ins->sreg2 = args [1]->dreg; // i8 value + ins->sreg3 = args [2]->dreg; // i32/i64 len + MONO_ADD_INS (cfg->cbb, ins); + MONO_START_BB (cfg, end_bb); } } diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index 8d569eae92a3..90a8f3f341e8 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -7514,6 +7514,84 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (cfg->gsharedvt_min && mini_is_gsharedvt_variable_signature (fsig)) GSHAREDVT_FAILURE (il_op); +#ifdef MONO_ARCH_HAVE_SWIFTCALL + /* + * We need to modify the signature of the swiftcall calli to account for the lowering of Swift structs. + * This is done by replacing struct arguments on stack with a lowered sequence and updating the signature. + */ + if (fsig->pinvoke && mono_method_signature_has_ext_callconv (fsig, MONO_EXT_CALLCONV_SWIFTCALL)) { + g_assert (!fsig->hasthis); // Swift P/Invoke calls shouldn't contain 'this' + + n = fsig->param_count; + sp -= n; + // Save the old arguments + MonoInst **old_params = (MonoInst**) mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * n); + for (int idx_param = 0; idx_param < n; ++idx_param) { + old_params [idx_param] = sp [idx_param]; + } + + GArray *new_params = g_array_sized_new (FALSE, FALSE, sizeof (MonoType*), n); + uint32_t new_param_count = 0; + MonoClass *swift_self = mono_class_try_get_swift_self_class (); + MonoClass *swift_error = mono_class_try_get_swift_error_class (); + /* + * Go through the lowered arguments, if the argument is a struct, + * we need to replace it with a sequence of lowered arguments. + * Also record the updated parameters for the new signature. + */ + for (int idx_param = 0; idx_param < n; ++idx_param) { + MonoType *ptype = fsig->params [idx_param]; + MonoClass *klass = mono_class_from_mono_type_internal (ptype); + + // SwiftSelf and SwiftError are special cases where we need to preserve the class information for the codegen to handle them correctly. + if (mono_type_is_struct (ptype) && !(klass == swift_self || klass == swift_error)) { + SwiftPhysicalLowering lowered_swift_struct = mono_marshal_get_swift_physical_lowering (ptype, FALSE); + if (!lowered_swift_struct.by_reference) { + // Create a new local variable to store the base address of the struct + MonoInst *struct_base_address = mono_compile_create_var (cfg, mono_get_int_type (), OP_LOCAL); + CHECK_ARG (idx_param); + NEW_ARGLOADA (cfg, struct_base_address, idx_param); + MONO_ADD_INS (cfg->cbb, struct_base_address); + + for (uint32_t idx_lowered = 0; idx_lowered < lowered_swift_struct.num_lowered_elements; ++idx_lowered) { + MonoInst *lowered_arg = NULL; + // Load the lowered elements of the struct + lowered_arg = mini_emit_memory_load (cfg, lowered_swift_struct.lowered_elements [idx_lowered], struct_base_address, lowered_swift_struct.offsets [idx_lowered], 0); + *sp++ = lowered_arg; + + ++new_param_count; + g_array_append_val (new_params, lowered_swift_struct.lowered_elements [idx_lowered]); + } + } else { + // For structs that cannot be lowered, we change the argument to byref type + ptype = mono_class_get_byref_type (mono_defaults.typed_reference_class); + // Load the address of the struct + MonoInst *struct_base_address = mono_compile_create_var (cfg, mono_get_int_type (), OP_LOCAL); + CHECK_ARG (idx_param); + NEW_ARGLOADA (cfg, struct_base_address, idx_param); + MONO_ADD_INS (cfg->cbb, struct_base_address); + *sp++ = struct_base_address; + + ++new_param_count; + g_array_append_val (new_params, ptype); + } + } else { + // Copy over non-struct arguments + *sp++ = old_params [idx_param]; + + ++new_param_count; + g_array_append_val (new_params, ptype); + } + } + + // Create a new dummy signature with the lowered arguments + fsig = mono_metadata_signature_dup_new_params (cfg->mempool, fsig, new_param_count, (MonoType**)new_params->data); + + // Deallocate temp array + g_array_free (new_params, TRUE); + } +#endif + if (method->dynamic && fsig->pinvoke) { MonoInst *args [3]; @@ -7864,7 +7942,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b UNVERIFIED; if (!cfg->gshared) - g_assert (!mono_method_check_context_used (cmethod)); + g_assertf (!mono_method_check_context_used (cmethod), "cmethod is %s", mono_method_get_full_name (cmethod)); CHECK_STACK (n); @@ -9595,8 +9673,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (klass == mono_defaults.void_class) UNVERIFIED; - if (target_type_is_incompatible (cfg, m_class_get_byval_arg (klass), val)) - UNVERIFIED; + /* frequent check in generic code: box (struct), brtrue */ /* @@ -9955,6 +10032,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MONO_ADD_INS (cfg->cbb, ins); *sp++ = ins; } else { + if (target_type_is_incompatible (cfg, m_class_get_byval_arg (klass), val)) + UNVERIFIED; *sp++ = mini_emit_box (cfg, val, klass, context_used); } CHECK_CFG_EXCEPTION; diff --git a/src/mono/mono/mini/mini-amd64.c b/src/mono/mono/mini/mini-amd64.c index d424577821ba..aeabd56a1ed5 100644 --- a/src/mono/mono/mini/mini-amd64.c +++ b/src/mono/mono/mini/mini-amd64.c @@ -127,7 +127,7 @@ static const char * const single_xmmregs [] = { const char* mono_arch_fregname (int reg) { - if (reg < AMD64_XMM_NREG) + if (reg >= 0 && reg < AMD64_XMM_NREG) return single_xmmregs [reg]; else return "unknown"; @@ -136,7 +136,7 @@ mono_arch_fregname (int reg) const char * mono_arch_xregname (int reg) { - if (reg < AMD64_XMM_NREG) + if (reg >= 0 && reg < AMD64_XMM_NREG) return packed_xmmregs [reg]; else return "unknown"; @@ -1324,7 +1324,7 @@ mono_arch_set_native_call_context_ret (CallContext *ccontext, gpointer frame, Mo storage = alloca (temp_size); else storage = arg_get_storage (ccontext, ainfo); - memset (ccontext, 0, sizeof (CallContext)); // FIXME + interp_cb->frame_arg_to_data ((MonoInterpFrameHandle)frame, sig, -1, storage); if (temp_size) arg_set_val (ccontext, ainfo, storage); @@ -1990,13 +1990,18 @@ mono_arch_allocate_vars (MonoCompile *cfg) } case ArgSwiftError: { ins->opcode = OP_REGOFFSET; - ins->inst_basereg = cfg->frame_reg; - ins->inst_offset = ainfo->offset + ARGS_OFFSET; offset = ALIGN_TO (offset, sizeof (target_mgreg_t)); + ins->inst_basereg = cfg->frame_reg; + ins->inst_offset = offset; offset += sizeof (target_mgreg_t); cfg->arch.swift_error_var = ins; - cfg->used_int_regs |= (size_t)(1 << AMD64_R12); + + /* In the n2m case, the error register functions as an extra return register + * and is thus is not treated as callee-saved. + */ + if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) + cfg->used_int_regs |= (size_t)(1 << AMD64_R12); } break; default: @@ -4280,8 +4285,13 @@ emit_move_return_value (MonoCompile *cfg, MonoInst *ins, guint8 *code) guint32 quad; if (cfg->arch.swift_error_var) { - amd64_mov_reg_membase (code, AMD64_R11, cfg->arch.swift_error_var->inst_basereg, cfg->arch.swift_error_var->inst_offset, sizeof (target_mgreg_t)); - amd64_mov_membase_reg (code, AMD64_R11, 0, AMD64_R12, sizeof (target_mgreg_t)); + if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) { + amd64_mov_reg_membase (code, AMD64_R11, cfg->arch.swift_error_var->inst_basereg, cfg->arch.swift_error_var->inst_offset, sizeof (target_mgreg_t)); + amd64_mov_membase_reg (code, AMD64_R11, 0, AMD64_R12, sizeof (target_mgreg_t)); + } + else if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) { + amd64_mov_reg_membase (code, AMD64_R12, cfg->arch.swift_error_var->inst_basereg, cfg->arch.swift_error_var->inst_offset, sizeof (target_mgreg_t)); + } } /* Move return value to the target register */ @@ -7770,12 +7780,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) amd64_mov_membase_reg (code, ins->sreg1, MONO_STRUCT_OFFSET (MonoContext, gregs) + i * sizeof (target_mgreg_t), i, sizeof (target_mgreg_t)); break; default: - g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__); + g_warning ("unknown opcode " M_PRI_INST " in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__); g_assert_not_reached (); } g_assertf ((code - cfg->native_code - offset) <= max_len, - "wrong maximal instruction length of instruction %s (expected %d, got %d)", + "wrong maximal instruction length of instruction " M_PRI_INST " (expected %d, got %d)", mono_inst_name (ins->opcode), max_len, (int)(code - cfg->native_code - offset)); } @@ -8248,11 +8258,17 @@ MONO_RESTORE_WARNING amd64_mov_membase_reg (code, ins->inst_basereg, ins->inst_offset, ainfo->reg, 8); break; case ArgSwiftError: - if (ainfo->offset) { - amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, ARGS_OFFSET + ainfo->offset, 8); - amd64_mov_membase_reg (code, cfg->arch.swift_error_var->inst_basereg, cfg->arch.swift_error_var->inst_offset, AMD64_R11, sizeof (target_mgreg_t)); - } else { - amd64_mov_membase_reg (code, cfg->arch.swift_error_var->inst_basereg, cfg->arch.swift_error_var->inst_offset, ainfo->reg, sizeof (target_mgreg_t)); + if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) { + if (ainfo->offset) { + amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, ARGS_OFFSET + ainfo->offset, 8); + amd64_mov_membase_reg (code, cfg->arch.swift_error_var->inst_basereg, cfg->arch.swift_error_var->inst_offset, AMD64_R11, sizeof (target_mgreg_t)); + } else { + amd64_mov_membase_reg (code, cfg->arch.swift_error_var->inst_basereg, cfg->arch.swift_error_var->inst_offset, ainfo->reg, sizeof (target_mgreg_t)); + } + } else if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) { + /* Relies on arguments being passed on the stack */ + amd64_lea_membase (code, AMD64_R11, cfg->arch.swift_error_var->inst_basereg, cfg->arch.swift_error_var->inst_offset); + amd64_mov_membase_reg (code, ins->inst_basereg, ins->inst_offset, AMD64_R11, 8); } break; default: diff --git a/src/mono/mono/mini/mini-arm.c b/src/mono/mono/mini/mini-arm.c index a6e6328e814a..9cab61db1cbc 100644 --- a/src/mono/mono/mini/mini-arm.c +++ b/src/mono/mono/mini/mini-arm.c @@ -3439,7 +3439,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) temp->dreg = mono_alloc_ireg (cfg); ins->sreg2 = temp->dreg; if (opcode2 == -1) - g_error ("mono_op_imm_to_op failed for %s\n", mono_inst_name (ins->opcode)); + g_error ("mono_op_imm_to_op failed for " M_PRI_INST "\n", mono_inst_name (ins->opcode)); ins->opcode = GUINT32_TO_OPCODE (opcode2); } if (ins->opcode == OP_SBB || ins->opcode == OP_ISBB || ins->opcode == OP_SUBCC) @@ -3497,7 +3497,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) temp->dreg = mono_alloc_ireg (cfg); ins->sreg2 = temp->dreg; if (opcode2 == -1) - g_error ("mono_op_imm_to_op failed for %s\n", mono_inst_name (ins->opcode)); + g_error ("mono_op_imm_to_op failed for " M_PRI_INST "\n", mono_inst_name (ins->opcode)); ins->opcode = GINT32_TO_UINT16 (opcode2); break; } @@ -5957,12 +5957,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ARM_STR_IMM (code, i, ins->sreg1, MONO_STRUCT_OFFSET (MonoContext, regs) + i * sizeof (target_mgreg_t)); break; default: - g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__); + g_warning ("unknown opcode " M_PRI_INST " in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__); g_assert_not_reached (); } if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) { - g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %d)", + g_warning ("wrong maximal instruction length of instruction " M_PRI_INST " (expected %d, got %d)", mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset); g_assert_not_reached (); } diff --git a/src/mono/mono/mini/mini-arm.h b/src/mono/mono/mini/mini-arm.h index 73bcc8bb8bb4..1d1a6af8b67a 100644 --- a/src/mono/mono/mini/mini-arm.h +++ b/src/mono/mono/mini/mini-arm.h @@ -371,7 +371,7 @@ typedef struct MonoCompileArch { #define MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP 1 #define MONO_ARCH_HAVE_INTERP_NATIVE_TO_MANAGED 1 -#if defined(TARGET_WATCHOS) || (defined(__linux__) && !defined(TARGET_ANDROID)) +#if defined(TARGET_WATCHOS) || (defined(__linux__) && !defined(TARGET_ANDROID) && !defined(TARGET_LINUX_MUSL)) #define MONO_ARCH_DISABLE_HW_TRAPS 1 #define MONO_ARCH_HAVE_UNWIND_BACKTRACE 1 #endif diff --git a/src/mono/mono/mini/mini-arm64.c b/src/mono/mono/mini/mini-arm64.c index 657aac2c79d8..05ea6500381a 100644 --- a/src/mono/mono/mini/mini-arm64.c +++ b/src/mono/mono/mini/mini-arm64.c @@ -2081,7 +2081,7 @@ mono_arch_set_native_call_context_ret (CallContext *ccontext, gpointer frame, Mo storage = alloca (temp_size); else storage = arg_get_storage (ccontext, ainfo); - memset (ccontext, 0, sizeof (CallContext)); // FIXME + interp_cb->frame_arg_to_data ((MonoInterpFrameHandle)frame, sig, -1, storage); if (temp_size) arg_set_val (ccontext, ainfo, storage); @@ -2887,7 +2887,12 @@ mono_arch_allocate_vars (MonoCompile *cfg) offset += size; cfg->arch.swift_error_var = ins; - cfg->used_int_regs |= 1 << ARMREG_R21; + + /* In the n2m case, the error register functions as an extra return register + * and is thus is not treated as callee-saved. + */ + if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) + cfg->used_int_regs |= 1 << ARMREG_R21; break; } default: @@ -3704,7 +3709,7 @@ opcode_to_armcond (int opcode) case OP_COND_EXC_INO: return ARMCOND_VC; default: - printf ("%s\n", mono_inst_name (opcode)); + printf ("" M_PRI_INST "\n", mono_inst_name (opcode)); g_assert_not_reached (); return -1; } @@ -3731,8 +3736,13 @@ emit_move_return_value (MonoCompile *cfg, guint8 * code, MonoInst *ins) MonoCallInst *call; if (cfg->arch.swift_error_var) { - code = emit_ldrx (code, ARMREG_IP0, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset)); - code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0); + if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) { + code = emit_ldrx (code, ARMREG_IP0, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset)); + code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0); + } else if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) { + /* Load the value of SwiftError into R21 */ + code = emit_ldrx (code, ARMREG_R21, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset)); + } } call = (MonoCallInst*)ins; @@ -5388,6 +5398,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) g_assert (!cfg->method->save_lmf); max_len += call->stack_usage / sizeof (target_mgreg_t) * ins_get_size (OP_TAILCALL_PARAMETER); + // HACK: In cpu-arm64.mdesc the tailcall opcodes have a len of 255, which is + // arbitrary, but it's the max uint8 value. It looks like in some + // circumstances we need more space than that. + // + // Add some more space to acount for mono_arm_emit_destroy_frame and + // emit_load_regset, below + max_len += 64; while (G_UNLIKELY (offset + max_len > cfg->code_size)) { cfg->code_size *= 2; cfg->native_code = (unsigned char *)mono_realloc_native_code (cfg); @@ -5801,13 +5818,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; default: - g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__); + g_warning ("unknown opcode " M_PRI_INST " in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__); g_assert_not_reached (); } after_instruction_emit: if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) { - g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %d)", + g_warning ("wrong maximal instruction length of instruction " M_PRI_INST " (expected %d, got %d)", mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset); g_assert_not_reached (); @@ -5937,11 +5954,17 @@ emit_move_args (MonoCompile *cfg, guint8 *code) code = emit_strfpq (code, ainfo->reg, ins->inst_basereg, GTMREG_TO_INT (ins->inst_offset)); break; case ArgSwiftError: - if (ainfo->offset) { - code = emit_ldrx (code, ARMREG_IP0, cfg->arch.args_reg, ainfo->offset); - code = emit_strx (code, ARMREG_IP0, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset)); - } else { - code = emit_strx (code, ainfo->reg, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset)); + if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) { + if (ainfo->offset) { + code = emit_ldrx (code, ARMREG_IP0, cfg->arch.args_reg, ainfo->offset); + code = emit_strx (code, ARMREG_IP0, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset)); + } else { + code = emit_strx (code, ainfo->reg, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset)); + } + } else if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) { + arm_addx_imm (code, ARMREG_IP0, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset)); + /* Relies on arguments being passed on the stack */ + code = emit_strx (code, ARMREG_IP0, ins->inst_basereg, GTMREG_TO_INT (ins->inst_offset)); } break; default: diff --git a/src/mono/mono/mini/mini-codegen.c b/src/mono/mono/mini/mini-codegen.c index 21b03a98ee7e..210c1619f629 100644 --- a/src/mono/mono/mini/mini-codegen.c +++ b/src/mono/mono/mini/mini-codegen.c @@ -439,9 +439,9 @@ mono_print_ins_index_strbuf (int i, MonoInst *ins) char spec_dest = (char)0, spec_src1 = (char)0, spec_src2 = (char)0, spec_src3 = (char)0; if (i != -1) - g_string_append_printf (sbuf, "\t%-2d %s", i, mono_inst_name (ins->opcode)); + g_string_append_printf (sbuf, "\t%-2d " M_PRI_INST "", i, mono_inst_name (ins->opcode)); else - g_string_append_printf (sbuf, " %s", mono_inst_name (ins->opcode)); + g_string_append_printf (sbuf, " " M_PRI_INST "", mono_inst_name (ins->opcode)); if (spec == (gpointer)MONO_ARCH_CPU_SPEC) { /* This is a lowered opcode */ if (ins->dreg != -1) { @@ -1160,11 +1160,11 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) ispec = INS_INFO (i); if ((spec [MONO_INST_DEST] && (ispec [MONO_INST_DEST] == ' '))) - g_error ("Instruction metadata for %s inconsistent.\n", mono_inst_name (i)); + g_error ("Instruction metadata for " M_PRI_INST " inconsistent.\n", mono_inst_name (i)); if ((spec [MONO_INST_SRC1] && (ispec [MONO_INST_SRC1] == ' '))) - g_error ("Instruction metadata for %s inconsistent.\n", mono_inst_name (i)); + g_error ("Instruction metadata for " M_PRI_INST " inconsistent.\n", mono_inst_name (i)); if ((spec [MONO_INST_SRC2] && (ispec [MONO_INST_SRC2] == ' '))) - g_error ("Instruction metadata for %s inconsistent.\n", mono_inst_name (i)); + g_error ("Instruction metadata for " M_PRI_INST " inconsistent.\n", mono_inst_name (i)); } #endif } @@ -1249,7 +1249,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) spec_dest = spec [MONO_INST_DEST]; if (G_UNLIKELY (spec == (gpointer)/*FIXME*/MONO_ARCH_CPU_SPEC)) { - g_error ("Opcode '%s' missing from machine description file.", mono_inst_name (ins->opcode)); + g_error ("Opcode '" M_PRI_INST "' missing from machine description file.", mono_inst_name (ins->opcode)); } DEBUG (mono_print_ins_index (i, ins)); @@ -2303,7 +2303,7 @@ mono_opcode_to_cond (int opcode) CompRelation rel = mono_opcode_to_cond_unchecked (opcode); if (rel == (CompRelation)-1) { - printf ("%s\n", mono_inst_name (opcode)); + printf ("" M_PRI_INST "\n", mono_inst_name (opcode)); g_assert_not_reached (); return (CompRelation)0; } @@ -2367,7 +2367,7 @@ mono_opcode_to_type (int opcode, int cmp_opcode) return CMP_TYPE_L; } } else { - g_error ("Unknown opcode '%s' in opcode_to_type", mono_inst_name (opcode)); + g_error ("Unknown opcode '" M_PRI_INST "' in opcode_to_type", mono_inst_name (opcode)); return (CompType)0; } } diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index f7e59ef5acbb..650a5a775e67 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -1028,7 +1029,7 @@ op_to_llvm_type (int opcode) case OP_LMUL_OVF_UN: return LLVMInt64Type (); default: - printf ("%s\n", mono_inst_name (opcode)); + printf ("" M_PRI_INST "\n", mono_inst_name (opcode)); g_assert_not_reached (); return NULL; } @@ -1426,15 +1427,18 @@ convert (EmitContext *ctx, LLVMValueRef v, LLVMTypeRef dtype) } static void -emit_memset (EmitContext *ctx, LLVMValueRef v, LLVMValueRef size, int alignment) +emit_memset (EmitContext *ctx, LLVMValueRef dest, LLVMValueRef val, LLVMValueRef size, int alignment) { LLVMValueRef args [5]; int aindex = 0; - args [aindex ++] = v; - args [aindex ++] = LLVMConstInt (LLVMInt8Type (), 0, FALSE); + args [aindex ++] = dest; + if (val) + args [aindex ++] = val; + else + args [aindex ++] = LLVMConstInt (LLVMInt8Type (), 0, FALSE); args [aindex ++] = size; - args [aindex ++] = LLVMConstInt (LLVMInt1Type (), 0, FALSE); + args [aindex ++] = LLVMConstInt (LLVMInt1Type (), 0, FALSE); // is_volatile call_intrins (ctx, INTRINS_MEMSET, args, ""); } @@ -6118,8 +6122,14 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) gboolean src_in_reg = FALSE; gboolean is_simd = mini_class_is_simd (ctx->cfg, mono_class_from_mono_type_internal (sig->ret)); switch (linfo->ret.storage) { - case LLVMArgNormal: src_in_reg = TRUE; break; - case LLVMArgVtypeInReg: case LLVMArgVtypeAsScalar: src_in_reg = is_simd; break; + case LLVMArgNormal: + src_in_reg = TRUE; + break; + case LLVMArgVtypeInReg: + case LLVMArgVtypeAsScalar: + case LLVMArgWasmVtypeAsScalar: + src_in_reg = is_simd; + break; } if (src_in_reg && (!lhs || ctx->is_dead [ins->sreg1])) { /* @@ -6152,7 +6162,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) * load it into registers. */ LLVMValueRef buf = build_alloca_llvm_type_name (ctx, pointer_type (ret_type), 0, "ret_buf"); - emit_memset (ctx, buf, LLVMSizeOf (ret_type), 1); + emit_memset (ctx, buf, NULL, LLVMSizeOf (ret_type), 1); int width = mono_type_size (sig->ret, NULL); LLVMValueRef args [] = { @@ -6993,7 +7003,7 @@ MONO_RESTORE_WARNING v = mono_llvm_build_alloca (builder, LLVMInt8Type (), const_int32 (size), MONO_ARCH_FRAME_ALIGNMENT, ""); if (ins->flags & MONO_INST_INIT) - emit_memset (ctx, v, const_int32 (size), MONO_ARCH_FRAME_ALIGNMENT); + emit_memset (ctx, v, NULL, const_int32 (size), MONO_ARCH_FRAME_ALIGNMENT); values [ins->dreg] = v; break; @@ -7006,7 +7016,7 @@ MONO_RESTORE_WARNING v = mono_llvm_build_alloca (builder, LLVMInt8Type (), size, MONO_ARCH_FRAME_ALIGNMENT, ""); if (ins->flags & MONO_INST_INIT) - emit_memset (ctx, v, size, MONO_ARCH_FRAME_ALIGNMENT); + emit_memset (ctx, v, NULL, size, MONO_ARCH_FRAME_ALIGNMENT); values [ins->dreg] = v; break; } @@ -7224,6 +7234,19 @@ MONO_RESTORE_WARNING call_intrins (ctx, INTRINS_MEMMOVE, args, ""); break; } + case OP_MEMSET_ZERO: { + LLVMValueRef dest = convert (ctx, values [ins->sreg1], pointer_type (LLVMInt8Type ())); + LLVMValueRef size = convert (ctx, values [ins->sreg2], LLVMInt64Type ()); + emit_memset (ctx, dest, NULL, size, MONO_ARCH_FRAME_ALIGNMENT); + break; + } + case OP_MEMSET: { + LLVMValueRef dest = convert (ctx, values [ins->sreg1], pointer_type (LLVMInt8Type ())); + LLVMValueRef val = convert (ctx, values [ins->sreg2], LLVMInt8Type ()); + LLVMValueRef size = convert (ctx, values [ins->sreg3], LLVMInt64Type ()); + emit_memset (ctx, dest, val, size, MONO_ARCH_FRAME_ALIGNMENT); + break; + } case OP_NOT_REACHED: LLVMBuildUnreachable (builder); has_terminator = TRUE; @@ -7856,7 +7879,7 @@ MONO_RESTORE_WARNING addresses [ins->dreg] = create_address (ctx, build_named_alloca (ctx, m_class_get_byval_arg (klass), "vzero"), etype); } LLVMValueRef ptr = build_ptr_cast (builder, addresses [ins->dreg]->value, pointer_type (LLVMInt8Type ())); - emit_memset (ctx, ptr, const_int32 (mono_class_value_size (klass, NULL)), 0); + emit_memset (ctx, ptr, NULL, const_int32 (mono_class_value_size (klass, NULL)), 0); break; } case OP_DUMMY_VZERO: @@ -12445,12 +12468,12 @@ MONO_RESTORE_WARNING case OP_LOAD_GOTADDR: { char reason [128]; - sprintf (reason, "opcode %s", mono_inst_name (ins->opcode)); + sprintf (reason, "opcode " M_PRI_INST "", mono_inst_name (ins->opcode)); set_failure (ctx, reason); break; } default: - g_error ("opcode %d %s", ins->opcode, mono_inst_name (ins->opcode)); + g_error ("opcode %d " M_PRI_INST "", ins->opcode, mono_inst_name (ins->opcode)); break; } @@ -14519,18 +14542,10 @@ emit_aot_file_info (MonoLLVMModule *module) LLVMSetInitializer (info_var, LLVMConstNamedStruct (module->info_var_type, fields, nfields)); if (module->static_link) { - char *s, *p; LLVMValueRef var; - - s = g_strdup_printf ("mono_aot_module_%s_info", module->assembly->aname.name); - /* Get rid of characters which cannot occur in symbols */ - p = s; - for (p = s; *p; ++p) { - if (!(isalnum (*p) || *p == '_')) - *p = '_'; - } - var = LLVMAddGlobal (module->lmodule, pointer_type (LLVMInt8Type ()), s); - g_free (s); + char *fixedName = mono_fixup_symbol_name ("mono_aot_module_", module->assembly->aname.name, "_info"); + var = LLVMAddGlobal (module->lmodule, pointer_type (LLVMInt8Type ()), fixedName); + free (fixedName); LLVMSetInitializer (var, LLVMConstBitCast (LLVMGetNamedGlobal (module->lmodule, "mono_aot_file_info"), pointer_type (LLVMInt8Type ()))); LLVMSetLinkage (var, LLVMExternalLinkage); } diff --git a/src/mono/mono/mini/mini-ops.h b/src/mono/mono/mini/mini-ops.h index ec82dd5de8a8..edf7d1b3930d 100644 --- a/src/mono/mono/mini/mini-ops.h +++ b/src/mono/mono/mini/mini-ops.h @@ -775,6 +775,7 @@ MINI_OP(OP_LDELEMA2D, "ldelema2d", NONE, NONE, NONE) MINI_OP(OP_MEMCPY, "memcpy", NONE, NONE, NONE) /* inlined small memset with constant length */ MINI_OP(OP_MEMSET, "memset", NONE, NONE, NONE) +MINI_OP(OP_MEMSET_ZERO, "memset_zero", NONE, IREG, IREG) /* * A RuntimeType object, the result ldtoken+GetTypeFromHandle. * inst_p0 is a MonoClass. diff --git a/src/mono/mono/mini/mini-ppc.c b/src/mono/mono/mini/mini-ppc.c index b3514123b7e9..a5c1fbb2f986 100644 --- a/src/mono/mono/mini/mini-ppc.c +++ b/src/mono/mono/mini/mini-ppc.c @@ -2420,7 +2420,7 @@ map_to_reg_reg_op (int op) return OP_STOREI8_MEMBASE_REG; } if (mono_op_imm_to_op (op) == -1) - g_error ("mono_op_imm_to_op failed for %s\n", mono_inst_name (op)); + g_error ("mono_op_imm_to_op failed for " M_PRI_INST "\n", mono_inst_name (op)); return mono_op_imm_to_op (op); } @@ -4734,12 +4734,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; } default: - g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__); + g_warning ("unknown opcode " M_PRI_INST " in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__); g_assert_not_reached (); } if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) { - g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)", + g_warning ("wrong maximal instruction length of instruction " M_PRI_INST " (expected %d, got %ld)", mono_inst_name (ins->opcode), max_len, (glong)(code - cfg->native_code - offset)); g_assert_not_reached (); } diff --git a/src/mono/mono/mini/mini-riscv.c b/src/mono/mono/mini/mini-riscv.c index 4f25347b37e6..4214f701ed2f 100644 --- a/src/mono/mono/mini/mini-riscv.c +++ b/src/mono/mono/mini/mini-riscv.c @@ -2155,7 +2155,7 @@ mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins) NULLIFY_INS (ins); break; default: - g_print ("Can't decompose the OP %s\n", mono_inst_name (ins->opcode)); + g_print ("Can't decompose the OP " M_PRI_INST "\n", mono_inst_name (ins->opcode)); NOT_IMPLEMENTED; } } @@ -2801,7 +2801,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) next_ins->sreg2 = RISCV_ZERO; } else { if (cfg->verbose_level > 1) { - g_print ("Unhandaled op %s following after OP_RCOMPARE\n", mono_inst_name (next_ins->opcode)); + g_print ("Unhandaled op " M_PRI_INST " following after OP_RCOMPARE\n", mono_inst_name (next_ins->opcode)); } NULLIFY_INS (ins); } @@ -2885,7 +2885,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) next_ins->sreg2 = RISCV_ZERO; } else { if (cfg->verbose_level > 1) { - g_print ("Unhandaled op %s following after OP_FCOMPARE\n", mono_inst_name (next_ins->opcode)); + g_print ("Unhandaled op " M_PRI_INST " following after OP_FCOMPARE\n", mono_inst_name (next_ins->opcode)); } NULLIFY_INS (ins); } @@ -3302,7 +3302,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) * what should I do? */ if (cfg->verbose_level > 1) { - g_print ("Unhandaled op %s following after OP_{I|L}COMPARE{|_IMM}\n", + g_print ("Unhandaled op " M_PRI_INST " following after OP_{I|L}COMPARE{|_IMM}\n", mono_inst_name (next_ins->opcode)); } NULLIFY_INS (ins); @@ -5632,7 +5632,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } g_assertf ((code - cfg->native_code - offset) <= max_len, - "wrong maximal instruction length of instruction %s (expected %d, got %d)", + "wrong maximal instruction length of instruction " M_PRI_INST " (expected %d, got %d)", mono_inst_name (ins->opcode), max_len, (int)(code - cfg->native_code - offset)); } set_code_cursor (cfg, code); diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 90fe8ddc799e..35ae4b04161d 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -4452,7 +4452,6 @@ free_jit_mem_manager (MonoMemoryManager *mem_manager) g_hash_table_destroy (info->dyn_delegate_info_hash); g_hash_table_destroy (info->static_rgctx_trampoline_hash); g_hash_table_destroy (info->mrgctx_hash); - g_hash_table_destroy (info->interp_method_pointer_hash); mono_conc_hashtable_destroy (info->runtime_invoke_hash); g_hash_table_destroy (info->seq_points); g_hash_table_destroy (info->arch_seq_points); diff --git a/src/mono/mono/mini/mini-runtime.h b/src/mono/mono/mini/mini-runtime.h index 1e4cb5dc1eb8..c6a82a5231b0 100644 --- a/src/mono/mono/mini/mini-runtime.h +++ b/src/mono/mono/mini/mini-runtime.h @@ -54,8 +54,6 @@ typedef struct { MonoInternalHashTable interp_code_hash; /* Maps MonoMethod -> MonoMethodRuntimeGenericContext */ GHashTable *mrgctx_hash; - /* Maps gpointer -> InterpMethod */ - GHashTable *interp_method_pointer_hash; /* Protected by 'jit_code_hash_lock' */ MonoInternalHashTable jit_code_hash; mono_mutex_t jit_code_hash_lock; diff --git a/src/mono/mono/mini/mini-s390x.c b/src/mono/mono/mini/mini-s390x.c index a5f228ea20f1..e90a0e6770e1 100644 --- a/src/mono/mono/mini/mini-s390x.c +++ b/src/mono/mono/mini/mini-s390x.c @@ -464,7 +464,7 @@ mono_arch_fregname (int reg) const char * mono_arch_xregname (int reg) { - if (reg < s390_VR_NREG) + if (reg >= 0 && reg < s390_VR_NREG) return vrNames [reg]; else return "unknown"; @@ -1580,7 +1580,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) inst->inst_offset = offset + (8 - size); } } - offset += MAX(size, 8); + offset += 8; } curinst++; } @@ -5436,12 +5436,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; #endif default: - g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__); + g_warning ("unknown opcode " M_PRI_INST " in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__); g_assert_not_reached (); } if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) { - g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)", + g_warning ("wrong maximal instruction length of instruction " M_PRI_INST " (expected %d, got %ld)", mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset); g_assert_not_reached (); } diff --git a/src/mono/mono/mini/mini-x86.c b/src/mono/mono/mini/mini-x86.c index 80116fb5497f..10a2d2f0255f 100644 --- a/src/mono/mono/mini/mini-x86.c +++ b/src/mono/mono/mini/mini-x86.c @@ -4912,12 +4912,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) code = emit_get_last_error (code, ins->dreg); break; default: - g_warning ("unknown opcode %s\n", mono_inst_name (ins->opcode)); + g_warning ("unknown opcode " M_PRI_INST "\n", mono_inst_name (ins->opcode)); g_assert_not_reached (); } if (G_UNLIKELY ((code - cfg->native_code - offset) > GINT_TO_UINT(max_len))) { - g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %d)", + g_warning ("wrong maximal instruction length of instruction " M_PRI_INST " (expected %d, got %d)", mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset); g_assert_not_reached (); } diff --git a/src/mono/mono/mini/mini.c b/src/mono/mono/mini/mini.c index 92bf21887c59..395a869ab22b 100644 --- a/src/mono/mono/mini/mini.c +++ b/src/mono/mono/mini/mini.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -602,7 +603,7 @@ mono_decompose_op_imm (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins) mono_bblock_insert_before_ins (bb, ins, temp); if (opcode2 == -1) - g_error ("mono_op_imm_to_op failed for %s\n", mono_inst_name (ins->opcode)); + g_error ("mono_op_imm_to_op failed for " M_PRI_INST "\n", mono_inst_name (ins->opcode)); ins->opcode = GINT_TO_OPCODE (opcode2); if (ins->opcode == OP_LOCALLOC) @@ -4613,3 +4614,61 @@ mini_get_simd_type_info (MonoClass *klass, guint32 *nelems) } } +MonoMethod* +mini_inflate_unsafe_accessor_wrapper (MonoMethod *extern_decl, MonoGenericContext *ctx, MonoUnsafeAccessorKind accessor_kind, const char *member_name, MonoError *error) +{ + MonoMethod *generic_wrapper = mono_marshal_get_unsafe_accessor_wrapper (extern_decl, accessor_kind, member_name); + MonoMethod *inflated_wrapper = mono_class_inflate_generic_method_checked (generic_wrapper, ctx, error); + return inflated_wrapper; +} + + +static MonoMethod* +inflate_unsafe_accessor_like_decl (MonoMethod *extern_method_inst, MonoUnsafeAccessorKind accessor_kind, const char *member_name, MonoError *error) +{ + g_assert (extern_method_inst->is_inflated); + MonoMethodInflated *infl = (MonoMethodInflated*)extern_method_inst; + MonoMethod *extern_decl = infl->declaring; + MonoGenericContext *ctx = &infl->context; + return mini_inflate_unsafe_accessor_wrapper (extern_decl, ctx, accessor_kind, member_name, error); +} + +/** + * Replaces some extern \c method by a wrapper. + * + * Unsafe accessor methods are static extern methods with no header. Calls to + * them are replaced by calls to a wrapper. So during AOT compilation when we + * collect methods to AOT, we replace these methods by the wrappers, too. + * + * Returns the wrapper method, or \c NULL if it doesn't need to be replaced. + * On error returns NULL and sets \c error. + */ +MonoMethod* +mini_replace_generated_method (MonoMethod *method, MonoError *error) +{ + if (G_LIKELY (mono_method_metadata_has_header (method))) + return NULL; + + /* Unsafe accessors methods. Replace attempts to compile the accessor method by + * its wrapper. + */ + char *member_name = NULL; + int accessor_kind = -1; + if (mono_method_get_unsafe_accessor_attr_data (method, &accessor_kind, &member_name, error)) { + MonoMethod *wrapper = NULL; + if (method->is_inflated) { + wrapper = inflate_unsafe_accessor_like_decl (method, (MonoUnsafeAccessorKind)accessor_kind, member_name, error); + } else { + wrapper = mono_marshal_get_unsafe_accessor_wrapper (method, (MonoUnsafeAccessorKind)accessor_kind, member_name); + } + if (is_ok (error)) { + if (mono_trace_is_traced (G_LOG_LEVEL_INFO, MONO_TRACE_AOT)) { + char * method_name = mono_method_get_full_name (wrapper); + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "Replacing generated method by %s", method_name); + g_free (method_name); + } + return wrapper; + } + } + return NULL; +} diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index 781cb54b0492..215abfee0fb5 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -2183,7 +2183,17 @@ GString *mono_print_ins_index_strbuf (int i, MonoInst *ins); void mono_print_ins (MonoInst *ins); void mono_print_bb (MonoBasicBlock *bb, const char *msg); void mono_print_code (MonoCompile *cfg, const char *msg); -const char* mono_inst_name (int op); +#ifndef DISABLE_LOGGING +#define M_PRI_INST "%s" +const char * mono_inst_name(int opcode); +#else +#define M_PRI_INST "%d" +static inline int +mono_inst_name(int opcode) +{ + return opcode; +} +#endif int mono_op_to_op_imm (int opcode); int mono_op_imm_to_op (int opcode); int mono_load_membase_to_load_mem (int opcode); @@ -3023,4 +3033,10 @@ MonoMemoryManager* mini_get_default_mem_manager (void); MONO_COMPONENT_API int mono_wasm_get_debug_level (void); +MonoMethod* +mini_inflate_unsafe_accessor_wrapper (MonoMethod *extern_decl, MonoGenericContext *ctx, MonoUnsafeAccessorKind accessor_kind, const char *member_name, MonoError *error); + +MonoMethod * +mini_replace_generated_method (MonoMethod *method, MonoError *error); + #endif /* __MONO_MINI_H__ */ diff --git a/src/mono/mono/mini/tramp-amd64.c b/src/mono/mono/mini/tramp-amd64.c index 4f0e48c61918..8cb668a1e457 100644 --- a/src/mono/mono/mini/tramp-amd64.c +++ b/src/mono/mono/mini/tramp-amd64.c @@ -1263,6 +1263,12 @@ mono_arch_get_native_to_interp_trampoline (MonoTrampInfo **info) for (i = 0; i < FLOAT_PARAM_REGS; i++) amd64_sse_movsd_membase_reg (code, AMD64_RSP, ctx_offset + MONO_STRUCT_OFFSET (CallContext, fregs) + i * sizeof (double), i); +#ifdef MONO_ARCH_HAVE_SWIFTCALL + /* set context registers to CallContext */ + for (i = 0; i < CTX_REGS; i++) + amd64_mov_membase_reg (code, AMD64_RSP, ctx_offset + MONO_STRUCT_OFFSET (CallContext, gregs) + (i + CTX_REGS_OFFSET) * sizeof (target_mgreg_t), i + CTX_REGS_OFFSET, sizeof (target_mgreg_t)); +#endif + /* set the stack pointer to the value at call site */ amd64_mov_reg_reg (code, AMD64_R11, AMD64_RBP, sizeof (target_mgreg_t)); amd64_alu_reg_imm (code, X86_ADD, AMD64_R11, 2 * sizeof (target_mgreg_t)); @@ -1283,6 +1289,12 @@ mono_arch_get_native_to_interp_trampoline (MonoTrampInfo **info) for (i = 0; i < FLOAT_RETURN_REGS; i++) amd64_sse_movsd_reg_membase (code, i, AMD64_RSP, ctx_offset + MONO_STRUCT_OFFSET (CallContext, fregs) + i * sizeof (double)); +#ifdef MONO_ARCH_HAVE_SWIFTCALL + /* set the context registers from CallContext */ + for (i = 0; i < CTX_REGS; i++) + amd64_mov_reg_membase (code, i + CTX_REGS_OFFSET, AMD64_RSP, ctx_offset + MONO_STRUCT_OFFSET (CallContext, gregs) + (i + CTX_REGS_OFFSET) * sizeof (target_mgreg_t), sizeof (target_mgreg_t)); +#endif + /* reset stack and return */ #if TARGET_WIN32 amd64_lea_membase (code, AMD64_RSP, AMD64_RBP, 0); diff --git a/src/mono/mono/mini/tramp-arm64.c b/src/mono/mono/mini/tramp-arm64.c index 7e8483409610..f4869988e87b 100644 --- a/src/mono/mono/mini/tramp-arm64.c +++ b/src/mono/mono/mini/tramp-arm64.c @@ -846,6 +846,12 @@ mono_arch_get_native_to_interp_trampoline (MonoTrampInfo **info) for (i = 0; i < FP_PARAM_REGS; i++) arm_strfpx (code, i, ARMREG_FP, ccontext_offset + MONO_STRUCT_OFFSET (CallContext, fregs) + i * sizeof (double)); +#ifdef MONO_ARCH_HAVE_SWIFTCALL + /* set context registers to CallContext */ + for (i = 0; i < CTX_REGS; i++) + arm_strx (code, i + CTX_REGS_OFFSET, ARMREG_FP, ccontext_offset + MONO_STRUCT_OFFSET (CallContext, gregs) + (i + PARAM_REGS + 1) * sizeof (host_mgreg_t)); +#endif + /* set the stack pointer to the value at call site */ arm_addx_imm (code, ARMREG_R0, ARMREG_FP, framesize); arm_strp (code, ARMREG_R0, ARMREG_FP, ccontext_offset + MONO_STRUCT_OFFSET (CallContext, stack)); @@ -863,6 +869,12 @@ mono_arch_get_native_to_interp_trampoline (MonoTrampInfo **info) for (i = 0; i < FP_PARAM_REGS; i++) arm_ldrfpx (code, i, ARMREG_FP, ccontext_offset + MONO_STRUCT_OFFSET (CallContext, fregs) + i * sizeof (double)); +#ifdef MONO_ARCH_HAVE_SWIFTCALL + /* set the context registers from CallContext */ + for (i = 0; i < CTX_REGS; i++) + arm_ldrx (code, i + CTX_REGS_OFFSET, ARMREG_FP, ccontext_offset + MONO_STRUCT_OFFSET (CallContext, gregs) + (i + PARAM_REGS + 1) * sizeof (host_mgreg_t)); +#endif + /* reset stack and return */ arm_ldpx (code, ARMREG_FP, ARMREG_LR, ARMREG_SP, 0); arm_addx_imm (code, ARMREG_SP, ARMREG_SP, framesize); diff --git a/src/mono/mono/sgen/sgen-gc.c b/src/mono/mono/sgen/sgen-gc.c index 07cf39ffd9df..705b8168ed36 100644 --- a/src/mono/mono/sgen/sgen-gc.c +++ b/src/mono/mono/sgen/sgen-gc.c @@ -2848,6 +2848,9 @@ sgen_gc_invoke_finalizers (void) g_assert (!pending_unqueued_finalizer); + gboolean gchandle_allocated = FALSE; + guint32 gchandle = 0; + /* FIXME: batch to reduce lock contention */ while (sgen_have_pending_finalizers ()) { GCObject *obj; @@ -2878,8 +2881,16 @@ sgen_gc_invoke_finalizers (void) if (!obj) break; + // We explicitly pin the object via a gchandle so we don't rely on the ref being + // present on stack/regs which is not scannable on WASM. + if (!gchandle_allocated) { + gchandle = sgen_gchandle_new (obj, TRUE); + gchandle_allocated = TRUE; + } else { + sgen_gchandle_set_target (gchandle, obj); + } + count++; - /* the object is on the stack so it is pinned */ /*g_print ("Calling finalizer for object: %p (%s)\n", obj, sgen_client_object_safe_name (obj));*/ sgen_client_run_finalize (obj); } @@ -2889,6 +2900,9 @@ sgen_gc_invoke_finalizers (void) pending_unqueued_finalizer = FALSE; } + if (gchandle_allocated) + sgen_gchandle_free (gchandle); + return count; } diff --git a/src/mono/mono/sgen/sgen-internal.c b/src/mono/mono/sgen/sgen-internal.c index c026d47b1a59..6ff3e6fda980 100644 --- a/src/mono/mono/sgen/sgen-internal.c +++ b/src/mono/mono/sgen/sgen-internal.c @@ -273,7 +273,7 @@ sgen_report_internal_mem_usage (void) void sgen_init_internal_allocator (void) { - int i, size; + int i; for (i = 0; i < INTERNAL_MEM_MAX; ++i) fixed_type_allocator_indexes [i] = -1; @@ -284,7 +284,10 @@ sgen_init_internal_allocator (void) mono_lock_free_allocator_init_allocator (&allocators [i], &size_classes [i], MONO_MEM_ACCOUNT_SGEN_INTERNAL); } - for (size = mono_pagesize (); size <= LOCK_FREE_ALLOC_SB_MAX_SIZE; size <<= 1) { + // FIXME: This whole algorithm is broken on WASM due to its 64KB page size. + // Previously SB_MAX_SIZE was < mono_pagesize, so none of this ran. +#ifndef HOST_WASM + for (int size = mono_pagesize (); size <= LOCK_FREE_ALLOC_SB_MAX_SIZE; size <<= 1) { int max_size = (LOCK_FREE_ALLOC_SB_USABLE_SIZE (size) / 2) & ~(SIZEOF_VOID_P - 1); /* * we assert that allocator_sizes contains the biggest possible object size @@ -297,6 +300,7 @@ sgen_init_internal_allocator (void) if (size < LOCK_FREE_ALLOC_SB_MAX_SIZE) g_assert (block_size (max_size + 1) == size << 1); } +#endif } #endif diff --git a/src/mono/mono/sgen/sgen-marksweep.c b/src/mono/mono/sgen/sgen-marksweep.c index 1767d4712def..a8160dbeee37 100644 --- a/src/mono/mono/sgen/sgen-marksweep.c +++ b/src/mono/mono/sgen/sgen-marksweep.c @@ -33,6 +33,7 @@ #include "mono/sgen/sgen-client.h" #include "mono/utils/mono-memory-model.h" #include "mono/utils/mono-proclib.h" +#include "mono/utils/options.h" static int ms_block_size; @@ -2133,12 +2134,15 @@ major_free_swept_blocks (size_t section_reserve) { SGEN_ASSERT (0, sweep_state == SWEEP_STATE_SWEPT, "Sweeping must have finished before freeing blocks"); -#if defined(HOST_WIN32) || defined(HOST_ORBIS) || defined (HOST_WASM) +#if defined(HOST_WIN32) || defined(HOST_ORBIS) /* * sgen_free_os_memory () asserts in mono_vfree () because windows doesn't like freeing the middle of * a VirtualAlloc ()-ed block. */ return; +#elif defined(HOST_WASM) + if (!mono_opt_wasm_mmap) + return; #endif { diff --git a/src/mono/mono/tools/offsets-tool/offsets-tool.py b/src/mono/mono/tools/offsets-tool/offsets-tool.py index ad450989afed..15d7deb45584 100644 --- a/src/mono/mono/tools/offsets-tool/offsets-tool.py +++ b/src/mono/mono/tools/offsets-tool/offsets-tool.py @@ -89,9 +89,11 @@ def require_emscipten_path (args): if "wasm" in args.abi: if args.wasi_path != None: - self.sys_includes = [args.wasi_path + "/share/wasi-sysroot/include", args.wasi_path + "/lib/clang/17/include", args.mono_path + "/wasi/mono-include"] + require_sysroot (args) + self.sys_includes = [args.wasi_path + "/share/wasi-sysroot/include", args.wasi_path + "/lib/clang/18/include", args.mono_path + "/wasi/mono-include"] self.target = Target ("TARGET_WASI", None, ["TARGET_WASM"] + WASI_DEFINES) self.target_args += ["-target", args.abi] + self.target_args += ["--sysroot", args.sysroot] else: require_emscipten_path (args) clang_path = os.path.dirname(args.libclang) @@ -159,13 +161,13 @@ def require_emscipten_path (args): elif "x86_64-apple-maccatalyst" == args.abi: require_sysroot (args) self.target = Target ("TARGET_AMD64", "TARGET_MACCAT", IOS_DEFINES) - self.target_args += ["-target", "x86_64-apple-ios13.5-macabi"] + self.target_args += ["-target", "x86_64-apple-ios15.0-macabi"] self.target_args += ["-isysroot", args.sysroot] elif "aarch64-apple-maccatalyst" == args.abi: require_sysroot (args) self.target = Target ("TARGET_ARM64", "TARGET_MACCAT", IOS_DEFINES) - self.target_args += ["-target", "arm64-apple-ios14.2-macabi"] + self.target_args += ["-target", "arm64-apple-ios15.0-macabi"] self.target_args += ["-isysroot", args.sysroot] # watchOS diff --git a/src/mono/mono/utils/CMakeLists.txt b/src/mono/mono/utils/CMakeLists.txt index e5dbf68b10f8..e5bd089b8203 100644 --- a/src/mono/mono/utils/CMakeLists.txt +++ b/src/mono/mono/utils/CMakeLists.txt @@ -37,7 +37,6 @@ else() endif() set(utils_common_sources - mono-md5.c mono-sha1.c mono-logger.c mono-logger-internals.h @@ -187,15 +186,9 @@ set(utils_arch_sources mach-support-unknown.c) elseif(HOST_AMD64) set(utils_arch_sources mach-support-amd64.c) -elseif(HOST_X86) -set(utils_arch_sources - mach-support-x86.c) elseif(HOST_ARM64) set(utils_arch_sources mach-support-arm64.c) -elseif(HOST_ARM) -set(utils_arch_sources - mach-support-arm.c) else() #message(FATAL_ERROR "") endif() @@ -213,7 +206,7 @@ set(utils_arch_sources "${utils_arch_sources};mono-hwcap-riscv.c") elseif(TARGET_S390X) set(utils_arch_sources "${utils_arch_sources};mono-hwcap-s390x.c") elseif(TARGET_WASM) -set(utils_arch_sources "${utils_arch_sources};mono-hwcap-wasm.c;mono-mmap-wasm.c") +set(utils_arch_sources "${utils_arch_sources};mono-hwcap-wasm.c;mono-mmap-wasm.c;mono-wasm-pagemgr.c") elseif(TARGET_WASI) set(utils_arch_sources "${utils_arch_sources};mono-hwcap-wasm.c") elseif(TARGET_POWERPC OR TARGET_POWERPC64) diff --git a/src/mono/mono/utils/atomic.h b/src/mono/mono/utils/atomic.h index 7c7c684ab94e..7d1d127f60c5 100644 --- a/src/mono/mono/utils/atomic.h +++ b/src/mono/mono/utils/atomic.h @@ -115,7 +115,7 @@ mono_atomic_cas_i64 (volatile gint64 *dest, gint64 exch, gint64 comp) (void)atomic_compare_exchange_strong ((volatile atomic_llong *)dest, (long long*)&comp, exch); return comp; #else -#error gint64 not same size atomic_llong or atomic_long, don't define MONO_USE_STDATOMIC +#error "gint64 not same size atomic_llong or atomic_long, don't define MONO_USE_STDATOMIC" #endif } @@ -188,7 +188,7 @@ mono_atomic_xchg_i64 (volatile gint64 *dest, gint64 exch) g_static_assert (sizeof (atomic_llong) == sizeof (*dest) && ATOMIC_LLONG_LOCK_FREE == 2); return atomic_exchange ((volatile atomic_llong *)dest, exch); #else -#error gint64 not same size atomic_llong or atomic_long, don't define MONO_USE_STDATOMIC +#error "gint64 not same size atomic_llong or atomic_long, don't define MONO_USE_STDATOMIC" #endif } @@ -216,7 +216,7 @@ mono_atomic_fetch_add_i64 (volatile gint64 *dest, gint64 add) g_static_assert (sizeof (atomic_llong) == sizeof (*dest) && ATOMIC_LLONG_LOCK_FREE == 2); return atomic_fetch_add ((volatile atomic_llong *)dest, add); #else -#error gint64 not same size atomic_llong or atomic_long, don't define MONO_USE_STDATOMIC +#error "gint64 not same size atomic_llong or atomic_long, don't define MONO_USE_STDATOMIC" #endif } @@ -250,7 +250,7 @@ mono_atomic_load_i64 (volatile gint64 *src) g_static_assert (sizeof (atomic_llong) == sizeof (*src) && ATOMIC_LLONG_LOCK_FREE == 2); return atomic_load ((volatile atomic_llong *)src); #else -#error gint64 not same size atomic_llong or atomic_long, don't define MONO_USE_STDATOMIC +#error "gint64 not same size atomic_llong or atomic_long, don't define MONO_USE_STDATOMIC" #endif } @@ -292,7 +292,7 @@ mono_atomic_store_i64 (volatile gint64 *dst, gint64 val) g_static_assert (sizeof (atomic_llong) == sizeof (*dst) && ATOMIC_LLONG_LOCK_FREE == 2); atomic_store ((volatile atomic_llong *)dst, val); #else -#error gint64 not same size atomic_llong or atomic_long, don't define MONO_USE_STDATOMIC +#error "gint64 not same size atomic_llong or atomic_long, don't define MONO_USE_STDATOMIC" #endif } diff --git a/src/mono/mono/utils/lock-free-alloc.h b/src/mono/mono/utils/lock-free-alloc.h index cca1d83eb661..5aa4e1ea9072 100644 --- a/src/mono/mono/utils/lock-free-alloc.h +++ b/src/mono/mono/utils/lock-free-alloc.h @@ -45,6 +45,7 @@ typedef struct { MonoMemAccountType account_type; } MonoLockFreeAllocator; +// FIXME: On WASM the page size is 64KB, so this isn't enough. #define LOCK_FREE_ALLOC_SB_MAX_SIZE 16384 #define LOCK_FREE_ALLOC_SB_HEADER_SIZE (sizeof (gpointer)) #define LOCK_FREE_ALLOC_SB_USABLE_SIZE(block_size) ((block_size) - LOCK_FREE_ALLOC_SB_HEADER_SIZE) diff --git a/src/mono/mono/utils/mach-support-arm.c b/src/mono/mono/utils/mach-support-arm.c deleted file mode 100644 index e08ab58452a8..000000000000 --- a/src/mono/mono/utils/mach-support-arm.c +++ /dev/null @@ -1,104 +0,0 @@ -/** - * \file - * mach support for ARM - * - * Authors: - * Geoff Norton (gnorton@novell.com) - * Rodrigo Kumpera (kumpera@gmail.com) - * - * (C) 2010 Novell, Inc. - * (C) 2011 Xamarin, Inc. - */ - -#include - -#if defined(__MACH__) -#include -#include -#include -#include "utils/mono-sigcontext.h" -#include "utils/mono-compiler.h" -#include "mach-support.h" - -/* _mcontext.h now defines __darwin_mcontext32, not __darwin_mcontext, starting with Xcode 5.1 */ -#ifdef _STRUCT_MCONTEXT32 - #define __darwin_mcontext __darwin_mcontext32 -#endif - -int -mono_mach_arch_get_mcontext_size (void) -{ - return sizeof (struct __darwin_mcontext); -} - -void -mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context) -{ - arm_thread_state_t *arch_state = (arm_thread_state_t *) state; - struct __darwin_mcontext *ctx = (struct __darwin_mcontext *) context; - - ctx->__ss = *arch_state; -} - -void -mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate) -{ - arm_thread_state_t *arch_state = (arm_thread_state_t *) state; - struct __darwin_mcontext *ctx = (struct __darwin_mcontext *) context; - - *arch_state = ctx->__ss; -} - -void -mono_mach_arch_thread_states_to_mono_context (thread_state_t state, thread_state_t fpstate, MonoContext *context) -{ - int i; - arm_thread_state_t *arch_state = (arm_thread_state_t *) state; - for (i = 0; i < 13; ++i) - context->regs [i] = arch_state->__r [i]; - context->regs [ARMREG_R13] = arch_state->__sp; - context->regs [ARMREG_R14] = arch_state->__lr; - context->regs [ARMREG_R15] = arch_state->__pc; - context->pc = arch_state->__pc; - context->cpsr = arch_state->__cpsr; -} - -int -mono_mach_arch_get_thread_state_size (void) -{ - return sizeof (arm_thread_state_t); -} - -int -mono_mach_arch_get_thread_fpstate_size (void) -{ - return sizeof (arm_neon_state_t); -} - -kern_return_t -mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount) -{ -#if defined(HOST_WATCHOS) - g_error ("thread_get_state() is not supported by this platform"); -#else - arm_thread_state_t *arch_state = (arm_thread_state_t *) state; - kern_return_t ret; - - *count = ARM_THREAD_STATE_COUNT; - - ret = thread_get_state (thread, ARM_THREAD_STATE, (thread_state_t) arch_state, count); - return ret; -#endif -} - -kern_return_t -mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount) -{ -#if defined(HOST_WATCHOS) - g_error ("thread_set_state() is not supported by this platform"); -#else - return thread_set_state (thread, ARM_THREAD_STATE, state, count); -#endif -} - -#endif diff --git a/src/mono/mono/utils/mach-support-arm64.c b/src/mono/mono/utils/mach-support-arm64.c index 6ddd5a8911da..7e1258272c5c 100644 --- a/src/mono/mono/utils/mach-support-arm64.c +++ b/src/mono/mono/utils/mach-support-arm64.c @@ -20,11 +20,6 @@ #include "utils/mono-compiler.h" #include "mach-support.h" -/* _mcontext.h now defines __darwin_mcontext32, not __darwin_mcontext, starting with Xcode 5.1 */ -#ifdef _STRUCT_MCONTEXT32 - #define __darwin_mcontext __darwin_mcontext32 -#endif - int mono_mach_arch_get_mcontext_size (void) { diff --git a/src/mono/mono/utils/mach-support-x86.c b/src/mono/mono/utils/mach-support-x86.c deleted file mode 100644 index 389a8b6ae924..000000000000 --- a/src/mono/mono/utils/mach-support-x86.c +++ /dev/null @@ -1,128 +0,0 @@ -/** - * \file - * mach support for x86 - * - * Authors: - * Geoff Norton (gnorton@novell.com) - * - * (C) 2010 Novell, Inc. - */ - -#include - -#if defined(__MACH__) -#include -#include -#include -#include "utils/mono-sigcontext.h" -#include "mach-support.h" - -// For reg numbers -#include - -int -mono_mach_arch_get_mcontext_size (void) -{ - return sizeof (struct __darwin_mcontext32); -} - -void -mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context) -{ - x86_thread_state32_t *arch_state = (x86_thread_state32_t *) state; - x86_float_state32_t *arch_fpstate = (x86_float_state32_t *) fpstate; - struct __darwin_mcontext32 *ctx = (struct __darwin_mcontext32 *) context; - ctx->__ss = *arch_state; - ctx->__fs = *arch_fpstate; -} - -void -mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate) -{ - x86_thread_state32_t *arch_state = (x86_thread_state32_t *) state; - x86_float_state32_t *arch_fpstate = (x86_float_state32_t *) fpstate; - struct __darwin_mcontext32 *ctx = (struct __darwin_mcontext32 *) context; - *arch_state = ctx->__ss; - *arch_fpstate = ctx->__fs; -} - -void -mono_mach_arch_thread_states_to_mono_context (thread_state_t state, thread_state_t fpstate, MonoContext *context) -{ - x86_thread_state32_t *arch_state = (x86_thread_state32_t *) state; - x86_float_state32_t *arch_fpstate = (x86_float_state32_t *) state; - context->eax = arch_state->__eax; - context->ebx = arch_state->__ebx; - context->ecx = arch_state->__ecx; - context->edx = arch_state->__edx; - context->ebp = arch_state->__ebp; - context->esp = arch_state->__esp; - context->esi = arch_state->__edi; - context->edi = arch_state->__esi; - context->eip = arch_state->__eip; - context->fregs [X86_XMM0] = arch_fpstate->__fpu_xmm0; - context->fregs [X86_XMM1] = arch_fpstate->__fpu_xmm1; - context->fregs [X86_XMM2] = arch_fpstate->__fpu_xmm2; - context->fregs [X86_XMM3] = arch_fpstate->__fpu_xmm3; - context->fregs [X86_XMM4] = arch_fpstate->__fpu_xmm4; - context->fregs [X86_XMM5] = arch_fpstate->__fpu_xmm5; - context->fregs [X86_XMM6] = arch_fpstate->__fpu_xmm6; - context->fregs [X86_XMM7] = arch_fpstate->__fpu_xmm7; -} - -int -mono_mach_arch_get_thread_state_size (void) -{ - return sizeof (x86_thread_state32_t); -} - -int -mono_mach_arch_get_thread_fpstate_size (void) -{ - return sizeof (x86_float_state32_t); -} - -kern_return_t -mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount) -{ -#if defined(HOST_WATCHOS) - g_error ("thread_get_state() is not supported by this platform"); -#else - x86_thread_state32_t *arch_state = (x86_thread_state32_t *) state; - x86_float_state32_t *arch_fpstate = (x86_float_state32_t *) fpstate; - kern_return_t ret; - - *count = x86_THREAD_STATE32_COUNT; - *fpcount = x86_FLOAT_STATE32_COUNT; - - ret = thread_get_state (thread, x86_THREAD_STATE32, (thread_state_t)arch_state, count); - if (ret != KERN_SUCCESS) - return ret; - - ret = thread_get_state (thread, x86_FLOAT_STATE32, (thread_state_t)arch_fpstate, fpcount); - return ret; -#endif -} - -kern_return_t -mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount) -{ -#if defined(HOST_WATCHOS) - g_error ("thread_set_state() is not supported by this platform"); -#else - kern_return_t ret; - ret = thread_set_state (thread, x86_THREAD_STATE32, state, count); - if (ret != KERN_SUCCESS) - return ret; - ret = thread_set_state (thread, x86_FLOAT_STATE32, fpstate, fpcount); - return ret; -#endif -} - -#else - -#include - -MONO_EMPTY_SOURCE_FILE (mach_support_x86); - -#endif diff --git a/src/mono/mono/utils/mach-support.h b/src/mono/mono/utils/mach-support.h index 0247db8bd131..9bc304604648 100644 --- a/src/mono/mono/utils/mach-support.h +++ b/src/mono/mono/utils/mach-support.h @@ -18,11 +18,6 @@ #include #define MONO_MACH_ARCH_SUPPORTED 1 -#if defined(__arm__) -typedef _STRUCT_MCONTEXT *mcontext_t; -#elif defined(__aarch64__) -typedef _STRUCT_MCONTEXT64 *mcontext_t; -#endif int mono_mach_arch_get_mcontext_size (void); void mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context); diff --git a/src/mono/mono/utils/mono-digest.h b/src/mono/mono/utils/mono-digest.h index 48c503652a4a..e470284e8069 100644 --- a/src/mono/mono/utils/mono-digest.h +++ b/src/mono/mono/utils/mono-digest.h @@ -1,26 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /** * \file - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to rpmMD5Init, call rpmMD5Update as - * needed on buffers full of bytes, and then call rpmMD5Final, which - * will fill a supplied 16-byte array with the digest. - */ - -/* parts of this file are : - * Written March 1993 by Branko Lankester - * Modified June 1993 by Colin Plumb for altered md5.c. - * Modified October 1995 by Erik Troan for RPM */ @@ -36,35 +16,9 @@ #include #define MonoSHA1Context CC_SHA1_CTX -#define MonoMD5Context CC_MD5_CTX #else -typedef struct { - guint32 buf[4]; - guint32 bits[2]; - guchar in[64]; - gint doByteReverse; -} MonoMD5Context; - -#endif - -MONO_API void mono_md5_get_digest (const guchar *buffer, gint buffer_size, guchar digest[16]); - -/* use this one when speed is needed */ -/* for use in provider code only */ -MONO_API void mono_md5_get_digest_from_file (const gchar *filename, guchar digest[16]); - -/* raw routines */ -MONO_API void mono_md5_init (MonoMD5Context *ctx); -MONO_API void mono_md5_update (MonoMD5Context *ctx, const guchar *buf, guint32 len); -MONO_API void mono_md5_final (MonoMD5Context *ctx, guchar digest[16]); - -uint64_t -mono_md5_ctx_byte_length (MonoMD5Context *ctx); - -#if !HAVE_COMMONCRYPTO_COMMONDIGEST_H - typedef struct { guint32 state[5]; guint32 count[2]; diff --git a/src/mono/mono/utils/mono-md5.c b/src/mono/mono/utils/mono-md5.c deleted file mode 100644 index dad02ffe06af..000000000000 --- a/src/mono/mono/utils/mono-md5.c +++ /dev/null @@ -1,415 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/** - * \file - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MonoMD5Context structure, pass it to mono_md5_init, call mono_md5_update as - * needed on buffers full of bytes, and then call md5_Final, which - * will fill a supplied 16-byte array with the digest. - */ - -/* parts of this file are : - * Written March 1993 by Branko Lankester - * Modified June 1993 by Colin Plumb for altered md5.c. - * Modified October 1995 by Erik Troan for RPM - */ - - -#include -#include -#include "mono-digest.h" - -#if HAVE_COMMONCRYPTO_COMMONDIGEST_H - -// CC_MD5_* API is deprecated on macOS 10.15 -#if defined(__APPLE__) && defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif - -/** - * mono_md5_init: - */ -void -mono_md5_init (MonoMD5Context *ctx) -{ - CC_MD5_Init (ctx); -} - -/** - * mono_md5_update: - */ -void -mono_md5_update (MonoMD5Context *ctx, const guchar *buf, guint32 len) -{ - CC_MD5_Update (ctx, buf, len); -} - -/** - * mono_md5_final: - */ -void -mono_md5_final (MonoMD5Context *ctx, guchar digest[16]) -{ - CC_MD5_Final (digest, ctx); -} - -uint64_t -mono_md5_ctx_byte_length (MonoMD5Context *ctx) -{ - return ctx->num; -} - -#if defined(__APPLE__) && defined(__clang__) -#pragma clang diagnostic pop -#endif - -#else - -static void md5_transform (guint32 buf[4], const guint32 in[16]); - -static gint _ie = 0x44332211; -static union _endian { gint i; gchar b[4]; } *_endian = (union _endian *)&_ie; -#define IS_BIG_ENDIAN() (_endian->b[0] == '\x44') -#define IS_LITTLE_ENDIAN() (_endian->b[0] == '\x11') - - -/* - * Note: this code is harmless on little-endian machines. - */ -static void -_byte_reverse (guchar *buf, guint32 longs) -{ - guint32 t; - do { - t = (guint32) ((guint32) buf[3] << 8 | buf[2]) << 16 | - ((guint32) buf[1] << 8 | buf[0]); - *(guint32 *) buf = t; - buf += 4; - } while (--longs); -} - -/** - * mono_md5_init: Initialise an md5 context object - * @ctx: md5 context - * - * Initialise an md5 buffer. - * - **/ -void -mono_md5_init (MonoMD5Context *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; - - if (IS_BIG_ENDIAN()) - ctx->doByteReverse = 1; - else - ctx->doByteReverse = 0; -} - - - -/** - * mono_md5_update: add a buffer to md5 hash computation - * @ctx: conetxt object used for md5 computaion - * @buf: buffer to add - * @len: buffer length - * - * Update context to reflect the concatenation of another buffer full - * of bytes. Use this to progressively construct an md5 hash. - **/ -void -mono_md5_update (MonoMD5Context *ctx, const guchar *buf, guint32 len) -{ - guint32 t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((guint32) len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) { - guchar *p = (guchar *) ctx->in + t; - - t = 64 - t; - if (len < t) { - memcpy (p, buf, len); - return; - } - memcpy (p, buf, t); - if (ctx->doByteReverse) - _byte_reverse (ctx->in, 16); - md5_transform (ctx->buf, (guint32 *) ctx->in); - buf += t; - len -= t; - } - /* Process data in 64-byte chunks */ - - while (len >= 64) { - memcpy (ctx->in, buf, 64); - if (ctx->doByteReverse) - _byte_reverse (ctx->in, 16); - md5_transform (ctx->buf, (guint32 *) ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memcpy (ctx->in, buf, len); -} - - - - - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -/** - * mono_md5_final: copy the final md5 hash to a bufer - * @digest: 16 bytes buffer - * @ctx: context containing the calculated md5 - * - * copy the final md5 hash to a bufer - **/ -void -mono_md5_final (MonoMD5Context *ctx, guchar digest[16]) -{ - guint32 count; - guchar *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset (p, 0, count); - if (ctx->doByteReverse) - _byte_reverse (ctx->in, 16); - md5_transform (ctx->buf, (guint32 *) ctx->in); - - /* Now fill the next block with 56 bytes */ - memset (ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset (p, 0, count - 8); - } - if (ctx->doByteReverse) - _byte_reverse (ctx->in, 14); - - /* Append length in bits and transform */ - ((guint32 *) ctx->in)[14] = ctx->bits[0]; - ((guint32 *) ctx->in)[15] = ctx->bits[1]; - - md5_transform (ctx->buf, (guint32 *) ctx->in); - if (ctx->doByteReverse) - _byte_reverse ((guchar *) ctx->buf, 4); - memcpy (digest, ctx->buf, 16); -} - -uint64_t -mono_md5_ctx_byte_length (MonoMD5Context *ctx) -{ - uint64_t lo = ((uint64_t)ctx->bits[0]) >> 3; - uint64_t hi = ((uint64_t)ctx->bits[1]) << 29; - return hi + lo; -} - - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. md5_Update blocks - * the data and converts bytes into longwords for this routine. - */ -static void -md5_transform (guint32 buf[4], const guint32 in[16]) -{ - guint32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP (F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP (F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP (F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP (F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP (F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP (F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP (F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP (F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP (F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP (F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP (F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP (F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP (F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP (F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP (F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP (F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP (F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP (F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP (F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP (F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP (F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP (F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP (F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP (F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP (F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP (F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP (F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP (F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP (F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP (F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP (F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP (F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP (F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP (F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP (F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP (F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP (F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP (F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP (F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP (F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP (F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP (F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP (F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP (F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP (F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP (F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP (F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP (F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP (F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP (F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP (F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP (F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP (F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP (F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP (F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP (F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP (F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP (F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP (F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP (F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP (F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP (F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP (F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP (F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -#endif - - -/** - * mono_md5_get_digest: - * \param buffer byte buffer - * \param buffer_size buffer size (in bytes) - * \param digest 16-byte buffer receiving the hash code. - * - * Get the MD5 hash of a buffer. The result is put in - * the 16-byte buffer \p digest. - */ -void -mono_md5_get_digest (const guchar *buffer, gint buffer_size, guchar digest[16]) -{ - MonoMD5Context ctx; - - mono_md5_init (&ctx); - mono_md5_update (&ctx, buffer, buffer_size); - mono_md5_final (&ctx, digest); - -} - - -/** - * mono_md5_get_digest_from_file: - * \param filename file name - * \param digest 16-byte buffer receiving the hash code. - * - * Get the MD5 hash of a file. The result is put in - * the 16-byte buffer \p digest. - * - * If an IO error happens the value in \p digest is not updated. - */ -void -mono_md5_get_digest_from_file (const gchar *filename, guchar digest[16]) -{ - MonoMD5Context ctx; - guchar tmp_buf[1024]; - gint nb_bytes_read; - FILE *fp; - - mono_md5_init (&ctx); - fp = fopen(filename, "r"); - if (!fp) { - return; - } - - while ((nb_bytes_read = (gint)fread (tmp_buf, sizeof (guchar), 1024, fp)) > 0) - mono_md5_update (&ctx, tmp_buf, nb_bytes_read); - - if (ferror(fp)) { - fclose(fp); - return; - } else { - fclose(fp); - } - - mono_md5_final (&ctx, digest); -} - - - - diff --git a/src/mono/mono/utils/mono-mmap-wasm.c b/src/mono/mono/utils/mono-mmap-wasm.c index b2f417b08603..aef7bfb9c3be 100644 --- a/src/mono/mono/utils/mono-mmap-wasm.c +++ b/src/mono/mono/utils/mono-mmap-wasm.c @@ -22,6 +22,9 @@ #include "mono-proclib.h" #include #include +#include + +#include "mono-wasm-pagemgr.h" #define BEGIN_CRITICAL_SECTION do { \ MonoThreadInfo *__info = mono_thread_info_current_unchecked (); \ @@ -34,6 +37,9 @@ int mono_pagesize (void) { + if (mono_opt_wasm_mmap) + return MWPM_PAGE_SIZE; + static int saved_pagesize = 0; if (saved_pagesize) @@ -108,7 +114,16 @@ valloc_impl (void *addr, size_t size, int flags, MonoMemAccountType type) mflags |= MAP_PRIVATE; BEGIN_CRITICAL_SECTION; - ptr = mmap (addr, size, prot, mflags, -1, 0); + if (mono_opt_wasm_mmap) { + // FIXME: Make this work if the requested address range is free + if ((flags & MONO_MMAP_FIXED) && addr) + return NULL; + + ptr = mwpm_alloc_range (size, 1); + if (!ptr) + return NULL; + } else + ptr = mmap (addr, size, prot, mflags, -1, 0); END_CRITICAL_SECTION; if (ptr == MAP_FAILED) @@ -142,6 +157,10 @@ typedef struct { void* mono_valloc_aligned (size_t size, size_t alignment, int flags, MonoMemAccountType type) { + // We don't need padding if the alignment is compatible with the page size + if (mono_opt_wasm_mmap && ((MWPM_PAGE_SIZE % alignment) == 0)) + return valloc_impl (NULL, size, flags, type); + /* Allocate twice the memory to be able to put the block on an aligned address */ char *mem = (char *) valloc_impl (NULL, size + alignment, flags, type); char *aligned; @@ -175,13 +194,22 @@ mono_vfree (void *addr, size_t length, MonoMemAccountType type) * mono_valloc_align (), free the original mapping. */ BEGIN_CRITICAL_SECTION; - munmap (info->addr, info->size); + if (mono_opt_wasm_mmap) + mwpm_free_range (info->addr, info->size); + else + munmap (info->addr, info->size); END_CRITICAL_SECTION; g_free (info); g_hash_table_remove (valloc_hash, addr); } else { + // FIXME: We could be trying to unmap part of an aligned mapping, in which case the + // hash lookup failed because addr isn't exactly the start of the mapping. + // Ideally if the custom page manager is enabled, we won't have done aligned alloc. BEGIN_CRITICAL_SECTION; - munmap (addr, length); + if (mono_opt_wasm_mmap) + mwpm_free_range (addr, length); + else + munmap (addr, length); END_CRITICAL_SECTION; } diff --git a/src/mono/mono/utils/mono-mmap.h b/src/mono/mono/utils/mono-mmap.h index 64591f106eab..fcf24bbea59c 100644 --- a/src/mono/mono/utils/mono-mmap.h +++ b/src/mono/mono/utils/mono-mmap.h @@ -22,7 +22,8 @@ enum { MONO_MMAP_ANON = 1 << 6, MONO_MMAP_FIXED = 1 << 7, MONO_MMAP_32BIT = 1 << 8, - MONO_MMAP_JIT = 1 << 9 + MONO_MMAP_JIT = 1 << 9, + MONO_MMAP_NOZERO = 1 << 10, }; typedef enum { diff --git a/src/mono/mono/utils/mono-wasm-pagemgr.c b/src/mono/mono/utils/mono-wasm-pagemgr.c new file mode 100644 index 000000000000..d3a25a0ec4b8 --- /dev/null +++ b/src/mono/mono/utils/mono-wasm-pagemgr.c @@ -0,0 +1,490 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include +#include "mono-wasm-pagemgr.h" +#include +#include +#include +#include +#include + +#ifndef DISABLE_THREADS +#include +#endif + +// #define MWPM_LOGGING +// #define MWPM_STATS + +typedef enum { + MWPM_MARK_DEAD_PAGES, + MWPM_MARK_NEW_PAGES, + MWPM_FREE_TO_ALLOCATED, + MWPM_FREE_TO_ALLOCATED_ZEROED, + MWPM_ALLOCATED_TO_FREE, +} page_action; + +#define is_page_free(state) (state & MWPM_FREE_BIT) +#define is_page_owned(state) (state & MWPM_STATE_MASK) +#define is_page_in_use(state) ((state & MWPM_STATE_MASK) == MWPM_ALLOCATED) +#define get_page_skip_count(state) (state & MWPM_SKIP_MASK) + +typedef uint8_t mwpm_page_state; + +static mono_mutex_t mutex; +static uint8_t page_table[MWPM_MAX_PAGES]; +#ifdef DISABLE_THREADS +static uint8_t is_initialized = 0; +#else +static once_flag is_initialized = ONCE_FLAG_INIT; +#endif +static uint32_t + // The index of the first page that we control. Not all pages after this + // necessarily belong to us, but scans can start here. + first_controlled_page_index = UINT32_MAX, + // The index of the last page we've allocated. Not all pages between this + // and first_controlled_page_index belong to us, but scans can end here. + last_controlled_page_index = 0; +static uint8_t *prev_waste_start = NULL, + *prev_waste_end = NULL; + +static inline void * +address_from_page_index (uint32_t page_index) { + uint64_t address = ((uint64_t)page_index * MWPM_PAGE_SIZE); + g_assert (address < UINT32_MAX); + return (void *)(uint32_t)address; +} + +static inline uint32_t +first_page_from_address (void *addr) { + return ((uint64_t)addr) / MWPM_PAGE_SIZE; +} + +static inline uint32_t +page_count_from_size (size_t size) { + return ((size + MWPM_PAGE_SIZE - 1) / MWPM_PAGE_SIZE); +} + +static inline uint32_t +last_page_of_range (void *addr, size_t size) { + uint32_t page_count_rounded_up = page_count_from_size (size), + first_page = first_page_from_address (addr); + return first_page + page_count_rounded_up - 1; +} + +static inline const char * +get_state_name (uint8_t state) { + switch (state & MWPM_STATE_MASK) { + case MWPM_EXTERNAL: + return "external"; + case MWPM_FREE_DIRTY: + return "dirty"; + case MWPM_FREE_ZEROED: + return "zeroed"; + case MWPM_ALLOCATED: + return "in use"; + default: + g_assert_not_reached (); + } +} + +static inline mwpm_page_state +encode_page_state (uint8_t bits, uint32_t skip_count) { + // We encode state into the page table like so: + // The top two bits are the free bit and the meta bit. + // For a free page, the meta bit indicates whether it is zeroed. + // For an occupied page, the meta bit indicates whether we control it. + // The remaining 6 bits encode the "skip count", which is a promise that + // the following N pages have the same state as the current page. + // The skip count allows us to jump forward safely during scans for free + // pages so that we don't have to do a full linear scan of the page table. + if (skip_count > MWPM_SKIP_MASK) + skip_count = MWPM_SKIP_MASK; + + return (bits & MWPM_STATE_MASK) | (skip_count & MWPM_SKIP_MASK); +} + +static void +cleanup_preceding_pages (uint32_t successor_page) { + uint32_t first_page = successor_page > 64 + ? successor_page - 64 + : 0; + + for (uint32_t i = first_page; i < successor_page; i++) { + mwpm_page_state page_state = page_table[i]; + // for a skip_count of 0 we will skip exactly one page (otherwise we would + // get stuck on pages with a 0 skip count). so the maximum skip value is + // distance - 1 to produce an actual skip of distance pages + uint32_t maximum_skip_value = successor_page - i - 1; + if (maximum_skip_value > MWPM_SKIP_MASK) + maximum_skip_value = MWPM_SKIP_MASK; + if (get_page_skip_count (page_state) <= maximum_skip_value) + continue; + +#if defined(MWPM_LOGGING) + g_print ( + "Repairing invalid skip value in predecessor page %u: %s %u -> %u\n", + i, get_state_name (page_state), get_page_skip_count (page_state), + maximum_skip_value + ); +#endif + page_table[i] = encode_page_state (page_state & MWPM_STATE_MASK, maximum_skip_value); + } +} + +static void +transition_page_states (page_action action, uint32_t first_page, uint32_t page_count) { + if (page_count == 0) + return; + + g_assert (first_page < MWPM_MAX_PAGES); + + uint32_t last_page = first_page + (page_count - 1); + g_assert (last_page >= first_page); + + g_assert (last_page < MWPM_MAX_PAGES); + + // POSIX specifies that munmap () on an address range that isn't mapped has no, + // effect, so we need to make sure that it's harmless to try and unmap pages we + // don't control. We can't use memset since it might trample UNKNOWN pages. + for (uint32_t i = first_page, skip_value = page_count - 1; i <= last_page; i++) { + mwpm_page_state page_state = page_table[i]; + + // TODO: Remove the duplication in here + switch (action) { + case MWPM_MARK_DEAD_PAGES: + g_assert (!is_page_owned (page_state)); + page_table[i] = encode_page_state (MWPM_EXTERNAL, skip_value--); + break; + case MWPM_MARK_NEW_PAGES: + g_assert (!is_page_owned (page_state)); + page_table[i] = encode_page_state (MWPM_FREE_ZEROED, skip_value--); + break; + case MWPM_FREE_TO_ALLOCATED: + g_assert (is_page_free (page_state)); + page_table[i] = encode_page_state (MWPM_ALLOCATED, skip_value--); + break; + case MWPM_FREE_TO_ALLOCATED_ZEROED: + g_assert (is_page_free (page_state)); + page_table[i] = encode_page_state (MWPM_ALLOCATED, skip_value--); + if (!(page_state & MWPM_META_BIT)) + // TODO: Don't recalculate the address from scratch each time + memset (address_from_page_index (i), 0, MWPM_PAGE_SIZE); + break; + case MWPM_ALLOCATED_TO_FREE: + // FIXME: Can we generate correct skip_value here? This is used + // by munmap, which is valid to call even on pages that are not mapped + if (is_page_in_use (page_state)) + page_table[i] = encode_page_state (MWPM_FREE_DIRTY, 0); + break; + default: + g_assert_not_reached (); + break; + } + } + + if (action == MWPM_ALLOCATED_TO_FREE) + cleanup_preceding_pages (first_page); +} + +static void +print_stats () { +#if defined(MWPM_LOGGING) || defined(MWPM_STATS) + uint32_t in_use = 0, free = 0, unallocated = 0, + max_run = 0, current_run = 0; + + for (uint32_t i = first_controlled_page_index; i <= last_controlled_page_index; i++) { + switch (page_table[i] & MWPM_STATE_MASK) { + case MWPM_ALLOCATED: + in_use++; + current_run = 0; + break; + + case MWPM_FREE_DIRTY: + case MWPM_FREE_ZEROED: + free++; + current_run++; + if (current_run > max_run) + max_run = current_run; + break; + + default: + unallocated++; + current_run = 0; + break; + } + } + + uint32_t total = in_use + free; // + unallocated; + g_print ( + "sbrk(0)==%u. %u pages in use (%f%%), %u pages free, %u pages unknown. largest possible allocation: %u pages\n", + (uint32_t)sbrk(0), in_use, in_use * 100.0 / total, free, unallocated, max_run + ); +#endif +} + +static void * +acquire_new_pages_initialized (uint32_t page_count) { + if (page_count < 1) + return NULL; + // Pad the allocation with an extra page, this will create waste bytes at the + // start and end we can use to align the resulting allocation. We will try + // to recover the waste if possible + uint64_t bytes = (page_count + 1) * MWPM_PAGE_SIZE; + uint32_t recovered_bytes = 0; + if (bytes >= UINT32_MAX) + return NULL; + + // We know that on WASM, sbrk grows the heap as necessary in order to return, + // a region of N zeroed bytes, which isn't necessarily aligned or page-sized + uint8_t *allocation = sbrk ((uint32_t)bytes); + + if (allocation == (uint8_t *)-1) { + // HACK: It is theoretically possible for sbrk to fail in a non-OOM condition + // due to identical bugs in v8 and spidermonkey, so retry exactly once. + allocation = sbrk ((uint32_t)bytes); + if (allocation == (uint8_t *)-1) { +#ifdef MWPM_LOGGING + g_print ("mwpm failed to acquire memory\n"); +#endif + return NULL; + } else { + g_print ("MWPM WARNING: sbrk() failed once, then succeeded. Continuing.\n"); + } + } + + uint8_t *allocation_end = allocation + bytes; + + g_assert (allocation_end != allocation); + + // If nobody else has called sbrk since we did, stitch the allocations together + // to eliminate the wasted page in the middle. + if (prev_waste_start && (prev_waste_end == allocation)) { + recovered_bytes = allocation - prev_waste_start; + allocation = prev_waste_start; + } else { + // Update the dead pages that were allocated by someone else via sbrk() + // so that they have skip data + uint32_t first_dead_page = first_page_from_address (prev_waste_end), + dead_page_count = page_count_from_size (allocation - prev_waste_end); + transition_page_states (MWPM_MARK_DEAD_PAGES, first_dead_page, dead_page_count); + } + + uint8_t *result = allocation; + // Unfortunately emscripten libc doesn't page-align sbrk's return value. + uint32_t realignment = MWPM_PAGE_SIZE - (((uint64_t)result) % MWPM_PAGE_SIZE); + if (realignment < MWPM_PAGE_SIZE) { + result += realignment; + g_assert ((((uint64_t)result) % MWPM_PAGE_SIZE) == 0); + } + + // Figure out how many wasted bytes are hanging off the end of our last page. + page_count = (allocation_end - result) / MWPM_PAGE_SIZE; + g_assert (page_count); + // Record the region of wasted bytes we allocated, so we can try to use it later. + prev_waste_start = result + (page_count * MWPM_PAGE_SIZE); + prev_waste_end = allocation_end; + + // Mark all the allocated pages as free and zeroed + uint32_t first_page_index = first_page_from_address (result), + last_page_index = first_page_index + page_count - 1; + + if ((first_page_index >= MWPM_MAX_PAGES) || (last_page_index >= MWPM_MAX_PAGES)) { +#ifdef MWPM_LOGGING + g_print ("mwpm failed to acquire pages because resulting page index was out of range: %u-%u\n", first_page_index, last_page_index); +#endif + return NULL; + } + + // g_print ("mwpm allocated %u bytes (%u pages) starting at @%u (%u recovered)\n", (uint32_t)bytes, page_count, (uint32_t)allocation, recovered_bytes); + transition_page_states (MWPM_MARK_NEW_PAGES, first_page_index, page_count); + print_stats (); + last_controlled_page_index = last_page_index; + return result; +} + +static inline void +free_pages_initialized (uint32_t first_page, uint32_t page_count) { + // expected behavior: freeing UNKNOWN pages leaves them unknown. + // freeing FREE_ZEROED pages leaves them zeroed. + // freeing ALLOCATED or FREE_DIRTY pages makes them FREE_DIRTY. + transition_page_states (MWPM_ALLOCATED_TO_FREE, first_page, page_count); +} + +static uint32_t +find_n_free_pages_in_range (uint32_t start_scan_where, uint32_t end_scan_where, uint32_t page_count) { + if (page_count == 0) + return UINT32_MAX; + + uint32_t i = start_scan_where; + + while (i <= end_scan_where) { + uint8_t found_obstruction = 0; + uint32_t j = i + page_count - 1; + if (j > last_controlled_page_index) + break; + + // Avoid worst case scenario of starting on an occupied page, then scanning + // backwards through a bunch of free pages to arrive at the occupied one + mwpm_page_state page_state = page_table[i]; + if (!is_page_free (page_state)) { + uint32_t skip_count = get_page_skip_count (page_state) + 1; + if (skip_count < 1) + skip_count = 1; + i += skip_count; + +#ifdef ENABLE_CHECKED_BUILD + g_assert (!is_page_free (page_table[i - 1])); +#endif + +#ifdef MWPM_LOGGING + if (skip_count > 1) + g_print ( + "scan skipping %u %s page(s) (head); new page is #%u with state %s\n", + skip_count, get_state_name (page_state), + i, get_state_name (page_table[i]) + ); +#endif + + continue; + } + + // TODO: If we find a free page with a skip count in it, that would indicate + // that there are N sequential free pages left we can claim without doing + // the scan below. + + // Scan backwards from the last candidate page to look for any non-free pages + // the first non-free page we find is the next place we will search from. + for (; j >= i; j--) { + page_state = page_table[j]; + + if (!is_page_free (page_state)) { + // Skip multiple pages + uint32_t skip_count = get_page_skip_count (page_state) + 1; + if (skip_count < 1) + skip_count = 1; + i = j + skip_count; + +#ifdef ENABLE_CHECKED_BUILD + g_assert (!is_page_free (page_table[i - 1])); +#endif + +#ifdef MWPM_LOGGING + if (skip_count > 1) + g_print ( + "scan skipping %u %s page(s) (tail); new page is #%u with state %s\n", + skip_count, get_state_name (page_state), + i, get_state_name (page_table[i]) + ); +#endif + found_obstruction = 1; + break; + } + } + + if (found_obstruction) + continue; + + // We scanned page_count pages starting from i and they were all free. + return i; + } + + return UINT32_MAX; +} + +// Scans all controlled pages to look for at least page_count free pages. +static uint32_t +find_n_free_pages (uint32_t page_count) { + // Start scanning from the beginning. This ensures we will try to grab small allocations + // from the front of the page table, and large allocations from anywhere we can find. + // This does make scans slower, but other approaches I tried have much worse fragmentation. + uint32_t result = find_n_free_pages_in_range (first_controlled_page_index, last_controlled_page_index, page_count); + return result; +} + +static void +mwpm_init () { + mono_os_mutex_init_recursive (&mutex); + // Set the entire page table to 'unknown state'. As we acquire pages from sbrk, we will + // set those respective ranges in the table to a known state. + memset (page_table, MWPM_EXTERNAL, sizeof(page_table)); + void *first_controlled_page_address = acquire_new_pages_initialized (MWPM_MINIMUM_PAGE_COUNT); + g_assert (first_controlled_page_address); + first_controlled_page_index = first_page_from_address (first_controlled_page_address); +} + +static inline void +mwpm_ensure_initialized () { +#ifdef DISABLE_THREADS + if (is_initialized) + return; + is_initialized = 1; + mwpm_init (); +#else + call_once (&is_initialized, mwpm_init); +#endif +} + +void * +mwpm_alloc_range (size_t size, uint8_t zeroed) { + void *result = NULL; + if (!size) + return result; + + mwpm_ensure_initialized (); + mono_os_mutex_lock (&mutex); + + uint32_t page_count = page_count_from_size (size), + first_existing_page = find_n_free_pages (page_count), + allocation_page_count = page_count; + + // If we didn't find existing pages to service our alloc, + if (first_existing_page == UINT32_MAX) { + // g_print ("mwpm could not find %u free pages\n", page_count); + if (allocation_page_count < MWPM_MINIMUM_PAGE_COUNT) + allocation_page_count = MWPM_MINIMUM_PAGE_COUNT; + // Ensure we have space for the whole allocation + void *start_of_new_pages = acquire_new_pages_initialized (allocation_page_count); + if (start_of_new_pages) { + // FIXME: Scan backwards from the new allocation to look for free pages + // before it that we can use to reduce fragmentation + result = start_of_new_pages; + } else { +#ifdef MWPM_LOGGING + g_print ("mwpm failed to acquire new pages\n"); +#endif + goto exit; + } + } else { + result = address_from_page_index (first_existing_page); + // g_print ("mwpm found %u free pages at %u\n", page_count, (uint32_t) result); + } + + if (!result) + goto exit; + + uint32_t first_result_page = first_page_from_address (result); + transition_page_states (zeroed ? MWPM_FREE_TO_ALLOCATED_ZEROED : MWPM_FREE_TO_ALLOCATED, first_result_page, page_count); + +#ifdef MWPM_LOGGING + g_print ("mwpm allocated %u bytes at %u\n", size, (uint32_t)result); +#endif + +exit: + mono_os_mutex_unlock (&mutex); + return result; +} + +void +mwpm_free_range (void *base, size_t size) { + mwpm_ensure_initialized (); + + mono_os_mutex_lock (&mutex); + uint32_t first_page = first_page_from_address (base), + page_count = page_count_from_size (size); + free_pages_initialized (first_page, page_count); + mono_os_mutex_unlock (&mutex); +#ifdef MWPM_LOGGING + g_print ("mwpm freed %u bytes at %u\n", size, (uint32_t)base); +#endif +} diff --git a/src/mono/mono/utils/mono-wasm-pagemgr.h b/src/mono/mono/utils/mono-wasm-pagemgr.h new file mode 100644 index 000000000000..1720ffaf0967 --- /dev/null +++ b/src/mono/mono/utils/mono-wasm-pagemgr.h @@ -0,0 +1,87 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Provides a simple, efficient implementation of anonymous mmap/munmap for WASM. +// The emscripten libc version of mmap for anonymous mappings is slow during startup +// because it spends a lot of time zeroing already-zeroed pages, and in some cases +// the allocated pages will then get zeroed one more time by a malloc0 operation. + +// This is distinct from malloc/free in that we support freeing a subset of an allocation, +// i.e. you can allocate 4 pages and then free page 1, leaving pages 0/2/3 allocated. + +// Note that pages mapped by MWPM can't be unmapped by libc, and vice versa. + +#ifndef __MONO_UTILS_WASM_PAGEMGR_H__ +#define __MONO_UTILS_WASM_PAGEMGR_H__ + +#ifdef HOST_WASI +#ifndef DISABLE_THREADS +#error MWPM does not support multithreaded WASI due to lack of call_once +#endif +#endif + +#include +#include + +// 64KB (WASM native page size) +// NOTE: emscripten sbrk() allows you to allocate less than 1 page, and doesn't +// return page-aligned addresses. So this value can theoretically be smaller. +// Shrinking this would reduce wasted memory if callers try to mmap less than a +// whole page. My initial testing didn't show big improvements though, and it +// would make mmap (and to a lesser degree, munmap) have to scan/touch more pages. +// I tested with 16KB pages and it wasn't an improvement over 64KB. +// 8KB pages produces a slight reduction in total memory usage (1.3%). 4KB is worse. +#define MWPM_PAGE_SIZE (64 * 1024) + +// 4GB (even though JS can't consistently handle addresses above 2GB) +// System.Text.JSON.Tests needs to allocate more than 2GB... +#define MWPM_MAX_MEMORY ((1024UL * 1024UL * 1024UL) * 4UL) + +// The proper definition compiles down to 0 for some reason even if I put typecasts +// around it +// #define MWPM_MAX_PAGES (uint32_t)(MWPM_MAX_MEMORY / MWPM_PAGE_SIZE) +#define MWPM_MAX_PAGES (64 * 1024) + +// When allocating new zeroed pages, always allocate at least this many. +// This ensures that we don't waste a bunch of time allocating 1-2 pages at once. +// sbrk() also doesn't return page-aligned addresses, so this produces fewer +// wasted page fragments and in general ensures we can service larger allocations. +// Setting this constant incorrectly will cause higher fragmentation and higher +// memory usage, potentially causing OOM. Data from S.T.J test suite: +// (minimum count) (total pages allocated) (largest available space) +// 16 13677 363 +// 24 14675 340 +// 30 14653 192 +// 32 11399 463 +// 34 14412 338 +// 48 14460 461 +// 64 11767 230 +// 96 12986 96 +// 128 14059 321 +// 192 14686 289 +// 256 12281 256 +#define MWPM_MINIMUM_PAGE_COUNT 32 + +#define MWPM_FREE_BIT 0b10000000 +#define MWPM_META_BIT 0b01000000 +#define MWPM_STATE_MASK 0b11000000 +#define MWPM_SKIP_MASK 0b00111111 + +#define MWPM_FREE_ZEROED (uint8_t)(MWPM_FREE_BIT | MWPM_META_BIT) +#define MWPM_FREE_DIRTY (uint8_t)(MWPM_FREE_BIT) +#define MWPM_ALLOCATED (uint8_t)(MWPM_META_BIT) +#define MWPM_EXTERNAL (uint8_t)(0) + +// Allocate enough pages to hold size bytes of data, optionally ensuring they are zeroed. +// Zeroing memory on wasm is somewhat expensive, so use this option wisely! +void * +mwpm_alloc_range (size_t size, uint8_t zeroed); + +// Free all the pages containing the memory range from base to base+size-1. +// If the specified range does not occupy an entire page, the page will still +// be freed! This matches the specified behavior of posix munmap. +// base must be a multiple of MWPM_PAGE_SIZE. +void +mwpm_free_range (void *base, size_t size); + +#endif diff --git a/src/mono/mono/utils/options-def.h b/src/mono/mono/utils/options-def.h index 8cdbc942e1b8..bd33aea9e23b 100644 --- a/src/mono/mono/utils/options-def.h +++ b/src/mono/mono/utils/options-def.h @@ -59,9 +59,15 @@ DEFINE_BOOL_READONLY(readonly_flag, "readonly-flag", FALSE, "Example") DEFINE_BOOL(wasm_exceptions, "wasm-exceptions", FALSE, "Enable codegen for WASM exceptions") DEFINE_BOOL(aot_lazy_assembly_load, "aot-lazy-assembly-load", FALSE, "Load assemblies referenced by AOT images lazily") +#ifdef DISABLE_THREADS +DEFINE_BOOL(wasm_mmap, "wasm-mmap", TRUE, "Enable custom memory manager for WASM") +#else +// Disabled by default for MT because it breaks strcmp somehow (??????) +DEFINE_BOOL(wasm_mmap, "wasm-mmap", FALSE, "Enable custom memory manager for WASM") +#endif #if HOST_BROWSER -DEFINE_BOOL(interp_pgo_recording, "interp-pgo-recording", TRUE, "Record interpreter tiering information for automatic PGO") +DEFINE_BOOL(interp_pgo_recording, "interp-pgo-recording", FALSE, "Record interpreter tiering information for automatic PGO") #else DEFINE_BOOL(interp_pgo_recording, "interp-pgo-recording", FALSE, "Record interpreter tiering information for automatic PGO") DEFINE_BOOL(wasm_gc_safepoints, "wasm-gc-safepoints", FALSE, "Use GC safepoints on WASM") diff --git a/src/mono/mono/utils/options.c b/src/mono/mono/utils/options.c index 2a8dc6f60480..eb94a7c22057 100644 --- a/src/mono/mono/utils/options.c +++ b/src/mono/mono/utils/options.c @@ -10,13 +10,6 @@ #include "options.h" #include "mono/utils/mono-error-internals.h" -typedef enum { - MONO_OPTION_BOOL, - MONO_OPTION_BOOL_READONLY, - MONO_OPTION_INT, - MONO_OPTION_STRING -} MonoOptionType; - /* Define flags */ #define DEFINE_OPTION_FULL(option_type, ctype, c_name, cmd_name, def_value, comment) \ ctype mono_opt_##c_name = def_value; @@ -333,3 +326,22 @@ mono_options_get_as_json (void) g_string_free(result, FALSE); return result_str; } + +gboolean +mono_options_get (const char *name, MonoOptionType *type, void **value_address) +{ + GHashTable *hash = get_option_hash (); + OptionData *meta = (OptionData *)g_hash_table_lookup (hash, name); + + if (!meta) { + if (value_address) + *value_address = NULL; + return FALSE; + } + + if (type) + *type = meta->option_type; + if (value_address) + *value_address = meta->addr; + return TRUE; +} diff --git a/src/mono/mono/utils/options.h b/src/mono/mono/utils/options.h index e7f2906eeb05..27667e114af1 100644 --- a/src/mono/mono/utils/options.h +++ b/src/mono/mono/utils/options.h @@ -22,6 +22,13 @@ MONO_BEGIN_DECLS #include "options-def.h" MONO_END_DECLS +typedef enum { + MONO_OPTION_BOOL, + MONO_OPTION_BOOL_READONLY, + MONO_OPTION_INT, + MONO_OPTION_STRING +} MonoOptionType; + extern int mono_options_version; void mono_options_print_usage (void); @@ -31,4 +38,7 @@ void mono_options_parse_options (const char **args, int argc, int *out_argc, GPt /* returns a json blob representing the current values of all options */ char * mono_options_get_as_json (void); +gboolean +mono_options_get (const char *name, MonoOptionType *type, void **value_address); + #endif diff --git a/src/mono/msbuild/apple/build/AppleBuild.LocalBuild.props b/src/mono/msbuild/apple/build/AppleBuild.LocalBuild.props index ed8be7e3ac38..ce1751cc91bf 100644 --- a/src/mono/msbuild/apple/build/AppleBuild.LocalBuild.props +++ b/src/mono/msbuild/apple/build/AppleBuild.LocalBuild.props @@ -34,15 +34,19 @@ $([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackLocationToUse), 'runtimes', '$(TargetOS)-$(TargetArchitecture.ToLowerInvariant())', 'lib', '$(_NetCoreAppCurrent)')) $([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackLocationToUse), 'runtimes', '$(TargetOS)-$(TargetArchitecture.ToLowerInvariant())', 'native')) - $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AppleAppBuilder', 'Debug', '$(_NetCoreAppToolCurrent)')) - $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'LibraryBuilder', 'Debug', '$(_NetCoreAppToolCurrent)')) - $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'MonoAOTCompiler', 'Debug', '$(_NetCoreAppToolCurrent)')) - $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'MonoTargetsTasks', 'Debug', '$(_NetCoreAppToolCurrent)')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AppleAppBuilder', '$(Configuration)', '$(_NetCoreAppToolCurrent)')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'LibraryBuilder', '$(Configuration)', '$(_NetCoreAppToolCurrent)')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'MonoAOTCompiler', '$(Configuration)', '$(_NetCoreAppToolCurrent)')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'MonoTargetsTasks', '$(Configuration)', '$(_NetCoreAppToolCurrent)')) $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'mono', '$(TargetOS).$(TargetArchitecture).$(RuntimeConfig)')) $([MSBuild]::NormalizePath($(MonoArtifactsPath), 'cross', '$(TargetOS)-$(TargetArchitecture.ToLowerInvariant())')) <_MonoAotCrossCompilerPath>$([MSBuild]::NormalizePath($(MonoAotCrossDir), 'mono-aot-cross')) <_MonoAotCrossCompilerPath Condition="$([MSBuild]::IsOSPlatform('WINDOWS'))">$(_MonoAotCrossCompilerPath).exe + + $([MSBuild]::NormalizePath('$(ArtifactsBinDir)', 'ILLink.Tasks', '$(Configuration)', '$(_NetCoreAppToolCurrent)', 'build', 'Microsoft.NET.ILLink.Tasks.props')) + $([MSBuild]::NormalizePath('$(ArtifactsBinDir)', 'ILLink.Tasks', '$(Configuration)', '$(_NetCoreAppToolCurrent)', 'build', 'Microsoft.NET.ILLink.targets')) + <_ILLinkTasksAssembly>$([MSBuild]::NormalizePath('$(ArtifactsBinDir)', 'ILLink.Tasks', '$(Configuration)', '$(_NetCoreAppToolCurrent)', 'ILLink.Tasks.dll')) @@ -64,8 +68,9 @@ $([MSBuild]::NormalizeDirectory('$(BuildBaseDir)', 'aotsdk')) $(MicrosoftNetCoreAppRuntimePackLibDir) $(MicrosoftNetCoreAppRuntimePackNativeDir) - $([MSBuild]::NormalizePath('$(BuildBaseDir)', 'microsoft.net.illink.tasks', '$(_NetCoreAppToolCurrent)', 'build', 'Microsoft.NET.ILLink.targets')) - $([MSBuild]::NormalizePath('$(BuildBaseDir)', 'microsoft.net.illink.tasks', '$(_NetCoreAppToolCurrent)', 'ILLink.Tasks.dll')) + $([MSBuild]::NormalizePath('$(BuildBaseDir)', '$(_NetCoreAppToolCurrent)', 'build', ''Microsoft.NET.ILLink.Tasks.props'')) + $([MSBuild]::NormalizePath('$(BuildBaseDir)', '$(_NetCoreAppToolCurrent)', 'build', 'Microsoft.NET.ILLink.targets')) + <_ILLinkTasksAssembly>$([MSBuild]::NormalizePath('$(BuildBaseDir)', '$(_NetCoreAppToolCurrent)', 'ILLink.Tasks.dll')) <_MonoAotCrossCompilerPath>$([MSBuild]::NormalizePath($(MonoAotCrossDir), 'mono-aot-cross')) <_MonoAotCrossCompilerPath Condition="$([MSBuild]::IsOSPlatform('WINDOWS'))">$(_MonoAotCrossCompilerPath).exe @@ -83,6 +88,12 @@ $([MSBuild]::NormalizePath('$(MonoTargetsTasksDir)', 'MonoTargetsTasks.dll')) + + + + $(_ILLinkTasksAssembly) + + diff --git a/src/mono/msbuild/apple/build/AppleBuild.LocalBuild.targets b/src/mono/msbuild/apple/build/AppleBuild.LocalBuild.targets index 05bdce89bf84..a28bff240a64 100644 --- a/src/mono/msbuild/apple/build/AppleBuild.LocalBuild.targets +++ b/src/mono/msbuild/apple/build/AppleBuild.LocalBuild.targets @@ -34,8 +34,38 @@ false + + + true + $(NoWarn);IL2103;IL2105;IL2025;IL2111 + + + + + + + + + + + + + + + + + %(Filename)%(Extension) + + + + - + - + - + diff --git a/src/mono/msbuild/apple/data/ProxyProjectForAOTOnHelix.proj b/src/mono/msbuild/apple/data/ProxyProjectForAOTOnHelix.proj index e1a82cd4f7c2..0230c7d10d3a 100644 --- a/src/mono/msbuild/apple/data/ProxyProjectForAOTOnHelix.proj +++ b/src/mono/msbuild/apple/data/ProxyProjectForAOTOnHelix.proj @@ -7,7 +7,11 @@ $([MSBuild]::NormalizeDirectory($(TestRootDir), '..', 'extraFiles')) $([MSBuild]::NormalizeDirectory($(TestRootDir), '..', 'obj')) - _PrepareForAppleBuildAppOnHelix;$(AppleBuildDependsOn);_AfterAppleBuildOnHelix + ConfigureTrimming;_AdjustTrimmedAssembliesToBundle;$(AppleBuildDependsOn) + _PublishRuntimePack;_PrepareForAppleBuildAppOnHelix;$(AppleBuildDependsOn);_AfterAppleBuildOnHelix + + true + $(OriginalPublishDir) @@ -18,12 +22,9 @@ <_IsApplePlatform>true true <_targetOS>$(TargetOS) - - - true - + $(OriginalPublishDir) static @@ -41,6 +42,12 @@ false + + + + + + @@ -49,14 +56,14 @@ - + true AppleTestRunner.dll - + $(OriginalPublishDir) $(TestRootDir)AppBundle\ @@ -89,6 +96,13 @@ + + + + + + + + + + + + + + + diff --git a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets index fcf283375f82..d161db4b45c8 100644 --- a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets +++ b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets @@ -123,8 +123,9 @@ Copyright (c) .NET Foundation. All rights reserved. - $(AddWasmStaticWebAssetsDependsOn); ResolveWasmOutputs; + _GenerateBuildWasmBootJson; + $(AddWasmStaticWebAssetsDependsOn); $(GenerateBuildWasmBootJsonDependsOn); @@ -167,6 +168,9 @@ Copyright (c) .NET Foundation. All rights reserved. + + + @@ -278,10 +282,19 @@ Copyright (c) .NET Foundation. All rights reserved. + + + + + @@ -292,6 +305,8 @@ Copyright (c) .NET Foundation. All rights reserved. + + @@ -343,7 +358,9 @@ Copyright (c) .NET Foundation. All rights reserved. TargetFrameworkVersion="$(TargetFrameworkVersion)" ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)" ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" - IsPublish="false" /> + IsPublish="false" + IsAot="$(RunAOTCompilation)" + IsMultiThreaded="$(WasmEnableThreads)" /> @@ -375,6 +392,22 @@ Copyright (c) .NET Foundation. All rights reserved. + + + + + + + + @@ -449,8 +482,8 @@ Copyright (c) .NET Foundation. All rights reserved. - - <_NewWebCilPublishStaticWebAssetsCandidatesNoMetadata + + <_NewWebCilPublishStaticWebAssetsCandidatesNoMetadata Include="@(_NewWebCilPublishStaticWebAssetsCandidates)" RemoveMetadata="Integrity;Fingerprint" /> @@ -459,9 +492,18 @@ Copyright (c) .NET Foundation. All rights reserved. + + + + + + + + + @@ -511,7 +561,7 @@ Copyright (c) .NET Foundation. All rights reserved. - + <_PublishWasmBootJson Include="$(IntermediateOutputPath)blazor.publish.boot.json" @@ -532,7 +582,17 @@ Copyright (c) .NET Foundation. All rights reserved. BasePath="$(StaticWebAssetBasePath)" > + + + + + + @@ -586,7 +646,9 @@ Copyright (c) .NET Foundation. All rights reserved. TargetFrameworkVersion="$(TargetFrameworkVersion)" ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)" ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" - IsPublish="true" /> + IsPublish="true" + IsAot="$(RunAOTCompilation)" + IsMultiThreaded="$(WasmEnableThreads)" /> diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadManifest.json.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadManifest.json.in index 160fca74ac5b..86fcb96c1932 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadManifest.json.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadManifest.json.in @@ -8,6 +8,7 @@ "description": ".NET WebAssembly build tools", "packs": [ "Microsoft.NET.Runtime.WebAssembly.Sdk", + "Microsoft.NET.Sdk.WebAssembly.Pack", "Microsoft.NETCore.App.Runtime.Mono.browser-wasm", "Microsoft.NETCore.App.Runtime.AOT.Cross.browser-wasm" ], @@ -177,6 +178,10 @@ "kind": "Sdk", "version": "${PackageVersion}" }, + "Microsoft.NET.Sdk.WebAssembly.Pack": { + "kind": "library", + "version": "${PackageVersion}" + }, "Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk": { "kind": "Sdk", "version": "${PackageVersion}" diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.cs.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.cs.json index da1ee8979a0a..57460f86f637 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.cs.json +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.cs.json @@ -1,3 +1,5 @@ { - "workloads/wasm-tools/description": "Nástroje pro sestavení .NET WebAssembly" + "workloads/wasm-tools/description": "Nástroje pro sestavení .NET WebAssembly", + "workloads/wasm-experimental/description": "Experimentální nástroje .NET WebAssembly", + "workloads/runtimes-windows/description": "Runtime balíčky pro Windows" } \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.de.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.de.json index 3d4467d7b055..6632e9c176b4 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.de.json +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.de.json @@ -1,3 +1,5 @@ { - "workloads/wasm-tools/description": ".NET WebAssembly-Buildtools" + "workloads/wasm-tools/description": ".NET WebAssembly-Buildtools", + "workloads/wasm-experimental/description": "Experimentelle .NET WebAssembly-Tools", + "workloads/runtimes-windows/description": "Windows-Runtime-Pakete" } \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.en.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.en.json index 5bcb3f575d5d..16bae7ec7b88 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.en.json +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.en.json @@ -1,5 +1,5 @@ { "workloads/wasm-tools/description": ".NET WebAssembly build tools", - "workloads/wasm-tools-experimental/description": ".NET WebAssembly experimental tooling", + "workloads/wasm-experimental/description": ".NET WebAssembly experimental tooling", "workloads/runtimes-windows/description": "Windows Runtime Packs" } diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.es.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.es.json index 166e1db9fe81..45886c1b558f 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.es.json +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.es.json @@ -1,3 +1,5 @@ { - "workloads/wasm-tools/description": "Herramientas de compilación de WebAssembly de .NET" + "workloads/wasm-tools/description": "Herramientas de compilación de WebAssembly de .NET", + "workloads/wasm-experimental/description": "Herramientas experimentales .NET WebAssembly", + "workloads/runtimes-windows/description": "Paquetes de tiempo de ejecución de Windows" } \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.fr.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.fr.json index e660e45a264d..b3989d6c44a8 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.fr.json +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.fr.json @@ -1,3 +1,5 @@ { - "workloads/wasm-tools/description": "Outils de construction .NET WebAssembly" + "workloads/wasm-tools/description": "Outils de build .NET WebAssembly", + "workloads/wasm-experimental/description": "Outils expérimentaux .NET WebAssembly", + "workloads/runtimes-windows/description": "Packs d'exécution Windows" } \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.it.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.it.json index 6703c0025606..04a6fc30048c 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.it.json +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.it.json @@ -1,3 +1,5 @@ { - "workloads/wasm-tools/description": "Strumenti di compilazione WebAssembly .NET" + "workloads/wasm-tools/description": "Strumenti di compilazione WebAssembly .NET", + "workloads/wasm-experimental/description": "Strumenti sperimentali di .NET WebAssembly", + "workloads/runtimes-windows/description": "Pacchetti di Windows Runtime" } \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.ja.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.ja.json index fd3fe984155a..556dcea77eeb 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.ja.json +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.ja.json @@ -1,3 +1,5 @@ { - "workloads/wasm-tools/description": ".NET WebAssembly ビルド ツール" + "workloads/wasm-tools/description": ".NET WebAssembly ビルドツール", + "workloads/wasm-experimental/description": ".NET WebAssembly 実験的ツール", + "workloads/runtimes-windows/description": "Windows ランタイム パック" } \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.ko.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.ko.json index c5261248ff60..98c2a9e341d9 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.ko.json +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.ko.json @@ -1,3 +1,5 @@ { - "workloads/wasm-tools/description": ".NET WebAssembly 빌드 도구" + "workloads/wasm-tools/description": ".NET WebAssembly 빌드 도구", + "workloads/wasm-experimental/description": ".NET WebAssembly 실험 도구", + "workloads/runtimes-windows/description": "Windows 런타임 팩" } \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.pl.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.pl.json index 858653c73b52..ac42d4cbf51c 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.pl.json +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.pl.json @@ -1,3 +1,5 @@ { - "workloads/wasm-tools/description": "Narzędzia kompilacji zestawu WebAssembly platformy .NET" + "workloads/wasm-tools/description": "Narzędzia kompilacji zestawu WebAssembly platformy .NET", + "workloads/wasm-experimental/description": "Eksperymentalne narzędzia .NET WebAssembly", + "workloads/runtimes-windows/description": "Pakiety środowiska wykonawczego systemu Windows" } \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.pt-BR.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.pt-BR.json index a8dceaf324f2..95101d70547e 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.pt-BR.json +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.pt-BR.json @@ -1,3 +1,5 @@ { - "workloads/wasm-tools/description": "Ferramentas de build do .NET WebAssembly" + "workloads/wasm-tools/description": "Ferramentas de build para .NET WebAssembly", + "workloads/wasm-experimental/description": "Ferramentas experimentais para .NET WebAssembly", + "workloads/runtimes-windows/description": "Pacotes de tempo de execução do Windows" } \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.ru.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.ru.json index 102e67acdc2c..5831473984c7 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.ru.json +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.ru.json @@ -1,3 +1,5 @@ { - "workloads/wasm-tools/description": "Средства сборки WebAssembly .NET" + "workloads/wasm-tools/description": "Средства сборки WebAssembly .NET", + "workloads/wasm-experimental/description": "Экспериментальный инструментарий .NET WebAssembly", + "workloads/runtimes-windows/description": "Пакеты среды выполнения Windows" } \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.tr.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.tr.json index 34d4e3b66de9..5c2ae06b4482 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.tr.json +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.tr.json @@ -1,3 +1,5 @@ { - "workloads/wasm-tools/description": ".NET WebAssembly derleme araçları" + "workloads/wasm-tools/description": ".NET WebAssembly derleme araçları", + "workloads/wasm-experimental/description": ".NET WebAssembly deneysel araçlar", + "workloads/runtimes-windows/description": "Windows Çalışma Zamanı Paketleri" } \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.zh-Hans.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.zh-Hans.json index 360e1e5a5d1f..30205fa4f853 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.zh-Hans.json +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.zh-Hans.json @@ -1,3 +1,5 @@ { - "workloads/wasm-tools/description": ".NET WebAssembly 生成工具" + "workloads/wasm-tools/description": ".NET WebAssembly 生成工具", + "workloads/wasm-experimental/description": ".NET WebAssembly 实验工具", + "workloads/runtimes-windows/description": "Windows 运行时包" } \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.zh-Hant.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.zh-Hant.json index c5d85ecc0f5c..c63f2cb9f12e 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.zh-Hant.json +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/localize/WorkloadManifest.zh-Hant.json @@ -1,3 +1,5 @@ { - "workloads/wasm-tools/description": ".NET WebAssembly 組建工具" + "workloads/wasm-tools/description": ".NET WebAssembly 組建工具", + "workloads/wasm-experimental/description": ".NET WebAssembly 實驗工具", + "workloads/runtimes-windows/description": "Windows 運行時包" } \ No newline at end of file diff --git a/src/mono/sample/Directory.Build.props b/src/mono/sample/Directory.Build.props index 878089963028..2d5011ce41f8 100644 --- a/src/mono/sample/Directory.Build.props +++ b/src/mono/sample/Directory.Build.props @@ -5,14 +5,22 @@ true + - $HARNESS_RUNNER - $XHARNESS_OUT + $HARNESS_RUNNER + $XHARNESS_OUT + $XHARNESS_COMMAND + $XHARNESS_ARGS - - %HARNESS_RUNNER% - %XHARNESS_OUT% + %HARNESS_RUNNER% + %XHARNESS_OUT% + %XHARNESS_COMMAND% + %XHARNESS_ARGS% diff --git a/src/mono/sample/HelloWorld/HelloWorld.csproj b/src/mono/sample/HelloWorld/HelloWorld.csproj index cc052494b398..4f897f0fc562 100644 --- a/src/mono/sample/HelloWorld/HelloWorld.csproj +++ b/src/mono/sample/HelloWorld/HelloWorld.csproj @@ -1,9 +1,14 @@ + Exe $(NetCoreAppCurrent) true + true + true + normal + full + LLVMPath="$(MonoAotCrossDir)" + Mode="$(SampleAOTMode)" + > diff --git a/src/mono/sample/HelloWorld/Makefile b/src/mono/sample/HelloWorld/Makefile index afdfa16f3512..441c0ee488c2 100644 --- a/src/mono/sample/HelloWorld/Makefile +++ b/src/mono/sample/HelloWorld/Makefile @@ -6,19 +6,26 @@ MONO_CONFIG?=Debug MONO_ARCH?=$(shell . $(TOP)eng/common/native/init-os-and-arch.sh && echo $${arch}) TARGET_OS?=$(shell . $(TOP)eng/common/native/init-os-and-arch.sh && echo $${os}) AOT?=false +FULL_AOT?=false +TRIM?=false USE_LLVM?=false StripILCode?=false TrimmingEligibleMethodsOutputDirectory?= # #MIBC_PROFILE_PATH= -MONO_ENV_OPTIONS ?= +MONO_ENV_OPTIONS ?= +ifeq ($(FULL_AOT),true) +MONO_ENV_OPTIONS += --full-aot +endif publish: $(DOTNET) publish \ -c $(MONO_CONFIG) \ -r $(TARGET_OS)-$(MONO_ARCH) \ - /p:RunAOTCompilation=$(AOT) \ + /p:SampleUseAOT=$(AOT) \ + /p:SampleUseFullAOT=$(FULL_AOT) \ + /p:SampleTrim=$(TRIM) \ /p:MonoEnableLLVM=$(USE_LLVM) \ /p:StripILCode=$(StripILCode) \ /p:TrimmingEligibleMethodsOutputDirectory=$(TrimmingEligibleMethodsOutputDirectory) \ diff --git a/src/mono/sample/wasi/Directory.Build.props b/src/mono/sample/wasi/Directory.Build.props index 28a09db931ed..15caee9a376b 100644 --- a/src/mono/sample/wasi/Directory.Build.props +++ b/src/mono/sample/wasi/Directory.Build.props @@ -7,6 +7,8 @@ wasm wasi-wasm --> + $(TestArchiveRoot)wasmtimeonly/ + $(TestArchiveTestsRoot)$(OSPlatformConfig)/ diff --git a/src/mono/sample/wasm/DefaultBrowserSample.targets b/src/mono/sample/wasm/DefaultBrowserSample.targets index 2862ef1ddb76..af224ce9c48a 100644 --- a/src/mono/sample/wasm/DefaultBrowserSample.targets +++ b/src/mono/sample/wasm/DefaultBrowserSample.targets @@ -7,8 +7,10 @@ -1 true $(WasmXHarnessArgs) --web-server-use-cop - $(ExecXHarnessCmd) wasm test-browser --app=. --browser=Chrome $(XHarnessBrowserPathArg) $(WasmXHarnessArgs) --html-file=index.html --output-directory=$(XHarnessOutput) -- $(MSBuildProjectName).dll + $(ExecXHarnessVar) wasm $(XHarnessCommandVar) --app=. $(XHarnessBrowserPathArg) $(WasmXHarnessArgsVar) $(WasmXHarnessArgs) --html-file=index.html --output-directory=$(XHarnessOutputVar) -- $(MSBuildProjectName).dll true + $(TestArchiveRoot)chromeonly/ + $(TestArchiveTestsRoot)$(OSPlatformConfig)/ diff --git a/src/mono/sample/wasm/Directory.Build.targets b/src/mono/sample/wasm/Directory.Build.targets index c50573788018..5ec9cf77532f 100644 --- a/src/mono/sample/wasm/Directory.Build.targets +++ b/src/mono/sample/wasm/Directory.Build.targets @@ -31,6 +31,7 @@ Outputs=" bin/$(Configuration)/AppBundle/dotnet.native.wasm; bin/$(Configuration)/AppBundle/dotnet.native.js; + bin/$(Configuration)/AppBundle/dotnet.globalization.js; bin/$(Configuration)/AppBundle/$(_WasmMainJSFileName); "> diff --git a/src/mono/sample/wasm/blazor-frame/blazor.csproj b/src/mono/sample/wasm/blazor-frame/blazor.csproj index 3061f77e83ac..362f1bc30cb4 100644 --- a/src/mono/sample/wasm/blazor-frame/blazor.csproj +++ b/src/mono/sample/wasm/blazor-frame/blazor.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/src/mono/sample/wasm/browser-advanced/main.js b/src/mono/sample/wasm/browser-advanced/main.js index f3c7f8db928f..115514db7299 100644 --- a/src/mono/sample/wasm/browser-advanced/main.js +++ b/src/mono/sample/wasm/browser-advanced/main.js @@ -64,6 +64,7 @@ try { console.log('user code Module.onDotnetReady'); }, postRun: () => { console.log('user code Module.postRun'); }, + out: (text) => { console.log("ADVANCED:" + text) }, }) .withResourceLoader((type, name, defaultUri, integrity, behavior) => { // loadBootResource could return string with unqualified name of resource. It assumes that we resolve it with document.baseURI diff --git a/src/mono/sample/wasm/browser-bench/main.js b/src/mono/sample/wasm/browser-bench/main.js index 0f1a65304912..71e4a677ddcc 100644 --- a/src/mono/sample/wasm/browser-bench/main.js +++ b/src/mono/sample/wasm/browser-bench/main.js @@ -225,11 +225,6 @@ try { // console to see statistics on how much code it generated and whether any new opcodes // are causing traces to fail to compile .withRuntimeOptions(["--jiterpreter-stats-enabled"]) - // We enable interpreter PGO so that you can exercise it in local tests, i.e. - // run browser-bench one, then refresh the tab to measure the performance improvement - // on the second run of browser-bench. The overall speed of the benchmarks won't - // improve much, but the time spent generating code during the run will go down - .withInterpreterPgo(true, 30) .withElementOnExit() .withExitCodeLogging() .create(); diff --git a/src/mono/sample/wasm/browser-frame/browser-frame.diff b/src/mono/sample/wasm/browser-frame/browser-frame.diff index 72795bed4394..a709abb5d609 100644 --- a/src/mono/sample/wasm/browser-frame/browser-frame.diff +++ b/src/mono/sample/wasm/browser-frame/browser-frame.diff @@ -1,15 +1,15 @@ diff -ru browser-frame/Program.cs browser-frame/Program.cs --- a/browser-frame/Program.cs 2024-03-07 09:00:37 +++ b/browser-frame/Program.cs 2024-03-05 15:38:42 -@@ -1,6 +1,8 @@ - using System; +@@ -3,6 +3,8 @@ using System.Runtime.InteropServices.JavaScript; + using System.Threading.Tasks; +BrowserBench.FrameApp.ReachedManaged(); + Console.WriteLine("Hello, Browser!"); - public partial class MyClass + if (args.Length == 1 && args[0] == "start") diff -ru browser-frame/wwwroot/index.html browser-frame/wwwroot/index.html --- a/browser-frame/wwwroot/index.html 2024-03-07 09:00:37 +++ b/browser-frame/wwwroot/index.html 2024-03-05 15:38:42 diff --git a/src/mono/sample/wasm/browser-minimal-config/main.js b/src/mono/sample/wasm/browser-minimal-config/main.js index acd81b2899a3..702234c984df 100644 --- a/src/mono/sample/wasm/browser-minimal-config/main.js +++ b/src/mono/sample/wasm/browser-minimal-config/main.js @@ -34,11 +34,13 @@ const assets = [ }, { name: "System.Private.CoreLib.wasm", - behavior: "assembly" + behavior: "assembly", + isCore: true, }, { name: "System.Runtime.InteropServices.JavaScript.wasm", - behavior: "assembly" + behavior: "assembly", + isCore: true, }, { name: "Wasm.Browser.Config.Sample.wasm", @@ -62,10 +64,12 @@ const resources = { "wasmNative": { "dotnet.native.wasm": "" }, - "assembly": { - "System.Console.wasm": "", + "coreAssembly": { "System.Private.CoreLib.wasm": "", "System.Runtime.InteropServices.JavaScript.wasm": "", + }, + "assembly": { + "System.Console.wasm": "", "Wasm.Browser.Config.Sample.wasm": "" }, }; diff --git a/src/mono/sample/wasm/browser-threads/Program.cs b/src/mono/sample/wasm/browser-threads/Program.cs index 8783ace18be7..c180b0d80dcd 100644 --- a/src/mono/sample/wasm/browser-threads/Program.cs +++ b/src/mono/sample/wasm/browser-threads/Program.cs @@ -16,11 +16,13 @@ public partial class Test private static int _animationCounter = 0; private static int _callCounter = 0; private static bool _isRunning = false; + private static Task later; private static readonly IReadOnlyList _animations = new string[] { "\u2680", "\u2681", "\u2682", "\u2683", "\u2684", "\u2685" }; public static async Task Main(string[] args) { Console.WriteLine("Hello, World!"); + later = Task.Delay(200); // this will create Timer thread await updateProgress2(); return 0; } @@ -40,12 +42,14 @@ public static void Progress2() // both calls here are sync POSIX calls dispatched to UI thread, which is already blocked because this is synchronous method on deputy thread // it should not deadlock anyway, see also invoke_later_when_on_ui_thread_sync and emscripten_yield var cwd = Directory.GetCurrentDirectory(); - Console.WriteLine("Progress! "+ cwd); + Console.WriteLine("Progress2 A " + cwd); // below is blocking call, which means that UI will spin-lock little longer // it will warn about blocking wait because of jsThreadBlockingMode: "WarnWhenBlockingWait" // but it will not deadlock because underlying task chain is not JS promise - Task.Delay(10).Wait(); + later.Wait(); + + Console.WriteLine("Progress2 B"); } [JSExport] diff --git a/src/mono/sample/wasm/console-node/Wasm.Console.Node.Sample.csproj b/src/mono/sample/wasm/console-node/Wasm.Console.Node.Sample.csproj index 7234698ff228..995e1d3650e2 100644 --- a/src/mono/sample/wasm/console-node/Wasm.Console.Node.Sample.csproj +++ b/src/mono/sample/wasm/console-node/Wasm.Console.Node.Sample.csproj @@ -6,7 +6,7 @@ true 2 - $(ExecXHarnessCmd) wasm test --app=. --engine=NodeJS --engine-arg=--stack-trace-limit=1000 --js-file=main.mjs --output-directory=$(XHarnessOutput) --expected-exit-code $(ExpectedExitCode) + $(ExecXHarnessVar) wasm test --app=. --engine=NodeJS --engine-arg=--stack-trace-limit=1000 --js-file=main.mjs --output-directory=$(XHarnessOutputVar) --expected-exit-code $(ExpectedExitCode) diff --git a/src/mono/sample/wasm/console-v8/Wasm.Console.V8.Sample.csproj b/src/mono/sample/wasm/console-v8/Wasm.Console.V8.Sample.csproj index 13ed38bfe63e..09e9f7bf1a0d 100644 --- a/src/mono/sample/wasm/console-v8/Wasm.Console.V8.Sample.csproj +++ b/src/mono/sample/wasm/console-v8/Wasm.Console.V8.Sample.csproj @@ -5,7 +5,7 @@ true true - $(ExecXHarnessCmd) wasm test --app=. --engine=V8 --engine-arg=--stack-trace-limit=1000 --engine-arg=--module --js-file=main.mjs --output-directory=$(XHarnessOutput) -- --run $(MSBuildProjectName).dll + $(ExecXHarnessVar) wasm test --app=. --engine=V8 --engine-arg=--stack-trace-limit=1000 --engine-arg=--module --js-file=main.mjs --output-directory=$(XHarnessOutputVar) -- --run $(MSBuildProjectName).dll diff --git a/src/mono/sample/wasm/simple-raytracer/Program.cs b/src/mono/sample/wasm/simple-raytracer/Program.cs index 5ee605e8ef68..50dec0a2395d 100644 --- a/src/mono/sample/wasm/simple-raytracer/Program.cs +++ b/src/mono/sample/wasm/simple-raytracer/Program.cs @@ -190,7 +190,7 @@ private static void renderPixel (int i, int j, ref Vec3f light, Intersector inte float hitZ = -999; bool didHitZ = false; for (int s = 0; s < scene.Length; s++) { - ref var sphere = ref scene[s]; + var sphere = scene[s]; if (didHitZ && (hitZ > sphere.Center.z)) continue; diff --git a/src/mono/sample/wasm/simple-raytracer/main.js b/src/mono/sample/wasm/simple-raytracer/main.js index decdf6453c94..7dc3397f0f87 100644 --- a/src/mono/sample/wasm/simple-raytracer/main.js +++ b/src/mono/sample/wasm/simple-raytracer/main.js @@ -19,8 +19,9 @@ const config = getConfig(); const exports = await getAssemblyExports(config.mainAssemblyName); globalThis.onClick = exports.Program.OnClick; -await dotnet +const runtime = await dotnet .withRuntimeOptions(["--jiterpreter-stats-enabled"]) - .run(); + .create(); +await runtime.runMain(); const btnRender = document.getElementById("btnRender"); btnRender.disabled = false; diff --git a/src/mono/wasi/build/WasiApp.InTree.props b/src/mono/wasi/build/WasiApp.InTree.props index 894b17f646e3..b85fd737856d 100644 --- a/src/mono/wasi/build/WasiApp.InTree.props +++ b/src/mono/wasi/build/WasiApp.InTree.props @@ -11,12 +11,4 @@ partial false - - - <_MonoRuntimeComponentDontLink Include="libmono-component-debugger-stub-static.a" /> - - <_MonoRuntimeComponentDontLink Include="libmono-component-diagnostics_tracing-static.a" Condition="'$(FeatureWasmPerfTracing)' != 'true' and $(FeatureWasmManagedThreads) != 'true'"/> - <_MonoRuntimeComponentDontLink Include="libmono-component-hot_reload-stub-static.a" /> - <_MonoRuntimeComponentDontLink Include="libmono-component-marshal-ilgen-stub-static.a" /> - diff --git a/src/mono/wasi/build/WasiApp.targets b/src/mono/wasi/build/WasiApp.targets index b229d76dd71f..cad25a760672 100644 --- a/src/mono/wasi/build/WasiApp.targets +++ b/src/mono/wasi/build/WasiApp.targets @@ -23,6 +23,16 @@ _WasmGenerateNodeScripts; + + $(WasiWriteRspForLinkingDependsOn); + _WasmSelectRuntimeComponentsForLinking; + _WasiGetWasiOutputFileName; + + + $(WasiWriteRspForLinkingDependsOn); + _MonoSelectRuntimeComponents; + + true @@ -138,6 +148,8 @@ $(_WasiClangOptimizationFlagDefault) $(WasiClangCompileOptimizationFlag) + -O2 + $(WasiClangCompileOptimizationFlag) -O2 $(WasiClangCompileOptimizationFlag) $(WasiClangLinkOptimizationFlag) @@ -255,13 +267,14 @@ - <_BitcodeLDFlags Include="@(_WasiClangLDFlags)" /> - <_BitcodeLDFlags Include="$(WasiClangExtraBitcodeLDFlags)" /> + <_BitcodeCompileFlags Include="@(WasiBitcodeCompileOptimizationFlag)" /> + <_BitcodeCompileFlags Include="@(_WasiClangCommonFlags)" /> + <_BitcodeCompileFlags Include="$(WasiClangExtraBitcodeCompileFlags)" /> @@ -296,12 +309,15 @@ <_WasmSIMDLibToExclude Condition="'$(WasmEnableSIMD)' == 'true'">libmono-wasm-nosimd.a + + <_MonoRuntimeComponentDontLink Include="wasm-bundled-timezones.a" Condition="'$(InvariantTimezone)' == 'true'"/> + <_MonoRuntimeComponentDontLink Include="libmono-component-diagnostics_tracing-static.a" Condition="'$(UsingWasiRuntimeWorkload)' != 'true'" /> + + <_WasmNativeFileForLinking Include="%(_BitcodeFile.ObjectFile)" /> - <_MonoRuntimeComponentDontLink Include="libmono-component-diagnostics_tracing-static.a" /> - <_MonoRuntimeComponentDontLink Include="wasm-bundled-timezones.a" Condition="'$(InvariantTimezone)' == 'true'"/> <_WasmNativeFileForLinking Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)*.a" @@ -440,4 +456,4 @@ wasi.start(instance); - + \ No newline at end of file diff --git a/src/mono/wasi/wasi-sdk-version.txt b/src/mono/wasi/wasi-sdk-version.txt index aabe6ec3909c..2bd5a0a98a36 100644 --- a/src/mono/wasi/wasi-sdk-version.txt +++ b/src/mono/wasi/wasi-sdk-version.txt @@ -1 +1 @@ -21 +22 diff --git a/src/mono/wasi/wasi.proj b/src/mono/wasi/wasi.proj index bd03a1a0e79b..59d2137cf972 100644 --- a/src/mono/wasi/wasi.proj +++ b/src/mono/wasi/wasi.proj @@ -202,10 +202,10 @@ cmake $(MSBuildThisFileDirectory)runtime cmake -G Ninja $(MSBuildThisFileDirectory)runtime + $(CMakeBuildRuntimeConfigureCmd) --no-warn-unused-cli -DCMAKE_TOOLCHAIN_FILE="$([MSBuild]::NormalizePath('$(WASI_SDK_PATH)', 'share/cmake/wasi-sdk.cmake'))" $(CMakeBuildRuntimeConfigureCmd) -DWASI_SDK_PREFIX=$(WASI_SDK_PATH) $(CMakeBuildRuntimeConfigureCmd) -DCMAKE_SYSROOT=$(WASI_SDK_PATH)share/wasi-sysroot $(CMakeBuildRuntimeConfigureCmd) -DCMAKE_CXX_FLAGS="--sysroot=$(WASI_SDK_PATH)share/wasi-sysroot" - $(CMakeBuildRuntimeConfigureCmd) -DCMAKE_TOOLCHAIN_FILE=$(WASI_SDK_PATH)share/cmake/wasi-sdk.cmake $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_WASICC_FLAGS="$(CMakeConfigurationWasiFlags)" $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_LINK_FLAGS="$(CMakeConfigurationLinkFlags)" diff --git a/src/mono/wasi/wasmtime-version.txt b/src/mono/wasi/wasmtime-version.txt index 0062ac971805..e021724948e0 100644 --- a/src/mono/wasi/wasmtime-version.txt +++ b/src/mono/wasi/wasmtime-version.txt @@ -1 +1 @@ -5.0.0 +19.0.2 diff --git a/src/mono/wasm/Wasm.Build.Tests/AspNetCore/SignalRClientTests.cs b/src/mono/wasm/Wasm.Build.Tests/AspNetCore/SignalRClientTests.cs new file mode 100644 index 000000000000..85f538fac1c2 --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/AspNetCore/SignalRClientTests.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Threading.Tasks; +using Xunit.Abstractions; +using Xunit; + +#nullable enable + +namespace Wasm.Build.Tests.AspNetCore; + +public class SignalRClientTests : SignalRTestsBase +{ + public SignalRClientTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + [ConditionalTheory(typeof(BuildTestBase), nameof(IsWorkloadWithMultiThreadingForDefaultFramework))] + [InlineData("Debug", "LongPolling")] + [InlineData("Release", "LongPolling")] + [InlineData("Debug", "WebSockets")] + [InlineData("Release", "WebSockets")] + public async Task SignalRPassMessageWasmBrowser(string config, string transport) => + await SignalRPassMessage("wasmclient", config, transport); +} diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs index da9c7764f2d1..46c8f2ce1328 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs @@ -205,7 +205,7 @@ public async Task BlazorRunTest(string runArgs, onConsoleMessage: OnConsoleMessage, onServerMessage: runOptions.OnServerMessage, onError: OnErrorMessage, - modifyBrowserUrl: browserUrl => browserUrl + runOptions.BrowserPath + runOptions.QueryString); + modifyBrowserUrl: browserUrl => new Uri(new Uri(browserUrl), runOptions.BrowserPath + runOptions.QueryString).ToString()); _testOutput.WriteLine("Waiting for page to load"); await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded, new () { Timeout = 1 * 60 * 1000 }); diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs index e7be07f71c89..fc22d03b303b 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs @@ -28,7 +28,7 @@ public BuildPublishTests(ITestOutputHelper output, SharedBuildPerTestClassFixtur [InlineData("Release")] public async Task DefaultTemplate_WithoutWorkload(string config) { - string id = $"blz_no_workload_{config}_{GetRandomId()}_{s_unicodeChar}"; + string id = $"blz_no_workload_{config}_{GetRandomId()}_{s_unicodeChars}"; CreateBlazorWasmTemplateProject(id); BlazorBuild(new BlazorBuildOptions(id, config)); @@ -63,7 +63,7 @@ public static TheoryData TestDataForDefaultTemplate_WithWorkload(b public void DefaultTemplate_NoAOT_WithWorkload(string config, bool testUnicode) { string id = testUnicode ? - $"blz_no_aot_{config}_{GetRandomId()}_{s_unicodeChar}" : + $"blz_no_aot_{config}_{GetRandomId()}_{s_unicodeChars}" : $"blz_no_aot_{config}_{GetRandomId()}"; CreateBlazorWasmTemplateProject(id); @@ -84,7 +84,7 @@ public void DefaultTemplate_NoAOT_WithWorkload(string config, bool testUnicode) public void DefaultTemplate_AOT_WithWorkload(string config, bool testUnicode) { string id = testUnicode ? - $"blz_aot_{config}_{GetRandomId()}_{s_unicodeChar}" : + $"blz_aot_{config}_{GetRandomId()}_{s_unicodeChars}" : $"blz_aot_{config}_{GetRandomId()}"; CreateBlazorWasmTemplateProject(id); diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests3.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests3.cs index 10717b334174..eeaf368640e9 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests3.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests3.cs @@ -33,7 +33,7 @@ public MiscTests3(ITestOutputHelper output, SharedBuildPerTestClassFixture build public async Task WithDllImportInMainAssembly(string config, bool build, bool publish) { // Based on https://github.com/dotnet/runtime/issues/59255 - string id = $"blz_dllimp_{config}_{s_unicodeChar}"; + string id = $"blz_dllimp_{config}_{s_unicodeChars}"; if (build && publish) id += "build_then_publish"; else if (build) diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/SignalRClientTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/SignalRClientTests.cs new file mode 100644 index 000000000000..cf4f938bc188 --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/SignalRClientTests.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +using System.Threading.Tasks; +using Xunit.Abstractions; +using Xunit; + +#nullable enable + +namespace Wasm.Build.Tests.Blazor; + +public class SignalRClientTests : SignalRTestsBase +{ + public SignalRClientTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + [ConditionalTheory(typeof(BuildTestBase), nameof(IsWorkloadWithMultiThreadingForDefaultFramework))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/100445")] // to be fixed by: "https://github.com/dotnet/aspnetcore/issues/54365" + [InlineData("Debug", "LongPolling")] + [InlineData("Release", "LongPolling")] + [InlineData("Debug", "WebSockets")] + [InlineData("Release", "WebSockets")] + public async Task SignalRPassMessageBlazor(string config, string transport) => + await SignalRPassMessage("blazorclient", config, transport); +} + diff --git a/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs b/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs index c29233c69844..b37deb5781b2 100644 --- a/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs +++ b/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs @@ -22,7 +22,7 @@ internal class BrowserRunner : IAsyncDisposable private static readonly Lazy s_chromePath = new(() => { string artifactsBinDir = Path.Combine(Path.GetDirectoryName(typeof(BuildTestBase).Assembly.Location)!, "..", "..", "..", ".."); - return BrowserLocator.FindChrome(artifactsBinDir, "BROWSER_PATH_FOR_TESTS"); + return BrowserLocator.FindChrome(artifactsBinDir, "CHROME_PATH_FOR_TESTS"); }); public IPlaywright? Playwright { get; private set; } @@ -109,11 +109,17 @@ public async Task SpawnBrowserAsync( // codespaces: ignore certificate error -> Microsoft.Playwright.PlaywrightException : net::ERR_CERT_AUTHORITY_INVALID string[] chromeArgs = new[] { $"--explicitly-allowed-ports={url.Port}", "--ignore-certificate-errors" }; _testOutput.WriteLine($"Launching chrome ('{s_chromePath.Value}') via playwright with args = {string.Join(',', chromeArgs)}"); - return Browser = await Playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions{ + Browser = await Playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions{ ExecutablePath = s_chromePath.Value, Headless = headless, Args = chromeArgs }); + Browser.Disconnected += (sender, e) => + { + Browser = null; + _testOutput.WriteLine("Browser has been disconnected"); + }; + return Browser; } // FIXME: options @@ -196,8 +202,21 @@ public async Task WaitForProcessExitAsync(TimeSpan timeout) public async ValueTask DisposeAsync() { - if (Browser is not null) - await Browser.DisposeAsync(); - Playwright?.Dispose(); + try + { + if (Browser is not null) + { + await Browser.DisposeAsync(); + Browser = null; + } + } + catch (PlaywrightException ex) + { + _testOutput.WriteLine($"PlaywrightException occurred during DisposeAsync: {ex.Message}"); + } + finally + { + Playwright?.Dispose(); + } } } diff --git a/src/mono/wasm/Wasm.Build.Tests/BuildPublishTests.cs b/src/mono/wasm/Wasm.Build.Tests/BuildPublishTests.cs index d171631c2c5e..f287fa457416 100644 --- a/src/mono/wasm/Wasm.Build.Tests/BuildPublishTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/BuildPublishTests.cs @@ -158,7 +158,7 @@ void CheckOutputForNativeBuild(bool expectAOT, bool expectRelinking, BuildArgs b { if (testUnicode) { - string projectNameCore = buildArgs.ProjectName.Trim(new char[] {s_unicodeChar}); + string projectNameCore = buildArgs.ProjectName.Replace(s_unicodeChars, ""); TestUtils.AssertMatches(@$"{projectNameCore}\S+.dll -> {projectNameCore}\S+.dll.bc", buildOutput, contains: expectAOT); TestUtils.AssertMatches(@$"{projectNameCore}\S+.dll.bc -> {projectNameCore}\S+.dll.o", buildOutput, contains: expectAOT); } diff --git a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs index f871c3d2bfe7..03db9aed6011 100644 --- a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs @@ -29,7 +29,7 @@ public abstract class BuildTestBase : IClassFixture' }; + // Keep synced with FixupSymbolName from src/tasks/Common/Utils.cs + // and with mono_fixup_symbol_name from src/mono/mono/metadata/native-library.c public static string FixupSymbolName(string name) { UTF8Encoding utf8 = new(); diff --git a/src/mono/wasm/Wasm.Build.Tests/HostRunner/BrowserHostRunner.cs b/src/mono/wasm/Wasm.Build.Tests/HostRunner/BrowserHostRunner.cs index f9a215652c58..a27e9be89290 100644 --- a/src/mono/wasm/Wasm.Build.Tests/HostRunner/BrowserHostRunner.cs +++ b/src/mono/wasm/Wasm.Build.Tests/HostRunner/BrowserHostRunner.cs @@ -17,11 +17,11 @@ private static string BinaryPathArg { if (s_binaryPathArg is null) { - if (!string.IsNullOrEmpty(EnvironmentVariables.BrowserPathForTests)) + if (!string.IsNullOrEmpty(EnvironmentVariables.ChromePathForTests)) { - if (!File.Exists(EnvironmentVariables.BrowserPathForTests)) - throw new Exception($"Cannot find BROWSER_PATH_FOR_TESTS={EnvironmentVariables.BrowserPathForTests}"); - s_binaryPathArg = $" --browser-path=\"{EnvironmentVariables.BrowserPathForTests}\""; + if (!File.Exists(EnvironmentVariables.ChromePathForTests)) + throw new Exception($"Cannot find CHROME_PATH_FOR_TESTS={EnvironmentVariables.ChromePathForTests}"); + s_binaryPathArg = $" --browser-path=\"{EnvironmentVariables.ChromePathForTests}\""; } else { diff --git a/src/mono/wasm/Wasm.Build.Tests/NativeLibraryTests.cs b/src/mono/wasm/Wasm.Build.Tests/NativeLibraryTests.cs index c8cca6cd0774..555cfa73fad1 100644 --- a/src/mono/wasm/Wasm.Build.Tests/NativeLibraryTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/NativeLibraryTests.cs @@ -136,5 +136,36 @@ public static int Main() string cryptoInitMsg = "MONO_WASM: Initializing Crypto WebWorker"; Assert.DoesNotContain(cryptoInitMsg, output); } + + [Theory] + [BuildAndRun(aot: false)] + [BuildAndRun(aot: true)] + public void ProjectWithNativeLibrary(BuildArgs buildArgs, RunHost host, string id) + { + string projectName = $"AppUsingNativeLibrary-a"; + buildArgs = buildArgs with { ProjectName = projectName }; + buildArgs = ExpandBuildArgs(buildArgs, extraItems: "\n"); + + if (!_buildContext.TryGetBuildFor(buildArgs, out BuildProduct? _)) + { + InitPaths(id); + if (Directory.Exists(_projectDir)) + Directory.Delete(_projectDir, recursive: true); + + Utils.DirectoryCopy(Path.Combine(BuildEnvironment.TestAssetsPath, "AppUsingNativeLib"), _projectDir); + File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "native-libs", "native-lib.o"), Path.Combine(_projectDir, "native-lib.o")); + } + + BuildProject(buildArgs, + id: id, + new BuildProjectOptions(DotnetWasmFromRuntimePack: false)); + + string output = RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 0, + test: output => {}, + host: host, id: id); + + Assert.Contains("print_line: 100", output); + Assert.Contains("from pinvoke: 142", output); + } } } diff --git a/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs b/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs index 10c2d6926d53..09fafe0df693 100644 --- a/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs @@ -110,7 +110,7 @@ protected BuildArgs GenerateProjectContents(BuildArgs buildArgs, bool nativeReli // appending UTF-8 char makes sure project build&publish under all types of paths is supported protected string GetTestProjectPath(string prefix, string config, bool appendUnicode=true) => - appendUnicode ? $"{prefix}_{config}_{s_unicodeChar}" : $"{prefix}_{config}"; + appendUnicode ? $"{prefix}_{config}_{s_unicodeChars}" : $"{prefix}_{config}"; } } diff --git a/src/mono/wasm/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs b/src/mono/wasm/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs index 8c0442a1b0d6..0daa8d098492 100644 --- a/src/mono/wasm/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs @@ -884,5 +884,31 @@ public void EnsureWasmAbiRulesAreFollowedInAOT(BuildArgs buildArgs, RunHost host [BuildAndRun(host: RunHost.Chrome, aot: false)] public void EnsureWasmAbiRulesAreFollowedInInterpreter(BuildArgs buildArgs, RunHost host, string id) => EnsureWasmAbiRulesAreFollowed(buildArgs, host, id); + + [Theory] + [BuildAndRun(host: RunHost.Chrome, aot: false)] + public void UCOWithSpecialCharacters(BuildArgs buildArgs, RunHost host, string id) + { + var extraProperties = "true"; + var extraItems = @""; + + buildArgs = ExpandBuildArgs(buildArgs, + extraItems: extraItems, + extraProperties: extraProperties); + + (string libraryDir, string output) = BuildProject(buildArgs, + id: id, + new BuildProjectOptions( + InitProject: () => + { + File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "Wasm.Buid.Tests.Programs", "UnmanagedCallback.cs"), Path.Combine(_projectDir!, "Program.cs")); + File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "native-libs", "local.c"), Path.Combine(_projectDir!, "local.c")); + }, + Publish: true, + DotnetWasmFromRuntimePack: false)); + + var runOutput = RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 42, host: host, id: id); + Assert.Contains("ManagedFunc returned 42", runOutput); + } } } diff --git a/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs b/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs index 581a187270ae..6be096cb67ea 100644 --- a/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs @@ -293,6 +293,7 @@ public static string FindSubDirIgnoringCase(string parentDir, string dirName) Path.Combine(paths.BundleDir, "_framework", "dotnet.native.wasm"), Path.Combine(paths.BundleDir, "_framework", "dotnet.native.js"), + Path.Combine(paths.BundleDir, "_framework", "dotnet.globalization.js"), }; if (buildArgs.AOT) @@ -316,6 +317,7 @@ public static string FindSubDirIgnoringCase(string parentDir, string dirName) dict["dotnet.js.map"]=(Path.Combine(paths.BundleDir, "_framework", "dotnet.js.map"), true); dict["dotnet.runtime.js"]=(Path.Combine(paths.BundleDir, "_framework", "dotnet.runtime.js"), true); dict["dotnet.runtime.js.map"]=(Path.Combine(paths.BundleDir, "_framework", "dotnet.runtime.js.map"), true); + dict["dotnet.globalization.js"]=(Path.Combine(paths.BundleDir, "_framework", "dotnet.globalization.js"), true); return dict; } @@ -404,7 +406,7 @@ public void AssertBootJson(AssertBundleOptionsBase options) BootJsonData bootJson = ParseBootData(bootJsonPath); string spcExpectedFilename = $"System.Private.CoreLib{WasmAssemblyExtension}"; - string? spcActualFilename = bootJson.resources.assembly.Keys + string? spcActualFilename = bootJson.resources.coreAssembly.Keys .Where(a => Path.GetFileNameWithoutExtension(a) == "System.Private.CoreLib") .SingleOrDefault(); if (spcActualFilename is null) @@ -415,6 +417,7 @@ public void AssertBootJson(AssertBundleOptionsBase options) var bootJsonEntries = bootJson.resources.jsModuleNative.Keys .Union(bootJson.resources.jsModuleRuntime.Keys) .Union(bootJson.resources.jsModuleWorker?.Keys ?? Enumerable.Empty()) + .Union(bootJson.resources.jsModuleGlobalization?.Keys ?? Enumerable.Empty()) .Union(bootJson.resources.wasmSymbols?.Keys ?? Enumerable.Empty()) .Union(bootJson.resources.wasmNative.Keys) .ToArray(); diff --git a/src/mono/wasm/Wasm.Build.Tests/SignalRTestsBase.cs b/src/mono/wasm/Wasm.Build.Tests/SignalRTestsBase.cs new file mode 100644 index 000000000000..183d984b39b4 --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/SignalRTestsBase.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Collections.Generic; +using Wasm.Build.Tests.TestAppScenarios; +using Xunit.Abstractions; +using Xunit; +#nullable enable + +namespace Wasm.Build.Tests; + +public class SignalRTestsBase : AppTestBase +{ + public SignalRTestsBase(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + protected async Task SignalRPassMessage(string staticWebAssetBasePath, string config, string transport) + { + CopyTestAsset("WasmOnAspNetCore", "SignalRClientTests", "AspNetCoreServer"); + PublishProject(config, runtimeType: RuntimeVariant.MultiThreaded, assertAppBundle: false); + + var result = await RunSdkStyleAppForBuild(new( + Configuration: config, + ServerEnvironment: new Dictionary { ["ASPNETCORE_ENVIRONMENT"] = "Development" }, + BrowserPath: staticWebAssetBasePath, + BrowserQueryString: new Dictionary { ["transport"] = transport, ["message"] = "ping" } )); + + string testOutput = string.Join("\n", result.TestOutput) ?? ""; + Assert.NotEmpty(testOutput); + // check sending and receiving threadId + string threadIdUsedForSending = GetThreadOfAction(testOutput, @"SignalRPassMessages was sent by CurrentManagedThreadId=(\d+)", "signalR message was sent"); + string threadIdUsedForReceiving = GetThreadOfAction(testOutput, @"ReceiveMessage from server on CurrentManagedThreadId=(\d+)", "signalR message was received"); + string consoleOutput = string.Join("\n", result.ConsoleOutput); + Assert.True("1" != threadIdUsedForSending || "1" != threadIdUsedForReceiving, + $"Expected to send/receive with signalR in non-UI threads, instead only CurrentManagedThreadId=1 was used. ConsoleOutput: {consoleOutput}."); + } + + private string GetThreadOfAction(string testOutput, string pattern, string actionDescription) + { + Match match = Regex.Match(testOutput, pattern); + Assert.True(match.Success, $"Expected to find a log that {actionDescription}. TestOutput: {testOutput}."); + return match.Groups[1].Value ?? ""; + } +} diff --git a/src/mono/wasm/Wasm.Build.Tests/Templates/InterpPgoTests.cs b/src/mono/wasm/Wasm.Build.Tests/Templates/InterpPgoTests.cs deleted file mode 100644 index 4fe88ee8daca..000000000000 --- a/src/mono/wasm/Wasm.Build.Tests/Templates/InterpPgoTests.cs +++ /dev/null @@ -1,127 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.IO; -using Wasm.Build.Tests; -using Xunit; -using Xunit.Abstractions; -using System.Threading; -using System.Threading.Tasks; -using System; -using System.Diagnostics; -using Microsoft.Playwright; - -#nullable enable - -namespace Wasm.Build.Templates.Tests; - -public class InterpPgoTests : WasmTemplateTestBase -{ - public InterpPgoTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) - : base(output, buildContext) - { - } - - [Theory] - // Interpreter PGO is not meaningful to enable in debug builds - tiering is inactive there so all methods - // would get added to the PGO table instead of just hot ones. - [InlineData("Release")] - public async Task FirstRunGeneratesTableAndSecondRunLoadsIt(string config) - { - // We need to invoke Greeting enough times to cause BCL code to tier so we can exercise interpreter PGO - // Invoking it too many times makes the test meaningfully slower. - const int iterationCount = 70; - - string id = $"browser_{config}_{GetRandomId()}"; - _testOutput.WriteLine("/// Creating project"); - string projectFile = CreateWasmTemplateProject(id, "wasmbrowser", extraProperties: "0"); - - _testOutput.WriteLine("/// Updating JS"); - UpdateBrowserMainJs((js) => { - // We need to capture INTERNAL so we can explicitly save the PGO table - js = js.Replace( - "const { setModuleImports, getAssemblyExports, getConfig, runMain } = await dotnet", - "const { setModuleImports, getAssemblyExports, getConfig, runMain, INTERNAL } = await dotnet" - ); - // Enable interpreter PGO + interpreter PGO logging + console output capturing - js = js.Replace( - ".create()", - ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().withExitOnUnhandledError().withRuntimeOptions(['--interp-pgo-logging']).withInterpreterPgo(true).create()" - ); - js = js.Replace("runMain()", "dotnet.run()"); - // Call Greeting in a loop to exercise enough code to cause something to tier, - // then call INTERNAL.interp_pgo_save_data() to save the interp PGO table - js = js.Replace( - "const text = exports.MyClass.Greeting();", - "console.log(`WASM debug level ${getConfig().debugLevel}`);\n" + - "let text = '';\n" + - $"for (let i = 0; i < {iterationCount}; i++) {{ text = exports.MyClass.Greeting(); }};\n" + - "await INTERNAL.interp_pgo_save_data();" - ); - return js; - }, DefaultTargetFramework); - - _testOutput.WriteLine("/// Building"); - - new DotNetCommand(s_buildEnv, _testOutput) - .WithWorkingDirectory(_projectDir!) - .Execute($"build -c {config} -bl:{Path.Combine(s_buildEnv.LogRootPath, $"{id}.binlog")}") - .EnsureSuccessful(); - - _testOutput.WriteLine("/// Starting server"); - - // Create a single browser instance and single context to host all our pages. - // If we don't do this, each page will have its own unique cache and the table won't be loaded. - using var runCommand = new RunCommand(s_buildEnv, _testOutput) - .WithWorkingDirectory(_projectDir!); - await using var runner = new BrowserRunner(_testOutput); - var url = await runner.StartServerAndGetUrlAsync(runCommand, $"run --no-silent -c {config} --no-build --project \"{projectFile}\" --forward-console"); - IBrowser browser = await runner.SpawnBrowserAsync(url); - IBrowserContext context = await browser.NewContextAsync(); - - string output; - { - _testOutput.WriteLine("/// First run"); - var page = await runner.RunAsync(context, url); - await runner.WaitForExitMessageAsync(TimeSpan.FromSeconds(30)); - lock (runner.OutputLines) - output = string.Join(Environment.NewLine, runner.OutputLines); - - Assert.Contains("Hello, Browser!", output); - // Verify that no PGO table was located in cache - Assert.Contains("Failed to load interp_pgo table", output); - // Verify that the table was saved after the app ran - Assert.Contains("Saved interp_pgo table", output); - // Verify that a specific method was tiered by the Greeting calls and recorded by PGO - Assert.Contains("added System.Runtime.CompilerServices.Unsafe:Add (byte&,int) to table", output); - } - - { - _testOutput.WriteLine("/// Second run"); - // Clear the shared output lines buffer so it's empty for the next run. - lock (runner.OutputLines) - runner.OutputLines.Clear(); - // resetExitedState is necessary for WaitForExitMessageAsync to work correctly - var page = await runner.RunAsync(context, url, resetExitedState: true); - await runner.WaitForExitMessageAsync(TimeSpan.FromSeconds(30)); - lock (runner.OutputLines) - output = string.Join(Environment.NewLine, runner.OutputLines); - - Assert.Contains("Hello, Browser!", output); - // Verify that table data was loaded from cache - // if this breaks, it could be caused by change in config which affects the config hash and the cache storage hash key - Assert.Contains(" bytes of interp_pgo data (table size == ", output); - // Verify that the table was saved after the app ran - Assert.Contains("Saved interp_pgo table", output); - // Verify that method(s) were found in the table and eagerly tiered - Assert.Contains("because it was in the interp_pgo table", output); - // Verify that a specific method was tiered by the Greeting calls and recorded by PGO - Assert.Contains("added System.Runtime.CompilerServices.Unsafe:Add (byte&,int) to table", output); - } - - _testOutput.WriteLine("/// Done"); - - (context as IDisposable)?.Dispose(); - (browser as IDisposable)?.Dispose(); - } -} diff --git a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs index d3e2e506b477..b1927711236c 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs @@ -20,7 +20,25 @@ public WasmTemplateTests(ITestOutputHelper output, SharedBuildPerTestClassFixtur { } - private void UpdateProgramCS() + private string StringReplaceWithAssert(string oldContent, string oldValue, string newValue) + { + string newContent = oldContent.Replace(oldValue, newValue); + if (oldValue != newValue && oldContent == newContent) + throw new XunitException($"Replacing '{oldValue}' with '{newValue}' did not change the content '{oldContent}'"); + + return newContent; + } + + private void UpdateBrowserProgramCs() + { + var path = Path.Combine(_projectDir!, "Program.cs"); + string text = File.ReadAllText(path); + text = StringReplaceWithAssert(text, "while(true)", $"int i = 0;{Environment.NewLine}while(i++ < 10)"); + text = StringReplaceWithAssert(text, "partial class StopwatchSample", $"return 42;{Environment.NewLine}partial class StopwatchSample"); + File.WriteAllText(path, text); + } + + private void UpdateConsoleProgramCs() { string programText = """ Console.WriteLine("Hello, Console!"); @@ -30,25 +48,36 @@ private void UpdateProgramCS() """; var path = Path.Combine(_projectDir!, "Program.cs"); string text = File.ReadAllText(path); - text = text.Replace(@"Console.WriteLine(""Hello, Console!"");", programText); - text = text.Replace("return 0;", "return 42;"); + text = StringReplaceWithAssert(text, @"Console.WriteLine(""Hello, Console!"");", programText); + text = StringReplaceWithAssert(text, "return 0;", "return 42;"); File.WriteAllText(path, text); } private void UpdateBrowserMainJs(string targetFramework, string runtimeAssetsRelativePath = DefaultRuntimeAssetsRelativePath) { - base.UpdateBrowserMainJs((mainJsContent) => { - // .withExitOnUnhandledError() is available only only >net7.0 - mainJsContent = mainJsContent.Replace(".create()", + base.UpdateBrowserMainJs( + (mainJsContent) => + { + // .withExitOnUnhandledError() is available only only >net7.0 + mainJsContent = StringReplaceWithAssert( + mainJsContent, + ".create()", (targetFramework == "net8.0" || targetFramework == "net9.0") ? ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().withExitOnUnhandledError().create()" - : ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().create()"); + : ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().create()" + ); - mainJsContent = mainJsContent.Replace("runMain()", "dotnet.run()"); - mainJsContent = mainJsContent.Replace("from './_framework/dotnet.js'", $"from '{runtimeAssetsRelativePath}dotnet.js'"); + // dotnet.run() is already used in <= net8.0 + if (targetFramework != "net8.0") + mainJsContent = StringReplaceWithAssert(mainJsContent, "runMain()", "dotnet.run()"); - return mainJsContent; - }, targetFramework, runtimeAssetsRelativePath); + mainJsContent = StringReplaceWithAssert(mainJsContent, "from './_framework/dotnet.js'", $"from '{runtimeAssetsRelativePath}dotnet.js'"); + + return mainJsContent; + }, + targetFramework, + runtimeAssetsRelativePath + ); } private void UpdateConsoleMainJs() @@ -56,8 +85,7 @@ private void UpdateConsoleMainJs() string mainJsPath = Path.Combine(_projectDir!, "main.mjs"); string mainJsContent = File.ReadAllText(mainJsPath); - mainJsContent = mainJsContent - .Replace(".create()", ".withConsoleForwarding().create()"); + mainJsContent = StringReplaceWithAssert(mainJsContent, ".create()", ".withConsoleForwarding().create()"); File.WriteAllText(mainJsPath, mainJsContent); } @@ -73,8 +101,7 @@ private void UpdateMainJsEnvironmentVariables(params (string key, string value)[ js.Append($".withEnvironmentVariable(\"{variable.key}\", \"{variable.value}\")"); } - mainJsContent = mainJsContent - .Replace(".create()", js.ToString() + ".create()"); + mainJsContent = StringReplaceWithAssert(mainJsContent, ".create()", js.ToString() + ".create()"); File.WriteAllText(mainJsPath, mainJsContent); } @@ -88,6 +115,7 @@ public void BrowserBuildThenPublish(string config) string projectFile = CreateWasmTemplateProject(id, "wasmbrowser"); string projectName = Path.GetFileNameWithoutExtension(projectFile); + UpdateBrowserProgramCs(); UpdateBrowserMainJs(DefaultTargetFramework); var buildArgs = new BuildArgs(projectName, config, false, id, null); @@ -96,10 +124,10 @@ public void BrowserBuildThenPublish(string config) atTheEnd: """ - - <_LinkedOutFile Include="$(IntermediateOutputPath)\linked\*.dll" /> - - + + <_LinkedOutFile Include="$(IntermediateOutputPath)\linked\*.dll" /> + + """ ); @@ -212,7 +240,7 @@ private void ConsoleBuildAndRun(string config, bool relinking, string extraNewAr string projectFile = CreateWasmTemplateProject(id, "wasmconsole", extraNewArgs, addFrameworkArg: addFrameworkArg); string projectName = Path.GetFileNameWithoutExtension(projectFile); - UpdateProgramCS(); + UpdateConsoleProgramCs(); UpdateConsoleMainJs(); if (relinking) AddItemsPropertiesToProject(projectFile, "true"); @@ -277,6 +305,7 @@ private async Task BrowserRunTwiceWithAndThenWithoutBuildAsync(string config, st string id = $"browser_{config}_{GetRandomId()}"; string projectFile = CreateWasmTemplateProject(id, "wasmbrowser"); + UpdateBrowserProgramCs(); UpdateBrowserMainJs(DefaultTargetFramework); if (!string.IsNullOrEmpty(extraProperties)) @@ -310,7 +339,7 @@ private Task ConsoleRunWithAndThenWithoutBuildAsync(string config, string extraP string id = $"console_{config}_{GetRandomId()}"; string projectFile = CreateWasmTemplateProject(id, "wasmconsole"); - UpdateProgramCS(); + UpdateConsoleProgramCs(); UpdateConsoleMainJs(); if (!string.IsNullOrEmpty(extraProperties)) @@ -374,7 +403,7 @@ public void ConsolePublishAndRun(string config, bool aot, bool relinking) string projectFile = CreateWasmTemplateProject(id, "wasmconsole"); string projectName = Path.GetFileNameWithoutExtension(projectFile); - UpdateProgramCS(); + UpdateConsoleProgramCs(); UpdateConsoleMainJs(); if (aot) @@ -436,6 +465,9 @@ public async Task BrowserBuildAndRun(string extraNewArgs, string targetFramework string id = $"browser_{config}_{GetRandomId()}"; CreateWasmTemplateProject(id, "wasmbrowser", extraNewArgs, addFrameworkArg: extraNewArgs.Length == 0); + if (targetFramework != "net8.0") + UpdateBrowserProgramCs(); + UpdateBrowserMainJs(targetFramework, runtimeAssetsRelativePath); new DotNetCommand(s_buildEnv, _testOutput) @@ -518,7 +550,7 @@ public void Test_WasmStripILAfterAOT(string stripILAfterAOT, bool expectILStripp string projectDirectory = Path.GetDirectoryName(projectFile)!; bool aot = true; - UpdateProgramCS(); + UpdateConsoleProgramCs(); UpdateConsoleMainJs(); string extraProperties = "true"; diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppSettingsTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppSettingsTests.cs index 5d028cc23890..4ce413429177 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppSettingsTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppSettingsTests.cs @@ -25,7 +25,7 @@ public AppSettingsTests(ITestOutputHelper output, SharedBuildPerTestClassFixture [InlineData("Production")] public async Task LoadAppSettingsBasedOnApplicationEnvironment(string applicationEnvironment) { - CopyTestAsset("WasmBasicTestApp", "AppSettingsTests"); + CopyTestAsset("WasmBasicTestApp", "AppSettingsTests", "App"); PublishProject("Debug"); var result = await RunSdkStyleAppForPublish(new( diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs index 01a1afe96c0b..9b228c65faaa 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs @@ -23,7 +23,7 @@ protected AppTestBase(ITestOutputHelper output, SharedBuildPerTestClassFixture b protected string Id { get; set; } protected string LogPath { get; set; } - protected void CopyTestAsset(string assetName, string generatedProjectNamePrefix = null) + protected void CopyTestAsset(string assetName, string generatedProjectNamePrefix = null, string? projectDirSuffix = null) { Id = $"{generatedProjectNamePrefix ?? assetName}_{GetRandomId()}"; InitBlazorWasmProjectDir(Id); @@ -31,27 +31,21 @@ protected void CopyTestAsset(string assetName, string generatedProjectNamePrefix LogPath = Path.Combine(s_buildEnv.LogRootPath, Id); Utils.DirectoryCopy(Path.Combine(BuildEnvironment.TestAssetsPath, assetName), Path.Combine(_projectDir!)); - switch(assetName) + if (!string.IsNullOrEmpty(projectDirSuffix)) { - case "WasmBasicTestApp": - // WasmBasicTestApp consists of App + Library projects - _projectDir = Path.Combine(_projectDir!, "App"); - break; - case "BlazorHostedApp": - // BlazorHostedApp consists of BlazorHosted.Client and BlazorHosted.Server projects - _projectDir = Path.Combine(_projectDir!, "BlazorHosted.Server"); - break; + _projectDir = Path.Combine(_projectDir, projectDirSuffix); } } protected void BlazorHostedBuild( string config, string assetName, + string projectDirSuffix, string clientDirRelativeToProjectDir = "", string? generatedProjectNamePrefix = null, RuntimeVariant runtimeType = RuntimeVariant.SingleThreaded) { - CopyTestAsset(assetName, generatedProjectNamePrefix); + CopyTestAsset(assetName, generatedProjectNamePrefix, projectDirSuffix); string frameworkDir = FindBlazorHostedBinFrameworkDir(config, forPublish: false, clientDirRelativeToProjectDir: clientDirRelativeToProjectDir); @@ -76,9 +70,17 @@ protected void BuildProject( result.EnsureSuccessful(); } - protected void PublishProject(string configuration, params string[] extraArgs) + protected void PublishProject( + string configuration, + RuntimeVariant runtimeType = RuntimeVariant.SingleThreaded, + bool assertAppBundle = true, + params string[] extraArgs) { - (CommandResult result, _) = BlazorPublish(new BlazorBuildOptions(Id, configuration), extraArgs); + (CommandResult result, _) = BlazorPublish(new BlazorBuildOptions( + Id: Id, + Config: configuration, + RuntimeType: runtimeType, + AssertAppBundle: assertAppBundle), extraArgs); result.EnsureSuccessful(); } @@ -99,12 +101,11 @@ private async Task RunSdkStyleApp(RunOptions options, BlazorRunHost h query.Add("test", options.TestScenario); var queryString = query.Any() ? "?" + string.Join("&", query.Select(kvp => $"{kvp.Key}={kvp.Value}")) : ""; - var tcs = new TaskCompletionSource(); List testOutput = new(); List consoleOutput = new(); List serverOutput = new(); - Regex exitRegex = new Regex("(WASM EXIT (?[0-9]+)$)|(Program terminated with exit\\((?[0-9]+)\\))"); + Regex exitRegex = new Regex("WASM EXIT (?[0-9]+)$"); BlazorRunOptions blazorRunOptions = new( CheckCounter: false, @@ -114,7 +115,8 @@ private async Task RunSdkStyleApp(RunOptions options, BlazorRunHost h OnServerMessage: OnServerMessage, BrowserPath: options.BrowserPath, QueryString: queryString, - Host: host); + Host: host, + ExtraArgs: options.ExtraArgs); await BlazorRunTest(blazorRunOptions); @@ -171,7 +173,8 @@ protected record RunOptions( Dictionary ServerEnvironment = null, Action OnConsoleMessage = null, Action OnServerMessage = null, - int? ExpectedExitCode = 0 + int? ExpectedExitCode = 0, + string? ExtraArgs = null ); protected record RunResult( diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DebugLevelTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DebugLevelTests.cs index 1bbe8691d80d..ee69b34819bb 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DebugLevelTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DebugLevelTests.cs @@ -33,7 +33,7 @@ private void AssertDebugLevel(RunResult result, int value) [InlineData("Release")] public async Task BuildWithDefaultLevel(string configuration) { - CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_BuildWithDefaultLevel_{configuration}"); + CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_BuildWithDefaultLevel_{configuration}", "App"); BuildProject(configuration); var result = await RunSdkStyleAppForBuild(new( @@ -50,7 +50,7 @@ public async Task BuildWithDefaultLevel(string configuration) [InlineData("Release", 0)] public async Task BuildWithExplicitValue(string configuration, int debugLevel) { - CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_BuildWithExplicitValue_{configuration}"); + CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_BuildWithExplicitValue_{configuration}", "App"); BuildProject(configuration: configuration, extraArgs: $"-p:WasmDebugLevel={debugLevel}"); var result = await RunSdkStyleAppForBuild(new( @@ -65,7 +65,7 @@ public async Task BuildWithExplicitValue(string configuration, int debugLevel) [InlineData("Release")] public async Task PublishWithDefaultLevel(string configuration) { - CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_PublishWithDefaultLevel_{configuration}"); + CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_PublishWithDefaultLevel_{configuration}", "App"); PublishProject(configuration); var result = await RunSdkStyleAppForPublish(new( @@ -82,8 +82,8 @@ public async Task PublishWithDefaultLevel(string configuration) [InlineData("Release", -1)] public async Task PublishWithExplicitValue(string configuration, int debugLevel) { - CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_PublishWithExplicitValue_{configuration}"); - PublishProject(configuration, $"-p:WasmDebugLevel={debugLevel}"); + CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_PublishWithExplicitValue_{configuration}", "App"); + PublishProject(configuration, RuntimeVariant.SingleThreaded, assertAppBundle: true, $"-p:WasmDebugLevel={debugLevel}"); var result = await RunSdkStyleAppForPublish(new( Configuration: configuration, @@ -97,8 +97,8 @@ public async Task PublishWithExplicitValue(string configuration, int debugLevel) [InlineData("Release")] public async Task PublishWithDefaultLevelAndPdbs(string configuration) { - CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_PublishWithDefaultLevelAndPdbs_{configuration}"); - PublishProject(configuration, $"-p:CopyOutputSymbolsToPublishDirectory=true"); + CopyTestAsset("WasmBasicTestApp", $"DebugLevelTests_PublishWithDefaultLevelAndPdbs_{configuration}", "App"); + PublishProject(configuration, RuntimeVariant.SingleThreaded, assertAppBundle: true, $"-p:CopyOutputSymbolsToPublishDirectory=true"); var result = await RunSdkStyleAppForPublish(new( Configuration: configuration, diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DownloadResourceProgressTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DownloadResourceProgressTests.cs deleted file mode 100644 index 7cc55ebd07ae..000000000000 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DownloadResourceProgressTests.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; - -#nullable enable - -namespace Wasm.Build.Tests.TestAppScenarios; - -public class DownloadResourceProgressTests : AppTestBase -{ - public DownloadResourceProgressTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) - : base(output, buildContext) - { - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public async Task DownloadProgressFinishes(bool failAssemblyDownload) - { - CopyTestAsset("WasmBasicTestApp", $"DownloadResourceProgressTests_{failAssemblyDownload}"); - PublishProject("Debug"); - - var result = await RunSdkStyleAppForPublish(new( - Configuration: "Debug", - TestScenario: "DownloadResourceProgressTest", - BrowserQueryString: new Dictionary { ["failAssemblyDownload"] = failAssemblyDownload.ToString().ToLowerInvariant() } - )); - Assert.True( - result.TestOutput.Any(m => m.Contains("DownloadResourceProgress: Finished")), - "The download progress test didn't emit expected error message" - ); - Assert.True( - result.ConsoleOutput.Any(m => m.Contains("Retrying download")) == failAssemblyDownload, - failAssemblyDownload - ? "The download progress test didn't emit expected message about retrying download" - : "The download progress test did emit unexpected message about retrying download" - ); - Assert.False( - result.ConsoleOutput.Any(m => m.Contains("Retrying download (2)")), - "The download progress test did emit unexpected message about second download retry" - ); - Assert.True( - result.TestOutput.Any(m => m.Contains("Throw error instead of downloading resource") == failAssemblyDownload), - failAssemblyDownload - ? "The download progress test didn't emit expected message about failing download" - : "The download progress test did emit unexpected message about failing download" - ); - } -} diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/InterpPgoTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/InterpPgoTests.cs new file mode 100644 index 000000000000..24e052f96d3f --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/InterpPgoTests.cs @@ -0,0 +1,101 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using Wasm.Build.Tests; +using Xunit; +using Xunit.Abstractions; +using System.Threading; +using System.Threading.Tasks; +using System; +using System.Diagnostics; +using Microsoft.Playwright; + +#nullable enable + +namespace Wasm.Build.Tests.TestAppScenarios; + +public class InterpPgoTests : AppTestBase +{ + public InterpPgoTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + [Theory] + // Interpreter PGO is not meaningful to enable in debug builds - tiering is inactive there so all methods + // would get added to the PGO table instead of just hot ones. + [InlineData("Release")] + public async Task FirstRunGeneratesTableAndSecondRunLoadsIt(string config) + { + // We need to invoke Greeting enough times to cause BCL code to tier so we can exercise interpreter PGO + // Invoking it too many times makes the test meaningfully slower. + const int iterationCount = 70; + + _testOutput.WriteLine("/// Creating project"); + CopyTestAsset("WasmBasicTestApp", "InterpPgoTest", "App"); + + _testOutput.WriteLine("/// Building"); + BuildProject(config, extraArgs: "-p:WasmDebugLevel=0"); + + _testOutput.WriteLine("/// Starting server"); + + // Create a single browser instance and single context to host all our pages. + // If we don't do this, each page will have its own unique cache and the table won't be loaded. + using var runCommand = new RunCommand(s_buildEnv, _testOutput) + .WithWorkingDirectory(_projectDir!); + await using var runner = new BrowserRunner(_testOutput); + var url = await runner.StartServerAndGetUrlAsync(runCommand, $"run --no-silent -c {config} --no-build --project \"{_projectDir!}\" --forward-console"); + url = $"{url}?test=InterpPgoTest&iterationCount={iterationCount}"; + + _testOutput.WriteLine($"/// Spawning browser at URL {url}"); + + IBrowser browser = await runner.SpawnBrowserAsync(url); + IBrowserContext context = await browser.NewContextAsync(); + + string output; + { + _testOutput.WriteLine("/// First run"); + var page = await runner.RunAsync(context, url); + await runner.WaitForExitMessageAsync(TimeSpan.FromSeconds(6 * 30)); + lock (runner.OutputLines) + output = string.Join(Environment.NewLine, runner.OutputLines); + + Assert.Contains("Hello, World!", output); + // Verify that no PGO table was located in cache + Assert.Contains("Failed to load interp_pgo table", output); + // Verify that the table was saved after the app ran + Assert.Contains("Saved interp_pgo table", output); + // Verify that a specific method was tiered by the Greeting calls and recorded by PGO + Assert.Contains("added System.Runtime.CompilerServices.Unsafe:Add (byte&,int) to table", output); + } + + { + _testOutput.WriteLine("/// Second run"); + // Clear the shared output lines buffer so it's empty for the next run. + lock (runner.OutputLines) + runner.OutputLines.Clear(); + // resetExitedState is necessary for WaitForExitMessageAsync to work correctly + var page = await runner.RunAsync(context, url, resetExitedState: true); + await runner.WaitForExitMessageAsync(TimeSpan.FromSeconds(30)); + lock (runner.OutputLines) + output = string.Join(Environment.NewLine, runner.OutputLines); + + Assert.Contains("Hello, World!", output); + // Verify that table data was loaded from cache + // if this breaks, it could be caused by change in config which affects the config hash and the cache storage hash key + Assert.Contains(" bytes of interp_pgo data (table size == ", output); + // Verify that the table was saved after the app ran + Assert.Contains("Saved interp_pgo table", output); + // Verify that method(s) were found in the table and eagerly tiered + Assert.Contains("because it was in the interp_pgo table", output); + // Verify that a specific method was tiered by the Greeting calls and recorded by PGO + Assert.Contains("added System.Runtime.CompilerServices.Unsafe:Add (byte&,int) to table", output); + } + + _testOutput.WriteLine("/// Done"); + + (context as IDisposable)?.Dispose(); + (browser as IDisposable)?.Dispose(); + } +} diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs index cf16a0536a38..038951e1822e 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs @@ -23,7 +23,7 @@ public LazyLoadingTests(ITestOutputHelper output, SharedBuildPerTestClassFixture [Fact] public async Task LoadLazyAssemblyBeforeItIsNeeded() { - CopyTestAsset("WasmBasicTestApp", "LazyLoadingTests"); + CopyTestAsset("WasmBasicTestApp", "LazyLoadingTests", "App"); PublishProject("Debug"); var result = await RunSdkStyleAppForPublish(new(Configuration: "Debug", TestScenario: "LazyLoadingTest")); @@ -33,7 +33,7 @@ public async Task LoadLazyAssemblyBeforeItIsNeeded() [Fact] public async Task FailOnMissingLazyAssembly() { - CopyTestAsset("WasmBasicTestApp", "LazyLoadingTests"); + CopyTestAsset("WasmBasicTestApp", "LazyLoadingTests", "App"); PublishProject("Debug"); var result = await RunSdkStyleAppForPublish(new( diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LibraryInitializerTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LibraryInitializerTests.cs index e985ad23d89a..c4380ed755a5 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LibraryInitializerTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LibraryInitializerTests.cs @@ -26,7 +26,7 @@ public LibraryInitializerTests(ITestOutputHelper output, SharedBuildPerTestClass [Fact] public async Task LoadLibraryInitializer() { - CopyTestAsset("WasmBasicTestApp", "LibraryInitializerTests_LoadLibraryInitializer"); + CopyTestAsset("WasmBasicTestApp", "LibraryInitializerTests_LoadLibraryInitializer", "App"); PublishProject("Debug"); var result = await RunSdkStyleAppForPublish(new(Configuration: "Debug", TestScenario: "LibraryInitializerTest")); @@ -39,7 +39,7 @@ public async Task LoadLibraryInitializer() [Fact] public async Task AbortStartupOnError() { - CopyTestAsset("WasmBasicTestApp", "LibraryInitializerTests_AbortStartupOnError"); + CopyTestAsset("WasmBasicTestApp", "LibraryInitializerTests_AbortStartupOnError", "App"); PublishProject("Debug"); var result = await RunSdkStyleAppForPublish(new( diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/ModuleConfigTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/ModuleConfigTests.cs new file mode 100644 index 000000000000..532751a4ac53 --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/ModuleConfigTests.cs @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; + +#nullable enable + +namespace Wasm.Build.Tests.TestAppScenarios; + +public class ModuleConfigTests : AppTestBase +{ + public ModuleConfigTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public async Task DownloadProgressFinishes(bool failAssemblyDownload) + { + CopyTestAsset("WasmBasicTestApp", $"ModuleConfigTests_DownloadProgressFinishes_{failAssemblyDownload}", "App"); + PublishProject("Debug"); + + var result = await RunSdkStyleAppForPublish(new( + Configuration: "Debug", + TestScenario: "DownloadResourceProgressTest", + BrowserQueryString: new Dictionary { ["failAssemblyDownload"] = failAssemblyDownload.ToString().ToLowerInvariant() } + )); + Assert.True( + result.TestOutput.Any(m => m.Contains("DownloadResourceProgress: Finished")), + "The download progress test didn't emit expected error message" + ); + Assert.True( + result.ConsoleOutput.Any(m => m.Contains("Retrying download")) == failAssemblyDownload, + failAssemblyDownload + ? "The download progress test didn't emit expected message about retrying download" + : "The download progress test did emit unexpected message about retrying download" + ); + Assert.False( + result.ConsoleOutput.Any(m => m.Contains("Retrying download (2)")), + "The download progress test did emit unexpected message about second download retry" + ); + Assert.True( + result.TestOutput.Any(m => m.Contains("Throw error instead of downloading resource") == failAssemblyDownload), + failAssemblyDownload + ? "The download progress test didn't emit expected message about failing download" + : "The download progress test did emit unexpected message about failing download" + ); + } + + [Fact] + public async Task OutErrOverrideWorks() + { + CopyTestAsset("WasmBasicTestApp", $"ModuleConfigTests_OutErrOverrideWorks", "App"); + PublishProject("Debug"); + + var result = await RunSdkStyleAppForPublish(new( + Configuration: "Debug", + TestScenario: "OutErrOverrideWorks" + )); + Assert.True( + result.ConsoleOutput.Any(m => m.Contains("Emscripten out override works!")), + "Emscripten out override doesn't work" + ); + Assert.True( + result.ConsoleOutput.Any(m => m.Contains("Emscripten err override works!")), + "Emscripten err override doesn't work" + ); + } +} diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SatelliteLoadingTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SatelliteLoadingTests.cs index 2088e1522ad7..517f34255f99 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SatelliteLoadingTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SatelliteLoadingTests.cs @@ -26,7 +26,7 @@ public SatelliteLoadingTests(ITestOutputHelper output, SharedBuildPerTestClassFi [Fact] public async Task LoadSatelliteAssembly() { - CopyTestAsset("WasmBasicTestApp", "SatelliteLoadingTests"); + CopyTestAsset("WasmBasicTestApp", "SatelliteLoadingTests", "App"); BuildProject("Debug"); var result = await RunSdkStyleAppForBuild(new(Configuration: "Debug", TestScenario: "SatelliteAssembliesTest")); diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SignalRClientTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SignalRClientTests.cs deleted file mode 100644 index 1b09272b4879..000000000000 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SignalRClientTests.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Microsoft.Playwright; -using Xunit.Abstractions; -using Xunit; - -#nullable enable - -namespace Wasm.Build.Tests.TestAppScenarios; - -public class SignalRClientTests : AppTestBase -{ - public SignalRClientTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) - : base(output, buildContext) - { - } - - [ConditionalTheory(typeof(BuildTestBase), nameof(IsWorkloadWithMultiThreadingForDefaultFramework))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/100445")] // to be fixed by: "https://github.com/dotnet/aspnetcore/issues/54365" - [InlineData("Debug", "LongPolling")] - [InlineData("Release", "LongPolling")] - [InlineData("Debug", "WebSockets")] - [InlineData("Release", "WebSockets")] - public async Task SignalRPassMessages(string config, string transport) - { - BlazorHostedBuild(config, - assetName: "BlazorHostedApp", - clientDirRelativeToProjectDir: "../BlazorHosted.Client", - generatedProjectNamePrefix: "SignalRClientTests", - runtimeType: RuntimeVariant.MultiThreaded); - - List consoleOutput = new(); - List serverOutput = new(); - - var result = await RunSdkStyleAppForBuild(new( - Configuration: config, - // We are using build (not publish), - // we need to instruct static web assets to use manifest file, - // because wwwroot in bin doesn't contain all files (for build) - ServerEnvironment: new Dictionary { ["ASPNETCORE_ENVIRONMENT"] = "Development" }, - BrowserPath: "/chat", - BrowserQueryString: new Dictionary { ["transport"] = transport, ["message"] = "ping" }, - OnServerMessage: (msg) => serverOutput.Add(msg), - OnConsoleMessage: async (page, msg) => - { - consoleOutput.Add(msg.Text); - if (msg.Text.Contains("TestOutput ->")) - _testOutput.WriteLine(msg.Text); - - // prevent timeouts with [Long Running Test] on error - if (msg.Text.ToLowerInvariant().Contains("error")) - { - Console.WriteLine(msg.Text); - Console.WriteLine(_testOutput); - throw new Exception(msg.Text); - } - - if (msg.Text.Contains("Finished GetQueryParameters")) - await SaveClickButtonAsync(page, "button#connectButton"); - - if (msg.Text.Contains("SignalR connected")) - await SaveClickButtonAsync(page, "button#subscribeButton"); - - if (msg.Text.Contains("Subscribed to ReceiveMessage")) - await SaveClickButtonAsync(page, "button#sendMessageButton"); - - if (msg.Text.Contains("ReceiveMessage from server")) - await SaveClickButtonAsync(page, "button#exitProgramButton"); - } - )); - - string output = _testOutput.ToString() ?? ""; - Assert.NotEmpty(output); - // check sending and receiving threadId - string threadIdUsedForSending = GetThreadOfAction(output, @"SignalRPassMessages was sent by CurrentManagedThreadId=(\d+)", "signalR message was sent"); - string threadIdUsedForReceiving = GetThreadOfAction(output, @"ReceiveMessage from server on CurrentManagedThreadId=(\d+)", "signalR message was received"); - Assert.True("1" != threadIdUsedForSending || "1" != threadIdUsedForReceiving, - $"Expected to send/receive with signalR in non-UI threads, instead only CurrentManagedThreadId=1 was used. TestOutput: {output}."); - } - - private string GetThreadOfAction(string testOutput, string pattern, string actionDescription) - { - Match match = Regex.Match(testOutput, pattern); - Assert.True(match.Success, $"Expected to find a log that {actionDescription}. TestOutput: {testOutput}."); - return match.Groups[1].Value ?? ""; - } - - private async Task SaveClickButtonAsync(IPage page, string selector) - { - await page.WaitForSelectorAsync(selector); - await page.ClickAsync(selector); - } -} diff --git a/src/mono/wasm/Wasm.Build.Tests/TestMainJsProjectProvider.cs b/src/mono/wasm/Wasm.Build.Tests/TestMainJsProjectProvider.cs index 89a1ddc8c132..1f481b680105 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestMainJsProjectProvider.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestMainJsProjectProvider.cs @@ -26,6 +26,7 @@ protected override IReadOnlyDictionary GetAllKnownDotnetFilesToFin { "dotnet.js.map", false }, { "dotnet.native.js", false }, { "dotnet.native.js.symbols", false }, + { "dotnet.globalization.js", false }, { "dotnet.native.wasm", false }, { "dotnet.native.worker.js", false }, { "dotnet.runtime.js", false }, @@ -61,6 +62,9 @@ protected override IReadOnlySet GetDotNetFilesExpectedSet(AssertBundleOp } } + if (assertOptions.GlobalizationMode is GlobalizationMode.Hybrid) + res.Add("dotnet.globalization.js"); + if (assertOptions.AssertSymbolsFile && assertOptions.ExpectSymbolsFile) res.Add("dotnet.native.js.symbols"); diff --git a/src/mono/wasm/Wasm.Build.Tests/TestMainJsTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/TestMainJsTestBase.cs index 2c56227c6693..4d5db19dc53f 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestMainJsTestBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestMainJsTestBase.cs @@ -55,7 +55,7 @@ protected TestMainJsTestBase(ITestOutputHelper output, SharedBuildPerTestClassFi Path.Combine(_projectDir, "test-main.js") ); - File.WriteAllText(Path.Combine(_projectDir!, "index.html"), @""); + File.WriteAllText(Path.Combine(_projectDir!, "index.html"), @""); } else if (_projectDir is null) { diff --git a/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj b/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj index 81110b4568ff..62601dd54d85 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj +++ b/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj @@ -19,6 +19,7 @@ true + true true @@ -30,8 +31,13 @@ - <_WasmBrowserPathForTests Condition="'$(BROWSER_PATH_FOR_TESTS)' != ''">$(BROWSER_PATH_FOR_TESTS) - <_WasmBrowserPathForTests Condition="'$(_WasmBrowserPathForTests)' == '' and '$(InstallChromeForTests)' == 'true'">$(ChromeBinaryPath) + <_WasmChromePathForTests Condition="'$(CHROME_PATH_FOR_TESTS)' != ''">$(CHROME_PATH_FOR_TESTS) + <_WasmChromePathForTests Condition="'$(_WasmChromePathForTests)' == '' and '$(InstallChromeForTests)' == 'true'">$(ChromeBinaryPath) + <_WasmFirefoxPathForTests Condition="'$(FIREFOX_PATH_FOR_TESTS)' != ''">$(FIREFOX_PATH_FOR_TESTS) + <_WasmFirefoxPathForTests Condition="'$(_WasmFirefoxPathForTests)' == '' and '$(InstallFirefoxForTests)' == 'true'">$(FirefoxBinaryPath) + + <_WasmFirefoxPathForTests Condition="'$(FIREFOX_PATH_FOR_TESTS)' != ''">$(FIREFOX_PATH_FOR_TESTS) + <_WasmFirefoxPathForTests Condition="'$(_WasmFirefoxPathForTests)' == '' and '$(InstallFirefoxForTests)' == 'true'">$(FirefoxBinaryPath) RunScriptTemplate.cmd RunScriptTemplate.sh @@ -57,6 +63,11 @@ + + + + + @@ -67,8 +78,11 @@ - - + + + + + @@ -104,8 +118,8 @@ - - + + diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmRunOutOfAppBundleTests.cs b/src/mono/wasm/Wasm.Build.Tests/WasmRunOutOfAppBundleTests.cs index a4651a9824e4..775d9cb46582 100644 --- a/src/mono/wasm/Wasm.Build.Tests/WasmRunOutOfAppBundleTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/WasmRunOutOfAppBundleTests.cs @@ -41,7 +41,7 @@ public void RunOutOfAppBundle(BuildArgs buildArgs, RunHost host, string id) indexHtmlPath = Path.Combine(outerDir, "index.html"); if (!File.Exists(indexHtmlPath)) { - var html = @""; + var html = @""; File.WriteAllText(indexHtmlPath, html); } } diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmSdkBasedProjectProvider.cs b/src/mono/wasm/Wasm.Build.Tests/WasmSdkBasedProjectProvider.cs index 9cfbcca73843..5807120bf887 100644 --- a/src/mono/wasm/Wasm.Build.Tests/WasmSdkBasedProjectProvider.cs +++ b/src/mono/wasm/Wasm.Build.Tests/WasmSdkBasedProjectProvider.cs @@ -26,6 +26,7 @@ protected override IReadOnlyDictionary GetAllKnownDotnetFilesToFin { "dotnet.js.map", false }, { "dotnet.native.js", true }, { "dotnet.native.js.symbols", false }, + { "dotnet.globalization.js", true }, { "dotnet.native.wasm", false }, { "dotnet.native.worker.js", true }, { "dotnet.runtime.js", true }, @@ -45,6 +46,10 @@ protected override IReadOnlySet GetDotNetFilesExpectedSet(AssertBundleOp { res.Add("dotnet.native.worker.js"); } + if (assertOptions.GlobalizationMode is GlobalizationMode.Hybrid) + { + res.Add("dotnet.globalization.js"); + } if (!assertOptions.IsPublish) { @@ -107,7 +112,14 @@ public void AssertBundle(AssertWasmSdkBundleOptions assertOptions) string buildType = assertOptions.IsPublish ? "publish" : "build"; var nativeFilesToCheck = new List() { "dotnet.native.wasm", "dotnet.native.js" }; if (assertOptions.RuntimeType == RuntimeVariant.MultiThreaded) + { nativeFilesToCheck.Add("dotnet.native.worker.js"); + } + if (assertOptions.GlobalizationMode == GlobalizationMode.Hybrid) + { + nativeFilesToCheck.Add("dotnet.globalization.js"); + } + foreach (string nativeFilename in nativeFilesToCheck) { if (!actualDotnetFiles.TryGetValue(nativeFilename, out DotNetFileName? dotnetFile)) diff --git a/src/mono/wasm/build/WasmApp.Common.targets b/src/mono/wasm/build/WasmApp.Common.targets index 5c7e4353fee0..54a202840b41 100644 --- a/src/mono/wasm/build/WasmApp.Common.targets +++ b/src/mono/wasm/build/WasmApp.Common.targets @@ -44,6 +44,8 @@ - $(EmccLinkOptimizationFlag) - Optimization flag to use for the link step - $(EmccCompileOptimizationFlag) - Optimization flag to use for compiling native files + - $(WasmBitcodeCompileOptimizationFlag) + - Optimization flag to use for compiling bitcode files - $(EmccFlags) - Emcc flags used for both compiling native files, and linking - $(EmccExtraLDFlags) - Extra emcc flags for linking @@ -251,9 +253,16 @@ - - - <_MonoComponent Include="hot_reload;debugger" /> + + + <_WasmDebuggerSupport Condition="'$(WasmDebugLevel)' != '' and '$(WasmDebugLevel)' != '0'">true + <_WasmDebuggerSupport Condition="'$(WasmDebugLevel)' != '' and '$(WasmDebugLevel)' == '0'">false + <_WasmDebuggerSupport Condition="'$(_WasmDebuggerSupport)' == '' and '$(WasmBuildingForNestedPublish)' == 'true'">false + <_WasmDebuggerSupport Condition="'$(_WasmDebuggerSupport)' == ''">true + + + <_MonoComponent Include="debugger" /> + <_MonoComponent Include="hot_reload" /> @@ -288,6 +297,11 @@ <_WasmShouldAOT Condition="'$(_WasmShouldAOT)' == ''">false + + <_ExistingNativeLibrary Include="@(NativeLibrary->Exists())" /> + + + @@ -421,7 +435,7 @@ - + @@ -590,7 +604,7 @@ - + <_AssembliesToScan Include="@(_WasmAssembliesInternal)" /> @@ -793,11 +807,11 @@ - + diff --git a/src/mono/wasm/templates/templates/browser/Program.cs b/src/mono/wasm/templates/templates/browser/Program.cs index ecf115b0e712..a9726e67fd6a 100644 --- a/src/mono/wasm/templates/templates/browser/Program.cs +++ b/src/mono/wasm/templates/templates/browser/Program.cs @@ -1,18 +1,55 @@ using System; +using System.Diagnostics; using System.Runtime.InteropServices.JavaScript; +using System.Threading.Tasks; Console.WriteLine("Hello, Browser!"); -public partial class MyClass +if (args.Length == 1 && args[0] == "start") + StopwatchSample.Start(); + +while(true) +{ + StopwatchSample.Render(); + await Task.Delay(1000); +} + +partial class StopwatchSample { + private static Stopwatch stopwatch = new(); + + public static void Start() => stopwatch.Start(); + public static void Render() => SetInnerText("#time", stopwatch.Elapsed.ToString(@"mm\:ss")); + + [JSImport("dom.setInnerText", "main.js")] + internal static partial void SetInnerText(string selector, string content); + [JSExport] - internal static string Greeting() + internal static bool Toggle() { - var text = $"Hello, World! Greetings from {GetHRef()}"; - Console.WriteLine(text); - return text; + if (stopwatch.IsRunning) + { + stopwatch.Stop(); + return false; + } + else + { + stopwatch.Start(); + return true; + } } - [JSImport("window.location.href", "main.js")] - internal static partial string GetHRef(); + [JSExport] + internal static void Reset() + { + if (stopwatch.IsRunning) + stopwatch.Restart(); + else + stopwatch.Reset(); + + Render(); + } + + [JSExport] + internal static bool IsRunning() => stopwatch.IsRunning; } diff --git a/src/mono/wasm/templates/templates/browser/wwwroot/index.html b/src/mono/wasm/templates/templates/browser/wwwroot/index.html index 417803bf38d9..287d8b531921 100644 --- a/src/mono/wasm/templates/templates/browser/wwwroot/index.html +++ b/src/mono/wasm/templates/templates/browser/wwwroot/index.html @@ -11,7 +11,14 @@ - +

    Stopwatch

    +

    + Time elapsed in .NET is loading... +

    +

    + + +

    diff --git a/src/mono/wasm/templates/templates/browser/wwwroot/main.js b/src/mono/wasm/templates/templates/browser/wwwroot/main.js index afcf21e4e651..82c86ed196b4 100644 --- a/src/mono/wasm/templates/templates/browser/wwwroot/main.js +++ b/src/mono/wasm/templates/templates/browser/wwwroot/main.js @@ -4,24 +4,29 @@ import { dotnet } from './_framework/dotnet.js' const { setModuleImports, getAssemblyExports, getConfig, runMain } = await dotnet - .withDiagnosticTracing(false) - .withApplicationArgumentsFromQuery() + .withApplicationArguments("start") .create(); setModuleImports('main.js', { - window: { - location: { - href: () => globalThis.window.location.href - } + dom: { + setInnerText: (selector, time) => document.querySelector(selector).innerText = time } }); const config = getConfig(); const exports = await getAssemblyExports(config.mainAssemblyName); -const text = exports.MyClass.Greeting(); -console.log(text); -document.getElementById('out').innerHTML = text; +document.getElementById('reset').addEventListener('click', e => { + exports.StopwatchSample.Reset(); + e.preventDefault(); +}); + +const pauseButton = document.getElementById('pause'); +pauseButton.addEventListener('click', e => { + const isRunning = exports.StopwatchSample.Toggle(); + pauseButton.innerText = isRunning ? 'Pause' : 'Start'; + e.preventDefault(); +}); // run the C# Main() method and keep the runtime process running and executing further API calls await runMain(); \ No newline at end of file diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/BlazorHosted.Client.csproj b/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/BlazorHosted.Client.csproj deleted file mode 100644 index 314f3453a08e..000000000000 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/BlazorHosted.Client.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - net9.0 - enable - enable - true - - CS8604;CS4014 - - - - - - - - - - diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Helper.cs b/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Helper.cs deleted file mode 100644 index 38ead1438099..000000000000 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Helper.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Specialized; -using Microsoft.AspNetCore.Http.Connections; - -namespace BlazorHosted.Client; - -public static class Helper -{ - public static string GetValue(NameValueCollection parameters, string key) - { - var values = parameters.GetValues(key); - if (values == null || values.Length == 0) - { - throw new Exception($"Parameter '{key}' is required in the query string"); - } - if (values.Length > 1) - { - throw new Exception($"Parameter '{key}' should be unique in the query string"); - } - return values[0]; - } - - public static HttpTransportType StringToTransportType(string transport) - { - switch (transport.ToLowerInvariant()) - { - case "longpolling": - return HttpTransportType.LongPolling; - case "websockets": - return HttpTransportType.WebSockets; - default: - throw new Exception($"{transport} is invalid transport type"); - } - } - - public static void TestOutputWriteLine(string message) - { - Console.WriteLine("TestOutput -> " + message); - } -} diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Pages/Chat.razor b/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Pages/Chat.razor deleted file mode 100644 index f90aa96c87b9..000000000000 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Pages/Chat.razor +++ /dev/null @@ -1,116 +0,0 @@ -@page "/chat" -@using Microsoft.AspNetCore.SignalR -@using Microsoft.AspNetCore.SignalR.Client -@using Microsoft.AspNetCore.Http.Connections; -@using System.Web; -@inject NavigationManager NavigationManager -@inject IJSRuntime JSRuntime - -

    Chat Room

    - - - - - -
    - @foreach (var chatMessage in chatMessages) - { -

    @chatMessage

    - } -
    - -@code { - private string _hubUrl = string.Empty; - private HubConnection? _hubConnection; - private string message = string.Empty; - private string transport = string.Empty; - private List chatMessages = new List(); - private string wrongQueryError = "Query string with parameters 'message' and 'transport' are required"; - - // remove when https://github.com/dotnet/runtime/issues/96546 is fixed - // log that rendering is about to start in case we hit the issue before OnAfterRender is called - protected override bool ShouldRender() - { - bool shouldRender = base.ShouldRender(); - Helper.TestOutputWriteLine($"ShouldRender = {shouldRender}"); - return shouldRender; - } - - protected override void OnAfterRender(bool firstRender) - { - if (firstRender) - { - Helper.TestOutputWriteLine($"OnAfterRender on CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); - GetQueryParameters(); - } - base.OnAfterRender(firstRender); - } - - private void GetQueryParameters() - { - var uri = new Uri(NavigationManager.Uri); - if (string.IsNullOrEmpty(uri.Query)) - { - throw new Exception(wrongQueryError); - } - var parameters = HttpUtility.ParseQueryString(uri.Query); - if (parameters == null) - { - throw new Exception(wrongQueryError); - } - transport = Helper.GetValue(parameters, "transport"); - message = $"{transport} {Helper.GetValue(parameters, "message")}" ; - Helper.TestOutputWriteLine($"Finished GetQueryParameters on CurrentManagedThreadId={Environment.CurrentManagedThreadId}."); - } - - private async Task Connect() - { - _hubUrl = NavigationManager.BaseUri + "chathub"; - HttpTransportType httpTransportType = Helper.StringToTransportType(transport); - _hubConnection = new HubConnectionBuilder() - .WithUrl(_hubUrl, options => - { - options.Transports = httpTransportType; - }) - .Build(); - - await _hubConnection.StartAsync(); - Helper.TestOutputWriteLine($"SignalR connected by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); - } - - private void Subscribe() - { - _hubConnection.On("ReceiveMessage", (message) => - { - Helper.TestOutputWriteLine($"Message = [{message}]. ReceiveMessage from server on CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); - chatMessages.Add(message); - }); - Helper.TestOutputWriteLine($"Subscribed to ReceiveMessage by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); - } - - private async Task SignalRPassMessages() => - await Task.Run(async () => - { - await _hubConnection.SendAsync( "SendMessage", message, Environment.CurrentManagedThreadId); - Helper.TestOutputWriteLine($"SignalRPassMessages was sent by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); - }); - - private async Task SendExitSignal() - { - await DisposeHubConnection(); - // exit the client - Helper.TestOutputWriteLine($"SendExitSignal by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); - await JSRuntime.InvokeVoidAsync("eval", "setTimeout(() => { getDotnetRuntime(0).exit(0); }, 50);"); - } - - private async Task DisposeHubConnection() - { - if (_hubConnection != null) - { - _hubConnection.Remove("ReceiveMessage"); - await _hubConnection.DisposeAsync(); - _hubConnection = null; - } - Helper.TestOutputWriteLine($"SignalR disconnected by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); - } -} diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Program.cs b/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Program.cs deleted file mode 100644 index 67a2fb06d6a1..000000000000 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Program.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using BlazorHosted.Client; -using Microsoft.AspNetCore.Components.Web; -using Microsoft.AspNetCore.Components.WebAssembly.Hosting; - -var builder = WebAssemblyHostBuilder.CreateDefault(args); -builder.RootComponents.Add("#app"); -builder.RootComponents.Add("head::after"); -builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); - -await builder.Build().RunAsync().ConfigureAwait(false); diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/_Imports.razor b/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/_Imports.razor deleted file mode 100644 index d39afd384f89..000000000000 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/_Imports.razor +++ /dev/null @@ -1,6 +0,0 @@ -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.AspNetCore.Components.Routing -@using Microsoft.AspNetCore.Components.Web -@using Microsoft.JSInterop -@using BlazorHosted.Client -@using BlazorHosted.Client.Layout \ No newline at end of file diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/wwwroot/favicon.ico b/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/wwwroot/favicon.ico deleted file mode 100644 index 63e859b476ef..000000000000 Binary files a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/wwwroot/favicon.ico and /dev/null differ diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/wwwroot/index.html b/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/wwwroot/index.html deleted file mode 100644 index 56dd2027fdf8..000000000000 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/wwwroot/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - BlazorHosted - - - - -
    Loading...
    - -
    - An unhandled error has occurred. - Reload - 🗙 -
    - - - - - diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/BlazorHosted.Server.csproj b/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/BlazorHosted.Server.csproj deleted file mode 100644 index cc3ac1aae891..000000000000 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/BlazorHosted.Server.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - net9.0 - enable - enable - - CA2007 - - - - - - - - - - - diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/Program.cs b/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/Program.cs deleted file mode 100644 index fea18a9250cc..000000000000 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/Program.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.Extensions.Configuration; -using System; -using Microsoft.Extensions.Logging; -using BlazorHosted.Server.Hubs; - -var builder = WebApplication.CreateBuilder(args); - -builder.Services.AddControllersWithViews(); -builder.Services.AddRazorPages(); -builder.Services.AddSignalR(options => -{ - options.KeepAliveInterval = TimeSpan.Zero; // minimize keep-alive messages -}); - -var app = builder.Build(); - -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - app.UseWebAssemblyDebugging(); -} -else -{ - app.UseExceptionHandler("/Error"); - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); -} - -// Add headers to enable SharedArrayBuffer -app.Use(async (context, next) => -{ - var response = context.Response; - response.Headers.Append("Cross-Origin-Opener-Policy", "same-origin"); - response.Headers.Append("Cross-Origin-Embedder-Policy", "require-corp"); - - await next(); -}); -app.UseBlazorFrameworkFiles(); -app.UseStaticFiles(); - -app.UseRouting(); - -app.MapRazorPages(); -app.MapControllers(); -app.MapFallbackToFile("index.html"); - -app.MapHub("/chathub"); - -app.Run(); diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/appsettings.json b/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/appsettings.json deleted file mode 100644 index 75b7c2aa1ece..000000000000 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/appsettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} \ No newline at end of file diff --git a/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/UnmanagedCallback.cs b/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/UnmanagedCallback.cs new file mode 100644 index 000000000000..2157909c3d5f --- /dev/null +++ b/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/UnmanagedCallback.cs @@ -0,0 +1,28 @@ +using System; +using System.Runtime.InteropServices; + +public unsafe partial class Test +{ + public unsafe static int Main(string[] args) + { + ((IntPtr)(delegate* unmanaged)&Interop.Managed8\u4F60Func).ToString(); + + Console.WriteLine($"main: {args.Length}"); + Interop.UnmanagedFunc(); + return 42; + } +} + +file partial class Interop +{ + [UnmanagedCallersOnly(EntryPoint = "ManagedFunc")] + public static int Managed8\u4F60Func(int number) + { + // called from UnmanagedFunc + Console.WriteLine($"Managed8\u4F60Func({number}) -> 42"); + return 42; + } + + [DllImport("local", EntryPoint = "UnmanagedFunc")] + public static extern void UnmanagedFunc(); // calls ManagedFunc +} diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/Common/Program.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/Common/Program.cs index 4f38c02031c7..eda19b81f506 100644 --- a/src/mono/wasm/testassets/WasmBasicTestApp/App/Common/Program.cs +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/Common/Program.cs @@ -2,3 +2,4 @@ // The .NET Foundation licenses this file to you under the MIT license. System.Console.WriteLine("WasmBasicTestApp"); +System.Console.Error.WriteLine("WasmBasicTestApp stderr"); diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/InterpPgoTest.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/InterpPgoTest.cs new file mode 100644 index 000000000000..6d093133b377 --- /dev/null +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/InterpPgoTest.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.IO; +using System.Text.Json; +using System.Runtime.InteropServices.JavaScript; + +public partial class InterpPgoTest +{ + [JSImport("window.location.href", "main.js")] + internal static partial string GetHRef(); + + [JSExport] + internal static string Greeting() + { + var text = $"Hello, World! Greetings from {GetHRef()}"; + Console.WriteLine(text); + return text; + } +} diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js index 3a01053875c0..e426886485d9 100644 --- a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js @@ -37,7 +37,7 @@ switch (testCase) { let alreadyFailed = []; dotnet.withDiagnosticTracing(true).withResourceLoader((type, name, defaultUri, integrity, behavior) => { if (type === "dotnetjs") { - // loadBootResource could return string with unqualified name of resource. + // loadBootResource could return string with unqualified name of resource. // It assumes that we resolve it with document.baseURI // we test it here return `_framework/${name}`; @@ -66,12 +66,30 @@ switch (testCase) { } }); break; + case "OutErrOverrideWorks": + dotnet.withModuleConfig({ + out: (message) => { + console.log("Emscripten out override works!"); + console.log(message) + }, + err: (message) => { + console.error("Emscripten err override works!"); + console.error(message) + }, + }); + break; + case "InterpPgoTest": + dotnet + .withConsoleForwarding() + .withRuntimeOptions(['--interp-pgo-logging']) + .withInterpreterPgo(true); + break; } -const { getAssemblyExports, getConfig, INTERNAL } = await dotnet.create(); +const { setModuleImports, getAssemblyExports, getConfig, INTERNAL } = await dotnet.create(); const config = getConfig(); const exports = await getAssemblyExports(config.mainAssemblyName); -const assemblyExtension = config.resources.assembly['System.Private.CoreLib.wasm'] !== undefined ? ".wasm" : ".dll"; +const assemblyExtension = config.resources.coreAssembly['System.Private.CoreLib.wasm'] !== undefined ? ".wasm" : ".dll"; // Run the test case try { @@ -97,10 +115,28 @@ try { case "DownloadResourceProgressTest": exit(0); break; + case "OutErrOverrideWorks": + dotnet.run(); + break; case "DebugLevelTest": testOutput("WasmDebugLevel: " + config.debugLevel); exit(0); break; + case "InterpPgoTest": + setModuleImports('main.js', { + window: { + location: { + href: () => globalThis.window.location.href + } + } + }); + const iterationCount = params.get("iterationCount") ?? 70; + for (let i = 0; i < iterationCount; i++) { + exports.InterpPgoTest.Greeting(); + }; + await INTERNAL.interp_pgo_save_data(); + exit(0); + break; default: console.error(`Unknown test case: ${testCase}`); exit(3); diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/AspNetCoreServer.csproj b/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/AspNetCoreServer.csproj new file mode 100644 index 000000000000..9b556e8a965d --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/AspNetCoreServer.csproj @@ -0,0 +1,22 @@ + + + + net9.0 + enable + enable + true + + CA2007 + + + + + + + + + + + + + diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/ChatHub.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/ChatHub.cs similarity index 93% rename from src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/ChatHub.cs rename to src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/ChatHub.cs index 8b2e77807c6f..2a1267d102c2 100644 --- a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Server/ChatHub.cs +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/ChatHub.cs @@ -3,7 +3,8 @@ using Microsoft.AspNetCore.SignalR; -namespace BlazorHosted.Server.Hubs; +namespace Server; + public class ChatHub : Hub { public async Task SendMessage(string message, int sendingThreadId) diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/Program.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/Program.cs new file mode 100644 index 000000000000..b22b8ded516a --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/AspNetCoreServer/Program.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http.Connections; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.FileProviders; +using Microsoft.AspNetCore.StaticFiles; +using Server; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddSignalR(); +var app = builder.Build(); + +// Add headers to enable SharedArrayBuffer +app.Use(async (context, next) => +{ + var response = context.Response; + response.Headers.Append("Cross-Origin-Opener-Policy", "same-origin"); + response.Headers.Append("Cross-Origin-Embedder-Policy", "require-corp"); + + await next(); +}); + +app.UseDefaultFiles(); + +var provider = new FileExtensionContentTypeProvider(); +provider.Mappings[".dll"] = "application/octet-stream"; +provider.Mappings[".pdb"] = "application/octet-stream"; +provider.Mappings[".dat"] = "application/octet-stream"; +app.UseStaticFiles(new StaticFileOptions +{ + ContentTypeProvider = provider, +}); + +ConfigureClientApp(app, "wasmclient"); +ConfigureClientApp(app, "blazorclient"); + +app.Run(); + + +static void ConfigureClientApp(WebApplication app, string clientAppPath) +{ + app.MapWhen( + ctx => ctx.Request.Path.StartsWithSegments($"/{clientAppPath}", out var rest), + clientApp => + { + clientApp + .UseBlazorFrameworkFiles($"/{clientAppPath}") + .UsePathBase($"/{clientAppPath}") + .UseRouting() + .UseEndpoints(endpoints => + { + endpoints.MapHub("/chathub"); + endpoints.MapFallbackToFile($"{clientAppPath}/index.html"); + }); + } + ); +} diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/App.razor b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/App.razor similarity index 100% rename from src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/App.razor rename to src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/App.razor diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/BlazorClient.csproj b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/BlazorClient.csproj new file mode 100644 index 000000000000..5c974a459386 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/BlazorClient.csproj @@ -0,0 +1,22 @@ + + + + net9.0 + enable + enable + true + + CS8604;CS4014 + blazorclient + + + + + + + + + + + + diff --git a/src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Layout/MainLayout.razor b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Layout/MainLayout.razor similarity index 100% rename from src/mono/wasm/testassets/BlazorHostedApp/BlazorHosted.Client/Layout/MainLayout.razor rename to src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Layout/MainLayout.razor diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Pages/Chat.razor b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Pages/Chat.razor new file mode 100644 index 000000000000..6009840f5022 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Pages/Chat.razor @@ -0,0 +1,34 @@ +@page "/" +@inject NavigationManager NavigationManager + +

    Chat Room

    +@code { + private SignalRTest signalRTest = new(); + + // remove when https://github.com/dotnet/runtime/issues/96546 is fixed + // log that rendering is about to start in case we hit the issue before OnAfterRender is called + protected override bool ShouldRender() + { + bool shouldRender = base.ShouldRender(); + TestOutput.WriteLine($"ShouldRender = {shouldRender}"); + return shouldRender; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + TestOutput.WriteLine($"SignalRTest is started on CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); + try + { + int result = await signalRTest.Run(NavigationManager.BaseUri, NavigationManager.Uri); + TestOutput.WriteLine($"SignalRTest finished with code {result}. WASM EXIT {result}"); + } + catch (Exception ex) + { + TestOutput.WriteLine($"SignalRTest failed with exception {ex}. WASM EXIT -1"); + } + } + base.OnAfterRenderAsync(firstRender); + } +} diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Program.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Program.cs new file mode 100644 index 000000000000..bcc0dff43d98 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/Program.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using BlazorClient; +using Microsoft.AspNetCore.Components.Web; +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; + +var builder = WebAssemblyHostBuilder.CreateDefault(args); +builder.RootComponents.Add("#app"); +builder.RootComponents.Add("head::after"); +builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); + +await builder.Build().RunAsync().ConfigureAwait(false); diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/_Imports.razor b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/_Imports.razor new file mode 100644 index 000000000000..1c193c143df2 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/_Imports.razor @@ -0,0 +1,7 @@ +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using Microsoft.JSInterop +@using BlazorClient +@using BlazorClient.Layout +@using Shared \ No newline at end of file diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/wwwroot/index.html b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/wwwroot/index.html new file mode 100644 index 000000000000..f911682fdf48 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/BlazorClient/wwwroot/index.html @@ -0,0 +1,22 @@ + + + + + + + BlazorHosted + + + + +
    Loading...
    + +
    + An unhandled error has occurred. + Reload + 🗙 +
    + + + + diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/QueryParser.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/QueryParser.cs new file mode 100644 index 000000000000..b863fa4ed549 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/QueryParser.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Specialized; + +namespace Shared; + +public static class QueryParser +{ + public static string GetValue(NameValueCollection parameters, string key) + { + var values = parameters.GetValues(key); + if (values == null || values.Length == 0) + { + throw new Exception($"Parameter '{key}' is required in the query string"); + } + if (values.Length > 1) + { + throw new Exception($"Parameter '{key}' should be unique in the query string"); + } + return values[0]; + } +} diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/Shared.csproj b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/Shared.csproj new file mode 100644 index 000000000000..5980a8781983 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/Shared.csproj @@ -0,0 +1,19 @@ + + + + net9.0 + Library + true + enable + CA2007 + + + + + + + + + + + diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/SignalRTest.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/SignalRTest.cs new file mode 100644 index 000000000000..5b4253646413 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/SignalRTest.cs @@ -0,0 +1,114 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Specialized; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http.Connections; +using Microsoft.AspNetCore.SignalR.Client; +using System.Web; + +namespace Shared; + +public class SignalRTest +{ + private TaskCompletionSource? tcs; + private HubConnection? _hubConnection; + private string transport = string.Empty; + private string message = string.Empty; + private string wrongQueryError = "Query string with parameters 'message' and 'transport' is required"; + + public async Task Run(string origin, string fullUrl) + { + tcs = new TaskCompletionSource(); + GetQueryParameters(fullUrl); + await Connect(origin); + await SignalRPassMessages(); + + int delayInMin = 2; + await Task.WhenAny( + tcs!.Task, + Task.Delay(TimeSpan.FromMinutes(delayInMin))); + + if (!tcs!.Task.IsCompleted) + throw new TimeoutException($"Test timed out after waiting {delayInMin} minutes for process to exit."); + return tcs.Task.Result; + + } + + private void SetResult(int value) => tcs?.SetResult(value); + + private void GetQueryParameters(string url) + { + var uri = new Uri(url); + if (string.IsNullOrEmpty(uri.Query)) + { + throw new Exception(wrongQueryError); + } + var parameters = HttpUtility.ParseQueryString(uri.Query); + if (parameters == null) + { + throw new Exception(wrongQueryError); + } + transport = QueryParser.GetValue(parameters, "transport"); + message = $"{transport} {QueryParser.GetValue(parameters, "message")}" ; + TestOutput.WriteLine($"Finished GetQueryParameters on CurrentManagedThreadId={Environment.CurrentManagedThreadId}."); + } + + private async Task Connect(string baseUri) + { + string hubUrl = new Uri(new Uri(baseUri), "chathub").ToString(); + Console.WriteLine($"hubUrl: {hubUrl}"); + HttpTransportType httpTransportType = StringToTransportType(transport); + _hubConnection = new HubConnectionBuilder() + .WithUrl(hubUrl, options => + { + options.Transports = httpTransportType; + }) + .Build(); + + _hubConnection.On("ReceiveMessage", async (message) => + { + TestOutput.WriteLine($"Message = [{message}]. ReceiveMessage from server on CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); + await DisposeHubConnection(); + SetResult(0); + }); + TestOutput.WriteLine($"Subscribed to ReceiveMessage by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); + + await _hubConnection.StartAsync(); + TestOutput.WriteLine($"SignalR connected by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); + } + + private static HttpTransportType StringToTransportType(string transport) + { + switch (transport.ToLowerInvariant()) + { + case "longpolling": + return HttpTransportType.LongPolling; + case "websockets": + return HttpTransportType.WebSockets; + default: + throw new Exception($"{transport} is invalid transport type"); + } + } + + private async Task SignalRPassMessages() => + await Task.Run(async () => + { + if (_hubConnection == null) + throw new Exception("Cannot send messages before establishing hub connection"); + await _hubConnection!.SendAsync("SendMessage", message, Environment.CurrentManagedThreadId); + TestOutput.WriteLine($"SignalRPassMessages was sent by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); + }); + + private async Task DisposeHubConnection() + { + if (_hubConnection != null) + { + _hubConnection.Remove("ReceiveMessage"); + await _hubConnection.DisposeAsync(); + _hubConnection = null; + } + TestOutput.WriteLine($"SignalR disconnected by CurrentManagedThreadId={Environment.CurrentManagedThreadId}"); + } +} diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/TestOutput.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/TestOutput.cs new file mode 100644 index 000000000000..3cb92a24277c --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/Shared/TestOutput.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Shared; + +public static class TestOutput +{ + public static void WriteLine(string message) + { + Console.WriteLine("TestOutput -> " + message); + } + + public static void WriteLine(object message) + { + Console.Write("TestOutput -> "); + Console.WriteLine(message); + } +} diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/Program.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/Program.cs new file mode 100644 index 000000000000..88bed62c3608 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/Program.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Threading.Tasks; +using Shared; + +public partial class Program +{ + public static async Task Main(string[] args) + { + if (args.Length < 2) + throw new Exception("Expected url origin and href passed as arguments"); + + SignalRTest test = new(); + Console.WriteLine($"arg0: {args[0]}, arg1: {args[1]}"); + int result = await test.Run(origin: args[0], fullUrl: args[1]); + if (result != 0) + throw new Exception($"WasmBrowser finished with non-success code: {result}"); + } +} diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/TestOutput.cs b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/TestOutput.cs new file mode 100644 index 000000000000..5755b753b5e4 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/TestOutput.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +public static class TestOutput +{ + public static void WriteLine(string message) + { + Console.WriteLine("TestOutput -> " + message); + } + + public static void WriteLine(object message) + { + Console.Write("TestOutput -> "); + Console.WriteLine(message); + } +} diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/WasmBrowserClient.csproj b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/WasmBrowserClient.csproj new file mode 100644 index 000000000000..a74e1246d8bd --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/WasmBrowserClient.csproj @@ -0,0 +1,17 @@ + + + net9.0 + browser-wasm + Exe + true + enable + + CA1050;CA2007;CA1861;IL2104 + true + wasmclient + + + + + + diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/index.html b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/index.html new file mode 100644 index 000000000000..86bc345d2e23 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/index.html @@ -0,0 +1,17 @@ + + + + + + + WasmBrowser + + + + + + + + + + \ No newline at end of file diff --git a/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/main.js b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/main.js new file mode 100644 index 000000000000..f182fd9eff99 --- /dev/null +++ b/src/mono/wasm/testassets/WasmOnAspNetCore/WasmBrowserClient/wwwroot/main.js @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +import { dotnet, exit } from './_framework/dotnet.js' + +try { + const dotnetRuntime = await dotnet + .withElementOnExit() + .withExitCodeLogging() + .withExitOnUnhandledError() + .create(); + const config = dotnetRuntime.getConfig(); + var url = window.location.origin + window.location.pathname; + await dotnetRuntime.runMainAndExit(config.mainAssemblyName, [url, window.location.href]); + +} +catch (err) { + exit(2, err); +} \ No newline at end of file diff --git a/src/mono/wasm/testassets/native-libs/local.c b/src/mono/wasm/testassets/native-libs/local.c new file mode 100644 index 000000000000..4d7a660513c1 --- /dev/null +++ b/src/mono/wasm/testassets/native-libs/local.c @@ -0,0 +1,10 @@ +#include +int ManagedFunc(int number); + +void UnmanagedFunc() +{ + int ret = 0; + printf("UnmanagedFunc calling ManagedFunc\n"); + ret = ManagedFunc(123); + printf("ManagedFunc returned %d\n", ret); +} \ No newline at end of file diff --git a/src/native/containers/containers.cmake b/src/native/containers/containers.cmake index dd8829e3bf04..4749dceea2dd 100644 --- a/src/native/containers/containers.cmake +++ b/src/native/containers/containers.cmake @@ -8,6 +8,13 @@ list(APPEND SHARED_CONTAINER_SOURCES dn-queue.c dn-umap.c dn-vector.c + # FIXME: Including these here causes a linker collision with sgen metadata + # dn-simdhash.c + # dn-simdhash-string-ptr.c + # dn-simdhash-u32-ptr.c + # dn-simdhash-ptr-ptr.c + # dn-simdhash-ght-compatible.c + # dn-simdhash-ptrpair-ptr.c ) list(APPEND SHARED_CONTAINER_HEADERS @@ -24,4 +31,11 @@ list(APPEND SHARED_CONTAINER_HEADERS dn-vector-ptr.h dn-vector-t.h dn-vector-types.h + dn-simdhash.h + dn-simdhash-specialization.h + dn-simdhash-specialization-declarations.h + dn-simdhash-specializations.h + dn-simdhash-arch.h + dn-simdhash-string-ptr.h + dn-simdhash-utils.h ) diff --git a/src/native/containers/dn-simdhash-arch.h b/src/native/containers/dn-simdhash-arch.h new file mode 100644 index 000000000000..22f3902eafa8 --- /dev/null +++ b/src/native/containers/dn-simdhash-arch.h @@ -0,0 +1,194 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_SIMDHASH_ARCH_H__ +#define __DN_SIMDHASH_ARCH_H__ + +// #define DN_SIMDHASH_WARNINGS 1 + +// HACK: for better language server parsing +#include "dn-simdhash.h" + +#if defined(__clang__) || defined (__GNUC__) // use vector intrinsics + +#if defined(__wasm_simd128__) +#include +#elif defined(_M_AMD64) || defined(_M_X64) || (_M_IX86_FP == 2) || defined(__SSE2__) +#include +#elif defined(__ARM_NEON) +#include +#elif defined(__wasm) +#define DN_SIMDHASH_USE_SCALAR_FALLBACK 1 +#ifdef DN_SIMDHASH_WARNINGS +#pragma message("WARNING: Building dn_simdhash for WASM without -msimd128! Performance will be terrible!") +#endif +#else +#define DN_SIMDHASH_USE_SCALAR_FALLBACK 1 +#ifdef DN_SIMDHASH_WARNINGS +#pragma message("WARNING: Unsupported architecture for dn_simdhash! Performance will be terrible!") +#endif +#endif + +// extract/replace lane opcodes require constant indices on some target architectures, +// and in some cases it is profitable to do a single-byte memory load/store instead of +// a full vector load/store, so we expose both layouts as a union + +typedef uint8_t dn_u8x16 __attribute__ ((vector_size (DN_SIMDHASH_VECTOR_WIDTH), aligned(DN_SIMDHASH_VECTOR_WIDTH))); +typedef union { + _Alignas(DN_SIMDHASH_VECTOR_WIDTH) dn_u8x16 vec; +#if defined(_M_AMD64) || defined(_M_X64) || (_M_IX86_FP == 2) || defined(__SSE2__) + _Alignas(DN_SIMDHASH_VECTOR_WIDTH) __m128i m128; +#endif + _Alignas(DN_SIMDHASH_VECTOR_WIDTH) uint8_t values[DN_SIMDHASH_VECTOR_WIDTH]; +} dn_simdhash_suffixes; + +#ifdef DN_SIMDHASH_USE_SCALAR_FALLBACK +typedef uint8_t dn_simdhash_search_vector; +#else +typedef dn_simdhash_suffixes dn_simdhash_search_vector; +#endif + +// Extracting lanes from a vector register on x86/x64 has horrible latency, +// so it's better to do regular byte loads from the stack +#if defined(__wasm_simd128__) +// For wasm with -msimd128, clang generates truly bizarre load/store code +// where it does two byte memory loads, then a vector load, then two +// lane insertions to write the byte loads into the loaded vector +// before finally passing it to find_first_matching_suffix. So we have to vec[]. +// See https://github.com/llvm/llvm-project/issues/87398#issuecomment-2050696298 +// Also see https://github.com/llvm/llvm-project/issues/88460 +#define dn_simdhash_extract_lane(suffixes, lane) \ + suffixes.vec[lane] +#else +#define dn_simdhash_extract_lane(suffixes, lane) \ + suffixes.values[lane] +#endif + +static DN_FORCEINLINE(uint32_t) +ctz (uint32_t value) +{ + // __builtin_ctz is undefined for 0 + if (value == 0) + return 32; + return (uint32_t)__builtin_ctz(value); +} + +static DN_FORCEINLINE(dn_simdhash_search_vector) +build_search_vector (uint8_t needle) +{ +#ifdef DN_SIMDHASH_USE_SCALAR_FALLBACK + return needle; +#else + dn_simdhash_suffixes result; + // this produces a splat in wasm, and the other architectures are fine too + dn_u8x16 needles = { + needle, needle, needle, needle, needle, needle, needle, needle, + needle, needle, needle, needle, needle, needle, needle, needle + }; + result.vec = needles; + return result; +#endif +} + +// returns an index in range 0-13 on match, 14-32 if no match +static DN_FORCEINLINE(uint32_t) +find_first_matching_suffix_simd ( + dn_simdhash_search_vector needle, + // Only used by the vectorized implementations; discarded by scalar. + dn_simdhash_suffixes haystack +) { +#if defined(__wasm_simd128__) + return ctz(wasm_i8x16_bitmask(wasm_i8x16_eq(needle.vec, haystack.vec))); +#elif defined(_M_AMD64) || defined(_M_X64) || (_M_IX86_FP == 2) || defined(__SSE2__) + return ctz(_mm_movemask_epi8(_mm_cmpeq_epi8(needle.m128, haystack.m128))); +#elif defined(__ARM_NEON) + dn_simdhash_suffixes match_vector; + // Completely untested. + static const dn_simdhash_suffixes byte_mask = { + 1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128 + }; + union { + uint8_t b[4]; + uint32_t u; + } msb; + match_vector.vec = vceqq_u8(needle.vec, haystack.vec); + dn_simdhash_suffixes masked; + masked.vec = vandq_u8(match_vector.vec, byte_mask.vec); + msb.b[0] = vaddv_u8(vget_low_u8(masked.vec)); + msb.b[1] = vaddv_u8(vget_high_u8(masked.vec)); + return ctz(msb.u); +#else + dn_simdhash_assert(!"Scalar fallback should be in use here"); + return 32; +#endif +} + +#elif defined(_M_AMD64) || defined(_M_X64) || (_M_IX86_FP == 2) || defined(__SSE2__) +// neither clang or gcc, but we have SSE2 available, so assume this is MSVC on x86 or x86-64 +// msvc neon intrinsics don't seem to expose a 128-bit wide vector so there's no neon in here +#include // for _BitScanForward + +static DN_FORCEINLINE(uint32_t) +ctz (uint32_t value) +{ + unsigned long result = 0; + if (_BitScanForward(&result, value)) + return (uint32_t)result; + else + return 32; +} + +#include + +typedef union { + _Alignas(DN_SIMDHASH_VECTOR_WIDTH) __m128i m128; + _Alignas(DN_SIMDHASH_VECTOR_WIDTH) uint8_t values[DN_SIMDHASH_VECTOR_WIDTH]; +} dn_simdhash_suffixes; + +typedef dn_simdhash_suffixes dn_simdhash_search_vector; + +#define dn_simdhash_extract_lane(suffixes, lane) \ + suffixes.values[lane] + +static DN_FORCEINLINE(dn_simdhash_search_vector) +build_search_vector (uint8_t needle) +{ + dn_simdhash_suffixes result; + result.m128 = _mm_set1_epi8(needle); + return result; +} + +// returns an index in range 0-13 on match, 14-32 if no match +static DN_FORCEINLINE(uint32_t) +find_first_matching_suffix_simd ( + dn_simdhash_search_vector needle, dn_simdhash_suffixes haystack +) { + return ctz(_mm_movemask_epi8(_mm_cmpeq_epi8(needle.m128, haystack.m128))); +} + +#else // unknown compiler and/or unknown non-simd arch + +#define DN_SIMDHASH_USE_SCALAR_FALLBACK 1 + +#ifdef DN_SIMDHASH_WARNINGS +#pragma message("WARNING: Unsupported architecture/compiler for dn_simdhash! Performance will be terrible!") +#endif + +typedef struct { + _Alignas(DN_SIMDHASH_VECTOR_WIDTH) uint8_t values[DN_SIMDHASH_VECTOR_WIDTH]; +} dn_simdhash_suffixes; + +typedef uint8_t dn_simdhash_search_vector; + +#define dn_simdhash_extract_lane(suffixes, lane) \ + suffixes.values[lane] + +static DN_FORCEINLINE(dn_simdhash_search_vector) +build_search_vector (uint8_t needle) +{ + return needle; +} + +#endif // end of clang/gcc or msvc or fallback + +#endif // __DN_SIMDHASH_ARCH_H__ diff --git a/src/native/containers/dn-simdhash-ght-compatible.c b/src/native/containers/dn-simdhash-ght-compatible.c new file mode 100644 index 000000000000..eced9aac478c --- /dev/null +++ b/src/native/containers/dn-simdhash-ght-compatible.c @@ -0,0 +1,147 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef NO_CONFIG_H +#include +#endif +#include "dn-simdhash.h" + +#include "dn-simdhash-utils.h" +#include "dn-simdhash-ght-compatible.h" + +typedef struct dn_simdhash_ght_data { + dn_simdhash_ght_hash_func hash_func; + dn_simdhash_ght_equal_func key_equal_func; + dn_simdhash_ght_destroy_func key_destroy_func; + dn_simdhash_ght_destroy_func value_destroy_func; +} dn_simdhash_ght_data; + +static inline uint32_t +dn_simdhash_ght_hash (dn_simdhash_ght_data data, void * key) +{ + dn_simdhash_ght_hash_func hash_func = data.hash_func; + if (hash_func) + return (uint32_t)hash_func(key); + else + // FIXME: Seed + return MurmurHash3_32_ptr(key, 0); +} + +static inline int32_t +dn_simdhash_ght_equals (dn_simdhash_ght_data data, void * lhs, void * rhs) +{ + dn_simdhash_ght_equal_func equal_func = data.key_equal_func; + if (equal_func) + return equal_func(lhs, rhs); + else + return lhs == rhs; +} + +static inline void +dn_simdhash_ght_removed (dn_simdhash_ght_data data, void * key, void * value) +{ + dn_simdhash_ght_destroy_func key_destroy_func = data.key_destroy_func, + value_destroy_func = data.value_destroy_func; + if (key_destroy_func) + key_destroy_func((void *)key); + if (value_destroy_func) + value_destroy_func((void *)value); +} + +static inline void +dn_simdhash_ght_replaced (dn_simdhash_ght_data data, void * old_key, void * new_key, void * old_value, void * new_value) +{ + if (old_key != new_key) { + dn_simdhash_ght_destroy_func key_destroy_func = data.key_destroy_func; + if (key_destroy_func) + key_destroy_func((void *)old_key); + } + + if (old_value != new_value) { + dn_simdhash_ght_destroy_func value_destroy_func = data.value_destroy_func; + if (value_destroy_func) + value_destroy_func((void *)old_value); + } +} + +#define DN_SIMDHASH_T dn_simdhash_ght +#define DN_SIMDHASH_KEY_T void * +#define DN_SIMDHASH_VALUE_T void * +#define DN_SIMDHASH_INSTANCE_DATA_T dn_simdhash_ght_data +#define DN_SIMDHASH_KEY_HASHER dn_simdhash_ght_hash +#define DN_SIMDHASH_KEY_EQUALS dn_simdhash_ght_equals +#define DN_SIMDHASH_ON_REMOVE dn_simdhash_ght_removed +#define DN_SIMDHASH_ON_REPLACE dn_simdhash_ght_replaced +#if SIZEOF_VOID_P == 8 +#define DN_SIMDHASH_BUCKET_CAPACITY 11 +#else +#define DN_SIMDHASH_BUCKET_CAPACITY 12 +#endif +#define DN_SIMDHASH_NO_DEFAULT_NEW 1 + +#include "dn-simdhash-specialization.h" + +dn_simdhash_ght_t * +dn_simdhash_ght_new ( + dn_simdhash_ght_hash_func hash_func, dn_simdhash_ght_equal_func key_equal_func, + uint32_t capacity, dn_allocator_t *allocator +) +{ + dn_simdhash_ght_t *hash = dn_simdhash_new_internal(&DN_SIMDHASH_T_META, DN_SIMDHASH_T_VTABLE, capacity, allocator); + dn_simdhash_instance_data(dn_simdhash_ght_data, hash).hash_func = hash_func; + dn_simdhash_instance_data(dn_simdhash_ght_data, hash).key_equal_func = key_equal_func; + return hash; +} + +dn_simdhash_ght_t * +dn_simdhash_ght_new_full ( + dn_simdhash_ght_hash_func hash_func, dn_simdhash_ght_equal_func key_equal_func, + dn_simdhash_ght_destroy_func key_destroy_func, dn_simdhash_ght_destroy_func value_destroy_func, + uint32_t capacity, dn_allocator_t *allocator +) +{ + dn_simdhash_ght_t *hash = dn_simdhash_new_internal(&DN_SIMDHASH_T_META, DN_SIMDHASH_T_VTABLE, capacity, allocator); + dn_simdhash_instance_data(dn_simdhash_ght_data, hash).hash_func = hash_func; + dn_simdhash_instance_data(dn_simdhash_ght_data, hash).key_equal_func = key_equal_func; + dn_simdhash_instance_data(dn_simdhash_ght_data, hash).key_destroy_func = key_destroy_func; + dn_simdhash_instance_data(dn_simdhash_ght_data, hash).value_destroy_func = value_destroy_func; + return hash; +} + +void +dn_simdhash_ght_insert_replace ( + dn_simdhash_ght_t *hash, + void * key, void * value, + int32_t overwrite_key +) +{ + check_self(hash); + uint32_t key_hash = DN_SIMDHASH_KEY_HASHER(DN_SIMDHASH_GET_DATA(hash), key); + dn_simdhash_insert_mode imode = overwrite_key + ? DN_SIMDHASH_INSERT_MODE_OVERWRITE_KEY_AND_VALUE + : DN_SIMDHASH_INSERT_MODE_OVERWRITE_VALUE; + + dn_simdhash_insert_result ok = DN_SIMDHASH_TRY_INSERT_INTERNAL(hash, key, key_hash, value, imode); + if (ok == DN_SIMDHASH_INSERT_NEED_TO_GROW) { + dn_simdhash_buffers_t old_buffers = dn_simdhash_ensure_capacity_internal(hash, dn_simdhash_capacity(hash) + 1); + if (old_buffers.buckets) { + DN_SIMDHASH_REHASH_INTERNAL(hash, old_buffers); + dn_simdhash_free_buffers(old_buffers); + } + ok = DN_SIMDHASH_TRY_INSERT_INTERNAL(hash, key, key_hash, value, imode); + } + + switch (ok) { + case DN_SIMDHASH_INSERT_OK_ADDED_NEW: + hash->count++; + return; + case DN_SIMDHASH_INSERT_OK_OVERWROTE_EXISTING: + return; + // We should always return one of the first two + case DN_SIMDHASH_INSERT_KEY_ALREADY_PRESENT: + case DN_SIMDHASH_INSERT_NEED_TO_GROW: + default: + assert(0); + return; + } +} diff --git a/src/native/containers/dn-simdhash-ght-compatible.h b/src/native/containers/dn-simdhash-ght-compatible.h new file mode 100644 index 000000000000..4474f02346d3 --- /dev/null +++ b/src/native/containers/dn-simdhash-ght-compatible.h @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +typedef dn_simdhash_t dn_simdhash_ght_t; + +typedef void (*dn_simdhash_ght_destroy_func) (void * data); +typedef unsigned int (*dn_simdhash_ght_hash_func) (const void * key); +typedef int32_t (*dn_simdhash_ght_equal_func) (const void * a, const void * b); + +dn_simdhash_ght_t * +dn_simdhash_ght_new ( + dn_simdhash_ght_hash_func hash_func, dn_simdhash_ght_equal_func key_equal_func, + uint32_t capacity, dn_allocator_t *allocator +); + +dn_simdhash_ght_t * +dn_simdhash_ght_new_full ( + dn_simdhash_ght_hash_func hash_func, dn_simdhash_ght_equal_func key_equal_func, + dn_simdhash_ght_destroy_func key_destroy_func, dn_simdhash_ght_destroy_func value_destroy_func, + uint32_t capacity, dn_allocator_t *allocator +); + +// compatible with g_hash_table_insert_replace +void +dn_simdhash_ght_insert_replace ( + dn_simdhash_ght_t *hash, + void * key, void * value, + int32_t overwrite_key +); + +// compatibility shims for the g_hash_table_ versions in glib.h +#define dn_simdhash_ght_insert(h,k,v) dn_simdhash_ght_insert_replace ((h),(k),(v),FALSE) +#define dn_simdhash_ght_replace(h,k,v) dn_simdhash_ght_insert_replace ((h),(k),(v),TRUE) +#define dn_simdhash_ght_add(h,k) dn_simdhash_ght_insert_replace ((h),(k),(k),TRUE) diff --git a/src/native/containers/dn-simdhash-ptr-ptr.c b/src/native/containers/dn-simdhash-ptr-ptr.c new file mode 100644 index 000000000000..25e7530d39dc --- /dev/null +++ b/src/native/containers/dn-simdhash-ptr-ptr.c @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef NO_CONFIG_H +#include +#endif +#include "dn-simdhash.h" + +#include "dn-simdhash-utils.h" + +#define DN_SIMDHASH_T dn_simdhash_ptr_ptr +#define DN_SIMDHASH_KEY_T void * +#define DN_SIMDHASH_VALUE_T void * +#define DN_SIMDHASH_KEY_HASHER(hash, key) (MurmurHash3_32_ptr(key, 0)) +#define DN_SIMDHASH_KEY_EQUALS(hash, lhs, rhs) (lhs == rhs) +#if SIZEOF_VOID_P == 8 +#define DN_SIMDHASH_BUCKET_CAPACITY 11 +#else +#define DN_SIMDHASH_BUCKET_CAPACITY 12 +#endif + +#include "dn-simdhash-specialization.h" diff --git a/src/native/containers/dn-simdhash-ptrpair-ptr.c b/src/native/containers/dn-simdhash-ptrpair-ptr.c new file mode 100644 index 000000000000..d377647b6636 --- /dev/null +++ b/src/native/containers/dn-simdhash-ptrpair-ptr.c @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include +#include "dn-simdhash.h" + +#include "dn-simdhash-utils.h" + +typedef struct dn_ptrpair_t { + void *first; + void *second; +} dn_ptrpair_t; + +static inline uint32_t +dn_ptrpair_t_hash (dn_ptrpair_t key) +{ + return (MurmurHash3_32_ptr(key.first, 0) ^ MurmurHash3_32_ptr(key.second, 1)); +} + +static inline uint8_t +dn_ptrpair_t_equals (dn_ptrpair_t lhs, dn_ptrpair_t rhs) +{ + return (lhs.first == rhs.first) && (lhs.second == rhs.second); +} + +#define DN_SIMDHASH_T dn_simdhash_ptrpair_ptr +#define DN_SIMDHASH_KEY_T dn_ptrpair_t +#define DN_SIMDHASH_VALUE_T void * +#define DN_SIMDHASH_KEY_HASHER(hash, key) dn_ptrpair_t_hash(key) +#define DN_SIMDHASH_KEY_EQUALS(hash, lhs, rhs) dn_ptrpair_t_equals(lhs, rhs) +#if SIZEOF_VOID_P == 8 +// 192 bytes holds 12 16-byte blocks, so 11 keys and one suffix table +#define DN_SIMDHASH_BUCKET_CAPACITY 11 +#else +// 128 bytes holds 16 8-byte blocks, so 14 keys and one suffix table +#define DN_SIMDHASH_BUCKET_CAPACITY 14 +#endif + +#include "dn-simdhash-specialization.h" diff --git a/src/native/containers/dn-simdhash-specialization-declarations.h b/src/native/containers/dn-simdhash-specialization-declarations.h new file mode 100644 index 000000000000..585f2094ee58 --- /dev/null +++ b/src/native/containers/dn-simdhash-specialization-declarations.h @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Gluing macro expansions together requires nested macro invocation :/ +#ifndef DN_SIMDHASH_GLUE +#define DN_SIMDHASH_GLUE_INNER(a, b) a ## b +#define DN_SIMDHASH_GLUE(a,b) DN_SIMDHASH_GLUE_INNER(a, b) +#endif +#ifndef DN_SIMDHASH_GLUE_3 +#define DN_SIMDHASH_GLUE_3_INNER(a, b, c) a ## b ## c +#define DN_SIMDHASH_GLUE_3(a, b, c) DN_SIMDHASH_GLUE_3_INNER(a, b, c) +#endif + +#ifndef DN_SIMDHASH_ACCESSOR_SUFFIX +#define DN_SIMDHASH_ACCESSOR_SUFFIX +#endif + +// We generate unique names for each specialization so that they will be easy to distinguish +// when debugging, profiling, or disassembling. Otherwise they would have linker-assigned names +#define DN_SIMDHASH_T_NAME DN_SIMDHASH_GLUE(DN_SIMDHASH_T,_t) +#define DN_SIMDHASH_T_PTR DN_SIMDHASH_GLUE(DN_SIMDHASH_T,_t *) +#define DN_SIMDHASH_T_VTABLE DN_SIMDHASH_GLUE(DN_SIMDHASH_T,_vtable) +#define DN_SIMDHASH_T_META DN_SIMDHASH_GLUE(DN_SIMDHASH_T,_meta) +#define DN_SIMDHASH_SCAN_BUCKET_INTERNAL DN_SIMDHASH_GLUE(DN_SIMDHASH_T,_scan_bucket_internal) +#define DN_SIMDHASH_FIND_VALUE_INTERNAL DN_SIMDHASH_GLUE(DN_SIMDHASH_T,_find_value_internal) +#define DN_SIMDHASH_TRY_INSERT_INTERNAL DN_SIMDHASH_GLUE(DN_SIMDHASH_T,_try_insert_internal) +#define DN_SIMDHASH_REHASH_INTERNAL DN_SIMDHASH_GLUE(DN_SIMDHASH_T,_rehash_internal) +#define DN_SIMDHASH_NEW DN_SIMDHASH_GLUE(DN_SIMDHASH_T,_new) +#define DN_SIMDHASH_TRY_ADD DN_SIMDHASH_GLUE_3(DN_SIMDHASH_T,_try_add,DN_SIMDHASH_ACCESSOR_SUFFIX) +#define DN_SIMDHASH_TRY_ADD_WITH_HASH DN_SIMDHASH_GLUE_3(DN_SIMDHASH_T,_try_add_with_hash,DN_SIMDHASH_ACCESSOR_SUFFIX) +#define DN_SIMDHASH_TRY_GET_VALUE DN_SIMDHASH_GLUE_3(DN_SIMDHASH_T,_try_get_value,DN_SIMDHASH_ACCESSOR_SUFFIX) +#define DN_SIMDHASH_TRY_GET_VALUE_WITH_HASH DN_SIMDHASH_GLUE_3(DN_SIMDHASH_T,_try_get_value_with_hash,DN_SIMDHASH_ACCESSOR_SUFFIX) +#define DN_SIMDHASH_TRY_REMOVE DN_SIMDHASH_GLUE_3(DN_SIMDHASH_T,_try_remove,DN_SIMDHASH_ACCESSOR_SUFFIX) +#define DN_SIMDHASH_TRY_REMOVE_WITH_HASH DN_SIMDHASH_GLUE_3(DN_SIMDHASH_T,_try_remove_with_hash,DN_SIMDHASH_ACCESSOR_SUFFIX) +#define DN_SIMDHASH_TRY_REPLACE_VALUE DN_SIMDHASH_GLUE_3(DN_SIMDHASH_T,_try_replace_value,DN_SIMDHASH_ACCESSOR_SUFFIX) +#define DN_SIMDHASH_TRY_REPLACE_VALUE_WITH_HASH DN_SIMDHASH_GLUE_3(DN_SIMDHASH_T,_try_replace_value_with_hash,DN_SIMDHASH_ACCESSOR_SUFFIX) +#define DN_SIMDHASH_FOREACH DN_SIMDHASH_GLUE_3(DN_SIMDHASH_T,_foreach,DN_SIMDHASH_ACCESSOR_SUFFIX) +#define DN_SIMDHASH_FOREACH_FUNC DN_SIMDHASH_GLUE_3(DN_SIMDHASH_T,_foreach_func,DN_SIMDHASH_ACCESSOR_SUFFIX) +#define DN_SIMDHASH_DESTROY_ALL DN_SIMDHASH_GLUE(DN_SIMDHASH_T,_destroy_all) + +typedef void (*DN_SIMDHASH_FOREACH_FUNC) (DN_SIMDHASH_KEY_T key, DN_SIMDHASH_VALUE_T value, void *user_data); + +// Declare a specific alias so intellisense gives more helpful info +typedef dn_simdhash_t DN_SIMDHASH_T_NAME; + +#ifndef DN_SIMDHASH_NO_DEFAULT_NEW +DN_SIMDHASH_T_PTR +DN_SIMDHASH_NEW (uint32_t capacity, dn_allocator_t *allocator); +#endif + +uint8_t +DN_SIMDHASH_TRY_ADD (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, DN_SIMDHASH_VALUE_T value); + +uint8_t +DN_SIMDHASH_TRY_ADD_WITH_HASH (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, uint32_t key_hash, DN_SIMDHASH_VALUE_T value); + +uint8_t +DN_SIMDHASH_TRY_GET_VALUE (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, DN_SIMDHASH_VALUE_T *result); + +uint8_t +DN_SIMDHASH_TRY_GET_VALUE_WITH_HASH (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, uint32_t key_hash, DN_SIMDHASH_VALUE_T *result); + +uint8_t +DN_SIMDHASH_TRY_REMOVE (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key); + +uint8_t +DN_SIMDHASH_TRY_REMOVE_WITH_HASH (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, uint32_t key_hash); + +uint8_t +DN_SIMDHASH_TRY_REPLACE_VALUE (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, DN_SIMDHASH_VALUE_T new_value); + +uint8_t +DN_SIMDHASH_TRY_REPLACE_VALUE_WITH_HASH (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, uint32_t key_hash, DN_SIMDHASH_VALUE_T new_value); + +void +DN_SIMDHASH_FOREACH (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_FOREACH_FUNC func, void *user_data); diff --git a/src/native/containers/dn-simdhash-specialization.h b/src/native/containers/dn-simdhash-specialization.h new file mode 100644 index 000000000000..7c5d9b2ecdb1 --- /dev/null +++ b/src/native/containers/dn-simdhash-specialization.h @@ -0,0 +1,617 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifdef __DN_SIMDHASH_SPECIALIZATION_H__ +#error Specialization header already included +#else +#define __DN_SIMDHASH_SPECIALIZATION_H__ +#endif + +#include "dn-simdhash.h" +#include "dn-simdhash-utils.h" +#include "dn-simdhash-arch.h" + +#ifndef DN_SIMDHASH_T +#error Expected DN_SIMDHASH_T definition i.e. dn_simdhash_string_ptr +#endif + +#ifndef DN_SIMDHASH_KEY_T +#error Expected DN_SIMDHASH_KEY_T definition i.e. const char * +#endif + +#ifndef DN_SIMDHASH_VALUE_T +#error Expected DN_SIMDHASH_VALUE_T definition i.e. int +#endif + +// If specified, we pass instance data to the handlers by-value, otherwise we +// pass the pointer to the hash itself by-value. This is enough to allow clang +// to hoist the load of the instance data out of the key scan loop, though it +// won't hoist it all the way out of the bucket scan loop. +#ifndef DN_SIMDHASH_INSTANCE_DATA_T +#define DN_SIMDHASH_GET_DATA(hash) (hash) +#define DN_SIMDHASH_INSTANCE_DATA_T DN_SIMDHASH_T_PTR +#else // DN_SIMDHASH_INSTANCE_DATA_T +#define DN_SIMDHASH_GET_DATA(hash) dn_simdhash_instance_data(DN_SIMDHASH_INSTANCE_DATA_T, hash) +#endif // DN_SIMDHASH_INSTANCE_DATA_T + +#ifndef DN_SIMDHASH_KEY_HASHER +#error Expected DN_SIMDHASH_KEY_HASHER definition with signature: uint32_t (DN_SIMDHASH_INSTANCE_DATA_T data, KEY_T key) +#endif + +#ifndef DN_SIMDHASH_KEY_EQUALS +#error Expected DN_SIMDHASH_KEY_EQUALS definition with signature: int (DN_SIMDHASH_INSTANCE_DATA_T data, KEY_T lhs, KEY_T rhs) that returns 1 for match +#endif + +#ifndef DN_SIMDHASH_ON_REPLACE +#define DN_SIMDHASH_HAS_REPLACE_HANDLER 0 +#define DN_SIMDHASH_ON_REPLACE(data, old_key, new_key, old_value, new_value) +#else // DN_SIMDHASH_ON_REPLACE +#define DN_SIMDHASH_HAS_REPLACE_HANDLER 1 +#ifndef DN_SIMDHASH_ON_REMOVE +#error Expected DN_SIMDHASH_ON_REMOVE(data, key, value) to be defined. +#endif +#endif // DN_SIMDHASH_ON_REPLACE + +#ifndef DN_SIMDHASH_ON_REMOVE +#define DN_SIMDHASH_HAS_REMOVE_HANDLER 0 +#define DN_SIMDHASH_ON_REMOVE(data, key, value) +#else // DN_SIMDHASH_ON_REMOVE +#define DN_SIMDHASH_HAS_REMOVE_HANDLER 1 +#ifndef DN_SIMDHASH_ON_REPLACE +#error Expected DN_SIMDHASH_ON_REPLACE(data, old_key, new_key, old_value, new_value) to be defined. +#endif +#endif // DN_SIMDHASH_ON_REMOVE + +#ifndef DN_SIMDHASH_BUCKET_CAPACITY +// TODO: Find some way to automatically select an ideal bucket capacity based on key size. +// Some sort of trick using _Generic? +#define DN_SIMDHASH_BUCKET_CAPACITY DN_SIMDHASH_DEFAULT_BUCKET_CAPACITY +#endif + +#include "dn-simdhash-specialization-declarations.h" + +static_assert(DN_SIMDHASH_BUCKET_CAPACITY <= DN_SIMDHASH_MAX_BUCKET_CAPACITY, "Maximum bucket capacity exceeded"); +static_assert(DN_SIMDHASH_BUCKET_CAPACITY > 1, "Bucket capacity too low"); + +// We set bucket_size_bytes to sizeof() this struct so that we can let the compiler +// generate the most optimal code possible when we're manipulating pointers to it - +// that is, it can do mul-by-constant instead of mul-by-(hash->meta.etc) +typedef struct bucket_t { + _Alignas(DN_SIMDHASH_VECTOR_WIDTH) dn_simdhash_suffixes suffixes; + DN_SIMDHASH_KEY_T keys[DN_SIMDHASH_BUCKET_CAPACITY]; +} bucket_t; + +static_assert((sizeof (bucket_t) % DN_SIMDHASH_VECTOR_WIDTH) == 0, "Bucket size is not vector aligned"); + + +// While we've inlined these constants into the specialized code we're generating, +// the generic code in dn-simdhash.c needs them, so we put them in this meta header +// that is referenced by every hash instance. +dn_simdhash_meta_t DN_SIMDHASH_T_META = { + DN_SIMDHASH_BUCKET_CAPACITY, + sizeof(bucket_t), + sizeof(DN_SIMDHASH_KEY_T), + sizeof(DN_SIMDHASH_VALUE_T), + sizeof(DN_SIMDHASH_INSTANCE_DATA_T), +}; + +static DN_FORCEINLINE(uint32_t) +find_first_matching_suffix_scalar ( + uint8_t needle, + uint8_t haystack[DN_SIMDHASH_VECTOR_WIDTH] +) { + uint32_t result = 32; + // ITERs for indices beyond our specialization's bucket capacity will be + // constant-false and not check the specific bucket slot +#define ITER(offset) \ + { \ + /* Avoid MSVC C4127 by computing this separately in a temp local */ \ + uint8_t in_bounds = (offset < DN_SIMDHASH_BUCKET_CAPACITY); \ + if (in_bounds && (needle == haystack[offset])) \ + result = offset; \ + } + + // It is safe to unroll this without bounds checks + // Looping from 0-count is slower than this in my testing, even though it's + // going to check fewer suffixes most of the time - probably due to the + // comparison against count for each suffix. + // Scanning in reverse and conditionally modifying result allows clang to + // emit a chain of 'select' operations per slot on wasm, which produces + // smaller code that seems to be much faster than a chain of + // 'if (...) return' for successful matches, and only slightly slower + // for failed matches + ITER(13); + ITER(12); + ITER(11); + ITER(10); + ITER(9); + ITER(8); + ITER(7); + ITER(6); + ITER(5); + ITER(4); + ITER(3); + ITER(2); + ITER(1); + ITER(0); +#undef ITER + return result; +} + +static DN_FORCEINLINE(void) +check_self (DN_SIMDHASH_T_PTR self) +{ +#ifdef NDEBUG + // In release builds, just nullcheck. Checking meta adds measurable overhead. + dn_simdhash_assert(self); +#else + // Verifies both that the self-ptr is non-null and that the meta pointer matches + // what it should be. This detects passing the wrong kind of simdhash_t pointer + // to one of the APIs, since C doesn't have fully type-safe pointers. + uint8_t ok = self && (self->meta == &DN_SIMDHASH_T_META); + dn_simdhash_assert(ok); +#endif +} + + +static DN_FORCEINLINE(bucket_t *) +address_of_bucket (dn_simdhash_buffers_t buffers, uint32_t bucket_index) +{ + return &((bucket_t *)buffers.buckets)[bucket_index]; +} + +static DN_FORCEINLINE(DN_SIMDHASH_VALUE_T *) +address_of_value (dn_simdhash_buffers_t buffers, uint32_t value_slot_index) +{ + return &((DN_SIMDHASH_VALUE_T *)buffers.values)[value_slot_index]; +} + +#define DN_SIMDHASH_SCAN_BUCKET_NO_OVERFLOW -1 +#define DN_SIMDHASH_SCAN_BUCKET_OVERFLOWED -2 + +// This helper is used to locate the first matching key in a given bucket, so that add +// operations don't potentially have to scan the whole table twice when hashes collide +// On success: returns index (0-n) +// On failure: returns -1 if bucket has not overflowed; -2 if it has +static DN_FORCEINLINE(int) +DN_SIMDHASH_SCAN_BUCKET_INTERNAL (DN_SIMDHASH_T_PTR hash, bucket_t *restrict bucket, DN_SIMDHASH_KEY_T needle, dn_simdhash_search_vector search_vector) +{ +#ifdef _MSC_VER + // MSVC won't do efficient lane extractions if we eager load the vector, + // so just operate through the pointer instead. + #define bucket_suffixes (bucket->suffixes) +#elif !defined(DN_SIMDHASH_USE_SCALAR_FALLBACK) + // Perform an eager load of the vector if SIMD is in use, even though we do + // byte loads to extract lanes on non-wasm platforms. It's faster on x64 for + // a reason I can't identify, and it significantly improves wasm codegen + dn_simdhash_suffixes bucket_suffixes = bucket->suffixes; +#else + // Load through the pointer instead. An eager load just copies to the stack for + // no good reason. + #define bucket_suffixes (bucket->suffixes) +#endif + uint8_t count = dn_simdhash_extract_lane(bucket_suffixes, DN_SIMDHASH_COUNT_SLOT), + overflow_count = dn_simdhash_extract_lane(bucket_suffixes, DN_SIMDHASH_CASCADED_SLOT); + // We could early-out here when count==0, but it doesn't appear to meaningfully improve + // search performance to do so, and might actually worsen it +#ifdef DN_SIMDHASH_USE_SCALAR_FALLBACK + uint32_t index = find_first_matching_suffix_scalar(search_vector, bucket->suffixes.values); +#else + uint32_t index = find_first_matching_suffix_simd(search_vector, bucket_suffixes); +#endif +#undef bucket_suffixes + for (; index < count; index++) { + // FIXME: Could be profitable to manually hoist the data load outside of the loop, + // if not out of SCAN_BUCKET_INTERNAL entirely. Clang appears to do LICM on it. + // It's better to index bucket->keys each iteration inside the loop than to precompute + // a pointer outside and bump the pointer, because in many cases the bucket will be + // empty, and in many other cases it will have one match. Putting the index inside the + // loop means that for empty/no-match buckets we don't do the index calculation at all. + if (DN_SIMDHASH_KEY_EQUALS(DN_SIMDHASH_GET_DATA(hash), needle, bucket->keys[index])) + return index; + } + + if (overflow_count) + return DN_SIMDHASH_SCAN_BUCKET_OVERFLOWED; + else + return DN_SIMDHASH_SCAN_BUCKET_NO_OVERFLOW; +} + +// Helper macros so that we can optimize and change scan logic more easily +#define BEGIN_SCAN_BUCKETS(buffers, initial_index, bucket_index, bucket_address) \ + { \ + uint32_t bucket_index = initial_index, scan_buckets_length = buffers.buckets_length; \ + bucket_t *restrict bucket_address = address_of_bucket(buffers, bucket_index); \ + do { + +#define END_SCAN_BUCKETS(buffers, initial_index, bucket_index, bucket_address) \ + bucket_index++; \ + bucket_address++; \ + /* Wrap around if we hit the last bucket. */ \ + if (bucket_index >= scan_buckets_length) { \ + bucket_index = 0; \ + bucket_address = address_of_bucket(buffers, 0); \ + } \ + /* if bucket_index == initial_index, we reached our starting point */ \ + } while (bucket_index != initial_index); \ + } + +#define BEGIN_SCAN_PAIRS(buffers, key_address, value_address) \ + bucket_t *scan_bucket_address = address_of_bucket(buffers, 0); \ + for ( \ + uint32_t scan_i = 0, scan_bc = buffers.buckets_length, scan_value_slot_base = 0; \ + scan_i < scan_bc; scan_i++, scan_bucket_address++, scan_value_slot_base += DN_SIMDHASH_BUCKET_CAPACITY \ + ) { \ + uint32_t scan_c = dn_simdhash_bucket_count(scan_bucket_address->suffixes); \ + for (uint32_t scan_j = 0; scan_j < scan_c; scan_j++) { \ + DN_SIMDHASH_KEY_T *key_address = &scan_bucket_address->keys[scan_j]; \ + DN_SIMDHASH_VALUE_T *value_address = address_of_value(buffers, scan_value_slot_base + scan_j); + +#define END_SCAN_PAIRS(buffers, key_address, value_address) \ + } \ + } + +// FIXME: inline? might improve performance for bucket overflow, but would +// increase code size, and maybe blow out icache. clang seems to inline it anyway. +static void +adjust_cascaded_counts (dn_simdhash_buffers_t buffers, uint32_t first_bucket_index, uint32_t last_bucket_index, uint8_t increase) +{ + BEGIN_SCAN_BUCKETS(buffers, first_bucket_index, bucket_index, bucket_address) + if (bucket_index == last_bucket_index) + break; + + uint8_t cascaded_count = dn_simdhash_bucket_cascaded_count(bucket_address->suffixes); + if (cascaded_count < 255) { + if (increase) + dn_simdhash_bucket_set_cascaded_count(bucket_address->suffixes, cascaded_count + 1); + else { + dn_simdhash_assert(cascaded_count > 0); + dn_simdhash_bucket_set_cascaded_count(bucket_address->suffixes, cascaded_count - 1); + } + } + END_SCAN_BUCKETS(buffers, first_bucket_index, bucket_index, bucket_address) +} + +static DN_FORCEINLINE(DN_SIMDHASH_VALUE_T *) +DN_SIMDHASH_FIND_VALUE_INTERNAL (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, uint32_t key_hash) +{ + uint8_t suffix = dn_simdhash_select_suffix(key_hash); + uint32_t first_bucket_index = dn_simdhash_select_bucket_index(hash->buffers, key_hash); + dn_simdhash_search_vector search_vector = build_search_vector(suffix); + + BEGIN_SCAN_BUCKETS(hash->buffers, first_bucket_index, bucket_index, bucket_address) + int index_in_bucket = DN_SIMDHASH_SCAN_BUCKET_INTERNAL(hash, bucket_address, key, search_vector); + if (index_in_bucket >= 0) { + uint32_t value_slot_index = (bucket_index * DN_SIMDHASH_BUCKET_CAPACITY) + index_in_bucket; + return address_of_value(hash->buffers, value_slot_index); + } else if (index_in_bucket == DN_SIMDHASH_SCAN_BUCKET_NO_OVERFLOW) { + return NULL; + } + END_SCAN_BUCKETS(hash->buffers, first_bucket_index, bucket_index, bucket_address) + + return NULL; +} + +typedef enum dn_simdhash_insert_mode { + // Ensures that no matching key exists in the hash, then adds the key/value pair + DN_SIMDHASH_INSERT_MODE_ENSURE_UNIQUE, + // If a matching key exists in the hash, overwrite its value but leave the key alone + DN_SIMDHASH_INSERT_MODE_OVERWRITE_VALUE, + // If a matching key exists in the hash, overwrite both the key and the value + DN_SIMDHASH_INSERT_MODE_OVERWRITE_KEY_AND_VALUE, + // Do not scan for existing matches before adding the new key/value pair. + DN_SIMDHASH_INSERT_MODE_REHASHING, +} dn_simdhash_insert_mode; + +static void +do_overwrite ( + DN_SIMDHASH_T_PTR hash, uint32_t bucket_index, bucket_t *bucket_address, int index_in_bucket, + DN_SIMDHASH_KEY_T key, DN_SIMDHASH_VALUE_T value, uint8_t overwrite_key +) { + DN_SIMDHASH_KEY_T *key_ptr = &bucket_address->keys[index_in_bucket]; + DN_SIMDHASH_VALUE_T *value_ptr = address_of_value(hash->buffers, (bucket_index * DN_SIMDHASH_BUCKET_CAPACITY) + index_in_bucket); +#if DN_SIMDHASH_HAS_REPLACE_HANDLER + DN_SIMDHASH_KEY_T old_key = *key_ptr; + DN_SIMDHASH_VALUE_T old_value = *value_ptr; +#endif + if (overwrite_key) + *key_ptr = key; + *value_ptr = value; +#if DN_SIMDHASH_HAS_REPLACE_HANDLER + DN_SIMDHASH_ON_REPLACE(DN_SIMDHASH_GET_DATA(hash), old_key, overwrite_key ? key : old_key, old_value, value); +#endif +} + +static dn_simdhash_insert_result +DN_SIMDHASH_TRY_INSERT_INTERNAL (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, uint32_t key_hash, DN_SIMDHASH_VALUE_T value, dn_simdhash_insert_mode mode) +{ + // HACK: Early out. Better to grow without scanning here. + // We're comparing with the computed grow_at_count threshold to maintain an appropriate load factor + if (hash->count >= hash->grow_at_count) { + // printf ("hash->count %d >= hash->grow_at_count %d\n", hash->count, hash->grow_at_count); + return DN_SIMDHASH_INSERT_NEED_TO_GROW; + } + + uint8_t suffix = dn_simdhash_select_suffix(key_hash); + uint32_t first_bucket_index = dn_simdhash_select_bucket_index(hash->buffers, key_hash); + dn_simdhash_search_vector search_vector = build_search_vector(suffix); + + BEGIN_SCAN_BUCKETS(hash->buffers, first_bucket_index, bucket_index, bucket_address) + // If necessary, check the current bucket for the key + if (mode != DN_SIMDHASH_INSERT_MODE_REHASHING) { + int index_in_bucket = DN_SIMDHASH_SCAN_BUCKET_INTERNAL(hash, bucket_address, key, search_vector); + if (index_in_bucket >= 0) { + if ( + (mode == DN_SIMDHASH_INSERT_MODE_OVERWRITE_KEY_AND_VALUE) || + (mode == DN_SIMDHASH_INSERT_MODE_OVERWRITE_VALUE) + ) { + do_overwrite ( + hash, bucket_index, bucket_address, index_in_bucket, + key, value, (mode == DN_SIMDHASH_INSERT_MODE_OVERWRITE_KEY_AND_VALUE) + ); + return DN_SIMDHASH_INSERT_OK_OVERWROTE_EXISTING; + } else + return DN_SIMDHASH_INSERT_KEY_ALREADY_PRESENT; + } + } + + // The current bucket doesn't contain the key, or duplicate checks are disabled (for rehashing), + // so attempt to insert into the bucket + uint8_t new_index = dn_simdhash_bucket_count(bucket_address->suffixes); + if (new_index < DN_SIMDHASH_BUCKET_CAPACITY) { + // Calculate key address early to reduce odds of a stall + DN_SIMDHASH_KEY_T *restrict key_slot_address = &bucket_address->keys[new_index]; + // We found a bucket with space, so claim the first free slot + dn_simdhash_bucket_set_count(bucket_address->suffixes, new_index + 1); + dn_simdhash_bucket_set_suffix(bucket_address->suffixes, new_index, suffix); + // Now store the key, it's probably in the same cache line as the count/suffix + *key_slot_address = key; + // Now store the value, it's in a different cache line + uint32_t value_slot_index = (bucket_index * DN_SIMDHASH_BUCKET_CAPACITY) + new_index; + DN_SIMDHASH_VALUE_T *restrict value_slot_address = address_of_value(hash->buffers, value_slot_index); + *value_slot_address = value; + // printf("Inserted [%zd, %zd] in bucket %d at index %d\n", key, value, bucket_index, new_index); + // If we cascaded out of our original target bucket, scan through our probe path + // and increase the cascade counters. We have to wait until now to do that, because + // during the process of getting here we may end up finding a duplicate, which would + // leave the cascade counters in a corrupted state + adjust_cascaded_counts(hash->buffers, first_bucket_index, bucket_index, 1); + return DN_SIMDHASH_INSERT_OK_ADDED_NEW; + } + + // The current bucket is full, so try the next bucket. + END_SCAN_BUCKETS(hash->buffers, first_bucket_index, bucket_index, bucket_address) + + return DN_SIMDHASH_INSERT_NEED_TO_GROW; +} + +static void +DN_SIMDHASH_REHASH_INTERNAL (DN_SIMDHASH_T_PTR hash, dn_simdhash_buffers_t old_buffers) +{ + BEGIN_SCAN_PAIRS(old_buffers, key_address, value_address) + uint32_t key_hash = DN_SIMDHASH_KEY_HASHER(DN_SIMDHASH_GET_DATA(hash), *key_address); + // This theoretically can't fail, since we just grew the container and we + // wrap around to the beginning when there's a collision in the last bucket. + dn_simdhash_insert_result ok = DN_SIMDHASH_TRY_INSERT_INTERNAL( + hash, *key_address, key_hash, + *value_address, + DN_SIMDHASH_INSERT_MODE_REHASHING + ); + dn_simdhash_assert(ok == DN_SIMDHASH_INSERT_OK_ADDED_NEW); + END_SCAN_PAIRS(old_buffers, key_address, value_address) +} + +#if DN_SIMDHASH_HAS_REMOVE_HANDLER +static void +DN_SIMDHASH_DESTROY_ALL (DN_SIMDHASH_T_PTR hash) +{ + BEGIN_SCAN_PAIRS(hash->buffers, key_address, value_address) + DN_SIMDHASH_ON_REMOVE(DN_SIMDHASH_GET_DATA(hash), *key_address, *value_address); + END_SCAN_PAIRS(hash->buffers, key_address, value_address) +} +#endif + + +// TODO: Store this by-reference instead of inline in the hash? +dn_simdhash_vtable_t DN_SIMDHASH_T_VTABLE = { + DN_SIMDHASH_REHASH_INTERNAL, +#if DN_SIMDHASH_HAS_REMOVE_HANDLER + DN_SIMDHASH_DESTROY_ALL, +#else + NULL, +#endif +}; + + +#ifndef DN_SIMDHASH_NO_DEFAULT_NEW +DN_SIMDHASH_T_PTR +DN_SIMDHASH_NEW (uint32_t capacity, dn_allocator_t *allocator) +{ + return dn_simdhash_new_internal(&DN_SIMDHASH_T_META, DN_SIMDHASH_T_VTABLE, capacity, allocator); +} +#endif + +uint8_t +DN_SIMDHASH_TRY_ADD (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, DN_SIMDHASH_VALUE_T value) +{ + check_self(hash); + + uint32_t key_hash = DN_SIMDHASH_KEY_HASHER(DN_SIMDHASH_GET_DATA(hash), key); + return DN_SIMDHASH_TRY_ADD_WITH_HASH(hash, key, key_hash, value); +} + +uint8_t +DN_SIMDHASH_TRY_ADD_WITH_HASH (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, uint32_t key_hash, DN_SIMDHASH_VALUE_T value) +{ + check_self(hash); + + dn_simdhash_insert_result ok = DN_SIMDHASH_TRY_INSERT_INTERNAL(hash, key, key_hash, value, DN_SIMDHASH_INSERT_MODE_ENSURE_UNIQUE); + if (ok == DN_SIMDHASH_INSERT_NEED_TO_GROW) { + dn_simdhash_buffers_t old_buffers = dn_simdhash_ensure_capacity_internal(hash, dn_simdhash_capacity(hash) + 1); + if (old_buffers.buckets) { + DN_SIMDHASH_REHASH_INTERNAL(hash, old_buffers); + dn_simdhash_free_buffers(old_buffers); + } + ok = DN_SIMDHASH_TRY_INSERT_INTERNAL(hash, key, key_hash, value, DN_SIMDHASH_INSERT_MODE_ENSURE_UNIQUE); + } + + switch (ok) { + case DN_SIMDHASH_INSERT_OK_ADDED_NEW: + hash->count++; + return 1; + case DN_SIMDHASH_INSERT_OK_OVERWROTE_EXISTING: + // This shouldn't happen + dn_simdhash_assert(!"Overwrote an existing item while adding"); + return 1; + case DN_SIMDHASH_INSERT_KEY_ALREADY_PRESENT: + return 0; + case DN_SIMDHASH_INSERT_NEED_TO_GROW: + // We should always have enough space after growing once. + default: + dn_simdhash_assert(!"Failed to add a new item but there was no existing item"); + return 0; + } +} + +uint8_t +DN_SIMDHASH_TRY_GET_VALUE (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, DN_SIMDHASH_VALUE_T *result) +{ + check_self(hash); + + uint32_t key_hash = DN_SIMDHASH_KEY_HASHER(DN_SIMDHASH_GET_DATA(hash), key); + return DN_SIMDHASH_TRY_GET_VALUE_WITH_HASH(hash, key, key_hash, result); +} + +uint8_t +DN_SIMDHASH_TRY_GET_VALUE_WITH_HASH (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, uint32_t key_hash, DN_SIMDHASH_VALUE_T *result) +{ + check_self(hash); + + DN_SIMDHASH_VALUE_T *value_ptr = DN_SIMDHASH_FIND_VALUE_INTERNAL(hash, key, key_hash); + if (!value_ptr) + return 0; + if (result) + *result = *value_ptr; + return 1; +} + +uint8_t +DN_SIMDHASH_TRY_REMOVE (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key) +{ + check_self(hash); + + uint32_t key_hash = DN_SIMDHASH_KEY_HASHER(DN_SIMDHASH_GET_DATA(hash), key); + return DN_SIMDHASH_TRY_REMOVE_WITH_HASH(hash, key, key_hash); +} + +uint8_t +DN_SIMDHASH_TRY_REMOVE_WITH_HASH (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, uint32_t key_hash) +{ + check_self(hash); + + uint8_t suffix = dn_simdhash_select_suffix(key_hash); + uint32_t first_bucket_index = dn_simdhash_select_bucket_index(hash->buffers, key_hash); + dn_simdhash_search_vector search_vector = build_search_vector(suffix); + + BEGIN_SCAN_BUCKETS(hash->buffers, first_bucket_index, bucket_index, bucket_address) + int index_in_bucket = DN_SIMDHASH_SCAN_BUCKET_INTERNAL(hash, bucket_address, key, search_vector); + if (index_in_bucket >= 0) { + // We found the item. Replace it with the last item in the bucket, then erase + // the last item in the bucket. This ensures sequential scans still work. + uint8_t bucket_count = dn_simdhash_bucket_count(bucket_address->suffixes), + replacement_index_in_bucket = bucket_count - 1; + uint32_t value_slot_index = (bucket_index * DN_SIMDHASH_BUCKET_CAPACITY) + index_in_bucket, + replacement_value_slot_index = (bucket_index * DN_SIMDHASH_BUCKET_CAPACITY) + replacement_index_in_bucket; + + DN_SIMDHASH_VALUE_T *value_address = address_of_value(hash->buffers, value_slot_index); + DN_SIMDHASH_VALUE_T *replacement_address = address_of_value(hash->buffers, replacement_value_slot_index); + DN_SIMDHASH_KEY_T *key_address = &bucket_address->keys[index_in_bucket]; + DN_SIMDHASH_KEY_T *replacement_key_address = &bucket_address->keys[replacement_index_in_bucket]; + +#if DN_SIMDHASH_HAS_REMOVE_HANDLER + // Store for later, so we can run the callback after we're done removing the item + DN_SIMDHASH_VALUE_T value = *value_address; + // The key used for lookup may not be the key that was actually stored inside us, + // so make sure we store the one that was inside and destroy that one + DN_SIMDHASH_KEY_T actual_key = *key_address; +#endif + + hash->count--; + + // Update count first + dn_simdhash_bucket_set_count(bucket_address->suffixes, bucket_count - 1); + // Rotate replacement suffix from the end of the bucket to here + dn_simdhash_bucket_set_suffix( + bucket_address->suffixes, index_in_bucket, + bucket_address->suffixes.values[replacement_index_in_bucket] + ); + // Zero replacement suffix's old slot so it won't produce false positives in scans + dn_simdhash_bucket_set_suffix( + bucket_address->suffixes, replacement_index_in_bucket, 0 + ); + // Rotate replacement value from the end of the bucket to here + *value_address = *replacement_address; + // Rotate replacement key from the end of the bucket to here + *key_address = *replacement_key_address; + // Erase replacement key/value's old slots + // Skipped because memset is slow on wasm + // memset(replacement_key_address, 0, sizeof(DN_SIMDHASH_KEY_T)); + // memset(replacement_address, 0, sizeof(DN_SIMDHASH_VALUE_T)); + + // If this item cascaded out of its original target bucket, we need + // to go through all the buckets we visited on the way here and reduce + // their cascade counters (if possible), to maintain better scan performance. + if (bucket_index != first_bucket_index) + adjust_cascaded_counts(hash->buffers, first_bucket_index, bucket_index, 0); + +#if DN_SIMDHASH_HAS_REMOVE_HANDLER + // We've finished removing the item, so we're in a consistent state and can notify + DN_SIMDHASH_ON_REMOVE(DN_SIMDHASH_GET_DATA(hash), actual_key, value); +#endif + + return 1; + } else if (index_in_bucket == DN_SIMDHASH_SCAN_BUCKET_NO_OVERFLOW) + return 0; + END_SCAN_BUCKETS(hash->buffers, first_bucket_index, bucket_index, bucket_address) + + return 0; +} + +uint8_t +DN_SIMDHASH_TRY_REPLACE_VALUE (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, DN_SIMDHASH_VALUE_T new_value) +{ + check_self(hash); + + uint32_t key_hash = DN_SIMDHASH_KEY_HASHER(DN_SIMDHASH_GET_DATA(hash), key); + return DN_SIMDHASH_TRY_REPLACE_VALUE_WITH_HASH(hash, key, key_hash, new_value); +} + +uint8_t +DN_SIMDHASH_TRY_REPLACE_VALUE_WITH_HASH (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, uint32_t key_hash, DN_SIMDHASH_VALUE_T new_value) +{ + check_self(hash); + + DN_SIMDHASH_VALUE_T *value_ptr = DN_SIMDHASH_FIND_VALUE_INTERNAL(hash, key, key_hash); + if (!value_ptr) + return 0; +#if DN_SIMDHASH_HAS_REPLACE_HANDLER + DN_SIMDHASH_VALUE_T old_value = *value_ptr; +#endif + *value_ptr = new_value; +#if DN_SIMDHASH_HAS_REPLACE_HANDLER + DN_SIMDHASH_ON_REPLACE(DN_SIMDHASH_GET_DATA(hash), key, key, old_value, new_value); +#endif + return 1; +} + +void +DN_SIMDHASH_FOREACH (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_FOREACH_FUNC func, void *user_data) +{ + check_self(hash); + dn_simdhash_assert(func); + + dn_simdhash_buffers_t buffers = hash->buffers; + BEGIN_SCAN_PAIRS(buffers, key_address, value_address) + func(*key_address, *value_address, user_data); + END_SCAN_PAIRS(buffers, key_address, value_address) +} diff --git a/src/native/containers/dn-simdhash-specializations.h b/src/native/containers/dn-simdhash-specializations.h new file mode 100644 index 000000000000..9533edfc5f3d --- /dev/null +++ b/src/native/containers/dn-simdhash-specializations.h @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_SIMDHASH_SPECIALIZATIONS_H__ +#define __DN_SIMDHASH_SPECIALIZATIONS_H__ + +#include "dn-simdhash.h" + +typedef struct dn_simdhash_str_key dn_simdhash_str_key; + +#define DN_SIMDHASH_T dn_simdhash_string_ptr +#define DN_SIMDHASH_KEY_T dn_simdhash_str_key +#define DN_SIMDHASH_VALUE_T void * +#define DN_SIMDHASH_ACCESSOR_SUFFIX _raw + +#include "dn-simdhash-specialization-declarations.h" + +#undef DN_SIMDHASH_T +#undef DN_SIMDHASH_KEY_T +#undef DN_SIMDHASH_VALUE_T +#undef DN_SIMDHASH_ACCESSOR_SUFFIX + +#include "dn-simdhash-string-ptr.h" + + +#define DN_SIMDHASH_T dn_simdhash_u32_ptr +#define DN_SIMDHASH_KEY_T uint32_t +#define DN_SIMDHASH_VALUE_T void * + +#include "dn-simdhash-specialization-declarations.h" + +#undef DN_SIMDHASH_T +#undef DN_SIMDHASH_KEY_T +#undef DN_SIMDHASH_VALUE_T + + +#define DN_SIMDHASH_T dn_simdhash_ptr_ptr +#define DN_SIMDHASH_KEY_T void * +#define DN_SIMDHASH_VALUE_T void * + +#include "dn-simdhash-specialization-declarations.h" + +#undef DN_SIMDHASH_T +#undef DN_SIMDHASH_KEY_T +#undef DN_SIMDHASH_VALUE_T + + +#define DN_SIMDHASH_T dn_simdhash_ght +#define DN_SIMDHASH_KEY_T void * +#define DN_SIMDHASH_VALUE_T void * +#define DN_SIMDHASH_NO_DEFAULT_NEW 1 + +#include "dn-simdhash-specialization-declarations.h" + +#undef DN_SIMDHASH_T +#undef DN_SIMDHASH_KEY_T +#undef DN_SIMDHASH_VALUE_T +#undef DN_SIMDHASH_NO_DEFAULT_NEW + +#include "dn-simdhash-ght-compatible.h" + + +typedef struct dn_ptrpair_t { + void *first, *second; +} dn_ptrpair_t; + +#define DN_SIMDHASH_T dn_simdhash_ptrpair_ptr +#define DN_SIMDHASH_KEY_T dn_ptrpair_t +#define DN_SIMDHASH_VALUE_T void * + +#include "dn-simdhash-specialization-declarations.h" + +#undef DN_SIMDHASH_T +#undef DN_SIMDHASH_KEY_T +#undef DN_SIMDHASH_VALUE_T + +#endif diff --git a/src/native/containers/dn-simdhash-string-ptr.c b/src/native/containers/dn-simdhash-string-ptr.c new file mode 100644 index 000000000000..87c00f40f018 --- /dev/null +++ b/src/native/containers/dn-simdhash-string-ptr.c @@ -0,0 +1,93 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef NO_CONFIG_H +#include +#endif +#include "dn-simdhash.h" + +#include "dn-simdhash-utils.h" + +typedef struct dn_simdhash_str_key { + const char *text; + // We keep a precomputed hash to speed up rehashing and scans. + uint32_t hash; +#if SIZEOF_VOID_P == 8 + // HACK: Perfect cache alignment isn't possible for a 12-byte struct, so pad it to 16 bytes + uint32_t padding; +#endif +} dn_simdhash_str_key; + +static inline int32_t +dn_simdhash_str_equal (dn_simdhash_str_key v1, dn_simdhash_str_key v2) +{ + if (v1.text == v2.text) + return 1; + return strcmp(v1.text, v2.text) == 0; +} + +static inline uint32_t +dn_simdhash_str_hash (dn_simdhash_str_key v1) +{ + return v1.hash; +} + +#define DN_SIMDHASH_T dn_simdhash_string_ptr +#define DN_SIMDHASH_KEY_T dn_simdhash_str_key +#define DN_SIMDHASH_VALUE_T void * +#define DN_SIMDHASH_KEY_HASHER(hash, key) dn_simdhash_str_hash(key) +#define DN_SIMDHASH_KEY_EQUALS(hash, lhs, rhs) dn_simdhash_str_equal(lhs, rhs) +#define DN_SIMDHASH_ACCESSOR_SUFFIX _raw + +// perfect cache alignment. 32-bit ptrs: 8-byte keys. 64-bit: 16-byte keys. +#if SIZEOF_VOID_P == 8 +#define DN_SIMDHASH_BUCKET_CAPACITY 11 +#else +#define DN_SIMDHASH_BUCKET_CAPACITY 12 +#endif + +#include "dn-simdhash-specialization.h" +#include "dn-simdhash-string-ptr.h" + +static dn_simdhash_str_key +dn_simdhash_make_str_key (const char *text) +{ + dn_simdhash_str_key result = { 0, }; + if (text) { + // FIXME: Select a good seed. + result.hash = MurmurHash3_32_streaming((uint8_t *)text, 0); + result.text = text; + } + return result; +} + +uint8_t +dn_simdhash_string_ptr_try_add (dn_simdhash_string_ptr_t *hash, const char *key, void *value) +{ + return dn_simdhash_string_ptr_try_add_raw(hash, dn_simdhash_make_str_key(key), value); +} + +uint8_t +dn_simdhash_string_ptr_try_get_value (dn_simdhash_string_ptr_t *hash, const char *key, void **result) +{ + return dn_simdhash_string_ptr_try_get_value_raw(hash, dn_simdhash_make_str_key(key), result); +} + +uint8_t +dn_simdhash_string_ptr_try_remove (dn_simdhash_string_ptr_t *hash, const char *key) +{ + return dn_simdhash_string_ptr_try_remove_raw(hash, dn_simdhash_make_str_key(key)); +} + +// FIXME: Find a way to make this easier to define +void +dn_simdhash_string_ptr_foreach (dn_simdhash_string_ptr_t *hash, dn_simdhash_string_ptr_foreach_func func, void *user_data) +{ + assert(hash); + assert(func); + + dn_simdhash_buffers_t buffers = hash->buffers; + BEGIN_SCAN_PAIRS(buffers, key_address, value_address) + func(key_address->text, *value_address, user_data); + END_SCAN_PAIRS(buffers, key_address, value_address) +} diff --git a/src/native/containers/dn-simdhash-string-ptr.h b/src/native/containers/dn-simdhash-string-ptr.h new file mode 100644 index 000000000000..fc3e80fef568 --- /dev/null +++ b/src/native/containers/dn-simdhash-string-ptr.h @@ -0,0 +1,13 @@ +uint8_t +dn_simdhash_string_ptr_try_add (dn_simdhash_string_ptr_t *hash, const char *key, void *value); + +uint8_t +dn_simdhash_string_ptr_try_get_value (dn_simdhash_string_ptr_t *hash, const char *key, void **result); + +uint8_t +dn_simdhash_string_ptr_try_remove (dn_simdhash_string_ptr_t *hash, const char *key); + +typedef void (*dn_simdhash_string_ptr_foreach_func) (const char *key, void *value, void *user_data); + +void +dn_simdhash_string_ptr_foreach (dn_simdhash_string_ptr_t *hash, dn_simdhash_string_ptr_foreach_func func, void *user_data); diff --git a/src/native/containers/dn-simdhash-test.c b/src/native/containers/dn-simdhash-test.c new file mode 100644 index 000000000000..da0e60acb288 --- /dev/null +++ b/src/native/containers/dn-simdhash-test.c @@ -0,0 +1,262 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#include +#define MTICKS_PER_SEC (10 * 1000 * 1000) +#else +#include +#endif + +#include "dn-vector.h" +#include "dn-simdhash.h" +#include "dn-simdhash-utils.h" + +typedef struct { + int i; + float f; +} instance_data_t; + +void +dn_simdhash_assert_fail (const char *file, int line, const char *condition) { + printf("simdhash assertion failed at %s:%i:\n%s\n", file, line, condition); + fflush(stdout); +} + +static DN_FORCEINLINE(uint8_t) +key_comparer (instance_data_t data, size_t lhs, size_t rhs) { + return ((data.f == 4.20f) || (lhs == rhs)); +} + +#define DN_SIMDHASH_T dn_simdhash_size_t_size_t +#define DN_SIMDHASH_KEY_T size_t +#define DN_SIMDHASH_VALUE_T size_t +#define DN_SIMDHASH_KEY_HASHER(data, key) (uint32_t)(key & 0xFFFFFFFFu) +#define DN_SIMDHASH_KEY_EQUALS key_comparer +#define DN_SIMDHASH_INSTANCE_DATA_T instance_data_t +#define DN_SIMDHASH_ON_REMOVE(data, key, value) // printf("remove [%zd, %zd], f==%f\n", key, value, data.f) +#define DN_SIMDHASH_ON_REPLACE(data, old_key, new_key, old_value, new_value) // printf("replace [%zd, %zd] with [%zd, %zd] i==%i\n", key, old_value, key, new_value, data.i) + +#include "dn-simdhash-specialization.h" + +uint32_t count_cascaded_buckets (dn_simdhash_size_t_size_t_t *hash) { + uint32_t result = 0; + dn_simdhash_buffers_t buffers = hash->buffers; + BEGIN_SCAN_BUCKETS(0, bucket_index, bucket_address) + result += dn_simdhash_bucket_cascaded_count(bucket_address->suffixes); + END_SCAN_BUCKETS(0, bucket_index, bucket_address) + return result; +} + +uint8_t tassert (int b, const char *msg) { + if (b) + return b; + printf("%s\n", msg); + return 0; +} + +uint8_t tassert1 (int b, size_t v, const char *msg) { + if (b) + return b; + printf("%s (%zd)\n", msg, v); + return 0; +} + +uint8_t tasserteq (size_t actual, size_t expected, const char *msg) { + if (actual == expected) + return 1; + printf("%s: expected %zd, got %zd\n", msg, expected, actual); + return 0; +} + +void foreach_callback (size_t key, size_t value, void * user_data) { + // printf("[%zd, %zd]\n", key, value); + (*(uint32_t *)user_data)++; +} + +int64_t get_100ns_ticks () { +#ifdef _MSC_VER + static LARGE_INTEGER freq; + static UINT64 start_time; + UINT64 cur_time; + LARGE_INTEGER value; + + if (!freq.QuadPart) { + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&value); + start_time = value.QuadPart; + } + QueryPerformanceCounter(&value); + cur_time = value.QuadPart; + return (int64_t)((cur_time - start_time) * (double)MTICKS_PER_SEC / freq.QuadPart); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return ((int64_t)tv.tv_sec * 1000000 + tv.tv_usec) * 10; +#endif +} + +int main () { + // NOTE: High values of C will cause this test to never complete if libc + // rand() is not high quality enough, i.e. MSVC 2022 on x64 + const int c = 32000; + dn_simdhash_size_t_size_t_t *test = dn_simdhash_size_t_size_t_new(0, NULL); + dn_simdhash_instance_data(instance_data_t, test).f = 3.14f; + dn_simdhash_instance_data(instance_data_t, test).i = 42; + + printf("hash(test)=%u\n", MurmurHash3_32_ptr(test, 0)); + + dn_vector_t *keys = dn_vector_alloc(sizeof(DN_SIMDHASH_KEY_T)), + *values = dn_vector_alloc(sizeof(DN_SIMDHASH_VALUE_T)); + // Ensure consistency between runs + srand(1); + + for (int i = 0; i < c; i++) { + DN_SIMDHASH_VALUE_T value = (i * 2) + 1; + DN_SIMDHASH_KEY_T key; + +retry: { + key = rand(); + uint8_t ok = dn_simdhash_size_t_size_t_try_add(test, key, value); + if (!ok) + goto retry; +} + + dn_vector_push_back(keys, key); + dn_vector_push_back(values, value); + } + + int64_t started = get_100ns_ticks(); + for (int iter = 0; iter < 5; iter++) { + if (!tasserteq(dn_simdhash_count(test), c, "count did not match")) + return 1; + + printf("Calling foreach:\n"); + uint32_t foreach_count = 0; + dn_simdhash_size_t_size_t_foreach(test, foreach_callback, &foreach_count); + printf("Foreach iterated %u time(s)\n", foreach_count); + printf("Count: %u, Capacity: %u, Cascaded item count: %u\n", dn_simdhash_count(test), dn_simdhash_capacity(test), count_cascaded_buckets(test)); + + for (int i = 0; i < c; i++) { + DN_SIMDHASH_KEY_T key = *dn_vector_index_t(keys, DN_SIMDHASH_KEY_T, i); + DN_SIMDHASH_VALUE_T value, expected_value = *dn_vector_index_t(values, DN_SIMDHASH_VALUE_T, i); + + uint8_t ok = dn_simdhash_size_t_size_t_try_get_value(test, key, &value); + if (tassert1(ok, key, "did not find key")) + tasserteq(value, expected_value, "value did not match"); + } + + // NOTE: Adding duplicates could grow the table if we're unlucky, since the add operation + // eagerly grows before doing a table scan if we're at the grow threshold. + for (int i = 0; i < c; i++) { + DN_SIMDHASH_KEY_T key = *dn_vector_index_t(keys, DN_SIMDHASH_KEY_T, i); + DN_SIMDHASH_VALUE_T value = *dn_vector_index_t(values, DN_SIMDHASH_VALUE_T, i); + + uint8_t ok = dn_simdhash_size_t_size_t_try_add(test, key, value); + tassert1(!ok, key, "added duplicate key successfully"); + } + + printf("After adding dupes: Count: %u, Capacity: %u, Cascaded item count: %u\n", dn_simdhash_count(test), dn_simdhash_capacity(test), count_cascaded_buckets(test)); + uint32_t final_capacity = dn_simdhash_capacity(test); + + for (int i = 0; i < c; i++) { + DN_SIMDHASH_KEY_T key = *dn_vector_index_t(keys, DN_SIMDHASH_KEY_T, i); + uint8_t ok = dn_simdhash_size_t_size_t_try_remove(test, key); + tassert1(ok, key, "could not remove key"); + + DN_SIMDHASH_VALUE_T value; + ok = dn_simdhash_size_t_size_t_try_get_value(test, key, &value); + tassert1(!ok, key, "found key after removal"); + } + + if (!tasserteq(dn_simdhash_count(test), 0, "was not empty")) + return 1; + if (!tasserteq(dn_simdhash_capacity(test), final_capacity, "capacity changed by emptying")) + return 1; + + printf ("Calling foreach after emptying:\n"); + foreach_count = 0; + dn_simdhash_size_t_size_t_foreach(test, foreach_callback, &foreach_count); + printf("Foreach iterated %u time(s)\n", foreach_count); + printf("Count: %u, Capacity: %u, Cascaded item count: %u\n", dn_simdhash_count(test), dn_simdhash_capacity(test), count_cascaded_buckets(test)); + + for (int i = 0; i < c; i++) { + DN_SIMDHASH_KEY_T key = *dn_vector_index_t(keys, DN_SIMDHASH_KEY_T, i); + DN_SIMDHASH_VALUE_T value; + uint8_t ok = dn_simdhash_size_t_size_t_try_get_value(test, key, &value); + tassert1(!ok, key, "found key after removal"); + } + + for (int i = 0; i < c; i++) { + DN_SIMDHASH_KEY_T key = *dn_vector_index_t(keys, DN_SIMDHASH_KEY_T, i); + DN_SIMDHASH_VALUE_T value = *dn_vector_index_t(values, DN_SIMDHASH_VALUE_T, i); + + uint8_t ok = dn_simdhash_size_t_size_t_try_add(test, key, value); + tassert1(ok, key, "could not re-insert key after emptying"); + } + + if (!tasserteq(dn_simdhash_capacity(test), final_capacity, "expected capacity not to change after refilling")) + return 1; + + for (int i = 0; i < c; i++) { + DN_SIMDHASH_KEY_T key = *dn_vector_index_t(keys, DN_SIMDHASH_KEY_T, i); + DN_SIMDHASH_VALUE_T value, expected_value = *dn_vector_index_t(values, DN_SIMDHASH_VALUE_T, i); + + uint8_t ok = dn_simdhash_size_t_size_t_try_get_value(test, key, &value); + if (tassert1(ok, key, "did not find key after refilling")) + tasserteq(value, expected_value, "value did not match after refilling"); + } + + printf("Calling foreach after refilling:\n"); + foreach_count = 0; + dn_simdhash_size_t_size_t_foreach(test, foreach_callback, &foreach_count); + printf("Foreach iterated %u time(s)\n", foreach_count); + printf("Count: %u, Capacity: %u, Cascaded item count: %u\n", dn_simdhash_count(test), dn_simdhash_capacity(test), count_cascaded_buckets(test)); + } + + int64_t ended = get_100ns_ticks(); + + printf("done. elapsed ticks: %lld\n", (ended - started)); + + return 0; + /* + var test = new SimdDictionary(); + var rng = new Random(1234); + int c = 4096, d = 4096 * 5; + var keys = new List(); + for (int i = 0; i < c; i++) + keys.Add(rng.NextInt64()); + for (int i = 0; i < c; i++) + test.Add(keys[i], i * 2 + 1); + + for (int j = 0; j < d; j++) + for (int i = 0; i < c; i++) + if (!test.TryGetValue(keys[i], out _)) + throw new Exception(); + + var keyList = test.Keys.ToArray(); + var valueList = test.Values.ToArray(); + + var copy = new SimdDictionary(test); + for (int i = 0; i < c; i++) + if (!copy.TryGetValue(keys[i], out _)) + throw new Exception(); + + for (int i = 0; i < c; i++) + if (!test.Remove(keys[i])) + throw new Exception(); + + for (int i = 0; i < c; i++) + if (test.TryGetValue(keys[i], out _)) + throw new Exception(); + + if (test.Count != 0) + throw new Exception(); + */ +} diff --git a/src/native/containers/dn-simdhash-u32-ptr.c b/src/native/containers/dn-simdhash-u32-ptr.c new file mode 100644 index 000000000000..a3e1a77a92c2 --- /dev/null +++ b/src/native/containers/dn-simdhash-u32-ptr.c @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "dn-simdhash.h" +#include "dn-simdhash-utils.h" + +#define DN_SIMDHASH_T dn_simdhash_u32_ptr +#define DN_SIMDHASH_KEY_T uint32_t +#define DN_SIMDHASH_VALUE_T void * +#define DN_SIMDHASH_KEY_HASHER(hash, key) murmur3_fmix32(key) +#define DN_SIMDHASH_KEY_EQUALS(hash, lhs, rhs) (lhs == rhs) + +#include "dn-simdhash-specialization.h" diff --git a/src/native/containers/dn-simdhash-utils.h b/src/native/containers/dn-simdhash-utils.h new file mode 100644 index 000000000000..889127d4088a --- /dev/null +++ b/src/native/containers/dn-simdhash-utils.h @@ -0,0 +1,189 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_SIMDHASH_UTILS_H__ +#define __DN_SIMDHASH_UTILS_H__ + +#include + +#if defined(__clang__) || defined (__GNUC__) +static DN_FORCEINLINE(uint32_t) +next_power_of_two (uint32_t value) { + if (value < 2) + return 1; + return 1u << (32 - __builtin_clz (value - 1)); +} +#else // __clang__ || __GNUC__ +static DN_FORCEINLINE(uint32_t) +next_power_of_two (uint32_t value) { + if (value < 2) + return 1; + value--; + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + value++; + return value; +} +#endif // __clang__ || __GNUC__ + +// MurmurHash3 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. + +static const uint32_t murmur3_c1 = 0xcc9e2d51, murmur3_c2 = 0x1b873593; + +inline static uint32_t +murmur3_rotl32 (uint32_t x, int8_t r) +{ + return (x << r) | (x >> (32 - r)); +} + +// Finalization mix - force all bits of a hash block to avalanche +inline static uint32_t +murmur3_fmix32 (uint32_t h) +{ + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + + return h; +} + +inline static uint64_t +murmur3_fmix64(uint64_t k) +{ + k ^= k >> 33; + k *= 0xff51afd7ed558ccdLLU; + k ^= k >> 33; + k *= 0xc4ceb9fe1a85ec53LLU; + k ^= k >> 33; + return k; +} + +// Convenience macro so you can define your own fixed-size MurmurHashes +#define MURMUR3_HASH_BLOCK(block) \ + { \ + uint32_t k1 = block; \ + k1 *= murmur3_c1; \ + k1 = murmur3_rotl32(k1, 15); \ + k1 *= murmur3_c2; \ + h1 ^= k1; \ + h1 = murmur3_rotl32(h1, 13); \ + h1 = h1 * 5 + 0xe6546b64; \ + } + +// Hash a void * (either 4 or 8 bytes) +static inline uint32_t +MurmurHash3_32_ptr (const void *ptr, uint32_t seed) +{ + // mono_aligned_addr_hash shifts all incoming pointers by 3 bits to account + // for a presumed 8-byte alignment of addresses (the dlmalloc default). + const uint32_t alignment_shift = 3; + // Compute this outside of the if to suppress msvc build warning + const uint8_t is_64_bit = sizeof(void*) == sizeof(uint64_t); + union { + uint32_t u32; + uint64_t u64; + const void *ptr; + } u; + u.ptr = ptr; + + // Apply murmurhash3's finalization bit mixer to a pointer to compute a 32-bit hash. + if (is_64_bit) { + // The high bits of a 64-bit pointer are usually low entropy, as are the + // 2-3 lowest bits. We want to capture most of the entropy and mix it into + // a 32-bit hash to reduce the odds of hash collisions for arbitrary 64-bit + // pointers. From my testing, this is a good way to do it. + return murmur3_fmix32((uint32_t)((u.u64 >> alignment_shift) & 0xFFFFFFFFu)); + // return (uint32_t)(murmur3_fmix64(u.u64 >> alignment_shift) & 0xFFFFFFFFu); + } else { + // No need for an alignment shift here, we're mixing the bits and then + // simdhash uses 7 of the top bits and a handful of the low bits. + return murmur3_fmix32(u.u32); + } +} + +// end of murmurhash + +// FNV has bad properties for simdhash even though it's a fairly fast/good hash, +// but the overhead of having to do strlen() first before passing a string key to +// MurmurHash3 is significant and annoying. This is an attempt to reformulate the +// 32-bit version of MurmurHash3 into a 1-pass version for null terminated strings. +// The output of this will probably be different from regular MurmurHash3. I don't +// see that as a problem, since you shouldn't rely on the exact bit patterns of +// a non-cryptographic hash anyway. +typedef struct murmur3_scan_result_t { + union { + uint32_t u32; + uint8_t bytes[4]; + } result; + const uint8_t *next; +} murmur3_scan_result_t; + +static inline murmur3_scan_result_t +murmur3_scan_forward (const uint8_t *ptr) +{ + // TODO: On wasm we could do a single u32 load then scan the bytes, + // as long as we're sure ptr isn't up against the end of memory + murmur3_scan_result_t result = { 0, }; + + // I tried to get a loop to auto-unroll, but GCC only unrolls at O3 and MSVC never does. +#define SCAN_1(i) \ + result.result.bytes[i] = ptr[i]; \ + if (DN_UNLIKELY(!result.result.bytes[i])) \ + return result; + + SCAN_1(0); + SCAN_1(1); + SCAN_1(2); + SCAN_1(3); +#undef SCAN_1 + + // doing ptr[i] 4 times then computing here produces better code than ptr++ especially on wasm + result.next = ptr + 4; + return result; +} + +static inline uint32_t +MurmurHash3_32_streaming (const uint8_t *key, uint32_t seed) +{ + uint32_t h1 = seed, block_count = 0; + + // Scan forward through the buffer collecting up to 4 bytes at a time, then hash + murmur3_scan_result_t block = murmur3_scan_forward(key); + // As long as the scan found at least one nonzero byte, u32 will be != 0 + while (block.result.u32) { + block_count += 1; + + MURMUR3_HASH_BLOCK(block.result.u32); + + // If the scan found a null byte next will be 0, so we stop scanning + if (DN_UNLIKELY(!block.next)) + break; + block = murmur3_scan_forward(block.next); + } + + // finalize. we don't have an exact byte length but we have a block count + // it would be ideal to figure out a cheap way to produce an exact byte count, + // since then we can compute the length and hash in one go and use memcmp later, + // since emscripten/musl strcmp isn't optimized at all + h1 ^= block_count; + h1 = murmur3_fmix32(h1); + return h1; +} + +// end of reformulated murmur3-32 + +void +dn_simdhash_assert_fail (const char *file, int line, const char *condition); + +#define dn_simdhash_assert(expr) \ + if (DN_UNLIKELY(!(expr))) { \ + dn_simdhash_assert_fail(__FILE__, __LINE__, #expr); \ + } + +#endif // __DN_SIMDHASH_UTILS_H__ diff --git a/src/native/containers/dn-simdhash.c b/src/native/containers/dn-simdhash.c new file mode 100644 index 000000000000..d1e2b6e330b6 --- /dev/null +++ b/src/native/containers/dn-simdhash.c @@ -0,0 +1,165 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "dn-simdhash.h" +#include "dn-simdhash-utils.h" + +static uint32_t +compute_adjusted_capacity (uint32_t requested_capacity) +{ + uint64_t _capacity = requested_capacity; + _capacity *= DN_SIMDHASH_SIZING_PERCENTAGE; + _capacity /= 100; + dn_simdhash_assert(_capacity <= UINT32_MAX); + return (uint32_t)_capacity; +} + +dn_simdhash_t * +dn_simdhash_new_internal (dn_simdhash_meta_t *meta, dn_simdhash_vtable_t vtable, uint32_t capacity, dn_allocator_t *allocator) +{ + const size_t size = sizeof(dn_simdhash_t) + meta->data_size; + dn_simdhash_t *result = (dn_simdhash_t *)dn_allocator_alloc(allocator, size); + memset(result, 0, size); + + dn_simdhash_assert(meta); + dn_simdhash_assert((meta->bucket_capacity > 1) && (meta->bucket_capacity <= DN_SIMDHASH_MAX_BUCKET_CAPACITY)); + dn_simdhash_assert(meta->key_size > 0); + dn_simdhash_assert(meta->bucket_size_bytes >= (DN_SIMDHASH_VECTOR_WIDTH + (meta->bucket_capacity * meta->key_size))); + result->meta = meta; + result->vtable = vtable; + result->buffers.allocator = allocator; + + dn_simdhash_ensure_capacity_internal(result, compute_adjusted_capacity(capacity)); + + return result; +} + +void +dn_simdhash_free (dn_simdhash_t *hash) +{ + dn_simdhash_assert(hash); + if (hash->vtable.destroy_all) + hash->vtable.destroy_all(hash); + dn_simdhash_buffers_t buffers = hash->buffers; + memset(hash, 0, sizeof(dn_simdhash_t)); + dn_simdhash_free_buffers(buffers); + dn_allocator_free(buffers.allocator, (void *)hash); +} + +void +dn_simdhash_free_buffers (dn_simdhash_buffers_t buffers) +{ + if (buffers.buckets) + dn_allocator_free(buffers.allocator, (void *)(((uint8_t *)buffers.buckets) - buffers.buckets_bias)); + if (buffers.values) + dn_allocator_free(buffers.allocator, buffers.values); +} + +dn_simdhash_buffers_t +dn_simdhash_ensure_capacity_internal (dn_simdhash_t *hash, uint32_t capacity) +{ + dn_simdhash_assert(hash); + size_t bucket_count = (capacity + hash->meta->bucket_capacity - 1) / hash->meta->bucket_capacity; + // FIXME: Only apply this when capacity == 0? + if (bucket_count < DN_SIMDHASH_MIN_BUCKET_COUNT) + bucket_count = DN_SIMDHASH_MIN_BUCKET_COUNT; + dn_simdhash_assert(bucket_count < UINT32_MAX); + // Bucket count must be a power of two (this enables more efficient hashcode -> bucket mapping) + bucket_count = next_power_of_two((uint32_t)bucket_count); + size_t value_count = bucket_count * hash->meta->bucket_capacity; + dn_simdhash_assert(value_count <= UINT32_MAX); + + dn_simdhash_buffers_t result = { 0, }; + if (bucket_count <= hash->buffers.buckets_length) { + dn_simdhash_assert(value_count <= hash->buffers.values_length); + return result; + } + + /* + printf ( + "growing from %d bucket(s) to %d bucket(s) for requested capacity %d (actual capacity %d)\n", + hash->buffers.buckets_length, bucket_count, + capacity, value_count + ); + */ + // Store old buffers so caller can rehash and then free them + result = hash->buffers; + + size_t grow_at_count = value_count; + grow_at_count *= 100; + grow_at_count /= DN_SIMDHASH_SIZING_PERCENTAGE; + hash->grow_at_count = (uint32_t)grow_at_count; + hash->buffers.buckets_length = (uint32_t)bucket_count; + hash->buffers.values_length = (uint32_t)value_count; + + // pad buckets allocation by the width of one vector so we can align it + size_t buckets_size_bytes = (bucket_count * hash->meta->bucket_size_bytes) + DN_SIMDHASH_VECTOR_WIDTH, + values_size_bytes = value_count * hash->meta->value_size; + + hash->buffers.buckets = dn_allocator_alloc(hash->buffers.allocator, buckets_size_bytes); + memset(hash->buffers.buckets, 0, buckets_size_bytes); + + // Calculate necessary bias for alignment + hash->buffers.buckets_bias = (uint32_t)(DN_SIMDHASH_VECTOR_WIDTH - (((size_t)hash->buffers.buckets) % DN_SIMDHASH_VECTOR_WIDTH)); + // Apply bias + hash->buffers.buckets = (void *)(((uint8_t *)hash->buffers.buckets) + hash->buffers.buckets_bias); + + // No need to go out of our way to align values + hash->buffers.values = dn_allocator_alloc(hash->buffers.allocator, values_size_bytes); + // Skip this for performance; memset is especially slow in wasm + // memset(hash->buffers.values, 0, values_size_bytes); + + return result; +} + +void +dn_simdhash_clear (dn_simdhash_t *hash) +{ + dn_simdhash_assert(hash); + if (hash->vtable.destroy_all) + hash->vtable.destroy_all(hash); + hash->count = 0; + // TODO: Implement a fast clear algorithm that scans buckets and only clears ones w/nonzero count + memset(hash->buffers.buckets, 0, hash->buffers.buckets_length * hash->meta->bucket_size_bytes); + // Skip this for performance; memset is especially slow in wasm + // memset(hash->buffers.values, 0, hash->buffers.values_length * hash->meta->value_size); +} + +uint32_t +dn_simdhash_capacity (dn_simdhash_t *hash) +{ + dn_simdhash_assert(hash); + return hash->buffers.buckets_length * hash->meta->bucket_capacity; +} + +uint32_t +dn_simdhash_count (dn_simdhash_t *hash) +{ + dn_simdhash_assert(hash); + return hash->count; +} + +uint32_t +dn_simdhash_overflow_count (dn_simdhash_t *hash) +{ + assert(hash); + uint32_t result = 0; + for (uint32_t bucket_index = 0; bucket_index < hash->buffers.buckets_length; bucket_index++) { + uint8_t *suffixes = ((uint8_t *)hash->buffers.buckets) + (bucket_index * hash->meta->bucket_size_bytes); + uint8_t cascade_count = suffixes[DN_SIMDHASH_CASCADED_SLOT]; + result += cascade_count; + } + return result; +} + +void +dn_simdhash_ensure_capacity (dn_simdhash_t *hash, uint32_t capacity) +{ + dn_simdhash_assert(hash); + capacity = compute_adjusted_capacity(capacity); + dn_simdhash_buffers_t old_buffers = dn_simdhash_ensure_capacity_internal(hash, capacity); + if (old_buffers.buckets) { + hash->vtable.rehash(hash, old_buffers); + dn_simdhash_free_buffers(old_buffers); + } +} diff --git a/src/native/containers/dn-simdhash.h b/src/native/containers/dn-simdhash.h new file mode 100644 index 000000000000..a2d6e87c9045 --- /dev/null +++ b/src/native/containers/dn-simdhash.h @@ -0,0 +1,157 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __DN_SIMDHASH_H__ +#define __DN_SIMDHASH_H__ + +#include +#include "dn-utils.h" +#include "dn-allocator.h" + +// We reserve the last two bytes of each suffix vector to store data +#define DN_SIMDHASH_MAX_BUCKET_CAPACITY 14 +// The ideal capacity depends on the size of your keys. For 4-byte keys, it is 12. +#define DN_SIMDHASH_DEFAULT_BUCKET_CAPACITY 12 +// We use the last two bytes specifically to store item count and cascade flag +#define DN_SIMDHASH_COUNT_SLOT (DN_SIMDHASH_MAX_BUCKET_CAPACITY) +// The cascade flag indicates that an item overflowed from this bucket into the next one +#define DN_SIMDHASH_CASCADED_SLOT (DN_SIMDHASH_MAX_BUCKET_CAPACITY + 1) +// We always use 16-byte-wide vectors (I've tested this, 32-byte vectors are slower) +#define DN_SIMDHASH_VECTOR_WIDTH 16 +// We need to make sure suffixes are never zero. A bad hash is more likely to collide +// at the top bit than at the bottom. +#define DN_SIMDHASH_SUFFIX_SALT 0b10000000 +// Set a minimum number of buckets when created, regardless of requested capacity +#define DN_SIMDHASH_MIN_BUCKET_COUNT 1 +// User-specified capacity values will be increased to this percentage in order +// to maintain an ideal load factor. FIXME: 120 isn't right +#define DN_SIMDHASH_SIZING_PERCENTAGE 120 + +typedef struct dn_simdhash_void_data_t { + // HACK: Empty struct or 0-element array produce a MSVC warning and break the build. + uint8_t data[1]; +} dn_simdhash_void_data_t; + +typedef struct dn_simdhash_buffers_t { + // sizes of current allocations in items (not bytes) + // so values_length should == (buckets_length * bucket_capacity) + uint32_t buckets_length, values_length, + // The number of bytes we pushed the buckets ptr forward after allocating it. + // We'll need to subtract this from the ptr before freeing. + buckets_bias; + void *buckets; + void *values; + dn_allocator_t *allocator; +} dn_simdhash_buffers_t; + +typedef struct dn_simdhash_t dn_simdhash_t; + +typedef struct dn_simdhash_meta_t { + // type metadata for generic implementation + uint32_t bucket_capacity, bucket_size_bytes, key_size, value_size, + // Allocate this many bytes of extra data inside the dn_simdhash_t + data_size; +} dn_simdhash_meta_t; + +typedef enum dn_simdhash_insert_result { + DN_SIMDHASH_INSERT_OK_ADDED_NEW, + DN_SIMDHASH_INSERT_OK_OVERWROTE_EXISTING, + DN_SIMDHASH_INSERT_NEED_TO_GROW, + DN_SIMDHASH_INSERT_KEY_ALREADY_PRESENT, +} dn_simdhash_insert_result; + +typedef struct dn_simdhash_vtable_t { + // Does not free old_buffers, that's your job. Required. + void (*rehash) (dn_simdhash_t *hash, dn_simdhash_buffers_t old_buffers); + // Invokes remove handler for all items, if necessary. Optional. + void (*destroy_all) (dn_simdhash_t *hash); +} dn_simdhash_vtable_t; + +typedef struct dn_simdhash_t { + // internal state + uint32_t count, grow_at_count; + dn_simdhash_buffers_t buffers; + dn_simdhash_vtable_t vtable; + dn_simdhash_meta_t *meta; + // We allocate extra space here based on meta.data_size + // This has one element because 0 elements generates a MSVC warning and breaks the build + uint8_t data[1]; +} dn_simdhash_t; + +#define dn_simdhash_instance_data(type, hash) \ + (*(type *)(&hash->data)) + +// These helpers use .values instead of .vec to avoid generating unnecessary +// vector loads/stores. Operations that touch these values may not need vectorization, +// so it's ideal to just do single-byte memory accesses instead. +// These unfortunately have to be macros because the suffixes type isn't defined yet +#define dn_simdhash_bucket_count(suffixes) \ + (suffixes).values[DN_SIMDHASH_COUNT_SLOT] + +#define dn_simdhash_bucket_cascaded_count(suffixes) \ + (suffixes).values[DN_SIMDHASH_CASCADED_SLOT] + +#define dn_simdhash_bucket_set_suffix(suffixes, slot, value) \ + (suffixes).values[(slot)] = (value) + +#define dn_simdhash_bucket_set_count(suffixes, value) \ + (suffixes).values[DN_SIMDHASH_COUNT_SLOT] = (value) + +#define dn_simdhash_bucket_set_cascaded_count(suffixes, value) \ + (suffixes).values[DN_SIMDHASH_CASCADED_SLOT] = (value) + +static DN_FORCEINLINE(uint8_t) +dn_simdhash_select_suffix (uint32_t key_hash) +{ + // Extract top 8 bits, then trash the highest one. + // The lowest bits of the hash are used to select the bucket index. + return (key_hash >> 24) | DN_SIMDHASH_SUFFIX_SALT; +} + +// This relies on bucket count being a power of two. +#define dn_simdhash_select_bucket_index(buffers, key_hash) \ + ((key_hash) & ((buffers).buckets_length - 1)) + + +// Creates a simdhash with the provided configuration metadata, vtable, size, and allocator. +// Be sure you know what you're doing. +dn_simdhash_t * +dn_simdhash_new_internal (dn_simdhash_meta_t *meta, dn_simdhash_vtable_t vtable, uint32_t capacity, dn_allocator_t *allocator); + +// Frees a simdhash and its associated buffers. +void +dn_simdhash_free (dn_simdhash_t *hash); + +// Frees a set of simdhash buffers (returned by ensure_capacity_internal). +void +dn_simdhash_free_buffers (dn_simdhash_buffers_t buffers); + +// If a resize happens, this will allocate new buffers and return the old ones. +// It is your responsibility to rehash and then free the old buffers. +dn_simdhash_buffers_t +dn_simdhash_ensure_capacity_internal (dn_simdhash_t *hash, uint32_t capacity); + +// Erases the contents of the table, but does not shrink it. +void +dn_simdhash_clear (dn_simdhash_t *hash); + +// Returns the actual number of values the table can currently hold. +// It may grow automatically before reaching that point. +uint32_t +dn_simdhash_capacity (dn_simdhash_t *hash); + +// Returns the number of value currently stored in the table. +uint32_t +dn_simdhash_count (dn_simdhash_t *hash); + +// Returns the estimated number of items that have overflowed out of a bucket. +// WARNING: This is expensive to calculate. +uint32_t +dn_simdhash_overflow_count (dn_simdhash_t *hash); + +// Automatically resizes the table if it is too small to hold the requested number +// of items. Will not shrink the table if it is already bigger. +void +dn_simdhash_ensure_capacity (dn_simdhash_t *hash, uint32_t capacity); + +#endif // __DN_SIMDHASH_H__ diff --git a/src/native/containers/dn-utils.h b/src/native/containers/dn-utils.h index 131889165b2f..dab4160852b1 100644 --- a/src/native/containers/dn-utils.h +++ b/src/native/containers/dn-utils.h @@ -39,7 +39,7 @@ #define DN_CALLBACK_CALLTYPE #endif -#if defined(__GNUC__) && (__GNUC__ > 2) +#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2)) #define DN_LIKELY(expr) (__builtin_expect ((expr) != 0, 1)) #define DN_UNLIKELY(expr) (__builtin_expect ((expr) != 0, 0)) #else @@ -51,6 +51,12 @@ #define _DN_STATIC_ASSERT(expr) static_assert(expr, "") +#ifdef _MSC_VER +#define DN_FORCEINLINE(RET_TYPE) __forceinline RET_TYPE +#else +#define DN_FORCEINLINE(RET_TYPE) inline RET_TYPE __attribute__((always_inline)) +#endif + static inline bool dn_safe_size_t_multiply (size_t lhs, size_t rhs, size_t *result) { @@ -58,7 +64,7 @@ dn_safe_size_t_multiply (size_t lhs, size_t rhs, size_t *result) *result = 0; return true; } - + if (((size_t)(~(size_t)0) / lhs) < rhs) return false; diff --git a/src/native/containers/simdhash-benchmark/Makefile b/src/native/containers/simdhash-benchmark/Makefile new file mode 100644 index 000000000000..6349d1c96538 --- /dev/null +++ b/src/native/containers/simdhash-benchmark/Makefile @@ -0,0 +1,33 @@ +.DEFAULT_GOAL := default_target + +dn_deps := $(wildcard ../*.c) $(wildcard ../*.h) +benchmark_deps := $(wildcard ./*.c) $(wildcard ./*.h) +# I don't know why this is necessary +nodejs_path := $(shell which node) + +benchmark_sources := ../dn-simdhash.c ../dn-vector.c ./benchmark.c ../dn-simdhash-u32-ptr.c ../dn-simdhash-string-ptr.c ./ghashtable.c ./all-measurements.c +common_options := -g -O3 -DNO_CONFIG_H -lm -DNDEBUG +ifeq ($(SIMD), 0) + wasm_options := -mbulk-memory +else + wasm_options := -mbulk-memory -msimd128 +endif + +benchmark-native: $(dn_deps) $(benchmark_deps) + clang $(benchmark_sources) $(common_options) -DSIZEOF_VOID_P=8 + +benchmark-wasm: $(dn_deps) $(benchmark_deps) + ~/Projects/emscripten/emcc $(benchmark_sources) $(common_options) $(wasm_options) -DSIZEOF_VOID_P=4 + +disassemble-benchmark: benchmark-native benchmark-wasm + objdump -d ./a.out > ./a.dis + ~/wabt/bin/wasm2wat ./a.out.wasm > ./a.wat + +run-native: benchmark-native + ./a.out $(FILTER) + +run-wasm: benchmark-wasm + $(nodejs_path) ./a.out.js $(FILTER) + +default_target: disassemble-benchmark + diff --git a/src/native/containers/simdhash-benchmark/all-measurements.c b/src/native/containers/simdhash-benchmark/all-measurements.c new file mode 100644 index 000000000000..ac3356e69712 --- /dev/null +++ b/src/native/containers/simdhash-benchmark/all-measurements.c @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#define _CRT_RAND_S + +#include +#include +#include +#include + +#include "../dn-vector.h" +#include "../dn-simdhash.h" +#include "../dn-simdhash-utils.h" +#include "../dn-simdhash-specializations.h" + +#include "measurement.h" + +#undef MEASUREMENT +#define MEASUREMENT(name, data_type, setup, teardown, body) \ + static void DN_SIMDHASH_GLUE(measurement_, name) (void *_data) { \ + data_type data = (data_type)_data; \ + body; \ + } + +#include "all-measurements.h" + +#undef MEASUREMENT +#define MEASUREMENT(name, data_type, setup, teardown, body) \ + measurement_info DN_SIMDHASH_GLUE(name, _measurement_info) = { \ + #name, \ + setup, \ + DN_SIMDHASH_GLUE(measurement_, name), \ + teardown \ + }; + +#include "all-measurements.h" diff --git a/src/native/containers/simdhash-benchmark/all-measurements.h b/src/native/containers/simdhash-benchmark/all-measurements.h new file mode 100644 index 000000000000..e6646f203e49 --- /dev/null +++ b/src/native/containers/simdhash-benchmark/all-measurements.h @@ -0,0 +1,219 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "ghashtable.h" + +#ifndef MEASUREMENTS_IMPLEMENTATION +#define MEASUREMENTS_IMPLEMENTATION 1 + +#define INNER_COUNT 1024 * 32 +#define BASELINE_SIZE 20480 + +static dn_simdhash_u32_ptr_t *random_u32s_hash; +static dn_vector_t *sequential_u32s, *random_u32s, *random_unused_u32s; + +// rand() isn't guaranteed to give 32 random bits on all targets, so +// use xoshiro seeded with 4 known integers +// We want to use the same random sequence on every benchmark run, otherwise +// execution times could vary +uint64_t rol64(uint64_t x, int k) { + return (x << k) | (x >> (64 - k)); +} + +static uint64_t rng_state[4] = { + 0x6ED11324ABA9232Cul, + 0x1F0C07E6522724A6ul, + 0x293F7FDA2AF571D4ul, + 0x5804EC9FFD70112Aul, +}; + +uint64_t xoshiro256ss() { + uint64_t const result = rol64(rng_state[1] * 5, 7) * 9; + uint64_t const t = rng_state[1] << 17; + + rng_state[2] ^= rng_state[0]; + rng_state[3] ^= rng_state[1]; + rng_state[1] ^= rng_state[2]; + rng_state[0] ^= rng_state[3]; + + rng_state[2] ^= t; + rng_state[3] = rol64(rng_state[3], 45); + + return result; +} + +static uint32_t random_uint () { + return (uint32_t)(xoshiro256ss() & 0xFFFFFFFFu); +} + +static void init_data () { + random_u32s_hash = dn_simdhash_u32_ptr_new(INNER_COUNT, NULL); + sequential_u32s = dn_vector_alloc(sizeof(uint32_t)); + random_u32s = dn_vector_alloc(sizeof(uint32_t)); + random_unused_u32s = dn_vector_alloc(sizeof(uint32_t)); + + for (uint32_t i = 0; i < INNER_COUNT; i++) { + dn_vector_push_back(sequential_u32s, i); + +retry: { + uint32_t key = random_uint(); + if (!dn_simdhash_u32_ptr_try_add(random_u32s_hash, key, NULL)) + goto retry; + + dn_vector_push_back(random_u32s, key); +} + } + + for (uint32_t i = 0; i < INNER_COUNT; i++) { +retry2: { + uint32_t key = random_uint(); + if (!dn_simdhash_u32_ptr_try_add(random_u32s_hash, key, NULL)) + goto retry2; + + dn_vector_push_back(random_unused_u32s, key); +} + } +} + + +static void * create_instance_u32_ptr () { + if (!random_u32s) + init_data(); + + return dn_simdhash_u32_ptr_new(INNER_COUNT, NULL); +} + +static void * create_instance_u32_ptr_random_values () { + if (!random_u32s) + init_data(); + + dn_simdhash_u32_ptr_t *result = dn_simdhash_u32_ptr_new(INNER_COUNT, NULL); + for (int i = 0; i < INNER_COUNT; i++) { + uint32_t key = *dn_vector_index_t(random_u32s, uint32_t, i); + dn_simdhash_u32_ptr_try_add(result, key, (void *)(size_t)i); + } + return result; +} + +static void destroy_instance (void *_data) { + dn_simdhash_u32_ptr_t *data = _data; + if (!data) + return; + + dn_simdhash_free(data); +} + + +static void * baseline_init () { + return malloc(BASELINE_SIZE); +} + + +static void * create_instance_ght () { + if (!random_u32s) + init_data(); + + return g_hash_table_new(NULL, NULL); +} + +static void * create_instance_ght_random_values () { + if (!random_u32s) + init_data(); + + GHashTable *result = g_hash_table_new(NULL, NULL); + for (int i = 0; i < INNER_COUNT; i++) { + uint32_t key = *dn_vector_index_t(random_u32s, uint32_t, i); + g_hash_table_insert(result, (gpointer)(size_t)key, (gpointer)(size_t)i); + } + return result; +} + +static void destroy_instance_ght (void *data) { + g_hash_table_destroy((GHashTable *)data); +} + +#endif // MEASUREMENTS_IMPLEMENTATION + +// These go outside the guard because we include this file multiple times. + +MEASUREMENT(baseline, uint8_t *, baseline_init, free, { + for (int i = 0; i < 256; i++) { + memset(data, i, BASELINE_SIZE); + // Without this the memset gets optimized out + dn_simdhash_assert(data[i] == i); + } +}); + +MEASUREMENT(dn_clear_then_fill_sequential, dn_simdhash_u32_ptr_t *, create_instance_u32_ptr, destroy_instance, { + dn_simdhash_clear(data); + for (int i = 0; i < INNER_COUNT; i++) { + uint32_t key = *dn_vector_index_t(sequential_u32s, uint32_t, i); + dn_simdhash_assert(dn_simdhash_u32_ptr_try_add(data, key, (void *)(size_t)i)); + } +}) + +MEASUREMENT(dn_clear_then_fill_random, dn_simdhash_u32_ptr_t *, create_instance_u32_ptr, destroy_instance, { + dn_simdhash_clear(data); + for (int i = 0; i < INNER_COUNT; i++) { + uint32_t key = *dn_vector_index_t(random_u32s, uint32_t, i); + dn_simdhash_assert(dn_simdhash_u32_ptr_try_add(data, key, (void *)(size_t)i)); + } +}) + +MEASUREMENT(dn_find_random_keys, dn_simdhash_u32_ptr_t *, create_instance_u32_ptr_random_values, destroy_instance, { + void *temp = NULL; + for (int i = 0; i < INNER_COUNT; i++) { + uint32_t key = *dn_vector_index_t(random_u32s, uint32_t, i); + dn_simdhash_assert(dn_simdhash_u32_ptr_try_get_value(data, key, &temp)); + } +}) + +MEASUREMENT(dn_find_missing_key, dn_simdhash_u32_ptr_t *, create_instance_u32_ptr_random_values, destroy_instance, { + void *temp = NULL; + for (int i = 0; i < INNER_COUNT; i++) { + uint32_t key = *dn_vector_index_t(random_unused_u32s, uint32_t, i); + dn_simdhash_assert(!dn_simdhash_u32_ptr_try_get_value(data, key, &temp)); + } +}) + +MEASUREMENT(dn_fill_then_remove_every_item, dn_simdhash_u32_ptr_t *, create_instance_u32_ptr, destroy_instance, { + for (int i = 0; i < INNER_COUNT; i++) { + uint32_t key = *dn_vector_index_t(random_u32s, uint32_t, i); + dn_simdhash_assert(dn_simdhash_u32_ptr_try_add(data, key, (void *)(size_t)i)); + } + + for (int i = 0; i < INNER_COUNT; i++) { + uint32_t key = *dn_vector_index_t(random_u32s, uint32_t, i); + dn_simdhash_assert(dn_simdhash_u32_ptr_try_remove(data, key)); + } +}) + +MEASUREMENT(ght_clear_then_fill_sequential, GHashTable *, create_instance_ght, destroy_instance_ght, { + g_hash_table_remove_all(data); + for (int i = 0; i < INNER_COUNT; i++) { + uint32_t key = *dn_vector_index_t(sequential_u32s, uint32_t, i); + g_hash_table_insert(data, (gpointer)(size_t)key, (gpointer)(size_t)i); + } +}) + +MEASUREMENT(ght_clear_then_fill_random, GHashTable *, create_instance_ght, destroy_instance_ght, { + g_hash_table_remove_all(data); + for (int i = 0; i < INNER_COUNT; i++) { + uint32_t key = *dn_vector_index_t(random_u32s, uint32_t, i); + g_hash_table_insert(data, (gpointer)(size_t)key, (gpointer)(size_t)i); + } +}) + +MEASUREMENT(ght_find_random_keys, GHashTable *, create_instance_ght_random_values, destroy_instance_ght, { + for (int i = 0; i < INNER_COUNT; i++) { + uint32_t key = *dn_vector_index_t(random_u32s, uint32_t, i); + dn_simdhash_assert(g_hash_table_lookup(data, (gpointer)(size_t)key) == (gpointer)(size_t)i); + } +}) + +MEASUREMENT(ght_find_missing_key, GHashTable *, create_instance_ght_random_values, destroy_instance_ght, { + for (int i = 0; i < INNER_COUNT; i++) { + uint32_t key = *dn_vector_index_t(random_unused_u32s, uint32_t, i); + dn_simdhash_assert(g_hash_table_lookup(data, (gpointer)(size_t)key) == NULL); + } +}) diff --git a/src/native/containers/simdhash-benchmark/benchmark.c b/src/native/containers/simdhash-benchmark/benchmark.c new file mode 100644 index 000000000000..320e43389cbe --- /dev/null +++ b/src/native/containers/simdhash-benchmark/benchmark.c @@ -0,0 +1,211 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#include +#else +#include +#include +char *strcasestr(const char *haystack, const char *needle); +#endif + +#include "../dn-vector.h" +#include "../dn-simdhash.h" +#include "../dn-simdhash-utils.h" +#include "../dn-simdhash-specializations.h" + +#include "measurement.h" + +dn_simdhash_string_ptr_t *all_measurements; + +#undef MEASUREMENT +#define MEASUREMENT(name, data_type, setup, teardown, body) \ + extern measurement_info DN_SIMDHASH_GLUE(name, _measurement_info); + +// Suppress actual codegen +#define MEASUREMENTS_IMPLEMENTATION 0 + +#include "all-measurements.h" + +void +dn_simdhash_assert_fail (const char *file, int line, const char *condition) { + fprintf(stderr, "simdhash assertion failed at %s:%i:\n%s\n", file, line, condition); + fflush(stderr); + abort(); +} + +#define MTICKS_PER_SEC (10 * 1000 * 1000) + +int64_t get_100ns_ticks () { +#ifdef _MSC_VER + static LARGE_INTEGER freq; + static UINT64 start_time; + UINT64 cur_time; + LARGE_INTEGER value; + + if (!freq.QuadPart) { + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&value); + start_time = value.QuadPart; + } + QueryPerformanceCounter(&value); + cur_time = value.QuadPart; + return (int64_t)((cur_time - start_time) * (double)MTICKS_PER_SEC / freq.QuadPart); +#else + struct timespec ts; + // FIXME: Use clock_monotonic for wall time instead? I think process time is what we want +#ifdef __wasm + dn_simdhash_assert(clock_gettime(CLOCK_MONOTONIC, &ts) == 0); +#else + dn_simdhash_assert(clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0); +#endif + return ((int64_t)ts.tv_sec * MTICKS_PER_SEC + ts.tv_nsec / 100); +#endif +} + +void init_measurements () { + if (!all_measurements) + all_measurements = dn_simdhash_string_ptr_new (0, NULL); + + #undef MEASUREMENT + #define MEASUREMENT(name, data_type, setup, teardown, body) \ + dn_simdhash_string_ptr_try_add(all_measurements, #name, &DN_SIMDHASH_GLUE(name, _measurement_info)); + + #include "all-measurements.h" +} + +int64_t run_measurement (int iteration_count, setup_func setup, measurement_func measurement, measurement_func teardown) { + void *data = NULL; + if (setup) + data = setup(); + + int64_t started = get_100ns_ticks(); + for (int i = 0; i < iteration_count; i++) + measurement(data); + int64_t ended = get_100ns_ticks(); + + if (teardown) + teardown(data); + + return ended - started; +} + +typedef struct { + int argc; + char **argv; + int result; +} main_args; + +void foreach_measurement (const char *name, void *_info, void *_args) { + measurement_info *info = _info; + main_args *args = _args; + + uint8_t match = args->argc <= 1; + for (int i = 1; i < args->argc; i++) { +#ifdef _MSC_VER + if (strstr(name, args->argv[i])) { +#else + if (strcasestr(name, args->argv[i])) { +#endif + match = 1; + break; + } + } + + if (!match) + return; + + printf("%s: ", name); + fflush(stdout); + + run_measurement(100, info->setup, info->func, info->teardown); + + int64_t overhead = run_measurement(1, info->setup, info->func, info->teardown); + + int64_t warmup_duration = 20000000, + target_step_duration = 10000000, + target_duration = warmup_duration * 10, + warmup_iterations = 500, + warmup_until = get_100ns_ticks() + warmup_duration, + warmup_elapsed_total = 0, + warmup_count = 0; + + do { + warmup_elapsed_total += run_measurement(warmup_iterations, info->setup, info->func, info->teardown) - overhead; + warmup_count++; + } while (get_100ns_ticks() < warmup_until); + + int64_t average_warmup_duration = warmup_elapsed_total / warmup_count, + necessary_iterations = (target_step_duration * warmup_iterations / average_warmup_duration), + steps = 0, + run_elapsed_total = 0, + run_elapsed_min = INT64_MAX, + run_elapsed_max = INT64_MIN, + run_until = get_100ns_ticks() + target_duration; + + if (necessary_iterations < 16) + necessary_iterations = 16; + // HACK: Reduce minor variation in iteration count + necessary_iterations = next_power_of_two((uint32_t)necessary_iterations); + + printf( + "Warmed %" PRId64 " time(s). Running %" PRId64 " iterations... ", + warmup_count, necessary_iterations + ); + fflush(stdout); + + do { + int64_t step_duration = run_measurement(necessary_iterations, info->setup, info->func, info->teardown) - overhead; + run_elapsed_total += step_duration; + if (step_duration < run_elapsed_min) + run_elapsed_min = step_duration; + if (step_duration > run_elapsed_max) + run_elapsed_max = step_duration; + steps++; + } while (get_100ns_ticks() < run_until); + + double run_elapsed_average = (double)(run_elapsed_total) / steps / necessary_iterations / 100.0; + + args->result = 0; + printf( + "%" PRId64 " step(s): avg %.3fns min %.3fns max %.3fns\n", + steps, + run_elapsed_average, + (double)run_elapsed_min / necessary_iterations / 100.0, + (double)run_elapsed_max / necessary_iterations / 100.0 + ); + fflush(stdout); +} + +int main (int argc, char* argv[]) { + init_measurements(); + + main_args args = { + argc, argv, 1 + }; + dn_simdhash_string_ptr_foreach(all_measurements, foreach_measurement, &args); + + fflush(stdout); + fflush(stderr); + + switch (args.result) { + case 0: + break; + case 1: + // no benchmarks run + fprintf(stderr, "No benchmarks run. List of all benchmarks follows:\n"); + break; + default: + fprintf(stderr, "Unknown failure!\n"); + break; + } + + return args.result; +} diff --git a/src/native/containers/simdhash-benchmark/ghashtable.c b/src/native/containers/simdhash-benchmark/ghashtable.c new file mode 100644 index 000000000000..6e3f24eb77e8 --- /dev/null +++ b/src/native/containers/simdhash-benchmark/ghashtable.c @@ -0,0 +1,606 @@ +/* + * ghashtable.c: Hashtable implementation + * Modified for simdhash benchmarking + * + * Author: + * Miguel de Icaza (miguel@novell.com) + * + * (C) 2006 Novell, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "ghashtable.h" +#include + +typedef struct _Slot Slot; + +struct _Slot { + gpointer key; + gpointer value; + Slot *next; +}; + +static gpointer KEYMARKER_REMOVED = &KEYMARKER_REMOVED; + +struct _GHashTable { + GHashFunc hash_func; + GEqualFunc key_equal_func; + + Slot **table; + int table_size; + int in_use; + int threshold; + int last_rehash; + GDestroyNotify value_destroy_func, key_destroy_func; +}; + +typedef struct { + GHashTable *ht; + int slot_index; + Slot *slot; +} Iter; + +static const guint prime_tbl[] = { + 11, 19, 37, 73, 109, 163, 251, 367, 557, 823, 1237, + 1861, 2777, 4177, 6247, 9371, 14057, 21089, 31627, + 47431, 71143, 106721, 160073, 240101, 360163, + 540217, 810343, 1215497, 1823231, 2734867, 4102283, + 6153409, 9230113, 13845163 +}; + +static gboolean +test_prime (int x) +{ + if ((x & 1) != 0) { + int n; + for (n = 3; n< (int)sqrt (x); n += 2) { + if ((x % n) == 0) + return FALSE; + } + return TRUE; + } + // There is only one even prime - 2. + return (x == 2); +} + +static int +calc_prime (int x) +{ + int i; + + for (i = (x & (~1))-1; i< G_MAXINT32; i += 2) { + if (test_prime (i)) + return i; + } + return x; +} + +guint +g_spaced_primes_closest (guint x) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (prime_tbl); i++) { + if (x <= prime_tbl [i]) + return prime_tbl [i]; + } + return calc_prime (x); +} + +GHashTable * +g_hash_table_new (GHashFunc hash_func, GEqualFunc key_equal_func) +{ + GHashTable *hash; + + if (hash_func == NULL) + hash_func = g_direct_hash; + if (key_equal_func == NULL) + key_equal_func = g_direct_equal; + hash = g_new0 (GHashTable, 1); + + hash->hash_func = hash_func; + hash->key_equal_func = key_equal_func; + + hash->table_size = g_spaced_primes_closest (1); + hash->table = g_new0 (Slot *, hash->table_size); + hash->last_rehash = hash->table_size; + + return hash; +} + +GHashTable * +g_hash_table_new_full (GHashFunc hash_func, GEqualFunc key_equal_func, + GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func) +{ + GHashTable *hash = g_hash_table_new (hash_func, key_equal_func); + if (hash == NULL) + return NULL; + + hash->key_destroy_func = key_destroy_func; + hash->value_destroy_func = value_destroy_func; + + return hash; +} + +#define sanity_check(HASH) do {}while(0) + +static void +do_rehash (GHashTable *hash) +{ + int current_size, i; + Slot **table; + + /* printf ("Resizing diff=%d slots=%d\n", hash->in_use - hash->last_rehash, hash->table_size); */ + hash->last_rehash = hash->table_size; + current_size = hash->table_size; + hash->table_size = g_spaced_primes_closest (hash->in_use); + /* printf ("New size: %d\n", hash->table_size); */ + table = hash->table; + hash->table = g_new0 (Slot *, hash->table_size); + + for (i = 0; i < current_size; i++){ + Slot *s, *next; + + for (s = table [i]; s != NULL; s = next){ + guint hashcode = ((*hash->hash_func) (s->key)) % hash->table_size; + next = s->next; + + s->next = hash->table [hashcode]; + hash->table [hashcode] = s; + } + } + g_free (table); +} + +static void +rehash (GHashTable *hash) +{ + int diff = ABS (hash->last_rehash - hash->in_use); + + /* These are the factors to play with to change the rehashing strategy */ + /* I played with them with a large range, and could not really get */ + /* something that was too good, maybe the tests are not that great */ + if (!(diff * 0.75 > hash->table_size * 2)) + return; + do_rehash (hash); + sanity_check (hash); +} + +void +g_hash_table_insert_replace (GHashTable *hash, gpointer key, gpointer value, gboolean replace) +{ + guint hashcode; + Slot *s; + GEqualFunc equal; + + g_return_if_fail (hash != NULL); + sanity_check (hash); + + equal = hash->key_equal_func; + if (hash->in_use >= hash->threshold) + rehash (hash); + + hashcode = ((*hash->hash_func) (key)) % hash->table_size; + for (s = hash->table [hashcode]; s != NULL; s = s->next){ + if ((*equal) (s->key, key)){ + if (replace){ + if (hash->key_destroy_func != NULL) + (*hash->key_destroy_func)(s->key); + s->key = key; + } + if (hash->value_destroy_func != NULL) + (*hash->value_destroy_func) (s->value); + s->value = value; + sanity_check (hash); + return; + } + } + s = g_new (Slot, 1); + s->key = key; + s->value = value; + s->next = hash->table [hashcode]; + hash->table [hashcode] = s; + hash->in_use++; + sanity_check (hash); +} + +guint +g_hash_table_size (GHashTable *hash) +{ + g_return_val_if_fail (hash != NULL, 0); + + return hash->in_use; +} + +gboolean +g_hash_table_contains (GHashTable *hash, gconstpointer key) +{ + g_return_val_if_fail (key != NULL, FALSE); + + return g_hash_table_lookup_extended (hash, key, NULL, NULL); +} + +gpointer +g_hash_table_lookup (GHashTable *hash, gconstpointer key) +{ + gpointer orig_key, value; + + if (g_hash_table_lookup_extended (hash, key, &orig_key, &value)) + return value; + else + return NULL; +} + +gboolean +g_hash_table_lookup_extended (GHashTable *hash, gconstpointer key, gpointer *orig_key, gpointer *value) +{ + GEqualFunc equal; + Slot *s; + guint hashcode; + + g_return_val_if_fail (hash != NULL, FALSE); + sanity_check (hash); + equal = hash->key_equal_func; + + hashcode = ((*hash->hash_func) (key)) % hash->table_size; + + for (s = hash->table [hashcode]; s != NULL; s = s->next){ + if ((*equal)(s->key, key)){ + if (orig_key) + *orig_key = s->key; + if (value) + *value = s->value; + return TRUE; + } + } + return FALSE; +} + +void +g_hash_table_foreach (GHashTable *hash, GHFunc func, gpointer user_data) +{ + int i; + + g_return_if_fail (hash != NULL); + g_return_if_fail (func != NULL); + + for (i = 0; i < hash->table_size; i++){ + Slot *s; + + for (s = hash->table [i]; s != NULL; s = s->next) + (*func)(s->key, s->value, user_data); + } +} + +gpointer +g_hash_table_find (GHashTable *hash, GHRFunc predicate, gpointer user_data) +{ + int i; + + g_return_val_if_fail (hash != NULL, NULL); + g_return_val_if_fail (predicate != NULL, NULL); + + for (i = 0; i < hash->table_size; i++){ + Slot *s; + + for (s = hash->table [i]; s != NULL; s = s->next) + if ((*predicate)(s->key, s->value, user_data)) + return s->value; + } + return NULL; +} + +void +g_hash_table_remove_all (GHashTable *hash) +{ + int i; + + g_return_if_fail (hash != NULL); + + for (i = 0; i < hash->table_size; i++){ + Slot *s; + + while (hash->table [i]) { + s = hash->table [i]; + g_hash_table_remove (hash, s->key); + } + } +} + +gboolean +g_hash_table_remove (GHashTable *hash, gconstpointer key) +{ + GEqualFunc equal; + Slot *s, *last; + guint hashcode; + + g_return_val_if_fail (hash != NULL, FALSE); + sanity_check (hash); + equal = hash->key_equal_func; + + hashcode = ((*hash->hash_func)(key)) % hash->table_size; + last = NULL; + for (s = hash->table [hashcode]; s != NULL; s = s->next){ + if ((*equal)(s->key, key)){ + if (hash->key_destroy_func != NULL) + (*hash->key_destroy_func)(s->key); + if (hash->value_destroy_func != NULL) + (*hash->value_destroy_func)(s->value); + if (last == NULL) + hash->table [hashcode] = s->next; + else + last->next = s->next; + g_free (s); + hash->in_use--; + sanity_check (hash); + return TRUE; + } + last = s; + } + sanity_check (hash); + return FALSE; +} + +guint +g_hash_table_foreach_remove (GHashTable *hash, GHRFunc func, gpointer user_data) +{ + int i; + int count = 0; + + g_return_val_if_fail (hash != NULL, 0); + g_return_val_if_fail (func != NULL, 0); + + sanity_check (hash); + for (i = 0; i < hash->table_size; i++){ + Slot *s, *last; + + last = NULL; + for (s = hash->table [i]; s != NULL; ){ + if ((*func)(s->key, s->value, user_data)){ + Slot *n; + + if (hash->key_destroy_func != NULL) + (*hash->key_destroy_func)(s->key); + if (hash->value_destroy_func != NULL) + (*hash->value_destroy_func)(s->value); + if (last == NULL){ + hash->table [i] = s->next; + n = s->next; + } else { + last->next = s->next; + n = last->next; + } + g_free (s); + hash->in_use--; + count++; + s = n; + } else { + last = s; + s = s->next; + } + } + } + sanity_check (hash); + if (count > 0) + rehash (hash); + return count; +} + +gboolean +g_hash_table_steal (GHashTable *hash, gconstpointer key) +{ + GEqualFunc equal; + Slot *s, *last; + guint hashcode; + + g_return_val_if_fail (hash != NULL, FALSE); + sanity_check (hash); + equal = hash->key_equal_func; + + hashcode = ((*hash->hash_func)(key)) % hash->table_size; + last = NULL; + for (s = hash->table [hashcode]; s != NULL; s = s->next){ + if ((*equal)(s->key, key)) { + if (last == NULL) + hash->table [hashcode] = s->next; + else + last->next = s->next; + g_free (s); + hash->in_use--; + sanity_check (hash); + return TRUE; + } + last = s; + } + sanity_check (hash); + return FALSE; + +} + +guint +g_hash_table_foreach_steal (GHashTable *hash, GHRFunc func, gpointer user_data) +{ + int i; + int count = 0; + + g_return_val_if_fail (hash != NULL, 0); + g_return_val_if_fail (func != NULL, 0); + + sanity_check (hash); + for (i = 0; i < hash->table_size; i++){ + Slot *s, *last; + + last = NULL; + for (s = hash->table [i]; s != NULL; ){ + if ((*func)(s->key, s->value, user_data)){ + Slot *n; + + if (last == NULL){ + hash->table [i] = s->next; + n = s->next; + } else { + last->next = s->next; + n = last->next; + } + g_free (s); + hash->in_use--; + count++; + s = n; + } else { + last = s; + s = s->next; + } + } + } + sanity_check (hash); + if (count > 0) + rehash (hash); + return count; +} + +void +g_hash_table_destroy (GHashTable *hash) +{ + int i; + + if (!hash) + return; + + for (i = 0; i < hash->table_size; i++){ + Slot *s, *next; + + for (s = hash->table [i]; s != NULL; s = next){ + next = s->next; + + if (hash->key_destroy_func != NULL) + (*hash->key_destroy_func)(s->key); + if (hash->value_destroy_func != NULL) + (*hash->value_destroy_func)(s->value); + g_free (s); + } + } + g_free (hash->table); + + g_free (hash); +} + +void +g_hash_table_print_stats (GHashTable *table) +{ + int i, max_chain_index, chain_size, max_chain_size; + Slot *node; + + max_chain_size = 0; + max_chain_index = -1; + for (i = 0; i < table->table_size; i++) { + chain_size = 0; + for (node = table->table [i]; node; node = node->next) + chain_size ++; + if (chain_size > max_chain_size) { + max_chain_size = chain_size; + max_chain_index = i; + } + } + + printf ("Size: %d Table Size: %d Max Chain Length: %d at %d\n", table->in_use, table->table_size, max_chain_size, max_chain_index); +} + +void +g_hash_table_iter_init (GHashTableIter *it, GHashTable *hash_table) +{ + Iter *iter = (Iter*)it; + + memset (iter, 0, sizeof (Iter)); + iter->ht = hash_table; + iter->slot_index = -1; +} + +gboolean g_hash_table_iter_next (GHashTableIter *it, gpointer *key, gpointer *value) +{ + Iter *iter = (Iter*)it; + + GHashTable *hash = iter->ht; + + g_assert (iter->slot_index != -2); + g_assert (sizeof (Iter) <= sizeof (GHashTableIter)); + + if (!iter->slot) { + while (TRUE) { + iter->slot_index ++; + if (iter->slot_index >= hash->table_size) { + iter->slot_index = -2; + return FALSE; + } + if (hash->table [iter->slot_index]) + break; + } + iter->slot = hash->table [iter->slot_index]; + } + + if (key) + *key = iter->slot->key; + if (value) + *value = iter->slot->value; + iter->slot = iter->slot->next; + + return TRUE; +} + +gboolean +g_direct_equal (gconstpointer v1, gconstpointer v2) +{ + return v1 == v2; +} + +guint +g_direct_hash (gconstpointer v1) +{ + return GCONSTPOINTER_TO_UINT (v1); +} + +gboolean +g_int_equal (gconstpointer v1, gconstpointer v2) +{ + return *(gint *)v1 == *(gint *)v2; +} + +guint +g_int_hash (gconstpointer v1) +{ + return *(guint *)v1; +} + +gboolean +g_str_equal (gconstpointer v1, gconstpointer v2) +{ + return v1 == v2 || strcmp ((const char*)v1, (const char*)v2) == 0; +} + +guint +g_str_hash (gconstpointer v1) +{ + guint hash = 0; + unsigned char *p = (unsigned char *) v1; + + while (*p++) + hash = (hash << 5) - (hash + *p); + + return hash; +} diff --git a/src/native/containers/simdhash-benchmark/ghashtable.h b/src/native/containers/simdhash-benchmark/ghashtable.h new file mode 100644 index 000000000000..076ddfde5e1c --- /dev/null +++ b/src/native/containers/simdhash-benchmark/ghashtable.h @@ -0,0 +1,157 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef GHASHTABLE_H +#define GHASHTABLE_H + +#include +#include +#include +#include + +/* + * Basic data types + */ +typedef int gint; +typedef unsigned int guint; +typedef short gshort; +typedef unsigned short gushort; +typedef long glong; +typedef unsigned long gulong; +typedef void * gpointer; +typedef const void * gconstpointer; +typedef char gchar; +typedef unsigned char guchar; + +/* Types defined in terms of the stdint.h */ +typedef int8_t gint8; +typedef uint8_t guint8; +typedef int16_t gint16; +typedef uint16_t guint16; +typedef int32_t gint32; +typedef uint32_t guint32; +typedef int64_t gint64; +typedef uint64_t guint64; +typedef float gfloat; +typedef double gdouble; +typedef int32_t gboolean; +// typedef ptrdiff_t gptrdiff; +typedef intptr_t gintptr; +typedef uintptr_t guintptr; + +#define G_N_ELEMENTS(arr) (sizeof(arr)/sizeof(arr[0])) + +#define FALSE 0 +#define TRUE 1 + +#define G_MINSHORT SHRT_MIN +#define G_MAXSHORT SHRT_MAX +#define G_MAXUSHORT USHRT_MAX +#define G_MAXINT INT_MAX +#define G_MININT INT_MIN +#define G_MAXINT8 INT8_MAX +#define G_MAXUINT8 UINT8_MAX +#define G_MININT8 INT8_MIN +#define G_MAXINT16 INT16_MAX +#define G_MAXUINT16 UINT16_MAX +#define G_MININT16 INT16_MIN +#define G_MAXINT32 INT32_MAX +#define G_MAXUINT32 UINT32_MAX +#define G_MININT32 INT32_MIN +#define G_MININT64 INT64_MIN +#define G_MAXINT64 INT64_MAX +#define G_MAXUINT64 UINT64_MAX + +#define G_LITTLE_ENDIAN 1234 +#define G_BIG_ENDIAN 4321 +#define G_STMT_START do +#define G_STMT_END while (0) + +typedef void (*GFunc) (gpointer data, gpointer user_data); +typedef gint (*GCompareFunc) (gconstpointer a, gconstpointer b); +typedef gint (*GCompareDataFunc) (gconstpointer a, gconstpointer b, gpointer user_data); +typedef void (*GHFunc) (gpointer key, gpointer value, gpointer user_data); +typedef gboolean (*GHRFunc) (gpointer key, gpointer value, gpointer user_data); +typedef void (*GDestroyNotify) (gpointer data); +typedef guint (*GHashFunc) (gconstpointer key); +typedef gboolean (*GEqualFunc) (gconstpointer a, gconstpointer b); +typedef void (*GFreeFunc) (gpointer data); + +/* + * Hashtables + */ +typedef struct _GHashTable GHashTable; +typedef struct _GHashTableIter GHashTableIter; + +/* Private, but needed for stack allocation */ +struct _GHashTableIter +{ + gpointer dummy [8]; +}; + +GHashTable *g_hash_table_new (GHashFunc hash_func, GEqualFunc key_equal_func); +GHashTable *g_hash_table_new_full (GHashFunc hash_func, GEqualFunc key_equal_func, + GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func); +void g_hash_table_insert_replace (GHashTable *hash, gpointer key, gpointer value, gboolean replace); +guint g_hash_table_size (GHashTable *hash); +gboolean g_hash_table_contains (GHashTable *hash, gconstpointer key); +gpointer g_hash_table_lookup (GHashTable *hash, gconstpointer key); +gboolean g_hash_table_lookup_extended (GHashTable *hash, gconstpointer key, gpointer *orig_key, gpointer *value); +void g_hash_table_foreach (GHashTable *hash, GHFunc func, gpointer user_data); +gpointer g_hash_table_find (GHashTable *hash, GHRFunc predicate, gpointer user_data); +gboolean g_hash_table_remove (GHashTable *hash, gconstpointer key); +gboolean g_hash_table_steal (GHashTable *hash, gconstpointer key); +void g_hash_table_remove_all (GHashTable *hash); +guint g_hash_table_foreach_remove (GHashTable *hash, GHRFunc func, gpointer user_data); +guint g_hash_table_foreach_steal (GHashTable *hash, GHRFunc func, gpointer user_data); +void g_hash_table_destroy (GHashTable *hash); +void g_hash_table_print_stats (GHashTable *table); + +void g_hash_table_iter_init (GHashTableIter *iter, GHashTable *hash_table); +gboolean g_hash_table_iter_next (GHashTableIter *iter, gpointer *key, gpointer *value); + +guint g_spaced_primes_closest (guint x); + +#define g_hash_table_insert(h,k,v) g_hash_table_insert_replace ((h),(k),(v),FALSE) +#define g_hash_table_replace(h,k,v) g_hash_table_insert_replace ((h),(k),(v),TRUE) +#define g_hash_table_add(h,k) g_hash_table_insert_replace ((h),(k),(k),TRUE) + +gboolean g_direct_equal (gconstpointer v1, gconstpointer v2); +guint g_direct_hash (gconstpointer v1); +gboolean g_int_equal (gconstpointer v1, gconstpointer v2); +guint g_int_hash (gconstpointer v1); +gboolean g_str_equal (gconstpointer v1, gconstpointer v2); +guint g_str_hash (gconstpointer v1); + +#define GCONSTPOINTER_TO_INT(v) (gint)((ssize_t)v) +#define GCONSTPOINTER_TO_UINT(v) (gint)((size_t)v) + +// FIXME +#define g_assert(expr) (void)(expr) + +#define g_malloc malloc +#define g_free free +#define g_realloc realloc + +#define g_new(type,size) ((type *) g_malloc (sizeof (type) * (size))) +#define g_new0(type,size) ((type *) g_malloc0 (sizeof (type)* (size))) +#define g_newa(type,size) ((type *) alloca (sizeof (type) * (size))) +#define g_newa0(type,size) ((type *) memset (alloca (sizeof (type) * (size)), 0, sizeof (type) * (size))) + +#define g_memmove(dest,src,len) memmove (dest, src, len) +#define g_renew(struct_type, mem, n_structs) ((struct_type*)g_realloc (mem, sizeof (struct_type) * n_structs)) +#define g_alloca(size) (g_cast (alloca (size))) + +#define g_return_if_fail(x) if (!(x)) { return; } +#define g_return_val_if_fail(x,e) if (!(x)) { return (e); } + +static inline void * +g_malloc0 (size_t size) { + void * result = malloc(size); + memset(result, 0, size); + return result; +} + +#define ABS(x) abs(x) + +#endif // GHASHTABLE_H diff --git a/src/native/containers/simdhash-benchmark/measurement.h b/src/native/containers/simdhash-benchmark/measurement.h new file mode 100644 index 000000000000..368253a357df --- /dev/null +++ b/src/native/containers/simdhash-benchmark/measurement.h @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +typedef void * (*setup_func) (void); +typedef void (*measurement_func) (void *data); + +typedef struct { + const char *name; + setup_func setup; + measurement_func func, teardown; +} measurement_info; diff --git a/src/native/containers/simdhash-benchmark/run-benchmark.ps1 b/src/native/containers/simdhash-benchmark/run-benchmark.ps1 new file mode 100755 index 000000000000..9417d16c505c --- /dev/null +++ b/src/native/containers/simdhash-benchmark/run-benchmark.ps1 @@ -0,0 +1,2 @@ +cl /GS- /O2 /std:c17 ./*.c ../dn-simdhash-u32-ptr.c ../dn-simdhash.c ../dn-vector.c ../dn-simdhash-string-ptr.c /DNO_CONFIG_H /DSIZEOF_VOID_P=8 /DNDEBUG /Fe:all-measurements.exe +./all-measurements.exe diff --git a/src/native/corehost/apphost/static/singlefilehost.def b/src/native/corehost/apphost/static/singlefilehost.def index e1208056b832..9d193783f950 100644 --- a/src/native/corehost/apphost/static/singlefilehost.def +++ b/src/native/corehost/apphost/static/singlefilehost.def @@ -18,3 +18,6 @@ g_dacTable = s_dacGlobals ; Used by profilers MetaDataGetDispenser + +; cDAC contract descriptor +DotNetRuntimeContractDescriptor diff --git a/src/native/corehost/apphost/static/singlefilehost_freebsdexports.src b/src/native/corehost/apphost/static/singlefilehost_freebsdexports.src index 1f9c51782185..da5cab866d93 100644 --- a/src/native/corehost/apphost/static/singlefilehost_freebsdexports.src +++ b/src/native/corehost/apphost/static/singlefilehost_freebsdexports.src @@ -10,6 +10,9 @@ g_dacTable ; Used by profilers MetaDataGetDispenser +; cDAC contract descriptor +DotNetRuntimeContractDescriptor + ; FreeBSD needs to reexport these __progname environ diff --git a/src/native/corehost/apphost/static/singlefilehost_unixexports.src b/src/native/corehost/apphost/static/singlefilehost_unixexports.src index 18d5697e8458..23c60f6b8b16 100644 --- a/src/native/corehost/apphost/static/singlefilehost_unixexports.src +++ b/src/native/corehost/apphost/static/singlefilehost_unixexports.src @@ -9,3 +9,6 @@ g_dacTable ; Used by profilers MetaDataGetDispenser + +; cDAC contract descriptor +DotNetRuntimeContractDescriptor diff --git a/src/native/corehost/bundle/extractor.cpp b/src/native/corehost/bundle/extractor.cpp index fc0659e82dc3..ab2c53295055 100644 --- a/src/native/corehost/bundle/extractor.cpp +++ b/src/native/corehost/bundle/extractor.cpp @@ -219,7 +219,7 @@ void extractor_t::commit_dir() // Retry the move operation with some wait in between the attempts. This is to workaround for possible file locking // caused by AV software. Basically the extraction process above writes a bunch of executable files to disk // and some AV software may decide to scan them on write. If this happens the files will be locked which blocks - // our ablity to move them. + // our ability to move them. bool extracted_by_concurrent_process = false; bool extracted_by_current_process = diff --git a/src/native/corehost/corehost.proj b/src/native/corehost/corehost.proj index 026cff692856..99a1bb9f5c5b 100644 --- a/src/native/corehost/corehost.proj +++ b/src/native/corehost/corehost.proj @@ -78,6 +78,20 @@ <_CoreHostUnixTargetOS Condition="'$(TargetsLinuxBionic)' == 'true'">linux-bionic $(Configuration) $(TargetArchitecture) -commithash "$([MSBuild]::ValueOrDefault('$(SourceRevisionId)', 'N/A'))" -os $(_CoreHostUnixTargetOS) $(BuildArgs) -cmakeargs "-DVERSION_FILE_PATH=$(NativeVersionFile)" + + + $(BuildArgs) -cmakeargs -DCLR_CMAKE_CXX_STANDARD_LIBRARY=$(CxxStandardLibrary) + + + + $(BuildArgs) -cmakeargs -DCLR_CMAKE_CXX_STANDARD_LIBRARY_STATIC=ON + + + + $(BuildArgs) -cmakeargs -DCLR_CMAKE_CXX_ABI_LIBRARY=$(CxxAbiLibrary) + + + $(BuildArgs) -configureonly $(BuildArgs) -portablebuild=false $(BuildArgs) -keepnativesymbols diff --git a/src/native/corehost/fxr/fx_muxer.cpp b/src/native/corehost/fxr/fx_muxer.cpp index cbaf90aa69cb..02c80c590948 100644 --- a/src/native/corehost/fxr/fx_muxer.cpp +++ b/src/native/corehost/fxr/fx_muxer.cpp @@ -465,7 +465,7 @@ namespace } else { - rc = fx_resolver_t::resolve_frameworks_for_app(host_info, app_config.get_is_multilevel_lookup_disabled(), override_settings, app_config, fx_definitions, mode == host_mode_t::muxer ? app_candidate.c_str() : nullptr); + rc = fx_resolver_t::resolve_frameworks_for_app(host_info.dotnet_root, override_settings, app_config, fx_definitions, mode == host_mode_t::muxer ? app_candidate.c_str() : host_info.host_path.c_str()); if (rc != StatusCode::Success) { return rc; @@ -619,7 +619,7 @@ namespace return StatusCode::InvalidConfigFile; } - rc = fx_resolver_t::resolve_frameworks_for_app(host_info, app_config.get_is_multilevel_lookup_disabled(), override_settings, app_config, fx_definitions); + rc = fx_resolver_t::resolve_frameworks_for_app(host_info.dotnet_root, override_settings, app_config, fx_definitions, host_info.host_path.c_str()); if (rc != StatusCode::Success) return rc; diff --git a/src/native/corehost/fxr/fx_resolver.cpp b/src/native/corehost/fxr/fx_resolver.cpp index 1340af625423..e78bd63eca10 100644 --- a/src/native/corehost/fxr/fx_resolver.cpp +++ b/src/native/corehost/fxr/fx_resolver.cpp @@ -184,7 +184,7 @@ namespace return best_match; } - fx_definition_t* resolve_framework_reference( + std::unique_ptr resolve_framework_reference( const fx_reference_t & fx_ref, const pal::string_t & oldest_requested_version, const pal::string_t & dotnet_dir, @@ -303,7 +303,7 @@ namespace trace::verbose(_X("Chose FX version [%s]"), selected_fx_dir.c_str()); - return new fx_definition_t(fx_ref.get_fx_name(), selected_fx_dir, oldest_requested_version, selected_fx_version); + return std::unique_ptr(new fx_definition_t(fx_ref.get_fx_name(), selected_fx_dir, oldest_requested_version, selected_fx_version)); } } @@ -320,7 +320,8 @@ namespace StatusCode fx_resolver_t::reconcile_fx_references( const fx_reference_t& fx_ref_a, const fx_reference_t& fx_ref_b, - /*out*/ fx_reference_t& effective_fx_ref) + /*out*/ fx_reference_t& effective_fx_ref, + resolution_failure_info& resolution_failure) { // Determine which framework reference is higher to do the compat check. The various tracing messages // make more sense if they're always written with higher/lower versions ordered in particular way. @@ -331,7 +332,8 @@ StatusCode fx_resolver_t::reconcile_fx_references( if (!lower_fx_ref.is_compatible_with_higher_version(higher_fx_ref.get_fx_version_number())) { // Error condition - not compatible with the other reference - display_incompatible_framework_error(higher_fx_ref.get_fx_version(), lower_fx_ref); + resolution_failure.incompatible_higher = higher_fx_ref; + resolution_failure.incompatible_lower = lower_fx_ref; return StatusCode::FrameworkCompatFailure; } @@ -393,13 +395,11 @@ void fx_resolver_t::update_newest_references( // FrameworkMissingFailure - the resolution failed because the requested framework doesn't exist on disk. // InvalidConfigFile - reading of a runtime config for some of the processed frameworks has failed. StatusCode fx_resolver_t::read_framework( - const host_startup_info_t & host_info, - bool disable_multilevel_lookup, - const runtime_config_t::settings_t& override_settings, - const runtime_config_t & config, - const fx_reference_t * effective_parent_fx_ref, - fx_definition_vector_t & fx_definitions, - const pal::char_t* app_display_name) + const pal::string_t& dotnet_root, + const runtime_config_t& config, + const fx_reference_t* effective_parent_fx_ref, + fx_definition_vector_t& fx_definitions, + resolution_failure_info& resolution_failure) { // This reconciles duplicate references to minimize the number of resolve retries. update_newest_references(config); @@ -423,7 +423,7 @@ StatusCode fx_resolver_t::read_framework( // Reconcile the framework reference with the most up to date so far we have for the framework. // This does not read any physical framework folders yet. - rc = reconcile_fx_references(fx_ref, current_effective_fx_ref, new_effective_fx_ref); + rc = reconcile_fx_references(fx_ref, current_effective_fx_ref, new_effective_fx_ref, resolution_failure); if (rc != StatusCode::Success) return rc; @@ -438,17 +438,10 @@ StatusCode fx_resolver_t::read_framework( m_effective_fx_references[fx_name] = new_effective_fx_ref; // Resolve the effective framework reference against the existing physical framework folders - fx_definition_t* fx = resolve_framework_reference(new_effective_fx_ref, m_oldest_fx_references[fx_name].get_fx_version(), host_info.dotnet_root, disable_multilevel_lookup); + std::unique_ptr fx = resolve_framework_reference(new_effective_fx_ref, m_oldest_fx_references[fx_name].get_fx_version(), dotnet_root, m_disable_multilevel_lookup); if (fx == nullptr) { - trace::error( - INSTALL_OR_UPDATE_NET_ERROR_MESSAGE - _X("\n\n") - _X("App: %s\n") - _X("Architecture: %s"), - app_display_name != nullptr ? app_display_name : host_info.host_path.c_str(), - get_current_arch_name()); - display_missing_framework_error(fx_name, new_effective_fx_ref.get_fx_version(), pal::string_t(), host_info.dotnet_root, disable_multilevel_lookup); + resolution_failure.missing = std::move(new_effective_fx_ref); return StatusCode::FrameworkMissingFailure; } @@ -462,22 +455,21 @@ StatusCode fx_resolver_t::read_framework( // will change the effective reference from "2.1.0 LatestMajor" to "2.1.0 Minor" and restart the framework resolution process. // So during the second run we will resolve for example "2.2.0" which will be compatible with both framework references. - fx_definitions.push_back(std::unique_ptr(fx)); - // Recursively process the base frameworks pal::string_t config_file; pal::string_t dev_config_file; get_runtime_config_paths(fx->get_dir(), fx_name, &config_file, &dev_config_file); - fx->parse_runtime_config(config_file, dev_config_file, override_settings); + fx->parse_runtime_config(config_file, dev_config_file, m_override_settings); runtime_config_t new_config = fx->get_runtime_config(); if (!new_config.is_valid()) { - trace::error(_X("Invalid framework config.json [%s]"), new_config.get_path().c_str()); + resolution_failure.invalid_config = std::move(fx); return StatusCode::InvalidConfigFile; } - rc = read_framework(host_info, disable_multilevel_lookup, override_settings, new_config, &new_effective_fx_ref, fx_definitions, app_display_name); + fx_definitions.push_back(std::move(fx)); + rc = read_framework(dotnet_root, new_config, &new_effective_fx_ref, fx_definitions, resolution_failure); if (rc != StatusCode::Success) return rc; } @@ -501,15 +493,14 @@ StatusCode fx_resolver_t::read_framework( return StatusCode::Success; } -StatusCode fx_resolver_t::resolve_frameworks_for_app( - const host_startup_info_t & host_info, - bool disable_multilevel_lookup, +StatusCode fx_resolver_t::resolve_frameworks( + const pal::string_t& dotnet_root, const runtime_config_t::settings_t& override_settings, - const runtime_config_t & app_config, - fx_definition_vector_t & fx_definitions, - const pal::char_t* app_display_name) + const runtime_config_t& app_config, + fx_definition_vector_t& fx_definitions, + resolution_failure_info& resolution_failure) { - fx_resolver_t resolver; + fx_resolver_t resolver{ app_config.get_is_multilevel_lookup_disabled(), override_settings }; // Read the shared frameworks; retry is necessary when a framework is already resolved, but then a newer compatible version is processed. StatusCode rc = StatusCode::Success; @@ -517,7 +508,7 @@ StatusCode fx_resolver_t::resolve_frameworks_for_app( do { fx_definitions.resize(1); // Erase any existing frameworks for re-try - rc = resolver.read_framework(host_info, disable_multilevel_lookup, override_settings, app_config, /*effective_parent_fx_ref*/ nullptr, fx_definitions, app_display_name); + rc = resolver.read_framework(dotnet_root, app_config, /*effective_parent_fx_ref*/ nullptr, fx_definitions, resolution_failure); } while (rc == StatusCode::FrameworkCompatRetry && retry_count++ < Max_Framework_Resolve_Retries); assert(retry_count < Max_Framework_Resolve_Retries); @@ -530,6 +521,40 @@ StatusCode fx_resolver_t::resolve_frameworks_for_app( return rc; } +StatusCode fx_resolver_t::resolve_frameworks_for_app( + const pal::string_t& dotnet_root, + const runtime_config_t::settings_t& override_settings, + const runtime_config_t& app_config, + fx_definition_vector_t& fx_definitions, + const pal::char_t* app_display_name) +{ + resolution_failure_info resolution_failure; + StatusCode rc = resolve_frameworks(dotnet_root, override_settings, app_config, fx_definitions, resolution_failure); + switch (rc) + { + case StatusCode::FrameworkMissingFailure: + trace::error( + INSTALL_OR_UPDATE_NET_ERROR_MESSAGE + _X("\n\n") + _X("App: %s\n") + _X("Architecture: %s"), + app_display_name, + get_current_arch_name()); + display_missing_framework_error(resolution_failure.missing.get_fx_name(), resolution_failure.missing.get_fx_version(), pal::string_t(), dotnet_root, app_config.get_is_multilevel_lookup_disabled()); + break; + case StatusCode::FrameworkCompatFailure: + display_incompatible_framework_error(resolution_failure.incompatible_higher.get_fx_version(), resolution_failure.incompatible_lower); + break; + case StatusCode::InvalidConfigFile: + trace::error(_X("Invalid framework config.json [%s]"), resolution_failure.invalid_config->get_runtime_config().get_path().c_str()); + break; + default: + break; + } + + return rc; +} + bool fx_resolver_t::is_config_compatible_with_frameworks( const runtime_config_t &config, const std::unordered_map &existing_framework_versions_by_name) diff --git a/src/native/corehost/fxr/fx_resolver.h b/src/native/corehost/fxr/fx_resolver.h index 018294148f30..466decd846fc 100644 --- a/src/native/corehost/fxr/fx_resolver.h +++ b/src/native/corehost/fxr/fx_resolver.h @@ -9,41 +9,57 @@ #include "fx_definition.h" class runtime_config_t; -struct host_startup_info_t; class fx_resolver_t { public: + struct resolution_failure_info + { + fx_reference_t missing; + fx_reference_t incompatible_lower; + fx_reference_t incompatible_higher; + std::unique_ptr invalid_config; + }; + +public: + static StatusCode resolve_frameworks( + const pal::string_t& dotnet_root, + const runtime_config_t::settings_t& override_settings, + const runtime_config_t& app_config, + /*in_out*/ fx_definition_vector_t& fx_definitions, + resolution_failure_info& resolution_failure); + static StatusCode resolve_frameworks_for_app( - const host_startup_info_t& host_info, - bool disable_multilevel_lookup, + const pal::string_t& dotnet_root, const runtime_config_t::settings_t& override_settings, const runtime_config_t& app_config, - fx_definition_vector_t& fx_definitions, - const pal::char_t* app_display_name = nullptr); + /*in_out*/ fx_definition_vector_t& fx_definitions, + const pal::char_t* app_display_name); static bool is_config_compatible_with_frameworks( const runtime_config_t& config, const std::unordered_map &existing_framework_versions_by_name); private: - fx_resolver_t() = default; + fx_resolver_t(bool disable_multilevel_lookup, const runtime_config_t::settings_t& override_settings) + : m_disable_multilevel_lookup{disable_multilevel_lookup} + , m_override_settings{override_settings} + { } void update_newest_references( const runtime_config_t& config); StatusCode read_framework( - const host_startup_info_t& host_info, - bool disable_multilevel_lookup, - const runtime_config_t::settings_t& override_settings, + const pal::string_t& dotnet_root, const runtime_config_t& config, const fx_reference_t * effective_parent_fx_ref, fx_definition_vector_t& fx_definitions, - const pal::char_t* app_display_name); + resolution_failure_info& resolution_failure); static StatusCode reconcile_fx_references( const fx_reference_t& fx_ref_a, const fx_reference_t& fx_ref_b, - /*out*/ fx_reference_t& effective_fx_ref); + /*out*/ fx_reference_t& effective_fx_ref, + resolution_failure_info& resolution_failure); static void display_missing_framework_error( const pal::string_t& fx_name, @@ -79,6 +95,9 @@ class fx_resolver_t // to fill the "oldest reference" for each resolved framework in the end. It does not affect the behavior // of the algorithm. fx_name_to_fx_reference_map_t m_oldest_fx_references; + + bool m_disable_multilevel_lookup; + const runtime_config_t::settings_t& m_override_settings; }; #endif // __FX_RESOLVER_H__ diff --git a/src/native/corehost/fxr/hostfxr.cpp b/src/native/corehost/fxr/hostfxr.cpp index a386cbe37621..1ae8bcd8faf1 100644 --- a/src/native/corehost/fxr/hostfxr.cpp +++ b/src/native/corehost/fxr/hostfxr.cpp @@ -7,6 +7,7 @@ #include "utils.h" #include "fx_ver.h" #include "fx_muxer.h" +#include "fx_resolver.h" #include "error_codes.h" #include "runtime_config.h" #include "sdk_info.h" @@ -113,7 +114,7 @@ SHARED_API int HOSTFXR_CALLTYPE hostfxr_main(const int argc, const pal::char_t* // // String encoding: // Windows - UTF-16 (pal::char_t is 2 byte wchar_t) -// Unix - UTF-8 (pal::char_t is 1 byte char) +// Non-Windows - UTF-8 (pal::char_t is 1 byte char) // SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_resolve_sdk( const pal::char_t* exe_dir, @@ -233,7 +234,7 @@ typedef void (HOSTFXR_CALLTYPE *hostfxr_resolve_sdk2_result_fn)( // // String encoding: // Windows - UTF-16 (pal::char_t is 2 byte wchar_t) -// Unix - UTF-8 (pal::char_t is 1 byte char) +// Non-Windows - UTF-8 (pal::char_t is 1 byte char) // SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_resolve_sdk2( const pal::char_t* exe_dir, @@ -316,7 +317,7 @@ typedef void (HOSTFXR_CALLTYPE *hostfxr_get_available_sdks_result_fn)( // // String encoding: // Windows - UTF-16 (pal::char_t is 2 byte wchar_t) -// Unix - UTF-8 (pal::char_t is 1 byte char) +// Non-Windows - UTF-8 (pal::char_t is 1 byte char) // SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_get_available_sdks( const pal::char_t* exe_dir, @@ -491,7 +492,7 @@ SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_get_dotnet_environment_info( // // String encoding: // Windows - UTF-16 (pal::char_t is 2 byte wchar_t) -// Unix - UTF-8 (pal::char_t is 1 byte char) +// Non-Windows - UTF-8 (pal::char_t is 1 byte char) // SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_get_native_search_directories(const int argc, const pal::char_t* argv[], pal::char_t buffer[], int32_t buffer_size, int32_t* required_buffer_size) { @@ -571,6 +572,126 @@ namespace } } +SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_resolve_frameworks_for_runtime_config( + const char_t* runtime_config_path, + /*opt*/ const hostfxr_initialize_parameters* parameters, + /*opt*/ hostfxr_resolve_frameworks_result_fn callback, + /*opt*/ void* result_context) +{ + trace_hostfxr_entry_point(_X("hostfxr_resolve_frameworks_for_runtime_config")); + if (trace::is_enabled()) + { + trace::info(_X(" runtime_config_path=%s"), runtime_config_path == nullptr ? _X("") : runtime_config_path); + if (parameters == nullptr) + { + trace::info(_X(" parameters=")); + } + else + { + trace::info( + _X(" parameters={") + _X(" host_path=%s\n") + _X(" dotnet_root=%s\n") + _X(" }"), + parameters->host_path == nullptr ? _X("") : parameters->host_path, + parameters->dotnet_root == nullptr ? _X("") : parameters->dotnet_root); + } + } + + if (runtime_config_path == nullptr) + { + trace::error(_X("hostfxr_resolve_frameworks_for_runtime_config received an invalid argument: runtime_config_path should not be null.")); + return StatusCode::InvalidArgFailure; + } + + pal::string_t runtime_config = runtime_config_path; + if (runtime_config.empty() || !pal::realpath(&runtime_config)) + { + trace::error(_X("The specified runtimeconfig.json [%s] does not exist"), runtime_config.c_str()); + return StatusCode::InvalidConfigFile; + } + + host_startup_info_t host_info{}; + int rc = populate_startup_info(parameters, host_info); + if (rc != StatusCode::Success) + return rc; + + fx_definition_vector_t fx_definitions; + auto app = new fx_definition_t(); + fx_definitions.push_back(std::unique_ptr(app)); + + const runtime_config_t::settings_t override_settings; + app->parse_runtime_config(runtime_config, _X(""), override_settings); + + const runtime_config_t app_config = app->get_runtime_config(); + + // Resolve frameworks for framework-dependent apps. + // Self-contained apps assume the framework is next to the app, so we just treat it as success. + fx_resolver_t::resolution_failure_info failure_info; + rc = app_config.get_is_framework_dependent() + ? fx_resolver_t::resolve_frameworks(host_info.dotnet_root, override_settings, app_config, fx_definitions, failure_info) + : StatusCode::Success; + + if (callback) + { + std::vector resolved; + std::vector unresolved; + + pal::string_t config_dir; + if (app_config.get_is_framework_dependent()) + { + for (const auto& fx : fx_definitions) + { + // Skip the app itself + if (fx.get() == app) + continue; + + resolved.push_back({ sizeof(hostfxr_framework_result), fx->get_name().c_str(), fx->get_requested_version().c_str(), fx->get_found_version().c_str(), fx->get_dir().c_str() }); + } + + switch ((StatusCode)rc) + { + case StatusCode::FrameworkMissingFailure: + unresolved.push_back({ sizeof(hostfxr_framework_result), failure_info.missing.get_fx_name().c_str(), failure_info.missing.get_fx_version().c_str(), nullptr, nullptr }); + break; + case StatusCode::FrameworkCompatFailure: + unresolved.push_back({ sizeof(hostfxr_framework_result), failure_info.incompatible_lower.get_fx_name().c_str(), failure_info.incompatible_lower.get_fx_version().c_str(), nullptr, nullptr }); + unresolved.push_back({ sizeof(hostfxr_framework_result), failure_info.incompatible_higher.get_fx_name().c_str(), failure_info.incompatible_higher.get_fx_version().c_str(), nullptr, nullptr }); + break; + case StatusCode::InvalidConfigFile: + assert(failure_info.invalid_config != nullptr); + unresolved.push_back({ sizeof(hostfxr_framework_result), failure_info.invalid_config->get_name().c_str(), failure_info.invalid_config->get_requested_version().c_str(), failure_info.invalid_config->get_found_version().c_str(), failure_info.invalid_config->get_dir().c_str() }); + break; + default: + break; + } + } + else + { + // For self-contained apps, add all the included frameworks as resolved frameworks assumed to be next to the config + config_dir = get_directory(runtime_config); + remove_trailing_dir_separator(&config_dir); + for (const fx_reference_t& fx : app_config.get_included_frameworks()) + { + resolved.push_back({ sizeof(hostfxr_framework_result), fx.get_fx_name().c_str(), fx.get_fx_version().c_str(), fx.get_fx_version().c_str(), config_dir.c_str() }); + } + } + + const hostfxr_resolve_frameworks_result result + { + sizeof(result), + resolved.size(), + resolved.empty() ? nullptr : resolved.data(), + unresolved.size(), + unresolved.empty() ? nullptr : unresolved.data() + }; + + callback(&result, result_context); + } + + return rc; +} + SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_initialize_for_dotnet_command_line( int argc, const pal::char_t *argv[], diff --git a/src/native/corehost/fxr/standalone/hostfxr.def b/src/native/corehost/fxr/standalone/hostfxr.def index 3488a4f21f27..6ce3efc37371 100644 --- a/src/native/corehost/fxr/standalone/hostfxr.def +++ b/src/native/corehost/fxr/standalone/hostfxr.def @@ -13,6 +13,7 @@ EXPORTS hostfxr_set_error_writer hostfxr_initialize_for_dotnet_command_line hostfxr_initialize_for_runtime_config + hostfxr_resolve_frameworks_for_runtime_config hostfxr_run_app hostfxr_get_runtime_delegate hostfxr_get_runtime_property_value diff --git a/src/native/corehost/fxr/standalone/hostfxr_unixexports.src b/src/native/corehost/fxr/standalone/hostfxr_unixexports.src index 1780b0157eb3..c5f9425e69c3 100644 --- a/src/native/corehost/fxr/standalone/hostfxr_unixexports.src +++ b/src/native/corehost/fxr/standalone/hostfxr_unixexports.src @@ -12,6 +12,7 @@ hostfxr_get_native_search_directories hostfxr_set_error_writer hostfxr_initialize_for_dotnet_command_line hostfxr_initialize_for_runtime_config +hostfxr_resolve_frameworks_for_runtime_config hostfxr_run_app hostfxr_get_runtime_delegate hostfxr_get_runtime_property_value diff --git a/src/native/corehost/hostfxr.h b/src/native/corehost/hostfxr.h index a19636b9e3fd..0c316a59b115 100644 --- a/src/native/corehost/hostfxr.h +++ b/src/native/corehost/hostfxr.h @@ -355,7 +355,7 @@ struct hostfxr_dotnet_environment_info // // String encoding: // Windows - UTF-16 (pal::char_t is 2 byte wchar_t) -// Unix - UTF-8 (pal::char_t is 1 byte char) +// Non-Windows - UTF-8 (pal::char_t is 1 byte char) // typedef int32_t(HOSTFXR_CALLTYPE* hostfxr_get_dotnet_environment_info_fn)( const char_t* dotnet_root, @@ -363,4 +363,56 @@ typedef int32_t(HOSTFXR_CALLTYPE* hostfxr_get_dotnet_environment_info_fn)( hostfxr_get_dotnet_environment_info_result_fn result, void* result_context); +struct hostfxr_framework_result +{ + size_t size; + const char_t* name; + const char_t* requested_version; + const char_t* resolved_version; + const char_t* resolved_path; +}; + +struct hostfxr_resolve_frameworks_result +{ + size_t size; + + size_t resolved_count; + const struct hostfxr_framework_result* resolved_frameworks; + + size_t unresolved_count; + const struct hostfxr_framework_result* unresolved_frameworks; +}; + +typedef void (HOSTFXR_CALLTYPE* hostfxr_resolve_frameworks_result_fn)( + const hostfxr_resolve_frameworks_result* result, + void* result_context); + +// +// Resolves frameworks for a runtime config +// +// Parameters: +// runtime_config_path +// Path to the .runtimeconfig.json file +// parameters +// Optional. Additional parameters for initialization. +// If null or dotnet_root is null, the root corresponding to the running hostfx is used. +// callback +// Optional. Result callback invoked with result of the resolution. +// Structs and their elements are valid for the duration of the call. +// result_context +// Optional. Additional context passed to the result callback. +// +// Return value: +// 0 on success, otherwise failure. +// +// String encoding: +// Windows - UTF-16 (pal::char_t is 2-byte wchar_t) +// Non-Windows - UTF-8 (pal::char_t is 1-byte char) +// +typedef int32_t(HOSTFXR_CALLTYPE* hostfxr_resolve_frameworks_for_runtime_config_fn)( + const char_t* runtime_config_path, + /*opt*/ const hostfxr_initialize_parameters* parameters, + /*opt*/ hostfxr_resolve_frameworks_result_fn callback, + /*opt*/ void* result_context); + #endif //__HOSTFXR_H__ diff --git a/src/native/corehost/hostmisc/pal.unix.cpp b/src/native/corehost/hostmisc/pal.unix.cpp index 34520aefd736..bdd8796c5d8e 100644 --- a/src/native/corehost/hostmisc/pal.unix.cpp +++ b/src/native/corehost/hostmisc/pal.unix.cpp @@ -591,6 +591,22 @@ bool pal::get_default_installation_dir_for_arch(pal::architecture arch, pal::str append_path(recv, get_arch_name(arch)); } #endif +#elif defined(TARGET_FREEBSD) + int mib[2]; + char buf[PATH_MAX]; + size_t len = PATH_MAX; + + mib[0] = CTL_USER; + mib[1] = USER_LOCALBASE; + if (::sysctl(mib, 2, buf, &len, NULL, 0) == 0) + { + recv->assign(buf); + recv->append(_X("/share/dotnet")); + } + else + { + recv->assign(_X("/usr/local/share/dotnet")); + } #else recv->assign(_X("/usr/share/dotnet")); #endif diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index d4248e71fe55..b359102ee0d3 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -46,6 +46,13 @@ eventpipe_collect_tracing_command_try_parse_rundown_requested ( uint32_t *buffer_len, bool *rundown_requested); +static +bool +eventpipe_collect_tracing_command_try_parse_rundown_keyword ( + uint8_t **buffer, + uint32_t *buffer_len, + uint64_t *rundown_keyword); + static bool eventpipe_collect_tracing_command_try_parse_stackwalk_requested ( @@ -78,6 +85,12 @@ eventpipe_collect_tracing3_command_try_parse_payload ( uint8_t *buffer, uint16_t buffer_len); +static +uint8_t * +eventpipe_collect_tracing4_command_try_parse_payload ( + uint8_t *buffer, + uint16_t buffer_len); + static bool eventpipe_protocol_helper_stop_tracing ( @@ -150,6 +163,21 @@ eventpipe_collect_tracing_command_try_parse_rundown_requested ( return ds_ipc_message_try_parse_bool (buffer, buffer_len, rundown_requested); } +static +inline +bool +eventpipe_collect_tracing_command_try_parse_rundown_keyword ( + uint8_t **buffer, + uint32_t *buffer_len, + uint64_t *rundown_keyword) +{ + EP_ASSERT (buffer != NULL); + EP_ASSERT (buffer_len != NULL); + EP_ASSERT (rundown_keyword != NULL); + + return ds_ipc_message_try_parse_uint64_t (buffer, buffer_len, rundown_keyword); +} + static inline bool @@ -299,6 +327,7 @@ eventpipe_collect_tracing_command_try_parse_payload ( ep_raise_error (); instance->rundown_requested = true; instance->stackwalk_requested = true; + instance->rundown_keyword = ep_default_rundown_keyword; ep_on_exit: return (uint8_t *)instance; @@ -330,6 +359,9 @@ eventpipe_collect_tracing2_command_try_parse_payload ( !eventpipe_collect_tracing_command_try_parse_rundown_requested (&buffer_cursor, &buffer_cursor_len, &instance->rundown_requested) || !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs)) ep_raise_error (); + + instance->rundown_keyword = instance->rundown_requested ? ep_default_rundown_keyword : 0; + instance->stackwalk_requested = true; ep_on_exit: @@ -364,6 +396,42 @@ eventpipe_collect_tracing3_command_try_parse_payload ( !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs)) ep_raise_error (); + instance->rundown_keyword = instance->rundown_requested ? ep_default_rundown_keyword : 0; + +ep_on_exit: + return (uint8_t *)instance; + +ep_on_error: + ds_eventpipe_collect_tracing_command_payload_free (instance); + instance = NULL; + ep_exit_error_handler (); +} + +static +uint8_t * +eventpipe_collect_tracing4_command_try_parse_payload ( + uint8_t *buffer, + uint16_t buffer_len) +{ + EP_ASSERT (buffer != NULL); + + uint8_t * buffer_cursor = buffer; + uint32_t buffer_cursor_len = buffer_len; + + EventPipeCollectTracingCommandPayload *instance = ds_eventpipe_collect_tracing_command_payload_alloc (); + ep_raise_error_if_nok (instance != NULL); + + instance->incoming_buffer = buffer; + + if (!eventpipe_collect_tracing_command_try_parse_circular_buffer_size (&buffer_cursor, &buffer_cursor_len, &instance->circular_buffer_size_in_mb ) || + !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || + !eventpipe_collect_tracing_command_try_parse_rundown_keyword (&buffer_cursor, &buffer_cursor_len, &instance->rundown_keyword) || + !eventpipe_collect_tracing_command_try_parse_stackwalk_requested (&buffer_cursor, &buffer_cursor_len, &instance->stackwalk_requested) || + !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs)) + ep_raise_error (); + + instance->rundown_requested = instance->rundown_keyword != 0; + ep_on_exit: return (uint8_t *)instance; @@ -471,7 +539,7 @@ eventpipe_protocol_helper_collect_tracing ( dn_vector_size (payload->provider_configs), EP_SESSION_TYPE_IPCSTREAM, payload->serialization_format, - payload->rundown_requested, + payload->rundown_keyword, payload->stackwalk_requested, ds_ipc_stream_get_stream_ref (stream), NULL, @@ -544,6 +612,10 @@ ds_eventpipe_protocol_helper_handle_ipc_message ( payload = (EventPipeCollectTracingCommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing3_command_try_parse_payload); result = eventpipe_protocol_helper_collect_tracing (payload, stream); break; + case EP_COMMANDID_COLLECT_TRACING_4: + payload = (EventPipeCollectTracingCommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing4_command_try_parse_payload); + result = eventpipe_protocol_helper_collect_tracing (payload, stream); + break; case EP_COMMANDID_STOP_TRACING: result = eventpipe_protocol_helper_stop_tracing (message, stream); break; diff --git a/src/native/eventpipe/ds-eventpipe-protocol.h b/src/native/eventpipe/ds-eventpipe-protocol.h index 7a3c4ebd41ff..14496068a109 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.h +++ b/src/native/eventpipe/ds-eventpipe-protocol.h @@ -20,6 +20,7 @@ // Command = 0x0202 // Command = 0x0203 // Command = 0x0204 +// Command = 0x0205 #if defined(DS_INLINE_GETTER_SETTER) || defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER) struct _EventPipeCollectTracingCommandPayload { #else @@ -40,6 +41,7 @@ struct _EventPipeCollectTracingCommandPayload_Internal { EventPipeSerializationFormat serialization_format; bool rundown_requested; bool stackwalk_requested; + uint64_t rundown_keyword; }; #if !defined(DS_INLINE_GETTER_SETTER) && !defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER) diff --git a/src/native/eventpipe/ds-ipc-pal-namedpipe.c b/src/native/eventpipe/ds-ipc-pal-namedpipe.c index 01a12275a421..b7cfd0528fa4 100644 --- a/src/native/eventpipe/ds-ipc-pal-namedpipe.c +++ b/src/native/eventpipe/ds-ipc-pal-namedpipe.c @@ -173,6 +173,25 @@ ds_ipc_free (DiagnosticsIpc *ipc) ep_rt_object_free (ipc); } +void +ds_ipc_reset (DiagnosticsIpc *ipc) +{ + if (!ipc) + return; + + if (ipc->pipe != INVALID_HANDLE_VALUE) { + CloseHandle (ipc->pipe); + ipc->pipe = INVALID_HANDLE_VALUE; + } + + if (ipc->overlap.hEvent != INVALID_HANDLE_VALUE) { + CloseHandle (ipc->overlap.hEvent); + ipc->overlap.hEvent = INVALID_HANDLE_VALUE; + } + + ipc->is_listening = false; +} + int32_t ds_ipc_poll ( DiagnosticsIpcPollHandle *poll_handles_data, @@ -192,6 +211,10 @@ ds_ipc_poll ( // SERVER EP_ASSERT (poll_handles_data [i].ipc->mode == DS_IPC_CONNECTION_MODE_LISTEN); handles [i] = poll_handles_data [i].ipc->overlap.hEvent; + if (handles [i] == INVALID_HANDLE_VALUE) { + // Invalid handle, wait will fail. Signal error + poll_handles_data [i].events = DS_IPC_POLL_EVENTS_ERR; + } } else { // CLIENT bool success = true; diff --git a/src/native/eventpipe/ds-ipc-pal-socket.c b/src/native/eventpipe/ds-ipc-pal-socket.c index d93233c506b7..7ad0b0f5d485 100644 --- a/src/native/eventpipe/ds-ipc-pal-socket.c +++ b/src/native/eventpipe/ds-ipc-pal-socket.c @@ -1064,6 +1064,11 @@ ds_ipc_free (DiagnosticsIpc *ipc) ep_rt_object_free (ipc); } +void +ds_ipc_reset (DiagnosticsIpc *ipc) +{ +} + int32_t ds_ipc_poll ( DiagnosticsIpcPollHandle *poll_handles_data, diff --git a/src/native/eventpipe/ds-ipc-pal.h b/src/native/eventpipe/ds-ipc-pal.h index 98e0fba180e6..8e246ed67195 100644 --- a/src/native/eventpipe/ds-ipc-pal.h +++ b/src/native/eventpipe/ds-ipc-pal.h @@ -35,6 +35,9 @@ ds_ipc_alloc ( void ds_ipc_free (DiagnosticsIpc *ipc); +void +ds_ipc_reset (DiagnosticsIpc *ipc); + // Poll // Parameters: // - IpcPollHandle * poll_handles_data: Array of IpcPollHandles to poll diff --git a/src/native/eventpipe/ds-ipc.c b/src/native/eventpipe/ds-ipc.c index 1256e3b00333..7d3c56ee28d4 100644 --- a/src/native/eventpipe/ds-ipc.c +++ b/src/native/eventpipe/ds-ipc.c @@ -431,6 +431,7 @@ ds_ipc_stream_factory_get_next_available_stream (ds_ipc_error_callback_func call DS_LOG_INFO_2 ("ds_ipc_stream_factory_get_next_available_stream - NON :: Poll attempt: %d, connection %d had no events.", poll_attempts, connection_id); break; default: + ds_port_reset_vcall ((DiagnosticsPort *)ipc_poll_handle.user_data, callback); DS_LOG_INFO_2 ("ds_ipc_stream_factory_get_next_available_stream - UNK :: Poll attempt: %d, connection %d had invalid PollEvent.", poll_attempts, connection_id); saw_error = true; break; @@ -441,6 +442,12 @@ ds_ipc_stream_factory_get_next_available_stream (ds_ipc_error_callback_func call } if (!stream && saw_error) { + // Some errors can cause the poll to return instantly, we want to delay if we see an error to avoid + // runaway CPU usage. + if (poll_timeout_ms == DS_IPC_TIMEOUT_INFINITE) + poll_timeout_ms = DS_IPC_POLL_TIMEOUT_MAX_MS; + DS_LOG_DEBUG_1 ("ds_ipc_stream_factory_get_next_available_stream - Saw error, sleeping using timeout: %dms.", poll_timeout_ms); + ep_rt_thread_sleep ((uint64_t)poll_timeout_ms * NUM_NANOSECONDS_IN_1_MS); _ds_current_port = NULL; ep_raise_error (); } @@ -839,7 +846,9 @@ listen_port_reset ( ds_ipc_error_callback_func callback) { EP_ASSERT (object != NULL); - return; + DiagnosticsListenPort *listen_port = (DiagnosticsListenPort *)object; + ds_ipc_reset (listen_port->port.ipc); + ds_ipc_listen (listen_port->port.ipc, callback); } static DiagnosticsPortVtable listen_port_vtable = { diff --git a/src/native/eventpipe/ds-types.h b/src/native/eventpipe/ds-types.h index 16d57f4cb7e8..a7596da6052a 100644 --- a/src/native/eventpipe/ds-types.h +++ b/src/native/eventpipe/ds-types.h @@ -104,6 +104,7 @@ typedef enum { EP_COMMANDID_COLLECT_TRACING = 0x02, EP_COMMANDID_COLLECT_TRACING_2 = 0x03, EP_COMMANDID_COLLECT_TRACING_3 = 0x04, + EP_COMMANDID_COLLECT_TRACING_4 = 0x05, // future } EventPipeCommandId; diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index a91dd108c2e9..c79d3972cd55 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -133,7 +133,7 @@ ep_session_alloc ( IpcStream *stream, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, bool stackwalk_requested, uint32_t circular_buffer_size_in_mb, const EventPipeProviderConfiguration *providers, @@ -164,7 +164,7 @@ ep_session_alloc ( instance->rundown_enabled = 0; instance->session_type = session_type; instance->format = format; - instance->rundown_requested = rundown_requested; + instance->rundown_keyword = rundown_keyword; instance->synchronous_callback = sync_callback; instance->callback_additional_data = callback_additional_data; @@ -317,17 +317,7 @@ ep_session_enable_rundown (EventPipeSession *session) ep_requires_lock_held (); bool result = false; - - //! This is CoreCLR specific keywords for native ETW events (ending up in event pipe). - //! The keywords below seems to correspond to: - //! GCKeyword (0x00000001) - //! LoaderKeyword (0x00000008) - //! JitKeyword (0x00000010) - //! NgenKeyword (0x00000020) - //! unused_keyword (0x00000100) - //! JittedMethodILToNativeMapKeyword (0x00020000) - //! ThreadTransferKeyword (0x80000000) - const uint64_t keywords = 0x80020139; + const uint64_t keywords = ep_session_get_rundown_keyword (session); const EventPipeEventLevel verbose_logging_level = EP_EVENT_LEVEL_VERBOSE; EventPipeProviderConfiguration rundown_provider; diff --git a/src/native/eventpipe/ep-session.h b/src/native/eventpipe/ep-session.h index 944b38c8e5d3..646c4ab566c0 100644 --- a/src/native/eventpipe/ep-session.h +++ b/src/native/eventpipe/ep-session.h @@ -53,7 +53,7 @@ struct _EventPipeSession_Internal { // irrelevant. EventPipeSerializationFormat format; // For determininig if a particular session needs rundown events. - bool rundown_requested; + uint64_t rundown_keyword; // Note - access to this field is NOT synchronized // This functionality is a workaround because we couldn't safely enable/disable the session where we wanted to due to lock-leveling. // we expect to remove it in the future once that limitation is resolved other scenarios are discouraged from using this given that @@ -79,7 +79,7 @@ EP_DEFINE_GETTER(EventPipeSession *, session, uint32_t, index) EP_DEFINE_GETTER(EventPipeSession *, session, EventPipeSessionProviderList *, providers) EP_DEFINE_GETTER(EventPipeSession *, session, EventPipeBufferManager *, buffer_manager) EP_DEFINE_GETTER_REF(EventPipeSession *, session, volatile uint32_t *, rundown_enabled) -EP_DEFINE_GETTER(EventPipeSession *, session, bool, rundown_requested) +EP_DEFINE_GETTER(EventPipeSession *, session, uint64_t, rundown_keyword) EP_DEFINE_GETTER(EventPipeSession *, session, ep_timestamp_t, session_start_time) EP_DEFINE_GETTER(EventPipeSession *, session, ep_timestamp_t, session_start_timestamp) EP_DEFINE_GETTER(EventPipeSession *, session, EventPipeFile *, file) @@ -92,7 +92,7 @@ ep_session_alloc ( IpcStream *stream, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, bool stackwalk_requested, uint32_t circular_buffer_size_in_mb, const EventPipeProviderConfiguration *providers, diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index 7313fcb856dc..b65326a16bcf 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -15,6 +15,17 @@ #include "ep-session.h" #include "ep-sample-profiler.h" +//! This is CoreCLR specific keywords for native ETW events (ending up in event pipe). +//! The keywords below seems to correspond to: +//! GCKeyword (0x00000001) +//! LoaderKeyword (0x00000008) +//! JitKeyword (0x00000010) +//! NgenKeyword (0x00000020) +//! unused_keyword (0x00000100) +//! JittedMethodILToNativeMapKeyword (0x00020000) +//! ThreadTransferKeyword (0x80000000) +uint64_t ep_default_rundown_keyword = 0x80020139; + static bool _ep_can_start_threads = false; static dn_vector_t *_ep_deferred_enable_session_ids = NULL; @@ -494,7 +505,7 @@ enable ( options->stream, options->session_type, options->format, - options->rundown_requested, + options->rundown_keyword, options->stackwalk_requested, options->circular_buffer_size_in_mb, options->providers, @@ -589,7 +600,7 @@ disable_holding_lock ( ep_session_disable (session); // WriteAllBuffersToFile, and remove providers. // Do rundown before fully stopping the session unless rundown wasn't requested - if (ep_session_get_rundown_requested (session) && _ep_can_start_threads) { + if ((ep_session_get_rundown_keyword (session) != 0) && _ep_can_start_threads) { ep_session_enable_rundown (session); // Set Rundown provider. EventPipeThread *const thread = ep_thread_get_or_create (); if (thread != NULL) { @@ -908,7 +919,7 @@ enable_default_session_via_env_variables (void) ep_config, ep_rt_config_value_get_output_streaming () ? EP_SESSION_TYPE_FILESTREAM : EP_SESSION_TYPE_FILE, EP_SERIALIZATION_FORMAT_NETTRACE_V4, - true, + ep_default_rundown_keyword, NULL, NULL, NULL); @@ -959,7 +970,7 @@ ep_enable ( uint32_t providers_len, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, IpcStream *stream, EventPipeSessionSynchronousCallback sync_callback, void *callback_additional_data) @@ -975,7 +986,7 @@ ep_enable ( providers_len, session_type, format, - rundown_requested, + rundown_keyword, true, // stackwalk_requested stream, sync_callback, @@ -995,7 +1006,7 @@ ep_enable_2 ( const ep_char8_t *providers_config, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, IpcStream *stream, EventPipeSessionSynchronousCallback sync_callback, void *callback_additional_data) @@ -1073,7 +1084,7 @@ ep_enable_2 ( providers_len, session_type, format, - rundown_requested, + rundown_keyword, stream, sync_callback, callback_additional_data); @@ -1105,7 +1116,7 @@ ep_session_options_init ( uint32_t providers_len, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, bool stackwalk_requested, IpcStream* stream, EventPipeSessionSynchronousCallback sync_callback, @@ -1119,7 +1130,7 @@ ep_session_options_init ( options->providers_len = providers_len; options->session_type = session_type; options->format = format; - options->rundown_requested = rundown_requested; + options->rundown_keyword = rundown_keyword; options->stackwalk_requested = stackwalk_requested; options->stream = stream; options->sync_callback = sync_callback; diff --git a/src/native/eventpipe/ep.h b/src/native/eventpipe/ep.h index b7b31d04cdb0..fd8c019121c1 100644 --- a/src/native/eventpipe/ep.h +++ b/src/native/eventpipe/ep.h @@ -13,6 +13,12 @@ extern volatile EventPipeSession *_ep_sessions [EP_MAX_NUMBER_OF_SESSIONS]; extern volatile uint32_t _ep_number_of_sessions; extern volatile uint64_t _ep_allow_write; +/* + * Global constants + */ + +extern uint64_t ep_default_rundown_keyword; + /* * Globals and volatile access functions. */ @@ -119,7 +125,7 @@ typedef struct EventPipeSessionOptions { uint32_t providers_len; EventPipeSessionType session_type; EventPipeSerializationFormat format; - bool rundown_requested; + uint64_t rundown_keyword; bool stackwalk_requested; } EventPipeSessionOptions; @@ -132,7 +138,7 @@ ep_session_options_init ( uint32_t providers_len, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, bool stackwalk_requested, IpcStream *stream, EventPipeSessionSynchronousCallback sync_callback, @@ -164,7 +170,7 @@ ep_enable ( uint32_t providers_len, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, IpcStream *stream, EventPipeSessionSynchronousCallback sync_callback, void *callback_additional_data); @@ -176,7 +182,7 @@ ep_enable_2 ( const ep_char8_t *providers, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, IpcStream *stream, EventPipeSessionSynchronousCallback sync_callback, void *callback_additional_data); diff --git a/src/native/libs/CMakeLists.txt b/src/native/libs/CMakeLists.txt index ded638d85418..51856e0e1dd0 100644 --- a/src/native/libs/CMakeLists.txt +++ b/src/native/libs/CMakeLists.txt @@ -111,7 +111,7 @@ if (CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI) add_subdirectory(System.IO.Ports.Native) endif () - if (CMAKE_C_COMPILER_ID STREQUAL Clang) + if (CMAKE_C_COMPILER_ID MATCHES "Clang") add_compile_options(-Weverything) add_compile_options(-Wno-format-nonliteral) add_compile_options(-Wno-disabled-macro-expansion) @@ -120,6 +120,8 @@ if (CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI) add_compile_options(-Wno-cast-align) add_compile_options(-Wno-typedef-redefinition) add_compile_options(-Wno-c11-extensions) + add_compile_options(-Wno-pre-c11-compat) # fixes build on Debian + add_compile_options(-Wno-unknown-warning-option) # unknown warning option '-Wno-pre-c11-compat' add_compile_options(-Wno-thread-safety-analysis) add_compile_options(-Wno-strict-prototypes) # TODO-LLVM: fix the reasons for this warning failure diff --git a/src/native/libs/Common/pal_config.h.in b/src/native/libs/Common/pal_config.h.in index c4843bf8712d..22b1d5713acf 100644 --- a/src/native/libs/Common/pal_config.h.in +++ b/src/native/libs/Common/pal_config.h.in @@ -100,6 +100,7 @@ #cmakedefine01 HAVE_IOS_NET_IFMEDIA_H #cmakedefine01 HAVE_LINUX_RTNETLINK_H #cmakedefine01 HAVE_LINUX_CAN_H +#cmakedefine01 HAVE_LINUX_ERRQUEUE_H #cmakedefine01 HAVE_GETDOMAINNAME_SIZET #cmakedefine01 HAVE_INOTIFY #cmakedefine01 HAVE_CLOCK_MONOTONIC diff --git a/src/native/libs/Common/pal_error_common.h b/src/native/libs/Common/pal_error_common.h index e9de2b793e40..7541132da7b1 100644 --- a/src/native/libs/Common/pal_error_common.h +++ b/src/native/libs/Common/pal_error_common.h @@ -336,6 +336,8 @@ inline static int32_t ConvertErrorPlatformToPal(int32_t platformErrno) case EWOULDBLOCK: return Error_EWOULDBLOCK; #endif + default: + break; // fall through to error } return Error_ENONSTANDARD; @@ -528,6 +530,8 @@ inline static int32_t ConvertErrorPalToPlatform(int32_t error) case Error_ENONSTANDARD: break; // fall through to assert + default: + break; // fall through to assert } // We should not use this function to round-trip platform -> pal diff --git a/src/native/libs/System.Globalization.Native/pal_calendarData.m b/src/native/libs/System.Globalization.Native/pal_calendarData.m index 9520e1764675..41bba41d20f1 100644 --- a/src/native/libs/System.Globalization.Native/pal_calendarData.m +++ b/src/native/libs/System.Globalization.Native/pal_calendarData.m @@ -87,7 +87,7 @@ static CalendarId GetCalendarId(const char* calendarName) { @autoreleasepool { - NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSString *locName = [[NSString alloc] initWithUTF8String:localeName]; NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; if (dataType == CalendarData_MonthDay) @@ -162,8 +162,8 @@ static CalendarId GetCalendarId(const char* calendarName) assert(false); return NULL; } - - NSString *arrayToString = [[result valueForKey:@"description"] componentsJoinedByString:@"||"]; + NSArray *descriptionsArray = [result valueForKey:@"description"]; + NSString *arrayToString = [descriptionsArray componentsJoinedByString:@"||"]; return arrayToString ? strdup([arrayToString UTF8String]) : NULL; } } @@ -211,7 +211,7 @@ int32_t GlobalizationNative_GetJapaneseEraStartDateNative(int32_t era, int32_t* for (int month = 0; month <= 12; month++) { NSDateComponents *eraComponents = [japaneseCalendar components:NSCalendarUnitEra fromDate:date]; - currentEra = [eraComponents era]; + currentEra = (int32_t)[eraComponents era]; if (currentEra == era) { for (int day = 0; day < 31; day++) @@ -220,7 +220,7 @@ int32_t GlobalizationNative_GetJapaneseEraStartDateNative(int32_t era, int32_t* startDateComponents.day = startDateComponents.day - 1; date = [japaneseCalendar dateFromComponents:startDateComponents]; eraComponents = [japaneseCalendar components:NSCalendarUnitEra fromDate:date]; - currentEra = [eraComponents era]; + currentEra = (int32_t)[eraComponents era]; if (currentEra != era) { // add back 1 day to get back into the specified Era @@ -228,9 +228,9 @@ int32_t GlobalizationNative_GetJapaneseEraStartDateNative(int32_t era, int32_t* date = [japaneseCalendar dateFromComponents:startDateComponents]; NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; NSDateComponents *components = [gregorianCalendar components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date]; - *startYear = [components year]; - *startMonth = [components month]; - *startDay = [components day]; + *startYear = (int32_t)[components year]; + *startMonth = (int32_t)[components month]; + *startDay = (int32_t)[components day]; return 1; } } @@ -239,7 +239,7 @@ int32_t GlobalizationNative_GetJapaneseEraStartDateNative(int32_t era, int32_t* startDateComponents.month = startDateComponents.month + 1; date = [japaneseCalendar dateFromComponents:startDateComponents]; eraComponents = [japaneseCalendar components:NSCalendarUnitEra fromDate:date]; - currentEra = [eraComponents era]; + currentEra = (int32_t)[eraComponents era]; } return 0; @@ -267,17 +267,18 @@ int32_t GlobalizationNative_GetCalendarsNative(const char* localeName, CalendarI NSCalendarIdentifierRepublicOfChina, ]; - NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSString *locName = [[NSString alloc] initWithUTF8String:localeName]; NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; NSString *defaultCalendarIdentifier = [currentLocale calendarIdentifier]; - int32_t calendarCount = MIN(calendarIdentifiers.count, calendarsCapacity); + int32_t calendarCount = (int32_t)calendarIdentifiers.count < calendarsCapacity ? (int32_t)calendarIdentifiers.count : calendarsCapacity; int32_t calendarIndex = 0; CalendarId defaultCalendarId = GetCalendarId([defaultCalendarIdentifier UTF8String]); // If the default calendar is not supported, return the Gregorian calendar as the default. calendars[calendarIndex++] = defaultCalendarId == UNINITIALIZED_VALUE ? GREGORIAN : defaultCalendarId; for (int i = 0; i < calendarCount; i++) { - CalendarId calendarId = GetCalendarId([calendarIdentifiers[i] UTF8String]); + NSCalendarIdentifier calendarIdentifier = calendarIdentifiers[(NSUInteger)i]; + CalendarId calendarId = GetCalendarId([calendarIdentifier UTF8String]); if (calendarId == UNINITIALIZED_VALUE || calendarId == defaultCalendarId) continue; calendars[calendarIndex++] = calendarId; diff --git a/src/native/libs/System.Globalization.Native/pal_casing.m b/src/native/libs/System.Globalization.Native/pal_casing.m index ba5c853c0b4c..8b27a56827ca 100644 --- a/src/native/libs/System.Globalization.Native/pal_casing.m +++ b/src/native/libs/System.Globalization.Native/pal_casing.m @@ -78,7 +78,7 @@ int32_t GlobalizationNative_ChangeCaseNative(const uint16_t* localeName, int32_t } else { - NSString *locName = [NSString stringWithCharacters: localeName length: lNameLength]; + NSString *locName = [NSString stringWithCharacters: localeName length: (NSUInteger)lNameLength]; currentLocale = [NSLocale localeWithLocaleIdentifier:locName]; } @@ -89,14 +89,14 @@ int32_t GlobalizationNative_ChangeCaseNative(const uint16_t* localeName, int32_t int32_t startIndex = srcIdx; NEXTOFFSET(lpSrc, srcIdx, cwSrcLength); int32_t srcLength = srcIdx - startIndex; - NSString *src = [NSString stringWithCharacters: lpSrc + startIndex length: srcLength]; + NSString *src = [NSString stringWithCharacters: lpSrc + startIndex length: (NSUInteger)srcLength]; NSString *dst = bToUpper ? [src uppercaseStringWithLocale:currentLocale] : [src lowercaseStringWithLocale:currentLocale]; int32_t index = 0; // iterate over all code points of a surrogate pair character while (index < srcLength) { // the dst.length > srcLength is to prevent code point expansions - dstCodepoint = dst.length > srcLength ? [src characterAtIndex: index] : [dst characterAtIndex: index]; + dstCodepoint = (int32_t)dst.length > srcLength ? [src characterAtIndex: (NSUInteger)index] : [dst characterAtIndex: (NSUInteger)index]; Append(lpDst, dstIdx, cwDstLength, dstCodepoint, isError); index++; } @@ -130,14 +130,14 @@ int32_t GlobalizationNative_ChangeCaseInvariantNative(const uint16_t* lpSrc, int int32_t startIndex = srcIdx; NEXTOFFSET(lpSrc, srcIdx, cwSrcLength); int32_t srcLength = srcIdx - startIndex; - NSString *src = [NSString stringWithCharacters: lpSrc + startIndex length: srcLength]; + NSString *src = [NSString stringWithCharacters: lpSrc + startIndex length: (NSUInteger)srcLength]; NSString *dst = bToUpper ? src.uppercaseString : src.lowercaseString; int32_t index = 0; // iterate over all code points of a surrogate pair character while (index < srcLength) { // the dst.length > srcLength is to prevent code point expansions - dstCodepoint = dst.length > srcLength ? [src characterAtIndex: index] : [dst characterAtIndex: index]; + dstCodepoint = (int32_t)dst.length > srcLength ? [src characterAtIndex: (NSUInteger)index] : [dst characterAtIndex: (NSUInteger)index]; Append(lpDst, dstIdx, cwDstLength, dstCodepoint, isError); index++; } diff --git a/src/native/libs/System.Globalization.Native/pal_collation.m b/src/native/libs/System.Globalization.Native/pal_collation.m index 9a63c11be44a..f18066d0812e 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.m +++ b/src/native/libs/System.Globalization.Native/pal_collation.m @@ -39,7 +39,7 @@ } else { - NSString *locName = [NSString stringWithCharacters: localeName length: lNameLength]; + NSString *locName = [NSString stringWithCharacters: localeName length: (NSUInteger)lNameLength]; currentLocale = [NSLocale localeWithLocaleIdentifier:locName]; } return currentLocale; @@ -90,9 +90,9 @@ int32_t GlobalizationNative_CompareStringNative(const uint16_t* localeName, int3 if (!IsComparisonOptionSupported(comparisonOptions)) return ERROR_COMPARISON_OPTIONS_NOT_FOUND; NSLocale *currentLocale = GetCurrentLocale(localeName, lNameLength); - NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength]; + NSString *sourceString = [NSString stringWithCharacters: lpSource length: (NSUInteger)cwSourceLength]; NSString *sourceStrPrecomposed = sourceString.precomposedStringWithCanonicalMapping; - NSString *targetString = [NSString stringWithCharacters: lpTarget length: cwTargetLength]; + NSString *targetString = [NSString stringWithCharacters: lpTarget length: (NSUInteger)cwTargetLength]; NSString *targetStrPrecomposed = targetString.precomposedStringWithCanonicalMapping; if (comparisonOptions & IgnoreKanaType) @@ -110,7 +110,7 @@ int32_t GlobalizationNative_CompareStringNative(const uint16_t* localeName, int3 NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions, true); NSRange comparisonRange = NSMakeRange(0, sourceStrPrecomposed.length); - return [sourceStrPrecomposed compare:targetStrPrecomposed + return (int32_t)[sourceStrPrecomposed compare:targetStrPrecomposed options:options range:comparisonRange locale:currentLocale]; @@ -158,9 +158,9 @@ Range GlobalizationNative_IndexOfNative(const uint16_t* localeName, int32_t lNam return result; } NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions, true); - NSString *searchString = [NSString stringWithCharacters: lpTarget length: cwTargetLength]; + NSString *searchString = [NSString stringWithCharacters: lpTarget length: (NSUInteger)cwTargetLength]; NSString *searchStrCleaned = RemoveWeightlessCharacters(searchString); - NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength]; + NSString *sourceString = [NSString stringWithCharacters: lpSource length: (NSUInteger)cwSourceLength]; NSString *sourceStrCleaned = RemoveWeightlessCharacters(sourceString); if (comparisonOptions & IgnoreKanaType) { @@ -170,7 +170,7 @@ Range GlobalizationNative_IndexOfNative(const uint16_t* localeName, int32_t lNam if (sourceStrCleaned.length == 0 || searchStrCleaned.length == 0) { - result.location = fromBeginning ? 0 : sourceString.length; + result.location = fromBeginning ? 0 : (int32_t)sourceString.length; return result; } @@ -204,8 +204,8 @@ Range GlobalizationNative_IndexOfNative(const uint16_t* localeName, int32_t lNam if (nsRange.location != NSNotFound) { - result.location = nsRange.location; - result.length = nsRange.length; + result.location = (int32_t)nsRange.location; + result.length = (int32_t)nsRange.length; // in case of CompareOptions.IgnoreCase if letters have different representations in source and search strings // and case insensitive search appears more than one time in source string take last index for LastIndexOf and first index for IndexOf // e.g. new CultureInfo().CompareInfo.LastIndexOf("Is \u0055\u0308 or \u0075\u0308 the same as \u00DC or \u00FC?", "U\u0308", 25,18, CompareOptions.IgnoreCase); @@ -230,8 +230,8 @@ Range GlobalizationNative_IndexOfNative(const uint16_t* localeName, int32_t lNam if ((comparisonOptions & IgnoreCase) && IsIndexFound(fromBeginning, (int32_t)result.location, (int32_t)precomposedRange.location)) return result; - result.location = precomposedRange.location; - result.length = precomposedRange.length; + result.location = (int32_t)precomposedRange.location; + result.length = (int32_t)precomposedRange.length; if (!(comparisonOptions & IgnoreCase)) return result; } @@ -249,8 +249,8 @@ Range GlobalizationNative_IndexOfNative(const uint16_t* localeName, int32_t lNam if ((comparisonOptions & IgnoreCase) && IsIndexFound(fromBeginning, (int32_t)result.location, (int32_t)decomposedRange.location)) return result; - result.location = decomposedRange.location; - result.length = decomposedRange.length; + result.location = (int32_t)decomposedRange.location; + result.length = (int32_t)decomposedRange.length; return result; } @@ -270,9 +270,9 @@ int32_t GlobalizationNative_StartsWithNative(const uint16_t* localeName, int32_t return ERROR_COMPARISON_OPTIONS_NOT_FOUND; NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions, true); NSLocale *currentLocale = GetCurrentLocale(localeName, lNameLength); - NSString *prefixString = [NSString stringWithCharacters: lpPrefix length: cwPrefixLength]; + NSString *prefixString = [NSString stringWithCharacters: lpPrefix length: (NSUInteger)cwPrefixLength]; NSString *prefixStrComposed = RemoveWeightlessCharacters(prefixString.precomposedStringWithCanonicalMapping); - NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength]; + NSString *sourceString = [NSString stringWithCharacters: lpSource length: (NSUInteger)cwSourceLength]; NSString *sourceStrComposed = RemoveWeightlessCharacters(sourceString.precomposedStringWithCanonicalMapping); if (comparisonOptions & IgnoreKanaType) { @@ -282,7 +282,7 @@ int32_t GlobalizationNative_StartsWithNative(const uint16_t* localeName, int32_t NSRange sourceRange = NSMakeRange(0, prefixStrComposed.length > sourceStrComposed.length ? sourceStrComposed.length : prefixStrComposed.length); - int32_t result = [sourceStrComposed compare:prefixStrComposed + int32_t result = (int32_t)[sourceStrComposed compare:prefixStrComposed options:options range:sourceRange locale:currentLocale]; @@ -302,19 +302,19 @@ int32_t GlobalizationNative_EndsWithNative(const uint16_t* localeName, int32_t l return ERROR_COMPARISON_OPTIONS_NOT_FOUND; NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions, true); NSLocale *currentLocale = GetCurrentLocale(localeName, lNameLength); - NSString *suffixString = [NSString stringWithCharacters: lpSuffix length: cwSuffixLength]; + NSString *suffixString = [NSString stringWithCharacters: lpSuffix length: (NSUInteger)cwSuffixLength]; NSString *suffixStrComposed = RemoveWeightlessCharacters(suffixString.precomposedStringWithCanonicalMapping); - NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength]; + NSString *sourceString = [NSString stringWithCharacters: lpSource length: (NSUInteger)cwSourceLength]; NSString *sourceStrComposed = RemoveWeightlessCharacters(sourceString.precomposedStringWithCanonicalMapping); if (comparisonOptions & IgnoreKanaType) { suffixStrComposed = ConvertToKatakana(suffixStrComposed); sourceStrComposed = ConvertToKatakana(sourceStrComposed); } - int32_t startIndex = suffixStrComposed.length > sourceStrComposed.length ? 0 : sourceStrComposed.length - suffixStrComposed.length; + NSUInteger startIndex = suffixStrComposed.length > sourceStrComposed.length ? 0 : sourceStrComposed.length - suffixStrComposed.length; NSRange sourceRange = NSMakeRange(startIndex, sourceStrComposed.length - startIndex); - int32_t result = [sourceStrComposed compare:suffixStrComposed + int32_t result = (int32_t)[sourceStrComposed compare:suffixStrComposed options:options range:sourceRange locale:currentLocale]; @@ -334,7 +334,7 @@ int32_t GlobalizationNative_GetSortKeyNative(const uint16_t* localeName, int32_t } if (!IsComparisonOptionSupported(options)) return 0; - NSString *sourceString = [NSString stringWithCharacters: lpStr length: cwStrLength]; + NSString *sourceString = [NSString stringWithCharacters: lpStr length: (NSUInteger)cwStrLength]; if (options & IgnoreKanaType) { sourceString = ConvertToKatakana(sourceString); @@ -363,6 +363,7 @@ int32_t GlobalizationNative_GetSortKeyNative(const uint16_t* localeName, int32_t if (result) return (int32_t)usedLength; + (void)cbSortKeyLength; // ignore unused parameter return 0; } } diff --git a/src/native/libs/System.Globalization.Native/pal_icushim.c b/src/native/libs/System.Globalization.Native/pal_icushim.c index 11b4ea6b748b..7cc76a287983 100644 --- a/src/native/libs/System.Globalization.Native/pal_icushim.c +++ b/src/native/libs/System.Globalization.Native/pal_icushim.c @@ -62,8 +62,19 @@ static int FindSymbolVersion(int majorVer, int minorVer, int subVer, char* symbo // First try just the unversioned symbol if (dlsym(libicuuc, "u_strlen") == NULL) { + // suppress Wformat-truncation false-positive warning for gcc 7 and 8 +#if defined(__GNUC__) && __GNUC__ > 6 &&__GNUC__ < 9 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-truncation" +#endif + // Now try just the _majorVer added snprintf(symbolVersion, symbolVersionLen, "_%d%s", majorVer, suffix); + +#if defined(__GNUC__) && __GNUC__ > 6 &&__GNUC__ < 9 +#pragma GCC diagnostic pop +#endif + snprintf(symbolName, SYMBOL_NAME_SIZE, "u_strlen%s", symbolVersion); if (dlsym(libicuuc, symbolName) == NULL) { diff --git a/src/native/libs/System.Globalization.Native/pal_locale.m b/src/native/libs/System.Globalization.Native/pal_locale.m index 873b56950ee3..c777687e3e19 100644 --- a/src/native/libs/System.Globalization.Native/pal_locale.m +++ b/src/native/libs/System.Globalization.Native/pal_locale.m @@ -41,7 +41,7 @@ { @autoreleasepool { - NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSString *locName = [[NSString alloc] initWithUTF8String:localeName]; NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; const char* value = [currentLocale.localeIdentifier UTF8String]; return strdup(value); @@ -79,11 +79,11 @@ static void GetParent(const char* localeID, char* parent, int32_t parentCapacity { localeID += 3; i -= 3; - memmove(parent, localeID, MIN(i, parentCapacity)); + memmove(parent, localeID, i < parentCapacity ? i : parentCapacity); } else if (parent != localeID) { - memcpy(parent, localeID, MIN(i, parentCapacity)); + memcpy(parent, localeID, i < parentCapacity ? i : parentCapacity); } } @@ -139,7 +139,7 @@ static int16_t _findIndex(const char* const* list, const char* key) @autoreleasepool { NSString *value; - NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSString *locName = [[NSString alloc] initWithUTF8String:localeName]; NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; numberFormatter.locale = currentLocale; @@ -152,7 +152,7 @@ static int16_t _findIndex(const char* const* list, const char* key) ///// localized name of locale, eg "German (Germany)" in UI language (corresponds to LOCALE_SLOCALIZEDDISPLAYNAME) case LocaleString_LocalizedDisplayName: { - NSString *currUILocaleName = [NSString stringWithFormat:@"%s", currentUILocaleName == NULL ? GlobalizationNative_GetDefaultLocaleNameNative() : currentUILocaleName]; + NSString *currUILocaleName = [[NSString alloc] initWithUTF8String: currentUILocaleName == NULL ? GlobalizationNative_GetDefaultLocaleNameNative() : currentUILocaleName]; NSLocale *currentUILocale = [[NSLocale alloc] initWithLocaleIdentifier:currUILocaleName]; value = [currentUILocale displayNameForKey:NSLocaleIdentifier value:currentLocale.localeIdentifier]; break; @@ -168,7 +168,7 @@ static int16_t _findIndex(const char* const* list, const char* key) /// Language Display Name for a language, eg "German" in UI language (corresponds to LOCALE_SLOCALIZEDLANGUAGENAME) case LocaleString_LocalizedLanguageName: { - NSString *currUILocaleName = [NSString stringWithFormat:@"%s", currentUILocaleName == NULL ? GlobalizationNative_GetDefaultLocaleNameNative() : currentUILocaleName]; + NSString *currUILocaleName = [[NSString alloc] initWithUTF8String: currentUILocaleName == NULL ? GlobalizationNative_GetDefaultLocaleNameNative() : currentUILocaleName]; NSLocale *currentUILocale = [[NSLocale alloc] initWithLocaleIdentifier:currUILocaleName]; value = [currentUILocale localizedStringForLanguageCode:currentLocale.languageCode]; break; @@ -183,11 +183,11 @@ static int16_t _findIndex(const char* const* list, const char* key) break; /// English name of country, eg "Germany" (corresponds to LOCALE_SENGLISHCOUNTRYNAME) case LocaleString_EnglishCountryName: - value = [gbLocale localizedStringForCountryCode:currentLocale.countryCode]; + value = [gbLocale localizedStringForCountryCode:currentLocale.countryCode == nil ? @"" : currentLocale.countryCode]; break; /// native name of country, eg "Deutschland" (corresponds to LOCALE_SNATIVECOUNTRYNAME) case LocaleString_NativeCountryName: - value = [currentLocale localizedStringForCountryCode:currentLocale.countryCode]; + value = [currentLocale localizedStringForCountryCode:currentLocale.countryCode == nil ? @"" : currentLocale.countryCode]; break; case LocaleString_ThousandSeparator: value = currentLocale.groupingSeparator; @@ -214,10 +214,10 @@ static int16_t _findIndex(const char* const* list, const char* key) value = currentLocale.currencyCode; break; case LocaleString_CurrencyEnglishName: - value = [gbLocale localizedStringForCurrencyCode:currentLocale.currencyCode]; + value = [gbLocale localizedStringForCurrencyCode:currentLocale.currencyCode == nil ? @"" : currentLocale.currencyCode]; break; case LocaleString_CurrencyNativeName: - value = [currentLocale localizedStringForCurrencyCode:currentLocale.currencyCode]; + value = [currentLocale localizedStringForCurrencyCode:currentLocale.currencyCode == nil ? @"" : currentLocale.currencyCode]; break; case LocaleString_MonetaryDecimalSeparator: value = numberFormatter.currencyDecimalSeparator; @@ -307,7 +307,7 @@ static int16_t _findIndex(const char* const* list, const char* key) static char* NormalizeNumericPattern(const char* srcPattern, int isNegative) { int iStart = 0; - int iEnd = strlen(srcPattern); + int iEnd = (int)strlen(srcPattern); // ';' separates positive and negative subpatterns. // When there is no explicit negative subpattern, @@ -315,7 +315,7 @@ static int16_t _findIndex(const char* const* list, const char* key) char * ptrNegativePattern = strrchr(srcPattern,';'); if (ptrNegativePattern) { - int32_t iNegativePatternStart = ptrNegativePattern - srcPattern; + int32_t iNegativePatternStart = (int32_t)(ptrNegativePattern - srcPattern); if (isNegative) { iStart = iNegativePatternStart + 1; @@ -529,17 +529,16 @@ int32_t GlobalizationNative_GetLocaleInfoIntNative(const char* localeName, Local bool isSuccess = true; #endif int32_t value; - NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSString *locName = [[NSString alloc] initWithUTF8String:localeName]; NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; switch (localeNumberData) { case LocaleNumber_MeasurementSystem: { - const char *measurementSystem = [[currentLocale objectForKey:NSLocaleMeasurementSystem] UTF8String]; - NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; - const char *us_measurementSystem = [[usLocale objectForKey:NSLocaleMeasurementSystem] UTF8String]; - value = (measurementSystem == us_measurementSystem) ? 1 : 0; + NSString *currenMeasurementSystem = [currentLocale objectForKey:NSLocaleMeasurementSystem]; + NSString *usMeasurementSystem = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"] objectForKey:NSLocaleMeasurementSystem]; + value = [currenMeasurementSystem isEqualToString:usMeasurementSystem] ? 1 : 0; break; } case LocaleNumber_FractionalDigitsCount: @@ -600,7 +599,8 @@ int32_t GlobalizationNative_GetLocaleInfoIntNative(const char* localeName, Local } case LocaleNumber_ReadingLayout: { - NSLocaleLanguageDirection langDir = [NSLocale characterDirectionForLanguage:[currentLocale objectForKey:NSLocaleLanguageCode]]; + NSString* langCode = [currentLocale objectForKey:NSLocaleLanguageCode]; + NSLocaleLanguageDirection langDir = [NSLocale characterDirectionForLanguage:langCode]; // 0 - Left to right (such as en-US) // 1 - Right to left (such as arabic locales) value = NSLocaleLanguageDirectionRightToLeft == langDir ? 1 : 0; @@ -609,7 +609,7 @@ int32_t GlobalizationNative_GetLocaleInfoIntNative(const char* localeName, Local case LocaleNumber_FirstDayofWeek: { NSCalendar *calendar = [currentLocale objectForKey:NSLocaleCalendar]; - value = [calendar firstWeekday] - 1; // .NET is 0-based and in Apple is 1-based; + value = (int32_t)[calendar firstWeekday] - 1; // .NET is 0-based and in Apple is 1-based; break; } default: @@ -636,7 +636,7 @@ int32_t GlobalizationNative_GetLocaleInfoPrimaryGroupingSizeNative(const char* l { @autoreleasepool { - NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSString *locName = [[NSString alloc] initWithUTF8String:localeName]; NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; numberFormatter.locale = currentLocale; @@ -653,7 +653,7 @@ int32_t GlobalizationNative_GetLocaleInfoPrimaryGroupingSizeNative(const char* l assert(false); break; } - return [numberFormatter groupingSize]; + return (int32_t)[numberFormatter groupingSize]; } } @@ -667,7 +667,7 @@ int32_t GlobalizationNative_GetLocaleInfoSecondaryGroupingSizeNative(const char* { @autoreleasepool { - NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSString *locName = [[NSString alloc] initWithUTF8String:localeName]; NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; numberFormatter.locale = currentLocale; @@ -685,7 +685,7 @@ int32_t GlobalizationNative_GetLocaleInfoSecondaryGroupingSizeNative(const char* break; } - return [numberFormatter secondaryGroupingSize]; + return (int32_t)[numberFormatter secondaryGroupingSize]; } } @@ -699,7 +699,7 @@ Returns time format information (in native format, it needs to be converted to . { @autoreleasepool { - NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSString *locName = [[NSString alloc] initWithUTF8String:localeName]; NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setLocale:currentLocale]; @@ -729,26 +729,26 @@ int32_t GlobalizationNative_GetLocalesNative(UChar* value, int32_t length) @autoreleasepool { NSArray* availableLocaleIdentifiers = [NSLocale availableLocaleIdentifiers]; - int32_t index = 0; - int32_t totalLength = 0; - int32_t availableLength = (int32_t)[availableLocaleIdentifiers count]; + NSUInteger index = 0; + NSUInteger totalLength = 0; + NSUInteger availableLength = [availableLocaleIdentifiers count]; if (availableLength <= 0) return -1; // failed - for (NSInteger i = 0; i < availableLength; i++) + for (NSUInteger i = 0; i < availableLength; i++) { NSString *localeIdentifier = availableLocaleIdentifiers[i]; - int32_t localeNameLength = localeIdentifier.length; + NSUInteger localeNameLength = localeIdentifier.length; totalLength += localeNameLength + 1; // add 1 for the name length if (value != NULL) { - if (totalLength > length) + if (totalLength > (NSUInteger)length) return -3; value[index++] = (UChar) localeNameLength; - for (int j = 0; j < localeNameLength; j++) + for (NSUInteger j = 0; j < localeNameLength; j++) { if ((UChar)[localeIdentifier characterAtIndex:j] == '_') { @@ -761,7 +761,7 @@ int32_t GlobalizationNative_GetLocalesNative(UChar* value, int32_t length) } } } - return totalLength; + return (int32_t)totalLength; } } @@ -770,7 +770,8 @@ int32_t GlobalizationNative_GetLocalesNative(UChar* value, int32_t length) @autoreleasepool { NSString *bundlePath = [[NSBundle mainBundle] bundlePath]; - NSString *dataPath = [bundlePath stringByAppendingPathComponent: [NSString stringWithFormat:@"%s", path]]; + NSString *pathInBundle = [[NSString alloc] initWithUTF8String:path]; + NSString *dataPath = [bundlePath stringByAppendingPathComponent:pathInBundle]; return strdup([dataPath UTF8String]); } @@ -824,7 +825,7 @@ int32_t GlobalizationNative_IsPredefinedLocaleNative(const char* localeName) { @autoreleasepool { - NSString *localeIdentifier = [NSString stringWithFormat:@"%s", localeName]; + NSString *localeIdentifier = [[NSString alloc] initWithUTF8String:localeName]; NSString *localeIdentifierByRegionDesignator = [localeIdentifier stringByReplacingOccurrencesOfString:@"-" withString:@"_"]; NSArray *availableLocales = [NSLocale availableLocaleIdentifiers]; diff --git a/src/native/libs/System.Globalization.Native/pal_localeNumberData.c b/src/native/libs/System.Globalization.Native/pal_localeNumberData.c index 1cc0e55d188b..837006eee9bf 100644 --- a/src/native/libs/System.Globalization.Native/pal_localeNumberData.c +++ b/src/native/libs/System.Globalization.Native/pal_localeNumberData.c @@ -72,6 +72,8 @@ static char* NormalizeNumericPattern(const UChar* srcPattern, int isNegative) case UCHAR_CLOSEPAREN: minusAdded = true; break; + default: + break; } } @@ -145,6 +147,9 @@ static char* NormalizeNumericPattern(const UChar* srcPattern, int isNegative) case UCHAR_PERCENT: destPattern[index++] = '%'; break; + + default: + break; } } diff --git a/src/native/libs/System.Globalization.Native/pal_normalization.m b/src/native/libs/System.Globalization.Native/pal_normalization.m index c029a16328bb..4dac9969a27d 100644 --- a/src/native/libs/System.Globalization.Native/pal_normalization.m +++ b/src/native/libs/System.Globalization.Native/pal_normalization.m @@ -45,7 +45,7 @@ int32_t GlobalizationNative_IsNormalizedNative(NormalizationForm normalizationFo { @autoreleasepool { - NSString *sourceString = [NSString stringWithCharacters: lpStr length: cwStrLength]; + NSString *sourceString = [NSString stringWithCharacters: lpStr length: (NSUInteger)cwStrLength]; NSString *normalizedString = GetNormalizedStringForForm(normalizationForm, sourceString); return normalizedString == NULL ? -1 : [sourceString isEqualToString: normalizedString]; @@ -67,7 +67,7 @@ int32_t GlobalizationNative_NormalizeStringNative(NormalizationForm normalizatio { @autoreleasepool { - NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength]; + NSString *sourceString = [NSString stringWithCharacters: lpSource length: (NSUInteger)cwSourceLength]; NSString *normalizedString = GetNormalizedStringForForm(normalizationForm, sourceString); if (normalizedString == NULL || normalizedString.length == 0) @@ -77,14 +77,14 @@ int32_t GlobalizationNative_NormalizeStringNative(NormalizationForm normalizatio int32_t index = 0, dstIdx = 0, isError = 0; uint16_t dstCodepoint; - while (index < normalizedString.length) + while ((NSUInteger)index < normalizedString.length) { - dstCodepoint = [normalizedString characterAtIndex: index]; + dstCodepoint = [normalizedString characterAtIndex: (NSUInteger)index]; Append(lpDst, dstIdx, cwDstLength, dstCodepoint, isError); index++; } - return !isError ? [normalizedString length] : 0; + return !isError ? (int32_t)[normalizedString length] : 0; } } #endif diff --git a/src/native/libs/System.Globalization.Native/pal_placeholders.c b/src/native/libs/System.Globalization.Native/pal_placeholders.c index 7d0f9624e082..413e2d311a29 100644 --- a/src/native/libs/System.Globalization.Native/pal_placeholders.c +++ b/src/native/libs/System.Globalization.Native/pal_placeholders.c @@ -16,14 +16,6 @@ #include "pal_timeZoneInfo.h" #ifdef DEBUG -#define assert_err(cond, msg, err) do \ -{ \ - if(!(cond)) \ - { \ - fprintf(stderr, "%s (%d): error %d: %s. %s (%s failed)\n", __FILE__, __LINE__, err, msg, strerror(err), #cond); \ - assert(false && "assert_err failed"); \ - } \ -} while(0) #define assert_msg(cond, msg, val) do \ { \ if(!(cond)) \ @@ -33,10 +25,12 @@ } \ } while(0) #else // DEBUG -#define assert_err(cond, msg, err) #define assert_msg(cond, msg, val) #endif // DEBUG +// don't generate warnings for placeholders +#pragma clang diagnostic ignored "-Wunused-parameter" +#pragma clang diagnostic ignored "-Wmissing-noreturn" // Placeholder for calendar data int32_t GlobalizationNative_GetCalendars( diff --git a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m index e5404e5cb0d4..b7e7dc627da2 100644 --- a/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m +++ b/src/native/libs/System.Globalization.Native/pal_timeZoneInfo.m @@ -20,7 +20,7 @@ int32_t GlobalizationNative_GetTimeZoneDisplayNameNative(const uint16_t* localeN { @autoreleasepool { - NSString* tzName = [NSString stringWithCharacters: timeZoneId length: timeZoneIdLength]; + NSString* tzName = [NSString stringWithCharacters: timeZoneId length: (NSUInteger)timeZoneIdLength]; NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:tzName]; if (timeZone == NULL) { @@ -39,7 +39,7 @@ int32_t GlobalizationNative_GetTimeZoneDisplayNameNative(const uint16_t* localeN } else { - NSString *locName = [NSString stringWithCharacters: localeName length: lNameLength]; + NSString *locName = [NSString stringWithCharacters: localeName length: (NSUInteger)lNameLength]; currentLocale = [NSLocale localeWithLocaleIdentifier:locName]; } NSTimeZoneNameStyle style; @@ -68,9 +68,9 @@ int32_t GlobalizationNative_GetTimeZoneDisplayNameNative(const uint16_t* localeN int32_t index = 0, dstIdx = 0, resultCode = Success; uint16_t dstCodepoint; - while (index < timeZoneName.length) + while ((NSUInteger)index < timeZoneName.length) { - dstCodepoint = [timeZoneName characterAtIndex: index]; + dstCodepoint = [timeZoneName characterAtIndex: (NSUInteger)index]; Append(result, dstIdx, resultLength, dstCodepoint, resultCode); if (resultCode != Success) return resultCode; diff --git a/src/native/libs/System.IO.Compression.Native/CMakeLists.txt b/src/native/libs/System.IO.Compression.Native/CMakeLists.txt index 3906adaf7be1..6e2d785b0452 100644 --- a/src/native/libs/System.IO.Compression.Native/CMakeLists.txt +++ b/src/native/libs/System.IO.Compression.Native/CMakeLists.txt @@ -76,7 +76,7 @@ if (CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI) ${NATIVE_LIBS_EXTRA} ) - if (NOT CLR_CMAKE_TARGET_MACCATALYST AND NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CMAKE_TARGET_TVOS AND NOT CLR_CMAKE_TARGET_ANDROID) + if (NOT CLR_CMAKE_TARGET_MACCATALYST AND NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CMAKE_TARGET_TVOS AND NOT CLR_CMAKE_TARGET_ANDROID AND NOT CLR_CMAKE_USE_SYSTEM_BROTLI) set(DEF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/System.IO.Compression.Native_unixexports.src) set(EXPORTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/System.IO.Compression.Native.exports) generate_exports_file(${DEF_SOURCES} ${EXPORTS_FILE}) @@ -88,16 +88,14 @@ if (CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI) set_property(TARGET System.IO.Compression.Native APPEND_STRING PROPERTY LINK_FLAGS ${EXPORTS_LINKER_OPTION}) set_property(TARGET System.IO.Compression.Native APPEND_STRING PROPERTY LINK_DEPENDS ${EXPORTS_FILE}) - if (NOT CLR_CMAKE_USE_SYSTEM_BROTLI) - add_custom_command(TARGET System.IO.Compression.Native POST_BUILD - COMMENT "Verifying System.IO.Compression.Native entry points against entrypoints.c " - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../verify-entrypoints.sh - $ - ${CMAKE_CURRENT_SOURCE_DIR}/entrypoints.c - ${CMAKE_NM} - VERBATIM - ) - endif () + add_custom_command(TARGET System.IO.Compression.Native POST_BUILD + COMMENT "Verifying System.IO.Compression.Native entry points against entrypoints.c " + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../verify-entrypoints.sh + $ + ${CMAKE_CURRENT_SOURCE_DIR}/entrypoints.c + ${CMAKE_NM} + VERBATIM + ) endif () install_with_stripped_symbols (System.IO.Compression.Native PROGRAMS .) diff --git a/src/native/libs/System.Native/entrypoints.c b/src/native/libs/System.Native/entrypoints.c index ee842ee2b736..30cc86f2aff9 100644 --- a/src/native/libs/System.Native/entrypoints.c +++ b/src/native/libs/System.Native/entrypoints.c @@ -160,6 +160,7 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_SetSendTimeout) DllImportEntry(SystemNative_Receive) DllImportEntry(SystemNative_ReceiveMessage) + DllImportEntry(SystemNative_ReceiveSocketError) DllImportEntry(SystemNative_Send) DllImportEntry(SystemNative_SendMessage) DllImportEntry(SystemNative_Accept) diff --git a/src/native/libs/System.Native/ios/net/if_media.h b/src/native/libs/System.Native/ios/net/if_media.h index e7e1a838d420..cef4c1f666a3 100644 --- a/src/native/libs/System.Native/ios/net/if_media.h +++ b/src/native/libs/System.Native/ios/net/if_media.h @@ -586,4 +586,4 @@ struct ifmedia_description { { 0, NULL }, \ } -#endif /* _NET_IF_MEDIA_H_ */ \ No newline at end of file +#endif /* _NET_IF_MEDIA_H_ */ diff --git a/src/native/libs/System.Native/ios/netinet/icmp_var.h b/src/native/libs/System.Native/ios/netinet/icmp_var.h index 2633ab1bcf5a..da5c3955e1a7 100644 --- a/src/native/libs/System.Native/ios/netinet/icmp_var.h +++ b/src/native/libs/System.Native/ios/netinet/icmp_var.h @@ -118,4 +118,4 @@ extern boolean_t badport_bandlim(int which); extern struct icmpstat icmpstat; #endif /* BSD_KERNEL_PRIVATE */ -#endif /* _NETINET_ICMP_VAR_H_ */ \ No newline at end of file +#endif /* _NETINET_ICMP_VAR_H_ */ diff --git a/src/native/libs/System.Native/ios/netinet/ip_var.h b/src/native/libs/System.Native/ios/netinet/ip_var.h index e5137effeed4..7fbe4ba82bfc 100644 --- a/src/native/libs/System.Native/ios/netinet/ip_var.h +++ b/src/native/libs/System.Native/ios/netinet/ip_var.h @@ -368,4 +368,4 @@ extern int ip_gre_output(struct mbuf *); typedef struct mbuf *(*gre_input_func_t)(struct mbuf *, int, int); extern int ip_gre_register_input(gre_input_func_t); #endif /* KERNEL_PRIVATE */ -#endif /* !_NETINET_IP_VAR_H_ */ \ No newline at end of file +#endif /* !_NETINET_IP_VAR_H_ */ diff --git a/src/native/libs/System.Native/ios/netinet/tcp_fsm.h b/src/native/libs/System.Native/ios/netinet/tcp_fsm.h index 869d9bcef8d5..0bdb5b0fe60f 100644 --- a/src/native/libs/System.Native/ios/netinet/tcp_fsm.h +++ b/src/native/libs/System.Native/ios/netinet/tcp_fsm.h @@ -136,7 +136,7 @@ static u_char tcp_outflags[TCP_NSTATES] = { #endif #endif /* KERNEL_PRIVATE */ -#if KPROF +#ifdef KPROF #ifdef KERNEL_PRIVATE int tcp_acounts[TCP_NSTATES][PRU_NREQ]; #endif /* KERNEL_PRIVATE */ @@ -150,4 +150,4 @@ char *tcpstates[] = { }; #endif -#endif \ No newline at end of file +#endif diff --git a/src/native/libs/System.Native/ios/netinet/udp_var.h b/src/native/libs/System.Native/ios/netinet/udp_var.h index 12e4ea51f0b4..54afeab9deb5 100644 --- a/src/native/libs/System.Native/ios/netinet/udp_var.h +++ b/src/native/libs/System.Native/ios/netinet/udp_var.h @@ -185,4 +185,4 @@ extern void udp_fill_keepalive_offload_frames(struct ifnet *, __END_DECLS #endif /* BSD_KERNEL_PRIVATE */ -#endif /* _NETINET_UDP_VAR_H_ */ \ No newline at end of file +#endif /* _NETINET_UDP_VAR_H_ */ diff --git a/src/native/libs/System.Native/pal_autoreleasepool.m b/src/native/libs/System.Native/pal_autoreleasepool.m index 9f20031ffca4..740a059e7e0e 100644 --- a/src/native/libs/System.Native/pal_autoreleasepool.m +++ b/src/native/libs/System.Native/pal_autoreleasepool.m @@ -20,9 +20,12 @@ void EnsureNSThreadIsMultiThreaded(void) // We need to use detachNewThreadSelector to put NSThread into multithreaded mode. // We can't use detachNewThreadWithBlock since it doesn't change NSThread into multithreaded mode for some reason. // See https://developer.apple.com/documentation/foundation/nswillbecomemultithreadednotification for more information. - id placeholderObject = [[NSMutableString alloc] init]; + id placeholderObject = [[NSMutableString alloc] init]; [NSThread detachNewThreadSelector:@selector(appendString:) toTarget:placeholderObject withObject:@""]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-messaging-id" [placeholderObject release]; +#pragma clang diagnostic pop } assert([NSThread isMultiThreaded]); } diff --git a/src/native/libs/System.Native/pal_datetime.m b/src/native/libs/System.Native/pal_datetime.m index f023703f27be..74914d4fdc32 100644 --- a/src/native/libs/System.Native/pal_datetime.m +++ b/src/native/libs/System.Native/pal_datetime.m @@ -8,9 +8,9 @@ #error This file uses manual memory management and must not use ARC, but ARC is enabled. #endif -char* SystemNative_GetDefaultTimeZone() +char* SystemNative_GetDefaultTimeZone(void) { NSTimeZone *tz = [NSTimeZone localTimeZone]; NSString *name = [tz name]; return (name != nil) ? strdup([name UTF8String]) : NULL; -} \ No newline at end of file +} diff --git a/src/native/libs/System.Native/pal_environment.m b/src/native/libs/System.Native/pal_environment.m index fe02a2f96d4b..3293b8b37bf0 100644 --- a/src/native/libs/System.Native/pal_environment.m +++ b/src/native/libs/System.Native/pal_environment.m @@ -25,8 +25,8 @@ static void get_environ_helper(const void *key, const void *value, void *context char ***temp_environ_ptr = (char***)context; const char *utf8_key = [(NSString *)key UTF8String]; const char *utf8_value = [(NSString *)value UTF8String]; - int utf8_key_length = strlen(utf8_key); - int utf8_value_length = strlen(utf8_value); + size_t utf8_key_length = strlen(utf8_key); + size_t utf8_value_length = strlen(utf8_value); char *key_value_pair; key_value_pair = malloc(utf8_key_length + utf8_value_length + 2); @@ -47,13 +47,13 @@ static void get_environ_helper(const void *key, const void *value, void *context (*temp_environ_ptr)++; } -char** SystemNative_GetEnviron() +char** SystemNative_GetEnviron(void) { char **temp_environ; char **temp_environ_ptr; CFDictionaryRef environment = (CFDictionaryRef)[[NSProcessInfo processInfo] environment]; - int count = CFDictionaryGetCount(environment); + size_t count = (size_t)CFDictionaryGetCount(environment); temp_environ = (char **)malloc((count + 1) * sizeof(char *)); if (temp_environ != NULL) { diff --git a/src/native/libs/System.Native/pal_io.c b/src/native/libs/System.Native/pal_io.c index 9c65db55c4ee..cdd86ed46f06 100644 --- a/src/native/libs/System.Native/pal_io.c +++ b/src/native/libs/System.Native/pal_io.c @@ -49,8 +49,10 @@ #elif HAVE_SYS_STATVFS_H && !HAVE_NON_LEGACY_STATFS // SunOS #include #include +#if HAVE_STATFS_VFS #include #endif +#endif #ifdef _AIX #include @@ -1050,6 +1052,8 @@ int32_t SystemNative_MAdvise(void* address, uint64_t length, int32_t advice) errno = ENOTSUP; return -1; #endif + default: + break; // fall through to error } assert_msg(false, "Unknown MemoryAdvice", (int)advice); @@ -1087,6 +1091,8 @@ int64_t SystemNative_SysConf(int32_t name) return sysconf(_SC_CLK_TCK); case PAL_SC_PAGESIZE: return sysconf(_SC_PAGESIZE); + default: + break; // fall through to error } assert_msg(false, "Unknown SysConf name", (int)name); diff --git a/src/native/libs/System.Native/pal_iossupportversion.m b/src/native/libs/System.Native/pal_iossupportversion.m index 0a531350a1d0..b3ace719f2e1 100644 --- a/src/native/libs/System.Native/pal_iossupportversion.m +++ b/src/native/libs/System.Native/pal_iossupportversion.m @@ -9,7 +9,7 @@ #error This file uses manual memory management and must not use ARC, but ARC is enabled. #endif -const char* SystemNative_iOSSupportVersion() +const char* SystemNative_iOSSupportVersion(void) { NSDictionary *plist = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]; NSString *iOSSupportVersion = (NSString *)[plist objectForKey:@"iOSSupportVersion"]; diff --git a/src/native/libs/System.Native/pal_log.m b/src/native/libs/System.Native/pal_log.m index b62e4f750a83..befc96a518e3 100644 --- a/src/native/libs/System.Native/pal_log.m +++ b/src/native/libs/System.Native/pal_log.m @@ -10,7 +10,7 @@ void SystemNative_Log (uint8_t* buffer, int32_t length) { - NSString *msg = [[NSString alloc] initWithBytes: buffer length: length encoding: NSUTF16LittleEndianStringEncoding]; + NSString *msg = [[NSString alloc] initWithBytes: buffer length: (NSUInteger)length encoding: NSUTF16LittleEndianStringEncoding]; if (length > 4096) { // Write in chunks of max 4096 characters; older versions of iOS seems to have a bug where NSLog may hang with long strings (!). @@ -32,7 +32,10 @@ void SystemNative_Log (uint8_t* buffer, int32_t length) // No newline found, break in the middle. chunk_size = len > max_size ? max_size : len; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcstring-format-directive" NSLog (@"%.*s", (int) chunk_size, utf8); +#pragma clang diagnostic pop len -= chunk_size; utf8 += chunk_size; } diff --git a/src/native/libs/System.Native/pal_networking.c b/src/native/libs/System.Native/pal_networking.c index ee8c9a89e28a..113ef377294f 100644 --- a/src/native/libs/System.Native/pal_networking.c +++ b/src/native/libs/System.Native/pal_networking.c @@ -62,6 +62,10 @@ #if HAVE_SYS_FILIO_H #include #endif +#if HAVE_LINUX_ERRQUEUE_H +#include +#endif + #if HAVE_KQUEUE #if KEVENT_HAS_VOID_UDATA @@ -1325,7 +1329,11 @@ int32_t SystemNative_SetSendTimeout(intptr_t socket, int32_t millisecondsTimeout static int8_t ConvertSocketFlagsPalToPlatform(int32_t palFlags, int* platformFlags) { - const int32_t SupportedFlagsMask = SocketFlags_MSG_OOB | SocketFlags_MSG_PEEK | SocketFlags_MSG_DONTROUTE | SocketFlags_MSG_TRUNC | SocketFlags_MSG_CTRUNC; + const int32_t SupportedFlagsMask = +#ifdef MSG_ERRQUEUE + SocketFlags_MSG_ERRQUEUE | +#endif + SocketFlags_MSG_OOB | SocketFlags_MSG_PEEK | SocketFlags_MSG_DONTROUTE | SocketFlags_MSG_TRUNC | SocketFlags_MSG_CTRUNC | SocketFlags_MSG_DONTWAIT; if ((palFlags & ~SupportedFlagsMask) != 0) { @@ -1335,9 +1343,15 @@ static int8_t ConvertSocketFlagsPalToPlatform(int32_t palFlags, int* platformFla *platformFlags = ((palFlags & SocketFlags_MSG_OOB) == 0 ? 0 : MSG_OOB) | ((palFlags & SocketFlags_MSG_PEEK) == 0 ? 0 : MSG_PEEK) | ((palFlags & SocketFlags_MSG_DONTROUTE) == 0 ? 0 : MSG_DONTROUTE) | + ((palFlags & SocketFlags_MSG_DONTWAIT) == 0 ? 0 : MSG_DONTWAIT) | ((palFlags & SocketFlags_MSG_TRUNC) == 0 ? 0 : MSG_TRUNC) | ((palFlags & SocketFlags_MSG_CTRUNC) == 0 ? 0 : MSG_CTRUNC); - +#ifdef MSG_ERRQUEUE + if ((palFlags & SocketFlags_MSG_ERRQUEUE) != 0) + { + *platformFlags |= MSG_ERRQUEUE; + } +#endif return true; } @@ -1381,6 +1395,51 @@ int32_t SystemNative_Receive(intptr_t socket, void* buffer, int32_t bufferLen, i return SystemNative_ConvertErrorPlatformToPal(errno); } +int32_t SystemNative_ReceiveSocketError(intptr_t socket, MessageHeader* messageHeader) +{ + int fd = ToFileDescriptor(socket); + ssize_t res; + +#if HAVE_LINUX_ERRQUEUE_H + char buffer[sizeof(struct sock_extended_err) + sizeof(struct sockaddr_storage)]; + messageHeader->ControlBufferLen = sizeof(buffer); + messageHeader->ControlBuffer = (void*)buffer; + + struct msghdr header; + ConvertMessageHeaderToMsghdr(&header, messageHeader, fd); + + while ((res = recvmsg(fd, &header, SocketFlags_MSG_DONTWAIT | SocketFlags_MSG_ERRQUEUE)) < 0 && errno == EINTR); + + struct cmsghdr *cmsg; + for (cmsg = CMSG_FIRSTHDR(&header); cmsg; cmsg = GET_CMSG_NXTHDR(&header, cmsg)) + { + if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) + { + struct sock_extended_err *e = (struct sock_extended_err *)CMSG_DATA(cmsg); + if (e->ee_origin == SO_EE_ORIGIN_ICMP) + { + int size = (int)(cmsg->cmsg_len - sizeof(struct sock_extended_err)); + messageHeader->SocketAddressLen = size < messageHeader->SocketAddressLen ? size : messageHeader->SocketAddressLen; + memcpy(messageHeader->SocketAddress, (struct sockaddr_in*)(e+1), (size_t)messageHeader->SocketAddressLen); + return Error_SUCCESS; + } + } + } +#else + res = -1; + errno = ENOTSUP; +#endif + + messageHeader->SocketAddressLen = 0; + + if (res != -1) + { + return Error_SUCCESS; + } + + return SystemNative_ConvertErrorPlatformToPal(errno); +} + int32_t SystemNative_ReceiveMessage(intptr_t socket, MessageHeader* messageHeader, int32_t flags, int64_t* received) { if (messageHeader == NULL || received == NULL || messageHeader->SocketAddressLen < 0 || @@ -2017,7 +2076,7 @@ int32_t SystemNative_GetSockOpt( } struct socket_fdinfo fdi; - if (proc_pidfdinfo(getpid(), fd, PROC_PIDFDSOCKETINFO, &fdi, sizeof(fdi)) < sizeof(fdi)) + if (proc_pidfdinfo(getpid(), fd, PROC_PIDFDSOCKETINFO, &fdi, sizeof(fdi)) < (int)sizeof(fdi)) { return SystemNative_ConvertErrorPlatformToPal(errno); } @@ -2530,7 +2589,7 @@ int32_t SystemNative_GetSocketType(intptr_t socket, int32_t* addressFamily, int3 #if HAVE_SYS_PROCINFO_H struct socket_fdinfo fdi; - if (proc_pidfdinfo(getpid(), fd, PROC_PIDFDSOCKETINFO, &fdi, sizeof(fdi)) < sizeof(fdi)) + if (proc_pidfdinfo(getpid(), fd, PROC_PIDFDSOCKETINFO, &fdi, sizeof(fdi)) < (int)sizeof(fdi)) { return Error_EFAULT; } @@ -3159,8 +3218,8 @@ int32_t SystemNative_SendFile(intptr_t out_fd, intptr_t in_fd, int64_t offset, i char* buffer = NULL; // Save the original input file position and seek to the offset position - off_t inputFileOrigOffset = lseek(in_fd, 0, SEEK_CUR); - if (inputFileOrigOffset == -1 || lseek(in_fd, offtOffset, SEEK_SET) == -1) + off_t inputFileOrigOffset = lseek(infd, 0, SEEK_CUR); + if (inputFileOrigOffset == -1 || lseek(infd, offtOffset, SEEK_SET) == -1) { goto error; } @@ -3180,7 +3239,7 @@ int32_t SystemNative_SendFile(intptr_t out_fd, intptr_t in_fd, int64_t offset, i // Read up to what will fit in our buffer. We're done if we get back 0 bytes or read 'count' bytes ssize_t bytesRead; - while ((bytesRead = read(in_fd, buffer, numBytesToRead)) < 0 && errno == EINTR); + while ((bytesRead = read(infd, buffer, numBytesToRead)) < 0 && errno == EINTR); if (bytesRead == -1) { goto error; @@ -3196,7 +3255,7 @@ int32_t SystemNative_SendFile(intptr_t out_fd, intptr_t in_fd, int64_t offset, i while (bytesRead > 0) { ssize_t bytesWritten; - while ((bytesWritten = write(out_fd, buffer + writeOffset, (size_t)bytesRead)) < 0 && errno == EINTR); + while ((bytesWritten = write(outfd, buffer + writeOffset, (size_t)bytesRead)) < 0 && errno == EINTR); if (bytesWritten == -1) { goto error; @@ -3210,7 +3269,7 @@ int32_t SystemNative_SendFile(intptr_t out_fd, intptr_t in_fd, int64_t offset, i } // Restore the original input file position - if (lseek(in_fd, inputFileOrigOffset, SEEK_SET) == -1) + if (lseek(infd, inputFileOrigOffset, SEEK_SET) == -1) { goto error; } diff --git a/src/native/libs/System.Native/pal_networking.h b/src/native/libs/System.Native/pal_networking.h index 0a46f1490aab..5dfe1c1c54df 100644 --- a/src/native/libs/System.Native/pal_networking.h +++ b/src/native/libs/System.Native/pal_networking.h @@ -206,6 +206,8 @@ typedef enum SocketFlags_MSG_DONTROUTE = 0x0004, // SocketFlags.DontRoute SocketFlags_MSG_TRUNC = 0x0100, // SocketFlags.Truncated SocketFlags_MSG_CTRUNC = 0x0200, // SocketFlags.ControlDataTruncated + SocketFlags_MSG_DONTWAIT = 0x1000, // used privately by Ping + SocketFlags_MSG_ERRQUEUE = 0x2000, // used privately by Ping } SocketFlags; /* @@ -356,6 +358,8 @@ PALEXPORT int32_t SystemNative_Receive(intptr_t socket, void* buffer, int32_t bu PALEXPORT int32_t SystemNative_ReceiveMessage(intptr_t socket, MessageHeader* messageHeader, int32_t flags, int64_t* received); +PALEXPORT int32_t SystemNative_ReceiveSocketError(intptr_t socket, MessageHeader* messageHeader); + PALEXPORT int32_t SystemNative_Send(intptr_t socket, void* buffer, int32_t bufferLen, int32_t flags, int32_t* sent); PALEXPORT int32_t SystemNative_SendMessage(intptr_t socket, MessageHeader* messageHeader, int32_t flags, int64_t* sent); diff --git a/src/native/libs/System.Native/pal_networkstatistics.c b/src/native/libs/System.Native/pal_networkstatistics.c index eeeb8ac80294..bfa1cc50074b 100644 --- a/src/native/libs/System.Native/pal_networkstatistics.c +++ b/src/native/libs/System.Native/pal_networkstatistics.c @@ -18,6 +18,7 @@ #if HAVE_NETINET_TCP_VAR_H #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wreserved-id-macro" +#pragma clang diagnostic ignored "-Wunused-macros" #define _WANT_INPCB #define _WANT_TCPCB #pragma clang diagnostic pop diff --git a/src/native/libs/System.Native/pal_process.c b/src/native/libs/System.Native/pal_process.c index 509049b2fdcd..fa5e522c3620 100644 --- a/src/native/libs/System.Native/pal_process.c +++ b/src/native/libs/System.Native/pal_process.c @@ -507,6 +507,23 @@ done:; return success ? 0 : -1; #else + // ignore unused parameters + (void)filename; + (void)argv; + (void)envp; + (void)cwd; + (void)redirectStdin; + (void)redirectStdout; + (void)redirectStderr; + (void)setCredentials; + (void)userId; + (void)groupId; + (void)groups; + (void)groupsLength; + (void)childPid; + (void)stdinFd; + (void)stdoutFd; + (void)stderrFd; return -1; #endif } diff --git a/src/native/libs/System.Native/pal_searchpath.m b/src/native/libs/System.Native/pal_searchpath.m index e8d07c163cc4..571e9b04116f 100644 --- a/src/native/libs/System.Native/pal_searchpath.m +++ b/src/native/libs/System.Native/pal_searchpath.m @@ -16,7 +16,7 @@ return path == NULL ? NULL : strdup (path); } -const char* SystemNative_SearchPath_TempDirectory() +const char* SystemNative_SearchPath_TempDirectory(void) { NSString* tempPath = NSTemporaryDirectory(); const char *path = [tempPath UTF8String]; diff --git a/src/native/libs/System.Native/pal_threading.c b/src/native/libs/System.Native/pal_threading.c index 975e94acc476..1d9f3cd6bf33 100644 --- a/src/native/libs/System.Native/pal_threading.c +++ b/src/native/libs/System.Native/pal_threading.c @@ -21,9 +21,6 @@ #undef _XOPEN_SOURCE #endif #include -#if defined(TARGET_OSX) -#define _XOPEN_SOURCE -#endif //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // LowLevelMonitor - Represents a non-recursive mutex and condition diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_digest.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_digest.c index dba8026dd315..b2b89be4e664 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_digest.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_digest.c @@ -167,7 +167,7 @@ int32_t AppleCryptoNative_DigestOneShot(PAL_HashAlgorithm algorithm, uint8_t* pB { return -1; } - CC_SHA1(pBuf, cbBuf, pOutput); + CC_SHA1(pBuf, (CC_LONG)cbBuf, pOutput); return 1; case PAL_SHA256: *pcbDigest = CC_SHA256_DIGEST_LENGTH; @@ -175,7 +175,7 @@ int32_t AppleCryptoNative_DigestOneShot(PAL_HashAlgorithm algorithm, uint8_t* pB { return -1; } - CC_SHA256(pBuf, cbBuf, pOutput); + CC_SHA256(pBuf, (CC_LONG)cbBuf, pOutput); return 1; case PAL_SHA384: *pcbDigest = CC_SHA384_DIGEST_LENGTH; @@ -183,7 +183,7 @@ int32_t AppleCryptoNative_DigestOneShot(PAL_HashAlgorithm algorithm, uint8_t* pB { return -1; } - CC_SHA384(pBuf, cbBuf, pOutput); + CC_SHA384(pBuf, (CC_LONG)cbBuf, pOutput); return 1; case PAL_SHA512: *pcbDigest = CC_SHA512_DIGEST_LENGTH; @@ -191,7 +191,7 @@ int32_t AppleCryptoNative_DigestOneShot(PAL_HashAlgorithm algorithm, uint8_t* pB { return -1; } - CC_SHA512(pBuf, cbBuf, pOutput); + CC_SHA512(pBuf, (CC_LONG)cbBuf, pOutput); return 1; case PAL_MD5: *pcbDigest = CC_MD5_DIGEST_LENGTH; @@ -201,7 +201,7 @@ int32_t AppleCryptoNative_DigestOneShot(PAL_HashAlgorithm algorithm, uint8_t* pB } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - CC_MD5(pBuf, cbBuf, pOutput); + CC_MD5(pBuf, (CC_LONG)cbBuf, pOutput); #pragma clang diagnostic pop return 1; default: @@ -233,6 +233,4 @@ int32_t AppleCryptoNative_DigestReset(DigestCtx* ctx) assert(false); return -2; } - - return 1; } diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_hmac.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_hmac.c index 4ffbc2f094d9..6dfc1067d2f0 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_hmac.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_hmac.c @@ -142,6 +142,6 @@ int32_t AppleCryptoNative_HmacOneShot(PAL_HashAlgorithm algorithm, if (cbOutput < *pcbDigest) return -1; - CCHmac(ccAlgorithm, pKey, cbKey, pBuf, cbBuf, pOutput); + CCHmac(ccAlgorithm, pKey, (size_t)cbKey, pBuf, (size_t)cbBuf, pOutput); return 1; } diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keychain_ios.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keychain_ios.c index a666297f04d6..8139fd626073 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keychain_ios.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keychain_ios.c @@ -96,12 +96,12 @@ int32_t AppleCryptoNative_X509StoreRemoveCertificate(CFTypeRef certOrIdentity, u assert(certOrIdentity != NULL); - const void* keys[] = {kSecValueRef}; - const void* values[] = {certOrIdentity}; + const void* keys1[] = {kSecValueRef}; + const void* values1[] = {certOrIdentity}; CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, - keys, - values, - sizeof(keys) / sizeof(*keys), + keys1, + values1, + sizeof(keys1) / sizeof(*keys1), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); @@ -143,12 +143,12 @@ int32_t AppleCryptoNative_X509StoreRemoveCertificate(CFTypeRef certOrIdentity, u { OSStatus keyStatus; - const void* keys[] = {kSecClass, kSecAttrPublicKeyHash}; - const void* values[] = {kSecClassCertificate, publicKeyLabel}; + const void* keys2[] = {kSecClass, kSecAttrPublicKeyHash}; + const void* values2[] = {kSecClassCertificate, publicKeyLabel}; query = CFDictionaryCreate(kCFAllocatorDefault, - keys, - values, - sizeof(keys) / sizeof(*keys), + keys2, + values2, + sizeof(keys2) / sizeof(*keys2), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); @@ -170,12 +170,12 @@ int32_t AppleCryptoNative_X509StoreRemoveCertificate(CFTypeRef certOrIdentity, u if (keyStatus == errSecItemNotFound) { - const void* keys[] = {kSecClass, kSecAttrApplicationLabel}; - const void* values[] = {kSecClassKey, publicKeyLabel}; + const void* keys3[] = {kSecClass, kSecAttrApplicationLabel}; + const void* values3[] = {kSecClassKey, publicKeyLabel}; query = CFDictionaryCreate(kCFAllocatorDefault, - keys, - values, - sizeof(keys) / sizeof(*keys), + keys3, + values3, + sizeof(keys3) / sizeof(*keys3), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keyderivation.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keyderivation.c index 753d30d31d48..9d3838be5470 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keyderivation.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keyderivation.c @@ -35,7 +35,7 @@ int32_t AppleCryptoNative_Pbkdf2(PAL_HashAlgorithm prfAlgorithm, int32_t saltLen, int32_t iterations, uint8_t* derivedKey, - uint32_t derivedKeyLen, + int32_t derivedKeyLen, int32_t* errorCode) { if (errorCode != NULL) @@ -73,8 +73,8 @@ int32_t AppleCryptoNative_Pbkdf2(PAL_HashAlgorithm prfAlgorithm, return -2; } - CCStatus result = CCKeyDerivationPBKDF(kCCPBKDF2, password, passwordLen, salt, - saltLen, prf, iterations, derivedKey, derivedKeyLen); + CCStatus result = CCKeyDerivationPBKDF(kCCPBKDF2, password, (size_t)passwordLen, salt, + (size_t)saltLen, prf, (uint32_t)iterations, derivedKey, (size_t)derivedKeyLen); *errorCode = result; return result == kCCSuccess ? 1 : 0; } diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keyderivation.h b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keyderivation.h index 7f02f0aa13c3..dfd06fd190b2 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keyderivation.h +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_keyderivation.h @@ -34,5 +34,5 @@ PALEXPORT int32_t AppleCryptoNative_Pbkdf2(PAL_HashAlgorithm prfAlgorithm, int32_t saltLen, int32_t iterations, uint8_t* derivedKey, - uint32_t derivedKeyLen, + int32_t derivedKeyLen, int32_t* errorCode); diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_signverify.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_signverify.c index 6e7c77e9d7d0..e7aac896311f 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_signverify.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_signverify.c @@ -16,7 +16,10 @@ static int32_t ExecuteSignTransform(SecTransformRef signer, CFDataRef* pSignatur assert(pErrorOut != NULL); int32_t ret = INT_MIN; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" CFTypeRef signerResponse = SecTransformExecute(signer, pErrorOut); +#pragma clang diagnostic pop CFDataRef signature = NULL; if (signerResponse == NULL || *pErrorOut != NULL) @@ -62,7 +65,10 @@ static int32_t ExecuteVerifyTransform(SecTransformRef verifier, CFErrorRef* pErr assert(pErrorOut != NULL); int32_t ret = kErrorSeeError; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" CFTypeRef verifierResponse = SecTransformExecute(verifier, pErrorOut); +#pragma clang diagnostic pop if (verifierResponse != NULL) { @@ -79,6 +85,8 @@ static int32_t ExecuteVerifyTransform(SecTransformRef verifier, CFErrorRef* pErr static int32_t ConfigureSignVerifyTransform(SecTransformRef xform, CFDataRef cfDataHash, CFErrorRef* pErrorOut) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" if (!SecTransformSetAttribute(xform, kSecInputIsAttributeName, kSecInputIsDigest, pErrorOut)) { return 0; @@ -88,13 +96,14 @@ static int32_t ConfigureSignVerifyTransform(SecTransformRef xform, CFDataRef cfD { return 0; } +#pragma clang diagnostic pop return 1; } #endif // Legacy algorithm identifiers -const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5 = CFSTR("algid:sign:RSA:digest-PKCS1v15:MD5"); +static const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5 = CFSTR("algid:sign:RSA:digest-PKCS1v15:MD5"); static CFStringRef GetSignatureAlgorithmIdentifier(PAL_HashAlgorithm hashAlgorithm, PAL_SignatureAlgorithm signatureAlgorithm) diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_ssl.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_ssl.c index d37f08ed14e2..2fba375bd423 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_ssl.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_ssl.c @@ -262,7 +262,7 @@ int32_t AppleCryptoNative_SSLSetALPNProtocol(SSLContextRef sslContext, void* pro // This is extra consistency check to verify that the ALPN data appeared where we expect them // before dereferencing sslContext - if (tls != NULL && tls->alpnOwnData.length == length + 1) + if (tls != NULL && tls->alpnOwnData.length == (size_t)length + 1) { tls->alpn_announced = 1; tls->alpn_received = 1 ; @@ -463,7 +463,11 @@ int32_t AppleCryptoNative_SslIsHostnameMatch(SSLContextRef sslContext, CFStringR for (CFIndex i = 0; i < certificateCount; i++) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" SecCertificateRef item = SecTrustGetCertificateAtIndex(existingTrust, i); +#pragma clang diagnostic pop + CFArrayAppendValue(certs, item); // Copy the EE cert into the anchors set, this will make the chain part @@ -696,10 +700,14 @@ PALEXPORT int32_t AppleCryptoNative_SslSetCertificateAuthorities(SSLContextRef s #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" // The underlying call handles NULL inputs, so just pass it through - return SSLSetCertificateAuthorities(sslContext, certificates, replaceExisting); + return SSLSetCertificateAuthorities(sslContext, certificates, replaceExisting > 0 ? 1 : 0); #pragma clang diagnostic pop #else + // ignore unused parameters + (void)sslContext; + (void)certificates; + (void)replaceExisting; return 0; #endif } diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509.c index 94e22f28c879..39b8e4619912 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509.c @@ -43,16 +43,7 @@ AppleCryptoNative_X509GetPublicKey(SecCertificateRef cert, SecKeyRef* pPublicKey if (cert == NULL || pPublicKeyOut == NULL) return kErrorUnknownState; - if (__builtin_available(macOS 10.14, iOS 12, tvOS 12, *)) - { - *pPublicKeyOut = SecCertificateCopyKey(cert); - } -#if defined(TARGET_IOS) || defined(TARGET_TVOS) - else - { - *pPublicKeyOut = SecCertificateCopyPublicKey(cert); - } -#endif + *pPublicKeyOut = SecCertificateCopyKey(cert); return 1; } diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509_ios.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509_ios.c index 8ffa1751e132..600ed61e0a56 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509_ios.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509_ios.c @@ -70,7 +70,10 @@ int32_t AppleCryptoNative_X509ImportCertificate(uint8_t* pbData, if (CFArrayGetCount(p12Items) > 0) { CFDictionaryRef item_dict = CFArrayGetValueAtIndex(p12Items, 0); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcast-qual" *pIdentityOut = (SecIdentityRef)CFRetain(CFDictionaryGetValue(item_dict, kSecImportItemIdentity)); +#pragma clang diagnostic pop } CFRelease(p12Items); } @@ -167,8 +170,11 @@ int32_t AppleCryptoNative_X509ImportCollection(uint8_t* pbData, for (int i = 0; i < CFArrayGetCount(p12Items); i++) { CFDictionaryRef item_dict = CFArrayGetValueAtIndex(p12Items, i); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcast-qual" SecIdentityRef identity = (SecIdentityRef)CFRetain(CFDictionaryGetValue(item_dict, kSecImportItemIdentity)); +#pragma clang diagnostic pop assert(identity != NULL); CFArrayAppendValue(outItems, identity); } @@ -179,4 +185,4 @@ int32_t AppleCryptoNative_X509ImportCollection(uint8_t* pbData, return status; } -} \ No newline at end of file +} diff --git a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509chain.c b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509chain.c index 152ed890ed6e..5f84bd898c3a 100644 --- a/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509chain.c +++ b/src/native/libs/System.Security.Cryptography.Native.Apple/pal_x509chain.c @@ -92,7 +92,10 @@ SecCertificateRef AppleCryptoNative_X509ChainGetCertificateAtIndex(SecTrustRef c if (chain == NULL || index < 0) return NULL; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return SecTrustGetCertificateAtIndex(chain, index); +#pragma clang diagnostic pop } CFArrayRef AppleCryptoNative_X509ChainGetTrustResults(SecTrustRef chain) @@ -204,7 +207,7 @@ static void MergeStatusCodes(CFTypeRef key, CFTypeRef value, void* context) #if defined DEBUG || defined DEBUGGING_UNKNOWN_VALUE CFIndex keyStringLength = CFStringGetLength(keyString); CFIndex maxEncodedLength = CFStringGetMaximumSizeForEncoding(keyStringLength, kCFStringEncodingUTF8) + 1; - char* keyStringBuffer = malloc(maxEncodedLength); + char* keyStringBuffer = malloc((size_t)maxEncodedLength); if (keyStringBuffer) { diff --git a/src/native/libs/System.Security.Cryptography.Native/configure.cmake b/src/native/libs/System.Security.Cryptography.Native/configure.cmake index 74ed49f5d191..ea779318c667 100644 --- a/src/native/libs/System.Security.Cryptography.Native/configure.cmake +++ b/src/native/libs/System.Security.Cryptography.Native/configure.cmake @@ -22,6 +22,11 @@ check_function_exists( HAVE_OPENSSL_SHA3 ) +check_function_exists( + EVP_DigestSqueeze + HAVE_OPENSSL_SHA3_SQUEEZE +) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/pal_crypto_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/pal_crypto_config.h) diff --git a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c index 0268221b428b..cb4b621e27fa 100644 --- a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c +++ b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c @@ -142,6 +142,7 @@ static const Entry s_cryptoNative[] = DllImportEntry(CryptoNative_EvpDigestFinalXOF) DllImportEntry(CryptoNative_EvpDigestOneShot) DllImportEntry(CryptoNative_EvpDigestReset) + DllImportEntry(CryptoNative_EvpDigestSqueeze) DllImportEntry(CryptoNative_EvpDigestUpdate) DllImportEntry(CryptoNative_EvpDigestXOFOneShot) DllImportEntry(CryptoNative_EvpMacFetch) @@ -155,6 +156,7 @@ static const Entry s_cryptoNative[] = DllImportEntry(CryptoNative_EvpMacOneShot) DllImportEntry(CryptoNative_EvpMacReset) DllImportEntry(CryptoNative_EvpMd5) + DllImportEntry(CryptoNative_EvpMdCtxCopyEx) DllImportEntry(CryptoNative_EvpMdCtxCreate) DllImportEntry(CryptoNative_EvpMdCtxDestroy) DllImportEntry(CryptoNative_EvpMdSize) @@ -310,6 +312,7 @@ static const Entry s_cryptoNative[] = DllImportEntry(CryptoNative_IsSslStateOK) DllImportEntry(CryptoNative_SslCtxAddExtraChainCert) DllImportEntry(CryptoNative_SslCtxSetCaching) + DllImportEntry(CryptoNative_SslCtxRemoveSession) DllImportEntry(CryptoNative_SslCtxSetCiphers) DllImportEntry(CryptoNative_SslCtxSetDefaultOcspCallback) DllImportEntry(CryptoNative_SslCtxSetEncryptionPolicy) diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.c b/src/native/libs/System.Security.Cryptography.Native/openssl.c index 9e57a8413ca3..227cef44faae 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.c @@ -627,8 +627,8 @@ BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32_t forIssue break; } - STACK_OF(GENERAL_NAME)* altNames = (STACK_OF(GENERAL_NAME)*)( - X509_get_ext_d2i(x509, forIssuer ? NID_issuer_alt_name : NID_subject_alt_name, NULL, NULL)); + GENERAL_NAMES* altNames = (GENERAL_NAMES*) + X509_get_ext_d2i(x509, forIssuer ? NID_issuer_alt_name : NID_subject_alt_name, NULL, NULL); if (altNames) { @@ -684,13 +684,13 @@ BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32_t forIssue { BIO* b = BIO_new(BIO_s_mem()); ASN1_STRING_print_ex(b, str, ASN1_STRFLGS_UTF8_CONVERT); - sk_GENERAL_NAME_free(altNames); + GENERAL_NAMES_free(altNames); return b; } } } - sk_GENERAL_NAME_free(altNames); + GENERAL_NAMES_free(altNames); } } diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h index b48d39de83cd..7837810de715 100644 --- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h @@ -178,6 +178,13 @@ const EVP_MD *EVP_shake256(void); int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len); #endif +#if !HAVE_OPENSSL_SHA3_SQUEEZE +#undef HAVE_OPENSSL_SHA3_SQUEEZE +#define HAVE_OPENSSL_SHA3_SQUEEZE 1 +int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen); +#endif + + #define API_EXISTS(fn) (fn != NULL) // List of all functions from the libssl that are used in the System.Security.Cryptography.Native. @@ -369,6 +376,7 @@ int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len); REQUIRED_FUNCTION(EVP_DigestFinal_ex) \ LIGHTUP_FUNCTION(EVP_DigestFinalXOF) \ REQUIRED_FUNCTION(EVP_DigestInit_ex) \ + LIGHTUP_FUNCTION(EVP_DigestSqueeze) \ REQUIRED_FUNCTION(EVP_DigestUpdate) \ REQUIRED_FUNCTION(EVP_get_digestbyname) \ LIGHTUP_FUNCTION(EVP_MAC_fetch) \ @@ -547,6 +555,7 @@ int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len); REQUIRED_FUNCTION(SSL_CTX_new) \ REQUIRED_FUNCTION(SSL_CTX_sess_set_new_cb) \ REQUIRED_FUNCTION(SSL_CTX_sess_set_remove_cb) \ + REQUIRED_FUNCTION(SSL_CTX_remove_session) \ LIGHTUP_FUNCTION(SSL_CTX_set_alpn_protos) \ LIGHTUP_FUNCTION(SSL_CTX_set_alpn_select_cb) \ REQUIRED_FUNCTION(SSL_CTX_set_cipher_list) \ @@ -895,6 +904,7 @@ FOR_ALL_OPENSSL_FUNCTIONS #define EVP_DigestFinal_ex EVP_DigestFinal_ex_ptr #define EVP_DigestFinalXOF EVP_DigestFinalXOF_ptr #define EVP_DigestInit_ex EVP_DigestInit_ex_ptr +#define EVP_DigestSqueeze EVP_DigestSqueeze_ptr #define EVP_DigestUpdate EVP_DigestUpdate_ptr #define EVP_get_digestbyname EVP_get_digestbyname_ptr #define EVP_md5 EVP_md5_ptr @@ -1074,6 +1084,7 @@ FOR_ALL_OPENSSL_FUNCTIONS #define SSL_CTX_new SSL_CTX_new_ptr #define SSL_CTX_sess_set_new_cb SSL_CTX_sess_set_new_cb_ptr #define SSL_CTX_sess_set_remove_cb SSL_CTX_sess_set_remove_cb_ptr +#define SSL_CTX_remove_session SSL_CTX_remove_session_ptr #define SSL_CTX_set_alpn_protos SSL_CTX_set_alpn_protos_ptr #define SSL_CTX_set_alpn_select_cb SSL_CTX_set_alpn_select_cb_ptr #define SSL_CTX_set_cipher_list SSL_CTX_set_cipher_list_ptr diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_crypto_config.h.in b/src/native/libs/System.Security.Cryptography.Native/pal_crypto_config.h.in index d7aef5a7d1b6..c216e88e272e 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_crypto_config.h.in +++ b/src/native/libs/System.Security.Cryptography.Native/pal_crypto_config.h.in @@ -4,3 +4,4 @@ #cmakedefine01 HAVE_OPENSSL_ALPN #cmakedefine01 HAVE_OPENSSL_CHACHA20POLY1305 #cmakedefine01 HAVE_OPENSSL_SHA3 +#cmakedefine01 HAVE_OPENSSL_SHA3_SQUEEZE diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp.c b/src/native/libs/System.Security.Cryptography.Native/pal_evp.c index 7559b4c1970b..1fcb0fc0058c 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp.c @@ -143,7 +143,7 @@ int32_t CryptoNative_EvpDigestFinalXOF(EVP_MD_CTX* ctx, uint8_t* md, uint32_t le return 0; } -static EVP_MD_CTX* EvpDup(const EVP_MD_CTX* ctx) +EVP_MD_CTX* CryptoNative_EvpMdCtxCopyEx(const EVP_MD_CTX* ctx) { if (ctx == NULL) { @@ -174,7 +174,7 @@ int32_t CryptoNative_EvpDigestCurrent(const EVP_MD_CTX* ctx, uint8_t* md, uint32 { ERR_clear_error(); - EVP_MD_CTX* dup = EvpDup(ctx); + EVP_MD_CTX* dup = CryptoNative_EvpMdCtxCopyEx(ctx); if (dup != NULL) { @@ -190,7 +190,7 @@ int32_t CryptoNative_EvpDigestCurrentXOF(const EVP_MD_CTX* ctx, uint8_t* md, uin { ERR_clear_error(); - EVP_MD_CTX* dup = EvpDup(ctx); + EVP_MD_CTX* dup = CryptoNative_EvpMdCtxCopyEx(ctx); if (dup != NULL) { @@ -262,6 +262,29 @@ int32_t CryptoNative_EvpDigestXOFOneShot(const EVP_MD* type, const void* source, return ret; } +int32_t CryptoNative_EvpDigestSqueeze(EVP_MD_CTX* ctx, uint8_t* md, uint32_t len, int32_t* haveFeature) +{ + ERR_clear_error(); + + if (ctx == NULL || haveFeature == NULL || (md == NULL && len > 0)) + { + return 0; + } + + *haveFeature = 0; + int32_t ret = 0; + +#if HAVE_OPENSSL_SHA3_SQUEEZE + if (API_EXISTS(EVP_DigestSqueeze)) + { + *haveFeature = 1; + ret = EVP_DigestSqueeze(ctx, md, (size_t)len); + } +#endif + + return ret; +} + int32_t CryptoNative_EvpMdSize(const EVP_MD* md) { // No error queue impact. diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp.h b/src/native/libs/System.Security.Cryptography.Native/pal_evp.h index f31521ff0e6d..5d8460c7b7d0 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp.h +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp.h @@ -89,6 +89,14 @@ Combines EVP_MD_CTX_create, EVP_DigestUpdate, and EVP_DigestFinalXOF in to a sin */ PALEXPORT int32_t CryptoNative_EvpDigestXOFOneShot(const EVP_MD* type, const void* source, int32_t sourceSize, uint8_t* md, uint32_t len); +/* +Function: +EvpMdCtxCopyEx + +Creates a new EVP_MD_CTX and copies the ctx input using EVP_MD_CTX_copy_ex. Returns NULL on error. +*/ +PALEXPORT EVP_MD_CTX* CryptoNative_EvpMdCtxCopyEx(const EVP_MD_CTX* ctx); + /* Function: EvpMdSize @@ -97,6 +105,15 @@ Direct shim to EVP_MD_size. */ PALEXPORT int32_t CryptoNative_EvpMdSize(const EVP_MD* md); +/* +Function: +EvpDigestSqueeze + +Calls EVP_DigestSqueeze. If the function is not available, haveFeature is set to zero and the return value should +be ignored. If the function is available, haveFeature is set to one and the operation result is returned. +*/ +PALEXPORT int32_t CryptoNative_EvpDigestSqueeze(EVP_MD_CTX* ctx, uint8_t* md, uint32_t len, int32_t* haveFeature); + /* Function: EvpMd5 diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c index e6bd41143c16..e320d1c73d77 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c @@ -701,6 +701,11 @@ int CryptoNative_SslCtxSetCaching(SSL_CTX* ctx, int mode, int cacheSize, int con return retValue; } +int CryptoNative_SslCtxRemoveSession(SSL_CTX* ctx, SSL_SESSION* session) +{ + return SSL_CTX_remove_session(ctx, session); +} + const char* CryptoNative_SslGetServerName(SSL* ssl) { return SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h index 3c63564cc4e5..9c9d7026119c 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h @@ -167,6 +167,11 @@ Sets session caching. 0 is disabled. */ PALEXPORT int CryptoNative_SslCtxSetCaching(SSL_CTX* ctx, int mode, int cacheSize, int contextIdLength, uint8_t* contextId, SslCtxNewSessionCallback newSessionCb, SslCtxRemoveSessionCallback removeSessionCb); +/* +Removes a session from internal cache. +*/ +PALEXPORT int CryptoNative_SslCtxRemoveSession(SSL_CTX* ctx, SSL_SESSION* session); + /* Sets callback to log TLS session keys */ diff --git a/src/native/libs/build-native.sh b/src/native/libs/build-native.sh index e0f43011d970..0df282082ec7 100755 --- a/src/native/libs/build-native.sh +++ b/src/native/libs/build-native.sh @@ -112,7 +112,7 @@ elif [[ "$__TargetOS" == linux-bionic && -z "$ROOTFS_DIR" ]]; then elif [[ "$__TargetOS" == iossimulator ]]; then # set default iOS simulator deployment target # keep in sync with SetOSTargetMinVersions in the root Directory.Build.props - __CMakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $__CMakeArgs" + __CMakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $__CMakeArgs" if [[ "$__TargetArch" == x64 ]]; then __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"x86_64\" $__CMakeArgs" elif [[ "$__TargetArch" == x86 ]]; then @@ -126,7 +126,7 @@ elif [[ "$__TargetOS" == iossimulator ]]; then elif [[ "$__TargetOS" == ios ]]; then # set default iOS device deployment target # keep in sync with SetOSTargetMinVersions in the root Directory.Build.props - __CMakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $__CMakeArgs" + __CMakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $__CMakeArgs" if [[ "$__TargetArch" == arm64 ]]; then __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"arm64\" $__CMakeArgs" elif [[ "$__TargetArch" == arm ]]; then @@ -138,7 +138,7 @@ elif [[ "$__TargetOS" == ios ]]; then elif [[ "$__TargetOS" == tvossimulator ]]; then # set default tvOS simulator deployment target # keep in sync with SetOSTargetMinVersions in the root Directory.Build.props - __CMakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $__CMakeArgs" + __CMakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $__CMakeArgs" if [[ "$__TargetArch" == x64 ]]; then __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"x86_64\" $__CMakeArgs" elif [[ "$__TargetArch" == arm64 ]]; then @@ -150,7 +150,7 @@ elif [[ "$__TargetOS" == tvossimulator ]]; then elif [[ "$__TargetOS" == tvos ]]; then # set default tvOS device deployment target # keep in sync with the root Directory.Build.props - __CMakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 $__CMakeArgs" + __CMakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2 $__CMakeArgs" if [[ "$__TargetArch" == arm64 ]]; then __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"arm64\" $__CMakeArgs" else diff --git a/src/native/libs/configure.cmake b/src/native/libs/configure.cmake index 42502a34b4ef..bba930e0c007 100644 --- a/src/native/libs/configure.cmake +++ b/src/native/libs/configure.cmake @@ -13,6 +13,7 @@ if (CLR_CMAKE_TARGET_OSX) # Xcode's clang does not include /usr/local/include by default, but brew's does. # This ensures an even playing field. include_directories(SYSTEM /usr/local/include) + add_compile_options(-Wno-poison-system-directories) elseif (CLR_CMAKE_TARGET_FREEBSD) include_directories(SYSTEM ${CROSS_ROOTFS}/usr/local/include) set(CMAKE_REQUIRED_INCLUDES ${CROSS_ROOTFS}/usr/local/include) @@ -33,7 +34,7 @@ endif() # which are not distinguished from the test failing. So no error for that one. # For clang-5.0 avoid errors like "unused variable 'err' [-Werror,-Wunused-variable]". set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror -Wno-error=unused-value -Wno-error=unused-variable") -if (CMAKE_C_COMPILER_ID STREQUAL "Clang") +if (CMAKE_C_COMPILER_ID MATCHES "Clang") set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Wno-error=builtin-requires-header") endif() @@ -500,6 +501,10 @@ check_include_files( "sys/proc_info.h" HAVE_SYS_PROCINFO_H) +check_include_files( + "time.h;linux/errqueue.h" + HAVE_LINUX_ERRQUEUE_H) + check_symbol_exists( epoll_create1 sys/epoll.h diff --git a/src/native/managed/cdacreader/inc/cdac_reader.h b/src/native/managed/cdacreader/inc/cdac_reader.h index b6c71b671a6e..505dab92815d 100644 --- a/src/native/managed/cdacreader/inc/cdac_reader.h +++ b/src/native/managed/cdacreader/inc/cdac_reader.h @@ -9,8 +9,20 @@ extern "C" { #endif -int cdac_reader_init(intptr_t descriptor, intptr_t* handle); +// Initialize the cDAC reader +// descriptor: the address of the descriptor in the target process +// read_from_target: a callback that reads memory from the target process +// read_context: a context pointer that will be passed to read_from_target +// handle: returned opaque the handle to the reader. This should be passed to other functions in this API. +int cdac_reader_init(uint64_t descriptor, int(*read_from_target)(uint64_t, uint8_t*, uint32_t, void*), void* read_context, /*out*/ intptr_t* handle); + +// Free the cDAC reader +// handle: handle to the reader int cdac_reader_free(intptr_t handle); + +// Get the SOS interface from the cDAC reader +// handle: handle to the reader +// obj: returned SOS interface that can be QI'd to ISOSDacInterface* int cdac_reader_get_sos_interface(intptr_t handle, IUnknown** obj); #ifdef __cplusplus diff --git a/src/native/managed/cdacreader/src/Constants.cs b/src/native/managed/cdacreader/src/Constants.cs new file mode 100644 index 000000000000..a4874ce179e1 --- /dev/null +++ b/src/native/managed/cdacreader/src/Constants.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader; + +internal static class Constants +{ + internal static class Globals + { + // See src/coreclr/debug/runtimeinfo/datadescriptor.h + internal const string ThreadStore = nameof(ThreadStore); + internal const string SOSBreakingChangeVersion = nameof(SOSBreakingChangeVersion); + } +} diff --git a/src/native/managed/cdacreader/src/ContractDescriptorParser.cs b/src/native/managed/cdacreader/src/ContractDescriptorParser.cs new file mode 100644 index 000000000000..a82235731e4a --- /dev/null +++ b/src/native/managed/cdacreader/src/ContractDescriptorParser.cs @@ -0,0 +1,342 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Contracts; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.Diagnostics.DataContractReader; + +/// +/// A parser for the JSON representation of a contract descriptor. +/// +/// +/// See design doc for the format. +/// +public partial class ContractDescriptorParser +{ + // data_descriptor.md uses a distinguished property name to indicate the size of a type + public const string TypeDescriptorSizeSigil = "!"; + + /// + /// Parses the "compact" representation of a contract descriptor. + /// + // Workaround for https://github.com/dotnet/runtime/issues/101205 + [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Root))] + public static ContractDescriptor? ParseCompact(ReadOnlySpan json) + { + return JsonSerializer.Deserialize(json, ContractDescriptorContext.Default.ContractDescriptor); + } + + [JsonSerializable(typeof(ContractDescriptor))] + [JsonSerializable(typeof(int?))] + [JsonSerializable(typeof(string))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(TypeDescriptor))] + [JsonSerializable(typeof(FieldDescriptor))] + [JsonSerializable(typeof(GlobalDescriptor))] + [JsonSerializable(typeof(Dictionary))] + [JsonSourceGenerationOptions(AllowTrailingCommas = true, + DictionaryKeyPolicy = JsonKnownNamingPolicy.Unspecified, // contracts, types and globals are case sensitive + PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, + NumberHandling = JsonNumberHandling.AllowReadingFromString, + ReadCommentHandling = JsonCommentHandling.Skip, + UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip, + UnknownTypeHandling = JsonUnknownTypeHandling.JsonElement, + Converters = [typeof(TypeDescriptorConverter), + typeof(FieldDescriptorConverter), + typeof(GlobalDescriptorConverter)])] + internal sealed partial class ContractDescriptorContext : JsonSerializerContext + { + } + + public class ContractDescriptor + { + public int? Version { get; set; } + public string? Baseline { get; set; } + public Dictionary? Contracts { get; set; } + + public Dictionary? Types { get; set; } + + public Dictionary? Globals { get; set; } + + [JsonExtensionData] + public Dictionary? Extras { get; set; } + + public override string ToString() + { + return $"Version: {Version}, Baseline: {Baseline}, Contracts: {Contracts?.Count}, Types: {Types?.Count}, Globals: {Globals?.Count}"; + } + + } + + [JsonConverter(typeof(TypeDescriptorConverter))] + public class TypeDescriptor + { + public uint? Size { get; set; } + public Dictionary? Fields { get; set; } + } + + [JsonConverter(typeof(FieldDescriptorConverter))] + public class FieldDescriptor + { + public string? Type { get; set; } + public int Offset { get; set; } + } + + [JsonConverter(typeof(GlobalDescriptorConverter))] + public class GlobalDescriptor + { + public string? Type { get; set; } + public ulong Value { get; set; } + public bool Indirect { get; set; } + } + + internal sealed class TypeDescriptorConverter : JsonConverter + { + // Almost a normal dictionary converter except: + // 1. looks for a special key "!" to set the Size property + // 2. field names are property names, but treated case-sensitively + public override TypeDescriptor Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType != JsonTokenType.StartObject) + throw new JsonException(); + uint? size = null; + Dictionary? fields = new(); + while (reader.Read()) + { + switch (reader.TokenType) + { + case JsonTokenType.EndObject: + return new TypeDescriptor { Size = size, Fields = fields }; + case JsonTokenType.PropertyName: + string? fieldNameOrSizeSigil = reader.GetString(); + reader.Read(); // read the next value: either a number or a field descriptor + if (fieldNameOrSizeSigil == TypeDescriptorSizeSigil) + { + uint newSize = reader.GetUInt32(); + if (size is not null) + { + throw new JsonException($"Size specified multiple times: {size} and {newSize}"); + } + size = newSize; + } + else + { + string? fieldName = fieldNameOrSizeSigil; + var field = JsonSerializer.Deserialize(ref reader, ContractDescriptorContext.Default.FieldDescriptor); + if (fieldName is null || field is null) + throw new JsonException(); + if (!fields.TryAdd(fieldName, field)) + { + throw new JsonException($"Duplicate field name: {fieldName}"); + } + } + break; + case JsonTokenType.Comment: + // unexpected - we specified to skip comments. but let's ignore anyway + break; + default: + throw new JsonException(); + } + } + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, TypeDescriptor value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + } + + internal sealed class FieldDescriptorConverter : JsonConverter + { + // Compact Field descriptors are either a number or a two element array + // 1. number - no type, offset is given as the number + // 2. [number, string] - offset is given as the number, type name is given as the string + public override FieldDescriptor Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (TryGetInt32FromToken(ref reader, out int offset)) + return new FieldDescriptor { Offset = offset }; + if (reader.TokenType != JsonTokenType.StartArray) + throw new JsonException(); + reader.Read(); + // [number, string] + // ^ we're here + if (!TryGetInt32FromToken(ref reader, out offset)) + throw new JsonException(); + reader.Read(); // string + if (reader.TokenType != JsonTokenType.String) + throw new JsonException(); + string? type = reader.GetString(); + reader.Read(); // end of array + if (reader.TokenType != JsonTokenType.EndArray) + throw new JsonException(); + return new FieldDescriptor { Type = type, Offset = offset }; + } + + public override void Write(Utf8JsonWriter writer, FieldDescriptor value, JsonSerializerOptions options) + { + throw new JsonException(); + } + } + + internal sealed class GlobalDescriptorConverter : JsonConverter + { + public override GlobalDescriptor Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + // four cases: + // 1. number - no type, direct value, given value + // 2. [number] - no type, indirect value, given aux data ptr + // 3. [number, string] - type, direct value, given value + // 4. [[number], string] - type, indirect value, given aux data ptr + + // Case 1: number + if (TryGetUInt64FromToken(ref reader, out ulong valueCase1)) + return new GlobalDescriptor { Value = valueCase1 }; + if (reader.TokenType != JsonTokenType.StartArray) + throw new JsonException(); + reader.Read(); + // we're in case 2 or 3 or 4: + // case 2: [number] + // ^ we're here + // case 3: [number, string] + // ^ we're here + // case 4: [[number], string] + // ^ we're here + if (TryGetUInt64FromToken(ref reader, out ulong valueCase2or3)) + { + // case 2 or 3 + // case 2: [number] + // ^ we're here + // case 3: [number, string] + // ^ we're here + reader.Read(); // end of array (case 2) or string (case 3) + if (reader.TokenType == JsonTokenType.EndArray) // it was case 2 + { + return new GlobalDescriptor { Value = valueCase2or3, Indirect = true }; + } + if (reader.TokenType == JsonTokenType.String) // it was case 3 + { + string? type = reader.GetString(); + reader.Read(); // end of array for case 3 + if (reader.TokenType != JsonTokenType.EndArray) + throw new JsonException(); + return new GlobalDescriptor { Type = type, Value = valueCase2or3 }; + } + throw new JsonException(); + } + if (reader.TokenType == JsonTokenType.StartArray) + { + // case 4: [[number], string] + // ^ we're here + reader.Read(); // number + if (!TryGetUInt64FromToken(ref reader, out ulong value)) + throw new JsonException(); + reader.Read(); // end of inner array + if (reader.TokenType != JsonTokenType.EndArray) + throw new JsonException(); + reader.Read(); // string + if (reader.TokenType != JsonTokenType.String) + throw new JsonException(); + string? type = reader.GetString(); + reader.Read(); // end of outer array + if (reader.TokenType != JsonTokenType.EndArray) + throw new JsonException(); + return new GlobalDescriptor { Type = type, Value = value, Indirect = true }; + } + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, GlobalDescriptor value, JsonSerializerOptions options) + { + throw new JsonException(); + } + } + + // Somewhat flexible parsing of numbers, allowing json number tokens or strings as decimal or hex, possibly negatated. + private static bool TryGetUInt64FromToken(ref Utf8JsonReader reader, out ulong value) + { + if (reader.TokenType == JsonTokenType.Number) + { + if (reader.TryGetUInt64(out value)) + return true; + if (reader.TryGetInt64(out long signedValue)) + { + value = (ulong)signedValue; + return true; + } + } + if (reader.TokenType == JsonTokenType.String) + { + var s = reader.GetString(); + if (s == null) + { + value = 0u; + return false; + } + if (ulong.TryParse(s, out value)) + return true; + if (long.TryParse(s, out long signedValue)) + { + value = (ulong)signedValue; + return true; + } + if (s.StartsWith("0x", StringComparison.OrdinalIgnoreCase) && + ulong.TryParse(s.AsSpan(2), System.Globalization.NumberStyles.HexNumber, null, out value)) + { + return true; + } + if (s.StartsWith("-0x", StringComparison.OrdinalIgnoreCase) && + ulong.TryParse(s.AsSpan(3), System.Globalization.NumberStyles.HexNumber, null, out ulong negValue)) + { + value = ~negValue + 1; // two's complement + return true; + } + } + value = 0; + return false; + } + + // Somewhat flexible parsing of numbers, allowing json number tokens or strings as either decimal or hex, possibly negated + private static bool TryGetInt32FromToken(ref Utf8JsonReader reader, out int value) + { + if (reader.TokenType == JsonTokenType.Number) + { + value = reader.GetInt32(); + return true; + } + if (reader.TokenType == JsonTokenType.String) + { + var s = reader.GetString(); + if (s == null) + { + value = 0; + return false; + } + if (int.TryParse(s, out value)) + { + return true; + } + if (s.StartsWith("0x", StringComparison.OrdinalIgnoreCase) && + int.TryParse(s.AsSpan(2), System.Globalization.NumberStyles.HexNumber, null, out value)) + { + return true; + } + if (s.StartsWith("-0x", StringComparison.OrdinalIgnoreCase) && + int.TryParse(s.AsSpan(3), System.Globalization.NumberStyles.HexNumber, null, out int negValue)) + { + value = -negValue; + return true; + } + } + value = 0; + return false; + } +} diff --git a/src/native/managed/cdacreader/src/Contracts/IContract.cs b/src/native/managed/cdacreader/src/Contracts/IContract.cs new file mode 100644 index 000000000000..1a78ce2a4292 --- /dev/null +++ b/src/native/managed/cdacreader/src/Contracts/IContract.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.Diagnostics.DataContractReader.Contracts; + +internal interface IContract +{ + static virtual string Name => throw new NotImplementedException(); + static virtual IContract Create(Target target, int version) => throw new NotImplementedException(); +} diff --git a/src/native/managed/cdacreader/src/Contracts/Registry.cs b/src/native/managed/cdacreader/src/Contracts/Registry.cs new file mode 100644 index 000000000000..aad64ce52718 --- /dev/null +++ b/src/native/managed/cdacreader/src/Contracts/Registry.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; + +namespace Microsoft.Diagnostics.DataContractReader.Contracts; + +internal sealed class Registry +{ + // Contracts that have already been created for a target. + // Items should not be removed from this, only added. + private readonly Dictionary _contracts = []; + private readonly Target _target; + + public Registry(Target target) + { + _target = target; + } + + public IThread Thread => GetContract(); + + private T GetContract() where T : IContract + { + if (_contracts.TryGetValue(typeof(T), out IContract? contractMaybe)) + return (T)contractMaybe; + + if (!_target.TryGetContractVersion(T.Name, out int version)) + throw new NotImplementedException(); + + // Create and register the contract + IContract contract = T.Create(_target, version); + if (_contracts.TryAdd(typeof(T), contract)) + return (T)contract; + + // Contract was already registered by someone else + return (T)_contracts[typeof(T)]; + } +} diff --git a/src/native/managed/cdacreader/src/Contracts/Thread.cs b/src/native/managed/cdacreader/src/Contracts/Thread.cs new file mode 100644 index 000000000000..30187567fe56 --- /dev/null +++ b/src/native/managed/cdacreader/src/Contracts/Thread.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.Diagnostics.DataContractReader.Contracts; + +// TODO: [cdac] Add other counts / threads +internal record struct ThreadStoreData( + int ThreadCount, + TargetPointer FirstThread); + +internal interface IThread : IContract +{ + static string IContract.Name { get; } = nameof(Thread); + static IContract IContract.Create(Target target, int version) + { + TargetPointer threadStore = target.ReadGlobalPointer(Constants.Globals.ThreadStore); + return version switch + { + 1 => new Thread_1(target, threadStore), + _ => default(Thread), + }; + } + + public virtual ThreadStoreData GetThreadStoreData() => throw new NotImplementedException(); +} + +internal readonly struct Thread : IThread +{ + // Everything throws NotImplementedException +} + +internal readonly struct Thread_1 : IThread +{ + private readonly Target _target; + private readonly TargetPointer _threadStoreAddr; + + internal Thread_1(Target target, TargetPointer threadStore) + { + _target = target; + _threadStoreAddr = threadStore; + } + + ThreadStoreData IThread.GetThreadStoreData() + { + Data.ThreadStore? threadStore; + if (!_target.ProcessedData.TryGet(_threadStoreAddr.Value, out threadStore)) + { + threadStore = new Data.ThreadStore(_target, _threadStoreAddr); + + // Still okay if processed data is already registered by someone else + _ = _target.ProcessedData.TryRegister(_threadStoreAddr.Value, threadStore); + } + + return new ThreadStoreData(threadStore.ThreadCount, threadStore.FirstThread); + } +} diff --git a/src/native/managed/cdacreader/src/Data/ThreadStore.cs b/src/native/managed/cdacreader/src/Data/ThreadStore.cs new file mode 100644 index 000000000000..1ba13596359b --- /dev/null +++ b/src/native/managed/cdacreader/src/Data/ThreadStore.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +internal sealed class ThreadStore +{ + public ThreadStore(Target target, TargetPointer pointer) + { + Target.TypeInfo type = target.GetTypeInfo(DataType.ThreadStore); + TargetPointer addr = target.ReadPointer(pointer.Value); + + ThreadCount = target.Read(addr.Value + (ulong)type.Fields[nameof(ThreadCount)].Offset); + FirstThread = TargetPointer.Null; + } + + public int ThreadCount { get; init; } + + public TargetPointer FirstThread { get; init; } +} diff --git a/src/native/managed/cdacreader/src/DataType.cs b/src/native/managed/cdacreader/src/DataType.cs new file mode 100644 index 000000000000..c301c6a008d7 --- /dev/null +++ b/src/native/managed/cdacreader/src/DataType.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader; + +public enum DataType +{ + Unknown = 0, + + int8, + uint8, + int16, + uint16, + int32, + uint32, + int64, + uint64, + nint, + nuint, + pointer, + + GCHandle, + Thread, + ThreadStore, +} diff --git a/src/native/managed/cdacreader/src/Entrypoints.cs b/src/native/managed/cdacreader/src/Entrypoints.cs index a65ba9c5fa5e..908d534fe60c 100644 --- a/src/native/managed/cdacreader/src/Entrypoints.cs +++ b/src/native/managed/cdacreader/src/Entrypoints.cs @@ -12,9 +12,12 @@ internal static class Entrypoints private const string CDAC = "cdac_reader_"; [UnmanagedCallersOnly(EntryPoint = $"{CDAC}init")] - private static unsafe int Init(nint descriptor, IntPtr* handle) + private static unsafe int Init(ulong descriptor, delegate* unmanaged readFromTarget, void* readContext, IntPtr* handle) { - Target target = new(descriptor); + // TODO: [cdac] Better error code/details + if (!Target.TryCreate(descriptor, readFromTarget, readContext, out Target? target)) + return -1; + GCHandle gcHandle = GCHandle.Alloc(target); *handle = GCHandle.ToIntPtr(gcHandle); return 0; @@ -42,7 +45,7 @@ private static unsafe int GetSOSInterface(IntPtr handle, nint* obj) if (target == null) return -1; - SOSDacImpl impl = new(target); + Legacy.SOSDacImpl impl = new(target); nint ptr = cw.GetOrCreateComInterfaceForObject(impl, CreateComInterfaceFlags.None); *obj = ptr; return 0; diff --git a/src/native/managed/cdacreader/src/Legacy/ISOSDacInterface.cs b/src/native/managed/cdacreader/src/Legacy/ISOSDacInterface.cs new file mode 100644 index 000000000000..bd0d20e65b77 --- /dev/null +++ b/src/native/managed/cdacreader/src/Legacy/ISOSDacInterface.cs @@ -0,0 +1,293 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +namespace Microsoft.Diagnostics.DataContractReader.Legacy; + +// This file contains managed declarations for the SOS-DAC interfaces. +// See src/coreclr/inc/sospriv.idl + +#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value +internal struct DacpThreadStoreData +{ + public int threadCount; + public int unstartedThreadCount; + public int backgroundThreadCount; + public int pendingThreadCount; + public int deadThreadCount; + public ulong firstThread; + public ulong finalizerThread; + public ulong gcThread; + public int fHostConfig; // Uses hosting flags defined above +}; + +internal struct DacpThreadData +{ + public int corThreadId; + public int osThreadId; + public int state; + public uint preemptiveGCDisabled; + public ulong allocContextPtr; + public ulong allocContextLimit; + public ulong context; + public ulong domain; + public ulong pFrame; + public int lockCount; + public ulong firstNestedException; // Pass this pointer to DacpNestedExceptionInfo + public ulong teb; + public ulong fiberData; + public ulong lastThrownObjectHandle; + public ulong nextThread; +} +#pragma warning restore CS0649 // Field is never assigned to, and will always have its default value + +[GeneratedComInterface] +[Guid("436f00f2-b42a-4b9f-870c-e73db66ae930")] +internal unsafe partial interface ISOSDacInterface +{ + // All functions are explicitly PreserveSig so that we can just return E_NOTIMPL instead of throwing + // as the cDAC slowly replaces parts of the DAC. + + // ThreadStore + [PreserveSig] + int GetThreadStoreData(DacpThreadStoreData* data); + + // AppDomains + [PreserveSig] + int GetAppDomainStoreData(/*struct DacpAppDomainStoreData*/ void* data); + [PreserveSig] + int GetAppDomainList(uint count, [In, Out, MarshalUsing(CountElementName = nameof(count))] ulong[] values, uint* pNeeded); + [PreserveSig] + int GetAppDomainData(ulong addr, /*struct DacpAppDomainData*/ void* data); + [PreserveSig] + int GetAppDomainName(ulong addr, uint count, char* name, uint* pNeeded); + [PreserveSig] + int GetDomainFromContext(ulong context, ulong* domain); + + // Assemblies + [PreserveSig] + int GetAssemblyList(ulong appDomain, int count, [In, Out, MarshalUsing(CountElementName = nameof(count))] ulong[] values, int* pNeeded); + [PreserveSig] + int GetAssemblyData(ulong baseDomainPtr, ulong assembly, /*struct DacpAssemblyData*/ void* data); + [PreserveSig] + int GetAssemblyName(ulong assembly, uint count, char* name, uint* pNeeded); + + // Modules + [PreserveSig] + int GetModule(ulong addr, /*IXCLRDataModule*/ void** mod); + [PreserveSig] + int GetModuleData(ulong moduleAddr, /*struct DacpModuleData*/ void* data); + [PreserveSig] + int TraverseModuleMap(/*ModuleMapType*/ int mmt, ulong moduleAddr, /*MODULEMAPTRAVERSE*/ void* pCallback, void* token); + [PreserveSig] + int GetAssemblyModuleList(ulong assembly, uint count, [In, Out, MarshalUsing(CountElementName = nameof(count))] ulong[] modules, uint* pNeeded); + [PreserveSig] + int GetILForModule(ulong moduleAddr, int rva, ulong* il); + + // Threads + [PreserveSig] + int GetThreadData(ulong thread, DacpThreadData *data); + [PreserveSig] + int GetThreadFromThinlockID(uint thinLockId, ulong* pThread); + [PreserveSig] + int GetStackLimits(ulong threadPtr, ulong* lower, ulong* upper, ulong* fp); + + // MethodDescs + [PreserveSig] + int GetMethodDescData(ulong methodDesc, ulong ip, /*struct DacpMethodDescData*/ void* data, uint cRevertedRejitVersions, /*struct DacpReJitData*/ void* rgRevertedRejitData, uint* pcNeededRevertedRejitData); + [PreserveSig] + int GetMethodDescPtrFromIP(ulong ip, ulong* ppMD); + [PreserveSig] + int GetMethodDescName(ulong methodDesc, uint count, char* name, uint* pNeeded); + [PreserveSig] + int GetMethodDescPtrFromFrame(ulong frameAddr, ulong* ppMD); + [PreserveSig] + int GetMethodDescFromToken(ulong moduleAddr, /*mdToken*/ uint token, ulong* methodDesc); + [PreserveSig] + int GetMethodDescTransparencyData(ulong methodDesc, /*struct DacpMethodDescTransparencyData*/ void* data); + + // JIT Data + [PreserveSig] + int GetCodeHeaderData(ulong ip, /*struct DacpCodeHeaderData*/ void* data); + [PreserveSig] + int GetJitManagerList(uint count, /*struct DacpJitManagerInfo*/ void* managers, uint* pNeeded); + [PreserveSig] + int GetJitHelperFunctionName(ulong ip, uint count, byte* name, uint* pNeeded); + [PreserveSig] + int GetJumpThunkTarget(/*T_CONTEXT*/void* ctx, ulong* targetIP, ulong* targetMD); + + // ThreadPool + [PreserveSig] + int GetThreadpoolData(/*struct DacpThreadpoolData*/ void* data); + [PreserveSig] + int GetWorkRequestData(ulong addrWorkRequest, /*struct DacpWorkRequestData*/ void* data); + [PreserveSig] + int GetHillClimbingLogEntry(ulong addr, /*struct DacpHillClimbingLogEntry*/ void* data); + + // Objects + [PreserveSig] + int GetObjectData(ulong objAddr, /*struct DacpObjectData*/ void* data); + [PreserveSig] + int GetObjectStringData(ulong obj, uint count, char* stringData, uint* pNeeded); + [PreserveSig] + int GetObjectClassName(ulong obj, uint count, char* className, uint* pNeeded); + + // MethodTable + [PreserveSig] + int GetMethodTableName(ulong mt, uint count, char* mtName, uint* pNeeded); + [PreserveSig] + int GetMethodTableData(ulong mt, /*struct DacpMethodTableData*/ void* data); + [PreserveSig] + int GetMethodTableSlot(ulong mt, uint slot, ulong* value); + [PreserveSig] + int GetMethodTableFieldData(ulong mt, /*struct DacpMethodTableFieldData*/ void* data); + [PreserveSig] + int GetMethodTableTransparencyData(ulong mt, /*struct DacpMethodTableTransparencyData*/ void* data); + + // EEClass + [PreserveSig] + int GetMethodTableForEEClass(ulong eeClass, ulong* value); + + // FieldDesc + [PreserveSig] + int GetFieldDescData(ulong fieldDesc, /*struct DacpFieldDescData*/ void* data); + + // Frames + [PreserveSig] + int GetFrameName(ulong vtable, uint count, char* frameName, uint* pNeeded); + + // PEFiles + [PreserveSig] + int GetPEFileBase(ulong addr, ulong* peBase); + [PreserveSig] + int GetPEFileName(ulong addr, uint count, char* fileName, uint* pNeeded); + + // GC + [PreserveSig] + int GetGCHeapData(/*struct DacpGcHeapData*/ void* data); + [PreserveSig] + int GetGCHeapList(uint count, [In, Out, MarshalUsing(CountElementName = nameof(count))] ulong[] heaps, uint* pNeeded); // svr only + [PreserveSig] + int GetGCHeapDetails(ulong heap, /*struct DacpGcHeapDetails */ void* details); // wks only + [PreserveSig] + int GetGCHeapStaticData(/*struct DacpGcHeapDetails */ void* data); + [PreserveSig] + int GetHeapSegmentData(ulong seg, /*struct DacpHeapSegmentData */ void* data); + [PreserveSig] + int GetOOMData(ulong oomAddr, /*struct DacpOomData */ void* data); + [PreserveSig] + int GetOOMStaticData(/*struct DacpOomData */ void* data); + [PreserveSig] + int GetHeapAnalyzeData(ulong addr, /*struct DacpGcHeapAnalyzeData */ void* data); + [PreserveSig] + int GetHeapAnalyzeStaticData(/*struct DacpGcHeapAnalyzeData */ void* data); + + // DomainLocal + [PreserveSig] + int GetDomainLocalModuleData(ulong addr, /*struct DacpDomainLocalModuleData */ void* data); + [PreserveSig] + int GetDomainLocalModuleDataFromAppDomain(ulong appDomainAddr, int moduleID, /*struct DacpDomainLocalModuleData */ void* data); + [PreserveSig] + int GetDomainLocalModuleDataFromModule(ulong moduleAddr, /*struct DacpDomainLocalModuleData */ void* data); + + // ThreadLocal + [PreserveSig] + int GetThreadLocalModuleData(ulong thread, uint index, /*struct DacpThreadLocalModuleData */ void* data); + + // SyncBlock + [PreserveSig] + int GetSyncBlockData(uint number, /*struct DacpSyncBlockData */ void* data); + [PreserveSig] + int GetSyncBlockCleanupData(ulong addr, /*struct DacpSyncBlockCleanupData */ void* data); + + // Handles + [PreserveSig] + int GetHandleEnum(/*ISOSHandleEnum*/ void** ppHandleEnum); + [PreserveSig] + int GetHandleEnumForTypes([In, MarshalUsing(CountElementName = nameof(count))] uint[] types, uint count, /*ISOSHandleEnum*/ void** ppHandleEnum); + [PreserveSig] + int GetHandleEnumForGC(uint gen, /*ISOSHandleEnum*/ void** ppHandleEnum); + + // EH + [PreserveSig] + int TraverseEHInfo(ulong ip, /*DUMPEHINFO*/ void* pCallback, void* token); + [PreserveSig] + int GetNestedExceptionData(ulong exception, ulong* exceptionObject, ulong* nextNestedException); + + // StressLog + [PreserveSig] + int GetStressLogAddress(ulong* stressLog); + + // Heaps + [PreserveSig] + int TraverseLoaderHeap(ulong loaderHeapAddr, /*VISITHEAP*/ void* pCallback); + [PreserveSig] + int GetCodeHeapList(ulong jitManager, uint count, /*struct DacpJitCodeHeapInfo*/ void* codeHeaps, uint* pNeeded); + [PreserveSig] + int TraverseVirtCallStubHeap(ulong pAppDomain, /*VCSHeapType*/ int heaptype, /*VISITHEAP*/ void* pCallback); + + // Other + [PreserveSig] + int GetUsefulGlobals(/*struct DacpUsefulGlobalsData */ void* data); + [PreserveSig] + int GetClrWatsonBuckets(ulong thread, void* pGenericModeBlock); + [PreserveSig] + int GetTLSIndex(uint* pIndex); + [PreserveSig] + int GetDacModuleHandle(/*HMODULE*/ void* phModule); + + // COM + [PreserveSig] + int GetRCWData(ulong addr, /*struct DacpRCWData */ void* data); + [PreserveSig] + int GetRCWInterfaces(ulong rcw, uint count, /*struct DacpCOMInterfacePointerData*/ void* interfaces, uint* pNeeded); + [PreserveSig] + int GetCCWData(ulong ccw, /*struct DacpCCWData */ void* data); + [PreserveSig] + int GetCCWInterfaces(ulong ccw, uint count, /*struct DacpCOMInterfacePointerData*/ void* interfaces, uint* pNeeded); + [PreserveSig] + int TraverseRCWCleanupList(ulong cleanupListPtr, /*VISITRCWFORCLEANUP*/ void* pCallback, void* token); + + // GC Reference Functions + + /* GetStackReferences + * Enumerates all references on a given callstack. + */ + [PreserveSig] + int GetStackReferences(int osThreadID, /*ISOSStackRefEnum*/ void** ppEnum); + [PreserveSig] + int GetRegisterName(int regName, uint count, char* buffer, uint* pNeeded); + + [PreserveSig] + int GetThreadAllocData(ulong thread, /*struct DacpAllocData */ void* data); + [PreserveSig] + int GetHeapAllocData(uint count, /*struct DacpGenerationAllocData */ void* data, uint* pNeeded); + + // For BindingDisplay plugin + [PreserveSig] + int GetFailedAssemblyList(ulong appDomain, int count, [In, Out, MarshalUsing(CountElementName = nameof(count))] ulong[] values, uint* pNeeded); + [PreserveSig] + int GetPrivateBinPaths(ulong appDomain, int count, char* paths, uint* pNeeded); + [PreserveSig] + int GetAssemblyLocation(ulong assembly, int count, char* location, uint* pNeeded); + [PreserveSig] + int GetAppDomainConfigFile(ulong appDomain, int count, char* configFile, uint* pNeeded); + [PreserveSig] + int GetApplicationBase(ulong appDomain, int count, char* appBase, uint* pNeeded); + [PreserveSig] + int GetFailedAssemblyData(ulong assembly, uint* pContext, int* pResult); + [PreserveSig] + int GetFailedAssemblyLocation(ulong assesmbly, uint count, char* location, uint* pNeeded); + [PreserveSig] + int GetFailedAssemblyDisplayName(ulong assembly, uint count, char* name, uint* pNeeded); +}; + +[GeneratedComInterface] +[Guid("4eca42d8-7e7b-4c8a-a116-7bfbf6929267")] +internal partial interface ISOSDacInterface9 +{ + int GetBreakingChangeVersion(); +} diff --git a/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs b/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs new file mode 100644 index 000000000000..5cea71a68b8a --- /dev/null +++ b/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs @@ -0,0 +1,136 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +namespace Microsoft.Diagnostics.DataContractReader.Legacy; + +/// +/// Implementation of ISOSDacInterface* interfaces intended to be passed out to consumers +/// interacting with the DAC via those COM interfaces. +/// +[GeneratedComClass] +internal sealed partial class SOSDacImpl : ISOSDacInterface, ISOSDacInterface9 +{ + private readonly Target _target; + + public SOSDacImpl(Target target) + { + _target = target; + } + + public unsafe int GetAppDomainConfigFile(ulong appDomain, int count, char* configFile, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetAppDomainData(ulong addr, void* data) => HResults.E_NOTIMPL; + public unsafe int GetAppDomainList(uint count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] values, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetAppDomainName(ulong addr, uint count, char* name, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetAppDomainStoreData(void* data) => HResults.E_NOTIMPL; + public unsafe int GetApplicationBase(ulong appDomain, int count, char* appBase, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetAssemblyData(ulong baseDomainPtr, ulong assembly, void* data) => HResults.E_NOTIMPL; + public unsafe int GetAssemblyList(ulong appDomain, int count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] values, int* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetAssemblyLocation(ulong assembly, int count, char* location, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetAssemblyModuleList(ulong assembly, uint count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] modules, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetAssemblyName(ulong assembly, uint count, char* name, uint* pNeeded) => HResults.E_NOTIMPL; + + public int GetBreakingChangeVersion() + { + return _target.ReadGlobal(Constants.Globals.SOSBreakingChangeVersion); + } + + public unsafe int GetCCWData(ulong ccw, void* data) => HResults.E_NOTIMPL; + public unsafe int GetCCWInterfaces(ulong ccw, uint count, void* interfaces, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetClrWatsonBuckets(ulong thread, void* pGenericModeBlock) => HResults.E_NOTIMPL; + public unsafe int GetCodeHeaderData(ulong ip, void* data) => HResults.E_NOTIMPL; + public unsafe int GetCodeHeapList(ulong jitManager, uint count, void* codeHeaps, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetDacModuleHandle(void* phModule) => HResults.E_NOTIMPL; + public unsafe int GetDomainFromContext(ulong context, ulong* domain) => HResults.E_NOTIMPL; + public unsafe int GetDomainLocalModuleData(ulong addr, void* data) => HResults.E_NOTIMPL; + public unsafe int GetDomainLocalModuleDataFromAppDomain(ulong appDomainAddr, int moduleID, void* data) => HResults.E_NOTIMPL; + public unsafe int GetDomainLocalModuleDataFromModule(ulong moduleAddr, void* data) => HResults.E_NOTIMPL; + public unsafe int GetFailedAssemblyData(ulong assembly, uint* pContext, int* pResult) => HResults.E_NOTIMPL; + public unsafe int GetFailedAssemblyDisplayName(ulong assembly, uint count, char* name, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetFailedAssemblyList(ulong appDomain, int count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] values, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetFailedAssemblyLocation(ulong assesmbly, uint count, char* location, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetFieldDescData(ulong fieldDesc, void* data) => HResults.E_NOTIMPL; + public unsafe int GetFrameName(ulong vtable, uint count, char* frameName, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetGCHeapData(void* data) => HResults.E_NOTIMPL; + public unsafe int GetGCHeapDetails(ulong heap, void* details) => HResults.E_NOTIMPL; + public unsafe int GetGCHeapList(uint count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] heaps, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetGCHeapStaticData(void* data) => HResults.E_NOTIMPL; + public unsafe int GetHandleEnum(void** ppHandleEnum) => HResults.E_NOTIMPL; + public unsafe int GetHandleEnumForGC(uint gen, void** ppHandleEnum) => HResults.E_NOTIMPL; + public unsafe int GetHandleEnumForTypes([In, MarshalUsing(CountElementName = "count")] uint[] types, uint count, void** ppHandleEnum) => HResults.E_NOTIMPL; + public unsafe int GetHeapAllocData(uint count, void* data, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetHeapAnalyzeData(ulong addr, void* data) => HResults.E_NOTIMPL; + public unsafe int GetHeapAnalyzeStaticData(void* data) => HResults.E_NOTIMPL; + public unsafe int GetHeapSegmentData(ulong seg, void* data) => HResults.E_NOTIMPL; + public unsafe int GetHillClimbingLogEntry(ulong addr, void* data) => HResults.E_NOTIMPL; + public unsafe int GetILForModule(ulong moduleAddr, int rva, ulong* il) => HResults.E_NOTIMPL; + public unsafe int GetJitHelperFunctionName(ulong ip, uint count, byte* name, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetJitManagerList(uint count, void* managers, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetJumpThunkTarget(void* ctx, ulong* targetIP, ulong* targetMD) => HResults.E_NOTIMPL; + public unsafe int GetMethodDescData(ulong methodDesc, ulong ip, void* data, uint cRevertedRejitVersions, void* rgRevertedRejitData, uint* pcNeededRevertedRejitData) => HResults.E_NOTIMPL; + public unsafe int GetMethodDescFromToken(ulong moduleAddr, uint token, ulong* methodDesc) => HResults.E_NOTIMPL; + public unsafe int GetMethodDescName(ulong methodDesc, uint count, char* name, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetMethodDescPtrFromFrame(ulong frameAddr, ulong* ppMD) => HResults.E_NOTIMPL; + public unsafe int GetMethodDescPtrFromIP(ulong ip, ulong* ppMD) => HResults.E_NOTIMPL; + public unsafe int GetMethodDescTransparencyData(ulong methodDesc, void* data) => HResults.E_NOTIMPL; + public unsafe int GetMethodTableData(ulong mt, void* data) => HResults.E_NOTIMPL; + public unsafe int GetMethodTableFieldData(ulong mt, void* data) => HResults.E_NOTIMPL; + public unsafe int GetMethodTableForEEClass(ulong eeClass, ulong* value) => HResults.E_NOTIMPL; + public unsafe int GetMethodTableName(ulong mt, uint count, char* mtName, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetMethodTableSlot(ulong mt, uint slot, ulong* value) => HResults.E_NOTIMPL; + public unsafe int GetMethodTableTransparencyData(ulong mt, void* data) => HResults.E_NOTIMPL; + public unsafe int GetModule(ulong addr, void** mod) => HResults.E_NOTIMPL; + public unsafe int GetModuleData(ulong moduleAddr, void* data) => HResults.E_NOTIMPL; + public unsafe int GetNestedExceptionData(ulong exception, ulong* exceptionObject, ulong* nextNestedException) => HResults.E_NOTIMPL; + public unsafe int GetObjectClassName(ulong obj, uint count, char* className, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetObjectData(ulong objAddr, void* data) => HResults.E_NOTIMPL; + public unsafe int GetObjectStringData(ulong obj, uint count, char* stringData, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetOOMData(ulong oomAddr, void* data) => HResults.E_NOTIMPL; + public unsafe int GetOOMStaticData(void* data) => HResults.E_NOTIMPL; + public unsafe int GetPEFileBase(ulong addr, ulong* peBase) => HResults.E_NOTIMPL; + public unsafe int GetPEFileName(ulong addr, uint count, char* fileName, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetPrivateBinPaths(ulong appDomain, int count, char* paths, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetRCWData(ulong addr, void* data) => HResults.E_NOTIMPL; + public unsafe int GetRCWInterfaces(ulong rcw, uint count, void* interfaces, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetRegisterName(int regName, uint count, char* buffer, uint* pNeeded) => HResults.E_NOTIMPL; + public unsafe int GetStackLimits(ulong threadPtr, ulong* lower, ulong* upper, ulong* fp) => HResults.E_NOTIMPL; + public unsafe int GetStackReferences(int osThreadID, void** ppEnum) => HResults.E_NOTIMPL; + public unsafe int GetStressLogAddress(ulong* stressLog) => HResults.E_NOTIMPL; + public unsafe int GetSyncBlockCleanupData(ulong addr, void* data) => HResults.E_NOTIMPL; + public unsafe int GetSyncBlockData(uint number, void* data) => HResults.E_NOTIMPL; + public unsafe int GetThreadAllocData(ulong thread, void* data) => HResults.E_NOTIMPL; + public unsafe int GetThreadData(ulong thread, DacpThreadData* data) => HResults.E_NOTIMPL; + public unsafe int GetThreadFromThinlockID(uint thinLockId, ulong* pThread) => HResults.E_NOTIMPL; + public unsafe int GetThreadLocalModuleData(ulong thread, uint index, void* data) => HResults.E_NOTIMPL; + public unsafe int GetThreadpoolData(void* data) => HResults.E_NOTIMPL; + + public unsafe int GetThreadStoreData(DacpThreadStoreData* data) + { + try + { + Contracts.IThread thread = _target.Contracts.Thread; + Contracts.ThreadStoreData threadStoreData = thread.GetThreadStoreData(); + data->threadCount = threadStoreData.ThreadCount; + data->firstThread = threadStoreData.FirstThread.Value; + data->fHostConfig = 0; + } + catch (Exception ex) + { + return ex.HResult; + } + + return HResults.E_NOTIMPL; + } + + public unsafe int GetTLSIndex(uint* pIndex) => HResults.E_NOTIMPL; + public unsafe int GetUsefulGlobals(void* data) => HResults.E_NOTIMPL; + public unsafe int GetWorkRequestData(ulong addrWorkRequest, void* data) => HResults.E_NOTIMPL; + public unsafe int TraverseEHInfo(ulong ip, void* pCallback, void* token) => HResults.E_NOTIMPL; + public unsafe int TraverseLoaderHeap(ulong loaderHeapAddr, void* pCallback) => HResults.E_NOTIMPL; + public unsafe int TraverseModuleMap(int mmt, ulong moduleAddr, void* pCallback, void* token) => HResults.E_NOTIMPL; + public unsafe int TraverseRCWCleanupList(ulong cleanupListPtr, void* pCallback, void* token) => HResults.E_NOTIMPL; + public unsafe int TraverseVirtCallStubHeap(ulong pAppDomain, int heaptype, void* pCallback) => HResults.E_NOTIMPL; +} diff --git a/src/native/managed/cdacreader/src/Root.cs b/src/native/managed/cdacreader/src/Root.cs new file mode 100644 index 000000000000..05aefea3dea2 --- /dev/null +++ b/src/native/managed/cdacreader/src/Root.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text.Json.Serialization; + +namespace Microsoft.Diagnostics.DataContractReader; + +internal static class Root +{ + // https://github.com/dotnet/runtime/issues/101205 + public static JsonDerivedTypeAttribute[] R1 = new JsonDerivedTypeAttribute[] { null! }; +} diff --git a/src/native/managed/cdacreader/src/SOSDacImpl.cs b/src/native/managed/cdacreader/src/SOSDacImpl.cs deleted file mode 100644 index 893c39bff883..000000000000 --- a/src/native/managed/cdacreader/src/SOSDacImpl.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; - -namespace Microsoft.Diagnostics.DataContractReader; - -[GeneratedComInterface] -[Guid("4eca42d8-7e7b-4c8a-a116-7bfbf6929267")] -internal partial interface ISOSDacInterface9 -{ - int GetBreakingChangeVersion(); -} - -/// -/// Implementation of ISOSDacInterface* interfaces intended to be passed out to consumers -/// interacting with the DAC via those COM interfaces. -/// -[GeneratedComClass] -internal sealed partial class SOSDacImpl : ISOSDacInterface9 -{ - private readonly Target _target; - - public SOSDacImpl(Target target) - { - _target = target; - } - - public int GetBreakingChangeVersion() - { - // TODO: Return non-hard-coded version - return 4; - } -} diff --git a/src/native/managed/cdacreader/src/Target.cs b/src/native/managed/cdacreader/src/Target.cs index 1590984f017c..0202efaea38e 100644 --- a/src/native/managed/cdacreader/src/Target.cs +++ b/src/native/managed/cdacreader/src/Target.cs @@ -1,11 +1,376 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Numerics; +using System.Runtime.CompilerServices; + namespace Microsoft.Diagnostics.DataContractReader; -internal sealed class Target +public struct TargetPointer { - public Target(nint _) + public static TargetPointer Null = new(0); + + public ulong Value; + public TargetPointer(ulong value) => Value = value; +} + +public sealed unsafe class Target +{ + public record struct TypeInfo + { + public uint? Size; + public Dictionary Fields = []; + + public TypeInfo() { } + } + + public record struct FieldInfo + { + public int Offset; + public DataType Type; + public string? TypeName; + } + + private const int StackAllocByteThreshold = 1024; + + private readonly struct Configuration + { + public bool IsLittleEndian { get; init; } + public int PointerSize { get; init; } + } + + private readonly Configuration _config; + private readonly Reader _reader; + + private readonly Dictionary _contracts = []; + private readonly IReadOnlyDictionary _globals = new Dictionary(); + private readonly Dictionary _knownTypes = []; + private readonly Dictionary _types = []; + + internal Contracts.Registry Contracts { get; } + internal DataCache ProcessedData { get; } = new DataCache(); + + public static bool TryCreate(ulong contractDescriptor, delegate* unmanaged readFromTarget, void* readContext, out Target? target) + { + Reader reader = new Reader(readFromTarget, readContext); + if (TryReadContractDescriptor(contractDescriptor, reader, out Configuration config, out ContractDescriptorParser.ContractDescriptor? descriptor, out TargetPointer[] pointerData)) + { + target = new Target(config, descriptor!, pointerData, reader); + return true; + } + + target = null; + return false; + } + + private Target(Configuration config, ContractDescriptorParser.ContractDescriptor descriptor, TargetPointer[] pointerData, Reader reader) { + Contracts = new Contracts.Registry(this); + _config = config; + _reader = reader; + + _contracts = descriptor.Contracts ?? []; + + // Read types and map to known data types + if (descriptor.Types is not null) + { + foreach ((string name, ContractDescriptorParser.TypeDescriptor type) in descriptor.Types) + { + TypeInfo typeInfo = new() { Size = type.Size }; + if (type.Fields is not null) + { + foreach ((string fieldName, ContractDescriptorParser.FieldDescriptor field) in type.Fields) + { + typeInfo.Fields[fieldName] = new FieldInfo() + { + Offset = field.Offset, + Type = field.Type is null ? DataType.Unknown : GetDataType(field.Type), + TypeName = field.Type + }; + } + } + + DataType dataType = GetDataType(name); + if (dataType is not DataType.Unknown) + { + _knownTypes[dataType] = typeInfo; + } + else + { + _types[name] = typeInfo; + } + } + } + + // Read globals and map indirect values to pointer data + if (descriptor.Globals is not null) + { + Dictionary globals = []; + foreach ((string name, ContractDescriptorParser.GlobalDescriptor global) in descriptor.Globals) + { + ulong value = global.Value; + if (global.Indirect) + { + if (value >= (ulong)pointerData.Length) + throw new InvalidOperationException($"Invalid pointer data index {value}."); + + value = pointerData[value].Value; + } + + globals[name] = (value, global.Type); + } + + _globals = globals; + } + } + + // See docs/design/datacontracts/contract-descriptor.md + private static bool TryReadContractDescriptor( + ulong address, + Reader reader, + out Configuration config, + out ContractDescriptorParser.ContractDescriptor? descriptor, + out TargetPointer[] pointerData) + { + config = default; + descriptor = null; + pointerData = []; + + // Magic - uint64_t + Span buffer = stackalloc byte[sizeof(ulong)]; + if (reader.ReadFromTarget(address, buffer) < 0) + return false; + + address += sizeof(ulong); + ReadOnlySpan magicLE = "DNCCDAC\0"u8; + ReadOnlySpan magicBE = "\0CADCCND"u8; + bool isLittleEndian = buffer.SequenceEqual(magicLE); + if (!isLittleEndian && !buffer.SequenceEqual(magicBE)) + return false; + + // Flags - uint32_t + if (!TryRead(address, isLittleEndian, reader, out uint flags)) + return false; + + address += sizeof(uint); + + // Bit 1 represents the pointer size. 0 = 64-bit, 1 = 32-bit. + int pointerSize = (int)(flags & 0x2) == 0 ? sizeof(ulong) : sizeof(uint); + + config = new Configuration { IsLittleEndian = isLittleEndian, PointerSize = pointerSize }; + + // Descriptor size - uint32_t + if (!TryRead(address, config.IsLittleEndian, reader, out uint descriptorSize)) + return false; + + address += sizeof(uint); + + // Descriptor - char* + if (!TryReadPointer(address, config, reader, out TargetPointer descriptorAddr)) + return false; + + address += (uint)pointerSize; + + // Pointer data count - uint32_t + if (!TryRead(address, config.IsLittleEndian, reader, out uint pointerDataCount)) + return false; + + address += sizeof(uint); + + // Padding - uint32_t + address += sizeof(uint); + + // Pointer data - uintptr_t* + if (!TryReadPointer(address, config, reader, out TargetPointer pointerDataAddr)) + return false; + + // Read descriptor + Span descriptorBuffer = descriptorSize <= StackAllocByteThreshold + ? stackalloc byte[(int)descriptorSize] + : new byte[(int)descriptorSize]; + if (reader.ReadFromTarget(descriptorAddr.Value, descriptorBuffer) < 0) + return false; + + descriptor = ContractDescriptorParser.ParseCompact(descriptorBuffer); + if (descriptor is null) + return false; + + // Read pointer data + pointerData = new TargetPointer[pointerDataCount]; + for (int i = 0; i < pointerDataCount; i++) + { + if (!TryReadPointer(pointerDataAddr.Value + (uint)(i * pointerSize), config, reader, out pointerData[i])) + return false; + } + + return true; + } + + private static DataType GetDataType(string type) + { + if (Enum.TryParse(type, false, out DataType dataType) && Enum.IsDefined(dataType)) + return dataType; + + return DataType.Unknown; + } + + public T Read(ulong address) where T : unmanaged, IBinaryInteger, IMinMaxValue + { + if (!TryRead(address, _config.IsLittleEndian, _reader, out T value)) + throw new InvalidOperationException($"Failed to read {typeof(T)} at 0x{address:x8}."); + + return value; + } + + private static bool TryRead(ulong address, bool isLittleEndian, Reader reader, out T value) where T : unmanaged, IBinaryInteger, IMinMaxValue + { + value = default; + Span buffer = stackalloc byte[sizeof(T)]; + if (reader.ReadFromTarget(address, buffer) < 0) + return false; + + return isLittleEndian + ? T.TryReadLittleEndian(buffer, !IsSigned(), out value) + : T.TryReadBigEndian(buffer, !IsSigned(), out value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsSigned() where T : struct, INumberBase, IMinMaxValue + { + return T.IsNegative(T.MinValue); + } + + public TargetPointer ReadPointer(ulong address) + { + if (!TryReadPointer(address, _config, _reader, out TargetPointer pointer)) + throw new InvalidOperationException($"Failed to read pointer at 0x{address:x8}."); + + return pointer; + } + + private static bool TryReadPointer(ulong address, Configuration config, Reader reader, out TargetPointer pointer) + { + pointer = TargetPointer.Null; + + Span buffer = stackalloc byte[config.PointerSize]; + if (reader.ReadFromTarget(address, buffer) < 0) + return false; + + if (config.PointerSize == sizeof(uint) + && TryRead(address, config.IsLittleEndian, reader, out uint value32)) + { + pointer = new TargetPointer(value32); + return true; + } + else if (config.PointerSize == sizeof(ulong) + && TryRead(address, config.IsLittleEndian, reader, out ulong value64)) + { + pointer = new TargetPointer(value64); + return true; + } + + return false; + } + + public T ReadGlobal(string name) where T : struct, INumber + => ReadGlobal(name, out _); + + public T ReadGlobal(string name, out string? type) where T : struct, INumber + { + if (!_globals.TryGetValue(name, out (ulong Value, string? Type) global)) + throw new InvalidOperationException($"Failed to read global {typeof(T)} '{name}'."); + + type = global.Type; + return T.CreateChecked(global.Value); + } + + public TargetPointer ReadGlobalPointer(string name) + => ReadGlobalPointer(name, out _); + + public TargetPointer ReadGlobalPointer(string name, out string? type) + { + if (!_globals.TryGetValue(name, out (ulong Value, string? Type) global)) + throw new InvalidOperationException($"Failed to read global pointer '{name}'."); + + type = global.Type; + return new TargetPointer(global.Value); + } + + public TypeInfo GetTypeInfo(DataType type) + { + if (!_knownTypes.TryGetValue(type, out TypeInfo typeInfo)) + throw new InvalidOperationException($"Failed to get type info for '{type}'"); + + return typeInfo; + } + + public TypeInfo GetTypeInfo(string type) + { + if (_types.TryGetValue(type, out TypeInfo typeInfo)) + return typeInfo; + + DataType dataType = GetDataType(type); + if (dataType is not DataType.Unknown) + return GetTypeInfo(dataType); + + throw new InvalidOperationException($"Failed to get type info for '{type}'"); + } + + internal bool TryGetContractVersion(string contractName, out int version) + => _contracts.TryGetValue(contractName, out version); + + /// + /// Store of addresses that have already been read into corresponding data models. + /// This is simply used to avoid re-processing data on every request. + /// + internal sealed class DataCache + { + private readonly Dictionary<(ulong, Type), object?> _readDataByAddress = []; + + public bool TryRegister(ulong address, T data) + { + return _readDataByAddress.TryAdd((address, typeof(T)), data); + } + + public bool TryGet(ulong address, [NotNullWhen(true)] out T? data) + { + data = default; + if (!_readDataByAddress.TryGetValue((address, typeof(T)), out object? dataObj)) + return false; + + if (dataObj is T dataMaybe) + { + data = dataMaybe; + return true; + } + + return false; + } + } + + private sealed class Reader + { + private readonly delegate* unmanaged _readFromTarget; + private readonly void* _context; + + public Reader(delegate* unmanaged readFromTarget, void* context) + { + _readFromTarget = readFromTarget; + _context = context; + } + + public int ReadFromTarget(ulong address, Span buffer) + { + fixed (byte* bufferPtr = buffer) + { + return _readFromTarget(address, bufferPtr, (uint)buffer.Length, _context); + } + } + + public int ReadFromTarget(ulong address, byte* buffer, uint bytesToRead) + => _readFromTarget(address, buffer, bytesToRead, _context); } } diff --git a/src/native/managed/cdacreader/src/cdacreader.csproj b/src/native/managed/cdacreader/src/cdacreader.csproj index 51f87fa8908d..20ecd197c704 100644 --- a/src/native/managed/cdacreader/src/cdacreader.csproj +++ b/src/native/managed/cdacreader/src/cdacreader.csproj @@ -1,13 +1,20 @@ + lib$(MSBuildProjectName) $(NetCoreAppToolCurrent) + Microsoft.Diagnostics.DataContractReader enable true false + true + false + + + diff --git a/src/native/managed/cdacreader/tests/ContractDescriptorParserTests.cs b/src/native/managed/cdacreader/tests/ContractDescriptorParserTests.cs new file mode 100644 index 000000000000..6f93b1225670 --- /dev/null +++ b/src/native/managed/cdacreader/tests/ContractDescriptorParserTests.cs @@ -0,0 +1,215 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Text.Json; +using System.Text.Unicode; +using Xunit; + +namespace Microsoft.Diagnostics.DataContractReader.UnitTests; + +public class ContractDescriptorParserTests +{ + [Fact] + public void ParsesEmptyContract() + { + Assert.False(JsonSerializer.IsReflectionEnabledByDefault); + ReadOnlySpan json = "{}"u8; + ContractDescriptorParser.ContractDescriptor descriptor = ContractDescriptorParser.ParseCompact(json); + Assert.Null(descriptor.Version); + Assert.Null(descriptor.Baseline); + Assert.Null(descriptor.Contracts); + Assert.Null(descriptor.Types); + Assert.Null(descriptor.Extras); + } + [Fact] + public void ParsesTrivialContract() + { + ReadOnlySpan json = """ + { + "version": 0, + "baseline": "empty", + "contracts": {}, + "types": {}, + "globals": {} + } + """u8; + ContractDescriptorParser.ContractDescriptor descriptor = ContractDescriptorParser.ParseCompact(json); + Assert.Equal(0, descriptor.Version); + Assert.Equal("empty", descriptor.Baseline); + Assert.Empty(descriptor.Contracts); + Assert.Empty(descriptor.Types); + Assert.Empty(descriptor.Globals); + Assert.Null(descriptor.Extras); + } + + [Fact] + public void ParseSizedTypes() + { + ReadOnlySpan json = """ + { + "version": 0, + "baseline": "empty", + "contracts": {}, + "types": + { + "pointer": { "!" : 8}, + "int": { "!" : 4}, + "Point": { + "x": [ 4, "int"], + "y": 8, + "!": 12 + }, + "Point3D": { // no size + "r": [ 0, "double"], + "phi": 8, + "rho": 16 + } + }, + "globals": {} + } + """u8; + ContractDescriptorParser.ContractDescriptor descriptor = ContractDescriptorParser.ParseCompact(json); + Assert.Equal(0, descriptor.Version); + Assert.Equal("empty", descriptor.Baseline); + Assert.Empty(descriptor.Contracts); + Assert.Empty(descriptor.Globals); + Assert.Equal(4, descriptor.Types.Count); + Assert.Equal(8u, descriptor.Types["pointer"].Size); + Assert.Equal(4u, descriptor.Types["int"].Size); + Assert.Equal(2, descriptor.Types["Point"].Fields.Count); + Assert.Equal(4, descriptor.Types["Point"].Fields["x"].Offset); + Assert.Equal(8, descriptor.Types["Point"].Fields["y"].Offset); + Assert.Equal("int", descriptor.Types["Point"].Fields["x"].Type); + Assert.Null(descriptor.Types["Point"].Fields["y"].Type); + Assert.Equal(12u, descriptor.Types["Point"].Size); + Assert.Equal(3, descriptor.Types["Point3D"].Fields.Count); + Assert.Equal(0, descriptor.Types["Point3D"].Fields["r"].Offset); + Assert.Equal(8, descriptor.Types["Point3D"].Fields["phi"].Offset); + Assert.Equal(16, descriptor.Types["Point3D"].Fields["rho"].Offset); + Assert.Equal("double", descriptor.Types["Point3D"].Fields["r"].Type); + Assert.Null(descriptor.Types["Point3D"].Fields["phi"].Type); + Assert.Null(descriptor.Types["Point3D"].Size); + } + + [Fact] + public void ParseContractsCaseSensitive() + { + ReadOnlySpan json = """ + { + "version": 0, + "baseline": "empty", + "contracts": { + "foo": 1, + "Foo": 2 + }, + "types": {}, + "globals": {} + } + """u8; + ContractDescriptorParser.ContractDescriptor descriptor = ContractDescriptorParser.ParseCompact(json); + Assert.Equal(0, descriptor.Version); + Assert.Equal("empty", descriptor.Baseline); + Assert.Equal(2, descriptor.Contracts.Count); + Assert.Equal(1, descriptor.Contracts["foo"]); + Assert.Equal(2, descriptor.Contracts["Foo"]); + } + + [Fact] + public void ParsesGlobals() + { + ReadOnlySpan json = """ + { + "version": 0, + "baseline": "empty", + "contracts": {}, + "types": {}, + "globals": { + "globalInt": 1, + "globalPtr": [2], + "globalTypedInt": [3, "uint8"], + "globalTypedPtr": [[4], "uintptr"], + "globalHex": "0x1234", + "globalNegative": -2, + "globalStringyInt": "17", + "globalStringyNegative": "-2", + "globalNegativeHex": "-0xff", + "globalBigStringyInt": "0x123456789abcdef", + "globalStringyPtr": ["0x1234"], + "globalTypedStringyInt": ["0x1234", "int"], + "globalTypedStringyPtr": [["0x1234"], "int"] + } + } + """u8; + ContractDescriptorParser.ContractDescriptor descriptor = ContractDescriptorParser.ParseCompact(json); + Assert.Equal(0, descriptor.Version); + Assert.Equal("empty", descriptor.Baseline); + Assert.Empty(descriptor.Contracts); + Assert.Empty(descriptor.Types); + Assert.Equal(13, descriptor.Globals.Count); + Assert.Equal((ulong)1, descriptor.Globals["globalInt"].Value); + Assert.False(descriptor.Globals["globalInt"].Indirect); + Assert.Equal((ulong)2, descriptor.Globals["globalPtr"].Value); + Assert.True(descriptor.Globals["globalPtr"].Indirect); + Assert.Equal((ulong)3, descriptor.Globals["globalTypedInt"].Value); + Assert.False(descriptor.Globals["globalTypedInt"].Indirect); + Assert.Equal("uint8", descriptor.Globals["globalTypedInt"].Type); + Assert.Equal((ulong)4, descriptor.Globals["globalTypedPtr"].Value); + Assert.True(descriptor.Globals["globalTypedPtr"].Indirect); + Assert.Equal("uintptr", descriptor.Globals["globalTypedPtr"].Type); + Assert.Equal((ulong)0x1234, descriptor.Globals["globalHex"].Value); + Assert.False(descriptor.Globals["globalHex"].Indirect); + Assert.Equal((ulong)0xfffffffffffffffe, descriptor.Globals["globalNegative"].Value); + Assert.False(descriptor.Globals["globalNegative"].Indirect); + Assert.Equal((ulong)17, descriptor.Globals["globalStringyInt"].Value); + Assert.False(descriptor.Globals["globalStringyInt"].Indirect); + Assert.Equal((ulong)0xfffffffffffffffe, descriptor.Globals["globalStringyNegative"].Value); + Assert.False(descriptor.Globals["globalStringyNegative"].Indirect); + Assert.Equal((ulong)0xffffffffffffff01, descriptor.Globals["globalNegativeHex"].Value); + Assert.False(descriptor.Globals["globalNegativeHex"].Indirect); + Assert.Equal((ulong)0x123456789abcdef, descriptor.Globals["globalBigStringyInt"].Value); + Assert.False(descriptor.Globals["globalBigStringyInt"].Indirect); + Assert.Equal((ulong)0x1234, descriptor.Globals["globalStringyPtr"].Value); + Assert.True(descriptor.Globals["globalStringyPtr"].Indirect); + Assert.Equal("int", descriptor.Globals["globalTypedStringyInt"].Type); + Assert.Equal((ulong)0x1234, descriptor.Globals["globalTypedStringyInt"].Value); + Assert.False(descriptor.Globals["globalTypedStringyInt"].Indirect); + Assert.Equal("int", descriptor.Globals["globalTypedStringyPtr"].Type); + Assert.Equal((ulong)0x1234, descriptor.Globals["globalTypedStringyPtr"].Value); + Assert.True(descriptor.Globals["globalTypedStringyPtr"].Indirect); + } + + [Fact] + void ParsesExoticOffsets() + { + ReadOnlySpan json = """ + { + "version": 0, + "baseline": "empty", + "contracts": {}, + "types": { + "OddStruct": { + "a": -12, + "b": "0x12", + "c": "-0x12", + "d": ["0x100", "int"] + } + }, + "globals": { + } + } + """u8; + ContractDescriptorParser.ContractDescriptor descriptor = ContractDescriptorParser.ParseCompact(json); + Assert.Equal(0, descriptor.Version); + Assert.Equal("empty", descriptor.Baseline); + Assert.Empty(descriptor.Contracts); + Assert.Empty(descriptor.Globals); + Assert.Equal(1, descriptor.Types.Count); + Assert.Equal(4, descriptor.Types["OddStruct"].Fields.Count); + Assert.Equal(-12, descriptor.Types["OddStruct"].Fields["a"].Offset); + Assert.Equal(0x12, descriptor.Types["OddStruct"].Fields["b"].Offset); + Assert.Equal(-0x12, descriptor.Types["OddStruct"].Fields["c"].Offset); + Assert.Equal(0x100, descriptor.Types["OddStruct"].Fields["d"].Offset); + Assert.Equal("int", descriptor.Types["OddStruct"].Fields["d"].Type); + } +} diff --git a/src/native/managed/cdacreader/tests/Microsoft.Diagnostics.DataContractReader.Tests.csproj b/src/native/managed/cdacreader/tests/Microsoft.Diagnostics.DataContractReader.Tests.csproj new file mode 100644 index 000000000000..c12c45e6f1fe --- /dev/null +++ b/src/native/managed/cdacreader/tests/Microsoft.Diagnostics.DataContractReader.Tests.csproj @@ -0,0 +1,16 @@ + + + true + $(NetCoreAppToolCurrent) + false + + + + + + + + + + diff --git a/src/native/managed/cdacreader/tests/TargetTests.cs b/src/native/managed/cdacreader/tests/TargetTests.cs new file mode 100644 index 000000000000..ec1899327b3f --- /dev/null +++ b/src/native/managed/cdacreader/tests/TargetTests.cs @@ -0,0 +1,447 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using Xunit; + +namespace Microsoft.Diagnostics.DataContractReader.UnitTests; + +public unsafe class TargetTests +{ + private const ulong ContractDescriptorAddr = 0xaaaaaaaa; + private const uint JsonDescriptorAddr = 0xdddddddd; + private const uint PointerDataAddr = 0xeeeeeeee; + + private static readonly (DataType Type, Target.TypeInfo Info)[] TestTypes = + [ + // Size and fields + (DataType.Thread, new(){ + Size = 56, + Fields = { + { "Field1", new(){ Offset = 8, Type = DataType.uint16, TypeName = DataType.uint16.ToString() }}, + { "Field2", new(){ Offset = 16, Type = DataType.GCHandle, TypeName = DataType.GCHandle.ToString() }}, + { "Field3", new(){ Offset = 32 }} + }}), + // Fields only + (DataType.ThreadStore, new(){ + Fields = { + { "Field1", new(){ Offset = 0, TypeName = "FieldType" }}, + { "Field2", new(){ Offset = 8 }} + }}), + // Size only + (DataType.GCHandle, new(){ + Size = 8 + }) + ]; + + [Theory] + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(false, false)] + public void GetTypeInfo(bool isLittleEndian, bool is64Bit) + { + string typesJson = string.Join(',', TestTypes.Select(t => GetTypeJson(t.Type.ToString(), t.Info))); + byte[] json = Encoding.UTF8.GetBytes($$""" + { + "version": 0, + "baseline": "empty", + "contracts": {}, + "types": { {{typesJson}} }, + "globals": {} + } + """); + Span descriptor = stackalloc byte[ContractDescriptor.Size(is64Bit)]; + ContractDescriptor.Fill(descriptor, isLittleEndian, is64Bit, json.Length, 0); + fixed (byte* jsonPtr = json) + { + ReadContext context = new ReadContext + { + ContractDescriptor = (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(descriptor)), + ContractDescriptorLength = descriptor.Length, + JsonDescriptor = jsonPtr, + JsonDescriptorLength = json.Length, + }; + + bool success = Target.TryCreate(ContractDescriptorAddr, &ReadFromTarget, &context, out Target? target); + Assert.True(success); + + foreach ((DataType type, Target.TypeInfo info) in TestTypes) + { + { + // By known type + Target.TypeInfo actual = target.GetTypeInfo(type); + Assert.Equal(info.Size, actual.Size); + Assert.Equal(info.Fields, actual.Fields); + } + { + // By name + Target.TypeInfo actual = target.GetTypeInfo(type.ToString()); + Assert.Equal(info.Size, actual.Size); + Assert.Equal(info.Fields, actual.Fields); + } + } + } + + static string GetTypeJson(string name, Target.TypeInfo info) + { + string ret = string.Empty; + List fields = info.Size is null ? [] : [$"\"!\":{info.Size}"]; + fields.AddRange(info.Fields.Select(f => $"\"{f.Key}\":{(f.Value.TypeName is null ? f.Value.Offset : $"[{f.Value.Offset},\"{f.Value.TypeName}\"]")}")); + return $"\"{name}\":{{{string.Join(',', fields)}}}"; + } + } + + private static readonly (string Name, ulong Value, string? Type)[] TestGlobals = + [ + ("value", (ulong)sbyte.MaxValue, null), + ("int8Value", 0x12, "int8"), + ("uint8Value", 0x12, "uint8"), + ("int16Value", 0x1234, "int16"), + ("uint16Value", 0x1234, "uint16"), + ("int32Value", 0x12345678, "int32"), + ("uint32Value", 0x12345678, "uint32"), + ("int64Value", 0x123456789abcdef0, "int64"), + ("uint64Value", 0x123456789abcdef0, "uint64"), + ("nintValue", 0xabcdef0, "nint"), + ("nuintValue", 0xabcdef0, "nuint"), + ("pointerValue", 0xabcdef0, "pointer"), + ]; + + [Theory] + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(false, false)] + public void ReadGlobalValue(bool isLittleEndian, bool is64Bit) + { + string globalsJson = string.Join(',', TestGlobals.Select(i => $"\"{i.Name}\": {(i.Type is null ? i.Value.ToString() : $"[{i.Value}, \"{i.Type}\"]")}")); + byte[] json = Encoding.UTF8.GetBytes($$""" + { + "version": 0, + "baseline": "empty", + "contracts": {}, + "types": {}, + "globals": { {{globalsJson}} } + } + """); + Span descriptor = stackalloc byte[ContractDescriptor.Size(is64Bit)]; + ContractDescriptor.Fill(descriptor, isLittleEndian, is64Bit, json.Length, 0); + fixed (byte* jsonPtr = json) + { + ReadContext context = new ReadContext + { + ContractDescriptor = (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(descriptor)), + ContractDescriptorLength = descriptor.Length, + JsonDescriptor = jsonPtr, + JsonDescriptorLength = json.Length, + }; + + bool success = Target.TryCreate(ContractDescriptorAddr, &ReadFromTarget, &context, out Target? target); + Assert.True(success); + + ValidateGlobals(target, TestGlobals); + } + } + + [Theory] + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(false, false)] + public void ReadIndirectGlobalValue(bool isLittleEndian, bool is64Bit) + { + int pointerSize = is64Bit ? sizeof(ulong) : sizeof(uint); + Span pointerData = stackalloc byte[TestGlobals.Length * pointerSize]; + for (int i = 0; i < TestGlobals.Length; i++) + { + var (_, value, _) = TestGlobals[i]; + WritePointer(pointerData.Slice(i * pointerSize), value, isLittleEndian, pointerSize); + } + + string globalsJson = string.Join(',', TestGlobals.Select((g, i) => $"\"{g.Name}\": {(g.Type is null ? $"[{i}]" : $"[[{i}], \"{g.Type}\"]")}")); + byte[] json = Encoding.UTF8.GetBytes($$""" + { + "version": 0, + "baseline": "empty", + "contracts": {}, + "types": {}, + "globals": { {{globalsJson}} } + } + """); + Span descriptor = stackalloc byte[ContractDescriptor.Size(is64Bit)]; + ContractDescriptor.Fill(descriptor, isLittleEndian, is64Bit, json.Length, pointerData.Length / pointerSize); + fixed (byte* jsonPtr = json) + { + ReadContext context = new ReadContext + { + ContractDescriptor = (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(descriptor)), + ContractDescriptorLength = descriptor.Length, + JsonDescriptor = jsonPtr, + JsonDescriptorLength = json.Length, + PointerData = (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(pointerData)), + PointerDataLength = pointerData.Length + }; + + bool success = Target.TryCreate(ContractDescriptorAddr, &ReadFromTarget, &context, out Target? target); + Assert.True(success); + + // Indirect values are pointer-sized, so max 32-bits for a 32-bit target + var expected = is64Bit + ? TestGlobals + : TestGlobals.Select(g => (g.Name, g.Value & 0xffffffff, g.Type)).ToArray(); + + ValidateGlobals(target, expected); + } + } + + private static void WritePointer(Span dest, ulong value, bool isLittleEndian, int pointerSize) + { + if (pointerSize == sizeof(ulong)) + { + if (isLittleEndian) + { + BinaryPrimitives.WriteUInt64LittleEndian(dest, value); + } + else + { + BinaryPrimitives.WriteUInt64BigEndian(dest, value); + } + } + else if (pointerSize == sizeof(uint)) + { + if (isLittleEndian) + { + BinaryPrimitives.WriteUInt32LittleEndian(dest, (uint)value); + } + else + { + BinaryPrimitives.WriteUInt32BigEndian(dest, (uint)value); + } + } + } + + private static void ValidateGlobals( + Target target, + (string Name, ulong Value, string? Type)[] globals, + [CallerMemberName] string caller = "", + [CallerFilePath] string filePath = "", + [CallerLineNumber] int lineNumber = 0) + { + foreach (var (name, value, type) in globals) + { + // Validate that each global can be read successfully based on its type + // and that it matches the expected value + if (type is null || type == "int8") + { + sbyte actual = target.ReadGlobal(name, out string? actualType); + AssertEqualsWithCallerInfo(actualType, type); + AssertEqualsWithCallerInfo((sbyte)value, actual); + } + + if (type is null || type == "uint8") + { + byte actual = target.ReadGlobal(name, out string? actualType); + AssertEqualsWithCallerInfo(actualType, type); + AssertEqualsWithCallerInfo(value, actual); + } + + if (type is null || type == "int16") + { + short actual = target.ReadGlobal(name, out string? actualType); + AssertEqualsWithCallerInfo(actualType, type); + AssertEqualsWithCallerInfo((short)value, actual); + } + + if (type is null || type == "uint16") + { + ushort actual = target.ReadGlobal(name, out string? actualType); + AssertEqualsWithCallerInfo(actualType, type); + AssertEqualsWithCallerInfo(value, actual); + } + + if (type is null || type == "int32") + { + int actual = target.ReadGlobal(name, out string? actualType); + AssertEqualsWithCallerInfo(actualType, type); + AssertEqualsWithCallerInfo((int)value, actual); + } + + if (type is null || type == "uint32") + { + uint actual = target.ReadGlobal(name, out string? actualType); + AssertEqualsWithCallerInfo(actualType, type); + AssertEqualsWithCallerInfo((uint)value, actual); + } + + if (type is null || type == "int64") + { + long actual = target.ReadGlobal(name, out string? actualType); + AssertEqualsWithCallerInfo(actualType, type); + AssertEqualsWithCallerInfo((long)value, actual); + } + + if (type is null || type == "uint64") + { + ulong actual = target.ReadGlobal(name, out string? actualType); + AssertEqualsWithCallerInfo(actualType, type); + AssertEqualsWithCallerInfo(value, actual); + } + + if (type is null || type == "pointer" || type == "nint" || type == "nuint") + { + TargetPointer actual = target.ReadGlobalPointer(name, out string? actualType); + AssertEqualsWithCallerInfo(actualType, type); + AssertEqualsWithCallerInfo(value, actual.Value); + } + } + + void AssertEqualsWithCallerInfo(T expected, T actual) + { + Assert.True((expected is null && actual is null) || expected.Equals(actual), $"Expected: {expected}. Actual: {actual}. [test case: {caller} in {filePath}:{lineNumber}]"); + } + } + + [UnmanagedCallersOnly] + private static int ReadFromTarget(ulong address, byte* buffer, uint length, void* context) + { + ReadContext* readContext = (ReadContext*)context; + var span = new Span(buffer, (int)length); + + // Populate the span with the requested portion of the contract descriptor + if (address >= ContractDescriptorAddr && address <= ContractDescriptorAddr + (ulong)readContext->ContractDescriptorLength - length) + { + ulong offset = address - ContractDescriptorAddr; + new ReadOnlySpan(readContext->ContractDescriptor + offset, (int)length).CopyTo(span); + return 0; + } + + // Populate the span with the JSON descriptor - this assumes the product will read it all at once. + if (address == JsonDescriptorAddr) + { + new ReadOnlySpan(readContext->JsonDescriptor, readContext->JsonDescriptorLength).CopyTo(span); + return 0; + } + + // Populate the span with the requested portion of the pointer data + if (address >= PointerDataAddr && address <= PointerDataAddr + (ulong)readContext->PointerDataLength - length) + { + ulong offset = address - PointerDataAddr; + new ReadOnlySpan(readContext->PointerData + offset, (int)length).CopyTo(span); + return 0; + } + + return -1; + } + + // Used by ReadFromTarget to return the appropriate bytes + private struct ReadContext + { + public byte* ContractDescriptor; + public int ContractDescriptorLength; + + public byte* JsonDescriptor; + public int JsonDescriptorLength; + + public byte* PointerData; + public int PointerDataLength; + } + + private static class ContractDescriptor + { + public static int Size(bool is64Bit) => is64Bit ? sizeof(ContractDescriptor64) : sizeof(ContractDescriptor32); + + public static void Fill(Span dest, bool isLittleEndian, bool is64Bit, int jsonDescriptorSize, int pointerDataCount) + { + if (is64Bit) + { + ContractDescriptor64.Fill(dest, isLittleEndian, jsonDescriptorSize, pointerDataCount); + } + else + { + ContractDescriptor32.Fill(dest, isLittleEndian, jsonDescriptorSize, pointerDataCount); + } + } + + private struct ContractDescriptor32 + { + public ulong Magic = BitConverter.ToUInt64("DNCCDAC\0"u8); + public uint Flags = 0x2 /*32-bit*/ | 0x1; + public uint DescriptorSize; + public uint Descriptor = JsonDescriptorAddr; + public uint PointerDataCount; + public uint Pad0 = 0; + public uint PointerData = PointerDataAddr; + + public ContractDescriptor32() { } + + public static void Fill(Span dest, bool isLittleEndian, int jsonDescriptorSize, int pointerDataCount) + { + ContractDescriptor32 descriptor = new() + { + DescriptorSize = (uint)jsonDescriptorSize, + PointerDataCount = (uint)pointerDataCount, + }; + if (BitConverter.IsLittleEndian != isLittleEndian) + descriptor.ReverseEndianness(); + + MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref descriptor, 1)).CopyTo(dest); + } + + private void ReverseEndianness() + { + Magic = BinaryPrimitives.ReverseEndianness(Magic); + Flags = BinaryPrimitives.ReverseEndianness(Flags); + DescriptorSize = BinaryPrimitives.ReverseEndianness(DescriptorSize); + Descriptor = BinaryPrimitives.ReverseEndianness(Descriptor); + PointerDataCount = BinaryPrimitives.ReverseEndianness(PointerDataCount); + Pad0 = BinaryPrimitives.ReverseEndianness(Pad0); + PointerData = BinaryPrimitives.ReverseEndianness(PointerData); + } + } + + private struct ContractDescriptor64 + { + public ulong Magic = BitConverter.ToUInt64("DNCCDAC\0"u8); + public uint Flags = 0x1; + public uint DescriptorSize; + public ulong Descriptor = JsonDescriptorAddr; + public uint PointerDataCount; + public uint Pad0 = 0; + public ulong PointerData = PointerDataAddr; + + public ContractDescriptor64() { } + + public static void Fill(Span dest, bool isLittleEndian, int jsonDescriptorSize, int pointerDataCount) + { + ContractDescriptor64 descriptor = new() + { + DescriptorSize = (uint)jsonDescriptorSize, + PointerDataCount = (uint)pointerDataCount, + }; + if (BitConverter.IsLittleEndian != isLittleEndian) + descriptor.ReverseEndianness(); + + MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref descriptor, 1)).CopyTo(dest); + } + + private void ReverseEndianness() + { + Magic = BinaryPrimitives.ReverseEndianness(Magic); + Flags = BinaryPrimitives.ReverseEndianness(Flags); + DescriptorSize = BinaryPrimitives.ReverseEndianness(DescriptorSize); + Descriptor = BinaryPrimitives.ReverseEndianness(Descriptor); + PointerDataCount = BinaryPrimitives.ReverseEndianness(PointerDataCount); + Pad0 = BinaryPrimitives.ReverseEndianness(Pad0); + PointerData = BinaryPrimitives.ReverseEndianness(PointerData); + } + } + } + +} diff --git a/src/native/managed/compile-native.proj b/src/native/managed/compile-native.proj index b9815ae30e48..bcda8c5d6b57 100644 --- a/src/native/managed/compile-native.proj +++ b/src/native/managed/compile-native.proj @@ -1,8 +1,6 @@ - + - - Release - + shared @@ -24,6 +22,7 @@ false + false false true false @@ -36,28 +35,22 @@ --gcc-toolchain=$(ROOTFS_DIR)/usr - - - - - - - + + - - @(SubprojectProps->'%(Identity)=%(Value)', ';') - - + + + Targets="LinkNative" + Condition="$(SupportsNativeAotComponents)"/> diff --git a/src/native/managed/native-library.props b/src/native/managed/native-library.props index 89a80a8005a0..7acadfa32d42 100644 --- a/src/native/managed/native-library.props +++ b/src/native/managed/native-library.props @@ -6,6 +6,7 @@ the same way as eng/native/functions.cmake strip_symbols --> false + true
    + + + + + diff --git a/src/native/managed/native-library.targets b/src/native/managed/native-library.targets index e0f23322bba4..298da3c50ce7 100644 --- a/src/native/managed/native-library.targets +++ b/src/native/managed/native-library.targets @@ -1,107 +1,119 @@ - - - - - $(OutputPath)stripped\ - $(StrippedOutputPath)$(TargetName)$(NativeBinaryExt) - .dylib.dwarf - .so.dbg - $(StrippedOutputPath)$(TargetName)$(StrippedExt) - - - - - - - true - - - - - - false - - - - - - - - - - - - - <_StripLike Condition="'$(TargetsOSX)' == 'true' or '$(TargetsAppleMobile)' == 'true'">apple - <_StripLike Condition="'$(_StripLike)' == ''">gnu - - - - - - - - - - - - - - - - - - $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', '$(RuntimeFlavor.ToLower())', '$(TargetOS).$(TargetArchitecture).$(RuntimeConfiguration)')) - - - - <_NormalizedInstallRuntimeComponentDest Include="$([MSBuild]::NormalizeDirectory('$(FinalRuntimeComponentDestinationBase)', '%(InstallRuntimeComponentDestination.Identity)'))" /> - - - - - - - - - - - - - - - - - - - + + + + + + + + + $(OutputPath)stripped\ + $(StrippedOutputPath)$(TargetName)$(NativeBinaryExt) + .dylib.dwarf + .so.dbg + $(StrippedOutputPath)$(TargetName)$(StrippedExt) + + + + + + + true + + + + + + false + + + + + + + + + + + + + <_StripLike Condition="'$(TargetsOSX)' == 'true' or '$(TargetsAppleMobile)' == 'true'">apple + <_StripLike Condition="'$(_StripLike)' == ''">gnu + + + + + + + + + + + + + + + + + + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', '$(RuntimeFlavor.ToLower())', '$(TargetOS).$(TargetArchitecture).$(RuntimeConfiguration)')) + + + + <_NormalizedInstallRuntimeComponentDest Include="$([MSBuild]::NormalizeDirectory('$(FinalRuntimeComponentDestinationBase)', '%(InstallRuntimeComponentDestination.Identity)'))" /> + + + + + + + + + + + + + + + + + + diff --git a/src/native/managed/subproject.props b/src/native/managed/subproject.props new file mode 100644 index 000000000000..b51d6f3428a4 --- /dev/null +++ b/src/native/managed/subproject.props @@ -0,0 +1,13 @@ + + + + + + + + + + + @(SubprojectProps->'%(Identity)=%(Value)', ';') + + diff --git a/src/native/minipal/UnicodeDataGenerator/Program.cs b/src/native/minipal/UnicodeDataGenerator/Program.cs new file mode 100644 index 000000000000..f4611ef26454 --- /dev/null +++ b/src/native/minipal/UnicodeDataGenerator/Program.cs @@ -0,0 +1,112 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; + +Console.WriteLine(@" +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// +// THIS FILE IS GENERATED. DO NOT HAND EDIT. +// IF YOU NEED TO UPDATE UNICODE VERSION FOLLOW THE GUIDE AT src/libraries/System.Private.CoreLib/Tools/GenUnicodeProp/Updating-Unicode-Versions.md +// + +#include +#include + +typedef struct +{ + CHAR16_T code; + uint8_t upperOrLower; + CHAR16_T opposingCode; +} UnicodeDataRec; + +#define UPPER_CASE 0 +#define LOWER_CASE 1 + +static const UnicodeDataRec UnicodeData[] = +{"); + +string sourceFileName = args[0]; + +int numberOfCases = 0; +using StreamReader sourceFile = File.OpenText(sourceFileName); +while (sourceFile.ReadLine() is string line) +{ + var fields = line.Split(';'); + + var code = int.Parse(fields[0], NumberStyles.HexNumber); + + bool hasUpperCaseMapping = fields[12].Length != 0; + bool hasLowerCaseMapping = fields[13].Length != 0; + + if (!hasLowerCaseMapping && !hasUpperCaseMapping) + continue; + + + int opposingCase = hasUpperCaseMapping ? + int.Parse(fields[12], NumberStyles.HexNumber) : + int.Parse(fields[13], NumberStyles.HexNumber); + + // These won't fit in 16 bits - no point carrying them + if (code > 0xFFFF) + continue; + + Debug.Assert(opposingCase <= 0xFFFF); + + string specifier = hasUpperCaseMapping ? "LOWER_CASE" : "UPPER_CASE"; + Console.WriteLine($" {{ 0x{code:X}, {specifier}, 0x{opposingCase:X} }},"); + + numberOfCases++; +} + +Console.WriteLine("};"); + +Console.WriteLine($@" +#define UNICODE_DATA_SIZE {numberOfCases}"); + +Console.WriteLine(@" +static int UnicodeDataComp(const void *opposingCode, const void *elem) +{ + CHAR16_T code = ((UnicodeDataRec*)elem)->code; + + if (*((CHAR16_T*)opposingCode) < code) + { + return -1; + } + else if (*((CHAR16_T*)opposingCode) > code) + { + return 1; + } + else + { + return 0; + } +} + +CHAR16_T minipal_toupper_invariant(CHAR16_T code) +{ + UnicodeDataRec *record = (UnicodeDataRec *) bsearch(&code, UnicodeData, UNICODE_DATA_SIZE, + sizeof(UnicodeDataRec), UnicodeDataComp); + + if (!record || record->upperOrLower != LOWER_CASE) + return code; + + return record->opposingCode; +} + +CHAR16_T minipal_tolower_invariant(CHAR16_T code) +{ + UnicodeDataRec *record = (UnicodeDataRec *) bsearch(&code, UnicodeData, UNICODE_DATA_SIZE, + sizeof(UnicodeDataRec), UnicodeDataComp); + + if (!record || record->upperOrLower != UPPER_CASE) + return code; + + return record->opposingCode; +}"); diff --git a/src/native/minipal/UnicodeDataGenerator/UnicodeDataGenerator.csproj b/src/native/minipal/UnicodeDataGenerator/UnicodeDataGenerator.csproj new file mode 100644 index 000000000000..962ce8016a36 --- /dev/null +++ b/src/native/minipal/UnicodeDataGenerator/UnicodeDataGenerator.csproj @@ -0,0 +1,8 @@ + + + + $(NetCoreAppToolCurrent) + enable + + + diff --git a/src/native/minipal/cpufeatures.c b/src/native/minipal/cpufeatures.c index 89b30724aafd..a7c2ae737bad 100644 --- a/src/native/minipal/cpufeatures.c +++ b/src/native/minipal/cpufeatures.c @@ -12,6 +12,10 @@ #include +#ifndef PF_ARM_SVE_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SVE_INSTRUCTIONS_AVAILABLE (46) +#endif + #else // HOST_WINDOWS #include "minipalconfig.h" @@ -458,6 +462,11 @@ int minipal_getcpufeatures(void) // TODO: IsProcessorFeaturePresent doesn't support LRCPC2 yet. + if (IsProcessorFeaturePresent(PF_ARM_SVE_INSTRUCTIONS_AVAILABLE)) + { + result |= ARM64IntrinsicConstants_Sve; + } + #endif // HOST_WINDOWS #endif // HOST_ARM64 diff --git a/src/native/minipal/getexepath.h b/src/native/minipal/getexepath.h index 601447a1af21..d9b6bdd85bdf 100644 --- a/src/native/minipal/getexepath.h +++ b/src/native/minipal/getexepath.h @@ -37,7 +37,11 @@ static inline char* minipal_getexepath(void) return NULL; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Walloca" char* path_buf = (char*)alloca(path_length); +#pragma clang diagnostic pop + if (_NSGetExecutablePath(path_buf, &path_length) != 0) { errno = EINVAL; diff --git a/src/native/minipal/random.c b/src/native/minipal/random.c index bde7edc47d11..20fcc07802e6 100644 --- a/src/native/minipal/random.c +++ b/src/native/minipal/random.c @@ -80,16 +80,12 @@ int32_t minipal_get_cryptographically_secure_random_bytes(uint8_t* buffer, int32 return 0; } #elif defined(__APPLE__) && __APPLE__ - CCRNGStatus status = CCRandomGenerateBytes(buffer, bufferLength); + CCRNGStatus status = CCRandomGenerateBytes(buffer, (size_t)bufferLength); if (status == kCCSuccess) { return 0; } - else - { - return -1; - } #else static volatile int rand_des = -1; diff --git a/src/native/minipal/strings.h b/src/native/minipal/strings.h new file mode 100644 index 000000000000..250dada9f539 --- /dev/null +++ b/src/native/minipal/strings.h @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef HAVE_MINIPAL_STRINGS_H +#define HAVE_MINIPAL_STRINGS_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/** + * Convert a UTF-16 character to uppercase using invariant culture. + * + * @param code The UTF-16 character to be converted. + * @return The uppercase equivalent of the character or the character itself if no conversion is necessary. + */ +CHAR16_T minipal_toupper_invariant(CHAR16_T code); + +/** + * Convert a UTF-16 character to lowercase using invariant culture. + * + * @param code The UTF-16 character to be converted. + * @return The lowercase equivalent of the character or the character itself if no conversion is necessary. + */ +CHAR16_T minipal_tolower_invariant(CHAR16_T code); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* HAVE_MINIPAL_STRINGS_H */ diff --git a/src/native/minipal/types.h b/src/native/minipal/types.h index aa834ee1abee..997e9db21c97 100644 --- a/src/native/minipal/types.h +++ b/src/native/minipal/types.h @@ -4,6 +4,8 @@ #ifndef HAVE_MINIPAL_TYPES_H #define HAVE_MINIPAL_TYPES_H +#include + #if defined(TARGET_32BIT) || defined(TARGET_OSX) || defined(TARGET_WINDOWS) #define FORMAT_PREFIX "l" #else @@ -22,4 +24,10 @@ #define PRIu64 FORMAT_PREFIX "lu" #endif +#ifdef TARGET_WINDOWS +typedef wchar_t CHAR16_T; +#else +typedef unsigned short CHAR16_T; +#endif + #endif // HAVE_MINIPAL_TYPES_H diff --git a/src/native/minipal/unicodedata.c b/src/native/minipal/unicodedata.c new file mode 100644 index 000000000000..18c1d0213972 --- /dev/null +++ b/src/native/minipal/unicodedata.c @@ -0,0 +1,2426 @@ + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// +// THIS FILE IS GENERATED. DO NOT HAND EDIT. +// IF YOU NEED TO UPDATE UNICODE VERSION FOLLOW THE GUIDE AT src/libraries/System.Private.CoreLib/Tools/GenUnicodeProp/Updating-Unicode-Versions.md +// + +#include +#include + +typedef struct +{ + CHAR16_T code; + uint8_t upperOrLower; + CHAR16_T opposingCode; +} UnicodeDataRec; + +#define UPPER_CASE 0 +#define LOWER_CASE 1 + +static const UnicodeDataRec UnicodeData[] = +{ + { 0x41, UPPER_CASE, 0x61 }, + { 0x42, UPPER_CASE, 0x62 }, + { 0x43, UPPER_CASE, 0x63 }, + { 0x44, UPPER_CASE, 0x64 }, + { 0x45, UPPER_CASE, 0x65 }, + { 0x46, UPPER_CASE, 0x66 }, + { 0x47, UPPER_CASE, 0x67 }, + { 0x48, UPPER_CASE, 0x68 }, + { 0x49, UPPER_CASE, 0x69 }, + { 0x4A, UPPER_CASE, 0x6A }, + { 0x4B, UPPER_CASE, 0x6B }, + { 0x4C, UPPER_CASE, 0x6C }, + { 0x4D, UPPER_CASE, 0x6D }, + { 0x4E, UPPER_CASE, 0x6E }, + { 0x4F, UPPER_CASE, 0x6F }, + { 0x50, UPPER_CASE, 0x70 }, + { 0x51, UPPER_CASE, 0x71 }, + { 0x52, UPPER_CASE, 0x72 }, + { 0x53, UPPER_CASE, 0x73 }, + { 0x54, UPPER_CASE, 0x74 }, + { 0x55, UPPER_CASE, 0x75 }, + { 0x56, UPPER_CASE, 0x76 }, + { 0x57, UPPER_CASE, 0x77 }, + { 0x58, UPPER_CASE, 0x78 }, + { 0x59, UPPER_CASE, 0x79 }, + { 0x5A, UPPER_CASE, 0x7A }, + { 0x61, LOWER_CASE, 0x41 }, + { 0x62, LOWER_CASE, 0x42 }, + { 0x63, LOWER_CASE, 0x43 }, + { 0x64, LOWER_CASE, 0x44 }, + { 0x65, LOWER_CASE, 0x45 }, + { 0x66, LOWER_CASE, 0x46 }, + { 0x67, LOWER_CASE, 0x47 }, + { 0x68, LOWER_CASE, 0x48 }, + { 0x69, LOWER_CASE, 0x49 }, + { 0x6A, LOWER_CASE, 0x4A }, + { 0x6B, LOWER_CASE, 0x4B }, + { 0x6C, LOWER_CASE, 0x4C }, + { 0x6D, LOWER_CASE, 0x4D }, + { 0x6E, LOWER_CASE, 0x4E }, + { 0x6F, LOWER_CASE, 0x4F }, + { 0x70, LOWER_CASE, 0x50 }, + { 0x71, LOWER_CASE, 0x51 }, + { 0x72, LOWER_CASE, 0x52 }, + { 0x73, LOWER_CASE, 0x53 }, + { 0x74, LOWER_CASE, 0x54 }, + { 0x75, LOWER_CASE, 0x55 }, + { 0x76, LOWER_CASE, 0x56 }, + { 0x77, LOWER_CASE, 0x57 }, + { 0x78, LOWER_CASE, 0x58 }, + { 0x79, LOWER_CASE, 0x59 }, + { 0x7A, LOWER_CASE, 0x5A }, + { 0xB5, LOWER_CASE, 0x39C }, + { 0xC0, UPPER_CASE, 0xE0 }, + { 0xC1, UPPER_CASE, 0xE1 }, + { 0xC2, UPPER_CASE, 0xE2 }, + { 0xC3, UPPER_CASE, 0xE3 }, + { 0xC4, UPPER_CASE, 0xE4 }, + { 0xC5, UPPER_CASE, 0xE5 }, + { 0xC6, UPPER_CASE, 0xE6 }, + { 0xC7, UPPER_CASE, 0xE7 }, + { 0xC8, UPPER_CASE, 0xE8 }, + { 0xC9, UPPER_CASE, 0xE9 }, + { 0xCA, UPPER_CASE, 0xEA }, + { 0xCB, UPPER_CASE, 0xEB }, + { 0xCC, UPPER_CASE, 0xEC }, + { 0xCD, UPPER_CASE, 0xED }, + { 0xCE, UPPER_CASE, 0xEE }, + { 0xCF, UPPER_CASE, 0xEF }, + { 0xD0, UPPER_CASE, 0xF0 }, + { 0xD1, UPPER_CASE, 0xF1 }, + { 0xD2, UPPER_CASE, 0xF2 }, + { 0xD3, UPPER_CASE, 0xF3 }, + { 0xD4, UPPER_CASE, 0xF4 }, + { 0xD5, UPPER_CASE, 0xF5 }, + { 0xD6, UPPER_CASE, 0xF6 }, + { 0xD8, UPPER_CASE, 0xF8 }, + { 0xD9, UPPER_CASE, 0xF9 }, + { 0xDA, UPPER_CASE, 0xFA }, + { 0xDB, UPPER_CASE, 0xFB }, + { 0xDC, UPPER_CASE, 0xFC }, + { 0xDD, UPPER_CASE, 0xFD }, + { 0xDE, UPPER_CASE, 0xFE }, + { 0xE0, LOWER_CASE, 0xC0 }, + { 0xE1, LOWER_CASE, 0xC1 }, + { 0xE2, LOWER_CASE, 0xC2 }, + { 0xE3, LOWER_CASE, 0xC3 }, + { 0xE4, LOWER_CASE, 0xC4 }, + { 0xE5, LOWER_CASE, 0xC5 }, + { 0xE6, LOWER_CASE, 0xC6 }, + { 0xE7, LOWER_CASE, 0xC7 }, + { 0xE8, LOWER_CASE, 0xC8 }, + { 0xE9, LOWER_CASE, 0xC9 }, + { 0xEA, LOWER_CASE, 0xCA }, + { 0xEB, LOWER_CASE, 0xCB }, + { 0xEC, LOWER_CASE, 0xCC }, + { 0xED, LOWER_CASE, 0xCD }, + { 0xEE, LOWER_CASE, 0xCE }, + { 0xEF, LOWER_CASE, 0xCF }, + { 0xF0, LOWER_CASE, 0xD0 }, + { 0xF1, LOWER_CASE, 0xD1 }, + { 0xF2, LOWER_CASE, 0xD2 }, + { 0xF3, LOWER_CASE, 0xD3 }, + { 0xF4, LOWER_CASE, 0xD4 }, + { 0xF5, LOWER_CASE, 0xD5 }, + { 0xF6, LOWER_CASE, 0xD6 }, + { 0xF8, LOWER_CASE, 0xD8 }, + { 0xF9, LOWER_CASE, 0xD9 }, + { 0xFA, LOWER_CASE, 0xDA }, + { 0xFB, LOWER_CASE, 0xDB }, + { 0xFC, LOWER_CASE, 0xDC }, + { 0xFD, LOWER_CASE, 0xDD }, + { 0xFE, LOWER_CASE, 0xDE }, + { 0xFF, LOWER_CASE, 0x178 }, + { 0x100, UPPER_CASE, 0x101 }, + { 0x101, LOWER_CASE, 0x100 }, + { 0x102, UPPER_CASE, 0x103 }, + { 0x103, LOWER_CASE, 0x102 }, + { 0x104, UPPER_CASE, 0x105 }, + { 0x105, LOWER_CASE, 0x104 }, + { 0x106, UPPER_CASE, 0x107 }, + { 0x107, LOWER_CASE, 0x106 }, + { 0x108, UPPER_CASE, 0x109 }, + { 0x109, LOWER_CASE, 0x108 }, + { 0x10A, UPPER_CASE, 0x10B }, + { 0x10B, LOWER_CASE, 0x10A }, + { 0x10C, UPPER_CASE, 0x10D }, + { 0x10D, LOWER_CASE, 0x10C }, + { 0x10E, UPPER_CASE, 0x10F }, + { 0x10F, LOWER_CASE, 0x10E }, + { 0x110, UPPER_CASE, 0x111 }, + { 0x111, LOWER_CASE, 0x110 }, + { 0x112, UPPER_CASE, 0x113 }, + { 0x113, LOWER_CASE, 0x112 }, + { 0x114, UPPER_CASE, 0x115 }, + { 0x115, LOWER_CASE, 0x114 }, + { 0x116, UPPER_CASE, 0x117 }, + { 0x117, LOWER_CASE, 0x116 }, + { 0x118, UPPER_CASE, 0x119 }, + { 0x119, LOWER_CASE, 0x118 }, + { 0x11A, UPPER_CASE, 0x11B }, + { 0x11B, LOWER_CASE, 0x11A }, + { 0x11C, UPPER_CASE, 0x11D }, + { 0x11D, LOWER_CASE, 0x11C }, + { 0x11E, UPPER_CASE, 0x11F }, + { 0x11F, LOWER_CASE, 0x11E }, + { 0x120, UPPER_CASE, 0x121 }, + { 0x121, LOWER_CASE, 0x120 }, + { 0x122, UPPER_CASE, 0x123 }, + { 0x123, LOWER_CASE, 0x122 }, + { 0x124, UPPER_CASE, 0x125 }, + { 0x125, LOWER_CASE, 0x124 }, + { 0x126, UPPER_CASE, 0x127 }, + { 0x127, LOWER_CASE, 0x126 }, + { 0x128, UPPER_CASE, 0x129 }, + { 0x129, LOWER_CASE, 0x128 }, + { 0x12A, UPPER_CASE, 0x12B }, + { 0x12B, LOWER_CASE, 0x12A }, + { 0x12C, UPPER_CASE, 0x12D }, + { 0x12D, LOWER_CASE, 0x12C }, + { 0x12E, UPPER_CASE, 0x12F }, + { 0x12F, LOWER_CASE, 0x12E }, + { 0x130, UPPER_CASE, 0x69 }, + { 0x131, LOWER_CASE, 0x49 }, + { 0x132, UPPER_CASE, 0x133 }, + { 0x133, LOWER_CASE, 0x132 }, + { 0x134, UPPER_CASE, 0x135 }, + { 0x135, LOWER_CASE, 0x134 }, + { 0x136, UPPER_CASE, 0x137 }, + { 0x137, LOWER_CASE, 0x136 }, + { 0x139, UPPER_CASE, 0x13A }, + { 0x13A, LOWER_CASE, 0x139 }, + { 0x13B, UPPER_CASE, 0x13C }, + { 0x13C, LOWER_CASE, 0x13B }, + { 0x13D, UPPER_CASE, 0x13E }, + { 0x13E, LOWER_CASE, 0x13D }, + { 0x13F, UPPER_CASE, 0x140 }, + { 0x140, LOWER_CASE, 0x13F }, + { 0x141, UPPER_CASE, 0x142 }, + { 0x142, LOWER_CASE, 0x141 }, + { 0x143, UPPER_CASE, 0x144 }, + { 0x144, LOWER_CASE, 0x143 }, + { 0x145, UPPER_CASE, 0x146 }, + { 0x146, LOWER_CASE, 0x145 }, + { 0x147, UPPER_CASE, 0x148 }, + { 0x148, LOWER_CASE, 0x147 }, + { 0x14A, UPPER_CASE, 0x14B }, + { 0x14B, LOWER_CASE, 0x14A }, + { 0x14C, UPPER_CASE, 0x14D }, + { 0x14D, LOWER_CASE, 0x14C }, + { 0x14E, UPPER_CASE, 0x14F }, + { 0x14F, LOWER_CASE, 0x14E }, + { 0x150, UPPER_CASE, 0x151 }, + { 0x151, LOWER_CASE, 0x150 }, + { 0x152, UPPER_CASE, 0x153 }, + { 0x153, LOWER_CASE, 0x152 }, + { 0x154, UPPER_CASE, 0x155 }, + { 0x155, LOWER_CASE, 0x154 }, + { 0x156, UPPER_CASE, 0x157 }, + { 0x157, LOWER_CASE, 0x156 }, + { 0x158, UPPER_CASE, 0x159 }, + { 0x159, LOWER_CASE, 0x158 }, + { 0x15A, UPPER_CASE, 0x15B }, + { 0x15B, LOWER_CASE, 0x15A }, + { 0x15C, UPPER_CASE, 0x15D }, + { 0x15D, LOWER_CASE, 0x15C }, + { 0x15E, UPPER_CASE, 0x15F }, + { 0x15F, LOWER_CASE, 0x15E }, + { 0x160, UPPER_CASE, 0x161 }, + { 0x161, LOWER_CASE, 0x160 }, + { 0x162, UPPER_CASE, 0x163 }, + { 0x163, LOWER_CASE, 0x162 }, + { 0x164, UPPER_CASE, 0x165 }, + { 0x165, LOWER_CASE, 0x164 }, + { 0x166, UPPER_CASE, 0x167 }, + { 0x167, LOWER_CASE, 0x166 }, + { 0x168, UPPER_CASE, 0x169 }, + { 0x169, LOWER_CASE, 0x168 }, + { 0x16A, UPPER_CASE, 0x16B }, + { 0x16B, LOWER_CASE, 0x16A }, + { 0x16C, UPPER_CASE, 0x16D }, + { 0x16D, LOWER_CASE, 0x16C }, + { 0x16E, UPPER_CASE, 0x16F }, + { 0x16F, LOWER_CASE, 0x16E }, + { 0x170, UPPER_CASE, 0x171 }, + { 0x171, LOWER_CASE, 0x170 }, + { 0x172, UPPER_CASE, 0x173 }, + { 0x173, LOWER_CASE, 0x172 }, + { 0x174, UPPER_CASE, 0x175 }, + { 0x175, LOWER_CASE, 0x174 }, + { 0x176, UPPER_CASE, 0x177 }, + { 0x177, LOWER_CASE, 0x176 }, + { 0x178, UPPER_CASE, 0xFF }, + { 0x179, UPPER_CASE, 0x17A }, + { 0x17A, LOWER_CASE, 0x179 }, + { 0x17B, UPPER_CASE, 0x17C }, + { 0x17C, LOWER_CASE, 0x17B }, + { 0x17D, UPPER_CASE, 0x17E }, + { 0x17E, LOWER_CASE, 0x17D }, + { 0x17F, LOWER_CASE, 0x53 }, + { 0x180, LOWER_CASE, 0x243 }, + { 0x181, UPPER_CASE, 0x253 }, + { 0x182, UPPER_CASE, 0x183 }, + { 0x183, LOWER_CASE, 0x182 }, + { 0x184, UPPER_CASE, 0x185 }, + { 0x185, LOWER_CASE, 0x184 }, + { 0x186, UPPER_CASE, 0x254 }, + { 0x187, UPPER_CASE, 0x188 }, + { 0x188, LOWER_CASE, 0x187 }, + { 0x189, UPPER_CASE, 0x256 }, + { 0x18A, UPPER_CASE, 0x257 }, + { 0x18B, UPPER_CASE, 0x18C }, + { 0x18C, LOWER_CASE, 0x18B }, + { 0x18E, UPPER_CASE, 0x1DD }, + { 0x18F, UPPER_CASE, 0x259 }, + { 0x190, UPPER_CASE, 0x25B }, + { 0x191, UPPER_CASE, 0x192 }, + { 0x192, LOWER_CASE, 0x191 }, + { 0x193, UPPER_CASE, 0x260 }, + { 0x194, UPPER_CASE, 0x263 }, + { 0x195, LOWER_CASE, 0x1F6 }, + { 0x196, UPPER_CASE, 0x269 }, + { 0x197, UPPER_CASE, 0x268 }, + { 0x198, UPPER_CASE, 0x199 }, + { 0x199, LOWER_CASE, 0x198 }, + { 0x19A, LOWER_CASE, 0x23D }, + { 0x19C, UPPER_CASE, 0x26F }, + { 0x19D, UPPER_CASE, 0x272 }, + { 0x19E, LOWER_CASE, 0x220 }, + { 0x19F, UPPER_CASE, 0x275 }, + { 0x1A0, UPPER_CASE, 0x1A1 }, + { 0x1A1, LOWER_CASE, 0x1A0 }, + { 0x1A2, UPPER_CASE, 0x1A3 }, + { 0x1A3, LOWER_CASE, 0x1A2 }, + { 0x1A4, UPPER_CASE, 0x1A5 }, + { 0x1A5, LOWER_CASE, 0x1A4 }, + { 0x1A6, UPPER_CASE, 0x280 }, + { 0x1A7, UPPER_CASE, 0x1A8 }, + { 0x1A8, LOWER_CASE, 0x1A7 }, + { 0x1A9, UPPER_CASE, 0x283 }, + { 0x1AC, UPPER_CASE, 0x1AD }, + { 0x1AD, LOWER_CASE, 0x1AC }, + { 0x1AE, UPPER_CASE, 0x288 }, + { 0x1AF, UPPER_CASE, 0x1B0 }, + { 0x1B0, LOWER_CASE, 0x1AF }, + { 0x1B1, UPPER_CASE, 0x28A }, + { 0x1B2, UPPER_CASE, 0x28B }, + { 0x1B3, UPPER_CASE, 0x1B4 }, + { 0x1B4, LOWER_CASE, 0x1B3 }, + { 0x1B5, UPPER_CASE, 0x1B6 }, + { 0x1B6, LOWER_CASE, 0x1B5 }, + { 0x1B7, UPPER_CASE, 0x292 }, + { 0x1B8, UPPER_CASE, 0x1B9 }, + { 0x1B9, LOWER_CASE, 0x1B8 }, + { 0x1BC, UPPER_CASE, 0x1BD }, + { 0x1BD, LOWER_CASE, 0x1BC }, + { 0x1BF, LOWER_CASE, 0x1F7 }, + { 0x1C4, UPPER_CASE, 0x1C6 }, + { 0x1C5, LOWER_CASE, 0x1C4 }, + { 0x1C6, LOWER_CASE, 0x1C4 }, + { 0x1C7, UPPER_CASE, 0x1C9 }, + { 0x1C8, LOWER_CASE, 0x1C7 }, + { 0x1C9, LOWER_CASE, 0x1C7 }, + { 0x1CA, UPPER_CASE, 0x1CC }, + { 0x1CB, LOWER_CASE, 0x1CA }, + { 0x1CC, LOWER_CASE, 0x1CA }, + { 0x1CD, UPPER_CASE, 0x1CE }, + { 0x1CE, LOWER_CASE, 0x1CD }, + { 0x1CF, UPPER_CASE, 0x1D0 }, + { 0x1D0, LOWER_CASE, 0x1CF }, + { 0x1D1, UPPER_CASE, 0x1D2 }, + { 0x1D2, LOWER_CASE, 0x1D1 }, + { 0x1D3, UPPER_CASE, 0x1D4 }, + { 0x1D4, LOWER_CASE, 0x1D3 }, + { 0x1D5, UPPER_CASE, 0x1D6 }, + { 0x1D6, LOWER_CASE, 0x1D5 }, + { 0x1D7, UPPER_CASE, 0x1D8 }, + { 0x1D8, LOWER_CASE, 0x1D7 }, + { 0x1D9, UPPER_CASE, 0x1DA }, + { 0x1DA, LOWER_CASE, 0x1D9 }, + { 0x1DB, UPPER_CASE, 0x1DC }, + { 0x1DC, LOWER_CASE, 0x1DB }, + { 0x1DD, LOWER_CASE, 0x18E }, + { 0x1DE, UPPER_CASE, 0x1DF }, + { 0x1DF, LOWER_CASE, 0x1DE }, + { 0x1E0, UPPER_CASE, 0x1E1 }, + { 0x1E1, LOWER_CASE, 0x1E0 }, + { 0x1E2, UPPER_CASE, 0x1E3 }, + { 0x1E3, LOWER_CASE, 0x1E2 }, + { 0x1E4, UPPER_CASE, 0x1E5 }, + { 0x1E5, LOWER_CASE, 0x1E4 }, + { 0x1E6, UPPER_CASE, 0x1E7 }, + { 0x1E7, LOWER_CASE, 0x1E6 }, + { 0x1E8, UPPER_CASE, 0x1E9 }, + { 0x1E9, LOWER_CASE, 0x1E8 }, + { 0x1EA, UPPER_CASE, 0x1EB }, + { 0x1EB, LOWER_CASE, 0x1EA }, + { 0x1EC, UPPER_CASE, 0x1ED }, + { 0x1ED, LOWER_CASE, 0x1EC }, + { 0x1EE, UPPER_CASE, 0x1EF }, + { 0x1EF, LOWER_CASE, 0x1EE }, + { 0x1F1, UPPER_CASE, 0x1F3 }, + { 0x1F2, LOWER_CASE, 0x1F1 }, + { 0x1F3, LOWER_CASE, 0x1F1 }, + { 0x1F4, UPPER_CASE, 0x1F5 }, + { 0x1F5, LOWER_CASE, 0x1F4 }, + { 0x1F6, UPPER_CASE, 0x195 }, + { 0x1F7, UPPER_CASE, 0x1BF }, + { 0x1F8, UPPER_CASE, 0x1F9 }, + { 0x1F9, LOWER_CASE, 0x1F8 }, + { 0x1FA, UPPER_CASE, 0x1FB }, + { 0x1FB, LOWER_CASE, 0x1FA }, + { 0x1FC, UPPER_CASE, 0x1FD }, + { 0x1FD, LOWER_CASE, 0x1FC }, + { 0x1FE, UPPER_CASE, 0x1FF }, + { 0x1FF, LOWER_CASE, 0x1FE }, + { 0x200, UPPER_CASE, 0x201 }, + { 0x201, LOWER_CASE, 0x200 }, + { 0x202, UPPER_CASE, 0x203 }, + { 0x203, LOWER_CASE, 0x202 }, + { 0x204, UPPER_CASE, 0x205 }, + { 0x205, LOWER_CASE, 0x204 }, + { 0x206, UPPER_CASE, 0x207 }, + { 0x207, LOWER_CASE, 0x206 }, + { 0x208, UPPER_CASE, 0x209 }, + { 0x209, LOWER_CASE, 0x208 }, + { 0x20A, UPPER_CASE, 0x20B }, + { 0x20B, LOWER_CASE, 0x20A }, + { 0x20C, UPPER_CASE, 0x20D }, + { 0x20D, LOWER_CASE, 0x20C }, + { 0x20E, UPPER_CASE, 0x20F }, + { 0x20F, LOWER_CASE, 0x20E }, + { 0x210, UPPER_CASE, 0x211 }, + { 0x211, LOWER_CASE, 0x210 }, + { 0x212, UPPER_CASE, 0x213 }, + { 0x213, LOWER_CASE, 0x212 }, + { 0x214, UPPER_CASE, 0x215 }, + { 0x215, LOWER_CASE, 0x214 }, + { 0x216, UPPER_CASE, 0x217 }, + { 0x217, LOWER_CASE, 0x216 }, + { 0x218, UPPER_CASE, 0x219 }, + { 0x219, LOWER_CASE, 0x218 }, + { 0x21A, UPPER_CASE, 0x21B }, + { 0x21B, LOWER_CASE, 0x21A }, + { 0x21C, UPPER_CASE, 0x21D }, + { 0x21D, LOWER_CASE, 0x21C }, + { 0x21E, UPPER_CASE, 0x21F }, + { 0x21F, LOWER_CASE, 0x21E }, + { 0x220, UPPER_CASE, 0x19E }, + { 0x222, UPPER_CASE, 0x223 }, + { 0x223, LOWER_CASE, 0x222 }, + { 0x224, UPPER_CASE, 0x225 }, + { 0x225, LOWER_CASE, 0x224 }, + { 0x226, UPPER_CASE, 0x227 }, + { 0x227, LOWER_CASE, 0x226 }, + { 0x228, UPPER_CASE, 0x229 }, + { 0x229, LOWER_CASE, 0x228 }, + { 0x22A, UPPER_CASE, 0x22B }, + { 0x22B, LOWER_CASE, 0x22A }, + { 0x22C, UPPER_CASE, 0x22D }, + { 0x22D, LOWER_CASE, 0x22C }, + { 0x22E, UPPER_CASE, 0x22F }, + { 0x22F, LOWER_CASE, 0x22E }, + { 0x230, UPPER_CASE, 0x231 }, + { 0x231, LOWER_CASE, 0x230 }, + { 0x232, UPPER_CASE, 0x233 }, + { 0x233, LOWER_CASE, 0x232 }, + { 0x23A, UPPER_CASE, 0x2C65 }, + { 0x23B, UPPER_CASE, 0x23C }, + { 0x23C, LOWER_CASE, 0x23B }, + { 0x23D, UPPER_CASE, 0x19A }, + { 0x23E, UPPER_CASE, 0x2C66 }, + { 0x23F, LOWER_CASE, 0x2C7E }, + { 0x240, LOWER_CASE, 0x2C7F }, + { 0x241, UPPER_CASE, 0x242 }, + { 0x242, LOWER_CASE, 0x241 }, + { 0x243, UPPER_CASE, 0x180 }, + { 0x244, UPPER_CASE, 0x289 }, + { 0x245, UPPER_CASE, 0x28C }, + { 0x246, UPPER_CASE, 0x247 }, + { 0x247, LOWER_CASE, 0x246 }, + { 0x248, UPPER_CASE, 0x249 }, + { 0x249, LOWER_CASE, 0x248 }, + { 0x24A, UPPER_CASE, 0x24B }, + { 0x24B, LOWER_CASE, 0x24A }, + { 0x24C, UPPER_CASE, 0x24D }, + { 0x24D, LOWER_CASE, 0x24C }, + { 0x24E, UPPER_CASE, 0x24F }, + { 0x24F, LOWER_CASE, 0x24E }, + { 0x250, LOWER_CASE, 0x2C6F }, + { 0x251, LOWER_CASE, 0x2C6D }, + { 0x252, LOWER_CASE, 0x2C70 }, + { 0x253, LOWER_CASE, 0x181 }, + { 0x254, LOWER_CASE, 0x186 }, + { 0x256, LOWER_CASE, 0x189 }, + { 0x257, LOWER_CASE, 0x18A }, + { 0x259, LOWER_CASE, 0x18F }, + { 0x25B, LOWER_CASE, 0x190 }, + { 0x25C, LOWER_CASE, 0xA7AB }, + { 0x260, LOWER_CASE, 0x193 }, + { 0x261, LOWER_CASE, 0xA7AC }, + { 0x263, LOWER_CASE, 0x194 }, + { 0x265, LOWER_CASE, 0xA78D }, + { 0x266, LOWER_CASE, 0xA7AA }, + { 0x268, LOWER_CASE, 0x197 }, + { 0x269, LOWER_CASE, 0x196 }, + { 0x26A, LOWER_CASE, 0xA7AE }, + { 0x26B, LOWER_CASE, 0x2C62 }, + { 0x26C, LOWER_CASE, 0xA7AD }, + { 0x26F, LOWER_CASE, 0x19C }, + { 0x271, LOWER_CASE, 0x2C6E }, + { 0x272, LOWER_CASE, 0x19D }, + { 0x275, LOWER_CASE, 0x19F }, + { 0x27D, LOWER_CASE, 0x2C64 }, + { 0x280, LOWER_CASE, 0x1A6 }, + { 0x282, LOWER_CASE, 0xA7C5 }, + { 0x283, LOWER_CASE, 0x1A9 }, + { 0x287, LOWER_CASE, 0xA7B1 }, + { 0x288, LOWER_CASE, 0x1AE }, + { 0x289, LOWER_CASE, 0x244 }, + { 0x28A, LOWER_CASE, 0x1B1 }, + { 0x28B, LOWER_CASE, 0x1B2 }, + { 0x28C, LOWER_CASE, 0x245 }, + { 0x292, LOWER_CASE, 0x1B7 }, + { 0x29D, LOWER_CASE, 0xA7B2 }, + { 0x29E, LOWER_CASE, 0xA7B0 }, + { 0x345, LOWER_CASE, 0x399 }, + { 0x370, UPPER_CASE, 0x371 }, + { 0x371, LOWER_CASE, 0x370 }, + { 0x372, UPPER_CASE, 0x373 }, + { 0x373, LOWER_CASE, 0x372 }, + { 0x376, UPPER_CASE, 0x377 }, + { 0x377, LOWER_CASE, 0x376 }, + { 0x37B, LOWER_CASE, 0x3FD }, + { 0x37C, LOWER_CASE, 0x3FE }, + { 0x37D, LOWER_CASE, 0x3FF }, + { 0x37F, UPPER_CASE, 0x3F3 }, + { 0x386, UPPER_CASE, 0x3AC }, + { 0x388, UPPER_CASE, 0x3AD }, + { 0x389, UPPER_CASE, 0x3AE }, + { 0x38A, UPPER_CASE, 0x3AF }, + { 0x38C, UPPER_CASE, 0x3CC }, + { 0x38E, UPPER_CASE, 0x3CD }, + { 0x38F, UPPER_CASE, 0x3CE }, + { 0x391, UPPER_CASE, 0x3B1 }, + { 0x392, UPPER_CASE, 0x3B2 }, + { 0x393, UPPER_CASE, 0x3B3 }, + { 0x394, UPPER_CASE, 0x3B4 }, + { 0x395, UPPER_CASE, 0x3B5 }, + { 0x396, UPPER_CASE, 0x3B6 }, + { 0x397, UPPER_CASE, 0x3B7 }, + { 0x398, UPPER_CASE, 0x3B8 }, + { 0x399, UPPER_CASE, 0x3B9 }, + { 0x39A, UPPER_CASE, 0x3BA }, + { 0x39B, UPPER_CASE, 0x3BB }, + { 0x39C, UPPER_CASE, 0x3BC }, + { 0x39D, UPPER_CASE, 0x3BD }, + { 0x39E, UPPER_CASE, 0x3BE }, + { 0x39F, UPPER_CASE, 0x3BF }, + { 0x3A0, UPPER_CASE, 0x3C0 }, + { 0x3A1, UPPER_CASE, 0x3C1 }, + { 0x3A3, UPPER_CASE, 0x3C3 }, + { 0x3A4, UPPER_CASE, 0x3C4 }, + { 0x3A5, UPPER_CASE, 0x3C5 }, + { 0x3A6, UPPER_CASE, 0x3C6 }, + { 0x3A7, UPPER_CASE, 0x3C7 }, + { 0x3A8, UPPER_CASE, 0x3C8 }, + { 0x3A9, UPPER_CASE, 0x3C9 }, + { 0x3AA, UPPER_CASE, 0x3CA }, + { 0x3AB, UPPER_CASE, 0x3CB }, + { 0x3AC, LOWER_CASE, 0x386 }, + { 0x3AD, LOWER_CASE, 0x388 }, + { 0x3AE, LOWER_CASE, 0x389 }, + { 0x3AF, LOWER_CASE, 0x38A }, + { 0x3B1, LOWER_CASE, 0x391 }, + { 0x3B2, LOWER_CASE, 0x392 }, + { 0x3B3, LOWER_CASE, 0x393 }, + { 0x3B4, LOWER_CASE, 0x394 }, + { 0x3B5, LOWER_CASE, 0x395 }, + { 0x3B6, LOWER_CASE, 0x396 }, + { 0x3B7, LOWER_CASE, 0x397 }, + { 0x3B8, LOWER_CASE, 0x398 }, + { 0x3B9, LOWER_CASE, 0x399 }, + { 0x3BA, LOWER_CASE, 0x39A }, + { 0x3BB, LOWER_CASE, 0x39B }, + { 0x3BC, LOWER_CASE, 0x39C }, + { 0x3BD, LOWER_CASE, 0x39D }, + { 0x3BE, LOWER_CASE, 0x39E }, + { 0x3BF, LOWER_CASE, 0x39F }, + { 0x3C0, LOWER_CASE, 0x3A0 }, + { 0x3C1, LOWER_CASE, 0x3A1 }, + { 0x3C2, LOWER_CASE, 0x3A3 }, + { 0x3C3, LOWER_CASE, 0x3A3 }, + { 0x3C4, LOWER_CASE, 0x3A4 }, + { 0x3C5, LOWER_CASE, 0x3A5 }, + { 0x3C6, LOWER_CASE, 0x3A6 }, + { 0x3C7, LOWER_CASE, 0x3A7 }, + { 0x3C8, LOWER_CASE, 0x3A8 }, + { 0x3C9, LOWER_CASE, 0x3A9 }, + { 0x3CA, LOWER_CASE, 0x3AA }, + { 0x3CB, LOWER_CASE, 0x3AB }, + { 0x3CC, LOWER_CASE, 0x38C }, + { 0x3CD, LOWER_CASE, 0x38E }, + { 0x3CE, LOWER_CASE, 0x38F }, + { 0x3CF, UPPER_CASE, 0x3D7 }, + { 0x3D0, LOWER_CASE, 0x392 }, + { 0x3D1, LOWER_CASE, 0x398 }, + { 0x3D5, LOWER_CASE, 0x3A6 }, + { 0x3D6, LOWER_CASE, 0x3A0 }, + { 0x3D7, LOWER_CASE, 0x3CF }, + { 0x3D8, UPPER_CASE, 0x3D9 }, + { 0x3D9, LOWER_CASE, 0x3D8 }, + { 0x3DA, UPPER_CASE, 0x3DB }, + { 0x3DB, LOWER_CASE, 0x3DA }, + { 0x3DC, UPPER_CASE, 0x3DD }, + { 0x3DD, LOWER_CASE, 0x3DC }, + { 0x3DE, UPPER_CASE, 0x3DF }, + { 0x3DF, LOWER_CASE, 0x3DE }, + { 0x3E0, UPPER_CASE, 0x3E1 }, + { 0x3E1, LOWER_CASE, 0x3E0 }, + { 0x3E2, UPPER_CASE, 0x3E3 }, + { 0x3E3, LOWER_CASE, 0x3E2 }, + { 0x3E4, UPPER_CASE, 0x3E5 }, + { 0x3E5, LOWER_CASE, 0x3E4 }, + { 0x3E6, UPPER_CASE, 0x3E7 }, + { 0x3E7, LOWER_CASE, 0x3E6 }, + { 0x3E8, UPPER_CASE, 0x3E9 }, + { 0x3E9, LOWER_CASE, 0x3E8 }, + { 0x3EA, UPPER_CASE, 0x3EB }, + { 0x3EB, LOWER_CASE, 0x3EA }, + { 0x3EC, UPPER_CASE, 0x3ED }, + { 0x3ED, LOWER_CASE, 0x3EC }, + { 0x3EE, UPPER_CASE, 0x3EF }, + { 0x3EF, LOWER_CASE, 0x3EE }, + { 0x3F0, LOWER_CASE, 0x39A }, + { 0x3F1, LOWER_CASE, 0x3A1 }, + { 0x3F2, LOWER_CASE, 0x3F9 }, + { 0x3F3, LOWER_CASE, 0x37F }, + { 0x3F4, UPPER_CASE, 0x3B8 }, + { 0x3F5, LOWER_CASE, 0x395 }, + { 0x3F7, UPPER_CASE, 0x3F8 }, + { 0x3F8, LOWER_CASE, 0x3F7 }, + { 0x3F9, UPPER_CASE, 0x3F2 }, + { 0x3FA, UPPER_CASE, 0x3FB }, + { 0x3FB, LOWER_CASE, 0x3FA }, + { 0x3FD, UPPER_CASE, 0x37B }, + { 0x3FE, UPPER_CASE, 0x37C }, + { 0x3FF, UPPER_CASE, 0x37D }, + { 0x400, UPPER_CASE, 0x450 }, + { 0x401, UPPER_CASE, 0x451 }, + { 0x402, UPPER_CASE, 0x452 }, + { 0x403, UPPER_CASE, 0x453 }, + { 0x404, UPPER_CASE, 0x454 }, + { 0x405, UPPER_CASE, 0x455 }, + { 0x406, UPPER_CASE, 0x456 }, + { 0x407, UPPER_CASE, 0x457 }, + { 0x408, UPPER_CASE, 0x458 }, + { 0x409, UPPER_CASE, 0x459 }, + { 0x40A, UPPER_CASE, 0x45A }, + { 0x40B, UPPER_CASE, 0x45B }, + { 0x40C, UPPER_CASE, 0x45C }, + { 0x40D, UPPER_CASE, 0x45D }, + { 0x40E, UPPER_CASE, 0x45E }, + { 0x40F, UPPER_CASE, 0x45F }, + { 0x410, UPPER_CASE, 0x430 }, + { 0x411, UPPER_CASE, 0x431 }, + { 0x412, UPPER_CASE, 0x432 }, + { 0x413, UPPER_CASE, 0x433 }, + { 0x414, UPPER_CASE, 0x434 }, + { 0x415, UPPER_CASE, 0x435 }, + { 0x416, UPPER_CASE, 0x436 }, + { 0x417, UPPER_CASE, 0x437 }, + { 0x418, UPPER_CASE, 0x438 }, + { 0x419, UPPER_CASE, 0x439 }, + { 0x41A, UPPER_CASE, 0x43A }, + { 0x41B, UPPER_CASE, 0x43B }, + { 0x41C, UPPER_CASE, 0x43C }, + { 0x41D, UPPER_CASE, 0x43D }, + { 0x41E, UPPER_CASE, 0x43E }, + { 0x41F, UPPER_CASE, 0x43F }, + { 0x420, UPPER_CASE, 0x440 }, + { 0x421, UPPER_CASE, 0x441 }, + { 0x422, UPPER_CASE, 0x442 }, + { 0x423, UPPER_CASE, 0x443 }, + { 0x424, UPPER_CASE, 0x444 }, + { 0x425, UPPER_CASE, 0x445 }, + { 0x426, UPPER_CASE, 0x446 }, + { 0x427, UPPER_CASE, 0x447 }, + { 0x428, UPPER_CASE, 0x448 }, + { 0x429, UPPER_CASE, 0x449 }, + { 0x42A, UPPER_CASE, 0x44A }, + { 0x42B, UPPER_CASE, 0x44B }, + { 0x42C, UPPER_CASE, 0x44C }, + { 0x42D, UPPER_CASE, 0x44D }, + { 0x42E, UPPER_CASE, 0x44E }, + { 0x42F, UPPER_CASE, 0x44F }, + { 0x430, LOWER_CASE, 0x410 }, + { 0x431, LOWER_CASE, 0x411 }, + { 0x432, LOWER_CASE, 0x412 }, + { 0x433, LOWER_CASE, 0x413 }, + { 0x434, LOWER_CASE, 0x414 }, + { 0x435, LOWER_CASE, 0x415 }, + { 0x436, LOWER_CASE, 0x416 }, + { 0x437, LOWER_CASE, 0x417 }, + { 0x438, LOWER_CASE, 0x418 }, + { 0x439, LOWER_CASE, 0x419 }, + { 0x43A, LOWER_CASE, 0x41A }, + { 0x43B, LOWER_CASE, 0x41B }, + { 0x43C, LOWER_CASE, 0x41C }, + { 0x43D, LOWER_CASE, 0x41D }, + { 0x43E, LOWER_CASE, 0x41E }, + { 0x43F, LOWER_CASE, 0x41F }, + { 0x440, LOWER_CASE, 0x420 }, + { 0x441, LOWER_CASE, 0x421 }, + { 0x442, LOWER_CASE, 0x422 }, + { 0x443, LOWER_CASE, 0x423 }, + { 0x444, LOWER_CASE, 0x424 }, + { 0x445, LOWER_CASE, 0x425 }, + { 0x446, LOWER_CASE, 0x426 }, + { 0x447, LOWER_CASE, 0x427 }, + { 0x448, LOWER_CASE, 0x428 }, + { 0x449, LOWER_CASE, 0x429 }, + { 0x44A, LOWER_CASE, 0x42A }, + { 0x44B, LOWER_CASE, 0x42B }, + { 0x44C, LOWER_CASE, 0x42C }, + { 0x44D, LOWER_CASE, 0x42D }, + { 0x44E, LOWER_CASE, 0x42E }, + { 0x44F, LOWER_CASE, 0x42F }, + { 0x450, LOWER_CASE, 0x400 }, + { 0x451, LOWER_CASE, 0x401 }, + { 0x452, LOWER_CASE, 0x402 }, + { 0x453, LOWER_CASE, 0x403 }, + { 0x454, LOWER_CASE, 0x404 }, + { 0x455, LOWER_CASE, 0x405 }, + { 0x456, LOWER_CASE, 0x406 }, + { 0x457, LOWER_CASE, 0x407 }, + { 0x458, LOWER_CASE, 0x408 }, + { 0x459, LOWER_CASE, 0x409 }, + { 0x45A, LOWER_CASE, 0x40A }, + { 0x45B, LOWER_CASE, 0x40B }, + { 0x45C, LOWER_CASE, 0x40C }, + { 0x45D, LOWER_CASE, 0x40D }, + { 0x45E, LOWER_CASE, 0x40E }, + { 0x45F, LOWER_CASE, 0x40F }, + { 0x460, UPPER_CASE, 0x461 }, + { 0x461, LOWER_CASE, 0x460 }, + { 0x462, UPPER_CASE, 0x463 }, + { 0x463, LOWER_CASE, 0x462 }, + { 0x464, UPPER_CASE, 0x465 }, + { 0x465, LOWER_CASE, 0x464 }, + { 0x466, UPPER_CASE, 0x467 }, + { 0x467, LOWER_CASE, 0x466 }, + { 0x468, UPPER_CASE, 0x469 }, + { 0x469, LOWER_CASE, 0x468 }, + { 0x46A, UPPER_CASE, 0x46B }, + { 0x46B, LOWER_CASE, 0x46A }, + { 0x46C, UPPER_CASE, 0x46D }, + { 0x46D, LOWER_CASE, 0x46C }, + { 0x46E, UPPER_CASE, 0x46F }, + { 0x46F, LOWER_CASE, 0x46E }, + { 0x470, UPPER_CASE, 0x471 }, + { 0x471, LOWER_CASE, 0x470 }, + { 0x472, UPPER_CASE, 0x473 }, + { 0x473, LOWER_CASE, 0x472 }, + { 0x474, UPPER_CASE, 0x475 }, + { 0x475, LOWER_CASE, 0x474 }, + { 0x476, UPPER_CASE, 0x477 }, + { 0x477, LOWER_CASE, 0x476 }, + { 0x478, UPPER_CASE, 0x479 }, + { 0x479, LOWER_CASE, 0x478 }, + { 0x47A, UPPER_CASE, 0x47B }, + { 0x47B, LOWER_CASE, 0x47A }, + { 0x47C, UPPER_CASE, 0x47D }, + { 0x47D, LOWER_CASE, 0x47C }, + { 0x47E, UPPER_CASE, 0x47F }, + { 0x47F, LOWER_CASE, 0x47E }, + { 0x480, UPPER_CASE, 0x481 }, + { 0x481, LOWER_CASE, 0x480 }, + { 0x48A, UPPER_CASE, 0x48B }, + { 0x48B, LOWER_CASE, 0x48A }, + { 0x48C, UPPER_CASE, 0x48D }, + { 0x48D, LOWER_CASE, 0x48C }, + { 0x48E, UPPER_CASE, 0x48F }, + { 0x48F, LOWER_CASE, 0x48E }, + { 0x490, UPPER_CASE, 0x491 }, + { 0x491, LOWER_CASE, 0x490 }, + { 0x492, UPPER_CASE, 0x493 }, + { 0x493, LOWER_CASE, 0x492 }, + { 0x494, UPPER_CASE, 0x495 }, + { 0x495, LOWER_CASE, 0x494 }, + { 0x496, UPPER_CASE, 0x497 }, + { 0x497, LOWER_CASE, 0x496 }, + { 0x498, UPPER_CASE, 0x499 }, + { 0x499, LOWER_CASE, 0x498 }, + { 0x49A, UPPER_CASE, 0x49B }, + { 0x49B, LOWER_CASE, 0x49A }, + { 0x49C, UPPER_CASE, 0x49D }, + { 0x49D, LOWER_CASE, 0x49C }, + { 0x49E, UPPER_CASE, 0x49F }, + { 0x49F, LOWER_CASE, 0x49E }, + { 0x4A0, UPPER_CASE, 0x4A1 }, + { 0x4A1, LOWER_CASE, 0x4A0 }, + { 0x4A2, UPPER_CASE, 0x4A3 }, + { 0x4A3, LOWER_CASE, 0x4A2 }, + { 0x4A4, UPPER_CASE, 0x4A5 }, + { 0x4A5, LOWER_CASE, 0x4A4 }, + { 0x4A6, UPPER_CASE, 0x4A7 }, + { 0x4A7, LOWER_CASE, 0x4A6 }, + { 0x4A8, UPPER_CASE, 0x4A9 }, + { 0x4A9, LOWER_CASE, 0x4A8 }, + { 0x4AA, UPPER_CASE, 0x4AB }, + { 0x4AB, LOWER_CASE, 0x4AA }, + { 0x4AC, UPPER_CASE, 0x4AD }, + { 0x4AD, LOWER_CASE, 0x4AC }, + { 0x4AE, UPPER_CASE, 0x4AF }, + { 0x4AF, LOWER_CASE, 0x4AE }, + { 0x4B0, UPPER_CASE, 0x4B1 }, + { 0x4B1, LOWER_CASE, 0x4B0 }, + { 0x4B2, UPPER_CASE, 0x4B3 }, + { 0x4B3, LOWER_CASE, 0x4B2 }, + { 0x4B4, UPPER_CASE, 0x4B5 }, + { 0x4B5, LOWER_CASE, 0x4B4 }, + { 0x4B6, UPPER_CASE, 0x4B7 }, + { 0x4B7, LOWER_CASE, 0x4B6 }, + { 0x4B8, UPPER_CASE, 0x4B9 }, + { 0x4B9, LOWER_CASE, 0x4B8 }, + { 0x4BA, UPPER_CASE, 0x4BB }, + { 0x4BB, LOWER_CASE, 0x4BA }, + { 0x4BC, UPPER_CASE, 0x4BD }, + { 0x4BD, LOWER_CASE, 0x4BC }, + { 0x4BE, UPPER_CASE, 0x4BF }, + { 0x4BF, LOWER_CASE, 0x4BE }, + { 0x4C0, UPPER_CASE, 0x4CF }, + { 0x4C1, UPPER_CASE, 0x4C2 }, + { 0x4C2, LOWER_CASE, 0x4C1 }, + { 0x4C3, UPPER_CASE, 0x4C4 }, + { 0x4C4, LOWER_CASE, 0x4C3 }, + { 0x4C5, UPPER_CASE, 0x4C6 }, + { 0x4C6, LOWER_CASE, 0x4C5 }, + { 0x4C7, UPPER_CASE, 0x4C8 }, + { 0x4C8, LOWER_CASE, 0x4C7 }, + { 0x4C9, UPPER_CASE, 0x4CA }, + { 0x4CA, LOWER_CASE, 0x4C9 }, + { 0x4CB, UPPER_CASE, 0x4CC }, + { 0x4CC, LOWER_CASE, 0x4CB }, + { 0x4CD, UPPER_CASE, 0x4CE }, + { 0x4CE, LOWER_CASE, 0x4CD }, + { 0x4CF, LOWER_CASE, 0x4C0 }, + { 0x4D0, UPPER_CASE, 0x4D1 }, + { 0x4D1, LOWER_CASE, 0x4D0 }, + { 0x4D2, UPPER_CASE, 0x4D3 }, + { 0x4D3, LOWER_CASE, 0x4D2 }, + { 0x4D4, UPPER_CASE, 0x4D5 }, + { 0x4D5, LOWER_CASE, 0x4D4 }, + { 0x4D6, UPPER_CASE, 0x4D7 }, + { 0x4D7, LOWER_CASE, 0x4D6 }, + { 0x4D8, UPPER_CASE, 0x4D9 }, + { 0x4D9, LOWER_CASE, 0x4D8 }, + { 0x4DA, UPPER_CASE, 0x4DB }, + { 0x4DB, LOWER_CASE, 0x4DA }, + { 0x4DC, UPPER_CASE, 0x4DD }, + { 0x4DD, LOWER_CASE, 0x4DC }, + { 0x4DE, UPPER_CASE, 0x4DF }, + { 0x4DF, LOWER_CASE, 0x4DE }, + { 0x4E0, UPPER_CASE, 0x4E1 }, + { 0x4E1, LOWER_CASE, 0x4E0 }, + { 0x4E2, UPPER_CASE, 0x4E3 }, + { 0x4E3, LOWER_CASE, 0x4E2 }, + { 0x4E4, UPPER_CASE, 0x4E5 }, + { 0x4E5, LOWER_CASE, 0x4E4 }, + { 0x4E6, UPPER_CASE, 0x4E7 }, + { 0x4E7, LOWER_CASE, 0x4E6 }, + { 0x4E8, UPPER_CASE, 0x4E9 }, + { 0x4E9, LOWER_CASE, 0x4E8 }, + { 0x4EA, UPPER_CASE, 0x4EB }, + { 0x4EB, LOWER_CASE, 0x4EA }, + { 0x4EC, UPPER_CASE, 0x4ED }, + { 0x4ED, LOWER_CASE, 0x4EC }, + { 0x4EE, UPPER_CASE, 0x4EF }, + { 0x4EF, LOWER_CASE, 0x4EE }, + { 0x4F0, UPPER_CASE, 0x4F1 }, + { 0x4F1, LOWER_CASE, 0x4F0 }, + { 0x4F2, UPPER_CASE, 0x4F3 }, + { 0x4F3, LOWER_CASE, 0x4F2 }, + { 0x4F4, UPPER_CASE, 0x4F5 }, + { 0x4F5, LOWER_CASE, 0x4F4 }, + { 0x4F6, UPPER_CASE, 0x4F7 }, + { 0x4F7, LOWER_CASE, 0x4F6 }, + { 0x4F8, UPPER_CASE, 0x4F9 }, + { 0x4F9, LOWER_CASE, 0x4F8 }, + { 0x4FA, UPPER_CASE, 0x4FB }, + { 0x4FB, LOWER_CASE, 0x4FA }, + { 0x4FC, UPPER_CASE, 0x4FD }, + { 0x4FD, LOWER_CASE, 0x4FC }, + { 0x4FE, UPPER_CASE, 0x4FF }, + { 0x4FF, LOWER_CASE, 0x4FE }, + { 0x500, UPPER_CASE, 0x501 }, + { 0x501, LOWER_CASE, 0x500 }, + { 0x502, UPPER_CASE, 0x503 }, + { 0x503, LOWER_CASE, 0x502 }, + { 0x504, UPPER_CASE, 0x505 }, + { 0x505, LOWER_CASE, 0x504 }, + { 0x506, UPPER_CASE, 0x507 }, + { 0x507, LOWER_CASE, 0x506 }, + { 0x508, UPPER_CASE, 0x509 }, + { 0x509, LOWER_CASE, 0x508 }, + { 0x50A, UPPER_CASE, 0x50B }, + { 0x50B, LOWER_CASE, 0x50A }, + { 0x50C, UPPER_CASE, 0x50D }, + { 0x50D, LOWER_CASE, 0x50C }, + { 0x50E, UPPER_CASE, 0x50F }, + { 0x50F, LOWER_CASE, 0x50E }, + { 0x510, UPPER_CASE, 0x511 }, + { 0x511, LOWER_CASE, 0x510 }, + { 0x512, UPPER_CASE, 0x513 }, + { 0x513, LOWER_CASE, 0x512 }, + { 0x514, UPPER_CASE, 0x515 }, + { 0x515, LOWER_CASE, 0x514 }, + { 0x516, UPPER_CASE, 0x517 }, + { 0x517, LOWER_CASE, 0x516 }, + { 0x518, UPPER_CASE, 0x519 }, + { 0x519, LOWER_CASE, 0x518 }, + { 0x51A, UPPER_CASE, 0x51B }, + { 0x51B, LOWER_CASE, 0x51A }, + { 0x51C, UPPER_CASE, 0x51D }, + { 0x51D, LOWER_CASE, 0x51C }, + { 0x51E, UPPER_CASE, 0x51F }, + { 0x51F, LOWER_CASE, 0x51E }, + { 0x520, UPPER_CASE, 0x521 }, + { 0x521, LOWER_CASE, 0x520 }, + { 0x522, UPPER_CASE, 0x523 }, + { 0x523, LOWER_CASE, 0x522 }, + { 0x524, UPPER_CASE, 0x525 }, + { 0x525, LOWER_CASE, 0x524 }, + { 0x526, UPPER_CASE, 0x527 }, + { 0x527, LOWER_CASE, 0x526 }, + { 0x528, UPPER_CASE, 0x529 }, + { 0x529, LOWER_CASE, 0x528 }, + { 0x52A, UPPER_CASE, 0x52B }, + { 0x52B, LOWER_CASE, 0x52A }, + { 0x52C, UPPER_CASE, 0x52D }, + { 0x52D, LOWER_CASE, 0x52C }, + { 0x52E, UPPER_CASE, 0x52F }, + { 0x52F, LOWER_CASE, 0x52E }, + { 0x531, UPPER_CASE, 0x561 }, + { 0x532, UPPER_CASE, 0x562 }, + { 0x533, UPPER_CASE, 0x563 }, + { 0x534, UPPER_CASE, 0x564 }, + { 0x535, UPPER_CASE, 0x565 }, + { 0x536, UPPER_CASE, 0x566 }, + { 0x537, UPPER_CASE, 0x567 }, + { 0x538, UPPER_CASE, 0x568 }, + { 0x539, UPPER_CASE, 0x569 }, + { 0x53A, UPPER_CASE, 0x56A }, + { 0x53B, UPPER_CASE, 0x56B }, + { 0x53C, UPPER_CASE, 0x56C }, + { 0x53D, UPPER_CASE, 0x56D }, + { 0x53E, UPPER_CASE, 0x56E }, + { 0x53F, UPPER_CASE, 0x56F }, + { 0x540, UPPER_CASE, 0x570 }, + { 0x541, UPPER_CASE, 0x571 }, + { 0x542, UPPER_CASE, 0x572 }, + { 0x543, UPPER_CASE, 0x573 }, + { 0x544, UPPER_CASE, 0x574 }, + { 0x545, UPPER_CASE, 0x575 }, + { 0x546, UPPER_CASE, 0x576 }, + { 0x547, UPPER_CASE, 0x577 }, + { 0x548, UPPER_CASE, 0x578 }, + { 0x549, UPPER_CASE, 0x579 }, + { 0x54A, UPPER_CASE, 0x57A }, + { 0x54B, UPPER_CASE, 0x57B }, + { 0x54C, UPPER_CASE, 0x57C }, + { 0x54D, UPPER_CASE, 0x57D }, + { 0x54E, UPPER_CASE, 0x57E }, + { 0x54F, UPPER_CASE, 0x57F }, + { 0x550, UPPER_CASE, 0x580 }, + { 0x551, UPPER_CASE, 0x581 }, + { 0x552, UPPER_CASE, 0x582 }, + { 0x553, UPPER_CASE, 0x583 }, + { 0x554, UPPER_CASE, 0x584 }, + { 0x555, UPPER_CASE, 0x585 }, + { 0x556, UPPER_CASE, 0x586 }, + { 0x561, LOWER_CASE, 0x531 }, + { 0x562, LOWER_CASE, 0x532 }, + { 0x563, LOWER_CASE, 0x533 }, + { 0x564, LOWER_CASE, 0x534 }, + { 0x565, LOWER_CASE, 0x535 }, + { 0x566, LOWER_CASE, 0x536 }, + { 0x567, LOWER_CASE, 0x537 }, + { 0x568, LOWER_CASE, 0x538 }, + { 0x569, LOWER_CASE, 0x539 }, + { 0x56A, LOWER_CASE, 0x53A }, + { 0x56B, LOWER_CASE, 0x53B }, + { 0x56C, LOWER_CASE, 0x53C }, + { 0x56D, LOWER_CASE, 0x53D }, + { 0x56E, LOWER_CASE, 0x53E }, + { 0x56F, LOWER_CASE, 0x53F }, + { 0x570, LOWER_CASE, 0x540 }, + { 0x571, LOWER_CASE, 0x541 }, + { 0x572, LOWER_CASE, 0x542 }, + { 0x573, LOWER_CASE, 0x543 }, + { 0x574, LOWER_CASE, 0x544 }, + { 0x575, LOWER_CASE, 0x545 }, + { 0x576, LOWER_CASE, 0x546 }, + { 0x577, LOWER_CASE, 0x547 }, + { 0x578, LOWER_CASE, 0x548 }, + { 0x579, LOWER_CASE, 0x549 }, + { 0x57A, LOWER_CASE, 0x54A }, + { 0x57B, LOWER_CASE, 0x54B }, + { 0x57C, LOWER_CASE, 0x54C }, + { 0x57D, LOWER_CASE, 0x54D }, + { 0x57E, LOWER_CASE, 0x54E }, + { 0x57F, LOWER_CASE, 0x54F }, + { 0x580, LOWER_CASE, 0x550 }, + { 0x581, LOWER_CASE, 0x551 }, + { 0x582, LOWER_CASE, 0x552 }, + { 0x583, LOWER_CASE, 0x553 }, + { 0x584, LOWER_CASE, 0x554 }, + { 0x585, LOWER_CASE, 0x555 }, + { 0x586, LOWER_CASE, 0x556 }, + { 0x10A0, UPPER_CASE, 0x2D00 }, + { 0x10A1, UPPER_CASE, 0x2D01 }, + { 0x10A2, UPPER_CASE, 0x2D02 }, + { 0x10A3, UPPER_CASE, 0x2D03 }, + { 0x10A4, UPPER_CASE, 0x2D04 }, + { 0x10A5, UPPER_CASE, 0x2D05 }, + { 0x10A6, UPPER_CASE, 0x2D06 }, + { 0x10A7, UPPER_CASE, 0x2D07 }, + { 0x10A8, UPPER_CASE, 0x2D08 }, + { 0x10A9, UPPER_CASE, 0x2D09 }, + { 0x10AA, UPPER_CASE, 0x2D0A }, + { 0x10AB, UPPER_CASE, 0x2D0B }, + { 0x10AC, UPPER_CASE, 0x2D0C }, + { 0x10AD, UPPER_CASE, 0x2D0D }, + { 0x10AE, UPPER_CASE, 0x2D0E }, + { 0x10AF, UPPER_CASE, 0x2D0F }, + { 0x10B0, UPPER_CASE, 0x2D10 }, + { 0x10B1, UPPER_CASE, 0x2D11 }, + { 0x10B2, UPPER_CASE, 0x2D12 }, + { 0x10B3, UPPER_CASE, 0x2D13 }, + { 0x10B4, UPPER_CASE, 0x2D14 }, + { 0x10B5, UPPER_CASE, 0x2D15 }, + { 0x10B6, UPPER_CASE, 0x2D16 }, + { 0x10B7, UPPER_CASE, 0x2D17 }, + { 0x10B8, UPPER_CASE, 0x2D18 }, + { 0x10B9, UPPER_CASE, 0x2D19 }, + { 0x10BA, UPPER_CASE, 0x2D1A }, + { 0x10BB, UPPER_CASE, 0x2D1B }, + { 0x10BC, UPPER_CASE, 0x2D1C }, + { 0x10BD, UPPER_CASE, 0x2D1D }, + { 0x10BE, UPPER_CASE, 0x2D1E }, + { 0x10BF, UPPER_CASE, 0x2D1F }, + { 0x10C0, UPPER_CASE, 0x2D20 }, + { 0x10C1, UPPER_CASE, 0x2D21 }, + { 0x10C2, UPPER_CASE, 0x2D22 }, + { 0x10C3, UPPER_CASE, 0x2D23 }, + { 0x10C4, UPPER_CASE, 0x2D24 }, + { 0x10C5, UPPER_CASE, 0x2D25 }, + { 0x10C7, UPPER_CASE, 0x2D27 }, + { 0x10CD, UPPER_CASE, 0x2D2D }, + { 0x10D0, LOWER_CASE, 0x1C90 }, + { 0x10D1, LOWER_CASE, 0x1C91 }, + { 0x10D2, LOWER_CASE, 0x1C92 }, + { 0x10D3, LOWER_CASE, 0x1C93 }, + { 0x10D4, LOWER_CASE, 0x1C94 }, + { 0x10D5, LOWER_CASE, 0x1C95 }, + { 0x10D6, LOWER_CASE, 0x1C96 }, + { 0x10D7, LOWER_CASE, 0x1C97 }, + { 0x10D8, LOWER_CASE, 0x1C98 }, + { 0x10D9, LOWER_CASE, 0x1C99 }, + { 0x10DA, LOWER_CASE, 0x1C9A }, + { 0x10DB, LOWER_CASE, 0x1C9B }, + { 0x10DC, LOWER_CASE, 0x1C9C }, + { 0x10DD, LOWER_CASE, 0x1C9D }, + { 0x10DE, LOWER_CASE, 0x1C9E }, + { 0x10DF, LOWER_CASE, 0x1C9F }, + { 0x10E0, LOWER_CASE, 0x1CA0 }, + { 0x10E1, LOWER_CASE, 0x1CA1 }, + { 0x10E2, LOWER_CASE, 0x1CA2 }, + { 0x10E3, LOWER_CASE, 0x1CA3 }, + { 0x10E4, LOWER_CASE, 0x1CA4 }, + { 0x10E5, LOWER_CASE, 0x1CA5 }, + { 0x10E6, LOWER_CASE, 0x1CA6 }, + { 0x10E7, LOWER_CASE, 0x1CA7 }, + { 0x10E8, LOWER_CASE, 0x1CA8 }, + { 0x10E9, LOWER_CASE, 0x1CA9 }, + { 0x10EA, LOWER_CASE, 0x1CAA }, + { 0x10EB, LOWER_CASE, 0x1CAB }, + { 0x10EC, LOWER_CASE, 0x1CAC }, + { 0x10ED, LOWER_CASE, 0x1CAD }, + { 0x10EE, LOWER_CASE, 0x1CAE }, + { 0x10EF, LOWER_CASE, 0x1CAF }, + { 0x10F0, LOWER_CASE, 0x1CB0 }, + { 0x10F1, LOWER_CASE, 0x1CB1 }, + { 0x10F2, LOWER_CASE, 0x1CB2 }, + { 0x10F3, LOWER_CASE, 0x1CB3 }, + { 0x10F4, LOWER_CASE, 0x1CB4 }, + { 0x10F5, LOWER_CASE, 0x1CB5 }, + { 0x10F6, LOWER_CASE, 0x1CB6 }, + { 0x10F7, LOWER_CASE, 0x1CB7 }, + { 0x10F8, LOWER_CASE, 0x1CB8 }, + { 0x10F9, LOWER_CASE, 0x1CB9 }, + { 0x10FA, LOWER_CASE, 0x1CBA }, + { 0x10FD, LOWER_CASE, 0x1CBD }, + { 0x10FE, LOWER_CASE, 0x1CBE }, + { 0x10FF, LOWER_CASE, 0x1CBF }, + { 0x13A0, UPPER_CASE, 0xAB70 }, + { 0x13A1, UPPER_CASE, 0xAB71 }, + { 0x13A2, UPPER_CASE, 0xAB72 }, + { 0x13A3, UPPER_CASE, 0xAB73 }, + { 0x13A4, UPPER_CASE, 0xAB74 }, + { 0x13A5, UPPER_CASE, 0xAB75 }, + { 0x13A6, UPPER_CASE, 0xAB76 }, + { 0x13A7, UPPER_CASE, 0xAB77 }, + { 0x13A8, UPPER_CASE, 0xAB78 }, + { 0x13A9, UPPER_CASE, 0xAB79 }, + { 0x13AA, UPPER_CASE, 0xAB7A }, + { 0x13AB, UPPER_CASE, 0xAB7B }, + { 0x13AC, UPPER_CASE, 0xAB7C }, + { 0x13AD, UPPER_CASE, 0xAB7D }, + { 0x13AE, UPPER_CASE, 0xAB7E }, + { 0x13AF, UPPER_CASE, 0xAB7F }, + { 0x13B0, UPPER_CASE, 0xAB80 }, + { 0x13B1, UPPER_CASE, 0xAB81 }, + { 0x13B2, UPPER_CASE, 0xAB82 }, + { 0x13B3, UPPER_CASE, 0xAB83 }, + { 0x13B4, UPPER_CASE, 0xAB84 }, + { 0x13B5, UPPER_CASE, 0xAB85 }, + { 0x13B6, UPPER_CASE, 0xAB86 }, + { 0x13B7, UPPER_CASE, 0xAB87 }, + { 0x13B8, UPPER_CASE, 0xAB88 }, + { 0x13B9, UPPER_CASE, 0xAB89 }, + { 0x13BA, UPPER_CASE, 0xAB8A }, + { 0x13BB, UPPER_CASE, 0xAB8B }, + { 0x13BC, UPPER_CASE, 0xAB8C }, + { 0x13BD, UPPER_CASE, 0xAB8D }, + { 0x13BE, UPPER_CASE, 0xAB8E }, + { 0x13BF, UPPER_CASE, 0xAB8F }, + { 0x13C0, UPPER_CASE, 0xAB90 }, + { 0x13C1, UPPER_CASE, 0xAB91 }, + { 0x13C2, UPPER_CASE, 0xAB92 }, + { 0x13C3, UPPER_CASE, 0xAB93 }, + { 0x13C4, UPPER_CASE, 0xAB94 }, + { 0x13C5, UPPER_CASE, 0xAB95 }, + { 0x13C6, UPPER_CASE, 0xAB96 }, + { 0x13C7, UPPER_CASE, 0xAB97 }, + { 0x13C8, UPPER_CASE, 0xAB98 }, + { 0x13C9, UPPER_CASE, 0xAB99 }, + { 0x13CA, UPPER_CASE, 0xAB9A }, + { 0x13CB, UPPER_CASE, 0xAB9B }, + { 0x13CC, UPPER_CASE, 0xAB9C }, + { 0x13CD, UPPER_CASE, 0xAB9D }, + { 0x13CE, UPPER_CASE, 0xAB9E }, + { 0x13CF, UPPER_CASE, 0xAB9F }, + { 0x13D0, UPPER_CASE, 0xABA0 }, + { 0x13D1, UPPER_CASE, 0xABA1 }, + { 0x13D2, UPPER_CASE, 0xABA2 }, + { 0x13D3, UPPER_CASE, 0xABA3 }, + { 0x13D4, UPPER_CASE, 0xABA4 }, + { 0x13D5, UPPER_CASE, 0xABA5 }, + { 0x13D6, UPPER_CASE, 0xABA6 }, + { 0x13D7, UPPER_CASE, 0xABA7 }, + { 0x13D8, UPPER_CASE, 0xABA8 }, + { 0x13D9, UPPER_CASE, 0xABA9 }, + { 0x13DA, UPPER_CASE, 0xABAA }, + { 0x13DB, UPPER_CASE, 0xABAB }, + { 0x13DC, UPPER_CASE, 0xABAC }, + { 0x13DD, UPPER_CASE, 0xABAD }, + { 0x13DE, UPPER_CASE, 0xABAE }, + { 0x13DF, UPPER_CASE, 0xABAF }, + { 0x13E0, UPPER_CASE, 0xABB0 }, + { 0x13E1, UPPER_CASE, 0xABB1 }, + { 0x13E2, UPPER_CASE, 0xABB2 }, + { 0x13E3, UPPER_CASE, 0xABB3 }, + { 0x13E4, UPPER_CASE, 0xABB4 }, + { 0x13E5, UPPER_CASE, 0xABB5 }, + { 0x13E6, UPPER_CASE, 0xABB6 }, + { 0x13E7, UPPER_CASE, 0xABB7 }, + { 0x13E8, UPPER_CASE, 0xABB8 }, + { 0x13E9, UPPER_CASE, 0xABB9 }, + { 0x13EA, UPPER_CASE, 0xABBA }, + { 0x13EB, UPPER_CASE, 0xABBB }, + { 0x13EC, UPPER_CASE, 0xABBC }, + { 0x13ED, UPPER_CASE, 0xABBD }, + { 0x13EE, UPPER_CASE, 0xABBE }, + { 0x13EF, UPPER_CASE, 0xABBF }, + { 0x13F0, UPPER_CASE, 0x13F8 }, + { 0x13F1, UPPER_CASE, 0x13F9 }, + { 0x13F2, UPPER_CASE, 0x13FA }, + { 0x13F3, UPPER_CASE, 0x13FB }, + { 0x13F4, UPPER_CASE, 0x13FC }, + { 0x13F5, UPPER_CASE, 0x13FD }, + { 0x13F8, LOWER_CASE, 0x13F0 }, + { 0x13F9, LOWER_CASE, 0x13F1 }, + { 0x13FA, LOWER_CASE, 0x13F2 }, + { 0x13FB, LOWER_CASE, 0x13F3 }, + { 0x13FC, LOWER_CASE, 0x13F4 }, + { 0x13FD, LOWER_CASE, 0x13F5 }, + { 0x1C80, LOWER_CASE, 0x412 }, + { 0x1C81, LOWER_CASE, 0x414 }, + { 0x1C82, LOWER_CASE, 0x41E }, + { 0x1C83, LOWER_CASE, 0x421 }, + { 0x1C84, LOWER_CASE, 0x422 }, + { 0x1C85, LOWER_CASE, 0x422 }, + { 0x1C86, LOWER_CASE, 0x42A }, + { 0x1C87, LOWER_CASE, 0x462 }, + { 0x1C88, LOWER_CASE, 0xA64A }, + { 0x1C90, UPPER_CASE, 0x10D0 }, + { 0x1C91, UPPER_CASE, 0x10D1 }, + { 0x1C92, UPPER_CASE, 0x10D2 }, + { 0x1C93, UPPER_CASE, 0x10D3 }, + { 0x1C94, UPPER_CASE, 0x10D4 }, + { 0x1C95, UPPER_CASE, 0x10D5 }, + { 0x1C96, UPPER_CASE, 0x10D6 }, + { 0x1C97, UPPER_CASE, 0x10D7 }, + { 0x1C98, UPPER_CASE, 0x10D8 }, + { 0x1C99, UPPER_CASE, 0x10D9 }, + { 0x1C9A, UPPER_CASE, 0x10DA }, + { 0x1C9B, UPPER_CASE, 0x10DB }, + { 0x1C9C, UPPER_CASE, 0x10DC }, + { 0x1C9D, UPPER_CASE, 0x10DD }, + { 0x1C9E, UPPER_CASE, 0x10DE }, + { 0x1C9F, UPPER_CASE, 0x10DF }, + { 0x1CA0, UPPER_CASE, 0x10E0 }, + { 0x1CA1, UPPER_CASE, 0x10E1 }, + { 0x1CA2, UPPER_CASE, 0x10E2 }, + { 0x1CA3, UPPER_CASE, 0x10E3 }, + { 0x1CA4, UPPER_CASE, 0x10E4 }, + { 0x1CA5, UPPER_CASE, 0x10E5 }, + { 0x1CA6, UPPER_CASE, 0x10E6 }, + { 0x1CA7, UPPER_CASE, 0x10E7 }, + { 0x1CA8, UPPER_CASE, 0x10E8 }, + { 0x1CA9, UPPER_CASE, 0x10E9 }, + { 0x1CAA, UPPER_CASE, 0x10EA }, + { 0x1CAB, UPPER_CASE, 0x10EB }, + { 0x1CAC, UPPER_CASE, 0x10EC }, + { 0x1CAD, UPPER_CASE, 0x10ED }, + { 0x1CAE, UPPER_CASE, 0x10EE }, + { 0x1CAF, UPPER_CASE, 0x10EF }, + { 0x1CB0, UPPER_CASE, 0x10F0 }, + { 0x1CB1, UPPER_CASE, 0x10F1 }, + { 0x1CB2, UPPER_CASE, 0x10F2 }, + { 0x1CB3, UPPER_CASE, 0x10F3 }, + { 0x1CB4, UPPER_CASE, 0x10F4 }, + { 0x1CB5, UPPER_CASE, 0x10F5 }, + { 0x1CB6, UPPER_CASE, 0x10F6 }, + { 0x1CB7, UPPER_CASE, 0x10F7 }, + { 0x1CB8, UPPER_CASE, 0x10F8 }, + { 0x1CB9, UPPER_CASE, 0x10F9 }, + { 0x1CBA, UPPER_CASE, 0x10FA }, + { 0x1CBD, UPPER_CASE, 0x10FD }, + { 0x1CBE, UPPER_CASE, 0x10FE }, + { 0x1CBF, UPPER_CASE, 0x10FF }, + { 0x1D79, LOWER_CASE, 0xA77D }, + { 0x1D7D, LOWER_CASE, 0x2C63 }, + { 0x1D8E, LOWER_CASE, 0xA7C6 }, + { 0x1E00, UPPER_CASE, 0x1E01 }, + { 0x1E01, LOWER_CASE, 0x1E00 }, + { 0x1E02, UPPER_CASE, 0x1E03 }, + { 0x1E03, LOWER_CASE, 0x1E02 }, + { 0x1E04, UPPER_CASE, 0x1E05 }, + { 0x1E05, LOWER_CASE, 0x1E04 }, + { 0x1E06, UPPER_CASE, 0x1E07 }, + { 0x1E07, LOWER_CASE, 0x1E06 }, + { 0x1E08, UPPER_CASE, 0x1E09 }, + { 0x1E09, LOWER_CASE, 0x1E08 }, + { 0x1E0A, UPPER_CASE, 0x1E0B }, + { 0x1E0B, LOWER_CASE, 0x1E0A }, + { 0x1E0C, UPPER_CASE, 0x1E0D }, + { 0x1E0D, LOWER_CASE, 0x1E0C }, + { 0x1E0E, UPPER_CASE, 0x1E0F }, + { 0x1E0F, LOWER_CASE, 0x1E0E }, + { 0x1E10, UPPER_CASE, 0x1E11 }, + { 0x1E11, LOWER_CASE, 0x1E10 }, + { 0x1E12, UPPER_CASE, 0x1E13 }, + { 0x1E13, LOWER_CASE, 0x1E12 }, + { 0x1E14, UPPER_CASE, 0x1E15 }, + { 0x1E15, LOWER_CASE, 0x1E14 }, + { 0x1E16, UPPER_CASE, 0x1E17 }, + { 0x1E17, LOWER_CASE, 0x1E16 }, + { 0x1E18, UPPER_CASE, 0x1E19 }, + { 0x1E19, LOWER_CASE, 0x1E18 }, + { 0x1E1A, UPPER_CASE, 0x1E1B }, + { 0x1E1B, LOWER_CASE, 0x1E1A }, + { 0x1E1C, UPPER_CASE, 0x1E1D }, + { 0x1E1D, LOWER_CASE, 0x1E1C }, + { 0x1E1E, UPPER_CASE, 0x1E1F }, + { 0x1E1F, LOWER_CASE, 0x1E1E }, + { 0x1E20, UPPER_CASE, 0x1E21 }, + { 0x1E21, LOWER_CASE, 0x1E20 }, + { 0x1E22, UPPER_CASE, 0x1E23 }, + { 0x1E23, LOWER_CASE, 0x1E22 }, + { 0x1E24, UPPER_CASE, 0x1E25 }, + { 0x1E25, LOWER_CASE, 0x1E24 }, + { 0x1E26, UPPER_CASE, 0x1E27 }, + { 0x1E27, LOWER_CASE, 0x1E26 }, + { 0x1E28, UPPER_CASE, 0x1E29 }, + { 0x1E29, LOWER_CASE, 0x1E28 }, + { 0x1E2A, UPPER_CASE, 0x1E2B }, + { 0x1E2B, LOWER_CASE, 0x1E2A }, + { 0x1E2C, UPPER_CASE, 0x1E2D }, + { 0x1E2D, LOWER_CASE, 0x1E2C }, + { 0x1E2E, UPPER_CASE, 0x1E2F }, + { 0x1E2F, LOWER_CASE, 0x1E2E }, + { 0x1E30, UPPER_CASE, 0x1E31 }, + { 0x1E31, LOWER_CASE, 0x1E30 }, + { 0x1E32, UPPER_CASE, 0x1E33 }, + { 0x1E33, LOWER_CASE, 0x1E32 }, + { 0x1E34, UPPER_CASE, 0x1E35 }, + { 0x1E35, LOWER_CASE, 0x1E34 }, + { 0x1E36, UPPER_CASE, 0x1E37 }, + { 0x1E37, LOWER_CASE, 0x1E36 }, + { 0x1E38, UPPER_CASE, 0x1E39 }, + { 0x1E39, LOWER_CASE, 0x1E38 }, + { 0x1E3A, UPPER_CASE, 0x1E3B }, + { 0x1E3B, LOWER_CASE, 0x1E3A }, + { 0x1E3C, UPPER_CASE, 0x1E3D }, + { 0x1E3D, LOWER_CASE, 0x1E3C }, + { 0x1E3E, UPPER_CASE, 0x1E3F }, + { 0x1E3F, LOWER_CASE, 0x1E3E }, + { 0x1E40, UPPER_CASE, 0x1E41 }, + { 0x1E41, LOWER_CASE, 0x1E40 }, + { 0x1E42, UPPER_CASE, 0x1E43 }, + { 0x1E43, LOWER_CASE, 0x1E42 }, + { 0x1E44, UPPER_CASE, 0x1E45 }, + { 0x1E45, LOWER_CASE, 0x1E44 }, + { 0x1E46, UPPER_CASE, 0x1E47 }, + { 0x1E47, LOWER_CASE, 0x1E46 }, + { 0x1E48, UPPER_CASE, 0x1E49 }, + { 0x1E49, LOWER_CASE, 0x1E48 }, + { 0x1E4A, UPPER_CASE, 0x1E4B }, + { 0x1E4B, LOWER_CASE, 0x1E4A }, + { 0x1E4C, UPPER_CASE, 0x1E4D }, + { 0x1E4D, LOWER_CASE, 0x1E4C }, + { 0x1E4E, UPPER_CASE, 0x1E4F }, + { 0x1E4F, LOWER_CASE, 0x1E4E }, + { 0x1E50, UPPER_CASE, 0x1E51 }, + { 0x1E51, LOWER_CASE, 0x1E50 }, + { 0x1E52, UPPER_CASE, 0x1E53 }, + { 0x1E53, LOWER_CASE, 0x1E52 }, + { 0x1E54, UPPER_CASE, 0x1E55 }, + { 0x1E55, LOWER_CASE, 0x1E54 }, + { 0x1E56, UPPER_CASE, 0x1E57 }, + { 0x1E57, LOWER_CASE, 0x1E56 }, + { 0x1E58, UPPER_CASE, 0x1E59 }, + { 0x1E59, LOWER_CASE, 0x1E58 }, + { 0x1E5A, UPPER_CASE, 0x1E5B }, + { 0x1E5B, LOWER_CASE, 0x1E5A }, + { 0x1E5C, UPPER_CASE, 0x1E5D }, + { 0x1E5D, LOWER_CASE, 0x1E5C }, + { 0x1E5E, UPPER_CASE, 0x1E5F }, + { 0x1E5F, LOWER_CASE, 0x1E5E }, + { 0x1E60, UPPER_CASE, 0x1E61 }, + { 0x1E61, LOWER_CASE, 0x1E60 }, + { 0x1E62, UPPER_CASE, 0x1E63 }, + { 0x1E63, LOWER_CASE, 0x1E62 }, + { 0x1E64, UPPER_CASE, 0x1E65 }, + { 0x1E65, LOWER_CASE, 0x1E64 }, + { 0x1E66, UPPER_CASE, 0x1E67 }, + { 0x1E67, LOWER_CASE, 0x1E66 }, + { 0x1E68, UPPER_CASE, 0x1E69 }, + { 0x1E69, LOWER_CASE, 0x1E68 }, + { 0x1E6A, UPPER_CASE, 0x1E6B }, + { 0x1E6B, LOWER_CASE, 0x1E6A }, + { 0x1E6C, UPPER_CASE, 0x1E6D }, + { 0x1E6D, LOWER_CASE, 0x1E6C }, + { 0x1E6E, UPPER_CASE, 0x1E6F }, + { 0x1E6F, LOWER_CASE, 0x1E6E }, + { 0x1E70, UPPER_CASE, 0x1E71 }, + { 0x1E71, LOWER_CASE, 0x1E70 }, + { 0x1E72, UPPER_CASE, 0x1E73 }, + { 0x1E73, LOWER_CASE, 0x1E72 }, + { 0x1E74, UPPER_CASE, 0x1E75 }, + { 0x1E75, LOWER_CASE, 0x1E74 }, + { 0x1E76, UPPER_CASE, 0x1E77 }, + { 0x1E77, LOWER_CASE, 0x1E76 }, + { 0x1E78, UPPER_CASE, 0x1E79 }, + { 0x1E79, LOWER_CASE, 0x1E78 }, + { 0x1E7A, UPPER_CASE, 0x1E7B }, + { 0x1E7B, LOWER_CASE, 0x1E7A }, + { 0x1E7C, UPPER_CASE, 0x1E7D }, + { 0x1E7D, LOWER_CASE, 0x1E7C }, + { 0x1E7E, UPPER_CASE, 0x1E7F }, + { 0x1E7F, LOWER_CASE, 0x1E7E }, + { 0x1E80, UPPER_CASE, 0x1E81 }, + { 0x1E81, LOWER_CASE, 0x1E80 }, + { 0x1E82, UPPER_CASE, 0x1E83 }, + { 0x1E83, LOWER_CASE, 0x1E82 }, + { 0x1E84, UPPER_CASE, 0x1E85 }, + { 0x1E85, LOWER_CASE, 0x1E84 }, + { 0x1E86, UPPER_CASE, 0x1E87 }, + { 0x1E87, LOWER_CASE, 0x1E86 }, + { 0x1E88, UPPER_CASE, 0x1E89 }, + { 0x1E89, LOWER_CASE, 0x1E88 }, + { 0x1E8A, UPPER_CASE, 0x1E8B }, + { 0x1E8B, LOWER_CASE, 0x1E8A }, + { 0x1E8C, UPPER_CASE, 0x1E8D }, + { 0x1E8D, LOWER_CASE, 0x1E8C }, + { 0x1E8E, UPPER_CASE, 0x1E8F }, + { 0x1E8F, LOWER_CASE, 0x1E8E }, + { 0x1E90, UPPER_CASE, 0x1E91 }, + { 0x1E91, LOWER_CASE, 0x1E90 }, + { 0x1E92, UPPER_CASE, 0x1E93 }, + { 0x1E93, LOWER_CASE, 0x1E92 }, + { 0x1E94, UPPER_CASE, 0x1E95 }, + { 0x1E95, LOWER_CASE, 0x1E94 }, + { 0x1E9B, LOWER_CASE, 0x1E60 }, + { 0x1E9E, UPPER_CASE, 0xDF }, + { 0x1EA0, UPPER_CASE, 0x1EA1 }, + { 0x1EA1, LOWER_CASE, 0x1EA0 }, + { 0x1EA2, UPPER_CASE, 0x1EA3 }, + { 0x1EA3, LOWER_CASE, 0x1EA2 }, + { 0x1EA4, UPPER_CASE, 0x1EA5 }, + { 0x1EA5, LOWER_CASE, 0x1EA4 }, + { 0x1EA6, UPPER_CASE, 0x1EA7 }, + { 0x1EA7, LOWER_CASE, 0x1EA6 }, + { 0x1EA8, UPPER_CASE, 0x1EA9 }, + { 0x1EA9, LOWER_CASE, 0x1EA8 }, + { 0x1EAA, UPPER_CASE, 0x1EAB }, + { 0x1EAB, LOWER_CASE, 0x1EAA }, + { 0x1EAC, UPPER_CASE, 0x1EAD }, + { 0x1EAD, LOWER_CASE, 0x1EAC }, + { 0x1EAE, UPPER_CASE, 0x1EAF }, + { 0x1EAF, LOWER_CASE, 0x1EAE }, + { 0x1EB0, UPPER_CASE, 0x1EB1 }, + { 0x1EB1, LOWER_CASE, 0x1EB0 }, + { 0x1EB2, UPPER_CASE, 0x1EB3 }, + { 0x1EB3, LOWER_CASE, 0x1EB2 }, + { 0x1EB4, UPPER_CASE, 0x1EB5 }, + { 0x1EB5, LOWER_CASE, 0x1EB4 }, + { 0x1EB6, UPPER_CASE, 0x1EB7 }, + { 0x1EB7, LOWER_CASE, 0x1EB6 }, + { 0x1EB8, UPPER_CASE, 0x1EB9 }, + { 0x1EB9, LOWER_CASE, 0x1EB8 }, + { 0x1EBA, UPPER_CASE, 0x1EBB }, + { 0x1EBB, LOWER_CASE, 0x1EBA }, + { 0x1EBC, UPPER_CASE, 0x1EBD }, + { 0x1EBD, LOWER_CASE, 0x1EBC }, + { 0x1EBE, UPPER_CASE, 0x1EBF }, + { 0x1EBF, LOWER_CASE, 0x1EBE }, + { 0x1EC0, UPPER_CASE, 0x1EC1 }, + { 0x1EC1, LOWER_CASE, 0x1EC0 }, + { 0x1EC2, UPPER_CASE, 0x1EC3 }, + { 0x1EC3, LOWER_CASE, 0x1EC2 }, + { 0x1EC4, UPPER_CASE, 0x1EC5 }, + { 0x1EC5, LOWER_CASE, 0x1EC4 }, + { 0x1EC6, UPPER_CASE, 0x1EC7 }, + { 0x1EC7, LOWER_CASE, 0x1EC6 }, + { 0x1EC8, UPPER_CASE, 0x1EC9 }, + { 0x1EC9, LOWER_CASE, 0x1EC8 }, + { 0x1ECA, UPPER_CASE, 0x1ECB }, + { 0x1ECB, LOWER_CASE, 0x1ECA }, + { 0x1ECC, UPPER_CASE, 0x1ECD }, + { 0x1ECD, LOWER_CASE, 0x1ECC }, + { 0x1ECE, UPPER_CASE, 0x1ECF }, + { 0x1ECF, LOWER_CASE, 0x1ECE }, + { 0x1ED0, UPPER_CASE, 0x1ED1 }, + { 0x1ED1, LOWER_CASE, 0x1ED0 }, + { 0x1ED2, UPPER_CASE, 0x1ED3 }, + { 0x1ED3, LOWER_CASE, 0x1ED2 }, + { 0x1ED4, UPPER_CASE, 0x1ED5 }, + { 0x1ED5, LOWER_CASE, 0x1ED4 }, + { 0x1ED6, UPPER_CASE, 0x1ED7 }, + { 0x1ED7, LOWER_CASE, 0x1ED6 }, + { 0x1ED8, UPPER_CASE, 0x1ED9 }, + { 0x1ED9, LOWER_CASE, 0x1ED8 }, + { 0x1EDA, UPPER_CASE, 0x1EDB }, + { 0x1EDB, LOWER_CASE, 0x1EDA }, + { 0x1EDC, UPPER_CASE, 0x1EDD }, + { 0x1EDD, LOWER_CASE, 0x1EDC }, + { 0x1EDE, UPPER_CASE, 0x1EDF }, + { 0x1EDF, LOWER_CASE, 0x1EDE }, + { 0x1EE0, UPPER_CASE, 0x1EE1 }, + { 0x1EE1, LOWER_CASE, 0x1EE0 }, + { 0x1EE2, UPPER_CASE, 0x1EE3 }, + { 0x1EE3, LOWER_CASE, 0x1EE2 }, + { 0x1EE4, UPPER_CASE, 0x1EE5 }, + { 0x1EE5, LOWER_CASE, 0x1EE4 }, + { 0x1EE6, UPPER_CASE, 0x1EE7 }, + { 0x1EE7, LOWER_CASE, 0x1EE6 }, + { 0x1EE8, UPPER_CASE, 0x1EE9 }, + { 0x1EE9, LOWER_CASE, 0x1EE8 }, + { 0x1EEA, UPPER_CASE, 0x1EEB }, + { 0x1EEB, LOWER_CASE, 0x1EEA }, + { 0x1EEC, UPPER_CASE, 0x1EED }, + { 0x1EED, LOWER_CASE, 0x1EEC }, + { 0x1EEE, UPPER_CASE, 0x1EEF }, + { 0x1EEF, LOWER_CASE, 0x1EEE }, + { 0x1EF0, UPPER_CASE, 0x1EF1 }, + { 0x1EF1, LOWER_CASE, 0x1EF0 }, + { 0x1EF2, UPPER_CASE, 0x1EF3 }, + { 0x1EF3, LOWER_CASE, 0x1EF2 }, + { 0x1EF4, UPPER_CASE, 0x1EF5 }, + { 0x1EF5, LOWER_CASE, 0x1EF4 }, + { 0x1EF6, UPPER_CASE, 0x1EF7 }, + { 0x1EF7, LOWER_CASE, 0x1EF6 }, + { 0x1EF8, UPPER_CASE, 0x1EF9 }, + { 0x1EF9, LOWER_CASE, 0x1EF8 }, + { 0x1EFA, UPPER_CASE, 0x1EFB }, + { 0x1EFB, LOWER_CASE, 0x1EFA }, + { 0x1EFC, UPPER_CASE, 0x1EFD }, + { 0x1EFD, LOWER_CASE, 0x1EFC }, + { 0x1EFE, UPPER_CASE, 0x1EFF }, + { 0x1EFF, LOWER_CASE, 0x1EFE }, + { 0x1F00, LOWER_CASE, 0x1F08 }, + { 0x1F01, LOWER_CASE, 0x1F09 }, + { 0x1F02, LOWER_CASE, 0x1F0A }, + { 0x1F03, LOWER_CASE, 0x1F0B }, + { 0x1F04, LOWER_CASE, 0x1F0C }, + { 0x1F05, LOWER_CASE, 0x1F0D }, + { 0x1F06, LOWER_CASE, 0x1F0E }, + { 0x1F07, LOWER_CASE, 0x1F0F }, + { 0x1F08, UPPER_CASE, 0x1F00 }, + { 0x1F09, UPPER_CASE, 0x1F01 }, + { 0x1F0A, UPPER_CASE, 0x1F02 }, + { 0x1F0B, UPPER_CASE, 0x1F03 }, + { 0x1F0C, UPPER_CASE, 0x1F04 }, + { 0x1F0D, UPPER_CASE, 0x1F05 }, + { 0x1F0E, UPPER_CASE, 0x1F06 }, + { 0x1F0F, UPPER_CASE, 0x1F07 }, + { 0x1F10, LOWER_CASE, 0x1F18 }, + { 0x1F11, LOWER_CASE, 0x1F19 }, + { 0x1F12, LOWER_CASE, 0x1F1A }, + { 0x1F13, LOWER_CASE, 0x1F1B }, + { 0x1F14, LOWER_CASE, 0x1F1C }, + { 0x1F15, LOWER_CASE, 0x1F1D }, + { 0x1F18, UPPER_CASE, 0x1F10 }, + { 0x1F19, UPPER_CASE, 0x1F11 }, + { 0x1F1A, UPPER_CASE, 0x1F12 }, + { 0x1F1B, UPPER_CASE, 0x1F13 }, + { 0x1F1C, UPPER_CASE, 0x1F14 }, + { 0x1F1D, UPPER_CASE, 0x1F15 }, + { 0x1F20, LOWER_CASE, 0x1F28 }, + { 0x1F21, LOWER_CASE, 0x1F29 }, + { 0x1F22, LOWER_CASE, 0x1F2A }, + { 0x1F23, LOWER_CASE, 0x1F2B }, + { 0x1F24, LOWER_CASE, 0x1F2C }, + { 0x1F25, LOWER_CASE, 0x1F2D }, + { 0x1F26, LOWER_CASE, 0x1F2E }, + { 0x1F27, LOWER_CASE, 0x1F2F }, + { 0x1F28, UPPER_CASE, 0x1F20 }, + { 0x1F29, UPPER_CASE, 0x1F21 }, + { 0x1F2A, UPPER_CASE, 0x1F22 }, + { 0x1F2B, UPPER_CASE, 0x1F23 }, + { 0x1F2C, UPPER_CASE, 0x1F24 }, + { 0x1F2D, UPPER_CASE, 0x1F25 }, + { 0x1F2E, UPPER_CASE, 0x1F26 }, + { 0x1F2F, UPPER_CASE, 0x1F27 }, + { 0x1F30, LOWER_CASE, 0x1F38 }, + { 0x1F31, LOWER_CASE, 0x1F39 }, + { 0x1F32, LOWER_CASE, 0x1F3A }, + { 0x1F33, LOWER_CASE, 0x1F3B }, + { 0x1F34, LOWER_CASE, 0x1F3C }, + { 0x1F35, LOWER_CASE, 0x1F3D }, + { 0x1F36, LOWER_CASE, 0x1F3E }, + { 0x1F37, LOWER_CASE, 0x1F3F }, + { 0x1F38, UPPER_CASE, 0x1F30 }, + { 0x1F39, UPPER_CASE, 0x1F31 }, + { 0x1F3A, UPPER_CASE, 0x1F32 }, + { 0x1F3B, UPPER_CASE, 0x1F33 }, + { 0x1F3C, UPPER_CASE, 0x1F34 }, + { 0x1F3D, UPPER_CASE, 0x1F35 }, + { 0x1F3E, UPPER_CASE, 0x1F36 }, + { 0x1F3F, UPPER_CASE, 0x1F37 }, + { 0x1F40, LOWER_CASE, 0x1F48 }, + { 0x1F41, LOWER_CASE, 0x1F49 }, + { 0x1F42, LOWER_CASE, 0x1F4A }, + { 0x1F43, LOWER_CASE, 0x1F4B }, + { 0x1F44, LOWER_CASE, 0x1F4C }, + { 0x1F45, LOWER_CASE, 0x1F4D }, + { 0x1F48, UPPER_CASE, 0x1F40 }, + { 0x1F49, UPPER_CASE, 0x1F41 }, + { 0x1F4A, UPPER_CASE, 0x1F42 }, + { 0x1F4B, UPPER_CASE, 0x1F43 }, + { 0x1F4C, UPPER_CASE, 0x1F44 }, + { 0x1F4D, UPPER_CASE, 0x1F45 }, + { 0x1F51, LOWER_CASE, 0x1F59 }, + { 0x1F53, LOWER_CASE, 0x1F5B }, + { 0x1F55, LOWER_CASE, 0x1F5D }, + { 0x1F57, LOWER_CASE, 0x1F5F }, + { 0x1F59, UPPER_CASE, 0x1F51 }, + { 0x1F5B, UPPER_CASE, 0x1F53 }, + { 0x1F5D, UPPER_CASE, 0x1F55 }, + { 0x1F5F, UPPER_CASE, 0x1F57 }, + { 0x1F60, LOWER_CASE, 0x1F68 }, + { 0x1F61, LOWER_CASE, 0x1F69 }, + { 0x1F62, LOWER_CASE, 0x1F6A }, + { 0x1F63, LOWER_CASE, 0x1F6B }, + { 0x1F64, LOWER_CASE, 0x1F6C }, + { 0x1F65, LOWER_CASE, 0x1F6D }, + { 0x1F66, LOWER_CASE, 0x1F6E }, + { 0x1F67, LOWER_CASE, 0x1F6F }, + { 0x1F68, UPPER_CASE, 0x1F60 }, + { 0x1F69, UPPER_CASE, 0x1F61 }, + { 0x1F6A, UPPER_CASE, 0x1F62 }, + { 0x1F6B, UPPER_CASE, 0x1F63 }, + { 0x1F6C, UPPER_CASE, 0x1F64 }, + { 0x1F6D, UPPER_CASE, 0x1F65 }, + { 0x1F6E, UPPER_CASE, 0x1F66 }, + { 0x1F6F, UPPER_CASE, 0x1F67 }, + { 0x1F70, LOWER_CASE, 0x1FBA }, + { 0x1F71, LOWER_CASE, 0x1FBB }, + { 0x1F72, LOWER_CASE, 0x1FC8 }, + { 0x1F73, LOWER_CASE, 0x1FC9 }, + { 0x1F74, LOWER_CASE, 0x1FCA }, + { 0x1F75, LOWER_CASE, 0x1FCB }, + { 0x1F76, LOWER_CASE, 0x1FDA }, + { 0x1F77, LOWER_CASE, 0x1FDB }, + { 0x1F78, LOWER_CASE, 0x1FF8 }, + { 0x1F79, LOWER_CASE, 0x1FF9 }, + { 0x1F7A, LOWER_CASE, 0x1FEA }, + { 0x1F7B, LOWER_CASE, 0x1FEB }, + { 0x1F7C, LOWER_CASE, 0x1FFA }, + { 0x1F7D, LOWER_CASE, 0x1FFB }, + { 0x1F80, LOWER_CASE, 0x1F88 }, + { 0x1F81, LOWER_CASE, 0x1F89 }, + { 0x1F82, LOWER_CASE, 0x1F8A }, + { 0x1F83, LOWER_CASE, 0x1F8B }, + { 0x1F84, LOWER_CASE, 0x1F8C }, + { 0x1F85, LOWER_CASE, 0x1F8D }, + { 0x1F86, LOWER_CASE, 0x1F8E }, + { 0x1F87, LOWER_CASE, 0x1F8F }, + { 0x1F88, UPPER_CASE, 0x1F80 }, + { 0x1F89, UPPER_CASE, 0x1F81 }, + { 0x1F8A, UPPER_CASE, 0x1F82 }, + { 0x1F8B, UPPER_CASE, 0x1F83 }, + { 0x1F8C, UPPER_CASE, 0x1F84 }, + { 0x1F8D, UPPER_CASE, 0x1F85 }, + { 0x1F8E, UPPER_CASE, 0x1F86 }, + { 0x1F8F, UPPER_CASE, 0x1F87 }, + { 0x1F90, LOWER_CASE, 0x1F98 }, + { 0x1F91, LOWER_CASE, 0x1F99 }, + { 0x1F92, LOWER_CASE, 0x1F9A }, + { 0x1F93, LOWER_CASE, 0x1F9B }, + { 0x1F94, LOWER_CASE, 0x1F9C }, + { 0x1F95, LOWER_CASE, 0x1F9D }, + { 0x1F96, LOWER_CASE, 0x1F9E }, + { 0x1F97, LOWER_CASE, 0x1F9F }, + { 0x1F98, UPPER_CASE, 0x1F90 }, + { 0x1F99, UPPER_CASE, 0x1F91 }, + { 0x1F9A, UPPER_CASE, 0x1F92 }, + { 0x1F9B, UPPER_CASE, 0x1F93 }, + { 0x1F9C, UPPER_CASE, 0x1F94 }, + { 0x1F9D, UPPER_CASE, 0x1F95 }, + { 0x1F9E, UPPER_CASE, 0x1F96 }, + { 0x1F9F, UPPER_CASE, 0x1F97 }, + { 0x1FA0, LOWER_CASE, 0x1FA8 }, + { 0x1FA1, LOWER_CASE, 0x1FA9 }, + { 0x1FA2, LOWER_CASE, 0x1FAA }, + { 0x1FA3, LOWER_CASE, 0x1FAB }, + { 0x1FA4, LOWER_CASE, 0x1FAC }, + { 0x1FA5, LOWER_CASE, 0x1FAD }, + { 0x1FA6, LOWER_CASE, 0x1FAE }, + { 0x1FA7, LOWER_CASE, 0x1FAF }, + { 0x1FA8, UPPER_CASE, 0x1FA0 }, + { 0x1FA9, UPPER_CASE, 0x1FA1 }, + { 0x1FAA, UPPER_CASE, 0x1FA2 }, + { 0x1FAB, UPPER_CASE, 0x1FA3 }, + { 0x1FAC, UPPER_CASE, 0x1FA4 }, + { 0x1FAD, UPPER_CASE, 0x1FA5 }, + { 0x1FAE, UPPER_CASE, 0x1FA6 }, + { 0x1FAF, UPPER_CASE, 0x1FA7 }, + { 0x1FB0, LOWER_CASE, 0x1FB8 }, + { 0x1FB1, LOWER_CASE, 0x1FB9 }, + { 0x1FB3, LOWER_CASE, 0x1FBC }, + { 0x1FB8, UPPER_CASE, 0x1FB0 }, + { 0x1FB9, UPPER_CASE, 0x1FB1 }, + { 0x1FBA, UPPER_CASE, 0x1F70 }, + { 0x1FBB, UPPER_CASE, 0x1F71 }, + { 0x1FBC, UPPER_CASE, 0x1FB3 }, + { 0x1FBE, LOWER_CASE, 0x399 }, + { 0x1FC3, LOWER_CASE, 0x1FCC }, + { 0x1FC8, UPPER_CASE, 0x1F72 }, + { 0x1FC9, UPPER_CASE, 0x1F73 }, + { 0x1FCA, UPPER_CASE, 0x1F74 }, + { 0x1FCB, UPPER_CASE, 0x1F75 }, + { 0x1FCC, UPPER_CASE, 0x1FC3 }, + { 0x1FD0, LOWER_CASE, 0x1FD8 }, + { 0x1FD1, LOWER_CASE, 0x1FD9 }, + { 0x1FD8, UPPER_CASE, 0x1FD0 }, + { 0x1FD9, UPPER_CASE, 0x1FD1 }, + { 0x1FDA, UPPER_CASE, 0x1F76 }, + { 0x1FDB, UPPER_CASE, 0x1F77 }, + { 0x1FE0, LOWER_CASE, 0x1FE8 }, + { 0x1FE1, LOWER_CASE, 0x1FE9 }, + { 0x1FE5, LOWER_CASE, 0x1FEC }, + { 0x1FE8, UPPER_CASE, 0x1FE0 }, + { 0x1FE9, UPPER_CASE, 0x1FE1 }, + { 0x1FEA, UPPER_CASE, 0x1F7A }, + { 0x1FEB, UPPER_CASE, 0x1F7B }, + { 0x1FEC, UPPER_CASE, 0x1FE5 }, + { 0x1FF3, LOWER_CASE, 0x1FFC }, + { 0x1FF8, UPPER_CASE, 0x1F78 }, + { 0x1FF9, UPPER_CASE, 0x1F79 }, + { 0x1FFA, UPPER_CASE, 0x1F7C }, + { 0x1FFB, UPPER_CASE, 0x1F7D }, + { 0x1FFC, UPPER_CASE, 0x1FF3 }, + { 0x2126, UPPER_CASE, 0x3C9 }, + { 0x212A, UPPER_CASE, 0x6B }, + { 0x212B, UPPER_CASE, 0xE5 }, + { 0x2132, UPPER_CASE, 0x214E }, + { 0x214E, LOWER_CASE, 0x2132 }, + { 0x2160, UPPER_CASE, 0x2170 }, + { 0x2161, UPPER_CASE, 0x2171 }, + { 0x2162, UPPER_CASE, 0x2172 }, + { 0x2163, UPPER_CASE, 0x2173 }, + { 0x2164, UPPER_CASE, 0x2174 }, + { 0x2165, UPPER_CASE, 0x2175 }, + { 0x2166, UPPER_CASE, 0x2176 }, + { 0x2167, UPPER_CASE, 0x2177 }, + { 0x2168, UPPER_CASE, 0x2178 }, + { 0x2169, UPPER_CASE, 0x2179 }, + { 0x216A, UPPER_CASE, 0x217A }, + { 0x216B, UPPER_CASE, 0x217B }, + { 0x216C, UPPER_CASE, 0x217C }, + { 0x216D, UPPER_CASE, 0x217D }, + { 0x216E, UPPER_CASE, 0x217E }, + { 0x216F, UPPER_CASE, 0x217F }, + { 0x2170, LOWER_CASE, 0x2160 }, + { 0x2171, LOWER_CASE, 0x2161 }, + { 0x2172, LOWER_CASE, 0x2162 }, + { 0x2173, LOWER_CASE, 0x2163 }, + { 0x2174, LOWER_CASE, 0x2164 }, + { 0x2175, LOWER_CASE, 0x2165 }, + { 0x2176, LOWER_CASE, 0x2166 }, + { 0x2177, LOWER_CASE, 0x2167 }, + { 0x2178, LOWER_CASE, 0x2168 }, + { 0x2179, LOWER_CASE, 0x2169 }, + { 0x217A, LOWER_CASE, 0x216A }, + { 0x217B, LOWER_CASE, 0x216B }, + { 0x217C, LOWER_CASE, 0x216C }, + { 0x217D, LOWER_CASE, 0x216D }, + { 0x217E, LOWER_CASE, 0x216E }, + { 0x217F, LOWER_CASE, 0x216F }, + { 0x2183, UPPER_CASE, 0x2184 }, + { 0x2184, LOWER_CASE, 0x2183 }, + { 0x24B6, UPPER_CASE, 0x24D0 }, + { 0x24B7, UPPER_CASE, 0x24D1 }, + { 0x24B8, UPPER_CASE, 0x24D2 }, + { 0x24B9, UPPER_CASE, 0x24D3 }, + { 0x24BA, UPPER_CASE, 0x24D4 }, + { 0x24BB, UPPER_CASE, 0x24D5 }, + { 0x24BC, UPPER_CASE, 0x24D6 }, + { 0x24BD, UPPER_CASE, 0x24D7 }, + { 0x24BE, UPPER_CASE, 0x24D8 }, + { 0x24BF, UPPER_CASE, 0x24D9 }, + { 0x24C0, UPPER_CASE, 0x24DA }, + { 0x24C1, UPPER_CASE, 0x24DB }, + { 0x24C2, UPPER_CASE, 0x24DC }, + { 0x24C3, UPPER_CASE, 0x24DD }, + { 0x24C4, UPPER_CASE, 0x24DE }, + { 0x24C5, UPPER_CASE, 0x24DF }, + { 0x24C6, UPPER_CASE, 0x24E0 }, + { 0x24C7, UPPER_CASE, 0x24E1 }, + { 0x24C8, UPPER_CASE, 0x24E2 }, + { 0x24C9, UPPER_CASE, 0x24E3 }, + { 0x24CA, UPPER_CASE, 0x24E4 }, + { 0x24CB, UPPER_CASE, 0x24E5 }, + { 0x24CC, UPPER_CASE, 0x24E6 }, + { 0x24CD, UPPER_CASE, 0x24E7 }, + { 0x24CE, UPPER_CASE, 0x24E8 }, + { 0x24CF, UPPER_CASE, 0x24E9 }, + { 0x24D0, LOWER_CASE, 0x24B6 }, + { 0x24D1, LOWER_CASE, 0x24B7 }, + { 0x24D2, LOWER_CASE, 0x24B8 }, + { 0x24D3, LOWER_CASE, 0x24B9 }, + { 0x24D4, LOWER_CASE, 0x24BA }, + { 0x24D5, LOWER_CASE, 0x24BB }, + { 0x24D6, LOWER_CASE, 0x24BC }, + { 0x24D7, LOWER_CASE, 0x24BD }, + { 0x24D8, LOWER_CASE, 0x24BE }, + { 0x24D9, LOWER_CASE, 0x24BF }, + { 0x24DA, LOWER_CASE, 0x24C0 }, + { 0x24DB, LOWER_CASE, 0x24C1 }, + { 0x24DC, LOWER_CASE, 0x24C2 }, + { 0x24DD, LOWER_CASE, 0x24C3 }, + { 0x24DE, LOWER_CASE, 0x24C4 }, + { 0x24DF, LOWER_CASE, 0x24C5 }, + { 0x24E0, LOWER_CASE, 0x24C6 }, + { 0x24E1, LOWER_CASE, 0x24C7 }, + { 0x24E2, LOWER_CASE, 0x24C8 }, + { 0x24E3, LOWER_CASE, 0x24C9 }, + { 0x24E4, LOWER_CASE, 0x24CA }, + { 0x24E5, LOWER_CASE, 0x24CB }, + { 0x24E6, LOWER_CASE, 0x24CC }, + { 0x24E7, LOWER_CASE, 0x24CD }, + { 0x24E8, LOWER_CASE, 0x24CE }, + { 0x24E9, LOWER_CASE, 0x24CF }, + { 0x2C00, UPPER_CASE, 0x2C30 }, + { 0x2C01, UPPER_CASE, 0x2C31 }, + { 0x2C02, UPPER_CASE, 0x2C32 }, + { 0x2C03, UPPER_CASE, 0x2C33 }, + { 0x2C04, UPPER_CASE, 0x2C34 }, + { 0x2C05, UPPER_CASE, 0x2C35 }, + { 0x2C06, UPPER_CASE, 0x2C36 }, + { 0x2C07, UPPER_CASE, 0x2C37 }, + { 0x2C08, UPPER_CASE, 0x2C38 }, + { 0x2C09, UPPER_CASE, 0x2C39 }, + { 0x2C0A, UPPER_CASE, 0x2C3A }, + { 0x2C0B, UPPER_CASE, 0x2C3B }, + { 0x2C0C, UPPER_CASE, 0x2C3C }, + { 0x2C0D, UPPER_CASE, 0x2C3D }, + { 0x2C0E, UPPER_CASE, 0x2C3E }, + { 0x2C0F, UPPER_CASE, 0x2C3F }, + { 0x2C10, UPPER_CASE, 0x2C40 }, + { 0x2C11, UPPER_CASE, 0x2C41 }, + { 0x2C12, UPPER_CASE, 0x2C42 }, + { 0x2C13, UPPER_CASE, 0x2C43 }, + { 0x2C14, UPPER_CASE, 0x2C44 }, + { 0x2C15, UPPER_CASE, 0x2C45 }, + { 0x2C16, UPPER_CASE, 0x2C46 }, + { 0x2C17, UPPER_CASE, 0x2C47 }, + { 0x2C18, UPPER_CASE, 0x2C48 }, + { 0x2C19, UPPER_CASE, 0x2C49 }, + { 0x2C1A, UPPER_CASE, 0x2C4A }, + { 0x2C1B, UPPER_CASE, 0x2C4B }, + { 0x2C1C, UPPER_CASE, 0x2C4C }, + { 0x2C1D, UPPER_CASE, 0x2C4D }, + { 0x2C1E, UPPER_CASE, 0x2C4E }, + { 0x2C1F, UPPER_CASE, 0x2C4F }, + { 0x2C20, UPPER_CASE, 0x2C50 }, + { 0x2C21, UPPER_CASE, 0x2C51 }, + { 0x2C22, UPPER_CASE, 0x2C52 }, + { 0x2C23, UPPER_CASE, 0x2C53 }, + { 0x2C24, UPPER_CASE, 0x2C54 }, + { 0x2C25, UPPER_CASE, 0x2C55 }, + { 0x2C26, UPPER_CASE, 0x2C56 }, + { 0x2C27, UPPER_CASE, 0x2C57 }, + { 0x2C28, UPPER_CASE, 0x2C58 }, + { 0x2C29, UPPER_CASE, 0x2C59 }, + { 0x2C2A, UPPER_CASE, 0x2C5A }, + { 0x2C2B, UPPER_CASE, 0x2C5B }, + { 0x2C2C, UPPER_CASE, 0x2C5C }, + { 0x2C2D, UPPER_CASE, 0x2C5D }, + { 0x2C2E, UPPER_CASE, 0x2C5E }, + { 0x2C2F, UPPER_CASE, 0x2C5F }, + { 0x2C30, LOWER_CASE, 0x2C00 }, + { 0x2C31, LOWER_CASE, 0x2C01 }, + { 0x2C32, LOWER_CASE, 0x2C02 }, + { 0x2C33, LOWER_CASE, 0x2C03 }, + { 0x2C34, LOWER_CASE, 0x2C04 }, + { 0x2C35, LOWER_CASE, 0x2C05 }, + { 0x2C36, LOWER_CASE, 0x2C06 }, + { 0x2C37, LOWER_CASE, 0x2C07 }, + { 0x2C38, LOWER_CASE, 0x2C08 }, + { 0x2C39, LOWER_CASE, 0x2C09 }, + { 0x2C3A, LOWER_CASE, 0x2C0A }, + { 0x2C3B, LOWER_CASE, 0x2C0B }, + { 0x2C3C, LOWER_CASE, 0x2C0C }, + { 0x2C3D, LOWER_CASE, 0x2C0D }, + { 0x2C3E, LOWER_CASE, 0x2C0E }, + { 0x2C3F, LOWER_CASE, 0x2C0F }, + { 0x2C40, LOWER_CASE, 0x2C10 }, + { 0x2C41, LOWER_CASE, 0x2C11 }, + { 0x2C42, LOWER_CASE, 0x2C12 }, + { 0x2C43, LOWER_CASE, 0x2C13 }, + { 0x2C44, LOWER_CASE, 0x2C14 }, + { 0x2C45, LOWER_CASE, 0x2C15 }, + { 0x2C46, LOWER_CASE, 0x2C16 }, + { 0x2C47, LOWER_CASE, 0x2C17 }, + { 0x2C48, LOWER_CASE, 0x2C18 }, + { 0x2C49, LOWER_CASE, 0x2C19 }, + { 0x2C4A, LOWER_CASE, 0x2C1A }, + { 0x2C4B, LOWER_CASE, 0x2C1B }, + { 0x2C4C, LOWER_CASE, 0x2C1C }, + { 0x2C4D, LOWER_CASE, 0x2C1D }, + { 0x2C4E, LOWER_CASE, 0x2C1E }, + { 0x2C4F, LOWER_CASE, 0x2C1F }, + { 0x2C50, LOWER_CASE, 0x2C20 }, + { 0x2C51, LOWER_CASE, 0x2C21 }, + { 0x2C52, LOWER_CASE, 0x2C22 }, + { 0x2C53, LOWER_CASE, 0x2C23 }, + { 0x2C54, LOWER_CASE, 0x2C24 }, + { 0x2C55, LOWER_CASE, 0x2C25 }, + { 0x2C56, LOWER_CASE, 0x2C26 }, + { 0x2C57, LOWER_CASE, 0x2C27 }, + { 0x2C58, LOWER_CASE, 0x2C28 }, + { 0x2C59, LOWER_CASE, 0x2C29 }, + { 0x2C5A, LOWER_CASE, 0x2C2A }, + { 0x2C5B, LOWER_CASE, 0x2C2B }, + { 0x2C5C, LOWER_CASE, 0x2C2C }, + { 0x2C5D, LOWER_CASE, 0x2C2D }, + { 0x2C5E, LOWER_CASE, 0x2C2E }, + { 0x2C5F, LOWER_CASE, 0x2C2F }, + { 0x2C60, UPPER_CASE, 0x2C61 }, + { 0x2C61, LOWER_CASE, 0x2C60 }, + { 0x2C62, UPPER_CASE, 0x26B }, + { 0x2C63, UPPER_CASE, 0x1D7D }, + { 0x2C64, UPPER_CASE, 0x27D }, + { 0x2C65, LOWER_CASE, 0x23A }, + { 0x2C66, LOWER_CASE, 0x23E }, + { 0x2C67, UPPER_CASE, 0x2C68 }, + { 0x2C68, LOWER_CASE, 0x2C67 }, + { 0x2C69, UPPER_CASE, 0x2C6A }, + { 0x2C6A, LOWER_CASE, 0x2C69 }, + { 0x2C6B, UPPER_CASE, 0x2C6C }, + { 0x2C6C, LOWER_CASE, 0x2C6B }, + { 0x2C6D, UPPER_CASE, 0x251 }, + { 0x2C6E, UPPER_CASE, 0x271 }, + { 0x2C6F, UPPER_CASE, 0x250 }, + { 0x2C70, UPPER_CASE, 0x252 }, + { 0x2C72, UPPER_CASE, 0x2C73 }, + { 0x2C73, LOWER_CASE, 0x2C72 }, + { 0x2C75, UPPER_CASE, 0x2C76 }, + { 0x2C76, LOWER_CASE, 0x2C75 }, + { 0x2C7E, UPPER_CASE, 0x23F }, + { 0x2C7F, UPPER_CASE, 0x240 }, + { 0x2C80, UPPER_CASE, 0x2C81 }, + { 0x2C81, LOWER_CASE, 0x2C80 }, + { 0x2C82, UPPER_CASE, 0x2C83 }, + { 0x2C83, LOWER_CASE, 0x2C82 }, + { 0x2C84, UPPER_CASE, 0x2C85 }, + { 0x2C85, LOWER_CASE, 0x2C84 }, + { 0x2C86, UPPER_CASE, 0x2C87 }, + { 0x2C87, LOWER_CASE, 0x2C86 }, + { 0x2C88, UPPER_CASE, 0x2C89 }, + { 0x2C89, LOWER_CASE, 0x2C88 }, + { 0x2C8A, UPPER_CASE, 0x2C8B }, + { 0x2C8B, LOWER_CASE, 0x2C8A }, + { 0x2C8C, UPPER_CASE, 0x2C8D }, + { 0x2C8D, LOWER_CASE, 0x2C8C }, + { 0x2C8E, UPPER_CASE, 0x2C8F }, + { 0x2C8F, LOWER_CASE, 0x2C8E }, + { 0x2C90, UPPER_CASE, 0x2C91 }, + { 0x2C91, LOWER_CASE, 0x2C90 }, + { 0x2C92, UPPER_CASE, 0x2C93 }, + { 0x2C93, LOWER_CASE, 0x2C92 }, + { 0x2C94, UPPER_CASE, 0x2C95 }, + { 0x2C95, LOWER_CASE, 0x2C94 }, + { 0x2C96, UPPER_CASE, 0x2C97 }, + { 0x2C97, LOWER_CASE, 0x2C96 }, + { 0x2C98, UPPER_CASE, 0x2C99 }, + { 0x2C99, LOWER_CASE, 0x2C98 }, + { 0x2C9A, UPPER_CASE, 0x2C9B }, + { 0x2C9B, LOWER_CASE, 0x2C9A }, + { 0x2C9C, UPPER_CASE, 0x2C9D }, + { 0x2C9D, LOWER_CASE, 0x2C9C }, + { 0x2C9E, UPPER_CASE, 0x2C9F }, + { 0x2C9F, LOWER_CASE, 0x2C9E }, + { 0x2CA0, UPPER_CASE, 0x2CA1 }, + { 0x2CA1, LOWER_CASE, 0x2CA0 }, + { 0x2CA2, UPPER_CASE, 0x2CA3 }, + { 0x2CA3, LOWER_CASE, 0x2CA2 }, + { 0x2CA4, UPPER_CASE, 0x2CA5 }, + { 0x2CA5, LOWER_CASE, 0x2CA4 }, + { 0x2CA6, UPPER_CASE, 0x2CA7 }, + { 0x2CA7, LOWER_CASE, 0x2CA6 }, + { 0x2CA8, UPPER_CASE, 0x2CA9 }, + { 0x2CA9, LOWER_CASE, 0x2CA8 }, + { 0x2CAA, UPPER_CASE, 0x2CAB }, + { 0x2CAB, LOWER_CASE, 0x2CAA }, + { 0x2CAC, UPPER_CASE, 0x2CAD }, + { 0x2CAD, LOWER_CASE, 0x2CAC }, + { 0x2CAE, UPPER_CASE, 0x2CAF }, + { 0x2CAF, LOWER_CASE, 0x2CAE }, + { 0x2CB0, UPPER_CASE, 0x2CB1 }, + { 0x2CB1, LOWER_CASE, 0x2CB0 }, + { 0x2CB2, UPPER_CASE, 0x2CB3 }, + { 0x2CB3, LOWER_CASE, 0x2CB2 }, + { 0x2CB4, UPPER_CASE, 0x2CB5 }, + { 0x2CB5, LOWER_CASE, 0x2CB4 }, + { 0x2CB6, UPPER_CASE, 0x2CB7 }, + { 0x2CB7, LOWER_CASE, 0x2CB6 }, + { 0x2CB8, UPPER_CASE, 0x2CB9 }, + { 0x2CB9, LOWER_CASE, 0x2CB8 }, + { 0x2CBA, UPPER_CASE, 0x2CBB }, + { 0x2CBB, LOWER_CASE, 0x2CBA }, + { 0x2CBC, UPPER_CASE, 0x2CBD }, + { 0x2CBD, LOWER_CASE, 0x2CBC }, + { 0x2CBE, UPPER_CASE, 0x2CBF }, + { 0x2CBF, LOWER_CASE, 0x2CBE }, + { 0x2CC0, UPPER_CASE, 0x2CC1 }, + { 0x2CC1, LOWER_CASE, 0x2CC0 }, + { 0x2CC2, UPPER_CASE, 0x2CC3 }, + { 0x2CC3, LOWER_CASE, 0x2CC2 }, + { 0x2CC4, UPPER_CASE, 0x2CC5 }, + { 0x2CC5, LOWER_CASE, 0x2CC4 }, + { 0x2CC6, UPPER_CASE, 0x2CC7 }, + { 0x2CC7, LOWER_CASE, 0x2CC6 }, + { 0x2CC8, UPPER_CASE, 0x2CC9 }, + { 0x2CC9, LOWER_CASE, 0x2CC8 }, + { 0x2CCA, UPPER_CASE, 0x2CCB }, + { 0x2CCB, LOWER_CASE, 0x2CCA }, + { 0x2CCC, UPPER_CASE, 0x2CCD }, + { 0x2CCD, LOWER_CASE, 0x2CCC }, + { 0x2CCE, UPPER_CASE, 0x2CCF }, + { 0x2CCF, LOWER_CASE, 0x2CCE }, + { 0x2CD0, UPPER_CASE, 0x2CD1 }, + { 0x2CD1, LOWER_CASE, 0x2CD0 }, + { 0x2CD2, UPPER_CASE, 0x2CD3 }, + { 0x2CD3, LOWER_CASE, 0x2CD2 }, + { 0x2CD4, UPPER_CASE, 0x2CD5 }, + { 0x2CD5, LOWER_CASE, 0x2CD4 }, + { 0x2CD6, UPPER_CASE, 0x2CD7 }, + { 0x2CD7, LOWER_CASE, 0x2CD6 }, + { 0x2CD8, UPPER_CASE, 0x2CD9 }, + { 0x2CD9, LOWER_CASE, 0x2CD8 }, + { 0x2CDA, UPPER_CASE, 0x2CDB }, + { 0x2CDB, LOWER_CASE, 0x2CDA }, + { 0x2CDC, UPPER_CASE, 0x2CDD }, + { 0x2CDD, LOWER_CASE, 0x2CDC }, + { 0x2CDE, UPPER_CASE, 0x2CDF }, + { 0x2CDF, LOWER_CASE, 0x2CDE }, + { 0x2CE0, UPPER_CASE, 0x2CE1 }, + { 0x2CE1, LOWER_CASE, 0x2CE0 }, + { 0x2CE2, UPPER_CASE, 0x2CE3 }, + { 0x2CE3, LOWER_CASE, 0x2CE2 }, + { 0x2CEB, UPPER_CASE, 0x2CEC }, + { 0x2CEC, LOWER_CASE, 0x2CEB }, + { 0x2CED, UPPER_CASE, 0x2CEE }, + { 0x2CEE, LOWER_CASE, 0x2CED }, + { 0x2CF2, UPPER_CASE, 0x2CF3 }, + { 0x2CF3, LOWER_CASE, 0x2CF2 }, + { 0x2D00, LOWER_CASE, 0x10A0 }, + { 0x2D01, LOWER_CASE, 0x10A1 }, + { 0x2D02, LOWER_CASE, 0x10A2 }, + { 0x2D03, LOWER_CASE, 0x10A3 }, + { 0x2D04, LOWER_CASE, 0x10A4 }, + { 0x2D05, LOWER_CASE, 0x10A5 }, + { 0x2D06, LOWER_CASE, 0x10A6 }, + { 0x2D07, LOWER_CASE, 0x10A7 }, + { 0x2D08, LOWER_CASE, 0x10A8 }, + { 0x2D09, LOWER_CASE, 0x10A9 }, + { 0x2D0A, LOWER_CASE, 0x10AA }, + { 0x2D0B, LOWER_CASE, 0x10AB }, + { 0x2D0C, LOWER_CASE, 0x10AC }, + { 0x2D0D, LOWER_CASE, 0x10AD }, + { 0x2D0E, LOWER_CASE, 0x10AE }, + { 0x2D0F, LOWER_CASE, 0x10AF }, + { 0x2D10, LOWER_CASE, 0x10B0 }, + { 0x2D11, LOWER_CASE, 0x10B1 }, + { 0x2D12, LOWER_CASE, 0x10B2 }, + { 0x2D13, LOWER_CASE, 0x10B3 }, + { 0x2D14, LOWER_CASE, 0x10B4 }, + { 0x2D15, LOWER_CASE, 0x10B5 }, + { 0x2D16, LOWER_CASE, 0x10B6 }, + { 0x2D17, LOWER_CASE, 0x10B7 }, + { 0x2D18, LOWER_CASE, 0x10B8 }, + { 0x2D19, LOWER_CASE, 0x10B9 }, + { 0x2D1A, LOWER_CASE, 0x10BA }, + { 0x2D1B, LOWER_CASE, 0x10BB }, + { 0x2D1C, LOWER_CASE, 0x10BC }, + { 0x2D1D, LOWER_CASE, 0x10BD }, + { 0x2D1E, LOWER_CASE, 0x10BE }, + { 0x2D1F, LOWER_CASE, 0x10BF }, + { 0x2D20, LOWER_CASE, 0x10C0 }, + { 0x2D21, LOWER_CASE, 0x10C1 }, + { 0x2D22, LOWER_CASE, 0x10C2 }, + { 0x2D23, LOWER_CASE, 0x10C3 }, + { 0x2D24, LOWER_CASE, 0x10C4 }, + { 0x2D25, LOWER_CASE, 0x10C5 }, + { 0x2D27, LOWER_CASE, 0x10C7 }, + { 0x2D2D, LOWER_CASE, 0x10CD }, + { 0xA640, UPPER_CASE, 0xA641 }, + { 0xA641, LOWER_CASE, 0xA640 }, + { 0xA642, UPPER_CASE, 0xA643 }, + { 0xA643, LOWER_CASE, 0xA642 }, + { 0xA644, UPPER_CASE, 0xA645 }, + { 0xA645, LOWER_CASE, 0xA644 }, + { 0xA646, UPPER_CASE, 0xA647 }, + { 0xA647, LOWER_CASE, 0xA646 }, + { 0xA648, UPPER_CASE, 0xA649 }, + { 0xA649, LOWER_CASE, 0xA648 }, + { 0xA64A, UPPER_CASE, 0xA64B }, + { 0xA64B, LOWER_CASE, 0xA64A }, + { 0xA64C, UPPER_CASE, 0xA64D }, + { 0xA64D, LOWER_CASE, 0xA64C }, + { 0xA64E, UPPER_CASE, 0xA64F }, + { 0xA64F, LOWER_CASE, 0xA64E }, + { 0xA650, UPPER_CASE, 0xA651 }, + { 0xA651, LOWER_CASE, 0xA650 }, + { 0xA652, UPPER_CASE, 0xA653 }, + { 0xA653, LOWER_CASE, 0xA652 }, + { 0xA654, UPPER_CASE, 0xA655 }, + { 0xA655, LOWER_CASE, 0xA654 }, + { 0xA656, UPPER_CASE, 0xA657 }, + { 0xA657, LOWER_CASE, 0xA656 }, + { 0xA658, UPPER_CASE, 0xA659 }, + { 0xA659, LOWER_CASE, 0xA658 }, + { 0xA65A, UPPER_CASE, 0xA65B }, + { 0xA65B, LOWER_CASE, 0xA65A }, + { 0xA65C, UPPER_CASE, 0xA65D }, + { 0xA65D, LOWER_CASE, 0xA65C }, + { 0xA65E, UPPER_CASE, 0xA65F }, + { 0xA65F, LOWER_CASE, 0xA65E }, + { 0xA660, UPPER_CASE, 0xA661 }, + { 0xA661, LOWER_CASE, 0xA660 }, + { 0xA662, UPPER_CASE, 0xA663 }, + { 0xA663, LOWER_CASE, 0xA662 }, + { 0xA664, UPPER_CASE, 0xA665 }, + { 0xA665, LOWER_CASE, 0xA664 }, + { 0xA666, UPPER_CASE, 0xA667 }, + { 0xA667, LOWER_CASE, 0xA666 }, + { 0xA668, UPPER_CASE, 0xA669 }, + { 0xA669, LOWER_CASE, 0xA668 }, + { 0xA66A, UPPER_CASE, 0xA66B }, + { 0xA66B, LOWER_CASE, 0xA66A }, + { 0xA66C, UPPER_CASE, 0xA66D }, + { 0xA66D, LOWER_CASE, 0xA66C }, + { 0xA680, UPPER_CASE, 0xA681 }, + { 0xA681, LOWER_CASE, 0xA680 }, + { 0xA682, UPPER_CASE, 0xA683 }, + { 0xA683, LOWER_CASE, 0xA682 }, + { 0xA684, UPPER_CASE, 0xA685 }, + { 0xA685, LOWER_CASE, 0xA684 }, + { 0xA686, UPPER_CASE, 0xA687 }, + { 0xA687, LOWER_CASE, 0xA686 }, + { 0xA688, UPPER_CASE, 0xA689 }, + { 0xA689, LOWER_CASE, 0xA688 }, + { 0xA68A, UPPER_CASE, 0xA68B }, + { 0xA68B, LOWER_CASE, 0xA68A }, + { 0xA68C, UPPER_CASE, 0xA68D }, + { 0xA68D, LOWER_CASE, 0xA68C }, + { 0xA68E, UPPER_CASE, 0xA68F }, + { 0xA68F, LOWER_CASE, 0xA68E }, + { 0xA690, UPPER_CASE, 0xA691 }, + { 0xA691, LOWER_CASE, 0xA690 }, + { 0xA692, UPPER_CASE, 0xA693 }, + { 0xA693, LOWER_CASE, 0xA692 }, + { 0xA694, UPPER_CASE, 0xA695 }, + { 0xA695, LOWER_CASE, 0xA694 }, + { 0xA696, UPPER_CASE, 0xA697 }, + { 0xA697, LOWER_CASE, 0xA696 }, + { 0xA698, UPPER_CASE, 0xA699 }, + { 0xA699, LOWER_CASE, 0xA698 }, + { 0xA69A, UPPER_CASE, 0xA69B }, + { 0xA69B, LOWER_CASE, 0xA69A }, + { 0xA722, UPPER_CASE, 0xA723 }, + { 0xA723, LOWER_CASE, 0xA722 }, + { 0xA724, UPPER_CASE, 0xA725 }, + { 0xA725, LOWER_CASE, 0xA724 }, + { 0xA726, UPPER_CASE, 0xA727 }, + { 0xA727, LOWER_CASE, 0xA726 }, + { 0xA728, UPPER_CASE, 0xA729 }, + { 0xA729, LOWER_CASE, 0xA728 }, + { 0xA72A, UPPER_CASE, 0xA72B }, + { 0xA72B, LOWER_CASE, 0xA72A }, + { 0xA72C, UPPER_CASE, 0xA72D }, + { 0xA72D, LOWER_CASE, 0xA72C }, + { 0xA72E, UPPER_CASE, 0xA72F }, + { 0xA72F, LOWER_CASE, 0xA72E }, + { 0xA732, UPPER_CASE, 0xA733 }, + { 0xA733, LOWER_CASE, 0xA732 }, + { 0xA734, UPPER_CASE, 0xA735 }, + { 0xA735, LOWER_CASE, 0xA734 }, + { 0xA736, UPPER_CASE, 0xA737 }, + { 0xA737, LOWER_CASE, 0xA736 }, + { 0xA738, UPPER_CASE, 0xA739 }, + { 0xA739, LOWER_CASE, 0xA738 }, + { 0xA73A, UPPER_CASE, 0xA73B }, + { 0xA73B, LOWER_CASE, 0xA73A }, + { 0xA73C, UPPER_CASE, 0xA73D }, + { 0xA73D, LOWER_CASE, 0xA73C }, + { 0xA73E, UPPER_CASE, 0xA73F }, + { 0xA73F, LOWER_CASE, 0xA73E }, + { 0xA740, UPPER_CASE, 0xA741 }, + { 0xA741, LOWER_CASE, 0xA740 }, + { 0xA742, UPPER_CASE, 0xA743 }, + { 0xA743, LOWER_CASE, 0xA742 }, + { 0xA744, UPPER_CASE, 0xA745 }, + { 0xA745, LOWER_CASE, 0xA744 }, + { 0xA746, UPPER_CASE, 0xA747 }, + { 0xA747, LOWER_CASE, 0xA746 }, + { 0xA748, UPPER_CASE, 0xA749 }, + { 0xA749, LOWER_CASE, 0xA748 }, + { 0xA74A, UPPER_CASE, 0xA74B }, + { 0xA74B, LOWER_CASE, 0xA74A }, + { 0xA74C, UPPER_CASE, 0xA74D }, + { 0xA74D, LOWER_CASE, 0xA74C }, + { 0xA74E, UPPER_CASE, 0xA74F }, + { 0xA74F, LOWER_CASE, 0xA74E }, + { 0xA750, UPPER_CASE, 0xA751 }, + { 0xA751, LOWER_CASE, 0xA750 }, + { 0xA752, UPPER_CASE, 0xA753 }, + { 0xA753, LOWER_CASE, 0xA752 }, + { 0xA754, UPPER_CASE, 0xA755 }, + { 0xA755, LOWER_CASE, 0xA754 }, + { 0xA756, UPPER_CASE, 0xA757 }, + { 0xA757, LOWER_CASE, 0xA756 }, + { 0xA758, UPPER_CASE, 0xA759 }, + { 0xA759, LOWER_CASE, 0xA758 }, + { 0xA75A, UPPER_CASE, 0xA75B }, + { 0xA75B, LOWER_CASE, 0xA75A }, + { 0xA75C, UPPER_CASE, 0xA75D }, + { 0xA75D, LOWER_CASE, 0xA75C }, + { 0xA75E, UPPER_CASE, 0xA75F }, + { 0xA75F, LOWER_CASE, 0xA75E }, + { 0xA760, UPPER_CASE, 0xA761 }, + { 0xA761, LOWER_CASE, 0xA760 }, + { 0xA762, UPPER_CASE, 0xA763 }, + { 0xA763, LOWER_CASE, 0xA762 }, + { 0xA764, UPPER_CASE, 0xA765 }, + { 0xA765, LOWER_CASE, 0xA764 }, + { 0xA766, UPPER_CASE, 0xA767 }, + { 0xA767, LOWER_CASE, 0xA766 }, + { 0xA768, UPPER_CASE, 0xA769 }, + { 0xA769, LOWER_CASE, 0xA768 }, + { 0xA76A, UPPER_CASE, 0xA76B }, + { 0xA76B, LOWER_CASE, 0xA76A }, + { 0xA76C, UPPER_CASE, 0xA76D }, + { 0xA76D, LOWER_CASE, 0xA76C }, + { 0xA76E, UPPER_CASE, 0xA76F }, + { 0xA76F, LOWER_CASE, 0xA76E }, + { 0xA779, UPPER_CASE, 0xA77A }, + { 0xA77A, LOWER_CASE, 0xA779 }, + { 0xA77B, UPPER_CASE, 0xA77C }, + { 0xA77C, LOWER_CASE, 0xA77B }, + { 0xA77D, UPPER_CASE, 0x1D79 }, + { 0xA77E, UPPER_CASE, 0xA77F }, + { 0xA77F, LOWER_CASE, 0xA77E }, + { 0xA780, UPPER_CASE, 0xA781 }, + { 0xA781, LOWER_CASE, 0xA780 }, + { 0xA782, UPPER_CASE, 0xA783 }, + { 0xA783, LOWER_CASE, 0xA782 }, + { 0xA784, UPPER_CASE, 0xA785 }, + { 0xA785, LOWER_CASE, 0xA784 }, + { 0xA786, UPPER_CASE, 0xA787 }, + { 0xA787, LOWER_CASE, 0xA786 }, + { 0xA78B, UPPER_CASE, 0xA78C }, + { 0xA78C, LOWER_CASE, 0xA78B }, + { 0xA78D, UPPER_CASE, 0x265 }, + { 0xA790, UPPER_CASE, 0xA791 }, + { 0xA791, LOWER_CASE, 0xA790 }, + { 0xA792, UPPER_CASE, 0xA793 }, + { 0xA793, LOWER_CASE, 0xA792 }, + { 0xA794, LOWER_CASE, 0xA7C4 }, + { 0xA796, UPPER_CASE, 0xA797 }, + { 0xA797, LOWER_CASE, 0xA796 }, + { 0xA798, UPPER_CASE, 0xA799 }, + { 0xA799, LOWER_CASE, 0xA798 }, + { 0xA79A, UPPER_CASE, 0xA79B }, + { 0xA79B, LOWER_CASE, 0xA79A }, + { 0xA79C, UPPER_CASE, 0xA79D }, + { 0xA79D, LOWER_CASE, 0xA79C }, + { 0xA79E, UPPER_CASE, 0xA79F }, + { 0xA79F, LOWER_CASE, 0xA79E }, + { 0xA7A0, UPPER_CASE, 0xA7A1 }, + { 0xA7A1, LOWER_CASE, 0xA7A0 }, + { 0xA7A2, UPPER_CASE, 0xA7A3 }, + { 0xA7A3, LOWER_CASE, 0xA7A2 }, + { 0xA7A4, UPPER_CASE, 0xA7A5 }, + { 0xA7A5, LOWER_CASE, 0xA7A4 }, + { 0xA7A6, UPPER_CASE, 0xA7A7 }, + { 0xA7A7, LOWER_CASE, 0xA7A6 }, + { 0xA7A8, UPPER_CASE, 0xA7A9 }, + { 0xA7A9, LOWER_CASE, 0xA7A8 }, + { 0xA7AA, UPPER_CASE, 0x266 }, + { 0xA7AB, UPPER_CASE, 0x25C }, + { 0xA7AC, UPPER_CASE, 0x261 }, + { 0xA7AD, UPPER_CASE, 0x26C }, + { 0xA7AE, UPPER_CASE, 0x26A }, + { 0xA7B0, UPPER_CASE, 0x29E }, + { 0xA7B1, UPPER_CASE, 0x287 }, + { 0xA7B2, UPPER_CASE, 0x29D }, + { 0xA7B3, UPPER_CASE, 0xAB53 }, + { 0xA7B4, UPPER_CASE, 0xA7B5 }, + { 0xA7B5, LOWER_CASE, 0xA7B4 }, + { 0xA7B6, UPPER_CASE, 0xA7B7 }, + { 0xA7B7, LOWER_CASE, 0xA7B6 }, + { 0xA7B8, UPPER_CASE, 0xA7B9 }, + { 0xA7B9, LOWER_CASE, 0xA7B8 }, + { 0xA7BA, UPPER_CASE, 0xA7BB }, + { 0xA7BB, LOWER_CASE, 0xA7BA }, + { 0xA7BC, UPPER_CASE, 0xA7BD }, + { 0xA7BD, LOWER_CASE, 0xA7BC }, + { 0xA7BE, UPPER_CASE, 0xA7BF }, + { 0xA7BF, LOWER_CASE, 0xA7BE }, + { 0xA7C0, UPPER_CASE, 0xA7C1 }, + { 0xA7C1, LOWER_CASE, 0xA7C0 }, + { 0xA7C2, UPPER_CASE, 0xA7C3 }, + { 0xA7C3, LOWER_CASE, 0xA7C2 }, + { 0xA7C4, UPPER_CASE, 0xA794 }, + { 0xA7C5, UPPER_CASE, 0x282 }, + { 0xA7C6, UPPER_CASE, 0x1D8E }, + { 0xA7C7, UPPER_CASE, 0xA7C8 }, + { 0xA7C8, LOWER_CASE, 0xA7C7 }, + { 0xA7C9, UPPER_CASE, 0xA7CA }, + { 0xA7CA, LOWER_CASE, 0xA7C9 }, + { 0xA7D0, UPPER_CASE, 0xA7D1 }, + { 0xA7D1, LOWER_CASE, 0xA7D0 }, + { 0xA7D6, UPPER_CASE, 0xA7D7 }, + { 0xA7D7, LOWER_CASE, 0xA7D6 }, + { 0xA7D8, UPPER_CASE, 0xA7D9 }, + { 0xA7D9, LOWER_CASE, 0xA7D8 }, + { 0xA7F5, UPPER_CASE, 0xA7F6 }, + { 0xA7F6, LOWER_CASE, 0xA7F5 }, + { 0xAB53, LOWER_CASE, 0xA7B3 }, + { 0xAB70, LOWER_CASE, 0x13A0 }, + { 0xAB71, LOWER_CASE, 0x13A1 }, + { 0xAB72, LOWER_CASE, 0x13A2 }, + { 0xAB73, LOWER_CASE, 0x13A3 }, + { 0xAB74, LOWER_CASE, 0x13A4 }, + { 0xAB75, LOWER_CASE, 0x13A5 }, + { 0xAB76, LOWER_CASE, 0x13A6 }, + { 0xAB77, LOWER_CASE, 0x13A7 }, + { 0xAB78, LOWER_CASE, 0x13A8 }, + { 0xAB79, LOWER_CASE, 0x13A9 }, + { 0xAB7A, LOWER_CASE, 0x13AA }, + { 0xAB7B, LOWER_CASE, 0x13AB }, + { 0xAB7C, LOWER_CASE, 0x13AC }, + { 0xAB7D, LOWER_CASE, 0x13AD }, + { 0xAB7E, LOWER_CASE, 0x13AE }, + { 0xAB7F, LOWER_CASE, 0x13AF }, + { 0xAB80, LOWER_CASE, 0x13B0 }, + { 0xAB81, LOWER_CASE, 0x13B1 }, + { 0xAB82, LOWER_CASE, 0x13B2 }, + { 0xAB83, LOWER_CASE, 0x13B3 }, + { 0xAB84, LOWER_CASE, 0x13B4 }, + { 0xAB85, LOWER_CASE, 0x13B5 }, + { 0xAB86, LOWER_CASE, 0x13B6 }, + { 0xAB87, LOWER_CASE, 0x13B7 }, + { 0xAB88, LOWER_CASE, 0x13B8 }, + { 0xAB89, LOWER_CASE, 0x13B9 }, + { 0xAB8A, LOWER_CASE, 0x13BA }, + { 0xAB8B, LOWER_CASE, 0x13BB }, + { 0xAB8C, LOWER_CASE, 0x13BC }, + { 0xAB8D, LOWER_CASE, 0x13BD }, + { 0xAB8E, LOWER_CASE, 0x13BE }, + { 0xAB8F, LOWER_CASE, 0x13BF }, + { 0xAB90, LOWER_CASE, 0x13C0 }, + { 0xAB91, LOWER_CASE, 0x13C1 }, + { 0xAB92, LOWER_CASE, 0x13C2 }, + { 0xAB93, LOWER_CASE, 0x13C3 }, + { 0xAB94, LOWER_CASE, 0x13C4 }, + { 0xAB95, LOWER_CASE, 0x13C5 }, + { 0xAB96, LOWER_CASE, 0x13C6 }, + { 0xAB97, LOWER_CASE, 0x13C7 }, + { 0xAB98, LOWER_CASE, 0x13C8 }, + { 0xAB99, LOWER_CASE, 0x13C9 }, + { 0xAB9A, LOWER_CASE, 0x13CA }, + { 0xAB9B, LOWER_CASE, 0x13CB }, + { 0xAB9C, LOWER_CASE, 0x13CC }, + { 0xAB9D, LOWER_CASE, 0x13CD }, + { 0xAB9E, LOWER_CASE, 0x13CE }, + { 0xAB9F, LOWER_CASE, 0x13CF }, + { 0xABA0, LOWER_CASE, 0x13D0 }, + { 0xABA1, LOWER_CASE, 0x13D1 }, + { 0xABA2, LOWER_CASE, 0x13D2 }, + { 0xABA3, LOWER_CASE, 0x13D3 }, + { 0xABA4, LOWER_CASE, 0x13D4 }, + { 0xABA5, LOWER_CASE, 0x13D5 }, + { 0xABA6, LOWER_CASE, 0x13D6 }, + { 0xABA7, LOWER_CASE, 0x13D7 }, + { 0xABA8, LOWER_CASE, 0x13D8 }, + { 0xABA9, LOWER_CASE, 0x13D9 }, + { 0xABAA, LOWER_CASE, 0x13DA }, + { 0xABAB, LOWER_CASE, 0x13DB }, + { 0xABAC, LOWER_CASE, 0x13DC }, + { 0xABAD, LOWER_CASE, 0x13DD }, + { 0xABAE, LOWER_CASE, 0x13DE }, + { 0xABAF, LOWER_CASE, 0x13DF }, + { 0xABB0, LOWER_CASE, 0x13E0 }, + { 0xABB1, LOWER_CASE, 0x13E1 }, + { 0xABB2, LOWER_CASE, 0x13E2 }, + { 0xABB3, LOWER_CASE, 0x13E3 }, + { 0xABB4, LOWER_CASE, 0x13E4 }, + { 0xABB5, LOWER_CASE, 0x13E5 }, + { 0xABB6, LOWER_CASE, 0x13E6 }, + { 0xABB7, LOWER_CASE, 0x13E7 }, + { 0xABB8, LOWER_CASE, 0x13E8 }, + { 0xABB9, LOWER_CASE, 0x13E9 }, + { 0xABBA, LOWER_CASE, 0x13EA }, + { 0xABBB, LOWER_CASE, 0x13EB }, + { 0xABBC, LOWER_CASE, 0x13EC }, + { 0xABBD, LOWER_CASE, 0x13ED }, + { 0xABBE, LOWER_CASE, 0x13EE }, + { 0xABBF, LOWER_CASE, 0x13EF }, + { 0xFF21, UPPER_CASE, 0xFF41 }, + { 0xFF22, UPPER_CASE, 0xFF42 }, + { 0xFF23, UPPER_CASE, 0xFF43 }, + { 0xFF24, UPPER_CASE, 0xFF44 }, + { 0xFF25, UPPER_CASE, 0xFF45 }, + { 0xFF26, UPPER_CASE, 0xFF46 }, + { 0xFF27, UPPER_CASE, 0xFF47 }, + { 0xFF28, UPPER_CASE, 0xFF48 }, + { 0xFF29, UPPER_CASE, 0xFF49 }, + { 0xFF2A, UPPER_CASE, 0xFF4A }, + { 0xFF2B, UPPER_CASE, 0xFF4B }, + { 0xFF2C, UPPER_CASE, 0xFF4C }, + { 0xFF2D, UPPER_CASE, 0xFF4D }, + { 0xFF2E, UPPER_CASE, 0xFF4E }, + { 0xFF2F, UPPER_CASE, 0xFF4F }, + { 0xFF30, UPPER_CASE, 0xFF50 }, + { 0xFF31, UPPER_CASE, 0xFF51 }, + { 0xFF32, UPPER_CASE, 0xFF52 }, + { 0xFF33, UPPER_CASE, 0xFF53 }, + { 0xFF34, UPPER_CASE, 0xFF54 }, + { 0xFF35, UPPER_CASE, 0xFF55 }, + { 0xFF36, UPPER_CASE, 0xFF56 }, + { 0xFF37, UPPER_CASE, 0xFF57 }, + { 0xFF38, UPPER_CASE, 0xFF58 }, + { 0xFF39, UPPER_CASE, 0xFF59 }, + { 0xFF3A, UPPER_CASE, 0xFF5A }, + { 0xFF41, LOWER_CASE, 0xFF21 }, + { 0xFF42, LOWER_CASE, 0xFF22 }, + { 0xFF43, LOWER_CASE, 0xFF23 }, + { 0xFF44, LOWER_CASE, 0xFF24 }, + { 0xFF45, LOWER_CASE, 0xFF25 }, + { 0xFF46, LOWER_CASE, 0xFF26 }, + { 0xFF47, LOWER_CASE, 0xFF27 }, + { 0xFF48, LOWER_CASE, 0xFF28 }, + { 0xFF49, LOWER_CASE, 0xFF29 }, + { 0xFF4A, LOWER_CASE, 0xFF2A }, + { 0xFF4B, LOWER_CASE, 0xFF2B }, + { 0xFF4C, LOWER_CASE, 0xFF2C }, + { 0xFF4D, LOWER_CASE, 0xFF2D }, + { 0xFF4E, LOWER_CASE, 0xFF2E }, + { 0xFF4F, LOWER_CASE, 0xFF2F }, + { 0xFF50, LOWER_CASE, 0xFF30 }, + { 0xFF51, LOWER_CASE, 0xFF31 }, + { 0xFF52, LOWER_CASE, 0xFF32 }, + { 0xFF53, LOWER_CASE, 0xFF33 }, + { 0xFF54, LOWER_CASE, 0xFF34 }, + { 0xFF55, LOWER_CASE, 0xFF35 }, + { 0xFF56, LOWER_CASE, 0xFF36 }, + { 0xFF57, LOWER_CASE, 0xFF37 }, + { 0xFF58, LOWER_CASE, 0xFF38 }, + { 0xFF59, LOWER_CASE, 0xFF39 }, + { 0xFF5A, LOWER_CASE, 0xFF3A }, +}; + +#define UNICODE_DATA_SIZE 2359 + +static int UnicodeDataComp(const void *opposingCode, const void *elem) +{ + CHAR16_T code = ((UnicodeDataRec*)elem)->code; + + if (*((CHAR16_T*)opposingCode) < code) + { + return -1; + } + else if (*((CHAR16_T*)opposingCode) > code) + { + return 1; + } + else + { + return 0; + } +} + +CHAR16_T minipal_toupper_invariant(CHAR16_T code) +{ + UnicodeDataRec *record = (UnicodeDataRec *) bsearch(&code, UnicodeData, UNICODE_DATA_SIZE, + sizeof(UnicodeDataRec), UnicodeDataComp); + + if (!record || record->upperOrLower != LOWER_CASE) + return code; + + return record->opposingCode; +} + +CHAR16_T minipal_tolower_invariant(CHAR16_T code) +{ + UnicodeDataRec *record = (UnicodeDataRec *) bsearch(&code, UnicodeData, UNICODE_DATA_SIZE, + sizeof(UnicodeDataRec), UnicodeDataComp); + + if (!record || record->upperOrLower != UPPER_CASE) + return code; + + return record->opposingCode; +} diff --git a/src/native/minipal/utf8.h b/src/native/minipal/utf8.h index bd648f137a2b..009f0f0c1712 100644 --- a/src/native/minipal/utf8.h +++ b/src/native/minipal/utf8.h @@ -5,7 +5,7 @@ #define HAVE_MINIPAL_UTF8_H #include -#include +#include #include #define MINIPAL_MB_NO_REPLACE_INVALID_CHARS 0x00000008 @@ -18,12 +18,6 @@ extern "C" { #endif // __cplusplus -#ifdef TARGET_WINDOWS -typedef wchar_t CHAR16_T; -#else -typedef unsigned short CHAR16_T; -#endif - /** * Get length of destination needed for UTF-8 to UTF-16 (UCS-2) conversion * diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index 09d58b2a9d08..2dc46b0c65a7 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -752,7 +752,7 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st if (CollectTrimmingEligibleMethods) { - string assemblyName = assemblyFilename.Replace(".", "_"); + string assemblyName = FixupSymbolName(assemblyFilename); string outputFileName = assemblyName + "_compiled_methods.txt"; string outputFilePath; if (string.IsNullOrEmpty(TrimmingEligibleMethodsOutputDirectory)) @@ -1237,26 +1237,7 @@ private string FixupSymbolName(string name) if (_symbolNameFixups.TryGetValue(name, out string? fixedName)) return fixedName; - UTF8Encoding utf8 = new(); - byte[] bytes = utf8.GetBytes(name); - StringBuilder sb = new(); - - foreach (byte b in bytes) - { - if ((b >= (byte)'0' && b <= (byte)'9') || - (b >= (byte)'a' && b <= (byte)'z') || - (b >= (byte)'A' && b <= (byte)'Z') || - (b == (byte)'_')) - { - sb.Append((char)b); - } - else - { - sb.Append('_'); - } - } - - fixedName = sb.ToString(); + fixedName = Utils.FixupSymbolName(name); _symbolNameFixups[name] = fixedName; return fixedName; } diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.props b/src/tasks/AotCompilerTask/MonoAOTCompiler.props index 1c7bc065d2a4..1fc8e8f41adf 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.props +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.props @@ -1,9 +1,9 @@ - + - + diff --git a/src/tasks/AppleAppBuilder/Xcode.cs b/src/tasks/AppleAppBuilder/Xcode.cs index a9bf648f8129..aed4bf7dfaeb 100644 --- a/src/tasks/AppleAppBuilder/Xcode.cs +++ b/src/tasks/AppleAppBuilder/Xcode.cs @@ -218,15 +218,24 @@ public void CreateXcodeProject(string projectName, string cmakeDirectoryPath) targetName = Target.ToString(); break; } - var deployTarget = (Target == TargetNames.MacCatalyst) ? " -DCMAKE_OSX_ARCHITECTURES=" + XcodeArch : " -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0"; var cmakeArgs = new StringBuilder(); cmakeArgs .Append("-S.") .Append(" -B").Append(projectName) .Append(" -GXcode") .Append(" -DTARGETS_APPLE_MOBILE=1") - .Append(" -DCMAKE_SYSTEM_NAME=").Append(targetName) - .Append(deployTarget); + .Append(" -DCMAKE_SYSTEM_NAME=").Append(targetName); + + if (Target == TargetNames.MacCatalyst) + { + // min deploy target version is passed later when invoking xcodebuild + cmakeArgs.Append(" -DCMAKE_OSX_ARCHITECTURES=" + XcodeArch); + } + else + { + // arch is passed later when invoking xcodebuild + cmakeArgs.Append(" -DCMAKE_OSX_DEPLOYMENT_TARGET=12.2"); + } Utils.RunProcess(Logger, "cmake", cmakeArgs.ToString(), workingDir: cmakeDirectoryPath); } @@ -608,7 +617,7 @@ public string BuildAppBundle( .Append(" -UseModernBuildSystem=YES") .Append(" -archivePath \"").Append(Path.GetDirectoryName(xcodePrjPath)).Append('"') .Append(" -derivedDataPath \"").Append(Path.GetDirectoryName(xcodePrjPath)).Append('"') - .Append(" IPHONEOS_DEPLOYMENT_TARGET=14.2"); + .Append(" IPHONEOS_DEPLOYMENT_TARGET=15.0"); break; } } @@ -633,7 +642,7 @@ public string BuildAppBundle( .Append(" -UseModernBuildSystem=YES") .Append(" -archivePath \"").Append(Path.GetDirectoryName(xcodePrjPath)).Append('"') .Append(" -derivedDataPath \"").Append(Path.GetDirectoryName(xcodePrjPath)).Append('"') - .Append(" IPHONEOS_DEPLOYMENT_TARGET=13.5"); + .Append(" IPHONEOS_DEPLOYMENT_TARGET=15.0"); break; } } diff --git a/src/tasks/Common/Utils.cs b/src/tasks/Common/Utils.cs index eca2ccd97402..1e724bf3ce2d 100644 --- a/src/tasks/Common/Utils.cs +++ b/src/tasks/Common/Utils.cs @@ -11,6 +11,7 @@ using System.Reflection.Metadata; using System.Security.Cryptography; using System.Text; +using System.Linq; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; @@ -33,6 +34,8 @@ public enum HashEncodingType private static readonly object s_SyncObj = new object(); + private static readonly char[] s_charsToReplace = new[] { '.', '-', '+', '<', '>' }; + public static string GetEmbeddedResource(string file) { using Stream stream = typeof(Utils).Assembly @@ -323,7 +326,7 @@ public static string ComputeTextIntegrity(string str) return "sha256-" + Convert.ToBase64String(hash); } -#if NETCOREAPP +#if NET public static void DirectoryCopy(string sourceDir, string destDir, Func? predicate=null) { if (!Directory.Exists(destDir)) @@ -347,7 +350,7 @@ public static void DirectoryCopy(string sourceDir, string destDir, Func= (byte)'0' && b <= (byte)'9') || + (b >= (byte)'a' && b <= (byte)'z') || + (b >= (byte)'A' && b <= (byte)'Z') || + (b == (byte)'_')) + { + sb.Append((char)b); + } + else if (s_charsToReplace.Contains((char)b)) + { + sb.Append('_'); + } + else + { + sb.Append($"_{b:X}_"); + } + } + + return sb.ToString(); + } } diff --git a/src/tasks/Crossgen2Tasks/ResolveReadyToRunCompilers.cs b/src/tasks/Crossgen2Tasks/ResolveReadyToRunCompilers.cs index 843333ff3fcb..1ec6c1a090a6 100644 --- a/src/tasks/Crossgen2Tasks/ResolveReadyToRunCompilers.cs +++ b/src/tasks/Crossgen2Tasks/ResolveReadyToRunCompilers.cs @@ -233,6 +233,9 @@ private static bool ExtractTargetPlatformAndArchitecture(string runtimeIdentifie case "riscv64": architecture = Architecture.RiscV64; break; + case "loongarch64": + architecture = Architecture.LoongArch64; + break; default: return false; } @@ -391,6 +394,7 @@ private static string ArchitectureToString(Architecture architecture) Architecture.Arm => "arm", Architecture.Arm64 => "arm64", Architecture.RiscV64 => "riscv64", + Architecture.LoongArch64 => "loongarch64", _ => null }; } diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonBuilderHelper.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonBuilderHelper.cs index 17760e84aad0..2d075541db17 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonBuilderHelper.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonBuilderHelper.cs @@ -10,8 +10,29 @@ namespace Microsoft.NET.Sdk.WebAssembly { - public class BootJsonBuilderHelper(TaskLoggingHelper Log) + public class BootJsonBuilderHelper(TaskLoggingHelper Log, bool IsMultiThreaded) { + private static readonly string[] coreAssemblyNames = [ + "System.Private.CoreLib", + "System.Runtime.InteropServices.JavaScript", + ]; + + private static readonly string[] extraMultiThreadedCoreAssemblyName = [ + "System.Threading.Channels" + ]; + + public bool IsCoreAssembly(string fileName) + { + var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName); + if (coreAssemblyNames.Contains(fileNameWithoutExtension)) + return true; + + if (IsMultiThreaded && extraMultiThreadedCoreAssemblyName.Contains(fileNameWithoutExtension)) + return true; + + return false; + } + public void ComputeResourcesHash(BootJsonData bootConfig) { var sb = new StringBuilder(); @@ -26,8 +47,10 @@ static void AddDictionary(StringBuilder sb, Dictionary? res) } AddDictionary(sb, bootConfig.resources.assembly); + AddDictionary(sb, bootConfig.resources.coreAssembly); AddDictionary(sb, bootConfig.resources.jsModuleWorker); + AddDictionary(sb, bootConfig.resources.jsModuleGlobalization); AddDictionary(sb, bootConfig.resources.jsModuleNative); AddDictionary(sb, bootConfig.resources.jsModuleRuntime); AddDictionary(sb, bootConfig.resources.wasmNative); @@ -48,6 +71,12 @@ static void AddDictionary(StringBuilder sb, Dictionary? res) AddDictionary(sb, entry.Value); } + if (bootConfig.resources.coreVfs != null) + { + foreach (var entry in bootConfig.resources.coreVfs) + AddDictionary(sb, entry.Value); + } + bootConfig.resources.hash = Utils.ComputeTextIntegrity(sb.ToString()); } @@ -56,6 +85,8 @@ static void AddDictionary(StringBuilder sb, Dictionary? res) string resourceExtension = Path.GetExtension(resourceName); if (resourceName.StartsWith("dotnet.native.worker", StringComparison.OrdinalIgnoreCase) && string.Equals(resourceExtension, ".js", StringComparison.OrdinalIgnoreCase)) return bootConfig.resources.jsModuleWorker ??= new(); + if (resourceName.StartsWith("dotnet.globalization", StringComparison.OrdinalIgnoreCase) && string.Equals(resourceExtension, ".js", StringComparison.OrdinalIgnoreCase)) + return bootConfig.resources.jsModuleGlobalization ??= new(); else if (resourceName.StartsWith("dotnet.native", StringComparison.OrdinalIgnoreCase) && string.Equals(resourceExtension, ".js", StringComparison.OrdinalIgnoreCase)) return bootConfig.resources.jsModuleNative ??= new(); else if (resourceName.StartsWith("dotnet.runtime", StringComparison.OrdinalIgnoreCase) && string.Equals(resourceExtension, ".js", StringComparison.OrdinalIgnoreCase)) diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonData.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonData.cs index 22edc2c68fbe..19c0d1f02e76 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonData.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonData.cs @@ -137,6 +137,9 @@ public class ResourcesData [DataMember(EmitDefaultValue = false)] public ResourceHashesByNameDictionary jsModuleWorker { get; set; } + [DataMember(EmitDefaultValue = false)] + public ResourceHashesByNameDictionary jsModuleGlobalization { get; set; } + [DataMember(EmitDefaultValue = false)] public ResourceHashesByNameDictionary jsModuleNative { get; set; } @@ -152,11 +155,22 @@ public class ResourcesData [DataMember(EmitDefaultValue = false)] public ResourceHashesByNameDictionary icu { get; set; } + /// + /// "assembly" (.dll) resources needed to start MonoVM + /// + public ResourceHashesByNameDictionary coreAssembly { get; set; } = new ResourceHashesByNameDictionary(); + /// /// "assembly" (.dll) resources /// public ResourceHashesByNameDictionary assembly { get; set; } = new ResourceHashesByNameDictionary(); + /// + /// "debug" (.pdb) resources needed to start MonoVM + /// + [DataMember(EmitDefaultValue = false)] + public ResourceHashesByNameDictionary corePdb { get; set; } + /// /// "debug" (.pdb) resources /// @@ -201,6 +215,9 @@ public class ResourcesData [DataMember(EmitDefaultValue = false)] public Dictionary runtimeAssets { get; set; } + [DataMember(EmitDefaultValue = false)] + public Dictionary coreVfs { get; set; } + [DataMember(EmitDefaultValue = false)] public Dictionary vfs { get; set; } diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs index 2d21f3820a55..01c5d4dda4dd 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Collections.Generic; using System.IO; using Microsoft.Build.Framework; @@ -59,52 +60,66 @@ public override bool Execute() continue; } - var dllFilePath = candidate.ItemSpec; - var webcilFileName = Path.GetFileNameWithoutExtension(dllFilePath) + Utils.WebcilInWasmExtension; - string candidatePath = candidate.GetMetadata("AssetTraitName") == "Culture" - ? Path.Combine(OutputPath, candidate.GetMetadata("AssetTraitValue")) - : OutputPath; - - string finalWebcil = Path.Combine(candidatePath, webcilFileName); - - if (Utils.IsNewerThan(dllFilePath, finalWebcil)) + try { - var tmpWebcil = Path.Combine(tmpDir, webcilFileName); - var logAdapter = new LogAdapter(Log); - var webcilWriter = Microsoft.WebAssembly.Build.Tasks.WebcilConverter.FromPortableExecutable(inputPath: dllFilePath, outputPath: tmpWebcil, logger: logAdapter); - webcilWriter.ConvertToWebcil(); - - if (!Directory.Exists(candidatePath)) - Directory.CreateDirectory(candidatePath); - - if (Utils.CopyIfDifferent(tmpWebcil, finalWebcil, useHash: true)) - Log.LogMessage(MessageImportance.Low, $"Generated {finalWebcil} ."); - else - Log.LogMessage(MessageImportance.Low, $"Skipped generating {finalWebcil} as the contents are unchanged."); + TaskItem webcilItem = ConvertDll(tmpDir, candidate); + webCilCandidates.Add(webcilItem); } - else + catch (Exception ex) { - Log.LogMessage(MessageImportance.Low, $"Skipping {dllFilePath} as it is older than the output file {finalWebcil}"); + Log.LogError($"Failed to convert '{candidate.ItemSpec}' to webcil: {ex.Message}"); + return false; } + } + + WebCilCandidates = webCilCandidates.ToArray(); + return true; + } - _fileWrites.Add(finalWebcil); + private TaskItem ConvertDll(string tmpDir, ITaskItem candidate) + { + var dllFilePath = candidate.ItemSpec; + var webcilFileName = Path.GetFileNameWithoutExtension(dllFilePath) + Utils.WebcilInWasmExtension; + string candidatePath = candidate.GetMetadata("AssetTraitName") == "Culture" + ? Path.Combine(OutputPath, candidate.GetMetadata("AssetTraitValue")) + : OutputPath; - var webcilItem = new TaskItem(finalWebcil, candidate.CloneCustomMetadata()); - webcilItem.SetMetadata("RelativePath", Path.ChangeExtension(candidate.GetMetadata("RelativePath"), Utils.WebcilInWasmExtension)); - webcilItem.SetMetadata("OriginalItemSpec", finalWebcil); + string finalWebcil = Path.Combine(candidatePath, webcilFileName); - if (webcilItem.GetMetadata("AssetTraitName") == "Culture") - { - string relatedAsset = webcilItem.GetMetadata("RelatedAsset"); - relatedAsset = Path.ChangeExtension(relatedAsset, Utils.WebcilInWasmExtension); - webcilItem.SetMetadata("RelatedAsset", relatedAsset); - Log.LogMessage(MessageImportance.Low, $"Changing related asset of {webcilItem} to {relatedAsset}."); - } + if (Utils.IsNewerThan(dllFilePath, finalWebcil)) + { + var tmpWebcil = Path.Combine(tmpDir, webcilFileName); + var logAdapter = new LogAdapter(Log); + var webcilWriter = Microsoft.WebAssembly.Build.Tasks.WebcilConverter.FromPortableExecutable(inputPath: dllFilePath, outputPath: tmpWebcil, logger: logAdapter); + webcilWriter.ConvertToWebcil(); - webCilCandidates.Add(webcilItem); + if (!Directory.Exists(candidatePath)) + Directory.CreateDirectory(candidatePath); + + if (Utils.CopyIfDifferent(tmpWebcil, finalWebcil, useHash: true)) + Log.LogMessage(MessageImportance.Low, $"Generated {finalWebcil} ."); + else + Log.LogMessage(MessageImportance.Low, $"Skipped generating {finalWebcil} as the contents are unchanged."); + } + else + { + Log.LogMessage(MessageImportance.Low, $"Skipping {dllFilePath} as it is older than the output file {finalWebcil}"); } - WebCilCandidates = webCilCandidates.ToArray(); - return true; + _fileWrites.Add(finalWebcil); + + var webcilItem = new TaskItem(finalWebcil, candidate.CloneCustomMetadata()); + webcilItem.SetMetadata("RelativePath", Path.ChangeExtension(candidate.GetMetadata("RelativePath"), Utils.WebcilInWasmExtension)); + webcilItem.SetMetadata("OriginalItemSpec", finalWebcil); + + if (webcilItem.GetMetadata("AssetTraitName") == "Culture") + { + string relatedAsset = webcilItem.GetMetadata("RelatedAsset"); + relatedAsset = Path.ChangeExtension(relatedAsset, Utils.WebcilInWasmExtension); + webcilItem.SetMetadata("RelatedAsset", relatedAsset); + Log.LogMessage(MessageImportance.Low, $"Changing related asset of {webcilItem} to {relatedAsset}."); + } + + return webcilItem; } } diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs index d5dc83e4252d..fbe0aa7e3733 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs @@ -22,7 +22,11 @@ namespace Microsoft.NET.Sdk.WebAssembly; public class GenerateWasmBootJson : Task { - private static readonly string[] jiterpreterOptions = new[] { "jiterpreter-traces-enabled", "jiterpreter-interp-entry-enabled", "jiterpreter-jit-call-enabled" }; + private static readonly string[] jiterpreterOptions = [ + "jiterpreter-traces-enabled", + "jiterpreter-interp-entry-enabled", + "jiterpreter-jit-call-enabled" + ]; [Required] public string AssemblyPath { get; set; } @@ -73,6 +77,10 @@ public class GenerateWasmBootJson : Task public bool IsPublish { get; set; } + public bool IsAot { get; set; } + + public bool IsMultiThreaded { get; set; } + public override bool Execute() { using var fileStream = File.Create(OutputPath); @@ -93,7 +101,7 @@ public override bool Execute() // Internal for tests public void WriteBootJson(Stream output, string entryAssemblyName) { - var helper = new BootJsonBuilderHelper(Log); + var helper = new BootJsonBuilderHelper(Log, IsMultiThreaded); var result = new BootJsonData { @@ -205,15 +213,32 @@ public void WriteBootJson(Stream output, string entryAssemblyName) } else { - Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as symbols file.", resource.ItemSpec); - resourceData.pdb ??= new ResourceHashesByNameDictionary(); - resourceList = resourceData.pdb; + if (IsTargeting90OrLater() && (IsAot || helper.IsCoreAssembly(resourceName))) + { + Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as core symbols file.", resource.ItemSpec); + resourceData.corePdb ??= new ResourceHashesByNameDictionary(); + resourceList = resourceData.corePdb; + } + else + { + Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as symbols file.", resource.ItemSpec); + resourceData.pdb ??= new ResourceHashesByNameDictionary(); + resourceList = resourceData.pdb; + } } } else if (string.Equals("runtime", assetTraitValue, StringComparison.OrdinalIgnoreCase)) { - Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as an app assembly.", resource.ItemSpec); - resourceList = resourceData.assembly; + if (IsTargeting90OrLater() && (IsAot || helper.IsCoreAssembly(resourceName))) + { + Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as core assembly.", resource.ItemSpec); + resourceList = resourceData.coreAssembly; + } + else + { + Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as an app assembly.", resource.ItemSpec); + resourceList = resourceData.assembly; + } } else if (string.Equals(assetTraitName, "WasmResource", StringComparison.OrdinalIgnoreCase) && string.Equals(assetTraitValue, "native", StringComparison.OrdinalIgnoreCase)) @@ -445,8 +470,15 @@ private bool TryGetLazyLoadedAssembly(string fileName, out ITaskItem lazyLoadedA private Version? parsedTargetFrameworkVersion; private static readonly Version version80 = new Version(8, 0); + private static readonly Version version90 = new Version(9, 0); private bool IsTargeting80OrLater() + => IsTargetingVersionOrLater(version80); + + private bool IsTargeting90OrLater() + => IsTargetingVersionOrLater(version90); + + private bool IsTargetingVersionOrLater(Version version) { if (parsedTargetFrameworkVersion == null) { @@ -457,6 +489,6 @@ private bool IsTargeting80OrLater() parsedTargetFrameworkVersion = Version.Parse(tfv); } - return parsedTargetFrameworkVersion >= version80; + return parsedTargetFrameworkVersion >= version; } } diff --git a/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs b/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs index 13c34bde4b8e..0a0495f72fef 100644 --- a/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs +++ b/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs @@ -213,7 +213,7 @@ private static void WriteSectionHeader(Stream s, WebcilSectionHeader sectionHead WriteStructure(s, sectionHeader); } -#if NETCOREAPP2_1_OR_GREATER +#if NET private static void WriteStructure(Stream s, T structure) where T : unmanaged { @@ -256,7 +256,7 @@ private static void CopySections(Stream outStream, FileStream inputStream, Immut } } -#if NETCOREAPP2_1_OR_GREATER +#if NET private static void ReadExactly(FileStream s, Span buffer) { s.ReadExactly(buffer); diff --git a/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs b/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs index ac4f9d86095a..6e079b58c325 100644 --- a/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs +++ b/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs @@ -278,7 +278,7 @@ private static MetadataReaderProvider DecodeEmbeddedPortablePdbDirectoryData(Blo using (var compressedStream = new MemoryStream(compressedBuffer, writable: false)) using (var deflateStream = new System.IO.Compression.DeflateStream(compressedStream, System.IO.Compression.CompressionMode.Decompress, leaveOpen: true)) { -#if NETCOREAPP1_1_OR_GREATER +#if NET decompressedBuffer = GC.AllocateUninitializedArray(decompressedSize); #else decompressedBuffer = new byte[decompressedSize]; diff --git a/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilWasmWrapper.cs b/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilWasmWrapper.cs index 3f8560446306..f47a12474747 100644 --- a/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilWasmWrapper.cs +++ b/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilWasmWrapper.cs @@ -63,7 +63,7 @@ public void WriteWasmWrappedWebcil(Stream outputStream) // // extracted by wasm-reader -s wrapper.wasm private static -#if NET7_0_OR_GREATER +#if NET ReadOnlyMemory #else byte[] @@ -80,7 +80,7 @@ private static // // extracted by wasm-reader -s wrapper.wasm private static -#if NET7_0_OR_GREATER +#if NET ReadOnlyMemory #else byte[] @@ -91,7 +91,7 @@ private static private static void WriteWasmHeader(Stream outputStream) { -#if NET7_0_OR_GREATER +#if NET outputStream.Write(s_wasmWrapperPrefix.Span); #else outputStream.Write(s_wasmWrapperPrefix, 0, s_wasmWrapperPrefix.Length); @@ -100,7 +100,7 @@ private static void WriteWasmHeader(Stream outputStream) private static void WriteWasmSuffix(Stream outputStream) { -#if NET7_0_OR_GREATER +#if NET outputStream.Write(s_wasmWrapperSuffix.Span); #else outputStream.Write(s_wasmWrapperSuffix, 0, s_wasmWrapperSuffix.Length); diff --git a/src/tasks/MobileBuildTasks/Apple/AppleProject.cs b/src/tasks/MobileBuildTasks/Apple/AppleProject.cs index f7927fa2bb5a..6a0f61c1968c 100644 --- a/src/tasks/MobileBuildTasks/Apple/AppleProject.cs +++ b/src/tasks/MobileBuildTasks/Apple/AppleProject.cs @@ -27,7 +27,7 @@ public AppleProject(string projectName, string runtimeIdentifier, TaskLoggingHel { GetTargets(runtimeIdentifier, out targetOS, out targetArchitecture); - defaultMinOSVersion = (targetOS == "maccatalyst") ? "13.1" : "11.0"; + defaultMinOSVersion = (targetOS == "maccatalyst") ? "15.0" : "12.2"; targetAbi = DetermineAbi(targetArchitecture); AppleSdk sdk = new AppleSdk(targetOS, logger); diff --git a/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs b/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs index 3acdcf06ba8a..db9cf0cef04d 100644 --- a/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs +++ b/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs @@ -36,8 +36,6 @@ public class ManagedToNativeGenerator : Task [Output] public string[]? FileWrites { get; private set; } - private static readonly char[] s_charsToReplace = new[] { '.', '-', '+', '<', '>' }; - public override bool Execute() { if (Assemblies!.Length == 0) @@ -108,30 +106,7 @@ string FixupSymbolName(string name) if (_symbolNameFixups.TryGetValue(name, out string? fixedName)) return fixedName; - UTF8Encoding utf8 = new(); - byte[] bytes = utf8.GetBytes(name); - StringBuilder sb = new(); - - foreach (byte b in bytes) - { - if ((b >= (byte)'0' && b <= (byte)'9') || - (b >= (byte)'a' && b <= (byte)'z') || - (b >= (byte)'A' && b <= (byte)'Z') || - (b == (byte)'_')) - { - sb.Append((char)b); - } - else if (s_charsToReplace.Contains((char)b)) - { - sb.Append('_'); - } - else - { - sb.Append($"_{b:X}_"); - } - } - - fixedName = sb.ToString(); + fixedName = Utils.FixupSymbolName(name); _symbolNameFixups[name] = fixedName; return fixedName; } diff --git a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs index 4a29b47666e9..7808655b7f6b 100644 --- a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs @@ -304,7 +304,7 @@ private string DelegateKey(PInvokeCallback export) // it needs to match the key generated in get_native_to_interp var method = export.Method; string module_symbol = method.DeclaringType!.Module!.Assembly!.GetName()!.Name!; - return $"\"{module_symbol}_{method.DeclaringType.Name}_{method.Name}\"".Replace('.', '_'); + return $"\"{_fixupSymbolName($"{module_symbol}_{method.DeclaringType.Name}_{method.Name}")}\""; } #pragma warning disable SYSLIB1045 // framework doesn't support GeneratedRegexAttribute diff --git a/src/tasks/WasmAppBuilder/RunWithEmSdkEnv.cs b/src/tasks/WasmAppBuilder/RunWithEmSdkEnv.cs index b4c524bb2251..5e53d603c12c 100644 --- a/src/tasks/WasmAppBuilder/RunWithEmSdkEnv.cs +++ b/src/tasks/WasmAppBuilder/RunWithEmSdkEnv.cs @@ -25,7 +25,12 @@ public override bool Execute() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - string envScriptPath = Path.Combine(EmSdkPath, "emsdk_env.bat"); + // TODO-LLVM: The .cmd version does not exists in the version of Emscripten NAOT-LLVM uses, so check for both. + string envScriptPath = Path.Combine(EmSdkPath, "emsdk_env.cmd"); + if (!File.Exists(envScriptPath)) + { + envScriptPath = Path.Combine(EmSdkPath, "emsdk_env.bat"); + } if (!CheckEnvScript(envScriptPath)) return false; diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs index 7847039163b1..b16c21e117fd 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs @@ -31,6 +31,8 @@ public class WasmAppBuilder : WasmAppBuilderBaseTask public string? RuntimeAssetsLocation { get; set; } public bool CacheBootResources { get; set; } public int DebugLevel { get; set; } + public bool IsAot { get; set; } + public bool IsMultiThreaded { get; set; } private static readonly JsonSerializerOptions s_jsonOptions = new JsonSerializerOptions { @@ -95,7 +97,7 @@ private GlobalizationMode GetGlobalizationMode() protected override bool ExecuteInternal() { - var helper = new BootJsonBuilderHelper(Log); + var helper = new BootJsonBuilderHelper(Log, IsMultiThreaded); var logAdapter = new LogAdapter(Log); if (!ValidateArguments()) @@ -168,6 +170,9 @@ protected override bool ExecuteInternal() if (!IncludeThreadsWorker && name == "dotnet.native.worker.js") continue; + if (!HybridGlobalization && name == "dotnet.globalization.js") + continue; + if (name == "dotnet.runtime.js.map" || name == "dotnet.js.map") { Log.LogMessage(MessageImportance.Low, $"Skipping {item.ItemSpec} from boot config"); @@ -206,16 +211,30 @@ protected override bool ExecuteInternal() bytes = File.ReadAllBytes(assemblyPath); } - bootConfig.resources.assembly[Path.GetFileName(assemblyPath)] = Utils.ComputeIntegrity(bytes); + var assemblyName = Path.GetFileName(assemblyPath); + bool isCoreAssembly = IsAot || helper.IsCoreAssembly(assemblyName); + + var assemblyList = isCoreAssembly ? bootConfig.resources.coreAssembly : bootConfig.resources.assembly; + assemblyList[assemblyName] = Utils.ComputeIntegrity(bytes); + if (DebugLevel != 0) { var pdb = Path.ChangeExtension(assembly, ".pdb"); if (File.Exists(pdb)) { - if (bootConfig.resources.pdb == null) - bootConfig.resources.pdb = new(); - - bootConfig.resources.pdb[Path.GetFileName(pdb)] = Utils.ComputeIntegrity(pdb); + if (isCoreAssembly) + { + if (bootConfig.resources.corePdb == null) + bootConfig.resources.corePdb = new(); + } + else + { + if (bootConfig.resources.pdb == null) + bootConfig.resources.pdb = new(); + } + + var pdbList = isCoreAssembly ? bootConfig.resources.corePdb : bootConfig.resources.pdb; + pdbList[Path.GetFileName(pdb)] = Utils.ComputeIntegrity(pdb); } } } @@ -268,9 +287,11 @@ protected override bool ExecuteInternal() var i = 0; StringDictionary targetPathTable = new(); var vfs = new Dictionary>(); + var coreVfs = new Dictionary>(); foreach (var item in FilesToIncludeInFileSystem) { string? targetPath = item.GetMetadata("TargetPath"); + string? loadingStage = item.GetMetadata("LoadingStage"); if (string.IsNullOrEmpty(targetPath)) { targetPath = Path.GetFileName(item.ItemSpec); @@ -298,7 +319,14 @@ protected override bool ExecuteInternal() var vfsPath = Path.Combine(supportFilesDir, generatedFileName); FileCopyChecked(item.ItemSpec, vfsPath, "FilesToIncludeInFileSystem"); - vfs[targetPath] = new() + var vfsDict = loadingStage switch + { + null => vfs, + "" => vfs, + "Core" => coreVfs, + _ => throw new LogAsErrorException($"The WasmFilesToIncludeInFileSystem '{item.ItemSpec}' has LoadingStage set to unsupported '{loadingStage}' (empty or 'Core' is currently supported).") + }; + vfsDict[targetPath] = new() { [$"supportFiles/{generatedFileName}"] = Utils.ComputeIntegrity(vfsPath) }; @@ -306,6 +334,9 @@ protected override bool ExecuteInternal() if (vfs.Count > 0) bootConfig.resources.vfs = vfs; + + if (coreVfs.Count > 0) + bootConfig.resources.coreVfs = coreVfs; } if (!InvariantGlobalization) diff --git a/src/tests/Common/CLRTest.Jit.targets b/src/tests/Common/CLRTest.Jit.targets index 6fd00de8977f..5c2a0735a414 100644 --- a/src/tests/Common/CLRTest.Jit.targets +++ b/src/tests/Common/CLRTest.Jit.targets @@ -140,7 +140,7 @@ IF NOT DEFINED DoLink ( DependsOnTargets="GetDisasmCheckData"> false - true + true $(scriptPath)__jit_disasm.out $(scriptPath)__jit_disasm_list.out @@ -184,7 +184,7 @@ fi DependsOnTargets="GetDisasmCheckData"> false - true + true $(scriptPath)__jit_disasm.out $(scriptPath)__jit_disasm_list.out diff --git a/src/tests/Common/CoreCLRTestLibrary/OutOfProcessTest.cs b/src/tests/Common/CoreCLRTestLibrary/OutOfProcessTest.cs index 0337fa9e624f..66937878587d 100644 --- a/src/tests/Common/CoreCLRTestLibrary/OutOfProcessTest.cs +++ b/src/tests/Common/CoreCLRTestLibrary/OutOfProcessTest.cs @@ -49,7 +49,7 @@ static OutOfProcessTest() && !OperatingSystem.IsBrowser() && !OperatingSystem.IsOSPlatform("Wasi"); - public static void RunOutOfProcessTest(string assemblyPath) + public static void RunOutOfProcessTest(string assemblyPath, string testPathPrefix) { int ret = -100; string baseDir = AppContext.BaseDirectory; @@ -63,17 +63,23 @@ public static void RunOutOfProcessTest(string assemblyPath) { CoreclrTestWrapperLib wrapper = new CoreclrTestWrapperLib(); + string testScriptPath = assemblyPath; + if (testPathPrefix != null) + testScriptPath = Path.Combine(testPathPrefix, testScriptPath); + if (OperatingSystem.IsWindows()) { - testExecutable = Path.Combine(baseDir, Path.ChangeExtension(assemblyPath, ".cmd")); + testExecutable = Path.Combine(baseDir, Path.ChangeExtension(testScriptPath, ".cmd")); } else { - testExecutable = Path.Combine(baseDir, Path.ChangeExtension(assemblyPath.Replace("\\", "/"), ".sh")); + testExecutable = Path.Combine(baseDir, Path.ChangeExtension(testScriptPath.Replace("\\", "/"), ".sh")); } if (!File.Exists(testExecutable)) { + Console.WriteLine($"Test executable '{testExecutable}' not found, skipping."); + // Skip platform-specific test when running on the excluded platform return; } diff --git a/src/tests/Common/CoreCLRTestLibrary/PlatformDetection.cs b/src/tests/Common/CoreCLRTestLibrary/PlatformDetection.cs index d03327e5fdde..f0118d60db34 100644 --- a/src/tests/Common/CoreCLRTestLibrary/PlatformDetection.cs +++ b/src/tests/Common/CoreCLRTestLibrary/PlatformDetection.cs @@ -14,6 +14,7 @@ public static class PlatformDetection public static bool IsX86Process => RuntimeInformation.ProcessArchitecture == Architecture.X86; public static bool IsNotX86Process => !IsX86Process; + public static bool IsArm64Process => RuntimeInformation.ProcessArchitecture == Architecture.Arm64; public static bool IsWindows => OperatingSystem.IsWindows(); @@ -46,6 +47,10 @@ public static bool IsNonZeroLowerBoundArraySupported } } + public static bool IsNonZeroLowerBoundArrayNotSupported => !IsNonZeroLowerBoundArraySupported; + + public static bool IsMonoRuntime => Type.GetType("Mono.RuntimeStructs") != null; + static string _variant = Environment.GetEnvironmentVariable("DOTNET_RUNTIME_VARIANT"); public static bool IsMonoLLVMAOT => _variant == "llvmaot"; diff --git a/src/tests/Common/CoreCLRTestLibrary/Utilities.cs b/src/tests/Common/CoreCLRTestLibrary/Utilities.cs index d48a3e6bd6e7..a3d6df5a6234 100644 --- a/src/tests/Common/CoreCLRTestLibrary/Utilities.cs +++ b/src/tests/Common/CoreCLRTestLibrary/Utilities.cs @@ -101,7 +101,7 @@ public static bool IsWindowsIoTCore public static bool HasAssemblyFiles => !string.IsNullOrEmpty(typeof(Utilities).Assembly.Location); public static bool IsSingleFile => !HasAssemblyFiles; -#if NETCOREAPP +#if NET public static bool IsReflectionEmitSupported => RuntimeFeature.IsDynamicCodeSupported; public static bool IsNotReflectionEmitSupported => !IsReflectionEmitSupported; #else diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs index 5ee032e2842d..b37ec3a274b1 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs @@ -47,6 +47,36 @@ } }"; +const string SimpleTernVecOpTest_ValidationLogic = @"for (var i = 0; i < RetElementCount; i++) + { + if ({ValidateIterResult}) + { + succeeded = false; + break; + } + }"; + + +const string SimpleVecOpTest_ValidationLogicForCndSel = @"for (var i = 0; i < RetElementCount; i++) + { + {Op1BaseType} iterResult = (mask[i] != 0) ? {GetIterResult} : falseVal[i]; + if (iterResult != result[i]) + { + succeeded = false; + break; + } + }"; + +const string SimpleTernVecOpTest_ValidationLogicForCndSel = @"for (var i = 0; i < RetElementCount; i++) + { + {Op1BaseType} iterResult = (mask[i] != 0) ? {GetIterResult} : falseVal[i]; + if ({ConvertFunc}(iterResult) != {ConvertFunc}(result[i])) + { + succeeded = false; + break; + } + }"; + const string VecPairBinOpTest_ValidationLogic = @" int index = 0; int half = RetElementCount / 2; @@ -88,26 +118,36 @@ (string templateFileName, string outputTemplateName, Dictionary templateData)[] Templates = new[] { - ("_UnaryOpScalarTestTemplate.template", "DuplicateTest.template", new Dictionary { ["TemplateName"] = "Duplicate", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_ImmUnaryOpTestTemplate.template", "ImmUnOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_ImmUnaryOpTestTemplate.template", "VecImmUnOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), - ("_ImmTernaryOpTestTemplate.template", "ImmTernOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), - ("_ImmOpTestTemplate.template", "ImmOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_ImmBinaryOpTestTemplate.template", "ImmBinOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_ImmBinaryOpTestTemplate.template", "VecImmBinOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), - ("_BinaryOpTestTemplate.template", "SimpleBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_TernaryOpTestTemplate.template", "VecTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), - ("_ImmTernaryOpTestTemplate.template", "VecImmTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), - ("_ImmTernaryOpTestTemplate.template", "SimpleImmTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_UnaryOpTestTemplate.template", "SimpleUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_UnaryOpTestTemplate.template", "SimpleVecOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), - ("_BinaryOpTestTemplate.template", "VecPairBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecPairBinOpTest_ValidationLogic }), - ("_UnaryOpTestTemplate.template", "VecReduceUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecReduceOpTest_ValidationLogic }), - ("_BinaryOpTestTemplate.template", "VecBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), - ("_TernaryOpTestTemplate.template", "SimpleTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_UnaryOpTestTemplate.template", "SecureHashUnOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), - ("_BinaryOpTestTemplate.template", "SecureHashBinOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), - ("_TernaryOpTestTemplate.template", "SecureHashTernOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }) + ("_UnaryOpScalarTestTemplate.template", "DuplicateTest.template", new Dictionary { ["TemplateName"] = "Duplicate", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_ImmUnaryOpTestTemplate.template", "ImmUnOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_ImmUnaryOpTestTemplate.template", "VecImmUnOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_ImmTernaryOpTestTemplate.template", "ImmTernOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_ImmOpTestTemplate.template", "ImmOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_ImmBinaryOpTestTemplate.template", "ImmBinOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_ImmBinaryOpTestTemplate.template", "VecImmBinOpTest.template", new Dictionary { ["TemplateName"] = "Imm", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_BinaryOpTestTemplate.template", "SimpleBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_TernaryOpTestTemplate.template", "VecTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_ImmTernaryOpTestTemplate.template", "VecImmTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_ImmTernaryOpTestTemplate.template", "SimpleImmTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_UnaryOpTestTemplate.template", "SimpleUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_UnaryOpTestTemplate.template", "SimpleVecOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_BinaryOpTestTemplate.template", "VecPairBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecPairBinOpTest_ValidationLogic }), + ("_BinaryOp_SveTestTemplate.template", "SveVecPairBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecPairBinOpTest_ValidationLogic }), + ("_UnaryOpTestTemplate.template", "VecReduceUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecReduceOpTest_ValidationLogic }), + ("_BinaryOpTestTemplate.template", "VecBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic }), + ("_TernaryOpTestTemplate.template", "SimpleTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_UnaryOpTestTemplate.template", "SecureHashUnOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), + ("_BinaryOpTestTemplate.template", "SecureHashBinOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), + ("_TernaryOpTestTemplate.template", "SecureHashTernOpTest.template", new Dictionary { ["TemplateName"] = "SecureHash", ["TemplateValidationLogic"] = SecureHashOpTest_ValidationLogic }), + ("_SveUnaryOpTestTemplate.template", "SveSimpleVecOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic, ["TemplateValidationLogicForCndSel"] = SimpleVecOpTest_ValidationLogicForCndSel }), + ("_SveBinaryOpTestTemplate.template", "SveVecBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic, ["TemplateValidationLogicForCndSel"] = SimpleVecOpTest_ValidationLogicForCndSel }), + ("_SveBinaryOpTestTemplate.template", "SveVecBinOpConvertTest.template",new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic, ["TemplateValidationLogicForCndSel"] = SimpleTernVecOpTest_ValidationLogicForCndSel }), + ("_SveImmBinaryOpTestTemplate.template", "SveVecImmBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic, ["TemplateValidationLogicForCndSel"] = SimpleVecOpTest_ValidationLogicForCndSel }), + ("_SveTernOpTestTemplate.template", "SveVecTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic, ["TemplateValidationLogicForCndSel"] = SimpleTernVecOpTest_ValidationLogicForCndSel }), + ("_SveTernOpFirstArgTestTemplate.template", "SveVecTernOpFirstArgTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic, ["TemplateValidationLogicForCndSel"] = SimpleTernVecOpTest_ValidationLogicForCndSel }), + ("_SveImmTernOpTestTemplate.template", "SveVecImmTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic, ["TemplateValidationLogicForCndSel"] = SimpleTernVecOpTest_ValidationLogicForCndSel }), + ("_SveImmTernOpFirstArgTestTemplate.template", "SveVecImmTernOpFirstArgTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleVecOpTest_ValidationLogic, ["TemplateValidationLogicForCndSel"] = SimpleTernVecOpTest_ValidationLogicForCndSel }), + ("_SveMinimalUnaryOpTestTemplate.template", "SveVecReduceUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = VecReduceOpTest_ValidationLogic }), }; (string templateFileName, Dictionary templateData)[] AdvSimdInputs = new [] @@ -1636,15 +1676,9 @@ ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowing(firstOp[i], Imm) != result[i]"}), ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingLower_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowing(firstOp[i], Imm) != result[i]"}), ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), - ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), - ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), - ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), ("VecImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateLower_Vector64_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateLower", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[i], Imm) != result[i]"}), ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), - ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), - ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_Int32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), - ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_SByte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt16_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper_Vector128_UInt32_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturateUpper(firstOp, secondOp, Imm, i) != result[i]"}), ("VecImmBinOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingUpper_Vector128_Byte_1", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingUpper", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingUpper(firstOp, secondOp, Imm, i) != result[i]"}), @@ -2488,9 +2522,6 @@ ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt16_5", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "15", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalNarrowingSaturateScalar_Vector64_UInt32_7", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "31", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Byte_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "3", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int16_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["Imm"] = "5", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_Int32_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["Imm"] = "7", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), - ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_SByte_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "3", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt16_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["Imm"] = "5", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), ("ImmUnOpTest.template", new Dictionary { ["TestName"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar_Vector64_UInt32_1", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ShiftRightLogicalRoundedNarrowingSaturateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["Imm"] = "7", ["ValidateFirstResult"] = "Helpers.ShiftRightLogicalRoundedNarrowingSaturate(firstOp[0], Imm) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), ("SimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sqrt_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Sqrt", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Sqrt(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}), @@ -2887,16 +2918,451 @@ (string templateFileName, Dictionary templateData)[] SveInputs = new [] { - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_float", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_double", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_sbyte", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_short", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_int", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_long", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_byte", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_ushort", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_uint", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), - ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_ulong", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)-TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "(sbyte)Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)-TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "(short)Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Abs(firstOp[i]) != result[i]", ["GetIterResult"] = "(int)Helpers.Abs(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Abs_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Abs", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "(long)Helpers.Abs(firstOp[i]) != (long)result[i]", ["GetIterResult"] = "(long)Helpers.Abs(leftOp[i])"}), + + ("SveVecBinOpConvertTest.template", new Dictionary { ["TestName"] = "Sve_AbsoluteDifference_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.AbsoluteDifference(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])", ["GetIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i])", ["ConvertFunc"] = "BitConverter.SingleToInt32Bits"}), + ("SveVecBinOpConvertTest.template", new Dictionary { ["TestName"] = "Sve_AbsoluteDifference_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.AbsoluteDifference(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])", ["GetIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i])", ["ConvertFunc"] = "BitConverter.DoubleToInt64Bits"}), + ("SveVecBinOpConvertTest.template", new Dictionary { ["TestName"] = "Sve_AbsoluteDifference_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]", ["GetIterResult"] = "(sbyte)Helpers.AbsoluteDifference(left[i], right[i])", ["ConvertFunc"] = ""}), + ("SveVecBinOpConvertTest.template", new Dictionary { ["TestName"] = "Sve_AbsoluteDifference_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]", ["GetIterResult"] = "(short)Helpers.AbsoluteDifference(left[i], right[i])", ["ConvertFunc"] = ""}), + ("SveVecBinOpConvertTest.template", new Dictionary { ["TestName"] = "Sve_AbsoluteDifference_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]", ["GetIterResult"] = "(int)Helpers.AbsoluteDifference(left[i], right[i])", ["ConvertFunc"] = ""}), + ("SveVecBinOpConvertTest.template", new Dictionary { ["TestName"] = "Sve_AbsoluteDifference_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]", ["GetIterResult"] = "(long)Helpers.AbsoluteDifference(left[i], right[i])", ["ConvertFunc"] = ""}), + ("SveVecBinOpConvertTest.template", new Dictionary { ["TestName"] = "Sve_AbsoluteDifference_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]", ["GetIterResult"] = "(byte)Helpers.AbsoluteDifference(left[i], right[i])", ["ConvertFunc"] = ""}), + ("SveVecBinOpConvertTest.template", new Dictionary { ["TestName"] = "Sve_AbsoluteDifference_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]", ["GetIterResult"] = "(ushort)Helpers.AbsoluteDifference(left[i], right[i])", ["ConvertFunc"] = ""}), + ("SveVecBinOpConvertTest.template", new Dictionary { ["TestName"] = "Sve_AbsoluteDifference_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]", ["GetIterResult"] = "(uint)Helpers.AbsoluteDifference(left[i], right[i])", ["ConvertFunc"] = ""}), + ("SveVecBinOpConvertTest.template", new Dictionary { ["TestName"] = "Sve_AbsoluteDifference_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AbsoluteDifference", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.AbsoluteDifference(left[i], right[i]) != result[i]", ["GetIterResult"] = "(UInt64)Helpers.AbsoluteDifference(left[i], right[i])", ["ConvertFunc"] = ""}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Add_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Add", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Add(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Add(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossRecursivePairwise(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0.0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossRecursivePairwise(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0.0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_long_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossWideningLong(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_long_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossWideningLong(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_long_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossWidening(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_ulong_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossWideningULong(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_ulong_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossWideningULong(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_ulong_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.AddAcrossWidening(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AddAcross_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateReduceOpResult"] = "Helpers.AddAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_AddSaturate_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.AddSaturate(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_AddSaturate_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.AddSaturate(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_AddSaturate_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.AddSaturate(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_AddSaturate_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.AddSaturate(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_AddSaturate_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.AddSaturate(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_AddSaturate_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.AddSaturate(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_AddSaturate_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.AddSaturate(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_AddSaturate_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AddSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.AddSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.AddSaturate(left[i], right[i])"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_And_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "And", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.And(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_AndAcross_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "AndAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateReduceOpResult"] = "Helpers.AndAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_BitwiseClear_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.BitwiseClear(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_BitwiseClear_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.BitwiseClear(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_BitwiseClear_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.BitwiseClear(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_BitwiseClear_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.BitwiseClear(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_BitwiseClear_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.BitwiseClear(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_BitwiseClear_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.BitwiseClear(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_BitwiseClear_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.BitwiseClear(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_BitwiseClear_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.BitwiseClear(left[i], right[i])"}), + + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_BooleanNot_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BooleanNot", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BooleanNot(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.BooleanNot(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_BooleanNot_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BooleanNot", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.BooleanNot(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.BooleanNot(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_BooleanNot_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BooleanNot", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.BooleanNot(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.BooleanNot(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_BooleanNot_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BooleanNot", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.BooleanNot(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.BooleanNot(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_BooleanNot_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BooleanNot", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BooleanNot(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.BooleanNot(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_BooleanNot_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BooleanNot", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.BooleanNot(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.BooleanNot(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_BooleanNot_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BooleanNot", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.BooleanNot(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.BooleanNot(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_BooleanNot_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "BooleanNot", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.BooleanNot(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.BooleanNot(leftOp[i])"}), + + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + ("SveConditionalSelect.template", new Dictionary { ["TestName"] = "Sve_ConditionalSelect_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ConditionalSelect", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "(firstOp[i] != 0 ? (result[i] != secondOp[i]) : (result[i] != thirdOp[i]))",}), + + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count16BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count16BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Int16)));",}), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count32BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count32BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Int32)));",}), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count64BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count64BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Int64)));",}), + ("ScalarUnOpTest.template", new Dictionary { ["TestName"] = "Sve_Count8BitElements", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Count8BitElements", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "SveMaskPattern", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "SveMaskPattern.All", ["ValidateResult"] = "isUnexpectedResult = (result != (UInt64)(Unsafe.SizeOf>() / sizeof(Byte)));",}), + + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask16Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask32Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask32Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask32Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask32Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask64Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask64Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask64Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask64Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask8Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask8Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask8Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanMask8Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask16Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask16Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask16Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask16Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask16Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask32Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask32Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask32Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask32Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask32Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask64Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask64Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask64Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask64Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask64Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask8Bit_Int32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int32)i, right) != (Int32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask8Bit_Int64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (Int64)i, right) != (Int64)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask8Bit_UInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt32)i, right) != (UInt32)result[i]",}), + ("ScalarBinOpRetVecTest.template",new Dictionary {["TestName"] = "Sve_CreateWhileLessThanOrEqualMask8Bit_UInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateWhileLessThanOrEqualMask8Bit", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.WhileLessThanOrEqualMask(left + (UInt64)i, right) != (UInt64)result[i]",}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Divide_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Divide", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Divide(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Divide(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Divide_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Divide", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Divide(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Divide(left[i], right[i])"}), + + ("SveVecTernOpFirstArgTest.template", new Dictionary { ["TestName"] = "Sve_DotProduct_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "DotProduct", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * i) != result[i]", ["GetIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * i)", ["ConvertFunc"] = ""}), + ("SveVecTernOpFirstArgTest.template", new Dictionary { ["TestName"] = "Sve_DotProduct_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "DotProduct", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * i) != result[i]", ["GetIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * i)", ["ConvertFunc"] = ""}), + ("SveVecTernOpFirstArgTest.template", new Dictionary { ["TestName"] = "Sve_DotProduct_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "DotProduct", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * i) != result[i]", ["GetIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * i)", ["ConvertFunc"] = ""}), + ("SveVecTernOpFirstArgTest.template", new Dictionary { ["TestName"] = "Sve_DotProduct_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "DotProduct", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * i) != result[i]", ["GetIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * i)", ["ConvertFunc"] = ""}), + + ("SveVecImmTernOpFirstArgTest.template", new Dictionary { ["TestName"] = "Sve_DotProductBySelectedScalar_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "DotProductBySelectedScalar", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["Imm"] = "2", ["ValidateIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * Imm) != result[i]", ["GetIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * Imm)", ["ConvertFunc"] = ""}), + ("SveVecImmTernOpFirstArgTest.template", new Dictionary { ["TestName"] = "Sve_DotProductBySelectedScalar_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "DotProductBySelectedScalar", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * Imm) != result[i]", ["GetIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * Imm)", ["ConvertFunc"] = ""}), + ("SveVecImmTernOpFirstArgTest.template", new Dictionary { ["TestName"] = "Sve_DotProductBySelectedScalar_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "DotProductBySelectedScalar", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * Imm) != result[i]", ["GetIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * Imm)", ["ConvertFunc"] = ""}), + ("SveVecImmTernOpFirstArgTest.template", new Dictionary { ["TestName"] = "Sve_DotProductBySelectedScalar_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "DotProductBySelectedScalar", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["Imm"] = "1", ["ValidateIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * Imm) != result[i]", ["GetIterResult"] = "Helpers.DotProduct(first[i], second, 4 * i, third, 4 * Imm)", ["ConvertFunc"] = ""}), + + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_FusedMultiplyAdd_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "FusedMultiplyAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2BaseType"] = "Single", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])", ["GetIterResult"] = "Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = "BitConverter.SingleToInt32Bits"}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_FusedMultiplyAdd_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "FusedMultiplyAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2BaseType"] = "Double", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.DoubleToInt64Bits(result[i])", ["GetIterResult"] = "Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = "BitConverter.DoubleToInt64Bits"}), + + ("SveVecImmTernOpTest.template", new Dictionary {["TestName"] = "Sve_FusedMultiplyAddBySelectedScalar_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "FusedMultiplyAddBySelectedScalar", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["Imm"] = "1", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[Imm])) != BitConverter.SingleToInt32Bits(result[i])", ["GetIterResult"] = "Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[Imm])", ["ConvertFunc"] = "BitConverter.SingleToInt32Bits"}), + ("SveVecImmTernOpTest.template", new Dictionary {["TestName"] = "Sve_FusedMultiplyAddBySelectedScalar_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "FusedMultiplyAddBySelectedScalar", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["Imm"] = "0", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[Imm])) != BitConverter.DoubleToInt64Bits(result[i])", ["GetIterResult"] = "Helpers.FusedMultiplyAdd(firstOp[i], secondOp[i], thirdOp[Imm])", ["ConvertFunc"] = "BitConverter.DoubleToInt64Bits"}), + + ("SveVecTernOpTest.template", new Dictionary {["TestName"] = "Sve_FusedMultiplyAddNegated_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "FusedMultiplyAddNegated", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2BaseType"] = "Single", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplyAddNegated(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])", ["GetIterResult"] = "Helpers.FusedMultiplyAddNegated(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = "BitConverter.SingleToInt32Bits"}), + ("SveVecTernOpTest.template", new Dictionary {["TestName"] = "Sve_FusedMultiplyAddNegated_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "FusedMultiplyAddNegated", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2BaseType"] = "Double", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplyAddNegated(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.DoubleToInt64Bits(result[i])", ["GetIterResult"] = "Helpers.FusedMultiplyAddNegated(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = "BitConverter.DoubleToInt64Bits"}), + + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_FusedMultiplySubtract_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "FusedMultiplySubtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2BaseType"] = "Single", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])", ["GetIterResult"] = "Helpers.FusedMultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = "BitConverter.SingleToInt32Bits"}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_FusedMultiplySubtract_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "FusedMultiplySubtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2BaseType"] = "Double", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.DoubleToInt64Bits(result[i])", ["GetIterResult"] = "Helpers.FusedMultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = "BitConverter.DoubleToInt64Bits"}), + + ("SveVecImmTernOpTest.template", new Dictionary {["TestName"] = "Sve_FusedMultiplySubtractBySelectedScalar_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "FusedMultiplySubtractBySelectedScalar", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["Imm"] = "1", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplySubtract(firstOp[i], secondOp[i], thirdOp[Imm])) != BitConverter.SingleToInt32Bits(result[i])", ["GetIterResult"] = "Helpers.FusedMultiplySubtract(firstOp[i], secondOp[i], thirdOp[Imm])", ["ConvertFunc"] = "BitConverter.SingleToInt32Bits"}), + ("SveVecImmTernOpTest.template", new Dictionary {["TestName"] = "Sve_FusedMultiplySubtractBySelectedScalar_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "FusedMultiplySubtractBySelectedScalar", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["Imm"] = "0", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplySubtract(firstOp[i], secondOp[i], thirdOp[Imm])) != BitConverter.DoubleToInt64Bits(result[i])", ["GetIterResult"] = "Helpers.FusedMultiplySubtract(firstOp[i], secondOp[i], thirdOp[Imm])", ["ConvertFunc"] = "BitConverter.DoubleToInt64Bits"}), + + ("SveVecTernOpTest.template", new Dictionary {["TestName"] = "Sve_FusedMultiplySubtractNegated_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "FusedMultiplySubtractNegated", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2BaseType"] = "Single", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.FusedMultiplySubtractNegated(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.SingleToInt32Bits(result[i])", ["GetIterResult"] = "Helpers.FusedMultiplySubtractNegated(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = "BitConverter.SingleToInt32Bits"}), + ("SveVecTernOpTest.template", new Dictionary {["TestName"] = "Sve_FusedMultiplySubtractNegated_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "FusedMultiplySubtractNegated", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2BaseType"] = "Double", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.FusedMultiplySubtractNegated(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.DoubleToInt64Bits(result[i])", ["GetIterResult"] = "Helpers.FusedMultiplySubtractNegated(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = "BitConverter.DoubleToInt64Bits"}), + + ("SveSimpleNoOpTest.template", new Dictionary { ["TestName"] = "Sve_CreateFalseMaskByte_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateFalseMaskByte", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["ValidateIterResult"] = "result[i] != 0",}), + ("SveSimpleNoOpTest.template", new Dictionary { ["TestName"] = "Sve_CreateFalseMaskDouble_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateFalseMaskDouble", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["ValidateIterResult"] = "result[i] != 0",}), + ("SveSimpleNoOpTest.template", new Dictionary { ["TestName"] = "Sve_CreateFalseMaskInt16_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateFalseMaskInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["ValidateIterResult"] = "result[i] != 0",}), + ("SveSimpleNoOpTest.template", new Dictionary { ["TestName"] = "Sve_CreateFalseMaskInt32_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateFalseMaskInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["ValidateIterResult"] = "result[i] != 0",}), + ("SveSimpleNoOpTest.template", new Dictionary { ["TestName"] = "Sve_CreateFalseMaskInt64_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateFalseMaskInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["ValidateIterResult"] = "result[i] != 0",}), + ("SveSimpleNoOpTest.template", new Dictionary { ["TestName"] = "Sve_CreateFalseMaskSByte_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateFalseMaskSByte", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["ValidateIterResult"] = "result[i] != 0",}), + ("SveSimpleNoOpTest.template", new Dictionary { ["TestName"] = "Sve_CreateFalseMaskSingle_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateFalseMaskSingle", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["ValidateIterResult"] = "result[i] != 0",}), + ("SveSimpleNoOpTest.template", new Dictionary { ["TestName"] = "Sve_CreateFalseMaskUInt16_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateFalseMaskUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["ValidateIterResult"] = "result[i] != 0",}), + ("SveSimpleNoOpTest.template", new Dictionary { ["TestName"] = "Sve_CreateFalseMaskUInt32_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateFalseMaskUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["ValidateIterResult"] = "result[i] != 0",}), + ("SveSimpleNoOpTest.template", new Dictionary { ["TestName"] = "Sve_CreateFalseMaskUInt64_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateFalseMaskUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["ValidateIterResult"] = "result[i] != 0",}), + ("SveCreateTrueMaskTest.template", new Dictionary { ["TestName"] = "Sve_CreateTrueMaskByte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateTrueMaskByte", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1Type"] = "SveMaskPattern"}), + ("SveCreateTrueMaskTest.template", new Dictionary { ["TestName"] = "Sve_CreateTrueMaskDouble", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateTrueMaskDouble", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1Type"] = "SveMaskPattern"}), + ("SveCreateTrueMaskTest.template", new Dictionary { ["TestName"] = "Sve_CreateTrueMaskInt16", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateTrueMaskInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1Type"] = "SveMaskPattern"}), + ("SveCreateTrueMaskTest.template", new Dictionary { ["TestName"] = "Sve_CreateTrueMaskInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateTrueMaskInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1Type"] = "SveMaskPattern"}), + ("SveCreateTrueMaskTest.template", new Dictionary { ["TestName"] = "Sve_CreateTrueMaskInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateTrueMaskInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1Type"] = "SveMaskPattern"}), + ("SveCreateTrueMaskTest.template", new Dictionary { ["TestName"] = "Sve_CreateTrueMaskSByte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateTrueMaskSByte", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1Type"] = "SveMaskPattern"}), + ("SveCreateTrueMaskTest.template", new Dictionary { ["TestName"] = "Sve_CreateTrueMaskSingle", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateTrueMaskSingle", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1Type"] = "SveMaskPattern"}), + ("SveCreateTrueMaskTest.template", new Dictionary { ["TestName"] = "Sve_CreateTrueMaskUInt16", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateTrueMaskUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1Type"] = "SveMaskPattern"}), + ("SveCreateTrueMaskTest.template", new Dictionary { ["TestName"] = "Sve_CreateTrueMaskUInt32", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateTrueMaskUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1Type"] = "SveMaskPattern"}), + ("SveCreateTrueMaskTest.template", new Dictionary { ["TestName"] = "Sve_CreateTrueMaskUInt64", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "CreateTrueMaskUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1Type"] = "SveMaskPattern"}), + + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_float", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_double", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_sbyte", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_short", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_int", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_long", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_byte", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_ushort", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_uint", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVector_ulong", ["Isa"] = "Sve", ["Method"] = "LoadVector", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt16SignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt16SignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt32SignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt32SignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorInt32SignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorInt32SignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorSByteSignExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorSByteSignExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "(ulong)firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt16", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorByteZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorByteZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToUInt32", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToUInt32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt16ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt16ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt32ZeroExtendToInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + ("SveLoadMaskedUnOpTest.template", new Dictionary { ["TestName"] = "SveLoadVectorUInt32ZeroExtendToUInt64", ["Isa"] = "Sve", ["Method"] = "LoadVectorUInt32ZeroExtendToUInt64", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Max_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Max", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxAcross_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxNumber_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxNumber", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxNumber_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxNumber", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Max(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxNumberAcross_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxNumberAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MaxNumberAcross_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MaxNumberAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateReduceOpResult"] = "Helpers.MaxAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Min_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Min", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinAcross_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_MinNumber_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinNumber", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_MinNumber_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinNumber", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Min(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinNumberAcross_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinNumberAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_MinNumberAcross_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MinNumberAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateReduceOpResult"] = "Helpers.MinAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Multiply_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Multiply", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Multiply(left[i], right[i])"}), + + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplyAdd_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplyAdd_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplyAdd_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplyAdd_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplyAdd_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplyAdd_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplyAdd_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplyAdd_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplyAdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplyAdd(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + + ("SveVecImmBinOpTest.template", new Dictionary {["TestName"] = "Sve_MultiplyBySelectedScalar_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplyBySelectedScalar", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "TestLibrary.Generator.GetSingle()", ["Imm"] = "1", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Multiply(firstOp[i], secondOp[Imm])) != BitConverter.SingleToInt32Bits(result[i])",["GetIterResult"] = "Helpers.Multiply(firstOp[i], secondOp[Imm])", ["ConvertFunc"] = "BitConverter.SingleToInt32Bits"}), + ("SveVecImmBinOpTest.template", new Dictionary {["TestName"] = "Sve_MultiplyBySelectedScalar_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplyBySelectedScalar", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "TestLibrary.Generator.GetDouble()", ["Imm"] = "0", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Multiply(firstOp[i], secondOp[Imm])) != BitConverter.DoubleToInt64Bits(result[i])",["GetIterResult"] = "Helpers.Multiply(firstOp[i], secondOp[Imm])", ["ConvertFunc"] = "BitConverter.DoubleToInt64Bits"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplyExtended_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplyExtended", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.MultiplyExtended(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplyExtended(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplyExtended_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplyExtended", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.MultiplyExtended(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplyExtended(left[i], right[i])"}), + + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplySubtract_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplySubtract_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplySubtract_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplySubtract_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplySubtract_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplySubtract_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplySubtract_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + ("SveVecTernOpTest.template", new Dictionary { ["TestName"] = "Sve_MultiplySubtract_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "MultiplySubtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i]) != result[i]", ["GetIterResult"] = "Helpers.MultiplySubtract(firstOp[i], secondOp[i], thirdOp[i])", ["ConvertFunc"] = ""}), + + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Negate_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Negate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.Negate(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Negate_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Negate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]", ["GetIterResult"] = "Helpers.Negate(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Negate_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Negate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)-TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]", ["GetIterResult"] = "(sbyte)Helpers.Negate(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Negate_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Negate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)-TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]", ["GetIterResult"] = "(short)Helpers.Negate(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Negate_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Negate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]", ["GetIterResult"] = "(int)Helpers.Negate(leftOp[i])"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_Negate_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Negate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "-TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "(long)Helpers.Negate(firstOp[i]) != (long)result[i]", ["GetIterResult"] = "(long)Helpers.Negate(leftOp[i])"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Or_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Or", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Or(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_OrAcross_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "OrAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateReduceOpResult"] = "Helpers.OrAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend16_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend16_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend32_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 32, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 32, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend8_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend8_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, false)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_SignExtend8_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, false)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, false)"}), + + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_SignExtendWideningLower_short_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtendWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.SignExtendWidening(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "Helpers.SignExtendWidening(firstOp[i]) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_SignExtendWideningLower_int_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtendWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.SignExtendWidening(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "Helpers.SignExtendWidening(firstOp[i]) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_SignExtendWideningLower_long_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtendWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.SignExtendWidening(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "Helpers.SignExtendWidening(firstOp[i]) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_SignExtendWideningUpper_short_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtendWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.SignExtendWideningUpper(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "Helpers.SignExtendWideningUpper(firstOp, i) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_SignExtendWideningUpper_int_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtendWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.SignExtendWideningUpper(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "Helpers.SignExtendWideningUpper(firstOp, i) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_SignExtendWideningUpper_long_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SignExtendWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.SignExtendWideningUpper(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "Helpers.SignExtendWideningUpper(firstOp, i) != result[i]"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Subtract_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Subtract", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Subtract(left[i], right[i])"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_SubtractSaturate_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.SubtractSaturate(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_SubtractSaturate_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.SubtractSaturate(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_SubtractSaturate_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.SubtractSaturate(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_SubtractSaturate_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.SubtractSaturate(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_SubtractSaturate_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.SubtractSaturate(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_SubtractSaturate_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.SubtractSaturate(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_SubtractSaturate_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.SubtractSaturate(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_SubtractSaturate_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.SubtractSaturate(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.SubtractSaturate(left[i], right[i])"}), + + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(sbyte)TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(short)TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(byte)TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + ("SveVecBinOpTest.template", new Dictionary { ["TestName"] = "Sve_Xor_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "Xor", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]", ["GetIterResult"] = "Helpers.Xor(left[i], right[i])"}), + + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + ("SveVecReduceUnOpTest.template", new Dictionary { ["TestName"] = "Sve_XorAcross_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "XorAcross", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateReduceOpResult"] = "Helpers.XorAcross(firstOp) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}), + + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipEven_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipEven", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i] || result[index + half] != right[i]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveUnzipOdd_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "UnzipOdd", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[index] != left[i + 1] || result[index + half] != right[i + 1]"}), + + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend16_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend16_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend16", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 16, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 16, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend32_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend32", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 32, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 32, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), + ("SveSimpleVecOpTest.template", new Dictionary { ["TestName"] = "Sve_ZeroExtend8_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtend8", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x3FFFFFFFFFFFFFFF)", ["ValidateIterResult"] = "result[i] != Helpers.SignExtend(firstOp[i], 8, true)", ["GetIterResult"] = "Helpers.SignExtend(leftOp[i], 8, true)"}), + + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_ZeroExtendWideningLower_ushort_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtendWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.ZeroExtendWidening(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "Helpers.ZeroExtendWidening(firstOp[i]) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_ZeroExtendWideningLower_uint_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtendWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.ZeroExtendWidening(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "Helpers.ZeroExtendWidening(firstOp[i]) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_ZeroExtendWideningLower_ulong_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtendWideningLower", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.ZeroExtendWidening(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "Helpers.ZeroExtendWidening(firstOp[i]) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_ZeroExtendWideningUpper_ushort_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtendWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateReduceOpResult"] = "Helpers.ZeroExtendWideningUpper(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_ZeroExtendWideningUpper_uint_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtendWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateReduceOpResult"] = "Helpers.ZeroExtendWideningUpper(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]"}), + ("SveVecReduceUnOpTest.template",new Dictionary {["TestName"] = "Sve_ZeroExtendWideningUpper_ulong_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZeroExtendWideningUpper", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateReduceOpResult"] = "Helpers.ZeroExtendWideningUpper(firstOp, 0) != result[0]", ["ValidateRemainingResults"] = "Helpers.ZeroExtendWideningUpper(firstOp, i) != result[i]"}), + + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipHigh_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipHigh", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[i] != left[index + half] || result[i + 1] != right[index + half]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_float", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_double", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_sbyte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_short", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_int", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_long", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_byte", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_ushort", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_uint", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), + ("SveVecPairBinOpTest.template", new Dictionary { ["TestName"] = "SveZipLow_ulong", ["Isa"] = "Sve", ["LoadIsa"] = "Sve", ["Method"] = "ZipLow", ["RetVectorType"] = "Vector", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateEntry"] = "result[i] != left[index] || result[i + 1] != right[index]"}), }; diff --git a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_X86.cs b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_X86.cs index 20b8942132da..ed85a8453a61 100644 --- a/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_X86.cs +++ b/src/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_X86.cs @@ -22,21 +22,37 @@ // * outputDirectory - This should be somewhere under the obj folder for the project and is where generated tests are written // * testListFileName - This should likewise be somewhere under the obj folder and is where the list of generated tests is written -const string AlternatingOpTest_ValidationLogic = @"for (var i = 0; i < RetElementCount; i += 2) +const string AlternatingBinOpTest_ValidationLogic = @"for (var i = 0; i < RetElementCount; i += 2) { - if ({ValidateFirstResult}) + if ({ValidateFirstResult} && (!mask.HasValue || ((left[i] != default) && result[i] != mask.Value))) { succeeded = false; break; } - if ({ValidateRemainingResults}) + if ({ValidateRemainingResults} && (!mask.HasValue || ((left[i + 1] != default) && result[i + 1] != mask.Value))) { succeeded = false; break; } }"; +const string AlternatingTernOpTest_ValidationLogic = @"for (var i = 0; i < RetElementCount; i += 2) + { + if ({ValidateFirstResult} && (!mask.HasValue || ((firstOp[0] != default) && result[0] != mask.Value))) + { + succeeded = false; + break; + } + + if ({ValidateRemainingResults} && (!mask.HasValue || ((firstOp[i] != default) && result[i] != mask.Value))) + { + succeeded = false; + break; + } + }"; + + const string BooleanCmpTest_ValidationLogic = @"if ({ValidateFirstResult}) { succeeded = false; @@ -75,13 +91,13 @@ var i2 = i1 + (8 / sizeof({RetBaseType})); var i3 = (outer * (16 / sizeof({RetBaseType}))) + (inner * 2); - if ({ValidateFirstResult}) + if ({ValidateFirstResult} && (!mask.HasValue || ((left[i1] != default) && result[i1] != mask.Value))) { succeeded = false; break; } - if ({ValidateRemainingResults}) + if ({ValidateRemainingResults} && (!mask.HasValue || ((left[i2] != default) && result[i2] != mask.Value))) { succeeded = false; break; @@ -89,7 +105,7 @@ } }"; -const string SimpleOpTest_ValidationLogic = @"if ({ValidateFirstResult}) +const string SimpleUnOpTest_ValidationLogic = @"if ({ValidateFirstResult} && (!mask.HasValue || ((firstOp[0] != default) && result[0] != mask.Value))) { succeeded = false; } @@ -97,7 +113,39 @@ { for (var i = 1; i < RetElementCount; i++) { - if ({ValidateRemainingResults}) + if ({ValidateRemainingResults} && (!mask.HasValue || ((firstOp[i] != default) && result[i] != mask.Value))) + { + succeeded = false; + break; + } + } + }"; + +const string SimpleBinOpTest_ValidationLogic = @"if ({ValidateFirstResult} && (!mask.HasValue || ((left[0] != default) && result[0] != mask.Value))) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ({ValidateRemainingResults} && (!mask.HasValue || ((left[i] != default) && result[i] != mask.Value))) + { + succeeded = false; + break; + } + } + }"; + +const string SimpleTernOpTest_ValidationLogic = @"if ({ValidateFirstResult} && (!mask.HasValue || ((firstOp[0] != default) && result[0] != mask.Value))) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ({ValidateRemainingResults} && (!mask.HasValue || ((firstOp[i] != default) && result[i] != mask.Value))) { succeeded = false; break; @@ -107,16 +155,16 @@ (string templateFileName, string outputTemplateName, Dictionary templateData)[] Templates = new[] { - ("_BinaryOpTestTemplate.template", "AlternatingBinOpTest.template", new Dictionary { ["TemplateName"] = "Alternating", ["TemplateValidationLogic"] = AlternatingOpTest_ValidationLogic }), + ("_BinaryOpTestTemplate.template", "AlternatingBinOpTest.template", new Dictionary { ["TemplateName"] = "Alternating", ["TemplateValidationLogic"] = AlternatingBinOpTest_ValidationLogic }), ("_BinaryOpTestTemplate.template", "HorizontalBinOpTest.template", new Dictionary { ["TemplateName"] = "Horizontal", ["TemplateValidationLogic"] = HorizontalOpTest_ValidationLogic }), - ("_BinaryOpTestTemplate.template", "SimpleBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_BinaryOpTestTemplate.template", "SimpleBinOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleBinOpTest_ValidationLogic }), ("_BooleanBinaryOpTestTemplate.template", "BooleanBinOpTest.template", new Dictionary { ["TemplateName"] = "Boolean", ["TemplateValidationLogic"] = BooleanOpTest_ValidationLogic }), ("_BooleanBinaryOpTestTemplate.template", "BooleanCmpOpTest.template", new Dictionary { ["TemplateName"] = "Boolean", ["TemplateValidationLogic"] = BooleanCmpTest_ValidationLogic }), ("_BooleanBinaryOpTestTemplate.template", "BooleanTwoCmpOpTest.template", new Dictionary { ["TemplateName"] = "Boolean", ["TemplateValidationLogic"] = BooleanTwoCmpTest_ValidationLogic }), ("_BooleanUnaryOpTestTemplate.template", "BooleanUnOpTest.template", new Dictionary { ["TemplateName"] = "Boolean", ["TemplateValidationLogic"] = BooleanOpTest_ValidationLogic }), - ("_TernaryOpTestTemplate.template", "AlternatingTernOpTest.template", new Dictionary { ["TemplateName"] = "Alternating", ["TemplateValidationLogic"] = AlternatingOpTest_ValidationLogic }), - ("_TernaryOpTestTemplate.template", "SimpleTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), - ("_UnaryOpTestTemplate.template", "SimpleUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleOpTest_ValidationLogic }), + ("_TernaryOpTestTemplate.template", "AlternatingTernOpTest.template", new Dictionary { ["TemplateName"] = "Alternating", ["TemplateValidationLogic"] = AlternatingTernOpTest_ValidationLogic }), + ("_TernaryOpTestTemplate.template", "SimpleTernOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleTernOpTest_ValidationLogic }), + ("_UnaryOpTestTemplate.template", "SimpleUnOpTest.template", new Dictionary { ["TemplateName"] = "Simple", ["TemplateValidationLogic"] = SimpleUnOpTest_ValidationLogic }), }; (string templateFileName, Dictionary templateData)[] Sse1Inputs = new [] @@ -331,9 +379,9 @@ ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "(ushort)(left[0] | right[0]) != result[0]", ["ValidateRemainingResults"] = "(ushort)(left[i] | right[i]) != result[i]"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "(uint)(left[0] | right[0]) != result[0]", ["ValidateRemainingResults"] = "(uint)(left[i] | right[i]) != result[i]"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "(ulong)(left[0] | right[0]) != result[0]", ["ValidateRemainingResults"] = "(ulong)(left[i] | right[i]) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "PackSignedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (short)Math.Min(Math.Max(left[0], short.MinValue), short.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i < 4) ? (short)Math.Min(Math.Max(left[i], short.MinValue), short.MaxValue) : (short)Math.Min(Math.Max(right[i&3], short.MinValue), short.MaxValue))"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "PackSignedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (sbyte)Math.Min(Math.Max(left[0], sbyte.MinValue), sbyte.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i < 8) ? (sbyte)Math.Min(Math.Max(left[i], sbyte.MinValue), sbyte.MaxValue) : (sbyte)Math.Min(Math.Max(right[i&7], sbyte.MinValue), sbyte.MaxValue))"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "PackUnsignedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (byte)Math.Min(Math.Max(left[0], byte.MinValue), byte.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i < 8) ? (byte)Math.Min(Math.Max(left[i], byte.MinValue), byte.MaxValue) : (byte)Math.Min(Math.Max(right[i&7], byte.MinValue), byte.MaxValue))"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "PackSignedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (short)Math.Min(Math.Max(left[0], short.MinValue), short.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i < 4) ? (short)Math.Min(Math.Max(left[i], short.MinValue), short.MaxValue) : (short)Math.Min(Math.Max(right[i&3], short.MinValue), short.MaxValue))"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "PackSignedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (sbyte)Math.Min(Math.Max(left[0], sbyte.MinValue), sbyte.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i < 8) ? (sbyte)Math.Min(Math.Max(left[i], sbyte.MinValue), sbyte.MaxValue) : (sbyte)Math.Min(Math.Max(right[i&7], sbyte.MinValue), sbyte.MaxValue))"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "PackUnsignedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (byte)Math.Min(Math.Max(left[0], byte.MinValue), byte.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i < 8) ? (byte)Math.Min(Math.Max(left[i], byte.MinValue), byte.MaxValue) : (byte)Math.Min(Math.Max(right[i&7], byte.MinValue), byte.MaxValue))"}), ("ImmUnOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Imm"] = "1", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "(short)(firstOp[0] << 1) != result[0]", ["ValidateRemainingResults"] = "(short)(firstOp[i] << 1) != result[i]"}), ("ImmUnOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Imm"] = "1", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "(ushort)(firstOp[0] << 1) != result[0]", ["ValidateRemainingResults"] = "(ushort)(firstOp[i] << 1) != result[i]"}), ("ImmUnOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "ShiftLeftLogical", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Imm"] = "1", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "(int)(firstOp[0] << 1) != result[0]", ["ValidateRemainingResults"] = "(int)(firstOp[i] << 1) != result[i]"}), @@ -409,24 +457,24 @@ ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "SubtractSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "SseVerify.SubtractSaturate(left[0], right[0], result[0])", ["ValidateRemainingResults"] = "SseVerify.SubtractSaturate(left[i], right[i], result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(left[0] - right[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "SumAbsoluteDifferences", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != SseVerify.SumAbsoluteDifferences(left, right, 0)", ["ValidateRemainingResults"] = "result[i] != SseVerify.SumAbsoluteDifferences(left, right, i)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(left[1])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(left[i/2+1]) : BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(right[(i - 1)/2 + 1])"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != left[1] || result[1] != right[1]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 1] : result[i] != right[(i - 1)/2 + 1]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "result[0] != left[1] || result[1] != right[1]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 1] : result[i] != right[(i - 1)/2 + 1]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != left[2]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 2] : result[i] != right[(i - 1)/2 + 2]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != left[2]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 2] : result[i] != right[(i - 1)/2 + 2]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != left[4]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 4] : result[i] != right[(i - 1)/2 + 4]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "result[0] != left[4]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 4] : result[i] != right[(i - 1)/2 + 4]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "result[0] != left[8]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 8] : result[i] != right[(i - 1)/2 + 8]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != left[8]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 8] : result[i] != right[(i - 1)/2 + 8]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(left[0])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(left[i/2]) : BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(right[(i - 1)/2])"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != left[0] || result[1] != right[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "result[0] != left[0] || result[1] != right[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(left[1])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(left[i/2+1]) : BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(right[(i - 1)/2 + 1])"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != left[1] || result[1] != right[1]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 1] : result[i] != right[(i - 1)/2 + 1]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "result[0] != left[1] || result[1] != right[1]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 1] : result[i] != right[(i - 1)/2 + 1]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != left[2]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 2] : result[i] != right[(i - 1)/2 + 2]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != left[2]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 2] : result[i] != right[(i - 1)/2 + 2]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != left[4]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 4] : result[i] != right[(i - 1)/2 + 4]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "result[0] != left[4]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 4] : result[i] != right[(i - 1)/2 + 4]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "result[0] != left[8]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 8] : result[i] != right[(i - 1)/2 + 8]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackHigh", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != left[8]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2 + 8] : result[i] != right[(i - 1)/2 + 8]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(left[0])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(left[i/2]) : BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(right[(i - 1)/2])"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != left[0] || result[1] != right[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "result[0] != left[0] || result[1] != right[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "UnpackLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != left[0]", ["ValidateRemainingResults"] = "((i & 1) == 0) ? result[i] != left[i/2] : result[i] != right[(i - 1)/2]"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(BitConverter.DoubleToInt64Bits(left[0]) ^ BitConverter.DoubleToInt64Bits(right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.DoubleToInt64Bits(left[i]) ^ BitConverter.DoubleToInt64Bits(right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "(byte)(left[0] ^ right[0]) != result[0]", ["ValidateRemainingResults"] = "(byte)(left[i] ^ right[i]) != result[i]"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "(short)(left[0] ^ right[0]) != result[0]", ["ValidateRemainingResults"] = "(short)(left[i] ^ right[i]) != result[i]"}), @@ -497,16 +545,16 @@ (string templateFileName, Dictionary templateData)[] Sse41Inputs = new [] { - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "(byte)(((i & 1) == 0) ? 128 : 1)", ["ValidateFirstResult"] = "((thirdOp[0] >> 7) & 1) == 1 ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "((thirdOp[i] >> 7) & 1) == 1 ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "(double)(((i & 1) == 0) ? -0.0 : 1.0)", ["ValidateFirstResult"] = "((BitConverter.DoubleToInt64Bits(thirdOp[0]) >> 63) & 1) == 1 ? BitConverter.DoubleToInt64Bits(secondOp[0]) != BitConverter.DoubleToInt64Bits(result[0]) : BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "((BitConverter.DoubleToInt64Bits(thirdOp[i]) >> 63) & 1) == 1 ? BitConverter.DoubleToInt64Bits(secondOp[i]) != BitConverter.DoubleToInt64Bits(result[i]) : BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "(sbyte)(((i & 1) == 0) ? -128 : 1)", ["ValidateFirstResult"] = "((thirdOp[0] >> 7) & 1) == 1 ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "((thirdOp[i] >> 7) & 1) == 1 ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "(float)(((i & 1) == 0) ? -0.0 : 1.0)", ["ValidateFirstResult"] = "((BitConverter.SingleToInt32Bits(thirdOp[0]) >> 31) & 1) == 1 ? BitConverter.SingleToInt32Bits(secondOp[0]) != BitConverter.SingleToInt32Bits(result[0]) : BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "((BitConverter.SingleToInt32Bits(thirdOp[i]) >> 31) & 1) == 1 ? BitConverter.SingleToInt32Bits(secondOp[i]) != BitConverter.SingleToInt32Bits(result[i]) : BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToInt16(\"0xFFFF\", 16) : (short)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToUInt16(\"0xFFFF\", 16) : (ushort)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToInt32(\"0xFFFFFFFF\", 16) : (int)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToUInt32(\"0xFFFFFFFF\", 16) : (uint)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToInt64(\"0xFFFFFFFFFFFFFFFF\", 16) : (long)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToUInt64(\"0xFFFFFFFFFFFFFFFF\", 16): (ulong)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "(byte)(((i & 1) == 0) ? 128 : 1)", ["ValidateFirstResult"] = "((thirdOp[0] >> 7) & 1) == 1 ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "((thirdOp[i] >> 7) & 1) == 1 ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "(double)(((i & 1) == 0) ? -0.0 : 1.0)", ["ValidateFirstResult"] = "((BitConverter.DoubleToInt64Bits(thirdOp[0]) >> 63) & 1) == 1 ? BitConverter.DoubleToInt64Bits(secondOp[0]) != BitConverter.DoubleToInt64Bits(result[0]) : BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "((BitConverter.DoubleToInt64Bits(thirdOp[i]) >> 63) & 1) == 1 ? BitConverter.DoubleToInt64Bits(secondOp[i]) != BitConverter.DoubleToInt64Bits(result[i]) : BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "(sbyte)(((i & 1) == 0) ? -128 : 1)", ["ValidateFirstResult"] = "((thirdOp[0] >> 7) & 1) == 1 ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "((thirdOp[i] >> 7) & 1) == 1 ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "(float)(((i & 1) == 0) ? -0.0 : 1.0)", ["ValidateFirstResult"] = "((BitConverter.SingleToInt32Bits(thirdOp[0]) >> 31) & 1) == 1 ? BitConverter.SingleToInt32Bits(secondOp[0]) != BitConverter.SingleToInt32Bits(result[0]) : BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "((BitConverter.SingleToInt32Bits(thirdOp[i]) >> 31) & 1) == 1 ? BitConverter.SingleToInt32Bits(secondOp[i]) != BitConverter.SingleToInt32Bits(result[i]) : BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToInt16(\"0xFFFF\", 16) : (short)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToUInt16(\"0xFFFF\", 16) : (ushort)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToInt32(\"0xFFFFFFFF\", 16) : (int)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToUInt32(\"0xFFFFFFFF\", 16) : (uint)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToInt64(\"0xFFFFFFFFFFFFFFFF\", 16) : (long)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector128", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToUInt64(\"0xFFFFFFFFFFFFFFFF\", 16): (ulong)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "Ceiling", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Ceiling(firstOp[0]))", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(Math.Ceiling(firstOp[i]))"}), ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse", ["Method"] = "Ceiling", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(MathF.Ceiling(firstOp[0]))", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(MathF.Ceiling(firstOp[i]))"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "CeilingScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Ceiling(right[0]))", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(left[i])"}), @@ -555,7 +603,7 @@ ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != Math.Min(left[0], right[0])", ["ValidateRemainingResults"] = "result[i] != Math.Min(left[i], right[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "MultiplyLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != BitConverter.ToInt32(BitConverter.GetBytes(((long)(left[0])) * right[0]), 0)", ["ValidateRemainingResults"] = "result[i] != BitConverter.ToInt32(BitConverter.GetBytes(((long)(left[i])) * right[i]), 0)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "MultiplyLow", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != BitConverter.ToUInt32(BitConverter.GetBytes(((ulong)(left[0])) * right[0]), 0)", ["ValidateRemainingResults"] = "result[i] != BitConverter.ToUInt32(BitConverter.GetBytes(((ulong)(left[i])) * right[i]), 0)"}), - ("HorizontalBinOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "PackUnsignedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[i1] != ((left[i3 - inner] > 0xFFFF) ? 0xFFFF : ((left[i3 - inner] < 0) ? 0 : BitConverter.ToUInt16(BitConverter.GetBytes(left[i3 - inner]), 0)))", ["ValidateRemainingResults"] = "result[i2] != ((right[i3 - inner] > 0xFFFF) ? 0xFFFF : ((right[i3 - inner] < 0) ? 0 : BitConverter.ToUInt16(BitConverter.GetBytes(right[i3 - inner]), 0)))"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "PackUnsignedSaturate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (ushort)Math.Clamp(left[0], ushort.MinValue, ushort.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i < 4) ? (ushort)Math.Clamp(left[i], ushort.MinValue, ushort.MaxValue) : (ushort)Math.Clamp(right[i&3], ushort.MinValue, ushort.MaxValue))"}), ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "RoundCurrentDirection", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Round(firstOp[0]))", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(Math.Round(firstOp[i]))"}), ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse", ["Method"] = "RoundCurrentDirection", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(MathF.Round(firstOp[0]))", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(MathF.Round(firstOp[i]))"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "RoundCurrentDirectionScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Round(right[0]))", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(left[i])"}), @@ -635,14 +683,14 @@ { ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "Add", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(left[0] + right[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i] + right[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "Add", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(left[0] + right[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i] + right[i]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "AddSubtract", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(left[0] - right[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(((i & 1) != 0) && (BitConverter.DoubleToInt64Bits(left[i] + right[i]) != BitConverter.DoubleToInt64Bits(result[i]))) || (((i & 1) == 0) && (BitConverter.DoubleToInt64Bits(left[i] - right[i]) != BitConverter.DoubleToInt64Bits(result[i])))"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "AddSubtract", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(left[0] - right[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "(((i & 1) != 0) && (BitConverter.SingleToInt32Bits(left[i] + right[i]) != BitConverter.SingleToInt32Bits(result[i]))) || (((i & 1) == 0) && (BitConverter.SingleToInt32Bits(left[i] - right[i]) != BitConverter.SingleToInt32Bits(result[i])))"}), + ("AlternatingBinOpTest.template",new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "AddSubtract", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(left[i] - right[i]) != BitConverter.DoubleToInt64Bits(result[i])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i + 1] + right[i + 1]) != BitConverter.DoubleToInt64Bits(result[i + 1])"}), + ("AlternatingBinOpTest.template",new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "AddSubtract", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(left[i] - right[i]) != BitConverter.SingleToInt32Bits(result[i])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i + 1] + right[i + 1]) != BitConverter.SingleToInt32Bits(result[i + 1])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "And", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(BitConverter.DoubleToInt64Bits(left[0]) & BitConverter.DoubleToInt64Bits(right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.DoubleToInt64Bits(left[i]) & BitConverter.DoubleToInt64Bits(right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "And", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(BitConverter.SingleToInt32Bits(left[0]) & BitConverter.SingleToInt32Bits(right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.SingleToInt32Bits(left[i]) & BitConverter.SingleToInt32Bits(right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "AndNot", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "((~BitConverter.DoubleToInt64Bits(left[0])) & BitConverter.DoubleToInt64Bits(right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "((~BitConverter.DoubleToInt64Bits(left[i])) & BitConverter.DoubleToInt64Bits(right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "AndNot", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "((~BitConverter.SingleToInt32Bits(left[0])) & BitConverter.SingleToInt32Bits(right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "((~BitConverter.SingleToInt32Bits(left[i])) & BitConverter.SingleToInt32Bits(right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "(double)(((i & 1) == 0) ? -0.0 : 1.0)", ["ValidateFirstResult"] = "((BitConverter.DoubleToInt64Bits(thirdOp[0]) >> 63) & 1) == 1 ? BitConverter.DoubleToInt64Bits(secondOp[0]) != BitConverter.DoubleToInt64Bits(result[0]) : BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "((BitConverter.DoubleToInt64Bits(thirdOp[i]) >> 63) & 1) == 1 ? BitConverter.DoubleToInt64Bits(secondOp[i]) != BitConverter.DoubleToInt64Bits(result[i]) : BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "(float)(((i & 1) == 0) ? -0.0 : 1.0)", ["ValidateFirstResult"] = "((BitConverter.SingleToInt32Bits(thirdOp[0]) >> 31) & 1) == 1 ? BitConverter.SingleToInt32Bits(secondOp[0]) != BitConverter.SingleToInt32Bits(result[0]) : BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "((BitConverter.SingleToInt32Bits(thirdOp[i]) >> 31) & 1) == 1 ? BitConverter.SingleToInt32Bits(secondOp[i]) != BitConverter.SingleToInt32Bits(result[i]) : BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "(double)(((i & 1) == 0) ? -0.0 : 1.0)", ["ValidateFirstResult"] = "((BitConverter.DoubleToInt64Bits(thirdOp[0]) >> 63) & 1) == 1 ? BitConverter.DoubleToInt64Bits(secondOp[0]) != BitConverter.DoubleToInt64Bits(result[0]) : BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "((BitConverter.DoubleToInt64Bits(thirdOp[i]) >> 63) & 1) == 1 ? BitConverter.DoubleToInt64Bits(secondOp[i]) != BitConverter.DoubleToInt64Bits(result[i]) : BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "(float)(((i & 1) == 0) ? -0.0 : 1.0)", ["ValidateFirstResult"] = "((BitConverter.SingleToInt32Bits(thirdOp[0]) >> 31) & 1) == 1 ? BitConverter.SingleToInt32Bits(secondOp[0]) != BitConverter.SingleToInt32Bits(result[0]) : BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "((BitConverter.SingleToInt32Bits(thirdOp[i]) >> 31) & 1) == 1 ? BitConverter.SingleToInt32Bits(secondOp[i]) != BitConverter.SingleToInt32Bits(result[i]) : BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])"}), ("LoadUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"]="Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[i])"}), ("LoadUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"]="Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[i])"}), ("LoadUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"]="Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[i])"}), @@ -679,9 +727,9 @@ ("SimpleUnOpConvTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "ConvertToVector256Single", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits((float)firstOp[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((float)firstOp[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "Divide", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(left[0] / right[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i] / right[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "Divide", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(left[0] / right[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i] / right[i]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "DuplicateEvenIndexed", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? (BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])) : (BitConverter.DoubleToInt64Bits(firstOp[i - 1]) != BitConverter.DoubleToInt64Bits(result[i]))"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "DuplicateEvenIndexed", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? (BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])) : (BitConverter.SingleToInt32Bits(firstOp[i - 1]) != BitConverter.SingleToInt32Bits(result[i]))"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "DuplicateOddIndexed", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[1]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? (BitConverter.SingleToInt32Bits(firstOp[i + 1]) != BitConverter.SingleToInt32Bits(result[i])) : (BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i]))"}), + ("ComplexUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "DuplicateEvenIndexed", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? (BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])) : (BitConverter.DoubleToInt64Bits(firstOp[i - 1]) != BitConverter.DoubleToInt64Bits(result[i]))"}), + ("ComplexUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "DuplicateEvenIndexed", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? (BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])) : (BitConverter.SingleToInt32Bits(firstOp[i - 1]) != BitConverter.SingleToInt32Bits(result[i]))"}), + ("ComplexUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "DuplicateOddIndexed", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[1]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? (BitConverter.SingleToInt32Bits(firstOp[i + 1]) != BitConverter.SingleToInt32Bits(result[i])) : (BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i]))"}), ("ImmUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Imm"] = "1", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(firstOp[4])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i+4])"}), ("ImmUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Imm"] = "1", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(firstOp[2])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i+2])"}), ("ImmUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Byte", ["Imm"] = "1", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != firstOp[16]", ["ValidateRemainingResults"] = "result[i] != firstOp[i+16]"}), @@ -740,8 +788,8 @@ ("ImmBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "Permute2x128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt32", ["Imm"] = "2", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != right[0]", ["ValidateRemainingResults"] = "result[i] != (i < 4 ? right[i] : left[i-4])"}), ("ImmBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "Permute2x128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int64", ["Imm"] = "2", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != right[0]", ["ValidateRemainingResults"] = "result[i] != (i < 2 ? right[i] : left[i-2])"}), ("ImmBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "Permute2x128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt64", ["Imm"] = "2", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "result[0] != right[0]", ["ValidateRemainingResults"] = "result[i] != (i < 2 ? right[i] : left[i-2])"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "PermuteVar", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "1", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(left[1]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "i > 3 ? (BitConverter.SingleToInt32Bits(left[5]) != BitConverter.SingleToInt32Bits(result[i])) : (BitConverter.SingleToInt32Bits(left[1]) != BitConverter.SingleToInt32Bits(result[i]))"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "PermuteVar", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "(long)1", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(left[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "i > 1 ? (BitConverter.DoubleToInt64Bits(left[2]) != BitConverter.DoubleToInt64Bits(result[i])) : (BitConverter.DoubleToInt64Bits(left[0]) != BitConverter.DoubleToInt64Bits(result[i]))"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "PermuteVar", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "1", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(left[1]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "i > 3 ? (BitConverter.SingleToInt32Bits(left[5]) != BitConverter.SingleToInt32Bits(result[i])) : (BitConverter.SingleToInt32Bits(left[1]) != BitConverter.SingleToInt32Bits(result[i]))"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "PermuteVar", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "(long)1", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(left[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "i > 1 ? (BitConverter.DoubleToInt64Bits(left[2]) != BitConverter.DoubleToInt64Bits(result[i])) : (BitConverter.DoubleToInt64Bits(left[0]) != BitConverter.DoubleToInt64Bits(result[i]))"}), ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "RoundCurrentDirection", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Round(firstOp[0]))", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(Math.Round(firstOp[i]))"}), ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "RoundCurrentDirection", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(MathF.Round(firstOp[0]))", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(MathF.Round(firstOp[i]))"}), ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "RoundToNearestInteger", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Round(firstOp[0], MidpointRounding.AwayFromZero))", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(Math.Round(firstOp[i], MidpointRounding.AwayFromZero))"}), @@ -790,8 +838,8 @@ ("LoadBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "MaskLoad", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits((BitConverter.SingleToInt32Bits(right[0]) < 0) ? left[0] : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((BitConverter.SingleToInt32Bits(right[i]) < 0) ? left[i] : 0)"}), ("StoreBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "MaskStore", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits((BitConverter.DoubleToInt64Bits(left[0]) < 0) ? right[0] : BitConverter.DoubleToInt64Bits(result[0]))", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits((BitConverter.DoubleToInt64Bits(left[i]) < 0) ? right[i] : BitConverter.DoubleToInt64Bits(result[i]))"}), ("StoreBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "MaskStore", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits((BitConverter.SingleToInt32Bits(left[0]) < 0) ? right[0] : BitConverter.SingleToInt32Bits(result[0]))", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((BitConverter.SingleToInt32Bits(left[i]) < 0) ? right[i] : BitConverter.SingleToInt32Bits(result[i]))"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "PermuteVar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "1", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(left[1]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[1]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "PermuteVar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "(long)1", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(left[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[0]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "PermuteVar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "1", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(left[1]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[1]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Avx", ["LoadIsa"] = "Avx", ["Method"] = "PermuteVar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "(long)1", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(left[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[0]) != BitConverter.DoubleToInt64Bits(result[i])"}), }; (string templateFileName, Dictionary templateData)[] Avx2Inputs = new [] @@ -865,34 +913,34 @@ ("ImmBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "Blend", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt32", ["Imm"] = "2", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != (((2 & (1 << 0)) == 0) ? left[0] : right[0])", ["ValidateRemainingResults"] = "result[i] != (((2 & (1 << i)) == 0) ? left[i] : right[i])"}), ("ImmBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "Blend", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt32", ["Imm"] = "4", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != (((4 & (1 << 0)) == 0) ? left[0] : right[0])", ["ValidateRemainingResults"] = "result[i] != (((4 & (1 << i)) == 0) ? left[i] : right[i])"}), ("ImmBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "Blend", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt32", ["Imm"] = "85", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != (((85 & (1 << 0)) == 0) ? left[0] : right[0])", ["ValidateRemainingResults"] = "result[i] != (((85 & (1 << i)) == 0) ? left[i] : right[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "(byte)(((i & 1) == 0) ? 128 : 1)", ["ValidateFirstResult"] = "((thirdOp[0] >> 7) & 1) == 1 ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "((thirdOp[i] >> 7) & 1) == 1 ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "(sbyte)(((i & 1) == 0) ? -128 : 1)", ["ValidateFirstResult"] = "((thirdOp[0] >> 7) & 1) == 1 ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "((thirdOp[i] >> 7) & 1) == 1 ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToInt16(\"0xFFFF\", 16) : (short)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToUInt16(\"0xFFFF\", 16) : (ushort)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToInt32(\"0xFFFFFFFF\", 16) : (int)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToUInt32(\"0xFFFFFFFF\", 16) : (uint)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToInt64(\"0xFFFFFFFFFFFFFFFF\", 16) : (long)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToUInt64(\"0xFFFFFFFFFFFFFFFF\", 16): (ulong)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[i]))"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[i]))"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[i]))"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[i]))"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "(byte)(((i & 1) == 0) ? 128 : 1)", ["ValidateFirstResult"] = "((thirdOp[0] >> 7) & 1) == 1 ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "((thirdOp[i] >> 7) & 1) == 1 ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "(sbyte)(((i & 1) == 0) ? -128 : 1)", ["ValidateFirstResult"] = "((thirdOp[0] >> 7) & 1) == 1 ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "((thirdOp[i] >> 7) & 1) == 1 ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToInt16(\"0xFFFF\", 16) : (short)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToUInt16(\"0xFFFF\", 16) : (ushort)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToInt32(\"0xFFFFFFFF\", 16) : (int)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToUInt32(\"0xFFFFFFFF\", 16) : (uint)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToInt64(\"0xFFFFFFFFFFFFFFFF\", 16) : (long)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector256", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "(((i & 1) == 0) ? Convert.ToUInt64(\"0xFFFFFFFFFFFFFFFF\", 16): (ulong)0)", ["ValidateFirstResult"] = "(thirdOp[0] != 0) ? secondOp[0] != result[0] : firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(thirdOp[i] != 0) ? secondOp[i] != result[i] : firstOp[i] != result[i]"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[i]))"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[i]))"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[i]))"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[i]))"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != ((left[0] == right[0]) ? unchecked((byte)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] == right[i]) ? unchecked((byte)(-1)) : 0)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != ((left[0] == right[0]) ? unchecked((short)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] == right[i]) ? unchecked((short)(-1)) : 0)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != ((left[0] == right[0]) ? unchecked((int)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] == right[i]) ? unchecked((int)(-1)) : 0)"}), @@ -961,10 +1009,10 @@ ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "Or", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "(ushort)(left[0] | right[0]) != result[0]", ["ValidateRemainingResults"] = "(ushort)(left[i] | right[i]) != result[i]"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "Or", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "(uint)(left[0] | right[0]) != result[0]", ["ValidateRemainingResults"] = "(uint)(left[i] | right[i]) != result[i]"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "Or", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "(ulong)(left[0] | right[0]) != result[0]", ["ValidateRemainingResults"] = "(ulong)(left[i] | right[i]) != result[i]"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "PackUnsignedSaturate", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (ushort)Math.Clamp(left[0], ushort.MinValue, ushort.MaxValue)", ["ValidateRemainingResults"] = "result[i] != (i < 4 ? (ushort)Math.Clamp(left[i], ushort.MinValue, ushort.MaxValue) : (i < 8 && i > 3 ? (ushort)Math.Clamp(right[i&3], ushort.MinValue, ushort.MaxValue) : (i < 12 && i > 7 ? (ushort)Math.Clamp(left[i-4], ushort.MinValue, ushort.MaxValue) : (ushort)Math.Clamp(right[i-8], ushort.MinValue, ushort.MaxValue))))"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "PackUnsignedSaturate", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (byte)Math.Clamp(left[0], byte.MinValue, byte.MaxValue)", ["ValidateRemainingResults"] = "result[i] != (i < 8 ? (byte)Math.Clamp(left[i], byte.MinValue, byte.MaxValue) : (i < 16 && i > 7 ? (byte)Math.Clamp(right[i&7], byte.MinValue, byte.MaxValue) : (i < 24 && i > 15 ? (byte)Math.Clamp(left[i-8], byte.MinValue, byte.MaxValue) : (byte)Math.Clamp(right[i-16], byte.MinValue, byte.MaxValue))))"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "PackSignedSaturate", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (short)Math.Clamp(left[0], short.MinValue, short.MaxValue)", ["ValidateRemainingResults"] = "result[i] != (i < 4 ? (short)Math.Clamp(left[i], short.MinValue, short.MaxValue) : (i < 8 && i > 3 ? (short)Math.Clamp(right[i&3], short.MinValue, short.MaxValue) : (i < 12 && i > 7 ? (short)Math.Clamp(left[i-4], short.MinValue, short.MaxValue) : (short)Math.Clamp(right[i-8], short.MinValue, short.MaxValue))))"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "PackSignedSaturate", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (sbyte)Math.Clamp(left[0], sbyte.MinValue, sbyte.MaxValue)", ["ValidateRemainingResults"] = "result[i] != (i < 8 ? (sbyte)Math.Clamp(left[i], sbyte.MinValue, sbyte.MaxValue) : (i < 16 && i > 7 ? (sbyte)Math.Clamp(right[i&7], sbyte.MinValue, sbyte.MaxValue) : (i < 24 && i > 15 ? (sbyte)Math.Clamp(left[i-8], sbyte.MinValue, sbyte.MaxValue) : (sbyte)Math.Clamp(right[i-16], sbyte.MinValue, sbyte.MaxValue))))"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "PackUnsignedSaturate", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (ushort)Math.Clamp(left[0], ushort.MinValue, ushort.MaxValue)", ["ValidateRemainingResults"] = "result[i] != (i < 4 ? (ushort)Math.Clamp(left[i], ushort.MinValue, ushort.MaxValue) : (i < 8 && i > 3 ? (ushort)Math.Clamp(right[i&3], ushort.MinValue, ushort.MaxValue) : (i < 12 && i > 7 ? (ushort)Math.Clamp(left[i-4], ushort.MinValue, ushort.MaxValue) : (ushort)Math.Clamp(right[i-8], ushort.MinValue, ushort.MaxValue))))"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "PackUnsignedSaturate", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (byte)Math.Clamp(left[0], byte.MinValue, byte.MaxValue)", ["ValidateRemainingResults"] = "result[i] != (i < 8 ? (byte)Math.Clamp(left[i], byte.MinValue, byte.MaxValue) : (i < 16 && i > 7 ? (byte)Math.Clamp(right[i&7], byte.MinValue, byte.MaxValue) : (i < 24 && i > 15 ? (byte)Math.Clamp(left[i-8], byte.MinValue, byte.MaxValue) : (byte)Math.Clamp(right[i-16], byte.MinValue, byte.MaxValue))))"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "PackSignedSaturate", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (short)Math.Clamp(left[0], short.MinValue, short.MaxValue)", ["ValidateRemainingResults"] = "result[i] != (i < 4 ? (short)Math.Clamp(left[i], short.MinValue, short.MaxValue) : (i < 8 && i > 3 ? (short)Math.Clamp(right[i&3], short.MinValue, short.MaxValue) : (i < 12 && i > 7 ? (short)Math.Clamp(left[i-4], short.MinValue, short.MaxValue) : (short)Math.Clamp(right[i-8], short.MinValue, short.MaxValue))))"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "PackSignedSaturate", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (sbyte)Math.Clamp(left[0], sbyte.MinValue, sbyte.MaxValue)", ["ValidateRemainingResults"] = "result[i] != (i < 8 ? (sbyte)Math.Clamp(left[i], sbyte.MinValue, sbyte.MaxValue) : (i < 16 && i > 7 ? (sbyte)Math.Clamp(right[i&7], sbyte.MinValue, sbyte.MaxValue) : (i < 24 && i > 15 ? (sbyte)Math.Clamp(left[i-8], sbyte.MinValue, sbyte.MaxValue) : (sbyte)Math.Clamp(right[i-16], sbyte.MinValue, sbyte.MaxValue))))"}), ("ImmBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "Permute2x128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int32", ["Imm"] = "2", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != right[0]", ["ValidateRemainingResults"] = "i > 3 ? (result[i] != left[i - 4]) : (result[i] != right[i])"}), ("ImmBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "Permute2x128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "UInt32", ["Imm"] = "2", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != right[0]", ["ValidateRemainingResults"] = "i > 3 ? (result[i] != left[i - 4]) : (result[i] != right[i])"}), ("ImmBinOpTest.template", new Dictionary { ["Isa"] = "Avx2", ["LoadIsa"] = "Avx", ["Method"] = "Permute2x128", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector256", ["Op2BaseType"] = "Int64", ["Imm"] = "2", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "result[0] != right[0]", ["ValidateRemainingResults"] = "i > 1 ? (result[i] != left[i - 2]) : (result[i] != right[i])"}), @@ -1125,18 +1173,18 @@ ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "AndNot", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "(ushort)(~left[0] & right[0]) != result[0]", ["ValidateRemainingResults"] = "(ushort)(~left[i] & right[i]) != result[i]"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "AndNot", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "(uint)(~left[0] & right[0]) != result[0]", ["ValidateRemainingResults"] = "(uint)(~left[i] & right[i]) != result[i]"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "AndNot", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "(ulong)(~left[0] & right[0]) != result[0]", ["ValidateRemainingResults"] = "(ulong)(~left[i] & right[i]) != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "(double)(((i & 1) == 0) ? -0.0 : 0.0)", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(double.IsNegative(thirdOp[0]) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(double.IsNegative(thirdOp[i]) ? secondOp[i] : firstOp[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "(int)(((i & 1) == 0) ? -1 : 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "(long)(((i & 1) == 0) ? -1 : 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "(float)(((i & 1) == 0) ? -0.0 : 0.0)", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(float.IsNegative(thirdOp[0]) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(float.IsNegative(thirdOp[i]) ? secondOp[i] : firstOp[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "(uint)(((i & 1) == 0) ? -1 : 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "(ulong)(((i & 1) == 0) ? -1: 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[i]))"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[i]))"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Double", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp3"] = "(double)(((i & 1) == 0) ? -0.0 : 0.0)", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(double.IsNegative(thirdOp[0]) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(double.IsNegative(thirdOp[i]) ? secondOp[i] : firstOp[i])"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int32", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp3"] = "(int)(((i & 1) == 0) ? -1 : 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int64", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp3"] = "(long)(((i & 1) == 0) ? -1 : 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Single", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp3"] = "(float)(((i & 1) == 0) ? -0.0 : 0.0)", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(float.IsNegative(thirdOp[0]) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(float.IsNegative(thirdOp[i]) ? secondOp[i] : firstOp[i])"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "UInt32", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp3"] = "(uint)(((i & 1) == 0) ? -1 : 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "UInt64", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp3"] = "(ulong)(((i & 1) == 0) ? -1: 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[i]))"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[i]))"}), ("LoadUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["Method"] = "BroadcastVector128ToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "result[i] != firstOp[i & 3]"}), ("LoadUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["Method"] = "BroadcastVector128ToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "result[i] != firstOp[i & 3]"}), ("LoadUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["Method"] = "BroadcastVector128ToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i & 3])"}), @@ -1241,9 +1289,9 @@ ("SimpleUnOpConvTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "ConvertToVector512UInt32WithTruncation", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "result[0] != (uint)firstOp[0]", ["ValidateRemainingResults"] = "result[i] != (uint)firstOp[i]"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "Divide", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(left[0] / right[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i] / right[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "Divide", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(left[0] / right[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i] / right[i]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "DuplicateEvenIndexed", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? (BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])) : (BitConverter.DoubleToInt64Bits(firstOp[i - 1]) != BitConverter.DoubleToInt64Bits(result[i]))"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "DuplicateEvenIndexed", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? (BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])) : (BitConverter.SingleToInt32Bits(firstOp[i - 1]) != BitConverter.SingleToInt32Bits(result[i]))"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "DuplicateOddIndexed", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[1]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? (BitConverter.SingleToInt32Bits(firstOp[i + 1]) != BitConverter.SingleToInt32Bits(result[i])) : (BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i]))"}), + ("ComplexUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "DuplicateEvenIndexed", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? (BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i])) : (BitConverter.DoubleToInt64Bits(firstOp[i - 1]) != BitConverter.DoubleToInt64Bits(result[i]))"}), + ("ComplexUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "DuplicateEvenIndexed", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? (BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i])) : (BitConverter.SingleToInt32Bits(firstOp[i - 1]) != BitConverter.SingleToInt32Bits(result[i]))"}), + ("ComplexUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "DuplicateOddIndexed", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(firstOp[1]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "((i & 1) == 0) ? (BitConverter.SingleToInt32Bits(firstOp[i + 1]) != BitConverter.SingleToInt32Bits(result[i])) : (BitConverter.SingleToInt32Bits(firstOp[i]) != BitConverter.SingleToInt32Bits(result[i]))"}), ("ImmUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Single", ["Imm"] = "1", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(firstOp[4])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i+4])"}), ("ImmUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Double", ["Imm"] = "1", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(firstOp[2])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i+2])"}), ("ImmUnOpTest.template", new Dictionary { ["Isa"] = "Avx512F", ["LoadIsa"] = "Avx512F", ["Method"] = "ExtractVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Byte", ["Imm"] = "1", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != firstOp[16]", ["ValidateRemainingResults"] = "result[i] != firstOp[i+16]"}), @@ -2085,14 +2133,14 @@ ("ImmBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "AlignRight", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Byte", ["Imm"] = "250", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != 0", ["ValidateRemainingResults"] = "result[i] != 0"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "Average", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "(byte)((left[0] + right[0] + 1) >> 1) != result[0]", ["ValidateRemainingResults"] = "(byte)((left[i] + right[i] + 1) >> 1) != result[i]"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "Average", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "(ushort)((left[0] + right[0] + 1) >> 1) != result[0]", ["ValidateRemainingResults"] = "(ushort)((left[i] + right[i] + 1) >> 1) != result[i]"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "(byte)(((i & 1) == 0) ? -1 : 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "(short)(((i & 1) == 0) ? -1 : 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "(sbyte)(((i & 1) == 0) ? -1 : 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), - ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "(ushort)(((i & 1) == 0) ? -1 : 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "(byte)(((i & 1) == 0) ? -1 : 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "(short)(((i & 1) == 0) ? -1 : 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "SByte", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp3"] = "(sbyte)(((i & 1) == 0) ? -1 : 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), + ("ComplexTernOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BlendVariable", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "UInt16", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp3"] = "(ushort)(((i & 1) == 0) ? -1 : 0)", ["ValidateFirstResult"] = "result[0] != ((thirdOp[0] != 0) ? secondOp[0] : firstOp[0])", ["ValidateRemainingResults"] = "result[i] != ((thirdOp[i] != 0) ? secondOp[i] : firstOp[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(firstOp[0] != result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateFirstResult"] = "result[0] != ((left[0] == right[0]) ? unchecked((byte)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] == right[i]) ? unchecked((byte)(-1)) : 0)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != ((left[0] == right[0]) ? unchecked((short)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] == right[i]) ? unchecked((short)(-1)) : 0)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "result[0] != ((left[0] == right[0]) ? unchecked((sbyte)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] == right[i]) ? unchecked((sbyte)(-1)) : 0)"}), @@ -2142,10 +2190,10 @@ ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "MultiplyHighRoundScale", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (short)((((left[0] * right[0]) >> 14) + 1) >> 1)", ["ValidateRemainingResults"] = "result[i] != (short)((((left[i] * right[i]) >> 14) + 1) >> 1)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "MultiplyLow", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != BitConverter.ToInt16(BitConverter.GetBytes(((int)(left[0])) * right[0]), 0)", ["ValidateRemainingResults"] = "result[i] != BitConverter.ToInt16(BitConverter.GetBytes(((int)(left[i])) * right[i]), 0)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "MultiplyLow", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "result[0] != BitConverter.ToUInt16(BitConverter.GetBytes(((uint)(left[0])) * right[0]), 0)", ["ValidateRemainingResults"] = "result[i] != BitConverter.ToUInt16(BitConverter.GetBytes(((uint)(left[i])) * right[i]), 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "PackSignedSaturate", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (short)Math.Clamp(left[0], short.MinValue, short.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i & 7) < 4 ? (short)Math.Clamp(left[i - ((i / 8) * 4)], short.MinValue, short.MaxValue) : (short)Math.Clamp(right[i - 4 - ((i / 8) * 4)], short.MinValue, short.MaxValue))"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "PackSignedSaturate", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (sbyte)Math.Clamp(left[0], sbyte.MinValue, sbyte.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i & 15) < 8 ? (sbyte)Math.Clamp(left[i- ((i / 16) * 8)], sbyte.MinValue, sbyte.MaxValue) : (sbyte)Math.Clamp(right[i - 8 - ((i / 16) * 8)], sbyte.MinValue, sbyte.MaxValue))"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "PackUnsignedSaturate", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (byte)Math.Clamp(left[0], byte.MinValue, byte.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i & 15) < 8 ? (byte)Math.Clamp(left[i- ((i / 16) * 8)], byte.MinValue, byte.MaxValue) : (byte)Math.Clamp(right[i - 8 - ((i / 16) * 8)], byte.MinValue, byte.MaxValue))"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "PackUnsignedSaturate", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (ushort)Math.Clamp(left[0], ushort.MinValue, ushort.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i & 7) < 4 ? (ushort)Math.Clamp(left[i- ((i / 8) * 4)], ushort.MinValue, ushort.MaxValue) : (ushort)Math.Clamp(right[i - 4 - ((i / 8) * 4)], ushort.MinValue, ushort.MaxValue))"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "PackSignedSaturate", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (short)Math.Clamp(left[0], short.MinValue, short.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i & 7) < 4 ? (short)Math.Clamp(left[i - ((i / 8) * 4)], short.MinValue, short.MaxValue) : (short)Math.Clamp(right[i - 4 - ((i / 8) * 4)], short.MinValue, short.MaxValue))"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "PackSignedSaturate", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (sbyte)Math.Clamp(left[0], sbyte.MinValue, sbyte.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i & 15) < 8 ? (sbyte)Math.Clamp(left[i- ((i / 16) * 8)], sbyte.MinValue, sbyte.MaxValue) : (sbyte)Math.Clamp(right[i - 8 - ((i / 16) * 8)], sbyte.MinValue, sbyte.MaxValue))"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "PackUnsignedSaturate", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (byte)Math.Clamp(left[0], byte.MinValue, byte.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i & 15) < 8 ? (byte)Math.Clamp(left[i- ((i / 16) * 8)], byte.MinValue, byte.MaxValue) : (byte)Math.Clamp(right[i - 8 - ((i / 16) * 8)], byte.MinValue, byte.MaxValue))"}), + ("ComplexBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "PackUnsignedSaturate", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != (ushort)Math.Clamp(left[0], ushort.MinValue, ushort.MaxValue)", ["ValidateRemainingResults"] = "result[i] != ((i & 7) < 4 ? (ushort)Math.Clamp(left[i- ((i / 8) * 4)], ushort.MinValue, ushort.MaxValue) : (ushort)Math.Clamp(right[i - 4 - ((i / 8) * 4)], ushort.MinValue, ushort.MaxValue))"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "PermuteVar32x16", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != left[(right[0] & 31)]", ["ValidateRemainingResults"] = "result[i] != left[(right[i] & 31)]"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "PermuteVar32x16", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "result[0] != left[(right[0] & 31)]", ["ValidateRemainingResults"] = "result[i] != left[(right[i] & 31)]"}), ("SimpleTernOpTest.template", new Dictionary { ["Isa"] = "Avx512BW", ["LoadIsa"] = "Avx512F", ["Method"] = "PermuteVar32x16x2", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector512", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != (((secondOp[0] & 63) <= 31) ? firstOp[secondOp[0] & 31] : thirdOp[secondOp[0] & 31])", ["ValidateRemainingResults"] = "result[i] != (((secondOp[i] & 63) <= 31) ? firstOp[secondOp[i] & 31] : thirdOp[secondOp[i] & 31])"}), @@ -2305,9 +2353,9 @@ ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512DQ", ["LoadIsa"] = "Avx512F", ["Method"] = "And", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(BitConverter.SingleToInt32Bits(left[0]) & BitConverter.SingleToInt32Bits(right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.SingleToInt32Bits(left[i]) & BitConverter.SingleToInt32Bits(right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512DQ", ["LoadIsa"] = "Avx512F", ["Method"] = "AndNot", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "((~BitConverter.DoubleToInt64Bits(left[0])) & BitConverter.DoubleToInt64Bits(right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "((~BitConverter.DoubleToInt64Bits(left[i])) & BitConverter.DoubleToInt64Bits(right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Avx512DQ", ["LoadIsa"] = "Avx512F", ["Method"] = "AndNot", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector512", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector512", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "((~BitConverter.SingleToInt32Bits(left[0])) & BitConverter.SingleToInt32Bits(right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "((~BitConverter.SingleToInt32Bits(left[i])) & BitConverter.SingleToInt32Bits(right[i])) != BitConverter.SingleToInt32Bits(result[i])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512DQ", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastPairScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i & 1])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512DQ", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastPairScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i & 1])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512DQ", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastPairScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i & 1]))"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512DQ", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastPairScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i & 1])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512DQ", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastPairScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i & 1])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512DQ", ["LoadIsa"] = "Avx512F", ["Method"] = "BroadcastPairScalarToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i & 1]))"}), ("LoadUnOpTest.template", new Dictionary { ["Isa"] = "Avx512DQ", ["Method"] = "BroadcastVector128ToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "result[i] != firstOp[i & 1]"}), ("LoadUnOpTest.template", new Dictionary { ["Isa"] = "Avx512DQ", ["Method"] = "BroadcastVector128ToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "result[i] != firstOp[i & 1]"}), ("LoadUnOpTest.template", new Dictionary { ["Isa"] = "Avx512DQ", ["Method"] = "BroadcastVector128ToVector512", ["RetVectorType"] = "Vector512", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "64", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i & 1])"}), @@ -2396,8 +2444,8 @@ (string templateFileName, Dictionary templateData)[] Avx512DQ_VL_Vector128Inputs = new [] { - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastPairScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i & 1])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastPairScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i & 1])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastPairScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i & 1])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Sse2", ["Method"] = "BroadcastPairScalarToVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i & 1])"}), ("SimpleUnOpConvTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Sse2", ["Method"] = "ConvertToVector128Double", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(firstOp[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i])"}), ("SimpleUnOpConvTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Sse2", ["Method"] = "ConvertToVector128Double", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x7FFF_FFFF_FFFF_FFFFUL)", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(firstOp[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i])"}), ("SimpleUnOpConvTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Sse2", ["Method"] = "ConvertToVector128Int64", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != (long)double.Round(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (long)double.Round(firstOp[i])"}), @@ -2424,9 +2472,9 @@ (string templateFileName, Dictionary templateData)[] Avx512DQ_VL_Vector256Inputs = new [] { - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Avx", ["Method"] = "BroadcastPairScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i & 1])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Avx", ["Method"] = "BroadcastPairScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i & 1])"}), - ("SimpleUnOpTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Avx", ["Method"] = "BroadcastPairScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i & 1]))"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Avx", ["Method"] = "BroadcastPairScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i & 1])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Avx", ["Method"] = "BroadcastPairScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "firstOp[0] != result[0]", ["ValidateRemainingResults"] = "(result[i] != firstOp[i & 1])"}), + ("BroadcastTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Avx", ["Method"] = "BroadcastPairScalarToVector256", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(firstOp[0]) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i & 1]))"}), ("SimpleUnOpConvTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Avx", ["Method"] = "ConvertToVector256Double", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(firstOp[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i])"}), ("SimpleUnOpConvTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Avx", ["Method"] = "ConvertToVector256Double", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "(TestLibrary.Generator.GetUInt64() & 0x7FFF_FFFF_FFFF_FFFFUL)", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(firstOp[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i])"}), ("SimpleUnOpConvTest.template", new Dictionary { ["Isa"] = "Avx512DQ.VL", ["LoadIsa"] = "Avx", ["Method"] = "ConvertToVector256Int64", ["RetVectorType"] = "Vector256", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector256", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "32", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "result[0] != (long)double.Round(firstOp[0])", ["ValidateRemainingResults"] = "result[i] != (long)double.Round(firstOp[i])"}), @@ -2680,12 +2728,18 @@ { ["SseVerify"] = @"..\..\X86\Shared\SseVerify.cs", ["Avx512Verify"] = @"..\..\X86\Shared\Avx512Verify.cs", + ["AlternatingBinaryOpTest"] = @"..\..\X86\Shared\SimpleBinOpTest_DataTable.cs", + ["AlternatingTernaryOpTest"] = @"..\..\X86\Shared\SimpleTernOpTest_DataTable.cs", + ["ComplexBinaryOpTest"] = @"..\..\X86\Shared\SimpleBinOpTest_DataTable.cs", + ["ComplexTernaryOpTest"] = @"..\..\X86\Shared\SimpleTernOpTest_DataTable.cs", + ["ComplexUnaryOpTest"] = @"..\..\X86\Shared\SimpleUnOpTest_DataTable.cs", + ["HorizontalBinaryOpTest"] = @"..\..\X86\Shared\SimpleBinOpTest_DataTable.cs", ["ScalarSimdUnaryOpTest"] = @"..\..\X86\Shared\ScalarSimdUnOpTest_DataTable.cs", ["SimdScalarUnaryOpTest"] = @"..\..\X86\Shared\SimdScalarUnOpTest_DataTable.cs", - ["SimpleTernaryOpTest"] = @"..\..\X86\Shared\SimpleTernOpTest_DataTable.cs", + ["SimpleBinaryOpConvTest"] = @"..\..\X86\Shared\SimpleBinOpConvTest_DataTable.cs", ["SimpleBinaryOpTest"] = @"..\..\X86\Shared\SimpleBinOpTest_DataTable.cs", + ["SimpleTernaryOpTest"] = @"..\..\X86\Shared\SimpleTernOpTest_DataTable.cs", ["SimpleUnaryOpTest"] = @"..\..\X86\Shared\SimpleUnOpTest_DataTable.cs", - ["SimpleBinaryOpConvTest"] = @"..\..\X86\Shared\SimpleBinOpConvTest_DataTable.cs", }; bool isImmTemplate(string name) diff --git a/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs b/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs index c4bdef69eb9e..712c435162aa 100644 --- a/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs +++ b/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs @@ -336,13 +336,16 @@ public sealed class OutOfProcessTest : ITestInfo private CodeBuilder _executionStatement { get; } private string RelativeAssemblyPath { get; } - public OutOfProcessTest(string displayName, string relativeAssemblyPath) + public OutOfProcessTest(string displayName, string relativeAssemblyPath, string? testBuildMode) { Method = displayName; DisplayNameForFiltering = displayName; TestNameExpression = $"@\"{displayName}\""; RelativeAssemblyPath = relativeAssemblyPath; + // Native AOT tests get generated into a 'native' directory, so we need to get out of that one first to find the test + string testPathPrefix = string.Equals(testBuildMode, "nativeaot", StringComparison.OrdinalIgnoreCase) ? "\"..\"" : "null"; + _executionStatement = new CodeBuilder(); _executionStatement.AppendLine(); _executionStatement.AppendLine("if (TestLibrary.OutOfProcessTest.OutOfProcessTestsSupported)"); @@ -350,7 +353,7 @@ public OutOfProcessTest(string displayName, string relativeAssemblyPath) using (_executionStatement.NewBracesScope()) { _executionStatement.AppendLine($@"TestLibrary.OutOfProcessTest" - + $@".RunOutOfProcessTest(@""{relativeAssemblyPath}"");"); + + $@".RunOutOfProcessTest(@""{relativeAssemblyPath}"", {testPathPrefix});"); } } diff --git a/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs b/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs index 9b9dd10b2356..61f4488f0aaa 100644 --- a/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs +++ b/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs @@ -9,6 +9,7 @@ public static class OptionsHelper private const string InMergedTestDirectoryOption = "build_property.InMergedTestDirectory"; private const string IsMergedTestRunnerAssemblyOption = "build_property.IsMergedTestRunnerAssembly"; private const string PriorityOption = "build_property.Priority"; + private const string TestBuildModeOption = "build_property.TestBuildMode"; private const string RuntimeFlavorOption = "build_property.RuntimeFlavor"; private const string IsOutOfProcessTestAssemblyOption = "build_metadata.AdditionalFiles.IsOutOfProcessTestAssembly"; private const string TestFilterOption = "build_property.TestFilter"; @@ -38,6 +39,8 @@ private static bool GetBoolOption(this AnalyzerConfigOptions options, string key internal static string RuntimeFlavor(this AnalyzerConfigOptions options) => options.TryGetValue(RuntimeFlavorOption, out string? flavor) ? flavor : "CoreCLR"; + internal static string? TestBuildMode(this AnalyzerConfigOptions options) => options.TryGetValue(TestBuildModeOption, out string? option) ? option : null; + internal static bool IsOutOfProcessTestAssembly(this AnalyzerConfigOptions options) => options.GetBoolOption(IsOutOfProcessTestAssemblyOption); internal static string? TestFilter(this AnalyzerConfigOptions options) => options.TryGetValue(TestFilterOption, out string? filter) ? filter : null; diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index 06cfdf3022c1..9e7b2e0104df 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -56,7 +56,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) string? testDisplayName = fileOptions.TestDisplayName(); if (assemblyPath is not null && testDisplayName is not null) { - return ImmutableArray.Create(new OutOfProcessTest(testDisplayName, assemblyPath)); + return ImmutableArray.Create(new OutOfProcessTest(testDisplayName, assemblyPath, fileOptions.TestBuildMode())); } } @@ -832,15 +832,15 @@ private static IEnumerable GetTestMethodInfosForMethod(IMethodSymbol Xunit.RuntimeConfiguration skippedConfigurations = 0; Xunit.RuntimeTestModes skippedTestModes = 0; - for (int i = 1; i < filterAttribute.AttributeConstructor!.Parameters.Length; i++) + for (int i = 1; i < filterAttribute.ConstructorArguments.Length; i++) { - ReadSkippedInformationFromSkipOnCoreClrAttributeArgument(filterAttribute, i); + ReadSkippedInformationFromSkipOnCoreClrAttributeArgument(filterAttribute.ConstructorArguments[i]); } - void ReadSkippedInformationFromSkipOnCoreClrAttributeArgument(AttributeData filterAttribute, int argumentIndex) + void ReadSkippedInformationFromSkipOnCoreClrAttributeArgument(TypedConstant argument) { - int argumentValue = (int)filterAttribute.ConstructorArguments[argumentIndex].Value!; - switch (filterAttribute.AttributeConstructor!.Parameters[argumentIndex].Type.ToDisplayString()) + int argumentValue = (int)argument.Value!; + switch (argument.Type!.ToDisplayString()) { case "Xunit.TestPlatforms": skippedTestPlatforms = (Xunit.TestPlatforms)argumentValue; diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props index 067c31f8d6b4..fca5c164fba2 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props @@ -5,6 +5,7 @@ + diff --git a/src/tests/Common/dirs.proj b/src/tests/Common/dirs.proj index 3a77c4c574fd..f984afee54a3 100644 --- a/src/tests/Common/dirs.proj +++ b/src/tests/Common/dirs.proj @@ -112,24 +112,20 @@ 5 - <_GroupStartsWith Include="$(TestRoot)JIT\Methodical\flowgraph"> - 6 - - <_GroupStartsWith Include="$(TestRoot)JIT\opt"> - 7 + 6 <_GroupStartsWith Include="$(TestRoot)JIT\Regression\CLR-x86-JIT\V1-M11-Beta2"> - 8 + 7 <_GroupStartsWith Include="$(TestRoot)JIT\SIMD"> - 9 + 8 <_GroupStartsWith Include="$(TestRoot)Loader\classloader\TypeGeneratorTests\TypeGeneratorTest200"> - 10 + 9 diff --git a/src/tests/Common/testenvironment.proj b/src/tests/Common/testenvironment.proj index 73c5bf8a151c..8333973b0c0c 100644 --- a/src/tests/Common/testenvironment.proj +++ b/src/tests/Common/testenvironment.proj @@ -84,6 +84,7 @@ DOTNET_JitEnableOptRepeat; DOTNET_JitOptRepeat; DOTNET_JitOptRepeatCount; + DOTNET_JitDoReversePostOrderLayout; @@ -243,6 +244,7 @@ + diff --git a/src/tests/Common/wasm-test-runner/index.html b/src/tests/Common/wasm-test-runner/index.html index ff7d959f164d..716b7c4c11f3 100644 --- a/src/tests/Common/wasm-test-runner/index.html +++ b/src/tests/Common/wasm-test-runner/index.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/tests/Directory.Build.props b/src/tests/Directory.Build.props index 28dfc3b471f4..5e9dca28e2bb 100644 --- a/src/tests/Directory.Build.props +++ b/src/tests/Directory.Build.props @@ -141,6 +141,7 @@ false false false + true @@ -213,6 +214,7 @@ <_targetOS>$(TargetOS) + <_targetArchitecture>$(TargetArchitecture) true static true diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets index 8db0908c316c..496981ee0ac7 100644 --- a/src/tests/Directory.Build.targets +++ b/src/tests/Directory.Build.targets @@ -34,8 +34,8 @@ - true - Exe + true + Exe BuildAndRun SharedLibrary @@ -441,7 +441,7 @@ - + MergedTestAssembly diff --git a/src/tests/Directory.Merged.props b/src/tests/Directory.Merged.props index ea43b155669e..1f7dcd2eb642 100644 --- a/src/tests/Directory.Merged.props +++ b/src/tests/Directory.Merged.props @@ -1,6 +1,7 @@ true + true false diff --git a/src/tests/FunctionalTests/WebAssembly/Directory.Build.props b/src/tests/FunctionalTests/WebAssembly/Directory.Build.props index e0eb44a860c4..f0095527e9c4 100644 --- a/src/tests/FunctionalTests/WebAssembly/Directory.Build.props +++ b/src/tests/FunctionalTests/WebAssembly/Directory.Build.props @@ -5,7 +5,7 @@ Exe true - WasmTestOnBrowser + WasmTestOnChrome $(TestArchiveRoot)browseronly/ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ $(DefineConstants);TARGET_BROWSER diff --git a/src/tests/GC/API/Frozen/Frozen.csproj b/src/tests/GC/API/Frozen/Frozen.csproj index 365f9ae36ae0..cdead21ae973 100644 --- a/src/tests/GC/API/Frozen/Frozen.csproj +++ b/src/tests/GC/API/Frozen/Frozen.csproj @@ -7,7 +7,6 @@ true - PdbOnly diff --git a/src/tests/GC/API/GC/Collect.csproj b/src/tests/GC/API/GC/Collect.csproj index f63c83499536..004c93a1d507 100644 --- a/src/tests/GC/API/GC/Collect.csproj +++ b/src/tests/GC/API/GC/Collect.csproj @@ -5,7 +5,6 @@ true - PdbOnly diff --git a/src/tests/GC/API/GC/Collect0.csproj b/src/tests/GC/API/GC/Collect0.csproj index b9852e6827c7..13bec04412bb 100644 --- a/src/tests/GC/API/GC/Collect0.csproj +++ b/src/tests/GC/API/GC/Collect0.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly true diff --git a/src/tests/GC/API/GC/Collect1.csproj b/src/tests/GC/API/GC/Collect1.csproj index 5614f8470570..fd7b51c30391 100644 --- a/src/tests/GC/API/GC/Collect1.csproj +++ b/src/tests/GC/API/GC/Collect1.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly true diff --git a/src/tests/GC/API/GC/Collect_Aggressive.csproj b/src/tests/GC/API/GC/Collect_Aggressive.csproj index 86f2ea87f144..fbed62fde605 100644 --- a/src/tests/GC/API/GC/Collect_Aggressive.csproj +++ b/src/tests/GC/API/GC/Collect_Aggressive.csproj @@ -7,7 +7,6 @@ 0 - PdbOnly diff --git a/src/tests/GC/API/GC/Collect_Aggressive_MultipleParameters.csproj b/src/tests/GC/API/GC/Collect_Aggressive_MultipleParameters.csproj index fca19989bd5e..a2f9aa2b2359 100644 --- a/src/tests/GC/API/GC/Collect_Aggressive_MultipleParameters.csproj +++ b/src/tests/GC/API/GC/Collect_Aggressive_MultipleParameters.csproj @@ -7,7 +7,6 @@ 0 - PdbOnly diff --git a/src/tests/GC/API/GC/Collect_Default_1.csproj b/src/tests/GC/API/GC/Collect_Default_1.csproj index 8f57c4f9dedc..fb4b09e3f95d 100644 --- a/src/tests/GC/API/GC/Collect_Default_1.csproj +++ b/src/tests/GC/API/GC/Collect_Default_1.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GC/Collect_Default_2.csproj b/src/tests/GC/API/GC/Collect_Default_2.csproj index 3d54080c946d..3dc093cfad13 100644 --- a/src/tests/GC/API/GC/Collect_Default_2.csproj +++ b/src/tests/GC/API/GC/Collect_Default_2.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GC/Collect_Default_3.csproj b/src/tests/GC/API/GC/Collect_Default_3.csproj index f7c634662f35..c222fc8398c4 100644 --- a/src/tests/GC/API/GC/Collect_Default_3.csproj +++ b/src/tests/GC/API/GC/Collect_Default_3.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GC/Collect_Forced_1.csproj b/src/tests/GC/API/GC/Collect_Forced_1.csproj index af42f4bee160..68ccf82ad68e 100644 --- a/src/tests/GC/API/GC/Collect_Forced_1.csproj +++ b/src/tests/GC/API/GC/Collect_Forced_1.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly true diff --git a/src/tests/GC/API/GC/Collect_Forced_2.csproj b/src/tests/GC/API/GC/Collect_Forced_2.csproj index e0f46d4b1dfb..614679d5d3d3 100644 --- a/src/tests/GC/API/GC/Collect_Forced_2.csproj +++ b/src/tests/GC/API/GC/Collect_Forced_2.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly true diff --git a/src/tests/GC/API/GC/Collect_Forced_3.csproj b/src/tests/GC/API/GC/Collect_Forced_3.csproj index f68948c42716..305b3fa81751 100644 --- a/src/tests/GC/API/GC/Collect_Forced_3.csproj +++ b/src/tests/GC/API/GC/Collect_Forced_3.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly true diff --git a/src/tests/GC/API/GC/Collect_Optimized_1.csproj b/src/tests/GC/API/GC/Collect_Optimized_1.csproj index 90698ba19d82..eab85ce11f5a 100644 --- a/src/tests/GC/API/GC/Collect_Optimized_1.csproj +++ b/src/tests/GC/API/GC/Collect_Optimized_1.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GC/Collect_Optimized_2.csproj b/src/tests/GC/API/GC/Collect_Optimized_2.csproj index e4080e0820a0..15c4ccda5fba 100644 --- a/src/tests/GC/API/GC/Collect_Optimized_2.csproj +++ b/src/tests/GC/API/GC/Collect_Optimized_2.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GC/Collect_Optimized_3.csproj b/src/tests/GC/API/GC/Collect_Optimized_3.csproj index 4974668203c4..df949d361c10 100644 --- a/src/tests/GC/API/GC/Collect_Optimized_3.csproj +++ b/src/tests/GC/API/GC/Collect_Optimized_3.csproj @@ -4,7 +4,6 @@ 2 - PdbOnly diff --git a/src/tests/GC/API/GC/Collect_fail.csproj b/src/tests/GC/API/GC/Collect_fail.csproj index 586cd07c9df2..9d52bc72ec6b 100644 --- a/src/tests/GC/API/GC/Collect_fail.csproj +++ b/src/tests/GC/API/GC/Collect_fail.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GC/Collect_neg.csproj b/src/tests/GC/API/GC/Collect_neg.csproj index 905acf448213..34d6e3c98db2 100644 --- a/src/tests/GC/API/GC/Collect_neg.csproj +++ b/src/tests/GC/API/GC/Collect_neg.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GC/CollectionCountTest.csproj b/src/tests/GC/API/GC/CollectionCountTest.csproj index 5212016e6e78..0d14b24d30d4 100644 --- a/src/tests/GC/API/GC/CollectionCountTest.csproj +++ b/src/tests/GC/API/GC/CollectionCountTest.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GC/Finalize.csproj b/src/tests/GC/API/GC/Finalize.csproj index fe5e039d5087..521c526c2fa5 100644 --- a/src/tests/GC/API/GC/Finalize.csproj +++ b/src/tests/GC/API/GC/Finalize.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GC/GetAllocatedBytesForCurrentThread.csproj b/src/tests/GC/API/GC/GetAllocatedBytesForCurrentThread.csproj index 71463c3dabd0..63d34b1f8d16 100644 --- a/src/tests/GC/API/GC/GetAllocatedBytesForCurrentThread.csproj +++ b/src/tests/GC/API/GC/GetAllocatedBytesForCurrentThread.csproj @@ -4,7 +4,6 @@ true - PdbOnly true diff --git a/src/tests/GC/API/GC/GetGCMemoryInfo.csproj b/src/tests/GC/API/GC/GetGCMemoryInfo.csproj index fc8c52964d6a..a3e583fd6189 100644 --- a/src/tests/GC/API/GC/GetGCMemoryInfo.csproj +++ b/src/tests/GC/API/GC/GetGCMemoryInfo.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly true diff --git a/src/tests/GC/API/GC/GetGeneration.csproj b/src/tests/GC/API/GC/GetGeneration.csproj index ed537d44d582..9b2082bee17a 100644 --- a/src/tests/GC/API/GC/GetGeneration.csproj +++ b/src/tests/GC/API/GC/GetGeneration.csproj @@ -4,7 +4,6 @@ true - PdbOnly diff --git a/src/tests/GC/API/GC/GetGenerationWR.csproj b/src/tests/GC/API/GC/GetGenerationWR.csproj index 755022a8b246..ac7441211d25 100644 --- a/src/tests/GC/API/GC/GetGenerationWR.csproj +++ b/src/tests/GC/API/GC/GetGenerationWR.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GC/GetGenerationWR2.csproj b/src/tests/GC/API/GC/GetGenerationWR2.csproj index 7fb316e5a064..376eef44664e 100644 --- a/src/tests/GC/API/GC/GetGenerationWR2.csproj +++ b/src/tests/GC/API/GC/GetGenerationWR2.csproj @@ -6,7 +6,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GC/GetGeneration_box.csproj b/src/tests/GC/API/GC/GetGeneration_box.csproj index 1abd1e9906a9..a3fc3c30e942 100644 --- a/src/tests/GC/API/GC/GetGeneration_box.csproj +++ b/src/tests/GC/API/GC/GetGeneration_box.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GC/GetGeneration_fail.csproj b/src/tests/GC/API/GC/GetGeneration_fail.csproj index f6ac71b6b7f8..f453c7a01504 100644 --- a/src/tests/GC/API/GC/GetGeneration_fail.csproj +++ b/src/tests/GC/API/GC/GetGeneration_fail.csproj @@ -4,7 +4,6 @@ - PdbOnly diff --git a/src/tests/GC/API/GC/GetTotalAllocatedBytes.csproj b/src/tests/GC/API/GC/GetTotalAllocatedBytes.csproj index 3bb2bb694796..6ea7fdcaae13 100644 --- a/src/tests/GC/API/GC/GetTotalAllocatedBytes.csproj +++ b/src/tests/GC/API/GC/GetTotalAllocatedBytes.csproj @@ -4,7 +4,6 @@ true - PdbOnly true diff --git a/src/tests/GC/API/GC/GetTotalMemory.csproj b/src/tests/GC/API/GC/GetTotalMemory.csproj index f2dcbc0e03cd..8c5282f18571 100644 --- a/src/tests/GC/API/GC/GetTotalMemory.csproj +++ b/src/tests/GC/API/GC/GetTotalMemory.csproj @@ -6,7 +6,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GC/GetTotalPauseDuration.csproj b/src/tests/GC/API/GC/GetTotalPauseDuration.csproj index 00a592fd61bd..d53082231162 100644 --- a/src/tests/GC/API/GC/GetTotalPauseDuration.csproj +++ b/src/tests/GC/API/GC/GetTotalPauseDuration.csproj @@ -12,7 +12,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GC/KeepAlive.csproj b/src/tests/GC/API/GC/KeepAlive.csproj index 308c0fb740cb..d12dd0eadf19 100644 --- a/src/tests/GC/API/GC/KeepAlive.csproj +++ b/src/tests/GC/API/GC/KeepAlive.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GC/KeepAliveNull.csproj b/src/tests/GC/API/GC/KeepAliveNull.csproj index 1c4d5f7167e3..4c851cfc3448 100644 --- a/src/tests/GC/API/GC/KeepAliveNull.csproj +++ b/src/tests/GC/API/GC/KeepAliveNull.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GC/KeepAliveRecur.csproj b/src/tests/GC/API/GC/KeepAliveRecur.csproj index ae0789f10dae..dbcce512cfb3 100644 --- a/src/tests/GC/API/GC/KeepAliveRecur.csproj +++ b/src/tests/GC/API/GC/KeepAliveRecur.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly true diff --git a/src/tests/GC/API/GC/MaxGeneration.csproj b/src/tests/GC/API/GC/MaxGeneration.csproj index 20539e8b3361..d6cbd21707c5 100644 --- a/src/tests/GC/API/GC/MaxGeneration.csproj +++ b/src/tests/GC/API/GC/MaxGeneration.csproj @@ -4,7 +4,6 @@ - PdbOnly diff --git a/src/tests/GC/API/GC/ReRegisterForFinalize.csproj b/src/tests/GC/API/GC/ReRegisterForFinalize.csproj index ae6b4fb0116a..1aece2971c5f 100644 --- a/src/tests/GC/API/GC/ReRegisterForFinalize.csproj +++ b/src/tests/GC/API/GC/ReRegisterForFinalize.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GC/ReRegisterForFinalize_null.csproj b/src/tests/GC/API/GC/ReRegisterForFinalize_null.csproj index 88d435668d96..5346d389e2fc 100644 --- a/src/tests/GC/API/GC/ReRegisterForFinalize_null.csproj +++ b/src/tests/GC/API/GC/ReRegisterForFinalize_null.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GC/SuppressFinalize.csproj b/src/tests/GC/API/GC/SuppressFinalize.csproj index cec0f4d9966f..dff48cb97c2f 100644 --- a/src/tests/GC/API/GC/SuppressFinalize.csproj +++ b/src/tests/GC/API/GC/SuppressFinalize.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GC/SuppressFinalize_Null.csproj b/src/tests/GC/API/GC/SuppressFinalize_Null.csproj index 127a1cf08c37..6635d8672bdd 100644 --- a/src/tests/GC/API/GC/SuppressFinalize_Null.csproj +++ b/src/tests/GC/API/GC/SuppressFinalize_Null.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GC/TotalMemory.csproj b/src/tests/GC/API/GC/TotalMemory.csproj index 27048c1d81d0..596eb4993202 100644 --- a/src/tests/GC/API/GC/TotalMemory.csproj +++ b/src/tests/GC/API/GC/TotalMemory.csproj @@ -9,7 +9,6 @@ true - PdbOnly diff --git a/src/tests/GC/API/GC/TotalMemory2.csproj b/src/tests/GC/API/GC/TotalMemory2.csproj index eccd9b6b2452..7bfeb7fc251e 100644 --- a/src/tests/GC/API/GC/TotalMemory2.csproj +++ b/src/tests/GC/API/GC/TotalMemory2.csproj @@ -8,7 +8,6 @@ true - PdbOnly diff --git a/src/tests/GC/API/GCHandle/AddrOfPinnedObject.csproj b/src/tests/GC/API/GCHandle/AddrOfPinnedObject.csproj index 5d5995864f42..6e35030fb62f 100644 --- a/src/tests/GC/API/GCHandle/AddrOfPinnedObject.csproj +++ b/src/tests/GC/API/GCHandle/AddrOfPinnedObject.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GCHandle/AddrOfPinnedObject_neg.csproj b/src/tests/GC/API/GCHandle/AddrOfPinnedObject_neg.csproj index 2b9241bfbcd3..9e48185f5999 100644 --- a/src/tests/GC/API/GCHandle/AddrOfPinnedObject_neg.csproj +++ b/src/tests/GC/API/GCHandle/AddrOfPinnedObject_neg.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GCHandle/Alloc.csproj b/src/tests/GC/API/GCHandle/Alloc.csproj index 9bca1f7f4753..8f1d6ffb32c9 100644 --- a/src/tests/GC/API/GCHandle/Alloc.csproj +++ b/src/tests/GC/API/GCHandle/Alloc.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GCHandle/Alloc_neg.csproj b/src/tests/GC/API/GCHandle/Alloc_neg.csproj index c69256d889aa..c23324e49937 100644 --- a/src/tests/GC/API/GCHandle/Alloc_neg.csproj +++ b/src/tests/GC/API/GCHandle/Alloc_neg.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GCHandle/Alloc_neg2.csproj b/src/tests/GC/API/GCHandle/Alloc_neg2.csproj index 3c0d036f3ba9..6fd6d4d4aa28 100644 --- a/src/tests/GC/API/GCHandle/Alloc_neg2.csproj +++ b/src/tests/GC/API/GCHandle/Alloc_neg2.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GCHandle/Casting.csproj b/src/tests/GC/API/GCHandle/Casting.csproj index 510b17aac585..5946d43303d4 100644 --- a/src/tests/GC/API/GCHandle/Casting.csproj +++ b/src/tests/GC/API/GCHandle/Casting.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GCHandle/Equality.csproj b/src/tests/GC/API/GCHandle/Equality.csproj index 3ea3368efbf7..3d5e3096d047 100644 --- a/src/tests/GC/API/GCHandle/Equality.csproj +++ b/src/tests/GC/API/GCHandle/Equality.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GCHandle/Free.csproj b/src/tests/GC/API/GCHandle/Free.csproj index 0d6d7e862450..9aeaf494b6a0 100644 --- a/src/tests/GC/API/GCHandle/Free.csproj +++ b/src/tests/GC/API/GCHandle/Free.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GCHandle/Free_neg.csproj b/src/tests/GC/API/GCHandle/Free_neg.csproj index 36279f7400b9..6974d529047d 100644 --- a/src/tests/GC/API/GCHandle/Free_neg.csproj +++ b/src/tests/GC/API/GCHandle/Free_neg.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GCHandle/HandleCopy.csproj b/src/tests/GC/API/GCHandle/HandleCopy.csproj index 87252e3288c7..7aa1d8a04719 100644 --- a/src/tests/GC/API/GCHandle/HandleCopy.csproj +++ b/src/tests/GC/API/GCHandle/HandleCopy.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GCHandle/IsAllocated.csproj b/src/tests/GC/API/GCHandle/IsAllocated.csproj index a99488d00135..90ee1212b6ce 100644 --- a/src/tests/GC/API/GCHandle/IsAllocated.csproj +++ b/src/tests/GC/API/GCHandle/IsAllocated.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GCHandle/Normal.csproj b/src/tests/GC/API/GCHandle/Normal.csproj index 639c06d44174..a3d5caa82496 100644 --- a/src/tests/GC/API/GCHandle/Normal.csproj +++ b/src/tests/GC/API/GCHandle/Normal.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GCHandle/PinObj_neg.csproj b/src/tests/GC/API/GCHandle/PinObj_neg.csproj index 88b89f5f4a3a..8cd014f5a608 100644 --- a/src/tests/GC/API/GCHandle/PinObj_neg.csproj +++ b/src/tests/GC/API/GCHandle/PinObj_neg.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GCHandle/Pinned.csproj b/src/tests/GC/API/GCHandle/Pinned.csproj index 73491ac61579..1c4aad385b86 100644 --- a/src/tests/GC/API/GCHandle/Pinned.csproj +++ b/src/tests/GC/API/GCHandle/Pinned.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GCHandle/Target.csproj b/src/tests/GC/API/GCHandle/Target.csproj index 88a544493521..c2abd20d6b50 100644 --- a/src/tests/GC/API/GCHandle/Target.csproj +++ b/src/tests/GC/API/GCHandle/Target.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GCHandle/Target_neg.csproj b/src/tests/GC/API/GCHandle/Target_neg.csproj index f336cf89c9e1..b1513bdb591c 100644 --- a/src/tests/GC/API/GCHandle/Target_neg.csproj +++ b/src/tests/GC/API/GCHandle/Target_neg.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GCHandle/ToFromIntPtr.csproj b/src/tests/GC/API/GCHandle/ToFromIntPtr.csproj index 002849ac72f6..d2aba16c1003 100644 --- a/src/tests/GC/API/GCHandle/ToFromIntPtr.csproj +++ b/src/tests/GC/API/GCHandle/ToFromIntPtr.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GCHandle/Weak.csproj b/src/tests/GC/API/GCHandle/Weak.csproj index 8ae51211427b..61b13247d833 100644 --- a/src/tests/GC/API/GCHandle/Weak.csproj +++ b/src/tests/GC/API/GCHandle/Weak.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GCHandleCollector/Count.csproj b/src/tests/GC/API/GCHandleCollector/Count.csproj index e5803f9590d9..83aa55728255 100644 --- a/src/tests/GC/API/GCHandleCollector/Count.csproj +++ b/src/tests/GC/API/GCHandleCollector/Count.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GCHandleCollector/CtorsAndProperties.csproj b/src/tests/GC/API/GCHandleCollector/CtorsAndProperties.csproj index 99d8c3aefaad..8b12dcf7d495 100644 --- a/src/tests/GC/API/GCHandleCollector/CtorsAndProperties.csproj +++ b/src/tests/GC/API/GCHandleCollector/CtorsAndProperties.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/GCHandleCollector/NegTests.csproj b/src/tests/GC/API/GCHandleCollector/NegTests.csproj index b162eea2c8b5..2be1f8990b0e 100644 --- a/src/tests/GC/API/GCHandleCollector/NegTests.csproj +++ b/src/tests/GC/API/GCHandleCollector/NegTests.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/GCHandleCollector/Usage.csproj b/src/tests/GC/API/GCHandleCollector/Usage.csproj index 9500555357d4..3171a3bc7850 100644 --- a/src/tests/GC/API/GCHandleCollector/Usage.csproj +++ b/src/tests/GC/API/GCHandleCollector/Usage.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly true diff --git a/src/tests/GC/API/GCSettings/InputValidation.csproj b/src/tests/GC/API/GCSettings/InputValidation.csproj index d9b649833ac9..e692c9bee70a 100644 --- a/src/tests/GC/API/GCSettings/InputValidation.csproj +++ b/src/tests/GC/API/GCSettings/InputValidation.csproj @@ -4,7 +4,6 @@ - PdbOnly diff --git a/src/tests/GC/API/NoGCRegion/NoGC.csproj b/src/tests/GC/API/NoGCRegion/NoGC.csproj index 922c42de6b3e..53b720b9bc5b 100644 --- a/src/tests/GC/API/NoGCRegion/NoGC.csproj +++ b/src/tests/GC/API/NoGCRegion/NoGC.csproj @@ -6,7 +6,6 @@ true - PdbOnly diff --git a/src/tests/GC/API/Refresh/Refresh.csproj b/src/tests/GC/API/Refresh/Refresh.csproj index 9750538a788b..cc3b9259c5b7 100644 --- a/src/tests/GC/API/Refresh/Refresh.csproj +++ b/src/tests/GC/API/Refresh/Refresh.csproj @@ -7,7 +7,6 @@ true - PdbOnly diff --git a/src/tests/GC/API/WeakReference/Finalize.csproj b/src/tests/GC/API/WeakReference/Finalize.csproj index e8723dbc5630..80e622a36169 100644 --- a/src/tests/GC/API/WeakReference/Finalize.csproj +++ b/src/tests/GC/API/WeakReference/Finalize.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/WeakReference/Finalize2.csproj b/src/tests/GC/API/WeakReference/Finalize2.csproj index 0c6869d9a286..6de8c8aabb34 100644 --- a/src/tests/GC/API/WeakReference/Finalize2.csproj +++ b/src/tests/GC/API/WeakReference/Finalize2.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/WeakReference/IsAlive.csproj b/src/tests/GC/API/WeakReference/IsAlive.csproj index b6fc8222d2c9..8f2de355a1e7 100644 --- a/src/tests/GC/API/WeakReference/IsAlive.csproj +++ b/src/tests/GC/API/WeakReference/IsAlive.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/WeakReference/IsAlive_neg.csproj b/src/tests/GC/API/WeakReference/IsAlive_neg.csproj index 00324dc1ad73..1797ef549eeb 100644 --- a/src/tests/GC/API/WeakReference/IsAlive_neg.csproj +++ b/src/tests/GC/API/WeakReference/IsAlive_neg.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/WeakReference/NullHandle.csproj b/src/tests/GC/API/WeakReference/NullHandle.csproj index 1910559b5b95..e0bc348dbc6b 100644 --- a/src/tests/GC/API/WeakReference/NullHandle.csproj +++ b/src/tests/GC/API/WeakReference/NullHandle.csproj @@ -3,7 +3,6 @@ Exe - PdbOnly diff --git a/src/tests/GC/API/WeakReference/Target.csproj b/src/tests/GC/API/WeakReference/Target.csproj index 88a544493521..c2abd20d6b50 100644 --- a/src/tests/GC/API/WeakReference/Target.csproj +++ b/src/tests/GC/API/WeakReference/Target.csproj @@ -4,7 +4,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/WeakReference/TrackResurrection.csproj b/src/tests/GC/API/WeakReference/TrackResurrection.csproj index ee6c76b610cf..adf191efb965 100644 --- a/src/tests/GC/API/WeakReference/TrackResurrection.csproj +++ b/src/tests/GC/API/WeakReference/TrackResurrection.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/GC/API/WeakReference/multipleWRs.csproj b/src/tests/GC/API/WeakReference/multipleWRs.csproj index faf1dc4b5ae4..d2d0d362488c 100644 --- a/src/tests/GC/API/WeakReference/multipleWRs.csproj +++ b/src/tests/GC/API/WeakReference/multipleWRs.csproj @@ -4,7 +4,6 @@ 10000 - PdbOnly diff --git a/src/tests/GC/API/WeakReference/multipleWRs_1.csproj b/src/tests/GC/API/WeakReference/multipleWRs_1.csproj index 8672dd9e41a0..bc148682db0c 100644 --- a/src/tests/GC/API/WeakReference/multipleWRs_1.csproj +++ b/src/tests/GC/API/WeakReference/multipleWRs_1.csproj @@ -4,7 +4,6 @@ 10000 track - PdbOnly diff --git a/src/tests/GC/Features/HeapExpansion/bestfit_1.csproj b/src/tests/GC/Features/HeapExpansion/bestfit_1.csproj index bb47f926fe14..fabfffe5902b 100644 --- a/src/tests/GC/Features/HeapExpansion/bestfit_1.csproj +++ b/src/tests/GC/Features/HeapExpansion/bestfit_1.csproj @@ -5,7 +5,6 @@ true - PdbOnly diff --git a/src/tests/Interop/ArrayMarshalling/UnalignedStructArray/MarshalUnalignedStructArray.cs b/src/tests/Interop/ArrayMarshalling/UnalignedStructArray/MarshalUnalignedStructArray.cs new file mode 100644 index 000000000000..266a5dbf28d8 --- /dev/null +++ b/src/tests/Interop/ArrayMarshalling/UnalignedStructArray/MarshalUnalignedStructArray.cs @@ -0,0 +1,75 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Runtime.InteropServices; +using TestLibrary; +using Xunit; + +public static unsafe class MarshalUnalignedStructArrayTest +{ + [Fact] + public static void TestEntryPoint() + { + /* + * This test validates that the size and offsets of InnerStruct and OuterStruct are as expected. + * It also demonstrates accessing unaligned data in an array. + */ + // Validate that both InnerStruct and OuterStruct have the correct size + Assert.Equal(12, sizeof(InnerStruct)); + Assert.Equal(24, sizeof(OuterStruct)); + + // Validate that the fields of InnerStruct are at the expected offsets + Assert.Equal(0, Marshal.OffsetOf("F0").ToInt32()); + Assert.Equal(8, Marshal.OffsetOf("F1").ToInt32()); + + // Validate that the fields of OuterStruct are at the expected offsets + Assert.Equal(0, Marshal.OffsetOf("F0").ToInt32()); + Assert.Equal(8, Marshal.OffsetOf("F1").ToInt32()); + Assert.Equal(20, Marshal.OffsetOf("F2").ToInt32()); + + // Validate that we are able to access unaligned in an array + InnerStruct[] arrStructs = new InnerStruct[] + { + new InnerStruct(1, 2), + new InnerStruct(3, 4), + new InnerStruct(5, 6), + }; + + fixed (InnerStruct* pStruct = &arrStructs[0]) + { + byte* ptr = (byte*)pStruct; + ptr += 12; + Assert.Equal(3, *(long*)ptr); + Assert.Equal(4, *(int*)(ptr + 8)); + } + + } +} + +[StructLayout(LayoutKind.Sequential, Size = 12)] +struct InnerStruct +{ + public long F0; + public uint F1; + + public InnerStruct(long f0, uint f1) + { + F0 = f0; + F1 = f1; + } +} + +[StructLayout(LayoutKind.Sequential, Size = 24)] +struct OuterStruct +{ + public sbyte F0; + public InnerStruct F1; + public uint F2; + + public OuterStruct(sbyte f0, InnerStruct f1, uint f2) + { + F0 = f0; + F1 = f1; + F2 = f2; + } +} diff --git a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs index 3de48ae59b79..69865c8f97b8 100644 --- a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs +++ b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs @@ -5,6 +5,7 @@ namespace NetClient { using System; + using System.Drawing; using System.Globalization; using System.Reflection; using System.Runtime.InteropServices; @@ -215,6 +216,103 @@ System.Collections.Generic.IEnumerable GetEnumerable(System.Collections.IEn } } + static void Validate_ValueCoerce_ReturnToManaged() + { + var dispatchCoerceTesting = (DispatchCoerceTesting)new DispatchCoerceTestingClass(); + + Console.WriteLine($"Calling {nameof(DispatchCoerceTesting.ReturnToManaged)} ..."); + + // Supported types + // See returned values in DispatchCoerceTesting.h + (VarEnum type, int expectedValue)[] supportedTypes = + { + (VarEnum.VT_EMPTY, 0), + (VarEnum.VT_I2, 123), + (VarEnum.VT_I4, 123), + (VarEnum.VT_R4, 1), + (VarEnum.VT_R8, 1), + (VarEnum.VT_CY, 123), + (VarEnum.VT_DATE, 1), + (VarEnum.VT_BSTR, 123), + (VarEnum.VT_ERROR, 123), + (VarEnum.VT_BOOL, -1), + (VarEnum.VT_DECIMAL, 123), + }; + + foreach (var (vt, expected) in supportedTypes) + { + Console.WriteLine($"Converting {vt} to int should be supported."); + int result = dispatchCoerceTesting.ReturnToManaged((short)vt); + Assert.Equal(expected, result); + } + + // Not supported source or destination type: COMException { HResult: 0x80020005 } + + // DISP_E_PARAMNOTFOUND: Converts to Missing + Console.WriteLine("Converting from VT_ERROR with DISP_E_PARAMNOTFOUND should be rejected."); + var comException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged(unchecked((short)((short)VarEnum.VT_ERROR | 0x8000)))); + Assert.Equal(unchecked((int)0x80020005), comException.HResult); + + // Types rejected by OAVariantLib + VarEnum[] unsupportedTypes = + { + VarEnum.VT_ERROR | (VarEnum)0x8000, + }; + + // Types rejected by VariantChangeTypeEx + VarEnum[] invalidCastTypes = + { + VarEnum.VT_UNKNOWN, + VarEnum.VT_NULL, + }; + + foreach (var vt in invalidCastTypes) + { + Console.WriteLine($"Converting {vt} to int should fail from VariantChangeTypeEx."); + Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged((short)vt)); + } + + // Invalid: Rejected before reaching coerce + Console.WriteLine("Invalid variant type should throw InvalidOleVariantTypeException."); + var variantException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged(0x7FFF)); + Assert.Equal(unchecked((int)0x80131531), variantException.HResult); + + Console.WriteLine("Invoking void-returning method should not allocate return buffer."); + // E_POINTER translates to NullReferenceException + Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged_Void(0)); + + Console.WriteLine("Converting int to double should be supported."); + Assert.Equal(1234d, dispatchCoerceTesting.ReturnToManaged_Double(1234)); + + Console.WriteLine("Converting int to string should be supported."); + Assert.Equal("1234", dispatchCoerceTesting.ReturnToManaged_String(1234)); + + Console.WriteLine("Converting int to decimal should be supported."); + Assert.Equal(1234m, dispatchCoerceTesting.ReturnToManaged_Decimal(1234)); + + Console.WriteLine("Converting int to DateTime should be supported."); + Assert.Equal(new DateTime(100, 1, 1), dispatchCoerceTesting.ReturnToManaged_DateTime(-657434)); + Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged_DateTime(-657435)); + Assert.Equal(new DateTime(9999, 12, 31), dispatchCoerceTesting.ReturnToManaged_DateTime(2958465)); + Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged_DateTime(2958466)); + + Console.WriteLine("Converting int to System.Drawing.Color should be supported."); + Assert.Equal(Color.FromKnownColor(KnownColor.ActiveBorder), dispatchCoerceTesting.ReturnToManaged_Color(unchecked((int)0x8000000A))); + Assert.Equal(ColorTranslator.FromOle(1234), dispatchCoerceTesting.ReturnToManaged_Color(1234)); + + Console.WriteLine("Converting int to VT_MISSING should be rejected."); + comException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged_Missing(0)); + Assert.Equal(unchecked((int)0x80020005), comException.HResult); + + Console.WriteLine("Converting int to VT_NULL should be rejected."); + comException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged_DBNull(0)); + Assert.Equal(unchecked((int)0x80020005), comException.HResult); + + // LOCAL_BOOL + Console.WriteLine("VARIANT_BOOL should convert to non-numeric string."); + Assert.Equal("True", dispatchCoerceTesting.BoolToString()); + } + [Fact] public static int TestEntryPoint() { @@ -233,6 +331,7 @@ public static int TestEntryPoint() Validate_StructNotSupported(); Validate_LCID_Marshaled(); Validate_Enumerator(); + Validate_ValueCoerce_ReturnToManaged(); } catch (Exception e) { diff --git a/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs new file mode 100644 index 000000000000..37330058801e --- /dev/null +++ b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs @@ -0,0 +1,69 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; +using Server.Contract; + +[ComVisible(true)] +[Guid(Server.Contract.Guids.DispatchCoerceTesting)] +public class DispatchCoerceTesting : Server.Contract.IDispatchCoerceTesting +{ + public int ReturnToManaged(short vt) + { + throw new NotImplementedException(); + } + + public int ManagedArgument(int arg) + { + return arg; + } + + public string BoolToString() + { + throw new NotImplementedException(); + } + + public void ReturnToManaged_Void(int value) + { + throw new NotImplementedException(); + } + + public double ReturnToManaged_Double(int value) + { + throw new NotImplementedException(); + } + + public string ReturnToManaged_String(int value) + { + throw new NotImplementedException(); + } + + public decimal ReturnToManaged_Decimal(int value) + { + throw new NotImplementedException(); + } + + public DateTime ReturnToManaged_DateTime(int value) + { + throw new NotImplementedException(); + } + + public System.Drawing.Color ReturnToManaged_Color(int value) + { + throw new NotImplementedException(); + } + + public System.Reflection.Missing ReturnToManaged_Missing(int value) + { + return System.Reflection.Missing.Value; + } + + public DBNull ReturnToManaged_DBNull(int value) + { + return DBNull.Value; + } +} \ No newline at end of file diff --git a/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp b/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp index 827b8d228763..b2286e25b2d0 100644 --- a/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp +++ b/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp @@ -11,6 +11,7 @@ void Validate_Float_In_ReturnAndUpdateByRef(); void Validate_Double_In_ReturnAndUpdateByRef(); void Validate_LCID_Marshaled(); void Validate_Enumerator(); +void Validate_ParamCoerce(); template struct ComInit @@ -48,6 +49,7 @@ int __cdecl main() Validate_Double_In_ReturnAndUpdateByRef(); Validate_LCID_Marshaled(); Validate_Enumerator(); + Validate_ParamCoerce(); } catch (HRESULT hr) { @@ -459,3 +461,146 @@ void Validate_Enumerator() ::printf(" -- Validate returned IEnumVARIANT\n"); ValidateReturnedEnumerator(&result); } + +void Validate_ParamCoerce_Success(ComSmartPtr& dispatchCoerceTesting, int lcid, DISPID methodId, VARIANT arg, int expected) +{ + HRESULT hr; + + DISPPARAMS params; + VARIANTARG args; + params.cArgs = 1; + params.rgvarg = &args; + params.cNamedArgs = 0; + params.rgdispidNamedArgs = nullptr; + + args = arg; + VARIANT result; + + THROW_IF_FAILED(dispatchCoerceTesting->Invoke( + methodId, + IID_NULL, + lcid, + DISPATCH_METHOD, + ¶ms, + &result, + nullptr, + nullptr + )); + + THROW_FAIL_IF_FALSE(V_I4(&result) == expected); +} + +void Validate_ParamCoerce_Exception(ComSmartPtr& dispatchCoerceTesting, int lcid, DISPID methodId, VARIANT arg, HRESULT expected) +{ + HRESULT hr; + + DISPPARAMS params; + VARIANTARG args; + params.cArgs = 1; + params.rgvarg = &args; + params.cNamedArgs = 0; + params.rgdispidNamedArgs = nullptr; + + args = arg; + VARIANT result; + + hr = dispatchCoerceTesting->Invoke( + methodId, + IID_NULL, + lcid, + DISPATCH_METHOD, + ¶ms, + &result, + nullptr, + nullptr + ); + + THROW_FAIL_IF_FALSE(hr == expected); +} + +void Validate_ParamCoerce() +{ + HRESULT hr; + + CoreShimComActivation csact{ W("NETServer"), W("DispatchCoerceTesting") }; + + ComSmartPtr dispatchCoerceTesting; + THROW_IF_FAILED(::CoCreateInstance(CLSID_DispatchCoerceTesting, nullptr, CLSCTX_INPROC, IID_IDispatchCoerceTesting, (void**)&dispatchCoerceTesting)); + + LPOLESTR numericMethodName = (LPOLESTR)W("ManagedArgument"); + LCID lcid = MAKELCID(LANG_USER_DEFAULT, SORT_DEFAULT); + DISPID methodId; + + ::wprintf(W("Invoke %s\n"), numericMethodName); + THROW_IF_FAILED(dispatchCoerceTesting->GetIDsOfNames( + IID_NULL, + &numericMethodName, + 1, + lcid, + &methodId)); + + VARIANT arg; + + ::wprintf(W("Validating VT_UI4\n")); + V_VT(&arg) = VT_UI4; + V_UI4(&arg) = 0x1234ABCD; + Validate_ParamCoerce_Success(dispatchCoerceTesting, lcid, methodId, arg, 0x1234ABCD); + + ::wprintf(W("Validating VT_I2\n")); + V_VT(&arg) = VT_I2; + V_I2(&arg) = 123; + Validate_ParamCoerce_Success(dispatchCoerceTesting, lcid, methodId, arg, 123); + + ::wprintf(W("Validating VT_I8\n")); + V_VT(&arg) = VT_I8; + V_I8(&arg) = int64_t(1) << 32; + Validate_ParamCoerce_Exception(dispatchCoerceTesting, lcid, methodId, arg, DISP_E_OVERFLOW); + + ::wprintf(W("Validating VT_R8\n")); + V_VT(&arg) = VT_R8; + V_R8(&arg) = 123.45; + Validate_ParamCoerce_Success(dispatchCoerceTesting, lcid, methodId, arg, 123); + + ::wprintf(W("Validating VT_CY\n")); + V_VT(&arg) = VT_CY; + V_I8(&arg) = 123456; + Validate_ParamCoerce_Success(dispatchCoerceTesting, lcid, methodId, arg, 12); + + ::wprintf(W("Validating VT_BSTR\n")); + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = ::SysAllocString(L"123"); + Validate_ParamCoerce_Success(dispatchCoerceTesting, lcid, methodId, arg, 123); + + ::wprintf(W("Validating VT_BOOL\n")); + V_VT(&arg) = VT_BOOL; + V_BOOL(&arg) = VARIANT_TRUE; + Validate_ParamCoerce_Success(dispatchCoerceTesting, lcid, methodId, arg, -1); + V_VT(&arg) = VT_BOOL; + V_I4(&arg) = 123; + Validate_ParamCoerce_Success(dispatchCoerceTesting, lcid, methodId, arg, -1); + V_VT(&arg) = VT_BOOL; + V_BOOL(&arg) = VARIANT_FALSE; + Validate_ParamCoerce_Success(dispatchCoerceTesting, lcid, methodId, arg, 0); + + ::wprintf(W("Validating VT_DATE\n")); + V_VT(&arg) = VT_DATE; + V_R8(&arg) = -657434.0; + Validate_ParamCoerce_Success(dispatchCoerceTesting, lcid, methodId, arg, -657434); + V_VT(&arg) = VT_DATE; + V_R8(&arg) = -657435.0; + Validate_ParamCoerce_Exception(dispatchCoerceTesting, lcid, methodId, arg, E_INVALIDARG); + V_VT(&arg) = VT_DATE; + V_R8(&arg) = 2958465.0; + Validate_ParamCoerce_Success(dispatchCoerceTesting, lcid, methodId, arg, 2958465); + V_VT(&arg) = VT_DATE; + V_R8(&arg) = 2958466.0; + Validate_ParamCoerce_Exception(dispatchCoerceTesting, lcid, methodId, arg, E_INVALIDARG); + + ::wprintf(W("Validating VT_DECIMAL\n")); + V_VT(&arg) = VT_DECIMAL; + VarDecFromI4(123, &V_DECIMAL(&arg)); + Validate_ParamCoerce_Success(dispatchCoerceTesting, lcid, methodId, arg, 123); + V_VT(&arg) = VT_DECIMAL; + VarDecFromI8(int64_t(1) << 32, &V_DECIMAL(&arg)); + Validate_ParamCoerce_Exception(dispatchCoerceTesting, lcid, methodId, arg, DISP_E_OVERFLOW); +} diff --git a/src/tests/Interop/COM/NativeClients/Dispatch/CoreShim.X.manifest b/src/tests/Interop/COM/NativeClients/Dispatch/CoreShim.X.manifest index 0e635e03c3ee..94105dbcbf72 100644 --- a/src/tests/Interop/COM/NativeClients/Dispatch/CoreShim.X.manifest +++ b/src/tests/Interop/COM/NativeClients/Dispatch/CoreShim.X.manifest @@ -11,6 +11,11 @@ + + + diff --git a/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest b/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest index 9f688bc8e22b..12ac7bd541cd 100644 --- a/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest +++ b/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest @@ -42,6 +42,11 @@ clsid="{4DBD9B61-E372-499F-84DE-EFC70AA8A009}" threadingModel="Both" /> + + + cArgs)); + + if (pVarResult == nullptr) + return E_POINTER; + + VARENUM currType; + VARIANTARG *currArg; + size_t argIdx = expectedArgCount - 1; + + // Extract args + { + currType = VT_I2; + currArg = NextArg(pDispParams->rgvarg, argIdx); + RETURN_IF_FAILED(VerifyValues(VARENUM(currType), VARENUM(currArg->vt))); + args[0] = &currArg->iVal; + } + + VARENUM resultType = (VARENUM)*args[0]; + VariantInit(pVarResult); + V_VT(pVarResult) = resultType & 0x7FFF; + + switch ((uint16_t)resultType) + { + case VT_BSTR: + { + BSTR str = ::SysAllocString(L"123"); + V_BSTR(pVarResult) = str; + break; + } + case VT_R4: + { + V_R4(pVarResult) = 1.23f; + break; + } + case VT_DATE: + case VT_R8: + { + V_R8(pVarResult) = 1.23; + break; + } + case VT_CY: + { + VarCyFromI4(123, &V_CY(pVarResult)); + break; + } + case VT_DECIMAL: + { + VarDecFromI4(123, &V_DECIMAL(pVarResult)); + break; + } + case ((VT_ERROR | 0x8000)): + { + V_I4(pVarResult) = DISP_E_PARAMNOTFOUND; + break; + } + case VT_UNKNOWN: + { + (void)QueryInterface(IID_IUnknown, (void**)&V_UNKNOWN(pVarResult)); + break; + } + default: + { + V_I1(pVarResult) = 123; + break; + } + } + + return S_OK; + } + + HRESULT ManagedArgument_Dispatch(_In_ DISPPARAMS *pDispParams, _Inout_ VARIANT *pVarResult) + { + HRESULT hr; + + int *args[1]; + size_t expectedArgCount = 1; + RETURN_IF_FAILED(VerifyValues(uint32_t(expectedArgCount), pDispParams->cArgs)); + + if (pVarResult == nullptr) + return E_POINTER; + + VARENUM currType; + VARIANTARG *currArg; + size_t argIdx = expectedArgCount - 1; + + // Extract args + { + currType = VT_I4; + currArg = NextArg(pDispParams->rgvarg, argIdx); + RETURN_IF_FAILED(VerifyValues(VARENUM(currType), VARENUM(currArg->vt))); + args[0] = &currArg->intVal; + } + + V_VT(pVarResult) = VT_I2; + V_I2(pVarResult) = *args[0]; + return S_OK; + } + + HRESULT ReturnToManaged_Any_Dispatch(_In_ DISPPARAMS *pDispParams, _Inout_ VARIANT *pVarResult) + { + HRESULT hr; + + int *args[1]; + size_t expectedArgCount = 1; + RETURN_IF_FAILED(VerifyValues(uint32_t(expectedArgCount), pDispParams->cArgs)); + + if (pVarResult == nullptr) + return E_POINTER; + + VARENUM currType; + VARIANTARG *currArg; + size_t argIdx = expectedArgCount - 1; + + // Extract args + { + currType = VT_I4; + currArg = NextArg(pDispParams->rgvarg, argIdx); + RETURN_IF_FAILED(VerifyValues(VARENUM(currType), VARENUM(currArg->vt))); + args[0] = &currArg->intVal; + } + + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = *args[0]; + return S_OK; + } + + HRESULT BoolToString_Dispatch(_In_ DISPPARAMS *pDispParams, _Inout_ VARIANT *pVarResult) + { + HRESULT hr; + + size_t expectedArgCount = 0; + RETURN_IF_FAILED(VerifyValues(uint32_t(expectedArgCount), pDispParams->cArgs)); + + if (pVarResult == nullptr) + return E_POINTER; + + V_VT(pVarResult) = VT_BOOL; + V_BOOL(pVarResult) = VARIANT_TRUE; + return S_OK; + } + +public: // IUnknown + STDMETHOD(QueryInterface)( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject) + { + return DoQueryInterface(riid, ppvObject, static_cast(this), static_cast(this)); + } + + DEFINE_REF_COUNTING(); +}; + +const WCHAR * const DispatchCoerceTesting::Names[] = +{ + W("__RESERVED__"), + W("ReturnToManaged"), + W("ManagedArgument"), + W("BoolToString"), + W("ReturnToManaged_Void"), + W("ReturnToManaged_Double"), + W("ReturnToManaged_String"), + W("ReturnToManaged_Decimal"), + W("ReturnToManaged_DateTime"), + W("ReturnToManaged_Color"), + W("ReturnToManaged_Missing"), + W("ReturnToManaged_DBNull"), +}; + +const int DispatchCoerceTesting::NamesCount = ARRAY_SIZE(DispatchCoerceTesting::Names); diff --git a/src/tests/Interop/COM/NativeServer/Servers.cpp b/src/tests/Interop/COM/NativeServer/Servers.cpp index 05f26be8d474..ebe4f9df5acd 100644 --- a/src/tests/Interop/COM/NativeServer/Servers.cpp +++ b/src/tests/Interop/COM/NativeServer/Servers.cpp @@ -166,6 +166,7 @@ STDAPI DllRegisterServer(void) RETURN_IF_FAILED(RegisterClsid(__uuidof(ErrorMarshalTesting), L"Both")); RETURN_IF_FAILED(RegisterClsid(__uuidof(DispatchTesting), L"Both")); RETURN_IF_FAILED(RegisterClsid(__uuidof(EventTesting), L"Both")); + RETURN_IF_FAILED(RegisterClsid(__uuidof(DispatchCoerceTesting), L"Both")); RETURN_IF_FAILED(RegisterClsid(__uuidof(AggregationTesting), L"Both")); RETURN_IF_FAILED(RegisterClsid(__uuidof(ColorTesting), L"Both")); RETURN_IF_FAILED(RegisterClsid(__uuidof(InspectableTesting), L"Both")); @@ -185,6 +186,7 @@ STDAPI DllUnregisterServer(void) RETURN_IF_FAILED(RemoveClsid(__uuidof(ErrorMarshalTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(DispatchTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(EventTesting))); + RETURN_IF_FAILED(RemoveClsid(__uuidof(DispatchCoerceTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(AggregationTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(ColorTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(InspectableTesting))); @@ -216,6 +218,9 @@ STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Out_ LPVOID FA if (rclsid == __uuidof(EventTesting)) return ClassFactoryBasic::Create(riid, ppv); + if (rclsid == __uuidof(DispatchCoerceTesting)) + return ClassFactoryBasic::Create(riid, ppv); + if (rclsid == __uuidof(AggregationTesting)) return ClassFactoryAggregate::Create(riid, ppv); diff --git a/src/tests/Interop/COM/NativeServer/Servers.h b/src/tests/Interop/COM/NativeServer/Servers.h index c87288d2535b..44e5070a25a6 100644 --- a/src/tests/Interop/COM/NativeServer/Servers.h +++ b/src/tests/Interop/COM/NativeServer/Servers.h @@ -16,6 +16,7 @@ class DECLSPEC_UUID("CCFF894B-A27C-45E0-9B30-6C88D722E843") MiscTypesTesting; class DECLSPEC_UUID("71CF5C45-106C-4B32-B418-43A463C6041F") ErrorMarshalTesting; class DECLSPEC_UUID("0F8ACD0C-ECE0-4F2A-BD1B-6BFCA93A0726") DispatchTesting; class DECLSPEC_UUID("4DBD9B61-E372-499F-84DE-EFC70AA8A009") EventTesting; +class DECLSPEC_UUID("661F9962-3477-416B-BE40-4CBA3190A562") DispatchCoerceTesting; class DECLSPEC_UUID("4CEFE36D-F377-4B6E-8C34-819A8BB9CB04") AggregationTesting; class DECLSPEC_UUID("C222F472-DA5A-4FC6-9321-92F4F7053A65") ColorTesting; class DECLSPEC_UUID("66DB7882-E2B0-471D-92C7-B2B52A0EA535") LicenseTesting; @@ -30,6 +31,7 @@ class DECLSPEC_UUID("4F54231D-9E11-4C0B-8E0B-2EBD8B0E5811") TrackMyLifetimeTesti #define CLSID_ErrorMarshalTesting __uuidof(ErrorMarshalTesting) #define CLSID_DispatchTesting __uuidof(DispatchTesting) #define CLSID_EventTesting __uuidof(EventTesting) +#define CLSID_DispatchCoerceTesting __uuidof(DispatchCoerceTesting) #define CLSID_AggregationTesting __uuidof(AggregationTesting) #define CLSID_ColorTesting __uuidof(ColorTesting) #define CLSID_LicenseTesting __uuidof(LicenseTesting) @@ -45,6 +47,7 @@ class DECLSPEC_UUID("4F54231D-9E11-4C0B-8E0B-2EBD8B0E5811") TrackMyLifetimeTesti #define IID_IDispatchTesting __uuidof(IDispatchTesting) #define IID_TestingEvents __uuidof(TestingEvents) #define IID_IEventTesting __uuidof(IEventTesting) +#define IID_IDispatchCoerceTesting __uuidof(IDispatchCoerceTesting) #define IID_IAggregationTesting __uuidof(IAggregationTesting) #define IID_IColorTesting __uuidof(IColorTesting) #define IID_ILicenseTesting __uuidof(ILicenseTesting) @@ -89,6 +92,7 @@ struct CoreShimComActivation #include "ErrorMarshalTesting.h" #include "DispatchTesting.h" #include "EventTesting.h" + #include "DispatchCoerceTesting.h" #include "AggregationTesting.h" #include "ColorTesting.h" #include "LicenseTesting.h" diff --git a/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs b/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs index 2479e6cd6f08..f2c44e4cab4b 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs +++ b/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs @@ -123,6 +123,25 @@ internal class DispatchTestingClass { } + /// + /// Managed definition of CoClass + /// + [ComImport] + [CoClass(typeof(DispatchCoerceTestingClass))] + [Guid("B630A508-4DA5-4C14-A7AB-618AD66B2EBF")] + internal interface DispatchCoerceTesting : Server.Contract.IDispatchCoerceTesting + { + } + + /// + /// Managed activation for CoClass + /// + [ComImport] + [Guid(Server.Contract.Guids.DispatchCoerceTesting)] + internal class DispatchCoerceTestingClass + { + } + /// /// Managed definition of CoClass /// diff --git a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs index dd0f71634e2b..476899377660 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs +++ b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs @@ -319,6 +319,24 @@ public interface TestingEvents void OnEvent([MarshalAs(UnmanagedType.BStr)] string msg); }; + [ComVisible(true)] + [Guid("B630A508-4DA5-4C14-A7AB-618AD66B2EBF")] + [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IDispatchCoerceTesting + { + int ReturnToManaged(short vt); + int ManagedArgument(int arg); + string BoolToString(); + void ReturnToManaged_Void(int value); + double ReturnToManaged_Double(int value); + string ReturnToManaged_String(int value); + decimal ReturnToManaged_Decimal(int value); + DateTime ReturnToManaged_DateTime(int value); + Color ReturnToManaged_Color(int value); + System.Reflection.Missing ReturnToManaged_Missing(int value); + DBNull ReturnToManaged_DBNull(int value); + } + [ComVisible(true)] [Guid("98cc27f0-d521-4f79-8b63-e980e3a92974")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] diff --git a/src/tests/Interop/COM/ServerContracts/Server.Contracts.h b/src/tests/Interop/COM/ServerContracts/Server.Contracts.h index d2c26884589e..719659b7ed90 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.Contracts.h +++ b/src/tests/Interop/COM/ServerContracts/Server.Contracts.h @@ -452,6 +452,12 @@ TestingEvents : IDispatch // void OnEvent(_In_z_ BSTR t); }; +struct __declspec(uuid("b630a508-4da5-4c14-a7ab-618ad66b2ebf")) +IDispatchCoerceTesting : IDispatch +{ + // Methods should only be invoked via IDispatch +}; + struct __declspec(uuid("98cc27f0-d521-4f79-8b63-e980e3a92974")) IAggregationTesting : IUnknown { diff --git a/src/tests/Interop/COM/ServerContracts/ServerGuids.cs b/src/tests/Interop/COM/ServerContracts/ServerGuids.cs index 8b0c65a3ce15..6c6b6569b634 100644 --- a/src/tests/Interop/COM/ServerContracts/ServerGuids.cs +++ b/src/tests/Interop/COM/ServerContracts/ServerGuids.cs @@ -15,6 +15,7 @@ internal sealed class Guids public const string ErrorMarshalTesting = "71CF5C45-106C-4B32-B418-43A463C6041F"; public const string DispatchTesting = "0F8ACD0C-ECE0-4F2A-BD1B-6BFCA93A0726"; public const string EventTesting = "4DBD9B61-E372-499F-84DE-EFC70AA8A009"; + public const string DispatchCoerceTesting = "661F9962-3477-416B-BE40-4CBA3190A562"; public const string AggregationTesting = "4CEFE36D-F377-4B6E-8C34-819A8BB9CB04"; public const string ColorTesting = "C222F472-DA5A-4FC6-9321-92F4F7053A65"; public const string LicenseTesting = "66DB7882-E2B0-471D-92C7-B2B52A0EA535"; diff --git a/src/tests/Interop/Interop.csproj b/src/tests/Interop/Interop.csproj index 2a02c40a4fd5..b0762fcd2eea 100644 --- a/src/tests/Interop/Interop.csproj +++ b/src/tests/Interop/Interop.csproj @@ -6,6 +6,7 @@ Debug;Release;Checked true + true diff --git a/src/tests/Interop/StringMarshalling/AnsiBSTR/AnsiBStrTest.csproj b/src/tests/Interop/StringMarshalling/AnsiBSTR/AnsiBStrTest.csproj index cbf26e129303..712e25136e2d 100644 --- a/src/tests/Interop/StringMarshalling/AnsiBSTR/AnsiBStrTest.csproj +++ b/src/tests/Interop/StringMarshalling/AnsiBSTR/AnsiBStrTest.csproj @@ -13,5 +13,6 @@ + diff --git a/src/tests/Interop/StringMarshalling/LPTSTR/LPTSTRTest.csproj b/src/tests/Interop/StringMarshalling/LPTSTR/LPTSTRTest.csproj index af1674c30184..a505e444b82c 100644 --- a/src/tests/Interop/StringMarshalling/LPTSTR/LPTSTRTest.csproj +++ b/src/tests/Interop/StringMarshalling/LPTSTR/LPTSTRTest.csproj @@ -12,5 +12,6 @@
    + diff --git a/src/tests/Interop/StringMarshalling/UTF8/UTF8Test.csproj b/src/tests/Interop/StringMarshalling/UTF8/UTF8Test.csproj index 40feb428523a..27727cec9cbf 100644 --- a/src/tests/Interop/StringMarshalling/UTF8/UTF8Test.csproj +++ b/src/tests/Interop/StringMarshalling/UTF8/UTF8Test.csproj @@ -7,5 +7,6 @@
    + diff --git a/src/tests/Interop/StringMarshalling/VBByRefStr/VBByRefStrTest.csproj b/src/tests/Interop/StringMarshalling/VBByRefStr/VBByRefStrTest.csproj index a3017d0e8145..46bc389426e8 100644 --- a/src/tests/Interop/StringMarshalling/VBByRefStr/VBByRefStrTest.csproj +++ b/src/tests/Interop/StringMarshalling/VBByRefStr/VBByRefStrTest.csproj @@ -6,5 +6,6 @@ + diff --git a/src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.cs b/src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.cs index b1575e04deab..0f8b3c4294fb 100644 --- a/src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.cs +++ b/src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.cs @@ -128,7 +128,6 @@ public unsafe static void TestSwiftErrorOnStackNotThrown() } [Fact] - [SkipOnMono("needs reverse P/Invoke support")] public static unsafe void TestUnmanagedCallersOnly() { SwiftError error; @@ -144,7 +143,6 @@ public static unsafe void TestUnmanagedCallersOnly() } [Fact] - [SkipOnMono("needs reverse P/Invoke support")] public static unsafe void TestUnmanagedCallersOnlyWithReturn() { SwiftError error; diff --git a/src/tests/JIT/Directed/Misc/Concat/ConcatTest.csproj b/src/tests/JIT/Directed/Misc/Concat/ConcatTest.csproj index 35b03986da64..dce96cbd3efd 100644 --- a/src/tests/JIT/Directed/Misc/Concat/ConcatTest.csproj +++ b/src/tests/JIT/Directed/Misc/Concat/ConcatTest.csproj @@ -4,8 +4,6 @@ None - True - True diff --git a/src/tests/JIT/Directed/Misc/gettype/gettypetypeofmatrix_gettype.csproj b/src/tests/JIT/Directed/Misc/gettype/gettypetypeofmatrix_gettype.csproj index 9f52ab6b1eb8..806b9941f7a4 100644 --- a/src/tests/JIT/Directed/Misc/gettype/gettypetypeofmatrix_gettype.csproj +++ b/src/tests/JIT/Directed/Misc/gettype/gettypetypeofmatrix_gettype.csproj @@ -1,8 +1,6 @@ None - True - True diff --git a/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv1_PREFIX_cs_r.csproj b/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv1_PREFIX_cs_r.csproj index 96678ca134c6..0ea930e593f2 100644 --- a/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv1_PREFIX_cs_r.csproj +++ b/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv1_PREFIX_cs_r.csproj @@ -4,7 +4,6 @@ 1 - False diff --git a/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv1_PREFIX_cs_ro.csproj b/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv1_PREFIX_cs_ro.csproj index acf9ac5bf3f8..62baeac5851e 100644 --- a/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv1_PREFIX_cs_ro.csproj +++ b/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv1_PREFIX_cs_ro.csproj @@ -4,7 +4,6 @@ 1 - True diff --git a/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv2_PREFIX_cs_r.csproj b/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv2_PREFIX_cs_r.csproj index ebb48ab4886a..302930c8037f 100644 --- a/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv2_PREFIX_cs_r.csproj +++ b/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv2_PREFIX_cs_r.csproj @@ -4,7 +4,6 @@ 1 - False diff --git a/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv2_PREFIX_cs_ro.csproj b/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv2_PREFIX_cs_ro.csproj index a7a7639762de..ad0e47962efd 100644 --- a/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv2_PREFIX_cs_ro.csproj +++ b/src/tests/JIT/Directed/PREFIX/PrimitiveVT/callconv2_PREFIX_cs_ro.csproj @@ -4,7 +4,6 @@ 1 - True diff --git a/src/tests/JIT/Directed/PREFIX/PrimitiveVT/helper.csproj b/src/tests/JIT/Directed/PREFIX/PrimitiveVT/helper.csproj index 4a5a8955a8e8..a2aaf3d6217b 100644 --- a/src/tests/JIT/Directed/PREFIX/PrimitiveVT/helper.csproj +++ b/src/tests/JIT/Directed/PREFIX/PrimitiveVT/helper.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/Directed/PREFIX/unaligned/1/add_unaligned_1.ilproj b/src/tests/JIT/Directed/PREFIX/unaligned/1/add_unaligned_1.ilproj index 5d4f6409840b..191c2dfe9eaa 100644 --- a/src/tests/JIT/Directed/PREFIX/unaligned/1/add_unaligned_1.ilproj +++ b/src/tests/JIT/Directed/PREFIX/unaligned/1/add_unaligned_1.ilproj @@ -2,9 +2,6 @@ 1 - - - diff --git a/src/tests/JIT/Directed/PREFIX/unaligned/4/add_unaligned_4.ilproj b/src/tests/JIT/Directed/PREFIX/unaligned/4/add_unaligned_4.ilproj index 5d4f6409840b..191c2dfe9eaa 100644 --- a/src/tests/JIT/Directed/PREFIX/unaligned/4/add_unaligned_4.ilproj +++ b/src/tests/JIT/Directed/PREFIX/unaligned/4/add_unaligned_4.ilproj @@ -2,9 +2,6 @@ 1 - - - diff --git a/src/tests/JIT/Directed/VectorABI/VectorMgdMgdArray_r.csproj b/src/tests/JIT/Directed/VectorABI/VectorMgdMgdArray_r.csproj index 34fd1286e5e9..8cbba2056455 100644 --- a/src/tests/JIT/Directed/VectorABI/VectorMgdMgdArray_r.csproj +++ b/src/tests/JIT/Directed/VectorABI/VectorMgdMgdArray_r.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Directed/VectorABI/VectorMgdMgdArray_ro.csproj b/src/tests/JIT/Directed/VectorABI/VectorMgdMgdArray_ro.csproj index fed23a960141..cc807e118f66 100644 --- a/src/tests/JIT/Directed/VectorABI/VectorMgdMgdArray_ro.csproj +++ b/src/tests/JIT/Directed/VectorABI/VectorMgdMgdArray_ro.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Directed/VectorABI/VectorMgdMgdStatic_r.csproj b/src/tests/JIT/Directed/VectorABI/VectorMgdMgdStatic_r.csproj index 30413af3755a..a161e3aefefc 100644 --- a/src/tests/JIT/Directed/VectorABI/VectorMgdMgdStatic_r.csproj +++ b/src/tests/JIT/Directed/VectorABI/VectorMgdMgdStatic_r.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Directed/VectorABI/VectorMgdMgdStatic_ro.csproj b/src/tests/JIT/Directed/VectorABI/VectorMgdMgdStatic_ro.csproj index bad61ff7d4dd..946654cc420a 100644 --- a/src/tests/JIT/Directed/VectorABI/VectorMgdMgdStatic_ro.csproj +++ b/src/tests/JIT/Directed/VectorABI/VectorMgdMgdStatic_ro.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Directed/VectorABI/VectorMgdMgd_r.csproj b/src/tests/JIT/Directed/VectorABI/VectorMgdMgd_r.csproj index e7d8df2d7d81..e31007095a74 100644 --- a/src/tests/JIT/Directed/VectorABI/VectorMgdMgd_r.csproj +++ b/src/tests/JIT/Directed/VectorABI/VectorMgdMgd_r.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Directed/VectorABI/VectorMgdMgd_ro.csproj b/src/tests/JIT/Directed/VectorABI/VectorMgdMgd_ro.csproj index e24219718742..84c47242a853 100644 --- a/src/tests/JIT/Directed/VectorABI/VectorMgdMgd_ro.csproj +++ b/src/tests/JIT/Directed/VectorABI/VectorMgdMgd_ro.csproj @@ -4,7 +4,6 @@ true - True True true diff --git a/src/tests/JIT/Directed/coverage/importer/ldfldstatic1_importer_r.ilproj b/src/tests/JIT/Directed/coverage/importer/ldfldstatic1_importer_r.ilproj index 27d4cb828eec..9f792d997e6b 100644 --- a/src/tests/JIT/Directed/coverage/importer/ldfldstatic1_importer_r.ilproj +++ b/src/tests/JIT/Directed/coverage/importer/ldfldstatic1_importer_r.ilproj @@ -2,9 +2,6 @@ 1 - - - diff --git a/src/tests/JIT/Directed/coverage/importer/stfldstatic1_importer_r.ilproj b/src/tests/JIT/Directed/coverage/importer/stfldstatic1_importer_r.ilproj index 8a2c60399b14..4e63aa66b6a2 100644 --- a/src/tests/JIT/Directed/coverage/importer/stfldstatic1_importer_r.ilproj +++ b/src/tests/JIT/Directed/coverage/importer/stfldstatic1_importer_r.ilproj @@ -2,9 +2,6 @@ 1 - - - diff --git a/src/tests/JIT/Directed/coverage/importer/subovfun1_r.ilproj b/src/tests/JIT/Directed/coverage/importer/subovfun1_r.ilproj index 4aaa0bf164f4..d93712ff7953 100644 --- a/src/tests/JIT/Directed/coverage/importer/subovfun1_r.ilproj +++ b/src/tests/JIT/Directed/coverage/importer/subovfun1_r.ilproj @@ -2,9 +2,6 @@ 1 - - - diff --git a/src/tests/JIT/Directed/coverage/oldtests/tls1.ilproj b/src/tests/JIT/Directed/coverage/oldtests/tls1.ilproj index 91073167ada0..9d3165242e3e 100644 --- a/src/tests/JIT/Directed/coverage/oldtests/tls1.ilproj +++ b/src/tests/JIT/Directed/coverage/oldtests/tls1.ilproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/Directed/coverage/oldtests/tls2.ilproj b/src/tests/JIT/Directed/coverage/oldtests/tls2.ilproj index 4cf9a8c7ac5c..77a76e8a3b49 100644 --- a/src/tests/JIT/Directed/coverage/oldtests/tls2.ilproj +++ b/src/tests/JIT/Directed/coverage/oldtests/tls2.ilproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/Directed/forceinlining/LargeNumberOfArgs.csproj b/src/tests/JIT/Directed/forceinlining/LargeNumberOfArgs.csproj index 18d5ea871958..c256718c5406 100644 --- a/src/tests/JIT/Directed/forceinlining/LargeNumberOfArgs.csproj +++ b/src/tests/JIT/Directed/forceinlining/LargeNumberOfArgs.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Directed/forceinlining/NoMetaData.csproj b/src/tests/JIT/Directed/forceinlining/NoMetaData.csproj index ff234a4ab836..e47c9b6235e3 100644 --- a/src/tests/JIT/Directed/forceinlining/NoMetaData.csproj +++ b/src/tests/JIT/Directed/forceinlining/NoMetaData.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Directed/forceinlining/Recursion.csproj b/src/tests/JIT/Directed/forceinlining/Recursion.csproj index 15332f77c63d..d2e8bcfef79f 100644 --- a/src/tests/JIT/Directed/forceinlining/Recursion.csproj +++ b/src/tests/JIT/Directed/forceinlining/Recursion.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Directed/gettypetypeof/gettypetypeofmatrix_gettypetypeof.csproj b/src/tests/JIT/Directed/gettypetypeof/gettypetypeofmatrix_gettypetypeof.csproj index 633e8fa521a0..666bd86f9ec0 100644 --- a/src/tests/JIT/Directed/gettypetypeof/gettypetypeofmatrix_gettypetypeof.csproj +++ b/src/tests/JIT/Directed/gettypetypeof/gettypetypeofmatrix_gettypetypeof.csproj @@ -1,8 +1,5 @@ - - - True diff --git a/src/tests/JIT/Directed/lifetime/lifetime2.csproj b/src/tests/JIT/Directed/lifetime/lifetime2.csproj index 7913879515eb..0e79bac317c9 100644 --- a/src/tests/JIT/Directed/lifetime/lifetime2.csproj +++ b/src/tests/JIT/Directed/lifetime/lifetime2.csproj @@ -10,6 +10,7 @@ None True True + true diff --git a/src/tests/JIT/Directed/nullabletypes/constructor_d.csproj b/src/tests/JIT/Directed/nullabletypes/constructor_d.csproj index 6ab4de272c83..f6a0bc7ae762 100644 --- a/src/tests/JIT/Directed/nullabletypes/constructor_d.csproj +++ b/src/tests/JIT/Directed/nullabletypes/constructor_d.csproj @@ -3,7 +3,6 @@ 1 - Full diff --git a/src/tests/JIT/Directed/nullabletypes/constructor_do.csproj b/src/tests/JIT/Directed/nullabletypes/constructor_do.csproj index f526947f878c..c85345c54d29 100644 --- a/src/tests/JIT/Directed/nullabletypes/constructor_do.csproj +++ b/src/tests/JIT/Directed/nullabletypes/constructor_do.csproj @@ -3,7 +3,6 @@ 1 - Full True diff --git a/src/tests/JIT/Directed/nullabletypes/constructor_r.csproj b/src/tests/JIT/Directed/nullabletypes/constructor_r.csproj index 90bcc3f8610f..89d794c4a304 100644 --- a/src/tests/JIT/Directed/nullabletypes/constructor_r.csproj +++ b/src/tests/JIT/Directed/nullabletypes/constructor_r.csproj @@ -3,7 +3,6 @@ 1 - None diff --git a/src/tests/JIT/Directed/nullabletypes/constructor_ro.csproj b/src/tests/JIT/Directed/nullabletypes/constructor_ro.csproj index 40a3da121f91..40b2310f2a8b 100644 --- a/src/tests/JIT/Directed/nullabletypes/constructor_ro.csproj +++ b/src/tests/JIT/Directed/nullabletypes/constructor_ro.csproj @@ -3,7 +3,6 @@ 1 - None True diff --git a/src/tests/JIT/Directed/nullabletypes/hashcode_d.csproj b/src/tests/JIT/Directed/nullabletypes/hashcode_d.csproj index bcdf5eb1b4e9..230a629c7aeb 100644 --- a/src/tests/JIT/Directed/nullabletypes/hashcode_d.csproj +++ b/src/tests/JIT/Directed/nullabletypes/hashcode_d.csproj @@ -1,6 +1,5 @@ - Full diff --git a/src/tests/JIT/Directed/nullabletypes/hashcode_do.csproj b/src/tests/JIT/Directed/nullabletypes/hashcode_do.csproj index d87c6ceb3cf7..65ab3d9e7542 100644 --- a/src/tests/JIT/Directed/nullabletypes/hashcode_do.csproj +++ b/src/tests/JIT/Directed/nullabletypes/hashcode_do.csproj @@ -1,6 +1,5 @@ - Full True diff --git a/src/tests/JIT/Directed/nullabletypes/hashcode_r.csproj b/src/tests/JIT/Directed/nullabletypes/hashcode_r.csproj index f623daf60f95..eaae37cc8835 100644 --- a/src/tests/JIT/Directed/nullabletypes/hashcode_r.csproj +++ b/src/tests/JIT/Directed/nullabletypes/hashcode_r.csproj @@ -1,6 +1,5 @@ - None diff --git a/src/tests/JIT/Directed/nullabletypes/hashcode_ro.csproj b/src/tests/JIT/Directed/nullabletypes/hashcode_ro.csproj index adbad9caec27..f617c0888182 100644 --- a/src/tests/JIT/Directed/nullabletypes/hashcode_ro.csproj +++ b/src/tests/JIT/Directed/nullabletypes/hashcode_ro.csproj @@ -1,6 +1,5 @@ - None True diff --git a/src/tests/JIT/Directed/nullabletypes/hasvalue_d.csproj b/src/tests/JIT/Directed/nullabletypes/hasvalue_d.csproj index e37186898274..a11241a13796 100644 --- a/src/tests/JIT/Directed/nullabletypes/hasvalue_d.csproj +++ b/src/tests/JIT/Directed/nullabletypes/hasvalue_d.csproj @@ -3,7 +3,6 @@ 1 - Full diff --git a/src/tests/JIT/Directed/nullabletypes/hasvalue_do.csproj b/src/tests/JIT/Directed/nullabletypes/hasvalue_do.csproj index 17c7038594a5..7663e243b6e9 100644 --- a/src/tests/JIT/Directed/nullabletypes/hasvalue_do.csproj +++ b/src/tests/JIT/Directed/nullabletypes/hasvalue_do.csproj @@ -3,7 +3,6 @@ 1 - Full True diff --git a/src/tests/JIT/Directed/nullabletypes/hasvalue_r.csproj b/src/tests/JIT/Directed/nullabletypes/hasvalue_r.csproj index 2dccb1127ba5..43690dbb04b4 100644 --- a/src/tests/JIT/Directed/nullabletypes/hasvalue_r.csproj +++ b/src/tests/JIT/Directed/nullabletypes/hasvalue_r.csproj @@ -3,7 +3,6 @@ 1 - None diff --git a/src/tests/JIT/Directed/nullabletypes/hasvalue_ro.csproj b/src/tests/JIT/Directed/nullabletypes/hasvalue_ro.csproj index 48fab0d5e616..70b951c5cdf3 100644 --- a/src/tests/JIT/Directed/nullabletypes/hasvalue_ro.csproj +++ b/src/tests/JIT/Directed/nullabletypes/hasvalue_ro.csproj @@ -3,7 +3,6 @@ 1 - None True diff --git a/src/tests/JIT/Directed/nullabletypes/invocation_d.csproj b/src/tests/JIT/Directed/nullabletypes/invocation_d.csproj index 923c18fdf786..4a8bdfd7d02c 100644 --- a/src/tests/JIT/Directed/nullabletypes/invocation_d.csproj +++ b/src/tests/JIT/Directed/nullabletypes/invocation_d.csproj @@ -3,7 +3,6 @@ 1 - Full diff --git a/src/tests/JIT/Directed/nullabletypes/invocation_do.csproj b/src/tests/JIT/Directed/nullabletypes/invocation_do.csproj index 338f3875c4a6..46fcdc434de3 100644 --- a/src/tests/JIT/Directed/nullabletypes/invocation_do.csproj +++ b/src/tests/JIT/Directed/nullabletypes/invocation_do.csproj @@ -3,7 +3,6 @@ 1 - Full True diff --git a/src/tests/JIT/Directed/nullabletypes/invocation_r.csproj b/src/tests/JIT/Directed/nullabletypes/invocation_r.csproj index f1fbcbad5f04..92feeffc4e4f 100644 --- a/src/tests/JIT/Directed/nullabletypes/invocation_r.csproj +++ b/src/tests/JIT/Directed/nullabletypes/invocation_r.csproj @@ -3,7 +3,6 @@ 1 - None diff --git a/src/tests/JIT/Directed/nullabletypes/invocation_ro.csproj b/src/tests/JIT/Directed/nullabletypes/invocation_ro.csproj index 9bf7f5615f04..1962c01cb21f 100644 --- a/src/tests/JIT/Directed/nullabletypes/invocation_ro.csproj +++ b/src/tests/JIT/Directed/nullabletypes/invocation_ro.csproj @@ -3,7 +3,6 @@ 1 - None True diff --git a/src/tests/JIT/Directed/nullabletypes/tostring_d.csproj b/src/tests/JIT/Directed/nullabletypes/tostring_d.csproj index ea1b5b84a4ff..f0f9688e2298 100644 --- a/src/tests/JIT/Directed/nullabletypes/tostring_d.csproj +++ b/src/tests/JIT/Directed/nullabletypes/tostring_d.csproj @@ -3,7 +3,6 @@ 1 - Full diff --git a/src/tests/JIT/Directed/nullabletypes/tostring_do.csproj b/src/tests/JIT/Directed/nullabletypes/tostring_do.csproj index a92e85b46202..4aac1c6305bf 100644 --- a/src/tests/JIT/Directed/nullabletypes/tostring_do.csproj +++ b/src/tests/JIT/Directed/nullabletypes/tostring_do.csproj @@ -3,7 +3,6 @@ 1 - Full True diff --git a/src/tests/JIT/Directed/nullabletypes/tostring_r.csproj b/src/tests/JIT/Directed/nullabletypes/tostring_r.csproj index 7097390ac2ad..fc96f245be02 100644 --- a/src/tests/JIT/Directed/nullabletypes/tostring_r.csproj +++ b/src/tests/JIT/Directed/nullabletypes/tostring_r.csproj @@ -3,7 +3,6 @@ 1 - None diff --git a/src/tests/JIT/Directed/nullabletypes/tostring_ro.csproj b/src/tests/JIT/Directed/nullabletypes/tostring_ro.csproj index 9b1af1eca9c5..e3c7b54832dc 100644 --- a/src/tests/JIT/Directed/nullabletypes/tostring_ro.csproj +++ b/src/tests/JIT/Directed/nullabletypes/tostring_ro.csproj @@ -3,7 +3,6 @@ 1 - None True diff --git a/src/tests/JIT/Directed/nullabletypes/unboxnullable_d.csproj b/src/tests/JIT/Directed/nullabletypes/unboxnullable_d.csproj index 472f2e0a6f70..69ca233e1767 100644 --- a/src/tests/JIT/Directed/nullabletypes/unboxnullable_d.csproj +++ b/src/tests/JIT/Directed/nullabletypes/unboxnullable_d.csproj @@ -1,10 +1,7 @@ - Full False - True - True diff --git a/src/tests/JIT/Directed/nullabletypes/unboxnullable_do.csproj b/src/tests/JIT/Directed/nullabletypes/unboxnullable_do.csproj index c55fcdf0a491..e7d8fad09439 100644 --- a/src/tests/JIT/Directed/nullabletypes/unboxnullable_do.csproj +++ b/src/tests/JIT/Directed/nullabletypes/unboxnullable_do.csproj @@ -1,10 +1,7 @@ - Full True - True - True diff --git a/src/tests/JIT/Directed/nullabletypes/unboxnullable_r.csproj b/src/tests/JIT/Directed/nullabletypes/unboxnullable_r.csproj index 362d304aa013..4a1df951c042 100644 --- a/src/tests/JIT/Directed/nullabletypes/unboxnullable_r.csproj +++ b/src/tests/JIT/Directed/nullabletypes/unboxnullable_r.csproj @@ -1,10 +1,7 @@ - None False - True - True diff --git a/src/tests/JIT/Directed/nullabletypes/unboxnullable_ro.csproj b/src/tests/JIT/Directed/nullabletypes/unboxnullable_ro.csproj index 6d4fbcc0f6df..58628f30e3cb 100644 --- a/src/tests/JIT/Directed/nullabletypes/unboxnullable_ro.csproj +++ b/src/tests/JIT/Directed/nullabletypes/unboxnullable_ro.csproj @@ -1,10 +1,7 @@ - None True - True - True diff --git a/src/tests/JIT/Directed/nullabletypes/value_d.csproj b/src/tests/JIT/Directed/nullabletypes/value_d.csproj index 433345004036..a3c60c2718cf 100644 --- a/src/tests/JIT/Directed/nullabletypes/value_d.csproj +++ b/src/tests/JIT/Directed/nullabletypes/value_d.csproj @@ -1,10 +1,7 @@ - Full False - True - True diff --git a/src/tests/JIT/Directed/nullabletypes/value_do.csproj b/src/tests/JIT/Directed/nullabletypes/value_do.csproj index 236bf1fdc5d2..1f5bce06f0d0 100644 --- a/src/tests/JIT/Directed/nullabletypes/value_do.csproj +++ b/src/tests/JIT/Directed/nullabletypes/value_do.csproj @@ -1,10 +1,7 @@ - Full True - True - True diff --git a/src/tests/JIT/Directed/nullabletypes/value_r.csproj b/src/tests/JIT/Directed/nullabletypes/value_r.csproj index 1b949577452b..53a6830faeed 100644 --- a/src/tests/JIT/Directed/nullabletypes/value_r.csproj +++ b/src/tests/JIT/Directed/nullabletypes/value_r.csproj @@ -1,10 +1,7 @@ - None - True - True diff --git a/src/tests/JIT/Directed/nullabletypes/value_ro.csproj b/src/tests/JIT/Directed/nullabletypes/value_ro.csproj index b507082b55b0..fa3ada8dc08e 100644 --- a/src/tests/JIT/Directed/nullabletypes/value_ro.csproj +++ b/src/tests/JIT/Directed/nullabletypes/value_ro.csproj @@ -1,10 +1,7 @@ - None True - True - True diff --git a/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_d.csproj b/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_d.csproj index 3e211f329712..e8178c3508b8 100644 --- a/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_d.csproj +++ b/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_d.csproj @@ -3,11 +3,8 @@ 1 - Full False - True - True diff --git a/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_do.csproj b/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_do.csproj index 7b48178b311a..b6fc9e368d00 100644 --- a/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_do.csproj +++ b/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_do.csproj @@ -3,11 +3,8 @@ 1 - Full True - True - True diff --git a/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_r.csproj b/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_r.csproj index b2cbd11acfef..41e85d65611a 100644 --- a/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_r.csproj +++ b/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_r.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True diff --git a/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_ro.csproj b/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_ro.csproj index ea7779dc1825..718f083ad5ee 100644 --- a/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_ro.csproj +++ b/src/tests/JIT/Directed/perffix/commutativecse/ccse_cs_ro.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_d.csproj b/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_d.csproj index 593f241ca096..b4d332ad4294 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_d.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_d.csproj @@ -3,7 +3,6 @@ 1 - Full True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_do.csproj b/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_do.csproj index 5adbd19844b7..ade9ec09434c 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_do.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_do.csproj @@ -3,7 +3,6 @@ 1 - Full True True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_r.csproj b/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_r.csproj index 622c345ddd5a..6a20bc566d0e 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_r.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_r.csproj @@ -3,7 +3,6 @@ 1 - None True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_ro.csproj b/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_ro.csproj index 503fd57be321..f20dea513e46 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_ro.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/callconv1_perffix_cs_ro.csproj @@ -3,7 +3,6 @@ 1 - None True True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_d.csproj b/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_d.csproj index 0afd4df87acd..7827d9e9025d 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_d.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_d.csproj @@ -3,7 +3,6 @@ 1 - Full True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_do.csproj b/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_do.csproj index 3c2e6d138320..cc54b47cff8b 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_do.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_do.csproj @@ -3,7 +3,6 @@ 1 - Full True True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_r.csproj b/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_r.csproj index 353921da02ee..770f1747f6c9 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_r.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_r.csproj @@ -3,7 +3,6 @@ 1 - None True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_ro.csproj b/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_ro.csproj index de470d1085aa..a5a648f63447 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_ro.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/callconv2_perffix_cs_ro.csproj @@ -3,7 +3,6 @@ 1 - None True True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_d.csproj b/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_d.csproj index ce78f7dd8cf4..389f948ba06b 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_d.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_d.csproj @@ -3,11 +3,8 @@ 1 - Full False - True - True True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_do.csproj b/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_do.csproj index fb7e59790db1..b2674ad985ce 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_do.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_do.csproj @@ -1,10 +1,7 @@ - Full True - True - True True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_r.csproj b/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_r.csproj index 3bcefab62204..3bbf429c8397 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_r.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_r.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_ro.csproj b/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_ro.csproj index 544fe7a84b5f..527c5750d589 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_ro.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/mixed1_cs_ro.csproj @@ -1,10 +1,7 @@ - None True - True - True True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_d.csproj b/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_d.csproj index 3bac8525408c..7f76f49d02c1 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_d.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_d.csproj @@ -3,11 +3,8 @@ 1 - Full False - True - True True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_do.csproj b/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_do.csproj index 6007ac2cfe88..8eadaccad6e8 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_do.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_do.csproj @@ -3,11 +3,8 @@ 1 - Full True - True - True True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_r.csproj b/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_r.csproj index 318e3db1f329..e068e69a7988 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_r.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_r.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True True diff --git a/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_ro.csproj b/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_ro.csproj index 351c5a5ca54b..aefd435a30f9 100644 --- a/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_ro.csproj +++ b/src/tests/JIT/Directed/perffix/primitivevt/mixed2_cs_ro.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True True diff --git a/src/tests/JIT/Directed/shift/int16_r.csproj b/src/tests/JIT/Directed/shift/int16_r.csproj index 504c60fa275c..805237d89a56 100644 --- a/src/tests/JIT/Directed/shift/int16_r.csproj +++ b/src/tests/JIT/Directed/shift/int16_r.csproj @@ -3,7 +3,6 @@ 1 - diff --git a/src/tests/JIT/Directed/shift/int16_ro.csproj b/src/tests/JIT/Directed/shift/int16_ro.csproj index 046cae5c16bd..3659879ba042 100644 --- a/src/tests/JIT/Directed/shift/int16_ro.csproj +++ b/src/tests/JIT/Directed/shift/int16_ro.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Directed/shift/int32_r.csproj b/src/tests/JIT/Directed/shift/int32_r.csproj index 38a64e66b053..cfefd9612839 100644 --- a/src/tests/JIT/Directed/shift/int32_r.csproj +++ b/src/tests/JIT/Directed/shift/int32_r.csproj @@ -3,7 +3,6 @@ 1 - diff --git a/src/tests/JIT/Directed/shift/int32_ro.csproj b/src/tests/JIT/Directed/shift/int32_ro.csproj index b92c75753070..2929b8f6e68b 100644 --- a/src/tests/JIT/Directed/shift/int32_ro.csproj +++ b/src/tests/JIT/Directed/shift/int32_ro.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Directed/shift/int64_r.csproj b/src/tests/JIT/Directed/shift/int64_r.csproj index a06d291d1fc9..2ee6293bce75 100644 --- a/src/tests/JIT/Directed/shift/int64_r.csproj +++ b/src/tests/JIT/Directed/shift/int64_r.csproj @@ -3,7 +3,6 @@ 1 - diff --git a/src/tests/JIT/Directed/shift/int64_ro.csproj b/src/tests/JIT/Directed/shift/int64_ro.csproj index 05e46dc88a1e..fadbe0b4460e 100644 --- a/src/tests/JIT/Directed/shift/int64_ro.csproj +++ b/src/tests/JIT/Directed/shift/int64_ro.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Directed/shift/uint16_r.csproj b/src/tests/JIT/Directed/shift/uint16_r.csproj index a7f9bf904b4e..552d2689e20f 100644 --- a/src/tests/JIT/Directed/shift/uint16_r.csproj +++ b/src/tests/JIT/Directed/shift/uint16_r.csproj @@ -3,7 +3,6 @@ 1 - diff --git a/src/tests/JIT/Directed/shift/uint16_ro.csproj b/src/tests/JIT/Directed/shift/uint16_ro.csproj index cb5c10be1036..7ef4960954d4 100644 --- a/src/tests/JIT/Directed/shift/uint16_ro.csproj +++ b/src/tests/JIT/Directed/shift/uint16_ro.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Directed/shift/uint32_r.csproj b/src/tests/JIT/Directed/shift/uint32_r.csproj index e04ab62b5bc7..ec2ef0538bb4 100644 --- a/src/tests/JIT/Directed/shift/uint32_r.csproj +++ b/src/tests/JIT/Directed/shift/uint32_r.csproj @@ -3,7 +3,6 @@ 1 - diff --git a/src/tests/JIT/Directed/shift/uint32_ro.csproj b/src/tests/JIT/Directed/shift/uint32_ro.csproj index adbdf821b4e9..ef4e4250cb82 100644 --- a/src/tests/JIT/Directed/shift/uint32_ro.csproj +++ b/src/tests/JIT/Directed/shift/uint32_ro.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Directed/shift/uint64Opt_r.csproj b/src/tests/JIT/Directed/shift/uint64Opt_r.csproj index d89cc69d91bb..3d2ea3a414c2 100644 --- a/src/tests/JIT/Directed/shift/uint64Opt_r.csproj +++ b/src/tests/JIT/Directed/shift/uint64Opt_r.csproj @@ -3,7 +3,6 @@ 1 - diff --git a/src/tests/JIT/Directed/shift/uint64Opt_ro.csproj b/src/tests/JIT/Directed/shift/uint64Opt_ro.csproj index 4162727d91a9..93b4db588628 100644 --- a/src/tests/JIT/Directed/shift/uint64Opt_ro.csproj +++ b/src/tests/JIT/Directed/shift/uint64Opt_ro.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Directed/shift/uint64_r.csproj b/src/tests/JIT/Directed/shift/uint64_r.csproj index 1234a12964f2..9ebdf9ab56ac 100644 --- a/src/tests/JIT/Directed/shift/uint64_r.csproj +++ b/src/tests/JIT/Directed/shift/uint64_r.csproj @@ -3,7 +3,6 @@ 1 - diff --git a/src/tests/JIT/Directed/shift/uint64_ro.csproj b/src/tests/JIT/Directed/shift/uint64_ro.csproj index 0c831b4cc5a8..7a9c3ce0ffa1 100644 --- a/src/tests/JIT/Directed/shift/uint64_ro.csproj +++ b/src/tests/JIT/Directed/shift/uint64_ro.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Directed/shift/uint8_r.csproj b/src/tests/JIT/Directed/shift/uint8_r.csproj index 31ce989e3993..316cfafa35a2 100644 --- a/src/tests/JIT/Directed/shift/uint8_r.csproj +++ b/src/tests/JIT/Directed/shift/uint8_r.csproj @@ -3,7 +3,6 @@ 1 - diff --git a/src/tests/JIT/Directed/shift/uint8_ro.csproj b/src/tests/JIT/Directed/shift/uint8_ro.csproj index 83b542b20d75..9ea93e3b8a2e 100644 --- a/src/tests/JIT/Directed/shift/uint8_ro.csproj +++ b/src/tests/JIT/Directed/shift/uint8_ro.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Directed/tailcall/mutual_recursion.fsproj b/src/tests/JIT/Directed/tailcall/mutual_recursion.fsproj index 83624287a592..efd544a172ba 100644 --- a/src/tests/JIT/Directed/tailcall/mutual_recursion.fsproj +++ b/src/tests/JIT/Directed/tailcall/mutual_recursion.fsproj @@ -2,10 +2,11 @@ true + + + true - True - True True True $(NetCoreAppToolCurrent) diff --git a/src/tests/JIT/Generics/Constraints/Call_instance01_r.csproj b/src/tests/JIT/Generics/Constraints/Call_instance01_r.csproj index 9816743a8382..a0ad4c2cc6fa 100644 --- a/src/tests/JIT/Generics/Constraints/Call_instance01_r.csproj +++ b/src/tests/JIT/Generics/Constraints/Call_instance01_r.csproj @@ -3,7 +3,6 @@ 1 - diff --git a/src/tests/JIT/Generics/Constraints/Call_instance01_ro.csproj b/src/tests/JIT/Generics/Constraints/Call_instance01_ro.csproj index c0a2e1f042ce..7ba8ec832b27 100644 --- a/src/tests/JIT/Generics/Constraints/Call_instance01_ro.csproj +++ b/src/tests/JIT/Generics/Constraints/Call_instance01_ro.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Generics/Fields/getclassfrommethodparam.csproj b/src/tests/JIT/Generics/Fields/getclassfrommethodparam.csproj index c82afdca25be..5b2d0905f3fb 100644 --- a/src/tests/JIT/Generics/Fields/getclassfrommethodparam.csproj +++ b/src/tests/JIT/Generics/Fields/getclassfrommethodparam.csproj @@ -7,7 +7,6 @@ true - PdbOnly diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs index 125c187bdd2d..d6b561bd0fab 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs @@ -1409,6 +1409,8 @@ public static float CompareTest(float left, float right) public static double Sqrt(double value) => Math.Sqrt(value); + public static long AbsoluteDifference(long op1, long op2) => op1 < op2 ? (long)(op2 - op1) : (long)(op1 - op2); + public static byte AbsoluteDifference(sbyte op1, sbyte op2) => op1 < op2 ? (byte)(op2 - op1) : (byte)(op1 - op2); public static sbyte AbsoluteDifferenceAdd(sbyte op1, sbyte op2, sbyte op3) => (sbyte)(op1 + AbsoluteDifference(op2, op3)); @@ -1427,6 +1429,8 @@ public static float CompareTest(float left, float right) public static ushort AbsoluteDifference(ushort op1, ushort op2) => op1 < op2 ? (ushort)(op2 - op1) : (ushort)(op1 - op2); + public static ulong AbsoluteDifference(ulong op1, ulong op2) => op1 < op2 ? (ulong)(op2 - op1) : (ulong)(op1 - op2); + public static ushort AbsoluteDifferenceAdd(ushort op1, ushort op2, ushort op3) => (ushort)(op1 + AbsoluteDifference(op2, op3)); public static uint AbsoluteDifference(uint op1, uint op2) => op1 < op2 ? (uint)(op2 - op1) : (uint)(op1 - op2); @@ -1443,6 +1447,8 @@ public static float CompareTest(float left, float right) public static short AddAcrossWidening(sbyte[] op1) => Reduce(AddWidening, op1); + public static long AddAcrossWideningLong(sbyte[] op1) => Reduce(AddWidening, op1); + public static short AddPairwiseWidening(sbyte[] op1, int i) => AddWidening(op1[2 * i], op1[2 * i + 1]); public static short AddPairwiseWideningAndAdd(short[] op1, sbyte[] op2, int i) => (short)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); @@ -1469,10 +1475,28 @@ private static sbyte HighNarrowing(short op1, bool round) public static short AddWidening(short op1, sbyte op2) => (short)(op1 + op2); + public static long AddWidening(long op1, sbyte op2) => (long)(op1 + (long)op2); + public static short AddWideningUpper(sbyte[] op1, sbyte[] op2, int i) => AddWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); public static short AddWideningUpper(short[] op1, sbyte[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); + public static sbyte BooleanNot(sbyte value) => (sbyte)(value == 0 ? 1 : 0); + + public static byte BooleanNot(byte value) => (byte)(value == 0 ? 1 : 0); + + public static short BooleanNot(short value) => (short)(value == 0 ? 1 : 0); + + public static ushort BooleanNot(ushort value) => (ushort)(value == 0 ? 1 : 0); + + public static int BooleanNot(int value) => (int)(value == 0 ? 1 : 0); + + public static uint BooleanNot(uint value) => (uint)(value == 0 ? 1 : 0); + + public static long BooleanNot(long value) => (long)(value == 0 ? 1 : 0); + + public static ulong BooleanNot(ulong value) => (ulong)(value == 0 ? 1 : 0); + public static sbyte ExtractNarrowing(short op1) => (sbyte)op1; public static sbyte ExtractNarrowingUpper(sbyte[] op1, short[] op2, int i) => i < op1.Length ? op1[i] : ExtractNarrowing(op2[i - op1.Length]); @@ -1533,6 +1557,18 @@ private static short Reduce(Func reduceOp, sbyte[] op1) return acc; } + private static long Reduce(Func reduceOp, sbyte[] op1) + { + long acc = op1[0]; + + for (int i = 1; i < op1.Length; i++) + { + acc = reduceOp(acc, op1[i]); + } + + return acc; + } + public static uint AbsoluteDifferenceWidening(short op1, short op2) => op1 < op2 ? (uint)(op2 - op1) : (uint)(op1 - op2); public static uint AbsoluteDifferenceWideningUpper(short[] op1, short[] op2, int i) => AbsoluteDifferenceWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); @@ -1543,6 +1579,8 @@ private static short Reduce(Func reduceOp, sbyte[] op1) public static int AddAcrossWidening(short[] op1) => Reduce(AddWidening, op1); + public static long AddAcrossWideningLong(short[] op1) => Reduce(AddWidening, op1); + public static int AddPairwiseWidening(short[] op1, int i) => AddWidening(op1[2 * i], op1[2 * i + 1]); public static int AddPairwiseWideningAndAdd(int[] op1, short[] op2, int i) => (int)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); @@ -1569,6 +1607,8 @@ private static short HighNarrowing(int op1, bool round) public static int AddWidening(int op1, short op2) => (int)(op1 + op2); + public static long AddWidening(long op1, short op2) => (long)(op1 + (long)op2); + public static int AddWideningUpper(short[] op1, short[] op2, int i) => AddWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); public static int AddWideningUpper(int[] op1, short[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); @@ -1633,6 +1673,18 @@ private static int Reduce(Func reduceOp, short[] op1) return acc; } + private static long Reduce(Func reduceOp, short[] op1) + { + long acc = op1[0]; + + for (int i = 1; i < op1.Length; i++) + { + acc = reduceOp(acc, op1[i]); + } + + return acc; + } + public static ulong AbsoluteDifferenceWidening(int op1, int op2) => op1 < op2 ? (ulong)(op2 - op1) : (ulong)(op1 - op2); public static ulong AbsoluteDifferenceWideningUpper(int[] op1, int[] op2, int i) => AbsoluteDifferenceWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); @@ -1701,6 +1753,29 @@ private static int HighNarrowing(long op1, bool round) public static long MultiplyWideningUpperAndSubtract(long[] op1, int[] op2, int[] op3, int i) => MultiplyWideningAndSubtract(op1[i], op2[i + op2.Length / 2], op3[i + op3.Length / 2]); + public static T SignExtend(T n, int numBits, bool zeroExtend) where T : struct, IComparable, IConvertible + { + // Get the underlying integer value + dynamic value = Convert.ChangeType(n, typeof(long)); + + // Mask to extract the lowest numBits + long mask = (1L << numBits) - 1; + long lowestBits = value & mask; + + // Sign extension for signed integers + long signBitMask = 1L << (numBits - 1); + if (!zeroExtend && ((lowestBits & signBitMask) != 0)) + { + // If sign bit is set, it's a negative number + return (T)Convert.ChangeType(-((~lowestBits & mask) + 1), typeof(T)); + } + else + { + // If sign bit is not set, it's a positive number + return (T)Convert.ChangeType(lowestBits, typeof(T)); + } + } + public static int SubtractHighNarrowing(long op1, long op2) => HighNarrowing((long)(op1 - op2), round: false); public static long SubtractHighNarrowingUpper(int[] op1, long[] op2, long[] op3, int i) => i < op1.Length ? op1[i] : SubtractHighNarrowing(op2[i - op1.Length], op3[i - op1.Length]); @@ -1743,6 +1818,8 @@ private static long Reduce(Func reduceOp, int[] op1) public static ushort AddAcrossWidening(byte[] op1) => Reduce(AddWidening, op1); + public static ulong AddAcrossWideningULong(byte[] op1) => Reduce(AddWidening, op1); + public static ushort AddPairwiseWidening(byte[] op1, int i) => AddWidening(op1[2 * i], op1[2 * i + 1]); public static ushort AddPairwiseWideningAndAdd(ushort[] op1, byte[] op2, int i) => (ushort)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); @@ -1769,6 +1846,8 @@ private static byte HighNarrowing(ushort op1, bool round) public static ushort AddWidening(ushort op1, byte op2) => (ushort)(op1 + op2); + public static ulong AddWidening(ulong op1, byte op2) => (ulong)(op1 + (ulong)op2); + public static ushort AddWideningUpper(byte[] op1, byte[] op2, int i) => AddWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); public static ushort AddWideningUpper(ushort[] op1, byte[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); @@ -1833,6 +1912,18 @@ private static ushort Reduce(Func reduceOp, byte[] op1) return acc; } + private static ulong Reduce(Func reduceOp, byte[] op1) + { + ulong acc = op1[0]; + + for (int i = 1; i < op1.Length; i++) + { + acc = reduceOp(acc, op1[i]); + } + + return acc; + } + public static uint AbsoluteDifferenceWidening(ushort op1, ushort op2) => op1 < op2 ? (uint)(op2 - op1) : (uint)(op1 - op2); public static uint AbsoluteDifferenceWideningUpper(ushort[] op1, ushort[] op2, int i) => AbsoluteDifferenceWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); @@ -1843,6 +1934,8 @@ private static ushort Reduce(Func reduceOp, byte[] op1) public static uint AddAcrossWidening(ushort[] op1) => Reduce(AddWidening, op1); + public static ulong AddAcrossWideningULong(ushort[] op1) => Reduce(AddWidening, op1); + public static uint AddPairwiseWidening(ushort[] op1, int i) => AddWidening(op1[2 * i], op1[2 * i + 1]); public static uint AddPairwiseWideningAndAdd(uint[] op1, ushort[] op2, int i) => (uint)(op1[i] + AddWidening(op2[2 * i], op2[2 * i + 1])); @@ -1869,6 +1962,8 @@ private static ushort HighNarrowing(uint op1, bool round) public static uint AddWidening(uint op1, ushort op2) => (uint)(op1 + op2); + public static ulong AddWidening(ulong op1, ushort op2) => (ulong)(op1 + (ulong)op2); + public static uint AddWideningUpper(ushort[] op1, ushort[] op2, int i) => AddWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); public static uint AddWideningUpper(uint[] op1, ushort[] op2, int i) => AddWidening(op1[i], op2[i + op2.Length / 2]); @@ -1933,6 +2028,18 @@ private static uint Reduce(Func reduceOp, ushort[] op1) return acc; } + private static ulong Reduce(Func reduceOp, ushort[] op1) + { + ulong acc = op1[0]; + + for (int i = 1; i < op1.Length; i++) + { + acc = reduceOp(acc, op1[i]); + } + + return acc; + } + public static ulong AbsoluteDifferenceWidening(uint op1, uint op2) => op1 < op2 ? (ulong)(op2 - op1) : (ulong)(op1 - op2); public static ulong AbsoluteDifferenceWideningUpper(uint[] op1, uint[] op2, int i) => AbsoluteDifferenceWidening(op1[i + op1.Length / 2], op2[i + op2.Length / 2]); @@ -2033,6 +2140,9 @@ private static ulong Reduce(Func reduceOp, uint[] op1) return acc; } + public static double AddWidening(double op1, float op2) => (double)(op1 + (double)op2); + + private static bool SignedSatQ(short val, out sbyte result) { bool saturated = false; @@ -5028,10 +5138,16 @@ private static double Pairwise(Func pairOp, double[] op1 public static sbyte AddAcross(sbyte[] op1) => Reduce(Add, op1); + public static sbyte AndAcross(sbyte[] op1) => Reduce(And, op1); + public static sbyte MaxAcross(sbyte[] op1) => Reduce(Max, op1); public static sbyte MinAcross(sbyte[] op1) => Reduce(Min, op1); + public static sbyte OrAcross(sbyte[] op1) => Reduce(Or, op1); + + public static sbyte XorAcross(sbyte[] op1) => Reduce(Xor, op1); + private static sbyte Reduce(Func reduceOp, sbyte[] op1) { sbyte acc = op1[0]; @@ -5046,10 +5162,16 @@ private static sbyte Reduce(Func reduceOp, sbyte[] op1) public static byte AddAcross(byte[] op1) => Reduce(Add, op1); + public static byte AndAcross(byte[] op1) => Reduce(And, op1); + public static byte MaxAcross(byte[] op1) => Reduce(Max, op1); public static byte MinAcross(byte[] op1) => Reduce(Min, op1); + public static byte OrAcross(byte[] op1) => Reduce(Or, op1); + + public static byte XorAcross(byte[] op1) => Reduce(Xor, op1); + private static byte Reduce(Func reduceOp, byte[] op1) { byte acc = op1[0]; @@ -5064,10 +5186,16 @@ private static byte Reduce(Func reduceOp, byte[] op1) public static short AddAcross(short[] op1) => Reduce(Add, op1); + public static short AndAcross(short[] op1) => Reduce(And, op1); + public static short MaxAcross(short[] op1) => Reduce(Max, op1); public static short MinAcross(short[] op1) => Reduce(Min, op1); + public static short OrAcross(short[] op1) => Reduce(Or, op1); + + public static short XorAcross(short[] op1) => Reduce(Xor, op1); + private static short Reduce(Func reduceOp, short[] op1) { short acc = op1[0]; @@ -5082,10 +5210,16 @@ private static short Reduce(Func reduceOp, short[] op1) public static ushort AddAcross(ushort[] op1) => Reduce(Add, op1); + public static ushort AndAcross(ushort[] op1) => Reduce(And, op1); + public static ushort MaxAcross(ushort[] op1) => Reduce(Max, op1); public static ushort MinAcross(ushort[] op1) => Reduce(Min, op1); + public static ushort OrAcross(ushort[] op1) => Reduce(Or, op1); + + public static ushort XorAcross(ushort[] op1) => Reduce(Xor, op1); + private static ushort Reduce(Func reduceOp, ushort[] op1) { ushort acc = op1[0]; @@ -5100,10 +5234,16 @@ private static ushort Reduce(Func reduceOp, ushort[] op1 public static int AddAcross(int[] op1) => Reduce(Add, op1); + public static int AndAcross(int[] op1) => Reduce(And, op1); + public static int MaxAcross(int[] op1) => Reduce(Max, op1); public static int MinAcross(int[] op1) => Reduce(Min, op1); + public static int OrAcross(int[] op1) => Reduce(Or, op1); + + public static int XorAcross(int[] op1) => Reduce(Xor, op1); + private static int Reduce(Func reduceOp, int[] op1) { int acc = op1[0]; @@ -5118,10 +5258,16 @@ private static int Reduce(Func reduceOp, int[] op1) public static uint AddAcross(uint[] op1) => Reduce(Add, op1); + public static uint AndAcross(uint[] op1) => Reduce(And, op1); + public static uint MaxAcross(uint[] op1) => Reduce(Max, op1); public static uint MinAcross(uint[] op1) => Reduce(Min, op1); + public static uint OrAcross(uint[] op1) => Reduce(Or, op1); + + public static uint XorAcross(uint[] op1) => Reduce(Xor, op1); + private static uint Reduce(Func reduceOp, uint[] op1) { uint acc = op1[0]; @@ -5134,6 +5280,54 @@ private static uint Reduce(Func reduceOp, uint[] op1) return acc; } + public static long AddAcross(long[] op1) => Reduce(Add, op1); + + public static long AndAcross(long[] op1) => Reduce(And, op1); + + public static long MaxAcross(long[] op1) => Reduce(Max, op1); + + public static long MinAcross(long[] op1) => Reduce(Min, op1); + + public static long OrAcross(long[] op1) => Reduce(Or, op1); + + public static long XorAcross(long[] op1) => Reduce(Xor, op1); + + private static long Reduce(Func reduceOp, long[] op1) + { + long acc = op1[0]; + + for (int i = 1; i < op1.Length; i++) + { + acc = reduceOp(acc, op1[i]); + } + + return acc; + } + + public static ulong AddAcross(ulong[] op1) => Reduce(Add, op1); + + public static ulong AndAcross(ulong[] op1) => Reduce(And, op1); + + public static ulong MaxAcross(ulong[] op1) => Reduce(Max, op1); + + public static ulong MinAcross(ulong[] op1) => Reduce(Min, op1); + + public static ulong OrAcross(ulong[] op1) => Reduce(Or, op1); + + public static ulong XorAcross(ulong[] op1) => Reduce(Xor, op1); + + private static ulong Reduce(Func reduceOp, ulong[] op1) + { + ulong acc = op1[0]; + + for (int i = 1; i < op1.Length; i++) + { + acc = reduceOp(acc, op1[i]); + } + + return acc; + } + public static float AddAcross(float[] op1) => Reduce(Add, op1); public static float MaxAcross(float[] op1) => Reduce(Max, op1); @@ -5152,6 +5346,31 @@ private static float Reduce(Func reduceOp, float[] op1) return acc; } + public static float AddAcrossRecursivePairwise(float[] op1) => ReduceRecursivePairwise(Add, op1); + + private static float ReduceRecursivePairwise(Func reduceOp, float[] op1) + { + if (op1.Length == 2) + { + return reduceOp(op1[0], op1[1]); + } + + if (op1.Length % 2 != 0) + { + return float.NaN; + } + + float[] l = new float[op1.Length / 2]; + Array.Copy(op1, 0, l, 0, (op1.Length / 2)); + float l_reduced = ReduceRecursivePairwise(reduceOp, l); + + float[] r = new float[op1.Length / 2]; + Array.Copy(op1, (op1.Length / 2), r, 0, (op1.Length / 2)); + float r_reduced = ReduceRecursivePairwise(reduceOp, r); + + return reduceOp(l_reduced, r_reduced); + } + public static double AddAcross(double[] op1) => Reduce(Add, op1); public static double MaxAcross(double[] op1) => Reduce(Max, op1); @@ -5170,6 +5389,31 @@ private static double Reduce(Func reduceOp, double[] op1 return acc; } + public static double AddAcrossRecursivePairwise(double[] op1) => ReduceRecursivePairwise(Add, op1); + + private static double ReduceRecursivePairwise(Func reduceOp, double[] op1) + { + if (op1.Length == 2) + { + return reduceOp(op1[0], op1[1]); + } + + if (op1.Length % 2 != 0) + { + return double.NaN; + } + + double[] l = new double[op1.Length / 2]; + Array.Copy(op1, 0, l, 0, (op1.Length / 2)); + double l_reduced = ReduceRecursivePairwise(reduceOp, l); + + double[] r = new double[op1.Length / 2]; + Array.Copy(op1, (op1.Length / 2), r, 0, (op1.Length / 2)); + double r_reduced = ReduceRecursivePairwise(reduceOp, r); + + return reduceOp(l_reduced, r_reduced); + } + public static float MaxNumberAcross(float[] op1) => Reduce(MaxNumber, op1); public static float MinNumberAcross(float[] op1) => Reduce(MinNumber, op1); @@ -5986,5 +6230,69 @@ public static int DotProduct(int op1, sbyte[] op2, int s, sbyte[] op3, int t) return result; } + + public static ulong DotProduct(ulong op1, ushort[] op2, int s, ushort[] op3, int t) + { + ulong result = op1; + + for (int i = 0; i < 4; i++) + { + result += (ulong)((ulong)op2[s + i] * (ulong)op3[t + i]); + } + + return result; + } + + public static long DotProduct(long op1, short[] op2, int s, short[] op3, int t) + { + long result = op1; + + for (int i = 0; i < 4; i++) + { + result += (long)((long)op2[s + i] * (long)op3[t + i]); + } + + return result; + } + + public static int WhileLessThanMask(int op1, int op2) + { + return (op1 < op2) ? 1 : 0; + } + + public static uint WhileLessThanMask(uint op1, uint op2) + { + return (uint)((op1 < op2) ? 1 : 0); + } + + public static long WhileLessThanMask(long op1, long op2) + { + return (op1 < op2) ? 1 : 0; + } + + public static ulong WhileLessThanMask(ulong op1, ulong op2) + { + return (ulong)((op1 < op2) ? 1 : 0); + } + + public static int WhileLessThanOrEqualMask(int op1, int op2) + { + return (op1 <= op2) ? 1 : 0; + } + + public static uint WhileLessThanOrEqualMask(uint op1, uint op2) + { + return (uint)((op1 <= op2) ? 1 : 0); + } + + public static long WhileLessThanOrEqualMask(long op1, long op2) + { + return (op1 <= op2) ? 1 : 0; + } + + public static ulong WhileLessThanOrEqualMask(ulong op1, ulong op2) + { + return (ulong)((op1 <= op2) ? 1 : 0); + } } } diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/ScalarBinOpRetVecTest.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/ScalarBinOpRetVecTest.template new file mode 100644 index 000000000000..a2434756fae8 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/ScalarBinOpRetVecTest.template @@ -0,0 +1,216 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new ScalarBinaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.ReadUnaligned + test.RunBasicScenario_UnsafeRead(); + + // Validates calling via reflection works, using Unsafe.ReadUnaligned + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.ReadUnaligned + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ScalarBinaryOpTest__{TestName} + { + private struct TestStruct + { + public {Op1BaseType} _fld1; + public {Op2BaseType} _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + testStruct._fld1 = {NextValueOp1}; + testStruct._fld2 = {NextValueOp2}; + + return testStruct; + } + + public void RunStructFldScenario(ScalarBinaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2); + testClass.ValidateResult(_fld1, _fld2, result); + } + } + + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType} _data1; + private static {Op2BaseType} _data2; + + private {Op1BaseType} _fld1; + private {Op2BaseType} _fld2; + + public ScalarBinaryOpTest__{TestName}() + { + Succeeded = true; + + _fld1 = {NextValueOp1}; + _fld2 = {NextValueOp2}; + + _data1 = {NextValueOp1}; + _data2 = {NextValueOp2}; + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1)), + Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2)) + ); + + ValidateResult(_data1, _data2, result); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1BaseType}), typeof({Op2BaseType}) }) + .Invoke(null, new object[] { + Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1)), + Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2)) + }); + + ValidateResult(_data1, _data2, ({RetVectorType}<{RetBaseType}>)result); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var data1 = Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1)); + var data2 = Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2)); + var result = {Isa}.{Method}(data1, data2); + + ValidateResult(data1, data2, result); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2); + ValidateResult(_fld1, _fld2, result); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2); + + ValidateResult(test._fld1, test._fld2, result); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1BaseType} left, {Op2BaseType} right, {RetVectorType}<{RetBaseType}> result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (int i = 0; i < RetElementCount; i++) + { + if ({ValidateIterResult}) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetVectorType}<{RetBaseType}>>({Op1BaseType}, {Op2BaseType}): {Method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: {left}"); + TestLibrary.TestFramework.LogInformation($" right: {right}"); + TestLibrary.TestFramework.LogInformation($" result: {result}"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/ScalarUnOpTest.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/ScalarUnOpTest.template index c6fe68908e56..f057ad4a8186 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/ScalarUnOpTest.template +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/ScalarUnOpTest.template @@ -9,6 +9,7 @@ ******************************************************************************/ using System; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveConditionalSelect.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveConditionalSelect.template new file mode 100644 index 000000000000..963fa1713eec --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveConditionalSelect.template @@ -0,0 +1,362 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using System.Numerics; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new TernaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class TernaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] inArray3; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle inHandle3; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op2BaseType}[] inArray2, {Op3BaseType}[] inArray3, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op2BaseType}>(); + int sizeOfinArray3 = inArray3.Length * Unsafe.SizeOf<{Op3BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfinArray3 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException($"Invalid value of alignment: {alignment}, sizeOfinArray1: {sizeOfinArray1}, sizeOfinArray2: {sizeOfinArray2}, sizeOfinArray3: {sizeOfinArray3}, sizeOfoutArray: {sizeOfoutArray}"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.inArray3 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.inHandle3 = GCHandle.Alloc(this.inArray3, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray3Ptr), ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), (uint)sizeOfinArray3); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray3Ptr => Align((byte*)(inHandle3.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + inHandle3.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op2VectorType}<{Op2BaseType}> _fld2; + public {Op3VectorType}<{Op3BaseType}> _fld3; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3VectorType}<{Op3BaseType}>, byte>(ref testStruct._fld3), ref Unsafe.As<{Op3BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario(TernaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2, _fld3); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op2ElementCount = Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>() / sizeof({Op2BaseType}); + private static readonly int Op3ElementCount = Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>() / sizeof({Op3BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + private static {Op3BaseType}[] _data3 = new {Op3BaseType}[Op3ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op2VectorType}<{Op2BaseType}> _fld2; + private {Op3VectorType}<{Op3BaseType}> _fld3; + + private DataTable _dataTable; + + public TernaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3VectorType}<{Op3BaseType}>, byte>(ref _fld3), ref Unsafe.As<{Op3BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + _dataTable = new DataTable(_data1, _data2, _data3, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op3VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + //TODO-SVE: Once register allocation exists for predicates, move loadMask into DataTable + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{RetBaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(loadMask, ({Op2BaseType}*)(_dataTable.inArray2Ptr)), + {LoadIsa}.Load{Op3VectorType}(loadMask, ({Op3BaseType}*)(_dataTable.inArray3Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op2VectorType}<{Op2BaseType}>), typeof({Op3VectorType}<{Op3BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op3VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var op3 = Unsafe.Read<{Op3VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr); + var result = {Isa}.{Method}(op1, op2, op3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2, _fld3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2, test._fld3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, {Op3VectorType}<{Op3BaseType}> op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] inArray3 = new {Op3BaseType}[Op3ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), op3); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] inArray3 = new {Op3BaseType}[Op3ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), ref Unsafe.AsRef(op3), (uint)Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {Op2BaseType}[] secondOp, {Op3BaseType}[] thirdOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if ({ValidateIterResult}) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op2VectorType}<{Op2BaseType}>, {Op3VectorType}<{Op3BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveCreateTrueMaskTest.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveCreateTrueMaskTest.template new file mode 100644 index 000000000000..6c88cd1fb2ec --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveCreateTrueMaskTest.template @@ -0,0 +1,230 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Numerics; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new CreateTrueMaskTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario_CreateTrueMask(); + + // Validates calling via reflection works + test.RunReflectionScenario_CreateTrueMask(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class CreateTrueMaskTest__{TestName} + { + private static int FloorPow2(int x) + { + if (x <= 0) + { + throw new Exception("Expected a positive argument value."); + } + + int result = 1; + + for (x = x / 2; x > 0; x /= 2) + { + result <<= 1; + } + + return result; + } + + // Decode a pattern specifier into a predicate constraint. + + private static int DecodePredCount({Op1Type} bitpattern, int esize) + { + if (bitpattern > {Op1Type}.All) + { + throw new Exception("Bit patterns must be 5 bits long."); + } + + switch (esize) { + case 8: + case 16: + case 32: + case 64: + break; + default: + throw new Exception("Incorrect esize"); + } + + int elements = (int)(Sve.Count8BitElements()) * 8 / esize; + switch (bitpattern) + { + case {Op1Type}.LargestPowerOf2: + return FloorPow2(elements); + case {Op1Type}.VectorCount1: + return elements >= 1 ? 1 : 0; + case {Op1Type}.VectorCount2: + return elements >= 2 ? 2 : 0; + case {Op1Type}.VectorCount3: + return elements >= 3 ? 3 : 0; + case {Op1Type}.VectorCount4: + return elements >= 4 ? 4 : 0; + case {Op1Type}.VectorCount5: + return elements >= 5 ? 5 : 0; + case {Op1Type}.VectorCount6: + return elements >= 6 ? 6 : 0; + case {Op1Type}.VectorCount7: + return elements >= 7 ? 7 : 0; + case {Op1Type}.VectorCount8: + return elements >= 8 ? 8 : 0; + case {Op1Type}.VectorCount16: + return elements >= 16 ? 16 : 0; + case {Op1Type}.VectorCount32: + return elements >= 32 ? 32 : 0; + case {Op1Type}.VectorCount64: + return elements >= 64 ? 64 : 0; + case {Op1Type}.VectorCount128: + return elements >= 128 ? 128 : 0; + case {Op1Type}.VectorCount256: + return elements >= 256 ? 256 : 0; + case {Op1Type}.LargestMultipleOf4: + return elements - (elements % 4); + case {Op1Type}.LargestMultipleOf3: + return elements - (elements % 3); + case {Op1Type}.All: + return elements; + default: + return 0; + } + + throw new Exception("Should be unreachable."); + return 0; + } + + // Calculate the expected result of a PTRUE instruction. + + private static {RetVectorType}<{RetBaseType}> PtrueOp({Op1Type} bitpattern, int esize) + { + int VL = (int)(Sve.Count8BitElements()) * 8; + int PL = VL / 8; + int elements = VL / esize; + int count = DecodePredCount(bitpattern, esize); + // {RetVectorType}<{RetBaseType}> result = {RetVectorType}<{RetBaseType}>.Zero; + int psize = esize / 8; + + {RetBaseType}[] elemArray = new {RetBaseType}[elements]; + for (int e = 0; e < elements; e++) + { + if (typeof({RetBaseType}) == typeof(Single)) + { + elemArray[e] = Unsafe.BitCast(e < count ? 1 : 0); + } + else if (typeof({RetBaseType}) == typeof(Double)) + { + elemArray[e] = Unsafe.BitCast(e < count ? 1 : 0); + } + else + { + elemArray[e] = ({RetBaseType})(e < count ? 1 : 0); + } + } + + return new {RetVectorType}<{RetBaseType}>(elemArray); + } + + public CreateTrueMaskTest__{TestName}() + { + Succeeded = true; + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_CreateTrueMask() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_CreateTrueMask)); + + for ({Op1Type} pattern = {Op1Type}.LargestPowerOf2; pattern <= {Op1Type}.All ; pattern++) + { + var result = {Isa}.{Method}(pattern); + + ValidateResult(pattern, result); + } + } + + public void RunReflectionScenario_CreateTrueMask() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_CreateTrueMask)); + + for ({Op1Type} pattern = {Op1Type}.LargestPowerOf2; pattern <= {Op1Type}.All ; pattern++) + { + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1Type}) }) + .Invoke(null, new object[] { + pattern + }); + + ValidateResult(pattern, ({RetVectorType}<{RetBaseType}>)(result)); + } + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_CreateTrueMask(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult({Op1Type} pattern, {RetVectorType}<{RetBaseType}> result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {RetVectorType}<{RetBaseType}> expected = PtrueOp(pattern, sizeof({RetBaseType}) * 8); + if (!Vector.EqualsAll(expected, result)) + { + succeeded = false; + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({pattern}): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation($" expected: ({string.Join(", ", expected)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveLoadMaskedUnOpTest.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveLoadMaskedUnOpTest.template index 09aaf2f442e1..d5a62e5cda1c 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveLoadMaskedUnOpTest.template +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveLoadMaskedUnOpTest.template @@ -64,9 +64,9 @@ namespace JIT.HardwareIntrinsics.Arm { int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op2BaseType}>(); int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); - if ((alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) { - throw new ArgumentException("Invalid value of alignment"); + throw new ArgumentException($"Invalid value of alignment: {alignment}, sizeOfinArray1: {sizeOfinArray1}, sizeOfoutArray: {sizeOfoutArray}"); } this.inArray1 = new byte[alignment * 2]; diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveSimpleNoOpTest.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveSimpleNoOpTest.template new file mode 100644 index 000000000000..6ad3242c1b76 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/SveSimpleNoOpTest.template @@ -0,0 +1,114 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Numerics; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new CreateFalseMaskTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works + test.RunBasicScenario_CreateFalseMask(); + + // Validates calling via reflection works + test.RunReflectionScenario_CreateFalseMask(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class CreateFalseMaskTest__{TestName} + { + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + public CreateFalseMaskTest__{TestName}() + { + Succeeded = true; + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_CreateFalseMask() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_CreateFalseMask)); + + var result = {Isa}.{Method}(); + + ValidateResult(result); + } + + public void RunReflectionScenario_CreateFalseMask() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_CreateFalseMask)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { }) + .Invoke(null, new object[] {}); + + ValidateResult(({RetVectorType}<{RetBaseType}>)(result)); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + Succeeded = false; + + try + { + RunBasicScenario_CreateFalseMask(); + } + catch (PlatformNotSupportedException) + { + Succeeded = true; + } + } + + private void ValidateResult({RetVectorType}<{RetBaseType}> result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + for (var i = 0; i < RetElementCount; i++) + { + if ({ValidateIterResult}) + { + succeeded = false; + break; + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>(): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_BinaryOp_SveTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_BinaryOp_SveTestTemplate.template new file mode 100644 index 000000000000..9e2c2c7516c2 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_BinaryOp_SveTestTemplate.template @@ -0,0 +1,327 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new {TemplateName}BinaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}BinaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op2BaseType}[] inArray2, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op2BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op2VectorType}<{Op2BaseType}> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}BinaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op2ElementCount = Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>() / sizeof({Op2BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op2VectorType}<{Op2BaseType}> _fld2; + + private DataTable _dataTable; + + public {TemplateName}BinaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + _dataTable = new DataTable(_data1, _data2, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + Vector<{Op1BaseType}> loadMask = Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(loadMask, ({Op2BaseType}*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op2VectorType}<{Op2BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var result = {Isa}.{Method}(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] left, {Op2BaseType}[] right, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op2VectorType}<{Op2BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveBinaryOpTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveBinaryOpTestTemplate.template new file mode 100644 index 000000000000..bd15acab428a --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveBinaryOpTestTemplate.template @@ -0,0 +1,435 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new {TemplateName}BinaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + // Validates executing the test inside conditional, with op1 as falseValue + test.ConditionalSelect_Op1(); + + // Validates executing the test inside conditional, with op2 as falseValue + test.ConditionalSelect_Op2(); + + // Validates executing the test inside conditional, with op3 as falseValue + test.ConditionalSelect_FalseOp(); + + // Validates executing the test inside conditional, with op3 as zero + test.ConditionalSelect_ZeroOp(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}BinaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op2BaseType}[] inArray2, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op2BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException($"Invalid value of alignment: {alignment}, sizeOfinArray1: {sizeOfinArray1}, sizeOfinArray2: {sizeOfinArray2}, sizeOfoutArray: {sizeOfoutArray}"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op2VectorType}<{Op2BaseType}> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}BinaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op2ElementCount = Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>() / sizeof({Op2BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _maskData = new {Op1BaseType}[Op1ElementCount]; + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _mask; + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op2VectorType}<{Op2BaseType}> _fld2; + private {Op2VectorType}<{Op2BaseType}> _falseFld; + + private DataTable _dataTable; + + public {TemplateName}BinaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _maskData[i] = ({Op1BaseType})({NextValueOp1} % 2); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _mask), ref Unsafe.As<{Op1BaseType}, byte>(ref _maskData[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _falseFld), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + _dataTable = new DataTable(_data1, _data2, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{RetBaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(loadMask, ({Op2BaseType}*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op2VectorType}<{Op2BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var result = {Isa}.{Method}(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void ConditionalSelect_Op1() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld1); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld1); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld1); + } + + public void ConditionalSelect_Op2() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld2); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld2); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld2); + } + + public void ConditionalSelect_FalseOp() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _falseFld); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _falseFld); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _falseFld); + } + + public void ConditionalSelect_ZeroOp() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, {Op1VectorType}<{Op1BaseType}>.Zero); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, {Op1VectorType}<{Op1BaseType}>.Zero); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, {Op1VectorType}<{Op1BaseType}>.Zero); + } + + [method: MethodImpl(MethodImplOptions.AggressiveInlining)] + private void ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}> mask, {Op1VectorType}<{Op1BaseType}> op1, {Op1VectorType}<{Op1BaseType}> op2, {Op1VectorType}<{Op1BaseType}> falseOp) + { + var result = Sve.ConditionalSelect(mask, {Isa}.{Method}(op1, op2), falseOp); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateConditionalSelectResult(mask, op1, op2, falseOp, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateConditionalSelectResult({Op1VectorType}<{Op1BaseType}> maskOp, {Op1VectorType}<{Op1BaseType}> leftOp, {Op1VectorType}<{Op1BaseType}> rightOp, {Op1VectorType}<{Op1BaseType}> falseOp, void* output, [CallerMemberName] string method = "") + { + {Op1BaseType}[] mask = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] left = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] right = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] falseVal = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] result = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref mask[0]), maskOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref left[0]), leftOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref right[0]), rightOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref falseVal[0]), falseOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref result[0]), ref Unsafe.AsRef(output), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + bool succeeded = true; + + {TemplateValidationLogicForCndSel} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op2VectorType}<{Op2BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" mask: ({string.Join(", ", mask)})"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" falseOp: ({string.Join(", ", falseVal)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] left, {Op2BaseType}[] right, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op2VectorType}<{Op2BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveImmBinaryOpTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveImmBinaryOpTestTemplate.template new file mode 100644 index 000000000000..e891aa8a1810 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveImmBinaryOpTestTemplate.template @@ -0,0 +1,415 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new {TemplateName}BinaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + // Validates executing the test inside conditional, with op1 as falseValue + test.ConditionalSelect_Op1(); + // Validates executing the test inside conditional, with op2 as falseValue + test.ConditionalSelect_Op2(); + // Validates executing the test inside conditional, with op3 as falseValue + test.ConditionalSelect_FalseOp(); + // Validates executing the test inside conditional, with op3 as zero + test.ConditionalSelect_ZeroOp(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}BinaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op1BaseType}[] inArray2, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op1VectorType}<{Op1BaseType}> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data2[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op1BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}BinaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2, {Imm}); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + private static readonly byte Imm = {Imm}; + + private static {Op1BaseType}[] _maskData = new {Op1BaseType}[Op1ElementCount]; + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op1BaseType}[] _data2 = new {Op1BaseType}[Op1ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _mask; + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op1VectorType}<{Op1BaseType}> _fld2; + private {Op1VectorType}<{Op1BaseType}> _falseFld; + + private DataTable _dataTable; + + public {TemplateName}BinaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _maskData[i] = ({Op1BaseType})({NextValueOp1} % 2); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _mask), ref Unsafe.As<{Op1BaseType}, byte>(ref _maskData[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data2[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op1BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _falseFld), ref Unsafe.As<{Op1BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op1ElementCount; i++) { _data2[i] = {NextValueOp1}; } + _dataTable = new DataTable(_data1, _data2, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray2Ptr), + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{RetBaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray2Ptr)), + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op1VectorType}<{Op1BaseType}>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray2Ptr), + (byte){Imm} + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray2Ptr); + var result = {Isa}.{Method}(op1, op2, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + public void ConditionalSelect_Op1() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld1); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld1); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld1); + } + public void ConditionalSelect_Op2() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld2); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld2); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld2); + } + + public void ConditionalSelect_FalseOp() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _falseFld); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _falseFld); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _falseFld); + } + public void ConditionalSelect_ZeroOp() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, {Op1VectorType}<{Op1BaseType}>.Zero); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, {Op1VectorType}<{Op1BaseType}>.Zero); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, {Op1VectorType}<{Op1BaseType}>.Zero); + } + [method: MethodImpl(MethodImplOptions.AggressiveInlining)] + private void ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}> mask, {Op1VectorType}<{Op1BaseType}> op1, {Op1VectorType}<{Op1BaseType}> op2, {Op1VectorType}<{Op1BaseType}> falseOp) + { + var result = Sve.ConditionalSelect(mask, {Isa}.{Method}(op1, op2, Imm), falseOp); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateConditionalSelectResult(mask, op1, op2, falseOp, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + private void ValidateConditionalSelectResult({Op1VectorType}<{Op1BaseType}> maskOp, {Op1VectorType}<{Op1BaseType}> firstOp, {Op1VectorType}<{Op1BaseType}> secondOp, {Op1VectorType}<{Op1BaseType}> falseOp, void* output, [CallerMemberName] string method = "") + { + {Op1BaseType}[] mask = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] first = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] second = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] falseVal = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] result = new {RetBaseType}[RetElementCount]; + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref mask[0]), maskOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref first[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref second[0]), secondOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref falseVal[0]), falseOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref result[0]), ref Unsafe.AsRef(output), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + bool succeeded = true; + {TemplateValidationLogicForCndSel} + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" mask: ({string.Join(", ", mask)})"); + TestLibrary.TestFramework.LogInformation($" first: ({string.Join(", ", first)})"); + TestLibrary.TestFramework.LogInformation($" second: ({string.Join(", ", second)})"); + TestLibrary.TestFramework.LogInformation($" falseOp: ({string.Join(", ", falseVal)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op1VectorType}<{Op1BaseType}> op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] inArray2 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] inArray2 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {Op1BaseType}[] secondOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveImmTernOpFirstArgTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveImmTernOpFirstArgTestTemplate.template new file mode 100644 index 000000000000..186cb5279acb --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveImmTernOpFirstArgTestTemplate.template @@ -0,0 +1,436 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new {TemplateName}TernaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + // Validates executing the test inside conditional, with op1 as falseValue + test.ConditionalSelect_Op1(); + // Validates executing the test inside conditional, with op3 as falseValue + test.ConditionalSelect_FalseOp(); + // Validates executing the test inside conditional, with op3 as zero + test.ConditionalSelect_ZeroOp(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}TernaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] inArray3; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle inHandle3; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op2BaseType}[] inArray2, {Op3BaseType}[] inArray3, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op2BaseType}>(); + int sizeOfinArray3 = inArray3.Length * Unsafe.SizeOf<{Op3BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfinArray3 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.inArray3 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.inHandle3 = GCHandle.Alloc(this.inArray3, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray3Ptr), ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), (uint)sizeOfinArray3); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray3Ptr => Align((byte*)(inHandle3.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + inHandle3.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op1VectorType}<{Op2BaseType}> _fld2; + public {Op1VectorType}<{Op3BaseType}> _fld3; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op2BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op3BaseType}>, byte>(ref testStruct._fld3), ref Unsafe.As<{Op3BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}TernaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2, _fld3, {Imm}); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op2ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op2BaseType}>>() / sizeof({Op2BaseType}); + private static readonly int Op3ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op3BaseType}>>() / sizeof({Op3BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + private static readonly byte Imm = {Imm}; + + private static {Op1BaseType}[] _maskData = new {Op1BaseType}[Op1ElementCount]; + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + private static {Op3BaseType}[] _data3 = new {Op3BaseType}[Op3ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _mask; + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op1VectorType}<{Op2BaseType}> _fld2; + private {Op1VectorType}<{Op3BaseType}> _fld3; + private {Op1VectorType}<{Op1BaseType}> _falseFld; + + private DataTable _dataTable; + + public {TemplateName}TernaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _maskData[i] = ({Op1BaseType})({NextValueOp1} % 2); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _mask), ref Unsafe.As<{Op1BaseType}, byte>(ref _maskData[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op2BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op2BaseType}>>()); + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op3BaseType}>, byte>(ref _fld3), ref Unsafe.As<{Op3BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op3BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _falseFld), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + _dataTable = new DataTable(_data1, _data2, _data3, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op1VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op1VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr), + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + {Op1VectorType}<{Op1BaseType}> loadMask1 = Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All); + {Op1VectorType}<{Op2BaseType}> loadMask2 = Sve.CreateTrueMask{Op2BaseType}(SveMaskPattern.All); + {Op1VectorType}<{Op3BaseType}> loadMask3 = Sve.CreateTrueMask{Op3BaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask1, ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op1VectorType}(loadMask2, ({Op2BaseType}*)(_dataTable.inArray2Ptr)), + {LoadIsa}.Load{Op1VectorType}(loadMask3, ({Op3BaseType}*)(_dataTable.inArray3Ptr)), + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op1VectorType}<{Op2BaseType}>), typeof({Op1VectorType}<{Op3BaseType}>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op1VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op1VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr), + (byte){Imm} + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op1VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var op3 = Unsafe.Read<{Op1VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr); + var result = {Isa}.{Method}(op1, op2, op3, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2, _fld3, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2, test._fld3, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + public void ConditionalSelect_Op1() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, _fld1); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, _fld1); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, _fld1); + } + + public void ConditionalSelect_FalseOp() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, _falseFld); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, _falseFld); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, _falseFld); + } + public void ConditionalSelect_ZeroOp() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, {Op1VectorType}<{Op1BaseType}>.Zero); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, {Op1VectorType}<{Op1BaseType}>.Zero); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, {Op1VectorType}<{Op1BaseType}>.Zero); + } + [method: MethodImpl(MethodImplOptions.AggressiveInlining)] + private void ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}> mask, {Op1VectorType}<{Op1BaseType}> op1, {Op1VectorType}<{Op2BaseType}> op2, {Op1VectorType}<{Op3BaseType}> op3, {Op1VectorType}<{Op1BaseType}> falseOp) + { + var result = Sve.ConditionalSelect(mask, {Isa}.{Method}(op1, op2, op3, Imm), falseOp); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateConditionalSelectResult(mask, op1, op2, op3, falseOp, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + private void ValidateConditionalSelectResult({Op1VectorType}<{Op1BaseType}> maskOp, {Op1VectorType}<{Op1BaseType}> firstOp, {Op1VectorType}<{Op2BaseType}> secondOp, {Op1VectorType}<{Op3BaseType}> thirdOp, {Op1VectorType}<{Op1BaseType}> falseOp, void* output, [CallerMemberName] string method = "") + { + {Op1BaseType}[] mask = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] first = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] second = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] third = new {Op3BaseType}[Op3ElementCount]; + {Op1BaseType}[] falseVal = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] result = new {RetBaseType}[RetElementCount]; + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref mask[0]), maskOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref first[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref second[0]), secondOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref third[0]), thirdOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref falseVal[0]), falseOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref result[0]), ref Unsafe.AsRef(output), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + bool succeeded = true; + {TemplateValidationLogicForCndSel} + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op2BaseType}>, {Op1VectorType}<{Op3BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" mask: ({string.Join(", ", mask)})"); + TestLibrary.TestFramework.LogInformation($" first: ({string.Join(", ", first)})"); + TestLibrary.TestFramework.LogInformation($" second: ({string.Join(", ", second)})"); + TestLibrary.TestFramework.LogInformation($" third: ({string.Join(", ", third)})"); + TestLibrary.TestFramework.LogInformation($" falseOp: ({string.Join(", ", falseVal)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op1VectorType}<{Op2BaseType}> op2, {Op1VectorType}<{Op3BaseType}> op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] inArray3 = new {Op3BaseType}[Op3ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), op3); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] inArray3 = new {Op3BaseType}[Op3ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), ref Unsafe.AsRef(op3), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op3BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] first, {Op2BaseType}[] second, {Op3BaseType}[] third, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", first)})"); + TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", second)})"); + TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", third)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveImmTernOpTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveImmTernOpTestTemplate.template new file mode 100644 index 000000000000..3378f32c9a95 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveImmTernOpTestTemplate.template @@ -0,0 +1,453 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new {TemplateName}TernaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + // Validates executing the test inside conditional, with op1 as falseValue + test.ConditionalSelect_Op1(); + // Validates executing the test inside conditional, with op2 as falseValue + test.ConditionalSelect_Op2(); + // Validates executing the test inside conditional, with op3 as falseValue + test.ConditionalSelect_Op3(); + // Validates executing the test inside conditional, with op3 as falseValue + test.ConditionalSelect_FalseOp(); + // Validates executing the test inside conditional, with op3 as zero + test.ConditionalSelect_ZeroOp(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}TernaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] inArray3; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle inHandle3; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op1BaseType}[] inArray2, {Op1BaseType}[] inArray3, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray3 = inArray3.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfinArray3 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.inArray3 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.inHandle3 = GCHandle.Alloc(this.inArray3, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray3Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray3[0]), (uint)sizeOfinArray3); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray3Ptr => Align((byte*)(inHandle3.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + inHandle3.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op1VectorType}<{Op1BaseType}> _fld2; + public {Op1VectorType}<{Op1BaseType}> _fld3; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op1BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld3), ref Unsafe.As<{Op1BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}TernaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2, _fld3, {Imm}); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + private static readonly byte Imm = {Imm}; + + private static {Op1BaseType}[] _maskData = new {Op1BaseType}[Op1ElementCount]; + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op1BaseType}[] _data2 = new {Op1BaseType}[Op1ElementCount]; + private static {Op1BaseType}[] _data3 = new {Op1BaseType}[Op1ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _mask; + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op1VectorType}<{Op1BaseType}> _fld2; + private {Op1VectorType}<{Op1BaseType}> _fld3; + private {Op1VectorType}<{Op1BaseType}> _falseFld; + + private DataTable _dataTable; + + public {TemplateName}TernaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _maskData[i] = ({Op1BaseType})({NextValueOp1} % 2); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _mask), ref Unsafe.As<{Op1BaseType}, byte>(ref _maskData[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op1BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld3), ref Unsafe.As<{Op1BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _falseFld), ref Unsafe.As<{Op1BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op1ElementCount; i++) { _data2[i] = {NextValueOp2}; } + for (var i = 0; i < Op1ElementCount; i++) { _data3[i] = {NextValueOp3}; } + _dataTable = new DataTable(_data1, _data2, _data3, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray3Ptr), + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{RetBaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray2Ptr)), + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray3Ptr)), + {Imm} + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op1VectorType}<{Op1BaseType}>), typeof(byte) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray3Ptr), + (byte){Imm} + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray2Ptr); + var op3 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray3Ptr); + var result = {Isa}.{Method}(op1, op2, op3, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2, _fld3, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2, test._fld3, {Imm}); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + public void ConditionalSelect_Op1() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, _fld1); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, _fld1); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, _fld1); + } + public void ConditionalSelect_Op2() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, _fld2); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, _fld2); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, _fld2); + } + public void ConditionalSelect_Op3() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op3_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, _fld3); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op3_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, _fld3); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op3_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, _fld3); + } + public void ConditionalSelect_FalseOp() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, _falseFld); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, _falseFld); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, _falseFld); + } + public void ConditionalSelect_ZeroOp() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, {Op1VectorType}<{Op1BaseType}>.Zero); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, {Op1VectorType}<{Op1BaseType}>.Zero); + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, {Op1VectorType}<{Op1BaseType}>.Zero); + } + [method: MethodImpl(MethodImplOptions.AggressiveInlining)] + private void ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}> mask, {Op1VectorType}<{Op1BaseType}> op1, {Op1VectorType}<{Op1BaseType}> op2, {Op1VectorType}<{Op1BaseType}> op3, {Op1VectorType}<{Op1BaseType}> falseOp) + { + var result = Sve.ConditionalSelect(mask, {Isa}.{Method}(op1, op2, op3, Imm), falseOp); + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateConditionalSelectResult(mask, op1, op2, op3, falseOp, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + private void ValidateConditionalSelectResult({Op1VectorType}<{Op1BaseType}> maskOp, {Op1VectorType}<{Op1BaseType}> firstOp, {Op1VectorType}<{Op1BaseType}> secondOp, {Op1VectorType}<{Op1BaseType}> thirdOp, {Op1VectorType}<{Op1BaseType}> falseOp, void* output, [CallerMemberName] string method = "") + { + {Op1BaseType}[] mask = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] first = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] second = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] third = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] falseVal = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] result = new {RetBaseType}[RetElementCount]; + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref mask[0]), maskOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref first[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref second[0]), secondOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref third[0]), thirdOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref falseVal[0]), falseOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref result[0]), ref Unsafe.AsRef(output), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + bool succeeded = true; + {TemplateValidationLogicForCndSel} + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" mask: ({string.Join(", ", mask)})"); + TestLibrary.TestFramework.LogInformation($" first: ({string.Join(", ", first)})"); + TestLibrary.TestFramework.LogInformation($" second: ({string.Join(", ", second)})"); + TestLibrary.TestFramework.LogInformation($" third: ({string.Join(", ", third)})"); + TestLibrary.TestFramework.LogInformation($" falseOp: ({string.Join(", ", falseVal)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op1VectorType}<{Op1BaseType}> op2, {Op1VectorType}<{Op1BaseType}> op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] inArray2 = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] inArray3 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray3[0]), op3); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] inArray2 = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] inArray3 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray3[0]), ref Unsafe.AsRef(op3), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {Op1BaseType}[] secondOp, {Op1BaseType}[] thirdOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveMinimalUnaryOpTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveMinimalUnaryOpTestTemplate.template new file mode 100644 index 000000000000..782f77de3520 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveMinimalUnaryOpTestTemplate.template @@ -0,0 +1,302 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new {TemplateName}UnaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}UnaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException($"Invalid value of alignment: {alignment}, sizeOfinArray1: {sizeOfinArray1}, sizeOfoutArray: {sizeOfoutArray}"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}UnaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + + private DataTable _dataTable; + + public {TemplateName}UnaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + _dataTable = new DataTable(_data1, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var result = {Isa}.{Method}(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveTernOpFirstArgTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveTernOpFirstArgTestTemplate.template new file mode 100644 index 000000000000..1ec3f6d9d2c5 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveTernOpFirstArgTestTemplate.template @@ -0,0 +1,452 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new {TemplateName}TernaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + // Validates executing the test inside conditional, with op1 as falseValue + test.ConditionalSelect_Op1(); + + // Validates executing the test inside conditional, with op3 as falseValue + test.ConditionalSelect_FalseOp(); + + // Validates executing the test inside conditional, with op3 as zero + test.ConditionalSelect_ZeroOp(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}TernaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] inArray3; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle inHandle3; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op2BaseType}[] inArray2, {Op3BaseType}[] inArray3, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op2BaseType}>(); + int sizeOfinArray3 = inArray3.Length * Unsafe.SizeOf<{Op3BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfinArray3 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.inArray3 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.inHandle3 = GCHandle.Alloc(this.inArray3, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray3Ptr), ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), (uint)sizeOfinArray3); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray3Ptr => Align((byte*)(inHandle3.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + inHandle3.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op1VectorType}<{Op2BaseType}> _fld2; + public {Op1VectorType}<{Op3BaseType}> _fld3; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op2BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op2BaseType}>>()); + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op3BaseType}>, byte>(ref testStruct._fld3), ref Unsafe.As<{Op3BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op3BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}TernaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2, _fld3); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op2ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op2BaseType}>>() / sizeof({Op2BaseType}); + private static readonly int Op3ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op3BaseType}>>() / sizeof({Op3BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _maskData = new {Op1BaseType}[Op1ElementCount]; + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + private static {Op3BaseType}[] _data3 = new {Op3BaseType}[Op3ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _mask; + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op1VectorType}<{Op2BaseType}> _fld2; + private {Op1VectorType}<{Op3BaseType}> _fld3; + private {Op1VectorType}<{Op1BaseType}> _falseFld; + + private DataTable _dataTable; + + public {TemplateName}TernaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _maskData[i] = ({Op1BaseType})({NextValueOp1} % 2); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _mask), ref Unsafe.As<{Op1BaseType}, byte>(ref _maskData[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op2BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op2BaseType}>>()); + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op3BaseType}>, byte>(ref _fld3), ref Unsafe.As<{Op3BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op3BaseType}>>()); + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _falseFld), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + _dataTable = new DataTable(_data1, _data2, _data3, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op1VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op1VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + {Op1VectorType}<{Op1BaseType}> loadMask1 = Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All); + {Op1VectorType}<{Op2BaseType}> loadMask2 = Sve.CreateTrueMask{Op2BaseType}(SveMaskPattern.All); + {Op1VectorType}<{Op3BaseType}> loadMask3 = Sve.CreateTrueMask{Op3BaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask1, ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op1VectorType}(loadMask2, ({Op2BaseType}*)(_dataTable.inArray2Ptr)), + {LoadIsa}.Load{Op1VectorType}(loadMask3, ({Op3BaseType}*)(_dataTable.inArray3Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op1VectorType}<{Op2BaseType}>), typeof({Op1VectorType}<{Op3BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op1VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op1VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op1VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var op3 = Unsafe.Read<{Op1VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr); + var result = {Isa}.{Method}(op1, op2, op3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2, _fld3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2, test._fld3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void ConditionalSelect_Op1() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, _fld1); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, _fld1); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, _fld1); + } + + public void ConditionalSelect_FalseOp() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, _falseFld); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, _falseFld); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, _falseFld); + } + + public void ConditionalSelect_ZeroOp() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, {Op1VectorType}<{Op1BaseType}>.Zero); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, {Op1VectorType}<{Op1BaseType}>.Zero); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, {Op1VectorType}<{Op1BaseType}>.Zero); + } + + [method: MethodImpl(MethodImplOptions.AggressiveInlining)] + private void ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}> mask, {Op1VectorType}<{Op1BaseType}> op1, {Op1VectorType}<{Op2BaseType}> op2, {Op1VectorType}<{Op3BaseType}> op3, {Op1VectorType}<{Op1BaseType}> falseOp) + { + var result = Sve.ConditionalSelect(mask, {Isa}.{Method}(op1, op2, op3), falseOp); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateConditionalSelectResult(mask, op1, op2, op3, falseOp, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateConditionalSelectResult({Op1VectorType}<{Op1BaseType}> maskOp, {Op1VectorType}<{Op1BaseType}> firstOp, {Op1VectorType}<{Op2BaseType}> secondOp, {Op1VectorType}<{Op3BaseType}> thirdOp, {Op1VectorType}<{Op1BaseType}> falseOp, void* output, [CallerMemberName] string method = "") + { + {Op1BaseType}[] mask = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] first = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] second = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] third = new {Op3BaseType}[Op3ElementCount]; + {Op1BaseType}[] falseVal = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] result = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref mask[0]), maskOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref first[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref second[0]), secondOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref third[0]), thirdOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref falseVal[0]), falseOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref result[0]), ref Unsafe.AsRef(output), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + bool succeeded = true; + + {TemplateValidationLogicForCndSel} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" mask: ({string.Join(", ", mask)})"); + TestLibrary.TestFramework.LogInformation($" first: ({string.Join(", ", first)})"); + TestLibrary.TestFramework.LogInformation($" second: ({string.Join(", ", second)})"); + TestLibrary.TestFramework.LogInformation($" third: ({string.Join(", ", third)})"); + TestLibrary.TestFramework.LogInformation($" falseOp: ({string.Join(", ", falseVal)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op1VectorType}<{Op2BaseType}> op2, {Op1VectorType}<{Op3BaseType}> op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] inArray3 = new {Op3BaseType}[Op3ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), op3); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] inArray3 = new {Op3BaseType}[Op3ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), ref Unsafe.AsRef(op3), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op3BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] first, {Op2BaseType}[] second, {Op3BaseType}[] third, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op2BaseType}>, {Op1VectorType}<{Op3BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", first)})"); + TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", second)})"); + TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", third)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveTernOpTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveTernOpTestTemplate.template new file mode 100644 index 000000000000..044643bfa5fe --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveTernOpTestTemplate.template @@ -0,0 +1,482 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new {TemplateName}TernaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + // Validates executing the test inside conditional, with op1 as falseValue + test.ConditionalSelect_Op1(); + + // Validates executing the test inside conditional, with op2 as falseValue + test.ConditionalSelect_Op2(); + + // Validates executing the test inside conditional, with op3 as falseValue + test.ConditionalSelect_Op3(); + + // Validates executing the test inside conditional, with op3 as falseValue + test.ConditionalSelect_FalseOp(); + + // Validates executing the test inside conditional, with op3 as zero + test.ConditionalSelect_ZeroOp(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}TernaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] inArray2; + private byte[] inArray3; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle inHandle2; + private GCHandle inHandle3; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {Op2BaseType}[] inArray2, {Op3BaseType}[] inArray3, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<{Op2BaseType}>(); + int sizeOfinArray3 = inArray3.Length * Unsafe.SizeOf<{Op3BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfinArray2 || (alignment * 2) < sizeOfinArray3 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException("Invalid value of alignment"); + } + + this.inArray1 = new byte[alignment * 2]; + this.inArray2 = new byte[alignment * 2]; + this.inArray3 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.inHandle2 = GCHandle.Alloc(this.inArray2, GCHandleType.Pinned); + this.inHandle3 = GCHandle.Alloc(this.inArray3, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray2Ptr), ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), (uint)sizeOfinArray2); + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray3Ptr), ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), (uint)sizeOfinArray3); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray2Ptr => Align((byte*)(inHandle2.AddrOfPinnedObject().ToPointer()), alignment); + public void* inArray3Ptr => Align((byte*)(inHandle3.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + inHandle2.Free(); + inHandle3.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op1VectorType}<{Op2BaseType}> _fld2; + public {Op1VectorType}<{Op3BaseType}> _fld3; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op2BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op2BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op3BaseType}>, byte>(ref testStruct._fld3), ref Unsafe.As<{Op3BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op3BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}TernaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2, _fld3); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op2ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op2BaseType}>>() / sizeof({Op2BaseType}); + private static readonly int Op3ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op3BaseType}>>() / sizeof({Op3BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _maskData = new {Op1BaseType}[Op1ElementCount]; + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + private static {Op3BaseType}[] _data3 = new {Op3BaseType}[Op3ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _mask; + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op1VectorType}<{Op2BaseType}> _fld2; + private {Op1VectorType}<{Op3BaseType}> _fld3; + private {Op1VectorType}<{Op1BaseType}> _falseFld; + + private DataTable _dataTable; + + public {TemplateName}TernaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _maskData[i] = ({Op1BaseType})({NextValueOp1} % 2); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _mask), ref Unsafe.As<{Op1BaseType}, byte>(ref _maskData[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op2BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op2BaseType}>>()); + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op3BaseType}>, byte>(ref _fld3), ref Unsafe.As<{Op3BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op3BaseType}>>()); + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _falseFld), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + _dataTable = new DataTable(_data1, _data2, _data3, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op1VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op1VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + {Op1VectorType}<{Op1BaseType}> loadMask1 = Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All); + {Op1VectorType}<{Op2BaseType}> loadMask2 = Sve.CreateTrueMask{Op2BaseType}(SveMaskPattern.All); + {Op1VectorType}<{Op3BaseType}> loadMask3 = Sve.CreateTrueMask{Op3BaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask1, ({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op1VectorType}(loadMask2, ({Op2BaseType}*)(_dataTable.inArray2Ptr)), + {LoadIsa}.Load{Op1VectorType}(loadMask3, ({Op3BaseType}*)(_dataTable.inArray3Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op1VectorType}<{Op2BaseType}>), typeof({Op1VectorType}<{Op3BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op1VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op1VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op1VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var op3 = Unsafe.Read<{Op1VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr); + var result = {Isa}.{Method}(op1, op2, op3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2, _fld3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2, test._fld3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void ConditionalSelect_Op1() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, _fld1); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, _fld1); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, _fld1); + } + + public void ConditionalSelect_Op2() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, _fld2); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, _fld2); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op2_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, _fld2); + } + + public void ConditionalSelect_Op3() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op3_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, _fld3); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op3_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, _fld3); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op3_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, _fld3); + } + + public void ConditionalSelect_FalseOp() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, _falseFld); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, _falseFld); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, _falseFld); + } + + public void ConditionalSelect_ZeroOp() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld2, _fld3, {Op1VectorType}<{Op1BaseType}>.Zero); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld2, _fld3, {Op1VectorType}<{Op1BaseType}>.Zero); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld2, _fld3, {Op1VectorType}<{Op1BaseType}>.Zero); + } + + [method: MethodImpl(MethodImplOptions.AggressiveInlining)] + private void ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}> mask, {Op1VectorType}<{Op1BaseType}> op1, {Op1VectorType}<{Op2BaseType}> op2, {Op1VectorType}<{Op3BaseType}> op3, {Op1VectorType}<{Op1BaseType}> falseOp) + { + var result = Sve.ConditionalSelect(mask, {Isa}.{Method}(op1, op2, op3), falseOp); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateConditionalSelectResult(mask, op1, op2, op3, falseOp, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateConditionalSelectResult({Op1VectorType}<{Op1BaseType}> maskOp, {Op1VectorType}<{Op1BaseType}> firstOp, {Op1VectorType}<{Op2BaseType}> secondOp, {Op1VectorType}<{Op3BaseType}> thirdOp, {Op1VectorType}<{Op1BaseType}> falseOp, void* output, [CallerMemberName] string method = "") + { + {Op1BaseType}[] mask = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] first = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] second = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] third = new {Op3BaseType}[Op3ElementCount]; + {Op1BaseType}[] falseVal = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] result = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref mask[0]), maskOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref first[0]), firstOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref second[0]), secondOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref third[0]), thirdOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref falseVal[0]), falseOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref result[0]), ref Unsafe.AsRef(output), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + bool succeeded = true; + + {TemplateValidationLogicForCndSel} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" mask: ({string.Join(", ", mask)})"); + TestLibrary.TestFramework.LogInformation($" first: ({string.Join(", ", first)})"); + TestLibrary.TestFramework.LogInformation($" second: ({string.Join(", ", second)})"); + TestLibrary.TestFramework.LogInformation($" third: ({string.Join(", ", third)})"); + TestLibrary.TestFramework.LogInformation($" falseOp: ({string.Join(", ", falseVal)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op1VectorType}<{Op2BaseType}> op2, {Op1VectorType}<{Op3BaseType}> op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op1ElementCount]; + {Op3BaseType}[] inArray3 = new {Op3BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), op3); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op1ElementCount]; + {Op3BaseType}[] inArray3 = new {Op3BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), ref Unsafe.AsRef(op3), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op3BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {Op2BaseType}[] secondOp, {Op3BaseType}[] thirdOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op2BaseType}>, {Op1VectorType}<{Op3BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveUnaryOpTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveUnaryOpTestTemplate.template new file mode 100644 index 000000000000..119cc5d88cb6 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/_SveUnaryOpTestTemplate.template @@ -0,0 +1,391 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics.Arm\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using Xunit; + +namespace JIT.HardwareIntrinsics.Arm +{ + public static partial class Program + { + [Fact] + public static void {TestName}() + { + var test = new {TemplateName}UnaryOpTest__{TestName}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + + // Validates executing the test inside conditional, with op1 as falseValue + test.ConditionalSelect_Op1(); + + // Validates executing the test inside conditional, with op3 as falseValue + test.ConditionalSelect_FalseOp(); + + // Validates executing the test inside conditional, with op3 as zero + test.ConditionalSelect_ZeroOp(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class {TemplateName}UnaryOpTest__{TestName} + { + private struct DataTable + { + private byte[] inArray1; + private byte[] outArray; + + private GCHandle inHandle1; + private GCHandle outHandle; + + private ulong alignment; + + public DataTable({Op1BaseType}[] inArray1, {RetBaseType}[] outArray, int alignment) + { + int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<{Op1BaseType}>(); + int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<{RetBaseType}>(); + if ((alignment != 64 && alignment != 16 && alignment != 8) || (alignment * 2) < sizeOfinArray1 || (alignment * 2) < sizeOfoutArray) + { + throw new ArgumentException($"Invalid value of alignment: {alignment}, sizeOfinArray1: {sizeOfinArray1}, sizeOfoutArray: {sizeOfoutArray}"); + } + + this.inArray1 = new byte[alignment * 2]; + this.outArray = new byte[alignment * 2]; + + this.inHandle1 = GCHandle.Alloc(this.inArray1, GCHandleType.Pinned); + this.outHandle = GCHandle.Alloc(this.outArray, GCHandleType.Pinned); + + this.alignment = (ulong)alignment; + + Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef(inArray1Ptr), ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), (uint)sizeOfinArray1); + } + + public void* inArray1Ptr => Align((byte*)(inHandle1.AddrOfPinnedObject().ToPointer()), alignment); + public void* outArrayPtr => Align((byte*)(outHandle.AddrOfPinnedObject().ToPointer()), alignment); + + public void Dispose() + { + inHandle1.Free(); + outHandle.Free(); + } + + private static unsafe void* Align(byte* buffer, ulong expectedAlignment) + { + return (void*)(((ulong)buffer + expectedAlignment - 1) & ~(expectedAlignment - 1)); + } + } + + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario({TemplateName}UnaryOpTest__{TestName} testClass) + { + var result = {Isa}.{Method}(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _maskData = new {Op1BaseType}[Op1ElementCount]; + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _mask; + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op1VectorType}<{Op1BaseType}> _falseFld; + + private DataTable _dataTable; + + public {TemplateName}UnaryOpTest__{TestName}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _maskData[i] = ({Op1BaseType})({NextValueOp1} % 2); } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _mask), ref Unsafe.As<{Op1BaseType}, byte>(ref _maskData[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _falseFld), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + _dataTable = new DataTable(_data1, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + {Op1VectorType}<{Op1BaseType}> loadMask = Sve.CreateTrueMask{Op1BaseType}(SveMaskPattern.All); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(loadMask, ({Op1BaseType}*)(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var result = {Isa}.{Method}(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void ConditionalSelect_Op1() + { + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_mask"); + ConditionalSelectScenario(_mask, _fld1, _fld1); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _fld1); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_Op1_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _fld1); + } + + public void ConditionalSelect_FalseOp() + { + TestLibrary.TestFramework.BeginScenario(nameof(ConditionalSelect_FalseOp)); + ConditionalSelectScenario(_mask, _fld1, _falseFld); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, _falseFld); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_FalseOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, _falseFld); + } + + public void ConditionalSelect_ZeroOp() + { + TestLibrary.TestFramework.BeginScenario(nameof(ConditionalSelect_ZeroOp)); + ConditionalSelectScenario(_mask, _fld1, {Op1VectorType}<{Op1BaseType}>.Zero); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_zero"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.Zero, _fld1, {Op1VectorType}<{Op1BaseType}>.Zero); + + TestLibrary.TestFramework.BeginScenario("ConditionalSelect_ZeroOp_all"); + ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}>.AllBitsSet, _fld1, {Op1VectorType}<{Op1BaseType}>.Zero); + } + + [method: MethodImpl(MethodImplOptions.AggressiveInlining)] + private void ConditionalSelectScenario({Op1VectorType}<{Op1BaseType}> mask, {Op1VectorType}<{Op1BaseType}> op1, {Op1VectorType}<{Op1BaseType}> falseOp) + { + var result = Sve.ConditionalSelect(mask, {Isa}.{Method}(op1), falseOp); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateConditionalSelectResult(mask, op1, falseOp, _dataTable.outArrayPtr); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateConditionalSelectResult({Op1VectorType}<{Op1BaseType}> maskOp, {Op1VectorType}<{Op1BaseType}> leftOp, {Op1VectorType}<{Op1BaseType}> falseOp, void* output, [CallerMemberName] string method = "") + { + {Op1BaseType}[] mask = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] left = new {Op1BaseType}[Op1ElementCount]; + {Op1BaseType}[] falseVal = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] result = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref mask[0]), maskOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref left[0]), leftOp); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref falseVal[0]), falseOp); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref result[0]), ref Unsafe.AsRef(output), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + bool succeeded = true; + + {TemplateValidationLogicForCndSel} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" mask: ({string.Join(", ", mask)})"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" falseOp: ({string.Join(", ", falseVal)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + {TemplateValidationLogic} + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorBinaryOpTest.template b/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorBinaryOpTest.template index 54b276bdca1a..dd919c86c7e9 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorBinaryOpTest.template +++ b/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorBinaryOpTest.template @@ -29,6 +29,18 @@ namespace JIT.HardwareIntrinsics.General // Validates calling via reflection works, using Unsafe.Read test.RunReflectionScenario_UnsafeRead(); + // Validates broadcast functionality works + test.RunBroadcastScenario(); + + // Validates masking with a value functionality works + test.RunMaskingValueScenario(); + + // Validates masking with zero functionality works + test.RunMaskingZeroScenario(); + + // Validates broadcast + masking functionality works + test.RunBroadcastAndMaskingScenario(); + // Validates passing a static member works test.RunClsVarScenario(); @@ -220,6 +232,77 @@ namespace JIT.HardwareIntrinsics.General ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); } + public void RunBroadcastScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastScenario)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + {Op2VectorType}.Create<{Op2BaseType}>(Unsafe.Read<{Op2BaseType}>(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr, isBroadcast: true); + } + + public void RunMaskingValueScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingValueScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + op1, + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + ), + {RetVectorType}.Create<{RetBaseType}>(1) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr, mask: 1); + } + + + public void RunMaskingZeroScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingZeroScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + op1, + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + ), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr, mask: 0); + } + + public void RunBroadcastAndMaskingScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastAndMaskingScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + op1, + {Op2VectorType}.Create<{Op2BaseType}>(Unsafe.Read<{Op2BaseType}>(_dataTable.inArray2Ptr)) + ), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr, isBroadcast: true, mask: 0); + } + public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); @@ -285,7 +368,7 @@ namespace JIT.HardwareIntrinsics.General test.RunStructFldScenario(this); } - private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, void* result, [CallerMemberName] string method = "") + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; @@ -295,10 +378,10 @@ namespace JIT.HardwareIntrinsics.General Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, inArray2, outArray, method); + ValidateResult(inArray1, inArray2, outArray, isBroadcast, mask, method); } - private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + private void ValidateResult(void* op1, void* op2, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; @@ -308,14 +391,19 @@ namespace JIT.HardwareIntrinsics.General Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, inArray2, outArray, method); + ValidateResult(inArray1, inArray2, outArray, isBroadcast, mask, method); } - private void ValidateResult({Op1BaseType}[] left, {Op2BaseType}[] right, {RetBaseType}[] result, [CallerMemberName] string method = "") + private void ValidateResult({Op1BaseType}[] left, {Op2BaseType}[] right, {RetBaseType}[] result, bool isBroadcast, {RetBaseType}? mask, [CallerMemberName] string method = "") { bool succeeded = true; - if ({ValidateFirstResult}) + if (isBroadcast) + { + right.AsSpan().Fill(right[0]); + } + + if ({ValidateFirstResult} && (!mask.HasValue || ((left[0] != default) && result[0] != mask.Value))) { succeeded = false; } @@ -323,7 +411,7 @@ namespace JIT.HardwareIntrinsics.General { for (var i = 1; i < RetElementCount; i++) { - if ({ValidateRemainingResults}) + if ({ValidateRemainingResults} && (!mask.HasValue || ((left[i] != default) && result[i] != mask.Value))) { succeeded = false; break; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorBinaryOperatorTest.template b/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorBinaryOperatorTest.template index 4d953387db0f..8d2f62ed861f 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorBinaryOperatorTest.template +++ b/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorBinaryOperatorTest.template @@ -29,6 +29,18 @@ namespace JIT.HardwareIntrinsics.General // Validates calling via reflection works, using Unsafe.Read test.RunReflectionScenario_UnsafeRead(); + // Validates broadcast functionality works + test.RunBroadcastScenario(); + + // Validates masking with a value functionality works + test.RunMaskingValueScenario(); + + // Validates masking with zero functionality works + test.RunMaskingZeroScenario(); + + // Validates broadcast + masking functionality works + test.RunBroadcastAndMaskingScenario(); + // Validates passing a static member works test.RunClsVarScenario(); @@ -200,6 +212,64 @@ namespace JIT.HardwareIntrinsics.General ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); } + public void RunBroadcastScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastScenario)); + + var result = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr) {Opcode} {Op2VectorType}.Create<{Op2BaseType}>(Unsafe.Read<{Op2BaseType}>(_dataTable.inArray2Ptr)); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr, isBroadcast: true); + } + + public void RunMaskingValueScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingValueScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + op1 {Opcode} Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + {RetVectorType}.Create<{RetBaseType}>(1) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr, mask: 1); + } + + public void RunMaskingZeroScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingZeroScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + op1 {Opcode} Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr, mask: 0); + } + + public void RunBroadcastAndMaskingScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastAndMaskingScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + op1 {Opcode} {Op2VectorType}.Create<{Op2BaseType}>(Unsafe.Read<{Op2BaseType}>(_dataTable.inArray2Ptr)), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr, isBroadcast: true, mask: 0); + } + public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); @@ -262,7 +332,7 @@ namespace JIT.HardwareIntrinsics.General test.RunStructFldScenario(this); } - private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, void* result, [CallerMemberName] string method = "") + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; @@ -272,10 +342,10 @@ namespace JIT.HardwareIntrinsics.General Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, inArray2, outArray, method); + ValidateResult(inArray1, inArray2, outArray, isBroadcast, mask, method); } - private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + private void ValidateResult(void* op1, void* op2, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; @@ -285,14 +355,19 @@ namespace JIT.HardwareIntrinsics.General Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, inArray2, outArray, method); + ValidateResult(inArray1, inArray2, outArray, isBroadcast, mask, method); } - private void ValidateResult({Op1BaseType}[] left, {Op2BaseType}[] right, {RetBaseType}[] result, [CallerMemberName] string method = "") + private void ValidateResult({Op1BaseType}[] left, {Op2BaseType}[] right, {RetBaseType}[] result, bool isBroadcast, {RetBaseType}? mask, [CallerMemberName] string method = "") { bool succeeded = true; - if ({ValidateFirstResult}) + if (isBroadcast) + { + right.AsSpan().Fill(right[0]); + } + + if ({ValidateFirstResult} && (!mask.HasValue || ((left[0] != default) && result[0] != mask.Value))) { succeeded = false; } @@ -300,7 +375,7 @@ namespace JIT.HardwareIntrinsics.General { for (var i = 1; i < RetElementCount; i++) { - if ({ValidateRemainingResults}) + if ({ValidateRemainingResults} && (!mask.HasValue || ((left[i] != default) && result[i] != mask.Value))) { succeeded = false; break; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorTernaryOpTest.template b/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorTernaryOpTest.template index dd51391b96dd..7018b5ab67c7 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorTernaryOpTest.template +++ b/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorTernaryOpTest.template @@ -29,6 +29,18 @@ namespace JIT.HardwareIntrinsics.General // Validates calling via reflection works, using Unsafe.Read test.RunReflectionScenario_UnsafeRead(); + // Validates broadcast functionality works + test.RunBroadcastScenario(); + + // Validates masking with a value functionality works + test.RunMaskingValueScenario(); + + // Validates masking with zero functionality works + test.RunMaskingZeroScenario(); + + // Validates broadcast + masking functionality + test.RunBroadcastAndMaskingScenario(); + // Validates passing a static member works test.RunClsVarScenario(); @@ -244,6 +256,80 @@ namespace JIT.HardwareIntrinsics.General ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); } + public void RunBroadcastScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastScenario)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + {Op3VectorType}.Create<{Op3BaseType}>(Unsafe.Read<{Op3BaseType}>(_dataTable.inArray3Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr, isBroadcast: true); + } + + public void RunMaskingValueScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingValueScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + op1, + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray3Ptr) + ), + {RetVectorType}.Create<{RetBaseType}>(1) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr, mask: 1); + } + + public void RunMaskingZeroScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingZeroScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + op1, + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray3Ptr) + ), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr, mask: 0); + } + + public void RunBroadcastAndMaskingScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastAndMaskingScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + op1, + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + {Op3VectorType}.Create<{Op3BaseType}>(Unsafe.Read<{Op3BaseType}>(_dataTable.inArray3Ptr)) + ), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr, isBroadcast: true, mask: 0); + } + public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); @@ -311,7 +397,7 @@ namespace JIT.HardwareIntrinsics.General test.RunStructFldScenario(this); } - private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, {Op3VectorType}<{Op3BaseType}> op3, void* result, [CallerMemberName] string method = "") + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, {Op3VectorType}<{Op3BaseType}> op3, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; @@ -323,10 +409,10 @@ namespace JIT.HardwareIntrinsics.General Unsafe.WriteUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), op3); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, inArray2, inArray3, outArray, method); + ValidateResult(inArray1, inArray2, inArray3, outArray, isBroadcast, mask, method); } - private void ValidateResult(void* op1, void* op2, void* op3, void* result, [CallerMemberName] string method = "") + private void ValidateResult(void* op1, void* op2, void* op3, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; @@ -338,14 +424,19 @@ namespace JIT.HardwareIntrinsics.General Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), ref Unsafe.AsRef(op3), (uint)Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>()); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, inArray2, inArray3, outArray, method); + ValidateResult(inArray1, inArray2, inArray3, outArray, isBroadcast, mask, method); } - private void ValidateResult({Op1BaseType}[] firstOp, {Op2BaseType}[] secondOp, {Op3BaseType}[] thirdOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + private void ValidateResult({Op1BaseType}[] firstOp, {Op2BaseType}[] secondOp, {Op3BaseType}[] thirdOp, {RetBaseType}[] result, bool isBroadcast, {RetBaseType}? mask, [CallerMemberName] string method = "") { bool succeeded = true; - if ({ValidateFirstResult}) + if (isBroadcast) + { + thirdOp.AsSpan().Fill(thirdOp[0]); + } + + if ({ValidateFirstResult} && (!mask.HasValue || ((firstOp[0] != default) && result[0] != mask.Value))) { succeeded = false; } @@ -353,7 +444,7 @@ namespace JIT.HardwareIntrinsics.General { for (var i = 1; i < RetElementCount; i++) { - if ({ValidateRemainingResults}) + if ({ValidateRemainingResults} && (!mask.HasValue || ((firstOp[i] != default) && result[i] != mask.Value))) { succeeded = false; break; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorUnaryOpTest.template b/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorUnaryOpTest.template index eb80b1cbde78..15f73f76b59e 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorUnaryOpTest.template +++ b/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorUnaryOpTest.template @@ -29,6 +29,18 @@ namespace JIT.HardwareIntrinsics.General // Validates calling via reflection works, using Unsafe.Read test.RunReflectionScenario_UnsafeRead(); + // Validates broadcast functionality works + test.RunBroadcastScenario(); + + // Validates masking with a value functionality works + test.RunMaskingValueScenario(); + + // Validates masking with zero functionality works + test.RunMaskingZeroScenario(); + + // Validates broadcast + masking functionality + test.RunBroadcastAndMaskingScenario(); + // Validates passing a static member works test.RunClsVarScenario(); @@ -196,6 +208,72 @@ namespace JIT.HardwareIntrinsics.General ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); } + public void RunBroadcastScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastScenario)); + + var result = {Isa}.{Method}( + {Op1VectorType}.Create<{Op1BaseType}>(Unsafe.Read<{Op1BaseType}>(_dataTable.inArray1Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr, isBroadcast: true); + } + + public void RunMaskingValueScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingValueScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr) + ), + {RetVectorType}.Create<{RetBaseType}>(1) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr, mask: 1); + } + + public void RunMaskingZeroScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingZeroScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr) + ), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr, mask: 0); + } + + public void RunBroadcastAndMaskingScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastAndMaskingScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + {Op1VectorType}.Create<{Op1BaseType}>(Unsafe.Read<{Op1BaseType}>(_dataTable.inArray1Ptr)) + ), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr, isBroadcast: true, mask: 0); + } + public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); @@ -259,7 +337,7 @@ namespace JIT.HardwareIntrinsics.General test.RunStructFldScenario(this); } - private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, [CallerMemberName] string method = "") + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; @@ -267,10 +345,10 @@ namespace JIT.HardwareIntrinsics.General Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, outArray, method); + ValidateResult(inArray1, outArray, isBroadcast, mask, method); } - private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + private void ValidateResult(void* op1, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; @@ -278,14 +356,19 @@ namespace JIT.HardwareIntrinsics.General Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, outArray, method); + ValidateResult(inArray1, outArray, isBroadcast, mask, method); } - private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, bool isBroadcast, {RetBaseType}? mask, [CallerMemberName] string method = "") { bool succeeded = true; - if ({ValidateFirstResult}) + if (isBroadcast) + { + firstOp.AsSpan().Fill(firstOp[0]); + } + + if ({ValidateFirstResult} && (!mask.HasValue || ((firstOp[0] != default) && result[0] != mask.Value))) { succeeded = false; } @@ -293,7 +376,7 @@ namespace JIT.HardwareIntrinsics.General { for (var i = 1; i < RetElementCount; i++) { - if ({ValidateRemainingResults}) + if ({ValidateRemainingResults} && (!mask.HasValue || ((firstOp[i] != default) && result[i] != mask.Value))) { succeeded = false; break; diff --git a/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorUnaryOperatorTest.template b/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorUnaryOperatorTest.template index 833b83cb90a0..616c2eb2728f 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorUnaryOperatorTest.template +++ b/src/tests/JIT/HardwareIntrinsics/General/Shared/VectorUnaryOperatorTest.template @@ -29,6 +29,18 @@ namespace JIT.HardwareIntrinsics.General // Validates calling via reflection works, using Unsafe.Read test.RunReflectionScenario_UnsafeRead(); + // Validates broadcast functionality works + test.RunBroadcastScenario(); + + // Validates masking with a value functionality works + test.RunMaskingValueScenario(); + + // Validates masking with zero functionality works + test.RunMaskingZeroScenario(); + + // Validates broadcast + masking functionality + test.RunBroadcastAndMaskingScenario(); + // Validates passing a static member works test.RunClsVarScenario(); @@ -179,6 +191,64 @@ namespace JIT.HardwareIntrinsics.General ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr); } + public void RunBroadcastScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastScenario)); + + var result = {Opcode}{Op1VectorType}.Create<{Op1BaseType}>(Unsafe.Read<{Op1BaseType}>(_dataTable.inArray1Ptr)); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr, isBroadcast: true); + } + + public void RunMaskingValueScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingValueScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + {Opcode}Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + {RetVectorType}.Create<{RetBaseType}>(1) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr, mask: 1); + } + + public void RunMaskingZeroScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingZeroScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + {Opcode}Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr, mask: 0); + } + + public void RunBroadcastAndMaskingScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastAndMaskingScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1, {RetVectorType}<{RetBaseType}>.Zero), + {Opcode}{Op1VectorType}.Create<{Op1BaseType}>(Unsafe.Read<{Op1BaseType}>(_dataTable.inArray1Ptr)), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr, isBroadcast: true, mask: 0); + } + public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); @@ -240,7 +310,7 @@ namespace JIT.HardwareIntrinsics.General test.RunStructFldScenario(this); } - private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, [CallerMemberName] string method = "") + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; @@ -248,10 +318,10 @@ namespace JIT.HardwareIntrinsics.General Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, outArray, method); + ValidateResult(inArray1, outArray, isBroadcast, mask, method); } - private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + private void ValidateResult(void* op1, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; @@ -259,14 +329,19 @@ namespace JIT.HardwareIntrinsics.General Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, outArray, method); + ValidateResult(inArray1, outArray, isBroadcast, mask, method); } - private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, bool isBroadcast, {RetBaseType}? mask, [CallerMemberName] string method = "") { bool succeeded = true; - if ({ValidateFirstResult}) + if (isBroadcast) + { + firstOp.AsSpan().Fill(firstOp[0]); + } + + if ({ValidateFirstResult} && (!mask.HasValue || ((firstOp[0] != default) && result[0] != mask.Value))) { succeeded = false; } @@ -274,7 +349,7 @@ namespace JIT.HardwareIntrinsics.General { for (var i = 1; i < RetElementCount; i++) { - if ({ValidateRemainingResults}) + if ({ValidateRemainingResults} && (!mask.HasValue || ((firstOp[i] != default) && result[i] != mask.Value))) { succeeded = false; break; diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Shared/BroadcastTest.template b/src/tests/JIT/HardwareIntrinsics/X86/Shared/BroadcastTest.template new file mode 100644 index 000000000000..7c0bf494d44f --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/X86/Shared/BroadcastTest.template @@ -0,0 +1,283 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using Xunit; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + [Fact] + public static void {Method}{RetBaseType}() + { + var test = new BroadcastTest__{Method}{RetBaseType}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class BroadcastTest__{Method}{RetBaseType} + { + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario(BroadcastTest__{Method}{RetBaseType} testClass) + { + var result = {Isa}.{Method}(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + + private SimpleUnaryOpTest__DataTable<{RetBaseType}, {Op1BaseType}> _dataTable; + + public BroadcastTest__{Method}{RetBaseType}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + _dataTable = new SimpleUnaryOpTest__DataTable<{RetBaseType}, {Op1BaseType}>(_data1, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArrayPtr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArrayPtr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = {Isa}.{Method}( + {LoadIsa}.LoadAligned{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArrayPtr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArrayPtr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArrayPtr); + var result = {Isa}.{Method}(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if ({ValidateFirstResult}) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ({ValidateRemainingResults}) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Shared/ComplexBinOpTest.template b/src/tests/JIT/HardwareIntrinsics/X86/Shared/ComplexBinOpTest.template new file mode 100644 index 000000000000..9993b82565d1 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/X86/Shared/ComplexBinOpTest.template @@ -0,0 +1,302 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using Xunit; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + [Fact] + public static void {Method}{RetBaseType}() + { + var test = new ComplexBinaryOpTest__{Method}{RetBaseType}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ComplexBinaryOpTest__{Method}{RetBaseType} + { + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op2VectorType}<{Op2BaseType}> _fld2; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario(ComplexBinaryOpTest__{Method}{RetBaseType} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op2ElementCount = Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>() / sizeof({Op2BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op2VectorType}<{Op2BaseType}> _fld2; + + private SimpleBinaryOpTest__DataTable<{RetBaseType}, {Op1BaseType}, {Op2BaseType}> _dataTable; + + public ComplexBinaryOpTest__{Method}{RetBaseType}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + _dataTable = new SimpleBinaryOpTest__DataTable<{RetBaseType}, {Op1BaseType}, {Op2BaseType}>(_data1, _data2, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(({Op2BaseType}*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = {Isa}.{Method}( + {LoadIsa}.LoadAligned{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.LoadAligned{Op2VectorType}(({Op2BaseType}*)(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op2VectorType}<{Op2BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var result = {Isa}.{Method}(op1, op2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] left, {Op2BaseType}[] right, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if ({ValidateFirstResult}) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ({ValidateRemainingResults}) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op2VectorType}<{Op2BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); + TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Shared/ComplexTernOpTest.template b/src/tests/JIT/HardwareIntrinsics/X86/Shared/ComplexTernOpTest.template new file mode 100644 index 000000000000..8e8265dd3199 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/X86/Shared/ComplexTernOpTest.template @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using Xunit; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + [Fact] + public static void {Method}{RetBaseType}() + { + var test = new ComplexTernaryOpTest__{Method}{RetBaseType}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ComplexTernaryOpTest__{Method}{RetBaseType} + { + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + public {Op2VectorType}<{Op2BaseType}> _fld2; + public {Op2VectorType}<{Op3BaseType}> _fld3; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref testStruct._fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3VectorType}<{Op3BaseType}>, byte>(ref testStruct._fld3), ref Unsafe.As<{Op3BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario(ComplexTernaryOpTest__{Method}{RetBaseType} testClass) + { + var result = {Isa}.{Method}(_fld1, _fld2, _fld3); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int Op2ElementCount = Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>() / sizeof({Op2BaseType}); + private static readonly int Op3ElementCount = Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>() / sizeof({Op3BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + private static {Op2BaseType}[] _data2 = new {Op2BaseType}[Op2ElementCount]; + private static {Op3BaseType}[] _data3 = new {Op3BaseType}[Op3ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + private {Op2VectorType}<{Op2BaseType}> _fld2; + private {Op3VectorType}<{Op3BaseType}> _fld3; + + private SimpleTernaryOpTest__DataTable<{RetBaseType}, {Op1BaseType}, {Op2BaseType}, {Op3BaseType}> _dataTable; + + public ComplexTernaryOpTest__{Method}{RetBaseType}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2VectorType}<{Op2BaseType}>, byte>(ref _fld2), ref Unsafe.As<{Op2BaseType}, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3VectorType}<{Op3BaseType}>, byte>(ref _fld3), ref Unsafe.As<{Op3BaseType}, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = {NextValueOp2}; } + for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = {NextValueOp3}; } + _dataTable = new SimpleTernaryOpTest__DataTable<{RetBaseType}, {Op1BaseType}, {Op2BaseType}, {Op3BaseType}>(_data1, _data2, _data3, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op3VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.Load{Op2VectorType}(({Op2BaseType}*)(_dataTable.inArray2Ptr)), + {LoadIsa}.Load{Op3VectorType}(({Op3BaseType}*)(_dataTable.inArray3Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = {Isa}.{Method}( + {LoadIsa}.LoadAligned{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArray1Ptr)), + {LoadIsa}.LoadAligned{Op2VectorType}(({Op2BaseType}*)(_dataTable.inArray2Ptr)), + {LoadIsa}.LoadAligned{Op3VectorType}(({Op3BaseType}*)(_dataTable.inArray3Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>), typeof({Op2VectorType}<{Op2BaseType}>), typeof({Op3VectorType}<{Op3BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op3VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + var op2 = Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr); + var op3 = Unsafe.Read<{Op3VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr); + var result = {Isa}.{Method}(op1, op2, op3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, op2, op3, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1, _fld2, _fld3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1, test._fld2, test._fld3); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, {Op3VectorType}<{Op3BaseType}> op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] inArray3 = new {Op3BaseType}[Op3ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); + Unsafe.WriteUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), op3); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult(void* op1, void* op2, void* op3, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; + {Op3BaseType}[] inArray3 = new {Op3BaseType}[Op3ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), ref Unsafe.AsRef(op3), (uint)Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, inArray2, inArray3, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {Op2BaseType}[] secondOp, {Op3BaseType}[] thirdOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if ({ValidateFirstResult}) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ({ValidateRemainingResults}) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>, {Op2VectorType}<{Op2BaseType}>, {Op3VectorType}<{Op3BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($"secondOp: ({string.Join(", ", secondOp)})"); + TestLibrary.TestFramework.LogInformation($" thirdOp: ({string.Join(", ", thirdOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Shared/ComplexUnOpTest.template b/src/tests/JIT/HardwareIntrinsics/X86/Shared/ComplexUnOpTest.template new file mode 100644 index 000000000000..f15bbe7dec56 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/X86/Shared/ComplexUnOpTest.template @@ -0,0 +1,283 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************************** + * This file is auto-generated from a template file by the GenerateTests.csx * + * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make * + * changes, please update the corresponding template and run according to the * + * directions listed in the file. * + ******************************************************************************/ + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using Xunit; + +namespace JIT.HardwareIntrinsics.X86 +{ + public static partial class Program + { + [Fact] + public static void {Method}{RetBaseType}() + { + var test = new ComplexUnaryOpTest__{Method}{RetBaseType}(); + + if (test.IsSupported) + { + // Validates basic functionality works, using Unsafe.Read + test.RunBasicScenario_UnsafeRead(); + + if ({LoadIsa}.IsSupported) + { + // Validates basic functionality works, using Load + test.RunBasicScenario_Load(); + + // Validates basic functionality works, using LoadAligned + test.RunBasicScenario_LoadAligned(); + } + + // Validates calling via reflection works, using Unsafe.Read + test.RunReflectionScenario_UnsafeRead(); + + // Validates passing a local works, using Unsafe.Read + test.RunLclVarScenario_UnsafeRead(); + + // Validates passing an instance member of a class works + test.RunClassFldScenario(); + + // Validates passing the field of a local struct works + test.RunStructLclFldScenario(); + + // Validates passing an instance member of a struct works + test.RunStructFldScenario(); + } + else + { + // Validates we throw on unsupported hardware + test.RunUnsupportedScenario(); + } + + if (!test.Succeeded) + { + throw new Exception("One or more scenarios did not complete as expected."); + } + } + } + + public sealed unsafe class ComplexUnaryOpTest__{Method}{RetBaseType} + { + private struct TestStruct + { + public {Op1VectorType}<{Op1BaseType}> _fld1; + + public static TestStruct Create() + { + var testStruct = new TestStruct(); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref testStruct._fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + return testStruct; + } + + public void RunStructFldScenario(ComplexUnaryOpTest__{Method}{RetBaseType} testClass) + { + var result = {Isa}.{Method}(_fld1); + + Unsafe.Write(testClass._dataTable.outArrayPtr, result); + testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr); + } + } + + private static readonly int LargestVectorSize = {LargestVectorSize}; + + private static readonly int Op1ElementCount = Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>() / sizeof({Op1BaseType}); + private static readonly int RetElementCount = Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>() / sizeof({RetBaseType}); + + private static {Op1BaseType}[] _data1 = new {Op1BaseType}[Op1ElementCount]; + + private {Op1VectorType}<{Op1BaseType}> _fld1; + + private SimpleUnaryOpTest__DataTable<{RetBaseType}, {Op1BaseType}> _dataTable; + + public ComplexUnaryOpTest__{Method}{RetBaseType}() + { + Succeeded = true; + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1VectorType}<{Op1BaseType}>, byte>(ref _fld1), ref Unsafe.As<{Op1BaseType}, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + + for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = {NextValueOp1}; } + _dataTable = new SimpleUnaryOpTest__DataTable<{RetBaseType}, {Op1BaseType}>(_data1, new {RetBaseType}[RetElementCount], LargestVectorSize); + } + + public bool IsSupported => {Isa}.IsSupported; + + public bool Succeeded { get; set; } + + public void RunBasicScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArrayPtr) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_Load() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); + + var result = {Isa}.{Method}( + {LoadIsa}.Load{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArrayPtr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunBasicScenario_LoadAligned() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); + + var result = {Isa}.{Method}( + {LoadIsa}.LoadAligned{Op1VectorType}(({Op1BaseType}*)(_dataTable.inArrayPtr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunReflectionScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); + + var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1VectorType}<{Op1BaseType}>) }) + .Invoke(null, new object[] { + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArrayPtr) + }); + + Unsafe.Write(_dataTable.outArrayPtr, ({RetVectorType}<{RetBaseType}>)(result)); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); + } + + public void RunLclVarScenario_UnsafeRead() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArrayPtr); + var result = {Isa}.{Method}(op1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(op1, _dataTable.outArrayPtr); + } + + public void RunClassFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); + + var result = {Isa}.{Method}(_fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_fld1, _dataTable.outArrayPtr); + } + + public void RunStructLclFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); + + var test = TestStruct.Create(); + var result = {Isa}.{Method}(test._fld1); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(test._fld1, _dataTable.outArrayPtr); + } + + public void RunStructFldScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario)); + + var test = TestStruct.Create(); + test.RunStructFldScenario(this); + } + + public void RunUnsupportedScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunUnsupportedScenario)); + + bool succeeded = false; + + try + { + RunBasicScenario_UnsafeRead(); + } + catch (PlatformNotSupportedException) + { + succeeded = true; + } + + if (!succeeded) + { + Succeeded = false; + } + } + + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + { + {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; + {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; + + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); + Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); + + ValidateResult(inArray1, outArray, method); + } + + private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + { + bool succeeded = true; + + if ({ValidateFirstResult}) + { + succeeded = false; + } + else + { + for (var i = 1; i < RetElementCount; i++) + { + if ({ValidateRemainingResults}) + { + succeeded = false; + break; + } + } + } + + if (!succeeded) + { + TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1VectorType}<{Op1BaseType}>): {method} failed:"); + TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})"); + TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); + TestLibrary.TestFramework.LogInformation(string.Empty); + + Succeeded = false; + } + } + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Shared/_BinaryOpTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/X86/Shared/_BinaryOpTestTemplate.template index 2335fdc58658..b268a4c1d976 100644 --- a/src/tests/JIT/HardwareIntrinsics/X86/Shared/_BinaryOpTestTemplate.template +++ b/src/tests/JIT/HardwareIntrinsics/X86/Shared/_BinaryOpTestTemplate.template @@ -41,6 +41,18 @@ namespace JIT.HardwareIntrinsics.X86 // Validates calling via reflection works, using Unsafe.Read test.RunReflectionScenario_UnsafeRead(); + // Validates broadcast functionality works + test.RunBroadcastScenario(); + + // Validates masking with a value functionality works + test.RunMaskingValueScenario(); + + // Validates masking with zero functionality works + test.RunMaskingZeroScenario(); + + // Validates broadcast + masking functionality + test.RunBroadcastAndMaskingScenario(); + // Validates passing a local works, using Unsafe.Read test.RunLclVarScenario_UnsafeRead(); @@ -179,6 +191,76 @@ namespace JIT.HardwareIntrinsics.X86 ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr); } + public void RunBroadcastScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastScenario)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + {Op2VectorType}.Create<{Op2BaseType}>(Unsafe.Read<{Op2BaseType}>(_dataTable.inArray2Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr, isBroadcast: true); + } + + public void RunMaskingValueScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingValueScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1.As{RetBaseType}(), {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + op1, + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + ), + {RetVectorType}.Create<{RetBaseType}>(1) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr, mask: 1); + } + + public void RunMaskingZeroScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingZeroScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1.As{RetBaseType}(), {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + op1, + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr) + ), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr, mask: 0); + } + + public void RunBroadcastAndMaskingScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastAndMaskingScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1.As{RetBaseType}(), {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + op1, + {Op2VectorType}.Create<{Op2BaseType}>(Unsafe.Read<{Op2BaseType}>(_dataTable.inArray2Ptr)) + ), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr, isBroadcast: true, mask: 0); + } + public void RunLclVarScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); @@ -241,7 +323,7 @@ namespace JIT.HardwareIntrinsics.X86 } } - private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, void* result, [CallerMemberName] string method = "") + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; @@ -251,10 +333,10 @@ namespace JIT.HardwareIntrinsics.X86 Unsafe.WriteUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), op2); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, inArray2, outArray, method); + ValidateResult(inArray1, inArray2, outArray, isBroadcast, mask, method); } - private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "") + private void ValidateResult(void* op1, void* op2, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; @@ -264,13 +346,18 @@ namespace JIT.HardwareIntrinsics.X86 Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op2BaseType}, byte>(ref inArray2[0]), ref Unsafe.AsRef(op2), (uint)Unsafe.SizeOf<{Op2VectorType}<{Op2BaseType}>>()); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, inArray2, outArray, method); + ValidateResult(inArray1, inArray2, outArray, isBroadcast, mask, method); } - private void ValidateResult({Op1BaseType}[] left, {Op2BaseType}[] right, {RetBaseType}[] result, [CallerMemberName] string method = "") + private void ValidateResult({Op1BaseType}[] left, {Op2BaseType}[] right, {RetBaseType}[] result, bool isBroadcast, {RetBaseType}? mask, [CallerMemberName] string method = "") { bool succeeded = true; + if (isBroadcast) + { + right.AsSpan().Fill(right[0]); + } + {TemplateValidationLogic} if (!succeeded) diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Shared/_TernaryOpTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/X86/Shared/_TernaryOpTestTemplate.template index 5cd0ab652ea0..cd9caf6b7072 100644 --- a/src/tests/JIT/HardwareIntrinsics/X86/Shared/_TernaryOpTestTemplate.template +++ b/src/tests/JIT/HardwareIntrinsics/X86/Shared/_TernaryOpTestTemplate.template @@ -41,6 +41,18 @@ namespace JIT.HardwareIntrinsics.X86 // Validates calling via reflection works, using Unsafe.Read test.RunReflectionScenario_UnsafeRead(); + // Validates broadcast functionality works + test.RunBroadcastScenario(); + + // Validates masking with a value functionality works + test.RunMaskingValueScenario(); + + // Validates masking with zero functionality works + test.RunMaskingZeroScenario(); + + // Validates broadcast + masking functionality + test.RunBroadcastAndMaskingScenario(); + // Validates passing a local works, using Unsafe.Read test.RunLclVarScenario_UnsafeRead(); @@ -192,6 +204,80 @@ namespace JIT.HardwareIntrinsics.X86 ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr); } + public void RunBroadcastScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastScenario)); + + var result = {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr), + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + {Op3VectorType}.Create<{Op3BaseType}>(Unsafe.Read<{Op3BaseType}>(_dataTable.inArray3Ptr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr, isBroadcast: true); + } + + public void RunMaskingValueScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingValueScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1.As{RetBaseType}(), {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + op1, + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op3VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr) + ), + {RetVectorType}.Create<{RetBaseType}>(1) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr, mask: 1); + } + + public void RunMaskingZeroScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingZeroScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1.As{RetBaseType}(), {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + op1, + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + Unsafe.Read<{Op3VectorType}<{Op3BaseType}>>(_dataTable.inArray3Ptr) + ), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr, mask: 0); + } + + public void RunBroadcastAndMaskingScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastAndMaskingScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArray1Ptr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1.As{RetBaseType}(), {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + op1, + Unsafe.Read<{Op2VectorType}<{Op2BaseType}>>(_dataTable.inArray2Ptr), + {Op3VectorType}.Create<{Op3BaseType}>(Unsafe.Read<{Op3BaseType}>(_dataTable.inArray3Ptr)) + ), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr, isBroadcast: true, mask: 0); + } + public void RunLclVarScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); @@ -255,7 +341,7 @@ namespace JIT.HardwareIntrinsics.X86 } } - private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, {Op3VectorType}<{Op3BaseType}> op3, void* result, [CallerMemberName] string method = "") + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, {Op2VectorType}<{Op2BaseType}> op2, {Op3VectorType}<{Op3BaseType}> op3, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; @@ -267,10 +353,10 @@ namespace JIT.HardwareIntrinsics.X86 Unsafe.WriteUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), op3); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, inArray2, inArray3, outArray, method); + ValidateResult(inArray1, inArray2, inArray3, outArray, isBroadcast, mask, method); } - private void ValidateResult(void* op1, void* op2, void* op3, void* result, [CallerMemberName] string method = "") + private void ValidateResult(void* op1, void* op2, void* op3, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {Op2BaseType}[] inArray2 = new {Op2BaseType}[Op2ElementCount]; @@ -282,13 +368,18 @@ namespace JIT.HardwareIntrinsics.X86 Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op3BaseType}, byte>(ref inArray3[0]), ref Unsafe.AsRef(op3), (uint)Unsafe.SizeOf<{Op3VectorType}<{Op3BaseType}>>()); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, inArray2, inArray3, outArray, method); + ValidateResult(inArray1, inArray2, inArray3, outArray, isBroadcast, mask, method); } - private void ValidateResult({Op1BaseType}[] firstOp, {Op2BaseType}[] secondOp, {Op3BaseType}[] thirdOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + private void ValidateResult({Op1BaseType}[] firstOp, {Op2BaseType}[] secondOp, {Op3BaseType}[] thirdOp, {RetBaseType}[] result, bool isBroadcast, {RetBaseType}? mask, [CallerMemberName] string method = "") { bool succeeded = true; + if (isBroadcast) + { + thirdOp.AsSpan().Fill(thirdOp[0]); + } + {TemplateValidationLogic} if (!succeeded) diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Shared/_UnaryOpTestTemplate.template b/src/tests/JIT/HardwareIntrinsics/X86/Shared/_UnaryOpTestTemplate.template index 308bb33e72fd..04f0f5e05f9a 100644 --- a/src/tests/JIT/HardwareIntrinsics/X86/Shared/_UnaryOpTestTemplate.template +++ b/src/tests/JIT/HardwareIntrinsics/X86/Shared/_UnaryOpTestTemplate.template @@ -41,6 +41,18 @@ namespace JIT.HardwareIntrinsics.X86 // Validates calling via reflection works, using Unsafe.Read test.RunReflectionScenario_UnsafeRead(); + // Validates broadcast functionality works + test.RunBroadcastScenario(); + + // Validates masking with a value functionality works + test.RunMaskingValueScenario(); + + // Validates masking with zero functionality works + test.RunMaskingZeroScenario(); + + // Validates broadcast + masking functionality + test.RunBroadcastAndMaskingScenario(); + // Validates passing a local works, using Unsafe.Read test.RunLclVarScenario_UnsafeRead(); @@ -166,6 +178,73 @@ namespace JIT.HardwareIntrinsics.X86 ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } + public void RunBroadcastScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastScenario)); + + var result = {Isa}.{Method}( + {Op1VectorType}.Create<{Op1BaseType}>(Unsafe.Read<{Op1BaseType}>(_dataTable.inArrayPtr)) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr, isBroadcast: true); + } + + public void RunMaskingValueScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingValueScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArrayPtr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1.As{RetBaseType}(), {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArrayPtr) + ), + {RetVectorType}.Create<{RetBaseType}>(1) + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr, mask: 1); + } + + + public void RunMaskingZeroScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunMaskingZeroScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArrayPtr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1.As{RetBaseType}(), {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArrayPtr) + ), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr, mask: 0); + } + + public void RunBroadcastAndMaskingScenario() + { + TestLibrary.TestFramework.BeginScenario(nameof(RunBroadcastAndMaskingScenario)); + + var op1 = Unsafe.Read<{Op1VectorType}<{Op1BaseType}>>(_dataTable.inArrayPtr); + + var result = {RetVectorType}.ConditionalSelect( + {RetVectorType}.Equals<{RetBaseType}>(op1.As{RetBaseType}(), {RetVectorType}<{RetBaseType}>.Zero), + {Isa}.{Method}( + {Op1VectorType}.Create<{Op1BaseType}>(Unsafe.Read<{Op1BaseType}>(_dataTable.inArrayPtr)) + ), + {RetVectorType}<{RetBaseType}>.Zero + ); + + Unsafe.Write(_dataTable.outArrayPtr, result); + ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr, isBroadcast: true, mask: 0); + } + public void RunLclVarScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead)); @@ -227,7 +306,7 @@ namespace JIT.HardwareIntrinsics.X86 } } - private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, [CallerMemberName] string method = "") + private void ValidateResult({Op1VectorType}<{Op1BaseType}> op1, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; @@ -235,10 +314,10 @@ namespace JIT.HardwareIntrinsics.X86 Unsafe.WriteUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), op1); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, outArray, method); + ValidateResult(inArray1, outArray, isBroadcast, mask, method); } - private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "") + private void ValidateResult(void* op1, void* result, bool isBroadcast = false, {RetBaseType}? mask = null, [CallerMemberName] string method = "") { {Op1BaseType}[] inArray1 = new {Op1BaseType}[Op1ElementCount]; {RetBaseType}[] outArray = new {RetBaseType}[RetElementCount]; @@ -246,13 +325,18 @@ namespace JIT.HardwareIntrinsics.X86 Unsafe.CopyBlockUnaligned(ref Unsafe.As<{Op1BaseType}, byte>(ref inArray1[0]), ref Unsafe.AsRef(op1), (uint)Unsafe.SizeOf<{Op1VectorType}<{Op1BaseType}>>()); Unsafe.CopyBlockUnaligned(ref Unsafe.As<{RetBaseType}, byte>(ref outArray[0]), ref Unsafe.AsRef(result), (uint)Unsafe.SizeOf<{RetVectorType}<{RetBaseType}>>()); - ValidateResult(inArray1, outArray, method); + ValidateResult(inArray1, outArray, isBroadcast, mask, method); } - private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, [CallerMemberName] string method = "") + private void ValidateResult({Op1BaseType}[] firstOp, {RetBaseType}[] result, bool isBroadcast, {RetBaseType}? mask, [CallerMemberName] string method = "") { bool succeeded = true; + if (isBroadcast) + { + firstOp.AsSpan().Fill(firstOp[0]); + } + {TemplateValidationLogic} if (!succeeded) diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs b/src/tests/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs index f49aa9dca521..e5dcc90c9db3 100644 --- a/src/tests/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs +++ b/src/tests/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; [assembly:Xunit.ActiveIssue("https://github.com/dotnet/runtime/issues/75767", typeof(TestLibrary.PlatformDetection), nameof(TestLibrary.PlatformDetection.IsMonoLLVMAOT))] +[assembly:Xunit.ActiveIssue("https://github.com/dotnet/runtime/issues/102150", typeof(TestLibrary.PlatformDetection), nameof(TestLibrary.PlatformDetection.IsMonoFULLAOT))] namespace JIT.HardwareIntrinsics.X86._Sse2 { public static partial class Program diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj b/src/tests/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj index 6a121d1f87d5..dbe58f761ca4 100644 --- a/src/tests/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj +++ b/src/tests/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj @@ -2,6 +2,8 @@ X86_Sse2_r true + + true Embedded diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj b/src/tests/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj index 9fa0b5774cae..0a8a0a8357b6 100644 --- a/src/tests/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj +++ b/src/tests/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj @@ -2,6 +2,8 @@ X86_Sse2_ro true + + true Embedded diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/ConvDLL.ilproj b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/ConvDLL.ilproj index 374da69e0fde..3850f8216c86 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/ConvDLL.ilproj +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/ConvDLL.ilproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcs.cs b/src/tests/JIT/Methodical/Arrays/lcs/lcs.cs index c61ef112134d..f2fa4b0ff888 100644 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcs.cs +++ b/src/tests/JIT/Methodical/Arrays/lcs/lcs.cs @@ -84,6 +84,7 @@ private static void findLCS(int[,,,] c, int[,,,] b, char[][] seq, int[] len) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Console.WriteLine("Test searches for longest common subsequence of 4 strings\n\n"); diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcs2.cs b/src/tests/JIT/Methodical/Arrays/lcs/lcs2.cs index cfe3cc8e4626..2a39785a207e 100644 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcs2.cs +++ b/src/tests/JIT/Methodical/Arrays/lcs/lcs2.cs @@ -84,6 +84,7 @@ private static void findLCS(ref int[][][][] c, ref int[][][][] b, ref char[][] s } [Fact] + [SkipOnCoreClr("This test is not compatible with GCStress.", RuntimeTestModes.AnyGCStress)] public static int TestEntryPoint() { Console.WriteLine("Test searches for longest common subsequence of 4 strings\n\n"); diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcs2_d.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcs2_d.csproj deleted file mode 100644 index 2b819bbe50da..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcs2_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Full - False - true - true - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcs2_do.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcs2_do.csproj deleted file mode 100644 index 2b3163667b7c..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcs2_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Full - True - true - true - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcs2_r.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcs2_r.csproj deleted file mode 100644 index c2809bcaed71..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcs2_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - None - False - true - true - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcs2_ro.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcs2_ro.csproj deleted file mode 100644 index 2f3e9fb863f9..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcs2_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - None - True - true - true - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcs_lcs_d.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcs_lcs_d.csproj deleted file mode 100644 index 1cf5fa05ed4e..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcs_lcs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcs_lcs_do.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcs_lcs_do.csproj deleted file mode 100644 index 8523d170b698..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcs_lcs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcs_lcs_r.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcs_lcs_r.csproj deleted file mode 100644 index 421d13320872..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcs_lcs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcs_lcs_ro.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcs_lcs_ro.csproj deleted file mode 100644 index 1658068ca8c2..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcs_lcs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsbas.cs b/src/tests/JIT/Methodical/Arrays/lcs/lcsbas.cs index 5c2eeb772136..4b0a2b8872cb 100644 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsbas.cs +++ b/src/tests/JIT/Methodical/Arrays/lcs/lcsbas.cs @@ -108,6 +108,7 @@ private static void findLCS(int[,,,] c, int[,,,] b, char[][] seq, int[] len) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Console.WriteLine("Test searches for longest common subsequence of 4 strings\n\n"); diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsbas_d.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsbas_d.csproj deleted file mode 100644 index 0e9f76de5382..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsbas_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsbas_do.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsbas_do.csproj deleted file mode 100644 index 1981cc9bb00d..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsbas_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsbas_r.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsbas_r.csproj deleted file mode 100644 index 7f9ef6e0aacc..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsbas_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsbas_ro.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsbas_ro.csproj deleted file mode 100644 index 3cc2117f7ce6..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsbas_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsbox_d.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsbox_d.csproj deleted file mode 100644 index 97b05853f1d5..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsbox_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsbox_do.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsbox_do.csproj deleted file mode 100644 index adf15757935b..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsbox_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsbox_r.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsbox_r.csproj deleted file mode 100644 index a73777348a41..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsbox_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsbox_ro.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsbox_ro.csproj deleted file mode 100644 index 8447615d9efa..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsbox_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsmax.cs b/src/tests/JIT/Methodical/Arrays/lcs/lcsmax.cs index 875bc8f6eaae..efcd06a9356f 100644 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsmax.cs +++ b/src/tests/JIT/Methodical/Arrays/lcs/lcsmax.cs @@ -89,6 +89,7 @@ private static void findLCS(int[,,,,,,,] c, int[,,,,,,,] b, char[][] seq, int[] } [Fact] + [OuterLoop] public static int TestEntryPoint() { Console.WriteLine("Test searches for longest common subsequence of 8 strings\n\n"); diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsmax_d.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsmax_d.csproj deleted file mode 100644 index e6bbe6c02995..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsmax_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsmax_do.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsmax_do.csproj deleted file mode 100644 index 0a019dbbc7b9..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsmax_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsmax_r.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsmax_r.csproj deleted file mode 100644 index 1e17a021ce43..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsmax_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsmax_ro.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsmax_ro.csproj deleted file mode 100644 index 0e0ceee089fe..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsmax_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsmixed_d.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsmixed_d.csproj deleted file mode 100644 index 9d0713c333c1..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsmixed_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsmixed_do.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsmixed_do.csproj deleted file mode 100644 index d44ee7bc77e6..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsmixed_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsmixed_r.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsmixed_r.csproj deleted file mode 100644 index d33f975222bd..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsmixed_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsmixed_ro.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsmixed_ro.csproj deleted file mode 100644 index 045eebc682c1..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsmixed_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsval.cs b/src/tests/JIT/Methodical/Arrays/lcs/lcsval.cs index cebc53e7aaca..8b95492b4f2d 100644 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsval.cs +++ b/src/tests/JIT/Methodical/Arrays/lcs/lcsval.cs @@ -89,6 +89,7 @@ private static void findLCS(Data[,,,] mtx, char[][] seq, int[] len) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Console.WriteLine("Test searches for longest common subsequence of 4 strings\n\n"); diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsval_d.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsval_d.csproj deleted file mode 100644 index 256916584879..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsval_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsval_do.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsval_do.csproj deleted file mode 100644 index 0860ba2ca125..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsval_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsval_r.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsval_r.csproj deleted file mode 100644 index 224885505dec..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsval_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsval_ro.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsval_ro.csproj deleted file mode 100644 index bd95a12e7a8f..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsval_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox.cs b/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox.cs index 4653fcc67d29..ca03f1c562ba 100644 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox.cs +++ b/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox.cs @@ -107,6 +107,7 @@ private static void findLCS(object[,,,] mtx, char[][] seq, int[] len) } [Fact] + [SkipOnCoreClr("This test is not compatible with GCStress.", RuntimeTestModes.AnyGCStress)] public static int TestEntryPoint() { Console.WriteLine("Test searches for longest common subsequence of 4 strings\n\n"); diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox_d.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox_d.csproj deleted file mode 100644 index b91be94a0d25..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - true - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox_do.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox_do.csproj deleted file mode 100644 index 9a09a4ec43fe..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - true - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox_r.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox_r.csproj deleted file mode 100644 index 410d2bc367b7..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - true - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox_ro.csproj b/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox_ro.csproj deleted file mode 100644 index e667b971bb03..000000000000 --- a/src/tests/JIT/Methodical/Arrays/lcs/lcsvalbox_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - true - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/misc/IndexingSideEffects.csproj b/src/tests/JIT/Methodical/Arrays/misc/IndexingSideEffects.csproj deleted file mode 100644 index 501217e4d868..000000000000 --- a/src/tests/JIT/Methodical/Arrays/misc/IndexingSideEffects.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/misc/arrres.cs b/src/tests/JIT/Methodical/Arrays/misc/arrres.cs index 4d3d40874de1..64391cf0feae 100644 --- a/src/tests/JIT/Methodical/Arrays/misc/arrres.cs +++ b/src/tests/JIT/Methodical/Arrays/misc/arrres.cs @@ -35,6 +35,7 @@ internal virtual void CheckValid() } [Fact] + [OuterLoop] public static void TestEntryPoint() { Test1(); diff --git a/src/tests/JIT/Methodical/Arrays/misc/arrres_il_r.ilproj b/src/tests/JIT/Methodical/Arrays/misc/arrres_il_r.ilproj index e0dae15c09d4..ed015073b43d 100644 --- a/src/tests/JIT/Methodical/Arrays/misc/arrres_il_r.ilproj +++ b/src/tests/JIT/Methodical/Arrays/misc/arrres_il_r.ilproj @@ -7,7 +7,6 @@ PdbOnly true - true diff --git a/src/tests/JIT/Methodical/Arrays/misc/gcarr.cs b/src/tests/JIT/Methodical/Arrays/misc/gcarr.cs index f9bc806adc9a..637fe82a3f90 100644 --- a/src/tests/JIT/Methodical/Arrays/misc/gcarr.cs +++ b/src/tests/JIT/Methodical/Arrays/misc/gcarr.cs @@ -16,6 +16,7 @@ internal virtual void CheckValid() } [Fact] + [OuterLoop] public static void TestEntryPoint() { Test[] arr = new Test[97]; diff --git a/src/tests/JIT/Methodical/Arrays/misc/gcarr_d.csproj b/src/tests/JIT/Methodical/Arrays/misc/gcarr_d.csproj deleted file mode 100644 index 8825e61226e4..000000000000 --- a/src/tests/JIT/Methodical/Arrays/misc/gcarr_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/misc/gcarr_do.csproj b/src/tests/JIT/Methodical/Arrays/misc/gcarr_do.csproj deleted file mode 100644 index 5056e36523e8..000000000000 --- a/src/tests/JIT/Methodical/Arrays/misc/gcarr_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/misc/gcarr_il_d.ilproj b/src/tests/JIT/Methodical/Arrays/misc/gcarr_il_d.ilproj index 72bc7896bbea..63e30b3e7640 100644 --- a/src/tests/JIT/Methodical/Arrays/misc/gcarr_il_d.ilproj +++ b/src/tests/JIT/Methodical/Arrays/misc/gcarr_il_d.ilproj @@ -1,8 +1,6 @@ 1 - - true Full diff --git a/src/tests/JIT/Methodical/Arrays/misc/gcarr_il_r.ilproj b/src/tests/JIT/Methodical/Arrays/misc/gcarr_il_r.ilproj index 34514571e8d1..95bbbf43046f 100644 --- a/src/tests/JIT/Methodical/Arrays/misc/gcarr_il_r.ilproj +++ b/src/tests/JIT/Methodical/Arrays/misc/gcarr_il_r.ilproj @@ -1,8 +1,4 @@ - - - true - PdbOnly diff --git a/src/tests/JIT/Methodical/Arrays/misc/gcarr_r.csproj b/src/tests/JIT/Methodical/Arrays/misc/gcarr_r.csproj deleted file mode 100644 index 12d1d42fe3ae..000000000000 --- a/src/tests/JIT/Methodical/Arrays/misc/gcarr_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/misc/gcarr_ro.csproj b/src/tests/JIT/Methodical/Arrays/misc/gcarr_ro.csproj deleted file mode 100644 index 09c6e63233b3..000000000000 --- a/src/tests/JIT/Methodical/Arrays/misc/gcarr_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/misc/selfref.cs b/src/tests/JIT/Methodical/Arrays/misc/selfref.cs index 3ecdb648e165..fb8f85c0f259 100644 --- a/src/tests/JIT/Methodical/Arrays/misc/selfref.cs +++ b/src/tests/JIT/Methodical/Arrays/misc/selfref.cs @@ -9,6 +9,7 @@ namespace GCTest_selfref_cs public class Test { [Fact] + [OuterLoop] public static int TestEntryPoint() { object aref = null; diff --git a/src/tests/JIT/Methodical/Arrays/misc/selfref_d.csproj b/src/tests/JIT/Methodical/Arrays/misc/selfref_d.csproj deleted file mode 100644 index 8f69ff79d00c..000000000000 --- a/src/tests/JIT/Methodical/Arrays/misc/selfref_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/misc/selfref_do.csproj b/src/tests/JIT/Methodical/Arrays/misc/selfref_do.csproj deleted file mode 100644 index f3bc3de00dcf..000000000000 --- a/src/tests/JIT/Methodical/Arrays/misc/selfref_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/misc/selfref_r.csproj b/src/tests/JIT/Methodical/Arrays/misc/selfref_r.csproj deleted file mode 100644 index f7edda42ad57..000000000000 --- a/src/tests/JIT/Methodical/Arrays/misc/selfref_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Arrays/misc/selfref_ro.csproj b/src/tests/JIT/Methodical/Arrays/misc/selfref_ro.csproj deleted file mode 100644 index 394cbcfd1a98..000000000000 --- a/src/tests/JIT/Methodical/Arrays/misc/selfref_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i4/i4.cs b/src/tests/JIT/Methodical/AsgOp/i4/i4.cs index fb4dda2b8174..b7364f52fc7b 100644 --- a/src/tests/JIT/Methodical/AsgOp/i4/i4.cs +++ b/src/tests/JIT/Methodical/AsgOp/i4/i4.cs @@ -670,6 +670,7 @@ private static int f109(int x, int y) [Fact] + [OuterLoop] public static int TestEntryPoint() { int x; diff --git a/src/tests/JIT/Methodical/AsgOp/i4/i4_cs_d.csproj b/src/tests/JIT/Methodical/AsgOp/i4/i4_cs_d.csproj deleted file mode 100644 index 05c0eee6054e..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i4/i4_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i4/i4_cs_do.csproj b/src/tests/JIT/Methodical/AsgOp/i4/i4_cs_do.csproj deleted file mode 100644 index ba70fafb90d0..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i4/i4_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i4/i4_cs_r.csproj b/src/tests/JIT/Methodical/AsgOp/i4/i4_cs_r.csproj deleted file mode 100644 index 010aada021b8..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i4/i4_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i4/i4_cs_ro.csproj b/src/tests/JIT/Methodical/AsgOp/i4/i4_cs_ro.csproj deleted file mode 100644 index 70647bb03920..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i4/i4_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i4/i4flat.cs b/src/tests/JIT/Methodical/AsgOp/i4/i4flat.cs index c1342e077a4e..5820cee0c3f6 100644 --- a/src/tests/JIT/Methodical/AsgOp/i4/i4flat.cs +++ b/src/tests/JIT/Methodical/AsgOp/i4/i4flat.cs @@ -9,6 +9,7 @@ namespace Test_i4flat_cs public class test { [Fact] + [OuterLoop] public static int TestEntryPoint() { int x; diff --git a/src/tests/JIT/Methodical/AsgOp/i4/i4flat_cs_d.csproj b/src/tests/JIT/Methodical/AsgOp/i4/i4flat_cs_d.csproj deleted file mode 100644 index 0fc81d87794e..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i4/i4flat_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i4/i4flat_cs_do.csproj b/src/tests/JIT/Methodical/AsgOp/i4/i4flat_cs_do.csproj deleted file mode 100644 index b84a9fa27477..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i4/i4flat_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i4/i4flat_cs_r.csproj b/src/tests/JIT/Methodical/AsgOp/i4/i4flat_cs_r.csproj deleted file mode 100644 index ee8dfddaef6a..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i4/i4flat_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i4/i4flat_cs_ro.csproj b/src/tests/JIT/Methodical/AsgOp/i4/i4flat_cs_ro.csproj deleted file mode 100644 index 3d9f0176ec14..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i4/i4flat_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i8/i8.cs b/src/tests/JIT/Methodical/AsgOp/i8/i8.cs index 329bb3784c9c..6aba9b319ffb 100644 --- a/src/tests/JIT/Methodical/AsgOp/i8/i8.cs +++ b/src/tests/JIT/Methodical/AsgOp/i8/i8.cs @@ -670,6 +670,7 @@ private static Int64 f109(Int64 x, Int64 y) [Fact] + [OuterLoop] public static int TestEntryPoint() { Int64 x; @@ -1216,60 +1217,60 @@ public static int TestEntryPoint() } /* - x = f60(-10, 4); - if (x != -671088640) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); - Console.WriteLine("f60 x <<= x + y failed."); - Console.WriteLine("x: {0}, \texpected: -671088640", x); - pass = false; - } - - x = f61(-10, 4); - if (x != -2621440) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); - Console.WriteLine("f61 x <<= x - y failed."); - Console.WriteLine("x: {0}, \texpected: -2621440", x); - pass = false; - } - - x = f62(-10, 4); - if (x != -167772160) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); - Console.WriteLine("f62 x <<= x * y failed."); - Console.WriteLine("x: {0}, \texpected: -167772160", x); - pass = false; - } - - x = f63(-10, 4); - if (x != -2147483648) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); - Console.WriteLine("f63 x <<= x / y failed."); - Console.WriteLine("x: {0}, \texpected: -2147483648", x); - pass = false; - } - - x = f64(-10, 4); - if (x != -2147483648) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); - Console.WriteLine("f64 x <<= x % y failed."); - Console.WriteLine("x: {0}, \texpected: -2147483648", x); - pass = false; - } - - x = f65(-10, 4); - if (x != -10) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); - Console.WriteLine("f65 x <<= x << y failed."); - Console.WriteLine("x: {0}, \texpected: -10", x); - pass = false; - } - */ + x = f60(-10, 4); + if (x != -671088640) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); + Console.WriteLine("f60 x <<= x + y failed."); + Console.WriteLine("x: {0}, \texpected: -671088640", x); + pass = false; + } + + x = f61(-10, 4); + if (x != -2621440) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); + Console.WriteLine("f61 x <<= x - y failed."); + Console.WriteLine("x: {0}, \texpected: -2621440", x); + pass = false; + } + + x = f62(-10, 4); + if (x != -167772160) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); + Console.WriteLine("f62 x <<= x * y failed."); + Console.WriteLine("x: {0}, \texpected: -167772160", x); + pass = false; + } + + x = f63(-10, 4); + if (x != -2147483648) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); + Console.WriteLine("f63 x <<= x / y failed."); + Console.WriteLine("x: {0}, \texpected: -2147483648", x); + pass = false; + } + + x = f64(-10, 4); + if (x != -2147483648) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); + Console.WriteLine("f64 x <<= x % y failed."); + Console.WriteLine("x: {0}, \texpected: -2147483648", x); + pass = false; + } + + x = f65(-10, 4); + if (x != -10) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); + Console.WriteLine("f65 x <<= x << y failed."); + Console.WriteLine("x: {0}, \texpected: -10", x); + pass = false; + } + */ x = f66(-10, 4); if (x != 0) @@ -1290,24 +1291,24 @@ public static int TestEntryPoint() } /* - x = f68(-10, 4); - if (x != -2621440) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); - Console.WriteLine("f68 x <<= x ^ y failed."); - Console.WriteLine("x: {0}, \texpected: -2621440", x); - pass = false; - } - - x = f69(-10, 4); - if (x != -41943040) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); - Console.WriteLine("f69 x <<= x | y failed."); - Console.WriteLine("x: {0}, \texpected: -41943040", x); - pass = false; - } - */ + x = f68(-10, 4); + if (x != -2621440) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); + Console.WriteLine("f68 x <<= x ^ y failed."); + Console.WriteLine("x: {0}, \texpected: -2621440", x); + pass = false; + } + + x = f69(-10, 4); + if (x != -41943040) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); + Console.WriteLine("f69 x <<= x | y failed."); + Console.WriteLine("x: {0}, \texpected: -41943040", x); + pass = false; + } + */ x = f70(-10, 4); if (x != -1) @@ -1355,15 +1356,15 @@ public static int TestEntryPoint() } /* - x = f75(-10, 4); - if (x != -10) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); - Console.WriteLine("f75 x >>= x << y failed."); - Console.WriteLine("x: {0}, \texpected: -10", x); - pass = false; - } - */ + x = f75(-10, 4); + if (x != -10) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4."); + Console.WriteLine("f75 x >>= x << y failed."); + Console.WriteLine("x: {0}, \texpected: -10", x); + pass = false; + } + */ x = f76(-10, 4); if (x != -1) diff --git a/src/tests/JIT/Methodical/AsgOp/i8/i8_cs_d.csproj b/src/tests/JIT/Methodical/AsgOp/i8/i8_cs_d.csproj deleted file mode 100644 index 637e3cf56d1b..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i8/i8_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i8/i8_cs_do.csproj b/src/tests/JIT/Methodical/AsgOp/i8/i8_cs_do.csproj deleted file mode 100644 index 4a98a6bb5a2e..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i8/i8_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i8/i8_cs_r.csproj b/src/tests/JIT/Methodical/AsgOp/i8/i8_cs_r.csproj deleted file mode 100644 index d9f20b3c02c2..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i8/i8_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i8/i8_cs_ro.csproj b/src/tests/JIT/Methodical/AsgOp/i8/i8_cs_ro.csproj deleted file mode 100644 index 42d221b2eef5..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i8/i8_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i8/i8flat.cs b/src/tests/JIT/Methodical/AsgOp/i8/i8flat.cs index 9c8d0920e3dc..e93eff20e26d 100644 --- a/src/tests/JIT/Methodical/AsgOp/i8/i8flat.cs +++ b/src/tests/JIT/Methodical/AsgOp/i8/i8flat.cs @@ -9,6 +9,7 @@ namespace Test_i8flat_cs public class test { [Fact] + [OuterLoop] public static int TestEntryPoint() { Int64 x; @@ -680,69 +681,69 @@ public static int TestEntryPoint() y = 4; /* - x <<= (int)( x + y); - if (x != -671088640) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); - Console.WriteLine("x <<= (int)( x + y) failed.\nx: {0}, \texpected: -671088640\n", x); - pass = false; - } - - x = -10; - y = 4; - - x <<= (int)( x - y); - if (x != -2621440) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); - Console.WriteLine("x <<= (int)( x - y) failed.\nx: {0}, \texpected: -2621440\n", x); - pass = false; - } - - x = -10; - y = 4; - - x <<= (int)( x * y); - if (x != -167772160) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); - Console.WriteLine("x <<= (int)( x * y) failed.\nx: {0}, \texpected: -167772160\n", x); - pass = false; - } - - x = -10; - y = 4; - - x <<= (int)( x / y); - if (x != -2147483648) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); - Console.WriteLine("x <<= (int)( x / y) failed.\nx: {0}, \texpected: -2147483648\n", x); - pass = false; - } - - x = -10; - y = 4; - - x <<= (int)( x % y); - if (x != -2147483648) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); - Console.WriteLine("x <<= (int)( x % y) failed.\nx: {0}, \texpected: -2147483648\n", x); - pass = false; - } - - x = -10; - y = 4; - - x <<= (int)( x << (int)y); - if (x != -10) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); - Console.WriteLine("x <<= (int)( x << (int)y) failed.\nx: {0}, \texpected: -10\n", x); - pass = false; - } - */ + x <<= (int)( x + y); + if (x != -671088640) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); + Console.WriteLine("x <<= (int)( x + y) failed.\nx: {0}, \texpected: -671088640\n", x); + pass = false; + } + + x = -10; + y = 4; + + x <<= (int)( x - y); + if (x != -2621440) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); + Console.WriteLine("x <<= (int)( x - y) failed.\nx: {0}, \texpected: -2621440\n", x); + pass = false; + } + + x = -10; + y = 4; + + x <<= (int)( x * y); + if (x != -167772160) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); + Console.WriteLine("x <<= (int)( x * y) failed.\nx: {0}, \texpected: -167772160\n", x); + pass = false; + } + + x = -10; + y = 4; + + x <<= (int)( x / y); + if (x != -2147483648) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); + Console.WriteLine("x <<= (int)( x / y) failed.\nx: {0}, \texpected: -2147483648\n", x); + pass = false; + } + + x = -10; + y = 4; + + x <<= (int)( x % y); + if (x != -2147483648) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); + Console.WriteLine("x <<= (int)( x % y) failed.\nx: {0}, \texpected: -2147483648\n", x); + pass = false; + } + + x = -10; + y = 4; + + x <<= (int)( x << (int)y); + if (x != -10) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); + Console.WriteLine("x <<= (int)( x << (int)y) failed.\nx: {0}, \texpected: -10\n", x); + pass = false; + } + */ x = -10; y = 4; @@ -770,25 +771,25 @@ public static int TestEntryPoint() y = 4; /* - x <<= (int)( x ^ y); - if (x != -2621440) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); - Console.WriteLine("x <<= (int)( x ^ y) failed.\nx: {0}, \texpected: -2621440\n", x); - pass = false; - } + x <<= (int)( x ^ y); + if (x != -2621440) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); + Console.WriteLine("x <<= (int)( x ^ y) failed.\nx: {0}, \texpected: -2621440\n", x); + pass = false; + } - x = -10; - y = 4; + x = -10; + y = 4; - x <<= (int)( x | y); - if (x != -41943040) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); - Console.WriteLine("x <<= (int)( x | y) failed.\nx: {0}, \texpected: -41943040\n", x); - pass = false; - } - */ + x <<= (int)( x | y); + if (x != -41943040) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); + Console.WriteLine("x <<= (int)( x | y) failed.\nx: {0}, \texpected: -41943040\n", x); + pass = false; + } + */ x = -10; y = 4; @@ -849,14 +850,14 @@ public static int TestEntryPoint() y = 4; /* - x >>= (int)( x << (int)y); - if (x != -10) - { - Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); - Console.WriteLine("x >>= (int)( x << (int)y) failed.\nx: {0}, \texpected: -10\n", x); - pass = false; - } - */ + x >>= (int)( x << (int)y); + if (x != -10) + { + Console.WriteLine("\nInitial parameters: x is -10 and y is 4"); + Console.WriteLine("x >>= (int)( x << (int)y) failed.\nx: {0}, \texpected: -10\n", x); + pass = false; + } + */ x = -10; y = 4; diff --git a/src/tests/JIT/Methodical/AsgOp/i8/i8flat_cs_d.csproj b/src/tests/JIT/Methodical/AsgOp/i8/i8flat_cs_d.csproj deleted file mode 100644 index b87f2512a812..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i8/i8flat_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i8/i8flat_cs_do.csproj b/src/tests/JIT/Methodical/AsgOp/i8/i8flat_cs_do.csproj deleted file mode 100644 index 1b29e1eb7130..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i8/i8flat_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i8/i8flat_cs_r.csproj b/src/tests/JIT/Methodical/AsgOp/i8/i8flat_cs_r.csproj deleted file mode 100644 index 5dc888527a93..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i8/i8flat_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/i8/i8flat_cs_ro.csproj b/src/tests/JIT/Methodical/AsgOp/i8/i8flat_cs_ro.csproj deleted file mode 100644 index 55ff13fc8d66..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/i8/i8flat_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r4/r4.cs b/src/tests/JIT/Methodical/AsgOp/r4/r4.cs index 5af3f018592d..8639f1d67849 100644 --- a/src/tests/JIT/Methodical/AsgOp/r4/r4.cs +++ b/src/tests/JIT/Methodical/AsgOp/r4/r4.cs @@ -186,6 +186,7 @@ private static float f44(float x, float y) [Fact] + [OuterLoop] public static int TestEntryPoint() { float x; diff --git a/src/tests/JIT/Methodical/AsgOp/r4/r4_cs_d.csproj b/src/tests/JIT/Methodical/AsgOp/r4/r4_cs_d.csproj deleted file mode 100644 index 9f6c87a0df01..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r4/r4_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r4/r4_cs_do.csproj b/src/tests/JIT/Methodical/AsgOp/r4/r4_cs_do.csproj deleted file mode 100644 index e7bad46b0841..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r4/r4_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r4/r4_cs_r.csproj b/src/tests/JIT/Methodical/AsgOp/r4/r4_cs_r.csproj deleted file mode 100644 index 53a19494c29c..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r4/r4_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r4/r4_cs_ro.csproj b/src/tests/JIT/Methodical/AsgOp/r4/r4_cs_ro.csproj deleted file mode 100644 index e718279dadde..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r4/r4_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r4/r4flat.cs b/src/tests/JIT/Methodical/AsgOp/r4/r4flat.cs index 407bac354fb4..f07242ed27da 100644 --- a/src/tests/JIT/Methodical/AsgOp/r4/r4flat.cs +++ b/src/tests/JIT/Methodical/AsgOp/r4/r4flat.cs @@ -9,6 +9,7 @@ namespace Test_r4flat_cs public class test { [Fact] + [OuterLoop] public static int TestEntryPoint() { float x; diff --git a/src/tests/JIT/Methodical/AsgOp/r4/r4flat_cs_d.csproj b/src/tests/JIT/Methodical/AsgOp/r4/r4flat_cs_d.csproj deleted file mode 100644 index 17c9ad7d050c..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r4/r4flat_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r4/r4flat_cs_do.csproj b/src/tests/JIT/Methodical/AsgOp/r4/r4flat_cs_do.csproj deleted file mode 100644 index ccabbdc8860a..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r4/r4flat_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r4/r4flat_cs_r.csproj b/src/tests/JIT/Methodical/AsgOp/r4/r4flat_cs_r.csproj deleted file mode 100644 index c3895441b31c..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r4/r4flat_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r4/r4flat_cs_ro.csproj b/src/tests/JIT/Methodical/AsgOp/r4/r4flat_cs_ro.csproj deleted file mode 100644 index 454bcec299de..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r4/r4flat_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r8/r8.cs b/src/tests/JIT/Methodical/AsgOp/r8/r8.cs index b922a4584722..62abd5819d24 100644 --- a/src/tests/JIT/Methodical/AsgOp/r8/r8.cs +++ b/src/tests/JIT/Methodical/AsgOp/r8/r8.cs @@ -160,6 +160,7 @@ private static double f44(double x, double y) [Fact] + [OuterLoop] public static int TestEntryPoint() { double x; diff --git a/src/tests/JIT/Methodical/AsgOp/r8/r8_cs_d.csproj b/src/tests/JIT/Methodical/AsgOp/r8/r8_cs_d.csproj deleted file mode 100644 index 55b5a0fd8752..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r8/r8_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r8/r8_cs_do.csproj b/src/tests/JIT/Methodical/AsgOp/r8/r8_cs_do.csproj deleted file mode 100644 index 5b2b328e028d..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r8/r8_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r8/r8_cs_r.csproj b/src/tests/JIT/Methodical/AsgOp/r8/r8_cs_r.csproj deleted file mode 100644 index 6bf2b5c2c0d0..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r8/r8_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r8/r8_cs_ro.csproj b/src/tests/JIT/Methodical/AsgOp/r8/r8_cs_ro.csproj deleted file mode 100644 index b8bcdae4a3b3..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r8/r8_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r8/r8flat.cs b/src/tests/JIT/Methodical/AsgOp/r8/r8flat.cs index 589832c58ab8..344fdc20cc2c 100644 --- a/src/tests/JIT/Methodical/AsgOp/r8/r8flat.cs +++ b/src/tests/JIT/Methodical/AsgOp/r8/r8flat.cs @@ -9,6 +9,7 @@ namespace Test_r8flat_cs public class test { [Fact] + [OuterLoop] public static int TestEntryPoint() { double x; diff --git a/src/tests/JIT/Methodical/AsgOp/r8/r8flat_cs_d.csproj b/src/tests/JIT/Methodical/AsgOp/r8/r8flat_cs_d.csproj deleted file mode 100644 index 6a5ab9d69119..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r8/r8flat_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r8/r8flat_cs_do.csproj b/src/tests/JIT/Methodical/AsgOp/r8/r8flat_cs_do.csproj deleted file mode 100644 index 26f4d51aa87f..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r8/r8flat_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r8/r8flat_cs_r.csproj b/src/tests/JIT/Methodical/AsgOp/r8/r8flat_cs_r.csproj deleted file mode 100644 index a3b191fe8884..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r8/r8flat_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/AsgOp/r8/r8flat_cs_ro.csproj b/src/tests/JIT/Methodical/AsgOp/r8/r8flat_cs_ro.csproj deleted file mode 100644 index e05fc3eb00db..000000000000 --- a/src/tests/JIT/Methodical/AsgOp/r8/r8flat_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/boxunbox/BoxPatternMatchAndSideEffects.cs b/src/tests/JIT/Methodical/Boxing/boxunbox/BoxPatternMatchAndSideEffects.cs index 7437bd7d7a32..a4c09ddabc12 100644 --- a/src/tests/JIT/Methodical/Boxing/boxunbox/BoxPatternMatchAndSideEffects.cs +++ b/src/tests/JIT/Methodical/Boxing/boxunbox/BoxPatternMatchAndSideEffects.cs @@ -8,6 +8,7 @@ public class BoxPatternMatchAndSideEffects { [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/90427", typeof(TestLibrary.PlatformDetection), nameof(TestLibrary.PlatformDetection.IsMonoMINIFULLAOT))] public static int TestEntryPoint() { if (!Problem(new Struct[0])) diff --git a/src/tests/JIT/Methodical/Boxing/boxunbox/BoxPatternMatchAndSideEffects.csproj b/src/tests/JIT/Methodical/Boxing/boxunbox/BoxPatternMatchAndSideEffects.csproj deleted file mode 100644 index 7df006c9f1a4..000000000000 --- a/src/tests/JIT/Methodical/Boxing/boxunbox/BoxPatternMatchAndSideEffects.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - PdbOnly - - true - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/callconv/instance.cs b/src/tests/JIT/Methodical/Boxing/callconv/instance.cs index bc32f7d7b115..69f035950619 100644 --- a/src/tests/JIT/Methodical/Boxing/callconv/instance.cs +++ b/src/tests/JIT/Methodical/Boxing/callconv/instance.cs @@ -51,6 +51,7 @@ public object Print() } [Fact] + [OuterLoop] public static void TestEntryPoint() { Test test = new Test(20.0d); diff --git a/src/tests/JIT/Methodical/Boxing/callconv/instance_cs_d.csproj b/src/tests/JIT/Methodical/Boxing/callconv/instance_cs_d.csproj deleted file mode 100644 index dc79a6298a6b..000000000000 --- a/src/tests/JIT/Methodical/Boxing/callconv/instance_cs_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - Full - False - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/callconv/instance_cs_do.csproj b/src/tests/JIT/Methodical/Boxing/callconv/instance_cs_do.csproj deleted file mode 100644 index 95d46de5a917..000000000000 --- a/src/tests/JIT/Methodical/Boxing/callconv/instance_cs_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - - Full - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/callconv/instance_cs_r.csproj b/src/tests/JIT/Methodical/Boxing/callconv/instance_cs_r.csproj deleted file mode 100644 index 732c284a3fba..000000000000 --- a/src/tests/JIT/Methodical/Boxing/callconv/instance_cs_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - None - False - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/callconv/instance_cs_ro.csproj b/src/tests/JIT/Methodical/Boxing/callconv/instance_cs_ro.csproj deleted file mode 100644 index cd10ba24469e..000000000000 --- a/src/tests/JIT/Methodical/Boxing/callconv/instance_cs_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - - None - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/functional/fibo.cs b/src/tests/JIT/Methodical/Boxing/functional/fibo.cs index df61d4a7206a..81cf72b47649 100644 --- a/src/tests/JIT/Methodical/Boxing/functional/fibo.cs +++ b/src/tests/JIT/Methodical/Boxing/functional/fibo.cs @@ -37,6 +37,7 @@ protected object Fibonacci2(object num, object flag) } [Fact] + [OuterLoop] public static void TestEntryPoint() { new Test().Fibonacci(20, true); diff --git a/src/tests/JIT/Methodical/Boxing/functional/fibo_cs_d.csproj b/src/tests/JIT/Methodical/Boxing/functional/fibo_cs_d.csproj deleted file mode 100644 index 8e78a31860cc..000000000000 --- a/src/tests/JIT/Methodical/Boxing/functional/fibo_cs_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - - Full - False - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/functional/fibo_cs_do.csproj b/src/tests/JIT/Methodical/Boxing/functional/fibo_cs_do.csproj deleted file mode 100644 index c6e5894e8f56..000000000000 --- a/src/tests/JIT/Methodical/Boxing/functional/fibo_cs_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - Full - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/functional/fibo_cs_r.csproj b/src/tests/JIT/Methodical/Boxing/functional/fibo_cs_r.csproj deleted file mode 100644 index 1344fc8b7ca5..000000000000 --- a/src/tests/JIT/Methodical/Boxing/functional/fibo_cs_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - None - False - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/functional/fibo_cs_ro.csproj b/src/tests/JIT/Methodical/Boxing/functional/fibo_cs_ro.csproj deleted file mode 100644 index 331fa8188cc0..000000000000 --- a/src/tests/JIT/Methodical/Boxing/functional/fibo_cs_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - None - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/functional/sin.cs b/src/tests/JIT/Methodical/Boxing/functional/sin.cs index 10543b74a8eb..4401463b317f 100644 --- a/src/tests/JIT/Methodical/Boxing/functional/sin.cs +++ b/src/tests/JIT/Methodical/Boxing/functional/sin.cs @@ -54,6 +54,7 @@ protected static object mySin(object Angle) } [Fact] + [OuterLoop] public static int TestEntryPoint() { object i; diff --git a/src/tests/JIT/Methodical/Boxing/functional/sin_functional_cs_d.csproj b/src/tests/JIT/Methodical/Boxing/functional/sin_functional_cs_d.csproj deleted file mode 100644 index b3e917eaccce..000000000000 --- a/src/tests/JIT/Methodical/Boxing/functional/sin_functional_cs_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - Full - False - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/functional/sin_functional_cs_do.csproj b/src/tests/JIT/Methodical/Boxing/functional/sin_functional_cs_do.csproj deleted file mode 100644 index 01ce725db034..000000000000 --- a/src/tests/JIT/Methodical/Boxing/functional/sin_functional_cs_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - - Full - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/functional/sin_functional_cs_r.csproj b/src/tests/JIT/Methodical/Boxing/functional/sin_functional_cs_r.csproj deleted file mode 100644 index 06a6dfa4cc91..000000000000 --- a/src/tests/JIT/Methodical/Boxing/functional/sin_functional_cs_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - - None - False - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/functional/sin_functional_cs_ro.csproj b/src/tests/JIT/Methodical/Boxing/functional/sin_functional_cs_ro.csproj deleted file mode 100644 index 96c01ae763af..000000000000 --- a/src/tests/JIT/Methodical/Boxing/functional/sin_functional_cs_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - None - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/misc/enum.cs b/src/tests/JIT/Methodical/Boxing/misc/enum.cs index 76f4ebb4bff6..9d559f30577d 100644 --- a/src/tests/JIT/Methodical/Boxing/misc/enum.cs +++ b/src/tests/JIT/Methodical/Boxing/misc/enum.cs @@ -37,6 +37,7 @@ protected object Fibonacci2(object num, object flag) } [Fact] + [OuterLoop] public static void TestEntryPoint() { new Test().Fibonacci(20, ToPrintOrNotToPrint.Print); diff --git a/src/tests/JIT/Methodical/Boxing/misc/enum_cs_d.csproj b/src/tests/JIT/Methodical/Boxing/misc/enum_cs_d.csproj deleted file mode 100644 index fd9c03ea622b..000000000000 --- a/src/tests/JIT/Methodical/Boxing/misc/enum_cs_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/misc/enum_cs_do.csproj b/src/tests/JIT/Methodical/Boxing/misc/enum_cs_do.csproj deleted file mode 100644 index e1b38bf214f6..000000000000 --- a/src/tests/JIT/Methodical/Boxing/misc/enum_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/misc/enum_cs_r.csproj b/src/tests/JIT/Methodical/Boxing/misc/enum_cs_r.csproj deleted file mode 100644 index a2d1e4acff40..000000000000 --- a/src/tests/JIT/Methodical/Boxing/misc/enum_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/misc/enum_cs_ro.csproj b/src/tests/JIT/Methodical/Boxing/misc/enum_cs_ro.csproj deleted file mode 100644 index 65e012cfebb5..000000000000 --- a/src/tests/JIT/Methodical/Boxing/misc/enum_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/misc/nestval.cs b/src/tests/JIT/Methodical/Boxing/misc/nestval.cs index 4a266d2d2015..aa2798761761 100644 --- a/src/tests/JIT/Methodical/Boxing/misc/nestval.cs +++ b/src/tests/JIT/Methodical/Boxing/misc/nestval.cs @@ -50,6 +50,7 @@ protected object FibonacciImpl(object args) } [Fact] + [OuterLoop] public static void TestEntryPoint() { ArgInfo args = new ArgInfo(); diff --git a/src/tests/JIT/Methodical/Boxing/misc/nestval_cs_d.csproj b/src/tests/JIT/Methodical/Boxing/misc/nestval_cs_d.csproj deleted file mode 100644 index f0c9dd0c131b..000000000000 --- a/src/tests/JIT/Methodical/Boxing/misc/nestval_cs_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/misc/nestval_cs_do.csproj b/src/tests/JIT/Methodical/Boxing/misc/nestval_cs_do.csproj deleted file mode 100644 index ec86af7b4e7a..000000000000 --- a/src/tests/JIT/Methodical/Boxing/misc/nestval_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/misc/nestval_cs_r.csproj b/src/tests/JIT/Methodical/Boxing/misc/nestval_cs_r.csproj deleted file mode 100644 index 5c23363c8704..000000000000 --- a/src/tests/JIT/Methodical/Boxing/misc/nestval_cs_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/misc/nestval_cs_ro.csproj b/src/tests/JIT/Methodical/Boxing/misc/nestval_cs_ro.csproj deleted file mode 100644 index 107690f7f8b7..000000000000 --- a/src/tests/JIT/Methodical/Boxing/misc/nestval_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/misc/tailjump.cs b/src/tests/JIT/Methodical/Boxing/misc/tailjump.cs index 283b97542854..70bbb5023f37 100644 --- a/src/tests/JIT/Methodical/Boxing/misc/tailjump.cs +++ b/src/tests/JIT/Methodical/Boxing/misc/tailjump.cs @@ -30,6 +30,7 @@ protected object Fibonacci2(object num, object flag) } [Fact] + [OuterLoop] public static void TestEntryPoint() { new Test().Fibonacci(20, true); diff --git a/src/tests/JIT/Methodical/Boxing/misc/tailjump_cs_d.csproj b/src/tests/JIT/Methodical/Boxing/misc/tailjump_cs_d.csproj deleted file mode 100644 index 6e519b07e4e0..000000000000 --- a/src/tests/JIT/Methodical/Boxing/misc/tailjump_cs_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/misc/tailjump_cs_do.csproj b/src/tests/JIT/Methodical/Boxing/misc/tailjump_cs_do.csproj deleted file mode 100644 index 4c647e1e475d..000000000000 --- a/src/tests/JIT/Methodical/Boxing/misc/tailjump_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/misc/tailjump_cs_r.csproj b/src/tests/JIT/Methodical/Boxing/misc/tailjump_cs_r.csproj deleted file mode 100644 index 064190d32250..000000000000 --- a/src/tests/JIT/Methodical/Boxing/misc/tailjump_cs_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/misc/tailjump_cs_ro.csproj b/src/tests/JIT/Methodical/Boxing/misc/tailjump_cs_ro.csproj deleted file mode 100644 index d17cfa1f3290..000000000000 --- a/src/tests/JIT/Methodical/Boxing/misc/tailjump_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/misc/unusedindir.csproj b/src/tests/JIT/Methodical/Boxing/misc/unusedindir.csproj deleted file mode 100644 index 6bb31ca7e7ea..000000000000 --- a/src/tests/JIT/Methodical/Boxing/misc/unusedindir.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/morph/sin.cs b/src/tests/JIT/Methodical/Boxing/morph/sin.cs index f377e145f968..6bf7ff662d00 100644 --- a/src/tests/JIT/Methodical/Boxing/morph/sin.cs +++ b/src/tests/JIT/Methodical/Boxing/morph/sin.cs @@ -30,6 +30,7 @@ protected static object mySin(object Angle) } [Fact] + [OuterLoop] public static int TestEntryPoint() { object i; diff --git a/src/tests/JIT/Methodical/Boxing/morph/sin_morph_cs_d.csproj b/src/tests/JIT/Methodical/Boxing/morph/sin_morph_cs_d.csproj deleted file mode 100644 index 449344c35fb9..000000000000 --- a/src/tests/JIT/Methodical/Boxing/morph/sin_morph_cs_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - - Full - False - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/morph/sin_morph_cs_do.csproj b/src/tests/JIT/Methodical/Boxing/morph/sin_morph_cs_do.csproj deleted file mode 100644 index eff1294a83f2..000000000000 --- a/src/tests/JIT/Methodical/Boxing/morph/sin_morph_cs_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - Full - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/morph/sin_morph_cs_r.csproj b/src/tests/JIT/Methodical/Boxing/morph/sin_morph_cs_r.csproj deleted file mode 100644 index 06a6dfa4cc91..000000000000 --- a/src/tests/JIT/Methodical/Boxing/morph/sin_morph_cs_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - - None - False - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/morph/sin_morph_cs_ro.csproj b/src/tests/JIT/Methodical/Boxing/morph/sin_morph_cs_ro.csproj deleted file mode 100644 index e6176c114768..000000000000 --- a/src/tests/JIT/Methodical/Boxing/morph/sin_morph_cs_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - - None - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/seh/try.cs b/src/tests/JIT/Methodical/Boxing/seh/try.cs index e986ddfea0a8..c647096b78a8 100644 --- a/src/tests/JIT/Methodical/Boxing/seh/try.cs +++ b/src/tests/JIT/Methodical/Boxing/seh/try.cs @@ -51,6 +51,7 @@ protected static object CalcAndCheck(object Angle, object Expected) } [Fact] + [OuterLoop] public static void TestEntryPoint() { object i; diff --git a/src/tests/JIT/Methodical/Boxing/seh/try_cs_d.csproj b/src/tests/JIT/Methodical/Boxing/seh/try_cs_d.csproj deleted file mode 100644 index b5ed0583f74c..000000000000 --- a/src/tests/JIT/Methodical/Boxing/seh/try_cs_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - - Full - False - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/seh/try_cs_do.csproj b/src/tests/JIT/Methodical/Boxing/seh/try_cs_do.csproj deleted file mode 100644 index 2c4d1cbe5790..000000000000 --- a/src/tests/JIT/Methodical/Boxing/seh/try_cs_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - Full - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/seh/try_cs_r.csproj b/src/tests/JIT/Methodical/Boxing/seh/try_cs_r.csproj deleted file mode 100644 index 7d8785f2be3f..000000000000 --- a/src/tests/JIT/Methodical/Boxing/seh/try_cs_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - - None - False - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/seh/try_cs_ro.csproj b/src/tests/JIT/Methodical/Boxing/seh/try_cs_ro.csproj deleted file mode 100644 index d248389023b9..000000000000 --- a/src/tests/JIT/Methodical/Boxing/seh/try_cs_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - None - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs.cs b/src/tests/JIT/Methodical/Boxing/xlang/sin_cs.cs index 96a56bbe7af1..ad80e4e48942 100644 --- a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs.cs +++ b/src/tests/JIT/Methodical/Boxing/xlang/sin_cs.cs @@ -1,15 +1,17 @@ // Licensed to the .NET Foundation under one or more agreements. -using Xunit; // The .NET Foundation licenses this file to you under the MIT license. +extern alias sinlib_cs; +using Xunit; namespace SinCalc_against_sinlib_cs { using System; - using SinCalcLib; + using sinlib_cs::SinCalcLib; public class SinCalc { [Fact] + [OuterLoop] public static int TestEntryPoint() { object i; diff --git a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_cs_sinlib_d.csproj b/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_cs_sinlib_d.csproj deleted file mode 100644 index 14593bb8c3d8..000000000000 --- a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_cs_sinlib_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_cs_sinlib_do.csproj b/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_cs_sinlib_do.csproj deleted file mode 100644 index fa0e5420e473..000000000000 --- a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_cs_sinlib_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_cs_sinlib_r.csproj b/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_cs_sinlib_r.csproj deleted file mode 100644 index f228bcbe5e67..000000000000 --- a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_cs_sinlib_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_cs_sinlib_ro.csproj b/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_cs_sinlib_ro.csproj deleted file mode 100644 index 87f61d39f077..000000000000 --- a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_cs_sinlib_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_il_sinlib_d.csproj b/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_il_sinlib_d.csproj deleted file mode 100644 index 9fc6ec3a4030..000000000000 --- a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_il_sinlib_d.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - 1 - - - - Full - - $(NoWarn),8002 - - - - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_il_sinlib_do.csproj b/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_il_sinlib_do.csproj deleted file mode 100644 index db992213e120..000000000000 --- a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_il_sinlib_do.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - 1 - - - - Full - True - $(NoWarn),8002 - - - - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_il_sinlib_r.csproj b/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_il_sinlib_r.csproj deleted file mode 100644 index 5ca54fa2ed1d..000000000000 --- a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_il_sinlib_r.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - 1 - - - - None - - $(NoWarn),8002 - - - - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_il_sinlib_ro.csproj b/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_il_sinlib_ro.csproj deleted file mode 100644 index 2e948373cbf1..000000000000 --- a/src/tests/JIT/Methodical/Boxing/xlang/sin_cs_il_sinlib_ro.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - 1 - - - - None - True - $(NoWarn),8002 - - - - - - - - diff --git a/src/tests/JIT/Methodical/Boxing/xlang/sin_il.cs b/src/tests/JIT/Methodical/Boxing/xlang/sin_il.cs index fa2ac8be4464..136c28de8ab1 100644 --- a/src/tests/JIT/Methodical/Boxing/xlang/sin_il.cs +++ b/src/tests/JIT/Methodical/Boxing/xlang/sin_il.cs @@ -1,15 +1,17 @@ // Licensed to the .NET Foundation under one or more agreements. -using Xunit; // The .NET Foundation licenses this file to you under the MIT license. +extern alias sinlib_il; +using Xunit; namespace SinCalc_against_sinlib_il { using System; - using SinCalcLib; + using sinlib_il::SinCalcLib; public class SinCalc { [Fact] + [OuterLoop] public static int TestEntryPoint() { object i; diff --git a/src/tests/JIT/Methodical/Boxing/xlang/sinlib_cs.csproj b/src/tests/JIT/Methodical/Boxing/xlang/sinlib_cs.csproj index 1fb8afdf8cd7..9d09f4633bad 100644 --- a/src/tests/JIT/Methodical/Boxing/xlang/sinlib_cs.csproj +++ b/src/tests/JIT/Methodical/Boxing/xlang/sinlib_cs.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/Methodical/Coverage/b39946.ilproj b/src/tests/JIT/Methodical/Coverage/b39946.ilproj index 9accd6730381..0e16edcabf74 100644 --- a/src/tests/JIT/Methodical/Coverage/b39946.ilproj +++ b/src/tests/JIT/Methodical/Coverage/b39946.ilproj @@ -1,9 +1,6 @@ - - - diff --git a/src/tests/JIT/Methodical/Coverage/b433189.cs b/src/tests/JIT/Methodical/Coverage/b433189.cs index 193aa1dc9e3a..3eee1941867b 100644 --- a/src/tests/JIT/Methodical/Coverage/b433189.cs +++ b/src/tests/JIT/Methodical/Coverage/b433189.cs @@ -47,6 +47,7 @@ public static void foo() } [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/Coverage/b433189.csproj b/src/tests/JIT/Methodical/Coverage/b433189.csproj deleted file mode 100644 index e832736e93f2..000000000000 --- a/src/tests/JIT/Methodical/Coverage/b433189.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Coverage/b518440.ilproj b/src/tests/JIT/Methodical/Coverage/b518440.ilproj index 59000e519a60..6594fe421f10 100644 --- a/src/tests/JIT/Methodical/Coverage/b518440.ilproj +++ b/src/tests/JIT/Methodical/Coverage/b518440.ilproj @@ -2,9 +2,6 @@ 1 - - - diff --git a/src/tests/JIT/Methodical/Coverage/hole.ilproj b/src/tests/JIT/Methodical/Coverage/hole.ilproj index c976ba172a6a..fee335ab7aee 100644 --- a/src/tests/JIT/Methodical/Coverage/hole.ilproj +++ b/src/tests/JIT/Methodical/Coverage/hole.ilproj @@ -1,9 +1,6 @@ - - - diff --git a/src/tests/JIT/Methodical/FPtrunc/convr4a.cs b/src/tests/JIT/Methodical/FPtrunc/convr4a.cs index 98261a2db48f..45511434c58d 100644 --- a/src/tests/JIT/Methodical/FPtrunc/convr4a.cs +++ b/src/tests/JIT/Methodical/FPtrunc/convr4a.cs @@ -6,6 +6,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.FPtrunc.convr4a; + public struct VT { public float f1; @@ -87,6 +89,7 @@ private static float floatdiv_inline() } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool pass = true; diff --git a/src/tests/JIT/Methodical/FPtrunc/convr4a_cs_d.csproj b/src/tests/JIT/Methodical/FPtrunc/convr4a_cs_d.csproj deleted file mode 100644 index 3c337d79b076..000000000000 --- a/src/tests/JIT/Methodical/FPtrunc/convr4a_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/FPtrunc/convr4a_cs_do.csproj b/src/tests/JIT/Methodical/FPtrunc/convr4a_cs_do.csproj deleted file mode 100644 index baf18011af72..000000000000 --- a/src/tests/JIT/Methodical/FPtrunc/convr4a_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/FPtrunc/convr4a_cs_r.csproj b/src/tests/JIT/Methodical/FPtrunc/convr4a_cs_r.csproj deleted file mode 100644 index c30622aa080b..000000000000 --- a/src/tests/JIT/Methodical/FPtrunc/convr4a_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/FPtrunc/convr4a_cs_ro.csproj b/src/tests/JIT/Methodical/FPtrunc/convr4a_cs_ro.csproj deleted file mode 100644 index b98525997efe..000000000000 --- a/src/tests/JIT/Methodical/FPtrunc/convr4a_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/FPtrunc/convr8a.cs b/src/tests/JIT/Methodical/FPtrunc/convr8a.cs index 9366d6058041..1366d2fa2205 100644 --- a/src/tests/JIT/Methodical/FPtrunc/convr8a.cs +++ b/src/tests/JIT/Methodical/FPtrunc/convr8a.cs @@ -6,6 +6,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.FPtrunc.convr8a; + public struct VT { public double f1; @@ -87,6 +89,7 @@ private static double doublediv_inline() } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool pass = true; diff --git a/src/tests/JIT/Methodical/FPtrunc/convr8a_cs_d.csproj b/src/tests/JIT/Methodical/FPtrunc/convr8a_cs_d.csproj deleted file mode 100644 index 2257bd884697..000000000000 --- a/src/tests/JIT/Methodical/FPtrunc/convr8a_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/FPtrunc/convr8a_cs_do.csproj b/src/tests/JIT/Methodical/FPtrunc/convr8a_cs_do.csproj deleted file mode 100644 index 4983af729f3d..000000000000 --- a/src/tests/JIT/Methodical/FPtrunc/convr8a_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/FPtrunc/convr8a_cs_r.csproj b/src/tests/JIT/Methodical/FPtrunc/convr8a_cs_r.csproj deleted file mode 100644 index d461dabde9b9..000000000000 --- a/src/tests/JIT/Methodical/FPtrunc/convr8a_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/FPtrunc/convr8a_cs_ro.csproj b/src/tests/JIT/Methodical/FPtrunc/convr8a_cs_ro.csproj deleted file mode 100644 index 75c0b116d0ff..000000000000 --- a/src/tests/JIT/Methodical/FPtrunc/convr8a_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param1a.cs b/src/tests/JIT/Methodical/Invoke/25params/25param1a.cs index 3477fc30dff4..7f21bb098a1d 100644 --- a/src/tests/JIT/Methodical/Invoke/25params/25param1a.cs +++ b/src/tests/JIT/Methodical/Invoke/25params/25param1a.cs @@ -57,6 +57,7 @@ private static int f(int a1, int a2, int a3, int a4, int a5, } [Fact] + [OuterLoop] public static int TestEntryPoint() { Console.WriteLine("Testing method of 25 parameters, all of int data type"); diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param1a_cs_d.csproj b/src/tests/JIT/Methodical/Invoke/25params/25param1a_cs_d.csproj deleted file mode 100644 index 0b46466dd311..000000000000 --- a/src/tests/JIT/Methodical/Invoke/25params/25param1a_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param1a_cs_do.csproj b/src/tests/JIT/Methodical/Invoke/25params/25param1a_cs_do.csproj deleted file mode 100644 index 70cbe1730710..000000000000 --- a/src/tests/JIT/Methodical/Invoke/25params/25param1a_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param1a_cs_r.csproj b/src/tests/JIT/Methodical/Invoke/25params/25param1a_cs_r.csproj deleted file mode 100644 index c745087b2dff..000000000000 --- a/src/tests/JIT/Methodical/Invoke/25params/25param1a_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param1a_cs_ro.csproj b/src/tests/JIT/Methodical/Invoke/25params/25param1a_cs_ro.csproj deleted file mode 100644 index 6885bad37584..000000000000 --- a/src/tests/JIT/Methodical/Invoke/25params/25param1a_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param2a.cs b/src/tests/JIT/Methodical/Invoke/25params/25param2a.cs index 58ccf2922097..63282138428c 100644 --- a/src/tests/JIT/Methodical/Invoke/25params/25param2a.cs +++ b/src/tests/JIT/Methodical/Invoke/25params/25param2a.cs @@ -69,6 +69,7 @@ private static int f(short a1, ushort a2, int a3, uint a4, long a5, } [Fact] + [OuterLoop] public static int TestEntryPoint() { Console.WriteLine("Testing method of 25 parameters, mixed data type"); diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param2a_cs_d.csproj b/src/tests/JIT/Methodical/Invoke/25params/25param2a_cs_d.csproj deleted file mode 100644 index fdef9835f1fa..000000000000 --- a/src/tests/JIT/Methodical/Invoke/25params/25param2a_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param2a_cs_do.csproj b/src/tests/JIT/Methodical/Invoke/25params/25param2a_cs_do.csproj deleted file mode 100644 index c653a2f08bdb..000000000000 --- a/src/tests/JIT/Methodical/Invoke/25params/25param2a_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param2a_cs_r.csproj b/src/tests/JIT/Methodical/Invoke/25params/25param2a_cs_r.csproj deleted file mode 100644 index 717962f43ce4..000000000000 --- a/src/tests/JIT/Methodical/Invoke/25params/25param2a_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param2a_cs_ro.csproj b/src/tests/JIT/Methodical/Invoke/25params/25param2a_cs_ro.csproj deleted file mode 100644 index 558423c30f81..000000000000 --- a/src/tests/JIT/Methodical/Invoke/25params/25param2a_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param3a.cs b/src/tests/JIT/Methodical/Invoke/25params/25param3a.cs index 0d8cab255622..f8f1db10ef83 100644 --- a/src/tests/JIT/Methodical/Invoke/25params/25param3a.cs +++ b/src/tests/JIT/Methodical/Invoke/25params/25param3a.cs @@ -323,6 +323,7 @@ private static int f(int a1, int a2, int a3, int a4, int a5, } [Fact] + [OuterLoop] public static int TestEntryPoint() { Console.WriteLine("Testing method of 25 parameters, all of int data type, long chain of method calls"); diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param3a_cs_d.csproj b/src/tests/JIT/Methodical/Invoke/25params/25param3a_cs_d.csproj deleted file mode 100644 index fe4f27d06a2e..000000000000 --- a/src/tests/JIT/Methodical/Invoke/25params/25param3a_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param3a_cs_do.csproj b/src/tests/JIT/Methodical/Invoke/25params/25param3a_cs_do.csproj deleted file mode 100644 index ccb1c350324c..000000000000 --- a/src/tests/JIT/Methodical/Invoke/25params/25param3a_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param3a_cs_r.csproj b/src/tests/JIT/Methodical/Invoke/25params/25param3a_cs_r.csproj deleted file mode 100644 index cbe2ce9b36e2..000000000000 --- a/src/tests/JIT/Methodical/Invoke/25params/25param3a_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/25params/25param3a_cs_ro.csproj b/src/tests/JIT/Methodical/Invoke/25params/25param3a_cs_ro.csproj deleted file mode 100644 index e223075df538..000000000000 --- a/src/tests/JIT/Methodical/Invoke/25params/25param3a_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_d.csproj b/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_d.csproj deleted file mode 100644 index 0b14296c4568..000000000000 --- a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_do.csproj b/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_do.csproj deleted file mode 100644 index a55844ea464a..000000000000 --- a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_r.csproj b/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_r.csproj deleted file mode 100644 index 7869d0ba4bc1..000000000000 --- a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_ro.csproj b/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_ro.csproj deleted file mode 100644 index dbf86d2dab81..000000000000 --- a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_tail_d.csproj b/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_tail_d.csproj deleted file mode 100644 index 49a1509c8e4d..000000000000 --- a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_tail_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_tail_do.csproj b/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_tail_do.csproj deleted file mode 100644 index 52ce19644d06..000000000000 --- a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_tail_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_tail_r.csproj b/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_tail_r.csproj deleted file mode 100644 index 0f084f4e648b..000000000000 --- a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_tail_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_tail_ro.csproj b/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_tail_ro.csproj deleted file mode 100644 index 4b07443da605..000000000000 --- a/src/tests/JIT/Methodical/Invoke/SEH/catchfinally_tail_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/callvirt/test1.cs b/src/tests/JIT/Methodical/Invoke/callvirt/test1.cs index cfe1cffc4ab3..fda7cea18fb9 100644 --- a/src/tests/JIT/Methodical/Invoke/callvirt/test1.cs +++ b/src/tests/JIT/Methodical/Invoke/callvirt/test1.cs @@ -33,6 +33,7 @@ public override Base[] Clone(int numOfCopies) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Base bas = new Derived(); diff --git a/src/tests/JIT/Methodical/Invoke/callvirt/test1_d.csproj b/src/tests/JIT/Methodical/Invoke/callvirt/test1_d.csproj deleted file mode 100644 index 2c61b708a513..000000000000 --- a/src/tests/JIT/Methodical/Invoke/callvirt/test1_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/callvirt/test1_do.csproj b/src/tests/JIT/Methodical/Invoke/callvirt/test1_do.csproj deleted file mode 100644 index 84f675709b5e..000000000000 --- a/src/tests/JIT/Methodical/Invoke/callvirt/test1_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/callvirt/test1_r.csproj b/src/tests/JIT/Methodical/Invoke/callvirt/test1_r.csproj deleted file mode 100644 index 35cc80ba00d7..000000000000 --- a/src/tests/JIT/Methodical/Invoke/callvirt/test1_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/callvirt/test1_ro.csproj b/src/tests/JIT/Methodical/Invoke/callvirt/test1_ro.csproj deleted file mode 100644 index 1f9e49aa62e2..000000000000 --- a/src/tests/JIT/Methodical/Invoke/callvirt/test1_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/ctor/val_ctor.cs b/src/tests/JIT/Methodical/Invoke/ctor/val_ctor.cs index 1340acfbfcf7..eff7bbf71802 100644 --- a/src/tests/JIT/Methodical/Invoke/ctor/val_ctor.cs +++ b/src/tests/JIT/Methodical/Invoke/ctor/val_ctor.cs @@ -23,6 +23,7 @@ private TestStruct(ulong testParam) } [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/Invoke/ctor/val_ctor_d.csproj b/src/tests/JIT/Methodical/Invoke/ctor/val_ctor_d.csproj deleted file mode 100644 index 170949d5fd77..000000000000 --- a/src/tests/JIT/Methodical/Invoke/ctor/val_ctor_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/ctor/val_ctor_do.csproj b/src/tests/JIT/Methodical/Invoke/ctor/val_ctor_do.csproj deleted file mode 100644 index af3e7148f219..000000000000 --- a/src/tests/JIT/Methodical/Invoke/ctor/val_ctor_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/ctor/val_ctor_r.csproj b/src/tests/JIT/Methodical/Invoke/ctor/val_ctor_r.csproj deleted file mode 100644 index bea8e3ea840d..000000000000 --- a/src/tests/JIT/Methodical/Invoke/ctor/val_ctor_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/ctor/val_ctor_ro.csproj b/src/tests/JIT/Methodical/Invoke/ctor/val_ctor_ro.csproj deleted file mode 100644 index 357055668cbc..000000000000 --- a/src/tests/JIT/Methodical/Invoke/ctor/val_ctor_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/deep/deep_d.csproj b/src/tests/JIT/Methodical/Invoke/deep/deep_d.csproj deleted file mode 100644 index 42ba1e956a12..000000000000 --- a/src/tests/JIT/Methodical/Invoke/deep/deep_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/deep/deep_do.csproj b/src/tests/JIT/Methodical/Invoke/deep/deep_do.csproj deleted file mode 100644 index 098efe8d1591..000000000000 --- a/src/tests/JIT/Methodical/Invoke/deep/deep_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/deep/deep_r.csproj b/src/tests/JIT/Methodical/Invoke/deep/deep_r.csproj deleted file mode 100644 index a68cfa2a3421..000000000000 --- a/src/tests/JIT/Methodical/Invoke/deep/deep_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/deep/deep_ro.csproj b/src/tests/JIT/Methodical/Invoke/deep/deep_ro.csproj deleted file mode 100644 index f2a09b8976bb..000000000000 --- a/src/tests/JIT/Methodical/Invoke/deep/deep_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/fptr/recurse.cs b/src/tests/JIT/Methodical/Invoke/fptr/recurse.cs index 8a2497521113..ce49a1244c61 100644 --- a/src/tests/JIT/Methodical/Invoke/fptr/recurse.cs +++ b/src/tests/JIT/Methodical/Invoke/fptr/recurse.cs @@ -20,6 +20,7 @@ private static int Fact1(ref int arg, ref int result) } [Fact] + [OuterLoop] public static int TestEntryPoint() { int arg = 6; diff --git a/src/tests/JIT/Methodical/Invoke/fptr/recurse_d.csproj b/src/tests/JIT/Methodical/Invoke/fptr/recurse_d.csproj deleted file mode 100644 index ddd4e01a987d..000000000000 --- a/src/tests/JIT/Methodical/Invoke/fptr/recurse_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/fptr/recurse_do.csproj b/src/tests/JIT/Methodical/Invoke/fptr/recurse_do.csproj deleted file mode 100644 index 368344e1b41b..000000000000 --- a/src/tests/JIT/Methodical/Invoke/fptr/recurse_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/fptr/recurse_r.csproj b/src/tests/JIT/Methodical/Invoke/fptr/recurse_r.csproj deleted file mode 100644 index 637f035d9010..000000000000 --- a/src/tests/JIT/Methodical/Invoke/fptr/recurse_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/fptr/recurse_ro.csproj b/src/tests/JIT/Methodical/Invoke/fptr/recurse_ro.csproj deleted file mode 100644 index 67c1449c9d3b..000000000000 --- a/src/tests/JIT/Methodical/Invoke/fptr/recurse_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/hfa_params/hfa_params_cs_d.csproj b/src/tests/JIT/Methodical/Invoke/hfa_params/hfa_params_cs_d.csproj deleted file mode 100644 index b4429d7e26d1..000000000000 --- a/src/tests/JIT/Methodical/Invoke/hfa_params/hfa_params_cs_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/hfa_params/hfa_params_cs_do.csproj b/src/tests/JIT/Methodical/Invoke/hfa_params/hfa_params_cs_do.csproj deleted file mode 100644 index 264ecb88c69d..000000000000 --- a/src/tests/JIT/Methodical/Invoke/hfa_params/hfa_params_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/hfa_params/hfa_params_cs_r.csproj b/src/tests/JIT/Methodical/Invoke/hfa_params/hfa_params_cs_r.csproj deleted file mode 100644 index fc50543be3ca..000000000000 --- a/src/tests/JIT/Methodical/Invoke/hfa_params/hfa_params_cs_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/hfa_params/hfa_params_cs_ro.csproj b/src/tests/JIT/Methodical/Invoke/hfa_params/hfa_params_cs_ro.csproj deleted file mode 100644 index 2961237f04d3..000000000000 --- a/src/tests/JIT/Methodical/Invoke/hfa_params/hfa_params_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/implicit/obj.cs b/src/tests/JIT/Methodical/Invoke/implicit/obj.cs index 6d0b12ed403e..e5d82cead683 100644 --- a/src/tests/JIT/Methodical/Invoke/implicit/obj.cs +++ b/src/tests/JIT/Methodical/Invoke/implicit/obj.cs @@ -21,6 +21,7 @@ private static void TestFunc(Base obj) } [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/Invoke/implicit/obj_d.csproj b/src/tests/JIT/Methodical/Invoke/implicit/obj_d.csproj deleted file mode 100644 index 611011a1f3dc..000000000000 --- a/src/tests/JIT/Methodical/Invoke/implicit/obj_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/implicit/obj_do.csproj b/src/tests/JIT/Methodical/Invoke/implicit/obj_do.csproj deleted file mode 100644 index a11b139f0bf6..000000000000 --- a/src/tests/JIT/Methodical/Invoke/implicit/obj_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/implicit/obj_r.csproj b/src/tests/JIT/Methodical/Invoke/implicit/obj_r.csproj deleted file mode 100644 index 6839bca24a64..000000000000 --- a/src/tests/JIT/Methodical/Invoke/implicit/obj_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Invoke/implicit/obj_ro.csproj b/src/tests/JIT/Methodical/Invoke/implicit/obj_ro.csproj deleted file mode 100644 index 6375b0ac7a39..000000000000 --- a/src/tests/JIT/Methodical/Invoke/implicit/obj_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/bool.cs b/src/tests/JIT/Methodical/MDArray/DataTypes/bool.cs index 072903671031..343881266d6b 100644 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/bool.cs +++ b/src/tests/JIT/Methodical/MDArray/DataTypes/bool.cs @@ -5,6 +5,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.DataTypes.@bool; + public struct VT { public bool[,] bool2darr; @@ -27,6 +29,7 @@ public class Bool2D3DArrTest static bool[][, ,] ja2 = new bool[2][, ,]; [Fact] + [OuterLoop] public static int TestEntryPoint() { diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/bool_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/bool_cs_d.csproj deleted file mode 100644 index 0c8121d59d35..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/bool_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/bool_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/bool_cs_do.csproj deleted file mode 100644 index 00dfa1dc5eee..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/bool_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/bool_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/bool_cs_r.csproj deleted file mode 100644 index 1ab614913821..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/bool_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/bool_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/bool_cs_ro.csproj deleted file mode 100644 index cd51352afca0..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/bool_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/byte.cs b/src/tests/JIT/Methodical/MDArray/DataTypes/byte.cs index 374db66f3560..5aef36722ddd 100644 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/byte.cs +++ b/src/tests/JIT/Methodical/MDArray/DataTypes/byte.cs @@ -5,6 +5,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.DataTypes.@byte; + public struct VT { public byte[,] byte2darr; @@ -36,6 +38,7 @@ public class byteMDArrTest static byte[][, ,] ja2_b = new byte[2][, ,]; [Fact] + [OuterLoop] public static int TestEntryPoint() { diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/byte_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/byte_cs_d.csproj deleted file mode 100644 index 4c6fc6e69b15..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/byte_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/byte_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/byte_cs_do.csproj deleted file mode 100644 index f66120f5c086..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/byte_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/byte_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/byte_cs_r.csproj deleted file mode 100644 index 261e5566d7dc..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/byte_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/byte_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/byte_cs_ro.csproj deleted file mode 100644 index f1bb8a230c69..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/byte_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/char.cs b/src/tests/JIT/Methodical/MDArray/DataTypes/char.cs index 14cb4384bed0..024da88ed55a 100644 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/char.cs +++ b/src/tests/JIT/Methodical/MDArray/DataTypes/char.cs @@ -5,6 +5,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.DataTypes.@char; + public struct VT { public char[,] char2darr; @@ -27,6 +29,7 @@ public class charMDArrTest static char[][, ,] ja2 = new char[2][, ,]; [Fact] + [OuterLoop] public static int TestEntryPoint() { diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/char_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/char_cs_d.csproj deleted file mode 100644 index b37219c90306..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/char_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/char_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/char_cs_do.csproj deleted file mode 100644 index 4641bc78ce02..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/char_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/char_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/char_cs_r.csproj deleted file mode 100644 index f86c853a03df..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/char_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/char_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/char_cs_ro.csproj deleted file mode 100644 index 2dbc05babd59..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/char_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/decimal.cs b/src/tests/JIT/Methodical/MDArray/DataTypes/decimal.cs index 5651dcc57280..cf40e4c3d3d8 100644 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/decimal.cs +++ b/src/tests/JIT/Methodical/MDArray/DataTypes/decimal.cs @@ -5,6 +5,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.DataTypes.@decimal; + public struct VT { public decimal[,] decimal2darr; @@ -35,6 +37,7 @@ public class decimalMDArrTest static decimal[][, ,] ja2_b = new decimal[2][, ,]; [Fact] + [OuterLoop] public static int TestEntryPoint() { diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/decimal_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/decimal_cs_d.csproj deleted file mode 100644 index 9eed23b0f5ad..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/decimal_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/decimal_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/decimal_cs_do.csproj deleted file mode 100644 index ed85b7af8e85..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/decimal_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/decimal_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/decimal_cs_r.csproj deleted file mode 100644 index b1b739899dc2..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/decimal_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/decimal_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/decimal_cs_ro.csproj deleted file mode 100644 index f89c061ab67b..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/decimal_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/double.cs b/src/tests/JIT/Methodical/MDArray/DataTypes/double.cs index 3309a4997356..16be2c628fdb 100644 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/double.cs +++ b/src/tests/JIT/Methodical/MDArray/DataTypes/double.cs @@ -5,6 +5,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.DataTypes.@double; + public struct VT { public double[,] double2darr; @@ -35,6 +37,7 @@ public class doubleMDArrTest static double[][, ,] ja2_b = new double[2][, ,]; [Fact] + [OuterLoop] public static int TestEntryPoint() { diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/double_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/double_cs_d.csproj deleted file mode 100644 index 0b5e5714c74f..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/double_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/double_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/double_cs_do.csproj deleted file mode 100644 index d2bf76f44415..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/double_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/double_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/double_cs_r.csproj deleted file mode 100644 index 50f578bddb68..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/double_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/double_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/double_cs_ro.csproj deleted file mode 100644 index 75129c47c524..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/double_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/float.cs b/src/tests/JIT/Methodical/MDArray/DataTypes/float.cs index 651196612ce5..174d65864afa 100644 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/float.cs +++ b/src/tests/JIT/Methodical/MDArray/DataTypes/float.cs @@ -5,6 +5,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.DataTypes.@float; + public struct VT { public float[,] float2darr; @@ -35,6 +37,7 @@ public class floatMDArrTest static float[][, ,] ja2_b = new float[2][, ,]; [Fact] + [OuterLoop] public static int TestEntryPoint() { diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/float_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/float_cs_d.csproj deleted file mode 100644 index 464d58d710cd..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/float_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/float_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/float_cs_do.csproj deleted file mode 100644 index 3bfc6cad62b2..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/float_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/float_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/float_cs_r.csproj deleted file mode 100644 index 3203113766fc..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/float_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/float_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/float_cs_ro.csproj deleted file mode 100644 index de0e72b3e8b4..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/float_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/int.cs b/src/tests/JIT/Methodical/MDArray/DataTypes/int.cs index 90303200e3f7..ddcb0e75f458 100644 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/int.cs +++ b/src/tests/JIT/Methodical/MDArray/DataTypes/int.cs @@ -5,6 +5,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.DataTypes.@int; + public struct VT { public int[,] int2darr; @@ -44,6 +46,7 @@ public class intMDArrTest [Fact] + [OuterLoop] public static int TestEntryPoint() { diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/int_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/int_cs_d.csproj deleted file mode 100644 index 7eefde30191b..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/int_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/int_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/int_cs_do.csproj deleted file mode 100644 index 43c627c15d91..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/int_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/int_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/int_cs_r.csproj deleted file mode 100644 index 8b9c6537ab06..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/int_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/int_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/int_cs_ro.csproj deleted file mode 100644 index 6f1a579557a2..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/int_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/long.cs b/src/tests/JIT/Methodical/MDArray/DataTypes/long.cs index da68fe99b4ff..b923b6458794 100644 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/long.cs +++ b/src/tests/JIT/Methodical/MDArray/DataTypes/long.cs @@ -5,6 +5,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.DataTypes.@long; + public struct VT { public long[,] long2darr; @@ -43,6 +45,7 @@ public class longMDArrTest static long[][, ,] ja2_c = new long[2][, ,]; [Fact] + [OuterLoop] public static int TestEntryPoint() { diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/long_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/long_cs_d.csproj deleted file mode 100644 index 0347b14c8d6b..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/long_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/long_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/long_cs_do.csproj deleted file mode 100644 index b1342493dcc7..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/long_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/long_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/long_cs_r.csproj deleted file mode 100644 index c74ddc6b4ac4..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/long_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/long_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/long_cs_ro.csproj deleted file mode 100644 index 71491f4179cf..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/long_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte.cs b/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte.cs index b87f2e8dd573..6c0d92403ef8 100644 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte.cs +++ b/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte.cs @@ -5,6 +5,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.DataTypes.@sbyte; + public struct VT { public sbyte[,] sbyte2darr; @@ -35,6 +37,7 @@ public class sbyteMDArrTest static sbyte[][, ,] ja2_b = new sbyte[2][, ,]; [Fact] + [OuterLoop] public static int TestEntryPoint() { diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte_cs_d.csproj deleted file mode 100644 index 94e323579265..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte_cs_do.csproj deleted file mode 100644 index 703974e49790..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte_cs_r.csproj deleted file mode 100644 index a390883cd8e3..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte_cs_ro.csproj deleted file mode 100644 index 052c79d0da45..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/sbyte_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/short.cs b/src/tests/JIT/Methodical/MDArray/DataTypes/short.cs index 1292a35d60c0..c353bf6f9329 100644 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/short.cs +++ b/src/tests/JIT/Methodical/MDArray/DataTypes/short.cs @@ -5,6 +5,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.DataTypes.@short; + public struct VT { public short[,] short2darr; @@ -35,6 +37,7 @@ public class shortMDArrTest static short[][, ,] ja2_b = new short[2][, ,]; [Fact] + [OuterLoop] public static int TestEntryPoint() { diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/short_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/short_cs_d.csproj deleted file mode 100644 index 753cc7fc93f5..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/short_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/short_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/short_cs_do.csproj deleted file mode 100644 index 231f1ec3906a..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/short_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/short_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/short_cs_r.csproj deleted file mode 100644 index 4601ccff222d..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/short_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/short_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/short_cs_ro.csproj deleted file mode 100644 index b0c5ea988569..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/short_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/uint.cs b/src/tests/JIT/Methodical/MDArray/DataTypes/uint.cs index 50c785be7687..e4f2712a0bad 100644 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/uint.cs +++ b/src/tests/JIT/Methodical/MDArray/DataTypes/uint.cs @@ -5,6 +5,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.DataTypes.@uint; + public struct VT { public uint[,] uint2darr; @@ -35,6 +37,7 @@ public class uintMDArrTest static uint[][, ,] ja2_b = new uint[2][, ,]; [Fact] + [OuterLoop] public static int TestEntryPoint() { diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/uint_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/uint_cs_d.csproj deleted file mode 100644 index 8cd16c0c896f..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/uint_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/uint_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/uint_cs_do.csproj deleted file mode 100644 index 9662d192d59f..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/uint_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/uint_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/uint_cs_r.csproj deleted file mode 100644 index 68321a84d5b9..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/uint_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/uint_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/uint_cs_ro.csproj deleted file mode 100644 index 88089a23f70e..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/uint_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/ulong.cs b/src/tests/JIT/Methodical/MDArray/DataTypes/ulong.cs index 1bbe44887214..d4db24914284 100644 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/ulong.cs +++ b/src/tests/JIT/Methodical/MDArray/DataTypes/ulong.cs @@ -5,6 +5,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.DataTypes.@ulong; + public struct VT { public ulong[,] ulong2darr; @@ -35,6 +37,7 @@ public class ulongMDArrTest static ulong[][, ,] ja2_b = new ulong[2][, ,]; [Fact] + [OuterLoop] public static int TestEntryPoint() { diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/ulong_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/ulong_cs_d.csproj deleted file mode 100644 index f7e9772c9369..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/ulong_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/ulong_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/ulong_cs_do.csproj deleted file mode 100644 index a4e72accaa8a..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/ulong_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/ulong_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/ulong_cs_r.csproj deleted file mode 100644 index 65b0220c0a1b..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/ulong_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/ulong_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/ulong_cs_ro.csproj deleted file mode 100644 index becd80f86d5b..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/ulong_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/ushort.cs b/src/tests/JIT/Methodical/MDArray/DataTypes/ushort.cs index 4f1e35e0bd4c..b82d4ecb14c2 100644 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/ushort.cs +++ b/src/tests/JIT/Methodical/MDArray/DataTypes/ushort.cs @@ -5,6 +5,8 @@ using System; using Xunit; +namespace JIT.Methodical.MDArray.DataTypes.@ushort; + public struct VT { public ushort[,] ushort2darr; @@ -35,6 +37,7 @@ public class ushortMDArrTest static ushort[][, ,] ja2_b = new ushort[2][, ,]; [Fact] + [OuterLoop] public static int TestEntryPoint() { diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/ushort_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/ushort_cs_d.csproj deleted file mode 100644 index 459cedb93eca..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/ushort_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/ushort_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/ushort_cs_do.csproj deleted file mode 100644 index 2c0edbebd442..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/ushort_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/ushort_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/ushort_cs_r.csproj deleted file mode 100644 index 08d77e95e01d..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/ushort_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/DataTypes/ushort_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/DataTypes/ushort_cs_ro.csproj deleted file mode 100644 index c18c1e8b093f..000000000000 --- a/src/tests/JIT/Methodical/MDArray/DataTypes/ushort_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr.cs b/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr.cs index 1ce5bc5e72f7..5d052e85297a 100644 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr.cs +++ b/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr.cs @@ -96,6 +96,7 @@ public static void gaussj(MatrixCls a, int n, MatrixCls b, int m) } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool pass = false; diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr_GaussJordan_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr_GaussJordan_cs_d.csproj deleted file mode 100644 index 7d9e47e5ff1a..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr_GaussJordan_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr_GaussJordan_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr_GaussJordan_cs_do.csproj deleted file mode 100644 index f69c3c32a88a..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr_GaussJordan_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr_GaussJordan_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr_GaussJordan_cs_r.csproj deleted file mode 100644 index 5114d79e78c4..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr_GaussJordan_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr_GaussJordan_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr_GaussJordan_cs_ro.csproj deleted file mode 100644 index e688c56182c8..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/classarr_GaussJordan_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr.cs b/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr.cs index 6f01ff3a9577..34b7cb3eb16d 100644 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr.cs +++ b/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr.cs @@ -89,6 +89,7 @@ public static void gaussj(double[][,] a, int n, double[][,] b, int m) } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool pass = false; diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr_GaussJordan_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr_GaussJordan_cs_d.csproj deleted file mode 100644 index 19d97893fb5b..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr_GaussJordan_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr_GaussJordan_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr_GaussJordan_cs_do.csproj deleted file mode 100644 index 69994ed5d9ea..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr_GaussJordan_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr_GaussJordan_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr_GaussJordan_cs_r.csproj deleted file mode 100644 index 8a50b699d342..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr_GaussJordan_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr_GaussJordan_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr_GaussJordan_cs_ro.csproj deleted file mode 100644 index 4af2dc59f2a1..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/jaggedarr_GaussJordan_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr.cs b/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr.cs index 9bd82bbbd1d8..10ff7716551e 100644 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr.cs +++ b/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr.cs @@ -86,6 +86,7 @@ public static void gaussj(double[,] a, int n, double[,] b, int m) } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool pass = false; diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr_cs_d.csproj deleted file mode 100644 index 13cfec1fb63a..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr_cs_do.csproj deleted file mode 100644 index f4d0ded42316..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr_cs_r.csproj deleted file mode 100644 index 071c9317d567..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr_cs_ro.csproj deleted file mode 100644 index 33db54aeef33..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/plainarr_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr.cs b/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr.cs index f9779d801500..d9153ab7d742 100644 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr.cs +++ b/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr.cs @@ -95,6 +95,7 @@ public static void gaussj(MatrixStruct a, int n, MatrixStruct b, int m) } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool pass = false; diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr_GaussJordan_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr_GaussJordan_cs_d.csproj deleted file mode 100644 index 1e2c2233f77c..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr_GaussJordan_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr_GaussJordan_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr_GaussJordan_cs_do.csproj deleted file mode 100644 index b5c324562361..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr_GaussJordan_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr_GaussJordan_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr_GaussJordan_cs_r.csproj deleted file mode 100644 index 87bd03e993c4..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr_GaussJordan_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr_GaussJordan_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr_GaussJordan_cs_ro.csproj deleted file mode 100644 index 8f4ce659ede9..000000000000 --- a/src/tests/JIT/Methodical/MDArray/GaussJordan/structarr_GaussJordan_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/classarr.cs b/src/tests/JIT/Methodical/MDArray/InnerProd/classarr.cs index e55008d21ffc..9af520bdbcfc 100644 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/classarr.cs +++ b/src/tests/JIT/Methodical/MDArray/InnerProd/classarr.cs @@ -124,7 +124,8 @@ public static void InnerProduct3DRef(out int res, int[][] a3d, int[][] b, int ro } [Fact] - public static int TestEntryPoint() + [OuterLoop] + public static int TestEntryPoint() { bool pass = false; diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/classarr_InnerProd_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/classarr_InnerProd_cs_d.csproj deleted file mode 100644 index 7d9e47e5ff1a..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/classarr_InnerProd_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/classarr_InnerProd_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/classarr_InnerProd_cs_do.csproj deleted file mode 100644 index 48c35fde4e69..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/classarr_InnerProd_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/classarr_InnerProd_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/classarr_InnerProd_cs_r.csproj deleted file mode 100644 index 5114d79e78c4..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/classarr_InnerProd_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/classarr_InnerProd_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/classarr_InnerProd_cs_ro.csproj deleted file mode 100644 index 19ea8d281430..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/classarr_InnerProd_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr.cs b/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr.cs index 7c212ddd8f7b..7669bf4d8660 100644 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr.cs +++ b/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr.cs @@ -118,7 +118,8 @@ public static void InnerProduct3DRef(out double res, double[][] a, double[][] b, } [Fact] - public static int TestEntryPoint() + [OuterLoop] + public static int TestEntryPoint() { bool pass = false; diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr_InnerProd_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr_InnerProd_cs_d.csproj deleted file mode 100644 index 4c0d77324fee..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr_InnerProd_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr_InnerProd_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr_InnerProd_cs_do.csproj deleted file mode 100644 index f8b336279b17..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr_InnerProd_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr_InnerProd_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr_InnerProd_cs_r.csproj deleted file mode 100644 index 71b566b5c13c..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr_InnerProd_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr_InnerProd_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr_InnerProd_cs_ro.csproj deleted file mode 100644 index 4f370680e9f4..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/doublearr_InnerProd_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/intarr.cs b/src/tests/JIT/Methodical/MDArray/InnerProd/intarr.cs index 78b2bfd7e9fd..b110d132acd0 100644 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/intarr.cs +++ b/src/tests/JIT/Methodical/MDArray/InnerProd/intarr.cs @@ -105,7 +105,8 @@ public static void InnerProduct3DRef(out int res, int[][] a, int[][] b, int row, } [Fact] - public static int TestEntryPoint() + [OuterLoop] + public static int TestEntryPoint() { bool pass = false; diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/intarr_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/intarr_cs_d.csproj deleted file mode 100644 index eab81c392e11..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/intarr_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/intarr_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/intarr_cs_do.csproj deleted file mode 100644 index f272a66c631e..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/intarr_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/intarr_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/intarr_cs_r.csproj deleted file mode 100644 index d94ed43f8cae..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/intarr_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/intarr_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/intarr_cs_ro.csproj deleted file mode 100644 index 44871e505d94..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/intarr_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr.cs b/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr.cs index e2db95651bf3..2983382f41d9 100644 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr.cs +++ b/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr.cs @@ -118,7 +118,8 @@ public static void InnerProduct3DRef(out double res, double[][] a, double[][] b, } [Fact] - public static int TestEntryPoint() + [OuterLoop] + public static int TestEntryPoint() { bool pass = false; diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr_InnerProd_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr_InnerProd_cs_d.csproj deleted file mode 100644 index 19d97893fb5b..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr_InnerProd_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr_InnerProd_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr_InnerProd_cs_do.csproj deleted file mode 100644 index 69994ed5d9ea..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr_InnerProd_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr_InnerProd_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr_InnerProd_cs_r.csproj deleted file mode 100644 index 8a50b699d342..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr_InnerProd_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr_InnerProd_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr_InnerProd_cs_ro.csproj deleted file mode 100644 index 4af2dc59f2a1..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/jaggedarr_InnerProd_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr.cs b/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr.cs index 02e8d21a8753..f6e8ffc05ac0 100644 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr.cs +++ b/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr.cs @@ -133,6 +133,7 @@ public static void InnerProduct3DRef(out String res, String[][] a, String[][] b, } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool pass = false; diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr_InnerProd_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr_InnerProd_cs_d.csproj deleted file mode 100644 index f0a0845255f4..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr_InnerProd_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr_InnerProd_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr_InnerProd_cs_do.csproj deleted file mode 100644 index 56a3e3f941c0..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr_InnerProd_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr_InnerProd_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr_InnerProd_cs_r.csproj deleted file mode 100644 index df0113a204b2..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr_InnerProd_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr_InnerProd_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr_InnerProd_cs_ro.csproj deleted file mode 100644 index d59e9f27058d..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/stringarr_InnerProd_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/structarr.cs b/src/tests/JIT/Methodical/MDArray/InnerProd/structarr.cs index 537787541a5d..63669ba2814b 100644 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/structarr.cs +++ b/src/tests/JIT/Methodical/MDArray/InnerProd/structarr.cs @@ -121,7 +121,8 @@ public static void InnerProduct3DRef(out int res, int[][] a3d, int[][] b, int ro } [Fact] - public static int TestEntryPoint() + [OuterLoop] + public static int TestEntryPoint() { bool pass = false; diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/structarr_InnerProd_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/structarr_InnerProd_cs_d.csproj deleted file mode 100644 index 1e2c2233f77c..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/structarr_InnerProd_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/structarr_InnerProd_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/structarr_InnerProd_cs_do.csproj deleted file mode 100644 index fab39bbae71b..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/structarr_InnerProd_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/structarr_InnerProd_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/structarr_InnerProd_cs_r.csproj deleted file mode 100644 index 87bd03e993c4..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/structarr_InnerProd_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/InnerProd/structarr_InnerProd_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/InnerProd/structarr_InnerProd_cs_ro.csproj deleted file mode 100644 index 4208472e59c2..000000000000 --- a/src/tests/JIT/Methodical/MDArray/InnerProd/structarr_InnerProd_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/classarr_basics_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/basics/classarr_basics_cs_d.csproj deleted file mode 100644 index 04e71b03f23a..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/classarr_basics_cs_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/classarr_basics_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/basics/classarr_basics_cs_do.csproj deleted file mode 100644 index f69c3c32a88a..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/classarr_basics_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/classarr_basics_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/basics/classarr_basics_cs_r.csproj deleted file mode 100644 index 914f7d837273..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/classarr_basics_cs_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/classarr_basics_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/basics/classarr_basics_cs_ro.csproj deleted file mode 100644 index e688c56182c8..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/classarr_basics_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/doublearr_basics_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/basics/doublearr_basics_cs_d.csproj deleted file mode 100644 index d9a216dfc151..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/doublearr_basics_cs_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/doublearr_basics_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/basics/doublearr_basics_cs_do.csproj deleted file mode 100644 index f8b336279b17..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/doublearr_basics_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/doublearr_basics_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/basics/doublearr_basics_cs_r.csproj deleted file mode 100644 index a041bd00fadb..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/doublearr_basics_cs_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/doublearr_basics_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/basics/doublearr_basics_cs_ro.csproj deleted file mode 100644 index 4f370680e9f4..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/doublearr_basics_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/jaggedarr_basics_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/basics/jaggedarr_basics_cs_d.csproj deleted file mode 100644 index f497dfce1954..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/jaggedarr_basics_cs_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/jaggedarr_basics_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/basics/jaggedarr_basics_cs_do.csproj deleted file mode 100644 index 69994ed5d9ea..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/jaggedarr_basics_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/jaggedarr_basics_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/basics/jaggedarr_basics_cs_r.csproj deleted file mode 100644 index 5dd5ff10ef76..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/jaggedarr_basics_cs_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/jaggedarr_basics_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/basics/jaggedarr_basics_cs_ro.csproj deleted file mode 100644 index 4af2dc59f2a1..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/jaggedarr_basics_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/stringarr_basics_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/basics/stringarr_basics_cs_d.csproj deleted file mode 100644 index 6917472c8c9d..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/stringarr_basics_cs_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/stringarr_basics_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/basics/stringarr_basics_cs_do.csproj deleted file mode 100644 index 56a3e3f941c0..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/stringarr_basics_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/stringarr_basics_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/basics/stringarr_basics_cs_r.csproj deleted file mode 100644 index ee12f245b94e..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/stringarr_basics_cs_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/stringarr_basics_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/basics/stringarr_basics_cs_ro.csproj deleted file mode 100644 index d59e9f27058d..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/stringarr_basics_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/structarr_basics_cs_d.csproj b/src/tests/JIT/Methodical/MDArray/basics/structarr_basics_cs_d.csproj deleted file mode 100644 index 273a24d2222a..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/structarr_basics_cs_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/structarr_basics_cs_do.csproj b/src/tests/JIT/Methodical/MDArray/basics/structarr_basics_cs_do.csproj deleted file mode 100644 index b5c324562361..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/structarr_basics_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/structarr_basics_cs_r.csproj b/src/tests/JIT/Methodical/MDArray/basics/structarr_basics_cs_r.csproj deleted file mode 100644 index 6330437001a1..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/structarr_basics_cs_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/MDArray/basics/structarr_basics_cs_ro.csproj b/src/tests/JIT/Methodical/MDArray/basics/structarr_basics_cs_ro.csproj deleted file mode 100644 index 8f4ce659ede9..000000000000 --- a/src/tests/JIT/Methodical/MDArray/basics/structarr_basics_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Methodical_d1.csproj b/src/tests/JIT/Methodical/Methodical_d1.csproj index 0053845f3227..034f0317e249 100644 --- a/src/tests/JIT/Methodical/Methodical_d1.csproj +++ b/src/tests/JIT/Methodical/Methodical_d1.csproj @@ -1,11 +1,163 @@ + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + \ No newline at end of file diff --git a/src/tests/JIT/Methodical/Methodical_d2.csproj b/src/tests/JIT/Methodical/Methodical_d2.csproj index 4aca955892f5..3053cf52ca45 100644 --- a/src/tests/JIT/Methodical/Methodical_d2.csproj +++ b/src/tests/JIT/Methodical/Methodical_d2.csproj @@ -1,4 +1,7 @@ + + true + @@ -6,7 +9,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + \ No newline at end of file diff --git a/src/tests/JIT/Methodical/Methodical_do.csproj b/src/tests/JIT/Methodical/Methodical_do.csproj index 96b0976b7ccf..9aaafafe01da 100644 --- a/src/tests/JIT/Methodical/Methodical_do.csproj +++ b/src/tests/JIT/Methodical/Methodical_do.csproj @@ -1,7 +1,287 @@ + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + \ No newline at end of file diff --git a/src/tests/JIT/Methodical/Methodical_others.csproj b/src/tests/JIT/Methodical/Methodical_others.csproj index 2fd089bdb777..9106bfe6c520 100644 --- a/src/tests/JIT/Methodical/Methodical_others.csproj +++ b/src/tests/JIT/Methodical/Methodical_others.csproj @@ -1,5 +1,6 @@ + true true @@ -9,7 +10,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + \ No newline at end of file diff --git a/src/tests/JIT/Methodical/Methodical_r1.csproj b/src/tests/JIT/Methodical/Methodical_r1.csproj index 1efc37e0cbb0..573d082a80f0 100644 --- a/src/tests/JIT/Methodical/Methodical_r1.csproj +++ b/src/tests/JIT/Methodical/Methodical_r1.csproj @@ -1,11 +1,164 @@ + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + \ No newline at end of file diff --git a/src/tests/JIT/Methodical/Methodical_r2.csproj b/src/tests/JIT/Methodical/Methodical_r2.csproj index 5e54baf3ed6d..f07b36dfa1e9 100644 --- a/src/tests/JIT/Methodical/Methodical_r2.csproj +++ b/src/tests/JIT/Methodical/Methodical_r2.csproj @@ -1,4 +1,7 @@ + + true + @@ -6,7 +9,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + \ No newline at end of file diff --git a/src/tests/JIT/Methodical/Methodical_ro.csproj b/src/tests/JIT/Methodical/Methodical_ro.csproj index acf22626a849..e78c01515054 100644 --- a/src/tests/JIT/Methodical/Methodical_ro.csproj +++ b/src/tests/JIT/Methodical/Methodical_ro.csproj @@ -1,7 +1,287 @@ + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + \ No newline at end of file diff --git a/src/tests/JIT/Methodical/NaN/arithm32.cs b/src/tests/JIT/Methodical/NaN/arithm32.cs index 94725083f983..34fd5f12096b 100644 --- a/src/tests/JIT/Methodical/NaN/arithm32.cs +++ b/src/tests/JIT/Methodical/NaN/arithm32.cs @@ -88,6 +88,7 @@ static void RunTests(float nan, float plusinf, float minusinf) } [Fact] + [OuterLoop] public static void TestEntryPoint() { RunTests(Single.NaN, Single.PositiveInfinity, Single.NegativeInfinity); diff --git a/src/tests/JIT/Methodical/NaN/arithm32_d.csproj b/src/tests/JIT/Methodical/NaN/arithm32_d.csproj deleted file mode 100644 index 21ac1e0e2277..000000000000 --- a/src/tests/JIT/Methodical/NaN/arithm32_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - full - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/arithm32_do.csproj b/src/tests/JIT/Methodical/NaN/arithm32_do.csproj deleted file mode 100644 index c4f71540a710..000000000000 --- a/src/tests/JIT/Methodical/NaN/arithm32_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - full - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/arithm32_r.csproj b/src/tests/JIT/Methodical/NaN/arithm32_r.csproj deleted file mode 100644 index aab9e0160bcb..000000000000 --- a/src/tests/JIT/Methodical/NaN/arithm32_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/arithm32_ro.csproj b/src/tests/JIT/Methodical/NaN/arithm32_ro.csproj deleted file mode 100644 index cf6568f602c3..000000000000 --- a/src/tests/JIT/Methodical/NaN/arithm32_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/arithm64_d.csproj b/src/tests/JIT/Methodical/NaN/arithm64_d.csproj deleted file mode 100644 index 44cd6d87f5d1..000000000000 --- a/src/tests/JIT/Methodical/NaN/arithm64_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - full - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/arithm64_do.csproj b/src/tests/JIT/Methodical/NaN/arithm64_do.csproj deleted file mode 100644 index 0477ad657c29..000000000000 --- a/src/tests/JIT/Methodical/NaN/arithm64_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - full - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/arithm64_r.csproj b/src/tests/JIT/Methodical/NaN/arithm64_r.csproj deleted file mode 100644 index f7bbf7c0d96d..000000000000 --- a/src/tests/JIT/Methodical/NaN/arithm64_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/arithm64_ro.csproj b/src/tests/JIT/Methodical/NaN/arithm64_ro.csproj deleted file mode 100644 index 2f19dd595f51..000000000000 --- a/src/tests/JIT/Methodical/NaN/arithm64_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/intrinsic.cs b/src/tests/JIT/Methodical/NaN/intrinsic.cs index d963b7839785..51ef0970d1f6 100644 --- a/src/tests/JIT/Methodical/NaN/intrinsic.cs +++ b/src/tests/JIT/Methodical/NaN/intrinsic.cs @@ -486,6 +486,7 @@ private static void TestAtan2(double arg1, double arg2, double exp) } [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/NaN/intrinsic_cs_d.csproj b/src/tests/JIT/Methodical/NaN/intrinsic_cs_d.csproj deleted file mode 100644 index c71235481eb2..000000000000 --- a/src/tests/JIT/Methodical/NaN/intrinsic_cs_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - - Full - - - - - - diff --git a/src/tests/JIT/Methodical/NaN/intrinsic_cs_do.csproj b/src/tests/JIT/Methodical/NaN/intrinsic_cs_do.csproj deleted file mode 100644 index ce3d17234305..000000000000 --- a/src/tests/JIT/Methodical/NaN/intrinsic_cs_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/intrinsic_cs_r.csproj b/src/tests/JIT/Methodical/NaN/intrinsic_cs_r.csproj deleted file mode 100644 index c795356b316b..000000000000 --- a/src/tests/JIT/Methodical/NaN/intrinsic_cs_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - - None - - - - - - diff --git a/src/tests/JIT/Methodical/NaN/intrinsic_cs_ro.csproj b/src/tests/JIT/Methodical/NaN/intrinsic_cs_ro.csproj deleted file mode 100644 index 7b024d7ec8e6..000000000000 --- a/src/tests/JIT/Methodical/NaN/intrinsic_cs_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNadd.cs b/src/tests/JIT/Methodical/NaN/r4NaNadd.cs index 397e599598b5..a4910cd319b7 100644 --- a/src/tests/JIT/Methodical/NaN/r4NaNadd.cs +++ b/src/tests/JIT/Methodical/NaN/r4NaNadd.cs @@ -80,6 +80,7 @@ struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/NaN/r4NaNadd_cs_d.csproj b/src/tests/JIT/Methodical/NaN/r4NaNadd_cs_d.csproj deleted file mode 100644 index 64ec94f4e9bd..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNadd_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNadd_cs_do.csproj b/src/tests/JIT/Methodical/NaN/r4NaNadd_cs_do.csproj deleted file mode 100644 index 26421229e299..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNadd_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNadd_cs_r.csproj b/src/tests/JIT/Methodical/NaN/r4NaNadd_cs_r.csproj deleted file mode 100644 index 3953ab994c68..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNadd_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNadd_cs_ro.csproj b/src/tests/JIT/Methodical/NaN/r4NaNadd_cs_ro.csproj deleted file mode 100644 index eea14ca40680..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNadd_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNdiv.cs b/src/tests/JIT/Methodical/NaN/r4NaNdiv.cs index c8188e8bb759..467fa9c1b370 100644 --- a/src/tests/JIT/Methodical/NaN/r4NaNdiv.cs +++ b/src/tests/JIT/Methodical/NaN/r4NaNdiv.cs @@ -80,6 +80,7 @@ struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/NaN/r4NaNdiv_cs_d.csproj b/src/tests/JIT/Methodical/NaN/r4NaNdiv_cs_d.csproj deleted file mode 100644 index fcec16e76bc5..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNdiv_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNdiv_cs_do.csproj b/src/tests/JIT/Methodical/NaN/r4NaNdiv_cs_do.csproj deleted file mode 100644 index 7b5dea0c17da..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNdiv_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNdiv_cs_r.csproj b/src/tests/JIT/Methodical/NaN/r4NaNdiv_cs_r.csproj deleted file mode 100644 index a7b7c035e58a..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNdiv_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNdiv_cs_ro.csproj b/src/tests/JIT/Methodical/NaN/r4NaNdiv_cs_ro.csproj deleted file mode 100644 index f94063970f82..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNdiv_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNmul.cs b/src/tests/JIT/Methodical/NaN/r4NaNmul.cs index 3c1a480b0742..d122a85c058e 100644 --- a/src/tests/JIT/Methodical/NaN/r4NaNmul.cs +++ b/src/tests/JIT/Methodical/NaN/r4NaNmul.cs @@ -80,6 +80,7 @@ struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/NaN/r4NaNmul_cs_d.csproj b/src/tests/JIT/Methodical/NaN/r4NaNmul_cs_d.csproj deleted file mode 100644 index 35562db9e90a..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNmul_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNmul_cs_do.csproj b/src/tests/JIT/Methodical/NaN/r4NaNmul_cs_do.csproj deleted file mode 100644 index 61cb7b9a1b76..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNmul_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNmul_cs_r.csproj b/src/tests/JIT/Methodical/NaN/r4NaNmul_cs_r.csproj deleted file mode 100644 index 310b7867c869..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNmul_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNmul_cs_ro.csproj b/src/tests/JIT/Methodical/NaN/r4NaNmul_cs_ro.csproj deleted file mode 100644 index 57ae5e95cd5a..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNmul_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNrem.cs b/src/tests/JIT/Methodical/NaN/r4NaNrem.cs index 46d218f5223e..dc3e843ce315 100644 --- a/src/tests/JIT/Methodical/NaN/r4NaNrem.cs +++ b/src/tests/JIT/Methodical/NaN/r4NaNrem.cs @@ -80,6 +80,7 @@ struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/NaN/r4NaNrem_cs_d.csproj b/src/tests/JIT/Methodical/NaN/r4NaNrem_cs_d.csproj deleted file mode 100644 index 91734cf7f950..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNrem_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNrem_cs_do.csproj b/src/tests/JIT/Methodical/NaN/r4NaNrem_cs_do.csproj deleted file mode 100644 index 9a2ddd77f4d6..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNrem_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNrem_cs_r.csproj b/src/tests/JIT/Methodical/NaN/r4NaNrem_cs_r.csproj deleted file mode 100644 index 35a17465d4cc..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNrem_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNrem_cs_ro.csproj b/src/tests/JIT/Methodical/NaN/r4NaNrem_cs_ro.csproj deleted file mode 100644 index a8f22fa1361a..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNrem_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNsub.cs b/src/tests/JIT/Methodical/NaN/r4NaNsub.cs index 9f0e2bed91df..76b2abb42b63 100644 --- a/src/tests/JIT/Methodical/NaN/r4NaNsub.cs +++ b/src/tests/JIT/Methodical/NaN/r4NaNsub.cs @@ -80,6 +80,7 @@ struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/NaN/r4NaNsub_cs_d.csproj b/src/tests/JIT/Methodical/NaN/r4NaNsub_cs_d.csproj deleted file mode 100644 index 89dd7d3fed50..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNsub_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNsub_cs_do.csproj b/src/tests/JIT/Methodical/NaN/r4NaNsub_cs_do.csproj deleted file mode 100644 index 712afb92432a..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNsub_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNsub_cs_r.csproj b/src/tests/JIT/Methodical/NaN/r4NaNsub_cs_r.csproj deleted file mode 100644 index f1f7f425c998..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNsub_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r4NaNsub_cs_ro.csproj b/src/tests/JIT/Methodical/NaN/r4NaNsub_cs_ro.csproj deleted file mode 100644 index 24f100812c3b..000000000000 --- a/src/tests/JIT/Methodical/NaN/r4NaNsub_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNadd.cs b/src/tests/JIT/Methodical/NaN/r8NaNadd.cs index 684643af482d..13d8723dfb82 100644 --- a/src/tests/JIT/Methodical/NaN/r8NaNadd.cs +++ b/src/tests/JIT/Methodical/NaN/r8NaNadd.cs @@ -79,6 +79,7 @@ struct VT public double d_vt_test3_op2; } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/NaN/r8NaNadd_cs_d.csproj b/src/tests/JIT/Methodical/NaN/r8NaNadd_cs_d.csproj deleted file mode 100644 index 604fa3ce50f3..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNadd_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNadd_cs_do.csproj b/src/tests/JIT/Methodical/NaN/r8NaNadd_cs_do.csproj deleted file mode 100644 index d2ba9c82a66d..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNadd_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNadd_cs_r.csproj b/src/tests/JIT/Methodical/NaN/r8NaNadd_cs_r.csproj deleted file mode 100644 index 038c8b89a12f..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNadd_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNadd_cs_ro.csproj b/src/tests/JIT/Methodical/NaN/r8NaNadd_cs_ro.csproj deleted file mode 100644 index f1da836bd5b2..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNadd_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNdiv.cs b/src/tests/JIT/Methodical/NaN/r8NaNdiv.cs index ef79ddcc8801..37d23c4c754b 100644 --- a/src/tests/JIT/Methodical/NaN/r8NaNdiv.cs +++ b/src/tests/JIT/Methodical/NaN/r8NaNdiv.cs @@ -80,6 +80,7 @@ struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/NaN/r8NaNdiv_cs_d.csproj b/src/tests/JIT/Methodical/NaN/r8NaNdiv_cs_d.csproj deleted file mode 100644 index f23db0ddcc20..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNdiv_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNdiv_cs_do.csproj b/src/tests/JIT/Methodical/NaN/r8NaNdiv_cs_do.csproj deleted file mode 100644 index e75e94654741..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNdiv_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNdiv_cs_r.csproj b/src/tests/JIT/Methodical/NaN/r8NaNdiv_cs_r.csproj deleted file mode 100644 index dc6c9aa84d7e..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNdiv_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNdiv_cs_ro.csproj b/src/tests/JIT/Methodical/NaN/r8NaNdiv_cs_ro.csproj deleted file mode 100644 index df32d870bd11..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNdiv_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNmul.cs b/src/tests/JIT/Methodical/NaN/r8NaNmul.cs index 739904b3bfbc..0fcd266ded9e 100644 --- a/src/tests/JIT/Methodical/NaN/r8NaNmul.cs +++ b/src/tests/JIT/Methodical/NaN/r8NaNmul.cs @@ -80,6 +80,7 @@ struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/NaN/r8NaNmul_cs_d.csproj b/src/tests/JIT/Methodical/NaN/r8NaNmul_cs_d.csproj deleted file mode 100644 index f9fc826b6fa3..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNmul_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNmul_cs_do.csproj b/src/tests/JIT/Methodical/NaN/r8NaNmul_cs_do.csproj deleted file mode 100644 index 331b700789fa..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNmul_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNmul_cs_r.csproj b/src/tests/JIT/Methodical/NaN/r8NaNmul_cs_r.csproj deleted file mode 100644 index fed177b036e1..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNmul_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNmul_cs_ro.csproj b/src/tests/JIT/Methodical/NaN/r8NaNmul_cs_ro.csproj deleted file mode 100644 index 6af5b84510d0..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNmul_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNrem.cs b/src/tests/JIT/Methodical/NaN/r8NaNrem.cs index 69218ff1ab7a..3304e649a251 100644 --- a/src/tests/JIT/Methodical/NaN/r8NaNrem.cs +++ b/src/tests/JIT/Methodical/NaN/r8NaNrem.cs @@ -80,6 +80,7 @@ struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/NaN/r8NaNrem_cs_d.csproj b/src/tests/JIT/Methodical/NaN/r8NaNrem_cs_d.csproj deleted file mode 100644 index b96535f61969..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNrem_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNrem_cs_do.csproj b/src/tests/JIT/Methodical/NaN/r8NaNrem_cs_do.csproj deleted file mode 100644 index 69eea1d83849..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNrem_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNrem_cs_r.csproj b/src/tests/JIT/Methodical/NaN/r8NaNrem_cs_r.csproj deleted file mode 100644 index e880611ca992..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNrem_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNrem_cs_ro.csproj b/src/tests/JIT/Methodical/NaN/r8NaNrem_cs_ro.csproj deleted file mode 100644 index 4ac89aa4fd61..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNrem_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNsub.cs b/src/tests/JIT/Methodical/NaN/r8NaNsub.cs index 1138aaf6808e..15e5c4b0a9ef 100644 --- a/src/tests/JIT/Methodical/NaN/r8NaNsub.cs +++ b/src/tests/JIT/Methodical/NaN/r8NaNsub.cs @@ -79,6 +79,7 @@ struct VT public double d_vt_test3_op2; } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/NaN/r8NaNsub_cs_d.csproj b/src/tests/JIT/Methodical/NaN/r8NaNsub_cs_d.csproj deleted file mode 100644 index 56e7ff6e67ce..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNsub_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNsub_cs_do.csproj b/src/tests/JIT/Methodical/NaN/r8NaNsub_cs_do.csproj deleted file mode 100644 index 0569abad1702..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNsub_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNsub_cs_r.csproj b/src/tests/JIT/Methodical/NaN/r8NaNsub_cs_r.csproj deleted file mode 100644 index 7aae2abffb24..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNsub_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/NaN/r8NaNsub_cs_ro.csproj b/src/tests/JIT/Methodical/NaN/r8NaNsub_cs_ro.csproj deleted file mode 100644 index 2f057ee93fd8..000000000000 --- a/src/tests/JIT/Methodical/NaN/r8NaNsub_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt.cs b/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt.cs index 6065d9b96c65..96202353bfad 100644 --- a/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt.cs +++ b/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt.cs @@ -304,6 +304,7 @@ public static int TestValues() } [Fact] + [OuterLoop] public static int TestEntryPoint() { int res = TestValues(); diff --git a/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt_d.csproj b/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt_d.csproj deleted file mode 100644 index 422f6af75ccf..000000000000 --- a/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt_do.csproj b/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt_do.csproj deleted file mode 100644 index af67b9f5dfcc..000000000000 --- a/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt_r.csproj b/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt_r.csproj deleted file mode 100644 index 58b2ef94fd37..000000000000 --- a/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt_ro.csproj b/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt_ro.csproj deleted file mode 100644 index 319e759d1b41..000000000000 --- a/src/tests/JIT/Methodical/Overflow/FloatInfinitiesToInt_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2.cs b/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2.cs index 9b3226f44ca0..4c77ac4da01b 100644 --- a/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2.cs +++ b/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2.cs @@ -11,7 +11,7 @@ public class FloatOvfToInt { [MethodImpl(MethodImplOptions.NoInlining)] public static bool BreakUpFlow() => false; - + [MethodImpl(MethodImplOptions.NoInlining)] public static long FloatToLong(float f) { @@ -237,30 +237,30 @@ public static int TestValuesFloatLong() public static int TestValuesFloatLongVN() { float bigf = 100000000000000000000000000000.0f; - + if (BreakUpFlow()) return 1000; - + if (FloatToLong(bigf) != FloatToLongInline(bigf)) return 401; if (FloatToUlong(bigf) != FloatToUlongInline(bigf)) return 402; if (FloatToLong(-bigf) != FloatToLongInline(-bigf)) return 403; if (FloatToUlong(-bigf) != FloatToUlongInline(-bigf)) return 404; bigf = 987654321001234567899876543210.0f; - + if (BreakUpFlow()) return 1000; - + if (FloatToLong(bigf) != FloatToLongInline(bigf)) return 401; if (FloatToUlong(bigf) != FloatToUlongInline(bigf)) return 402; if (FloatToLong(-bigf) != FloatToLongInline(-bigf)) return 403; if (FloatToUlong(-bigf) != FloatToUlongInline(-bigf)) return 404; bigf = 254783961024896571038054632179.0f; - + if (BreakUpFlow()) return 1000; - + if (FloatToLong(bigf) != FloatToLongInline(bigf)) return 401; if (FloatToUlong(bigf) != FloatToUlongInline(bigf)) return 402; if (FloatToLong(-bigf) != FloatToLongInline(-bigf)) return 403; @@ -318,30 +318,30 @@ public static int TestValuesFloatInt() public static int TestValuesFloatIntVN() { float bigf = 100000000000000000000000000000.0f; - + if (BreakUpFlow()) return 1000; - + if (FloatToInt(bigf) != FloatToIntInline(bigf)) return 411; if (FloatToUint(bigf) != FloatToUintInline(bigf)) return 412; if (FloatToInt(-bigf) != FloatToIntInline(-bigf)) return 413; if (FloatToUint(-bigf) != FloatToUintInline(-bigf)) return 414; bigf = 987654321001234567899876543210.0f; - + if (BreakUpFlow()) return 1000; - + if (FloatToInt(bigf) != FloatToIntInline(bigf)) return 411; if (FloatToUint(bigf) != FloatToUintInline(bigf)) return 412; if (FloatToInt(-bigf) != FloatToIntInline(-bigf)) return 413; if (FloatToUint(-bigf) != FloatToUintInline(-bigf)) return 414; bigf = 254783961024896571038054632179.0f; - + if (BreakUpFlow()) return 1000; - + if (FloatToInt(bigf) != FloatToIntInline(bigf)) return 411; if (FloatToUint(bigf) != FloatToUintInline(bigf)) return 412; if (FloatToInt(-bigf) != FloatToIntInline(-bigf)) return 413; @@ -402,27 +402,27 @@ public static int TestValuesFloatShortVN() if (BreakUpFlow()) return 1000; - + if (FloatToShort(bigf) != FloatToShortInline(bigf)) return 421; if (FloatToUshort(bigf) != FloatToUshortInline(bigf)) return 422; if (FloatToShort(-bigf) != FloatToShortInline(-bigf)) return 423; if (FloatToUshort(-bigf) != FloatToUshortInline(-bigf)) return 424; bigf = 987654321001234567899876543210.0f; - + if (BreakUpFlow()) return 1000; - + if (FloatToShort(bigf) != FloatToShortInline(bigf)) return 421; if (FloatToUshort(bigf) != FloatToUshortInline(bigf)) return 422; if (FloatToShort(-bigf) != FloatToShortInline(-bigf)) return 423; if (FloatToUshort(-bigf) != FloatToUshortInline(-bigf)) return 424; bigf = 254783961024896571038054632179.0f; - + if (BreakUpFlow()) return 1000; - + if (FloatToShort(bigf) != FloatToShortInline(bigf)) return 421; if (FloatToUshort(bigf) != FloatToUshortInline(bigf)) return 422; if (FloatToShort(-bigf) != FloatToShortInline(-bigf)) return 423; @@ -480,30 +480,30 @@ public static int TestValuesFloatByte() public static int TestValuesFloatByteVN() { float bigf = 100000000000000000000000000000.0f; - + if (BreakUpFlow()) return 1000; - + if (FloatToSbyte(bigf) != FloatToSbyteInline(bigf)) return 441; if (FloatToByte(bigf) != FloatToByteInline(bigf)) return 442; if (FloatToSbyte(-bigf) != FloatToSbyteInline(-bigf)) return 443; if (FloatToByte(-bigf) != FloatToByteInline(-bigf)) return 444; bigf = 987654321001234567899876543210.0f; - + if (BreakUpFlow()) return 1000; - + if (FloatToSbyte(bigf) != FloatToSbyteInline(bigf)) return 441; if (FloatToByte(bigf) != FloatToByteInline(bigf)) return 442; if (FloatToSbyte(-bigf) != FloatToSbyteInline(-bigf)) return 443; if (FloatToByte(-bigf) != FloatToByteInline(-bigf)) return 444; bigf = 254783961024896571038054632179.0f; - + if (BreakUpFlow()) return 1000; - + if (FloatToSbyte(bigf) != FloatToSbyteInline(bigf)) return 441; if (FloatToByte(bigf) != FloatToByteInline(bigf)) return 442; if (FloatToSbyte(-bigf) != FloatToSbyteInline(-bigf)) return 443; @@ -538,30 +538,30 @@ public static int TestValuesFloatByteImport() public static int TestValuesDoubleLong() { double bigd = 100000000000000000000000000000.0; - + if (BreakUpFlow()) return 1000; - + if (DoubleToLong(bigd) != DoubleToLongInline(bigd)) return 201; if (DoubleToUlong(bigd) != DoubleToUlongInline(bigd)) return 202; if (DoubleToLong(-bigd) != DoubleToLongInline(-bigd)) return 203; if (DoubleToUlong(-bigd) != DoubleToUlongInline(-bigd)) return 204; bigd = 987654321001234567899876543210.0; - + if (BreakUpFlow()) return 1000; - + if (DoubleToLong(bigd) != DoubleToLongInline(bigd)) return 201; if (DoubleToUlong(bigd) != DoubleToUlongInline(bigd)) return 202; if (DoubleToLong(-bigd) != DoubleToLongInline(-bigd)) return 203; if (DoubleToUlong(-bigd) != DoubleToUlongInline(-bigd)) return 204; bigd = 254783961024896571038054632179.0; - + if (BreakUpFlow()) return 1000; - + if (DoubleToLong(bigd) != DoubleToLongInline(bigd)) return 201; if (DoubleToUlong(bigd) != DoubleToUlongInline(bigd)) return 202; if (DoubleToLong(-bigd) != DoubleToLongInline(-bigd)) return 203; @@ -642,30 +642,30 @@ public static int TestValuesDoubleInt() public static int TestValuesDoubleIntVN() { double bigd = 100000000000000000000000000000.0; - + if (BreakUpFlow()) return 1000; - + if (DoubleToInt(bigd) != DoubleToIntInline(bigd)) return 311; if (DoubleToUint(bigd) != DoubleToUintInline(bigd)) return 312; if (DoubleToInt(-bigd) != DoubleToIntInline(-bigd)) return 313; if (DoubleToUint(-bigd) != DoubleToUintInline(-bigd)) return 314; bigd = 987654321001234567899876543210.0; - + if (BreakUpFlow()) return 1000; - + if (DoubleToInt(bigd) != DoubleToIntInline(bigd)) return 311; if (DoubleToUint(bigd) != DoubleToUintInline(bigd)) return 312; if (DoubleToInt(-bigd) != DoubleToIntInline(-bigd)) return 313; if (DoubleToUint(-bigd) != DoubleToUintInline(-bigd)) return 314; bigd = 254783961024896571038054632179.0; - + if (BreakUpFlow()) return 1000; - + if (DoubleToInt(bigd) != DoubleToIntInline(bigd)) return 311; if (DoubleToUint(bigd) != DoubleToUintInline(bigd)) return 312; if (DoubleToInt(-bigd) != DoubleToIntInline(-bigd)) return 313; @@ -723,30 +723,30 @@ public static int TestValuesDoubleShort() public static int TestValuesDoubleShortVN() { double bigd = 100000000000000000000000000000.0; - + if (BreakUpFlow()) return 1000; - + if (DoubleToShort(bigd) != DoubleToShortInline(bigd)) return 321; if (DoubleToUshort(bigd) != DoubleToUshortInline(bigd)) return 322; if (DoubleToShort(-bigd) != DoubleToShortInline(-bigd)) return 323; if (DoubleToUshort(-bigd) != DoubleToUshortInline(-bigd)) return 324; bigd = 987654321001234567899876543210.0; - + if (BreakUpFlow()) return 1000; - + if (DoubleToShort(bigd) != DoubleToShortInline(bigd)) return 321; if (DoubleToUshort(bigd) != DoubleToUshortInline(bigd)) return 322; if (DoubleToShort(-bigd) != DoubleToShortInline(-bigd)) return 323; if (DoubleToUshort(-bigd) != DoubleToUshortInline(-bigd)) return 324; bigd = 254783961024896571038054632179.0; - + if (BreakUpFlow()) return 1000; - + if (DoubleToShort(bigd) != DoubleToShortInline(bigd)) return 321; if (DoubleToUshort(bigd) != DoubleToUshortInline(bigd)) return 322; if (DoubleToShort(-bigd) != DoubleToShortInline(-bigd)) return 323; @@ -804,30 +804,30 @@ public static int TestValuesDoubleByte() public static int TestValuesDoubleByteVN() { double bigd = 100000000000000000000000000000.0; - + if (BreakUpFlow()) return 1000; - + if (DoubleToSbyte(bigd) != DoubleToSbyteInline(bigd)) return 341; if (DoubleToByte(bigd) != DoubleToByteInline(bigd)) return 342; if (DoubleToSbyte(-bigd) != DoubleToSbyteInline(-bigd)) return 343; if (DoubleToByte(-bigd) != DoubleToByteInline(-bigd)) return 344; bigd = 987654321001234567899876543210.0; - + if (BreakUpFlow()) return 1000; - + if (DoubleToSbyte(bigd) != DoubleToSbyteInline(bigd)) return 341; if (DoubleToByte(bigd) != DoubleToByteInline(bigd)) return 342; if (DoubleToSbyte(-bigd) != DoubleToSbyteInline(-bigd)) return 343; if (DoubleToByte(-bigd) != DoubleToByteInline(-bigd)) return 344; bigd = 254783961024896571038054632179.0; - + if (BreakUpFlow()) return 1000; - + if (DoubleToSbyte(bigd) != DoubleToSbyteInline(bigd)) return 341; if (DoubleToByte(bigd) != DoubleToByteInline(bigd)) return 342; if (DoubleToSbyte(-bigd) != DoubleToSbyteInline(-bigd)) return 343; @@ -891,6 +891,7 @@ public static int TestValues() } [Fact] + [OuterLoop] public static int TestEntryPoint() { int res = TestValues(); diff --git a/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2_d.csproj b/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2_d.csproj deleted file mode 100644 index 57f519c54f26..000000000000 --- a/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2_do.csproj b/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2_do.csproj deleted file mode 100644 index bd606339512b..000000000000 --- a/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2_r.csproj b/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2_r.csproj deleted file mode 100644 index 8734cb7d210e..000000000000 --- a/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2_ro.csproj b/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2_ro.csproj deleted file mode 100644 index cf7fc648ddc9..000000000000 --- a/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/call.cs b/src/tests/JIT/Methodical/VT/callconv/call.cs index 81a50e54b17b..1bf32a8bdb5b 100644 --- a/src/tests/JIT/Methodical/VT/callconv/call.cs +++ b/src/tests/JIT/Methodical/VT/callconv/call.cs @@ -63,6 +63,7 @@ private static void TryInterface(ISomething smth) } [Fact] + [OuterLoop] public static int TestEntryPoint() { VT vt = new VT(10, "10"); diff --git a/src/tests/JIT/Methodical/VT/callconv/call_d.csproj b/src/tests/JIT/Methodical/VT/callconv/call_d.csproj deleted file mode 100644 index 783e0cc54930..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/call_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/call_do.csproj b/src/tests/JIT/Methodical/VT/callconv/call_do.csproj deleted file mode 100644 index d8e074eb4c82..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/call_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/call_r.csproj b/src/tests/JIT/Methodical/VT/callconv/call_r.csproj deleted file mode 100644 index a78f5ed8a431..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/call_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/call_ro.csproj b/src/tests/JIT/Methodical/VT/callconv/call_ro.csproj deleted file mode 100644 index 3610bd29efe9..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/call_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/jumper.cs b/src/tests/JIT/Methodical/VT/callconv/jumper.cs index d87be0ec09e2..09dd7821c44a 100644 --- a/src/tests/JIT/Methodical/VT/callconv/jumper.cs +++ b/src/tests/JIT/Methodical/VT/callconv/jumper.cs @@ -16,6 +16,7 @@ public struct VT private VT sub(VT what) { _m_n -= what._m_n; return this; } //this will be implemented via NEG+JMP in IL [Fact] + [OuterLoop] public static int TestEntryPoint() { VT vt = new VT(100); diff --git a/src/tests/JIT/Methodical/VT/callconv/jumper_d.csproj b/src/tests/JIT/Methodical/VT/callconv/jumper_d.csproj deleted file mode 100644 index cdcf248ea31e..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/jumper_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/jumper_do.csproj b/src/tests/JIT/Methodical/VT/callconv/jumper_do.csproj deleted file mode 100644 index 2d1838a9046b..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/jumper_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/jumper_r.csproj b/src/tests/JIT/Methodical/VT/callconv/jumper_r.csproj deleted file mode 100644 index c1ac8f764154..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/jumper_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/jumper_ro.csproj b/src/tests/JIT/Methodical/VT/callconv/jumper_ro.csproj deleted file mode 100644 index c9a4ab141efa..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/jumper_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/jumps.cs b/src/tests/JIT/Methodical/VT/callconv/jumps.cs index 22fea84250e4..386806c19dec 100644 --- a/src/tests/JIT/Methodical/VT/callconv/jumps.cs +++ b/src/tests/JIT/Methodical/VT/callconv/jumps.cs @@ -83,6 +83,7 @@ private bool RunTests() } [Fact] + [OuterLoop] public static int TestEntryPoint() { if (new VT().RunTests()) diff --git a/src/tests/JIT/Methodical/VT/callconv/jumps_d.csproj b/src/tests/JIT/Methodical/VT/callconv/jumps_d.csproj deleted file mode 100644 index a90081b54932..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/jumps_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/jumps_do.csproj b/src/tests/JIT/Methodical/VT/callconv/jumps_do.csproj deleted file mode 100644 index b2aa3c37b49d..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/jumps_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/jumps_r.csproj b/src/tests/JIT/Methodical/VT/callconv/jumps_r.csproj deleted file mode 100644 index 51b80695c8c6..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/jumps_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/jumps_ro.csproj b/src/tests/JIT/Methodical/VT/callconv/jumps_ro.csproj deleted file mode 100644 index 86eb6bd19d50..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/jumps_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/vtret.cs b/src/tests/JIT/Methodical/VT/callconv/vtret.cs index 336a5c101d55..1196a05a3590 100644 --- a/src/tests/JIT/Methodical/VT/callconv/vtret.cs +++ b/src/tests/JIT/Methodical/VT/callconv/vtret.cs @@ -16,6 +16,7 @@ public struct VT private static VT sub(VT me, VT what) { me._m_n -= what._m_n; return me; } [Fact] + [OuterLoop] public static int TestEntryPoint() { VT vt = new VT(100); diff --git a/src/tests/JIT/Methodical/VT/callconv/vtret_d.csproj b/src/tests/JIT/Methodical/VT/callconv/vtret_d.csproj deleted file mode 100644 index 998ef01e8bd8..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/vtret_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/vtret_do.csproj b/src/tests/JIT/Methodical/VT/callconv/vtret_do.csproj deleted file mode 100644 index 1265a39a4976..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/vtret_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/vtret_r.csproj b/src/tests/JIT/Methodical/VT/callconv/vtret_r.csproj deleted file mode 100644 index 5e471fda3326..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/vtret_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/callconv/vtret_ro.csproj b/src/tests/JIT/Methodical/VT/callconv/vtret_ro.csproj deleted file mode 100644 index c6ea34a1bdc5..000000000000 --- a/src/tests/JIT/Methodical/VT/callconv/vtret_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/ctor_recurse.cs b/src/tests/JIT/Methodical/VT/etc/ctor_recurse.cs index 39cc3852288e..9c7e2bb59bb7 100644 --- a/src/tests/JIT/Methodical/VT/etc/ctor_recurse.cs +++ b/src/tests/JIT/Methodical/VT/etc/ctor_recurse.cs @@ -23,6 +23,7 @@ public struct T private void DoMethod() { } [Fact] + [OuterLoop] public static void TestEntryPoint() { s_stat = diff --git a/src/tests/JIT/Methodical/VT/etc/ctor_recurse_d.csproj b/src/tests/JIT/Methodical/VT/etc/ctor_recurse_d.csproj deleted file mode 100644 index 80cf61341b6a..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/ctor_recurse_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/ctor_recurse_do.csproj b/src/tests/JIT/Methodical/VT/etc/ctor_recurse_do.csproj deleted file mode 100644 index 8b12341eb1e2..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/ctor_recurse_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/ctor_recurse_r.csproj b/src/tests/JIT/Methodical/VT/etc/ctor_recurse_r.csproj deleted file mode 100644 index 5fce53b67fde..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/ctor_recurse_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/ctor_recurse_ro.csproj b/src/tests/JIT/Methodical/VT/etc/ctor_recurse_ro.csproj deleted file mode 100644 index 721f72e455bd..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/ctor_recurse_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/gc_nested.cs b/src/tests/JIT/Methodical/VT/etc/gc_nested.cs index c0b0b8a51939..dd48445a7b8f 100644 --- a/src/tests/JIT/Methodical/VT/etc/gc_nested.cs +++ b/src/tests/JIT/Methodical/VT/etc/gc_nested.cs @@ -30,6 +30,7 @@ public void Verify() public class Test { [Fact] + [OuterLoop] public static void TestEntryPoint() { Struct1 str1 = new Struct1(); diff --git a/src/tests/JIT/Methodical/VT/etc/gc_nested_d.csproj b/src/tests/JIT/Methodical/VT/etc/gc_nested_d.csproj deleted file mode 100644 index e58b54ee1eed..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/gc_nested_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/gc_nested_do.csproj b/src/tests/JIT/Methodical/VT/etc/gc_nested_do.csproj deleted file mode 100644 index b766dd459d66..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/gc_nested_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/gc_nested_r.csproj b/src/tests/JIT/Methodical/VT/etc/gc_nested_r.csproj deleted file mode 100644 index 00658c805499..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/gc_nested_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/gc_nested_ro.csproj b/src/tests/JIT/Methodical/VT/etc/gc_nested_ro.csproj deleted file mode 100644 index a0da270972ce..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/gc_nested_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han2.cs b/src/tests/JIT/Methodical/VT/etc/han2.cs index 40c53f37e948..0c14541ea236 100644 --- a/src/tests/JIT/Methodical/VT/etc/han2.cs +++ b/src/tests/JIT/Methodical/VT/etc/han2.cs @@ -67,6 +67,7 @@ private static int move(Column from, Column to, Column temp, int num) } [Fact] + [OuterLoop] public static void TestEntryPoint() { int NUM = 17; diff --git a/src/tests/JIT/Methodical/VT/etc/han2_d.csproj b/src/tests/JIT/Methodical/VT/etc/han2_d.csproj deleted file mode 100644 index d953f3c66bbb..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han2_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han2_do.csproj b/src/tests/JIT/Methodical/VT/etc/han2_do.csproj deleted file mode 100644 index b68f0766a2b5..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han2_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han2_r.csproj b/src/tests/JIT/Methodical/VT/etc/han2_r.csproj deleted file mode 100644 index 6c26092aa5b3..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han2_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han2_ro.csproj b/src/tests/JIT/Methodical/VT/etc/han2_ro.csproj deleted file mode 100644 index 90015c6f7ad5..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han2_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han3.cs b/src/tests/JIT/Methodical/VT/etc/han3.cs index 77a266004769..0405fc441617 100644 --- a/src/tests/JIT/Methodical/VT/etc/han3.cs +++ b/src/tests/JIT/Methodical/VT/etc/han3.cs @@ -67,6 +67,7 @@ private static int move(Column from, Column to, Column temp, int num) } [Fact] + [OuterLoop] public static void TestEntryPoint() { int NUM = 17; diff --git a/src/tests/JIT/Methodical/VT/etc/han3_ctor.cs b/src/tests/JIT/Methodical/VT/etc/han3_ctor.cs index 5a7121d3cf8d..872964542e23 100644 --- a/src/tests/JIT/Methodical/VT/etc/han3_ctor.cs +++ b/src/tests/JIT/Methodical/VT/etc/han3_ctor.cs @@ -70,6 +70,7 @@ private static int move(Column from, Column to, Column temp, int num) } [Fact] + [OuterLoop] public static int TestEntryPoint() { return move(new Column(17, 17), diff --git a/src/tests/JIT/Methodical/VT/etc/han3_ctor_d.csproj b/src/tests/JIT/Methodical/VT/etc/han3_ctor_d.csproj deleted file mode 100644 index ec10b1cc5ba6..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han3_ctor_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han3_ctor_do.csproj b/src/tests/JIT/Methodical/VT/etc/han3_ctor_do.csproj deleted file mode 100644 index 8c257be25c81..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han3_ctor_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han3_ctor_r.csproj b/src/tests/JIT/Methodical/VT/etc/han3_ctor_r.csproj deleted file mode 100644 index 25e09168a5a9..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han3_ctor_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han3_ctor_ro.csproj b/src/tests/JIT/Methodical/VT/etc/han3_ctor_ro.csproj deleted file mode 100644 index c1643f675843..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han3_ctor_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han3_d.csproj b/src/tests/JIT/Methodical/VT/etc/han3_d.csproj deleted file mode 100644 index 7d0d69ee3aa3..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han3_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han3_do.csproj b/src/tests/JIT/Methodical/VT/etc/han3_do.csproj deleted file mode 100644 index dcbe3720d026..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han3_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han3_r.csproj b/src/tests/JIT/Methodical/VT/etc/han3_r.csproj deleted file mode 100644 index a624c728b7a6..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han3_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han3_ref.cs b/src/tests/JIT/Methodical/VT/etc/han3_ref.cs index 4255c8ecb382..cdee3fdd4f5d 100644 --- a/src/tests/JIT/Methodical/VT/etc/han3_ref.cs +++ b/src/tests/JIT/Methodical/VT/etc/han3_ref.cs @@ -70,6 +70,7 @@ private static int move(ref Column from, ref Column to, ref Column temp, int num } [Fact] + [OuterLoop] public static int TestEntryPoint() { Column c1 = new Column(17, 17); diff --git a/src/tests/JIT/Methodical/VT/etc/han3_ref_d.csproj b/src/tests/JIT/Methodical/VT/etc/han3_ref_d.csproj deleted file mode 100644 index 4a90deae7229..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han3_ref_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han3_ref_do.csproj b/src/tests/JIT/Methodical/VT/etc/han3_ref_do.csproj deleted file mode 100644 index 8c80c1fb00a2..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han3_ref_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han3_ref_r.csproj b/src/tests/JIT/Methodical/VT/etc/han3_ref_r.csproj deleted file mode 100644 index 4c2d1071ab81..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han3_ref_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han3_ref_ro.csproj b/src/tests/JIT/Methodical/VT/etc/han3_ref_ro.csproj deleted file mode 100644 index 18816ae553da..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han3_ref_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/han3_ro.csproj b/src/tests/JIT/Methodical/VT/etc/han3_ro.csproj deleted file mode 100644 index e6c5b1ee9cc9..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/han3_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/hanoi.cs b/src/tests/JIT/Methodical/VT/etc/hanoi.cs index ca678c3f1595..88329b728ef7 100644 --- a/src/tests/JIT/Methodical/VT/etc/hanoi.cs +++ b/src/tests/JIT/Methodical/VT/etc/hanoi.cs @@ -54,6 +54,7 @@ private static int move(CI from, CI to, int num) } [Fact] + [OuterLoop] public static void TestEntryPoint() { int NUM = 17; diff --git a/src/tests/JIT/Methodical/VT/etc/hanoi_d.csproj b/src/tests/JIT/Methodical/VT/etc/hanoi_d.csproj deleted file mode 100644 index c2bd380aa0eb..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/hanoi_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/hanoi_do.csproj b/src/tests/JIT/Methodical/VT/etc/hanoi_do.csproj deleted file mode 100644 index 10e7c15e3dc6..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/hanoi_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/hanoi_r.csproj b/src/tests/JIT/Methodical/VT/etc/hanoi_r.csproj deleted file mode 100644 index 1b5e30b28342..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/hanoi_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/hanoi_ro.csproj b/src/tests/JIT/Methodical/VT/etc/hanoi_ro.csproj deleted file mode 100644 index 321b98d9b556..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/hanoi_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/knight.cs b/src/tests/JIT/Methodical/VT/etc/knight.cs index e474b3e5d8d9..00712cf4403c 100644 --- a/src/tests/JIT/Methodical/VT/etc/knight.cs +++ b/src/tests/JIT/Methodical/VT/etc/knight.cs @@ -16,6 +16,7 @@ public struct SQ public int visited; [Fact] + [OuterLoop] public static int TestEntryPoint() { const int SIZE = 5; diff --git a/src/tests/JIT/Methodical/VT/etc/knight_d.csproj b/src/tests/JIT/Methodical/VT/etc/knight_d.csproj deleted file mode 100644 index 05e0e7966e76..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/knight_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/knight_do.csproj b/src/tests/JIT/Methodical/VT/etc/knight_do.csproj deleted file mode 100644 index 31f54077db10..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/knight_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/knight_r.csproj b/src/tests/JIT/Methodical/VT/etc/knight_r.csproj deleted file mode 100644 index b72aeeee2b0e..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/knight_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/knight_ro.csproj b/src/tests/JIT/Methodical/VT/etc/knight_ro.csproj deleted file mode 100644 index bde2fd075ff2..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/knight_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/nested.cs b/src/tests/JIT/Methodical/VT/etc/nested.cs index bfea224d6096..23645cc4aacd 100644 --- a/src/tests/JIT/Methodical/VT/etc/nested.cs +++ b/src/tests/JIT/Methodical/VT/etc/nested.cs @@ -30,6 +30,7 @@ public void Verify() public class Test { [Fact] + [OuterLoop] public static void TestEntryPoint() { Struct1 str1 = new Struct1(); diff --git a/src/tests/JIT/Methodical/VT/etc/nested_d.csproj b/src/tests/JIT/Methodical/VT/etc/nested_d.csproj deleted file mode 100644 index 77815ce743f0..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/nested_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/nested_do.csproj b/src/tests/JIT/Methodical/VT/etc/nested_do.csproj deleted file mode 100644 index 40c2ad576daa..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/nested_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/nested_r.csproj b/src/tests/JIT/Methodical/VT/etc/nested_r.csproj deleted file mode 100644 index fdc17935b00f..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/nested_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/etc/nested_ro.csproj b/src/tests/JIT/Methodical/VT/etc/nested_ro.csproj deleted file mode 100644 index fe4a0d1e957b..000000000000 --- a/src/tests/JIT/Methodical/VT/etc/nested_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/identity/accum.cs b/src/tests/JIT/Methodical/VT/identity/accum.cs index 32b24fef345e..9e1338dff777 100644 --- a/src/tests/JIT/Methodical/VT/identity/accum.cs +++ b/src/tests/JIT/Methodical/VT/identity/accum.cs @@ -18,6 +18,7 @@ private static int test(CI c1, CI c2, CI c3, int dummy, CI c4, CI c5) } [Fact] + [OuterLoop] public static int TestEntryPoint() { CI c = new CI(); diff --git a/src/tests/JIT/Methodical/VT/identity/accum_d.csproj b/src/tests/JIT/Methodical/VT/identity/accum_d.csproj deleted file mode 100644 index de0ec314d449..000000000000 --- a/src/tests/JIT/Methodical/VT/identity/accum_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/identity/accum_do.csproj b/src/tests/JIT/Methodical/VT/identity/accum_do.csproj deleted file mode 100644 index a958230147e7..000000000000 --- a/src/tests/JIT/Methodical/VT/identity/accum_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/identity/accum_r.csproj b/src/tests/JIT/Methodical/VT/identity/accum_r.csproj deleted file mode 100644 index 26613268f5c3..000000000000 --- a/src/tests/JIT/Methodical/VT/identity/accum_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/identity/accum_ro.csproj b/src/tests/JIT/Methodical/VT/identity/accum_ro.csproj deleted file mode 100644 index 92609f43678b..000000000000 --- a/src/tests/JIT/Methodical/VT/identity/accum_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/identity/vcall.cs b/src/tests/JIT/Methodical/VT/identity/vcall.cs index f726df64c3f6..e5a12121157b 100644 --- a/src/tests/JIT/Methodical/VT/identity/vcall.cs +++ b/src/tests/JIT/Methodical/VT/identity/vcall.cs @@ -17,6 +17,7 @@ private static void Test(VT arg1, ref VT arg2) } [Fact] + [OuterLoop] public static int TestEntryPoint() { VT vt; diff --git a/src/tests/JIT/Methodical/VT/identity/vcall_d.csproj b/src/tests/JIT/Methodical/VT/identity/vcall_d.csproj deleted file mode 100644 index b81a3dccd2cc..000000000000 --- a/src/tests/JIT/Methodical/VT/identity/vcall_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/identity/vcall_do.csproj b/src/tests/JIT/Methodical/VT/identity/vcall_do.csproj deleted file mode 100644 index bb381e561926..000000000000 --- a/src/tests/JIT/Methodical/VT/identity/vcall_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/identity/vcall_r.csproj b/src/tests/JIT/Methodical/VT/identity/vcall_r.csproj deleted file mode 100644 index 14b060119f4e..000000000000 --- a/src/tests/JIT/Methodical/VT/identity/vcall_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/identity/vcall_ro.csproj b/src/tests/JIT/Methodical/VT/identity/vcall_ro.csproj deleted file mode 100644 index ed2bca406231..000000000000 --- a/src/tests/JIT/Methodical/VT/identity/vcall_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/port/lcs.cs b/src/tests/JIT/Methodical/VT/port/lcs.cs index 541c3f103c73..100c5bfa77c7 100644 --- a/src/tests/JIT/Methodical/VT/port/lcs.cs +++ b/src/tests/JIT/Methodical/VT/port/lcs.cs @@ -90,6 +90,7 @@ private static void findLCS(LCSV[,,,] c, LCSV[,,,] b, char[][] seq, LCSV[] len) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Console.WriteLine("Test searches for longest common subsequence of 4 strings\n\n"); diff --git a/src/tests/JIT/Methodical/VT/port/lcs_gcref.cs b/src/tests/JIT/Methodical/VT/port/lcs_gcref.cs index 5b6f2a132569..34defadc1b8c 100644 --- a/src/tests/JIT/Methodical/VT/port/lcs_gcref.cs +++ b/src/tests/JIT/Methodical/VT/port/lcs_gcref.cs @@ -100,6 +100,7 @@ private static void findLCS(LCSV[,,,] c, LCSV[,,,] b, char[][] seq, LCSV[] len) } [Fact] + [SkipOnCoreClr("This test is not compatible with GCStress.", RuntimeTestModes.AnyGCStress)] public static int TestEntryPoint() { Console.WriteLine("Test searches for longest common subsequence of 4 strings\n\n"); diff --git a/src/tests/JIT/Methodical/VT/port/lcs_gcref_d.csproj b/src/tests/JIT/Methodical/VT/port/lcs_gcref_d.csproj deleted file mode 100644 index bdd81d214901..000000000000 --- a/src/tests/JIT/Methodical/VT/port/lcs_gcref_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - true - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/port/lcs_gcref_do.csproj b/src/tests/JIT/Methodical/VT/port/lcs_gcref_do.csproj deleted file mode 100644 index d5b0ed05c75f..000000000000 --- a/src/tests/JIT/Methodical/VT/port/lcs_gcref_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - true - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/port/lcs_gcref_r.csproj b/src/tests/JIT/Methodical/VT/port/lcs_gcref_r.csproj deleted file mode 100644 index 14c8c0be8442..000000000000 --- a/src/tests/JIT/Methodical/VT/port/lcs_gcref_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - true - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/port/lcs_gcref_ro.csproj b/src/tests/JIT/Methodical/VT/port/lcs_gcref_ro.csproj deleted file mode 100644 index 9f728f13a700..000000000000 --- a/src/tests/JIT/Methodical/VT/port/lcs_gcref_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - true - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/port/lcs_port_d.csproj b/src/tests/JIT/Methodical/VT/port/lcs_port_d.csproj deleted file mode 100644 index 1cf5fa05ed4e..000000000000 --- a/src/tests/JIT/Methodical/VT/port/lcs_port_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/port/lcs_port_do.csproj b/src/tests/JIT/Methodical/VT/port/lcs_port_do.csproj deleted file mode 100644 index f750def602a4..000000000000 --- a/src/tests/JIT/Methodical/VT/port/lcs_port_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/VT/port/lcs_port_r.csproj b/src/tests/JIT/Methodical/VT/port/lcs_port_r.csproj deleted file mode 100644 index 421d13320872..000000000000 --- a/src/tests/JIT/Methodical/VT/port/lcs_port_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/VT/port/lcs_port_ro.csproj b/src/tests/JIT/Methodical/VT/port/lcs_port_ro.csproj deleted file mode 100644 index 6cb7027fd196..000000000000 --- a/src/tests/JIT/Methodical/VT/port/lcs_port_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/SEH/cast_throw.cs b/src/tests/JIT/Methodical/casts/SEH/cast_throw.cs index 50b858c83f28..d4c0a0afc61d 100644 --- a/src/tests/JIT/Methodical/casts/SEH/cast_throw.cs +++ b/src/tests/JIT/Methodical/casts/SEH/cast_throw.cs @@ -10,6 +10,7 @@ internal class DerivedException : BaseException { } public class Test_cast_throw { [Fact] + [OuterLoop] public static int TestEntryPoint() { BaseException ex = new DerivedException(); diff --git a/src/tests/JIT/Methodical/casts/SEH/cast_throw_d.csproj b/src/tests/JIT/Methodical/casts/SEH/cast_throw_d.csproj deleted file mode 100644 index 3ff53e6bd1b4..000000000000 --- a/src/tests/JIT/Methodical/casts/SEH/cast_throw_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/SEH/cast_throw_do.csproj b/src/tests/JIT/Methodical/casts/SEH/cast_throw_do.csproj deleted file mode 100644 index 2332813a16cc..000000000000 --- a/src/tests/JIT/Methodical/casts/SEH/cast_throw_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/SEH/cast_throw_r.csproj b/src/tests/JIT/Methodical/casts/SEH/cast_throw_r.csproj deleted file mode 100644 index a0b3d6f9215b..000000000000 --- a/src/tests/JIT/Methodical/casts/SEH/cast_throw_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/SEH/cast_throw_ro.csproj b/src/tests/JIT/Methodical/casts/SEH/cast_throw_ro.csproj deleted file mode 100644 index 998481bb1743..000000000000 --- a/src/tests/JIT/Methodical/casts/SEH/cast_throw_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/SEH/throw_d.csproj b/src/tests/JIT/Methodical/casts/SEH/throw_d.csproj deleted file mode 100644 index d0422f126ad4..000000000000 --- a/src/tests/JIT/Methodical/casts/SEH/throw_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/SEH/throw_do.csproj b/src/tests/JIT/Methodical/casts/SEH/throw_do.csproj deleted file mode 100644 index 8a9baf1d90ee..000000000000 --- a/src/tests/JIT/Methodical/casts/SEH/throw_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/SEH/throw_r.csproj b/src/tests/JIT/Methodical/casts/SEH/throw_r.csproj deleted file mode 100644 index cf3e1f1bcecf..000000000000 --- a/src/tests/JIT/Methodical/casts/SEH/throw_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/SEH/throw_ro.csproj b/src/tests/JIT/Methodical/casts/SEH/throw_ro.csproj deleted file mode 100644 index 51221089f4fc..000000000000 --- a/src/tests/JIT/Methodical/casts/SEH/throw_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_call_d.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_call_d.csproj deleted file mode 100644 index 9ccb94b8246a..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_call_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_call_do.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_call_do.csproj deleted file mode 100644 index f8d0fedcea08..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_call_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_call_r.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_call_r.csproj deleted file mode 100644 index 77b6b3b8fe8a..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_call_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_call_ro.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_call_ro.csproj deleted file mode 100644 index bffd6f7c6358..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_call_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_ldarg_d.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_ldarg_d.csproj deleted file mode 100644 index abeed829a1f0..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_ldarg_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_ldarg_do.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_ldarg_do.csproj deleted file mode 100644 index 8fec721c42ef..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_ldarg_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_ldarg_r.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_ldarg_r.csproj deleted file mode 100644 index 6aa5aa46e940..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_ldarg_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_ldarg_ro.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_ldarg_ro.csproj deleted file mode 100644 index ef44fdfae5a0..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_ldarg_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_ldloc_d.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_ldloc_d.csproj deleted file mode 100644 index 4cb35825029c..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_ldloc_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_ldloc_do.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_ldloc_do.csproj deleted file mode 100644 index caeaddb532fe..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_ldloc_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_ldloc_r.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_ldloc_r.csproj deleted file mode 100644 index 37131729b28c..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_ldloc_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_ldloc_ro.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_ldloc_ro.csproj deleted file mode 100644 index b89f1a6a0888..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_ldloc_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_newobj_d.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_newobj_d.csproj deleted file mode 100644 index 133fc3b3dc82..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_newobj_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_newobj_do.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_newobj_do.csproj deleted file mode 100644 index 9134b3d7c3a9..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_newobj_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_newobj_r.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_newobj_r.csproj deleted file mode 100644 index 2dd96314b073..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_newobj_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/castclass_newobj_ro.csproj b/src/tests/JIT/Methodical/casts/coverage/castclass_newobj_ro.csproj deleted file mode 100644 index 4d27f7e352c3..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/castclass_newobj_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_call.cs b/src/tests/JIT/Methodical/casts/coverage/isinst_call.cs index e8d9dbd040c0..01c1f0ec04f5 100644 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_call.cs +++ b/src/tests/JIT/Methodical/casts/coverage/isinst_call.cs @@ -50,6 +50,7 @@ private static bool Test_CALL(int cookie, bool flag) } [Fact] + [OuterLoop] public static int TestEntryPoint() { if (!Test_CALL(0, true)) diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_call_d.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_call_d.csproj deleted file mode 100644 index 438144cc3b4b..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_call_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_call_do.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_call_do.csproj deleted file mode 100644 index d5be37c01cd4..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_call_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_call_r.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_call_r.csproj deleted file mode 100644 index 96d27c1d52ba..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_call_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_call_ro.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_call_ro.csproj deleted file mode 100644 index 421f0bfec31b..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_call_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg.cs b/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg.cs index fb3be6455d39..1c23ea4e3776 100644 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg.cs +++ b/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg.cs @@ -33,6 +33,7 @@ private static bool Test_LDARG(object obj, bool flag) } [Fact] + [OuterLoop] public static int TestEntryPoint() { if (!Test_LDARG(new TestClass(), true)) diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg_d.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg_d.csproj deleted file mode 100644 index 09556e49f06e..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg_do.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg_do.csproj deleted file mode 100644 index f4a1c3f8d88c..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg_r.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg_r.csproj deleted file mode 100644 index af3a549ee753..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg_ro.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg_ro.csproj deleted file mode 100644 index 232f43da6762..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_ldarg_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc.cs b/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc.cs index 39881e50fdc9..826f4a3b39c0 100644 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc.cs +++ b/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc.cs @@ -34,6 +34,7 @@ private static bool Test_LDLOC(object _obj, bool flag) } [Fact] + [OuterLoop] public static int TestEntryPoint() { if (!Test_LDLOC(new TestClass(), true)) diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc_d.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc_d.csproj deleted file mode 100644 index 1d4336deda38..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc_do.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc_do.csproj deleted file mode 100644 index a506d8d3ac84..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc_r.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc_r.csproj deleted file mode 100644 index ecc73fc3c2ce..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc_ro.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc_ro.csproj deleted file mode 100644 index df508d31d0e6..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_ldloc_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_newobj.cs b/src/tests/JIT/Methodical/casts/coverage/isinst_newobj.cs index 4e7563dceb5c..c7448ba8a927 100644 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_newobj.cs +++ b/src/tests/JIT/Methodical/casts/coverage/isinst_newobj.cs @@ -49,6 +49,7 @@ private static bool Test_NEWOBJ(TestClass _this, int cookie, bool flag) } [Fact] + [OuterLoop] public static int TestEntryPoint() { TestClass _this = new TestClass(); diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_newobj_d.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_newobj_d.csproj deleted file mode 100644 index 7706b734b03e..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_newobj_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_newobj_do.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_newobj_do.csproj deleted file mode 100644 index 5cff27368e19..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_newobj_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_newobj_r.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_newobj_r.csproj deleted file mode 100644 index bfa18c5cb475..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_newobj_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/coverage/isinst_newobj_ro.csproj b/src/tests/JIT/Methodical/casts/coverage/isinst_newobj_ro.csproj deleted file mode 100644 index b7c2dfff76eb..000000000000 --- a/src/tests/JIT/Methodical/casts/coverage/isinst_newobj_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/iface/iface1_d.csproj b/src/tests/JIT/Methodical/casts/iface/iface1_d.csproj deleted file mode 100644 index 95cf71986f56..000000000000 --- a/src/tests/JIT/Methodical/casts/iface/iface1_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/iface/iface1_do.csproj b/src/tests/JIT/Methodical/casts/iface/iface1_do.csproj deleted file mode 100644 index 27e353c81cb2..000000000000 --- a/src/tests/JIT/Methodical/casts/iface/iface1_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/iface/iface1_r.csproj b/src/tests/JIT/Methodical/casts/iface/iface1_r.csproj deleted file mode 100644 index dd51799d80bd..000000000000 --- a/src/tests/JIT/Methodical/casts/iface/iface1_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/casts/iface/iface1_ro.csproj b/src/tests/JIT/Methodical/casts/iface/iface1_ro.csproj deleted file mode 100644 index 59f6378b41e3..000000000000 --- a/src/tests/JIT/Methodical/casts/iface/iface1_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/ilseq/CommonBase_il_r.csproj b/src/tests/JIT/Methodical/casts/ilseq/CommonBase_il_r.csproj deleted file mode 100644 index 93f737397ab5..000000000000 --- a/src/tests/JIT/Methodical/casts/ilseq/CommonBase_il_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/casts/ilseq/commonBase.cs b/src/tests/JIT/Methodical/casts/ilseq/commonBase.cs index 36b24511d234..5bd21d23e3cc 100644 --- a/src/tests/JIT/Methodical/casts/ilseq/commonBase.cs +++ b/src/tests/JIT/Methodical/casts/ilseq/commonBase.cs @@ -43,6 +43,7 @@ private static int Bug(object o) } [Fact] + [OuterLoop] public static int TestEntryPoint() { return Bug(new Sibling2()); diff --git a/src/tests/JIT/Methodical/cctor/misc/Desktop/throw_Desktop_cs_d.csproj b/src/tests/JIT/Methodical/cctor/misc/Desktop/throw_Desktop_cs_d.csproj deleted file mode 100644 index d0422f126ad4..000000000000 --- a/src/tests/JIT/Methodical/cctor/misc/Desktop/throw_Desktop_cs_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/cctor/misc/Desktop/throw_Desktop_cs_do.csproj b/src/tests/JIT/Methodical/cctor/misc/Desktop/throw_Desktop_cs_do.csproj deleted file mode 100644 index 8a9baf1d90ee..000000000000 --- a/src/tests/JIT/Methodical/cctor/misc/Desktop/throw_Desktop_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/cctor/misc/Desktop/throw_Desktop_cs_r.csproj b/src/tests/JIT/Methodical/cctor/misc/Desktop/throw_Desktop_cs_r.csproj deleted file mode 100644 index cf3e1f1bcecf..000000000000 --- a/src/tests/JIT/Methodical/cctor/misc/Desktop/throw_Desktop_cs_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/cctor/misc/Desktop/throw_Desktop_cs_ro.csproj b/src/tests/JIT/Methodical/cctor/misc/Desktop/throw_Desktop_cs_ro.csproj deleted file mode 100644 index 51221089f4fc..000000000000 --- a/src/tests/JIT/Methodical/cctor/misc/Desktop/throw_Desktop_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/cctor/misc/assemname.cs b/src/tests/JIT/Methodical/cctor/misc/assemname.cs index 3f8d0be75201..f4744279d0c3 100644 --- a/src/tests/JIT/Methodical/cctor/misc/assemname.cs +++ b/src/tests/JIT/Methodical/cctor/misc/assemname.cs @@ -11,6 +11,7 @@ namespace Precise public class Driver_assemname { [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/cctor/misc/assemname_cs_d.csproj b/src/tests/JIT/Methodical/cctor/misc/assemname_cs_d.csproj deleted file mode 100644 index ae32f910d880..000000000000 --- a/src/tests/JIT/Methodical/cctor/misc/assemname_cs_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - Full - - - - - - - diff --git a/src/tests/JIT/Methodical/cctor/misc/assemname_cs_do.csproj b/src/tests/JIT/Methodical/cctor/misc/assemname_cs_do.csproj deleted file mode 100644 index 6f7dbf409299..000000000000 --- a/src/tests/JIT/Methodical/cctor/misc/assemname_cs_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - Full - True - - - - - - diff --git a/src/tests/JIT/Methodical/cctor/misc/assemname_cs_r.csproj b/src/tests/JIT/Methodical/cctor/misc/assemname_cs_r.csproj deleted file mode 100644 index 937996abc9bb..000000000000 --- a/src/tests/JIT/Methodical/cctor/misc/assemname_cs_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - None - - - - - - - diff --git a/src/tests/JIT/Methodical/cctor/misc/assemname_cs_ro.csproj b/src/tests/JIT/Methodical/cctor/misc/assemname_cs_ro.csproj deleted file mode 100644 index 844560f626ce..000000000000 --- a/src/tests/JIT/Methodical/cctor/misc/assemname_cs_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - None - True - - - - - - diff --git a/src/tests/JIT/Methodical/cctor/misc/testlib_misc.csproj b/src/tests/JIT/Methodical/cctor/misc/testlib_misc.csproj index 5460dac9d1e0..739dc08364bf 100644 --- a/src/tests/JIT/Methodical/cctor/misc/testlib_misc.csproj +++ b/src/tests/JIT/Methodical/cctor/misc/testlib_misc.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/Methodical/cctor/misc/threads1.cs b/src/tests/JIT/Methodical/cctor/misc/threads1.cs index 0a3aed1dc767..7074c4f9f11e 100644 --- a/src/tests/JIT/Methodical/cctor/misc/threads1.cs +++ b/src/tests/JIT/Methodical/cctor/misc/threads1.cs @@ -16,6 +16,7 @@ public static void f() test.b = 0xF; } [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/cctor/misc/threads1_cs_d.csproj b/src/tests/JIT/Methodical/cctor/misc/threads1_cs_d.csproj index 309891b38bc3..2a3a85a16dd5 100644 --- a/src/tests/JIT/Methodical/cctor/misc/threads1_cs_d.csproj +++ b/src/tests/JIT/Methodical/cctor/misc/threads1_cs_d.csproj @@ -4,7 +4,6 @@ true - Full diff --git a/src/tests/JIT/Methodical/cctor/misc/threads1_cs_do.csproj b/src/tests/JIT/Methodical/cctor/misc/threads1_cs_do.csproj index f75a5dda540e..2339bb495888 100644 --- a/src/tests/JIT/Methodical/cctor/misc/threads1_cs_do.csproj +++ b/src/tests/JIT/Methodical/cctor/misc/threads1_cs_do.csproj @@ -3,7 +3,6 @@ true - Full True diff --git a/src/tests/JIT/Methodical/cctor/misc/threads1_cs_r.csproj b/src/tests/JIT/Methodical/cctor/misc/threads1_cs_r.csproj index 11ebaf8c9435..d6e780b69a87 100644 --- a/src/tests/JIT/Methodical/cctor/misc/threads1_cs_r.csproj +++ b/src/tests/JIT/Methodical/cctor/misc/threads1_cs_r.csproj @@ -4,7 +4,6 @@ true - None diff --git a/src/tests/JIT/Methodical/cctor/misc/threads1_cs_ro.csproj b/src/tests/JIT/Methodical/cctor/misc/threads1_cs_ro.csproj index 1f8bf1bcdf6f..f3c453b974a4 100644 --- a/src/tests/JIT/Methodical/cctor/misc/threads1_cs_ro.csproj +++ b/src/tests/JIT/Methodical/cctor/misc/threads1_cs_ro.csproj @@ -4,7 +4,6 @@ true - None True diff --git a/src/tests/JIT/Methodical/cctor/misc/threads2.cs b/src/tests/JIT/Methodical/cctor/misc/threads2.cs index ccd4f38fdb3d..bfc072849f8d 100644 --- a/src/tests/JIT/Methodical/cctor/misc/threads2.cs +++ b/src/tests/JIT/Methodical/cctor/misc/threads2.cs @@ -17,6 +17,7 @@ public static void f() RuntimeHelpers.RunClassConstructor(typeof(test).TypeHandle); } [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/cctor/misc/threads2_cs_d.csproj b/src/tests/JIT/Methodical/cctor/misc/threads2_cs_d.csproj index 9d915a5d8086..acf66f2eefba 100644 --- a/src/tests/JIT/Methodical/cctor/misc/threads2_cs_d.csproj +++ b/src/tests/JIT/Methodical/cctor/misc/threads2_cs_d.csproj @@ -4,7 +4,6 @@ true - Full diff --git a/src/tests/JIT/Methodical/cctor/misc/threads2_cs_do.csproj b/src/tests/JIT/Methodical/cctor/misc/threads2_cs_do.csproj index c7f4c2f5f35a..84a6a235f5fc 100644 --- a/src/tests/JIT/Methodical/cctor/misc/threads2_cs_do.csproj +++ b/src/tests/JIT/Methodical/cctor/misc/threads2_cs_do.csproj @@ -5,7 +5,6 @@ true - Full True diff --git a/src/tests/JIT/Methodical/cctor/misc/threads2_cs_r.csproj b/src/tests/JIT/Methodical/cctor/misc/threads2_cs_r.csproj index fc3b9fe80417..469732170db5 100644 --- a/src/tests/JIT/Methodical/cctor/misc/threads2_cs_r.csproj +++ b/src/tests/JIT/Methodical/cctor/misc/threads2_cs_r.csproj @@ -4,7 +4,6 @@ true - None diff --git a/src/tests/JIT/Methodical/cctor/misc/threads2_cs_ro.csproj b/src/tests/JIT/Methodical/cctor/misc/threads2_cs_ro.csproj index 49a2e2243a19..82eb8ee9cd72 100644 --- a/src/tests/JIT/Methodical/cctor/misc/threads2_cs_ro.csproj +++ b/src/tests/JIT/Methodical/cctor/misc/threads2_cs_ro.csproj @@ -4,7 +4,6 @@ true - None True diff --git a/src/tests/JIT/Methodical/cctor/misc/throw_misc_cs_d.csproj b/src/tests/JIT/Methodical/cctor/misc/throw_misc_cs_d.csproj deleted file mode 100644 index 6e8e315a8b3e..000000000000 --- a/src/tests/JIT/Methodical/cctor/misc/throw_misc_cs_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - full - False - True - True - - - - - diff --git a/src/tests/JIT/Methodical/cctor/misc/throw_misc_cs_do.csproj b/src/tests/JIT/Methodical/cctor/misc/throw_misc_cs_do.csproj deleted file mode 100644 index ea7d25ec30a1..000000000000 --- a/src/tests/JIT/Methodical/cctor/misc/throw_misc_cs_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - full - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/cctor/misc/throw_misc_cs_r.csproj b/src/tests/JIT/Methodical/cctor/misc/throw_misc_cs_r.csproj deleted file mode 100644 index be27205ee9fe..000000000000 --- a/src/tests/JIT/Methodical/cctor/misc/throw_misc_cs_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - True - True - - - - - diff --git a/src/tests/JIT/Methodical/cctor/misc/throw_misc_cs_ro.csproj b/src/tests/JIT/Methodical/cctor/misc/throw_misc_cs_ro.csproj deleted file mode 100644 index 6b4e4fe404f4..000000000000 --- a/src/tests/JIT/Methodical/cctor/misc/throw_misc_cs_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise1.cs b/src/tests/JIT/Methodical/cctor/simple/precise1.cs index 38cd689fd3c4..621e02e51a43 100644 --- a/src/tests/JIT/Methodical/cctor/simple/precise1.cs +++ b/src/tests/JIT/Methodical/cctor/simple/precise1.cs @@ -41,6 +41,7 @@ static test() public class Driver { [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/cctor/simple/precise1_cs_d.csproj b/src/tests/JIT/Methodical/cctor/simple/precise1_cs_d.csproj deleted file mode 100644 index ef9efba18c1c..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise1_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise1_cs_do.csproj b/src/tests/JIT/Methodical/cctor/simple/precise1_cs_do.csproj deleted file mode 100644 index 397ad702903d..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise1_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise1_cs_r.csproj b/src/tests/JIT/Methodical/cctor/simple/precise1_cs_r.csproj deleted file mode 100644 index fd523ae3c2a4..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise1_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise1_cs_ro.csproj b/src/tests/JIT/Methodical/cctor/simple/precise1_cs_ro.csproj deleted file mode 100644 index 9dc8577cde73..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise1_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise1b.cs b/src/tests/JIT/Methodical/cctor/simple/precise1b.cs index 17c044332774..498fea11f7f0 100644 --- a/src/tests/JIT/Methodical/cctor/simple/precise1b.cs +++ b/src/tests/JIT/Methodical/cctor/simple/precise1b.cs @@ -40,6 +40,7 @@ static test() public class Driver { [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/cctor/simple/precise1b_cs_d.csproj b/src/tests/JIT/Methodical/cctor/simple/precise1b_cs_d.csproj deleted file mode 100644 index 6487e1857aa4..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise1b_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise1b_cs_do.csproj b/src/tests/JIT/Methodical/cctor/simple/precise1b_cs_do.csproj deleted file mode 100644 index 43a35f7724b1..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise1b_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise1b_cs_r.csproj b/src/tests/JIT/Methodical/cctor/simple/precise1b_cs_r.csproj deleted file mode 100644 index b70e4d4fcda3..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise1b_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise1b_cs_ro.csproj b/src/tests/JIT/Methodical/cctor/simple/precise1b_cs_ro.csproj deleted file mode 100644 index 0c2eee841340..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise1b_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise2.cs b/src/tests/JIT/Methodical/cctor/simple/precise2.cs index b5610243558d..592bc495d5ea 100644 --- a/src/tests/JIT/Methodical/cctor/simple/precise2.cs +++ b/src/tests/JIT/Methodical/cctor/simple/precise2.cs @@ -36,6 +36,7 @@ static test() public class Driver { [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/cctor/simple/precise2_cs_d.csproj b/src/tests/JIT/Methodical/cctor/simple/precise2_cs_d.csproj deleted file mode 100644 index dc646f78b466..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise2_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise2_cs_do.csproj b/src/tests/JIT/Methodical/cctor/simple/precise2_cs_do.csproj deleted file mode 100644 index 28eed0ae562b..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise2_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise2_cs_r.csproj b/src/tests/JIT/Methodical/cctor/simple/precise2_cs_r.csproj deleted file mode 100644 index 9d971c962ee2..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise2_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise2_cs_ro.csproj b/src/tests/JIT/Methodical/cctor/simple/precise2_cs_ro.csproj deleted file mode 100644 index 84c053e19002..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise2_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise4.cs b/src/tests/JIT/Methodical/cctor/simple/precise4.cs index 5130c2531ecb..2c4774f80816 100644 --- a/src/tests/JIT/Methodical/cctor/simple/precise4.cs +++ b/src/tests/JIT/Methodical/cctor/simple/precise4.cs @@ -38,6 +38,7 @@ static test() public class Driver { [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/cctor/simple/precise4_cs_d.csproj b/src/tests/JIT/Methodical/cctor/simple/precise4_cs_d.csproj deleted file mode 100644 index df75c52d0187..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise4_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise4_cs_do.csproj b/src/tests/JIT/Methodical/cctor/simple/precise4_cs_do.csproj deleted file mode 100644 index 906752375945..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise4_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise4_cs_r.csproj b/src/tests/JIT/Methodical/cctor/simple/precise4_cs_r.csproj deleted file mode 100644 index fa645090c76e..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise4_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/cctor/simple/precise4_cs_ro.csproj b/src/tests/JIT/Methodical/cctor/simple/precise4_cs_ro.csproj deleted file mode 100644 index 2ea50434c051..000000000000 --- a/src/tests/JIT/Methodical/cctor/simple/precise4_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/cctor/xassem/xprecise1.cs b/src/tests/JIT/Methodical/cctor/xassem/xprecise1.cs index 9268f6194513..374faeda362c 100644 --- a/src/tests/JIT/Methodical/cctor/xassem/xprecise1.cs +++ b/src/tests/JIT/Methodical/cctor/xassem/xprecise1.cs @@ -3,40 +3,45 @@ // static method using System; using Xunit; -namespace Precise { +namespace Precise +{ public class Driver_xprecise1 { - [Fact] - public static int TestEntryPoint() - { - try { - byte b = 0xF; - Console.WriteLine("Testing .cctor() invocation by calling static method across assembly"); - Console.WriteLine(); - Console.WriteLine("Before calling static method"); - // .cctor should not run yet - if (measure.a!=0xCC) { - Console.WriteLine("in Main(), measure.a is {0}", measure.a); - Console.WriteLine("FAILED"); - return 1; - } - // the next line should trigger .cctor - test.f(ref b); - Console.WriteLine("After calling static method"); - if (measure.a!=8) { - Console.WriteLine("in Main() after f(ref b), measure.a is {0}", measure.a); - Console.WriteLine("FAILED"); - return -1; - } - } - catch (Exception e) - { - Console.WriteLine(e.StackTrace); - return -1; - } - Console.WriteLine(); - Console.WriteLine("PASSED"); - return 100; - } + [Fact] + [OuterLoop] + public static int TestEntryPoint() + { + try + { + byte b = 0xF; + Console.WriteLine("Testing .cctor() invocation by calling static method across assembly"); + Console.WriteLine(); + Console.WriteLine("Before calling static method"); + // .cctor should not run yet + if (measure.a != 0xCC) + { + Console.WriteLine("in Main(), measure.a is {0}", measure.a); + Console.WriteLine("FAILED"); + return 1; + } + // the next line should trigger .cctor + test.f(ref b); + Console.WriteLine("After calling static method"); + if (measure.a != 8) + { + Console.WriteLine("in Main() after f(ref b), measure.a is {0}", measure.a); + Console.WriteLine("FAILED"); + return -1; + } + } + catch (Exception e) + { + Console.WriteLine(e.StackTrace); + return -1; + } + Console.WriteLine(); + Console.WriteLine("PASSED"); + return 100; + } } } diff --git a/src/tests/JIT/Methodical/cctor/xassem/xprecise1_cs_do.csproj b/src/tests/JIT/Methodical/cctor/xassem/xprecise1_cs_do.csproj index 1d488e70ca1c..880fd8e8eb33 100644 --- a/src/tests/JIT/Methodical/cctor/xassem/xprecise1_cs_do.csproj +++ b/src/tests/JIT/Methodical/cctor/xassem/xprecise1_cs_do.csproj @@ -1,6 +1,5 @@ - 1 true diff --git a/src/tests/JIT/Methodical/cctor/xassem/xprecise1b.cs b/src/tests/JIT/Methodical/cctor/xassem/xprecise1b.cs index 7ed312ae6803..870d27f612bb 100644 --- a/src/tests/JIT/Methodical/cctor/xassem/xprecise1b.cs +++ b/src/tests/JIT/Methodical/cctor/xassem/xprecise1b.cs @@ -9,6 +9,7 @@ namespace Precise public class Driver_xprecise1b { [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/cctor/xassem/xprecise2.cs b/src/tests/JIT/Methodical/cctor/xassem/xprecise2.cs index 4b8f1623321a..4ddd28f17055 100644 --- a/src/tests/JIT/Methodical/cctor/xassem/xprecise2.cs +++ b/src/tests/JIT/Methodical/cctor/xassem/xprecise2.cs @@ -9,6 +9,7 @@ namespace Precise public class Driver_xprecise2 { [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/cctor/xassem/xprecise4.cs b/src/tests/JIT/Methodical/cctor/xassem/xprecise4.cs index b732a4266e83..e574583c13d1 100644 --- a/src/tests/JIT/Methodical/cctor/xassem/xprecise4.cs +++ b/src/tests/JIT/Methodical/cctor/xassem/xprecise4.cs @@ -9,6 +9,7 @@ namespace Precise public class Driver_xprecise4 { [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/delegate/GSDelegate.cs b/src/tests/JIT/Methodical/delegate/GSDelegate.cs index ee68adb0fec0..00732f168691 100644 --- a/src/tests/JIT/Methodical/delegate/GSDelegate.cs +++ b/src/tests/JIT/Methodical/delegate/GSDelegate.cs @@ -19,7 +19,7 @@ public struct MyStruct : IGetContents { } } -public class Program { +public partial class Program { public delegate (string, int, T) MyDelegate(IGetContents arg); diff --git a/src/tests/JIT/Methodical/delegate/GSDelegate.csproj b/src/tests/JIT/Methodical/delegate/GSDelegate.csproj deleted file mode 100644 index b47c3e8e8d9f..000000000000 --- a/src/tests/JIT/Methodical/delegate/GSDelegate.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/delegate/VirtualDelegate.csproj b/src/tests/JIT/Methodical/delegate/VirtualDelegate.csproj deleted file mode 100644 index cddd1e53bad8..000000000000 --- a/src/tests/JIT/Methodical/delegate/VirtualDelegate.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/decimaldiv.cs b/src/tests/JIT/Methodical/divrem/div/decimaldiv.cs index a566d6706204..2f10703c4261 100644 --- a/src/tests/JIT/Methodical/divrem/div/decimaldiv.cs +++ b/src/tests/JIT/Methodical/divrem/div/decimaldiv.cs @@ -93,6 +93,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/div/decimaldiv_cs_d.csproj b/src/tests/JIT/Methodical/divrem/div/decimaldiv_cs_d.csproj deleted file mode 100644 index e7d5f6780496..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/decimaldiv_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/decimaldiv_cs_do.csproj b/src/tests/JIT/Methodical/divrem/div/decimaldiv_cs_do.csproj deleted file mode 100644 index 16c066a490fd..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/decimaldiv_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/decimaldiv_cs_r.csproj b/src/tests/JIT/Methodical/divrem/div/decimaldiv_cs_r.csproj deleted file mode 100644 index dc0104be1b1b..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/decimaldiv_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/decimaldiv_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/div/decimaldiv_cs_ro.csproj deleted file mode 100644 index 188f9cd383f9..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/decimaldiv_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/i4div.cs b/src/tests/JIT/Methodical/divrem/div/i4div.cs index 171f049e125a..36d77950b43e 100644 --- a/src/tests/JIT/Methodical/divrem/div/i4div.cs +++ b/src/tests/JIT/Methodical/divrem/div/i4div.cs @@ -93,6 +93,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/div/i4div_cs_d.csproj b/src/tests/JIT/Methodical/divrem/div/i4div_cs_d.csproj deleted file mode 100644 index 80b4210be927..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/i4div_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/i4div_cs_do.csproj b/src/tests/JIT/Methodical/divrem/div/i4div_cs_do.csproj deleted file mode 100644 index 5d84a6d5a680..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/i4div_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/i4div_cs_r.csproj b/src/tests/JIT/Methodical/divrem/div/i4div_cs_r.csproj deleted file mode 100644 index a1a5b6948f7c..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/i4div_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/i4div_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/div/i4div_cs_ro.csproj deleted file mode 100644 index 905ac005c73f..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/i4div_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/i8div.cs b/src/tests/JIT/Methodical/divrem/div/i8div.cs index 0e1d39889f63..a45b1f7f7db7 100644 --- a/src/tests/JIT/Methodical/divrem/div/i8div.cs +++ b/src/tests/JIT/Methodical/divrem/div/i8div.cs @@ -93,6 +93,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/div/i8div_cs_d.csproj b/src/tests/JIT/Methodical/divrem/div/i8div_cs_d.csproj deleted file mode 100644 index a2b4e17b2a4e..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/i8div_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/i8div_cs_do.csproj b/src/tests/JIT/Methodical/divrem/div/i8div_cs_do.csproj deleted file mode 100644 index 3c3dbb5ff31b..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/i8div_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/i8div_cs_r.csproj b/src/tests/JIT/Methodical/divrem/div/i8div_cs_r.csproj deleted file mode 100644 index d6132bdf4078..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/i8div_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/i8div_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/div/i8div_cs_ro.csproj deleted file mode 100644 index 80050f658c0f..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/i8div_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/negSignedMod.cs b/src/tests/JIT/Methodical/divrem/div/negSignedMod.cs index 22774c27a8a0..bb52b395d5f8 100644 --- a/src/tests/JIT/Methodical/divrem/div/negSignedMod.cs +++ b/src/tests/JIT/Methodical/divrem/div/negSignedMod.cs @@ -8,6 +8,7 @@ public class Test_negSignedMod { [Fact] + [OuterLoop] public static int TestEntryPoint() { Console.WriteLine(TimeSpan.FromTicks(-2567240321185713219).Seconds); diff --git a/src/tests/JIT/Methodical/divrem/div/negSignedMod.csproj b/src/tests/JIT/Methodical/divrem/div/negSignedMod.csproj deleted file mode 100644 index b932a3821ec7..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/negSignedMod.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/overlddiv.cs b/src/tests/JIT/Methodical/divrem/div/overlddiv.cs index 7849b57745bf..f8508e4c221b 100644 --- a/src/tests/JIT/Methodical/divrem/div/overlddiv.cs +++ b/src/tests/JIT/Methodical/divrem/div/overlddiv.cs @@ -236,6 +236,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/div/overlddiv_cs_d.csproj b/src/tests/JIT/Methodical/divrem/div/overlddiv_cs_d.csproj deleted file mode 100644 index c581a2f764b5..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/overlddiv_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/overlddiv_cs_do.csproj b/src/tests/JIT/Methodical/divrem/div/overlddiv_cs_do.csproj deleted file mode 100644 index 366fe5e892eb..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/overlddiv_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/overlddiv_cs_r.csproj b/src/tests/JIT/Methodical/divrem/div/overlddiv_cs_r.csproj deleted file mode 100644 index 934923af98ce..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/overlddiv_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/overlddiv_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/div/overlddiv_cs_ro.csproj deleted file mode 100644 index cbe4a38f4311..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/overlddiv_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/r4div.cs b/src/tests/JIT/Methodical/divrem/div/r4div.cs index 17e30020619d..eadcfe02dc51 100644 --- a/src/tests/JIT/Methodical/divrem/div/r4div.cs +++ b/src/tests/JIT/Methodical/divrem/div/r4div.cs @@ -93,6 +93,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/div/r4div_cs_d.csproj b/src/tests/JIT/Methodical/divrem/div/r4div_cs_d.csproj deleted file mode 100644 index 2150688a88fd..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/r4div_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/r4div_cs_do.csproj b/src/tests/JIT/Methodical/divrem/div/r4div_cs_do.csproj deleted file mode 100644 index cd402c7d8629..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/r4div_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/r4div_cs_r.csproj b/src/tests/JIT/Methodical/divrem/div/r4div_cs_r.csproj deleted file mode 100644 index 4d3fc5155081..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/r4div_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/r4div_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/div/r4div_cs_ro.csproj deleted file mode 100644 index c9e791105978..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/r4div_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/r8div.cs b/src/tests/JIT/Methodical/divrem/div/r8div.cs index ca7da8e8e3eb..9b356103c1d6 100644 --- a/src/tests/JIT/Methodical/divrem/div/r8div.cs +++ b/src/tests/JIT/Methodical/divrem/div/r8div.cs @@ -93,6 +93,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/div/r8div_cs_d.csproj b/src/tests/JIT/Methodical/divrem/div/r8div_cs_d.csproj deleted file mode 100644 index 2ff71c44910a..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/r8div_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/r8div_cs_do.csproj b/src/tests/JIT/Methodical/divrem/div/r8div_cs_do.csproj deleted file mode 100644 index 36e49877d444..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/r8div_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/r8div_cs_r.csproj b/src/tests/JIT/Methodical/divrem/div/r8div_cs_r.csproj deleted file mode 100644 index a664334bb9f0..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/r8div_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/r8div_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/div/r8div_cs_ro.csproj deleted file mode 100644 index 9af0e23785cd..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/r8div_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/u4div.cs b/src/tests/JIT/Methodical/divrem/div/u4div.cs index d24bd93b091c..61f50b9e46e9 100644 --- a/src/tests/JIT/Methodical/divrem/div/u4div.cs +++ b/src/tests/JIT/Methodical/divrem/div/u4div.cs @@ -93,6 +93,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/div/u4div_cs_d.csproj b/src/tests/JIT/Methodical/divrem/div/u4div_cs_d.csproj deleted file mode 100644 index d31531241895..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/u4div_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/u4div_cs_do.csproj b/src/tests/JIT/Methodical/divrem/div/u4div_cs_do.csproj deleted file mode 100644 index 6a7c486f0e29..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/u4div_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/u4div_cs_r.csproj b/src/tests/JIT/Methodical/divrem/div/u4div_cs_r.csproj deleted file mode 100644 index 6f779b02e516..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/u4div_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/u4div_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/div/u4div_cs_ro.csproj deleted file mode 100644 index 73e0ea525fd1..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/u4div_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/u8div.cs b/src/tests/JIT/Methodical/divrem/div/u8div.cs index 37850335f319..c6541b4e0667 100644 --- a/src/tests/JIT/Methodical/divrem/div/u8div.cs +++ b/src/tests/JIT/Methodical/divrem/div/u8div.cs @@ -93,6 +93,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/div/u8div_cs_d.csproj b/src/tests/JIT/Methodical/divrem/div/u8div_cs_d.csproj deleted file mode 100644 index 5f3ee52820ac..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/u8div_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/u8div_cs_do.csproj b/src/tests/JIT/Methodical/divrem/div/u8div_cs_do.csproj deleted file mode 100644 index bc322682e355..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/u8div_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/u8div_cs_r.csproj b/src/tests/JIT/Methodical/divrem/div/u8div_cs_r.csproj deleted file mode 100644 index 98e0795884c0..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/u8div_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/div/u8div_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/div/u8div_cs_ro.csproj deleted file mode 100644 index 1563b7ddd161..000000000000 --- a/src/tests/JIT/Methodical/divrem/div/u8div_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/decimalrem.cs b/src/tests/JIT/Methodical/divrem/rem/decimalrem.cs index babb86b05cfc..82053b16a551 100644 --- a/src/tests/JIT/Methodical/divrem/rem/decimalrem.cs +++ b/src/tests/JIT/Methodical/divrem/rem/decimalrem.cs @@ -93,6 +93,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/rem/decimalrem_cs_d.csproj b/src/tests/JIT/Methodical/divrem/rem/decimalrem_cs_d.csproj deleted file mode 100644 index f71247342b21..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/decimalrem_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/decimalrem_cs_do.csproj b/src/tests/JIT/Methodical/divrem/rem/decimalrem_cs_do.csproj deleted file mode 100644 index bb16299f963e..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/decimalrem_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/decimalrem_cs_r.csproj b/src/tests/JIT/Methodical/divrem/rem/decimalrem_cs_r.csproj deleted file mode 100644 index db2b3d086c23..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/decimalrem_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/decimalrem_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/rem/decimalrem_cs_ro.csproj deleted file mode 100644 index 663b28851a6b..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/decimalrem_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/i4rem.cs b/src/tests/JIT/Methodical/divrem/rem/i4rem.cs index 94fd4c0312e7..9808183657ab 100644 --- a/src/tests/JIT/Methodical/divrem/rem/i4rem.cs +++ b/src/tests/JIT/Methodical/divrem/rem/i4rem.cs @@ -93,6 +93,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/rem/i4rem_cs_d.csproj b/src/tests/JIT/Methodical/divrem/rem/i4rem_cs_d.csproj deleted file mode 100644 index b09639d67e8d..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/i4rem_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/i4rem_cs_do.csproj b/src/tests/JIT/Methodical/divrem/rem/i4rem_cs_do.csproj deleted file mode 100644 index a9df57e9e11e..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/i4rem_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/i4rem_cs_r.csproj b/src/tests/JIT/Methodical/divrem/rem/i4rem_cs_r.csproj deleted file mode 100644 index 20bd5f165a61..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/i4rem_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/i4rem_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/rem/i4rem_cs_ro.csproj deleted file mode 100644 index 19f0dbf3c5ef..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/i4rem_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/i8rem.cs b/src/tests/JIT/Methodical/divrem/rem/i8rem.cs index b1b12ec1ffcb..9569a762991e 100644 --- a/src/tests/JIT/Methodical/divrem/rem/i8rem.cs +++ b/src/tests/JIT/Methodical/divrem/rem/i8rem.cs @@ -93,6 +93,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/rem/i8rem_cs_d.csproj b/src/tests/JIT/Methodical/divrem/rem/i8rem_cs_d.csproj deleted file mode 100644 index 317fa3f7ba0b..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/i8rem_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/i8rem_cs_do.csproj b/src/tests/JIT/Methodical/divrem/rem/i8rem_cs_do.csproj deleted file mode 100644 index 6dae82c2c077..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/i8rem_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/i8rem_cs_r.csproj b/src/tests/JIT/Methodical/divrem/rem/i8rem_cs_r.csproj deleted file mode 100644 index 4e8ad282f2d1..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/i8rem_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/i8rem_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/rem/i8rem_cs_ro.csproj deleted file mode 100644 index 4090f7183a91..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/i8rem_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/overldrem.cs b/src/tests/JIT/Methodical/divrem/rem/overldrem.cs index 9418ca4ed2f7..735e212685f1 100644 --- a/src/tests/JIT/Methodical/divrem/rem/overldrem.cs +++ b/src/tests/JIT/Methodical/divrem/rem/overldrem.cs @@ -236,6 +236,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/rem/overldrem_cs_d.csproj b/src/tests/JIT/Methodical/divrem/rem/overldrem_cs_d.csproj deleted file mode 100644 index 11922d537b75..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/overldrem_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/overldrem_cs_do.csproj b/src/tests/JIT/Methodical/divrem/rem/overldrem_cs_do.csproj deleted file mode 100644 index c93685cddbc8..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/overldrem_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/overldrem_cs_r.csproj b/src/tests/JIT/Methodical/divrem/rem/overldrem_cs_r.csproj deleted file mode 100644 index 0d22f1c45688..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/overldrem_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/overldrem_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/rem/overldrem_cs_ro.csproj deleted file mode 100644 index 8f958a24a291..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/overldrem_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/r4rem.cs b/src/tests/JIT/Methodical/divrem/rem/r4rem.cs index 00d17a23a443..96ac8a390d98 100644 --- a/src/tests/JIT/Methodical/divrem/rem/r4rem.cs +++ b/src/tests/JIT/Methodical/divrem/rem/r4rem.cs @@ -93,6 +93,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/rem/r4rem_cs_d.csproj b/src/tests/JIT/Methodical/divrem/rem/r4rem_cs_d.csproj deleted file mode 100644 index 336fda92e732..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/r4rem_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/r4rem_cs_do.csproj b/src/tests/JIT/Methodical/divrem/rem/r4rem_cs_do.csproj deleted file mode 100644 index a4bfb2af83ff..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/r4rem_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/r4rem_cs_r.csproj b/src/tests/JIT/Methodical/divrem/rem/r4rem_cs_r.csproj deleted file mode 100644 index f65dc9ecb8f6..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/r4rem_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/r4rem_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/rem/r4rem_cs_ro.csproj deleted file mode 100644 index c62d2739d445..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/r4rem_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/r8rem.cs b/src/tests/JIT/Methodical/divrem/rem/r8rem.cs index f7d6e215507a..c10ce9f09dc6 100644 --- a/src/tests/JIT/Methodical/divrem/rem/r8rem.cs +++ b/src/tests/JIT/Methodical/divrem/rem/r8rem.cs @@ -93,6 +93,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/rem/r8rem_cs_d.csproj b/src/tests/JIT/Methodical/divrem/rem/r8rem_cs_d.csproj deleted file mode 100644 index d28cdb3fd7fa..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/r8rem_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/r8rem_cs_do.csproj b/src/tests/JIT/Methodical/divrem/rem/r8rem_cs_do.csproj deleted file mode 100644 index 5dbaf83c672d..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/r8rem_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/r8rem_cs_r.csproj b/src/tests/JIT/Methodical/divrem/rem/r8rem_cs_r.csproj deleted file mode 100644 index 93c05a2b0b8a..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/r8rem_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/r8rem_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/rem/r8rem_cs_ro.csproj deleted file mode 100644 index aecfdee3f208..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/r8rem_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/u4rem.cs b/src/tests/JIT/Methodical/divrem/rem/u4rem.cs index 4afb4bda0fd3..d09b0f5956eb 100644 --- a/src/tests/JIT/Methodical/divrem/rem/u4rem.cs +++ b/src/tests/JIT/Methodical/divrem/rem/u4rem.cs @@ -93,6 +93,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/rem/u4rem_cs_d.csproj b/src/tests/JIT/Methodical/divrem/rem/u4rem_cs_d.csproj deleted file mode 100644 index 1bf1f301c2b2..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/u4rem_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/u4rem_cs_do.csproj b/src/tests/JIT/Methodical/divrem/rem/u4rem_cs_do.csproj deleted file mode 100644 index c296887073b0..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/u4rem_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/u4rem_cs_r.csproj b/src/tests/JIT/Methodical/divrem/rem/u4rem_cs_r.csproj deleted file mode 100644 index 49e883122494..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/u4rem_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/u4rem_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/rem/u4rem_cs_ro.csproj deleted file mode 100644 index edc2cf299c67..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/u4rem_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/u8rem.cs b/src/tests/JIT/Methodical/divrem/rem/u8rem.cs index e24afd0b7f36..8bf0ff6b9a37 100644 --- a/src/tests/JIT/Methodical/divrem/rem/u8rem.cs +++ b/src/tests/JIT/Methodical/divrem/rem/u8rem.cs @@ -93,6 +93,7 @@ private struct VT } [Fact] + [OuterLoop] public static int TestEntryPoint() { bool passed = true; diff --git a/src/tests/JIT/Methodical/divrem/rem/u8rem_cs_d.csproj b/src/tests/JIT/Methodical/divrem/rem/u8rem_cs_d.csproj deleted file mode 100644 index a894e6a12a7e..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/u8rem_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/u8rem_cs_do.csproj b/src/tests/JIT/Methodical/divrem/rem/u8rem_cs_do.csproj deleted file mode 100644 index 66563f60ed3c..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/u8rem_cs_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/u8rem_cs_r.csproj b/src/tests/JIT/Methodical/divrem/rem/u8rem_cs_r.csproj deleted file mode 100644 index 4e7efb9a9eed..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/u8rem_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/divrem/rem/u8rem_cs_ro.csproj b/src/tests/JIT/Methodical/divrem/rem/u8rem_cs_ro.csproj deleted file mode 100644 index 0be3d9c7aebe..000000000000 --- a/src/tests/JIT/Methodical/divrem/rem/u8rem_cs_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/doublearray/dblarray1.cs b/src/tests/JIT/Methodical/doublearray/dblarray1.cs index 726e5d2a55dc..7c377fc85792 100644 --- a/src/tests/JIT/Methodical/doublearray/dblarray1.cs +++ b/src/tests/JIT/Methodical/doublearray/dblarray1.cs @@ -92,6 +92,9 @@ public static void Run(Action f) } [Fact] + [SkipOnCoreClr("This test is not compatible with GCStress.", RuntimeTestModes.AnyGCStress)] + [OuterLoop] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101284", typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNativeAot))] public static int TestEntryPoint() { if (RuntimeInformation.ProcessArchitecture == Architecture.X86) diff --git a/src/tests/JIT/Methodical/doublearray/dblarray1_cs_d.csproj b/src/tests/JIT/Methodical/doublearray/dblarray1_cs_d.csproj deleted file mode 100644 index 9ebb330e3d94..000000000000 --- a/src/tests/JIT/Methodical/doublearray/dblarray1_cs_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - False - true - true - - - - - diff --git a/src/tests/JIT/Methodical/doublearray/dblarray1_cs_do.csproj b/src/tests/JIT/Methodical/doublearray/dblarray1_cs_do.csproj deleted file mode 100644 index e63112c952b0..000000000000 --- a/src/tests/JIT/Methodical/doublearray/dblarray1_cs_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - True - true - true - - - - - diff --git a/src/tests/JIT/Methodical/doublearray/dblarray1_cs_r.csproj b/src/tests/JIT/Methodical/doublearray/dblarray1_cs_r.csproj deleted file mode 100644 index 1053af22bc9d..000000000000 --- a/src/tests/JIT/Methodical/doublearray/dblarray1_cs_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - False - true - true - - - - - diff --git a/src/tests/JIT/Methodical/doublearray/dblarray1_cs_ro.csproj b/src/tests/JIT/Methodical/doublearray/dblarray1_cs_ro.csproj deleted file mode 100644 index 849e86388d30..000000000000 --- a/src/tests/JIT/Methodical/doublearray/dblarray1_cs_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - True - true - true - - - - - diff --git a/src/tests/JIT/Methodical/doublearray/dblarray2.cs b/src/tests/JIT/Methodical/doublearray/dblarray2.cs index 64e2e8d00ee3..427b72d15b47 100644 --- a/src/tests/JIT/Methodical/doublearray/dblarray2.cs +++ b/src/tests/JIT/Methodical/doublearray/dblarray2.cs @@ -281,6 +281,9 @@ public static void Run(Action f) } [Fact] + [SkipOnCoreClr("This test is not compatible with GCStress.", RuntimeTestModes.AnyGCStress)] + [SkipOnMono("Needs triage")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101284", typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNativeAot))] public static int TestEntryPoint() { if (RuntimeInformation.ProcessArchitecture == Architecture.X86) diff --git a/src/tests/JIT/Methodical/doublearray/dblarray2_cs_d.csproj b/src/tests/JIT/Methodical/doublearray/dblarray2_cs_d.csproj deleted file mode 100644 index 786b61921aed..000000000000 --- a/src/tests/JIT/Methodical/doublearray/dblarray2_cs_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Full - False - true - true - - - - - diff --git a/src/tests/JIT/Methodical/doublearray/dblarray2_cs_do.csproj b/src/tests/JIT/Methodical/doublearray/dblarray2_cs_do.csproj deleted file mode 100644 index ac6d56e84364..000000000000 --- a/src/tests/JIT/Methodical/doublearray/dblarray2_cs_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Full - True - true - true - - - - - diff --git a/src/tests/JIT/Methodical/doublearray/dblarray2_cs_r.csproj b/src/tests/JIT/Methodical/doublearray/dblarray2_cs_r.csproj deleted file mode 100644 index 6e5871b90f25..000000000000 --- a/src/tests/JIT/Methodical/doublearray/dblarray2_cs_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - None - False - true - true - - - - - diff --git a/src/tests/JIT/Methodical/doublearray/dblarray2_cs_ro.csproj b/src/tests/JIT/Methodical/doublearray/dblarray2_cs_ro.csproj deleted file mode 100644 index 3754733b5bb3..000000000000 --- a/src/tests/JIT/Methodical/doublearray/dblarray2_cs_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - None - True - true - true - - - - - diff --git a/src/tests/JIT/Methodical/doublearray/dblarray3.cs b/src/tests/JIT/Methodical/doublearray/dblarray3.cs index 03f521d6baf0..053e1c14700e 100644 --- a/src/tests/JIT/Methodical/doublearray/dblarray3.cs +++ b/src/tests/JIT/Methodical/doublearray/dblarray3.cs @@ -141,6 +141,10 @@ public static void Run(Action f) } [Fact] + [SkipOnCoreClr("This test is not compatible with GCStress.", RuntimeTestModes.AnyGCStress)] + [SkipOnMono("Needs triage")] + [OuterLoop] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101284", typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNativeAot))] public static int TestEntryPoint() { Console.WriteLine(RuntimeInformation.ProcessArchitecture); diff --git a/src/tests/JIT/Methodical/doublearray/dblarray3_cs_d.csproj b/src/tests/JIT/Methodical/doublearray/dblarray3_cs_d.csproj deleted file mode 100644 index 3b629bc3ce92..000000000000 --- a/src/tests/JIT/Methodical/doublearray/dblarray3_cs_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - False - true - true - - - - - diff --git a/src/tests/JIT/Methodical/doublearray/dblarray3_cs_do.csproj b/src/tests/JIT/Methodical/doublearray/dblarray3_cs_do.csproj deleted file mode 100644 index 945823645f28..000000000000 --- a/src/tests/JIT/Methodical/doublearray/dblarray3_cs_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Full - True - true - true - - - - - diff --git a/src/tests/JIT/Methodical/doublearray/dblarray3_cs_r.csproj b/src/tests/JIT/Methodical/doublearray/dblarray3_cs_r.csproj deleted file mode 100644 index 44a6fe9268fe..000000000000 --- a/src/tests/JIT/Methodical/doublearray/dblarray3_cs_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - False - true - true - - - - - diff --git a/src/tests/JIT/Methodical/doublearray/dblarray3_cs_ro.csproj b/src/tests/JIT/Methodical/doublearray/dblarray3_cs_ro.csproj deleted file mode 100644 index f9a67d05880b..000000000000 --- a/src/tests/JIT/Methodical/doublearray/dblarray3_cs_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - True - true - true - - - - - diff --git a/src/tests/JIT/Methodical/doublearray/dblarray4.cs b/src/tests/JIT/Methodical/doublearray/dblarray4.cs index 6ed7e8360e71..748bf3de2fa2 100644 --- a/src/tests/JIT/Methodical/doublearray/dblarray4.cs +++ b/src/tests/JIT/Methodical/doublearray/dblarray4.cs @@ -20,6 +20,9 @@ public class DblArray4 { private static int s_LOH_GEN = 0; [Fact] + [SkipOnCoreClr("This test is not compatible with GCStress.", RuntimeTestModes.AnyGCStress)] + [OuterLoop] + [ActiveIssue("https://github.com/dotnet/runtime/issues/101284", typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNativeAot))] public static int TestEntryPoint() { if (RuntimeInformation.ProcessArchitecture == Architecture.X86) diff --git a/src/tests/JIT/Methodical/doublearray/dblarray4_cs_d.csproj b/src/tests/JIT/Methodical/doublearray/dblarray4_cs_d.csproj index d2612ba78b4a..51b3550346b9 100644 --- a/src/tests/JIT/Methodical/doublearray/dblarray4_cs_d.csproj +++ b/src/tests/JIT/Methodical/doublearray/dblarray4_cs_d.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/tests/JIT/Methodical/doublearray/dblarray4_cs_do.csproj b/src/tests/JIT/Methodical/doublearray/dblarray4_cs_do.csproj index 4fba8ea934c2..ac2740b94747 100644 --- a/src/tests/JIT/Methodical/doublearray/dblarray4_cs_do.csproj +++ b/src/tests/JIT/Methodical/doublearray/dblarray4_cs_do.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/tests/JIT/Methodical/doublearray/dblarray4_cs_r.csproj b/src/tests/JIT/Methodical/doublearray/dblarray4_cs_r.csproj index 6fd9649c99cc..869938404993 100644 --- a/src/tests/JIT/Methodical/doublearray/dblarray4_cs_r.csproj +++ b/src/tests/JIT/Methodical/doublearray/dblarray4_cs_r.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/tests/JIT/Methodical/doublearray/dblarray4_cs_ro.csproj b/src/tests/JIT/Methodical/doublearray/dblarray4_cs_ro.csproj index 99f64aa73dbe..de054c04ca67 100644 --- a/src/tests/JIT/Methodical/doublearray/dblarray4_cs_ro.csproj +++ b/src/tests/JIT/Methodical/doublearray/dblarray4_cs_ro.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/tests/JIT/Methodical/dynamic_methods/bug_445388.cs b/src/tests/JIT/Methodical/dynamic_methods/bug_445388.cs index 7026dc50fa26..982119b3bc9e 100644 --- a/src/tests/JIT/Methodical/dynamic_methods/bug_445388.cs +++ b/src/tests/JIT/Methodical/dynamic_methods/bug_445388.cs @@ -18,6 +18,7 @@ public class Program private delegate string Getter(); [Fact] + [OuterLoop] public static int TestEntryPoint() { DynamicMethod method = new DynamicMethod("GetField", diff --git a/src/tests/JIT/Methodical/dynamic_methods/bug_445388.csproj b/src/tests/JIT/Methodical/dynamic_methods/bug_445388.csproj deleted file mode 100644 index 77d95a6ca1b6..000000000000 --- a/src/tests/JIT/Methodical/dynamic_methods/bug_445388.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - 1 - - - PdbOnly - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/multihandler_d.csproj b/src/tests/JIT/Methodical/eh/basics/multihandler_d.csproj deleted file mode 100644 index 92d5abd95592..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/multihandler_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/multihandler_do.csproj b/src/tests/JIT/Methodical/eh/basics/multihandler_do.csproj deleted file mode 100644 index 4a9abf2e94e4..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/multihandler_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/multihandler_r.csproj b/src/tests/JIT/Methodical/eh/basics/multihandler_r.csproj deleted file mode 100644 index b79d84baa6e5..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/multihandler_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/multihandler_ro.csproj b/src/tests/JIT/Methodical/eh/basics/multihandler_ro.csproj deleted file mode 100644 index b87be1128fe5..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/multihandler_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwincatch.cs b/src/tests/JIT/Methodical/eh/basics/throwincatch.cs index 8f891ec470cc..85f314b931aa 100644 --- a/src/tests/JIT/Methodical/eh/basics/throwincatch.cs +++ b/src/tests/JIT/Methodical/eh/basics/throwincatch.cs @@ -29,6 +29,7 @@ static Class1() } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/basics/throwincatch_basics_d.csproj b/src/tests/JIT/Methodical/eh/basics/throwincatch_basics_d.csproj deleted file mode 100644 index 5edb8c855532..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwincatch_basics_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwincatch_basics_do.csproj b/src/tests/JIT/Methodical/eh/basics/throwincatch_basics_do.csproj deleted file mode 100644 index 49c009510798..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwincatch_basics_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwincatch_basics_r.csproj b/src/tests/JIT/Methodical/eh/basics/throwincatch_basics_r.csproj deleted file mode 100644 index 0ad8ca5698b0..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwincatch_basics_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwincatch_basics_ro.csproj b/src/tests/JIT/Methodical/eh/basics/throwincatch_basics_ro.csproj deleted file mode 100644 index d2692a5e5e33..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwincatch_basics_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinclassconstructor_d.csproj b/src/tests/JIT/Methodical/eh/basics/throwinclassconstructor_d.csproj deleted file mode 100644 index 2fff9d90e658..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinclassconstructor_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinclassconstructor_do.csproj b/src/tests/JIT/Methodical/eh/basics/throwinclassconstructor_do.csproj deleted file mode 100644 index 7a292a44ceb9..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinclassconstructor_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinclassconstructor_r.csproj b/src/tests/JIT/Methodical/eh/basics/throwinclassconstructor_r.csproj deleted file mode 100644 index 066dec682d7b..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinclassconstructor_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinclassconstructor_ro.csproj b/src/tests/JIT/Methodical/eh/basics/throwinclassconstructor_ro.csproj deleted file mode 100644 index 9f5112c5cd61..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinclassconstructor_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinfinally_basics_d.csproj b/src/tests/JIT/Methodical/eh/basics/throwinfinally_basics_d.csproj deleted file mode 100644 index b01250febfa4..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinfinally_basics_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinfinally_basics_do.csproj b/src/tests/JIT/Methodical/eh/basics/throwinfinally_basics_do.csproj deleted file mode 100644 index 16e16d80b694..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinfinally_basics_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinfinally_basics_r.csproj b/src/tests/JIT/Methodical/eh/basics/throwinfinally_basics_r.csproj deleted file mode 100644 index 8f7da9c003bb..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinfinally_basics_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinfinally_basics_ro.csproj b/src/tests/JIT/Methodical/eh/basics/throwinfinally_basics_ro.csproj deleted file mode 100644 index cb0d78021d12..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinfinally_basics_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath.cs b/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath.cs index d0669711304c..e2a4816c049d 100644 --- a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath.cs +++ b/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath.cs @@ -46,6 +46,7 @@ static public void inFinally() Console.WriteLine("in Finally"); } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath_d.csproj b/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath_d.csproj deleted file mode 100644 index d56428fd35d7..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath_do.csproj b/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath_do.csproj deleted file mode 100644 index c6b88bc7c857..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath_r.csproj b/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath_r.csproj deleted file mode 100644 index 7a06cb492ed1..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath_ro.csproj b/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath_ro.csproj deleted file mode 100644 index 68034fac3f82..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpath_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn.cs b/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn.cs index 98aced2284fc..1b0290515205 100644 --- a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn.cs +++ b/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn.cs @@ -43,6 +43,7 @@ public static void MiddleMethod() } [Fact] + [OuterLoop] public static int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn_d.csproj b/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn_d.csproj deleted file mode 100644 index 9b8a34e0b61b..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn_do.csproj b/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn_do.csproj deleted file mode 100644 index eb305983a951..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn_r.csproj b/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn_r.csproj deleted file mode 100644 index 0fb49468c330..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn_ro.csproj b/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn_ro.csproj deleted file mode 100644 index 0d014f2f5688..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwinfinallyerrpathfn_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwoutside.cs b/src/tests/JIT/Methodical/eh/basics/throwoutside.cs index 7fcb442e52de..5037143cbab5 100644 --- a/src/tests/JIT/Methodical/eh/basics/throwoutside.cs +++ b/src/tests/JIT/Methodical/eh/basics/throwoutside.cs @@ -33,6 +33,7 @@ public static void MiddleMethod() } [Fact] + [OuterLoop] public static int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/basics/throwoutside_d.csproj b/src/tests/JIT/Methodical/eh/basics/throwoutside_d.csproj deleted file mode 100644 index fff08fd76be2..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwoutside_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwoutside_do.csproj b/src/tests/JIT/Methodical/eh/basics/throwoutside_do.csproj deleted file mode 100644 index 5bd522e865e3..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwoutside_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwoutside_r.csproj b/src/tests/JIT/Methodical/eh/basics/throwoutside_r.csproj deleted file mode 100644 index 0531f2126554..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwoutside_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/throwoutside_ro.csproj b/src/tests/JIT/Methodical/eh/basics/throwoutside_ro.csproj deleted file mode 100644 index fc0149147df8..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/throwoutside_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trycatch.cs b/src/tests/JIT/Methodical/eh/basics/trycatch.cs index f99cd6bbacdf..7b916cc60684 100644 --- a/src/tests/JIT/Methodical/eh/basics/trycatch.cs +++ b/src/tests/JIT/Methodical/eh/basics/trycatch.cs @@ -36,6 +36,7 @@ static public void inCatch() static public void inFinally() { } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/basics/trycatch_d.csproj b/src/tests/JIT/Methodical/eh/basics/trycatch_d.csproj deleted file mode 100644 index 6ee9059b3299..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trycatch_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trycatch_do.csproj b/src/tests/JIT/Methodical/eh/basics/trycatch_do.csproj deleted file mode 100644 index d7ccca19bece..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trycatch_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trycatch_r.csproj b/src/tests/JIT/Methodical/eh/basics/trycatch_r.csproj deleted file mode 100644 index 31a691141ab3..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trycatch_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trycatch_ro.csproj b/src/tests/JIT/Methodical/eh/basics/trycatch_ro.csproj deleted file mode 100644 index e830b38bb6b3..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trycatch_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch.cs b/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch.cs index 8248bd78e297..64c4b4dfecb7 100644 --- a/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch.cs +++ b/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch.cs @@ -39,6 +39,7 @@ static public void inFinally() } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch_d.csproj b/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch_d.csproj deleted file mode 100644 index baeb8a40174c..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch_do.csproj b/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch_do.csproj deleted file mode 100644 index d8097835ea72..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch_r.csproj b/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch_r.csproj deleted file mode 100644 index dc8726f5d67b..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch_ro.csproj b/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch_ro.csproj deleted file mode 100644 index 511ddc836c8b..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trycatchtrycatch_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinally.cs b/src/tests/JIT/Methodical/eh/basics/tryfinally.cs index 68e22057d305..f27c8602fb45 100644 --- a/src/tests/JIT/Methodical/eh/basics/tryfinally.cs +++ b/src/tests/JIT/Methodical/eh/basics/tryfinally.cs @@ -36,6 +36,7 @@ static public void inFinally() } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinally_d.csproj b/src/tests/JIT/Methodical/eh/basics/tryfinally_d.csproj deleted file mode 100644 index 6bfeb7dfd262..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/tryfinally_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinally_do.csproj b/src/tests/JIT/Methodical/eh/basics/tryfinally_do.csproj deleted file mode 100644 index af4c79e6cd1b..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/tryfinally_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinally_r.csproj b/src/tests/JIT/Methodical/eh/basics/tryfinally_r.csproj deleted file mode 100644 index 79cd614e8f5e..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/tryfinally_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinally_ro.csproj b/src/tests/JIT/Methodical/eh/basics/tryfinally_ro.csproj deleted file mode 100644 index b1ba1496ea41..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/tryfinally_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch.cs b/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch.cs index 5b6f03d68afd..2274774d2ec6 100644 --- a/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch.cs +++ b/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch.cs @@ -46,6 +46,7 @@ static public void inFinally() } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch_d.csproj b/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch_d.csproj deleted file mode 100644 index 46e5a7311f28..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch_do.csproj b/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch_do.csproj deleted file mode 100644 index 7b0f083b24ae..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch_r.csproj b/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch_r.csproj deleted file mode 100644 index 9527f45c75b7..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch_ro.csproj b/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch_ro.csproj deleted file mode 100644 index 0ce466c479d6..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/tryfinallytrycatch_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally.cs b/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally.cs index 482b53291067..ec08223e265c 100644 --- a/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally.cs +++ b/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally.cs @@ -26,6 +26,7 @@ static Class1() } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally_d.csproj b/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally_d.csproj deleted file mode 100644 index 8994b5332fbc..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally_do.csproj b/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally_do.csproj deleted file mode 100644 index cc693144c634..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally_r.csproj b/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally_r.csproj deleted file mode 100644 index 45b7f1648eb6..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally_ro.csproj b/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally_ro.csproj deleted file mode 100644 index f9c0a4db33c6..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/tryfinallytryfinally_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trythrowcatch.cs b/src/tests/JIT/Methodical/eh/basics/trythrowcatch.cs index a8d4f8c3998d..d0283627d945 100644 --- a/src/tests/JIT/Methodical/eh/basics/trythrowcatch.cs +++ b/src/tests/JIT/Methodical/eh/basics/trythrowcatch.cs @@ -37,6 +37,7 @@ static public void inCatch() static public void inFinally() { } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/basics/trythrowcatch_d.csproj b/src/tests/JIT/Methodical/eh/basics/trythrowcatch_d.csproj deleted file mode 100644 index 2fad2a5e1509..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trythrowcatch_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trythrowcatch_do.csproj b/src/tests/JIT/Methodical/eh/basics/trythrowcatch_do.csproj deleted file mode 100644 index 914b66d65d5c..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trythrowcatch_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trythrowcatch_r.csproj b/src/tests/JIT/Methodical/eh/basics/trythrowcatch_r.csproj deleted file mode 100644 index 8a871d8789d5..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trythrowcatch_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trythrowcatch_ro.csproj b/src/tests/JIT/Methodical/eh/basics/trythrowcatch_ro.csproj deleted file mode 100644 index 2c6a0831228f..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trythrowcatch_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally.cs b/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally.cs index edf9f0b67c42..318a1a68e48d 100644 --- a/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally.cs +++ b/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally.cs @@ -27,6 +27,7 @@ static test() } [Fact] + [OuterLoop] public static int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally_d.csproj b/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally_d.csproj deleted file mode 100644 index d549831d794f..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally_do.csproj b/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally_do.csproj deleted file mode 100644 index 9a3f6b236321..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally_r.csproj b/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally_r.csproj deleted file mode 100644 index d4c9b23cdafd..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally_ro.csproj b/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally_ro.csproj deleted file mode 100644 index 6209006c18f0..000000000000 --- a/src/tests/JIT/Methodical/eh/basics/trythrowcatchfinally_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/cs/unsafe.cs b/src/tests/JIT/Methodical/eh/cs/unsafe.cs index a8a617e10ff5..7e8ed9b4894c 100644 --- a/src/tests/JIT/Methodical/eh/cs/unsafe.cs +++ b/src/tests/JIT/Methodical/eh/cs/unsafe.cs @@ -54,6 +54,7 @@ unsafe static void WriteLocations(byte[] arr) } [Fact] + [OuterLoop] public static int TestEntryPoint() { //Start recording @@ -70,7 +71,7 @@ public static int TestEntryPoint() goto done; } Console.WriteLine("After try"); - done: + done: Console.WriteLine("Done"); // stop recoding testLog.StopRecording(); diff --git a/src/tests/JIT/Methodical/eh/cs/unsafe_d.csproj b/src/tests/JIT/Methodical/eh/cs/unsafe_d.csproj deleted file mode 100644 index 20a012cc9cee..000000000000 --- a/src/tests/JIT/Methodical/eh/cs/unsafe_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/cs/unsafe_do.csproj b/src/tests/JIT/Methodical/eh/cs/unsafe_do.csproj deleted file mode 100644 index 8314c7435955..000000000000 --- a/src/tests/JIT/Methodical/eh/cs/unsafe_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/cs/unsafe_r.csproj b/src/tests/JIT/Methodical/eh/cs/unsafe_r.csproj deleted file mode 100644 index d37104ec3ca8..000000000000 --- a/src/tests/JIT/Methodical/eh/cs/unsafe_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - true - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/cs/unsafe_ro.csproj b/src/tests/JIT/Methodical/eh/cs/unsafe_ro.csproj deleted file mode 100644 index f2da963662aa..000000000000 --- a/src/tests/JIT/Methodical/eh/cs/unsafe_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - true - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto.cs b/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto.cs index 096551c7a306..963669b7f0b9 100644 --- a/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto.cs +++ b/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto.cs @@ -27,6 +27,7 @@ static Class1() } [Fact] + [OuterLoop] public static int TestEntryPoint() { string[] s = { "one", "two", "three", "four", "five", "six" }; diff --git a/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto_d.csproj b/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto_d.csproj deleted file mode 100644 index b5590f44bcfa..000000000000 --- a/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - Full - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto_do.csproj b/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto_do.csproj deleted file mode 100644 index 3f0e27131e90..000000000000 --- a/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - Full - True - - - - - - diff --git a/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto_r.csproj b/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto_r.csproj deleted file mode 100644 index d6909f678df3..000000000000 --- a/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - None - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto_ro.csproj b/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto_ro.csproj deleted file mode 100644 index 4142657f83fc..000000000000 --- a/src/tests/JIT/Methodical/eh/deadcode/loopstrswitchgoto_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - None - True - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry_cs_d.csproj b/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry_cs_d.csproj deleted file mode 100644 index 802a5977149a..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry_cs_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry_cs_do.csproj b/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry_cs_do.csproj deleted file mode 100644 index 6205bb9ffd2e..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry_cs_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry_cs_r.csproj b/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry_cs_r.csproj deleted file mode 100644 index 04e5374587f7..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry_cs_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - PdbOnly - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry_cs_ro.csproj b/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry_cs_ro.csproj deleted file mode 100644 index 6b6b9cd46349..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/catchrettoinnertry_cs_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - PdbOnly - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler.cs b/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler.cs index 79b9b7998d2a..46aa796eb0c7 100644 --- a/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler.cs +++ b/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler.cs @@ -28,6 +28,7 @@ static Class1() testLog = new TestUtil.TestLog(expectedOut); } [Fact] + [OuterLoop] public static int TestEntryPoint() { //Start recording @@ -58,7 +59,7 @@ public static int TestEntryPoint() Console.WriteLine("Will never see this code, jumping over it!"); - LABEL: + LABEL: Console.WriteLine("Back in inner try 1..."); } diff --git a/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler_d.csproj b/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler_d.csproj deleted file mode 100644 index 6bf3ccd86052..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler_do.csproj b/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler_do.csproj deleted file mode 100644 index 0c5eabc14f77..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler_r.csproj b/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler_r.csproj deleted file mode 100644 index e6cd7ad7a68c..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler_ro.csproj b/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler_ro.csproj deleted file mode 100644 index 7382672262e8..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/localgotoinahandler_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally.cs b/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally.cs index 3b9be67adc22..58a91ef0f950 100644 --- a/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally.cs +++ b/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally.cs @@ -27,6 +27,7 @@ static Class1() } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/65704", TestRuntimes.Mono)] public static int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally_d.csproj b/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally_d.csproj deleted file mode 100644 index 03ed68b549a2..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally_do.csproj b/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally_do.csproj deleted file mode 100644 index 6aaec0b746d4..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally_r.csproj b/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally_r.csproj deleted file mode 100644 index ef40527f68d3..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally_ro.csproj b/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally_ro.csproj deleted file mode 100644 index dd0413e4ec89..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/loopinfinally_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry.cs b/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry.cs index ead333c6f090..bf381b484547 100644 --- a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry.cs +++ b/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry.cs @@ -29,6 +29,7 @@ static Class1() } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry_d.csproj b/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry_d.csproj deleted file mode 100644 index a84a811be49e..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry_do.csproj b/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry_do.csproj deleted file mode 100644 index 9409fb0080c6..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry_r.csproj b/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry_r.csproj deleted file mode 100644 index aade27e58d77..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry_ro.csproj b/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry_ro.csproj deleted file mode 100644 index 01c7dd6aef13..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalexittobeginningoftry_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler.cs b/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler.cs index e3698288cde1..15415f6bdf98 100644 --- a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler.cs +++ b/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler.cs @@ -28,6 +28,7 @@ static simple() testLog = new TestUtil.TestLog(expectedOut); } [Fact] + [OuterLoop] public static int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler_d.csproj b/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler_d.csproj deleted file mode 100644 index 31e4e6f77817..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler_do.csproj b/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler_do.csproj deleted file mode 100644 index 1990e510fb01..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler_r.csproj b/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler_r.csproj deleted file mode 100644 index 324e2e2d9638..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler_ro.csproj b/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler_ro.csproj deleted file mode 100644 index d895f05d2184..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/nonlocalgotoinatryblockinahandler_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit.cs b/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit.cs index 5fa901819ab3..6ec5dbe69c6e 100644 --- a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit.cs +++ b/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit.cs @@ -25,6 +25,7 @@ static Class1() } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit_d.csproj b/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit_d.csproj deleted file mode 100644 index e6ef3322a887..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit_do.csproj b/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit_do.csproj deleted file mode 100644 index 01bcb81e0a94..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit_r.csproj b/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit_r.csproj deleted file mode 100644 index f5f4ecb4862a..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit_ro.csproj b/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit_ro.csproj deleted file mode 100644 index 516e213e3bbc..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexit_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch.cs b/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch.cs index e4ef850f47d4..2012ae568375 100644 --- a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch.cs +++ b/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch.cs @@ -24,6 +24,7 @@ static Class1() } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch_d.csproj b/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch_d.csproj deleted file mode 100644 index e97676784d3a..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch_do.csproj b/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch_do.csproj deleted file mode 100644 index 2c7e95cf5b9a..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch_r.csproj b/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch_r.csproj deleted file mode 100644 index 375bd29c4aa0..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch_ro.csproj b/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch_ro.csproj deleted file mode 100644 index be3ce2a5be5b..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/simplenonlocalexitnestedintrycatch_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/switchincatch.cs b/src/tests/JIT/Methodical/eh/finallyexec/switchincatch.cs index 894306a90f8d..2d07df2d9bc1 100644 --- a/src/tests/JIT/Methodical/eh/finallyexec/switchincatch.cs +++ b/src/tests/JIT/Methodical/eh/finallyexec/switchincatch.cs @@ -42,6 +42,7 @@ static Class1() /// The main entry point for the application. /// [Fact] + [OuterLoop] public static int TestEntryPoint() { string[] s = { "one", "two", "three", "four", "five", "six" }; @@ -51,7 +52,7 @@ public static int TestEntryPoint() for (int i = 0; i < s.Length; i++) { - beginloop: + beginloop: try { try @@ -86,11 +87,11 @@ public static int TestEntryPoint() Console.WriteLine("In outer finally\n"); } - continueloop: + continueloop: Console.WriteLine("Continuing"); } - finish: + finish: // stop recoding testLog.StopRecording(); return testLog.VerifyOutput(); diff --git a/src/tests/JIT/Methodical/eh/finallyexec/switchincatch_d.csproj b/src/tests/JIT/Methodical/eh/finallyexec/switchincatch_d.csproj deleted file mode 100644 index e03fe144ab8d..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/switchincatch_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/switchincatch_do.csproj b/src/tests/JIT/Methodical/eh/finallyexec/switchincatch_do.csproj deleted file mode 100644 index 2e73f476388a..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/switchincatch_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/switchincatch_r.csproj b/src/tests/JIT/Methodical/eh/finallyexec/switchincatch_r.csproj deleted file mode 100644 index 254410a30920..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/switchincatch_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/switchincatch_ro.csproj b/src/tests/JIT/Methodical/eh/finallyexec/switchincatch_ro.csproj deleted file mode 100644 index b2a47d2588e6..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/switchincatch_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1.cs b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1.cs index cc6065f47851..ab7a266993a4 100644 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1.cs +++ b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1.cs @@ -42,11 +42,12 @@ static public void Middle1(int i) if (i == 0) throw new Exception(); } Console.WriteLine("after finally"); - L1: + L1: Console.WriteLine("middle1 L1"); } [Fact] + [OuterLoop] static public int TestEntryPoint() { // start recording diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1_d.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1_d.csproj deleted file mode 100644 index dc5ac7aeb79a..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1_do.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1_do.csproj deleted file mode 100644 index b8af8f6e80e4..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1_r.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1_r.csproj deleted file mode 100644 index d89521aee0f6..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1_ro.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1_ro.csproj deleted file mode 100644 index 1cab52abfaac..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit1_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2.cs b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2.cs index e1982fd9ec81..97e9fc3bc2b0 100644 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2.cs +++ b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2.cs @@ -46,7 +46,7 @@ static public void Middle1(int i) if (i == 0) throw new Exception(); } Console.WriteLine("after middle1 finally"); - L1: + L1: Console.WriteLine("middle1 L1"); } @@ -67,11 +67,12 @@ static public void Middle2(int i) if (i == 0) throw new Exception(); } Console.WriteLine("after middle2 finally"); - L2: + L2: Console.WriteLine("middle2 L2"); } [Fact] + [OuterLoop] static public int TestEntryPoint() { // start recording diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2_d.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2_d.csproj deleted file mode 100644 index f1063b0379ae..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2_do.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2_do.csproj deleted file mode 100644 index 55be758d423e..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2_r.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2_r.csproj deleted file mode 100644 index e71e2225043b..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2_ro.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2_ro.csproj deleted file mode 100644 index d1e3cf0918fe..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit2_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3.cs b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3.cs index 77c89c97e80e..b5971f67e6e3 100644 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3.cs +++ b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3.cs @@ -38,7 +38,7 @@ static Class1() static public void Middle1(int i) { - L1A: + L1A: Console.WriteLine(" in middle1 L1A"); try { @@ -58,13 +58,13 @@ static public void Middle1(int i) i--; } Console.WriteLine(" after middle1 finally"); - L1B: + L1B: Console.WriteLine(" in middle1 L1"); } static public void Middle2(int i) { - L2A: + L2A: Console.WriteLine(" in middle2 L2A"); try { @@ -83,11 +83,12 @@ static public void Middle2(int i) i--; } Console.WriteLine(" after middle2 finally"); - L2B: + L2B: Console.WriteLine(" in middle2 L2B"); } [Fact] + [OuterLoop] static public int TestEntryPoint() { // start recording diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3_d.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3_d.csproj deleted file mode 100644 index dd35a29f26dd..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3_do.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3_do.csproj deleted file mode 100644 index ebb1dae69e25..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3_r.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3_r.csproj deleted file mode 100644 index 7c0ae289a156..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3_ro.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3_ro.csproj deleted file mode 100644 index e794afeeadff..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit3_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4.cs b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4.cs index 0534c69bc6ad..800521d33454 100644 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4.cs +++ b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4.cs @@ -58,12 +58,13 @@ static public void foo(int i) if (i == 0) throw new Exception(); } Console.WriteLine("after finally"); - L1: + L1: Console.WriteLine("foo L1"); } [Fact] + [OuterLoop] static public int TestEntryPoint() { // start recording diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4_d.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4_d.csproj deleted file mode 100644 index dc0c8c703339..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4_do.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4_do.csproj deleted file mode 100644 index 36aca48eebc2..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4_r.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4_r.csproj deleted file mode 100644 index 0e319ed14957..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4_ro.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4_ro.csproj deleted file mode 100644 index c1b1099b4ebb..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryCatchFinallyThrow_nonlocalexit4_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit.cs b/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit.cs index 34836f8e6ccf..61e4ce847136 100644 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit.cs +++ b/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit.cs @@ -55,6 +55,7 @@ static public void Middle(int i) } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit_d.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit_d.csproj deleted file mode 100644 index 3fbb7597d671..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit_do.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit_do.csproj deleted file mode 100644 index 686daca23452..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit_r.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit_r.csproj deleted file mode 100644 index c0f535dcf80d..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit_ro.csproj b/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit_ro.csproj deleted file mode 100644 index 0b120d97b118..000000000000 --- a/src/tests/JIT/Methodical/eh/finallyexec/tryfinallythrow_nonlocalexit_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/generics/throwincatch.cs b/src/tests/JIT/Methodical/eh/generics/throwincatch.cs index 3eb62002f6cb..7cc2579b6f10 100644 --- a/src/tests/JIT/Methodical/eh/generics/throwincatch.cs +++ b/src/tests/JIT/Methodical/eh/generics/throwincatch.cs @@ -5,6 +5,7 @@ using System.IO; using Xunit; +namespace JIT.Methodical.eh.generics.throwincatch; public class GenException : Exception { diff --git a/src/tests/JIT/Methodical/eh/generics/throwincatch_generics_d.csproj b/src/tests/JIT/Methodical/eh/generics/throwincatch_generics_d.csproj deleted file mode 100644 index 7a946d405442..000000000000 --- a/src/tests/JIT/Methodical/eh/generics/throwincatch_generics_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/generics/throwincatch_generics_do.csproj b/src/tests/JIT/Methodical/eh/generics/throwincatch_generics_do.csproj deleted file mode 100644 index a654a1c98e0d..000000000000 --- a/src/tests/JIT/Methodical/eh/generics/throwincatch_generics_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/generics/throwincatch_generics_r.csproj b/src/tests/JIT/Methodical/eh/generics/throwincatch_generics_r.csproj deleted file mode 100644 index 16d6b53b3d65..000000000000 --- a/src/tests/JIT/Methodical/eh/generics/throwincatch_generics_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/generics/throwincatch_generics_ro.csproj b/src/tests/JIT/Methodical/eh/generics/throwincatch_generics_ro.csproj deleted file mode 100644 index ef4a4a278f24..000000000000 --- a/src/tests/JIT/Methodical/eh/generics/throwincatch_generics_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype.cs b/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype.cs index a43af3246e44..76d1d68023a7 100644 --- a/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype.cs +++ b/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype.cs @@ -5,6 +5,7 @@ using System.IO; using Xunit; +namespace JIT.Methodical.eh.generics.trycatchnestedtype; public class GenException : Exception { diff --git a/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype_d.csproj b/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype_d.csproj deleted file mode 100644 index c9328c48b6d8..000000000000 --- a/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype_do.csproj b/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype_do.csproj deleted file mode 100644 index bbe6869b327c..000000000000 --- a/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype_r.csproj b/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype_r.csproj deleted file mode 100644 index cb484c0dedc4..000000000000 --- a/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype_ro.csproj b/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype_ro.csproj deleted file mode 100644 index ce8304c4b31e..000000000000 --- a/src/tests/JIT/Methodical/eh/generics/trycatchnestedtype_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype.cs b/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype.cs index a6cf237311bf..0b3fde559232 100644 --- a/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype.cs +++ b/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype.cs @@ -5,6 +5,7 @@ using System.IO; using Xunit; +namespace JIT.Methodical.eh.generics.trycatchsimpletype; public class GenException : Exception { diff --git a/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype_d.csproj b/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype_d.csproj deleted file mode 100644 index b8a1a960a2f0..000000000000 --- a/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype_do.csproj b/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype_do.csproj deleted file mode 100644 index 451dceb610e2..000000000000 --- a/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype_r.csproj b/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype_r.csproj deleted file mode 100644 index 200c6059d86e..000000000000 --- a/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype_ro.csproj b/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype_ro.csproj deleted file mode 100644 index 4354935f2ea9..000000000000 --- a/src/tests/JIT/Methodical/eh/generics/trycatchsimpletype_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/ehSO.cs b/src/tests/JIT/Methodical/eh/interactions/ehSO.cs index bc42ee8d1ec7..b51981b38b76 100644 --- a/src/tests/JIT/Methodical/eh/interactions/ehSO.cs +++ b/src/tests/JIT/Methodical/eh/interactions/ehSO.cs @@ -31,6 +31,7 @@ public Form1() } [Fact] + [OuterLoop] public static void TestEntryPoint() { Form1 f = new Form1(); diff --git a/src/tests/JIT/Methodical/eh/interactions/ehso.csproj b/src/tests/JIT/Methodical/eh/interactions/ehso.csproj deleted file mode 100644 index 89cc59c51bd7..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/ehso.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - 1 - - - Full - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/gcincatch.cs b/src/tests/JIT/Methodical/eh/interactions/gcincatch.cs index 85407bbaba29..f360175e00ce 100644 --- a/src/tests/JIT/Methodical/eh/interactions/gcincatch.cs +++ b/src/tests/JIT/Methodical/eh/interactions/gcincatch.cs @@ -42,6 +42,7 @@ static Class1() /// The main entry point for the application. /// [Fact] + [OuterLoop] public static int TestEntryPoint() { int[] ar = new int[] { 1, 2, 3, 4, 5 }; diff --git a/src/tests/JIT/Methodical/eh/interactions/gcincatch_d.csproj b/src/tests/JIT/Methodical/eh/interactions/gcincatch_d.csproj deleted file mode 100644 index 151edb796cec..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/gcincatch_d.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - 1 - - true - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/gcincatch_do.csproj b/src/tests/JIT/Methodical/eh/interactions/gcincatch_do.csproj deleted file mode 100644 index 8a0b3d630bb4..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/gcincatch_do.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - 1 - - true - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/gcincatch_r.csproj b/src/tests/JIT/Methodical/eh/interactions/gcincatch_r.csproj deleted file mode 100644 index aa7e47e195ca..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/gcincatch_r.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - 1 - - true - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/gcincatch_ro.csproj b/src/tests/JIT/Methodical/eh/interactions/gcincatch_ro.csproj deleted file mode 100644 index 2e58575297ba..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/gcincatch_ro.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - 1 - - true - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/rangecheckinfinally_d.csproj b/src/tests/JIT/Methodical/eh/interactions/rangecheckinfinally_d.csproj deleted file mode 100644 index 75343d6c2442..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/rangecheckinfinally_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/rangecheckinfinally_do.csproj b/src/tests/JIT/Methodical/eh/interactions/rangecheckinfinally_do.csproj deleted file mode 100644 index b5812ac85e85..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/rangecheckinfinally_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/rangecheckinfinally_r.csproj b/src/tests/JIT/Methodical/eh/interactions/rangecheckinfinally_r.csproj deleted file mode 100644 index ecddeaa61ad7..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/rangecheckinfinally_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/rangecheckinfinally_ro.csproj b/src/tests/JIT/Methodical/eh/interactions/rangecheckinfinally_ro.csproj deleted file mode 100644 index 7766e1dda3f0..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/rangecheckinfinally_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/strswitchfinal_d.csproj b/src/tests/JIT/Methodical/eh/interactions/strswitchfinal_d.csproj deleted file mode 100644 index 218db32ece71..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/strswitchfinal_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - Full - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/strswitchfinal_do.csproj b/src/tests/JIT/Methodical/eh/interactions/strswitchfinal_do.csproj deleted file mode 100644 index 797eb24aa82d..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/strswitchfinal_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - Full - True - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/strswitchfinal_r.csproj b/src/tests/JIT/Methodical/eh/interactions/strswitchfinal_r.csproj deleted file mode 100644 index 37af775826d4..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/strswitchfinal_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - None - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/strswitchfinal_ro.csproj b/src/tests/JIT/Methodical/eh/interactions/strswitchfinal_ro.csproj deleted file mode 100644 index 1a46ccd74ade..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/strswitchfinal_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - None - True - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/switchinfinally.cs b/src/tests/JIT/Methodical/eh/interactions/switchinfinally.cs index 7dce04e5e753..8d4878c219a6 100644 --- a/src/tests/JIT/Methodical/eh/interactions/switchinfinally.cs +++ b/src/tests/JIT/Methodical/eh/interactions/switchinfinally.cs @@ -87,6 +87,7 @@ static Class1() /// The main entry point for the application. /// [Fact] + [ActiveIssue("needs triage", TestPlatforms.Browser | TestPlatforms.Wasi | TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public static int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/interactions/switchinfinally_d.csproj b/src/tests/JIT/Methodical/eh/interactions/switchinfinally_d.csproj deleted file mode 100644 index 9054ee0e709b..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/switchinfinally_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/switchinfinally_do.csproj b/src/tests/JIT/Methodical/eh/interactions/switchinfinally_do.csproj deleted file mode 100644 index 63d6d8a98172..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/switchinfinally_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/switchinfinally_r.csproj b/src/tests/JIT/Methodical/eh/interactions/switchinfinally_r.csproj deleted file mode 100644 index 3748824984ab..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/switchinfinally_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/switchinfinally_ro.csproj b/src/tests/JIT/Methodical/eh/interactions/switchinfinally_ro.csproj deleted file mode 100644 index 40b179bc907d..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/switchinfinally_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/interactions/volatileFromFinally.cs b/src/tests/JIT/Methodical/eh/interactions/volatileFromFinally.cs index e4316f97e073..89fe827220d7 100644 --- a/src/tests/JIT/Methodical/eh/interactions/volatileFromFinally.cs +++ b/src/tests/JIT/Methodical/eh/interactions/volatileFromFinally.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -/* +/* Expected behavior: 64 bit = False @@ -41,6 +41,7 @@ private static void Crash() } [Fact] + [OuterLoop] public static int TestEntryPoint() { //Console.WriteLine("64 bit = {0}", Environment.Is64BitProcess); diff --git a/src/tests/JIT/Methodical/eh/interactions/volatilefromfinally.csproj b/src/tests/JIT/Methodical/eh/interactions/volatilefromfinally.csproj deleted file mode 100644 index 2f8cce3c974c..000000000000 --- a/src/tests/JIT/Methodical/eh/interactions/volatilefromfinally.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - 1 - - - Full - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/catchretnonlocalexitinfunclet_d.csproj b/src/tests/JIT/Methodical/eh/leaves/catchretnonlocalexitinfunclet_d.csproj deleted file mode 100644 index 40205910dd28..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/catchretnonlocalexitinfunclet_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/catchretnonlocalexitinfunclet_do.csproj b/src/tests/JIT/Methodical/eh/leaves/catchretnonlocalexitinfunclet_do.csproj deleted file mode 100644 index 0da35c73ace4..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/catchretnonlocalexitinfunclet_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/catchretnonlocalexitinfunclet_r.csproj b/src/tests/JIT/Methodical/eh/leaves/catchretnonlocalexitinfunclet_r.csproj deleted file mode 100644 index 30ace912c5bd..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/catchretnonlocalexitinfunclet_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/catchretnonlocalexitinfunclet_ro.csproj b/src/tests/JIT/Methodical/eh/leaves/catchretnonlocalexitinfunclet_ro.csproj deleted file mode 100644 index 4cb855c68e46..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/catchretnonlocalexitinfunclet_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch.cs b/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch.cs index d1f489375d43..edd6275b544d 100644 --- a/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch.cs +++ b/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch.cs @@ -30,6 +30,7 @@ static test() testLog = new TestUtil.TestLog(expectedOut); } [Fact] + [OuterLoop] public static int TestEntryPoint() { //Start recording @@ -67,7 +68,7 @@ public static int TestEntryPoint() } Console.WriteLine("Never executed"); - L: + L: Console.WriteLine("Done"); // stop recoding testLog.StopRecording(); diff --git a/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch_d.csproj b/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch_d.csproj deleted file mode 100644 index eaf966640262..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch_do.csproj b/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch_do.csproj deleted file mode 100644 index c80ff7f2f034..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch_r.csproj b/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch_r.csproj deleted file mode 100644 index 029b6d0ce063..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch_ro.csproj b/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch_ro.csproj deleted file mode 100644 index c999137f580f..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/nonlocalexitfromnestedcatch_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/oponerror_d.csproj b/src/tests/JIT/Methodical/eh/leaves/oponerror_d.csproj deleted file mode 100644 index d43b6965240f..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/oponerror_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/oponerror_do.csproj b/src/tests/JIT/Methodical/eh/leaves/oponerror_do.csproj deleted file mode 100644 index b9f6ca1becda..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/oponerror_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/oponerror_r.csproj b/src/tests/JIT/Methodical/eh/leaves/oponerror_r.csproj deleted file mode 100644 index a766576e0d0b..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/oponerror_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/oponerror_ro.csproj b/src/tests/JIT/Methodical/eh/leaves/oponerror_ro.csproj deleted file mode 100644 index 5bb4b401c413..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/oponerror_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop.cs b/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop.cs index b5c7e6f3ddde..c542e5500610 100644 --- a/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop.cs +++ b/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop.cs @@ -43,6 +43,7 @@ static public void inFinally() Console.WriteLine("in Finally\n"); } [Fact] + [OuterLoop] static public int TestEntryPoint() { int i = 0; diff --git a/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop_d.csproj b/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop_d.csproj deleted file mode 100644 index 088ce04bf0fe..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop_do.csproj b/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop_do.csproj deleted file mode 100644 index bb637b2a269b..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop_r.csproj b/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop_r.csproj deleted file mode 100644 index 50654d6d3c27..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop_ro.csproj b/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop_ro.csproj deleted file mode 100644 index 259c6f87fadd..000000000000 --- a/src/tests/JIT/Methodical/eh/leaves/tryfinallyloop_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch.cs b/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch.cs index 17d31848d869..66750a75671c 100644 --- a/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch.cs +++ b/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch.cs @@ -59,6 +59,7 @@ static public void inFinally() } [Fact] + [OuterLoop] static public int TestEntryPoint() { string[] args = new string[] {}; diff --git a/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch_d.csproj b/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch_d.csproj deleted file mode 100644 index ecf453f99238..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch_do.csproj b/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch_do.csproj deleted file mode 100644 index 472ed9bc6f92..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch_r.csproj b/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch_r.csproj deleted file mode 100644 index 2d591aa2d570..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch_ro.csproj b/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch_ro.csproj deleted file mode 100644 index 7bfd9d47ae12..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/cascadedcatch_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally.cs b/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally.cs index d196bd87fc35..771bbec94edf 100644 --- a/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally.cs +++ b/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally.cs @@ -34,6 +34,7 @@ static Class1() } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally_d.csproj b/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally_d.csproj deleted file mode 100644 index 5a5bcc941181..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally_do.csproj b/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally_do.csproj deleted file mode 100644 index 80bb18d81856..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally_r.csproj b/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally_r.csproj deleted file mode 100644 index 918a1df6beb9..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally_ro.csproj b/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally_ro.csproj deleted file mode 100644 index 1cd62e7048f8..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/methodthrowsinfinally_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/rethrowincatchnestedinfinally_d.csproj b/src/tests/JIT/Methodical/eh/nested/general/rethrowincatchnestedinfinally_d.csproj deleted file mode 100644 index 154b6c18fcc8..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/rethrowincatchnestedinfinally_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/rethrowincatchnestedinfinally_do.csproj b/src/tests/JIT/Methodical/eh/nested/general/rethrowincatchnestedinfinally_do.csproj deleted file mode 100644 index d585fa0f6ea4..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/rethrowincatchnestedinfinally_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/rethrowincatchnestedinfinally_r.csproj b/src/tests/JIT/Methodical/eh/nested/general/rethrowincatchnestedinfinally_r.csproj deleted file mode 100644 index 3df492e2b75e..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/rethrowincatchnestedinfinally_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/rethrowincatchnestedinfinally_ro.csproj b/src/tests/JIT/Methodical/eh/nested/general/rethrowincatchnestedinfinally_ro.csproj deleted file mode 100644 index 9dd08f6330d5..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/rethrowincatchnestedinfinally_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/throwinfinally_general_d.csproj b/src/tests/JIT/Methodical/eh/nested/general/throwinfinally_general_d.csproj deleted file mode 100644 index 978706fbf965..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/throwinfinally_general_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/throwinfinally_general_do.csproj b/src/tests/JIT/Methodical/eh/nested/general/throwinfinally_general_do.csproj deleted file mode 100644 index 4fbb831788bb..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/throwinfinally_general_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/throwinfinally_general_r.csproj b/src/tests/JIT/Methodical/eh/nested/general/throwinfinally_general_r.csproj deleted file mode 100644 index bc46cbb5e683..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/throwinfinally_general_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/throwinfinally_general_ro.csproj b/src/tests/JIT/Methodical/eh/nested/general/throwinfinally_general_ro.csproj deleted file mode 100644 index c4f6a39c55bc..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/throwinfinally_general_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/throwinfinallynestedintry_d.csproj b/src/tests/JIT/Methodical/eh/nested/general/throwinfinallynestedintry_d.csproj deleted file mode 100644 index 2a4b3bcbb5de..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/throwinfinallynestedintry_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/throwinfinallynestedintry_do.csproj b/src/tests/JIT/Methodical/eh/nested/general/throwinfinallynestedintry_do.csproj deleted file mode 100644 index 272503347e71..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/throwinfinallynestedintry_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/throwinfinallynestedintry_r.csproj b/src/tests/JIT/Methodical/eh/nested/general/throwinfinallynestedintry_r.csproj deleted file mode 100644 index 2ed3716a8b0c..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/throwinfinallynestedintry_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/throwinfinallynestedintry_ro.csproj b/src/tests/JIT/Methodical/eh/nested/general/throwinfinallynestedintry_ro.csproj deleted file mode 100644 index 1eab4a16c2ce..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/throwinfinallynestedintry_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/throwinnestedfinally_d.csproj b/src/tests/JIT/Methodical/eh/nested/general/throwinnestedfinally_d.csproj deleted file mode 100644 index 58100b851ea2..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/throwinnestedfinally_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/throwinnestedfinally_do.csproj b/src/tests/JIT/Methodical/eh/nested/general/throwinnestedfinally_do.csproj deleted file mode 100644 index 8b53f33aab46..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/throwinnestedfinally_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/throwinnestedfinally_r.csproj b/src/tests/JIT/Methodical/eh/nested/general/throwinnestedfinally_r.csproj deleted file mode 100644 index 7be6bdf776fd..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/throwinnestedfinally_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/throwinnestedfinally_ro.csproj b/src/tests/JIT/Methodical/eh/nested/general/throwinnestedfinally_ro.csproj deleted file mode 100644 index eeea79a97c94..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/throwinnestedfinally_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/trycatchintryfinally_d.csproj b/src/tests/JIT/Methodical/eh/nested/general/trycatchintryfinally_d.csproj deleted file mode 100644 index 3fee9720823e..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/trycatchintryfinally_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/trycatchintryfinally_do.csproj b/src/tests/JIT/Methodical/eh/nested/general/trycatchintryfinally_do.csproj deleted file mode 100644 index 3a716feaab93..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/trycatchintryfinally_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/trycatchintryfinally_r.csproj b/src/tests/JIT/Methodical/eh/nested/general/trycatchintryfinally_r.csproj deleted file mode 100644 index 0f282b3fa307..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/trycatchintryfinally_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/general/trycatchintryfinally_ro.csproj b/src/tests/JIT/Methodical/eh/nested/general/trycatchintryfinally_ro.csproj deleted file mode 100644 index d085efb2c9a1..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/general/trycatchintryfinally_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinally_50_d.csproj b/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinally_50_d.csproj deleted file mode 100644 index f38686416f96..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinally_50_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinally_50_do.csproj b/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinally_50_do.csproj deleted file mode 100644 index d4f7f003a895..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinally_50_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinally_50_r.csproj b/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinally_50_r.csproj deleted file mode 100644 index d17fde0def6b..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinally_50_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinally_50_ro.csproj b/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinally_50_ro.csproj deleted file mode 100644 index 1640b5498900..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinally_50_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallynestedintry_30_d.csproj b/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallynestedintry_30_d.csproj deleted file mode 100644 index f8b63f3c3375..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallynestedintry_30_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallynestedintry_30_do.csproj b/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallynestedintry_30_do.csproj deleted file mode 100644 index ed0127d3aca6..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallynestedintry_30_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallynestedintry_30_r.csproj b/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallynestedintry_30_r.csproj deleted file mode 100644 index accf2ebc5e6b..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallynestedintry_30_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallynestedintry_30_ro.csproj b/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallynestedintry_30_ro.csproj deleted file mode 100644 index de4b97b26798..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallynestedintry_30_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallyrecursive_20_d.csproj b/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallyrecursive_20_d.csproj deleted file mode 100644 index ce5b96f21483..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallyrecursive_20_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallyrecursive_20_do.csproj b/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallyrecursive_20_do.csproj deleted file mode 100644 index 345d19936c46..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallyrecursive_20_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallyrecursive_20_r.csproj b/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallyrecursive_20_r.csproj deleted file mode 100644 index 4cc7f8838b63..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallyrecursive_20_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallyrecursive_20_ro.csproj b/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallyrecursive_20_ro.csproj deleted file mode 100644 index 013ce9153842..000000000000 --- a/src/tests/JIT/Methodical/eh/nested/nonlocalexit/throwinfinallyrecursive_20_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/regress/asurt/122239/outermostFinally.csproj b/src/tests/JIT/Methodical/eh/regress/asurt/122239/outermostFinally.csproj deleted file mode 100644 index 717f9fa50a87..000000000000 --- a/src/tests/JIT/Methodical/eh/regress/asurt/122239/outermostFinally.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - PdbOnly - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/regress/asurt/140713/innerFinally_d.csproj b/src/tests/JIT/Methodical/eh/regress/asurt/140713/innerFinally_d.csproj deleted file mode 100644 index e8d9c4906ba9..000000000000 --- a/src/tests/JIT/Methodical/eh/regress/asurt/140713/innerFinally_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/regress/asurt/140713/innerFinally_do.csproj b/src/tests/JIT/Methodical/eh/regress/asurt/140713/innerFinally_do.csproj deleted file mode 100644 index e9e30520b14e..000000000000 --- a/src/tests/JIT/Methodical/eh/regress/asurt/140713/innerFinally_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/regress/asurt/140713/innerFinally_r.csproj b/src/tests/JIT/Methodical/eh/regress/asurt/140713/innerFinally_r.csproj deleted file mode 100644 index 921b5e4b12df..000000000000 --- a/src/tests/JIT/Methodical/eh/regress/asurt/140713/innerFinally_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/regress/asurt/140713/innerFinally_ro.csproj b/src/tests/JIT/Methodical/eh/regress/asurt/140713/innerFinally_ro.csproj deleted file mode 100644 index e62c47ceaf1a..000000000000 --- a/src/tests/JIT/Methodical/eh/regress/asurt/140713/innerFinally_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException.cs b/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException.cs index c339bf532639..810023a4f679 100644 --- a/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException.cs +++ b/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException.cs @@ -32,6 +32,7 @@ static Class1() testLog = new TestUtil.TestLog(expectedOut); } [Fact] + [OuterLoop] public static int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException_d.csproj b/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException_d.csproj deleted file mode 100644 index a65b43bf723d..000000000000 --- a/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException_do.csproj b/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException_do.csproj deleted file mode 100644 index 39f3b0e075a0..000000000000 --- a/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException_r.csproj b/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException_r.csproj deleted file mode 100644 index 4a1983488dd5..000000000000 --- a/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException_ro.csproj b/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException_ro.csproj deleted file mode 100644 index aa87b35910fb..000000000000 --- a/src/tests/JIT/Methodical/eh/regress/asurt/141358/uncaughtException_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/regress/vswhidbey/148190/baduwinfo.cs b/src/tests/JIT/Methodical/eh/regress/vswhidbey/148190/baduwinfo.cs index 2474c759d51d..7c289c917c88 100644 --- a/src/tests/JIT/Methodical/eh/regress/vswhidbey/148190/baduwinfo.cs +++ b/src/tests/JIT/Methodical/eh/regress/vswhidbey/148190/baduwinfo.cs @@ -115,6 +115,7 @@ public static int foo() return ret; } [Fact] + [OuterLoop] public static int TestEntryPoint() { String s = "Test1"; diff --git a/src/tests/JIT/Methodical/eh/regress/vswhidbey/148190/baduwinfo.csproj b/src/tests/JIT/Methodical/eh/regress/vswhidbey/148190/baduwinfo.csproj deleted file mode 100644 index af9b7952114b..000000000000 --- a/src/tests/JIT/Methodical/eh/regress/vswhidbey/148190/baduwinfo.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - PdbOnly - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/regress/vswhidbey/148190/baduwinfo1.cs b/src/tests/JIT/Methodical/eh/regress/vswhidbey/148190/baduwinfo1.cs index 6a0084ee14d1..1fd932bcd411 100644 --- a/src/tests/JIT/Methodical/eh/regress/vswhidbey/148190/baduwinfo1.cs +++ b/src/tests/JIT/Methodical/eh/regress/vswhidbey/148190/baduwinfo1.cs @@ -117,6 +117,7 @@ public static int foo() return ret; } [Fact] + [OuterLoop] public static int TestEntryPoint() { String s = "Test1"; diff --git a/src/tests/JIT/Methodical/eh/regress/vswhidbey/148190/baduwinfo1.csproj b/src/tests/JIT/Methodical/eh/regress/vswhidbey/148190/baduwinfo1.csproj deleted file mode 100644 index 036aa8edf351..000000000000 --- a/src/tests/JIT/Methodical/eh/regress/vswhidbey/148190/baduwinfo1.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - PdbOnly - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch.cs b/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch.cs index d72d20e38549..f8c185fa0d66 100644 --- a/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch.cs +++ b/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch.cs @@ -38,6 +38,7 @@ static Class1() } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch_d.csproj b/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch_d.csproj deleted file mode 100644 index b88274eb54f5..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch_do.csproj b/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch_do.csproj deleted file mode 100644 index 665739ceaa92..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch_r.csproj b/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch_r.csproj deleted file mode 100644 index fe7b54ff248d..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch_ro.csproj b/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch_ro.csproj deleted file mode 100644 index f738fd05b19e..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/rethrowinfinallyaftercatch_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase.cs b/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase.cs index 6d2cc12b62a1..569064505755 100644 --- a/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase.cs +++ b/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase.cs @@ -57,6 +57,7 @@ static public void f1() } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase_d.csproj b/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase_d.csproj deleted file mode 100644 index c3eb3550c607..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase_do.csproj b/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase_do.csproj deleted file mode 100644 index 7563bf06f8d2..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase_r.csproj b/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase_r.csproj deleted file mode 100644 index 084478d7d53b..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase_ro.csproj b/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase_ro.csproj deleted file mode 100644 index 9e2a05c80511..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/rethrowwithhandlerscatchingbase_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/samerethrowtwice_d.csproj b/src/tests/JIT/Methodical/eh/rethrow/samerethrowtwice_d.csproj deleted file mode 100644 index 9d1b39495541..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/samerethrowtwice_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/samerethrowtwice_do.csproj b/src/tests/JIT/Methodical/eh/rethrow/samerethrowtwice_do.csproj deleted file mode 100644 index 390b3486700e..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/samerethrowtwice_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/samerethrowtwice_r.csproj b/src/tests/JIT/Methodical/eh/rethrow/samerethrowtwice_r.csproj deleted file mode 100644 index f36fc5b40f08..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/samerethrowtwice_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/samerethrowtwice_ro.csproj b/src/tests/JIT/Methodical/eh/rethrow/samerethrowtwice_ro.csproj deleted file mode 100644 index 6c3bde65d413..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/samerethrowtwice_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/samethrowtwice_d.csproj b/src/tests/JIT/Methodical/eh/rethrow/samethrowtwice_d.csproj deleted file mode 100644 index ab67f7e2ad67..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/samethrowtwice_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/samethrowtwice_do.csproj b/src/tests/JIT/Methodical/eh/rethrow/samethrowtwice_do.csproj deleted file mode 100644 index 002bd582ade7..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/samethrowtwice_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/samethrowtwice_r.csproj b/src/tests/JIT/Methodical/eh/rethrow/samethrowtwice_r.csproj deleted file mode 100644 index 67893f2e098d..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/samethrowtwice_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/samethrowtwice_ro.csproj b/src/tests/JIT/Methodical/eh/rethrow/samethrowtwice_ro.csproj deleted file mode 100644 index 28c0828b1c8b..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/samethrowtwice_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/simplerethrow.cs b/src/tests/JIT/Methodical/eh/rethrow/simplerethrow.cs index 4b6c489ae001..09c9bd8aa261 100644 --- a/src/tests/JIT/Methodical/eh/rethrow/simplerethrow.cs +++ b/src/tests/JIT/Methodical/eh/rethrow/simplerethrow.cs @@ -28,6 +28,7 @@ static Class1() } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/rethrow/simplerethrow_d.csproj b/src/tests/JIT/Methodical/eh/rethrow/simplerethrow_d.csproj deleted file mode 100644 index 358201ae77b6..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/simplerethrow_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/simplerethrow_do.csproj b/src/tests/JIT/Methodical/eh/rethrow/simplerethrow_do.csproj deleted file mode 100644 index 3aca83edab53..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/simplerethrow_do.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/simplerethrow_r.csproj b/src/tests/JIT/Methodical/eh/rethrow/simplerethrow_r.csproj deleted file mode 100644 index aee5d009d1d8..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/simplerethrow_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/simplerethrow_ro.csproj b/src/tests/JIT/Methodical/eh/rethrow/simplerethrow_ro.csproj deleted file mode 100644 index 8d929e4cdda2..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/simplerethrow_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase.cs b/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase.cs index 6efe9d6d45d1..d6fbf7f4cc8d 100644 --- a/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase.cs +++ b/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase.cs @@ -57,6 +57,7 @@ static public void f1() } [Fact] + [OuterLoop] static public int TestEntryPoint() { //Start recording diff --git a/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase_d.csproj b/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase_d.csproj deleted file mode 100644 index b630e295ffd9..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - Full - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase_do.csproj b/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase_do.csproj deleted file mode 100644 index bf810c63f054..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Full - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase_r.csproj b/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase_r.csproj deleted file mode 100644 index 8c4e4b8caab5..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase_ro.csproj b/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase_ro.csproj deleted file mode 100644 index f3a963c40265..000000000000 --- a/src/tests/JIT/Methodical/eh/rethrow/throwwithhandlerscatchingbase_ro.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - None - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_c.cs b/src/tests/JIT/Methodical/explicit/basic/refarg_c.cs index 67ea0f5c8b09..95651bd6e2d5 100644 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_c.cs +++ b/src/tests/JIT/Methodical/explicit/basic/refarg_c.cs @@ -53,6 +53,7 @@ private static void Test(ref char n) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Test(ref s_aa.mm); diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_c_d.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_c_d.csproj deleted file mode 100644 index 24f4c6e893c1..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_c_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_c_do.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_c_do.csproj deleted file mode 100644 index 284da49dad38..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_c_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_c_r.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_c_r.csproj deleted file mode 100644 index c0fa5ad9dac9..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_c_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_c_ro.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_c_ro.csproj deleted file mode 100644 index a304f8aa4f59..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_c_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_f4.cs b/src/tests/JIT/Methodical/explicit/basic/refarg_f4.cs index 8d4d65fb4927..929b0f7a7866 100644 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_f4.cs +++ b/src/tests/JIT/Methodical/explicit/basic/refarg_f4.cs @@ -69,6 +69,7 @@ private static int Test(ref float n) } [Fact] + [OuterLoop] public static int TestEntryPoint() { int exitCode = Test(ref s_aa.mm2); diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_f4_d.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_f4_d.csproj deleted file mode 100644 index f2f97691b245..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_f4_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_f4_do.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_f4_do.csproj deleted file mode 100644 index ba4eefcee8af..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_f4_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_f4_r.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_f4_r.csproj deleted file mode 100644 index b44fb3ee8f98..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_f4_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_f4_ro.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_f4_ro.csproj deleted file mode 100644 index f6158b8a7a02..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_f4_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_f8_d.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_f8_d.csproj deleted file mode 100644 index 559d32043f72..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_f8_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_f8_do.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_f8_do.csproj deleted file mode 100644 index d13b8a9aeb3e..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_f8_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_f8_r.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_f8_r.csproj deleted file mode 100644 index b58207a52899..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_f8_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_f8_ro.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_f8_ro.csproj deleted file mode 100644 index 7fe74efd8f9e..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_f8_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i1.cs b/src/tests/JIT/Methodical/explicit/basic/refarg_i1.cs index 0bee189efbd8..e7e07f4bcfbf 100644 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i1.cs +++ b/src/tests/JIT/Methodical/explicit/basic/refarg_i1.cs @@ -30,7 +30,6 @@ internal class AA catch (NullReferenceException) { App.exitCode = 100; - Console.WriteLine("NullReferenceException caught in Finalizer as expected"); } } } @@ -59,6 +58,7 @@ private static void Test(ref byte n) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Test(ref s_aa.mm); diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i1_d.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_i1_d.csproj deleted file mode 100644 index 1d983ccc5a3e..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i1_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - true - true - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i1_do.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_i1_do.csproj deleted file mode 100644 index 2e3da1c5eb48..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i1_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i1_r.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_i1_r.csproj deleted file mode 100644 index 13014101cd86..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i1_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - true - true - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i1_ro.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_i1_ro.csproj deleted file mode 100644 index d01aef2a6148..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i1_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i2.cs b/src/tests/JIT/Methodical/explicit/basic/refarg_i2.cs index 16b3cdd2c36c..fae50e12dc1c 100644 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i2.cs +++ b/src/tests/JIT/Methodical/explicit/basic/refarg_i2.cs @@ -52,6 +52,7 @@ private static void Test(ref short n) } [Fact] + [OuterLoop] public static int TestEntryPoint() { s_aa.self = new AA(); diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i2_d.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_i2_d.csproj deleted file mode 100644 index a1e736606de6..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i2_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i2_do.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_i2_do.csproj deleted file mode 100644 index b428daedfae3..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i2_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i2_r.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_i2_r.csproj deleted file mode 100644 index 60b1e35c3add..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i2_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i2_ro.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_i2_ro.csproj deleted file mode 100644 index c0f53b3c4157..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i2_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i4.cs b/src/tests/JIT/Methodical/explicit/basic/refarg_i4.cs index 111987f7ea91..ddee848b7378 100644 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i4.cs +++ b/src/tests/JIT/Methodical/explicit/basic/refarg_i4.cs @@ -70,6 +70,7 @@ private static void Test(ref int n) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Test(ref s_aa.mm); diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i4_d.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_i4_d.csproj deleted file mode 100644 index 0b161a7279ec..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i4_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i4_do.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_i4_do.csproj deleted file mode 100644 index 2d6319ea55cd..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i4_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i4_r.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_i4_r.csproj deleted file mode 100644 index 38bed42672f4..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i4_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_i4_ro.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_i4_ro.csproj deleted file mode 100644 index 9b2608bda9b7..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_i4_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_o.cs b/src/tests/JIT/Methodical/explicit/basic/refarg_o.cs index 89a517f7581b..9b39a41e662d 100644 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_o.cs +++ b/src/tests/JIT/Methodical/explicit/basic/refarg_o.cs @@ -52,6 +52,7 @@ private static int Test(ref AA aa) } [Fact] + [OuterLoop] public static int TestEntryPoint() { int exitCode = Test(ref s_aa.m_aa); diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_o_d.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_o_d.csproj deleted file mode 100644 index d78761563e60..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_o_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_o_do.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_o_do.csproj deleted file mode 100644 index a8a341bf0175..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_o_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_o_r.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_o_r.csproj deleted file mode 100644 index 2db4222c1b31..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_o_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_o_ro.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_o_ro.csproj deleted file mode 100644 index 4f5897929c95..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_o_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_s.cs b/src/tests/JIT/Methodical/explicit/basic/refarg_s.cs index e3c76c7f1b9b..861826e3f43b 100644 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_s.cs +++ b/src/tests/JIT/Methodical/explicit/basic/refarg_s.cs @@ -52,6 +52,7 @@ private static int Test(ref String n) } [Fact] + [OuterLoop] public static int TestEntryPoint() { int exitCode = Test(ref s_aa.mm); diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_s_d.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_s_d.csproj deleted file mode 100644 index 6bfb64896286..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_s_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - true - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_s_do.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_s_do.csproj deleted file mode 100644 index 7387a109b89e..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_s_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_s_r.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_s_r.csproj deleted file mode 100644 index a699cae60f64..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_s_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/basic/refarg_s_ro.csproj b/src/tests/JIT/Methodical/explicit/basic/refarg_s_ro.csproj deleted file mode 100644 index d187415fffc1..000000000000 --- a/src/tests/JIT/Methodical/explicit/basic/refarg_s_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - true - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/coverage/expl_double_1.cs b/src/tests/JIT/Methodical/explicit/coverage/expl_double_1.cs index 4d1dcfb2b266..41698780746d 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/expl_double_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/expl_double_1.cs @@ -71,6 +71,7 @@ internal struct BB public static class Test_expl_double_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/expl_float_1.cs b/src/tests/JIT/Methodical/explicit/coverage/expl_float_1.cs index fd40bb671dd5..140a8c09d205 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/expl_float_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/expl_float_1.cs @@ -71,6 +71,7 @@ internal struct BB public static class Test_expl_float_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/expl_gc_double_1.cs b/src/tests/JIT/Methodical/explicit/coverage/expl_gc_double_1.cs index 4340a506bc44..c742828dca0b 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/expl_gc_double_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/expl_gc_double_1.cs @@ -80,6 +80,7 @@ internal struct BB public static class Test_expl_gc_double_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/expl_gc_float_1.cs b/src/tests/JIT/Methodical/explicit/coverage/expl_gc_float_1.cs index 5f9070e6c4fd..f1f8e1affccc 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/expl_gc_float_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/expl_gc_float_1.cs @@ -83,6 +83,7 @@ internal struct BB public static class Test_expl_gc_float_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/expl_gc_int_1.cs b/src/tests/JIT/Methodical/explicit/coverage/expl_gc_int_1.cs index 38cb7135f3bb..74825d816e04 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/expl_gc_int_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/expl_gc_int_1.cs @@ -74,6 +74,7 @@ internal struct BB public static class Test_expl_gc_int_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/expl_gc_long_1.cs b/src/tests/JIT/Methodical/explicit/coverage/expl_gc_long_1.cs index fdd413190004..5c4fd4f547cd 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/expl_gc_long_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/expl_gc_long_1.cs @@ -71,6 +71,7 @@ internal struct BB public static class Test_expl_gc_long_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/expl_gc_obj_1.cs b/src/tests/JIT/Methodical/explicit/coverage/expl_gc_obj_1.cs index 8c349930f637..7452db41a8dc 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/expl_gc_obj_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/expl_gc_obj_1.cs @@ -78,6 +78,7 @@ internal struct BB public static class Test_expl_gc_obj_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/expl_gc_short_1.cs b/src/tests/JIT/Methodical/explicit/coverage/expl_gc_short_1.cs index ac765a840a06..2bf91c5369fc 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/expl_gc_short_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/expl_gc_short_1.cs @@ -80,6 +80,7 @@ internal struct BB public static class Test_expl_gc_short_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/expl_gc_val_1.cs b/src/tests/JIT/Methodical/explicit/coverage/expl_gc_val_1.cs index 884617e275b4..c956c9cba512 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/expl_gc_val_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/expl_gc_val_1.cs @@ -87,6 +87,7 @@ internal struct BB public static class Test_expl_gc_val_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/expl_int_1.cs b/src/tests/JIT/Methodical/explicit/coverage/expl_int_1.cs index 9d98877a125d..d4f05e94ca87 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/expl_int_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/expl_int_1.cs @@ -80,6 +80,7 @@ internal struct BB public static class Test_expl_int_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/expl_long_1.cs b/src/tests/JIT/Methodical/explicit/coverage/expl_long_1.cs index 068609bbd90f..3a402de33596 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/expl_long_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/expl_long_1.cs @@ -83,6 +83,7 @@ internal struct BB public static class Test_expl_long_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/expl_obj_1.cs b/src/tests/JIT/Methodical/explicit/coverage/expl_obj_1.cs index c1dedb69238a..1421cf801c47 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/expl_obj_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/expl_obj_1.cs @@ -87,6 +87,7 @@ internal struct BB public static class Test_expl_obj_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/expl_short_1.cs b/src/tests/JIT/Methodical/explicit/coverage/expl_short_1.cs index 7caa6d529e85..33b13bacba75 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/expl_short_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/expl_short_1.cs @@ -74,6 +74,7 @@ internal struct BB public static class Test_expl_short_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/expl_val_1.cs b/src/tests/JIT/Methodical/explicit/coverage/expl_val_1.cs index e86822189307..e7d5f4953c29 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/expl_val_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/expl_val_1.cs @@ -87,6 +87,7 @@ internal struct BB public static class Test_expl_val_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/seq_double_1.cs b/src/tests/JIT/Methodical/explicit/coverage/seq_double_1.cs index 25e5206cb736..fcc0b400771a 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/seq_double_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/seq_double_1.cs @@ -70,6 +70,7 @@ internal struct BB public static class Test_seq_double_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/seq_float_1.cs b/src/tests/JIT/Methodical/explicit/coverage/seq_float_1.cs index d34d388ddce2..9c26fe9c0d71 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/seq_float_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/seq_float_1.cs @@ -70,6 +70,7 @@ internal struct BB public static class Test_seq_float_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/seq_gc_double_1.cs b/src/tests/JIT/Methodical/explicit/coverage/seq_gc_double_1.cs index 9d1280b0a5f6..0979521cd90e 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/seq_gc_double_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/seq_gc_double_1.cs @@ -79,6 +79,7 @@ internal struct BB public static class Test_seq_gc_double_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/seq_gc_float_1.cs b/src/tests/JIT/Methodical/explicit/coverage/seq_gc_float_1.cs index 39111bb0dfd8..77f3683535d0 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/seq_gc_float_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/seq_gc_float_1.cs @@ -82,6 +82,7 @@ internal struct BB public static class Test_seq_gc_float_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/seq_gc_int_1.cs b/src/tests/JIT/Methodical/explicit/coverage/seq_gc_int_1.cs index fdd0899ba15d..294987f85ff1 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/seq_gc_int_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/seq_gc_int_1.cs @@ -73,6 +73,7 @@ internal struct BB public static class Test_seq_gc_int_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/seq_gc_long_1.cs b/src/tests/JIT/Methodical/explicit/coverage/seq_gc_long_1.cs index 4ea49126a396..22f30a892955 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/seq_gc_long_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/seq_gc_long_1.cs @@ -70,6 +70,7 @@ internal struct BB public static class Test_seq_gc_long_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/seq_gc_obj_1.cs b/src/tests/JIT/Methodical/explicit/coverage/seq_gc_obj_1.cs index 64d92a073392..6bd20185c9bb 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/seq_gc_obj_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/seq_gc_obj_1.cs @@ -78,6 +78,7 @@ internal struct BB public static class Test_seq_gc_obj_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/seq_gc_short_1.cs b/src/tests/JIT/Methodical/explicit/coverage/seq_gc_short_1.cs index 73783c84a646..995c3f635841 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/seq_gc_short_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/seq_gc_short_1.cs @@ -80,6 +80,7 @@ internal struct BB public static class Test_seq_gc_short_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/seq_gc_val_1.cs b/src/tests/JIT/Methodical/explicit/coverage/seq_gc_val_1.cs index 5b4225eff018..1d46d3380ced 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/seq_gc_val_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/seq_gc_val_1.cs @@ -87,6 +87,7 @@ internal struct BB public static class Test_seq_gc_val_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/seq_int_1.cs b/src/tests/JIT/Methodical/explicit/coverage/seq_int_1.cs index 90eb07e50a34..dd801587a266 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/seq_int_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/seq_int_1.cs @@ -79,6 +79,7 @@ internal struct BB public static class Test_seq_int_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/seq_long_1.cs b/src/tests/JIT/Methodical/explicit/coverage/seq_long_1.cs index 424364c1a123..8f96a621f983 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/seq_long_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/seq_long_1.cs @@ -82,6 +82,7 @@ internal struct BB public static class Test_seq_long_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/seq_obj_1.cs b/src/tests/JIT/Methodical/explicit/coverage/seq_obj_1.cs index 64bde845f93c..93a5a8b0e949 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/seq_obj_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/seq_obj_1.cs @@ -87,6 +87,7 @@ internal struct BB public static class Test_seq_obj_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/seq_short_1.cs b/src/tests/JIT/Methodical/explicit/coverage/seq_short_1.cs index 103612dca851..a8c7d2261c57 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/seq_short_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/seq_short_1.cs @@ -74,6 +74,7 @@ internal struct BB public static class Test_seq_short_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/coverage/seq_val_1.cs b/src/tests/JIT/Methodical/explicit/coverage/seq_val_1.cs index 3d8154ba8630..c54f2b1ef8c9 100644 --- a/src/tests/JIT/Methodical/explicit/coverage/seq_val_1.cs +++ b/src/tests/JIT/Methodical/explicit/coverage/seq_val_1.cs @@ -78,6 +78,7 @@ internal struct BB public static class Test_seq_val_1 { [Fact] + [OuterLoop] public static int TestEntrypoint() { return TestApp.RunAllTests(); diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit1_d.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit1_d.csproj deleted file mode 100644 index f9097d4b49fb..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit1_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit1_do.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit1_do.csproj deleted file mode 100644 index 3f3d3dc61780..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit1_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit1_r.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit1_r.csproj deleted file mode 100644 index d0d17889226b..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit1_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit1_ro.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit1_ro.csproj deleted file mode 100644 index 1e0ed5e8130b..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit1_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit2_d.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit2_d.csproj deleted file mode 100644 index d91f51a2e7dd..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit2_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit2_do.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit2_do.csproj deleted file mode 100644 index 347a5254e23a..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit2_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit2_r.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit2_r.csproj deleted file mode 100644 index 017f5c5ff124..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit2_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit2_ro.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit2_ro.csproj deleted file mode 100644 index e3a44567f8cb..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit2_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit3_d.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit3_d.csproj deleted file mode 100644 index 381658397062..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit3_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit3_do.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit3_do.csproj deleted file mode 100644 index 6d7831aae12e..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit3_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit3_r.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit3_r.csproj deleted file mode 100644 index 9e572b9d402f..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit3_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit3_ro.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit3_ro.csproj deleted file mode 100644 index e94c36f5d3e4..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit3_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit4_d.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit4_d.csproj deleted file mode 100644 index 9e1697edef4e..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit4_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit4_do.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit4_do.csproj deleted file mode 100644 index 2cad15eccdd6..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit4_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit4_r.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit4_r.csproj deleted file mode 100644 index cd1067cae3a1..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit4_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit4_ro.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit4_ro.csproj deleted file mode 100644 index f865b0451567..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit4_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit5_d.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit5_d.csproj deleted file mode 100644 index 36dc02082f03..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit5_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit5_do.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit5_do.csproj deleted file mode 100644 index 290ccefde92f..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit5_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit5_r.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit5_r.csproj deleted file mode 100644 index 0b9305335d02..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit5_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit5_ro.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit5_ro.csproj deleted file mode 100644 index fd86f3f92494..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit5_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit6_d.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit6_d.csproj deleted file mode 100644 index ef0377f05c9b..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit6_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit6_do.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit6_do.csproj deleted file mode 100644 index ef9862dd5fb8..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit6_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit6_r.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit6_r.csproj deleted file mode 100644 index f5b9d82ccaba..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit6_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit6_ro.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit6_ro.csproj deleted file mode 100644 index de07fb25bca9..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit6_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit7_d.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit7_d.csproj deleted file mode 100644 index 8434ad089dab..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit7_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit7_do.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit7_do.csproj deleted file mode 100644 index e795c69b56e8..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit7_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit7_r.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit7_r.csproj deleted file mode 100644 index 985b9f8805b9..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit7_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit7_ro.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit7_ro.csproj deleted file mode 100644 index 1ea54e73f429..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit7_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit8_d.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit8_d.csproj deleted file mode 100644 index aedca7f8e72f..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit8_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit8_do.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit8_do.csproj deleted file mode 100644 index 7416db95567b..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit8_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit8_r.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit8_r.csproj deleted file mode 100644 index 60e98944c29b..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit8_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/misc/explicit8_ro.csproj b/src/tests/JIT/Methodical/explicit/misc/explicit8_ro.csproj deleted file mode 100644 index d00676f7fe1c..000000000000 --- a/src/tests/JIT/Methodical/explicit/misc/explicit8_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_double_d.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_double_d.csproj deleted file mode 100644 index eb7b446fa3db..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_double_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_double_do.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_double_do.csproj deleted file mode 100644 index 09818390bf48..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_double_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_double_r.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_double_r.csproj deleted file mode 100644 index f07504b12d02..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_double_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_double_ro.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_double_ro.csproj deleted file mode 100644 index 07995eb9ad0c..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_double_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_float_d.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_float_d.csproj deleted file mode 100644 index 007778b47ff6..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_float_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_float_do.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_float_do.csproj deleted file mode 100644 index 1b5d2cd0b922..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_float_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_float_r.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_float_r.csproj deleted file mode 100644 index f02ecdccb6f9..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_float_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_float_ro.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_float_ro.csproj deleted file mode 100644 index 99253bd77243..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_float_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_objref_d.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_objref_d.csproj deleted file mode 100644 index 5de9202db680..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_objref_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_objref_do.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_objref_do.csproj deleted file mode 100644 index f96b5bf64a63..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_objref_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_objref_r.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_objref_r.csproj deleted file mode 100644 index 3ba0389419f1..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_objref_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_objref_ro.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_objref_ro.csproj deleted file mode 100644 index 5066a3f95356..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_objref_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_valref_d.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_valref_d.csproj deleted file mode 100644 index d79b42dd81b3..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_valref_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_valref_do.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_valref_do.csproj deleted file mode 100644 index 892ca77b1243..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_valref_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_valref_r.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_valref_r.csproj deleted file mode 100644 index 8c88033b5dbe..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_valref_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/explicit/rotate/rotarg_valref_ro.csproj b/src/tests/JIT/Methodical/explicit/rotate/rotarg_valref_ro.csproj deleted file mode 100644 index 5a6ce47268a6..000000000000 --- a/src/tests/JIT/Methodical/explicit/rotate/rotarg_valref_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/bug614098/intToByte.cs b/src/tests/JIT/Methodical/flowgraph/bug614098/intToByte.cs index e5a2003cdd0b..dbaa8b6caee6 100644 --- a/src/tests/JIT/Methodical/flowgraph/bug614098/intToByte.cs +++ b/src/tests/JIT/Methodical/flowgraph/bug614098/intToByte.cs @@ -35,6 +35,7 @@ public MyStruct(ushort value) static private MyStruct[] s_myObjects = { new MyStruct(0x0100) }; [Fact] + [OuterLoop] public static int TestEntryPoint() { MyStruct obj = s_myObjects[0]; diff --git a/src/tests/JIT/Methodical/flowgraph/bug614098/intToByte.csproj b/src/tests/JIT/Methodical/flowgraph/bug614098/intToByte.csproj deleted file mode 100644 index 1061232386ae..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/bug614098/intToByte.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/bug619534/ehCodeMotion.csproj b/src/tests/JIT/Methodical/flowgraph/bug619534/ehCodeMotion.csproj deleted file mode 100644 index f8e997fee587..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/bug619534/ehCodeMotion.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/bug619534/finallyclone.cs b/src/tests/JIT/Methodical/flowgraph/bug619534/finallyclone.cs index cecbfd066a40..26713fb5dacb 100644 --- a/src/tests/JIT/Methodical/flowgraph/bug619534/finallyclone.cs +++ b/src/tests/JIT/Methodical/flowgraph/bug619534/finallyclone.cs @@ -5,9 +5,9 @@ * Problem: There were no SSA edges added for cloned finally blocks. A finally block is cloned if there is an EH, switch or throw within it. This implied bad codegen as described in the customer scenario below. The call to Console.WriteLine changes code movement around the call and so the issue appears to go away but the Console.WriteLine is not really related. * * Solution: Add an OPONERROR edge around the summary OPSIDEEFFECT tuples to show that they are conditional. - * + * * Customer Scenario: We seem to be hitting this strange bug (see repro code). If there is a try/catch statement in the finally block, the Test() method returns false, even if this should be impossible. Uncommenting the Console.WriteLine in the try block suddenly makes the test pass. Note that there is only one place where shouldFail becomes true. We tried this on an x86 machine, and the test always returns what we expected (true), we also get the correct result on VS2008, so the bug seems to be only on x64 builds. - * + * * */ using System; @@ -20,6 +20,7 @@ class ApplicationException : Exception { } public class TestClass { [Fact] + [OuterLoop] public static int TestEntryPoint() { //this should return true; diff --git a/src/tests/JIT/Methodical/flowgraph/bug619534/finallyclone.csproj b/src/tests/JIT/Methodical/flowgraph/bug619534/finallyclone.csproj deleted file mode 100644 index 281cbe5cc0a4..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/bug619534/finallyclone.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/bug619534/moduleHandleCache.csproj b/src/tests/JIT/Methodical/flowgraph/bug619534/moduleHandleCache.csproj deleted file mode 100644 index 1eae335a9713..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/bug619534/moduleHandleCache.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - PdbOnly - False - - - - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/bug619534/moduleLibrary.csproj b/src/tests/JIT/Methodical/flowgraph/bug619534/moduleLibrary.csproj deleted file mode 100644 index ecbc2704d760..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/bug619534/moduleLibrary.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - Library - - - - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/bug619534/twoEndFinallys.cs b/src/tests/JIT/Methodical/flowgraph/bug619534/twoEndFinallys.cs index 61f516867f57..06c6a7e28ef0 100644 --- a/src/tests/JIT/Methodical/flowgraph/bug619534/twoEndFinallys.cs +++ b/src/tests/JIT/Methodical/flowgraph/bug619534/twoEndFinallys.cs @@ -32,9 +32,10 @@ private Test() } [Fact] + [OuterLoop] public static int TestEntryPoint() { - Test t = TwoEndFinallys(new string[] {}); + Test t = TwoEndFinallys(new string[] { }); if (t._temp == 101) return 100; else return 101; diff --git a/src/tests/JIT/Methodical/flowgraph/bug619534/twoEndFinallys.csproj b/src/tests/JIT/Methodical/flowgraph/bug619534/twoEndFinallys.csproj deleted file mode 100644 index 5e399e6677fa..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/bug619534/twoEndFinallys.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/bug621705/ptuple_lost.cs b/src/tests/JIT/Methodical/flowgraph/bug621705/ptuple_lost.cs index 58b13c5d2d85..c74cb75c7cd4 100644 --- a/src/tests/JIT/Methodical/flowgraph/bug621705/ptuple_lost.cs +++ b/src/tests/JIT/Methodical/flowgraph/bug621705/ptuple_lost.cs @@ -8,6 +8,7 @@ namespace Test_ptuple_lost public class A { [Fact] + [OuterLoop] public static int TestEntryPoint() { int[] arr = new int[10]; diff --git a/src/tests/JIT/Methodical/flowgraph/bug621705/ptuple_lost.csproj b/src/tests/JIT/Methodical/flowgraph/bug621705/ptuple_lost.csproj deleted file mode 100644 index 4a486c5df78e..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/bug621705/ptuple_lost.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/bug647189/ssa_tuIsAddr.cs b/src/tests/JIT/Methodical/flowgraph/bug647189/ssa_tuIsAddr.cs index 0b85290af7c4..7a92a79dbab5 100644 --- a/src/tests/JIT/Methodical/flowgraph/bug647189/ssa_tuIsAddr.cs +++ b/src/tests/JIT/Methodical/flowgraph/bug647189/ssa_tuIsAddr.cs @@ -2,10 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. /* - * The SSA phase isn't counting TU_ISADDR leafs when determining how many hash nodes to allocate. - * The repro can be generated as: - * Basically a lot of static field direct accesses with nothing else in the methods. - */ +* The SSA phase isn't counting TU_ISADDR leafs when determining how many hash nodes to allocate. +* The repro can be generated as: +* Basically a lot of static field direct accesses with nothing else in the methods. +*/ using System; using Xunit; @@ -76,6 +76,7 @@ public class Repro private static int s_field59 = 59; [Fact] + [OuterLoop] public static int TestEntryPoint() { s_field0 = 2; diff --git a/src/tests/JIT/Methodical/flowgraph/bug647189/ssa_tuIsAddr.csproj b/src/tests/JIT/Methodical/flowgraph/bug647189/ssa_tuIsAddr.csproj deleted file mode 100644 index 8dd28e3c1ae5..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/bug647189/ssa_tuIsAddr.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug675304/arrayDim.cs b/src/tests/JIT/Methodical/flowgraph/dev10_bug675304/arrayDim.cs index 604eaeffa41f..d2a7a304cc33 100644 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug675304/arrayDim.cs +++ b/src/tests/JIT/Methodical/flowgraph/dev10_bug675304/arrayDim.cs @@ -12,6 +12,7 @@ public class Test_arrayDim { [Fact] + [OuterLoop] public static void TestEntryPoint() { int[] iAr1 = null; diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug675304/arrayDim.csproj b/src/tests/JIT/Methodical/flowgraph/dev10_bug675304/arrayDim.csproj deleted file mode 100644 index def6c0b98d78..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug675304/arrayDim.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug675304/osrAddovershot.cs b/src/tests/JIT/Methodical/flowgraph/dev10_bug675304/osrAddovershot.cs index b33a619dcf23..5e41f429902a 100644 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug675304/osrAddovershot.cs +++ b/src/tests/JIT/Methodical/flowgraph/dev10_bug675304/osrAddovershot.cs @@ -15,11 +15,11 @@ // - multiply by a positive constant // - add/subtract when the initial IV is known to be >= 0 // - add a value smaller than pointer size (to avoid a value off the end of an array) <-- This last check was missing and hence the bug!!!!! -// -// Problem: The JIT seems to be rewriting the IV and the loop test in terms of the struct member, which is not safe because the member is more than pointer size past the end of the array. -// -// Fix: Stop OSR from rewriting IV's when the ADD is greater than pointer size. Need to further beat down OSR to have it stop rewriting IVs when they would be offset more than pointer-sized past the end of an array or object. -// +// +// Problem: The JIT seems to be rewriting the IV and the loop test in terms of the struct member, which is not safe because the member is more than pointer size past the end of the array. +// +// Fix: Stop OSR from rewriting IV's when the ADD is greater than pointer size. Need to further beat down OSR to have it stop rewriting IVs when they would be offset more than pointer-sized past the end of an array or object. +// // PLEASE NOTE: You have to set DOTNET_GCSTRESS=4 to see the AV. using System; @@ -40,7 +40,7 @@ private static int SumMSH(MyStruct[] ms) for (int i = 0; i < ms.Length; i++) { sum += ms[i].h; //Gives an AV - //sum += ms[i].b; //will not give an AV since offset is less than 8 bytes. + //sum += ms[i].b; //will not give an AV since offset is less than 8 bytes. } return sum; } @@ -63,11 +63,12 @@ private static MyStruct[] InitMS(int length) } [Fact] + [OuterLoop] public static int TestEntryPoint() { MyStruct[] ms = InitMS(5); //InitMS(args.Length > 0 ? int.Parse(args[0]) : 5); - //Do not expect to take in any arguments here for simplicity sake. - //This does not impact functionality of the repro. + //Do not expect to take in any arguments here for simplicity sake. + //This does not impact functionality of the repro. if (SumMSH(ms) == 115) return 100; else return 101; } } diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug675304/osrAddovershot.csproj b/src/tests/JIT/Methodical/flowgraph/dev10_bug675304/osrAddovershot.csproj deleted file mode 100644 index dea1e872f2de..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug675304/osrAddovershot.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/EHCopyProp.cs b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/EHCopyProp.cs index 7fcfb6381df2..13039c95d007 100644 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/EHCopyProp.cs +++ b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/EHCopyProp.cs @@ -7,6 +7,7 @@ public static class Exploit { [Fact] + [OuterLoop] public static int TestEntryPoint() { string s = "my string"; diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/EHCopyProp.csproj b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/EHCopyProp.csproj deleted file mode 100644 index 790258961e9e..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/EHCopyProp.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - - PdbOnly - True - $(NoWarn),8002 - - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/GCOverReporting.cs b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/GCOverReporting.cs index 65168181d624..66b5ff176565 100644 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/GCOverReporting.cs +++ b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/GCOverReporting.cs @@ -25,7 +25,7 @@ * 2 * 3 * and then a crash! - * + * */ using System; diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/GCOverReporting.csproj b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/GCOverReporting.csproj deleted file mode 100644 index 8a6e5b3493de..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/GCOverReporting.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - - PdbOnly - True - True - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/castClassEH.cs b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/castClassEH.cs index bf730ef07286..0fdecdf77bd9 100644 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/castClassEH.cs +++ b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/castClassEH.cs @@ -2,9 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. /* -This is a potential security exploit. -If the result of a cast is stored into a local the JIT incorrectly optimizes it such that the local gets set to the new object -reference before throwing any exception. Thus if the cast is in a try block, and the cast fails and the exception is caught, +This is a potential security exploit. +If the result of a cast is stored into a local the JIT incorrectly optimizes it such that the local gets set to the new object +reference before throwing any exception. Thus if the cast is in a try block, and the cast fails and the exception is caught, the code can still use the local as if the cast had succeeded. Fix: Use an intermediate temporary, just like for other patterns, when the cast is inside a try block. diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/castClassEH.csproj b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/castClassEH.csproj deleted file mode 100644 index 7d63fe458ca2..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/castClassEH.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/sealedCastVariance.cs b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/sealedCastVariance.cs index 19f11b2ac387..1323bf568234 100644 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/sealedCastVariance.cs +++ b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/sealedCastVariance.cs @@ -2,8 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. /* - * This is a potential security exploit. Variance allows a sealed type to be cast to/from another sealed type that is neither it's base class or derived class (which to the JIT makes it look like interfaces or other unsealed types). - */ +* This is a potential security exploit. Variance allows a sealed type to be cast to/from another sealed type that is neither it's base class or derived class (which to the JIT makes it look like interfaces or other unsealed types). +*/ using System; using Xunit; @@ -17,6 +17,7 @@ private static bool CheckType(Action a) return a.GetType() == typeof(Action); } [Fact] + [OuterLoop] public static int TestEntryPoint() { Action a = (Action)Console.WriteLine; diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/sealedCastVariance.csproj b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/sealedCastVariance.csproj deleted file mode 100644 index 3260400e738b..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/sealedCastVariance.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/singleRefField.cs b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/singleRefField.cs index 1404c521a7c2..a24922cede3d 100644 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/singleRefField.cs +++ b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/singleRefField.cs @@ -2,10 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. /* - * The JIT generates incorrect code for occasional uses of a struct parameter that contains a single field that is a reference type. - * This can cause GC holes, GC overreporting, crashes, corrupt data. - * Fix is to not undo a register allocation as worthless, but rather to just force it to spill (and not spill when the spill would be redundant). - */ +* The JIT generates incorrect code for occasional uses of a struct parameter that contains a single field that is a reference type. +* This can cause GC holes, GC overreporting, crashes, corrupt data. +* Fix is to not undo a register allocation as worthless, but rather to just force it to spill (and not spill when the spill would be redundant). +*/ using System; using System.Runtime.CompilerServices; @@ -70,6 +70,7 @@ private int Bug(MB8 mb8, string V_2) } [Fact] + [OuterLoop] public static void TestEntryPoint() { new Repro().Bug(new MB8(), "Test"); diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/singleRefField.csproj b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/singleRefField.csproj deleted file mode 100644 index 680bd55bf0a0..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/singleRefField.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/zeroInitStackSlot.cs b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/zeroInitStackSlot.cs index 8dc08c47d8ca..5c6bdc4ea1ee 100644 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/zeroInitStackSlot.cs +++ b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/zeroInitStackSlot.cs @@ -2,9 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. /* - * The JIT was removing a zero-init, but then emitting an untracked lifetime. - * Please run under GCSTRESS = 0x4 - */ +* The JIT was removing a zero-init, but then emitting an untracked lifetime. +* Please run under GCSTRESS = 0x4 +*/ using System; using System.Runtime.CompilerServices; @@ -35,6 +35,7 @@ void IDisposable.Dispose() public class Repro { [Fact] + [OuterLoop] public static void TestEntryPoint() { new Repro().ProcessResults(Query); diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/zeroInitStackSlot.csproj b/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/zeroInitStackSlot.csproj deleted file mode 100644 index a64c23f1595c..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug679008/zeroInitStackSlot.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug723489/qMarkColon.cs b/src/tests/JIT/Methodical/flowgraph/dev10_bug723489/qMarkColon.cs index 7e1a24d317fd..0cbd863b1d89 100644 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug723489/qMarkColon.cs +++ b/src/tests/JIT/Methodical/flowgraph/dev10_bug723489/qMarkColon.cs @@ -2,9 +2,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. /* - * Basically when we have two Qmark-Colon trees used as the register arguments to a call we don’t take into account that the first one to be evaluated should add a register interference with ECX/EDX so that the next tree will not try to use that register when deciding what register it can use for enregistration of locals. - * An OKMask Assert was being hit in this case. - */ +* Basically when we have two Qmark-Colon trees used as the register arguments to a call we don’t take into account that the first one to be evaluated should add a register interference with ECX/EDX so that the next tree will not try to use that register when deciding what register it can use for enregistration of locals. +* An OKMask Assert was being hit in this case. +*/ using System; using Xunit; @@ -18,6 +18,7 @@ public static bool MyEquals(object obj1, object obj2) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Version ver0 = null; diff --git a/src/tests/JIT/Methodical/flowgraph/dev10_bug723489/qMarkColon.csproj b/src/tests/JIT/Methodical/flowgraph/dev10_bug723489/qMarkColon.csproj deleted file mode 100644 index 575db859d63e..000000000000 --- a/src/tests/JIT/Methodical/flowgraph/dev10_bug723489/qMarkColon.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/apps/BouncingBall.cs b/src/tests/JIT/Methodical/fp/apps/BouncingBall.cs index 3ca0bdde807b..d8fbce941cc8 100644 --- a/src/tests/JIT/Methodical/fp/apps/BouncingBall.cs +++ b/src/tests/JIT/Methodical/fp/apps/BouncingBall.cs @@ -10,6 +10,7 @@ public class BouncingBall { [Fact] + [OuterLoop] public static int TestEntryPoint() { double coef; diff --git a/src/tests/JIT/Methodical/fp/apps/bouncingball_cs_d.csproj b/src/tests/JIT/Methodical/fp/apps/bouncingball_cs_d.csproj deleted file mode 100644 index 913464733831..000000000000 --- a/src/tests/JIT/Methodical/fp/apps/bouncingball_cs_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - Full - False - - - - - - diff --git a/src/tests/JIT/Methodical/fp/apps/bouncingball_cs_do.csproj b/src/tests/JIT/Methodical/fp/apps/bouncingball_cs_do.csproj deleted file mode 100644 index 1651a052d235..000000000000 --- a/src/tests/JIT/Methodical/fp/apps/bouncingball_cs_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - Full - True - - - - - - diff --git a/src/tests/JIT/Methodical/fp/apps/bouncingball_cs_r.csproj b/src/tests/JIT/Methodical/fp/apps/bouncingball_cs_r.csproj deleted file mode 100644 index c4b2d2711420..000000000000 --- a/src/tests/JIT/Methodical/fp/apps/bouncingball_cs_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - None - False - - - - - - diff --git a/src/tests/JIT/Methodical/fp/apps/bouncingball_cs_ro.csproj b/src/tests/JIT/Methodical/fp/apps/bouncingball_cs_ro.csproj deleted file mode 100644 index 212b73431810..000000000000 --- a/src/tests/JIT/Methodical/fp/apps/bouncingball_cs_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - None - True - - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/1000w1d_cs_d.csproj b/src/tests/JIT/Methodical/fp/exgen/1000w1d_cs_d.csproj deleted file mode 100644 index 38a802708c79..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/1000w1d_cs_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - - Full - False - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/1000w1d_cs_do.csproj b/src/tests/JIT/Methodical/fp/exgen/1000w1d_cs_do.csproj deleted file mode 100644 index e57ef0dd4969..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/1000w1d_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - - Full - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/1000w1d_cs_r.csproj b/src/tests/JIT/Methodical/fp/exgen/1000w1d_cs_r.csproj deleted file mode 100644 index 702d8f644155..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/1000w1d_cs_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - - None - False - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/1000w1d_cs_ro.csproj b/src/tests/JIT/Methodical/fp/exgen/1000w1d_cs_ro.csproj deleted file mode 100644 index fb2aa19baede..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/1000w1d_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - - None - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/10w250d.cs b/src/tests/JIT/Methodical/fp/exgen/10w250d.cs index a205a1659fb4..2fd8f7f0591b 100644 --- a/src/tests/JIT/Methodical/fp/exgen/10w250d.cs +++ b/src/tests/JIT/Methodical/fp/exgen/10w250d.cs @@ -4287,6 +4287,7 @@ public static double Func_0() } [Fact] + [OuterLoop] public static int TestEntryPoint() { s_arr2d_0[2, 0] = -0.000244140625; diff --git a/src/tests/JIT/Methodical/fp/exgen/10w250d_cs_d.csproj b/src/tests/JIT/Methodical/fp/exgen/10w250d_cs_d.csproj deleted file mode 100644 index ef7f81673659..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/10w250d_cs_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - Full - False - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/10w250d_cs_do.csproj b/src/tests/JIT/Methodical/fp/exgen/10w250d_cs_do.csproj deleted file mode 100644 index 667c75031820..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/10w250d_cs_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - Full - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/10w250d_cs_r.csproj b/src/tests/JIT/Methodical/fp/exgen/10w250d_cs_r.csproj deleted file mode 100644 index eab2c32e9c7a..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/10w250d_cs_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - None - False - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/10w250d_cs_ro.csproj b/src/tests/JIT/Methodical/fp/exgen/10w250d_cs_ro.csproj deleted file mode 100644 index 1fe81f4529e7..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/10w250d_cs_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - None - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/10w5d.cs b/src/tests/JIT/Methodical/fp/exgen/10w5d.cs index d42ff9b01d72..5cdf47d75b3e 100644 --- a/src/tests/JIT/Methodical/fp/exgen/10w5d.cs +++ b/src/tests/JIT/Methodical/fp/exgen/10w5d.cs @@ -36319,6 +36319,7 @@ public static int Func_0() } [Fact] + [Xunit.SkipOnCoreClrAttribute("This test simply takes too long to complete under GC stress/heap verify; it is not fundamentally incompatible.", RuntimeTestModes.HeapVerify | RuntimeTestModes.AnyGCStress)] public static int TestEntryPoint() { diff --git a/src/tests/JIT/Methodical/fp/exgen/10w5d_cs_d.csproj b/src/tests/JIT/Methodical/fp/exgen/10w5d_cs_d.csproj deleted file mode 100644 index d991e16332b9..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/10w5d_cs_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - true - true - true - - - Full - False - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/10w5d_cs_do.csproj b/src/tests/JIT/Methodical/fp/exgen/10w5d_cs_do.csproj deleted file mode 100644 index d1e37c52b642..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/10w5d_cs_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - true - true - - - Full - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/10w5d_cs_r.csproj b/src/tests/JIT/Methodical/fp/exgen/10w5d_cs_r.csproj deleted file mode 100644 index 705b82f5ec62..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/10w5d_cs_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - true - true - true - - - None - False - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/10w5d_cs_ro.csproj b/src/tests/JIT/Methodical/fp/exgen/10w5d_cs_ro.csproj deleted file mode 100644 index c578348dfc34..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/10w5d_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - - None - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/200w1d-01.cs b/src/tests/JIT/Methodical/fp/exgen/200w1d-01.cs index 4014254bd4d9..5d45d45f47bc 100644 --- a/src/tests/JIT/Methodical/fp/exgen/200w1d-01.cs +++ b/src/tests/JIT/Methodical/fp/exgen/200w1d-01.cs @@ -185,6 +185,7 @@ public static double Func_0() } [Fact] + [OuterLoop] public static int TestEntryPoint() { int retval; diff --git a/src/tests/JIT/Methodical/fp/exgen/200w1d-01_cs_d.csproj b/src/tests/JIT/Methodical/fp/exgen/200w1d-01_cs_d.csproj deleted file mode 100644 index 524df0679243..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/200w1d-01_cs_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - Full - False - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/200w1d-01_cs_do.csproj b/src/tests/JIT/Methodical/fp/exgen/200w1d-01_cs_do.csproj deleted file mode 100644 index 51a861e76bec..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/200w1d-01_cs_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - Full - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/200w1d-01_cs_r.csproj b/src/tests/JIT/Methodical/fp/exgen/200w1d-01_cs_r.csproj deleted file mode 100644 index a26a42619b79..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/200w1d-01_cs_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - None - False - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/200w1d-01_cs_ro.csproj b/src/tests/JIT/Methodical/fp/exgen/200w1d-01_cs_ro.csproj deleted file mode 100644 index 6c56375341a1..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/200w1d-01_cs_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - None - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/200w1d-02.cs b/src/tests/JIT/Methodical/fp/exgen/200w1d-02.cs index 6f50c0f9b6f3..c90e14b13c03 100644 --- a/src/tests/JIT/Methodical/fp/exgen/200w1d-02.cs +++ b/src/tests/JIT/Methodical/fp/exgen/200w1d-02.cs @@ -151,6 +151,7 @@ public static int Func_0() } [Fact] + [OuterLoop] public static int TestEntryPoint() { vtstatic_0.a0_0 = 3.7914999471280252E-09; diff --git a/src/tests/JIT/Methodical/fp/exgen/200w1d-02_cs_d.csproj b/src/tests/JIT/Methodical/fp/exgen/200w1d-02_cs_d.csproj deleted file mode 100644 index 676c8bc495db..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/200w1d-02_cs_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - Full - False - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/200w1d-02_cs_do.csproj b/src/tests/JIT/Methodical/fp/exgen/200w1d-02_cs_do.csproj deleted file mode 100644 index 5ae3a4258cc2..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/200w1d-02_cs_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - - Full - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/200w1d-02_cs_r.csproj b/src/tests/JIT/Methodical/fp/exgen/200w1d-02_cs_r.csproj deleted file mode 100644 index 2c26142232ec..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/200w1d-02_cs_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - None - False - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/200w1d-02_cs_ro.csproj b/src/tests/JIT/Methodical/fp/exgen/200w1d-02_cs_ro.csproj deleted file mode 100644 index 6cff42441c94..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/200w1d-02_cs_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - - None - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/3w1d-01.cs b/src/tests/JIT/Methodical/fp/exgen/3w1d-01.cs index 05d20d03b033..09ac4db8a1a3 100644 --- a/src/tests/JIT/Methodical/fp/exgen/3w1d-01.cs +++ b/src/tests/JIT/Methodical/fp/exgen/3w1d-01.cs @@ -23,6 +23,7 @@ public static int Func_0() } [Fact] + [OuterLoop] public static int TestEntryPoint() { int retval; diff --git a/src/tests/JIT/Methodical/fp/exgen/3w1d-01_cs_d.csproj b/src/tests/JIT/Methodical/fp/exgen/3w1d-01_cs_d.csproj deleted file mode 100644 index 22410a42890a..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/3w1d-01_cs_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/3w1d-01_cs_do.csproj b/src/tests/JIT/Methodical/fp/exgen/3w1d-01_cs_do.csproj deleted file mode 100644 index 2b2593c2d6cc..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/3w1d-01_cs_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/3w1d-01_cs_r.csproj b/src/tests/JIT/Methodical/fp/exgen/3w1d-01_cs_r.csproj deleted file mode 100644 index c6416f98e594..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/3w1d-01_cs_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/3w1d-01_cs_ro.csproj b/src/tests/JIT/Methodical/fp/exgen/3w1d-01_cs_ro.csproj deleted file mode 100644 index 6dc69b0007ea..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/3w1d-01_cs_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/3w1d-02.cs b/src/tests/JIT/Methodical/fp/exgen/3w1d-02.cs index c47800319399..8bcafbe122da 100644 --- a/src/tests/JIT/Methodical/fp/exgen/3w1d-02.cs +++ b/src/tests/JIT/Methodical/fp/exgen/3w1d-02.cs @@ -36,6 +36,7 @@ public static double Func_0() } [Fact] + [OuterLoop] public static int TestEntryPoint() { vtstatic_0.arr3d_0[4, 0, 3] = 1UL; diff --git a/src/tests/JIT/Methodical/fp/exgen/3w1d-02_cs_d.csproj b/src/tests/JIT/Methodical/fp/exgen/3w1d-02_cs_d.csproj deleted file mode 100644 index d3c8bf55db2d..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/3w1d-02_cs_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/3w1d-02_cs_do.csproj b/src/tests/JIT/Methodical/fp/exgen/3w1d-02_cs_do.csproj deleted file mode 100644 index 3e07c7748f1b..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/3w1d-02_cs_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/3w1d-02_cs_r.csproj b/src/tests/JIT/Methodical/fp/exgen/3w1d-02_cs_r.csproj deleted file mode 100644 index 451d561e0564..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/3w1d-02_cs_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/3w1d-02_cs_ro.csproj b/src/tests/JIT/Methodical/fp/exgen/3w1d-02_cs_ro.csproj deleted file mode 100644 index a036bcc573de..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/3w1d-02_cs_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-01.cs b/src/tests/JIT/Methodical/fp/exgen/5w1d-01.cs index 02cf66b169c7..3bcf23334ff2 100644 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-01.cs +++ b/src/tests/JIT/Methodical/fp/exgen/5w1d-01.cs @@ -51,6 +51,7 @@ public static int Func_0() } [Fact] + [OuterLoop] public static int TestEntryPoint() { vtstatic_0.arr2d_0[2, 0] = -2.125; diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-01_cs_d.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-01_cs_d.csproj deleted file mode 100644 index c0402a730dac..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-01_cs_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-01_cs_do.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-01_cs_do.csproj deleted file mode 100644 index 4fe7717f66af..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-01_cs_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-01_cs_r.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-01_cs_r.csproj deleted file mode 100644 index b0a02a2a2d7d..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-01_cs_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-01_cs_ro.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-01_cs_ro.csproj deleted file mode 100644 index 5e4888ddc051..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-01_cs_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-02.cs b/src/tests/JIT/Methodical/fp/exgen/5w1d-02.cs index 0356bda3eade..50d94c51a489 100644 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-02.cs +++ b/src/tests/JIT/Methodical/fp/exgen/5w1d-02.cs @@ -22,6 +22,7 @@ public static double Func_0() } [Fact] + [OuterLoop] public static int TestEntryPoint() { s_arr1d_0[0] = 3758096384.0; diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-02_cs_d.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-02_cs_d.csproj deleted file mode 100644 index 61f7ce8ea9e4..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-02_cs_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-02_cs_do.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-02_cs_do.csproj deleted file mode 100644 index af6f5f5c6fed..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-02_cs_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-02_cs_r.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-02_cs_r.csproj deleted file mode 100644 index 557cb3b3cecb..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-02_cs_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-02_cs_ro.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-02_cs_ro.csproj deleted file mode 100644 index 7fdbc27fdbae..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-02_cs_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-03.cs b/src/tests/JIT/Methodical/fp/exgen/5w1d-03.cs index d032ecb30df0..dead9aafaa21 100644 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-03.cs +++ b/src/tests/JIT/Methodical/fp/exgen/5w1d-03.cs @@ -26,6 +26,7 @@ public static int Func_0() } [Fact] + [OuterLoop] public static int TestEntryPoint() { int retval; diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-03_cs_d.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-03_cs_d.csproj deleted file mode 100644 index 37ee78a8743a..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-03_cs_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-03_cs_do.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-03_cs_do.csproj deleted file mode 100644 index 2a4a64208588..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-03_cs_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-03_cs_r.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-03_cs_r.csproj deleted file mode 100644 index ebf57343dd71..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-03_cs_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-03_cs_ro.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-03_cs_ro.csproj deleted file mode 100644 index 85f0fa1b01e1..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-03_cs_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-04.cs b/src/tests/JIT/Methodical/fp/exgen/5w1d-04.cs index d52d26b35d47..dc94b9fe4f91 100644 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-04.cs +++ b/src/tests/JIT/Methodical/fp/exgen/5w1d-04.cs @@ -35,6 +35,7 @@ public static double Func_0() } [Fact] + [OuterLoop] public static int TestEntryPoint() { int retval; diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-04_cs_d.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-04_cs_d.csproj deleted file mode 100644 index 1b79d0339fd4..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-04_cs_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-04_cs_do.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-04_cs_do.csproj deleted file mode 100644 index d0066c973cfa..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-04_cs_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-04_cs_r.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-04_cs_r.csproj deleted file mode 100644 index 3bd44f60c7a0..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-04_cs_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-04_cs_ro.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-04_cs_ro.csproj deleted file mode 100644 index e9460ed56fd6..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-04_cs_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-05.cs b/src/tests/JIT/Methodical/fp/exgen/5w1d-05.cs index e79fac60a3df..0f40f81c3f53 100644 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-05.cs +++ b/src/tests/JIT/Methodical/fp/exgen/5w1d-05.cs @@ -22,6 +22,7 @@ public static int Func_0() } [Fact] + [OuterLoop] public static int TestEntryPoint() { s_arr1d_0[0] = -3996.0F; diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-05_cs_d.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-05_cs_d.csproj deleted file mode 100644 index 5604e96f7d74..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-05_cs_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - Full - False - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-05_cs_do.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-05_cs_do.csproj deleted file mode 100644 index fc5b7e94154a..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-05_cs_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - Full - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-05_cs_r.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-05_cs_r.csproj deleted file mode 100644 index bb414bc7802c..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-05_cs_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - None - False - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-05_cs_ro.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-05_cs_ro.csproj deleted file mode 100644 index eabaa6ec4810..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-05_cs_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - None - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-06.cs b/src/tests/JIT/Methodical/fp/exgen/5w1d-06.cs index ccc95faf2f9a..30502fa1c1d0 100644 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-06.cs +++ b/src/tests/JIT/Methodical/fp/exgen/5w1d-06.cs @@ -22,6 +22,7 @@ public static int Func_0() } [Fact] + [OuterLoop] public static int TestEntryPoint() { int retval; diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-06_cs_d.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-06_cs_d.csproj deleted file mode 100644 index fd4a1a44e8d7..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-06_cs_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-06_cs_do.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-06_cs_do.csproj deleted file mode 100644 index fcdff41a7351..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-06_cs_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-06_cs_r.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-06_cs_r.csproj deleted file mode 100644 index bd9894d53f4d..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-06_cs_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/fp/exgen/5w1d-06_cs_ro.csproj b/src/tests/JIT/Methodical/fp/exgen/5w1d-06_cs_ro.csproj deleted file mode 100644 index d213ebb2e9c7..000000000000 --- a/src/tests/JIT/Methodical/fp/exgen/5w1d-06_cs_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/gc_poll/InsertGCPoll.cs b/src/tests/JIT/Methodical/gc_poll/InsertGCPoll.cs index c080dae1c74c..8c7f3ba93697 100644 --- a/src/tests/JIT/Methodical/gc_poll/InsertGCPoll.cs +++ b/src/tests/JIT/Methodical/gc_poll/InsertGCPoll.cs @@ -85,8 +85,17 @@ private static void LoopOn64() i += GCPollNative.NextUInt64(1); } } + + public static readonly bool IsMonoJitArm64 = + TestLibrary.PlatformDetection.IsArm64Process + && TestLibrary.PlatformDetection.IsMonoRuntime + && !TestLibrary.PlatformDetection.IsMonoInterpreter + && !TestLibrary.PlatformDetection.IsMonoFULLAOT + && !TestLibrary.PlatformDetection.IsMonoLLVMAOT; [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/82859", typeof(InsertGCPoll), nameof(IsMonoJitArm64))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/91388", typeof(TestLibrary.PlatformDetection), nameof(TestLibrary.PlatformDetection.PlatformDoesNotSupportNativeTestAssets))] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/gc_poll/InsertGCPoll.csproj b/src/tests/JIT/Methodical/gc_poll/InsertGCPoll.csproj deleted file mode 100644 index 1bf11922b1f5..000000000000 --- a/src/tests/JIT/Methodical/gc_poll/InsertGCPoll.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - true - - - True - - - - - - - - diff --git a/src/tests/JIT/Methodical/inlining/boolean/InlineBool.cs b/src/tests/JIT/Methodical/inlining/boolean/InlineBool.cs index 227b37ec2672..716ca23595db 100644 --- a/src/tests/JIT/Methodical/inlining/boolean/InlineBool.cs +++ b/src/tests/JIT/Methodical/inlining/boolean/InlineBool.cs @@ -159,6 +159,7 @@ public class Program [MethodImpl(MethodImplOptions.NoOptimization)] [Fact] + [OuterLoop] public static int TestEntryPoint() { bool result = true; diff --git a/src/tests/JIT/Methodical/inlining/boolean/test_boolean.csproj b/src/tests/JIT/Methodical/inlining/boolean/test_boolean.csproj deleted file mode 100644 index db4c532003fb..000000000000 --- a/src/tests/JIT/Methodical/inlining/boolean/test_boolean.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - 1 - - - PdbOnly - - - - - diff --git a/src/tests/JIT/Methodical/inlining/bug505642/test.cs b/src/tests/JIT/Methodical/inlining/bug505642/test.cs index 8d7a106d5b12..3eeb66dcdc86 100644 --- a/src/tests/JIT/Methodical/inlining/bug505642/test.cs +++ b/src/tests/JIT/Methodical/inlining/bug505642/test.cs @@ -29,6 +29,7 @@ public Tuple(T0 Field0, T1 Field1) public static class M { [Fact] + [OuterLoop] public static int TestEntryPoint() { return meth(8, 100); diff --git a/src/tests/JIT/Methodical/inlining/bug505642/test_bug505642.csproj b/src/tests/JIT/Methodical/inlining/bug505642/test_bug505642.csproj deleted file mode 100644 index a10728d944d6..000000000000 --- a/src/tests/JIT/Methodical/inlining/bug505642/test_bug505642.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - 1 - - - PdbOnly - - - - - diff --git a/src/tests/JIT/Methodical/int64/arrays/lcs_long.cs b/src/tests/JIT/Methodical/int64/arrays/lcs_long.cs index 309aa9bffe00..725278dac612 100644 --- a/src/tests/JIT/Methodical/int64/arrays/lcs_long.cs +++ b/src/tests/JIT/Methodical/int64/arrays/lcs_long.cs @@ -84,6 +84,7 @@ private static void findLCS(long[,,,] c, long[,,,] b, char[][] seq, long[] len) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Console.WriteLine("Test searches for longest common subsequence of 4 strings\n\n"); diff --git a/src/tests/JIT/Methodical/int64/arrays/lcs_long_d.csproj b/src/tests/JIT/Methodical/int64/arrays/lcs_long_d.csproj deleted file mode 100644 index 9a4827d68232..000000000000 --- a/src/tests/JIT/Methodical/int64/arrays/lcs_long_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/arrays/lcs_long_do.csproj b/src/tests/JIT/Methodical/int64/arrays/lcs_long_do.csproj deleted file mode 100644 index d0c043e44c43..000000000000 --- a/src/tests/JIT/Methodical/int64/arrays/lcs_long_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/arrays/lcs_long_r.csproj b/src/tests/JIT/Methodical/int64/arrays/lcs_long_r.csproj deleted file mode 100644 index 18a696b67078..000000000000 --- a/src/tests/JIT/Methodical/int64/arrays/lcs_long_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/arrays/lcs_long_ro.csproj b/src/tests/JIT/Methodical/int64/arrays/lcs_long_ro.csproj deleted file mode 100644 index b8f79dcc111f..000000000000 --- a/src/tests/JIT/Methodical/int64/arrays/lcs_long_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/arrays/lcs_ulong.cs b/src/tests/JIT/Methodical/int64/arrays/lcs_ulong.cs index 6c9798c506d3..ccfee0c59f31 100644 --- a/src/tests/JIT/Methodical/int64/arrays/lcs_ulong.cs +++ b/src/tests/JIT/Methodical/int64/arrays/lcs_ulong.cs @@ -84,6 +84,7 @@ private static void findLCS(ulong[,,,] c, ulong[,,,] b, char[][] seq, ulong[] le } [Fact] + [OuterLoop] public static int TestEntryPoint() { Console.WriteLine("Test searches for ulongest common subsequence of 4 strings\n\n"); diff --git a/src/tests/JIT/Methodical/int64/arrays/lcs_ulong_d.csproj b/src/tests/JIT/Methodical/int64/arrays/lcs_ulong_d.csproj deleted file mode 100644 index 4a1da957a747..000000000000 --- a/src/tests/JIT/Methodical/int64/arrays/lcs_ulong_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/arrays/lcs_ulong_do.csproj b/src/tests/JIT/Methodical/int64/arrays/lcs_ulong_do.csproj deleted file mode 100644 index 2eb04e993497..000000000000 --- a/src/tests/JIT/Methodical/int64/arrays/lcs_ulong_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/arrays/lcs_ulong_r.csproj b/src/tests/JIT/Methodical/int64/arrays/lcs_ulong_r.csproj deleted file mode 100644 index 4dbaeaa36a75..000000000000 --- a/src/tests/JIT/Methodical/int64/arrays/lcs_ulong_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/arrays/lcs_ulong_ro.csproj b/src/tests/JIT/Methodical/int64/arrays/lcs_ulong_ro.csproj deleted file mode 100644 index 9f32a72fc935..000000000000 --- a/src/tests/JIT/Methodical/int64/arrays/lcs_ulong_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/misc/binop.cs b/src/tests/JIT/Methodical/int64/misc/binop.cs index b3b262008dcb..6336c544d29c 100644 --- a/src/tests/JIT/Methodical/int64/misc/binop.cs +++ b/src/tests/JIT/Methodical/int64/misc/binop.cs @@ -9,6 +9,7 @@ namespace JitTest_binop_misc_cs public class Test { [Fact] + [OuterLoop] public static int TestEntryPoint() { long L1, L2; diff --git a/src/tests/JIT/Methodical/int64/misc/binop_d.csproj b/src/tests/JIT/Methodical/int64/misc/binop_d.csproj deleted file mode 100644 index 005d8ece53af..000000000000 --- a/src/tests/JIT/Methodical/int64/misc/binop_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/misc/binop_do.csproj b/src/tests/JIT/Methodical/int64/misc/binop_do.csproj deleted file mode 100644 index 1b78fd9cbd02..000000000000 --- a/src/tests/JIT/Methodical/int64/misc/binop_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/misc/binop_r.csproj b/src/tests/JIT/Methodical/int64/misc/binop_r.csproj deleted file mode 100644 index 090b65542246..000000000000 --- a/src/tests/JIT/Methodical/int64/misc/binop_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/misc/binop_ro.csproj b/src/tests/JIT/Methodical/int64/misc/binop_ro.csproj deleted file mode 100644 index a6edf7cffde9..000000000000 --- a/src/tests/JIT/Methodical/int64/misc/binop_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/misc/box.cs b/src/tests/JIT/Methodical/int64/misc/box.cs index 06253d3943bc..75e87ed51e42 100644 --- a/src/tests/JIT/Methodical/int64/misc/box.cs +++ b/src/tests/JIT/Methodical/int64/misc/box.cs @@ -9,6 +9,7 @@ namespace JitTest_box_misc_cs public class Test { [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/int64/misc/box_d.csproj b/src/tests/JIT/Methodical/int64/misc/box_d.csproj deleted file mode 100644 index 429d945db7fb..000000000000 --- a/src/tests/JIT/Methodical/int64/misc/box_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/misc/box_do.csproj b/src/tests/JIT/Methodical/int64/misc/box_do.csproj deleted file mode 100644 index 05a5ba97e791..000000000000 --- a/src/tests/JIT/Methodical/int64/misc/box_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/misc/box_r.csproj b/src/tests/JIT/Methodical/int64/misc/box_r.csproj deleted file mode 100644 index 48381e96bbe6..000000000000 --- a/src/tests/JIT/Methodical/int64/misc/box_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/misc/box_ro.csproj b/src/tests/JIT/Methodical/int64/misc/box_ro.csproj deleted file mode 100644 index da3280fc05e5..000000000000 --- a/src/tests/JIT/Methodical/int64/misc/box_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_addsub.cs b/src/tests/JIT/Methodical/int64/signed/s_addsub.cs index 49a495ae586b..6f849fac5b7f 100644 --- a/src/tests/JIT/Methodical/int64/signed/s_addsub.cs +++ b/src/tests/JIT/Methodical/int64/signed/s_addsub.cs @@ -68,6 +68,7 @@ private static void testNumbers(long a, long b) } [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/int64/signed/s_addsub_d.csproj b/src/tests/JIT/Methodical/int64/signed/s_addsub_d.csproj deleted file mode 100644 index d149a23b82e7..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_addsub_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_addsub_do.csproj b/src/tests/JIT/Methodical/int64/signed/s_addsub_do.csproj deleted file mode 100644 index 5e233287ac22..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_addsub_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_addsub_r.csproj b/src/tests/JIT/Methodical/int64/signed/s_addsub_r.csproj deleted file mode 100644 index e0c4270a32d7..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_addsub_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_addsub_ro.csproj b/src/tests/JIT/Methodical/int64/signed/s_addsub_ro.csproj deleted file mode 100644 index 339ad0ecbdec..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_addsub_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldc_div_d.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldc_div_d.csproj deleted file mode 100644 index b5c99db4c352..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldc_div_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldc_div_do.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldc_div_do.csproj deleted file mode 100644 index 230d07ed1783..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldc_div_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldc_div_r.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldc_div_r.csproj deleted file mode 100644 index 20a7d3348a23..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldc_div_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldc_div_ro.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldc_div_ro.csproj deleted file mode 100644 index de7851e3737c..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldc_div_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldc_mul.cs b/src/tests/JIT/Methodical/int64/signed/s_ldc_mul.cs index 116a09d509fd..8f4f6f592353 100644 --- a/src/tests/JIT/Methodical/int64/signed/s_ldc_mul.cs +++ b/src/tests/JIT/Methodical/int64/signed/s_ldc_mul.cs @@ -26,6 +26,7 @@ private static bool check(long op1, long op2, long product, bool overflow) } [Fact] + [OuterLoop] public static int TestEntryPoint() { if (!check(0x000000007fffffff, 0x000000007fffffff, 0x3fffffff00000001, false)) diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldc_mul_d.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldc_mul_d.csproj deleted file mode 100644 index e352b80e0713..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldc_mul_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldc_mul_do.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldc_mul_do.csproj deleted file mode 100644 index dbdd8c5f1c2b..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldc_mul_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldc_mul_r.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldc_mul_r.csproj deleted file mode 100644 index a29b98a0038e..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldc_mul_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldc_mul_ro.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldc_mul_ro.csproj deleted file mode 100644 index b238ab2afa7f..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldc_mul_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldc_mulovf_d.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldc_mulovf_d.csproj deleted file mode 100644 index 7ec8104ec271..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldc_mulovf_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldc_mulovf_do.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldc_mulovf_do.csproj deleted file mode 100644 index cd65a9fe5b9a..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldc_mulovf_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldc_mulovf_r.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldc_mulovf_r.csproj deleted file mode 100644 index 89783a781c66..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldc_mulovf_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldc_mulovf_ro.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldc_mulovf_ro.csproj deleted file mode 100644 index 852d28146063..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldc_mulovf_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul.cs b/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul.cs index 980ad0640b61..767e30bb5db0 100644 --- a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul.cs +++ b/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul.cs @@ -27,6 +27,7 @@ private bool check(long product, bool overflow) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Test app = new Test(); diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul_d.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul_d.csproj deleted file mode 100644 index bd7ce8a7532d..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul_do.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul_do.csproj deleted file mode 100644 index 11ae3bf1e06a..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul_r.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul_r.csproj deleted file mode 100644 index ac9d8b57af4d..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul_ro.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul_ro.csproj deleted file mode 100644 index 97b77ff3699e..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mul_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mulovf_d.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldfld_mulovf_d.csproj deleted file mode 100644 index 6bd9541a9148..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mulovf_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mulovf_do.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldfld_mulovf_do.csproj deleted file mode 100644 index ed9a82144cdc..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mulovf_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mulovf_r.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldfld_mulovf_r.csproj deleted file mode 100644 index 5fa429fc6856..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mulovf_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mulovf_ro.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldfld_mulovf_ro.csproj deleted file mode 100644 index 176ea7ba0eeb..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldfld_mulovf_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul.cs b/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul.cs index 146d22cf72ae..ccea0e3dc108 100644 --- a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul.cs +++ b/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul.cs @@ -27,6 +27,7 @@ private static bool check(long product, bool overflow) } [Fact] + [OuterLoop] public static int TestEntryPoint() { s_op1 = 0x000000007fffffff; diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul_d.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul_d.csproj deleted file mode 100644 index 268144e18d4c..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul_do.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul_do.csproj deleted file mode 100644 index 14f6175164f3..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul_r.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul_r.csproj deleted file mode 100644 index 25f9bacd4f23..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul_ro.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul_ro.csproj deleted file mode 100644 index cc75b843485b..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mul_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mulovf_d.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mulovf_d.csproj deleted file mode 100644 index b6677e0ca65b..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mulovf_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mulovf_do.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mulovf_do.csproj deleted file mode 100644 index e5e4f6385413..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mulovf_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mulovf_r.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mulovf_r.csproj deleted file mode 100644 index 47984ed0082e..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mulovf_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mulovf_ro.csproj b/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mulovf_ro.csproj deleted file mode 100644 index 1ab580df20de..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_ldsfld_mulovf_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_muldiv_d.csproj b/src/tests/JIT/Methodical/int64/signed/s_muldiv_d.csproj deleted file mode 100644 index cca03ff987cc..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_muldiv_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_muldiv_do.csproj b/src/tests/JIT/Methodical/int64/signed/s_muldiv_do.csproj deleted file mode 100644 index 3e99e95c66ef..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_muldiv_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_muldiv_r.csproj b/src/tests/JIT/Methodical/int64/signed/s_muldiv_r.csproj deleted file mode 100644 index c0b7bedb86a8..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_muldiv_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/signed/s_muldiv_ro.csproj b/src/tests/JIT/Methodical/int64/signed/s_muldiv_ro.csproj deleted file mode 100644 index 556811243108..000000000000 --- a/src/tests/JIT/Methodical/int64/signed/s_muldiv_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/superlong/superlong_d.csproj b/src/tests/JIT/Methodical/int64/superlong/superlong_d.csproj deleted file mode 100644 index 0d52db667256..000000000000 --- a/src/tests/JIT/Methodical/int64/superlong/superlong_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/superlong/superlong_do.csproj b/src/tests/JIT/Methodical/int64/superlong/superlong_do.csproj deleted file mode 100644 index 689fd3a94b78..000000000000 --- a/src/tests/JIT/Methodical/int64/superlong/superlong_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/superlong/superlong_r.csproj b/src/tests/JIT/Methodical/int64/superlong/superlong_r.csproj deleted file mode 100644 index c820428455f1..000000000000 --- a/src/tests/JIT/Methodical/int64/superlong/superlong_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/superlong/superlong_ro.csproj b/src/tests/JIT/Methodical/int64/superlong/superlong_ro.csproj deleted file mode 100644 index 3a4c1c4d91a3..000000000000 --- a/src/tests/JIT/Methodical/int64/superlong/superlong_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/addsub_d.csproj b/src/tests/JIT/Methodical/int64/unsigned/addsub_d.csproj deleted file mode 100644 index b19db0b5d63c..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/addsub_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/addsub_do.csproj b/src/tests/JIT/Methodical/int64/unsigned/addsub_do.csproj deleted file mode 100644 index a6ba6e79c1e4..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/addsub_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/addsub_r.csproj b/src/tests/JIT/Methodical/int64/unsigned/addsub_r.csproj deleted file mode 100644 index 22bd977c9fb9..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/addsub_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/addsub_ro.csproj b/src/tests/JIT/Methodical/int64/unsigned/addsub_ro.csproj deleted file mode 100644 index 0c8fcc4f7e4b..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/addsub_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldc_mul.cs b/src/tests/JIT/Methodical/int64/unsigned/ldc_mul.cs index dc479ef43ca1..6e6c38aa5320 100644 --- a/src/tests/JIT/Methodical/int64/unsigned/ldc_mul.cs +++ b/src/tests/JIT/Methodical/int64/unsigned/ldc_mul.cs @@ -26,6 +26,7 @@ private static bool check(ulong op1, ulong op2, ulong product, bool overflow) } [Fact] + [OuterLoop] public static int TestEntryPoint() { if (!check(0x00000000ffffffff, 0x00000000ffffffff, 0xfffffffe00000001, false)) diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldc_mul_d.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldc_mul_d.csproj deleted file mode 100644 index 47215e6c0fb7..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldc_mul_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldc_mul_do.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldc_mul_do.csproj deleted file mode 100644 index 1ca4b9504f40..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldc_mul_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldc_mul_r.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldc_mul_r.csproj deleted file mode 100644 index 5749796d6c91..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldc_mul_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldc_mul_ro.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldc_mul_ro.csproj deleted file mode 100644 index 88545a23a3c2..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldc_mul_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldc_mulovf_d.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldc_mulovf_d.csproj deleted file mode 100644 index 322258695ce8..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldc_mulovf_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldc_mulovf_do.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldc_mulovf_do.csproj deleted file mode 100644 index 780f88d6f9de..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldc_mulovf_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldc_mulovf_r.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldc_mulovf_r.csproj deleted file mode 100644 index 1be6bc13b184..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldc_mulovf_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldc_mulovf_ro.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldc_mulovf_ro.csproj deleted file mode 100644 index 2f91dddcb8aa..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldc_mulovf_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul.cs b/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul.cs index 6bc2932aacae..880d5201a8dd 100644 --- a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul.cs +++ b/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul.cs @@ -28,6 +28,7 @@ private bool check(ulong product, bool overflow) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Test app = new Test(); diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul_d.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul_d.csproj deleted file mode 100644 index c512c3649da0..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul_do.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul_do.csproj deleted file mode 100644 index 870fd84c600b..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul_r.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul_r.csproj deleted file mode 100644 index 5cf7f1f1beac..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul_ro.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul_ro.csproj deleted file mode 100644 index ebf985ab40d2..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mul_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mulovf_d.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldfld_mulovf_d.csproj deleted file mode 100644 index 78dfcd9fd386..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mulovf_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mulovf_do.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldfld_mulovf_do.csproj deleted file mode 100644 index 940e59e4aa97..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mulovf_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mulovf_r.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldfld_mulovf_r.csproj deleted file mode 100644 index 240d4e953a5b..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mulovf_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mulovf_ro.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldfld_mulovf_ro.csproj deleted file mode 100644 index f447dd46b06c..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldfld_mulovf_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul.cs b/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul.cs index 7105964a5d58..07eeecfb4407 100644 --- a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul.cs +++ b/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul.cs @@ -28,6 +28,7 @@ private static bool check(ulong product, bool overflow) } [Fact] + [OuterLoop] public static int TestEntryPoint() { s_op1 = 0x00000000ffffffff; diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul_d.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul_d.csproj deleted file mode 100644 index b294c0abb429..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul_do.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul_do.csproj deleted file mode 100644 index 10efd6b3f80b..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul_r.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul_r.csproj deleted file mode 100644 index 00a2834f992e..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul_ro.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul_ro.csproj deleted file mode 100644 index 3215e8c741a8..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mul_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mulovf_d.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mulovf_d.csproj deleted file mode 100644 index 69bc95e00c6f..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mulovf_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mulovf_do.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mulovf_do.csproj deleted file mode 100644 index 15b495813887..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mulovf_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mulovf_r.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mulovf_r.csproj deleted file mode 100644 index ad5337fc1cbf..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mulovf_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mulovf_ro.csproj b/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mulovf_ro.csproj deleted file mode 100644 index 958b8466fdfc..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/ldsfld_mulovf_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/muldiv_d.csproj b/src/tests/JIT/Methodical/int64/unsigned/muldiv_d.csproj deleted file mode 100644 index a1dee267f807..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/muldiv_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/muldiv_do.csproj b/src/tests/JIT/Methodical/int64/unsigned/muldiv_do.csproj deleted file mode 100644 index 258548c16cf5..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/muldiv_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/muldiv_r.csproj b/src/tests/JIT/Methodical/int64/unsigned/muldiv_r.csproj deleted file mode 100644 index 72b256370e47..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/muldiv_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/int64/unsigned/muldiv_ro.csproj b/src/tests/JIT/Methodical/int64/unsigned/muldiv_ro.csproj deleted file mode 100644 index 919b7db311d7..000000000000 --- a/src/tests/JIT/Methodical/int64/unsigned/muldiv_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/jitinterface/bug603649.cs b/src/tests/JIT/Methodical/jitinterface/bug603649.cs index 72f2afe822a9..46600a1ca703 100644 --- a/src/tests/JIT/Methodical/jitinterface/bug603649.cs +++ b/src/tests/JIT/Methodical/jitinterface/bug603649.cs @@ -10,6 +10,7 @@ public class foo { private static object s_o = typeof(string); [Fact] + [OuterLoop] public static int TestEntryPoint() { bool f = typeof(string) == s_o as Type; diff --git a/src/tests/JIT/Methodical/jitinterface/bug603649.csproj b/src/tests/JIT/Methodical/jitinterface/bug603649.csproj deleted file mode 100644 index a91bee346310..000000000000 --- a/src/tests/JIT/Methodical/jitinterface/bug603649.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - PdbOnly - True - True - - - - - diff --git a/src/tests/JIT/Methodical/largeframes/basic/bigframes.cs b/src/tests/JIT/Methodical/largeframes/basic/bigframes.cs index c7b1622d601b..694f518bf363 100644 --- a/src/tests/JIT/Methodical/largeframes/basic/bigframes.cs +++ b/src/tests/JIT/Methodical/largeframes/basic/bigframes.cs @@ -143,6 +143,7 @@ public static void Test5() } [Fact] + [OuterLoop] public static int TestEntryPoint() { Test1(); diff --git a/src/tests/JIT/Methodical/largeframes/basic/bigframes.csproj b/src/tests/JIT/Methodical/largeframes/basic/bigframes.csproj deleted file mode 100644 index a67d3655f35d..000000000000 --- a/src/tests/JIT/Methodical/largeframes/basic/bigframes.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/largeframes/skip/skippage.cs b/src/tests/JIT/Methodical/largeframes/skip/skippage.cs index aeb231df37e6..44c73f865c87 100644 --- a/src/tests/JIT/Methodical/largeframes/skip/skippage.cs +++ b/src/tests/JIT/Methodical/largeframes/skip/skippage.cs @@ -59,6 +59,7 @@ public static void Test1(bool call_struct_function) } [Fact] + [OuterLoop] public static int TestEntryPoint() { TestWrite2(); // Make sure this is JITted first, so the call from Test1() is not to the prestub. diff --git a/src/tests/JIT/Methodical/largeframes/skip/skippage.csproj b/src/tests/JIT/Methodical/largeframes/skip/skippage.csproj deleted file mode 100644 index 4af529267606..000000000000 --- a/src/tests/JIT/Methodical/largeframes/skip/skippage.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/largeframes/skip2/skippage2.cs b/src/tests/JIT/Methodical/largeframes/skip2/skippage2.cs index 889e2c9d017e..e83b34749deb 100644 --- a/src/tests/JIT/Methodical/largeframes/skip2/skippage2.cs +++ b/src/tests/JIT/Methodical/largeframes/skip2/skippage2.cs @@ -221,6 +221,7 @@ public static void Test1(bool call_struct_function) } [Fact] + [OuterLoop] public static int TestEntryPoint() { SmallFrameSize(); // Make sure this is JITted first, so the call from Test1() is not to the prestub. diff --git a/src/tests/JIT/Methodical/largeframes/skip2/skippage2.csproj b/src/tests/JIT/Methodical/largeframes/skip2/skippage2.csproj deleted file mode 100644 index 58d5044193b6..000000000000 --- a/src/tests/JIT/Methodical/largeframes/skip2/skippage2.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/largeframes/skip3/skippage3.cs b/src/tests/JIT/Methodical/largeframes/skip3/skippage3.cs index 861227dee2c8..66cededccdf6 100644 --- a/src/tests/JIT/Methodical/largeframes/skip3/skippage3.cs +++ b/src/tests/JIT/Methodical/largeframes/skip3/skippage3.cs @@ -69,6 +69,7 @@ public static void EatStackThenTest1(int level = 0) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Test1(); // force JIT of this diff --git a/src/tests/JIT/Methodical/largeframes/skip3/skippage3.csproj b/src/tests/JIT/Methodical/largeframes/skip3/skippage3.csproj deleted file mode 100644 index cc7708b554a4..000000000000 --- a/src/tests/JIT/Methodical/largeframes/skip3/skippage3.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/largeframes/skip4/skippage4.cs b/src/tests/JIT/Methodical/largeframes/skip4/skippage4.cs index b35bab401f40..906e38a8005c 100644 --- a/src/tests/JIT/Methodical/largeframes/skip4/skippage4.cs +++ b/src/tests/JIT/Methodical/largeframes/skip4/skippage4.cs @@ -44,6 +44,7 @@ public static void Test1() } [Fact] + [OuterLoop] public static int TestEntryPoint() { Test1(); diff --git a/src/tests/JIT/Methodical/largeframes/skip4/skippage4.csproj b/src/tests/JIT/Methodical/largeframes/skip4/skippage4.csproj deleted file mode 100644 index 60c25e1f245e..000000000000 --- a/src/tests/JIT/Methodical/largeframes/skip4/skippage4.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/largeframes/skip5/skippage5.cs b/src/tests/JIT/Methodical/largeframes/skip5/skippage5.cs index 21dd848f9eb0..1facc2bb7e6c 100644 --- a/src/tests/JIT/Methodical/largeframes/skip5/skippage5.cs +++ b/src/tests/JIT/Methodical/largeframes/skip5/skippage5.cs @@ -22,7 +22,8 @@ class C } [Fact] - public static void TestEntryPoint() => Test(new C()); + [OuterLoop] + public static void TestEntryPoint() => Test(new C()); [MethodImpl(MethodImplOptions.NoInlining)] static void Call(int r0, int r1, int r2, int r3, int r4, int r5, int r6, S s) diff --git a/src/tests/JIT/Methodical/largeframes/skip5/skippage5.csproj b/src/tests/JIT/Methodical/largeframes/skip5/skippage5.csproj deleted file mode 100644 index 531c58f2a2a6..000000000000 --- a/src/tests/JIT/Methodical/largeframes/skip5/skippage5.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - true - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/largeframes/skip6/skippage6.cs b/src/tests/JIT/Methodical/largeframes/skip6/skippage6.cs index b25df301217f..f6226149d46b 100644 --- a/src/tests/JIT/Methodical/largeframes/skip6/skippage6.cs +++ b/src/tests/JIT/Methodical/largeframes/skip6/skippage6.cs @@ -12092,7 +12092,8 @@ public static void Escape(ref LargeStruct s) } [Fact] - public static int TestEntryPoint() + [OuterLoop] + public static int TestEntryPoint() { Test1(1); // force JIT of this Test1(80); diff --git a/src/tests/JIT/Methodical/largeframes/skip6/skippage6.csproj b/src/tests/JIT/Methodical/largeframes/skip6/skippage6.csproj deleted file mode 100644 index e00db2ddc8e3..000000000000 --- a/src/tests/JIT/Methodical/largeframes/skip6/skippage6.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - true - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/largeframes/skip7/skippage7.cs b/src/tests/JIT/Methodical/largeframes/skip7/skippage7.cs index 2b9c36b53ccd..a9d8bcc5158a 100644 --- a/src/tests/JIT/Methodical/largeframes/skip7/skippage7.cs +++ b/src/tests/JIT/Methodical/largeframes/skip7/skippage7.cs @@ -85,7 +85,8 @@ public static void Escape(ref LargeStruct s) } [Fact] - public static int TestEntryPoint() + [OuterLoop] + public static int TestEntryPoint() { Test1(1); // force JIT of this Test1(80); diff --git a/src/tests/JIT/Methodical/largeframes/skip7/skippage7.csproj b/src/tests/JIT/Methodical/largeframes/skip7/skippage7.csproj deleted file mode 100644 index 48cdf680a35d..000000000000 --- a/src/tests/JIT/Methodical/largeframes/skip7/skippage7.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - true - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/localloc/call/call01.cs b/src/tests/JIT/Methodical/localloc/call/call01.cs index ba2e625377e4..766d3c253b9d 100644 --- a/src/tests/JIT/Methodical/localloc/call/call01.cs +++ b/src/tests/JIT/Methodical/localloc/call/call01.cs @@ -16,23 +16,14 @@ public class LocallocTest private static int s_locallocSize = 0; [Fact] + [OuterLoop] public static unsafe int TestEntryPoint() { ulong local1 = Global.INITIAL_VALUE; ulong local2 = local1 + 1; -#if LOCALLOC_SMALL Int32* intArray1 = stackalloc Int32[1]; Int32* intArray2 = stackalloc Int32[1]; s_locallocSize = 1; -#elif LOCALLOC_LARGE - Int32* intArray1 = stackalloc Int32[0x1000]; - Int32* intArray2 = stackalloc Int32[0x1000]; - locallocSize = 0x1000; -#else - Int32* intArray1 = stackalloc Int32[Global.stackAllocSize]; - Int32* intArray2 = stackalloc Int32[Global.stackAllocSize]; - locallocSize = Global.stackAllocSize; -#endif Global.initializeStack(intArray1, s_locallocSize, 1000); Global.initializeStack(intArray2, s_locallocSize, 2000); @@ -61,16 +52,8 @@ public static unsafe int TestEntryPoint() private static unsafe bool func1(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, Int32* ar1, Int32* ar2) { -#if LOCALLOC_SMALL Int32* intArray1 = stackalloc Int32[1]; Int32* intArray2 = stackalloc Int32[1]; -#elif LOCALLOC_LARGE - Int32* intArray1 = stackalloc Int32[0x1000]; - Int32* intArray2 = stackalloc Int32[0x1000]; -#else - Int32* intArray1 = stackalloc Int32[Global.stackAllocSize]; - Int32* intArray2 = stackalloc Int32[Global.stackAllocSize]; -#endif Global.initializeStack(intArray1, s_locallocSize, 3000); Global.initializeStack(intArray2, s_locallocSize, 4000); diff --git a/src/tests/JIT/Methodical/localloc/call/call01_small.csproj b/src/tests/JIT/Methodical/localloc/call/call01_small.csproj deleted file mode 100644 index 682f255af5ec..000000000000 --- a/src/tests/JIT/Methodical/localloc/call/call01_small.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - PdbOnly - True - $(DefineConstants);LOCALLOC_SMALL - $(NoWarn),8002 - - - - - - diff --git a/src/tests/JIT/Methodical/nonvirtualcall/classic.cs b/src/tests/JIT/Methodical/nonvirtualcall/classic.cs index d62e6d3ef676..f8667a2e675b 100644 --- a/src/tests/JIT/Methodical/nonvirtualcall/classic.cs +++ b/src/tests/JIT/Methodical/nonvirtualcall/classic.cs @@ -191,6 +191,7 @@ public static void CallFromInsideGrandChild() } [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/nonvirtualcall/classic.csproj b/src/tests/JIT/Methodical/nonvirtualcall/classic.csproj deleted file mode 100644 index 5e260c8c7704..000000000000 --- a/src/tests/JIT/Methodical/nonvirtualcall/classic.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/nonvirtualcall/delegate.cs b/src/tests/JIT/Methodical/nonvirtualcall/delegate.cs index ca98089d6a23..12d414880d41 100644 --- a/src/tests/JIT/Methodical/nonvirtualcall/delegate.cs +++ b/src/tests/JIT/Methodical/nonvirtualcall/delegate.cs @@ -150,6 +150,7 @@ public static void CallDelegateFromGrandChild() } [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/nonvirtualcall/delegate.csproj b/src/tests/JIT/Methodical/nonvirtualcall/delegate.csproj deleted file mode 100644 index 528f79c7379c..000000000000 --- a/src/tests/JIT/Methodical/nonvirtualcall/delegate.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/nonvirtualcall/generics.cs b/src/tests/JIT/Methodical/nonvirtualcall/generics.cs index a654bcbaf056..28582a4b645e 100644 --- a/src/tests/JIT/Methodical/nonvirtualcall/generics.cs +++ b/src/tests/JIT/Methodical/nonvirtualcall/generics.cs @@ -190,6 +190,7 @@ public static void CallFromInsideGrandChild() } [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/nonvirtualcall/generics.csproj b/src/tests/JIT/Methodical/nonvirtualcall/generics.csproj deleted file mode 100644 index b39e24bbe83f..000000000000 --- a/src/tests/JIT/Methodical/nonvirtualcall/generics.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/nonvirtualcall/generics2.cs b/src/tests/JIT/Methodical/nonvirtualcall/generics2.cs index dc76f4a240b0..ff43e4037e45 100644 --- a/src/tests/JIT/Methodical/nonvirtualcall/generics2.cs +++ b/src/tests/JIT/Methodical/nonvirtualcall/generics2.cs @@ -190,6 +190,7 @@ public static void CallFromInsideGrandChild() } [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/nonvirtualcall/generics2.csproj b/src/tests/JIT/Methodical/nonvirtualcall/generics2.csproj deleted file mode 100644 index c1a79a455503..000000000000 --- a/src/tests/JIT/Methodical/nonvirtualcall/generics2.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/nonvirtualcall/tailcall.cs b/src/tests/JIT/Methodical/nonvirtualcall/tailcall.cs index eebe6892b580..089e314a265d 100644 --- a/src/tests/JIT/Methodical/nonvirtualcall/tailcall.cs +++ b/src/tests/JIT/Methodical/nonvirtualcall/tailcall.cs @@ -191,6 +191,7 @@ public static void CallFromInsideGrandChild() } [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/nonvirtualcall/tailcall.csproj b/src/tests/JIT/Methodical/nonvirtualcall/tailcall.csproj deleted file mode 100644 index 91a89007096d..000000000000 --- a/src/tests/JIT/Methodical/nonvirtualcall/tailcall.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/nonvirtualcall/valuetype.cs b/src/tests/JIT/Methodical/nonvirtualcall/valuetype.cs index ed517239a6e6..d3451f46dad1 100644 --- a/src/tests/JIT/Methodical/nonvirtualcall/valuetype.cs +++ b/src/tests/JIT/Methodical/nonvirtualcall/valuetype.cs @@ -35,6 +35,7 @@ public static void CallDummy() } [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/nonvirtualcall/valuetype.csproj b/src/tests/JIT/Methodical/nonvirtualcall/valuetype.csproj deleted file mode 100644 index f8d7c3739270..000000000000 --- a/src/tests/JIT/Methodical/nonvirtualcall/valuetype.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/array1.cs b/src/tests/JIT/Methodical/refany/array1.cs index f14a662ec30d..b4eadfd45ea2 100644 --- a/src/tests/JIT/Methodical/refany/array1.cs +++ b/src/tests/JIT/Methodical/refany/array1.cs @@ -43,6 +43,7 @@ private static void TestRef(TypedReference _ref) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Array genericArray = Array.CreateInstance(typeof(Test), 16); diff --git a/src/tests/JIT/Methodical/refany/array1.csproj b/src/tests/JIT/Methodical/refany/array1.csproj deleted file mode 100644 index a99edb8b6dd2..000000000000 --- a/src/tests/JIT/Methodical/refany/array1.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/array2.cs b/src/tests/JIT/Methodical/refany/array2.cs index 843130a29055..9db5f90ef836 100644 --- a/src/tests/JIT/Methodical/refany/array2.cs +++ b/src/tests/JIT/Methodical/refany/array2.cs @@ -3,6 +3,7 @@ using System; using Xunit; +using TestLibrary; namespace JitTest_array2_refany_cs { @@ -23,6 +24,7 @@ private static void TestRef(TypedReference _ref) } [Fact] + [OuterLoop] public static int TestEntryPoint() { ulong[,] aul2 = new ulong[,] { { 1, 2, 3 }, { 4, 5, 6 } }; diff --git a/src/tests/JIT/Methodical/refany/array2.csproj b/src/tests/JIT/Methodical/refany/array2.csproj deleted file mode 100644 index 91b89ac31728..000000000000 --- a/src/tests/JIT/Methodical/refany/array2.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/array2.il b/src/tests/JIT/Methodical/refany/array2.il index 5e88f1b5c178..77ebee43c117 100644 --- a/src/tests/JIT/Methodical/refany/array2.il +++ b/src/tests/JIT/Methodical/refany/array2.il @@ -11,10 +11,13 @@ .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) .ver 4:0:0:0 } +.assembly extern System.Runtime { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) } .assembly ASSEMBLY_NAME { } .assembly extern xunit.core {} +.assembly extern Microsoft.DotNet.XUnitExtensions { .publickeytoken = (31 BF 38 56 AD 36 4E 35 ) } +.assembly extern TestLibrary {} // MVID: {1781A471-82F3-4159-8D0F-B3B5A9FF1BB6} .namespace JitTest_array2_refany_il { @@ -125,6 +128,22 @@ .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 ) + // [ActiveIssue("https://github.com/dotnet/runtimelab/issues/155", typeof(PlatformDetection), nameof(PlatformDetection.IsNonZeroLowerBoundArrayNotSupported))] + .custom instance void [Microsoft.DotNet.XUnitExtensions]Xunit.ActiveIssueAttribute::.ctor(string, + class [System.Runtime]System.Type, + string[]) = ( 01 00 2F 68 74 74 70 73 3A 2F 2F 67 69 74 68 75 + 62 2E 63 6F 6D 2F 64 6F 74 6E 65 74 2F 72 75 6E + 74 69 6D 65 6C 61 62 2F 69 73 73 75 65 73 2F 31 + 35 35 61 54 65 73 74 4C 69 62 72 61 72 79 2E 50 + 6C 61 74 66 6F 72 6D 44 65 74 65 63 74 69 6F 6E + 2C 20 54 65 73 74 4C 69 62 72 61 72 79 2C 20 56 + 65 72 73 69 6F 6E 3D 30 2E 30 2E 30 2E 30 2C 20 + 43 75 6C 74 75 72 65 3D 6E 65 75 74 72 61 6C 2C + 20 50 75 62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D + 6E 75 6C 6C 01 00 00 00 24 49 73 4E 6F 6E 5A 65 + 72 6F 4C 6F 77 65 72 42 6F 75 6E 64 41 72 72 61 + 79 4E 6F 74 53 75 70 70 6F 72 74 65 64 00 00 ) + .entrypoint // Code size 150 (0x96) .maxstack 4 diff --git a/src/tests/JIT/Methodical/refany/format.cs b/src/tests/JIT/Methodical/refany/format.cs index 7880066d4d9c..b7625e6577d1 100644 --- a/src/tests/JIT/Methodical/refany/format.cs +++ b/src/tests/JIT/Methodical/refany/format.cs @@ -280,6 +280,7 @@ private static void TestArrayElem() } [Fact] + [OuterLoop] public static void TestEntryPoint() { TestLocals(); diff --git a/src/tests/JIT/Methodical/refany/format.csproj b/src/tests/JIT/Methodical/refany/format.csproj deleted file mode 100644 index 56f6ee2365b2..000000000000 --- a/src/tests/JIT/Methodical/refany/format.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/gcreport_d.csproj b/src/tests/JIT/Methodical/refany/gcreport_d.csproj deleted file mode 100644 index 36cf222ae009..000000000000 --- a/src/tests/JIT/Methodical/refany/gcreport_d.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/gcreport_do.csproj b/src/tests/JIT/Methodical/refany/gcreport_do.csproj deleted file mode 100644 index 19254e125dc6..000000000000 --- a/src/tests/JIT/Methodical/refany/gcreport_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/refany/gcreport_r.csproj b/src/tests/JIT/Methodical/refany/gcreport_r.csproj deleted file mode 100644 index d54daedad74c..000000000000 --- a/src/tests/JIT/Methodical/refany/gcreport_r.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/gcreport_ro.csproj b/src/tests/JIT/Methodical/refany/gcreport_ro.csproj deleted file mode 100644 index 7230b78113e0..000000000000 --- a/src/tests/JIT/Methodical/refany/gcreport_ro.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/refany/lcs.cs b/src/tests/JIT/Methodical/refany/lcs.cs index 4aa60a26797d..fa77a57cee25 100644 --- a/src/tests/JIT/Methodical/refany/lcs.cs +++ b/src/tests/JIT/Methodical/refany/lcs.cs @@ -99,6 +99,7 @@ private static void findLCS( /*int[,,,]*/ TypedReference _c, } [Fact] + [OuterLoop] public static int TestEntryPoint() { String[] str = new String[RANK] { diff --git a/src/tests/JIT/Methodical/refany/lcs.csproj b/src/tests/JIT/Methodical/refany/lcs.csproj deleted file mode 100644 index 1cf5fa05ed4e..000000000000 --- a/src/tests/JIT/Methodical/refany/lcs.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/native.cs b/src/tests/JIT/Methodical/refany/native.cs index 70c37cf15c36..aab4ce1a498b 100644 --- a/src/tests/JIT/Methodical/refany/native.cs +++ b/src/tests/JIT/Methodical/refany/native.cs @@ -12,6 +12,7 @@ namespace JitTest public class Test { [Fact] + [OuterLoop] public static int TestEntryPoint() { int N = 0x1492; diff --git a/src/tests/JIT/Methodical/refany/native_d.csproj b/src/tests/JIT/Methodical/refany/native_d.csproj deleted file mode 100644 index 08c0a46f3fb8..000000000000 --- a/src/tests/JIT/Methodical/refany/native_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/native_do.csproj b/src/tests/JIT/Methodical/refany/native_do.csproj deleted file mode 100644 index 6adb8c4c120c..000000000000 --- a/src/tests/JIT/Methodical/refany/native_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/refany/native_r.csproj b/src/tests/JIT/Methodical/refany/native_r.csproj deleted file mode 100644 index 3dff54000215..000000000000 --- a/src/tests/JIT/Methodical/refany/native_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/native_ro.csproj b/src/tests/JIT/Methodical/refany/native_ro.csproj deleted file mode 100644 index 48eaa8815aa4..000000000000 --- a/src/tests/JIT/Methodical/refany/native_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/refany/stress1.cs b/src/tests/JIT/Methodical/refany/stress1.cs index 3cb80c2aeeb1..82bc5c2f1fff 100644 --- a/src/tests/JIT/Methodical/refany/stress1.cs +++ b/src/tests/JIT/Methodical/refany/stress1.cs @@ -48,6 +48,7 @@ private static void PackRef(TypedReference _ref, int iterCount) } [Fact] + [SkipOnCoreClr("This test is not compatible with GCStress.", RuntimeTestModes.AnyGCStress)] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/refany/stress1_d.csproj b/src/tests/JIT/Methodical/refany/stress1_d.csproj deleted file mode 100644 index 2b80632dbcaa..000000000000 --- a/src/tests/JIT/Methodical/refany/stress1_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - true - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/stress1_do.csproj b/src/tests/JIT/Methodical/refany/stress1_do.csproj deleted file mode 100644 index 977311b4a021..000000000000 --- a/src/tests/JIT/Methodical/refany/stress1_do.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/refany/stress1_r.csproj b/src/tests/JIT/Methodical/refany/stress1_r.csproj deleted file mode 100644 index 1e51910cd522..000000000000 --- a/src/tests/JIT/Methodical/refany/stress1_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - true - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/stress1_ro.csproj b/src/tests/JIT/Methodical/refany/stress1_ro.csproj deleted file mode 100644 index 972f3e4f8856..000000000000 --- a/src/tests/JIT/Methodical/refany/stress1_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - true - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/refany/stress3-64bit.cs b/src/tests/JIT/Methodical/refany/stress3-64bit.cs index 4aa0b261fdeb..42fbd1cf415b 100644 --- a/src/tests/JIT/Methodical/refany/stress3-64bit.cs +++ b/src/tests/JIT/Methodical/refany/stress3-64bit.cs @@ -29,6 +29,8 @@ private static void PackRef(ref String refee, int iterCount) } [Fact] + [OuterLoop] + [ActiveIssue("https://github.com/dotnet/runtime/issues/10478", TestPlatforms.AnyUnix)] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/refany/stress3_d.csproj b/src/tests/JIT/Methodical/refany/stress3_d.csproj deleted file mode 100644 index ae244aa8cb48..000000000000 --- a/src/tests/JIT/Methodical/refany/stress3_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/stress3_do.csproj b/src/tests/JIT/Methodical/refany/stress3_do.csproj deleted file mode 100644 index 5654ea15a645..000000000000 --- a/src/tests/JIT/Methodical/refany/stress3_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/refany/stress3_r.csproj b/src/tests/JIT/Methodical/refany/stress3_r.csproj deleted file mode 100644 index 033bc6848d3a..000000000000 --- a/src/tests/JIT/Methodical/refany/stress3_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/stress3_ro.csproj b/src/tests/JIT/Methodical/refany/stress3_ro.csproj deleted file mode 100644 index c681ac625550..000000000000 --- a/src/tests/JIT/Methodical/refany/stress3_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/refany/virtcall.cs b/src/tests/JIT/Methodical/refany/virtcall.cs index 6ec0cfc5d23d..064d28714146 100644 --- a/src/tests/JIT/Methodical/refany/virtcall.cs +++ b/src/tests/JIT/Methodical/refany/virtcall.cs @@ -42,6 +42,7 @@ public virtual void PackRef(TypedReference _ref, int iterCount) } [Fact] + [SkipOnCoreClr("This test is not compatible with GCStress.", RuntimeTestModes.AnyGCStress)] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/refany/virtcall_d.csproj b/src/tests/JIT/Methodical/refany/virtcall_d.csproj deleted file mode 100644 index b4973c02027e..000000000000 --- a/src/tests/JIT/Methodical/refany/virtcall_d.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - true - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/virtcall_do.csproj b/src/tests/JIT/Methodical/refany/virtcall_do.csproj deleted file mode 100644 index 439ca8929536..000000000000 --- a/src/tests/JIT/Methodical/refany/virtcall_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - true - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/refany/virtcall_r.csproj b/src/tests/JIT/Methodical/refany/virtcall_r.csproj deleted file mode 100644 index ca0f5ff04ead..000000000000 --- a/src/tests/JIT/Methodical/refany/virtcall_r.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - true - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/refany/virtcall_ro.csproj b/src/tests/JIT/Methodical/refany/virtcall_ro.csproj deleted file mode 100644 index 59006943cb28..000000000000 --- a/src/tests/JIT/Methodical/refany/virtcall_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - None - True - true - true - - - - - diff --git a/src/tests/JIT/Methodical/stringintern/_Simpleb207621.csproj b/src/tests/JIT/Methodical/stringintern/_Simpleb207621.csproj deleted file mode 100644 index e95053cbff6d..000000000000 --- a/src/tests/JIT/Methodical/stringintern/_Simpleb207621.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - PdbOnly - True - True - - - - - diff --git a/src/tests/JIT/Methodical/stringintern/_Simpletest1.csproj b/src/tests/JIT/Methodical/stringintern/_Simpletest1.csproj deleted file mode 100644 index 885d8b964e76..000000000000 --- a/src/tests/JIT/Methodical/stringintern/_Simpletest1.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - PdbOnly - - - - - - - diff --git a/src/tests/JIT/Methodical/stringintern/_Simpletest2.csproj b/src/tests/JIT/Methodical/stringintern/_Simpletest2.csproj deleted file mode 100644 index 294bc5404e97..000000000000 --- a/src/tests/JIT/Methodical/stringintern/_Simpletest2.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - PdbOnly - - - - - - - diff --git a/src/tests/JIT/Methodical/stringintern/_Simpletest4.csproj b/src/tests/JIT/Methodical/stringintern/_Simpletest4.csproj deleted file mode 100644 index 91751b297499..000000000000 --- a/src/tests/JIT/Methodical/stringintern/_Simpletest4.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - PdbOnly - - - - - - - diff --git a/src/tests/JIT/Methodical/stringintern/b207621.cs b/src/tests/JIT/Methodical/stringintern/b207621.cs index 9422d372b138..16fbc062ab14 100644 --- a/src/tests/JIT/Methodical/stringintern/b207621.cs +++ b/src/tests/JIT/Methodical/stringintern/b207621.cs @@ -14,6 +14,7 @@ private static string FooBar() } [Fact] + [OuterLoop] static public int TestEntryPoint() { string a = null; diff --git a/src/tests/JIT/Methodical/stringintern/test1-xassem.csproj b/src/tests/JIT/Methodical/stringintern/test1-xassem.csproj index 4ccd4eedc616..f1ced8e00b60 100644 --- a/src/tests/JIT/Methodical/stringintern/test1-xassem.csproj +++ b/src/tests/JIT/Methodical/stringintern/test1-xassem.csproj @@ -4,7 +4,6 @@ $(DefineConstants);XASSEM - False diff --git a/src/tests/JIT/Methodical/stringintern/test1.cs b/src/tests/JIT/Methodical/stringintern/test1.cs index ee8d7dd59692..24b48cddc079 100644 --- a/src/tests/JIT/Methodical/stringintern/test1.cs +++ b/src/tests/JIT/Methodical/stringintern/test1.cs @@ -99,6 +99,7 @@ public static bool TestSameObjRef() } [Fact] + [OuterLoop] public static int TestEntryPoint() { if (TestSameObjRef()) diff --git a/src/tests/JIT/Methodical/stringintern/test2-xassem.csproj b/src/tests/JIT/Methodical/stringintern/test2-xassem.csproj index 0086d9346587..b8b9cb076011 100644 --- a/src/tests/JIT/Methodical/stringintern/test2-xassem.csproj +++ b/src/tests/JIT/Methodical/stringintern/test2-xassem.csproj @@ -4,7 +4,6 @@ $(DefineConstants);XASSEM - False diff --git a/src/tests/JIT/Methodical/stringintern/test2.cs b/src/tests/JIT/Methodical/stringintern/test2.cs index 4c616a72c1fe..ca5215ca1f7c 100644 --- a/src/tests/JIT/Methodical/stringintern/test2.cs +++ b/src/tests/JIT/Methodical/stringintern/test2.cs @@ -125,6 +125,7 @@ public static bool TestSameObjRef() } [Fact] + [OuterLoop] public static int TestEntryPoint() { if (TestSameObjRef()) diff --git a/src/tests/JIT/Methodical/stringintern/test4-xassem.csproj b/src/tests/JIT/Methodical/stringintern/test4-xassem.csproj index 1f059ec1117d..61f17213c516 100644 --- a/src/tests/JIT/Methodical/stringintern/test4-xassem.csproj +++ b/src/tests/JIT/Methodical/stringintern/test4-xassem.csproj @@ -4,7 +4,6 @@ $(DefineConstants);XASSEM - False diff --git a/src/tests/JIT/Methodical/stringintern/test4.cs b/src/tests/JIT/Methodical/stringintern/test4.cs index 14771c2179f1..d6abacce4468 100644 --- a/src/tests/JIT/Methodical/stringintern/test4.cs +++ b/src/tests/JIT/Methodical/stringintern/test4.cs @@ -250,6 +250,7 @@ public static bool TestSameObjRef() } [Fact] + [OuterLoop] public static int TestEntryPoint() { if (TestSameObjRef()) diff --git a/src/tests/JIT/Methodical/stringintern/testgenstr.csproj b/src/tests/JIT/Methodical/stringintern/testgenstr.csproj index 0f6fe758008d..189b3800387b 100644 --- a/src/tests/JIT/Methodical/stringintern/testgenstr.csproj +++ b/src/tests/JIT/Methodical/stringintern/testgenstr.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/Methodical/stringintern/teststr.csproj b/src/tests/JIT/Methodical/stringintern/teststr.csproj index 1dd78a17ccd2..e5552d1c8206 100644 --- a/src/tests/JIT/Methodical/stringintern/teststr.csproj +++ b/src/tests/JIT/Methodical/stringintern/teststr.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/Methodical/structs/ExplicitLayout.cs b/src/tests/JIT/Methodical/structs/ExplicitLayout.cs index a41e4a165535..eafba1a5c878 100644 --- a/src/tests/JIT/Methodical/structs/ExplicitLayout.cs +++ b/src/tests/JIT/Methodical/structs/ExplicitLayout.cs @@ -29,6 +29,7 @@ internal unsafe struct TestStruct public class Program { [Fact] + [OuterLoop] public static int TestEntrypoint() { int returnVal = 100; diff --git a/src/tests/JIT/Methodical/structs/ExplicitLayout.csproj b/src/tests/JIT/Methodical/structs/ExplicitLayout.csproj deleted file mode 100644 index 50f1b02366fc..000000000000 --- a/src/tests/JIT/Methodical/structs/ExplicitLayout.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/structs/StructStackParams.csproj b/src/tests/JIT/Methodical/structs/StructStackParams.csproj deleted file mode 100644 index bf85249eecbe..000000000000 --- a/src/tests/JIT/Methodical/structs/StructStackParams.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - True - - - - - diff --git a/src/tests/JIT/Methodical/structs/StructWithSingleFloat.cs b/src/tests/JIT/Methodical/structs/StructWithSingleFloat.cs index efb41c0ff0b2..5c46d9f18c92 100644 --- a/src/tests/JIT/Methodical/structs/StructWithSingleFloat.cs +++ b/src/tests/JIT/Methodical/structs/StructWithSingleFloat.cs @@ -39,6 +39,7 @@ public void Method0() } } [Fact] + [OuterLoop] public static int TestEntryPoint() { new TestClass().Method0(); diff --git a/src/tests/JIT/Methodical/structs/StructWithSingleFloat.csproj b/src/tests/JIT/Methodical/structs/StructWithSingleFloat.csproj deleted file mode 100644 index 14a6b64107d4..000000000000 --- a/src/tests/JIT/Methodical/structs/StructWithSingleFloat.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - true - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/structs/systemvbringup/structinregs.csproj b/src/tests/JIT/Methodical/structs/systemvbringup/structinregs.csproj deleted file mode 100644 index d99fc34828d6..000000000000 --- a/src/tests/JIT/Methodical/structs/systemvbringup/structinregs.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - true - 1 - - - PdbOnly - True - - - - - - - - - - - - diff --git a/src/tests/JIT/Methodical/structs/systemvbringup/structpasstest.cs b/src/tests/JIT/Methodical/structs/systemvbringup/structpasstest.cs index cda27f8b7fca..07a01f449b8e 100644 --- a/src/tests/JIT/Methodical/structs/systemvbringup/structpasstest.cs +++ b/src/tests/JIT/Methodical/structs/systemvbringup/structpasstest.cs @@ -8,6 +8,7 @@ namespace structinreg public class Program { [Fact] + [OuterLoop] public static int TestEntryPoint() { try diff --git a/src/tests/JIT/Methodical/structs/valuetuple.cs b/src/tests/JIT/Methodical/structs/valuetuple.cs index 84a9e82544f4..e0b27ff9087b 100644 --- a/src/tests/JIT/Methodical/structs/valuetuple.cs +++ b/src/tests/JIT/Methodical/structs/valuetuple.cs @@ -79,6 +79,7 @@ public static int ConvertToRef3() } [Fact] + [OuterLoop] public static int TestEntryPoint() { int returnVal = Fail; diff --git a/src/tests/JIT/Methodical/structs/valuetuple.csproj b/src/tests/JIT/Methodical/structs/valuetuple.csproj deleted file mode 100644 index 897e36092ef9..000000000000 --- a/src/tests/JIT/Methodical/structs/valuetuple.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/tailcall/Desktop/thread-race.cs b/src/tests/JIT/Methodical/tailcall/Desktop/thread-race.cs index a8a728653d79..49fa175616e5 100644 --- a/src/tests/JIT/Methodical/tailcall/Desktop/thread-race.cs +++ b/src/tests/JIT/Methodical/tailcall/Desktop/thread-race.cs @@ -14,6 +14,9 @@ public class Repro private const int FibSeriesMin = 20; [Fact] + [SkipOnCoreClr("This test is not compatible with GCStress.", RuntimeTestModes.AnyGCStress)] + [SkipOnCoreClr("This test is not compatible with HeapVerify.", RuntimeTestModes.HeapVerify)] + [OuterLoop] public static int TestEntrypoint() { // Compute the expected value for a single thread diff --git a/src/tests/JIT/Methodical/tailcall/widen_r.csproj b/src/tests/JIT/Methodical/tailcall/widen_r.csproj deleted file mode 100644 index 2418344ad9a1..000000000000 --- a/src/tests/JIT/Methodical/tailcall/widen_r.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/tailcall_v4/delegateParamCallTarget.cs b/src/tests/JIT/Methodical/tailcall_v4/delegateParamCallTarget.cs index fff9cdcc88bd..94dd776b5814 100644 --- a/src/tests/JIT/Methodical/tailcall_v4/delegateParamCallTarget.cs +++ b/src/tests/JIT/Methodical/tailcall_v4/delegateParamCallTarget.cs @@ -2,18 +2,18 @@ // The .NET Foundation licenses this file to you under the MIT license. /* - * When generating the code for a tail call, the JIT was not careful to preserve any stack-based parameters used in the computation of the call target address if it is a simple indirection (like in the case of delegate.Invoke). - * Thus, in the case where an outgoing argument overwrites the same slot as the incoming delegate, the new value is used in the indirection to compute the target address. - * The fix is to not hoist any parameter uses when we hoist the indirection onto the call, and instead use tmpvars. This leaves the use of the parameter above the assignment to the slot for the outgoing tail call. In this one example it actually made the code better. - * - * Expected output: - * Accomplice - * Passed - * - * Actual output: - * Accomplice - * Failed - */ +* When generating the code for a tail call, the JIT was not careful to preserve any stack-based parameters used in the computation of the call target address if it is a simple indirection (like in the case of delegate.Invoke). +* Thus, in the case where an outgoing argument overwrites the same slot as the incoming delegate, the new value is used in the indirection to compute the target address. +* The fix is to not hoist any parameter uses when we hoist the indirection onto the call, and instead use tmpvars. This leaves the use of the parameter above the assignment to the slot for the outgoing tail call. In this one example it actually made the code better. +* +* Expected output: +* Accomplice +* Passed +* +* Actual output: +* Accomplice +* Failed +*/ using System; using Xunit; @@ -44,6 +44,7 @@ private int Accomplice(int a, int b, int c, DoIt d) } [Fact] + [OuterLoop] public static int TestEntryPoint() { Repro r = new Repro(); diff --git a/src/tests/JIT/Methodical/tailcall_v4/delegateParamCallTarget.csproj b/src/tests/JIT/Methodical/tailcall_v4/delegateParamCallTarget.csproj deleted file mode 100644 index bb32e20eb3ca..000000000000 --- a/src/tests/JIT/Methodical/tailcall_v4/delegateParamCallTarget.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - PdbOnly - True - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-0.cs b/src/tests/JIT/Methodical/unsafecsharp/unsafe-0.cs index ca9247909434..1db3f4a56236 100644 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-0.cs +++ b/src/tests/JIT/Methodical/unsafecsharp/unsafe-0.cs @@ -275,6 +275,7 @@ private static unsafe long test_392(B* pb1, B* pb2) return e[pb1 >= pb2 ? 0 : 1]; } [Fact] + [OuterLoop] public static unsafe int TestEntryPoint() { AA loc_x = new AA(0, 100); diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-0_d.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-0_d.csproj deleted file mode 100644 index 1719cfcfc59f..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-0_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - False - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-0_do.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-0_do.csproj deleted file mode 100644 index a412e3ed8249..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-0_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - True - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-0_r.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-0_r.csproj deleted file mode 100644 index 2fe91124b22a..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-0_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - False - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-0_ro.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-0_ro.csproj deleted file mode 100644 index 3302474bc91f..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-0_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - True - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-1.cs b/src/tests/JIT/Methodical/unsafecsharp/unsafe-1.cs index a592ee8ec62c..d3044ed56c32 100644 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-1.cs +++ b/src/tests/JIT/Methodical/unsafecsharp/unsafe-1.cs @@ -278,6 +278,7 @@ private static unsafe long test_393(B* pb) return pb + 1 > pb ? 100 : 101; } [Fact] + [OuterLoop] public static unsafe int TestEntryPoint() { AA loc_x = new AA(0, 100); diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-1_d.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-1_d.csproj deleted file mode 100644 index b4613009dc6d..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-1_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - False - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-1_do.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-1_do.csproj deleted file mode 100644 index 96c38e5903e5..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-1_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Full - True - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-1_r.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-1_r.csproj deleted file mode 100644 index ad988d6ff709..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-1_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - False - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-1_ro.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-1_ro.csproj deleted file mode 100644 index 91c3a48f7ffd..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-1_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - None - True - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-2.cs b/src/tests/JIT/Methodical/unsafecsharp/unsafe-2.cs index 0343874b7cc4..c73bb80e839f 100644 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-2.cs +++ b/src/tests/JIT/Methodical/unsafecsharp/unsafe-2.cs @@ -280,6 +280,7 @@ private static unsafe long test_394(B* pb1, B* pb2) return pb1 >= pb2 ? 100 : 101; } [Fact] + [OuterLoop] public static unsafe int TestEntryPoint() { AA loc_x = new AA(0, 100); diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-2_d.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-2_d.csproj deleted file mode 100644 index f61a840ad967..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-2_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - False - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-2_do.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-2_do.csproj deleted file mode 100644 index b11ec156eb4a..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-2_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - True - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-2_r.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-2_r.csproj deleted file mode 100644 index 175b2c51bca3..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-2_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - False - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-2_ro.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-2_ro.csproj deleted file mode 100644 index b12dd2b73089..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-2_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - True - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-3.cs b/src/tests/JIT/Methodical/unsafecsharp/unsafe-3.cs index b4ee43618ab4..d39691249865 100644 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-3.cs +++ b/src/tests/JIT/Methodical/unsafecsharp/unsafe-3.cs @@ -283,6 +283,7 @@ private static unsafe long test_395(B* pb) throw new Exception(); } [Fact] + [OuterLoop] public static unsafe int TestEntryPoint() { AA loc_x = new AA(0, 100); diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-3_d.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-3_d.csproj deleted file mode 100644 index 1834eb69ed2c..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-3_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - False - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-3_do.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-3_do.csproj deleted file mode 100644 index d76865529897..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-3_do.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Full - True - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-3_r.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-3_r.csproj deleted file mode 100644 index ce20d09ef772..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-3_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - False - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-3_ro.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-3_ro.csproj deleted file mode 100644 index 9885884b89bd..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-3_ro.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - None - True - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-4.cs b/src/tests/JIT/Methodical/unsafecsharp/unsafe-4.cs index 3cb1e9a76749..033f2d9698b3 100644 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-4.cs +++ b/src/tests/JIT/Methodical/unsafecsharp/unsafe-4.cs @@ -281,6 +281,7 @@ private static unsafe long test_396(B* pb1, B* pb2) throw new Exception(); } [Fact] + [OuterLoop] public static unsafe int TestEntryPoint() { AA loc_x = new AA(0, 100); diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-4_d.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-4_d.csproj deleted file mode 100644 index b7b994adf533..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-4_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - False - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-4_do.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-4_do.csproj deleted file mode 100644 index c8a92b3bb371..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-4_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - True - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-4_r.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-4_r.csproj deleted file mode 100644 index 1abae9f643ab..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-4_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - False - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-4_ro.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-4_ro.csproj deleted file mode 100644 index be9bd77feb58..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-4_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - True - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-5.cs b/src/tests/JIT/Methodical/unsafecsharp/unsafe-5.cs index 0ae9c80addf2..8b429157156c 100644 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-5.cs +++ b/src/tests/JIT/Methodical/unsafecsharp/unsafe-5.cs @@ -274,6 +274,7 @@ private static unsafe long test_390(long p, long s) return AA.get_bv1(((B*)((p >> 4) | s))) != 100 ? 99 : 100; } [Fact] + [OuterLoop] public static unsafe int TestEntryPoint() { AA loc_x = new AA(0, 100); diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-5_d.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-5_d.csproj deleted file mode 100644 index 9ab6c2216540..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-5_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - False - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-5_do.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-5_do.csproj deleted file mode 100644 index e5bd6952ffaa..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-5_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - True - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-5_r.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-5_r.csproj deleted file mode 100644 index 937f34feec88..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-5_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - False - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-5_ro.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-5_ro.csproj deleted file mode 100644 index e9563d26855f..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-5_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - True - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-6.cs b/src/tests/JIT/Methodical/unsafecsharp/unsafe-6.cs index 11e777a16de4..64d0f4025ecf 100644 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-6.cs +++ b/src/tests/JIT/Methodical/unsafecsharp/unsafe-6.cs @@ -277,6 +277,7 @@ private static unsafe long test_391(B* pb) return e[pb + 1 > pb ? 0 : 1]; } [Fact] + [OuterLoop] public static unsafe int TestEntryPoint() { AA loc_x = new AA(0, 100); diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-6_d.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-6_d.csproj deleted file mode 100644 index f3f03daa0c99..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-6_d.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - False - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-6_do.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-6_do.csproj deleted file mode 100644 index 1c4edc05859a..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-6_do.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - Full - True - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-6_r.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-6_r.csproj deleted file mode 100644 index 12bff34d57ff..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-6_r.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - False - True - - - - - - diff --git a/src/tests/JIT/Methodical/unsafecsharp/unsafe-6_ro.csproj b/src/tests/JIT/Methodical/unsafecsharp/unsafe-6_ro.csproj deleted file mode 100644 index d72331dd6a59..000000000000 --- a/src/tests/JIT/Methodical/unsafecsharp/unsafe-6_ro.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - None - True - True - - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/operand/refanyval.cs b/src/tests/JIT/Methodical/xxobj/operand/refanyval.cs index cfbf68c10e7f..3bbc82b325a0 100644 --- a/src/tests/JIT/Methodical/xxobj/operand/refanyval.cs +++ b/src/tests/JIT/Methodical/xxobj/operand/refanyval.cs @@ -48,6 +48,7 @@ private static int refanyval_stobj() } [Fact] + [OuterLoop] public static int TestEntryPoint() { if (refanyval_ldobj() != 0) diff --git a/src/tests/JIT/Methodical/xxobj/operand/refanyval_d.csproj b/src/tests/JIT/Methodical/xxobj/operand/refanyval_d.csproj deleted file mode 100644 index df5950fd4500..000000000000 --- a/src/tests/JIT/Methodical/xxobj/operand/refanyval_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/operand/refanyval_do.csproj b/src/tests/JIT/Methodical/xxobj/operand/refanyval_do.csproj deleted file mode 100644 index dae9ab27ba14..000000000000 --- a/src/tests/JIT/Methodical/xxobj/operand/refanyval_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/operand/refanyval_r.csproj b/src/tests/JIT/Methodical/xxobj/operand/refanyval_r.csproj deleted file mode 100644 index 6eff06539d42..000000000000 --- a/src/tests/JIT/Methodical/xxobj/operand/refanyval_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/operand/refanyval_ro.csproj b/src/tests/JIT/Methodical/xxobj/operand/refanyval_ro.csproj deleted file mode 100644 index aeb44d944523..000000000000 --- a/src/tests/JIT/Methodical/xxobj/operand/refanyval_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/operand/unbox.cs b/src/tests/JIT/Methodical/xxobj/operand/unbox.cs index ea8ef88fd9e4..a59951da504a 100644 --- a/src/tests/JIT/Methodical/xxobj/operand/unbox.cs +++ b/src/tests/JIT/Methodical/xxobj/operand/unbox.cs @@ -48,6 +48,7 @@ private static int unbox_stobj() } [Fact] + [OuterLoop] public static int TestEntryPoint() { if (unbox_ldobj() != 0) diff --git a/src/tests/JIT/Methodical/xxobj/operand/unbox_d.csproj b/src/tests/JIT/Methodical/xxobj/operand/unbox_d.csproj deleted file mode 100644 index c862911be386..000000000000 --- a/src/tests/JIT/Methodical/xxobj/operand/unbox_d.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - False - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/operand/unbox_do.csproj b/src/tests/JIT/Methodical/xxobj/operand/unbox_do.csproj deleted file mode 100644 index 854a071f9ef6..000000000000 --- a/src/tests/JIT/Methodical/xxobj/operand/unbox_do.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - Full - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/operand/unbox_r.csproj b/src/tests/JIT/Methodical/xxobj/operand/unbox_r.csproj deleted file mode 100644 index 7e1f510f0930..000000000000 --- a/src/tests/JIT/Methodical/xxobj/operand/unbox_r.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - False - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/operand/unbox_ro.csproj b/src/tests/JIT/Methodical/xxobj/operand/unbox_ro.csproj deleted file mode 100644 index eb5120668f7c..000000000000 --- a/src/tests/JIT/Methodical/xxobj/operand/unbox_ro.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - 1 - - - None - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof.cs b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof.cs index 065083dcdd8d..f8fc67fed398 100644 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof.cs +++ b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof.cs @@ -26,7 +26,7 @@ struct ComplexStruct SimpleStruct ss1; SimpleStruct ss2; } - + struct ComplexStruct2 { ComplexStruct x1; @@ -52,6 +52,7 @@ struct ComplexStruct2 public struct Test { [Fact] + [OuterLoop] public static unsafe int TestEntryPoint() { if (sizeof(SimpleStruct) != 32) diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32.cs b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32.cs index 31e653e5b429..f0969171449e 100644 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32.cs +++ b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32.cs @@ -30,6 +30,7 @@ internal struct RefComplexStruct public struct Test { [Fact] + [OuterLoop] public static unsafe int TestEntryPoint() { int l = (sbyte)sizeof(RefComplexStruct); diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32_d.csproj b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32_d.csproj deleted file mode 100644 index 9e0472b6df00..000000000000 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32_do.csproj b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32_do.csproj deleted file mode 100644 index 121b314588f4..000000000000 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32_r.csproj b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32_r.csproj deleted file mode 100644 index e5cb51ff3407..000000000000 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32_ro.csproj b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32_ro.csproj deleted file mode 100644 index 8f9ccff7daa4..000000000000 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof32_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64.cs b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64.cs index 47f518234cdf..227eddd6c948 100644 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64.cs +++ b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64.cs @@ -34,6 +34,7 @@ internal struct RefComplexStruct public struct Test { [Fact] + [OuterLoop] public static unsafe int TestEntryPoint() { long l = (sbyte)sizeof(RefComplexStruct); diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64_d.csproj b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64_d.csproj deleted file mode 100644 index 7c66e75306ae..000000000000 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64_d.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - Full - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64_do.csproj b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64_do.csproj deleted file mode 100644 index 2641e09ad514..000000000000 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64_r.csproj b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64_r.csproj deleted file mode 100644 index a3949cbd0117..000000000000 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64_r.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - None - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64_ro.csproj b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64_ro.csproj deleted file mode 100644 index d1893cc62c07..000000000000 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof64_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof_d.csproj b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof_d.csproj deleted file mode 100644 index b6230d5bf530..000000000000 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof_d.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof_do.csproj b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof_do.csproj deleted file mode 100644 index 312d72174783..000000000000 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof_do.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - Full - True - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof_r.csproj b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof_r.csproj deleted file mode 100644 index 4ec30ece03f8..000000000000 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof_r.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - False - True - True - True - - - - - diff --git a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof_ro.csproj b/src/tests/JIT/Methodical/xxobj/sizeof/sizeof_ro.csproj deleted file mode 100644 index cc1666c47bc3..000000000000 --- a/src/tests/JIT/Methodical/xxobj/sizeof/sizeof_ro.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - None - True - True - True - True - - - - - diff --git a/src/tests/JIT/Performance/CodeQuality/Benchstones/MDBenchI/MDGeneralArray/MDGeneralArray.cs b/src/tests/JIT/Performance/CodeQuality/Benchstones/MDBenchI/MDGeneralArray/MDGeneralArray.cs index 412e04d6f845..74f760ba06c3 100644 --- a/src/tests/JIT/Performance/CodeQuality/Benchstones/MDBenchI/MDGeneralArray/MDGeneralArray.cs +++ b/src/tests/JIT/Performance/CodeQuality/Benchstones/MDBenchI/MDGeneralArray/MDGeneralArray.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.CompilerServices; +using TestLibrary; using Xunit; namespace Benchstone.MDBenchI @@ -73,6 +74,7 @@ public static bool Test2() { } [Fact] + [ActiveIssue("https://github.com/dotnet/runtimelab/issues/155", typeof(PlatformDetection), nameof(PlatformDetection.IsNonZeroLowerBoundArrayNotSupported))] public static int TestEntryPoint() { bool result = Test() && Test2(); return (result ? 100 : -1); diff --git a/src/tests/JIT/Performance/CodeQuality/Benchstones/MDBenchI/MDGeneralArray/MDGeneralArray.csproj b/src/tests/JIT/Performance/CodeQuality/Benchstones/MDBenchI/MDGeneralArray/MDGeneralArray.csproj index c70b4831be6e..4c1999083022 100644 --- a/src/tests/JIT/Performance/CodeQuality/Benchstones/MDBenchI/MDGeneralArray/MDGeneralArray.csproj +++ b/src/tests/JIT/Performance/CodeQuality/Benchstones/MDBenchI/MDGeneralArray/MDGeneralArray.csproj @@ -4,6 +4,7 @@ true + diff --git a/src/tests/JIT/Regression/CLR-x86-EJIT/V1-M09.5-PDC/b14426/b14426.csproj b/src/tests/JIT/Regression/CLR-x86-EJIT/V1-M09.5-PDC/b14426/b14426.csproj index 25629ae88fc2..17ce8036e6a8 100644 --- a/src/tests/JIT/Regression/CLR-x86-EJIT/V1-M09.5-PDC/b14426/b14426.csproj +++ b/src/tests/JIT/Regression/CLR-x86-EJIT/V1-M09.5-PDC/b14426/b14426.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-EJIT/v1-m10/b02353/b02353.csproj b/src/tests/JIT/Regression/CLR-x86-EJIT/v1-m10/b02353/b02353.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-EJIT/v1-m10/b02353/b02353.csproj +++ b/src/tests/JIT/Regression/CLR-x86-EJIT/v1-m10/b02353/b02353.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b12053/b12053.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b12053/b12053.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b12053/b12053.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b12053/b12053.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b14066/b14066.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b14066/b14066.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b14066/b14066.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b14066/b14066.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b14077/b14077.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b14077/b14077.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b14077/b14077.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b14077/b14077.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b16345/b16345.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b16345/b16345.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b16345/b16345.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b16345/b16345.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b29456/b29456.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b29456/b29456.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b29456/b29456.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b29456/b29456.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b31150/b31150.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b31150/b31150.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b31150/b31150.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b31150/b31150.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b13621/b13621.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b13621/b13621.csproj index 7eda4b0278ce..a139a578ed1e 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b13621/b13621.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b13621/b13621.csproj @@ -5,10 +5,7 @@ true - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b13944/b13944.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b13944/b13944.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b13944/b13944.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b13944/b13944.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14228/b14228.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14228/b14228.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14228/b14228.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14228/b14228.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14323/b14323.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14323/b14323.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14323/b14323.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14323/b14323.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14475/b14475.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14475/b14475.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14475/b14475.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14475/b14475.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14779/b14779.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14779/b14779.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14779/b14779.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b14779/b14779.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b15307/b15307.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b15307/b15307.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b15307/b15307.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b15307/b15307.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b16102/b16102.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b16102/b16102.csproj index 27a209663bff..be344bcca244 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b16102/b16102.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M09/b16102/b16102.csproj @@ -8,10 +8,7 @@ false - PdbOnly - True - True 0 diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b04914/b04914.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b04914/b04914.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b04914/b04914.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b04914/b04914.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b07483/b07483.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b07483/b07483.csproj index de438cc04adc..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b07483/b07483.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b07483/b07483.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b08172/b08172.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b08172/b08172.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b08172/b08172.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b08172/b08172.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b09246/b09246.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b09246/b09246.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b09246/b09246.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M10/b09246/b09246.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b41990/b41990.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b41990/b41990.csproj index 25629ae88fc2..17ce8036e6a8 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b41990/b41990.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b41990/b41990.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b43313/Desktop/b43313_Desktop.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b43313/Desktop/b43313_Desktop.csproj index db0fd7c1d1b4..a53576e3cc6d 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b43313/Desktop/b43313_Desktop.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b43313/Desktop/b43313_Desktop.csproj @@ -1,6 +1,5 @@ - PdbOnly diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b43313/b43313.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b43313/b43313.csproj index 0aa420bd859b..197767e2c4e2 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b43313/b43313.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b43313/b43313.csproj @@ -1,7 +1,4 @@ - - - diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b11553/b11553.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b11553/b11553.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b11553/b11553.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b11553/b11553.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b51875/b51875.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b51875/b51875.csproj index 8b400c41eb51..4343e5ef8f07 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b51875/b51875.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b51875/b51875.csproj @@ -3,10 +3,6 @@ 1 - - - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b53547/b53547.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b53547/b53547.csproj index 6a586fef5502..51eb740fa8e3 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b53547/b53547.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b53547/b53547.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b55197/Desktop/b55197_Desktop.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b55197/Desktop/b55197_Desktop.csproj index a66d079bd6e4..695eeb305641 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b55197/Desktop/b55197_Desktop.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b55197/Desktop/b55197_Desktop.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b55197/b55197.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b55197/b55197.csproj index 7bf489d8955e..1e74cf137db1 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b55197/b55197.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b55197/b55197.csproj @@ -2,9 +2,6 @@ 1 - - - diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b56772/b56772.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b56772/b56772.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b56772/b56772.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b56772/b56772.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b60600/b60600.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b60600/b60600.csproj index 6a586fef5502..51eb740fa8e3 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b60600/b60600.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b60600/b60600.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b64579/b64579.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b64579/b64579.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b64579/b64579.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b64579/b64579.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b71005/b71005.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b71005/b71005.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b71005/b71005.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b71005/b71005.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b71093/b71093.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b71093/b71093.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b71093/b71093.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b71093/b71093.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72164/b72164.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72164/b72164.csproj index 6a586fef5502..51eb740fa8e3 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72164/b72164.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72164/b72164.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72422/b72422.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72422/b72422.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72422/b72422.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72422/b72422.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72687/b72687.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72687/b72687.csproj index 6a586fef5502..51eb740fa8e3 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72687/b72687.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72687/b72687.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72932/b72932.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72932/b72932.csproj index 6a586fef5502..51eb740fa8e3 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72932/b72932.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72932/b72932.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72986/b72986.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72986/b72986.csproj index 6a586fef5502..51eb740fa8e3 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72986/b72986.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b72986/b72986.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b76267/b76267.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b76267/b76267.csproj index 6a586fef5502..51eb740fa8e3 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b76267/b76267.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b76267/b76267.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b76511/b76511.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b76511/b76511.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b76511/b76511.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b76511/b76511.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b76717/b76717.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b76717/b76717.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b76717/b76717.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b76717/b76717.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b78694/b78694.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b78694/b78694.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b78694/b78694.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b78694/b78694.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b79642/b79642.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b79642/b79642.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b79642/b79642.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b79642/b79642.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b80764/b80764.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b80764/b80764.csproj index 6a586fef5502..51eb740fa8e3 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b80764/b80764.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b80764/b80764.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b81618/b81618.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b81618/b81618.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b81618/b81618.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b81618/b81618.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b82048/b82048.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b82048/b82048.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b82048/b82048.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b82048/b82048.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b83702/b83702.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b83702/b83702.csproj index 25629ae88fc2..17ce8036e6a8 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b83702/b83702.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b83702/b83702.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b113239/b113239.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b113239/b113239.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b113239/b113239.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b113239/b113239.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b87285/b87285.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b87285/b87285.csproj index 6a586fef5502..51eb740fa8e3 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b87285/b87285.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b87285/b87285.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b89797/b89797.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b89797/b89797.csproj index 6a586fef5502..51eb740fa8e3 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b89797/b89797.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b89797/b89797.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b92714/b92714.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b92714/b92714.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b92714/b92714.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b92714/b92714.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b99222/b99222.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b99222/b99222.csproj index 6a586fef5502..51eb740fa8e3 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b99222/b99222.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b99222/b99222.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b99235/b99235.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b99235/b99235.csproj index 6a586fef5502..51eb740fa8e3 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b99235/b99235.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1-M13-RTM/b99235/b99235.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1.1-M1-Beta1/b140902/b140902.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1.1-M1-Beta1/b140902/b140902.csproj index 6a586fef5502..51eb740fa8e3 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1.1-M1-Beta1/b140902/b140902.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1.1-M1-Beta1/b140902/b140902.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-Beta1/b103058/b103058.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-Beta1/b103058/b103058.csproj index 7d1e242545bb..2c9072bd446d 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-Beta1/b103058/b103058.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-Beta1/b103058/b103058.csproj @@ -5,10 +5,7 @@ 1 - PdbOnly - True - True True True True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-Beta1/b210352/csharpgenerictypes.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-Beta1/b210352/csharpgenerictypes.csproj index 4183d78879a9..e40021410397 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-Beta1/b210352/csharpgenerictypes.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-Beta1/b210352/csharpgenerictypes.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-Beta1/b210352/csharptester.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-Beta1/b210352/csharptester.csproj index 95f0c2689dd8..3d0e5445d9c4 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-Beta1/b210352/csharptester.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-Beta1/b210352/csharptester.csproj @@ -1,6 +1,5 @@ - PdbOnly diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b02762/b02762.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b02762/b02762.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b02762/b02762.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b02762/b02762.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b16570/b16570.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b16570/b16570.csproj index 8c086bb59ac7..3b050979669c 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b16570/b16570.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b16570/b16570.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M02/b00719/b00719.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M02/b00719/b00719.csproj index 25629ae88fc2..17ce8036e6a8 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M02/b00719/b00719.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M02/b00719/b00719.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M02/b31398/b31398.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M02/b31398/b31398.csproj index bbd6d65fec40..99d044cf9cbe 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M02/b31398/b31398.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M02/b31398/b31398.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V2.0-Beta2/b399444/b399444.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V2.0-Beta2/b399444/b399444.csproj index d8d7f80200bb..de4f07e83a8d 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V2.0-Beta2/b399444/b399444.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V2.0-Beta2/b399444/b399444.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V2.0-Beta2/b449827/b449827.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V2.0-Beta2/b449827/b449827.csproj index 119ebcd1d21e..4ee2e5892f22 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V2.0-Beta2/b449827/b449827.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V2.0-Beta2/b449827/b449827.csproj @@ -3,11 +3,8 @@ 1 - PdbOnly True - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V2.0-RTM/b491215/b491215.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V2.0-RTM/b491215/b491215.csproj index 3914985cff90..ff29f26fa7d2 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V2.0-RTM/b491215/b491215.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V2.0-RTM/b491215/b491215.csproj @@ -1,9 +1,5 @@ - - - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/dev10/b393481/b393481.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/dev10/b393481/b393481.csproj index def6cfae5561..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/dev10/b393481/b393481.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/dev10/b393481/b393481.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/dev10/b402701/b402701.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/dev10/b402701/b402701.csproj index c57fb3438e3a..377bf381b528 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/dev10/b402701/b402701.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/dev10/b402701/b402701.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/DDB/b188478/b188478.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/DDB/b188478/b188478.csproj index 119ebcd1d21e..4ee2e5892f22 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/DDB/b188478/b188478.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/DDB/b188478/b188478.csproj @@ -3,11 +3,8 @@ 1 - PdbOnly True - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/DDB/b19679/b19679.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/DDB/b19679/b19679.csproj index d17e3f51df6d..e29a7fdc7eb2 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/DDB/b19679/b19679.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/DDB/b19679/b19679.csproj @@ -1,10 +1,7 @@ - Full True - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/DDB/b202743/b202743.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/DDB/b202743/b202743.csproj index 7e6c2ca68972..ae039b8ee0de 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/DDB/b202743/b202743.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/DDB/b202743/b202743.csproj @@ -7,10 +7,8 @@ 1 - Full False - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/b152292/b152292.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/b152292/b152292.csproj index 0aa420bd859b..197767e2c4e2 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/b152292/b152292.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/b152292/b152292.csproj @@ -1,7 +1,4 @@ - - - diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/b569942/b569942.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/b569942/b569942.csproj index 119ebcd1d21e..4ee2e5892f22 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/b569942/b569942.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/v2.1/b569942/b569942.csproj @@ -3,11 +3,8 @@ 1 - PdbOnly True - True - True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/v2.2/ddb/ddb188478/DDB188478.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/v2.2/ddb/ddb188478/DDB188478.csproj index d8821366b3a0..2df83e68cc91 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/v2.2/ddb/ddb188478/DDB188478.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/v2.2/ddb/ddb188478/DDB188478.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/Dev11/External/Dev11_243742/dll.csproj b/src/tests/JIT/Regression/Dev11/External/Dev11_243742/dll.csproj index 6a13b1f10f88..c9a44a21d097 100644 --- a/src/tests/JIT/Regression/Dev11/External/Dev11_243742/dll.csproj +++ b/src/tests/JIT/Regression/Dev11/External/Dev11_243742/dll.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/Regression/Dev11/External/dev11_132534/CSharpPart_132534.csproj b/src/tests/JIT/Regression/Dev11/External/dev11_132534/CSharpPart_132534.csproj index 9bc370f66d6d..12059a1dd97c 100644 --- a/src/tests/JIT/Regression/Dev11/External/dev11_132534/CSharpPart_132534.csproj +++ b/src/tests/JIT/Regression/Dev11/External/dev11_132534/CSharpPart_132534.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly $(NoWarn),8002 diff --git a/src/tests/JIT/Regression/Dev11/External/dev11_145295/CSharpPart_145295.csproj b/src/tests/JIT/Regression/Dev11/External/dev11_145295/CSharpPart_145295.csproj index 1c791e914154..e8fdeb758110 100644 --- a/src/tests/JIT/Regression/Dev11/External/dev11_145295/CSharpPart_145295.csproj +++ b/src/tests/JIT/Regression/Dev11/External/dev11_145295/CSharpPart_145295.csproj @@ -3,7 +3,6 @@ 1 - Full True True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_1206929/DevDiv_1206929.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_1206929/DevDiv_1206929.csproj index e4faefb7ff90..03e6e186fec9 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_1206929/DevDiv_1206929.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_1206929/DevDiv_1206929.csproj @@ -3,7 +3,6 @@ 1 - True True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_142976/DevDiv_142976.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_142976/DevDiv_142976.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_142976/DevDiv_142976.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_142976/DevDiv_142976.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_150265/DevDiv_150265.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_150265/DevDiv_150265.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_150265/DevDiv_150265.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_150265/DevDiv_150265.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_168744/DevDiv_168744.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_168744/DevDiv_168744.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_168744/DevDiv_168744.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_168744/DevDiv_168744.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_200492/DevDiv_200492.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_200492/DevDiv_200492.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_200492/DevDiv_200492.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_200492/DevDiv_200492.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_255294/DevDiv_255294.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_255294/DevDiv_255294.csproj index 302871156174..2990adb09e01 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_255294/DevDiv_255294.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_255294/DevDiv_255294.csproj @@ -5,7 +5,6 @@ 1 - True true diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_278365/DevDiv_278365.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_278365/DevDiv_278365.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_278365/DevDiv_278365.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_278365/DevDiv_278365.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_278375/DevDiv_278375.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_278375/DevDiv_278375.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_278375/DevDiv_278375.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_278375/DevDiv_278375.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_278376/DevDiv_278376.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_278376/DevDiv_278376.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_278376/DevDiv_278376.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_278376/DevDiv_278376.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_278526/DevDiv_278526.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_278526/DevDiv_278526.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_278526/DevDiv_278526.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_278526/DevDiv_278526.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_280120/DevDiv_280120.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_280120/DevDiv_280120.csproj index c67fe98b045f..5ed04eb6afbf 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_280120/DevDiv_280120.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_280120/DevDiv_280120.csproj @@ -5,7 +5,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_280123/DevDiv_280123.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_280123/DevDiv_280123.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_280123/DevDiv_280123.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_280123/DevDiv_280123.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_280127/DevDiv_280127.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_280127/DevDiv_280127.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_280127/DevDiv_280127.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_280127/DevDiv_280127.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_283795/DevDiv_283795.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_283795/DevDiv_283795.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_283795/DevDiv_283795.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_283795/DevDiv_283795.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_284785/DevDiv_284785.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_284785/DevDiv_284785.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_284785/DevDiv_284785.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_284785/DevDiv_284785.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_288222/DevDiv_288222.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_288222/DevDiv_288222.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_288222/DevDiv_288222.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_288222/DevDiv_288222.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_461649/DevDiv_461649.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_461649/DevDiv_461649.csproj index aae41a38bff8..c59c26da4cf2 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_461649/DevDiv_461649.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_461649/DevDiv_461649.csproj @@ -4,7 +4,6 @@ true - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_468732/DevDiv_468732.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_468732/DevDiv_468732.csproj index e4faefb7ff90..03e6e186fec9 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_468732/DevDiv_468732.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_468732/DevDiv_468732.csproj @@ -3,7 +3,6 @@ 1 - True True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_541653/DevDiv_541653.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_541653/DevDiv_541653.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_541653/DevDiv_541653.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_541653/DevDiv_541653.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_543057/DevDiv_543057.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_543057/DevDiv_543057.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_543057/DevDiv_543057.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_543057/DevDiv_543057.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_543057a/DevDiv_543057a.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_543057a/DevDiv_543057a.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_543057a/DevDiv_543057a.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_543057a/DevDiv_543057a.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_545504/DevDiv_545504.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_545504/DevDiv_545504.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_545504/DevDiv_545504.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_545504/DevDiv_545504.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_546018/DevDiv_546018.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_546018/DevDiv_546018.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_546018/DevDiv_546018.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_546018/DevDiv_546018.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_590358/DevDiv_590358.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_590358/DevDiv_590358.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_590358/DevDiv_590358.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_590358/DevDiv_590358.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_714266/DevDiv_714266.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_714266/DevDiv_714266.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_714266/DevDiv_714266.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_714266/DevDiv_714266.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/DevDiv_718151/DevDiv_718151.csproj b/src/tests/JIT/Regression/JitBlue/DevDiv_718151/DevDiv_718151.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/DevDiv_718151/DevDiv_718151.csproj +++ b/src/tests/JIT/Regression/JitBlue/DevDiv_718151/DevDiv_718151.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_10215/GitHub_10215.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_10215/GitHub_10215.csproj index a04106372a50..3d229cfd723c 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_10215/GitHub_10215.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_10215/GitHub_10215.csproj @@ -5,7 +5,6 @@ false - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_10481/GitHub_10481.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_10481/GitHub_10481.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_10481/GitHub_10481.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_10481/GitHub_10481.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_10621/GitHub_10621.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_10621/GitHub_10621.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_10621/GitHub_10621.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_10621/GitHub_10621.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_10714/GitHub_10714.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_10714/GitHub_10714.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_10714/GitHub_10714.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_10714/GitHub_10714.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_10780/GitHub_10780.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_10780/GitHub_10780.csproj index e4faefb7ff90..03e6e186fec9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_10780/GitHub_10780.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_10780/GitHub_10780.csproj @@ -3,7 +3,6 @@ 1 - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_10940/GitHub_10940.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_10940/GitHub_10940.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_10940/GitHub_10940.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_10940/GitHub_10940.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_1133/GitHub_1133.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_1133/GitHub_1133.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_1133/GitHub_1133.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_1133/GitHub_1133.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_11343/GitHub_11343.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_11343/GitHub_11343.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_11343/GitHub_11343.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_11343/GitHub_11343.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_11407/GitHub_11407.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_11407/GitHub_11407.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_11407/GitHub_11407.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_11407/GitHub_11407.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_11408/GitHub_11408.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_11408/GitHub_11408.csproj index d8cac844f9fa..622a8679b8df 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_11408/GitHub_11408.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_11408/GitHub_11408.csproj @@ -4,7 +4,6 @@ true - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_1161/GitHub_1161.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_1161/GitHub_1161.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_1161/GitHub_1161.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_1161/GitHub_1161.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_11689/GitHub_11689.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_11689/GitHub_11689.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_11689/GitHub_11689.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_11689/GitHub_11689.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_11733/GitHub_11733.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_11733/GitHub_11733.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_11733/GitHub_11733.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_11733/GitHub_11733.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_11814/GitHub_11814.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_11814/GitHub_11814.csproj index e4faefb7ff90..03e6e186fec9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_11814/GitHub_11814.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_11814/GitHub_11814.csproj @@ -3,7 +3,6 @@ 1 - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_11816/GitHub_11816.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_11816/GitHub_11816.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_11816/GitHub_11816.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_11816/GitHub_11816.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_12037/GitHub_12037.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_12037/GitHub_12037.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_12037/GitHub_12037.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_12037/GitHub_12037.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_12392/GitHub_12392.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_12392/GitHub_12392.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_12392/GitHub_12392.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_12392/GitHub_12392.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_12398/Github_12398.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_12398/Github_12398.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_12398/Github_12398.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_12398/Github_12398.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_1.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_1.csproj index e4faefb7ff90..03e6e186fec9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_1.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_1.csproj @@ -3,7 +3,6 @@ 1 - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_2.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_2.csproj index e4faefb7ff90..03e6e186fec9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_2.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_2.csproj @@ -3,7 +3,6 @@ 1 - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_3.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_3.csproj index e4faefb7ff90..03e6e186fec9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_3.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_3.csproj @@ -3,7 +3,6 @@ 1 - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_4.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_4.csproj index e4faefb7ff90..03e6e186fec9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_4.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_4.csproj @@ -3,7 +3,6 @@ 1 - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_5.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_5.csproj index e4faefb7ff90..03e6e186fec9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_5.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_5.csproj @@ -3,7 +3,6 @@ 1 - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_6.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_6.csproj index e4faefb7ff90..03e6e186fec9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_6.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_6.csproj @@ -3,7 +3,6 @@ 1 - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_7.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_7.csproj index e4faefb7ff90..03e6e186fec9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_7.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_7.csproj @@ -3,7 +3,6 @@ 1 - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_8.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_8.csproj index e4faefb7ff90..03e6e186fec9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_8.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_8.csproj @@ -3,7 +3,6 @@ 1 - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_12950/GitHub_12950.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_12950/GitHub_12950.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_12950/GitHub_12950.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_12950/GitHub_12950.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_1296/GitHub_1296.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_1296/GitHub_1296.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_1296/GitHub_1296.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_1296/GitHub_1296.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_13056/GitHub_13056.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_13056/GitHub_13056.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_13056/GitHub_13056.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_13056/GitHub_13056.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_13057/GitHub_13057.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_13057/GitHub_13057.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_13057/GitHub_13057.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_13057/GitHub_13057.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_1323/GitHub_1323.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_1323/GitHub_1323.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_1323/GitHub_1323.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_1323/GitHub_1323.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_13486/GitHub_13486.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_13486/GitHub_13486.csproj index 69cc9d37063a..6f727749d6c3 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_13486/GitHub_13486.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_13486/GitHub_13486.csproj @@ -1,6 +1,5 @@ - False diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_13561/GitHub_13561.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_13561/GitHub_13561.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_13561/GitHub_13561.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_13561/GitHub_13561.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_13568/GitHub_13568.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_13568/GitHub_13568.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_13568/GitHub_13568.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_13568/GitHub_13568.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_13735/GitHub_13735.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_13735/GitHub_13735.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_13735/GitHub_13735.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_13735/GitHub_13735.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_13910/GitHub_13910.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_13910/GitHub_13910.csproj index aa5f81eb0d89..e7f3746f0d59 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_13910/GitHub_13910.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_13910/GitHub_13910.csproj @@ -4,7 +4,6 @@ true - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_13919/GitHub_13919.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_13919/GitHub_13919.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_13919/GitHub_13919.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_13919/GitHub_13919.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_14028/GitHub_14028.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_14028/GitHub_14028.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_14028/GitHub_14028.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_14028/GitHub_14028.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_14783/GitHub_14783.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_14783/GitHub_14783.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_14783/GitHub_14783.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_14783/GitHub_14783.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_15077/GitHub_15077.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_15077/GitHub_15077.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_15077/GitHub_15077.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_15077/GitHub_15077.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_15237/GitHub_15237.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_15237/GitHub_15237.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_15237/GitHub_15237.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_15237/GitHub_15237.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_15319/GitHub_15319.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_15319/GitHub_15319.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_15319/GitHub_15319.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_15319/GitHub_15319.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_15718/GitHub_15718.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_15718/GitHub_15718.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_15718/GitHub_15718.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_15718/GitHub_15718.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_16210/GitHub_16210_1.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_16210/GitHub_16210_1.csproj index 5c07f95aaa96..755e64fea260 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_16210/GitHub_16210_1.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_16210/GitHub_16210_1.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_16210/GitHub_16210_2.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_16210/GitHub_16210_2.csproj index 2d22793a7259..889a538c6f88 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_16210/GitHub_16210_2.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_16210/GitHub_16210_2.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_16210/GitHub_16210_3.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_16210/GitHub_16210_3.csproj index 1a3f495e1de3..17c87909ed4c 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_16210/GitHub_16210_3.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_16210/GitHub_16210_3.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_16254/GitHub_16254.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_16254/GitHub_16254.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_16254/GitHub_16254.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_16254/GitHub_16254.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_16377/GitHub_16377.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_16377/GitHub_16377.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_16377/GitHub_16377.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_16377/GitHub_16377.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_16443/GitHub_16443.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_16443/GitHub_16443.csproj index 69cc9d37063a..6f727749d6c3 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_16443/GitHub_16443.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_16443/GitHub_16443.csproj @@ -1,6 +1,5 @@ - False diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_16472/Github_16472.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_16472/Github_16472.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_16472/Github_16472.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_16472/Github_16472.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_17329/GitHub_17329.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_17329/GitHub_17329.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_17329/GitHub_17329.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_17329/GitHub_17329.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_17777/GitHub_17777.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_17777/GitHub_17777.csproj index 7f1127f274b5..bf31ce93fc0a 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_17777/GitHub_17777.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_17777/GitHub_17777.csproj @@ -6,7 +6,6 @@ true - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18232/GitHub_18232.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18232/GitHub_18232.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18232/GitHub_18232.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18232/GitHub_18232.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18235/GitHub_18235_1.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18235/GitHub_18235_1.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18235/GitHub_18235_1.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18235/GitHub_18235_1.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18235/GitHub_18235_2.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18235/GitHub_18235_2.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18235/GitHub_18235_2.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18235/GitHub_18235_2.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18259/GitHub_18259.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18259/GitHub_18259.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18259/GitHub_18259.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18259/GitHub_18259.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18332/GitHub_18332.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18332/GitHub_18332.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18332/GitHub_18332.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18332/GitHub_18332.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18362/GitHub_18362.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18362/GitHub_18362.csproj index d8cac844f9fa..622a8679b8df 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18362/GitHub_18362.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18362/GitHub_18362.csproj @@ -4,7 +4,6 @@ true - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18408/GitHub_18408.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18408/GitHub_18408.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18408/GitHub_18408.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18408/GitHub_18408.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18482/GitHub_18482.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18482/GitHub_18482.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18482/GitHub_18482.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18482/GitHub_18482.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18497/GitHub_18497.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18497/GitHub_18497.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18497/GitHub_18497.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18497/GitHub_18497.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_1.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_1.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_1.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_1.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_2.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_2.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_2.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_2.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_3.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_3.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_3.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_3.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_4.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_4.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_4.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_4.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_5.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_5.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_5.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_5.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_6.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_6.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_6.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_6.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_7.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_7.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_7.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_7.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_8.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_8.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_8.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_8.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18542/GitHub_18542.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18542/GitHub_18542.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18542/GitHub_18542.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18542/GitHub_18542.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18582/GitHub_18582.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18582/GitHub_18582.csproj index 1b1a956b59e2..6437d366de17 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18582/GitHub_18582.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18582/GitHub_18582.csproj @@ -5,7 +5,6 @@ 1 - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18672/GitHub_18672.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18672/GitHub_18672.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18672/GitHub_18672.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18672/GitHub_18672.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18770/GitHub_18770.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18770/GitHub_18770.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18770/GitHub_18770.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18770/GitHub_18770.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18780/GitHub_18780.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18780/GitHub_18780.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18780/GitHub_18780.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18780/GitHub_18780.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18867/GitHub_18867.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18867/GitHub_18867.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18867/GitHub_18867.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18867/GitHub_18867.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18884/GitHub_18884.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18884/GitHub_18884.csproj index d8cac844f9fa..622a8679b8df 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18884/GitHub_18884.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18884/GitHub_18884.csproj @@ -4,7 +4,6 @@ true - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_18887/GitHub_18887.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_18887/GitHub_18887.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_18887/GitHub_18887.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_18887/GitHub_18887.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_19022/GitHub_19022.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_19022/GitHub_19022.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_19022/GitHub_19022.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_19022/GitHub_19022.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_19149/GitHub_19149.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_19149/GitHub_19149.csproj index b5bf2d9a289f..ead44837892c 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_19149/GitHub_19149.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_19149/GitHub_19149.csproj @@ -1,6 +1,5 @@ - true True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_19397/GitHub_19397.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_19397/GitHub_19397.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_19397/GitHub_19397.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_19397/GitHub_19397.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_19438/GitHub_19438.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_19438/GitHub_19438.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_19438/GitHub_19438.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_19438/GitHub_19438.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_19444/GitHub_19444.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_19444/GitHub_19444.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_19444/GitHub_19444.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_19444/GitHub_19444.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_19599/GitHub_19599.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_19599/GitHub_19599.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_19599/GitHub_19599.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_19599/GitHub_19599.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_19910/GitHub_19910.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_19910/GitHub_19910.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_19910/GitHub_19910.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_19910/GitHub_19910.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_2003/GitHub_2003.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_2003/GitHub_2003.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_2003/GitHub_2003.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_2003/GitHub_2003.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_20651/GitHub_20651.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_20651/GitHub_20651.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_20651/GitHub_20651.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_20651/GitHub_20651.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_20838/GitHub_20838.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_20838/GitHub_20838.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_20838/GitHub_20838.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_20838/GitHub_20838.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_21231/GitHub_21231a.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_21231/GitHub_21231a.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_21231/GitHub_21231a.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_21231/GitHub_21231a.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_21231/GitHub_21231b.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_21231/GitHub_21231b.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_21231/GitHub_21231b.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_21231/GitHub_21231b.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_21295/GitHub_21295.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_21295/GitHub_21295.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_21295/GitHub_21295.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_21295/GitHub_21295.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_22583/GitHub_22583.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_22583/GitHub_22583.csproj index c1ef19436c2d..d82d44d64e78 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_22583/GitHub_22583.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_22583/GitHub_22583.csproj @@ -6,7 +6,6 @@ true - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_22583/base.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_22583/base.csproj index c79e857dfcac..12f9d9cdfeaa 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_22583/base.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_22583/base.csproj @@ -3,7 +3,6 @@ Library - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_22583/lib.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_22583/lib.csproj index cf2995e5a936..f398f3d91b5b 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_22583/lib.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_22583/lib.csproj @@ -3,7 +3,6 @@ Library - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_23530/GitHub_23530.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_23530/GitHub_23530.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_23530/GitHub_23530.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_23530/GitHub_23530.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_23545/GitHub_23545.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_23545/GitHub_23545.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_23545/GitHub_23545.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_23545/GitHub_23545.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_23794/GitHub_23794.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_23794/GitHub_23794.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_23794/GitHub_23794.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_23794/GitHub_23794.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_24159/GitHub_24159.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_24159/GitHub_24159.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_24159/GitHub_24159.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_24159/GitHub_24159.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_24657/GitHub_24657.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_24657/GitHub_24657.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_24657/GitHub_24657.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_24657/GitHub_24657.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_24846/GitHub_24846.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_24846/GitHub_24846.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_24846/GitHub_24846.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_24846/GitHub_24846.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_25020/GitHub_25020.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_25020/GitHub_25020.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_25020/GitHub_25020.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_25020/GitHub_25020.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_2580/GitHub_2580.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_2580/GitHub_2580.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_2580/GitHub_2580.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_2580/GitHub_2580.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_2610/GitHub_2610.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_2610/GitHub_2610.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_2610/GitHub_2610.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_2610/GitHub_2610.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_27027/GitHub_27027.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_27027/GitHub_27027.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_27027/GitHub_27027.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_27027/GitHub_27027.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_27551/GitHub_27551.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_27551/GitHub_27551.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_27551/GitHub_27551.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_27551/GitHub_27551.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_3449/GitHub_3449.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_3449/GitHub_3449.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_3449/GitHub_3449.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_3449/GitHub_3449.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_3539/GitHub_3539.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_3539/GitHub_3539.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_3539/GitHub_3539.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_3539/GitHub_3539.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_36614/GitHub_36614.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_36614/GitHub_36614.csproj index 77cf6476374a..aa296f5ef543 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_36614/GitHub_36614.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_36614/GitHub_36614.csproj @@ -4,7 +4,6 @@ true - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_36905/GitHub_36905.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_36905/GitHub_36905.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_36905/GitHub_36905.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_36905/GitHub_36905.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_4044/GitHub_4044.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_4044/GitHub_4044.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_4044/GitHub_4044.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_4044/GitHub_4044.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_4115/GitHub_4115.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_4115/GitHub_4115.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_4115/GitHub_4115.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_4115/GitHub_4115.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_5047/GitHub_5047.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_5047/GitHub_5047.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_5047/GitHub_5047.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_5047/GitHub_5047.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_5556/GitHub_5556.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_5556/GitHub_5556.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_5556/GitHub_5556.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_5556/GitHub_5556.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_5696/GitHub_5696.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_5696/GitHub_5696.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_5696/GitHub_5696.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_5696/GitHub_5696.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_6234/GitHub_6234.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_6234/GitHub_6234.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_6234/GitHub_6234.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_6234/GitHub_6234.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_6238/GitHub_6238.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_6238/GitHub_6238.csproj index c9d5463b8578..bd81775844b7 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_6238/GitHub_6238.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_6238/GitHub_6238.csproj @@ -3,7 +3,6 @@ 1 - False diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_6239/GitHub_6239.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_6239/GitHub_6239.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_6239/GitHub_6239.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_6239/GitHub_6239.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_6318/GitHub_6318.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_6318/GitHub_6318.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_6318/GitHub_6318.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_6318/GitHub_6318.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_6649/GitHub_6649.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_6649/GitHub_6649.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_6649/GitHub_6649.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_6649/GitHub_6649.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_7147/GitHub_7147.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_7147/GitHub_7147.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_7147/GitHub_7147.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_7147/GitHub_7147.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_7508/Vector3Test.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_7508/Vector3Test.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_7508/Vector3Test.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_7508/Vector3Test.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_7906/GitHub_7906.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_7906/GitHub_7906.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_7906/GitHub_7906.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_7906/GitHub_7906.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_8220/GitHub_8220.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_8220/GitHub_8220.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_8220/GitHub_8220.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_8220/GitHub_8220.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_8460/GitHub_8460.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_8460/GitHub_8460.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_8460/GitHub_8460.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_8460/GitHub_8460.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_8599/GitHub_8599.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_8599/GitHub_8599.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_8599/GitHub_8599.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_8599/GitHub_8599.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_9692/GitHub_9692.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_9692/GitHub_9692.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_9692/GitHub_9692.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_9692/GitHub_9692.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/GitHub_9891/GitHub_9891.csproj b/src/tests/JIT/Regression/JitBlue/GitHub_9891/GitHub_9891.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/GitHub_9891/GitHub_9891.csproj +++ b/src/tests/JIT/Regression/JitBlue/GitHub_9891/GitHub_9891.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_100809/Runtime_100809.cs b/src/tests/JIT/Regression/JitBlue/Runtime_100809/Runtime_100809.cs new file mode 100644 index 000000000000..eba4e112918c --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_100809/Runtime_100809.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using Xunit; + +public static class Runtime_100809 +{ + [Fact] + public static int TestEntryPoint() + { + return AlwaysFalse(96) ? -1 : 100; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool AlwaysFalse(int x) + { + var result = new byte[x]; + int count = result.Length - 2; + return (x < 0 || result.Length - count < 0); + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_100809/Runtime_100809.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_100809/Runtime_100809.csproj new file mode 100644 index 000000000000..6c8c63b83414 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_100809/Runtime_100809.csproj @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_101028/Runtime_101028.cs b/src/tests/JIT/Regression/JitBlue/Runtime_101028/Runtime_101028.cs new file mode 100644 index 000000000000..31b69aaffaf1 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_101028/Runtime_101028.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using Xunit; + +public class Runtime_101028 +{ + public static bool C1Run = false; + public static bool C2Run = false; + + [Fact] + public static int TestEntryPoint() + { + int x = 1234; + Foo(ref x); + if (!C1Run) + { + return 101; + } + + if (!C2Run) + { + return 102; + } + + return 100; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Foo(ref int x) + { + int value = x; + int calc = value / (C1.Value | -1); + int calc2 = value / (C2.Value | -1); + Consume(calc + calc2); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Consume(int value) + { + } + + static class C1 + { + public static int Value; + static C1() + { + C1Run = true; + } + } + + static class C2 + { + public static int Value; + static C2() + { + C2Run = true; + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_101028/Runtime_101028.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_101028/Runtime_101028.csproj new file mode 100644 index 000000000000..15edd99711a1 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_101028/Runtime_101028.csproj @@ -0,0 +1,8 @@ + + + True + + + + + \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_101034/Runtime_101034.cs b/src/tests/JIT/Regression/JitBlue/Runtime_101034/Runtime_101034.cs new file mode 100644 index 000000000000..751dceda1963 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_101034/Runtime_101034.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using Xunit; + +public static unsafe class Runtime_101034 +{ + [Fact] + public static void Test() + { + StructWithTwoShorts x = new() { ShortOne = -1, ShortTwo = -1 }; + StructWithThreeBytes y = default; + Problem(&x, &y); + Assert.True(y.ByteThree == 0); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static StructWithTwoShorts Problem(StructWithTwoShorts* s, StructWithThreeBytes* p) + { + StructWithTwoShorts y = *s; + + int z = 255; + ForceILLocal(&z); + if (z == 255) + { + y.ShortOne = 255; + } + else + { + y.ShortOne = 1; + } + + if (p != null) + { + int x = 255; + *p = Unsafe.As(ref x); + } + + return y; + } + + private static void ForceILLocal(void* x) { } + + struct StructWithTwoShorts + { + public short ShortOne; + public short ShortTwo; + } + + struct StructWithThreeBytes + { + public byte ByteOne; + public byte ByteTwo; + public byte ByteThree; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_101034/Runtime_101034.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_101034/Runtime_101034.csproj new file mode 100644 index 000000000000..de6d5e08882e --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_101034/Runtime_101034.csproj @@ -0,0 +1,8 @@ + + + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_101175/Runtime_101175.cs b/src/tests/JIT/Regression/JitBlue/Runtime_101175/Runtime_101175.cs new file mode 100644 index 000000000000..e1ac79c0971b --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_101175/Runtime_101175.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using Xunit; + +public static class Runtime_101175 +{ + [Fact] + public static void Test() + { + Activator.CreateInstance(typeof(Foo<>).MakeGenericType(typeof(object))); + } + + class Foo + { + public Foo() + { + if (new T[0].ToString() != "System.Object[]") + throw new Exception(); + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_101175/Runtime_101175.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_101175/Runtime_101175.csproj new file mode 100644 index 000000000000..de6d5e08882e --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_101175/Runtime_101175.csproj @@ -0,0 +1,8 @@ + + + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_101731/Runtime_101731.cs b/src/tests/JIT/Regression/JitBlue/Runtime_101731/Runtime_101731.cs new file mode 100644 index 000000000000..98c9f2a570ab --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_101731/Runtime_101731.cs @@ -0,0 +1,116 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using Xunit; + +public static class Runtime_101731 +{ + [Theory] + [InlineData(double.MaxValue)] + public static void TestConvertToInt32NativeDouble(double value) + { + Func func = double.ConvertToIntegerNative; + int expectedValue = double.ConvertToIntegerNative(value); + Assert.Equal(expectedValue, func(value)); + } + + [Theory] + [InlineData(float.MaxValue)] + public static void TestConvertToInt32NativeSingle(float value) + { + Func func = float.ConvertToIntegerNative; + int expectedValue = float.ConvertToIntegerNative(value); + Assert.Equal(expectedValue, func(value)); + } + + [Theory] + [InlineData(double.MaxValue)] + public static void TestConvertToInt64NativeDouble(double value) + { + Func func = double.ConvertToIntegerNative; + long expectedValue = double.ConvertToIntegerNative(value); + Assert.Equal(expectedValue, func(value)); + } + + [Theory] + [InlineData(float.MaxValue)] + public static void TestConvertToInt64NativeSingle(float value) + { + Func func = float.ConvertToIntegerNative; + long expectedValue = float.ConvertToIntegerNative(value); + Assert.Equal(expectedValue, func(value)); + } + + [Theory] + [InlineData(double.MaxValue)] + public static void TestConvertToUInt32NativeDouble(double value) + { + Func func = double.ConvertToIntegerNative; + uint expectedValue = double.ConvertToIntegerNative(value); + Assert.Equal(expectedValue, func(value)); + } + + [Theory] + [InlineData(float.MaxValue)] + public static void TestConvertToUInt32NativeSingle(float value) + { + Func func = float.ConvertToIntegerNative; + uint expectedValue = float.ConvertToIntegerNative(value); + Assert.Equal(expectedValue, func(value)); + } + + [Theory] + [InlineData(double.MaxValue)] + public static void TestConvertToUInt64NativeDouble(double value) + { + Func func = double.ConvertToIntegerNative; + ulong expectedValue = double.ConvertToIntegerNative(value); + Assert.Equal(expectedValue, func(value)); + } + + [Theory] + [InlineData(float.MaxValue)] + public static void TestConvertToUInt64NativeSingle(float value) + { + Func func = float.ConvertToIntegerNative; + ulong expectedValue = float.ConvertToIntegerNative(value); + Assert.Equal(expectedValue, func(value)); + } + + [Theory] + [InlineData(5)] + public static void TestReciprocalEstimateDouble(double value) + { + Func func = double.ReciprocalEstimate; + double expectedValue = double.ReciprocalEstimate(value); + Assert.Equal(expectedValue, func(value)); + } + + [Theory] + [InlineData(5)] + public static void TestReciprocalEstimateSingle(float value) + { + Func func = float.ReciprocalEstimate; + float expectedValue = float.ReciprocalEstimate(value); + Assert.Equal(expectedValue, func(value)); + } + + [Theory] + [InlineData(-double.Epsilon)] + public static void TestReciprocalSqrtEstimateDouble(double value) + { + Func func = double.ReciprocalSqrtEstimate; + double expectedValue = double.ReciprocalSqrtEstimate(value); + Assert.Equal(expectedValue, func(value)); + } + + [Theory] + [InlineData(-float.Epsilon)] + public static void TestReciprocalSqrtEstimateSingle(float value) + { + Func func = float.ReciprocalSqrtEstimate; + float expectedValue = float.ReciprocalSqrtEstimate(value); + Assert.Equal(expectedValue, func(value)); + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_101731/Runtime_101731.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_101731/Runtime_101731.csproj new file mode 100644 index 000000000000..de6d5e08882e --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_101731/Runtime_101731.csproj @@ -0,0 +1,8 @@ + + + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_102149/Runtime_102149.cs b/src/tests/JIT/Regression/JitBlue/Runtime_102149/Runtime_102149.cs new file mode 100644 index 000000000000..038f61d1b14e --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_102149/Runtime_102149.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using Xunit; + +public static class Runtime_102149 +{ + [Fact] + public static void Test() + { + if (BitConverter.DoubleToUInt64Bits(U8_to_R8(Const(9303915604039947368UL))) != 4890948523238023291UL) + throw new InvalidOperationException("Case 1 failed"); + + if (BitConverter.DoubleToUInt64Bits((double)Const(9303915604039947368UL)) != 4890948523238023291UL) + throw new InvalidOperationException("Case 2 failed"); + + if (NonConst(10648738977740919977d) != NonConst(10648738977740919977UL)) + throw new InvalidOperationException("Case 3 failed"); + + if (Const(10648738977740919977d) != Const(10648738977740919977UL)) + throw new InvalidOperationException("Case 4 failed"); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T Const(T val) => val; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static T NonConst(T val) => val; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static double U8_to_R8(ulong x) => x; +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_102149/Runtime_102149.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_102149/Runtime_102149.csproj new file mode 100644 index 000000000000..de6d5e08882e --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_102149/Runtime_102149.csproj @@ -0,0 +1,8 @@ + + + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_1102138/Runtime_102138.cs b/src/tests/JIT/Regression/JitBlue/Runtime_1102138/Runtime_102138.cs new file mode 100644 index 000000000000..d534090154a1 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_1102138/Runtime_102138.cs @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using Xunit; + +// Generated by Fuzzlyn v1.6 on 2024-05-12 19:09:35 +// Run on X86 Windows +// Seed: 9851999836185511275 +// Reduced from 93.1 KiB to 0.8 KiB in 00:03:30 +// Debug: Runs successfully +// Release: Throws 'System.NullReferenceException' + +public class C0 +{ +} + +public struct S0 +{ + public C0 F0; + public C0 F1; +} + +public struct S1 +{ + public C0 F1; + public S0 F2; + public C0 F3; +} + +public struct S2 +{ + public S1 F4; +} + +public struct S3 +{ + public S2 F0; +} + +public struct S5 +{ + public int F0; +} + +public class Runtime_102138 +{ + public static S3 s_10; + public static byte[] s_11; + + [Fact] + public static void TestEntryPoint() + { + var vr3 = new short[][][]{new short[][]{new short[]{0}}}; + var vr8 = new S5(); + s_10 = M8(vr8, ref s_11, vr3); + } + + public static ref S3 M8(S5 argThis, ref byte[] arg0, short[][][] arg1) + { + arg1[0] = new short[][]{new short[]{0}}; + return ref s_10; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_1102138/Runtime_102138.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_1102138/Runtime_102138.csproj new file mode 100644 index 000000000000..de6d5e08882e --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_1102138/Runtime_102138.csproj @@ -0,0 +1,8 @@ + + + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_1241/Runtime_1241.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_1241/Runtime_1241.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_1241/Runtime_1241.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_1241/Runtime_1241.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_13417/Runtime_13417.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_13417/Runtime_13417.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_13417/Runtime_13417.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_13417/Runtime_13417.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_13669/Runtime_13669.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_13669/Runtime_13669.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_13669/Runtime_13669.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_13669/Runtime_13669.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_31673/Runtime_31673.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_31673/Runtime_31673.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_31673/Runtime_31673.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_31673/Runtime_31673.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_34170/Runtime_34170.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_34170/Runtime_34170.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_34170/Runtime_34170.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_34170/Runtime_34170.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.csproj index 97a94f113847..5f7776bf6f49 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_34937/Runtime_34937.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_34937/Runtime_34937.csproj index 9a726192cd74..970ebc046a16 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_34937/Runtime_34937.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_34937/Runtime_34937.csproj @@ -4,7 +4,6 @@ true - True True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_35144/Runtime_35144.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_35144/Runtime_35144.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_35144/Runtime_35144.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_35144/Runtime_35144.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_35724/Runtime_35724.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_35724/Runtime_35724.csproj index 72a60b051fc6..e562d2d441d9 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_35724/Runtime_35724.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_35724/Runtime_35724.csproj @@ -3,7 +3,6 @@ 1 - True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_35976/Runtime_35976.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_35976/Runtime_35976.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_35976/Runtime_35976.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_35976/Runtime_35976.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_36468/Runtime_36468.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_36468/Runtime_36468.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_36468/Runtime_36468.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_36468/Runtime_36468.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_36584/Runtime_36584.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_36584/Runtime_36584.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_36584/Runtime_36584.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_36584/Runtime_36584.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_39403/Runtime_39403.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_39403/Runtime_39403.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_39403/Runtime_39403.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_39403/Runtime_39403.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_39737/Runtime_39737.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_39737/Runtime_39737.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_39737/Runtime_39737.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_39737/Runtime_39737.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_40440/Runtime_40440.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_40440/Runtime_40440.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_40440/Runtime_40440.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_40440/Runtime_40440.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_40444/Runtime_40444.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_40444/Runtime_40444.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_40444/Runtime_40444.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_40444/Runtime_40444.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.csproj index 31ff4e84636a..26453f8c5e2f 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.csproj @@ -4,7 +4,6 @@ true - True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_72845/Runtime_72845.fsproj b/src/tests/JIT/Regression/JitBlue/Runtime_72845/Runtime_72845.fsproj index 4ecbaba4ff43..6235ab0c3ab5 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_72845/Runtime_72845.fsproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_72845/Runtime_72845.fsproj @@ -2,11 +2,12 @@ true - True - True True $(NetCoreAppToolCurrent) True + + + true diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_73615/Runtime_73615.cs b/src/tests/JIT/Regression/JitBlue/Runtime_73615/Runtime_73615.cs new file mode 100644 index 000000000000..ccca99fb956c --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_73615/Runtime_73615.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Reference source for Runtime_73615.il. + +using InlineIL; +using System; +using System.Runtime.CompilerServices; +using Xunit; + +public class Runtime_73615 +{ + [Fact] + public static int TestEntryPoint() + { + Foo(new C(101)); + return Result; + } + + public static int Result; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Foo(C arg) + { + IL.Emit.Ldarga(nameof(arg)); + IL.Emit.Ldarga(nameof(arg)); + IL.Emit.Call(new MethodRef(typeof(Runtime_73615), nameof(Bar))); + IL.Emit.Constrained(); + IL.Emit.Callvirt(new MethodRef(typeof(C), nameof(arg.Baz))); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static int Bar(ref C o) + { + o = new C(100); + return 0; + } + + public class C + { + public C(int result) => Result = result; + public int Result; + + [MethodImpl(MethodImplOptions.NoInlining)] + public void Baz(int arg) + { + Runtime_73615.Result = Result; + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_73615/Runtime_73615.il b/src/tests/JIT/Regression/JitBlue/Runtime_73615/Runtime_73615.il new file mode 100644 index 000000000000..261d8f25f84b --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_73615/Runtime_73615.il @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern System.Runtime { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) } +.assembly extern xunit.core { } +.assembly extern System.Console { } + +.assembly Runtime_73615 { } + +.class public auto ansi beforefieldinit Runtime_73615 + extends [System.Runtime]System.Object +{ + .class auto ansi nested public beforefieldinit C + extends [System.Runtime]System.Object + { + .field public int32 Result + .method public hidebysig specialname rtspecialname + instance void .ctor(int32 result) cil managed + { + // Code size 14 (0xe) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [System.Runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 Runtime_73615/C::Result + IL_000d: ret + } // end of method C::.ctor + + .method public hidebysig instance void + Baz(int32 arg) cil managed noinlining + { + // Code size 12 (0xc) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 Runtime_73615/C::Result + IL_0006: stsfld int32 Runtime_73615::Result + IL_000b: ret + } // end of method C::Baz + + } // end of class C + + .field public static int32 Result + .method public hidebysig static int32 Main() cil managed + { + .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( 01 00 00 00 ) + .entrypoint + // Code size 18 (0x12) + .maxstack 8 + IL_0000: ldc.i4.s 101 + IL_0002: newobj instance void Runtime_73615/C::.ctor(int32) + IL_0007: call void Runtime_73615::Foo(class Runtime_73615/C) + IL_000c: ldsfld int32 Runtime_73615::Result + IL_0011: ret + } // end of method Runtime_73615::TestEntryPoint + + .method private hidebysig static void Foo(class Runtime_73615/C arg) cil managed noinlining + { + // Code size 21 (0x15) + .maxstack 2 + IL_0000: ldarga.s arg + IL_0002: ldarga.s arg + IL_0004: call int32 Runtime_73615::Bar(class Runtime_73615/C&) + IL_0009: constrained. Runtime_73615/C + IL_000f: callvirt instance void Runtime_73615/C::Baz(int32) + IL_0014: ret + } // end of method Runtime_73615::Foo + + .method private hidebysig static int32 + Bar(class Runtime_73615/C& o) cil managed noinlining + { + // Code size 11 (0xb) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.s 100 + IL_0003: newobj instance void Runtime_73615/C::.ctor(int32) + IL_0008: stind.ref + IL_0009: ldc.i4.0 + IL_000a: ret + } // end of method Runtime_73615::Bar + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [System.Runtime]System.Object::.ctor() + IL_0006: ret + } // end of method Runtime_73615::.ctor + +} // end of class Runtime_73615 diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_73615/Runtime_73615.ilproj b/src/tests/JIT/Regression/JitBlue/Runtime_73615/Runtime_73615.ilproj new file mode 100644 index 000000000000..5fa250452852 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_73615/Runtime_73615.ilproj @@ -0,0 +1,8 @@ + + + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_82291/Runtime_82291.cs b/src/tests/JIT/Regression/JitBlue/Runtime_82291/Runtime_82291.cs new file mode 100644 index 000000000000..6432672d45ca --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_82291/Runtime_82291.cs @@ -0,0 +1,42 @@ +using System; +using System.Runtime.CompilerServices; +using Xunit; + +public class Runtime_82291 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + static bool GetValueOrNull() + { + if (default(T) != null) + return true; + + return false; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static bool GetValueOrNullSlow() + { + if (default(T) != null) + return false; + + return false; + } + + + [MethodImpl(MethodImplOptions.NoInlining)] + static void GetValueOrNullSlow2() + { + if (default(T) != null) + return; + + return; + } + + [Fact] + public static void Test() + { + GetValueOrNull(); + GetValueOrNullSlow(); + GetValueOrNullSlow2(); + } +} \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_82291/Runtime_82291.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_82291/Runtime_82291.csproj new file mode 100644 index 000000000000..197767e2c4e2 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_82291/Runtime_82291.csproj @@ -0,0 +1,5 @@ + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_87393/Runtime_87393.fsproj b/src/tests/JIT/Regression/JitBlue/Runtime_87393/Runtime_87393.fsproj index 01cde35672f6..a61c916b3b87 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_87393/Runtime_87393.fsproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_87393/Runtime_87393.fsproj @@ -2,8 +2,6 @@ true - True - True True $(NetCoreAppToolCurrent) True diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_94467/Runtime_94467.cs b/src/tests/JIT/Regression/JitBlue/Runtime_94467/Runtime_94467.cs new file mode 100644 index 000000000000..85aa6e62655d --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_94467/Runtime_94467.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using Xunit; + +public static class Runtime_94467 +{ + public interface ITypeChecker + { + static abstract bool Test(T value); + } + + public interface IHandler + { + bool Test(T value); + } + + public struct TypeChecker : ITypeChecker + { + public static bool Test(T value) => true; + } + + public class Handler : IHandler where TChecker : ITypeChecker + { + public bool Test(T value) => TChecker.Test(value); + } + + public static IHandler GetHandler() => new Handler(); + + [Fact] + public static int Test() + { + try { + var handler = GetHandler(); + if (handler.Test(true) && handler.Test(true)) + return 100; + else + return 101; + } catch (Exception) { + return -1; + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_94467/Runtime_94467.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_94467/Runtime_94467.csproj new file mode 100644 index 000000000000..15edd99711a1 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_94467/Runtime_94467.csproj @@ -0,0 +1,8 @@ + + + True + + + + + \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/WPF_3226/CSharpRepro/WPF_3226.csproj b/src/tests/JIT/Regression/JitBlue/WPF_3226/CSharpRepro/WPF_3226.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/Regression/JitBlue/WPF_3226/CSharpRepro/WPF_3226.csproj +++ b/src/tests/JIT/Regression/JitBlue/WPF_3226/CSharpRepro/WPF_3226.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/Regression/VS-ia64-JIT/V1.2-M02/b108129/b108129.csproj b/src/tests/JIT/Regression/VS-ia64-JIT/V1.2-M02/b108129/b108129.csproj index f3c93cec4281..f8901585d65c 100644 --- a/src/tests/JIT/Regression/VS-ia64-JIT/V1.2-M02/b108129/b108129.csproj +++ b/src/tests/JIT/Regression/VS-ia64-JIT/V1.2-M02/b108129/b108129.csproj @@ -5,10 +5,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/VS-ia64-JIT/V1.2-M02/b15539/b15539.csproj b/src/tests/JIT/Regression/VS-ia64-JIT/V1.2-M02/b15539/b15539.csproj index 43a783077f58..26846f115155 100644 --- a/src/tests/JIT/Regression/VS-ia64-JIT/V1.2-M02/b15539/b15539.csproj +++ b/src/tests/JIT/Regression/VS-ia64-JIT/V1.2-M02/b15539/b15539.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True diff --git a/src/tests/JIT/Regression/clr-x64-JIT/v2.1/b601838/b601838.csproj b/src/tests/JIT/Regression/clr-x64-JIT/v2.1/b601838/b601838.csproj index de438cc04adc..e3c43ccd5605 100644 --- a/src/tests/JIT/Regression/clr-x64-JIT/v2.1/b601838/b601838.csproj +++ b/src/tests/JIT/Regression/clr-x64-JIT/v2.1/b601838/b601838.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/SIMD/VectorConvert.cs b/src/tests/JIT/SIMD/VectorConvert.cs index 9bd57b940089..6c1c4628bbb6 100644 --- a/src/tests/JIT/SIMD/VectorConvert.cs +++ b/src/tests/JIT/SIMD/VectorConvert.cs @@ -147,8 +147,9 @@ public static int VectorConvertSingleInt(Vector A) int returnVal = Pass; for (int i = 0; i < Vector.Count; i++) { - Int32 int32Val = (Int32)A[i]; + Int32 int32Val = float.ConvertToInteger(A[i]); Single cvtSglVal = (Single)int32Val; + if (B[i] != int32Val) { Console.WriteLine("B[" + i + "] = " + B[i] + ", int32Val = " + int32Val); @@ -171,8 +172,9 @@ public static int VectorConvertSingleUInt(Vector A) int returnVal = Pass; for (int i = 0; i < Vector.Count; i++) { - UInt32 uint32Val = (UInt32)A[i]; + UInt32 uint32Val = float.ConvertToInteger(A[i]); Single cvtSglVal = (Single)uint32Val; + if ((B[i] != uint32Val) || (C[i] != cvtSglVal)) { Console.WriteLine("A[{0}] = {1}, B[{0}] = {2}, C[{0}] = {3}, uint32Val = {4}, cvtSglVal = {5}", @@ -191,8 +193,9 @@ public static int VectorConvertDoubleInt64(Vector A) int returnVal = Pass; for (int i = 0; i < Vector.Count; i++) { - Int64 int64Val = (Int64)A[i]; + Int64 int64Val = double.ConvertToInteger(A[i]); Double cvtDblVal = (Double)int64Val; + if (B[i] != int64Val) { Console.WriteLine("B[" + i + "] = " + B[i] + ", int64Val = " + int64Val); @@ -215,8 +218,9 @@ public static int VectorConvertDoubleUInt64(Vector A) int returnVal = Pass; for (int i = 0; i < Vector.Count; i++) { - UInt64 uint64Val = (UInt64)A[i]; + UInt64 uint64Val = double.ConvertToInteger(A[i]); Double cvtDblVal = (Double)uint64Val; + if ((B[i] != uint64Val) || (C[i] != cvtDblVal)) { Console.WriteLine("A[{0}] = {1}, B[{0}] = {2}, C[{0}] = {3}, uint64Val = {4}, cvtDblVal = {5}", @@ -340,7 +344,7 @@ public static int VectorConvertInt32And16(Vector A1, Vector A2) } return returnVal; } - + public static int VectorConvertInt16And8(Vector A1, Vector A2) { Vector B = Vector.Narrow(A1, A2); @@ -378,7 +382,7 @@ public static int VectorConvertInt16And8(Vector A1, Vector A2) } return returnVal; } - + public static int VectorConvertUInt64And32(Vector A1, Vector A2) { Vector B = Vector.Narrow(A1, A2); @@ -454,7 +458,7 @@ public static int VectorConvertUInt32And16(Vector A1, Vector A2) } return returnVal; } - + public static int VectorConvertUInt16And8(Vector A1, Vector A2) { Vector B = Vector.Narrow(A1, A2); @@ -495,6 +499,7 @@ public static int VectorConvertUInt16And8(Vector A1, Vector A2) } [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] public static int TestEntryPoint() { int returnVal = Pass; @@ -508,7 +513,7 @@ public static int TestEntryPoint() returnVal = Fail; } } - + for (int i = 0; i < 10; i++) { Vector singleVector = getRandomVector(singles, i); @@ -518,7 +523,7 @@ public static int TestEntryPoint() returnVal = Fail; } } - + for (int i = 0; i < 10; i++) { Vector doubleVector = getRandomVector(doubles, i); @@ -528,7 +533,7 @@ public static int TestEntryPoint() returnVal = Fail; } } - + for (int i = 0; i < 10; i++) { Vector doubleVector = getRandomVector(doubles, i); @@ -538,7 +543,7 @@ public static int TestEntryPoint() returnVal = Fail; } } - + for (int i = 0; i < 10; i++) { Vector doubleVector1 = getRandomVector(doubles, i); @@ -549,7 +554,7 @@ public static int TestEntryPoint() returnVal = Fail; } } - + for (int i = 0; i < 10; i++) { Vector int64Vector1 = getRandomVector(int64s, i); @@ -560,7 +565,7 @@ public static int TestEntryPoint() returnVal = Fail; } } - + for (int i = 0; i < 10; i++) { Vector int32Vector1 = getRandomVector(int32s, i); @@ -571,7 +576,7 @@ public static int TestEntryPoint() returnVal = Fail; } } - + for (int i = 0; i < 10; i++) { Vector int16Vector1 = getRandomVector(int16s, i); @@ -582,7 +587,7 @@ public static int TestEntryPoint() returnVal = Fail; } } - + for (int i = 0; i < 10; i++) { Vector uint64Vector1 = getRandomVector(uint64s, i); @@ -593,7 +598,7 @@ public static int TestEntryPoint() returnVal = Fail; } } - + for (int i = 0; i < 10; i++) { Vector uint32Vector1 = getRandomVector(uint32s, i); @@ -604,7 +609,7 @@ public static int TestEntryPoint() returnVal = Fail; } } - + for (int i = 0; i < 10; i++) { Vector uint16Vector1 = getRandomVector(uint16s, i); @@ -616,9 +621,9 @@ public static int TestEntryPoint() } } - JitLog jitLog = new JitLog(); + JitLog jitLog = new JitLog(); // SIMD conversions from floating point to unsigned are not supported on x86 or x64 - + if (!jitLog.Check("System.Numerics.Vector:ConvertToInt32(struct):struct")) returnVal = Fail; if (!jitLog.Check("System.Numerics.Vector:ConvertToSingle(struct):struct")) returnVal = Fail; // SIMD Conversion to Int64 is not supported on x86 diff --git a/src/tests/JIT/common/localloc_common.ilproj b/src/tests/JIT/common/localloc_common.ilproj index 1bacf06c98e0..102de7ba3747 100644 --- a/src/tests/JIT/common/localloc_common.ilproj +++ b/src/tests/JIT/common/localloc_common.ilproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/jit64/ebvts/cs/generics/generics/repro52.csproj b/src/tests/JIT/jit64/ebvts/cs/generics/generics/repro52.csproj index 221b99c432a7..2e7d062633ea 100644 --- a/src/tests/JIT/jit64/ebvts/cs/generics/generics/repro52.csproj +++ b/src/tests/JIT/jit64/ebvts/cs/generics/generics/repro52.csproj @@ -3,10 +3,7 @@ 1 - Full - True - True diff --git a/src/tests/JIT/jit64/hfa/main/dll/common.csproj b/src/tests/JIT/jit64/hfa/main/dll/common.csproj index 07048e114fd8..5cc1e57d40bc 100644 --- a/src/tests/JIT/jit64/hfa/main/dll/common.csproj +++ b/src/tests/JIT/jit64/hfa/main/dll/common.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f32_common.csproj b/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f32_common.csproj index 3915fd08c17a..16606e1fcf9c 100644 --- a/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f32_common.csproj +++ b/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f32_common.csproj @@ -3,7 +3,6 @@ Library - $(DefineConstants);NESTED_HFA;FLOAT32 diff --git a/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f32_interop_cpp.csproj b/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f32_interop_cpp.csproj index ea3606ddba9c..2a21adbfa80d 100644 --- a/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f32_interop_cpp.csproj +++ b/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f32_interop_cpp.csproj @@ -3,7 +3,6 @@ Library - $(DefineConstants);NESTED_HFA;FLOAT32;NATIVE_CPP diff --git a/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f32_managed.csproj b/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f32_managed.csproj index cf2f6d505ebf..c3b80a4374e0 100644 --- a/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f32_managed.csproj +++ b/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f32_managed.csproj @@ -3,7 +3,6 @@ Library - $(DefineConstants);NESTED_HFA;FLOAT32 diff --git a/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_common.csproj b/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_common.csproj index 388c4696678c..0bd887dda8f2 100644 --- a/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_common.csproj +++ b/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_common.csproj @@ -3,7 +3,6 @@ Library - $(DefineConstants);NESTED_HFA;FLOAT64 diff --git a/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_interop_cpp.csproj b/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_interop_cpp.csproj index e266f818d14a..a667982e30e2 100644 --- a/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_interop_cpp.csproj +++ b/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_interop_cpp.csproj @@ -3,7 +3,6 @@ Library - $(DefineConstants);NESTED_HFA;FLOAT64;NATIVE_CPP diff --git a/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_managed.csproj b/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_managed.csproj index 2c0c66f5dbf6..2c62417c3bc2 100644 --- a/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_managed.csproj +++ b/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_managed.csproj @@ -3,7 +3,6 @@ Library - $(DefineConstants);NESTED_HFA;FLOAT64 diff --git a/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f32_common.csproj b/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f32_common.csproj index 6fd5ec94d833..3b937bf1a0f1 100644 --- a/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f32_common.csproj +++ b/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f32_common.csproj @@ -3,7 +3,6 @@ Library - $(DefineConstants);SIMPLE_HFA;FLOAT32 diff --git a/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f32_interop_cpp.csproj b/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f32_interop_cpp.csproj index ee98470816d6..2587454b7db7 100644 --- a/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f32_interop_cpp.csproj +++ b/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f32_interop_cpp.csproj @@ -3,7 +3,6 @@ Library - $(DefineConstants);SIMPLE_HFA;FLOAT32;NATIVE_CPP diff --git a/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f32_managed.csproj b/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f32_managed.csproj index 1a53b65923f3..062b80d95943 100644 --- a/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f32_managed.csproj +++ b/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f32_managed.csproj @@ -3,7 +3,6 @@ Library - $(DefineConstants);SIMPLE_HFA;FLOAT32 diff --git a/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f64_common.csproj b/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f64_common.csproj index 2832b4028c20..509702cab15a 100644 --- a/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f64_common.csproj +++ b/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f64_common.csproj @@ -3,7 +3,6 @@ Library - $(DefineConstants);SIMPLE_HFA;FLOAT64 diff --git a/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f64_interop_cpp.csproj b/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f64_interop_cpp.csproj index 28f993570f53..f6b712d4fda4 100644 --- a/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f64_interop_cpp.csproj +++ b/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f64_interop_cpp.csproj @@ -3,7 +3,6 @@ Library - $(DefineConstants);SIMPLE_HFA;FLOAT64;NATIVE_CPP diff --git a/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f64_managed.csproj b/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f64_managed.csproj index 12e48e3825d6..91fe2ef46bbf 100644 --- a/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f64_managed.csproj +++ b/src/tests/JIT/jit64/hfa/main/dll/hfa_simple_f64_managed.csproj @@ -3,7 +3,6 @@ Library - $(DefineConstants);SIMPLE_HFA;FLOAT64 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_d.csproj index 8b1500bee41b..da191efaf5b2 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_r.csproj index 6937ea9846c4..a4380d994b4c 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_d.csproj index 376fac88591a..76653333475b 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_r.csproj index 3a5893f6b336..a644f3db52b3 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_d.csproj index 21bdad87843d..76b4ce34b282 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_r.csproj index 3a46ef05347e..3d7e473c2e9a 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_d.csproj index 6057799056c1..3d8cf0224409 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_r.csproj index 52473178f8fd..66095581005a 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_nd0B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_nd0B_r.csproj index dd8663685216..c33df19bebb8 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_nd0B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_nd0B_r.csproj @@ -4,9 +4,6 @@ true 1 - - - diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_nd2B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_nd2B_r.csproj index 4c801ae1c82c..63c94600c7c9 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_nd2B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_nd2B_r.csproj @@ -4,9 +4,6 @@ true 1 - - - diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_nf0B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_nf0B_r.csproj index c7a3766513dd..ff6b1d327988 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_nf0B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_nf0B_r.csproj @@ -4,9 +4,6 @@ true 1 - - - diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_nf2B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_nf2B_r.csproj index 6ef20ef810fd..cda150a02ad5 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_nf2B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_nf2B_r.csproj @@ -4,9 +4,6 @@ true 1 - - - diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_sd0B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_sd0B_r.csproj index 26489292994b..844ee631e048 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_sd0B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_sd0B_r.csproj @@ -4,9 +4,6 @@ true 1 - - - diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_sd2B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_sd2B_r.csproj index 3ade2557c344..fe56d1f47265 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_sd2B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_sd2B_r.csproj @@ -4,9 +4,6 @@ true 1 - - - diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_sf0B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_sf0B_r.csproj index 37b53b18061b..a62d66b7f4c7 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_sf0B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_sf0B_r.csproj @@ -4,9 +4,6 @@ true 1 - - - diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_sf2B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_sf2B_r.csproj index 29c506b2790e..cb9eb7640504 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_sf2B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_sf2B_r.csproj @@ -4,9 +4,6 @@ true 1 - - - diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_d.csproj index 2f0bf8a33c4e..88b0e0aceafe 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_r.csproj index 7c13fd93eee3..3d2d53728b4f 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_r.csproj @@ -4,7 +4,6 @@ true - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_d.csproj index 76ea59e3367d..27dceaddd9cf 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_r.csproj index c1ac53c6a2a9..bc3b1a6dc0e1 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_d.csproj index 4fab292dad1f..aad65d7d0a46 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_r.csproj index 0ef9745f42f1..d4fa63063e8a 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_d.csproj index 39faf9a40c6c..d68bd16fc2ef 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_r.csproj index 1d759d6c64a7..6726921a74ac 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_d.csproj index 50e7f3350334..4a64c5b956fa 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_r.csproj index 122edeb93386..cab53553d649 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_d.csproj index 25d5a609adf8..dfa7a0cd63d7 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_r.csproj index de482963feb9..4900b6f0831c 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_d.csproj index 5d9ae737edaa..2f49d970aece 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_r.csproj index ba796caf8ea0..c1e5ea7a400d 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_d.csproj index b0c69e2b4f51..6365117624af 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_r.csproj index 9515e62f30c0..68d35b2dcc7a 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_d.csproj index 880da0d0b39a..456d75ba94aa 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_r.csproj index da8252509ce4..7ce16104572e 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_d.csproj index 9a22a6c926b1..f0c983f5eaa6 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_r.csproj index 4d9ffeaaa94b..36e9a1895c17 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_d.csproj index 054a3a6b2202..43779d651d5d 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_r.csproj index c2f2b19a4a48..5962d7bfc79b 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_d.csproj index 1ba27cf2ee6f..7b24ad20afbf 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_d.csproj @@ -5,7 +5,6 @@ 1 - full False diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_r.csproj index 8646e5699594..c103cb447894 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_r.csproj @@ -5,7 +5,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/localloc/eh/eh01_dynamic.csproj b/src/tests/JIT/jit64/localloc/eh/eh01_dynamic.csproj index e3f874b4bf5e..fe5b221e5758 100644 --- a/src/tests/JIT/jit64/localloc/eh/eh01_dynamic.csproj +++ b/src/tests/JIT/jit64/localloc/eh/eh01_dynamic.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_DYNAMIC diff --git a/src/tests/JIT/jit64/localloc/eh/eh01_large.csproj b/src/tests/JIT/jit64/localloc/eh/eh01_large.csproj index 96d948d47815..8adb2c3cb930 100644 --- a/src/tests/JIT/jit64/localloc/eh/eh01_large.csproj +++ b/src/tests/JIT/jit64/localloc/eh/eh01_large.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_LARGE diff --git a/src/tests/JIT/jit64/localloc/eh/eh01_small.csproj b/src/tests/JIT/jit64/localloc/eh/eh01_small.csproj index 283332f45550..e933c84ae77f 100644 --- a/src/tests/JIT/jit64/localloc/eh/eh01_small.csproj +++ b/src/tests/JIT/jit64/localloc/eh/eh01_small.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_SMALL diff --git a/src/tests/JIT/jit64/localloc/eh/eh02_dynamic.csproj b/src/tests/JIT/jit64/localloc/eh/eh02_dynamic.csproj index 3b518cd82872..9d4a1b4d2f0e 100644 --- a/src/tests/JIT/jit64/localloc/eh/eh02_dynamic.csproj +++ b/src/tests/JIT/jit64/localloc/eh/eh02_dynamic.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_DYNAMIC diff --git a/src/tests/JIT/jit64/localloc/eh/eh02_large.csproj b/src/tests/JIT/jit64/localloc/eh/eh02_large.csproj index 1f76d8808ad5..18d1332e4e57 100644 --- a/src/tests/JIT/jit64/localloc/eh/eh02_large.csproj +++ b/src/tests/JIT/jit64/localloc/eh/eh02_large.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_LARGE diff --git a/src/tests/JIT/jit64/localloc/eh/eh02_small.csproj b/src/tests/JIT/jit64/localloc/eh/eh02_small.csproj index ffe9df5c6dd0..f31ba1ac5565 100644 --- a/src/tests/JIT/jit64/localloc/eh/eh02_small.csproj +++ b/src/tests/JIT/jit64/localloc/eh/eh02_small.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_SMALL diff --git a/src/tests/JIT/jit64/localloc/eh/eh05_dynamic.csproj b/src/tests/JIT/jit64/localloc/eh/eh05_dynamic.csproj index e2f2c9eaeb0d..65581a8daac9 100644 --- a/src/tests/JIT/jit64/localloc/eh/eh05_dynamic.csproj +++ b/src/tests/JIT/jit64/localloc/eh/eh05_dynamic.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_DYNAMIC diff --git a/src/tests/JIT/jit64/localloc/eh/eh05_large.csproj b/src/tests/JIT/jit64/localloc/eh/eh05_large.csproj index 96d2c451ab84..b16729211e02 100644 --- a/src/tests/JIT/jit64/localloc/eh/eh05_large.csproj +++ b/src/tests/JIT/jit64/localloc/eh/eh05_large.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_LARGE diff --git a/src/tests/JIT/jit64/localloc/eh/eh05_small.csproj b/src/tests/JIT/jit64/localloc/eh/eh05_small.csproj index 17c529de7298..9f4effabd93d 100644 --- a/src/tests/JIT/jit64/localloc/eh/eh05_small.csproj +++ b/src/tests/JIT/jit64/localloc/eh/eh05_small.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_SMALL diff --git a/src/tests/JIT/jit64/localloc/ehverify/eh09_dynamic.csproj b/src/tests/JIT/jit64/localloc/ehverify/eh09_dynamic.csproj index a53d91f071d7..7b7c341cef50 100644 --- a/src/tests/JIT/jit64/localloc/ehverify/eh09_dynamic.csproj +++ b/src/tests/JIT/jit64/localloc/ehverify/eh09_dynamic.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_SMALL diff --git a/src/tests/JIT/jit64/localloc/ehverify/eh09_large.csproj b/src/tests/JIT/jit64/localloc/ehverify/eh09_large.csproj index a53d91f071d7..7b7c341cef50 100644 --- a/src/tests/JIT/jit64/localloc/ehverify/eh09_large.csproj +++ b/src/tests/JIT/jit64/localloc/ehverify/eh09_large.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_SMALL diff --git a/src/tests/JIT/jit64/localloc/ehverify/eh09_small.csproj b/src/tests/JIT/jit64/localloc/ehverify/eh09_small.csproj index a53d91f071d7..7b7c341cef50 100644 --- a/src/tests/JIT/jit64/localloc/ehverify/eh09_small.csproj +++ b/src/tests/JIT/jit64/localloc/ehverify/eh09_small.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_SMALL diff --git a/src/tests/JIT/jit64/localloc/unwind/unwind01_dynamic.csproj b/src/tests/JIT/jit64/localloc/unwind/unwind01_dynamic.csproj index 6afe8f60e5fd..fb8226570140 100644 --- a/src/tests/JIT/jit64/localloc/unwind/unwind01_dynamic.csproj +++ b/src/tests/JIT/jit64/localloc/unwind/unwind01_dynamic.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_DYNAMIC diff --git a/src/tests/JIT/jit64/localloc/unwind/unwind01_large.csproj b/src/tests/JIT/jit64/localloc/unwind/unwind01_large.csproj index 91cb7f92597d..2addeca4c571 100644 --- a/src/tests/JIT/jit64/localloc/unwind/unwind01_large.csproj +++ b/src/tests/JIT/jit64/localloc/unwind/unwind01_large.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_LARGE diff --git a/src/tests/JIT/jit64/localloc/unwind/unwind01_small.csproj b/src/tests/JIT/jit64/localloc/unwind/unwind01_small.csproj index 37579534dfa3..b237276f370d 100644 --- a/src/tests/JIT/jit64/localloc/unwind/unwind01_small.csproj +++ b/src/tests/JIT/jit64/localloc/unwind/unwind01_small.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_SMALL diff --git a/src/tests/JIT/jit64/localloc/unwind/unwind02_dynamic.csproj b/src/tests/JIT/jit64/localloc/unwind/unwind02_dynamic.csproj index e5a238e9d0af..233139dcfa04 100644 --- a/src/tests/JIT/jit64/localloc/unwind/unwind02_dynamic.csproj +++ b/src/tests/JIT/jit64/localloc/unwind/unwind02_dynamic.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_DYNAMIC diff --git a/src/tests/JIT/jit64/localloc/unwind/unwind02_large.csproj b/src/tests/JIT/jit64/localloc/unwind/unwind02_large.csproj index 6d58613d9132..9d7b2f13a1fc 100644 --- a/src/tests/JIT/jit64/localloc/unwind/unwind02_large.csproj +++ b/src/tests/JIT/jit64/localloc/unwind/unwind02_large.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_LARGE diff --git a/src/tests/JIT/jit64/localloc/unwind/unwind02_small.csproj b/src/tests/JIT/jit64/localloc/unwind/unwind02_small.csproj index af6bec381172..59798d0ea839 100644 --- a/src/tests/JIT/jit64/localloc/unwind/unwind02_small.csproj +++ b/src/tests/JIT/jit64/localloc/unwind/unwind02_small.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_SMALL diff --git a/src/tests/JIT/jit64/localloc/unwind/unwind03_dynamic.csproj b/src/tests/JIT/jit64/localloc/unwind/unwind03_dynamic.csproj index 1b6889fc030d..77990248fb15 100644 --- a/src/tests/JIT/jit64/localloc/unwind/unwind03_dynamic.csproj +++ b/src/tests/JIT/jit64/localloc/unwind/unwind03_dynamic.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_DYNAMIC diff --git a/src/tests/JIT/jit64/localloc/unwind/unwind03_large.csproj b/src/tests/JIT/jit64/localloc/unwind/unwind03_large.csproj index d3ad694ac439..a60dcb6971b4 100644 --- a/src/tests/JIT/jit64/localloc/unwind/unwind03_large.csproj +++ b/src/tests/JIT/jit64/localloc/unwind/unwind03_large.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_LARGE diff --git a/src/tests/JIT/jit64/localloc/unwind/unwind03_small.csproj b/src/tests/JIT/jit64/localloc/unwind/unwind03_small.csproj index c4b0be9b5895..e16f7d691bd3 100644 --- a/src/tests/JIT/jit64/localloc/unwind/unwind03_small.csproj +++ b/src/tests/JIT/jit64/localloc/unwind/unwind03_small.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly True $(DefineConstants);LOCALLOC_SMALL diff --git a/src/tests/JIT/jit64/opt/cprop/cprop001_d.csproj b/src/tests/JIT/jit64/opt/cprop/cprop001_d.csproj index b5e235e0cc4a..3d0c1a9d1d72 100644 --- a/src/tests/JIT/jit64/opt/cprop/cprop001_d.csproj +++ b/src/tests/JIT/jit64/opt/cprop/cprop001_d.csproj @@ -3,11 +3,8 @@ 1 - Full False - True - True diff --git a/src/tests/JIT/jit64/opt/cprop/cprop001_do.csproj b/src/tests/JIT/jit64/opt/cprop/cprop001_do.csproj index 6607912d46db..66559b488381 100644 --- a/src/tests/JIT/jit64/opt/cprop/cprop001_do.csproj +++ b/src/tests/JIT/jit64/opt/cprop/cprop001_do.csproj @@ -3,11 +3,8 @@ 1 - Full True - True - True diff --git a/src/tests/JIT/jit64/opt/cprop/cprop001_r.csproj b/src/tests/JIT/jit64/opt/cprop/cprop001_r.csproj index 86ac1b30a8fd..7a94120af24b 100644 --- a/src/tests/JIT/jit64/opt/cprop/cprop001_r.csproj +++ b/src/tests/JIT/jit64/opt/cprop/cprop001_r.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True diff --git a/src/tests/JIT/jit64/opt/cprop/cprop001_ro.csproj b/src/tests/JIT/jit64/opt/cprop/cprop001_ro.csproj index 9e8a20aad241..f785304b99dd 100644 --- a/src/tests/JIT/jit64/opt/cprop/cprop001_ro.csproj +++ b/src/tests/JIT/jit64/opt/cprop/cprop001_ro.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_add.csproj b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_add.csproj index ebcc2b8ff657..6ec8c3625523 100644 --- a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_add.csproj +++ b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_add.csproj @@ -5,10 +5,7 @@ 1 - PdbOnly - True - True $(DefineConstants);OP_ADD diff --git a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_and.csproj b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_and.csproj index 2ef5552003c1..43ba05cc09c8 100644 --- a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_and.csproj +++ b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_and.csproj @@ -5,10 +5,7 @@ 1 - PdbOnly - True - True $(DefineConstants);OP_AND diff --git a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_div.csproj b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_div.csproj index 5c2852002b29..b813d374365b 100644 --- a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_div.csproj +++ b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_div.csproj @@ -5,10 +5,7 @@ 1 - PdbOnly - True - True $(DefineConstants);OP_DIV diff --git a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_mod.csproj b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_mod.csproj index 88ff7d59ddb5..d56ac3d91bfa 100644 --- a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_mod.csproj +++ b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_mod.csproj @@ -5,10 +5,7 @@ 1 - PdbOnly - True - True $(DefineConstants);OP_MOD diff --git a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_mul.csproj b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_mul.csproj index 9d7ea3696248..d7826117b7b3 100644 --- a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_mul.csproj +++ b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_mul.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_MUL diff --git a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_or.csproj b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_or.csproj index 68ca00d08e38..4ae00bba4604 100644 --- a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_or.csproj +++ b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_or.csproj @@ -5,10 +5,7 @@ 1 - PdbOnly - True - True $(DefineConstants);OP_OR diff --git a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_shr.csproj b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_shr.csproj index 798062909f4a..b5af7c2526c1 100644 --- a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_shr.csproj +++ b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_shr.csproj @@ -5,10 +5,7 @@ 1 - PdbOnly - True - True $(DefineConstants);OP_SHR diff --git a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_sub.csproj b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_sub.csproj index 9891e7c670be..413b136304e5 100644 --- a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_sub.csproj +++ b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_sub.csproj @@ -5,10 +5,7 @@ 1 - PdbOnly - True - True $(DefineConstants);OP_SUB diff --git a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_xor.csproj b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_xor.csproj index 6f4472939169..3fde629fb6a3 100644 --- a/src/tests/JIT/jit64/opt/cse/VolatileTest_op_xor.csproj +++ b/src/tests/JIT/jit64/opt/cse/VolatileTest_op_xor.csproj @@ -5,10 +5,7 @@ 1 - PdbOnly - True - True $(DefineConstants);OP_XOR diff --git a/src/tests/JIT/jit64/opt/cse/arrayexpr2_d_loop_try.csproj b/src/tests/JIT/jit64/opt/cse/arrayexpr2_d_loop_try.csproj index 89e74d4a1141..16bc146cf8ad 100644 --- a/src/tests/JIT/jit64/opt/cse/arrayexpr2_d_loop_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/arrayexpr2_d_loop_try.csproj @@ -3,11 +3,8 @@ 1 - Full False - True - True $(DefineConstants);LOOP;TRY diff --git a/src/tests/JIT/jit64/opt/cse/arrayexpr2_r_loop.csproj b/src/tests/JIT/jit64/opt/cse/arrayexpr2_r_loop.csproj index d77330ff326a..a9fbfe5991e8 100644 --- a/src/tests/JIT/jit64/opt/cse/arrayexpr2_r_loop.csproj +++ b/src/tests/JIT/jit64/opt/cse/arrayexpr2_r_loop.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True $(DefineConstants);LOOP diff --git a/src/tests/JIT/jit64/opt/cse/arrayexpr2_r_loop_try.csproj b/src/tests/JIT/jit64/opt/cse/arrayexpr2_r_loop_try.csproj index c4326639ed32..ea96c6a830ad 100644 --- a/src/tests/JIT/jit64/opt/cse/arrayexpr2_r_loop_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/arrayexpr2_r_loop_try.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True $(DefineConstants);LOOP;TRY diff --git a/src/tests/JIT/jit64/opt/cse/arrayexpr2_r_try.csproj b/src/tests/JIT/jit64/opt/cse/arrayexpr2_r_try.csproj index 1c4278456e5b..807b51c6735c 100644 --- a/src/tests/JIT/jit64/opt/cse/arrayexpr2_r_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/arrayexpr2_r_try.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True $(DefineConstants);TRY diff --git a/src/tests/JIT/jit64/opt/cse/arrayexpr2_ro_loop.csproj b/src/tests/JIT/jit64/opt/cse/arrayexpr2_ro_loop.csproj index a0b3da551bed..d94088527a54 100644 --- a/src/tests/JIT/jit64/opt/cse/arrayexpr2_ro_loop.csproj +++ b/src/tests/JIT/jit64/opt/cse/arrayexpr2_ro_loop.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True $(DefineConstants);LOOP diff --git a/src/tests/JIT/jit64/opt/cse/mixedexpr1_d_loop_try.csproj b/src/tests/JIT/jit64/opt/cse/mixedexpr1_d_loop_try.csproj index d7078f260af4..a18d9d832900 100644 --- a/src/tests/JIT/jit64/opt/cse/mixedexpr1_d_loop_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/mixedexpr1_d_loop_try.csproj @@ -3,11 +3,8 @@ 1 - Full False - True - True $(DefineConstants);LOOP;TRY diff --git a/src/tests/JIT/jit64/opt/cse/mixedexpr1_r_loop.csproj b/src/tests/JIT/jit64/opt/cse/mixedexpr1_r_loop.csproj index 550ddf837d72..ee7f5146d2fe 100644 --- a/src/tests/JIT/jit64/opt/cse/mixedexpr1_r_loop.csproj +++ b/src/tests/JIT/jit64/opt/cse/mixedexpr1_r_loop.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True $(DefineConstants);LOOP diff --git a/src/tests/JIT/jit64/opt/cse/mixedexpr1_r_loop_try.csproj b/src/tests/JIT/jit64/opt/cse/mixedexpr1_r_loop_try.csproj index 681e0b9e93d7..52e7127f73ef 100644 --- a/src/tests/JIT/jit64/opt/cse/mixedexpr1_r_loop_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/mixedexpr1_r_loop_try.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True $(DefineConstants);LOOP;TRY diff --git a/src/tests/JIT/jit64/opt/cse/mixedexpr1_r_try.csproj b/src/tests/JIT/jit64/opt/cse/mixedexpr1_r_try.csproj index a8a934452a9b..c7105ac3e0d4 100644 --- a/src/tests/JIT/jit64/opt/cse/mixedexpr1_r_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/mixedexpr1_r_try.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True $(DefineConstants);TRY diff --git a/src/tests/JIT/jit64/opt/cse/mixedexpr1_ro_loop.csproj b/src/tests/JIT/jit64/opt/cse/mixedexpr1_ro_loop.csproj index 61ffaf187e4e..51518656f63d 100644 --- a/src/tests/JIT/jit64/opt/cse/mixedexpr1_ro_loop.csproj +++ b/src/tests/JIT/jit64/opt/cse/mixedexpr1_ro_loop.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True $(DefineConstants);LOOP diff --git a/src/tests/JIT/jit64/opt/cse/simpleexpr4_d_loop_try.csproj b/src/tests/JIT/jit64/opt/cse/simpleexpr4_d_loop_try.csproj index 674a95a19bdd..eb90fd0bb9a6 100644 --- a/src/tests/JIT/jit64/opt/cse/simpleexpr4_d_loop_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/simpleexpr4_d_loop_try.csproj @@ -3,11 +3,8 @@ 1 - Full False - True - True $(DefineConstants);LOOP;TRY diff --git a/src/tests/JIT/jit64/opt/cse/simpleexpr4_r_loop.csproj b/src/tests/JIT/jit64/opt/cse/simpleexpr4_r_loop.csproj index 98bbd3fdcc6a..5e821cf32d11 100644 --- a/src/tests/JIT/jit64/opt/cse/simpleexpr4_r_loop.csproj +++ b/src/tests/JIT/jit64/opt/cse/simpleexpr4_r_loop.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True $(DefineConstants);LOOP diff --git a/src/tests/JIT/jit64/opt/cse/simpleexpr4_r_loop_try.csproj b/src/tests/JIT/jit64/opt/cse/simpleexpr4_r_loop_try.csproj index 88baf36468f3..6b53c19ca2de 100644 --- a/src/tests/JIT/jit64/opt/cse/simpleexpr4_r_loop_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/simpleexpr4_r_loop_try.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True $(DefineConstants);LOOP;TRY diff --git a/src/tests/JIT/jit64/opt/cse/simpleexpr4_r_try.csproj b/src/tests/JIT/jit64/opt/cse/simpleexpr4_r_try.csproj index e1e3e83b5d37..b8e17a46e907 100644 --- a/src/tests/JIT/jit64/opt/cse/simpleexpr4_r_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/simpleexpr4_r_try.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True $(DefineConstants);TRY diff --git a/src/tests/JIT/jit64/opt/cse/simpleexpr4_ro_loop.csproj b/src/tests/JIT/jit64/opt/cse/simpleexpr4_ro_loop.csproj index 8927fb011ea0..e9384a7bbde9 100644 --- a/src/tests/JIT/jit64/opt/cse/simpleexpr4_ro_loop.csproj +++ b/src/tests/JIT/jit64/opt/cse/simpleexpr4_ro_loop.csproj @@ -1,10 +1,7 @@ - None True - True - True $(DefineConstants);LOOP diff --git a/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_d_loop_try.csproj b/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_d_loop_try.csproj index c668093024d1..872ae0830445 100644 --- a/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_d_loop_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_d_loop_try.csproj @@ -3,11 +3,8 @@ 1 - Full False - True - True $(DefineConstants);LOOP;TRY diff --git a/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_r_loop.csproj b/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_r_loop.csproj index cc4bf7797cb6..07be6e65465a 100644 --- a/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_r_loop.csproj +++ b/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_r_loop.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True $(DefineConstants);LOOP diff --git a/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_r_loop_try.csproj b/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_r_loop_try.csproj index aff346a38adf..0cf54a84cce4 100644 --- a/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_r_loop_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_r_loop_try.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True $(DefineConstants);LOOP;TRY diff --git a/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_r_try.csproj b/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_r_try.csproj index 22d126d1aff7..63d3489ff98a 100644 --- a/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_r_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_r_try.csproj @@ -3,11 +3,8 @@ 1 - None False - True - True $(DefineConstants);TRY diff --git a/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_ro_loop.csproj b/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_ro_loop.csproj index 7eedd560f2ec..66c666c9411a 100644 --- a/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_ro_loop.csproj +++ b/src/tests/JIT/jit64/opt/cse/staticFieldExpr1_ro_loop.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True $(DefineConstants);LOOP diff --git a/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_d_loop_try.csproj b/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_d_loop_try.csproj index 2cc57b7b85f5..f8108db6d3c9 100644 --- a/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_d_loop_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_d_loop_try.csproj @@ -1,10 +1,7 @@ - Full False - True - True $(DefineConstants);LOOP;TRY diff --git a/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_r_loop.csproj b/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_r_loop.csproj index 072f970e334d..72b6de1be1ae 100644 --- a/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_r_loop.csproj +++ b/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_r_loop.csproj @@ -1,10 +1,7 @@ - None False - True - True $(DefineConstants);LOOP diff --git a/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_r_loop_try.csproj b/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_r_loop_try.csproj index 71aa29224627..d033eefd2402 100644 --- a/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_r_loop_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_r_loop_try.csproj @@ -1,10 +1,7 @@ - None False - True - True $(DefineConstants);LOOP;TRY diff --git a/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_r_try.csproj b/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_r_try.csproj index 6a135dd0bf16..b66f8c26d9ee 100644 --- a/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_r_try.csproj +++ b/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_r_try.csproj @@ -1,10 +1,7 @@ - None False - True - True $(DefineConstants);TRY diff --git a/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_ro_loop.csproj b/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_ro_loop.csproj index e55b17710b0c..ee02e2f5f8d2 100644 --- a/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_ro_loop.csproj +++ b/src/tests/JIT/jit64/opt/cse/staticFieldExprUnchecked1_ro_loop.csproj @@ -1,10 +1,7 @@ - None True - True - True $(DefineConstants);LOOP diff --git a/src/tests/JIT/jit64/opt/rngchk/ArrayWithThread_o.csproj b/src/tests/JIT/jit64/opt/rngchk/ArrayWithThread_o.csproj index efd1ef8c9b9a..d3b44366cb13 100644 --- a/src/tests/JIT/jit64/opt/rngchk/ArrayWithThread_o.csproj +++ b/src/tests/JIT/jit64/opt/rngchk/ArrayWithThread_o.csproj @@ -6,11 +6,8 @@ true - PdbOnly True - True - True diff --git a/src/tests/JIT/jit64/regress/vsw/560402/opadd.csproj b/src/tests/JIT/jit64/regress/vsw/560402/opadd.csproj index e739876b9d2e..89906d662d61 100644 --- a/src/tests/JIT/jit64/regress/vsw/560402/opadd.csproj +++ b/src/tests/JIT/jit64/regress/vsw/560402/opadd.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/jit64/regress/vsw/560402/opmul.csproj b/src/tests/JIT/jit64/regress/vsw/560402/opmul.csproj index 22840d9c1d0b..7e852ce07195 100644 --- a/src/tests/JIT/jit64/regress/vsw/560402/opmul.csproj +++ b/src/tests/JIT/jit64/regress/vsw/560402/opmul.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/jit64/regress/vsw/560402/opsub.csproj b/src/tests/JIT/jit64/regress/vsw/560402/opsub.csproj index e731ea4fda93..107f3b0bfad2 100644 --- a/src/tests/JIT/jit64/regress/vsw/560402/opsub.csproj +++ b/src/tests/JIT/jit64/regress/vsw/560402/opsub.csproj @@ -3,10 +3,7 @@ 1 - PdbOnly - True - True True diff --git a/src/tests/JIT/jit64/regress/vsw/568666/library1.csproj b/src/tests/JIT/jit64/regress/vsw/568666/library1.csproj index f4b3d69ccdf3..ae98c7fd3c5a 100644 --- a/src/tests/JIT/jit64/regress/vsw/568666/library1.csproj +++ b/src/tests/JIT/jit64/regress/vsw/568666/library1.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/jit64/regress/vsw/568666/library2.csproj b/src/tests/JIT/jit64/regress/vsw/568666/library2.csproj index f4b3d69ccdf3..ae98c7fd3c5a 100644 --- a/src/tests/JIT/jit64/regress/vsw/568666/library2.csproj +++ b/src/tests/JIT/jit64/regress/vsw/568666/library2.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/jit64/regress/vsw/568666/test_568666.csproj b/src/tests/JIT/jit64/regress/vsw/568666/test_568666.csproj index 973cb27bd461..80abc6393806 100644 --- a/src/tests/JIT/jit64/regress/vsw/568666/test_568666.csproj +++ b/src/tests/JIT/jit64/regress/vsw/568666/test_568666.csproj @@ -3,7 +3,6 @@ 1 - PdbOnly diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow01_add.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow01_add.csproj index a25776abad61..dfc28cb5ec0c 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow01_add.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow01_add.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_ADD diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow01_div.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow01_div.csproj index 7dd331ceff57..a6a7449095db 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow01_div.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow01_div.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_DIV diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow01_mul.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow01_mul.csproj index d3a8c957b825..942b3aee6282 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow01_mul.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow01_mul.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_MUL diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow01_sub.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow01_sub.csproj index bc1efe5badc0..a7086cfb59db 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow01_sub.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow01_sub.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_SUB diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow02_add.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow02_add.csproj index b4fb1489434d..2c7728eee965 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow02_add.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow02_add.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_ADD diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow02_div.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow02_div.csproj index 9227a0e8fbc0..1ce6a2eed60f 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow02_div.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow02_div.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_DIV diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow02_mul.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow02_mul.csproj index 250324e9729b..421ad8234572 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow02_mul.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow02_mul.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_MUL diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow02_sub.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow02_sub.csproj index 79af346f8675..3c6cd01d4d3a 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow02_sub.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow02_sub.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_SUB diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow03_add.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow03_add.csproj index 086e105de0a3..53b0e1168787 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow03_add.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow03_add.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_ADD diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow03_div.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow03_div.csproj index 924a1fd8294e..24f23516b193 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow03_div.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow03_div.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_DIV diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow03_mul.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow03_mul.csproj index 696aae70198c..f1df72b3532f 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow03_mul.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow03_mul.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_MUL diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow03_sub.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow03_sub.csproj index 38c91474b18a..7bbcd71b9753 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow03_sub.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow03_sub.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_SUB diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow04_add.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow04_add.csproj index c9a46847a757..385dbfc3db9e 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow04_add.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow04_add.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_ADD diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow04_div.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow04_div.csproj index fb21c73f8454..c35e29c0e9b3 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow04_div.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow04_div.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_DIV diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow04_mul.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow04_mul.csproj index 32042cad7ceb..ace138bf5451 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow04_mul.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow04_mul.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_MUL diff --git a/src/tests/JIT/jit64/rtchecks/overflow/overflow04_sub.csproj b/src/tests/JIT/jit64/rtchecks/overflow/overflow04_sub.csproj index 2d6d4f6a19b4..b7c35f2f1cfe 100644 --- a/src/tests/JIT/jit64/rtchecks/overflow/overflow04_sub.csproj +++ b/src/tests/JIT/jit64/rtchecks/overflow/overflow04_sub.csproj @@ -1,9 +1,6 @@ - PdbOnly - True - True $(DefineConstants);OP_SUB diff --git a/src/tests/JIT/opt/AssertionPropagation/ArrBoundUnsigned.csproj b/src/tests/JIT/opt/AssertionPropagation/ArrBoundUnsigned.csproj index dd42de3b8653..f4d38ecd2b9e 100644 --- a/src/tests/JIT/opt/AssertionPropagation/ArrBoundUnsigned.csproj +++ b/src/tests/JIT/opt/AssertionPropagation/ArrBoundUnsigned.csproj @@ -1,10 +1,7 @@ - None True - True - True diff --git a/src/tests/JIT/opt/AssertionPropagation/ConstantProp.csproj b/src/tests/JIT/opt/AssertionPropagation/ConstantProp.csproj index 2d6c0da6ebda..61b1b22d8c43 100644 --- a/src/tests/JIT/opt/AssertionPropagation/ConstantProp.csproj +++ b/src/tests/JIT/opt/AssertionPropagation/ConstantProp.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/AssertionPropagation/CopyProp.csproj b/src/tests/JIT/opt/AssertionPropagation/CopyProp.csproj index b44877cd1cd2..f9cfdb8fe290 100644 --- a/src/tests/JIT/opt/AssertionPropagation/CopyProp.csproj +++ b/src/tests/JIT/opt/AssertionPropagation/CopyProp.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion1.csproj b/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion1.csproj index 1d9ab7517b7e..e25bab2fe615 100644 --- a/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion1.csproj +++ b/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion1.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion2.csproj b/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion2.csproj index 6337206d18c3..159985b12a69 100644 --- a/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion2.csproj +++ b/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion2.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion3.csproj b/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion3.csproj index d6ae7bbd9a00..e09de6b69887 100644 --- a/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion3.csproj +++ b/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion3.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion4.csproj b/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion4.csproj index cbf7b51e8778..66e493edadc7 100644 --- a/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion4.csproj +++ b/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion4.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion5.csproj b/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion5.csproj index 47fa32f2af1b..bb0427586778 100644 --- a/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion5.csproj +++ b/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion5.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion6.csproj b/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion6.csproj index 0358b654a0b9..d92c96d4042a 100644 --- a/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion6.csproj +++ b/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion6.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion7.csproj b/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion7.csproj index 6910bedf7adc..36d4d426e658 100644 --- a/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion7.csproj +++ b/src/tests/JIT/opt/AssertionPropagation/NullCheckAssertion7.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/AssertionPropagation/TypeOfAssertion.csproj b/src/tests/JIT/opt/AssertionPropagation/TypeOfAssertion.csproj index 601f6fc5e61f..997624a762f2 100644 --- a/src/tests/JIT/opt/AssertionPropagation/TypeOfAssertion.csproj +++ b/src/tests/JIT/opt/AssertionPropagation/TypeOfAssertion.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/AssertionPropagation/regression/dev10/bug573840/bug573840.csproj b/src/tests/JIT/opt/AssertionPropagation/regression/dev10/bug573840/bug573840.csproj index c57fb3438e3a..377bf381b528 100644 --- a/src/tests/JIT/opt/AssertionPropagation/regression/dev10/bug573840/bug573840.csproj +++ b/src/tests/JIT/opt/AssertionPropagation/regression/dev10/bug573840/bug573840.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/FastTailCall/FastTailCallCandidates.csproj b/src/tests/JIT/opt/FastTailCall/FastTailCallCandidates.csproj index e6a95ae3076d..a55723e1f05a 100644 --- a/src/tests/JIT/opt/FastTailCall/FastTailCallCandidates.csproj +++ b/src/tests/JIT/opt/FastTailCall/FastTailCallCandidates.csproj @@ -4,10 +4,7 @@ true - PdbOnly - True - True True True True diff --git a/src/tests/JIT/opt/FastTailCall/FastTailCallInlining.csproj b/src/tests/JIT/opt/FastTailCall/FastTailCallInlining.csproj index 6e4107a85807..0d4c16c9a80e 100644 --- a/src/tests/JIT/opt/FastTailCall/FastTailCallInlining.csproj +++ b/src/tests/JIT/opt/FastTailCall/FastTailCallInlining.csproj @@ -4,10 +4,7 @@ true - None - True - True True True True diff --git a/src/tests/JIT/opt/FastTailCall/GitHubIssue12479.csproj b/src/tests/JIT/opt/FastTailCall/GitHubIssue12479.csproj index f35649562084..b4f3017d9d00 100644 --- a/src/tests/JIT/opt/FastTailCall/GitHubIssue12479.csproj +++ b/src/tests/JIT/opt/FastTailCall/GitHubIssue12479.csproj @@ -4,10 +4,7 @@ true - None - True - True True True True diff --git a/src/tests/JIT/opt/FastTailCall/StackFixup.csproj b/src/tests/JIT/opt/FastTailCall/StackFixup.csproj index ba8ad7c14401..c05363b778da 100644 --- a/src/tests/JIT/opt/FastTailCall/StackFixup.csproj +++ b/src/tests/JIT/opt/FastTailCall/StackFixup.csproj @@ -4,10 +4,7 @@ true - None - True - True True True True diff --git a/src/tests/JIT/opt/FastTailCall/StructPassingSimple.csproj b/src/tests/JIT/opt/FastTailCall/StructPassingSimple.csproj index 57484ce9c8a2..ee0615c63e2e 100644 --- a/src/tests/JIT/opt/FastTailCall/StructPassingSimple.csproj +++ b/src/tests/JIT/opt/FastTailCall/StructPassingSimple.csproj @@ -4,10 +4,7 @@ true - None - True - True True True True diff --git a/src/tests/JIT/opt/ForwardSub/andnotcontained.csproj b/src/tests/JIT/opt/ForwardSub/andnotcontained.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/opt/ForwardSub/andnotcontained.csproj +++ b/src/tests/JIT/opt/ForwardSub/andnotcontained.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/opt/ForwardSub/callArgInterference.csproj b/src/tests/JIT/opt/ForwardSub/callArgInterference.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/opt/ForwardSub/callArgInterference.csproj +++ b/src/tests/JIT/opt/ForwardSub/callArgInterference.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/opt/ForwardSub/callArgInterference2.csproj b/src/tests/JIT/opt/ForwardSub/callArgInterference2.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/opt/ForwardSub/callArgInterference2.csproj +++ b/src/tests/JIT/opt/ForwardSub/callArgInterference2.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/opt/ForwardSub/callArgInterference3.csproj b/src/tests/JIT/opt/ForwardSub/callArgInterference3.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/opt/ForwardSub/callArgInterference3.csproj +++ b/src/tests/JIT/opt/ForwardSub/callArgInterference3.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/opt/ForwardSub/earlyLiveness.csproj b/src/tests/JIT/opt/ForwardSub/earlyLiveness.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/opt/ForwardSub/earlyLiveness.csproj +++ b/src/tests/JIT/opt/ForwardSub/earlyLiveness.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/opt/ForwardSub/lowerContainCheckCompare.csproj b/src/tests/JIT/opt/ForwardSub/lowerContainCheckCompare.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/opt/ForwardSub/lowerContainCheckCompare.csproj +++ b/src/tests/JIT/opt/ForwardSub/lowerContainCheckCompare.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/opt/ForwardSub/modOpt.csproj b/src/tests/JIT/opt/ForwardSub/modOpt.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/opt/ForwardSub/modOpt.csproj +++ b/src/tests/JIT/opt/ForwardSub/modOpt.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/opt/ForwardSub/switchWithSideEffects.csproj b/src/tests/JIT/opt/ForwardSub/switchWithSideEffects.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/opt/ForwardSub/switchWithSideEffects.csproj +++ b/src/tests/JIT/opt/ForwardSub/switchWithSideEffects.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/opt/GuardedDevirtualization/enumerablecloning.csproj b/src/tests/JIT/opt/GuardedDevirtualization/enumerablecloning.csproj index f2066253c894..64abfdba0534 100644 --- a/src/tests/JIT/opt/GuardedDevirtualization/enumerablecloning.csproj +++ b/src/tests/JIT/opt/GuardedDevirtualization/enumerablecloning.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/GuardedDevirtualization/typetestcloning.csproj b/src/tests/JIT/opt/GuardedDevirtualization/typetestcloning.csproj index f2066253c894..64abfdba0534 100644 --- a/src/tests/JIT/opt/GuardedDevirtualization/typetestcloning.csproj +++ b/src/tests/JIT/opt/GuardedDevirtualization/typetestcloning.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/Inline/regression/bug595776/bug595776.csproj b/src/tests/JIT/opt/Inline/regression/bug595776/bug595776.csproj index 119ebcd1d21e..4ee2e5892f22 100644 --- a/src/tests/JIT/opt/Inline/regression/bug595776/bug595776.csproj +++ b/src/tests/JIT/opt/Inline/regression/bug595776/bug595776.csproj @@ -3,11 +3,8 @@ 1 - PdbOnly True - True - True diff --git a/src/tests/JIT/opt/Inline/tests/ArrayOfStructs.csproj b/src/tests/JIT/opt/Inline/tests/ArrayOfStructs.csproj index 39e5d72fbcbe..c51b8a08313a 100644 --- a/src/tests/JIT/opt/Inline/tests/ArrayOfStructs.csproj +++ b/src/tests/JIT/opt/Inline/tests/ArrayOfStructs.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/Inline/tests/DelegInstanceFtn.csproj b/src/tests/JIT/opt/Inline/tests/DelegInstanceFtn.csproj index 3c5310591305..11f0ce1e85ce 100644 --- a/src/tests/JIT/opt/Inline/tests/DelegInstanceFtn.csproj +++ b/src/tests/JIT/opt/Inline/tests/DelegInstanceFtn.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/DelegStaticFtn.csproj b/src/tests/JIT/opt/Inline/tests/DelegStaticFtn.csproj index 4338f8ce69d5..f7cae3f585eb 100644 --- a/src/tests/JIT/opt/Inline/tests/DelegStaticFtn.csproj +++ b/src/tests/JIT/opt/Inline/tests/DelegStaticFtn.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/GenericStructs.csproj b/src/tests/JIT/opt/Inline/tests/GenericStructs.csproj index 30ee603e329f..882d39528caa 100644 --- a/src/tests/JIT/opt/Inline/tests/GenericStructs.csproj +++ b/src/tests/JIT/opt/Inline/tests/GenericStructs.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/Inline/tests/Inline.csproj b/src/tests/JIT/opt/Inline/tests/Inline.csproj index 872890f85a8b..25ae71e8be64 100644 --- a/src/tests/JIT/opt/Inline/tests/Inline.csproj +++ b/src/tests/JIT/opt/Inline/tests/Inline.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/InlineThrow.csproj b/src/tests/JIT/opt/Inline/tests/InlineThrow.csproj index d005333a98b8..5d1e5441bedf 100644 --- a/src/tests/JIT/opt/Inline/tests/InlineThrow.csproj +++ b/src/tests/JIT/opt/Inline/tests/InlineThrow.csproj @@ -1,9 +1,6 @@ - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/Inline_DelegateStruct.csproj b/src/tests/JIT/opt/Inline/tests/Inline_DelegateStruct.csproj index ae94367e8e65..dc3d98a5681a 100644 --- a/src/tests/JIT/opt/Inline/tests/Inline_DelegateStruct.csproj +++ b/src/tests/JIT/opt/Inline/tests/Inline_DelegateStruct.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/Inline/tests/Inline_GenericMethods.csproj b/src/tests/JIT/opt/Inline/tests/Inline_GenericMethods.csproj index 37d279645265..dccc1b8f4ece 100644 --- a/src/tests/JIT/opt/Inline/tests/Inline_GenericMethods.csproj +++ b/src/tests/JIT/opt/Inline/tests/Inline_GenericMethods.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/Inline_Many.csproj b/src/tests/JIT/opt/Inline/tests/Inline_Many.csproj index 2a0f921da735..7f8096fcf66b 100644 --- a/src/tests/JIT/opt/Inline/tests/Inline_Many.csproj +++ b/src/tests/JIT/opt/Inline/tests/Inline_Many.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/Inline_MultipleReturn.csproj b/src/tests/JIT/opt/Inline/tests/Inline_MultipleReturn.csproj index 3b07d5f1c9cd..3d90106255e4 100644 --- a/src/tests/JIT/opt/Inline/tests/Inline_MultipleReturn.csproj +++ b/src/tests/JIT/opt/Inline/tests/Inline_MultipleReturn.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/Inline_NewObj.csproj b/src/tests/JIT/opt/Inline/tests/Inline_NewObj.csproj index 80e4085d6f9a..c5e78c1912b3 100644 --- a/src/tests/JIT/opt/Inline/tests/Inline_NewObj.csproj +++ b/src/tests/JIT/opt/Inline/tests/Inline_NewObj.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/Inline_NormalizeStack.csproj b/src/tests/JIT/opt/Inline/tests/Inline_NormalizeStack.csproj index fca563c19d5a..dd4adb7a3107 100644 --- a/src/tests/JIT/opt/Inline/tests/Inline_NormalizeStack.csproj +++ b/src/tests/JIT/opt/Inline/tests/Inline_NormalizeStack.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/Inline_Recursion.csproj b/src/tests/JIT/opt/Inline/tests/Inline_Recursion.csproj index 01873ce544b8..b32e11e83c28 100644 --- a/src/tests/JIT/opt/Inline/tests/Inline_Recursion.csproj +++ b/src/tests/JIT/opt/Inline/tests/Inline_Recursion.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/Inline_RecursiveMethod.csproj b/src/tests/JIT/opt/Inline/tests/Inline_RecursiveMethod.csproj index e0033f461bb7..4ee191054b1f 100644 --- a/src/tests/JIT/opt/Inline/tests/Inline_RecursiveMethod.csproj +++ b/src/tests/JIT/opt/Inline/tests/Inline_RecursiveMethod.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/Inline/tests/Inline_RecursiveMethod21.csproj b/src/tests/JIT/opt/Inline/tests/Inline_RecursiveMethod21.csproj index d251b5d64203..c127e964ceba 100644 --- a/src/tests/JIT/opt/Inline/tests/Inline_RecursiveMethod21.csproj +++ b/src/tests/JIT/opt/Inline/tests/Inline_RecursiveMethod21.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/Inline/tests/Inline_STARG.csproj b/src/tests/JIT/opt/Inline/tests/Inline_STARG.csproj index 24b5658f9af6..8ba3341efc5a 100644 --- a/src/tests/JIT/opt/Inline/tests/Inline_STARG.csproj +++ b/src/tests/JIT/opt/Inline/tests/Inline_STARG.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/Inline_SideAffects.csproj b/src/tests/JIT/opt/Inline/tests/Inline_SideAffects.csproj index 3c6271c22261..0e705b5a165f 100644 --- a/src/tests/JIT/opt/Inline/tests/Inline_SideAffects.csproj +++ b/src/tests/JIT/opt/Inline/tests/Inline_SideAffects.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/Inline_Vars.csproj b/src/tests/JIT/opt/Inline/tests/Inline_Vars.csproj index b4e593000c77..ef7787f37eba 100644 --- a/src/tests/JIT/opt/Inline/tests/Inline_Vars.csproj +++ b/src/tests/JIT/opt/Inline/tests/Inline_Vars.csproj @@ -2,10 +2,7 @@ - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/Inline_handler.csproj b/src/tests/JIT/opt/Inline/tests/Inline_handler.csproj index 06addf13c247..26977bb69629 100644 --- a/src/tests/JIT/opt/Inline/tests/Inline_handler.csproj +++ b/src/tests/JIT/opt/Inline/tests/Inline_handler.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/LotsOfInlines.csproj b/src/tests/JIT/opt/Inline/tests/LotsOfInlines.csproj index 38d994d57c57..9b7067377ef3 100644 --- a/src/tests/JIT/opt/Inline/tests/LotsOfInlines.csproj +++ b/src/tests/JIT/opt/Inline/tests/LotsOfInlines.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/ReturnStruct_Method.csproj b/src/tests/JIT/opt/Inline/tests/ReturnStruct_Method.csproj index 93e55f025959..d98bb0899194 100644 --- a/src/tests/JIT/opt/Inline/tests/ReturnStruct_Method.csproj +++ b/src/tests/JIT/opt/Inline/tests/ReturnStruct_Method.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/StructAsParam_Method.csproj b/src/tests/JIT/opt/Inline/tests/StructAsParam_Method.csproj index d9f1c8ba38c1..0996fdbb881f 100644 --- a/src/tests/JIT/opt/Inline/tests/StructAsParam_Method.csproj +++ b/src/tests/JIT/opt/Inline/tests/StructAsParam_Method.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/StructInClass.csproj b/src/tests/JIT/opt/Inline/tests/StructInClass.csproj index dd9de59658ee..dd7bb1c862af 100644 --- a/src/tests/JIT/opt/Inline/tests/StructInClass.csproj +++ b/src/tests/JIT/opt/Inline/tests/StructInClass.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/Inline/tests/UnsafeBlockCopy.csproj b/src/tests/JIT/opt/Inline/tests/UnsafeBlockCopy.csproj index 2bec71401967..c6a9fd673312 100644 --- a/src/tests/JIT/opt/Inline/tests/UnsafeBlockCopy.csproj +++ b/src/tests/JIT/opt/Inline/tests/UnsafeBlockCopy.csproj @@ -5,8 +5,6 @@ PdbOnly True - True - True True diff --git a/src/tests/JIT/opt/Inline/tests/args1.csproj b/src/tests/JIT/opt/Inline/tests/args1.csproj index df6c2dd71e2e..4193fea30861 100644 --- a/src/tests/JIT/opt/Inline/tests/args1.csproj +++ b/src/tests/JIT/opt/Inline/tests/args1.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/args2.csproj b/src/tests/JIT/opt/Inline/tests/args2.csproj index fb00610cb0ce..6e33da91bbf5 100644 --- a/src/tests/JIT/opt/Inline/tests/args2.csproj +++ b/src/tests/JIT/opt/Inline/tests/args2.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/args3.csproj b/src/tests/JIT/opt/Inline/tests/args3.csproj index 0f718444a8ca..3a0ec4761a9d 100644 --- a/src/tests/JIT/opt/Inline/tests/args3.csproj +++ b/src/tests/JIT/opt/Inline/tests/args3.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/Inline/tests/array.csproj b/src/tests/JIT/opt/Inline/tests/array.csproj index de6a0e98dc37..efcb95e6015e 100644 --- a/src/tests/JIT/opt/Inline/tests/array.csproj +++ b/src/tests/JIT/opt/Inline/tests/array.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/debug.csproj b/src/tests/JIT/opt/Inline/tests/debug.csproj index 9526be447574..8c76c092ed36 100644 --- a/src/tests/JIT/opt/Inline/tests/debug.csproj +++ b/src/tests/JIT/opt/Inline/tests/debug.csproj @@ -3,10 +3,7 @@ 1 - Full - True - True diff --git a/src/tests/JIT/opt/Inline/tests/deepcall.csproj b/src/tests/JIT/opt/Inline/tests/deepcall.csproj index 600f24d6ef39..a2a23bf90b43 100644 --- a/src/tests/JIT/opt/Inline/tests/deepcall.csproj +++ b/src/tests/JIT/opt/Inline/tests/deepcall.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/ifelse.csproj b/src/tests/JIT/opt/Inline/tests/ifelse.csproj index 7709cd7d9b8b..4c24c6b51541 100644 --- a/src/tests/JIT/opt/Inline/tests/ifelse.csproj +++ b/src/tests/JIT/opt/Inline/tests/ifelse.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/indexer.csproj b/src/tests/JIT/opt/Inline/tests/indexer.csproj index c4dab6da26b9..abd63652dcb4 100644 --- a/src/tests/JIT/opt/Inline/tests/indexer.csproj +++ b/src/tests/JIT/opt/Inline/tests/indexer.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/Inline/tests/interfaceCall.csproj b/src/tests/JIT/opt/Inline/tests/interfaceCall.csproj index bba523a07125..84b25eded018 100644 --- a/src/tests/JIT/opt/Inline/tests/interfaceCall.csproj +++ b/src/tests/JIT/opt/Inline/tests/interfaceCall.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/interfaceproperty.csproj b/src/tests/JIT/opt/Inline/tests/interfaceproperty.csproj index 9fc0dc54f6c1..15f60cd3d33f 100644 --- a/src/tests/JIT/opt/Inline/tests/interfaceproperty.csproj +++ b/src/tests/JIT/opt/Inline/tests/interfaceproperty.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/mathfunc.csproj b/src/tests/JIT/opt/Inline/tests/mathfunc.csproj index 69e9a41a29aa..cec028d67b4d 100644 --- a/src/tests/JIT/opt/Inline/tests/mathfunc.csproj +++ b/src/tests/JIT/opt/Inline/tests/mathfunc.csproj @@ -1,9 +1,6 @@ - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/mthdimpl.csproj b/src/tests/JIT/opt/Inline/tests/mthdimpl.csproj index faaa51bbef31..25c2363a1bfc 100644 --- a/src/tests/JIT/opt/Inline/tests/mthdimpl.csproj +++ b/src/tests/JIT/opt/Inline/tests/mthdimpl.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/property.csproj b/src/tests/JIT/opt/Inline/tests/property.csproj index a1d710d17192..c889d5599474 100644 --- a/src/tests/JIT/opt/Inline/tests/property.csproj +++ b/src/tests/JIT/opt/Inline/tests/property.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/size.csproj b/src/tests/JIT/opt/Inline/tests/size.csproj index 565e3971d649..6ebdc3882ccf 100644 --- a/src/tests/JIT/opt/Inline/tests/size.csproj +++ b/src/tests/JIT/opt/Inline/tests/size.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/Inline/tests/struct_opcodes.csproj b/src/tests/JIT/opt/Inline/tests/struct_opcodes.csproj index 59f912d4eb4d..2b8ac0c39c9b 100644 --- a/src/tests/JIT/opt/Inline/tests/struct_opcodes.csproj +++ b/src/tests/JIT/opt/Inline/tests/struct_opcodes.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/Inline/tests/throwtest.csproj b/src/tests/JIT/opt/Inline/tests/throwtest.csproj index a79d2ee9187b..01b34e07a46e 100644 --- a/src/tests/JIT/opt/Inline/tests/throwtest.csproj +++ b/src/tests/JIT/opt/Inline/tests/throwtest.csproj @@ -3,11 +3,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/opt/Inline/tests/trycatch.csproj b/src/tests/JIT/opt/Inline/tests/trycatch.csproj index 5c405b20fa82..e2b60584797e 100644 --- a/src/tests/JIT/opt/Inline/tests/trycatch.csproj +++ b/src/tests/JIT/opt/Inline/tests/trycatch.csproj @@ -3,10 +3,7 @@ 1 - None - True - True diff --git a/src/tests/JIT/opt/OSR/Runtime_69032.csproj b/src/tests/JIT/opt/OSR/Runtime_69032.csproj index c1f1286cd5b6..4abd5eb41960 100644 --- a/src/tests/JIT/opt/OSR/Runtime_69032.csproj +++ b/src/tests/JIT/opt/OSR/Runtime_69032.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/Runtime_89666.csproj b/src/tests/JIT/opt/OSR/Runtime_89666.csproj index 9fc3a6fe026a..d9c90bbb0d39 100644 --- a/src/tests/JIT/opt/OSR/Runtime_89666.csproj +++ b/src/tests/JIT/opt/OSR/Runtime_89666.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/addressexposedlocal.csproj b/src/tests/JIT/opt/OSR/addressexposedlocal.csproj index b07fc4f3823f..44bab58ad10a 100644 --- a/src/tests/JIT/opt/OSR/addressexposedlocal.csproj +++ b/src/tests/JIT/opt/OSR/addressexposedlocal.csproj @@ -2,7 +2,6 @@ true - True true diff --git a/src/tests/JIT/opt/OSR/doublestackalloc.csproj b/src/tests/JIT/opt/OSR/doublestackalloc.csproj index b07fc4f3823f..44bab58ad10a 100644 --- a/src/tests/JIT/opt/OSR/doublestackalloc.csproj +++ b/src/tests/JIT/opt/OSR/doublestackalloc.csproj @@ -2,7 +2,6 @@ true - True true diff --git a/src/tests/JIT/opt/OSR/example.csproj b/src/tests/JIT/opt/OSR/example.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/example.csproj +++ b/src/tests/JIT/opt/OSR/example.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/exposure1.csproj b/src/tests/JIT/opt/OSR/exposure1.csproj index 6b6dff02e3aa..862e20bd0546 100644 --- a/src/tests/JIT/opt/OSR/exposure1.csproj +++ b/src/tests/JIT/opt/OSR/exposure1.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/exposure2.csproj b/src/tests/JIT/opt/OSR/exposure2.csproj index 6b6dff02e3aa..862e20bd0546 100644 --- a/src/tests/JIT/opt/OSR/exposure2.csproj +++ b/src/tests/JIT/opt/OSR/exposure2.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/genericmethodpatchpoint.csproj b/src/tests/JIT/opt/OSR/genericmethodpatchpoint.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/genericmethodpatchpoint.csproj +++ b/src/tests/JIT/opt/OSR/genericmethodpatchpoint.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/handlerloop.csproj b/src/tests/JIT/opt/OSR/handlerloop.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/handlerloop.csproj +++ b/src/tests/JIT/opt/OSR/handlerloop.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/innerloop.csproj b/src/tests/JIT/opt/OSR/innerloop.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/innerloop.csproj +++ b/src/tests/JIT/opt/OSR/innerloop.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/integersumloop.csproj b/src/tests/JIT/opt/OSR/integersumloop.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/integersumloop.csproj +++ b/src/tests/JIT/opt/OSR/integersumloop.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/invalidpromotion.csproj b/src/tests/JIT/opt/OSR/invalidpromotion.csproj index c5c2200ef2f1..02dabaa66c4e 100644 --- a/src/tests/JIT/opt/OSR/invalidpromotion.csproj +++ b/src/tests/JIT/opt/OSR/invalidpromotion.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/largefuncletframe.csproj b/src/tests/JIT/opt/OSR/largefuncletframe.csproj index 20b843f9edbe..e68a3348df81 100644 --- a/src/tests/JIT/opt/OSR/largefuncletframe.csproj +++ b/src/tests/JIT/opt/OSR/largefuncletframe.csproj @@ -2,7 +2,6 @@ true - True true diff --git a/src/tests/JIT/opt/OSR/livelocaladdress.csproj b/src/tests/JIT/opt/OSR/livelocaladdress.csproj index c99ef44a02dd..9f1cf69989ce 100644 --- a/src/tests/JIT/opt/OSR/livelocaladdress.csproj +++ b/src/tests/JIT/opt/OSR/livelocaladdress.csproj @@ -2,7 +2,6 @@ true - True true diff --git a/src/tests/JIT/opt/OSR/livelocalstackalloc.csproj b/src/tests/JIT/opt/OSR/livelocalstackalloc.csproj index b07fc4f3823f..44bab58ad10a 100644 --- a/src/tests/JIT/opt/OSR/livelocalstackalloc.csproj +++ b/src/tests/JIT/opt/OSR/livelocalstackalloc.csproj @@ -2,7 +2,6 @@ true - True true diff --git a/src/tests/JIT/opt/OSR/mainloop.csproj b/src/tests/JIT/opt/OSR/mainloop.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/mainloop.csproj +++ b/src/tests/JIT/opt/OSR/mainloop.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/mainloop2.csproj b/src/tests/JIT/opt/OSR/mainloop2.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/mainloop2.csproj +++ b/src/tests/JIT/opt/OSR/mainloop2.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/mainlooptry.csproj b/src/tests/JIT/opt/OSR/mainlooptry.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/mainlooptry.csproj +++ b/src/tests/JIT/opt/OSR/mainlooptry.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/mainlooptry2.csproj b/src/tests/JIT/opt/OSR/mainlooptry2.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/mainlooptry2.csproj +++ b/src/tests/JIT/opt/OSR/mainlooptry2.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/mainlooptry3.csproj b/src/tests/JIT/opt/OSR/mainlooptry3.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/mainlooptry3.csproj +++ b/src/tests/JIT/opt/OSR/mainlooptry3.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/mainlooptry4.csproj b/src/tests/JIT/opt/OSR/mainlooptry4.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/mainlooptry4.csproj +++ b/src/tests/JIT/opt/OSR/mainlooptry4.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/memoryargument.csproj b/src/tests/JIT/opt/OSR/memoryargument.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/memoryargument.csproj +++ b/src/tests/JIT/opt/OSR/memoryargument.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/nesteddoloops.csproj b/src/tests/JIT/opt/OSR/nesteddoloops.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/nesteddoloops.csproj +++ b/src/tests/JIT/opt/OSR/nesteddoloops.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/normalizeonload.csproj b/src/tests/JIT/opt/OSR/normalizeonload.csproj index a5c97d8b83ec..5834268fc839 100644 --- a/src/tests/JIT/opt/OSR/normalizeonload.csproj +++ b/src/tests/JIT/opt/OSR/normalizeonload.csproj @@ -2,7 +2,6 @@ true - True True diff --git a/src/tests/JIT/opt/OSR/originalstackalloc.csproj b/src/tests/JIT/opt/OSR/originalstackalloc.csproj index b07fc4f3823f..44bab58ad10a 100644 --- a/src/tests/JIT/opt/OSR/originalstackalloc.csproj +++ b/src/tests/JIT/opt/OSR/originalstackalloc.csproj @@ -2,7 +2,6 @@ true - True true diff --git a/src/tests/JIT/opt/OSR/osrcontainstry.csproj b/src/tests/JIT/opt/OSR/osrcontainstry.csproj index b07fc4f3823f..44bab58ad10a 100644 --- a/src/tests/JIT/opt/OSR/osrcontainstry.csproj +++ b/src/tests/JIT/opt/OSR/osrcontainstry.csproj @@ -2,7 +2,6 @@ true - True true diff --git a/src/tests/JIT/opt/OSR/pinnedlocal.csproj b/src/tests/JIT/opt/OSR/pinnedlocal.csproj index 36e30677dedf..cce19ee11649 100644 --- a/src/tests/JIT/opt/OSR/pinnedlocal.csproj +++ b/src/tests/JIT/opt/OSR/pinnedlocal.csproj @@ -2,7 +2,6 @@ true - True True diff --git a/src/tests/JIT/opt/OSR/promoted.csproj b/src/tests/JIT/opt/OSR/promoted.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/promoted.csproj +++ b/src/tests/JIT/opt/OSR/promoted.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/shadowparam.csproj b/src/tests/JIT/opt/OSR/shadowparam.csproj index b54fcc5b5436..a4cc9d0594f9 100644 --- a/src/tests/JIT/opt/OSR/shadowparam.csproj +++ b/src/tests/JIT/opt/OSR/shadowparam.csproj @@ -1,6 +1,5 @@ - True True diff --git a/src/tests/JIT/opt/OSR/shortenregisteredlocal.csproj b/src/tests/JIT/opt/OSR/shortenregisteredlocal.csproj index 5b958079e77f..1a79fa62ffa2 100644 --- a/src/tests/JIT/opt/OSR/shortenregisteredlocal.csproj +++ b/src/tests/JIT/opt/OSR/shortenregisteredlocal.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/synchronized.csproj b/src/tests/JIT/opt/OSR/synchronized.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/synchronized.csproj +++ b/src/tests/JIT/opt/OSR/synchronized.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/tailpgo.csproj b/src/tests/JIT/opt/OSR/tailpgo.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/tailpgo.csproj +++ b/src/tests/JIT/opt/OSR/tailpgo.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/tailpgo2.csproj b/src/tests/JIT/opt/OSR/tailpgo2.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/tailpgo2.csproj +++ b/src/tests/JIT/opt/OSR/tailpgo2.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/tailrecurse.csproj b/src/tests/JIT/opt/OSR/tailrecurse.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/tailrecurse.csproj +++ b/src/tests/JIT/opt/OSR/tailrecurse.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/tailrecursetry.csproj b/src/tests/JIT/opt/OSR/tailrecursetry.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/tailrecursetry.csproj +++ b/src/tests/JIT/opt/OSR/tailrecursetry.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/tailrecursetry2.csproj b/src/tests/JIT/opt/OSR/tailrecursetry2.csproj index b07fc4f3823f..44bab58ad10a 100644 --- a/src/tests/JIT/opt/OSR/tailrecursetry2.csproj +++ b/src/tests/JIT/opt/OSR/tailrecursetry2.csproj @@ -2,7 +2,6 @@ true - True true diff --git a/src/tests/JIT/opt/OSR/twoosrmethods.csproj b/src/tests/JIT/opt/OSR/twoosrmethods.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/twoosrmethods.csproj +++ b/src/tests/JIT/opt/OSR/twoosrmethods.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/OSR/twoosrmethods1.csproj b/src/tests/JIT/opt/OSR/twoosrmethods1.csproj index 13fe7de074f9..5de43644ba99 100644 --- a/src/tests/JIT/opt/OSR/twoosrmethods1.csproj +++ b/src/tests/JIT/opt/OSR/twoosrmethods1.csproj @@ -2,7 +2,6 @@ true - True diff --git a/src/tests/JIT/opt/RangeChecks/Overflow.cs b/src/tests/JIT/opt/RangeChecks/Overflow.cs new file mode 100644 index 000000000000..27ebc3b3a039 --- /dev/null +++ b/src/tests/JIT/opt/RangeChecks/Overflow.cs @@ -0,0 +1,26 @@ +using System; +using System.Runtime.CompilerServices; +using Xunit; + +public class RangeCheck_Overflow +{ + [Fact] + public static int TestEntryPoint() + { + return Overflow([10, 0, 20, 0, 30, 0, 40]); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static int Overflow(Span a) + { + // CHECK: CORINFO_HELP_RNGCHKFAIL + + int sum = 0; + for (int i = 0; i < a.Length; i += 2) + { + sum += a[i]; + } + + return sum; + } +} diff --git a/src/tests/JIT/opt/RangeChecks/Overflow.csproj b/src/tests/JIT/opt/RangeChecks/Overflow.csproj new file mode 100644 index 000000000000..842f0d76a261 --- /dev/null +++ b/src/tests/JIT/opt/RangeChecks/Overflow.csproj @@ -0,0 +1,16 @@ + + + None + True + + true + + + + true + + + + + + diff --git a/src/tests/JIT/opt/RedundantBranch/RedundantBranchAnd.csproj b/src/tests/JIT/opt/RedundantBranch/RedundantBranchAnd.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/opt/RedundantBranch/RedundantBranchAnd.csproj +++ b/src/tests/JIT/opt/RedundantBranch/RedundantBranchAnd.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/opt/RedundantBranch/RedundantBranchOr.csproj b/src/tests/JIT/opt/RedundantBranch/RedundantBranchOr.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/opt/RedundantBranch/RedundantBranchOr.csproj +++ b/src/tests/JIT/opt/RedundantBranch/RedundantBranchOr.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/opt/RedundantBranch/RedundantBranchUnsigned.csproj b/src/tests/JIT/opt/RedundantBranch/RedundantBranchUnsigned.csproj index 4f39869373b7..de6d5e08882e 100644 --- a/src/tests/JIT/opt/RedundantBranch/RedundantBranchUnsigned.csproj +++ b/src/tests/JIT/opt/RedundantBranch/RedundantBranchUnsigned.csproj @@ -1,6 +1,5 @@ - True diff --git a/src/tests/JIT/opt/Vectorization/UnrollEqualsStartsWith.csproj b/src/tests/JIT/opt/Vectorization/UnrollEqualsStartsWith.csproj index c9327d09cb4d..87fba405d81e 100644 --- a/src/tests/JIT/opt/Vectorization/UnrollEqualsStartsWith.csproj +++ b/src/tests/JIT/opt/Vectorization/UnrollEqualsStartsWith.csproj @@ -1,6 +1,10 @@ True + + true + + true diff --git a/src/tests/JIT/opt/perf/doublealign/Arrays.csproj b/src/tests/JIT/opt/perf/doublealign/Arrays.csproj index 3dfec14b80d7..1c9bde194b36 100644 --- a/src/tests/JIT/opt/perf/doublealign/Arrays.csproj +++ b/src/tests/JIT/opt/perf/doublealign/Arrays.csproj @@ -4,10 +4,7 @@ true - None - True - True True true diff --git a/src/tests/JIT/opt/perf/doublealign/Locals.csproj b/src/tests/JIT/opt/perf/doublealign/Locals.csproj index a16058b17185..e2d8516deb97 100644 --- a/src/tests/JIT/opt/perf/doublealign/Locals.csproj +++ b/src/tests/JIT/opt/perf/doublealign/Locals.csproj @@ -5,10 +5,7 @@ 1 - None - True - True True True True diff --git a/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_d.csproj b/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_d.csproj index 56ec63049cce..8bbfd7a98aec 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_d.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_d.csproj @@ -8,11 +8,8 @@ 1 - Full False - True - True diff --git a/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_do.csproj b/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_do.csproj index 678da7a02c25..a1195ae0d381 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_do.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_do.csproj @@ -1,10 +1,7 @@ - Full True - True - True diff --git a/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_r.csproj b/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_r.csproj index 000c91d91ac7..fc1fb170d61e 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_r.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_r.csproj @@ -7,11 +7,8 @@ true - None False - True - True diff --git a/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_ro.csproj b/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_ro.csproj index 7350ddf7a43f..500ffeed56ea 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_ro.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_ro.csproj @@ -1,10 +1,7 @@ - None True - True - True diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived1.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived1.csproj index 72716afa014e..53ea4c947a3b 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived1.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived1.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived10.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived10.csproj index 5022795c8924..86acaf88409b 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived10.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived10.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived11.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived11.csproj index bee1144905cc..332d6c6f6344 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived11.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived11.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived12.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived12.csproj index 32d68c06de2f..6a7f17e951dd 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived12.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived12.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived13.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived13.csproj index 9fc87e0d0c11..44f05c35c9a0 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived13.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived13.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived14.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived14.csproj index e66cc156c56f..547b5d5bb749 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived14.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived14.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived15.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived15.csproj index 8681d1da5a4f..d1f7d51ecbad 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived15.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived15.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived16.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived16.csproj index 960ea68a5419..1a5d4c0e317b 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived16.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived16.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived17.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived17.csproj index 2b5ce3271e7b..ac43567bba71 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived17.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived17.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived18.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived18.csproj index 328decd7c77c..1bab325a88ac 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived18.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived18.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived19.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived19.csproj index 62809c88b79e..cb05d5ead398 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived19.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived19.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived2.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived2.csproj index 590bf84ed7b3..e7749c70e099 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived2.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived2.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived20.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived20.csproj index 50c4b2882580..abda5454bcf7 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived20.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived20.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived3.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived3.csproj index ef682b24a9b9..1c83b78fe445 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived3.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived3.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived4.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived4.csproj index 42cc08782155..9747447a98b7 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived4.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived4.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived5.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived5.csproj index 6e93bcff53a2..3c5b23a19e16 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived5.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived5.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived6.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived6.csproj index f8a4f24059a6..5327bedeaddf 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived6.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived6.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived7.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived7.csproj index b015ff2ceb8a..22b3799f0ddf 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived7.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived7.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived8.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived8.csproj index 88d6f2dc7867..0e5c64fdc18b 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived8.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived8.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived9.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived9.csproj index 0bdd72cdf641..1a4d2df549e2 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived9.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/cderived9.csproj @@ -3,7 +3,6 @@ Library - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_d.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_d.csproj index 13360ecb6453..56119d622780 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_d.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_d.csproj @@ -3,7 +3,6 @@ 1 - Full diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_do.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_do.csproj index bbd6c5d03c1b..734850fd485f 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_do.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_do.csproj @@ -3,7 +3,6 @@ 1 - Full True diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_r.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_r.csproj index 7e14fe5f8192..6a3c46274bb1 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_r.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_r.csproj @@ -3,7 +3,6 @@ 1 - None diff --git a/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_ro.csproj b/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_ro.csproj index 747221ee8bc2..da30029f8b11 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_ro.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/hashcode/ctest1_cs_ro.csproj @@ -3,7 +3,6 @@ 1 - None True diff --git a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest1.csproj b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest1.csproj index c878dbfde60b..1377cc5590cb 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest1.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest1.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest10.csproj b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest10.csproj index 39bd2a7d4bef..7f1af917234b 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest10.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest10.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest2.csproj b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest2.csproj index 7f471baa9623..82fe052d2eeb 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest2.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest2.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest3.csproj b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest3.csproj index 3531b9051aa5..b1628123337b 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest3.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest3.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest4.csproj b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest4.csproj index 99b15cb4b336..72faf24f88bd 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest4.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest4.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest5.csproj b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest5.csproj index b5820ddce6db..807efced7093 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest5.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest5.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest6.csproj b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest6.csproj index 78bde8fe8f3c..0c195d61495c 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest6.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest6.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest7.csproj b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest7.csproj index 4125bb06c23f..c8d23f0a124a 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest7.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest7.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest8.csproj b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest8.csproj index fac2eb0a90b2..33504863da50 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest8.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest8.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest9.csproj b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest9.csproj index e6627145111e..46dc949a20a0 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest9.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/manyintf/itest9.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_d.csproj b/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_d.csproj index 317743c8ef60..b9995de61431 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_d.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_d.csproj @@ -5,11 +5,8 @@ 1 - Full False - True - True diff --git a/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_do.csproj b/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_do.csproj index 36a3d52e51c1..e78a79aa21e7 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_do.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_do.csproj @@ -5,11 +5,8 @@ 1 - Full True - True - True diff --git a/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_r.csproj b/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_r.csproj index 3653a777388c..a42ad98f8860 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_r.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_r.csproj @@ -5,11 +5,8 @@ 1 - None False - True - True diff --git a/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_ro.csproj b/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_ro.csproj index 48a78d99def6..b903f531af78 100644 --- a/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_ro.csproj +++ b/src/tests/JIT/opt/virtualstubdispatch/mixed/mixed_cs_ro.csproj @@ -5,11 +5,8 @@ 1 - None True - True - True diff --git a/src/tests/JIT/superpmi/superpmicollect.csproj b/src/tests/JIT/superpmi/superpmicollect.csproj index df3d304510a3..680377625aae 100644 --- a/src/tests/JIT/superpmi/superpmicollect.csproj +++ b/src/tests/JIT/superpmi/superpmicollect.csproj @@ -30,9 +30,10 @@ <_SpmiTestProjects Include="..\Performance\CodeQuality\Bytemark\Bytemark.csproj" /> <_SpmiTestProjects Include="..\Performance\CodeQuality\Roslyn\CscBench.csproj" /> - <_SpmiTestProjects Include="..\Methodical\fp\exgen\10w5d_cs_do.csproj" /> + <_SpmiTestProjects Include="..\Methodical\cctor\xassem\xprecise1_cs_do.csproj" /> + <_SpmiTestSupportProjects Include="..\Methodical\cctor\xassem\testlib_xassem.csproj" /> - + Build _SpmiTest %(FileName) diff --git a/src/tests/Loader/binding/tracing/BinderTracingTest.Basic.csproj b/src/tests/Loader/binding/tracing/BinderTracingTest.Basic.csproj index aea7260ca1a9..c5b8d00433f9 100644 --- a/src/tests/Loader/binding/tracing/BinderTracingTest.Basic.csproj +++ b/src/tests/Loader/binding/tracing/BinderTracingTest.Basic.csproj @@ -1,10 +1,4 @@ - - - true - - true - diff --git a/src/tests/Loader/binding/tracing/BinderTracingTest.ResolutionFlow.csproj b/src/tests/Loader/binding/tracing/BinderTracingTest.ResolutionFlow.csproj index 07f4907e396c..7d3485339fd9 100644 --- a/src/tests/Loader/binding/tracing/BinderTracingTest.ResolutionFlow.csproj +++ b/src/tests/Loader/binding/tracing/BinderTracingTest.ResolutionFlow.csproj @@ -1,10 +1,5 @@ - - true - - true - true true diff --git a/src/tests/Loader/binding/tracing/BinderTracingTest.cs b/src/tests/Loader/binding/tracing/BinderTracingTest.cs index a48e3ab419dd..2f246ee8eeb0 100644 --- a/src/tests/Loader/binding/tracing/BinderTracingTest.cs +++ b/src/tests/Loader/binding/tracing/BinderTracingTest.cs @@ -85,9 +85,6 @@ public static bool RunAllTests() foreach (var method in methods) { BinderTestAttribute attribute = method.GetCustomAttribute(); - if (attribute.Isolate && Environment.GetEnvironmentVariable("DOTNET_GCStress") != null) - continue; - bool success = attribute.Isolate ? RunTestInSeparateProcess(method) : RunSingleTest(method); diff --git a/src/tests/Loader/binding/tracing/BinderTracingTest.targets b/src/tests/Loader/binding/tracing/BinderTracingTest.targets index 5851e914132d..c2165d7c89e6 100644 --- a/src/tests/Loader/binding/tracing/BinderTracingTest.targets +++ b/src/tests/Loader/binding/tracing/BinderTracingTest.targets @@ -4,6 +4,12 @@ true false + + true + + true + + true diff --git a/src/tests/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape_r.ilproj b/src/tests/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape_r.ilproj index 213376d19b11..10ede01cc9c5 100644 --- a/src/tests/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape_r.ilproj +++ b/src/tests/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape_r.ilproj @@ -3,9 +3,6 @@ true - - - diff --git a/src/tests/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics_r.ilproj b/src/tests/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics_r.ilproj index 637d7430104a..df4e8d33431f 100644 --- a/src/tests/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics_r.ilproj +++ b/src/tests/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics_r.ilproj @@ -3,9 +3,6 @@ true - - - diff --git a/src/tests/Loader/classloader/InlineArray/InlineArrayInvalid.csproj b/src/tests/Loader/classloader/InlineArray/InlineArrayInvalid.csproj index 8323d950dff7..098ebbb26a69 100644 --- a/src/tests/Loader/classloader/InlineArray/InlineArrayInvalid.csproj +++ b/src/tests/Loader/classloader/InlineArray/InlineArrayInvalid.csproj @@ -3,6 +3,8 @@ true true + + false diff --git a/src/tests/Loader/classloader/RefFields/Validate.csproj b/src/tests/Loader/classloader/RefFields/Validate.csproj index f8e94ce317a3..8d5547ca7cf0 100644 --- a/src/tests/Loader/classloader/RefFields/Validate.csproj +++ b/src/tests/Loader/classloader/RefFields/Validate.csproj @@ -4,6 +4,8 @@ true true true + + false diff --git a/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape_r.ilproj b/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape_r.ilproj index fce818ebdb7b..263d3cdf307d 100644 --- a/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape_r.ilproj +++ b/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape_r.ilproj @@ -3,9 +3,6 @@ true - - - diff --git a/src/tests/Loader/classloader/StaticVirtualMethods/GenericContext/GenericContextCommonCs.csproj b/src/tests/Loader/classloader/StaticVirtualMethods/GenericContext/GenericContextCommonCs.csproj index 78ae4cdeb270..88c0d86a674f 100644 --- a/src/tests/Loader/classloader/StaticVirtualMethods/GenericContext/GenericContextCommonCs.csproj +++ b/src/tests/Loader/classloader/StaticVirtualMethods/GenericContext/GenericContextCommonCs.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/Loader/classloader/StaticVirtualMethods/TypeHierarchy/TypeHierarchyCommonCs.csproj b/src/tests/Loader/classloader/StaticVirtualMethods/TypeHierarchy/TypeHierarchyCommonCs.csproj index 5bbda6c8b9f3..9694afc6e42c 100644 --- a/src/tests/Loader/classloader/StaticVirtualMethods/TypeHierarchy/TypeHierarchyCommonCs.csproj +++ b/src/tests/Loader/classloader/StaticVirtualMethods/TypeHierarchy/TypeHierarchyCommonCs.csproj @@ -2,9 +2,6 @@ Library - - - diff --git a/src/tests/Loader/classloader/explicitlayout/Regressions/100220/Runtime_100220.cs b/src/tests/Loader/classloader/explicitlayout/Regressions/100220/Runtime_100220.cs new file mode 100644 index 000000000000..043acbe73252 --- /dev/null +++ b/src/tests/Loader/classloader/explicitlayout/Regressions/100220/Runtime_100220.cs @@ -0,0 +1,189 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Xunit; + +public static class Runtime_100220 +{ + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/100220", TestRuntimes.Mono)] + // Also, Mono needs RuntimeHelpers.GetRawObjectDataSize or equivalent to get an object size + public static void TestEntryPoint() + { + if (IntPtr.Size == 8) + { + // Classes + Assert.Equal(16, ObjectSize()); + Assert.Equal(16, ObjectSize()); + Assert.Equal(16, ObjectSize()); + Assert.Equal(16, ObjectSize()); + Assert.Equal(1000, ObjectSize()); + Assert.Equal(24, ObjectSize()); + Assert.Equal(40, ObjectSize()); + Assert.Equal(48, ObjectSize()); + Assert.Equal(32, ObjectSize()); + Assert.Equal(16, ObjectSize()); + + // Structs + Assert.Equal(16, Unsafe.SizeOf()); + Assert.Equal(16, Unsafe.SizeOf()); + Assert.Equal(16, Unsafe.SizeOf()); + Assert.Equal(16, Unsafe.SizeOf()); + Assert.Equal(1000, Unsafe.SizeOf()); + } + else + { + // Classes + Assert.Equal(8, ObjectSize()); + Assert.Equal(12, ObjectSize()); + Assert.Equal(8, ObjectSize()); + Assert.Equal(12, ObjectSize()); + Assert.Equal(1000, ObjectSize()); + Assert.Equal(20, ObjectSize()); + Assert.Equal(36, ObjectSize()); + Assert.Equal(44, ObjectSize()); + Assert.Equal(28, ObjectSize()); + Assert.Equal(8, ObjectSize()); + + // Structs + Assert.Equal(8, Unsafe.SizeOf()); + Assert.Equal(8, Unsafe.SizeOf()); + Assert.Equal(12, Unsafe.SizeOf()); + Assert.Equal(8, Unsafe.SizeOf()); + Assert.Equal(1000, Unsafe.SizeOf()); + } + + // Field offsets: + Assert.Equal("(5, 3, 4, 1, 2, 6)", FieldOffsets(new SubclassSubclassSeq { A = 1, B = 2, C = 3, D = 4, E = 5, F = 6 }).ToString()); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static object FieldOffsets(SubclassSubclassSeq f) => (f.E, f.C, f.D, f.A, f.B, f.F); + + [StructLayout(LayoutKind.Sequential, Size = 20)] + public class BaseClassSeq + { + public byte A; + public nint B; + } + + [StructLayout(LayoutKind.Sequential, Size = 20)] + public class BaseClassWithGcSeq + { + public byte A; + public string B; + } + + public class SubclassOfBaseWithGcSeq : BaseClassWithGcSeq + { + public byte C; + } + + [StructLayout(LayoutKind.Sequential, Size = 16)] + public class SubclassSeq : BaseClassSeq + { + public byte C; + public nint D; + } + + [StructLayout(LayoutKind.Sequential, Size = 32)] + public class SubclassWithGcSeq : BaseClassSeq + { + public byte C; + public object D; + } + + public class SubclassSubclassSeq : SubclassSeq + { + public byte E; + public nint F; + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + private static int ObjectSize() where T : new() + { + return (int)(nuint)typeof(RuntimeHelpers) + .GetMethod("GetRawObjectDataSize", BindingFlags.Static | BindingFlags.NonPublic) + .Invoke(null, [new T()]); + } + + private class MyClassAuto + { + private byte[] a; + private byte b; + } + + [StructLayout(LayoutKind.Explicit, Size = 1000)] + private class MyClass1000Exp + { + [FieldOffset(0)] + private byte[] a; + [FieldOffset(8)] + private byte b; + } + + [StructLayout(LayoutKind.Sequential, Size = 1000)] + private class MyClass1000Seq + { + private byte[] a; + private byte b; + } + + [StructLayout(LayoutKind.Explicit, Size = 1000)] + private class MyClass1000NoGcExp + { + [FieldOffset(0)] + private nint a; + [FieldOffset(8)] + private byte b; + } + + [StructLayout(LayoutKind.Sequential, Size = 1000)] + private class MyClass1000NoGcSeq + { + private nint a; + private byte b; + } + + private struct MyStructAuto + { + private byte[] a; + private byte b; + } + + [StructLayout(LayoutKind.Explicit, Size = 1000)] + private struct MyStruct1000Exp + { + [FieldOffset(0)] + private byte[] a; + [FieldOffset(8)] + private byte b; + } + + [StructLayout(LayoutKind.Sequential, Size = 1000)] + private struct MyStruct1000Seq + { + private byte[] a; + private byte b; + } + + [StructLayout(LayoutKind.Explicit, Size = 9)] + private struct MyStruct9Exp + { + [FieldOffset(0)] + private byte[] a; + [FieldOffset(8)] + private byte b; + } + + [StructLayout(LayoutKind.Sequential, Size = 9)] + private struct MyStruct9Seq + { + private byte[] a; + private byte b; + } +} diff --git a/src/tests/Loader/classloader/explicitlayout/Regressions/100220/Runtime_100220.csproj b/src/tests/Loader/classloader/explicitlayout/Regressions/100220/Runtime_100220.csproj new file mode 100644 index 000000000000..efc38a9429de --- /dev/null +++ b/src/tests/Loader/classloader/explicitlayout/Regressions/100220/Runtime_100220.csproj @@ -0,0 +1,8 @@ + + + true + + + + + diff --git a/src/tests/Loader/classloader/generics/ByRefLike/InvalidCSharp.il b/src/tests/Loader/classloader/generics/ByRefLike/InvalidCSharp.il index 72f0dc67f69e..8480a5cf4520 100644 --- a/src/tests/Loader/classloader/generics/ByRefLike/InvalidCSharp.il +++ b/src/tests/Loader/classloader/generics/ByRefLike/InvalidCSharp.il @@ -73,6 +73,26 @@ .field public !T Field + .method public hidebysig + instance !T CreateDefaultInstance() cil managed + { + .locals init ( + [0] !T + ) + ldloca.s 0 + initobj !T + ldloc.0 + ret + } + + .method public hidebysig + instance class [System.Runtime]System.Type GetGenericType() cil managed + { + ldtoken !T + call class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle) + ret + } + .method public hidebysig instance object BoxAsObject(!T) cil managed { @@ -129,6 +149,41 @@ ret } + .method public hidebysig + instance bool BoxBranchToOther(!T) cil managed + { + ldarg.1 + // Begin sequence + box !!U + brfalse.s NEXT_1 + // End sequence + NEXT_1: + + ldarg.1 + // Begin sequence + box !!U + brfalse NEXT_2 + // End sequence + NEXT_2: + + ldarg.1 + // Begin sequence + box !!U + brtrue.s NEXT_3 + // End sequence + NEXT_3: + + ldarg.1 + // Begin sequence + box !!U + brtrue NEXT_4 + // End sequence + NEXT_4: + + ldc.i4.1 + ret + } + .method public hidebysig instance bool BoxBranch_WithSideEffects(!T&) cil managed { @@ -264,6 +319,26 @@ ret } + .method public hidebysig + instance bool BoxIsinstBranch_UsingTypeConstraints(class InvalidCSharp.EmptyInterface) cil managed + { + .locals init ( + [0] !!U + ) + ldarg.1 + isinst !!U + brfalse.s NOT_U + ldarg.1 + isinst !!U + unbox.any !!U + stloc.0 + ldc.i4.0 + ret + NOT_U: + ldc.i4.1 + ret + } + .method public hidebysig instance bool AllocArrayOfT() cil managed aggressiveinlining { @@ -386,6 +461,19 @@ { } +.class public auto ansi beforefieldinit InvalidCSharp.ClassWithInterface + extends [System.Runtime]System.Object + implements InvalidCSharp.EmptyInterface +{ + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + ldarg.0 + call instance void [System.Runtime]System.Object::.ctor() + ret + } +} + // Generic substitution of allow-byreflike with allow-byreflike .class interface public auto ansi abstract InvalidCSharp.GenericDerivedInterface_OverByRef`1 implements class InvalidCSharp.GenericInterface_Over`1 @@ -564,6 +652,24 @@ ret } + .method public hidebysig static + string CreateDefaultInstance() cil managed + { + .locals init ( + [0] valuetype InvalidCSharp.GenericByRefLike_Over`1 + ) + + ldloca.s 0 + initobj valuetype InvalidCSharp.GenericByRefLike_Over`1 + ldloca.s 0 + call instance !0 valuetype InvalidCSharp.GenericByRefLike_Over`1::CreateDefaultInstance() + pop + ldloca.s 0 + call instance class [System.Runtime]System.Type valuetype InvalidCSharp.GenericByRefLike_Over`1::GetGenericType() + callvirt instance string [System.Runtime]System.Object::ToString() + ret + } + .method public hidebysig static object BoxAsObject() cil managed { @@ -613,6 +719,18 @@ call instance bool valuetype InvalidCSharp.GenericByRefLike_Over`1::BoxBranch(!0) pop + ldloca.s 0 + ldloc 0 + ldfld !0 valuetype InvalidCSharp.GenericByRefLike_Over`1::Field + call instance bool valuetype InvalidCSharp.GenericByRefLike_Over`1::BoxBranchToOther(!0) + pop + + ldloca.s 0 + ldloc 0 + ldfld !0 valuetype InvalidCSharp.GenericByRefLike_Over`1::Field + call instance bool valuetype InvalidCSharp.GenericByRefLike_Over`1::BoxBranchToOther(!0) + pop + ldloca.s 0 ldloca.s 0 ldflda !0 valuetype InvalidCSharp.GenericByRefLike_Over`1::Field @@ -657,6 +775,11 @@ ldloca.s 0 ldflda !0 valuetype InvalidCSharp.GenericByRefLike_Over`1::Field call instance bool valuetype InvalidCSharp.GenericByRefLike_Over`1::BoxIsinstBranch_WithSideEffects(!0&) + pop + + ldloca.s 0 + newobj instance void InvalidCSharp.ClassWithInterface::.ctor() + call instance bool valuetype InvalidCSharp.GenericByRefLike_Over`1::BoxIsinstBranch_UsingTypeConstraints(class InvalidCSharp.EmptyInterface) ret } diff --git a/src/tests/Loader/classloader/generics/ByRefLike/Validate.cs b/src/tests/Loader/classloader/generics/ByRefLike/Validate.cs index 50a7b42e06ed..867cccd32d5b 100644 --- a/src/tests/Loader/classloader/generics/ByRefLike/Validate.cs +++ b/src/tests/Loader/classloader/generics/ByRefLike/Validate.cs @@ -21,6 +21,7 @@ public static void Validate_TypeLoad() Console.WriteLine($" -- Instantiate: {Exec.GenericValueType()}"); Console.WriteLine($" -- Instantiate: {Exec.GenericByRefLike()}"); Console.WriteLine($" -- Instantiate: {Exec.GenericByRefLike_ConstraintsAreIndependent_Int32_Int32()}"); + Console.WriteLine($" -- Create: {Exec.CreateDefaultInstance()}"); Assert.Throws(() => { Exec.GenericClass_Invalid(); }); Assert.Throws(() => { Exec.GenericInterface_Invalid(); }); diff --git a/src/tests/Loader/classloader/regressions/GitHub_93597/GitHub_93597.cs b/src/tests/Loader/classloader/regressions/GitHub_93597/GitHub_93597.cs index 4b5a375faf17..ca4c4417cc90 100644 --- a/src/tests/Loader/classloader/regressions/GitHub_93597/GitHub_93597.cs +++ b/src/tests/Loader/classloader/regressions/GitHub_93597/GitHub_93597.cs @@ -3,10 +3,12 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; +using TestLibrary; using Xunit; public class ReproGH93597 { [Fact] + [ActiveIssue("https://github.com/dotnet/runtimelab/issues/155", typeof(PlatformDetection), nameof(PlatformDetection.IsNonZeroLowerBoundArrayNotSupported))] public static int TestEntryPoint() { var expected = new int[] {5,4,3,2,1}; diff --git a/src/tests/Loader/classloader/regressions/GitHub_93597/GitHub_93597.csproj b/src/tests/Loader/classloader/regressions/GitHub_93597/GitHub_93597.csproj index 0a04d2e9323a..97bdc5b034ce 100644 --- a/src/tests/Loader/classloader/regressions/GitHub_93597/GitHub_93597.csproj +++ b/src/tests/Loader/classloader/regressions/GitHub_93597/GitHub_93597.csproj @@ -1,9 +1,6 @@ - - - true - + diff --git a/src/tests/MergedTestRunner.targets b/src/tests/MergedTestRunner.targets index 686ba0d11d49..91e14677b906 100644 --- a/src/tests/MergedTestRunner.targets +++ b/src/tests/MergedTestRunner.targets @@ -17,6 +17,11 @@ - + + diff --git a/src/tests/Regressions/coreclr/GitHub_100536/test100536.cs b/src/tests/Regressions/coreclr/GitHub_100536/test100536.cs new file mode 100644 index 000000000000..8d4626814412 --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_100536/test100536.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Xunit; + +public class Test100536 +{ + [DllImport("__test", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Nonexistent")] + private static extern IntPtr Nonexistent(); + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] + private static void GarbleStack() + { + Span local = stackalloc byte[4096]; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Test() + { + try + { + Nonexistent(); + } + catch (Exception ex) + { + Console.WriteLine($"Expected exception {ex} caught"); + } + } + + [Fact] + public static void TestEntryPoint() + { + Test(); + GarbleStack(); + GC.Collect(); + } +} + diff --git a/src/tests/Regressions/coreclr/GitHub_100536/test100536.csproj b/src/tests/Regressions/coreclr/GitHub_100536/test100536.csproj new file mode 100644 index 000000000000..fa208f1214f9 --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_100536/test100536.csproj @@ -0,0 +1,11 @@ + + + 1 + + + + + + + + diff --git a/src/tests/Regressions/coreclr/GitHub_17398/test17398.csproj b/src/tests/Regressions/coreclr/GitHub_17398/test17398.csproj index e3832670314d..7d56ee3b4c5a 100644 --- a/src/tests/Regressions/coreclr/GitHub_17398/test17398.csproj +++ b/src/tests/Regressions/coreclr/GitHub_17398/test17398.csproj @@ -5,7 +5,6 @@ true - True diff --git a/src/tests/Regressions/coreclr/GitHub_22888/test22888.csproj b/src/tests/Regressions/coreclr/GitHub_22888/test22888.csproj index f2a1d423be02..f74b821627d9 100644 --- a/src/tests/Regressions/coreclr/GitHub_22888/test22888.csproj +++ b/src/tests/Regressions/coreclr/GitHub_22888/test22888.csproj @@ -3,6 +3,9 @@ true true + + + true diff --git a/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs b/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs index e1029797bf12..c64306a27bdc 100644 --- a/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs +++ b/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs @@ -63,7 +63,6 @@ private void Add(Struct a) => } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_AccessStaticFieldClass() { Console.WriteLine($"Running {nameof(Verify_Generic_AccessStaticFieldClass)}"); @@ -99,7 +98,6 @@ public static void Verify_Generic_AccessStaticFieldClass() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_AccessFieldClass() { Console.WriteLine($"Running {nameof(Verify_Generic_AccessFieldClass)}"); @@ -142,7 +140,6 @@ sealed class Derived2 : GenericBase } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_InheritanceMethodResolution() { string expect = "abc"; @@ -232,7 +229,6 @@ sealed class Accessors } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_CallCtor() { Console.WriteLine($"Running {nameof(Verify_Generic_CallCtor)}"); @@ -284,7 +280,6 @@ public static void Verify_Generic_CallCtor() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_GenericTypeNonGenericInstanceMethod() { Console.WriteLine($"Running {nameof(Verify_Generic_GenericTypeNonGenericInstanceMethod)}"); @@ -315,7 +310,6 @@ public static void Verify_Generic_GenericTypeNonGenericInstanceMethod() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_GenericTypeGenericInstanceMethod() { Console.WriteLine($"Running {nameof(Verify_Generic_GenericTypeGenericInstanceMethod)}"); @@ -358,7 +352,6 @@ public static void Verify_Generic_GenericTypeGenericInstanceMethod() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_GenericTypeNonGenericStaticMethod() { Console.WriteLine($"Running {nameof(Verify_Generic_GenericTypeNonGenericStaticMethod)}"); @@ -370,7 +363,6 @@ public static void Verify_Generic_GenericTypeNonGenericStaticMethod() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_GenericTypeGenericStaticMethod() { Console.WriteLine($"Running {nameof(Verify_Generic_GenericTypeGenericStaticMethod)}"); @@ -445,7 +437,6 @@ class Invalid } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)] public static void Verify_Generic_InvalidUseUnsafeAccessor() { Console.WriteLine($"Running {nameof(Verify_Generic_InvalidUseUnsafeAccessor)}"); diff --git a/src/tests/baseservices/compilerservices/modulector/runmoduleconstructor.cs b/src/tests/baseservices/compilerservices/modulector/runmoduleconstructor.cs index c3aa06934246..f13ba23fa553 100644 --- a/src/tests/baseservices/compilerservices/modulector/runmoduleconstructor.cs +++ b/src/tests/baseservices/compilerservices/modulector/runmoduleconstructor.cs @@ -14,12 +14,13 @@ public class RuntimeHelperTest [Fact] public static void TestEntryPoint() { + const string asmName = "moduleCctor"; AssemblyLoadContext resolver0 = AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()); - Assembly asm0 = resolver0.LoadFromAssemblyName(new AssemblyName("moduleCctor")); + Assembly asm0 = resolver0.LoadFromAssemblyName(new AssemblyName(asmName)); Module mod = asm0.ManifestModule; RuntimeHelpers.RunModuleConstructor(mod.ModuleHandle); - var oType = asm0.GetType("IntHolder",true); + var oType = Type.GetType("IntHolder, " + asmName,true); MethodInfo check = oType.GetMethod("Check"); MethodInfo assign = oType.GetMethod("Assign"); diff --git a/src/tests/baseservices/exceptions/regressions/Dev11/154243/dynamicmethodliveness.csproj b/src/tests/baseservices/exceptions/regressions/Dev11/154243/dynamicmethodliveness.csproj index c4643b642af3..8f92451cf4f8 100644 --- a/src/tests/baseservices/exceptions/regressions/Dev11/154243/dynamicmethodliveness.csproj +++ b/src/tests/baseservices/exceptions/regressions/Dev11/154243/dynamicmethodliveness.csproj @@ -4,6 +4,8 @@ true true 1 + + true diff --git a/src/tests/baseservices/exceptions/sharedexceptions/emptystacktrace/oomexception01.cs b/src/tests/baseservices/exceptions/sharedexceptions/emptystacktrace/oomexception01.cs index 3c6305620c64..e72e4cdcc4a5 100644 --- a/src/tests/baseservices/exceptions/sharedexceptions/emptystacktrace/oomexception01.cs +++ b/src/tests/baseservices/exceptions/sharedexceptions/emptystacktrace/oomexception01.cs @@ -53,11 +53,19 @@ public void CreateAndThrow() { oomStack = oomStack.Substring(0, oomStack.IndexOf(':') - 1); } + if (oomStack.IndexOf("+ 0x") != -1) + { + oomStack = oomStack.Substring(0, oomStack.IndexOf("+ 0x") - 1); + } if (expectedStack.IndexOf(':') != -1) { expectedStack = expectedStack.Substring(0, expectedStack.IndexOf(':') - 1); } + if (expectedStack.IndexOf("+ 0x") != -1) + { + expectedStack = expectedStack.Substring(0, expectedStack.IndexOf("+ 0x") - 1); + } if (oomStack != expectedStack) { diff --git a/src/tests/baseservices/exceptions/simple/ParallelCrashTester.csproj b/src/tests/baseservices/exceptions/simple/ParallelCrashTester.csproj index f60f1f053aaa..d298cd5e42dd 100644 --- a/src/tests/baseservices/exceptions/simple/ParallelCrashTester.csproj +++ b/src/tests/baseservices/exceptions/simple/ParallelCrashTester.csproj @@ -5,6 +5,8 @@ true true + + true diff --git a/src/tests/baseservices/invalid_operations/InvalidOperations.csproj b/src/tests/baseservices/invalid_operations/InvalidOperations.csproj index 5f4c03e91ae1..1c5f1bf80013 100644 --- a/src/tests/baseservices/invalid_operations/InvalidOperations.csproj +++ b/src/tests/baseservices/invalid_operations/InvalidOperations.csproj @@ -3,6 +3,8 @@ true true + + false diff --git a/src/tests/baseservices/threading/threadpool/bindhandle/Directory.Build.props b/src/tests/baseservices/threading/threadpool/bindhandle/Directory.Build.props new file mode 100644 index 000000000000..4345c59e4e14 --- /dev/null +++ b/src/tests/baseservices/threading/threadpool/bindhandle/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + + + false + + diff --git a/src/tests/build.proj b/src/tests/build.proj index 7f2a0b6b38af..0222d6b95a6b 100644 --- a/src/tests/build.proj +++ b/src/tests/build.proj @@ -567,6 +567,7 @@ + diff --git a/src/tests/ilverify/TestDataLoader.cs b/src/tests/ilverify/TestDataLoader.cs index dbf901bf2b2c..aba75551c9bb 100644 --- a/src/tests/ilverify/TestDataLoader.cs +++ b/src/tests/ilverify/TestDataLoader.cs @@ -279,10 +279,10 @@ public TestResolver(Dictionary simpleNameToPathMap) _simpleNameToPathMap = simpleNameToPathMap; } - PEReader IResolver.ResolveAssembly(AssemblyName assemblyName) + PEReader IResolver.ResolveAssembly(AssemblyNameInfo assemblyName) => Resolve(assemblyName.Name); - PEReader IResolver.ResolveModule(AssemblyName referencingModule, string fileName) + PEReader IResolver.ResolveModule(AssemblyNameInfo referencingModule, string fileName) => Resolve(Path.GetFileNameWithoutExtension(fileName)); public PEReader Resolve(string simpleName) diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 6b21cc19290a..d781f23977fb 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -345,21 +345,12 @@ https://github.com/dotnet/runtime/issues/10478 - - https://github.com/dotnet/runtime/issues/10478 - https://github.com/dotnet/runtime/issues/10478 - - https://github.com/dotnet/runtime/issues/10478 - https://github.com/dotnet/runtime/issues/10478 - - https://github.com/dotnet/runtime/issues/10478 - https://github.com/dotnet/runtime/issues/10478 @@ -682,6 +673,18 @@ + + https://github.com/dotnet/runtime/issues/102544 + + + needs triage + + + needs triage + + + https://github.com/dotnet/runtime/issues/91381 + https://github.com/dotnet/runtime/issues/89157 @@ -706,6 +709,9 @@ Test expects being run with corerun + + Test expects being run with corerun + Just-in-time compilation test @@ -1115,7 +1121,6 @@ - @@ -1148,6 +1153,31 @@ + + + + https://github.com/dotnet/runtime/issues/101284 + + + https://github.com/dotnet/runtime/issues/101363 + + + https://github.com/dotnet/runtime/issues/101363 + + + https://github.com/dotnet/runtime/issues/101363 + + + https://github.com/dotnet/runtime/issues/101363 + + + https://github.com/dotnet/runtime/issues/101363 + + + https://github.com/dotnet/runtime/issues/101364 + + + @@ -1514,21 +1544,6 @@ Relies on precise finalization and thus precise GC - - needs triage - - - needs triage - - - needs triage - - - needs triage - - - needs triage - https://github.com/dotnet/runtime/issues/34196 @@ -1867,9 +1882,6 @@ https://github.com/dotnet/runtime/issues/98628 - - https://github.com/dotnet/runtime/issues/93631: Swift frozen struct support is not implemented on Mono yet - https://github.com/dotnet/runtime/issues/93631: Swift frozen struct support is not implemented on Mono yet @@ -1919,12 +1931,6 @@ https://github.com/dotnet/runtime/issues/65702 - - https://github.com/dotnet/runtime/issues/65704 - - - https://github.com/dotnet/runtime/issues/65704 - Triggers OOM issue on CI, pass on local test run @@ -2418,9 +2424,6 @@ Needs coreclr build - - Needs coreclr build - Needs coreclr build @@ -2570,8 +2573,6 @@ - - @@ -2644,9 +2645,6 @@ https://github.com/dotnet/runtime/issues/82859 - - https://github.com/dotnet/runtime/issues/82859 - https://github.com/dotnet/runtime/issues/82859 @@ -2678,12 +2676,6 @@ Doesn't compile with LLVM AOT. - - needs triage - - - needs triage - needs triage @@ -2952,18 +2944,6 @@ Allocates large contiguous array that is not consistently available - - needs triage - - - needs triage - - - needs triage - - - needs triage - https://github.com/dotnet/runtime/issues/41472 @@ -2983,9 +2963,6 @@ needs triage - - needs triage - needs triage @@ -3395,9 +3372,6 @@ needs triage - - https://github.com/dotnet/runtime/issues/54906 - https://github.com/dotnet/runtime/issues/54906 @@ -3510,9 +3484,6 @@ System.IO.FileNotFoundException: Could not load file or assembly 'xunit.assert, Version=2.4.1.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c' or one of its dependencies. - - System.DllNotFoundException: GCPollNative - System.DllNotFoundException: CrossplatVirtualAlloc @@ -3728,12 +3699,6 @@ - - https://github.com/dotnet/runtime/issues/65704 - - - https://github.com/dotnet/runtime/issues/65704 - https://github.com/dotnet/runtime/issues/54393 @@ -3843,7 +3808,6 @@ - @@ -3874,7 +3838,6 @@ - diff --git a/src/tests/nativeaot/SmokeTests/DynamicGenerics/activation.cs b/src/tests/nativeaot/SmokeTests/DynamicGenerics/activation.cs index 2e358c53eb59..4e645560d6a0 100644 --- a/src/tests/nativeaot/SmokeTests/DynamicGenerics/activation.cs +++ b/src/tests/nativeaot/SmokeTests/DynamicGenerics/activation.cs @@ -131,6 +131,18 @@ public override string ToString() return memberVar; } } + struct StructToString + { + string memberVar; + public StructToString() + { + memberVar = typeof(T).Name; + } + public override string ToString() + { + return memberVar; + } + } class SomeUnrealtedType { string memberVar; @@ -195,5 +207,7 @@ public static void TestDefaultCtorInLazyGenerics() AllocViaGVMBase typeWithGVM = AllocViaGVMDerived.Alloc(); Assert.AreEqual("ToStringIsInteresting1", typeWithGVM.Alloc().ToString()); Assert.AreEqual("ToStringIsInteresting2", typeWithGVM.Alloc().ToString()); + Assert.AreEqual("ToStringIsInteresting1", typeWithGVM.Alloc>().ToString()); + Assert.AreEqual("ToStringIsInteresting2", typeWithGVM.Alloc>().ToString()); } } diff --git a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs index 7c0c0b2ffe19..41ee2b15f2fd 100644 --- a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs +++ b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Text; @@ -163,6 +164,8 @@ public static int Main() TestFirstChanceExceptionEvent(); + TestUnwindInFunclet(); + throw new Exception("UnhandledException"); } @@ -301,5 +304,27 @@ static bool FilterWithGC() CreateSomeGarbage(); return true; } + + static void TestUnwindInFunclet() + { + try + { + throw new Exception(); + } + catch (Exception e) + { + // x86 pushes the call arguments on the stack and moves the stack pointer. + // We use a non-inlined call with enough parameters to force this to happen, + // so we can verify that the unwinder can walk through this funclet. The + // unwinding is triggered by the GC.Collect call. + MultiparameterCallWithGC(0, 1, 2, 3, 4); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void MultiparameterCallWithGC(nint a, nint b, nint c, nint d, nint f) + { + GC.Collect(); + } } diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DeadCodeElimination.cs b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DeadCodeElimination.cs index 076ce813828c..eb03716ce3d1 100644 --- a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DeadCodeElimination.cs +++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DeadCodeElimination.cs @@ -21,6 +21,7 @@ public static int Run() TestArrayElementTypeOperations.Run(); TestStaticVirtualMethodOptimizations.Run(); TestTypeEquals.Run(); + TestTypeIsEnum.Run(); TestTypeIsValueType.Run(); TestBranchesInGenericCodeRemoval.Run(); TestUnmodifiableStaticFieldOptimization.Run(); @@ -362,6 +363,31 @@ public static void Run() } } + class TestTypeIsEnum + { + class Never { } + + class Ever { } + + static void Generic() + { + if (typeof(T).IsEnum) + { + Activator.CreateInstance(typeof(Never)); + } + + Activator.CreateInstance(typeof(Ever)); + } + + public static void Run() + { + Generic(); + + ThrowIfPresent(typeof(TestTypeIsEnum), nameof(Never)); + ThrowIfNotPresent(typeof(TestTypeIsEnum), nameof(Ever)); + } + } + class TestTypeIsValueType { class Never { } diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/ILLinkDescriptor.cs b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/ILLinkDescriptor.cs index 105ff1379df4..4e4404a5b89e 100644 --- a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/ILLinkDescriptor.cs +++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/ILLinkDescriptor.cs @@ -17,6 +17,7 @@ public static int Run() ThrowIfMemberNotPresent(typeof(ILLinkDescriptor), nameof(PropertyKeptViaDescriptor)); ThrowIfMemberNotPresent(typeof(ILLinkDescriptor), nameof(EventKeptViaDescriptor)); ThrowIfTypeNotPresent(typeof(ILLinkDescriptor), nameof(NestedTypeKeptViaDescriptor)); + ThrowIfTypeNotPresent("LibraryClass, ShimLibrary"); ThrowIfTypePresent(typeof(ILLinkDescriptor), nameof(NestedTypeNonKept)); return 100; } @@ -51,6 +52,10 @@ class NestedTypeNonKept Justification = "That's the point")] private static bool IsTypePresent(Type testType, string typeName) => testType.GetNestedType(typeName, BindingFlags.NonPublic | BindingFlags.Public) != null; + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2057:UnrecognizedReflectionPattern", + Justification = "That's the point")] + private static bool IsTypePresent(string typeName) => Type.GetType(typeName) != null; + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", Justification = "That's the point")] private static bool IsMemberPresent(Type testType, string memberName) { @@ -70,6 +75,14 @@ private static void ThrowIfTypeNotPresent(Type testType, string typeName) } } + private static void ThrowIfTypeNotPresent(string typeName) + { + if (!IsTypePresent(typeName)) + { + throw new Exception(typeName); + } + } + private static void ThrowIfTypePresent(Type testType, string typeName) { if (IsTypePresent(testType, typeName)) diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Library.cs b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Library.cs new file mode 100644 index 000000000000..d7a9483709bc --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Library.cs @@ -0,0 +1,4 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +public class LibraryClass { } diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Library.csproj b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Library.csproj new file mode 100644 index 000000000000..71634a598824 --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Library.csproj @@ -0,0 +1,8 @@ + + + Library + + + + + diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/NonEmbedded.ILLink.Descriptor.xml b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/NonEmbedded.ILLink.Descriptor.xml index ef70498ef497..c33d576e31c2 100644 --- a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/NonEmbedded.ILLink.Descriptor.xml +++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/NonEmbedded.ILLink.Descriptor.xml @@ -4,4 +4,8 @@ + + + + diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/ShimLibrary.cs b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/ShimLibrary.cs new file mode 100644 index 000000000000..dbac9ac09317 --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/ShimLibrary.cs @@ -0,0 +1,6 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; + +[assembly: TypeForwardedTo(typeof(LibraryClass))] diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/ShimLibrary.csproj b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/ShimLibrary.csproj new file mode 100644 index 000000000000..cc00bd360d38 --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/ShimLibrary.csproj @@ -0,0 +1,11 @@ + + + Library + + + + + + + + diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/TrimmingBehaviors.csproj b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/TrimmingBehaviors.csproj index fa0c9d0e4d7b..c69f6e042a57 100644 --- a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/TrimmingBehaviors.csproj +++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/TrimmingBehaviors.csproj @@ -8,6 +8,11 @@ true + + + + + diff --git a/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs b/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs index a9d3d44c758d..5df11edec245 100644 --- a/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs +++ b/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs @@ -55,6 +55,8 @@ internal static int Run() TestRecursionThroughGenericLookups.Run(); TestRecursionInFields.Run(); TestGvmLookupDependency.Run(); + Test99198Regression.Run(); + Test102259Regression.Run(); TestInvokeMemberCornerCaseInGenerics.Run(); TestRefAny.Run(); TestNullableCasting.Run(); @@ -3480,6 +3482,100 @@ public static void Run() } } + class Test99198Regression + { + delegate void Set(ref T t, IFoo ifoo); + + interface IFoo + { + void Do(); + } + + class Atom { } + + struct Foo : IFoo + { + public nint Cookie1; + public nint Cookie2; + + public void Do() + { + Cookie1 = 42; + } + } + + class C where T : IFoo + { + [MethodImpl(MethodImplOptions.NoInlining)] + public static void Set(ref T t, IFoo ifoo) + { + t.Do(); + ifoo.Do(); + } + } + + public static void RunDynamic() + { + static Type GetObject() => typeof(Foo); + var s = typeof(C<>).MakeGenericType(GetObject()).GetMethod("Set").CreateDelegate>>(); + + Foo ob = default; + IFoo boxed = ob; + + s(ref ob, boxed); + + if (ob.Cookie1 != 42 || ob.Cookie2 != 0) + throw new Exception(); + + ob = (Foo)boxed; + if (ob.Cookie1 != 42 || ob.Cookie2 != 0) + throw new Exception(); + } + + public static void Run() + { + new C>().ToString(); + + static Type GetObject() => typeof(Foo); + var s = typeof(C<>).MakeGenericType(GetObject()).GetMethod("Set").CreateDelegate>>(); + + Foo ob = default; + IFoo boxed = ob; + + s(ref ob, boxed); + + if (ob.Cookie1 != 42 || ob.Cookie2 != 0) + throw new Exception(); + + ob = (Foo)boxed; + if (ob.Cookie1 != 42 || ob.Cookie2 != 0) + throw new Exception(); + + static Type GetAtom() => typeof(Atom); + typeof(Test99198Regression).GetMethod(nameof(RunDynamic)).MakeGenericMethod(GetAtom()).Invoke(null, []); + } + } + + class Test102259Regression + { + class Gen + { + static Func _theval; + + public static object TheFunc(object obj) => obj; + + static Gen() + { + _theval = typeof(Gen).GetMethod(nameof(TheFunc), BindingFlags.Public | BindingFlags.Static).CreateDelegate>().WithObjectTResult(); + } + } + + public static void Run() + { + new Gen(); + } + } + class TestInvokeMemberCornerCaseInGenerics { class Generic @@ -3526,3 +3622,16 @@ public static void Run() } } } + +static class Ext +{ + public static Func WithObjectTResult(this Func function) + { + return function.InvokeWithObjectTResult; + } + + private static object InvokeWithObjectTResult(this Func func, T arg) + { + return func(arg); + } +} diff --git a/src/tests/profiler/common/ProfilerTestRunner.cs b/src/tests/profiler/common/ProfilerTestRunner.cs index d78a1221b422..e95817116c90 100644 --- a/src/tests/profiler/common/ProfilerTestRunner.cs +++ b/src/tests/profiler/common/ProfilerTestRunner.cs @@ -52,7 +52,7 @@ public static int Run(string profileePath, if (loadAsNotification) { StringBuilder builder = new StringBuilder(); - for(int i = 0; i < notificationCopies; ++i) + for (int i = 0; i < notificationCopies; ++i) { builder.Append(profilerPath); builder.Append("="); @@ -94,13 +94,11 @@ public static int Run(string profileePath, envVars.Add("Profiler_Test_Name", testName); - if(!File.Exists(profilerPath)) + if (!File.Exists(profilerPath)) { FailFastWithMessage("Profiler library not found at expected path: " + profilerPath); } - ProfileeOutputVerifier verifier = new ProfileeOutputVerifier(); - Process process = new Process(); process.StartInfo.FileName = program; process.StartInfo.Arguments = arguments; @@ -117,15 +115,10 @@ public static int Run(string profileePath, process.StartInfo.EnvironmentVariables[key] = envVars[key]; } - process.OutputDataReceived += (sender, args) => - { - Console.WriteLine(args.Data); - verifier.WriteLine(args.Data); - }; process.Start(); + ProfileeOutputVerifier verifier = new ProfileeOutputVerifier(process.StandardOutput); - process.BeginOutputReadLine(); - + verifier.VerifyOutput(); process.WaitForExit(); // There are two conditions for profiler tests to pass, the output of the profiled program @@ -135,9 +128,9 @@ public static int Run(string profileePath, if (!verifier.HasPassingOutput) { - FailFastWithMessage("Profiler tests are expected to contain the text \'" + verifier.SuccessPhrase + "\' in the console output " + - "of the profilee app to indicate a passing test. Usually it is printed from the Shutdown() method of the profiler implementation. This " + - "text was not found in the output above."); + FailFastWithMessage($"Profiler tests are expected to contain the text '{verifier.SuccessPhrase}' in the console output " + + $"of the profilee app to indicate a passing test. Usually it is printed from the Shutdown() method of the profiler implementation. This " + + $"text was not found in the output above. Profilee returned exit code {process.ExitCode}."); } if (process.ExitCode != 100) @@ -195,22 +188,29 @@ private static void FailFastWithMessage(string error) /// class ProfileeOutputVerifier { + private volatile bool _hasPassingOutput; + public string SuccessPhrase = "PROFILER TEST PASSES"; - public bool HasPassingOutput { get; private set; } + private StreamReader standardOutput; - public void WriteLine(string message) + public ProfileeOutputVerifier(StreamReader standardOutput) { - if (message != null && message.Contains(SuccessPhrase)) - { - HasPassingOutput = true; - } + this.standardOutput = standardOutput; } - public void WriteLine(string format, params object[] args) + public bool HasPassingOutput => _hasPassingOutput; + + internal void VerifyOutput() { - if (string.Format(format,args).Contains(SuccessPhrase)) + string line; + while ((line = standardOutput.ReadLine()) != null) { - HasPassingOutput = true; + if (line.Contains(SuccessPhrase)) + { + _hasPassingOutput = true; + } + + Console.WriteLine($"Profilee STDOUT: {line}"); } } } diff --git a/src/tests/profiler/multiple/multiple.cs b/src/tests/profiler/multiple/multiple.cs index 0d686ae0691a..7f2a5a549492 100644 --- a/src/tests/profiler/multiple/multiple.cs +++ b/src/tests/profiler/multiple/multiple.cs @@ -10,16 +10,17 @@ namespace Profiler.Tests { class MultiplyLoaded { - static readonly Guid MultipleProfilerGuid = new Guid("BFA8EF13-E144-49B9-B95C-FC1C150C7651"); - static readonly string ProfilerPath = ProfilerTestRunner.GetProfilerPath(); + private static readonly Guid MultipleProfilerGuid = new Guid("BFA8EF13-E144-49B9-B95C-FC1C150C7651"); + private static readonly string ProfilerPath = ProfilerTestRunner.GetProfilerPath(); [DllImport("Profiler")] private static extern void PassCallbackToProfiler(ProfilerCallback callback); public static int RunTest(String[] args) { - ManualResetEvent _profilerDone = new ManualResetEvent(false); - PassCallbackToProfiler(() => _profilerDone.Set()); + ManualResetEvent profilerDone = new ManualResetEvent(false); + ProfilerCallback profilerDoneDelegate = () => profilerDone.Set(); + PassCallbackToProfiler(profilerDoneDelegate); ProfilerControlHelpers.AttachProfilerToSelf(MultipleProfilerGuid, ProfilerPath); @@ -35,21 +36,17 @@ public static int RunTest(String[] args) } Console.WriteLine("Waiting for profilers to all detach"); - if (!_profilerDone.WaitOne(TimeSpan.FromMinutes(10))) + if (!profilerDone.WaitOne(TimeSpan.FromMinutes(5))) { throw new Exception("Test timed out waiting for the profilers to set the callback, test will fail."); } + GC.KeepAlive(profilerDoneDelegate); return 100; } public static int Main(string[] args) { - // failing on MacOs 12 https://github.com/dotnet/runtime/issues/64765 - if (OperatingSystem.IsMacOS()) - { - return 100; - } if (args.Length > 0 && args[0].Equals("RunTest", StringComparison.OrdinalIgnoreCase)) { return RunTest(args); diff --git a/src/tests/profiler/native/CMakeLists.txt b/src/tests/profiler/native/CMakeLists.txt index 8d915a9d7503..0e5765fc0c11 100644 --- a/src/tests/profiler/native/CMakeLists.txt +++ b/src/tests/profiler/native/CMakeLists.txt @@ -32,9 +32,10 @@ set(SOURCES include_directories(../../../coreclr/pal/prebuilt/inc) +add_compile_definitions(SOS_INCLUDE) + if(NOT WIN32) include_directories(../../../coreclr/pal/inc/rt ../../../coreclr/pal/inc ../../../coreclr/inc) - add_compile_options(-DPAL_STDCPP_COMPAT) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wno-null-arithmetic) else(CMAKE_CXX_COMPILER_ID MATCHES "Clang") diff --git a/src/tests/profiler/native/multiple/multiple.cpp b/src/tests/profiler/native/multiple/multiple.cpp index c36e4a8efa49..054cb3e1e426 100644 --- a/src/tests/profiler/native/multiple/multiple.cpp +++ b/src/tests/profiler/native/multiple/multiple.cpp @@ -57,11 +57,14 @@ HRESULT MultiplyLoaded::ProfilerDetachSucceeded() ++_detachCount; printf("ProfilerDetachSucceeded _detachCount=%d\n", _detachCount.load()); - if (_detachCount == MAX_PROFILERS - && _exceptionThrownSeenCount >= MAX_PROFILERS - && _failures == 0) + if (_detachCount == MAX_PROFILERS) { - printf("PROFILER TEST PASSES\n"); + if (_exceptionThrownSeenCount >= MAX_PROFILERS && _failures == 0) + { + printf("PROFILER TEST PASSES\n"); + fflush(stdout); + } + NotifyManagedCodeViaCallback(pCorProfilerInfo); } diff --git a/src/tests/profiler/native/rejitprofiler/ilrewriter.cpp b/src/tests/profiler/native/rejitprofiler/ilrewriter.cpp index 371bac8f125a..c145a49aa03a 100644 --- a/src/tests/profiler/native/rejitprofiler/ilrewriter.cpp +++ b/src/tests/profiler/native/rejitprofiler/ilrewriter.cpp @@ -4,6 +4,8 @@ #define _ASSERTE(e) ((void)0) #include +#include +#include #include #include "ilrewriter.h" #include "sigparse.h" diff --git a/src/tests/profiler/unittest/releaseondetach.cs b/src/tests/profiler/unittest/releaseondetach.cs index e50190b1872d..0e5ec490984c 100644 --- a/src/tests/profiler/unittest/releaseondetach.cs +++ b/src/tests/profiler/unittest/releaseondetach.cs @@ -15,7 +15,7 @@ class ReleaseOnShutdown [DllImport("Profiler")] private static extern void PassCallbackToProfiler(ProfilerCallback callback); - + public unsafe static int RunTest(string[] args) { string profilerName; @@ -35,16 +35,18 @@ public unsafe static int RunTest(string[] args) string rootPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); string profilerPath = Path.Combine(rootPath, profilerName); - ManualResetEvent _profilerDone = new ManualResetEvent(false); Console.WriteLine($"Attaching profiler {profilerPath} to self."); ProfilerControlHelpers.AttachProfilerToSelf(ReleaseOnShutdownGuid, profilerPath); - PassCallbackToProfiler(() => _profilerDone.Set()); - if (!_profilerDone.WaitOne(TimeSpan.FromMinutes(5))) + ManualResetEvent profilerDone = new ManualResetEvent(false); + ProfilerCallback profilerDoneDelegate = () => profilerDone.Set(); + PassCallbackToProfiler(profilerDoneDelegate); + if (!profilerDone.WaitOne(TimeSpan.FromMinutes(5))) { Console.WriteLine("Profiler did not set the callback, test will fail."); } + GC.KeepAlive(profilerDoneDelegate); return 100; } diff --git a/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcUnixDomainSocketEndPoint.cs b/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcUnixDomainSocketEndPoint.cs index f9413852a510..b939b4b22d15 100644 --- a/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcUnixDomainSocketEndPoint.cs +++ b/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcUnixDomainSocketEndPoint.cs @@ -23,7 +23,7 @@ public IpcUnixDomainSocketEndPoint(string endPoint) private static EndPoint CreateEndPoint(string endPoint) { -#if NETCOREAPP +#if NET return new UnixDomainSocketEndPoint(endPoint); #elif NETSTANDARD2_0 // UnixDomainSocketEndPoint is not part of .NET Standard 2.0 diff --git a/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsServerRouter/DiagnosticsServerRouterFactory.cs b/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsServerRouter/DiagnosticsServerRouterFactory.cs index 30ccdc1a48f4..41726e928679 100644 --- a/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsServerRouter/DiagnosticsServerRouterFactory.cs +++ b/src/tests/tracing/eventpipe/common/Microsoft.Diagnostics.NETCore.Client/DiagnosticsServerRouter/DiagnosticsServerRouterFactory.cs @@ -136,7 +136,7 @@ protected async Task IsStreamConnectedAsync(Stream stream, CancellationToken tok protected bool IsCompletedSuccessfully(Task t) { -#if NETCOREAPP2_0_OR_GREATER +#if NET return t.IsCompletedSuccessfully; #else return t.IsCompleted && !t.IsCanceled && !t.IsFaulted; diff --git a/src/tools/illink/external/Mono.Options/Options.cs b/src/tools/illink/external/Mono.Options/Options.cs index 07176081d7b3..d8b3d78a4550 100644 --- a/src/tools/illink/external/Mono.Options/Options.cs +++ b/src/tools/illink/external/Mono.Options/Options.cs @@ -749,7 +749,7 @@ public string OptionName { get {return this.option;} } -#if !PCL && !NETCOREAPP +#if !PCL && !NET #pragma warning disable 618 // SecurityPermissionAttribute is obsolete [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)] #pragma warning restore 618 diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/NullableAttributes.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/NullableAttributes.cs index 7ab77287ed5f..7cf10912ea38 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/NullableAttributes.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/NullableAttributes.cs @@ -5,7 +5,7 @@ // and updated to have the scope of the attributes be internal. namespace System.Diagnostics.CodeAnalysis { -#if !NETCOREAPP +#if !NET /// Specifies that null is allowed as an input even if the corresponding type disallows it. [AttributeUsage (AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] @@ -86,7 +86,7 @@ internal sealed class DoesNotReturnIfAttribute : Attribute #endif -#if !NETCOREAPP || NETCOREAPP3_1 +#if !NET /// Specifies that the method or property will ensure that the listed field and property members have not-null values. [AttributeUsage (AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs index c31a69a24d24..28118233b656 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; +using MultiValue = ILLink.Shared.DataFlow.ValueSet; namespace ILLink.RoslynAnalyzer { @@ -342,5 +343,14 @@ internal bool CheckAndCreateRequiresDiagnostic ( incompatibleMembers, out diagnostic); } + + internal virtual bool IsIntrinsicallyHandled ( + IMethodSymbol calledMethod, + MultiValue instance, + ImmutableArray arguments + ) + { + return false; + } } } diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresDynamicCodeAnalyzer.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresDynamicCodeAnalyzer.cs index 34bb7808d203..4e5c5d26a253 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresDynamicCodeAnalyzer.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresDynamicCodeAnalyzer.cs @@ -5,8 +5,11 @@ using System.Collections.Immutable; using System.Linq; using ILLink.Shared; +using ILLink.Shared.TrimAnalysis; +using ILLink.Shared.TypeSystemProxy; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; +using MultiValue = ILLink.Shared.DataFlow.ValueSet; namespace ILLink.RoslynAnalyzer { @@ -38,6 +41,77 @@ public sealed class RequiresDynamicCodeAnalyzer : RequiresAnalyzerBase internal override bool IsAnalyzerEnabled (AnalyzerOptions options) => options.IsMSBuildPropertyValueTrue (MSBuildPropertyOptionNames.EnableAotAnalyzer); + internal override bool IsIntrinsicallyHandled (IMethodSymbol calledMethod, MultiValue instance, ImmutableArray arguments) { + MethodProxy method = new (calledMethod); + var intrinsicId = Intrinsics.GetIntrinsicIdForMethod (method); + + switch (intrinsicId) { + case IntrinsicId.Type_MakeGenericType: { + if (!instance.IsEmpty ()) { + foreach (var value in instance.AsEnumerable ()) { + if (value is SystemTypeValue) { + if (!IsKnownInstantiation (arguments[0])) { + return false; + } + } else { + return false; + } + } + } + return true; + } + case IntrinsicId.MethodInfo_MakeGenericMethod: { + if (!instance.IsEmpty ()) { + foreach (var methodValue in instance.AsEnumerable ()) { + if (methodValue is SystemReflectionMethodBaseValue methodBaseValue) { + if (!IsKnownInstantiation (arguments[0])) { + return false; + } + } else { + return false; + } + } + } + return true; + } + } + + return false; + + static bool IsKnownInstantiation(MultiValue genericParametersArray) { + var typesValue = genericParametersArray.AsSingleValue (); + if (typesValue is NullValue) { + // This will fail at runtime but no warning needed + return true; + } + + // Is this an array we model? + if (typesValue is not ArrayValue array) { + return false; + } + + int? size = array.Size.AsConstInt (); + if (size == null) { + return false; + } + + for (int i = 0; i < size.Value; i++) { + // Go over each element of the array. If the value is unknown, bail. + if (!array.TryGetValueByIndex (i, out MultiValue value)) { + return false; + } + + var singleValue = value.AsSingleValue (); + + if (singleValue is not SystemTypeValue and not GenericParameterValue and not NullableSystemTypeValue) { + return false; + } + } + + return true; + } + } + private protected override bool IsRequiresCheck (IPropertySymbol propertySymbol, Compilation compilation) { var runtimeFeaturesType = compilation.GetTypeByMetadataName ("System.Runtime.CompilerServices.RuntimeFeature"); if (runtimeFeaturesType == null) diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/FlowAnnotations.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/FlowAnnotations.cs index db0eb0af579e..2fa967fdc940 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/FlowAnnotations.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/FlowAnnotations.cs @@ -103,11 +103,11 @@ public static DynamicallyAccessedMemberTypes GetTypeAnnotation(ITypeSymbol type) internal partial bool MethodRequiresDataFlowAnalysis (MethodProxy method) => RequiresDataFlowAnalysis (method.Method); - internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) - => new MethodReturnValue (method.Method, dynamicallyAccessedMemberTypes); + internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, bool isNewObj, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + => new MethodReturnValue (method.Method, isNewObj, dynamicallyAccessedMemberTypes); - internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method) - => GetMethodReturnValue (method, GetMethodReturnValueAnnotation (method.Method)); + internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, bool isNewObj) + => GetMethodReturnValue (method, isNewObj, GetMethodReturnValueAnnotation (method.Method)); internal partial GenericParameterValue GetGenericParameterValue (GenericParameterProxy genericParameter) => new GenericParameterValue (genericParameter.TypeParameterSymbol); diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/GenericParameterProxy.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/GenericParameterProxy.cs index 6418e85b1857..b51c2c6ecce0 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/GenericParameterProxy.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/GenericParameterProxy.cs @@ -14,6 +14,16 @@ internal partial bool HasDefaultConstructorConstraint () => TypeParameterSymbol.HasValueTypeConstraint | TypeParameterSymbol.HasUnmanagedTypeConstraint; + internal partial bool HasEnumConstraint () + { + foreach (ITypeSymbol constraintType in TypeParameterSymbol.ConstraintTypes) { + if (constraintType.SpecialType == SpecialType.System_Enum) + return true; + } + + return false; + } + public readonly ITypeParameterSymbol TypeParameterSymbol; public override string ToString () => TypeParameterSymbol.ToString (); diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs index 96c4a07a92a7..d41ccee2388a 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/HandleCallAction.cs @@ -7,8 +7,11 @@ using ILLink.RoslynAnalyzer; using ILLink.RoslynAnalyzer.DataFlow; using ILLink.RoslynAnalyzer.TrimAnalysis; +using ILLink.Shared.DataFlow; using ILLink.Shared.TypeSystemProxy; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Operations; +using MultiValue = ILLink.Shared.DataFlow.ValueSet; namespace ILLink.Shared.TrimAnalysis { @@ -20,15 +23,125 @@ internal partial struct HandleCallAction readonly ISymbol _owningSymbol; readonly IOperation _operation; readonly ReflectionAccessAnalyzer _reflectionAccessAnalyzer; + ValueSetLattice _multiValueLattice; - public HandleCallAction (in DiagnosticContext diagnosticContext, ISymbol owningSymbol, IOperation operation) + public HandleCallAction ( + in DiagnosticContext diagnosticContext, + ISymbol owningSymbol, + IOperation operation, + ValueSetLattice multiValueLattice) { _owningSymbol = owningSymbol; _operation = operation; + _isNewObj = operation.Kind == OperationKind.ObjectCreation; _diagnosticContext = diagnosticContext; _annotations = FlowAnnotations.Instance; _reflectionAccessAnalyzer = default; _requireDynamicallyAccessedMembersAction = new (diagnosticContext, _reflectionAccessAnalyzer); + _multiValueLattice = multiValueLattice; + } + + private partial bool TryHandleIntrinsic ( + MethodProxy calledMethod, + MultiValue instanceValue, + IReadOnlyList argumentValues, + IntrinsicId intrinsicId, + out MultiValue? methodReturnValue) + { + MultiValue? maybeMethodReturnValue = methodReturnValue = null; + ValueSetLattice multiValueLattice = _multiValueLattice; + + switch (intrinsicId) { + case IntrinsicId.Array_Empty: + AddReturnValue (ArrayValue.Create (0)); + break; + + case IntrinsicId.TypeDelegator_Ctor: + if (_operation is IObjectCreationOperation) + AddReturnValue (argumentValues[0]); + + break; + + case IntrinsicId.Object_GetType: { + foreach (var valueNode in instanceValue.AsEnumerable ()) { + // Note that valueNode can be statically typed as some generic argument type. + // For example: + // void Method(T instance) { instance.GetType().... } + // But it could be that T is annotated with for example PublicMethods: + // void Method<[DAM(PublicMethods)] T>(T instance) { instance.GetType().GetMethod("Test"); } + // In this case it's in theory possible to handle it, by treating the T basically as a base class + // for the actual type of "instance". But the analysis for this would be pretty complicated (as the marking + // has to happen on the callsite, which doesn't know that GetType() will be used...). + // For now we're intentionally ignoring this case - it will produce a warning. + // The counter example is: + // Method(new Derived); + // In this case to get correct results, trimmer would have to mark all public methods on Derived. Which + // currently it won't do. + + // To emulate IL tools behavior (trimmer, NativeAOT compiler), we're going to intentionally "forget" the static type + // if it is a generic argument type. + + ITypeSymbol? staticType = (valueNode as IValueWithStaticType)?.StaticType?.Type; + if (staticType?.TypeKind == TypeKind.TypeParameter) + staticType = null; + + if (staticType is null) { + // We don't know anything about the type GetType was called on. Track this as a usual "result of a method call without any annotations" + AddReturnValue (FlowAnnotations.Instance.GetMethodReturnValue (calledMethod, _isNewObj)); + } else if (staticType.IsSealed || staticType.IsTypeOf ("System", "Delegate") || staticType.TypeKind == TypeKind.Array) { + // We can treat this one the same as if it was a typeof() expression + + // We can allow Object.GetType to be modeled as System.Delegate because we keep all methods + // on delegates anyway so reflection on something this approximation would miss is actually safe. + + // We can also treat all arrays as "sealed" since it's not legal to derive from Array type (even though it is not sealed itself) + + // We ignore the fact that the type can be annotated (see below for handling of annotated types) + // This means the annotations (if any) won't be applied - instead we rely on the exact knowledge + // of the type. So for example even if the type is annotated with PublicMethods + // but the code calls GetProperties on it - it will work - mark properties, don't mark methods + // since we ignored the fact that it's annotated. + // This can be seen a little bit as a violation of the annotation, but we already have similar cases + // where a parameter is annotated and if something in the method sets a specific known type to it + // we will also make it just work, even if the annotation doesn't match the usage. + AddReturnValue (new SystemTypeValue (new (staticType))); + } else { + var annotation = FlowAnnotations.GetTypeAnnotation (staticType); + AddReturnValue (FlowAnnotations.Instance.GetMethodReturnValue (calledMethod, _isNewObj, annotation)); + } + } + break; + } + + // Some intrinsics are unimplemented by the analyzer. + // These will fall back to the usual return-value handling. + case IntrinsicId.Array_CreateInstance: + case IntrinsicId.Assembly_GetFile: + case IntrinsicId.Assembly_GetFiles: + case IntrinsicId.AssemblyName_get_EscapedCodeBase: + case IntrinsicId.Assembly_get_Location: + case IntrinsicId.AssemblyName_get_CodeBase: + case IntrinsicId.Delegate_get_Method: + case IntrinsicId.Enum_GetValues: + case IntrinsicId.Marshal_DestroyStructure: + case IntrinsicId.Marshal_GetDelegateForFunctionPointer: + case IntrinsicId.Marshal_OffsetOf: + case IntrinsicId.Marshal_PtrToStructure: + case IntrinsicId.Marshal_SizeOf: + case IntrinsicId.RuntimeReflectionExtensions_GetMethodInfo: + break; + + default: + return false; + } + + methodReturnValue = maybeMethodReturnValue; + return true; + + void AddReturnValue (MultiValue value) + { + maybeMethodReturnValue = (maybeMethodReturnValue is null) ? value : multiValueLattice.Meet ((MultiValue) maybeMethodReturnValue, value); + } } private partial IEnumerable GetMethodsOnTypeHierarchy (TypeProxy type, string name, BindingFlags? bindingFlags) diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodProxy.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodProxy.cs index 5001e5836eac..0b274879440f 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodProxy.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodProxy.cs @@ -46,6 +46,8 @@ internal partial ImmutableArray GetGenericParameters () return builder.ToImmutableArray (); } + internal partial bool IsConstructor () => Method.IsConstructor (); + internal partial bool IsStatic () => Method.IsStatic; internal partial bool HasImplicitThis () => Method.HasImplicitThis (); diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodReturnValue.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodReturnValue.cs index 6a84896e577a..d11181ad96d2 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodReturnValue.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodReturnValue.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using ILLink.RoslynAnalyzer; using ILLink.Shared.DataFlow; @@ -11,16 +12,17 @@ namespace ILLink.Shared.TrimAnalysis { internal partial record MethodReturnValue { - public MethodReturnValue (IMethodSymbol methodSymbol) - : this (methodSymbol, FlowAnnotations.GetMethodReturnValueAnnotation (methodSymbol)) + public MethodReturnValue (IMethodSymbol methodSymbol, bool isNewObj) + : this (methodSymbol, isNewObj, FlowAnnotations.GetMethodReturnValueAnnotation (methodSymbol)) { } - public MethodReturnValue (IMethodSymbol methodSymbol, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + public MethodReturnValue (IMethodSymbol methodSymbol, bool isNewObj, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) { + Debug.Assert (!isNewObj || methodSymbol.MethodKind == MethodKind.Constructor, "isNewObj can only be true for constructors"); MethodSymbol = methodSymbol; DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; - StaticType = new (methodSymbol.ReturnType); + StaticType = new (isNewObj ? methodSymbol.ContainingType : methodSymbol.ReturnType); } public readonly IMethodSymbol MethodSymbol; diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisMethodCallPattern.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisMethodCallPattern.cs index 3dfd7fa28552..845ac7e884a9 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisMethodCallPattern.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisMethodCallPattern.cs @@ -84,8 +84,11 @@ public IEnumerable CollectDiagnostics (DataFlowAnalyzerContext conte foreach (var requiresAnalyzer in context.EnabledRequiresAnalyzers) { - if (requiresAnalyzer.CheckAndCreateRequiresDiagnostic(Operation, CalledMethod, OwningSymbol, context, FeatureContext, out Diagnostic? diag)) - diagnosticContext.AddDiagnostic(diag); + if (requiresAnalyzer.CheckAndCreateRequiresDiagnostic (Operation, CalledMethod, OwningSymbol, context, FeatureContext, out Diagnostic? diag) + && !requiresAnalyzer.IsIntrinsicallyHandled (CalledMethod, Instance, Arguments)) + { + diagnosticContext.AddDiagnostic (diag); + } } return diagnosticContext.Diagnostics; diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs index 9db61498b28c..2d9cb6cd8416 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/TrimAnalysisVisitor.cs @@ -75,16 +75,22 @@ public override void ApplyCondition (FeatureChecksValue featureChecksValue, ref // - 'this' parameter (for annotated methods) // - field reference - public override MultiValue Visit (IOperation? operation, StateValue argument) + public override MultiValue DefaultVisit (IOperation operation, StateValue argument) { - var returnValue = base.Visit (operation, argument); + var returnValue = base.DefaultVisit (operation, argument); // If the return value is empty (TopValue basically) and the Operation tree // reports it as having a constant value, use that as it will automatically cover // cases we don't need/want to handle. - if (operation != null && returnValue.IsEmpty () && TryGetConstantValue (operation, out var constValue)) + if (!returnValue.IsEmpty ()) + return returnValue; + + if (TryGetConstantValue (operation, out var constValue)) return constValue; + if (operation.Type is not null) + return UnknownValue.Instance; + return returnValue; } @@ -116,7 +122,7 @@ public override MultiValue VisitConversion (IConversionOperation operation, Stat var value = base.VisitConversion (operation, state); if (operation.OperatorMethod != null) - return operation.OperatorMethod.ReturnType.IsTypeInterestingForDataflow () ? new MethodReturnValue (operation.OperatorMethod) : value; + return operation.OperatorMethod.ReturnType.IsTypeInterestingForDataflow () ? new MethodReturnValue (operation.OperatorMethod, isNewObj: false) : value; // TODO - is it possible to have annotation on the operator method parameters? // if so, will these be checked here? @@ -321,92 +327,16 @@ internal static void HandleCall( ValueSetLattice multiValueLattice, out MultiValue methodReturnValue) { - var handleCallAction = new HandleCallAction (diagnosticContext, owningSymbol, operation); + var handleCallAction = new HandleCallAction (diagnosticContext, owningSymbol, operation, multiValueLattice); MethodProxy method = new (calledMethod); var intrinsicId = Intrinsics.GetIntrinsicIdForMethod (method); + if (!handleCallAction.Invoke (method, instance, arguments, intrinsicId, out methodReturnValue)) + UnhandledIntrinsicHelper (intrinsicId); - if (handleCallAction.Invoke (method, instance, arguments, intrinsicId, out methodReturnValue)) { - return; - } - - MultiValue? maybeMethodReturnValue = default; - - switch (intrinsicId) { - case IntrinsicId.Array_Empty: - AddReturnValue (ArrayValue.Create (0)); - break; - - case IntrinsicId.TypeDelegator_Ctor: - if (operation is IObjectCreationOperation) - AddReturnValue (arguments[0]); - - break; - - case IntrinsicId.Object_GetType: { - foreach (var valueNode in instance.AsEnumerable ()) { - // Note that valueNode can be statically typed as some generic argument type. - // For example: - // void Method(T instance) { instance.GetType().... } - // But it could be that T is annotated with for example PublicMethods: - // void Method<[DAM(PublicMethods)] T>(T instance) { instance.GetType().GetMethod("Test"); } - // In this case it's in theory possible to handle it, by treating the T basically as a base class - // for the actual type of "instance". But the analysis for this would be pretty complicated (as the marking - // has to happen on the callsite, which doesn't know that GetType() will be used...). - // For now we're intentionally ignoring this case - it will produce a warning. - // The counter example is: - // Method(new Derived); - // In this case to get correct results, trimmer would have to mark all public methods on Derived. Which - // currently it won't do. - - // To emulate IL tools behavior (trimmer, NativeAOT compiler), we're going to intentionally "forget" the static type - // if it is a generic argument type. - - ITypeSymbol? staticType = (valueNode as IValueWithStaticType)?.StaticType?.Type; - if (staticType?.TypeKind == TypeKind.TypeParameter) - staticType = null; - - if (staticType is null) { - // We don't know anything about the type GetType was called on. Track this as a usual "result of a method call without any annotations" - AddReturnValue (FlowAnnotations.Instance.GetMethodReturnValue (new (calledMethod))); - } else if (staticType.IsSealed || staticType.IsTypeOf ("System", "Delegate") || staticType.TypeKind == TypeKind.Array) { - // We can treat this one the same as if it was a typeof() expression - - // We can allow Object.GetType to be modeled as System.Delegate because we keep all methods - // on delegates anyway so reflection on something this approximation would miss is actually safe. - - // We can also treat all arrays as "sealed" since it's not legal to derive from Array type (even though it is not sealed itself) - - // We ignore the fact that the type can be annotated (see below for handling of annotated types) - // This means the annotations (if any) won't be applied - instead we rely on the exact knowledge - // of the type. So for example even if the type is annotated with PublicMethods - // but the code calls GetProperties on it - it will work - mark properties, don't mark methods - // since we ignored the fact that it's annotated. - // This can be seen a little bit as a violation of the annotation, but we already have similar cases - // where a parameter is annotated and if something in the method sets a specific known type to it - // we will also make it just work, even if the annotation doesn't match the usage. - AddReturnValue (new SystemTypeValue (new (staticType))); - } else { - var annotation = FlowAnnotations.GetTypeAnnotation (staticType); - AddReturnValue (FlowAnnotations.Instance.GetMethodReturnValue (new (calledMethod), annotation)); - } - } - } - - break; - - default: - Debug.Fail ($"Unexpected method {calledMethod.GetDisplayName ()} unhandled by HandleCallAction."); - - // Do nothing even if we reach a point which we didn't expect - the analyzer should never crash as it's a too disruptive experience for the user. - break; - } - - methodReturnValue = maybeMethodReturnValue ?? multiValueLattice.Top; - - void AddReturnValue (MultiValue value) - { - maybeMethodReturnValue = (maybeMethodReturnValue is null) ? value : multiValueLattice.Meet ((MultiValue) maybeMethodReturnValue, value); - } + // Avoid crashing the analyzer in release builds + [Conditional ("DEBUG")] + static void UnhandledIntrinsicHelper (IntrinsicId intrinsicId) + => throw new NotImplementedException ($"Unhandled intrinsic: {intrinsicId}"); } public override void HandleReturnValue (MultiValue returnValue, IOperation operation, in FeatureContext featureContext) @@ -417,7 +347,7 @@ public override void HandleReturnValue (MultiValue returnValue, IOperation opera return; if (method.ReturnType.IsTypeInterestingForDataflow ()) { - var returnParameter = new MethodReturnValue (method); + var returnParameter = new MethodReturnValue (method, isNewObj: false); TrimAnalysisPatterns.Add ( new TrimAnalysisAssignmentPattern (returnValue, returnParameter, operation, OwningSymbol, featureContext), diff --git a/src/tools/illink/src/ILLink.Shared/TrimAnalysis/FlowAnnotations.cs b/src/tools/illink/src/ILLink.Shared/TrimAnalysis/FlowAnnotations.cs index 7ca5df5a6b8f..4ef9a9ce61a4 100644 --- a/src/tools/illink/src/ILLink.Shared/TrimAnalysis/FlowAnnotations.cs +++ b/src/tools/illink/src/ILLink.Shared/TrimAnalysis/FlowAnnotations.cs @@ -19,9 +19,9 @@ partial class FlowAnnotations { internal partial bool MethodRequiresDataFlowAnalysis (MethodProxy method); - internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes); + internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, bool isNewObj, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes); - internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method); + internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, bool isNewObj); internal partial GenericParameterValue GetGenericParameterValue (GenericParameterProxy genericParameter); diff --git a/src/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs b/src/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs index 9063ac7368db..ff2a393928de 100644 --- a/src/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs +++ b/src/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs @@ -26,13 +26,63 @@ internal partial struct HandleCallAction private readonly DiagnosticContext _diagnosticContext; private readonly FlowAnnotations _annotations; private readonly RequireDynamicallyAccessedMembersAction _requireDynamicallyAccessedMembersAction; + private readonly bool _isNewObj; public bool Invoke (MethodProxy calledMethod, MultiValue instanceValue, IReadOnlyList argumentValues, IntrinsicId intrinsicId, out MultiValue methodReturnValue) { - MultiValue? returnValue = null; + MultiValue? maybeMethodReturnValue; + + var handledIntrinsic = + TryHandleIntrinsic (calledMethod, instanceValue, argumentValues, intrinsicId, out maybeMethodReturnValue) || + TryHandleSharedIntrinsic (calledMethod, instanceValue, argumentValues, intrinsicId, out maybeMethodReturnValue); + + // As a convenience, if the code above didn't set the return value (and the method has a return value), + // we will set it to be an unknown value with the return type of the method. + var annotatedMethodReturnValue = _annotations.GetMethodReturnValue (calledMethod, _isNewObj); + bool returnsVoid = calledMethod.ReturnsVoid (); + methodReturnValue = maybeMethodReturnValue ?? + ((returnsVoid && !_isNewObj) + ? MultiValueLattice.Top + : annotatedMethodReturnValue); + + // Validate that the return value has the correct annotations as per the method return value annotations + if (annotatedMethodReturnValue.DynamicallyAccessedMemberTypes != 0) { + foreach (var uniqueValue in methodReturnValue.AsEnumerable ()) { + if (uniqueValue is ValueWithDynamicallyAccessedMembers methodReturnValueWithMemberTypes) { + if (!methodReturnValueWithMemberTypes.DynamicallyAccessedMemberTypes.HasFlag (annotatedMethodReturnValue.DynamicallyAccessedMemberTypes)) + throw new InvalidOperationException ($"Internal trimming error: processing of call from {GetContainingSymbolDisplayName ()} to {calledMethod.GetDisplayName ()} returned value which is not correctly annotated with the expected dynamic member access kinds."); + } else if (uniqueValue is SystemTypeValue) { + // SystemTypeValue can fulfill any requirement, so it's always valid + // The requirements will be applied at the point where it's consumed (passed as a method parameter, set as field value, returned from the method) + } else if (uniqueValue == NullValue.Instance) { + // NullValue can fulfill any requirements because reflection access to it will typically throw. + } else { + throw new InvalidOperationException ($"Internal trimming error: processing of call from {GetContainingSymbolDisplayName ()} to {calledMethod.GetDisplayName ()} returned value which is not correctly annotated with the expected dynamic member access kinds."); + } + } + } + + return handledIntrinsic; + } + + private partial bool TryHandleIntrinsic ( + MethodProxy calledMethod, + MultiValue instanceValue, + IReadOnlyList argumentValues, + IntrinsicId intrinsicId, + out MultiValue? methodReturnValue); + + bool TryHandleSharedIntrinsic ( + MethodProxy calledMethod, + MultiValue instanceValue, + IReadOnlyList argumentValues, + IntrinsicId intrinsicId, + out MultiValue? methodReturnValue) + { + MultiValue? returnValue = methodReturnValue = null; bool requiresDataFlowAnalysis = _annotations.MethodRequiresDataFlowAnalysis (calledMethod); - var annotatedMethodReturnValue = _annotations.GetMethodReturnValue (calledMethod); + var annotatedMethodReturnValue = _annotations.GetMethodReturnValue (calledMethod, _isNewObj); Debug.Assert (requiresDataFlowAnalysis || annotatedMethodReturnValue.DynamicallyAccessedMemberTypes == DynamicallyAccessedMemberTypes.None); switch (intrinsicId) { @@ -154,8 +204,7 @@ GenericParameterValue genericParam // Array.Empty must for now be handled by the specific implementation since it requires instantiated generic method handling case IntrinsicId.Object_GetType: // Object.GetType requires additional handling by the caller to implement type hierarchy marking and related diagnostics - methodReturnValue = MultiValueLattice.Top; - return false; + throw new NotImplementedException ("These intrinsics should be handled by the specific implementation: " + intrinsicId); // // GetInterface (String) @@ -190,7 +239,7 @@ GenericParameterValue genericParam && valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes == DynamicallyAccessedMemberTypes.All) returnMemberTypes = DynamicallyAccessedMemberTypes.All; - AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, returnMemberTypes)); + AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, _isNewObj, returnMemberTypes)); } } } @@ -497,7 +546,7 @@ GenericParameterValue genericParam // We only applied the annotation based on binding flags, so we will keep the necessary types // but we will not keep anything on them. So the return value has no known annotations on it - AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, DynamicallyAccessedMemberTypes.None)); + AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, _isNewObj, DynamicallyAccessedMemberTypes.None)); } } } else if (value is NullValue) { @@ -511,9 +560,9 @@ GenericParameterValue genericParam // since All applies recursively to all nested type (see MarkStep.MarkEntireType). // Otherwise we only mark the nested type itself, nothing on it, so the return value has no annotation on it. if (value is ValueWithDynamicallyAccessedMembers { DynamicallyAccessedMemberTypes: DynamicallyAccessedMemberTypes.All }) - AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, DynamicallyAccessedMemberTypes.All)); + AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, _isNewObj, DynamicallyAccessedMemberTypes.All)); else - AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, DynamicallyAccessedMemberTypes.None)); + AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, _isNewObj, DynamicallyAccessedMemberTypes.None)); } } } @@ -785,7 +834,7 @@ GenericParameterValue genericParam } else if (typeNameValue is ValueWithDynamicallyAccessedMembers valueWithDynamicallyAccessedMembers && valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes != 0) { // Propagate the annotation from the type name to the return value. Annotation on a string value will be fulfilled whenever a value is assigned to the string with annotation. // So while we don't know which type it is, we can guarantee that it will fulfill the annotation. - AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes)); + AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, _isNewObj, valueWithDynamicallyAccessedMembers.DynamicallyAccessedMemberTypes)); } else { _diagnosticContext.AddDiagnostic (DiagnosticId.UnrecognizedTypeNameInTypeGetType, calledMethod.GetDisplayName ()); AddReturnValue (MultiValueLattice.Top); @@ -909,7 +958,7 @@ GenericParameterValue genericParam propagatedMemberTypes |= DynamicallyAccessedMemberTypes.Interfaces; } - AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, propagatedMemberTypes)); + AddReturnValue (_annotations.GetMethodReturnValue (calledMethod, _isNewObj, propagatedMemberTypes)); } else if (value is SystemTypeValue systemTypeValue) { if (TryGetBaseType (systemTypeValue.RepresentedType, out var baseType)) AddReturnValue (new SystemTypeValue (baseType.Value)); @@ -1153,44 +1202,14 @@ GenericParameterValue genericParam } break; - // Disable warnings for all unimplemented intrinsics. Some intrinsic methods have annotations, but analyzing them - // would produce unnecessary warnings even for cases that are intrinsically handled. So we disable handling these calls - // until a proper intrinsic handling is made - // NOTE: Currently this is done "for the analyzer" and it relies on illink/NativeAOT to not call HandleCallAction - // for intrinsics which illink/NativeAOT need special handling for or those which are not implemented here and only there. - // Ideally we would run everything through HandleCallAction and it would return "false" for intrinsics it doesn't handle - // like it already does for Activator.CreateInstance for example. default: - methodReturnValue = MultiValueLattice.Top; - return true; + return false; } - // For now, if the intrinsic doesn't set a return value, fall back on the annotations. - // Note that this will be DynamicallyAccessedMembers.None for the intrinsics which don't return types. - returnValue ??= calledMethod.ReturnsVoid () ? MultiValueLattice.Top : annotatedMethodReturnValue; - if (MethodIsTypeConstructor (calledMethod)) returnValue = UnknownValue.Instance; - // Validate that the return value has the correct annotations as per the method return value annotations - if (annotatedMethodReturnValue.DynamicallyAccessedMemberTypes != DynamicallyAccessedMemberTypes.None) { - foreach (var uniqueValue in returnValue.Value.AsEnumerable ()) { - if (uniqueValue is ValueWithDynamicallyAccessedMembers methodReturnValueWithMemberTypes) { - if (!methodReturnValueWithMemberTypes.DynamicallyAccessedMemberTypes.HasFlag (annotatedMethodReturnValue.DynamicallyAccessedMemberTypes)) - throw new InvalidOperationException ($"Internal ILLink error: in {GetContainingSymbolDisplayName ()} processing call to {calledMethod.GetDisplayName ()} returned value which is not correctly annotated with the expected dynamic member access kinds."); - } else if (uniqueValue is SystemTypeValue) { - // SystemTypeValue can fulfill any requirement, so it's always valid - // The requirements will be applied at the point where it's consumed (passed as a method parameter, set as field value, returned from the method) - } else if (uniqueValue == NullValue.Instance) { - // NullValue can fulfill any requirements because reflection access to it will typically throw. - } else { - throw new InvalidOperationException ($"Internal ILLink error: in {GetContainingSymbolDisplayName ()} processing call to {calledMethod.GetDisplayName ()} returned value which is not correctly annotated with the expected dynamic member access kinds."); - } - } - } - - methodReturnValue = returnValue.Value; - + methodReturnValue = returnValue; return true; void AddReturnValue (MultiValue value) diff --git a/src/tools/illink/src/ILLink.Shared/TrimAnalysis/RequireDynamicallyAccessedMembersAction.cs b/src/tools/illink/src/ILLink.Shared/TrimAnalysis/RequireDynamicallyAccessedMembersAction.cs index 50166c803be3..dd8e5891c37b 100644 --- a/src/tools/illink/src/ILLink.Shared/TrimAnalysis/RequireDynamicallyAccessedMembersAction.cs +++ b/src/tools/illink/src/ILLink.Shared/TrimAnalysis/RequireDynamicallyAccessedMembersAction.cs @@ -28,6 +28,10 @@ public void Invoke (in MultiValue value, ValueWithDynamicallyAccessedMembers tar && uniqueValue is GenericParameterValue genericParam && genericParam.GenericParameter.HasDefaultConstructorConstraint ()) { // We allow a new() constraint on a generic parameter to satisfy DynamicallyAccessedMemberTypes.PublicParameterlessConstructor + } else if (targetValue.DynamicallyAccessedMemberTypes == DynamicallyAccessedMemberTypes.PublicFields + && uniqueValue is GenericParameterValue maybeEnumConstrainedGenericParam + && maybeEnumConstrainedGenericParam.GenericParameter.HasEnumConstraint ()) { + // We allow a System.Enum constraint on a generic parameter to satisfy DynamicallyAccessedMemberTypes.PublicFields } else if (uniqueValue is ValueWithDynamicallyAccessedMembers valueWithDynamicallyAccessedMembers) { if (uniqueValue is NullableValueWithDynamicallyAccessedMembers nullableValue) { MarkTypeForDynamicallyAccessedMembers (nullableValue.NullableType, nullableValue.DynamicallyAccessedMemberTypes); diff --git a/src/tools/illink/src/ILLink.Shared/TypeSystemProxy/GenericParameterProxy.cs b/src/tools/illink/src/ILLink.Shared/TypeSystemProxy/GenericParameterProxy.cs index 09ddbc4ae052..1e9e21c24f0f 100644 --- a/src/tools/illink/src/ILLink.Shared/TypeSystemProxy/GenericParameterProxy.cs +++ b/src/tools/illink/src/ILLink.Shared/TypeSystemProxy/GenericParameterProxy.cs @@ -9,5 +9,7 @@ namespace ILLink.Shared.TypeSystemProxy internal readonly partial struct GenericParameterProxy { internal partial bool HasDefaultConstructorConstraint (); + + internal partial bool HasEnumConstraint (); } } diff --git a/src/tools/illink/src/ILLink.Shared/TypeSystemProxy/MethodProxy.cs b/src/tools/illink/src/ILLink.Shared/TypeSystemProxy/MethodProxy.cs index 92ba44e630ba..008d1c1536ef 100644 --- a/src/tools/illink/src/ILLink.Shared/TypeSystemProxy/MethodProxy.cs +++ b/src/tools/illink/src/ILLink.Shared/TypeSystemProxy/MethodProxy.cs @@ -56,6 +56,7 @@ internal bool HasParameterOfType (ParameterIndex parameterIndex, string fullType internal partial bool HasGenericParameters (); internal partial bool HasGenericParametersCount (int genericParameterCount); internal partial ImmutableArray GetGenericParameters (); + internal partial bool IsConstructor (); internal partial bool IsStatic (); internal partial bool HasImplicitThis (); internal partial bool ReturnsVoid (); diff --git a/src/tools/illink/src/ILLink.Tasks/build/Microsoft.NET.ILLink.targets b/src/tools/illink/src/ILLink.Tasks/build/Microsoft.NET.ILLink.targets index bac804e1e1d4..d6d45f475fc3 100644 --- a/src/tools/illink/src/ILLink.Tasks/build/Microsoft.NET.ILLink.targets +++ b/src/tools/illink/src/ILLink.Tasks/build/Microsoft.NET.ILLink.targets @@ -52,6 +52,9 @@ Copyright (c) .NET Foundation. All rights reserved. <_UseManagedNtlm Condition="'$(_UseManagedNtlm)' == '' and $(RuntimeIdentifier.StartsWith('linux-bionic'))">true <_UseManagedNtlm Condition="'$(_UseManagedNtlm)' == '' and $(RuntimeIdentifier.StartsWith('linux'))">false + <_ComObjectDescriptorSupport Condition="'$(_ComObjectDescriptorSupport)' == ''">false + <_DesignerHostSupport Condition="'$(_DesignerHostSupport)' == ''">false + <_DefaultValueAttributeSupport Condition="'$(_DefaultValueAttributeSupport)' == ''">false diff --git a/src/tools/illink/src/linker/CompatibilitySuppressions.xml b/src/tools/illink/src/linker/CompatibilitySuppressions.xml index 7bf0a1e0ce69..a1c6c7ff8297 100644 --- a/src/tools/illink/src/linker/CompatibilitySuppressions.xml +++ b/src/tools/illink/src/linker/CompatibilitySuppressions.xml @@ -1,4 +1,4 @@ - + @@ -1497,6 +1497,18 @@ CP0002 M:Mono.Linker.Steps.SubStepsDispatcher.Process(Mono.Linker.LinkContext) + + CP0002 + M:Mono.Linker.LinkContext.get_KeepComInterfaces + ref/net9.0/illink.dll + lib/net9.0/illink.dll + + + CP0002 + M:Mono.Linker.LinkContext.set_KeepComInterfaces(System.Boolean) + ref/net9.0/illink.dll + lib/net9.0/illink.dll + CP0008 T:Mono.Linker.LinkContext @@ -1537,4 +1549,4 @@ CP0017 M:Mono.Linker.LinkContext.Resolve(Mono.Cecil.AssemblyNameReference)$0 - + \ No newline at end of file diff --git a/src/tools/illink/src/linker/Linker.Dataflow/FlowAnnotations.cs b/src/tools/illink/src/linker/Linker.Dataflow/FlowAnnotations.cs index 0c257fa068d8..3b148cf3a1ac 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/FlowAnnotations.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/FlowAnnotations.cs @@ -682,11 +682,11 @@ public FieldAnnotation (FieldDefinition field, DynamicallyAccessedMemberTypes an internal partial bool MethodRequiresDataFlowAnalysis (MethodProxy method) => RequiresDataFlowAnalysis (method.Method); - internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) - => new MethodReturnValue (method.Method.ReturnType.ResolveToTypeDefinition (_context), method.Method, dynamicallyAccessedMemberTypes); + internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, bool isNewObj, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + => MethodReturnValue.Create (method.Method, isNewObj, dynamicallyAccessedMemberTypes, _context); - internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method) - => GetMethodReturnValue (method, GetReturnParameterAnnotation (method.Method)); + internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, bool isNewObj) + => GetMethodReturnValue (method, isNewObj, GetReturnParameterAnnotation (method.Method)); internal partial GenericParameterValue GetGenericParameterValue (GenericParameterProxy genericParameter) => new GenericParameterValue (genericParameter.GenericParameter, GetGenericParameterAnnotation (genericParameter.GenericParameter)); diff --git a/src/tools/illink/src/linker/Linker.Dataflow/GenericParameterProxy.cs b/src/tools/illink/src/linker/Linker.Dataflow/GenericParameterProxy.cs index 1c92df4559c5..5eb73751b4c9 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/GenericParameterProxy.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/GenericParameterProxy.cs @@ -13,6 +13,18 @@ internal readonly partial struct GenericParameterProxy internal partial bool HasDefaultConstructorConstraint () => GenericParameter.HasDefaultConstructorConstraint; + internal partial bool HasEnumConstraint () + { + if (GenericParameter.HasConstraints) { + foreach (GenericParameterConstraint? constraint in GenericParameter.Constraints) { + if (constraint.ConstraintType.Name == "Enum" && constraint.ConstraintType.Namespace == "System") + return true; + } + } + + return false; + } + public readonly GenericParameter GenericParameter; public override string ToString () => GenericParameter.ToString (); diff --git a/src/tools/illink/src/linker/Linker.Dataflow/HandleCallAction.cs b/src/tools/illink/src/linker/Linker.Dataflow/HandleCallAction.cs index 108b79356a02..998d9a06fdae 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/HandleCallAction.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/HandleCallAction.cs @@ -2,11 +2,16 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using ILLink.Shared.TypeSystemProxy; using Mono.Cecil; +using Mono.Cecil.Cil; using Mono.Linker; using Mono.Linker.Dataflow; +using Mono.Linker.Steps; +using MultiValue = ILLink.Shared.DataFlow.ValueSet; namespace ILLink.Shared.TrimAnalysis { @@ -15,21 +20,163 @@ internal partial struct HandleCallAction #pragma warning disable CA1822 // Mark members as static - the other partial implementations might need to be instance methods readonly LinkContext _context; + readonly Instruction _operation; + readonly MarkStep _markStep; readonly ReflectionMarker _reflectionMarker; readonly MethodDefinition _callingMethodDefinition; + readonly MethodReference _calledMethodReference; public HandleCallAction ( LinkContext context, + Instruction operation, + MarkStep markStep, ReflectionMarker reflectionMarker, in DiagnosticContext diagnosticContext, - MethodDefinition callingMethodDefinition) + MethodDefinition callingMethodDefinition, + MethodReference calledMethodReference) { _context = context; + _operation = operation; + _isNewObj = operation.OpCode == OpCodes.Newobj; + _markStep = markStep; _reflectionMarker = reflectionMarker; _diagnosticContext = diagnosticContext; _callingMethodDefinition = callingMethodDefinition; _annotations = context.Annotations.FlowAnnotations; _requireDynamicallyAccessedMembersAction = new (reflectionMarker, diagnosticContext); + _calledMethodReference = calledMethodReference; + } + + private partial bool TryHandleIntrinsic ( + MethodProxy calledMethod, + MultiValue instanceValue, + IReadOnlyList argumentValues, + IntrinsicId intrinsicId, + out MultiValue? methodReturnValue) + { + MultiValue? maybeMethodReturnValue = methodReturnValue = null; + Debug.Assert (calledMethod.Method == _context.Resolve (_calledMethodReference)); + + switch (intrinsicId) { + case IntrinsicId.None: { + if (ReflectionMethodBodyScanner.IsPInvokeDangerous (calledMethod.Method, _context, out bool comDangerousMethod)) { + Debug.Assert (comDangerousMethod); // Currently COM dangerous is the only one we detect + _diagnosticContext.AddDiagnostic (DiagnosticId.CorrectnessOfCOMCannotBeGuaranteed, calledMethod.GetDisplayName ()); + } + if (_context.Annotations.DoesMethodRequireUnreferencedCode (calledMethod.Method, out RequiresUnreferencedCodeAttribute? requiresUnreferencedCode)) + MarkStep.ReportRequiresUnreferencedCode (calledMethod.GetDisplayName (), requiresUnreferencedCode, _diagnosticContext); + + return TryHandleSharedIntrinsic (calledMethod, instanceValue, argumentValues, intrinsicId, out methodReturnValue); + } + + case IntrinsicId.TypeDelegator_Ctor: { + // This is an identity function for analysis purposes + if (_operation.OpCode == OpCodes.Newobj) + AddReturnValue (argumentValues[0]); + } + break; + + case IntrinsicId.Array_Empty: { + AddReturnValue (ArrayValue.Create (0, ((GenericInstanceMethod) _calledMethodReference).GenericArguments[0])); + } + break; + + case IntrinsicId.Array_CreateInstance: + case IntrinsicId.Enum_GetValues: + case IntrinsicId.Marshal_SizeOf: + case IntrinsicId.Marshal_OffsetOf: + case IntrinsicId.Marshal_PtrToStructure: + case IntrinsicId.Marshal_DestroyStructure: + case IntrinsicId.Marshal_GetDelegateForFunctionPointer: + case IntrinsicId.Assembly_get_Location: + case IntrinsicId.Assembly_GetFile: + case IntrinsicId.Assembly_GetFiles: + case IntrinsicId.AssemblyName_get_CodeBase: + case IntrinsicId.AssemblyName_get_EscapedCodeBase: + case IntrinsicId.RuntimeReflectionExtensions_GetMethodInfo: + case IntrinsicId.Delegate_get_Method: + // These intrinsics are not interesting for trimmer (they are interesting for AOT and that's why they are recognized) + break; + + // + // System.Object + // + // GetType() + // + case IntrinsicId.Object_GetType: { + foreach (var valueNode in instanceValue.AsEnumerable ()) { + // Note that valueNode can be statically typed in IL as some generic argument type. + // For example: + // void Method(T instance) { instance.GetType().... } + // Currently this case will end up with null StaticType - since there's no typedef for the generic argument type. + // But it could be that T is annotated with for example PublicMethods: + // void Method<[DAM(PublicMethods)] T>(T instance) { instance.GetType().GetMethod("Test"); } + // In this case it's in theory possible to handle it, by treating the T basically as a base class + // for the actual type of "instance". But the analysis for this would be pretty complicated (as the marking + // has to happen on the callsite, which doesn't know that GetType() will be used...). + // For now we're intentionally ignoring this case - it will produce a warning. + // The counter example is: + // Method(new Derived); + // In this case to get correct results, trimmer would have to mark all public methods on Derived. Which + // currently it won't do. + + TypeDefinition? staticType = (valueNode as IValueWithStaticType)?.StaticType?.Type; + if (staticType is null) { + // We don't know anything about the type GetType was called on. Track this as a usual result of a method call without any annotations + AddReturnValue (_context.Annotations.FlowAnnotations.GetMethodReturnValue (calledMethod, _isNewObj)); + } else if (staticType.IsSealed || staticType.IsTypeOf ("System", "Delegate") || staticType.IsTypeOf ("System", "Array")) { + // We can treat this one the same as if it was a typeof() expression + + // We can allow Object.GetType to be modeled as System.Delegate because we keep all methods + // on delegates anyway so reflection on something this approximation would miss is actually safe. + + // We can also treat all arrays as "sealed" since it's not legal to derive from Array type (even though it is not sealed itself) + + // We ignore the fact that the type can be annotated (see below for handling of annotated types) + // This means the annotations (if any) won't be applied - instead we rely on the exact knowledge + // of the type. So for example even if the type is annotated with PublicMethods + // but the code calls GetProperties on it - it will work - mark properties, don't mark methods + // since we ignored the fact that it's annotated. + // This can be seen a little bit as a violation of the annotation, but we already have similar cases + // where a parameter is annotated and if something in the method sets a specific known type to it + // we will also make it just work, even if the annotation doesn't match the usage. + AddReturnValue (new SystemTypeValue (staticType)); + } else { + // Make sure the type is marked (this will mark it as used via reflection, which is sort of true) + // This should already be true for most cases (method params, fields, ...), but just in case + _reflectionMarker.MarkType (_diagnosticContext.Origin, staticType); + + var annotation = _markStep.DynamicallyAccessedMembersTypeHierarchy + .ApplyDynamicallyAccessedMembersToTypeHierarchy (staticType); + + // Return a value which is "unknown type" with annotation. For now we'll use the return value node + // for the method, which means we're loosing the information about which staticType this + // started with. For now we don't need it, but we can add it later on. + AddReturnValue (_context.Annotations.FlowAnnotations.GetMethodReturnValue (calledMethod, _isNewObj, annotation)); + } + } + } + break; + + // Note about Activator.CreateInstance + // There are 2 interesting cases: + // - The generic argument for T is either specific type or annotated - in that case generic instantiation will handle this + // since from .NET 6+ the T is annotated with PublicParameterlessConstructor annotation, so the trimming tools would apply this as for any other method. + // - The generic argument for T is unannotated type - the generic instantiantion handling has a special case for handling PublicParameterlessConstructor requirement + // in such that if the generic argument type has the "new" constraint it will not warn (as it is effectively the same thing semantically). + // For all other cases, the trimming tools would have already produced a warning. + + default: + return false; + } + + methodReturnValue = maybeMethodReturnValue; + return true; + + void AddReturnValue (MultiValue value) + { + maybeMethodReturnValue = (maybeMethodReturnValue is null) ? value : MultiValueLattice.Meet ((MultiValue) maybeMethodReturnValue, value); + } } private partial bool MethodIsTypeConstructor (MethodProxy method) diff --git a/src/tools/illink/src/linker/Linker.Dataflow/MethodBodyScanner.cs b/src/tools/illink/src/linker/Linker.Dataflow/MethodBodyScanner.cs index 4d4855dc7ce6..34e5797ffd03 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/MethodBodyScanner.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/MethodBodyScanner.cs @@ -986,11 +986,8 @@ private ValueNodeList PopCallArguments ( Stack currentStack, MethodReference methodCalled, MethodBody containingMethodBody, - bool isNewObj, int ilOffset, - out SingleValue? newObjValue) + bool isNewObj, int ilOffset) { - newObjValue = null; - int countToPop = 0; if (!isNewObj && methodCalled.HasThis && !methodCalled.ExplicitThis) countToPop++; @@ -1003,8 +1000,7 @@ private ValueNodeList PopCallArguments ( } if (isNewObj) { - newObjValue = UnknownValue.Instance; - methodParams.Add (newObjValue); + methodParams.Add (UnknownValue.Instance); } methodParams.Reverse (); return methodParams; @@ -1090,33 +1086,15 @@ private void HandleCall ( bool isNewObj = operation.OpCode.Code == Code.Newobj; - SingleValue? newObjValue; - ValueNodeList methodArguments = PopCallArguments (currentStack, calledMethod, callingMethodBody, isNewObj, - operation.Offset, out newObjValue); + ValueNodeList methodArguments = PopCallArguments (currentStack, calledMethod, callingMethodBody, isNewObj, operation.Offset); var dereferencedMethodParams = new List (); foreach (var argument in methodArguments) dereferencedMethodParams.Add (DereferenceValue (argument, locals, ref interproceduralState)); - MultiValue methodReturnValue; - bool handledFunction = HandleCall ( + MultiValue methodReturnValue = HandleCall ( callingMethodBody, calledMethod, operation, - new ValueNodeList (dereferencedMethodParams), - out methodReturnValue); - - // Handle the return value or newobj result - if (!handledFunction) { - if (isNewObj) { - if (newObjValue == null) - methodReturnValue = new MultiValue (UnknownValue.Instance); - else - methodReturnValue = newObjValue; - } else { - if (!calledMethod.ReturnsVoid ()) { - methodReturnValue = UnknownValue.Instance; - } - } - } + new ValueNodeList (dereferencedMethodParams)); if (isNewObj || !calledMethod.ReturnsVoid ()) currentStack.Push (new StackSlot (methodReturnValue)); @@ -1134,12 +1112,11 @@ private void HandleCall ( public TypeDefinition? ResolveToTypeDefinition (TypeReference typeReference) => typeReference.ResolveToTypeDefinition (_context); - public abstract bool HandleCall ( + public abstract MultiValue HandleCall ( MethodBody callingMethodBody, MethodReference calledMethod, Instruction operation, - ValueNodeList methodParams, - out MultiValue methodReturnValue); + ValueNodeList methodParams); // Limit tracking array values to 32 values for performance reasons. There are many arrays much longer than 32 elements in .NET, but the interesting ones for trimming are nearly always less than 32 elements. private const int MaxTrackedArrayValues = 32; diff --git a/src/tools/illink/src/linker/Linker.Dataflow/MethodProxy.cs b/src/tools/illink/src/linker/Linker.Dataflow/MethodProxy.cs index a4ca0634a81f..6e6fd7a1bf21 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/MethodProxy.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/MethodProxy.cs @@ -59,6 +59,8 @@ internal partial ImmutableArray GetGenericParameters () return builder.ToImmutableArray (); } + internal partial bool IsConstructor () => Method.IsConstructor; + internal partial bool IsStatic () => Method.IsStatic; internal partial bool HasImplicitThis () => Method.HasImplicitThis (); diff --git a/src/tools/illink/src/linker/Linker.Dataflow/MethodReturnValue.cs b/src/tools/illink/src/linker/Linker.Dataflow/MethodReturnValue.cs index 9197a7bda6be..bec6951b17e4 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/MethodReturnValue.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/MethodReturnValue.cs @@ -2,9 +2,11 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using ILLink.Shared.DataFlow; using Mono.Cecil; +using Mono.Linker; using Mono.Linker.Dataflow; using TypeDefinition = Mono.Cecil.TypeDefinition; @@ -16,7 +18,14 @@ namespace ILLink.Shared.TrimAnalysis /// internal partial record MethodReturnValue { - public MethodReturnValue (TypeDefinition? staticType, MethodDefinition method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + public static MethodReturnValue Create (MethodDefinition method, bool isNewObj, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes, LinkContext context) + { + Debug.Assert (!isNewObj || method.IsConstructor, "isNewObj can only be true for constructors"); + var staticType = isNewObj ? method.DeclaringType : method.ReturnType.ResolveToTypeDefinition (context); + return new MethodReturnValue (staticType, method, dynamicallyAccessedMemberTypes); + } + + private MethodReturnValue (TypeDefinition? staticType, MethodDefinition method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) { StaticType = staticType == null ? null : new (staticType); Method = method; diff --git a/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMarker.cs b/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMarker.cs index 6dbd6e7ca8c6..214565c2ed32 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMarker.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMarker.cs @@ -149,7 +149,7 @@ void MarkInterfaceImplementation (in MessageOrigin origin, InterfaceImplementati if (!_enabled) return; - _markStep.MarkInterfaceImplementation (interfaceImplementation, null, new DependencyInfo (dependencyKind, origin.Provider)); + _markStep.MarkInterfaceImplementation (interfaceImplementation, origin, new DependencyInfo (dependencyKind, origin.Provider)); } internal void MarkConstructorsOnType (in MessageOrigin origin, TypeDefinition type, Func? filter, BindingFlags? bindingFlags = null) diff --git a/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs index 72e9339bc3bc..3f5109bfeff9 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; -using ILLink.Shared; using ILLink.Shared.TrimAnalysis; using ILLink.Shared.TypeSystemProxy; using Mono.Cecil; @@ -76,7 +75,7 @@ protected override void Scan (MethodIL methodIL, ref InterproceduralState interp if (!methodIL.Method.ReturnsVoid ()) { var method = methodIL.Method; - var methodReturnValue = _annotations.GetMethodReturnValue (method); + var methodReturnValue = _annotations.GetMethodReturnValue (method, isNewObj: false); if (methodReturnValue.DynamicallyAccessedMemberTypes != 0) HandleAssignmentPattern (_origin, ReturnValue, methodReturnValue); } @@ -118,19 +117,17 @@ protected override void HandleStoreParameter (MethodDefinition method, MethodPar protected override void HandleStoreMethodReturnValue (MethodDefinition method, MethodReturnValue returnValue, Instruction operation, MultiValue valueToStore) => HandleStoreValueWithDynamicallyAccessedMembers (returnValue, operation, valueToStore); - public override bool HandleCall (MethodBody callingMethodBody, MethodReference calledMethod, Instruction operation, ValueNodeList methodParams, out MultiValue methodReturnValue) + public override MultiValue HandleCall (MethodBody callingMethodBody, MethodReference calledMethod, Instruction operation, ValueNodeList methodParams) { var reflectionProcessed = _markStep.ProcessReflectionDependency (callingMethodBody, operation); if (reflectionProcessed) { - methodReturnValue = default; - return false; + return UnknownValue.Instance; } Debug.Assert (callingMethodBody.Method == _origin.Provider); var calledMethodDefinition = _context.TryResolve (calledMethod); if (calledMethodDefinition == null) { - methodReturnValue = default; - return false; + return UnknownValue.Instance; } _origin = _origin.WithInstructionOffset (operation.Offset); @@ -162,11 +159,10 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c diagnosticContext, _reflectionMarker, _context, - _markStep, - out methodReturnValue); + _markStep); } - public static bool HandleCall ( + public static MultiValue HandleCall ( Instruction operation, MethodReference calledMethod, MultiValue instanceValue, @@ -174,8 +170,7 @@ public static bool HandleCall ( DiagnosticContext diagnosticContext, ReflectionMarker reflectionMarker, LinkContext context, - MarkStep markStep, - out MultiValue methodReturnValue) + MarkStep markStep) { var origin = diagnosticContext.Origin; var calledMethodDefinition = context.TryResolve (calledMethod); @@ -184,203 +179,15 @@ public static bool HandleCall ( Debug.Assert (callingMethodDefinition != null); bool requiresDataFlowAnalysis = context.Annotations.FlowAnnotations.RequiresDataFlowAnalysis (calledMethodDefinition); - var annotatedMethodReturnValue = context.Annotations.FlowAnnotations.GetMethodReturnValue (calledMethodDefinition); + bool isNewObj = operation.OpCode.Code == Code.Newobj; + var annotatedMethodReturnValue = context.Annotations.FlowAnnotations.GetMethodReturnValue (calledMethodDefinition, isNewObj); Debug.Assert (requiresDataFlowAnalysis || annotatedMethodReturnValue.DynamicallyAccessedMemberTypes == DynamicallyAccessedMemberTypes.None); - MultiValue? maybeMethodReturnValue = null; - - var handleCallAction = new HandleCallAction (context, reflectionMarker, diagnosticContext, callingMethodDefinition); + var handleCallAction = new HandleCallAction (context, operation, markStep, reflectionMarker, diagnosticContext, callingMethodDefinition, calledMethod); var intrinsicId = Intrinsics.GetIntrinsicIdForMethod (calledMethodDefinition); - switch (intrinsicId) { - case IntrinsicId.IntrospectionExtensions_GetTypeInfo: - case IntrinsicId.TypeInfo_AsType: - case IntrinsicId.Type_get_UnderlyingSystemType: - case IntrinsicId.Type_GetTypeFromHandle: - case IntrinsicId.Type_get_TypeHandle: - case IntrinsicId.Type_GetInterface: - case IntrinsicId.Type_get_AssemblyQualifiedName: - case IntrinsicId.RuntimeHelpers_RunClassConstructor: - case IntrinsicId.Type_GetConstructors__BindingFlags: - case IntrinsicId.Type_GetMethods__BindingFlags: - case IntrinsicId.Type_GetFields__BindingFlags: - case IntrinsicId.Type_GetProperties__BindingFlags: - case IntrinsicId.Type_GetEvents__BindingFlags: - case IntrinsicId.Type_GetNestedTypes__BindingFlags: - case IntrinsicId.Type_GetMembers__BindingFlags: - case IntrinsicId.Type_GetField: - case IntrinsicId.Type_GetProperty: - case IntrinsicId.Type_GetEvent: - case IntrinsicId.RuntimeReflectionExtensions_GetRuntimeEvent: - case IntrinsicId.RuntimeReflectionExtensions_GetRuntimeField: - case IntrinsicId.RuntimeReflectionExtensions_GetRuntimeMethod: - case IntrinsicId.RuntimeReflectionExtensions_GetRuntimeProperty: - case IntrinsicId.Type_GetMember: - case IntrinsicId.Type_GetMethod: - case IntrinsicId.Type_GetNestedType: - case IntrinsicId.Nullable_GetUnderlyingType: - case IntrinsicId.Expression_Property: - case IntrinsicId.Expression_Field: - case IntrinsicId.Type_get_BaseType: - case IntrinsicId.Type_GetConstructor: - case IntrinsicId.MethodBase_GetMethodFromHandle: - case IntrinsicId.MethodBase_get_MethodHandle: - case IntrinsicId.Type_MakeGenericType: - case IntrinsicId.MethodInfo_MakeGenericMethod: - case IntrinsicId.Expression_Call: - case IntrinsicId.Expression_New: - case IntrinsicId.Type_GetType: - case IntrinsicId.Activator_CreateInstance__Type: - case IntrinsicId.Activator_CreateInstance__AssemblyName_TypeName: - case IntrinsicId.Activator_CreateInstanceFrom: - case IntrinsicId.AppDomain_CreateInstance: - case IntrinsicId.AppDomain_CreateInstanceAndUnwrap: - case IntrinsicId.AppDomain_CreateInstanceFrom: - case IntrinsicId.AppDomain_CreateInstanceFromAndUnwrap: - case IntrinsicId.Assembly_CreateInstance: { - return handleCallAction.Invoke (calledMethodDefinition, instanceValue, argumentValues, intrinsicId, out methodReturnValue); - } - - case IntrinsicId.None: { - if (IsPInvokeDangerous (calledMethodDefinition, context, out bool comDangerousMethod)) { - Debug.Assert (comDangerousMethod); // Currently COM dangerous is the only one we detect - diagnosticContext.AddDiagnostic (DiagnosticId.CorrectnessOfCOMCannotBeGuaranteed, calledMethodDefinition.GetDisplayName ()); - } - if (context.Annotations.DoesMethodRequireUnreferencedCode (calledMethodDefinition, out RequiresUnreferencedCodeAttribute? requiresUnreferencedCode)) - MarkStep.ReportRequiresUnreferencedCode (calledMethodDefinition.GetDisplayName (), requiresUnreferencedCode, diagnosticContext); - - return handleCallAction.Invoke (calledMethodDefinition, instanceValue, argumentValues, intrinsicId, out methodReturnValue); - } - - case IntrinsicId.TypeDelegator_Ctor: { - // This is an identity function for analysis purposes - if (operation.OpCode == OpCodes.Newobj) - AddReturnValue (argumentValues[0]); - } - break; - - case IntrinsicId.Array_Empty: { - AddReturnValue (ArrayValue.Create (0, ((GenericInstanceMethod) calledMethod).GenericArguments[0])); - } - break; - - case IntrinsicId.Array_CreateInstance: - case IntrinsicId.Enum_GetValues: - case IntrinsicId.Marshal_SizeOf: - case IntrinsicId.Marshal_OffsetOf: - case IntrinsicId.Marshal_PtrToStructure: - case IntrinsicId.Marshal_DestroyStructure: - case IntrinsicId.Marshal_GetDelegateForFunctionPointer: - case IntrinsicId.Assembly_get_Location: - case IntrinsicId.Assembly_GetFile: - case IntrinsicId.Assembly_GetFiles: - case IntrinsicId.AssemblyName_get_CodeBase: - case IntrinsicId.AssemblyName_get_EscapedCodeBase: - case IntrinsicId.RuntimeReflectionExtensions_GetMethodInfo: - case IntrinsicId.Delegate_get_Method: - // These intrinsics are not interesting for trimmer (they are interesting for AOT and that's why they are recognized) - break; - - // - // System.Object - // - // GetType() - // - case IntrinsicId.Object_GetType: { - foreach (var valueNode in instanceValue.AsEnumerable ()) { - // Note that valueNode can be statically typed in IL as some generic argument type. - // For example: - // void Method(T instance) { instance.GetType().... } - // Currently this case will end up with null StaticType - since there's no typedef for the generic argument type. - // But it could be that T is annotated with for example PublicMethods: - // void Method<[DAM(PublicMethods)] T>(T instance) { instance.GetType().GetMethod("Test"); } - // In this case it's in theory possible to handle it, by treating the T basically as a base class - // for the actual type of "instance". But the analysis for this would be pretty complicated (as the marking - // has to happen on the callsite, which doesn't know that GetType() will be used...). - // For now we're intentionally ignoring this case - it will produce a warning. - // The counter example is: - // Method(new Derived); - // In this case to get correct results, trimmer would have to mark all public methods on Derived. Which - // currently it won't do. - - TypeDefinition? staticType = (valueNode as IValueWithStaticType)?.StaticType?.Type; - if (staticType is null) { - // We don't know anything about the type GetType was called on. Track this as a usual result of a method call without any annotations - AddReturnValue (context.Annotations.FlowAnnotations.GetMethodReturnValue (calledMethodDefinition)); - } else if (staticType.IsSealed || staticType.IsTypeOf ("System", "Delegate") || staticType.IsTypeOf ("System", "Array")) { - // We can treat this one the same as if it was a typeof() expression - - // We can allow Object.GetType to be modeled as System.Delegate because we keep all methods - // on delegates anyway so reflection on something this approximation would miss is actually safe. - - // We can also treat all arrays as "sealed" since it's not legal to derive from Array type (even though it is not sealed itself) - - // We ignore the fact that the type can be annotated (see below for handling of annotated types) - // This means the annotations (if any) won't be applied - instead we rely on the exact knowledge - // of the type. So for example even if the type is annotated with PublicMethods - // but the code calls GetProperties on it - it will work - mark properties, don't mark methods - // since we ignored the fact that it's annotated. - // This can be seen a little bit as a violation of the annotation, but we already have similar cases - // where a parameter is annotated and if something in the method sets a specific known type to it - // we will also make it just work, even if the annotation doesn't match the usage. - AddReturnValue (new SystemTypeValue (staticType)); - } else { - // Make sure the type is marked (this will mark it as used via reflection, which is sort of true) - // This should already be true for most cases (method params, fields, ...), but just in case - reflectionMarker.MarkType (origin, staticType); - - var annotation = markStep.DynamicallyAccessedMembersTypeHierarchy - .ApplyDynamicallyAccessedMembersToTypeHierarchy (staticType); - - // Return a value which is "unknown type" with annotation. For now we'll use the return value node - // for the method, which means we're loosing the information about which staticType this - // started with. For now we don't need it, but we can add it later on. - AddReturnValue (context.Annotations.FlowAnnotations.GetMethodReturnValue (calledMethodDefinition, annotation)); - } - } - } - break; - - // Note about Activator.CreateInstance - // There are 2 interesting cases: - // - The generic argument for T is either specific type or annotated - in that case generic instantiation will handle this - // since from .NET 6+ the T is annotated with PublicParameterlessConstructor annotation, so the trimming tools would apply this as for any other method. - // - The generic argument for T is unannotated type - the generic instantiantion handling has a special case for handling PublicParameterlessConstructor requirement - // in such that if the generic argument type has the "new" constraint it will not warn (as it is effectively the same thing semantically). - // For all other cases, the trimming tools would have already produced a warning. - - default: + if (!handleCallAction.Invoke (calledMethodDefinition, instanceValue, argumentValues, intrinsicId, out MultiValue methodReturnValue)) throw new NotImplementedException ($"Unhandled intrinsic: {intrinsicId}"); - } - - // If we get here, we handled this as an intrinsic. As a convenience, if the code above - // didn't set the return value (and the method has a return value), we will set it to be an - // unknown value with the return type of the method. - bool returnsVoid = calledMethod.ReturnsVoid (); - methodReturnValue = maybeMethodReturnValue ?? (returnsVoid ? - MultiValueLattice.Top : - annotatedMethodReturnValue); - - // Validate that the return value has the correct annotations as per the method return value annotations - if (annotatedMethodReturnValue.DynamicallyAccessedMemberTypes != 0) { - foreach (var uniqueValue in methodReturnValue.AsEnumerable ()) { - if (uniqueValue is ValueWithDynamicallyAccessedMembers methodReturnValueWithMemberTypes) { - if (!methodReturnValueWithMemberTypes.DynamicallyAccessedMemberTypes.HasFlag (annotatedMethodReturnValue.DynamicallyAccessedMemberTypes)) - throw new InvalidOperationException ($"Internal trimming error: processing of call from {callingMethodDefinition.GetDisplayName ()} to {calledMethod.GetDisplayName ()} returned value which is not correctly annotated with the expected dynamic member access kinds."); - } else if (uniqueValue is SystemTypeValue) { - // SystemTypeValue can fulfill any requirement, so it's always valid - // The requirements will be applied at the point where it's consumed (passed as a method parameter, set as field value, returned from the method) - } else { - throw new InvalidOperationException ($"Internal trimming error: processing of call from {callingMethodDefinition.GetDisplayName ()} to {calledMethod.GetDisplayName ()} returned value which is not correctly annotated with the expected dynamic member access kinds."); - } - } - } - - return true; - - void AddReturnValue (MultiValue value) - { - maybeMethodReturnValue = (maybeMethodReturnValue is null) ? value : MultiValueLattice.Meet ((MultiValue) maybeMethodReturnValue, value); - } + return methodReturnValue; } static bool IsComInterop (IMarshalInfoProvider marshalInfoProvider, TypeReference parameterType, LinkContext context) @@ -449,7 +256,7 @@ void HandleAssignmentPattern ( TrimAnalysisPatterns.Add (new TrimAnalysisAssignmentPattern (value, targetValue, origin)); } - private static bool IsPInvokeDangerous (MethodDefinition methodDefinition, LinkContext context, out bool comDangerousMethod) + internal static bool IsPInvokeDangerous (MethodDefinition methodDefinition, LinkContext context, out bool comDangerousMethod) { // The method in ILLink only detects one condition - COM Dangerous, but it's structured like this // so that the code looks very similar to AOT which has more than one condition. diff --git a/src/tools/illink/src/linker/Linker.Dataflow/TrimAnalysisMethodCallPattern.cs b/src/tools/illink/src/linker/Linker.Dataflow/TrimAnalysisMethodCallPattern.cs index a7b42a048c7c..417e0240a9c0 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/TrimAnalysisMethodCallPattern.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/TrimAnalysisMethodCallPattern.cs @@ -69,8 +69,7 @@ public void MarkAndProduceDiagnostics (ReflectionMarker reflectionMarker, MarkSt diagnosticContext, reflectionMarker, context, - markStep, - out MultiValue _); + markStep); } } } diff --git a/src/tools/illink/src/linker/Linker.Steps/DescriptorMarker.cs b/src/tools/illink/src/linker/Linker.Steps/DescriptorMarker.cs index a527ca2e0df6..f07200ab47e4 100644 --- a/src/tools/illink/src/linker/Linker.Steps/DescriptorMarker.cs +++ b/src/tools/illink/src/linker/Linker.Steps/DescriptorMarker.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; @@ -23,14 +24,24 @@ public class DescriptorMarker : ProcessLinkerXmlBase static readonly string[] _accessorsAll = new string[] { "all" }; static readonly char[] _accessorsSep = new char[] { ';' }; + protected readonly HashSet _preservedMembers; + public DescriptorMarker (LinkContext context, Stream documentStream, string xmlDocumentLocation) : base (context, documentStream, xmlDocumentLocation) { + _preservedMembers = new (); } public DescriptorMarker (LinkContext context, Stream documentStream, EmbeddedResource resource, AssemblyDefinition resourceAssembly, string xmlDocumentLocation = "") : base (context, documentStream, resource, resourceAssembly, xmlDocumentLocation) { + _preservedMembers = new (); + } + + protected void LogDuplicatePreserve(string memberName, XPathNavigator duplicatePosition) + { + var origin = GetMessageOriginForPosition (duplicatePosition); + _context.LogMessage (MessageContainer.CreateInfoMessage (origin, $"Duplicate preserve of '{memberName}'")); } public void Mark () @@ -147,16 +158,16 @@ protected static TypePreserve GetTypePreserve (XPathNavigator nav) protected override void ProcessField (TypeDefinition type, FieldDefinition field, XPathNavigator nav) { - if (_context.Annotations.IsMarked (field)) - LogWarning (nav, DiagnosticId.XmlDuplicatePreserveMember, field.FullName); + if (!_preservedMembers.Add (field)) + LogDuplicatePreserve (field.FullName, nav); _context.Annotations.Mark (field, new DependencyInfo (DependencyKind.XmlDescriptor, _xmlDocumentLocation), GetMessageOriginForPosition (nav)); } protected override void ProcessMethod (TypeDefinition type, MethodDefinition method, XPathNavigator nav, object? customData) { - if (_context.Annotations.IsMarked (method)) - LogWarning (nav, DiagnosticId.XmlDuplicatePreserveMember, method.GetDisplayName ()); + if (!_preservedMembers.Add (method)) + LogDuplicatePreserve (method.GetDisplayName (), nav); _context.Annotations.MarkIndirectlyCalledMethod (method); _context.Annotations.SetAction (method, MethodAction.Parse); @@ -212,8 +223,8 @@ public static string GetMethodSignature (MethodDefinition meth, bool includeGene protected override void ProcessEvent (TypeDefinition type, EventDefinition @event, XPathNavigator nav, object? customData) { - if (_context.Annotations.IsMarked (@event)) - LogWarning (nav, DiagnosticId.XmlDuplicatePreserveMember, @event.FullName); + if (!_preservedMembers.Add (@event)) + LogDuplicatePreserve(@event.FullName, nav); ProcessMethod (type, @event.AddMethod, nav, customData); ProcessMethod (type, @event.RemoveMethod, nav, customData); @@ -224,8 +235,8 @@ protected override void ProcessProperty (TypeDefinition type, PropertyDefinition { string[] accessors = fromSignature ? GetAccessors (nav) : _accessorsAll; - if (_context.Annotations.IsMarked (property)) - LogWarning (nav, DiagnosticId.XmlDuplicatePreserveMember, property.FullName); + if (!_preservedMembers.Add (property)) + LogDuplicatePreserve(property.FullName, nav); if (Array.IndexOf (accessors, "all") >= 0) { ProcessMethodIfNotNull (type, property.GetMethod, nav, customData); diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkScopeStack.cs b/src/tools/illink/src/linker/Linker.Steps/MarkScopeStack.cs deleted file mode 100644 index ab1ad448754f..000000000000 --- a/src/tools/illink/src/linker/Linker.Steps/MarkScopeStack.cs +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using Mono.Cecil; - -namespace Mono.Linker.Steps -{ - public class MarkScopeStack - { - public readonly struct Scope - { - public readonly MessageOrigin Origin; - - public Scope (in MessageOrigin origin) - { - Origin = origin; - } - } - - readonly Stack _scopeStack; - - internal readonly struct LocalScope : IDisposable - { - readonly MessageOrigin _origin; - readonly MarkScopeStack _scopeStack; - - public LocalScope (in MessageOrigin origin, MarkScopeStack scopeStack) - { - _origin = origin; - _scopeStack = scopeStack; - - _scopeStack.Push (new Scope (new MessageOrigin (origin))); - } - - public LocalScope (in Scope scope, MarkScopeStack scopeStack) - { - _origin = scope.Origin; - _scopeStack = scopeStack; - _scopeStack.Push (scope); - } - - public void Dispose () - { - Scope scope = _scopeStack.Pop (); - - if (_origin.Provider != scope.Origin.Provider) - throw new InternalErrorException ($"Scope stack imbalance - expected to pop '{_origin}' but instead popped '{scope.Origin}'."); - } - } - - internal readonly struct ParentScope : IDisposable - { - readonly Scope _parentScope; - readonly Scope _childScope; - readonly MarkScopeStack _scopeStack; - - public ParentScope (MarkScopeStack scopeStack) - { - _scopeStack = scopeStack; - _childScope = _scopeStack.Pop (); - _parentScope = _scopeStack.CurrentScope; - } - - public void Dispose () - { - if (_parentScope.Origin.Provider != _scopeStack.CurrentScope.Origin.Provider) - throw new InternalErrorException ($"Scope stack imbalance - expected top of stack to be '{_parentScope.Origin}' but instead found '{_scopeStack.CurrentScope.Origin}'."); - - _scopeStack.Push (_childScope); - } - } - - public MarkScopeStack () - { - _scopeStack = new Stack (); - } - - internal LocalScope PushLocalScope (in MessageOrigin origin) - { - return new LocalScope (origin, this); - } - - internal LocalScope PushLocalScope (in Scope scope) - { - return new LocalScope (scope, this); - } - - internal ParentScope PopToParentScope () - { - return new ParentScope (this); - } - - public IDisposable PushScope (in MessageOrigin origin) - { - return new LocalScope (origin, this); - } - - public IDisposable PushScope (in Scope scope) - { - return new LocalScope (scope, this); - } - - public IDisposable PopToParent () - { - return new ParentScope (this); - } - - public Scope CurrentScope { - get { - if (!_scopeStack.TryPeek (out var result)) - throw new InternalErrorException ($"Scope stack imbalance - expected scope but instead the stack is empty."); - - return result; - } - } - - public void UpdateCurrentScopeInstructionOffset (int offset) - { - var scope = _scopeStack.Pop (); - if (scope.Origin.Provider is not MethodDefinition) - throw new InternalErrorException ($"Trying to update instruction offset of scope stack which is not a method. Current stack scope is '{scope}'."); - - _scopeStack.Push (new Scope (new MessageOrigin (scope.Origin.Provider, offset))); - } - - void Push (in Scope scope) - { - _scopeStack.Push (scope); - } - - Scope Pop () - { - if (!_scopeStack.TryPop (out var result)) - throw new InternalErrorException ($"Scope stack imbalance - trying to pop empty stack."); - - return result; - } - - [Conditional ("DEBUG")] - public void AssertIsEmpty () => Debug.Assert (_scopeStack.Count == 0); - - } -} diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.MethodDefinitionNode.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.MethodDefinitionNode.cs new file mode 100644 index 000000000000..34dd6e8a8d03 --- /dev/null +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.MethodDefinitionNode.cs @@ -0,0 +1,43 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using ILCompiler.DependencyAnalysisFramework; +using Mono.Cecil; + +namespace Mono.Linker.Steps +{ + public partial class MarkStep + { + internal sealed class MethodDefinitionNode : DependencyNodeCore + { + readonly MethodDefinition method; + readonly DependencyInfo reason; + + public MethodDefinitionNode (MethodDefinition method, DependencyInfo reason) + { + this.method = method; + this.reason = reason; + } + + public override bool InterestingForDynamicDependencyAnalysis => false; + + public override bool HasDynamicDependencies => false; + + public override bool HasConditionalStaticDependencies => false; + + public override bool StaticDependenciesAreComputed => true; + + public override IEnumerable? GetStaticDependencies (NodeFactory context) + { + context.MarkStep.ProcessMethod (method, reason); + return null; + } + + public override IEnumerable? GetConditionalStaticDependencies (NodeFactory context) => null; + public override IEnumerable? SearchDynamicDependencies (List> markedNodes, int firstNode, NodeFactory context) => null; + protected override string GetName (NodeFactory context) => method.GetDisplayName(); + } + } +} diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.NodeFactory.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.NodeFactory.cs new file mode 100644 index 000000000000..61d1e806209f --- /dev/null +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.NodeFactory.cs @@ -0,0 +1,71 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using Mono.Cecil; + +namespace Mono.Linker.Steps +{ + public partial class MarkStep + { + internal sealed class NodeFactory (MarkStep markStep) + { + public MarkStep MarkStep { get; } = markStep; + readonly NodeCache _typeNodes = new (static t => new TypeDefinitionNode(t)); + readonly NodeCache _methodNodes = new (static _ => throw new InvalidOperationException ("Creation of node requires more than the key.")); + readonly NodeCache _propertyNodes = new (static p => new PropertyDefinitionNode(p)); + readonly NodeCache _typeIsRelevantToVariantCastingNodes = new (static (t) => new TypeIsRelevantToVariantCastingNode (t)); + + internal TypeDefinitionNode GetTypeNode (TypeDefinition definition) + { + return _typeNodes.GetOrAdd (definition); + } + + internal MethodDefinitionNode GetMethodDefinitionNode (MethodDefinition method, DependencyInfo reason) + { + return _methodNodes.GetOrAdd (method, (k) => new MethodDefinitionNode (k, reason)); + } + + internal TypeIsRelevantToVariantCastingNode GetTypeIsRelevantToVariantCastingNode (TypeDefinition type) + { + return _typeIsRelevantToVariantCastingNodes.GetOrAdd (type); + } + + internal PropertyDefinitionNode GetPropertyNode (PropertyDefinition prop) + { + return _propertyNodes.GetOrAdd (prop); + } + + struct NodeCache where TKey : notnull + { + // Change to concurrent dictionary if/when multithreaded marking is enabled + readonly Dictionary _cache; + readonly Func _creator; + + public NodeCache (Func creator, IEqualityComparer comparer) + { + _creator = creator; + _cache = new (comparer); + } + + public NodeCache (Func creator) + { + _creator = creator; + _cache = new (); + } + + public TValue GetOrAdd (TKey key) + { + return _cache.GetOrAdd (key, _creator); + } + + public TValue GetOrAdd (TKey key, Func creator) + { + return _cache.GetOrAdd (key, creator); + } + } + } + } +} diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.ProcessCallbackNode.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.ProcessCallbackNode.cs new file mode 100644 index 000000000000..9fe4821f4438 --- /dev/null +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.ProcessCallbackNode.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using ILCompiler.DependencyAnalysisFramework; + +namespace Mono.Linker.Steps +{ + public partial class MarkStep + { + sealed class ProcessCallbackNode : DependencyNodeCore + { + Func _processAction; + DependencyList? _dependencies; + + public ProcessCallbackNode (Func action) => _processAction = action; + + public void Process () + { + _dependencies = new DependencyList (); + if (_processAction ()) { + _dependencies.Add (new ProcessCallbackNode (_processAction), "Some processing was done, continuation required"); + } + } + + public override bool InterestingForDynamicDependencyAnalysis => false; + + public override bool HasDynamicDependencies => false; + + public override bool HasConditionalStaticDependencies => false; + + public override bool StaticDependenciesAreComputed => _dependencies != null; + + public override IEnumerable? GetStaticDependencies (NodeFactory context) => _dependencies; + + public override IEnumerable? GetConditionalStaticDependencies (NodeFactory context) => null; + public override IEnumerable? SearchDynamicDependencies (List> markedNodes, int firstNode, NodeFactory context) => null; + protected override string GetName (NodeFactory context) => "Process"; + } + } +} diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.PropertyDefinitionNode.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.PropertyDefinitionNode.cs new file mode 100644 index 000000000000..68e86ba7edca --- /dev/null +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.PropertyDefinitionNode.cs @@ -0,0 +1,46 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.Generic; +using ILCompiler.DependencyAnalysisFramework; +using Mono.Cecil; + +namespace Mono.Linker.Steps +{ + + public partial class MarkStep + { + internal sealed class PropertyDefinitionNode : DependencyNodeCore + { + PropertyDefinition _property; + public PropertyDefinitionNode(PropertyDefinition property) + { + _property = property; + } + + public override bool InterestingForDynamicDependencyAnalysis => false; + + public override bool HasDynamicDependencies => false; + + public override bool HasConditionalStaticDependencies => false; + + public override bool StaticDependenciesAreComputed => true; + + public override IEnumerable? GetConditionalStaticDependencies (NodeFactory context) => null; + + public override IEnumerable? GetStaticDependencies (NodeFactory context) + { + var propertyOrigin = new MessageOrigin (_property); + + // Consider making this more similar to MarkEvent method? + context.MarkStep.MarkCustomAttributes (_property, new DependencyInfo (DependencyKind.CustomAttribute, _property), propertyOrigin); + context.MarkStep.DoAdditionalPropertyProcessing (_property); + return null; + } + + public override IEnumerable? SearchDynamicDependencies (List> markedNodes, int firstNode, NodeFactory context) => null; + + protected override string GetName (NodeFactory context) => _property.GetDisplayName (); + } + } +} diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.TypeDefinitionNode.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.TypeDefinitionNode.cs new file mode 100644 index 000000000000..d26467930afc --- /dev/null +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.TypeDefinitionNode.cs @@ -0,0 +1,40 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.Generic; +using ILCompiler.DependencyAnalysisFramework; +using Mono.Cecil; + +namespace Mono.Linker.Steps +{ + public partial class MarkStep + { + internal sealed class TypeDefinitionNode : DependencyNodeCore + { + readonly TypeDefinition type; + + public TypeDefinitionNode (TypeDefinition type) + { + this.type = type; + } + + public override bool InterestingForDynamicDependencyAnalysis => false; + + public override bool HasDynamicDependencies => false; + + public override bool HasConditionalStaticDependencies => false; + + public override bool StaticDependenciesAreComputed => true; + + public override IEnumerable? GetStaticDependencies (NodeFactory context) + { + context.MarkStep.ProcessType (type); + return null; + } + + public override IEnumerable? GetConditionalStaticDependencies (NodeFactory context) => null; + public override IEnumerable? SearchDynamicDependencies (List> markedNodes, int firstNode, NodeFactory context) => null; + protected override string GetName (NodeFactory context) => type.GetDisplayName(); + } + } +} diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.TypeIsRelevantToVariantCastingNode.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.TypeIsRelevantToVariantCastingNode.cs new file mode 100644 index 000000000000..00f790b5d9d4 --- /dev/null +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.TypeIsRelevantToVariantCastingNode.cs @@ -0,0 +1,39 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.Generic; +using ILCompiler.DependencyAnalysisFramework; +using Mono.Cecil; + +namespace Mono.Linker.Steps +{ + public partial class MarkStep + { + internal sealed class TypeIsRelevantToVariantCastingNode : DependencyNodeCore + { + TypeDefinition type; + public TypeIsRelevantToVariantCastingNode (TypeDefinition type) => this.type = type; + + public override bool InterestingForDynamicDependencyAnalysis => false; + + public override bool HasDynamicDependencies => false; + + public override bool HasConditionalStaticDependencies => false; + + public override bool StaticDependenciesAreComputed => true; + + public override IEnumerable? GetStaticDependencies (NodeFactory context) + { + yield break; + } + + public override IEnumerable? GetConditionalStaticDependencies (NodeFactory context) => null; + public override IEnumerable? SearchDynamicDependencies (List> markedNodes, int firstNode, NodeFactory context) => null; + protected override string GetName (NodeFactory context) => $"{type.GetDisplayName()} is relevant to variant casting"; + protected override void OnMarked (NodeFactory context) + { + context.MarkStep.Annotations.MarkRelevantToVariantCasting (type); + } + } + } +} diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs index 02fd1412caf8..7a9acfb22677 100644 --- a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs @@ -37,7 +37,9 @@ using System.Linq; using System.Reflection.Metadata.Ecma335; using System.Reflection.Runtime.TypeParsing; +using System.Runtime.CompilerServices; using System.Text.RegularExpressions; +using ILCompiler.DependencyAnalysisFramework; using ILLink.Shared; using ILLink.Shared.TrimAnalysis; using ILLink.Shared.TypeSystemProxy; @@ -59,21 +61,22 @@ protected LinkContext Context { } } - protected Queue<(MethodDefinition, DependencyInfo, MessageOrigin)> _methods; - protected HashSet<(MethodDefinition, MarkScopeStack.Scope)> _virtual_methods; + private bool _completed; + protected Dictionary _interface_methods; protected Queue _assemblyLevelAttributes; - readonly List _ivt_attributes; - protected Queue<(AttributeProviderPair, DependencyInfo, MarkScopeStack.Scope)> _lateMarkedAttributes; - protected List<(TypeDefinition, MarkScopeStack.Scope)> _typesWithInterfaces; + protected Queue<(AttributeProviderPair, DependencyInfo, MessageOrigin)> _lateMarkedAttributes; + protected List<(TypeDefinition, MessageOrigin)> _typesWithInterfaces; protected HashSet _dynamicInterfaceCastableImplementationTypesDiscovered; protected List _dynamicInterfaceCastableImplementationTypes; - protected List<(MethodBody, MarkScopeStack.Scope)> _unreachableBodies; + protected List<(MethodBody, MessageOrigin)> _unreachableBodies; readonly List<(TypeDefinition Type, MethodBody Body, Instruction Instr)> _pending_isinst_instr; // Stores, for compiler-generated methods only, whether they require the reflection // method body scanner. readonly Dictionary _compilerGeneratedMethodRequiresScanner; + private readonly NodeFactory _nodeFactory; + private readonly DependencyAnalyzer, NodeFactory> _dependencyGraph; MarkStepContext? _markContext; MarkStepContext MarkContext { @@ -84,13 +87,6 @@ MarkStepContext MarkContext { } readonly HashSet _entireTypesMarked; DynamicallyAccessedMembersTypeHierarchy? _dynamicallyAccessedMembersTypeHierarchy; - MarkScopeStack? _scopeStack; - protected MarkScopeStack ScopeStack { - get { - Debug.Assert (_scopeStack != null); - return _scopeStack; - } - } internal DynamicallyAccessedMembersTypeHierarchy DynamicallyAccessedMembersTypeHierarchy { get { @@ -219,18 +215,19 @@ internal DynamicallyAccessedMembersTypeHierarchy DynamicallyAccessedMembersTypeH public MarkStep () { - _methods = new Queue<(MethodDefinition, DependencyInfo, MessageOrigin)> (); - _virtual_methods = new HashSet<(MethodDefinition, MarkScopeStack.Scope)> (); + _completed = false; + _interface_methods = new Dictionary (); _assemblyLevelAttributes = new Queue (); - _ivt_attributes = new List (); - _lateMarkedAttributes = new Queue<(AttributeProviderPair, DependencyInfo, MarkScopeStack.Scope)> (); - _typesWithInterfaces = new List<(TypeDefinition, MarkScopeStack.Scope)> (); + _lateMarkedAttributes = new Queue<(AttributeProviderPair, DependencyInfo, MessageOrigin)> (); + _typesWithInterfaces = new List<(TypeDefinition, MessageOrigin)> (); _dynamicInterfaceCastableImplementationTypesDiscovered = new HashSet (); _dynamicInterfaceCastableImplementationTypes = new List (); - _unreachableBodies = new List<(MethodBody, MarkScopeStack.Scope)> (); + _unreachableBodies = new List<(MethodBody, MessageOrigin)> (); _pending_isinst_instr = new List<(TypeDefinition, MethodBody, Instruction)> (); _entireTypesMarked = new HashSet (); _compilerGeneratedMethodRequiresScanner = new Dictionary (); + _nodeFactory = new NodeFactory (this); + _dependencyGraph = new DependencyAnalyzer, NodeFactory> (_nodeFactory, null); } public AnnotationStore Annotations => Context.Annotations; @@ -242,7 +239,6 @@ public virtual void Process (LinkContext context) { _context = context; _markContext = new MarkStepContext (); - _scopeStack = new MarkScopeStack (); _dynamicallyAccessedMembersTypeHierarchy = new DynamicallyAccessedMembersTypeHierarchy (_context, this); Initialize (); @@ -288,42 +284,6 @@ protected virtual void Complete () } } - bool ProcessInternalsVisibleAttributes () - { - bool marked_any = false; - foreach (var attr in _ivt_attributes) { - - var provider = attr.Provider; - Debug.Assert (attr.Provider is ModuleDefinition or AssemblyDefinition); - var assembly = (provider is ModuleDefinition module) ? module.Assembly : provider as AssemblyDefinition; - - using var assemblyScope = ScopeStack.PushLocalScope (new MessageOrigin (assembly)); - - if (!Annotations.IsMarked (attr.Attribute) && IsInternalsVisibleAttributeAssemblyMarked (attr.Attribute)) { - MarkCustomAttribute (attr.Attribute, new DependencyInfo (DependencyKind.AssemblyOrModuleAttribute, attr.Provider)); - marked_any = true; - } - } - - return marked_any; - - bool IsInternalsVisibleAttributeAssemblyMarked (CustomAttribute ca) - { - System.Reflection.AssemblyName an; - try { - an = new System.Reflection.AssemblyName ((string) ca.ConstructorArguments[0].Value); - } catch { - return false; - } - - var assembly = Context.GetLoadedAssembly (an.Name!); - if (assembly == null) - return false; - - return Annotations.IsMarked (assembly.MainModule); - } - } - static bool TypeIsDynamicInterfaceCastableImplementation (TypeDefinition type) { if (!type.IsInterface || !type.HasInterfaces || !type.HasCustomAttributes) @@ -353,7 +313,7 @@ protected bool IsFullyPreserved (TypeDefinition type) return false; } - internal void MarkEntireType (TypeDefinition type, in DependencyInfo reason) + internal void MarkEntireType (TypeDefinition type, in DependencyInfo reason, MessageOrigin origin) { #if DEBUG if (!_entireTypeReasons.Contains (reason.Kind)) @@ -362,30 +322,30 @@ internal void MarkEntireType (TypeDefinition type, in DependencyInfo reason) // Prevent cases where there's nothing on the stack (can happen when marking entire assemblies) // In which case we would generate warnings with no source (hard to debug) - using MarkScopeStack.LocalScope? _ = ScopeStack.CurrentScope.Origin.Provider == null ? ScopeStack.PushLocalScope (new MessageOrigin (type)) : null; + origin = origin.Provider is not null ? origin : new MessageOrigin (type); if (!_entireTypesMarked.Add (type)) return; if (type.HasNestedTypes) { foreach (TypeDefinition nested in type.NestedTypes) - MarkEntireType (nested, new DependencyInfo (DependencyKind.NestedType, type)); + MarkEntireType (nested, new DependencyInfo (DependencyKind.NestedType, type), origin); } - MarkTypeVisibleToReflection (type, type, reason, ScopeStack.CurrentScope.Origin); - MarkCustomAttributes (type, new DependencyInfo (DependencyKind.CustomAttribute, type)); - MarkTypeSpecialCustomAttributes (type); + MarkTypeVisibleToReflection (type, type, reason, origin); + MarkCustomAttributes (type, new DependencyInfo (DependencyKind.CustomAttribute, type), origin); + MarkTypeSpecialCustomAttributes (type, origin); if (type.HasInterfaces) { foreach (InterfaceImplementation iface in type.Interfaces) MarkInterfaceImplementation (iface, new MessageOrigin (type)); } - MarkGenericParameterProvider (type); + MarkGenericParameterProvider (type, origin); if (type.HasFields) { foreach (FieldDefinition field in type.Fields) { - MarkFieldVisibleToReflection (field, new DependencyInfo (DependencyKind.MemberOfType, type), ScopeStack.CurrentScope.Origin); + MarkFieldVisibleToReflection (field, new DependencyInfo (DependencyKind.MemberOfType, type), origin); } } @@ -393,33 +353,42 @@ internal void MarkEntireType (TypeDefinition type, in DependencyInfo reason) foreach (MethodDefinition method in type.Methods) { if (IsFullyPreservedAction (Annotations.GetAction (type.Module.Assembly))) Annotations.SetAction (method, MethodAction.ForceParse); - MarkMethodVisibleToReflection (method, new DependencyInfo (DependencyKind.MemberOfType, type), ScopeStack.CurrentScope.Origin); + MarkMethodVisibleToReflection (method, new DependencyInfo (DependencyKind.MemberOfType, type), origin); } } if (type.HasProperties) { foreach (var property in type.Properties) { - MarkPropertyVisibleToReflection (property, new DependencyInfo (DependencyKind.MemberOfType, type), ScopeStack.CurrentScope.Origin); + MarkPropertyVisibleToReflection (property, new DependencyInfo (DependencyKind.MemberOfType, type), origin); } } if (type.HasEvents) { foreach (var ev in type.Events) { - MarkEventVisibleToReflection (ev, new DependencyInfo (DependencyKind.MemberOfType, ScopeStack.CurrentScope.Origin), ScopeStack.CurrentScope.Origin); + MarkEventVisibleToReflection (ev, new DependencyInfo (DependencyKind.MemberOfType, origin), origin); } } } void Process () { - while (ProcessPrimaryQueue () || + _dependencyGraph.ComputeDependencyRoutine += (List> nodes) => { + foreach (DependencyNodeCore node in nodes) { + if (node is ProcessCallbackNode processNode) + processNode.Process (); + } + }; + _dependencyGraph.AddRoot (new ProcessCallbackNode (ProcessAllPendingItems), "start"); + _dependencyGraph.ComputeMarkedNodes (); + + ProcessPendingTypeChecks (); + + bool ProcessAllPendingItems () + => ProcessPrimaryQueue () || ProcessMarkedPending () || ProcessLazyAttributes () || ProcessLateMarkedAttributes () || - MarkFullyPreservedAssemblies () || - ProcessInternalsVisibleAttributes ()) ; - - ProcessPendingTypeChecks (); + MarkFullyPreservedAssemblies (); } static bool IsFullyPreservedAction (AssemblyAction action) => action == AssemblyAction.Copy || action == AssemblyAction.Save; @@ -449,9 +418,9 @@ bool MarkFullyPreservedAssemblies () } } - // Setup empty scope - there has to be some scope setup since we're doing marking below + // Setup empty origin - there has to be some origin setup since we're doing marking below // but there's no "origin" right now (command line is the origin really) - using var localScope = ScopeStack.PushLocalScope (new MessageOrigin ((ICustomAttributeProvider?) null)); + var emptyOrigin = new MessageOrigin (null as ICustomAttributeProvider); // Beware: this works on loaded assemblies, not marked assemblies, so it should not be tied to marking. // We could further optimize this to only iterate through assemblies if the last mark iteration loaded @@ -464,19 +433,19 @@ bool MarkFullyPreservedAssemblies () continue; if (!Annotations.IsProcessed (assembly)) markedNewAssembly = true; - MarkAssembly (assembly, new DependencyInfo (DependencyKind.AssemblyAction, null)); + MarkAssembly (assembly, new DependencyInfo (DependencyKind.AssemblyAction, null), emptyOrigin); } return markedNewAssembly; } bool ProcessPrimaryQueue () { - if (QueueIsEmpty ()) + if (_completed) return false; - while (!QueueIsEmpty ()) { - ProcessQueue (); - ProcessVirtualMethods (); + while (!_completed) { + _completed = true; + ProcessInterfaceMethods (); ProcessMarkedTypesWithInterfaces (); ProcessDynamicCastableImplementationInterfaces (); ProcessPendingBodies (); @@ -488,8 +457,6 @@ bool ProcessPrimaryQueue () bool ProcessMarkedPending () { - using var emptyScope = ScopeStack.PushLocalScope (new MessageOrigin (null as ICustomAttributeProvider)); - bool marked = false; foreach (var pending in Annotations.GetMarkedPending ()) { marked = true; @@ -498,21 +465,19 @@ bool ProcessMarkedPending () if (Annotations.IsProcessed (pending.Key)) continue; - using var localScope = ScopeStack.PushLocalScope (pending.Value); - switch (pending.Key) { case TypeDefinition type: - MarkType (type, DependencyInfo.AlreadyMarked); + MarkType (type, DependencyInfo.AlreadyMarked, pending.Value); break; case MethodDefinition method: - MarkMethod (method, DependencyInfo.AlreadyMarked, ScopeStack.CurrentScope.Origin); + MarkMethod (method, DependencyInfo.AlreadyMarked, pending.Value); // Methods will not actually be processed until we drain the method queue. break; case FieldDefinition field: - MarkField (field, DependencyInfo.AlreadyMarked, ScopeStack.CurrentScope.Origin); + MarkField (field, DependencyInfo.AlreadyMarked, pending.Value); break; case ModuleDefinition module: - MarkModule (module, DependencyInfo.AlreadyMarked); + MarkModule (module, DependencyInfo.AlreadyMarked, pending.Value); break; case ExportedType exportedType: Annotations.SetProcessed (exportedType); @@ -551,30 +516,10 @@ void ProcessPendingTypeChecks () } } - void ProcessQueue () + void ProcessInterfaceMethods () { - while (!QueueIsEmpty ()) { - (MethodDefinition method, DependencyInfo reason, MessageOrigin origin) = _methods.Dequeue (); - ProcessMethod (method, reason, origin); - } - } - - bool QueueIsEmpty () - { - return _methods.Count == 0; - } - - protected virtual void EnqueueMethod (MethodDefinition method, in DependencyInfo reason, in MessageOrigin origin) - { - _methods.Enqueue ((method, reason, origin)); - } - - void ProcessVirtualMethods () - { - foreach ((var method, var scope) in _virtual_methods) { - using (ScopeStack.PushLocalScope (scope)) { - ProcessVirtualMethod (method); - } + foreach ((var method, var origin) in _interface_methods) { + ProcessInterfaceMethod (method, origin); } } @@ -588,29 +533,24 @@ void ProcessMarkedTypesWithInterfaces () // We may mark an interface type later on. Which means we need to reprocess any time with one or more interface implementations that have not been marked // and if an interface type is found to be marked and implementation is not marked, then we need to mark that implementation - // copy the data to avoid modified while enumerating error potential, which can happen under certain conditions. - var typesWithInterfaces = _typesWithInterfaces.ToArray (); - - foreach ((var type, var scope) in typesWithInterfaces) { + for (int i = 0; i < _typesWithInterfaces.Count; i++) { + (var type, var origin) = _typesWithInterfaces[i]; // Exception, types that have not been flagged as instantiated yet. These types may not need their interfaces even if the // interface type is marked // UnusedInterfaces optimization is turned off mark all interface implementations bool unusedInterfacesOptimizationEnabled = Context.IsOptimizationEnabled (CodeOptimizations.UnusedInterfaces, type); - - using (ScopeStack.PushLocalScope (scope)) { - if (Annotations.IsInstantiated (type) || Annotations.IsRelevantToVariantCasting (type) || - !unusedInterfacesOptimizationEnabled) { - MarkInterfaceImplementations (type); - } - // Interfaces in PreservedScope should have their methods added to _virtual_methods so that they are properly processed - foreach (var method in type.Methods) { - var baseMethods = Annotations.GetBaseMethods (method); - if (baseMethods is null) - continue; - foreach (var ov in baseMethods) { - if (ov.Base.DeclaringType is not null && ov.Base.DeclaringType.IsInterface && IgnoreScope (ov.Base.DeclaringType.Scope)) { - _virtual_methods.Add ((ov.Base, ScopeStack.CurrentScope)); - } + if (Annotations.IsInstantiated (type) || Annotations.IsRelevantToVariantCasting (type) || + !unusedInterfacesOptimizationEnabled) { + MarkInterfaceImplementations (type); + } + // Interfaces in PreservedScope should have their methods added to _virtual_methods so that they are properly processed + foreach (var method in type.Methods) { + var baseMethods = Annotations.GetBaseMethods (method); + if (baseMethods is null) + continue; + foreach (var ov in baseMethods) { + if (ov.Base.DeclaringType is not null && ov.Base.DeclaringType.IsInterface && IgnoreScope (ov.Base.DeclaringType.Scope)) { + MarkMethodAsVirtual (ov.Base, origin); } } } @@ -683,36 +623,41 @@ void ProcessDynamicCastableImplementationInterfaces () void ProcessPendingBodies () { for (int i = 0; i < _unreachableBodies.Count; i++) { - (var body, var scope) = _unreachableBodies[i]; + (var body, var origin) = _unreachableBodies[i]; if (Annotations.IsInstantiated (body.Method.DeclaringType)) { - using (ScopeStack.PushLocalScope (scope)) - MarkMethodBody (body); + MarkMethodBody (body, origin); _unreachableBodies.RemoveAt (i--); } } } - void ProcessVirtualMethod (MethodDefinition method) + void MarkMethodAsVirtual (MethodDefinition method, MessageOrigin origin) { Annotations.EnqueueVirtualMethod (method); - if (method.DeclaringType.IsInterface) { - var defaultImplementations = Annotations.GetDefaultInterfaceImplementations (method); - if (defaultImplementations is not null) { - foreach (var dimInfo in defaultImplementations) { - ProcessDefaultImplementation (dimInfo); + _interface_methods.TryAdd (method, origin); + } + } - if (IsInterfaceImplementationMethodNeededByTypeDueToInterface (dimInfo)) - MarkMethod (dimInfo.Override, new DependencyInfo (DependencyKind.Override, dimInfo.Base), ScopeStack.CurrentScope.Origin); - } + void ProcessInterfaceMethod (MethodDefinition method, MessageOrigin origin) + { + Debug.Assert (method.DeclaringType.IsInterface); + var defaultImplementations = Annotations.GetDefaultInterfaceImplementations (method); + if (defaultImplementations is not null) { + foreach (var dimInfo in defaultImplementations) { + ProcessDefaultImplementation (dimInfo, origin); + + if (IsInterfaceImplementationMethodNeededByTypeDueToInterface (dimInfo)) + MarkMethod (dimInfo.Override, new DependencyInfo (DependencyKind.Override, dimInfo.Base), origin); } - var overridingMethods = Annotations.GetOverrides (method); - if (overridingMethods is not null) { - foreach (OverrideInformation ov in overridingMethods) { - if (IsInterfaceImplementationMethodNeededByTypeDueToInterface (ov)) - MarkMethod (ov.Override, new DependencyInfo (DependencyKind.Override, ov.Base), ScopeStack.CurrentScope.Origin); - } + } + List? overridingMethods = (List?) Annotations.GetOverrides (method); + if (overridingMethods is not null) { + for (int i = 0; i < overridingMethods.Count; i++) { + OverrideInformation ov = overridingMethods[i]; + if (IsInterfaceImplementationMethodNeededByTypeDueToInterface (ov)) + MarkMethod (ov.Override, new DependencyInfo (DependencyKind.Override, ov.Base), origin); } } } @@ -752,19 +697,19 @@ bool ShouldMarkOverrideForBase (OverrideInformation overrideInformation) /// Marks the Override of with the correct reason. Should be called when returns true. /// // TODO: Take into account a base method in preserved scope - void MarkOverrideForBaseMethod (OverrideInformation overrideInformation) + void MarkOverrideForBaseMethod (OverrideInformation overrideInformation, MessageOrigin origin) { Debug.Assert (ShouldMarkOverrideForBase (overrideInformation)); if (Context.IsOptimizationEnabled (CodeOptimizations.OverrideRemoval, overrideInformation.Override) && Annotations.IsInstantiated (overrideInformation.Override.DeclaringType)) { - MarkMethod (overrideInformation.Override, new DependencyInfo (DependencyKind.OverrideOnInstantiatedType, overrideInformation.Override.DeclaringType), ScopeStack.CurrentScope.Origin); + MarkMethod (overrideInformation.Override, new DependencyInfo (DependencyKind.OverrideOnInstantiatedType, overrideInformation.Override.DeclaringType), origin); } else { // If the optimization is disabled or it's an abstract type, we just mark it as a normal override. Debug.Assert (!Context.IsOptimizationEnabled (CodeOptimizations.OverrideRemoval, overrideInformation.Override) || overrideInformation.Base.IsAbstract); - MarkMethod (overrideInformation.Override, new DependencyInfo (DependencyKind.Override, overrideInformation.Base), ScopeStack.CurrentScope.Origin); + MarkMethod (overrideInformation.Override, new DependencyInfo (DependencyKind.Override, overrideInformation.Base), origin); } } - void MarkMethodIfNeededByBaseMethod (MethodDefinition method) + void MarkMethodIfNeededByBaseMethod (MethodDefinition method, MessageOrigin origin) { Debug.Assert (Annotations.IsMarked (method.DeclaringType)); @@ -775,7 +720,7 @@ void MarkMethodIfNeededByBaseMethod (MethodDefinition method) var markedBaseMethods = bases.Where (ov => Annotations.IsMarked (ov.Base) || IgnoreScope (ov.Base.DeclaringType.Scope)); foreach (var ov in markedBaseMethods) { if (ShouldMarkOverrideForBase (ov)) - MarkOverrideForBaseMethod (ov); + MarkOverrideForBaseMethod (ov, origin); } } @@ -818,43 +763,43 @@ bool RequiresInterfaceRecursively (TypeDefinition typeToExamine, TypeDefinition return false; } - void ProcessDefaultImplementation (OverrideInformation ov) + void ProcessDefaultImplementation (OverrideInformation ov, MessageOrigin origin) { Debug.Assert (ov.IsOverrideOfInterfaceMember); if ((!ov.Override.IsStatic && !Annotations.IsInstantiated (ov.InterfaceImplementor.Implementor)) || ov.Override.IsStatic && !Annotations.IsRelevantToVariantCasting (ov.InterfaceImplementor.Implementor)) return; - MarkInterfaceImplementation (ov.InterfaceImplementor.InterfaceImplementation); + MarkInterfaceImplementation (ov.InterfaceImplementor.InterfaceImplementation, origin); } - void MarkMarshalSpec (IMarshalInfoProvider spec, in DependencyInfo reason) + void MarkMarshalSpec (IMarshalInfoProvider spec, in DependencyInfo reason, MessageOrigin origin) { if (!spec.HasMarshalInfo) return; if (spec.MarshalInfo is CustomMarshalInfo marshaler) { - MarkType (marshaler.ManagedType, reason); + MarkType (marshaler.ManagedType, reason, origin); TypeDefinition? type = Context.Resolve (marshaler.ManagedType); if (type != null) { - MarkICustomMarshalerMethods (type, in reason); - MarkCustomMarshalerGetInstance (type, in reason); + MarkICustomMarshalerMethods (type, in reason, origin); + MarkCustomMarshalerGetInstance (type, in reason, origin); } } } - void MarkCustomAttributes (ICustomAttributeProvider provider, in DependencyInfo reason) + void MarkCustomAttributes (ICustomAttributeProvider provider, in DependencyInfo reason, MessageOrigin origin) { if (provider.HasCustomAttributes) { bool providerInLinkedAssembly = Annotations.GetAction (CustomAttributeSource.GetAssemblyFromCustomAttributeProvider (provider)) == AssemblyAction.Link; bool markOnUse = Context.KeepUsedAttributeTypesOnly && providerInLinkedAssembly; foreach (CustomAttribute ca in provider.CustomAttributes) { - if (ProcessLinkerSpecialAttribute (ca, provider, reason)) + if (ProcessLinkerSpecialAttribute (ca, provider, reason, origin)) continue; if (markOnUse) { - _lateMarkedAttributes.Enqueue ((new AttributeProviderPair (ca, provider), reason, ScopeStack.CurrentScope)); + _lateMarkedAttributes.Enqueue ((new AttributeProviderPair (ca, provider), reason, origin)); continue; } @@ -866,7 +811,7 @@ void MarkCustomAttributes (ICustomAttributeProvider provider, in DependencyInfo if (providerInLinkedAssembly && IsAttributeRemoved (ca, resolvedAttributeType)) continue; - MarkCustomAttribute (ca, reason); + MarkCustomAttribute (ca, reason, origin); } } @@ -874,9 +819,9 @@ void MarkCustomAttributes (ICustomAttributeProvider provider, in DependencyInfo return; IMemberDefinition providerMember = (IMemberDefinition) provider; ; - using (ScopeStack.PushLocalScope (new MessageOrigin (providerMember))) - foreach (var dynamicDependency in Annotations.GetLinkerAttributes (providerMember)) - MarkDynamicDependency (dynamicDependency, providerMember); + MessageOrigin providerOrigin = new MessageOrigin (providerMember); + foreach (var dynamicDependency in Annotations.GetLinkerAttributes (providerMember)) + MarkDynamicDependency (dynamicDependency, providerMember, providerOrigin); } bool IsAttributeRemoved (CustomAttribute ca, TypeDefinition attributeType) @@ -905,7 +850,7 @@ static bool HasMatchingArguments (CustomAttributeArgument[] removeAttrInstancesA } } - protected virtual bool ProcessLinkerSpecialAttribute (CustomAttribute ca, ICustomAttributeProvider provider, in DependencyInfo reason) + protected virtual bool ProcessLinkerSpecialAttribute (CustomAttribute ca, ICustomAttributeProvider provider, in DependencyInfo reason, MessageOrigin origin) { var isPreserveDependency = IsUserDependencyMarker (ca.AttributeType); var isDynamicDependency = ca.AttributeType.IsTypeOf (); @@ -914,26 +859,26 @@ protected virtual bool ProcessLinkerSpecialAttribute (CustomAttribute ca, ICusto return false; if (isPreserveDependency) - MarkUserDependency (member, ca); + MarkUserDependency (member, ca, origin); if (Context.CanApplyOptimization (CodeOptimizations.RemoveDynamicDependencyAttribute, member.DeclaringType.Module.Assembly)) { // Record the custom attribute so that it has a reason, without actually marking it. Tracer.AddDirectDependency (ca, reason, marked: false); } else { - MarkCustomAttribute (ca, reason); + MarkCustomAttribute (ca, reason, origin); } return true; } - void MarkDynamicDependency (DynamicDependency dynamicDependency, IMemberDefinition context) + void MarkDynamicDependency (DynamicDependency dynamicDependency, IMemberDefinition context, MessageOrigin origin) { Debug.Assert (context is MethodDefinition || context is FieldDefinition); AssemblyDefinition? assembly; if (dynamicDependency.AssemblyName != null) { assembly = Context.TryResolve (dynamicDependency.AssemblyName); if (assembly == null) { - Context.LogWarning (ScopeStack.CurrentScope.Origin, DiagnosticId.UnresolvedAssemblyInDynamicDependencyAttribute, dynamicDependency.AssemblyName); + Context.LogWarning (origin, DiagnosticId.UnresolvedAssemblyInDynamicDependencyAttribute, dynamicDependency.AssemblyName); return; } } else { @@ -945,15 +890,15 @@ void MarkDynamicDependency (DynamicDependency dynamicDependency, IMemberDefiniti if (dynamicDependency.TypeName is string typeName) { type = DocumentationSignatureParser.GetTypeByDocumentationSignature (assembly, typeName, Context); if (type == null) { - Context.LogWarning (ScopeStack.CurrentScope.Origin, DiagnosticId.UnresolvedTypeInDynamicDependencyAttribute, typeName); + Context.LogWarning (origin, DiagnosticId.UnresolvedTypeInDynamicDependencyAttribute, typeName); return; } - MarkingHelpers.MarkMatchingExportedType (type, assembly, new DependencyInfo (DependencyKind.DynamicDependency, type), ScopeStack.CurrentScope.Origin); + MarkingHelpers.MarkMatchingExportedType (type, assembly, new DependencyInfo (DependencyKind.DynamicDependency, type), origin); } else if (dynamicDependency.Type is TypeReference typeReference) { type = Context.TryResolve (typeReference); if (type == null) { - Context.LogWarning (ScopeStack.CurrentScope.Origin, DiagnosticId.UnresolvedTypeInDynamicDependencyAttribute, typeReference.GetDisplayName ()); + Context.LogWarning (origin, DiagnosticId.UnresolvedTypeInDynamicDependencyAttribute, typeReference.GetDisplayName ()); return; } } else { @@ -968,42 +913,42 @@ void MarkDynamicDependency (DynamicDependency dynamicDependency, IMemberDefiniti if (dynamicDependency.MemberSignature is string memberSignature) { members = DocumentationSignatureParser.GetMembersByDocumentationSignature (type, memberSignature, Context, acceptName: true); if (!members.Any ()) { - Context.LogWarning (ScopeStack.CurrentScope.Origin, DiagnosticId.NoMembersResolvedForMemberSignatureOrType, memberSignature, type.GetDisplayName ()); + Context.LogWarning (origin, DiagnosticId.NoMembersResolvedForMemberSignatureOrType, memberSignature, type.GetDisplayName ()); return; } } else { var memberTypes = dynamicDependency.MemberTypes; members = type.GetDynamicallyAccessedMembers (Context, memberTypes); if (!members.Any ()) { - Context.LogWarning (ScopeStack.CurrentScope.Origin, DiagnosticId.NoMembersResolvedForMemberSignatureOrType, memberTypes.ToString (), type.GetDisplayName ()); + Context.LogWarning (origin, DiagnosticId.NoMembersResolvedForMemberSignatureOrType, memberTypes.ToString (), type.GetDisplayName ()); return; } } - MarkMembersVisibleToReflection (members, new DependencyInfo (DependencyKind.DynamicDependency, context)); + MarkMembersVisibleToReflection (members, new DependencyInfo (DependencyKind.DynamicDependency, context), origin); } - void MarkMembersVisibleToReflection (IEnumerable members, in DependencyInfo reason) + void MarkMembersVisibleToReflection (IEnumerable members, in DependencyInfo reason, MessageOrigin origin) { foreach (var member in members) { switch (member) { case TypeDefinition type: - MarkTypeVisibleToReflection (type, type, reason, ScopeStack.CurrentScope.Origin); + MarkTypeVisibleToReflection (type, type, reason, origin); break; case MethodDefinition method: - MarkMethodVisibleToReflection (method, reason, ScopeStack.CurrentScope.Origin); + MarkMethodVisibleToReflection (method, reason, origin); break; case FieldDefinition field: - MarkFieldVisibleToReflection (field, reason, ScopeStack.CurrentScope.Origin); + MarkFieldVisibleToReflection (field, reason, origin); break; case PropertyDefinition property: - MarkPropertyVisibleToReflection (property, reason, ScopeStack.CurrentScope.Origin); + MarkPropertyVisibleToReflection (property, reason, origin); break; case EventDefinition @event: - MarkEventVisibleToReflection (@event, reason, ScopeStack.CurrentScope.Origin); + MarkEventVisibleToReflection (@event, reason, origin); break; case InterfaceImplementation interfaceType: - MarkInterfaceImplementation (interfaceType, null, reason); + MarkInterfaceImplementation (interfaceType, origin, reason); break; } } @@ -1014,7 +959,7 @@ protected virtual bool IsUserDependencyMarker (TypeReference type) return type.Name == "PreserveDependencyAttribute" && type.Namespace == "System.Runtime.CompilerServices"; } - protected virtual void MarkUserDependency (IMemberDefinition context, CustomAttribute ca) + protected virtual void MarkUserDependency (IMemberDefinition context, CustomAttribute ca, MessageOrigin origin) { Context.LogWarning (context, DiagnosticId.DeprecatedPreserveDependencyAttribute); @@ -1043,7 +988,7 @@ protected virtual void MarkUserDependency (IMemberDefinition context, CustomAttr return; } - MarkingHelpers.MarkMatchingExportedType (td, assemblyDef, new DependencyInfo (DependencyKind.PreservedDependency, ca), ScopeStack.CurrentScope.Origin); + MarkingHelpers.MarkMatchingExportedType (td, assemblyDef, new DependencyInfo (DependencyKind.PreservedDependency, ca), origin); } else { td = context.DeclaringType; } @@ -1064,22 +1009,22 @@ protected virtual void MarkUserDependency (IMemberDefinition context, CustomAttr } if (member == "*") { - MarkEntireType (td, new DependencyInfo (DependencyKind.PreservedDependency, ca)); + MarkEntireType (td, new DependencyInfo (DependencyKind.PreservedDependency, ca), origin); return; } if (member != null) { - if (MarkDependencyMethod (td, member, signature, new DependencyInfo (DependencyKind.PreservedDependency, ca))) + if (MarkDependencyMethod (td, member, signature, new DependencyInfo (DependencyKind.PreservedDependency, ca), origin)) return; - if (MarkNamedField (td, member, new DependencyInfo (DependencyKind.PreservedDependency, ca))) + if (MarkNamedField (td, member, new DependencyInfo (DependencyKind.PreservedDependency, ca), origin)) return; } Context.LogWarning (context, DiagnosticId.CouldNotResolveDependencyMember, member ?? "", td.GetDisplayName ()); } - bool MarkDependencyMethod (TypeDefinition type, string name, string[]? signature, in DependencyInfo reason) + bool MarkDependencyMethod (TypeDefinition type, string name, string[]? signature, in DependencyInfo reason, MessageOrigin origin) { bool marked = false; @@ -1098,7 +1043,7 @@ bool MarkDependencyMethod (TypeDefinition type, string name, string[]? signature continue; if (signature == null) { - MarkMethodVisibleToReflection (m, reason, ScopeStack.CurrentScope.Origin); + MarkMethodVisibleToReflection (m, reason, origin); marked = true; continue; } @@ -1117,7 +1062,7 @@ bool MarkDependencyMethod (TypeDefinition type, string name, string[]? signature if (!matched) continue; - MarkMethodVisibleToReflection (m, reason, ScopeStack.CurrentScope.Origin); + MarkMethodVisibleToReflection (m, reason, origin); marked = true; } @@ -1135,12 +1080,12 @@ void LazyMarkCustomAttributes (ICustomAttributeProvider provider) } } - protected virtual void MarkCustomAttribute (CustomAttribute ca, in DependencyInfo reason) + protected virtual void MarkCustomAttribute (CustomAttribute ca, in DependencyInfo reason, MessageOrigin origin) { Annotations.Mark (ca, reason); - MarkMethod (ca.Constructor, new DependencyInfo (DependencyKind.AttributeConstructor, ca), ScopeStack.CurrentScope.Origin); + MarkMethod (ca.Constructor, new DependencyInfo (DependencyKind.AttributeConstructor, ca), origin); - MarkCustomAttributeArguments (ca); + MarkCustomAttributeArguments (ca, origin); TypeReference constructor_type = ca.Constructor.DeclaringType; TypeDefinition? type = Context.Resolve (constructor_type); @@ -1149,8 +1094,8 @@ protected virtual void MarkCustomAttribute (CustomAttribute ca, in DependencyInf return; } - MarkCustomAttributeProperties (ca, type); - MarkCustomAttributeFields (ca, type); + MarkCustomAttributeProperties (ca, type, origin); + MarkCustomAttributeFields (ca, type, origin); } protected virtual bool ShouldMarkCustomAttribute (CustomAttribute ca, ICustomAttributeProvider provider) @@ -1170,6 +1115,9 @@ protected virtual bool ShouldMarkCustomAttribute (CustomAttribute ca, ICustomAtt case "System.Runtime.InteropServices.InterfaceTypeAttribute": case "System.Runtime.InteropServices.GuidAttribute": return true; + // May be implicitly used by the runtime + case "System.Runtime.CompilerServices.InternalsVisibleToAttribute": + return true; } TypeDefinition? type = Context.Resolve (attr_type); @@ -1223,7 +1171,7 @@ protected virtual bool ShouldMarkTopLevelCustomAttribute (AttributeProviderPair return true; } - protected void MarkSecurityDeclarations (ISecurityDeclarationProvider provider, in DependencyInfo reason) + protected void MarkSecurityDeclarations (ISecurityDeclarationProvider provider, in DependencyInfo reason, MessageOrigin origin) { // most security declarations are removed (if linked) but user code might still have some // and if the attributes references types then they need to be marked too @@ -1231,19 +1179,19 @@ protected void MarkSecurityDeclarations (ISecurityDeclarationProvider provider, return; foreach (var sd in provider.SecurityDeclarations) - MarkSecurityDeclaration (sd, reason); + MarkSecurityDeclaration (sd, reason, origin); } - protected virtual void MarkSecurityDeclaration (SecurityDeclaration sd, in DependencyInfo reason) + protected virtual void MarkSecurityDeclaration (SecurityDeclaration sd, in DependencyInfo reason, MessageOrigin origin) { if (!sd.HasSecurityAttributes) return; foreach (var sa in sd.SecurityAttributes) - MarkSecurityAttribute (sa, reason); + MarkSecurityAttribute (sa, reason, origin); } - protected virtual void MarkSecurityAttribute (SecurityAttribute sa, in DependencyInfo reason) + protected virtual void MarkSecurityAttribute (SecurityAttribute sa, in DependencyInfo reason, MessageOrigin origin) { TypeReference security_type = sa.AttributeType; TypeDefinition? type = Context.Resolve (security_type); @@ -1253,30 +1201,30 @@ protected virtual void MarkSecurityAttribute (SecurityAttribute sa, in Dependenc // Security attributes participate in inference logic without being marked. Tracer.AddDirectDependency (sa, reason, marked: false); - MarkType (security_type, new DependencyInfo (DependencyKind.AttributeType, sa)); - MarkCustomAttributeProperties (sa, type); - MarkCustomAttributeFields (sa, type); + MarkType (security_type, new DependencyInfo (DependencyKind.AttributeType, sa), origin); + MarkCustomAttributeProperties (sa, type, origin); + MarkCustomAttributeFields (sa, type, origin); } - protected void MarkCustomAttributeProperties (ICustomAttribute ca, TypeDefinition attribute) + protected void MarkCustomAttributeProperties (ICustomAttribute ca, TypeDefinition attribute, MessageOrigin origin) { if (!ca.HasProperties) return; foreach (var named_argument in ca.Properties) - MarkCustomAttributeProperty (named_argument, attribute, ca, new DependencyInfo (DependencyKind.AttributeProperty, ca)); + MarkCustomAttributeProperty (named_argument, attribute, ca, new DependencyInfo (DependencyKind.AttributeProperty, ca), origin); } - protected void MarkCustomAttributeProperty (CustomAttributeNamedArgument namedArgument, TypeDefinition attribute, ICustomAttribute ca, in DependencyInfo reason) + protected void MarkCustomAttributeProperty (CustomAttributeNamedArgument namedArgument, TypeDefinition attribute, ICustomAttribute ca, in DependencyInfo reason, MessageOrigin origin) { PropertyDefinition? property = GetProperty (attribute, namedArgument.Name); if (property != null) - MarkMethod (property.SetMethod, reason, ScopeStack.CurrentScope.Origin); + MarkMethod (property.SetMethod, reason, origin); - MarkCustomAttributeArgument (namedArgument.Argument, ca); + MarkCustomAttributeArgument (namedArgument.Argument, ca, origin); if (property != null && Annotations.FlowAnnotations.RequiresDataFlowAnalysis (property.SetMethod)) { - var scanner = new AttributeDataFlow (Context, this, ScopeStack.CurrentScope.Origin); + var scanner = new AttributeDataFlow (Context, this, origin); scanner.ProcessAttributeDataflow (property.SetMethod, new List { namedArgument.Argument }); } } @@ -1295,25 +1243,25 @@ protected void MarkCustomAttributeProperty (CustomAttributeNamedArgument namedAr return null; } - protected void MarkCustomAttributeFields (ICustomAttribute ca, TypeDefinition attribute) + protected void MarkCustomAttributeFields (ICustomAttribute ca, TypeDefinition attribute, MessageOrigin origin) { if (!ca.HasFields) return; foreach (var named_argument in ca.Fields) - MarkCustomAttributeField (named_argument, attribute, ca); + MarkCustomAttributeField (named_argument, attribute, ca, origin); } - protected void MarkCustomAttributeField (CustomAttributeNamedArgument namedArgument, TypeDefinition attribute, ICustomAttribute ca) + protected void MarkCustomAttributeField (CustomAttributeNamedArgument namedArgument, TypeDefinition attribute, ICustomAttribute ca, MessageOrigin origin) { FieldDefinition? field = GetField (attribute, namedArgument.Name); if (field != null) - MarkField (field, new DependencyInfo (DependencyKind.CustomAttributeField, ca), ScopeStack.CurrentScope.Origin); + MarkField (field, new DependencyInfo (DependencyKind.CustomAttributeField, ca), origin); - MarkCustomAttributeArgument (namedArgument.Argument, ca); + MarkCustomAttributeArgument (namedArgument.Argument, ca, origin); if (field != null && Annotations.FlowAnnotations.RequiresDataFlowAnalysis (field)) { - var scanner = new AttributeDataFlow (Context, this, ScopeStack.CurrentScope.Origin); + var scanner = new AttributeDataFlow (Context, this, origin); scanner.ProcessAttributeDataflow (field, namedArgument.Argument); } } @@ -1346,36 +1294,36 @@ protected void MarkCustomAttributeField (CustomAttributeNamedArgument namedArgum return null; } - void MarkCustomAttributeArguments (CustomAttribute ca) + void MarkCustomAttributeArguments (CustomAttribute ca, MessageOrigin origin) { if (!ca.HasConstructorArguments) return; foreach (var argument in ca.ConstructorArguments) - MarkCustomAttributeArgument (argument, ca); + MarkCustomAttributeArgument (argument, ca, origin); var resolvedConstructor = Context.TryResolve (ca.Constructor); if (resolvedConstructor != null && Annotations.FlowAnnotations.RequiresDataFlowAnalysis (resolvedConstructor)) { - var scanner = new AttributeDataFlow (Context, this, ScopeStack.CurrentScope.Origin); + var scanner = new AttributeDataFlow (Context, this, origin); scanner.ProcessAttributeDataflow (resolvedConstructor, ca.ConstructorArguments); } } - void MarkCustomAttributeArgument (CustomAttributeArgument argument, ICustomAttribute ca) + void MarkCustomAttributeArgument (CustomAttributeArgument argument, ICustomAttribute ca, MessageOrigin origin) { var at = argument.Type; if (at.IsArray) { var et = at.GetElementType (); - MarkType (et, new DependencyInfo (DependencyKind.CustomAttributeArgumentType, ca)); + MarkType (et, new DependencyInfo (DependencyKind.CustomAttributeArgumentType, ca), origin); if (argument.Value == null) return; // Array arguments are modeled as a CustomAttributeArgument [], and will mark the // Type once for each element in the array. foreach (var caa in (CustomAttributeArgument[]) argument.Value) - MarkCustomAttributeArgument (caa, ca); + MarkCustomAttributeArgument (caa, ca, origin); return; } @@ -1383,14 +1331,14 @@ void MarkCustomAttributeArgument (CustomAttributeArgument argument, ICustomAttri if (at.Namespace == "System") { switch (at.Name) { case "Type": - MarkType (argument.Type, new DependencyInfo (DependencyKind.CustomAttributeArgumentType, ca)); - MarkType ((TypeReference) argument.Value, new DependencyInfo (DependencyKind.CustomAttributeArgumentValue, ca)); + MarkType (argument.Type, new DependencyInfo (DependencyKind.CustomAttributeArgumentType, ca), origin); + MarkType ((TypeReference) argument.Value, new DependencyInfo (DependencyKind.CustomAttributeArgumentValue, ca), origin); return; case "Object": var boxed_value = (CustomAttributeArgument) argument.Value; - MarkType (boxed_value.Type, new DependencyInfo (DependencyKind.CustomAttributeArgumentType, ca)); - MarkCustomAttributeArgument (boxed_value, ca); + MarkType (boxed_value.Type, new DependencyInfo (DependencyKind.CustomAttributeArgumentType, ca), origin); + MarkCustomAttributeArgument (boxed_value, ca, origin); return; } } @@ -1401,13 +1349,13 @@ protected bool CheckProcessed (IMetadataTokenProvider provider) return !Annotations.SetProcessed (provider); } - protected virtual void MarkAssembly (AssemblyDefinition assembly, DependencyInfo reason) + protected virtual void MarkAssembly (AssemblyDefinition assembly, DependencyInfo reason, MessageOrigin origin) { - Annotations.Mark (assembly, reason, ScopeStack.CurrentScope.Origin); + Annotations.Mark (assembly, reason, origin); if (CheckProcessed (assembly)) return; - using var assemblyScope = ScopeStack.PushLocalScope (new MessageOrigin (assembly)); + var assemblyOrigin = new MessageOrigin (assembly); EmbeddedXmlInfo.ProcessDescriptors (assembly, Context); @@ -1425,34 +1373,34 @@ protected virtual void MarkAssembly (AssemblyDefinition assembly, DependencyInfo if (action != AssemblyAction.Copy || !Context.TryGetCustomData ("DisableMarkingOfCopyAssemblies", out string? disableMarkingOfCopyAssembliesValue) || disableMarkingOfCopyAssembliesValue != "true") { - MarkEntireAssembly (assembly); + MarkEntireAssembly (assembly, assemblyOrigin); } return; } else if (Annotations.IsRootAssembly (assembly)) { - MarkEntireAssembly (assembly); + MarkEntireAssembly (assembly, assemblyOrigin); } - ProcessModuleType (assembly); + ProcessModuleType (assembly, origin); LazyMarkCustomAttributes (assembly); - MarkSecurityDeclarations (assembly, new DependencyInfo (DependencyKind.AssemblyOrModuleAttribute, assembly)); + MarkSecurityDeclarations (assembly, new DependencyInfo (DependencyKind.AssemblyOrModuleAttribute, assembly), assemblyOrigin); foreach (ModuleDefinition module in assembly.Modules) LazyMarkCustomAttributes (module); } - void MarkEntireAssembly (AssemblyDefinition assembly) + void MarkEntireAssembly (AssemblyDefinition assembly, MessageOrigin origin) { Debug.Assert (Annotations.IsProcessed (assembly)); ModuleDefinition module = assembly.MainModule; - MarkCustomAttributes (assembly, new DependencyInfo (DependencyKind.AssemblyOrModuleAttribute, assembly)); - MarkCustomAttributes (module, new DependencyInfo (DependencyKind.AssemblyOrModuleAttribute, module)); + MarkCustomAttributes (assembly, new DependencyInfo (DependencyKind.AssemblyOrModuleAttribute, assembly), origin); + MarkCustomAttributes (module, new DependencyInfo (DependencyKind.AssemblyOrModuleAttribute, module), origin); foreach (TypeDefinition type in module.Types) - MarkEntireType (type, new DependencyInfo (DependencyKind.TypeInAssembly, assembly)); + MarkEntireType (type, new DependencyInfo (DependencyKind.TypeInAssembly, assembly), origin); // Mark scopes of type references and exported types. TypeReferenceMarker.MarkTypeReferences (assembly, MarkingHelpers); @@ -1509,12 +1457,12 @@ TypeReference CreateTypeReferenceForExportedTypeTarget (ExportedType exportedTyp } } - void ProcessModuleType (AssemblyDefinition assembly) + void ProcessModuleType (AssemblyDefinition assembly, MessageOrigin origin) { // The type may have an initializer, in which case we want to keep it. TypeDefinition? moduleType = assembly.MainModule.Types.FirstOrDefault (t => t.MetadataToken.RID == 1); if (moduleType != null && moduleType.HasMethods) - MarkType (moduleType, new DependencyInfo (DependencyKind.TypeInAssembly, assembly)); + MarkType (moduleType, new DependencyInfo (DependencyKind.TypeInAssembly, assembly), origin); } bool ProcessLazyAttributes () @@ -1537,7 +1485,7 @@ bool ProcessLazyAttributes () Debug.Assert (provider is ModuleDefinition or AssemblyDefinition); var assembly = (provider is ModuleDefinition module) ? module.Assembly : provider as AssemblyDefinition; - using var assemblyScope = ScopeStack.PushLocalScope (new MessageOrigin (assembly)); + MessageOrigin assemblyOrigin = new MessageOrigin (assembly); var resolved = Context.Resolve (customAttribute.Constructor); if (resolved == null) { @@ -1547,29 +1495,26 @@ bool ProcessLazyAttributes () if (IsAttributeRemoved (customAttribute, resolved.DeclaringType) && Annotations.GetAction (CustomAttributeSource.GetAssemblyFromCustomAttributeProvider (assemblyLevelAttribute.Provider)) == AssemblyAction.Link) continue; - if (customAttribute.AttributeType.IsTypeOf ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute") && !Annotations.IsMarked (customAttribute)) { - _ivt_attributes.Add (assemblyLevelAttribute); - continue; - } else if (!ShouldMarkTopLevelCustomAttribute (assemblyLevelAttribute, resolved)) { + if (!ShouldMarkTopLevelCustomAttribute (assemblyLevelAttribute, resolved)) { skippedItems.Add (assemblyLevelAttribute); continue; } markOccurred = true; - MarkCustomAttribute (customAttribute, new DependencyInfo (DependencyKind.AssemblyOrModuleAttribute, assemblyLevelAttribute.Provider)); + MarkCustomAttribute (customAttribute, new DependencyInfo (DependencyKind.AssemblyOrModuleAttribute, assemblyLevelAttribute.Provider), assemblyOrigin); string attributeFullName = customAttribute.Constructor.DeclaringType.FullName; switch (attributeFullName) { case "System.Diagnostics.DebuggerDisplayAttribute": { TypeDefinition? targetType = GetDebuggerAttributeTargetType (assemblyLevelAttribute.Attribute, (AssemblyDefinition) assemblyLevelAttribute.Provider); if (targetType != null) - MarkTypeWithDebuggerDisplayAttribute (targetType, customAttribute); + MarkTypeWithDebuggerDisplayAttribute (targetType, customAttribute, assemblyOrigin); break; } case "System.Diagnostics.DebuggerTypeProxyAttribute": { TypeDefinition? targetType = GetDebuggerAttributeTargetType (assemblyLevelAttribute.Attribute, (AssemblyDefinition) assemblyLevelAttribute.Provider); if (targetType != null) - MarkTypeWithDebuggerTypeProxyAttribute (targetType, customAttribute); + MarkTypeWithDebuggerTypeProxyAttribute (targetType, customAttribute, assemblyOrigin); break; } } @@ -1588,11 +1533,11 @@ bool ProcessLateMarkedAttributes () if (startingQueueCount == 0) return false; - var skippedItems = new List<(AttributeProviderPair, DependencyInfo, MarkScopeStack.Scope)> (); + var skippedItems = new List<(AttributeProviderPair, DependencyInfo, MessageOrigin)> (); var markOccurred = false; while (_lateMarkedAttributes.Count != 0) { - var (attributeProviderPair, reason, scope) = _lateMarkedAttributes.Dequeue (); + var (attributeProviderPair, reason, origin) = _lateMarkedAttributes.Dequeue (); var customAttribute = attributeProviderPair.Attribute; var provider = attributeProviderPair.Provider; @@ -1602,14 +1547,12 @@ bool ProcessLateMarkedAttributes () } if (!ShouldMarkCustomAttribute (customAttribute, provider)) { - skippedItems.Add ((attributeProviderPair, reason, scope)); + skippedItems.Add ((attributeProviderPair, reason, origin)); continue; } markOccurred = true; - using (ScopeStack.PushLocalScope (scope)) { - MarkCustomAttribute (customAttribute, reason); - } + MarkCustomAttribute (customAttribute, reason, origin); } // requeue the items we skipped in case we need to make another pass @@ -1625,7 +1568,7 @@ protected void MarkField (FieldReference reference, DependencyInfo reason, in Me Debug.Assert (reason.Kind == DependencyKind.FieldAccess || reason.Kind == DependencyKind.Ldtoken); // Blame the field reference (without actually marking) on the original reason. Tracer.AddDirectDependency (reference, reason, marked: false); - MarkType (reference.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, reference)); + MarkType (reference.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, reference), origin); // Blame the field definition that we will resolve on the field reference. reason = new DependencyInfo (DependencyKind.FieldOnGenericInstance, reference); @@ -1785,13 +1728,13 @@ void MarkField (FieldDefinition field, in DependencyInfo reason, in MessageOrigi if (CheckProcessed (field)) return; - // Use the original scope for marking the declaring type - it provides better warning message location - MarkType (field.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, field)); + // Use the original origin for marking the declaring type - it provides better warning message location + MarkType (field.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, field), origin); - using var fieldScope = ScopeStack.PushLocalScope (new MessageOrigin (field)); - MarkType (field.FieldType, new DependencyInfo (DependencyKind.FieldType, field)); - MarkCustomAttributes (field, new DependencyInfo (DependencyKind.CustomAttribute, field)); - MarkMarshalSpec (field, new DependencyInfo (DependencyKind.FieldMarshalSpec, field)); + var fieldOrigin = new MessageOrigin (field); + MarkType (field.FieldType, new DependencyInfo (DependencyKind.FieldType, field), fieldOrigin); + MarkCustomAttributes (field, new DependencyInfo (DependencyKind.CustomAttribute, field), fieldOrigin); + MarkMarshalSpec (field, new DependencyInfo (DependencyKind.FieldMarshalSpec, field), fieldOrigin); DoAdditionalFieldProcessing (field); // If we accessed a field on a type and the type has explicit/sequential layout, make sure to keep @@ -1807,7 +1750,7 @@ void MarkField (FieldDefinition field, in DependencyInfo reason, in MessageOrigi // layout of the base. TypeDefinition? typeWithFields = field.DeclaringType; while (typeWithFields != null) { - MarkImplicitlyUsedFields (typeWithFields); + MarkImplicitlyUsedFields (typeWithFields, fieldOrigin); typeWithFields = Context.TryResolve (typeWithFields.BaseType); } } @@ -1819,7 +1762,7 @@ void MarkField (FieldDefinition field, in DependencyInfo reason, in MessageOrigi DependencyKind.FieldAccess => new DependencyInfo (DependencyKind.TriggersCctorThroughFieldAccess, reason.Source), _ => new DependencyInfo (DependencyKind.CctorForField, field) }; - MarkStaticConstructor (parent, cctorReason, ScopeStack.CurrentScope.Origin); + MarkStaticConstructor (parent, cctorReason, fieldOrigin); } if (Annotations.HasSubstitutedInit (field)) { @@ -1848,11 +1791,6 @@ bool ShouldWarnForReflectionAccessToCompilerGeneratedCode (FieldDefinition field void ProcessAnalysisAnnotationsForField (FieldDefinition field, DependencyKind dependencyKind, in MessageOrigin origin) { - if (origin.Provider != ScopeStack.CurrentScope.Origin.Provider) { - Debug.Assert (dependencyKind == DependencyKind.DynamicallyAccessedMemberOnType || - (origin.Provider is MethodDefinition originMethod && CompilerGeneratedState.IsNestedFunctionOrStateMachineMember (originMethod))); - } - switch (dependencyKind) { // Marked through things like descriptor - don't want to warn as it's intentional choice case DependencyKind.AlreadyMarked: @@ -1908,19 +1846,19 @@ protected virtual bool IgnoreScope (IMetadataScope scope) return assembly != null && Annotations.GetAction (assembly) != AssemblyAction.Link; } - void MarkModule (ModuleDefinition module, DependencyInfo reason) + void MarkModule (ModuleDefinition module, DependencyInfo reason, MessageOrigin origin) { if (reason.Kind == DependencyKind.AlreadyMarked) { Debug.Assert (Annotations.IsMarked (module)); } else { - Annotations.Mark (module, reason, ScopeStack.CurrentScope.Origin); + Annotations.Mark (module, reason, origin); } if (CheckProcessed (module)) return; - MarkAssembly (module.Assembly, new DependencyInfo (DependencyKind.AssemblyOfModule, module)); + MarkAssembly (module.Assembly, new DependencyInfo (DependencyKind.AssemblyOfModule, module), origin); } - protected virtual void MarkSerializable (TypeDefinition type) + protected virtual void MarkSerializable (TypeDefinition type, MessageOrigin origin) { if (!type.HasMethods) return; @@ -1929,14 +1867,14 @@ protected virtual void MarkSerializable (TypeDefinition type) return; if (type.IsSerializable ()) { - MarkDefaultConstructor (type, new DependencyInfo (DependencyKind.SerializationMethodForType, type)); - MarkMethodsIf (type.Methods, IsSpecialSerializationConstructor, new DependencyInfo (DependencyKind.SerializationMethodForType, type), ScopeStack.CurrentScope.Origin); + MarkDefaultConstructor (type, new DependencyInfo (DependencyKind.SerializationMethodForType, type), origin); + MarkMethodsIf (type.Methods, IsSpecialSerializationConstructor, new DependencyInfo (DependencyKind.SerializationMethodForType, type), origin); } - MarkMethodsIf (type.Methods, HasOnSerializeOrDeserializeAttribute, new DependencyInfo (DependencyKind.SerializationMethodForType, type), ScopeStack.CurrentScope.Origin); + MarkMethodsIf (type.Methods, HasOnSerializeOrDeserializeAttribute, new DependencyInfo (DependencyKind.SerializationMethodForType, type), origin); } - protected internal virtual TypeDefinition? MarkTypeVisibleToReflection (TypeReference type, TypeDefinition definition, in DependencyInfo reason, in MessageOrigin origin) + protected internal virtual void MarkTypeVisibleToReflection (TypeReference type, TypeDefinition definition, in DependencyInfo reason, in MessageOrigin origin) { // If a type is visible to reflection, we need to stop doing optimization that could cause observable difference // in reflection APIs. This includes APIs like MakeGenericType (where variant castability of the produced type @@ -1945,9 +1883,9 @@ protected virtual void MarkSerializable (TypeDefinition type) Annotations.MarkReflectionUsed (definition); - MarkImplicitlyUsedFields (definition); + MarkImplicitlyUsedFields (definition, origin); - return MarkType (type, reason, origin); + MarkType (type, reason, origin); } internal void MarkMethodVisibleToReflection (MethodReference method, in DependencyInfo reason, in MessageOrigin origin) @@ -1977,7 +1915,7 @@ internal void MarkPropertyVisibleToReflection (PropertyDefinition property, in D internal void MarkEventVisibleToReflection (EventDefinition @event, in DependencyInfo reason, in MessageOrigin origin) { - MarkEvent (@event, reason); + MarkEvent (@event, reason, origin); // MarkEvent already marks the add/remove/invoke methods, but we need to mark them with the // DependencyInfo used to access the event from reflection, to produce warnings for annotated // event methods. @@ -1992,13 +1930,14 @@ internal void MarkStaticConstructorVisibleToReflection (TypeDefinition type, in MarkStaticConstructor (type, reason, origin); } + /// /// Marks the specified as referenced. /// /// The type reference to mark. /// The reason why the marking is occuring /// The resolved type definition if the reference can be resolved - protected internal virtual TypeDefinition? MarkType (TypeReference reference, DependencyInfo reason, MessageOrigin? origin = null) + protected internal virtual TypeDefinition? MarkType (TypeReference reference, DependencyInfo reason, MessageOrigin origin) { #if DEBUG if (!_typeReasons.Contains (reason.Kind)) @@ -2007,9 +1946,7 @@ internal void MarkStaticConstructorVisibleToReflection (TypeDefinition type, in if (reference == null) return null; - using MarkScopeStack.LocalScope? localScope = origin.HasValue ? ScopeStack.PushLocalScope (origin.Value) : null; - - (reference, reason) = GetOriginalType (reference, reason); + (reference, reason) = GetOriginalType (reference, reason, origin); if (reference is FunctionPointerType) return null; @@ -2028,13 +1965,13 @@ internal void MarkStaticConstructorVisibleToReflection (TypeDefinition type, in Debug.Assert (Annotations.IsMarked (type)); break; default: - Annotations.Mark (type, reason, ScopeStack.CurrentScope.Origin); + Annotations.Mark (type, reason, origin); break; } // Treat cctors triggered by a called method specially and mark this case up-front. if (type.HasMethods && ShouldMarkTypeStaticConstructor (type) && reason.Kind == DependencyKind.DeclaringTypeOfCalledMethod) - MarkStaticConstructor (type, new DependencyInfo (DependencyKind.TriggersCctorForCalledMethod, reason.Source), ScopeStack.CurrentScope.Origin); + MarkStaticConstructor (type, new DependencyInfo (DependencyKind.TriggersCctorForCalledMethod, reason.Source), origin); if (Annotations.HasLinkerAttribute (type)) { // Don't warn about references from the removed attribute itself (for example the .ctor on the attribute @@ -2044,21 +1981,27 @@ internal void MarkStaticConstructorVisibleToReflection (TypeDefinition type, in // Also don't warn when the type is marked due to an assembly being rooted. if (!(reason.Source is IMemberDefinition sourceMemberDefinition && sourceMemberDefinition.DeclaringType == type) && reason.Kind is not DependencyKind.TypeInAssembly) - Context.LogWarning (ScopeStack.CurrentScope.Origin, DiagnosticId.AttributeIsReferencedButTrimmerRemoveAllInstances, type.GetDisplayName ()); + Context.LogWarning (origin, DiagnosticId.AttributeIsReferencedButTrimmerRemoveAllInstances, type.GetDisplayName ()); } if (CheckProcessed (type)) return type; if (type.Scope is ModuleDefinition module) - MarkModule (module, new DependencyInfo (DependencyKind.ScopeOfType, type)); + MarkModule (module, new DependencyInfo (DependencyKind.ScopeOfType, type), origin); - using var typeScope = ScopeStack.PushLocalScope (new MessageOrigin (type)); + _dependencyGraph.AddRoot (_nodeFactory.GetTypeNode (type), Enum.GetName (reason.Kind)); + return type; + } + + protected internal virtual void ProcessType (TypeDefinition type) + { + var typeOrigin = new MessageOrigin (type); foreach (Action handleMarkType in MarkContext.MarkTypeActions) handleMarkType (type); - MarkType (type.BaseType, new DependencyInfo (DependencyKind.BaseType, type)); + MarkType (type.BaseType, new DependencyInfo (DependencyKind.BaseType, type), typeOrigin); // The DynamicallyAccessedMembers hierarchy processing must be done after the base type was marked // (to avoid inconsistencies in the cache), but before anything else as work done below @@ -2066,41 +2009,39 @@ internal void MarkStaticConstructorVisibleToReflection (TypeDefinition type, in DynamicallyAccessedMembersTypeHierarchy.ProcessMarkedTypeForDynamicallyAccessedMembersHierarchy (type); if (type.DeclaringType != null) - MarkType (type.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, type)); - MarkCustomAttributes (type, new DependencyInfo (DependencyKind.CustomAttribute, type)); - MarkSecurityDeclarations (type, new DependencyInfo (DependencyKind.CustomAttribute, type)); + MarkType (type.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, type), typeOrigin); + MarkCustomAttributes (type, new DependencyInfo (DependencyKind.CustomAttribute, type), typeOrigin); + MarkSecurityDeclarations (type, new DependencyInfo (DependencyKind.CustomAttribute, type), typeOrigin); if (Context.TryResolve (type.BaseType) is TypeDefinition baseType && !Annotations.HasLinkerAttribute (type) && Annotations.TryGetLinkerAttribute (baseType, out RequiresUnreferencedCodeAttribute? effectiveRequiresUnreferencedCode)) { - var currentOrigin = ScopeStack.CurrentScope.Origin; - string arg1 = MessageFormat.FormatRequiresAttributeMessageArg (effectiveRequiresUnreferencedCode.Message); string arg2 = MessageFormat.FormatRequiresAttributeUrlArg (effectiveRequiresUnreferencedCode.Url); - Context.LogWarning (currentOrigin, DiagnosticId.RequiresUnreferencedCodeOnBaseClass, type.GetDisplayName (), type.BaseType.GetDisplayName (), arg1, arg2); + Context.LogWarning (typeOrigin, DiagnosticId.RequiresUnreferencedCodeOnBaseClass, type.GetDisplayName (), type.BaseType.GetDisplayName (), arg1, arg2); } if (type.IsMulticastDelegate ()) { - MarkMulticastDelegate (type); + MarkMulticastDelegate (type, typeOrigin); } if (type.IsClass && type.BaseType == null && type.Name == "Object" && ShouldMarkSystemObjectFinalize) - MarkMethodIf (type.Methods, m => m.Name == "Finalize", new DependencyInfo (DependencyKind.MethodForSpecialType, type), ScopeStack.CurrentScope.Origin); + MarkMethodIf (type.Methods, static m => m.Name == "Finalize", new DependencyInfo (DependencyKind.MethodForSpecialType, type), typeOrigin); - MarkSerializable (type); + MarkSerializable (type, typeOrigin); // This marks static fields of KeyWords/OpCodes/Tasks subclasses of an EventSource type. // The special handling of EventSource is still needed in .NET6 in library mode if ((!Context.DisableEventSourceSpecialHandling || Context.GetTargetRuntimeVersion () < TargetRuntimeVersion.NET6) && BCL.EventTracingForWindows.IsEventSourceImplementation (type, Context)) { - MarkEventSourceProviders (type); + MarkEventSourceProviders (type, typeOrigin); } // This marks properties for [EventData] types as well as other attribute dependencies. - MarkTypeSpecialCustomAttributes (type); + MarkTypeSpecialCustomAttributes (type, typeOrigin); - MarkGenericParameterProvider (type); + MarkGenericParameterProvider (type, typeOrigin); // There are a number of markings we can defer until later when we know it's possible a reference type could be instantiated // For example, if no instance of a type exist, then we don't need to mark the interfaces on that type -- Note this is not true for static interfaces @@ -2129,29 +2070,28 @@ internal void MarkStaticConstructorVisibleToReflection (TypeDefinition type, in // Save for later once we know which interfaces are marked and then determine which interface implementations and methods to keep if (type.HasInterfaces) - _typesWithInterfaces.Add ((type, ScopeStack.CurrentScope)); + _typesWithInterfaces.Add ((type, typeOrigin)); if (type.HasMethods) { // TODO: MarkMethodIfNeededByBaseMethod should include logic for IsMethodNeededByTypeDueToPreservedScope: https://github.com/dotnet/linker/issues/3090 foreach (var method in type.Methods) { - MarkMethodIfNeededByBaseMethod (method); + MarkMethodIfNeededByBaseMethod (method, typeOrigin); if (IsMethodNeededByTypeDueToPreservedScope (method)) { // For methods that must be preserved, blame the declaring type. - MarkMethod (method, new DependencyInfo (DependencyKind.VirtualNeededDueToPreservedScope, type), ScopeStack.CurrentScope.Origin); + MarkMethod (method, new DependencyInfo (DependencyKind.VirtualNeededDueToPreservedScope, type), typeOrigin); } } - if (ShouldMarkTypeStaticConstructor (type) && reason.Kind != DependencyKind.TriggersCctorForCalledMethod) { - using (ScopeStack.PopToParentScope ()) - MarkStaticConstructor (type, new DependencyInfo (DependencyKind.CctorForType, type), ScopeStack.CurrentScope.Origin); + if (ShouldMarkTypeStaticConstructor (type)) { + MarkStaticConstructor (type, new DependencyInfo (DependencyKind.CctorForType, type), typeOrigin); } } DoAdditionalTypeProcessing (type); ApplyPreserveInfo (type); - ApplyPreserveMethods (type); + ApplyPreserveMethods (type, typeOrigin); - return type; + return; } /// @@ -2210,7 +2150,7 @@ protected virtual void DoAdditionalInstantiatedTypeProcessing (TypeDefinition ty return null; } - void MarkTypeSpecialCustomAttributes (TypeDefinition type) + void MarkTypeSpecialCustomAttributes (TypeDefinition type, MessageOrigin origin) { if (!type.HasCustomAttributes) return; @@ -2227,24 +2167,24 @@ void MarkTypeSpecialCustomAttributes (TypeDefinition type) switch (attrType.Name) { case "XmlSchemaProviderAttribute" when attrType.Namespace == "System.Xml.Serialization": - MarkXmlSchemaProvider (type, attribute); + MarkXmlSchemaProvider (type, attribute, origin); break; case "DebuggerDisplayAttribute" when attrType.Namespace == "System.Diagnostics": - MarkTypeWithDebuggerDisplayAttribute (type, attribute); + MarkTypeWithDebuggerDisplayAttribute (type, attribute, origin); break; case "DebuggerTypeProxyAttribute" when attrType.Namespace == "System.Diagnostics": - MarkTypeWithDebuggerTypeProxyAttribute (type, attribute); + MarkTypeWithDebuggerTypeProxyAttribute (type, attribute, origin); break; // The special handling of EventSource is still needed in .NET6 in library mode case "EventDataAttribute" when attrType.Namespace == "System.Diagnostics.Tracing" && (!Context.DisableEventSourceSpecialHandling || Context.GetTargetRuntimeVersion () < TargetRuntimeVersion.NET6): - if (MarkMethodsIf (type.Methods, MethodDefinitionExtensions.IsPublicInstancePropertyMethod, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, type), ScopeStack.CurrentScope.Origin)) + if (MarkMethodsIf (type.Methods, MethodDefinitionExtensions.IsPublicInstancePropertyMethod, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, type), origin)) Tracer.AddDirectDependency (attribute, new DependencyInfo (DependencyKind.CustomAttribute, type), marked: false); break; } } } - void MarkMethodSpecialCustomAttributes (MethodDefinition method) + void MarkMethodSpecialCustomAttributes (MethodDefinition method, MessageOrigin origin) { if (!method.HasCustomAttributes) return; @@ -2252,17 +2192,17 @@ void MarkMethodSpecialCustomAttributes (MethodDefinition method) foreach (CustomAttribute attribute in method.CustomAttributes) { switch (attribute.Constructor.DeclaringType.FullName) { case "System.Web.Services.Protocols.SoapHeaderAttribute": - MarkSoapHeader (method, attribute); + MarkSoapHeader (method, attribute, origin); break; } } } - void MarkXmlSchemaProvider (TypeDefinition type, CustomAttribute attribute) + void MarkXmlSchemaProvider (TypeDefinition type, CustomAttribute attribute, MessageOrigin origin) { if (TryGetStringArgument (attribute, out string? name)) { Tracer.AddDirectDependency (attribute, new DependencyInfo (DependencyKind.CustomAttribute, type), marked: false); - MarkNamedMethod (type, name, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); + MarkNamedMethod (type, name, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), origin); } } @@ -2272,25 +2212,25 @@ void MarkXmlSchemaProvider (TypeDefinition type, CustomAttribute attribute) [GeneratedRegex (@".+,\s*nq")] private static partial Regex ContainsNqSuffixRegex (); - void MarkTypeWithDebuggerDisplayAttribute (TypeDefinition type, CustomAttribute attribute) + void MarkTypeWithDebuggerDisplayAttribute (TypeDefinition type, CustomAttribute attribute, MessageOrigin origin) { if (Context.KeepMembersForDebugger) { // Members referenced by the DebuggerDisplayAttribute are kept even if the attribute may not be. // Record a logical dependency on the attribute so that we can blame it for the kept members below. Tracer.AddDirectDependency (attribute, new DependencyInfo (DependencyKind.CustomAttribute, type), marked: false); - MarkTypeWithDebuggerDisplayAttributeValue (type, attribute, (string) attribute.ConstructorArguments[0].Value); + MarkTypeWithDebuggerDisplayAttributeValue (type, attribute, (string) attribute.ConstructorArguments[0].Value, origin); if (attribute.HasProperties) { foreach (var property in attribute.Properties) { if (property.Name is "Name" or "Type") { - MarkTypeWithDebuggerDisplayAttributeValue (type, attribute, (string) property.Argument.Value); + MarkTypeWithDebuggerDisplayAttributeValue (type, attribute, (string) property.Argument.Value, origin); } } } } } - void MarkTypeWithDebuggerDisplayAttributeValue (TypeDefinition type, CustomAttribute attribute, string? displayString) + void MarkTypeWithDebuggerDisplayAttributeValue (TypeDefinition type, CustomAttribute attribute, string? displayString, MessageOrigin origin) { if (string.IsNullOrEmpty (displayString)) return; @@ -2317,23 +2257,23 @@ void MarkTypeWithDebuggerDisplayAttributeValue (TypeDefinition type, CustomAttri MethodDefinition? method = GetMethodWithNoParameters (type, methodName); if (method != null) { - MarkMethod (method, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), ScopeStack.CurrentScope.Origin); + MarkMethod (method, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), origin); continue; } } else { FieldDefinition? field = GetField (type, realMatch); if (field != null) { - MarkField (field, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), ScopeStack.CurrentScope.Origin); + MarkField (field, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), origin); continue; } PropertyDefinition? property = GetProperty (type, realMatch); if (property != null) { if (property.GetMethod != null) { - MarkMethod (property.GetMethod, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), ScopeStack.CurrentScope.Origin); + MarkMethod (property.GetMethod, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), origin); } if (property.SetMethod != null) { - MarkMethod (property.SetMethod, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), ScopeStack.CurrentScope.Origin); + MarkMethod (property.SetMethod, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), origin); } continue; } @@ -2342,8 +2282,8 @@ void MarkTypeWithDebuggerDisplayAttributeValue (TypeDefinition type, CustomAttri while (true) { // Currently if we don't understand the DebuggerDisplayAttribute we mark everything on the type // This can be improved: dotnet/linker/issues/1873 - MarkMethods (type, new DependencyInfo (DependencyKind.KeptForSpecialAttribute, attribute)); - MarkFields (type, includeStatic: true, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); + MarkMethods (type, new DependencyInfo (DependencyKind.KeptForSpecialAttribute, attribute), origin); + MarkFields (type, includeStatic: true, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), origin); if (Context.TryResolve (type.BaseType) is not TypeDefinition baseType) break; type = baseType; @@ -2352,7 +2292,7 @@ void MarkTypeWithDebuggerDisplayAttributeValue (TypeDefinition type, CustomAttri } } - void MarkTypeWithDebuggerTypeProxyAttribute (TypeDefinition type, CustomAttribute attribute) + void MarkTypeWithDebuggerTypeProxyAttribute (TypeDefinition type, CustomAttribute attribute, MessageOrigin origin) { if (Context.KeepMembersForDebugger) { object constructorArgument = attribute.ConstructorArguments[0].Value; @@ -2368,11 +2308,11 @@ void MarkTypeWithDebuggerTypeProxyAttribute (TypeDefinition type, CustomAttribut } Tracer.AddDirectDependency (attribute, new DependencyInfo (DependencyKind.CustomAttribute, type), marked: false); - MarkType (proxyTypeReference, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); + MarkType (proxyTypeReference, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), origin); if (Context.TryResolve (proxyTypeReference) is TypeDefinition proxyType) { - MarkMethods (proxyType, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); - MarkFields (proxyType, includeStatic: true, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); + MarkMethods (proxyType, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), origin); + MarkFields (proxyType, includeStatic: true, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), origin); } } } @@ -2389,7 +2329,7 @@ static bool TryGetStringArgument (CustomAttribute attribute, [NotNullWhen (true) return argument != null; } - protected int MarkNamedMethod (TypeDefinition type, string method_name, in DependencyInfo reason) + protected int MarkNamedMethod (TypeDefinition type, string method_name, in DependencyInfo reason, MessageOrigin origin) { if (!type.HasMethods) return 0; @@ -2399,23 +2339,23 @@ protected int MarkNamedMethod (TypeDefinition type, string method_name, in Depen if (method.Name != method_name) continue; - MarkMethod (method, reason, ScopeStack.CurrentScope.Origin); + MarkMethod (method, reason, origin); count++; } return count; } - void MarkSoapHeader (MethodDefinition method, CustomAttribute attribute) + void MarkSoapHeader (MethodDefinition method, CustomAttribute attribute, MessageOrigin origin) { if (!TryGetStringArgument (attribute, out string? member_name)) return; - MarkNamedField (method.DeclaringType, member_name, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); - MarkNamedProperty (method.DeclaringType, member_name, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); + MarkNamedField (method.DeclaringType, member_name, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), origin); + MarkNamedProperty (method.DeclaringType, member_name, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute), origin); } - bool MarkNamedField (TypeDefinition type, string field_name, in DependencyInfo reason) + bool MarkNamedField (TypeDefinition type, string field_name, in DependencyInfo reason, MessageOrigin origin) { if (!type.HasFields) return false; @@ -2424,14 +2364,14 @@ bool MarkNamedField (TypeDefinition type, string field_name, in DependencyInfo r if (field.Name != field_name) continue; - MarkField (field, reason, ScopeStack.CurrentScope.Origin); + MarkField (field, reason, origin); return true; } return false; } - void MarkNamedProperty (TypeDefinition type, string property_name, in DependencyInfo reason) + void MarkNamedProperty (TypeDefinition type, string property_name, in DependencyInfo reason, MessageOrigin origin) { if (!type.HasProperties) return; @@ -2440,11 +2380,9 @@ void MarkNamedProperty (TypeDefinition type, string property_name, in Dependency if (property.Name != property_name) continue; - using (ScopeStack.PushLocalScope (new MessageOrigin (property))) { - // This marks methods directly without reporting the property. - MarkMethod (property.GetMethod, reason, ScopeStack.CurrentScope.Origin); - MarkMethod (property.SetMethod, reason, ScopeStack.CurrentScope.Origin); - } + // This marks methods directly without reporting the property. + MarkMethod (property.GetMethod, reason, origin); + MarkMethod (property.SetMethod, reason, origin); } } @@ -2478,30 +2416,30 @@ protected virtual bool ShouldMarkInterfaceImplementationList (TypeDefinition typ // It's hard to know if a com or windows runtime interface will be needed from managed code alone, // so as a precaution we will mark these interfaces once the type is instantiated - if (resolvedInterfaceType.IsImport || resolvedInterfaceType.IsWindowsRuntime) + if (Context.KeepComInterfaces && (resolvedInterfaceType.IsImport || resolvedInterfaceType.IsWindowsRuntime)) return true; return IsFullyPreserved (type); } - void MarkGenericParameterProvider (IGenericParameterProvider provider) + void MarkGenericParameterProvider (IGenericParameterProvider provider, MessageOrigin origin) { if (!provider.HasGenericParameters) return; foreach (GenericParameter parameter in provider.GenericParameters) - MarkGenericParameter (parameter); + MarkGenericParameter (parameter, origin); } - void MarkGenericParameter (GenericParameter parameter) + void MarkGenericParameter (GenericParameter parameter, MessageOrigin origin) { - MarkCustomAttributes (parameter, new DependencyInfo (DependencyKind.GenericParameterCustomAttribute, parameter.Owner)); + MarkCustomAttributes (parameter, new DependencyInfo (DependencyKind.GenericParameterCustomAttribute, parameter.Owner), origin); if (!parameter.HasConstraints) return; foreach (var constraint in parameter.Constraints) { - MarkCustomAttributes (constraint, new DependencyInfo (DependencyKind.GenericParameterConstraintCustomAttribute, parameter.Owner)); - MarkType (constraint.ConstraintType, new DependencyInfo (DependencyKind.GenericParameterConstraintType, parameter.Owner)); + MarkCustomAttributes (constraint, new DependencyInfo (DependencyKind.GenericParameterConstraintCustomAttribute, parameter.Owner), origin); + MarkType (constraint.ConstraintType, new DependencyInfo (DependencyKind.GenericParameterConstraintType, parameter.Owner), origin); } } @@ -2624,15 +2562,15 @@ protected internal bool MarkMethodsIf (Collection methods, Fun return null; } - protected bool MarkDefaultConstructor (TypeDefinition type, in DependencyInfo reason) + protected bool MarkDefaultConstructor (TypeDefinition type, in DependencyInfo reason, MessageOrigin origin) { if (type?.HasMethods != true) return false; - return MarkMethodIf (type.Methods, MethodDefinitionExtensions.IsDefaultConstructor, reason, ScopeStack.CurrentScope.Origin) != null; + return MarkMethodIf (type.Methods, MethodDefinitionExtensions.IsDefaultConstructor, reason, origin) != null; } - void MarkCustomMarshalerGetInstance (TypeDefinition type, in DependencyInfo reason) + void MarkCustomMarshalerGetInstance (TypeDefinition type, in DependencyInfo reason, MessageOrigin origin) { if (!type.HasMethods) return; @@ -2644,10 +2582,10 @@ void MarkCustomMarshalerGetInstance (TypeDefinition type, in DependencyInfo reas && m.GetMetadataParametersCount () == 1 && m.GetParameter ((ParameterIndex) 0).ParameterType.MetadataType == MetadataType.String, reason, - ScopeStack.CurrentScope.Origin); + origin); } - void MarkICustomMarshalerMethods (TypeDefinition inputType, in DependencyInfo reason) + void MarkICustomMarshalerMethods (TypeDefinition inputType, in DependencyInfo reason, MessageOrigin origin) { TypeDefinition? type = inputType; do { @@ -2668,7 +2606,7 @@ void MarkICustomMarshalerMethods (TypeDefinition inputType, in DependencyInfo re return; } - MarkMethodsIf (tdef.Methods, m => !m.IsStatic, reason, ScopeStack.CurrentScope.Origin); + MarkMethodsIf (tdef.Methods, m => !m.IsStatic, reason, origin); MarkInterfaceImplementation (iface, new MessageOrigin (type)); return; @@ -2727,34 +2665,34 @@ protected virtual bool AlwaysMarkTypeAsInstantiated (TypeDefinition td) return false; } - void MarkEventSourceProviders (TypeDefinition td) + void MarkEventSourceProviders (TypeDefinition td, MessageOrigin origin) { Debug.Assert (Context.GetTargetRuntimeVersion () < TargetRuntimeVersion.NET6 || !Context.DisableEventSourceSpecialHandling); foreach (var nestedType in td.NestedTypes) { if (BCL.EventTracingForWindows.IsProviderName (nestedType.Name)) - MarkStaticFields (nestedType, new DependencyInfo (DependencyKind.EventSourceProviderField, td)); + MarkStaticFields (nestedType, new DependencyInfo (DependencyKind.EventSourceProviderField, td), origin); } } - protected virtual void MarkMulticastDelegate (TypeDefinition type) + protected virtual void MarkMulticastDelegate (TypeDefinition type, MessageOrigin origin) { - MarkMethodsIf (type.Methods, m => m.Name == ".ctor" || m.Name == "Invoke", new DependencyInfo (DependencyKind.MethodForSpecialType, type), ScopeStack.CurrentScope.Origin); + MarkMethodsIf (type.Methods, m => m.Name == ".ctor" || m.Name == "Invoke", new DependencyInfo (DependencyKind.MethodForSpecialType, type), origin); } - protected (TypeReference, DependencyInfo) GetOriginalType (TypeReference type, DependencyInfo reason) + protected (TypeReference, DependencyInfo) GetOriginalType (TypeReference type, DependencyInfo reason, MessageOrigin origin) { while (type is TypeSpecification specification) { if (type is GenericInstanceType git) { - MarkGenericArguments (git); + MarkGenericArguments (git, origin); Debug.Assert (!(specification.ElementType is TypeSpecification)); } if (type is IModifierType mod) - MarkModifierType (mod); + MarkModifierType (mod, origin); if (type is FunctionPointerType fnptr) { - MarkParameters (fnptr); - MarkType (fnptr.ReturnType, new DependencyInfo (DependencyKind.ReturnType, fnptr)); + MarkParameters (fnptr, origin); + MarkType (fnptr.ReturnType, new DependencyInfo (DependencyKind.ReturnType, fnptr), origin); break; // FunctionPointerType is the original type } @@ -2767,22 +2705,22 @@ protected virtual void MarkMulticastDelegate (TypeDefinition type) return (type, reason); } - void MarkParameters (FunctionPointerType fnptr) + void MarkParameters (FunctionPointerType fnptr, MessageOrigin origin) { if (!fnptr.HasParameters) return; for (int i = 0; i < fnptr.Parameters.Count; i++) { - MarkType (fnptr.Parameters[i].ParameterType, new DependencyInfo (DependencyKind.ParameterType, fnptr)); + MarkType (fnptr.Parameters[i].ParameterType, new DependencyInfo (DependencyKind.ParameterType, fnptr), origin); } } - void MarkModifierType (IModifierType mod) + void MarkModifierType (IModifierType mod, MessageOrigin origin) { - MarkType (mod.ModifierType, new DependencyInfo (DependencyKind.ModifierType, mod)); + MarkType (mod.ModifierType, new DependencyInfo (DependencyKind.ModifierType, mod), origin); } - void MarkGenericArguments (IGenericInstance instance) + void MarkGenericArguments (IGenericInstance instance, MessageOrigin origin) { var arguments = instance.GenericArguments; @@ -2799,24 +2737,24 @@ void MarkGenericArguments (IGenericInstance instance) var argument = arguments[i]; var parameter = parameters[i]; - TypeDefinition? argumentTypeDef = MarkType (argument, new DependencyInfo (DependencyKind.GenericArgumentType, instance)); + var argumentTypeDef = MarkType (argument, new DependencyInfo (DependencyKind.GenericArgumentType, instance), origin); if (Annotations.FlowAnnotations.RequiresGenericArgumentDataFlowAnalysis (parameter)) { // The only two implementations of IGenericInstance both derive from MemberReference Debug.Assert (instance is MemberReference); - using MarkScopeStack.LocalScope? _ = ScopeStack.CurrentScope.Origin.Provider == null ? ScopeStack.PushLocalScope (new MessageOrigin (((MemberReference) instance).Resolve ())) : null; - var scanner = new GenericArgumentDataFlow (Context, this, ScopeStack.CurrentScope.Origin); + var instanceMemberOrigin = origin.Provider is not null ? origin : new MessageOrigin (((MemberReference) instance).Resolve ()); + var scanner = new GenericArgumentDataFlow (Context, this, instanceMemberOrigin); scanner.ProcessGenericArgumentDataFlow (parameter, argument); } if (argumentTypeDef == null) continue; - Annotations.MarkRelevantToVariantCasting (argumentTypeDef); + _dependencyGraph.AddRoot (_nodeFactory.GetTypeIsRelevantToVariantCastingNode (argumentTypeDef), "Generic Argument"); if (parameter.HasDefaultConstructorConstraint) - MarkDefaultConstructor (argumentTypeDef, new DependencyInfo (DependencyKind.DefaultCtorForNewConstrainedGenericArgument, instance)); + MarkDefaultConstructor (argumentTypeDef, new DependencyInfo (DependencyKind.DefaultCtorForNewConstrainedGenericArgument, instance), origin); } } @@ -2833,7 +2771,7 @@ void MarkGenericArguments (IGenericInstance instance) void ApplyPreserveInfo (TypeDefinition type) { - using var typeScope = ScopeStack.PushLocalScope (new MessageOrigin (type)); + var typeOrigin = new MessageOrigin (type); if (Annotations.TryGetPreserve (type, out TypePreserve preserve)) { if (!Annotations.SetAppliedPreserve (type, preserve)) @@ -2843,16 +2781,16 @@ void ApplyPreserveInfo (TypeDefinition type) switch (preserve) { case TypePreserve.All: - MarkFields (type, true, di); - MarkMethods (type, di); + MarkFields (type, true, di, typeOrigin); + MarkMethods (type, di, typeOrigin); return; case TypePreserve.Fields: - if (!MarkFields (type, true, di, true)) + if (!MarkFields (type, true, di, typeOrigin, true)) Context.LogWarning (type, DiagnosticId.TypeHasNoFieldsToPreserve, type.GetDisplayName ()); break; case TypePreserve.Methods: - if (!MarkMethods (type, di)) + if (!MarkMethods (type, di, typeOrigin)) Context.LogWarning (type, DiagnosticId.TypeHasNoMethodsToPreserve, type.GetDisplayName ()); break; } @@ -2864,18 +2802,18 @@ void ApplyPreserveInfo (TypeDefinition type) if (type.HasMethods) { foreach (var m in type.Methods) { if ((members & TypePreserveMembers.Visible) != 0 && IsMethodVisible (m)) { - MarkMethod (m, di, ScopeStack.CurrentScope.Origin); + MarkMethod (m, di, typeOrigin); continue; } if ((members & TypePreserveMembers.Internal) != 0 && IsMethodInternal (m)) { - MarkMethod (m, di, ScopeStack.CurrentScope.Origin); + MarkMethod (m, di, typeOrigin); continue; } if ((members & TypePreserveMembers.Library) != 0) { if (IsSpecialSerializationConstructor (m) || HasOnSerializeOrDeserializeAttribute (m)) { - MarkMethod (m, di, ScopeStack.CurrentScope.Origin); + MarkMethod (m, di, typeOrigin); continue; } } @@ -2885,12 +2823,12 @@ void ApplyPreserveInfo (TypeDefinition type) if (type.HasFields) { foreach (var f in type.Fields) { if ((members & TypePreserveMembers.Visible) != 0 && IsFieldVisible (f)) { - MarkField (f, di, ScopeStack.CurrentScope.Origin); + MarkField (f, di, typeOrigin); continue; } if ((members & TypePreserveMembers.Internal) != 0 && IsFieldInternal (f)) { - MarkField (f, di, ScopeStack.CurrentScope.Origin); + MarkField (f, di, typeOrigin); continue; } } @@ -2918,27 +2856,27 @@ static bool IsFieldInternal (FieldDefinition field) return field.IsAssembly || field.IsFamilyAndAssembly; } - void ApplyPreserveMethods (TypeDefinition type) + void ApplyPreserveMethods (TypeDefinition type, MessageOrigin origin) { var list = Annotations.GetPreservedMethods (type); if (list == null) return; Annotations.ClearPreservedMethods (type); - MarkMethodCollection (list, new DependencyInfo (DependencyKind.PreservedMethod, type)); + MarkMethodCollection (list, new DependencyInfo (DependencyKind.PreservedMethod, type), origin); } - void ApplyPreserveMethods (MethodDefinition method) + void ApplyPreserveMethods (MethodDefinition method, MessageOrigin origin) { var list = Annotations.GetPreservedMethods (method); if (list == null) return; Annotations.ClearPreservedMethods (method); - MarkMethodCollection (list, new DependencyInfo (DependencyKind.PreservedMethod, method)); + MarkMethodCollection (list, new DependencyInfo (DependencyKind.PreservedMethod, method), origin); } - protected bool MarkFields (TypeDefinition type, bool includeStatic, in DependencyInfo reason, bool markBackingFieldsOnlyIfPropertyMarked = false) + protected bool MarkFields (TypeDefinition type, bool includeStatic, in DependencyInfo reason, MessageOrigin origin, bool markBackingFieldsOnlyIfPropertyMarked = false) { if (!type.HasFields) return false; @@ -2959,7 +2897,7 @@ protected bool MarkFields (TypeDefinition type, bool includeStatic, in Dependenc if (propertyDefinition != null && !Annotations.IsMarked (propertyDefinition)) continue; } - MarkField (field, reason, ScopeStack.CurrentScope.Origin); + MarkField (field, reason, origin); } return true; @@ -2981,39 +2919,39 @@ protected bool MarkFields (TypeDefinition type, bool includeStatic, in Dependenc return null; } - protected void MarkStaticFields (TypeDefinition type, in DependencyInfo reason) + protected void MarkStaticFields (TypeDefinition type, in DependencyInfo reason, MessageOrigin origin) { if (!type.HasFields) return; foreach (FieldDefinition field in type.Fields) { if (field.IsStatic) - MarkField (field, reason, ScopeStack.CurrentScope.Origin); + MarkField (field, reason, origin); } } - protected virtual bool MarkMethods (TypeDefinition type, in DependencyInfo reason) + protected virtual bool MarkMethods (TypeDefinition type, in DependencyInfo reason, MessageOrigin origin) { if (!type.HasMethods) return false; - MarkMethodCollection (type.Methods, reason); + MarkMethodCollection (type.Methods, reason, origin); return true; } - void MarkMethodCollection (IList methods, in DependencyInfo reason) + void MarkMethodCollection (IList methods, in DependencyInfo reason, MessageOrigin origin) { foreach (MethodDefinition method in methods) - MarkMethod (method, reason, ScopeStack.CurrentScope.Origin); + MarkMethod (method, reason, origin); } protected virtual MethodDefinition? MarkMethod (MethodReference reference, DependencyInfo reason, in MessageOrigin origin) { DependencyKind originalReasonKind = reason.Kind; - (reference, reason) = GetOriginalMethod (reference, reason); + (reference, reason) = GetOriginalMethod (reference, reason, origin); if (reference.DeclaringType is ArrayType arrayType) { - MarkType (reference.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, reference)); + MarkType (reference.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, reference), origin); if (reference.Name == ".ctor" && Context.TryResolve (arrayType) is TypeDefinition typeDefinition) { Annotations.MarkRelevantToVariantCasting (typeDefinition); @@ -3024,7 +2962,7 @@ void MarkMethodCollection (IList methods, in DependencyInfo re if (reference.DeclaringType is GenericInstanceType) { // Blame the method reference on the original reason without marking it. Tracer.AddDirectDependency (reference, reason, marked: false); - MarkType (reference.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, reference)); + MarkType (reference.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, reference), origin); // Mark the resolved method definition as a dependency of the reference. reason = new DependencyInfo (DependencyKind.MethodOnGenericInstance, reference); } @@ -3066,7 +3004,8 @@ void MarkMethodCollection (IList methods, in DependencyInfo re // We will only enqueue a method to be processed if it hasn't been processed yet. if (!CheckProcessed (method)) - EnqueueMethod (method, reason, origin); + _completed = false; + _dependencyGraph.AddRoot (_nodeFactory.GetMethodDefinitionNode (method, reason), Enum.GetName (reason.Kind)); return method; } @@ -3089,16 +3028,6 @@ bool ShouldWarnForReflectionAccessToCompilerGeneratedCode (MethodDefinition meth void ProcessAnalysisAnnotationsForMethod (MethodDefinition method, DependencyKind dependencyKind, in MessageOrigin origin) { - // There are only two ways to get there such that the origin isn't the same as the top of the scopestack. - // - For DAM on type, the current scope is the caller of GetType, while the origin is the type itself. - // - For warnings produced inside compiler-generated code, the current scope is the user code that - // owns the compiler-generated code, while the origin is the compiler-generated code. - // In either case any warnings produced here should use the origin instead of the scopestack. - if (origin.Provider != ScopeStack.CurrentScope.Origin.Provider) { - Debug.Assert (dependencyKind == DependencyKind.DynamicallyAccessedMemberOnType || - (origin.Provider is MethodDefinition originMethod && CompilerGeneratedState.IsNestedFunctionOrStateMachineMember (originMethod))); - } - switch (dependencyKind) { // DirectCall, VirtualCall and NewObj are handled by ReflectionMethodBodyScanner // This is necessary since the ReflectionMethodBodyScanner has intrinsic handling for some @@ -3181,14 +3110,14 @@ internal static void ReportRequiresUnreferencedCode (string displayName, Require diagnosticContext.AddDiagnostic (DiagnosticId.RequiresUnreferencedCode, displayName, arg1, arg2); } - protected (MethodReference, DependencyInfo) GetOriginalMethod (MethodReference method, DependencyInfo reason) + protected (MethodReference, DependencyInfo) GetOriginalMethod (MethodReference method, DependencyInfo reason, MessageOrigin origin) { while (method is MethodSpecification specification) { // Blame the method reference (which isn't marked) on the original reason. Tracer.AddDirectDependency (specification, reason, marked: false); // Blame the outgoing element method on the specification. if (method is GenericInstanceMethod gim) - MarkGenericArguments (gim); + MarkGenericArguments (gim, origin); (method, reason) = (specification.ElementMethod, new DependencyInfo (DependencyKind.ElementMethod, specification)); Debug.Assert (!(method is MethodSpecification)); @@ -3197,15 +3126,13 @@ internal static void ReportRequiresUnreferencedCode (string displayName, Require return (method, reason); } - protected virtual void ProcessMethod (MethodDefinition method, in DependencyInfo reason, in MessageOrigin origin) + protected virtual void ProcessMethod (MethodDefinition method, in DependencyInfo reason) { #if DEBUG if (!_methodReasons.Contains (reason.Kind)) throw new InternalErrorException ($"Unsupported method dependency {reason.Kind}"); #endif - ScopeStack.AssertIsEmpty (); - using var parentScope = ScopeStack.PushLocalScope (new MarkScopeStack.Scope (origin)); - using var methodScope = ScopeStack.PushLocalScope (new MessageOrigin (method)); + var methodOrigin = new MessageOrigin (method); bool markedForCall = reason.Kind == DependencyKind.DirectCall || @@ -3216,17 +3143,17 @@ protected virtual void ProcessMethod (MethodDefinition method, in DependencyInfo handleMarkMethod (method); if (!markedForCall) - MarkType (method.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, method)); - MarkCustomAttributes (method, new DependencyInfo (DependencyKind.CustomAttribute, method)); - MarkSecurityDeclarations (method, new DependencyInfo (DependencyKind.CustomAttribute, method)); + MarkType (method.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, method), methodOrigin); + MarkCustomAttributes (method, new DependencyInfo (DependencyKind.CustomAttribute, method), methodOrigin); + MarkSecurityDeclarations (method, new DependencyInfo (DependencyKind.CustomAttribute, method), methodOrigin); - MarkGenericParameterProvider (method); + MarkGenericParameterProvider (method, methodOrigin); if (method.IsInstanceConstructor ()) { MarkRequirementsForInstantiatedTypes (method.DeclaringType); Tracer.AddDirectDependency (method.DeclaringType, new DependencyInfo (DependencyKind.InstantiatedByCtor, method), marked: false); } else if (method.IsStaticConstructor () && Annotations.HasLinkerAttribute (method)) - Context.LogWarning (ScopeStack.CurrentScope.Origin, DiagnosticId.RequiresUnreferencedCodeOnStaticConstructor, method.GetDisplayName ()); + Context.LogWarning (methodOrigin, DiagnosticId.RequiresUnreferencedCodeOnStaticConstructor, method.GetDisplayName ()); if (method.IsConstructor) { if (!Annotations.ProcessSatelliteAssemblies && KnownMembers.IsSatelliteAssemblyMarker (method)) @@ -3234,15 +3161,15 @@ protected virtual void ProcessMethod (MethodDefinition method, in DependencyInfo } else if (method.TryGetProperty (out PropertyDefinition? property)) MarkProperty (property, new DependencyInfo (PropagateDependencyKindToAccessors (reason.Kind, DependencyKind.PropertyOfPropertyMethod), method)); else if (method.TryGetEvent (out EventDefinition? @event)) { - MarkEvent (@event, new DependencyInfo (PropagateDependencyKindToAccessors (reason.Kind, DependencyKind.EventOfEventMethod), method)); + MarkEvent (@event, new DependencyInfo (PropagateDependencyKindToAccessors (reason.Kind, DependencyKind.EventOfEventMethod), method), methodOrigin); } if (method.HasMetadataParameters ()) { #pragma warning disable RS0030 // MethodReference.Parameters is banned. It's easiest to leave the code as is for now foreach (ParameterDefinition pd in method.Parameters) { - MarkType (pd.ParameterType, new DependencyInfo (DependencyKind.ParameterType, method)); - MarkCustomAttributes (pd, new DependencyInfo (DependencyKind.ParameterAttribute, method)); - MarkMarshalSpec (pd, new DependencyInfo (DependencyKind.ParameterMarshalSpec, method)); + MarkType (pd.ParameterType, new DependencyInfo (DependencyKind.ParameterType, method), methodOrigin); + MarkCustomAttributes (pd, new DependencyInfo (DependencyKind.ParameterAttribute, method), methodOrigin); + MarkMarshalSpec (pd, new DependencyInfo (DependencyKind.ParameterMarshalSpec, method), methodOrigin); } #pragma warning restore RS0030 } @@ -3259,33 +3186,33 @@ protected virtual void ProcessMethod (MethodDefinition method, in DependencyInfo Context.Resolve (@base) is MethodDefinition baseDefinition && baseDefinition.DeclaringType.IsInterface && baseDefinition.IsStatic && method.IsStatic) continue; - MarkMethod (@base, new DependencyInfo (DependencyKind.MethodImplOverride, method), ScopeStack.CurrentScope.Origin); + MarkMethod (@base, new DependencyInfo (DependencyKind.MethodImplOverride, method), methodOrigin); MarkExplicitInterfaceImplementation (method, @base); } } - MarkMethodSpecialCustomAttributes (method); + MarkMethodSpecialCustomAttributes (method, methodOrigin); if (method.IsVirtual) - _virtual_methods.Add ((method, ScopeStack.CurrentScope)); + MarkMethodAsVirtual (method, methodOrigin); - MarkNewCodeDependencies (method); + MarkNewCodeDependencies (method, methodOrigin); - MarkBaseMethods (method); + MarkBaseMethods (method, methodOrigin); if (Annotations.GetOverrides (method) is IEnumerable overrides) { foreach (var @override in overrides.Where (ov => Annotations.IsMarked (ov.Base) || IgnoreScope (ov.Base.DeclaringType.Scope))) { if (ShouldMarkOverrideForBase (@override)) - MarkOverrideForBaseMethod (@override); + MarkOverrideForBaseMethod (@override, methodOrigin); } } - MarkType (method.ReturnType, new DependencyInfo (DependencyKind.ReturnType, method)); - MarkCustomAttributes (method.MethodReturnType, new DependencyInfo (DependencyKind.ReturnTypeAttribute, method)); - MarkMarshalSpec (method.MethodReturnType, new DependencyInfo (DependencyKind.ReturnTypeMarshalSpec, method)); + MarkType (method.ReturnType, new DependencyInfo (DependencyKind.ReturnType, method), methodOrigin); + MarkCustomAttributes (method.MethodReturnType, new DependencyInfo (DependencyKind.ReturnTypeAttribute, method), methodOrigin); + MarkMarshalSpec (method.MethodReturnType, new DependencyInfo (DependencyKind.ReturnTypeMarshalSpec, method), methodOrigin); if (method.IsPInvokeImpl || method.IsInternalCall) { - ProcessInteropMethod (method); + ProcessInteropMethod (method, methodOrigin); } if (!method.HasBody || method.Body.CodeSize == 0) { @@ -3293,7 +3220,7 @@ protected virtual void ProcessMethod (MethodDefinition method, in DependencyInfo } if (ShouldParseMethodBody (method)) - MarkMethodBody (method.Body); + MarkMethodBody (method.Body, methodOrigin); if (method.DeclaringType.IsMulticastDelegate ()) { string? methodPair = null; @@ -3304,13 +3231,13 @@ protected virtual void ProcessMethod (MethodDefinition method, in DependencyInfo if (methodPair != null) { TypeDefinition declaringType = method.DeclaringType; - MarkMethodIf (declaringType.Methods, m => m.Name == methodPair, new DependencyInfo (DependencyKind.MethodForSpecialType, declaringType), ScopeStack.CurrentScope.Origin); + MarkMethodIf (declaringType.Methods, m => m.Name == methodPair, new DependencyInfo (DependencyKind.MethodForSpecialType, declaringType), methodOrigin); } } DoAdditionalMethodProcessing (method); - ApplyPreserveMethods (method); + ApplyPreserveMethods (method, methodOrigin); } // Allow subclassers to mark additional things when marking a method @@ -3333,14 +3260,14 @@ static DependencyKind PropagateDependencyKindToAccessors (DependencyKind parentD } } - void MarkImplicitlyUsedFields (TypeDefinition type) + void MarkImplicitlyUsedFields (TypeDefinition type, MessageOrigin origin) { if (type?.HasFields != true) return; // keep fields for types with explicit layout, for enums and for InlineArray types if (!type.IsAutoLayout || type.IsEnum || TypeIsInlineArrayType (type)) - MarkFields (type, includeStatic: type.IsEnum, reason: new DependencyInfo (DependencyKind.MemberOfType, type)); + MarkFields (type, includeStatic: type.IsEnum, reason: new DependencyInfo (DependencyKind.MemberOfType, type), origin); } static bool TypeIsInlineArrayType (TypeDefinition type) @@ -3362,16 +3289,16 @@ protected virtual void MarkRequirementsForInstantiatedTypes (TypeDefinition type Annotations.MarkInstantiated (type); - using var typeScope = ScopeStack.PushLocalScope (new MessageOrigin (type)); + var typeOrigin = new MessageOrigin (type); MarkInterfaceImplementations (type); // Requires interface implementations to be marked first foreach (var method in type.Methods) { - MarkMethodIfNeededByBaseMethod (method); + MarkMethodIfNeededByBaseMethod (method, typeOrigin); } - MarkImplicitlyUsedFields (type); + MarkImplicitlyUsedFields (type, typeOrigin); DoAdditionalInstantiatedTypeProcessing (type); } @@ -3396,7 +3323,7 @@ void MarkExplicitInterfaceImplementation (MethodDefinition method, MethodReferen } } - void MarkNewCodeDependencies (MethodDefinition method) + void MarkNewCodeDependencies (MethodDefinition method, MessageOrigin origin) { switch (Annotations.GetAction (method)) { case MethodAction.ConvertToStub: @@ -3406,18 +3333,18 @@ void MarkNewCodeDependencies (MethodDefinition method) var baseType = Context.Resolve (method.DeclaringType.BaseType); if (baseType == null) break; - if (!MarkDefaultConstructor (baseType, new DependencyInfo (DependencyKind.BaseDefaultCtorForStubbedMethod, method))) - throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage (ScopeStack.CurrentScope.Origin, DiagnosticId.CannotStubConstructorWhenBaseTypeDoesNotHaveConstructor, method.DeclaringType.GetDisplayName ())); + if (!MarkDefaultConstructor (baseType, new DependencyInfo (DependencyKind.BaseDefaultCtorForStubbedMethod, method), origin)) + throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage (origin, DiagnosticId.CannotStubConstructorWhenBaseTypeDoesNotHaveConstructor, method.DeclaringType.GetDisplayName ())); break; case MethodAction.ConvertToThrow: - MarkAndCacheConvertToThrowExceptionCtor (new DependencyInfo (DependencyKind.UnreachableBodyRequirement, method)); + MarkAndCacheConvertToThrowExceptionCtor (new DependencyInfo (DependencyKind.UnreachableBodyRequirement, method), origin); break; } } - protected virtual void MarkAndCacheConvertToThrowExceptionCtor (DependencyInfo reason) + protected virtual void MarkAndCacheConvertToThrowExceptionCtor (DependencyInfo reason, MessageOrigin origin) { if (Context.MarkedKnownMembers.NotSupportedExceptionCtorString != null) return; @@ -3426,9 +3353,9 @@ protected virtual void MarkAndCacheConvertToThrowExceptionCtor (DependencyInfo r if (nse == null) throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage (null, DiagnosticId.CouldNotFindType, "System.NotSupportedException")); - MarkType (nse, reason); + MarkType (nse, reason, origin); - var nseCtor = MarkMethodIf (nse.Methods, KnownMembers.IsNotSupportedExceptionCtorString, reason, ScopeStack.CurrentScope.Origin); + var nseCtor = MarkMethodIf (nse.Methods, KnownMembers.IsNotSupportedExceptionCtorString, reason, origin); Context.MarkedKnownMembers.NotSupportedExceptionCtorString = nseCtor ?? throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage (null, DiagnosticId.CouldNotFindConstructor, nse.GetDisplayName ())); @@ -3436,9 +3363,9 @@ protected virtual void MarkAndCacheConvertToThrowExceptionCtor (DependencyInfo r if (objectType == null) throw new NotSupportedException ("Missing predefined 'System.Object' type"); - MarkType (objectType, reason); + MarkType (objectType, reason, origin); - var objectCtor = MarkMethodIf (objectType.Methods, MethodDefinitionExtensions.IsDefaultConstructor, reason, ScopeStack.CurrentScope.Origin); + var objectCtor = MarkMethodIf (objectType.Methods, MethodDefinitionExtensions.IsDefaultConstructor, reason, origin); Context.MarkedKnownMembers.ObjectCtor = objectCtor ?? throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage (null, DiagnosticId.CouldNotFindConstructor, objectType.GetDisplayName ())); } @@ -3452,39 +3379,38 @@ bool MarkDisablePrivateReflectionAttribute () if (disablePrivateReflection == null) throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage (null, DiagnosticId.CouldNotFindType, "System.Runtime.CompilerServices.DisablePrivateReflectionAttribute")); - using (ScopeStack.PushLocalScope (new MessageOrigin (null as ICustomAttributeProvider))) { - MarkType (disablePrivateReflection, DependencyInfo.DisablePrivateReflectionRequirement); + var emptyOrigin = new MessageOrigin (null as ICustomAttributeProvider); + MarkType (disablePrivateReflection, DependencyInfo.DisablePrivateReflectionRequirement, emptyOrigin); - var ctor = MarkMethodIf (disablePrivateReflection.Methods, MethodDefinitionExtensions.IsDefaultConstructor, new DependencyInfo (DependencyKind.DisablePrivateReflectionRequirement, disablePrivateReflection), ScopeStack.CurrentScope.Origin); - Context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor = ctor ?? - throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage (null, DiagnosticId.CouldNotFindConstructor, disablePrivateReflection.GetDisplayName ())); - } + var ctor = MarkMethodIf (disablePrivateReflection.Methods, MethodDefinitionExtensions.IsDefaultConstructor, new DependencyInfo (DependencyKind.DisablePrivateReflectionRequirement, disablePrivateReflection), emptyOrigin); + Context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor = ctor ?? + throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage (null, DiagnosticId.CouldNotFindConstructor, disablePrivateReflection.GetDisplayName ())); return true; } - void MarkBaseMethods (MethodDefinition method) + void MarkBaseMethods (MethodDefinition method, MessageOrigin origin) { var base_methods = Annotations.GetBaseMethods (method); if (base_methods == null) return; foreach (OverrideInformation ov in base_methods) { - // We should add all interface base methods to _virtual_methods for virtual override annotation validation + // We should add all interface base methods to _interface_methods for virtual override annotation validation // Interfaces from preserved scope will be missed if we don't add them here // This will produce warnings for all interface methods and virtual methods regardless of whether the interface, interface implementation, or interface method is kept or not. if (ov.Base.DeclaringType.IsInterface && !method.DeclaringType.IsInterface) { // These are all virtual, no need to check IsVirtual before adding to list - _virtual_methods.Add ((ov.Base, ScopeStack.CurrentScope)); + MarkMethodAsVirtual (ov.Base, origin); continue; } - MarkMethod (ov.Base, new DependencyInfo (DependencyKind.BaseMethod, method), ScopeStack.CurrentScope.Origin); - MarkBaseMethods (ov.Base); + MarkMethod (ov.Base, new DependencyInfo (DependencyKind.BaseMethod, method), origin); + MarkBaseMethods (ov.Base, origin); } } - void ProcessInteropMethod (MethodDefinition method) + void ProcessInteropMethod (MethodDefinition method, MessageOrigin origin) { if (method.IsPInvokeImpl && method.PInvokeInfo != null) { var pii = method.PInvokeInfo; @@ -3505,14 +3431,14 @@ void ProcessInteropMethod (MethodDefinition method) if (returnTypeDefinition != null) { if (!returnTypeDefinition.IsImport) { // What we keep here is correct most of the time, but not every time. Fine for now. - MarkDefaultConstructor (returnTypeDefinition, new DependencyInfo (DependencyKind.InteropMethodDependency, method)); - MarkFields (returnTypeDefinition, includeStaticFields, new DependencyInfo (DependencyKind.InteropMethodDependency, method)); + MarkDefaultConstructor (returnTypeDefinition, new DependencyInfo (DependencyKind.InteropMethodDependency, method), origin); + MarkFields (returnTypeDefinition, includeStaticFields, new DependencyInfo (DependencyKind.InteropMethodDependency, method), origin); } } if (method.HasThis && !method.DeclaringType.IsImport) { // This is probably Mono-specific. One can't have InternalCall or P/invoke instance methods in CoreCLR or .NET. - MarkFields (method.DeclaringType, includeStaticFields, new DependencyInfo (DependencyKind.InteropMethodDependency, method)); + MarkFields (method.DeclaringType, includeStaticFields, new DependencyInfo (DependencyKind.InteropMethodDependency, method), origin); } #pragma warning disable RS0030 // MethodReference.Parameters is banned. It's easiest to leave this code as is for now @@ -3525,9 +3451,9 @@ void ProcessInteropMethod (MethodDefinition method) if (paramTypeDefinition != null) { if (!paramTypeDefinition.IsImport) { // What we keep here is correct most of the time, but not every time. Fine for now. - MarkFields (paramTypeDefinition, includeStaticFields, new DependencyInfo (DependencyKind.InteropMethodDependency, method)); + MarkFields (paramTypeDefinition, includeStaticFields, new DependencyInfo (DependencyKind.InteropMethodDependency, method), origin); if (pd.ParameterType.IsByReference) { - MarkDefaultConstructor (paramTypeDefinition, new DependencyInfo (DependencyKind.InteropMethodDependency, method)); + MarkDefaultConstructor (paramTypeDefinition, new DependencyInfo (DependencyKind.InteropMethodDependency, method), origin); } } } @@ -3572,27 +3498,24 @@ protected internal void MarkProperty (PropertyDefinition prop, in DependencyInfo if (!Annotations.MarkProcessed (prop, reason)) return; - using var propertyScope = ScopeStack.PushLocalScope (new MessageOrigin (prop)); - - // Consider making this more similar to MarkEvent method? - MarkCustomAttributes (prop, new DependencyInfo (DependencyKind.CustomAttribute, prop)); - DoAdditionalPropertyProcessing (prop); + PropertyDefinitionNode propertyNode = _nodeFactory.GetPropertyNode (prop); + _dependencyGraph.AddRoot (propertyNode, reason.Kind.ToString ()); } - protected internal virtual void MarkEvent (EventDefinition evt, in DependencyInfo reason) + protected internal virtual void MarkEvent (EventDefinition evt, in DependencyInfo reason, MessageOrigin origin) { if (!Annotations.MarkProcessed (evt, reason)) return; - var origin = reason.Source is IMemberDefinition member ? new MessageOrigin (member) : ScopeStack.CurrentScope.Origin; + origin = reason.Source is IMemberDefinition member ? new MessageOrigin (member) : origin; DependencyKind dependencyKind = PropagateDependencyKindToAccessors (reason.Kind, DependencyKind.EventMethod); MarkMethodIfNotNull (evt.AddMethod, new DependencyInfo (dependencyKind, evt), origin); MarkMethodIfNotNull (evt.InvokeMethod, new DependencyInfo (dependencyKind, evt), origin); MarkMethodIfNotNull (evt.RemoveMethod, new DependencyInfo (dependencyKind, evt), origin); - using var eventScope = ScopeStack.PushLocalScope (new MessageOrigin (evt)); + var eventOrigin = new MessageOrigin (evt); - MarkCustomAttributes (evt, new DependencyInfo (DependencyKind.CustomAttribute, evt)); + MarkCustomAttributes (evt, new DependencyInfo (DependencyKind.CustomAttribute, evt), eventOrigin); DoAdditionalEventProcessing (evt); } @@ -3604,13 +3527,13 @@ internal void MarkMethodIfNotNull (MethodReference method, in DependencyInfo rea MarkMethod (method, reason, origin); } - protected virtual void MarkMethodBody (MethodBody body) + protected virtual void MarkMethodBody (MethodBody body, MessageOrigin origin) { var processedMethodBody = Context.GetMethodIL (body); if (Context.IsOptimizationEnabled (CodeOptimizations.UnreachableBodies, body.Method) && IsUnreachableBody (processedMethodBody)) { - MarkAndCacheConvertToThrowExceptionCtor (new DependencyInfo (DependencyKind.UnreachableBodyRequirement, body.Method)); - _unreachableBodies.Add ((body, ScopeStack.CurrentScope)); + MarkAndCacheConvertToThrowExceptionCtor (new DependencyInfo (DependencyKind.UnreachableBodyRequirement, body.Method), origin); + _unreachableBodies.Add ((body, origin)); return; } @@ -3619,14 +3542,14 @@ protected virtual void MarkMethodBody (MethodBody body) // But for compiler-generated methods we only do dataflow analysis if they're used through their // corresponding user method, so we will skip dataflow for compiler-generated methods which // are only accessed via reflection. - bool requiresReflectionMethodBodyScanner = MarkAndCheckRequiresReflectionMethodBodyScanner (processedMethodBody); + bool requiresReflectionMethodBodyScanner = MarkAndCheckRequiresReflectionMethodBodyScanner (processedMethodBody, origin); // Data-flow (reflection scanning) for compiler-generated methods will happen as part of the // data-flow scan of the user-defined method which uses this compiler-generated method. if (CompilerGeneratedState.IsNestedFunctionOrStateMachineMember (body.Method)) return; - MarkReflectionLikeDependencies (processedMethodBody, requiresReflectionMethodBodyScanner); + MarkReflectionLikeDependencies (processedMethodBody, requiresReflectionMethodBodyScanner, origin); } bool CheckRequiresReflectionMethodBodyScanner (MethodIL methodIL) @@ -3656,7 +3579,7 @@ bool CheckRequiresReflectionMethodBodyScanner (MethodIL methodIL) // It computes the same value, while also marking as it goes, as an optimization. // This should only be called behind a check to IsProcessed for the method or corresponding user method, // to avoid recursion. - bool MarkAndCheckRequiresReflectionMethodBodyScanner (MethodIL methodIL) + bool MarkAndCheckRequiresReflectionMethodBodyScanner (MethodIL methodIL, MessageOrigin origin) { #if DEBUG if (!Annotations.IsProcessed (methodIL.Method)) { @@ -3675,17 +3598,17 @@ bool MarkAndCheckRequiresReflectionMethodBodyScanner (MethodIL methodIL) return requiresReflectionMethodBodyScanner; foreach (VariableDefinition var in methodIL.Variables) - MarkType (var.VariableType, new DependencyInfo (DependencyKind.VariableType, methodIL.Method)); + MarkType (var.VariableType, new DependencyInfo (DependencyKind.VariableType, methodIL.Method), origin); foreach (ExceptionHandler eh in methodIL.ExceptionHandlers) if (eh.HandlerType == ExceptionHandlerType.Catch) - MarkType (eh.CatchType, new DependencyInfo (DependencyKind.CatchType, methodIL.Method)); + MarkType (eh.CatchType, new DependencyInfo (DependencyKind.CatchType, methodIL.Method), origin); requiresReflectionMethodBodyScanner = ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForMethodBody (Context, methodIL.Method); - using var _ = ScopeStack.PushLocalScope (new MessageOrigin (methodIL.Method)); + MessageOrigin ilOrigin = new MessageOrigin (methodIL.Method); foreach (Instruction instruction in methodIL.Instructions) - MarkInstruction (instruction, methodIL.Method, ref requiresReflectionMethodBodyScanner); + MarkInstruction (instruction, methodIL.Method, ref requiresReflectionMethodBodyScanner, ref ilOrigin); MarkInterfacesNeededByBodyStack (methodIL); @@ -3737,14 +3660,14 @@ Code.Ldfld or Code.Ldsfld when ((FieldReference) instruction.Operand).FieldType. _ => false }; - protected virtual void MarkInstruction (Instruction instruction, MethodDefinition method, ref bool requiresReflectionMethodBodyScanner) + protected virtual void MarkInstruction (Instruction instruction, MethodDefinition method, ref bool requiresReflectionMethodBodyScanner, ref MessageOrigin origin) { switch (instruction.OpCode.OperandType) { case OperandType.InlineField: requiresReflectionMethodBodyScanner |= InstructionRequiresReflectionMethodBodyScannerForFieldAccess (instruction); - ScopeStack.UpdateCurrentScopeInstructionOffset (instruction.Offset); - MarkField ((FieldReference) instruction.Operand, new DependencyInfo (DependencyKind.FieldAccess, method), ScopeStack.CurrentScope.Origin); + origin = new MessageOrigin (origin, instruction.Offset); + MarkField ((FieldReference) instruction.Operand, new DependencyInfo (DependencyKind.FieldAccess, method), origin); break; case OperandType.InlineMethod: { @@ -3763,11 +3686,11 @@ protected virtual void MarkInstruction (Instruction instruction, MethodDefinitio requiresReflectionMethodBodyScanner |= ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForCallSite (Context, methodReference); - ScopeStack.UpdateCurrentScopeInstructionOffset (instruction.Offset); + origin = new MessageOrigin (origin, instruction.Offset); if (markForReflectionAccess) { - MarkMethodVisibleToReflection (methodReference, new DependencyInfo (dependencyKind, method), ScopeStack.CurrentScope.Origin); + MarkMethodVisibleToReflection (methodReference, new DependencyInfo (dependencyKind, method), origin); } else { - MarkMethod (methodReference, new DependencyInfo (dependencyKind, method), ScopeStack.CurrentScope.Origin); + MarkMethod (methodReference, new DependencyInfo (dependencyKind, method), origin); } break; } @@ -3776,16 +3699,16 @@ protected virtual void MarkInstruction (Instruction instruction, MethodDefinitio object token = instruction.Operand; Debug.Assert (instruction.OpCode.Code == Code.Ldtoken); var reason = new DependencyInfo (DependencyKind.Ldtoken, method); - ScopeStack.UpdateCurrentScopeInstructionOffset (instruction.Offset); + origin = new MessageOrigin (origin, instruction.Offset); if (token is TypeReference typeReference) { // Error will be reported as part of MarkType if (Context.TryResolve (typeReference) is TypeDefinition type) - MarkTypeVisibleToReflection (typeReference, type, reason, ScopeStack.CurrentScope.Origin); + MarkTypeVisibleToReflection (typeReference, type, reason, origin); } else if (token is MethodReference methodReference) { - MarkMethodVisibleToReflection (methodReference, reason, ScopeStack.CurrentScope.Origin); + MarkMethodVisibleToReflection (methodReference, reason, origin); } else { - MarkFieldVisibleToReflection ((FieldReference) token, reason, ScopeStack.CurrentScope.Origin); + MarkFieldVisibleToReflection ((FieldReference) token, reason, origin); } break; } @@ -3820,31 +3743,29 @@ protected virtual void MarkInstruction (Instruction instruction, MethodDefinitio break; } - ScopeStack.UpdateCurrentScopeInstructionOffset (instruction.Offset); - MarkType (operand, new DependencyInfo (DependencyKind.InstructionTypeRef, method)); + origin = new MessageOrigin (origin, instruction.Offset); + MarkType (operand, new DependencyInfo (DependencyKind.InstructionTypeRef, method), origin); break; } } - void MarkInterfaceImplementationList (List ifaces, MessageOrigin? origin = null, DependencyInfo? reason = null) + void MarkInterfaceImplementationList (List ifaces, MessageOrigin origin, DependencyInfo? reason = null) { foreach (var iface in ifaces) { MarkInterfaceImplementation (iface, origin, reason); } } - protected internal virtual void MarkInterfaceImplementation (InterfaceImplementation iface, MessageOrigin? origin = null, DependencyInfo? reason = null) + protected internal virtual void MarkInterfaceImplementation (InterfaceImplementation iface, MessageOrigin origin, DependencyInfo? reason = null) { if (Annotations.IsMarked (iface)) return; - Annotations.MarkProcessed (iface, reason ?? new DependencyInfo (DependencyKind.InterfaceImplementationOnType, ScopeStack.CurrentScope.Origin.Provider)); - - using MarkScopeStack.LocalScope? localScope = origin.HasValue ? ScopeStack.PushLocalScope (origin.Value) : null; + Annotations.MarkProcessed (iface, reason ?? new DependencyInfo (DependencyKind.InterfaceImplementationOnType, origin.Provider)); // Blame the type that has the interfaceimpl, expecting the type itself to get marked for other reasons. - MarkCustomAttributes (iface, new DependencyInfo (DependencyKind.CustomAttribute, iface)); + MarkCustomAttributes (iface, new DependencyInfo (DependencyKind.CustomAttribute, iface), origin); // Blame the interface type on the interfaceimpl itself. - MarkType (iface.InterfaceType, reason ?? new DependencyInfo (DependencyKind.InterfaceImplementationInterfaceType, iface)); + MarkType (iface.InterfaceType, reason ?? new DependencyInfo (DependencyKind.InterfaceImplementationInterfaceType, iface), origin); } // @@ -3858,7 +3779,7 @@ protected internal virtual bool ProcessReflectionDependency (MethodBody body, In // // Tries to mark additional dependencies used in reflection like calls (e.g. typeof (MyClass).GetField ("fname")) // - protected virtual void MarkReflectionLikeDependencies (MethodIL methodIL, bool requiresReflectionMethodBodyScanner) + protected virtual void MarkReflectionLikeDependencies (MethodIL methodIL, bool requiresReflectionMethodBodyScanner, MessageOrigin origin) { Debug.Assert (!CompilerGeneratedState.IsNestedFunctionOrStateMachineMember (methodIL.Method)); // requiresReflectionMethodBodyScanner tells us whether the method body itself requires a dataflow scan. @@ -3870,12 +3791,12 @@ protected virtual void MarkReflectionLikeDependencies (MethodIL methodIL, bool r switch (compilerGeneratedCallee) { case MethodDefinition nestedFunction: if (nestedFunction.Body is MethodBody nestedBody) - requiresReflectionMethodBodyScanner |= MarkAndCheckRequiresReflectionMethodBodyScanner (Context.GetMethodIL (nestedBody)); + requiresReflectionMethodBodyScanner |= MarkAndCheckRequiresReflectionMethodBodyScanner (Context.GetMethodIL (nestedBody), origin); break; case TypeDefinition stateMachineType: foreach (var method in stateMachineType.Methods) { if (method.Body is MethodBody stateMachineBody) - requiresReflectionMethodBodyScanner |= MarkAndCheckRequiresReflectionMethodBodyScanner (Context.GetMethodIL (stateMachineBody)); + requiresReflectionMethodBodyScanner |= MarkAndCheckRequiresReflectionMethodBodyScanner (Context.GetMethodIL (stateMachineBody), origin); } break; default: @@ -3887,8 +3808,7 @@ protected virtual void MarkReflectionLikeDependencies (MethodIL methodIL, bool r if (!requiresReflectionMethodBodyScanner) return; - Debug.Assert (ScopeStack.CurrentScope.Origin.Provider == methodIL.Method); - var scanner = new ReflectionMethodBodyScanner (Context, this, ScopeStack.CurrentScope.Origin); + var scanner = new ReflectionMethodBodyScanner (Context, this, origin); scanner.InterproceduralScan (methodIL); } diff --git a/src/tools/illink/src/linker/Linker.Steps/OutputStep.cs b/src/tools/illink/src/linker/Linker.Steps/OutputStep.cs index 5cf6f0e3f1e9..2fa3c03f2b39 100644 --- a/src/tools/illink/src/linker/Linker.Steps/OutputStep.cs +++ b/src/tools/illink/src/linker/Linker.Steps/OutputStep.cs @@ -42,17 +42,6 @@ namespace Mono.Linker.Steps public class OutputStep : BaseStep { - private Dictionary? architectureMap; - - private enum NativeOSOverride - { - Apple = 0x4644, - FreeBSD = 0xadc4, - Linux = 0x7b79, - NetBSD = 0x1993, - Default = 0 - } - readonly List assembliesWritten; public OutputStep () @@ -60,25 +49,6 @@ public OutputStep () assembliesWritten = new List (); } - TargetArchitecture CalculateArchitecture (TargetArchitecture readyToRunArch) - { - if (architectureMap == null) { - architectureMap = new Dictionary (); - foreach (var os in Enum.GetValues (typeof (NativeOSOverride))) { - ushort osVal = (ushort) (NativeOSOverride) os; - foreach (var arch in Enum.GetValues (typeof (TargetArchitecture))) { - ushort archVal = (ushort) (TargetArchitecture) arch; - architectureMap.Add ((ushort) (archVal ^ osVal), (TargetArchitecture) arch); - } - } - } - - if (architectureMap.TryGetValue ((ushort) readyToRunArch, out TargetArchitecture pureILArch)) { - return pureILArch; - } - throw new BadImageFormatException ("unrecognized module attributes"); - } - protected override bool ConditionToProcess () { return Context.ErrorsCount == 0; @@ -125,7 +95,7 @@ protected virtual void WriteAssembly (AssemblyDefinition assembly, string direct if (module.IsCrossgened ()) { module.Attributes |= ModuleAttributes.ILOnly; module.Attributes ^= ModuleAttributes.ILLibrary; - module.Architecture = CalculateArchitecture (module.Architecture); + module.Architecture = TargetArchitecture.I386; // I386+ILOnly which ultimately translates to AnyCPU } } diff --git a/src/tools/illink/src/linker/Linker.Steps/ValidateVirtualMethodAnnotationsStep.cs b/src/tools/illink/src/linker/Linker.Steps/ValidateVirtualMethodAnnotationsStep.cs index 807a9b03b8a8..ac4b07e6681b 100644 --- a/src/tools/illink/src/linker/Linker.Steps/ValidateVirtualMethodAnnotationsStep.cs +++ b/src/tools/illink/src/linker/Linker.Steps/ValidateVirtualMethodAnnotationsStep.cs @@ -40,10 +40,15 @@ protected override void Process () void ValidateMethodRequiresUnreferencedCodeAreSame (MethodDefinition method, MethodDefinition baseMethod) { var annotations = Context.Annotations; - bool methodHasAttribute = annotations.IsInRequiresUnreferencedCodeScope (method, out _); - if (methodHasAttribute != annotations.IsInRequiresUnreferencedCodeScope (baseMethod, out _)) { - string message = MessageFormat.FormatRequiresAttributeMismatch (methodHasAttribute, - baseMethod.DeclaringType.IsInterface, nameof (RequiresUnreferencedCodeAttribute), method.GetDisplayName (), baseMethod.GetDisplayName ()); + bool methodSatisfies = annotations.IsInRequiresUnreferencedCodeScope (method, out _); + bool baseRequires = annotations.DoesMethodRequireUnreferencedCode (baseMethod, out _); + if ((baseRequires && !methodSatisfies) || (!baseRequires && annotations.DoesMethodRequireUnreferencedCode (method, out _))) { + string message = MessageFormat.FormatRequiresAttributeMismatch ( + methodSatisfies, + baseMethod.DeclaringType.IsInterface, + nameof (RequiresUnreferencedCodeAttribute), + method.GetDisplayName (), + baseMethod.GetDisplayName ()); Context.LogWarning (method, DiagnosticId.RequiresUnreferencedCodeAttributeMismatch, message); } } diff --git a/src/tools/illink/src/linker/Linker/Annotations.cs b/src/tools/illink/src/linker/Linker/Annotations.cs index a7f77cf0efae..68c8c3207499 100644 --- a/src/tools/illink/src/linker/Linker/Annotations.cs +++ b/src/tools/illink/src/linker/Linker/Annotations.cs @@ -719,7 +719,7 @@ public void EnqueueVirtualMethod (MethodDefinition method) VirtualMethodsWithAnnotationsToValidate.Add (method); } - internal List<(TypeReference, List)>? GetRecursiveInterfaces (TypeDefinition type) + internal List<(TypeReference InterfaceType, List ImplementationChain)>? GetRecursiveInterfaces (TypeDefinition type) { return TypeMapInfo.GetRecursiveInterfaces (type); } diff --git a/src/tools/illink/src/linker/Linker/DictionaryExtensions.cs b/src/tools/illink/src/linker/Linker/DictionaryExtensions.cs index 9cf8945fe480..470cf9eb182a 100644 --- a/src/tools/illink/src/linker/Linker/DictionaryExtensions.cs +++ b/src/tools/illink/src/linker/Linker/DictionaryExtensions.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; using System.Collections.Generic; namespace Mono.Linker @@ -16,5 +17,15 @@ public static void AddToList (this Dictionary (this Dictionary dict, T key, Func createValue) where T : notnull + { + if (dict.TryGetValue (key, out var value)) { + return value; + } + U val = createValue (key); + dict.Add (key, val); + return val; + } } } diff --git a/src/tools/illink/src/linker/Linker/Driver.cs b/src/tools/illink/src/linker/Linker/Driver.cs index f699127b16c3..43495d535820 100644 --- a/src/tools/illink/src/linker/Linker/Driver.cs +++ b/src/tools/illink/src/linker/Linker/Driver.cs @@ -362,6 +362,12 @@ protected int SetupContext (ILogger? customLogger = null) context.SetCustomData (values[0], values[1]); continue; + case "--keep-com-interfaces": + if (!GetBoolParam (token, l => context.KeepComInterfaces = l)) + return -1; + + continue; + case "--keep-compilers-resources": if (!GetBoolParam (token, l => keepCompilersResources = l)) return -1; @@ -1284,6 +1290,7 @@ protected virtual LinkContext GetDefaultContext (Pipeline pipeline, ILogger? log return new LinkContext (pipeline, logger ?? new ConsoleLogger (), "output") { TrimAction = AssemblyAction.Link, DefaultAction = AssemblyAction.Link, + KeepComInterfaces = true, }; } @@ -1369,6 +1376,7 @@ static void Usage () Console.WriteLine (" sealer: Any method or type which does not have override is marked as sealed"); Console.WriteLine (" --explicit-reflection Adds to members never used through reflection DisablePrivateReflection attribute. Defaults to false"); Console.WriteLine (" --feature FEATURE VALUE Apply any optimizations defined when this feature setting is a constant known at link time"); + Console.WriteLine (" --keep-com-interfaces Keep COM interfaces implemented by kept types. Defaults to true"); Console.WriteLine (" --keep-compilers-resources Keep assembly resources used for F# compilation resources. Defaults to false"); Console.WriteLine (" --keep-dep-attributes Keep attributes used for manual dependency tracking. Defaults to false"); Console.WriteLine (" --keep-metadata NAME Keep metadata which would otherwise be removed if not used"); diff --git a/src/tools/illink/src/linker/Linker/LinkContext.cs b/src/tools/illink/src/linker/Linker/LinkContext.cs index 4af4cdc654ab..d5c9804a2d50 100644 --- a/src/tools/illink/src/linker/Linker/LinkContext.cs +++ b/src/tools/illink/src/linker/Linker/LinkContext.cs @@ -108,6 +108,8 @@ public Pipeline Pipeline { public bool LinkSymbols { get; set; } + public bool KeepComInterfaces { get; set; } + public bool KeepMembersForDebugger { get; set; } = true; public bool IgnoreUnresolved { get; set; } = true; @@ -606,7 +608,7 @@ public void LogWarning (MessageOrigin origin, DiagnosticId id, params string[] a /// Unique warning ID. Please see https://github.com/dotnet/runtime/blob/main/docs/tools/illink/error-codes.md for the list of warnings and possibly add a new one /// Type or member where the warning is coming from /// Optionally, further categorize this warning - public void LogWarning (string text, int code, IMemberDefinition origin, int? ilOffset = null, string subcategory = MessageSubCategory.None) + internal void LogWarning (string text, int code, IMemberDefinition origin, int ilOffset = MessageOrigin.UnsetILOffset, string subcategory = MessageSubCategory.None) { MessageOrigin _origin = new MessageOrigin (origin, ilOffset); LogWarning (text, code, _origin, subcategory); @@ -620,7 +622,7 @@ public void LogWarning (string text, int code, IMemberDefinition origin, int? il /// Type or member where the warning is coming from /// Unique warning ID. Please see https://github.com/dotnet/runtime/blob/main/docs/tools/illink/error-codes.md for the list of warnings and possibly add a new one /// Additional arguments to form a humanly readable message describing the warning - public void LogWarning (IMemberDefinition origin, DiagnosticId id, int? ilOffset = null, params string[] args) + internal void LogWarning (IMemberDefinition origin, DiagnosticId id, int ilOffset = MessageOrigin.UnsetILOffset, params string[] args) { MessageOrigin _origin = new MessageOrigin (origin, ilOffset); LogWarning (_origin, id, args); diff --git a/src/tools/illink/src/linker/Linker/MessageContainer.cs b/src/tools/illink/src/linker/Linker/MessageContainer.cs index eb1fe94a53cf..0de844bd6e80 100644 --- a/src/tools/illink/src/linker/Linker/MessageContainer.cs +++ b/src/tools/illink/src/linker/Linker/MessageContainer.cs @@ -253,6 +253,11 @@ public static MessageContainer CreateInfoMessage (string text) return new MessageContainer (MessageCategory.Info, text, null); } + internal static MessageContainer CreateInfoMessage (MessageOrigin origin, string text) + { + return new MessageContainer (MessageCategory.Info, text, null, "", origin); + } + /// /// Create a diagnostics message. /// diff --git a/src/tools/illink/src/linker/Linker/MessageOrigin.cs b/src/tools/illink/src/linker/Linker/MessageOrigin.cs index 6cc13521faaf..77394c28160f 100644 --- a/src/tools/illink/src/linker/Linker/MessageOrigin.cs +++ b/src/tools/illink/src/linker/Linker/MessageOrigin.cs @@ -17,17 +17,19 @@ namespace Mono.Linker public int SourceLine { get; } public int SourceColumn { get; } - public int? ILOffset { get; } + internal int ILOffset { get; } + + internal const int UnsetILOffset = -1; const int HiddenLineNumber = 0xfeefee; public MessageOrigin (IMemberDefinition? memberDefinition, int? ilOffset = null) - : this (memberDefinition as ICustomAttributeProvider, ilOffset) + : this (memberDefinition as ICustomAttributeProvider, ilOffset ?? UnsetILOffset) { } public MessageOrigin (ICustomAttributeProvider? provider) - : this (provider, null) + : this (provider, UnsetILOffset) { } @@ -44,7 +46,7 @@ public MessageOrigin (string fileName, int sourceLine, int sourceColumn, Assembl SourceLine = sourceLine; SourceColumn = sourceColumn; Provider = assembly; - ILOffset = null; + ILOffset = UnsetILOffset; } public MessageOrigin (ICustomAttributeProvider? provider, int? ilOffset) @@ -54,7 +56,7 @@ public MessageOrigin (ICustomAttributeProvider? provider, int? ilOffset) Provider = provider; SourceLine = 0; SourceColumn = 0; - ILOffset = ilOffset; + ILOffset = ilOffset ?? UnsetILOffset; } public MessageOrigin (MessageOrigin other) @@ -83,7 +85,7 @@ public MessageOrigin (MessageOrigin other, int ilOffset) string? fileName = FileName; if (Provider is MethodDefinition method && method.DebugInformation.HasSequencePoints) { - var offset = ILOffset ?? method.DebugInformation.SequencePoints[0].Offset; + var offset = ILOffset == UnsetILOffset ? method.DebugInformation.SequencePoints[0].Offset : ILOffset; SequencePoint? correspondingSequencePoint = method.DebugInformation.SequencePoints .Where (s => s.Offset <= offset)?.Last (); @@ -138,10 +140,10 @@ public int CompareTo (MessageOrigin other) if (result != 0) return result; - if (ILOffset != null && other.ILOffset != null) - return ILOffset.Value.CompareTo (other.ILOffset); + if (ILOffset != UnsetILOffset && other.ILOffset != UnsetILOffset) + return ILOffset.CompareTo (other.ILOffset); - return ILOffset == null ? (other.ILOffset == null ? 0 : 1) : -1; + return ILOffset == UnsetILOffset ? (other.ILOffset == UnsetILOffset ? 0 : 1) : -1; } else if (Provider == null && other.Provider == null) { if (FileName != null && other.FileName != null) { return string.Compare (FileName, other.FileName); diff --git a/src/tools/illink/src/linker/Linker/TypeMapInfo.cs b/src/tools/illink/src/linker/Linker/TypeMapInfo.cs index d2813c8982c4..1d7b24e070d1 100644 --- a/src/tools/illink/src/linker/Linker/TypeMapInfo.cs +++ b/src/tools/illink/src/linker/Linker/TypeMapInfo.cs @@ -66,7 +66,7 @@ public void EnsureProcessed (AssemblyDefinition assembly) /// /// Returns a list of all known methods that override . The list may be incomplete if other overrides exist in assemblies that haven't been processed by TypeMapInfo yet /// - public IEnumerable? GetOverrides (MethodDefinition method) + public List? GetOverrides (MethodDefinition method) { EnsureProcessed (method.Module.Assembly); override_methods.TryGetValue (method, out List? overrides); @@ -130,14 +130,15 @@ protected virtual void MapType (TypeDefinition type) MapType (nested); } - internal List<(TypeReference, List)>? GetRecursiveInterfaces (TypeDefinition type) + internal List<(TypeReference InterfaceType, List ImplementationChain)>? GetRecursiveInterfaces (TypeDefinition type) { + EnsureProcessed(type.Module.Assembly); if (interfaces.TryGetValue (type, out var value)) return value; return null; } - List<(TypeReference, List)> GetRecursiveInterfaceImplementations (TypeDefinition type) + List<(TypeReference InterfaceType, List ImplementationChain)> GetRecursiveInterfaceImplementations (TypeDefinition type) { List<(TypeReference, List)> firstImplementationChain = new (); diff --git a/src/tools/illink/src/linker/Mono.Linker.csproj b/src/tools/illink/src/linker/Mono.Linker.csproj index f19ff4063e68..24c4eba87ef3 100644 --- a/src/tools/illink/src/linker/Mono.Linker.csproj +++ b/src/tools/illink/src/linker/Mono.Linker.csproj @@ -76,6 +76,10 @@ + + + + all diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs index 087c7afea46a..c59afbfd8fd5 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs @@ -186,7 +186,7 @@ public Task InlineArrayDataflow () } [Fact] - public Task InterpolatedStringHandlerDataFlow () + public Task InterpolatedStringDataFlow () { return RunTest (); } @@ -197,6 +197,12 @@ public Task MakeGenericDataFlow () return RunTest (); } + [Fact] + public Task MakeGenericDataflowIntrinsics () + { + return RunTest (); + } + [Fact] public Task MethodByRefReturnDataFlow () { @@ -283,6 +289,12 @@ public Task MemberTypesRelationships () return RunTest (nameof (MemberTypesRelationships)); } + [Fact] + public Task MethodOutParameterDataFlow () + { + return RunTest (); + } + [Fact] public Task MethodParametersDataFlow () { @@ -307,6 +319,12 @@ public Task NullableAnnotations () return RunTest (); } + [Fact] + public Task ObjectGetTypeDataflow () + { + return RunTest (); + } + [Fact] public Task PropertyDataFlow () { diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs index a06c8115c315..fccb0de0d95e 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs @@ -1309,7 +1309,9 @@ public static void Main() return VerifyDynamicallyAccessedMembersAnalyzer (Source, consoleApplication: false, // (12,34): error CS0103: The name 'type' does not exist in the current context - DiagnosticResult.CompilerError ("CS0103").WithSpan (12, 34, 12, 38).WithArguments ("type")); + DiagnosticResult.CompilerError ("CS0103").WithSpan (12, 34, 12, 38).WithArguments ("type"), + // (12,34): warning IL2063: Value returned from method 'C.GetTypeWithAll()' can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. + VerifyCS.Diagnostic (DiagnosticId.MethodReturnValueCannotBeStaticallyDetermined).WithSpan(12, 34, 12, 38).WithArguments("C.GetTypeWithAll()")); } [Fact] @@ -1333,7 +1335,9 @@ public static void Main() return VerifyDynamicallyAccessedMembersAnalyzer (Source, consoleApplication: false, // (8,22): error CS0103: The name 'type' does not exist in the current context - DiagnosticResult.CompilerError ("CS0103").WithSpan (8, 22, 8, 26).WithArguments ("type")); + DiagnosticResult.CompilerError ("CS0103").WithSpan (8, 22, 8, 26).WithArguments ("type"), + // (8,3): warning IL2064: Value assigned to C.fieldRequiresAll can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. + VerifyCS.Diagnostic(DiagnosticId.FieldValueCannotBeStaticallyDetermined).WithSpan(8, 3, 8, 26).WithArguments("C.fieldRequiresAll")); } [Fact] diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresDynamicCodeAnalyzerTests.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresDynamicCodeAnalyzerTests.cs index ecc5e2c3e7c9..c2d32af6a401 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresDynamicCodeAnalyzerTests.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresDynamicCodeAnalyzerTests.cs @@ -2,8 +2,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Collections.Generic; using System.Threading.Tasks; using ILLink.Shared; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Testing; using Microsoft.CodeAnalysis.Text; using Xunit; @@ -34,6 +36,19 @@ public RequiresDynamicCodeAttribute (string message) } }"; + static async Task VerifyRequiresDynamicCodeAnalyzer ( + string source, + params DiagnosticResult[] expected) + { + + await VerifyCS.VerifyAnalyzerAsync ( + source, + consoleApplication: false, + TestCaseUtils.UseMSBuildProperties (MSBuildPropertyOptionNames.EnableAotAnalyzer), + Array.Empty (), + expected); + } + static Task VerifyRequiresDynamicCodeCodeFix ( string source, string fixedSource, @@ -332,5 +347,133 @@ private int M2 { }; return VerifyRequiresDynamicCodeCodeFix (src, fix, diag, Array.Empty ()); } + + [Fact] + public Task MakeGenericTypeWithAllKnownTypes () + { + const string src = $$""" + class C + { + public void M() => typeof(Gen<>).MakeGenericType(typeof(object)); + } + class Gen { } + """; + + return VerifyRequiresDynamicCodeAnalyzer (src); + } + + [Fact] + public Task MakeGenericTypeWithAllKnownTypesInGenericContext () + { + const string src = $$""" + class C + { + public void M() => typeof(Gen<>).MakeGenericType(typeof(T)); + } + class Gen { } + """; + + return VerifyRequiresDynamicCodeAnalyzer (src); + } + + [Fact] + public Task MakeGenericTypeWithUnknownDefinition () + { + const string src = $$""" + using System; + class C + { + public void M() => GetDefinition().MakeGenericType(typeof(object)); + static Type GetDefinition() => typeof(Gen<>); + } + class Gen { } + """; + + return VerifyRequiresDynamicCodeAnalyzer (src, + // (4,21): warning IL3050: Using member 'System.Type.MakeGenericType(params Type[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime. + VerifyCS.Diagnostic (DiagnosticId.RequiresDynamicCode).WithSpan (4, 21, 4, 68).WithArguments ("System.Type.MakeGenericType(params Type[])", " The native code for this instantiation might not be available at runtime.", "")); + } + + [Fact] + public Task MakeGenericTypeWithUnknownArgument () + { + const string src = $$""" + using System; + class C + { + public void M() => typeof(Gen<>).MakeGenericType(GetObject()); + static Type GetObject() => typeof(object); + } + class Gen { } + """; + + return VerifyRequiresDynamicCodeAnalyzer (src, + // (4,21): warning IL3050: Using member 'System.Type.MakeGenericType(params Type[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime. + VerifyCS.Diagnostic (DiagnosticId.RequiresDynamicCode).WithSpan (4, 21, 4, 63).WithArguments ("System.Type.MakeGenericType(params Type[])", " The native code for this instantiation might not be available at runtime.", "")); + } + + [Fact] + public Task MakeGenericMethodWithAllKnownTypes () + { + const string src = $$""" + class C + { + public void M() => typeof(C).GetMethod(nameof(N)).MakeGenericMethod(typeof(object)); + public void N() { } + } + """; + + return VerifyRequiresDynamicCodeAnalyzer (src); + } + + [Fact] + public Task MakeGenericMethodWithAllKnownTypesInGenericContext () + { + const string src = $$""" + class C + { + public void M() => typeof(C).GetMethod(nameof(N)).MakeGenericMethod(typeof(T)); + public void N() { } + } + """; + + return VerifyRequiresDynamicCodeAnalyzer (src); + } + + [Fact] + public Task MakeGenericMethodWithUnknownDefinition () + { + const string src = $$""" + using System.Reflection; + class C + { + public void M() => GetMethodInfo().MakeGenericMethod(typeof(object)); + public void N() { } + public MethodInfo GetMethodInfo() => typeof(C).GetMethod(nameof(N)); + } + """; + + return VerifyRequiresDynamicCodeAnalyzer (src, + // (4,21): warning IL3050: Using member 'System.Reflection.MethodInfo.MakeGenericMethod(params Type[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime. + VerifyCS.Diagnostic (DiagnosticId.RequiresDynamicCode).WithSpan (4, 21, 4, 70).WithArguments ("System.Reflection.MethodInfo.MakeGenericMethod(params Type[])", " The native code for this instantiation might not be available at runtime.", "")); + } + + [Fact] + public Task MakeGenericMethodWithUnknownArgument () + { + const string src = $$""" + using System; + class C + { + public void M() => typeof(C).GetMethod(nameof(N)).MakeGenericMethod(GetObject()); + public void N() { } + static Type GetObject() => typeof(object); + } + """; + + return VerifyRequiresDynamicCodeAnalyzer (src, + // (4,21): warning IL3050: Using member 'System.Reflection.MethodInfo.MakeGenericMethod(params Type[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime. + VerifyCS.Diagnostic (DiagnosticId.RequiresDynamicCode).WithSpan (4, 21, 4, 82).WithArguments ("System.Reflection.MethodInfo.MakeGenericMethod(params Type[])", " The native code for this instantiation might not be available at runtime.", "")); + } } } diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs index d05326239a39..4bf104b67a7c 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs @@ -90,7 +90,7 @@ private static IEnumerable GetTestDependencies (string testCaseDir, Synt switch (attributeName) { case "SetupCompileBefore": { var arrayExpression = args["#1"]; - if (arrayExpression is not (ArrayCreationExpressionSyntax or ImplicitArrayCreationExpressionSyntax)) + if (arrayExpression is not (ArrayCreationExpressionSyntax or ImplicitArrayCreationExpressionSyntax or CollectionExpressionSyntax)) throw new InvalidOperationException (); foreach (var sourceFile in args["#1"].DescendantNodes ().OfType ()) yield return Path.Combine (testCaseDir, LinkerTestBase.GetStringFromExpression (sourceFile)); diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs index 7631b802fbcc..c50d24f13605 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text.RegularExpressions; @@ -66,7 +67,7 @@ public void Check (bool allowMissingWarnings) } if (message.Length > 0) { - Assert.Fail(message); + Assert.Fail (message); } } @@ -207,51 +208,62 @@ private void ValidateDiagnostics (CSharpSyntaxNode memberSyntax, SyntaxList arg.Key.StartsWith ('#')).Count () - 2; + if (args.TryGetValue ($"#{toolArg}", out var maybeProducedBy) && TryGetProducedBy (maybeProducedBy, out Tool producedByTool)) { + return producedByTool.HasFlag (Tool.Analyzer); + } return true; default: return false; } - static Tool GetProducedBy (ExpressionSyntax expression) + static bool TryGetProducedBy (ExpressionSyntax expression, out Tool producedBy) { - var producedBy = (Tool) 0x0; + producedBy = (Tool) 0x0; switch (expression) { - case BinaryExpressionSyntax binaryExpressionSyntax: + case BinaryExpressionSyntax binaryExpressionSyntax when binaryExpressionSyntax.Kind () == SyntaxKind.BitwiseOrExpression: if (!Enum.TryParse ((binaryExpressionSyntax.Left as MemberAccessExpressionSyntax)!.Name.Identifier.ValueText, out var besProducedBy)) - throw new ArgumentException ("Expression must be a ProducedBy value", nameof (expression)); + return false; producedBy |= besProducedBy; producedBy |= GetProducedBy (binaryExpressionSyntax.Right); break; case MemberAccessExpressionSyntax memberAccessExpressionSyntax: if (!Enum.TryParse (memberAccessExpressionSyntax.Name.Identifier.ValueText, out var maeProducedBy)) - throw new ArgumentException ("Expression must be a ProducedBy value", nameof (expression)); + return false; producedBy |= maeProducedBy; break; default: - break; + return false; } - return producedBy; + return true; + } + + static Tool GetProducedBy (ExpressionSyntax expression) + { + return TryGetProducedBy (expression, out var tool) ? tool : throw new ArgumentException ("Expression must be a ProducedBy value", nameof (expression)); } } bool TryValidateExpectedDiagnostic (AttributeSyntax attribute, List diagnostics, [NotNullWhen (true)] out int? matchIndex, [NotNullWhen (false)] out string? missingDiagnosticMessage) { - switch (attribute.Name.ToString ()) { - case "ExpectedWarning": + switch (attribute.Name.ToString () + "Attribute") { + case nameof (ExpectedWarningAttribute): + case nameof (UnexpectedWarningAttribute): return TryValidateExpectedWarningAttribute (attribute!, diagnostics, out matchIndex, out missingDiagnosticMessage); - case "LogContains": + case nameof (LogContainsAttribute): return TryValidateLogContainsAttribute (attribute!, diagnostics, out matchIndex, out missingDiagnosticMessage); default: throw new InvalidOperationException ($"Unsupported attribute type {attribute.Name}"); @@ -268,10 +280,29 @@ private bool TryValidateExpectedWarningAttribute (AttributeSyntax attribute, Lis if (!expectedWarningCode.StartsWith ("IL")) throw new InvalidOperationException ($"Expected warning code should start with \"IL\" prefix."); - List expectedMessages = args - .Where (arg => arg.Key.StartsWith ("#") && arg.Key != "#0") - .Select (arg => LinkerTestBase.GetStringFromExpression (arg.Value, _semanticModel)) - .ToList (); + List expectedMessages = ((IMethodSymbol) (_semanticModel.GetSymbolInfo (attribute).Symbol!)).Parameters switch { + // ExpectedWarningAttribute(string warningCode, params string[] expectedMessages) + [_, { IsParams: true }] + => args + .Where (arg => arg.Key.StartsWith ('#') && arg.Key != "#0") + .Select (arg => LinkerTestBase.GetStringFromExpression (arg.Value, _semanticModel)) + .ToList (), + // ExpectedWarningAttribute(string warningCode, string[] expectedMessages, Tool producedBy, string issueLink) + [_, { Type.TypeKind: TypeKind.Array }, _, _] + => ((CollectionExpressionSyntax) args["#1"]).Elements + .Select (arg => LinkerTestBase.GetStringFromExpression (((ExpressionElementSyntax) arg).Expression, _semanticModel)) + .ToList (), + // ExpectedWarningAttribute(string warningCode, string expectedMessage, Tool producedBy, string issueLink) + [_, { Type.SpecialType: SpecialType.System_String }, _, _] + => [LinkerTestBase.GetStringFromExpression (args["#1"], _semanticModel)], + // ExpectedWarningAttribute(string warningCode, string expectedMessage1, string expectedMessage2, Tool producedBy, string issueLink) + [_, { Type.SpecialType: SpecialType.System_String }, { Type.SpecialType: SpecialType.System_String }, _, _] + => [LinkerTestBase.GetStringFromExpression (args["#1"], _semanticModel), LinkerTestBase.GetStringFromExpression (args["#2"], _semanticModel)], + // ExpectedWarningAttribute(string warningCode, Tool producedBy, string issueLink) + [_, _, _] + => [], + _ => throw new UnreachableException (), + }; for (int i = 0; i < diagnostics.Count; i++) { if (Matches (diagnostics[i])) { @@ -318,7 +349,7 @@ private void ValidateLogDoesNotContainAttribute (AttributeSyntax attribute, IRea Assert.False (args.ContainsKey ("#1")); _ = LinkerTestBase.GetStringFromExpression (arg, _semanticModel); if (LogContains (attribute, diagnosticMessages, out var matchIndex, out var findText)) { - Assert.Fail($"LogDoesNotContain failure: Text\n\"{findText}\"\nfound in diagnostic:\n {diagnosticMessages[(int) matchIndex]}"); + Assert.Fail ($"LogDoesNotContain failure: Text\n\"{findText}\"\nfound in diagnostic:\n {diagnosticMessages[(int) matchIndex]}"); } } diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/AttributesTests.g.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/AttributesTests.g.cs index f563a23f9e3d..a912649e9ced 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/AttributesTests.g.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/AttributesTests.g.cs @@ -123,6 +123,12 @@ public Task IVTUnused () return RunTest (allowMissingWarnings: true); } + [Fact] + public Task IVTUnusedKeptWhenKeepingUsedAttributesOnly () + { + return RunTest (allowMissingWarnings: true); + } + [Fact] public Task IVTUsed () { diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs index 5c3bd5a9d665..8f435261c793 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs @@ -25,12 +25,6 @@ public Task MethodByRefParameterDataFlow () return RunTest (allowMissingWarnings: true); } - [Fact] - public Task MethodOutParameterDataFlow () - { - return RunTest (allowMissingWarnings: true); - } - [Fact] public Task StaticInterfaceMethodDataflow () { diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/Inheritance.Interfaces.OnReferenceTypeTests.g.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/Inheritance.Interfaces.OnReferenceTypeTests.g.cs index 980cadd5d7a5..d87fcc06d688 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/Inheritance.Interfaces.OnReferenceTypeTests.g.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/Inheritance.Interfaces.OnReferenceTypeTests.g.cs @@ -147,6 +147,12 @@ public Task UnusedComInterfaceIsKept () return RunTest (allowMissingWarnings: true); } + [Fact] + public Task UnusedComInterfaceIsRemoved () + { + return RunTest (allowMissingWarnings: true); + } + [Fact] public Task UnusedExplicitInterfaceHasMethodPreservedViaXml () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedWarningAttribute.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedWarningAttribute.cs index 648241200ef1..19b785adabcc 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedWarningAttribute.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedWarningAttribute.cs @@ -9,8 +9,27 @@ namespace Mono.Linker.Tests.Cases.Expectations.Assertions AttributeTargets.Assembly | AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Event, AllowMultiple = true, Inherited = false)] + /// + /// An attribute applied to a member to indicate that a warning is expected in ideal behavior, and is present in all tools + /// public class ExpectedWarningAttribute : EnableLoggerAttribute { + public ExpectedWarningAttribute (string warningCode, string[] messageContains, Tool producedBy, string issueLinkOrReason) + { + } + + public ExpectedWarningAttribute (string warningCode, string messageContains, Tool producedBy, string issueLinkOrReason) + { + } + + public ExpectedWarningAttribute (string warningCode, string messageContains, string messageContains2, Tool producedBy, string issueLinkOrReason) + { + } + + public ExpectedWarningAttribute (string warningCode, Tool producedBy, string issueLinkOrReason) + { + } + public ExpectedWarningAttribute (string warningCode, params string[] messageContains) { } @@ -19,12 +38,6 @@ public ExpectedWarningAttribute (string warningCode, params string[] messageCont public int SourceLine { get; set; } public int SourceColumn { get; set; } - /// - /// Property used by the result checkers of trimmer and analyzers to determine whether - /// the tool should have produced the specified warning on the annotated member. - /// - public Tool ProducedBy { get; set; } = Tool.TrimmerAnalyzerAndNativeAot; - public bool CompilerGeneratedCode { get; set; } } } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/Tool.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/Tool.cs index c6a00e11e1e2..19667c8a8b75 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/Tool.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/Tool.cs @@ -13,6 +13,7 @@ namespace Mono.Linker.Tests.Cases.Expectations.Assertions [Flags] public enum Tool { + None = 0, Trimmer = 1, Analyzer = 2, NativeAot = 4, diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/UnexpectedWarningAttribute.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/UnexpectedWarningAttribute.cs new file mode 100644 index 000000000000..d745b61f3a16 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/UnexpectedWarningAttribute.cs @@ -0,0 +1,26 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; + +namespace Mono.Linker.Tests.Cases.Expectations.Assertions +{ + [AttributeUsage ( + AttributeTargets.Assembly | AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Event, + AllowMultiple = true, + Inherited = false)] + /// + /// An attribute applied to a member to indicate that a warning is raised in tests, but should not be present in ideal behavior + /// + public class UnexpectedWarningAttribute : ExpectedWarningAttribute + { + public UnexpectedWarningAttribute (string warningCode, string[] messageContains, Tool producedBy, string issueLinkOrReason) + : base (warningCode, messageContains, producedBy, issueLinkOrReason) { } + public UnexpectedWarningAttribute (string warningCode, string messageContains, Tool producedBy, string issueLinkOrReason) + : base (warningCode, messageContains, producedBy, issueLinkOrReason) { } + public UnexpectedWarningAttribute (string warningCode, string messageContains, string messageContains2, Tool producedBy, string issueLinkOrReason) + : base (warningCode, messageContains, messageContains2, producedBy, issueLinkOrReason) { } + public UnexpectedWarningAttribute (string warningCode, Tool producedBy, string issueLinkOrReason) + : base (warningCode, producedBy, issueLinkOrReason) { } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Helpers/PlatformAssemblies.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Helpers/PlatformAssemblies.cs index c2e77e98f8d4..8638267f26ac 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Helpers/PlatformAssemblies.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Helpers/PlatformAssemblies.cs @@ -5,7 +5,7 @@ namespace Mono.Linker.Tests.Cases.Expectations.Helpers { public static class PlatformAssemblies { -#if NETCOREAPP +#if NET public const string CoreLib = "System.Private.CoreLib.dll"; #else public const string CoreLib = "mscorlib.dll"; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Support/FeatureGuardAttribute.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Support/FeatureGuardAttribute.cs deleted file mode 100644 index a4351d0fa8ef..000000000000 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Support/FeatureGuardAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Diagnostics.CodeAnalysis -{ - // Allow AttributeTargets.Method for testing invalid usages of a custom FeatureGuardAttribute - [AttributeUsage (AttributeTargets.Property | AttributeTargets.Method, Inherited = false, AllowMultiple = true)] - public sealed class FeatureGuardAttribute : Attribute - { - public Type FeatureType { get; } - - public FeatureGuardAttribute (Type featureType) - { - FeatureType = featureType; - } - } -} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Support/FeatureSwitchDefinitionAttribute.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Support/FeatureSwitchDefinitionAttribute.cs deleted file mode 100644 index 71b030ab299f..000000000000 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Support/FeatureSwitchDefinitionAttribute.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Diagnostics.CodeAnalysis -{ - [AttributeUsage(AttributeTargets.Property, Inherited = false)] - public sealed class FeatureSwitchDefinitionAttribute : Attribute - { - public string SwitchName { get; } - - public FeatureSwitchDefinitionAttribute (string switchName) - { - SwitchName = switchName; - } - } -} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs index ff3d0937d561..f0c6c8cd4dee 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs @@ -10,7 +10,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers { [SetupLinkerTrimMode ("link")] -#if !NETCOREAPP +#if !NET [SetupLinkerKeepDebugMembers ("true")] #endif diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs index 31a098588c05..e6da349605d7 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs @@ -9,7 +9,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers { [SetupLinkerTrimMode ("link")] -#if !NETCOREAPP +#if !NET [SetupLinkerKeepDebugMembers ("true")] #endif diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs index db44758dbb2a..0f88184ecf3a 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs @@ -10,7 +10,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers { [SetupLinkerTrimMode ("link")] -#if !NETCOREAPP +#if !NET [SetupLinkerKeepDebugMembers ("true")] #endif [SetupCompileBefore ("library.dll", new[] { "../Dependencies/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.cs" })] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs index af5922ed8fe7..8e65562af475 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers { -#if !NETCOREAPP +#if !NET [SetupLinkerKeepDebugMembers ("true")] #endif diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToExtensionMethodOnFieldType.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToExtensionMethodOnFieldType.cs index 71ed65a23c0e..6e13271e8679 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToExtensionMethodOnFieldType.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToExtensionMethodOnFieldType.cs @@ -7,7 +7,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers { -#if !NETCOREAPP +#if !NET [SetupLinkerKeepDebugMembers ("true")] #endif public class DebuggerDisplayOnTypeWithCallToExtensionMethodOnFieldType diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToMethodOnFieldType.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToMethodOnFieldType.cs index 156bdb28e78c..e2fe84975f7c 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToMethodOnFieldType.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayOnTypeWithCallToMethodOnFieldType.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers { -#if !NETCOREAPP +#if !NET [SetupLinkerKeepDebugMembers ("true")] #endif public class DebuggerDisplayOnTypeWithCallToMethodOnFieldType diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs index e4d0bf419cc3..d86d4bf3fbd6 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs @@ -13,7 +13,7 @@ namespace Mono.Linker.Tests.Cases.Attributes [SetupLinkerArgument ("--skip-unresolved", "true")] [KeptAttributeInAssembly (PlatformAssemblies.CoreLib, typeof (AssemblyDescriptionAttribute))] [KeptAttributeInAssembly (PlatformAssemblies.CoreLib, typeof (AssemblyCompanyAttribute))] -#if !NETCOREAPP +#if !NET [KeptAttributeInAssembly ("System.dll", typeof (AssemblyDescriptionAttribute))] [KeptAttributeInAssembly ("System.dll", typeof (AssemblyCompanyAttribute))] #endif diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/IVTUnused_Lib.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/IVTUnused_Lib.cs new file mode 100644 index 000000000000..93a680a28589 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/IVTUnused_Lib.cs @@ -0,0 +1,8 @@ +#if IVT +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo ("missing")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo ("test-with-key, PublicKey=00240000")] +#endif + +namespace Mono.Linker.Tests.Cases.Attributes.Dependencies; + +public class IVTUnusedLib; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/IVTUnused.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/IVTUnused.cs index 82a1007d1b45..fed2aa80f8a9 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/IVTUnused.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/IVTUnused.cs @@ -1,20 +1,18 @@ using System.Runtime.CompilerServices; +using Mono.Linker.Tests.Cases.Attributes.Dependencies; using Mono.Linker.Tests.Cases.Expectations.Assertions; using Mono.Linker.Tests.Cases.Expectations.Metadata; -#if IVT -[assembly: InternalsVisibleTo ("missing")] -[assembly: InternalsVisibleTo ("test-with-key, PublicKey=00240000")] +namespace Mono.Linker.Tests.Cases.Attributes; -#endif - -namespace Mono.Linker.Tests.Cases.Attributes +[SetupCompileBefore ("lib.dll", ["Dependencies/IVTUnused_Lib.cs"], defines: ["IVT"])] +[KeptAssembly ("lib.dll")] +[KeptTypeInAssembly ("lib.dll", typeof(IVTUnusedLib))] +[KeptAttributeInAssembly ("lib.dll", typeof (InternalsVisibleToAttribute))] +class IVTUnused { - [Define ("IVT")] - class IVTUnused + static void Main () { - static void Main () - { - } + _ = new IVTUnusedLib (); } } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/IVTUnusedKeptWhenKeepingUsedAttributesOnly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/IVTUnusedKeptWhenKeepingUsedAttributesOnly.cs new file mode 100644 index 000000000000..1713c8b2600d --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/IVTUnusedKeptWhenKeepingUsedAttributesOnly.cs @@ -0,0 +1,20 @@ +using System.Runtime.CompilerServices; +using Mono.Linker.Tests.Cases.Attributes.Dependencies; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.Attributes; + +[SetupCompileBefore ("lib.dll", ["Dependencies/IVTUnused_Lib.cs"], defines: ["IVT"])] +[KeptAssembly ("lib.dll")] +[KeptTypeInAssembly ("lib.dll", typeof(IVTUnusedLib))] +[KeptAttributeInAssembly ("lib.dll", typeof (InternalsVisibleToAttribute))] + +[SetupLinkerArgument("--used-attrs-only", "true")] +class IVTUnusedKeptWhenKeepingUsedAttributesOnly +{ + static void Main () + { + _ = new IVTUnusedLib (); + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs index 64e046ec7710..44ab4218270a 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs @@ -10,7 +10,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed [SetupLinkerTrimMode ("link")] [SetupLinkerArgument ("--used-attrs-only", "true")] [RemovedAttributeInAssembly (PlatformAssemblies.CoreLib, typeof (AssemblyDescriptionAttribute))] -#if !NETCOREAPP +#if !NET [RemovedAttributeInAssembly ("System.dll", typeof (AssemblyDescriptionAttribute))] #endif public class CoreLibraryUnusedAssemblyAttributesAreRemoved diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs index bbbbe72db926..f3c70ec1a38d 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs @@ -10,7 +10,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed [SetupLinkerTrimMode ("link")] [SetupLinkerArgument ("--used-attrs-only", "true")] [KeptAttributeInAssembly (PlatformAssemblies.CoreLib, typeof (AssemblyDescriptionAttribute))] -#if !NETCOREAPP +#if !NET [KeptAttributeInAssembly ("System.dll", typeof (AssemblyDescriptionAttribute))] #endif public class CoreLibraryUsedAssemblyAttributesAreKept diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/TypeWithDynamicInterfaceCastableImplementationAttributeIsKept.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/TypeWithDynamicInterfaceCastableImplementationAttributeIsKept.cs index c6dd27cb5755..51be76c9f7fa 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/TypeWithDynamicInterfaceCastableImplementationAttributeIsKept.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/TypeWithDynamicInterfaceCastableImplementationAttributeIsKept.cs @@ -22,7 +22,7 @@ public class TypeWithDynamicInterfaceCastableImplementationAttributeIsKept { public static void Main () { -#if NETCOREAPP +#if NET Foo foo = new Foo (); GetBar (foo).Bar (); IReferenced baz = GetBaz (foo); @@ -32,7 +32,7 @@ public static void Main () #endif } -#if NETCOREAPP +#if NET [Kept] private static IReferencedAndCalled GetBar (object obj) { @@ -53,7 +53,7 @@ static IReferencedAssembly GetReferencedInterface (object obj) #endif } -#if NETCOREAPP +#if NET [Kept] [KeptMember (".ctor()")] [KeptInterface (typeof (IDynamicInterfaceCastable))] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InvalidIsTrimmableAttribute.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InvalidIsTrimmableAttribute.cs index 35463fd52d44..57b000fe3d37 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InvalidIsTrimmableAttribute.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InvalidIsTrimmableAttribute.cs @@ -29,4 +29,4 @@ public static void Unused () { } } -} \ No newline at end of file +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaReflection.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaReflection.cs index d3fcbf32df47..616e392ecae3 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaReflection.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaReflection.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; +using System.Reflection; using System.Runtime.InteropServices; using Mono.Linker.Tests.Cases.DataFlow; using Mono.Linker.Tests.Cases.Expectations.Assertions; @@ -29,6 +30,7 @@ public static void Main () AnnotationOnGenerics.Test (); AnnotationOnInteropMethod.Test (); DelegateCreation.Test (); + DamOnTypeAccessesMembers.Test (); } class AnnotatedField @@ -54,8 +56,8 @@ static void ReflectionReadOnly () typeof (AnnotatedField).GetField ("_annotatedField").GetValue (null); } - // DynamicDependency is not supported yet in the analyzer https://github.com/dotnet/runtime/issues/83080 - [ExpectedWarning ("IL2110", nameof (_annotatedField), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // DynamicDependency is not supported yet in the analyzer + [ExpectedWarning ("IL2110", nameof (_annotatedField), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency (DynamicallyAccessedMemberTypes.PublicFields, typeof (AnnotatedField))] static void DynamicDependency () { @@ -67,8 +69,8 @@ static void DynamicDependencySuppressedByRUC () { } - // DynamicDependency is not supported yet in the analyzer https://github.com/dotnet/runtime/issues/83080 - [ExpectedWarning ("IL2110", nameof (_annotatedField), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // DynamicDependency is not supported yet in the analyzer + [ExpectedWarning ("IL2110", nameof (_annotatedField), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency (nameof (_annotatedField), typeof (AnnotatedField))] static void DynamicDependencyByName () { @@ -128,8 +130,7 @@ static void PotentialWriteAccess (ref Type type) { } - // https://github.com/dotnet/linker/issues/3172 - [ExpectedWarning ("IL2110", nameof (AnnotatedField._annotatedField), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2110", nameof (AnnotatedField._annotatedField), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/3172")] static void LdToken () { Expression a = () => PotentialWriteAccess (ref _annotatedField); @@ -177,7 +178,7 @@ void LdftnOnLambda () { var _ = new Action ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] - () => MethodWithAnnotatedThisParameter ()); + () => MethodWithAnnotatedThisParameter ()); } [ExpectedWarning ("IL2111")] @@ -233,8 +234,8 @@ static void AnnotatedAttributeConstructor () { } - // DynamicDependency is not supported yet in the analyzer https://github.com/dotnet/runtime/issues/83080 - [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // DynamicDependency is not supported yet in the analyzer + [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency (DynamicallyAccessedMemberTypes.PublicMethods, typeof (AnnotatedMethodParameters))] static void DynamicDependency () { @@ -246,8 +247,8 @@ static void DynamicDependencySuppressedByRUC () { } - // DynamicDependency is not supported yet in the analyzer https://github.com/dotnet/runtime/issues/83080 - [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // DynamicDependency is not supported yet in the analyzer + [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency (nameof (MethodWithSingleAnnotatedParameter), typeof (AnnotatedMethodParameters))] static void DynamicDependencyByName () { @@ -278,7 +279,7 @@ static void LdftnSuppressedByRequiresUnreferencedCode () } [ExpectedWarning ("IL2111")] - static void + static void LdftnOnLambda () { var _ = new Action ( @@ -299,7 +300,7 @@ static void LdftnOnLambdaTriggersLamdaAnalysis () { var _ = new Action ( [ExpectedWarning ("IL2067", nameof (type), nameof (DataFlowTypeExtensions.RequiresAll))] - (Type type) => { type.RequiresAll (); }); + (Type type) => { type.RequiresAll (); }); } static void LdftnOnLocalMethodTriggersLocalMethodAnalysis () @@ -332,8 +333,8 @@ static void Ldvirtftn () [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter))] [ExpectedWarning ("IL2111", nameof (IWithAnnotatedMethod.AnnotatedMethod))] [ExpectedWarning ("IL2111", nameof (IWithAnnotatedMethod.AnnotatedMethod))] - [ExpectedWarning ("IL2118", nameof (LdftnOnLambdaTriggersLamdaAnalysis), ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", nameof (LdftnOnLocalMethodTriggersLocalMethodAnalysis), ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2118", nameof (LdftnOnLambdaTriggersLamdaAnalysis), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", nameof (LdftnOnLocalMethodTriggersLocalMethodAnalysis), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] static void DynamicallyAccessedMembersAll1 () { typeof (AnnotatedMethodParameters).RequiresAll (); @@ -346,16 +347,15 @@ static void DynamicallyAccessedMembersAll1 () [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter))] [ExpectedWarning ("IL2111", nameof (IWithAnnotatedMethod.AnnotatedMethod))] [ExpectedWarning ("IL2111", nameof (IWithAnnotatedMethod.AnnotatedMethod))] - [ExpectedWarning ("IL2118", nameof (LdftnOnLambdaTriggersLamdaAnalysis), ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", nameof (LdftnOnLocalMethodTriggersLocalMethodAnalysis), ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2118", nameof (LdftnOnLambdaTriggersLamdaAnalysis), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", nameof (LdftnOnLocalMethodTriggersLocalMethodAnalysis), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] static void DynamicallyAccessedMembersAll2 () { typeof (AnnotatedMethodParameters).RequiresAll (); } - // https://github.com/dotnet/linker/issues/3172 - [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2067", nameof (MethodWithSingleAnnotatedParameter), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2111", nameof (MethodWithSingleAnnotatedParameter), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/3172")] + [UnexpectedWarning ("IL2067", nameof (MethodWithSingleAnnotatedParameter), Tool.Analyzer, "https://github.com/dotnet/linker/issues/3172")] static void LdToken () { Expression> _ = (Type t) => MethodWithSingleAnnotatedParameter (t); @@ -420,8 +420,7 @@ static void ReflectionOnVirtualSuppressedByRUC () typeof (AnnotatedMethodReturnValue).GetMethod (nameof (VirtualMethodWithAnnotatedReturnValue)).Invoke (null, null); } - // DynamicDependency is not supported yet in the analyzer https://github.com/dotnet/runtime/issues/83080 - [ExpectedWarning ("IL2111", nameof (VirtualMethodWithAnnotatedReturnValue), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2111", nameof (VirtualMethodWithAnnotatedReturnValue), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency (DynamicallyAccessedMemberTypes.PublicMethods, typeof (AnnotatedMethodReturnValue))] static void DynamicDependency () { @@ -443,8 +442,7 @@ static void DynamicDependencyByNameOnInstance () { } - // DynamicDependency is not supported yet in the analyzer https://github.com/dotnet/runtime/issues/83080 - [ExpectedWarning ("IL2111", nameof (VirtualMethodWithAnnotatedReturnValue), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2111", nameof (VirtualMethodWithAnnotatedReturnValue), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency (nameof (VirtualMethodWithAnnotatedReturnValue), typeof (AnnotatedMethodReturnValue))] static void DynamicDependencyByNameOnVirtual () { @@ -483,8 +481,7 @@ static void LdTokenOnStatic () Expression _ = () => StaticMethodWithAnnotatedReturnValue (); } - // https://github.com/dotnet/linker/issues/3172 - [ExpectedWarning ("IL2111", nameof (VirtualMethodWithAnnotatedReturnValue), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2111", nameof (VirtualMethodWithAnnotatedReturnValue), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/3172")] static void LdTokenOnVirtual () { Expression> _ = (a) => a.VirtualMethodWithAnnotatedReturnValue (); @@ -527,7 +524,7 @@ class AnnotatedProperty public virtual Type VirtualProperty4WithAnnotation { get => null; set { value.ToString (); } } public static Type Property5WithAnnotationOnMembers { - [ExpectedWarning ("IL2078", nameof (Property5WithAnnotationOnMembers) + ".get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2078", nameof (Property5WithAnnotationOnMembers) + ".get", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101191")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicEvents)] get; [param: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicEvents)] @@ -596,13 +593,13 @@ static void AnnotatedAttributeProperty () } // DynamicDependency is not supported yet in the analyzer https://github.com/dotnet/runtime/issues/83080 - [ExpectedWarning ("IL2111", nameof (Property1WithAnnotation) + ".set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2111", nameof (VirtualProperty3WithAnnotationGetterOnly) + ".get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2111", nameof (VirtualProperty4WithAnnotation) + ".get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2111", nameof (VirtualProperty4WithAnnotation) + ".set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2111", nameof (Property5WithAnnotationOnMembers) + ".set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2111", nameof (VirtualProperty6WithAnnotationOnMembers) + ".get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2111", nameof (VirtualProperty6WithAnnotationOnMembers) + ".set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2111", nameof (Property1WithAnnotation) + ".set", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] + [ExpectedWarning ("IL2111", nameof (VirtualProperty3WithAnnotationGetterOnly) + ".get", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] + [ExpectedWarning ("IL2111", nameof (VirtualProperty4WithAnnotation) + ".get", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] + [ExpectedWarning ("IL2111", nameof (VirtualProperty4WithAnnotation) + ".set", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] + [ExpectedWarning ("IL2111", nameof (Property5WithAnnotationOnMembers) + ".set", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] + [ExpectedWarning ("IL2111", nameof (VirtualProperty6WithAnnotationOnMembers) + ".get", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] + [ExpectedWarning ("IL2111", nameof (VirtualProperty6WithAnnotationOnMembers) + ".set", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency (DynamicallyAccessedMemberTypes.PublicProperties, typeof (AnnotatedProperty))] static void DynamicDependency () { @@ -685,15 +682,15 @@ static void DynamicallyAccessedMembersAll2 () typeof (AnnotatedProperty).RequiresAll (); } - // Analyzer doesn't produce this warning https://github.com/dotnet/linker/issues/2628 - [ExpectedWarning ("IL2110", nameof (Property1WithAnnotation), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // Analyzer doesn't produce this warning + [ExpectedWarning ("IL2110", nameof (Property1WithAnnotation), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2628")] static void DynamicallyAccessedFields () { typeof (AnnotatedProperty).RequiresNonPublicFields (); } - // Action delegate is not handled correctly https://github.com/dotnet/runtime/issues/84918 - [ExpectedWarning ("IL2111", nameof (Property1WithAnnotation), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // Analyzer doesn't recognize Linq.Expressions + [ExpectedWarning ("IL2111", nameof (Property1WithAnnotation) + ".set", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101148")] static void LdToken () { Expression> _ = () => Property1WithAnnotation; @@ -835,8 +832,7 @@ static void DynamicallyAccessedMembersAll2 () typeof (AnnotationOnGenerics).RequiresAll (); } - // https://github.com/dotnet/linker/issues/3172 - [ExpectedWarning ("IL2111", "GenericWithAnnotatedMethod", "AnnotatedMethod", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2111", ["GenericWithAnnotatedMethod", "AnnotatedMethod"], Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/3172")] static void LdToken () { // Note that this should warn even though the code looks "Correct" @@ -867,13 +863,13 @@ struct ValueWithAnnotatedField public Type _typeField; } - // Analyzer doesn't take into account interop attributes https://github.com/dotnet/linker/issues/2562 - [ExpectedWarning ("IL2110", nameof (ValueWithAnnotatedField._typeField), ProducedBy = Tool.Trimmer)] + // Analyzer doesn't take into account interop attributes + [ExpectedWarning ("IL2110", nameof (ValueWithAnnotatedField._typeField), Tool.Trimmer, "https://github.com/dotnet/linker/issues/2562")] [DllImport ("nonexistent")] static extern ValueWithAnnotatedField GetValueWithAnnotatedField (); - // Analyzer doesn't take into account interop attributes https://github.com/dotnet/linker/issues/2562 - [ExpectedWarning ("IL2110", nameof (ValueWithAnnotatedField._typeField), ProducedBy = Tool.Trimmer)] + // Analyzer doesn't take into account interop attributes + [ExpectedWarning ("IL2110", nameof (ValueWithAnnotatedField._typeField), Tool.Trimmer, "https://github.com/dotnet/linker/issues/2562")] [DllImport ("nonexistent")] static extern void AcceptValueWithAnnotatedField (ValueWithAnnotatedField value); @@ -899,29 +895,28 @@ class DelegateCreation static void TestField () { var d = new UnannotatedDelegate (field); - d(typeof(int)); + d (typeof (int)); } static void TestProperty () { var d = new UnannotatedDelegate (Property); - d(typeof(int)); + d (typeof (int)); } [ExpectedWarning ("IL2111")] static void TestLambda () { var d = new UnannotatedDelegate ( - ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type t) => - { }); - d(typeof(int)); + ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type t) => { }); + d (typeof (int)); } [ExpectedWarning ("IL2111", "LocalMethod")] static void TestLocalMethod () { var d = new UnannotatedDelegate (LocalMethod); - d(typeof(int)); + d (typeof (int)); void LocalMethod ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) @@ -931,14 +926,14 @@ void LocalMethod ( static void TestMethodReturnValue () { var d = new UnannotatedDelegate (MethodReturnValue ()); - d(typeof(int)); + d (typeof (int)); } static void TestEvent () { var d = new UnannotatedDelegate (Event); - d(typeof(int)); + d (typeof (int)); } public static void Test () @@ -954,6 +949,39 @@ public static void Test () } } + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] + public class DamOnTypeAccessesMembers + { + public DamOnTypeAccessesMembers() { } + + [RequiresDynamicCode ("--AnnotatedType--")] + [RequiresUnreferencedCode("--AnnotatedType--")] + public class AnnotatedType + { + [ExpectedWarning("IL2112", [nameof(AnnotatedType), "requires unreferenced code", "--AnnotatedType--"], Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/102002")] + public AnnotatedType () { } + } + + [ExpectedWarning("IL2114", nameof(MethodWithDataflow), nameof(DynamicallyAccessedMembersAttribute), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/102002")] + public void MethodWithDataflow ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { } + + [RequiresDynamicCode ("--MethodWithRequires--")] + [RequiresUnreferencedCode("--MethodWithRequires--")] + [RequiresAssemblyFiles("--MethodWithRequires--")] + [ExpectedWarning("IL2112", "requires unreferenced code", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/102002")] + public void MethodWithRequires () { } + + public static void Test () + { + var o = new DamOnTypeAccessesMembers (); + var t = o.GetType (); + t.RequiresAll(); + t.ToString (); + // This triggers the warnings in the analyzer, but not Object.GetType() on DamOnTypeAccessesMembers + //typeof(DamOnTypeAccessesMembers).RequiresAll(); + } + } + class TestType { } [RequiresUnreferencedCode ("--RequiresUnreferencedCodeType--")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaUnsafeAccessor.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaUnsafeAccessor.cs index 9b8cd8959651..eb016da603f4 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaUnsafeAccessor.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaUnsafeAccessor.cs @@ -54,7 +54,7 @@ private static void MethodWithAnnotationMismatch ([DynamicallyAccessedMembers (D private static Type FieldWithAnnotationMismatch; } - [ExpectedWarning ("IL2111", ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2111", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/101195")] [UnsafeAccessor (UnsafeAccessorKind.StaticMethod)] extern static void MethodWithAnnotatedParameter (Target target, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type); @@ -63,23 +63,23 @@ private static void MethodWithAnnotationMismatch ([DynamicallyAccessedMembers (D [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] extern static Type StaticMethodWithAnnotatedReturnValue (Target target); - [ExpectedWarning ("IL2111", ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2111", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/101195")] [UnsafeAccessor (UnsafeAccessorKind.Method)] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] extern static Type VirtualMethodWithAnnotatedReturnValue (Target target); - [ExpectedWarning ("IL2110", ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2110", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/101195")] [UnsafeAccessor (UnsafeAccessorKind.StaticField)] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] extern static ref Type AnnotatedField (Target target); - [ExpectedWarning ("IL2111", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2067", ProducedBy = Tool.NativeAot)] + [UnexpectedWarning ("IL2111", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/101195")] + [ExpectedWarning ("IL2067", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101195")] [UnsafeAccessor (UnsafeAccessorKind.StaticMethod)] extern static void MethodWithAnnotationMismatch (Target target, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] Type type); - [ExpectedWarning ("IL2110", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2078", ProducedBy = Tool.NativeAot)] + [UnexpectedWarning ("IL2110", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/101195")] + [ExpectedWarning ("IL2078", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101195")] [UnsafeAccessor (UnsafeAccessorKind.StaticField)] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] extern static ref Type FieldWithAnnotationMismatch (Target target); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ArrayDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ArrayDataFlow.cs index 1fc103037b38..8da3ce7d97ad 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ArrayDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ArrayDataFlow.cs @@ -117,13 +117,9 @@ static void TestArraySetElementOneElementMix () arr[0].RequiresAll (); } - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] - // https://github.com/dotnet/linker/issues/2737 - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "https://github.com/dotnet/linker/issues/2737")] + [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "https://github.com/dotnet/linker/issues/2737")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2737")] static void TestArraySetElementOneElementMerged () { Type[] arr = new Type[1]; @@ -210,14 +206,9 @@ static void TestGetElementAtUnknownIndex (int i = 0) arr[i].RequiresPublicFields (); } - // https://github.com/dotnet/runtime/issues/93416 tracks the discrepancy between - // the analyzer and ILLink/ILCompiler. - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (GetMethods), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetFields), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/93416")] + [ExpectedWarning ("IL2072", [nameof (GetMethods), nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "https://github.com/dotnet/runtime/issues/93416")] + [ExpectedWarning ("IL2072", [nameof (GetFields), nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "https://github.com/dotnet/runtime/issues/93416")] static void TestGetMergedArrayElement (bool b = true) { Type[] arr = new Type[] { GetMethods () }; @@ -227,8 +218,8 @@ static void TestGetMergedArrayElement (bool b = true) arr[0].RequiresAll (); } - // Trimmer code doesnt handle locals from different branches separetely, therefore merges incorrectly GetMethods with Unknown producing both warnings - [ExpectedWarning ("IL2072", nameof (ArrayDataFlow.GetMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // Trimmer code doesn't handle locals from different branches separately, therefore merges incorrectly GetMethods with Unknown producing both warnings + [UnexpectedWarning ("IL2072", nameof (ArrayDataFlow.GetMethods), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/93416")] [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll))] static void TestMergedArrayElementWithUnknownIndex (int i) { @@ -251,10 +242,8 @@ static void TestArrayResetStoreUnknownIndex (int i = 0) arr[0].RequiresPublicFields (); // Warns } - // https://github.com/dotnet/linker/issues/2680 - analyzer doesn't reset array in this case - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - // https://github.com/dotnet/linker/issues/2680 - analyzer doesn't reset array in this case - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2680")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2680")] static void TestArrayResetGetElementOnByRefArray (int i = 0) { Type[] arr = new Type[] { typeof (TestType), typeof (TestType) }; @@ -285,8 +274,7 @@ static void TestArrayResetAfterCall () static void TakesTypesArray (Type[] types) { } - // https://github.com/dotnet/linker/issues/2680 - // [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields))] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.None, "https://github.com/dotnet/linker/issues/2680")] static void TestArrayResetAfterAssignment () { Type[] arr = new Type[] { typeof (TestType) }; @@ -314,6 +302,10 @@ static void ConsumeArray (object[] a) { } static Type[] _externalArray; + /// + /// These tests are for tracking dataflow values through multi-dimensional arrays. We likely won't support this anytime soon. + /// UnexpectedWarnings here are for the ideal behavior if tracking through multidimensional arrays was supported. They can be treated more as ExpectedWarnings. + /// static class TestMultiDimensionalArray { public static void Test () @@ -344,9 +336,9 @@ public static void Test () TestAddressOfElement (); } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestArrayWithInitializerOneElementStaticType () { Type[,] arr = new Type[,] { { typeof (TestType) } }; @@ -354,9 +346,9 @@ static void TestArrayWithInitializerOneElementStaticType () arr[0, 1].RequiresPublicMethods (); // Should warn - unknown value at this index } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestArrayWithInitializerOneElementParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type type) { Type[,] arr = new Type[,] { { type } }; @@ -364,11 +356,11 @@ static void TestArrayWithInitializerOneElementParameter ([DynamicallyAccessedMem arr[0, 1].RequiresPublicMethods (); // Should warn - unknown value at this index } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] // Below are because we do not handle Multi dimensional arrays - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestArrayWithInitializerMultipleElementsStaticType () { Type[,] arr = new Type[,] { { typeof (TestType), typeof (TestType), typeof (TestType) } }; @@ -379,13 +371,12 @@ static void TestArrayWithInitializerMultipleElementsStaticType () } // Bug - // [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] // Below are because we do not handle Multi dimensional arrays - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestArrayWithInitializerMultipleElementsMix<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties)] TProperties> ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type typeAll) { @@ -397,9 +388,9 @@ static void TestArrayWithInitializerMultipleElementsStaticType () arr[0, 3].RequiresPublicMethods (); // Should warn - unknown value at this index } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestArraySetElementOneElementStaticType () { Type[,] arr = new Type[1, 1]; @@ -408,9 +399,8 @@ static void TestArraySetElementOneElementStaticType () arr[0, 1].RequiresPublicMethods (); // Should warn - unknown value at this index } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestArraySetElementOneElementParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type type) { Type[,] arr = new Type[1, 1]; @@ -419,11 +409,10 @@ static void TestArraySetElementOneElementParameter ([DynamicallyAccessedMembers arr[0, 1].RequiresPublicMethods (); // Should warn - unknown value at this index } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - // Below are because we do not handle Multi dimensional arrays - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestArraySetElementMultipleElementsStaticType () { Type[,] arr = new Type[1, 3]; @@ -437,13 +426,12 @@ static void TestArraySetElementMultipleElementsStaticType () } // Bug - // [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] // Below are because we do not handle Multi dimensional arrays - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestArraySetElementMultipleElementsMix<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties)] TProperties> ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type typeAll) { @@ -459,13 +447,11 @@ static void TestArraySetElementMultipleElementsStaticType () } // Bug - // [ExpectedWarning ("IL2087", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - // Below are because we do not handle Multi dimensional arrays - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestArraySetElementAndInitializerMultipleElementsMix<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties)] TProperties> ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type typeAll) { @@ -479,16 +465,15 @@ static void TestArraySetElementMultipleElementsStaticType () arr[0, 3].RequiresPublicMethods (); // Should warn - unknown value at this index } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestGetElementAtUnknownIndex (int i = 0) { Type[,] arr = new Type[,] { { typeof (TestType) } }; arr[0, i].RequiresPublicFields (); } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestArrayResetStoreUnknownIndex (int i = 0) { Type[,] arr = new Type[,] { { typeof (TestType) } }; @@ -499,12 +484,10 @@ static void TestArrayResetStoreUnknownIndex (int i = 0) arr[0, 0].RequiresPublicFields (); // Warns } - // https://github.com/dotnet/linker/issues/2680 - analyzer doesn't reset array in this case - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // Analyzer doesn't reset array in this case + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2680")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestArrayResetGetElementOnByRefArray (int i = 0) { Type[,] arr = new Type[,] { { typeof (TestType) } }; @@ -519,9 +502,9 @@ static void TestArrayResetGetElementOnByRefArray (int i = 0) static void TakesTypeByRef (ref Type type) { } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestArrayResetAfterCall () { Type[,] arr = new Type[,] { { typeof (TestType) } }; @@ -536,10 +519,9 @@ static void TestArrayResetAfterCall () static void TakesTypesArray (Type[,] types) { } - // https://github.com/dotnet/linker/issues/2680 - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2680")] // Multidimensional Arrays not handled -- assumed to be UnknownValue - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicProperties), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestArrayResetAfterAssignment () { Type[,] arr = new Type[,] { { typeof (TestType) } }; @@ -553,7 +535,7 @@ static void TestArrayResetAfterAssignment () arr[0, 0].RequiresPublicFields (); // Should warn } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101951")] static void TestAddressOfElement () { Type[,] arr = new Type[,] { { typeof (TestType) } }; @@ -566,13 +548,9 @@ static void TestAddressOfElement () class WriteCapturedArrayElement { - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] - // https://github.com/dotnet/linker/issues/2737 - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "https://github.com/dotnet/linker/issues/2737")] + [UnexpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "https://github.com/dotnet/linker/issues/2737")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2737")] static void TestNullCoalesce () { Type[] arr = new Type[1]; @@ -590,11 +568,8 @@ static void TestNullCoalescingAssignment () arr[0].RequiresAll (); } - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] - // https://github.com/dotnet/linker/issues/2746 - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "https://github.com/dotnet/linker/issues/2746")] + [UnexpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2746")] static void TestNullCoalescingAssignmentToEmpty () { Type[] arr = new Type[1]; @@ -603,11 +578,9 @@ static void TestNullCoalescingAssignmentToEmpty () } [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll))] - // https://github.com/dotnet/linker/issues/2746 (ILLink produces incomplete set of IL2072 warnings) - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll), - ProducedBy = Tool.Analyzer)] + // (ILLink produces incomplete set of IL2072 warnings) + [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "https://github.com/dotnet/linker/issues/2746")] + [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "https://github.com/dotnet/linker/issues/2746")] static void TestNullCoalescingAssignmentComplex () { Type[] arr = new Type[1]; @@ -617,8 +590,9 @@ static void TestNullCoalescingAssignmentComplex () } // ILLink only incidentally matches the analyzer behavior here. - // https://github.com/dotnet/linker/issues/2737 - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll))] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/linker/issues/2737")] + [ExpectedWarning("IL2072", nameof(GetUnknownType), nameof(DataFlowTypeExtensions.RequiresAll), Tool.None, "https://github.com/dotnet/linker/issues/2737")] + [ExpectedWarning("IL2072", nameof(GetTypeWithPublicConstructors), nameof(DataFlowTypeExtensions.RequiresAll), Tool.None, "https://github.com/dotnet/linker/issues/2737")] static void TestNullCoalescingAssignmentToEmptyComplex () { Type[] arr = new Type[1]; @@ -641,7 +615,8 @@ class WriteElementOfCapturedArray [Kept] [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll))] [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll))] - // Analysis hole: https://github.com/dotnet/runtime/issues/90335 + [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll), Tool.None, "https://github.com/dotnet/runtime/issues/90335")] + // Analysis hole: // The array element assignment assigns to a temp array created as a copy of // arr1 or arr2, and writes to it aren't reflected back in arr1/arr2. static void TestArrayElementAssignment (bool b = true) @@ -690,8 +665,10 @@ static void TestInlineArrayElementReferenceAssignment (bool b = true) [ExpectedWarning ("IL2087", nameof (T), nameof (DataFlowTypeExtensions.RequiresAll))] [ExpectedWarning ("IL2087", nameof (U), nameof (DataFlowTypeExtensions.RequiresPublicFields))] + [ExpectedWarning ("IL2087", nameof (V), nameof (DataFlowTypeExtensions.RequiresAll), Tool.None, "https://github.com/dotnet/linker/issues/2158")] + [ExpectedWarning ("IL2087", nameof (V), nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.None, "https://github.com/dotnet/linker/issues/2158")] // Missing warnings for 'V' possibly assigned to arr or arr2 because write to temp - // array isn't reflected back in the local variables. https://github.com/dotnet/linker/issues/2158 + // array isn't reflected back in the local variables. static void TestNullCoalesce (bool b = false) { Type[]? arr = new Type[1] { typeof (T) }; @@ -702,16 +679,18 @@ static void TestNullCoalesce (bool b = false) arr2[0].RequiresPublicFields (); } - [ExpectedWarning ("IL2087", nameof (T), nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2087", nameof (T), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "https://github.com/dotnet/runtime/issues/93416")] [ExpectedWarning ("IL2087", nameof (U), nameof (DataFlowTypeExtensions.RequiresPublicFields))] // Missing warnings for 'V' possibly assigned to arr or arr2 because write to temp // array isn't reflected back in the local variables. https://github.com/dotnet/linker/issues/2158 + [ExpectedWarning ("IL2087", nameof (V), nameof (DataFlowTypeExtensions.RequiresAll), Tool.None, "https://github.com/dotnet/linker/issues/2158")] + [ExpectedWarning ("IL2087", nameof (V), nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.None, "https://github.com/dotnet/linker/issues/2158")] // This also causes an extra analyzer warning for 'U' in 'arr', because the analyzer models the // possible assignment of arr2 to arr, without overwriting index '0'. And it produces a warning // for each possible value, unlike ILLink/ILCompiler, which produce an unknown value for a merged // array value: https://github.com/dotnet/runtime/issues/93416 - [ExpectedWarning ("IL2087", nameof (U), nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2087", nameof (U), nameof (DataFlowTypeExtensions.RequiresAll), Tool.Analyzer, "https://github.com/dotnet/runtime/issues/93416")] + [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/93416")] static void TestNullCoalescingAssignment (bool b = true) { Type[]? arr = new Type[1] { typeof (T) }; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AssemblyQualifiedNameDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AssemblyQualifiedNameDataflow.cs index f2c0f5185f5c..4a3689cda9e6 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AssemblyQualifiedNameDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AssemblyQualifiedNameDataflow.cs @@ -58,10 +58,7 @@ static void TestConstructors () RequireNothing (type); } - [ExpectedWarning ("IL2105", - "Type 'System.Invalid.TypeName' was not found in the caller assembly nor in the base library. " + - "Type name strings used for dynamically accessing a type should be assembly qualified.", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2105", "Type 'System.Invalid.TypeName' was not found in the caller assembly nor in the base library. " + "Type name strings used for dynamically accessing a type should be assembly qualified.", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")] static void TestUnqualifiedTypeNameWarns () { RequirePublicConstructors ("System.Invalid.TypeName"); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeConstructorDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeConstructorDataflow.cs index 4611e06773df..b4e991b9928c 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeConstructorDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeConstructorDataflow.cs @@ -8,8 +8,7 @@ using Mono.Linker.Tests.Cases.Expectations.Assertions; [assembly: KeptAttributeAttribute (typeof (AttributeConstructorDataflow.KeepsPublicPropertiesAttribute))] -// https://github.com/dotnet/linker/issues/2273 -[assembly: ExpectedWarning ("IL2026", "--ClassWithKeptPublicProperties--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] +[assembly: ExpectedWarning ("IL2026", "--ClassWithKeptPublicProperties--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2273")] [assembly: AttributeConstructorDataflow.KeepsPublicProperties (typeof (AttributeConstructorDataflow.ClassWithKeptPublicProperties))] namespace Mono.Linker.Tests.Cases.DataFlow @@ -26,8 +25,7 @@ class AttributeConstructorDataflow [KeepsPublicMethods ("Mono.Linker.Tests.Cases.DataFlow.AttributeConstructorDataflow+ClassWithKeptPublicMethods")] [KeepsPublicFields (null, null)] [TypeArray (new Type[] { typeof (AttributeConstructorDataflow) })] - // https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2273")] public static void Main () { typeof (AttributeConstructorDataflow).GetMethod ("Main").GetCustomAttribute (typeof (KeepsPublicConstructorAttribute)); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeFieldDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeFieldDataflow.cs index e581797e2347..7d0a08861b59 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeFieldDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributeFieldDataflow.cs @@ -41,7 +41,7 @@ public static void TestKeepsPublicMethods () [Kept] [KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))] // Trimmer/NativeAot only for now - https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")] [KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributeFieldDataflow+ClassWithKeptPublicMethods")] public static void TestKeepsPublicMethodsString () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributePropertyDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributePropertyDataflow.cs index f953784dc375..e56d961102c4 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributePropertyDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AttributePropertyDataflow.cs @@ -55,8 +55,8 @@ public static void TestKeepsPublicMethods () [Kept] [KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))] - // Trimmer/NativeAot only for now - https://github.com/dotnet/runtime/issues/95118 - [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethodsKeptByName--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // Trimmer/NativeAot only for now + [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethodsKeptByName--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")] [KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributesOnMethod+ClassWithKeptPublicMethodsKeptByName")] public static void TestKeepsPublicMethodsByName () { @@ -211,8 +211,8 @@ class AttributeWithConditionalExpression { [Kept] [KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))] - // Trimmer/NativeAot only for now - https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // Trimmer/NativeAot only for now + [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")] [KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethods" : null)] public static void Test () { @@ -224,7 +224,7 @@ public static void Test () // where the owning symbol is not a method. [Kept] [KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))] - [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")] [KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethods" : null)] public static int field; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ByRefDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ByRefDataflow.cs index d00af37b2beb..a268d1f70b2e 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ByRefDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ByRefDataflow.cs @@ -45,13 +45,13 @@ public static void Main () static Type s_typeWithPublicParameterlessConstructor; [Kept] - // Trimmer and analyzer use different formats for ref parameters: https://github.com/dotnet/linker/issues/2406 - [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(Type&)", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(ref Type)", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2069", nameof (s_typeWithPublicParameterlessConstructor), "parameter 'type'", nameof (MethodWithRefParameter), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // Trimmer and analyzer use different formats for ref parameters + [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(Type&)", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2406")] + [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(ref Type)", Tool.Analyzer, "https://github.com/dotnet/linker/issues/2406")] + [ExpectedWarning ("IL2069", [nameof (s_typeWithPublicParameterlessConstructor), "parameter 'type'", nameof (MethodWithRefParameter)], Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101955")] // MethodWithRefParameter (ref x) - [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(Type&)", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(ref Type)", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(Type&)", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2406")] + [ExpectedWarning ("IL2077", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(ref Type)", Tool.Analyzer, "https://github.com/dotnet/linker/issues/2406")] public static void PassRefToField () { MethodWithRefParameter (ref s_typeWithPublicParameterlessConstructor); @@ -60,9 +60,9 @@ public static void PassRefToField () } [Kept] - // Trimmer and analyzer use different formats for ref parameters: https://github.com/dotnet/linker/issues/2406 - [ExpectedWarning ("IL2067", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(Type&)", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2067", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(ref Type)", ProducedBy = Tool.Analyzer)] + // Trimmer and analyzer use different formats for ref parameters: + [ExpectedWarning ("IL2067", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(Type&)", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2406")] + [ExpectedWarning ("IL2067", nameof (ByRefDataflow) + "." + nameof (MethodWithRefParameter) + "(ref Type)", Tool.Analyzer, "https://github.com/dotnet/linker/issues/2406")] public static void PassRefToParameter (Type parameter) { MethodWithRefParameter (ref parameter); @@ -181,9 +181,8 @@ static void TwoOutRefs ( } [Kept] - // https://github.com/dotnet/runtime/issues/85464 - [ExpectedWarning ("IL2069", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2069", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85464")] + [ExpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85464")] public static void Test () { TwoOutRefs (out _publicMethodsField, out _publicPropertiesField); @@ -243,13 +242,13 @@ static void TestLocalAssignment (bool b = true) } [Kept] - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] - // ILLink/ILCompiler produce different warning code: https://github.com/dotnet/linker/issues/2737 - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // ILLink/ILCompiler produce different warning code: + [ExpectedWarning ("IL2072", [nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "https://github.com/dotnet/linker/issues/2737")] + [ExpectedWarning ("IL2072", [nameof (GetTypeWithPublicConstructors), nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "https://github.com/dotnet/linker/issues/2737")] + [ExpectedWarning ("IL2072", [nameof (GetTypeWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "https://github.com/dotnet/linker/issues/2737")] + [ExpectedWarning ("IL2072", [nameof (GetTypeWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "https://github.com/dotnet/linker/issues/2737")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2737")] + [UnexpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2737")] static void TestArrayElementReferenceAssignment (bool b = true) { var arr1 = new Type[] { GetUnknownType () }; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs index cb609bc59060..2c40b8f45513 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs @@ -39,10 +39,8 @@ public static IEnumerable BaseIteratorWithCorrectDataflow () } } - [ExpectedWarning ("IL2120", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2120", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2120", ["<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "MoveNext"], Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2120", ["<" + nameof (BaseIteratorWithCorrectDataflow) + ">", ""], Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] class IteratorStateMachines : BaseTypeWithIteratorStateMachines { @@ -52,22 +50,17 @@ public static IEnumerable IteratorWithoutDataflow () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", - ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", - ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL2119", "<" + nameof (IteratorCallsMethodWithRequires) + ">", "MoveNext", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT specific warnings", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT specific warnings", CompilerGeneratedCode = true)] + [UnexpectedWarning ("IL2119", "<" + nameof (IteratorCallsMethodWithRequires) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042", CompilerGeneratedCode = true)] public static IEnumerable IteratorCallsMethodWithRequires () { yield return 0; MethodWithRequires (); } - [ExpectedWarning ("IL2119", "<" + nameof (IteratorWithCorrectDataflow) + ">", "MoveNext", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2119", "", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2119", "<" + nameof (IteratorWithCorrectDataflow) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042", CompilerGeneratedCode = true)] + [UnexpectedWarning ("IL2119", "", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042", CompilerGeneratedCode = true)] public static IEnumerable IteratorWithCorrectDataflow () { var t_IteratorWithCorrectDataflow = GetAll (); @@ -75,10 +68,8 @@ public static IEnumerable IteratorWithCorrectDataflow () t_IteratorWithCorrectDataflow.RequiresAll (); } - [ExpectedWarning ("IL2119", "<" + nameof (IteratorWithIntegerDataflow) + ">", "MoveNext", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2119", "", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2119", "<" + nameof (IteratorWithIntegerDataflow) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042", CompilerGeneratedCode = true)] + [UnexpectedWarning ("IL2119", "", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042", CompilerGeneratedCode = true)] public static IEnumerable IteratorWithIntegerDataflow () { int integerLocal = 0; @@ -87,10 +78,8 @@ public static IEnumerable IteratorWithIntegerDataflow () types[integerLocal].RequiresPublicMethods (); } - [ExpectedWarning ("IL2119", "<" + nameof (IteratorWithProblematicDataflow) + ">", "MoveNext", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2119", "", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2119", "<" + nameof (IteratorWithProblematicDataflow) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042", CompilerGeneratedCode = true)] + [UnexpectedWarning ("IL2119", "", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042", CompilerGeneratedCode = true)] [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true)] public static IEnumerable IteratorWithProblematicDataflow () { @@ -99,25 +88,22 @@ public static IEnumerable IteratorWithProblematicDataflow () t_IteratorWithProblematicDataflow.RequiresAll (); } - [ExpectedWarning ("IL2112", nameof (RUCTypeWithIterators) + "()", "--RUCTypeWithIterators--", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // warning about .ctor + [ExpectedWarning ("IL2112", nameof (RUCTypeWithIterators) + "()", "--RUCTypeWithIterators--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/102002", CompilerGeneratedCode = true)] // warning about .ctor [RequiresUnreferencedCode ("--RUCTypeWithIterators--")] class RUCTypeWithIterators { - [ExpectedWarning ("IL2112", nameof (StaticIteratorCallsMethodWithRequires) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2112", nameof (StaticIteratorCallsMethodWithRequires) + "()", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/102002")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warning", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warning", CompilerGeneratedCode = true)] public static IEnumerable StaticIteratorCallsMethodWithRequires () { yield return 0; MethodWithRequires (); } - [ExpectedWarning ("IL2112", nameof (InstanceIteratorCallsMethodWithRequires) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2112", nameof (InstanceIteratorCallsMethodWithRequires) + "()", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/102002")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warning", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warning", CompilerGeneratedCode = true)] public IEnumerable InstanceIteratorCallsMethodWithRequires () { yield return 0; @@ -125,32 +111,23 @@ public IEnumerable InstanceIteratorCallsMethodWithRequires () } } - [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithProblematicDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (IteratorCallsMethodWithRequires) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithCorrectDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithIntegerDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2118", "<" + nameof (IteratorWithProblematicDataflow) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (IteratorCallsMethodWithRequires) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (IteratorWithCorrectDataflow) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (IteratorWithIntegerDataflow) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] [ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators) + "()", "--RUCTypeWithIterators--")] // Expect to see warnings about RUC on type, for all static state machine members. [ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators.StaticIteratorCallsMethodWithRequires) + "()", "--RUCTypeWithIterators--")] [ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators.InstanceIteratorCallsMethodWithRequires) + "()")] - [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithCorrectDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithProblematicDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2118", "<" + nameof (IteratorWithCorrectDataflow) + ">", "", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (IteratorWithProblematicDataflow) + ">", "", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] // Technically the access to IteratorWithIntegerDataflow should warn about access to the integer // field integerLocal, but our heuristics only warn if the field type satisfies the // "IsTypeInterestingForDatafllow" check. This is likely good enough because in most cases the // compiler-generated code will have other hoisted fields with types that _are_ interesting for dataflow. - [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithIntegerDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2118", "<" + nameof (IteratorWithIntegerDataflow) + ">", "", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] public static void Test (IteratorStateMachines test = null) { typeof (IteratorStateMachines).RequiresAll (); @@ -166,8 +143,8 @@ public static async Task AsyncWithoutDataflow () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings", CompilerGeneratedCode = true)] public static async Task AsyncCallsMethodWithRequires () { MethodWithRequires (); @@ -186,16 +163,11 @@ public static async Task AsyncWithProblematicDataflow () t_AsyncWithProblematicDataflow.RequiresAll (); } - [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithProblematicDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncCallsMethodWithRequires) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithCorrectDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithCorrectDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithProblematicDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2118", "<" + nameof (AsyncWithProblematicDataflow) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (AsyncCallsMethodWithRequires) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (AsyncWithCorrectDataflow) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (AsyncWithCorrectDataflow) + ">", "", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (AsyncWithProblematicDataflow) + ">", "", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] public static void Test () { typeof (AsyncStateMachines).RequiresAll (); @@ -210,8 +182,8 @@ public static async IAsyncEnumerable AsyncIteratorWithoutDataflow () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings", CompilerGeneratedCode = true)] public static async IAsyncEnumerable AsyncIteratorCallsMethodWithRequires () { yield return await MethodAsync (); @@ -233,16 +205,11 @@ public static async IAsyncEnumerable AsyncIteratorWithProblematicDataflow ( t.RequiresAll (); } - [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithProblematicDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorCallsMethodWithRequires) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithCorrectDataflow) + ">", "MoveNext", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithCorrectDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithProblematicDataflow) + ">", "", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithProblematicDataflow) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (AsyncIteratorCallsMethodWithRequires) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithCorrectDataflow) + ">", "MoveNext", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithCorrectDataflow) + ">", "", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithProblematicDataflow) + ">", "", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] public static void Test () { typeof (AsyncIteratorStateMachines).RequiresAll (); @@ -262,10 +229,9 @@ static void LambdaCallsMethodWithRequires () { var lambda = [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL2119", "<" + nameof (LambdaCallsMethodWithRequires) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + [UnexpectedWarning ("IL2119", "<" + nameof (LambdaCallsMethodWithRequires) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] () => MethodWithRequires (); lambda (); } @@ -273,8 +239,7 @@ static void LambdaCallsMethodWithRequires () static void LambdaWithCorrectDataflow () { var lambda = - [ExpectedWarning ("IL2119", "<" + nameof (LambdaWithCorrectDataflow) + ">", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2119", "<" + nameof (LambdaWithCorrectDataflow) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] () => { var t = GetAll (); t.RequiresAll (); @@ -295,8 +260,7 @@ static void LambdaWithCorrectParameter () static void LambdaWithProblematicDataflow () { var lambda = - [ExpectedWarning ("IL2119", "<" + nameof (LambdaWithProblematicDataflow) + ">", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2119", "<" + nameof (LambdaWithProblematicDataflow) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll))] () => { var t = GetWithPublicMethods (); @@ -309,8 +273,7 @@ static void LambdaWithCapturedTypeToDAM () { var t = GetWithPublicMethods (); var lambda = - [ExpectedWarning ("IL2119", "<" + nameof (LambdaWithCapturedTypeToDAM) + ">", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2119", "<" + nameof (LambdaWithCapturedTypeToDAM) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll))] () => { t.RequiresAll (); @@ -337,29 +300,27 @@ static void LambdaCallsPInvokeTakingObject () { var lambda = [ExpectedWarning ("IL2050")] - [ExpectedWarning ("IL2119", "<" + nameof (LambdaCallsPInvokeTakingObject) + ">", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2119", "<" + nameof (LambdaCallsPInvokeTakingObject) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] () => MethodTakingObject (null); lambda (); } - [ExpectedWarning ("IL2112", nameof (RUCTypeWithLambdas) + "()", "--RUCTypeWithLambdas--", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", nameof (RUCTypeWithLambdas) + "()", "--RUCTypeWithLambdas--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/102002", CompilerGeneratedCode = true)] [RequiresUnreferencedCode ("--RUCTypeWithLambdas--")] class RUCTypeWithLambdas { - [ExpectedWarning ("IL2112", nameof (MethodWithLambdas), "--RUCTypeWithLambdas--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", [nameof (MethodWithLambdas), "--RUCTypeWithLambdas--"], Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/102002")] public void MethodWithLambdas () { var lambda = - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] () => MethodWithRequires (); int i = 0; var lambdaWithCapturedState = - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] () => { i++; MethodWithRequires (); @@ -370,16 +331,11 @@ public void MethodWithLambdas () } } - [ExpectedWarning ("IL2118", "<" + nameof (LambdaCallsPInvokeTakingObject) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (LambdaCallsMethodWithRequires) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithCorrectDataflow) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithProblematicDataflow) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithCapturedTypeToDAM) + ">", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2118", "<" + nameof (LambdaCallsPInvokeTakingObject) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (LambdaCallsMethodWithRequires) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (LambdaWithCorrectDataflow) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (LambdaWithProblematicDataflow) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (LambdaWithCapturedTypeToDAM) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] [ExpectedWarning ("IL2026", nameof (RUCTypeWithLambdas) + "()", "--RUCTypeWithLambdas--")] [ExpectedWarning ("IL2026", nameof (RUCTypeWithLambdas.MethodWithLambdas) + "()", "--RUCTypeWithLambdas--")] public static void Test (Lambdas test = null) @@ -402,18 +358,16 @@ static void LocalFunctionWithoutDataflow () static void LocalFunctionCallsMethodWithRequires () { [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionCallsMethodWithRequires) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + [UnexpectedWarning ("IL2119", "<" + nameof (LocalFunctionCallsMethodWithRequires) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] void LocalFunction () => MethodWithRequires (); LocalFunction (); } static void LocalFunctionWithCorrectDataflow () { - [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithCorrectDataflow) + ">", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithCorrectDataflow) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] void LocalFunction () { var t = GetAll (); @@ -425,8 +379,7 @@ void LocalFunction () static void LocalFunctionWithProblematicDataflow () { [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll))] - [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithProblematicDataflow) + ">", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithProblematicDataflow) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] void LocalFunction () { var t = GetWithPublicMethods (); @@ -438,8 +391,7 @@ void LocalFunction () static void LocalFunctionWithCapturedTypeToDAM () { var t = GetAll (); - [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithCapturedTypeToDAM) + ">", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithCapturedTypeToDAM) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] void LocalFunction () { t.RequiresAll (); @@ -464,32 +416,29 @@ static void LocalFunctionCallsPInvokeTakingPrimitiveType () static void LocalFunctionCallsPInvokeTakingObject () { [ExpectedWarning ("IL2050")] - [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionCallsPInvokeTakingObject) + ">", - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2119", "<" + nameof (LocalFunctionCallsPInvokeTakingObject) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] void LocalFunction () => MethodTakingObject (null); LocalFunction (); } - [ExpectedWarning ("IL2112", nameof (RUCTypeWithLocalFunctions) + "()", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", nameof (RUCTypeWithLocalFunctions) + "()", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/102002", CompilerGeneratedCode = true)] [RequiresUnreferencedCode ("--RUCTypeWithLocalFunctions--")] class RUCTypeWithLocalFunctions { - [ExpectedWarning ("IL2112", nameof (MethodWithLocalFunctions), "--RUCTypeWithLocalFunctions--", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", nameof (MethodWithLocalFunctions), "--RUCTypeWithLocalFunctions--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/102002")] public void MethodWithLocalFunctions () { - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] void LocalFunction () => MethodWithRequires (); - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void StaticLocalFunction () => MethodWithRequires (); int i = 0; - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] void LocalFunctionWithCapturedState () { i++; @@ -502,16 +451,11 @@ void LocalFunctionWithCapturedState () } } - [ExpectedWarning ("IL2118", nameof (LocalFunctionCallsPInvokeTakingObject), - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", nameof (LocalFunctionCallsMethodWithRequires), - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", nameof (LocalFunctionWithCorrectDataflow), - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", nameof (LocalFunctionWithProblematicDataflow), - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", nameof (LocalFunctionWithCapturedTypeToDAM), - ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2118", nameof (LocalFunctionCallsPInvokeTakingObject), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", nameof (LocalFunctionCallsMethodWithRequires), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", nameof (LocalFunctionWithCorrectDataflow), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", nameof (LocalFunctionWithProblematicDataflow), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", nameof (LocalFunctionWithCapturedTypeToDAM), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] // Expect RUC warnings for static, compiler-generated code warnings for instance. [ExpectedWarning ("IL2026", nameof (RUCTypeWithLocalFunctions) + "()", "--RUCTypeWithLocalFunctions--")] [ExpectedWarning ("IL2026", nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + "()")] @@ -648,7 +592,7 @@ static void TestLocalFunctionThroughDelegate () Action a = LocalFunction; a (null); - void LocalFunction ([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + void LocalFunction ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { } } @@ -658,7 +602,7 @@ static void TestGenericLocalFunctionThroughDelegate () Action a = LocalFunction; a (); - void LocalFunction <[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () + void LocalFunction<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { } } @@ -685,10 +629,10 @@ static void Lambda () a (typeof (string)); } - static void LambdaOnGeneric<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T> () + static void LambdaOnGeneric<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { Action a = () => { - typeof(T).GetMethods (); + typeof (T).GetMethods (); }; a (); @@ -698,23 +642,23 @@ static void LocalFunction () { LocalFunctionInner (typeof (string)); - static void LocalFunctionInner ([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + static void LocalFunctionInner ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { type.GetMethods (); } } - static void LocalFunctionOnGeneric<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() + static void LocalFunctionOnGeneric<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { LocalFunctionInner (); static void LocalFunctionInner () { - typeof(T).GetMethods (); + typeof (T).GetMethods (); } } - static IEnumerable IteratorOnGeneric<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() + static IEnumerable IteratorOnGeneric<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { yield return 0; } @@ -730,8 +674,8 @@ static void LocalFunctionInner () await Task.Delay (100); } - [ExpectedWarning ("IL2118", "<" + nameof (LambdaOnGeneric) + ">", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", "<" + nameof (LocalFunctionOnGeneric) + ">", ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2118", "<" + nameof (LambdaOnGeneric) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", "<" + nameof (LocalFunctionOnGeneric) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] public static void Test () { typeof (DAMReflectionAccessToCompilerGeneratedCode).RequiresAll (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs index bae9341ecde8..e0bb05872b84 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs @@ -38,10 +38,8 @@ static IEnumerable FlowAcrossYieldReturn () } // Trimmer tracks all assignments of hoisted locals, so this produces warnings. - [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresPublicFields), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresPublicMethods), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2072", [nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresPublicMethods)], Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static IEnumerable NoFlowAcrossYieldReturn () { Type t = GetWithPublicMethods (); @@ -227,10 +225,8 @@ static async void FlowAcrossAwait () } // Trimmer tracks all assignments of hoisted locals, so this produces warnings. - [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresPublicFields), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresPublicMethods), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async void NoFlowAcrossAwait () { Type t = GetWithPublicMethods (); @@ -447,7 +443,7 @@ public static void ReadCapturedParameterAfterWrite (Type tParameter = null) void LocalFunction () => tParameter.RequiresPublicMethods (); } - [ExpectedWarning ("IL2072", "tParameter", nameof (GetWithPublicFields), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", ["tParameter", nameof (GetWithPublicFields)], Tool.Analyzer, "")] public static void ReadCapturedParameterAfterWriteMismatch ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type tParameter = null) { tParameter = GetWithPublicFields (); @@ -576,7 +572,7 @@ public static void ReadCapturedParameterAfterWrite (Type tParameter = null) lambda (); } - [ExpectedWarning ("IL2072", "tParameter", nameof (GetWithPublicFields), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", ["tParameter", nameof (GetWithPublicFields)], Tool.Analyzer, "")] public static void ReadCapturedParameterAfterWriteMismatch ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type tParameter = null) { tParameter = GetWithPublicFields (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.cs index 2cd0f49317f1..83ae5834cdc9 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssembly.cs @@ -42,7 +42,7 @@ public static void WithLocalFunctionInner () // Analyzer doesn't implement constant propagation and branch removal, so it reaches this code // NativeAOT behavioral difference: // https://github.com/dotnet/runtime/issues/85161 - [ExpectedWarning ("IL2026", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Analyzer | Tool.NativeAot, "")] void LocalWithWarning () { // No warning @@ -64,7 +64,7 @@ public static void WithLocalFunction () // Analyzer doesn't implement constant propagation and branch removal, so it reaches this code // NativeAOT behavioral difference: // https://github.com/dotnet/runtime/issues/85161 - [ExpectedWarning ("IL2026", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Analyzer | Tool.NativeAot, "")] void LocalWithWarning () { Requires (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssemblyWithWarning.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssemblyWithWarning.cs index 2023c19aaa85..30424e3a3f01 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssemblyWithWarning.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeInPreservedAssemblyWithWarning.cs @@ -37,8 +37,7 @@ public static void WithLocalFunctionInner () LocalWithWarning (); } - // https://github.com/dotnet/linker/issues/2937 - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.Trimmer, "https://github.com/dotnet/linker/issues/2937")] void LocalWithWarning () { // Warning! @@ -54,8 +53,7 @@ public static void WithLocalFunction () LocalWithWarning (); } - // https://github.com/dotnet/linker/issues/2937 - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.Trimmer, "https://github.com/dotnet/linker/issues/2937")] void LocalWithWarning () { // No warning diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ComplexTypeHandling.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ComplexTypeHandling.cs index ad29941cae2c..8d72fc68f364 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ComplexTypeHandling.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ComplexTypeHandling.cs @@ -151,7 +151,7 @@ public ArrayCreateInstanceByNameElement () } [Kept] - [ExpectedWarning ("IL2032", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/82447 + [ExpectedWarning ("IL2032", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/82447")] static void TestArrayCreateInstanceByName () { Activator.CreateInstance ("test", "Mono.Linker.Tests.Cases.DataFlow.ComplexTypeHandling+ArrayCreateInstanceByNameElement[]"); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructedTypesDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructedTypesDataFlow.cs index abeed77e1bc0..305811103958 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructedTypesDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructedTypesDataFlow.cs @@ -20,8 +20,7 @@ public static void Main () class DeconstructedVariable { - // https://github.com/dotnet/linker/issues/3158 - [ExpectedWarning ("IL2077", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2077", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/3158")] static void DeconstructVariableNoAnnotation ((Type type, object instance) input) { var (type, instance) = input; @@ -30,8 +29,7 @@ static void DeconstructVariableNoAnnotation ((Type type, object instance) input) static (Type type, object instance) GetInput (int unused) => (typeof (string), null); - // https://github.com/dotnet/linker/issues/3158 - [ExpectedWarning ("IL2077", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2077", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/3158")] static void DeconstructVariableFlowCapture (bool b = true) { // This creates a control-flow graph where the tuple elements assigned to @@ -50,9 +48,8 @@ static void DeconstructVariableFlowCapture (bool b = true) [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] static ref Type AnnotatedProperty => ref annotatedfield; - // https://github.com/dotnet/linker/issues/3158 - [ExpectedWarning ("IL2062", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2078", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2062", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/3158")] + [ExpectedWarning ("IL2078", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/3158")] static void DeconstructVariablePropertyReference ((Type type, object instance) input) { object instance; @@ -72,7 +69,7 @@ record TypeAndInstance ( // For analyzer, this is currently // https://github.com/dotnet/linker/issues/3158 // But it's possible that with that fixed there won't be a warning from the analyzer anyway (depends on the implementation) - [ExpectedWarning ("IL2067", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2067", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/3158")] static void DeconstructRecordWithAnnotation (TypeAndInstance value) { var (type, instance) = value; @@ -118,8 +115,7 @@ static void DeconstructRecordManualWithAnnotation (TypeAndInstanceRecordManual v type.RequiresPublicMethods (); } - // https://github.com/dotnet/linker/issues/3158 - [ExpectedWarning ("IL2067", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2067", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/3158")] static void DeconstructRecordManualWithMismatchAnnotation (TypeAndInstanceRecordManual value) { var (type, instance) = value; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructorDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructorDataFlow.cs index fe0d1af1f62c..12bf90f1b2d6 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructorDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ConstructorDataFlow.cs @@ -39,13 +39,11 @@ public DataFlowInConstructor () [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type annotatedField = GetUnknown (); - [ExpectedWarning ("IL2074", nameof (GetUnknown), nameof (AnnotatedProperty), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/93277 + [ExpectedWarning ("IL2074", nameof (GetUnknown), nameof (AnnotatedProperty), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/93277", CompilerGeneratedCode = true)] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type AnnotatedProperty { get; } = GetUnknown (); - [ExpectedWarning ("IL2074", nameof (GetUnknown), nameof (AnnotatedPropertyWithSetter), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/93277 + [ExpectedWarning ("IL2074", nameof (GetUnknown), nameof (AnnotatedPropertyWithSetter), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/93277", CompilerGeneratedCode = true)] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type AnnotatedPropertyWithSetter { get; set; } = GetUnknown (); @@ -81,12 +79,10 @@ public DataFlowInConstructor () int PropertyWithThrowStatementInInitializer { get; } = string.Empty.Length == 0 ? throw new Exception() : 0; - [ExpectedWarning ("IL2067", nameof (TryGetUnknown), nameof (RequireAll), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // https://github.com/dotnet/linker/issues/2158 + [ExpectedWarning ("IL2067", nameof (TryGetUnknown), nameof (RequireAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2158", CompilerGeneratedCode = true)] int fieldWithLocalReferenceInInitializer = TryGetUnknown (out var type) ? RequireAll (type) : 0; - [ExpectedWarning ("IL2067", nameof (TryGetUnknown), nameof (RequireAll), CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // https://github.com/dotnet/linker/issues/2158 + [ExpectedWarning ("IL2067", nameof (TryGetUnknown), nameof (RequireAll), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2158", CompilerGeneratedCode = true)] int PropertyWithLocalReferenceInInitializer { get; } = TryGetUnknown (out var type) ? RequireAll (type) : 0; public static void Test () diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/DynamicObjects.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/DynamicObjects.cs index d048bec91e5d..d98b7dc2aa57 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/DynamicObjects.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/DynamicObjects.cs @@ -29,7 +29,7 @@ public static void Main () class InvocationOnDynamicType { [ExpectedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + [ExpectedWarning ("IL3050", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/94427")] static void DynamicArgument () { dynamic dynamicObject = "Some string"; @@ -48,15 +48,15 @@ static void MethodWithDynamicParameterDoNothing (dynamic arg) } [ExpectedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + [ExpectedWarning ("IL3050", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/94427")] static void MethodWithDynamicParameter (dynamic arg) { arg.MethodWithDynamicParameter (arg); } // Roslyn codegen no longer produces a call to Binder.InvokeConstructor. - // [ExpectedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.InvokeConstructor")] - // [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + // [ExpectedSharedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.InvokeConstructor")] + // [ExpectedWarning ("IL3050", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/94427")] // static void ObjectCreationDynamicArgument () // { // dynamic dynamicObject = "Some string"; @@ -81,14 +81,14 @@ public static void Test () class DynamicMemberReference { [ExpectedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.GetMember")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + [ExpectedWarning ("IL3050", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/94427")] static void Read (dynamic d) { var x = d.Member; } [ExpectedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.SetMember")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + [ExpectedWarning ("IL3050", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/94427")] static void Write (dynamic d) { d.Member = 0; @@ -104,14 +104,14 @@ public static void Test () class DynamicIndexerAccess { [ExpectedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.GetIndex")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + [ExpectedWarning ("IL3050", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/94427")] static void Read (dynamic d) { var x = d[0]; } [ExpectedWarning ("IL2026", "Microsoft.CSharp.RuntimeBinder.Binder.SetIndex")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + [ExpectedWarning ("IL3050", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/94427")] static void Write (dynamic d) { d[0] = 0; @@ -129,7 +129,7 @@ class DynamicInRequiresUnreferencedCodeClass [RequiresUnreferencedCode("message")] class ClassWithRequires { - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] // https://github.com/dotnet/runtime/issues/94427 + [ExpectedWarning ("IL3050", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/94427")] public static void MethodWithDynamicArg (dynamic arg) { arg.DynamicInvocation (); @@ -154,7 +154,7 @@ static void MethodWithRequires () } [ExpectedWarning ("IL2026", nameof (MethodWithRequires))] - [ExpectedWarning ("IL3050", nameof (MethodWithRequires), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (MethodWithRequires), Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { MethodWithRequires (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExceptionalDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExceptionalDataFlow.cs index beaf3237c7c4..8cc5bf9b6c1a 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExceptionalDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExceptionalDataFlow.cs @@ -46,10 +46,8 @@ public static void Main () ExceptionFilterWithException (); } - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void TryFlowsToFinally () { @@ -109,12 +107,9 @@ public static void MultipleTryExits () // On each path, only one state is possible, but we conservatively merge the (non-exceptional) // finally states for each path and expect the warnings to reflect this merged state. [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicEvents) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicEvents) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] @@ -124,12 +119,9 @@ public static void MultipleTryExits () [ExpectedWarning ("IL2073", nameof (MultipleFinallyPaths) + "()", nameof (GetWithPublicEvents) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2073", nameof (MultipleFinallyPaths) + "()", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2073", nameof (MultipleFinallyPaths) + "()", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2073", nameof (MultipleFinallyPaths) + "()", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2073", nameof (MultipleFinallyPaths) + "()", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2073", nameof (MultipleFinallyPaths) + "()", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2073", nameof (MultipleFinallyPaths) + "()", nameof (GetWithPublicProperties) + "()", Tool.Trimmer | Tool.NativeAot, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] public static Type MultipleFinallyPaths () { @@ -160,14 +152,11 @@ public static Type MultipleFinallyPaths () throw new Exception (); } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void FinallyChain () { @@ -184,16 +173,12 @@ public static void FinallyChain () } } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] - + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicProperties) + "()")] @@ -218,10 +203,8 @@ public static void FinallyChainWithPostFinallyState () RequireAll4 (t); } - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void TryFlowsToCatch () { @@ -235,10 +218,8 @@ public static void TryFlowsToCatch () } } - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void CatchFlowsToFinally () { @@ -253,8 +234,7 @@ public static void CatchFlowsToFinally () } } - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void CatchFlowsToAfterTry () { @@ -268,8 +248,7 @@ public static void CatchFlowsToAfterTry () RequireAll (t); } - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void CatchFlowsToAfterFinally () { @@ -303,20 +282,17 @@ public class Exception2 : Exception { } [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicFields) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll5) + "(Type)", nameof (GetWithPublicEvents) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll6) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll6) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll6) + "(Type)", nameof (GetWithPublicFields) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll6) + "(Type)", nameof (GetWithPublicProperties) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll6) + "(Type)", nameof (GetWithPublicEvents) + "()")] @@ -326,26 +302,16 @@ public class Exception2 : Exception { } [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicConstructors) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll5) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll5) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll7) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll7) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll7) + "(Type)", nameof (GetWithPublicEvents) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicEvents) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll5) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll5) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll7) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll7) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll7) + "(Type)", nameof (GetWithPublicEvents) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicEvents) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void TryFlowsToMultipleCatchAndFinally () { @@ -370,20 +336,15 @@ public static void TryFlowsToMultipleCatchAndFinally () } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicConstructors) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicEvents) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicEvents) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicConstructors) + "()")] public static void NestedWithFinally () @@ -408,17 +369,14 @@ public static void NestedWithFinally () } } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicEvents) + "()")] @@ -446,22 +404,16 @@ public static void ControlFlowsOutOfMultipleFinally () } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicConstructors) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicEvents) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicEvents) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicConstructors) + "()")] public static void NestedWithCatch () @@ -488,8 +440,7 @@ public static void NestedWithCatch () [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void CatchInTry () { try { @@ -510,11 +461,10 @@ public static void CatchInTry () [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] // The bug was producing this warning: - // [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicConstructors) + "()")] + // [ExpectedSharedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicConstructors) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void CatchInTryWithFinally () { Type t = GetWithPublicConstructors (); @@ -540,12 +490,10 @@ public static void CatchInTryWithFinally () } } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicConstructors) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicConstructors) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicConstructors) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicConstructors) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] static void CatchInFinally () { @@ -565,8 +513,7 @@ static void CatchInFinally () { [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void TestCatchesHaveSeparateState () { Type t = GetWithPublicMethods (); @@ -581,8 +528,7 @@ public static void TestCatchesHaveSeparateState () } [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] public static void FinallyWithBranchToFirstBlock () { Type t = GetWithPublicMethods (); @@ -596,8 +542,7 @@ public static void FinallyWithBranchToFirstBlock () } [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] public static void FinallyWithBranchToFirstBlockAndEnclosingTryCatchState () { try { @@ -619,8 +564,7 @@ public static void FinallyWithBranchToFirstBlockAndEnclosingTryCatchState () } [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] public static void CatchWithBranchToFirstBlock () { Type t = GetWithPublicMethods (); @@ -634,8 +578,7 @@ public static void CatchWithBranchToFirstBlock () } [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] public static void CatchWithBranchToFirstBlockAndReassignment () { Type t = GetWithPublicMethods (); @@ -651,10 +594,8 @@ public static void CatchWithBranchToFirstBlockAndReassignment () [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void CatchWithNonSimplePredecessor () { @@ -676,10 +617,8 @@ public static void CatchWithNonSimplePredecessor () [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void FinallyWithNonSimplePredecessor () { @@ -701,10 +640,8 @@ public static void FinallyWithNonSimplePredecessor () [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicProperties) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] public static void FinallyInTryWithPredecessor () { @@ -724,20 +661,17 @@ public static void FinallyInTryWithPredecessor () } } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void NestedFinally () { Type t = GetWithPublicMethods (); @@ -760,10 +694,8 @@ public static void NestedFinally () [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicFields) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll4) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void ChangeInFinallyNestedInFinally () { Type t = GetWithPublicMethods (); @@ -780,20 +712,17 @@ public static void ChangeInFinallyNestedInFinally () RequireAll4 (t); // fields only } - [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll1) + "(Type)", nameof (GetWithPublicFields) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties) + "()")] [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicProperties) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll3) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void NestedFinallyWithPredecessor () { Type t = GetWithPublicMethods (); @@ -811,11 +740,9 @@ public static void NestedFinallyWithPredecessor () } } - [ExpectedWarning ("IL2072", nameof (RequireAllTrue) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAllTrue) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAllTrue) + "(Type)", nameof (GetWithPublicFields) + "()")] - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicFields) + "()")] public static void ExceptionFilter () { @@ -833,8 +760,7 @@ public static void ExceptionFilter () [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void ExceptionFilterStateChange () { Type t = GetWithPublicMethods (); @@ -872,12 +798,9 @@ public static void ExceptionFilterStateChange () [ExpectedWarning ("IL2072", nameof (RequireAll6) + "(Type)", nameof (GetWithPublicProperties) + "()")] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicMethods) + "()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicFields) + "()", Tool.Trimmer | Tool.NativeAot, "")] public static void ExceptionMultipleFilters () { Type t = GetWithPublicMethods (); @@ -908,8 +831,7 @@ public static void ExceptionMultipleFilters () [ExpectedWarning ("IL2072", nameof (RequireAll2) + "(Type)", nameof (GetWithPublicProperties))] // Trimmer merges branches going forward. - [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (RequireAll) + "(Type)", nameof (GetWithPublicMethods), Tool.Trimmer | Tool.NativeAot, "")] public static void ExceptionFilterWithBranch () { Type t = GetWithPublicMethods (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExponentialDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExponentialDataFlow.cs index 2f749beae0f8..a7715c507f2a 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExponentialDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExponentialDataFlow.cs @@ -58,7 +58,7 @@ class GenericTypeWithRequires<[DynamicallyAccessedMembers (DynamicallyAccessedMe { } - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", Tool.Analyzer, "")] [ExpectedWarning ("IL2090", "'T'")] public static void Test () { @@ -94,32 +94,32 @@ class GenericTypeWithRequires< { } - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] // The way we track arrays causes the analyzer to track exponentially many // ArrayValues in the ValueSet for the pattern in this method, hitting the limit. // When this happens, we replace the ValueSet with an unknown value, producing // this warning. - [ExpectedWarning ("IL2055", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2055", Tool.Analyzer, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2090", "'T'", Tool.Trimmer | Tool.NativeAot, "")] public static void Test () { Type[] types = new Type[20] { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureCheckDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureCheckDataFlow.cs index 8c8c3baf5ab5..ab94f5052d42 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureCheckDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureCheckDataFlow.cs @@ -40,8 +40,8 @@ public static void Main () class CallFeatureUnguarded { [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer | Tool.NativeAot, "")] static void Unguarded () { RequiresUnreferencedCode (); @@ -50,8 +50,8 @@ static void Unguarded () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer | Tool.NativeAot, "")] static void UnguardedIf () { if (!TestFeatures.IsUnreferencedCodeSupported) { @@ -62,8 +62,8 @@ static void UnguardedIf () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer | Tool.NativeAot, "")] static void UnguardedElse () { if (TestFeatures.IsUnreferencedCodeSupported) @@ -99,8 +99,8 @@ static void UnguardedTernary () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer | Tool.NativeAot, "")] static void UnguardedThrow () { if (TestFeatures.IsUnreferencedCodeSupported) @@ -114,8 +114,8 @@ static void UnguardedThrow () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer | Tool.NativeAot, "")] static void UnguardedReturn () { if (TestFeatures.IsUnreferencedCodeSupported) @@ -205,8 +205,8 @@ public static void Test () GuardedDoesNotReturnIfFalseCtor (); } - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer, "")] static void GuardedIf () { if (TestFeatures.IsUnreferencedCodeSupported) { @@ -216,8 +216,8 @@ static void GuardedIf () } } - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer, "")] static void GuardedElse () { if (!TestFeatures.IsUnreferencedCodeSupported) @@ -248,8 +248,8 @@ static void GuardedTernary () var b = !TestFeatures.IsUnreferencedCodeSupported ? true : RequiresUnreferencedCodeBool (); } - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer, "")] static void GuardedThrow () { if (!TestFeatures.IsUnreferencedCodeSupported) @@ -262,8 +262,8 @@ static void GuardedThrow () RequiresAssemblyFiles (); } - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer, "")] static void GuardedReturn () { if (!TestFeatures.IsUnreferencedCodeSupported) @@ -277,7 +277,7 @@ static void GuardedReturn () } // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] static void GuardedAssert () { Debug.Assert (TestFeatures.IsUnreferencedCodeSupported); @@ -286,7 +286,7 @@ static void GuardedAssert () } // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] static void GuardedDoesNotReturnIfTrue () { DoesNotReturnIfTrue (!TestFeatures.IsUnreferencedCodeSupported); @@ -295,7 +295,7 @@ static void GuardedDoesNotReturnIfTrue () } // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] static void GuardedDoesNotReturnIfFalse () { DoesNotReturnIfFalse (TestFeatures.IsUnreferencedCodeSupported); @@ -304,7 +304,7 @@ static void GuardedDoesNotReturnIfFalse () } // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] static void GuardedDoesNotReturn () { if (!TestFeatures.IsUnreferencedCodeSupported) @@ -314,7 +314,7 @@ static void GuardedDoesNotReturn () } // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] static void GuardedDoesNotReturnIfFalseCtor () { new DoesNotReturnIfFalseCtor (TestFeatures.IsUnreferencedCodeSupported); @@ -326,8 +326,8 @@ static void GuardedDoesNotReturnIfFalseCtor () class FeatureCheckBooleanExpressions { // Trimmer/NativeAot aren't able to optimize away the branch in this case. - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.NativeAot, "")] static void And () { if (TestFeatures.IsUnreferencedCodeSupported && RuntimeFeature.IsDynamicCodeSupported) { @@ -337,7 +337,7 @@ static void And () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] static void AndNot () { if (!TestFeatures.IsUnreferencedCodeSupported && !RuntimeFeature.IsDynamicCodeSupported) @@ -348,8 +348,8 @@ static void AndNot () } // Trimmer/NativeAot aren't able to optimize away the branch in this case. - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.NativeAot, "")] static void NotAnd () { if (!(TestFeatures.IsUnreferencedCodeSupported && RuntimeFeature.IsDynamicCodeSupported)) @@ -360,7 +360,7 @@ static void NotAnd () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] static void Or () { if (TestFeatures.IsUnreferencedCodeSupported || RuntimeFeature.IsDynamicCodeSupported) { @@ -370,8 +370,8 @@ static void Or () } // Trimmer/NativeAot aren't able to optimize away the branch in this case. - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.NativeAot, "")] static void OrNot () { if (!TestFeatures.IsUnreferencedCodeSupported || !RuntimeFeature.IsDynamicCodeSupported) @@ -382,7 +382,7 @@ static void OrNot () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] static void NotOr () { if (!(TestFeatures.IsUnreferencedCodeSupported || RuntimeFeature.IsDynamicCodeSupported)) @@ -477,7 +477,7 @@ static void IsNotFalse () } [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode))] - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "")] static void Contradiction () { if (TestFeatures.IsUnreferencedCodeSupported && !TestFeatures.IsUnreferencedCodeSupported) { @@ -532,7 +532,7 @@ static void CallTestDynamicCodeGuarded () RequiresDynamicCode (); } - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer | Tool.NativeAot, "")] static void CallTestDynamicCodeUnguarded () { RequiresDynamicCode (); @@ -545,7 +545,7 @@ static void CallTestAssemblyFilesGuarded () } } - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer | Tool.NativeAot, "")] static void CallTestAssemblyFilesUnguarded () { RequiresAssemblyFiles (); @@ -564,9 +564,9 @@ public static void Test () class FeatureCheckCombinations { - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer, "")] // Trimmer warns because IsDynamicCodeSupported is not a constant, so the call is reachable. - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Analyzer | Tool.Trimmer)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Analyzer | Tool.Trimmer, "")] static void MeetFeaturesEmptyIntersection (bool b = true) { if (b) { @@ -582,7 +582,7 @@ static void MeetFeaturesEmptyIntersection (bool b = true) // Shows that ILLink has the same branch removal as NativeAot for this pattern, when // the branches both use a feature check that's substituted by ILLink. - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer, "")] static void MeetFeaturesEmptyIntersection_IdenticalBranches (bool b = true) { if (b) { @@ -596,7 +596,7 @@ static void MeetFeaturesEmptyIntersection_IdenticalBranches (bool b = true) RequiresDynamicCode (); } - [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3050", nameof (RequiresDynamicCode), Tool.Analyzer, "")] static void MeetFeaturesIntersection (bool b = true) { if (b) { @@ -622,7 +622,7 @@ static void IntroduceFeature () } } - [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", nameof (RequiresAssemblyFiles), Tool.Analyzer, "")] static void RemoveFeature () { if (TestFeatures.IsUnreferencedCodeSupported) { @@ -787,7 +787,7 @@ static void NestedTryInCheckInFinally () [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInTryNoCatch () { try { Debug.Assert (TestFeatures.IsUnreferencedCodeSupported); @@ -828,7 +828,7 @@ static void AssertInCatch () { [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1))] // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInFinally () { try { RequiresUnreferencedCode0 (); @@ -843,8 +843,8 @@ static void AssertInFinally () { [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2))] // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInTryNestedInTry () { try { @@ -885,8 +885,8 @@ static void AssertInTryWithCatchNestedInTry () [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1))] // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInTryNestedInFinally () { try { @@ -925,8 +925,8 @@ static void AssertInTryWithCatchNestedInFinally () [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2))] // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInFinallyNestedInTry () { try { try { @@ -944,8 +944,8 @@ static void AssertInFinallyNestedInTry () { [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2))] // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInFinallyWithCatchNestedInTry () { try { try { @@ -965,8 +965,8 @@ static void AssertInFinallyWithCatchNestedInTry () { [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1))] // Trimmer/NativeAot don't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInFinallyNestedInFinally () { try { @@ -985,8 +985,8 @@ static void AssertInFinallyNestedInFinally () [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode0))] [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode1))] // Trimmer/NativeAot doesn't optimize branches away based on DoesNotReturnIfAttribute - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode2), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode3), Tool.Trimmer | Tool.NativeAot, "")] static void AssertInFinallyWithCatchNestedInFinally () { try { @@ -1056,8 +1056,7 @@ static IEnumerable GuardInIterator () } } - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer, - CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer, "", CompilerGeneratedCode = true)] static IEnumerable StateFlowsAcrossYield () { if (!TestFeatures.IsUnreferencedCodeSupported) @@ -1076,8 +1075,7 @@ static async Task GuardInAsync () } } - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot, - CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async Task StateFlowsAcrossAwait () { if (!TestFeatures.IsUnreferencedCodeSupported) @@ -1097,8 +1095,7 @@ static async IAsyncEnumerable GuardInAsyncIterator () } } - [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), ProducedBy = Tool.Trimmer | Tool.NativeAot, - CompilerGeneratedCode = true)] + [ExpectedWarning ("IL2026", nameof (RequiresUnreferencedCode), Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async IAsyncEnumerable StateFlowsAcrossAwaitAndYield () { if (!TestFeatures.IsUnreferencedCodeSupported) diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureGuardAttributeDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureGuardAttributeDataFlow.cs index 60aa4f18a066..6b0e605ac773 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureGuardAttributeDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FeatureGuardAttributeDataFlow.cs @@ -65,7 +65,7 @@ static void TestIndirectGuard () // // The analyzer doesn't do constant propagation of the boolean, so it doesn't know that // the return value is always false when TestFeatures.IsUnreferencedCodeSupported is false. - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool AndGuard => TestFeatures.IsUnreferencedCodeSupported && OtherCondition (); @@ -138,7 +138,7 @@ static void TestIsNotFalseGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool IfReturnTrueGuard { get { @@ -148,7 +148,7 @@ static bool IfReturnTrueGuard { } } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool ElseReturnTrueGuard { get { @@ -199,7 +199,7 @@ static void TestAssertNotReturnFalseGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool AssertReturnTrueGuard { get { @@ -229,7 +229,7 @@ static void TestThrowGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool TernaryIfGuard => TestFeatures.IsUnreferencedCodeSupported ? true : false; @@ -239,7 +239,7 @@ static void TestTernaryIfGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool TernaryElseGuard => !TestFeatures.IsUnreferencedCodeSupported ? false : true; @@ -275,7 +275,7 @@ public static void Test () } class InvalidGuardBodies { - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool ReturnTrueGuard => true; @@ -285,7 +285,7 @@ static void TestReturnTrueGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool OtherConditionGuard => OtherCondition (); @@ -295,7 +295,7 @@ static void TestOtherConditionGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool OrGuard => TestFeatures.IsUnreferencedCodeSupported || OtherCondition (); @@ -305,7 +305,7 @@ static void TestOrGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool NotGuard => !TestFeatures.IsUnreferencedCodeSupported; @@ -315,7 +315,7 @@ static void TestNotGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool EqualsFalseGuard => TestFeatures.IsUnreferencedCodeSupported == false; @@ -325,7 +325,7 @@ static void TestEqualsFalseGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool FalseEqualsGuard => false == TestFeatures.IsUnreferencedCodeSupported; @@ -335,7 +335,7 @@ static void TestFalseEqualsGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool NotEqualsTrueGuard => TestFeatures.IsUnreferencedCodeSupported != true; @@ -345,7 +345,7 @@ static void TestNotEqualsTrueGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool TrueNotEqualsGuard => true != TestFeatures.IsUnreferencedCodeSupported; @@ -355,7 +355,7 @@ static void TestTrueNotEqualsGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool IsNotTrueGuard => TestFeatures.IsUnreferencedCodeSupported is not true; @@ -365,7 +365,7 @@ static void TestIsNotTrueGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool IsFalseGuard => TestFeatures.IsUnreferencedCodeSupported is false; @@ -375,7 +375,7 @@ static void TestIsFalseGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool IfReturnFalseGuard { get { @@ -391,7 +391,7 @@ static void TestIfReturnFalseGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool ElseReturnFalseGuard { get { @@ -408,7 +408,7 @@ static void TestElseReturnFalseGuard () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool AssertNotReturnTrueGuard { get { @@ -443,7 +443,7 @@ public static void Test () } class InvalidFeatureGuards { - [ExpectedWarning ("IL4001", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4001", Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static int NonBooleanProperty => 0; @@ -454,7 +454,7 @@ static void TestNonBooleanProperty () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4001", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4001", Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] bool NonStaticProperty => true; @@ -476,7 +476,7 @@ static void TestSetOnlyProperty () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4001", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4001", Tool.Analyzer, "")] [FeatureGuard (typeof(RequiresUnreferencedCodeAttribute))] static bool GetAndSetProperty { get => true; set => throw null; } @@ -516,3 +516,18 @@ static void RequiresUnreferencedCode () { } static bool OtherCondition () => true; } } + +namespace System.Diagnostics.CodeAnalysis +{ + // Allow AttributeTargets.Method for testing invalid usages of a custom FeatureGuardAttribute + [AttributeUsage (AttributeTargets.Property | AttributeTargets.Method, Inherited = false, AllowMultiple = true)] + public sealed class FeatureGuardAttribute : Attribute + { + public Type FeatureType { get; } + + public FeatureGuardAttribute (Type featureType) + { + FeatureType = featureType; + } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs index 9fcc94ed7a02..be75f5dca1c4 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FieldDataFlow.cs @@ -39,6 +39,7 @@ public static void Main () TestStringEmpty (); + AnnotationOnUnsupportedField.Test (); WriteArrayField.Test (); AccessReturnedInstanceField.Test (); } @@ -229,24 +230,21 @@ class AccessReturnedInstanceField static AccessReturnedInstanceField GetInstance ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type unused) => null; - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (GetInstance), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // https://github.com/dotnet/linker/issues/2832 + [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (GetInstance), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2832")] [ExpectedWarning ("IL2077", nameof (field), nameof (DataFlowTypeExtensions.RequiresAll))] static void TestRead () { GetInstance (GetUnknownType ()).field.RequiresAll (); } - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (GetInstance), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // https://github.com/dotnet/linker/issues/2832 + [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (GetInstance), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2832")] [ExpectedWarning ("IL2074", nameof (GetUnknownType), nameof (field))] static void TestWrite () { GetInstance (GetUnknownType ()).field = GetUnknownType (); } - [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (GetInstance), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] // https://github.com/dotnet/linker/issues/2832 + [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (GetInstance), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2832")] [ExpectedWarning ("IL2074", nameof (GetUnknownType), nameof (field))] static void TestNullCoalescingAssignment () { @@ -321,6 +319,39 @@ class TypeStore public static Type _staticTypeWithPublicParameterlessConstructor; } + class AnnotationOnUnsupportedField + { + class UnsupportedType + { + } + + static UnsupportedType GetUnsupportedTypeInstance () => null; + + [ExpectedWarning ("IL2097")] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + static UnsupportedType unsupportedTypeInstance; + + [ExpectedWarning ("IL2098")] + static void RequirePublicFields ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] + UnsupportedType unsupportedTypeInstance) + { + } + + [ExpectedWarning ("IL2077", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/101211")] + static void TestFlowOutOfField () + { + RequirePublicFields (unsupportedTypeInstance); + } + + [ExpectedWarning ("IL2074", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/101211")] + public static void Test () { + var t = GetUnsupportedTypeInstance (); + unsupportedTypeInstance = t; + TestFlowOutOfField (); + } + } + class WriteArrayField { static Type[] ArrayField; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs index fb4088a0e27f..2cbd62f6d434 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs @@ -37,6 +37,8 @@ public static void Main () TestStructConstraintSatisfiesParameterlessConstructor (); TestUnmanagedConstraintSatisfiesParameterlessConstructor (); + TestEnumConstraintSatisfiesPublicFields (); + TestGenericParameterFlowsToField (); TestGenericParameterFlowsToReturnValue (); @@ -406,7 +408,7 @@ class TypeGenericRequirementsOnMembers<[DynamicallyAccessedMembers (DynamicallyA { public TypeRequiresPublicFields PublicFieldsField; - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType public TypeRequiresPublicMethods PublicMethodsField; public TypeRequiresPublicFields PublicFieldsProperty { @@ -415,23 +417,23 @@ public TypeRequiresPublicFields PublicFieldsProperty { } public TypeRequiresPublicMethods PublicMethodsProperty { - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType get => null; - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType set { } } - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer, CompilerGeneratedCode = true)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "", CompilerGeneratedCode = true)] // NativeAOT_StorageSpaceType public TypeRequiresPublicMethods PublicMethodsImplicitGetter => null; public void PublicFieldsMethodParameter (TypeRequiresPublicFields param) { } - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType public void PublicMethodsMethodParameter (TypeRequiresPublicMethods param) { } public TypeRequiresPublicFields PublicFieldsMethodReturnValue () { return null; } - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType public TypeRequiresPublicMethods PublicMethodsMethodReturnValue () { return null; } public void PublicFieldsMethodLocalVariable () @@ -440,7 +442,7 @@ public void PublicFieldsMethodLocalVariable () } // The analyzer matches NativeAot behavior for local variables - it doesn't warn on generic types of local variables. - [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeRequiresPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType public void PublicMethodsMethodLocalVariable () { TypeRequiresPublicMethods t = null; @@ -709,17 +711,15 @@ public static void StaticPartialInstantiation () } [ExpectedWarning ("IL2091", - nameof (TOuter), + [nameof (TOuter), "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter", "TMethods", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams()", - ProducedBy = Tool.Analyzer)] + "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams()"], Tool.Analyzer, "")] [ExpectedWarning ("IL2091", - "'TOuter'", + ["'TOuter'", "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.TypeWithInstantiatedGenericMethodViaGenericParameter", "'TMethods'", - "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + "Mono.Linker.Tests.Cases.DataFlow.GenericParameterDataFlow.BaseTypeWithGenericMethod.StaticRequiresMultipleGenericParams"], Tool.Trimmer | Tool.NativeAot, "")] public static void StaticPartialInstantiationUnrecognized () { StaticRequiresMultipleGenericParams (); @@ -798,6 +798,11 @@ static void TestUnmanagedConstraintSatisfiesParameterlessConstructor () where { } + static void TestEnumConstraintSatisfiesPublicFields () where T : Enum + { + typeof (T).RequiresPublicFields (); + } + // Warn about calls to static methods: [ExpectedWarning ("IL2026", "TypeRequiresPublicFields", "RUCTest()", "message")] [ExpectedWarning ("IL2026", "RUCMethodRequiresPublicMethods", "message")] @@ -826,10 +831,10 @@ static void TestNoWarningsInRUCMethod () [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // StaticMethodRequiresPublicMethods [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // StaticMethodRequiresPublicMethods [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // RUCTypeRequiresPublicFields ctor - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = Tool.Trimmer)] // RUCTypeRequiresPublicFields local, // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = Tool.Trimmer)] // InstanceMethod, // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", Tool.Trimmer, "")] // RUCTypeRequiresPublicFields local, // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", Tool.Trimmer, "")] // InstanceMethod, // NativeAOT_StorageSpaceType [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // InstanceMethodRequiresPublicMethods - [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", ProducedBy = Tool.Trimmer)] // VirtualMethod, // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields", Tool.Trimmer, "")] // VirtualMethod, // NativeAOT_StorageSpaceType [ExpectedWarning ("IL2091", "RUCTypeRequiresPublicFields")] // VirtualMethodRequiresPublicMethods static void TestNoWarningsInRUCType () { @@ -901,9 +906,9 @@ static void TestGenericParameterFlowsToDelegateMethodDeclaringType () [ExpectedWarning ("IL2091", nameof (DelegateMethodTypeRequiresFields))] // NativeAOT_StorageSpaceType: illink warns about the type of 'instance' local variable - [ExpectedWarning ("IL2091", nameof (DelegateMethodTypeRequiresFields), ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2091", nameof (DelegateMethodTypeRequiresFields), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType: illink warns about the declaring type of 'InstanceMethod' on ldftn - [ExpectedWarning ("IL2091", nameof (DelegateMethodTypeRequiresFields), ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2091", nameof (DelegateMethodTypeRequiresFields), Tool.Trimmer, "")] static void TestGenericParameterFlowsToDelegateMethodDeclaringTypeInstance () { var instance = new DelegateMethodTypeRequiresFields (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterWarningLocation.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterWarningLocation.cs index d4acbe6a90ed..560560df1223 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterWarningLocation.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterWarningLocation.cs @@ -190,11 +190,11 @@ interface IWithTwo< static void MethodWithSpecificType (TypeWithPublicMethods one, IWithTwo two) { } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void MethodWithOneMismatch (TypeWithPublicMethods one) { } - [ExpectedWarning ("IL2091", nameof (IWithTwo), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", nameof (TypeWithPublicMethods), ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (IWithTwo), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", nameof (TypeWithPublicMethods), Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void MethodWithTwoMismatches< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -205,11 +205,11 @@ static void MethodWithTwoMismatches< static TypeWithPublicMethods MethodWithMatchingReturn<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () => null; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static TypeWithPublicMethods MethodWithOneMismatchReturn () => null; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static IWithTwo MethodWithTwoMismatchesInReturn< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -217,7 +217,7 @@ static IWithTwo MethodWithTwoMismatchesInReturn< class ConstructorWithOneMatchAndOneMismatch<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods> { - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType public ConstructorWithOneMatchAndOneMismatch (IWithTwo two) { } } @@ -252,11 +252,11 @@ interface IWithTwo< static void MethodWithSpecificType (TypeWithPublicMethods one, IWithTwo two) { } - [ExpectedWarning ("IL2091", ProducedBy = Tool.NativeAot | Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.NativeAot | Tool.Trimmer, "")] static void MethodWithOneMismatch (TypeWithPublicMethods one) { } - [ExpectedWarning ("IL2091", nameof (IWithTwo), ProducedBy = Tool.NativeAot | Tool.Trimmer)] - [ExpectedWarning ("IL2091", nameof (TypeWithPublicMethods), ProducedBy = Tool.NativeAot | Tool.Trimmer)] + [ExpectedWarning ("IL2091", nameof (IWithTwo), Tool.NativeAot | Tool.Trimmer, "")] + [ExpectedWarning ("IL2091", nameof (TypeWithPublicMethods), Tool.NativeAot | Tool.Trimmer, "")] static void MethodWithTwoMismatches< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -267,11 +267,11 @@ static void MethodWithTwoMismatches< static TypeWithPublicMethods MethodWithMatchingReturn<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () => null; - [ExpectedWarning ("IL2091", ProducedBy = Tool.NativeAot | Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.NativeAot | Tool.Trimmer, "")] static TypeWithPublicMethods MethodWithOneMismatchReturn () => null; - [ExpectedWarning ("IL2091", ProducedBy = Tool.NativeAot | Tool.Trimmer)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.NativeAot | Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.NativeAot | Tool.Trimmer, "")] + [ExpectedWarning ("IL2091", Tool.NativeAot | Tool.Trimmer, "")] static IWithTwo MethodWithTwoMismatchesInReturn< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -279,7 +279,7 @@ static IWithTwo MethodWithTwoMismatchesInReturn< class ConstructorWithOneMatchAndOneMismatch<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TMethods> { - [ExpectedWarning ("IL2091", ProducedBy = Tool.NativeAot | Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.NativeAot | Tool.Trimmer, "")] public ConstructorWithOneMatchAndOneMismatch (IWithTwo two) { } } @@ -325,10 +325,10 @@ public static void Test () class MultipleReferencesToTheSameType<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> { - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static TypeWithPublicMethods _field1; static TypeWithPublicMethods _field2; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static TypeWithPublicMethods _field3; public static void Test () @@ -343,8 +343,8 @@ class TwoMismatchesInOne< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> { - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static IWithTwo _field; public static void Test () @@ -388,10 +388,10 @@ class OneMatchingAnnotation<[DynamicallyAccessedMembers (DynamicallyAccessedMemb class MultipleReferencesToTheSameType<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> { - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static TypeWithPublicMethods _field1; static TypeWithPublicMethods _field2; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static TypeWithPublicMethods _field3; } @@ -399,8 +399,8 @@ class TwoMismatchesInOne< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> { - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static IWithTwo _field; } @@ -450,12 +450,12 @@ public static void Test () class MultipleReferencesToTheSameType<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> { // The warning is generated on the backing field - [ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "", CompilerGeneratedCode = true)] // NativeAOT_StorageSpaceType static TypeWithPublicMethods Property1 { - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType get; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType set; } @@ -465,12 +465,12 @@ static TypeWithPublicMethods Property2 { } // The warning is generated on the backing field - [ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "", CompilerGeneratedCode = true)] // NativeAOT_StorageSpaceType static TypeWithPublicMethods Property3 { - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType get; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType set; } @@ -487,14 +487,14 @@ class TwoMismatchesInOne< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields> { // The warnings are generated on the backing field - [ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "", CompilerGeneratedCode = true)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "", CompilerGeneratedCode = true)] // NativeAOT_StorageSpaceType static IWithTwo Property { // Getter is trimmed and doesn't produce any warning get; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType set; } @@ -554,7 +554,7 @@ static void MethodWithTwo< static MethodBody GetInstance () => null; - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // return type // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // return type // NativeAOT_StorageSpaceType static TypeWithPublicMethods GetInstanceForTypeWithPublicMethods () => null; class TypeOf @@ -578,8 +578,8 @@ static void SpecificType () } // Analyzer doesn't warn on typeof - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void MultipleReferencesToTheSameType< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -590,8 +590,8 @@ static void MultipleReferencesToTheSameType< } // Analyzer doesn't warn on typeof - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -694,8 +694,8 @@ static void TwoMismatchesInOneStatement< IWithTwo.Method (); } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // local variable // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // local variable // NativeAOT_StorageSpaceType static void InstanceMethodMismatch () { TypeWithPublicMethods instance = GetInstanceForTypeWithPublicMethods (); @@ -746,8 +746,8 @@ static void TwoMismatchesInOneStatement< _ = IWithTwo.Field; } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // access to the field // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // access to the field // NativeAOT_StorageSpaceType static void InstanceFieldMismatch () { TypeWithPublicMethods instance = GetInstanceForTypeWithPublicMethods (); @@ -779,8 +779,8 @@ static void SpecificType () TypeWithPublicMethods t = null; } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void MultipleReferencesToTheSameType< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -790,8 +790,8 @@ static void MultipleReferencesToTheSameType< TypeWithPublicMethods t3 = null; // Warn } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -952,9 +952,9 @@ static void SpecificType () // ldtoken owningtype // In order to call the right Expression APIs. [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void MultipleReferencesToTheSameMethod< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -969,9 +969,9 @@ static void MultipleReferencesToTheSameMethod< // ldtoken owningtype // In order to call the right Expression APIs. [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] [ExpectedWarning ("IL2091")] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -1007,8 +1007,8 @@ static void SpecificType () // ldtoken field // ldtoken owningtype // In order to call the right Expression APIs. - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void MultipleReferencesToTheSameField< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -1024,8 +1024,8 @@ static void MultipleReferencesToTheSameField< // ldtoken field // ldtoken owningtype // In order to call the right Expression APIs. - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -1061,8 +1061,8 @@ static void SpecificType () // ldtoken method (getter) // ldtoken owningtype // In order to call the right Expression APIs. - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void MultipleReferencesToTheSameProperty< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -1078,8 +1078,8 @@ static void MultipleReferencesToTheSameProperty< // ldtoken method (getter) // ldtoken owningtype // In order to call the right Expression APIs. - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2091", Tool.Trimmer | Tool.NativeAot, "")] static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -1155,8 +1155,8 @@ static void SpecificType () bool a = _value is TypeWithPublicMethods; } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void MultipleReferencesToTheSameMethod< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -1166,8 +1166,8 @@ static void MultipleReferencesToTheSameMethod< bool a3 = _value is TypeWithPublicMethods; // Warn } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -1200,8 +1200,8 @@ static void SpecificType () object a = _value as TypeWithPublicMethods; } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void MultipleReferencesToTheSameMethod< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -1211,8 +1211,8 @@ static void MultipleReferencesToTheSameMethod< object a3 = _value as TypeWithPublicMethods; // Warn } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -1251,8 +1251,8 @@ static void SpecificType () } } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void MultipleReferencesToTheSameType< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -1273,8 +1273,8 @@ static void MultipleReferencesToTheSameType< } } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -1314,8 +1314,8 @@ static void SpecificType () } } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void MultipleReferencesToTheSameType< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods, TUnknown> () @@ -1336,8 +1336,8 @@ static void MultipleReferencesToTheSameType< } } - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] // NativeAOT_StorageSpaceType static void TwoMismatchesInOneStatement< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TPublicFields, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> @@ -1373,16 +1373,14 @@ class AnnotatedString static void MethodWithAnnotatedParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] string typeName) { } // Analyzer: https://github.com/dotnet/runtime/issues/95118 - // NativeAOT: https://github.com/dotnet/runtime/issues/95140 - [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")] static void AnnotatedParameter () { MethodWithAnnotatedParameter ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]"); } // Analyzer: https://github.com/dotnet/runtime/issues/95118 - // NativeAOT: https://github.com/dotnet/runtime/issues/95140 - [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] static string AnnotatedReturnValue () { @@ -1393,8 +1391,7 @@ static string AnnotatedReturnValue () static string _annotatedField; // Analyzer: https://github.com/dotnet/runtime/issues/95118 - // NativeAOT: https://github.com/dotnet/runtime/issues/95140 - [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")] static void AnnotatedField () { _annotatedField = "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]"; @@ -1411,8 +1408,7 @@ public static void Test () class TypeGetType { // Analyzer: https://github.com/dotnet/runtime/issues/95118 - // NativeAOT: https://github.com/dotnet/runtime/issues/95140 - [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")] static void SpecificType () { Type.GetType ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]"); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs index d99b7557a257..31ef05ef3e55 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs @@ -168,9 +168,8 @@ public void Method1 () { } [RequiresUnreferencedCode ("--Method2--")] public void Method2 () { } - // https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2026", "--Method1--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--Method2--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--Method1--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")] + [ExpectedWarning ("IL2026", "--Method2--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")] public static void Test () { Type.GetType ("Mono.Linker.Tests.Cases.DataFlow." + nameof (GetTypeDataFlow) + "+" + nameof (TypeWithWarnings)).RequiresPublicMethods (); @@ -184,8 +183,7 @@ class OverConstTypeName [RequiresUnreferencedCode ("--Method1--")] public void Method1 () { } - // https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2026", "--Method1--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--Method1--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")] public static void Test () { Type.GetType (s_ConstTypeName).RequiresPublicMethods (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/IReflectDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/IReflectDataflow.cs index ea14e8b4f286..db2bc09e13e5 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/IReflectDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/IReflectDataflow.cs @@ -164,6 +164,9 @@ class TestType } [Kept] + // MyReflectOverType is not intrinsically understood by the analysis, so + // it doesn't satisfy the PublicFields | NonPublicFields requirement. + [ExpectedWarning ("IL2075")] public static void Test () { new MyReflectOverType (typeof (TestType)).GetFields (BindingFlags.Instance | BindingFlags.Public); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InlineArrayDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InlineArrayDataflow.cs index c7725fcdf261..5915bb2d4538 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InlineArrayDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InlineArrayDataflow.cs @@ -14,7 +14,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow [ExpectedNoWarnings] public class InlineArrayDataflow { - public static void Main() + public static void Main () { AccessPrimitiveTypeArray (); AccessUnannotatedTypeArray (); @@ -63,7 +63,7 @@ struct AnnotatedTypeArray } // Currently tracking of annotations on inline array values is not implemented - [ExpectedWarning("IL2065", "GetProperty")] + [ExpectedWarning ("IL2065", "GetProperty")] static void AccessAnnotatedTypeArray () { AnnotatedTypeArray a = new AnnotatedTypeArray (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InterpolatedStringDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InterpolatedStringDataFlow.cs new file mode 100644 index 000000000000..f862348ddec3 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InterpolatedStringDataFlow.cs @@ -0,0 +1,41 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Helpers; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.DataFlow +{ + [ExpectedNoWarnings] + [SkipKeptItemsValidation] + [Define ("DEBUG")] + public class InterpolatedStringDataFlow + { + public static void Main () + { + TestInterpolatedStringHandler (); + TestUnknownInterpolatedString (); + } + + static void TestInterpolatedStringHandler (bool b = true) { + // Creates a control-flow graph for the analyzer that has an + // IFlowCaptureReferenceOperation that represents a capture + // because it is used as an out param (so has IsInitialization = true). + // See https://github.com/dotnet/roslyn/issues/57484 for context. + // This test ensures the analyzer has coverage for cases + // where IsInitialization = true. + Debug.Assert (b, $"Debug interpolated string handler {b}"); + } + + [ExpectedWarning ("IL2057")] + static void TestUnknownInterpolatedString (string input = "test") { + Type.GetType ($"{input}"); + } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InterpolatedStringHandlerDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InterpolatedStringHandlerDataFlow.cs deleted file mode 100644 index 6e30b600d736..000000000000 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/InterpolatedStringHandlerDataFlow.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Helpers; -using Mono.Linker.Tests.Cases.Expectations.Metadata; - -namespace Mono.Linker.Tests.Cases.DataFlow -{ - [ExpectedNoWarnings] - [SkipKeptItemsValidation] - [Define ("DEBUG")] - public class InterpolatedStringHandlerDataFlow - { - public static void Main () - { - Test (); - } - - static void Test(bool b = true) { - // Creates a control-flow graph for the analyzer that has an - // IFlowCaptureReferenceOperation that represents a capture - // because it is used as an out param (so has IsInitialization = true). - // See https://github.com/dotnet/roslyn/issues/57484 for context. - // This test ensures the analyzer has coverage for cases - // where IsInitialization = true. - Debug.Assert (b, $"Debug interpolated string handler {b}"); - } - } -} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/LocalDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/LocalDataFlow.cs index 788312c2c262..fc412d642dfb 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/LocalDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/LocalDataFlow.cs @@ -218,8 +218,7 @@ public static void TestBranchMergeCatch () nameof (LocalDataFlow) + "." + nameof (GetWithPublicFields) + "()")] // ILLink produces extraneous warnings [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields) + "(String)", - nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer)] + nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", Tool.Trimmer, "")] public static void TestBranchMergeFinally () { string str = GetWithPublicMethods (); @@ -235,8 +234,7 @@ public static void TestBranchMergeFinally () } // Analyzer gets this right (no warning), but trimmer merges all branches going forward. - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields) + "(String)", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields) + "(String)", Tool.Trimmer, "")] public static void TestBranchGoto () { string str = GetWithPublicMethods (); @@ -249,8 +247,7 @@ public static void TestBranchGoto () } // Analyzer gets this right (no warning), but trimmer merges all branches going forward. - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields), - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields), Tool.Trimmer, "")] public static void TestBranchIf () { string str = GetWithPublicMethods (); @@ -261,8 +258,7 @@ public static void TestBranchIf () } // Analyzer gets this right (no warning), but trimmer merges all branches going forward. - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields), - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields), Tool.Trimmer, "")] public static void TestBranchIfElse () { string str; @@ -278,18 +274,12 @@ public static void TestBranchIfElse () } // Analyzer gets this right (no warning), but trimmer merges all branches going forward. - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresNonPublicMethods) + "(String)", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicMethods) + "(String)", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicMethods) + "(String)", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicConstructors) + "(String)", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicConstructors) + "(String)", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicConstructors) + "(String)", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresNonPublicMethods) + "(String)", Tool.Trimmer, "")] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicMethods) + "(String)", Tool.Trimmer, "")] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicMethods) + "(String)", Tool.Trimmer, "")] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicConstructors) + "(String)", Tool.Trimmer, "")] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicConstructors) + "(String)", Tool.Trimmer, "")] + [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicConstructors) + "(String)", Tool.Trimmer, "")] public static void TestBranchSwitch () { string str = null; @@ -315,8 +305,7 @@ public static void TestBranchSwitch () // Analyzer gets this right (no warning), but trimmer merges all branches going forward. [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields), - nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer)] + nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", Tool.Trimmer, "")] public static void TestBranchTry () { string str = GetWithPublicMethods (); @@ -332,8 +321,7 @@ public static void TestBranchTry () // Analyzer gets this right (no warning), but trimmer merges all branches going forward. [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields), - nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer)] + nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", Tool.Trimmer, "")] public static void TestBranchCatch () { string str = GetWithPublicMethods (); @@ -348,8 +336,7 @@ public static void TestBranchCatch () // Analyzer gets this right (no warning), but trimmer merges all branches going forward. [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicFields), - nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", - ProducedBy = Tool.Trimmer)] + nameof (LocalDataFlow) + "." + nameof (GetWithPublicMethods) + "()", Tool.Trimmer, "")] public static void TestBranchFinally () { string str = GetWithPublicMethods (); @@ -365,8 +352,7 @@ public static void TestBranchFinally () // Analyzer gets this right, but ILLink doesn't consider backwards branches. [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicMethods) + "(String)", - nameof (LocalDataFlow) + "." + nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + nameof (LocalDataFlow) + "." + nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] public static void TestBackwardsEdgeLoop () { string str = GetWithPublicMethods (); @@ -382,8 +368,7 @@ public static void TestBackwardsEdgeLoop () // Analyzer gets this right, but ILLink doesn't consider backwards branches. [ExpectedWarning ("IL2072", nameof (DataFlowStringExtensions) + "." + nameof (DataFlowStringExtensions.RequiresPublicMethods) + "(String)", - nameof (LocalDataFlow) + "." + nameof (GetWithPublicFields) + "()", - ProducedBy = Tool.Analyzer)] + nameof (LocalDataFlow) + "." + nameof (GetWithPublicFields) + "()", Tool.Analyzer, "")] public static void TestBackwardsEdgeGoto () { string str = null; @@ -438,10 +423,9 @@ public virtual void VirtualMethod () } } - // https://github.com/dotnet/linker/issues/2273 // Analyzer doesn't see through foreach over array at all - will not warn - [ExpectedWarning ("IL2063", ProducedBy = Tool.Trimmer)] // The types loaded from the array don't have annotations, so the "return" should warn - [ExpectedWarning ("IL2073", ProducedBy = Tool.Analyzer)] // Analyzer tracks resultType as the value from IEnumerable.Current.get() + [ExpectedWarning ("IL2063", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/96646")] // The types loaded from the array don't have annotations, so the "return" should warn + [ExpectedWarning ("IL2073", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/96646")] // Analyzer tracks resultType as the value from IEnumerable.Current.get() [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] public static Type TestBackwardEdgeWithLdElem (Type[] types = null) { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs index 50451dcd3f1e..34ae3994f667 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataFlow.cs @@ -125,8 +125,7 @@ static void TestWithRequirementsFromParam ( typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (type); } - // https://github.com/dotnet/linker/issues/2428 - // [ExpectedWarning ("IL2071", "'T'")] + [ExpectedWarning ("IL2071", "'T'", Tool.None, "https://github.com/dotnet/linker/issues/2428")] [ExpectedWarning ("IL2070", "'this'")] static void TestWithRequirementsFromParamWithMismatch ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) @@ -140,8 +139,7 @@ static void TestWithRequirementsFromGenericParam< typeof (GenericWithPublicFieldsArgument<>).MakeGenericType (typeof (T)); } - // https://github.com/dotnet/linker/issues/2428 - // [ExpectedWarning ("IL2091", "'T'")] + [ExpectedWarning ("IL2091", "'T'", Tool.None,"https://github.com/dotnet/linker/issues/2428")] [ExpectedWarning ("IL2090", "'this'")] // Note that this actually produces a warning which should not be possible to produce right now static void TestWithRequirementsFromGenericParamWithMismatch< [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TInput> () @@ -550,8 +548,8 @@ static void TestWithArrayUnknownIndexSet (int indexToSet) .MakeGenericMethod (types); } - // https://github.com/dotnet/linker/issues/2158 - analyzer doesn't work the same as ILLink, it simply doesn't handle refs - [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + // Analyzer doesn't work the same as ILLink, it simply doesn't handle refs + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2158")] static void TestWithArrayUnknownIndexSetByRef (int indexToSet) { Type[] types = new Type[1]; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataflowIntrinsics.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataflowIntrinsics.cs new file mode 100644 index 000000000000..b1a67bd42dbd --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MakeGenericDataflowIntrinsics.cs @@ -0,0 +1,72 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using Mono.Linker.Tests.Cases.Expectations.Assertions; + +namespace Mono.Linker.Tests.Cases.DataFlow +{ + [SkipKeptItemsValidation] + [ExpectedNoWarnings] + class MakeGenericDataflowIntrinsics + { + public static void Main () + { + MakeGenericType.Test (); + MakeGenericMethod.Test (); + } + + class MakeGenericType + { + class Gen { } + + static Type GrabUnknownType () => null; + + public static void Test () + { + TestRecognizedIntrinsic (); + TestRecognizedGenericIntrinsic (); + TestUnknownOwningType (); + TestUnknownArgument (); + } + + public static void TestRecognizedIntrinsic () => typeof (Gen<>).MakeGenericType (typeof (object)); + + public static void TestRecognizedGenericIntrinsic () => typeof (Gen<>).MakeGenericType (typeof (T)); + + [ExpectedWarning ("IL2055", nameof (Type.MakeGenericType))] + [ExpectedWarning ("IL3050", nameof (Type.MakeGenericType), Tool.Analyzer | Tool.NativeAot, "")] + public static void TestUnknownOwningType () => GrabUnknownType ().MakeGenericType (typeof (object)); + + [ExpectedWarning ("IL3050", nameof (Type.MakeGenericType), Tool.Analyzer | Tool.NativeAot, "")] + public static void TestUnknownArgument () => typeof (Gen<>).MakeGenericType (GrabUnknownType ()); + } + + class MakeGenericMethod + { + public static void Gen () { } + + static MethodInfo GrabUnknownMethod () => null; + + static Type GrabUnknownType () => null; + + public static void Test () + { + TestRecognizedIntrinsic (); + TestRecognizedGenericIntrinsic (); + TestUnknownOwningMethod (); + TestUnknownArgument (); + } + + public static void TestRecognizedIntrinsic () => typeof (MakeGenericMethod).GetMethod (nameof (Gen)).MakeGenericMethod (typeof (object)); + + public static void TestRecognizedGenericIntrinsic () => typeof (MakeGenericMethod).GetMethod (nameof (Gen)).MakeGenericMethod (typeof (T)); + + [ExpectedWarning ("IL2060", nameof (MethodInfo.MakeGenericMethod))] + [ExpectedWarning ("IL3050", nameof (MethodInfo.MakeGenericMethod), Tool.Analyzer | Tool.NativeAot, "")] + public static void TestUnknownOwningMethod () => GrabUnknownMethod ().MakeGenericMethod (typeof (object)); + + [ExpectedWarning ("IL3050", nameof (MethodInfo.MakeGenericMethod), Tool.Analyzer | Tool.NativeAot, "")] + public static void TestUnknownArgument () => typeof (MakeGenericMethod).GetMethod (nameof (Gen)).MakeGenericMethod (GrabUnknownType()); + } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefParameterDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefParameterDataFlow.cs index 7ea036c5c39b..0f67d469d42d 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefParameterDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefParameterDataFlow.cs @@ -57,10 +57,9 @@ public static void Main () [ExpectedWarning ("IL2026", "Message for --TestType.Requires--")] - // https://github.com/dotnet/linker/issues/2158 // The type.GetMethods call generates a warning because we're not able to correctly track the value of the "this". // (there's a ldind.ref insruction here which we currently don't handle and the "this" becomes unknown) - [ExpectedWarning ("IL2065")] + [UnexpectedWarning ("IL2065", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/linker/issues/2158")] static void TestAssignStaticToAnnotatedRefParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] ref Type type) { type = typeof (TestTypeWithRequires); @@ -71,10 +70,9 @@ static void TestAssignStaticToAnnotatedRefParameter ([DynamicallyAccessedMembers // which is definitely not the case here. [ExpectedWarning ("IL2067", "typeWithFields")] - // https://github.com/dotnet/linker/issues/2158 // The type.GetMethods call generates a warning because we're not able to correctly track the value of the "this". // (there's a ldind.ref insruction here which we currently don't handle and the "this" becomes unknown) - [ExpectedWarning ("IL2065")] + [UnexpectedWarning ("IL2065", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/linker/issues/2158")] static void TestAssignParameterToAnnotatedRefParameter ( [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] ref Type type, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] Type typeWithFields) @@ -120,10 +118,9 @@ static void TestReadFromRefParameter_MismatchOnOutput_PassedTwice () } [ExpectedWarning ("IL2072", nameof (TryGetAnnotatedValue))] - // https://github.com/dotnet/linker/issues/2632 // This second warning should not be generated, the value of typeWithMethods should have PublicMethods // after the call with out parameter. - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Analyzer)] + [UnexpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Analyzer, "https://github.com/dotnet/linker/issues/2632")] static void TestReadFromRefParameter_MismatchOnInput () { Type typeWithMethods = GetTypeWithFields (); @@ -133,10 +130,9 @@ static void TestReadFromRefParameter_MismatchOnInput () [ExpectedWarning ("IL2072", nameof (TryGetAnnotatedValueFromValue))] [ExpectedWarning ("IL2072", nameof (TryGetAnnotatedValueFromValue))] - // https://github.com/dotnet/linker/issues/2632 // This third warning should not be generated, the value of typeWithMethods should have PublicMethods // after the call with ref parameter. - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Analyzer)] + [UnexpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Analyzer, "https://github.com/dotnet/linker/issues/2632")] static void TestReadFromRefParameter_MismatchOnInput_PassedTwice () { Type typeWithMethods = GetTypeWithFields (); @@ -269,7 +265,7 @@ static void TestPassingRefProperty_OutParameter () TryGetAnnotatedValueOut (out TypeWithMethodsProperty); } - [ExpectedWarning ("IL2072", nameof (TryGetAnnotatedValue), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", nameof (TryGetAnnotatedValue), Tool.Trimmer | Tool.NativeAot, "")] static void TestPassingRefProperty_Mismatch () { TryGetAnnotatedValue (ref TypeWithFieldsProperty); @@ -316,8 +312,8 @@ static void TestPassingRefIndexer_OutParameter () } // https://github.com/dotnet/linker/issues/2158 - [ExpectedWarning ("IL2068", nameof (TryGetAnnotatedValue), ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2072", nameof (TryGetAnnotatedValue), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2068", nameof (TryGetAnnotatedValue), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2072", nameof (TryGetAnnotatedValue), Tool.Trimmer | Tool.NativeAot, "")] static void TestPassingRefIndexer_Mismatch () { var indexer = new RefIndexer_PublicFields (); @@ -325,7 +321,7 @@ static void TestPassingRefIndexer_Mismatch () } // https://github.com/dotnet/linker/issues/2158 - [ExpectedWarning ("IL2068", nameof (TryGetAnnotatedValue), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2068", nameof (TryGetAnnotatedValue), Tool.Trimmer | Tool.NativeAot, "")] static void TestPassingRefIndexer_OutParameter_Mismatch () { var indexer = new RefIndexer_PublicFields (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefReturnDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefReturnDataFlow.cs index 7220a83d3ce2..99978295d675 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefReturnDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodByRefReturnDataFlow.cs @@ -43,7 +43,7 @@ public static void Main () // Correct behavior in the trimming tools, but needs to be added in analyzer // Bug link: https://github.com/dotnet/linker/issues/2158 - [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", Tool.Trimmer | Tool.NativeAot, "")] static void AssignToAnnotatedTypeReference () { ref Type typeShouldHaveAllMethods = ref ReturnAnnotatedTypeReferenceAsAnnotated (); @@ -53,7 +53,7 @@ static void AssignToAnnotatedTypeReference () // Same as above for IL analysis, but this looks different to the Roslyn analyzer. // https://github.com/dotnet/linker/issues/2158 - [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", Tool.Trimmer | Tool.NativeAot, "")] static void AssignDirectlyToAnnotatedTypeReference () { ReturnAnnotatedTypeReferenceAsAnnotated () = typeof (TestTypeWithRequires); @@ -61,7 +61,7 @@ static void AssignDirectlyToAnnotatedTypeReference () } // https://github.com/dotnet/linker/issues/2158 - [ExpectedWarning ("IL2073", nameof (GetWithPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2073", nameof (GetWithPublicFields), Tool.Trimmer | Tool.NativeAot, "")] static void AssignToCapturedAnnotatedTypeReference () { // In this testcase, the Roslyn analyzer sees an assignment to a flow-capture reference. @@ -69,7 +69,7 @@ static void AssignToCapturedAnnotatedTypeReference () } [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (ReturnAnnotatedTypeWithRequirements))] - [ExpectedWarning ("IL2073", nameof (ReturnAnnotatedTypeWithRequirements), nameof (GetWithPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2073", nameof (ReturnAnnotatedTypeWithRequirements), nameof (GetWithPublicFields), Tool.Trimmer | Tool.NativeAot, "")] static void AssignToAnnotatedTypeReferenceWithRequirements () { ReturnAnnotatedTypeWithRequirements (GetWithPublicMethods ()) = GetWithPublicFields (); @@ -80,7 +80,7 @@ static void AssignToAnnotatedTypeReferenceWithRequirements () [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] static ref Type AnnotatedTypeReferenceAsAnnotatedProperty => ref _annotatedField; - [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", Tool.Trimmer | Tool.NativeAot, "")] static void AssignToAnnotatedTypeReferenceProperty () { ref Type typeShouldHaveAllMethods = ref AnnotatedTypeReferenceAsAnnotatedProperty; @@ -89,7 +89,7 @@ static void AssignToAnnotatedTypeReferenceProperty () } // https://github.com/dotnet/linker/issues/2158 - [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "Message for --TestType.Requires--", Tool.Trimmer | Tool.NativeAot, "")] static void AssignDirectlyToAnnotatedTypeReferenceProperty () { AnnotatedTypeReferenceAsAnnotatedProperty = typeof (TestTypeWithRequires); @@ -97,7 +97,7 @@ static void AssignDirectlyToAnnotatedTypeReferenceProperty () } // https://github.com/dotnet/linker/issues/2158 - [ExpectedWarning ("IL2073", nameof (GetWithPublicFields), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2073", nameof (GetWithPublicFields), Tool.Trimmer | Tool.NativeAot, "")] static void AssignToCapturedAnnotatedTypeReferenceProperty () { AnnotatedTypeReferenceAsAnnotatedProperty = GetWithPublicMethods () ?? GetWithPublicFields (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodOutParameterDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodOutParameterDataFlow.cs index 582c86ee012b..bb7a37074d2d 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodOutParameterDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodOutParameterDataFlow.cs @@ -19,6 +19,7 @@ public static void Main () TestInitializedReadFromOutParameter_PassedTwice (); TestUninitializedReadFromOutParameter (); TestInitializedReadFromOutParameter_MismatchOnOutput (); + TestInitializedReturnOutParameter_MismatchOnOutput (); TestInitializedReadFromOutParameter_MismatchOnOutput_PassedTwice (); TestInitializedReadFromOutParameter_MismatchOnInput (); TestInitializedReadFromOutParameter_MismatchOnInput_PassedTwice (); @@ -55,7 +56,7 @@ static void TestUninitializedReadFromOutParameter () typeWithMethods.RequiresPublicMethods (); } - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields))] + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2632")] static void TestInitializedReadFromOutParameter_MismatchOnOutput () { Type typeWithMethods = null; @@ -63,9 +64,18 @@ static void TestInitializedReadFromOutParameter_MismatchOnOutput () typeWithMethods.RequiresPublicFields (); } - // https://github.com/dotnet/linker/issues/2632 // This test should generate a warning since there's mismatch on annotations - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields))] + [ExpectedWarning ("IL2068", nameof (TryGetAnnotatedValue), nameof (DynamicallyAccessedMemberTypes.PublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2632")] + [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] + static Type TestInitializedReturnOutParameter_MismatchOnOutput () + { + Type typeWithMethods = null; + TryGetAnnotatedValue (out typeWithMethods); + return typeWithMethods; + } + + // This test should generate a warning since there's mismatch on annotations + [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2632")] static void TestInitializedReadFromOutParameter_MismatchOnOutput_PassedTwice () { Type typeWithMethods = null; @@ -73,10 +83,9 @@ static void TestInitializedReadFromOutParameter_MismatchOnOutput_PassedTwice () typeWithMethods.RequiresPublicFields (); } - // https://github.com/dotnet/linker/issues/2632 // This warning should not be generated, the value of typeWithMethods should have PublicMethods // after the call with out parameter. - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Analyzer)] + [UnexpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Analyzer, "https://github.com/dotnet/linker/issues/2632")] static void TestInitializedReadFromOutParameter_MismatchOnInput () { Type typeWithMethods = GetTypeWithFields (); @@ -86,10 +95,9 @@ static void TestInitializedReadFromOutParameter_MismatchOnInput () } [ExpectedWarning ("IL2072", nameof (TryGetAnnotatedValueFromValue))] - // https://github.com/dotnet/linker/issues/2632 // This warning should not be generated, the value of typeWithMethods should have PublicMethods // after the call with out parameter. - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicMethods), Tool.Analyzer, "https://github.com/dotnet/linker/issues/2632")] static void TestInitializedReadFromOutParameter_MismatchOnInput_PassedTwice () { Type typeWithMethods = GetTypeWithFields (); @@ -103,7 +111,7 @@ static void TestPassingOutParameter ([DynamicallyAccessedMembers (DynamicallyAcc TryGetAnnotatedValue (out typeWithMethods); } - [ExpectedWarning ("IL2067", "typeWithFields", nameof (TryGetAnnotatedValue))] + [ExpectedWarning ("IL2067", "typeWithFields", nameof (TryGetAnnotatedValue), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2632")] static void TestPassingOutParameter_Mismatch ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] out Type typeWithFields) { TryGetAnnotatedValue (out typeWithFields); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodParametersDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodParametersDataFlow.cs index 792ddce44223..4d9d0e5284db 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodParametersDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodParametersDataFlow.cs @@ -35,7 +35,6 @@ public static void Main () instance.UnknownValueToUnAnnotatedParameterOnInterestingMethod (); instance.WriteToParameterOnInstanceMethod (null); instance.LongWriteToParameterOnInstanceMethod (0, 0, 0, 0, null); - instance.UnsupportedParameterType (null); ParametersPassedToInstanceCtor (typeof (TestType), typeof (TestType)); @@ -44,7 +43,7 @@ public static void Main () #if !NATIVEAOT TestVarargsMethod (typeof (TestType), __arglist (0, 1, 2)); #endif - + AnnotationOnUnsupportedParameter.Test (); WriteCapturedParameter.Test (); } @@ -143,8 +142,6 @@ private void TwoAnnotatedParameters ( type2.RequiresPublicConstructors (); } - // TODO: https://github.com/dotnet/linker/issues/2273 - // (Dataflow analysis is not supported by the analyzer yet) [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions) + "." + nameof (DataFlowTypeExtensions.RequiresPublicConstructors) + "(Type)", "'type'")] @@ -199,11 +196,6 @@ private void UnknownValueToUnAnnotatedParameterOnInterestingMethod () RequirePublicParameterlessConstructorAndNothing (typeof (TestType), this.GetType ()); } - [ExpectedWarning ("IL2098", "p1", nameof (UnsupportedParameterType))] - private void UnsupportedParameterType ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] object p1) - { - } - private class InstanceCtor { [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicConstructors))] @@ -243,6 +235,37 @@ static void TestVarargsMethod ([DynamicallyAccessedMembers (DynamicallyAccessedM { } + class AnnotationOnUnsupportedParameter + { + class UnsupportedType () + { + } + + static UnsupportedType GetUnsupportedTypeInstance () => null; + + [ExpectedWarning ("IL2098", nameof (UnsupportedType))] + [ExpectedWarning ("IL2067", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/101211")] + static void RequirePublicMethods ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + UnsupportedType unsupportedTypeInstance) + { + RequirePublicFields (unsupportedTypeInstance); + } + + [ExpectedWarning ("IL2098", nameof (UnsupportedType))] + static void RequirePublicFields ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] + UnsupportedType unsupportedTypeInstance) + { + } + + [ExpectedWarning ("IL2072", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/101211")] + public static void Test () { + var t = GetUnsupportedTypeInstance (); + RequirePublicMethods (t); + } + } + class WriteCapturedParameter { [ExpectedWarning ("IL2072", nameof (GetUnknownType), "parameter")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodReturnParameterDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodReturnParameterDataFlow.cs index 544e6318f120..b201db94ded6 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodReturnParameterDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodReturnParameterDataFlow.cs @@ -35,8 +35,8 @@ public static void Main () instance.ReturnWithRequirementsAlwaysThrows (); - UnsupportedReturnType (); UnsupportedReturnTypeAndParameter (null); + AnnotationOnUnsupportedReturnType.Test (); } static Type NoRequirements () @@ -181,15 +181,57 @@ Type ReturnWithRequirementsAlwaysThrows () throw new NotImplementedException (); } - [ExpectedWarning ("IL2106", nameof (UnsupportedReturnType))] - [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] - static object UnsupportedReturnType () => null; - [ExpectedWarning ("IL2106", nameof (UnsupportedReturnTypeAndParameter))] [ExpectedWarning ("IL2098", nameof (UnsupportedReturnTypeAndParameter))] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] static object UnsupportedReturnTypeAndParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] object param) => null; + class AnnotationOnUnsupportedReturnType + { + class UnsupportedType + { + [UnexpectedWarning ("IL2082", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/101211")] + public UnsupportedType () { + RequirePublicFields (this); + } + } + + static UnsupportedType GetUnsupportedTypeInstance () => null; + + [ExpectedWarning ("IL2106")] + // Linker and NativeAot should not produce IL2073 + // They produce dataflow warnings despite the invalid annotations. + [UnexpectedWarning ("IL2073", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101211")] + [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + static UnsupportedType GetWithPublicMethods () { + return GetUnsupportedTypeInstance (); + } + + [ExpectedWarning ("IL2098")] + static void RequirePublicFields ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] + UnsupportedType unsupportedTypeInstance) + { + } + + [UnexpectedWarning ("IL2072", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/101211")] + static void TestMethodReturnValue () { + var t = GetWithPublicMethods (); + RequirePublicFields (t); + } + + [ExpectedWarning ("IL2072", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/101211")] + static void TestCtorReturnValue () { + var t = new UnsupportedType (); + RequirePublicFields (t); + } + + public static void Test () { + TestMethodReturnValue (); + TestCtorReturnValue (); + } + } + class TestType { public TestType () { } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodThisDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodThisDataFlow.cs index fe39c6a92d94..c57d784bce24 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodThisDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/MethodThisDataFlow.cs @@ -23,7 +23,7 @@ public static void Main () PropagateToThisWithSetters (); AssignToThis (); - TestAnnotationOnNonTypeMethod (); + AnnotationOnUnsupportedThisParameter.Test (); TestUnknownThis (); TestFromParameterToThis (null); TestFromFieldToThis (); @@ -88,11 +88,56 @@ static void AssignToThis () s.AssignToThisCaptured (); } - static void TestAnnotationOnNonTypeMethod () + class AnnotationOnUnsupportedThisParameter { - var t = new NonTypeType (); - t.GetMethod ("foo"); - NonTypeType.StaticMethod (); + class UnsupportedType + { + // The AttributeTargets don't support constructors. + // [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + // public UnsupportedType () { + // RequirePublicFields (this); + // } + + [ExpectedWarning ("IL2041")] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + public MethodInfo GetMethod (string name) + { + RequirePublicFields (this); + return null; + } + + [ExpectedWarning ("IL2041")] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + public static void StaticMethod () + { + } + } + + // Note: this returns a new instance, so that the GetMethod body is considered reachable. + // If nothing created an instance, ILLink would remove the GetMethod body and RequirePublicFields. + static UnsupportedType GetUnsupportedTypeInstance () => new (); + + [ExpectedWarning ("IL2098")] + static void RequirePublicFields ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + UnsupportedType unsupportedTypeInstance) { } + + [ExpectedWarning ("IL2075", nameof (UnsupportedType), nameof (UnsupportedType.GetMethod), Tool.Analyzer, "https://github.com/dotnet/runtime/issues/101211")] + static void TestMethodThisParameter () { + var t = GetUnsupportedTypeInstance (); + t.GetMethod ("foo"); + } + + // static void TestConstructorThisParameter () { + // new UnsupportedType (); + // } + + public static void Test () + { + TestMethodThisParameter (); + // TestConstructorThisParameter (); + UnsupportedType.StaticMethod (); + } } [ExpectedWarning ("IL2065", nameof (MethodThisDataFlowTypeTest) + "." + nameof (MethodThisDataFlowTypeTest.RequireThisNonPublicMethods), "'this'")] @@ -138,22 +183,6 @@ static void TestFromThisToOthers () GetWithPublicMethods ().PropagateToThis (); } - class NonTypeType - { - [ExpectedWarning ("IL2041")] - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] - public MethodInfo GetMethod (string name) - { - return null; - } - - [ExpectedWarning ("IL2041")] - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] - public static void StaticMethod () - { - } - } - struct StructType { int f; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ObjectGetTypeDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ObjectGetTypeDataflow.cs new file mode 100644 index 000000000000..e089abd68955 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ObjectGetTypeDataflow.cs @@ -0,0 +1,44 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Helpers; + +namespace Mono.Linker.Tests.Cases.DataFlow +{ + [SkipKeptItemsValidation] + [ExpectedNoWarnings] + public class ObjectGetTypeDataflow + { + public static void Main () + { + SealedConstructorAsSource.Test (); + } + + class SealedConstructorAsSource + { + [KeptMember (".ctor()")] + public class Base + { + } + + [KeptMember (".ctor()")] + [KeptBaseType (typeof (Base))] + public sealed class Derived : Base + { + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode (nameof (Method))] + public void Method () { } + } + + [ExpectedWarning ("IL2026", nameof (Derived.Method))] + public static void Test () + { + new Derived ().GetType ().GetMethod ("Method"); + } + } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs index 1a8930c8a7c8..76a1a48a0642 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/PropertyDataFlow.cs @@ -215,8 +215,7 @@ static Type PropertyWithSimpleGetter { // is highly unlikely to be done by anybody. If it happens, the analyzer will produce warnings which the trimming tools will not // but those warnings are not really wrong, so it's better if the developer fixes them anyway. [ExpectedWarning ("IL2077", nameof (DataFlowTypeExtensions) + "." + nameof (DataFlowTypeExtensions.RequiresPublicConstructors) + "(Type)", - nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWhichLooksLikeCompilerGenerated_Field), - ProducedBy = Tool.Analyzer)] + nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWhichLooksLikeCompilerGenerated_Field), Tool.Analyzer, "")] public void TestPropertyWhichLooksLikeCompilerGenerated () { // If the property was correctly recognized both the property getter and the backing field should get the annotation. @@ -231,8 +230,7 @@ public void TestPropertyWhichLooksLikeCompilerGenerated () static Type PropertyWhichLooksLikeCompilerGenerated { // See above comment about fake compiler generated backing fields - this warning is expected from the analyzer [ExpectedWarning ("IL2078", nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWhichLooksLikeCompilerGenerated) + ".get", - nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWhichLooksLikeCompilerGenerated_Field), - ProducedBy = Tool.Analyzer)] + nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWhichLooksLikeCompilerGenerated_Field), Tool.Analyzer, "")] get { return PropertyWhichLooksLikeCompilerGenerated_Field; } @@ -272,17 +270,14 @@ public void TestPropertyWithDifferentBackingFields () // Analyzer doesn't try to detect backing fields of properties: https://github.com/dotnet/linker/issues/2273 [ExpectedWarning ("IL2042", - "Mono.Linker.Tests.Cases.DataFlow.PropertyDataFlow.TestAutomaticPropagationType.PropertyWithDifferentBackingFields", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + "Mono.Linker.Tests.Cases.DataFlow.PropertyDataFlow.TestAutomaticPropagationType.PropertyWithDifferentBackingFields", Tool.Trimmer | Tool.NativeAot, "")] [ExpectedWarning ("IL2078", nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWithDifferentBackingFields) + ".get", - "Type", - ProducedBy = Tool.Analyzer)] + "Type", Tool.Analyzer, "")] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] Type PropertyWithDifferentBackingFields { [ExpectedWarning ("IL2078", - nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWithDifferentBackingFields) + ".get", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWithDifferentBackingFields) + ".get", Tool.Trimmer | Tool.NativeAot, "")] get { return PropertyWithDifferentBackingFields_GetterField; } @@ -299,25 +294,22 @@ public void TestPropertyWithExistingAttributes () } // Analyzer doesn't try to detect backing fields of properties: https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2056", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes_Field", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2056", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes_Field", Tool.Trimmer | Tool.NativeAot, "")] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] [CompilerGenerated] Type PropertyWithExistingAttributes_Field; - [ExpectedWarning ("IL2043", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.get", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2043", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.set", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2043", ["PropertyWithExistingAttributes", "PropertyWithExistingAttributes.get"], Tool.Analyzer, "")] + [ExpectedWarning ("IL2043", [ "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.set"], Tool.Analyzer, "")] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] Type PropertyWithExistingAttributes { // On property/accessor mismatch, ILLink warns on accessor and analyzer warns on property https://github.com/dotnet/linker/issues/2654 - [ExpectedWarning ("IL2043", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.get", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2043", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.get", Tool.Trimmer | Tool.NativeAot, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] get { return PropertyWithExistingAttributes_Field; } // On property/accessor mismatch, ILLink warns on accessor and analyzer warns on property https://github.com/dotnet/linker/issues/2654 - [ExpectedWarning ("IL2043", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.set", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2043", "PropertyWithExistingAttributes", "PropertyWithExistingAttributes.set", Tool.Trimmer | Tool.NativeAot, "")] [param: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] set { PropertyWithExistingAttributes_Field = value; } } @@ -337,25 +329,22 @@ public void TestPropertyWithConflictingAttributes () } // Analyzer doesn't try to detect backing fields of properties: https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2056", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes_Field", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2056", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes_Field", Tool.Trimmer | Tool.NativeAot, "")] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicConstructors)] [CompilerGenerated] Type PropertyWithConflictingAttributes_Field; - [ExpectedWarning ("IL2043", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.get", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2043", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.set", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2043", ["PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.get"], Tool.Analyzer, "")] + [ExpectedWarning ("IL2043", ["PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.set"], Tool.Analyzer, "")] [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] Type PropertyWithConflictingAttributes { // On property/accessor mismatch, ILLink warns on accessor and analyzer warns on property https://github.com/dotnet/linker/issues/2654 - [ExpectedWarning ("IL2043", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.get", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2043", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.get", Tool.Trimmer | Tool.NativeAot, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicConstructors)] get { return PropertyWithConflictingAttributes_Field; } // On property/accessor mismatch, ILLink warns on accessor and analyzer warns on property https://github.com/dotnet/linker/issues/2654 - [ExpectedWarning ("IL2043", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.set", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2043", "PropertyWithConflictingAttributes", "PropertyWithConflictingAttributes.set", Tool.Trimmer | Tool.NativeAot, "")] [param: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicConstructors)] set { PropertyWithConflictingAttributes_Field = value; } } @@ -382,8 +371,7 @@ public void TestPropertyWithConflictingNoneAttributes () Type PropertyWithConflictingNoneAttributes { // See above comment about fake compiler generated backing fields - this warning is expected from analyzer [ExpectedWarning ("IL2078", nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWithConflictingNoneAttributes) + ".get", - nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWithConflictingNoneAttributes_Field), - ProducedBy = Tool.Analyzer)] + nameof (TestAutomaticPropagationType) + "." + nameof (PropertyWithConflictingNoneAttributes_Field), Tool.Analyzer, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.None)] get { return PropertyWithConflictingNoneAttributes_Field; } @@ -399,8 +387,8 @@ public void TestPropertyWithIndexerWithMatchingAnnotations ([DynamicallyAccessed } // Trimmer and analyzer handle formatting of indexers differently. - [ExpectedWarning ("IL2067", nameof (PropertyWithIndexer) + ".Item.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2067", nameof (PropertyWithIndexer) + ".this[Int32].set", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2067", nameof (PropertyWithIndexer) + ".Item.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2067", nameof (PropertyWithIndexer) + ".this[Int32].set", Tool.Analyzer, "")] [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions) + "." + nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors) + "(Type)")] [LogDoesNotContain ("'Value passed to parameter 'index' of method 'Mono.Linker.Tests.Cases.DataFlow.PropertyDataFlow.TestAutomaticPropagationType.PropertyWithIndexer.Item.set'")] public void TestPropertyWithIndexerWithoutMatchingAnnotations (Type myType) @@ -418,8 +406,8 @@ public class PropertyWithIndexer [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] public Type this[int index] { // Trimmer and analyzer handle formatting of indexers differently. - [ExpectedWarning ("IL2063", nameof (PropertyWithIndexer) + ".Item.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2063", nameof (PropertyWithIndexer) + ".this[Int32].get", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2063", nameof (PropertyWithIndexer) + ".Item.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2063", nameof (PropertyWithIndexer) + ".this[Int32].get", Tool.Analyzer, "")] get => Property_Field[index]; set => Property_Field[index] = value; } @@ -482,8 +470,7 @@ class WriteToGetOnlyProperty public Type GetOnlyProperty { get; } // Analyzer doesn't warn about compiler-generated backing field of property: https://github.com/dotnet/runtime/issues/93277 - [ExpectedWarning ("IL2074", nameof (WriteToGetOnlyProperty), nameof (GetUnknownType), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2074", nameof (WriteToGetOnlyProperty), nameof (GetUnknownType), Tool.Trimmer | Tool.NativeAot, "")] public WriteToGetOnlyProperty () { GetOnlyProperty = GetUnknownType (); @@ -562,10 +549,8 @@ class WriteCapturedGetOnlyProperty Type GetOnlyProperty { get; } // Analyzer doesn't warn about compiler-generated backing field of property: https://github.com/dotnet/runtime/issues/93277 - [ExpectedWarning ("IL2074", nameof (WriteCapturedGetOnlyProperty), nameof (GetUnknownType), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2074", nameof (WriteCapturedGetOnlyProperty), nameof (GetTypeWithPublicConstructors), - ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2074", nameof (WriteCapturedGetOnlyProperty), nameof (GetUnknownType), Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2074", nameof (WriteCapturedGetOnlyProperty), nameof (GetTypeWithPublicConstructors), Tool.Trimmer | Tool.NativeAot, "")] public WriteCapturedGetOnlyProperty () { GetOnlyProperty = GetUnknownType () ?? GetTypeWithPublicConstructors (); @@ -677,15 +662,15 @@ Type this[Index idx] { set => throw new NotImplementedException (); } - [ExpectedWarning ("IL2072", "this[Index].get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", "Item.get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", ["this[Index].get", nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", ["Item.get", nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Trimmer | Tool.NativeAot, "")] static void TestRead (ExplicitIndexerAccess instance = null) { instance[new Index (1)].RequiresAll (); } - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "this[Index].set", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "Item.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", [nameof (GetTypeWithPublicConstructors), "this[Index].set"], Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", [nameof (GetTypeWithPublicConstructors), "Item.set"], Tool.Trimmer | Tool.NativeAot, "")] static void TestWrite (ExplicitIndexerAccess instance = null) { instance[^1] = GetTypeWithPublicConstructors (); @@ -708,22 +693,22 @@ Type this[int idx] { int Length => throw new NotImplementedException (); - [ExpectedWarning ("IL2072", "this[Int32].get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", "Item.get", nameof (DataFlowTypeExtensions.RequiresAll), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", ["this[Int32].get", nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", ["Item.get", nameof (DataFlowTypeExtensions.RequiresAll)], Tool.Trimmer | Tool.NativeAot, "")] static void TestRead (ImplicitIndexerAccess instance = null) { instance[new Index (1)].RequiresAll (); } - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "this[Int32].set", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetTypeWithPublicConstructors), "Item.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", [nameof (GetTypeWithPublicConstructors), "this[Int32].set"], Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", [nameof (GetTypeWithPublicConstructors), "Item.set"], Tool.Trimmer | Tool.NativeAot, "")] static void TestWrite (ImplicitIndexerAccess instance = null) { instance[^1] = GetTypeWithPublicConstructors (); } - [ExpectedWarning ("IL2072", nameof (GetUnknownType), "this[Int32].set", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2072", nameof (GetUnknownType), "Item.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2072", [nameof (GetUnknownType), "this[Int32].set"], Tool.Analyzer, "")] + [ExpectedWarning ("IL2072", [nameof (GetUnknownType), "Item.set"], Tool.Trimmer | Tool.NativeAot, "")] static void TestNullCoalescingAssignment (ImplicitIndexerAccess instance = null) { instance[new Index (1)] ??= GetUnknownType (); @@ -747,8 +732,8 @@ int this[[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicField get => throw new NotImplementedException (); } - [ExpectedWarning ("IL2067", "this[Type].get", nameof (ParamDoesNotMeetRequirements), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2067", "Item.get", nameof (ParamDoesNotMeetRequirements), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2067", ["this[Type].get", nameof (ParamDoesNotMeetRequirements)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2067", ["Item.get", nameof (ParamDoesNotMeetRequirements)], Tool.Trimmer | Tool.NativeAot, "")] static void ParamDoesNotMeetRequirements (Type t) { var x = new IndexWithTypeWithDam (); @@ -761,8 +746,8 @@ static void ParamDoesMeetRequirements ([DynamicallyAccessedMembers (DynamicallyA _ = x[t]; } - [ExpectedWarning ("IL2087", "this[Type].get", nameof (TypeParamDoesNotMeetRequirements), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2087", "Item.get", nameof (TypeParamDoesNotMeetRequirements), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2087", ["this[Type].get", nameof (TypeParamDoesNotMeetRequirements)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2087", ["Item.get", nameof (TypeParamDoesNotMeetRequirements)], Tool.Trimmer | Tool.NativeAot, "")] static void TypeParamDoesNotMeetRequirements () { var x = new IndexWithTypeWithDam (); @@ -802,8 +787,8 @@ Type this[[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFiel [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] static Type fieldWithMethods; - [ExpectedWarning ("IL2067", "this[Type].get", nameof (ParamDoesNotMeetRequirements), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2067", "Item.get", nameof (ParamDoesNotMeetRequirements), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2067", ["this[Type].get", nameof (ParamDoesNotMeetRequirements)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2067", ["Item.get", nameof (ParamDoesNotMeetRequirements)], Tool.Trimmer | Tool.NativeAot, "")] static void ParamDoesNotMeetRequirements (Type t) { var x = new IndexWithTypeWithDam (); @@ -816,8 +801,8 @@ static void ParamDoesMeetRequirements ([DynamicallyAccessedMembers (DynamicallyA fieldWithMethods = x[t]; } - [ExpectedWarning ("IL2087", "this[Type].get", nameof (TypeParamDoesNotMeetRequirements), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2087", "Item.get", nameof (TypeParamDoesNotMeetRequirements), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2087", ["this[Type].get", nameof (TypeParamDoesNotMeetRequirements)], Tool.Analyzer, "")] + [ExpectedWarning ("IL2087", ["Item.get", nameof (TypeParamDoesNotMeetRequirements)], Tool.Trimmer | Tool.NativeAot, "")] static void TypeParamDoesNotMeetRequirements () { var x = new IndexWithTypeWithDam (); @@ -839,16 +824,16 @@ static void KnownTypeDoesMeetRequirements () fieldWithMethods = x[t]; } - [ExpectedWarning ("IL2067", "this[Type].set", nameof (t), "idx", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2067", "Item.set", nameof (t), "idx", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2067", ["this[Type].set", nameof (t), "idx"], Tool.Analyzer, "")] + [ExpectedWarning ("IL2067", ["Item.set", nameof (t), "idx"], Tool.Trimmer | Tool.NativeAot, "")] static void ValueMeetsRequirementsIndexDoesNot (Type t) { var x = new IndexWithTypeWithDam (); x[t] = fieldWithMethods; } - [ExpectedWarning ("IL2067", "this[Type].set", nameof (tUnannotated), "value", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2067", "Item.set", nameof (tUnannotated), "value", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2067", ["this[Type].set", nameof (tUnannotated), "value"], Tool.Analyzer, "")] + [ExpectedWarning ("IL2067", ["Item.set", nameof (tUnannotated), "value"], Tool.Trimmer | Tool.NativeAot, "")] static void ValueDoesNotMeetRequirementsIndexDoes ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] Type t, Type tUnannotated) { var x = new IndexWithTypeWithDam (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/RefFieldDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/RefFieldDataFlow.cs index 415dff13582b..94db35301c6b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/RefFieldDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/RefFieldDataFlow.cs @@ -13,11 +13,10 @@ namespace Mono.Linker.Tests.Cases.DataFlow class RefFieldDataFlow { [Kept] - // Bug for the IL2069's here: https://github.com/dotnet/runtime/issues/85464 - [ExpectedWarning ("IL2069", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2069", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2069", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2069", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [UnexpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85464")] + [UnexpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85464")] + [UnexpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85464")] + [UnexpectedWarning ("IL2069", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85464")] public static void Main () { RefFieldWithMethods withMethods = new (ref fieldWithMethods); @@ -96,11 +95,11 @@ static void AssignRefToLocals< tmf = typeof (TF); // This is a hole that doesn't warn but assigns a misannotated value to target.T } - [ExpectedWarning ("IL2089", "RefFieldWithMethods", "T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2089", "RefFieldWithFields", "T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2089", "RefFieldWithMethodsAndFields", "T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2089", "RefFieldWithMethodsAndFields", "T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2089", "RefFieldWithFields", "T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2089", "RefFieldWithMethods", "T", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2089", "RefFieldWithFields", "T", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2089", "RefFieldWithMethodsAndFields", "T", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2089", "RefFieldWithMethodsAndFields", "T", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2089", "RefFieldWithFields", "T", Tool.Trimmer | Tool.NativeAot, "")] static void AssignRefLocals< T, [DAM (DAMT.PublicMethods)] TM, @@ -174,15 +173,14 @@ static void AssignParameters (scoped RefFieldWithMethods target, [ExpectedWarning ("IL2069", "RefFieldWithMethods.T", "paramWithFields")] [ExpectedWarning ("IL2077", "paramWithMethodsAndFields", "RefFieldWithMethods.T")] // ILLink doesn't recognize ldind.ref - // https://github.com/dotnet/runtime/issues/85465 // IL2064's are bugs - shouldn't be unknown values - [ExpectedWarning ("IL2064", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2064", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2064", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2064", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2064", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2069", "RefFieldWithMethods.T", "param", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2069", "RefFieldWithMethods.T", "paramWithFields", ProducedBy = Tool.Analyzer)] + [UnexpectedWarning ("IL2064", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] + [UnexpectedWarning ("IL2064", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] + [UnexpectedWarning ("IL2064", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] + [UnexpectedWarning ("IL2064", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] + [UnexpectedWarning ("IL2064", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] + [ExpectedWarning ("IL2069", "RefFieldWithMethods.T", "param", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/85465")] + [ExpectedWarning ("IL2069", "RefFieldWithMethods.T", "paramWithFields", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/85465")] static void AssignRefParameters< T, [DAM (DAMT.PublicMethods)] TM, @@ -233,15 +231,14 @@ static void AssignFields (RefFieldWithMethods target, UnannotatedField unannotat [ExpectedWarning ("IL2079", "RefFieldWithMethods.T", "RefFieldUnannotated.T")] [ExpectedWarning ("IL2079", "RefFieldWithMethods.T", "RefFieldWithFields.T")] - [ExpectedWarning ("IL2079", "RefFieldWithMethods.T", "RefFieldUnannotated.T", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2079", "RefFieldWithMethods.T", "RefFieldWithFields.T", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2079", "RefFieldWithMethods.T", "RefFieldUnannotated.T", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/85465")] + [ExpectedWarning ("IL2079", "RefFieldWithMethods.T", "RefFieldWithFields.T", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/85465")] // IL2064's are bugs - shouldn't be unknown values - // https://github.com/dotnet/runtime/issues/85465 - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = unannotated.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withMethods.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withFields.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withMethodsAndFields.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withMethodsAndFields.T; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = unannotated.T; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = withMethods.T; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = withFields.T; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = withMethodsAndFields.T; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = withMethodsAndFields.T; static void AssignRefFields ( RefFieldWithMethods target, RefFieldUnannotated unannotated, @@ -265,14 +262,13 @@ static void AssignRefFields ( [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "GetRefWithFields")] [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "GetRefUnannotated")] [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "GetRefWithFields")] - [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "GetRefUnannotated", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "GetRefWithFields", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "GetRefUnannotated", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/85465")] + [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "GetRefWithFields", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/85465")] // IL2064's are bugs - shouldn't be unknown values - // https://github.com/dotnet/runtime/issues/85465 - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = t; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = t; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = t; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = t; static void AssignRefReturns< T, [DAM (DAMT.PublicMethods)] TM, @@ -348,26 +344,25 @@ static void AssignProperties (RefFieldWithMethods target, } // target.T = x.T - [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropUnannotated.T", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropWithFields.T", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropUnannotated.T", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/85465")] + [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropWithFields.T", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/85465")] // target.T = t; - [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropUnannotated.T", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropWithFields.T", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropUnannotated.T", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/85465")] + [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropWithFields.T", Tool.Analyzer, "https://github.com/dotnet/runtime/issues/85465")] // target.T = ref x.T [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropUnannotated.T")] [ExpectedWarning ("IL2074", "RefFieldWithMethods.T", "RefPropWithFields.T")] // ref Type t = ref x.T; target.T = t; // IL2064's are bugs - shouldn't be unknown values - // https://github.com/dotnet/runtime/issues/85465 - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = unannotated.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withMethods.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withFields.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withMethodsAndFieldswithMtho.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = withMethods.T; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; - [ExpectedWarning ("IL2064", "RefFieldWithMethods.T", ProducedBy = Tool.Trimmer | Tool.NativeAot)] // target.T = t; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = unannotated.T; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = withMethods.T; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = withFields.T; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = withMethodsAndFieldswithMtho.T; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = withMethods.T; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = t; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = t; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = t; + [UnexpectedWarning ("IL2064", "RefFieldWithMethods.T", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/85465")] // target.T = t; static void AssignRefProperties (RefFieldWithMethods target, RefPropUnannotated unannotated = null, RefPropWithMethods withMethods = null, diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs index 8fc0362921be..445b1b6304dc 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/TypeBaseTypeDataFlow.cs @@ -58,9 +58,7 @@ static void TestAllPropagated ([DynamicallyAccessedMembers (DynamicallyAccessedM class AllPropagatedWithDerivedClass { - // https://github.com/dotnet/linker/issues/2673 - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll) + "(Type)", nameof (TestSystemTypeBase.BaseType) + ".get", - ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll) + "(Type)", nameof (TestSystemTypeBase.BaseType) + ".get", Tool.Analyzer, "https://github.com/dotnet/linker/issues/2673")] static void TestAllPropagated ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] TestSystemTypeBase derivedType) { derivedType.BaseType.RequiresAll (); @@ -284,7 +282,7 @@ static void EnumerateInterfacesOnBaseTypes ([DynamicallyAccessedMembers (Dynamic } [ExpectedWarning ("IL2070")] - [ExpectedWarning ("IL2075", ProducedBy = Tool.Analyzer)] // ILLink doesn't implement backward branches data flow yet + [ExpectedWarning ("IL2075", Tool.Analyzer, "")] // ILLink doesn't implement backward branches data flow yet static void EnumerateInterfacesOnBaseTypes_Unannotated (Type type) { Type? t = type; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnresolvedMembers.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnresolvedMembers.cs index e32c8727f91e..130f7ade7aa1 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnresolvedMembers.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnresolvedMembers.cs @@ -45,9 +45,9 @@ static void MethodWithUnresolvedGenericArgument< { } [Kept] - [ExpectedWarning ("IL2066", "TypeWithUnresolvedGenericArgument", ProducedBy = Tool.Trimmer | Tool.Analyzer)] // Local variable type - [ExpectedWarning ("IL2066", "TypeWithUnresolvedGenericArgument", ProducedBy = Tool.Trimmer | Tool.Analyzer)] // Called method declaring type - [ExpectedWarning ("IL2066", nameof (MethodWithUnresolvedGenericArgument), ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2066", "TypeWithUnresolvedGenericArgument", Tool.Trimmer | Tool.Analyzer, "")] // Local variable type + [ExpectedWarning ("IL2066", "TypeWithUnresolvedGenericArgument", Tool.Trimmer | Tool.Analyzer, "")] // Called method declaring type + [ExpectedWarning ("IL2066", nameof (MethodWithUnresolvedGenericArgument), Tool.Trimmer | Tool.Analyzer, "")] static void UnresolvedGenericArgument () { var a = new TypeWithUnresolvedGenericArgument (); @@ -77,7 +77,7 @@ public AttributeWithRequirements ( } [Kept] - [ExpectedWarning ("IL2062", nameof (AttributeWithRequirements), ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2062", nameof (AttributeWithRequirements), Tool.Trimmer | Tool.Analyzer, "")] [KeptAttributeAttribute (typeof (AttributeWithRequirements))] [AttributeWithRequirements (typeof (Dependencies.UnresolvedType))] static void UnresolvedAttributeArgument () @@ -85,7 +85,7 @@ static void UnresolvedAttributeArgument () } [Kept] - [ExpectedWarning ("IL2062", nameof (AttributeWithRequirements.PropertyWithRequirements), ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2062", nameof (AttributeWithRequirements.PropertyWithRequirements), Tool.Trimmer | Tool.Analyzer, "")] [KeptAttributeAttribute (typeof (AttributeWithRequirements))] [AttributeWithRequirements (typeof (EmptyType), PropertyWithRequirements = typeof (Dependencies.UnresolvedType))] static void UnresolvedAttributePropertyValue () @@ -93,7 +93,7 @@ static void UnresolvedAttributePropertyValue () } [Kept] - [ExpectedWarning ("IL2064", nameof (AttributeWithRequirements.FieldWithRequirements), ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2064", nameof (AttributeWithRequirements.FieldWithRequirements), Tool.Trimmer | Tool.Analyzer, "")] [KeptAttributeAttribute (typeof (AttributeWithRequirements))] [AttributeWithRequirements (typeof (EmptyType), FieldWithRequirements = typeof (Dependencies.UnresolvedType))] static void UnresolvedAttributeFieldValue () @@ -104,14 +104,14 @@ static void UnresolvedAttributeFieldValue () static Dependencies.UnresolvedType _unresolvedField; [Kept] - [ExpectedWarning ("IL2072", nameof (Object.GetType), ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (Object.GetType), Tool.Trimmer | Tool.Analyzer, "")] static void UnresolvedObjectGetType () { RequirePublicMethods (_unresolvedField.GetType ()); } [Kept] - [ExpectedWarning ("IL2072", nameof (Object.GetType), ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2072", nameof (Object.GetType), Tool.Trimmer | Tool.Analyzer, "")] static void UnresolvedMethodParameter () { RequirePublicMethods (typeof (Dependencies.UnresolvedType)); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/VirtualMethodHierarchyDataflowAnnotationValidation.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/VirtualMethodHierarchyDataflowAnnotationValidation.cs index a7725afafac6..d19bcfe349aa 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/VirtualMethodHierarchyDataflowAnnotationValidation.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/VirtualMethodHierarchyDataflowAnnotationValidation.cs @@ -50,6 +50,7 @@ public static void Main () StaticInterfaceMethods.Test (); BaseInPreservedScope.Test (); DirectCall.Test (); + RequiresAndDynamicallyAccessedMembersValidation.Test (); } static void RequirePublicMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) @@ -632,24 +633,24 @@ class ImplIDamOnAllMissing : IDamOnAll // NativeAOT doesn't validate overrides when accessed through reflection because it's a direct call (non-virtual) // So it doesn't matter that the annotations are not in-sync since the access will validate // the annotations on the implementation method - it doesn't even see the base method in this case. - [ExpectedWarning ("IL2092", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2093", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2092", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2093", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] public static Type AbstractMethod (Type type) => null; // NativeAOT doesn't validate overrides when accessed through reflection because it's a direct call (non-virtual) - [ExpectedWarning ("IL2092", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2093", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2092", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2093", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] public static Type VirtualMethod (Type type) => null; } class ImplIDamOnAllMismatch : IDamOnAll { // NativeAOT doesn't validate overrides when accessed through reflection because it's a direct call (non-virtual) - [ExpectedWarning ("IL2092", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2093", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2092", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2093", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] public static Type AbstractMethod <[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] @@ -659,9 +660,9 @@ public static Type AbstractMethod { return null; } // NativeAOT doesn't validate overrides when accessed through reflection because it's a direct call (non-virtual) - [ExpectedWarning ("IL2092", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2093", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2092", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2093", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] public static Type VirtualMethod <[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] @@ -705,9 +706,9 @@ class ImplIDamOnNoneMatch : IDamOnNone class ImplIDamOnNoneMismatch : IDamOnNone { // NativeAOT doesn't validate overrides when accessed through reflection because it's a direct call (non-virtual) - [ExpectedWarning ("IL2092", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2093", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2092", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2093", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] public static Type AbstractMethod <[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] @@ -717,9 +718,9 @@ public static Type AbstractMethod { return null; } // NativeAOT doesn't validate overrides when accessed through reflection because it's a direct call (non-virtual) - [ExpectedWarning ("IL2092", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2093", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2092", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2093", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] public static Type VirtualMethod <[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] @@ -748,7 +749,7 @@ class BaseInPreservedScope class ImplIAnnotatedMethodsMismatch : Library.IAnnotatedMethods { // NativeAOT doesn't always validate static overrides when accessed through reflection because it's a direct call (non-virtual) - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] public static void GenericWithMethodsStatic () { } [ExpectedWarning ("IL2092")] @@ -770,7 +771,7 @@ public void ParamWithMethods (Type t) { } class ImplIUnannotatedMethodsMismatch : Library.IUnannotatedMethods { // NativeAOT doesn't always validate static overrides when accessed through reflection because it's a direct call (non-virtual) - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] public static void GenericStatic<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { } [ExpectedWarning ("IL2092")] @@ -946,7 +947,7 @@ interface IBaseWithDefault interface IDerivedWithDefault : IBaseWithDefault { [ExpectedWarning ("IL2092")] - [ExpectedWarning ("IL2092", ProducedBy = Tool.Analyzer)] // https://github.com/dotnet/linker/issues/3121 + [UnexpectedWarning ("IL2092", Tool.Analyzer, "https://github.com/dotnet/linker/issues/3121")] void IBaseWithDefault.DefaultMethod ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { } } @@ -968,9 +969,9 @@ interface IGvmBase class ImplIGvmBase : IGvmBase { // NativeAOT doesn't validate overrides when it can resolve them as direct calls - [ExpectedWarning ("IL2092", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2093", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2095", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2092", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2093", Tool.Trimmer | Tool.Analyzer, "")] + [ExpectedWarning ("IL2095", Tool.Trimmer | Tool.Analyzer, "")] [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] public Type UnannotatedGvm<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) => null; @@ -1019,6 +1020,61 @@ public static void Test () CallStaticGvm (); } } + + class RequiresAndDynamicallyAccessedMembersValidation + { + // These tests have both DynamicallyAccessedMembers annotations and Requires annotations. + // This is to reproduce a bug where the virtual method annotations would be validated due to + // the presence of DynamicallyAccessedMembers, but the logic for checking Requires annotations + // was incorrect. The bug didn't manifest with just Requires annotations because the methods wouldn't + // be validated at all for Requires on type. + + class BaseMethodWithRequires + { + [RequiresUnreferencedCode (nameof (MethodWithRequires))] + [RequiresDynamicCode (nameof (MethodWithRequires))] + public virtual void MethodWithRequires ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type t) {} + } + + [RequiresUnreferencedCode (nameof (DerivedTypeWithRequires_BaseMethodWithRequires))] + [RequiresDynamicCode (nameof (DerivedTypeWithRequires_BaseMethodWithRequires))] + class DerivedTypeWithRequires_BaseMethodWithRequires : BaseMethodWithRequires + { + public override void MethodWithRequires ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type t) {} + } + + [ExpectedWarning ("IL2026", nameof (DerivedTypeWithRequires_BaseMethodWithRequires))] + [ExpectedWarning ("IL2026", nameof (DerivedTypeWithRequires_BaseMethodWithRequires.MethodWithRequires))] + [ExpectedWarning ("IL3050", nameof (DerivedTypeWithRequires_BaseMethodWithRequires), Tool.NativeAot | Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", nameof (DerivedTypeWithRequires_BaseMethodWithRequires.MethodWithRequires), Tool.NativeAot | Tool.Analyzer, "")] + static void Test_DerivedTypeWithRequires_BaseMethodWithRequires () + { + new DerivedTypeWithRequires_BaseMethodWithRequires ().MethodWithRequires (typeof (int)); + } + + class BaseMethodWithoutRequires + { + public virtual void MethodWithoutRequires ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type t) {} + } + + [RequiresUnreferencedCode (nameof (DerivedTypeWithRequires_BaseMethodWithoutRequires))] + class DerivedTypeWithRequires_BaseMethodWithoutRequires : BaseMethodWithoutRequires + { + public override void MethodWithoutRequires ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type t) {} + } + + [ExpectedWarning ("IL2026", nameof (DerivedTypeWithRequires_BaseMethodWithoutRequires))] + static void Test_DerivedTypeWithRequires_BaseMethodWithoutRequires () + { + new DerivedTypeWithRequires_BaseMethodWithoutRequires ().MethodWithoutRequires (typeof (int)); + } + + public static void Test () + { + Test_DerivedTypeWithRequires_BaseMethodWithRequires (); + Test_DerivedTypeWithRequires_BaseMethodWithoutRequires (); + } + } } } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXml.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXml.cs index e80a60f55ec2..7c9acc549bdf 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXml.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXml.cs @@ -7,7 +7,7 @@ namespace Mono.Linker.Tests.Cases.DynamicDependencies // and will be found always. // For mono though, we have to specify the assembly (Mono.Linker.Tests.Cases.Expectations) because at the time of processing // that assembly is not yet loaded into the closure in ILLink, so it won't find the attribute type. -#if NETCOREAPP +#if NET [SetupLinkAttributesFile ("DynamicDependencyFromAttributeXml.netcore.Attributes.xml")] #else [SetupLinkAttributesFile ("DynamicDependencyFromAttributeXml.mono.Attributes.xml")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXmlOnNonReferencedAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXmlOnNonReferencedAssembly.cs index f3daf2eeaf03..6660e84b1ec1 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXmlOnNonReferencedAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyFromAttributeXmlOnNonReferencedAssembly.cs @@ -12,7 +12,7 @@ namespace Mono.Linker.Tests.Cases.DynamicDependencies [KeptAssembly ("field_library.dll")] [KeptMemberInAssembly ("method_library.dll", "Mono.Linker.Tests.Cases.DynamicDependencies.Dependencies.DynamicDependencyFromAttributeXmlOnNonReferencedAssemblyLibrary_Method", "Method()")] [KeptMemberInAssembly ("field_library.dll", "Mono.Linker.Tests.Cases.DynamicDependencies.Dependencies.DynamicDependencyFromAttributeXmlOnNonReferencedAssemblyLibrary_Field", "Method()")] -#if NETCOREAPP +#if NET [SetupLinkAttributesFile ("DynamicDependencyFromAttributeXmlOnNonReferencedAssembly.netcore.Attributes.xml")] #else [SetupLinkAttributesFile ("DynamicDependencyFromAttributeXmlOnNonReferencedAssembly.mono.Attributes.xml")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Extensibility/CustomWarningUsage.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Extensibility/CustomWarningUsage.cs index 063038c93ead..941f6c59e543 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Extensibility/CustomWarningUsage.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Extensibility/CustomWarningUsage.cs @@ -10,7 +10,7 @@ namespace Mono.Linker.Tests.Cases.Extensibility [ExpectedNoWarnings] public class CustomWarningUsage { - [ExpectedWarning ("IL2026", "--RUCMethod--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--RUCMethod--", Tool.Analyzer, "")] public static void Main () { new KnownTypeThatShouldWarn (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsKept.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsKept.cs index 61ebdf89cda8..048dfb63629b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsKept.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsKept.cs @@ -21,6 +21,9 @@ public static void Main () [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")] interface IBar { + // Trimming may remove members from COM interfaces + // even when keeping the COM-related attributes. + // https://github.com/dotnet/runtime/issues/101128 void Bar (); } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsRemoved.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsRemoved.cs new file mode 100644 index 000000000000..64612b1b704f --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsRemoved.cs @@ -0,0 +1,40 @@ +using System.Runtime.InteropServices; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType +{ + /// + /// With --keep-com-interfaces false, we apply the unused interface rules also to com interfaces. + /// + [SetupLinkerArgument ("--keep-com-interfaces", "false")] + public class UnusedComInterfaceIsRemoved + { + public static void Main () + { + var i = new A (); + i.Foo (); + } + + [ComImport] + [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")] + interface IBar + { + void Bar (); + } + + [Kept] + [KeptMember (".ctor()")] + class A : IBar + { + [Kept] + public void Foo () + { + } + + public void Bar () + { + } + } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemoval.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemoval.cs index 9a8e4c4cb28c..3a7317444127 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemoval.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkAttributes/LinkerAttributeRemoval.cs @@ -17,7 +17,7 @@ namespace Mono.Linker.Tests.Cases.LinkAttributes [SetupCompileBefore ("attribute.dll", new[] { "Dependencies/LinkerAttributeRemovalAttributeToRemove.cs" })] [SetupCompileBefore ("copyattribute.dll", new[] { "Dependencies/LinkerAttributeRemovalAttributeFromCopyAssembly.cs" })] [SetupLinkerAction ("copy", "copyattribute")] -#if !NETCOREAPP +#if !NET [Reference ("System.dll")] [SetupCompileBefore ("copyassembly.dll", new[] { "Dependencies/LinkerAttributeRemovalCopyAssembly.cs" }, references: new[] { "System.dll", "attribute.dll" })] #else diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkXml/LinkXmlErrorCases.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkXml/LinkXmlErrorCases.cs index 074216595ed3..e9021db105d4 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkXml/LinkXmlErrorCases.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/LinkXml/LinkXmlErrorCases.cs @@ -6,6 +6,7 @@ namespace Mono.Linker.Tests.Cases.LinkXml { [SetupLinkerDescriptorFile ("LinkXmlErrorCases.xml")] [SetupLinkerArgument ("--skip-unresolved", "true")] + [SetupLinkerArgument ("--verbose")] [ExpectedWarning ("IL2001", "TypeWithNoFields", FileName = "LinkXmlErrorCases.xml", SourceLine = 3, SourceColumn = 6)] [ExpectedWarning ("IL2002", "TypeWithNoMethods", FileName = "LinkXmlErrorCases.xml", SourceLine = 4, SourceColumn = 6)] @@ -17,13 +18,18 @@ namespace Mono.Linker.Tests.Cases.LinkXml [ExpectedWarning ("IL2017", "NonExistentProperty", "TypeWithNoProperties", FileName = "LinkXmlErrorCases.xml", SourceLine = 21, SourceColumn = 8)] [ExpectedWarning ("IL2018", "SetOnlyProperty", "TypeWithProperties", FileName = "LinkXmlErrorCases.xml", SourceLine = 25, SourceColumn = 8)] [ExpectedWarning ("IL2019", "GetOnlyProperty", "TypeWithProperties", FileName = "LinkXmlErrorCases.xml", SourceLine = 26, SourceColumn = 8)] - [ExpectedWarning ("IL2025", "Method", FileName = "LinkXmlErrorCases.xml", SourceLine = 39, SourceColumn = 8, ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2025", "Event", FileName = "LinkXmlErrorCases.xml", SourceLine = 40, SourceColumn = 8, ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2025", "Field", FileName = "LinkXmlErrorCases.xml", SourceLine = 41, SourceColumn = 8, ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2025", "Property", FileName = "LinkXmlErrorCases.xml", SourceLine = 42, SourceColumn = 8, ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'System.Int32 Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases/TypeWithEverything::Field'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases.TypeWithEverything.TypeWithEverything()'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases.TypeWithEverything.Method()'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'System.EventHandler Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases/TypeWithEverything::Event'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases.TypeWithEverything.Event.add'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases.TypeWithEverything.Event.remove'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'System.Int32 Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases/TypeWithEverything::Property()'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases.TypeWithEverything.Property.get'", ProducedBy = Tool.Trimmer)] + [LogContains ("Duplicate preserve of 'Mono.Linker.Tests.Cases.LinkXml.LinkXmlErrorCases.TypeWithEverything.Property.set'", ProducedBy = Tool.Trimmer)] // NativeAOT doesn't support wildcard * and will skip usages of it, including if they would warn // https://github.com/dotnet/runtime/issues/80466 - [ExpectedWarning ("IL2100", FileName = "LinkXmlErrorCases.xml", SourceLine = 50, SourceColumn = 4, ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2100", Tool.Trimmer, "", FileName = "LinkXmlErrorCases.xml", SourceLine = 50, SourceColumn = 4)] class LinkXmlErrorCases { public static void Main () diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Logging/SourceLines.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Logging/SourceLines.cs index 4da189cced1f..e6f445dfaca2 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Logging/SourceLines.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Logging/SourceLines.cs @@ -31,16 +31,16 @@ static Type GetUnknownType () // Analyzer test infrastructure doesn't support ExpectedWarning at the top-level. // This is OK because the test is meant to validate that the ILLink infrastructure produces the right line numbers, // and we have separate tests to check the line number of analyzer warnings. - [ExpectedWarning ("IL2074", nameof (SourceLines) + "." + nameof (type), nameof (SourceLines) + "." + nameof (GetUnknownType) + "()", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2074", nameof (SourceLines) + "." + nameof (type), nameof (SourceLines) + "." + nameof (GetUnknownType) + "()", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2074", nameof (SourceLines) + "." + nameof (type), nameof (SourceLines) + "." + nameof (GetUnknownType) + "()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2074", nameof (SourceLines) + "." + nameof (type), nameof (SourceLines) + "." + nameof (GetUnknownType) + "()", Tool.Analyzer, "")] static void UnrecognizedReflectionPattern () { type = GetUnknownType (); // IL2074 type = GetUnknownType (); // IL2074 } - [ExpectedWarning ("IL2091", "LocalFunction()", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2089", nameof (SourceLines) + "." + nameof (type), "TOuterMethod", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2091", "LocalFunction()", Tool.Analyzer, "")] + [ExpectedWarning ("IL2089", nameof (SourceLines) + "." + nameof (type), "TOuterMethod", Tool.Analyzer, "")] static IEnumerable GenericMethodIteratorWithRequirement<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TOuterMethod> () { LocalFunction (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ActivatorCreateInstance.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ActivatorCreateInstance.cs index a14030d90ad1..4aca2d518618 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ActivatorCreateInstance.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ActivatorCreateInstance.cs @@ -171,8 +171,8 @@ public FromParameterOnStaticMethodTypeB (int arg) { } } // Small formatting difference - [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, Object[])", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, params Object[])", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, Object[])", Tool.Trimmer, "")] + [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, params Object[])", Tool.Analyzer, "")] [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance), nameof (CultureInfo))] [Kept] private void FromParameterOnInstanceMethod ( @@ -197,8 +197,8 @@ public FromParameterOnInstanceMethodType (int arg, int arg2) { } [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type)")] // Small formatting difference - [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, Object[])", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, params Object[])", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, Object[])", Tool.Trimmer, "")] + [ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, params Object[])", Tool.Analyzer, "")] [Kept] private static void FromParameterWithNonPublicConstructors ( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] @@ -375,7 +375,7 @@ private static void WithAssemblyAndNoValueTypeName () [Kept] // Analyzer doesn't handle assembly resolution - [ExpectedWarning ("IL2061", nameof (Activator) + "." + nameof (Activator.CreateInstance), "NonExistingAssembly", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2061", nameof (Activator) + "." + nameof (Activator.CreateInstance), "NonExistingAssembly", Tool.Trimmer, "")] private static void WithNonExistingAssemblyName () { Activator.CreateInstance ("NonExistingAssembly", "Mono.Linker.Tests.Cases.Reflection.ActivatorCreateInstance+WithAssemblyNameParameterless1"); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs index 7ca59831a01a..dae1731331bb 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs @@ -16,7 +16,7 @@ public static void Main () GetConstructor_BindingAttr_Binder_Types_Modifiers.TestWithBindingFlags (); GetConstructor_BindingAttr_Binder_Types_Modifiers.TestWithUnknownBindingFlags (BindingFlags.Public); GetConstructor_BindingAttr_Binder_CallConvention_Types_Modifiers.TestWithCallingConvention (); -#if NETCOREAPP +#if NET GetConstructor_BindingAttr_Types.Test (); #endif TestNullType (); @@ -217,7 +217,7 @@ public static void TestWithCallingConvention () } } -#if NETCOREAPP +#if NET [Kept] class GetConstructor_BindingAttr_Types { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyMethodInfo.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyMethodInfo.cs index 5fa8b48caddc..27f3422c76d9 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyMethodInfo.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyMethodInfo.cs @@ -83,12 +83,10 @@ public int InstancePropertyViaReflection { } [Kept] - // https://github.com/dotnet/linker/issues/2669 - [ExpectedWarning ("IL2026", nameof (StaticPropertyExpressionAccess), ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", nameof (StaticPropertyExpressionAccess), Tool.Trimmer, "https://github.com/dotnet/linker/issues/2669")] [ExpectedWarning ("IL2026", nameof (StaticPropertyViaReflection))] [ExpectedWarning ("IL2026", nameof (StaticPropertyViaRuntimeMethod))] - // https://github.com/dotnet/linker/issues/2669 - [ExpectedWarning ("IL2026", nameof (InstancePropertyExpressionAccess), ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", nameof (InstancePropertyExpressionAccess), Tool.Trimmer, "https://github.com/dotnet/linker/issues/2669")] [ExpectedWarning ("IL2026", nameof (InstancePropertyViaReflection))] public static void Test () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs index baf8860765d2..55e6c440fbc1 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs @@ -26,7 +26,7 @@ public static void Main () GetMethod_Name_BindingAttr.TestUnknownNameAndWrongBindingFlags ("Unknown"); GetMethod_Name_BindingAttr_Binder_Types_Modifiers.TestNameBindingFlagsAndParameterModifier (); GetMethod_Name_BindingAttr_Binder_CallConvention_Types_Modifiers.TestNameBindingFlagsCallingConventionParameterModifier (); -#if NETCOREAPP +#if NET GetMethod_Name_BindingAttr_Types.TestNameBindingFlagsAndTypes (); GetMethod_Name_GenericParameterCount_Types.TestNameWithIntAndType (); GetMethod_Name_GenericParameterCount_Types_Modifiers.TestNameWithIntAndTypeAndModifiers (); @@ -391,7 +391,7 @@ public static void TestNameBindingFlagsCallingConventionParameterModifier () } } -#if NETCOREAPP +#if NET // GetMethod(string name, BindingFlags bindingAttr, Type[] types) [Kept] class GetMethod_Name_BindingAttr_Types diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodsUsedViaReflection.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodsUsedViaReflection.cs index c91fb020f7fe..c6cb02a55017 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodsUsedViaReflection.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodsUsedViaReflection.cs @@ -337,8 +337,7 @@ private void PrivateMethodWithRUC () { } } [Kept] - // https://github.com/dotnet/linker/issues/2638 - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", Tool.Trimmer, "https://github.com/dotnet/linker/issues/2638")] public static void Test () { BindingFlags left = BindingFlags.Instance | BindingFlags.Static; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ObjectGetType.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ObjectGetType.cs index 9ec76e4de21e..3dcd1b7fd117 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ObjectGetType.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ObjectGetType.cs @@ -295,9 +295,7 @@ public void UnusedMethod () { } } [Kept] - // https://github.com/dotnet/runtime/issues/93718 - // This should not warn - [ExpectedWarning ("IL2075", "GetMethod", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [UnexpectedWarning ("IL2075", "GetMethod", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/93718")] static void TestStruct (BasicAnnotatedStruct instance) { instance.GetType ().GetMethod ("UsedMethod"); @@ -682,8 +680,7 @@ public void Method () { } } [Kept] - // https://github.com/dotnet/linker/issues/2755 - [ExpectedWarning ("IL2075", "GetMethod", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2075", "GetMethod")] public static void Test () { new Derived ().GetType ().GetMethod ("Method"); @@ -1409,8 +1406,7 @@ public void Method () { } static IEnumerable GetInstances () => new AnnotatedBase[] { new Derived () }; [Kept] - // https://github.com/dotnet/runtime/issues/93719 - [ExpectedWarning ("IL2075", nameof (Type.GetType), ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [UnexpectedWarning ("IL2075", nameof (Type.GetType), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/93719")] public static void Test () { foreach (var instance in GetInstances ()) { @@ -1585,9 +1581,7 @@ class Target } [Kept] - // https://github.com/dotnet/runtime/issues/93720 - // https://github.com/dotnet/linker/issues/2755 - [ExpectedWarning ("IL2072", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [UnexpectedWarning ("IL2072", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/runtime/issues/93720")] static void TestIsInstOf (object o) { if (o is Target t) { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchyReflectionWarnings.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchyReflectionWarnings.cs index 13ecc2ec2906..7579257e7908 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchyReflectionWarnings.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeHierarchyReflectionWarnings.cs @@ -250,7 +250,7 @@ public event MyEventHandler RUCEvent { [Kept] [ExpectedWarning ("IL2112", nameof (AnnotatedPublicEvents), "--RUC on add_RUCEvent--")] // https://github.com/dotnet/runtime/issues/100499 - [ExpectedWarning ("IL2112", nameof (AnnotatedPublicEvents), "--RUC on add_RUCEvent--", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2112", [nameof (AnnotatedPublicEvents), "--RUC on add_RUCEvent--"], Tool.Trimmer, "")] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] [RequiresUnreferencedCode ("--RUC on add_RUCEvent--")] add { } @@ -313,7 +313,7 @@ class DerivedFromAnnotatedPublicParameterlessConstructor : AnnotatedPublicParame [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] [ExpectedWarning ("IL2112", "--RUC on DerivedFromAnnotatedPublicParameterlessConstructor()--")] - [ExpectedWarning ("IL2112", "--RUC on DerivedFromAnnotatedPublicParameterlessConstructor()--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "--RUC on DerivedFromAnnotatedPublicParameterlessConstructor()--", Tool.Trimmer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("--RUC on DerivedFromAnnotatedPublicParameterlessConstructor()--")] public DerivedFromAnnotatedPublicParameterlessConstructor () { } @@ -701,18 +701,16 @@ public class Base [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] [RequiresUnreferencedCode ("--RUCOnVirtualMethodDerivedAnnotated.Base.RUCVirtualMethod--")] - // https://github.com/dotnet/runtime/issues/86580 // Compare to the case above - the only difference is the type of the field // and it causes different warnings to be produced. - // [ExpectedWarning ("IL2112", "--RUCOnVirtualMethodDerivedAnnotated.Base.RUCVirtualMethod--")] + [ExpectedWarning ("IL2112", "--RUCOnVirtualMethodDerivedAnnotated.Base.RUCVirtualMethod--", Tool.None, "https://github.com/dotnet/runtime/issues/86580")] public virtual void RUCVirtualMethod () { } } [Kept] [KeptMember (".ctor()")] [KeptBaseType (typeof (Base))] - // https://github.com/dotnet/runtime/issues/86580 - [ExpectedWarning ("IL2113", "--RUCOnVirtualMethodDerivedAnnotated.Base.RUCVirtualMethod--", ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2113", "--RUCOnVirtualMethodDerivedAnnotated.Base.RUCVirtualMethod--", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/86580")] public class Derived : Base { [Kept] @@ -755,8 +753,7 @@ public virtual void VirtualMethodWithRequires () { } [Kept] [KeptBaseType (typeof (AnnotatedBase))] [KeptMember (".ctor()")] - // https://github.com/dotnet/runtime/issues/86580 - [ExpectedWarning ("IL2113", "--AnnotatedBase.VirtualMethodWithRequires--", ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2113", "--AnnotatedBase.VirtualMethodWithRequires--", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/86580")] class Derived : AnnotatedBase { [Kept] @@ -956,7 +953,7 @@ static void LocalFunctionWithDAMInner ([DynamicallyAccessedMembers(DynamicallyAc [Kept] [KeptAttributeAttribute (typeof (IteratorStateMachineAttribute))] - [ExpectedWarning ("IL2119", nameof (IteratorWithGenericDAM), CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2119", nameof (IteratorWithGenericDAM), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042", CompilerGeneratedCode = true)] static IEnumerable IteratorWithGenericDAM< [KeptAttributeAttribute(typeof(DynamicallyAccessedMembersAttribute))] [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T> () @@ -968,7 +965,7 @@ static IEnumerable IteratorWithGenericDAM< [Kept] [KeptAttributeAttribute (typeof (AsyncStateMachineAttribute))] [KeptAttributeAttribute (typeof (DebuggerStepThroughAttribute))] - [ExpectedWarning ("IL2119", nameof (AsyncWithGenericDAM), CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2119", nameof (AsyncWithGenericDAM), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042", CompilerGeneratedCode = true)] static async Task AsyncWithGenericDAM< [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() @@ -979,7 +976,7 @@ static async Task AsyncWithGenericDAM< [Kept] [KeptAttributeAttribute (typeof (AsyncIteratorStateMachineAttribute))] - [ExpectedWarning("IL2119", nameof(AsyncIteratorWithGenericDAM), CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + [ExpectedWarning("IL2119", nameof(AsyncIteratorWithGenericDAM), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042", CompilerGeneratedCode = true)] static async IAsyncEnumerable AsyncIteratorWithGenericDAM< [KeptAttributeAttribute(typeof(DynamicallyAccessedMembersAttribute))] [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs index 3e5752977d7b..981ad6227ceb 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs @@ -331,9 +331,9 @@ public class OverloadWith5ParametersWithIgnoreCase { } [Kept] // Small difference in formatting between analyzer/NativeAOT/linker - [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2096", "'System.Type.GetType(String,Func`2,Func`4,Boolean,Boolean)'", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", Tool.Trimmer, "")] + [ExpectedWarning ("IL2096", "'System.Type.GetType(String,Func`2,Func`4,Boolean,Boolean)'", Tool.NativeAot, "")] + [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", Tool.Analyzer, "")] static void TestTypeOverloadWith5ParametersWithIgnoreCase () { const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+OverloadWith5ParametersWithIgnoreCase"; @@ -384,9 +384,9 @@ static void TestUnknownIgnoreCase3Params (int num) [Kept] // Small difference in formatting between analyzer/NativeAOT/linker - [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2096", "'System.Type.GetType(String,Func`2,Func`4,Boolean,Boolean)'", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", Tool.Trimmer, "")] + [ExpectedWarning ("IL2096", "'System.Type.GetType(String,Func`2,Func`4,Boolean,Boolean)'", Tool.NativeAot, "")] + [ExpectedWarning ("IL2096", "'System.Type.GetType(String, Func, Func, Boolean, Boolean)'", Tool.Analyzer, "")] static void TestUnknownIgnoreCase5Params (int num) { const string reflectionTypeKeptString = "mono.linker.tests.cases.reflection.TypeUsedViaReflection+CaseUnknown2, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"; @@ -404,10 +404,9 @@ public class GenericTypeWithAnnotations_OuterType< [Kept] public class GenericTypeWithAnnotations_InnerType { - // NativeAOT: https://github.com/dotnet/runtime/issues/95140 - [Kept (By = Tool.Trimmer)] + [Kept] [KeptBackingField] - private static bool PrivateProperty { [Kept (By = Tool.Trimmer)] get; [Kept (By = Tool.Trimmer)] set; } + private static bool PrivateProperty { [Kept] get; [Kept] set; } private static void PrivateMethod () { } } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs index d9536b935810..453f5661502f 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs @@ -28,8 +28,8 @@ public static void Main () } [ExpectedWarning ("IL2026", "Message for --RequiresWithMessageOnly--.")] - [ExpectedWarning ("IL3002", "Message for --RequiresWithMessageOnly--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --RequiresWithMessageOnly--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message for --RequiresWithMessageOnly--.", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Message for --RequiresWithMessageOnly--.", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresWithMessageOnlyOnMethod () { RequiresWithMessageOnly (); @@ -43,8 +43,8 @@ static void RequiresWithMessageOnly () } [ExpectedWarning ("IL2026", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl")] - [ExpectedWarning ("IL3002", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresWithMessageAndUrlOnMethod () { RequiresWithMessageAndUrl (); @@ -58,8 +58,8 @@ static void RequiresWithMessageAndUrl () } [ExpectedWarning ("IL2026", "Message for --ConstructorRequires--.")] - [ExpectedWarning ("IL3002", "Message for --ConstructorRequires--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --ConstructorRequires--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message for --ConstructorRequires--.", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Message for --ConstructorRequires--.", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresOnConstructor () { new ConstructorRequires (); @@ -77,10 +77,10 @@ public ConstructorRequires () [ExpectedWarning ("IL2026", "Message for --getter PropertyRequires--.")] [ExpectedWarning ("IL2026", "Message for --setter PropertyRequires--.")] - [ExpectedWarning ("IL3002", "Message for --getter PropertyRequires--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "Message for --setter PropertyRequires--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --getter PropertyRequires--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --setter PropertyRequires--.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message for --getter PropertyRequires--.", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "Message for --setter PropertyRequires--.", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Message for --getter PropertyRequires--.", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Message for --setter PropertyRequires--.", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresOnPropertyGetterAndSetter () { _ = PropertyRequires; @@ -107,8 +107,8 @@ static void WarningMessageWithoutEndingPeriod () } [ExpectedWarning ("IL2026", "Adds a trailing period to this message.")] - [ExpectedWarning ("IL3002", "Adds a trailing period to this message.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Adds a trailing period to this message.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Adds a trailing period to this message.", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Adds a trailing period to this message.", Tool.Analyzer | Tool.NativeAot, "")] static void TestThatTrailingPeriodIsAddedToMessage () { WarningMessageWithoutEndingPeriod (); @@ -123,8 +123,8 @@ static void WarningMessageEndsWithPeriod () [LogDoesNotContain ("Does not add a period to this message..")] [ExpectedWarning ("IL2026", "Does not add a period to this message.")] - [ExpectedWarning ("IL3002", "Does not add a period to this message.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Does not add a period to this message.", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Does not add a period to this message.", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Does not add a period to this message.", Tool.Analyzer | Tool.NativeAot, "")] static void TestThatTrailingPeriodIsNotDuplicatedInWarningMessage () { WarningMessageEndsWithPeriod (); @@ -157,11 +157,11 @@ static event EventHandler EventToTestAdd { static event EventHandler AnnotatedEvent; [ExpectedWarning ("IL2026", "--EventToTestRemove.remove--")] - [ExpectedWarning ("IL3002", "--EventToTestRemove.remove--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--EventToTestRemove.remove--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--EventToTestRemove.remove--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--EventToTestRemove.remove--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--EventToTestAdd.add--")] - [ExpectedWarning ("IL3002", "--EventToTestAdd.add--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--EventToTestAdd.add--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--EventToTestAdd.add--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--EventToTestAdd.add--", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { EventToTestRemove -= (sender, e) => { }; @@ -181,8 +181,8 @@ public static void GenericTypeWithStaticMethodWhichRequires () { } } [ExpectedWarning ("IL2026", "--GenericTypeWithStaticMethodWhichRequires--")] - [ExpectedWarning ("IL3002", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--GenericTypeWithStaticMethodWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--GenericTypeWithStaticMethodWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] public static void GenericTypeWithStaticMethodViaLdftn () { var _ = new Action (GenericWithStaticMethod.GenericTypeWithStaticMethodWhichRequires); @@ -208,8 +208,8 @@ static void Requires () { } [RequiresAssemblyFiles ("--PropertyRequires--")] static int PropertyRequires { get; set; } - [ExpectedWarning ("IL3002", "--PropertyRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--PropertyRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--PropertyRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--PropertyRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestProperty () { var a = PropertyRequires; @@ -219,11 +219,11 @@ static void TestProperty () [RequiresAssemblyFiles ("--EventRequires--")] static event EventHandler EventRequires; - [ExpectedWarning ("IL3002", "--EventRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--EventRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--EventRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--EventRequires--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--RequiresOnEventLambda--")] - [ExpectedWarning ("IL3002", "--RequiresOnEventLambda--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--RequiresOnEventLambda--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--RequiresOnEventLambda--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--RequiresOnEventLambda--", Tool.Analyzer | Tool.NativeAot, "")] static void TestEvent () { EventRequires += (object sender, EventArgs e) => throw new NotImplementedException (); @@ -237,7 +237,7 @@ static void TestEvent () EventRequires (null, null); // no warning on invocation } - [ExpectedWarning("IL3002", "--Requires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning("IL3002", "--Requires--", Tool.Analyzer | Tool.NativeAot, "")] public static void Test() { Requires (); @@ -251,7 +251,7 @@ class DynamicCodeOnly [RequiresDynamicCode ("--Requires--")] static void Requires () { } - [ExpectedWarning ("IL3050", "--Requires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--Requires--", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { Requires (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs index 2b2c0438c1d0..683175d1dd84 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs @@ -24,10 +24,9 @@ public static void Main () class ReflectionAccessFromStateMachine { [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101998", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101998", CompilerGeneratedCode = true)] + [UnexpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042", CompilerGeneratedCode = true)] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations), CompilerGeneratedCode = true)] static IEnumerable TestIterator () { @@ -45,10 +44,9 @@ static IEnumerable TestIteratorWithRUC () } [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101998", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101998", CompilerGeneratedCode = true)] + [UnexpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042", CompilerGeneratedCode = true)] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations), CompilerGeneratedCode = true)] static async void TestAsync () { @@ -66,11 +64,11 @@ static async void TestAsyncWithRUC () } [ExpectedWarning ("IL2026", "--TestIteratorWithRUC--")] - [ExpectedWarning ("IL3002", "--TestIteratorWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--TestIteratorWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--TestIteratorWithRUC--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--TestIteratorWithRUC--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] [ExpectedWarning ("IL2026", "--TestAsyncWithRUC--")] - [ExpectedWarning ("IL3002", "--TestAsyncWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--TestAsyncWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--TestAsyncWithRUC--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--TestAsyncWithRUC--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] public static void Test () { TestIterator ().GetEnumerator ().MoveNext (); // Must actually use the enumerator, otherwise NativeAOT will trim the implementation @@ -85,10 +83,9 @@ class ReflectionAccessFromLocalFunction static void TestLocalFunction () { [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101998")] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101998")] + [UnexpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations))] void LocalFunction () { @@ -98,8 +95,8 @@ void LocalFunction () } [ExpectedWarning ("IL2026", "--LocalFunction--")] - [ExpectedWarning ("IL3002", "--LocalFunction--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--LocalFunction--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--LocalFunction--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--LocalFunction--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] static void TestLocalFunctionWithRUC () { [RequiresUnreferencedCode ("--LocalFunction--")] @@ -125,8 +122,8 @@ void LocalFunction () } [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRUC--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] public static void Test () { TestLocalFunction (); @@ -141,10 +138,9 @@ static void TestLambda () { var lambda = [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101998")] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/101998")] + [UnexpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations))] () => { typeof (TypeWithMethodWithRequires).RequiresAll (); @@ -153,8 +149,8 @@ static void TestLambda () } [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRUC--")] - [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] static void TestLambdaWithRUC () { var lambda = @@ -168,8 +164,8 @@ static void TestLambdaWithRUC () } [ExpectedWarning ("IL2026", "--TestLambdaWithRUCLdftn--")] - [ExpectedWarning ("IL3002", "--TestLambdaWithRUCLdftn--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--TestLambdaWithRUCLdftn--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--TestLambdaWithRUCLdftn--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--TestLambdaWithRUCLdftn--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] static void TestLambdaWithRUCLdftn () { var lambda = @@ -196,8 +192,8 @@ static void TestLambdaInMethodWithRUC () } [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRUC--")] - [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] public static void Test () { TestLambda (); @@ -224,8 +220,8 @@ public static void MethodWithRequires () public static void MethodWithAnnotations ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type t) { } [ExpectedWarning ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--")] - [ExpectedWarning ("IL3002", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithLocalFunctionWithRUC.LocalFunction--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--MethodWithLocalFunctionWithRUC.LocalFunction--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] public static void MethodWithLocalFunctionWithRUC () { [RequiresUnreferencedCode ("--MethodWithLocalFunctionWithRUC.LocalFunction--")] @@ -239,8 +235,8 @@ void LocalFunction () public static void MethodWithLocalFunctionCallsRUC () { [ExpectedWarning ("IL2026", "--MethodWithRUC--")] - [ExpectedWarning ("IL3002", "--MethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] + [ExpectedWarning ("IL3050", "--MethodWithRUC--", Tool.NativeAot | Tool.Analyzer, "NativeAOT Specific Warnings")] void LocalFunction () => MethodWithRUC (); LocalFunction (); } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAccessedThrough.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAccessedThrough.cs index 727463e80080..199b7e1d955d 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAccessedThrough.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAccessedThrough.cs @@ -40,11 +40,9 @@ static void RequiresOnlyThroughReflection () { } - // https://github.com/dotnet/linker/issues/2739 - the discussion there explains why (at least for now) we don't produce - // RAF and RDC warnings from the analyzer in these cases. [ExpectedWarning ("IL2026", "--RequiresOnlyThroughReflection--")] - [ExpectedWarning ("IL3002", "--RequiresOnlyThroughReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--RequiresOnlyThroughReflection--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--RequiresOnlyThroughReflection--", Tool.NativeAot, "https://github.com/dotnet/linker/issues/2739")] + [ExpectedWarning ("IL3050", "--RequiresOnlyThroughReflection--", Tool.NativeAot, "https://github.com/dotnet/linker/issues/2739")] static void TestRequiresOnlyThroughReflection () { typeof (RequiresAccessedThrough) @@ -62,8 +60,8 @@ public static void RequiresOnlyThroughReflection () } [ExpectedWarning ("IL2026", "--GenericType.RequiresOnlyThroughReflection--")] - [ExpectedWarning ("IL3002", "--GenericType.RequiresOnlyThroughReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--GenericType.RequiresOnlyThroughReflection--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--GenericType.RequiresOnlyThroughReflection--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--GenericType.RequiresOnlyThroughReflection--", Tool.NativeAot, "")] public static void Test () { typeof (AccessedThroughReflectionOnGenericType) @@ -74,8 +72,7 @@ public static void Test () class AccessThroughSpecialAttribute { - // https://github.com/dotnet/linker/issues/1873 - // [ExpectedWarning ("IL2026", "--DebuggerProxyType.Method--")] + [ExpectedWarning ("IL2026", "--DebuggerProxyType.Method--", Tool.None, "https://github.com/dotnet/linker/issues/1873")] [DebuggerDisplay ("Some{*}value")] class TypeWithDebuggerDisplay { @@ -103,13 +100,12 @@ class PInvokeReturnType public PInvokeReturnType () { } } - // https://github.com/mono/linker/issues/2116 - [ExpectedWarning ("IL2026", "--PInvokeReturnType.ctor--", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", "--PInvokeReturnType.ctor--", Tool.Trimmer, "https://github.com/mono/linker/issues/2116")] [DllImport ("nonexistent")] static extern PInvokeReturnType PInvokeReturnsType (); // Analyzer doesn't support IL2050 yet - [ExpectedWarning ("IL2050", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2050", Tool.Trimmer | Tool.NativeAot, "")] public static void Test () { PInvokeReturnsType (); @@ -136,8 +132,8 @@ class NewConstraintTestAnnotatedType [ExpectedWarning ("IL2026", "--NewConstraintTestType.ctor--")] [ExpectedWarning ("IL2026", "--NewConstraintTestAnnotatedType--")] - [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () where T : new() { GenericMethod (); @@ -156,8 +152,8 @@ public static void DoNothing () { } [ExpectedWarning ("IL2026", "--NewConstraintTestType.ctor--")] [ExpectedWarning ("IL2026", "--NewConstraintTestAnnotatedType--")] - [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] public static void TestNewConstraintOnTypeParameter () where T : new() { _ = new NewConstraintOnTypeParameter (); @@ -166,8 +162,8 @@ public static void DoNothing () { } } [ExpectedWarning ("IL2026", "--AnnotatedMethod--")] - [ExpectedWarning ("IL3002", "--AnnotatedMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AnnotatedMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AnnotatedMethod--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AnnotatedMethod--", Tool.Analyzer | Tool.NativeAot, "")] public static void TestNewConstraintOnTypeParameterInAnnotatedMethod () { AnnotatedMethod (); @@ -191,8 +187,8 @@ public static void TestNewConstraintOnTypeParameterInAnnotatedType () [RequiresUnreferencedCode ("--AnnotatedType--")] class AnnotatedType { - [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] public static void Method () { _ = new NewConstraintOnTypeParameter (); @@ -202,8 +198,8 @@ public static void Method () [ExpectedWarning ("IL2026", "--NewConstraintTestType.ctor--")] [ExpectedWarning ("IL2026", "--NewConstraintTestAnnotatedType--")] - [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--NewConstraintTestType.ctor--", Tool.Analyzer | Tool.NativeAot, "")] public static void TestNewConstraintOnTypeParameterOfStaticType () where T : new() { NewConstraintOnTypeParameterOfStaticType.DoNothing (); @@ -224,11 +220,11 @@ static bool PropertyWithLdToken { } [ExpectedWarning ("IL2026", "--PropertyWithLdToken.get--")] - [ExpectedWarning ("IL2026", "--PropertyWithLdToken.get--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--PropertyWithLdToken.get--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--PropertyWithLdToken.get--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--PropertyWithLdToken.get--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--PropertyWithLdToken.get--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--PropertyWithLdToken.get--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--PropertyWithLdToken.get--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--PropertyWithLdToken.get--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--PropertyWithLdToken.get--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--PropertyWithLdToken.get--", Tool.NativeAot, "")] static void TestPropertyLdToken () { Expression> getter = () => PropertyWithLdToken; @@ -242,8 +238,8 @@ static void MethodWithLdToken () } [ExpectedWarning ("IL2026", "--MethodWithLdToken--")] - [ExpectedWarning ("IL3002", "--MethodWithLdToken--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithLdToken--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithLdToken--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithLdToken--", Tool.Analyzer | Tool.NativeAot, "")] static void TestMethodLdToken () { Expression e = () => MethodWithLdToken (); @@ -257,7 +253,7 @@ class FieldWithLdTokenType } [ExpectedWarning ("IL2026", "--FieldWithLdToken--")] - [ExpectedWarning ("IL3050", "--FieldWithLdToken--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--FieldWithLdToken--", Tool.Analyzer | Tool.NativeAot, "")] static void TestFieldLdToken () { Expression> f = () => FieldWithLdTokenType.Field; @@ -281,16 +277,16 @@ static void MethodWithDelegate () } [ExpectedWarning ("IL2026", "--MethodWithDelegate--")] - [ExpectedWarning ("IL3002", "--MethodWithDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithDelegate--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithDelegate--", Tool.Analyzer | Tool.NativeAot, "")] static void TestMethodWithDelegate () { Action a = MethodWithDelegate; } [ExpectedWarning ("IL2026", "--LambdaThroughDelegate--")] - [ExpectedWarning ("IL3002", "--LambdaThroughDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--LambdaThroughDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--LambdaThroughDelegate--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--LambdaThroughDelegate--", Tool.Analyzer | Tool.NativeAot, "")] static void LambdaThroughDelegate () { Action a = @@ -303,8 +299,8 @@ static void LambdaThroughDelegate () } [ExpectedWarning ("IL2026", "--LocalFunctionThroughDelegate--")] - [ExpectedWarning ("IL3002", "--LocalFunctionThroughDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--LocalFunctionThroughDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--LocalFunctionThroughDelegate--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--LocalFunctionThroughDelegate--", Tool.Analyzer | Tool.NativeAot, "")] static void LocalFunctionThroughDelegate () { Action a = Local; @@ -341,15 +337,15 @@ private Target (int i) { } private static void MethodRequires () { } } - [ExpectedWarning ("IL2026", "--Target.MethodRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--Target.MethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--Target.MethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--Target.MethodRequires--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--Target.MethodRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--Target.MethodRequires--", Tool.NativeAot, "")] [UnsafeAccessor (UnsafeAccessorKind.StaticMethod)] extern static void MethodRequires (Target target); - [ExpectedWarning ("IL2026", "--Target..ctor--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--Target..ctor--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--Target..ctor--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--Target..ctor--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--Target..ctor--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--Target..ctor--", Tool.NativeAot, "")] [UnsafeAccessor (UnsafeAccessorKind.Constructor)] extern static Target Constructor (int i); @@ -367,22 +363,22 @@ private void InstanceMethod () { } private int InstanceField; } - [ExpectedWarning ("IL2026", "--TargetWitRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--TargetWitRequires--", Tool.Trimmer | Tool.NativeAot, "")] [UnsafeAccessor (UnsafeAccessorKind.Constructor)] extern static TargetWithRequires TargetRequiresConstructor (); - [ExpectedWarning ("IL2026", "--TargetWitRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--TargetWitRequires--", Tool.Trimmer | Tool.NativeAot, "")] [UnsafeAccessor (UnsafeAccessorKind.StaticMethod, Name = "StaticMethod")] extern static void TargetRequiresStaticMethod (TargetWithRequires target); // For trimmer this is a reflection access to an instance method - and as such it must warn (since it's in theory possible // to invoke the method via reflection on a null instance) // For NativeAOT this is a direct call to an instance method (there's no reflection involved) and as such it doesn't need to warn - [ExpectedWarning ("IL2026", "--TargetWitRequires--", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", "--TargetWitRequires--", Tool.Trimmer, "")] [UnsafeAccessor (UnsafeAccessorKind.Method, Name = "InstanceMethod")] extern static void TargetRequiresInstanceMethod (TargetWithRequires target); - [ExpectedWarning ("IL2026", "--TargetWitRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--TargetWitRequires--", Tool.Trimmer | Tool.NativeAot, "")] [UnsafeAccessor (UnsafeAccessorKind.StaticField, Name = "StaticField")] extern static ref int TargetRequiresStaticField (TargetWithRequires target); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs index 4653f445cabb..94249d6af5b6 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs @@ -26,87 +26,87 @@ class RequiresAttributeMismatch // The analyzer matches this behavior, treating the get/set methods as annotated if the property is annotated, // and warning only on the get/set methods. [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set")] - [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.get")] - [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.set")] - [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.set")] - [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualMethod()")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualMethod()")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualMethod()")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedClassWithRequires.VirtualMethod()")] - [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "DerivedClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "DerivedClassWithRequires.VirtualMethod()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "IBaseWithRequires.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "IBaseWithRequires.PropertyAnnotationInAccesor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set")] - [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "IBaseWithRequires.Method()")] - [ExpectedWarning ("IL3002", "IBaseWithRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "IBaseWithRequires.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "IBaseWithRequires.Method()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "IBaseWithRequires.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.Method()")] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "ImplementationClassWithRequires.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.Method()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "ImplementationClassWithRequires.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3002", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationClassWithRequiresInSource.Method()")] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "ImplementationClassWithRequiresInSource.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.Method()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "ImplementationClassWithRequiresInSource.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty.set", Tool.NativeAot, "")] public static void Main () { @@ -174,8 +174,8 @@ class DerivedClassWithRequires : BaseClassWithoutRequires [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] [ExpectedWarning ("IL2046", "DerivedClassWithRequires.VirtualMethod()", "BaseClassWithoutRequires.VirtualMethod()")] - [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualMethod()", "BaseClassWithoutRequires.VirtualMethod()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "DerivedClassWithRequires.VirtualMethod()", "BaseClassWithoutRequires.VirtualMethod()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualMethod()", "BaseClassWithoutRequires.VirtualMethod()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "DerivedClassWithRequires.VirtualMethod()", "BaseClassWithoutRequires.VirtualMethod()", Tool.Analyzer | Tool.NativeAot, "")] public override void VirtualMethod () { } @@ -183,8 +183,8 @@ public override void VirtualMethod () private string name; public override string VirtualPropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message")] [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] @@ -194,9 +194,9 @@ public override string VirtualPropertyAnnotationInAccesor { [RequiresAssemblyFiles ("Message")] public override string VirtualPropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithoutRequires.VirtualPropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithoutRequires.VirtualPropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithoutRequires.VirtualPropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithoutRequires.VirtualPropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -237,8 +237,8 @@ public static void Test() class DerivedClassWithoutRequires : BaseClassWithRequires { [ExpectedWarning ("IL2046", "DerivedClassWithoutRequires.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()")] - [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "DerivedClassWithoutRequires.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "DerivedClassWithoutRequires.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", Tool.Analyzer | Tool.NativeAot, "")] public override void VirtualMethod () { } @@ -246,24 +246,24 @@ public override void VirtualMethod () private string name; public override string VirtualPropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] get { return name; } set { name = value; } } public override string VirtualPropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInProperty", "BaseClassWithRequires.VirtualPropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] set; } public override string VirtualPropertyAnnotationInPropertyAndAccessor { [ExpectedWarning ("IL2046", "VirtualPropertyAnnotationInPropertyAndAccessor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInPropertyAndAccessor", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithoutRequires.VirtualPropertyAnnotationInPropertyAndAccessor", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -271,8 +271,8 @@ public override string VirtualPropertyAnnotationInPropertyAndAccessor { class DerivedClassWithAllWarnings : BaseClassWithRequires { [ExpectedWarning ("IL2046", "DerivedClassWithAllWarnings.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()")] - [ExpectedWarning ("IL3003", "DerivedClassWithAllWarnings.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "DerivedClassWithAllWarnings.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithAllWarnings.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "DerivedClassWithAllWarnings.VirtualMethod()", "BaseClassWithRequires.VirtualMethod()", Tool.Analyzer | Tool.NativeAot, "")] public override void VirtualMethod () { } @@ -282,12 +282,12 @@ public override void VirtualMethod () [RequiresAssemblyFiles ("Message")] public override string VirtualPropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3051", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3051", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] get { return name; } [RequiresAssemblyFiles ("Message")] [RequiresUnreferencedCode ("Message")] [ExpectedWarning ("IL2046", "VirtualPropertyAnnotationInAccesor.set", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.set")] - [ExpectedWarning ("IL3003", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.set", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.set", Tool.Analyzer | Tool.NativeAot, "")] set { name = value; } } @@ -304,7 +304,7 @@ public override string VirtualPropertyAnnotationInProperty { public override string VirtualPropertyAnnotationInPropertyAndAccessor { [ExpectedWarning ("IL2046", "VirtualPropertyAnnotationInPropertyAndAccessor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3003", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.get", "BaseClassWithRequires.VirtualPropertyAnnotationInPropertyAndAccessor.get", Tool.Analyzer | Tool.NativeAot, "")] get; [RequiresAssemblyFiles ("Message")] [RequiresUnreferencedCode ("Message")] @@ -357,8 +357,8 @@ class ImplementationClassWithRequires : IBaseWithoutRequires [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] [ExpectedWarning ("IL2046", "ImplementationClassWithRequires.Method()", "IBaseWithoutRequires.Method()")] - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.Method()", "IBaseWithoutRequires.Method()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithRequires.Method()", "IBaseWithoutRequires.Method()", Tool.Analyzer | Tool.NativeAot, "")] public void Method () { } @@ -366,8 +366,8 @@ public void Method () private string name; public string PropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message")] [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] @@ -376,23 +376,23 @@ public string PropertyAnnotationInAccesor { } [RequiresAssemblyFiles ("Message")] - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", Tool.Analyzer, "")] public string PropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", Tool.NativeAot | Tool.Analyzer, "")] get; - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", Tool.NativeAot | Tool.Analyzer, "")] set; } [RequiresAssemblyFiles ("Message")] - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", Tool.Analyzer, "")] public string PropertyAnnotationInPropertyAndAccessor { [RequiresAssemblyFiles ("Message")] [RequiresUnreferencedCode ("Message")] [ExpectedWarning ("IL2046", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -403,12 +403,12 @@ class ExplicitImplementationClassWithRequires : IBaseWithoutRequires [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] // ILLink member string format includes namespace of explicit interface method. - [ExpectedWarning ("IL2046", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2046", "ExplicitImplementationClassWithRequires.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithRequires.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3051", "IBaseWithoutRequires.Method()", "ExplicitImplementationClassWithRequires.IBaseWithoutRequires.Method()", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2046", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", Tool.NativeAot, "")] + [ExpectedWarning ("IL2046", "ExplicitImplementationClassWithRequires.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", Tool.Analyzer, "")] + [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithRequires.IBaseWithoutRequires.Method()", "IBaseWithoutRequires.Method()", Tool.Analyzer, "")] + [ExpectedWarning ("IL3051", "IBaseWithoutRequires.Method()", "ExplicitImplementationClassWithRequires.IBaseWithoutRequires.Method()", Tool.Analyzer, "")] void IBaseWithoutRequires.Method () { } @@ -416,8 +416,8 @@ void IBaseWithoutRequires.Method () private string name; string IBaseWithoutRequires.PropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "PropertyAnnotationInAccesor.get", "IBaseWithoutRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message")] [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] @@ -426,23 +426,23 @@ string IBaseWithoutRequires.PropertyAnnotationInAccesor { } [RequiresAssemblyFiles ("Message")] - [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", Tool.Analyzer, "")] string IBaseWithoutRequires.PropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithoutRequires.PropertyAnnotationInProperty", "IBaseWithoutRequires.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] set; } [RequiresAssemblyFiles ("Message")] - [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", Tool.Analyzer, "")] string IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor { [RequiresAssemblyFiles ("Message")] [RequiresUnreferencedCode ("Message")] [ExpectedWarning ("IL2046", "PropertyAnnotationInPropertyAndAccessor.get", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get")] - [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor.get", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor.get", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor", "IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -450,8 +450,8 @@ string IBaseWithoutRequires.PropertyAnnotationInPropertyAndAccessor { class ImplementationClassWithoutRequires : IBaseWithRequires { [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequires.Method()", "IBaseWithRequires.Method()")] - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.Method()", "IBaseWithRequires.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequires.Method()", "IBaseWithRequires.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.Method()", "IBaseWithRequires.Method()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequires.Method()", "IBaseWithRequires.Method()", Tool.Analyzer | Tool.NativeAot, "")] public void Method () { } @@ -459,28 +459,28 @@ public void Method () private string name; public string PropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequires.PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequires.PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequires.PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] get { return name; } set { name = value; } } - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", Tool.Analyzer, "")] public string PropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] set; } - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", Tool.Analyzer, "")] public string PropertyAnnotationInPropertyAndAccessor { [RequiresAssemblyFiles ("Message")] [RequiresUnreferencedCode ("Message")] [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.get")] get; [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.set", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set")] - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.set", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.set", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -488,12 +488,12 @@ public string PropertyAnnotationInPropertyAndAccessor { class ExplicitImplementationClassWithoutRequires : IBaseWithRequires { // ILLink member string format includes namespace of explicit interface method. - [ExpectedWarning ("IL2046", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.Method()", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3003", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3051", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2046", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.IBaseWithRequires.Method()", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3003", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.IBaseWithRequires.Method()", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3051", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.IBaseWithRequires.Method()", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2046", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.Method()", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3003", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.Method()", Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.Method()", Tool.NativeAot, "")] + [ExpectedWarning ("IL2046", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.IBaseWithRequires.Method()", Tool.Analyzer, "")] + [ExpectedWarning ("IL3003", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.IBaseWithRequires.Method()", Tool.Analyzer, "")] + [ExpectedWarning ("IL3051", "IBaseWithRequires.Method()", "ExplicitImplementationClassWithoutRequires.IBaseWithRequires.Method()", Tool.Analyzer, "")] void IBaseWithRequires.Method () { } @@ -501,26 +501,26 @@ void IBaseWithRequires.Method () private string name; string IBaseWithRequires.PropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "PropertyAnnotationInAccesor.get", "IBaseWithRequires.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] get { return name; } set { name = value; } } - [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", Tool.Analyzer, "")] string IBaseWithRequires.PropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInProperty", "IBaseWithRequires.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] set; } - [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ExplicitImplementationClassWithoutRequires.Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", Tool.Analyzer, "")] string IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor { - [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "Mono.Linker.Tests.Cases.RequiresCapability.RequiresAttributeMismatch.IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor", Tool.Analyzer | Tool.NativeAot, "")] get; [ExpectedWarning ("IL2046", "PropertyAnnotationInPropertyAndAccessor.set", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set")] - [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor.set", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "PropertyAnnotationInPropertyAndAccessor.set", "IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor.set", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -528,8 +528,8 @@ string IBaseWithRequires.PropertyAnnotationInPropertyAndAccessor { class ImplementationClassWithoutRequiresInSource : ReferenceInterfaces.IBaseWithRequiresInReference { [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequiresInSource.Method()", "IBaseWithRequiresInReference.Method()")] - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.Method()", "IBaseWithRequiresInReference.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequiresInSource.Method()", "IBaseWithRequiresInReference.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.Method()", "IBaseWithRequiresInReference.Method()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequiresInSource.Method()", "IBaseWithRequiresInReference.Method()", Tool.Analyzer | Tool.NativeAot, "")] public void Method () { } @@ -537,17 +537,17 @@ public void Method () private string name; public string PropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithRequiresInReference.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithRequiresInReference.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithRequiresInReference.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithRequiresInReference.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithRequiresInReference.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] get { return name; } set { name = value; } } - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInProperty", "IBaseWithRequiresInReference.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInProperty", "IBaseWithRequiresInReference.PropertyAnnotationInProperty", Tool.Analyzer, "")] public string PropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInProperty.get", "IBaseWithRequiresInReference.PropertyAnnotationInProperty.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInProperty.get", "IBaseWithRequiresInReference.PropertyAnnotationInProperty.get", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInProperty.set", "IBaseWithRequiresInReference.PropertyAnnotationInProperty.set", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithoutRequiresInSource.PropertyAnnotationInProperty.set", "IBaseWithRequiresInReference.PropertyAnnotationInProperty.set", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -555,8 +555,8 @@ public string PropertyAnnotationInProperty { class ImplementationClassWithRequiresInSource : ReferenceInterfaces.IBaseWithoutRequiresInReference { [ExpectedWarning ("IL2046", "ImplementationClassWithRequiresInSource.Method()", "IBaseWithoutRequiresInReference.Method()")] - [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.Method()", "IBaseWithoutRequiresInReference.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithRequiresInSource.Method()", "IBaseWithoutRequiresInReference.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.Method()", "IBaseWithoutRequiresInReference.Method()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithRequiresInSource.Method()", "IBaseWithoutRequiresInReference.Method()", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message")] [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] @@ -567,8 +567,8 @@ public void Method () private string name; public string PropertyAnnotationInAccesor { [ExpectedWarning ("IL2046", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithoutRequiresInReference.PropertyAnnotationInAccesor.get")] - [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithoutRequiresInReference.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithoutRequiresInReference.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithoutRequiresInReference.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", "IBaseWithoutRequiresInReference.PropertyAnnotationInAccesor.get", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message")] [RequiresAssemblyFiles ("Message")] [RequiresDynamicCode ("Message")] @@ -576,12 +576,12 @@ public string PropertyAnnotationInAccesor { set { name = value; } } - [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty", "IBaseWithoutRequiresInReference.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty", "IBaseWithoutRequiresInReference.PropertyAnnotationInProperty", Tool.Analyzer, "")] [RequiresAssemblyFiles ("Message")] public string PropertyAnnotationInProperty { - [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty", "IBaseWithoutRequiresInReference.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty", "IBaseWithoutRequiresInReference.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty", "IBaseWithoutRequiresInReference.PropertyAnnotationInProperty", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplementationClassWithRequiresInSource.PropertyAnnotationInProperty", "IBaseWithoutRequiresInReference.PropertyAnnotationInProperty", Tool.Analyzer | Tool.NativeAot, "")] set; } } @@ -589,23 +589,23 @@ public string PropertyAnnotationInProperty { class StaticInterfaceMethods { [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] public static void Test () { typeof (IRequires).RequiresPublicMethods (); @@ -650,13 +650,13 @@ public static void AbstractMethod () { } class ImplIRequiresMismatching : IRequires { [ExpectedWarning ("IL2046", "ImplIRequiresMismatching.VirtualMethod", "IRequires.VirtualMethod")] - [ExpectedWarning ("IL3003", "ImplIRequiresMismatching.VirtualMethod", "IRequires.VirtualMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplIRequiresMismatching.VirtualMethod", "IRequires.VirtualMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplIRequiresMismatching.VirtualMethod", "IRequires.VirtualMethod", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplIRequiresMismatching.VirtualMethod", "IRequires.VirtualMethod", Tool.Analyzer | Tool.NativeAot, "")] public static void VirtualMethod () { } [ExpectedWarning ("IL2046", "ImplIRequiresMismatching.AbstractMethod", "IRequires.AbstractMethod")] - [ExpectedWarning ("IL3003", "ImplIRequiresMismatching.AbstractMethod", "IRequires.AbstractMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplIRequiresMismatching.AbstractMethod", "IRequires.AbstractMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplIRequiresMismatching.AbstractMethod", "IRequires.AbstractMethod", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplIRequiresMismatching.AbstractMethod", "IRequires.AbstractMethod", Tool.Analyzer | Tool.NativeAot, "")] public static void AbstractMethod () { } } class ImplINoRequiresMatching : INoRequires @@ -669,16 +669,16 @@ public static void AbstractMethod () { } class ImplINoRequiresMismatching : INoRequires { [ExpectedWarning ("IL2046", "ImplINoRequiresMismatching.VirtualMethod", "INoRequires.VirtualMethod")] - [ExpectedWarning ("IL3003", "ImplINoRequiresMismatching.VirtualMethod", "INoRequires.VirtualMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplINoRequiresMismatching.VirtualMethod", "INoRequires.VirtualMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplINoRequiresMismatching.VirtualMethod", "INoRequires.VirtualMethod", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplINoRequiresMismatching.VirtualMethod", "INoRequires.VirtualMethod", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.VirtualMethod--")] [RequiresAssemblyFiles ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.VirtualMethod--")] [RequiresDynamicCode ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.VirtualMethod--")] public static void VirtualMethod () { } [ExpectedWarning ("IL2046", "ImplINoRequiresMismatching.AbstractMethod", "INoRequires.AbstractMethod")] - [ExpectedWarning ("IL3003", "ImplINoRequiresMismatching.AbstractMethod", "INoRequires.AbstractMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3051", "ImplINoRequiresMismatching.AbstractMethod", "INoRequires.AbstractMethod", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3003", "ImplINoRequiresMismatching.AbstractMethod", "INoRequires.AbstractMethod", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3051", "ImplINoRequiresMismatching.AbstractMethod", "INoRequires.AbstractMethod", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.AbstractMethod--")] [RequiresAssemblyFiles ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.AbstractMethod--")] [RequiresDynamicCode ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.AbstractMethod--")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs index 3def1ee762be..0c4d84e42602 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs @@ -50,8 +50,8 @@ public static void Main () class WarnInIteratorBody { [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static IEnumerable TestCallBeforeYieldReturn () { MethodWithRequires (); @@ -59,8 +59,8 @@ static IEnumerable TestCallBeforeYieldReturn () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static IEnumerable TestCallAfterYieldReturn () { yield return 0; @@ -68,8 +68,8 @@ static IEnumerable TestCallAfterYieldReturn () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] static IEnumerable TestReflectionAccess () { yield return 0; @@ -80,15 +80,15 @@ static IEnumerable TestReflectionAccess () } #if !RELEASE - [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] #else // In release mode, the compiler optimizes away the unused Action (and reference to MethodWithRequires) #endif - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer, "")] static IEnumerable TestLdftn () { yield return 0; @@ -98,8 +98,8 @@ static IEnumerable TestLdftn () // Cannot annotate fields either with RUC nor RAF therefore the warning persists [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static IEnumerable TestLazyDelegate () @@ -110,8 +110,8 @@ static IEnumerable TestLazyDelegate () } [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] static IEnumerable TestDynamicallyAccessedMethod () { typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); @@ -167,8 +167,8 @@ static IEnumerable TestLdftn () // Cannot annotate fields either with RUC nor RAF therefore the warning persists [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static IEnumerable TestLazyDelegate () @@ -234,8 +234,8 @@ public static void Test () class WarnInAsyncBody { [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async void TestCallBeforeYieldReturn () { MethodWithRequires (); @@ -243,8 +243,8 @@ static async void TestCallBeforeYieldReturn () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async void TestCallAfterYieldReturn () { await MethodAsync (); @@ -252,8 +252,8 @@ static async void TestCallAfterYieldReturn () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] static async void TestReflectionAccess () { await MethodAsync (); @@ -264,13 +264,13 @@ static async void TestReflectionAccess () } #if !RELEASE - [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] #endif - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer, "")] static async void TestLdftn () { await MethodAsync (); @@ -278,8 +278,8 @@ static async void TestLdftn () } [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static async void TestLazyDelegate () @@ -289,8 +289,8 @@ static async void TestLazyDelegate () } [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] static async void TestDynamicallyAccessedMethod () { typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); @@ -344,8 +344,8 @@ static async void TestLdftn () // Cannot annotate fields either with RUC nor RAF therefore the warning persists [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static async void TestLazyDelegate () @@ -409,8 +409,8 @@ public static void Test () class WarnInAsyncIteratorBody { [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async IAsyncEnumerable TestCallBeforeYieldReturn () { await MethodAsync (); @@ -419,8 +419,8 @@ static async IAsyncEnumerable TestCallBeforeYieldReturn () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async IAsyncEnumerable TestCallAfterYieldReturn () { yield return 0; @@ -429,8 +429,8 @@ static async IAsyncEnumerable TestCallAfterYieldReturn () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] static async IAsyncEnumerable TestReflectionAccess () { yield return 0; @@ -443,13 +443,13 @@ static async IAsyncEnumerable TestReflectionAccess () } #if !RELEASE - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] #endif - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer, "")] static async IAsyncEnumerable TestLdftn () { await MethodAsync (); @@ -458,8 +458,8 @@ static async IAsyncEnumerable TestLdftn () } [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static async IAsyncEnumerable TestLazyDelegate () @@ -470,8 +470,8 @@ static async IAsyncEnumerable TestLazyDelegate () } [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "", CompilerGeneratedCode = true)] static async IAsyncEnumerable TestDynamicallyAccessedMethod () { typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); @@ -530,8 +530,8 @@ static async IAsyncEnumerable TestLdftn () // Cannot annotate fields either with RUC nor RAF therefore the warning persists [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static async IAsyncEnumerable TestLazyDelegate () @@ -604,14 +604,14 @@ static void TestCall () LocalFunction (); [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] void LocalFunction () => MethodWithRequires (); } [ExpectedWarning ("IL2026", "--LocalFunctionWithRequires--")] - [ExpectedWarning ("IL3002", "--LocalFunctionWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--LocalFunctionWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--LocalFunctionWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--LocalFunctionWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestLocalFunctionWithRequires () { LocalFunction (); @@ -633,8 +633,8 @@ static void TestCallWithClosure (int p = 0) LocalFunction (); [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] void LocalFunction () { p++; @@ -657,8 +657,8 @@ static void TestReflectionAccess () LocalFunction (); [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "")] void LocalFunction () => typeof (RequiresInCompilerGeneratedCode) .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) .Invoke (null, new object[] { }); @@ -669,13 +669,13 @@ static void TestLdftn () LocalFunction (); #if !RELEASE - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "")] #endif - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer, "")] void LocalFunction () { var action = new Action (MethodWithRequires); @@ -683,8 +683,8 @@ void LocalFunction () } [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static void TestLazyDelegate () @@ -702,8 +702,8 @@ static void TestDynamicallyAccessedMethod () LocalFunction (); [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "")] void LocalFunction () => typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); } @@ -788,8 +788,8 @@ void LocalFunction () } [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static void TestLazyDelegate () @@ -919,7 +919,7 @@ public static void TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction class DynamicallyAccessedLocalFunctionUnusedShouldWarn { - [ExpectedWarning ("IL2118", nameof (TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction), "LocalFunction", ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2118", [nameof (TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction), "LocalFunction"], Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] public static void TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction () { typeof (DynamicallyAccessedLocalFunctionUnusedShouldWarn).RequiresNonPublicMethods (); @@ -949,8 +949,8 @@ public static void TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction } [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] static void TestSuppressionOnLocalFunction () { LocalFunction (); // This will produce a warning since the local function has Requires on it @@ -966,8 +966,8 @@ void LocalFunction (Type unknownType = null) } [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] static void TestSuppressionOnLocalFunctionWithAssignment () { LocalFunction (); // This will produce a warning since the local function has Requires on it @@ -986,8 +986,8 @@ void LocalFunction (Type unknownType = null) static Type typeWithNonPublicMethods; [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] static void TestSuppressionOnLocalFunctionWithNestedLocalFunction () { LocalFunction (); // This will produce a warning since the local function has Requires on it @@ -1001,9 +1001,9 @@ void LocalFunction () // ILLink doesn't have enough information to associate the Requires on LocalFunction // with this nested local function. - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot, "")] void NestedLocalFunction () => MethodWithRequires (); } } @@ -1028,8 +1028,8 @@ void LocalFunction (Type unknownType = null) class TestSuppressionOnOuterWithSameName { [ExpectedWarning ("IL2026", nameof (Outer) + "()")] - [ExpectedWarning ("IL3002", nameof (Outer) + "()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", nameof (Outer) + "()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", nameof (Outer) + "()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", nameof (Outer) + "()", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { Outer (); @@ -1051,8 +1051,8 @@ static void Outer (int i) LocalFunction (); [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] void LocalFunction () => MethodWithRequires (); } } @@ -1093,14 +1093,14 @@ static void WarnInNonNestedLocalFunctionTest () LocalFunction (); [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void LocalFunction () => MethodWithRequires (); } [ExpectedWarning ("IL2026", "--MethodWithNonNestedLocalFunction--")] - [ExpectedWarning ("IL3002", "--MethodWithNonNestedLocalFunction--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithNonNestedLocalFunction--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithNonNestedLocalFunction--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithNonNestedLocalFunction--", Tool.Analyzer | Tool.NativeAot, "")] static void SuppressInNonNestedLocalFunctionTest () { MethodWithNonNestedLocalFunction (); @@ -1122,16 +1122,16 @@ static void TestCall () { Action lambda = [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] () => MethodWithRequires (); lambda (); } [ExpectedWarning ("IL2026", "--LambdaWithRequires--")] - [ExpectedWarning ("IL3002", "--LambdaWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--LambdaWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--LambdaWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--LambdaWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestLambdaWithRequires () { Action lambda = @@ -1147,14 +1147,14 @@ static void TestCallUnused () { Action _ = [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] () => MethodWithRequires (); } [ExpectedWarning ("IL2026", "--LambdaWithRequires--")] - [ExpectedWarning ("IL3002", "--LambdaWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--LambdaWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--LambdaWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--LambdaWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestLambdaWithRequiresUnused () { Action _ = @@ -1168,8 +1168,8 @@ static void TestCallWithClosure (int p = 0) { Action lambda = [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] () => { p++; MethodWithRequires (); @@ -1182,13 +1182,13 @@ static void TestCallWithClosureUnused (int p = 0) { Action _ = #if !RELEASE - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "")] #endif - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer, "")] () => { p++; MethodWithRequires (); @@ -1199,8 +1199,8 @@ static void TestReflectionAccess () { Action _ = [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "")] () => { typeof (RequiresInCompilerGeneratedCode) .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) @@ -1212,21 +1212,21 @@ static void TestLdftn () { Action _ = #if !RELEASE - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "")] #endif - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer, "")] () => { var action = new Action (MethodWithRequires); }; } [ExpectedWarning ("IL2026", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static void TestLazyDelegate () @@ -1240,8 +1240,8 @@ static void TestDynamicallyAccessedMethod () { Action _ = [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", Tool.NativeAot, "")] () => { typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); }; @@ -1330,8 +1330,8 @@ static void TestLdftn () } [ExpectedWarning ("IL2026", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequiresAndReturns--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); static void TestLazyDelegate () @@ -1383,8 +1383,8 @@ static void TestGenericTypeParameterRequirement () } [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] static void TestSuppressionOnLambda () { var lambda = @@ -1397,8 +1397,8 @@ static void TestSuppressionOnLambda () } [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] static void TestSuppressionOnLambdaWithNestedLambda () { var lambda = @@ -1411,9 +1411,9 @@ static void TestSuppressionOnLambdaWithNestedLambda () // an IL reference to the generated lambda method, unlike local functions. // However, we don't make this association, for consistency with local functions. var nestedLambda = - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", ProducedBy = Tool.NativeAot | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.NativeAot | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", Tool.NativeAot | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.NativeAot | Tool.NativeAot, "")] () => MethodWithRequires (); }; @@ -1440,8 +1440,8 @@ static void TestSuppressionOnOuterAndLambda () class TestSuppressionOnOuterWithSameName { [ExpectedWarning ("IL2026", nameof (Outer) + "()")] - [ExpectedWarning ("IL3002", nameof (Outer) + "()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", nameof (Outer) + "()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", nameof (Outer) + "()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", nameof (Outer) + "()", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { Outer (); @@ -1462,8 +1462,8 @@ static void Outer (int i) { var lambda = [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] () => MethodWithRequires (); lambda (); @@ -1503,8 +1503,8 @@ static async void TestIteratorLocalFunctionInAsync () await MethodAsync (); [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] IEnumerable LocalFunction () { yield return 0; @@ -1543,8 +1543,8 @@ IEnumerable IteratorLocalFunction () yield return 1; [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] void LocalFunction () => MethodWithRequires (); } } @@ -1561,8 +1561,8 @@ IEnumerable IteratorLocalFunction () } [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] void LocalFunction () => MethodWithRequires (); } @@ -1754,8 +1754,8 @@ static IEnumerable TestDynamicallyAccessedMethodViaGenericMethodParameterIn #endif [ExpectedWarning ("IL2026", "--IteratorLocalFunction--")] - [ExpectedWarning ("IL3002", "--IteratorLocalFunction--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--IteratorLocalFunction--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--IteratorLocalFunction--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--IteratorLocalFunction--", Tool.Analyzer | Tool.NativeAot, "")] static void TestLocalFunctionInIteratorLocalFunction () { IteratorLocalFunction (); @@ -1771,16 +1771,16 @@ IEnumerable IteratorLocalFunction () yield return 1; // Trimmer doesn't try to associate LocalFunction with IteratorLocalFunction - [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--MethodWithRequires--", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.NativeAot, "")] void LocalFunction () => MethodWithRequires (); } } [ExpectedWarning ("IL2026", "--IteratorLocalFunction--")] - [ExpectedWarning ("IL3002", "--IteratorLocalFunction--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--IteratorLocalFunction--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--IteratorLocalFunction--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--IteratorLocalFunction--", Tool.Analyzer | Tool.NativeAot, "")] static void TestLocalFunctionCalledFromIteratorLocalFunctionAndMethod () { IteratorLocalFunction (); @@ -1798,8 +1798,8 @@ IEnumerable IteratorLocalFunction () } [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] void LocalFunction () => MethodWithRequires (); } @@ -1847,8 +1847,8 @@ static async void TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress () } [ExpectedWarning ("IL2026", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static IEnumerable TestIteratorOnlyReferencedViaReflectionWhichShouldWarn () { yield return 0; @@ -1856,8 +1856,8 @@ static IEnumerable TestIteratorOnlyReferencedViaReflectionWhichShouldWarn ( } [ExpectedWarning ("IL2026", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "", CompilerGeneratedCode = true)] static async void TestAsyncOnlyReferencedViaReflectionWhichShouldWarn () { await MethodAsync (); @@ -1865,26 +1865,24 @@ static async void TestAsyncOnlyReferencedViaReflectionWhichShouldWarn () } [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--")] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--")] - [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (StateMachinesOnlyReferencedViaReflection), "<" + nameof (TestAsyncOnlyReferencedViaReflectionWhichShouldWarn) + ">", "MoveNext()", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2118", nameof (StateMachinesOnlyReferencedViaReflection), "<" + nameof (TestIteratorOnlyReferencedViaReflectionWhichShouldWarn) + ">", "MoveNext()", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] + [UnexpectedWarning ("IL2118", [nameof (StateMachinesOnlyReferencedViaReflection), "<" + nameof (TestAsyncOnlyReferencedViaReflectionWhichShouldWarn) + ">", "MoveNext()"], Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] + [UnexpectedWarning ("IL2118", [nameof (StateMachinesOnlyReferencedViaReflection), "<" + nameof (TestIteratorOnlyReferencedViaReflectionWhichShouldWarn) + ">", "MoveNext()"], Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] static void TestAll () { typeof (StateMachinesOnlyReferencedViaReflection).RequiresAll (); } [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--")] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--")] - [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", Tool.NativeAot, "")] // NonPublicMethods doesn't warn for members emitted into compiler-generated state machine types. static void TestNonPublicMethods () { @@ -1901,8 +1899,8 @@ public static void Test () class LocalFunctionsReferencedViaReflection { [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestLocalFunctionWithRequires () { LocalFunction (); @@ -1922,8 +1920,8 @@ static void TestLocalFunctionWithRequiresOnlyAccessedViaReflection () } [ExpectedWarning ("IL2026", "LocalFunction")] - [ExpectedWarning ("IL3002", "LocalFunction", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "LocalFunction", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "LocalFunction", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "LocalFunction", Tool.Analyzer | Tool.NativeAot, "")] static void TestLocalFunctionWithClosureWithRequires (int p = 0) { LocalFunction (); @@ -1974,16 +1972,15 @@ void LocalFunction () // Warnings for Reflection access to methods with Requires [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureInMethodWithRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection), - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", Tool.NativeAot, "")] + [UnexpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] static void TestAll () { typeof (LocalFunctionsReferencedViaReflection).RequiresAll (); @@ -1991,16 +1988,15 @@ static void TestAll () // Warnings for Reflection access to methods with Requires [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureInMethodWithRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--")] - [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), "<" + nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection) + ">", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", Tool.NativeAot, "")] + [UnexpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), "<" + nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection) + ">", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] static void TestNonPublicMethods () { typeof (LocalFunctionsReferencedViaReflection).RequiresNonPublicMethods (); @@ -2016,8 +2012,8 @@ public static void Test () class LambdasReferencedViaReflection { [ExpectedWarning ("IL2026", "--TestLambdaWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLambdaWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLambdaWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLambdaWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestLambdaWithRequires () { var lambda = @@ -2030,8 +2026,8 @@ static void TestLambdaWithRequires () } [ExpectedWarning ("IL2026", "Lambda")] - [ExpectedWarning ("IL3002", "Lambda", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Lambda", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Lambda", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Lambda", Tool.Analyzer | Tool.NativeAot, "")] static void TestLambdaWithClosureWithRequires (int p = 0) { var lambda = @@ -2071,11 +2067,11 @@ static void TestLambdaWithClosureInMethodWithRequires (int p = 0) // Warnings for Reflection access to methods with Requires [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestLambdaWithClosureInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLambdaWithClosureInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLambdaWithClosureInMethodWithRequires--", Tool.NativeAot, "")] static void TestAll () { typeof (LambdasReferencedViaReflection).RequiresAll (); @@ -2083,11 +2079,11 @@ static void TestAll () // Warnings for Reflection access to methods with Requires [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TestLambdaWithClosureInMethodWithRequires--")] - [ExpectedWarning ("IL3002", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TestLambdaWithClosureInMethodWithRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TestLambdaWithClosureInMethodWithRequires--", Tool.NativeAot, "")] static void TestNonPublicMethods () { typeof (LambdasReferencedViaReflection).RequiresNonPublicMethods (); @@ -2123,8 +2119,8 @@ static async Task AsyncMethodCallingRequires (Type type) } [ExpectedWarning ("IL2026", "ParentSuppression")] - [ExpectedWarning ("IL3002", "ParentSuppression", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "ParentSuppression", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ParentSuppression", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "ParentSuppression", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { AsyncMethodCallingRequires (typeof (object)); @@ -2152,8 +2148,8 @@ static async Task AsyncMethodCallingRequires () } [ExpectedWarning ("IL2026", "ParentSuppression")] - [ExpectedWarning ("IL3002", "ParentSuppression", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "ParentSuppression", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ParentSuppression", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "ParentSuppression", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { AsyncMethodCallingRequires (); @@ -2192,8 +2188,8 @@ static async IAsyncEnumerable CreateAsync () } [ExpectedWarning ("IL2026", "ParentSuppression")] - [ExpectedWarning ("IL3002", "ParentSuppression", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "ParentSuppression", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "ParentSuppression", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "ParentSuppression", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { AsyncEnumMethodCallingRequires (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnAttribute.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnAttribute.cs index 8710ed0e45cf..a8f5ab60dd05 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnAttribute.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnAttribute.cs @@ -61,16 +61,16 @@ public bool PropertyWhichRequires { } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] class GenericTypeWithAttributedParameter<[AttributeWhichRequires] T> { public static void TestMethod () { } } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] static void GenericMethodWithAttributedParameter<[AttributeWhichRequires] T> () { } static void TestRequiresOnAttributeOnGenericParameter () @@ -80,11 +80,11 @@ static void TestRequiresOnAttributeOnGenericParameter () } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] [AttributeWhichRequires] [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)] class TypeWithAttributeWhichRequires @@ -92,31 +92,31 @@ class TypeWithAttributeWhichRequires } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] [AttributeWhichRequires] [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)] static void MethodWithAttributeWhichRequires () { } [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] [AttributeWhichRequires] [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)] static int _fieldWithAttributeWhichRequires; [ExpectedWarning ("IL2026", "--AttributeWhichRequiresAttribute.ctor--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresAttribute.ctor--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--")] - [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AttributeWhichRequiresOnPropertyAttribute.PropertyWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] [AttributeWhichRequires] [AttributeWhichRequiresOnProperty (PropertyWhichRequires = true)] static bool PropertyWithAttributeWhichRequires { get; set; } @@ -129,8 +129,8 @@ static void MethodWithAttributeWhichRequires () { } static void MethodWhichRequiresWithAttributeWhichRequires () { } [ExpectedWarning ("IL2026", "--MethodWhichRequiresWithAttributeWhichRequires--")] - [ExpectedWarning ("IL3002", "--MethodWhichRequiresWithAttributeWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWhichRequiresWithAttributeWhichRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWhichRequiresWithAttributeWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWhichRequiresWithAttributeWhichRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestMethodWhichRequiresWithAttributeWhichRequires () { MethodWhichRequiresWithAttributeWhichRequires (); @@ -152,8 +152,8 @@ public void MethodWhichRequires () { } } [ExpectedWarning ("IL2026", "--TypeWithMethodWhichRequires--")] - [ExpectedWarning ("IL3002", "--TypeWithMethodWhichRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWithMethodWhichRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWithMethodWhichRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TypeWithMethodWhichRequires--", Tool.NativeAot, "")] [AttributeWhichMarksPublicMethods (typeof(TypeWithMethodWhichRequires))] static void ShouldWarn() { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs index f1faf7684750..125dd610d68a 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs @@ -59,7 +59,7 @@ public static void NestedStaticMethod () { } // This warning doesn't get suppressed since the declaring type NestedClass is not annotated with Requires [ExpectedWarning ("IL2026", "RequiresOnClass.RequiresOnMethod.MethodWithRequires()", "MethodWithRequires")] - [ExpectedWarning ("IL3050", "RequiresOnClass.RequiresOnMethod.MethodWithRequires()", "MethodWithRequires", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.RequiresOnMethod.MethodWithRequires()", "MethodWithRequires", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] public static void CallMethodWithRequires () => RequiresOnMethod.MethodWithRequires (); } @@ -101,7 +101,7 @@ private class DerivedWithoutRequires : ClassWithRequires { // This method contains implicit call to ClassWithRequires.ctor() [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] public DerivedWithoutRequires () { } public static void StaticMethodInInheritedClass () { } @@ -155,7 +155,7 @@ static StaticCtor () } [ExpectedWarning ("IL2026", "RequiresOnClass.StaticCtor.StaticCtor()", "Message for --StaticCtor--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.StaticCtor.StaticCtor()", "Message for --StaticCtor--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.StaticCtor.StaticCtor()", "Message for --StaticCtor--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void TestStaticCctorRequires () { _ = new StaticCtor (); @@ -174,14 +174,14 @@ static StaticCtorTriggeredByFieldAccess () } [ExpectedWarning ("IL2026", "StaticCtorTriggeredByFieldAccess.field", "Message for --StaticCtorTriggeredByFieldAccess--")] - [ExpectedWarning ("IL3050", "StaticCtorTriggeredByFieldAccess.field", "Message for --StaticCtorTriggeredByFieldAccess--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "StaticCtorTriggeredByFieldAccess.field", "Message for --StaticCtorTriggeredByFieldAccess--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void TestStaticCtorMarkingIsTriggeredByFieldAccessWrite () { StaticCtorTriggeredByFieldAccess.field = 1; } [ExpectedWarning ("IL2026", "StaticCtorTriggeredByFieldAccess.field", "Message for --StaticCtorTriggeredByFieldAccess--")] - [ExpectedWarning ("IL3050", "StaticCtorTriggeredByFieldAccess.field", "Message for --StaticCtorTriggeredByFieldAccess--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "StaticCtorTriggeredByFieldAccess.field", "Message for --StaticCtorTriggeredByFieldAccess--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void TestStaticCtorMarkingTriggeredOnSecondAccessWrite () { StaticCtorTriggeredByFieldAccess.field = 2; @@ -209,7 +209,7 @@ class StaticCCtorTriggeredByFieldAccessRead } [ExpectedWarning ("IL2026", "StaticCCtorTriggeredByFieldAccessRead.field", "Message for --StaticCCtorTriggeredByFieldAccessRead--")] - [ExpectedWarning ("IL3050", "StaticCCtorTriggeredByFieldAccessRead.field", "Message for --StaticCCtorTriggeredByFieldAccessRead--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "StaticCCtorTriggeredByFieldAccessRead.field", "Message for --StaticCCtorTriggeredByFieldAccessRead--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void TestStaticCtorMarkingIsTriggeredByFieldAccessRead () { var _ = StaticCCtorTriggeredByFieldAccessRead.field; @@ -229,7 +229,7 @@ public void TriggerStaticCtorMarking () } [ExpectedWarning ("IL2026", "StaticCtorTriggeredByCtorCalls.StaticCtorTriggeredByCtorCalls()")] - [ExpectedWarning ("IL3050", "StaticCtorTriggeredByCtorCalls.StaticCtorTriggeredByCtorCalls()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "StaticCtorTriggeredByCtorCalls.StaticCtorTriggeredByCtorCalls()", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void TestStaticCtorTriggeredByCtorCall () { new StaticCtorTriggeredByCtorCalls (); @@ -243,7 +243,7 @@ class ClassWithInstanceField } [ExpectedWarning ("IL2026", "ClassWithInstanceField.ClassWithInstanceField()")] - [ExpectedWarning ("IL3050", "ClassWithInstanceField.ClassWithInstanceField()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "ClassWithInstanceField.ClassWithInstanceField()", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void TestInstanceFieldCallDontWarn () { ClassWithInstanceField instance = new ClassWithInstanceField (); @@ -260,7 +260,7 @@ public ClassWithInstanceFieldWhichInitsDangerousClass () { } } [ExpectedWarning ("IL2026", "Calling the constructor is dangerous")] - [ExpectedWarning ("IL3050", "Calling the constructor is dangerous", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "Calling the constructor is dangerous", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void TestInstanceFieldSuppression () { _ = new ClassWithInstanceFieldWhichInitsDangerousClass (); @@ -310,7 +310,7 @@ public class DerivedNestedClass : ClassWithRequires { // This method contains implicit call to ClassWithRequires.ctor() [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] public DerivedNestedClass () { } public static void NestedStaticMethod () { } @@ -389,14 +389,14 @@ public int Method (int a) } [ExpectedWarning ("IL2026", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void TestRequiresInClassAccessedByStaticMethod () { ClassWithRequires.StaticMethod (); } [ExpectedWarning ("IL2026", "RequiresOnClass.ClassWithRequires", "--ClassWithRequires--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires", "--ClassWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires", "--ClassWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void TestRequiresInClassAccessedByCctor () { var classObject = new ClassWithRequires (); @@ -408,12 +408,12 @@ static void TestRequiresInParentClassAccesedByStaticMethod () } [ExpectedWarning ("IL2026", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] // Although we suppress the warning from RequiresOnMethod.MethodWithRequires () we still get a warning because we call CallRequiresMethod() which is an static method on a type with RUC [ExpectedWarning ("IL2026", "RequiresOnClass.ClassWithRequires.CallMethodWithRequires()", "--ClassWithRequires--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.CallMethodWithRequires()", "--ClassWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.CallMethodWithRequires()", "--ClassWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] [ExpectedWarning ("IL2026", "ClassWithRequires.Instance", "--ClassWithRequires--")] - [ExpectedWarning ("IL3050", "ClassWithRequires.Instance", "--ClassWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "ClassWithRequires.Instance", "--ClassWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void TestRequiresOnBaseButNotOnDerived () { var a = new DerivedWithoutRequires (); // Must instantiate to force checks on the base type (otherwise base type is non-interesting) @@ -429,7 +429,7 @@ static void TestRequiresOnBaseButNotOnDerived () } [ExpectedWarning ("IL2026", "RequiresOnClass.DerivedWithRequires.StaticMethodInInheritedClass()", "--DerivedWithRequires--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.DerivedWithRequires.StaticMethodInInheritedClass()", "--DerivedWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.DerivedWithRequires.StaticMethodInInheritedClass()", "--DerivedWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void TestRequiresOnDerivedButNotOnBase () { DerivedWithRequires.StaticMethodInInheritedClass (); @@ -439,9 +439,9 @@ static void TestRequiresOnDerivedButNotOnBase () } [ExpectedWarning ("IL2026", "RequiresOnClass.DerivedWithRequires2.StaticMethodInInheritedClass()", "--DerivedWithRequires2--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.DerivedWithRequires2.StaticMethodInInheritedClass()", "--DerivedWithRequires2--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.DerivedWithRequires2.StaticMethodInInheritedClass()", "--DerivedWithRequires2--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] [ExpectedWarning ("IL2026", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--")] - [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.StaticMethod()", "--ClassWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void TestRequiresOnBaseAndDerived () { DerivedWithRequires2.StaticMethodInInheritedClass (); @@ -452,7 +452,7 @@ static void TestRequiresOnBaseAndDerived () } [ExpectedWarning ("IL2026", "RequiresOnClass.ClassWithRequires.TestSuppressions(", "Type[])")] - [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.TestSuppressions(", "Type[])", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "RequiresOnClass.ClassWithRequires.TestSuppressions(", "Type[])", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void TestSuppressionsOnClass () { ClassWithRequires.TestSuppressions (new[] { typeof (ClassWithRequires) }); @@ -496,11 +496,11 @@ class MemberTypesWithRequires } [ExpectedWarning ("IL2026", "MemberTypesWithRequires.field")] - [ExpectedWarning ("IL3050", "MemberTypesWithRequires.field", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "MemberTypesWithRequires.field", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] [ExpectedWarning ("IL2026", "MemberTypesWithRequires.Property.set")] - [ExpectedWarning ("IL3050", "MemberTypesWithRequires.Property.set", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "MemberTypesWithRequires.Property.set", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] [ExpectedWarning ("IL2026", "MemberTypesWithRequires.Event.remove")] - [ExpectedWarning ("IL3050", "MemberTypesWithRequires.Event.remove", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "MemberTypesWithRequires.Event.remove", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warnings")] static void TestOtherMemberTypesWithRequires () { MemberTypesWithRequires.field = 1; @@ -519,25 +519,25 @@ static void TestNameOfDoesntWarn () class ReflectionAccessOnMethod { [ExpectedWarning ("IL2026", "BaseWithRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "BaseWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseWithRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "BaseWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseWithoutRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseWithoutRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "DerivedWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "InterfaceWithoutRequires.Method(Int32)")] - [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method(Int32)", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method(Int32)", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "InterfaceWithoutRequires.Method()")] - [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationWithRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationWithRequiresOnType.Method(Int32)")] - [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method(Int32)", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method(Int32)", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()")] - [ExpectedWarning ("IL3050", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()", Tool.NativeAot, "")] static void TestDAMAccess () { // Warns because BaseWithoutRequiresOnType.Method has Requires on the method @@ -563,17 +563,17 @@ static void TestDAMAccess () } [ExpectedWarning ("IL2026", "BaseWithRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "BaseWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseWithoutRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "InterfaceWithoutRequires.Method(Int32)")] - [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method(Int32)", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method(Int32)", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "InterfaceWithoutRequires.Method()")] - [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationWithRequiresOnType.Method()")] - [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "ImplementationWithRequiresOnType.Method(Int32)")] - [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method(Int32)", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method(Int32)", Tool.NativeAot, "")] static void TestDirectReflectionAccess () { // Requires on the method itself @@ -609,7 +609,7 @@ public BaseWithRequires () { } class DerivedWithoutRequires : BaseWithRequires { [ExpectedWarning ("IL2026", "--BaseWithRequires--")] // The body has direct call to the base.ctor() - [ExpectedWarning ("IL3050", "--BaseWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--BaseWithRequires--", Tool.Analyzer | Tool.NativeAot, "NativeAOT Specific Warning")] public DerivedWithoutRequires () { } } @@ -631,15 +631,15 @@ public DerivedWithRequiresOnBaseWithoutRequires () { } } [ExpectedWarning ("IL2026", "BaseWithRequires.BaseWithRequires()")] - [ExpectedWarning ("IL3050", "BaseWithRequires.BaseWithRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithRequires.BaseWithRequires()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseWithRequires.BaseWithRequires()")] - [ExpectedWarning ("IL3050", "BaseWithRequires.BaseWithRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithRequires.BaseWithRequires()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()")] - [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()")] - [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()")] - [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", Tool.NativeAot, "")] static void TestDAMAccess () { // Warns because the type has Requires @@ -656,11 +656,11 @@ static void TestDAMAccess () } [ExpectedWarning ("IL2026", "BaseWithRequires.BaseWithRequires()")] - [ExpectedWarning ("IL3050", "BaseWithRequires.BaseWithRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseWithRequires.BaseWithRequires()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()")] - [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithRequires.DerivedWithRequiresOnBaseWithRequires()", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()")] - [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnBaseWithoutRequires.DerivedWithRequiresOnBaseWithoutRequires()", Tool.NativeAot, "")] static void TestDirectReflectionAccess () { typeof (BaseWithRequires).GetConstructor (Type.EmptyTypes); @@ -708,15 +708,15 @@ class DerivedWithRequires : WithRequires } [ExpectedWarning ("IL2026", "WithRequires.StaticField")] - [ExpectedWarning ("IL3050", "WithRequires.StaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticField", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticField")] - [ExpectedWarning ("IL3050", "WithRequires.StaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticField", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticField")] - [ExpectedWarning ("IL3050", "WithRequires.StaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticField", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.PrivateStaticField")] - [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticField", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticField")] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticField", Tool.NativeAot, "")] static void TestDAMAccess () { typeof (WithRequires).RequiresPublicFields (); @@ -727,11 +727,11 @@ static void TestDAMAccess () } [ExpectedWarning ("IL2026", "WithRequires.StaticField")] - [ExpectedWarning ("IL3050", "WithRequires.StaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticField", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.PrivateStaticField")] - [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticField", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticField")] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticField", Tool.NativeAot, "")] static void TestDirectReflectionAccess () { typeof (WithRequires).GetField (nameof (WithRequires.StaticField)); @@ -742,17 +742,17 @@ static void TestDirectReflectionAccess () typeof (DerivedWithRequires).GetField (nameof (DerivedWithRequires.DerivedStaticField)); } - [ExpectedWarning ("IL2026", "WithRequires.StaticField", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticField", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticField", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticField", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticField", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "WithRequires.StaticField", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticField", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticField", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticField", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticField", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticField", Tool.NativeAot, "")] [DynamicDependency (nameof (WithRequires.StaticField), typeof (WithRequires))] [DynamicDependency (nameof (WithRequires.InstanceField), typeof (WithRequires))] // Doesn't warn [DynamicDependency (DynamicallyAccessedMemberTypes.PublicFields, typeof (DerivedWithoutRequires))] // Doesn't warn - [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticField", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticField", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticField", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticField", Tool.NativeAot, "")] [DynamicDependency (DynamicallyAccessedMemberTypes.PublicFields, typeof (DerivedWithRequires))] static void TestDynamicDependencyAccess () { @@ -768,13 +768,13 @@ class BaseForDAMAnnotatedClass [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] [RequiresUnreferencedCode ("This class is dangerous")] [RequiresDynamicCode ("This class is dangerous")] - [ExpectedWarning ("IL2113", "BaseForDAMAnnotatedClass.baseField", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2113", "BaseForDAMAnnotatedClass.baseField", Tool.Trimmer | Tool.NativeAot, "")] class DAMAnnotatedClass : BaseForDAMAnnotatedClass { - [ExpectedWarning ("IL2112", "DAMAnnotatedClass.publicField", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "DAMAnnotatedClass.publicField", Tool.Trimmer | Tool.NativeAot, "")] public static int publicField; - [ExpectedWarning ("IL2112", "DAMAnnotatedClass.privatefield", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "DAMAnnotatedClass.privatefield", Tool.Trimmer | Tool.NativeAot, "")] static int privatefield; } @@ -786,7 +786,7 @@ static void TestDAMOnTypeAccess (DAMAnnotatedClass instance) [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] class DAMAnnotatedClassAccessedFromRUCScope { - [ExpectedWarning ("IL2112", "DAMAnnotatedClassAccessedFromRUCScope.RUCMethod", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "DAMAnnotatedClassAccessedFromRUCScope.RUCMethod", Tool.Trimmer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("--RUCMethod--")] public static void RUCMethod () { } } @@ -807,14 +807,14 @@ class GenericTypeWithRequires } [ExpectedWarning ("IL2026", "NonGenericField", "--GenericTypeWithRequires--")] - [ExpectedWarning ("IL3050", "NonGenericField", "--GenericTypeWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "NonGenericField", "--GenericTypeWithRequires--", Tool.NativeAot, "")] static void TestDAMAccessOnOpenGeneric () { typeof (GenericTypeWithRequires<>).RequiresPublicFields (); } [ExpectedWarning ("IL2026", "NonGenericField", "--GenericTypeWithRequires--")] - [ExpectedWarning ("IL3050", "NonGenericField", "--GenericTypeWithRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "NonGenericField", "--GenericTypeWithRequires--", Tool.NativeAot, "")] static void TestDAMAccessOnInstantiatedGeneric () { typeof (GenericTypeWithRequires).RequiresPublicFields (); @@ -846,11 +846,11 @@ class WithRequires } [ExpectedWarning ("IL2026", "StaticEvent.add")] - [ExpectedWarning ("IL3050", "StaticEvent.add", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "StaticEvent.add", Tool.NativeAot, "")] // https://github.com/dotnet/runtime/issues/100499 - [ExpectedWarning ("IL2026", "StaticEvent.add", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", "StaticEvent.add", Tool.Trimmer, "")] [ExpectedWarning ("IL2026", "StaticEvent.remove")] - [ExpectedWarning ("IL3050", "StaticEvent.remove", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "StaticEvent.remove", Tool.NativeAot, "")] static void TestDirectReflectionAccess () { typeof (WithRequires).GetEvent (nameof (WithRequires.StaticEvent)); @@ -894,41 +894,41 @@ class DerivedWithRequires : WithRequires } [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.PrivateStaticProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.PrivateStaticProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.get")] - [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.set")] - [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.get")] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.set")] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.set", Tool.NativeAot, "")] static void TestDAMAccess () { typeof (WithRequires).RequiresPublicProperties (); @@ -939,25 +939,25 @@ static void TestDAMAccess () } [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.PrivateStaticProperty.get")] - [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequires.PrivateStaticProperty.set")] - [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequires.PrivateStaticProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.get")] - [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "WithRequiresOnlyInstanceProperties.InstanceProperty.set")] - [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "WithRequiresOnlyInstanceProperties.InstanceProperty.set", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.get")] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.get", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.set")] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.set", Tool.NativeAot, "")] static void TestDirectReflectionAccess () { typeof (WithRequires).GetProperty (nameof (WithRequires.StaticProperty)); @@ -968,37 +968,37 @@ static void TestDirectReflectionAccess () typeof (DerivedWithRequires).GetProperty (nameof (DerivedWithRequires.DerivedStaticProperty)); } - [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.InstanceProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.InstanceProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "WithRequires.StaticProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "WithRequires.StaticProperty.set", Tool.NativeAot, "")] [DynamicDependency (nameof (WithRequires.StaticProperty), typeof (WithRequires))] [DynamicDependency (nameof (WithRequires.InstanceProperty), typeof (WithRequires))] // Doesn't warn [DynamicDependency (DynamicallyAccessedMemberTypes.PublicProperties, typeof (DerivedWithoutRequires))] // Doesn't warn - [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.get", Tool.NativeAot, "")] + [ExpectedWarning ("IL2026", "DerivedWithRequires.DerivedStaticProperty.set", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "DerivedWithRequires.DerivedStaticProperty.set", Tool.NativeAot, "")] [DynamicDependency (DynamicallyAccessedMemberTypes.PublicProperties, typeof (DerivedWithRequires))] static void TestDynamicDependencyAccess () { @@ -1014,21 +1014,21 @@ class BaseForDAMAnnotatedClass [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] [RequiresUnreferencedCode ("This class is dangerous")] [RequiresDynamicCode ("This class is dangerous")] - [ExpectedWarning ("IL2113", "BaseForDAMAnnotatedClass.baseProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2113", "BaseForDAMAnnotatedClass.baseProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2113", "BaseForDAMAnnotatedClass.baseProperty.get", Tool.Trimmer | Tool.NativeAot, "")] + [ExpectedWarning ("IL2113", "BaseForDAMAnnotatedClass.baseProperty.set", Tool.Trimmer | Tool.NativeAot, "")] class DAMAnnotatedClass : BaseForDAMAnnotatedClass { public static int publicProperty { - [ExpectedWarning ("IL2112", "DAMAnnotatedClass.publicProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "DAMAnnotatedClass.publicProperty.get", Tool.Trimmer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL2112", "DAMAnnotatedClass.publicProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "DAMAnnotatedClass.publicProperty.set", Tool.Trimmer | Tool.NativeAot, "")] set; } static int privateProperty { - [ExpectedWarning ("IL2112", "DAMAnnotatedClass.privateProperty.get", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "DAMAnnotatedClass.privateProperty.get", Tool.Trimmer | Tool.NativeAot, "")] get; - [ExpectedWarning ("IL2112", "DAMAnnotatedClass.privateProperty.set", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2112", "DAMAnnotatedClass.privateProperty.set", Tool.Trimmer | Tool.NativeAot, "")] set; } } @@ -1064,7 +1064,7 @@ public int PropertyOnAttribute { [AttributeWithRequires (PropertyOnAttribute = 42)] [ExpectedWarning ("IL2026", "AttributeWithRequires.AttributeWithRequires()")] - [ExpectedWarning ("IL3050", "AttributeWithRequires.AttributeWithRequires()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "AttributeWithRequires.AttributeWithRequires()", Tool.Analyzer | Tool.NativeAot, "")] static void KeepFieldOnAttributeInner () { } static void KeepFieldOnAttribute () @@ -1114,7 +1114,7 @@ public static void Test () { } } [ExpectedWarning ("IL2026")] - [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { TestClass.Test (); @@ -1140,17 +1140,15 @@ public class ClassWithRequires { public static RequiresAll field; - // https://github.com/dotnet/linker/issues/3142 // Instance fields get generic warnings but static fields don't. - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2091", Tool.Trimmer, "https://github.com/dotnet/linker/issues/3142")] public RequiresAll instanceField; [RequiresOnCtor] public static int fieldWithAttribute; - // https://github.com/dotnet/linker/issues/3140 // Instance fields get attribute warnings but static fields don't. - [ExpectedWarning ("IL2026", "--RequiresOnCtorAttribute--", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", "--RequiresOnCtorAttribute--", Tool.Trimmer, "https://github.com/dotnet/linker/issues/3140")] [RequiresOnCtor] public int instanceFieldWithAttribute; @@ -1183,23 +1181,20 @@ public class ClassWithAttribute } // This warning should ideally be suppressed by the RUC on the type: - // https://github.com/dotnet/linker/issues/3142 - [ExpectedWarning ("IL2091")] + [UnexpectedWarning ("IL2091", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/linker/issues/3142")] [RequiresUnreferencedCode ("--GenericClassWithWarningWithRequires--")] public class GenericClassWithWarningWithRequires : RequiresAll { } // This warning should ideally be suppressed by the RUC on the type: - // https://github.com/dotnet/linker/issues/3142 - [ExpectedWarning ("IL2091")] + [UnexpectedWarning ("IL2091", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/linker/issues/3142")] [RequiresUnreferencedCode ("--ClassWithWarningWithRequires--")] public class ClassWithWarningWithRequires : RequiresAll { } - // https://github.com/dotnet/linker/issues/3142 - [ExpectedWarning ("IL2091")] + [UnexpectedWarning ("IL2091", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/linker/issues/3142")] [RequiresUnreferencedCode ("--GenericAnnotatedWithWarningWithRequires--")] public class GenericAnnotatedWithWarningWithRequires<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] TFields> : RequiresAll { @@ -1212,7 +1207,7 @@ public class GenericAnnotatedWithWarningWithRequires<[DynamicallyAccessedMembers [ExpectedWarning ("IL2026", "--GenericClassWithWarningWithRequires--")] [ExpectedWarning ("IL2026", "--ClassWithWarningWithRequires--")] [ExpectedWarning ("IL2026", "--GenericAnnotatedWithWarningWithRequires--")] - [ExpectedWarning ("IL2091", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2091", Tool.Trimmer, "")] public static void Test (ClassWithRequires inst = null) { var f = ClassWithRequires.field; @@ -1244,7 +1239,7 @@ public static void Method () { } } [ExpectedWarning ("IL2026", "--ConstClassWithRequires--", nameof (ConstClassWithRequires.Method))] - [ExpectedWarning ("IL3050", "--ConstClassWithRequires--", nameof (ConstClassWithRequires.Method), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--ConstClassWithRequires--", nameof (ConstClassWithRequires.Method), Tool.Analyzer | Tool.NativeAot, "")] static void TestClassWithRequires () { var a = ConstClassWithRequires.Message; @@ -1263,7 +1258,7 @@ public static void Method () { } } [ExpectedWarning ("IL2026", "--ConstClassWithRequiresUsingField--", nameof (ConstClassWithRequiresUsingField.Method))] - [ExpectedWarning ("IL3050", "--ConstClassWithRequiresUsingField--", nameof (ConstClassWithRequiresUsingField.Method), ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--ConstClassWithRequiresUsingField--", nameof (ConstClassWithRequiresUsingField.Method), Tool.Analyzer | Tool.NativeAot, "")] static void TestClassUsingFieldInAttribute () { ConstClassWithRequiresUsingField.Method (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnStaticConstructor.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnStaticConstructor.cs index 98fbe6876f0a..cfd8bfd9145f 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnStaticConstructor.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnStaticConstructor.cs @@ -30,8 +30,8 @@ public static void Main () class StaticCtor { [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2116", "StaticCtor..cctor()")] [RequiresUnreferencedCode ("Message for --TestStaticCtor--")] static StaticCtor () @@ -48,8 +48,8 @@ static void TestStaticCctorRequires () [RequiresUnreferencedCode ("Message for --StaticCtorOnTypeWithRequires--")] class StaticCtorOnTypeWithRequires { - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static StaticCtorOnTypeWithRequires () => MethodWithRequires (); } @@ -70,8 +70,8 @@ static void TestRunClassConstructorOnTypeWithRequires () class StaticCtorForRunClassConstructorWithRequires { [ExpectedWarning ("IL2116")] - [ExpectedWarning ("IL3004", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3056", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3004", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3056", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message for --StaticCtorOnTypeWithRequires--")] [RequiresAssemblyFiles ("Message for --StaticCtorOnTypeWithRequires--")] [RequiresDynamicCode ("Message for --StaticCtorOnTypeWithRequires--")] @@ -118,8 +118,8 @@ static void TestStaticCtorMarkingIsTriggeredByFieldAccessOnExplicitLayout () class StaticCtorTriggeredByMethodCall { [ExpectedWarning ("IL2116", "StaticCtorTriggeredByMethodCall..cctor()")] - [ExpectedWarning ("IL3004", "StaticCtorTriggeredByMethodCall..cctor()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3056", "StaticCtorTriggeredByMethodCall..cctor()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3004", "StaticCtorTriggeredByMethodCall..cctor()", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3056", "StaticCtorTriggeredByMethodCall..cctor()", Tool.Analyzer | Tool.NativeAot, "")] [RequiresUnreferencedCode ("Message for --StaticCtorTriggeredByMethodCall.Cctor--")] [RequiresAssemblyFiles ("Message for --StaticCtorTriggeredByMethodCall.Cctor--")] [RequiresDynamicCode ("Message for --StaticCtorTriggeredByMethodCall.Cctor--")] @@ -137,8 +137,8 @@ public void TriggerStaticCtorMarking () [ExpectedWarning ("IL2026", "--StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--")] - [ExpectedWarning ("IL3002", "--StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--StaticCtorTriggeredByMethodCall.TriggerStaticCtorMarking--", Tool.Analyzer | Tool.NativeAot, "")] static void TestStaticCtorTriggeredByMethodCall () { new StaticCtorTriggeredByMethodCall ().TriggerStaticCtorMarking (); @@ -146,9 +146,9 @@ static void TestStaticCtorTriggeredByMethodCall () class TypeIsBeforeFieldInit { - [ExpectedWarning ("IL2026", "Message from --TypeIsBeforeFieldInit.AnnotatedMethod--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3002", "Message from --TypeIsBeforeFieldInit.AnnotatedMethod--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "Message from --TypeIsBeforeFieldInit.AnnotatedMethod--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "Message from --TypeIsBeforeFieldInit.AnnotatedMethod--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3002", "Message from --TypeIsBeforeFieldInit.AnnotatedMethod--", Tool.Analyzer, "")] + [ExpectedWarning ("IL3050", "Message from --TypeIsBeforeFieldInit.AnnotatedMethod--", Tool.Analyzer, "")] public static int field = AnnotatedMethod (); [RequiresUnreferencedCode ("Message from --TypeIsBeforeFieldInit.AnnotatedMethod--")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs index b9ac10e61c11..4623dd6355fc 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs @@ -46,8 +46,8 @@ public override void VirtualMethodRequires () } [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestCallOnBase () { var tmp = new BaseType (); @@ -55,8 +55,8 @@ static void TestCallOnBase () } [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestCallOnOverride () { var tmp = new TypeWhichOverridesMethod (); @@ -64,8 +64,8 @@ static void TestCallOnOverride () } [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestCallOnOverrideViaBase () { BaseType tmp = new TypeWhichOverridesMethod (); @@ -73,11 +73,11 @@ static void TestCallOnOverrideViaBase () } [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TypeWhichOverridesMethod.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWhichOverridesMethod.VirtualMethodRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TypeWhichOverridesMethod.VirtualMethodRequires--", Tool.NativeAot, "")] static void TestDirectReflectionAccess () { BaseType tmp = new TypeWhichOverridesMethod (); @@ -90,11 +90,11 @@ static void TestDirectReflectionAccess () } [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--TypeWhichOverridesMethod.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--TypeWhichOverridesMethod.VirtualMethodRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--TypeWhichOverridesMethod.VirtualMethodRequires--", Tool.NativeAot, "")] static void TestAnnotatedReflectionAccess() { CallMethodWithRequiresOnInstance(new TypeWhichOverridesMethod ()); @@ -133,8 +133,8 @@ public override int VirtualPropertyRequires { } [ExpectedWarning ("IL2026", "--PropertyBaseType.VirtualPropertyRequires--")] - [ExpectedWarning ("IL3002", "--PropertyBaseType.VirtualPropertyRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--PropertyBaseType.VirtualPropertyRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--PropertyBaseType.VirtualPropertyRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--PropertyBaseType.VirtualPropertyRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void CallOnDerived () { var tmp = new TypeWhichOverridesProperty (); @@ -171,8 +171,8 @@ public void MethodWithRequires () } [ExpectedWarning ("IL2026", "--IRequires.MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--IRequires.MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--IRequires.MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--IRequires.MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--IRequires.MethodWithRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void TestCallViaInterface () { IRequires inst = new ImplementationClass (); @@ -180,8 +180,8 @@ static void TestCallViaInterface () } [ExpectedWarning ("IL2026", "--ImplementationClass.RequiresMethod--")] - [ExpectedWarning ("IL3002", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--ImplementationClass.RequiresMethod--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--ImplementationClass.RequiresMethod--", Tool.Analyzer | Tool.NativeAot, "")] static void TestCallViaImplementationClass () { ImplementationClass inst = new ImplementationClass (); @@ -189,8 +189,8 @@ static void TestCallViaImplementationClass () } [ExpectedWarning ("IL2026", "--ImplementationClass.RequiresMethod--")] - [ExpectedWarning ("IL3002", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--ImplementationClass.RequiresMethod--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--ImplementationClass.RequiresMethod--", Tool.NativeAot, "")] static void TestDirectReflectionAccess () { typeof (ImplementationClass).GetMethod ("MethodWithRequires").Invoke (new ImplementationClass (), Array.Empty ()); @@ -202,8 +202,8 @@ static void TestDirectReflectionAccess () } [ExpectedWarning ("IL2026", "--ImplementationClass.RequiresMethod--")] - [ExpectedWarning ("IL3002", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--ImplementationClass.RequiresMethod--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--ImplementationClass.RequiresMethod--", Tool.NativeAot, "")] static void TestAnnotatedReflectionAccess () { CallMethodWithRequiresOnInstance (new ImplementationClass ()); @@ -240,8 +240,8 @@ public override DerivedReturnType GetRequires () } [ExpectedWarning ("IL2026", "--CovariantReturnDerived.GetRequires--")] - [ExpectedWarning ("IL3002", "--CovariantReturnDerived.GetRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--CovariantReturnDerived.GetRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--CovariantReturnDerived.GetRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--CovariantReturnDerived.GetRequires--", Tool.Analyzer | Tool.NativeAot, "")] static void CallOnDerived () { var tmp = new CovariantReturnDerived (); @@ -276,8 +276,8 @@ public override DerivedReturnType GetRequires () } [ExpectedWarning ("IL2026", "--CovariantReturnViaLdftn.Derived.GetRequires--")] - [ExpectedWarning ("IL3002", "--CovariantReturnViaLdftn.Derived.GetRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--CovariantReturnViaLdftn.Derived.GetRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--CovariantReturnViaLdftn.Derived.GetRequires--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--CovariantReturnViaLdftn.Derived.GetRequires--", Tool.Analyzer | Tool.NativeAot, "")] public static void Test () { var tmp = new Derived (); @@ -305,12 +305,12 @@ public virtual void RUCMethod () { } [ExpectedWarning ("IL2026", "Message for --NewSlotVirtual.Base.RUCMethod--")] // Reflection triggered warnings are not produced by analyzer for RDC/RAS - [ExpectedWarning ("IL3002", "Message for --NewSlotVirtual.Base.RUCMethod--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --NewSlotVirtual.Base.RUCMethod--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message for --NewSlotVirtual.Base.RUCMethod--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Message for --NewSlotVirtual.Base.RUCMethod--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "Message for --NewSlotVirtual.Derived.RUCMethod--")] // Reflection triggered warnings are not produced by analyzer for RDC/RAS - [ExpectedWarning ("IL3002", "Message for --NewSlotVirtual.Derived.RUCMethod--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --NewSlotVirtual.Derived.RUCMethod--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "Message for --NewSlotVirtual.Derived.RUCMethod--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "Message for --NewSlotVirtual.Derived.RUCMethod--", Tool.NativeAot, "")] public static void Test () { typeof (Derived).RequiresPublicMethods (); @@ -343,11 +343,11 @@ public static void AbstractMethod () { } } [ExpectedWarning ("IL2026", "--StaticInterfaces.IRequires.VirtualMethod--")] - [ExpectedWarning ("IL3002", "--StaticInterfaces.IRequires.VirtualMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--StaticInterfaces.IRequires.VirtualMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--StaticInterfaces.IRequires.VirtualMethod--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--StaticInterfaces.IRequires.VirtualMethod--", Tool.Analyzer | Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--StaticInterfaces.IRequires.AbstractMethod--")] - [ExpectedWarning ("IL3002", "--StaticInterfaces.IRequires.AbstractMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--StaticInterfaces.IRequires.AbstractMethod--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--StaticInterfaces.IRequires.AbstractMethod--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--StaticInterfaces.IRequires.AbstractMethod--", Tool.Analyzer | Tool.NativeAot, "")] static void UseRequiresMethods () where T : IRequires { T.AbstractMethod (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaDataflow.cs index bec62cf5dbc4..0be02b8402de 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaDataflow.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaDataflow.cs @@ -60,11 +60,11 @@ public override void VirtualMethodRequires () } [ExpectedWarning ("IL2026", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", Tool.NativeAot, "")] static void TestOverriddenVirtualMethod () { MethodWithAnnotatedParameter (typeof (TypeWhichOverridesMethod)); @@ -93,8 +93,8 @@ public TypeWithPublicMethods () { } } [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", Tool.NativeAot, "")] static void TestAccessOnGenericType () { new TypeWithPublicMethods (); @@ -103,8 +103,8 @@ static void TestAccessOnGenericType () static void MethodWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { } [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", Tool.NativeAot, "")] static void TestAccessOnGenericMethod () { MethodWithPublicMethods (); @@ -113,8 +113,8 @@ static void TestAccessOnGenericMethod () static void MethodWithPublicMethodsInference<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> (T instance) { } [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", Tool.NativeAot, "")] static void TestAccessOnGenericMethodWithInferenceOnMethod () { MethodWithPublicMethodsInference (new TypeWithRequiresMethod ()); @@ -137,10 +137,10 @@ static void RequiresInDynamicDependency () { } - // https://github.com/dotnet/runtime/issues/83080 - Analyzer doesn't recognize DynamicDependency in any way - [ExpectedWarning ("IL2026", "--RequiresInDynamicDependency--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--RequiresInDynamicDependency--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--RequiresInDynamicDependency--", ProducedBy = Tool.NativeAot)] + // Analyzer doesn't recognize DynamicDependency in any way + [ExpectedWarning ("IL2026", "--RequiresInDynamicDependency--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] + [ExpectedWarning ("IL3002", "--RequiresInDynamicDependency--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] + [ExpectedWarning ("IL3050", "--RequiresInDynamicDependency--", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/83080")] [DynamicDependency ("RequiresInDynamicDependency")] public static void Test () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaXml.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaXml.cs index ab0ecd81cab7..eb0c4fcde0a1 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaXml.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresViaXml.cs @@ -17,7 +17,7 @@ class RequiresViaXml // The second attribute is added through link attribute XML [RequiresUnreferencedCode ("Message for --MethodWithDuplicateRequiresAttribute--")] - [ExpectedWarning ("IL2027", "RequiresUnreferencedCodeAttribute", nameof (MethodWithDuplicateRequiresAttribute), ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2027", "RequiresUnreferencedCodeAttribute", nameof (MethodWithDuplicateRequiresAttribute), Tool.Trimmer, "")] static void MethodWithDuplicateRequiresAttribute () { } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresWithCopyAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresWithCopyAssembly.cs index 91485b261a5f..e935d9418785 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresWithCopyAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresWithCopyAssembly.cs @@ -29,11 +29,11 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class RequiresWithCopyAssembly { [ExpectedWarning ("IL2026", "--IDerivedInterface.MethodInDerivedInterface--")] - [ExpectedWarning ("IL3002", "--IDerivedInterface.MethodInDerivedInterface--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--IDerivedInterface.MethodInDerivedInterface--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--IDerivedInterface.MethodInDerivedInterface--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--IDerivedInterface.MethodInDerivedInterface--", Tool.NativeAot, "")] [ExpectedWarning ("IL2026", "--IBaseInterface.MethodInBaseInterface--")] - [ExpectedWarning ("IL3002", "--IBaseInterface.MethodInBaseInterface--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--IBaseInterface.MethodInBaseInterface--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--IBaseInterface.MethodInBaseInterface--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--IBaseInterface.MethodInBaseInterface--", Tool.NativeAot, "")] public static void Main () { TestRequiresInMethodFromCopiedAssembly (); @@ -42,8 +42,8 @@ public static void Main () } [ExpectedWarning ("IL2026", "--Method--")] - [ExpectedWarning ("IL3002", "--Method--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--Method--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--Method--", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--Method--", Tool.Analyzer | Tool.NativeAot, "")] static void TestRequiresInMethodFromCopiedAssembly () { var tmp = new RequiresInCopyAssembly (); @@ -51,8 +51,8 @@ static void TestRequiresInMethodFromCopiedAssembly () } [ExpectedWarning ("IL2026", "--MethodCalledThroughReflection--")] - [ExpectedWarning ("IL3002", "--MethodCalledThroughReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodCalledThroughReflection--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodCalledThroughReflection--", Tool.NativeAot, "")] + [ExpectedWarning ("IL3050", "--MethodCalledThroughReflection--", Tool.NativeAot, "")] static void TestRequiresThroughReflectionInMethodFromCopiedAssembly () { typeof (RequiresInCopyAssembly) diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/SingleFile/SingleFileIntrinsics.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/SingleFile/SingleFileIntrinsics.cs index 5273af0230c1..617e286e1e64 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/SingleFile/SingleFileIntrinsics.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/SingleFile/SingleFileIntrinsics.cs @@ -27,7 +27,7 @@ public static void Main () TestAssemblyGetFilesSuppressedByRAF (); } - [ExpectedWarning("IL3000", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning("IL3000", Tool.Analyzer | Tool.NativeAot, "")] static void TestAssemblyLocation() { var a = typeof (SingleFileIntrinsics).Assembly.Location; @@ -39,7 +39,7 @@ static void TestAssemblyLocationSuppressedByRAF() var a = typeof (SingleFileIntrinsics).Assembly.Location; } - [ExpectedWarning ("IL3000", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3000", Tool.Analyzer | Tool.NativeAot, "")] static void TestAssemblyNameCodeBase() { var a = typeof (SingleFileIntrinsics).Assembly.GetName ().CodeBase; @@ -51,7 +51,7 @@ static void TestAssemblyNameCodeBaseSuppressedByRAF () var a = typeof (SingleFileIntrinsics).Assembly.GetName ().CodeBase; } - [ExpectedWarning ("IL3000", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3000", Tool.Analyzer | Tool.NativeAot, "")] static void TestAssemblyNameEscapedCodeBase () { var a = typeof (SingleFileIntrinsics).Assembly.GetName ().EscapedCodeBase; @@ -63,7 +63,7 @@ static void TestAssemblyNameEscapedCodeBaseSuppressedByRAF () var a = typeof (SingleFileIntrinsics).Assembly.GetName ().EscapedCodeBase; } - [ExpectedWarning ("IL3001", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3001", Tool.Analyzer | Tool.NativeAot, "")] static void TestAssemblyGetFile() { var a = typeof (SingleFileIntrinsics).Assembly.GetFile ("unknown"); @@ -75,8 +75,8 @@ static void TestAssemblyGetFileSuppressedByRAF () var a = typeof (SingleFileIntrinsics).Assembly.GetFile ("unknown"); } - [ExpectedWarning ("IL3001", ProducedBy = Tool.Analyzer | Tool.NativeAot)] - [ExpectedWarning ("IL3001", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3001", Tool.Analyzer | Tool.NativeAot, "")] + [ExpectedWarning ("IL3001", Tool.Analyzer | Tool.NativeAot, "")] static void TestAssemblyGetFiles () { var a = typeof (SingleFileIntrinsics).Assembly.GetFiles (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutions.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutions.cs index e34f2b4bbfd3..b4723f350543 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutions.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutions.cs @@ -93,8 +93,8 @@ static void TestGuardAssemblyFiles () RequiresAssemblyFiles (); } - [ExpectedWarning ("IL4000", nameof (RequiresDynamicCodeAttribute), ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresDynamicCodeAttribute), Tool.Analyzer, "")] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureGuard (typeof (RequiresDynamicCodeAttribute))] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool GuardDynamicCodeAndUnreferencedCode => RuntimeFeature.IsDynamicCodeSupported && TestFeatures.IsUnreferencedCodeSupported; @@ -152,7 +152,7 @@ static void TestIndirectGuard () [FeatureSwitchDefinition ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.DefineFeatureGuard.FeatureSwitch")] static bool FeatureSwitch => AppContext.TryGetSwitch ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.DefineFeatureGuard.FeatureSwitch", out bool isEnabled) && isEnabled; - [ExpectedWarning ("IL2026", ProducedBy = Tool.Analyzer)] // Analyzer doesn't respect FeatureSwitchDefinition or feature settings + [ExpectedWarning ("IL2026", Tool.Analyzer, "")] // Analyzer doesn't respect FeatureSwitchDefinition or feature settings [ExpectedInstructionSequence (new[] { "nop", "ldc.i4.0", @@ -169,7 +169,7 @@ static void TestFeatureSwitch () RequiresUnreferencedCode (); } - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureSwitchDefinition ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.DefineFeatureGuard.FeatureSwitchAndGuard")] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool FeatureSwitchAndGuard => AppContext.TryGetSwitch ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.DefineFeatureGuard.FeatureSwitchAndGuard", out bool isEnabled) && isEnabled; @@ -264,7 +264,7 @@ public static void Test () [Kept] class FeatureGuardPrecedence { - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureSwitchDefinition ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.FeatureGuardPrecedence.GuardAndSwitch")] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool GuardAndSwitch => AppContext.TryGetSwitch ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.FeatureGuardPrecedence.GuardAndSwitch", out bool isEnabled) && isEnabled; @@ -281,7 +281,7 @@ class FeatureGuardPrecedence { "ret" })] // ILLink/ILCompiler ignore FeatureGuard on properties that also have FeatureSwitchDefinition - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "")] static void TestSwitchWinsOverGuard () { if (GuardAndSwitch) @@ -291,7 +291,7 @@ static void TestSwitchWinsOverGuard () [Kept] [KeptAttributeAttribute (typeof (FeatureSwitchDefinitionAttribute))] [KeptAttributeAttribute (typeof (FeatureGuardAttribute))] - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureSwitchDefinition ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.FeatureGuardPrecedence.GuardAndSwitchNotSet")] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool GuardAndSwitchNotSet { @@ -301,7 +301,7 @@ static bool GuardAndSwitchNotSet { [Kept] // No IL modifications because feature is not set, and FeatureGuard is ignored due to FeatureSwitchDefinition. - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "")] static void TestSwitchNotSetWinsOverGuard () { if (GuardAndSwitchNotSet) @@ -322,7 +322,7 @@ static void TestSwitchNotSetWinsOverGuard () "nop", "ret" })] - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "")] static void TestXmlWinsOverGuard () { if (GuardWithXml) @@ -331,7 +331,7 @@ static void TestXmlWinsOverGuard () [KeptAttributeAttribute (typeof (FeatureSwitchDefinitionAttribute))] [KeptAttributeAttribute (typeof (FeatureGuardAttribute))] - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureSwitchDefinition ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.FeatureGuardPrecedence.SwitchWithXml")] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool SwitchWithXml => AppContext.TryGetSwitch ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.FeatureGuardPrecedence.SwitchWithXml", out bool isEnabled) && isEnabled; @@ -348,7 +348,7 @@ static void TestXmlWinsOverGuard () "nop", "ret" })] - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "")] static void TestXmlWinsOverSwitch () { if (SwitchWithXml) RequiresUnreferencedCode (); @@ -356,7 +356,7 @@ static void TestXmlWinsOverSwitch () { [KeptAttributeAttribute (typeof (FeatureSwitchDefinitionAttribute))] [KeptAttributeAttribute (typeof (FeatureGuardAttribute))] - [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", nameof (RequiresUnreferencedCodeAttribute), Tool.Analyzer, "")] [FeatureSwitchDefinition ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardPrecedence.GuardAndSwitchWithXml")] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool GuardAndSwitchWithXml => AppContext.TryGetSwitch ("Mono.Linker.Tests.Cases.Substitutions.FeatureGuardSubstitutions.FeatureGuardPrecedence.GuardAndSwitchWithXml", out bool isEnabled) && isEnabled; @@ -373,7 +373,7 @@ static void TestXmlWinsOverSwitch () { "nop", "ret" })] - [ExpectedWarning ("IL2026", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "")] static void TestXmlWinsOverGuardAndSwitch () { if (GuardAndSwitchWithXml) RequiresUnreferencedCode (); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutionsDisabled.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutionsDisabled.cs index 198595d79394..725f849d9093 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutionsDisabled.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/FeatureGuardSubstitutionsDisabled.cs @@ -25,7 +25,7 @@ public static void Main () } [Kept] - [ExpectedWarning ("IL4000", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL4000", Tool.Analyzer, "")] [KeptAttributeAttribute (typeof (FeatureGuardAttribute))] [FeatureGuard (typeof (RequiresUnreferencedCodeAttribute))] static bool GuardUnreferencedCode { @@ -46,7 +46,7 @@ static void TestGuard () static bool FeatureSwitch => throw null; [Kept] - [ExpectedWarning ("IL2026", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", Tool.Analyzer, "")] // Feature switches are still substituted when feature guard substitutions are disabled [ExpectBodyModified] static void TestFeatureSwitch () diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/ResourceSubstitutions.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/ResourceSubstitutions.cs index 9bdf9075dae9..d52432adfb10 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/ResourceSubstitutions.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/ResourceSubstitutions.cs @@ -15,4 +15,4 @@ public static void Main () { } } -} \ No newline at end of file +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwardersRewrite.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwardersRewrite.cs index 240f36543995..4ed5061aa498 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwardersRewrite.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwardersRewrite.cs @@ -21,7 +21,7 @@ unsafe class TypeForwardersRewrite { static void Main () { -#if NETCOREAPP +#if NET Test (null); #endif Test2 (null); @@ -56,7 +56,7 @@ static void Main () [KeptMember ("Invoke()")] delegate C D (); -#if NETCOREAPP +#if NET [Kept] static void Test (delegate* arg) { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/CompilerGeneratedCodeSubstitutions.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/CompilerGeneratedCodeSubstitutions.cs index 3c59c3e446aa..b93b47f0aebc 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/CompilerGeneratedCodeSubstitutions.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/CompilerGeneratedCodeSubstitutions.cs @@ -158,8 +158,7 @@ static IEnumerable TestBranchWithYieldAfter () } [ExpectedWarning ("IL2026", "--UsedMethod--", CompilerGeneratedCode = true)] - // https://github.com/dotnet/linker/issues/3087 - [ExpectedWarning ("IL2026", "--RemovedMethod--", CompilerGeneratedCode = true)] + [UnexpectedWarning ("IL2026", "--RemovedMethod--", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/linker/issues/3087", CompilerGeneratedCode = true)] static IEnumerable TestBranchWithYieldBefore () { if (AlwaysFalse) { @@ -197,8 +196,7 @@ static async Task TestBranchWithNormalCall () } [ExpectedWarning ("IL2026", "--UsedMethod--", CompilerGeneratedCode = true)] - // https://github.com/dotnet/linker/issues/3087 - [ExpectedWarning ("IL2026", "--RemovedMethod--", CompilerGeneratedCode = true)] + [UnexpectedWarning ("IL2026", "--RemovedMethod--", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/linker/issues/3087", CompilerGeneratedCode = true)] static async Task TestBranchWithNormalCallAfterWAwait () { if (AlwaysFalse) { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs index ea7d62c5fb7d..68714608fcca 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/ComplexConditions.cs @@ -17,7 +17,7 @@ public static void Main () } [Kept] -#if !NETCOREAPP +#if !NET [ExpectBodyModified] #else [ExpectedInstructionSequence (new[] { @@ -50,7 +50,7 @@ static void Test_1 (object type) } [Kept] -#if !NETCOREAPP +#if !NET [ExpectBodyModified] #else [ExpectedInstructionSequence (new[] { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.cs index 0e0c1ef2a335..230b7e4e9ba0 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/SizeOfInConditions.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.UnreachableBlock { -#if NETCOREAPP +#if NET [SetupLinkerSubstitutionFile ("SizeOfInConditions.netcore.xml")] #else [SetupLinkerSubstitutionFile ("SizeOfInConditions.net_4_x.xml")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibrary.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibrary.cs index 9c9ae70e6dc1..0da48a31799d 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibrary.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibrary.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.UnreachableBody { -#if NETCOREAPP +#if NET [SetupLinkerArgument ("-a", "other2.dll")] #else [SetupLinkerArgument ("-r", "other2")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibraryNoInstanceCtor.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibraryNoInstanceCtor.cs index 852c9351af12..9cdfe5cb72f1 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibraryNoInstanceCtor.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBody/LinkedOtherIncludedLibraryNoInstanceCtor.cs @@ -5,7 +5,7 @@ namespace Mono.Linker.Tests.Cases.UnreachableBody { [SetupLinkerArgument ("--skip-unresolved", "true")] [Define ("OTHER_INCLUDED")] -#if NETCOREAPP +#if NET [SetupLinkerArgument ("-a", "other.dll", "visible")] #else [SetupLinkerArgument ("-r", "other")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileCSharp.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileCSharp.cs index 4bb2c22213bf..afe1832a0013 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileCSharp.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileCSharp.cs @@ -8,7 +8,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.Individual { [SetupLinkerTrimMode ("skip")] -#if !NETCOREAPP +#if !NET [Reference ("System.Core.dll")] [SetupCompileBefore ("library.dll", new[] { typeof (TriggerWarnings_Lib) }, new[] { "System.Core.dll" })] #else diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileXml.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileXml.cs index 47d1c929435d..e11f941e23f8 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileXml.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/CanGenerateWarningSuppressionFileXml.cs @@ -5,7 +5,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.Individual { [SetupLinkerTrimMode ("skip")] -#if !NETCOREAPP +#if !NET [SetupCompileBefore ("library.dll", new[] { typeof (TriggerWarnings_Lib) }, new[] { "System.Core.dll" })] #else [SetupCompileBefore ("library.dll", new[] { typeof (TriggerWarnings_Lib) })] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/WarningsAreSorted.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/WarningsAreSorted.cs index c39f6a9028ce..10cd9d58982d 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/WarningsAreSorted.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/Individual/WarningsAreSorted.cs @@ -12,7 +12,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.Individual { [SkipRemainingErrorsValidation] [SetupLinkerTrimMode ("skip")] -#if !NETCOREAPP +#if !NET [SetupCompileBefore ("library.dll", new[] { typeof (TriggerWarnings_Lib) }, new[] { "System.Core.dll" })] #else [SetupCompileBefore ("library.dll", new[] { typeof (TriggerWarnings_Lib) })] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFeatureSubstitutions.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFeatureSubstitutions.cs index 2f271f000919..a5cb25f76134 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFeatureSubstitutions.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFeatureSubstitutions.cs @@ -37,13 +37,11 @@ public static bool IsFeatureEnabled { class ReportRedundantSuppressionWhenTrimmerIncompatibleCodeDisabled { - // The test simulates the following issue. - // https://github.com/dotnet/linker/issues/2921 // The suppressed warning is issued in the 'if' branch. // With feature switched to false, the trimming tools see only the 'else' branch. // The 'else' branch contains trimmer-compatible code, the trimming tools identifies the suppression as redundant. - [ExpectedWarning ("IL2121", "IL2072", ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2121", "IL2072", Tool.Trimmer, "https://github.com/dotnet/linker/issues/2921")] [UnconditionalSuppressMessage ("Test", "IL2072")] public static void Test () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFromXML.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFromXML.cs index 4d669f696fc2..aab9f0072888 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFromXML.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsFromXML.cs @@ -8,8 +8,8 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression { [SkipKeptItemsValidation] [ExpectedNoWarnings] - [ExpectedWarning ("IL2121", "IL2026", ProducedBy = Tool.Trimmer, FileName = "DetectRedundantSuppressionsFromXML.xml", SourceLine = 7)] - [ExpectedWarning ("IL2121", "IL2109", ProducedBy = Tool.Trimmer, FileName = "DetectRedundantSuppressionsFromXML.xml", SourceLine = 12)] + [ExpectedWarning ("IL2121", "IL2026", Tool.Trimmer, "", FileName = "DetectRedundantSuppressionsFromXML.xml", SourceLine = 7)] + [ExpectedWarning ("IL2121", "IL2109", Tool.Trimmer, "", FileName = "DetectRedundantSuppressionsFromXML.xml", SourceLine = 12)] [SetupLinkAttributesFile ("DetectRedundantSuppressionsFromXML.xml")] public class DetectRedundantSuppressionsFromXML { @@ -32,4 +32,4 @@ static void DoNotTriggerWarning () { } class DoNotTriggerWarningType { } } } -} \ No newline at end of file +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInAssembly.cs index b1b985278a0a..389953653024 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInAssembly.cs @@ -4,7 +4,7 @@ using System.Diagnostics.CodeAnalysis; using Mono.Linker.Tests.Cases.Expectations.Assertions; -[assembly: ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] +[assembly: ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [assembly: UnconditionalSuppressMessage ("Test", "IL2071:Redundant suppression, warning is not issued in this assembly")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInCompilerGeneratedCode.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInCompilerGeneratedCode.cs index a707584bef36..54082fccd74e 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInCompilerGeneratedCode.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInCompilerGeneratedCode.cs @@ -34,7 +34,7 @@ public class RedundantSuppressionOnLocalMethod { public static void Test () { - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] void LocalMethod () { @@ -52,7 +52,7 @@ public static void Test () Enumerable (); } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] static IEnumerable Enumerable () { @@ -63,7 +63,7 @@ static IEnumerable Enumerable () public class RedundantSuppressionInAsyncBody { - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public static async void Test () { @@ -71,7 +71,7 @@ public static async void Test () await MethodAsync (); } - [ExpectedWarning ("IL2121", "IL2070", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2070", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2070")] static async Task MethodAsync () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypes.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypes.cs index 56998d29aee5..884ceb4a6c81 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypes.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypes.cs @@ -50,7 +50,7 @@ public static string TrimmerCompatibleMethod () return "test"; } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public class RedundantSuppressionOnType { @@ -62,7 +62,7 @@ public static void Test () public class RedundantSuppressionOnMethod { - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public static void Test () { @@ -77,7 +77,7 @@ public static void Test () NestedType.TrimmerCompatibleMethod (); } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public class NestedType { @@ -96,7 +96,7 @@ public static void Test () } public static string TrimmerCompatibleProperty { - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] get { return TrimmerCompatibleMethod (); @@ -112,7 +112,7 @@ public static void Test () TrimmerCompatibleProperty = "test"; } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public static string TrimmerCompatibleProperty { get { @@ -131,7 +131,7 @@ public static void Test () var property = TrimmerCompatibleProperty; } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public static string TrimmerCompatibleProperty { get { @@ -147,7 +147,7 @@ public static void Test () TrimmerCompatibleProperty = "test"; } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public static string TrimmerCompatibleProperty { set { @@ -163,7 +163,7 @@ public static void Test () typeof (RedundantSuppressionOnPropertyAccessedByReflection).GetProperty ("TrimmerCompatibleProperty"); } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public static string TrimmerCompatibleProperty { get { @@ -185,7 +185,7 @@ static void EventSubscriber (object sender, EventArgs e) } public static event EventHandler TrimmerCompatibleEvent { - [ExpectedWarning ("IL2121", "IL2072", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2072", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2072")] add { TrimmerCompatibleMethod (); } remove { } @@ -204,7 +204,7 @@ static void EventSubscriber (object sender, EventArgs e) } - [ExpectedWarning ("IL2121", "IL2072", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2072", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2072")] public static event EventHandler TrimmerCompatibleEvent { add { TrimmerCompatibleMethod (); } @@ -219,7 +219,7 @@ public static void Test () typeof (RedundantSuppressionOnEventAccessedByReflection).GetEvent ("TrimmerCompatibleEvent"); } - [ExpectedWarning ("IL2121", "IL2072", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2072", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2072")] public static event EventHandler TrimmerCompatibleEvent { add { TrimmerCompatibleMethod (); } @@ -227,15 +227,15 @@ public static event EventHandler TrimmerCompatibleEvent { } } - [ExpectedWarning ("IL2121", "IL2072", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2072", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2072")] - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public class MultipleRedundantSuppressions { - [ExpectedWarning ("IL2121", "IL2072", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2072", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2072")] - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] public static void Test () { @@ -245,7 +245,7 @@ public static void Test () public class RedundantAndUsedSuppressions { - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2071")] [UnconditionalSuppressMessage ("Test", "IL2072")] public static void Test () @@ -317,7 +317,7 @@ public static void Test () MethodMarkedRUC (); } - [ExpectedWarning ("IL2121", "IL2072", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2072", Tool.Trimmer, "")] [UnconditionalSuppressMessage ("Test", "IL2072")] [RequiresUnreferencedCode ("Test")] public static void MethodMarkedRUC () diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypesUsingTarget.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypesUsingTarget.cs index 5991e418197f..6b6c3df46f5b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypesUsingTarget.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInMembersAndTypesUsingTarget.cs @@ -37,7 +37,7 @@ public static string TrimmerCompatibleMethod () return "test"; } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] public class RedundantSuppressionOnType { public static void Test () @@ -48,7 +48,7 @@ public static void Test () public class RedundantSuppressionOnMethod { - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] public static void Test () { TrimmerCompatibleMethod (); @@ -62,7 +62,7 @@ public static void Test () NestedType.TrimmerCompatibleMethod (); } - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] public class NestedType { public static void TrimmerCompatibleMethod () @@ -80,7 +80,7 @@ public static void Test () } public static string TrimmerCompatibleProperty { - [ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] get { return TrimmerCompatibleMethod (); } diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInModule.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInModule.cs index 9dc15690107d..da7717bc6c14 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInModule.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/DetectRedundantSuppressionsInModule.cs @@ -4,7 +4,7 @@ using System.Diagnostics.CodeAnalysis; using Mono.Linker.Tests.Cases.Expectations.Assertions; -[assembly: ExpectedWarning ("IL2121", "IL2071", ProducedBy = Tool.Trimmer)] +[assembly: ExpectedWarning ("IL2121", "IL2071", Tool.Trimmer, "")] [module: UnconditionalSuppressMessage ("Test", "IL2071:Redundant suppression, warning is not issued in this assembly")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInAssembly.cs index c9e88bdf6a72..63b0c109c179 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInAssembly.cs @@ -7,7 +7,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression { -#if !NETCOREAPP +#if !NET [Mono.Linker.Tests.Cases.Expectations.Metadata.Reference ("System.Core.dll")] #endif [SkipKeptItemsValidation] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCompilerGeneratedCode.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCompilerGeneratedCode.cs index 5e3d6023c3b1..7ccc24a9b1fc 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCompilerGeneratedCode.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCompilerGeneratedCode.cs @@ -278,7 +278,7 @@ static void TestCallRUCMethodInLtftnLocalFunction () class DynamicallyAccessedLocalFunction { - [ExpectedWarning ("IL2118", "LocalFunction", ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2118", "LocalFunction", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] [UnconditionalSuppressMessage ("Test", "IL2026")] public static void TestCallRUCMethodInDynamicallyAccessedLocalFunction () { @@ -426,7 +426,7 @@ static void TestGenericTypeParameterRequirement () class DynamicallyAccessedLambda { - [ExpectedWarning ("IL2118", nameof (TestCallRUCMethodInDynamicallyAccessedLambda), ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2118", nameof (TestCallRUCMethodInDynamicallyAccessedLambda), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] [UnconditionalSuppressMessage ("Test", "IL2026")] public static void TestCallRUCMethodInDynamicallyAccessedLambda () { @@ -440,7 +440,7 @@ public static void TestCallRUCMethodInDynamicallyAccessedLambda () class DynamicallyAccessedLambdaUnused { - [ExpectedWarning ("IL2118", nameof (TestCallRUCMethodInDynamicallyAccessedLambda), ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2118", nameof (TestCallRUCMethodInDynamicallyAccessedLambda), Tool.Trimmer, "https://github.com/dotnet/runtime/issues/85042")] [UnconditionalSuppressMessage ("Test", "IL2026")] public static void TestCallRUCMethodInDynamicallyAccessedLambda () { @@ -453,8 +453,7 @@ public static void TestCallRUCMethodInDynamicallyAccessedLambda () static void TestSuppressionOnLambda () { var lambda = - // https://github.com/dotnet/roslyn/issues/59746 - [ExpectedWarning ("IL2026", ProducedBy = Tool.Analyzer)] + [UnexpectedWarning ("IL2026", Tool.Analyzer, "https://github.com/dotnet/roslyn/issues/59746")] [UnconditionalSuppressMessage ("Test", "IL2026")] () => RequiresUnreferencedCodeMethod (); @@ -465,8 +464,7 @@ static void TestSuppressionOnLambda () static void TestSuppressionOnOuterAndLambda () { var lambda = - // https://github.com/dotnet/roslyn/issues/59746 - [ExpectedWarning ("IL2026", ProducedBy = Tool.Analyzer)] + [UnexpectedWarning ("IL2026", Tool.Analyzer, "https://github.com/dotnet/roslyn/issues/59746")] [UnconditionalSuppressMessage ("Test", "IL2026")] (Type unknownType) => { RequiresUnreferencedCodeMethod (); @@ -576,9 +574,8 @@ static IEnumerable TestDynamicallyAccessedMethodViaGenericMethodParameterIn static event EventHandler TestEvent; - // https://github.com/dotnet/runtime/issues/82956 - the suppression is ignored - [ExpectedWarning ("IL2026", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2121", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + [UnexpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/82956", CompilerGeneratedCode = true)] + [UnexpectedWarning ("IL2121", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/82956", CompilerGeneratedCode = true)] static void TestLambdaInLocalFunction () { LocalFunction (); @@ -592,10 +589,9 @@ void LocalFunction () } } - // https://github.com/dotnet/runtime/issues/82956 - the suppression is ignored - // https://github.com/dotnet/roslyn/issues/59746 - [ExpectedWarning ("IL2026", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL2121", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + // The suppression on the lambda is ignored + [UnexpectedWarning ("IL2026", Tool.TrimmerAnalyzerAndNativeAot, "https://github.com/dotnet/roslyn/issues/59746 https://github.com/dotnet/roslyn/issues/82956", CompilerGeneratedCode = true)] + [UnexpectedWarning ("IL2121", Tool.Trimmer, "https://github.com/dotnet/runtime/issues/82956", CompilerGeneratedCode = true)] static void TestLocalFunctionInLambda () { TestEvent += diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCopyAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCopyAssembly.cs index a4e0082b3b5e..8985bc618975 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCopyAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCopyAssembly.cs @@ -7,7 +7,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression { -#if !NETCOREAPP +#if !NET [Reference ("System.Core.dll")] #endif [SetupLinkerAction ("copy", "test")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypes.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypes.cs index 596b7d2cf62f..8287c0caddb7 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypes.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypes.cs @@ -6,7 +6,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression { -#if !NETCOREAPP +#if !NET [Mono.Linker.Tests.Cases.Expectations.Metadata.Reference ("System.Core.dll")] #endif [SkipKeptItemsValidation] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypesUsingTarget.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypesUsingTarget.cs index a0121281c249..d00ac7d68fb4 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypesUsingTarget.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInMembersAndTypesUsingTarget.cs @@ -12,7 +12,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression { -#if !NETCOREAPP +#if !NET [Mono.Linker.Tests.Cases.Expectations.Metadata.Reference ("System.Core.dll")] #endif [SkipKeptItemsValidation] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInModule.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInModule.cs index 8273e453bc8f..9906cecac482 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInModule.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInModule.cs @@ -9,7 +9,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression { -#if !NETCOREAPP +#if !NET [Mono.Linker.Tests.Cases.Expectations.Metadata.Reference ("System.Core.dll")] #endif [SkipKeptItemsValidation] diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCases/TestSuites.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCases/TestSuites.cs index fd25f5cc8cef..a05e68b17bd4 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCases/TestSuites.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCases/TestSuites.cs @@ -52,7 +52,7 @@ public void CodegenAnnotationTests (TestCase testCase) if (Environment.OSVersion.Platform == PlatformID.Win32NT) Assert.Ignore ("These tests are not valid when trimming .NET Framework"); -#if NETCOREAPP +#if NET Assert.Ignore ("These tests are not valid when trimming .NET Core"); #endif Run (testCase); diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs index 7b5835d2b0fc..bff5b87a9950 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs @@ -49,7 +49,7 @@ protected virtual void SetupProcess (Process process, CompilerOptions options) private static string BuildArguments (CompilerOptions options) { var args = new StringBuilder (); -#if NETCOREAPP +#if NET args.Append (options.OutputPath.ExtensionWithDot == ".dll" ? "-dll" : "-exe"); args.Append ($" -out:{options.OutputPath.InQuotes ()}"); #else @@ -62,7 +62,7 @@ private static string BuildArguments (CompilerOptions options) protected virtual NPath LocateIlasm () { -#if NETCOREAPP +#if NET var extension = RuntimeInformation.IsOSPlatform (OSPlatform.Windows) ? ".exe" : ""; var toolsDir = (string)AppContext.GetData("Mono.Linker.Tests.ILToolsDir")!; diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/ILVerifier.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/ILVerifier.cs index 37b6c8b50bb4..2f5da68b9e4c 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/ILVerifier.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/ILVerifier.cs @@ -33,7 +33,7 @@ public ILVerifier (NPath[] searchDirectories, string systemModuleName) IncludeMetadataTokensInErrorMessages = true }); - _verifier.SetSystemModuleName (new AssemblyName (systemModuleName)); + _verifier.SetSystemModuleName (new AssemblyNameInfo (systemModuleName)); } public ILVerifierResult[] VerifyByName (string assemblyName) @@ -132,10 +132,10 @@ bool TryLoadAssemblyFromFolder (string assemblyName, NPath folder, [NotNullWhen return null; } - PEReader? IResolver.ResolveAssembly (AssemblyName assemblyName) + PEReader? IResolver.ResolveAssembly (AssemblyNameInfo assemblyName) => Resolve (assemblyName.Name ?? assemblyName.FullName); - PEReader? IResolver.ResolveModule (AssemblyName referencingModule, string fileName) + PEReader? IResolver.ResolveModule (AssemblyNameInfo referencingModule, string fileName) => Resolve (Path.GetFileNameWithoutExtension (fileName)); public void Dispose () diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerifier.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerifier.cs index 1f907e753d1a..87169314fbb1 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerifier.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerifier.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using System.Runtime.Loader; using ILVerify; @@ -42,7 +43,7 @@ public ILVerifier (NPath assemblyPath) SanityChecks = true, IncludeMetadataTokensInErrorMessages = true }); - _verifier.SetSystemModuleName (new AssemblyName ("mscorlib")); + _verifier.SetSystemModuleName (new AssemblyNameInfo ("mscorlib")); var allResults = _verifier.Verify (Resolve (assemblyName)) ?? Enumerable.Empty (); @@ -118,10 +119,10 @@ bool TryLoadAssemblyFromFolder (string assemblyName, NPath folder, [NotNullWhen return null; } - PEReader? ILVerify.IResolver.ResolveAssembly (AssemblyName assemblyName) + PEReader? ILVerify.IResolver.ResolveAssembly (AssemblyNameInfo assemblyName) => Resolve (assemblyName.Name ?? assemblyName.FullName); - PEReader? ILVerify.IResolver.ResolveModule (AssemblyName referencingModule, string fileName) + PEReader? ILVerify.IResolver.ResolveModule (AssemblyNameInfo referencingAssembly, string fileName) => Resolve (Path.GetFileNameWithoutExtension (fileName)); public static string GetErrorMessage (VerificationResult result) diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs index 2f05eab1e4c6..8b4dd418554a 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs @@ -223,7 +223,7 @@ void VerifyExitCode (TrimmedTestCaseResult linkResult, AssemblyDefinition origin Assert.AreEqual (expectedExitCode, linkResult.ExitCode, $"Expected exit code {expectedExitCode} but got {linkResult.ExitCode}. Output was:\n{FormatLinkerOutput()}"); } else { if (linkResult.ExitCode != 0) { - Assert.Fail($"Linker exited with an unexpected non-zero exit code of {linkResult.ExitCode} and output:\n{FormatLinkerOutput()}"); + Assert.Fail ($"Linker exited with an unexpected non-zero exit code of {linkResult.ExitCode} and output:\n{FormatLinkerOutput()}"); } } @@ -734,6 +734,9 @@ void VerifyKeptAllTypesAndMembersInAssembly (AssemblyDefinition linked) static bool IsProducedByLinker (CustomAttribute attr) { + if (attr.Constructor.Parameters.Count > 2 && attr.ConstructorArguments[^2].Type.Name == "Tool") { + return ((Tool)attr.ConstructorArguments[^2].Value).HasFlag (Tool.Trimmer) == true; + } var producedBy = attr.GetPropertyValue ("ProducedBy"); return producedBy is null ? true : ((Tool) producedBy).HasFlag (Tool.Trimmer); } @@ -794,12 +797,29 @@ void VerifyLoggedMessages (AssemblyDefinition original, TrimmingTestLogger logge } break; - case nameof (ExpectedWarningAttribute): { + case nameof (ExpectedWarningAttribute) or nameof(UnexpectedWarningAttribute): { var expectedWarningCode = (string) attr.GetConstructorArgumentValue (0); if (!expectedWarningCode.StartsWith ("IL")) { - Assert.Fail ($"The warning code specified in {nameof (ExpectedWarningAttribute)} must start with the 'IL' prefix. Specified value: '{expectedWarningCode}'."); + Assert.Fail ($"The warning code specified in {attr.AttributeType.Name} must start with the 'IL' prefix. Specified value: '{expectedWarningCode}'."); } - var expectedMessageContains = ((CustomAttributeArgument[]) attr.GetConstructorArgumentValue (1)).Select (a => (string) a.Value).ToArray (); + IEnumerable expectedMessageContains = attr.Constructor.Parameters switch + { + // ExpectedWarningAttribute(string warningCode, params string[] expectedMessages) + // ExpectedWarningAttribute(string warningCode, string[] expectedMessages, Tool producedBy, string issueLink) + [_, { ParameterType.IsArray: true }, ..] + => ((CustomAttributeArgument[])attr.ConstructorArguments[1].Value) + .Select(caa => (string)caa.Value), + // ExpectedWarningAttribute(string warningCode, string expectedMessage1, string expectedMessage2, Tool producedBy, string issueLink) + [_, { ParameterType.Name: "String" }, { ParameterType.Name: "String" }, { ParameterType.Name: "Tool" }, _] + => [(string)attr.GetConstructorArgumentValue(1), (string)attr.GetConstructorArgumentValue(2)], + // ExpectedWarningAttribute(string warningCode, string expectedMessage, Tool producedBy, string issueLink) + [_, { ParameterType.Name: "String" }, { ParameterType.Name: "Tool" }, _] + => [(string)attr.GetConstructorArgumentValue(1)], + // ExpectedWarningAttribute(string warningCode, Tool producedBy, string issueLink) + [_, { ParameterType.Name: "Tool" }, _] + => [], + _ => throw new UnreachableException(), + }; string fileName = (string) attr.GetPropertyValue ("FileName"); int? sourceLine = (int?) attr.GetPropertyValue ("SourceLine"); int? sourceColumn = (int?) attr.GetPropertyValue ("SourceColumn"); diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs index c26e833d9e9f..fe25e06dd2c7 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs @@ -76,7 +76,7 @@ public virtual IEnumerable GetDefines () yield return "WIN32"; if (Characteristics.HasFlag (TestRunCharacteristics.TargetingNetCore)) - yield return "NETCOREAPP"; + yield return "NET"; if (Characteristics.HasFlag (TestRunCharacteristics.SupportsDefaultInterfaceMethods)) yield return "SUPPORTS_DEFAULT_INTERFACE_METHODS"; diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs index ec427ebdbc48..89c202e472c0 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs @@ -9,7 +9,7 @@ using System.Text; using Mono.Linker.Tests.Extensions; using NUnit.Framework; -#if NETCOREAPP +#if NET using System.Runtime.InteropServices; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Emit; @@ -190,7 +190,7 @@ protected static NPath MakeSupportingAssemblyReferencePathAbsolute (NPath output if (Path.IsPathRooted (referenceFileName)) return referenceFileName.ToNPath (); -#if NETCOREAPP +#if NET if (referenceFileName.StartsWith ("System.", StringComparison.Ordinal) || referenceFileName.StartsWith ("Mono.", StringComparison.Ordinal) || referenceFileName.StartsWith ("Microsoft.", StringComparison.Ordinal) || @@ -224,14 +224,14 @@ protected NPath CompileAssembly (CompilerOptions options) protected virtual NPath CompileCSharpAssemblyWithDefaultCompiler (CompilerOptions options) { -#if NETCOREAPP +#if NET return CompileCSharpAssemblyWithRoslyn (options); #else return CompileCSharpAssemblyWithCsc (options); #endif } -#if NETCOREAPP +#if NET protected virtual NPath CompileCSharpAssemblyWithRoslyn (CompilerOptions options) { var languageVersion = LanguageVersion.Preview; @@ -328,7 +328,7 @@ protected virtual NPath CompileCSharpAssemblyWithRoslyn (CompilerOptions options protected virtual NPath CompileCSharpAssemblyWithCsc (CompilerOptions options) { -#if NETCOREAPP +#if NET return CompileCSharpAssemblyWithRoslyn (options); #else return CompileCSharpAssemblyWithExternalCompiler (LocateCscExecutable (), options, "/shared "); diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs index cdb59e657113..8789c404839b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TrimmingArgumentBuilder.cs @@ -66,7 +66,7 @@ public virtual void RootAssemblyEntryPoint (string fileName) public virtual void RootAssemblyVisible (string fileName) { -#if NETCOREAPP +#if NET Append ("-a"); Append (fileName); Append ("visible"); @@ -213,7 +213,7 @@ public virtual void ProcessOptions (TestCaseLinkerOptions options) IgnoreLinkAttributes (options.IgnoreLinkAttributes); -#if !NETCOREAPP +#if !NET if (!string.IsNullOrEmpty (options.Il8n)) AddIl8n (options.Il8n); #endif diff --git a/src/workloads/workloads.csproj b/src/workloads/workloads.csproj index 2f91a14f59c6..304fe4ad12e8 100644 --- a/src/workloads/workloads.csproj +++ b/src/workloads/workloads.csproj @@ -9,9 +9,7 @@ $(ArtifactsObjDir)workloads/ $(WorkloadIntermediateOutputPath)VS/ $(ArtifactsBinDir)workloads/ - $(workloadArtifactsPath)/ $(ArtifactsShippingPackagesDir) - $(workloadPackagesPath)/ false @@ -42,32 +40,32 @@ - <_ComponentResources Include="microsoft-net-runtime-mono-tooling" Title=".NET Shared Mobile Build Tools" + <_ComponentResources Include="microsoft-net-runtime-mono-tooling" Title=".NET 8.0 Shared Mobile Build Tools" Description="Shared build tasks for mobile platform development."/> - <_ComponentResources Include="wasm-tools" Title=".NET WebAssembly Build Tools" + <_ComponentResources Include="wasm-tools" Title=".NET 8.0 WebAssembly Build Tools" Description="Build tools for WebAssembly ahead-of-time (AoT) compilation and native linking."/> - <_ComponentResources Include="wasm-experimental" Title=".NET WebAssembly Experimental Tools" - Description=".NET WebAssembly experimental tooling"/> - <_ComponentResources Include="wasi-experimental" Title=".NET Wasi Experimental" - Description=".NET Experimental SDK and tooling for WASI"/> - <_ComponentResources Include="microsoft-net-runtime-android" Title=".NET Android Build Tools" + <_ComponentResources Include="wasm-experimental" Title=".NET 8.0 WebAssembly Experimental Tools" + Description=".NET 8.0 WebAssembly experimental tooling"/> + <_ComponentResources Include="wasi-experimental" Title=".NET 8.0 Wasi Experimental" + Description=".NET 8.0 Experimental SDK and tooling for WASI"/> + <_ComponentResources Include="microsoft-net-runtime-android" Title=".NET 8.0 Android Build Tools" Description="Build tools for Android compilation and native linking."/> - <_ComponentResources Include="microsoft-net-runtime-android-aot" Title=".NET Android Build Tools (AoT)" + <_ComponentResources Include="microsoft-net-runtime-android-aot" Title=".NET 8.0 Android Build Tools (AoT)" Description="Build tools for Android ahead-of-time (AoT) compilation and native linking."/> - <_ComponentResources Include="microsoft-net-runtime-ios" Title=".NET iOS Build Tools" + <_ComponentResources Include="microsoft-net-runtime-ios" Title=".NET 8.0 iOS Build Tools" Description="Build tools for iOS compilation and native linking."/> - <_ComponentResources Include="microsoft-net-runtime-tvos" Title=".NET tvOS Build Tools" + <_ComponentResources Include="microsoft-net-runtime-tvos" Title=".NET 8.0 tvOS Build Tools" Description="Build tools for tvOS compilation and native linking."/> - <_ComponentResources Include="microsoft-net-runtime-maccatalyst" Title=".NET Mac Catalyst Build Tools" + <_ComponentResources Include="microsoft-net-runtime-maccatalyst" Title=".NET 8.0 Mac Catalyst Build Tools" Description="Build tools for Mac Catalyst compilation and native linking."/> - <_ComponentResources Include="runtimes-ios" Title=".NET iOS Runtimes" - Description=".NET runtime components for iOS execution."/> - <_ComponentResources Include="runtimes-tvos" Title=".NET tvOS Build Tools" - Description=".NET runtime components for tvOS execution."/> - <_ComponentResources Include="runtimes-maccatalyst" Title=".NET Mac Catalyst Build Tools" - Description=".NET runtime components for Mac Catalyst execution."/> - <_ComponentResources Include="runtimes-windows" Title=".NET Windows Runtimes" - Description=".NET runtime components for Windows execution."/> + <_ComponentResources Include="runtimes-ios" Title=".NET 8.0 iOS Runtimes" + Description=".NET 8.0 runtime components for iOS execution."/> + <_ComponentResources Include="runtimes-tvos" Title=".NET 8.0 tvOS Build Tools" + Description=".NET 8.0 runtime components for tvOS execution."/> + <_ComponentResources Include="runtimes-maccatalyst" Title=".NET 8.0 Mac Catalyst Build Tools" + Description=".NET 8.0 runtime components for Mac Catalyst execution."/> + <_ComponentResources Include="runtimes-windows" Title=".NET 8.0 Windows Runtimes" + Description=".NET 8.0 runtime components for Windows execution."/> <_ComponentResources Include="microsoft-net-runtime-mono-tooling-net7" Title=".NET 7.0 Shared Mobile Build Tools" Description="Shared build tasks for mobile platform development."/> @@ -132,7 +130,7 @@ Mono. - + Microsoft @@ -141,7 +139,7 @@ -